void r_perm_matrix_complex_128(__complex128 r[MATRIX_SIZE][MATRIX_SIZE]){ int i,j; __float128 nn = MATRIX_SIZE; std::random_device rd; std::mt19937 mt(rd()); if(! init_for_perm_flg){ init_for_perm(); } for(i=0; i<MATRIX_SIZE; i++){ for(j=0; j<MATRIX_SIZE; j++){ COMPLEX_ASSIGN(r[i][j], 0.0Q, 0.0Q); } } std::vector<int> perm(for_perm,for_perm+MATRIX_SIZE); for(i=0; i<MATRIX_SIZE; i++){ __float128 rval = random_float_128(M_PIq); int idx = mt() % (MATRIX_SIZE - i); if(rval < 0.0Q) rval = -rval; COMPLEX_ASSIGN(r[i][perm[idx]], cosq(-2.0Q*M_PIq*rval/nn), sinq(-2.0Q*M_PIq*rval/nn)); perm.erase(perm.begin()+idx); } }
__complex128 ctanhq (__complex128 a) { __float128 rt = tanhq (REALPART (a)), it = tanq (IMAGPART (a)); __complex128 n, d; COMPLEX_ASSIGN (n, rt, it); COMPLEX_ASSIGN (d, 1, rt * it); return C128_DIV(n,d); }
long double complex ctanl (long double complex a) { long double rt, it; long double complex n, d; rt = tanl (REALPART (a)); it = tanhl (IMAGPART (a)); COMPLEX_ASSIGN (n, rt, it); COMPLEX_ASSIGN (d, 1, - (rt * it)); return n / d; }
float complex ctanf (float complex a) { float rt, it; float complex n, d; rt = tanf (REALPART (a)); it = tanhf (IMAGPART (a)); COMPLEX_ASSIGN (n, rt, it); COMPLEX_ASSIGN (d, 1, - (rt * it)); return n / d; }
double complex ctan (double complex a) { double rt, it; double complex n, d; rt = tan (REALPART (a)); it = tanh (IMAGPART (a)); COMPLEX_ASSIGN (n, rt, it); COMPLEX_ASSIGN (d, 1, - (rt * it)); return n / d; }
/* sqrt(z). Algorithm pulled from glibc. */ GFC_COMPLEX_4 csqrtf (GFC_COMPLEX_4 z) { GFC_REAL_4 re; GFC_REAL_4 im; GFC_COMPLEX_4 v; re = REALPART (z); im = IMAGPART (z); if (im == 0.0) { if (re < 0.0) { COMPLEX_ASSIGN (v, 0.0, copysignf (sqrtf (-re), im)); } else { COMPLEX_ASSIGN (v, fabsf (sqrt (re)), copysignf (0.0, im)); } } else if (re == 0.0) { GFC_REAL_4 r; r = sqrtf (0.5 * fabs (im)); COMPLEX_ASSIGN (v, copysignf (r, im), r); } else { GFC_REAL_4 d, r, s; d = hypotf (re, im); /* Use the identity 2 Re res Im res = Im x to avoid cancellation error in d +/- Re x. */ if (re > 0) { r = sqrtf (0.5 * d + 0.5 * re); s = (0.5 * im) / r; } else { s = sqrtf (0.5 * d - 0.5 * re); r = fabsf ((0.5 * im) / s); } COMPLEX_ASSIGN (v, r, copysignf (s, im)); } return v; }
long double complex csqrtl (long double complex z) { long double re, im; long double complex v; re = REALPART (z); im = IMAGPART (z); if (im == 0) { if (re < 0) { COMPLEX_ASSIGN (v, 0, copysignl (sqrtl (-re), im)); } else { COMPLEX_ASSIGN (v, fabsl (sqrtl (re)), copysignl (0, im)); } } else if (re == 0) { long double r; r = sqrtl (0.5 * fabsl (im)); COMPLEX_ASSIGN (v, copysignl (r, im), r); } else { long double d, r, s; d = hypotl (re, im); /* Use the identity 2 Re res Im res = Im x to avoid cancellation error in d +/- Re x. */ if (re > 0) { r = sqrtl (0.5 * d + 0.5 * re); s = (0.5 * im) / r; } else { s = sqrtl (0.5 * d - 0.5 * re); r = fabsl ((0.5 * im) / s); } COMPLEX_ASSIGN (v, r, copysignl (s, im)); } return v; }
float complex csqrtf (float complex z) { float re, im; float complex v; re = REALPART (z); im = IMAGPART (z); if (im == 0) { if (re < 0) { COMPLEX_ASSIGN (v, 0, copysignf (sqrtf (-re), im)); } else { COMPLEX_ASSIGN (v, fabsf (sqrtf (re)), copysignf (0, im)); } } else if (re == 0) { float r; r = sqrtf (0.5 * fabsf (im)); COMPLEX_ASSIGN (v, r, copysignf (r, im)); } else { float d, r, s; d = hypotf (re, im); /* Use the identity 2 Re res Im res = Im x to avoid cancellation error in d +/- Re x. */ if (re > 0) { r = sqrtf (0.5 * d + 0.5 * re); s = (0.5 * im) / r; } else { s = sqrtf (0.5 * d - 0.5 * re); r = fabsf ((0.5 * im) / s); } COMPLEX_ASSIGN (v, r, copysignf (s, im)); } return v; }
/* tanh(z) = (tanh(a) + itan(b)) / (1 - itanh(a)tan(b)) */ GFC_COMPLEX_4 ctanhf (GFC_COMPLEX_4 a) { GFC_REAL_4 rt; GFC_REAL_4 it; GFC_COMPLEX_4 n; GFC_COMPLEX_4 d; rt = tanhf (REALPART (a)); it = tanf (IMAGPART (a)); COMPLEX_ASSIGN (n, rt, it); COMPLEX_ASSIGN (d, 1, - (rt * it)); return n / d; }
__complex128 cexpiq (__float128 x) { __complex128 v; COMPLEX_ASSIGN (v, cosq (x), sinq (x)); return v; }
__complex128 clog10q (__complex128 z) { __complex128 v; COMPLEX_ASSIGN (v, log10q (cabsq (z)), cargq (z)); return v; }
__complex128 ccoshq (__complex128 a) { __float128 r = REALPART (a), i = IMAGPART (a); __complex128 v; COMPLEX_ASSIGN (v, coshq (r) * cosq (i), sinhq (r) * sinq (i)); return v; }
long double complex clog10l (long double complex z) { long double complex v; COMPLEX_ASSIGN (v, log10l (cabsl (z)), cargl (z)); return v; }
double complex clog10 (double complex z) { double complex v; COMPLEX_ASSIGN (v, log10 (cabs (z)), carg (z)); return v; }
float complex clog10f (float complex z) { float complex v; COMPLEX_ASSIGN (v, log10f (cabsf (z)), cargf (z)); return v; }
static inline __complex128 mult_c128 (__complex128 x, __complex128 y) { __float128 r1 = REALPART(x), i1 = IMAGPART(x); __float128 r2 = REALPART(y), i2 = IMAGPART(y); __complex128 res; COMPLEX_ASSIGN(res, r1*r2 - i1*i2, i2*r1 + i1*r2); return res; }
/* log10(z) = log10 (cabs(z)) + i*carg(z) */ GFC_COMPLEX_4 clog10f (GFC_COMPLEX_4 z) { GFC_COMPLEX_4 v; COMPLEX_ASSIGN (v, log10f (cabsf (z)), cargf (z)); return v; }
// Careful: the algorithm for the division sucks. A lot. static inline __complex128 div_c128 (__complex128 x, __complex128 y) { __float128 n = hypotq (REALPART (y), IMAGPART (y)); __float128 r1 = REALPART(x), i1 = IMAGPART(x); __float128 r2 = REALPART(y), i2 = IMAGPART(y); __complex128 res; COMPLEX_ASSIGN(res, r1*r2 + i1*i2, i1*r2 - i2*r1); return res / n; }
void r_matrix_complex_128(__complex128 r[MATRIX_SIZE][MATRIX_SIZE]){ int i; __float128 nn = MATRIX_SIZE; for(i=0; i<MATRIX_SIZE; i++){ __float128 rval = random_float_128(M_PIq); if(rval < 0.0Q) rval = -rval; COMPLEX_ASSIGN(r[i][i], cosq(-2.0Q*M_PIq*rval/nn), sinq(-2.0Q*M_PIq*rval/nn)); } }
double complex cexp (double complex z) { double a, b; double complex v; a = REALPART (z); b = IMAGPART (z); COMPLEX_ASSIGN (v, cos (b), sin (b)); return exp (a) * v; }
void dft_matrix_complex_128(__complex128 f[MATRIX_SIZE][MATRIX_SIZE]){ int i, j; __float128 nn = MATRIX_SIZE; for(i=0; i<MATRIX_SIZE; i++){ for(j=0; j<MATRIX_SIZE; j++){ __float128 ii = i; __float128 jj = j; COMPLEX_ASSIGN(f[i][j], cosq(-2.0Q*M_PIq*ii*jj/nn), sinq(-2.0Q*M_PIq*ii*jj/nn)); } } }
float complex cexpf (float complex z) { float a, b; float complex v; a = REALPART (z); b = IMAGPART (z); COMPLEX_ASSIGN (v, cosf (b), sinf (b)); return expf (a) * v; }
float complex ccoshf (float complex a) { float r, i; float complex v; r = REALPART (a); i = IMAGPART (a); COMPLEX_ASSIGN (v, coshf (r) * cosf (i), - (sinhf (r) * sinf (i))); return v; }
double complex ccosh (double complex a) { double r, i; double complex v; r = REALPART (a); i = IMAGPART (a); COMPLEX_ASSIGN (v, cosh (r) * cos (i), - (sinh (r) * sin (i))); return v; }
long double complex ccoshl (long double complex a) { long double r, i; long double complex v; r = REALPART (a); i = IMAGPART (a); COMPLEX_ASSIGN (v, coshl (r) * cosl (i), - (sinhl (r) * sinl (i))); return v; }
__complex128 cexpq (__complex128 z) { __float128 a, b; __complex128 v; a = REALPART (z); b = IMAGPART (z); COMPLEX_ASSIGN (v, cosq (b), sinq (b)); return expq (a) * v; }
long double complex cexpl (long double complex z) { long double a, b; long double complex v; a = REALPART (z); b = IMAGPART (z); COMPLEX_ASSIGN (v, cosl (b), sinl (b)); return expl (a) * v; }
/* cosh(z) = cosh(a)cos(b) - isinh(a)sin(b) */ GFC_COMPLEX_4 ccoshf (GFC_COMPLEX_4 a) { GFC_REAL_4 r; GFC_REAL_4 i; GFC_COMPLEX_4 v; r = REALPART (a); i = IMAGPART (a); COMPLEX_ASSIGN (v, coshf (r) * cosf (i), - (sinhf (r) * sinf (i))); return v; }
/* exp(z) = exp(a)*(cos(b) + isin(b)) */ GFC_COMPLEX_4 cexpf (GFC_COMPLEX_4 z) { GFC_REAL_4 a; GFC_REAL_4 b; GFC_COMPLEX_4 v; a = REALPART (z); b = IMAGPART (z); COMPLEX_ASSIGN (v, cosf (b), sinf (b)); return expf (a) * v; }
/* Square root algorithm from glibc. */ __complex128 csqrtq (__complex128 z) { __float128 re = REALPART(z), im = IMAGPART(z); __complex128 v; if (im == 0) { if (re < 0) { COMPLEX_ASSIGN (v, 0, copysignq (sqrtq (-re), im)); } else { COMPLEX_ASSIGN (v, fabsq (sqrtq (re)), copysignq (0, im)); } } else if (re == 0) { __float128 r = sqrtq (0.5 * fabsq (im)); COMPLEX_ASSIGN (v, r, copysignq (r, im)); } else { __float128 d = hypotq (re, im); __float128 r, s; /* Use the identity 2 Re res Im res = Im x to avoid cancellation error in d +/- Re x. */ if (re > 0) r = sqrtq (0.5 * d + 0.5 * re), s = (0.5 * im) / r; else s = sqrtq (0.5 * d - 0.5 * re), r = fabsq ((0.5 * im) / s); COMPLEX_ASSIGN (v, r, copysignq (s, im)); } return v; }