Skip to content

Commit

Permalink
2024/08/08 時点の英語版に基づき更新
Browse files Browse the repository at this point in the history
  • Loading branch information
mfuji09 committed Nov 10, 2024
1 parent 47b856e commit bc98028
Showing 1 changed file with 76 additions and 103 deletions.
179 changes: 76 additions & 103 deletions files/ja/web/javascript/reference/global_objects/math/clz32/index.md
Original file line number Diff line number Diff line change
@@ -1,38 +1,68 @@
---
title: Math.clz32()
slug: Web/JavaScript/Reference/Global_Objects/Math/clz32
l10n:
sourceCommit: d71da812ee94c20658cb1916a123a42254ea545c
---

{{JSRef}}

**`Math.clz32()`** 関数は、引数として与えられた数値の 32 ビットバイナリ表現での先頭の 0 の個数を返します。
**`Math.clz32()`** は静的メソッドで、引数として与えられた数値の 32 ビットバイナリー表現での先頭の 0 の個数を返します。

{{EmbedInteractiveExample("pages/js/math-clz32.html")}}

## 構文

```
```js-nolint
Math.clz32(x)
```

### 引数

- `x`
- : 数値
- : 数値です

### 返値

与えられた数値の 32 ビットバイナリ表現での先頭の 0 の個数。
`x`32 ビットバイナリー表現での先頭の 0 の個数。

## 解説

"`clz32`"**CountLeadingZeroes32** の省略形です。
`clz32`**C**ount**L**eading**Z**eros**32** の省略形です。

`x` が数値でない場合、まず数値に変換され、32 ビット符号なし整数値に変換されます。

変換された 32 ビット符号なし整数値が `0` の場合、すべてのビットが `0` であるため、`32` を返します。
変換された 32 ビット符号なし整数が `0` の場合、 `32` が返されます。これは、すべてのビットが `0` であるためです。最上位ビットが `1` の場合(すなわち、数値が 2<sup>31</sup> 以上の数値である場合)、 `0` が返されます。

この関数は [Emscripten](https://emscripten.org/) のような JS にコンパイルするシステムに対して特に役に立ちます。

##

### Math.clz32() の使用

```js
Math.clz32(1); // 31
Math.clz32(1000); // 22
Math.clz32(); // 32

const stuff = [
NaN,
Infinity,
-Infinity,
0,
-0,
false,
null,
undefined,
"foo",
{},
[],
];
stuff.every((n) => Math.clz32(n) === 32); // true

この関数は [Emscripten](/ja/docs/Emscripten) のような JS にコンパイルするシステムに対して特に役に立ちます。
Math.clz32(true); // 31
Math.clz32(3.5); // 30
```

### 先頭の 1 を数える

Expand All @@ -41,133 +71,75 @@ Math.clz32(x)
以下の 32 ビットワード値を想定してみます。

```js
var a = 32776; // 00000000000000001000000000001000 (16 leading zeros)
const a = 32776; // 00000000000000001000000000001000 (先頭のゼロは 16 個)
Math.clz32(a); // 16

var b = ~32776; // 11111111111111110111111111110111 (32776 inversed, 0 leading zeros)
Math.clz32(b); // 0 (this is equal to how many leading one's there are in a)
const b = ~32776; // 11111111111111110111111111110111 32776 の逆、先頭のゼロは 0 個)
Math.clz32(b); // 0 (これは、 a にある先頭の 1 の数に等しい)
```

この論理を使用すると、 `clon` 関数は次のように作成することができます。

```js
var clz = Math.clz32;
const clz = Math.clz32;

