Skip to content

Commit

Permalink
Implement missing math functions in LLVM backend
Browse files Browse the repository at this point in the history
Implement cos, sin, atan, tan, log, log1p, _pi, exp & pow.
All functions use the LLVM intrinsics except tan & atan. They do not exist in the version of LLVM we are using.

Fixes #608
  • Loading branch information
mattisboeckle committed Jan 10, 2025
1 parent 3cbf9cf commit b464321
Show file tree
Hide file tree
Showing 4 changed files with 38 additions and 0 deletions.
9 changes: 9 additions & 0 deletions examples/pos/math.check
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
1
0
0
0
1
32
0
0
1
11 changes: 11 additions & 0 deletions examples/pos/math.effekt
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
def main() = {
println(cos(0.0))
println(sin(0.0))
println(log(1.0))
println(log1p(0.0))
println(exp(0.0))
println(pow(2.0, 5.0))
println(tan(0.0))
println(atan(0.0))
println(sin(PI / 2.0))
}
9 changes: 9 additions & 0 deletions libraries/common/effekt.effekt
Original file line number Diff line number Diff line change
Expand Up @@ -344,21 +344,25 @@ extern pure def cos(x: Double): Double =
js "Math.cos(${x})"
chez "(cos ${x})"
vm "effekt::cos(Double)"
llvm "%z = call %Double @llvm.cos.f64(double ${x}) ret %Double %z"

extern pure def sin(x: Double): Double =
js "Math.sin(${x})"
chez "(sin ${x})"
vm "effekt::sin(Double)"
llvm "%z = call %Double @llvm.sin.f64(double ${x}) ret %Double %z"

extern pure def atan(x: Double): Double =
js "Math.atan(${x})"
chez "(atan ${x})"
vm "effekt::atan(Double)"
llvm "%z = call %Double @atan(double ${x}) ret %Double %z"

extern pure def tan(x: Double): Double =
js "Math.tan(${x})"
chez "(tan ${x})"
vm "effekt::tan(Double)"
llvm "%z = call %Double @tan(double ${x}) ret %Double %z"

extern pure def sqrt(x: Double): Double =
js "Math.sqrt(${x})"
Expand All @@ -381,15 +385,18 @@ extern pure def log(x: Double): Double =
js "Math.log(${x})"
chez "(log ${x})"
vm "effekt::log(Double)"
llvm "%z = call %Double @llvm.log.f64(double ${x}) ret %Double %z"

extern pure def log1p(x: Double): Double =
js "Math.log1p(${x})"
chez "(log (+ ${x} 1))"
llvm "%z = call %Double @log1p(double ${x}) ret %Double %z"

extern pure def exp(x: Double): Double =
js "Math.exp(${x})"
chez "(exp ${x})"
vm "effekt::exp(Double)"
llvm "%z = call %Double @llvm.exp.f64(double ${x}) ret %Double %z"

def pow(base: Double, exponent: Int): Double = {
def loop(base: Double, exponent: Int, acc: Double): Double = {
Expand All @@ -408,12 +415,14 @@ extern pure def pow(base: Double, exponent: Double): Double =
js "Math.pow(${base}, ${exponent})"
chez "(expt ${base} ${exponent})"
vm "effekt::pow(Double, Double)"
llvm "%z = call %Double @llvm.pow.f64(double ${base}, double ${exponent}) ret %Double %z"

// since we do not have "extern val", yet
extern pure def _pi(): Double =
js "Math.PI"
chez "(* 4 (atan 1))"
vm "effekt::pi()"
llvm "ret double 3.14159265358979323846264338327950288419716939937510582097494459"

val PI: Double = _pi()

Expand Down
9 changes: 9 additions & 0 deletions libraries/llvm/rts.ll
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,15 @@ declare double @llvm.sqrt.f64(double)
declare double @llvm.round.f64(double)
declare double @llvm.ceil.f64(double)
declare double @llvm.floor.f64(double)
declare double @llvm.cos.f64(double)
declare double @llvm.sin.f64(double)
declare double @llvm.log.f64(double)
declare double @llvm.exp.f64(double)
declare double @llvm.pow.f64(double, double)
declare double @log1p(double)
; Intrinsic versions of the following two only added in LLVM 19
declare double @atan(double)
declare double @tan(double)
declare void @print(i64)
declare void @exit(i64)
declare void @llvm.assume(i1)
Expand Down

0 comments on commit b464321

Please sign in to comment.