| // 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; |
| } |
| } |