diff --git a/half-floats.js b/half-floats.js new file mode 100644 index 0000000..cdd1aea --- /dev/null +++ b/half-floats.js @@ -0,0 +1,62 @@ + +// ref: http://stackoverflow.com/questions/32633585/how-do-you-convert-to-half-floats-in-javascript +function toHalf(value) { + const floatView = new Float32Array(1); + const int32View = new Int32Array(floatView.buffer); + + // This method is faster than the OpenEXR implementation (very often + // used, eg. in Ogre), with the additional benefit of rounding, inspired + // by James Tursa's half-precision code. + + floatView[0] = value; + const x = int32View[0]; + + let bits = (x >> 16) & 0x8000; // Get the sign + let m = (x >> 12) & 0x07ff; // Keep one extra bit for rounding + const e = (x >> 23) & 0xff; // Using int is faster here + + // If zero, or denormal, or exponent underflows too much for a denormal + // half, return signed zero. + if (e < 103) { + return bits; + } + + // If NaN, return NaN. If Inf or exponent overflow, return Inf. + if (e > 142) { + bits |= 0x7c00; + // If exponent was 0xff and one mantissa bit was set, it means NaN, + // not Inf, so make sure we set one mantissa bit too. + bits |= ((e == 255) ? 0 : 1) && (x & 0x007fffff); + return bits; + } + + // If exponent underflows but not too much, return a denormal + if (e < 113) { + m |= 0x0800; + // Extra rounding may overflow and set mantissa to 0 and exponent + // to 1, which is OK. + bits |= (m >> (114 - e)) + ((m >> (113 - e)) & 1); + return bits; + } + + bits |= ((e - 112) << 10) | (m >> 1); + // Extra rounding. An overflow will set mantissa to 0 and increment + // the exponent, which is OK. + bits += m & 1; + return bits; +} + +// ref: https://stackoverflow.com/questions/5678432/decompressing-half-precision-floats-in-javascript +function fromHalf(h) { + const s = (h & 0x8000) >> 15 ? -1 : 1; + const e = (h & 0x7C00) >> 10; + const f = h & 0x03FF; + + if (e == 0) { + return s * Math.pow(2, -14) * (f / Math.pow(2, 10)); + } else if (e == 0x1F) { + return f ? NaN : (s * Infinity); + } + + return s * Math.pow(2, e - 15) * (1 + (f / Math.pow(2, 10))); +} \ No newline at end of file diff --git a/webnn-add.html b/webnn-add.html index 6b03a6f..8e97eb3 100644 --- a/webnn-add.html +++ b/webnn-add.html @@ -1,6 +1,7 @@ WebNN Simple Example +

@@ -93,68 +94,6 @@ } } - // ref: http://stackoverflow.com/questions/32633585/how-do-you-convert-to-half-floats-in-javascript - function toHalf(value) { - const floatView = new Float32Array(1); - const int32View = new Int32Array(floatView.buffer); - - // This method is faster than the OpenEXR implementation (very often - // used, eg. in Ogre), with the additional benefit of rounding, inspired - // by James Tursa's half-precision code. - - floatView[0] = value; - const x = int32View[0]; - - let bits = (x >> 16) & 0x8000; // Get the sign - let m = (x >> 12) & 0x07ff; // Keep one extra bit for rounding - const e = (x >> 23) & 0xff; // Using int is faster here - - // If zero, or denormal, or exponent underflows too much for a denormal - // half, return signed zero. - if (e < 103) { - return bits; - } - - // If NaN, return NaN. If Inf or exponent overflow, return Inf. - if (e > 142) { - bits |= 0x7c00; - // If exponent was 0xff and one mantissa bit was set, it means NaN, - // not Inf, so make sure we set one mantissa bit too. - bits |= ((e == 255) ? 0 : 1) && (x & 0x007fffff); - return bits; - } - - // If exponent underflows but not too much, return a denormal - if (e < 113) { - m |= 0x0800; - // Extra rounding may overflow and set mantissa to 0 and exponent - // to 1, which is OK. - bits |= (m >> (114 - e)) + ((m >> (113 - e)) & 1); - return bits; - } - - bits |= ((e - 112) << 10) | (m >> 1); - // Extra rounding. An overflow will set mantissa to 0 and increment - // the exponent, which is OK. - bits += m & 1; - return bits; - } - - // ref: https://stackoverflow.com/questions/5678432/decompressing-half-precision-floats-in-javascript - function fromHalf(h) { - const s = (h & 0x8000) >> 15 ? -1 : 1; - const e = (h & 0x7C00) >> 10; - const f = h & 0x03FF; - - if (e == 0) { - return s * Math.pow(2, -14) * (f / Math.pow(2, 10)); - } else if (e == 0x1F) { - return f ? NaN : (s * Infinity); - } - - return s * Math.pow(2, e - 15) * (1 + (f / Math.pow(2, 10))); - } - function maybeEncodeInput(input) { if (dataTypeOption.value == 'float16') { return toHalf(input); diff --git a/webnn-conv2d.html b/webnn-conv2d.html index 00b7055..fd0e39f 100644 --- a/webnn-conv2d.html +++ b/webnn-conv2d.html @@ -1,6 +1,7 @@ WebNN Conv2D +

@@ -11,6 +12,13 @@

+

+ Data type: + +