Skip to content

Commit

Permalink
add math_utils submodule containing power for static integers
Browse files Browse the repository at this point in the history
  • Loading branch information
Vindaar committed Nov 16, 2022
1 parent 2c4696f commit b56c174
Showing 1 changed file with 43 additions and 0 deletions.
43 changes: 43 additions & 0 deletions measuremancer/math_utils.nim
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
import std / macros

# Taken from `unchained`. This won't be exported from `measuremancer` though,
# rather we will `bind` in the scope in which we use this.
macro power*(x: typed, num: static int): untyped =
## general purpose power using `^` for integers, which works for any
## type by rewriting to a product of `*`.
##
## For the special cases of -1, 0, 1 we simply rewrite to the correct
## result. Negative powers are written as `1 / x^p`
if num == 0:
result = quote do:
`x` * typeof(`x`)(0.0)
elif num == 1:
result = x
elif num == -1:
## Assume that the type supports addition by a float!
result = quote do:
1.0 / `x`
else:
result = nnkInfix.newTree(ident"*")

proc addInfix(n, x: NimNode, num: int) =
var it = n
if num > 0:
it.add nnkInfix.newTree(ident"*")
it[1].addInfix(x, num - 1)
while it.len < 3:
it.add x

result.addInfix(x, abs(num) - 2)

# invert if num is negative
if num < -1:
## Assume that the type supports addition by a float!
result = quote do:
1.0 / (`result`)

import std/math
proc power*[T](x: T, num: SomeInteger): T =
if num > 0: result = x ^ num
elif num == 0: result = T(1)
else: result = T(1) / (x ^ abs(num))

0 comments on commit b56c174

Please sign in to comment.