chiark / gitweb /
Improve primitive-element testing a lot. Now much more sensible and
[catacomb] / prim.c
1 /* -*-c-*-
2  *
3  * $Id: prim.c,v 1.2 2000/07/29 09:57:42 mdw Exp $
4  *
5  * Finding primitive elements
6  *
7  * (c) 1999 Straylight/Edgeware
8  */
9
10 /*----- Licensing notice --------------------------------------------------* 
11  *
12  * This file is part of Catacomb.
13  *
14  * Catacomb is free software; you can redistribute it and/or modify
15  * it under the terms of the GNU Library General Public License as
16  * published by the Free Software Foundation; either version 2 of the
17  * License, or (at your option) any later version.
18  * 
19  * Catacomb is distributed in the hope that it will be useful,
20  * but WITHOUT ANY WARRANTY; without even the implied warranty of
21  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
22  * GNU Library General Public License for more details.
23  * 
24  * You should have received a copy of the GNU Library General Public
25  * License along with Catacomb; if not, write to the Free
26  * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
27  * MA 02111-1307, USA.
28  */
29
30 /*----- Revision history --------------------------------------------------* 
31  *
32  * $Log: prim.c,v $
33  * Revision 1.2  2000/07/29 09:57:42  mdw
34  * Improve primitive-element testing a lot.  Now much more sensible and
35  * orthogonal: you can find a generator for any given subgroup order by
36  * putting in the appropriate parameters.
37  *
38  * Revision 1.1  1999/12/22 15:58:59  mdw
39  * Search for primitive elements using prime-search equipment.
40  *
41  */
42
43 /*----- Header files ------------------------------------------------------*/
44
45 #include "mp.h"
46 #include "mpint.h"
47 #include "mpmont.h"
48 #include "mprand.h"
49 #include "pgen.h"
50 #include "prim.h"
51
52 /*----- Main code ---------------------------------------------------------*/
53
54 /* --- @prim_test@ --- */
55
56 int prim_test(int rq, pgen_event *ev, void *p)
57 {
58   prim_ctx *c = p;
59   int rc = rq;
60
61   switch (rq) {
62     case PGEN_BEGIN:
63       return (PGEN_TRY);
64     case PGEN_TRY: {
65       mp *x;
66       rc = PGEN_FAIL;
67
68       if (!c->exp)
69         x = mp_copy(ev->m);
70       else {
71         x = mpmont_exp(&c->mm, MP_NEW, ev->m, c->exp);
72         if (MP_CMP(x, ==, MP_ONE))
73           goto done;
74       }
75       if (c->n == 0)
76         goto ok;
77       else {
78         size_t n = c->n;
79         mp **f = c->f;
80         mp *y = MP_NEW;
81         while (n) {
82           y = mpmont_exp(&c->mm, y, x, *f);
83           if (MP_CMP(y, ==, MP_ONE)) {
84             mp_drop(y);
85             goto done;
86           }
87           n--; f++;
88         }
89         mp_drop(y);
90       }
91     ok:
92       rc = PGEN_DONE;
93       mp_drop(ev->m);
94       ev->m = x;
95       break;
96     done:
97       mp_drop(x);
98     } break;
99   }
100
101   return (rc);
102 }
103
104 /* --- Trivial stepping functions -----------------------------------------*/
105
106 /* --- @prim_step@ --- */
107
108 int prim_step(int rq, pgen_event *ev, void *p)
109 {
110   unsigned *i = p;
111   switch (rq) {
112     case PGEN_BEGIN:
113     case PGEN_TRY:
114       if (*i >= NPRIME)
115         return PGEN_FAIL;
116       ev->m = mp_fromint(ev->m, primetab[(*i)++]);
117       return (PGEN_TRY);
118   }
119   return (0);
120 }
121
122 /*----- That's all, folks -------------------------------------------------*/