complex_float complex_cos(complex_float c1){ complex_float exp1 = complex_pow( complex_make(exp(1)), complex_i(c1) ); complex_float exp2 = complex_pow( complex_make(exp(1)), complex_mul(complex_make(-1.0f),complex_i(c1)) ); complex_float sum = complex_add(exp1,exp2); complex_float r = complex_div( sum, complex_make(2.0f) ); return r; }
complex_float complex_sin(complex_float c1){ // So... Euler said: exp(i*t) = cos(t) + i*sin(t) // and then: sin(t) = (exp(i*t) - exp(-i*t)) / 2i // and also: cos(t) = (exp(i*t) + exp(-i*t)) / 2 // Hm... I already have functions that raise complex numbers // to complex numbers so I'll use those for sin/code. complex_float exp1 = complex_pow( complex_make(exp(1)), complex_i(c1) ); complex_float exp2 = complex_pow( complex_make(exp(1)), complex_mul(complex_make(-1.0f),complex_i(c1)) ); complex_float diff = complex_sub(exp1,exp2); complex_float r = complex_div( diff, complex_i(complex_make(2.0f)) ); return r; }
Big<amplitude_t> DMetalWavefunction::Amplitude::psi_ (void) const { if (m_partial_update_step != 0) return Big<amplitude_t>(); const DMetalWavefunction *wf_ = boost::polymorphic_downcast<const DMetalWavefunction *>(wf.get()); return (complex_pow(m_cmat_d1.get_determinant(), wf_->d1_exponent) * complex_pow(m_cmat_d2.get_determinant(), wf_->d2_exponent) * complex_pow(m_cmat_f_up.get_determinant(), wf_->f_up_exponent) * complex_pow(m_cmat_f_dn.get_determinant(), wf_->f_dn_exponent)); }
complex_float complex_arccos(complex_float c1){ // arccos(z) = (pi/2) + i * log(i*z + sqrt(1 - z*z)) complex_float zz = complex_mul(c1,c1); complex_float a = complex_make(1.0f); a = complex_sub(a,zz); // 1 - z*z a = complex_pow(a,complex_make(0.5f)); // sqrt(...) complex_float iz = complex_i(c1); // i*z a = complex_add(iz,a); // i*z + sqrt(...) a = complex_ln(a); // log(...) a = complex_mul(complex_i(complex_make( 1.0f )),a); // i * log(...) complex_float r = complex_add( complex_make(1.57079632f), a); // pi/2 + ... return r; }
void complex_gamma (complex_t *dst, complex_t const *src) { if (complex_real_p (src)) { complex_init (dst, gnm_gamma (src->re), 0); } else if (src->re < 0) { /* Gamma(z) = pi / (sin(pi*z) * Gamma(-z+1)) */ complex_t a, b, mz; complex_init (&mz, -src->re, -src->im); complex_fact (&a, &mz); complex_init (&b, M_PIgnum * gnm_fmod (src->re, 2), M_PIgnum * src->im); /* Hmm... sin overflows when b.im is large. */ complex_sin (&b, &b); complex_mul (&a, &a, &b); complex_init (&b, M_PIgnum, 0); complex_div (dst, &b, &a); } else { complex_t zmh, zmhd2, zmhpg, f, f2, p, q, pq; int i; i = G_N_ELEMENTS(lanczos_num) - 1; complex_init (&p, lanczos_num[i], 0); complex_init (&q, lanczos_denom[i], 0); while (--i >= 0) { complex_mul (&p, &p, src); p.re += lanczos_num[i]; complex_mul (&q, &q, src); q.re += lanczos_denom[i]; } complex_div (&pq, &p, &q); complex_init (&zmh, src->re - 0.5, src->im); complex_init (&zmhpg, zmh.re + lanczos_g, zmh.im); complex_init (&zmhd2, zmh.re * 0.5, zmh.im * 0.5); complex_pow (&f, &zmhpg, &zmhd2); zmh.re = -zmh.re; zmh.im = -zmh.im; complex_exp (&f2, &zmh); complex_mul (&f2, &f, &f2); complex_mul (&f2, &f2, &f); complex_mul (dst, &f2, &pq); } }
complex_float complex_arcsin(complex_float c1){ // Hopefully I got this right, from a paper called: // "Implementing the Complex Arcsine and Arccosine Functions Using Exception Handling" // arcsin(z) = -i* log(i*z + sqrt(1 - z*z)) complex_float zz = complex_mul(c1,c1); complex_float a = complex_make(1.0f); a = complex_sub(a,zz); // 1 - z*z a = complex_pow(a,complex_make(0.5f)); // sqrt(...) complex_float iz = complex_i(c1); // i*z a = complex_add(iz,a); // i*z + sqrt(...) a = complex_ln(a); // log(...) complex_float r = complex_mul(complex_i(complex_make( -1.0f )),a); // -i * log(...) return r; }
/* do the iterations * if binary is true, check halfplane of last iteration. * if demrange is non zero, estimate lower bound of dist(c, M) * * DEM - Distance Estimator Method * Based on Peitgen & Saupe's "The Science of Fractal Images" * * ALPHA - level sets of closest return. * INDEX - index of ALPHA. * Based on Peitgen & Richter's "The Beauty of Fractals" (Fig 33,34) * * LYAPUNOV - lyapunov exponent estimate * Based on an idea by Jan Thor * */ static int reps(complex c, double p, int r, Bool binary, interior_t interior, double demrange, Bool zpow, Bool zsin) { int rep; int escaped = 0; complex t; int escape = (int) ((demrange == 0) ? ESCAPE : ESCAPE*ESCAPE*ESCAPE*ESCAPE); /* 2 more iterations */ complex t1; complex dt; double L = 0.0; double l2; double dl2 = 1.0; double alpha2 = ESCAPE; int index = 0; #if defined(USE_LOG) double log_top = log((double) r); #endif t = c; dt.real = 1; dt.imag = 0; for (rep = 0; rep < r; rep++) { t1 = t; ipow(&t, (int) p); add(&t, c); if (zpow) add(&t, complex_pow(t1, t1)); if (zsin) add(&t, complex_sin(t1)); l2 = t.real * t.real + t.imag * t.imag; if (l2 <= alpha2) { alpha2 = l2; index = rep; } if (l2 >= escape) { escaped = 1; break; } else if (interior == LYAPUNOV) { /* Crude estimate of Lyapunov exponent. The stronger the attractor, the more negative the exponent will be. */ /* n=N L = lim 1/N * Sum log(abs(dx(n+1)/dx(n)))/ln(2) N->inf n=1 */ L += log(sqrt(l2)); } if (demrange){ /* compute dt/dc * p-1 * dt = p * t * dt + 1 * k+1 k k */ /* Note this is incorrect for zpow or zsin, but a correct implementation is too slow to be useful. */ dt.real *= p; dt.imag *= p; if(p > 2) ipow(&t1, (int) (p - 1)); mult(&dt, t1); dt.real += 1; dl2 = dt.real * dt.real + dt.imag * dt.imag; if (dl2 >= 1e300) { escaped = 2; break; } } } if (escaped) { if(demrange) { double mt = sqrt(t1.real * t1.real + t1.imag * t1.imag); /* distance estimate */ double dist = 0.5 * mt * log(mt) / sqrt(dl2); /* scale for viewing. Allow black when showing interior. */ rep = (int) (((interior > NONE)?0:1) + 10*r*dist/demrange); if(rep > r-1) rep = r-1; /* chop into color range */ } if(binary && t.imag > 0) rep = (r + rep / 2) % r; /* binary decomp */ #ifdef USE_LOG if ( rep > 0 ) rep = (int) (r * log((double) rep)/log_top); /* Log Scale */ #endif return rep; } else if (interior == LYAPUNOV) { return -(int)(L/M_LN2) % r; } else if (interior == INDEX) { return 1 + index; } else if (interior == ALPHA) { return (int) (r * sqrt(alpha2)); } else return r; }
// expect wavelength in m int SetReflectivity(struct ElementType *ep, double wavelength) { double f1, f2, a, rho, energy, nt, delta, beta, ac, sinag, cosag, Rs, Rp; int z, myreturn; COMPLEX cn, cn2, cwu, crs, cts, crp, ctp, c1, c2, c3, csinag; char *material; struct ReflecType *rp; material= ep->MDat.material; rp= (struct ReflecType *)&ep->reflec; #ifdef DEBUG printf("debug: SetReflectivity called, material= >%s<, file= %s\n", material, __FILE__); #endif if (!(wavelength > 0.0)) { fprintf(stderr, "error SetReflectivity: wavelength not defined (%f)- return"); return 0; } energy= 1240e-9/ wavelength; myreturn= ReadMaterial(material, &z, &a, &rho); myreturn &= ReadHenke(material, energy, &f1, &f2); nt= 1e6* rho * NA / a; // Teilchendichte (1/m^3), rho is in (g/cm^3) delta= RE * pow(wavelength, 2) * nt * f1 / (2.0 * PI); beta = RE * pow(wavelength, 2) * nt * f2 / (2.0 * PI); ac = acos(1.0 - delta); // critical (grazing) angle in rad complex_in(&cn, (1.0- delta), beta); // complex index of refraction sinag= ep->geo.cosa; // sin(grazing angle) grazing angle in rad cosag= ep->geo.sina; // sin <-> cos change for grazing angle // we calculate the compex reflectivity and transmission coefficients // transmission coefficients not used so far complex_x (&cn, &cn, &cn2); // n^2 complex_in (&c1, pow(cosag, 2.0), 0.0); // cos(theta))^2 saved in c1 complex_minus(&cn2, &c1, &c2); // c2= n2- c1 complex_pow (&c2, 0.5, &cwu); // wu= sqrt(c2) complex_in (&csinag, sinag, 0.0); // sin(theta) saved in csinag complex_minus(&csinag, &cwu, &c1); // zehler in c1 complex_plus (&csinag, &cwu, &c2); // nenner in c2 complex_div (&c1, &c2, &crs); // calc crs complex_in (&c1, (2* sinag), 0.0); // zehler in c1 complex_div(&c1, &c2, &cts); // calc cts complex_x (&cn2, &csinag, &c3); // c3 complex_minus(&c3, &cwu, &c1); // zehler in c1 complex_plus (&c3, &cwu, &c2); // nenner in c2 complex_div (&c1, &c2, &crp); // calc crp complex_in (&c1, 2.0, 0.0); // 2.0 in c1 complex_x (&c1, &cn, &c3); // 2n in c3 complex_x (&c3, &csinag, &c1); // zaehler in c1 complex_div(&c1, &c2, &ctp); // calc ctp Rs= pow(crs.re, 2)+ pow(crs.im, 2); // abs()^2 Rp= pow(crp.re, 2)+ pow(crp.im, 2); // abs()^2; rp->runpol= 0.5 * (Rs + Rp); // fill double ryamp, rypha, rzamp, rzpha, runpol; switch (ep->GDat.azimut) /* vertikal 0; nach links 1; nach unten 2 ; nach rechts 3 */ { case 0: case 2: rp->ryamp= sqrt(pow(crp.re, 2)+ pow(crp.im, 2)); rp->rypha= atan2(crp.im, crp.re); rp->rzamp= sqrt(pow(crs.re, 2)+ pow(crs.im, 2)); rp->rzpha= atan2(crs.im, crs.re); break; case 1: case 3: rp->rzamp= sqrt(pow(crp.re, 2)+ pow(crp.im, 2)); rp->rzpha= atan2(crp.im, crp.re); rp->ryamp= sqrt(pow(crs.re, 2)+ pow(crs.im, 2)); rp->rypha= atan2(crs.im, crs.re); break; default: fprintf(stderr, "error in file %s- azimut >>%d<<out of range\n", __FILE__, ep->GDat.azimut); exit(-1); } return myreturn; } // SetReflectivity