@@ -1426,27 +1426,22 @@ public protocol BinaryInteger :
1426
1426
/// - Parameter source: An integer to convert to this type.
1427
1427
init < T : BinaryInteger> ( clamping source: T)
1428
1428
1429
- /// Returns the n-th word, counting from the least significant to most
1430
- /// significant, of this value's binary representation.
1431
- ///
1432
- /// The `_word(at:)` method returns negative values in two's complement
1433
- /// representation, regardless of a type's underlying implementation. If `n`
1434
- /// is greater than the number of words in this value's current
1435
- /// representation, the result is `0` for positive numbers and `~0` for
1436
- /// negative numbers.
1437
- ///
1438
- /// - Parameter n: The word to return, counting from the least significant to
1439
- /// most significant. `n` must be greater than or equal to zero.
1440
- /// - Returns: An word-sized, unsigned integer with the bit pattern of the
1441
- /// n-th word of this value.
1442
- func _word( at n: Int ) -> UInt
1443
-
1444
- // FIXME(integers): add doc comments
1445
- // FIXME: Should be `Words : Collection where Words.Iterator.Element == UInt`
1429
+ // FIXME: Should be `Words : Collection where Words.Element == UInt`
1446
1430
// See <rdar://problem/31798916> for why it isn't.
1447
- associatedtype Words
1431
+ /// A type that represents the words of a binary integer.
1432
+ /// Must implement the `Collection` protocol with an `UInt` element type.
1433
+ associatedtype Words : Sequence where Words. Element == UInt
1434
+
1435
+ /// Returns a collection containing the words of this value's binary
1436
+ /// representation, in order from the least significant to most significant.
1437
+ ///
1438
+ /// Negative values are returned in two's complement representation,
1439
+ /// regardless of the type's underlying implementation.
1448
1440
var words : Words { get }
1449
1441
1442
+ /// The least significant word in this value's binary representation.
1443
+ var _lowWord : UInt { get }
1444
+
1450
1445
/// The number of bits in the current binary representation of this value.
1451
1446
///
1452
1447
/// This property is a constant for instances of fixed-width integer
@@ -1542,13 +1537,10 @@ extension BinaryInteger {
1542
1537
return ( self > ( 0 as Self ) ? 1 : 0 ) - ( self < ( 0 as Self ) ? 1 : 0 )
1543
1538
}
1544
1539
1545
- /// The number of words used for the current binary representation of this
1546
- /// value.
1547
- ///
1548
- /// This property is a constant for instances of fixed-width integer types.
1549
1540
@_transparent
1550
- public var _countRepresentedWords : Int {
1551
- return ( self . bitWidth + ${ word_bits} - 1 ) / ${ word_bits}
1541
+ public var _lowWord : UInt {
1542
+ var it = words. makeIterator ( )
1543
+ return it. next ( ) ?? 0
1552
1544
}
1553
1545
1554
1546
public func quotientAndRemainder( dividingBy rhs: Self )
@@ -1886,19 +1878,6 @@ extension BinaryInteger {
1886
1878
}
1887
1879
#endif
1888
1880
1889
- extension BinaryInteger {
1890
- // FIXME(integers): inefficient. Should get rid of _word(at:) and
1891
- // _countRepresentedWords, and make `words` the basic operation.
1892
- public var words: [ UInt ] {
1893
- var result = [ UInt] ( )
1894
- result. reserveCapacity ( _countRepresentedWords)
1895
- for i in 0 ..< self . _countRepresentedWords {
1896
- result. append ( _word ( at: i) )
1897
- }
1898
- return result
1899
- }
1900
- }
1901
-
1902
1881
//===----------------------------------------------------------------------===//
1903
1882
//===--- FixedWidthInteger ------------------------------------------------===//
1904
1883
//===----------------------------------------------------------------------===//
@@ -2282,21 +2261,21 @@ ${unsafeOperationComment(x.operator)}
2282
2261
@inline ( __always)
2283
2262
public init< T : BinaryInteger> ( extendingOrTruncating source: T) {
2284
2263
if Self . bitWidth <= ${ word_bits} {
2285
- self = Self . init ( _truncatingBits: source. _word ( at : 0 ) )
2264
+ self = Self . init ( _truncatingBits: source. _lowWord )
2286
2265
}
2287
2266
else {
2288
- var result : Self = source < ( 0 as T ) ? ~ 0 : 0
2289
- // start with the most significant word
2290
- var n = source. _countRepresentedWords
2291
- while n >= 0 {
2292
- // masking is OK here because this we have already ensured
2293
- // that Self.bitWidth > ${word_bits}. Not masking results in
2267
+ let neg = source < ( 0 as T )
2268
+ var result : Self = neg ? ~ 0 : 0
2269
+ var shift : Self = 0
2270
+ let width = Self ( _truncatingBits: Self . bitWidth. _lowWord)
2271
+ for word in source. words {
2272
+ guard shift < width else { break }
2273
+ // masking shift is OK here because we have already ensured
2274
+ // that shift < Self.bitWidth. Not masking results in
2294
2275
// infinite recursion.
2295
- result &<<= ( ${ word_bits} as Self )
2296
- result |= Self ( _truncatingBits: source. _word ( at: n) )
2297
- n -= 1
2276
+ result ^= Self ( _truncatingBits: neg ? ~ word : word) &<< shift
2277
+ shift += ${ word_bits}
2298
2278
}
2299
-
2300
2279
self = result
2301
2280
}
2302
2281
}
@@ -2740,45 +2719,71 @@ ${assignmentOperatorComment(x.operator, True)}
2740
2719
return Int (
2741
2720
${ Self} (
2742
2721
Builtin . int_ctlz_Int ${ bits} ( self . _value, false . _value)
2743
- ) . _lowUWord . _value)
2722
+ ) . _lowWord . _value)
2744
2723
}
2745
2724
2746
2725
@_transparent
2747
2726
public var trailingZeroBitCount: Int {
2748
2727
return Int (
2749
2728
${ Self} (
2750
2729
Builtin . int_cttz_Int ${ bits} ( self . _value, false . _value)
2751
- ) . _lowUWord . _value)
2730
+ ) . _lowWord . _value)
2752
2731
}
2753
2732
2754
2733
@_transparent
2755
2734
public var nonzeroBitCount: Int {
2756
2735
return Int (
2757
2736
${ Self} (
2758
2737
Builtin . int_ctpop_Int ${ bits} ( self . _value)
2759
- ) . _lowUWord . _value)
2738
+ ) . _lowWord . _value)
2760
2739
}
2761
2740
2762
- @_transparent
2763
- public func _word( at n: Int) - > UInt {
2764
- _precondition ( n >= 0 , " Negative word index " )
2765
- if _fastPath ( n < _countRepresentedWords) {
2766
- let shift = UInt ( n. _value) &* ${ word_bits}
2767
- let bitWidth = UInt ( self . bitWidth. _value)
2768
- _sanityCheck ( shift < bitWidth)
2769
- return ( self &>> ${ Self} ( _truncatingBits: shift) ) . _lowUWord
2741
+ // FIXME should be RandomAccessCollection
2742
+ public struct Words : BidirectionalCollection {
2743
+ public typealias Indices = CountableRange< Int>
2744
+ public typealias SubSequence = BidirectionalSlice < ${ Self} . Words>
2745
+
2746
+ var _value: ${ Self}
2747
+
2748
+ public init( _ value: ${ Self} ) {
2749
+ self . _value = value
2750
+ }
2751
+
2752
+ public var count: Int {
2753
+ return ( ${ bits} + ${ word_bits} - 1 ) / ${ word_bits}
2754
+ }
2755
+
2756
+ public var startIndex: Int { return 0 }
2757
+
2758
+ public var endIndex: Int { return count }
2759
+
2760
+ public var indices: Indices { return startIndex ..< endIndex }
2761
+
2762
+ @_transparent
2763
+ public func index( after i: Int) - > Int { return i + 1 }
2764
+
2765
+ @_transparent
2766
+ public func index( before i: Int) - > Int { return i - 1 }
2767
+
2768
+ public subscript( position: Int) - > UInt {
2769
+ get {
2770
+ _precondition ( position >= 0 , " Negative word index " )
2771
+ _precondition ( position < endIndex, " Word index out of range " )
2772
+ let shift = UInt ( position. _value) &* ${ word_bits}
2773
+ _sanityCheck ( shift < UInt ( _value. bitWidth. _value) )
2774
+ return ( _value &>> ${ Self} ( _truncatingBits: shift) ) . _lowWord
2775
+ }
2770
2776
}
2771
- % if signed:
2772
- return self < ( 0 as ${ Self} ) ? ~ 0 : 0
2773
- % else:
2774
- return 0
2775
- % end
2776
2777
}
2777
2778
2779
+ @_transparent
2780
+ public var words: Words {
2781
+ return Words ( self )
2782
+ }
2778
2783
2779
2784
@_transparent
2780
2785
public // transparent
2781
- var _lowUWord : UInt {
2786
+ var _lowWord : UInt {
2782
2787
% truncOrExt = z + 'ext' if bits <= word_bits else 'trunc'
2783
2788
return UInt(
2784
2789
Builtin . ${ truncOrExt} OrBitCast_Int${ bits} _Int${ word_bits} ( _value)
0 commit comments