You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
This repository has been archived by the owner on Nov 24, 2022. It is now read-only.
Describe the bug
While solving issue #373 (PR #542), we found out that the conversion of 64-bit JavaScript Numbers into BigInts is lossy. Though somewhat expected [1], this has repercussions for Asterius, since the 64-bit versions of memset do not work as expected when contents above MAX_SAFE_INTEGER are used (this affects types that are represented using 64 bits such as Word, Word64, and Ptr). For example, running this piece of code
do
dst <- newPinnedByteArray 32
setByteArray dst (3*8) 1 (0xcccccccccccccccc::Word64)
w <- readByteArray dst 3print (w == (0xcccccccccccccccc::Word64))
unintuitively prints False.
[1]: The maximum integer that can be safely represented in JavaScript is Number.MAX_SAFE_INTEGER = 2^53 - 1, because JavaScript uses IEEE754 double precision floating point number representation (see here).
To Reproduce
The easiest way to reproduce the issue is to run:
stack test asterius:primitive
This test uses all Haskell variants of memset on a given array, and checks that storing (using memset) and retrieving should yield the same result. Hence, it is expected that running the test prints only Trues (each False is a case where this above property is violated).
Expected behavior
Running stack test asterius:primitive should only print ByteArrays and True.
The conversion from Number to BigInt happens in asterius/rts/rts.memory.mjs where a JS version of memset is implemented:
memset(_dst,c,n,size=1){// We only allow 1, 2, 4, 8. Any other size should get a runtime error.constty={1 : Uint8Array,2 : Uint16Array,4 : Uint32Array,8 : BigUint64Array};constbuf=this.expose(_dst,n,ty[size]);if(size===8){// TODO: The conversion BigInt(c) is lossy. Numbers are represented as // IEEE754 double precision floating point numbers, for which the maximum// (representable) safe integer in JavaScript is (Number.MAX_SAFE_INTEGER// = 2^53 - 1).buf.fill(BigInt(c));}else{buf.fill(c);}}
The input values are always Numbers, even when we want them to represent 64-bit integers, so the conversion BigInt(c) is unavoidable.
The text was updated successfully, but these errors were encountered:
Describe the bug
While solving issue #373 (PR #542), we found out that the conversion of 64-bit JavaScript
Number
s intoBigInt
s is lossy. Though somewhat expected [1], this has repercussions for Asterius, since the 64-bit versions ofmemset
do not work as expected when contents aboveMAX_SAFE_INTEGER
are used (this affects types that are represented using 64 bits such asWord
,Word64
, andPtr
). For example, running this piece of codeunintuitively prints
False
.[1]: The maximum integer that can be safely represented in JavaScript is
Number.MAX_SAFE_INTEGER = 2^53 - 1
, because JavaScript uses IEEE754 double precision floating point number representation (see here).To Reproduce
The easiest way to reproduce the issue is to run:
This test uses all Haskell variants of
memset
on a given array, and checks that storing (usingmemset
) and retrieving should yield the same result. Hence, it is expected that running the test prints onlyTrue
s (eachFalse
is a case where this above property is violated).Expected behavior
Running
stack test asterius:primitive
should only printByteArray
s andTrue
.Environment
Additional context
The conversion from
Number
toBigInt
happens inasterius/rts/rts.memory.mjs
where a JS version ofmemset
is implemented:The input values are always
Number
s, even when we want them to represent 64-bit integers, so the conversionBigInt(c)
is unavoidable.The text was updated successfully, but these errors were encountered: