1#!/bin/sh
2#
3# Generate a discrete lookup table for a sigmoid function in the smoothstep
4# family (https://en.wikipedia.org/wiki/Smoothstep), where the lookup table
5# entries correspond to x in [1/nsteps, 2/nsteps, ..., nsteps/nsteps].  Encode
6# the entries using a binary fixed point representation.
7#
8# Usage: smoothstep.sh <variant> <nsteps> <bfp> <xprec> <yprec>
9#
10#        <variant> is in {smooth, smoother, smoothest}.
11#        <nsteps> must be greater than zero.
12#        <bfp> must be in [0..62]; reasonable values are roughly [10..30].
13#        <xprec> is x decimal precision.
14#        <yprec> is y decimal precision.
15
16#set -x
17
18cmd="sh smoothstep.sh $*"
19variant=$1
20nsteps=$2
21bfp=$3
22xprec=$4
23yprec=$5
24
25case "${variant}" in
26  smooth)
27    ;;
28  smoother)
29    ;;
30  smoothest)
31    ;;
32  *)
33    echo "Unsupported variant"
34    exit 1
35    ;;
36esac
37
38smooth() {
39  step=$1
40  y=`echo ${yprec} k ${step} ${nsteps} / sx _2 lx 3 ^ '*' 3 lx 2 ^ '*' + p | dc | tr -d '\\\\\n' | sed -e 's#^\.#0.#g'`
41  h=`echo ${yprec} k 2 ${bfp} ^ ${y} '*' p | dc | tr -d '\\\\\n' | sed -e 's#^\.#0.#g' | tr '.' ' ' | awk '{print $1}' `
42}
43
44smoother() {
45  step=$1
46  y=`echo ${yprec} k ${step} ${nsteps} / sx 6 lx 5 ^ '*' _15 lx 4 ^ '*' + 10 lx 3 ^ '*' + p | dc | tr -d '\\\\\n' | sed -e 's#^\.#0.#g'`
47  h=`echo ${yprec} k 2 ${bfp} ^ ${y} '*' p | dc | tr -d '\\\\\n' | sed -e 's#^\.#0.#g' | tr '.' ' ' | awk '{print $1}' `
48}
49
50smoothest() {
51  step=$1
52  y=`echo ${yprec} k ${step} ${nsteps} / sx _20 lx 7 ^ '*' 70 lx 6 ^ '*' + _84 lx 5 ^ '*' + 35 lx 4 ^ '*' + p | dc | tr -d '\\\\\n' | sed -e 's#^\.#0.#g'`
53  h=`echo ${yprec} k 2 ${bfp} ^ ${y} '*' p | dc | tr -d '\\\\\n' | sed -e 's#^\.#0.#g' | tr '.' ' ' | awk '{print $1}' `
54}
55
56cat <<EOF
57/*
58 * This file was generated by the following command:
59 *   $cmd
60 */
61/******************************************************************************/
62#ifdef JEMALLOC_H_TYPES
63
64/*
65 * This header defines a precomputed table based on the smoothstep family of
66 * sigmoidal curves (https://en.wikipedia.org/wiki/Smoothstep) that grow from 0
67 * to 1 in 0 <= x <= 1.  The table is stored as integer fixed point values so
68 * that floating point math can be avoided.
69 *
70 *                      3     2
71 *   smoothstep(x) = -2x  + 3x
72 *
73 *                       5      4      3
74 *   smootherstep(x) = 6x  - 15x  + 10x
75 *
76 *                          7      6      5      4
77 *   smootheststep(x) = -20x  + 70x  - 84x  + 35x
78 */
79
80#define	SMOOTHSTEP_VARIANT	"${variant}"
81#define	SMOOTHSTEP_NSTEPS	${nsteps}
82#define	SMOOTHSTEP_BFP		${bfp}
83#define	SMOOTHSTEP \\
84 /* STEP(step, h,                            x,     y) */ \\
85EOF
86
87s=1
88while [ $s -le $nsteps ] ; do
89  $variant ${s}
90  x=`echo ${xprec} k ${s} ${nsteps} / p | dc | tr -d '\\\\\n' | sed -e 's#^\.#0.#g'`
91  printf '    STEP(%4d, UINT64_C(0x%016x), %s, %s) \\\n' ${s} ${h} ${x} ${y}
92
93  s=$((s+1))
94done
95echo
96
97cat <<EOF
98#endif /* JEMALLOC_H_TYPES */
99/******************************************************************************/
100#ifdef JEMALLOC_H_STRUCTS
101
102
103#endif /* JEMALLOC_H_STRUCTS */
104/******************************************************************************/
105#ifdef JEMALLOC_H_EXTERNS
106
107
108#endif /* JEMALLOC_H_EXTERNS */
109/******************************************************************************/
110#ifdef JEMALLOC_H_INLINES
111
112
113#endif /* JEMALLOC_H_INLINES */
114/******************************************************************************/
115EOF
116