Created
May 6, 2015 20:35
-
-
Save apense/d7afe800ecb32b877059 to your computer and use it in GitHub Desktop.
Doing 128-bit math in Nim
This file contains 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
## NOTICE: I have no idea how this works on most systems. it will eat your family | |
# these probably don't work right | |
{.emit: """#ifndef __float128 | |
#define __float128 long double | |
#define __int128 long long | |
#endif""".} | |
type float128* {.importc: "__float128", nodecl.} = clongdouble | |
type int128* {.importc: "__int128", nodecl.} = clonglong | |
# OK so technically this is unsigned, but it's SO much easier to declare it as `clonglong`, especially | |
# since everything is done by the compiler. No worrying about the unsigned stuff. It's ugly enough as-is. | |
type uint128* {.importc: "unsigned __int128", nodecl.} = clonglong | |
proc `+`*(i: uint128, i2: SomeNumber): uint128 = | |
## Honestly, this is too easy, but it seems nice. let's let the compiler do the hard stuff | |
{.emit: "result = `i` + `i2`;".} # do i need these ticks? | |
# stolen from http://stackoverflow.com/questions/11656241/how-to-print-uint128-t-number-using-gcc | |
# probably creates garbage with signed int128. totally unsafe | |
{.emit: """ | |
void uint128_to_str_iter(unsigned __int128 n, char *out, int firstiter) { | |
static int offset = 0; | |
if(firstiter) { | |
offset = 0; | |
} | |
if(n == 0) { | |
return; | |
} | |
uint128_to_str_iter(n/10,out,0); | |
out[offset++]=n%10+0x30; | |
} | |
""".} | |
proc cstr(u: uint128): cstring = | |
## the emitted function works with `char *`, which Nim treats as `cstring` | |
{.emit: """ | |
result = calloc(sizeof(char),40); | |
uint128_to_str_iter(`u`, result, 1); | |
""".} | |
proc `$`*(u: uint128): string = | |
## convert our `cstring` into a `string` | |
result = $cstr(u) | |
var ff: float128 | |
var ii, jj: uint128 | |
ii = 0 | |
ii = ii - 1 | |
echo ii # 340282366920938463463374607431768211455 | |
import math # test against actual value | |
echo pow(2,128)-1 # 3.402823669209385e+038 | |
# so, we know we're getting the right results. it's kind of nice to see this in its entirety |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment