Skip to content

Commit

Permalink
fix float formatting in picotron
Browse files Browse the repository at this point in the history
  • Loading branch information
thisismypassport committed Jun 6, 2024
1 parent b3d09f2 commit a601c8d
Show file tree
Hide file tree
Showing 6 changed files with 25 additions and 26 deletions.
41 changes: 19 additions & 22 deletions pico_output.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,8 @@ def float_str_add_1(str):
else:
return str[:-1] + chr(ord(str[-1]) + 1)

def float_str_minify(value, str, parse=float, keep_float=False):
ok = parse(str) == value
def float_str_minify(str, parse, cmpval, keep_float=False):
ok = parse(str) == cmpval

while "." in str:
ch = str[-1]
Expand All @@ -29,14 +29,14 @@ def float_str_minify(value, str, parse=float, keep_float=False):

nextvalue = str[:-1]
nextupvalue = float_str_add_1(nextvalue)
if parse(nextvalue) == value:
if parse(nextvalue) == cmpval:
str = nextvalue
ok = True
elif parse(nextupvalue) == value:
elif parse(nextupvalue) == cmpval:
str = nextupvalue
ok = True
else:
#check(ok, "float_str_minify error") # can this happen? YES!
check(ok, "float_str_minify error")
break

if str.startswith("0.") and str != "0.":
Expand Down Expand Up @@ -69,7 +69,7 @@ def format_fixnum(value, sign=None, base=None):

if base is None or base == 10:
numvalue = value / (1 << 16)
decvalue = float_str_minify(value, "%.6f" % numvalue, parse_fixnum)
decvalue = float_str_minify("%.6f" % numvalue, parse_fixnum, value)

if base:
minvalue = decvalue
Expand All @@ -94,11 +94,9 @@ def format_fixnum(value, sign=None, base=None):
def float_sign(value):
return "-" if float_is_negative(value) else ""

def float_hex(value, keep_float=False): # like value.hex(), except doesn't use an exponent
precision = 56
dotpos = precision // 4
hexval = hex(int(abs(value) * (1 << precision)))[2:].rjust(dotpos, '0')
result = f"0x{hexval[:-dotpos]}.{hexval[-dotpos:]}".rstrip("0")
def float_hex(value, hexdigits, keep_float=False): # like value.hex(), except doesn't use an exponent
hexval = hex(int(abs(value) * (1 << (hexdigits * 4))))[2:].rjust(hexdigits, '0')
result = f"0x{hexval[:-hexdigits]}.{hexval[-hexdigits:]}".rstrip("0")
if not keep_float:
result = result.rstrip(".")
if result in ("0x", "0x."):
Expand Down Expand Up @@ -129,7 +127,7 @@ def format_luanum(value, sign=None, base=None):
minvalue = decvalue

if not base:
if value == 0x8000000000000000:
if value >= 0x8000000000000000:
minvalue = hexvalue # else, it won't be parsed as an integer
else:
minvalue = hexvalue if len(hexvalue) < len(decvalue) else decvalue
Expand Down Expand Up @@ -166,15 +164,15 @@ def format_luanum(value, sign=None, base=None):
raise ValueError("nan not supported") # could output <inf>*0 in parens? (0/0 doesn't currently nan)

else:
few_digits = value == 0 or 1e-30 <= abs(value) <= 1e30 # to avoid needless computation (also avoids python denormal bug)
# TODO: this is very not optimal (but at least it's correct this time...)

if base is None or base == 16:
manvalue, expvalue = math.frexp(value)
manvalue *= 2; expvalue -= 1 # the 1..2 range is better for us
expvalue = f"{float_hex(manvalue)}p{expvalue}"
expvalue = f"{float_hex(manvalue, 56)}p{expvalue}"

if few_digits:
hexvalue = float_hex(value, keep_float=True)
if value == 0 or 1e-4 <= abs(value) <= 1e24:
hexvalue = float_hex(value, 88, keep_float=True)
hexvalue = expvalue if len(expvalue) < len(hexvalue) else hexvalue
else:
hexvalue = expvalue
Expand All @@ -183,13 +181,12 @@ def format_luanum(value, sign=None, base=None):
minvalue = hexvalue

if base is None or base == 10:
expvalue = int(math.log10(abs(value))) if value else 0
manvalue = value / math.pow(10, expvalue)
manvalue = float_str_minify(manvalue, "%.19f" % manvalue)
expvalue = f"{manvalue}e{expvalue}"
manstr, expstr = ("%.19e" % value).split("e")
expstr = f"e{int(expstr)}"
expvalue = float_str_minify(manstr, lambda v: float(v + expstr), value) + expstr

if few_digits:
decvalue = float_str_minify(value, "%.19f" % value, keep_float=True)
if value == 0 or 1e-3 <= abs(value) <= 1e21:
decvalue = float_str_minify("%.24f" % value, float, value, keep_float=True)
decvalue = expvalue if len(expvalue) < len(decvalue) else decvalue
else:
decvalue = expvalue
Expand Down
2 changes: 1 addition & 1 deletion shrinko8.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
from picotron_cart import write_cart64_compressed_size, write_cart64_version
import argparse

k_version = 'v1.2.2'
k_version = 'v1.2.2b'

def SplitBySeps(val):
return k_hint_split_re.split(val)
Expand Down
2 changes: 1 addition & 1 deletion test_compare/consttron.p64
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,7 @@ if (ERROR) ?1 + me
?-1
?0x8000000000000001
?0x8000000000000000
?-1e-323
?-9e-324
if (ERROR) ?"a" - "a"
-- mul
?48
Expand Down
2 changes: 1 addition & 1 deletion test_compare/consttronmin.p64
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ end if f then?1+l
end?-1
?0x8000000000000001
?0x8000000000000000
?-1e-323
?-9e-324
if f then?"a"-"a"
end?48
?5535
Expand Down
2 changes: 1 addition & 1 deletion test_compare/testtron.p64
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ picotron cartridge // www.picotron.net
version 3

:: main.lua
function n(n,e)return type(n)==type(e)and math.type(n)==math.type(e)and n==e end d=1 assert(true,1)assert(d==1,2)assert("\0 3\n Aa"=="\0 3\n Aa",2.5)assert("'\"\\'"==[['"\']],3)assert("\0€߿ࠀ￿𐀀��������������������������"=="\0€߿ࠀ￿𐀀��������������������������",3.5)assert([=[]]]=]=="]]",4)assert(not n(1234567890,1234567890.),5)assert(n(1e3,1e3)and n(0xab54a98ceb1f0800.,0xab54a98ceb1f0800.),5.1)assert(n(0x.12345,0x.12345),5.2)assert(0xf.f==0xf.f and 2.25==2.25,6)assert(12==12 and-1==-1,6.1)assert(1e333==1e333 and-1e333==-math.huge,6.2)u,c,e=1,{},3 u,c.n,c[1],e=e,2,4,u assert(u==3 and e==1 and c["n"]==2 and c[1]==4,8)do local n=u+1 assert(n==4,9)local n=n*2 assert(n==8,9.1)end assert(u==3,9.2)local n=_ENV assert(n==_ENV,10)local n assert(n==nil,11)function i()return 1,2,3 end local n,d,f,e,o,l=0,i()assert(n==0 and d==1 and f==2 and e==3 and o==nil and l==nil,12)m=0 do j=setmetatable({},{__close=function()m=33 end})local n<const>,e<close> =4,j assert(n==4,12.5)end assert(m==33,12.6)function i(...)return...end assert(i(1,2,3)==1,13)u,c=(i(1,2))assert(u==1 and c==nil,14)u,c=i(1,2),3 assert(u==1 and c==3,15)assert(pack(i(1,2,nil,3,nil,nil)).n==6,16)function i(...)return...,...,...end assert(pack(i(1,2,3)).n==5,17)for n=1,3 do assert(select(n,i(1,2,3))==1,18)end assert(select(4,i(1,2,3))==2,19)a=0 for n=5,1,-2 do a=1 assert(n==5 or n==3 or n==1,20)end assert(a==1,20.5)for n=5,1 do assert(false,21)end a=0 for n,e in ipairs{4,5}do assert(n==1 and e==4 or n==2 and e==5,22)a+=1 end assert(a==2,22.5)if a==2 then a+=1 else assert(false,23)end assert(a==3,23.5)if a==2 then assert(false,24)elseif a==3 then a+=1 else assert(false,24.5)end assert(a==4,24.6)if a==2 then assert(false,25)else a+=1 end assert(a==5,25.5)if a==2 then assert(false,25.8)else a+=1 end assert(a==6,25.9)if a==6 then a=0 a=1 else assert(false,26)end assert(a==1,27)if a==5 then assert(false,28)else a=2 end assert(a==2,29)r=1 while a>0 do a-=1 r*=2 end assert(r==4 and a==0,30)while r>0 do r-=1 a+=1 end assert(a==4 and r==0,31)while a>0 do a-=1 r+=1 if r==3 then break end end assert(a==1 and r==3,32)repeat a+=1 r-=1 until a==1 or a==3 assert(a==3 and r==1,33)function i()return end function p()end assert(i()==nil and pack(i()).n==0,34)assert(p()==nil and pack(p()).n==0,35)function b(...)return...end u={1,2,d=1,a=2,3,4,[12]=4,b(5,6,nil,8)}assert(u[1]==1 and u[2]==2 and u[3]==3 and u[4]==4 and u[5]==5 and u[6]==6,36)assert(u[7]==nil and u[8]==8 and u["d"]==1 and u.a==2 and u[12]==4,37)function b(...)return{...}end do local function n(...)return{...,d=3}end assert(#n(1,2)==1 and n(1,2).d==3,38)end assert(#b(1,2)==2,39)assert(1+4*5==21 and 498&255<<4==496,40)assert((1+4)*5==25 and(498&255)<<4==3872,41)assert(-2^4==-16 and(-2)^4==16,42)assert(1~=2 and 1~=2 or assert(false,43),43.1)poke8(4,-3)assert(2**4==-6,43.5)e={f=function(n)return n.z end,z=3}assert(e:f()==3 and e.f{z=4}==4,44)setmetatable(e,{__index=function(e,n)return n end})assert(e.t=="t",45)e.e=e function e.e.e.z(n)return n end assert(e.z(false)==false,46)function e.e.e:o(n)return self,n end assert(e:o(true)==e and select(2,e:o(true))==true,47)do n=1 do::n::n+=1 if n==4 then goto e end goto n end::e::assert(n==4,48)end do::e::do goto n assert(false,49)::n::end end n=0 for e,d in next,{5}do assert(e==1 and d==5,50)n+=1 end assert(n==1,50.5)do local n,_ENV=add,{assert=assert}n(_ENV,3)assert(_ENV[1]==3,51)end local function e(n)_ENV=n end local d=_ENV e{assert=assert,q=123}assert(q==123,52)e(d)function i()return 9,0,1 end function v(n)return n()end function y(n)return(n())end assert(pack(v(i)).n==3 and pack(y(i)).n==1,53)n=0x.004 if n<1 then if n==0 then n=123 end else n=321 end assert(n==0x.004,55)h=23\4 assert(h==5,55.1)h\=3 assert(h==1,55.2)do local n=1 function n()end end assert(nn==nil,56)n=1 repeat local n=2 until assert(n==2,57)do local n=2 repeat local e=3 until assert(n*e==6,57.5)end local function e()return 3 end assert(-e()+e()==0,58)local function d()return e end assert(d()()==3,59)local function n(e,d)local f=function()e+=1 return e end if d and d>0 then return f,n(e*2,d-1)else return f end end local f,o,l,a=n(10),n(20),n(30,1)assert(f()==11 and o()==21 and n(0)()==1 and l()==31 and a()==61 and f()==12 and o()==22 and n(0)()==1 and l()==32 and a()==62,60)function w(n)return n end assert(w"me"=="me"and w[[me]]=="me",61)z={l=function(e,n)return n end}assert(z:l"me"=="me"and#z:l{}==0,62)do while true do if 1==1 then::e::end goto n end::n::end local n=1 function _()return n end local n=2 assert(_()==1,63)local n=1 do function n1()return n end local n=2 assert(n1()==1,64)end do local n,e=1,2::n::assert(e==2,65)if n>1 then assert(s()==4 and e==2,66)goto d end local e=3 s=function()e+=1 return e end n+=1 goto n end::d::do local n=1::n::local e=n d=s s=function()e+=1 return e end n+=1 if n==3 then goto f else goto n end end::f::assert(s()==3 and s()==4 and d()==2 and s()==5 and d()==3,67)do goto n local n::n::end if 1==1 then end local n=0 function ord(e,d)assert(n==e,68)n+=1 return d end local n={}ord(0,n).x,ord(1,n).x=ord(2,2),ord(3,function()return 3 end)(ord(4,1),ord(5,1))assert(n.x==2,69)local f,n=1,2 assert(n==2,70)function e(e,n)assert(n==2,71)end e(1,2)k=0 g={10,20}function d()k+=1 return k end g[d()]+=1 assert(g[1]==11 and g[2]==20,72)n=0 n+=16 assert(n==16,73)assert([[[[]]=="[[",73.5)if 1==1 then if 2==3 then n=1 else n=2 end else n=3 end assert(n==2,74)if 1==2 then if 2==3 then n=1 else n=2 end else n=3 end assert(n==3,74.1)x=1 while x<10 do x+=1 if x==5 then break end end assert(x==5,75)if 1==2 then x=1 else if 1==3 then x=2 else x=3 end end assert(x==3,76)if 1==1 then if 2==2 then n=4 else n=5 end else n=6 end assert(n==4,77)do n=0 if 1==2 then end end n=123 assert(n==123,78)do local e,n=print print=function(e)n=e end?1
function n(n,e)return type(n)==type(e)and math.type(n)==math.type(e)and n==e end d=1 assert(true,1)assert(d==1,2)assert("\0 3\n Aa"=="\0 3\n Aa",2.5)assert("'\"\\'"==[['"\']],3)assert("\0€߿ࠀ￿𐀀��������������������������"=="\0€߿ࠀ￿𐀀��������������������������",3.5)assert([=[]]]=]=="]]",4)assert(not n(1234567890,1234567890.),5)assert(n(1e3,1e3)and n(0xab54a98ceb1f0800.,0xab54a98ceb1f0800.),5.1)assert(n(0x.12345,0x.12345),5.2)assert(0xf.f==0xf.f and 2.25==2.25,6)assert(12==12 and-1==-1,6.1)assert(1e333==1e333 and-1e333==-math.huge,6.2)assert(0x1.8d6c9578929dcp-920==tonum"1.7515328388329703e-277",7)assert(0x1.1013ebb6632cp-97==tonum"6.707235992995134e-30",7.1)u,c,e=1,{},3 u,c.n,c[1],e=e,2,4,u assert(u==3 and e==1 and c["n"]==2 and c[1]==4,8)do local n=u+1 assert(n==4,9)local n=n*2 assert(n==8,9.1)end assert(u==3,9.2)local n=_ENV assert(n==_ENV,10)local n assert(n==nil,11)function i()return 1,2,3 end local n,d,f,e,o,l=0,i()assert(n==0 and d==1 and f==2 and e==3 and o==nil and l==nil,12)m=0 do j=setmetatable({},{__close=function()m=33 end})local n<const>,e<close> =4,j assert(n==4,12.5)end assert(m==33,12.6)function i(...)return...end assert(i(1,2,3)==1,13)u,c=(i(1,2))assert(u==1 and c==nil,14)u,c=i(1,2),3 assert(u==1 and c==3,15)assert(pack(i(1,2,nil,3,nil,nil)).n==6,16)function i(...)return...,...,...end assert(pack(i(1,2,3)).n==5,17)for n=1,3 do assert(select(n,i(1,2,3))==1,18)end assert(select(4,i(1,2,3))==2,19)a=0 for n=5,1,-2 do a=1 assert(n==5 or n==3 or n==1,20)end assert(a==1,20.5)for n=5,1 do assert(false,21)end a=0 for n,e in ipairs{4,5}do assert(n==1 and e==4 or n==2 and e==5,22)a+=1 end assert(a==2,22.5)if a==2 then a+=1 else assert(false,23)end assert(a==3,23.5)if a==2 then assert(false,24)elseif a==3 then a+=1 else assert(false,24.5)end assert(a==4,24.6)if a==2 then assert(false,25)else a+=1 end assert(a==5,25.5)if a==2 then assert(false,25.8)else a+=1 end assert(a==6,25.9)if a==6 then a=0 a=1 else assert(false,26)end assert(a==1,27)if a==5 then assert(false,28)else a=2 end assert(a==2,29)r=1 while a>0 do a-=1 r*=2 end assert(r==4 and a==0,30)while r>0 do r-=1 a+=1 end assert(a==4 and r==0,31)while a>0 do a-=1 r+=1 if r==3 then break end end assert(a==1 and r==3,32)repeat a+=1 r-=1 until a==1 or a==3 assert(a==3 and r==1,33)function i()return end function p()end assert(i()==nil and pack(i()).n==0,34)assert(p()==nil and pack(p()).n==0,35)function b(...)return...end u={1,2,d=1,a=2,3,4,[12]=4,b(5,6,nil,8)}assert(u[1]==1 and u[2]==2 and u[3]==3 and u[4]==4 and u[5]==5 and u[6]==6,36)assert(u[7]==nil and u[8]==8 and u["d"]==1 and u.a==2 and u[12]==4,37)function b(...)return{...}end do local function n(...)return{...,d=3}end assert(#n(1,2)==1 and n(1,2).d==3,38)end assert(#b(1,2)==2,39)assert(1+4*5==21 and 498&255<<4==496,40)assert((1+4)*5==25 and(498&255)<<4==3872,41)assert(-2^4==-16 and(-2)^4==16,42)assert(1~=2 and 1~=2 or assert(false,43),43.1)poke8(4,-3)assert(2**4==-6,43.5)e={f=function(n)return n.z end,z=3}assert(e:f()==3 and e.f{z=4}==4,44)setmetatable(e,{__index=function(e,n)return n end})assert(e.t=="t",45)e.e=e function e.e.e.z(n)return n end assert(e.z(false)==false,46)function e.e.e:o(n)return self,n end assert(e:o(true)==e and select(2,e:o(true))==true,47)do n=1 do::n::n+=1 if n==4 then goto e end goto n end::e::assert(n==4,48)end do::e::do goto n assert(false,49)::n::end end n=0 for e,d in next,{5}do assert(e==1 and d==5,50)n+=1 end assert(n==1,50.5)do local n,_ENV=add,{assert=assert}n(_ENV,3)assert(_ENV[1]==3,51)end local function e(n)_ENV=n end local d=_ENV e{assert=assert,q=123}assert(q==123,52)e(d)function i()return 9,0,1 end function v(n)return n()end function y(n)return(n())end assert(pack(v(i)).n==3 and pack(y(i)).n==1,53)n=0x.004 if n<1 then if n==0 then n=123 end else n=321 end assert(n==0x.004,55)h=23\4 assert(h==5,55.1)h\=3 assert(h==1,55.2)do local n=1 function n()end end assert(nn==nil,56)n=1 repeat local n=2 until assert(n==2,57)do local n=2 repeat local e=3 until assert(n*e==6,57.5)end local function e()return 3 end assert(-e()+e()==0,58)local function d()return e end assert(d()()==3,59)local function n(e,d)local f=function()e+=1 return e end if d and d>0 then return f,n(e*2,d-1)else return f end end local f,o,l,a=n(10),n(20),n(30,1)assert(f()==11 and o()==21 and n(0)()==1 and l()==31 and a()==61 and f()==12 and o()==22 and n(0)()==1 and l()==32 and a()==62,60)function w(n)return n end assert(w"me"=="me"and w[[me]]=="me",61)z={l=function(e,n)return n end}assert(z:l"me"=="me"and#z:l{}==0,62)do while true do if 1==1 then::e::end goto n end::n::end local n=1 function _()return n end local n=2 assert(_()==1,63)local n=1 do function n1()return n end local n=2 assert(n1()==1,64)end do local n,e=1,2::n::assert(e==2,65)if n>1 then assert(s()==4 and e==2,66)goto d end local e=3 s=function()e+=1 return e end n+=1 goto n end::d::do local n=1::n::local e=n d=s s=function()e+=1 return e end n+=1 if n==3 then goto f else goto n end end::f::assert(s()==3 and s()==4 and d()==2 and s()==5 and d()==3,67)do goto n local n::n::end if 1==1 then end local n=0 function ord(e,d)assert(n==e,68)n+=1 return d end local n={}ord(0,n).x,ord(1,n).x=ord(2,2),ord(3,function()return 3 end)(ord(4,1),ord(5,1))assert(n.x==2,69)local f,n=1,2 assert(n==2,70)function e(e,n)assert(n==2,71)end e(1,2)k=0 g={10,20}function d()k+=1 return k end g[d()]+=1 assert(g[1]==11 and g[2]==20,72)n=0 n+=16 assert(n==16,73)assert([[[[]]=="[[",73.5)if 1==1 then if 2==3 then n=1 else n=2 end else n=3 end assert(n==2,74)if 1==2 then if 2==3 then n=1 else n=2 end else n=3 end assert(n==3,74.1)x=1 while x<10 do x+=1 if x==5 then break end end assert(x==5,75)if 1==2 then x=1 else if 1==3 then x=2 else x=3 end end assert(x==3,76)if 1==1 then if 2==2 then n=4 else n=5 end else n=6 end assert(n==4,77)do n=0 if 1==2 then end end n=123 assert(n==123,78)do local e,n=print print=function(e)n=e end?1
assert(n==1,79)print=e end do local n local print=function(e)n=e end?2
assert(n==2,80)end e=1({x=1}).x=2 assert(e==1,81)e={1}({x=1}).x=2 assert(e[1]==1,81.1)e="1"({x=1}).x=2 assert(e=="1",81.2)e=function()end({x=1}).x=2 assert(e()==nil,81.3)printh"DONE"
:: [eoc]
2 changes: 2 additions & 0 deletions test_input/testtron.p64
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,8 @@ assert(xeq(0x123.45p-12,0.071110725402832031),5.2)
assert(0xf.f==15.9375 and 0B10.01==2.25,6)
assert(0b01100==0xc and 0b11111111111111111111111111111111111111111111111111111111111111111==-1,6.1)
assert(1e400==0x1p1024 and -1e400==-math.huge,6.2)
assert(001.751532838832970300e-00277 == tonum("1.7515328388329703e-277"), 7)
assert(6.707235992995134e-30 == tonum("6.707235992995134e-30"), 7.1)
a,b,c=1,{},3
a,b.n,b[1],c=c,2,4,a
assert(a==3 and c==1 and b['n']==2 and b[1]==4,8)
Expand Down

0 comments on commit a601c8d

Please sign in to comment.