void compute_core_geodesic( Cusp *cusp, int *singularity_index, Complex length[2]) { int i; long int positive_d, negative_c; Real pi_over_n; /* * If the Cusp is unfilled or the Dehn filling coefficients aren't * integers, then just write in some zeros (as explained at the top * of this file) and return. */ if (cusp->is_complete == TRUE || Dehn_coefficients_are_integers(cusp) == FALSE) { *singularity_index = 0; length[ultimate] = Zero; length[penultimate] = Zero; return; } /* * The euclidean_algorithm() will give the singularity index * directly (as the g.c.d.), and the coefficients lead to the * complex length (cf. the explanation at the top of this file). */ *singularity_index = euclidean_algorithm( (long int) cusp->m, (long int) cusp->l, &positive_d, &negative_c); for (i = 0; i < 2; i++) /* i = ultimate, penultimate */ { /* * length[i] = c H(m) + d H(l) * * (The holonomies are already in logarithmic form.) */ length[i] = complex_plus( complex_real_mult( (Real) (double)(- negative_c), cusp->holonomy[i][M] ), complex_real_mult( (Real) (double) positive_d, cusp->holonomy[i][L] ) ); /* * Make sure the length is positive. */ if (length[i].real < 0.0) length[i] = complex_negate(length[i]); /* * We want to normalize the torsion to the range * [-pi/n + epsilon, pi/n + epsilon], where n is * the order of the singular locus. */ pi_over_n = PI / *singularity_index; while (length[i].imag < - pi_over_n + TORSION_EPSILON) length[i].imag += 2.0 * pi_over_n; while (length[i].imag > pi_over_n + TORSION_EPSILON) length[i].imag -= 2.0 * pi_over_n; /* * In the case of a Klein bottle cusp, H(m) will be purely * rotational and H(l) will be purely translational * (cf. the documentation at the top of holonomy.c). * But the longitude used in practice is actually the * double cover of the true longitude, so we have to * divide the core_length by two to compensate. */ if (cusp->topology == Klein_cusp) length[i].real /= 2.0; } }
bool MultiplyCrypter::isKeyUnambiguous( const Restklasse& key ) { return euclidean_algorithm( key.getSmallestIntegerRepresentation(), key.getModulo() ) == 1; }
static void current_curve_basis_on_cusp( Cusp *cusp, MatrixInt22 basis_change) { int m_int, l_int, the_gcd; long a, b; Complex new_shape; int multiple; int i, j; m_int = (int) cusp->m; l_int = (int) cusp->l; if (cusp->is_complete == FALSE /* cusp is filled and */ && m_int == cusp->m /* coefficients are integers */ && l_int == cusp->l) { /* * Find a and b such that am + bl = gcd(m, l). */ the_gcd = euclidean_algorithm(m_int, l_int, &a, &b); /* * Divide through by the g.c.d. */ m_int /= the_gcd; l_int /= the_gcd; /* * Set basis_change to * * m l * -b a */ basis_change[0][0] = m_int; basis_change[0][1] = l_int; basis_change[1][0] = -b; basis_change[1][1] = a; /* * Make sure the new longitude is as short as possible. * The ratio (new longitude)/(new meridian) should have a * real part in the interval (-1/2, +1/2]. */ /* * Compute the new_shape, using the tentative longitude. */ new_shape = transformed_cusp_shape( cusp->cusp_shape[initial], basis_change); /* * 96/10/1 There is a danger that for nonhyperbolic solutions * the cusp shape will be ill-defined (either very large or NaN). * However for some nonhyperbolic solutions (flat solutions * for example) it may make good sense. So we attempt to * make the longitude short iff the new_shape is defined and * not outrageously large; otherwise we're content with an * arbitrary longitude. */ if (complex_modulus(new_shape) < BIG_MODULUS) { /* * Figure out how many meridians we need to subtract * from the longitude. */ multiple = (int) floor(new_shape.real - (-0.5 + EPSILON)); /* * longitude -= multiple * meridian */ for (j = 0; j < 2; j++) basis_change[1][j] -= multiple * basis_change[0][j]; } } else { /* * Set basis_change to the identity. */ for (i = 0; i < 2; i++) for (j = 0; j < 2; j++) basis_change[i][j] = (i == j); } }