190 lines
7.2 KiB
C++
190 lines
7.2 KiB
C++
//! \~\file pimathcomplex.h
|
||
//! \~\ingroup Math
|
||
//! \~\brief
|
||
//! \~english Complex numbers
|
||
//! \~russian Комплексные числа
|
||
/*
|
||
PIP - Platform Independent Primitives
|
||
PIP math complex
|
||
Ivan Pelipenko peri4ko@yandex.ru, Andrey Bychkov work.a.b@yandex.ru
|
||
|
||
This program is free software: you can redistribute it and/or modify
|
||
it under the terms of the GNU Lesser General Public License as published by
|
||
the Free Software Foundation, either version 3 of the License, or
|
||
(at your option) any later version.
|
||
|
||
This program is distributed in the hope that it will be useful,
|
||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||
GNU Lesser General Public License for more details.
|
||
|
||
You should have received a copy of the GNU Lesser General Public License
|
||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||
*/
|
||
|
||
#ifndef PIMATHCOMPLEX_H
|
||
#define PIMATHCOMPLEX_H
|
||
|
||
#include "pibytearray.h"
|
||
#include "pimathbase.h"
|
||
#include "pivector2d.h"
|
||
|
||
#include <complex>
|
||
|
||
#define PIP_MATH_COMPLEX
|
||
|
||
using std::complex;
|
||
|
||
//! \~\ingroup Math
|
||
//! \~english Type trait that reports whether \a T is a specialization of \c std::complex.
|
||
//! \~russian Признак типа, определяющий, является ли \a T специализацией \c std::complex.
|
||
template<typename T>
|
||
struct is_complex: std::false_type {};
|
||
|
||
//! \~\ingroup Math
|
||
//! \~english Specialization for complex types.
|
||
//! \~russian Специализация для комплексных типов.
|
||
template<typename T>
|
||
struct is_complex<std::complex<T>>: std::true_type {};
|
||
|
||
//! \~english Complex integer type.
|
||
//! \~russian Комплексный тип на целых числах.
|
||
typedef complex<int> complexi;
|
||
//! \~english Complex short integer type.
|
||
//! \~russian Комплексный тип на \c short.
|
||
typedef complex<short> complexs;
|
||
//! \~english Complex single-precision type.
|
||
//! \~russian Комплексный тип одинарной точности.
|
||
typedef complex<float> complexf;
|
||
//! \~english Complex extended-precision type.
|
||
//! \~russian Комплексный тип расширенной точности.
|
||
typedef complex<ldouble> complexld;
|
||
#ifndef QPIEVALUATOR_COMPLEX
|
||
//! \~english Complex double-precision type.
|
||
//! \~russian Комплексный тип двойной точности.
|
||
typedef complex<double> complexd;
|
||
|
||
//! \~english Imaginary unit in double precision.
|
||
//! \~russian Мнимая единица двойной точности.
|
||
const complexd complexd_i(0., 1.);
|
||
//! \~english Zero value in double precision.
|
||
//! \~russian Нулевое значение двойной точности.
|
||
const complexd complexd_0(0.);
|
||
//! \~english Unity value in double precision.
|
||
//! \~russian Единичное значение двойной точности.
|
||
const complexd complexd_1(1.);
|
||
#endif
|
||
//! \~english Imaginary unit in extended precision.
|
||
//! \~russian Мнимая единица расширенной точности.
|
||
const complexld complexld_i(0., 1.);
|
||
//! \~english Zero value in extended precision.
|
||
//! \~russian Нулевое значение расширенной точности.
|
||
const complexld complexld_0(0.);
|
||
//! \~english Unity value in extended precision.
|
||
//! \~russian Единичное значение расширенной точности.
|
||
const complexld complexld_1(1.);
|
||
|
||
//! \~english Returns sign for real and imaginary parts independently.
|
||
//! \~russian Возвращает знак действительной и мнимой частей по отдельности.
|
||
inline complexd sign(const complexd & x) {
|
||
return complexd(sign(x.real()), sign(x.imag()));
|
||
}
|
||
|
||
//! \~\brief
|
||
//! \~english Round, floor, and ceil functions for complex numbers.
|
||
//! \~russian Округление, округление вниз и округление вверх комплексных чисел.
|
||
inline complexd round(const complexd & c) {
|
||
return complexd(piRound<double>(c.real()), piRound<double>(c.imag()));
|
||
}
|
||
|
||
//! \~\brief
|
||
//! \~english Floor a complex number.
|
||
//! \~russian Округление комплексного числа вниз.
|
||
inline complexd floor(const complexd & c) {
|
||
return complexd(floor(c.real()), floor(c.imag()));
|
||
}
|
||
|
||
//! \~\brief
|
||
//! \~english Ceil a complex number.
|
||
//! \~russian Округление комплексного числа вверх.
|
||
inline complexd ceil(const complexd & c) {
|
||
return complexd(ceil(c.real()), ceil(c.imag()));
|
||
}
|
||
|
||
#define acosc acos
|
||
#define asinc asin
|
||
#define atanc atan
|
||
|
||
#ifdef CC_GCC
|
||
# if CC_GCC_VERSION <= 0x025F
|
||
inline complexd tan(const complexd & c) {
|
||
return sin(c) / cos(c);
|
||
}
|
||
inline complexd tanh(const complexd & c) {
|
||
return sinh(c) / cosh(c);
|
||
}
|
||
inline complexd log2(const complexd & c) {
|
||
return log(c) / M_LN2;
|
||
}
|
||
inline complexd log10(const complexd & c) {
|
||
return log(c) / M_LN10;
|
||
}
|
||
# endif
|
||
#endif
|
||
|
||
//! \relatesalso PICout
|
||
//! \~english Writes a complex number as `(real; imag)`.
|
||
//! \~russian Записывает комплексное число в виде `(real; imag)`.
|
||
template<typename T>
|
||
inline PICout operator<<(PICout s, const complex<T> & v) {
|
||
s.space();
|
||
s.saveAndSetControls(0);
|
||
s << "(" << v.real() << "; " << v.imag() << ")";
|
||
s.restoreControls();
|
||
return s;
|
||
}
|
||
|
||
|
||
//! \~english Returns magnitudes of all complex elements in the vector.
|
||
//! \~russian Возвращает модули всех комплексных элементов вектора.
|
||
inline PIVector<double> abs(const PIVector<complexd> & v) {
|
||
PIVector<double> result;
|
||
result.resize(v.size());
|
||
for (uint i = 0; i < v.size(); i++)
|
||
result[i] = abs(v[i]);
|
||
return result;
|
||
}
|
||
|
||
|
||
//! \~english Returns element-wise magnitudes of a complex matrix.
|
||
//! \~russian Возвращает матрицу модулей для комплексной матрицы.
|
||
inline PIVector2D<double> abs(const PIVector2D<complexd> & v) {
|
||
PIVector2D<double> result(v.rows(), v.cols());
|
||
for (uint i = 0; i < v.rows(); i++)
|
||
for (uint j = 0; j < v.cols(); j++)
|
||
result[i][j] = abs(v.element(i, j));
|
||
return result;
|
||
}
|
||
|
||
|
||
//! \~english Checks whether a floating-point value is close to zero.
|
||
//! \~russian Проверяет, находится ли вещественное значение вблизи нуля.
|
||
template<typename T, typename std::enable_if<std::is_floating_point<T>::value, int>::type = 0>
|
||
inline bool PIMathFloatNullCompare(const T v) {
|
||
static_assert(std::is_floating_point<T>::value, "Type must be floating point");
|
||
return (piAbs(v) < T(1E-200));
|
||
}
|
||
|
||
//! \~english Checks whether a complex value with floating-point components is close to zero.
|
||
//! \~russian Проверяет, находится ли комплексное значение с вещественными компонентами вблизи нуля.
|
||
template<typename T,
|
||
typename std::enable_if<std::is_floating_point<decltype(T::real)>::value && std::is_floating_point<decltype(T::imag)>::value,
|
||
int>::type = 0>
|
||
inline bool PIMathFloatNullCompare(const T v) {
|
||
static_assert(std::is_floating_point<decltype(v.real)>::value, "Type must be floating point");
|
||
static_assert(std::is_floating_point<decltype(v.imag)>::value, "Type must be floating point");
|
||
return (abs(v) < float(1E-200));
|
||
}
|
||
|
||
#endif // PIMATHCOMPLEX_H
|