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 <algorithm>
#include <cmath>
#include <complex>
#include <memory>
#include "analysisdefs.hxx"
@ -1591,9 +1592,8 @@ bool Complex::ParseString( const OUString& rStr, Complex& rCompl )
if( IsImagUnit( *pStr ) && rStr.getLength() == 1)
{
rCompl.r = 0.0;
rCompl.i = 1.0;
rCompl.c = *pStr;
rCompl.num = std::complex(0.0, 1.0);
return true;
}
@ -1613,8 +1613,7 @@ bool Complex::ParseString( const OUString& rStr, Complex& rCompl )
rCompl.c = pStr[ 1 ];
if( pStr[ 2 ] == 0 )
{
rCompl.r = f;
rCompl.i = ( *pStr == '+' )? 1.0 : -1.0;
rCompl.num = std::complex(f, ( *pStr == '+' )? 1.0 : -1.0);
return true;
}
}
@ -1624,8 +1623,7 @@ bool Complex::ParseString( const OUString& rStr, Complex& rCompl )
pStr++;
if( *pStr == 0 )
{
rCompl.r = r;
rCompl.i = f;
rCompl.num = std::complex(r, f);
return true;
}
}
@ -1637,43 +1635,40 @@ bool Complex::ParseString( const OUString& rStr, Complex& rCompl )
pStr++;
if( *pStr == 0 )
{
rCompl.i = f;
rCompl.r = 0.0;
rCompl.num = std::complex(0.0, f);
return true;
}
break;
case 0: // only real-part
rCompl.r = f;
rCompl.i = 0.0;
rCompl.num = std::complex(f, 0.0);
return true;
}
return false;
}
OUString Complex::GetString() const
{
finiteOrThrow(r);
finiteOrThrow(i);
finiteOrThrow(num.real());
finiteOrThrow(num.imag());
OUStringBuffer aRet;
bool bHasImag = i != 0.0;
bool bHasReal = !bHasImag || (r != 0.0);
bool bHasImag = num.imag() != 0.0;
bool bHasReal = !bHasImag || (num.real() != 0.0);
if( bHasReal )
aRet.append(::GetString( r, false ));
aRet.append(::GetString( num.real(), false ));
if( bHasImag )
{
if( i == 1.0 )
if( num.imag() == 1.0 )
{
if( bHasReal )
aRet.append('+');
}
else if( i == -1.0 )
else if( num.imag() == -1.0 )
aRet.append('-');
else
aRet.append(::GetString( i, bHasReal ));
aRet.append(::GetString( num.imag(), bHasReal ));
aRet.append((c != 'j') ? 'i' : 'j');
}
@ -1683,139 +1678,65 @@ OUString Complex::GetString() 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();
double phi = acos( r / Abs() );
if( i < 0.0 )
phi = -phi;
return phi;
return std::arg(num);
}
void Complex::Power( double fPower )
{
if( r == 0.0 && i == 0.0 )
{
if( fPower <= 0 )
if( num.real() == 0.0 && num.imag() == 0.0 && fPower <= 0 )
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;
num = std::pow(num, fPower);
}
void Complex::Sqrt()
{
static const double fMultConst = M_SQRT1_2;
double p = Abs();
double i_ = sqrt( p - r ) * fMultConst;
r = sqrt( p + r ) * fMultConst;
i = ( i < 0.0 )? -i_ : i_;
num = std::sqrt(num);
}
void Complex::Sin()
{
if( !::rtl::math::isValidArcArg( r ) )
if( !::rtl::math::isValidArcArg( num.real() ) )
throw lang::IllegalArgumentException();
if( i )
{
double r_;
r_ = sin( r ) * cosh( i );
i = cos( r ) * sinh( i );
r = r_;
}
else
r = sin( r );
num = std::sin(num);
}
void Complex::Cos()
{
if( !::rtl::math::isValidArcArg( r ) )
if( !::rtl::math::isValidArcArg( num.real() ) )
throw lang::IllegalArgumentException();
if( i )
{
double r_;
r_ = cos( r ) * cosh( i );
i = -( sin( r ) * sinh( i ) );
r = r_;
}
else
r = cos( r );
num = std::cos(num);
}
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();
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;
num = num / z.num;
}
void Complex::Exp()
{
double fE = exp( r );
r = fE * cos( i );
i = fE * sin( i );
num = std::exp(num);
}
void Complex::Ln()
{
if( r == 0.0 && i == 0.0 )
throw lang::IllegalArgumentException();
double fAbs = Abs();
bool bNegi = i < 0.0;
i = acos( r / fAbs );
if( bNegi )
i = -i;
r = log( fAbs );
num = std::log(num);
}
void Complex::Log10()
{
Ln();
Mult( M_LOG10E );
num = std::log10(num);
}
@ -1828,157 +1749,64 @@ void Complex::Log2()
void Complex::Tan()
{
if ( i )
{
if( !::rtl::math::isValidArcArg( 2.0 * r ) )
// 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 ( ( num.imag() && !::rtl::math::isValidArcArg( 2.0 * num.real() ) )
|| ( !num.imag() && !::rtl::math::isValidArcArg( num.real() ) ) )
throw lang::IllegalArgumentException();
double fScale =1.0 / ( cos( 2.0 * r ) + cosh( 2.0 * i ));
r = sin( 2.0 * r ) * fScale;
i = sinh( 2.0 * i ) * fScale;
}
else
{
if( !::rtl::math::isValidArcArg( r ) )
throw lang::IllegalArgumentException();
r = tan( r );
}
num = std::tan(num);
}
void Complex::Sec()
{
if( i )
{
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 );
}
Cos();
num = 1.0 / num;
}
void Complex::Csc()
{
if( i )
{
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 );
}
Sin();
num = 1.0 / num;
}
void Complex::Cot()
{
if ( i )
{
if( !::rtl::math::isValidArcArg( 2.0 * r ) )
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 );
}
Tan();
num = 1.0 / num;
}
void Complex::Sinh()
{
if( !::rtl::math::isValidArcArg( r ) )
if( !::rtl::math::isValidArcArg( num.imag() ) )
throw lang::IllegalArgumentException();
if( i )
{
double r_;
r_ = sinh( r ) * cos( i );
i = cosh( r ) * sin( i );
r = r_;
}
else
r = sinh( r );
num = std::sinh(num);
}
void Complex::Cosh()
{
if( !::rtl::math::isValidArcArg( r ) )
if( !::rtl::math::isValidArcArg( num.imag() ) )
throw lang::IllegalArgumentException();
if( i )
{
double r_;
r_ = cosh( r ) * cos( i );
i = sinh( r ) * sin( i );
r = r_;
}
else
r = cosh( r );
num = std::cosh(num);
}
void Complex::Sech()
{
if ( i )
{
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 );
}
Cosh();
num = 1.0 / num;
}
void Complex::Csch()
{
if ( i )
{
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 );
}
Sinh();
num = 1.0 / num;
}

View file

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