nx_perlin_test.nx source
↩ module page · 77 lines · 3317 B
1// nx_perlin_test.nx -- smoke for seeded Perlin noise + classification.
2
3import "nx_syscalls.nx"
4import "nx_tier.nx"
5import "nx_perlin.nx"
6
7func main() -> nx_int {
8 // === Test 1: same seed -> identical permutation tables ===
9 let s_a: *PerlinState = nx_perlin_alloc(42)
10 let s_b: *PerlinState = nx_perlin_alloc(42)
11 var i: nx_int = 0
12 while i < 16 {
13 if s_a.perm[i] != s_b.perm[i] { return 1 }
14 i = i + 1
15 }
16
17 // === Test 2: different seed -> different table (at least one cell) ===
18 let s_c: *PerlinState = nx_perlin_alloc(99)
19 var any_diff: nx_int = 0
20 var j: nx_int = 0
21 while j < 256 {
22 if s_a.perm[j] != s_c.perm[j] { any_diff = 1 }
23 j = j + 1
24 }
25 if any_diff != 1 { return 2 }
26
27 // === Test 3: 2D noise at integer cell corners returns 0 ===
28 // At any integer (cell corner), fractional offsets are 0, dot
29 // products with gradient are 0, so noise = 0.
30 let n_corner: nx_int = nx_perlin_2d(s_a, 0, 0)
31 if n_corner != 0 { return 10 }
32 let n_corner2: nx_int = nx_perlin_2d(s_a, 1024 * 5, 1024 * 3)
33 if n_corner2 != 0 { return 11 }
34
35 // === Test 4: 2D noise mid-cell is in valid range ===
36 // At fractional (0.5, 0.5), magnitude bounded by gradient
37 // contribution -- well within [-Q, Q] = [-1024, 1024].
38 let n_mid: nx_int = nx_perlin_2d(s_a, 512, 512)
39 if n_mid < (0 - 1024) { return 20 }
40 if n_mid > 1024 { return 21 }
41
42 // === Test 5: determinism -- two calls at same point return same value ===
43 let v1: nx_int = nx_perlin_2d(s_a, 300, 700)
44 let v2: nx_int = nx_perlin_2d(s_a, 300, 700)
45 if v1 != v2 { return 30 }
46
47 // === Test 6: FBM bounded ===
48 let f: nx_int = nx_perlin_fbm_2d(s_a, 512, 512, 4, 512)
49 if f < (0 - 1024) { return 40 }
50 if f > 1024 { return 41 }
51
52 // === Test 7: qualitative classification bands ===
53 // Sealed-enum validity predicate behaves correctly.
54 if nx_perlin_band_is_valid(NX_PERLIN_BAND_VOID) != 1 { return 50 }
55 if nx_perlin_band_is_valid(NX_PERLIN_BAND_SATURATED) != 1 { return 51 }
56 if nx_perlin_band_is_valid(99) != 0 { return 52 }
57 if nx_perlin_band_is_valid(0 - 1) != 0 { return 53 }
58 // Specific values map to expected bands.
59 if nx_perlin_classify(0) != NX_PERLIN_BAND_VOID { return 60 }
60 if nx_perlin_classify(50) != NX_PERLIN_BAND_VOID { return 61 }
61 if nx_perlin_classify(200) != NX_PERLIN_BAND_QUIET { return 62 }
62 if nx_perlin_classify(500) != NX_PERLIN_BAND_MODERATE { return 63 }
63 if nx_perlin_classify(700) != NX_PERLIN_BAND_STRONG { return 64 }
64 if nx_perlin_classify(1000) != NX_PERLIN_BAND_SATURATED { return 65 }
65 // Signed: negative values classify by magnitude.
66 if nx_perlin_classify(0 - 200) != NX_PERLIN_BAND_QUIET { return 66 }
67 if nx_perlin_classify(0 - 1000) != NX_PERLIN_BAND_SATURATED { return 67 }
68
69 // === Test 8: 1D noise also returns 0 at integer cells ===
70 let n_1d: nx_int = nx_perlin_1d(s_a, 0)
71 if n_1d != 0 { return 70 }
72 let n_1d_mid: nx_int = nx_perlin_1d(s_a, 512)
73 if n_1d_mid < (0 - 1024) { return 71 }
74 if n_1d_mid > 1024 { return 72 }
75
76 return 0
77}