[BACK]Return to qcn.c CVS log [TXT][DIR] Up to [local] / OpenXM_contrib / gmp / demos

Annotation of OpenXM_contrib/gmp/demos/qcn.c, Revision 1.1.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>