@@ -1427,27 +1427,22 @@ public protocol BinaryInteger :
1427
1427
/// - Parameter source: An integer to convert to this type.
1428
1428
init < T : BinaryInteger> ( clamping source: T)
1429
1429
1430
- /// Returns the n-th word, counting from the least significant to most
1431
- /// significant, of this value's binary representation.
1432
- ///
1433
- /// The `_word(at:)` method returns negative values in two's complement
1434
- /// representation, regardless of a type's underlying implementation. If `n`
1435
- /// is greater than the number of words in this value's current
1436
- /// representation, the result is `0` for positive numbers and `~0` for
1437
- /// negative numbers.
1438
- ///
1439
- /// - Parameter n: The word to return, counting from the least significant to
1440
- /// most significant. `n` must be greater than or equal to zero.
1441
- /// - Returns: An word-sized, unsigned integer with the bit pattern of the
1442
- /// n-th word of this value.
1443
- func _word( at n: Int ) -> UInt
1444
-
1445
- // FIXME(integers): add doc comments
1446
- // FIXME: Should be `Words : Collection where Words.Iterator.Element == UInt`
1430
+ // FIXME: Should be `Words : Collection where Words.Element == UInt`
1447
1431
// See <rdar://problem/31798916> for why it isn't.
1448
- associatedtype Words
1432
+ /// A type that represents the words of a binary integer.
1433
+ /// Must implement the `Collection` protocol with an `UInt` element type.
1434
+ associatedtype Words : Sequence where Words. Element == UInt
1435
+
1436
+ /// Returns a collection containing the words of this value's binary
1437
+ /// representation, in order from the least significant to most significant.
1438
+ ///
1439
+ /// Negative values are returned in two's complement representation,
1440
+ /// regardless of the type's underlying implementation.
1449
1441
var words : Words { get }
1450
1442
1443
+ /// The least significant word in this value's binary representation.
1444
+ var _lowUWord : UInt { get }
1445
+
1451
1446
/// The number of bits in the current binary representation of this value.
1452
1447
///
1453
1448
/// This property is a constant for instances of fixed-width integer
@@ -1543,13 +1538,10 @@ extension BinaryInteger {
1543
1538
return ( self > ( 0 as Self ) ? 1 : 0 ) - ( self < ( 0 as Self ) ? 1 : 0 )
1544
1539
}
1545
1540
1546
- /// The number of words used for the current binary representation of this
1547
- /// value.
1548
- ///
1549
- /// This property is a constant for instances of fixed-width integer types.
1550
1541
@_transparent
1551
- public var _countRepresentedWords : Int {
1552
- return ( self . bitWidth + ${ word_bits} - 1 ) / ${ word_bits}
1542
+ public var _lowUWord : UInt {
1543
+ var it = words. makeIterator ( )
1544
+ return it. next ( ) ?? 0
1553
1545
}
1554
1546
1555
1547
public func quotientAndRemainder( dividingBy rhs: Self )
@@ -1887,26 +1879,6 @@ extension BinaryInteger {
1887
1879
}
1888
1880
#endif
1889
1881
1890
- extension BinaryInteger {
1891
- // FIXME(integers): Should be removed once words get implemented properly.
1892
- // Meanhile it allows to conform to the BinaryInteger without implementing
1893
- // underscored APIs. https://bugs.swift.org/browse/SR-5275
1894
- public func _word( at n: Int) - > UInt {
1895
- fatalError ( " Should be overridden " )
1896
- }
1897
-
1898
- // FIXME(integers): inefficient. Should get rid of _word(at:) and
1899
- // _countRepresentedWords, and make `words` the basic operation.
1900
- public var words : [ UInt ] {
1901
- var result = [ UInt] ( )
1902
- result. reserveCapacity ( _countRepresentedWords)
1903
- for i in 0 ..< self . _countRepresentedWords {
1904
- result. append ( _word ( at: i) )
1905
- }
1906
- return result
1907
- }
1908
- }
1909
-
1910
1882
//===----------------------------------------------------------------------===//
1911
1883
//===--- FixedWidthInteger ------------------------------------------------===//
1912
1884
//===----------------------------------------------------------------------===//
@@ -2320,24 +2292,24 @@ ${unsafeOperationComment(x.operator)}
2320
2292
}
2321
2293
% end
2322
2294
2323
- @inline ( __always )
2295
+ @_transparent
2324
2296
public init< T : BinaryInteger> ( extendingOrTruncating source: T) {
2325
- if Self . bitWidth <= ${ word_bits} {
2326
- self = Self . init ( _truncatingBits: source. _word ( at : 0 ) )
2297
+ if Self . bitWidth <= ${ word_bits} || source . bitWidth <= $ { word_bits } {
2298
+ self = Self . init ( _truncatingBits: source. _lowUWord )
2327
2299
}
2328
2300
else {
2329
- var result : Self = source < ( 0 as T ) ? ~ 0 : 0
2330
- // start with the most significant word
2331
- var n = source. _countRepresentedWords
2332
- while n >= 0 {
2333
- // masking is OK here because this we have already ensured
2334
- // that Self.bitWidth > ${word_bits}. Not masking results in
2301
+ let neg = source < ( 0 as T )
2302
+ var result : Self = neg ? ~ 0 : 0
2303
+ var shift : Self = 0
2304
+ let width = Self ( _truncatingBits: Self . bitWidth. _lowUWord)
2305
+ for word in source. words {
2306
+ guard shift < width else { break }
2307
+ // masking shift is OK here because we have already ensured
2308
+ // that shift < Self.bitWidth. Not masking results in
2335
2309
// infinite recursion.
2336
- result &<<= ( ${ word_bits} as Self )
2337
- result |= Self ( _truncatingBits: source. _word ( at: n) )
2338
- n -= 1
2310
+ result ^= Self ( _truncatingBits: neg ? ~ word : word) &<< shift
2311
+ shift += ${ word_bits}
2339
2312
}
2340
-
2341
2313
self = result
2342
2314
}
2343
2315
}
@@ -2798,22 +2770,6 @@ ${assignmentOperatorComment(x.operator, True)}
2798
2770
) . _lowUWord. _value)
2799
2771
}
2800
2772
2801
- @_transparent
2802
- public func _word( at n: Int) - > UInt {
2803
- _precondition ( n >= 0 , " Negative word index " )
2804
- if _fastPath ( n < _countRepresentedWords) {
2805
- let shift = UInt ( n. _value) &* ${ word_bits}
2806
- let bitWidth = UInt ( self . bitWidth. _value)
2807
- _sanityCheck ( shift < bitWidth)
2808
- return ( self &>> ${ Self} ( _truncatingBits: shift) ) . _lowUWord
2809
- }
2810
- % if signed:
2811
- return self < ( 0 as ${ Self} ) ? ~ 0 : 0
2812
- % else:
2813
- return 0
2814
- % end
2815
- }
2816
-
2817
2773
% if Self == 'UInt' or ( bits > word_bits and not signed) :
2818
2774
// FIXME should be RandomAccessCollection
2819
2775
public struct Words : BidirectionalCollection {
0 commit comments