Current section

Files

Jump to
argamak src argamak@tensor.erl
Raw

src/argamak@tensor.erl

-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>>,
<<Data/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).