/[dtapublic]/projs/dtats/trunk/projs/20161014_cfbrapab/c_main.c
ViewVC logotype

Diff of /projs/dtats/trunk/projs/20161014_cfbrapab/c_main.c

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

projs/trunk/projs/20161014_cfbrapab/c_main.c revision 48 by dashley, Mon Oct 17 00:09:05 2016 UTC projs/dtats/trunk/projs/20161014_cfbrapab/c_main.c revision 98 by dashley, Sun Dec 18 00:57:31 2016 UTC
# Line 1  Line 1 
1  // $Header: svn://localhost/dtapublic/projs/trunk/projs/20161014_cfbrapab/cfbrapab.cpp 47 2016-10-17 00:04:56Z dashley $  // $Header: svn://localhost/dtapublic/projs/trunk/projs/20161014_cfbrapab/cfbrapab.cpp 47 2016-10-17 00:04:56Z dashley $
2  //-------------------------------------------------------------------------------------------------  //-------------------------------------------------------------------------------------------------
3  //This file is part of "cfbrapab", a program for determining the best rational approximation to a  //This file is part of "cfbrapab", a program for determining the best rational approximation to a
4  //real number, subject to constraints on the numerator and denominator, using continued fraction  //real number, subject to constraints on the numerator and denominator, using continued fraction
5  //algorithms.  //algorithms.
6  //-------------------------------------------------------------------------------------------------  //-------------------------------------------------------------------------------------------------
7  //This source code and any program in which it is compiled/used is provided under the MIT License,  //This source code and any program in which it is compiled/used is provided under the MIT License,
8  //reproduced below.  //reproduced below.
9  //-------------------------------------------------------------------------------------------------  //-------------------------------------------------------------------------------------------------
10  //Permission is hereby granted, free of charge, to any person obtaining a copy of  //Permission is hereby granted, free of charge, to any person obtaining a copy of
11  //this software and associated documentation files(the "Software"), to deal in the  //this software and associated documentation files(the "Software"), to deal in the
12  //Software without restriction, including without limitation the rights to use,  //Software without restriction, including without limitation the rights to use,
13  //copy, modify, merge, publish, distribute, sublicense, and / or sell copies of the  //copy, modify, merge, publish, distribute, sublicense, and / or sell copies of the
14  //Software, and to permit persons to whom the Software is furnished to do so,  //Software, and to permit persons to whom the Software is furnished to do so,
15  //subject to the following conditions :  //subject to the following conditions :
16  //  //
17  //The above copyright notice and this permission notice shall be included in all  //The above copyright notice and this permission notice shall be included in all
18  //copies or substantial portions of the Software.  //copies or substantial portions of the Software.
19  //  //
20  //THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR  //THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
21  //IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,  //IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
22  //FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE  //FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE
23  //AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER  //AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
24  //LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,  //LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
25  //OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE  //OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
26  //SOFTWARE.  //SOFTWARE.
27  //-------------------------------------------------------------------------------------------------  //-------------------------------------------------------------------------------------------------
28  #include <assert.h>  #include <assert.h>
29  #include <malloc.h>  #include <malloc.h>
30  #include <process.h>  #include <process.h>
31  #include <stdio.h>  #include <stdio.h>
32  #include <string.h>  #include <string.h>
33  #include <time.h>  #include <time.h>
34    
35    
36  #include "bstrfunc.h"  #include "bstrfunc.h"
37  #include "ccmalloc.h"  #include "ccmalloc.h"
38  #include "ccmfatal.h"  #include "ccmfatal.h"
39  #include "charfunc.h"  #include "charfunc.h"
40  #include "cu_msgs.h"  #include "cu_msgs.h"
41  #include "fcmiof.h"  #include "fcmiof.h"
42  #include "gmp_ints.h"  #include "gmp_ints.h"
43  #include "gmp_rats.h"  #include "gmp_rats.h"
44  #include "gmp_ralg.h"  #include "gmp_ralg.h"
45  #include "intfunc.h"  #include "intfunc.h"
46    
47    
48  #define PNAME "cfbrapab"  #define PNAME "cfbrapab"
49  #define PNAMEUC "CFBRAPAB"  #define PNAMEUC "CFBRAPAB"
50    
51    
52  const char *C_MAIN_cvcinfo(void)  const char *C_MAIN_cvcinfo(void)
53     {     {
54     return("$Header: /cvsroot/esrg/sfesrg/esrgpcpj/cfbrapab/c_main.c,v 1.6 2002/01/27 17:58:15 dtashley Exp $");     return("$Header: /cvsroot/esrg/sfesrg/esrgpcpj/cfbrapab/c_main.c,v 1.6 2002/01/27 17:58:15 dtashley Exp $");
55     }     }
56    
57    
58  //This is a NULL-terminated table of pointers to functions  //This is a NULL-terminated table of pointers to functions
59  //which return version control strings for all of the files  //which return version control strings for all of the files
60  //which make up the INTFAC program.  This information would  //which make up the INTFAC program.  This information would
61  //be helpful for debugging.  //be helpful for debugging.
62  static const char *(*C_MAIN_vcinfoptrs[])(void) =  static const char *(*C_MAIN_vcinfoptrs[])(void) =
63     {     {
64     //This is the main module, should come first.     //This is the main module, should come first.
65     C_MAIN_cvcinfo,     C_MAIN_cvcinfo,
66    
67     //And now the others, in alphabetical order.     //And now the others, in alphabetical order.
68     BSTRFUNC_hvcinfo,     BSTRFUNC_hvcinfo,
69     BSTRFUNC_cvcinfo,     BSTRFUNC_cvcinfo,
70     CCMALLOC_hvcinfo,     CCMALLOC_hvcinfo,
71     CCMALLOC_cvcinfo,     CCMALLOC_cvcinfo,
72     CCMFATAL_hvcinfo,     CCMFATAL_hvcinfo,
73     CCMFATAL_cvcinfo,     CCMFATAL_cvcinfo,
74     CHARFUNC_hvcinfo,     CHARFUNC_hvcinfo,
75     CHARFUNC_cvcinfo,     CHARFUNC_cvcinfo,
76     CU_MSGS_hvcinfo,     CU_MSGS_hvcinfo,
77     CU_MSGS_cvcinfo,     CU_MSGS_cvcinfo,
78     FCMIOF_hvcinfo,     FCMIOF_hvcinfo,
79     FCMIOF_cvcinfo,     FCMIOF_cvcinfo,
80     GMP_INTS_hvcinfo,     GMP_INTS_hvcinfo,
81     GMP_INTS_cvcinfo,     GMP_INTS_cvcinfo,
82     GMP_RALG_hvcinfo,     GMP_RALG_hvcinfo,
83     GMP_RALG_cvcinfo,     GMP_RALG_cvcinfo,
84     GMP_RATS_hvcinfo,     GMP_RATS_hvcinfo,
85     GMP_RATS_cvcinfo,     GMP_RATS_cvcinfo,
86     INTFUNC_hvcinfo,     INTFUNC_hvcinfo,
87     INTFUNC_cvcinfo,     INTFUNC_cvcinfo,
88     NULL     NULL
89     };     };
90    
91    
92  //This is the structure type used to hold information about all the  //This is the structure type used to hold information about all the
93  //command-line parameters.  //command-line parameters.
94  //  //
95  struct CfbrapabCmainStruct  struct CfbrapabCmainStruct
96     {     {
97     GMP_RATS_mpq_struct rn;     GMP_RATS_mpq_struct rn;
98        //The rational number specified on the command line.        //The rational number specified on the command line.
99        //symmetry.        //symmetry.
100     GMP_INTS_mpz_struct kmax;     GMP_INTS_mpz_struct kmax;
101        //The value of KMAX specified on the command line.  This must always        //The value of KMAX specified on the command line.  This must always
102        //be present.        //be present.
103     int hmax_specified;     int hmax_specified;
104        //TRUE if HMAX is specified in addition to KMAX.  KMAX is mandatory        //TRUE if HMAX is specified in addition to KMAX.  KMAX is mandatory
105        //in all cases.        //in all cases.
106     GMP_INTS_mpz_struct hmax;     GMP_INTS_mpz_struct hmax;
107        //The value of HMAX if it is specified.  This is optional.  This will be        //The value of HMAX if it is specified.  This is optional.  This will be
108        //set to zero if it is not present on the command line.        //set to zero if it is not present on the command line.
109     int neversmaller_specified;     int neversmaller_specified;
110        //TRUE if the -neversmaller option is specified on the command line.        //TRUE if the -neversmaller option is specified on the command line.
111     int neverlarger_specified;     int neverlarger_specified;
112        //TRUE if the -neverlarger option is specified on the command line.        //TRUE if the -neverlarger option is specified on the command line.
113     int pred_specified;     int pred_specified;
114        //TRUE if the -pred option is specified on the command line.        //TRUE if the -pred option is specified on the command line.
115     int succ_specified;     int succ_specified;
116        //TRUE if the -succ option specified on the command line.        //TRUE if the -succ option specified on the command line.
117     int n_specified;     int n_specified;
118        //TRUE if the -n parameter is specified on the command line.        //TRUE if the -n parameter is specified on the command line.
119     unsigned n;     unsigned n;
120        //The value of n if it has been specified.        //The value of n if it has been specified.
121     CU_MSGS_std_cmd_line_par_results_struct argblock;     CU_MSGS_std_cmd_line_par_results_struct argblock;
122        //The block holding the options which are common across all        //The block holding the options which are common across all
123        //of these command-line utilities.        //of these command-line utilities.
124     };     };
125    
126    
127  //Processes the command-line parameters, and abstracts it to a  //Processes the command-line parameters, and abstracts it to a
128  //the contents of a structure plus a failure flag.  //the contents of a structure plus a failure flag.
129  static void process_command_line_args(struct CfbrapabCmainStruct *parblock,  static void process_command_line_args(struct CfbrapabCmainStruct *parblock,
130                                       int argc,                                       int argc,
131                                       char* argv[])                                       char* argv[])
132     {     {
133     int error_flag;     int error_flag;
134     int first_dashed_parameter;     int first_dashed_parameter;
135     int i;     int i;
136     int recognized;     int recognized;
137    
138     //Eyeball the input parameters.     //Eyeball the input parameters.
139     assert(parblock != NULL);     assert(parblock != NULL);
140     assert(argc >= 1);     assert(argc >= 1);
141     assert(argv != NULL);     assert(argv != NULL);
142    
143     //We have to have at least 3 total parameters.  However, this is covered     //We have to have at least 3 total parameters.  However, this is covered
144     //in main().     //in main().
145    
146     //Process the first parameter, which has to be the rational number we     //Process the first parameter, which has to be the rational number we
147     //want to approximate.  If there is a problem, give a helpful message     //want to approximate.  If there is a problem, give a helpful message
148     //and exit with an error code.     //and exit with an error code.
149     GMP_RATS_mpq_init(&(parblock->rn));     GMP_RATS_mpq_init(&(parblock->rn));
150     GMP_RATS_mpq_set_all_format_rat_num( argv[1],     GMP_RATS_mpq_set_all_format_rat_num( argv[1],
151                                         &error_flag,                                         &error_flag,
152                                         &(parblock->rn));                                         &(parblock->rn));
153    
154     //If there was a parse error, announce and abort.     //If there was a parse error, announce and abort.
155     if (error_flag || GMP_RATS_mpq_is_nan(&(parblock->rn)))     if (error_flag || GMP_RATS_mpq_is_nan(&(parblock->rn)))
156        {        {
157        printf("\"%s\" is not a properly formatted rational number.\n", argv[1]);        printf("\"%s\" is not a properly formatted rational number.\n", argv[1]);
158        exit(4);        exit(4);
159        }        }
160    
161     //Normalize the rational number specified as input.  It is allowed to     //Normalize the rational number specified as input.  It is allowed to
162     //be negative.     //be negative.
163     GMP_RATS_mpq_normalize(&(parblock->rn));     GMP_RATS_mpq_normalize(&(parblock->rn));
164    
165     //The next item has to be a number, it has to be     //The next item has to be a number, it has to be
166     //an integer, it has to be positive, and it     //an integer, it has to be positive, and it
167     //is KMAX.  Parse out that.  If there are any     //is KMAX.  Parse out that.  If there are any
168     //errors, abort.     //errors, abort.
169     GMP_INTS_mpz_init(&(parblock->kmax));     GMP_INTS_mpz_init(&(parblock->kmax));
170     GMP_INTS_mpz_set_general_int(&(parblock->kmax), &error_flag, argv[2]);     GMP_INTS_mpz_set_general_int(&(parblock->kmax), &error_flag, argv[2]);
171     if (error_flag || GMP_INTS_mpz_is_zero(&(parblock->kmax)) || GMP_INTS_mpz_is_neg(&(parblock->kmax)))     if (error_flag || GMP_INTS_mpz_is_zero(&(parblock->kmax)) || GMP_INTS_mpz_is_neg(&(parblock->kmax)))
172        {        {
173        printf("\"%s\" is not a properly formatted positive integer.\n", argv[2]);        printf("\"%s\" is not a properly formatted positive integer.\n", argv[2]);
174        exit(4);        exit(4);
175        }        }
176    
177     //Unconditionally allocate space for hmax.     //Unconditionally allocate space for hmax.
178     GMP_INTS_mpz_init(&(parblock->hmax));     GMP_INTS_mpz_init(&(parblock->hmax));
179    
180     //If there is a third parameter, it can be two things.  It can     //If there is a third parameter, it can be two things.  It can
181     //be either HMAX, or it can be the start of the parameters     //be either HMAX, or it can be the start of the parameters
182     //with dashes.  First, let's decide which case applies.     //with dashes.  First, let's decide which case applies.
183     if (argc <= 3)     if (argc <= 3)
184        {        {
185        first_dashed_parameter = 3;        first_dashed_parameter = 3;
186        parblock->hmax_specified = 0;        parblock->hmax_specified = 0;
187        }        }
188     else     else
189        {        {
190        if (argv[3][0] == '-')        if (argv[3][0] == '-')
191           {           {
192           first_dashed_parameter = 3;           first_dashed_parameter = 3;
193           parblock->hmax_specified = 0;           parblock->hmax_specified = 0;
194           }           }
195        else        else
196           {           {
197           first_dashed_parameter = 4;           first_dashed_parameter = 4;
198           parblock->hmax_specified = 1;           parblock->hmax_specified = 1;
199    
200           GMP_INTS_mpz_set_general_int(&(parblock->hmax), &error_flag, argv[3]);           GMP_INTS_mpz_set_general_int(&(parblock->hmax), &error_flag, argv[3]);
201           if (error_flag || GMP_INTS_mpz_is_zero(&(parblock->hmax)) || GMP_INTS_mpz_is_neg(&(parblock->hmax)))           if (error_flag || GMP_INTS_mpz_is_zero(&(parblock->hmax)) || GMP_INTS_mpz_is_neg(&(parblock->hmax)))
202              {              {
203              printf("\"%s\" is not a properly formatted positive integer.\n", argv[3]);              printf("\"%s\" is not a properly formatted positive integer.\n", argv[3]);
204              exit(4);              exit(4);
205              }              }
206           }           }
207        }        }
208    
209     //Loop through the remaining parameters, trying to process each     //Loop through the remaining parameters, trying to process each
210     //one either as a parameter specific to this program or else     //one either as a parameter specific to this program or else
211     //as a general parameter.     //as a general parameter.
212     //     //
213     //Initialize the internal general parameter block.     //Initialize the internal general parameter block.
214     CU_MSGS_cmd_line_par_results_struct_create(&(parblock->argblock));     CU_MSGS_cmd_line_par_results_struct_create(&(parblock->argblock));
215     parblock->neversmaller_specified = 0;     parblock->neversmaller_specified = 0;
216     parblock->neverlarger_specified  = 0;     parblock->neverlarger_specified  = 0;
217     parblock->pred_specified         = 0;     parblock->pred_specified         = 0;
218     parblock->succ_specified         = 0;     parblock->succ_specified         = 0;
219     parblock->n_specified            = 0;     parblock->n_specified            = 0;
220     parblock->n                      = 0;     parblock->n                      = 0;
221    
222     for (i=first_dashed_parameter; i<argc; i++)     for (i=first_dashed_parameter; i<argc; i++)
223        {        {
224        if (!strcmp("-neversmaller", argv[i]))        if (!strcmp("-neversmaller", argv[i]))
225           {           {
226           parblock->neversmaller_specified = 1;           parblock->neversmaller_specified = 1;
227           }           }
228        else if (!strcmp("-neverlarger", argv[i]))        else if (!strcmp("-neverlarger", argv[i]))
229           {           {
230           parblock->neverlarger_specified = 1;           parblock->neverlarger_specified = 1;
231           }           }
232        else if (!strcmp("-pred", argv[i]))        else if (!strcmp("-pred", argv[i]))
233           {           {
234           parblock->pred_specified = 1;           parblock->pred_specified = 1;
235           }           }
236        else if (!strcmp("-succ", argv[i]))        else if (!strcmp("-succ", argv[i]))
237           {           {
238           parblock->succ_specified = 1;           parblock->succ_specified = 1;
239           }           }
240        else if (!strcmp("-n", argv[i]))        else if (!strcmp("-n", argv[i]))
241           {           {
242           parblock->n_specified = 1;           parblock->n_specified = 1;
243    
244           //To go along with -n, we have to have a next parameter.           //To go along with -n, we have to have a next parameter.
245           if (i == (argc-1))           if (i == (argc-1))
246              {              {
247              printf("The \"-n\" parameter must include a following count.\n");              printf("The \"-n\" parameter must include a following count.\n");
248              exit(4);              exit(4);
249              }              }
250    
251           //Bump i to index to next par.           //Bump i to index to next par.
252           i++;           i++;
253    
254           //Try to parse this as a UINT24.  It must be that.           //Try to parse this as a UINT24.  It must be that.
255           GMP_INTS_mpz_parse_into_uint32(&(parblock->n), &error_flag, argv[i]);           GMP_INTS_mpz_parse_into_uint32(&(parblock->n), &error_flag, argv[i]);
256    
257           //If it couldn't be parsed as an integer, flunk it.           //If it couldn't be parsed as an integer, flunk it.
258           if (error_flag)           if (error_flag)
259              {              {
260              printf("\"%s\" is not a valid unsigned integer or exceeds 24 bits.\n", argv[i]);              printf("\"%s\" is not a valid unsigned integer or exceeds 24 bits.\n", argv[i]);
261              exit(4);              exit(4);
262              }              }
263    
264           //If it is too large, flunk it.           //If it is too large, flunk it.
265           if (parblock->n > 0x00FFFFFF)           if (parblock->n > 0x00FFFFFF)
266              {              {
267              printf("\"%s\" is an unsigned integer but exceeds 24 bits.\n", argv[i]);              printf("\"%s\" is an unsigned integer but exceeds 24 bits.\n", argv[i]);
268              exit(4);              exit(4);
269              }              }
270    
271           //OK, we're cool ...           //OK, we're cool ...
272           }           }
273        else        else
274           {           {
275           //Two possibilities left.  Either general parameter, or else unrecognized.           //Two possibilities left.  Either general parameter, or else unrecognized.
276           CU_MSGS_cmd_line_par_results_struct_process_arg(&(parblock->argblock),           CU_MSGS_cmd_line_par_results_struct_process_arg(&(parblock->argblock),
277                                                           argv[i],                                                           argv[i],
278                                                           &recognized);                                                           &recognized);
279           if (!recognized)           if (!recognized)
280              {              {
281              printf("\"%s\" is not a recognized command-line parameter.\n", argv[i]);              printf("\"%s\" is not a recognized command-line parameter.\n", argv[i]);
282              exit(4);              exit(4);
283              }              }
284    
285           //Was picked up as general parameter.           //Was picked up as general parameter.
286           }           }
287        }        }
288    
289     //Congeal our thoughts on the "general" command-line parameters.  No errors possible     //Congeal our thoughts on the "general" command-line parameters.  No errors possible
290     //here.     //here.
291     CU_MSGS_cmd_line_par_results_struct_finalize(&(parblock->argblock));     CU_MSGS_cmd_line_par_results_struct_finalize(&(parblock->argblock));
292    
293     //printf("Boo.\n");     //printf("Boo.\n");
294     //printf("neverlarger %d succ %d\n", parblock->neverlarger_specified, parblock->succ_specified);     //printf("neverlarger %d succ %d\n", parblock->neverlarger_specified, parblock->succ_specified);
295    
296     //Look for mutually exclusive options among the program-specific parameters.     //Look for mutually exclusive options among the program-specific parameters.
297     if (     if (
298           (parblock->neversmaller_specified && (parblock->neverlarger_specified || parblock->pred_specified || parblock->succ_specified|| parblock->n_specified))           (parblock->neversmaller_specified && (parblock->neverlarger_specified || parblock->pred_specified || parblock->succ_specified|| parblock->n_specified))
299           ||           ||
300           (parblock->neverlarger_specified && (parblock->pred_specified || parblock->succ_specified || parblock->n_specified))           (parblock->neverlarger_specified && (parblock->pred_specified || parblock->succ_specified || parblock->n_specified))
301           ||           ||
302           (parblock->pred_specified && (parblock->succ_specified|| parblock->n_specified))           (parblock->pred_specified && (parblock->succ_specified|| parblock->n_specified))
303           ||           ||
304           (parblock->succ_specified && parblock->n_specified)           (parblock->succ_specified && parblock->n_specified)
305        )        )
306        {        {
307        printf("The \"-neversmaller\", \"-neverlarger\", \"-pred\", \"-succ\", and \"-n\" options are\nmutually exclusive.\n");        printf("The \"-neversmaller\", \"-neverlarger\", \"-pred\", \"-succ\", and \"-n\" options are\nmutually exclusive.\n");
308        exit(4);        exit(4);
309        }        }
310    
311     //OK, we're clean, all pars in order.     //OK, we're clean, all pars in order.
312     }     }
313    
314    
315  //Releases the dynamic memory associated with the parameter block.  //Releases the dynamic memory associated with the parameter block.
316  static void release_command_line_args(struct CfbrapabCmainStruct *parblock)  static void release_command_line_args(struct CfbrapabCmainStruct *parblock)
317     {     {
318     assert(parblock != NULL);     assert(parblock != NULL);
319    
320     //This function is superfluous, since in a command-line utility it doesn't really     //This function is superfluous, since in a command-line utility it doesn't really
321     //matter if everything is released.  But, here goes.     //matter if everything is released.  But, here goes.
322     CU_MSGS_cmd_line_par_results_struct_destroy(&(parblock->argblock));     CU_MSGS_cmd_line_par_results_struct_destroy(&(parblock->argblock));
323     GMP_RATS_mpq_clear(&(parblock->rn));     GMP_RATS_mpq_clear(&(parblock->rn));
324     GMP_INTS_mpz_clear(&(parblock->kmax));     GMP_INTS_mpz_clear(&(parblock->kmax));
325     GMP_INTS_mpz_clear(&(parblock->hmax));     GMP_INTS_mpz_clear(&(parblock->hmax));
326     }     }
327    
328    
329  //Prints out a single rational number in the format endorsed  //Prints out a single rational number in the format endorsed
330  //by this program.  This often includes DAP information  //by this program.  This often includes DAP information
331  //and difference information.  It is assumed that the  //and difference information.  It is assumed that the
332  //previous information is terminated by a horizontal line,  //previous information is terminated by a horizontal line,
333  //and this function terminates with a horizontal line.  //and this function terminates with a horizontal line.
334  static void CMAIN_print_app_in_std_form(FILE *s,  static void CMAIN_print_app_in_std_form(FILE *s,
335                                          int index,                                          int index,
336                                          GMP_RATS_mpq_struct *rn,                                          GMP_RATS_mpq_struct *rn,
337                                          GMP_RATS_mpq_struct *approx,                                          GMP_RATS_mpq_struct *approx,
338                                          int nf,                                          int nf,
339                                          int show_diff,                                          int show_diff,
340                                          int show_dap,                                          int show_dap,
341                                          GMP_INTS_mpz_struct *dap_den)                                          GMP_INTS_mpz_struct *dap_den)
342     {     {
343     char sbuf[250];     char sbuf[250];
344     GMP_RATS_mpq_struct diff, q_temp1;     GMP_RATS_mpq_struct diff, q_temp1;
345     GMP_INTS_mpz_struct z_temp1, quotient, remainder;     GMP_INTS_mpz_struct z_temp1, quotient, remainder;
346    
347     //Eyeball the input parameters.     //Eyeball the input parameters.
348     assert(s != NULL);     assert(s != NULL);
349     assert(rn != NULL);     assert(rn != NULL);
350     assert(approx != NULL);     assert(approx != NULL);
351     assert(dap_den != NULL);     assert(dap_den != NULL);
352    
353     //Allocate.     //Allocate.
354     GMP_RATS_mpq_init(&diff);     GMP_RATS_mpq_init(&diff);
355     GMP_RATS_mpq_init(&q_temp1);     GMP_RATS_mpq_init(&q_temp1);
356     GMP_INTS_mpz_init(&z_temp1);     GMP_INTS_mpz_init(&z_temp1);
357     GMP_INTS_mpz_init(&quotient);     GMP_INTS_mpz_init(&quotient);
358     GMP_INTS_mpz_init(&remainder);     GMP_INTS_mpz_init(&remainder);
359    
360     //Print out the approximation numerator.     //Print out the approximation numerator.
361     sprintf(sbuf, "approx_num(%d)", index);     sprintf(sbuf, "approx_num(%d)", index);
362     if (!nf)     if (!nf)
363        {        {
364        GMP_INTS_mpz_long_int_format_to_stream(s,        GMP_INTS_mpz_long_int_format_to_stream(s,
365                                               &(approx->num),                                               &(approx->num),
366                                               sbuf);                                               sbuf);
367        }        }
368     else     else
369        {        {
370        int nreserved;        int nreserved;
371        char *p;        char *p;
372                
373        fprintf(s, "%d\n", index);        fprintf(s, "%d\n", index);
374                
375        nreserved = GMP_INTS_mpz_size_in_base_10(&(approx->num));        nreserved = GMP_INTS_mpz_size_in_base_10(&(approx->num));
376        p = CCMALLOC_malloc(sizeof(char) * nreserved);        p = CCMALLOC_malloc(sizeof(char) * nreserved);
377        GMP_INTS_mpz_to_string(p, &(approx->num));        GMP_INTS_mpz_to_string(p, &(approx->num));
378        fprintf(s, "%s\n", p);        fprintf(s, "%s\n", p);
379        CCMALLOC_free(p);        CCMALLOC_free(p);
380        }        }
381    
382     if (!nf)     if (!nf)
383        FCMIOF_hline();        FCMIOF_hline();
384    
385     //Print out the approximation denominator.     //Print out the approximation denominator.
386     sprintf(sbuf, "approx_den(%d)", index);     sprintf(sbuf, "approx_den(%d)", index);
387     if (!nf)     if (!nf)
388        {        {
389        GMP_INTS_mpz_long_int_format_to_stream(s,        GMP_INTS_mpz_long_int_format_to_stream(s,
390                                               &(approx->den),                                               &(approx->den),
391                                               sbuf);                                               sbuf);
392        }        }
393     else     else
394        {        {
395        int nreserved;        int nreserved;
396        char *p;        char *p;
397    
398        nreserved = GMP_INTS_mpz_size_in_base_10(&(approx->den));        nreserved = GMP_INTS_mpz_size_in_base_10(&(approx->den));
399        p = CCMALLOC_malloc(sizeof(char) * nreserved);        p = CCMALLOC_malloc(sizeof(char) * nreserved);
400        GMP_INTS_mpz_to_string(p, &(approx->den));        GMP_INTS_mpz_to_string(p, &(approx->den));
401        fprintf(s, "%s\n", p);        fprintf(s, "%s\n", p);
402        CCMALLOC_free(p);        CCMALLOC_free(p);
403        }        }
404    
405     if (!nf)     if (!nf)
406        FCMIOF_hline();        FCMIOF_hline();
407    
408    
409     //If the "dap" flag is set, calculate and display decimal equivalent of the     //If the "dap" flag is set, calculate and display decimal equivalent of the
410     //approximation.     //approximation.
411     if (show_dap)     if (show_dap)
412        {        {
413        //Make the calculation for decimal approximation.        //Make the calculation for decimal approximation.
414        GMP_RATS_mpq_copy(&q_temp1, approx);        GMP_RATS_mpq_copy(&q_temp1, approx);
415        GMP_RATS_mpq_normalize(&q_temp1);        GMP_RATS_mpq_normalize(&q_temp1);
416        GMP_INTS_mpz_mul(&z_temp1, dap_den, &q_temp1.num);        GMP_INTS_mpz_mul(&z_temp1, dap_den, &q_temp1.num);
417        GMP_INTS_mpz_tdiv_qr(&quotient, &remainder,        GMP_INTS_mpz_tdiv_qr(&quotient, &remainder,
418                             &z_temp1, &q_temp1.den);                             &z_temp1, &q_temp1.den);
419    
420        sprintf(sbuf, "dap_num(%d)", index);        sprintf(sbuf, "dap_num(%d)", index);
421        if (!nf)        if (!nf)
422           {           {
423           GMP_INTS_mpz_long_int_format_to_stream(s,           GMP_INTS_mpz_long_int_format_to_stream(s,
424                                                  &(quotient),                                                  &(quotient),
425                                                  sbuf);                                                  sbuf);
426           }           }
427        else        else
428           {           {
429           int nreserved;           int nreserved;
430           char *p;           char *p;
431    
432           nreserved = GMP_INTS_mpz_size_in_base_10(&(quotient));           nreserved = GMP_INTS_mpz_size_in_base_10(&(quotient));
433           p = CCMALLOC_malloc(sizeof(char) * nreserved);           p = CCMALLOC_malloc(sizeof(char) * nreserved);
434           GMP_INTS_mpz_to_string(p, &(quotient));           GMP_INTS_mpz_to_string(p, &(quotient));
435           fprintf(s, "%s\n", p);           fprintf(s, "%s\n", p);
436           CCMALLOC_free(p);           CCMALLOC_free(p);
437           }           }
438    
439        if (!nf)        if (!nf)
440           FCMIOF_hline();           FCMIOF_hline();
441    
442        //Print out the approximation denominator.        //Print out the approximation denominator.
443        sprintf(sbuf, "dap_den(%d)", index);        sprintf(sbuf, "dap_den(%d)", index);
444        if (!nf)        if (!nf)
445           {           {
446           GMP_INTS_mpz_long_int_format_to_stream(s,           GMP_INTS_mpz_long_int_format_to_stream(s,
447                                                  dap_den,                                                  dap_den,
448                                                  sbuf);                                                  sbuf);
449           }           }
450        else        else
451           {           {
452           int nreserved;           int nreserved;
453           char *p;           char *p;
454    
455           nreserved = GMP_INTS_mpz_size_in_base_10(dap_den);           nreserved = GMP_INTS_mpz_size_in_base_10(dap_den);
456           p = CCMALLOC_malloc(sizeof(char) * nreserved);           p = CCMALLOC_malloc(sizeof(char) * nreserved);
457           GMP_INTS_mpz_to_string(p, dap_den);           GMP_INTS_mpz_to_string(p, dap_den);
458           fprintf(s, "%s\n", p);           fprintf(s, "%s\n", p);
459           CCMALLOC_free(p);           CCMALLOC_free(p);
460           }           }
461    
462        if (!nf)        if (!nf)
463           FCMIOF_hline();           FCMIOF_hline();
464        }        }
465    
466        
467     //If the "diff" flag is set, calculate and display the rational difference.     //If the "diff" flag is set, calculate and display the rational difference.
468     if (show_diff)     if (show_diff)
469        {        {
470        GMP_RATS_mpq_sub(&diff, approx, rn);        GMP_RATS_mpq_sub(&diff, approx, rn);
471        GMP_RATS_mpq_normalize(&diff);        GMP_RATS_mpq_normalize(&diff);
472    
473        sprintf(sbuf, "error_num(%d)", index);        sprintf(sbuf, "error_num(%d)", index);
474        if (!nf)        if (!nf)
475           {           {
476           GMP_INTS_mpz_long_int_format_to_stream(s,           GMP_INTS_mpz_long_int_format_to_stream(s,
477                                                  &(diff.num),                                                  &(diff.num),
478                                                  sbuf);                                                  sbuf);
479           }           }
480        else        else
481           {           {
482           int nreserved;           int nreserved;
483           char *p;           char *p;
484    
485           nreserved = GMP_INTS_mpz_size_in_base_10(&(diff.num));           nreserved = GMP_INTS_mpz_size_in_base_10(&(diff.num));
486           p = CCMALLOC_malloc(sizeof(char) * nreserved);           p = CCMALLOC_malloc(sizeof(char) * nreserved);
487           GMP_INTS_mpz_to_string(p, &(diff.num));           GMP_INTS_mpz_to_string(p, &(diff.num));
488           fprintf(s, "%s\n", p);           fprintf(s, "%s\n", p);
489           CCMALLOC_free(p);           CCMALLOC_free(p);
490           }           }
491    
492        if (!nf)        if (!nf)
493           FCMIOF_hline();           FCMIOF_hline();
494    
495        //Print out the approximation denominator.        //Print out the approximation denominator.
496        sprintf(sbuf, "error_den(%d)", index);        sprintf(sbuf, "error_den(%d)", index);
497        if (!nf)        if (!nf)
498           {           {
499           GMP_INTS_mpz_long_int_format_to_stream(s,           GMP_INTS_mpz_long_int_format_to_stream(s,
500                                                  &(diff.den),                                                  &(diff.den),
501                                                  sbuf);                                                  sbuf);
502           }           }
503        else        else
504           {           {
505           int nreserved;           int nreserved;
506           char *p;           char *p;
507    
508           nreserved = GMP_INTS_mpz_size_in_base_10(&(diff.den));           nreserved = GMP_INTS_mpz_size_in_base_10(&(diff.den));
509           p = CCMALLOC_malloc(sizeof(char) * nreserved);           p = CCMALLOC_malloc(sizeof(char) * nreserved);
510           GMP_INTS_mpz_to_string(p, &(diff.den));           GMP_INTS_mpz_to_string(p, &(diff.den));
511           fprintf(s, "%s\n", p);           fprintf(s, "%s\n", p);
512           CCMALLOC_free(p);           CCMALLOC_free(p);
513           }           }
514    
515        if (!nf)        if (!nf)
516           FCMIOF_hline();           FCMIOF_hline();
517        }        }
518    
519     //Deallocate.     //Deallocate.
520     GMP_RATS_mpq_clear(&diff);     GMP_RATS_mpq_clear(&diff);
521     GMP_RATS_mpq_clear(&q_temp1);     GMP_RATS_mpq_clear(&q_temp1);
522     GMP_INTS_mpz_clear(&z_temp1);     GMP_INTS_mpz_clear(&z_temp1);
523     GMP_INTS_mpz_clear(&quotient);     GMP_INTS_mpz_clear(&quotient);
524     GMP_INTS_mpz_clear(&remainder);     GMP_INTS_mpz_clear(&remainder);
525     }     }
526    
527    
528  //Handles the classic case of finding the closest  //Handles the classic case of finding the closest
529  //neighbor(s).  //neighbor(s).
530  static int CMAIN_classic_closest_neighbor(struct CfbrapabCmainStruct *parblock)  static int CMAIN_classic_closest_neighbor(struct CfbrapabCmainStruct *parblock)
531     {     {
532     int rv = 0;     int rv = 0;
533     GMP_RATS_mpq_struct hmax_over_one, hmax_over_kmax, rn_in_abs;     GMP_RATS_mpq_struct hmax_over_one, hmax_over_kmax, rn_in_abs;
534     GMP_INTS_mpz_struct dap_denominator;     GMP_INTS_mpz_struct dap_denominator;
535     GMP_RALG_cf_app_struct cf_decomp;     GMP_RALG_cf_app_struct cf_decomp;
536     GMP_RALG_fab_neighbor_collection_struct neighbor_data;     GMP_RALG_fab_neighbor_collection_struct neighbor_data;
537     int error_flag;     int error_flag;
538    
539     //Allocate all dynamic memory.     //Allocate all dynamic memory.
540     GMP_RATS_mpq_init(&hmax_over_one);     GMP_RATS_mpq_init(&hmax_over_one);
541     GMP_RATS_mpq_init(&hmax_over_kmax);     GMP_RATS_mpq_init(&hmax_over_kmax);
542     GMP_INTS_mpz_init(&dap_denominator);     GMP_INTS_mpz_init(&dap_denominator);
543     GMP_RATS_mpq_init(&rn_in_abs);     GMP_RATS_mpq_init(&rn_in_abs);
544    
545     //Set the DAP denominator to 1e108.     //Set the DAP denominator to 1e108.
546     GMP_INTS_mpz_set_general_int(&dap_denominator,     GMP_INTS_mpz_set_general_int(&dap_denominator,
547                                  &error_flag,                                  &error_flag,
548                                  "1e108");                                  "1e108");
549    
550     //By convention, we will not mess with anything with an     //By convention, we will not mess with anything with an
551     //absolute value greater than HMAX/1.  If such a condition exists, puke out.     //absolute value greater than HMAX/1.  If such a condition exists, puke out.
552     //Form up the value of HMAX/1 if HMAX was specified.     //Form up the value of HMAX/1 if HMAX was specified.
553     if (parblock->hmax_specified)     if (parblock->hmax_specified)
554        {        {
555        GMP_INTS_mpz_copy(&(hmax_over_one.num), &(parblock->hmax));        GMP_INTS_mpz_copy(&(hmax_over_one.num), &(parblock->hmax));
556        GMP_INTS_mpz_set_ui(&(hmax_over_one.den), 1);        GMP_INTS_mpz_set_ui(&(hmax_over_one.den), 1);
557        GMP_RATS_mpq_copy(&rn_in_abs, &(parblock->rn));        GMP_RATS_mpq_copy(&rn_in_abs, &(parblock->rn));
558        GMP_INTS_mpz_abs(&(rn_in_abs.num));        GMP_INTS_mpz_abs(&(rn_in_abs.num));
559        if (GMP_RATS_mpq_cmp(&(rn_in_abs), &hmax_over_one, NULL) > 0)        if (GMP_RATS_mpq_cmp(&(rn_in_abs), &hmax_over_one, NULL) > 0)
560           {           {
561           printf("The magnitude of the number supplied exceeds HMAX/1, and hence the number\n"           printf("The magnitude of the number supplied exceeds HMAX/1, and hence the number\n"
562                  "has no neighbors in the series of interest.  Calculation cannot continue.\n");                  "has no neighbors in the series of interest.  Calculation cannot continue.\n");
563           exit(4);           exit(4);
564           }           }
565        }        }
566    
567     //If the "verbose" option is specified, we want to give the continued fraction     //If the "verbose" option is specified, we want to give the continued fraction
568     //partial quotients and convergents of either the number to approximate,     //partial quotients and convergents of either the number to approximate,
569     //its reciprocal, or none of the above, as appropriate; and give a bit more     //its reciprocal, or none of the above, as appropriate; and give a bit more
570     //information, in addition.     //information, in addition.
571     if (parblock->argblock.verbose)     if (parblock->argblock.verbose)
572        {        {
573        if (parblock->hmax_specified)        if (parblock->hmax_specified)
574           {           {
575           //Stuff HMAX/KMAX.  This is necessary for comparison.           //Stuff HMAX/KMAX.  This is necessary for comparison.
576           GMP_INTS_mpz_copy(&(hmax_over_kmax.num), &(parblock->hmax));           GMP_INTS_mpz_copy(&(hmax_over_kmax.num), &(parblock->hmax));
577           GMP_INTS_mpz_copy(&(hmax_over_kmax.den), &(parblock->kmax));           GMP_INTS_mpz_copy(&(hmax_over_kmax.den), &(parblock->kmax));
578           }           }
579    
580        if (!(parblock->hmax_specified) || (GMP_RATS_mpq_cmp(&(parblock->rn), &hmax_over_kmax, NULL) < 0))        if (!(parblock->hmax_specified) || (GMP_RATS_mpq_cmp(&(parblock->rn), &hmax_over_kmax, NULL) < 0))
581           {           {
582           //Either HMAX was not specified or else we are below the corner point on the           //Either HMAX was not specified or else we are below the corner point on the
583           //integer lattice.  Get the continued fraction representation of the number           //integer lattice.  Get the continued fraction representation of the number
584           //rather than its reciprocal.           //rather than its reciprocal.
585           GMP_RALG_cfdecomp_init(&cf_decomp, &error_flag, &(rn_in_abs.num), &(rn_in_abs.den));           GMP_RALG_cfdecomp_init(&cf_decomp, &error_flag, &(rn_in_abs.num), &(rn_in_abs.den));
586    
587           //Print out the continued fraction decomposition of the rational number.           //Print out the continued fraction decomposition of the rational number.
588           GMP_RALG_cfdecomp_emit(stdout,           GMP_RALG_cfdecomp_emit(stdout,
589                                  "CF Rep Of Abs Value Of Number Specified",                                  "CF Rep Of Abs Value Of Number Specified",
590                                  &cf_decomp,                                  &cf_decomp,
591                                  0,                                  0,
592                                  1,                                  1,
593                                  &dap_denominator);                                  &dap_denominator);
594    
595           //Destroy the decomposition--free the memory.           //Destroy the decomposition--free the memory.
596           GMP_RALG_cfdecomp_destroy(&cf_decomp);           GMP_RALG_cfdecomp_destroy(&cf_decomp);
597           }           }
598        else if (GMP_RATS_mpq_cmp(&(rn_in_abs), &hmax_over_kmax, NULL) == 0)        else if (GMP_RATS_mpq_cmp(&(rn_in_abs), &hmax_over_kmax, NULL) == 0)
599           {           {
600           //In this case, the rational number specified is exactly the same in           //In this case, the rational number specified is exactly the same in
601           //magnitude as HMAX/KMAX.  I am inclined to suppress the CF decomp.           //magnitude as HMAX/KMAX.  I am inclined to suppress the CF decomp.
602           printf("Rational number specified is HMAX/KMAX.  CF decomp not provided.\n");           printf("Rational number specified is HMAX/KMAX.  CF decomp not provided.\n");
603           }           }
604        else        else
605           {           {
606           //The number specified is beyond the corner point.  It is appropriate to           //The number specified is beyond the corner point.  It is appropriate to
607           //provide the decomposition of the reciprocal rather than of the number           //provide the decomposition of the reciprocal rather than of the number
608           //itself.           //itself.
609           GMP_RALG_cfdecomp_init(&cf_decomp, &error_flag, &(rn_in_abs.den), &(rn_in_abs.num));           GMP_RALG_cfdecomp_init(&cf_decomp, &error_flag, &(rn_in_abs.den), &(rn_in_abs.num));
610    
611           //Print out the continued fraction decomposition of the rational number.           //Print out the continued fraction decomposition of the rational number.
612           GMP_RALG_cfdecomp_emit(stdout,           GMP_RALG_cfdecomp_emit(stdout,
613                                  "CF Rep Of Reciprocal Of Abs Value Of Number Specified",                                  "CF Rep Of Reciprocal Of Abs Value Of Number Specified",
614                                  &cf_decomp,                                  &cf_decomp,
615                                  0,                                  0,
616                                  1,                                  1,
617                                  &dap_denominator);                                  &dap_denominator);
618    
619           //Destroy the decomposition--free the memory.           //Destroy the decomposition--free the memory.
620           GMP_RALG_cfdecomp_destroy(&cf_decomp);           GMP_RALG_cfdecomp_destroy(&cf_decomp);
621           }           }
622        } //End if verbose.        } //End if verbose.
623    
624     //Do all the work to get the neighbors of the number passed.     //Do all the work to get the neighbors of the number passed.
625     GMP_RALG_consecutive_fab_terms(     GMP_RALG_consecutive_fab_terms(
626             &(parblock->rn),             &(parblock->rn),
627             &(parblock->kmax),             &(parblock->kmax),
628             (parblock->hmax_specified) ? (&(parblock->hmax)) : (NULL),             (parblock->hmax_specified) ? (&(parblock->hmax)) : (NULL),
629             1,             1,
630             1,             1,
631             &neighbor_data);             &neighbor_data);
632    
633     //Print the neighbor data block for debugging.     //Print the neighbor data block for debugging.
634     #if 0     #if 0
635     GMP_RALG_consecutive_fab_terms_result_dump(stdout, &neighbor_data);     GMP_RALG_consecutive_fab_terms_result_dump(stdout, &neighbor_data);
636     #endif     #endif
637    
638     //There are four possibilities at this point.     //There are four possibilities at this point.
639     //  a)Attempting to find the rational neighbors generated an error.     //  a)Attempting to find the rational neighbors generated an error.
640     //  b)The rational number specified was already in the series of interest,     //  b)The rational number specified was already in the series of interest,
641     //    in which case we will use it.     //    in which case we will use it.
642     //  c)The left neighbor is closer or in a tie we want to choose it.     //  c)The left neighbor is closer or in a tie we want to choose it.
643     //  d)The right neighbor is closer or in a tie we want to choose it.     //  d)The right neighbor is closer or in a tie we want to choose it.
644     if (neighbor_data.error)     if (neighbor_data.error)
645        {        {
646        //        //
647        printf("Internal error: %s\n", neighbor_data.error);        printf("Internal error: %s\n", neighbor_data.error);
648        }        }
649     else if (neighbor_data.equality)     else if (neighbor_data.equality)
650        {        {
651        CMAIN_print_app_in_std_form(stdout,        CMAIN_print_app_in_std_form(stdout,
652                                    0,                                    0,
653                                    &(neighbor_data.rn_in),                                    &(neighbor_data.rn_in),
654                                    &(neighbor_data.rn_in),                                    &(neighbor_data.rn_in),
655                                    parblock->argblock.noformat,                                    parblock->argblock.noformat,
656                                    0,                                    0,
657                                    1,                                    1,
658                                    &dap_denominator);                                    &dap_denominator);
659        }        }
660     else     else
661        {        {
662        GMP_RATS_mpq_struct left_neighbor, right_neighbor,        GMP_RATS_mpq_struct left_neighbor, right_neighbor,
663                            left_diff, right_diff,                            left_diff, right_diff,
664                            left_abs, right_abs;                            left_abs, right_abs;
665        int error_cmp;        int error_cmp;
666        int mag_cmp;        int mag_cmp;
667    
668        GMP_RATS_mpq_init(&left_neighbor);        GMP_RATS_mpq_init(&left_neighbor);
669        GMP_RATS_mpq_init(&right_neighbor);        GMP_RATS_mpq_init(&right_neighbor);
670        GMP_RATS_mpq_init(&left_diff);        GMP_RATS_mpq_init(&left_diff);
671        GMP_RATS_mpq_init(&right_diff);        GMP_RATS_mpq_init(&right_diff);
672        GMP_RATS_mpq_init(&left_abs);        GMP_RATS_mpq_init(&left_abs);
673        GMP_RATS_mpq_init(&right_abs);        GMP_RATS_mpq_init(&right_abs);
674    
675        //Snatch the left neighbor.        //Snatch the left neighbor.
676        if (neighbor_data.n_left_out)        if (neighbor_data.n_left_out)
677           {           {
678           GMP_RATS_mpq_copy(&left_neighbor, &(neighbor_data.lefts[0].neighbor));           GMP_RATS_mpq_copy(&left_neighbor, &(neighbor_data.lefts[0].neighbor));
679           }           }
680    
681        //Snatch the right neighbor.        //Snatch the right neighbor.
682        if (neighbor_data.n_right_out)        if (neighbor_data.n_right_out)
683           {           {
684           GMP_RATS_mpq_copy(&right_neighbor, &(neighbor_data.rights[0].neighbor));           GMP_RATS_mpq_copy(&right_neighbor, &(neighbor_data.rights[0].neighbor));
685           }           }
686    
687        //Calculate the differences, take their absolute        //Calculate the differences, take their absolute
688        //values.        //values.
689        GMP_RATS_mpq_sub(&left_diff,  &left_neighbor,  &(neighbor_data.rn_in));        GMP_RATS_mpq_sub(&left_diff,  &left_neighbor,  &(neighbor_data.rn_in));
690        GMP_RATS_mpq_sub(&right_diff, &right_neighbor, &(neighbor_data.rn_in));        GMP_RATS_mpq_sub(&right_diff, &right_neighbor, &(neighbor_data.rn_in));
691        GMP_RATS_mpq_normalize(&left_diff);        GMP_RATS_mpq_normalize(&left_diff);
692        GMP_RATS_mpq_normalize(&right_diff);        GMP_RATS_mpq_normalize(&right_diff);
693        GMP_INTS_mpz_abs(&(left_diff.num));        GMP_INTS_mpz_abs(&(left_diff.num));
694        GMP_INTS_mpz_abs(&(right_diff.num));        GMP_INTS_mpz_abs(&(right_diff.num));
695    
696        //Now that the differences are calculated, take the        //Now that the differences are calculated, take the
697        //absolute values of the neighbors themselves.        //absolute values of the neighbors themselves.
698        //We will use this to break ties.        //We will use this to break ties.
699        GMP_RATS_mpq_normalize(&left_neighbor);        GMP_RATS_mpq_normalize(&left_neighbor);
700        GMP_RATS_mpq_normalize(&right_neighbor);        GMP_RATS_mpq_normalize(&right_neighbor);
701        GMP_INTS_mpz_abs(&(left_neighbor.num));        GMP_INTS_mpz_abs(&(left_neighbor.num));
702        GMP_INTS_mpz_abs(&(right_neighbor.num));        GMP_INTS_mpz_abs(&(right_neighbor.num));
703    
704        //Compare the relative differences and magnitudes.        //Compare the relative differences and magnitudes.
705        error_cmp = GMP_RATS_mpq_cmp(&left_diff, &right_diff, NULL);        error_cmp = GMP_RATS_mpq_cmp(&left_diff, &right_diff, NULL);
706        mag_cmp   = GMP_RATS_mpq_cmp(&left_neighbor, &right_neighbor, NULL);        mag_cmp   = GMP_RATS_mpq_cmp(&left_neighbor, &right_neighbor, NULL);
707    
708        //Figure out which to present as the best approximation and        //Figure out which to present as the best approximation and
709        //do it.        //do it.
710        if (!(parblock->neversmaller_specified) &&        if (!(parblock->neversmaller_specified) &&
711           ((parblock->neverlarger_specified) || (error_cmp < 0) || ((error_cmp == 0) && (mag_cmp < 0))))           ((parblock->neverlarger_specified) || (error_cmp < 0) || ((error_cmp == 0) && (mag_cmp < 0))))
712           {           {
713           CMAIN_print_app_in_std_form(stdout,           CMAIN_print_app_in_std_form(stdout,
714                                       -1,                                       -1,
715                                       &(neighbor_data.rn_in),                                       &(neighbor_data.rn_in),
716                                       &(neighbor_data.lefts[0].neighbor),                                       &(neighbor_data.lefts[0].neighbor),
717                                       parblock->argblock.noformat,                                       parblock->argblock.noformat,
718                                       1,                                       1,
719                                       1,                                       1,
720                                       &dap_denominator);                                       &dap_denominator);
721           }           }
722        else        else
723           {           {
724           CMAIN_print_app_in_std_form(stdout,           CMAIN_print_app_in_std_form(stdout,
725                                       1,                                       1,
726                                       &(neighbor_data.rn_in),                                       &(neighbor_data.rn_in),
727                                       &(neighbor_data.rights[0].neighbor),                                       &(neighbor_data.rights[0].neighbor),
728                                       parblock->argblock.noformat,                                       parblock->argblock.noformat,
729                                       1,                                       1,
730                                       1,                                       1,
731                                       &dap_denominator);                                       &dap_denominator);
732           }           }
733    
734        //Deallocate.        //Deallocate.
735        GMP_RATS_mpq_clear(&left_neighbor);        GMP_RATS_mpq_clear(&left_neighbor);
736        GMP_RATS_mpq_clear(&right_neighbor);        GMP_RATS_mpq_clear(&right_neighbor);
737        GMP_RATS_mpq_clear(&left_diff);        GMP_RATS_mpq_clear(&left_diff);
738        GMP_RATS_mpq_clear(&right_diff);        GMP_RATS_mpq_clear(&right_diff);
739        GMP_RATS_mpq_clear(&left_abs);        GMP_RATS_mpq_clear(&left_abs);
740        GMP_RATS_mpq_clear(&right_abs);        GMP_RATS_mpq_clear(&right_abs);
741        }        }
742    
743     //Deallocate all dynamic memory.     //Deallocate all dynamic memory.
744     GMP_RALG_consecutive_fab_terms_result_free(&neighbor_data);     GMP_RALG_consecutive_fab_terms_result_free(&neighbor_data);
745     GMP_RATS_mpq_clear(&hmax_over_one);     GMP_RATS_mpq_clear(&hmax_over_one);
746     GMP_RATS_mpq_clear(&hmax_over_kmax);     GMP_RATS_mpq_clear(&hmax_over_kmax);
747     GMP_INTS_mpz_clear(&dap_denominator);     GMP_INTS_mpz_clear(&dap_denominator);
748     GMP_RATS_mpq_clear(&rn_in_abs);     GMP_RATS_mpq_clear(&rn_in_abs);
749    
750     return(rv);     return(rv);
751     }     }
752    
753    
754  //Handles the case of finding multiple neighbors.  //Handles the case of finding multiple neighbors.
755    
756  static int CMAIN_multiple_neighbor(struct CfbrapabCmainStruct *parblock)  static int CMAIN_multiple_neighbor(struct CfbrapabCmainStruct *parblock)
757     {     {
758     int rv = 0;     int rv = 0;
759     GMP_RATS_mpq_struct hmax_over_one, hmax_over_kmax, rn_in_abs;     GMP_RATS_mpq_struct hmax_over_one, hmax_over_kmax, rn_in_abs;
760     GMP_INTS_mpz_struct dap_denominator;     GMP_INTS_mpz_struct dap_denominator;
761     GMP_RALG_cf_app_struct cf_decomp;     GMP_RALG_cf_app_struct cf_decomp;
762     GMP_RALG_fab_neighbor_collection_struct neighbor_data;     GMP_RALG_fab_neighbor_collection_struct neighbor_data;
763     int error_flag;     int error_flag;
764     int i;     int i;
765    
766     //Allocate all dynamic memory.     //Allocate all dynamic memory.
767     GMP_RATS_mpq_init(&hmax_over_one);     GMP_RATS_mpq_init(&hmax_over_one);
768     GMP_RATS_mpq_init(&hmax_over_kmax);     GMP_RATS_mpq_init(&hmax_over_kmax);
769     GMP_INTS_mpz_init(&dap_denominator);     GMP_INTS_mpz_init(&dap_denominator);
770     GMP_RATS_mpq_init(&rn_in_abs);     GMP_RATS_mpq_init(&rn_in_abs);
771    
772     //Set the DAP denominator to 1e108.     //Set the DAP denominator to 1e108.
773     GMP_INTS_mpz_set_general_int(&dap_denominator,     GMP_INTS_mpz_set_general_int(&dap_denominator,
774                                  &error_flag,                                  &error_flag,
775                                  "1e108");                                  "1e108");
776    
777     //By convention, we will not mess with anything with an     //By convention, we will not mess with anything with an
778     //absolute value greater than HMAX/1.  If such a condition exists, puke out.     //absolute value greater than HMAX/1.  If such a condition exists, puke out.
779     //Form up the value of HMAX/1 if HMAX was specified.     //Form up the value of HMAX/1 if HMAX was specified.
780     if (parblock->hmax_specified)     if (parblock->hmax_specified)
781        {        {
782        GMP_INTS_mpz_copy(&(hmax_over_one.num), &(parblock->hmax));        GMP_INTS_mpz_copy(&(hmax_over_one.num), &(parblock->hmax));
783        GMP_INTS_mpz_set_ui(&(hmax_over_one.den), 1);        GMP_INTS_mpz_set_ui(&(hmax_over_one.den), 1);
784        GMP_RATS_mpq_copy(&rn_in_abs, &(parblock->rn));        GMP_RATS_mpq_copy(&rn_in_abs, &(parblock->rn));
785        GMP_INTS_mpz_abs(&(rn_in_abs.num));        GMP_INTS_mpz_abs(&(rn_in_abs.num));
786        if (GMP_RATS_mpq_cmp(&(rn_in_abs), &hmax_over_one, NULL) > 0)        if (GMP_RATS_mpq_cmp(&(rn_in_abs), &hmax_over_one, NULL) > 0)
787           {           {
788           printf("The magnitude of the number supplied exceeds HMAX/1, and hence the number\n"           printf("The magnitude of the number supplied exceeds HMAX/1, and hence the number\n"
789                  "has no neighbors in the series of interest.  Calculation cannot continue.\n");                  "has no neighbors in the series of interest.  Calculation cannot continue.\n");
790           exit(4);           exit(4);
791           }           }
792        }        }
793    
794     //If the "verbose" option is specified, we want to give the continued fraction     //If the "verbose" option is specified, we want to give the continued fraction
795     //partial quotients and convergents of either the number to approximate,     //partial quotients and convergents of either the number to approximate,
796     //its reciprocal, or none of the above, as appropriate; and give a bit more     //its reciprocal, or none of the above, as appropriate; and give a bit more
797     //information, in addition.     //information, in addition.
798     if (parblock->argblock.verbose)     if (parblock->argblock.verbose)
799        {        {
800        if (parblock->hmax_specified)        if (parblock->hmax_specified)
801           {           {
802           //Stuff HMAX/KMAX.  This is necessary for comparison.           //Stuff HMAX/KMAX.  This is necessary for comparison.
803           GMP_INTS_mpz_copy(&(hmax_over_kmax.num), &(parblock->hmax));           GMP_INTS_mpz_copy(&(hmax_over_kmax.num), &(parblock->hmax));
804           GMP_INTS_mpz_copy(&(hmax_over_kmax.den), &(parblock->kmax));           GMP_INTS_mpz_copy(&(hmax_over_kmax.den), &(parblock->kmax));
805           }           }
806    
807        if (!(parblock->hmax_specified) || (GMP_RATS_mpq_cmp(&(parblock->rn), &hmax_over_kmax, NULL) < 0))        if (!(parblock->hmax_specified) || (GMP_RATS_mpq_cmp(&(parblock->rn), &hmax_over_kmax, NULL) < 0))
808           {           {
809           //Either HMAX was not specified or else we are below the corner point on the           //Either HMAX was not specified or else we are below the corner point on the
810           //integer lattice.  Get the continued fraction representation of the number           //integer lattice.  Get the continued fraction representation of the number
811           //rather than its reciprocal.           //rather than its reciprocal.
812           GMP_RALG_cfdecomp_init(&cf_decomp, &error_flag, &(rn_in_abs.num), &(rn_in_abs.den));           GMP_RALG_cfdecomp_init(&cf_decomp, &error_flag, &(rn_in_abs.num), &(rn_in_abs.den));
813    
814           //Print out the continued fraction decomposition of the rational number.           //Print out the continued fraction decomposition of the rational number.
815           GMP_RALG_cfdecomp_emit(stdout,           GMP_RALG_cfdecomp_emit(stdout,
816                                  "CF Representation Of Absolute Value Of Rational Number Specified",                                  "CF Representation Of Absolute Value Of Rational Number Specified",
817                                  &cf_decomp,                                  &cf_decomp,
818                                  0,                                  0,
819                                  1,                                  1,
820                                  &dap_denominator);                                  &dap_denominator);
821    
822           //Destroy the decomposition--free the memory.           //Destroy the decomposition--free the memory.
823           GMP_RALG_cfdecomp_destroy(&cf_decomp);           GMP_RALG_cfdecomp_destroy(&cf_decomp);
824           }           }
825        else if (GMP_RATS_mpq_cmp(&(rn_in_abs), &hmax_over_kmax, NULL) == 0)        else if (GMP_RATS_mpq_cmp(&(rn_in_abs), &hmax_over_kmax, NULL) == 0)
826           {           {
827           //In this case, the rational number specified is exactly the same in           //In this case, the rational number specified is exactly the same in
828           //magnitude as HMAX/KMAX.  I am inclined to suppress the CF decomp.           //magnitude as HMAX/KMAX.  I am inclined to suppress the CF decomp.
829           printf("Rational number specified is HMAX/KMAX.  CF decomp not provided.\n");           printf("Rational number specified is HMAX/KMAX.  CF decomp not provided.\n");
830           }           }
831        else        else
832           {           {
833           //The number specified is beyond the corner point.  It is appropriate to           //The number specified is beyond the corner point.  It is appropriate to
834           //provide the decomposition of the reciprocal rather than of the number           //provide the decomposition of the reciprocal rather than of the number
835           //itself.           //itself.
836           GMP_RALG_cfdecomp_init(&cf_decomp, &error_flag, &(rn_in_abs.den), &(rn_in_abs.num));           GMP_RALG_cfdecomp_init(&cf_decomp, &error_flag, &(rn_in_abs.den), &(rn_in_abs.num));
837    
838           //Print out the continued fraction decomposition of the rational number.           //Print out the continued fraction decomposition of the rational number.
839           GMP_RALG_cfdecomp_emit(stdout,           GMP_RALG_cfdecomp_emit(stdout,
840                                  "CF Representation Of Reciprocal Of Absolute Value Of Rational Number Specified",                                  "CF Representation Of Reciprocal Of Absolute Value Of Rational Number Specified",
841                                  &cf_decomp,                                  &cf_decomp,
842                                  0,                                  0,
843                                  1,                                  1,
844                                  &dap_denominator);                                  &dap_denominator);
845    
846           //Destroy the decomposition--free the memory.           //Destroy the decomposition--free the memory.
847           GMP_RALG_cfdecomp_destroy(&cf_decomp);           GMP_RALG_cfdecomp_destroy(&cf_decomp);
848           }           }
849        } //End if verbose.        } //End if verbose.
850    
851     //Do all the work to get the neighbors of the number passed.     //Do all the work to get the neighbors of the number passed.
852     GMP_RALG_consecutive_fab_terms(     GMP_RALG_consecutive_fab_terms(
853             &(parblock->rn),             &(parblock->rn),
854             &(parblock->kmax),             &(parblock->kmax),
855             (parblock->hmax_specified) ? (&(parblock->hmax)) : (NULL),             (parblock->hmax_specified) ? (&(parblock->hmax)) : (NULL),
856             parblock->n,             parblock->n,
857             parblock->n,             parblock->n,
858             &neighbor_data);             &neighbor_data);
859    
860     //Print the neighbor data block for debugging.     //Print the neighbor data block for debugging.
861     #if 0     #if 0
862     GMP_RALG_consecutive_fab_terms_result_dump(stdout, &neighbor_data);     GMP_RALG_consecutive_fab_terms_result_dump(stdout, &neighbor_data);
863     #endif     #endif
864    
865     //Loop through, printing out the left neighbors in order.     //Loop through, printing out the left neighbors in order.
866     for (i = neighbor_data.n_left_out - 1; i >= 0; i--)     for (i = neighbor_data.n_left_out - 1; i >= 0; i--)
867        {        {
868        CMAIN_print_app_in_std_form(stdout,        CMAIN_print_app_in_std_form(stdout,
869                                    -(i + 1),                                    -(i + 1),
870                                    &(neighbor_data.rn_in),                                    &(neighbor_data.rn_in),
871                                    &(neighbor_data.lefts[i].neighbor),                                    &(neighbor_data.lefts[i].neighbor),
872                                    parblock->argblock.noformat,                                    parblock->argblock.noformat,
873                                    1,                                    1,
874                                    1,                                    1,
875                                    &dap_denominator);                                    &dap_denominator);
876        }        }
877    
878     //If the number itself appears in the series of interest, spit that out.     //If the number itself appears in the series of interest, spit that out.
879     if (neighbor_data.equality)     if (neighbor_data.equality)
880        {        {
881        CMAIN_print_app_in_std_form(stdout,        CMAIN_print_app_in_std_form(stdout,
882                                    0,                                    0,
883                                    &(neighbor_data.rn_in),                                    &(neighbor_data.rn_in),
884                                    &(neighbor_data.norm_rn),                                    &(neighbor_data.norm_rn),
885                                    parblock->argblock.noformat,                                    parblock->argblock.noformat,
886                                    1,                                    1,
887                                    1,                                    1,
888                                    &dap_denominator);                                    &dap_denominator);
889        }        }
890    
891     //Loop through, printing out the right neighbors in order.     //Loop through, printing out the right neighbors in order.
892     for (i = 0; i < neighbor_data.n_right_out; i++)     for (i = 0; i < neighbor_data.n_right_out; i++)
893        {        {
894        CMAIN_print_app_in_std_form(stdout,        CMAIN_print_app_in_std_form(stdout,
895                                    i+1,                                    i+1,
896                                    &(neighbor_data.rn_in),                                    &(neighbor_data.rn_in),
897                                    &(neighbor_data.rights[i].neighbor),                                    &(neighbor_data.rights[i].neighbor),
898                                    parblock->argblock.noformat,                                    parblock->argblock.noformat,
899                                    1,                                    1,
900                                    1,                                    1,
901                                    &dap_denominator);                                    &dap_denominator);
902        }        }
903    
904     //Deallocate all dynamic memory.     //Deallocate all dynamic memory.
905     GMP_RALG_consecutive_fab_terms_result_free(&neighbor_data);     GMP_RALG_consecutive_fab_terms_result_free(&neighbor_data);
906     GMP_RATS_mpq_clear(&hmax_over_one);     GMP_RATS_mpq_clear(&hmax_over_one);
907     GMP_RATS_mpq_clear(&hmax_over_kmax);     GMP_RATS_mpq_clear(&hmax_over_kmax);
908     GMP_INTS_mpz_clear(&dap_denominator);     GMP_INTS_mpz_clear(&dap_denominator);
909     GMP_RATS_mpq_clear(&rn_in_abs);     GMP_RATS_mpq_clear(&rn_in_abs);
910    
911     return(rv);     return(rv);
912     }     }
913    
914    
915  //Handles the case of finding the predecessor.  //Handles the case of finding the predecessor.
916  int CMAIN_predecessor(struct CfbrapabCmainStruct *parblock)  int CMAIN_predecessor(struct CfbrapabCmainStruct *parblock)
917     {     {
918     int rv = 0;     int rv = 0;
919     GMP_RATS_mpq_struct hmax_over_one, hmax_over_kmax, rn_in_abs;     GMP_RATS_mpq_struct hmax_over_one, hmax_over_kmax, rn_in_abs;
920     GMP_INTS_mpz_struct dap_denominator;     GMP_INTS_mpz_struct dap_denominator;
921     GMP_RALG_cf_app_struct cf_decomp;     GMP_RALG_cf_app_struct cf_decomp;
922     GMP_RALG_fab_neighbor_collection_struct neighbor_data;     GMP_RALG_fab_neighbor_collection_struct neighbor_data;
923     int error_flag;     int error_flag;
924    
925     //Allocate all dynamic memory.     //Allocate all dynamic memory.
926     GMP_RATS_mpq_init(&hmax_over_one);     GMP_RATS_mpq_init(&hmax_over_one);
927     GMP_RATS_mpq_init(&hmax_over_kmax);     GMP_RATS_mpq_init(&hmax_over_kmax);
928     GMP_INTS_mpz_init(&dap_denominator);     GMP_INTS_mpz_init(&dap_denominator);
929     GMP_RATS_mpq_init(&rn_in_abs);     GMP_RATS_mpq_init(&rn_in_abs);
930    
931     //Set the DAP denominator to 1e108.     //Set the DAP denominator to 1e108.
932     GMP_INTS_mpz_set_general_int(&dap_denominator,     GMP_INTS_mpz_set_general_int(&dap_denominator,
933                                  &error_flag,                                  &error_flag,
934                                  "1e108");                                  "1e108");
935    
936     //By convention, we will not mess with anything with an     //By convention, we will not mess with anything with an
937     //absolute value greater than HMAX/1.  If such a condition exists, puke out.     //absolute value greater than HMAX/1.  If such a condition exists, puke out.
938     //Form up the value of HMAX/1 if HMAX was specified.     //Form up the value of HMAX/1 if HMAX was specified.
939     if (parblock->hmax_specified)     if (parblock->hmax_specified)
940        {        {
941        GMP_INTS_mpz_copy(&(hmax_over_one.num), &(parblock->hmax));        GMP_INTS_mpz_copy(&(hmax_over_one.num), &(parblock->hmax));
942        GMP_INTS_mpz_set_ui(&(hmax_over_one.den), 1);        GMP_INTS_mpz_set_ui(&(hmax_over_one.den), 1);
943        GMP_RATS_mpq_copy(&rn_in_abs, &(parblock->rn));        GMP_RATS_mpq_copy(&rn_in_abs, &(parblock->rn));
944        GMP_INTS_mpz_abs(&(rn_in_abs.num));        GMP_INTS_mpz_abs(&(rn_in_abs.num));
945        if (GMP_RATS_mpq_cmp(&(rn_in_abs), &hmax_over_one, NULL) > 0)        if (GMP_RATS_mpq_cmp(&(rn_in_abs), &hmax_over_one, NULL) > 0)
946           {           {
947           printf("The magnitude of the number supplied exceeds HMAX/1, and hence the number\n"           printf("The magnitude of the number supplied exceeds HMAX/1, and hence the number\n"
948                  "has no neighbors in the series of interest.  Calculation cannot continue.\n");                  "has no neighbors in the series of interest.  Calculation cannot continue.\n");
949           exit(4);           exit(4);
950           }           }
951        }        }
952    
953     //If the "verbose" option is specified, we want to give the continued fraction     //If the "verbose" option is specified, we want to give the continued fraction
954     //partial quotients and convergents of either the number to approximate,     //partial quotients and convergents of either the number to approximate,
955     //its reciprocal, or none of the above, as appropriate; and give a bit more     //its reciprocal, or none of the above, as appropriate; and give a bit more
956     //information, in addition.     //information, in addition.
957     if (parblock->argblock.verbose)     if (parblock->argblock.verbose)
958        {        {
959        if (parblock->hmax_specified)        if (parblock->hmax_specified)
960           {           {
961           //Stuff HMAX/KMAX.  This is necessary for comparison.           //Stuff HMAX/KMAX.  This is necessary for comparison.
962           GMP_INTS_mpz_copy(&(hmax_over_kmax.num), &(parblock->hmax));           GMP_INTS_mpz_copy(&(hmax_over_kmax.num), &(parblock->hmax));
963           GMP_INTS_mpz_copy(&(hmax_over_kmax.den), &(parblock->kmax));           GMP_INTS_mpz_copy(&(hmax_over_kmax.den), &(parblock->kmax));
964           }           }
965    
966        if (!(parblock->hmax_specified) || (GMP_RATS_mpq_cmp(&(parblock->rn), &hmax_over_kmax, NULL) < 0))        if (!(parblock->hmax_specified) || (GMP_RATS_mpq_cmp(&(parblock->rn), &hmax_over_kmax, NULL) < 0))
967           {           {
968           //Either HMAX was not specified or else we are below the corner point on the           //Either HMAX was not specified or else we are below the corner point on the
969           //integer lattice.  Get the continued fraction representation of the number           //integer lattice.  Get the continued fraction representation of the number
970           //rather than its reciprocal.           //rather than its reciprocal.
971           GMP_RALG_cfdecomp_init(&cf_decomp, &error_flag, &(rn_in_abs.num), &(rn_in_abs.den));           GMP_RALG_cfdecomp_init(&cf_decomp, &error_flag, &(rn_in_abs.num), &(rn_in_abs.den));
972    
973           //Print out the continued fraction decomposition of the rational number.           //Print out the continued fraction decomposition of the rational number.
974           GMP_RALG_cfdecomp_emit(stdout,           GMP_RALG_cfdecomp_emit(stdout,
975                                  "CF Representation Of Absolute Value Of Rational Number Specified",                                  "CF Representation Of Absolute Value Of Rational Number Specified",
976                                  &cf_decomp,                                  &cf_decomp,
977                                  0,                                  0,
978                                  1,                                  1,
979                                  &dap_denominator);                                  &dap_denominator);
980    
981           //Destroy the decomposition--free the memory.           //Destroy the decomposition--free the memory.
982           GMP_RALG_cfdecomp_destroy(&cf_decomp);           GMP_RALG_cfdecomp_destroy(&cf_decomp);
983           }           }
984        else if (GMP_RATS_mpq_cmp(&(rn_in_abs), &hmax_over_kmax, NULL) == 0)        else if (GMP_RATS_mpq_cmp(&(rn_in_abs), &hmax_over_kmax, NULL) == 0)
985           {           {
986           //In this case, the rational number specified is exactly the same in           //In this case, the rational number specified is exactly the same in
987           //magnitude as HMAX/KMAX.  I am inclined to suppress the CF decomp.           //magnitude as HMAX/KMAX.  I am inclined to suppress the CF decomp.
988           printf("Rational number specified is HMAX/KMAX.  CF decomp not provided.\n");           printf("Rational number specified is HMAX/KMAX.  CF decomp not provided.\n");
989           }           }
990        else        else
991           {           {
992           //The number specified is beyond the corner point.  It is appropriate to           //The number specified is beyond the corner point.  It is appropriate to
993           //provide the decomposition of the reciprocal rather than of the number           //provide the decomposition of the reciprocal rather than of the number
994           //itself.           //itself.
995           GMP_RALG_cfdecomp_init(&cf_decomp, &error_flag, &(rn_in_abs.den), &(rn_in_abs.num));           GMP_RALG_cfdecomp_init(&cf_decomp, &error_flag, &(rn_in_abs.den), &(rn_in_abs.num));
996    
997           //Print out the continued fraction decomposition of the rational number.           //Print out the continued fraction decomposition of the rational number.
998           GMP_RALG_cfdecomp_emit(stdout,           GMP_RALG_cfdecomp_emit(stdout,
999                                  "CF Representation Of Reciprocal Of Absolute Value Of Rational Number Specified",                                  "CF Representation Of Reciprocal Of Absolute Value Of Rational Number Specified",
1000                                  &cf_decomp,                                  &cf_decomp,
1001                                  0,                                  0,
1002                                  1,                                  1,
1003                                  &dap_denominator);                                  &dap_denominator);
1004    
1005           //Destroy the decomposition--free the memory.           //Destroy the decomposition--free the memory.
1006           GMP_RALG_cfdecomp_destroy(&cf_decomp);           GMP_RALG_cfdecomp_destroy(&cf_decomp);
1007           }           }
1008        } //End if verbose.        } //End if verbose.
1009    
1010     //Do all the work to get the neighbors of the number passed.     //Do all the work to get the neighbors of the number passed.
1011     GMP_RALG_consecutive_fab_terms(     GMP_RALG_consecutive_fab_terms(
1012             &(parblock->rn),             &(parblock->rn),
1013             &(parblock->kmax),             &(parblock->kmax),
1014             (parblock->hmax_specified) ? (&(parblock->hmax)) : (NULL),             (parblock->hmax_specified) ? (&(parblock->hmax)) : (NULL),
1015             1,             1,
1016             0,             0,
1017             &neighbor_data);             &neighbor_data);
1018    
1019     //Print the neighbor data block for debugging.     //Print the neighbor data block for debugging.
1020     #if 0     #if 0
1021     GMP_RALG_consecutive_fab_terms_result_dump(stdout, &neighbor_data);     GMP_RALG_consecutive_fab_terms_result_dump(stdout, &neighbor_data);
1022     #endif     #endif
1023    
1024     //Print the neighbor on the left, if it exists.     //Print the neighbor on the left, if it exists.
1025     if (neighbor_data.n_left_out)     if (neighbor_data.n_left_out)
1026        {        {
1027        CMAIN_print_app_in_std_form(stdout,        CMAIN_print_app_in_std_form(stdout,
1028                                    -1,                                    -1,
1029                                    &(neighbor_data.rn_in),                                    &(neighbor_data.rn_in),
1030                                    &(neighbor_data.lefts[0].neighbor),                                    &(neighbor_data.lefts[0].neighbor),
1031                                    parblock->argblock.noformat,                                    parblock->argblock.noformat,
1032                                    0,                                    0,
1033                                    0,                                    0,
1034                                    &dap_denominator);                                    &dap_denominator);
1035        }        }
1036    
1037     //Deallocate all dynamic memory.     //Deallocate all dynamic memory.
1038     GMP_RALG_consecutive_fab_terms_result_free(&neighbor_data);     GMP_RALG_consecutive_fab_terms_result_free(&neighbor_data);
1039     GMP_RATS_mpq_clear(&hmax_over_one);     GMP_RATS_mpq_clear(&hmax_over_one);
1040     GMP_RATS_mpq_clear(&hmax_over_kmax);     GMP_RATS_mpq_clear(&hmax_over_kmax);
1041     GMP_INTS_mpz_clear(&dap_denominator);     GMP_INTS_mpz_clear(&dap_denominator);
1042     GMP_RATS_mpq_clear(&rn_in_abs);     GMP_RATS_mpq_clear(&rn_in_abs);
1043    
1044     return(rv);     return(rv);
1045     }     }
1046    
1047    
1048  //Handles the case of finding the successor.  //Handles the case of finding the successor.
1049  int CMAIN_successor(struct CfbrapabCmainStruct *parblock)  int CMAIN_successor(struct CfbrapabCmainStruct *parblock)
1050     {     {
1051     int rv = 0;     int rv = 0;
1052     GMP_RATS_mpq_struct hmax_over_one, hmax_over_kmax, rn_in_abs;     GMP_RATS_mpq_struct hmax_over_one, hmax_over_kmax, rn_in_abs;
1053     GMP_INTS_mpz_struct dap_denominator;     GMP_INTS_mpz_struct dap_denominator;
1054     GMP_RALG_cf_app_struct cf_decomp;     GMP_RALG_cf_app_struct cf_decomp;
1055     GMP_RALG_fab_neighbor_collection_struct neighbor_data;     GMP_RALG_fab_neighbor_collection_struct neighbor_data;
1056     int error_flag;     int error_flag;
1057    
1058     //Allocate all dynamic memory.     //Allocate all dynamic memory.
1059     GMP_RATS_mpq_init(&hmax_over_one);     GMP_RATS_mpq_init(&hmax_over_one);
1060     GMP_RATS_mpq_init(&hmax_over_kmax);     GMP_RATS_mpq_init(&hmax_over_kmax);
1061     GMP_INTS_mpz_init(&dap_denominator);     GMP_INTS_mpz_init(&dap_denominator);
1062     GMP_RATS_mpq_init(&rn_in_abs);     GMP_RATS_mpq_init(&rn_in_abs);
1063    
1064     //Set the DAP denominator to 1e108.     //Set the DAP denominator to 1e108.
1065     GMP_INTS_mpz_set_general_int(&dap_denominator,     GMP_INTS_mpz_set_general_int(&dap_denominator,
1066                                  &error_flag,                                  &error_flag,
1067                                  "1e108");                                  "1e108");
1068    
1069     //By convention, we will not mess with anything with an     //By convention, we will not mess with anything with an
1070     //absolute value greater than HMAX/1.  If such a condition exists, puke out.     //absolute value greater than HMAX/1.  If such a condition exists, puke out.
1071     //Form up the value of HMAX/1 if HMAX was specified.     //Form up the value of HMAX/1 if HMAX was specified.
1072     if (parblock->hmax_specified)     if (parblock->hmax_specified)
1073        {        {
1074        GMP_INTS_mpz_copy(&(hmax_over_one.num), &(parblock->hmax));        GMP_INTS_mpz_copy(&(hmax_over_one.num), &(parblock->hmax));
1075        GMP_INTS_mpz_set_ui(&(hmax_over_one.den), 1);        GMP_INTS_mpz_set_ui(&(hmax_over_one.den), 1);
1076        GMP_RATS_mpq_copy(&rn_in_abs, &(parblock->rn));        GMP_RATS_mpq_copy(&rn_in_abs, &(parblock->rn));
1077        GMP_INTS_mpz_abs(&(rn_in_abs.num));        GMP_INTS_mpz_abs(&(rn_in_abs.num));
1078        if (GMP_RATS_mpq_cmp(&(rn_in_abs), &hmax_over_one, NULL) > 0)        if (GMP_RATS_mpq_cmp(&(rn_in_abs), &hmax_over_one, NULL) > 0)
1079           {           {
1080           printf("The magnitude of the number supplied exceeds HMAX/1, and hence the number\n"           printf("The magnitude of the number supplied exceeds HMAX/1, and hence the number\n"
1081                  "has no neighbors in the series of interest.  Calculation cannot continue.\n");                  "has no neighbors in the series of interest.  Calculation cannot continue.\n");
1082           exit(4);           exit(4);
1083           }           }
1084        }        }
1085    
1086     //If the "verbose" option is specified, we want to give the continued fraction     //If the "verbose" option is specified, we want to give the continued fraction
1087     //partial quotients and convergents of either the number to approximate,     //partial quotients and convergents of either the number to approximate,
1088     //its reciprocal, or none of the above, as appropriate; and give a bit more     //its reciprocal, or none of the above, as appropriate; and give a bit more
1089     //information, in addition.     //information, in addition.
1090     if (parblock->argblock.verbose)     if (parblock->argblock.verbose)
1091        {        {
1092        if (parblock->hmax_specified)        if (parblock->hmax_specified)
1093           {           {
1094           //Stuff HMAX/KMAX.  This is necessary for comparison.           //Stuff HMAX/KMAX.  This is necessary for comparison.
1095           GMP_INTS_mpz_copy(&(hmax_over_kmax.num), &(parblock->hmax));           GMP_INTS_mpz_copy(&(hmax_over_kmax.num), &(parblock->hmax));
1096           GMP_INTS_mpz_copy(&(hmax_over_kmax.den), &(parblock->kmax));           GMP_INTS_mpz_copy(&(hmax_over_kmax.den), &(parblock->kmax));
1097           }           }
1098    
1099        if (!(parblock->hmax_specified) || (GMP_RATS_mpq_cmp(&(parblock->rn), &hmax_over_kmax, NULL) < 0))        if (!(parblock->hmax_specified) || (GMP_RATS_mpq_cmp(&(parblock->rn), &hmax_over_kmax, NULL) < 0))
1100           {           {
1101           //Either HMAX was not specified or else we are below the corner point on the           //Either HMAX was not specified or else we are below the corner point on the
1102           //integer lattice.  Get the continued fraction representation of the number           //integer lattice.  Get the continued fraction representation of the number
1103           //rather than its reciprocal.           //rather than its reciprocal.
1104           GMP_RALG_cfdecomp_init(&cf_decomp, &error_flag, &(rn_in_abs.num), &(rn_in_abs.den));           GMP_RALG_cfdecomp_init(&cf_decomp, &error_flag, &(rn_in_abs.num), &(rn_in_abs.den));
1105    
1106           //Print out the continued fraction decomposition of the rational number.           //Print out the continued fraction decomposition of the rational number.
1107           GMP_RALG_cfdecomp_emit(stdout,           GMP_RALG_cfdecomp_emit(stdout,
1108                                  "CF Representation Of Absolute Value Of Rational Number Specified",                                  "CF Representation Of Absolute Value Of Rational Number Specified",
1109                                  &cf_decomp,                                  &cf_decomp,
1110                                  0,                                  0,
1111                                  1,                                  1,
1112                                  &dap_denominator);                                  &dap_denominator);
1113    
1114           //Destroy the decomposition--free the memory.           //Destroy the decomposition--free the memory.
1115           GMP_RALG_cfdecomp_destroy(&cf_decomp);           GMP_RALG_cfdecomp_destroy(&cf_decomp);
1116           }           }
1117        else if (GMP_RATS_mpq_cmp(&(rn_in_abs), &hmax_over_kmax, NULL) == 0)        else if (GMP_RATS_mpq_cmp(&(rn_in_abs), &hmax_over_kmax, NULL) == 0)
1118           {           {
1119           //In this case, the rational number specified is exactly the same in           //In this case, the rational number specified is exactly the same in
1120           //magnitude as HMAX/KMAX.  I am inclined to suppress the CF decomp.           //magnitude as HMAX/KMAX.  I am inclined to suppress the CF decomp.
1121           printf("Rational number specified is HMAX/KMAX.  CF decomp not provided.\n");           printf("Rational number specified is HMAX/KMAX.  CF decomp not provided.\n");
1122           }           }
1123        else        else
1124           {           {
1125           //The number specified is beyond the corner point.  It is appropriate to           //The number specified is beyond the corner point.  It is appropriate to
1126           //provide the decomposition of the reciprocal rather than of the number           //provide the decomposition of the reciprocal rather than of the number
1127           //itself.           //itself.
1128           GMP_RALG_cfdecomp_init(&cf_decomp, &error_flag, &(rn_in_abs.den), &(rn_in_abs.num));           GMP_RALG_cfdecomp_init(&cf_decomp, &error_flag, &(rn_in_abs.den), &(rn_in_abs.num));
1129    
1130           //Print out the continued fraction decomposition of the rational number.           //Print out the continued fraction decomposition of the rational number.
1131           GMP_RALG_cfdecomp_emit(stdout,           GMP_RALG_cfdecomp_emit(stdout,
1132                                  "CF Representation Of Reciprocal Of Absolute Value Of Rational Number Specified",                                  "CF Representation Of Reciprocal Of Absolute Value Of Rational Number Specified",
1133                                  &cf_decomp,                                  &cf_decomp,
1134                                  0,                                  0,
1135                                  1,                                  1,
1136                                  &dap_denominator);                                  &dap_denominator);
1137    
1138           //Destroy the decomposition--free the memory.           //Destroy the decomposition--free the memory.
1139           GMP_RALG_cfdecomp_destroy(&cf_decomp);           GMP_RALG_cfdecomp_destroy(&cf_decomp);
1140           }           }
1141        } //End if verbose.        } //End if verbose.
1142    
1143     //Do all the work to get the neighbors of the number passed.     //Do all the work to get the neighbors of the number passed.
1144     GMP_RALG_consecutive_fab_terms(     GMP_RALG_consecutive_fab_terms(
1145             &(parblock->rn),             &(parblock->rn),
1146             &(parblock->kmax),             &(parblock->kmax),
1147             (parblock->hmax_specified) ? (&(parblock->hmax)) : (NULL),             (parblock->hmax_specified) ? (&(parblock->hmax)) : (NULL),
1148             0,             0,
1149             1,             1,
1150             &neighbor_data);             &neighbor_data);
1151    
1152     //Print the neighbor data block for debugging.     //Print the neighbor data block for debugging.
1153     #if 0     #if 0
1154     GMP_RALG_consecutive_fab_terms_result_dump(stdout, &neighbor_data);     GMP_RALG_consecutive_fab_terms_result_dump(stdout, &neighbor_data);
1155     #endif     #endif
1156    
1157     //Print the neighbor on the right, if it exists.     //Print the neighbor on the right, if it exists.
1158     if (neighbor_data.n_right_out)     if (neighbor_data.n_right_out)
1159        {        {
1160        CMAIN_print_app_in_std_form(stdout,        CMAIN_print_app_in_std_form(stdout,
1161                                    -1,                                    -1,
1162                                    &(neighbor_data.rn_in),                                    &(neighbor_data.rn_in),
1163                                    &(neighbor_data.rights[0].neighbor),                                    &(neighbor_data.rights[0].neighbor),
1164                                    parblock->argblock.noformat,                                    parblock->argblock.noformat,
1165                                    0,                                    0,
1166                                    0,                                    0,
1167                                    &dap_denominator);                                    &dap_denominator);
1168        }        }
1169    
1170     //Deallocate all dynamic memory.     //Deallocate all dynamic memory.
1171     GMP_RALG_consecutive_fab_terms_result_free(&neighbor_data);     GMP_RALG_consecutive_fab_terms_result_free(&neighbor_data);
1172     GMP_RATS_mpq_clear(&hmax_over_one);     GMP_RATS_mpq_clear(&hmax_over_one);
1173     GMP_RATS_mpq_clear(&hmax_over_kmax);     GMP_RATS_mpq_clear(&hmax_over_kmax);
1174     GMP_INTS_mpz_clear(&dap_denominator);     GMP_INTS_mpz_clear(&dap_denominator);
1175     GMP_RATS_mpq_clear(&rn_in_abs);     GMP_RATS_mpq_clear(&rn_in_abs);
1176    
1177     return(rv);     return(rv);
1178     }     }
1179    
1180    
1181  int c_main(int argc, char* argv[])  int c_main(int argc, char* argv[])
1182     {     {
1183     int rv=0;     int rv=0;
1184     struct CfbrapabCmainStruct parblock;     struct CfbrapabCmainStruct parblock;
1185    
1186     if (argc==2 && !strcmp(argv[1], "-help"))     if (argc==2 && !strcmp(argv[1], "-help"))
1187        {        {
1188        FCMIOF_hline();        FCMIOF_hline();
1189        printf("DESCRIPTION\n");        printf("DESCRIPTION\n");
1190        printf("   This utility calculates best rational approximations of the form h/k\n");        printf("   This utility calculates best rational approximations of the form h/k\n");
1191        printf("   under the constraint k <= KMAX (i.e. in the Farey series of order KMAX),\n");        printf("   under the constraint k <= KMAX (i.e. in the Farey series of order KMAX),\n");
1192        printf("   or under the constraints k <= KMAX and h <= HMAX (i.e. in a rectangular\n");        printf("   or under the constraints k <= KMAX and h <= HMAX (i.e. in a rectangular\n");
1193        printf("   region of the integer lattice).  This utility uses continued fraction\n");        printf("   region of the integer lattice).  This utility uses continued fraction\n");
1194        printf("   algorithms presented in the accompanying book \"A Practitioner's Guide\n");        printf("   algorithms presented in the accompanying book \"A Practitioner's Guide\n");
1195        printf("   ...\", and this book (a work in progress) should be consulted both as a\n");        printf("   ...\", and this book (a work in progress) should be consulted both as a\n");
1196        printf("   reference to the algorithms and a reference for this utility.  All\n");        printf("   reference to the algorithms and a reference for this utility.  All\n");
1197        printf("   rational numbers calculated are in lowest terms.  This utility will\n");        printf("   rational numbers calculated are in lowest terms.  This utility will\n");
1198        printf("   operate on negative numbers, but all results are produced by symmetry\n");        printf("   operate on negative numbers, but all results are produced by symmetry\n");
1199        printf("   (the continued fraction representation of negative numbers is NOT\n");        printf("   (the continued fraction representation of negative numbers is NOT\n");
1200        printf("   calculated).  The default operation of this utility is to calculated the\n");        printf("   calculated).  The default operation of this utility is to calculated the\n");
1201        printf("   closest rational number in the series of interest.  If the rational\n");        printf("   closest rational number in the series of interest.  If the rational\n");
1202        printf("   number supplied is equidistant between two formable rational numbers in\n");        printf("   number supplied is equidistant between two formable rational numbers in\n");
1203        printf("   the series of interest, the neighbor smaller in magnitude is returned.  If\n");        printf("   the series of interest, the neighbor smaller in magnitude is returned.  If\n");
1204        printf("   the rational number supplied is already formable, it is returned in lowest\n");        printf("   the rational number supplied is already formable, it is returned in lowest\n");
1205        printf("   terms.  If the rational number supplied does not have neighbors (i.e. it\n");        printf("   terms.  If the rational number supplied does not have neighbors (i.e. it\n");
1206        printf("   is larger than HMAX/1), an error is generated.\n");        printf("   is larger than HMAX/1), an error is generated.\n");
1207        printf("\n");        printf("\n");
1208        printf("USAGE\n");        printf("USAGE\n");
1209        printf("   cfbrapab srn urn_kmax [options]\n");        printf("   cfbrapab srn urn_kmax [options]\n");
1210        printf("   cfbrapab srn urn_kmax urn_hmax [options]\n");        printf("   cfbrapab srn urn_kmax urn_hmax [options]\n");
1211        printf("   cfbrapab -help\n");        printf("   cfbrapab -help\n");
1212        printf("\n");        printf("\n");
1213        printf("OPTIONS\n");        printf("OPTIONS\n");
1214        printf("   -neversmaller, -neverlarger\n");        printf("   -neversmaller, -neverlarger\n");
1215        printf("      The -neversmaller option will prohibit this utility from choosing a\n");        printf("      The -neversmaller option will prohibit this utility from choosing a\n");
1216        printf("      rational approximation which is smaller than the rational number\n");        printf("      rational approximation which is smaller than the rational number\n");
1217        printf("      supplied.  Thus, this option will force the utility to choose the right\n");        printf("      supplied.  Thus, this option will force the utility to choose the right\n");
1218        printf("      neighbor rather than the left, regardless of relative distance.  The\n");        printf("      neighbor rather than the left, regardless of relative distance.  The\n");
1219        printf("      behavior if the rational number supplied is formable under the \n");        printf("      behavior if the rational number supplied is formable under the \n");
1220        printf("      constraints is unchanged.  The -neverlarger option is analogous.\n");        printf("      constraints is unchanged.  The -neverlarger option is analogous.\n");
1221        printf("      These options cannot be used with -n, -pred, or -succ.\n");        printf("      These options cannot be used with -n, -pred, or -succ.\n");
1222        printf("   -pred, -succ\n");        printf("   -pred, -succ\n");
1223        printf("      Will cause the utility to find the predecessor or successor in the\n");        printf("      Will cause the utility to find the predecessor or successor in the\n");
1224        printf("      series of interest to the rational number supplied (in the event the\n");        printf("      series of interest to the rational number supplied (in the event the\n");
1225        printf("      number supplied is already formable under the constraints).  For\n");        printf("      number supplied is already formable under the constraints).  For\n");
1226        printf("      numbers not already formable under the constraints, the left or right\n");        printf("      numbers not already formable under the constraints, the left or right\n");
1227        printf("      formable neighbor will be returned.  Supplying a rational number that\n");        printf("      formable neighbor will be returned.  Supplying a rational number that\n");
1228        printf("      does not have a predecessor or successor (i.e. < 0/1 or > HMAX/1) will\n");        printf("      does not have a predecessor or successor (i.e. < 0/1 or > HMAX/1) will\n");
1229        printf("      generate an error.  These options cannot be used with -neversmaller,\n");        printf("      generate an error.  These options cannot be used with -neversmaller,\n");
1230        printf("      -neverlarger, or -n.\n");        printf("      -neverlarger, or -n.\n");
1231        CU_MSGS_std_options(stdout, PNAME);        CU_MSGS_std_options(stdout, PNAME);
1232        FCMIOF_hline();        FCMIOF_hline();
1233        CU_MSGS_toolset_info_msg(stdout, PNAME);        CU_MSGS_toolset_info_msg(stdout, PNAME);
1234        FCMIOF_hline();        FCMIOF_hline();
1235        }        }
1236     else if (argc < 3)     else if (argc < 3)
1237        {        {
1238        CU_MSGS_too_few_args_msg(stdout, PNAME);        CU_MSGS_too_few_args_msg(stdout, PNAME);
1239        rv = 4;        rv = 4;
1240        goto ret_pt;        goto ret_pt;
1241        }        }
1242     else     else
1243        {        {
1244        //In this branch, we must have an invocation of the form        //In this branch, we must have an invocation of the form
1245        //   cfbrapab SRN KMAX <options>        //   cfbrapab SRN KMAX <options>
1246        //or        //or
1247        //   cfbrapab SRN KMAX HMAX <options>        //   cfbrapab SRN KMAX HMAX <options>
1248        //        //
1249        //Call the function to collect all the command-line parameters.        //Call the function to collect all the command-line parameters.
1250        //This function takes care of error processing, as well.  If there        //This function takes care of error processing, as well.  If there
1251        //is an error of any kind, the function will simply abort and        //is an error of any kind, the function will simply abort and
1252        //supply the right return error code of 4.        //supply the right return error code of 4.
1253        process_command_line_args(&parblock,        process_command_line_args(&parblock,
1254                                   argc,                                   argc,
1255                                   argv);                                   argv);
1256    
1257        //If the debug option was set, emit the debugging information.        //If the debug option was set, emit the debugging information.
1258        if (parblock.argblock.debug)        if (parblock.argblock.debug)
1259           {           {
1260           FCMIOF_hline();           FCMIOF_hline();
1261           CU_MSGS_emit_vcinfo_from_ptr_table(stdout,C_MAIN_vcinfoptrs,PNAMEUC);           CU_MSGS_emit_vcinfo_from_ptr_table(stdout,C_MAIN_vcinfoptrs,PNAMEUC);
1262           }           }
1263    
1264        //Emit the opening horizontal line iff the -nf option isn't set.        //Emit the opening horizontal line iff the -nf option isn't set.
1265        if (!(parblock.argblock.noformat))        if (!(parblock.argblock.noformat))
1266           FCMIOF_hline();           FCMIOF_hline();
1267    
1268        //Print out a major mode message to indicate what we are trying to do.        //Print out a major mode message to indicate what we are trying to do.
1269        if (!(parblock.argblock.noformat))        if (!(parblock.argblock.noformat))
1270           {           {
1271           if (!parblock.neversmaller_specified && !parblock.neverlarger_specified && !parblock.pred_specified && !parblock.succ_specified)           if (!parblock.neversmaller_specified && !parblock.neverlarger_specified && !parblock.pred_specified && !parblock.succ_specified)
1272              {              {
1273              printf("MAJOR MODE:  Finding closest rational number(s) under the constraints.\n");              printf("MAJOR MODE:  Finding closest rational number(s) under the constraints.\n");
1274              }              }
1275           else if (parblock.neversmaller_specified)           else if (parblock.neversmaller_specified)
1276              {              {
1277              printf("MAJOR MODE:  Finding closest rational number with magnitude not smaller under\n             the constraints.\n");              printf("MAJOR MODE:  Finding closest rational number with magnitude not smaller under\n             the constraints.\n");
1278              }              }
1279           else if (parblock.neverlarger_specified)           else if (parblock.neverlarger_specified)
1280              {              {
1281              printf("MAJOR MODE:  Finding closest rational number with magnitude not larger under\n             the constraints.\n");              printf("MAJOR MODE:  Finding closest rational number with magnitude not larger under\n             the constraints.\n");
1282              }              }
1283           else if (parblock.pred_specified)           else if (parblock.pred_specified)
1284              {              {
1285              printf("MAJOR MODE:  Finding predecessor under the constraints.\n");              printf("MAJOR MODE:  Finding predecessor under the constraints.\n");
1286              }              }
1287           else if (parblock.succ_specified)           else if (parblock.succ_specified)
1288              {              {
1289              printf("MAJOR MODE:  Finding successor under the constraints.\n");              printf("MAJOR MODE:  Finding successor under the constraints.\n");
1290              }              }
1291           else           else
1292              {              {
1293              assert(0);              assert(0);
1294              }              }
1295    
1296           FCMIOF_hline();           FCMIOF_hline();
1297           }           }
1298    
1299        //Echo back the command-line parameters.        //Echo back the command-line parameters.
1300        if (!(parblock.argblock.noformat))        if (!(parblock.argblock.noformat))
1301           {           {
1302           GMP_INTS_mpz_long_int_format_to_stream(stdout,           GMP_INTS_mpz_long_int_format_to_stream(stdout,
1303                                                  &(parblock.rn.num),                                                  &(parblock.rn.num),
1304                                                  "RI_IN   Numerator");                                                  "RI_IN   Numerator");
1305           FCMIOF_hline();           FCMIOF_hline();
1306           GMP_INTS_mpz_long_int_format_to_stream(stdout,           GMP_INTS_mpz_long_int_format_to_stream(stdout,
1307                                                  &(parblock.rn.den),                                                  &(parblock.rn.den),
1308                                                  "RI_IN Denominator");                                                  "RI_IN Denominator");
1309           FCMIOF_hline();           FCMIOF_hline();
1310    
1311           GMP_INTS_mpz_long_int_format_to_stream(stdout,           GMP_INTS_mpz_long_int_format_to_stream(stdout,
1312                                                  &(parblock.kmax),                                                  &(parblock.kmax),
1313                                                  "K_MAX");                                                  "K_MAX");
1314           FCMIOF_hline();           FCMIOF_hline();
1315    
1316           if (parblock.hmax_specified)           if (parblock.hmax_specified)
1317              {              {
1318              GMP_INTS_mpz_long_int_format_to_stream(stdout,              GMP_INTS_mpz_long_int_format_to_stream(stdout,
1319                                                     &(parblock.hmax),                                                     &(parblock.hmax),
1320                                                     "H_MAX");                                                     "H_MAX");
1321              FCMIOF_hline();              FCMIOF_hline();
1322              }              }
1323    
1324           if (parblock.n_specified)           if (parblock.n_specified)
1325              {              {
1326              GMP_INTS_mpz_struct temp24;              GMP_INTS_mpz_struct temp24;
1327    
1328              GMP_INTS_mpz_init(&temp24);              GMP_INTS_mpz_init(&temp24);
1329    
1330              GMP_INTS_mpz_set_ui(&temp24, parblock.n);              GMP_INTS_mpz_set_ui(&temp24, parblock.n);
1331    
1332              GMP_INTS_mpz_long_int_format_to_stream(stdout,              GMP_INTS_mpz_long_int_format_to_stream(stdout,
1333                                                     &temp24,                                                     &temp24,
1334                                                     "Number Of Neighbors");                                                     "Number Of Neighbors");
1335    
1336              FCMIOF_hline();              FCMIOF_hline();
1337    
1338              GMP_INTS_mpz_clear(&temp24);              GMP_INTS_mpz_clear(&temp24);
1339              }              }
1340           }           }
1341    
1342        //We need to split now into distinct cases        //We need to split now into distinct cases
1343        //depending on the command-line parameters.  We will        //depending on the command-line parameters.  We will
1344        //then hack out solutions for each case.        //then hack out solutions for each case.
1345        if (!parblock.pred_specified && !parblock.succ_specified && !parblock.n_specified)        if (!parblock.pred_specified && !parblock.succ_specified && !parblock.n_specified)
1346           {           {
1347           //Classic closest neighbor case.           //Classic closest neighbor case.
1348           rv = CMAIN_classic_closest_neighbor(&parblock);           rv = CMAIN_classic_closest_neighbor(&parblock);
1349           }           }
1350        else if (parblock.n_specified)        else if (parblock.n_specified)
1351           {           {
1352           //Classic multiple neighbor case.           //Classic multiple neighbor case.
1353           rv = CMAIN_multiple_neighbor(&parblock);           rv = CMAIN_multiple_neighbor(&parblock);
1354           }           }
1355        else if (parblock.pred_specified)        else if (parblock.pred_specified)
1356           {           {
1357           rv = CMAIN_predecessor(&parblock);           rv = CMAIN_predecessor(&parblock);
1358           }           }
1359        else if (parblock.succ_specified)        else if (parblock.succ_specified)
1360           {           {
1361           rv = CMAIN_successor(&parblock);           rv = CMAIN_successor(&parblock);
1362           }           }
1363        else        else
1364           {           {
1365           assert(0);           assert(0);
1366           }           }
1367    
1368        //Emit the closing horizontal line iff the -nf option isn't set.        //Emit the closing horizontal line iff the -nf option isn't set.
1369        //if (!(parblock.argblock.noformat))        //if (!(parblock.argblock.noformat))
1370        //   FCMIOF_hline();        //   FCMIOF_hline();
1371    
1372        //Release all dynamic memory.        //Release all dynamic memory.
1373        release_command_line_args(&parblock);        release_command_line_args(&parblock);
1374        }        }
1375    
1376     ret_pt:     ret_pt:
1377     return(rv);     return(rv);
1378     }     }
1379    
1380  // End of c_main.c.  // End of c_main.c.

Legend:
Removed from v.48  
changed lines
  Added in v.98

dashley@gmail.com
ViewVC Help
Powered by ViewVC 1.1.25