-module(argamak@tensor). -compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch]). -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, to_string/3, print/1, debug/1, print_data/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]). -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(MFX) :: {tensor, native(), argamak@format:format(MFX), argamak@space:space()}. -type native() :: any(). -type tensor_error() :: axis_not_found | 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(MFY) :: {fit_acc, integer(), fit_by()} | {gleam_phantom, MFY}. -type reducible() :: away | in_situ. -type reducible_acc() :: {reducible_acc, list(argamak@axis:axis()), list(integer())}. -spec format(tensor(MGT)) -> argamak@format:format(MGT). 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(MHI)) -> tensor(MHI). 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(MHO), argamak@space:space()) -> {ok, tensor(MHO)} | {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(MHR), argamak@space:space(), fun((argamak@axis:axis()) -> binary()) ) -> {ok, tensor(MHR)} | {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_dict = maps:from_list(Mapped_axes), Pre_shape = (gleam@list:map( New_axes, fun(Axis@2) -> _pipe@2 = Axis_dict, _pipe@3 = gleam@dict: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(MJH)) -> tensor(MJH). logical_not(X) -> erlang:setelement(2, X, argamak_ffi:logical_not(to_native(X))). -spec absolute_value(tensor(MLO)) -> tensor(MLO). absolute_value(X) -> erlang:setelement(2, X, argamak_ffi:absolute_value(to_native(X))). -spec negate(tensor(MLR)) -> tensor(MLR). negate(X) -> erlang:setelement(2, X, argamak_ffi:negate(to_native(X))). -spec sign(tensor(MLU)) -> tensor(MLU). sign(X) -> erlang:setelement(2, X, argamak_ffi:sign(to_native(X))). -spec ceiling(tensor(MLX)) -> tensor(MLX). ceiling(X) -> erlang:setelement(2, X, argamak_ffi:ceiling(to_native(X))). -spec floor(tensor(MMA)) -> tensor(MMA). floor(X) -> erlang:setelement(2, X, argamak_ffi:floor(to_native(X))). -spec round(tensor(MMD)) -> tensor(MMD). round(X) -> erlang:setelement(2, X, argamak_ffi:round(to_native(X))). -spec exp(tensor(MMG)) -> tensor(MMG). exp(X) -> erlang:setelement(2, X, argamak_ffi:exp(to_native(X))). -spec square_root(tensor(MMJ)) -> {ok, tensor(MMJ)} | {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(MMM)) -> {ok, tensor(MMM)} | {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(MOR)), fun((argamak@axis:axis()) -> boolean())) -> {ok, tensor(MOR)} | {error, tensor_error()}. concat(Xs, Find) -> gleam@result:'try'(case Xs of [_ | _] -> {ok, Xs}; _ -> {error, invalid_data} end, fun(Xs@1) -> [X | Rest] = case Xs@1 of [_ | _] -> Xs@1; _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 => 3420}) end, 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(1, Item)) end ), _pipe@4 = gleam@result:map( _pipe@3, fun(X@1) -> erlang:element(2, X@1) end ), gleam@result:replace_error(_pipe@4, axis_not_found) end, fun(Index) -> gleam@result:'try'( (gleam@list:try_fold( Rest, New_axes, fun(New_axes@1, X@2) -> gleam@result:'try'( begin _pipe@5 = New_axes@1, _pipe@6 = gleam@list:strict_zip( _pipe@5, axes(X@2) ), gleam@result:replace_error( _pipe@6, incompatible_shape ) end, fun(Pairs) -> Pairs@1 = begin _pipe@7 = Pairs, _pipe@8 = gleam@iterator:from_list( _pipe@7 ), gleam@iterator:index(_pipe@8) end, gleam@iterator:try_fold( Pairs@1, [], fun(New_axes@2, Pair) -> {{A, B}, I} = Pair, case argamak@axis:name(A) =:= argamak@axis:name( B ) of true when I =:= Index -> _pipe@9 = [argamak@axis:resize( A, argamak@axis:size( A ) + argamak@axis:size( B ) ) | New_axes@2], {ok, _pipe@9}; true when A =:= B -> {ok, [A | New_axes@2]}; _ -> {error, incompatible_shape} end end ) end ) end )), fun(New_axes@3) -> _assert_subject = begin _pipe@10 = New_axes@3, _pipe@11 = gleam@list:reverse(_pipe@10), argamak@space:from_list(_pipe@11) end, {ok, Space} = case _assert_subject of {ok, _} -> _assert_subject; _assert_fail@1 -> erlang:error(#{gleam_error => let_assert, message => <<"Assertion pattern match failed"/utf8>>, value => _assert_fail@1, module => <<"argamak/tensor"/utf8>>, function => <<"concat"/utf8>>, line => 3452}) end, Native = begin _pipe@12 = Xs@1, _pipe@13 = gleam@list:map( _pipe@12, fun to_native/1 ), argamak_ffi:concat(_pipe@13, Index) end, _pipe@14 = erlang:setelement( 4, erlang:setelement(2, X, Native), Space ), {ok, _pipe@14} 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 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 )) ), _assert_subject = 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) -> {X@2, J@2} = Item, Builder = gleam@string_builder:append_builder( erlang:element(3, Acc@1), X@2 ), Should_build_j = Should_build(J@2), gleam@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() -> gleam@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() -> gleam@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) -> {X@3, J@3} = Item@1, Builder@4 = gleam@string_builder:append_builder( erlang:element(3, Acc@2), X@3 ), gleam@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 )) ), [{Xs@2, _}] = case _assert_subject of [{_, _}] -> _assert_subject; _assert_fail -> erlang:error(#{gleam_error => let_assert, message => <<"Assertion pattern match failed"/utf8>>, value => _assert_fail, module => <<"argamak/tensor"/utf8>>, function => <<"do_to_string"/utf8>>, line => 3809}) 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(MQE)) -> tensor(MQE). 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). -spec fit(tensor(MQR)) -> {ok, tensor(MQR)} | {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 => 4050}) end, _pipe = erlang:setelement(4, X, Space), {ok, _pipe}; _ -> {error, incompatible_shape} end. -spec reshape(tensor(MHL), argamak@space:space()) -> {ok, tensor(MHL)} | {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(MGQ)) -> {ok, tensor(MGQ)} | {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(MQM)) -> {ok, tensor(MQM)} | {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 => 71}) 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 => 86}) 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 => 107}) 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(MQU), tensor(MQU) ) -> {ok, tensor(MQU)} | {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(MHX), tensor(MHX)) -> {ok, tensor(MHX)} | {error, tensor_error()}. equal(A, B) -> broadcastable(fun argamak_ffi:equal/2, A, B). -spec not_equal(tensor(MIB), tensor(MIB)) -> {ok, tensor(MIB)} | {error, tensor_error()}. not_equal(A, B) -> broadcastable(fun argamak_ffi:not_equal/2, A, B). -spec greater(tensor(MIF), tensor(MIF)) -> {ok, tensor(MIF)} | {error, tensor_error()}. greater(A, B) -> broadcastable(fun argamak_ffi:greater/2, A, B). -spec greater_or_equal(tensor(MIJ), tensor(MIJ)) -> {ok, tensor(MIJ)} | {error, tensor_error()}. greater_or_equal(A, B) -> broadcastable(fun argamak_ffi:greater_or_equal/2, A, B). -spec less(tensor(MIN), tensor(MIN)) -> {ok, tensor(MIN)} | {error, tensor_error()}. less(A, B) -> broadcastable(fun argamak_ffi:less/2, A, B). -spec less_or_equal(tensor(MIR), tensor(MIR)) -> {ok, tensor(MIR)} | {error, tensor_error()}. less_or_equal(A, B) -> broadcastable(fun argamak_ffi:less_or_equal/2, A, B). -spec logical_and(tensor(MIV), tensor(MIV)) -> {ok, tensor(MIV)} | {error, tensor_error()}. logical_and(A, B) -> broadcastable(fun argamak_ffi:logical_and/2, A, B). -spec logical_or(tensor(MIZ), tensor(MIZ)) -> {ok, tensor(MIZ)} | {error, tensor_error()}. logical_or(A, B) -> broadcastable(fun argamak_ffi:logical_or/2, A, B). -spec logical_xor(tensor(MJD), tensor(MJD)) -> {ok, tensor(MJD)} | {error, tensor_error()}. logical_xor(A, B) -> broadcastable(fun argamak_ffi:logical_xor/2, A, B). -spec add(tensor(MJK), tensor(MJK)) -> {ok, tensor(MJK)} | {error, tensor_error()}. add(A, B) -> broadcastable(fun argamak_ffi:add/2, A, B). -spec subtract(tensor(MJO), tensor(MJO)) -> {ok, tensor(MJO)} | {error, tensor_error()}. subtract(A, B) -> broadcastable(fun argamak_ffi:subtract/2, A, B). -spec multiply(tensor(MJS), tensor(MJS)) -> {ok, tensor(MJS)} | {error, tensor_error()}. multiply(A, B) -> broadcastable(fun argamak_ffi:multiply/2, A, B). -spec power(tensor(MLC), tensor(MLC)) -> {ok, tensor(MLC)} | {error, tensor_error()}. power(A, B) -> broadcastable(fun argamak_ffi:power/2, A, B). -spec max(tensor(MLG), tensor(MLG)) -> {ok, tensor(MLG)} | {error, tensor_error()}. max(A, B) -> broadcastable(fun argamak_ffi:max/2, A, B). -spec min(tensor(MLK), tensor(MLK)) -> {ok, tensor(MLK)} | {error, tensor_error()}. min(A, B) -> broadcastable(fun argamak_ffi:min/2, A, B). -spec sign_not_equal(tensor(MQY), tensor(MQY)) -> {ok, tensor(MQY)} | {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(MRC), fun((tensor(MRC)) -> {ok, tensor(MRC)} | {error, tensor_error()}) ) -> {ok, tensor(MRC)} | {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(MJW), tensor(MJW)) -> {ok, tensor(MJW)} | {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(MKI), tensor(MKI)) -> {ok, tensor(MKI)} | {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(MKE), tensor(MKE)) -> {ok, tensor(MKE)} | {error, tensor_error()}. remainder(A, B) -> do_remainder(A, B). -spec do_modulo(tensor(MKU), tensor(MKU)) -> {ok, tensor(MKU)} | {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(MKQ), tensor(MKQ)) -> {ok, tensor(MKQ)} | {error, tensor_error()}. modulo(A, B) -> do_modulo(A, B). -spec reducible_over_axes( fun((native(), list(integer())) -> native()), tensor(MRK), fun((argamak@axis:axis()) -> boolean()), reducible() ) -> tensor(MRK). 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 => 4146}) 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 => 4154}) 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 => 4162}) end, Native@2 end, erlang:setelement(4, erlang:setelement(2, X, Native@3), New_space). -spec squeeze(tensor(MHU), fun((argamak@axis:axis()) -> boolean())) -> tensor(MHU). 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(MMP), fun((argamak@axis:axis()) -> boolean())) -> tensor(MMP). all(X, Filter) -> reducible_over_axes(fun argamak_ffi:all/2, X, Filter, away). -spec in_situ_all(tensor(MMS), fun((argamak@axis:axis()) -> boolean())) -> tensor(MMS). in_situ_all(X, Filter) -> reducible_over_axes(fun argamak_ffi:all/2, X, Filter, in_situ). -spec any(tensor(MMV), fun((argamak@axis:axis()) -> boolean())) -> tensor(MMV). any(X, Filter) -> reducible_over_axes(fun argamak_ffi:any/2, X, Filter, away). -spec in_situ_any(tensor(MMY), fun((argamak@axis:axis()) -> boolean())) -> tensor(MMY). in_situ_any(X, Filter) -> reducible_over_axes(fun argamak_ffi:any/2, X, Filter, in_situ). -spec max_over(tensor(MNN), fun((argamak@axis:axis()) -> boolean())) -> tensor(MNN). max_over(X, Filter) -> reducible_over_axes(fun argamak_ffi:max_over/2, X, Filter, away). -spec in_situ_max_over(tensor(MNQ), fun((argamak@axis:axis()) -> boolean())) -> tensor(MNQ). in_situ_max_over(X, Filter) -> reducible_over_axes(fun argamak_ffi:max_over/2, X, Filter, in_situ). -spec min_over(tensor(MNT), fun((argamak@axis:axis()) -> boolean())) -> tensor(MNT). min_over(X, Filter) -> reducible_over_axes(fun argamak_ffi:min_over/2, X, Filter, away). -spec in_situ_min_over(tensor(MNW), fun((argamak@axis:axis()) -> boolean())) -> tensor(MNW). in_situ_min_over(X, Filter) -> reducible_over_axes(fun argamak_ffi:min_over/2, X, Filter, in_situ). -spec sum(tensor(MNZ), fun((argamak@axis:axis()) -> boolean())) -> tensor(MNZ). sum(X, Filter) -> reducible_over_axes(fun argamak_ffi:sum/2, X, Filter, away). -spec in_situ_sum(tensor(MOC), fun((argamak@axis:axis()) -> boolean())) -> tensor(MOC). in_situ_sum(X, Filter) -> reducible_over_axes(fun argamak_ffi:sum/2, X, Filter, in_situ). -spec product(tensor(MOF), fun((argamak@axis:axis()) -> boolean())) -> tensor(MOF). product(X, Filter) -> reducible_over_axes(fun argamak_ffi:product/2, X, Filter, away). -spec in_situ_product(tensor(MOI), fun((argamak@axis:axis()) -> boolean())) -> tensor(MOI). in_situ_product(X, Filter) -> reducible_over_axes(fun argamak_ffi:product/2, X, Filter, in_situ). -spec mean(tensor(MOL), fun((argamak@axis:axis()) -> boolean())) -> tensor(MOL). mean(X, Filter) -> reducible_over_axes(fun argamak_ffi:mean/2, X, Filter, away). -spec in_situ_mean(tensor(MOO), fun((argamak@axis:axis()) -> boolean())) -> tensor(MOO). in_situ_mean(X, Filter) -> reducible_over_axes(fun argamak_ffi:mean/2, X, Filter, in_situ). -spec all_nonzero(tensor(MRH)) -> {ok, tensor(MRH)} | {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(MKA), tensor(MKA)) -> {ok, tensor(MKA)} | {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(MKM), tensor(MKM)) -> {ok, tensor(MKM)} | {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(MKY), tensor(MKY)) -> {ok, tensor(MKY)} | {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(MRN), fun((argamak@axis:axis()) -> boolean()), reducible() ) -> tensor(MRN). 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 => 4192}) 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 => 4199}) 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 => 4203}) 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 => 4207}) end, erlang:setelement(4, erlang:setelement(2, X, Native), New_space) end. -spec arg_max(tensor(MNB), fun((argamak@axis:axis()) -> boolean())) -> tensor(MNB). arg_max(X, Find) -> reducible_over_axis(fun argamak_ffi:arg_max/2, X, Find, away). -spec in_situ_arg_max(tensor(MNE), fun((argamak@axis:axis()) -> boolean())) -> tensor(MNE). in_situ_arg_max(X, Find) -> reducible_over_axis(fun argamak_ffi:arg_max/2, X, Find, in_situ). -spec arg_min(tensor(MNH), fun((argamak@axis:axis()) -> boolean())) -> tensor(MNH). arg_min(X, Find) -> reducible_over_axis(fun argamak_ffi:arg_min/2, X, Find, away). -spec in_situ_arg_min(tensor(MNK), fun((argamak@axis:axis()) -> boolean())) -> tensor(MNK). 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).