From 12377f23e3ae1c56df7dddaddf88bcb1e8a3e5f8 Mon Sep 17 00:00:00 2001 From: radrow Date: Mon, 10 Feb 2020 12:14:46 +0100 Subject: [PATCH] Added optimizer --- priv/stdlib/Frac.aes | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-) diff --git a/priv/stdlib/Frac.aes b/priv/stdlib/Frac.aes index 1a58012..27ad531 100644 --- a/priv/stdlib/Frac.aes +++ b/priv/stdlib/Frac.aes @@ -7,6 +7,7 @@ namespace Frac = datatype frac = Pos(int, int) | Zero | Neg(int, int) + // Checks if internal representation is correct. Numerator and denominator must be positive. function is_sane(f : frac) : bool = switch(f) Pos(n, d) => n > 0 && d > 0 Zero => true @@ -37,6 +38,7 @@ namespace Frac = Neg(n, d) => String.concat("-", to_str(Pos(n, d))) Zero => "0" + // Reduce fraction to normal form function simplify(f : frac) : frac = switch(f) Neg(n, d) => @@ -47,7 +49,7 @@ namespace Frac = let cd = gcd(n, d) Pos(n / cd, d / cd) - function make_frac(n : int, d : int): frac = + function make_frac(n : int, d : int) : frac = if (d == 0) abort("Division by zero") elif (n == 0) Zero elif ((n < 0) == (d < 0)) simplify(Pos(abs_int(n), abs_int(d))) @@ -109,6 +111,7 @@ namespace Frac = Zero => 0 Neg(n, d) => -(n + d - 1) / d + // Round towards nearest integer. If two integers are in the same distance, choose the even one. function round(f : frac) : int = let fl = floor(f) let cl = ceil(f) @@ -153,4 +156,16 @@ namespace Frac = else let half = int_exp_(b, e / 2) if (e mod 2 == 1) mul(mul(half, half), b) - else mul(half, half) \ No newline at end of file + else mul(half, half) + + // Reduces the fraction's in-memory size by dividing its components by two until the + // the error is bigger than `loss` value + function optimize(f : frac, loss : frac) : frac = + require(geq(loss, Zero), "negative loss optimize") + let s = sign(f) + mul(from_int(s), run_optimize(abs(f), loss)) + private function run_optimize(f : frac, loss : frac) : frac = + let t = make_frac((num(f) + 1) / 2, (den(f) + 1)/2) + if(gt(abs(sub(t, f)), loss)) f + elif (eq(t, f)) f + else run_optimize(t, loss)