diff --git a/src/org/mozilla/javascript/NativeMath.java b/src/org/mozilla/javascript/NativeMath.java index 61c495ad4f..dc8ab9b7c2 100644 --- a/src/org/mozilla/javascript/NativeMath.java +++ b/src/org/mozilla/javascript/NativeMath.java @@ -185,7 +185,33 @@ private static Object clz32(Context cx, Scriptable scope, Scriptable thisObj, Ob if (n == 0) { return Double32; } - return Double.valueOf(31 - Math.floor(Math.log(n >>> 0) * LOG2E)); + + int place = 0; + if ((n & 0xFFFF0000) != 0) { + place += 16; + n >>>= 16; + } + if ((n & 0xFF00) != 0) { + place += 8; + n >>>= 8; + } + if ((n & 0xF0) != 0) { + place += 4; + n >>>= 4; + } + if ((n & 0b1100) != 0) { + place += 2; + n >>>= 2; + } + if ((n & 0b10) != 0) { + place += 1; + n >>>= 1; + } + if ((n & 0b1) != 0) { + place += 1; + } + + return Double.valueOf(32 - place); } private static Object cos(Context cx, Scriptable scope, Scriptable thisObj, Object[] args) { diff --git a/testsrc/jstests/harmony/math-clz32.js b/testsrc/jstests/harmony/math-clz32.js new file mode 100644 index 0000000000..8b9d60bb5a --- /dev/null +++ b/testsrc/jstests/harmony/math-clz32.js @@ -0,0 +1,54 @@ +load("testsrc/assert.js"); + +assertEquals(Math.clz32(64), 25); +assertEquals(Math.clz32(0), 32); + +assertEquals(Math.clz32(0x00000001), 31); +assertEquals(Math.clz32(0x00000002), 30); +assertEquals(Math.clz32(0x00000004), 29); +assertEquals(Math.clz32(0x00000008), 28); +assertEquals(Math.clz32(0x000000010), 27); +assertEquals(Math.clz32(0x00000020), 26); +assertEquals(Math.clz32(0x00000040), 25); +assertEquals(Math.clz32(0x00000080), 24); +assertEquals(Math.clz32(0x00000100), 23); +assertEquals(Math.clz32(0x00000200), 22); +assertEquals(Math.clz32(0x00000400), 21); +assertEquals(Math.clz32(0x00000800), 20); +assertEquals(Math.clz32(0x00001000), 19); +assertEquals(Math.clz32(0x00002000), 18); +assertEquals(Math.clz32(0x00004000), 17); +assertEquals(Math.clz32(0x00008000), 16); +assertEquals(Math.clz32(0x00010000), 15); +assertEquals(Math.clz32(0x00020000), 14); +assertEquals(Math.clz32(0x00040000), 13); +assertEquals(Math.clz32(0x00080000), 12); +assertEquals(Math.clz32(0x00100000), 11); +assertEquals(Math.clz32(0x00200000), 10); +assertEquals(Math.clz32(0x00400000), 9); +assertEquals(Math.clz32(0x00800000), 8); +assertEquals(Math.clz32(0x01000000), 7); +assertEquals(Math.clz32(0x02000000), 6); +assertEquals(Math.clz32(0x04000000), 5); +assertEquals(Math.clz32(0x08000000), 4); +assertEquals(Math.clz32(0x10000000), 3); +assertEquals(Math.clz32(0x20000000), 2); +assertEquals(Math.clz32(0x40000000), 1); +assertEquals(Math.clz32(0x80000000), 0); +assertEquals(Math.clz32(0xFFFFFFFF), 0); +assertEquals(Math.clz32(0xFFFF0000), 0); +assertEquals(Math.clz32(0x0000FF00), 16); +assertEquals(Math.clz32(0x000000F0), 24); + +assertEquals(Math.clz32(-0), 32); +assertEquals(Math.clz32(-1), 0); +assertEquals(Math.clz32(-100), 0); + +assertEquals(Math.clz32(1.9), 31); +assertEquals(Math.clz32(Number.POSITIVE_INFINITY), 32); +assertEquals(Math.clz32(Number.NEGATIVE_INFINITY), 32); +assertEquals(Math.clz32(Number.NaN), 32); + +assertEquals(Math.clz32(0x1_0000_0100), 23); + +"success"; diff --git a/testsrc/org/mozilla/javascript/tests/harmony/MathClz32Test.java b/testsrc/org/mozilla/javascript/tests/harmony/MathClz32Test.java new file mode 100644 index 0000000000..47632d4cf6 --- /dev/null +++ b/testsrc/org/mozilla/javascript/tests/harmony/MathClz32Test.java @@ -0,0 +1,7 @@ +package org.mozilla.javascript.tests.harmony; + +import org.mozilla.javascript.drivers.RhinoTest; +import org.mozilla.javascript.drivers.ScriptTestsBase; + +@RhinoTest(value = "testsrc/jstests/harmony/math-clz32.js") +public class MathClz32Test extends ScriptTestsBase {}