-
Notifications
You must be signed in to change notification settings - Fork 8
/
Copy pathFgw.c
173 lines (144 loc) · 4.74 KB
/
Fgw.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
/*
Interface code for George Woltman's gwnum library
Copyright 2004-2006 Paul Zimmermann and Alexander Kruppa.
Contains code based on the GWNUM library,
copyright 2002-2005 George Woltman, Just For Fun Software, Inc.
This program is free software; you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by the
Free Software Foundation; either version 2 of the License, or (at your
option) any later version.
This program is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
more details.
You should have received a copy of the GNU General Public License along
with this program; see the file COPYING. If not, write to the Free
Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
02111-1307, USA.
*/
#include <stdlib.h>
#include <stdio.h>
#include <gmp.h>
#include "ecm-gmp.h"
#include "ecm.h"
#include "ecm-impl.h"
#define ADD_UNDERSCORES
#include "gwdbldbl.h"
#include "gwnum.h"
#include "cpuid.h"
void __gxx_personality_v0()
{
exit (EXIT_FAILURE);
}
void __cxa_guard_acquire ()
{
return;
}
void __cxa_guard_release ()
{
return;
}
static int
sgn (const int i)
{
if (i == 0)
return 0;
return i > 0 ? 1 : -1;
}
int
gw_ecm_stage1 (mpz_t f, curve *P, mpmod_t modulus,
double B1, double *B1done, mpz_t go)
{
const double gw_k = 1.;
const unsigned long gw_b = 2;
const unsigned long gw_n = abs (modulus->bits);
const signed long gw_c = sgn (modulus->bits);
ecm_uint gw_B1done = *B1done;
unsigned long siz_x, siz_z; /* Size of gw_x and gw_y as longs */
mpz_t gw_x, gw_z, gw_A;
int youpi;
if (mpz_cmp_ui (go, 1) > 0)
{
mpres_t b;
mpres_init (b, modulus);
mpres_add_ui (b, P->A, 2, modulus);
mpres_div_2exp (b, b, 2, modulus); /* b == (A+2)/4 */
ecm_mul (P->x, P->y, go, modulus, b);
mpres_clear (b, modulus);
}
outputf (OUTPUT_VERBOSE,
"Using gwnum_ecmStage1(%f, %d, %d, %d, , %.0f, %ld)\n",
gw_k, gw_b, gw_n, gw_c, B1, gw_B1done);
/* Copy x, z and A values from modular representation to
plain integers */
/* Allocate enough memory for any residue (mod 2^n+-1) for x, z */
mpz_init2 (gw_x, gw_n + 64);
mpz_init2 (gw_z, gw_n + 64);
mpz_init (gw_A);
/* mpres_get_z always produces non-negative integers */
mpres_get_z (gw_x, P->x, modulus);
mpres_get_z (gw_z, P->y, modulus);
mpres_get_z (gw_A, P->A, modulus);
/* gwnum_ecmStage1() wants long int pointers for size_x, size_z,
so copy them into long int vars */
siz_x = SIZ(gw_x);
siz_z = SIZ(gw_z);
#ifndef __MINGW64__
youpi = gwnum_ecmStage1_u32 (gw_k, gw_b, gw_n, gw_c,
PTR(modulus->orig_modulus), ABSIZ(modulus->orig_modulus),
B1, &gw_B1done, PTR(gw_A), ABSIZ(gw_A),
PTR(gw_x), &siz_x, PTR(gw_z), &siz_z, NULL, 0);
#else /* contributed by David Cleaver */
youpi = gwnum_ecmStage1_u64 (gw_k, gw_b, gw_n, gw_c,
PTR(modulus->orig_modulus), ABSIZ(modulus->orig_modulus),
B1, &gw_B1done, PTR(gw_A), ABSIZ(gw_A),
PTR(gw_x), &siz_x, PTR(gw_z), &siz_z, NULL, 0);
#endif
/* Test that not more was written to gw_x and gw_z than we had space for */
ASSERT_ALWAYS (siz_x <= (unsigned long) ALLOC(gw_x));
ASSERT_ALWAYS (siz_z <= (unsigned long) ALLOC(gw_z));
SIZ(gw_x) = siz_x;
SIZ(gw_z) = siz_z;
outputf (OUTPUT_DEVVERBOSE,
"gw_ecm_stage1: after gwnum_ecmStage1, \n"
"B1done = %lu, x = %Zd\nz = %Zd\n",
gw_B1done, gw_x, gw_z);
/* Copy x, z back to P and clean up the temp vars */
mpres_set_z (P->x, gw_x, modulus);
mpres_set_z (P->y, gw_z, modulus);
mpz_clear (gw_A);
mpz_clear (gw_z);
mpz_clear (gw_x);
*B1done = gw_B1done;
if (youpi > 1)
{
outputf (OUTPUT_ERROR, "GW stage 1 returned code %d\n", youpi);
youpi = ECM_ERROR;
goto end_of_gwecm;
}
if (youpi == 1)
{
/* How did that happen? Since we passed z, GWNUM should not do
an extgcd and so not find factors... but if it did anyways,
we deal with it. Who's going to turn down a factor? */
outputf (OUTPUT_DEVVERBOSE,
"gw_ecm_stage1: Strange, gwnum_ecmStage1 reports a factor\n");
mpres_get_z (f, P->x, modulus);
youpi = ECM_FACTOR_FOUND_STEP1;
goto end_of_gwecm;
}
/* Normalize z (in P->y) to 1 */
youpi = ECM_NO_FACTOR_FOUND;
if (!mpres_invert (P->y, P->y, modulus)) /* Factor found? */
{
mpres_gcd (f, P->y, modulus);
youpi = ECM_FACTOR_FOUND_STEP1;
}
else
{
mpres_mul (P->x, P->x, P->y, modulus);
mpres_set_ui (P->y, 1UL, modulus);
}
end_of_gwecm:
return youpi;
}