-module(argamak@tensor). -compile(no_auto_import). -export([from_float/1, from_int/1, from_floats/2, from_ints/2, from_native/3, axes/1, format/1, rank/1, shape/1, space/1, as_format/2, broadcast/2, broadcast_over/3, reshape/2, to_float/1, to_int/1, to_list/1, to_native/1, print/3]). -export_type([tensor/3, native/0, opt/1, tensor_error/0, fit_acc/1, data_to_string_acc/0, exception/0]). -opaque tensor(JVE, JVF, JVG) :: {tensor, native(), argamak@format:format(JVE), argamak@space:space(JVF, JVG)}. -type native() :: any(). -type opt(JVH) :: {names, list(JVH)}. -type tensor_error() :: empty_tensor | incompatible_axes | incompatible_shape | invalid_data | {space_errors, list(argamak@space:space_error())}. -type fit_acc(JVI) :: {fit_acc, integer(), gleam@option:option(JVI)}. -type data_to_string_acc() :: {data_to_string_acc, integer(), fun((integer()) -> boolean())}. -type exception() :: any(). -spec error(binary()) -> tensor_error(). error(Message) -> do_error(Message). -spec do_error(binary()) -> tensor_error(). do_error(Message) -> _pipe = [{empty_tensor, <<"empty tensor"/utf8>>}, {incompatible_axes, <<"axes .*? must be unique integers"/utf8>>}, {incompatible_axes, <<"broadcast axes must be ordered"/utf8>>}, {incompatible_axes, <<"cannot merge names"/utf8>>}, {incompatible_shape, <<"cannot broadcast"/utf8>>}, {incompatible_shape, <<"cannot reshape"/utf8>>}, {incompatible_shape, <<"invalid dimension"/utf8>>}, {invalid_data, <<"cannot infer the numerical type"/utf8>>}], replace_error(Message, _pipe). -spec from_float(float()) -> tensor(float(), argamak@space:d0(), nil). from_float(Float) -> {ok, Space@1} = case argamak@space:d0() of {ok, Space} -> {ok, Space}; _try -> erlang:error(#{gleam_error => assert, message => <<"Assertion pattern match failed"/utf8>>, value => _try, module => <<"argamak/tensor"/utf8>>, function => <<"from_float"/utf8>>, line => 96}) end, {ok, Tensor@1} = case tensor(Float, Space@1, fun argamak@format:float32/0) of {ok, Tensor} -> {ok, Tensor}; _try@1 -> erlang:error(#{gleam_error => assert, message => <<"Assertion pattern match failed"/utf8>>, value => _try@1, module => <<"argamak/tensor"/utf8>>, function => <<"from_float"/utf8>>, line => 97}) end, Tensor@1. -spec from_int(integer()) -> tensor(integer(), argamak@space:d0(), nil). from_int(Int) -> {ok, Space@1} = case argamak@space:d0() of {ok, Space} -> {ok, Space}; _try -> erlang:error(#{gleam_error => assert, message => <<"Assertion pattern match failed"/utf8>>, value => _try, module => <<"argamak/tensor"/utf8>>, function => <<"from_int"/utf8>>, line => 113}) end, {ok, Tensor@1} = case tensor(Int, Space@1, fun argamak@format:int32/0) of {ok, Tensor} -> {ok, Tensor}; _try@1 -> erlang:error(#{gleam_error => assert, message => <<"Assertion pattern match failed"/utf8>>, value => _try@1, module => <<"argamak/tensor"/utf8>>, function => <<"from_int"/utf8>>, line => 114}) end, Tensor@1. -spec from_floats(list(float()), argamak@space:space(JVX, JVY)) -> {ok, tensor(float(), JVX, JVY)} | {error, tensor_error()}. from_floats(List, Space) -> tensor(List, Space, fun argamak@format:float32/0). -spec from_ints(list(integer()), argamak@space:space(JWH, JWI)) -> {ok, tensor(integer(), JWH, JWI)} | {error, tensor_error()}. from_ints(List, Space) -> tensor(List, Space, fun argamak@format:int32/0). -spec from_native( native(), argamak@space:space(JWQ, JWR), fun(() -> argamak@format:format(JWU)) ) -> {ok, tensor(JWU, JWQ, JWR)} | {error, tensor_error()}. from_native(Native, Space, Format) -> _pipe = Native, _pipe@1 = 'Elixir.Nx':to_flat_list(_pipe), tensor(_pipe@1, Space, Format). -spec tensor( any(), argamak@space:space(JXC, JXD), fun(() -> argamak@format:format(JXG)) ) -> {ok, tensor(JXG, JXC, JXD)} | {error, tensor_error()}. tensor(Data, Space, Format) -> _pipe@4 = fun() -> _pipe = Data, _pipe@1 = 'Elixir.Nx':tensor(_pipe, []), _pipe@2 = {tensor, _pipe@1, Format(), Space}, _pipe@3 = reshape(_pipe@2, Space), gleam@result:map( _pipe@3, fun(_capture) -> as_format(_capture, Format) end ) end, _pipe@5 = rescue(_pipe@4, fun error/1), gleam@result:flatten(_pipe@5). -spec axes(tensor(any(), any(), JXT)) -> list(JXT). axes(Tensor) -> _pipe = Tensor, _pipe@1 = space(_pipe), argamak@space:axes(_pipe@1). -spec format(tensor(JXY, any(), any())) -> argamak@format:format(JXY). format(Tensor) -> erlang:element(3, Tensor). -spec rank(tensor(any(), any(), any())) -> integer(). rank(Tensor) -> _pipe = Tensor, _pipe@1 = space(_pipe), _pipe@2 = argamak@space:elements(_pipe@1), gleam@list:length(_pipe@2). -spec shape(tensor(any(), any(), any())) -> list(integer()). shape(Tensor) -> _pipe = Tensor, _pipe@1 = space(_pipe), argamak@space:shape(_pipe@1). -spec space(tensor(any(), JYT, JYU)) -> argamak@space:space(JYT, JYU). space(Tensor) -> erlang:element(4, Tensor). -spec as_format(tensor(any(), JZB, JZC), fun(() -> argamak@format:format(JZG))) -> tensor(JZG, JZB, JZC). as_format(Tensor, Format) -> Format@1 = Format(), _pipe = Tensor, _pipe@1 = to_native(_pipe), _pipe@2 = 'Elixir.Nx':as_type(_pipe@1, argamak@format:to_native(Format@1)), {tensor, _pipe@2, Format@1, space(Tensor)}. -spec broadcast(tensor(JZL, any(), any()), argamak@space:space(JZR, JZS)) -> {ok, tensor(JZL, JZR, JZS)} | {error, tensor_error()}. broadcast(Tensor, New_space) -> _pipe@7 = fun() -> Shape = begin _pipe = New_space, _pipe@1 = argamak@space:shape(_pipe), erlang:list_to_tuple(_pipe@1) end, Opts = [begin _pipe@2 = New_space, _pipe@3 = argamak@space:axes(_pipe@2), {names, _pipe@3} end], _pipe@4 = Tensor, _pipe@5 = to_native(_pipe@4), _pipe@6 = 'Elixir.Nx':broadcast(_pipe@5, Shape, Opts), {tensor, _pipe@6, format(Tensor), New_space} end, rescue(_pipe@7, fun error/1). -spec broadcast_over( tensor(KAE, any(), KAG), argamak@space:space(KAK, KAL), fun(({KAG, integer()}) -> KAL) ) -> {ok, tensor(KAE, KAK, KAL)} | {error, tensor_error()}. broadcast_over(Tensor, New_space, Axes) -> New_elements = begin _pipe = New_space, argamak@space:elements(_pipe) end, case begin _pipe@1 = Tensor, _pipe@2 = space(_pipe@1), _pipe@3 = argamak@space:elements(_pipe@2), _pipe@7 = gleam@list:map( _pipe@3, begin _pipe@4 = Axes, gleam@function:compose( _pipe@4, fun(Axis) -> _pipe@5 = New_elements, _pipe@6 = gleam@list:find( _pipe@5, fun(Element) -> erlang:element(1, Element) =:= Axis end ), gleam@result:replace_error(_pipe@6, incompatible_axes) end ) end ), gleam@result:all(_pipe@7) end of {error, _try} -> {error, _try}; {ok, Mapped_elements} -> Axis_map = begin _pipe@8 = Mapped_elements, gleam@map:from_list(_pipe@8) end, Pre_shape = begin _pipe@9 = New_elements, _pipe@12 = gleam@list:map( _pipe@9, fun(Element@1) -> _pipe@10 = Axis_map, _pipe@11 = gleam@map:get( _pipe@10, erlang:element(1, Element@1) ), gleam@result:unwrap(_pipe@11, 1) end ), erlang:list_to_tuple(_pipe@12) end, _pipe@21 = fun() -> Shape = begin _pipe@13 = New_space, _pipe@14 = argamak@space:shape(_pipe@13), erlang:list_to_tuple(_pipe@14) end, Opts = [begin _pipe@15 = New_space, _pipe@16 = argamak@space:axes(_pipe@15), {names, _pipe@16} end], _pipe@17 = Tensor, _pipe@18 = to_native(_pipe@17), _pipe@19 = 'Elixir.Nx':reshape(_pipe@18, Pre_shape, Opts), _pipe@20 = 'Elixir.Nx':broadcast(_pipe@19, Shape, Opts), {tensor, _pipe@20, format(Tensor), New_space} end, rescue(_pipe@21, fun error/1) end. -spec reshape(tensor(KAT, any(), any()), argamak@space:space(KAZ, KBA)) -> {ok, tensor(KAT, KAZ, KBA)} | {error, tensor_error()}. reshape(Tensor, New_space) -> case begin _pipe = Tensor, _pipe@1 = to_native(_pipe), _pipe@2 = {tensor, _pipe@1, format(Tensor), New_space}, fit(_pipe@2) end of {error, _try} -> {error, _try}; {ok, Tensor@1} -> _pipe@9 = fun() -> Space = begin _pipe@3 = Tensor@1, space(_pipe@3) end, Shape = begin _pipe@4 = Space, _pipe@5 = argamak@space:shape(_pipe@4), erlang:list_to_tuple(_pipe@5) end, Opts = [begin _pipe@6 = Space, _pipe@7 = argamak@space:axes(_pipe@6), {names, _pipe@7} end], _pipe@8 = Tensor@1, map_data( _pipe@8, fun(_capture) -> 'Elixir.Nx':reshape(_capture, Shape, Opts) end ) end, rescue(_pipe@9, fun error/1) end. -spec to_float(tensor(float(), argamak@space:d0(), any())) -> float(). to_float(Tensor) -> _pipe = Tensor, _pipe@1 = to_native(_pipe), 'Elixir.Nx':to_number(_pipe@1). -spec to_int(tensor(integer(), argamak@space:d0(), any())) -> integer(). to_int(Tensor) -> _pipe = Tensor, _pipe@1 = to_native(_pipe), 'Elixir.Nx':to_number(_pipe@1). -spec to_list(tensor(KBV, any(), any())) -> list(KBV). to_list(Tensor) -> _pipe = Tensor, _pipe@1 = to_native(_pipe), 'Elixir.Nx':to_flat_list(_pipe@1). -spec to_native(tensor(any(), any(), any())) -> native(). to_native(Tensor) -> erlang:element(2, Tensor). -spec fit(tensor(KCK, KCL, KCM)) -> {ok, tensor(KCK, KCL, KCM)} | {error, tensor_error()}. fit(Tensor) -> Space = begin _pipe = Tensor, space(_pipe) end, Dividend = begin _pipe@1 = Tensor, _pipe@2 = to_list(_pipe@1), gleam@list:length(_pipe@2) end, Initial = {fit_acc, 1, none}, {fit_acc, Divisor, Inferring} = begin _pipe@3 = Space, _pipe@4 = argamak@space:elements(_pipe@3), gleam@list:fold( _pipe@4, Initial, fun(Acc, Element) -> {Axis, Size} = Element, case Size of -1 -> erlang:setelement(3, Acc, {some, Axis}); _@1 -> erlang:setelement(2, Acc, erlang:element(2, Acc) * Size) end end ) end, case case Divisor of 0 -> 0; Gleam@denominator -> Dividend rem Gleam@denominator end of 0 -> case Inferring of none -> {ok, Tensor}; {some, Infer} -> {ok, Space@2} = case begin _pipe@5 = Space, argamak@space:map_elements( _pipe@5, fun(Element@1) -> {Axis@1, _@2} = Element@1, case Axis@1 =:= Infer of true -> {Axis@1, case Divisor of 0 -> 0; Gleam@denominator@1 -> Dividend div Gleam@denominator@1 end}; false -> Element@1 end end ) end of {ok, Space@1} -> {ok, Space@1}; _try -> erlang:error(#{gleam_error => assert, message => <<"Assertion pattern match failed"/utf8>>, value => _try, module => <<"argamak/tensor"/utf8>>, function => <<"fit"/utf8>>, line => 933}) end, _pipe@6 = erlang:setelement(4, Tensor, Space@2), {ok, _pipe@6} end; _@3 -> {error, incompatible_shape} end. -spec map_data(tensor(KCX, KCY, KCZ), fun((native()) -> native())) -> tensor(KCX, KCY, KCZ). map_data(Tensor, Fun) -> erlang:setelement( 2, Tensor, begin _pipe = Tensor, _pipe@1 = to_native(_pipe), Fun(_pipe@1) end ). -spec print(tensor(any(), any(), any()), integer(), boolean()) -> nil. print(Tensor, Max_width, Meta) -> String = begin _pipe = Tensor, data_to_string(_pipe, Max_width) end, String@1 = case rank(Tensor) > 0 of true -> String; false -> _pipe@1 = String, _pipe@2 = gleam@string:drop_left(_pipe@1, 1), gleam@string:drop_right(_pipe@2, 1) end, _pipe@10 = case Meta of true -> Format = begin _pipe@3 = Tensor, _pipe@4 = format(_pipe@3), argamak@format:to_string(_pipe@4) end, Space = begin _pipe@5 = Tensor, _pipe@6 = space(_pipe@5), argamak@space:to_string(_pipe@6) end, _pipe@9 = [<<"Tensor"/utf8>>, begin _pipe@7 = [<<"format:"/utf8>>, Format], gleam@string:join(_pipe@7, <<" "/utf8>>) end, begin _pipe@8 = [<<"space:"/utf8>>, Space], gleam@string:join(_pipe@8, <<" "/utf8>>) end, <<"data:"/utf8>>, <<""/utf8>>], gleam@string:join(_pipe@9, <<"\n"/utf8>>); false -> <<""/utf8>> end, _pipe@11 = gleam@string:append(_pipe@10, String@1), gleam@io:println(_pipe@11). -spec data_to_string(tensor(any(), any(), any()), integer()) -> binary(). data_to_string(Tensor, Max_width) -> Max_width@1 = case Max_width < 0 of true -> 39; false -> Max_width end, Is_long = case Max_width@1 of 0 -> fun(_) -> false end; _@1 -> fun(Int) -> Int > Max_width@1 end end, {_@2, String} = begin _pipe = Tensor, _pipe@1 = shape(_pipe), _pipe@2 = gleam@list:drop(_pipe@1, 1), _pipe@3 = gleam@list:reverse(_pipe@2), _pipe@9 = gleam@list:fold( _pipe@3, begin _pipe@4 = Tensor, _pipe@5 = to_list(_pipe@4), gleam@dynamic:from(_pipe@5) end, fun(Acc, Size) -> {ok, Acc@2} = case begin _pipe@6 = Acc, gleam@dynamic:shallow_list(_pipe@6) end of {ok, Acc@1} -> {ok, Acc@1}; _try -> erlang:error(#{gleam_error => assert, message => <<"Assertion pattern match failed"/utf8>>, value => _try, module => <<"argamak/tensor"/utf8>>, function => <<"data_to_string"/utf8>>, line => 1079}) end, _pipe@7 = Acc@2, _pipe@8 = gleam@list:sized_chunk(_pipe@7, Size), gleam@dynamic:from(_pipe@8) end ), data_to_string_acc({data_to_string_acc, 1, Is_long}, _pipe@9) end, gleam@string:concat([<<"["/utf8>>, String, <<"]"/utf8>>]). -spec data_to_string_acc(data_to_string_acc(), gleam@dynamic:dynamic()) -> {data_to_string_acc(), binary()}. data_to_string_acc(Acc, List) -> Ws = begin _pipe = <<" "/utf8>>, gleam@string:repeat(_pipe, erlang:element(2, Acc)) end, Ws_length = begin _pipe@1 = Ws, gleam@string:length(_pipe@1) end, {ok, String@4} = case begin _pipe@2 = List, (gleam@dynamic:any( [gleam@function:compose( gleam@dynamic:list(fun gleam@dynamic:shallow_list/1), fun(_capture) -> gleam@result:map( _capture, fun(List@1) -> {_@1, Strings} = begin _pipe@3 = List@1, gleam@list:map_fold( _pipe@3, erlang:setelement( 2, Acc, erlang:element(2, Acc) + 1 ), fun(Acc@1, List@2) -> _pipe@4 = List@2, _pipe@5 = gleam@dynamic:from(_pipe@4), data_to_string_acc(Acc@1, _pipe@5) end ) end, _pipe@6 = Strings, _pipe@7 = gleam@iterator:from_list(_pipe@6), _pipe@8 = gleam@iterator:map( _pipe@7, fun(String) -> gleam@string:concat( [<<"["/utf8>>, String, <<"]"/utf8>>] ) end ), _pipe@9 = gleam@iterator:intersperse( _pipe@8, gleam@string:append(<<",\n"/utf8>>, Ws) ), _pipe@10 = gleam@iterator:to_list(_pipe@9), gleam@string:concat(_pipe@10) end ) end ), gleam@function:compose( fun gleam@dynamic:shallow_list/1, fun(_capture@1) -> gleam@result:map( _capture@1, fun(List@3) -> {_@3, String@2} = begin _pipe@11 = List@3, _pipe@12 = gleam@iterator:from_list(_pipe@11), _pipe@13 = gleam@iterator:index(_pipe@12), gleam@iterator:fold( _pipe@13, {0, <<""/utf8>>}, fun(Inner_acc, Tuple) -> {Index, Item} = Tuple, {Line_length, String@1} = Inner_acc, Item@1 = item_to_string(Item), Item_length = gleam@string:length( Item@1 ) + 1, case Index of 0 -> {Ws_length + Item_length, Item@1}; _@2 -> Item_length@1 = Item_length, Line_length@1 = Line_length + Item_length@1, case (erlang:element(3, Acc))( Line_length@1 + Ws_length ) of true -> {Ws_length + Item_length@1, begin _pipe@14 = [String@1, <<",\n"/utf8>>, Ws, Item@1], gleam@string:concat( _pipe@14 ) end}; false -> {Line_length@1 + 1, begin _pipe@15 = [String@1, <<", "/utf8>>, Item@1], gleam@string:concat( _pipe@15 ) end} end end end ) end, String@2 end ) end )] ))(_pipe@2) end of {ok, String@3} -> {ok, String@3}; _try -> erlang:error(#{gleam_error => assert, message => <<"Assertion pattern match failed"/utf8>>, value => _try, module => <<"argamak/tensor"/utf8>>, function => <<"data_to_string_acc"/utf8>>, line => 1107}) end, {Acc, String@4}. -spec item_to_string(gleam@dynamic:dynamic()) -> binary(). item_to_string(Item) -> {ok, String@1} = case begin _pipe = Item, (gleam@dynamic:any( [gleam@function:compose( fun gleam@dynamic:float/1, fun(_capture) -> gleam@result:map(_capture, fun gleam@float:to_string/1) end ), gleam@function:compose( fun gleam@dynamic:int/1, fun(_capture@1) -> gleam@result:map(_capture@1, fun gleam@int:to_string/1) end ), fun gleam@dynamic:string/1] ))(_pipe) end of {ok, String} -> {ok, String}; _try -> erlang:error(#{gleam_error => assert, message => <<"Assertion pattern match failed"/utf8>>, value => _try, module => <<"argamak/tensor"/utf8>>, function => <<"item_to_string"/utf8>>, line => 1175}) end, String@1. -spec rescue(fun(() -> KDU), fun((binary()) -> KDV)) -> {ok, KDU} | {error, KDV}. rescue(Fun1, Fun2) -> do_rescue(Fun1, Fun2). -spec do_rescue(fun(() -> KDY), fun((binary()) -> KDZ)) -> {ok, KDY} | {error, KDZ}. do_rescue(Fun1, Fun2) -> _pipe = Fun1, _pipe@1 = gleam@erlang:rescue(_pipe), gleam@result:map_error( _pipe@1, begin _pipe@2 = fun decode_crash/1, gleam@function:compose(_pipe@2, Fun2) end ). -spec decode_crash(gleam@erlang:crash()) -> binary(). decode_crash(Crash) -> case Crash of {errored, Dynamic} -> _pipe@3 = case 'Elixir.Exception':'exception?'(Dynamic) of true -> _pipe = Dynamic, _pipe@1 = exception_from_dynamic(_pipe), gleam@result:map(_pipe@1, fun 'Elixir.Exception':message/1); false -> _pipe@2 = Dynamic, gleam@dynamic:string(_pipe@2) end, gleam@result:unwrap(_pipe@3, <<""/utf8>>); {exited, Dynamic} -> _pipe@3 = case 'Elixir.Exception':'exception?'(Dynamic) of true -> _pipe = Dynamic, _pipe@1 = exception_from_dynamic(_pipe), gleam@result:map(_pipe@1, fun 'Elixir.Exception':message/1); false -> _pipe@2 = Dynamic, gleam@dynamic:string(_pipe@2) end, gleam@result:unwrap(_pipe@3, <<""/utf8>>); {thrown, Dynamic} -> _pipe@3 = case 'Elixir.Exception':'exception?'(Dynamic) of true -> _pipe = Dynamic, _pipe@1 = exception_from_dynamic(_pipe), gleam@result:map(_pipe@1, fun 'Elixir.Exception':message/1); false -> _pipe@2 = Dynamic, gleam@dynamic:string(_pipe@2) end, gleam@result:unwrap(_pipe@3, <<""/utf8>>); _@1 -> <<""/utf8>> end. -spec exception_from_dynamic(gleam@dynamic:dynamic()) -> {ok, exception()} | {error, list(gleam@dynamic:decode_error())}. exception_from_dynamic(From) -> case 'Elixir.Exception':'exception?'(From) of true -> _pipe = From, _pipe@1 = gleam@dynamic:unsafe_coerce(_pipe), {ok, _pipe@1}; false -> _pipe@2 = [{decode_error, <<"Exception"/utf8>>, gleam@dynamic:classify(From), []}], {error, _pipe@2} end. -spec replace_error(binary(), list({KEF, binary()})) -> KEF. replace_error(Message, List) -> Opts = {options, true, false}, {ok, Error@2} = case begin _pipe = List, gleam@list:find_map( _pipe, fun(Pair) -> {Error, Test} = Pair, {ok, Test@2} = case begin _pipe@1 = Test, gleam@regex:compile(_pipe@1, Opts) end of {ok, Test@1} -> {ok, Test@1}; _try -> erlang:error(#{gleam_error => assert, message => <<"Assertion pattern match failed"/utf8>>, value => _try, module => <<"argamak/tensor"/utf8>>, function => <<"replace_error"/utf8>>, line => 1284}) end, case gleam@regex:check(Test@2, Message) of true -> {ok, Error}; false -> {error, nil} end end ) end of {ok, Error@1} -> {ok, Error@1}; _try@1 -> erlang:error(#{gleam_error => assert, message => <<"Assertion pattern match failed"/utf8>>, value => _try@1, module => <<"argamak/tensor"/utf8>>, function => <<"replace_error"/utf8>>, line => 1280}) end, Error@2.