/* complex.h Numerical Array Extension for Ruby (C) Copyright 1999-2017 by Masahiro TANAKA */ static inline dtype c_new(rtype r, rtype i) { dtype z; REAL(z) = r; IMAG(z) = i; return z; } static inline dtype c_set_real(dtype x, rtype r) { REAL(x)=r; return x; } static inline dtype c_set_imag(dtype x, rtype i) { IMAG(x)=i; return x; } static inline VALUE COMP2NUM(dtype x) { VALUE v; v = rb_funcall(rb_intern("Kernel"), rb_intern("Complex"), 2, rb_float_new(REAL(x)), rb_float_new(IMAG(x))); return v; } static inline dtype NUM2COMP(VALUE v) { dtype z; REAL(z) = NUM2DBL(rb_funcall(v,id_real,0)); IMAG(z) = NUM2DBL(rb_funcall(v,id_imag,0)); return z; } #define c_is_zero(x) (REAL(x)==0 && IMAG(x)==0) #define c_eq(x,y) (REAL(x)==REAL(y) && IMAG(x)==IMAG(y)) #define c_ne(x,y) (REAL(x)!=REAL(y) || IMAG(x)!=IMAG(y)) #define c_isnan(x) (isnan(REAL(x)) || isnan(IMAG(x))) #define c_isinf(x) (isinf(REAL(x)) || isinf(IMAG(x))) #define c_isposinf(x) ((isinf(REAL(x)) && signbit(REAL(x))==0) || \ (isinf(IMAG(x)) && signbit(IMAG(x))==0)) #define c_isneginf(x) ((isinf(REAL(x)) && signbit(REAL(x))) || \ (isinf(IMAG(x)) && signbit(IMAG(x)))) #define c_isfinite(x) (isfinite(REAL(x)) && isfinite(IMAG(x))) static inline dtype c_zero() { dtype z; REAL(z) = 0; IMAG(z) = 0; return z; } static inline dtype c_one() { dtype z; REAL(z) = 1; IMAG(z) = 0; return z; } static inline dtype c_minus(dtype x) { dtype z; REAL(z) = -REAL(x); IMAG(z) = -IMAG(x); return z; } static inline dtype c_im(dtype x) { dtype z; REAL(z) = -IMAG(x); IMAG(z) = REAL(x); return z; } static inline dtype c_add(dtype x, dtype y) { dtype z; REAL(z) = REAL(x)+REAL(y); IMAG(z) = IMAG(x)+IMAG(y); return z; } static inline dtype c_sub(dtype x, dtype y) { dtype z; REAL(z) = REAL(x)-REAL(y); IMAG(z) = IMAG(x)-IMAG(y); return z; } static inline dtype c_mul(dtype x, dtype y) { dtype z; REAL(z) = REAL(x)*REAL(y)-IMAG(x)*IMAG(y); IMAG(z) = REAL(x)*IMAG(y)+IMAG(x)*REAL(y); return z; } static inline dtype c_mul_r(dtype x, rtype y) { dtype z; REAL(z) = REAL(x)*y; IMAG(z) = IMAG(x)*y; return z; } static inline dtype c_div(dtype x, dtype y) { dtype z; rtype s,yr,yi; s = r_hypot(REAL(y),IMAG(y)); yr = REAL(y)/s; yi = IMAG(y)/s; REAL(z) = (REAL(x)*yr+IMAG(x)*yi)/s; IMAG(z) = (IMAG(x)*yr-REAL(x)*yi)/s; return z; } static inline dtype c_div_r(dtype x, rtype y) { dtype z; REAL(z) = REAL(x)/y; IMAG(z) = IMAG(x)/y; return z; } static inline dtype c_reciprocal(dtype x) { dtype z; if ( r_abs(REAL(x)) > r_abs(IMAG(x)) ) { IMAG(z) = IMAG(x)/REAL(x); REAL(z) = (1+IMAG(z)*IMAG(z))*REAL(x); IMAG(z) /= -REAL(z); REAL(z) = 1/REAL(z); } else { REAL(z) = REAL(x)/IMAG(x); IMAG(z) = (1+REAL(z)*REAL(z))*IMAG(x); REAL(z) /= IMAG(z); IMAG(z) = -1/IMAG(z); } return z; } static inline dtype c_square(dtype x) { dtype z; REAL(z) = REAL(x)*REAL(x)-IMAG(x)*IMAG(x); IMAG(z) = 2*REAL(x)*IMAG(x); return z; } static inline dtype c_sqrt(dtype x) { dtype z; rtype xr, xi, r; xr = REAL(x)/2; xi = IMAG(x)/2; r = r_hypot(xr,xi); if (xr>0) { REAL(z) = sqrt(r+xr); IMAG(z) = xi/REAL(z); } else if ( (r-=xr)!=0 ) { IMAG(z) = (xi>=0) ? sqrt(r):-sqrt(r); REAL(z) = xi/IMAG(z); } else { REAL(z) = IMAG(z) = 0; } return z; } static inline dtype c_log(dtype x) { dtype z; REAL(z) = r_log(r_hypot(REAL(x),IMAG(x))); IMAG(z) = r_atan2(IMAG(x),REAL(x)); return z; } static inline dtype c_log2(dtype x) { dtype z; z = c_log(x); z = c_mul_r(x,M_LOG2E); return z; } static inline dtype c_log10(dtype x) { dtype z; z = c_log(x); z = c_mul_r(x,M_LOG10E); return z; } static inline dtype c_exp(dtype x) { dtype z; rtype a = r_exp(REAL(x)); REAL(z) = a*r_cos(IMAG(x)); IMAG(z) = a*r_sin(IMAG(x)); return z; } static inline dtype c_exp2(dtype x) { dtype z; rtype a = r_exp(REAL(x)*M_LN2); REAL(z) = a*r_cos(IMAG(x)); IMAG(z) = a*r_sin(IMAG(x)); return z; } static inline dtype c_exp10(dtype x) { dtype z; rtype a = r_exp(REAL(x)*M_LN10); REAL(z) = a*r_cos(IMAG(x)); IMAG(z) = a*r_sin(IMAG(x)); return z; } static inline dtype c_sin(dtype x) { dtype z; REAL(z) = r_sin(REAL(x))*r_cosh(IMAG(x)); IMAG(z) = r_cos(REAL(x))*r_sinh(IMAG(x)); return z; } static inline dtype c_sinh(dtype x) { dtype z; REAL(z) = r_sinh(REAL(x))*r_cos(IMAG(x)); IMAG(z) = r_cosh(REAL(x))*r_sin(IMAG(x)); return z; } static inline dtype c_cos(dtype x) { dtype z; REAL(z) = r_cos(REAL(x))*r_cosh(IMAG(x)); IMAG(z) = -r_sin(REAL(x))*r_sinh(IMAG(x)); return z; } static inline dtype c_cosh(dtype x) { dtype z; REAL(z) = r_cosh(REAL(x))*r_cos(IMAG(x)); IMAG(z) = r_sinh(REAL(x))*r_sin(IMAG(x)); return z; } static inline dtype c_tan(dtype x) { dtype z; rtype c, d; if (r_abs(IMAG(x))<1) { c = r_cos(REAL(x)); d = r_sinh(IMAG(x)); d = c*c + d*d; REAL(z) = 0.5*r_sin(2*REAL(x))/d; IMAG(z) = 0.5*r_sinh(2*IMAG(x))/d; } else { d = r_exp(-IMAG(x)); c = 2*d/(1-d*d); c = c*c; d = r_cos(REAL(x)); d = 1.0 + d*d*c; REAL(z) = 0.5*r_sin(2*REAL(x))*c/d; IMAG(z) = 1/r_tanh(IMAG(x))/d; } return z; } static inline dtype c_tanh(dtype x) { dtype z; rtype c, d, s; c = r_cos(IMAG(x)); s = r_sinh(REAL(x)); d = c*c + s*s; if (r_abs(REAL(x))<1) { REAL(z) = s*r_cosh(REAL(x))/d; IMAG(z) = 0.5*r_sin(2*IMAG(x))/d; } else { c = c / s; c = 1 + c*c; REAL(z) = 1/(r_tanh(REAL(x))*c); IMAG(z) = 0.5*r_sin(2*IMAG(x))/d; } return z; } static inline dtype c_asin(dtype x) { dtype z, y; y = c_square(x); REAL(y) = 1-REAL(y); IMAG(y) = -IMAG(y); y = c_sqrt(y); REAL(y) -= IMAG(x); IMAG(y) += REAL(x); y = c_log(y); REAL(z) = IMAG(y); IMAG(z) = -REAL(y); return z; } static inline dtype c_asinh(dtype x) { dtype z, y; y = c_square(x); REAL(y) += 1; y = c_sqrt(y); REAL(y) += REAL(x); IMAG(y) += IMAG(x); z = c_log(y); return z; } static inline dtype c_acos(dtype x) { dtype z, y; y = c_square(x); REAL(y) = 1-REAL(y); IMAG(y) = -IMAG(y); y = c_sqrt(y); REAL(z) = REAL(x)-IMAG(y); IMAG(z) = IMAG(x)+REAL(y); y = c_log(z); REAL(z) = IMAG(y); IMAG(z) = -REAL(y); return z; } static inline dtype c_acosh(dtype x) { dtype z, y; y = c_square(x); REAL(y) -= 1; y = c_sqrt(y); REAL(y) += REAL(x); IMAG(y) += IMAG(x); z = c_log(y); return z; } static inline dtype c_atan(dtype x) { dtype z, y; REAL(y) = -REAL(x); IMAG(y) = 1-IMAG(x); REAL(z) = REAL(x); IMAG(z) = 1+IMAG(x); y = c_div(z,y); y = c_log(y); REAL(z) = -IMAG(y)/2; IMAG(z) = REAL(y)/2; return z; } static inline dtype c_atanh(dtype x) { dtype z, y; REAL(y) = 1-REAL(x); IMAG(y) = -IMAG(x); REAL(z) = 1+REAL(x); IMAG(z) = IMAG(x); y = c_div(z,y); y = c_log(y); REAL(z) = REAL(y)/2; IMAG(z) = IMAG(y)/2; return z; } static inline dtype c_pow(dtype x, dtype y) { dtype z; if (c_is_zero(y)) { z = c_one(); } else if (c_is_zero(x) && REAL(y)>0 && IMAG(y)==0) { z = c_zero(); } else { z = c_log(x); z = c_mul(y,z); z = c_exp(z); } return z; } static inline dtype c_pow_int(dtype x, int p) { dtype z = c_one(); if (p<0) { x = c_pow_int(x,-p); return c_reciprocal(x); } if (p==2) {return c_square(x);} if (p&1) {z = x;} p >>= 1; while (p) { x = c_square(x); if (p&1) z = c_mul(z,x); p >>= 1; } return z; } static inline dtype c_cbrt(dtype x) { dtype z; z = c_log(x); z = c_div_r(z,3); z = c_exp(z); return z; } static inline rtype c_abs(dtype x) { return r_hypot(REAL(x),IMAG(x)); } static inline rtype c_abs_square(dtype x) { return REAL(x)*REAL(x)+IMAG(x)*IMAG(x); } /* static inline rtype c_hypot(dtype x, dtype y) { return r_hypot(c_abs(x),c_abs(y)); } */