1 |
dashley |
172 |
//$Header$ |
2 |
|
|
// |
3 |
|
|
//******************************************************************************** |
4 |
|
|
//Copyright (C) 2003 David T. Ashley |
5 |
|
|
//******************************************************************************** |
6 |
|
|
//This program or source file is free software; you can redistribute it and/or |
7 |
|
|
//modify it under the terms of the GNU General Public License as published by |
8 |
|
|
//the Free Software Foundation; either version 2 of the License, or (at your |
9 |
|
|
//option) any later version. |
10 |
|
|
// |
11 |
|
|
//This program or source file is distributed in the hope that it will |
12 |
|
|
//be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of |
13 |
|
|
//MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
14 |
|
|
//GNU General Public License for more details. |
15 |
|
|
// |
16 |
|
|
//You may have received a copy of the GNU General Public License |
17 |
|
|
//along with this program; if not, write to the Free Software |
18 |
|
|
//Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
19 |
|
|
// |
20 |
|
|
//This module is the GCD subfunction of a general-purpose CGI-BIN program to support |
21 |
|
|
//number theory demonstration applications. |
22 |
|
|
// |
23 |
|
|
//INPUT PARAMETERS |
24 |
|
|
//---------------- |
25 |
|
|
//The subfunction accepts two parameters, the integers whose GCD is to be |
26 |
|
|
//calculated. There is substantial tolerance for invalid characters. |
27 |
|
|
//Naturally, the integers should be positive. |
28 |
|
|
// |
29 |
|
|
//OUTPUT RESULTS |
30 |
|
|
//-------------- |
31 |
|
|
//The notation below gives the outputs of the program. In some cases, [i] notation |
32 |
|
|
//is used to indicate line numbers. |
33 |
|
|
// |
34 |
|
|
//[01] An overall success or failure code for the operation. Valid responses |
35 |
|
|
// are: |
36 |
|
|
// S : Success. |
37 |
|
|
// EP1A : The first integer could not be parsed, which means it is ill-formatted. |
38 |
|
|
// EP1B : The first integer was zero or negative. |
39 |
|
|
// EP2A : The second integer could not be parsed, which means it is ill-formatted. |
40 |
|
|
// EP2B : The second integer was zero or negative. |
41 |
|
|
// EQ : Other or unspecified error. |
42 |
|
|
// |
43 |
|
|
//[02] The fully normalized first integer entered. This means it has been |
44 |
|
|
// stripped of all weird characters, etc. This can be used by the |
45 |
|
|
// PHP script to repopulate the form boxes. |
46 |
|
|
//[03] The fully normalized second integer entered. |
47 |
|
|
// |
48 |
|
|
//In the event that the status code indicates error, no further lines |
49 |
|
|
//will be written. |
50 |
|
|
// |
51 |
|
|
//[04] The round number of the application of Euclid's algorithm, starting |
52 |
|
|
// at "1". |
53 |
|
|
//[05] "a". |
54 |
|
|
//[06] "b". |
55 |
|
|
//[07] a div b. |
56 |
|
|
//[08] a mod b. |
57 |
|
|
//[09] ... repeating sequence, starting back at [4] and repeating until a |
58 |
|
|
// zero remainder. |
59 |
|
|
//[..] The GCD of the two integers. This will be positive and |
60 |
|
|
// contain no commas or extraneous characters. |
61 |
|
|
//[..] "S", indicating success. |
62 |
|
|
// |
63 |
|
|
//Note that as per the definition above, any valid non-error output from |
64 |
|
|
//this program will contain a number of lines which is a multiple of 5. |
65 |
|
|
// |
66 |
|
|
//The return value (exit code) from this subfunction is always 0. |
67 |
|
|
// |
68 |
|
|
|
69 |
|
|
#define MODULE_SUBFUNC_GCD |
70 |
|
|
|
71 |
|
|
#include <assert.h> |
72 |
|
|
#include <ctype.h> |
73 |
|
|
#include <stddef.h> |
74 |
|
|
#include <stdio.h> |
75 |
|
|
#include <stdlib.h> |
76 |
|
|
#include <string.h> |
77 |
|
|
#include <time.h> |
78 |
|
|
|
79 |
|
|
#include <gmp.h> |
80 |
|
|
|
81 |
|
|
#include "auxfuncs.h" |
82 |
|
|
#include "subfunc_gcd.h" |
83 |
|
|
|
84 |
|
|
int SUBFUNC_GCD_main(int argc, char *argv[]) |
85 |
|
|
{ |
86 |
|
|
//Normalized first and second parameters (the integers). |
87 |
|
|
char *arg1; |
88 |
|
|
char *arg2; |
89 |
|
|
|
90 |
|
|
//GMP types to maintain the algorithm. |
91 |
|
|
int round; |
92 |
|
|
mpz_t alg_a, alg_b, alg_adivb, alg_amodb; |
93 |
|
|
|
94 |
|
|
//There must be an acceptable number of command-line arguments. |
95 |
|
|
if (argc != 4) |
96 |
|
|
{ |
97 |
|
|
printf("EQ\n0\n0\n"); |
98 |
|
|
return(0); |
99 |
|
|
} |
100 |
|
|
|
101 |
|
|
//Copy the command-line arguments to a safe place where we can manipulate them. |
102 |
|
|
//Leave 2 characters of space in case we assign a "0". |
103 |
|
|
arg1 = (char *)malloc((AUXFUNCS_size_t_max(1, strlen(argv[2])) + 1) * sizeof(char)); |
104 |
|
|
arg2 = (char *)malloc((AUXFUNCS_size_t_max(1, strlen(argv[3])) + 1) * sizeof(char)); |
105 |
|
|
if ((arg1 == NULL) || (arg2 == NULL)) |
106 |
|
|
{ |
107 |
|
|
printf("EQ\n%s\n%s\n", argv[2], argv[3]); |
108 |
|
|
exit(0); |
109 |
|
|
} |
110 |
|
|
strcpy(arg1, argv[2]); |
111 |
|
|
strcpy(arg2, argv[3]); |
112 |
|
|
|
113 |
|
|
//Strip all of the non-digit trash out of the arguments. |
114 |
|
|
AUXFUNCS_remove_non_digits(arg1); |
115 |
|
|
AUXFUNCS_remove_non_digits(arg2); |
116 |
|
|
|
117 |
|
|
//Remove all leading zeros from both arguments. |
118 |
|
|
AUXFUNCS_remove_leading_zeros(arg1); |
119 |
|
|
AUXFUNCS_remove_leading_zeros(arg2); |
120 |
|
|
|
121 |
|
|
//If either argument is zero length, fill it in with 0. |
122 |
|
|
if (!strlen(arg1)) |
123 |
|
|
strcpy(arg1, "0"); |
124 |
|
|
if (!strlen(arg2)) |
125 |
|
|
strcpy(arg2, "0"); |
126 |
|
|
|
127 |
|
|
//If either argument exceeds 1000 digits, abort. |
128 |
|
|
if ((strlen(arg1)>1000) || (strlen(arg2) > 1000)) |
129 |
|
|
{ |
130 |
|
|
printf("EQ\n0\n0\n"); |
131 |
|
|
return(0); |
132 |
|
|
} |
133 |
|
|
|
134 |
|
|
//If either argument is zero, abort. |
135 |
|
|
if (!strcmp(arg1, "0")) |
136 |
|
|
{ |
137 |
|
|
printf("EP1B\n0\n0\n"); |
138 |
|
|
return(0); |
139 |
|
|
} |
140 |
|
|
if (!strcmp(arg2, "0")) |
141 |
|
|
{ |
142 |
|
|
printf("EP2B\n0\n0\n"); |
143 |
|
|
return(0); |
144 |
|
|
} |
145 |
|
|
|
146 |
|
|
//Initialize all of the GMP variables. |
147 |
|
|
mpz_init(alg_a); |
148 |
|
|
mpz_init(alg_b); |
149 |
|
|
mpz_init(alg_adivb); |
150 |
|
|
mpz_init(alg_amodb); |
151 |
|
|
|
152 |
|
|
//Assign a and b to initial values. |
153 |
|
|
mpz_set_str(alg_a, arg1, 10); |
154 |
|
|
mpz_set_str(alg_b, arg2, 10); |
155 |
|
|
|
156 |
|
|
//We assume at this point that we will be successful. Output |
157 |
|
|
//the header stuff. |
158 |
|
|
printf("S\n"); |
159 |
|
|
mpz_out_str(stdout, 10, alg_a); |
160 |
|
|
printf("\n"); |
161 |
|
|
mpz_out_str(stdout, 10, alg_b); |
162 |
|
|
printf("\n"); |
163 |
|
|
|
164 |
|
|
//We require as an initial condition that a >= b. Make |
165 |
|
|
//that happen. |
166 |
|
|
if (mpz_cmp(alg_a, alg_b) < 0) |
167 |
|
|
{ |
168 |
|
|
mpz_swap(alg_a, alg_b); |
169 |
|
|
} |
170 |
|
|
|
171 |
|
|
//To make the algorithm cleaner, we preload for the first |
172 |
|
|
//assignment. |
173 |
|
|
mpz_set(alg_amodb, alg_b); |
174 |
|
|
mpz_set(alg_b, alg_a); |
175 |
|
|
|
176 |
|
|
//Now begin the algorithm proper. |
177 |
|
|
round = 0; |
178 |
|
|
do |
179 |
|
|
{ |
180 |
|
|
//We are at next round. |
181 |
|
|
round++; |
182 |
|
|
|
183 |
|
|
//Values for this round inherited from the last one. |
184 |
|
|
mpz_set(alg_a, alg_b); |
185 |
|
|
mpz_set(alg_b, alg_amodb); |
186 |
|
|
|
187 |
|
|
//Calculate the quotient and remainder. |
188 |
|
|
mpz_fdiv_qr(alg_adivb, alg_amodb, alg_a, alg_b); |
189 |
|
|
|
190 |
|
|
//Output all the data from the round. |
191 |
|
|
printf("%d\n", round); |
192 |
|
|
mpz_out_str(stdout, 10, alg_a); |
193 |
|
|
printf("\n"); |
194 |
|
|
mpz_out_str(stdout, 10, alg_b); |
195 |
|
|
printf("\n"); |
196 |
|
|
mpz_out_str(stdout, 10, alg_adivb); |
197 |
|
|
printf("\n"); |
198 |
|
|
mpz_out_str(stdout, 10, alg_amodb); |
199 |
|
|
printf("\n"); |
200 |
|
|
} |
201 |
|
|
while((round < 2000) && (mpz_sgn(alg_amodb) > 0)); |
202 |
|
|
|
203 |
|
|
//The GCD canonically will be the last non-zero remainder. |
204 |
|
|
mpz_out_str(stdout, 10, alg_b); |
205 |
|
|
printf("\n"); |
206 |
|
|
|
207 |
|
|
//Finally, we output the trailing "S". |
208 |
|
|
printf("S\n"); |
209 |
|
|
|
210 |
|
|
return(0); |
211 |
|
|
} |
212 |
|
|
|
213 |
|
|
//******************************************************************************** |
214 |
|
|
// $Log: subfunc_gcd.c,v $ |
215 |
|
|
// Revision 1.5 2003/07/01 03:46:58 dtashley |
216 |
|
|
// Edits towards working continued fraction best rational approximation |
217 |
|
|
// functionality. |
218 |
|
|
// |
219 |
|
|
// Revision 1.4 2003/04/17 20:02:05 dtashley |
220 |
|
|
// License text for the GPL added. All source files are now under the GPL, |
221 |
|
|
// after some discussion on the GMP list. |
222 |
|
|
// |
223 |
|
|
// Revision 1.3 2003/04/14 23:27:01 dtashley |
224 |
|
|
// Subfunction GMP_PROB_PRIME finished. |
225 |
|
|
// |
226 |
|
|
// Revision 1.2 2003/04/14 02:55:25 dtashley |
227 |
|
|
// Final edits on GCD. |
228 |
|
|
// |
229 |
|
|
// Revision 1.1 2003/04/13 23:46:06 dtashley |
230 |
|
|
// Initial checkin. |
231 |
|
|
//******************************************************************************** |
232 |
|
|
// End of SUBFUNC_GCD.C. |
233 |
|
|
//******************************************************************************** |