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