code wiki / _hdl_build / nx_rational.nx
nx_rational.nx source
↩ module page · 62 lines · 2101 B
1// nx_rational.nx -- ME4 / WOLF-RATIONAL: EXACT rational arithmetic (the foundation of
2// symbolic + arbitrary-precision math, where f64 has rounding error and a CAS does not).
3// A rational is a 2-i64 block [num, den], kept gcd-NORMALIZED with den>0 (canonical, so
4// equality is a field compare). Operations are EXACT: a/b + c/d = (ad+bc)/(bd) reduced;
5// a/b * c/d = ac/bd reduced. (i64 limbs now; nx_bigint arbitrary-precision = the rung-2
6// upgrade for unbounded numerators -- the API is chosen so that swap is additive.)
7//
8// module: nishi-core.math.rational
9// depends: nishi-core.sys.syscalls
10// capability: EXACT_RATIONAL_ARITHMETIC
11// license_tier: ORIGINAL
12import "nx_syscalls.nx"
13
14func rat_new() -> *i64 { let r: *i64 = sys_mmap(16) as *i64; r[0] = 0; r[1] = 1; return r }
15
16// gcd of |a|,|b| (Euclid). gcd(x,0)=x.
17func rat_gcd(a: i64, b: i64) -> i64 {
18 var x: i64 = a
19 var y: i64 = b
20 if x < 0 { x = 0 - x }
21 if y < 0 { y = 0 - y }
22 while y != 0 { let t: i64 = x % y; x = y; y = t }
23 return x
24}
25
26// canonicalize r in place: den>0, divided by gcd(num,den). 0 -> 0/1.
27func rat_norm(r: *i64) -> i64 {
28 var num: i64 = r[0]
29 var den: i64 = r[1]
30 if den < 0 { num = 0 - num; den = 0 - den }
31 if num == 0 { r[0] = 0; r[1] = 1; return 0 }
32 let g: i64 = rat_gcd(num, den)
33 if g != 0 { num = num / g; den = den / g }
34 r[0] = num; r[1] = den
35 return 0
36}
37
38func rat_set(r: *i64, num: i64, den: i64) -> i64 { r[0] = num; r[1] = den; rat_norm(r); return 0 }
39
40// out = a + b (out may alias a or b)
41func rat_add(out: *i64, a: *i64, b: *i64) -> i64 {
42 let num: i64 = a[0] * b[1] + b[0] * a[1]
43 let den: i64 = a[1] * b[1]
44 out[0] = num; out[1] = den
45 rat_norm(out)
46 return 0
47}
48
49// out = a * b
50func rat_mul(out: *i64, a: *i64, b: *i64) -> i64 {
51 let num: i64 = a[0] * b[0]
52 let den: i64 = a[1] * b[1]
53 out[0] = num; out[1] = den
54 rat_norm(out)
55 return 0
56}
57
58// equality of canonical rationals: 1 iff num and den both match.
59func rat_eq(a: *i64, b: *i64) -> i64 {
60 if a[0] == b[0] { if a[1] == b[1] { return 1 } }
61 return 0
62}