Skip to content

Commit 13abb9a

Browse files
moiseevairspeedswift
authored andcommitted
[stdlib] BinaryInteger func word(at:) => var words: Words (#8984)
* [stdlib] Underscoring BinaryInteger.word(at:) * [stdlib] Implementing var words in terms of _word(at:)
1 parent 5a706e8 commit 13abb9a

File tree

3 files changed

+51
-22
lines changed

3 files changed

+51
-22
lines changed

stdlib/public/core/Integers.swift.gyb

Lines changed: 27 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1464,7 +1464,7 @@ public protocol BinaryInteger :
14641464
/// Returns the n-th word, counting from the least significant to most
14651465
/// significant, of this value's binary representation.
14661466
///
1467-
/// The `word(at:)` method returns negative values in two's complement
1467+
/// The `_word(at:)` method returns negative values in two's complement
14681468
/// representation, regardless of a type's underlying implementation. If `n`
14691469
/// is greater than the number of words in this value's current
14701470
/// representation, the result is `0` for positive numbers and `~0` for
@@ -1474,7 +1474,13 @@ public protocol BinaryInteger :
14741474
/// most significant. `n` must be greater than or equal to zero.
14751475
/// - Returns: An word-sized, unsigned integer with the bit pattern of the
14761476
/// n-th word of this value.
1477-
func word(at n: Int) -> UInt
1477+
func _word(at n: Int) -> UInt
1478+
1479+
// FIXME(integers): add doc comments
1480+
// FIXME: Should be `Words : Collection where Words.Iterator.Element == UInt`
1481+
// See <rdar://problem/31798916> for why it isn't.
1482+
associatedtype Words
1483+
var words: Words { get }
14781484

14791485
/// The number of bits in the current binary representation of this value.
14801486
///
@@ -1918,6 +1924,18 @@ extension BinaryInteger {
19181924
}
19191925
#endif
19201926

1927+
extension BinaryInteger {
1928+
// FIXME(integers): inefficient. Should get rid of _word(at:) and
1929+
// countRepresentedWords, and make `words` the basic operation.
1930+
public var words: [UInt] {
1931+
var result = [UInt]()
1932+
result.reserveCapacity(countRepresentedWords)
1933+
for i in 0..<self.countRepresentedWords {
1934+
result.append(_word(at: i))
1935+
}
1936+
return result
1937+
}
1938+
}
19211939

19221940
//===----------------------------------------------------------------------===//
19231941
//===--- FixedWidthInteger ------------------------------------------------===//
@@ -2307,7 +2325,7 @@ ${unsafeOperationComment(x.operator)}
23072325
@inline(__always)
23082326
public init<T : BinaryInteger>(extendingOrTruncating source: T) {
23092327
if Self.bitWidth <= ${word_bits} {
2310-
self = Self.init(_truncatingBits: source.word(at: 0))
2328+
self = Self.init(_truncatingBits: source._word(at: 0))
23112329
}
23122330
else {
23132331
var result: Self = source < (0 as T) ? ~0 : 0
@@ -2318,7 +2336,7 @@ ${unsafeOperationComment(x.operator)}
23182336
// that Self.bitWidth > ${word_bits}. Not masking results in
23192337
// infinite recursion.
23202338
result &<<= (${word_bits} as Self)
2321-
result |= Self(_truncatingBits: source.word(at: n))
2339+
result |= Self(_truncatingBits: source._word(at: n))
23222340
n -= 1
23232341
}
23242342

@@ -2866,7 +2884,7 @@ ${operatorComment(x.operator, True)}
28662884
}
28672885

28682886
@_transparent
2869-
public func word(at n: Int) -> UInt {
2887+
public func _word(at n: Int) -> UInt {
28702888
_precondition(n >= 0, "Negative word index")
28712889
if _fastPath(n < countRepresentedWords) {
28722890
let shift = UInt(n._value) &* ${word_bits}
@@ -3303,15 +3321,15 @@ public struct DoubleWidth<T : FixedWidthInteger>
33033321
fatalError()
33043322
}
33053323

3306-
public func word(at n: Int) -> UInt {
3324+
public func _word(at n: Int) -> UInt {
33073325
if T.bitWidth < ${word_bits} || T.bitWidth % ${word_bits} != 0 {
3308-
fatalError("word(at:) is not supported on this type")
3326+
fatalError("_word(at:) is not supported on this type")
33093327
}
33103328
// TODO: move to Int128 just like init(_builtinIntegerLiteral:) ?
33113329
let wordsInT = T.bitWidth / ${word_bits}
33123330
return (n < wordsInT) ?
3313-
_storage.low.word(at: n) :
3314-
_storage.high.word(at: n - wordsInT)
3331+
_storage.low._word(at: n) :
3332+
_storage.high._word(at: n - wordsInT)
33153333
}
33163334

33173335
public static var isSigned: Bool {

test/Prototypes/BigInt.swift

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -122,7 +122,7 @@ public struct _BigInt<Word: FixedWidthInteger & UnsignedInteger> :
122122
let wordRatio = UInt.bitWidth / Word.bitWidth
123123
_sanityCheck(wordRatio != 0)
124124
for i in 0..<source.countRepresentedWords {
125-
var sourceWord = source.word(at: i)
125+
var sourceWord = source._word(at: i)
126126
for _ in 0..<wordRatio {
127127
_data.append(Word(extendingOrTruncating: sourceWord))
128128
sourceWord >>= Word.bitWidth
@@ -660,7 +660,7 @@ public struct _BigInt<Word: FixedWidthInteger & UnsignedInteger> :
660660
}
661661
}
662662

663-
public func word(at n: Int) -> UInt {
663+
public func _word(at n: Int) -> UInt {
664664
let ratio = UInt.bitWidth / Word.bitWidth
665665
_sanityCheck(ratio != 0)
666666

@@ -1293,7 +1293,7 @@ struct Bit : FixedWidthInteger, UnsignedInteger {
12931293
return self
12941294
}
12951295

1296-
func word(at n: Int) -> UInt {
1296+
func _word(at n: Int) -> UInt {
12971297
return UInt(value)
12981298
}
12991299

test/stdlib/Integers.swift.gyb

Lines changed: 21 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -33,12 +33,12 @@ extension FixedWidthInteger {
3333
@discardableResult
3434
// @_transparent
3535
public mutating func replaceUWord(_ n: Int, with newBits: UInt) -> Bool {
36-
let flippedBits = word(at: n) ^ newBits
36+
let flippedBits = _word(at: n) ^ newBits
3737
self ^= Self(_truncatingBits: flippedBits) << (${word_bits} * n)
38-
if word(at: n) != newBits {
38+
if _word(at: n) != newBits {
3939
_log("###### overflow replacing word \(n) with \(newBits.hex)")
4040
}
41-
return word(at: n) == newBits
41+
return _word(at: n) == newBits
4242
}
4343

4444
/// a hex representation of every bit in the number
@@ -54,7 +54,7 @@ extension FixedWidthInteger {
5454
if nibbles % 4 == 0 && nibbles != 0 {
5555
result.insert("_", at: result.startIndex)
5656
}
57-
let lowUWord = x.word(at: 0)
57+
let lowUWord = x._word(at: 0)
5858
result.insert(
5959
hexDigits[Int(lowUWord._value) & 0xF],
6060
at: result.startIndex
@@ -495,16 +495,27 @@ tests.test("Basics") {
495495

496496
tests.test("word") {
497497
let x = UDWord(Int.max)
498-
expectEqual(Int.max._lowUWord, x.word(at: 0))
499-
expectEqual(0, x.word(at: 1))
498+
expectEqual(Int.max._lowUWord, x._word(at: 0))
499+
expectEqual(0, x._word(at: 1))
500500

501501
let y = DWord(Int.min)
502-
expectEqual(Int.min._lowUWord, y.word(at: 0))
503-
expectEqual(~0, y.word(at: 1))
502+
expectEqual(Int.min._lowUWord, y._word(at: 0))
503+
expectEqual(~0, y._word(at: 1))
504504

505505
let z = UInt(~Int.min) + 1
506-
expectEqual(Int.min._lowUWord, z.word(at: 0))
507-
expectEqual(0, z.word(at: 1))
506+
expectEqual(Int.min._lowUWord, z._word(at: 0))
507+
expectEqual(0, z._word(at: 1))
508+
}
509+
510+
tests.test("words") {
511+
expectEqualSequence([UInt.max], (-1 as Int).words)
512+
expectEqualSequence([UInt.max], (-1 as Int8).words)
513+
expectEqualSequence([UInt.max], (-1 as Int16).words)
514+
expectEqualSequence([UInt.max], (-1 as Int32).words)
515+
expectEqualSequence([UInt.max], (-1 as Int64).words)
516+
517+
expectEqualSequence([1], 1.words)
518+
expectEqualSequence([0], 0.words)
508519
}
509520

510521
tests.test("multipliedFullWidth/UInt8") {

0 commit comments

Comments
 (0)