[JavaScript] 整数を長さ 64 ビットの Uint8Array に変換する

# 1. `Number` 型の場合

JavaScript の通常の数値は `Number` 型で、絶対値の長さが 53 ビットの整数を扱うことができます。

参考「[Number.MIN_SAFE_INTEGER - JavaScript | MDN](https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/Number/MIN_SAFE_INTEGER)」
参考「[Number.MAX_SAFE_INTEGER - JavaScript | MDN](https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/Number/MAX_SAFE_INTEGER)」

ただし、JavaScript でのビット演算は数値を 32 ビットとして扱います。

参考「[バイナリービット演算子 - 式と演算子 - JavaScript | MDN](https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Operators#%E3%83%90%E3%82%A4%E3%83%8A%E3%83%AA%E3%83%BC%E3%83%93%E3%83%83%E3%83%88%E6%BC%94%E7%AE%97%E5%AD%90)」

そのため、ビット演算の右シフトでなく割り算を用いて長さを 32 ビット以下の値に分割する必要があります。

```js
/**
 * 整数をビッグエンディアン形式で Uint8Array に変換する
 */
const intToUint8ArrayInBigEndian = number => {

	// メモ: number が負の場合、Math.floor() なしだと正しい結果を得られないため注意
	const highOrderDigits = Math.floor(number / 0x1_00000000);

	// 
	const uint8Array = new Uint8Array(8);

	uint8Array[0] = highOrderDigits >>> 24 & 0xff;
	uint8Array[1] = highOrderDigits >>> 16 & 0xff;
	uint8Array[2] = highOrderDigits >>>  8 & 0xff;
	uint8Array[3] = highOrderDigits        & 0xff;

	uint8Array[4] = number >>> 24 & 0xff;
	uint8Array[5] = number >>> 16 & 0xff;
	uint8Array[6] = number >>>  8 & 0xff;
	uint8Array[7] = number        & 0xff;

	return uint8Array;

};
```

```js:例
// 絶対値の長さが 53 ビットの正の整数
const numberA = 0x123456_789abcde;
console.log(numberA.toString(16));

const uint8ArrayA = intToUint8ArrayInBigEndian(numberA);
console.log(Array.from(uint8ArrayA, uint8 => uint8.toString(16).padStart(2, '0')).join());

// 絶対値の長さが 53 ビットの正の整数
const numberB = Number.MAX_SAFE_INTEGER;
console.log(numberB.toString(16));

const uint8ArrayB = intToUint8ArrayInBigEndian(numberB);
console.log(Array.from(uint8ArrayB, uint8 => uint8.toString(16).padStart(2, '0')).join());

// 絶対値の長さが 53 ビットの負の整数
const numberC = Number.MIN_SAFE_INTEGER;
console.log(numberC.toString(16));

const uint8ArrayC = intToUint8ArrayInBigEndian(numberC);
console.log(Array.from(uint8ArrayC, uint8 => uint8.toString(16).padStart(2, '0')).join());
```

```text:例の実行結果
123456789abcde
00,12,34,56,78,9a,bc,de
1fffffffffffff
00,1f,ff,ff,ff,ff,ff,ff
-1fffffffffffff
ff,e0,00,00,00,00,00,01
```

ビット演算の右シフトは以下のように割り算で計算できます。

```js
 0x7fffffff >>> 16 === 0x7fff;
-0x7fffffff >>> 16 === 0x8000;
 0x80000001 >>> 16 === 0x8000;

(Math.floor( 0x7fffffff / 0x00010000) & 0xffff) === 0x7fff;
(Math.floor(-0x7fffffff / 0x00010000) & 0xffff) === 0x8000;
(Math.floor( 0x80000001 / 0x00010000) & 0xffff) === 0x8000;
```

# 2. `BigInt` 型の場合

JavaScript では `BigInt` 型を用いることで大きな数を扱えますが、`Number` 型より計算に時間がかかります。

```js
/**
 * BigInt をビッグエンディアン形式で Uint8Array に変換する
 */
const bigIntToUint8ArrayInBigEndian = bigInt => {

	const uint8Array = new Uint8Array(8);

	uint8Array[0] = Number(bigInt >> 56n & 0xffn);
	uint8Array[1] = Number(bigInt >> 48n & 0xffn);
	uint8Array[2] = Number(bigInt >> 40n & 0xffn);
	uint8Array[3] = Number(bigInt >> 32n & 0xffn);

	uint8Array[4] = Number(bigInt >> 24n & 0xffn);
	uint8Array[5] = Number(bigInt >> 16n & 0xffn);
	uint8Array[6] = Number(bigInt >>  8n & 0xffn);
	uint8Array[7] = Number(bigInt        & 0xffn);

	return uint8Array;

};
```

```js:例
// 長さが 64 ビットの正の整数
const bigIntA = 0x12345678_9abcdef0n;
console.log(bigIntA.toString(16));

const uint8ArrayA = bigIntToUint8ArrayInBigEndian(bigIntA);
console.log(Array.from(uint8ArrayA, uint8 => uint8.toString(16).padStart(2, '0')).join());

// 長さが 64 ビットの正の整数
const bigIntB = 0x7fffffff_ffffffffn;
console.log(bigIntB.toString(16));

const uint8ArrayB = bigIntToUint8ArrayInBigEndian(bigIntB);
console.log(Array.from(uint8ArrayB, uint8 => uint8.toString(16).padStart(2, '0')).join());

// 長さが 64 ビットの負の整数
const bigIntC = -0x7fffffff_ffffffffn;
console.log(bigIntC.toString(16));

const uint8ArrayC = bigIntToUint8ArrayInBigEndian(bigIntC);
console.log(Array.from(uint8ArrayC, uint8 => uint8.toString(16).padStart(2, '0')).join());
```

```text:例の実行結果
123456789abcdef0
12,34,56,78,9a,bc,de,f0
7fffffffffffffff
7f,ff,ff,ff,ff,ff,ff,ff
-7fffffffffffffff
80,00,00,00,00,00,00,01
```