예제 #1
0
파일: sf-gamma.c 프로젝트: nzinfo/gnumeric
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);
	}
}
예제 #2
0
complex_float complex_cot(complex_float c1){
	// this is 1/tan = 1/(sin/cos) = cos/sin
	complex_float cpx_sin = complex_sin(c1);
	complex_float cpx_cos = complex_cos(c1);
	complex_float r = complex_div(cpx_cos,cpx_sin);
	return r;
}
예제 #3
0
complex_float complex_log(complex_float c1, complex_float c2){
	complex_float a, b, r;
	a = complex_ln(c1);
	b = complex_ln(c2);
	r = complex_div(b,a);
	return r;
}
예제 #4
0
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;
}
예제 #5
0
complex_float complex_hyptan(complex_float c1){
	// I'm assuming sinh/cosh
	complex_float cpx_sinh = complex_hypsin(c1);
	complex_float cpx_cosh = complex_hypcos(c1);
	complex_float r = complex_div(cpx_sinh,cpx_cosh);
	return r;
}
예제 #6
0
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;
}
예제 #7
0
static void compute_cwl(
    ComplexWithLog  cwl[3],
    EdgeIndex       e)
{
    /*
     *  Compute cwl[(e+1)%3] and cwl[(e+2)%3] in terms of cwl[e].
     */

    int i;

    for (i = 1; i < 3; i++)
    {
        cwl[(e+i)%3].rect = complex_div(One, complex_minus(One, cwl[(e+i-1)%3].rect));
        cwl[(e+i)%3].log  = complex_log(cwl[(e+i)%3].rect, PI_OVER_2);
    }
}
예제 #8
0
/* 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);
}
예제 #9
0
/* poly: pointer to coefficients array of size degree + 1.
 * results: pointer to results output array of size degree.
 */
