19
19
#include " llvm/ADT/Hashing.h"
20
20
#include " llvm/ADT/StringExtras.h"
21
21
#include " llvm/ADT/StringRef.h"
22
+ #include " llvm/Support/Debug.h"
22
23
#include " llvm/Support/ErrorHandling.h"
23
24
#include " llvm/Support/MathExtras.h"
25
+ #include " llvm/Support/raw_ostream.h"
24
26
#include < cstring>
25
27
#include < limits.h>
26
28
@@ -3847,8 +3849,9 @@ DoubleAPFloat::DoubleAPFloat(const fltSemantics &S, integerPart I)
3847
3849
}
3848
3850
3849
3851
DoubleAPFloat::DoubleAPFloat (const fltSemantics &S, const APInt &I)
3850
- : Semantics(&S), Floats(new APFloat[2 ]{APFloat (PPCDoubleDoubleImpl, I),
3851
- APFloat (IEEEdouble)}) {
3852
+ : Semantics(&S), Floats(new APFloat[2 ]{
3853
+ APFloat (PPCDoubleDoubleImpl, I),
3854
+ APFloat (IEEEdouble, APInt (64 , I.getRawData ()[1 ]))}) {
3852
3855
assert (Semantics == &PPCDoubleDouble);
3853
3856
}
3854
3857
@@ -3858,7 +3861,8 @@ DoubleAPFloat::DoubleAPFloat(const fltSemantics &S, APFloat &&First,
3858
3861
Floats(new APFloat[2 ]{std::move (First), std::move (Second)}) {
3859
3862
assert (Semantics == &PPCDoubleDouble);
3860
3863
// TODO Check for First == &IEEEdouble once the transition is done.
3861
- assert (&Floats[0 ].getSemantics () == &PPCDoubleDoubleImpl);
3864
+ assert (&Floats[0 ].getSemantics () == &PPCDoubleDoubleImpl ||
3865
+ &Floats[0 ].getSemantics () == &IEEEdouble);
3862
3866
assert (&Floats[1 ].getSemantics () == &IEEEdouble);
3863
3867
}
3864
3868
@@ -3887,6 +3891,198 @@ DoubleAPFloat &DoubleAPFloat::operator=(const DoubleAPFloat &RHS) {
3887
3891
return *this ;
3888
3892
}
3889
3893
3894
+ // "Software for Doubled-Precision Floating-Point Computations",
3895
+ // by Seppo Linnainmaa, ACM TOMS vol 7 no 3, September 1981, pages 272-283.
3896
+ APFloat::opStatus DoubleAPFloat::addImpl (const APFloat &a, const APFloat &aa,
3897
+ const APFloat &c, const APFloat &cc,
3898
+ roundingMode RM) {
3899
+ int Status = opOK;
3900
+ APFloat z = a;
3901
+ Status |= z.add (c, RM);
3902
+ if (!z.isFinite ()) {
3903
+ if (!z.isInfinity ()) {
3904
+ Floats[0 ] = std::move (z);
3905
+ Floats[1 ].makeZero (false );
3906
+ return (opStatus)Status;
3907
+ }
3908
+ Status = opOK;
3909
+ auto AComparedToC = a.compareAbsoluteValue (c);
3910
+ z = cc;
3911
+ Status |= z.add (aa, RM);
3912
+ if (AComparedToC == APFloat::cmpGreaterThan) {
3913
+ // z = cc + aa + c + a;
3914
+ Status |= z.add (c, RM);
3915
+ Status |= z.add (a, RM);
3916
+ } else {
3917
+ // z = cc + aa + a + c;
3918
+ Status |= z.add (a, RM);
3919
+ Status |= z.add (c, RM);
3920
+ }
3921
+ if (!z.isFinite ()) {
3922
+ Floats[0 ] = std::move (z);
3923
+ Floats[1 ].makeZero (false );
3924
+ return (opStatus)Status;
3925
+ }
3926
+ Floats[0 ] = z;
3927
+ APFloat zz = aa;
3928
+ Status |= zz.add (cc, RM);
3929
+ if (AComparedToC == APFloat::cmpGreaterThan) {
3930
+ // Floats[1] = a - z + c + zz;
3931
+ Floats[1 ] = a;
3932
+ Status |= Floats[1 ].subtract (z, RM);
3933
+ Status |= Floats[1 ].add (c, RM);
3934
+ Status |= Floats[1 ].add (zz, RM);
3935
+ } else {
3936
+ // Floats[1] = c - z + a + zz;
3937
+ Floats[1 ] = c;
3938
+ Status |= Floats[1 ].subtract (z, RM);
3939
+ Status |= Floats[1 ].add (a, RM);
3940
+ Status |= Floats[1 ].add (zz, RM);
3941
+ }
3942
+ } else {
3943
+ // q = a - z;
3944
+ APFloat q = a;
3945
+ Status |= q.subtract (z, RM);
3946
+
3947
+ // zz = q + c + (a - (q + z)) + aa + cc;
3948
+ // Compute a - (q + z) as -((q + z) - a) to avoid temporary copies.
3949
+ auto zz = q;
3950
+ Status |= zz.add (c, RM);
3951
+ Status |= q.add (z, RM);
3952
+ Status |= q.subtract (a, RM);
3953
+ q.changeSign ();
3954
+ Status |= zz.add (q, RM);
3955
+ Status |= zz.add (aa, RM);
3956
+ Status |= zz.add (cc, RM);
3957
+ if (zz.isZero () && !zz.isNegative ()) {
3958
+ Floats[0 ] = std::move (z);
3959
+ Floats[1 ].makeZero (false );
3960
+ return opOK;
3961
+ }
3962
+ Floats[0 ] = z;
3963
+ Status |= Floats[0 ].add (zz, RM);
3964
+ if (!Floats[0 ].isFinite ()) {
3965
+ Floats[1 ].makeZero (false );
3966
+ return (opStatus)Status;
3967
+ }
3968
+ Floats[1 ] = std::move (z);
3969
+ Status |= Floats[1 ].subtract (Floats[0 ], RM);
3970
+ Status |= Floats[1 ].add (zz, RM);
3971
+ }
3972
+ return (opStatus)Status;
3973
+ }
3974
+
3975
+ APFloat::opStatus DoubleAPFloat::addWithSpecial (const DoubleAPFloat &LHS,
3976
+ const DoubleAPFloat &RHS,
3977
+ DoubleAPFloat &Out,
3978
+ roundingMode RM) {
3979
+ if (LHS.getCategory () == fcNaN) {
3980
+ Out = LHS;
3981
+ return opOK;
3982
+ }
3983
+ if (RHS.getCategory () == fcNaN) {
3984
+ Out = RHS;
3985
+ return opOK;
3986
+ }
3987
+ if (LHS.getCategory () == fcZero) {
3988
+ Out = RHS;
3989
+ return opOK;
3990
+ }
3991
+ if (RHS.getCategory () == fcZero) {
3992
+ Out = LHS;
3993
+ return opOK;
3994
+ }
3995
+ if (LHS.getCategory () == fcInfinity && RHS.getCategory () == fcInfinity &&
3996
+ LHS.isNegative () != RHS.isNegative ()) {
3997
+ Out.makeNaN (false , Out.isNegative (), nullptr );
3998
+ return opInvalidOp;
3999
+ }
4000
+ if (LHS.getCategory () == fcInfinity) {
4001
+ Out = LHS;
4002
+ return opOK;
4003
+ }
4004
+ if (RHS.getCategory () == fcInfinity) {
4005
+ Out = RHS;
4006
+ return opOK;
4007
+ }
4008
+ assert (LHS.getCategory () == fcNormal && RHS.getCategory () == fcNormal);
4009
+
4010
+ // These conversions will go away once PPCDoubleDoubleImpl goes away.
4011
+ // (PPCDoubleDoubleImpl, IEEEDouble) -> (IEEEDouble, IEEEDouble)
4012
+ APFloat A (IEEEdouble,
4013
+ APInt (64 , LHS.Floats [0 ].bitcastToAPInt ().getRawData ()[0 ])),
4014
+ AA (LHS.Floats [1 ]),
4015
+ C (IEEEdouble, APInt (64 , RHS.Floats [0 ].bitcastToAPInt ().getRawData ()[0 ])),
4016
+ CC (RHS.Floats [1 ]);
4017
+ assert (&AA.getSemantics () == &IEEEdouble);
4018
+ assert (&CC.getSemantics () == &IEEEdouble);
4019
+ Out.Floats [0 ] = APFloat (IEEEdouble);
4020
+ assert (&Out.Floats [1 ].getSemantics () == &IEEEdouble);
4021
+
4022
+ auto Ret = Out.addImpl (A, AA, C, CC, RM);
4023
+
4024
+ // (IEEEDouble, IEEEDouble) -> (PPCDoubleDoubleImpl, IEEEDouble)
4025
+ uint64_t Buffer[] = {Out.Floats [0 ].bitcastToAPInt ().getRawData ()[0 ],
4026
+ Out.Floats [1 ].bitcastToAPInt ().getRawData ()[0 ]};
4027
+ Out.Floats [0 ] = APFloat (PPCDoubleDoubleImpl, APInt (128 , 2 , Buffer));
4028
+ return Ret;
4029
+ }
4030
+
4031
+ APFloat::opStatus DoubleAPFloat::add (const DoubleAPFloat &RHS,
4032
+ roundingMode RM) {
4033
+ return addWithSpecial (*this , RHS, *this , RM);
4034
+ }
4035
+
4036
+ APFloat::opStatus DoubleAPFloat::subtract (const DoubleAPFloat &RHS,
4037
+ roundingMode RM) {
4038
+ changeSign ();
4039
+ auto Ret = add (RHS, RM);
4040
+ changeSign ();
4041
+ return Ret;
4042
+ }
4043
+
4044
+ void DoubleAPFloat::changeSign () {
4045
+ Floats[0 ].changeSign ();
4046
+ Floats[1 ].changeSign ();
4047
+ }
4048
+
4049
+ APFloat::cmpResult
4050
+ DoubleAPFloat::compareAbsoluteValue (const DoubleAPFloat &RHS) const {
4051
+ auto Result = Floats[0 ].compareAbsoluteValue (RHS.Floats [0 ]);
4052
+ if (Result != cmpEqual)
4053
+ return Result;
4054
+ Result = Floats[1 ].compareAbsoluteValue (RHS.Floats [1 ]);
4055
+ if (Result == cmpLessThan || Result == cmpGreaterThan) {
4056
+ auto Against = Floats[0 ].isNegative () ^ Floats[1 ].isNegative ();
4057
+ auto RHSAgainst = RHS.Floats [0 ].isNegative () ^ RHS.Floats [1 ].isNegative ();
4058
+ if (Against && !RHSAgainst)
4059
+ return cmpLessThan;
4060
+ if (!Against && RHSAgainst)
4061
+ return cmpGreaterThan;
4062
+ if (!Against && !RHSAgainst)
4063
+ return Result;
4064
+ if (Against && RHSAgainst)
4065
+ return (cmpResult)(cmpLessThan + cmpGreaterThan - Result);
4066
+ }
4067
+ return Result;
4068
+ }
4069
+
4070
+ APFloat::fltCategory DoubleAPFloat::getCategory () const {
4071
+ return Floats[0 ].getCategory ();
4072
+ }
4073
+
4074
+ bool DoubleAPFloat::isNegative () const { return Floats[0 ].isNegative (); }
4075
+
4076
+ void DoubleAPFloat::makeInf (bool Neg) {
4077
+ Floats[0 ].makeInf (Neg);
4078
+ Floats[1 ].makeZero (false );
4079
+ }
4080
+
4081
+ void DoubleAPFloat::makeNaN (bool SNaN, bool Neg, const APInt *fill) {
4082
+ Floats[0 ].makeNaN (SNaN, Neg, fill);
4083
+ Floats[1 ].makeZero (false );
4084
+ }
4085
+
3890
4086
} // End detail namespace
3891
4087
3892
4088
APFloat::Storage::Storage (IEEEFloat F, const fltSemantics &Semantics) {
@@ -3959,4 +4155,12 @@ APFloat APFloat::getAllOnesValue(unsigned BitWidth, bool isIEEE) {
3959
4155
}
3960
4156
}
3961
4157
4158
+ void APFloat::print (raw_ostream &OS) const {
4159
+ SmallVector<char , 16 > Buffer;
4160
+ toString (Buffer);
4161
+ OS << Buffer << " \n " ;
4162
+ }
4163
+
4164
+ void APFloat::dump () const { print (dbgs ()); }
4165
+
3962
4166
} // End llvm namespace
0 commit comments