nx_force_test.nx source
↩ module page · 102 lines · 3873 B
1// nx_force_test.nx -- 3D force vector ops verified against hand-
2// computed physics reference cases.
3//
4// Closed-form invariants (Q14 N throughout):
5// (a) Zero force: magnitude == 0.
6// (b) Unit +X force: (Q14, 0, 0) magnitude == Q14.
7// (c) (3, 4, 0) Q14 Newtons magnitude == 5 Q14 (3-4-5 triangle).
8// (d) Gravity on 1 kg: (0, 0, -9.80665 N) ≈ (0, 0, -160665 Q14).
9// (e) Gravity on 2 kg: 2x the above magnitude.
10// (f) Vector add: (1, 2, 3) + (4, 5, 6) = (5, 7, 9).
11// (g) Vector sub: (5, 7, 9) - (4, 5, 6) = (1, 2, 3).
12// (h) Scale by 2.0 (32768 Q14): doubles each component.
13// (i) Dot product (1, 0, 0)·(0, 1, 0) = 0 (perpendicular).
14// (j) Dot product (1, 2, 3)·(1, 2, 3) = 1 + 4 + 9 = 14 N² → 14 Q14
15// (each side has Q14 N; product is Q14 N², ratio Q14).
16// (k) Cross product +X × +Y = +Z (right-hand rule).
17// (l) Verdict name lookup non-NULL for every verdict.
18//
19// expect_exit: 0
20// license_tier: ORIGINAL
21
22import "nx_syscalls.nx"
23import "nx_force.nx"
24
25const Q14: i64 = 16384
26
27// Returns 1 if |actual - expected| <= tol, else 0.
28func near(actual: i64, expected: i64, tol: i64) -> i64 {
29 let diff: i64 = actual - expected
30 if diff < 0 { if -diff <= tol { return 1 } }
31 if diff >= 0 { if diff <= tol { return 1 } }
32 return 0
33}
34
35func main() -> i64 {
36 // --- (a) Zero ---
37 let f0: *NxForce = nx_force_zero()
38 if nx_force_magnitude_q14(f0) != 0 { return 10 }
39
40 // --- (b) Unit +X ---
41 let fx: *NxForce = nx_force_new(Q14, 0, 0)
42 if near(nx_force_magnitude_q14(fx), Q14, 1) != 1 { return 20 }
43
44 // --- (c) 3-4-5 ---
45 let f345: *NxForce = nx_force_new(3 * Q14, 4 * Q14, 0)
46 if near(nx_force_magnitude_q14(f345), 5 * Q14, 1) != 1 { return 30 }
47
48 // --- (d) Gravity on 1 kg ---
49 let g1: *NxForce = nx_force_gravity_on_kg(Q14) // 1 kg in Q14
50 if g1.fx_q14 != 0 { return 40 }
51 if g1.fy_q14 != 0 { return 41 }
52 if near(g1.fz_q14, -160665, 2) != 1 { return 42 }
53
54 // --- (e) Gravity on 2 kg (2x) ---
55 let g2: *NxForce = nx_force_gravity_on_kg(2 * Q14)
56 if near(nx_force_magnitude_q14(g2),
57 2 * nx_force_magnitude_q14(g1), 2) != 1 { return 50 }
58
59 // --- (f) Add ---
60 let a: *NxForce = nx_force_new(1, 2, 3)
61 let b: *NxForce = nx_force_new(4, 5, 6)
62 let sum: *NxForce = nx_force_add(a, b)
63 if sum.fx_q14 != 5 { return 60 }
64 if sum.fy_q14 != 7 { return 61 }
65 if sum.fz_q14 != 9 { return 62 }
66
67 // --- (g) Sub ---
68 let diff: *NxForce = nx_force_sub(sum, b)
69 if diff.fx_q14 != 1 { return 70 }
70 if diff.fy_q14 != 2 { return 71 }
71 if diff.fz_q14 != 3 { return 72 }
72
73 // --- (h) Scale by 2.0 (32768 Q14) ---
74 let s: *NxForce = nx_force_new(Q14, 2 * Q14, 3 * Q14)
75 let s2: *NxForce = nx_force_scale(s, 2 * Q14)
76 if near(s2.fx_q14, 2 * Q14, 1) != 1 { return 80 }
77 if near(s2.fy_q14, 4 * Q14, 1) != 1 { return 81 }
78 if near(s2.fz_q14, 6 * Q14, 1) != 1 { return 82 }
79
80 // --- (i) Perpendicular dot = 0 ---
81 let px: *NxForce = nx_force_new(Q14, 0, 0)
82 let py: *NxForce = nx_force_new(0, Q14, 0)
83 if nx_force_dot(px, py) != 0 { return 90 }
84
85 // --- (j) (1,2,3)·(1,2,3) = 14 ---
86 let v: *NxForce = nx_force_new(Q14, 2 * Q14, 3 * Q14)
87 // Expected: (1 + 4 + 9) Q14 = 14 Q14 = 229376
88 if near(nx_force_dot(v, v), 14 * Q14, 4) != 1 { return 100 }
89
90 // --- (k) Right-hand cross: +X × +Y = +Z ---
91 let cross: *NxForce = nx_force_cross(px, py)
92 if cross.fx_q14 != 0 { return 110 }
93 if cross.fy_q14 != 0 { return 111 }
94 if near(cross.fz_q14, Q14, 1) != 1 { return 112 }
95
96 // --- (l) Verdict names ---
97 if (nx_force_verdict_name(NX_FORCE_OK) as i64) == 0 { return 120 }
98 if (nx_force_verdict_name(NX_FORCE_ERR_NULL_INPUT) as i64) == 0 { return 121 }
99 if (nx_force_verdict_name(NX_FORCE_ERR_DEGENERATE) as i64) == 0 { return 122 }
100
101 return 0
102}