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}