Quartic roots
Utilities for C++ programming
Loading...
Searching...
No Matches
PolynomialRoots-complex.hxx
Go to the documentation of this file.
1/*--------------------------------------------------------------------------*\
2 | |
3 | Copyright (C) 2014 |
4 | |
5 | , __ , __ |
6 | /|/ \ /|/ \ |
7 | | __/ _ ,_ | __/ _ ,_ |
8 | | \|/ / | | | | \|/ / | | | |
9 | |(__/|__/ |_/ \_/|/|(__/|__/ |_/ \_/|/ |
10 | /| /| |
11 | \| \| |
12 | |
13 | Enrico Bertolazzi |
14 | Dipartimento di Ingegneria Industriale |
15 | Università degli Studi di Trento |
16 | email: enrico.bertolazzi@unitn.it |
17 | |
18\*--------------------------------------------------------------------------*/
19
20#pragma once
21
22#ifndef POLYNOMIAL_ROOTS_COMPLEX_HXX
23#define POLYNOMIAL_ROOTS_COMPLEX_HXX
24
25namespace PolynomialRoots
26{
27
30 {
31 real_type re = 0;
32 real_type im = 0;
33
34 public:
36 real_type const & real() const { return re; }
38 real_type const & imag() const { return im; }
39
41 real_complex() = default;
42
44 real_complex( real_type real_part, real_type imag_part = 0 ) : re( real_part ), im( imag_part ) {}
45
47 static inline real_type abs_real( real_type x ) { return std::fabs( x ); }
48
51 {
52 re += rhs;
53 return *this;
54 }
55
57 inline real_complex & operator+=( real_complex const & rhs )
58 {
59 re += rhs.re;
60 im += rhs.im;
61 return *this;
62 }
63
66 {
67 re -= rhs;
68 return *this;
69 }
70
72 inline real_complex & operator-=( real_complex const & rhs )
73 {
74 re -= rhs.re;
75 im -= rhs.im;
76 return *this;
77 }
78
81 {
82 re *= rhs;
83 im *= rhs;
84 return *this;
85 }
86
88 inline real_complex & operator*=( real_complex const & rhs )
89 {
90 long double const a = static_cast<long double>( re );
91 long double const b = static_cast<long double>( im );
92 long double const c = static_cast<long double>( rhs.re );
93 long double const d = static_cast<long double>( rhs.im );
94
95 long double const real = a * c - b * d;
96 long double const imag = a * d + b * c;
97
98 re = static_cast<real_type>( real );
99 im = static_cast<real_type>( imag );
100
101 return *this;
102 }
103
106 {
107 re /= rhs;
108 im /= rhs;
109 return *this;
110 }
111
113 inline real_complex & operator/=( real_complex const & rhs )
114 {
115 long double const a = static_cast<long double>( re );
116 long double const b = static_cast<long double>( im );
117 long double const c = static_cast<long double>( rhs.re );
118 long double const d = static_cast<long double>( rhs.im );
119
120 long double const abs_c = std::fabs( c );
121 long double const abs_d = std::fabs( d );
122
123 long double real;
124 long double imag;
125
126 if ( abs_c >= abs_d )
127 {
128 long double const r = d / c;
129 long double const den = c + d * r;
130
131 real = ( a + b * r ) / den;
132 imag = ( b - a * r ) / den;
133 }
134 else
135 {
136 long double const r = c / d;
137 long double const den = d + c * r;
138
139 real = ( a * r + b ) / den;
140 imag = ( b * r - a ) / den;
141 }
142
143 re = static_cast<real_type>( real );
144 im = static_cast<real_type>( imag );
145
146 return *this;
147 }
148 };
149
150#if POLYNOMIAL_ROOTS_HAS_MULTIPRECISION
152 class quad_complex
153 {
154 quad_real re = 0;
155 quad_real im = 0;
156
157 public:
159 quad_real const & real() const { return re; }
161 quad_real const & imag() const { return im; }
162
164 quad_complex() = default;
165
167 quad_complex( quad_real const & real_part, quad_real const & imag_part ) : re( real_part ), im( imag_part ) {}
168
170 quad_complex( real_type real_part, real_type imag_part = 0 ) : re( real_part ), im( imag_part ) {}
171
173 explicit quad_complex( real_complex const & z ) : re( z.real() ), im( z.imag() ) {}
174
176 static inline quad_real abs_real( quad_real const & x ) { return x >= quad_real{ 0 } ? x : -x; }
177
179 inline quad_complex & operator+=( quad_real const & rhs )
180 {
181 re += rhs;
182 return *this;
183 }
184
186 inline quad_complex & operator+=( quad_complex const & rhs )
187 {
188 re += rhs.re;
189 im += rhs.im;
190 return *this;
191 }
192
194 inline quad_complex & operator-=( quad_real const & rhs )
195 {
196 re -= rhs;
197 return *this;
198 }
199
201 inline quad_complex & operator-=( quad_complex const & rhs )
202 {
203 re -= rhs.re;
204 im -= rhs.im;
205 return *this;
206 }
207
209 inline quad_complex & operator*=( quad_real const & rhs )
210 {
211 re *= rhs;
212 im *= rhs;
213 return *this;
214 }
215
217 inline quad_complex & operator*=( quad_complex const & rhs )
218 {
219 quad_real const a = re;
220 quad_real const b = im;
221 quad_real const c = rhs.re;
222 quad_real const d = rhs.im;
223
224 quad_real const real = a * c - b * d;
225 quad_real const imag = a * d + b * c;
226
227 re = real;
228 im = imag;
229
230 return *this;
231 }
232
234 inline quad_complex & operator/=( quad_real const & rhs )
235 {
236 re /= rhs;
237 im /= rhs;
238 return *this;
239 }
240
242 inline quad_complex & operator/=( quad_complex const & rhs )
243 {
244 quad_real const a = re;
245 quad_real const b = im;
246 quad_real const c = rhs.re;
247 quad_real const d = rhs.im;
248
249 quad_real const abs_c = abs_real( c );
250 quad_real const abs_d = abs_real( d );
251
252 quad_real real;
253 quad_real imag;
254
255 if ( abs_c >= abs_d )
256 {
257 quad_real const r = d / c;
258 quad_real const den = c + d * r;
259
260 real = ( a + b * r ) / den;
261 imag = ( b - a * r ) / den;
262 }
263 else
264 {
265 quad_real const r = c / d;
266 quad_real const den = d + c * r;
267
268 real = ( a * r + b ) / den;
269 imag = ( b * r - a ) / den;
270 }
271
272 re = real;
273 im = imag;
274
275 return *this;
276 }
277 };
278#endif
279
281 inline real_complex operator+( real_complex const & a, real_complex const & b )
282 { return { a.real() + b.real(), a.imag() + b.imag() }; }
283
286 { return { a.real() + b, a.imag() }; }
287
290 { return { a + b.real(), b.imag() }; }
291
293 inline real_complex operator-( real_complex const & a, real_complex const & b )
294 { return { a.real() - b.real(), a.imag() - b.imag() }; }
295
298 { return { a.real() - b, a.imag() }; }
299
302 { return { a - b.real(), -b.imag() }; }
303
306 { return { -a.real(), -a.imag() }; }
307
309 inline real_complex operator*( real_complex const & a, real_complex const & b )
310 {
311 real_complex res{ a };
312 res *= b;
313 return res;
314 }
315
318 {
319 real_complex res{ a };
320 res *= b;
321 return res;
322 }
323
326 { return { a * b.real(), a * b.imag() }; }
327
329 inline real_complex operator/( real_complex const & a, real_complex const & b )
330 {
331 real_complex res{ a };
332 res /= b;
333 return res;
334 }
335
338 {
339 real_complex res{ a };
340 res /= b;
341 return res;
342 }
343
346 {
347 real_complex res{ a, 0 };
348 res /= b;
349 return res;
350 }
351
352#if POLYNOMIAL_ROOTS_HAS_MULTIPRECISION
354 inline quad_complex operator+( quad_complex const & a, quad_complex const & b )
355 { return { a.real() + b.real(), a.imag() + b.imag() }; }
356
358 inline quad_complex operator+( quad_complex const & a, quad_real const & b )
359 { return { a.real() + b, a.imag() }; }
360
362 inline quad_complex operator+( quad_real const & a, quad_complex const & b )
363 { return { a + b.real(), b.imag() }; }
364
366 inline quad_complex operator-( quad_complex const & a, quad_complex const & b )
367 { return { a.real() - b.real(), a.imag() - b.imag() }; }
368
370 inline quad_complex operator-( quad_complex const & a, quad_real const & b )
371 { return { a.real() - b, a.imag() }; }
372
374 inline quad_complex operator-( quad_real const & a, quad_complex const & b )
375 { return { a - b.real(), -b.imag() }; }
376
378 inline quad_complex operator-( quad_complex const & a )
379 { return { -a.real(), -a.imag() }; }
380
382 inline quad_complex operator*( quad_complex const & a, quad_complex const & b )
383 {
384 quad_complex res{ a };
385 res *= b;
386 return res;
387 }
388
390 inline quad_complex operator*( quad_complex const & a, quad_real const & b )
391 {
392 quad_complex res{ a };
393 res *= b;
394 return res;
395 }
396
398 inline quad_complex operator*( quad_real const & a, quad_complex const & b )
399 { return { a * b.real(), a * b.imag() }; }
400
402 inline quad_complex operator/( quad_complex const & a, quad_complex const & b )
403 {
404 quad_complex res{ a };
405 res /= b;
406 return res;
407 }
408
410 inline quad_complex operator/( quad_complex const & a, quad_real const & b )
411 {
412 quad_complex res{ a };
413 res /= b;
414 return res;
415 }
416
418 inline quad_complex operator/( quad_real const & a, quad_complex const & b )
419 {
420 quad_complex res{ a, quad_real{ 0 } };
421 res /= b;
422 return res;
423 }
424
425 inline quad_real sqrt( quad_real const & value )
426 {
427 using boost::multiprecision::sqrt;
428 return sqrt( value );
429 }
430
431 inline quad_real cbrt( quad_real const & value )
432 {
433 using boost::multiprecision::cbrt;
434 return cbrt( value );
435 }
436
437 inline quad_real abs2( quad_complex const & value )
438 {
439 quad_real const ax = abs( value.real() );
440 quad_real const ay = abs( value.imag() );
441
442 if ( ax == quad_real{ 0 } ) return ay * ay;
443 if ( ay == quad_real{ 0 } ) return ax * ax;
444
445 quad_real const scale = ax >= ay ? ax : ay;
446 quad_real const x = value.real() / scale;
447 quad_real const y = value.imag() / scale;
448
449 return ( x * x + y * y ) * scale * scale;
450 }
451
452 inline quad_real hypot( quad_real const & x, quad_real const & y )
453 {
454 quad_real const ax = abs( x );
455 quad_real const ay = abs( y );
456
457 if ( ax == quad_real{ 0 } ) return ay;
458 if ( ay == quad_real{ 0 } ) return ax;
459
460 quad_real const scale = ax >= ay ? ax : ay;
461 quad_real const X = x / scale;
462 quad_real const Y = y / scale;
463
464 return sqrt( X * X + Y * Y ) * scale;
465 }
466
467 inline quad_real abs( quad_complex const & value )
468 { return boost::math::hypot( value.real(), value.imag() ); }
469#endif
470
471 inline real_type abs( real_complex const & value )
472 { return std::hypot( value.real(), value.imag() ); }
473
474 inline real_type abs2( real_complex const & value )
475 { return value.real() * value.real() + value.imag() * value.imag(); }
476
477} // namespace PolynomialRoots
478
479#endif
Lightweight complex number type used by the standard-precision solvers.
Definition PolynomialRoots-complex.hxx:30
real_complex & operator-=(real_complex const &rhs)
Subtract a complex number in place.
Definition PolynomialRoots-complex.hxx:72
real_complex(real_type real_part, real_type imag_part=0)
Build a complex number from real and imaginary parts.
Definition PolynomialRoots-complex.hxx:44
real_type const & imag() const
Return the imaginary part.
Definition PolynomialRoots-complex.hxx:38
real_type const & real() const
Return the real part.
Definition PolynomialRoots-complex.hxx:36
real_complex & operator-=(real_type rhs)
Subtract a real scalar in place.
Definition PolynomialRoots-complex.hxx:65
static real_type abs_real(real_type x)
Return the absolute value of a real scalar.
Definition PolynomialRoots-complex.hxx:47
real_complex()=default
Build the zero complex number.
real_complex & operator*=(real_type rhs)
Multiply by a real scalar in place.
Definition PolynomialRoots-complex.hxx:80
real_complex & operator+=(real_complex const &rhs)
Add a complex number in place.
Definition PolynomialRoots-complex.hxx:57
real_complex & operator/=(real_type rhs)
Divide by a real scalar in place.
Definition PolynomialRoots-complex.hxx:105
real_complex & operator/=(real_complex const &rhs)
Divide by a complex number in place using a scaled algorithm.
Definition PolynomialRoots-complex.hxx:113
real_complex & operator*=(real_complex const &rhs)
Multiply by a complex number in place.
Definition PolynomialRoots-complex.hxx:88
real_complex & operator+=(real_type rhs)
Add a real scalar in place.
Definition PolynomialRoots-complex.hxx:50
Definition PolynomialRoots-1-Quadratic.cc:23
real_complex operator*(real_complex const &a, real_complex const &b)
Return the product of two standard-precision complex values.
Definition PolynomialRoots-complex.hxx:309
real_type abs(real_complex const &value)
Definition PolynomialRoots-complex.hxx:471
real_complex operator+(real_complex const &a, real_complex const &b)
Return the sum of two standard-precision complex values.
Definition PolynomialRoots-complex.hxx:281
real_complex operator/(real_complex const &a, real_complex const &b)
Return the quotient of two standard-precision complex values.
Definition PolynomialRoots-complex.hxx:329
real_type abs2(real_complex const &value)
Definition PolynomialRoots-complex.hxx:474
double real_type
Scalar type used by the standard-precision API.
Definition PolynomialRoots.hh:66
real_complex operator-(real_complex const &a, real_complex const &b)
Return the difference of two standard-precision complex values.
Definition PolynomialRoots-complex.hxx:293