@@ -1342,9 +1342,6 @@ public protocol BinaryInteger :
1342
1342
Hashable, Numeric, CustomStringConvertible, Strideable
1343
1343
where Magnitude : BinaryInteger, Magnitude . Magnitude == Magnitude
1344
1344
{
1345
- // FIXME(ABI) (Recursive Protocol Constraints): should add:
1346
- // where Magnitude : BinaryInteger
1347
-
1348
1345
/// A Boolean value indicating whether this type is a signed integer type.
1349
1346
///
1350
1347
/// *Signed* integer types can represent both positive and negative values.
@@ -2929,6 +2926,7 @@ ${assignmentOperatorComment(x.operator, True)}
2929
2926
}
2930
2927
2931
2928
/// A representation of this integer with the byte order swapped.
2929
+ @_transparent
2932
2930
public var byteSwapped: ${ Self} {
2933
2931
% if bits <= 8 :
2934
2932
return self
@@ -3186,10 +3184,10 @@ public struct DoubleWidth<Base : FixedWidthInteger> :
3186
3184
self . init ( ( 0 , 0 ) )
3187
3185
}
3188
3186
3189
- // integer
3187
+ // BinaryInteger
3190
3188
//
3191
3189
public var magnitude : DoubleWidth < Low > {
3192
- if Base . isSigned && _storage. high < 0 {
3190
+ if Base . isSigned && _storage. high < ( 0 as High ) {
3193
3191
return self == . min
3194
3192
? DoubleWidth . max. magnitude &+ 1
3195
3193
: ( 0 - self ) . magnitude
@@ -3216,18 +3214,18 @@ public struct DoubleWidth<Base : FixedWidthInteger> :
3216
3214
}
3217
3215
return lhs. _storage. low < rhs. _storage. low
3218
3216
}
3219
-
3217
+
3220
3218
public init< T : BinaryInteger> ( _ source: T) {
3221
3219
self . init ( exactly: source) !
3222
3220
}
3223
3221
3224
3222
public init? < T : BinaryInteger> ( exactly source: T) {
3225
3223
// Can't represent a negative 'source' if Base is unsigned
3226
- guard source >= 0 || DoubleWidth< Base > . isSigned else { return nil }
3224
+ guard source >= 0 || DoubleWidth . isSigned else { return nil }
3227
3225
3228
3226
// Is 'source' is entirely representable in Low?
3229
3227
if let low = Low ( exactly: source. magnitude) {
3230
- if source < 0 {
3228
+ if source < ( 0 as T ) {
3231
3229
self . init ( ( ~ 0 , ~ low + 1 ) )
3232
3230
} else {
3233
3231
self . init ( ( 0 , low) )
@@ -3243,7 +3241,7 @@ public struct DoubleWidth<Base : FixedWidthInteger> :
3243
3241
self . init ( ( high, low) )
3244
3242
}
3245
3243
}
3246
-
3244
+
3247
3245
public init< T : FloatingPoint> ( _ source: T) {
3248
3246
fatalError ( )
3249
3247
}
@@ -3255,18 +3253,17 @@ public struct DoubleWidth<Base : FixedWidthInteger> :
3255
3253
public init< T : BinaryFloatingPoint> ( _ source: T)
3256
3254
where T. RawSignificand : FixedWidthInteger
3257
3255
{
3258
- assert ( source. isFinite, " Can't create a DoubleWidth< \( Base . self) > from infinity " )
3259
- assert ( !source. isNaN, " Can't create a DoubleWidth< \( Base . self) > from a NaN " )
3256
+ _precondition ( source. isFinite, " Can't create a DoubleWidth from a non-finite value " )
3260
3257
self . init ( exactly: source. rounded ( . towardZero) ) !
3261
3258
}
3262
3259
3263
3260
public init? < T : BinaryFloatingPoint> ( exactly source: T)
3264
3261
where T. RawSignificand : FixedWidthInteger
3265
3262
{
3266
3263
// Need a finite value
3267
- guard source. isFinite && !source . isNaN else { return nil }
3264
+ guard source. isFinite else { return nil }
3268
3265
3269
- // Don't need to go further with zero
3266
+ // Don't need to go further with zero.
3270
3267
if source. isZero {
3271
3268
self . init ( 0 )
3272
3269
return
@@ -3276,28 +3273,29 @@ public struct DoubleWidth<Base : FixedWidthInteger> :
3276
3273
guard source. exponent >= 0 else { return nil }
3277
3274
3278
3275
typealias Raw = T . RawSignificand
3279
- let bitPattern : Raw = source. significandBitPattern | ( ( 1 as Raw ) &<< Raw ( T . significandBitCount) )
3280
- let offset : Int = T . significandBitCount - Int( source. exponent)
3276
+ let bitPattern = source. significandBitPattern |
3277
+ ( ( 1 as Raw ) &<< Raw ( T . significandBitCount) )
3278
+ let offset = T . significandBitCount - Int( source. exponent)
3281
3279
3282
3280
// FIXME: spurious compile error when 'where' clause above is removed:
3283
3281
// error: non-nominal type 'T.RawSignificand' does not support explicit initialization
3284
- let fractionPart : Raw = bitPattern &<< Raw ( Int ( Raw . bitWidth - offset) )
3282
+ let fractionPart : Raw = bitPattern &<< Raw ( Raw . bitWidth - offset)
3285
3283
guard fractionPart == 0 else {
3286
3284
return nil
3287
3285
}
3288
3286
3289
3287
let integerPart : Raw = bitPattern &>> Raw ( offset)
3290
3288
3291
- // Exit early for zero
3292
- guard integerPart > 0 else {
3293
- self . init ( 0 )
3294
- return
3295
- }
3289
+ // Should have caught any actual zero values above
3290
+ _sanityCheck ( integerPart > ( 0 as Raw ) )
3296
3291
3297
3292
if source. sign == . minus {
3298
3293
if !DoubleWidth. isSigned || integerPart &- 1 > DoubleWidth . max {
3299
3294
return nil
3300
3295
}
3296
+ // Have to juggle, or else the intermediate step of creating a value
3297
+ // with Self.min's magnitude will overflow. It's okay to use wrapping
3298
+ // subtraction because integerPart > 0.
3301
3299
self . init ( integerPart &- 1 )
3302
3300
self = 0 &- self &- 1
3303
3301
} else {
@@ -3311,20 +3309,22 @@ public struct DoubleWidth<Base : FixedWidthInteger> :
3311
3309
fatalError ( " word(at:) is not supported on this type " )
3312
3310
}
3313
3311
if n > 0 {
3312
+ // Since `Base` is narrower than word, any non-zero word will give us
3313
+ // the correct value here (0 or ~0).
3314
3314
return _storage. high. _word ( at: n)
3315
3315
}
3316
- return _storage. low. _word ( at: 0 ) | _storage. high. _word ( at: 0 ) << numericCast ( Base . bitWidth)
3316
+ return _storage. low. _word ( at: 0 ) |
3317
+ ( _storage. high. _word ( at: 0 ) << numericCast ( Base . bitWidth) )
3317
3318
} else {
3318
3319
// multiples of ${word_bits} only
3319
3320
if Base . bitWidth % ${ word_bits} != 0 {
3320
3321
fatalError ( " word(at:) is not supported on this type " )
3321
3322
}
3322
3323
3323
3324
// TODO: move to Int128 just like init(_builtinIntegerLiteral:) ?
3324
- let wordsInBase = Base . bitWidth / ${ word_bits}
3325
- return ( n < wordsInBase) ?
3325
+ return ( n < _storage. low. countRepresentedWords) ?
3326
3326
_storage. low. _word ( at: n) :
3327
- _storage. high. _word ( at: n - wordsInBase )
3327
+ _storage. high. _word ( at: n - _storage . low . countRepresentedWords )
3328
3328
}
3329
3329
}
3330
3330
@@ -3356,7 +3356,7 @@ public struct DoubleWidth<Base : FixedWidthInteger> :
3356
3356
let ( high, highOverflow) =
3357
3357
_storage. high . ${ x. name} ReportingOverflow( rhs. _storage. high)
3358
3358
let isLowOverflow = lowOverflow == . overflow
3359
- let result = ( high & ${ x. operator} ( isLowOverflow ? High ( 1 ) : High ( 0 ) ) , low)
3359
+ let result = ( high & ${ x. operator} ( isLowOverflow ? 1 : 0 ) , low)
3360
3360
let overflow = ArithmeticOverflow (
3361
3361
highOverflow == . overflow ||
3362
3362
high == ${ highAffectedByLowOverflow} && isLowOverflow
@@ -3372,7 +3372,7 @@ public struct DoubleWidth<Base : FixedWidthInteger> :
3372
3372
let ( carry, product) = multipliedFullWidth ( by: rhs)
3373
3373
let result = DoubleWidth ( extendingOrTruncating: product)
3374
3374
3375
- let isNegative = ( self < 0 ) != ( rhs < 0 )
3375
+ let isNegative = ( self < ( 0 as DoubleWidth ) ) != ( rhs < ( 0 as DoubleWidth ) )
3376
3376
let didCarry = isNegative ? carry != ~ 0 : carry != 0
3377
3377
let hadPositiveOverflow = !isNegative &&
3378
3378
DoubleWidth . isSigned && product. leadingZeroBitCount == 0
@@ -3382,7 +3382,7 @@ public struct DoubleWidth<Base : FixedWidthInteger> :
3382
3382
3383
3383
public func quotientAndRemainder( dividingBy other: DoubleWidth)
3384
3384
- > ( quotient: DoubleWidth, remainder: DoubleWidth) {
3385
- let isNegative = ( self < 0 ) != ( other < 0 )
3385
+ let isNegative = ( self < ( 0 as DoubleWidth ) ) != ( other < ( 0 as DoubleWidth ) )
3386
3386
3387
3387
let rhs = other. magnitude
3388
3388
var q = self . magnitude
@@ -3394,8 +3394,10 @@ public struct DoubleWidth<Base : FixedWidthInteger> :
3394
3394
3395
3395
// Calculate the number of bits before q and rhs line up,
3396
3396
// we can skip that many bits of iteration.
3397
- let initialOffset = q. leadingZeroBitCount + ( DoubleWidth . bitWidth - rhs. leadingZeroBitCount) - 1
3397
+ let initialOffset = q. leadingZeroBitCount +
3398
+ ( DoubleWidth . bitWidth - rhs. leadingZeroBitCount) - 1
3398
3399
3400
+ // TODO(performance): Use &>> instead here?
3399
3401
// Start with remainder capturing the high bits of q.
3400
3402
var r = q >> Magnitude ( DoubleWidth . bitWidth - initialOffset)
3401
3403
q <<= Magnitude ( initialOffset)
@@ -3415,7 +3417,7 @@ public struct DoubleWidth<Base : FixedWidthInteger> :
3415
3417
}
3416
3418
3417
3419
// Sign of remainder matches dividend
3418
- let remainder = self < 0
3420
+ let remainder = self < ( 0 as DoubleWidth )
3419
3421
? 0 - DoubleWidth( r)
3420
3422
: DoubleWidth ( r)
3421
3423
@@ -3428,7 +3430,7 @@ public struct DoubleWidth<Base : FixedWidthInteger> :
3428
3430
3429
3431
public func dividedReportingOverflow( by other: DoubleWidth)
3430
3432
- > ( partialValue: DoubleWidth, overflow: ArithmeticOverflow) {
3431
- if other == 0 || ( other < 0 && self == . min) {
3433
+ if other == 0 || ( DoubleWidth . isSigned && other == - 1 && self == . min) {
3432
3434
return ( self , . overflow)
3433
3435
}
3434
3436
@@ -3437,7 +3439,7 @@ public struct DoubleWidth<Base : FixedWidthInteger> :
3437
3439
3438
3440
public func remainderReportingOverflow( dividingBy other: DoubleWidth)
3439
3441
- > ( partialValue: DoubleWidth, overflow: ArithmeticOverflow) {
3440
- if other == 0 {
3442
+ if other == 0 || ( DoubleWidth . isSigned && other == - 1 && self == . min ) {
3441
3443
return ( self , . overflow)
3442
3444
}
3443
3445
@@ -3446,7 +3448,8 @@ public struct DoubleWidth<Base : FixedWidthInteger> :
3446
3448
3447
3449
public func multipliedFullWidth( by other: DoubleWidth)
3448
3450
- > ( high: DoubleWidth, low: DoubleWidth . Magnitude) {
3449
- let isNegative = DoubleWidth . isSigned && ( self < DoubleWidth ( ) ) != ( other < DoubleWidth ( ) )
3451
+ let isNegative = DoubleWidth . isSigned &&
3452
+ ( self < ( 0 as DoubleWidth ) ) != ( other < ( 0 as DoubleWidth ) )
3450
3453
3451
3454
func mul( _ x: Low , _ y: Low ) -> ( partial: Low , carry: Low ) {
3452
3455
let ( high, low) = x. multipliedFullWidth ( by: y)
@@ -3473,7 +3476,8 @@ public struct DoubleWidth<Base : FixedWidthInteger> :
3473
3476
let mid2 = sum ( b. carry, c. carry, d. partial)
3474
3477
3475
3478
let low = DoubleWidth < Low > ( ( mid1. partial, a. partial) )
3476
- let high = DoubleWidth ( ( High ( mid2. carry + d. carry) , mid1. carry + mid2. partial) )
3479
+ let high = DoubleWidth (
3480
+ ( High ( mid2. carry + d. carry) , mid1. carry + mid2. partial) )
3477
3481
3478
3482
if isNegative {
3479
3483
let ( lowComplement, overflow) = ( ~ low) . addingReportingOverflow ( 1 )
@@ -3504,41 +3508,41 @@ public struct DoubleWidth<Base : FixedWidthInteger> :
3504
3508
% end
3505
3509
3506
3510
public static func <<= ( lhs: inout DoubleWidth, rhs: DoubleWidth) {
3507
- if rhs < DoubleWidth ( ( 0 , 0 ) ) {
3508
- lhs >>= DoubleWidth ( ( 0 , 0 ) ) - rhs
3511
+ if rhs < ( 0 as DoubleWidth ) {
3512
+ lhs >>= 0 - rhs
3509
3513
return
3510
3514
}
3511
3515
3512
- if rhs. _storage. high != 0 as High || rhs. _storage. low >= DoubleWidth . bitWidth {
3513
- lhs = DoubleWidth ( ( 0 , 0 ) )
3516
+ if rhs. _storage. high != 0 || rhs. _storage. low >= DoubleWidth . bitWidth {
3517
+ lhs = 0
3514
3518
return
3515
3519
}
3516
3520
3517
3521
// Shift is exactly the width of `Base`, so low -> high.
3518
- if Int ( rhs. _storage. low) == Base . bitWidth {
3519
- lhs = DoubleWidth ( ( High ( extendingOrTruncating: lhs. _storage. low) , numericCast ( 0 ) ) )
3522
+ if rhs. _storage. low == Base . bitWidth {
3523
+ lhs = DoubleWidth ( ( High ( extendingOrTruncating: lhs. _storage. low) , 0 ) )
3520
3524
return
3521
3525
}
3522
3526
3523
3527
lhs &<<= rhs
3524
3528
}
3525
3529
3526
3530
public static func >>= ( lhs: inout DoubleWidth, rhs: DoubleWidth) {
3527
- if rhs < DoubleWidth ( ( 0 , 0 ) ) {
3528
- lhs <<= DoubleWidth ( ( 0 , 0 ) ) - rhs
3531
+ if rhs < ( 0 as DoubleWidth ) {
3532
+ lhs <<= 0 - rhs
3529
3533
return
3530
3534
}
3531
3535
3532
3536
// Shift is larger than this type's bit width.
3533
- if rhs. _storage. high != 0 as High || rhs. _storage. low >= DoubleWidth . bitWidth {
3534
- lhs = lhs < 0 ? ~ 0 : 0
3537
+ if rhs. _storage. high != 0 || rhs. _storage. low >= DoubleWidth . bitWidth {
3538
+ lhs = lhs < ( 0 as DoubleWidth ) ? ~ 0 : 0
3535
3539
return
3536
3540
}
3537
3541
3538
3542
// Shift is exactly the width of `Base`, so high -> low.
3539
- if rhs. _storage. low == numericCast ( Base . bitWidth) {
3543
+ if rhs. _storage. low == Base . bitWidth {
3540
3544
lhs = DoubleWidth (
3541
- ( lhs < 0 ? ~ 0 : 0 , Low ( extendingOrTruncating: lhs. _storage. high) ) )
3545
+ ( lhs < ( 0 as DoubleWidth ) ? ~ 0 : 0 , Low ( extendingOrTruncating: lhs. _storage. high) ) )
3542
3546
return
3543
3547
}
3544
3548
@@ -3602,8 +3606,8 @@ public struct DoubleWidth<Base : FixedWidthInteger> :
3602
3606
// other
3603
3607
//
3604
3608
public init( _builtinIntegerLiteral x: _MaxBuiltinIntegerType) {
3605
- // FIXME: This won't work if `x` is out of range for `Int `
3606
- self . init ( Int ( _builtinIntegerLiteral: x) )
3609
+ // FIXME: This won't work if `x` is out of range for `Int64 `
3610
+ self . init ( Int64 ( _builtinIntegerLiteral: x) )
3607
3611
}
3608
3612
3609
3613
public var description: String {
@@ -3630,6 +3634,7 @@ public struct DoubleWidth<Base : FixedWidthInteger> :
3630
3634
return _mixInt ( high. hashValue) ^ low. hashValue
3631
3635
}
3632
3636
3637
+ @_transparent
3633
3638
public var byteSwapped: DoubleWidth {
3634
3639
return DoubleWidth ( ( High ( extendingOrTruncating: low. byteSwapped) ,
3635
3640
Low ( extendingOrTruncating: high. byteSwapped) ) )
0 commit comments