int solve_poly(int degree, const complex_t* poly, complex_t* results) {
    complex_t normalized_poly[MAX_DEGREE + 1];
    int i;
    const complex_t a = poly[degree];
    if (complex_eq(a, complex_from_real(0.0)))
        return solve_poly(degree - 1, poly, results);
    if (degree > MAX_DEGREE)
        return -1;
    if (degree > 2 && stableness_score(poly[degree], poly[degree - 1]) > stableness_score(poly[0], poly[1])) {
        complex_t rev_poly[MAX_DEGREE + 1];
        int num_results;
        for (i = 0; i <= degree; ++i)
            rev_poly[i] = poly[degree - i];
        num_results = solve_poly(degree, rev_poly, results);
        for (i = 0; i < num_results; ++i)
            results[i] = complex_inverse(results[i]);
        return num_results;
    }
    for (i = 0; i < degree; ++i)
        normalized_poly[i] = complex_div(poly[i], a);
    normalized_poly[degree] = complex_from_real(1.0);
    return solve_normalized_poly(degree, normalized_poly, results);
}
예제 #10
0
/* 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;
}
예제 #11
0
// 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
예제 #12
0
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];
}
예제 #13
0
static void compute_derivative(
	Triangulation	*manifold)
{
	Tetrahedron	*tet;
	Complex		z[3],
				d[3],
				*eqn_coef = NULL,
				dz[2];
	EdgeIndex	e;
	VertexIndex	v;
	FaceIndex	initial_side,
				terminal_side;
	int			init[2][2],
				term[2][2];
	double		m,
				l,
				a,
				b,
				*eqn_coef_00 = NULL,
				*eqn_coef_01 = NULL,
				*eqn_coef_10 = NULL,
				*eqn_coef_11 = NULL;
	int			i,
				j;

	for (tet = manifold->tet_list_begin.next;
		 tet != &manifold->tet_list_end;
		 tet = tet->next)
	{
		/*
		 *	Note the three edge parameters.
		 */

		for (i = 0; i < 3; i++)
			z[i] = tet->shape[filled]->cwl[ultimate][i].rect;

		/*
		 *	Set the derivatives of log(z0), log(z1) and log(z2)
		 *	with respect to the given coordinate system, as
		 *	indicated by the above table.
		 */

		switch (tet->coordinate_system)
		{
			case 0:
				d[0] = One;
				d[1] = complex_div(MinusOne, z[2]);
				d[2] = complex_minus(Zero, z[1]);
				break;

			case 1:
				d[0] = complex_minus(Zero, z[2]);
				d[1] = One;
				d[2] = complex_div(MinusOne, z[0]);
				break;

			case 2:
				d[0] = complex_div(MinusOne, z[1]);
				d[1] = complex_minus(Zero, z[0]);
				d[2] = One;
				break;
		}


		/*
		 *	Record this tetrahedron's contribution to the edge equations.
		 */

		for (e = 0; e < 6; e++)		/* Look at each of the six edges. */
		{
			/*
			 *	Find the matrix entry(ies) corresponding to the
			 *	derivative of the edge equation with respect to this
			 *	tetrahedron.  If the manifold is oriented it will be
			 *	a single entry in the complex matrix.  If the manifold
			 *	is unoriented it will be a 2 x 2 block in the real matrix.
			 */

			if (manifold->orientability == oriented_manifold || manifold->orientability == oriented_orbifold ) /* DJH */
				eqn_coef	= &tet->edge_class[e]->complex_edge_equation[tet->index];
			else
			{
				eqn_coef_00	= &tet->edge_class[e]->real_edge_equation_re[2 * tet->index];
				eqn_coef_01	= &tet->edge_class[e]->real_edge_equation_re[2 * tet->index + 1];
				eqn_coef_10	= &tet->edge_class[e]->real_edge_equation_im[2 * tet->index];
				eqn_coef_11	= &tet->edge_class[e]->real_edge_equation_im[2 * tet->index + 1];
			}

			/*
			 *	Add in the derivative of the log of the edge parameter
			 *	with respect to the chosen coordinate system.  Please
			 *	see the comment preceding this function for details.
			 */

			if (manifold->orientability == oriented_manifold || manifold->orientability == oriented_orbifold ) /* DJH */

				*eqn_coef = complex_plus(*eqn_coef, d[edge3[e]]);

			else
			{
				/*
				 *	These are the same a and b as in the comment
				 *	preceding this function.
				 */

				a = d[edge3[e]].real;
				b = d[edge3[e]].imag;

				if (tet->edge_orientation[e] == right_handed)
				{
					*eqn_coef_00 += a;
					*eqn_coef_01 -= b;
					*eqn_coef_10 += b;
					*eqn_coef_11 += a;
				}
				else
				{
					*eqn_coef_00 -= a;
					*eqn_coef_01 += b;
					*eqn_coef_10 += b;
					*eqn_coef_11 += a;
				}
			}
		}


		/*
		 *	Record this tetrahedron's contribution to the cusp equations.
		 */

		for (v = 0; v < 4; v++)		/* Look at each ideal vertex. */
		{
			/*
			 *	Note the Dehn filling coefficients on this cusp.
			 *	If the cusp is complete, use m = 1.0 and l = 0.0.
			 */

			if (tet->cusp[v]->is_complete) /* DJH : not sure ? */
			{
				m = 1.0;
				l = 0.0;
			}
			else
			{
				m = tet->cusp[v]->m;
				l = tet->cusp[v]->l;
			}

			/*
			 *	Find the matrix entry(ies) corresponding to the
			 *	derivative of the cusp equation with respect to this
			 *	tetrahedron.  If the manifold is oriented it will be
			 *	a single entry in the complex matrix.  If the manifold
			 *	is unoriented it will be a 2 x 2 block in the real matrix.
			 */
													/* DJH */
			if ( (manifold->orientability == oriented_manifold || manifold->orientability == oriented_orbifold ) && (
 				tet->cusp[v]->topology == torus_cusp || tet->cusp[v]->topology == Klein_cusp ) ) 
				eqn_coef = &tet->cusp[v]->complex_cusp_equation[tet->index];
			else
			{
				eqn_coef_00 = &tet->cusp[v]->real_cusp_equation_re[2 * tet->index];
				eqn_coef_01 = &tet->cusp[v]->real_cusp_equation_re[2 * tet->index + 1];
				eqn_coef_10 = &tet->cusp[v]->real_cusp_equation_im[2 * tet->index];
				eqn_coef_11 = &tet->cusp[v]->real_cusp_equation_im[2 * tet->index + 1];
			}

			/*
			 *	Each ideal vertex contains two triangular cross sections,
			 *	one right_handed and the other left_handed.  We want to
			 *	compute the contribution of each angle of each triangle
			 *	to the holonomy.  We begin by considering the right_handed
			 *	triangle, looking at each of its three angles.  A directed
			 *	angle is specified by its initial and terminal sides.
			 *	We find the number of strands of the Dehn filling curve
			 *	passing from the initial side to the terminal side;
			 *	it is  m * (number of strands of meridian)
			 *	+ l * (number of strands of longitude), where (m,l) are
			 *	the Dehn filling coefficients (in practice, m and l need
			 *	not be integers, but it's simpler to imagine them to be
			 *	integers as you try to understand the following code).
			 *	The number of strands of the Dehn filling curves passing
			 *	from the initial to the terminal side is multiplied by
			 *	the derivative of the log of the complex angle, to yield
			 *	the contribution to the derivative matrix.  If the manifold
			 *	is oriented, that complex number is added directly to
			 *	the relevant matrix entry.  If the manifold is unoriented,
			 *	we convert the complex number to a 2 x 2 real matrix
			 *	(cf. the comments preceding this function) and add it to
			 *	the appropriate 2 x 2 block of the real derivative matrix.
			 *	The 2 x 2 matrix for the left_handed triangle is modified
			 *	to account for the fact that although the real part of the
			 *	derivative of the log (i.e. the compression/expansion
			 *	factor) is the same, the imaginary part (i.e. the rotation)
			 *	is negated.  [Note that in computing the edge equations
			 *	the real part was negated, while for the cusp equations
			 *	the imaginary part is negated.  I will leave an explanation
			 *	of the difference as an exercise for the reader.]
			 *
			 *	Note that we cannot possibly handle curves on the
			 *	left_handed sheet of the orientation double cover of
			 *	a cusp of an oriented manifold.  The reason is that the
			 *	log of the holonomy of the Dehn filling curve is not
			 *	a complex analytic function of the shape of the tetrahedron
			 *	(it's the complex conjugate of such a function).  I.e.
			 *	it doesn't have a derivative in the complex sense.  This
			 *	is why we make the convention that all peripheral curves
			 *	in oriented manifolds lie on the right_handed sheet of
			 *	the double cover.
			 */

			for (initial_side = 0; initial_side < 4; initial_side++)
			{
				if (initial_side == v)
					continue;

				terminal_side = remaining_face[v][initial_side];

				/*
				 *	Note the intersection numbers of the meridian and
				 *	longitude with the initial and terminal sides.
				 */

				for (i = 0; i < 2; i++)	{		/* which curve */
					for (j = 0; j < 2; j++)	{	/* which sheet */
						init[i][j] = tet->curve[i][j][v][initial_side];
						term[i][j] = tet->curve[i][j][v][terminal_side];
					}
				}

				/*
				 *	For each triangle (right_handed and left_handed),
				 *	multiply the number of strands of the Dehn filling
				 *	curve running from initial_side to terminal_side
				 *	by the derivative of the log of the edge parameter.
				 */

				for (i = 0; i < 2; i++)	/* which sheet */
					dz[i] = complex_real_mult(
						m * FLOW(init[M][i],term[M][i]) +	l * FLOW(init[L][i],term[L][i]),
						d[ edge3_between_faces[initial_side][terminal_side] ]
					);

				/*
				 *	If the manifold is oriented, the Dehn filling curve
				 *	must lie of the right_handed sheet of the orientation
				 *	double cover (cf. above).  Add its contributation to
				 *	the cusp equation.
				 */
													/* DJH */
				if (manifold->orientability == oriented_manifold || manifold->orientability == oriented_orbifold )

					*eqn_coef = complex_plus(*eqn_coef, dz[right_handed]);

				/* "else" follows below */

				/*
				 *	If the manifold is unoriented, treat the right_ and
				 *	left_handed sheets separately.  Add in the contribution
				 *	of the right_handed sheet normally.  For the left_handed
				 *	sheet, we must account for the fact that even though
				 *	the modulus of the derivative (i.e. the expansion/
				 *	contraction factor) is correct, its argument (i.e. the
				 *	angle of rotation) is the negative of what it should be.
				 */

				else
				{
					a = dz[right_handed].real;
					b = dz[right_handed].imag;
					*eqn_coef_00 += a;
					*eqn_coef_01 -= b;
					*eqn_coef_10 += b;
					*eqn_coef_11 += a;

					a = dz[left_handed].real;
					b = dz[left_handed].imag;
					*eqn_coef_00 += a;
					*eqn_coef_01 -= b;
					*eqn_coef_10 -= b;
					*eqn_coef_11 -= a;
				}

			}
		}
	}
}
예제 #14
0
complex_float complex_tan(complex_float c1){
	complex_float cpx_sin = complex_sin(c1);
	complex_float cpx_cos = complex_cos(c1);
	complex_float r = complex_div( cpx_sin, cpx_cos );
	return r;
}
예제 #15
0
static void compute_one_cusp_shape(
    Triangulation   *manifold,
    Cusp            *cusp,
    FillingStatus   which_structure)
{
    PositionedTet   initial_ptet;
    TraceDirection  direction[2];       /*  direction[M/L]                          */
    Complex         translation[2][2],  /*  translation[M/L][ultimate/penultimate]  */
                    shape[2];           /*  shape[ultimate/penultimate]             */
    int             i;

    /*
     *  Compute the longitudinal and meridional translations, and
     *  divide them to get the cusp shape.
     *
     *  Do parallel computations for the ultimate and penultimate shapes,
     *  to estimate the accuracy of the final answer.
     */

    /*
     *  Find and position a tetrahedron so that the near edge of the top
     *  vertex intersects both the meridian and the longitude.
     */
    initial_ptet = find_start(manifold, cusp);

    for (i = 0; i < 2; i++)     /* which curve */
    {
        /*
         *  Decide whether the meridian and longitude cross the near edge of the
         *  top vertex in a forwards or backwards direction.
         */
        direction[i] =
            (initial_ptet.tet->curve[i][initial_ptet.orientation] [initial_ptet.bottom_face] [initial_ptet.near_face] > 0) ?
            trace_forwards:
            trace_backwards;

        /*
         *  Compute the translation.
         */
        compute_translation(&initial_ptet, i, direction[i], translation[i], which_structure);
    }

    /*
     *  Compute the cusp shape.
     */
    for (i = 0; i < 2; i++)     /* i = ultimate, penultimate */
        shape[i] = complex_div(translation[L][i], translation[M][i]);   /* will handle division by Zero correctly */

    /*
     *  Record the cusp shape and its accuracy.
     */
    cusp->cusp_shape[which_structure]       = shape[ultimate];
    cusp->shape_precision[which_structure]  = complex_decimal_places_of_accuracy(shape[ultimate], shape[penultimate]);

    /*
     *  Adjust for the fact that the meridian and/or the longitude may have
     *  been traced backwards.
     */
    if (direction[M] != direction[L])
    {
        cusp->cusp_shape[which_structure].real = - cusp->cusp_shape[which_structure].real;
        cusp->cusp_shape[which_structure].imag = - cusp->cusp_shape[which_structure].imag;
    }

    /*
     *  As explained at the top of this file, the usual convention for the
     *  cusp shape requires viewing the cusp from the fat part of
     *  the manifold looking out, rather than from the cusp looking in, as
     *  in done in the rest of SnapPea.  For this reason, we must take the
     *  complex conjugate of the final cusp shape.
     */
    cusp->cusp_shape[which_structure].imag = - cusp->cusp_shape[which_structure].imag;
}
예제 #16
0
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;
}
예제 #17
0
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];
}
예제 #18
0
complex_float complex_sec(complex_float c1){
	// this is 1/cos
	complex_float cpx_cos = complex_cos(c1);
	complex_float r = complex_div(complex_make(1.0f),cpx_cos);
	return r;
}
예제 #19
0
complex_float complex_csc(complex_float c1){
	// this is 1/sin
	complex_float cpx_sin = complex_sin(c1);
	complex_float r = complex_div(complex_make(1.0f),cpx_sin);
	return r;
}
예제 #20
0
static void initial_tetrahedron(
	Triangulation	*manifold,
	Tetrahedron		**initial_tet,
	Boolean			compute_corners,
	Boolean			centroid_at_origin)
{
	VertexIndex	v[4];
	Complex		z,
				sqrt_z,
				w[4];
	Tetrahedron	*tet;
	EdgeIndex	best_edge,
				edge;

	/*
	 *	Set a default choice of tetrahedron and edge.
	 */
	*initial_tet = manifold->tet_list_begin.next;
	best_edge = 0;

	/*
	 *	2000/02/11 JRW  Can we choose the initial tetrahedron in such
	 *	a way that if we happen to have the canonical triangulation
	 *	of a 2-bridge knot or link complement, the basepoint falls
	 *	at a center of D2 symmetry?  That is, can we find a Tetrahedron
	 *	that looks like the "top of the tower" in the canonical
	 *	triangulation of a 2-bridge knot or link complement?
	 */
	for (tet = manifold->tet_list_begin.next;
		 tet != &manifold->tet_list_end;
		 tet = tet->next)
		for (edge = 0; edge < 6; edge++)
			if (tet->neighbor[one_face_at_edge  [edge]]
			 == tet->neighbor[other_face_at_edge[edge]])
			{
				*initial_tet	= tet;
				best_edge		= edge;
			}

	if (compute_corners)
	{
		if (centroid_at_origin == TRUE)
		{
			/*
			 *	Proposition.  For any value of w, positioning the corners at
			 *
			 *				corner[0] =  w
			 *				corner[1] =  w^-1
			 *				corner[2] = -w^-1
			 *				corner[3] = -w
			 *
			 *	defines a tetrahedron with its centroid at the "origin" and
			 *	the common perpendiculars between pairs of opposite edges
			 *	coincident with the "coordinate axes".  [In the Klein model,
			 *	the tetrahedron is inscribed in a rectangular box whose faces
			 *	are parallel to the coordinate axes.]
			 *
			 *	Proof:  Use the observation that the line from a0 to a1 will
			 *	intersect the line from b0 to b1 iff the cross ratio
			 *
			 *				(b0 - a0) (b1 - a1)
			 *				-------------------
			 *				(b1 - a0) (b0 - a1)
			 *
			 *	of the tetrahedron they span is real, and they will be
			 *	orthogonal iff the cross ratio is -1.
			 *
			 *	[-w, w] is orthogonal to [0, infinity] because
			 *
			 *				(0 - -w) (infinity - w)
			 *				----------------------- = -1
			 *				(infinity - -w) (0 - w)
			 *
			 *	and similarly for [-w^-1, w^-1] and [0, infinity].
			 *
			 *	[w^-1, w] is orthogonal to [-1, 1] because
			 *
			 *				(-1 - w^-1) (1 - w)
			 *				------------------- = -1
			 *				(1 - w^-1) (-1 - w)
			 *
			 *	and similarly for [-w^-1, -w] and [-1, 1].
			 *
			 *	[-w^-1, w] is orthogonal to [-i, i] because
			 *
			 *				(-i - -w^-1) (i - w)
			 *				-------------------- = -1
			 *				(i - -w^-1) (-i - w)
			 *
			 *	and similarly for [w^-1, -w] and [-i, i].
			 *
			 *	Q.E.D.
			 *
			 *
			 *	The tetrahedron will have the correct cross ratio z iff
			 *
			 *			(w - -w^-1) (w^-1 -   -w )    (w + w^-1)^2
			 *		z = -------------------------- = --------------
			 *			(w -   -w ) (w^-1 - -w^-1)         4
			 *
			 *	Solving for w in terms of z gives the four possibilities
			 *
			 *		w = +- (sqrt(z) +- sqrt(z - 1))
			 *
			 *	Note that sqrt(z) + sqrt(z - 1) and sqrt(z) - sqrt(z - 1) are
			 *	inverses of one another.  We can choose any of the four solutions
			 *	to be "w", and the other three will automatically become w^-1,
			 *	-w, and -w^-1.
			 *
			 *	Comment:  This position for the initial corners brings out
			 *	nice numerical properties in the O(3,1) matrices for manifolds
			 *	composed of regular ideal tetrahedra (cf. the proofs in the
			 *	directory "Tilings of H^3", which aren't part of SnapPea, but
			 *	I could give you a copy).
			 */

			z = (*initial_tet)->shape[filled]->cwl[ultimate][0].rect;

			w[0] = complex_plus(
					complex_sqrt(z),
					complex_sqrt(complex_minus(z, One))
				);
			w[1] = complex_div(One, w[0]);
			w[2] = complex_negate(w[1]);
			w[3] = complex_negate(w[0]);

			(*initial_tet)->corner[0] = w[0];
			(*initial_tet)->corner[1] = w[1];
			(*initial_tet)->corner[2] = w[2];
			(*initial_tet)->corner[3] = w[3];
		}
		else
		{
			/*
			 *	Originally this code positioned the Tetrahedron's vertices
			 *	at {0, 1, z, infinity}.  As of 2000/02/04 I modified it
			 *	to put the vertices at {0, 1/sqrt(z), sqrt(z), infinity} instead,
			 *	so that the basepoint (0,0,1) falls at the midpoint
			 *	of the edge extending from 0 to infinity, and the
			 *	tetrahedron's symmetry axis lies parallel to the x-axis.
			 *	To convince yourself that the tetrahedron's axis of
			 *	symmetry does indeed pass through that point, note
			 *	that a half turn around the axis of symmetry factors
			 *	as a reflection in the plane |z| = 1 followed by
			 *	a reflection in the vertical plane sitting over x-axis.
			 */

			/*
			 *	Order the vertices so that the tetrahedron is positively
			 *	oriented, and the selected edge is between vertices
			 *	v[0] and v[1].
			 */
			v[0] = one_vertex_at_edge[best_edge];
			v[1] = other_vertex_at_edge[best_edge];
			v[2] = remaining_face[v[1]][v[0]];
			v[3] = remaining_face[v[0]][v[1]];

			/*
			 *	Set the coordinates of the corners.
			 */

			z = (*initial_tet)->shape[filled]->cwl[ultimate][edge3[best_edge]].rect;
			sqrt_z = complex_sqrt(z);

			(*initial_tet)->corner[v[0]] = Infinity;
			(*initial_tet)->corner[v[1]] = Zero;
			(*initial_tet)->corner[v[2]] = complex_div(One, sqrt_z);
			(*initial_tet)->corner[v[3]] = sqrt_z;
		}
	}
}
예제 #21
0
complex_float complex_arctan(complex_float c1){
	complex_float cpx_asin = complex_arcsin(c1);
	complex_float cpx_acos = complex_arccos(c1);
	complex_float r = complex_div(cpx_asin,cpx_acos);
	return r;
}