-
Notifications
You must be signed in to change notification settings - Fork 18
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Use ULP based comparison. #139
Use ULP based comparison. #139
Conversation
test/utils.js
Outdated
@@ -36,11 +36,28 @@ export function almostEqual(a, b, criteria) { | |||
} | |||
} | |||
|
|||
export function checkValue( | |||
output, expected, criteria = opFp32AccuracyCriteria) { | |||
export function compareUlp(a, b, nulp = 1, base = 64) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please split this function into getBitwise
and cmopareUlp
as Chai's C++ example.
For getBitwise
, please change base to a string type, like float32
and float64
. BTW, I don't think we support float64
in spec so far, do we?
test/utils.js
Outdated
const bView = new DataView(bBuffer); | ||
|
||
if (base === 64) { | ||
aView.setFloat64(0, a, true); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I suppose we should not restrict to little endian.
test/utils.js
Outdated
export function compareUlp(a, b, nulp = 1, base = 64) { | ||
const aBuffer = new ArrayBuffer(8); | ||
const bBuffer = new ArrayBuffer(8); | ||
const aView = new DataView(aBuffer); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It should populate the buffer with 0 or ~0, as C++ code does
int64_t bitwiseValue = (value < T(0)) ? ~int64_t(0) : 0; // Extend sign.
You probably can use a JavaScript BigInt
object do that e.g.,
aView.setBigInt64(0, value < 0 ? ~BigInt(0) : BigInt(0))
test/utils.js
Outdated
bView.setFloat32(0, b, true); | ||
} | ||
|
||
return Math.abs(new BigUint64Array(aBuffer) - new BigUint64Array(bBuffer)) > |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
For getBitwise
, you could return aView.getBigInt64(0)
here.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Math.abs
doesn't work with BigInt64
, so you probably need to implement it by yourself. Fortunately, it would straightfoward, as BigInt64 support comparison and negate.
8b7c0e2
to
98d76cb
Compare
Thanks @huningxin . I updated PR following your suggestion, now new function getBitwise(value) {
const buffer = new ArrayBuffer(4);
const view = new DataView(buffer);
view.setFloat32(0, value);
return view.getInt32(0);
} About bitwise of float32 data, I compared the return value of this JS function with one of native C++ @huningxin Please take a look again, thanks. |
98d76cb
to
232887b
Compare
test/utils.js
Outdated
export function checkValue( | ||
output, expected, criteria = opFp32AccuracyCriteria) { | ||
function getBitwise(value) { | ||
const buffer = new ArrayBuffer(4); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should use length 8 to accommodate BigInt
test/utils.js
Outdated
const buffer = new ArrayBuffer(4); | ||
const view = new DataView(buffer); | ||
view.setFloat32(0, value); | ||
return view.getInt32(0); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
should use getBigInt64
and return a BigInt
as I commented #139 (comment)
test/utils.js
Outdated
output, expected, criteria = opFp32AccuracyCriteria) { | ||
function getBitwise(value) { | ||
const buffer = new ArrayBuffer(4); | ||
const view = new DataView(buffer); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
as I commented before, you should populate the buffer #139 (comment)
test/utils.js
Outdated
return view.getInt32(0); | ||
} | ||
|
||
export function compareUlp(a, b, nulp = 1, format = 'float32') { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nulp should be BigInt
test/utils.js
Outdated
} | ||
|
||
export function compareUlp(a, b, nulp = 1, format = 'float32') { | ||
assert(format === 'float32', `Format ${format} is not supported.`); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
format
is not a accurate name, probably dataType
test/utils.js
Outdated
@@ -36,11 +36,26 @@ export function almostEqual(a, b, criteria) { | |||
} | |||
} | |||
|
|||
export function checkValue( | |||
output, expected, criteria = opFp32AccuracyCriteria) { | |||
function getBitwise(value) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If it is only for float32, please name it as getBitwiseFloat32
test/utils.js
Outdated
const aBitwise = getBitwise(a); | ||
const bBitwise = getBitwise(b); | ||
let distance = aBitwise - bBitwise; | ||
distance = distance > 0 ? distance : -distance; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
= 0 ?
Thanks much @huningxin. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please also add js doc for these two methods. Thanks.
test/utils.js
Outdated
@@ -36,11 +36,28 @@ export function almostEqual(a, b, criteria) { | |||
} | |||
} | |||
|
|||
export function checkValue( | |||
output, expected, criteria = opFp32AccuracyCriteria) { | |||
export function getBitwiseFloat32(value) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It probably makes sense to support other data types and make this function more generic, like getBitwise
. It would also align with C++ implementation.
test/utils.js
Outdated
const buffer = new ArrayBuffer(8); | ||
const int64Array = new BigInt64Array(buffer); | ||
int64Array[0] = value < 0 ? ~BigInt(0) : BigInt(0); | ||
const f32Array = new Float32Array(buffer); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Create the typed array based on dataType
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You can assert the unsupported data types here.
test/utils.js
Outdated
} | ||
|
||
export function compareUlp(a, b, nulp = 1n, dataType = 'float32') { | ||
assert(dataType === 'float32', `DataType ${dataType} is not supported.`); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
avoid assertion here.
@huningxin I updated PR, PTAL, thanks. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks good, thanks @BruceDai .
test/utils.js
Outdated
@@ -45,6 +45,9 @@ export function almostEqual(a, b, criteria) { | |||
* @return {number} A 64-bit signed integer. | |||
*/ | |||
export function getBitwise(value, dataType) { | |||
if (Object.is(value, -0)) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@huningxin I caught an issue of -0, the returns of
getBitwise(-0, "float32")
is 2147483648n, so the distance between -0 and 0 is 2147483648n, it isn't the same as the distance of 0n between -0 and 0 by native C++ compareUlp()
function.
I added this workaround to deal with -0. What's your opinion? Thanks
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Did you try -0.0 in native C++?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hi @huningxin,
I tested with -0.0 in native C++, the GitBitwise()
function returns 2147483648n, and the distance between -0.0 and 0 is 2147483648n.
I checked that return of Object.is(-0.0, -0)
is ture
, that's, -0.0 and -0 are same value in JavaScript.
Should we make the behave in JavaScript align with native behave? Any suggestion? Thanks.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for the testing. I think in JavaScript -0 and -0.0 are same, because they are both Numbers. In C++, -0 is integer and -0.0 is float, so they are different.
With that, I think it doesn't need this conversion with float32
data type. For integer data type, it probably needs to use parseInt(v)
, it will convert -0 (float) to 0.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks @huningxin.
I will raise this special case on coming WG meeting.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Cool. Could you please file an issue to log this case? It could be used for WG discussion. Thanks.
1. Make getBitwise() function more generic 2. Add JS docs for getBitwise() and compareUlp() functions
db9b729
to
a111503
Compare
I rebased this PR to only add JavaScript's ULP based comparison implementation. @huningxin PTAL, thanks. |
@huningxin I implemented JavaScript
compareUlp()
function to align Chai's comment on #2, PTAL, thanks.