-module(argamak@tensor). -compile([no_auto_import, nowarn_unused_vars]). -export([format/1, space/1, axes/1, rank/1, shape/1, to_native/1, size/1, reformat/2, broadcast/2, broadcast_over/3, logical_not/1, absolute_value/1, negate/1, sign/1, ceiling/1, floor/1, round/1, exp/1, square_root/1, ln/1, concat/2, to_float/1, to_int/1, to_floats/1, to_ints/1, reshape/2, from_native/3, from_float/1, from_int/1, from_bool/1, from_floats/2, from_ints/2, from_bools/2, equal/2, not_equal/2, greater/2, greater_or_equal/2, less/2, less_or_equal/2, logical_and/2, logical_or/2, logical_xor/2, add/2, subtract/2, multiply/2, power/2, max/2, min/2, divide/2, remainder/2, modulo/2, squeeze/2, all/2, in_situ_all/2, any/2, in_situ_any/2, max_over/2, in_situ_max_over/2, min_over/2, in_situ_min_over/2, sum/2, in_situ_sum/2, product/2, in_situ_product/2, mean/2, in_situ_mean/2, try_divide/2, try_remainder/2, try_modulo/2, arg_max/2, in_situ_arg_max/2, arg_min/2, in_situ_arg_min/2, to_bool/1, to_bools/1, to_string/3, print/1, debug/1, print_data/1]). -export_type([tensor/1, native/0, tensor_error/0, to_string/0, to_string_acc/0, fit_by/0, fit_acc/1, reducible/0, reducible_acc/0]). -opaque tensor(LFW) :: {tensor, native(), argamak@format:format(LFW), argamak@space:space()}. -type native() :: any(). -type tensor_error() :: cannot_broadcast | incompatible_axes | incompatible_shape | invalid_data | {space_errors, list(argamak@space:space_error())} | zero_division. -type to_string() :: data | record. -type to_string_acc() :: {to_string_acc, list(gleam@string_builder:string_builder()), gleam@string_builder:string_builder()}. -type fit_by() :: definition | inference. -type fit_acc(LFX) :: {fit_acc, integer(), fit_by()} | {gleam_phantom, LFX}. -type reducible() :: away | in_situ. -type reducible_acc() :: {reducible_acc, list(argamak@axis:axis()), list(integer())}. -spec format(tensor(LGS)) -> argamak@format:format(LGS). format(X) -> erlang:element(3, X). -spec space(tensor(any())) -> argamak@space:space(). space(X) -> erlang:element(4, X). -spec axes(tensor(any())) -> list(argamak@axis:axis()). axes(X) -> _pipe = X, _pipe@1 = space(_pipe), argamak@space:axes(_pipe@1). -spec rank(tensor(any())) -> integer(). rank(X) -> _pipe = X, _pipe@1 = space(_pipe), argamak@space:degree(_pipe@1). -spec shape(tensor(any())) -> list(integer()). shape(X) -> _pipe = X, _pipe@1 = space(_pipe), argamak@space:shape(_pipe@1). -spec to_native(tensor(any())) -> native(). to_native(X) -> erlang:element(2, X). -spec size(tensor(any())) -> integer(). size(X) -> _pipe = X, _pipe@1 = to_native(_pipe), argamak_ffi:size(_pipe@1). -spec reformat(tensor(any()), argamak@format:format(LHH)) -> tensor(LHH). reformat(X, Format) -> _pipe = X, _pipe@1 = to_native(_pipe), _pipe@2 = argamak_ffi:reformat(_pipe@1, argamak@format:to_native(Format)), {tensor, _pipe@2, Format, space(X)}. -spec broadcast(tensor(LHN), argamak@space:space()) -> {ok, tensor(LHN)} | {error, tensor_error()}. broadcast(X, New_space) -> gleam@result:'try'( begin _pipe = X, _pipe@1 = to_native(_pipe), argamak_ffi:broadcast(_pipe@1, argamak@space:shape(New_space)) end, fun(Native) -> _pipe@2 = erlang:setelement( 4, erlang:setelement(2, X, Native), New_space ), {ok, _pipe@2} end ). -spec broadcast_over( tensor(LHQ), argamak@space:space(), fun((argamak@axis:axis()) -> binary()) ) -> {ok, tensor(LHQ)} | {error, tensor_error()}. broadcast_over(X, New_space, Space_map) -> New_axes = argamak@space:axes(New_space), gleam@result:'try'( gleam@result:all( (gleam@list:map( axes(X), fun(Axis) -> Name = Space_map(Axis), _pipe@1 = (gleam@list:find_map( New_axes, fun(Axis@1) -> case argamak@axis:name(Axis@1) =:= Name of true -> _pipe = {Name, argamak@axis:size(Axis@1)}, {ok, _pipe}; false -> {error, nil} end end )), gleam@result:replace_error(_pipe@1, incompatible_axes) end )) ), fun(Mapped_axes) -> Axis_map = gleam@map:from_list(Mapped_axes), Pre_shape = (gleam@list:map( New_axes, fun(Axis@2) -> _pipe@2 = Axis_map, _pipe@3 = gleam@map:get(_pipe@2, argamak@axis:name(Axis@2)), gleam@result:unwrap(_pipe@3, 1) end )), Shape = argamak@space:shape(New_space), gleam@result:'try'( begin _pipe@4 = X, _pipe@5 = to_native(_pipe@4), argamak_ffi:reshape(_pipe@5, Pre_shape) end, fun(Native) -> gleam@result:'try'( argamak_ffi:broadcast(Native, Shape), fun(Native@1) -> _pipe@6 = erlang:setelement( 4, erlang:setelement(2, X, Native@1), New_space ), {ok, _pipe@6} end ) end ) end ). -spec logical_not(tensor(LJG)) -> tensor(LJG). logical_not(X) -> erlang:setelement(2, X, argamak_ffi:logical_not(to_native(X))). -spec absolute_value(tensor(LLN)) -> tensor(LLN). absolute_value(X) -> erlang:setelement(2, X, argamak_ffi:absolute_value(to_native(X))). -spec negate(tensor(LLQ)) -> tensor(LLQ). negate(X) -> erlang:setelement(2, X, argamak_ffi:negate(to_native(X))). -spec sign(tensor(LLT)) -> tensor(LLT). sign(X) -> erlang:setelement(2, X, argamak_ffi:sign(to_native(X))). -spec ceiling(tensor(LLW)) -> tensor(LLW). ceiling(X) -> erlang:setelement(2, X, argamak_ffi:ceiling(to_native(X))). -spec floor(tensor(LLZ)) -> tensor(LLZ). floor(X) -> erlang:setelement(2, X, argamak_ffi:floor(to_native(X))). -spec round(tensor(LMC)) -> tensor(LMC). round(X) -> erlang:setelement(2, X, argamak_ffi:round(to_native(X))). -spec exp(tensor(LMF)) -> tensor(LMF). exp(X) -> erlang:setelement(2, X, argamak_ffi:exp(to_native(X))). -spec square_root(tensor(LMI)) -> {ok, tensor(LMI)} | {error, tensor_error()}. square_root(X) -> gleam@result:'try'( begin _pipe = X, _pipe@1 = to_native(_pipe), argamak_ffi:square_root(_pipe@1) end, fun(Native) -> _pipe@2 = erlang:setelement(2, X, Native), {ok, _pipe@2} end ). -spec ln(tensor(LML)) -> {ok, tensor(LML)} | {error, tensor_error()}. ln(X) -> gleam@result:'try'( begin _pipe = X, _pipe@1 = to_native(_pipe), argamak_ffi:ln(_pipe@1) end, fun(Native) -> _pipe@2 = erlang:setelement(2, X, Native), {ok, _pipe@2} end ). -spec concat(list(tensor(LOQ)), fun((argamak@axis:axis()) -> boolean())) -> {ok, tensor(LOQ)} | {error, tensor_error()}. concat(Xs, Find) -> gleam@result:'try'(case Xs of [_ | _] -> {ok, Xs}; _ -> {error, invalid_data} end, fun(_use0) -> [X | Rest] = _use0, New_axes = axes(X), gleam@result:'try'( begin _pipe = New_axes, _pipe@1 = gleam@iterator:from_list(_pipe), _pipe@2 = gleam@iterator:index(_pipe@1), _pipe@3 = gleam@iterator:find( _pipe@2, fun(Item) -> Find(erlang:element(2, Item)) end ), _pipe@4 = gleam@result:map( _pipe@3, fun(X@1) -> erlang:element(1, X@1) end ), _pipe@5 = gleam@result:lazy_or( _pipe@4, fun() -> case New_axes of [_ | _] -> {ok, 0}; _ -> {error, nil} end end ), gleam@result:replace_error(_pipe@5, incompatible_shape) end, fun(Index) -> gleam@result:'try'( (gleam@list:try_fold( Rest, New_axes, fun(New_axes@1, X@2) -> gleam@result:'try'( begin _pipe@6 = New_axes@1, _pipe@7 = gleam@list:strict_zip( _pipe@6, axes(X@2) ), gleam@result:replace_error( _pipe@7, incompatible_shape ) end, fun(Pairs) -> Pairs@1 = begin _pipe@8 = Pairs, _pipe@9 = gleam@iterator:from_list( _pipe@8 ), gleam@iterator:index(_pipe@9) end, gleam@iterator:try_fold( Pairs@1, [], fun(New_axes@2, Pair) -> {I, {A, B}} = Pair, case argamak@axis:name(A) =:= argamak@axis:name( B ) of true when I =:= Index -> _pipe@10 = [argamak@axis:resize( A, argamak@axis:size( A ) + argamak@axis:size( B ) ) | New_axes@2], {ok, _pipe@10}; true when A =:= B -> {ok, [A | New_axes@2]}; _ -> {error, incompatible_shape} end end ) end ) end )), fun(New_axes@3) -> _assert_subject = begin _pipe@11 = New_axes@3, _pipe@12 = gleam@list:reverse(_pipe@11), argamak@space:from_list(_pipe@12) end, {ok, Space} = case _assert_subject of {ok, _} -> _assert_subject; _assert_fail -> erlang:error(#{gleam_error => let_assert, message => <<"Assertion pattern match failed"/utf8>>, value => _assert_fail, module => <<"argamak/tensor"/utf8>>, function => <<"concat"/utf8>>, line => 3451}) end, Native = begin _pipe@13 = Xs, _pipe@14 = gleam@list:map( _pipe@13, fun to_native/1 ), argamak_ffi:concat(_pipe@14, Index) end, _pipe@15 = erlang:setelement( 4, erlang:setelement(2, X, Native), Space ), {ok, _pipe@15} end ) end ) end). -spec to_float(tensor(any())) -> {ok, float()} | {error, tensor_error()}. to_float(X) -> _pipe = X, _pipe@1 = to_native(_pipe), argamak_ffi:to_float(_pipe@1). -spec to_int(tensor(any())) -> {ok, integer()} | {error, tensor_error()}. to_int(X) -> _pipe = X, _pipe@1 = to_native(_pipe), argamak_ffi:to_int(_pipe@1). -spec to_floats(tensor(any())) -> list(float()). to_floats(X) -> _pipe = X, _pipe@1 = to_native(_pipe), argamak_ffi:to_floats(_pipe@1). -spec to_ints(tensor(any())) -> list(integer()). to_ints(X) -> _pipe = X, _pipe@1 = to_native(_pipe), argamak_ffi:to_ints(_pipe@1). -spec fit(tensor(LQQ)) -> {ok, tensor(LQQ)} | {error, tensor_error()}. fit(X) -> Dividend = size(X), {fit_acc, Divisor, Fit_by} = (gleam@list:fold( axes(X), {fit_acc, 1, definition}, fun(Acc, Axis) -> case Axis of {infer, _} -> erlang:setelement(3, Acc, inference); _ -> erlang:setelement( 2, Acc, erlang:element(2, Acc) * argamak@axis:size(Axis) ) end end )), case case Divisor of 0 -> 0; Gleam@denominator -> Dividend rem Gleam@denominator end of 0 when Fit_by =:= definition -> {ok, X}; 0 when Fit_by =:= inference -> _assert_subject = (argamak@space:map( space(X), fun(Axis@1) -> case Axis@1 of {infer, _} -> argamak@axis:resize(Axis@1, case Divisor of 0 -> 0; Gleam@denominator@1 -> Dividend div Gleam@denominator@1 end); _ -> Axis@1 end end )), {ok, Space} = case _assert_subject of {ok, _} -> _assert_subject; _assert_fail -> erlang:error(#{gleam_error => let_assert, message => <<"Assertion pattern match failed"/utf8>>, value => _assert_fail, module => <<"argamak/tensor"/utf8>>, function => <<"fit"/utf8>>, line => 4058}) end, _pipe = erlang:setelement(4, X, Space), {ok, _pipe}; _ -> {error, incompatible_shape} end. -spec reshape(tensor(LHK), argamak@space:space()) -> {ok, tensor(LHK)} | {error, tensor_error()}. reshape(X, New_space) -> gleam@result:'try'( begin _pipe = erlang:setelement(4, X, New_space), fit(_pipe) end, fun(X@1) -> Shape = shape(X@1), gleam@result:'try'( begin _pipe@1 = X@1, _pipe@2 = to_native(_pipe@1), argamak_ffi:reshape(_pipe@2, Shape) end, fun(Native) -> _pipe@3 = erlang:setelement(2, X@1, Native), {ok, _pipe@3} end ) end ). -spec from_native(native(), argamak@space:space(), argamak@format:format(LGP)) -> {ok, tensor(LGP)} | {error, tensor_error()}. from_native(X, Space, Format) -> _pipe = X, _pipe@1 = {tensor, _pipe, Format, Space}, _pipe@2 = reformat(_pipe@1, Format), reshape(_pipe@2, Space). -spec tensor(any(), argamak@space:space(), argamak@format:format(LQL)) -> {ok, tensor(LQL)} | {error, tensor_error()}. tensor(Data, Space, New_format) -> gleam@result:'try'( argamak_ffi:tensor(Data, argamak@format:to_native(New_format)), fun(Native) -> gleam@result:'try'( begin _pipe = Native, _pipe@1 = {tensor, _pipe, New_format, Space}, reshape(_pipe@1, Space) end, fun(X) -> {ok, X} end ) end ). -spec from_float(float()) -> tensor(argamak@format:float32()). from_float(X) -> _assert_subject = tensor(X, argamak@space:new(), argamak@format:float32()), {ok, X@1} = case _assert_subject of {ok, _} -> _assert_subject; _assert_fail -> erlang:error(#{gleam_error => let_assert, message => <<"Assertion pattern match failed"/utf8>>, value => _assert_fail, module => <<"argamak/tensor"/utf8>>, function => <<"from_float"/utf8>>, line => 70}) end, X@1. -spec from_int(integer()) -> tensor(argamak@format:int32()). from_int(X) -> _assert_subject = tensor(X, argamak@space:new(), argamak@format:int32()), {ok, X@1} = case _assert_subject of {ok, _} -> _assert_subject; _assert_fail -> erlang:error(#{gleam_error => let_assert, message => <<"Assertion pattern match failed"/utf8>>, value => _assert_fail, module => <<"argamak/tensor"/utf8>>, function => <<"from_int"/utf8>>, line => 85}) end, X@1. -spec from_bool(boolean()) -> tensor(argamak@format:int32()). from_bool(X) -> _assert_subject = begin _pipe = X, _pipe@1 = gleam@bool:to_int(_pipe), tensor(_pipe@1, argamak@space:new(), argamak@format:int32()) end, {ok, X@1} = case _assert_subject of {ok, _} -> _assert_subject; _assert_fail -> erlang:error(#{gleam_error => let_assert, message => <<"Assertion pattern match failed"/utf8>>, value => _assert_fail, module => <<"argamak/tensor"/utf8>>, function => <<"from_bool"/utf8>>, line => 106}) end, X@1. -spec from_floats(list(float()), argamak@space:space()) -> {ok, tensor(argamak@format:float32())} | {error, tensor_error()}. from_floats(Xs, Space) -> tensor(Xs, Space, argamak@format:float32()). -spec from_ints(list(integer()), argamak@space:space()) -> {ok, tensor(argamak@format:int32())} | {error, tensor_error()}. from_ints(Xs, Space) -> tensor(Xs, Space, argamak@format:int32()). -spec from_bools(list(boolean()), argamak@space:space()) -> {ok, tensor(argamak@format:int32())} | {error, tensor_error()}. from_bools(Xs, Space) -> _pipe = Xs, _pipe@1 = gleam@list:map(_pipe, fun gleam@bool:to_int/1), tensor(_pipe@1, Space, argamak@format:int32()). -spec broadcastable( fun((native(), native()) -> {ok, native()} | {error, tensor_error()}), tensor(LQT), tensor(LQT) ) -> {ok, tensor(LQT)} | {error, tensor_error()}. broadcastable(F, A, B) -> gleam@result:'try'( begin _pipe = A, _pipe@1 = space(_pipe), _pipe@2 = argamak@space:merge(_pipe@1, space(B)), gleam@result:map_error( _pipe@2, fun(Field@0) -> {space_errors, Field@0} end ) end, fun(Space) -> gleam@result:'try'( F(to_native(A), to_native(B)), fun(Native) -> _pipe@3 = erlang:setelement( 4, erlang:setelement(2, A, Native), Space ), {ok, _pipe@3} end ) end ). -spec equal(tensor(LHW), tensor(LHW)) -> {ok, tensor(LHW)} | {error, tensor_error()}. equal(A, B) -> broadcastable(fun argamak_ffi:equal/2, A, B). -spec not_equal(tensor(LIA), tensor(LIA)) -> {ok, tensor(LIA)} | {error, tensor_error()}. not_equal(A, B) -> broadcastable(fun argamak_ffi:not_equal/2, A, B). -spec greater(tensor(LIE), tensor(LIE)) -> {ok, tensor(LIE)} | {error, tensor_error()}. greater(A, B) -> broadcastable(fun argamak_ffi:greater/2, A, B). -spec greater_or_equal(tensor(LII), tensor(LII)) -> {ok, tensor(LII)} | {error, tensor_error()}. greater_or_equal(A, B) -> broadcastable(fun argamak_ffi:greater_or_equal/2, A, B). -spec less(tensor(LIM), tensor(LIM)) -> {ok, tensor(LIM)} | {error, tensor_error()}. less(A, B) -> broadcastable(fun argamak_ffi:less/2, A, B). -spec less_or_equal(tensor(LIQ), tensor(LIQ)) -> {ok, tensor(LIQ)} | {error, tensor_error()}. less_or_equal(A, B) -> broadcastable(fun argamak_ffi:less_or_equal/2, A, B). -spec logical_and(tensor(LIU), tensor(LIU)) -> {ok, tensor(LIU)} | {error, tensor_error()}. logical_and(A, B) -> broadcastable(fun argamak_ffi:logical_and/2, A, B). -spec logical_or(tensor(LIY), tensor(LIY)) -> {ok, tensor(LIY)} | {error, tensor_error()}. logical_or(A, B) -> broadcastable(fun argamak_ffi:logical_or/2, A, B). -spec logical_xor(tensor(LJC), tensor(LJC)) -> {ok, tensor(LJC)} | {error, tensor_error()}. logical_xor(A, B) -> broadcastable(fun argamak_ffi:logical_xor/2, A, B). -spec add(tensor(LJJ), tensor(LJJ)) -> {ok, tensor(LJJ)} | {error, tensor_error()}. add(A, B) -> broadcastable(fun argamak_ffi:add/2, A, B). -spec subtract(tensor(LJN), tensor(LJN)) -> {ok, tensor(LJN)} | {error, tensor_error()}. subtract(A, B) -> broadcastable(fun argamak_ffi:subtract/2, A, B). -spec multiply(tensor(LJR), tensor(LJR)) -> {ok, tensor(LJR)} | {error, tensor_error()}. multiply(A, B) -> broadcastable(fun argamak_ffi:multiply/2, A, B). -spec power(tensor(LLB), tensor(LLB)) -> {ok, tensor(LLB)} | {error, tensor_error()}. power(A, B) -> broadcastable(fun argamak_ffi:power/2, A, B). -spec max(tensor(LLF), tensor(LLF)) -> {ok, tensor(LLF)} | {error, tensor_error()}. max(A, B) -> broadcastable(fun argamak_ffi:max/2, A, B). -spec min(tensor(LLJ), tensor(LLJ)) -> {ok, tensor(LLJ)} | {error, tensor_error()}. min(A, B) -> broadcastable(fun argamak_ffi:min/2, A, B). -spec sign_not_equal(tensor(LQX), tensor(LQX)) -> {ok, tensor(LQX)} | {error, tensor_error()}. sign_not_equal(A, B) -> Zero = begin _pipe = 0, _pipe@1 = from_int(_pipe), reformat(_pipe@1, format(A)) end, gleam@result:'try'(multiply(sign(A), sign(B)), fun(X) -> less(X, Zero) end). -spec permit_zero( tensor(LRB), fun((tensor(LRB)) -> {ok, tensor(LRB)} | {error, tensor_error()}) ) -> {ok, tensor(LRB)} | {error, tensor_error()}. permit_zero(X, F) -> Zero = begin _pipe = 0, _pipe@1 = from_int(_pipe), reformat(_pipe@1, format(X)) end, gleam@result:'try'( not_equal(X, Zero), fun(Is_nonzero) -> gleam@result:'try'( equal(X, Zero), fun(Is_zero) -> gleam@result:'try'( add(X, Is_zero), fun(X@1) -> gleam@result:'try'( F(X@1), fun(X@2) -> multiply(X@2, Is_nonzero) end ) end ) end ) end ). -spec divide(tensor(LJV), tensor(LJV)) -> {ok, tensor(LJV)} | {error, tensor_error()}. divide(A, B) -> _pipe = fun(_capture) -> broadcastable(fun argamak_ffi:divide/2, A, _capture) end, permit_zero(B, _pipe). -spec do_remainder(tensor(LKH), tensor(LKH)) -> {ok, tensor(LKH)} | {error, tensor_error()}. do_remainder(A, B) -> _pipe = fun(_capture) -> broadcastable(fun argamak_ffi:remainder/2, A, _capture) end, permit_zero(B, _pipe). -spec remainder(tensor(LKD), tensor(LKD)) -> {ok, tensor(LKD)} | {error, tensor_error()}. remainder(A, B) -> do_remainder(A, B). -spec do_modulo(tensor(LKT), tensor(LKT)) -> {ok, tensor(LKT)} | {error, tensor_error()}. do_modulo(A, B) -> gleam@result:'try'( sign_not_equal(A, B), fun(Adjust) -> gleam@result:'try'( multiply(Adjust, B), fun(Adjust@1) -> gleam@result:'try'( remainder(A, B), fun(X) -> add(X, Adjust@1) end ) end ) end ). -spec modulo(tensor(LKP), tensor(LKP)) -> {ok, tensor(LKP)} | {error, tensor_error()}. modulo(A, B) -> do_modulo(A, B). -spec reducible_over_axes( fun((native(), list(integer())) -> native()), tensor(LRJ), fun((argamak@axis:axis()) -> boolean()), reducible() ) -> tensor(LRJ). reducible_over_axes(F, X, Filter, Reduce) -> Acc@1 = (gleam@list:index_fold( axes(X), {reducible_acc, [], []}, fun(Acc, Axis, Index) -> case Filter(Axis) of true when Reduce =:= in_situ -> Axis@1 = argamak@axis:resize(Axis, 1), {reducible_acc, [Axis@1 | erlang:element(2, Acc)], [Index | erlang:element(3, Acc)]}; true -> erlang:setelement(3, Acc, [Index | erlang:element(3, Acc)]); false -> erlang:setelement(2, Acc, [Axis | erlang:element(2, Acc)]) end end )), _assert_subject = begin _pipe = erlang:element(2, Acc@1), _pipe@1 = gleam@list:reverse(_pipe), argamak@space:from_list(_pipe@1) end, {ok, New_space} = case _assert_subject of {ok, _} -> _assert_subject; _assert_fail -> erlang:error(#{gleam_error => let_assert, message => <<"Assertion pattern match failed"/utf8>>, value => _assert_fail, module => <<"argamak/tensor"/utf8>>, function => <<"reducible_over_axes"/utf8>>, line => 4154}) end, Native = to_native(X), Native@3 = case gleam@list:reverse(erlang:element(3, Acc@1)) of [] -> _assert_subject@1 = begin _pipe@2 = X, _pipe@3 = shape(_pipe@2), _pipe@4 = gleam@list:append(_pipe@3, [1]), argamak_ffi:reshape(Native, _pipe@4) end, {ok, Native@1} = case _assert_subject@1 of {ok, _} -> _assert_subject@1; _assert_fail@1 -> erlang:error(#{gleam_error => let_assert, message => <<"Assertion pattern match failed"/utf8>>, value => _assert_fail@1, module => <<"argamak/tensor"/utf8>>, function => <<"reducible_over_axes"/utf8>>, line => 4162}) end, F(Native@1, [rank(X)]); Indices -> _assert_subject@2 = begin _pipe@5 = Native, _pipe@6 = F(_pipe@5, Indices), argamak_ffi:reshape(_pipe@6, argamak@space:shape(New_space)) end, {ok, Native@2} = case _assert_subject@2 of {ok, _} -> _assert_subject@2; _assert_fail@2 -> erlang:error(#{gleam_error => let_assert, message => <<"Assertion pattern match failed"/utf8>>, value => _assert_fail@2, module => <<"argamak/tensor"/utf8>>, function => <<"reducible_over_axes"/utf8>>, line => 4170}) end, Native@2 end, erlang:setelement(4, erlang:setelement(2, X, Native@3), New_space). -spec squeeze(tensor(LHT), fun((argamak@axis:axis()) -> boolean())) -> tensor(LHT). squeeze(X, Filter) -> reducible_over_axes( fun argamak_ffi:squeeze/2, X, fun(Axis) -> case argamak@axis:size(Axis) of 1 -> Filter(Axis); _ -> false end end, away ). -spec all(tensor(LMO), fun((argamak@axis:axis()) -> boolean())) -> tensor(LMO). all(X, Filter) -> reducible_over_axes(fun argamak_ffi:all/2, X, Filter, away). -spec in_situ_all(tensor(LMR), fun((argamak@axis:axis()) -> boolean())) -> tensor(LMR). in_situ_all(X, Filter) -> reducible_over_axes(fun argamak_ffi:all/2, X, Filter, in_situ). -spec any(tensor(LMU), fun((argamak@axis:axis()) -> boolean())) -> tensor(LMU). any(X, Filter) -> reducible_over_axes(fun argamak_ffi:any/2, X, Filter, away). -spec in_situ_any(tensor(LMX), fun((argamak@axis:axis()) -> boolean())) -> tensor(LMX). in_situ_any(X, Filter) -> reducible_over_axes(fun argamak_ffi:any/2, X, Filter, in_situ). -spec max_over(tensor(LNM), fun((argamak@axis:axis()) -> boolean())) -> tensor(LNM). max_over(X, Filter) -> reducible_over_axes(fun argamak_ffi:max_over/2, X, Filter, away). -spec in_situ_max_over(tensor(LNP), fun((argamak@axis:axis()) -> boolean())) -> tensor(LNP). in_situ_max_over(X, Filter) -> reducible_over_axes(fun argamak_ffi:max_over/2, X, Filter, in_situ). -spec min_over(tensor(LNS), fun((argamak@axis:axis()) -> boolean())) -> tensor(LNS). min_over(X, Filter) -> reducible_over_axes(fun argamak_ffi:min_over/2, X, Filter, away). -spec in_situ_min_over(tensor(LNV), fun((argamak@axis:axis()) -> boolean())) -> tensor(LNV). in_situ_min_over(X, Filter) -> reducible_over_axes(fun argamak_ffi:min_over/2, X, Filter, in_situ). -spec sum(tensor(LNY), fun((argamak@axis:axis()) -> boolean())) -> tensor(LNY). sum(X, Filter) -> reducible_over_axes(fun argamak_ffi:sum/2, X, Filter, away). -spec in_situ_sum(tensor(LOB), fun((argamak@axis:axis()) -> boolean())) -> tensor(LOB). in_situ_sum(X, Filter) -> reducible_over_axes(fun argamak_ffi:sum/2, X, Filter, in_situ). -spec product(tensor(LOE), fun((argamak@axis:axis()) -> boolean())) -> tensor(LOE). product(X, Filter) -> reducible_over_axes(fun argamak_ffi:product/2, X, Filter, away). -spec in_situ_product(tensor(LOH), fun((argamak@axis:axis()) -> boolean())) -> tensor(LOH). in_situ_product(X, Filter) -> reducible_over_axes(fun argamak_ffi:product/2, X, Filter, in_situ). -spec mean(tensor(LOK), fun((argamak@axis:axis()) -> boolean())) -> tensor(LOK). mean(X, Filter) -> reducible_over_axes(fun argamak_ffi:mean/2, X, Filter, away). -spec in_situ_mean(tensor(LON), fun((argamak@axis:axis()) -> boolean())) -> tensor(LON). in_situ_mean(X, Filter) -> reducible_over_axes(fun argamak_ffi:mean/2, X, Filter, in_situ). -spec all_nonzero(tensor(LRG)) -> {ok, tensor(LRG)} | {error, tensor_error()}. all_nonzero(X) -> gleam@result:'try'( begin _pipe = X, _pipe@1 = all(_pipe, fun(_) -> true end), _pipe@2 = reformat(_pipe@1, argamak@format:int32()), to_int(_pipe@2) end, fun(All) -> case All of 1 -> {ok, X}; _ -> {error, zero_division} end end ). -spec try_divide(tensor(LJZ), tensor(LJZ)) -> {ok, tensor(LJZ)} | {error, tensor_error()}. try_divide(A, B) -> gleam@result:'try'(all_nonzero(B), fun(B@1) -> divide(A, B@1) end). -spec try_remainder(tensor(LKL), tensor(LKL)) -> {ok, tensor(LKL)} | {error, tensor_error()}. try_remainder(A, B) -> gleam@result:'try'(all_nonzero(B), fun(B@1) -> remainder(A, B@1) end). -spec try_modulo(tensor(LKX), tensor(LKX)) -> {ok, tensor(LKX)} | {error, tensor_error()}. try_modulo(A, B) -> gleam@result:'try'(all_nonzero(B), fun(B@1) -> modulo(A, B@1) end). -spec reducible_over_axis( fun((native(), integer()) -> native()), tensor(LRM), fun((argamak@axis:axis()) -> boolean()), reducible() ) -> tensor(LRM). reducible_over_axis(F, X, Find, Reduce) -> Acc@1 = (gleam@list:index_fold( axes(X), {reducible_acc, [], []}, fun(Acc, Axis, Index) -> case (erlang:element(3, Acc) =:= []) andalso Find(Axis) of true when Reduce =:= in_situ -> Axis@1 = argamak@axis:resize(Axis, 1), {reducible_acc, [Axis@1 | erlang:element(2, Acc)], [Index]}; true -> erlang:setelement(3, Acc, [Index]); false -> erlang:setelement(2, Acc, [Axis | erlang:element(2, Acc)]) end end )), _assert_subject = begin _pipe = erlang:element(2, Acc@1), _pipe@1 = gleam@list:reverse(_pipe), argamak@space:from_list(_pipe@1) end, {ok, New_space} = case _assert_subject of {ok, _} -> _assert_subject; _assert_fail -> erlang:error(#{gleam_error => let_assert, message => <<"Assertion pattern match failed"/utf8>>, value => _assert_fail, module => <<"argamak/tensor"/utf8>>, function => <<"reducible_over_axis"/utf8>>, line => 4200}) end, case erlang:element(3, Acc@1) of [] -> _assert_subject@1 = begin _pipe@2 = <<"Nil"/utf8>>, _pipe@3 = {infer, _pipe@2}, argamak@space:d1(_pipe@3) end, {ok, New_space@1} = case _assert_subject@1 of {ok, _} -> _assert_subject@1; _assert_fail@1 -> erlang:error(#{gleam_error => let_assert, message => <<"Assertion pattern match failed"/utf8>>, value => _assert_fail@1, module => <<"argamak/tensor"/utf8>>, function => <<"reducible_over_axis"/utf8>>, line => 4207}) end, _assert_subject@2 = reshape(X, New_space@1), {ok, X@1} = case _assert_subject@2 of {ok, _} -> _assert_subject@2; _assert_fail@2 -> erlang:error(#{gleam_error => let_assert, message => <<"Assertion pattern match failed"/utf8>>, value => _assert_fail@2, module => <<"argamak/tensor"/utf8>>, function => <<"reducible_over_axis"/utf8>>, line => 4211}) end, erlang:setelement( 4, erlang:setelement(2, X@1, F(to_native(X@1), 0)), argamak@space:new() ); [Index@1 | _] -> _assert_subject@3 = begin _pipe@4 = X, _pipe@5 = to_native(_pipe@4), _pipe@6 = F(_pipe@5, Index@1), argamak_ffi:reshape(_pipe@6, argamak@space:shape(New_space)) end, {ok, Native} = case _assert_subject@3 of {ok, _} -> _assert_subject@3; _assert_fail@3 -> erlang:error(#{gleam_error => let_assert, message => <<"Assertion pattern match failed"/utf8>>, value => _assert_fail@3, module => <<"argamak/tensor"/utf8>>, function => <<"reducible_over_axis"/utf8>>, line => 4215}) end, erlang:setelement(4, erlang:setelement(2, X, Native), New_space) end. -spec arg_max(tensor(LNA), fun((argamak@axis:axis()) -> boolean())) -> tensor(LNA). arg_max(X, Find) -> reducible_over_axis(fun argamak_ffi:arg_max/2, X, Find, away). -spec in_situ_arg_max(tensor(LND), fun((argamak@axis:axis()) -> boolean())) -> tensor(LND). in_situ_arg_max(X, Find) -> reducible_over_axis(fun argamak_ffi:arg_max/2, X, Find, in_situ). -spec arg_min(tensor(LNG), fun((argamak@axis:axis()) -> boolean())) -> tensor(LNG). arg_min(X, Find) -> reducible_over_axis(fun argamak_ffi:arg_min/2, X, Find, away). -spec in_situ_arg_min(tensor(LNJ), fun((argamak@axis:axis()) -> boolean())) -> tensor(LNJ). in_situ_arg_min(X, Find) -> reducible_over_axis(fun argamak_ffi:arg_min/2, X, Find, in_situ). -spec int_to_bool(integer()) -> boolean(). int_to_bool(X) -> case X of 0 -> false; _ -> true end. -spec to_bool(tensor(any())) -> {ok, boolean()} | {error, tensor_error()}. to_bool(X) -> _pipe = X, _pipe@1 = all(_pipe, fun(_) -> false end), _pipe@2 = to_int(_pipe@1), gleam@result:map(_pipe@2, fun int_to_bool/1). -spec to_bools(tensor(any())) -> list(boolean()). to_bools(X) -> _pipe = X, _pipe@1 = all(_pipe, fun(_) -> false end), _pipe@2 = to_ints(_pipe@1), gleam@list:map(_pipe@2, fun int_to_bool/1). -spec bool_lazy_guard(boolean(), fun(() -> LRR), fun(() -> LRR)) -> LRR. bool_lazy_guard(Requirement, Consequence, Alternative) -> case Requirement of true -> Consequence(); false -> Alternative() end. -spec do_to_string(tensor(any()), integer(), integer()) -> binary(). do_to_string(X, Column, Tab) -> {Xs, Item_length} = begin _pipe = X, _pipe@1 = to_native(_pipe), argamak_ffi:prepare_to_string(_pipe@1) end, Rank = rank(X), Shape = case Rank of 0 -> [1]; _ -> _pipe@2 = X, _pipe@3 = shape(_pipe@2), gleam@list:reverse(_pipe@3) end, Should_wrap = case Column > 0 of true -> Max_length = (Column - Tab) - (Rank * 2), Item_length@1 = Item_length + 2, Wrap_at = gleam@int:max(case Item_length@1 of 0 -> 0; Gleam@denominator -> Max_length div Gleam@denominator end, 1), Inner_size@1 = case Shape of [Inner_size | _] -> Inner_size; _ -> 0 end, fun(J) -> ((case Wrap_at of 0 -> 0; Gleam@denominator@1 -> (J + 1) rem Gleam@denominator@1 end) =:= 0) andalso (Wrap_at < Inner_size@1) end; false -> fun(_) -> false end end, {to_string_acc, _, Init_builder} = To_string_acc = {to_string_acc, [], gleam@string_builder:new()}, Xs@1 = gleam@iterator:index( (gleam@iterator:map( gleam@iterator:from_list(Xs), fun(X@1) -> _pipe@4 = X@1, _pipe@5 = gleam@string:pad_left( _pipe@4, Item_length, <<" "/utf8>> ), gleam@string_builder:from_string(_pipe@5) end )) ), [{_, Xs@2}] = gleam@iterator:to_list( (gleam@list:index_fold( Shape, Xs@1, fun(Acc, Size, I) -> Should_build = fun(J@1) -> (case Size of 0 -> 0; Gleam@denominator@2 -> (J@1 + 1) rem Gleam@denominator@2 end) =:= 0 end, {to_string_acc, Built, _} = case I of 0 -> gleam@iterator:fold( Acc, To_string_acc, fun(Acc@1, Item) -> {J@2, X@2} = Item, Builder = gleam@string_builder:append_builder( erlang:element(3, Acc@1), X@2 ), Should_build_j = Should_build(J@2), bool_lazy_guard( Should_build_j andalso (Rank =:= 0), fun() -> erlang:setelement( 2, Acc@1, gleam@list:append( erlang:element(2, Acc@1), [Builder] ) ) end, fun() -> bool_lazy_guard( Should_build_j, fun() -> Builder@1 = begin _pipe@6 = Builder, _pipe@7 = gleam@string_builder:prepend( _pipe@6, <<"["/utf8>> ), gleam@string_builder:append( _pipe@7, <<"]"/utf8>> ) end, {to_string_acc, gleam@list:append( erlang:element(2, Acc@1), [Builder@1] ), Init_builder} end, fun() -> bool_lazy_guard( Should_wrap(J@2), fun() -> Indent = gleam@string:repeat( <<" "/utf8>>, Tab + Rank ), Builder@2 = begin _pipe@8 = Builder, _pipe@9 = gleam@string_builder:append( _pipe@8, <<",\n"/utf8>> ), gleam@string_builder:append( _pipe@9, Indent ) end, erlang:setelement( 3, Acc@1, Builder@2 ) end, fun() -> Builder@3 = gleam@string_builder:append( Builder, <<", "/utf8>> ), erlang:setelement( 3, Acc@1, Builder@3 ) end ) end ) end ) end ); _ -> gleam@iterator:fold( Acc, To_string_acc, fun(Acc@2, Item@1) -> {J@3, X@3} = Item@1, Builder@4 = gleam@string_builder:append_builder( erlang:element(3, Acc@2), X@3 ), bool_lazy_guard( Should_build(J@3), fun() -> Builder@5 = begin _pipe@10 = Builder@4, _pipe@11 = gleam@string_builder:prepend( _pipe@10, <<"["/utf8>> ), gleam@string_builder:append( _pipe@11, <<"]"/utf8>> ) end, {to_string_acc, gleam@list:append( erlang:element(2, Acc@2), [Builder@5] ), Init_builder} end, fun() -> Indent@1 = gleam@string:repeat( <<" "/utf8>>, (Tab + Rank) - I ), Builder@6 = begin _pipe@12 = Builder@4, _pipe@13 = gleam@string_builder:append( _pipe@12, <<",\n"/utf8>> ), gleam@string_builder:append( _pipe@13, Indent@1 ) end, erlang:setelement(3, Acc@2, Builder@6) end ) end ) end, _pipe@14 = Built, _pipe@15 = gleam@iterator:from_list(_pipe@14), gleam@iterator:index(_pipe@15) end )) ), Indent@2 = gleam@string:repeat(<<" "/utf8>>, Tab), _pipe@16 = Xs@2, _pipe@17 = gleam@string_builder:prepend(_pipe@16, Indent@2), gleam@string_builder:to_string(_pipe@17). -spec to_string(tensor(any()), to_string(), integer()) -> binary(). to_string(X, Record_or_data, Column) -> Column@1 = case Column < 0 of true -> argamak_ffi:columns(); false -> Column end, Tab = case Record_or_data of record -> 2; data -> 0 end, Data = begin _pipe = X, do_to_string(_pipe, Column@1, Tab) end, case Record_or_data of record -> Format = begin _pipe@1 = X, _pipe@2 = format(_pipe@1), argamak@format:to_string(_pipe@2) end, Space = begin _pipe@3 = X, _pipe@4 = space(_pipe@3), argamak@space:to_string(_pipe@4) end, Space@1 = case gleam@string:length(Space) > Column@1 of true when Column@1 > 0 -> _pipe@5 = Space, _pipe@6 = gleam@string:replace( _pipe@5, <<"Space("/utf8>>, <<"Space(\n "/utf8>> ), _pipe@7 = gleam@string:replace( _pipe@6, <<"), "/utf8>>, <<"),\n "/utf8>> ), gleam@string:replace( _pipe@7, <<"))"/utf8>>, <<"),\n )"/utf8>> ); _ -> Space end, _pipe@8 = [<<"Tensor("/utf8>>, <<<<" "/utf8, Format/binary>>/binary, ","/utf8>>, <<<<" "/utf8, Space@1/binary>>/binary, ","/utf8>>, <>, <<")"/utf8>>], gleam@string:join(_pipe@8, <<"\n"/utf8>>); data -> Data end. -spec print(tensor(any())) -> nil. print(X) -> _pipe = X, _pipe@1 = to_string(_pipe, record, -1), gleam@io:println(_pipe@1). -spec debug(tensor(LQD)) -> tensor(LQD). debug(X) -> print(X), X. -spec print_data(tensor(any())) -> nil. print_data(X) -> _pipe = X, _pipe@1 = to_string(_pipe, data, -1), gleam@io:println(_pipe@1).