Annotation of OpenXM_contrib/gmp/demos/qcn.c, Revision 1.1
1.1 ! maekawa 1: /* Use mpz_kronecker_ui() to calculate an estimate for the quadratic
! 2: class number h(d), for a given negative fundamental discriminant, using
! 3: Dirichlet's analytic formula. */
! 4:
! 5: /*
! 6: Copyright (C) 1999, 2000 Free Software Foundation, Inc.
! 7:
! 8: This file is part of the GNU MP Library.
! 9:
! 10: This program is free software; you can redistribute it and/or modify it
! 11: under the terms of the GNU General Public License as published by the Free
! 12: Software Foundation; either version 2 of the License, or (at your option)
! 13: any later version.
! 14:
! 15: This program is distributed in the hope that it will be useful, but WITHOUT
! 16: ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
! 17: FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
! 18: more details.
! 19:
! 20: You should have received a copy of the GNU General Public License along with
! 21: this program; if not, write to the Free Software Foundation, Inc., 59 Temple
! 22: Place - Suite 330, Boston, MA 02111-1307, USA. */
! 23:
! 24:
! 25: /* Usage: qcn <discriminant>...
! 26:
! 27: A fundamental discriminant means one of the form D or 4*D with D
! 28: square-free. Each argument is checked to see it's congruent to 0 or 1
! 29: mod 4 (as all discriminants must be), and that it's negative, but there's
! 30: no check on D being square-free.
! 31:
! 32: This program is a bit of a toy, there are better methods for calculating
! 33: the class number and class group structure.
! 34:
! 35: Reference:
! 36:
! 37: Daniel Shanks, "Class Number, A Theory of Factorization, and Genera",
! 38: Proc. Symp. Pure Math., vol 20, 1970, pages 415-440.
! 39:
! 40: */
! 41:
! 42: #include <math.h>
! 43: #include <stdio.h>
! 44:
! 45: #include "gmp.h"
! 46:
! 47:
! 48: /* A simple but slow primality test. */
! 49: int
! 50: prime_p (unsigned long n)
! 51: {
! 52: unsigned long i, limit;
! 53:
! 54: if (n == 2)
! 55: return 1;
! 56: if (n < 2 || !(n&1))
! 57: return 0;
! 58:
! 59: limit = (unsigned long) floor (sqrt ((double) n));
! 60: for (i = 3; i <= limit; i+=2)
! 61: if ((n % i) == 0)
! 62: return 0;
! 63:
! 64: return 1;
! 65: }
! 66:
! 67:
! 68: /* The formula is as follows, with d < 0.
! 69:
! 70: w * sqrt(-d) inf p
! 71: h(d) = ------------ * product --------
! 72: 2 * pi p=2 p - (d/p)
! 73:
! 74:
! 75: (d/p) is the Kronecker symbol and the product is over primes p. w is 6
! 76: when d=-3, 4 when d=-4, or 2 otherwise.
! 77:
! 78: Calculating the product up to p=infinity would take a long time, so for
! 79: the estimate primes up to 132,000 are used. Shanks found this giving an
! 80: accuracy of about 1 part in 1000, in normal cases. */
! 81:
! 82: double
! 83: qcn_estimate (mpz_t d)
! 84: {
! 85: #define P_LIMIT 132000
! 86:
! 87: double h;
! 88: unsigned long p;
! 89:
! 90: /* p=2 */
! 91: h = sqrt (-mpz_get_d (d)) / M_PI
! 92: * 2.0 / (2.0 - mpz_kronecker_ui (d, 2));
! 93:
! 94: if (mpz_cmp_si (d, -3) == 0) h *= 3;
! 95: else if (mpz_cmp_si (d, -4) == 0) h *= 2;
! 96:
! 97: for (p = 3; p < P_LIMIT; p += 2)
! 98: if (prime_p (p))
! 99: h *= (double) p / (double) (p - mpz_kronecker_ui (d, p));
! 100:
! 101: return h;
! 102: }
! 103:
! 104:
! 105: void
! 106: qcn_str (char *num)
! 107: {
! 108: mpz_t z;
! 109:
! 110: mpz_init_set_str (z, num, 0);
! 111:
! 112: if (mpz_sgn (z) >= 0)
! 113: {
! 114: mpz_out_str (stdout, 0, z);
! 115: printf (" is not supported (negatives only)\n");
! 116: }
! 117: else if (mpz_fdiv_ui (z, 4) != 0 && mpz_fdiv_ui (z, 4) != 1)
! 118: {
! 119: mpz_out_str (stdout, 0, z);
! 120: printf (" is not a discriminant (must == 0 or 1 mod 4)\n");
! 121: }
! 122: else
! 123: {
! 124: printf ("h(");
! 125: mpz_out_str (stdout, 0, z);
! 126: printf (") approx %.1f\n", qcn_estimate (z));
! 127: }
! 128: mpz_clear (z);
! 129: }
! 130:
! 131:
! 132: int
! 133: main (int argc, char *argv[])
! 134: {
! 135: int i;
! 136:
! 137: if (argc < 2)
! 138: {
! 139: qcn_str ("-85702502803"); /* is 16259 */
! 140: qcn_str ("-328878692999"); /* is 1499699 */
! 141: qcn_str ("-928185925902146563"); /* is 52739552 */
! 142: qcn_str ("-84148631888752647283"); /* is 496652272 */
! 143: }
! 144: else
! 145: {
! 146: for (i = 1; i < argc; i++)
! 147: qcn_str (argv[i]);
! 148: }
! 149:
! 150: return 0;
! 151: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>