|  | // Copyright (C) 2023 The Android Open Source Project | 
|  | // | 
|  | // Licensed under the Apache License, Version 2.0 (the "License"); | 
|  | // you may not use this file except in compliance with the License. | 
|  | // You may obtain a copy of the License at | 
|  | // | 
|  | //      http://www.apache.org/licenses/LICENSE-2.0 | 
|  | // | 
|  | // Unless required by applicable law or agreed to in writing, software | 
|  | // distributed under the License is distributed on an "AS IS" BASIS, | 
|  | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | 
|  | // See the License for the specific language governing permissions and | 
|  | // limitations under the License. | 
|  |  | 
|  | export class BigintMath { | 
|  | static INT64_MAX: bigint = 2n ** 63n - 1n; | 
|  | static INT64_MIN: bigint = -(2n ** 63n); | 
|  |  | 
|  | // Returns the smallest integral power of 2 that is not smaller than n. | 
|  | // If n is less than or equal to 0, returns 1. | 
|  | static bitCeil(n: bigint): bigint { | 
|  | let result = 1n; | 
|  | while (result < n) { | 
|  | result <<= 1n; | 
|  | } | 
|  | return result; | 
|  | } | 
|  |  | 
|  | // Returns the largest integral power of 2 which is not greater than n. | 
|  | // If n is less than or equal to 0, returns 1. | 
|  | static bitFloor(n: bigint): bigint { | 
|  | let result = 1n; | 
|  | while (result << 1n <= n) { | 
|  | result <<= 1n; | 
|  | } | 
|  | return result; | 
|  | } | 
|  |  | 
|  | // Returns the largest integral value x where 2^x is not greater than n. | 
|  | static log2(n: bigint): number { | 
|  | let result = 1n; | 
|  | let log2 = 0; | 
|  | while (result << 1n <= n) { | 
|  | result <<= 1n; | 
|  | ++log2; | 
|  | } | 
|  | return log2; | 
|  | } | 
|  |  | 
|  | // Returns the integral multiple of step which is closest to n. | 
|  | // If step is less than or equal to 0, returns n. | 
|  | static quant(n: bigint, step: bigint): bigint { | 
|  | step = BigintMath.max(1n, step); | 
|  | const halfStep = step / 2n; | 
|  | return step * ((n + halfStep) / step); | 
|  | } | 
|  |  | 
|  | // Returns the largest integral multiple of step which is not larger than n. | 
|  | // If step is less than or equal to 0, returns n. | 
|  | static quantFloor(n: bigint, step: bigint): bigint { | 
|  | step = BigintMath.max(1n, step); | 
|  | if (n >= 0) { | 
|  | return n - (n % step); | 
|  | } else { | 
|  | // If we're negative, just subtract one more "step", unless we're already | 
|  | // aligned to a step then do nothing. | 
|  | return n - (n % step) - (n % step === 0n ? 0n : step); | 
|  | } | 
|  | } | 
|  |  | 
|  | // Returns the smallest integral multiple of step which is not smaller than n. | 
|  | // If step is less than or equal to 0, returns n. | 
|  | static quantCeil(n: bigint, step: bigint): bigint { | 
|  | step = BigintMath.max(1n, step); | 
|  | if (n >= 0) { | 
|  | return n - (n % step) + (n % step === 0n ? 0n : step); | 
|  | } else { | 
|  | return n - (n % step); | 
|  | } | 
|  | } | 
|  |  | 
|  | // Returns the greater of a and b. | 
|  | static max(a: bigint, b: bigint): bigint { | 
|  | return a > b ? a : b; | 
|  | } | 
|  |  | 
|  | // Returns the smaller of a and b. | 
|  | static min(a: bigint, b: bigint): bigint { | 
|  | return a < b ? a : b; | 
|  | } | 
|  |  | 
|  | // Returns the number of 1 bits in n. | 
|  | static popcount(n: bigint): number { | 
|  | if (n < 0n) { | 
|  | throw Error(`Can\'t get popcount of negative number ${n}`); | 
|  | } | 
|  | let count = 0; | 
|  | while (n) { | 
|  | if (n & 1n) { | 
|  | ++count; | 
|  | } | 
|  | n >>= 1n; | 
|  | } | 
|  | return count; | 
|  | } | 
|  |  | 
|  | // Return the ratio between two bigints as a number. | 
|  | static ratio(dividend: bigint, divisor: bigint): number { | 
|  | return Number(dividend) / Number(divisor); | 
|  | } | 
|  |  | 
|  | // Calculates the absolute value of a n. | 
|  | static abs(n: bigint) { | 
|  | return n < 0n ? -1n * n : n; | 
|  | } | 
|  | } |