/[dtapublic]/projs/dtats/trunk/shared_source/c_tclxtens_7_5/arblenints.c
ViewVC logotype

Diff of /projs/dtats/trunk/shared_source/c_tclxtens_7_5/arblenints.c

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

projs/trunk/shared_source/tclxtens/arblenints.c revision 42 by dashley, Fri Oct 14 01:50:00 2016 UTC projs/dtats/trunk/shared_source/c_tclxtens_7_5/arblenints.c revision 98 by dashley, Sun Dec 18 00:57:31 2016 UTC
# Line 1  Line 1 
1  /* $Header: /cvsroot/esrg/sfesrg/esrgpcpj/shared/tclxtens/arblenints.c,v 1.12 2001/08/18 09:47:00 dtashley Exp $ */  //$Header$
2    //-------------------------------------------------------------------------------------------------
3  //--------------------------------------------------------------------------------  //This file is part of "David T. Ashley's Shared Source Code", a set of shared components
4  //Copyright 2001 David T. Ashley  //integrated into many of David T. Ashley's projects.
5  //-------------------------------------------------------------------------------------------------  //-------------------------------------------------------------------------------------------------
6  //This source code and any program in which it is compiled/used is provided under the GNU GENERAL  //This source code and any program in which it is compiled/used is provided under the MIT License,
7  //PUBLIC LICENSE, Version 3, full license text below.  //reproduced below.
8  //-------------------------------------------------------------------------------------------------  //-------------------------------------------------------------------------------------------------
9  //                    GNU GENERAL PUBLIC LICENSE  //Permission is hereby granted, free of charge, to any person obtaining a copy of
10  //                       Version 3, 29 June 2007  //this software and associated documentation files(the "Software"), to deal in the
11  //  //Software without restriction, including without limitation the rights to use,
12  // Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>  //copy, modify, merge, publish, distribute, sublicense, and / or sell copies of the
13  // Everyone is permitted to copy and distribute verbatim copies  //Software, and to permit persons to whom the Software is furnished to do so,
14  // of this license document, but changing it is not allowed.  //subject to the following conditions :
15  //  //
16  //                            Preamble  //The above copyright notice and this permission notice shall be included in all
17  //  //copies or substantial portions of the Software.
18  //  The GNU General Public License is a free, copyleft license for  //
19  //software and other kinds of works.  //THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20  //  //IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21  //  The licenses for most software and other practical works are designed  //FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE
22  //to take away your freedom to share and change the works.  By contrast,  //AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
23  //the GNU General Public License is intended to guarantee your freedom to  //LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
24  //share and change all versions of a program--to make sure it remains free  //OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
25  //software for all its users.  We, the Free Software Foundation, use the  //SOFTWARE.
26  //GNU General Public License for most of our software; it applies also to  //-------------------------------------------------------------------------------------------------
27  //any other work released this way by its authors.  You can apply it to  #define MODULE_ARBLENINTS
28  //your programs, too.  
29  //  #include <assert.h>
30  //  When we speak of free software, we are referring to freedom, not  #include <string.h>
31  //price.  Our General Public Licenses are designed to make sure that you  
32  //have the freedom to distribute copies of free software (and charge for  #include "tcl.h"
33  //them if you wish), that you receive source code or can get it if you  #include "tcldecls.h"
34  //want it, that you can change the software or use pieces of it in new  
35  //free programs, and that you know you can do these things.  #include "arblenints.h"
36  //  #include "bstrfunc.h"
37  //  To protect your rights, we need to prevent others from denying you  #include "extninit.h"
38  //these rights or asking you to surrender the rights.  Therefore, you have  #include "gmp_ints.h"
39  //certain responsibilities if you distribute copies of the software, or if  #include "gmp_rats.h"
40  //you modify it: responsibilities to respect the freedom of others.  #include "gmp_ralg.h"
41  //  #include "intfunc.h"
42  //  For example, if you distribute copies of such a program, whether  #include "tclalloc.h"
43  //gratis or for a fee, you must pass on to the recipients the same  
44  //freedoms that you received.  You must make sure that they, too, receive  
45  //or can get the source code.  And you must show them these terms so they  //Handles the "cfbrapab" subextension.
46  //know their rights.  //08/16/01: Visual inspection OK.
47  //  static
48  //  Developers that use the GNU GPL protect your rights with two steps:  int ARBLENINTS_cfbrapab_handler(ClientData dummy,
49  //(1) assert copyright on the software, and (2) offer you this License                                  Tcl_Interp *interp,
50  //giving you legal permission to copy, distribute and/or modify it.                                  int objc,
51  //                                  Tcl_Obj *objv[])
52  //  For the developers' and authors' protection, the GPL clearly explains     {
53  //that there is no warranty for this free software.  For both users' and     Tcl_Obj *rv;
54  //authors' sake, the GPL requires that modified versions be marked as  
55  //changed, so that their problems will not be attributed erroneously to     //We must have at least two additional arguments
56  //authors of previous versions.     //to this extension.
57  //     if (objc < 4)
58  //  Some devices are designed to deny users access to install or run        {
59  //modified versions of the software inside them, although the manufacturer        Tcl_WrongNumArgs(interp,
60  //can do so.  This is fundamentally incompatible with the aim of                         2,
61  //protecting users' freedom to change the software.  The systematic                         objv,
62  //pattern of such abuse occurs in the area of products for individuals to                         "srn uint_kmax ?uint_hmax? ?options?");
63  //use, which is precisely where it is most unacceptable.  Therefore, we        return(TCL_ERROR);
64  //have designed this version of the GPL to prohibit the practice for those        }
65  //products.  If such problems arise substantially in other domains, we     else
66  //stand ready to extend this provision to those domains in future versions        {
67  //of the GPL, as needed to protect the freedom of users.        char *input_arg;
68  //        int failure, first_dashed_parameter;
69  //  Finally, every program is threatened constantly by software patents.        char *string_result;
70  //States should not allow patents to restrict development and use of        int string_result_n_allocd;
71  //software on general-purpose computers, but in those that do, we wish to        int chars_reqd;
72  //avoid the special danger that patents applied to a free program could        int i;
73  //make it effectively proprietary.  To prevent this, the GPL assures that        int pred_option_specified         = 0;
74  //patents cannot be used to render the program non-free.        int succ_option_specified         = 0;
75  //        int neversmaller_option_specified = 0;
76  //  The precise terms and conditions for copying, distribution and        int neverlarger_option_specified  = 0;
77  //modification follow.        int n_option_specified            = 0;
78  //        unsigned n                        = 0;
79  //                       TERMS AND CONDITIONS  
80  //        GMP_RATS_mpq_struct q_rn;
81  //  0. Definitions.        GMP_INTS_mpz_struct z_kmax;
82  //        GMP_INTS_mpz_struct z_hmax;
83  //  "This License" refers to version 3 of the GNU General Public License.  
84  //        //Allocate dynamic memory.
85  //  "Copyright" also means copyright-like laws that apply to other kinds of        GMP_RATS_mpq_init(&q_rn);
86  //works, such as semiconductor masks.        GMP_INTS_mpz_init(&z_kmax);
87  //        GMP_INTS_mpz_init(&z_hmax);
88  //  "The Program" refers to any copyrightable work licensed under this  
89  //License.  Each licensee is addressed as "you".  "Licensees" and        //Grab a pointer to the string representation of
90  //"recipients" may be individuals or organizations.        //the first input argument.  The storage does not belong to us.
91  //        input_arg = Tcl_GetString(objv[2]);
92  //  To "modify" a work means to copy from or adapt all or part of the work        assert(input_arg != NULL);
93  //in a fashion requiring copyright permission, other than the making of an  
94  //exact copy.  The resulting work is called a "modified version" of the        //Try to parse our first input string as a rational number.
95  //earlier work or a work "based on" the earlier work.        //If we are not successful in this, must abort.
96  //        GMP_RATS_mpq_set_all_format_rat_num(input_arg,
97  //  A "covered work" means either the unmodified Program or a work based                                            &failure,
98  //on the Program.                                            &q_rn);
99  //  
100  //  To "propagate" a work means to do anything with it that, without        if (failure)
101  //permission, would make you directly or secondarily liable for           {
102  //infringement under applicable copyright law, except executing it on a           rv = Tcl_NewStringObj("arbint cfbrapab: \"", -1);
103  //computer or modifying a private copy.  Propagation includes copying,           Tcl_AppendToObj(rv, input_arg, -1);
104  //distribution (with or without modification), making available to the  
105  //public, and in some countries other activities as well.           Tcl_AppendToObj(rv, "\" is not a recognized rational number.", -1);
106  //           Tcl_SetObjResult(interp, rv);
107  //  To "convey" a work means any kind of propagation that enables other  
108  //parties to make or receive copies.  Mere interaction with a user through           GMP_RATS_mpq_clear(&q_rn);
109  //a computer network, with no transfer of a copy, is not conveying.           GMP_INTS_mpz_clear(&z_kmax);
110  //           GMP_INTS_mpz_clear(&z_hmax);
111  //  An interactive user interface displays "Appropriate Legal Notices"  
112  //to the extent that it includes a convenient and prominently visible           return(TCL_ERROR);
113  //feature that (1) displays an appropriate copyright notice, and (2)           }
114  //tells the user that there is no warranty for the work (except to the  
115  //extent that warranties are provided), that licensees may convey the        //Try to parse our next argument as an integer, which
116  //work under this License, and how to view a copy of this License.  If        //will be KMAX.  This must be specified.
117  //the interface presents a list of user commands or options, such as a        //
118  //menu, a prominent item in the list meets this criterion.        //Get string pointer.  Storage does not belong to us.
119  //        input_arg = Tcl_GetString(objv[3]);
120  //  1. Source Code.        assert(input_arg != NULL);
121  //  
122  //  The "source code" for a work means the preferred form of the work        //Try to convert KMAX to an integer.  Fatal if an error,
123  //for making modifications to it.  "Object code" means any non-source        //and fatal if the argument is zero or negative.
124  //form of a work.        GMP_INTS_mpz_set_general_int(&z_kmax, &failure, input_arg);
125  //  
126  //  A "Standard Interface" means an interface that either is an official        //If there was a parse failure or if the integer is zero
127  //standard defined by a recognized standards body, or, in the case of        //or negative, must flag error.
128  //interfaces specified for a particular programming language, one that        if (failure || GMP_INTS_mpz_is_neg(&z_kmax) || GMP_INTS_mpz_is_zero(&z_kmax))
129  //is widely used among developers working in that language.           {
130  //           rv = Tcl_NewStringObj("arbint cfbrapab: \"", -1);
131  //  The "System Libraries" of an executable work include anything, other           Tcl_AppendToObj(rv, input_arg, -1);
132  //than the work as a whole, that (a) is included in the normal form of           Tcl_AppendToObj(rv, "\" is not a recognized positive integer.", -1);
133  //packaging a Major Component, but which is not part of that Major           Tcl_SetObjResult(interp, rv);
134  //Component, and (b) serves only to enable use of the work with that  
135  //Major Component, or to implement a Standard Interface for which an           GMP_RATS_mpq_clear(&q_rn);
136  //implementation is available to the public in source code form.  A           GMP_INTS_mpz_clear(&z_kmax);
137  //"Major Component", in this context, means a major essential component           GMP_INTS_mpz_clear(&z_hmax);
138  //(kernel, window system, and so on) of the specific operating system  
139  //(if any) on which the executable work runs, or a compiler used to           return(TCL_ERROR);
140  //produce the work, or an object code interpreter used to run it.           }
141  //  
142  //  The "Corresponding Source" for a work in object code form means all        //We need to look for HMAX as the next parameter, if it exists.
143  //the source code needed to generate, install, and (for an executable        //The way we will figure this out is by whether the
144  //work) run the object code and to modify the work, including scripts to        //parameter begins with a "-" or not.
145  //control those activities.  However, it does not include the work's        if (objc >= 5)
146  //System Libraries, or general-purpose tools or generally available free           {
147  //programs which are used unmodified in performing those activities but           input_arg = Tcl_GetString(objv[4]);
148  //which are not part of the work.  For example, Corresponding Source           assert(input_arg != NULL);
149  //includes interface definition files associated with source files for  
150  //the work, and the source code for shared libraries and dynamically           if (input_arg[0] == '-')
151  //linked subprograms that the work is specifically designed to require,              {
152  //such as by intimate data communication or control flow between those              first_dashed_parameter = 4;
153  //subprograms and other parts of the work.              }
154  //           else
155  //  The Corresponding Source need not include anything that users              {
156  //can regenerate automatically from other parts of the Corresponding              first_dashed_parameter = 5;
157  //Source.              }
158  //           }
159  //  The Corresponding Source for a work in source code form is that        else
160  //same work.           {
161  //           first_dashed_parameter = 4;
162  //  2. Basic Permissions.           }
163  //  
164  //  All rights granted under this License are granted for the term of        //If there is another parameter and it
165  //copyright on the Program, and are irrevocable provided the stated        //doesn't begin with a dash, try to parse
166  //conditions are met.  This License explicitly affirms your unlimited        //it as HMAX.  We don't explicitly record whether
167  //permission to run the unmodified Program.  The output from running a        //HMAX is specified, because zero is a signal
168  //covered work is covered by this License only if the output, given its        //when calculating Farey neighbors that HMAX isn't
169  //content, constitutes a covered work.  This License acknowledges your        //to be considered.
170  //rights of fair use or other equivalent, as provided by copyright law.        if ((objc >= 5) && (first_dashed_parameter == 5))
171  //           {
172  //  You may make, run and propagate covered works that you do not           //Get string pointer.  Storage does not belong to us.
173  //convey, without conditions so long as your license otherwise remains           input_arg = Tcl_GetString(objv[4]);
174  //in force.  You may convey covered works to others for the sole purpose           assert(input_arg != NULL);
175  //of having them make modifications exclusively for you, or provide you  
176  //with facilities for running those works, provided that you comply with           //Try to convert HMAX to an integer.  Fatal if an error,
177  //the terms of this License in conveying all material for which you do           //and fatal if the argument is zero or negative.
178  //not control copyright.  Those thus making or running the covered works           GMP_INTS_mpz_set_general_int(&z_hmax, &failure, input_arg);
179  //for you must do so exclusively on your behalf, under your direction  
180  //and control, on terms that prohibit them from making any copies of           //If there was a parse failure or if the integer is zero
181  //your copyrighted material outside their relationship with you.           //or negative, must flag error.
182  //           if (failure || GMP_INTS_mpz_is_neg(&z_hmax) || GMP_INTS_mpz_is_zero(&z_hmax))
183  //  Conveying under any other circumstances is permitted solely under              {
184  //the conditions stated below.  Sublicensing is not allowed; section 10              rv = Tcl_NewStringObj("arbint cfbrapab: \"", -1);
185  //makes it unnecessary.              Tcl_AppendToObj(rv, input_arg, -1);
186  //              Tcl_AppendToObj(rv, "\" is not a recognized positive integer.", -1);
187  //  3. Protecting Users' Legal Rights From Anti-Circumvention Law.              Tcl_SetObjResult(interp, rv);
188  //  
189  //  No covered work shall be deemed part of an effective technological              GMP_RATS_mpq_clear(&q_rn);
190  //measure under any applicable law fulfilling obligations under article              GMP_INTS_mpz_clear(&z_kmax);
191  //11 of the WIPO copyright treaty adopted on 20 December 1996, or              GMP_INTS_mpz_clear(&z_hmax);
192  //similar laws prohibiting or restricting circumvention of such  
193  //measures.              return(TCL_ERROR);
194  //              }
195  //  When you convey a covered work, you waive any legal power to forbid           }
196  //circumvention of technological measures to the extent such circumvention  
197  //is effected by exercising rights under this License with respect to        //Process all of the dashed command-line arguments.
198  //the covered work, and you disclaim any intention to limit operation or        //This involves iterating through all of the
199  //modification of the work as a means of enforcing, against the work's        //parameters and processing them.
200  //users, your or third parties' legal rights to forbid circumvention of        for (i=first_dashed_parameter; i<objc; i++)
201  //technological measures.           {
202  //           input_arg = Tcl_GetString(objv[i]);
203  //  4. Conveying Verbatim Copies.           assert(input_arg != NULL);
204  //  
205  //  You may convey verbatim copies of the Program's source code as you           if (!strcmp("-pred", input_arg))
206  //receive it, in any medium, provided that you conspicuously and              {
207  //appropriately publish on each copy an appropriate copyright notice;              pred_option_specified = 1;
208  //keep intact all notices stating that this License and any              }
209  //non-permissive terms added in accord with section 7 apply to the code;           else if (!strcmp("-succ", input_arg))
210  //keep intact all notices of the absence of any warranty; and give all              {
211  //recipients a copy of this License along with the Program.              succ_option_specified = 1;
212  //              }
213  //  You may charge any price or no price for each copy that you convey,           else if (!strcmp("-neversmaller", input_arg))
214  //and you may offer support or warranty protection for a fee.              {
215  //              neversmaller_option_specified = 1;
216  //  5. Conveying Modified Source Versions.              }
217  //           else if (!strcmp("-neverlarger", input_arg))
218  //  You may convey a work based on the Program, or the modifications to              {
219  //produce it from the Program, in the form of source code under the              neverlarger_option_specified = 1;
220  //terms of section 4, provided that you also meet all of these conditions:              }
221  //           else if (!strcmp("-n", input_arg))
222  //    a) The work must carry prominent notices stating that you modified              {
223  //    it, and giving a relevant date.              n_option_specified = 1;
224  //  
225  //    b) The work must carry prominent notices stating that it is              //If -n was specified, there must be a following
226  //    released under this License and any conditions added under section              //parameter which supplies the integer.  First
227  //    7.  This requirement modifies the requirement in section 4 to              //check for existence of an additional parameter.
228  //    "keep intact all notices".              if (i >= (objc - 1))
229  //                 {
230  //    c) You must license the entire work, as a whole, under this                 rv = Tcl_NewStringObj("arbint cfbrapab: -n option specified without following integer.", -1);
231  //    License to anyone who comes into possession of a copy.  This                 Tcl_SetObjResult(interp, rv);
232  //    License will therefore apply, along with any applicable section 7  
233  //    additional terms, to the whole of the work, and all its parts,                 GMP_RATS_mpq_clear(&q_rn);
234  //    regardless of how they are packaged.  This License gives no                 GMP_INTS_mpz_clear(&z_kmax);
235  //    permission to license the work in any other way, but it does not                 GMP_INTS_mpz_clear(&z_hmax);
236  //    invalidate such permission if you have separately received it.  
237  //                 return(TCL_ERROR);
238  //    d) If the work has interactive user interfaces, each must display                 }
239  //    Appropriate Legal Notices; however, if the Program has interactive  
240  //    interfaces that do not display Appropriate Legal Notices, your              //We have at least one additional parameter.  Try
241  //    work need not make them do so.              //to parse out the next parameter as the integer
242  //              //we need for n.
243  //  A compilation of a covered work with other separate and independent              i++;
244  //works, which are not by their nature extensions of the covered work,  
245  //and which are not combined with it such as to form a larger program,              input_arg = Tcl_GetString(objv[i]);
246  //in or on a volume of a storage or distribution medium, is called an              assert(input_arg != NULL);
247  //"aggregate" if the compilation and its resulting copyright are not  
248  //used to limit the access or legal rights of the compilation's users              GMP_INTS_mpz_parse_into_uint32(&n, &failure, input_arg);
249  //beyond what the individual works permit.  Inclusion of a covered work  
250  //in an aggregate does not cause this License to apply to the other              //If the parse was unsuccessful, terminate.
251  //parts of the aggregate.              if (failure)
252  //                 {
253  //  6. Conveying Non-Source Forms.                 rv = Tcl_NewStringObj("arbint cfbrapab: -n option followed by invalid integer.", -1);
254  //                 Tcl_SetObjResult(interp, rv);
255  //  You may convey a covered work in object code form under the terms  
256  //of sections 4 and 5, provided that you also convey the                 GMP_RATS_mpq_clear(&q_rn);
257  //machine-readable Corresponding Source under the terms of this License,                 GMP_INTS_mpz_clear(&z_kmax);
258  //in one of these ways:                 GMP_INTS_mpz_clear(&z_hmax);
259  //  
260  //    a) Convey the object code in, or embodied in, a physical product                 return(TCL_ERROR);
261  //    (including a physical distribution medium), accompanied by the                 }
262  //    Corresponding Source fixed on a durable physical medium  
263  //    customarily used for software interchange.              //Clip the integer into a 24-bit quantity.
264  //              n &= 0x00FFFFFF;
265  //    b) Convey the object code in, or embodied in, a physical product              }
266  //    (including a physical distribution medium), accompanied by a           else
267  //    written offer, valid for at least three years and valid for as              {
268  //    long as you offer spare parts or customer support for that product              //Unrecognized option.  Crash out.
269  //    model, to give anyone who possesses the object code either (1) a              rv = Tcl_NewStringObj("arbint cfbrapab: \"", -1);
270  //    copy of the Corresponding Source for all the software in the              Tcl_AppendToObj(rv, input_arg, -1);
271  //    product that is covered by this License, on a durable physical              Tcl_AppendToObj(rv, "\" is not a recognized option.", -1);
272  //    medium customarily used for software interchange, for a price no              Tcl_SetObjResult(interp, rv);
273  //    more than your reasonable cost of physically performing this  
274  //    conveying of source, or (2) access to copy the              GMP_RATS_mpq_clear(&q_rn);
275  //    Corresponding Source from a network server at no charge.              GMP_INTS_mpz_clear(&z_kmax);
276  //              GMP_INTS_mpz_clear(&z_hmax);
277  //    c) Convey individual copies of the object code with a copy of the  
278  //    written offer to provide the Corresponding Source.  This              return(TCL_ERROR);
279  //    alternative is allowed only occasionally and noncommercially, and              }
280  //    only if you received the object code with such an offer, in accord           }
281  //    with subsection 6b.  
282  //        //Look for any mutually exclusive options.  Give a catchall if any of
283  //    d) Convey the object code by offering access from a designated        //them specified.  Because we set them all to 1, addition is the easiest
284  //    place (gratis or for a charge), and offer equivalent access to the        //way to do this.
285  //    Corresponding Source in the same way through the same place at no        if ((pred_option_specified + succ_option_specified + neversmaller_option_specified
286  //    further charge.  You need not require recipients to copy the             + neverlarger_option_specified + n_option_specified) > 1)
287  //    Corresponding Source along with the object code.  If the place to           {
288  //    copy the object code is a network server, the Corresponding Source           rv = Tcl_NewStringObj("arbint cfbrapab: -pred, -succ, -neversmaller, -neverlarger, and -n are mutually exclusive options.", -1);
289  //    may be on a different server (operated by you or a third party)           Tcl_SetObjResult(interp, rv);
290  //    that supports equivalent copying facilities, provided you maintain  
291  //    clear directions next to the object code saying where to find the           GMP_RATS_mpq_clear(&q_rn);
292  //    Corresponding Source.  Regardless of what server hosts the           GMP_INTS_mpz_clear(&z_kmax);
293  //    Corresponding Source, you remain obligated to ensure that it is           GMP_INTS_mpz_clear(&z_hmax);
294  //    available for as long as needed to satisfy these requirements.  
295  //           return(TCL_ERROR);
296  //    e) Convey the object code using peer-to-peer transmission, provided           }
297  //    you inform other peers where the object code and Corresponding  
298  //    Source of the work are being offered to the general public at no        //Split into cases based on what we're doing.  This is wasteful of code,
299  //    charge under subsection 6d.        //but this is a PC application, not an embedded application.  In all cases
300  //        //create a hard error if something goes wrong.  Any anomalies should trash
301  //  A separable portion of the object code, whose source code is excluded        //a script.
302  //from the Corresponding Source as a System Library, need not be        if (!pred_option_specified && !succ_option_specified && !n_option_specified)
303  //included in conveying the object code work.           {
304  //           //This is the traditional best approximation case, with the possibility of
305  //  A "User Product" is either (1) a "consumer product", which means any           //the -neverlarger or -neversmaller being specified.  This is the most messy
306  //tangible personal property which is normally used for personal, family,           //of all the cases.  We must gather neighbors and figure out which is closer,
307  //or household purposes, or (2) anything designed or sold for incorporation           //and if there is a tie, which has the smaller magnitude.  It is fairly
308  //into a dwelling.  In determining whether a product is a consumer product,           //messy.
309  //doubtful cases shall be resolved in favor of coverage.  For a particular           GMP_RALG_fab_neighbor_collection_struct neighbor_data;
310  //product received by a particular user, "normally used" refers to a           GMP_RATS_mpq_struct left_neigh, right_neigh, diff_left, diff_right, closer_neighbor;
311  //typical or common use of that class of product, regardless of the status           int dist_cmp;
312  //of the particular user or of the way in which the particular user           int mag_cmp;
313  //actually uses, or expects or is expected to use, the product.  A product  
314  //is a consumer product regardless of whether the product has substantial           //Allocate inner dynamic variables.
315  //commercial, industrial or non-consumer uses, unless such uses represent           GMP_RATS_mpq_init(&left_neigh);
316  //the only significant mode of use of the product.           GMP_RATS_mpq_init(&right_neigh);
317  //           GMP_RATS_mpq_init(&diff_left);
318  //  "Installation Information" for a User Product means any methods,           GMP_RATS_mpq_init(&diff_right);
319  //procedures, authorization keys, or other information required to install           GMP_RATS_mpq_init(&closer_neighbor);
320  //and execute modified versions of a covered work in that User Product from  
321  //a modified version of its Corresponding Source.  The information must           //Form up the neighbor data.  We're only looking for up to one neighbor on each
322  //suffice to ensure that the continued functioning of the modified object           //side.
323  //code is in no case prevented or interfered with solely because           GMP_RALG_consecutive_fab_terms(
324  //modification has been made.                                         &q_rn,
325  //                                         &z_kmax,
326  //  If you convey an object code work under this section in, or with, or                                         &z_hmax,
327  //specifically for use in, a User Product, and the conveying occurs as                                         1,
328  //part of a transaction in which the right of possession and use of the                                         1,
329  //User Product is transferred to the recipient in perpetuity or for a                                         &neighbor_data
330  //fixed term (regardless of how the transaction is characterized), the                                         );
331  //Corresponding Source conveyed under this section must be accompanied  
332  //by the Installation Information.  But this requirement does not apply           //If there was an error or we couldn't get any neighbors to play with, give
333  //if neither you nor any third party retains the ability to install           //an error return.  As long as we have one neighbor on either side, we can definitely
334  //modified object code on the User Product (for example, the work has           //complete.
335  //been installed in ROM).           if (neighbor_data.error || (!neighbor_data.equality && (!neighbor_data.n_left_out || !neighbor_data.n_right_out)))
336  //              {
337  //  The requirement to provide Installation Information does not include a              rv = Tcl_NewStringObj("arbint cfbrapab: unable to form neighbors.", -1);
338  //requirement to continue to provide support service, warranty, or updates              Tcl_SetObjResult(interp, rv);
339  //for a work that has been modified or installed by the recipient, or for  
340  //the User Product in which it has been modified or installed.  Access to a              GMP_RALG_consecutive_fab_terms_result_free(&neighbor_data);
341  //network may be denied when the modification itself materially and              GMP_RATS_mpq_clear(&q_rn);
342  //adversely affects the operation of the network or violates the rules and              GMP_INTS_mpz_clear(&z_kmax);
343  //protocols for communication across the network.              GMP_INTS_mpz_clear(&z_hmax);
344  //  
345  //  Corresponding Source conveyed, and Installation Information provided,              GMP_RATS_mpq_clear(&left_neigh);
346  //in accord with this section must be in a format that is publicly              GMP_RATS_mpq_clear(&right_neigh);
347  //documented (and with an implementation available to the public in              GMP_RATS_mpq_clear(&diff_left);
348  //source code form), and must require no special password or key for              GMP_RATS_mpq_clear(&diff_right);
349  //unpacking, reading or copying.              GMP_RATS_mpq_clear(&closer_neighbor);
350  //  
351  //  7. Additional Terms.              return(TCL_ERROR);
352  //              }
353  //  "Additional permissions" are terms that supplement the terms of this  
354  //License by making exceptions from one or more of its conditions.           if (neighbor_data.equality)
355  //Additional permissions that are applicable to the entire Program shall              {
356  //be treated as though they were included in this License, to the extent              //The equality case takes precedence, always.
357  //that they are valid under applicable law.  If additional permissions              GMP_RATS_mpq_copy(&closer_neighbor, &(neighbor_data.norm_rn));
358  //apply only to part of the Program, that part may be used separately              }
359  //under those permissions, but the entire Program remains governed by           else
360  //this License without regard to the additional permissions.              {
361  //              //The boolean test somewhat above guaranteed that we have both left
362  //  When you convey a copy of a covered work, you may at your option              //and right neighbors.  We can assume this.
363  //remove any additional permissions from that copy, or from any part of              GMP_RATS_mpq_copy(&left_neigh,  &(neighbor_data.lefts[0].neighbor));
364  //it.  (Additional permissions may be written to require their own              GMP_RATS_mpq_copy(&right_neigh, &(neighbor_data.rights[0].neighbor));
365  //removal in certain cases when you modify the work.)  You may place  
366  //additional permissions on material, added by you to a covered work,              GMP_RATS_mpq_sub(&diff_left,  &left_neigh,  &(neighbor_data.norm_rn));
367  //for which you have or can give appropriate copyright permission.              GMP_RATS_mpq_sub(&diff_right, &right_neigh, &(neighbor_data.norm_rn));
368  //              GMP_INTS_mpz_abs(&(diff_left.num));
369  //  Notwithstanding any other provision of this License, for material you              GMP_INTS_mpz_abs(&(diff_right.num));
370  //add to a covered work, you may (if authorized by the copyright holders of              dist_cmp = GMP_RATS_mpq_cmp(&diff_left, &diff_right, NULL);
371  //that material) supplement the terms of this License with terms:  
372  //              //If we have a tie on the distance, will need to revert to magnitude of the neighbors.
373  //    a) Disclaiming warranty or limiting liability differently from the              GMP_INTS_mpz_abs(&(left_neigh.num));
374  //    terms of sections 15 and 16 of this License; or              GMP_INTS_mpz_abs(&(right_neigh.num));
375  //              mag_cmp = GMP_RATS_mpq_cmp(&left_neigh, &right_neigh, NULL);
376  //    b) Requiring preservation of specified reasonable legal notices or  
377  //    author attributions in that material or in the Appropriate Legal              if (!neversmaller_option_specified
378  //    Notices displayed by works containing it; or                 &&
379  //                 (neverlarger_option_specified || (dist_cmp < 0) || ((dist_cmp==0) && (mag_cmp < 0))))
380  //    c) Prohibiting misrepresentation of the origin of that material, or                 {
381  //    requiring that modified versions of such material be marked in                 GMP_RATS_mpq_copy(&closer_neighbor, &(neighbor_data.lefts[0].neighbor));
382  //    reasonable ways as different from the original version; or                 }
383  //              else
384  //    d) Limiting the use for publicity purposes of names of licensors or                 {
385  //    authors of the material; or                 GMP_RATS_mpq_copy(&closer_neighbor, &(neighbor_data.rights[0].neighbor));
386  //                 }
387  //    e) Declining to grant rights under trademark law for use of some              }
388  //    trade names, trademarks, or service marks; or  
389  //           //Stuff our variable of choice into a string ...
390  //    f) Requiring indemnification of licensors and authors of that           chars_reqd = INTFUNC_max(
391  //    material by anyone who conveys the material (or modified versions of                                   GMP_INTS_mpz_size_in_base_10(&(closer_neighbor.num)),
392  //    it) with contractual assumptions of liability to the recipient, for                                   GMP_INTS_mpz_size_in_base_10(&(closer_neighbor.den))
393  //    any liability that these contractual assumptions directly impose on                                   );
394  //    those licensors and authors.           string_result = TclpAlloc(sizeof(char) * chars_reqd);
395  //           assert(string_result != NULL);
396  //  All other non-permissive additional terms are considered "further  
397  //restrictions" within the meaning of section 10.  If the Program as you           GMP_INTS_mpz_to_string(string_result, &(closer_neighbor.num));
398  //received it, or any part of it, contains a notice stating that it is           rv = Tcl_NewStringObj(string_result, -1);
399  //governed by this License along with a term that is a further           Tcl_AppendToObj(rv, "/", -1);
400  //restriction, you may remove that term.  If a license document contains           GMP_INTS_mpz_to_string(string_result, &(closer_neighbor.den));
401  //a further restriction but permits relicensing or conveying under this           Tcl_AppendToObj(rv, string_result, -1);
402  //License, you may add to a covered work material governed by the terms  
403  //of that license document, provided that the further restriction does           Tcl_SetObjResult(interp, rv);
404  //not survive such relicensing or conveying.  
405  //           //Deallocate variables, make normal return.
406  //  If you add terms to a covered work in accord with this section, you           TclpFree(string_result);
407  //must place, in the relevant source files, a statement of the           GMP_RALG_consecutive_fab_terms_result_free(&neighbor_data);
408  //additional terms that apply to those files, or a notice indicating           GMP_RATS_mpq_clear(&q_rn);
409  //where to find the applicable terms.           GMP_INTS_mpz_clear(&z_kmax);
410  //           GMP_INTS_mpz_clear(&z_hmax);
411  //  Additional terms, permissive or non-permissive, may be stated in the  
412  //form of a separately written license, or stated as exceptions;           GMP_RATS_mpq_clear(&left_neigh);
413  //the above requirements apply either way.           GMP_RATS_mpq_clear(&right_neigh);
414  //           GMP_RATS_mpq_clear(&diff_left);
415  //  8. Termination.           GMP_RATS_mpq_clear(&diff_right);
416  //           GMP_RATS_mpq_clear(&closer_neighbor);
417  //  You may not propagate or modify a covered work except as expressly  
418  //provided under this License.  Any attempt otherwise to propagate or           return(TCL_OK);
419  //modify it is void, and will automatically terminate your rights under           }
420  //this License (including any patent licenses granted under the third        else if (n_option_specified)
421  //paragraph of section 11).           {
422  //           char sbuf[50];
423  //  However, if you cease all violation of this License, then your              //Static buffer just to stage 32-bit integers.
424  //license from a particular copyright holder is reinstated (a)            
425  //provisionally, unless and until the copyright holder explicitly and           //Multiple neighbors.  Must iterate through.
426  //finally terminates your license, and (b) permanently, if the copyright  
427  //holder fails to notify you of the violation by some reasonable means           GMP_RALG_fab_neighbor_collection_struct neighbor_data;
428  //prior to 60 days after the cessation.  
429  //           //Form up the neighbor data.      
430  //  Moreover, your license from a particular copyright holder is           GMP_RALG_consecutive_fab_terms(
431  //reinstated permanently if the copyright holder notifies you of the                                         &q_rn,
432  //violation by some reasonable means, this is the first time you have                                         &z_kmax,
433  //received notice of violation of this License (for any work) from that                                         &z_hmax,
434  //copyright holder, and you cure the violation prior to 30 days after                                         n,
435  //your receipt of the notice.                                         n,
436  //                                         &neighbor_data
437  //  Termination of your rights under this section does not terminate the                                         );
438  //licenses of parties who have received copies or rights from you under  
439  //this License.  If your rights have been terminated and not permanently           //If there was an error forming up the neighbor data, create a hard error.
440  //reinstated, you do not qualify to receive new licenses for the same           if (neighbor_data.error)
441  //material under section 10.              {
442  //              rv = Tcl_NewStringObj("arbint cfbrapab: unable to form neighbors.", -1);
443  //  9. Acceptance Not Required for Having Copies.              Tcl_SetObjResult(interp, rv);
444  //  
445  //  You are not required to accept this License in order to receive or              GMP_RALG_consecutive_fab_terms_result_free(&neighbor_data);
446  //run a copy of the Program.  Ancillary propagation of a covered work              GMP_RATS_mpq_clear(&q_rn);
447  //occurring solely as a consequence of using peer-to-peer transmission              GMP_INTS_mpz_clear(&z_kmax);
448  //to receive a copy likewise does not require acceptance.  However,              GMP_INTS_mpz_clear(&z_hmax);
449  //nothing other than this License grants you permission to propagate or  
450  //modify any covered work.  These actions infringe copyright if you do              return(TCL_ERROR);
451  //not accept this License.  Therefore, by modifying or propagating a              }
452  //covered work, you indicate your acceptance of this License to do so.  
453  //           //Allocate a default buffer of 10K for the ASCII representation of integers.
454  //  10. Automatic Licensing of Downstream Recipients.           //In the vast majority of cases, there will be only one allocation, because it
455  //           //takes a mean integer to exceed 10K.  However, the logic allows it to grow.
456  //  Each time you convey a covered work, the recipient automatically           string_result_n_allocd = 10000;
457  //receives a license from the original licensors, to run, modify and           string_result = TclpAlloc(sizeof(char) * string_result_n_allocd);
458  //propagate that work, subject to this License.  You are not responsible           assert(string_result != NULL);
459  //for enforcing compliance by third parties with this License.  
460  //           //Start off with a return value of the null string.
461  //  An "entity transaction" is a transaction transferring control of an           rv = Tcl_NewStringObj("", -1);
462  //organization, or substantially all assets of one, or subdividing an  
463  //organization, or merging organizations.  If propagation of a covered           //Loop through, spitting out the left neighbors.
464  //work results from an entity transaction, each party to that           for (i = neighbor_data.n_left_out-1; i >= 0; i--)
465  //transaction who receives a copy of the work also receives whatever              {
466  //licenses to the work the party's predecessor in interest had or could              //The protocol here is everyone spits out one space before
467  //give under the previous paragraph, plus a right to possession of the              //they print anything.  Must skip this on first loop iteration.
468  //Corresponding Source of the work from the predecessor in interest, if              if (i != neighbor_data.n_left_out-1)
469  //the predecessor has it or can get it with reasonable efforts.                 Tcl_AppendToObj(rv, " ", -1);
470  //  
471  //  You may not impose any further restrictions on the exercise of the              //The index will be the negative of the iteration variable minus one.
472  //rights granted or affirmed under this License.  For example, you may              sprintf(sbuf, "%d", -i - 1);
473  //not impose a license fee, royalty, or other charge for exercise of              Tcl_AppendToObj(rv, sbuf, -1);
474  //rights granted under this License, and you may not initiate litigation              
475  //(including a cross-claim or counterclaim in a lawsuit) alleging that              //Force the buffer to have enough space for the components of the rational
476  //any patent claim is infringed by making, using, selling, offering for              //number.
477  //sale, or importing the Program or any portion of it.              chars_reqd = INTFUNC_max(
478  //                                      GMP_INTS_mpz_size_in_base_10(&(neighbor_data.lefts[i].neighbor.num)),
479  //  11. Patents.                                      GMP_INTS_mpz_size_in_base_10(&(neighbor_data.lefts[i].neighbor.den))
480  //                                      );
481  //  A "contributor" is a copyright holder who authorizes use under this              if (chars_reqd > string_result_n_allocd)
482  //License of the Program or a work on which the Program is based.  The                 {
483  //work thus licensed is called the contributor's "contributor version".                 string_result_n_allocd = chars_reqd;
484  //                 string_result = TclpRealloc(string_result, sizeof(char) * string_result_n_allocd);
485  //  A contributor's "essential patent claims" are all patent claims                 assert(string_result != NULL);
486  //owned or controlled by the contributor, whether already acquired or                 }
487  //hereafter acquired, that would be infringed by some manner, permitted  
488  //by this License, of making, using, or selling its contributor version,              //Print the rational number out to the Tcl object.
489  //but do not include claims that would be infringed only as a              Tcl_AppendToObj(rv, " ", -1);
490  //consequence of further modification of the contributor version.  For              GMP_INTS_mpz_to_string(string_result, &(neighbor_data.lefts[i].neighbor.num));
491  //purposes of this definition, "control" includes the right to grant              Tcl_AppendToObj(rv, string_result, -1);
492  //patent sublicenses in a manner consistent with the requirements of              Tcl_AppendToObj(rv, "/", -1);
493  //this License.              GMP_INTS_mpz_to_string(string_result, &(neighbor_data.lefts[i].neighbor.den));
494  //              Tcl_AppendToObj(rv, string_result, -1);
495  //  Each contributor grants you a non-exclusive, worldwide, royalty-free              }
496  //patent license under the contributor's essential patent claims, to  
497  //make, use, sell, offer for sale, import and otherwise run, modify and           //Spit out the equality case if appropriate.
498  //propagate the contents of its contributor version.           if (neighbor_data.equality)
499  //              {
500  //  In the following three paragraphs, a "patent license" is any express              if (neighbor_data.n_left_out)
501  //agreement or commitment, however denominated, not to enforce a patent                 Tcl_AppendToObj(rv, " ", -1);
502  //(such as an express permission to practice a patent or covenant not to  
503  //sue for patent infringement).  To "grant" such a patent license to a              Tcl_AppendToObj(rv, "0", -1);
504  //party means to make such an agreement or commitment not to enforce a          
505  //patent against the party.              //Force the buffer to have enough space for the components of the rational
506  //              //number.
507  //  If you convey a covered work, knowingly relying on a patent license,              chars_reqd = INTFUNC_max(
508  //and the Corresponding Source of the work is not available for anyone                                      GMP_INTS_mpz_size_in_base_10(&(neighbor_data.norm_rn.num)),
509  //to copy, free of charge and under the terms of this License, through a                                      GMP_INTS_mpz_size_in_base_10(&(neighbor_data.norm_rn.den))
510  //publicly available network server or other readily accessible means,                                      );
511  //then you must either (1) cause the Corresponding Source to be so              if (chars_reqd > string_result_n_allocd)
512  //available, or (2) arrange to deprive yourself of the benefit of the                 {
513  //patent license for this particular work, or (3) arrange, in a manner                 string_result_n_allocd = chars_reqd;
514  //consistent with the requirements of this License, to extend the patent                 string_result = TclpRealloc(string_result, sizeof(char) * string_result_n_allocd);
515  //license to downstream recipients.  "Knowingly relying" means you have                 assert(string_result != NULL);
516  //actual knowledge that, but for the patent license, your conveying the                 }
517  //covered work in a country, or your recipient's use of the covered work  
518  //in a country, would infringe one or more identifiable patents in that              //Print the rational number out to the Tcl object.
519  //country that you have reason to believe are valid.              Tcl_AppendToObj(rv, " ", -1);
520  //              GMP_INTS_mpz_to_string(string_result, &(neighbor_data.norm_rn.num));
521  //  If, pursuant to or in connection with a single transaction or              Tcl_AppendToObj(rv, string_result, -1);
522  //arrangement, you convey, or propagate by procuring conveyance of, a              Tcl_AppendToObj(rv, "/", -1);
523  //covered work, and grant a patent license to some of the parties              GMP_INTS_mpz_to_string(string_result, &(neighbor_data.norm_rn.den));
524  //receiving the covered work authorizing them to use, propagate, modify              Tcl_AppendToObj(rv, string_result, -1);
525  //or convey a specific copy of the covered work, then the patent license              }
526  //you grant is automatically extended to all recipients of the covered  
527  //work and works based on it.           //Loop through, spitting out the right neighbors.
528  //           for (i = 0; i < neighbor_data.n_right_out; i++)
529  //  A patent license is "discriminatory" if it does not include within              {
530  //the scope of its coverage, prohibits the exercise of, or is              //The protocol here is everyone spits out one space before
531  //conditioned on the non-exercise of one or more of the rights that are              //they print anything.  Must skip this on first loop iteration.
532  //specifically granted under this License.  You may not convey a covered              if (neighbor_data.n_left_out || neighbor_data.equality || i)
533  //work if you are a party to an arrangement with a third party that is                 Tcl_AppendToObj(rv, " ", -1);
534  //in the business of distributing software, under which you make payment  
535  //to the third party based on the extent of your activity of conveying              //The index will be the iteration variable plus one.
536  //the work, and under which the third party grants, to any of the              sprintf(sbuf, "%d", i+1);
537  //parties who would receive the covered work from you, a discriminatory              Tcl_AppendToObj(rv, sbuf, -1);
538  //patent license (a) in connection with copies of the covered work              
539  //conveyed by you (or copies made from those copies), or (b) primarily              //Force the buffer to have enough space for the components of the rational
540  //for and in connection with specific products or compilations that              //number.
541  //contain the covered work, unless you entered into that arrangement,              chars_reqd = INTFUNC_max(
542  //or that patent license was granted, prior to 28 March 2007.                                      GMP_INTS_mpz_size_in_base_10(&(neighbor_data.rights[i].neighbor.num)),
543  //                                      GMP_INTS_mpz_size_in_base_10(&(neighbor_data.rights[i].neighbor.den))
544  //  Nothing in this License shall be construed as excluding or limiting                                      );
545  //any implied license or other defenses to infringement that may              if (chars_reqd > string_result_n_allocd)
546  //otherwise be available to you under applicable patent law.                 {
547  //                 string_result_n_allocd = chars_reqd;
548  //  12. No Surrender of Others' Freedom.                 string_result = TclpRealloc(string_result, sizeof(char) * string_result_n_allocd);
549  //                 assert(string_result != NULL);
550  //  If conditions are imposed on you (whether by court order, agreement or                 }
551  //otherwise) that contradict the conditions of this License, they do not  
552  //excuse you from the conditions of this License.  If you cannot convey a              //Print the rational number out to the Tcl object.
553  //covered work so as to satisfy simultaneously your obligations under this              Tcl_AppendToObj(rv, " ", -1);
554  //License and any other pertinent obligations, then as a consequence you may              GMP_INTS_mpz_to_string(string_result, &(neighbor_data.rights[i].neighbor.num));
555  //not convey it at all.  For example, if you agree to terms that obligate you              Tcl_AppendToObj(rv, string_result, -1);
556  //to collect a royalty for further conveying from those to whom you convey              Tcl_AppendToObj(rv, "/", -1);
557  //the Program, the only way you could satisfy both those terms and this              GMP_INTS_mpz_to_string(string_result, &(neighbor_data.rights[i].neighbor.den));
558  //License would be to refrain entirely from conveying the Program.              Tcl_AppendToObj(rv, string_result, -1);
559  //              }
560  //  13. Use with the GNU Affero General Public License.  
561  //           //Set up for a normal return.
562  //  Notwithstanding any other provision of this License, you have           Tcl_SetObjResult(interp, rv);
563  //permission to link or combine any covered work with a work licensed  
564  //under version 3 of the GNU Affero General Public License into a single           TclpFree(string_result);
565  //combined work, and to convey the resulting work.  The terms of this           GMP_RALG_consecutive_fab_terms_result_free(&neighbor_data);
566  //License will continue to apply to the part which is the covered work,           GMP_RATS_mpq_clear(&q_rn);
567  //but the special requirements of the GNU Affero General Public License,           GMP_INTS_mpz_clear(&z_kmax);
568  //section 13, concerning interaction through a network will apply to the           GMP_INTS_mpz_clear(&z_hmax);
569  //combination as such.  
570  //           return(TCL_OK);
571  //  14. Revised Versions of this License.           }
572  //        else if (pred_option_specified)
573  //  The Free Software Foundation may publish revised and/or new versions of           {
574  //the GNU General Public License from time to time.  Such new versions will           //Simple predecessor case.
575  //be similar in spirit to the present version, but may differ in detail to  
576  //address new problems or concerns.           GMP_RALG_fab_neighbor_collection_struct neighbor_data;
577  //  
578  //  Each version is given a distinguishing version number.  If the           //Form up the neighbor data.      
579  //Program specifies that a certain numbered version of the GNU General           GMP_RALG_consecutive_fab_terms(
580  //Public License "or any later version" applies to it, you have the                                         &q_rn,
581  //option of following the terms and conditions either of that numbered                                         &z_kmax,
582  //version or of any later version published by the Free Software                                         &z_hmax,
583  //Foundation.  If the Program does not specify a version number of the                                         1,
584  //GNU General Public License, you may choose any version ever published                                         0,
585  //by the Free Software Foundation.                                         &neighbor_data
586  //                                         );
587  //  If the Program specifies that a proxy can decide which future  
588  //versions of the GNU General Public License can be used, that proxy's           //If there was an error forming up the neighbor data or there are no left neighbors,
589  //public statement of acceptance of a version permanently authorizes you           //create a hard error.
590  //to choose that version for the Program.           if (neighbor_data.error || !neighbor_data.n_left_out)
591  //              {
592  //  Later license versions may give you additional or different              rv = Tcl_NewStringObj("arbint cfbrapab: unable to find predecessor.", -1);
593  //permissions.  However, no additional obligations are imposed on any              Tcl_SetObjResult(interp, rv);
594  //author or copyright holder as a result of your choosing to follow a  
595  //later version.              GMP_RALG_consecutive_fab_terms_result_free(&neighbor_data);
596  //              GMP_RATS_mpq_clear(&q_rn);
597  //  15. Disclaimer of Warranty.              GMP_INTS_mpz_clear(&z_kmax);
598  //              GMP_INTS_mpz_clear(&z_hmax);
599  //  THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY  
600  //APPLICABLE LAW.  EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT              return(TCL_ERROR);
601  //HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY              }
602  //OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,  
603  //THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR           //The test above confirmed that we have at least one left neighbor calculated.
604  //PURPOSE.  THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM           //We can dump it to a string and finish up.
605  //IS WITH YOU.  SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF           chars_reqd = INTFUNC_max(
606  //ALL NECESSARY SERVICING, REPAIR OR CORRECTION.                                   GMP_INTS_mpz_size_in_base_10(&(neighbor_data.lefts[0].neighbor.num)),
607  //                                   GMP_INTS_mpz_size_in_base_10(&(neighbor_data.lefts[0].neighbor.den))
608  //  16. Limitation of Liability.                                   );
609  //           string_result = TclpAlloc(sizeof(char) * chars_reqd);
610  //  IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING           assert(string_result != NULL);
611  //WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS  
612  //THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY           GMP_INTS_mpz_to_string(string_result, &(neighbor_data.lefts[0].neighbor.num));
613  //GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE           rv = Tcl_NewStringObj(string_result, -1);
614  //USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF           Tcl_AppendToObj(rv, "/", -1);
615  //DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD           GMP_INTS_mpz_to_string(string_result, &(neighbor_data.lefts[0].neighbor.den));
616  //PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),           Tcl_AppendToObj(rv, string_result, -1);
617  //EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF  
618  //SUCH DAMAGES.           Tcl_SetObjResult(interp, rv);
619  //  
620  //  17. Interpretation of Sections 15 and 16.           TclpFree(string_result);
621  //           GMP_RALG_consecutive_fab_terms_result_free(&neighbor_data);
622  //  If the disclaimer of warranty and limitation of liability provided           GMP_RATS_mpq_clear(&q_rn);
623  //above cannot be given local legal effect according to their terms,           GMP_INTS_mpz_clear(&z_kmax);
624  //reviewing courts shall apply local law that most closely approximates           GMP_INTS_mpz_clear(&z_hmax);
625  //an absolute waiver of all civil liability in connection with the  
626  //Program, unless a warranty or assumption of liability accompanies a           return(TCL_OK);
627  //copy of the Program in return for a fee.           }
628  //        else if (succ_option_specified)
629  //                     END OF TERMS AND CONDITIONS           {
630  //           //Simple successor.
631  //            How to Apply These Terms to Your New Programs  
632  //           GMP_RALG_fab_neighbor_collection_struct neighbor_data;
633  //  If you develop a new program, and you want it to be of the greatest  
634  //possible use to the public, the best way to achieve this is to make it           //Form up the neighbor data.      
635  //free software which everyone can redistribute and change under these terms.           GMP_RALG_consecutive_fab_terms(
636  //                                         &q_rn,
637  //  To do so, attach the following notices to the program.  It is safest                                         &z_kmax,
638  //to attach them to the start of each source file to most effectively                                         &z_hmax,
639  //state the exclusion of warranty; and each file should have at least                                         0,
640  //the "copyright" line and a pointer to where the full notice is found.                                         1,
641  //                                         &neighbor_data
642  //    <one line to give the program's name and a brief idea of what it does.>                                         );
643  //    Copyright (C) <year>  <name of author>  
644  //           //If there was an error forming up the neighbor data or there are no right neighbors,
645  //    This program is free software: you can redistribute it and/or modify           //create a hard error.
646  //    it under the terms of the GNU General Public License as published by           if (neighbor_data.error || !neighbor_data.n_right_out)
647  //    the Free Software Foundation, either version 3 of the License, or              {
648  //    (at your option) any later version.              rv = Tcl_NewStringObj("arbint cfbrapab: unable to find successor.", -1);
649  //              Tcl_SetObjResult(interp, rv);
650  //    This program is distributed in the hope that it will be useful,  
651  //    but WITHOUT ANY WARRANTY; without even the implied warranty of              GMP_RALG_consecutive_fab_terms_result_free(&neighbor_data);
652  //    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the              GMP_RATS_mpq_clear(&q_rn);
653  //    GNU General Public License for more details.              GMP_INTS_mpz_clear(&z_kmax);
654  //              GMP_INTS_mpz_clear(&z_hmax);
655  //    You should have received a copy of the GNU General Public License  
656  //    along with this program.  If not, see <http://www.gnu.org/licenses/>.              return(TCL_ERROR);
657  //              }
658  //Also add information on how to contact you by electronic and paper mail.  
659  //           //The test above confirmed that we have at least one right neighbor calculated.
660  //  If the program does terminal interaction, make it output a short           //We can dump it to a string and finish up.
661  //notice like this when it starts in an interactive mode:           chars_reqd = INTFUNC_max(
662  //                                   GMP_INTS_mpz_size_in_base_10(&(neighbor_data.rights[0].neighbor.num)),
663  //    <program>  Copyright (C) <year>  <name of author>                                   GMP_INTS_mpz_size_in_base_10(&(neighbor_data.rights[0].neighbor.den))
664  //    This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.                                   );
665  //    This is free software, and you are welcome to redistribute it           string_result = TclpAlloc(sizeof(char) * chars_reqd);
666  //    under certain conditions; type `show c' for details.           assert(string_result != NULL);
667  //  
668  //The hypothetical commands `show w' and `show c' should show the appropriate           GMP_INTS_mpz_to_string(string_result, &(neighbor_data.rights[0].neighbor.num));
669  //parts of the General Public License.  Of course, your program's commands           rv = Tcl_NewStringObj(string_result, -1);
670  //might be different; for a GUI interface, you would use an "about box".           Tcl_AppendToObj(rv, "/", -1);
671  //           GMP_INTS_mpz_to_string(string_result, &(neighbor_data.rights[0].neighbor.den));
672  //  You should also get your employer (if you work as a programmer) or school,           Tcl_AppendToObj(rv, string_result, -1);
673  //if any, to sign a "copyright disclaimer" for the program, if necessary.  
674  //For more information on this, and how to apply and follow the GNU GPL, see           Tcl_SetObjResult(interp, rv);
675  //<http://www.gnu.org/licenses/>.  
676  //           TclpFree(string_result);
677  //  The GNU General Public License does not permit incorporating your program           GMP_RALG_consecutive_fab_terms_result_free(&neighbor_data);
678  //into proprietary programs.  If your program is a subroutine library, you           GMP_RATS_mpq_clear(&q_rn);
679  //may consider it more useful to permit linking proprietary applications with           GMP_INTS_mpz_clear(&z_kmax);
680  //the library.  If this is what you want to do, use the GNU Lesser General           GMP_INTS_mpz_clear(&z_hmax);
681  //Public License instead of this License.  But first, please read  
682  //<http://www.gnu.org/philosophy/why-not-lgpl.html>.           return(TCL_OK);
683  //-------------------------------------------------------------------------------------------------           }
684  //--------------------------------------------------------------------------------  
685  #define MODULE_ARBLENINTS        //Free up all dynamic memory.
686          GMP_RATS_mpq_clear(&q_rn);
687  #include <assert.h>        GMP_INTS_mpz_clear(&z_kmax);
688  #include <string.h>        GMP_INTS_mpz_clear(&z_hmax);
689    
690  #include "tcl.h"        //Return
691  #include "tcldecls.h"        return(TCL_OK);
692          }
693  #include "arblenints.h"     }
694  #include "bstrfunc.h"  
695  #include "extninit.h"  
696  #include "gmp_ints.h"  //Handles the "cfratnum" subextension.
697  #include "gmp_rats.h"  //08/07/01:  Visually inspected, OK.
698  #include "gmp_ralg.h"  static
699  #include "intfunc.h"  int ARBLENINTS_cfratnum_handler(ClientData dummy,
700  #include "tclalloc.h"                                Tcl_Interp *interp,
701                                  int objc,
702                                  Tcl_Obj *objv[])
703  //Handles the "cfbrapab" subextension.     {
704  //08/16/01: Visual inspection OK.     Tcl_Obj *rv;
705  static  
706  int ARBLENINTS_cfbrapab_handler(ClientData dummy,     //We must have exactly one additional argument
707                                  Tcl_Interp *interp,     //to this function, which is the rational number
708                                  int objc,     //whose continued fraction decomposition is to be
709                                  Tcl_Obj *objv[])     //calculated.
710     {     if (objc != 3)
711     Tcl_Obj *rv;        {
712          Tcl_WrongNumArgs(interp,
713     //We must have at least two additional arguments                         2,
714     //to this extension.                         objv,
715     if (objc < 4)                         "urn");
716        {        return(TCL_ERROR);
717        Tcl_WrongNumArgs(interp,        }
718                         2,     else
719                         objv,        {
720                         "srn uint_kmax ?uint_hmax? ?options?");        char *input_arg;
721        return(TCL_ERROR);        int failure;
722        }        unsigned chars_reqd;
723     else        char *string_result;
724        {        int n_string_result;
725        char *input_arg;        int i;
726        int failure, first_dashed_parameter;        GMP_RATS_mpq_struct rn;
727        char *string_result;        GMP_RALG_cf_app_struct decomp;
728        int string_result_n_allocd;  
729        int chars_reqd;        //In this function, we are going to return a string
730        int i;        //result formed by starting with a string and then
731        int pred_option_specified         = 0;        //concatenating  to it again and again.  We start
732        int succ_option_specified         = 0;        //off believing that 10,000 characters of space is enough,
733        int neversmaller_option_specified = 0;        //but we may need to revise upward and reallocate.  
734        int neverlarger_option_specified  = 0;        //A 10,000 character block is chosen because it is quick
735        int n_option_specified            = 0;        //to allocate and most times won't go beyond that.
736        unsigned n                        = 0;        n_string_result = 10000;
737          string_result = TclpAlloc(sizeof(char) * n_string_result);
738        GMP_RATS_mpq_struct q_rn;        assert(string_result != NULL);
739        GMP_INTS_mpz_struct z_kmax;  
740        GMP_INTS_mpz_struct z_hmax;        //We will need a rational number to hold the return value
741          //from the parsing function.  Allocate that now.
742        //Allocate dynamic memory.        GMP_RATS_mpq_init(&rn);
743        GMP_RATS_mpq_init(&q_rn);  
744        GMP_INTS_mpz_init(&z_kmax);        //Grab a pointer to the string representation of
745        GMP_INTS_mpz_init(&z_hmax);        //the input argument.  The storage does not belong to us.
746          input_arg = Tcl_GetString(objv[2]);
747        //Grab a pointer to the string representation of        assert(input_arg != NULL);
748        //the first input argument.  The storage does not belong to us.  
749        input_arg = Tcl_GetString(objv[2]);        //Try to parse our input string as a rational number.
750        assert(input_arg != NULL);        //If we are not successful in this, must abort.
751          GMP_RATS_mpq_set_all_format_rat_num(input_arg,
752        //Try to parse our first input string as a rational number.                                            &failure,
753        //If we are not successful in this, must abort.                                            &rn);
754        GMP_RATS_mpq_set_all_format_rat_num(input_arg,  
755                                            &failure,        if (failure)
756                                            &q_rn);           {
757             rv = Tcl_NewStringObj("arbint cfratnum: \"", -1);
758        if (failure)           Tcl_AppendToObj(rv, input_arg, -1);
759           {  
760           rv = Tcl_NewStringObj("arbint cfbrapab: \"", -1);           Tcl_AppendToObj(rv, "\" is not a recognized non-negative rational number.", -1);
761           Tcl_AppendToObj(rv, input_arg, -1);           Tcl_SetObjResult(interp, rv);
762    
763           Tcl_AppendToObj(rv, "\" is not a recognized rational number.", -1);           TclpFree(string_result);
764           Tcl_SetObjResult(interp, rv);           GMP_RATS_mpq_clear(&rn);
765    
766           GMP_RATS_mpq_clear(&q_rn);           return(TCL_ERROR);
767           GMP_INTS_mpz_clear(&z_kmax);           }
768           GMP_INTS_mpz_clear(&z_hmax);  
769          //OK, we have a rational number, but there is a possibility
770           return(TCL_ERROR);        //it is negative, which is a no-no.  Normalize the signs
771           }        //for easier testing.
772          GMP_RATS_mpq_normalize_sign(&rn);
773        //Try to parse our next argument as an integer, which        if (GMP_INTS_mpz_is_neg(&(rn.num)))
774        //will be KMAX.  This must be specified.           {
775        //           rv = Tcl_NewStringObj("arbint cfratnum: \"", -1);
776        //Get string pointer.  Storage does not belong to us.           Tcl_AppendToObj(rv, input_arg, -1);
777        input_arg = Tcl_GetString(objv[3]);  
778        assert(input_arg != NULL);           Tcl_AppendToObj(rv, "\" is negative.", -1);
779             Tcl_SetObjResult(interp, rv);
780        //Try to convert KMAX to an integer.  Fatal if an error,  
781        //and fatal if the argument is zero or negative.           TclpFree(string_result);
782        GMP_INTS_mpz_set_general_int(&z_kmax, &failure, input_arg);           GMP_RATS_mpq_clear(&rn);
783    
784        //If there was a parse failure or if the integer is zero           return(TCL_ERROR);
785        //or negative, must flag error.           }
786        if (failure || GMP_INTS_mpz_is_neg(&z_kmax) || GMP_INTS_mpz_is_zero(&z_kmax))  
787           {        //OK, we have a rational number.  Form the continued fraction
788           rv = Tcl_NewStringObj("arbint cfbrapab: \"", -1);        //decomposition of it.  The function called is set up so that
789           Tcl_AppendToObj(rv, input_arg, -1);        //one must deallocate, even in an error condition.
790           Tcl_AppendToObj(rv, "\" is not a recognized positive integer.", -1);        GMP_RALG_cfdecomp_init(&decomp,
791           Tcl_SetObjResult(interp, rv);                               &failure,
792                                 &(rn.num),
793           GMP_RATS_mpq_clear(&q_rn);                               &(rn.den));
794           GMP_INTS_mpz_clear(&z_kmax);  
795           GMP_INTS_mpz_clear(&z_hmax);        //If we failed in the decomposition (don't know why that would
796          //happen) use the general error flag "NAN".
797           return(TCL_ERROR);        if (failure)
798           }           {
799             rv = Tcl_NewStringObj("NAN", -1);
800        //We need to look for HMAX as the next parameter, if it exists.  
801        //The way we will figure this out is by whether the           Tcl_SetObjResult(interp, rv);
802        //parameter begins with a "-" or not.  
803        if (objc >= 5)           TclpFree(string_result);
804           {           GMP_RATS_mpq_clear(&rn);
805           input_arg = Tcl_GetString(objv[4]);           GMP_RALG_cfdecomp_destroy(&decomp);
806           assert(input_arg != NULL);  
807             return(TCL_ERROR);
808           if (input_arg[0] == '-')           }
809              {  
810              first_dashed_parameter = 4;        //OK, that really is the last error we could have.
811              }        //Iterate, adding the partial quotients and convergents
812           else        //to the string which we'll return.  We need to watch out
813              {        //for running over our 10K buffer.
814              first_dashed_parameter = 5;        rv = Tcl_NewStringObj("", -1);
815              }        for (i=0; i<decomp.n; i++)
816           }           {
817        else           //Partial quotient.
818           {           chars_reqd = GMP_INTS_mpz_size_in_base_10(&(decomp.a[i]));
819           first_dashed_parameter = 4;           if (chars_reqd > (unsigned)n_string_result)
820           }              {
821                n_string_result = chars_reqd;
822        //If there is another parameter and it              string_result = TclpRealloc(string_result,
823        //doesn't begin with a dash, try to parse                                          sizeof(char) * n_string_result);
824        //it as HMAX.  We don't explicitly record whether              }
825        //HMAX is specified, because zero is a signal           GMP_INTS_mpz_to_string(string_result, &(decomp.a[i]));
826        //when calculating Farey neighbors that HMAX isn't           Tcl_AppendToObj(rv, string_result, -1);
827        //to be considered.           Tcl_AppendToObj(rv, " ", -1);
828        if ((objc >= 5) && (first_dashed_parameter == 5))  
829           {           //Numerator of convergent.
830           //Get string pointer.  Storage does not belong to us.           chars_reqd = GMP_INTS_mpz_size_in_base_10(&(decomp.p[i]));
831           input_arg = Tcl_GetString(objv[4]);           if (chars_reqd > (unsigned)n_string_result)
832           assert(input_arg != NULL);              {
833                n_string_result = chars_reqd;
834           //Try to convert HMAX to an integer.  Fatal if an error,              string_result = TclpRealloc(string_result,
835           //and fatal if the argument is zero or negative.                                          sizeof(char) * n_string_result);
836           GMP_INTS_mpz_set_general_int(&z_hmax, &failure, input_arg);              }
837             GMP_INTS_mpz_to_string(string_result, &(decomp.p[i]));
838           //If there was a parse failure or if the integer is zero           Tcl_AppendToObj(rv, string_result, -1);
839           //or negative, must flag error.           Tcl_AppendToObj(rv, " ", -1);
840           if (failure || GMP_INTS_mpz_is_neg(&z_hmax) || GMP_INTS_mpz_is_zero(&z_hmax))  
841              {           //Denominator of convergent.
842              rv = Tcl_NewStringObj("arbint cfbrapab: \"", -1);           chars_reqd = GMP_INTS_mpz_size_in_base_10(&(decomp.q[i]));
843              Tcl_AppendToObj(rv, input_arg, -1);           if (chars_reqd > (unsigned)n_string_result)
844              Tcl_AppendToObj(rv, "\" is not a recognized positive integer.", -1);              {
845              Tcl_SetObjResult(interp, rv);              n_string_result = chars_reqd;
846                string_result = TclpRealloc(string_result,
847              GMP_RATS_mpq_clear(&q_rn);                                          sizeof(char) * n_string_result);
848              GMP_INTS_mpz_clear(&z_kmax);              }
849              GMP_INTS_mpz_clear(&z_hmax);           GMP_INTS_mpz_to_string(string_result, &(decomp.q[i]));
850             Tcl_AppendToObj(rv, string_result, -1);
851              return(TCL_ERROR);           if (i != (decomp.n - 1)) //No space after last number.
852              }              Tcl_AppendToObj(rv, " ", -1);
853           }           }
854    
855        //Process all of the dashed command-line arguments.        //Assign the result to be the return value.
856        //This involves iterating through all of the        Tcl_SetObjResult(interp, rv);
857        //parameters and processing them.  
858        for (i=first_dashed_parameter; i<objc; i++)        //Free up all dynamic memory.
859           {        TclpFree(string_result);
860           input_arg = Tcl_GetString(objv[i]);        GMP_RATS_mpq_clear(&rn);
861           assert(input_arg != NULL);        GMP_RALG_cfdecomp_destroy(&decomp);
862    
863           if (!strcmp("-pred", input_arg))        //Return
864              {        return(TCL_OK);
865              pred_option_specified = 1;        }
866              }     }
867           else if (!strcmp("-succ", input_arg))  
868              {  
869              succ_option_specified = 1;  //Handles the "commanate" subextension.
870              }  //07/29/01:  Visual inspection OK.  Have not located my Tcl book, am doing this
871           else if (!strcmp("-neversmaller", input_arg))  //from memory an intuition as far as how to set return results and so forth.
872              {  static
873              neversmaller_option_specified = 1;  int ARBLENINTS_commanate_handler(ClientData dummy,
874              }                                Tcl_Interp *interp,
875           else if (!strcmp("-neverlarger", input_arg))                                int objc,
876              {                                Tcl_Obj *objv[])
877              neverlarger_option_specified = 1;     {
878              }     Tcl_Obj *rv;
879           else if (!strcmp("-n", input_arg))  
880              {     //We must have one and exactly one additional argument
881              n_option_specified = 1;     //to this function, which is the string we want to
882       //commanate.
883              //If -n was specified, there must be a following     if (objc != 3)
884              //parameter which supplies the integer.  First        {
885              //check for existence of an additional parameter.        Tcl_WrongNumArgs(interp,
886              if (i >= (objc - 1))                         2,
887                 {                         objv,
888                 rv = Tcl_NewStringObj("arbint cfbrapab: -n option specified without following integer.", -1);                         "sint");
889                 Tcl_SetObjResult(interp, rv);        return(TCL_ERROR);
890          }
891                 GMP_RATS_mpq_clear(&q_rn);     else
892                 GMP_INTS_mpz_clear(&z_kmax);        {
893                 GMP_INTS_mpz_clear(&z_hmax);        char *string_arg;
894    
895                 return(TCL_ERROR);        //Grab a pointer to the string representation of
896                 }        //the input argument.  The storage does not belong to us.
897          string_arg = Tcl_GetString(objv[2]);
898              //We have at least one additional parameter.  Try        assert(string_arg != NULL);
899              //to parse out the next parameter as the integer  
900              //we need for n.        //Try to parse the string as one of the error tags.
901              i++;        //If it is one of those, it isn't an error, but don't
902          //want to touch the string.
903              input_arg = Tcl_GetString(objv[i]);        if (GMP_INTS_identify_nan_string(string_arg) >= 0)
904              assert(input_arg != NULL);           {
905             rv = Tcl_NewStringObj(string_arg, -1);
906              GMP_INTS_mpz_parse_into_uint32(&n, &failure, input_arg);           Tcl_SetObjResult(interp, rv);
907             return(TCL_OK);
908              //If the parse was unsuccessful, terminate.           }
909              if (failure)        //Try to parse it as a signed integer with commas already.
910                 {        //If it already has commas, there is no need to add any.
911                 rv = Tcl_NewStringObj("arbint cfbrapab: -n option followed by invalid integer.", -1);        else if (BSTRFUNC_is_sint_w_commas(string_arg))
912                 Tcl_SetObjResult(interp, rv);           {
913             //This is already an acceptable commanated signed integer.  Send it
914                 GMP_RATS_mpq_clear(&q_rn);           //back as the return value.
915                 GMP_INTS_mpz_clear(&z_kmax);           rv = Tcl_NewStringObj(string_arg, -1);
916                 GMP_INTS_mpz_clear(&z_hmax);           Tcl_SetObjResult(interp, rv);
917             return(TCL_OK);
918                 return(TCL_ERROR);           }
919                 }        //Try to parse the argument as a signed integer without commas.
920          //If it is one of those, commanate it and return it.
921              //Clip the integer into a 24-bit quantity.        else if (BSTRFUNC_is_sint_wo_commas(string_arg))
922              n &= 0x00FFFFFF;           {
923              }           size_t len;
924           else           char *buffer;
925              {  
926              //Unrecognized option.  Crash out.           len = strlen(string_arg);
927              rv = Tcl_NewStringObj("arbint cfbrapab: \"", -1);           buffer = TclpAlloc(((sizeof(char) * 4 * len) / 3) + 10);
928              Tcl_AppendToObj(rv, input_arg, -1);           strcpy(buffer, string_arg);
929              Tcl_AppendToObj(rv, "\" is not a recognized option.", -1);           BSTRFUNC_commanate(buffer);
930              Tcl_SetObjResult(interp, rv);           rv = Tcl_NewStringObj(buffer, -1);
931             TclpFree(buffer);
932              GMP_RATS_mpq_clear(&q_rn);           Tcl_SetObjResult(interp, rv);
933              GMP_INTS_mpz_clear(&z_kmax);           return(TCL_OK);
934              GMP_INTS_mpz_clear(&z_hmax);           }
935          else
936              return(TCL_ERROR);           {
937              }           //Error case.  Must give error message.
938           }           rv = Tcl_NewStringObj("arbint commanate: \"", -1);
939             Tcl_AppendToObj(rv, string_arg, -1);
940        //Look for any mutually exclusive options.  Give a catchall if any of           Tcl_AppendToObj(rv, "\" is not a recognized integer.", -1);
941        //them specified.  Because we set them all to 1, addition is the easiest           Tcl_SetObjResult(interp, rv);
942        //way to do this.           return(TCL_ERROR);
943        if ((pred_option_specified + succ_option_specified + neversmaller_option_specified           }
944             + neverlarger_option_specified + n_option_specified) > 1)        }
945           {     }
946           rv = Tcl_NewStringObj("arbint cfbrapab: -pred, -succ, -neversmaller, -neverlarger, and -n are mutually exclusive options.", -1);  
947           Tcl_SetObjResult(interp, rv);  
948    //Handles the "const" subextension.
949           GMP_RATS_mpq_clear(&q_rn);  //08/17/01: Visual inspection OK.
950           GMP_INTS_mpz_clear(&z_kmax);  static
951           GMP_INTS_mpz_clear(&z_hmax);  int ARBLENINTS_const_handler(ClientData dummy,
952                                 Tcl_Interp *interp,
953           return(TCL_ERROR);                               int objc,
954           }                               Tcl_Obj *objv[])
955       {
956        //Split into cases based on what we're doing.  This is wasteful of code,     //Table of constants used.
957        //but this is a PC application, not an embedded application.  In all cases     static struct
958        //create a hard error if something goes wrong.  Any anomalies should trash        {
959        //a script.        char *tag;
960        if (!pred_option_specified && !succ_option_specified && !n_option_specified)           //The symbolic tag used to identify the number.
961           {        char *desc;
962           //This is the traditional best approximation case, with the possibility of           //The full description of the number.  It must consist
963           //the -neverlarger or -neversmaller being specified.  This is the most messy           //of a string with lines no longer than about 70 chars,
964           //of all the cases.  We must gather neighbors and figure out which is closer,           //separated by newlines, and indented by 6 spaces.
965           //and if there is a tie, which has the smaller magnitude.  It is fairly        char *minmant;
966           //messy.           //The minimum mantissa or minimum representation.
967           GMP_RALG_fab_neighbor_collection_struct neighbor_data;           //May not be empty or NULL.
968           GMP_RATS_mpq_struct left_neigh, right_neigh, diff_left, diff_right, closer_neighbor;        char *mantrem;
969           int dist_cmp;           //The remaining mantissa or remaining portion of
970           int mag_cmp;           //number.  May be empty, but may not be NULL.
971          char *exp;
972           //Allocate inner dynamic variables.           //The exponent portion, if any, or NULL otherwise.
973           GMP_RATS_mpq_init(&left_neigh);        int deflen;
974           GMP_RATS_mpq_init(&right_neigh);           //The default number of digits for the constant
975           GMP_RATS_mpq_init(&diff_left);           //if none is specified.
976           GMP_RATS_mpq_init(&diff_right);        int digit_count_offset;
977           GMP_RATS_mpq_init(&closer_neighbor);           //The offset to go from string length of mantissa
978             //portions to number of digits.  Cheap way to adjust
979           //Form up the neighbor data.  We're only looking for up to one neighbor on each           //for - sign and decimal point.
980           //side.        } tbl[] =
981           GMP_RALG_consecutive_fab_terms(        {
982                                         &q_rn,        //e--the transcendental number e.
983                                         &z_kmax,           {
984                                         &z_hmax,           //tag
985                                         1,           "e",
986                                         1,           //desc
987                                         &neighbor_data           "      Historically significant transcendental constant.  Digits obtained\n"
988                                         );           "      from http://fermi.udw.ac.za/physics/e.html on 08/17/01.",
989             //minmant
990           //If there was an error or we couldn't get any neighbors to play with, give           "2.7",
991           //an error return.  As long as we have one neighbor on either side, we can definitely           //mantrem
992           //complete.           "182818284590452353602874713526624977572470936999595749669676277240766303535"
993           if (neighbor_data.error || (!neighbor_data.equality && (!neighbor_data.n_left_out || !neighbor_data.n_right_out)))           "475945713821785251664274274663919320030599218174135966290435729003342952605956"
994              {           "307381323286279434907632338298807531952510190115738341879307021540891499348841"
995              rv = Tcl_NewStringObj("arbint cfbrapab: unable to form neighbors.", -1);           "675092447614606680822648001684774118537423454424371075390777449920695517027618"
996              Tcl_SetObjResult(interp, rv);           "386062613313845830007520449338265602976067371132007093287091274437470472306969"
997             "772093101416928368190255151086574637721112523897844250569536967707854499699679"
998              GMP_RALG_consecutive_fab_terms_result_free(&neighbor_data);           "468644549059879316368892300987931277361782154249992295763514822082698951936680"
999              GMP_RATS_mpq_clear(&q_rn);           "331825288693984964651058209392398294887933203625094431173012381970684161403970"
1000              GMP_INTS_mpz_clear(&z_kmax);           "198376793206832823764648042953118023287825098194558153017567173613320698112509"
1001              GMP_INTS_mpz_clear(&z_hmax);           "961818815930416903515988885193458072738667385894228792284998920868058257492796"
1002             "104841984443634632449684875602336248270419786232090021609902353043699418491463"
1003              GMP_RATS_mpq_clear(&left_neigh);           "140934317381436405462531520961836908887070167683964243781405927145635490613031"
1004              GMP_RATS_mpq_clear(&right_neigh);           "07208510383750510115747704171898610687396965521267154688957035035",
1005              GMP_RATS_mpq_clear(&diff_left);           //exp
1006              GMP_RATS_mpq_clear(&diff_right);           NULL,
1007              GMP_RATS_mpq_clear(&closer_neighbor);           //deflen
1008             30,
1009              return(TCL_ERROR);           //digit_count_offset
1010              }           1
1011             },
1012           if (neighbor_data.equality)        //g_metric
1013              {           {
1014              //The equality case takes precedence, always.           //tag
1015              GMP_RATS_mpq_copy(&closer_neighbor, &(neighbor_data.norm_rn));           "g_si",
1016              }           //desc
1017           else           "      Gravitational acceleration in SI units, meters per second**2.\n"
1018              {           "      Obtained from NIST Special Publication 811 on 08/17/01.",
1019              //The boolean test somewhat above guaranteed that we have both left           //minmant
1020              //and right neighbors.  We can assume this.           "9.80665",
1021              GMP_RATS_mpq_copy(&left_neigh,  &(neighbor_data.lefts[0].neighbor));           //mantrem
1022              GMP_RATS_mpq_copy(&right_neigh, &(neighbor_data.rights[0].neighbor));           "",
1023             //exp
1024              GMP_RATS_mpq_sub(&diff_left,  &left_neigh,  &(neighbor_data.norm_rn));           NULL,
1025              GMP_RATS_mpq_sub(&diff_right, &right_neigh, &(neighbor_data.norm_rn));           //deflen
1026              GMP_INTS_mpz_abs(&(diff_left.num));           30,
1027              GMP_INTS_mpz_abs(&(diff_right.num));           //digit_count_offset
1028              dist_cmp = GMP_RATS_mpq_cmp(&diff_left, &diff_right, NULL);           1
1029             },
1030              //If we have a tie on the distance, will need to revert to magnitude of the neighbors.        //in2m
1031              GMP_INTS_mpz_abs(&(left_neigh.num));           {
1032              GMP_INTS_mpz_abs(&(right_neigh.num));           //tag
1033              mag_cmp = GMP_RATS_mpq_cmp(&left_neigh, &right_neigh, NULL);           "in2m",
1034             //desc
1035              if (!neversmaller_option_specified           "      Multiplicative conversion factor from inches to meters.\n"
1036                 &&           "      Obtained from NIST Special Publication 811 on 08/17/01.",
1037                 (neverlarger_option_specified || (dist_cmp < 0) || ((dist_cmp==0) && (mag_cmp < 0))))           //minmant
1038                 {           "2.54",
1039                 GMP_RATS_mpq_copy(&closer_neighbor, &(neighbor_data.lefts[0].neighbor));           //mantrem
1040                 }           "",
1041              else           //exp
1042                 {           "e-2",
1043                 GMP_RATS_mpq_copy(&closer_neighbor, &(neighbor_data.rights[0].neighbor));           //deflen
1044                 }           30,
1045              }           //digit_count_offset
1046             1
1047           //Stuff our variable of choice into a string ...           },
1048           chars_reqd = INTFUNC_max(        //mi2km
1049                                   GMP_INTS_mpz_size_in_base_10(&(closer_neighbor.num)),           {
1050                                   GMP_INTS_mpz_size_in_base_10(&(closer_neighbor.den))           //tag
1051                                   );           "mi2km",
1052           string_result = TclpAlloc(sizeof(char) * chars_reqd);           //desc
1053           assert(string_result != NULL);           "      Multiplicative conversion factor from miles to kilometers.\n"
1054             "      Obtained from NIST Special Publication 811 on 08/17/01.",
1055           GMP_INTS_mpz_to_string(string_result, &(closer_neighbor.num));           //minmant
1056           rv = Tcl_NewStringObj(string_result, -1);           "1.609344",
1057           Tcl_AppendToObj(rv, "/", -1);           //mantrem
1058           GMP_INTS_mpz_to_string(string_result, &(closer_neighbor.den));           "",
1059           Tcl_AppendToObj(rv, string_result, -1);           //exp
1060             NULL,
1061           Tcl_SetObjResult(interp, rv);           //deflen
1062             30,
1063           //Deallocate variables, make normal return.           //digit_count_offset
1064           TclpFree(string_result);           1
1065           GMP_RALG_consecutive_fab_terms_result_free(&neighbor_data);           },
1066           GMP_RATS_mpq_clear(&q_rn);        //pi--the transcendental number PI.
1067           GMP_INTS_mpz_clear(&z_kmax);           {
1068           GMP_INTS_mpz_clear(&z_hmax);           //tag
1069             "pi",
1070           GMP_RATS_mpq_clear(&left_neigh);           //desc
1071           GMP_RATS_mpq_clear(&right_neigh);           "      Transcendental constant supplying ratio of a circle's circumference\n"
1072           GMP_RATS_mpq_clear(&diff_left);           "      to its diameter.  Digits obtained from http://www.joyofpi.com/\n"
1073           GMP_RATS_mpq_clear(&diff_right);           "      pi.htm on 08/17/01.",
1074           GMP_RATS_mpq_clear(&closer_neighbor);           //minmant
1075             "3.14",
1076           return(TCL_OK);           //mantrem
1077           }           "15926535897932384626433832795028841971"
1078        else if (n_option_specified)           "6939937510582097494459230781640628620899"
1079           {           "8628034825342117067982148086513282306647"
1080           char sbuf[50];           "0938446095505822317253594081284811174502"
1081              //Static buffer just to stage 32-bit integers.           "8410270193852110555964462294895493038196"
1082                       "4428810975665933446128475648233786783165"
1083           //Multiple neighbors.  Must iterate through.           "2712019091456485669234603486104543266482"
1084             "1339360726024914127372458700660631558817"
1085           GMP_RALG_fab_neighbor_collection_struct neighbor_data;           "4881520920962829254091715364367892590360"
1086             "0113305305488204665213841469519415116094"
1087           //Form up the neighbor data.                 "3305727036575959195309218611738193261179"
1088           GMP_RALG_consecutive_fab_terms(           "3105118548074462379962749567351885752724"
1089                                         &q_rn,           "8912279381830119491298336733624406566430"
1090                                         &z_kmax,           "8602139494639522473719070217986094370277"
1091                                         &z_hmax,           "0539217176293176752384674818467669405132"
1092                                         n,           "0005681271452635608277857713427577896091"
1093                                         n,           "7363717872146844090122495343014654958537"
1094                                         &neighbor_data           "1050792279689258923542019956112129021960"
1095                                         );           "8640344181598136297747713099605187072113"
1096             "4999999837297804995105973173281609631859"
1097           //If there was an error forming up the neighbor data, create a hard error.           "5024459455346908302642522308253344685035"
1098           if (neighbor_data.error)           "2619311881710100031378387528865875332083"
1099              {           "8142061717766914730359825349042875546873"
1100              rv = Tcl_NewStringObj("arbint cfbrapab: unable to form neighbors.", -1);           "1159562863882353787593751957781857780532"
1101              Tcl_SetObjResult(interp, rv);           "1712268066130019278766111959092164201989"
1102             "3809525720106548586327886593615338182796"
1103              GMP_RALG_consecutive_fab_terms_result_free(&neighbor_data);           "8230301952035301852968995773622599413891"
1104              GMP_RATS_mpq_clear(&q_rn);           "2497217752834791315155748572424541506959"
1105              GMP_INTS_mpz_clear(&z_kmax);           "5082953311686172785588907509838175463746"
1106              GMP_INTS_mpz_clear(&z_hmax);           "4939319255060400927701671139009848824012",
1107             //exp
1108              return(TCL_ERROR);           NULL,
1109              }           //deflen
1110             30,
1111           //Allocate a default buffer of 10K for the ASCII representation of integers.           //digit_count_offset
1112           //In the vast majority of cases, there will be only one allocation, because it           1
1113           //takes a mean integer to exceed 10K.  However, the logic allows it to grow.           },
1114           string_result_n_allocd = 10000;        //sqrt5--the square root of 5.
1115           string_result = TclpAlloc(sizeof(char) * string_result_n_allocd);           {
1116           assert(string_result != NULL);           //tag
1117             "sqrt5",
1118           //Start off with a return value of the null string.           //desc
1119           rv = Tcl_NewStringObj("", -1);           "      The square root of 5.  Digits obtained from\n"
1120             "      http://home.earthlink.net/~maryski/sqrt51000000.txt on 08/17/01.",
1121           //Loop through, spitting out the left neighbors.           //minmant
1122           for (i = neighbor_data.n_left_out-1; i >= 0; i--)           "2.236",
1123              {           //mantrem
1124              //The protocol here is everyone spits out one space before           "0679774997896964091736687312762354406183596115257242708972454105209256378048"
1125              //they print anything.  Must skip this on first loop iteration.           "99414414408378782274969508176150773783504253267724447073863586360121533452708866"
1126              if (i != neighbor_data.n_left_out-1)           "77817319187916581127664532263985658053576135041753378500342339241406444208643253"
1127                 Tcl_AppendToObj(rv, " ", -1);           "90972525926272288762995174024406816117759089094984923713907297288984820886415426"
1128             "89894099131693577019748678884425089754132956183176921499977424801530434115035957"
1129              //The index will be the negative of the iteration variable minus one.           "66833251249881517813940800056242085524354223555610630634282023409333198293395974"
1130              sprintf(sbuf, "%d", -i - 1);           "63522712013417496142026359047378855043896870611356600457571399565955669569175645"
1131              Tcl_AppendToObj(rv, sbuf, -1);           "78221952500060539231234005009286764875529722056766253666074485853505262330678494"
1132                         "63342224231763727702663240768010444331582573350589309813622634319868647194698997"
1133              //Force the buffer to have enough space for the components of the rational           "01808189524264459620345221411922329125981963258111041704958070481204034559949435"
1134              //number.           "06855551855572512388641655010262436312571024449618789424682903404474716115455723"
1135              chars_reqd = INTFUNC_max(           "20173767659046091852957560357798439805415538077906439363972302875606299948221385"
1136                                      GMP_INTS_mpz_size_in_base_10(&(neighbor_data.lefts[i].neighbor.num)),           "21773485924535151210463455550407072278724215347787529112121211843317893351910380",
1137                                      GMP_INTS_mpz_size_in_base_10(&(neighbor_data.lefts[i].neighbor.den))           //exp
1138                                      );           NULL,
1139              if (chars_reqd > string_result_n_allocd)           //deflen
1140                 {           30,
1141                 string_result_n_allocd = chars_reqd;           //digit_count_offset
1142                 string_result = TclpRealloc(string_result, sizeof(char) * string_result_n_allocd);           1
1143                 assert(string_result != NULL);           },
1144                 }        };
1145          
1146              //Print the rational number out to the Tcl object.     Tcl_Obj *rv;
1147              Tcl_AppendToObj(rv, " ", -1);        //Value that will be returned to caller.
1148              GMP_INTS_mpz_to_string(string_result, &(neighbor_data.lefts[i].neighbor.num));     int i;
1149              Tcl_AppendToObj(rv, string_result, -1);        //Iteration variable.
1150              Tcl_AppendToObj(rv, "/", -1);     int tbl_idx;
1151              GMP_INTS_mpz_to_string(string_result, &(neighbor_data.lefts[i].neighbor.den));        //Index into lookup table, of -1 if not found.
1152              Tcl_AppendToObj(rv, string_result, -1);     int ndigits;
1153              }        //The number of digits to supply.
1154       int result_code;
1155           //Spit out the equality case if appropriate.        //Return value from Tcl library function.
1156           if (neighbor_data.equality)  
1157              {     //We must have either one or two additional arguments.
1158              if (neighbor_data.n_left_out)     if ((objc != 3) && (objc != 4))
1159                 Tcl_AppendToObj(rv, " ", -1);        {
1160          Tcl_WrongNumArgs(interp,
1161              Tcl_AppendToObj(rv, "0", -1);                         2,
1162                                   objv,
1163              //Force the buffer to have enough space for the components of the rational                         "constant_tag ?ndigits?");
1164              //number.        return(TCL_ERROR);
1165              chars_reqd = INTFUNC_max(        }
1166                                      GMP_INTS_mpz_size_in_base_10(&(neighbor_data.norm_rn.num)),     else
1167                                      GMP_INTS_mpz_size_in_base_10(&(neighbor_data.norm_rn.den))        {
1168                                      );        char *string_arg;
1169              if (chars_reqd > string_result_n_allocd)  
1170                 {        //Grab a pointer to the string representation of
1171                 string_result_n_allocd = chars_reqd;        //the input argument.  The storage does not belong to us.
1172                 string_result = TclpRealloc(string_result, sizeof(char) * string_result_n_allocd);        string_arg = Tcl_GetString(objv[2]);
1173                 assert(string_result != NULL);        assert(string_arg != NULL);
1174                 }  
1175          //Try to look up the string argument in the table.
1176              //Print the rational number out to the Tcl object.        tbl_idx = -1;
1177              Tcl_AppendToObj(rv, " ", -1);        for (i=0; i<sizeof(tbl)/sizeof(tbl[0]); i++)
1178              GMP_INTS_mpz_to_string(string_result, &(neighbor_data.norm_rn.num));           {
1179              Tcl_AppendToObj(rv, string_result, -1);           if (!strcmp(string_arg, tbl[i].tag))
1180              Tcl_AppendToObj(rv, "/", -1);              {
1181              GMP_INTS_mpz_to_string(string_result, &(neighbor_data.norm_rn.den));              tbl_idx = i;
1182              Tcl_AppendToObj(rv, string_result, -1);              break;
1183              }              }
1184             }
1185           //Loop through, spitting out the right neighbors.  
1186           for (i = 0; i < neighbor_data.n_right_out; i++)        //If the tag was not found in the table, print a hostile
1187              {        //message and abort.
1188              //The protocol here is everyone spits out one space before        if (tbl_idx == -1)
1189              //they print anything.  Must skip this on first loop iteration.           {
1190              if (neighbor_data.n_left_out || neighbor_data.equality || i)           char buf[100];
1191                 Tcl_AppendToObj(rv, " ", -1);  
1192             //Error case.  Must give error message.    
1193              //The index will be the iteration variable plus one.           //Must also list the constants available.
1194              sprintf(sbuf, "%d", i+1);           rv = Tcl_NewStringObj("arbint const: \"", -1);
1195              Tcl_AppendToObj(rv, sbuf, -1);           Tcl_AppendToObj(rv, string_arg, -1);
1196                         Tcl_AppendToObj(rv, "\" is not a recognized constant.\n", -1);
1197              //Force the buffer to have enough space for the components of the rational  
1198              //number.           Tcl_AppendToObj(rv, "Available constants are:\n", -1);
1199              chars_reqd = INTFUNC_max(  
1200                                      GMP_INTS_mpz_size_in_base_10(&(neighbor_data.rights[i].neighbor.num)),           for (i=0; i<sizeof(tbl)/sizeof(tbl[0]); i++)
1201                                      GMP_INTS_mpz_size_in_base_10(&(neighbor_data.rights[i].neighbor.den))              {
1202                                      );              Tcl_AppendToObj(rv, "   ", -1);
1203              if (chars_reqd > string_result_n_allocd)              Tcl_AppendToObj(rv, tbl[i].tag, -1);
1204                 {              sprintf(buf, " (%d digits available)\n",
1205                 string_result_n_allocd = chars_reqd;                      strlen(tbl[i].minmant) + strlen(tbl[i].mantrem) - tbl[i].digit_count_offset);
1206                 string_result = TclpRealloc(string_result, sizeof(char) * string_result_n_allocd);              Tcl_AppendToObj(rv, buf, -1);
1207                 assert(string_result != NULL);              Tcl_AppendToObj(rv, tbl[i].desc, -1);
1208                 }              if (i != (sizeof(tbl)/sizeof(tbl[0]) - 1))
1209                   Tcl_AppendToObj(rv, "\n", -1);
1210              //Print the rational number out to the Tcl object.              }
1211              Tcl_AppendToObj(rv, " ", -1);  
1212              GMP_INTS_mpz_to_string(string_result, &(neighbor_data.rights[i].neighbor.num));           Tcl_SetObjResult(interp, rv);
1213              Tcl_AppendToObj(rv, string_result, -1);           return(TCL_ERROR);
1214              Tcl_AppendToObj(rv, "/", -1);           }
1215              GMP_INTS_mpz_to_string(string_result, &(neighbor_data.rights[i].neighbor.den));  
1216              Tcl_AppendToObj(rv, string_result, -1);        //Make assertions about the string pointers.
1217              }        assert(tbl[tbl_idx].tag     != NULL);
1218          assert(tbl[tbl_idx].desc    != NULL);
1219           //Set up for a normal return.        assert(tbl[tbl_idx].minmant != NULL);
1220           Tcl_SetObjResult(interp, rv);        assert(tbl[tbl_idx].mantrem != NULL);
1221    
1222           TclpFree(string_result);        //Assume the default number of digits by default.
1223           GMP_RALG_consecutive_fab_terms_result_free(&neighbor_data);        ndigits = tbl[tbl_idx].deflen;
1224           GMP_RATS_mpq_clear(&q_rn);  
1225           GMP_INTS_mpz_clear(&z_kmax);        //If there is an additional parameter, try to interpret
1226           GMP_INTS_mpz_clear(&z_hmax);        //that as the number of digits.
1227          if (objc == 4)
1228           return(TCL_OK);           {
1229           }           //SetIntFromAny(interp, objPtr)
1230        else if (pred_option_specified)           result_code = Tcl_GetIntFromObj(NULL, objv[3], &ndigits);
1231           {  
1232           //Simple predecessor case.           if (result_code != TCL_OK)
1233                {
1234           GMP_RALG_fab_neighbor_collection_struct neighbor_data;              //Could not obtain an integer.  Use hostile error
1235                //message and abort.
1236           //Form up the neighbor data.                    string_arg = Tcl_GetString(objv[3]);
1237           GMP_RALG_consecutive_fab_terms(              assert(string_arg != NULL);
1238                                         &q_rn,  
1239                                         &z_kmax,              rv = Tcl_NewStringObj("arbint const: \"", -1);
1240                                         &z_hmax,              Tcl_AppendToObj(rv, string_arg, -1);
1241                                         1,              Tcl_AppendToObj(rv, "\" is not a recognized integer.", -1);
1242                                         0,              Tcl_SetObjResult(interp, rv);
1243                                         &neighbor_data              return(TCL_ERROR);
1244                                         );              }
1245             }
1246           //If there was an error forming up the neighbor data or there are no left neighbors,  
1247           //create a hard error.        //Ndigits may be corrupt.  We have to be careful below to not
1248           if (neighbor_data.error || !neighbor_data.n_left_out)        //allow any funny stuff.
1249              {        rv = Tcl_NewStringObj(tbl[tbl_idx].minmant, -1);
1250              rv = Tcl_NewStringObj("arbint cfbrapab: unable to find predecessor.", -1);        ndigits = ndigits - strlen(tbl[tbl_idx].minmant) + tbl[tbl_idx].digit_count_offset;
1251              Tcl_SetObjResult(interp, rv);        if (ndigits > 0)
1252             {
1253              GMP_RALG_consecutive_fab_terms_result_free(&neighbor_data);           if (ndigits >= (int)strlen(tbl[tbl_idx].mantrem))
1254              GMP_RATS_mpq_clear(&q_rn);              {
1255              GMP_INTS_mpz_clear(&z_kmax);              Tcl_AppendToObj(rv, tbl[tbl_idx].mantrem, -1);
1256              GMP_INTS_mpz_clear(&z_hmax);              }
1257             else
1258              return(TCL_ERROR);              {
1259              }              Tcl_AppendToObj(rv, tbl[tbl_idx].mantrem, ndigits);
1260                }
1261           //The test above confirmed that we have at least one left neighbor calculated.           }
1262           //We can dump it to a string and finish up.  
1263           chars_reqd = INTFUNC_max(        //Append the exponent portion.
1264                                   GMP_INTS_mpz_size_in_base_10(&(neighbor_data.lefts[0].neighbor.num)),        if (tbl[tbl_idx].exp)
1265                                   GMP_INTS_mpz_size_in_base_10(&(neighbor_data.lefts[0].neighbor.den))           Tcl_AppendToObj(rv, tbl[tbl_idx].exp, -1);
1266                                   );  
1267           string_result = TclpAlloc(sizeof(char) * chars_reqd);        //Default successful return.
1268           assert(string_result != NULL);        Tcl_SetObjResult(interp, rv);
1269          return(TCL_OK);
1270           GMP_INTS_mpz_to_string(string_result, &(neighbor_data.lefts[0].neighbor.num));        }
1271           rv = Tcl_NewStringObj(string_result, -1);     }
1272           Tcl_AppendToObj(rv, "/", -1);  
1273           GMP_INTS_mpz_to_string(string_result, &(neighbor_data.lefts[0].neighbor.den));  
1274           Tcl_AppendToObj(rv, string_result, -1);  //Handles the "decommanate" subextension.
1275    //07/29/01:  Visual inspection OK.  Have not located my Tcl book, am doing this
1276           Tcl_SetObjResult(interp, rv);  //from memory an intuition as far as how to set return results and so forth.
1277    static
1278           TclpFree(string_result);  int ARBLENINTS_decommanate_handler(ClientData dummy,
1279           GMP_RALG_consecutive_fab_terms_result_free(&neighbor_data);                                Tcl_Interp *interp,
1280           GMP_RATS_mpq_clear(&q_rn);                                int objc,
1281           GMP_INTS_mpz_clear(&z_kmax);                                Tcl_Obj *objv[])
1282           GMP_INTS_mpz_clear(&z_hmax);     {
1283       Tcl_Obj *rv;
1284           return(TCL_OK);  
1285           }     //We must have one and exactly one additional argument
1286        else if (succ_option_specified)     //to this function, which is the string we want to
1287           {     //decommanate.
1288           //Simple successor.     if (objc != 3)
1289          {
1290           GMP_RALG_fab_neighbor_collection_struct neighbor_data;        Tcl_WrongNumArgs(interp,
1291                           2,
1292           //Form up the neighbor data.                               objv,
1293           GMP_RALG_consecutive_fab_terms(                         "sint");
1294                                         &q_rn,        return(TCL_ERROR);
1295                                         &z_kmax,        }
1296                                         &z_hmax,     else
1297                                         0,        {
1298                                         1,        char *string_arg;
1299                                         &neighbor_data  
1300                                         );        //Grab a pointer to the string representation of
1301          //the input argument.  The storage does not belong to us.
1302           //If there was an error forming up the neighbor data or there are no right neighbors,        string_arg = Tcl_GetString(objv[2]);
1303           //create a hard error.        assert(string_arg != NULL);
1304           if (neighbor_data.error || !neighbor_data.n_right_out)  
1305              {        //Try to parse the string as one of the error tags.
1306              rv = Tcl_NewStringObj("arbint cfbrapab: unable to find successor.", -1);        //If it is one of those, it isn't an error, but don't
1307              Tcl_SetObjResult(interp, rv);        //want to touch the string.
1308          if (GMP_INTS_identify_nan_string(string_arg) >= 0)
1309              GMP_RALG_consecutive_fab_terms_result_free(&neighbor_data);           {
1310              GMP_RATS_mpq_clear(&q_rn);           rv = Tcl_NewStringObj(string_arg, -1);
1311              GMP_INTS_mpz_clear(&z_kmax);           Tcl_SetObjResult(interp, rv);
1312              GMP_INTS_mpz_clear(&z_hmax);           return(TCL_OK);
1313             }
1314              return(TCL_ERROR);        //Try to parse it as a signed integer without commas.
1315              }        //If it has no commas, there is no need to decommanate it.
1316          else if (BSTRFUNC_is_sint_wo_commas(string_arg))
1317           //The test above confirmed that we have at least one right neighbor calculated.           {
1318           //We can dump it to a string and finish up.           //This is already an acceptable commanated signed integer.  Send it
1319           chars_reqd = INTFUNC_max(           //back as the return value.
1320                                   GMP_INTS_mpz_size_in_base_10(&(neighbor_data.rights[0].neighbor.num)),           rv = Tcl_NewStringObj(string_arg, -1);
1321                                   GMP_INTS_mpz_size_in_base_10(&(neighbor_data.rights[0].neighbor.den))           Tcl_SetObjResult(interp, rv);
1322                                   );           return(TCL_OK);
1323           string_result = TclpAlloc(sizeof(char) * chars_reqd);           }
1324           assert(string_result != NULL);        //Try to parse the argument as a signed integer with commas.
1325          //If it is one of those, decommanate it and return it.
1326           GMP_INTS_mpz_to_string(string_result, &(neighbor_data.rights[0].neighbor.num));        else if (BSTRFUNC_is_sint_w_commas(string_arg))
1327           rv = Tcl_NewStringObj(string_result, -1);           {
1328           Tcl_AppendToObj(rv, "/", -1);           size_t len;
1329           GMP_INTS_mpz_to_string(string_result, &(neighbor_data.rights[0].neighbor.den));           char *buffer;
1330           Tcl_AppendToObj(rv, string_result, -1);  
1331             len = strlen(string_arg);
1332           Tcl_SetObjResult(interp, rv);           buffer = TclpAlloc(sizeof(char) * len + 1);
1333             strcpy(buffer, string_arg);
1334           TclpFree(string_result);           BSTRFUNC_decommanate(buffer);
1335           GMP_RALG_consecutive_fab_terms_result_free(&neighbor_data);           rv = Tcl_NewStringObj(buffer, -1);
1336           GMP_RATS_mpq_clear(&q_rn);           TclpFree(buffer);
1337           GMP_INTS_mpz_clear(&z_kmax);           Tcl_SetObjResult(interp, rv);
1338           GMP_INTS_mpz_clear(&z_hmax);           return(TCL_OK);
1339             }
1340           return(TCL_OK);        else
1341           }           {
1342             //Error case.  Must give error message.
1343        //Free up all dynamic memory.           rv = Tcl_NewStringObj("arbint decommanate: \"", -1);
1344        GMP_RATS_mpq_clear(&q_rn);           Tcl_AppendToObj(rv, string_arg, -1);
1345        GMP_INTS_mpz_clear(&z_kmax);           Tcl_AppendToObj(rv, "\" is not a recognized integer.", -1);
1346        GMP_INTS_mpz_clear(&z_hmax);           Tcl_SetObjResult(interp, rv);
1347             return(TCL_ERROR);
1348        //Return           }
1349        return(TCL_OK);        }
1350        }     }
1351     }  
1352    
1353    //Handles the "intadd" subextension.
1354  //Handles the "cfratnum" subextension.  //08/06/01:  Visual inspection OK.
1355  //08/07/01:  Visually inspected, OK.  static
1356  static  int ARBLENINTS_intadd_handler(ClientData dummy,
1357  int ARBLENINTS_cfratnum_handler(ClientData dummy,                                Tcl_Interp *interp,
1358                                Tcl_Interp *interp,                                int objc,
1359                                int objc,                                Tcl_Obj *objv[])
1360                                Tcl_Obj *objv[])     {
1361     {     Tcl_Obj *rv;
1362     Tcl_Obj *rv;  
1363       //We must have two and exactly two additional arguments
1364     //We must have exactly one additional argument     //to this function, which are the integers whose
1365     //to this function, which is the rational number     //sum is to be calculated.
1366     //whose continued fraction decomposition is to be     if (objc != 4)
1367     //calculated.        {
1368     if (objc != 3)        Tcl_WrongNumArgs(interp,
1369        {                         2,
1370        Tcl_WrongNumArgs(interp,                         objv,
1371                         2,                         "sint sint");
1372                         objv,        return(TCL_ERROR);
1373                         "urn");        }
1374        return(TCL_ERROR);     else
1375        }        {
1376     else        GMP_INTS_mpz_struct arb_arg1, arb_arg2, arb_result;
1377        {        char *add_arg1, *add_arg2;
1378        char *input_arg;        int failure1, failure2;
1379        int failure;        unsigned chars_reqd;
1380        unsigned chars_reqd;        char *string_result;
1381        char *string_result;        int i, j;
1382        int n_string_result;  
1383        int i;        //Allocate space for the arbitrary-length integer result.
1384        GMP_RATS_mpq_struct rn;        GMP_INTS_mpz_init(&arb_arg1);
1385        GMP_RALG_cf_app_struct decomp;        GMP_INTS_mpz_init(&arb_arg2);
1386          GMP_INTS_mpz_init(&arb_result);
1387        //In this function, we are going to return a string  
1388        //result formed by starting with a string and then        //Grab pointers to the string representation of
1389        //concatenating  to it again and again.  We start        //the input arguments.  The storage does not belong to us.
1390        //off believing that 10,000 characters of space is enough,        add_arg1 = Tcl_GetString(objv[2]);
1391        //but we may need to revise upward and reallocate.          assert(add_arg1 != NULL);
1392        //A 10,000 character block is chosen because it is quick        add_arg2 = Tcl_GetString(objv[3]);
1393        //to allocate and most times won't go beyond that.        assert(add_arg2 != NULL);
1394        n_string_result = 10000;  
1395        string_result = TclpAlloc(sizeof(char) * n_string_result);        //Try to interpret either of the  strings as one of the NAN tags.
1396        assert(string_result != NULL);        //If it is one, return the appropriate result for
1397          //a binary operation.
1398        //We will need a rational number to hold the return value        i = GMP_INTS_identify_nan_string(add_arg1);
1399        //from the parsing function.  Allocate that now.        j = GMP_INTS_identify_nan_string(add_arg2);
1400        GMP_RATS_mpq_init(&rn);  
1401          if ((i >= 0) || (j >= 0))
1402        //Grab a pointer to the string representation of           {
1403        //the input argument.  The storage does not belong to us.           const char *p;
1404        input_arg = Tcl_GetString(objv[2]);  
1405        assert(input_arg != NULL);           //Find the max of i and j.  This isn't a scientific way to tag the
1406             //result, but will be OK.  Some information is lost no matter what
1407        //Try to parse our input string as a rational number.           //we do.
1408        //If we are not successful in this, must abort.           if (i > j)
1409        GMP_RATS_mpq_set_all_format_rat_num(input_arg,              ;
1410                                            &failure,           else
1411                                            &rn);              i = j;
1412    
1413        if (failure)           //i now contains the max.
1414           {           switch (i)
1415           rv = Tcl_NewStringObj("arbint cfratnum: \"", -1);              {
1416           Tcl_AppendToObj(rv, input_arg, -1);              case 0:  p = GMP_INTS_supply_nan_string(2);
1417                         break;
1418           Tcl_AppendToObj(rv, "\" is not a recognized non-negative rational number.", -1);              case 1:  p = GMP_INTS_supply_nan_string(3);
1419           Tcl_SetObjResult(interp, rv);                       break;
1420                case 2:  p = GMP_INTS_supply_nan_string(2);
1421           TclpFree(string_result);                       break;
1422           GMP_RATS_mpq_clear(&rn);              case 3:  p = GMP_INTS_supply_nan_string(3);
1423                         break;
1424           return(TCL_ERROR);              default:
1425           }                       assert(0);
1426                         break;
1427        //OK, we have a rational number, but there is a possibility              }
1428        //it is negative, which is a no-no.  Normalize the signs  
1429        //for easier testing.           rv = Tcl_NewStringObj(p, -1);
1430        GMP_RATS_mpq_normalize_sign(&rn);           Tcl_SetObjResult(interp, rv);
1431        if (GMP_INTS_mpz_is_neg(&(rn.num)))  
1432           {           GMP_INTS_mpz_clear(&arb_arg1);
1433           rv = Tcl_NewStringObj("arbint cfratnum: \"", -1);           GMP_INTS_mpz_clear(&arb_arg2);
1434           Tcl_AppendToObj(rv, input_arg, -1);           GMP_INTS_mpz_clear(&arb_result);
1435    
1436           Tcl_AppendToObj(rv, "\" is negative.", -1);           return(TCL_OK);
1437           Tcl_SetObjResult(interp, rv);           }
1438    
1439           TclpFree(string_result);        //Try to convert both strings into arbitrary integers.
1440           GMP_RATS_mpq_clear(&rn);        GMP_INTS_mpz_set_general_int(&arb_arg1, &failure1, add_arg1);
1441          GMP_INTS_mpz_set_general_int(&arb_arg2, &failure2, add_arg2);
1442           return(TCL_ERROR);  
1443           }        //If there was a parse failure, we have to return an error
1444          //message.  It is possible that both arguments failed the parse,
1445        //OK, we have a rational number.  Form the continued fraction        //but only return one in the error message.
1446        //decomposition of it.  The function called is set up so that        if (failure1 || failure2)
1447        //one must deallocate, even in an error condition.           {
1448        GMP_RALG_cfdecomp_init(&decomp,           rv = Tcl_NewStringObj("arbint intadd: \"", -1);
1449                               &failure,           if (failure1)
1450                               &(rn.num),              Tcl_AppendToObj(rv, add_arg1, -1);
1451                               &(rn.den));           else
1452                Tcl_AppendToObj(rv, add_arg2, -1);
1453        //If we failed in the decomposition (don't know why that would  
1454        //happen) use the general error flag "NAN".           Tcl_AppendToObj(rv, "\" is not a recognized signed integer.", -1);
1455        if (failure)           Tcl_SetObjResult(interp, rv);
1456           {  
1457           rv = Tcl_NewStringObj("NAN", -1);           GMP_INTS_mpz_clear(&arb_arg1);
1458             GMP_INTS_mpz_clear(&arb_arg2);
1459           Tcl_SetObjResult(interp, rv);           GMP_INTS_mpz_clear(&arb_result);
1460    
1461           TclpFree(string_result);           return(TCL_ERROR);
1462           GMP_RATS_mpq_clear(&rn);           }
1463           GMP_RALG_cfdecomp_destroy(&decomp);  
1464          //Calculate the sum.
1465           return(TCL_ERROR);        GMP_INTS_mpz_add(&arb_result, &arb_arg1, &arb_arg2);
1466           }  
1467          //Figure out the number of characters required for
1468        //OK, that really is the last error we could have.        //the output string.
1469        //Iterate, adding the partial quotients and convergents        chars_reqd = GMP_INTS_mpz_size_in_base_10(&arb_result);
1470        //to the string which we'll return.  We need to watch out  
1471        //for running over our 10K buffer.        //Allocate space for the conversion result.
1472        rv = Tcl_NewStringObj("", -1);        string_result = TclpAlloc(sizeof(char) * chars_reqd);
1473        for (i=0; i<decomp.n; i++)        assert(string_result != NULL);
1474           {  
1475           //Partial quotient.        //Make the conversion to a character string.
1476           chars_reqd = GMP_INTS_mpz_size_in_base_10(&(decomp.a[i]));        GMP_INTS_mpz_to_string(string_result, &arb_result);
1477           if (chars_reqd > (unsigned)n_string_result)  
1478              {        //Assign the string result to a Tcl object.
1479              n_string_result = chars_reqd;        rv = Tcl_NewStringObj(string_result, -1);
1480              string_result = TclpRealloc(string_result,  
1481                                          sizeof(char) * n_string_result);        //Deallocate the string.
1482              }        TclpFree(string_result);
1483           GMP_INTS_mpz_to_string(string_result, &(decomp.a[i]));  
1484           Tcl_AppendToObj(rv, string_result, -1);        //Deallocate space for the arbitrary-length integers.
1485           Tcl_AppendToObj(rv, " ", -1);        GMP_INTS_mpz_clear(&arb_arg1);
1486          GMP_INTS_mpz_clear(&arb_arg2);
1487           //Numerator of convergent.        GMP_INTS_mpz_clear(&arb_result);
1488           chars_reqd = GMP_INTS_mpz_size_in_base_10(&(decomp.p[i]));  
1489           if (chars_reqd > (unsigned)n_string_result)        //Assign the result to be the return value.
1490              {        Tcl_SetObjResult(interp, rv);
1491              n_string_result = chars_reqd;  
1492              string_result = TclpRealloc(string_result,        //Return
1493                                          sizeof(char) * n_string_result);        return(TCL_OK);
1494              }        }
1495           GMP_INTS_mpz_to_string(string_result, &(decomp.p[i]));     }
1496           Tcl_AppendToObj(rv, string_result, -1);  
1497           Tcl_AppendToObj(rv, " ", -1);  
1498    //08/01/01:  Visual inspection and some unit testing, OK.
1499           //Denominator of convergent.  //Handles the "intcmp" subextension.
1500           chars_reqd = GMP_INTS_mpz_size_in_base_10(&(decomp.q[i]));  static
1501           if (chars_reqd > (unsigned)n_string_result)  int ARBLENINTS_intcmp_handler(ClientData dummy,
1502              {                                Tcl_Interp *interp,
1503              n_string_result = chars_reqd;                                int objc,
1504              string_result = TclpRealloc(string_result,                                Tcl_Obj *objv[])
1505                                          sizeof(char) * n_string_result);     {
1506              }     Tcl_Obj *rv;
1507           GMP_INTS_mpz_to_string(string_result, &(decomp.q[i]));  
1508           Tcl_AppendToObj(rv, string_result, -1);     //We must have two and exactly two additional arguments
1509           if (i != (decomp.n - 1)) //No space after last number.     //to this function, which are the integers to be compared.
1510              Tcl_AppendToObj(rv, " ", -1);     if (objc != 4)
1511           }        {
1512          Tcl_WrongNumArgs(interp,
1513        //Assign the result to be the return value.                         2,
1514        Tcl_SetObjResult(interp, rv);                         objv,
1515                           "sint sint");
1516        //Free up all dynamic memory.        return(TCL_ERROR);
1517        TclpFree(string_result);        }
1518        GMP_RATS_mpq_clear(&rn);     else
1519        GMP_RALG_cfdecomp_destroy(&decomp);        {
1520          GMP_INTS_mpz_struct arb_arg1, arb_arg2;
1521        //Return        char *cmp_arg1, *cmp_arg2;
1522        return(TCL_OK);        int failure1, failure2;
1523        }        int i, j, compare_result;
1524     }  
1525          //Allocate space for the arbitrary-length integer result.
1526          GMP_INTS_mpz_init(&arb_arg1);
1527  //Handles the "commanate" subextension.        GMP_INTS_mpz_init(&arb_arg2);
1528  //07/29/01:  Visual inspection OK.  Have not located my Tcl book, am doing this  
1529  //from memory an intuition as far as how to set return results and so forth.        //Grab pointers to the string representation of
1530  static        //the input arguments.  The storage does not belong to us.
1531  int ARBLENINTS_commanate_handler(ClientData dummy,        cmp_arg1 = Tcl_GetString(objv[2]);
1532                                Tcl_Interp *interp,        assert(cmp_arg1 != NULL);
1533                                int objc,        cmp_arg2 = Tcl_GetString(objv[3]);
1534                                Tcl_Obj *objv[])        assert(cmp_arg2 != NULL);
1535     {  
1536     Tcl_Obj *rv;        //Try to interpret either of the  strings as one of the NAN tags.
1537          //We cannot compare NAN tags.  If either is a NAN tag, we must signal an
1538     //We must have one and exactly one additional argument        //error.
1539     //to this function, which is the string we want to        i = GMP_INTS_identify_nan_string(cmp_arg1);
1540     //commanate.        j = GMP_INTS_identify_nan_string(cmp_arg2);
1541     if (objc != 3)  
1542        {        if ((i >= 0) || (j >= 0))
1543        Tcl_WrongNumArgs(interp,           {
1544                         2,           rv = Tcl_NewStringObj("arbint intcmp: cannot compare NAN symbolic tags.", -1);
1545                         objv,           Tcl_SetObjResult(interp, rv);
1546                         "sint");  
1547        return(TCL_ERROR);           GMP_INTS_mpz_clear(&arb_arg1);
1548        }           GMP_INTS_mpz_clear(&arb_arg2);
1549     else  
1550        {           return(TCL_ERROR);
1551        char *string_arg;           }
1552    
1553        //Grab a pointer to the string representation of        //Try to convert both strings into arbitrary integers.
1554        //the input argument.  The storage does not belong to us.        GMP_INTS_mpz_set_general_int(&arb_arg1, &failure1, cmp_arg1);
1555        string_arg = Tcl_GetString(objv[2]);        GMP_INTS_mpz_set_general_int(&arb_arg2, &failure2, cmp_arg2);
1556        assert(string_arg != NULL);  
1557          //If there was a parse failure, we have to return an error
1558        //Try to parse the string as one of the error tags.        //message.  It is possible that both arguments failed the parse,
1559        //If it is one of those, it isn't an error, but don't        //but only return one in the error message.
1560        //want to touch the string.        if (failure1 || failure2)
1561        if (GMP_INTS_identify_nan_string(string_arg) >= 0)           {
1562           {           rv = Tcl_NewStringObj("arbint intcmp: \"", -1);
1563           rv = Tcl_NewStringObj(string_arg, -1);           if (failure1)
1564           Tcl_SetObjResult(interp, rv);              Tcl_AppendToObj(rv, cmp_arg1, -1);
1565           return(TCL_OK);           else
1566           }              Tcl_AppendToObj(rv, cmp_arg2, -1);
1567        //Try to parse it as a signed integer with commas already.  
1568        //If it already has commas, there is no need to add any.           Tcl_AppendToObj(rv, "\" is not a recognized signed integer.", -1);
1569        else if (BSTRFUNC_is_sint_w_commas(string_arg))           Tcl_SetObjResult(interp, rv);
1570           {  
1571           //This is already an acceptable commanated signed integer.  Send it           GMP_INTS_mpz_clear(&arb_arg1);
1572           //back as the return value.           GMP_INTS_mpz_clear(&arb_arg2);
1573           rv = Tcl_NewStringObj(string_arg, -1);  
1574           Tcl_SetObjResult(interp, rv);           return(TCL_ERROR);
1575           return(TCL_OK);           }
1576           }  
1577        //Try to parse the argument as a signed integer without commas.        //Calculate the compare result.
1578        //If it is one of those, commanate it and return it.        compare_result = GMP_INTS_mpz_cmp(&arb_arg1, &arb_arg2);
1579        else if (BSTRFUNC_is_sint_wo_commas(string_arg))  
1580           {        //Assign the return value based on the result.
1581           size_t len;        if (compare_result < 0)
1582           char *buffer;           rv = Tcl_NewStringObj("-1", -1);
1583          else if (compare_result == 0)
1584           len = strlen(string_arg);           rv = Tcl_NewStringObj("0", -1);
1585           buffer = TclpAlloc(((sizeof(char) * 4 * len) / 3) + 10);        else
1586           strcpy(buffer, string_arg);           rv = Tcl_NewStringObj("1", -1);
1587           BSTRFUNC_commanate(buffer);  
1588           rv = Tcl_NewStringObj(buffer, -1);        //Deallocate space for the arbitrary-length integers.
1589           TclpFree(buffer);        GMP_INTS_mpz_clear(&arb_arg1);
1590           Tcl_SetObjResult(interp, rv);        GMP_INTS_mpz_clear(&arb_arg2);
1591           return(TCL_OK);  
1592           }        //Assign the result to be the return value.
1593        else        Tcl_SetObjResult(interp, rv);
1594           {  
1595           //Error case.  Must give error message.        //Return
1596           rv = Tcl_NewStringObj("arbint commanate: \"", -1);        return(TCL_OK);
1597           Tcl_AppendToObj(rv, string_arg, -1);        }
1598           Tcl_AppendToObj(rv, "\" is not a recognized integer.", -1);     }
1599           Tcl_SetObjResult(interp, rv);  
1600           return(TCL_ERROR);  
1601           }  //Handles the "intdiv" subextension.
1602        }  //07/31/01:  Visually inspected, OK.
1603     }  static
1604    int ARBLENINTS_intdiv_handler(ClientData dummy,
1605                                  Tcl_Interp *interp,
1606  //Handles the "const" subextension.                                int objc,
1607  //08/17/01: Visual inspection OK.                                Tcl_Obj *objv[])
1608  static     {
1609  int ARBLENINTS_const_handler(ClientData dummy,     Tcl_Obj *rv;
1610                               Tcl_Interp *interp,  
1611                               int objc,     //We must have two and exactly two additional arguments
1612                               Tcl_Obj *objv[])     //to this function, which are the integers whose
1613     {     //integer quotient is to be calculated.
1614     //Table of constants used.     if (objc != 4)
1615     static struct        {
1616        {        Tcl_WrongNumArgs(interp,
1617        char *tag;                         2,
1618           //The symbolic tag used to identify the number.                         objv,
1619        char *desc;                         "sint sint");
1620           //The full description of the number.  It must consist        return(TCL_ERROR);
1621           //of a string with lines no longer than about 70 chars,        }
1622           //separated by newlines, and indented by 6 spaces.     else
1623        char *minmant;        {
1624           //The minimum mantissa or minimum representation.        GMP_INTS_mpz_struct arb_dividend, arb_divisor, arb_quotient, arb_remainder;
1625           //May not be empty or NULL.        char *dividend_arg1, *divisor_arg2;
1626        char *mantrem;        int failure1, failure2;
1627           //The remaining mantissa or remaining portion of        unsigned chars_reqd;
1628           //number.  May be empty, but may not be NULL.        char *string_result;
1629        char *exp;        int i, j;
1630           //The exponent portion, if any, or NULL otherwise.  
1631        int deflen;        //Allocate space for the arbitrary-length integer arguments and results.
1632           //The default number of digits for the constant        GMP_INTS_mpz_init(&arb_dividend);
1633           //if none is specified.        GMP_INTS_mpz_init(&arb_divisor);
1634        int digit_count_offset;        GMP_INTS_mpz_init(&arb_quotient);
1635           //The offset to go from string length of mantissa        GMP_INTS_mpz_init(&arb_remainder);
1636           //portions to number of digits.  Cheap way to adjust  
1637           //for - sign and decimal point.        //Grab pointers to the string representation of
1638        } tbl[] =        //the input arguments.  The storage does not belong to us.
1639        {        dividend_arg1 = Tcl_GetString(objv[2]);
1640        //e--the transcendental number e.        assert(dividend_arg1 != NULL);
1641           {        divisor_arg2 = Tcl_GetString(objv[3]);
1642           //tag        assert(divisor_arg2 != NULL);
1643           "e",  
1644           //desc        //Try to interpret either of the  strings as one of the NAN tags.
1645           "      Historically significant transcendental constant.  Digits obtained\n"        //If it is one, return the appropriate result for
1646           "      from http://fermi.udw.ac.za/physics/e.html on 08/17/01.",        //a binary operation.
1647           //minmant        i = GMP_INTS_identify_nan_string(dividend_arg1);
1648           "2.7",        j = GMP_INTS_identify_nan_string(divisor_arg2);
1649           //mantrem  
1650           "182818284590452353602874713526624977572470936999595749669676277240766303535"        if ((i >= 0) || (j >= 0))
1651           "475945713821785251664274274663919320030599218174135966290435729003342952605956"           {
1652           "307381323286279434907632338298807531952510190115738341879307021540891499348841"           const char *p;
1653           "675092447614606680822648001684774118537423454424371075390777449920695517027618"  
1654           "386062613313845830007520449338265602976067371132007093287091274437470472306969"           //Find the max of i and j.  This isn't a scientific way to tag the
1655           "772093101416928368190255151086574637721112523897844250569536967707854499699679"           //result, but will be OK.  Some information is lost no matter what
1656           "468644549059879316368892300987931277361782154249992295763514822082698951936680"           //we do.
1657           "331825288693984964651058209392398294887933203625094431173012381970684161403970"           if (i > j)
1658           "198376793206832823764648042953118023287825098194558153017567173613320698112509"              ;
1659           "961818815930416903515988885193458072738667385894228792284998920868058257492796"           else
1660           "104841984443634632449684875602336248270419786232090021609902353043699418491463"              i = j;
1661           "140934317381436405462531520961836908887070167683964243781405927145635490613031"  
1662           "07208510383750510115747704171898610687396965521267154688957035035",           //i now contains the max.
1663           //exp           switch (i)
1664           NULL,              {
1665           //deflen              case 0:  p = GMP_INTS_supply_nan_string(2);
1666           30,                       break;
1667           //digit_count_offset              case 1:  p = GMP_INTS_supply_nan_string(3);
1668           1                       break;
1669           },              case 2:  p = GMP_INTS_supply_nan_string(2);
1670        //g_metric                       break;
1671           {              case 3:  p = GMP_INTS_supply_nan_string(3);
1672           //tag                       break;
1673           "g_si",              default:
1674           //desc                       assert(0);
1675           "      Gravitational acceleration in SI units, meters per second**2.\n"                       break;
1676           "      Obtained from NIST Special Publication 811 on 08/17/01.",              }
1677           //minmant  
1678           "9.80665",           rv = Tcl_NewStringObj(p, -1);
1679           //mantrem           Tcl_SetObjResult(interp, rv);
1680           "",  
1681           //exp           GMP_INTS_mpz_clear(&arb_dividend);
1682           NULL,           GMP_INTS_mpz_clear(&arb_divisor);
1683           //deflen           GMP_INTS_mpz_clear(&arb_quotient);
1684           30,           GMP_INTS_mpz_clear(&arb_remainder);
1685           //digit_count_offset  
1686           1           return(TCL_OK);
1687           },           }
1688        //in2m  
1689           {        //Try to convert both strings into arbitrary integers.
1690           //tag        GMP_INTS_mpz_set_general_int(&arb_dividend, &failure1, dividend_arg1);
1691           "in2m",        GMP_INTS_mpz_set_general_int(&arb_divisor,  &failure2, divisor_arg2);
1692           //desc  
1693           "      Multiplicative conversion factor from inches to meters.\n"        //If there was a parse failure, we have to return an error
1694           "      Obtained from NIST Special Publication 811 on 08/17/01.",        //message.  It is possible that both arguments failed the parse,
1695           //minmant        //but only return one in the error message.
1696           "2.54",        if (failure1 || failure2)
1697           //mantrem           {
1698           "",           rv = Tcl_NewStringObj("arbint intdiv: \"", -1);
1699           //exp           if (failure1)
1700           "e-2",              Tcl_AppendToObj(rv, dividend_arg1, -1);
1701           //deflen           else
1702           30,              Tcl_AppendToObj(rv, divisor_arg2, -1);
1703           //digit_count_offset  
1704           1           Tcl_AppendToObj(rv, "\" is not a recognized signed integer.", -1);
1705           },           Tcl_SetObjResult(interp, rv);
1706        //mi2km  
1707           {           GMP_INTS_mpz_clear(&arb_dividend);
1708           //tag           GMP_INTS_mpz_clear(&arb_divisor);
1709           "mi2km",           GMP_INTS_mpz_clear(&arb_quotient);
1710           //desc           GMP_INTS_mpz_clear(&arb_remainder);
1711           "      Multiplicative conversion factor from miles to kilometers.\n"  
1712           "      Obtained from NIST Special Publication 811 on 08/17/01.",           return(TCL_ERROR);
1713           //minmant           }
1714           "1.609344",  
1715           //mantrem        //Calculate the quotient.
1716           "",        GMP_INTS_mpz_tdiv_qr(&arb_quotient, &arb_remainder, &arb_dividend, &arb_divisor);
1717           //exp  
1718           NULL,        //Figure out the number of characters required for
1719           //deflen        //the output string.
1720           30,        chars_reqd = GMP_INTS_mpz_size_in_base_10(&arb_quotient);
1721           //digit_count_offset  
1722           1        //Allocate space for the conversion result.
1723           },        string_result = TclpAlloc(sizeof(char) * chars_reqd);
1724        //pi--the transcendental number PI.        assert(string_result != NULL);
1725           {  
1726           //tag        //Make the conversion to a character string.
1727           "pi",        GMP_INTS_mpz_to_string(string_result, &arb_quotient);
1728           //desc  
1729           "      Transcendental constant supplying ratio of a circle's circumference\n"        //Assign the string result to a Tcl object.
1730           "      to its diameter.  Digits obtained from http://www.joyofpi.com/\n"        rv = Tcl_NewStringObj(string_result, -1);
1731           "      pi.htm on 08/17/01.",  
1732           //minmant        //Deallocate the string.
1733           "3.14",        TclpFree(string_result);
1734           //mantrem  
1735           "15926535897932384626433832795028841971"        //Deallocate space for the arbitrary-length integers.
1736           "6939937510582097494459230781640628620899"        GMP_INTS_mpz_clear(&arb_dividend);
1737           "8628034825342117067982148086513282306647"        GMP_INTS_mpz_clear(&arb_divisor);
1738           "0938446095505822317253594081284811174502"        GMP_INTS_mpz_clear(&arb_quotient);
1739           "8410270193852110555964462294895493038196"        GMP_INTS_mpz_clear(&arb_remainder);
1740           "4428810975665933446128475648233786783165"  
1741           "2712019091456485669234603486104543266482"        //Assign the result to be the return value.
1742           "1339360726024914127372458700660631558817"        Tcl_SetObjResult(interp, rv);
1743           "4881520920962829254091715364367892590360"  
1744           "0113305305488204665213841469519415116094"        //Return
1745           "3305727036575959195309218611738193261179"        return(TCL_OK);
1746           "3105118548074462379962749567351885752724"        }
1747           "8912279381830119491298336733624406566430"     }
1748           "8602139494639522473719070217986094370277"  
1749           "0539217176293176752384674818467669405132"  
1750           "0005681271452635608277857713427577896091"  //08/01/01:  Visually inspected.
1751           "7363717872146844090122495343014654958537"  //Handles the "intexp" subextension.
1752           "1050792279689258923542019956112129021960"  static
1753           "8640344181598136297747713099605187072113"  int ARBLENINTS_intexp_handler(ClientData dummy,
1754           "4999999837297804995105973173281609631859"                                Tcl_Interp *interp,
1755           "5024459455346908302642522308253344685035"                                int objc,
1756           "2619311881710100031378387528865875332083"                                Tcl_Obj *objv[])
1757           "8142061717766914730359825349042875546873"     {
1758           "1159562863882353787593751957781857780532"     Tcl_Obj *rv;
1759           "1712268066130019278766111959092164201989"  
1760           "3809525720106548586327886593615338182796"     //We must have two and exactly two additional arguments
1761           "8230301952035301852968995773622599413891"     //to this function, which are the integers used to
1762           "2497217752834791315155748572424541506959"     //calculate the exponential.
1763           "5082953311686172785588907509838175463746"     if (objc != 4)
1764           "4939319255060400927701671139009848824012",        {
1765           //exp        Tcl_WrongNumArgs(interp,
1766           NULL,                         2,
1767           //deflen                         objv,
1768           30,                         "sint uint32");
1769           //digit_count_offset        return(TCL_ERROR);
1770           1        }
1771           },     else
1772        //sqrt5--the square root of 5.        {
1773           {        GMP_INTS_mpz_struct arb_arg1, arb_result;
1774           //tag        unsigned arg2;
1775           "sqrt5",        char *str_arg1, *str_arg2;
1776           //desc        int failure1, failure2;
1777           "      The square root of 5.  Digits obtained from\n"        unsigned chars_reqd;
1778           "      http://home.earthlink.net/~maryski/sqrt51000000.txt on 08/17/01.",        char *string_result;
1779           //minmant        int i, j;
1780           "2.236",  
1781           //mantrem        //Allocate space for the arbitrary-length integers.
1782           "0679774997896964091736687312762354406183596115257242708972454105209256378048"        GMP_INTS_mpz_init(&arb_arg1);
1783           "99414414408378782274969508176150773783504253267724447073863586360121533452708866"        GMP_INTS_mpz_init(&arb_result);
1784           "77817319187916581127664532263985658053576135041753378500342339241406444208643253"  
1785           "90972525926272288762995174024406816117759089094984923713907297288984820886415426"        //Grab pointers to the string representation of
1786           "89894099131693577019748678884425089754132956183176921499977424801530434115035957"        //the input arguments.  The storage does not belong to us.
1787           "66833251249881517813940800056242085524354223555610630634282023409333198293395974"        str_arg1 = Tcl_GetString(objv[2]);
1788           "63522712013417496142026359047378855043896870611356600457571399565955669569175645"        assert(str_arg1 != NULL);
1789           "78221952500060539231234005009286764875529722056766253666074485853505262330678494"        str_arg2 = Tcl_GetString(objv[3]);
1790           "63342224231763727702663240768010444331582573350589309813622634319868647194698997"        assert(str_arg2 != NULL);
1791           "01808189524264459620345221411922329125981963258111041704958070481204034559949435"  
1792           "06855551855572512388641655010262436312571024449618789424682903404474716115455723"        //Try to interpret either of the  strings as one of the NAN tags.
1793           "20173767659046091852957560357798439805415538077906439363972302875606299948221385"        //If it is one, return the appropriate result for
1794           "21773485924535151210463455550407072278724215347787529112121211843317893351910380",        //a binary operation.
1795           //exp        i = GMP_INTS_identify_nan_string(str_arg1);
1796           NULL,        j = GMP_INTS_identify_nan_string(str_arg2);
1797           //deflen  
1798           30,        if ((i >= 0) || (j >= 0))
1799           //digit_count_offset           {
1800           1           const char *p;
1801           },  
1802        };           //Find the max of i and j.  This isn't a scientific way to tag the
1803                   //result, but will be OK.  Some information is lost no matter what
1804     Tcl_Obj *rv;           //we do.
1805        //Value that will be returned to caller.           if (i > j)
1806     int i;              ;
1807        //Iteration variable.           else
1808     int tbl_idx;              i = j;
1809        //Index into lookup table, of -1 if not found.  
1810     int ndigits;           //i now contains the max.
1811        //The number of digits to supply.           switch (i)
1812     int result_code;              {
1813        //Return value from Tcl library function.              case 0:  p = GMP_INTS_supply_nan_string(2);
1814                         break;
1815     //We must have either one or two additional arguments.              case 1:  p = GMP_INTS_supply_nan_string(3);
1816     if ((objc != 3) && (objc != 4))                       break;
1817        {              case 2:  p = GMP_INTS_supply_nan_string(2);
1818        Tcl_WrongNumArgs(interp,                       break;
1819                         2,              case 3:  p = GMP_INTS_supply_nan_string(3);
1820                         objv,                       break;
1821                         "constant_tag ?ndigits?");              default:
1822        return(TCL_ERROR);                       assert(0);
1823        }                       break;
1824     else              }
1825        {  
1826        char *string_arg;           rv = Tcl_NewStringObj(p, -1);
1827             Tcl_SetObjResult(interp, rv);
1828        //Grab a pointer to the string representation of  
1829        //the input argument.  The storage does not belong to us.           GMP_INTS_mpz_clear(&arb_arg1);
1830        string_arg = Tcl_GetString(objv[2]);           GMP_INTS_mpz_clear(&arb_result);
1831        assert(string_arg != NULL);  
1832             return(TCL_OK);
1833        //Try to look up the string argument in the table.           }
1834        tbl_idx = -1;  
1835        for (i=0; i<sizeof(tbl)/sizeof(tbl[0]); i++)        //Try to convert the first string into arbitrary integers.
1836           {        //The first string can be anything, including zero or a negative
1837           if (!strcmp(string_arg, tbl[i].tag))        //arugument.
1838              {        GMP_INTS_mpz_set_general_int(&arb_arg1, &failure1, str_arg1);
1839              tbl_idx = i;  
1840              break;        //If the conversion of the first string did not go alright,
1841              }        //print error message and abort.
1842           }        if (failure1)
1843             {
1844        //If the tag was not found in the table, print a hostile           rv = Tcl_NewStringObj("arbint intexp: \"", -1);
1845        //message and abort.           Tcl_AppendToObj(rv, str_arg1, -1);
1846        if (tbl_idx == -1)           Tcl_AppendToObj(rv, "\" is not a recognized signed integer.", -1);
1847           {           Tcl_SetObjResult(interp, rv);
1848           char buf[100];  
1849             GMP_INTS_mpz_clear(&arb_arg1);
1850           //Error case.  Must give error message.               GMP_INTS_mpz_clear(&arb_result);
1851           //Must also list the constants available.  
1852           rv = Tcl_NewStringObj("arbint const: \"", -1);           return(TCL_ERROR);
1853           Tcl_AppendToObj(rv, string_arg, -1);           }
1854           Tcl_AppendToObj(rv, "\" is not a recognized constant.\n", -1);  
1855    
1856           Tcl_AppendToObj(rv, "Available constants are:\n", -1);        //Try to convert the second string into an unsigned 32-bit
1857          //integer.
1858           for (i=0; i<sizeof(tbl)/sizeof(tbl[0]); i++)        GMP_INTS_mpz_parse_into_uint32(&arg2, &failure2, str_arg2);
1859              {  
1860              Tcl_AppendToObj(rv, "   ", -1);        //If the conversion of the second string did not go alright,
1861              Tcl_AppendToObj(rv, tbl[i].tag, -1);        //print error message and abort.
1862              sprintf(buf, " (%d digits available)\n",        if (failure2)
1863                      strlen(tbl[i].minmant) + strlen(tbl[i].mantrem) - tbl[i].digit_count_offset);           {
1864              Tcl_AppendToObj(rv, buf, -1);           rv = Tcl_NewStringObj("arbint intexp: \"", -1);
1865              Tcl_AppendToObj(rv, tbl[i].desc, -1);           Tcl_AppendToObj(rv, str_arg2, -1);
1866              if (i != (sizeof(tbl)/sizeof(tbl[0]) - 1))           Tcl_AppendToObj(rv, "\" is not a recognized unsigned 32-bit integer.", -1);
1867                 Tcl_AppendToObj(rv, "\n", -1);           Tcl_SetObjResult(interp, rv);
1868              }  
1869             GMP_INTS_mpz_clear(&arb_arg1);
1870           Tcl_SetObjResult(interp, rv);           GMP_INTS_mpz_clear(&arb_result);
1871           return(TCL_ERROR);  
1872           }           return(TCL_ERROR);
1873             }
1874        //Make assertions about the string pointers.  
1875        assert(tbl[tbl_idx].tag     != NULL);        //Calculate the exponential.
1876        assert(tbl[tbl_idx].desc    != NULL);        GMP_INTS_mpz_pow_ui(&arb_result, &arb_arg1, arg2);
1877        assert(tbl[tbl_idx].minmant != NULL);  
1878        assert(tbl[tbl_idx].mantrem != NULL);        //Figure out the number of characters required for
1879          //the output string.
1880        //Assume the default number of digits by default.        chars_reqd = GMP_INTS_mpz_size_in_base_10(&arb_result);
1881        ndigits = tbl[tbl_idx].deflen;  
1882          //Allocate space for the conversion result.
1883        //If there is an additional parameter, try to interpret        string_result = TclpAlloc(sizeof(char) * chars_reqd);
1884        //that as the number of digits.        assert(string_result != NULL);
1885        if (objc == 4)  
1886           {        //Make the conversion to a character string.
1887           //SetIntFromAny(interp, objPtr)        GMP_INTS_mpz_to_string(string_result, &arb_result);
1888           result_code = Tcl_GetIntFromObj(NULL, objv[3], &ndigits);  
1889          //Assign the string result to a Tcl object.
1890           if (result_code != TCL_OK)        rv = Tcl_NewStringObj(string_result, -1);
1891              {  
1892              //Could not obtain an integer.  Use hostile error        //Deallocate the string.
1893              //message and abort.        TclpFree(string_result);
1894              string_arg = Tcl_GetString(objv[3]);  
1895              assert(string_arg != NULL);        //Deallocate space for the arbitrary-length integers.
1896          GMP_INTS_mpz_clear(&arb_arg1);
1897              rv = Tcl_NewStringObj("arbint const: \"", -1);        GMP_INTS_mpz_clear(&arb_result);
1898              Tcl_AppendToObj(rv, string_arg, -1);  
1899              Tcl_AppendToObj(rv, "\" is not a recognized integer.", -1);        //Assign the result to be the return value.
1900              Tcl_SetObjResult(interp, rv);        Tcl_SetObjResult(interp, rv);
1901              return(TCL_ERROR);  
1902              }        //Return
1903           }        return(TCL_OK);
1904          }
1905        //Ndigits may be corrupt.  We have to be careful below to not     }
1906        //allow any funny stuff.  
1907        rv = Tcl_NewStringObj(tbl[tbl_idx].minmant, -1);  
1908        ndigits = ndigits - strlen(tbl[tbl_idx].minmant) + tbl[tbl_idx].digit_count_offset;  //Handles the "intfac" subextension.
1909        if (ndigits > 0)  //07/29/01:  Visual inspection OK.  Have not located my Tcl book, am doing this
1910           {  //from memory an intuition as far as how to set return results and so forth.
1911           if (ndigits >= (int)strlen(tbl[tbl_idx].mantrem))  static
1912              {  int ARBLENINTS_intfac_handler(ClientData dummy,
1913              Tcl_AppendToObj(rv, tbl[tbl_idx].mantrem, -1);                                Tcl_Interp *interp,
1914              }                                int objc,
1915           else                                Tcl_Obj *objv[])
1916              {     {
1917              Tcl_AppendToObj(rv, tbl[tbl_idx].mantrem, ndigits);     Tcl_Obj *rv;
1918              }  
1919           }     //We must have one and exactly one additional argument
1920       //to this function, which is the integer whose
1921        //Append the exponent portion.     //factorial is to be evaluated.
1922        if (tbl[tbl_idx].exp)     if (objc != 3)
1923           Tcl_AppendToObj(rv, tbl[tbl_idx].exp, -1);        {
1924          Tcl_WrongNumArgs(interp,
1925        //Default successful return.                         2,
1926        Tcl_SetObjResult(interp, rv);                         objv,
1927        return(TCL_OK);                         "uint32");
1928        }        return(TCL_ERROR);
1929     }        }
1930       else
1931          {
1932  //Handles the "decommanate" subextension.        GMP_INTS_mpz_struct arb_result;
1933  //07/29/01:  Visual inspection OK.  Have not located my Tcl book, am doing this        char *fac_arg;
1934  //from memory an intuition as far as how to set return results and so forth.        int failure;
1935  static        unsigned fac_ui_arg;
1936  int ARBLENINTS_decommanate_handler(ClientData dummy,        unsigned chars_reqd;
1937                                Tcl_Interp *interp,        char *string_result;
1938                                int objc,        int i;
1939                                Tcl_Obj *objv[])  
1940     {        //Allocate space for the arbitrary-length integer result.
1941     Tcl_Obj *rv;        GMP_INTS_mpz_init(&arb_result);
1942    
1943     //We must have one and exactly one additional argument        //Grab a pointer to the string representation of
1944     //to this function, which is the string we want to        //the input argument.  The storage does not belong to us.
1945     //decommanate.        fac_arg = Tcl_GetString(objv[2]);
1946     if (objc != 3)        assert(fac_arg != NULL);
1947        {  
1948        Tcl_WrongNumArgs(interp,        //Try to interpret the string as one of the NAN tags.
1949                         2,        //If it is one, return the appropriate result for
1950                         objv,        //a unary operation.
1951                         "sint");        if ((i = GMP_INTS_identify_nan_string(fac_arg)) >= 0)
1952        return(TCL_ERROR);           {
1953        }           const char *p;
1954     else  
1955        {           switch (i)
1956        char *string_arg;              {
1957                case 0:  p = GMP_INTS_supply_nan_string(2);
1958        //Grab a pointer to the string representation of                       break;
1959        //the input argument.  The storage does not belong to us.              case 1:  p = GMP_INTS_supply_nan_string(3);
1960        string_arg = Tcl_GetString(objv[2]);                       break;
1961        assert(string_arg != NULL);              case 2:  p = GMP_INTS_supply_nan_string(2);
1962                         break;
1963        //Try to parse the string as one of the error tags.              case 3:  p = GMP_INTS_supply_nan_string(3);
1964        //If it is one of those, it isn't an error, but don't                       break;
1965        //want to touch the string.              default:
1966        if (GMP_INTS_identify_nan_string(string_arg) >= 0)                       assert(0);
1967           {                       break;
1968           rv = Tcl_NewStringObj(string_arg, -1);              }
1969           Tcl_SetObjResult(interp, rv);  
1970           return(TCL_OK);           rv = Tcl_NewStringObj(p, -1);
1971           }           Tcl_SetObjResult(interp, rv);
1972        //Try to parse it as a signed integer without commas.           GMP_INTS_mpz_clear(&arb_result);
1973        //If it has no commas, there is no need to decommanate it.           return(TCL_OK);
1974        else if (BSTRFUNC_is_sint_wo_commas(string_arg))           }
1975           {  
1976           //This is already an acceptable commanated signed integer.  Send it        //Try to convert the string to a UINT32 using all
1977           //back as the return value.        //known methods.
1978           rv = Tcl_NewStringObj(string_arg, -1);        GMP_INTS_mpz_parse_into_uint32(&fac_ui_arg, &failure, fac_arg);
1979           Tcl_SetObjResult(interp, rv);  
1980           return(TCL_OK);        //If there was a parse failure, we have to return an error
1981           }        //message.
1982        //Try to parse the argument as a signed integer with commas.        if (failure)
1983        //If it is one of those, decommanate it and return it.           {
1984        else if (BSTRFUNC_is_sint_w_commas(string_arg))           rv = Tcl_NewStringObj("arbint intfac: \"", -1);
1985           {           Tcl_AppendToObj(rv, fac_arg, -1);
1986           size_t len;           Tcl_AppendToObj(rv, "\" is not a recognized 32-bit unsigned integer.", -1);
1987           char *buffer;           Tcl_SetObjResult(interp, rv);
1988             GMP_INTS_mpz_clear(&arb_result);
1989           len = strlen(string_arg);           return(TCL_ERROR);
1990           buffer = TclpAlloc(sizeof(char) * len + 1);           }
1991           strcpy(buffer, string_arg);  
1992           BSTRFUNC_decommanate(buffer);        //Calculate the factorial.
1993           rv = Tcl_NewStringObj(buffer, -1);        GMP_INTS_mpz_fac_ui(&arb_result, fac_ui_arg);
1994           TclpFree(buffer);  
1995           Tcl_SetObjResult(interp, rv);        //Figure out the number of characters required for
1996           return(TCL_OK);        //the output string.
1997           }        chars_reqd = GMP_INTS_mpz_size_in_base_10(&arb_result);
1998        else  
1999           {        //Allocate space for the conversion result.
2000           //Error case.  Must give error message.        string_result = TclpAlloc(sizeof(char) * chars_reqd);
2001           rv = Tcl_NewStringObj("arbint decommanate: \"", -1);        assert(string_result != NULL);
2002           Tcl_AppendToObj(rv, string_arg, -1);  
2003           Tcl_AppendToObj(rv, "\" is not a recognized integer.", -1);        //Make the conversion to a character string.
2004           Tcl_SetObjResult(interp, rv);        GMP_INTS_mpz_to_string(string_result, &arb_result);
2005           return(TCL_ERROR);  
2006           }        //Assign the string result to a Tcl object.
2007        }        rv = Tcl_NewStringObj(string_result, -1);
2008     }  
2009          //Deallocate the string.
2010          TclpFree(string_result);
2011  //Handles the "intadd" subextension.  
2012  //08/06/01:  Visual inspection OK.        //Deallocate space for the arbitrary-length integer.
2013  static        GMP_INTS_mpz_clear(&arb_result);
2014  int ARBLENINTS_intadd_handler(ClientData dummy,  
2015                                Tcl_Interp *interp,        //Assign the result to be the return value.
2016                                int objc,        Tcl_SetObjResult(interp, rv);
2017                                Tcl_Obj *objv[])  
2018     {        //Return
2019     Tcl_Obj *rv;        return(TCL_OK);
2020          }
2021     //We must have two and exactly two additional arguments     }
2022     //to this function, which are the integers whose  
2023     //sum is to be calculated.  
2024     if (objc != 4)  //Handles the "intgcd" subextension.
2025        {  //08/06/01:  Visual inspection OK.
2026        Tcl_WrongNumArgs(interp,  static
2027                         2,  int ARBLENINTS_intgcd_handler(ClientData dummy,
2028                         objv,                                Tcl_Interp *interp,
2029                         "sint sint");                                int objc,
2030        return(TCL_ERROR);                                Tcl_Obj *objv[])
2031        }     {
2032     else     Tcl_Obj *rv;
2033        {  
2034        GMP_INTS_mpz_struct arb_arg1, arb_arg2, arb_result;     //We must have two and exactly two additional arguments
2035        char *add_arg1, *add_arg2;     //to this function, which are the integers whose
2036        int failure1, failure2;     //gcd is to be calculated.
2037        unsigned chars_reqd;     if (objc != 4)
2038        char *string_result;        {
2039        int i, j;        Tcl_WrongNumArgs(interp,
2040                           2,
2041        //Allocate space for the arbitrary-length integer result.                         objv,
2042        GMP_INTS_mpz_init(&arb_arg1);                         "sint sint");
2043        GMP_INTS_mpz_init(&arb_arg2);        return(TCL_ERROR);
2044        GMP_INTS_mpz_init(&arb_result);        }
2045       else
2046        //Grab pointers to the string representation of        {
2047        //the input arguments.  The storage does not belong to us.        GMP_INTS_mpz_struct arb_arg1, arb_arg2, arb_result;
2048        add_arg1 = Tcl_GetString(objv[2]);        char *gcd_arg1, *gcd_arg2;
2049        assert(add_arg1 != NULL);        int failure1, failure2;
2050        add_arg2 = Tcl_GetString(objv[3]);        unsigned chars_reqd;
2051        assert(add_arg2 != NULL);        char *string_result;
2052          int i, j;
2053        //Try to interpret either of the  strings as one of the NAN tags.  
2054        //If it is one, return the appropriate result for        //Allocate space for the arbitrary-length integer result.
2055        //a binary operation.        GMP_INTS_mpz_init(&arb_arg1);
2056        i = GMP_INTS_identify_nan_string(add_arg1);        GMP_INTS_mpz_init(&arb_arg2);
2057        j = GMP_INTS_identify_nan_string(add_arg2);        GMP_INTS_mpz_init(&arb_result);
2058    
2059        if ((i >= 0) || (j >= 0))        //Grab pointers to the string representation of
2060           {        //the input arguments.  The storage does not belong to us.
2061           const char *p;        gcd_arg1 = Tcl_GetString(objv[2]);
2062          assert(gcd_arg1 != NULL);
2063           //Find the max of i and j.  This isn't a scientific way to tag the        gcd_arg2 = Tcl_GetString(objv[3]);
2064           //result, but will be OK.  Some information is lost no matter what        assert(gcd_arg2 != NULL);
2065           //we do.  
2066           if (i > j)        //Try to interpret either of the  strings as one of the NAN tags.
2067              ;        //If it is one, return the appropriate result for
2068           else        //a binary operation.
2069              i = j;        i = GMP_INTS_identify_nan_string(gcd_arg1);
2070          j = GMP_INTS_identify_nan_string(gcd_arg2);
2071           //i now contains the max.  
2072           switch (i)        if ((i >= 0) || (j >= 0))
2073              {           {
2074              case 0:  p = GMP_INTS_supply_nan_string(2);           const char *p;
2075                       break;  
2076              case 1:  p = GMP_INTS_supply_nan_string(3);           //Find the max of i and j.  This isn't a scientific way to tag the
2077                       break;           //result, but will be OK.  Some information is lost no matter what
2078              case 2:  p = GMP_INTS_supply_nan_string(2);           //we do.
2079                       break;           if (i > j)
2080              case 3:  p = GMP_INTS_supply_nan_string(3);              ;
2081                       break;           else
2082              default:              i = j;
2083                       assert(0);  
2084                       break;           //i now contains the max.
2085              }           switch (i)
2086                {
2087           rv = Tcl_NewStringObj(p, -1);              case 0:  p = GMP_INTS_supply_nan_string(2);
2088           Tcl_SetObjResult(interp, rv);                       break;
2089                case 1:  p = GMP_INTS_supply_nan_string(3);
2090           GMP_INTS_mpz_clear(&arb_arg1);                       break;
2091           GMP_INTS_mpz_clear(&arb_arg2);              case 2:  p = GMP_INTS_supply_nan_string(2);
2092           GMP_INTS_mpz_clear(&arb_result);                       break;
2093                case 3:  p = GMP_INTS_supply_nan_string(3);
2094           return(TCL_OK);                       break;
2095           }              default:
2096                         assert(0);
2097        //Try to convert both strings into arbitrary integers.                       break;
2098        GMP_INTS_mpz_set_general_int(&arb_arg1, &failure1, add_arg1);              }
2099        GMP_INTS_mpz_set_general_int(&arb_arg2, &failure2, add_arg2);  
2100             rv = Tcl_NewStringObj(p, -1);
2101        //If there was a parse failure, we have to return an error           Tcl_SetObjResult(interp, rv);
2102        //message.  It is possible that both arguments failed the parse,  
2103        //but only return one in the error message.           GMP_INTS_mpz_clear(&arb_arg1);
2104        if (failure1 || failure2)           GMP_INTS_mpz_clear(&arb_arg2);
2105           {           GMP_INTS_mpz_clear(&arb_result);
2106           rv = Tcl_NewStringObj("arbint intadd: \"", -1);  
2107           if (failure1)           return(TCL_OK);
2108              Tcl_AppendToObj(rv, add_arg1, -1);           }
2109           else  
2110              Tcl_AppendToObj(rv, add_arg2, -1);        //Try to convert both strings into arbitrary integers.
2111          GMP_INTS_mpz_set_general_int(&arb_arg1, &failure1, gcd_arg1);
2112           Tcl_AppendToObj(rv, "\" is not a recognized signed integer.", -1);        GMP_INTS_mpz_set_general_int(&arb_arg2, &failure2, gcd_arg2);
2113           Tcl_SetObjResult(interp, rv);  
2114          //If there was a parse failure, we have to return an error
2115           GMP_INTS_mpz_clear(&arb_arg1);        //message.  It is possible that both arguments failed the parse,
2116           GMP_INTS_mpz_clear(&arb_arg2);        //but only return one in the error message.
2117           GMP_INTS_mpz_clear(&arb_result);        if (failure1 || failure2)
2118             {
2119           return(TCL_ERROR);           rv = Tcl_NewStringObj("arbint intgcd: \"", -1);
2120           }           if (failure1)
2121                Tcl_AppendToObj(rv, gcd_arg1, -1);
2122        //Calculate the sum.           else
2123        GMP_INTS_mpz_add(&arb_result, &arb_arg1, &arb_arg2);              Tcl_AppendToObj(rv, gcd_arg2, -1);
2124    
2125        //Figure out the number of characters required for           Tcl_AppendToObj(rv, "\" is not a recognized signed integer.", -1);
2126        //the output string.           Tcl_SetObjResult(interp, rv);
2127        chars_reqd = GMP_INTS_mpz_size_in_base_10(&arb_result);  
2128             GMP_INTS_mpz_clear(&arb_arg1);
2129        //Allocate space for the conversion result.           GMP_INTS_mpz_clear(&arb_arg2);
2130        string_result = TclpAlloc(sizeof(char) * chars_reqd);           GMP_INTS_mpz_clear(&arb_result);
2131        assert(string_result != NULL);  
2132             return(TCL_ERROR);
2133        //Make the conversion to a character string.           }
2134        GMP_INTS_mpz_to_string(string_result, &arb_result);  
2135          //Calculate the gcd.
2136        //Assign the string result to a Tcl object.        GMP_INTS_mpz_gcd(&arb_result, &arb_arg1, &arb_arg2);
2137        rv = Tcl_NewStringObj(string_result, -1);  
2138          //Figure out the number of characters required for
2139        //Deallocate the string.        //the output string.
2140        TclpFree(string_result);        chars_reqd = GMP_INTS_mpz_size_in_base_10(&arb_result);
2141    
2142        //Deallocate space for the arbitrary-length integers.        //Allocate space for the conversion result.
2143        GMP_INTS_mpz_clear(&arb_arg1);        string_result = TclpAlloc(sizeof(char) * chars_reqd);
2144        GMP_INTS_mpz_clear(&arb_arg2);        assert(string_result != NULL);
2145        GMP_INTS_mpz_clear(&arb_result);  
2146          //Make the conversion to a character string.
2147        //Assign the result to be the return value.        GMP_INTS_mpz_to_string(string_result, &arb_result);
2148        Tcl_SetObjResult(interp, rv);  
2149          //Assign the string result to a Tcl object.
2150        //Return        rv = Tcl_NewStringObj(string_result, -1);
2151        return(TCL_OK);  
2152        }        //Deallocate the string.
2153     }        TclpFree(string_result);
2154    
2155          //Deallocate space for the arbitrary-length integers.
2156  //08/01/01:  Visual inspection and some unit testing, OK.        GMP_INTS_mpz_clear(&arb_arg1);
2157  //Handles the "intcmp" subextension.        GMP_INTS_mpz_clear(&arb_arg2);
2158  static        GMP_INTS_mpz_clear(&arb_result);
2159  int ARBLENINTS_intcmp_handler(ClientData dummy,  
2160                                Tcl_Interp *interp,        //Assign the result to be the return value.
2161                                int objc,        Tcl_SetObjResult(interp, rv);
2162                                Tcl_Obj *objv[])  
2163     {        //Return
2164     Tcl_Obj *rv;        return(TCL_OK);
2165          }
2166     //We must have two and exactly two additional arguments     }
2167     //to this function, which are the integers to be compared.  
2168     if (objc != 4)  
2169        {  //Handles the "intlcm" subextension.
2170        Tcl_WrongNumArgs(interp,  //08/10/01:  Visual inspection OK.
2171                         2,  static
2172                         objv,  int ARBLENINTS_intlcm_handler(ClientData dummy,
2173                         "sint sint");                                Tcl_Interp *interp,
2174        return(TCL_ERROR);                                int objc,
2175        }                                Tcl_Obj *objv[])
2176     else     {
2177        {     Tcl_Obj *rv;
2178        GMP_INTS_mpz_struct arb_arg1, arb_arg2;  
2179        char *cmp_arg1, *cmp_arg2;     //We must have two and exactly two additional arguments
2180        int failure1, failure2;     //to this function, which are the integers whose
2181        int i, j, compare_result;     //lcm is to be calculated.
2182       if (objc != 4)
2183        //Allocate space for the arbitrary-length integer result.        {
2184        GMP_INTS_mpz_init(&arb_arg1);        Tcl_WrongNumArgs(interp,
2185        GMP_INTS_mpz_init(&arb_arg2);                         2,
2186                           objv,
2187        //Grab pointers to the string representation of                         "sint sint");
2188        //the input arguments.  The storage does not belong to us.        return(TCL_ERROR);
2189        cmp_arg1 = Tcl_GetString(objv[2]);        }
2190        assert(cmp_arg1 != NULL);     else
2191        cmp_arg2 = Tcl_GetString(objv[3]);        {
2192        assert(cmp_arg2 != NULL);        GMP_INTS_mpz_struct arb_arg1, arb_arg2, gcd, remainder, arb_result;
2193          char *lcm_arg1, *lcm_arg2;
2194        //Try to interpret either of the  strings as one of the NAN tags.        int failure1, failure2;
2195        //We cannot compare NAN tags.  If either is a NAN tag, we must signal an        unsigned chars_reqd;
2196        //error.        char *string_result;
2197        i = GMP_INTS_identify_nan_string(cmp_arg1);        int i, j;
2198        j = GMP_INTS_identify_nan_string(cmp_arg2);  
2199          //Allocate space for the arbitrary-length integers.
2200        if ((i >= 0) || (j >= 0))        GMP_INTS_mpz_init(&arb_arg1);
2201           {        GMP_INTS_mpz_init(&arb_arg2);
2202           rv = Tcl_NewStringObj("arbint intcmp: cannot compare NAN symbolic tags.", -1);        GMP_INTS_mpz_init(&gcd);
2203           Tcl_SetObjResult(interp, rv);        GMP_INTS_mpz_init(&remainder);
2204          GMP_INTS_mpz_init(&arb_result);
2205           GMP_INTS_mpz_clear(&arb_arg1);  
2206           GMP_INTS_mpz_clear(&arb_arg2);        //Grab pointers to the string representation of
2207          //the input arguments.  The storage does not belong to us.
2208           return(TCL_ERROR);        lcm_arg1 = Tcl_GetString(objv[2]);
2209           }        assert(lcm_arg1 != NULL);
2210          lcm_arg2 = Tcl_GetString(objv[3]);
2211        //Try to convert both strings into arbitrary integers.        assert(lcm_arg2 != NULL);
2212        GMP_INTS_mpz_set_general_int(&arb_arg1, &failure1, cmp_arg1);  
2213        GMP_INTS_mpz_set_general_int(&arb_arg2, &failure2, cmp_arg2);        //Try to interpret either of the  strings as one of the NAN tags.
2214          //If it is one, return the appropriate result for
2215        //If there was a parse failure, we have to return an error        //a binary operation.
2216        //message.  It is possible that both arguments failed the parse,        i = GMP_INTS_identify_nan_string(lcm_arg1);
2217        //but only return one in the error message.        j = GMP_INTS_identify_nan_string(lcm_arg2);
2218        if (failure1 || failure2)  
2219           {        if ((i >= 0) || (j >= 0))
2220           rv = Tcl_NewStringObj("arbint intcmp: \"", -1);           {
2221           if (failure1)           const char *p;
2222              Tcl_AppendToObj(rv, cmp_arg1, -1);  
2223           else           //Find the max of i and j.  This isn't a scientific way to tag the
2224              Tcl_AppendToObj(rv, cmp_arg2, -1);           //result, but will be OK.  Some information is lost no matter what
2225             //we do.
2226           Tcl_AppendToObj(rv, "\" is not a recognized signed integer.", -1);           if (i > j)
2227           Tcl_SetObjResult(interp, rv);              ;
2228             else
2229           GMP_INTS_mpz_clear(&arb_arg1);              i = j;
2230           GMP_INTS_mpz_clear(&arb_arg2);  
2231             //i now contains the max.
2232           return(TCL_ERROR);           switch (i)
2233           }              {
2234                case 0:  p = GMP_INTS_supply_nan_string(2);
2235        //Calculate the compare result.                       break;
2236        compare_result = GMP_INTS_mpz_cmp(&arb_arg1, &arb_arg2);              case 1:  p = GMP_INTS_supply_nan_string(3);
2237                         break;
2238        //Assign the return value based on the result.              case 2:  p = GMP_INTS_supply_nan_string(2);
2239        if (compare_result < 0)                       break;
2240           rv = Tcl_NewStringObj("-1", -1);              case 3:  p = GMP_INTS_supply_nan_string(3);
2241        else if (compare_result == 0)                       break;
2242           rv = Tcl_NewStringObj("0", -1);              default:
2243        else                       assert(0);
2244           rv = Tcl_NewStringObj("1", -1);                       break;
2245                }
2246        //Deallocate space for the arbitrary-length integers.  
2247        GMP_INTS_mpz_clear(&arb_arg1);           rv = Tcl_NewStringObj(p, -1);
2248        GMP_INTS_mpz_clear(&arb_arg2);           Tcl_SetObjResult(interp, rv);
2249    
2250        //Assign the result to be the return value.           GMP_INTS_mpz_clear(&arb_arg1);
2251        Tcl_SetObjResult(interp, rv);           GMP_INTS_mpz_clear(&arb_arg2);
2252             GMP_INTS_mpz_clear(&gcd);
2253        //Return           GMP_INTS_mpz_clear(&remainder);
2254        return(TCL_OK);           GMP_INTS_mpz_clear(&arb_result);
2255        }  
2256     }           return(TCL_OK);
2257             }
2258    
2259  //Handles the "intdiv" subextension.        //Try to convert both strings into arbitrary integers.
2260  //07/31/01:  Visually inspected, OK.        GMP_INTS_mpz_set_general_int(&arb_arg1, &failure1, lcm_arg1);
2261  static        GMP_INTS_mpz_set_general_int(&arb_arg2, &failure2, lcm_arg2);
2262  int ARBLENINTS_intdiv_handler(ClientData dummy,  
2263                                Tcl_Interp *interp,        //If there was a parse failure, we have to return an error
2264                                int objc,        //message.  It is possible that both arguments failed the parse,
2265                                Tcl_Obj *objv[])        //but only return one in the error message.
2266     {        if (failure1 || failure2)
2267     Tcl_Obj *rv;           {
2268             rv = Tcl_NewStringObj("arbint intlcm: \"", -1);
2269     //We must have two and exactly two additional arguments           if (failure1)
2270     //to this function, which are the integers whose              Tcl_AppendToObj(rv, lcm_arg1, -1);
2271     //integer quotient is to be calculated.           else
2272     if (objc != 4)              Tcl_AppendToObj(rv, lcm_arg2, -1);
2273        {  
2274        Tcl_WrongNumArgs(interp,           Tcl_AppendToObj(rv, "\" is not a recognized signed integer.", -1);
2275                         2,           Tcl_SetObjResult(interp, rv);
2276                         objv,  
2277                         "sint sint");           GMP_INTS_mpz_clear(&arb_arg1);
2278        return(TCL_ERROR);           GMP_INTS_mpz_clear(&arb_arg2);
2279        }           GMP_INTS_mpz_clear(&gcd);
2280     else           GMP_INTS_mpz_clear(&remainder);
2281        {           GMP_INTS_mpz_clear(&arb_result);
2282        GMP_INTS_mpz_struct arb_dividend, arb_divisor, arb_quotient, arb_remainder;  
2283        char *dividend_arg1, *divisor_arg2;           return(TCL_ERROR);
2284        int failure1, failure2;           }
2285        unsigned chars_reqd;  
2286        char *string_result;        //Adjust errant arguments.
2287        int i, j;        if (GMP_INTS_mpz_is_neg(&arb_arg1))
2288             GMP_INTS_mpz_negate(&arb_arg1);
2289        //Allocate space for the arbitrary-length integer arguments and results.        else if (GMP_INTS_mpz_is_zero(&arb_arg1))
2290        GMP_INTS_mpz_init(&arb_dividend);           GMP_INTS_mpz_set_ui(&arb_arg1, 1);
2291        GMP_INTS_mpz_init(&arb_divisor);        if (GMP_INTS_mpz_is_neg(&arb_arg2))
2292        GMP_INTS_mpz_init(&arb_quotient);           GMP_INTS_mpz_negate(&arb_arg2);
2293        GMP_INTS_mpz_init(&arb_remainder);        else if (GMP_INTS_mpz_is_zero(&arb_arg2))
2294             GMP_INTS_mpz_set_ui(&arb_arg2, 1);
2295        //Grab pointers to the string representation of        
2296        //the input arguments.  The storage does not belong to us.        //Calculate the gcd.
2297        dividend_arg1 = Tcl_GetString(objv[2]);        GMP_INTS_mpz_gcd(&gcd, &arb_arg1, &arb_arg2);
2298        assert(dividend_arg1 != NULL);  
2299        divisor_arg2 = Tcl_GetString(objv[3]);        //Calculate the lcm.
2300        assert(divisor_arg2 != NULL);        GMP_INTS_mpz_mul(&arb_arg1, &arb_arg1, &arb_arg2);
2301          GMP_INTS_mpz_tdiv_qr(&arb_result, &remainder,
2302        //Try to interpret either of the  strings as one of the NAN tags.                             &arb_arg1, &gcd);
2303        //If it is one, return the appropriate result for  
2304        //a binary operation.        //Figure out the number of characters required for
2305        i = GMP_INTS_identify_nan_string(dividend_arg1);        //the output string.
2306        j = GMP_INTS_identify_nan_string(divisor_arg2);        chars_reqd = GMP_INTS_mpz_size_in_base_10(&arb_result);
2307    
2308        if ((i >= 0) || (j >= 0))        //Allocate space for the conversion result.
2309           {        string_result = TclpAlloc(sizeof(char) * chars_reqd);
2310           const char *p;        assert(string_result != NULL);
2311    
2312           //Find the max of i and j.  This isn't a scientific way to tag the        //Make the conversion to a character string.
2313           //result, but will be OK.  Some information is lost no matter what        GMP_INTS_mpz_to_string(string_result, &arb_result);
2314           //we do.  
2315           if (i > j)        //Assign the string result to a Tcl object.
2316              ;        rv = Tcl_NewStringObj(string_result, -1);
2317           else  
2318              i = j;        //Deallocate the string.
2319          TclpFree(string_result);
2320           //i now contains the max.  
2321           switch (i)        //Deallocate space for the arbitrary-length integers.
2322              {        GMP_INTS_mpz_clear(&arb_arg1);
2323              case 0:  p = GMP_INTS_supply_nan_string(2);        GMP_INTS_mpz_clear(&arb_arg2);
2324                       break;        GMP_INTS_mpz_clear(&gcd);
2325              case 1:  p = GMP_INTS_supply_nan_string(3);        GMP_INTS_mpz_clear(&remainder);
2326                       break;        GMP_INTS_mpz_clear(&arb_result);
2327              case 2:  p = GMP_INTS_supply_nan_string(2);  
2328                       break;        //Assign the result to be the return value.
2329              case 3:  p = GMP_INTS_supply_nan_string(3);        Tcl_SetObjResult(interp, rv);
2330                       break;  
2331              default:        //Return
2332                       assert(0);        return(TCL_OK);
2333                       break;        }
2334              }     }
2335    
2336           rv = Tcl_NewStringObj(p, -1);  
2337           Tcl_SetObjResult(interp, rv);  //Handles the "intmod" subextension.
2338    //08/06/01:  Visual inspection OK.
2339           GMP_INTS_mpz_clear(&arb_dividend);  static
2340           GMP_INTS_mpz_clear(&arb_divisor);  int ARBLENINTS_intmod_handler(ClientData dummy,
2341           GMP_INTS_mpz_clear(&arb_quotient);                                Tcl_Interp *interp,
2342           GMP_INTS_mpz_clear(&arb_remainder);                                int objc,
2343                                  Tcl_Obj *objv[])
2344           return(TCL_OK);     {
2345           }     Tcl_Obj *rv;
2346    
2347        //Try to convert both strings into arbitrary integers.     //We must have two and exactly two additional arguments
2348        GMP_INTS_mpz_set_general_int(&arb_dividend, &failure1, dividend_arg1);     //to this function, which are the integers whose
2349        GMP_INTS_mpz_set_general_int(&arb_divisor,  &failure2, divisor_arg2);     //integer quotient is to be calculated.
2350       if (objc != 4)
2351        //If there was a parse failure, we have to return an error        {
2352        //message.  It is possible that both arguments failed the parse,        Tcl_WrongNumArgs(interp,
2353        //but only return one in the error message.                         2,
2354        if (failure1 || failure2)                         objv,
2355           {                         "sint sint");
2356           rv = Tcl_NewStringObj("arbint intdiv: \"", -1);        return(TCL_ERROR);
2357           if (failure1)        }
2358              Tcl_AppendToObj(rv, dividend_arg1, -1);     else
2359           else        {
2360              Tcl_AppendToObj(rv, divisor_arg2, -1);        GMP_INTS_mpz_struct arb_dividend, arb_divisor, arb_quotient, arb_remainder;
2361          char *dividend_arg1, *divisor_arg2;
2362           Tcl_AppendToObj(rv, "\" is not a recognized signed integer.", -1);        int failure1, failure2;
2363           Tcl_SetObjResult(interp, rv);        unsigned chars_reqd;
2364          char *string_result;
2365           GMP_INTS_mpz_clear(&arb_dividend);        int i, j;
2366           GMP_INTS_mpz_clear(&arb_divisor);  
2367           GMP_INTS_mpz_clear(&arb_quotient);        //Allocate space for the arbitrary-length integer arguments and results.
2368           GMP_INTS_mpz_clear(&arb_remainder);        GMP_INTS_mpz_init(&arb_dividend);
2369          GMP_INTS_mpz_init(&arb_divisor);
2370           return(TCL_ERROR);        GMP_INTS_mpz_init(&arb_quotient);
2371           }        GMP_INTS_mpz_init(&arb_remainder);
2372    
2373        //Calculate the quotient.        //Grab pointers to the string representation of
2374        GMP_INTS_mpz_tdiv_qr(&arb_quotient, &arb_remainder, &arb_dividend, &arb_divisor);        //the input arguments.  The storage does not belong to us.
2375          dividend_arg1 = Tcl_GetString(objv[2]);
2376        //Figure out the number of characters required for        assert(dividend_arg1 != NULL);
2377        //the output string.        divisor_arg2 = Tcl_GetString(objv[3]);
2378        chars_reqd = GMP_INTS_mpz_size_in_base_10(&arb_quotient);        assert(divisor_arg2 != NULL);
2379    
2380        //Allocate space for the conversion result.        //Try to interpret either of the  strings as one of the NAN tags.
2381        string_result = TclpAlloc(sizeof(char) * chars_reqd);        //If it is one, return the appropriate result for
2382        assert(string_result != NULL);        //a binary operation.
2383          i = GMP_INTS_identify_nan_string(dividend_arg1);
2384        //Make the conversion to a character string.        j = GMP_INTS_identify_nan_string(divisor_arg2);
2385        GMP_INTS_mpz_to_string(string_result, &arb_quotient);  
2386          if ((i >= 0) || (j >= 0))
2387        //Assign the string result to a Tcl object.           {
2388        rv = Tcl_NewStringObj(string_result, -1);           const char *p;
2389    
2390        //Deallocate the string.           //Find the max of i and j.  This isn't a scientific way to tag the
2391        TclpFree(string_result);           //result, but will be OK.  Some information is lost no matter what
2392             //we do.
2393        //Deallocate space for the arbitrary-length integers.           if (i > j)
2394        GMP_INTS_mpz_clear(&arb_dividend);              ;
2395        GMP_INTS_mpz_clear(&arb_divisor);           else
2396        GMP_INTS_mpz_clear(&arb_quotient);              i = j;
2397        GMP_INTS_mpz_clear(&arb_remainder);  
2398             //i now contains the max.
2399        //Assign the result to be the return value.           switch (i)
2400        Tcl_SetObjResult(interp, rv);              {
2401                case 0:  p = GMP_INTS_supply_nan_string(2);
2402        //Return                       break;
2403        return(TCL_OK);              case 1:  p = GMP_INTS_supply_nan_string(3);
2404        }                       break;
2405     }              case 2:  p = GMP_INTS_supply_nan_string(2);
2406                         break;
2407                case 3:  p = GMP_INTS_supply_nan_string(3);
2408  //08/01/01:  Visually inspected.                       break;
2409  //Handles the "intexp" subextension.              default:
2410  static                       assert(0);
2411  int ARBLENINTS_intexp_handler(ClientData dummy,                       break;
2412                                Tcl_Interp *interp,              }
2413                                int objc,  
2414                                Tcl_Obj *objv[])           rv = Tcl_NewStringObj(p, -1);
2415     {           Tcl_SetObjResult(interp, rv);
2416     Tcl_Obj *rv;  
2417             GMP_INTS_mpz_clear(&arb_dividend);
2418     //We must have two and exactly two additional arguments           GMP_INTS_mpz_clear(&arb_divisor);
2419     //to this function, which are the integers used to           GMP_INTS_mpz_clear(&arb_quotient);
2420     //cal