MCPcopy Create free account
hub / github.com/defold/defold / log2_est

Method log2_est

engine/dlib/src/basis/encoder/cppspmd_math.h:65–121  ·  view source on GitHub ↗

See https://tech.ebayinc.com/engineering/fast-approximate-logarithms-part-iii-the-formulas/

Source from the content-addressed store, hash-verified

63
64// See https://tech.ebayinc.com/engineering/fast-approximate-logarithms-part-iii-the-formulas/
65inline vfloat spmd_kernel::log2_est(vfloat v)
66{
67 vfloat signif, fexp;
68
69 // Just clamp to a very small value, instead of checking for invalid inputs.
70 vfloat x = max(v, 2.2e-38f);
71
72 /*
73 * Assume IEEE representation, which is sgn(1):exp(8):frac(23)
74 * representing (1+frac)*2^(exp-127). Call 1+frac the significand
75 */
76
77 // get exponent
78 vint ux1_i = cast_vfloat_to_vint(x);
79
80 vint exp = VUINT_SHIFT_RIGHT(ux1_i & 0x7F800000, 23);
81
82 // actual exponent is exp-127, will subtract 127 later
83
84 vint ux2_i;
85 vfloat ux2_f;
86
87 vint greater = ux1_i & 0x00400000; // true if signif > 1.5
88 SPMD_SIF(greater != 0)
89 {
90 // signif >= 1.5 so need to divide by 2. Accomplish this by stuffing exp = 126 which corresponds to an exponent of -1
91 store_all(ux2_i, (ux1_i & 0x007FFFFF) | 0x3f000000);
92
93 store_all(ux2_f, cast_vint_to_vfloat(ux2_i));
94
95 // 126 instead of 127 compensates for division by 2
96 store_all(fexp, vfloat(exp - 126));
97 }
98 SPMD_SELSE(greater != 0)
99 {
100 // get signif by stuffing exp = 127 which corresponds to an exponent of 0
101 store(ux2_i, (ux1_i & 0x007FFFFF) | 0x3f800000);
102
103 store(ux2_f, cast_vint_to_vfloat(ux2_i));
104
105 store(fexp, vfloat(exp - 127));
106 }
107 SPMD_SENDIF
108
109 store_all(signif, ux2_f);
110 store_all(signif, signif - 1.0f);
111
112 const float a = 0.1501692f, b = 3.4226132f, c = 5.0225057f, d = 4.1130283f, e = 3.4813372f;
113
114 vfloat xm1 = signif;
115 vfloat xm1sqr = xm1 * xm1;
116
117 return fexp + ((a * (xm1sqr * xm1) + b * xm1sqr + c * xm1) / (xm1sqr + d * xm1 + e));
118
119 // fma lowers accuracy for SSE4.1 - no idea why (compiler reordering?)
120 //return fexp + ((vfma(a, (xm1sqr * xm1), vfma(b, xm1sqr, c * xm1))) / (xm1sqr + vfma(d, xm1, e)));
121}
122

Callers

nothing calls this directly

Calls 4

cast_vfloat_to_vintFunction · 0.85
cast_vint_to_vfloatFunction · 0.85
vfloatClass · 0.85
maxFunction · 0.70

Tested by

no test coverage detected