static cut_result_t op_test(void) { complex_t a = { -1, 3 }; complex_t b = { 4, 0 }; CUT_ASSERT_COMPLEX(3, 3, complex_add(a, b)); CUT_ASSERT_COMPLEX(3, 3, complex_add(b, a)); CUT_ASSERT_COMPLEX(-5, 3, complex_sub(a, b)); CUT_ASSERT_COMPLEX(5, -3, complex_sub(b, a)); CUT_ASSERT_COMPLEX(-4, 12, complex_mul(a, b)); CUT_ASSERT_COMPLEX(-4, 12, complex_mul(b, a)); CUT_ASSERT_COMPLEX(-0.25, 0.75, complex_div(a, b)); CUT_ASSERT_COMPLEX(-0.4, -1.2, complex_div(b, a)); CUT_TEST_PASS(); }
static void ifftx(complex_t data[], complex_t temp[], int n) { int i; int h; int p; int t; int i2; complex_t wkt; if (n > 1) { h = n/2; for (i = 0; i < h; i++) { i2 = i*2; temp[i] = data[i2]; /* Even */ temp[h + i] = data[i2 + 1]; /* Odd */ } fftx(&temp[0], &data[0], h); fftx(&temp[h], &data[h], h); p = 0; t = MAX_FFT_LEN/n; for (i = 0; i < h; i++) { wkt = complex_mul(île[p], &temp[h + i]); data[i] = complex_add(&temp[i], &wkt); data[h + i] = complex_sub(&temp[i], &wkt); p += t; } } }
static inline void butterfly(osk_complex_t* r, const osk_complex_t* tf, int idx_a, int idx_b) { osk_complex_t up = r[idx_a]; osk_complex_t dn = r[idx_b]; //r[idx_a] = up + tf * dn; //r[idx_b] = up - tf * dn; osk_complex_t dntf = complex_mult(&dn, tf); r[idx_a] = complex_add(&up, &dntf); r[idx_b] = complex_sub(&up, &dntf); }
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; }
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; }
// When a root is found this function is called. // It looks in a vector to find if the given root // was already found, if yes it returns the position // in the vector of the root, if not it simple adds // the root in the first avaliable position. int process_root(_complex z, _roots *p, double eps){ int i; for(i=0;i<p->nor;i++){ if(complex_abs(complex_sub(z,p->root[i]))<2*eps){ return i+1; } } p->root[p->nor]=z; p->nor+=1; return p->nor; }
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; }
void test_complex() { complexFloat c = complex_new(1,2); CU_ASSERT(c.real==1); CU_ASSERT(c.imag==2); complexFloat d = complex_add(c,complex_zero()); CU_ASSERT(d.real==1); CU_ASSERT(d.imag==2); d = complex_sub(c,complex_new(-1,-2)); CU_ASSERT(d.real==2); CU_ASSERT(d.imag==4); CU_ASSERT(within_tol(complex_amp(c),sqrt(5))); CU_ASSERT(within_tol(complex_amp(d),sqrt(20))); CU_ASSERT(within_tol(complex_amp_sqr(c),5)); CU_ASSERT(within_tol(complex_amp_sqr(d),20)); CU_ASSERT(within_tol(complex_amp(complex_scale(d,.5)),sqrt(5))); d = complex_conj(c); CU_ASSERT(d.real==1); CU_ASSERT(d.imag==-2); complexFloat e = complex_conj(complex_add(d,complex_conj(c))); CU_ASSERT(e.real==2); CU_ASSERT(e.imag==4); complexVector v = complex_vector_new(c,d,e); CU_ASSERT(v.A.real==1); CU_ASSERT(v.A.imag==2); CU_ASSERT(v.B.real==1); CU_ASSERT(v.B.imag==-2); CU_ASSERT(v.C.real==2); CU_ASSERT(v.C.imag==4); complexVector vc = complex_vector_conj(v); CU_ASSERT(vc.A.real==1); CU_ASSERT(vc.A.imag==-2); CU_ASSERT(vc.B.real==1); CU_ASSERT(vc.B.imag==2); CU_ASSERT(vc.C.real==2); CU_ASSERT(vc.C.imag==-4); }
void dwf_deriv( char *name) { /* * This marks the argument registers as defined by ABI as off limits * to us until they are freed by "getarg()"; */ int dum = defargcount(1); int retno; /* * S=phi^dag (MdagM)^-1 phi * * dS = phi^dag (MdagM)^-1 [ dMdag M + Mdag dM ] (MdagM)^-1 phi * * Let X = (MdagM)^-1 phi * Y = M X = M^-dag phi * * Want terms: Ydag dM X * Xdag dMdag Y * * Take Xdag 1-gamma Y * * Still a bit confused about the 1+g 1-g terms; but this may be simply a factor of two as we add +h.c. * Will continue to follow Chroma's routine */ reg_array_2d(Y,Cregs,4,3); // 4 spinor - 24 regs reg_array_2d(X,Cregs,4,3); // 4 spinor - 12 regs reg_array_1d(F,Cregs,3); // Force alreg(Z,Cregs); // Zero alreg(creg,Cregs); // Zero offset_3d(CHIIMM,FourSpinType,2,3,2*nsimd()); offset_3d(PSIIMM,FourSpinType,4,3,2*nsimd()); offset_3d(GIMM ,GaugeType, 3, 3 ,2*nsimd() ); def_off( GAUGE_SITE_IMM, FourSpinType,4*18*nsimd()); def_off( MAT_IMM , GaugeType,18*nsimd()); def_off( PSI_IMM , FourSpinType,24*nsimd()); def_off( CHI_IMM , FourSpinType,12*nsimd()); def_off( CONST_ZERO_OFFSET,Double,2*2*nsimd()); /* * Integer registers */ alreg(F_p,Iregs); /*Pointer to the current cpt of force field */ alreg(F_p_s,Iregs); alreg(Y_mu,Iregs); alreg(Y_p,Iregs); alreg(X_p,Iregs); alreg(length,Iregs); /*number of sites*/ alreg(tab,Iregs); /*Pointer to current entry in offset table*/ alreg(Complex_i,Iregs);/*Point to (0,1)x Nsimd*/ alreg(Ls,Iregs); alreg(s,Iregs); alreg(recbuf_base,Iregs); alreg(args,Iregs); alreg(s_offset,Iregs); /*Useful integer immediate constants, in units of Fsize*/ def_off( ZERO_IMM,Byte,0); def_off( minusone,Byte,-1); def_off( one,Byte,1); // Mask bits for predicating directions def_off( mask_0,Byte,1); def_off( mask_1,Byte,2); def_off( mask_2,Byte,4); def_off( mask_3,Byte,8); def_off( mask_4,Byte,16); def_off( mask_5,Byte,32); def_off( mask_6,Byte,64); def_off( mask_7,Byte,128); int mask_imm[8] = { mask_0, mask_1, mask_2, mask_3, mask_4, mask_5, mask_6, mask_7 }; alreg(mask ,Iregs); offset_1d(TAB_IMM,TableType,17); // Integer sizes int Isize = def_offset(PROC->I_size,Byte,"Isize"); int ISsize = def_offset(PROC->IS_size,Byte,"ISsize"); int i,j,co,sp; /*********************************************************************/ make_inst(DIRECTIVE,Enter_Routine,name); grab_stack(0); save_regs(); /********************************************* * our arguments ********************************************* */ getarg(args); /*Pointer to arg list*/ queue_iload(X_p, ZERO_IMM,args); queue_load_addr(args,Isize,args); //0 queue_iload(Y_p, ZERO_IMM,args); queue_load_addr(args,Isize,args); //1 queue_iload(F_p, ZERO_IMM,args); queue_load_addr(args,Isize,args); //2 queue_iload(length,ZERO_IMM,args); queue_load_addr(args,Isize,args); //3 queue_iload(Ls, ZERO_IMM,args); queue_load_addr(args,Isize,args); //4 queue_iload(tab, ZERO_IMM,args); queue_load_addr(args,Isize,args); //5 queue_iload(Complex_i,ZERO_IMM,args);queue_load_addr(args,Isize,args); //6 queue_load_addr(args,Isize,args); //7 queue_iload(recbuf_base,ZERO_IMM,args);queue_load_addr(args,Isize,args); //8 /************************************************** * Load common constants into Iregs ************************************************** */ for (int i =0; i<12; i++ ) { need_constant(i*2*SizeofDatum(FourSpinType)*nsimd()); } for (int i =0; i<9; i++ ) { need_constant(i*2*SizeofDatum(GaugeType)*nsimd()); } complex_constants_prepare(creg,Complex_i); complex_load(Z,CONST_ZERO_OFFSET,Complex_i,Double); // Site loop retno = get_target_label(); check_iterations(length,retno); int branchsite = start_loop(length); // S loop queue_iload_short(mask,TAB_IMM[10],tab); queue_iadd_imm (s,Ls,ZERO_IMM); queue_iload_imm(s_offset,ZERO_IMM); int branchls = start_loop(s); queue_iadd_imm(F_p_s,F_p,ZERO_IMM); // debugI(s); // Loop over directions for ( int mu=0;mu<4;mu++ ) { int dir = mu*2+1; // Always in forward dir // Complex branch structure for interior/exterior neighbours int lab_proj_mu = get_target_label(); int lab_continue = get_target_label(); queue_iand_imm (Y_mu,mask,mask_imm[dir]); // non-zero if exterior check_iterations(Y_mu,lab_proj_mu); // Exterior points are already projected. Just load. queue_iload_short(Y_mu,TAB_IMM[dir],tab); queue_iadd (Y_mu,Y_mu,recbuf_base); // debugI(Y_mu); //debugI(recbuf_base); queue_iadd (Y_mu,Y_mu,s_offset); for(int sp=0;sp<2;sp++){ for(int co=0;co<3;co++){ complex_load(Y[sp][co],PSIIMM[sp][co][0],Y_mu,FourSpinType); } } jump(lab_continue); make_inst(DIRECTIVE,Target,lab_proj_mu); // Interior points are not already projected. // * Spin project 4 spinor queue_iload_short(Y_mu,TAB_IMM[dir],tab); // debugI(tab); // debugI(Y_mu); queue_iadd (Y_mu,Y_mu,Y_p); queue_iadd (Y_mu,Y_mu,s_offset); // offset for this "s" queue_iadd (Y_mu,Y_mu,s_offset); // offset for this "s" for(int sp=0;sp<4;sp++){ for(int co=0;co<3;co++){ complex_load(X[sp][co],PSIIMM[sp][co][0],Y_mu,FourSpinType); // debugC(X[sp][co]); } } int pm = 1; // pm=0 == 1+gamma, pm=1 => 1-gamma if ( dagger ) pm = 0; if ( mu == 0 ) { if ( pm ==0 ) { for(co=0;co<3;co++) complex_ApiB(Y[0][co],X[0][co],X[3][co]); for(co=0;co<3;co++) complex_ApiB(Y[1][co],X[1][co],X[2][co]); } else { for(co=0;co<3;co++) complex_AmiB(Y[0][co],X[0][co],X[3][co]); for(co=0;co<3;co++) complex_AmiB(Y[1][co],X[1][co],X[2][co]); } } else if ( mu == 1 ) { if ( pm ==0 ) { for(co=0;co<3;co++) complex_sub(Y[0][co],X[0][co],X[3][co]); for(co=0;co<3;co++) complex_add(Y[1][co],X[1][co],X[2][co]); } else { for(co=0;co<3;co++) complex_add(Y[0][co],X[0][co],X[3][co]); for(co=0;co<3;co++) complex_sub(Y[1][co],X[1][co],X[2][co]); } } else if ( mu == 2 ) { if ( pm ==0 ) { for(co=0;co<3;co++) complex_ApiB(Y[0][co],X[0][co],X[2][co]); for(co=0;co<3;co++) complex_AmiB(Y[1][co],X[1][co],X[3][co]); } else { for(co=0;co<3;co++) complex_AmiB(Y[0][co],X[0][co],X[2][co]); for(co=0;co<3;co++) complex_ApiB(Y[1][co],X[1][co],X[3][co]); } } else if ( mu == 3 ) { if ( pm ==0 ) { for(co=0;co<3;co++) complex_add(Y[0][co],X[0][co],X[2][co]); for(co=0;co<3;co++) complex_add(Y[1][co],X[1][co],X[3][co]); } else { for(co=0;co<3;co++) complex_sub(Y[0][co],X[0][co],X[2][co]); for(co=0;co<3;co++) complex_sub(Y[1][co],X[1][co],X[3][co]); } } make_inst(DIRECTIVE,Target,lab_continue); /////////////////////////////////////////////////////////////// // Y contains spin projection of forward neighbour in mu direction // Repromote to Y to 4 spinor /////////////////////////////////////////////////////////////// for(int co_y=0;co_y<3;co_y++){ if ( (mu==0) && (pm==0) ) complex_AmiB(Y[2][co_y],Z,Y[1][co_y]); if ( (mu==0) && (pm==1) ) complex_ApiB(Y[2][co_y],Z,Y[1][co_y]); if ( (mu==1) && (pm==0) ) complex_add (Y[2][co_y],Z,Y[1][co_y]); if ( (mu==1) && (pm==1) ) complex_sub (Y[2][co_y],Z,Y[1][co_y]); if ( (mu==2) && (pm==0) ) complex_AmiB(Y[2][co_y],Z,Y[0][co_y]); if ( (mu==2) && (pm==1) ) complex_ApiB(Y[2][co_y],Z,Y[0][co_y]); if ( (mu==3) && (pm==0) ) complex_add (Y[2][co_y],Z,Y[0][co_y]); if ( (mu==3) && (pm==1) ) complex_sub (Y[2][co_y],Z,Y[0][co_y]); if ( (mu==0) && (pm==0) ) complex_AmiB(Y[3][co_y],Z,Y[0][co_y]); if ( (mu==0) && (pm==1) ) complex_ApiB(Y[3][co_y],Z,Y[0][co_y]); if ( (mu==1) && (pm==0) ) complex_sub (Y[3][co_y],Z,Y[0][co_y]); if ( (mu==1) && (pm==1) ) complex_add (Y[3][co_y],Z,Y[0][co_y]); if ( (mu==2) && (pm==0) ) complex_ApiB(Y[3][co_y],Z,Y[1][co_y]); if ( (mu==2) && (pm==1) ) complex_AmiB(Y[3][co_y],Z,Y[1][co_y]); if ( (mu==3) && (pm==0) ) complex_add (Y[3][co_y],Z,Y[1][co_y]); if ( (mu==3) && (pm==1) ) complex_sub (Y[3][co_y],Z,Y[1][co_y]); } /////////////////////////////////////////////////////////////// // Load X /////////////////////////////////////////////////////////////// for(int co_x=0;co_x<3;co_x++){ for(int sp=0;sp<4;sp++) { complex_load(X[sp][co_x],PSIIMM[sp][co_x][0],X_p,FourSpinType); } } /////////////////////////////////////////////////////////////// // Spin trace tensor product /////////////////////////////////////////////////////////////// for(int co_x=0;co_x<3;co_x++){ // Spin trace outer product for ( int co_y=0;co_y<3;co_y++) complex_load (F[co_y],GIMM[co_y][co_x][0],F_p_s); for ( int co_y=0;co_y<3;co_y++) complex_conjmadd(F[co_y],X[0][co_x],Y[0][co_y]); for ( int co_y=0;co_y<3;co_y++) complex_conjmadd(F[co_y],X[1][co_x],Y[1][co_y]); for ( int co_y=0;co_y<3;co_y++) complex_conjmadd(F[co_y],X[2][co_x],Y[2][co_y]); for ( int co_y=0;co_y<3;co_y++) complex_conjmadd(F[co_y],X[3][co_x],Y[3][co_y]); for ( int co_y=0;co_y<3;co_y++) complex_store(F[co_y],GIMM[co_y][co_x][0],F_p_s); } queue_load_addr(F_p_s,MAT_IMM,F_p_s); } queue_iadd_imm(X_p,X_p,PSI_IMM); queue_iadd_imm(s_offset,s_offset,CHI_IMM); stop_loop(branchls,s); queue_iadd_imm(F_p,F_p_s,ZERO_IMM); queue_load_addr(tab,TAB_IMM[16],tab); stop_loop(branchsite,length); make_inst(DIRECTIVE,Target,retno); /* * * EPILOGUE * */ restore_regs(); free_stack(); make_inst(DIRECTIVE,Exit_Routine,name); return; }
struct signal* fft(struct signal* p_signal) { struct signal* p_input_signal = \ (struct signal*) malloc(sizeof(struct complex_number)*(p_signal->size) + sizeof(p_signal->size)); struct signal* p_out_put_signal = \ (struct signal*)malloc(sizeof(struct complex_number)*(p_signal->size) + sizeof(p_signal->size)); *p_input_signal = *p_signal; *p_out_put_signal = *p_signal; int tmp = 0; int index = 0; int bits = 0; int layyer= 0; int selected_point = 0; int pre_half = 0; int r = 0; double x = 0; struct complex_number W_rN ; struct complex_number complex_tmp ; /* ** We caculate how many bits should be used to ** represent the size of the number of input signal. */ for(tmp = p_signal->size-1;tmp > 0;tmp>>=1) { bits++; } /* ** We should re-sequence the input signal ** by bit-reverse. */ for(tmp = 0;tmp < p_signal->size;tmp++) { index = reverse_bits(tmp,bits); p_input_signal->points[tmp] = p_signal->points[index]; #ifdef DEBUG printf(" tmp:%5d index:%5d ",tmp,index); show_complex_number(&p_signal->points[index]); #endif } for(layyer = 1;layyer <= bits;layyer++) { #ifdef DEBUG printf("layyer %d input\n",layyer); show_signal(p_input_signal); #endif for(selected_point = 0;selected_point < p_signal->size;selected_point += 1<<(layyer)) { for(pre_half = selected_point,r = 0,x = 0; pre_half < (selected_point + (1<<(layyer-1))); pre_half++) { r = get_r_in_Wn(pre_half,layyer,bits); #ifdef DEBUG printf("r: %d\n",r); #endif x = -2*PI*r/((double)(p_input_signal->size)); W_rN.real = cos(x); W_rN.imagine = sin(x); complex_tmp = complex_mul(&W_rN , &(p_input_signal->points[pre_half + (1<<(layyer-1))]) ); #ifdef DEBUG show_complex_number(&complex_tmp); #endif p_out_put_signal->points[pre_half] = \ complex_add(&p_input_signal->points[pre_half],&complex_tmp); p_out_put_signal->points[pre_half + (1<<(layyer-1))] = \ complex_sub(&p_input_signal->points[pre_half],&complex_tmp); } } #ifdef DEBUG printf("layyer%d output\n",layyer); show_signal(p_out_put_signal); #endif for(tmp = 0;tmp < p_out_put_signal->size;tmp++) { p_input_signal->points[tmp] = p_out_put_signal->points[tmp]; } } free(p_input_signal); return p_out_put_signal; }
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; }