Skip to content

Commit 86a2ee9

Browse files
committed
Prepare for v4.0+7.
1 parent 7270622 commit 86a2ee9

12 files changed

+276
-326
lines changed

CHANGELOG.md

+6
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,12 @@
99
1010
[file an issue]: https://github.com/matanlurey/binary.dart/issues
1111

12+
## 4.0.0-alpha+7
13+
14+
- Added `<Int>.lsb`.
15+
- Removed bit-operations from `IntExtension`; they are too easy to use
16+
incorrectly in the JS VM.
17+
1218
## 4.0.0-alpha+6
1319

1420
- Just kidding, `checkRange` will return `{{Int}}` if no error is thrown.

lib/src/descriptor.dart

+51-7
Original file line numberDiff line numberDiff line change
@@ -185,7 +185,7 @@ final class IntDescriptor<T> {
185185
int countOnes(int v) {
186186
var count = 0;
187187
for (var i = 0; i < width; i++) {
188-
if (v.nthBit(i)) {
188+
if (nthBit(v, i)) {
189189
count++;
190190
}
191191
}
@@ -198,7 +198,7 @@ final class IntDescriptor<T> {
198198
int countLeadingOnes(int v) {
199199
var count = 0;
200200
for (var i = width - 1; i >= 0; i--) {
201-
if (v.nthBit(i)) {
201+
if (nthBit(v, i)) {
202202
count++;
203203
} else {
204204
break;
@@ -213,7 +213,7 @@ final class IntDescriptor<T> {
213213
int countLeadingZeros(int v) {
214214
var count = 0;
215215
for (var i = width - 1; i >= 0; i--) {
216-
if (!v.nthBit(i)) {
216+
if (!nthBit(v, i)) {
217217
count++;
218218
} else {
219219
break;
@@ -228,7 +228,7 @@ final class IntDescriptor<T> {
228228
int countTrailingOnes(int v) {
229229
var count = 0;
230230
for (var i = 0; i < width; i++) {
231-
if (v.nthBit(i)) {
231+
if (nthBit(v, i)) {
232232
count++;
233233
} else {
234234
break;
@@ -243,7 +243,7 @@ final class IntDescriptor<T> {
243243
int countTrailingZeros(int v) {
244244
var count = 0;
245245
for (var i = 0; i < width; i++) {
246-
if (!v.nthBit(i)) {
246+
if (!nthBit(v, i)) {
247247
count++;
248248
} else {
249249
break;
@@ -416,14 +416,18 @@ final class IntDescriptor<T> {
416416
@pragma('dart2js:tryInline')
417417
@pragma('vm:prefer-inline')
418418
T uncheckedBinaryAnd(int a, int b) {
419+
return _uncheckedCast(_overflowingBinaryAnd(a, b));
420+
}
421+
422+
int _overflowingBinaryAnd(int a, int b) {
419423
// coverage:ignore-start
420424
if (!_isJsNumerics || unsigned) {
421425
// coverage:ignore-end
422-
return _uncheckedCast(a & b);
426+
return a & b;
423427
}
424428
// coverage:ignore-start
425429
final result = a.toUnsigned(width) & b.toUnsigned(width);
426-
return _uncheckedCast(result.toSigned(width));
430+
return result.toSigned(width);
427431
// coverage:ignore-end
428432
}
429433

@@ -514,6 +518,46 @@ final class IntDescriptor<T> {
514518
// coverage:ignore-end
515519
}
516520

521+
/// Returns whether the n-th bit is set.
522+
@pragma('dart2js:tryInline')
523+
@pragma('vm:prefer-inline')
524+
bool nthBit(int v, int n) {
525+
// Same as `v & (1 << n) != 0`.
526+
return _overflowingBinaryAnd(v, overflowingShiftLeft(1, n)) != 0;
527+
}
528+
529+
/// Returns `true` iff `value == 2^n` for some integer `n`.
530+
@pragma('dart2js:tryInline')
531+
@pragma('vm:prefer-inline')
532+
bool isPowerOf2(int v) {
533+
// Same as `v > 0 && (v & (v - 1)) == 0`.
534+
return v > 0 && uncheckedBinaryAnd(v, v - 1) == 0;
535+
}
536+
537+
/// Returns the smallest power of two greater than or equal to `v`.
538+
///
539+
/// If `v` is already a power of two, it is returned.
540+
///
541+
/// `v` must be a positive integer.
542+
@pragma('dart2js:tryInline')
543+
@pragma('vm:prefer-inline')
544+
int overflowingNextPowerOf2(int v) {
545+
if (isPowerOf2(v)) {
546+
return v;
547+
}
548+
return overflowingShiftLeft(1, v.log2() + 1);
549+
}
550+
551+
/// Calculates the smallest value greater than or equal to `this` that is
552+
/// a multiple of [n].
553+
///
554+
/// `n` must be a positive integer.
555+
@pragma('dart2js:tryInline')
556+
@pragma('vm:prefer-inline')
557+
int overflowingNextMultipleOf(int v, int n) {
558+
return ((v + n - 1) ~/ RangeError.checkNotNegative(n)) * n;
559+
}
560+
517561
/// Returns [v] as a binary string.
518562
String toBinaryString(int v, {bool padded = true}) {
519563
var result = v.toUnsigned(width).toRadixString(2);

lib/src/extension.dart

+1-66
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ import 'dart:math' as math;
55
/// This extension provides additional functionality for integers that is not
66
/// provided by the standard library. This includes convenience methods for
77
/// accessing `dart:math` functions, as well as behavior that is not provided by
8-
/// the standard library such as [midpoint] and [isPowerOf2].
8+
/// the standard library such as [midpoint].
99
///
1010
/// Methods in [IntExtension] make no assumptions about the size of the
1111
/// integer.
@@ -119,69 +119,4 @@ extension IntExtension on int {
119119
// Uses ~/ to ensure that the operation is the same in the VM and JS.
120120
return (this + other) ~/ 2;
121121
}
122-
123-
/// Returns `true` iff `value == 2^n` for some integer `n`.
124-
///
125-
/// ## Example
126-
///
127-
/// ```dart
128-
/// 8.isPowerOf2(); // true
129-
/// 9.isPowerOf2(); // false
130-
/// ```
131-
@pragma('dart2js:tryInline')
132-
@pragma('vm:prefer-inline')
133-
bool isPowerOf2() => this > 0 && (this & (this - 1)) == 0;
134-
135-
/// Returns whether the n-th bit is set.
136-
///
137-
/// ## Example
138-
///
139-
/// ```dart
140-
/// 0x0F.nthBit(0); // true
141-
/// 0x0F.nthBit(1); // true
142-
/// 0x0F.nthBit(2); // true
143-
/// 0x0F.nthBit(3); // true
144-
/// 0x0F.nthBit(4); // false
145-
/// ```
146-
@pragma('dart2js:tryInline')
147-
@pragma('vm:prefer-inline')
148-
bool nthBit(int n) => (this & (1 << n)) != 0;
149-
150-
/// Returns whether the n-th bit is set.
151-
///
152-
/// This is an alias for [nthBit].
153-
bool operator [](int n) => nthBit(n);
154-
155-
/// Returns the smallest power of two greater than or equal to `this`.
156-
///
157-
/// If `this` is already a power of two, it is returned.
158-
///
159-
/// `this` must be a positive integer.
160-
///
161-
/// ## Example
162-
///
163-
/// ```dart
164-
/// 7.nextPowerOf2(); // 8
165-
/// 8.nextPowerOf2(); // 8
166-
/// ```
167-
@pragma('dart2js:tryInline')
168-
@pragma('vm:prefer-inline')
169-
int nextPowerOf2() => isPowerOf2() ? this : 1 << (log2() + 1);
170-
171-
/// Calculates the smallest value greater than or equal to `this` that is
172-
/// a multiple of [n].
173-
///
174-
/// `n` must be a positive integer.
175-
///
176-
/// ## Example
177-
///
178-
/// ```dart
179-
/// 7.nextMultipleOf(3); // 9
180-
/// 8.nextMultipleOf(3); // 9
181-
/// ```
182-
@pragma('dart2js:tryInline')
183-
@pragma('vm:prefer-inline')
184-
int nextMultipleOf(int n) {
185-
return ((this + n - 1) ~/ RangeError.checkNotNegative(n)) * n;
186-
}
187122
}

lib/src/int16.dart

+31-12
Original file line numberDiff line numberDiff line change
@@ -98,7 +98,7 @@ extension type const Int16._(int _) implements int {
9898
static bool isValid(int v) => v >= minInt && v <= maxInt;
9999

100100
/// Returns [value] if its in a valid range for Int16.
101-
static Int16 checkRange(int value) {
101+
factory Int16.checkRange(int value) {
102102
RangeError.checkValueInInterval(value, minInt, maxInt, 'value');
103103
return Int16.fromUnchecked(value);
104104
}
@@ -335,13 +335,18 @@ extension type const Int16._(int _) implements int {
335335
}
336336

337337
/// Returns whether the n-th bit is set.
338-
bool nthBit(int n) => _.nthBit(n);
338+
bool nthBit(int n) => _descriptor.nthBit(_, n);
339339

340340
/// Returns whether the n-th bit is set.
341341
///
342342
/// This is an alias for [nthBit].
343343
bool operator [](int n) => nthBit(n);
344344

345+
/// Returns whether the least significant bit is set.
346+
///
347+
/// This is equivalent to `nthBit(0)`.
348+
bool get lsb => nthBit(0);
349+
345350
/// Returns whether the most significant bit is set.
346351
///
347352
/// This is equivalent to `nthBit(width - 1)`.
@@ -399,7 +404,9 @@ extension type const Int16._(int _) implements int {
399404
/// ```dart
400405
/// Int16(3).nextPowerOf2(); // 4
401406
/// ```
402-
Int16 nextPowerOf2() => Int16(_.nextPowerOf2());
407+
Int16 nextPowerOf2() {
408+
return Int16(_descriptor.overflowingNextPowerOf2(_));
409+
}
403410

404411
/// Returns the smallest power of two greater than or equal to `this`.
405412
///
@@ -408,7 +415,9 @@ extension type const Int16._(int _) implements int {
408415
/// `this` must be a positive integer.
409416
///
410417
/// If the result is out of range, the behavior is undefined.
411-
Int16 uncheckedNextPowerOf2() => Int16.fromUnchecked(_.nextPowerOf2());
418+
Int16 uncheckedNextPowerOf2() {
419+
return Int16.fromUnchecked(_descriptor.overflowingNextPowerOf2(_));
420+
}
412421

413422
/// Returns the smallest power of two greater than or equal to `this`.
414423
///
@@ -428,7 +437,9 @@ extension type const Int16._(int _) implements int {
428437
/// ```dart
429438
/// Int16(3).tryNextPowerOf2(); // 4
430439
/// ```
431-
Int16? tryNextPowerOf2() => tryFrom(_.nextPowerOf2());
440+
Int16? tryNextPowerOf2() {
441+
return tryFrom(_descriptor.overflowingNextPowerOf2(_));
442+
}
432443

433444
/// Returns the smallest power of two greater than or equal to `this`.
434445
///
@@ -448,7 +459,9 @@ extension type const Int16._(int _) implements int {
448459
/// ```dart
449460
/// Int16(3).wrappedNextPowerOf2(); // 4
450461
/// ```
451-
Int16 wrappedNextPowerOf2() => Int16.fromWrapped(_.nextPowerOf2());
462+
Int16 wrappedNextPowerOf2() {
463+
return Int16.fromWrapped(_descriptor.overflowingNextPowerOf2(_));
464+
}
452465

453466
/// Returns the smallest power of two greater than or equal to `this`.
454467
///
@@ -468,7 +481,9 @@ extension type const Int16._(int _) implements int {
468481
/// ```dart
469482
/// Int16(3).clampedNextPowerOf2(); // 4
470483
/// ```
471-
Int16 clampedNextPowerOf2() => Int16.fromClamped(_.nextPowerOf2());
484+
Int16 clampedNextPowerOf2() {
485+
return Int16.fromClamped(_descriptor.overflowingNextPowerOf2(_));
486+
}
472487

473488
/// Calculates the smallest value greater than or equal to `this` that is
474489
/// a multiple of [n].
@@ -488,7 +503,9 @@ extension type const Int16._(int _) implements int {
488503
/// ```dart
489504
/// Int16(3).nextMultipleOf(2); // 4
490505
/// ```
491-
Int16 nextMultipleOf(Int16 n) => Int16(_.nextMultipleOf(n._));
506+
Int16 nextMultipleOf(Int16 n) {
507+
return Int16(_descriptor.overflowingNextMultipleOf(_, n));
508+
}
492509

493510
/// Calculates the smallest value greater than or equal to `this` that is
494511
///
@@ -498,7 +515,7 @@ extension type const Int16._(int _) implements int {
498515
///
499516
/// If the result is out of range, the behavior is undefined.
500517
Int16 uncheckedNextMultipleOf(Int16 n) {
501-
return Int16.fromUnchecked(_.nextMultipleOf(n._));
518+
return Int16.fromUnchecked(_descriptor.overflowingNextMultipleOf(_, n));
502519
}
503520

504521
/// Calculates the smallest value greater than or equal to `this` that is
@@ -519,7 +536,9 @@ extension type const Int16._(int _) implements int {
519536
/// ```dart
520537
/// Int16(3).tryNextMultipleOf(2); // 4
521538
/// ```
522-
Int16? tryNextMultipleOf(Int16 n) => tryFrom(_.nextMultipleOf(n._));
539+
Int16? tryNextMultipleOf(Int16 n) {
540+
return tryFrom(_descriptor.overflowingNextMultipleOf(_, n));
541+
}
523542

524543
/// Calculates the smallest value greater than or equal to `this` that is
525544
/// a multiple of [n].
@@ -540,7 +559,7 @@ extension type const Int16._(int _) implements int {
540559
/// Int16(3).wrappedNextMultipleOf(2); // 4
541560
/// ```
542561
Int16 wrappedNextMultipleOf(Int16 n) {
543-
return Int16.fromWrapped(_.nextMultipleOf(n._));
562+
return Int16.fromWrapped(_descriptor.overflowingNextMultipleOf(_, n));
544563
}
545564

546565
/// Calculates the smallest value greater than or equal to `this` that is
@@ -562,7 +581,7 @@ extension type const Int16._(int _) implements int {
562581
/// Int16(3).clampedNextMultipleOf(2); // 4
563582
/// ```
564583
Int16 clampedNextMultipleOf(Int16 n) {
565-
return Int16.fromClamped(_.nextMultipleOf(n._));
584+
return Int16.fromClamped(_descriptor.overflowingNextMultipleOf(_, n));
566585
}
567586

568587
/// Returns the number of `1`s in the binary representation of `this`.

0 commit comments

Comments
 (0)