function clon(integer) {
return clz(~integer);
}
```

さらに、この技術を拡張して、以下に示すようなジャンプレスの「Count Trailing Zeros」と「Count Trailing Ones」関数を作成することができます。以下の `ctrz` 関数は、すべての上位ビットを最も低いビットで埋め、そのビットを否定して上位のセットビットをすべて消去するので、clz が使用できます
さらに、このテクニックを拡張して、下記のようなジャンプのない "Count Trailing Zeros" 関数を作成することもできます。 `ctrz` 関数は、 2 の補数を持つ整数のビット単位の AND 演算を行います。 2 の補数にすることで、すべての末尾のゼロが 1 に変換され、 1 を加算すると、最初の 0 (元々は 1)に達するまで引き継がれます。それより上位のビットはすべてそのまま維持され、元の整数のビットの逆数となります。したがって、元の整数とビット単位の論理積を計算すると、上位のビットはすべて 0 となり、 `clz` でカウントできます。末尾のゼロの数に最初の 1 ビット、 `clz` でカウントされた上位ビットを足した合計は 32 です

```js
var clz = Math.clz32;
function ctrz(integer) {
// count trailing zeros
// 1. fill in all the higher bits after the first one
integer |= integer << 16;
integer |= integer << 8;
integer |= integer << 4;
integer |= integer << 2;
integer |= integer << 1;
// 2. Now, inversing the bits reveals the lowest bits
return (32 - clz(~integer)) | 0; // `|0` ensures integer coercion
integer >>>= 0; // Uint32 へ変換
if (integer === 0) {
// このステップを飛ばすと -1 を返すことになる
return 32;
}
integer &= -integer; // `int = int & (~int + 1)` と同等
return 31 - clz(integer);
}
```

次に、 "Count Trailing Ones" 関数を次のように定義します。

```js
function ctron(integer) {
// count trailing ones
// No shift-filling-in-with-ones operator is available in
// JavaScript, so the below code is the fastest
return ctrz(~integer);
/* Alternate implementation for demonstrational purposes:
// 1. erase all the higher bits after the first zero
integer &= (integer << 16) | 0xffff;
integer &= (integer << 8 ) | 0x00ff;
integer &= (integer << 4 ) | 0x000f;
integer &= (integer << 2 ) | 0x0003;
integer &= (integer << 1 ) | 0x0001;
// 2. Now, inversing the bits reveals the lowest zeros
return 32 - clon(~integer) |0;
*/
}
```

これらのヘルパー関数を ASM.JS モジュールに入れます。そして、そうすれば、真のパフォーマンスの傑作ができあがります。このような状況は、まさに ASM.JS のために設計されたものです
これらのヘルパー関数は、パフォーマンスの向上を目的として、 [asm.js](/ja/docs/Games/Tools/asm.js) モジュールにすることができます

```js
var countTrailsMethods = (function (stdlib, foreign, heap) {
const countTrailsMethods = (function (stdlib, foreign, heap) {
"use asm";
var clz = stdlib.Math.clz32;
const clz = stdlib.Math.clz32;

// 先頭のゼロを数える
function ctrz(integer) {
// count trailing zeros
integer = integer | 0; // coerce to an integer
// 1. fill in all the higher bits after the first one
// ASMjs for some reason does not allow ^=,&=, or |=
integer = integer | (integer << 16);
integer = integer | (integer << 8);
integer = integer | (integer << 4);
integer = integer | (integer << 2);
integer = integer | (integer << 1);
// 2. Now, inversing the bits reveals the lowest bits
return (32 - clz(~integer)) | 0;
integer = integer | 0; // 整数に変換
if ((integer | 0) == 0) {
// このステップを飛ばすと -1 を返すことになる
return 32;
}
// メモ: asm.js には &= のような複合代入演算子がない
integer = integer & -integer; // equivalent to `int = int & (~int + 1)`
return (31 - clz(integer)) | 0;
}

// 最後の 1 を数える
function ctron(integer) {
// count trailing ones
integer = integer | 0; // coerce to an integer
integer = integer | 0; // 整数に変換
return ctrz(~integer) | 0;
}
// unfourtunately, ASM.JS demands slow crummy objects:
return { a: ctrz, b: ctron };
})(window, null, null);
var ctrz = countTrailsMethods.a;
var ctron = countTrailsMethods.b;
```

##

### Math.clz32() の使用

```js
Math.clz32(1); // 31
Math.clz32(1000); // 22
Math.clz32(); // 32

var stuff = [
NaN,
Infinity,
-Infinity,
0,
-0,
false,
null,
undefined,
"foo",
{},
[],
];
stuff.every((n) => Math.clz32(n) == 32); // true

Math.clz32(true); // 31
Math.clz32(3.5); // 30
```

## ポリフィル

以下のポリフィルが最も効果的です。
// asm.js はプレーンオブジェクトを要求する
return { ctrz: ctrz, ctron: ctron };
})(window, null, null);

```js
if (!Math.clz32)
Math.clz32 = (function (log, LN2) {
return function (x) {
// Let n be ToUint32(x).
// Let p be the number of leading zero bits in
// the 32-bit binary representation of n.
// Return p.
var asUint = x >>> 0;
if (asUint === 0) {
return 32;
}
return (31 - ((log(asUint) / LN2) | 0)) | 0; // the "| 0" acts like math.floor
};
})(Math.log, Math.LN2);
const { ctrz, ctron } = countTrailsMethods;
```

## 仕様書
Expand All @@ -180,5 +152,6 @@ if (!Math.clz32)

## 関連情報

- [`Math.clz32` のポリフィル (`core-js`)](https://github.com/zloirock/core-js#ecmascript-math)
- {{jsxref("Math")}}
- {{jsxref("Math.imul")}}

0 comments on commit bc98028

Please sign in to comment.