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