complex.H 3.5 KB

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