blob: d603b57f5fcb9127944781200de42989d50f1633 [file] [log] [blame]
// Copyright (c) 2022, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
// Shared functionality used by multiple classes and their implementations.
int validateRadix(int radix) =>
RangeError.checkValueInInterval(radix, 2, 36, 'radix');
/// Converts radix digits into their numeric values.
///
/// Converts the characters `0`-`9` into the values 0 through 9,
/// and the letters `a`-`z` or `A`-`Z` into values 10 through 35,
/// and return that value.
/// Any other character returns a value above 35, which means it's
/// not a valid digit in any radix in the range 2 through 36.
int decodeDigit(int c) {
// Hex digit char codes
const int c0 = 48; // '0'.codeUnitAt(0)
const int ca = 97; // 'a'.codeUnitAt(0)
int digit = c ^ c0;
if (digit < 10) return digit;
int letter = (c | 0x20) - ca;
if (letter >= 0) {
// Returns values above 36 for invalid digits.
// The value is checked against the actual radix where the return
// value is used, so this is safe.
return letter + 10;
} else {
return 255; // Never a valid radix.
}
}
// Assumes i is <= 32-bit
int numberOfLeadingZeros(int i) {
i |= i >> 1;
i |= i >> 2;
i |= i >> 4;
i |= i >> 8;
i |= i >> 16;
return bitCount(~i);
}
int numberOfTrailingZeros(int i) => bitCount((i & -i) - 1);
// Assumes i is <= 32-bit.
int bitCount(int i) {
// See "Hacker's Delight", section 5-1, "Counting 1-Bits".
// The basic strategy is to use "divide and conquer" to
// add pairs (then quads, etc.) of bits together to obtain
// sub-counts.
//
// A straightforward approach would look like:
//
// i = (i & 0x55555555) + ((i >> 1) & 0x55555555);
// i = (i & 0x33333333) + ((i >> 2) & 0x33333333);
// i = (i & 0x0F0F0F0F) + ((i >> 4) & 0x0F0F0F0F);
// i = (i & 0x00FF00FF) + ((i >> 8) & 0x00FF00FF);
// i = (i & 0x0000FFFF) + ((i >> 16) & 0x0000FFFF);
//
// The code below removes unnecessary &'s and uses a
// trick to remove one instruction in the first line.
i -= (i >> 1) & 0x55555555;
i = (i & 0x33333333) + ((i >> 2) & 0x33333333);
i = (i + (i >> 4)) & 0x0F0F0F0F;
i += i >> 8;
i += i >> 16;
return i & 0x0000003F;
}