code wiki / _hdl_build / nx_f64_quad.nx

nx_f64_quad.nx source

↩ module page · 55 lines · 2274 B

1// nx_f64_quad.nx -- GAMS-H: sovereign numerical QUADRATURE (the integration class). 2// Composite Simpson's rule (O(h^4)) over a sign... over a function-id dispatch (no fn 3// pointers in the dialect); qf_eval composes our PROVEN kernels (x^2 / sin / exp / 1/x). 4// integral_a^b f dx ~= h/3 [ f0 + 4(f1+f3+..) + 2(f2+f4+..) + fn ], h=(b-a)/n, n even. 5// f64 software-IEEE; node x_i = a + i*h built from an exact integer-as-f64 (no drift). 6// (Gauss-Legendre / adaptive Gauss-Kronrod = the accuracy/perf upgrade -- its nodes are 7// Legendre roots, computable by composing the new nx_f64_rootfind.) 8// 9// module: nishi-core.math.f64_quad 10// depends: nishi-core.math.f64, nishi-core.math.f64_exp, nishi-core.math.f64_sincos 11// capability: F64_QUADRATURE_SIMPSON 12// license_tier: ORIGINAL 13import "nx_syscalls.nx" 14import "nx_f64.nx" 15import "nx_f64_div.nx" 16import "nx_f64_exp.nx" 17import "_pe_f64sincos.nx" 18 19const Q_ONE: i64 = 0x3FF0000000000000 // 1.0 20const Q_TWO: i64 = 0x4000000000000000 // 2.0 21const Q_THREE: i64 = 0x4008000000000000 // 3.0 22const Q_FOUR: i64 = 0x4010000000000000 // 4.0 23 24func qf_eval(fid: i64, x: i64) -> i64 { 25 if fid == 0 { return nx_f64_mul(x, x) } // x^2 26 if fid == 1 { return nx_f64_sin(x) } // sin(x) 27 if fid == 2 { return nx_f64_exp(x) } // e^x 28 return nx_f64_div(Q_ONE, x) // 1/x 29} 30 31// integer -> f64 by repeated +1.0 (exact for k < 2^53; k small here). 32func qf_i2f(k: i64) -> i64 { 33 var r: i64 = 0 34 var i: i64 = 0 35 while i < k { r = nx_f64_add(r, Q_ONE); i = i + 1 } 36 return r 37} 38 39// composite Simpson over [a,b] with n (even) panels. 40func nx_f64_quad_simpson(fid: i64, a: i64, b: i64, n: i64) -> i64 { 41 let nf: i64 = qf_i2f(n) 42 let h: i64 = nx_f64_div(nx_f64_sub(b, a), nf) 43 var sum: i64 = nx_f64_add(qf_eval(fid, a), qf_eval(fid, b)) 44 var if64: i64 = Q_ONE 45 var i: i64 = 1 46 while i < n { 47 let x: i64 = nx_f64_add(a, nx_f64_mul(if64, h)) 48 let fx: i64 = qf_eval(fid, x) 49 if (i & 1) == 1 { sum = nx_f64_add(sum, nx_f64_mul(Q_FOUR, fx)) } 50 else { sum = nx_f64_add(sum, nx_f64_mul(Q_TWO, fx)) } 51 if64 = nx_f64_add(if64, Q_ONE) 52 i = i + 1 53 } 54 return nx_f64_mul(sum, nx_f64_div(h, Q_THREE)) 55}