@@ -625,7 +625,16 @@ 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 != 80 :
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
+ // On arm, flush subnormal values to 0.
635
+ return . leastNormalMagnitude * 0x1 p- ${ SignificandBitCount}
636
+ % else :
637
+ guard _fastPath ( isFinite) else { return . nan }
629
638
if exponentBitPattern > UInt ( ${ Self} . significandBitCount) {
630
639
// self is large enough that self.ulp is normal, so we just compute its
631
640
// exponent and construct it with a significand of zero.
@@ -645,6 +654,7 @@ extension ${Self}: BinaryFloatingPoint {
645
654
return ${ Self} ( sign: . plus,
646
655
exponentBitPattern: 0 ,
647
656
significandBitPattern: 1 )
657
+ % end
648
658
}
649
659
650
660
/// The least positive normal number.
@@ -917,17 +927,23 @@ extension ${Self}: BinaryFloatingPoint {
917
927
/// - If `x` is `greatestFiniteMagnitude`, then `x.nextUp` is `infinity`.
918
928
@_inlineable // FIXME(sil-serialize-all)
919
929
public var nextUp : ${ Self} {
920
- if isNaN { return self }
921
- if sign == . minus {
930
+ % if bits != 80 :
931
+ // Silence signaling NaNs, map -0 to +0.
932
+ let x = self + 0
922
933
#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 )
929
- }
934
+ // On arm, treat subnormal values as zero.
935
+ if _slowPath ( x == 0 ) { return . leastNonzeroMagnitude }
936
+ if _slowPath ( x == - . leastNonzeroMagnitude) { return - 0.0 }
930
937
#endif
938
+ if _fastPath ( x < . infinity) {
939
+ let increment = Int ${ bits} ( bitPattern: x. bitPattern) &>> ${ bits - 1 } | 1
940
+ let bitPattern_ = x. bitPattern &+ UInt${ bits} ( bitPattern: increment)
941
+ return ${ Self} ( bitPattern: bitPattern_)
942
+ }
943
+ return x
944
+ % else :
945
+ if isNaN { /* Silence signaling NaNs. */ return self + 0 }
946
+ if sign == . minus {
931
947
if significandBitPattern == 0 {
932
948
if exponentBitPattern == 0 {
933
949
return . leastNonzeroMagnitude
@@ -946,15 +962,10 @@ extension ${Self}: BinaryFloatingPoint {
946
962
exponentBitPattern: exponentBitPattern + 1 ,
947
963
significandBitPattern: 0 )
948
964
}
949
- #if arch(arm)
950
- // On arm, subnormals are skipped.
951
- if exponentBitPattern == 0 {
952
- return . leastNonzeroMagnitude
953
- }
954
- #endif
955
965
return ${ Self} ( sign: . plus,
956
966
exponentBitPattern: exponentBitPattern,
957
967
significandBitPattern: significandBitPattern + 1 )
968
+ % end
958
969
}
959
970
960
971
/// Rounds the value to an integral value using the specified rounding rule.
@@ -1369,7 +1380,19 @@ extension ${Self}: BinaryFloatingPoint {
1369
1380
/// // y.exponent == 4
1370
1381
@_inlineable // FIXME(sil-serialize-all)
1371
1382
public var binade : ${ Self} {
1372
- if !isFinite { return . nan }
1383
+ % if bits != 80 :
1384
+ guard _fastPath ( isFinite) else { return . nan }
1385
+ #if !arch(arm)
1386
+ if _slowPath ( isSubnormal) {
1387
+ let bitPattern_ =
1388
+ ( self * 0x1 p${ SignificandBitCount} ) . bitPattern
1389
+ & ( - ${ Self} . infinity) . bitPattern
1390
+ return ${ Self} ( bitPattern: bitPattern_) * 0x1 p- ${ SignificandBitCount}
1391
+ }
1392
+ #endif
1393
+ return ${ Self} ( bitPattern: bitPattern & ( - ${ Self} . infinity) . bitPattern)
1394
+ % else :
1395
+ guard _fastPath ( isFinite) else { return . nan }
1373
1396
if exponentBitPattern != 0 {
1374
1397
return ${ Self} ( sign: sign, exponentBitPattern: exponentBitPattern,
1375
1398
significandBitPattern: 0 )
@@ -1379,6 +1402,7 @@ extension ${Self}: BinaryFloatingPoint {
1379
1402
let index = significandBitPattern. _binaryLogarithm ( )
1380
1403
return ${ Self} ( sign: sign, exponentBitPattern: 0 ,
1381
1404
significandBitPattern: 1 &<< index)
1405
+ % end
1382
1406
}
1383
1407
1384
1408
/// The number of bits required to represent the value's significand.
@@ -1490,6 +1514,7 @@ extension ${Self} : _ExpressibleByBuiltinFloatLiteral {
1490
1514
% if bits == builtinFloatLiteralBits:
1491
1515
self = ${ Self} ( _bits: value)
1492
1516
% elif bits < builtinFloatLiteralBits :
1517
+ // FIXME: This can result in double rounding errors (SR-7124).
1493
1518
self = ${ Self} ( _bits: Builtin . fptrunc_FPIEEE ${ builtinFloatLiteralBits} _FPIEEE${ bits} ( value) )
1494
1519
% else:
1495
1520
// FIXME: This is actually losing precision <rdar://problem/14073102>.
0 commit comments