complex.H 3.3 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192
  1. // (c) Daniel Llorens - 2005, 2015
  2. // This library is free software; you can redistribute it and/or modify it under
  3. // the terms of the GNU Lesser General Public License as published by the Free
  4. // Software Foundation; either version 3 of the License, or (at your option) any
  5. // later version.
  6. /// @file complex.H
  7. /// @brief Defines the complex type and standard operations on it.
  8. #pragma once
  9. #include <complex>
  10. #include "ra/real.H"
  11. #include "ra/type.H"
  12. namespace ra {
  13. template <class T> constexpr bool is_scalar_def<std::complex<T>> = true;
  14. } // namespace ra
  15. #define RA_REAL double
  16. #define RA_CPLX std::complex<RA_REAL>
  17. #define FOR_FLOAT(R, C) \
  18. inline constexpr C xI(R const x) { return C(0, x); } \
  19. inline constexpr C xI(C const z) { return C(-z.imag(), z.real()); } \
  20. inline constexpr R real_part(C const & z) { return z.real(); } \
  21. inline constexpr R imag_part(C const & z) { return z.imag(); } \
  22. inline constexpr R & real_part(C & z) { return reinterpret_cast<R *>(&z)[0]; } \
  23. inline constexpr R & imag_part(C & z) { return reinterpret_cast<R *>(&z)[1]; } \
  24. inline constexpr R sqrm(C const x) { return sqrm(x.real())+sqrm(x.imag()); } \
  25. inline constexpr R sqrm(C const x, C const y) { return sqrm(x.real()-y.real())+sqrm(x.imag()-y.imag()); } \
  26. inline constexpr R norm2(C const x) { return std::hypot(x.real(), x.imag()); } \
  27. inline constexpr R norm2(C const x, C const y) { return std::sqrt(sqrm(x, y)); } \
  28. inline constexpr R abs(C const x, C const y) { return std::sqrt(sqrm(x, y)); } \
  29. inline C sqr(C const x) { return x*x; } \
  30. inline C dot(C const x, C const y) { return x*y; }
  31. FOR_FLOAT(double, std::complex<double>);
  32. FOR_FLOAT(float, std::complex<float>);
  33. #undef FOR_FLOAT
  34. inline RA_CPLX fma(RA_CPLX const & a, RA_CPLX const & b, RA_CPLX const & c)
  35. {
  36. return RA_CPLX(fma(a.real(), b.real(), fma(-a.imag(), b.imag(), c.real())),
  37. fma(a.real(), b.imag(), fma(a.imag(), b.real(), c.imag())));
  38. }
  39. // conj(a) * b + c
  40. inline RA_CPLX fma_conj(RA_CPLX const & a, RA_CPLX const & b, RA_CPLX const & c)
  41. {
  42. return RA_CPLX(fma(a.real(), b.real(), fma(a.imag(), b.imag(), c.real())),
  43. fma(a.real(), b.imag(), fma(-a.imag(), b.real(), c.imag())));
  44. }
  45. // conj(a) * b
  46. inline RA_CPLX mul_conj(RA_CPLX const & a, RA_CPLX const & b)
  47. {
  48. return RA_CPLX(+a.real()*b.real()+a.imag()*b.imag(),
  49. a.real()*b.imag()-a.imag()*b.real());
  50. }
  51. inline bool isfinite(RA_CPLX const z)
  52. {
  53. return std::isfinite(z.real()) && std::isfinite(z.imag());
  54. }
  55. inline bool isnan(RA_CPLX const z)
  56. {
  57. return std::isnan(z.real()) || std::isnan(z.imag());
  58. }
  59. inline bool isinf(RA_CPLX const z)
  60. {
  61. bool const a = std::isinf(z.real());
  62. bool const b = std::isinf(z.imag());
  63. return (a && b) || (a && std::isfinite(z.imag())) || (b && std::isfinite(z.real()));
  64. }
  65. inline void swap(RA_CPLX & a, RA_CPLX & b)
  66. {
  67. std::swap(a, b);
  68. }
  69. inline RA_CPLX tanh(RA_CPLX const z)
  70. {
  71. return (z.real()>300.) ? 1. : ((z.real()<-300.) ? -1. : sinh(z)/cosh(z));
  72. }
  73. inline RA_REAL rel_error(RA_CPLX const a, RA_CPLX const b)
  74. {
  75. return (a==0. && b==0.) ? 0. : 2.*abs(a, b)/(abs(a)+abs(b));
  76. }
  77. #undef RA_CPLX
  78. #undef RA_REAL