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}