• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 #include "test/jemalloc_test.h"
2 
3 static const uint64_t smoothstep_tab[] = {
4 #define STEP(step, h, x, y)			\
5 	h,
6 	SMOOTHSTEP
7 #undef STEP
8 };
9 
TEST_BEGIN(test_smoothstep_integral)10 TEST_BEGIN(test_smoothstep_integral) {
11 	uint64_t sum, min, max;
12 	unsigned i;
13 
14 	/*
15 	 * The integral of smoothstep in the [0..1] range equals 1/2.  Verify
16 	 * that the fixed point representation's integral is no more than
17 	 * rounding error distant from 1/2.  Regarding rounding, each table
18 	 * element is rounded down to the nearest fixed point value, so the
19 	 * integral may be off by as much as SMOOTHSTEP_NSTEPS ulps.
20 	 */
21 	sum = 0;
22 	for (i = 0; i < SMOOTHSTEP_NSTEPS; i++) {
23 		sum += smoothstep_tab[i];
24 	}
25 
26 	max = (KQU(1) << (SMOOTHSTEP_BFP-1)) * (SMOOTHSTEP_NSTEPS+1);
27 	min = max - SMOOTHSTEP_NSTEPS;
28 
29 	assert_u64_ge(sum, min,
30 	    "Integral too small, even accounting for truncation");
31 	assert_u64_le(sum, max, "Integral exceeds 1/2");
32 	if (false) {
33 		malloc_printf("%"FMTu64" ulps under 1/2 (limit %d)\n",
34 		    max - sum, SMOOTHSTEP_NSTEPS);
35 	}
36 }
37 TEST_END
38 
TEST_BEGIN(test_smoothstep_monotonic)39 TEST_BEGIN(test_smoothstep_monotonic) {
40 	uint64_t prev_h;
41 	unsigned i;
42 
43 	/*
44 	 * The smoothstep function is monotonic in [0..1], i.e. its slope is
45 	 * non-negative.  In practice we want to parametrize table generation
46 	 * such that piecewise slope is greater than zero, but do not require
47 	 * that here.
48 	 */
49 	prev_h = 0;
50 	for (i = 0; i < SMOOTHSTEP_NSTEPS; i++) {
51 		uint64_t h = smoothstep_tab[i];
52 		assert_u64_ge(h, prev_h, "Piecewise non-monotonic, i=%u", i);
53 		prev_h = h;
54 	}
55 	assert_u64_eq(smoothstep_tab[SMOOTHSTEP_NSTEPS-1],
56 	    (KQU(1) << SMOOTHSTEP_BFP), "Last step must equal 1");
57 }
58 TEST_END
59 
TEST_BEGIN(test_smoothstep_slope)60 TEST_BEGIN(test_smoothstep_slope) {
61 	uint64_t prev_h, prev_delta;
62 	unsigned i;
63 
64 	/*
65 	 * The smoothstep slope strictly increases until x=0.5, and then
66 	 * strictly decreases until x=1.0.  Verify the slightly weaker
67 	 * requirement of monotonicity, so that inadequate table precision does
68 	 * not cause false test failures.
69 	 */
70 	prev_h = 0;
71 	prev_delta = 0;
72 	for (i = 0; i < SMOOTHSTEP_NSTEPS / 2 + SMOOTHSTEP_NSTEPS % 2; i++) {
73 		uint64_t h = smoothstep_tab[i];
74 		uint64_t delta = h - prev_h;
75 		assert_u64_ge(delta, prev_delta,
76 		    "Slope must monotonically increase in 0.0 <= x <= 0.5, "
77 		    "i=%u", i);
78 		prev_h = h;
79 		prev_delta = delta;
80 	}
81 
82 	prev_h = KQU(1) << SMOOTHSTEP_BFP;
83 	prev_delta = 0;
84 	for (i = SMOOTHSTEP_NSTEPS-1; i >= SMOOTHSTEP_NSTEPS / 2; i--) {
85 		uint64_t h = smoothstep_tab[i];
86 		uint64_t delta = prev_h - h;
87 		assert_u64_ge(delta, prev_delta,
88 		    "Slope must monotonically decrease in 0.5 <= x <= 1.0, "
89 		    "i=%u", i);
90 		prev_h = h;
91 		prev_delta = delta;
92 	}
93 }
94 TEST_END
95 
96 int
main(void)97 main(void) {
98 	return test(
99 	    test_smoothstep_integral,
100 	    test_smoothstep_monotonic,
101 	    test_smoothstep_slope);
102 }
103