24 #ifndef COM_DAFER45_TBTK_ARBITRARY_PRECISION_COMPLEX
25 #define COM_DAFER45_TBTK_ARBITRARY_PRECISION_COMPLEX
27 #include "TBTK/ArbitraryPrecision/Real.h"
38 namespace ArbitraryPrecision{
53 Complex(
unsigned int precision);
61 Complex(
unsigned int precision,
const std::complex<double> &value);
70 Complex(
unsigned int precision,
double real,
double imag);
76 Complex(
const Real &real,
const Real &imag);
83 Complex& operator=(
const std::complex<double> &rhs);
92 Complex& operator=(
const std::string &rhs);
99 Complex& operator+=(
const Complex &rhs);
106 Complex operator+(
const Complex &rhs)
const;
113 Complex& operator-=(
const Complex &rhs);
120 Complex operator-(
const Complex &rhs)
const;
127 Complex& operator*=(
const Complex &rhs);
134 Complex
operator*(
const Complex &rhs)
const;
141 Complex& operator/=(
const Complex &rhs);
148 Complex operator/(
const Complex &rhs)
const;
153 Complex operator-()
const;
159 friend std::ostream&
operator<<(std::ostream &os,
const Complex &complex);
164 std::complex<double> getComplexDouble()
const;
169 const Real& getReal()
const;
174 const Real& getImag()
const;
187 unsigned int precision
195 unsigned int precision,
196 const std::complex<double> &value
204 unsigned int precision,
230 std::stringstream ss(rhs);
231 const int STATE_BEFORE_FIRST_TERM = 0;
232 const int STATE_READING_FIRST_TERM = 1;
233 const int STATE_AFTER_FIRST_TERM = 2;
234 const int STATE_BEFORE_SECOND_TERM = 3;
235 const int STATE_READING_SECOND_TERM = 4;
236 const int STATE_AFTER_SECOND_TERM = 5;
237 int state = STATE_BEFORE_FIRST_TERM;
239 std::string firstTerm;
240 std::string secondTerm;
241 bool firstTermIsReal =
true;
242 bool secondTermIsReal =
true;
243 std::string firstTermSign;
244 std::string secondTermSign;
260 case STATE_BEFORE_FIRST_TERM:
261 state = STATE_READING_FIRST_TERM;
262 case STATE_READING_FIRST_TERM:
265 case STATE_BEFORE_SECOND_TERM:
266 state = STATE_READING_SECOND_TERM;
267 case STATE_READING_SECOND_TERM:
272 "ArbitraryPrecision::Complex::operator=()",
273 "Unable to parse '" << rhs <<
"' as a"
274 <<
" complex number. Found unexpected"
275 <<
" tocken '" << c <<
"' at position"
276 <<
" '" << position <<
"'.",
283 case STATE_BEFORE_FIRST_TERM:
284 if(firstTermSign.length() != 0){
286 "ArbitraryPrecision::Complex::operator=()",
287 "Unable to parse '" << rhs
288 <<
"' as a complex number."
289 <<
" Found unexpected tocken '"
290 << c <<
"' at position" <<
" '"
297 case STATE_READING_FIRST_TERM:
298 case STATE_AFTER_FIRST_TERM:
299 state = STATE_BEFORE_SECOND_TERM;
300 if(secondTermSign.length() != 0){
302 "ArbitraryPrecision::Complex::operator=()",
303 "Unable to parse '" << rhs
304 <<
"' as a complex number."
305 <<
" Found unexpected tocken '"
306 << c <<
"' at position" <<
" '"
311 secondTermSign =
"+";
315 "ArbitraryPrecision::Complex::operator=()",
316 "Unable to parse '" << rhs <<
"' as a"
317 <<
" complex number. Found unexpected"
318 <<
" tocken '" << c <<
"' at position"
319 <<
" '" << position <<
"'.",
326 case STATE_BEFORE_FIRST_TERM:
327 if(firstTermSign.length() != 0){
329 "ArbitraryPrecision::Complex::operator=()",
330 "Unable to parse '" << rhs
331 <<
"' as a complex number."
332 <<
" Found unexpected tocken '"
333 << c <<
"' at position" <<
" '"
340 case STATE_READING_FIRST_TERM:
341 case STATE_AFTER_FIRST_TERM:
342 state = STATE_BEFORE_SECOND_TERM;
343 if(secondTermSign.length() != 0){
345 "ArbitraryPrecision::Complex::operator=()",
346 "Unable to parse '" << rhs
347 <<
"' as a complex number."
348 <<
" Found unexpected tocken '"
349 << c <<
"' at position" <<
" '"
354 secondTermSign =
"-";
358 "ArbitraryPrecision::Complex::operator=()",
359 "Unable to parse '" << rhs <<
"' as a"
360 <<
" complex number. Found unexpected"
361 <<
" tocken '" << c <<
"' at position"
362 <<
" '" << position <<
"'.",
369 case STATE_READING_FIRST_TERM:
370 state = STATE_AFTER_FIRST_TERM;
371 case STATE_AFTER_FIRST_TERM:
372 case STATE_BEFORE_FIRST_TERM:
373 if(!firstTermIsReal){
375 "ArbitraryPrecision::Complex::operator=()",
376 "Unable to parse '" << rhs
377 <<
"' as a complex number."
378 <<
" Found unexpected tocken '"
379 << c <<
"' at position '"
384 firstTermIsReal =
false;
386 case STATE_READING_SECOND_TERM:
387 state = STATE_AFTER_SECOND_TERM;
388 case STATE_AFTER_SECOND_TERM:
389 case STATE_BEFORE_SECOND_TERM:
390 if(!secondTermIsReal){
392 "ArbitraryPrecision::Complex::operator=()",
393 "Unable to parse '" << rhs
394 <<
"' as a complex number."
395 <<
" Found unexpected tocken '"
396 << c <<
"' at position '"
401 secondTermIsReal =
false;
407 case STATE_BEFORE_FIRST_TERM:
408 case STATE_AFTER_FIRST_TERM:
409 case STATE_BEFORE_SECOND_TERM:
410 case STATE_AFTER_SECOND_TERM:
412 case STATE_READING_FIRST_TERM:
413 state = STATE_AFTER_FIRST_TERM;
415 case STATE_READING_SECOND_TERM:
416 state = STATE_AFTER_SECOND_TERM;
422 "ArbitraryPrecision::Complex::operator=()",
423 "Unable to parse '" << rhs <<
"' as a complex"
424 <<
" number. Found unexpected tocken '" << c
425 <<
"' at position '" << position <<
"'.",
433 if(secondTerm.length() == 0 && firstTermIsReal)
434 secondTermIsReal =
false;
437 firstTermIsReal != secondTermIsReal,
438 "ArbitraryPrecision::Complex::operator=()",
439 "Unable to parse '" << rhs <<
"' as a complex number. The two"
440 <<
" terms cannot both be real or both be imaginary.",
444 if(firstTermSign.compare(
"-") == 0)
445 firstTerm =
"-" + firstTerm;
446 if(secondTermSign.compare(
"-") == 0)
447 secondTerm =
"-" + secondTerm;
471 return complex += rhs;
484 return complex -= rhs;
490 real = r*rhs.real - i*rhs.imag;
491 imag = r*rhs.imag + i*rhs.real;
499 return complex *= rhs;
503 Real denominator = rhs.real*rhs.real + rhs.imag*rhs.imag;
507 real = (r*rhs.real + i*rhs.imag)/denominator;
508 imag = (i*rhs.real - r*rhs.imag)/denominator;
516 return complex /= rhs;
523 inline std::ostream&
operator<<(std::ostream &os,
const Complex &complex){
524 if(complex.imag.getDouble() >= 0)
525 os << complex.real <<
" + i" << complex.imag;
527 os << complex.real <<
" - i" << -complex.imag;
532 inline std::complex<double> Complex::getComplexDouble()
const{
533 return std::complex<double>(
real.getDouble(),
imag.getDouble());
536 inline const Real& Complex::getReal()
const{
540 inline const Real& Complex::getImag()
const{
545 inline Complex
pow(Complex base,
long unsigned int power){
550 mp_bitcnt_t realPrecision = base.getReal().getPrecision();
551 mp_bitcnt_t imagPrecision = base.getReal().getPrecision();
552 if(realPrecision > imagPrecision)
553 result = Complex(realPrecision, 1);
555 result = Complex(realPrecision, 1);
563 result = result*base;
570 inline Complex
pow(
const Complex &base,
long int power){
572 Complex result =
pow(base, (
long unsigned int)(-power));
574 return Complex(result.getReal().getPrecision(), 1)/result;
577 return pow(base, (
long unsigned int)power);
581 inline Complex
pow(
const Complex &base,
int power){
582 return pow(base, (
long int)power);