// The evaluation of the derivative happens here in // the same way as the funtion bove. _complex df(_complex z, int grad, double poly[]){ int i; _complex df; df=complex_init(grad*poly[grad],0); for(i=grad-1;i>0;i--){ df=complex_sum(complex_mult(df,z),complex_init(i*poly[i],0)); } return df; }
// Here the polynomial function is evaluated at a point Z // in the complex plane. _complex f(_complex z, int grad, double poly[]){ int i; _complex f; f=complex_init(poly[grad],0); for(i=grad-1;i>=0;i--){ f=complex_sum(complex_mult(f,z),complex_init(poly[i],0)); } return f; }
static void gsl_complex_arctanh_real (gnm_float a, complex_t *res) { /* z = arctanh(a) */ if (a > -1.0 && a < 1.0) { complex_init (res, gnm_atanh (a), 0); } else { complex_init (res, gnm_atanh (1 / a), (a < 0) ? M_PI_2gnum : -M_PI_2gnum); } }
static void gsl_complex_arcsin_real (gnm_float a, complex_t *res) { /* z = arcsin(a) */ if (gnm_abs (a) <= 1.0) { complex_init (res, gnm_asin (a), 0.0); } else { if (a < 0.0) { complex_init (res, -M_PI_2gnum, gnm_acosh (-a)); } else { complex_init (res, M_PI_2gnum, -gnm_acosh (a)); } } }
void gsl_complex_cosh (complex_t const *a, complex_t *res) { /* z = cosh(a) */ gnm_float R = GSL_REAL (a), I = GSL_IMAG (a); complex_init (res, cosh (R) * gnm_cos (I), gnm_sinh (R) * gnm_sin (I)); }
polynomial_t *polynomial_extractImaginary(polynomial_t *p) { polynomial_t *q = NULL; monomial_t *iterator = NULL; char *name = NULL; if (p == NULL) return NULL; q = polynomial_init(NULL); if (q == NULL) return NULL; name = (char*) malloc((sizeof(p->name) + 3) * sizeof(char)); if (name != NULL) { strcpy(name, "Im_"); strcat(name, p->name); q->name = name; } for (iterator = p->first; iterator != NULL; iterator = iterator->next) polynomial_append(q, complex_init(0.0, iterator->coef->im), iterator->degree); return q; }
int main() { int i; Complex cx; History hist; complex_init(&cx); history_init(&hist); srand(time(0)); read_asc(&cx, stdin); complex_compute_free_faces(&cx); printf("checking "); printf("%s", cx.serialized); printf("\n"); complex_print(&cx); fflush(stdout); for (i = 0; i < 100000; ++i) { if (!(i % 1000)) printf("%d\n", i); if (complex_collapse_random(&cx, &hist)) { printf("collapsed! yay!\n"); history_print(&hist); return 0; } } history_destroy(&hist); return 0; }
int32_t main ( int32_t argc, char * argv[] ) { complex_t x,y,z; complex_init(x,1.0,0.0); complex_init(y,0.0,1.0); complex_mul(z,y,y); complex_exp(z,y,10); dbg_print("exp of"); dbg_complex_print(y); dbg_print("is"); dbg_complex_print(z); return 0; }
void gsl_complex_inverse (complex_t const *a, complex_t *res) { /* z=1/a */ gnm_float s = 1.0 / complex_mod (a); complex_init (res, (GSL_REAL (a) * s) * s, -(GSL_IMAG (a) * s) * s); }
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); } }
// This function initialize the data structure for the roots void root_init(_roots *roots){ int i; for(i=0;i<MAX_ROOTS;i++){ roots->root[i]=complex_init(0,0); } roots->nor=0; roots->grad=0; }
void gsl_complex_arctan (complex_t const *a, complex_t *res) { /* z = arctan(a) */ gnm_float R = GSL_REAL (a), I = GSL_IMAG (a); if (I == 0) { complex_init (res, gnm_atan (R), 0); } else { /* FIXME: This is a naive implementation which does not fully * take into account cancellation errors, overflow, underflow * etc. It would benefit from the Hull et al treatment. */ gnm_float r = gnm_hypot (R, I); gnm_float imag; gnm_float u = 2 * I / (1 + r * r); /* FIXME: the following cross-over should be optimized but 0.1 * seems to work ok */ if (gnm_abs (u) < 0.1) { imag = 0.25 * (gnm_log1p (u) - gnm_log1p (-u)); } else { gnm_float A = gnm_hypot (R, I + 1); gnm_float B = gnm_hypot (R, I - 1); imag = 0.5 * gnm_log (A / B); } if (R == 0) { if (I > 1) { complex_init (res, M_PI_2gnum, imag); } else if (I < -1) { complex_init (res, -M_PI_2gnum, imag); } else { complex_init (res, 0, imag); } } else { complex_init (res, 0.5 * gnm_atan2 (2 * R, ((1 + r) * (1 - r))), imag); } } }
void gsl_complex_arccot (complex_t const *a, complex_t *res) { /* z = arccot(a) */ if (GSL_REAL (a) == 0.0 && GSL_IMAG (a) == 0.0) { complex_init (res, M_PI_2gnum, 0); } else { gsl_complex_inverse (a, res); gsl_complex_arctan (res, res); } }
void gsl_complex_arccos (complex_t const *a, complex_t *res) { /* z = arccos(a) */ gnm_float R = GSL_REAL (a), I = GSL_IMAG (a); if (I == 0) { gsl_complex_arccos_real (R, res); } else { gnm_float x = gnm_abs (R); gnm_float y = gnm_abs (I); gnm_float r = gnm_hypot (x + 1, y); gnm_float s = gnm_hypot (x - 1, y); gnm_float A = 0.5 * (r + s); gnm_float B = x / A; gnm_float y2 = y * y; gnm_float real, imag; const gnm_float A_crossover = 1.5; const gnm_float B_crossover = 0.6417; if (B <= B_crossover) { real = gnm_acos (B); } else { if (x <= 1) { gnm_float D = 0.5 * (A + x) * (y2 / (r + x + 1) + (s + (1 - x))); real = gnm_atan (gnm_sqrt (D) / x); } else { gnm_float Apx = A + x; gnm_float D = 0.5 * (Apx / (r + x + 1) + Apx / (s + (x - 1))); real = gnm_atan ((y * gnm_sqrt (D)) / x); } } if (A <= A_crossover) { gnm_float Am1; if (x < 1) { Am1 = 0.5 * (y2 / (r + (x + 1)) + y2 / (s + (1 - x))); } else { Am1 = 0.5 * (y2 / (r + (x + 1)) + (s + (x - 1))); } imag = gnm_log1p (Am1 + gnm_sqrt (Am1 * (A + 1))); } else { imag = gnm_log (A + gnm_sqrt (A * A - 1)); } complex_init (res, (R >= 0) ? real : M_PIgnum - real, (I >= 0) ? -imag : imag); } }
void gsl_complex_tanh (complex_t const *a, complex_t *res) { /* z = tanh(a) */ gnm_float R = GSL_REAL (a), I = GSL_IMAG (a); if (gnm_abs (R) < 1.0) { gnm_float D = gnm_pow (gnm_cos (I), 2.0) + gnm_pow (gnm_sinh (R), 2.0); complex_init (res, gnm_sinh (R) * cosh (R) / D, 0.5 * gnm_sin (2 * I) / D); } else { gnm_float D = gnm_pow (gnm_cos (I), 2.0) + gnm_pow (gnm_sinh (R), 2.0); gnm_float F = 1 + gnm_pow (gnm_cos (I) / gnm_sinh (R), 2.0); complex_init (res, 1.0 / (gnm_tanh (R) * F), 0.5 * gnm_sin (2 * I) / D); } }
void complex_fact (complex_t *dst, complex_t const *src) { if (complex_real_p (src)) { complex_init (dst, gnm_fact (src->re), 0); } else { /* * This formula is valid for all arguments except zero * which we conveniently handled above. */ complex_t gz; complex_gamma (&gz, src); complex_mul (dst, &gz, src); } }
polynomial_t *polynomial_extract(polynomial_t *p, unsigned long degree, unsigned long end) { polynomial_t *q = NULL; complex_t *z = NULL; monomial_t *iterator = NULL; unsigned long i = 0; if (p == NULL) return NULL; q = polynomial_init(NULL); if (q == NULL) return NULL; for (i = p->degree, iterator = p->first; i >= end && iterator != NULL; i--, iterator = iterator->next) { if (degree >= iterator->degree && iterator->degree >= end) { z = complex_init(iterator->coef->re, iterator->coef->im); if (z == NULL) { polynomial_free(q); return NULL; } polynomial_append(q, z, iterator->degree); } } if (q->size == 0) { polynomial_free(q); q = NULL; } return q; }
static void igamma_cf (complex_t *dst, const complex_t *a, const complex_t *z) { complex_t A0, A1, B0, B1; int i; const gboolean debug_cf = FALSE; complex_init (&A0, 1, 0); complex_init (&A1, 0, 0); complex_init (&B0, 0, 0); complex_init (&B1, 1, 0); for (i = 1; i < 100; i++) { complex_t ai, bi, t1, t2, c1, c2, A2, B2; gnm_float m; const gnm_float BIG = GNM_const(18446744073709551616.0); if (i == 1) complex_init (&ai, 1, 0); else if (i & 1) { gnm_float f = (i >> 1); complex_init (&ai, z->re * f, z->im * f); } else {
complex_t *polynomial_eval(polynomial_t *p, complex_t *coef, monomial_t *m, complex_t *eval) { complex_t *result = NULL, *tmp = NULL; unsigned long diff = 0; if (p == NULL || coef == NULL || eval == NULL) return NULL; if (p->first->degree == 0) return complex_init(coef->re, coef->im); else { diff = (m == NULL) ? p->last->degree : m->previous->degree - m->degree; while (diff > 0) { if (result == NULL) { result = complex_prod(coef, eval); if (result == NULL) return NULL; } else { tmp = complex_prod(result, eval); if (tmp == NULL) { complex_free(result); return NULL; } complex_free(result); result = tmp; } diff--; } if (m != NULL) { tmp = complex_sum(result, m->coef); if (tmp == NULL) { complex_free(result); return NULL; } complex_free(result); result = tmp; if (m->next != NULL || m->degree > 0) { result = polynomial_eval(p, tmp, m->next, eval); complex_free(tmp); } } return result; } }
static inline void gsl_complex_mul_imag (complex_t const *a, gnm_float y, complex_t *res) { /* z=a*iy */ complex_init (res, -y * GSL_IMAG (a), y * GSL_REAL (a)); }
int main(){ int ix,iy,radius,i,tries,nit; double zx,zy,zxn,zyn,cx,cy,theta, x,y,eps, poly[MAX_ROOTS+1]; _roots roots; _complex z,w,fz,dfz; root_init(&roots); // Number of iteration for each pointer. // The bigger, the less prone to error the program will be. nit=100; // The radius where the points will be looked for. radius=6; // Precision for the roots eps=1E-10; scanf("%d",&roots.grad); for(i=roots.grad;i>=0;i--){ scanf("%lf",&poly[i]); } printf("Coefficients:\n"); for(i=roots.grad;i>=0;i--){ printf(" a%d=%+.2f\n",i,poly[i]); } printf("\n f(0+0i)="); complex_print(f(complex_init(0,0),roots.grad, poly)); printf("df(0+0i)="); complex_print(df(complex_init(0,0),roots.grad, poly)); tries=0; do{ tries++; theta=drand48()*2*M_PI; x=radius*cos(theta); y=radius*sin(theta); z=complex_init(x,y); for(i=0;i<=nit;i++){ fz = f(z,roots.grad,poly); dfz=df(z,roots.grad,poly); if(complex_abs(dfz)<ee){ break; } w=z; z=complex_sub(z,complex_div(fz,dfz)); if(complex_abs(complex_sub(z,w))<=eps){ process_root(z,&roots,eps); break; } } }while(roots.nor<roots.grad); printf("\nTook %d tries to get all %d roots\n",tries,roots.grad); printf("\nZeroes and their images:\n\n"); for(i=0;i<roots.grad;i++){ printf("Root Z%d=%+lf %+lfi \tf(z%d)=",i+1,roots.root[i].x,roots.root[i].y,i+1); complex_print(f(roots.root[i],roots.grad, poly)); } return EXIT_SUCCESS; }
void gsl_complex_negative (complex_t const *a, complex_t *res) { /* z=1/a */ complex_init (res, -GSL_REAL (a), -GSL_IMAG (a)); }