diff --git a/fix16.tal b/fix16.tal index 2b19806..e468183 100644 --- a/fix16.tal +++ b/fix16.tal @@ -117,7 +117,7 @@ &<100 DUP #0a LTH ,&<10 JCN &>=10 #0a DIVk DUP x16-emit-dec-digit MUL SUB &<10 x16-emit-dec-digit - LIT '. #18 DEO + LIT ". #18 DEO ( emit fractional part ) #00 SWP ( lo* ) #000a MUL2 #0100 DIV2k DUP2 NIP x16-emit-dec-digit MUL2 SUB2 diff --git a/test-fix16.py b/test-fix16.py index 814aeb2..c47d3ca 100644 --- a/test-fix16.py +++ b/test-fix16.py @@ -1,33 +1,53 @@ #!/usr/bin/python -from math import floor, log +from math import floor, log, sin, cos, tan, copysign from os import environ from random import randint from subprocess import Popen, PIPE, run +def tosigned(x): + return x if x < 32768 else x - 65536 + u8 = {'sz': 1 << 8, 'fmt': b'%02x'} u16 = {'sz': 1 << 16, 'fmt': b'%04x'} z16 = {'sz': 1 << 16, 'fmt': b'%04x'} +p16 = {'sz': 1 << 16, 'fmt': b'%04x'} +t16 = {'sz': 1 << 16, 'fmt': b'%04x'} def eq(got, expected): return got == expected def booleq(got, expected): return bool(got) == bool(expected) -def releq(got, expected): +def releq(got0, expected0): + got, expected = tosigned(got0), tosigned(expected0) if (expected - 1) <= got and got <= (expected + 1): return True else: error = abs(got - expected) / (abs(expected) + 0.001) return error < 0.01 +def abseq(got0, expected0): + got, expected = tosigned(got0), tosigned(expected0) + if (expected - 10) <= got and got <= (expected + 10): + return True + else: + return False +def taneq(got0, expected0): + got, expected = tosigned(got0), tosigned(expected0) + if (expected - 1) <= got and got <= (expected + 1): + return True + else: + error = abs(got - expected) / (abs(expected) + 0.001) + return error < 0.1 def testcase(p, sym, args, out, f, eq): vals = [] for name, g in args: val = randint(0, g['sz'] - 1) - while val == 0 and g is z16: + while ((val == 0 and (g is z16 or g is p16)) or + (val >= 0x8000 and g is p16) or + (g is t16 and ((val >= 804) or ((val % 804) == 402)))): val = randint(0, g['sz'] - 1) vals.append((name, g, val)) - #vals = [(name, g, randint(0, g['sz'] - 1)) for (name, g) in args] p.stdin.write(sym) for _, g, x in vals: p.stdin.write(g['fmt'] % x) @@ -85,8 +105,6 @@ def x16_eq(x, y): return x == y def x16_ne(x, y): return x != y -def tosigned(x): - return x if x < 32768 else x - 65536 def x16_lt(x, y): return int(tosigned(x) < tosigned(y)) def x16_gt(x, y): @@ -95,9 +113,22 @@ def x16_lteq(x, y): return int(tosigned(x) <= tosigned(y)) def x16_gteq(x, y): return int(tosigned(x) >= tosigned(y)) +def x16_sin(x): + z = round(sin(x / 256) * 256) + return z if z >= 0 else 65536 + z +def x16_cos(x): + z = round(cos(x / 256) * 256) + return z if z >= 0 else 65536 + z +def x16_tan(x): + z0 = round(tan(x / 256) * 256) + z = min(max(z0, -0x7fff), 0x7fff) + return z if z >= 0 else 65536 + z +def x16_log(x): + z = round(log(x / 256) * 256) + return z if z >= 0 else 65536 + z def main(): - trials = 100000 + trials = 10000 run(['uxnasm', 'test-fix16.tal', 'run.rom']) p = pipe() test(p, trials, b'+', [('x', u16), ('y', u16)], u16, x16_add) @@ -114,6 +145,10 @@ def main(): test(p, trials, b'>', [('x', u16), ('y', u16)], u8, x16_gt) test(p, trials, b'{', [('x', u16), ('y', u16)], u8, x16_lteq) test(p, trials, b'}', [('x', u16), ('y', u16)], u8, x16_gteq) + test(p, trials, b's', [('x', p16)], u16, x16_sin, eq=abseq) + test(p, trials, b'c', [('x', p16)], u16, x16_cos, eq=abseq) + test(p, trials, b't', [('x', t16)], u16, x16_tan, eq=taneq) + test(p, trials, b'l', [('x', p16)], u16, x16_log, eq=releq) p.stdin.write(b'\n\n') p.stdin.flush() p.stdin.close()