Skip to content

Commit

Permalink
Merge pull request #1 from orsinium-labs/wasm-asm
Browse files Browse the repository at this point in the history
Optimized code for wasm
  • Loading branch information
orsinium authored May 21, 2024
2 parents 74ff2b4 + c7287f2 commit 4d1ee2e
Show file tree
Hide file tree
Showing 10 changed files with 115 additions and 19 deletions.
17 changes: 9 additions & 8 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,16 +28,17 @@ Here is a comparison of WebAssembly binary size (built with TinyGo) when using t

| function | tinymath | stdlib | ratio |
| ------------ | --------:| ------:| -----:|
| atan | 106 | 367 | 28% |
| atan2 | 167 | 782 | 21% |
| exp | 535 | 2722 | 19% |
| fract | 206 | 154 | 133% |
| hypot | 94 | 203 | 46% |
| exp | 463 | 2722 | 17% |
| fract | 166 | 154 | 107% |
| hypot | 67 | 203 | 33% |
| ln | 196 | 4892 | 4% |
| powf | 859 | 9167 | 9% |
| powf | 701 | 9167 | 7% |
| round | 129 | 171 | 75% |
| sin | 198 | 1237 | 16% |
| trunc | 136 | 57 | 238% |
| sin | 125 | 1237 | 10% |
| sqrt | 57 | 57 | 100% |
| tan | 138 | 1137 | 12% |
| trunc | 57 | 57 | 100% |

To reproduce: `python3 size_bench.py`

The two functions that are bigger in tinymath (but still small!) are the ones that have an optimized wasm-specific assembly in the standard library implementation. We're working on adding such assembly code on our side as well.
13 changes: 13 additions & 0 deletions arch_nowasm.go
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
//go:build !tinygo.wasm

package tinymath

// Functions that can be optimized for wasm
Expand All @@ -16,6 +18,17 @@ func Floor(self float32) float32 {
return float32(res)
}

// Approximates the square root of a number with an average deviation of ~5%.
//
// Returns [`NAN`] if `self` is a negative number.
func Sqrt(self float32) float32 {
if self >= 0.0 {
return FromBits((ToBits(self) + 0x3f80_0000) >> 1)
} else {
return NaN
}
}

// Returns the integer part of a number.
func Trunc(self float32) float32 {
const MANTISSA_MASK = 0b0000_0000_0111_1111_1111_1111_1111_1111
Expand Down
33 changes: 33 additions & 0 deletions arch_tinygo.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
//go:build tinygo.wasm

package tinymath

// Functions in this file are inlined and optimized by TinyGo compiler.
// The result is a single wasm instruction.
//
// https://github.com/tinygo-org/tinygo/blob/6384ecace093df2d0b93915886954abfc4ecfe01/compiler/intrinsics.go#L114C5-L114C22

import (
"math"
"math/bits"
)

func Ceil(self float32) float32 {
return float32(math.Ceil(float64(self)))
}

func Floor(self float32) float32 {
return float32(math.Floor(float64(self)))
}

func Sqrt(self float32) float32 {
return float32(math.Sqrt(float64(self)))
}

func Trunc(self float32) float32 {
return float32(math.Trunc(float64(self)))
}

func leadingZeros(x uint32) uint32 {
return uint32(bits.LeadingZeros32(x))
}
10 changes: 10 additions & 0 deletions size_bench/std/atan.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
//go:build !none || atan

package main

import "math"

//go:export f
func Atan(a float64) float64 {
return math.Atan(a)
}
10 changes: 10 additions & 0 deletions size_bench/std/sqrt.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
//go:build !none || sqrt

package main

import "math"

//go:export f
func Sqrt(x float64) float64 {
return math.Sqrt(x)
}
10 changes: 10 additions & 0 deletions size_bench/std/tan.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
//go:build !none || tan

package main

import "math"

//go:export f
func Tan(x float64) float64 {
return math.Tan(x)
}
10 changes: 10 additions & 0 deletions size_bench/tiny/atan.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
//go:build !none || atan

package main

import "github.com/orsinium-labs/tinymath"

//go:export f
func Atan(a float32) float32 {
return tinymath.Atan(a)
}
10 changes: 10 additions & 0 deletions size_bench/tiny/sqrt.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
//go:build !none || sqrt

package main

import "github.com/orsinium-labs/tinymath"

//go:export f
func Sqrt(x float32) float32 {
return tinymath.Sqrt(x)
}
10 changes: 10 additions & 0 deletions size_bench/tiny/tan.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
//go:build !none || tan

package main

import "github.com/orsinium-labs/tinymath"

//go:export f
func Tan(x float32) float32 {
return tinymath.Tan(x)
}
11 changes: 0 additions & 11 deletions tinymath.go
Original file line number Diff line number Diff line change
Expand Up @@ -349,17 +349,6 @@ func Sign(self float32) float32 {
}
}

// Approximates the square root of a number with an average deviation of ~5%.
//
// Returns [`NAN`] if `self` is a negative number.
func Sqrt(self float32) float32 {
if self >= 0.0 {
return FromBits((ToBits(self) + 0x3f80_0000) >> 1)
} else {
return NaN
}
}

func extractExponentBits(self float32) uint32 {
return (ToBits(self) & expMask) >> mantissaBits
}
Expand Down

0 comments on commit 4d1ee2e

Please sign in to comment.