Current section

Files

Jump to
viva_tensor src viva_tensor@observability@metrics.erl
Raw

src/viva_tensor@observability@metrics.erl

-module(viva_tensor@observability@metrics).
-compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch, inline]).
-define(FILEPATH, "src/viva_tensor/observability/metrics.gleam").
-export([try_mse/2, mse/2, try_mae/2, mae/2, try_rmse/2, rmse/2, try_cosine_similarity/2, cosine_similarity/2, try_snr_db/2, snr_db/2, theoretical_sqnr/1, try_max_error/2, max_error/2, try_error_percentile/3, error_percentile/3, try_outlier_percentage/3, outlier_percentage/3, try_compute_all/2, compute_all/2, compute_saliency/2, find_salient_weights/2, benchmark_metrics/0, main/0]).
-export_type([quant_metrics/0, layer_metrics/0]).
-if(?OTP_RELEASE >= 27).
-define(MODULEDOC(Str), -moduledoc(Str)).
-define(DOC(Str), -doc(Str)).
-else.
-define(MODULEDOC(Str), -compile([])).
-define(DOC(Str), -compile([])).
-endif.
?MODULEDOC(false).
-type quant_metrics() :: {quant_metrics,
float(),
float(),
float(),
float(),
float(),
float(),
float(),
float(),
float()}.
-type layer_metrics() :: {layer_metrics, binary(), quant_metrics(), float()}.
-file("src/viva_tensor/observability/metrics.gleam", 525).
?DOC(false).
-spec mean(list(float())) -> {ok, float()} |
{error, viva_tensor@core@error:tensor_error()}.
mean(Values) ->
case gleam_community@maths:mean(Values) of
{ok, Value} ->
{ok, Value};
{error, _} ->
{error,
{invalid_shape, <<"Cannot compute mean of an empty list"/utf8>>}}
end.
-file("src/viva_tensor/observability/metrics.gleam", 507).
?DOC(false).
-spec metric_data(viva_tensor@tensor:tensor(), viva_tensor@tensor:tensor()) -> {ok,
{list(float()), list(float())}} |
{error, viva_tensor@core@error:tensor_error()}.
metric_data(Original, Quantized) ->
case erlang:element(3, Original) =:= erlang:element(3, Quantized) of
false ->
{error,
{shape_mismatch,
erlang:element(3, Original),
erlang:element(3, Quantized)}};
true ->
gleam@result:'try'(
viva_tensor@tensor:try_to_list(Original),
fun(Orig) ->
gleam@result:'try'(
viva_tensor@tensor:try_to_list(Quantized),
fun(Quant) -> case Orig of
[] ->
{error,
{invalid_shape,
<<"Metrics require at least one element"/utf8>>}};
_ ->
{ok, {Orig, Quant}}
end end
)
end
)
end.
-file("src/viva_tensor/observability/metrics.gleam", 61).
?DOC(false).
-spec try_mse(viva_tensor@tensor:tensor(), viva_tensor@tensor:tensor()) -> {ok,
float()} |
{error, viva_tensor@core@error:tensor_error()}.
try_mse(Original, Quantized) ->
gleam@result:'try'(
metric_data(Original, Quantized),
fun(Pair) ->
{Orig, Quant} = Pair,
Squared_errors = gleam@list:map2(
Orig,
Quant,
fun(O, Q) ->
Diff = O - Q,
Diff * Diff
end
),
mean(Squared_errors)
end
).
-file("src/viva_tensor/observability/metrics.gleam", 78).
?DOC(false).
-spec mse(viva_tensor@tensor:tensor(), viva_tensor@tensor:tensor()) -> float().
mse(Original, Quantized) ->
_pipe = try_mse(Original, Quantized),
gleam@result:unwrap(_pipe, +0.0).
-file("src/viva_tensor/observability/metrics.gleam", 84).
?DOC(false).
-spec try_mae(viva_tensor@tensor:tensor(), viva_tensor@tensor:tensor()) -> {ok,
float()} |
{error, viva_tensor@core@error:tensor_error()}.
try_mae(Original, Quantized) ->
gleam@result:'try'(
metric_data(Original, Quantized),
fun(Pair) ->
{Orig, Quant} = Pair,
Abs_errors = gleam@list:map2(
Orig,
Quant,
fun(O, Q) -> gleam@float:absolute_value(O - Q) end
),
mean(Abs_errors)
end
).
-file("src/viva_tensor/observability/metrics.gleam", 98).
?DOC(false).
-spec mae(viva_tensor@tensor:tensor(), viva_tensor@tensor:tensor()) -> float().
mae(Original, Quantized) ->
_pipe = try_mae(Original, Quantized),
gleam@result:unwrap(_pipe, +0.0).
-file("src/viva_tensor/observability/metrics.gleam", 104).
?DOC(false).
-spec try_rmse(viva_tensor@tensor:tensor(), viva_tensor@tensor:tensor()) -> {ok,
float()} |
{error, viva_tensor@core@error:tensor_error()}.
try_rmse(Original, Quantized) ->
gleam@result:'try'(
try_mse(Original, Quantized),
fun(Mse_val) -> case gleam@float:square_root(Mse_val) of
{ok, Sqrt} ->
{ok, Sqrt};
{error, _} ->
{error,
{dimension_error,
<<"RMSE received a negative MSE"/utf8>>}}
end end
).
-file("src/viva_tensor/observability/metrics.gleam", 117).
?DOC(false).
-spec rmse(viva_tensor@tensor:tensor(), viva_tensor@tensor:tensor()) -> float().
rmse(Original, Quantized) ->
_pipe = try_rmse(Original, Quantized),
gleam@result:unwrap(_pipe, +0.0).
-file("src/viva_tensor/observability/metrics.gleam", 124).
?DOC(false).
-spec try_cosine_similarity(
viva_tensor@tensor:tensor(),
viva_tensor@tensor:tensor()
) -> {ok, float()} | {error, viva_tensor@core@error:tensor_error()}.
try_cosine_similarity(Original, Quantized) ->
gleam@result:'try'(
metric_data(Original, Quantized),
fun(Pair) ->
{Orig, Quant} = Pair,
case gleam_community@maths:cosine_similarity(
gleam@list:zip(Orig, Quant)
) of
{ok, Value} ->
{ok, Value};
{error, _} ->
{error,
{dimension_error,
<<"Cosine similarity requires non-zero norm tensors"/utf8>>}}
end
end
).
-file("src/viva_tensor/observability/metrics.gleam", 140).
?DOC(false).
-spec cosine_similarity(
viva_tensor@tensor:tensor(),
viva_tensor@tensor:tensor()
) -> float().
cosine_similarity(Original, Quantized) ->
_pipe = try_cosine_similarity(Original, Quantized),
gleam@result:unwrap(_pipe, +0.0).
-file("src/viva_tensor/observability/metrics.gleam", 558).
?DOC(false).
-spec log10(float()) -> float().
log10(X) ->
_pipe = gleam_community@maths:logarithm_10(X),
gleam@result:unwrap(_pipe, +0.0).
-file("src/viva_tensor/observability/metrics.gleam", 147).
?DOC(false).
-spec try_snr_db(viva_tensor@tensor:tensor(), viva_tensor@tensor:tensor()) -> {ok,
float()} |
{error, viva_tensor@core@error:tensor_error()}.
try_snr_db(Original, Quantized) ->
gleam@result:'try'(
metric_data(Original, Quantized),
fun(Pair) ->
{Orig, Quant} = Pair,
gleam@result:'try'(
mean(gleam@list:map(Orig, fun(X) -> X * X end)),
fun(Signal_power) ->
gleam@result:'try'(
begin
_pipe = gleam@list:map2(
Orig,
Quant,
fun(O, Q) ->
Diff = O - Q,
Diff * Diff
end
),
mean(_pipe)
end,
fun(Noise_power) -> case Noise_power > +0.0 of
true ->
{ok, 10.0 * log10(case Noise_power of
+0.0 -> +0.0;
-0.0 -> -0.0;
Gleam@denominator -> Signal_power
/ Gleam@denominator
end)};
false ->
{ok, 100.0}
end end
)
end
)
end
).
-file("src/viva_tensor/observability/metrics.gleam", 172).
?DOC(false).
-spec snr_db(viva_tensor@tensor:tensor(), viva_tensor@tensor:tensor()) -> float().
snr_db(Original, Quantized) ->
_pipe = try_snr_db(Original, Quantized),
gleam@result:unwrap(_pipe, +0.0).
-file("src/viva_tensor/observability/metrics.gleam", 179).
?DOC(false).
-spec theoretical_sqnr(integer()) -> float().
theoretical_sqnr(Bits) ->
(6.02 * erlang:float(Bits)) + 1.76.
-file("src/viva_tensor/observability/metrics.gleam", 184).
?DOC(false).
-spec try_max_error(viva_tensor@tensor:tensor(), viva_tensor@tensor:tensor()) -> {ok,
float()} |
{error, viva_tensor@core@error:tensor_error()}.
try_max_error(Original, Quantized) ->
gleam@result:'try'(
metric_data(Original, Quantized),
fun(Pair) ->
{Orig, Quant} = Pair,
{ok,
begin
_pipe = gleam@list:map2(
Orig,
Quant,
fun(O, Q) -> gleam@float:absolute_value(O - Q) end
),
gleam@list:fold(_pipe, +0.0, fun gleam@float:max/2)
end}
end
).
-file("src/viva_tensor/observability/metrics.gleam", 198).
?DOC(false).
-spec max_error(viva_tensor@tensor:tensor(), viva_tensor@tensor:tensor()) -> float().
max_error(Original, Quantized) ->
_pipe = try_max_error(Original, Quantized),
gleam@result:unwrap(_pipe, +0.0).
-file("src/viva_tensor/observability/metrics.gleam", 532).
?DOC(false).
-spec validate_percentile(float()) -> {ok, nil} |
{error, viva_tensor@core@error:tensor_error()}.
validate_percentile(Percentile) ->
case (Percentile >= +0.0) andalso (Percentile =< 100.0) of
true ->
{ok, nil};
false ->
{error,
{dimension_error,
<<"Percentile must be between 0 and 100"/utf8>>}}
end.
-file("src/viva_tensor/observability/metrics.gleam", 218).
?DOC(false).
-spec try_error_percentile(
viva_tensor@tensor:tensor(),
viva_tensor@tensor:tensor(),
float()
) -> {ok, float()} | {error, viva_tensor@core@error:tensor_error()}.
try_error_percentile(Original, Quantized, Percentile) ->
gleam@result:'try'(
metric_data(Original, Quantized),
fun(Pair) ->
{Orig, Quant} = Pair,
gleam@result:'try'(
validate_percentile(Percentile),
fun(_use0) ->
nil = _use0,
Errors = begin
_pipe = gleam@list:map2(
Orig,
Quant,
fun(O, Q) -> gleam@float:absolute_value(O - Q) end
),
gleam@list:sort(_pipe, fun gleam@float:compare/2)
end,
case gleam_community@maths:percentile(
Errors,
erlang:round(Percentile)
) of
{ok, Value} ->
{ok, Value};
{error, _} ->
{error,
{invalid_shape,
<<"Cannot compute percentile for empty tensors"/utf8>>}}
end
end
)
end
).
-file("src/viva_tensor/observability/metrics.gleam", 208).
?DOC(false).
-spec error_percentile(
viva_tensor@tensor:tensor(),
viva_tensor@tensor:tensor(),
float()
) -> float().
error_percentile(Original, Quantized, Percentile) ->
_pipe = try_error_percentile(Original, Quantized, Percentile),
gleam@result:unwrap(_pipe, +0.0).
-file("src/viva_tensor/observability/metrics.gleam", 249).
?DOC(false).
-spec try_outlier_percentage(
viva_tensor@tensor:tensor(),
viva_tensor@tensor:tensor(),
float()
) -> {ok, float()} | {error, viva_tensor@core@error:tensor_error()}.
try_outlier_percentage(Original, Quantized, Threshold) ->
gleam@result:'try'(
metric_data(Original, Quantized),
fun(Pair) ->
{Orig, Quant} = Pair,
Errors = gleam@list:map2(
Orig,
Quant,
fun(O, Q) -> gleam@float:absolute_value(O - Q) end
),
Outliers = gleam@list:filter(Errors, fun(E) -> E > Threshold end),
N = erlang:length(Errors),
{ok, case erlang:float(N) of
+0.0 -> +0.0;
-0.0 -> -0.0;
Gleam@denominator -> 100.0 * erlang:float(
erlang:length(Outliers)
)
/ Gleam@denominator
end}
end
).
-file("src/viva_tensor/observability/metrics.gleam", 239).
?DOC(false).
-spec outlier_percentage(
viva_tensor@tensor:tensor(),
viva_tensor@tensor:tensor(),
float()
) -> float().
outlier_percentage(Original, Quantized, Threshold) ->
_pipe = try_outlier_percentage(Original, Quantized, Threshold),
gleam@result:unwrap(_pipe, +0.0).
-file("src/viva_tensor/observability/metrics.gleam", 270).
?DOC(false).
-spec try_compute_all(viva_tensor@tensor:tensor(), viva_tensor@tensor:tensor()) -> {ok,
quant_metrics()} |
{error, viva_tensor@core@error:tensor_error()}.
try_compute_all(Original, Quantized) ->
gleam@result:'try'(
try_mse(Original, Quantized),
fun(Mse_val) ->
gleam@result:'try'(
try_mae(Original, Quantized),
fun(Mae_val) ->
gleam@result:'try'(
try_rmse(Original, Quantized),
fun(Rmse_val) ->
gleam@result:'try'(
try_cosine_similarity(Original, Quantized),
fun(Cosine_val) ->
gleam@result:'try'(
try_snr_db(Original, Quantized),
fun(Snr_val) ->
Sqnr_val = Snr_val,
gleam@result:'try'(
try_max_error(
Original,
Quantized
),
fun(Max_err) ->
gleam@result:'try'(
try_error_percentile(
Original,
Quantized,
99.0
),
fun(P99) ->
gleam@result:'try'(
try_outlier_percentage(
Original,
Quantized,
0.01
),
fun(Outliers) ->
{ok,
{quant_metrics,
Mse_val,
Mae_val,
Rmse_val,
Cosine_val,
Snr_val,
Sqnr_val,
Max_err,
P99,
Outliers}}
end
)
end
)
end
)
end
)
end
)
end
)
end
)
end
).
-file("src/viva_tensor/observability/metrics.gleam", 298).
?DOC(false).
-spec compute_all(viva_tensor@tensor:tensor(), viva_tensor@tensor:tensor()) -> quant_metrics().
compute_all(Original, Quantized) ->
_pipe = try_compute_all(Original, Quantized),
gleam@result:unwrap(
_pipe,
{quant_metrics, +0.0, +0.0, +0.0, +0.0, +0.0, +0.0, +0.0, +0.0, +0.0}
).
-file("src/viva_tensor/observability/metrics.gleam", 591).
?DOC(false).
-spec pad_or_truncate(list(ANSL), integer(), ANSL) -> list(ANSL).
pad_or_truncate(Lst, Target_len, Default) ->
Current_len = erlang:length(Lst),
case Current_len >= Target_len of
true ->
gleam@list:take(Lst, Target_len);
false ->
_pipe = Lst,
lists:append(
_pipe,
gleam@list:repeat(Default, Target_len - Current_len)
)
end.
-file("src/viva_tensor/observability/metrics.gleam", 584).
?DOC(false).
-spec result_or({ok, ANSH} | {error, any()}, ANSH) -> ANSH.
result_or(R, Default) ->
case R of
{ok, V} ->
V;
{error, _} ->
Default
end.
-file("src/viva_tensor/observability/metrics.gleam", 578).
?DOC(false).
-spec get_at(list(ANSD), integer()) -> {ok, ANSD} | {error, nil}.
get_at(List, Index) ->
_pipe = List,
_pipe@1 = gleam@list:drop(_pipe, Index),
gleam@list:first(_pipe@1).
-file("src/viva_tensor/observability/metrics.gleam", 319).
?DOC(false).
-spec compute_saliency(viva_tensor@tensor:tensor(), list(list(float()))) -> list(float()).
compute_saliency(Weights, Activations) ->
W_data = viva_tensor@tensor:to_list(Weights),
Activation_vars = case Activations of
[] ->
gleam@list:repeat(1.0, erlang:length(W_data));
[First | _] ->
N_channels = erlang:length(First),
N_samples = erlang:float(erlang:length(Activations)),
Means = begin
_pipe = gleam@list:repeat(+0.0, N_channels),
_pipe@1 = gleam@list:index_fold(
Activations,
_pipe,
fun(Acc, Acts, _) ->
gleam@list:map2(Acc, Acts, fun(A, Act) -> A + Act end)
end
),
gleam@list:map(_pipe@1, fun(S) -> case N_samples of
+0.0 -> +0.0;
-0.0 -> -0.0;
Gleam@denominator -> S / Gleam@denominator
end end)
end,
_pipe@4 = gleam@list:index_fold(
Activations,
gleam@list:repeat(+0.0, N_channels),
fun(Acc@1, Acts@1, _) ->
gleam@list:index_map(
Acc@1,
fun(A@1, I) ->
Mean = begin
_pipe@2 = get_at(Means, I),
result_or(_pipe@2, +0.0)
end,
Act@1 = begin
_pipe@3 = get_at(Acts@1, I),
result_or(_pipe@3, +0.0)
end,
Diff = Act@1 - Mean,
A@1 + (Diff * Diff)
end
)
end
),
gleam@list:map(_pipe@4, fun(V) -> case N_samples of
+0.0 -> +0.0;
-0.0 -> -0.0;
Gleam@denominator@1 -> V / Gleam@denominator@1
end end)
end,
Padded_vars = pad_or_truncate(Activation_vars, erlang:length(W_data), 1.0),
gleam@list:map2(Padded_vars, W_data, fun(Var, W) -> (Var * W) * W end).
-file("src/viva_tensor/observability/metrics.gleam", 365).
?DOC(false).
-spec find_salient_weights(list(float()), float()) -> list(integer()).
find_salient_weights(Saliency, Top_pct) ->
Indexed = gleam@list:index_map(Saliency, fun(S, I) -> {I, S} end),
Sorted = gleam@list:sort(
Indexed,
fun(A, B) ->
gleam@float:compare(erlang:element(2, B), erlang:element(2, A))
end
),
N = erlang:length(Saliency),
K = begin
_pipe = erlang:round((erlang:float(N) * Top_pct) / 100.0),
gleam@int:max(_pipe, 1)
end,
_pipe@1 = gleam@list:take(Sorted, K),
gleam@list:map(_pipe@1, fun(Pair) -> erlang:element(1, Pair) end).
-file("src/viva_tensor/observability/metrics.gleam", 563).
?DOC(false).
-spec float_to_str(float()) -> binary().
float_to_str(F) ->
Rounded = erlang:float(erlang:round(F * 100.0)) / 100.0,
gleam_stdlib:float_to_string(Rounded).
-file("src/viva_tensor/observability/metrics.gleam", 568).
?DOC(false).
-spec pad_float(float()) -> binary().
pad_float(F) ->
S = float_to_str(F),
Len = string:length(S),
Padding = 10 - Len,
case Padding > 0 of
true ->
<<S/binary, (gleam@string:repeat(<<" "/utf8>>, Padding))/binary>>;
false ->
gleam@string:slice(S, 0, 10)
end.
-file("src/viva_tensor/observability/metrics.gleam", 550).
?DOC(false).
-spec get_tensor_shape(viva_tensor@tensor:tensor()) -> list(integer()).
get_tensor_shape(T) ->
case T of
{tensor, _, Shape} ->
Shape;
{strided_tensor, _, Shape@1, _, _} ->
Shape@1;
{native_tensor, _, Shape@2} ->
Shape@2
end.
-file("src/viva_tensor/observability/metrics.gleam", 539).
?DOC(false).
-spec add_noise(viva_tensor@tensor:tensor(), float()) -> viva_tensor@tensor:tensor().
add_noise(T, Noise_level) ->
Data = viva_tensor@tensor:to_list(T),
Noisy = gleam@list:index_map(
Data,
fun(X, I) ->
Noise = (erlang:float((I rem 100) - 50) / 50.0) * Noise_level,
X + Noise
end
),
{tensor, Noisy, get_tensor_shape(T)}.
-file("src/viva_tensor/observability/metrics.gleam", 397).
?DOC(false).
-spec benchmark_metrics() -> nil.
benchmark_metrics() ->
gleam_stdlib:println(<<""/utf8>>),
gleam_stdlib:println(
<<"╔═══════════════════════════════════════════════════════════════╗"/utf8>>
),
gleam_stdlib:println(
<<"║ QUANTIZATION METRICS - BENCHMARK ║"/utf8>>
),
gleam_stdlib:println(
<<"╚═══════════════════════════════════════════════════════════════╝"/utf8>>
),
gleam_stdlib:println(<<""/utf8>>),
Original = viva_tensor@tensor:random_normal([1024], +0.0, 1.0),
Small_noise = add_noise(Original, 0.01),
Medium_noise = add_noise(Original, 0.05),
Large_noise = add_noise(Original, 0.1),
gleam_stdlib:println(<<"Original: 1024 floats, mean=0, std=1"/utf8>>),
gleam_stdlib:println(<<""/utf8>>),
gleam_stdlib:println(
<<"┌────────────────┬────────────┬────────────┬────────────┐"/utf8>>
),
gleam_stdlib:println(
<<"│ Metric │ Noise 1% │ Noise 5% │ Noise 10% │"/utf8>>
),
gleam_stdlib:println(
<<"├────────────────┼────────────┼────────────┼────────────┤"/utf8>>
),
M1 = compute_all(Original, Small_noise),
M2 = compute_all(Original, Medium_noise),
M3 = compute_all(Original, Large_noise),
gleam_stdlib:println(
<<<<<<<<<<<<"│ MSE │ "/utf8,
(pad_float(erlang:element(2, M1)))/binary>>/binary,
" │ "/utf8>>/binary,
(pad_float(erlang:element(2, M2)))/binary>>/binary,
" │ "/utf8>>/binary,
(pad_float(erlang:element(2, M3)))/binary>>/binary,
" │"/utf8>>
),
gleam_stdlib:println(
<<<<<<<<<<<<"│ MAE │ "/utf8,
(pad_float(erlang:element(3, M1)))/binary>>/binary,
" │ "/utf8>>/binary,
(pad_float(erlang:element(3, M2)))/binary>>/binary,
" │ "/utf8>>/binary,
(pad_float(erlang:element(3, M3)))/binary>>/binary,
" │"/utf8>>
),
gleam_stdlib:println(
<<<<<<<<<<<<"│ RMSE │ "/utf8,
(pad_float(erlang:element(4, M1)))/binary>>/binary,
" │ "/utf8>>/binary,
(pad_float(erlang:element(4, M2)))/binary>>/binary,
" │ "/utf8>>/binary,
(pad_float(erlang:element(4, M3)))/binary>>/binary,
" │"/utf8>>
),
gleam_stdlib:println(
<<<<<<<<<<<<"│ Cosine Sim │ "/utf8,
(pad_float(erlang:element(5, M1)))/binary>>/binary,
" │ "/utf8>>/binary,
(pad_float(erlang:element(5, M2)))/binary>>/binary,
" │ "/utf8>>/binary,
(pad_float(erlang:element(5, M3)))/binary>>/binary,
" │"/utf8>>
),
gleam_stdlib:println(
<<<<<<<<<<<<"│ SNR (dB) │ "/utf8,
(pad_float(erlang:element(6, M1)))/binary>>/binary,
" │ "/utf8>>/binary,
(pad_float(erlang:element(6, M2)))/binary>>/binary,
" │ "/utf8>>/binary,
(pad_float(erlang:element(6, M3)))/binary>>/binary,
" │"/utf8>>
),
gleam_stdlib:println(
<<<<<<<<<<<<"│ Max Error │ "/utf8,
(pad_float(erlang:element(8, M1)))/binary>>/binary,
" │ "/utf8>>/binary,
(pad_float(erlang:element(8, M2)))/binary>>/binary,
" │ "/utf8>>/binary,
(pad_float(erlang:element(8, M3)))/binary>>/binary,
" │"/utf8>>
),
gleam_stdlib:println(
<<<<<<<<<<<<"│ P99 Error │ "/utf8,
(pad_float(erlang:element(9, M1)))/binary>>/binary,
" │ "/utf8>>/binary,
(pad_float(erlang:element(9, M2)))/binary>>/binary,
" │ "/utf8>>/binary,
(pad_float(erlang:element(9, M3)))/binary>>/binary,
" │"/utf8>>
),
gleam_stdlib:println(
<<"└────────────────┴────────────┴────────────┴────────────┘"/utf8>>
),
gleam_stdlib:println(<<""/utf8>>),
gleam_stdlib:println(<<"Theoretical SQNR:"/utf8>>),
gleam_stdlib:println(
<<<<" INT8 (8 bits): "/utf8,
(float_to_str(theoretical_sqnr(8)))/binary>>/binary,
" dB"/utf8>>
),
gleam_stdlib:println(
<<<<" INT4 (4 bits): "/utf8,
(float_to_str(theoretical_sqnr(4)))/binary>>/binary,
" dB"/utf8>>
),
gleam_stdlib:println(
<<<<" INT2 (2 bits): "/utf8,
(float_to_str(theoretical_sqnr(2)))/binary>>/binary,
" dB"/utf8>>
),
gleam_stdlib:println(<<""/utf8>>).
-file("src/viva_tensor/observability/metrics.gleam", 393).
?DOC(false).
-spec main() -> nil.
main() ->
benchmark_metrics().