complex_list *compute_subtrahend (complex_node *mnode,complex_list *arow) { int decision; double real,imag; complex_node *num,*den,*anode,*snode; complex_list *subtr; subtr = (complex_list *) malloc (sizeof(complex_list)); complex_list_init (subtr,"Subtrahend"); anode = arow->head; while (anode != NULL) { //printf ("\nM: (%d , %d)\tA: (%d , %d)",mnode->row,mnode->col,anode->row,anode->col); if (anode->col >= mnode->row) { snode = (complex_node *) malloc (sizeof(complex_node)); snode = complex_mult (mnode,anode); complex_list_append (subtr,snode); } anode=anode->next; } return subtr; }
// input: pointer to an array of complex input samples // ouptut: pointer to an array where the result can be placed. // n : the number of samples. // step: what level are we currently at in the fft // preconditions: // input and output are valid pointers // input and output are of size n // n must be a power of 2. // DFT is defined as X(n) = sum( x[n] * e^(-2jnk*pi/N ) for n = 0 to N-1 static int _fft_run(complex_t* input, complex_t* output, int n, int step, int offset){ if( n == 1){ output[0] = input[0]; return 1; } complex_t even_output[n/2]; complex_t odd_output[n/2]; _fft_run(input, even_output, n/2, 2*step,offset); _fft_run(input+step, odd_output, n/2, 2*step, offset+1); int i = 0; complex_t Y_k,Z_k,W; for( i = 0;i < n/2; ++i){ Y_k = even_output[i]; Z_k = odd_output[i]; W = twiddle(n, i); complex_t temp; complex_mult(&W,&Z_k,&temp); output[i].re = Y_k.re + temp.re; output[i].im = Y_k.im + temp.im; output[i + n/2].re = Y_k.re - temp.re; output[i + n/2].im = Y_k.im - temp.im; } return 1; }
static void calc_powers(complex_t x, int max_power, complex_t* dst) { int i; dst[0] = complex_from_real(1.0); if (max_power >= 1) dst[1] = x; for (i = 2; i <= max_power; ++i) dst[i] = complex_mult(x, dst[i - 1]); }
// 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 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); }
/* Based on http://en.wikipedia.org/wiki/Quartic_function#Quick_and_memorable_solution_from_first_principles */ static int solve_depressed_quartic(const complex_t* poly, complex_t* results) { complex_t helper_cubic[4]; complex_t helper_results[3]; complex_t quadratic_factor[3]; complex_t p, c_plus_p_sqr, d_div_p; const complex_t e = poly[0]; const complex_t d = poly[1]; const complex_t c = poly[2]; int num_results; if (complex_eq(d, complex_from_real(0.0))) { int i, num_quad_results; complex_t quadratic[3]; complex_t quadratic_results[2]; quadratic[0] = e; quadratic[1] = c; quadratic[2] = complex_from_real(1.0); num_quad_results = solve_poly(2, quadratic, quadratic_results); for (i = 0; i < num_quad_results; ++i) { const complex_t s = complex_sqrt(quadratic_results[i]); results[2*i] = complex_negate(s); results[2*i + 1] = s; } return 2 * num_quad_results; } helper_cubic[0] = complex_negate(complex_mult(d, d)); helper_cubic[1] = complex_add(complex_mult(c, c), complex_mult_real(-4.0, e)); helper_cubic[2] = complex_mult_real(2.0, c); helper_cubic[3] = complex_from_real(1.0); if (solve_poly(3, helper_cubic, helper_results) < 1) return 0; p = complex_sqrt(helper_results[0]); c_plus_p_sqr = complex_add(c, complex_mult(p, p)); d_div_p = complex_div(d, p); quadratic_factor[0] = complex_add(c_plus_p_sqr, complex_negate(d_div_p)); quadratic_factor[1] = complex_mult_real(2.0, p); quadratic_factor[2] = complex_from_real(2.0); num_results = solve_poly(2, quadratic_factor, results); quadratic_factor[0] = complex_add(c_plus_p_sqr, d_div_p); quadratic_factor[1] = complex_negate(quadratic_factor[1]); return num_results + solve_poly(2, quadratic_factor, results + num_results); }
/* Based on http://en.wikipedia.org/wiki/Cubic_equation#Cardano.27s_method */ static int solve_depressed_cubic(const complex_t* poly, complex_t* results) { const complex_t q = poly[0]; const complex_t p = poly[1]; complex_t t, u, cubic_root_of_unity; int i; if (complex_eq(p, complex_from_real(0.0))) { results[0] = complex_pow_real(complex_negate(q), 1.0/3.0); return 1; } t = complex_add( complex_mult_real(0.25, complex_mult(q, q)), complex_mult_real(1.0/27.0, complex_mult(p, complex_mult(p, p)))); cubic_root_of_unity.real = -0.5; cubic_root_of_unity.imag = 0.5 * sqrt(3.0); for (i = 0; i < 3; ++i) { if (i == 0) u = complex_pow_real(complex_add(complex_mult_real(-0.5, q), complex_sqrt(t)), 1.0/3.0); else u = complex_mult(u, cubic_root_of_unity); results[i] = complex_add(u, complex_div(p, complex_mult_real(-3.0, u))); } return 3; }
int main(unsigned long long speid, unsigned long long argp, unsigned long long envp) { printf("Hello World! from Cell (0x%llx) with argp (0x%llx) \n", speid, argp); // TODO use argp float a[M] __attribute__ ((aligned(16))) = {10, 20, 0, 0, 0, 0, 0, 0}; float b[M] __attribute__ ((aligned(16))) = {1, 2, 0, 0, 0, 0, 0, 0}; float c[M] __attribute__ ((aligned(16))); printf("%f\n", dot_product(a, b, M)); complex_mult (in1, in2, out, N); return 0; }
int _fft(complex_t* input, complex_t* output, unsigned n){ jig_input(input,output,n); int level = 0; int num_levels = bit_len(n); int block_size = 2; for( level = num_levels-1; level != 0 ; --level){ int num_blocks = n / block_size; int segment = 0; complex_t Y_k,Z_k,W; complex_t* out; for(segment = 0; segment < num_blocks; ++segment){ out = output + segment*block_size; int i = 0; for( i = 0; i< block_size/2; ++i){ Y_k = out[i]; Z_k = out[i +block_size/2]; W = twiddle(block_size, i); complex_t temp; complex_mult(&W,&Z_k,&temp); out[i].re = Y_k.re + temp.re; out[i].im = Y_k.im + temp.im; out[i + block_size/2].re = Y_k.re - temp.re; out[i + block_size/2].im = Y_k.im - temp.im; } } block_size *= 2; } return 1; }
static void calc_shifted_coefs(complex_t shift, int degree, const complex_t* src, complex_t* dst) { double binomials[MAX_DEGREE + 1][MAX_DEGREE + 1]; complex_t shift_powers[MAX_DEGREE + 1]; int dst_i, src_i; for (dst_i = 0; dst_i <= degree; ++dst_i) dst[dst_i] = complex_from_real(0.0); calc_binomials(degree+1, sizeof(binomials[0]) / sizeof(binomials[0][0]), binomials[0]); calc_powers(shift, degree, shift_powers); for (src_i = 0; src_i <= degree; ++src_i) for (dst_i = 0; dst_i <= src_i; ++dst_i) dst[dst_i] = complex_add(dst[dst_i], complex_mult_real(binomials[src_i][dst_i], complex_mult(src[src_i], shift_powers[src_i - dst_i]))); }
static complex_t complex_div(complex_t a, complex_t b) { return complex_mult(a, complex_inverse(b)); }
static void compute_translation( PositionedTet *initial_ptet, PeripheralCurve which_curve, TraceDirection which_direction, Complex translation[2], /* returns translations based on ultimate */ /* and penultimate shapes */ FillingStatus which_structure) { PositionedTet ptet; int i, initial_strand, strand, *this_vertex, near_strands, left_strands; Complex left_endpoint[2], /* left_endpoint[ultimate/penultimate] */ right_endpoint[2], /* right_endpoint[ultimate/penultimate] */ old_diff, new_diff, rotation; /* * Place the near edge of the top vertex of the initial_ptet in the * complex plane with its left endpoint at zero and its right endpoint at one. * Trace the curve which_curve in the direction which_direction, using the * shapes of the ideal tetrahedra to compute the position of endpoints of * each edge we cross. When we return to our starting point in the manifold, * the position of the left endpoint (or the position of the right endpoint * minus one) will tell us the translation. * * Note that we are working in the orientation double cover of the cusp. * * Here's how we keep track of where we are. At each step, we are always * at the near edge of the top vertex (i.e. the truncated vertex opposite * the bottom face) of the PositionedTet ptet. The curve (i.e. the * meridian or longitude) may cross that edge several times. The variable * "strand" keeps track of which intersection we are at; 0 means we're at * the strand on the far left, 1 means we're at the next strand, etc. */ ptet = *initial_ptet; initial_strand = 0; strand = initial_strand; for (i = 0; i < 2; i++) /* i = ultimate, penultimate */ { left_endpoint[i] = Zero; right_endpoint[i] = One; } do { /* * Note the curve's intersection numbers with the near side and left side. */ this_vertex = ptet.tet->curve[which_curve][ptet.orientation][ptet.bottom_face]; near_strands = this_vertex[ptet.near_face]; left_strands = this_vertex[ptet.left_face]; /* * If we are tracing the curve backwards, negate the intersection numbers * so the rest of compute_translation() can enjoy the illusion that we * are tracing the curve forwards. */ if (which_direction == trace_backwards) { near_strands = - near_strands; left_strands = - left_strands; } /* * Does the current strand bend to the left or to the right? */ if (strand < FLOW(near_strands, left_strands)) { /* * The current strand bends to the left. */ /* * The left_endpoint remains fixed. * Update the right_endpoint. * * The plan is to compute the vector old_diff which runs * from left_endpoint to right_endpoint, multiply it by the * complex edge parameter to get the vector new_diff which * runs from left_endpoint to the new value of right_endpoint, * and then add new_diff to left_endpoint to get the new * value of right_endpoint itself. * * Note that the complex edge parameters are always expressed * relative to the right_handed Orientation, so if we are * viewing this Tetrahedron relative to the left_handed * Orientation, we must take the conjugate-inverse of the * edge parameter. */ for (i = 0; i < 2; i++) /* i = ultimate, penultimate */ { old_diff = complex_minus(right_endpoint[i], left_endpoint[i]); rotation = ptet.tet->shape[which_structure]->cwl[i][edge3_between_faces[ptet.near_face][ptet.left_face]].rect; if (ptet.orientation == left_handed) { rotation = complex_div(One, rotation); /* invert . . . */ rotation.imag = - rotation.imag; /* . . . and conjugate */ } new_diff = complex_mult(old_diff, rotation); right_endpoint[i] = complex_plus(left_endpoint[i], new_diff); } /* * strand remains unchanged. */ /* * Move the PositionedTet onward, following the curve. */ veer_left(&ptet); } else { /* * The current strand bends to the right. * * Proceed as above, but note that * * (1) We now divide by the complex edge parameter * instead of multiplying by it. * * (2) We must adjust the variable "strand". Some of the strands * from the near edge may be peeling off to the left (in which * case left_strands is negative), or some strands from the left * edge may be joining those from the near edge in passing to * the right edge (in which case left_strands is positive). * Either way, the code "strand += left_strands" is correct. */ for (i = 0; i < 2; i++) /* i = ultimate, penultimate */ { old_diff = complex_minus(left_endpoint[i], right_endpoint[i]); rotation = ptet.tet->shape[which_structure]->cwl[i][edge3_between_faces[ptet.near_face][ptet.right_face]].rect; if (ptet.orientation == left_handed) { rotation = complex_div(One, rotation); rotation.imag = - rotation.imag; } new_diff = complex_div(old_diff, rotation); left_endpoint[i] = complex_plus(right_endpoint[i], new_diff); } strand += left_strands; veer_right(&ptet); } } while ( ! same_positioned_tet(&ptet, initial_ptet) || strand != initial_strand); /* * Write the computed translations, and return. */ for (i = 0; i < 2; i++) /* i = ultimate, penultimate */ translation[i] = left_endpoint[i]; }
void compute_fourth_corner( Complex corner[4], VertexIndex missing_corner, Orientation orientation, ComplexWithLog cwl[3]) { int i; VertexIndex v[4]; Complex z[4], cross_ratio, diff20, diff21, numerator, denominator; /* * Given the locations on the sphere at infinity in * the upper half space model of three of a Tetrahedron's * four ideal vertices, compute_fourth_corner() computes * the location of the remaining corner. * * corner[4] is the array which contains the three known * corners, and into which the fourth will be * written. * * missing_corner is the index of the unknown corner. * * orientation is the Orientation with which the Tetrahedron * is currently being viewed. * * cwl[3] describes the shape of the Tetrahedron. */ /* * Set up an indexing scheme v[] for the vertices. * * If some vertex (!= missing_corner) is positioned at infinity, let its * index be v0. Otherwise choose v0 arbitrarily. Then choose * v2 and v3 so that the Tetrahedron looks right_handed relative * to the v[]. */ v[3] = missing_corner; v[0] = ! missing_corner; for (i = 0; i < 4; i++) if (i != missing_corner && complex_infinite(corner[i])) v[0] = i; if (orientation == right_handed) { v[1] = remaining_face[v[3]][v[0]]; v[2] = remaining_face[v[0]][v[3]]; } else { v[1] = remaining_face[v[0]][v[3]]; v[2] = remaining_face[v[3]][v[0]]; } /* * Let z[i] be the location of v[i]. * The z[i] are known for i < 3, unknown for i == 3. */ for (i = 0; i < 3; i++) z[i] = corner[v[i]]; /* * Note the cross_ratio at the edge connecting v0 to v1. */ cross_ratio = cwl[edge3_between_faces[v[0]][v[1]]].rect; if (orientation == left_handed) cross_ratio = complex_conjugate(complex_div(One, cross_ratio)); /* * The cross ratio is defined as * * (z3 - z1) (z2 - z0) * cross_ratio = ----------------------- * (z2 - z1) (z3 - z0) * * Solve for z3. * * z1*(z2 - z0) - cross_ratio*z0*(z2 - z1) * z3 = ----------------------------------------- * (z2 - z0) - cross_ratio*(z2 - z1) * * If z0 is infinite, this reduces to * * z3 = z1 + cross_ratio * (z2 - z1) * * which makes sense geometrically. */ if (complex_infinite(z[0]) == TRUE) z[3] = complex_plus( z[1], complex_mult( cross_ratio, complex_minus(z[2], z[1]) ) ); else { diff20 = complex_minus(z[2], z[0]); diff21 = complex_minus(z[2], z[1]); numerator = complex_minus( complex_mult(z[1], diff20), complex_mult( cross_ratio, complex_mult(z[0], diff21) ) ); denominator = complex_minus( diff20, complex_mult(cross_ratio, diff21) ); z[3] = complex_div(numerator, denominator); /* will handle division by Zero correctly */ } corner[missing_corner] = z[3]; }