1// Copyright (C) 2023 The Android Open Source Project 2// 3// Licensed under the Apache License, Version 2.0 (the "License"); 4// you may not use this file except in compliance with the License. 5// You may obtain a copy of the License at 6// 7// http://www.apache.org/licenses/LICENSE-2.0 8// 9// Unless required by applicable law or agreed to in writing, software 10// distributed under the License is distributed on an "AS IS" BASIS, 11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12// See the License for the specific language governing permissions and 13// limitations under the License. 14 15import {BigintMath as BIM} from './bigint_math'; 16 17describe('BigIntMath', () => { 18 describe('bitCeil', () => { 19 it('rounds powers of 2 to themselves', () => { 20 expect(BIM.bitCeil(1n)).toBe(1n); 21 expect(BIM.bitCeil(2n)).toBe(2n); 22 expect(BIM.bitCeil(4n)).toBe(4n); 23 expect(BIM.bitCeil(4294967296n)).toBe(4294967296n); 24 expect(BIM.bitCeil(2305843009213693952n)).toBe(2305843009213693952n); 25 }); 26 27 it('rounds non powers of 2 up to nearest power of 2', () => { 28 expect(BIM.bitCeil(3n)).toBe(4n); 29 expect(BIM.bitCeil(11n)).toBe(16n); 30 expect(BIM.bitCeil(33n)).toBe(64n); 31 expect(BIM.bitCeil(63n)).toBe(64n); 32 expect(BIM.bitCeil(1234567890123456789n)).toBe(2305843009213693952n); 33 }); 34 35 it('rounds 0 or negative values up to 1', () => { 36 expect(BIM.bitCeil(0n)).toBe(1n); 37 expect(BIM.bitCeil(-123n)).toBe(1n); 38 }); 39 }); 40 41 describe('bitFloor', () => { 42 it('rounds powers of 2 to themselves', () => { 43 expect(BIM.bitFloor(1n)).toBe(1n); 44 expect(BIM.bitFloor(2n)).toBe(2n); 45 expect(BIM.bitFloor(4n)).toBe(4n); 46 expect(BIM.bitFloor(4294967296n)).toBe(4294967296n); 47 expect(BIM.bitFloor(2305843009213693952n)).toBe(2305843009213693952n); 48 }); 49 50 it('rounds non powers of 2 down to nearest power of 2', () => { 51 expect(BIM.bitFloor(3n)).toBe(2n); 52 expect(BIM.bitFloor(11n)).toBe(8n); 53 expect(BIM.bitFloor(33n)).toBe(32n); 54 expect(BIM.bitFloor(63n)).toBe(32n); 55 expect(BIM.bitFloor(1234567890123456789n)).toBe(1152921504606846976n); 56 }); 57 58 it('rounds 0 or negative values up to 1', () => { 59 expect(BIM.bitFloor(0n)).toBe(1n); 60 expect(BIM.bitFloor(-123n)).toBe(1n); 61 }); 62 }); 63 64 describe('log2', () => { 65 it('calcs exact powers of 2', () => { 66 expect(BIM.log2(1n)).toBe(0); 67 expect(BIM.log2(2n)).toBe(1); 68 expect(BIM.log2(4n)).toBe(2); 69 expect(BIM.log2(4294967296n)).toBe(32); 70 expect(BIM.log2(2305843009213693952n)).toBe(61); 71 }); 72 73 it('rounds non powers of 2 down to nearest power of 2', () => { 74 expect(BIM.log2(3n)).toBe(1); 75 expect(BIM.log2(11n)).toBe(3); 76 expect(BIM.log2(33n)).toBe(5); 77 expect(BIM.log2(63n)).toBe(5); 78 expect(BIM.log2(1234567890123456789n)).toBe(60); 79 }); 80 81 it('returns 0 for 0n negative numbers', () => { 82 expect(BIM.log2(0n)).toBe(0); 83 expect(BIM.log2(-123n)).toBe(0); 84 }); 85 }); 86 87 describe('quant', () => { 88 it('should round an int to the nearest multiple of a stepsize', () => { 89 expect(BIM.quant(0n, 2n)).toEqual(0n); 90 expect(BIM.quant(1n, 2n)).toEqual(2n); 91 expect(BIM.quant(2n, 2n)).toEqual(2n); 92 expect(BIM.quant(3n, 2n)).toEqual(4n); 93 expect(BIM.quant(4n, 2n)).toEqual(4n); 94 95 expect(BIM.quant(0n, 3n)).toEqual(0n); 96 expect(BIM.quant(1n, 3n)).toEqual(0n); 97 expect(BIM.quant(2n, 3n)).toEqual(3n); 98 expect(BIM.quant(3n, 3n)).toEqual(3n); 99 expect(BIM.quant(4n, 3n)).toEqual(3n); 100 expect(BIM.quant(5n, 3n)).toEqual(6n); 101 expect(BIM.quant(6n, 3n)).toEqual(6n); 102 }); 103 104 it('should return value if stepsize is smaller than 1', () => { 105 expect(BIM.quant(123n, 0n)).toEqual(123n); 106 expect(BIM.quant(123n, -10n)).toEqual(123n); 107 }); 108 }); 109 110 describe('quantFloor', () => { 111 it('should quantize a number to the nearest multiple of a stepsize', () => { 112 expect(BIM.quantFloor(10n, 2n)).toEqual(10n); 113 expect(BIM.quantFloor(11n, 2n)).toEqual(10n); 114 expect(BIM.quantFloor(12n, 2n)).toEqual(12n); 115 expect(BIM.quantFloor(13n, 2n)).toEqual(12n); 116 117 expect(BIM.quantFloor(9n, 4n)).toEqual(8n); 118 expect(BIM.quantFloor(10n, 4n)).toEqual(8n); 119 expect(BIM.quantFloor(11n, 4n)).toEqual(8n); 120 expect(BIM.quantFloor(12n, 4n)).toEqual(12n); 121 expect(BIM.quantFloor(13n, 4n)).toEqual(12n); 122 }); 123 124 it('should handle negative numbers', () => { 125 expect(BIM.quantFloor(-4n, 10n)).toEqual(-10n); 126 expect(BIM.quantFloor(-10n, 10n)).toEqual(-10n); 127 expect(BIM.quantFloor(-11n, 10n)).toEqual(-20n); 128 }); 129 130 it('should return value if stepsize is smaller than 1', () => { 131 expect(BIM.quantFloor(123n, 0n)).toEqual(123n); 132 expect(BIM.quantFloor(123n, -10n)).toEqual(123n); 133 }); 134 }); 135 136 describe('quantCeil', () => { 137 it('should round an int up to the nearest multiple of a stepsize', () => { 138 expect(BIM.quantCeil(10n, 2n)).toEqual(10n); 139 expect(BIM.quantCeil(11n, 2n)).toEqual(12n); 140 expect(BIM.quantCeil(12n, 2n)).toEqual(12n); 141 expect(BIM.quantCeil(13n, 2n)).toEqual(14n); 142 143 expect(BIM.quantCeil(9n, 4n)).toEqual(12n); 144 expect(BIM.quantCeil(10n, 4n)).toEqual(12n); 145 expect(BIM.quantCeil(11n, 4n)).toEqual(12n); 146 expect(BIM.quantCeil(12n, 4n)).toEqual(12n); 147 expect(BIM.quantCeil(13n, 4n)).toEqual(16n); 148 }); 149 150 it('should handle negative numbers', () => { 151 expect(BIM.quantCeil(-4n, 10n)).toEqual(0n); 152 expect(BIM.quantCeil(-10n, 10n)).toEqual(-10n); 153 expect(BIM.quantCeil(-11n, 10n)).toEqual(-10n); 154 }); 155 156 it('should return value if stepsize is smaller than 1', () => { 157 expect(BIM.quantCeil(123n, 0n)).toEqual(123n); 158 expect(BIM.quantCeil(123n, -10n)).toEqual(123n); 159 }); 160 }); 161 162 describe('quantRound', () => { 163 it('should quantize a number to the nearest multiple of a stepsize', () => { 164 expect(BIM.quant(0n, 2n)).toEqual(0n); 165 expect(BIM.quant(1n, 2n)).toEqual(2n); 166 expect(BIM.quant(2n, 2n)).toEqual(2n); 167 expect(BIM.quant(3n, 2n)).toEqual(4n); 168 expect(BIM.quant(4n, 2n)).toEqual(4n); 169 170 expect(BIM.quant(0n, 3n)).toEqual(0n); 171 expect(BIM.quant(1n, 3n)).toEqual(0n); 172 expect(BIM.quant(2n, 3n)).toEqual(3n); 173 expect(BIM.quant(3n, 3n)).toEqual(3n); 174 expect(BIM.quant(4n, 3n)).toEqual(3n); 175 expect(BIM.quant(5n, 3n)).toEqual(6n); 176 expect(BIM.quant(6n, 3n)).toEqual(6n); 177 }); 178 179 it('should return value if stepsize is smaller than 1', () => { 180 expect(BIM.quant(123n, 0n)).toEqual(123n); 181 expect(BIM.quant(123n, -10n)).toEqual(123n); 182 }); 183 }); 184 185 describe('max', () => { 186 it('should return the greater of two numbers', () => { 187 expect(BIM.max(5n, 8n)).toEqual(8n); 188 expect(BIM.max(3n, 7n)).toEqual(7n); 189 expect(BIM.max(6n, 6n)).toEqual(6n); 190 expect(BIM.max(-7n, -12n)).toEqual(-7n); 191 }); 192 }); 193 194 describe('min', () => { 195 it('should return the smaller of two numbers', () => { 196 expect(BIM.min(5n, 8n)).toEqual(5n); 197 expect(BIM.min(3n, 7n)).toEqual(3n); 198 expect(BIM.min(6n, 6n)).toEqual(6n); 199 expect(BIM.min(-7n, -12n)).toEqual(-12n); 200 }); 201 }); 202 203 describe('popcount', () => { 204 it('should return the number of set bits in an integer', () => { 205 expect(BIM.popcount(0n)).toBe(0); 206 expect(BIM.popcount(1n)).toBe(1); 207 expect(BIM.popcount(2n)).toBe(1); 208 expect(BIM.popcount(3n)).toBe(2); 209 expect(BIM.popcount(4n)).toBe(1); 210 expect(BIM.popcount(5n)).toBe(2); 211 expect(BIM.popcount(3462151285050974216n)).toBe(10); 212 }); 213 214 it('should throw when presented with a negative integer', () => { 215 expect(() => BIM.popcount(-1n)).toThrowError( 216 "Can't get popcount of negative number -1", 217 ); 218 }); 219 }); 220 221 describe('ratio', () => { 222 it('should return ratio as number', () => { 223 expect(BIM.ratio(0n, 1n)).toBeCloseTo(0); 224 expect(BIM.ratio(1n, 1n)).toBeCloseTo(1); 225 expect(BIM.ratio(1n, 2n)).toBeCloseTo(0.5); 226 expect(BIM.ratio(1n, 100n)).toBeCloseTo(0.01); 227 expect( 228 BIM.ratio( 229 987654321098765432109876543210n, 230 123456789012345678901234567890n, 231 ), 232 ).toBeCloseTo(8); 233 expect( 234 BIM.ratio( 235 123456789012345678901234567890n, 236 987654321098765432109876543210n, 237 ), 238 ).toBeCloseTo(0.125, 3); 239 }); 240 }); 241 242 describe('abs', () => { 243 test('should return the absolute value of a positive BigInt', () => { 244 const result = BIM.abs(12345678901234567890n); 245 expect(result).toEqual(12345678901234567890n); 246 }); 247 248 test('should return the absolute value of a negative BigInt', () => { 249 const result = BIM.abs(-12345678901234567890n); 250 expect(result).toEqual(12345678901234567890n); 251 }); 252 253 test('should return the absolute value of zero', () => { 254 const result = BIM.abs(0n); 255 expect(result).toEqual(0n); 256 }); 257 }); 258}); 259