@@ -625,7 +625,20 @@ extension ${Self}: BinaryFloatingPoint {
625
625
/// almost never is.
626
626
@_inlineable // FIXME(sil-serialize-all)
627
627
public var ulp : ${ Self} {
628
- if !isFinite { return ${ Self} . nan }
628
+ % if bits == 32 or bits == 64 :
629
+ guard _fastPath ( isFinite) else { return . nan }
630
+ if _fastPath ( isNormal) {
631
+ let bitPattern_ = bitPattern & ${ Self} . infinity. bitPattern
632
+ return ${ Self} ( bitPattern: bitPattern_) / 0x1 p${ SignificandBitCount}
633
+ }
634
+ #if arch(arm)
635
+ // On arm, flush positive subnormal values to 0.
636
+ return 0
637
+ #else
638
+ return . leastNonzeroMagnitude
639
+ #endif
640
+ % else :
641
+ guard _fastPath ( isFinite) else { return . nan }
629
642
if exponentBitPattern > UInt ( ${ Self} . significandBitCount) {
630
643
// self is large enough that self.ulp is normal, so we just compute its
631
644
// exponent and construct it with a significand of zero.
@@ -645,6 +658,7 @@ extension ${Self}: BinaryFloatingPoint {
645
658
return ${ Self} ( sign: . plus,
646
659
exponentBitPattern: 0 ,
647
660
significandBitPattern: 1 )
661
+ % end
648
662
}
649
663
650
664
/// The least positive normal number.
@@ -917,17 +931,30 @@ extension ${Self}: BinaryFloatingPoint {
917
931
/// - If `x` is `greatestFiniteMagnitude`, then `x.nextUp` is `infinity`.
918
932
@_inlineable // FIXME(sil-serialize-all)
919
933
public var nextUp : ${ Self} {
920
- if isNaN { return self }
921
- if sign == . minus {
934
+ % if bits == 32 or bits == 64 :
935
+ // Silence signaling NaNs, map -0 to +0.
936
+ let x = self + 0
922
937
#if arch(arm)
923
- // On arm, subnormals are flushed to zero.
924
- if ( exponentBitPattern == 1 && significandBitPattern == 0 ) ||
925
- ( exponentBitPattern == 0 && significandBitPattern != 0 ) {
926
- return ${ Self} ( sign: . minus,
927
- exponentBitPattern: 0 ,
928
- significandBitPattern: 0 )
938
+ // On arm, skip positive subnormal values.
939
+ if _slowPath ( x. bitPattern & ( - ${ Self} . infinity) . bitPattern == 0 ) {
940
+ return . leastNormalMagnitude
941
+ }
942
+ #endif
943
+ if _fastPath ( x < . infinity) {
944
+ let increment = Int ${ bits} ( bitPattern: x. bitPattern) &>> ${ bits - 1 } | 1
945
+ let bitPattern_ = x. bitPattern &+ UInt${ bits} ( bitPattern: increment)
946
+ #if arch(arm)
947
+ // On arm, flush negative subnormal values to -0.
948
+ if _slowPath ( bitPattern_ & ${ Self} . infinity. bitPattern == 0 ) {
949
+ return - 0.0
929
950
}
930
951
#endif
952
+ return ${ Self} ( bitPattern: bitPattern_)
953
+ }
954
+ return x
955
+ % else :
956
+ if isNaN { /* Silence signaling NaNs. */ return self + 0 }
957
+ if sign == . minus {
931
958
if significandBitPattern == 0 {
932
959
if exponentBitPattern == 0 {
933
960
return . leastNonzeroMagnitude
@@ -946,15 +973,10 @@ extension ${Self}: BinaryFloatingPoint {
946
973
exponentBitPattern: exponentBitPattern + 1 ,
947
974
significandBitPattern: 0 )
948
975
}
949
- #if arch(arm)
950
- // On arm, subnormals are skipped.
951
- if exponentBitPattern == 0 {
952
- return . leastNonzeroMagnitude
953
- }
954
- #endif
955
976
return ${ Self} ( sign: . plus,
956
977
exponentBitPattern: exponentBitPattern,
957
978
significandBitPattern: significandBitPattern + 1 )
979
+ % end
958
980
}
959
981
960
982
/// Rounds the value to an integral value using the specified rounding rule.
@@ -1369,7 +1391,19 @@ extension ${Self}: BinaryFloatingPoint {
1369
1391
/// // y.exponent == 4
1370
1392
@_inlineable // FIXME(sil-serialize-all)
1371
1393
public var binade : ${ Self} {
1372
- if !isFinite { return . nan }
1394
+ % if bits == 32 or bits == 64 :
1395
+ guard _fastPath ( isFinite) else { return . nan }
1396
+ #if !arch(arm)
1397
+ if _slowPath ( isSubnormal) {
1398
+ let bitPattern_ =
1399
+ ( self * 0x1 p${ SignificandBitCount} ) . bitPattern
1400
+ & ( - ${ Self} . infinity) . bitPattern
1401
+ return ${ Self} ( bitPattern: bitPattern_) / 0x1 p${ SignificandBitCount}
1402
+ }
1403
+ #endif
1404
+ return ${ Self} ( bitPattern: bitPattern & ( - ${ Self} . infinity) . bitPattern)
1405
+ % else :
1406
+ guard _fastPath ( isFinite) else { return . nan }
1373
1407
if exponentBitPattern != 0 {
1374
1408
return ${ Self} ( sign: sign, exponentBitPattern: exponentBitPattern,
1375
1409
significandBitPattern: 0 )
@@ -1379,6 +1413,7 @@ extension ${Self}: BinaryFloatingPoint {
1379
1413
let index = significandBitPattern. _binaryLogarithm ( )
1380
1414
return ${ Self} ( sign: sign, exponentBitPattern: 0 ,
1381
1415
significandBitPattern: 1 &<< index)
1416
+ % end
1382
1417
}
1383
1418
1384
1419
/// The number of bits required to represent the value's significand.
@@ -1490,6 +1525,7 @@ extension ${Self} : _ExpressibleByBuiltinFloatLiteral {
1490
1525
% if bits == builtinFloatLiteralBits:
1491
1526
self = ${ Self} ( _bits: value)
1492
1527
% elif bits < builtinFloatLiteralBits :
1528
+ // FIXME: This can result in double rounding errors (SR-7124).
1493
1529
self = ${ Self} ( _bits: Builtin . fptrunc_FPIEEE ${ builtinFloatLiteralBits} _FPIEEE${ bits} ( value) )
1494
1530
% else:
1495
1531
// FIXME: This is actually losing precision <rdar://problem/14073102>.
0 commit comments