mirror of https://github.com/svaarala/duktape.git
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
177 lines
4.6 KiB
177 lines
4.6 KiB
/*
|
|
* NaN handling
|
|
*
|
|
* https://www.khronos.org/registry/typedarray/specs/latest/#4
|
|
*/
|
|
|
|
/*@include util-typedarray.js@*/
|
|
|
|
/*===
|
|
NaN handling test
|
|
through dataview
|
|
sign: 1
|
|
expt: 2047
|
|
mantissa is non-zero
|
|
through float64array
|
|
read back value: NaN
|
|
read back value is NaN: true
|
|
===*/
|
|
|
|
function nanHandlingTest() {
|
|
var b = new ArrayBuffer(8);
|
|
var v1 = new DataView(b);
|
|
var v2 = new Uint8Array(b);
|
|
var v3 = new Float64Array(b);
|
|
var sign, expt;
|
|
var i, t;
|
|
|
|
/* IEEE double NaN pattern is (http://en.wikipedia.org/wiki/Double-precision_floating-point_format):
|
|
*
|
|
* 7ffm mmmm mmmm mmmm
|
|
* fffm mmmm mmmm mmmm
|
|
*
|
|
* where mmm.. is mantissa, which must be non-zero (any non-zero value is OK).
|
|
*/
|
|
|
|
/*
|
|
* Test first through DataView
|
|
*/
|
|
|
|
print('through dataview');
|
|
|
|
v1.setFloat64(0, 0.0 / 0.0, false /*littleEndian*/);
|
|
|
|
for (i = 0; i < 8; i++) {
|
|
// Implementation specific, don't print
|
|
//print(i, v1.getUint8(i).toString(16));
|
|
}
|
|
|
|
expt = v1.getUint16(0, false /*littleEndian*/);
|
|
sign = expt >>> 15;
|
|
expt = (expt >> 4) & 0x7ff;
|
|
|
|
// Note: NaN normalization is allowed, and NaN sign is also platform
|
|
// dependent.
|
|
|
|
print('sign: ' + sign);
|
|
print('expt: ' + expt);
|
|
|
|
// Implementation specific, don't print
|
|
//print('mant hi: ' + (v1.getUint32(0, false /*littleEndian*/) & 0x000fffff).toString(16));
|
|
//print('mant lo: ' + (v1.getUint32(4, false /*littleEndian*/) & 0x000fffff).toString(16));
|
|
|
|
if ((v1.getUint32(0, false /*littleEndian*/) & 0x000fffff) == 0 &&
|
|
v1.getUint32(4, false /*littleEndian*/) == 0) {
|
|
print('mantissa is zero');
|
|
} else {
|
|
print('mantissa is non-zero');
|
|
}
|
|
|
|
/*
|
|
* Then writing NaN explicitly, reading it into an Ecmascript value,
|
|
* writing it back, and checking through DataView.
|
|
*/
|
|
|
|
print('through float64array');
|
|
|
|
b = new ArrayBuffer(8); // use a new ArrayBuffer just in case
|
|
v1 = new DataView(b);
|
|
v2 = new Uint8Array(b);
|
|
v3 = new Float64Array(b);
|
|
|
|
if (doubleEndianness == 'big') {
|
|
// FF F0 00 00 00 00 00 01, NaN with sign set, mantissa lowest bit set
|
|
v2[0] = 0xff;
|
|
v2[1] = 0xf0;
|
|
v2[2] = 0x00;
|
|
v2[3] = 0x00;
|
|
v2[4] = 0x00;
|
|
v2[5] = 0x00;
|
|
v2[6] = 0x00;
|
|
v2[7] = 0x01;
|
|
} else if (doubleEndianness == 'little') {
|
|
v2[0] = 0x01;
|
|
v2[1] = 0x00;
|
|
v2[2] = 0x00;
|
|
v2[3] = 0x00;
|
|
v2[4] = 0x00;
|
|
v2[5] = 0x00;
|
|
v2[6] = 0xf0;
|
|
v2[7] = 0xff;
|
|
} else if (doubleEndianness == 'mixed') {
|
|
v2[0] = 0x00;
|
|
v2[1] = 0x00;
|
|
v2[2] = 0xf0;
|
|
v2[3] = 0xff;
|
|
v2[4] = 0x01;
|
|
v2[5] = 0x00;
|
|
v2[6] = 0x00;
|
|
v2[7] = 0x00;
|
|
} else {
|
|
throw new Error('internal error');
|
|
}
|
|
|
|
t = v3[0];
|
|
print('read back value: ' + t);
|
|
print('read back value is NaN: ' + isNaN(t));
|
|
|
|
v3[0] = t;
|
|
|
|
for (i = 0; i < 8; i++) {
|
|
// Implementation specific, don't print
|
|
//print(i, v2[i].toString(16));
|
|
}
|
|
|
|
if (doubleEndianness == 'big') {
|
|
if ((v2[0] & 0x7f != 0x7f) ||
|
|
(v2[1] & 0xf0 != 0xf0)) {
|
|
throw new Error('expt is not 0x7ff'); // sign can be either
|
|
}
|
|
if ((v2[1] & 0x0f == 0x00) &&
|
|
(v2[2] == 0x00) &&
|
|
(v2[3] == 0x00) &&
|
|
(v2[4] == 0x00) &&
|
|
(v2[5] == 0x00) &&
|
|
(v2[6] == 0x00) &&
|
|
(v2[7] == 0x00)) {
|
|
throw new Error('mantissa is zero');
|
|
}
|
|
} else if (doubleEndianness == 'little') {
|
|
if ((v2[7] & 0x7f != 0x7f) ||
|
|
(v2[6] & 0xf0 != 0xf0)) {
|
|
throw new Error('expt is not 0x7ff'); // sign can be either
|
|
}
|
|
if ((v2[6] & 0x0f == 0x00) &&
|
|
(v2[5] == 0x00) &&
|
|
(v2[4] == 0x00) &&
|
|
(v2[3] == 0x00) &&
|
|
(v2[2] == 0x00) &&
|
|
(v2[1] == 0x00) &&
|
|
(v2[0] == 0x00)) {
|
|
throw new Error('mantissa is zero');
|
|
}
|
|
} else if (doubleEndianness == 'mixed') {
|
|
if ((v2[3] & 0x7f != 0x7f) ||
|
|
(v2[2] & 0xf0 != 0xf0)) {
|
|
throw new Error('expt is not 0x7ff'); // sign can be either
|
|
}
|
|
if ((v2[2] & 0x0f == 0x00) &&
|
|
(v2[1] == 0x00) &&
|
|
(v2[0] == 0x00) &&
|
|
(v2[7] == 0x00) &&
|
|
(v2[6] == 0x00) &&
|
|
(v2[5] == 0x00) &&
|
|
(v2[4] == 0x00)) {
|
|
throw new Error('mantissa is zero');
|
|
}
|
|
} else {
|
|
throw new Error('internal error');
|
|
}
|
|
}
|
|
|
|
try {
|
|
print('NaN handling test');
|
|
nanHandlingTest();
|
|
} catch (e) {
|
|
print(e.stack || e);
|
|
}
|
|
|