fd3ec3b96b
Fixes https://github.com/dart-lang/sdk/issues/63400 Issue: https://github.com/dart-lang/sdk/issues/61635 Change-Id: I45d4603212b1c8205ea8b0f76ea6b5e24bc06f2d Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/504683 Reviewed-by: Slava Egorov <vegorov@google.com> Commit-Queue: Alexander Markov <alexmarkov@google.com>
102 lines
3.2 KiB
Dart
102 lines
3.2 KiB
Dart
// Copyright (c) 2025, 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.
|
|
|
|
import 'dart:typed_data';
|
|
|
|
/// Compares elements of the given lists.
|
|
bool listEquals(List<Object?> a, List<Object?> b) {
|
|
if (a.length != b.length) return false;
|
|
for (var i = 0; i < a.length; i++) {
|
|
if (a[i] != b[i]) return false;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
/// Mixes hash code with a given [value] to produce a derived hash code.
|
|
///
|
|
/// Unlike [Object.hash], this function is guaranteed to be
|
|
/// stable over different runs, which is needed to keep compiler
|
|
/// fully deterministic.
|
|
int combineHash(int hash, int value) {
|
|
hash = 0x1fffffff & (hash + value);
|
|
hash = 0x1fffffff & (hash + ((0x0007ffff & hash) << 10));
|
|
return hash ^ (hash >> 6);
|
|
}
|
|
|
|
/// Finishes hash code construction after combining multiple values.
|
|
int finalizeHash(int hash) {
|
|
hash = 0x1fffffff & (hash + ((0x03ffffff & hash) << 3));
|
|
hash = hash ^ (hash >> 11);
|
|
return 0x1fffffff & (hash + ((0x00003fff & hash) << 15));
|
|
}
|
|
|
|
/// Returns combined hash code of [list] elements.
|
|
///
|
|
/// Unlike [Object.hashAll], this function is guaranteed to be
|
|
/// stable over different runs, which is needed to keep compiler
|
|
/// fully deterministic.
|
|
int listHashCode(List<Object?> list) {
|
|
var hash = 1;
|
|
for (final e in list) {
|
|
hash = combineHash(hash, e.hashCode);
|
|
}
|
|
return finalizeHash(hash);
|
|
}
|
|
|
|
/// Return true iff [x] is a power of 2.
|
|
bool isPowerOf2(int x) => (x != 0) && (x & (x - 1)) == 0;
|
|
|
|
/// Return log2 of the given [x], where [x] is a power of 2.
|
|
int log2OfPowerOf2(int x) {
|
|
assert(isPowerOf2(x));
|
|
return x > 0 ? x.bitLength - 1 : 63;
|
|
}
|
|
|
|
/// Rounds non-negative [value] down to the nearest multiple of [alignment].
|
|
/// [alignment] must be a power of 2.
|
|
@pragma("vm:prefer-inline")
|
|
int roundDown(int value, int alignment) {
|
|
assert(value >= 0);
|
|
assert(isPowerOf2(alignment));
|
|
return value & ~(alignment - 1);
|
|
}
|
|
|
|
/// Rounds non-negative [value] up to the nearest multiple of [alignment].
|
|
/// [alignment] must be a power of 2.
|
|
@pragma("vm:prefer-inline")
|
|
int roundUp(int value, int alignment) {
|
|
assert(value >= 0);
|
|
return roundDown(value + alignment - 1, alignment);
|
|
}
|
|
|
|
final ByteData _conversionBuffer = ByteData(8);
|
|
|
|
/// Integer value of the chosen canonical NaN value.
|
|
const int canonicalNaNBits = 0x7FF80000_00000000;
|
|
|
|
/// Reinterpret double [value] as int without changing bits,
|
|
/// except for NaN values.
|
|
/// Any NaN value is converted to [canonicalNaNBits].
|
|
int doubleToIntBits(double value) {
|
|
if (value.isNaN) {
|
|
return canonicalNaNBits;
|
|
}
|
|
_conversionBuffer.setFloat64(0, value, Endian.little);
|
|
return _conversionBuffer.getInt64(0, Endian.little);
|
|
}
|
|
|
|
/// Reinterpret int [value] as double without changing bits,
|
|
/// except for NaN values.
|
|
/// Any NaN value is converted to [double.nan].
|
|
double intBitsToDouble(int value) {
|
|
if ((value & 0x7FF00000_00000000 == 0x7FF00000_00000000) &&
|
|
(value & 0x000FFFFF_FFFFFFFF != 0)) {
|
|
return double.nan;
|
|
}
|
|
_conversionBuffer.setInt64(0, value, Endian.little);
|
|
final d = _conversionBuffer.getFloat64(0, Endian.little);
|
|
assert(!d.isNaN);
|
|
return d;
|
|
}
|