tdf#157794 refactor Complex to use std::complex where possible

Change-Id: Ie583399977caf266e3cc0a3cb78462be4cd63151
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/160394
Tested-by: Jenkins
Reviewed-by: Eike Rathke <erack@redhat.com>
This commit is contained in:
dtm 2023-12-06 14:31:55 +00:00 committed by Eike Rathke
parent 0a7b9ba8a4
commit 418a55e0dc
5 changed files with 8355 additions and 9024 deletions

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -27,6 +27,7 @@
#include <rtl/math.hxx> #include <rtl/math.hxx>
#include <algorithm> #include <algorithm>
#include <cmath> #include <cmath>
#include <complex>
#include <memory> #include <memory>
#include "analysisdefs.hxx" #include "analysisdefs.hxx"
@ -1591,9 +1592,8 @@ bool Complex::ParseString( const OUString& rStr, Complex& rCompl )
if( IsImagUnit( *pStr ) && rStr.getLength() == 1) if( IsImagUnit( *pStr ) && rStr.getLength() == 1)
{ {
rCompl.r = 0.0;
rCompl.i = 1.0;
rCompl.c = *pStr; rCompl.c = *pStr;
rCompl.num = std::complex(0.0, 1.0);
return true; return true;
} }
@ -1613,8 +1613,7 @@ bool Complex::ParseString( const OUString& rStr, Complex& rCompl )
rCompl.c = pStr[ 1 ]; rCompl.c = pStr[ 1 ];
if( pStr[ 2 ] == 0 ) if( pStr[ 2 ] == 0 )
{ {
rCompl.r = f; rCompl.num = std::complex(f, ( *pStr == '+' )? 1.0 : -1.0);
rCompl.i = ( *pStr == '+' )? 1.0 : -1.0;
return true; return true;
} }
} }
@ -1624,8 +1623,7 @@ bool Complex::ParseString( const OUString& rStr, Complex& rCompl )
pStr++; pStr++;
if( *pStr == 0 ) if( *pStr == 0 )
{ {
rCompl.r = r; rCompl.num = std::complex(r, f);
rCompl.i = f;
return true; return true;
} }
} }
@ -1637,43 +1635,40 @@ bool Complex::ParseString( const OUString& rStr, Complex& rCompl )
pStr++; pStr++;
if( *pStr == 0 ) if( *pStr == 0 )
{ {
rCompl.i = f; rCompl.num = std::complex(0.0, f);
rCompl.r = 0.0;
return true; return true;
} }
break; break;
case 0: // only real-part case 0: // only real-part
rCompl.r = f; rCompl.num = std::complex(f, 0.0);
rCompl.i = 0.0;
return true; return true;
} }
return false; return false;
} }
OUString Complex::GetString() const OUString Complex::GetString() const
{ {
finiteOrThrow(r); finiteOrThrow(num.real());
finiteOrThrow(i); finiteOrThrow(num.imag());
OUStringBuffer aRet; OUStringBuffer aRet;
bool bHasImag = i != 0.0; bool bHasImag = num.imag() != 0.0;
bool bHasReal = !bHasImag || (r != 0.0); bool bHasReal = !bHasImag || (num.real() != 0.0);
if( bHasReal ) if( bHasReal )
aRet.append(::GetString( r, false )); aRet.append(::GetString( num.real(), false ));
if( bHasImag ) if( bHasImag )
{ {
if( i == 1.0 ) if( num.imag() == 1.0 )
{ {
if( bHasReal ) if( bHasReal )
aRet.append('+'); aRet.append('+');
} }
else if( i == -1.0 ) else if( num.imag() == -1.0 )
aRet.append('-'); aRet.append('-');
else else
aRet.append(::GetString( i, bHasReal )); aRet.append(::GetString( num.imag(), bHasReal ));
aRet.append((c != 'j') ? 'i' : 'j'); aRet.append((c != 'j') ? 'i' : 'j');
} }
@ -1683,139 +1678,65 @@ OUString Complex::GetString() const
double Complex::Arg() const double Complex::Arg() const
{ {
if( r == 0.0 && i == 0.0 ) // Note: there are differing opinions on whether arg(0) should be 0 or undefined, we are treating it as undefined
if( num.real() == 0.0 && num.imag() == 0.0 )
throw lang::IllegalArgumentException(); throw lang::IllegalArgumentException();
return std::arg(num);
double phi = acos( r / Abs() );
if( i < 0.0 )
phi = -phi;
return phi;
} }
void Complex::Power( double fPower ) void Complex::Power( double fPower )
{ {
if( r == 0.0 && i == 0.0 ) if( num.real() == 0.0 && num.imag() == 0.0 && fPower <= 0 )
{ throw lang::IllegalArgumentException();
if( fPower <= 0 ) num = std::pow(num, fPower);
throw lang::IllegalArgumentException();
r = i = 0.0;
return;
}
double p, phi;
p = Abs();
phi = acos( r / p );
if( i < 0.0 )
phi = -phi;
p = pow( p, fPower );
phi *= fPower;
r = cos( phi ) * p;
i = sin( phi ) * p;
} }
void Complex::Sqrt() void Complex::Sqrt()
{ {
static const double fMultConst = M_SQRT1_2; num = std::sqrt(num);
double p = Abs();
double i_ = sqrt( p - r ) * fMultConst;
r = sqrt( p + r ) * fMultConst;
i = ( i < 0.0 )? -i_ : i_;
} }
void Complex::Sin() void Complex::Sin()
{ {
if( !::rtl::math::isValidArcArg( r ) ) if( !::rtl::math::isValidArcArg( num.real() ) )
throw lang::IllegalArgumentException(); throw lang::IllegalArgumentException();
num = std::sin(num);
if( i )
{
double r_;
r_ = sin( r ) * cosh( i );
i = cos( r ) * sinh( i );
r = r_;
}
else
r = sin( r );
} }
void Complex::Cos() void Complex::Cos()
{ {
if( !::rtl::math::isValidArcArg( r ) ) if( !::rtl::math::isValidArcArg( num.real() ) )
throw lang::IllegalArgumentException(); throw lang::IllegalArgumentException();
num = std::cos(num);
if( i )
{
double r_;
r_ = cos( r ) * cosh( i );
i = -( sin( r ) * sinh( i ) );
r = r_;
}
else
r = cos( r );
} }
void Complex::Div( const Complex& z ) void Complex::Div( const Complex& z )
{ {
if( z.r == 0 && z.i == 0 ) if( z.num.real() == 0 && z.num.imag() == 0 )
throw lang::IllegalArgumentException(); throw lang::IllegalArgumentException();
num = num / z.num;
double a1 = r;
double a2 = z.r;
double b1 = i;
double b2 = z.i;
double f = 1.0 / ( a2 * a2 + b2 * b2 );
r = ( a1 * a2 + b1 * b2 ) * f;
i = ( a2 * b1 - a1 * b2 ) * f;
if( !c ) c = z.c;
} }
void Complex::Exp() void Complex::Exp()
{ {
double fE = exp( r ); num = std::exp(num);
r = fE * cos( i );
i = fE * sin( i );
} }
void Complex::Ln() void Complex::Ln()
{ {
if( r == 0.0 && i == 0.0 ) num = std::log(num);
throw lang::IllegalArgumentException();
double fAbs = Abs();
bool bNegi = i < 0.0;
i = acos( r / fAbs );
if( bNegi )
i = -i;
r = log( fAbs );
} }
void Complex::Log10() void Complex::Log10()
{ {
Ln(); num = std::log10(num);
Mult( M_LOG10E );
} }
@ -1828,157 +1749,64 @@ void Complex::Log2()
void Complex::Tan() void Complex::Tan()
{ {
if ( i ) // using 2.0 * num.real/imag as a precaution because a) this is what our previous implementation did and
{ // b) the std::complex implementation may use cos(2x) etc, see the comment in isValidArcArg for details
if( !::rtl::math::isValidArcArg( 2.0 * r ) ) if ( ( num.imag() && !::rtl::math::isValidArcArg( 2.0 * num.real() ) )
throw lang::IllegalArgumentException(); || ( !num.imag() && !::rtl::math::isValidArcArg( num.real() ) ) )
double fScale =1.0 / ( cos( 2.0 * r ) + cosh( 2.0 * i )); throw lang::IllegalArgumentException();
r = sin( 2.0 * r ) * fScale; num = std::tan(num);
i = sinh( 2.0 * i ) * fScale;
}
else
{
if( !::rtl::math::isValidArcArg( r ) )
throw lang::IllegalArgumentException();
r = tan( r );
}
} }
void Complex::Sec() void Complex::Sec()
{ {
if( i ) Cos();
{ num = 1.0 / num;
if( !::rtl::math::isValidArcArg( 2 * r ) )
throw lang::IllegalArgumentException();
double fScale = 1.0 / (cosh( 2.0 * i) + cos ( 2.0 * r));
double r_;
r_ = 2.0 * cos( r ) * cosh( i ) * fScale;
i = 2.0 * sin( r ) * sinh( i ) * fScale;
r = r_;
}
else
{
if( !::rtl::math::isValidArcArg( r ) )
throw lang::IllegalArgumentException();
r = 1.0 / cos( r );
}
} }
void Complex::Csc() void Complex::Csc()
{ {
if( i ) Sin();
{ num = 1.0 / num;
if( !::rtl::math::isValidArcArg( 2 * r ) )
throw lang::IllegalArgumentException();
double fScale = 1.0 / (cosh( 2.0 * i) - cos ( 2.0 * r));
double r_;
r_ = 2.0 * sin( r ) * cosh( i ) * fScale;
i = -2.0 * cos( r ) * sinh( i ) * fScale;
r = r_;
}
else
{
if( !::rtl::math::isValidArcArg( r ) )
throw lang::IllegalArgumentException();
r = 1.0 / sin( r );
}
} }
void Complex::Cot() void Complex::Cot()
{ {
if ( i )
{ Tan();
if( !::rtl::math::isValidArcArg( 2.0 * r ) ) num = 1.0 / num;
throw lang::IllegalArgumentException();
double fScale =1.0 / ( cosh( 2.0 * i ) - cos( 2.0 * r ) );
r = sin( 2.0 * r ) * fScale;
i = - ( sinh( 2.0 * i ) * fScale );
}
else
{
if( !::rtl::math::isValidArcArg( r ) )
throw lang::IllegalArgumentException();
r = 1.0 / tan( r );
}
} }
void Complex::Sinh() void Complex::Sinh()
{ {
if( !::rtl::math::isValidArcArg( r ) ) if( !::rtl::math::isValidArcArg( num.imag() ) )
throw lang::IllegalArgumentException(); throw lang::IllegalArgumentException();
num = std::sinh(num);
if( i )
{
double r_;
r_ = sinh( r ) * cos( i );
i = cosh( r ) * sin( i );
r = r_;
}
else
r = sinh( r );
} }
void Complex::Cosh() void Complex::Cosh()
{ {
if( !::rtl::math::isValidArcArg( r ) ) if( !::rtl::math::isValidArcArg( num.imag() ) )
throw lang::IllegalArgumentException(); throw lang::IllegalArgumentException();
num = std::cosh(num);
if( i )
{
double r_;
r_ = cosh( r ) * cos( i );
i = sinh( r ) * sin( i );
r = r_;
}
else
r = cosh( r );
} }
void Complex::Sech() void Complex::Sech()
{ {
if ( i ) Cosh();
{ num = 1.0 / num;
if( !::rtl::math::isValidArcArg( 2.0 * r ) )
throw lang::IllegalArgumentException();
double fScale =1.0 / ( cosh( 2.0 * r ) + cos( 2.0 * i ));
double r_;
r_ = 2.0 * cosh( r ) * cos( i ) * fScale;
i = - (2.0 * sinh( r ) * sin( i ) * fScale );
r = r_ ;
}
else
{
if( !::rtl::math::isValidArcArg( r ) )
throw lang::IllegalArgumentException();
r = 1.0 / cosh( r );
}
} }
void Complex::Csch() void Complex::Csch()
{ {
if ( i ) Sinh();
{ num = 1.0 / num;
if( !::rtl::math::isValidArcArg( 2.0 * r ) )
throw lang::IllegalArgumentException();
double fScale =1.0 / ( cosh( 2.0 * r ) - cos( 2.0 * i ));
double r_;
r_ = 2.0 * sinh( r ) * cos( i ) * fScale;
i = - ( 2.0 * cosh( r ) * sin( i ) * fScale );
r = r_ ;
}
else
{
if( !::rtl::math::isValidArcArg( r ) )
throw lang::IllegalArgumentException();
r = 1.0 / sinh( r );
}
} }

View file

@ -23,6 +23,7 @@
#include <unotools/resmgr.hxx> #include <unotools/resmgr.hxx>
#include <cmath> #include <cmath>
#include <complex>
#include <memory> #include <memory>
#include <vector> #include <vector>
@ -380,8 +381,7 @@ public:
class Complex class Complex
{ {
double r; std::complex<double> num;
double i;
sal_Unicode c; sal_Unicode c;
public: public:
@ -629,66 +629,59 @@ inline FDCategory FuncData::GetCategory() const
inline Complex::Complex( double fReal, double fImag, sal_Unicode cC ) : inline Complex::Complex( double fReal, double fImag, sal_Unicode cC ) :
r( fReal ), i( fImag ), c( cC ) c( cC )
{ {
num = std::complex(fReal, fImag);
} }
inline double Complex::Real() const inline double Complex::Real() const
{ {
return r; return num.real();
} }
inline double Complex::Imag() const inline double Complex::Imag() const
{ {
return i; return num.imag();
} }
inline double Complex::Abs() const inline double Complex::Abs() const
{ {
return std::hypot(r, i); return std::abs(num);
} }
void Complex::Conjugate() void Complex::Conjugate()
{ {
i = -i; num = std::conj(num);
} }
inline void Complex::Mult( double f ) inline void Complex::Mult( double f )
{ {
i *= f; num = num * f;
r *= f;
} }
inline void Complex::Mult( const Complex& rM ) inline void Complex::Mult( const Complex& rM )
{ {
double r_ = r; num = num * rM.num;
double i_ = i;
r = r_ * rM.r - i_ * rM.i;
i = r_ * rM.i + i_ * rM.r;
if( !c ) c = rM.c; if( !c ) c = rM.c;
} }
inline void Complex::Sub( const Complex& rC ) inline void Complex::Sub( const Complex& rC )
{ {
r -= rC.r; num = num - rC.num;
i -= rC.i;
if( !c ) c = rC.c; if( !c ) c = rC.c;
} }
inline void Complex::Add( const Complex& rAdd ) inline void Complex::Add( const Complex& rAdd )
{ {
r += rAdd.r; num = num + rAdd.num;
i += rAdd.i;
if( !c ) c = rAdd.c; if( !c ) c = rAdd.c;
} }