%PDF- %PDF-
| Direktori : /backups/router/usr/local/lib/python3.11/site-packages/numexpr/ |
| Current File : //backups/router/usr/local/lib/python3.11/site-packages/numexpr/complex_functions.hpp |
#ifndef NUMEXPR_COMPLEX_FUNCTIONS_HPP
#define NUMEXPR_COMPLEX_FUNCTIONS_HPP
/*********************************************************************
Numexpr - Fast numerical array expression evaluator for NumPy.
License: MIT
Author: See AUTHORS.txt
See LICENSE.txt for details about copyright and rights to use.
**********************************************************************/
// Replace npy_cdouble with std::complex<double>
#include <complex>
/* constants */
static std::complex<double> nc_1(1., 0.);
static std::complex<double> nc_half(0.5, 0.);
static std::complex<double> nc_i(0., 1.);
static std::complex<double> nc_i2(0., 0.5);
/*
static std::complex<double> nc_mi = {0., -1.};
static std::complex<double> nc_pi2 = {M_PI/2., 0.};
*/
/* *************************** WARNING *****************************
Due to the way Numexpr places the results of operations, the *x and *r
pointers do point to the same address (apparently this doesn't happen
in NumPy). So, measures should be taken so as to not to reuse *x
after the first *r has been overwritten.
*********************************************************************
*/
static void
nc_assign(std::complex<double> *x, std::complex<double> *r)
{
r->real(x->real());
r->imag(x->imag());
return;
}
static void
nc_sum(std::complex<double> *a, std::complex<double> *b, std::complex<double> *r)
{
r->real(a->real() + b->real());
r->imag(a->imag() + b->imag());
return;
}
static void
nc_diff(std::complex<double> *a, std::complex<double> *b, std::complex<double> *r)
{
r->real(a->real() - b->real());
r->imag(a->imag() - b->imag());
return;
}
static void
nc_neg(std::complex<double> *a, std::complex<double> *r)
{
r->real(-a->real());
r->imag(-a->imag());
return;
}
static void
nc_conj(std::complex<double> *a, std::complex<double> *r)
{
r->real(a->real());
r->imag(-a->imag());
return;
}
// Needed for allowing the internal casting in numexpr machinery for
// conjugate operations
inline float fconjf(float x)
{
return x;
}
// Needed for allowing the internal casting in numexpr machinery for
// conjugate operations
inline double fconj(double x)
{
return x;
}
static void
nc_prod(std::complex<double> *a, std::complex<double> *b, std::complex<double> *r)
{
double ar=a->real(), br=b->real(), ai=a->imag(), bi=b->imag();
r->real(ar*br - ai*bi);
r->imag(ar*bi + ai*br);
return;
}
static void
nc_quot(std::complex<double> *a, std::complex<double> *b, std::complex<double> *r)
{
double ar=a->real(), br=b->real(), ai=a->imag(), bi=b->imag();
double d = br*br + bi*bi;
r->real((ar*br + ai*bi)/d);
r->imag((ai*br - ar*bi)/d);
return;
}
static void
nc_sqrt(std::complex<double> *x, std::complex<double> *r)
{
double s,d;
if (x->real() == 0. && x->imag() == 0.)
*r = *x;
else {
s = sqrt((fabs(x->real()) + hypot(x->real(),x->imag()))/2);
d = x->imag()/(2*s);
if (x->real() > 0.) {
r->real(s);
r->imag(d);
}
else if (x->imag() >= 0.) {
r->real(d);
r->imag(s);
}
else {
r->real(-d);
r->imag(-s);
}
}
return;
}
static void
nc_log(std::complex<double> *x, std::complex<double> *r)
{
double l = hypot(x->real(),x->imag());
r->imag(atan2(x->imag(), x->real()));
r->real(log(l));
return;
}
static void
nc_log1p(std::complex<double> *x, std::complex<double> *r)
{
double l = hypot(x->real() + 1.0,x->imag());
r->imag(atan2(x->imag(), x->real() + 1.0));
r->real(log(l));
return;
}
static void
nc_exp(std::complex<double> *x, std::complex<double> *r)
{
double a = exp(x->real());
r->real(a*cos(x->imag()));
r->imag(a*sin(x->imag()));
return;
}
static void
nc_expm1(std::complex<double> *x, std::complex<double> *r)
{
double a = sin(x->imag() / 2);
double b = exp(x->real());
r->real(expm1(x->real()) * cos(x->imag()) - 2 * a * a);
r->imag(b * sin(x->imag()));
return;
}
static void
nc_pow(std::complex<double> *a, std::complex<double> *b, std::complex<double> *r)
{
npy_intp n;
double ar=a->real(), br=b->real(), ai=a->imag(), bi=b->imag();
if (br == 0. && bi == 0.) {
r->real(1.);
r->imag(0.);
return;
}
if (ar == 0. && ai == 0.) {
r->real(0.);
r->imag(0.);
return;
}
if (bi == 0 && (n=(npy_intp)br) == br) {
if (n > -100 && n < 100) {
std::complex<double> p, aa;
npy_intp mask = 1;
if (n < 0) n = -n;
aa = nc_1;
p.real(ar); p.imag(ai);
while (1) {
if (n & mask)
nc_prod(&aa,&p,&aa);
mask <<= 1;
if (n < mask || mask <= 0) break;
nc_prod(&p,&p,&p);
}
r->real(aa.real()); r->imag(aa.imag());
if (br < 0) nc_quot(&nc_1, r, r);
return;
}
}
/* complexobject.c uses an inline version of this formula
investigate whether this had better performance or accuracy */
nc_log(a, r);
nc_prod(r, b, r);
nc_exp(r, r);
return;
}
static void
nc_prodi(std::complex<double> *x, std::complex<double> *r)
{
double xr = x->real();
r->real(-x->imag());
r->imag(xr);
return;
}
static void
nc_acos(std::complex<double> *x, std::complex<double> *r)
{
std::complex<double> a, *pa=&a;
nc_assign(x, pa);
nc_prod(x,x,r);
nc_diff(&nc_1, r, r);
nc_sqrt(r, r);
nc_prodi(r, r);
nc_sum(pa, r, r);
nc_log(r, r);
nc_prodi(r, r);
nc_neg(r, r);
return;
/* return nc_neg(nc_prodi(nc_log(nc_sum(x,nc_prod(nc_i,
nc_sqrt(nc_diff(nc_1,nc_prod(x,x))))))));
*/
}
static void
nc_acosh(std::complex<double> *x, std::complex<double> *r)
{
std::complex<double> t, a, *pa=&a;
nc_assign(x, pa);
nc_sum(x, &nc_1, &t);
nc_sqrt(&t, &t);
nc_diff(x, &nc_1, r);
nc_sqrt(r, r);
nc_prod(&t, r, r);
nc_sum(pa, r, r);
nc_log(r, r);
return;
/*
return nc_log(nc_sum(x,
nc_prod(nc_sqrt(nc_sum(x,nc_1)), nc_sqrt(nc_diff(x,nc_1)))));
*/
}
static void
nc_asin(std::complex<double> *x, std::complex<double> *r)
{
std::complex<double> a, *pa=&a;
nc_prodi(x, pa);
nc_prod(x, x, r);
nc_diff(&nc_1, r, r);
nc_sqrt(r, r);
nc_sum(pa, r, r);
nc_log(r, r);
nc_prodi(r, r);
nc_neg(r, r);
return;
/*
return nc_neg(nc_prodi(nc_log(nc_sum(nc_prod(nc_i,x),
nc_sqrt(nc_diff(nc_1,nc_prod(x,x)))))));
*/
}
static void
nc_asinh(std::complex<double> *x, std::complex<double> *r)
{
std::complex<double> a, *pa=&a;
nc_assign(x, pa);
nc_prod(x, x, r);
nc_sum(&nc_1, r, r);
nc_sqrt(r, r);
nc_sum(r, pa, r);
nc_log(r, r);
return;
/*
return nc_log(nc_sum(nc_sqrt(nc_sum(nc_1,nc_prod(x,x))),x));
*/
}
static void
nc_atan(std::complex<double> *x, std::complex<double> *r)
{
std::complex<double> a, *pa=&a;
nc_diff(&nc_i, x, pa);
nc_sum(&nc_i, x, r);
nc_quot(r, pa, r);
nc_log(r,r);
nc_prod(&nc_i2, r, r);
return;
/*
return nc_prod(nc_i2,nc_log(nc_quot(nc_sum(nc_i,x),nc_diff(nc_i,x))));
*/
}
static void
nc_atanh(std::complex<double> *x, std::complex<double> *r)
{
std::complex<double> a, b, *pa=&a, *pb=&b;
nc_assign(x, pa);
nc_diff(&nc_1, pa, r);
nc_sum(&nc_1, pa, pb);
nc_quot(pb, r, r);
nc_log(r, r);
nc_prod(&nc_half, r, r);
return;
/*
return nc_prod(nc_half,nc_log(nc_quot(nc_sum(nc_1,x),nc_diff(nc_1,x))));
*/
}
static void
nc_cos(std::complex<double> *x, std::complex<double> *r)
{
double xr=x->real(), xi=x->imag();
r->real(cos(xr)*cosh(xi));
r->imag(-sin(xr)*sinh(xi));
return;
}
static void
nc_cosh(std::complex<double> *x, std::complex<double> *r)
{
double xr=x->real(), xi=x->imag();
r->real(cos(xi)*cosh(xr));
r->imag(sin(xi)*sinh(xr));
return;
}
#define M_LOG10_E 0.434294481903251827651128918916605082294397
static void
nc_log10(std::complex<double> *x, std::complex<double> *r)
{
nc_log(x, r);
r->real(r->real() * M_LOG10_E);
r->imag(r->imag() * M_LOG10_E);
return;
}
static void
nc_sin(std::complex<double> *x, std::complex<double> *r)
{
double xr=x->real(), xi=x->imag();
r->real(sin(xr)*cosh(xi));
r->imag(cos(xr)*sinh(xi));
return;
}
static void
nc_sinh(std::complex<double> *x, std::complex<double> *r)
{
double xr=x->real(), xi=x->imag();
r->real(cos(xi)*sinh(xr));
r->imag(sin(xi)*cosh(xr));
return;
}
static void
nc_tan(std::complex<double> *x, std::complex<double> *r)
{
double sr,cr,shi,chi;
double rs,is,rc,ic;
double d;
double xr=x->real(), xi=x->imag();
sr = sin(xr);
cr = cos(xr);
shi = sinh(xi);
chi = cosh(xi);
rs = sr*chi;
is = cr*shi;
rc = cr*chi;
ic = -sr*shi;
d = rc*rc + ic*ic;
r->real((rs*rc+is*ic)/d);
r->imag((is*rc-rs*ic)/d);
return;
}
static void
nc_tanh(std::complex<double> *x, std::complex<double> *r)
{
double si,ci,shr,chr;
double rs,is,rc,ic;
double d;
double xr=x->real(), xi=x->imag();
si = sin(xi);
ci = cos(xi);
shr = sinh(xr);
chr = cosh(xr);
rs = ci*shr;
is = si*chr;
rc = ci*chr;
ic = si*shr;
d = rc*rc + ic*ic;
r->real((rs*rc+is*ic)/d);
r->imag((is*rc-rs*ic)/d);
return;
}
static void
nc_abs(std::complex<double> *x, std::complex<double> *r)
{
r->real(sqrt(x->real()*x->real() + x->imag()*x->imag()));
r->imag(0);
}
#endif // NUMEXPR_COMPLEX_FUNCTIONS_HPP