Last active
March 16, 2023 19:12
-
-
Save SMT50001/9998844c15a6e5ade5aa43dfa78ba592 to your computer and use it in GitHub Desktop.
Initial draft of fixed-point math library
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import math | |
export math | |
{.push inline.} | |
when defined(release) and not defined(vfixpExplicitChecks): | |
{.push noinit, checks: off.} | |
template genFixpType*(gname, btyp: untyped, tsize, tfraction: int, upscaleto: typedesc) = | |
when tsize notin [16, 32]: | |
{.error: "Unsupported variable size".} | |
when tfraction >= tsize: | |
{.error: "Fraction is too big".} | |
type `btyp tsize F tfraction` * {.inject.} = distinct `gname tsize` | |
const | |
typeInteger = tsize - tfraction | |
typeFraction = tfraction | |
proc `+`*(x, y: `btyp tsize F tfraction`): `btyp tsize F tfraction` {.borrow.} | |
proc `-`*(x, y: `btyp tsize F tfraction`): `btyp tsize F tfraction` {.borrow.} | |
proc `==`*(x, y: `btyp tsize F tfraction`): bool {.borrow.} | |
proc `<`*(x, y: `btyp tsize F tfraction`): bool {.borrow.} | |
proc `<=`*(x, y: `btyp tsize F tfraction`): bool {.borrow.} | |
proc `*`*(x, y: `btyp tsize F tfraction`): `btyp tsize F tfraction` = | |
when low(`gname tsize`) < 0 : | |
let product = upscaleto(x) * upscaleto( y) | |
`btyp tsize F tfraction`((abs(product) shr typeFraction) * sgn(product)) | |
else: | |
`btyp tsize F tfraction`((upscaleto(x) * upscaleto( y)) shr typeFraction) | |
proc `div`*(x, y: `btyp tsize F tfraction`): `btyp tsize F tfraction` = | |
when low(`gname tsize`) < 0 : | |
`btyp tsize F tfraction`((abs(upscaleto(x)) shl typeFraction) div upscaleto(y) * sgn(upscaleto(x))) | |
else: | |
`btyp tsize F tfraction`((upscaleto(x) shl typeFraction) div upscaleto(y)) | |
proc `/`*(x, y: `btyp tsize F tfraction`): `btyp tsize F tfraction` = x div y | |
proc `to btyp tsize`*(x: `btyp tsize F tfraction`): `gname tsize` = | |
`gname tsize`(x) div (1 shl typeFraction) | |
proc toFloat*(x: `btyp tsize F tfraction`): float = | |
float(x) / float(1 shl typeFraction) | |
proc `to btyp tsize F tfraction`*[T: SomeNumber](x: T): `btyp tsize F tfraction` = | |
`btyp tsize F tfraction`(x * T(1 shl typeFraction)) | |
proc `gname tsize f tfraction`*(integer: `gname tsize`, fractional: `uint tsize`): `btyp tsize F tfraction` = | |
# doesn't work yet | |
when not defined(release): | |
assert(integer*gname(sgn(integer)) < gname(1 shl typeInteger)) | |
assert(fractional < `uint tsize`(1 shl typeFraction)) | |
let | |
one = `gname tsize`(1 shl typeFraction) | |
frac = (`gname tsize`(fractional)) | |
var fracSetBits = tsize | |
while frac shr (fracSetBits - 1) != 1: dec fracSetBits | |
`btyp tsize F tfraction` (`gname tsize`(integer) * one + frac shl (typeFraction - fracSetBits)) | |
proc sqrt*(x: `btyp tsize F tfraction`): `btyp tsize F tfraction` = | |
# doesn't work yet | |
when (not defined(release)) and (low(`gname tsize`) < 0) : | |
assert( `gname tsize`(x) > 0) | |
var | |
temp: `gname tsize` | |
rslt: `gname tsize` | |
divisor: `gname tsize` = `gname tsize`(x) | |
rslt = `gname tsize`(x) | |
while true: | |
temp = `gname tsize`(x) div divisor + divisor | |
divisor = temp shr 1 | |
divisor += temp and 1 | |
if rslt > divisor: | |
rslt = divisor | |
else: | |
result = `btyp tsize F tfraction`(rslt) | |
break | |
proc `$`*(x: `btyp tsize F tfraction`): string = | |
let | |
ntg = `gname tsize`(x) div gname(2^typeFraction) | |
fra = `gname tsize`(x) shl typeInteger shr typeInteger | |
one = 1'u64 shl typeFraction | |
$ntg & "." & $(uint64(fra) * 10000000000'u64 div one ) | |
genFixpType(int, Int, 32, 16, int64) | |
genFixpType(uint, Uint, 32, 16, uint64) | |
genFixpType(int, Int, 32, 8, int64) | |
genFixpType(uint, Uint, 32, 8, uint64) | |
when isMainModule: | |
echo $(uint32f8(12, 5) + uint32f8(4, 1)) | |
echo $(toUint32F8(12.5) + toUint32F8(4.0)) | |
when defined(release) and not defined(vfixpExplicitChecks): | |
{.pop.} | |
{.pop.} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment