Home | History | Annotate | Download | only in unit
      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 
     10 TEST_BEGIN(test_smoothstep_integral)
     11 {
     12 	uint64_t sum, min, max;
     13 	unsigned i;
     14 
     15 	/*
     16 	 * The integral of smoothstep in the [0..1] range equals 1/2.  Verify
     17 	 * that the fixed point representation's integral is no more than
     18 	 * rounding error distant from 1/2.  Regarding rounding, each table
     19 	 * element is rounded down to the nearest fixed point value, so the
     20 	 * integral may be off by as much as SMOOTHSTEP_NSTEPS ulps.
     21 	 */
     22 	sum = 0;
     23 	for (i = 0; i < SMOOTHSTEP_NSTEPS; i++)
     24 		sum += smoothstep_tab[i];
     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 
     39 TEST_BEGIN(test_smoothstep_monotonic)
     40 {
     41 	uint64_t prev_h;
     42 	unsigned i;
     43 
     44 	/*
     45 	 * The smoothstep function is monotonic in [0..1], i.e. its slope is
     46 	 * non-negative.  In practice we want to parametrize table generation
     47 	 * such that piecewise slope is greater than zero, but do not require
     48 	 * that here.
     49 	 */
     50 	prev_h = 0;
     51 	for (i = 0; i < SMOOTHSTEP_NSTEPS; i++) {
     52 		uint64_t h = smoothstep_tab[i];
     53 		assert_u64_ge(h, prev_h, "Piecewise non-monotonic, i=%u", i);
     54 		prev_h = h;
     55 	}
     56 	assert_u64_eq(smoothstep_tab[SMOOTHSTEP_NSTEPS-1],
     57 	    (KQU(1) << SMOOTHSTEP_BFP), "Last step must equal 1");
     58 }
     59 TEST_END
     60 
     61 TEST_BEGIN(test_smoothstep_slope)
     62 {
     63 	uint64_t prev_h, prev_delta;
     64 	unsigned i;
     65 
     66 	/*
     67 	 * The smoothstep slope strictly increases until x=0.5, and then
     68 	 * strictly decreases until x=1.0.  Verify the slightly weaker
     69 	 * requirement of monotonicity, so that inadequate table precision does
     70 	 * not cause false test failures.
     71 	 */
     72 	prev_h = 0;
     73 	prev_delta = 0;
     74 	for (i = 0; i < SMOOTHSTEP_NSTEPS / 2 + SMOOTHSTEP_NSTEPS % 2; i++) {
     75 		uint64_t h = smoothstep_tab[i];
     76 		uint64_t delta = h - prev_h;
     77 		assert_u64_ge(delta, prev_delta,
     78 		    "Slope must monotonically increase in 0.0 <= x <= 0.5, "
     79 		    "i=%u", i);
     80 		prev_h = h;
     81 		prev_delta = delta;
     82 	}
     83 
     84 	prev_h = KQU(1) << SMOOTHSTEP_BFP;
     85 	prev_delta = 0;
     86 	for (i = SMOOTHSTEP_NSTEPS-1; i >= SMOOTHSTEP_NSTEPS / 2; i--) {
     87 		uint64_t h = smoothstep_tab[i];
     88 		uint64_t delta = prev_h - h;
     89 		assert_u64_ge(delta, prev_delta,
     90 		    "Slope must monotonically decrease in 0.5 <= x <= 1.0, "
     91 		    "i=%u", i);
     92 		prev_h = h;
     93 		prev_delta = delta;
     94 	}
     95 }
     96 TEST_END
     97 
     98 int
     99 main(void)
    100 {
    101 
    102 	return (test(
    103 	    test_smoothstep_integral,
    104 	    test_smoothstep_monotonic,
    105 	    test_smoothstep_slope));
    106 }
    107