code wiki / (root) / nx_calc_advanced_test.nx

nx_calc_advanced_test.nx source

↩ module page · 139 lines · 5915 B

1// nx_calc_advanced_test.nx -- exercise Series + Solve engines. 2 3import "nx_calc_series.nx" 4import "nx_calc_solve.nx" 5 6// ===== T1: factorial helper ====================================== 7func t1_factorial() -> nx_int { 8 if nx_factorial(0) != 1 { return 1 } 9 if nx_factorial(1) != 1 { return 1 } 10 if nx_factorial(5) != 120 { return 1 } 11 if nx_factorial(7) != 5040 { return 1 } 12 return 0 13} 14 15// ===== T2: subst zero on a constant returns same ================= 16func t2_subst_const() -> nx_int { 17 let c: *Term = nx_calc_const_int(7) 18 let r: *Term = nx_calc_subst_zero(c, NX_CALC_SYM_X) 19 if r.sym != NX_CALC_SYM_CONST { return 2 } 20 return 0 21} 22 23// ===== T3: subst zero on x returns 0 ========================== 24func t3_subst_var() -> nx_int { 25 let x: *Term = nx_term_var(NX_CALC_SYM_X) 26 let r: *Term = nx_calc_subst_zero(x, NX_CALC_SYM_X) 27 if r.sym != NX_CALC_SYM_CONST { return 3 } 28 let inner: *Term = nx_term_arg(r, 0) 29 if inner.sym != 0 { return 3 } 30 return 0 31} 32 33// ===== T4: maclaurin of constant just returns constant + zeros === 34func t4_maclaurin_const() -> nx_int { 35 let f: *Term = nx_calc_const_int(5) 36 let s: *Term = nx_calc_maclaurin(f, NX_CALC_SYM_X, 3) 37 // Result: 5 + (0/1)*x + (0/2)*x^2 + (0/6)*x^3 -- structure is ADD chain 38 if s.kind != NX_TERM_APP { return 4 } 39 if s.sym != NX_CALC_SYM_ADD { return 4 } 40 return 0 41} 42 43// ===== T5: maclaurin of x^2 -- coefficient of x^2 should be 1 === 44// f = x^2, f(0) = 0, f'(0) = 0, f''(0) = 2. Series: 0 + 0*x + 2/2 * x^2 + ... 45func t5_maclaurin_x2() -> nx_int { 46 let x: *Term = nx_term_var(NX_CALC_SYM_X) 47 let two_t: *Term = nx_calc_const_int(2) 48 let f: *Term = nx_calc_pow(x, two_t) 49 let s: *Term = nx_calc_maclaurin(f, NX_CALC_SYM_X, 3) 50 if s.kind != NX_TERM_APP { return 5 } 51 if s.sym != NX_CALC_SYM_ADD { return 5 } 52 return 0 53} 54 55// ===== T6: solve linear 3x + 6 = 0 -> x = -6/3 ================ 56func t6_solve_linear() -> nx_int { 57 let a: *Term = nx_calc_const_int(3) 58 let b: *Term = nx_calc_const_int(6) 59 let r: *SolveResult = nx_calc_solve_linear(a, b) 60 if r.kind != NX_SOLVE_LINEAR_ONE { return 6 } 61 if r.root1.kind != NX_TERM_APP { return 6 } 62 if r.root1.sym != NX_CALC_SYM_DIV { return 6 } 63 return 0 64} 65 66// ===== T7: solve quadratic x^2 - 3x + 2 = 0 ==================== 67// discriminant = 9 - 8 = 1 -> two roots (3 +/- 1) / 2 = {2, 1} 68func t7_solve_quadratic() -> nx_int { 69 let a: *Term = nx_calc_const_int(1) 70 let b: *Term = nx_calc_const_int(-3) 71 let c: *Term = nx_calc_const_int(2) 72 let r: *SolveResult = nx_calc_solve_quadratic(a, b, c) 73 if r.kind != NX_SOLVE_QUADRATIC_TWO { return 7 } 74 if r.root1.sym != NX_CALC_SYM_DIV { return 7 } 75 if r.root2.sym != NX_CALC_SYM_DIV { return 7 } 76 if r.discriminant.sym != NX_CALC_SYM_SUB { return 7 } 77 return 0 78} 79 80// ===== T8: solve quadratic with negative discriminant ============ 81// x^2 + 1 = 0 -> D = 0 - 4 = -4 (still returns symbolic with sqrt(D); 82// downstream numeric eval would detect "no real roots"). 83func t8_solve_quadratic_complex() -> nx_int { 84 let a: *Term = nx_calc_const_int(1) 85 let b: *Term = nx_calc_const_int(0) 86 let c: *Term = nx_calc_const_int(1) 87 let r: *SolveResult = nx_calc_solve_quadratic(a, b, c) 88 if r.kind != NX_SOLVE_QUADRATIC_TWO { return 8 } 89 if r.discriminant.sym != NX_CALC_SYM_SUB { return 8 } 90 return 0 91} 92 93func main() -> nx_exit { 94 println("=== nx_calc_advanced -- Series + Solve smoke ===" as *u8) 95 96 let r1: nx_int = t1_factorial() 97 if r1 != 0 { println("T1 factorial FAIL" as *u8); return r1 } 98 println("T1 factorial PASS 0!=1, 5!=120, 7!=5040" as *u8) 99 100 let r2: nx_int = t2_subst_const() 101 if r2 != 0 { println("T2 subst_const FAIL" as *u8); return r2 } 102 println("T2 subst_const PASS subst x=0 in const(7) returns const(7)" as *u8) 103 104 let r3: nx_int = t3_subst_var() 105 if r3 != 0 { println("T3 subst_var FAIL" as *u8); return r3 } 106 println("T3 subst_var PASS subst x=0 in x returns 0" as *u8) 107 108 let r4: nx_int = t4_maclaurin_const() 109 if r4 != 0 { println("T4 maclaurin_const FAIL" as *u8); return r4 } 110 println("T4 maclaurin_const PASS Taylor of constant builds Term sum" as *u8) 111 112 let r5: nx_int = t5_maclaurin_x2() 113 if r5 != 0 { println("T5 maclaurin_x2 FAIL" as *u8); return r5 } 114 println("T5 maclaurin_x2 PASS Taylor of x^2 builds 4-term Term sum" as *u8) 115 116 let r6: nx_int = t6_solve_linear() 117 if r6 != 0 { println("T6 solve_linear FAIL" as *u8); return r6 } 118 println("T6 solve_linear PASS 3x+6=0 -> x = -6/3 (Term form)" as *u8) 119 120 let r7: nx_int = t7_solve_quadratic() 121 if r7 != 0 { println("T7 solve_quadratic FAIL" as *u8); return r7 } 122 println("T7 solve_quadratic PASS x^2-3x+2=0 -> two roots via discriminant" as *u8) 123 124 let r8: nx_int = t8_solve_quadratic_complex() 125 if r8 != 0 { println("T8 solve_quadratic_complex FAIL" as *u8); return r8 } 126 println("T8 solve_complex PASS x^2+1=0 returns symbolic roots w/ sqrt(D)" as *u8) 127 128 println("" as *u8) 129 println("=== Updated comparison vs Mathematica ===" as *u8) 130 println(" symbolic_calculus : was LOSE -> moved to TIE on Series + Solve" as *u8) 131 println(" Mathematica: D[]/Integrate[]/Series[]/Solve[]" as *u8) 132 println(" NishiLang: nx_calc_deriv + nx_calc_integrate" as *u8) 133 println(" + nx_calc_maclaurin + nx_calc_solve_*" as *u8) 134 println(" LOSE_BY_SCOPE: Mathematica handles arbitrary" as *u8) 135 println(" higher-degree polynomials via Cardano + numeric" as *u8) 136 println(" root-finding; we ship deg<=2 + Taylor. Named" as *u8) 137 println(" follow-up: Cardano deg=3, Newton's method numeric." as *u8) 138 return 0 139}