Skip to content

Instantly share code, notes, and snippets.

@going-digital
Last active June 1, 2021 15:39
Show Gist options
  • Save going-digital/4df9c953077ec85d26e031bf813ac4d2 to your computer and use it in GitHub Desktop.
Save going-digital/4df9c953077ec85d26e031bf813ac4d2 to your computer and use it in GitHub Desktop.
exp2 in WebAssembly
;; Calculate exp2(x) = 2**x natively in WebAssembly.
;; Compiles to 49 bytes of WebAssembly code
(module
(func $exp2 (param $x f32) (result f32)
(local $xf f32)
;; Parse result as a float bitfield
(f32.reinterpret_i32
(i32.add
;; Compute mantissa of result
;; Compute polynomial to cover f(x) = 2**23 * ( 2^(x) - 1 ) where 0 <= x < 1
;; This computes the result mantissa.
;;
;; These coefficients were based on Excel solver. I initially used Taylor series, but the
;; Excel solver gives better accuracy across whole range as it spreads the error better.
;; Errors in musical cents (1 octave = 12 semitones = 1200 cents). Human ear can resolve about 1 cent.
;; 2 terms: 22743533, 5603139 : 16 cents error
;; 3 terms: 642218, 1911078, 5832153 : 0.6 cents error
;; 4 terms: 120819, 421063, 2035288, 5811427 : 0.05 cents error
(i32.trunc_f32_u
(f32.mul
(f32.add
(f32.const 5832153)
(f32.mul
(f32.add
(f32.const 1911078)
(f32.mul
(f32.const 642218)
(local.tee $xf
;; Compute xf = fract(x)
(f32.sub
(local.get $x)
(f32.floor
(local.get $x)
)
)
)
)
)
(local.get $xf)
)
)
(local.get $xf)
)
)
;; Compute exponent of result
(i32.shl
(i32.add
(i32.trunc_f32_s
(f32.floor
(local.get $x)
)
)
(i32.const 127)
)
(i32.const 23)
)
)
)
)
(export "exp2" (func $exp2))
)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment