//$Header: /cvsroot/esrg/sfesrg/esrgnxpj/sfnthcgi0304/subfunc_gcd.c,v 1.5 2003/07/01 03:46:58 dtashley Exp $ // //******************************************************************************** //Copyright (C) 2003 David T. Ashley //******************************************************************************** //This program or source file 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 or source file 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 may have received a copy of the GNU General Public License //along with this program; if not, write to the Free Software //Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA // //This module is the GCD subfunction of a general-purpose CGI-BIN program to support //number theory demonstration applications. // //INPUT PARAMETERS //---------------- //The subfunction accepts two parameters, the integers whose GCD is to be //calculated. There is substantial tolerance for invalid characters. //Naturally, the integers should be positive. // //OUTPUT RESULTS //-------------- //The notation below gives the outputs of the program. In some cases, [i] notation //is used to indicate line numbers. // //[01] An overall success or failure code for the operation. Valid responses // are: // S : Success. // EP1A : The first integer could not be parsed, which means it is ill-formatted. // EP1B : The first integer was zero or negative. // EP2A : The second integer could not be parsed, which means it is ill-formatted. // EP2B : The second integer was zero or negative. // EQ : Other or unspecified error. // //[02] The fully normalized first integer entered. This means it has been // stripped of all weird characters, etc. This can be used by the // PHP script to repopulate the form boxes. //[03] The fully normalized second integer entered. // //In the event that the status code indicates error, no further lines //will be written. // //[04] The round number of the application of Euclid's algorithm, starting // at "1". //[05] "a". //[06] "b". //[07] a div b. //[08] a mod b. //[09] ... repeating sequence, starting back at [4] and repeating until a // zero remainder. //[..] The GCD of the two integers. This will be positive and // contain no commas or extraneous characters. //[..] "S", indicating success. // //Note that as per the definition above, any valid non-error output from //this program will contain a number of lines which is a multiple of 5. // //The return value (exit code) from this subfunction is always 0. // #define MODULE_SUBFUNC_GCD #include #include #include #include #include #include #include #include #include "auxfuncs.h" #include "subfunc_gcd.h" int SUBFUNC_GCD_main(int argc, char *argv[]) { //Normalized first and second parameters (the integers). char *arg1; char *arg2; //GMP types to maintain the algorithm. int round; mpz_t alg_a, alg_b, alg_adivb, alg_amodb; //There must be an acceptable number of command-line arguments. if (argc != 4) { printf("EQ\n0\n0\n"); return(0); } //Copy the command-line arguments to a safe place where we can manipulate them. //Leave 2 characters of space in case we assign a "0". arg1 = (char *)malloc((AUXFUNCS_size_t_max(1, strlen(argv[2])) + 1) * sizeof(char)); arg2 = (char *)malloc((AUXFUNCS_size_t_max(1, strlen(argv[3])) + 1) * sizeof(char)); if ((arg1 == NULL) || (arg2 == NULL)) { printf("EQ\n%s\n%s\n", argv[2], argv[3]); exit(0); } strcpy(arg1, argv[2]); strcpy(arg2, argv[3]); //Strip all of the non-digit trash out of the arguments. AUXFUNCS_remove_non_digits(arg1); AUXFUNCS_remove_non_digits(arg2); //Remove all leading zeros from both arguments. AUXFUNCS_remove_leading_zeros(arg1); AUXFUNCS_remove_leading_zeros(arg2); //If either argument is zero length, fill it in with 0. if (!strlen(arg1)) strcpy(arg1, "0"); if (!strlen(arg2)) strcpy(arg2, "0"); //If either argument exceeds 1000 digits, abort. if ((strlen(arg1)>1000) || (strlen(arg2) > 1000)) { printf("EQ\n0\n0\n"); return(0); } //If either argument is zero, abort. if (!strcmp(arg1, "0")) { printf("EP1B\n0\n0\n"); return(0); } if (!strcmp(arg2, "0")) { printf("EP2B\n0\n0\n"); return(0); } //Initialize all of the GMP variables. mpz_init(alg_a); mpz_init(alg_b); mpz_init(alg_adivb); mpz_init(alg_amodb); //Assign a and b to initial values. mpz_set_str(alg_a, arg1, 10); mpz_set_str(alg_b, arg2, 10); //We assume at this point that we will be successful. Output //the header stuff. printf("S\n"); mpz_out_str(stdout, 10, alg_a); printf("\n"); mpz_out_str(stdout, 10, alg_b); printf("\n"); //We require as an initial condition that a >= b. Make //that happen. if (mpz_cmp(alg_a, alg_b) < 0) { mpz_swap(alg_a, alg_b); } //To make the algorithm cleaner, we preload for the first //assignment. mpz_set(alg_amodb, alg_b); mpz_set(alg_b, alg_a); //Now begin the algorithm proper. round = 0; do { //We are at next round. round++; //Values for this round inherited from the last one. mpz_set(alg_a, alg_b); mpz_set(alg_b, alg_amodb); //Calculate the quotient and remainder. mpz_fdiv_qr(alg_adivb, alg_amodb, alg_a, alg_b); //Output all the data from the round. printf("%d\n", round); mpz_out_str(stdout, 10, alg_a); printf("\n"); mpz_out_str(stdout, 10, alg_b); printf("\n"); mpz_out_str(stdout, 10, alg_adivb); printf("\n"); mpz_out_str(stdout, 10, alg_amodb); printf("\n"); } while((round < 2000) && (mpz_sgn(alg_amodb) > 0)); //The GCD canonically will be the last non-zero remainder. mpz_out_str(stdout, 10, alg_b); printf("\n"); //Finally, we output the trailing "S". printf("S\n"); return(0); } //******************************************************************************** // $Log: subfunc_gcd.c,v $ // Revision 1.5 2003/07/01 03:46:58 dtashley // Edits towards working continued fraction best rational approximation // functionality. // // Revision 1.4 2003/04/17 20:02:05 dtashley // License text for the GPL added. All source files are now under the GPL, // after some discussion on the GMP list. // // Revision 1.3 2003/04/14 23:27:01 dtashley // Subfunction GMP_PROB_PRIME finished. // // Revision 1.2 2003/04/14 02:55:25 dtashley // Final edits on GCD. // // Revision 1.1 2003/04/13 23:46:06 dtashley // Initial checkin. //******************************************************************************** // End of SUBFUNC_GCD.C. //********************************************************************************