# ideas by u/DaVinci103 # MIT License, Copyright (c) 2024 Marvin Borner # (p : q) ⇔ (1 / (q + 1)) :import std/Logic . :import std/Combinator . :import std/Logic . :import std/Pair . :import std/Math N # converts a balanced ternary number to a rational number number→rational [0 : (+0)] ⧗ Number → Rational :test (number→rational (+5)) ((+5.0)) # returns true if two rational numbers are equal eq? &[[&[[N.eq? (N.mul 3 N.++0) (N.mul N.++2 1)]]]] ⧗ Rational → Rational → Boolean …=?… eq? :test (((+1) : (+3)) =? ((+2) : (+7))) (true) :test ((+0.5) =? (+0.5)) (true) :test ((+42.0) =? (+42.0)) (true) :test ((+0.4) =? (+0.5)) (false) # finds smallest equivalent representation of a rational number compress &[[[(N.div 2 0) : N.--(N.div N.++1 0)] (N.gcd 1 N.++0)]] ⧗ Rational → Rational %‣ compress :test (%((+4) : (+1)) =? (+2.0)) (true) :test (%((+4) : (+7)) =? (+0.5)) (true) # adds two rational numbers add &[[&[[p : q]]]] ⧗ Rational → Rational → Rational p N.add (N.mul 3 N.++0) (N.mul 1 N.++2) q N.add (N.mul 2 0) (N.add 2 0) …+… add :test ((+0.5) + (+0.5) =? (+1.0)) (true) :test ((+1.8) + (+1.2) =? (+3.0)) (true) :test ((-1.8) + (+1.2) =? (-0.6)) (true) reduce [[[(N.div 2 0) : N.--(N.div 1 0)] (N.gcd 1 0)]] add' &[[&[[reduce p q]]]] p N.add (N.mul 3 N.++0) (N.mul 1 N.++2) q N.mul N.++0 N.++2 # subtracts two rational numbers sub &[[&[[p : q]]]] ⧗ Rational → Rational → Rational p N.sub (N.mul 3 N.++0) (N.mul 1 N.++2) q N.add (N.mul 2 0) (N.add 2 0) …-… sub :test ((+0.5) - (+0.5) =? (+0.0)) (true) :test ((+3.0) - (+1.8) =? (+1.2)) (true) :test ((+1.8) - (-1.2) =? (+3.0)) (true) # negates a rational number negate &[[N.-1 : 0]] ⧗ Rational → Rational -‣ negate :test (-(+0.0) =? (+0.0)) (true) :test (-(+4.2) =? (-4.2)) (true) :test (-(-4.2) =? (+4.2)) (true) # multiplies two rational numbers mul &[[&[[p : q]]]] ⧗ Rational → Rational → Rational p N.mul 3 1 q N.add (N.mul 2 0) (N.add 2 0) …⋅… mul :test ((+5.0) ⋅ (+5.0) =? (+25.0)) (true) :test ((+1.8) ⋅ (+1.2) =? (+2.16)) (true) # finds the multiplicative inverse of a rational number invert &[[N.compare-case eq gt lt 1 (+0)]] ⧗ Rational → Rational eq Ω gt N.++0 : N.--1 lt N.-(N.++0) : N.--(N.-1) ~‣ invert :test (~(+0.5) =? (+2.0)) (true) :test (~(-0.5) =? (-2.0)) (true) # divides two rational numbers div [[1 ⋅ ~0]] ⧗ Rational → Rational → Rational …/… div :test ((+8.0) / (+4.0) =? (+2.0)) (true) :test ((+18.0) / (+12.0) =? (+1.5)) (true) gt? &[[&[[(N.gt? 1 3) ⋀? (N.gt? 0 2)]]]] lt? &[[&[[(N.lt? 1 3) ⋀? (N.lt? 0 2)]]]] # increments a rational number inc add (+1.0) ⧗ Rational → Rational ++‣ inc # decrements a rational number dec \sub (+1.0) ⧗ Rational → Rational --‣ dec # TODO: Regression? Importing this into . won't find Q.eq? anymore :import std/List L # power function: rational^number pow-n [L.nth-iterate (mul 0) (+1.0)] ⧗ Rational → Number → Rational