/[dtapublic]/sf_code/esrgpubs/acm0010/c_imp/rap/rap_c.c
ViewVC logotype

Contents of /sf_code/esrgpubs/acm0010/c_imp/rap/rap_c.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 24 - (show annotations) (download)
Sat Oct 8 06:15:00 2016 UTC (7 years, 5 months ago) by dashley
File MIME type: text/plain
File size: 583746 byte(s)
Initial commit.
1 /* $Archive:: /ACM Rational Approximation Paper And Algorithms/C-Language Implementation/rap_c.c $ */
2 /* $Revision: 1.1 $ */
3 /* $Date: 2001/09/25 21:44:55 $ */
4 /* $Author: dtashley $ */
5 /* $Workfile:: rap_c.c $ */
6 /*
7 /*
8 //--------------------------------------------------------------------------------
9 //Copyright 2008 David T. Ashley
10 //-------------------------------------------------------------------------------------------------
11 //This source code and any program in which it is compiled/used is provided under the GNU GENERAL
12 //PUBLIC LICENSE, Version 3, full license text below.
13 //-------------------------------------------------------------------------------------------------
14 // GNU GENERAL PUBLIC LICENSE
15 // Version 3, 29 June 2007
16 //
17 // Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
18 // Everyone is permitted to copy and distribute verbatim copies
19 // of this license document, but changing it is not allowed.
20 //
21 // Preamble
22 //
23 // The GNU General Public License is a free, copyleft license for
24 //software and other kinds of works.
25 //
26 // The licenses for most software and other practical works are designed
27 //to take away your freedom to share and change the works. By contrast,
28 //the GNU General Public License is intended to guarantee your freedom to
29 //share and change all versions of a program--to make sure it remains free
30 //software for all its users. We, the Free Software Foundation, use the
31 //GNU General Public License for most of our software; it applies also to
32 //any other work released this way by its authors. You can apply it to
33 //your programs, too.
34 //
35 // When we speak of free software, we are referring to freedom, not
36 //price. Our General Public Licenses are designed to make sure that you
37 //have the freedom to distribute copies of free software (and charge for
38 //them if you wish), that you receive source code or can get it if you
39 //want it, that you can change the software or use pieces of it in new
40 //free programs, and that you know you can do these things.
41 //
42 // To protect your rights, we need to prevent others from denying you
43 //these rights or asking you to surrender the rights. Therefore, you have
44 //certain responsibilities if you distribute copies of the software, or if
45 //you modify it: responsibilities to respect the freedom of others.
46 //
47 // For example, if you distribute copies of such a program, whether
48 //gratis or for a fee, you must pass on to the recipients the same
49 //freedoms that you received. You must make sure that they, too, receive
50 //or can get the source code. And you must show them these terms so they
51 //know their rights.
52 //
53 // Developers that use the GNU GPL protect your rights with two steps:
54 //(1) assert copyright on the software, and (2) offer you this License
55 //giving you legal permission to copy, distribute and/or modify it.
56 //
57 // For the developers' and authors' protection, the GPL clearly explains
58 //that there is no warranty for this free software. For both users' and
59 //authors' sake, the GPL requires that modified versions be marked as
60 //changed, so that their problems will not be attributed erroneously to
61 //authors of previous versions.
62 //
63 // Some devices are designed to deny users access to install or run
64 //modified versions of the software inside them, although the manufacturer
65 //can do so. This is fundamentally incompatible with the aim of
66 //protecting users' freedom to change the software. The systematic
67 //pattern of such abuse occurs in the area of products for individuals to
68 //use, which is precisely where it is most unacceptable. Therefore, we
69 //have designed this version of the GPL to prohibit the practice for those
70 //products. If such problems arise substantially in other domains, we
71 //stand ready to extend this provision to those domains in future versions
72 //of the GPL, as needed to protect the freedom of users.
73 //
74 // Finally, every program is threatened constantly by software patents.
75 //States should not allow patents to restrict development and use of
76 //software on general-purpose computers, but in those that do, we wish to
77 //avoid the special danger that patents applied to a free program could
78 //make it effectively proprietary. To prevent this, the GPL assures that
79 //patents cannot be used to render the program non-free.
80 //
81 // The precise terms and conditions for copying, distribution and
82 //modification follow.
83 //
84 // TERMS AND CONDITIONS
85 //
86 // 0. Definitions.
87 //
88 // "This License" refers to version 3 of the GNU General Public License.
89 //
90 // "Copyright" also means copyright-like laws that apply to other kinds of
91 //works, such as semiconductor masks.
92 //
93 // "The Program" refers to any copyrightable work licensed under this
94 //License. Each licensee is addressed as "you". "Licensees" and
95 //"recipients" may be individuals or organizations.
96 //
97 // To "modify" a work means to copy from or adapt all or part of the work
98 //in a fashion requiring copyright permission, other than the making of an
99 //exact copy. The resulting work is called a "modified version" of the
100 //earlier work or a work "based on" the earlier work.
101 //
102 // A "covered work" means either the unmodified Program or a work based
103 //on the Program.
104 //
105 // To "propagate" a work means to do anything with it that, without
106 //permission, would make you directly or secondarily liable for
107 //infringement under applicable copyright law, except executing it on a
108 //computer or modifying a private copy. Propagation includes copying,
109 //distribution (with or without modification), making available to the
110 //public, and in some countries other activities as well.
111 //
112 // To "convey" a work means any kind of propagation that enables other
113 //parties to make or receive copies. Mere interaction with a user through
114 //a computer network, with no transfer of a copy, is not conveying.
115 //
116 // An interactive user interface displays "Appropriate Legal Notices"
117 //to the extent that it includes a convenient and prominently visible
118 //feature that (1) displays an appropriate copyright notice, and (2)
119 //tells the user that there is no warranty for the work (except to the
120 //extent that warranties are provided), that licensees may convey the
121 //work under this License, and how to view a copy of this License. If
122 //the interface presents a list of user commands or options, such as a
123 //menu, a prominent item in the list meets this criterion.
124 //
125 // 1. Source Code.
126 //
127 // The "source code" for a work means the preferred form of the work
128 //for making modifications to it. "Object code" means any non-source
129 //form of a work.
130 //
131 // A "Standard Interface" means an interface that either is an official
132 //standard defined by a recognized standards body, or, in the case of
133 //interfaces specified for a particular programming language, one that
134 //is widely used among developers working in that language.
135 //
136 // The "System Libraries" of an executable work include anything, other
137 //than the work as a whole, that (a) is included in the normal form of
138 //packaging a Major Component, but which is not part of that Major
139 //Component, and (b) serves only to enable use of the work with that
140 //Major Component, or to implement a Standard Interface for which an
141 //implementation is available to the public in source code form. A
142 //"Major Component", in this context, means a major essential component
143 //(kernel, window system, and so on) of the specific operating system
144 //(if any) on which the executable work runs, or a compiler used to
145 //produce the work, or an object code interpreter used to run it.
146 //
147 // The "Corresponding Source" for a work in object code form means all
148 //the source code needed to generate, install, and (for an executable
149 //work) run the object code and to modify the work, including scripts to
150 //control those activities. However, it does not include the work's
151 //System Libraries, or general-purpose tools or generally available free
152 //programs which are used unmodified in performing those activities but
153 //which are not part of the work. For example, Corresponding Source
154 //includes interface definition files associated with source files for
155 //the work, and the source code for shared libraries and dynamically
156 //linked subprograms that the work is specifically designed to require,
157 //such as by intimate data communication or control flow between those
158 //subprograms and other parts of the work.
159 //
160 // The Corresponding Source need not include anything that users
161 //can regenerate automatically from other parts of the Corresponding
162 //Source.
163 //
164 // The Corresponding Source for a work in source code form is that
165 //same work.
166 //
167 // 2. Basic Permissions.
168 //
169 // All rights granted under this License are granted for the term of
170 //copyright on the Program, and are irrevocable provided the stated
171 //conditions are met. This License explicitly affirms your unlimited
172 //permission to run the unmodified Program. The output from running a
173 //covered work is covered by this License only if the output, given its
174 //content, constitutes a covered work. This License acknowledges your
175 //rights of fair use or other equivalent, as provided by copyright law.
176 //
177 // You may make, run and propagate covered works that you do not
178 //convey, without conditions so long as your license otherwise remains
179 //in force. You may convey covered works to others for the sole purpose
180 //of having them make modifications exclusively for you, or provide you
181 //with facilities for running those works, provided that you comply with
182 //the terms of this License in conveying all material for which you do
183 //not control copyright. Those thus making or running the covered works
184 //for you must do so exclusively on your behalf, under your direction
185 //and control, on terms that prohibit them from making any copies of
186 //your copyrighted material outside their relationship with you.
187 //
188 // Conveying under any other circumstances is permitted solely under
189 //the conditions stated below. Sublicensing is not allowed; section 10
190 //makes it unnecessary.
191 //
192 // 3. Protecting Users' Legal Rights From Anti-Circumvention Law.
193 //
194 // No covered work shall be deemed part of an effective technological
195 //measure under any applicable law fulfilling obligations under article
196 //11 of the WIPO copyright treaty adopted on 20 December 1996, or
197 //similar laws prohibiting or restricting circumvention of such
198 //measures.
199 //
200 // When you convey a covered work, you waive any legal power to forbid
201 //circumvention of technological measures to the extent such circumvention
202 //is effected by exercising rights under this License with respect to
203 //the covered work, and you disclaim any intention to limit operation or
204 //modification of the work as a means of enforcing, against the work's
205 //users, your or third parties' legal rights to forbid circumvention of
206 //technological measures.
207 //
208 // 4. Conveying Verbatim Copies.
209 //
210 // You may convey verbatim copies of the Program's source code as you
211 //receive it, in any medium, provided that you conspicuously and
212 //appropriately publish on each copy an appropriate copyright notice;
213 //keep intact all notices stating that this License and any
214 //non-permissive terms added in accord with section 7 apply to the code;
215 //keep intact all notices of the absence of any warranty; and give all
216 //recipients a copy of this License along with the Program.
217 //
218 // You may charge any price or no price for each copy that you convey,
219 //and you may offer support or warranty protection for a fee.
220 //
221 // 5. Conveying Modified Source Versions.
222 //
223 // You may convey a work based on the Program, or the modifications to
224 //produce it from the Program, in the form of source code under the
225 //terms of section 4, provided that you also meet all of these conditions:
226 //
227 // a) The work must carry prominent notices stating that you modified
228 // it, and giving a relevant date.
229 //
230 // b) The work must carry prominent notices stating that it is
231 // released under this License and any conditions added under section
232 // 7. This requirement modifies the requirement in section 4 to
233 // "keep intact all notices".
234 //
235 // c) You must license the entire work, as a whole, under this
236 // License to anyone who comes into possession of a copy. This
237 // License will therefore apply, along with any applicable section 7
238 // additional terms, to the whole of the work, and all its parts,
239 // regardless of how they are packaged. This License gives no
240 // permission to license the work in any other way, but it does not
241 // invalidate such permission if you have separately received it.
242 //
243 // d) If the work has interactive user interfaces, each must display
244 // Appropriate Legal Notices; however, if the Program has interactive
245 // interfaces that do not display Appropriate Legal Notices, your
246 // work need not make them do so.
247 //
248 // A compilation of a covered work with other separate and independent
249 //works, which are not by their nature extensions of the covered work,
250 //and which are not combined with it such as to form a larger program,
251 //in or on a volume of a storage or distribution medium, is called an
252 //"aggregate" if the compilation and its resulting copyright are not
253 //used to limit the access or legal rights of the compilation's users
254 //beyond what the individual works permit. Inclusion of a covered work
255 //in an aggregate does not cause this License to apply to the other
256 //parts of the aggregate.
257 //
258 // 6. Conveying Non-Source Forms.
259 //
260 // You may convey a covered work in object code form under the terms
261 //of sections 4 and 5, provided that you also convey the
262 //machine-readable Corresponding Source under the terms of this License,
263 //in one of these ways:
264 //
265 // a) Convey the object code in, or embodied in, a physical product
266 // (including a physical distribution medium), accompanied by the
267 // Corresponding Source fixed on a durable physical medium
268 // customarily used for software interchange.
269 //
270 // b) Convey the object code in, or embodied in, a physical product
271 // (including a physical distribution medium), accompanied by a
272 // written offer, valid for at least three years and valid for as
273 // long as you offer spare parts or customer support for that product
274 // model, to give anyone who possesses the object code either (1) a
275 // copy of the Corresponding Source for all the software in the
276 // product that is covered by this License, on a durable physical
277 // medium customarily used for software interchange, for a price no
278 // more than your reasonable cost of physically performing this
279 // conveying of source, or (2) access to copy the
280 // Corresponding Source from a network server at no charge.
281 //
282 // c) Convey individual copies of the object code with a copy of the
283 // written offer to provide the Corresponding Source. This
284 // alternative is allowed only occasionally and noncommercially, and
285 // only if you received the object code with such an offer, in accord
286 // with subsection 6b.
287 //
288 // d) Convey the object code by offering access from a designated
289 // place (gratis or for a charge), and offer equivalent access to the
290 // Corresponding Source in the same way through the same place at no
291 // further charge. You need not require recipients to copy the
292 // Corresponding Source along with the object code. If the place to
293 // copy the object code is a network server, the Corresponding Source
294 // may be on a different server (operated by you or a third party)
295 // that supports equivalent copying facilities, provided you maintain
296 // clear directions next to the object code saying where to find the
297 // Corresponding Source. Regardless of what server hosts the
298 // Corresponding Source, you remain obligated to ensure that it is
299 // available for as long as needed to satisfy these requirements.
300 //
301 // e) Convey the object code using peer-to-peer transmission, provided
302 // you inform other peers where the object code and Corresponding
303 // Source of the work are being offered to the general public at no
304 // charge under subsection 6d.
305 //
306 // A separable portion of the object code, whose source code is excluded
307 //from the Corresponding Source as a System Library, need not be
308 //included in conveying the object code work.
309 //
310 // A "User Product" is either (1) a "consumer product", which means any
311 //tangible personal property which is normally used for personal, family,
312 //or household purposes, or (2) anything designed or sold for incorporation
313 //into a dwelling. In determining whether a product is a consumer product,
314 //doubtful cases shall be resolved in favor of coverage. For a particular
315 //product received by a particular user, "normally used" refers to a
316 //typical or common use of that class of product, regardless of the status
317 //of the particular user or of the way in which the particular user
318 //actually uses, or expects or is expected to use, the product. A product
319 //is a consumer product regardless of whether the product has substantial
320 //commercial, industrial or non-consumer uses, unless such uses represent
321 //the only significant mode of use of the product.
322 //
323 // "Installation Information" for a User Product means any methods,
324 //procedures, authorization keys, or other information required to install
325 //and execute modified versions of a covered work in that User Product from
326 //a modified version of its Corresponding Source. The information must
327 //suffice to ensure that the continued functioning of the modified object
328 //code is in no case prevented or interfered with solely because
329 //modification has been made.
330 //
331 // If you convey an object code work under this section in, or with, or
332 //specifically for use in, a User Product, and the conveying occurs as
333 //part of a transaction in which the right of possession and use of the
334 //User Product is transferred to the recipient in perpetuity or for a
335 //fixed term (regardless of how the transaction is characterized), the
336 //Corresponding Source conveyed under this section must be accompanied
337 //by the Installation Information. But this requirement does not apply
338 //if neither you nor any third party retains the ability to install
339 //modified object code on the User Product (for example, the work has
340 //been installed in ROM).
341 //
342 // The requirement to provide Installation Information does not include a
343 //requirement to continue to provide support service, warranty, or updates
344 //for a work that has been modified or installed by the recipient, or for
345 //the User Product in which it has been modified or installed. Access to a
346 //network may be denied when the modification itself materially and
347 //adversely affects the operation of the network or violates the rules and
348 //protocols for communication across the network.
349 //
350 // Corresponding Source conveyed, and Installation Information provided,
351 //in accord with this section must be in a format that is publicly
352 //documented (and with an implementation available to the public in
353 //source code form), and must require no special password or key for
354 //unpacking, reading or copying.
355 //
356 // 7. Additional Terms.
357 //
358 // "Additional permissions" are terms that supplement the terms of this
359 //License by making exceptions from one or more of its conditions.
360 //Additional permissions that are applicable to the entire Program shall
361 //be treated as though they were included in this License, to the extent
362 //that they are valid under applicable law. If additional permissions
363 //apply only to part of the Program, that part may be used separately
364 //under those permissions, but the entire Program remains governed by
365 //this License without regard to the additional permissions.
366 //
367 // When you convey a copy of a covered work, you may at your option
368 //remove any additional permissions from that copy, or from any part of
369 //it. (Additional permissions may be written to require their own
370 //removal in certain cases when you modify the work.) You may place
371 //additional permissions on material, added by you to a covered work,
372 //for which you have or can give appropriate copyright permission.
373 //
374 // Notwithstanding any other provision of this License, for material you
375 //add to a covered work, you may (if authorized by the copyright holders of
376 //that material) supplement the terms of this License with terms:
377 //
378 // a) Disclaiming warranty or limiting liability differently from the
379 // terms of sections 15 and 16 of this License; or
380 //
381 // b) Requiring preservation of specified reasonable legal notices or
382 // author attributions in that material or in the Appropriate Legal
383 // Notices displayed by works containing it; or
384 //
385 // c) Prohibiting misrepresentation of the origin of that material, or
386 // requiring that modified versions of such material be marked in
387 // reasonable ways as different from the original version; or
388 //
389 // d) Limiting the use for publicity purposes of names of licensors or
390 // authors of the material; or
391 //
392 // e) Declining to grant rights under trademark law for use of some
393 // trade names, trademarks, or service marks; or
394 //
395 // f) Requiring indemnification of licensors and authors of that
396 // material by anyone who conveys the material (or modified versions of
397 // it) with contractual assumptions of liability to the recipient, for
398 // any liability that these contractual assumptions directly impose on
399 // those licensors and authors.
400 //
401 // All other non-permissive additional terms are considered "further
402 //restrictions" within the meaning of section 10. If the Program as you
403 //received it, or any part of it, contains a notice stating that it is
404 //governed by this License along with a term that is a further
405 //restriction, you may remove that term. If a license document contains
406 //a further restriction but permits relicensing or conveying under this
407 //License, you may add to a covered work material governed by the terms
408 //of that license document, provided that the further restriction does
409 //not survive such relicensing or conveying.
410 //
411 // If you add terms to a covered work in accord with this section, you
412 //must place, in the relevant source files, a statement of the
413 //additional terms that apply to those files, or a notice indicating
414 //where to find the applicable terms.
415 //
416 // Additional terms, permissive or non-permissive, may be stated in the
417 //form of a separately written license, or stated as exceptions;
418 //the above requirements apply either way.
419 //
420 // 8. Termination.
421 //
422 // You may not propagate or modify a covered work except as expressly
423 //provided under this License. Any attempt otherwise to propagate or
424 //modify it is void, and will automatically terminate your rights under
425 //this License (including any patent licenses granted under the third
426 //paragraph of section 11).
427 //
428 // However, if you cease all violation of this License, then your
429 //license from a particular copyright holder is reinstated (a)
430 //provisionally, unless and until the copyright holder explicitly and
431 //finally terminates your license, and (b) permanently, if the copyright
432 //holder fails to notify you of the violation by some reasonable means
433 //prior to 60 days after the cessation.
434 //
435 // Moreover, your license from a particular copyright holder is
436 //reinstated permanently if the copyright holder notifies you of the
437 //violation by some reasonable means, this is the first time you have
438 //received notice of violation of this License (for any work) from that
439 //copyright holder, and you cure the violation prior to 30 days after
440 //your receipt of the notice.
441 //
442 // Termination of your rights under this section does not terminate the
443 //licenses of parties who have received copies or rights from you under
444 //this License. If your rights have been terminated and not permanently
445 //reinstated, you do not qualify to receive new licenses for the same
446 //material under section 10.
447 //
448 // 9. Acceptance Not Required for Having Copies.
449 //
450 // You are not required to accept this License in order to receive or
451 //run a copy of the Program. Ancillary propagation of a covered work
452 //occurring solely as a consequence of using peer-to-peer transmission
453 //to receive a copy likewise does not require acceptance. However,
454 //nothing other than this License grants you permission to propagate or
455 //modify any covered work. These actions infringe copyright if you do
456 //not accept this License. Therefore, by modifying or propagating a
457 //covered work, you indicate your acceptance of this License to do so.
458 //
459 // 10. Automatic Licensing of Downstream Recipients.
460 //
461 // Each time you convey a covered work, the recipient automatically
462 //receives a license from the original licensors, to run, modify and
463 //propagate that work, subject to this License. You are not responsible
464 //for enforcing compliance by third parties with this License.
465 //
466 // An "entity transaction" is a transaction transferring control of an
467 //organization, or substantially all assets of one, or subdividing an
468 //organization, or merging organizations. If propagation of a covered
469 //work results from an entity transaction, each party to that
470 //transaction who receives a copy of the work also receives whatever
471 //licenses to the work the party's predecessor in interest had or could
472 //give under the previous paragraph, plus a right to possession of the
473 //Corresponding Source of the work from the predecessor in interest, if
474 //the predecessor has it or can get it with reasonable efforts.
475 //
476 // You may not impose any further restrictions on the exercise of the
477 //rights granted or affirmed under this License. For example, you may
478 //not impose a license fee, royalty, or other charge for exercise of
479 //rights granted under this License, and you may not initiate litigation
480 //(including a cross-claim or counterclaim in a lawsuit) alleging that
481 //any patent claim is infringed by making, using, selling, offering for
482 //sale, or importing the Program or any portion of it.
483 //
484 // 11. Patents.
485 //
486 // A "contributor" is a copyright holder who authorizes use under this
487 //License of the Program or a work on which the Program is based. The
488 //work thus licensed is called the contributor's "contributor version".
489 //
490 // A contributor's "essential patent claims" are all patent claims
491 //owned or controlled by the contributor, whether already acquired or
492 //hereafter acquired, that would be infringed by some manner, permitted
493 //by this License, of making, using, or selling its contributor version,
494 //but do not include claims that would be infringed only as a
495 //consequence of further modification of the contributor version. For
496 //purposes of this definition, "control" includes the right to grant
497 //patent sublicenses in a manner consistent with the requirements of
498 //this License.
499 //
500 // Each contributor grants you a non-exclusive, worldwide, royalty-free
501 //patent license under the contributor's essential patent claims, to
502 //make, use, sell, offer for sale, import and otherwise run, modify and
503 //propagate the contents of its contributor version.
504 //
505 // In the following three paragraphs, a "patent license" is any express
506 //agreement or commitment, however denominated, not to enforce a patent
507 //(such as an express permission to practice a patent or covenant not to
508 //sue for patent infringement). To "grant" such a patent license to a
509 //party means to make such an agreement or commitment not to enforce a
510 //patent against the party.
511 //
512 // If you convey a covered work, knowingly relying on a patent license,
513 //and the Corresponding Source of the work is not available for anyone
514 //to copy, free of charge and under the terms of this License, through a
515 //publicly available network server or other readily accessible means,
516 //then you must either (1) cause the Corresponding Source to be so
517 //available, or (2) arrange to deprive yourself of the benefit of the
518 //patent license for this particular work, or (3) arrange, in a manner
519 //consistent with the requirements of this License, to extend the patent
520 //license to downstream recipients. "Knowingly relying" means you have
521 //actual knowledge that, but for the patent license, your conveying the
522 //covered work in a country, or your recipient's use of the covered work
523 //in a country, would infringe one or more identifiable patents in that
524 //country that you have reason to believe are valid.
525 //
526 // If, pursuant to or in connection with a single transaction or
527 //arrangement, you convey, or propagate by procuring conveyance of, a
528 //covered work, and grant a patent license to some of the parties
529 //receiving the covered work authorizing them to use, propagate, modify
530 //or convey a specific copy of the covered work, then the patent license
531 //you grant is automatically extended to all recipients of the covered
532 //work and works based on it.
533 //
534 // A patent license is "discriminatory" if it does not include within
535 //the scope of its coverage, prohibits the exercise of, or is
536 //conditioned on the non-exercise of one or more of the rights that are
537 //specifically granted under this License. You may not convey a covered
538 //work if you are a party to an arrangement with a third party that is
539 //in the business of distributing software, under which you make payment
540 //to the third party based on the extent of your activity of conveying
541 //the work, and under which the third party grants, to any of the
542 //parties who would receive the covered work from you, a discriminatory
543 //patent license (a) in connection with copies of the covered work
544 //conveyed by you (or copies made from those copies), or (b) primarily
545 //for and in connection with specific products or compilations that
546 //contain the covered work, unless you entered into that arrangement,
547 //or that patent license was granted, prior to 28 March 2007.
548 //
549 // Nothing in this License shall be construed as excluding or limiting
550 //any implied license or other defenses to infringement that may
551 //otherwise be available to you under applicable patent law.
552 //
553 // 12. No Surrender of Others' Freedom.
554 //
555 // If conditions are imposed on you (whether by court order, agreement or
556 //otherwise) that contradict the conditions of this License, they do not
557 //excuse you from the conditions of this License. If you cannot convey a
558 //covered work so as to satisfy simultaneously your obligations under this
559 //License and any other pertinent obligations, then as a consequence you may
560 //not convey it at all. For example, if you agree to terms that obligate you
561 //to collect a royalty for further conveying from those to whom you convey
562 //the Program, the only way you could satisfy both those terms and this
563 //License would be to refrain entirely from conveying the Program.
564 //
565 // 13. Use with the GNU Affero General Public License.
566 //
567 // Notwithstanding any other provision of this License, you have
568 //permission to link or combine any covered work with a work licensed
569 //under version 3 of the GNU Affero General Public License into a single
570 //combined work, and to convey the resulting work. The terms of this
571 //License will continue to apply to the part which is the covered work,
572 //but the special requirements of the GNU Affero General Public License,
573 //section 13, concerning interaction through a network will apply to the
574 //combination as such.
575 //
576 // 14. Revised Versions of this License.
577 //
578 // The Free Software Foundation may publish revised and/or new versions of
579 //the GNU General Public License from time to time. Such new versions will
580 //be similar in spirit to the present version, but may differ in detail to
581 //address new problems or concerns.
582 //
583 // Each version is given a distinguishing version number. If the
584 //Program specifies that a certain numbered version of the GNU General
585 //Public License "or any later version" applies to it, you have the
586 //option of following the terms and conditions either of that numbered
587 //version or of any later version published by the Free Software
588 //Foundation. If the Program does not specify a version number of the
589 //GNU General Public License, you may choose any version ever published
590 //by the Free Software Foundation.
591 //
592 // If the Program specifies that a proxy can decide which future
593 //versions of the GNU General Public License can be used, that proxy's
594 //public statement of acceptance of a version permanently authorizes you
595 //to choose that version for the Program.
596 //
597 // Later license versions may give you additional or different
598 //permissions. However, no additional obligations are imposed on any
599 //author or copyright holder as a result of your choosing to follow a
600 //later version.
601 //
602 // 15. Disclaimer of Warranty.
603 //
604 // THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
605 //APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
606 //HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
607 //OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
608 //THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
609 //PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
610 //IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
611 //ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
612 //
613 // 16. Limitation of Liability.
614 //
615 // IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
616 //WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
617 //THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
618 //GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
619 //USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
620 //DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
621 //PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
622 //EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
623 //SUCH DAMAGES.
624 //
625 // 17. Interpretation of Sections 15 and 16.
626 //
627 // If the disclaimer of warranty and limitation of liability provided
628 //above cannot be given local legal effect according to their terms,
629 //reviewing courts shall apply local law that most closely approximates
630 //an absolute waiver of all civil liability in connection with the
631 //Program, unless a warranty or assumption of liability accompanies a
632 //copy of the Program in return for a fee.
633 //
634 // END OF TERMS AND CONDITIONS
635 //
636 // How to Apply These Terms to Your New Programs
637 //
638 // If you develop a new program, and you want it to be of the greatest
639 //possible use to the public, the best way to achieve this is to make it
640 //free software which everyone can redistribute and change under these terms.
641 //
642 // To do so, attach the following notices to the program. It is safest
643 //to attach them to the start of each source file to most effectively
644 //state the exclusion of warranty; and each file should have at least
645 //the "copyright" line and a pointer to where the full notice is found.
646 //
647 // <one line to give the program's name and a brief idea of what it does.>
648 // Copyright (C) <year> <name of author>
649 //
650 // This program is free software: you can redistribute it and/or modify
651 // it under the terms of the GNU General Public License as published by
652 // the Free Software Foundation, either version 3 of the License, or
653 // (at your option) any later version.
654 //
655 // This program is distributed in the hope that it will be useful,
656 // but WITHOUT ANY WARRANTY; without even the implied warranty of
657 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
658 // GNU General Public License for more details.
659 //
660 // You should have received a copy of the GNU General Public License
661 // along with this program. If not, see <http://www.gnu.org/licenses/>.
662 //
663 //Also add information on how to contact you by electronic and paper mail.
664 //
665 // If the program does terminal interaction, make it output a short
666 //notice like this when it starts in an interactive mode:
667 //
668 // <program> Copyright (C) <year> <name of author>
669 // This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
670 // This is free software, and you are welcome to redistribute it
671 // under certain conditions; type `show c' for details.
672 //
673 //The hypothetical commands `show w' and `show c' should show the appropriate
674 //parts of the General Public License. Of course, your program's commands
675 //might be different; for a GUI interface, you would use an "about box".
676 //
677 // You should also get your employer (if you work as a programmer) or school,
678 //if any, to sign a "copyright disclaimer" for the program, if necessary.
679 //For more information on this, and how to apply and follow the GNU GPL, see
680 //<http://www.gnu.org/licenses/>.
681 //
682 // The GNU General Public License does not permit incorporating your program
683 //into proprietary programs. If your program is a subroutine library, you
684 //may consider it more useful to permit linking proprietary applications with
685 //the library. If this is what you want to do, use the GNU Lesser General
686 //Public License instead of this License. But first, please read
687 //<http://www.gnu.org/philosophy/why-not-lgpl.html>.
688 //-------------------------------------------------------------------------------------------------
689 //--------------------------------------------------------------------------------
690 ** Rational Approximation Software Submitted To CALGO To Accompany TOMS Paper
691 ** Entitled "On Best Rational Approximations Using Large Integers"
692 ** --------------------------------------------------------------------------
693 ** Please see accompanying user's guide for invocation instructions.
694 */
695
696 #include <process.h>
697 /* For the exit() function. */
698
699 #include <stdio.h>
700 /* printf() and similar functions require the stdio.h header file. */
701
702 #include <string.h>
703 /* String functions and memory manipulation functions defined there. */
704
705 #include <malloc.h>
706 /* Necessary for memory allocation functions. */
707
708
709 /* It wasn't straightforward to locate the file containing the constants TRUE
710 ** and FALSE. Must define them myself.
711 */
712 #ifndef FALSE
713 #define FALSE (0)
714 #endif
715 #ifndef TRUE
716 #define TRUE (1)
717 #endif
718
719
720 /* This source file is broken into segments, each
721 ** containing a specific family of functions
722 ** that operate on a specific data type, or at a
723 ** specific level of abstraction. In C++, these
724 ** would often tend to be made into classes (and
725 ** this could be done here), but it is a more
726 ** humane experience on anyone who would like to
727 ** recompile the program to keep everything in a
728 ** single source file.
729 **
730 ** Functions are arranged from the bottom of the calling tree upward. This
731 ** way, no function prototypes are needed to ensure the compiler will
732 ** detect definitions and invocations which are inconsistent.
733 */
734
735 /****************************************************************************/
736 /****************************************************************************/
737 /************* C O M P I L A T I O N C O N S T A N T S ***************/
738 /****************************************************************************/
739 /****************************************************************************/
740 /* Many aspects of the program's behavior can be changed by simply changing
741 ** the constants below. Many of the values chosen below are intended to
742 ** keep the software clear of platform-specific limits. Changes to the
743 ** constants may cause unforeseen difficulties.
744 */
745 #define MAX_CMDLINE_PARS (10)
746 /* The maximum number of command-line parameters that will be accepted.
747 ** This is ultimately dependent on what the subcommands take, but
748 ** 10 is a safe value, and let's me be lazy and not search to find the
749 ** command that takes the most parameters.
750 */
751
752 #define INPUT_INTEGER_MAX_DIGITS (463)
753 /* This value was chosen to allow operation in the Farey series of up to
754 ** order 2**1536.
755 */
756 #define INTERMEDIATE_CALC_MAX_DIGITS (4000)
757 /* This value wasn't chosen scientifically. It is just known that
758 ** multiplying a 463-digit integer by another will result in at most
759 ** a 926-digit result ... it would be quite difficult in the calculations
760 ** outlined in the TOMS paper to reach the 4,000 digit limit. Note that
761 ** this is also the limit for the size of the integer components of
762 ** rational results.
763 */
764 #define STDIN_MAX_CHARS (32000)
765 /* The maximum number of digits that may be read from the standard input
766 ** if batch mode is selected.
767 */
768 #define LINE_LEN (78)
769 /* The number of columns assumed to be displayable on the output.
770 ** because a standard monitor (legacy) was 80 columns wide, I've chosen
771 ** a value just a tad less.
772 */
773 #define NUMBER_DESC_WIDTH (20)
774 /* The number of characters at the left reserved for describing a particular
775 ** integer.
776 */
777 #define DIGITS_PER_LINE (27)
778 /* The number of digits to be displayed per line for very long
779 ** integers.
780 */
781 #define HORIZONTAL_BAR_SEP_CHAR ('-')
782 /* The character used to form large horizontal separators.
783 */
784
785 /****************************************************************************/
786 /****************************************************************************/
787 /********* V E R S I O N C O N T R O L F U N C T I O N S ***********/
788 /****************************************************************************/
789 /****************************************************************************/
790
791 /****************************************************************************/
792 /* vcGetVcData(): */
793 /*--------------------------------------------------------------------------*/
794 /* DESCRIPTION */
795 /* Returns the embedded version control information for this program, */
796 /* arranged as a sequence of lines to be displayed on an 80-column */
797 /* monitor. */
798 /* */
799 /* INPUTS */
800 /* n : Line number to return. The first line is number 0. */
801 /* */
802 /* OUTPUTS */
803 /* <--: Pointer to a constant character string to display on that line, */
804 /* or NULL if there are no more lines of version control */
805 /* information to display. */
806 /****************************************************************************/
807 const char *vcGetVcData(unsigned n)
808 {
809 const char *RAP_version_string_array[]
810 = {"$Revision: 1.1 $ $Date: 2001/09/25 21:44:55 $"};
811 /* Note that the info above is filled in automatically by Visual
812 ** Source Safe on every check-in--this is not manually maintained.
813 */
814
815 if (n < (sizeof(RAP_version_string_array)/sizeof(RAP_version_string_array[0])))
816 {
817 return(RAP_version_string_array[n]);
818 }
819 else
820 {
821 return(NULL);
822 }
823 }
824
825
826 /****************************************************************************/
827 /****************************************************************************/
828 /****** G E N E R A L F O R M A T T I N G F U N C T I O N S *******/
829 /****************************************************************************/
830 /****************************************************************************/
831
832 /****************************************************************************/
833 /* gfRepChar(): */
834 /*--------------------------------------------------------------------------*/
835 /* DESCRIPTION */
836 /* Repeats a character to stdout the specified number of times. */
837 /* */
838 /* INPUTS */
839 /* c : The character to repeat. */
840 /* */
841 /* n : The number of times to repeat it. */
842 /****************************************************************************/
843 void gfRepChar(char c, unsigned n)
844 {
845 while(n--)
846 printf("%c", c);
847 }
848
849
850 /****************************************************************************/
851 /* gfHline(): */
852 /*--------------------------------------------------------------------------*/
853 /* DESCRIPTION */
854 /* Dumps a horizontal line of the standard length to the standard output. */
855 /****************************************************************************/
856 void gfHline(void)
857 {
858 gfRepChar(HORIZONTAL_BAR_SEP_CHAR, LINE_LEN);
859 printf("\n");
860 }
861
862
863 /****************************************************************************/
864 /* gfBannerHeading(): */
865 /*--------------------------------------------------------------------------*/
866 /* DESCRIPTION */
867 /* Prints a banner heading bracketed by astreisks to the standard output. */
868 /* This function is useful for separating different sections of output. */
869 /****************************************************************************/
870 void gfBannerHeading(char *s, int n_extra_lines)
871 {
872 const int lr_padding = 3;
873 /* The number of spaces on each side of what is printed.
874 */
875 int i;
876 /* General iteration variable.
877 */
878 int n_asterisks;
879 int input_arg_len;
880 int n_left_spaces;
881 int n_right_spaces;
882
883 /* The order of the source deck prevents me from using the assertion
884 ** function without function prototypes, and I don't like function
885 ** prototypes, and I'm too lazy to move the functions, so I'll just
886 ** protect against naughty parameters causing bizarre behavior.
887 */
888 if (!s)
889 s = "";
890 if (n_extra_lines < 0)
891 n_extra_lines = 0;
892
893 /* Print the right number of solid lines of asterisks to the
894 ** standard output.
895 */
896 for (i=0; i<n_extra_lines; i++)
897 {
898 gfRepChar('*', LINE_LEN);
899 printf("\n");
900 }
901
902 /* Figure out how many asterisks to print on each side of the
903 ** argument, and how many spaces. We also need to figure out
904 ** how many characters of the input argument to print--if there
905 ** are too many characters, we need to truncate.
906 */
907 input_arg_len = strlen(s);
908 if(input_arg_len > (LINE_LEN - 2 * lr_padding - 2))
909 input_arg_len = LINE_LEN - 2 * lr_padding - 2;
910
911 n_asterisks = (LINE_LEN - 2*lr_padding - input_arg_len)/2;
912
913 n_left_spaces = lr_padding;
914
915 if ((LINE_LEN - 2*lr_padding - input_arg_len) % 2)
916 {
917 /* Odd, need to pad the right by one. */
918 n_right_spaces = lr_padding+1;
919 }
920 else
921 {
922 n_right_spaces = lr_padding;
923 }
924
925 /* Print the text. */
926 gfRepChar('*', n_asterisks);
927 gfRepChar(' ', n_left_spaces);
928 for (i=0; i<input_arg_len; i++)
929 printf("%c", s[i]);
930 gfRepChar(' ', n_right_spaces);
931 gfRepChar('*', n_asterisks);
932 printf("\n");
933
934 /* Print the right number of solid lines of asterisks to the
935 ** standard output.
936 */
937 for (i=0; i<n_extra_lines; i++)
938 {
939 gfRepChar('*', LINE_LEN);
940 printf("\n");
941 }
942 }
943
944
945 /****************************************************************************/
946 /****************************************************************************/
947 /******* L O G I C A L A S S E R T I O N F U N C T I O N S ********/
948 /****************************************************************************/
949 /****************************************************************************/
950
951 /****************************************************************************/
952 /* asAssert(): */
953 /*--------------------------------------------------------------------------*/
954 /* DESCRIPTION */
955 /* Terminates the program abnormally if the logical condition specified */
956 /* is false. Roughly speaking, this fills the same role as the */
957 /* C-language assert() macro. */
958 /* */
959 /* INPUTS */
960 /* c : The logical condition tested (or, more precisely, the result of */
961 /* the code inserted by the compiler to stuff this parameter). */
962 /* */
963 /* l : The line number on which the call to this function occurs. */
964 /* This is filled in by using a special preprocessor symbol. */
965 /****************************************************************************/
966 void asAssert(unsigned c, unsigned long l)
967 {
968 if (!c)
969 {
970 gfHline();
971 printf("Abnormal termination; Assertion failed, line: %lu.\n", l);
972 gfHline();
973
974 /* Now need to convince the 'C' runtime environment to kill us.
975 */
976 exit(0);
977 }
978 }
979
980
981 /****************************************************************************/
982 /* asFatal(): */
983 /*--------------------------------------------------------------------------*/
984 /* DESCRIPTION */
985 /* Terminates the program with a fatal error message. */
986 /* */
987 /* INPUTS */
988 /* *msg: The message to use. Must be fairly short. */
989 /****************************************************************************/
990 void asFatal(const char *msg)
991 {
992 asAssert(msg != NULL, __LINE__);
993
994 gfHline();
995 printf("FATAL ERROR: %s.\n", msg);
996 gfHline();
997
998 /* Now need to convince the 'C' runtime environment to kill us.
999 */
1000 exit(0);
1001 }
1002
1003
1004 /****************************************************************************/
1005 /* asInfo(): */
1006 /*--------------------------------------------------------------------------*/
1007 /* DESCRIPTION */
1008 /* Prints informational message to stdout and terminates the program. */
1009 /****************************************************************************/
1010 void asInfo(void)
1011 {
1012 static char *msglines[] =
1013 {
1014 "RAP.EXE: rational approximation calculation program.",
1015 "!",
1016 "Copyright 2001, The Association For Computing Machinery (www.acm.org),",
1017 "David T. Ashley (dtashley@aol.com), Joseph P. DeVoe (jdevoe@visteon.com),",
1018 "Cory Pratt (cory_pratt@3com.com), Karl Perttunen (kperttun@visteon.com),",
1019 "and Anatoly Zhigljavsky (zhigljavskyaa@cardiff.ac.uk).",
1020 "!",
1021 "Please submit any bug reports or inquiries to all of the e-mail addresses",
1022 "listed above.",
1023 "!",
1024 "This program accompanies a paper entitled \"On Best Rational",
1025 "Approximations Using Large Integers\" submitted to ACM TOMS in late 2000/",
1026 "early 2001. The paper fully documents the algorithms employed in this",
1027 "software. In a nutshell, this program will execute algorithms on very",
1028 "large integers (up to 463 digits) and rational numbers with very large",
1029 "integer components which are helpful in finding best rational",
1030 "approximations in Farey series of very large order and in large rectangular",
1031 "regions of the integer lattice. The source code for this program should",
1032 "be available from CALGO (collected algorithms of the ACM).",
1033 "!",
1034 "Format legend: MANDATORY_PARAMETER",
1035 " [OPTIONAL_PARAMETER]",
1036 " {a, b ...} = Exactly one must be chosen from set.",
1037 " i... = Integer",
1038 " i+... = Non-Negative Integer",
1039 " i++... = Positive Integer",
1040 " r... = Rational Number",
1041 " r+... = Non-Negative Rational Number",
1042 " r++... = Positive Rational Number",
1043 "!",
1044 "How to specify an integer:",
1045 " [-]<digits>",
1046 " <digits>.<more_digits>e[{-,+}]<exponent>",
1047 " where the exponent creates an integer. Example: 3.14e2 is an integer",
1048 " but 3.14e1 is not (the former is 314, the latter is 31.4). Note that",
1049 " an integer can be substituted for a rational number, but a rational",
1050 " number cannot always be substituted for an integer.",
1051 "!",
1052 "How to specify a rational number:",
1053 " [-]<digits>/<more_digits>",
1054 " [-]<digits>.<more_digits>[e[{-,+}]<exponent>]",
1055 "!",
1056 "RAP + i1 i2",
1057 " Adds two integers to produce an integer result. Result is i1 + i2.",
1058 "!",
1059 "RAP + r1 r2",
1060 " Adds two rational numbers to produce a rational or integral result.",
1061 " Result is r1 + r2.",
1062 "!",
1063 "RAP - i1 i2",
1064 " Subtracts two integers to produce an integer result. Result is i1 - i2.",
1065 "!",
1066 "RAP * i1 i2",
1067 " Multiplies two integers to produce an integer result. Result is i1 * i2.",
1068 "!",
1069 "RAP / i1 i2",
1070 " Divides two integers to produce an integer result. Result is i1 / i2.",
1071 "!",
1072 "RAP / r1 r2",
1073 " Divides two rational numbers to produce a rational or integral result.",
1074 " Result is r1 / r2.",
1075 "!",
1076 "RAP % i1 i2",
1077 " Divides two integers and produces the remainder from the division. The",
1078 " result is the same as i1 % i2 as defined by the 'C' programming language",
1079 " except that much longer integers are accomodated.",
1080 "!",
1081 "RAP ** i1 i2+",
1082 " Exponentiates the integer i1 to the i2+'th power.",
1083 "!",
1084 "RAP ** r1 i1+",
1085 " Exponentiates the rational number r1 to the i1+'th power.",
1086 "!",
1087 "RAP gcd i1++ i2++",
1088 " Calculates the greatest common divisor of i1 and i2 using Euclid's",
1089 " algorithm.",
1090 "!",
1091 "RAP dap r1 i1+",
1092 " Given rational number r1, forms a rational approximation with a",
1093 " different denominator i1. This functionality is very useful",
1094 " for converting a rational number to a more familiar decimal",
1095 " approximation. The accompanying user's manual gives full",
1096 " details about the formula used by the DAP command. DAP is also",
1097 " used by several other commands to provide a more familiar",
1098 " output form.",
1099 "!",
1100 "RAP cf r1+",
1101 " Forms the continued fraction partial quotients and convergents",
1102 " of a non-negative rational number r1.",
1103 "!",
1104 "RAP fn r1+ i1++",
1105 " Finds the two best neighboring rational approximations to non-negative",
1106 " rational number r1 in the Farey series of order i1.",
1107 "!",
1108 "RAP fn r1++ i1++ i2++ i3++",
1109 " Same as form above except finds i2 neighbors on either side of r1",
1110 " (rather than the default of 1), and uses i3 as the denominator for",
1111 " presenting the approximations and errors in decimal form.",
1112 "!",
1113 "RAP mind r1+ r2+",
1114 " Calculates a rational number in the interval [r1, r2] with the minimum",
1115 " denominator. If the rational number in the interval with the minimum",
1116 " denominator is not unique (i.e. there is more than one with the same ",
1117 " denominator), no assurances are made about which of the numbers with",
1118 " minimum denominator will be returned (however, it is assured that the",
1119 " result will be one of them).",
1120 "!",
1121 "RAP fab r1+ i1++ i2++",
1122 " Finds the two neighbors to r1 in a rectangular area of the integer",
1123 " lattice specified by h<=i1 and k<=i2. This is a similar concept to",
1124 " the \"fn\" command, but with numerator and denominator both constrained.",
1125 " On output, 4 lines of digits after the decimal point are assumed by",
1126 " default.",
1127 "!",
1128 "RAP fab r1+ i1++ i2++ i3++ i4++",
1129 " Same as form above, except optional parameters i3 and i4 specify the",
1130 " number of neighbors on both the left and right to generate, and the",
1131 " denominator to use for display of DAP information.",
1132 "!",
1133 "RAP fndmax r1+ r2+ i++",
1134 " Provides an upper bound on the distance between successive terms of",
1135 " the Farey series of order i in the interval [r1, r2]. It is required",
1136 " that r1 < r2 and that r1 and r2 are both in the Farey series of order",
1137 " i.",
1138 "!",
1139 "RAP fndmax r1+ r2+ i++ j++",
1140 " Same as form above except j may override the default denominator of",
1141 " 1e108 for DAP presentation.",
1142 "!",
1143 "RAP fabdmax r1+ r2+ i1+ i2+",
1144 " Provides an upper bound on the distance between successive terms of",
1145 " the \"rectangular\" Farey series (doubly-constrained) with h <= i1 and",
1146 " j <= i2 in the interval [r1, r2]. It is required that r1 < r2 and that",
1147 " both meet the constraints (i.e. are in the \"rectangular\" series).",
1148 "!",
1149 "RAP fabdmax r1+ r2+ i1+ i2+ j++",
1150 " Same as form above except j may override the default denominator of 1e108",
1151 " for DAP presentation.",
1152 "!",
1153 "If this information has scrolled off the screen and can't be read, try re-",
1154 "directing it to a file (for example, RAP >OUT.TXT) and then viewing the file",
1155 "with a text editor, or piping it through \"more\" (for example, RAP|MORE).",
1156 "!"
1157 };
1158
1159 int i;
1160
1161 /* Dump out the whole array and terminate the program. Lines beginning
1162 ** with an exclamation point should be replaced with a horizontal line.
1163 */
1164 for (i=0; i<sizeof(msglines)/sizeof(msglines[0]); i++)
1165 {
1166 if ((msglines[i])[0] == '!')
1167 {
1168 gfHline();
1169 }
1170 else
1171 {
1172 printf("%s\n", msglines[i]);
1173 }
1174 }
1175
1176 exit(0);
1177 }
1178
1179
1180
1181 /****************************************************************************/
1182 /****************************************************************************/
1183 /*************** D A T A - D R I V E N F U N C T I O N S *************/
1184 /****************************************************************************/
1185 /****************************************************************************/
1186 /* This section is reserved for data-driven functions with no I/O
1187 ** requirements and no side-effects.
1188 */
1189 /****************************************************************************/
1190 /* ddCharToLower(): */
1191 /*--------------------------------------------------------------------------*/
1192 /* DESCRIPTION */
1193 /* If a character is upper-case, translates it to lower-case. */
1194 /****************************************************************************/
1195 char ddCharToLower(char c)
1196 {
1197 switch(c)
1198 {
1199 case 'A' : return ('a');
1200 break;
1201 case 'B' : return ('b');
1202 break;
1203 case 'C' : return ('c');
1204 break;
1205 case 'D' : return ('d');
1206 break;
1207 case 'E' : return ('e');
1208 break;
1209 case 'F' : return ('f');
1210 break;
1211 case 'G' : return ('g');
1212 break;
1213 case 'H' : return ('h');
1214 break;
1215 case 'I' : return ('i');
1216 break;
1217 case 'J' : return ('j');
1218 break;
1219 case 'K' : return ('k');
1220 break;
1221 case 'L' : return ('l');
1222 break;
1223 case 'M' : return ('m');
1224 break;
1225 case 'N' : return ('n');
1226 break;
1227 case 'O' : return ('o');
1228 break;
1229 case 'P' : return ('p');
1230 break;
1231 case 'Q' : return ('q');
1232 break;
1233 case 'R' : return ('r');
1234 break;
1235 case 'S' : return ('s');
1236 break;
1237 case 'T' : return ('t');
1238 break;
1239 case 'U' : return ('u');
1240 break;
1241 case 'V' : return ('v');
1242 break;
1243 case 'W' : return ('w');
1244 break;
1245 case 'X' : return ('x');
1246 break;
1247 case 'Y' : return ('y');
1248 break;
1249 case 'Z' : return ('z');
1250 break;
1251 default: return(c);
1252 break;
1253 }
1254 }
1255
1256
1257 /****************************************************************************/
1258 /* ddIsInfoChar(): */
1259 /*--------------------------------------------------------------------------*/
1260 /* DESCRIPTION */
1261 /* Returns TRUE if the passed character is a character that should be in */
1262 /* a token, or FALSE otherwise. */
1263 /****************************************************************************/
1264 unsigned ddIsInfoChar(char c)
1265 {
1266 int i;
1267 char d;
1268 const char CONST_info_characters[] = { 'a', 'b', 'c', 'd', 'e', 'f', 'g',
1269 'h', 'i', 'j', 'k', 'l', 'm', 'n',
1270 'o', 'p', 'q', 'r', 's', 't', 'u',
1271 'v', 'w', 'x', 'y', 'z', '0', '1',
1272 '2', '3', '4', '5', '6', '7', '8',
1273 '9', '+', '-', '*', '/', '_', '.',
1274 '\\','%' };
1275
1276 d = ddCharToLower(c);
1277
1278 for (i=0; i<sizeof(CONST_info_characters)/sizeof(CONST_info_characters[0]); i++)
1279 {
1280 if (CONST_info_characters[i] == d)
1281 return(TRUE);
1282 }
1283
1284 return(FALSE);
1285 }
1286
1287
1288 /****************************************************************************/
1289 /* ddIsDiscardChar(): */
1290 /*--------------------------------------------------------------------------*/
1291 /* DESCRIPTION */
1292 /* Returns TRUE if the passed character is a character that should be */
1293 /* discarded, or FALSE otherwise. */
1294 /****************************************************************************/
1295 unsigned ddIsDiscardChar(char c)
1296 {
1297 int i;
1298 char d;
1299 const char CONST_discard_characters[] = {','};
1300
1301 d = ddCharToLower(c);
1302
1303 for (i=0; i<sizeof(CONST_discard_characters)/sizeof(CONST_discard_characters[0]); i++)
1304 {
1305 if (CONST_discard_characters[i] == d)
1306 return(TRUE);
1307 }
1308
1309 return(FALSE);
1310 }
1311
1312
1313 /****************************************************************************/
1314 /* ddIsWhitespaceChar(): */
1315 /*--------------------------------------------------------------------------*/
1316 /* DESCRIPTION */
1317 /* Returns TRUE if the passed character is a character that should be */
1318 /* treated as whitespace, or FALSE otherwise. */
1319 /****************************************************************************/
1320 unsigned ddIsWhitespaceChar(char c)
1321 {
1322 int i;
1323 char d;
1324 const char CONST_whitespace_chars[] = { ' ', '\t', '\n' };
1325
1326 d = ddCharToLower(c);
1327
1328 for (i=0; i<sizeof(CONST_whitespace_chars)/sizeof(CONST_whitespace_chars[0]); i++)
1329 {
1330 if (CONST_whitespace_chars[i] == d)
1331 return(TRUE);
1332 }
1333
1334 return(FALSE);
1335 }
1336
1337
1338 /****************************************************************************/
1339 /* ddIsDigit(): */
1340 /*--------------------------------------------------------------------------*/
1341 /* DESCRIPTION */
1342 /* Returns TRUE if the passed argument is a digit, or FALSE otherwise. */
1343 /* */
1344 /* INPUTS */
1345 /* c : Character to evaluate for digitness (or is that digiality??). */
1346 /* */
1347 /* OUTPUTS */
1348 /* <--: TRUE if a digit, FALSE otherwise. */
1349 /****************************************************************************/
1350 unsigned ddIsDigit(char c)
1351 {
1352 if ((c >= '0') && (c <= '9'))
1353 return(TRUE);
1354 else
1355 return(FALSE);
1356 }
1357
1358
1359 /****************************************************************************/
1360 /* ddDigitToValue(): */
1361 /*--------------------------------------------------------------------------*/
1362 /* DESCRIPTION */
1363 /* Converts from ASCII digit to unsigned integer value. Fatal to call */
1364 /* with non-digit. */
1365 /* */
1366 /* INPUTS */
1367 /* c : Character to convert to value. */
1368 /* */
1369 /* OUTPUTS */
1370 /* <--: Value. */
1371 /****************************************************************************/
1372 unsigned ddDigitToValue(char c)
1373 {
1374 if ((c >= '0') && (c <= '9'))
1375 {
1376 return(c - '0');
1377 }
1378 else
1379 {
1380 asAssert(0, __LINE__); /* Guaranteed fatal. */
1381 return(0); /* To satisfy compiler warning about path not
1382 ** returning a value.
1383 */
1384 }
1385 }
1386
1387
1388 /****************************************************************************/
1389 /* ddValueToDigit(): */
1390 /*--------------------------------------------------------------------------*/
1391 /* DESCRIPTION */
1392 /* Converts from unsigned value to digit '0'..'9'. Fatal to call with */
1393 /* with value out of range. */
1394 /* */
1395 /* INPUTS */
1396 /* i : Character to convert to value. */
1397 /* */
1398 /* OUTPUTS */
1399 /* <--: Value. */
1400 /****************************************************************************/
1401 char ddValueToDigit(unsigned i)
1402 {
1403 if (i < 10)
1404 {
1405 return(i + '0');
1406 }
1407 else
1408 {
1409 asAssert(0, __LINE__); /* Guaranteed fatal. */
1410 return('0'); /* To satisfy compiler warning about path not
1411 ** returning a value.
1412 */
1413 }
1414 }
1415
1416
1417 /****************************************************************************/
1418 /* ddStringContains(): */
1419 /*--------------------------------------------------------------------------*/
1420 /* DESCRIPTION */
1421 /* Determines whether STR1 contains any characters in STR2, and returns */
1422 /* TRUE if so or FALSE otherwise. */
1423 /****************************************************************************/
1424 int ddStringContains(const char *str1, const char *str2)
1425 {
1426 unsigned s1len, s2len;
1427 unsigned i, j;
1428
1429 asAssert(str1 != NULL, __LINE__);
1430 asAssert(str2 != NULL, __LINE__);
1431
1432 s1len = strlen(str1);
1433 s2len = strlen(str2);
1434
1435 for (i=0; i<s1len; i++)
1436 {
1437 for (j=0; j<s2len; j++)
1438 {
1439 if (str1[i] == str2[j])
1440 return(TRUE);
1441 }
1442 }
1443
1444 return(FALSE);
1445 }
1446
1447
1448 /****************************************************************************/
1449 /* ddStringContainsOnly(): */
1450 /*--------------------------------------------------------------------------*/
1451 /* DESCRIPTION */
1452 /* Returns TRUE if STR1 contains ONLY characters from STR2, or FALSE */
1453 /* otherwise. */
1454 /****************************************************************************/
1455 int ddStringContainsOnly(const char *str1, const char *str2)
1456 {
1457 int i, j;
1458 int l1, l2;
1459
1460 asAssert(str1 != NULL, __LINE__);
1461 asAssert(str2 != NULL, __LINE__);
1462
1463 l1 = strlen(str1);
1464 l2 = strlen(str2);
1465
1466 for (i=0; i<l1; i++)
1467 {
1468 for (j=0; j<l2; j++)
1469 {
1470 if (str1[i] == str2[j])
1471 break;
1472 }
1473
1474 if (j == l2)
1475 return(FALSE);
1476 }
1477
1478 return(TRUE);
1479 }
1480
1481
1482 /****************************************************************************/
1483 /* ddStringReverse(): */
1484 /*--------------------------------------------------------------------------*/
1485 /* DESCRIPTION */
1486 /* Reverses the order of characters in the string s. */
1487 /****************************************************************************/
1488 void ddStringReverse(char *s)
1489 {
1490 unsigned l;
1491 unsigned i;
1492 unsigned limit;
1493 char temp;
1494
1495 asAssert(s != NULL, __LINE__);
1496
1497 l = strlen(s);
1498 limit = l / 2;
1499
1500 for (i=0; i<limit; i++)
1501 {
1502 temp = s[i];
1503 s[i] = s[l-i-1];
1504 s[l-i-1] = temp;
1505 }
1506 }
1507
1508
1509 /****************************************************************************/
1510 /* ddStringDeleteLeadingChar(): */
1511 /*--------------------------------------------------------------------------*/
1512 /* DESCRIPTION */
1513 /* Deletes the leading character of a string. If there is no leading */
1514 /* character, takes no action. */
1515 /****************************************************************************/
1516 void ddStringDeleteLeadingChar(char *s)
1517 {
1518 int len;
1519 int i;
1520
1521 asAssert(s != NULL, __LINE__);
1522
1523 len = strlen(s);
1524
1525 for (i=0; i<len; i++)
1526 s[i] = s[i+1];
1527 }
1528
1529
1530 /****************************************************************************/
1531 /* ddFundamentalAdditionCell(): */
1532 /*--------------------------------------------------------------------------*/
1533 /* DESCRIPTION */
1534 /* Fundamental cell of addition, used to add one ASCII digit to another */
1535 /* ASCII digit, processing carries in and carries out. Unexpected values */
1536 /* will generate a fatal error. */
1537 /* */
1538 /* INPUTS */
1539 /* digit1: Digit 1 in. */
1540 /* digit2: Digit 2 in. */
1541 /* carry_in: Carry in. Must be '0' or '1'. */
1542 /* */
1543 /* OUTPUTS */
1544 /* *digit_out: Digit result out. */
1545 /* *carry_out: Carry out. Will be '0' or '1'. */
1546 /****************************************************************************/
1547 void ddFundamentalAdditionCell(char digit1,
1548 char digit2,
1549 char carry_in,
1550 char *digit_out,
1551 char *carry_out)
1552 {
1553 unsigned vd1;
1554 unsigned vd2;
1555 unsigned vci;
1556 unsigned total;
1557
1558 asAssert(ddIsDigit(digit1), __LINE__);
1559 asAssert(ddIsDigit(digit2), __LINE__);
1560 asAssert(ddDigitToValue(carry_in) <= 1, __LINE__);
1561 asAssert(digit_out != NULL, __LINE__);
1562 asAssert(carry_out != NULL, __LINE__);
1563
1564 vd1 = ddDigitToValue(digit1);
1565 vd2 = ddDigitToValue(digit2);
1566 vci = ddDigitToValue(carry_in);
1567
1568 total = vd1+vd2+vci;
1569
1570 *digit_out = ddValueToDigit(total % 10);
1571 *carry_out = ddValueToDigit(total / 10);
1572 }
1573
1574
1575 /****************************************************************************/
1576 /* ddFundamentalMultiplicationCell(): */
1577 /*--------------------------------------------------------------------------*/
1578 /* DESCRIPTION */
1579 /* Fundamental cell of multiplication, used to multiply one ASCII digit */
1580 /* by another, processing carries in and out. Unexpected inputs will */
1581 /* generate a fatal error. */
1582 /* */
1583 /* INPUTS */
1584 /* digit1: Digit 1 in. */
1585 /* digit2: Digit 2 in. */
1586 /* carry_in: Carry in. Because of the way multiplication works, */
1587 /* this must always be from '0' through '8'. */
1588 /* */
1589 /* OUTPUTS */
1590 /* *digit_out: Digit result out. */
1591 /* *carry_out: Carry out. Because of the way multiplication works, */
1592 /* this must always be from '0' through '8'. */
1593 /****************************************************************************/
1594 void ddFundamentalMultiplicationCell(char digit1,
1595 char digit2,
1596 char carry_in,
1597 char *digit_out,
1598 char *carry_out)
1599 {
1600 unsigned vd1;
1601 unsigned vd2;
1602 unsigned vci;
1603 unsigned total;
1604
1605 asAssert(ddIsDigit(digit1), __LINE__);
1606 asAssert(ddIsDigit(digit2), __LINE__);
1607 asAssert(ddDigitToValue(carry_in) <= 8, __LINE__);
1608 asAssert(digit_out != NULL, __LINE__);
1609 asAssert(carry_out != NULL, __LINE__);
1610
1611 vd1 = ddDigitToValue(digit1);
1612 vd2 = ddDigitToValue(digit2);
1613 vci = ddDigitToValue(carry_in);
1614
1615 total = (vd1 * vd2) + vci;
1616
1617 *digit_out = ddValueToDigit(total % 10);
1618 *carry_out = ddValueToDigit(total / 10);
1619 }
1620
1621
1622 /****************************************************************************/
1623 /* ddFundamentalSubtractionCell(): */
1624 /*--------------------------------------------------------------------------*/
1625 /* DESCRIPTION */
1626 /* Fundamental cell of subtraction, used to subtract one ASCII digit from */
1627 /* another ASCII digit, processing borrows in and borrows out. */
1628 /* Unexpected values will generate a fatal error. */
1629 /* */
1630 /* INPUTS */
1631 /* digit1: Digit 1 in. */
1632 /* digit2: Digit 2 in. */
1633 /* borrow_in: Borrow in. Must be '0' or '1'. */
1634 /* */
1635 /* OUTPUTS */
1636 /* *digit_out: Digit result out, digit1-digit2-borrow_in. */
1637 /* *borrow_out: Borrow out. Will be '0' or '1'. */
1638 /****************************************************************************/
1639 void ddFundamentalSubtractionCell(char digit1,
1640 char digit2,
1641 char borrow_in,
1642 char *digit_out,
1643 char *borrow_out)
1644 {
1645 unsigned vd1;
1646 unsigned vd2;
1647 unsigned vbi;
1648 unsigned total;
1649
1650 asAssert(ddIsDigit(digit1), __LINE__);
1651 asAssert(ddIsDigit(digit2), __LINE__);
1652 asAssert(ddDigitToValue(borrow_in) <= 1, __LINE__);
1653 asAssert(digit_out != NULL, __LINE__);
1654 asAssert(borrow_out != NULL, __LINE__);
1655
1656 vd1 = ddDigitToValue(digit1);
1657 vd2 = ddDigitToValue(digit2);
1658 vbi = ddDigitToValue(borrow_in);
1659
1660 total = 10+vd1-vd2-vbi;
1661
1662 *digit_out = ddValueToDigit(total % 10);
1663 if (total < 10)
1664 {
1665 *borrow_out = '1';
1666 /* If we went neggy neggy on the subtraction, we need a borrow.
1667 */
1668 }
1669 else
1670 {
1671 *borrow_out = '0'; /* No borrow. */
1672 }
1673 }
1674
1675
1676 /****************************************************************************/
1677 /* ddUmin(): */
1678 /*--------------------------------------------------------------------------*/
1679 /* DESCRIPTION */
1680 /* Returns the minimum of two unsigned integers. */
1681 /* */
1682 /* INPUTS */
1683 /* arg1, arg2 : Unsigned integers to compare. */
1684 /* */
1685 /* OUTPUTS */
1686 /* <-- : Samller of arg1, arg2. */
1687 /****************************************************************************/
1688 unsigned ddUmin(unsigned arg1, unsigned arg2)
1689 {
1690 if (arg1 < arg2)
1691 return(arg1);
1692 else
1693 return(arg2);
1694 }
1695
1696
1697
1698 /****************************************************************************/
1699 /* ddUmax(): */
1700 /*--------------------------------------------------------------------------*/
1701 /* DESCRIPTION */
1702 /* Returns the maximum of two unsigned integers. */
1703 /* */
1704 /* INPUTS */
1705 /* arg1, arg2 : Unsigned integers to compare. */
1706 /* */
1707 /* OUTPUTS */
1708 /* <-- : Larger of arg1, arg2. */
1709 /****************************************************************************/
1710 unsigned ddUmax(unsigned arg1, unsigned arg2)
1711 {
1712 if (arg1 > arg2)
1713 return(arg1);
1714 else
1715 return(arg2);
1716 }
1717
1718
1719 /****************************************************************************/
1720 /* ddSmin(): */
1721 /*--------------------------------------------------------------------------*/
1722 /* DESCRIPTION */
1723 /* Returns the minimum of two signed integers. */
1724 /* */
1725 /* INPUTS */
1726 /* arg1, arg2 : Signed integers to compare. */
1727 /* */
1728 /* OUTPUTS */
1729 /* <-- : Samller of arg1, arg2. */
1730 /****************************************************************************/
1731 int ddSmin(int arg1, int arg2)
1732 {
1733 if (arg1 < arg2)
1734 return(arg1);
1735 else
1736 return(arg2);
1737 }
1738
1739
1740
1741 /****************************************************************************/
1742 /* ddSmax(): */
1743 /*--------------------------------------------------------------------------*/
1744 /* DESCRIPTION */
1745 /* Returns the maximum of two signed integer. */
1746 /* */
1747 /* INPUTS */
1748 /* arg1, arg2 : Signed integers to compare. */
1749 /* */
1750 /* OUTPUTS */
1751 /* <-- : Larger of arg1, arg2. */
1752 /****************************************************************************/
1753 int ddSmax(int arg1, int arg2)
1754 {
1755 if (arg1 > arg2)
1756 return(arg1);
1757 else
1758 return(arg2);
1759 }
1760
1761
1762 /****************************************************************************/
1763 /****************************************************************************/
1764 /******* M E M O R Y A L L O C A T I O N F U N C T I O N S ********/
1765 /****************************************************************************/
1766 /****************************************************************************/
1767 /* These functions are primarily wrappers for the standard 'C' library
1768 ** functions. They will trap "out of memory" errors, and also provide a
1769 ** place to insert debugging code if it becomes necessary.
1770 */
1771 /****************************************************************************/
1772 /* maMalloc(): */
1773 /*--------------------------------------------------------------------------*/
1774 /* DESCRIPTION */
1775 /* Wrapper for malloc(). See malloc() documentation. */
1776 /****************************************************************************/
1777 void *maMalloc(size_t n)
1778 {
1779 void *rv;
1780
1781 rv = malloc(n);
1782
1783 asAssert(rv != NULL, __LINE__);
1784
1785 return(rv);
1786 }
1787
1788
1789 /****************************************************************************/
1790 /* maFree(): */
1791 /*--------------------------------------------------------------------------*/
1792 /* DESCRIPTION */
1793 /* Wrapper for free(). See free() documentation. */
1794 /****************************************************************************/
1795 void maFree(void *p)
1796 {
1797 asAssert(p != NULL, __LINE__);
1798
1799 free(p);
1800 }
1801
1802
1803 /****************************************************************************/
1804 /* maRealloc(): */
1805 /*--------------------------------------------------------------------------*/
1806 /* DESCRIPTION */
1807 /* Wrapper for realloc(). See realloc() documentation. */
1808 /****************************************************************************/
1809 void *maRealloc(void *ptr, size_t n)
1810 {
1811 void *rv;
1812
1813 rv = realloc(ptr, n);
1814
1815 asAssert(rv != NULL, __LINE__);
1816
1817 return(rv);
1818 }
1819
1820
1821 /****************************************************************************/
1822 /****************************************************************************/
1823 /******* S Y N T H E T I C I N T E G E R F U N C T I O N S ********/
1824 /****************************************************************************/
1825 /****************************************************************************/
1826 /* Definition of a synthetic integer.
1827 */
1828 struct synthetic_integer_struct
1829 {
1830 unsigned nan;
1831 /* Boolean variable used to remember errors that render the integer
1832 ** as "non a number", so that its value is invalid or unknown.
1833 ** NAN's propagate so that performing any operating involving a NAN
1834 ** also yields a NAN. A non-zero value here means that an error has
1835 ** been thrown and the synthetic integer is invalid.
1836 */
1837 unsigned neg;
1838 /* Only the absolute value of the integer is stored as a character
1839 ** string. This boolean remembers if the number is negative.
1840 ** A non-zero value here means the integer is negative. This may have
1841 ** either value when the value of zero is represented by the
1842 ** synthetic integer.
1843 */
1844 unsigned len;
1845 /* The number of characters in the string representing the integer.
1846 ** This is the same as would be returned by strlen(). This field
1847 ** is maintained to avoid the expense of counting characters before
1848 ** the terminator each time the length is needed.
1849 */
1850 unsigned char digits[INTERMEDIATE_CALC_MAX_DIGITS + 1];
1851 /* The string representing the synthetic integer. To avoid the need
1852 ** to move large blocks of characters, the integer is stored with the
1853 ** least significant digits first. The string must be \0 terminated--
1854 ** this is done primarily to make printing things for debugging
1855 ** easier, although the terminator is redundant with the "len" field
1856 ** above. The valid representation of zero is a "len" field of
1857 ** zero and a terminating \0 as element [0] here. No commas or other
1858 ** characters besides digits are allowed.
1859 */
1860 };
1861
1862
1863 typedef struct synthetic_integer_struct SYNTHETIC_INTEGER;
1864 /* Typedef for more compact reference to data type.
1865 */
1866
1867
1868 /****************************************************************************/
1869 /* siCreate(): */
1870 /*--------------------------------------------------------------------------*/
1871 /* DESCRIPTION */
1872 /* Creates a synthetic integer (allocates the memory and initializes) and */
1873 /* sets value to zero. */
1874 /* */
1875 /* INPUTS */
1876 /* *i : Pointer to pointer to synthetic integer. The caller's pointer */
1877 /* will be filled in to point to the allocated object. */
1878 /****************************************************************************/
1879 void siCreate(SYNTHETIC_INTEGER **i)
1880 {
1881 asAssert(i != NULL, __LINE__);
1882 /* Input pointer may not be NULL.
1883 */
1884
1885 *i = maMalloc(sizeof(SYNTHETIC_INTEGER));
1886 /* Allocate the memory, stuff the pointer in the caller's
1887 ** area.
1888 */
1889
1890 /* Initialize the synthetic integer to what is required for
1891 ** the number zero.
1892 */
1893 (*i)->nan = 0;
1894 (*i)->neg = 0;
1895 (*i)->len = 0;
1896 (*i)->digits[0] = 0;
1897 }
1898
1899
1900 /****************************************************************************/
1901 /* siDestroy(): */
1902 /*--------------------------------------------------------------------------*/
1903 /* DESCRIPTION */
1904 /* Destroys a synthetic integer (deallocates the memory and sets the */
1905 /* caller's pointer to NULL. */
1906 /* */
1907 /* INPUTS */
1908 /* *i : Pointer to pointer to synthetic integer. The synthetic integer */
1909 /* will be destroyed and the caller's pointer will be filled to */
1910 /* NULL. */
1911 /****************************************************************************/
1912 void siDestroy(SYNTHETIC_INTEGER **i)
1913 {
1914 asAssert(i != NULL, __LINE__);
1915 /* Input pointer to pointer may not be NULL.
1916 */
1917 asAssert(*i != NULL, __LINE__);
1918 /* Input pointer to block of memory may not be NULL.
1919 */
1920
1921 maFree(*i);
1922 /* Deallocate block of memory.
1923 */
1924
1925 *i = NULL;
1926 /* Fill in the caller's variable to NULL.
1927 */
1928 }
1929
1930
1931 /****************************************************************************/
1932 /* siCopy(): */
1933 /*--------------------------------------------------------------------------*/
1934 /* DESCRIPTION */
1935 /* Copies a synthetic integer. The integer must already be created. */
1936 /* */
1937 /* INPUTS */
1938 /* *src, *dst : Source and destination synthetic integers. */
1939 /****************************************************************************/
1940 void siCopy(SYNTHETIC_INTEGER **src, SYNTHETIC_INTEGER **dst)
1941 {
1942 asAssert(src != NULL, __LINE__);
1943 asAssert(*src != NULL, __LINE__);
1944 asAssert(dst != NULL, __LINE__);
1945 asAssert(*dst != NULL, __LINE__);
1946
1947 /* There are a lot of ways to copy, and pros and cons.
1948 ** I'll choose the one that gives the least typing
1949 ** here in the source code, but maybe I'll need to
1950 ** optimize it later.
1951 */
1952 memcpy(*dst, *src, sizeof(SYNTHETIC_INTEGER));
1953 }
1954
1955
1956 /****************************************************************************/
1957 /* siMulByTen(): */
1958 /*--------------------------------------------------------------------------*/
1959 /* DESCRIPTION */
1960 /* Multiplies a synthetic integer by 10, producing a NAN result if there */
1961 /* is an overflow in the number of digits. This is a primitive operation */
1962 /* used in multiplication of arbitrary integers. */
1963 /****************************************************************************/
1964 void siMulByTen(SYNTHETIC_INTEGER **arg)
1965 {
1966 asAssert(arg != NULL, __LINE__);
1967 asAssert(*arg != NULL, __LINE__);
1968
1969 /* If the integer is already NAN, NAN it stays.
1970 */
1971 if (!((*arg)->nan))
1972 {
1973 /* If the integer is 0, 0 it stays. */
1974 if ((*arg)->len)
1975 {
1976 /* The result will overflow iff the string is already
1977 ** at its length limit. If so, must declare a NAN. Multiplication
1978 ** by 10 is guaranteed to add exactly one digit.
1979 */
1980 asAssert((*arg)->len <= INTERMEDIATE_CALC_MAX_DIGITS, __LINE__);
1981 if ((*arg)->len == INTERMEDIATE_CALC_MAX_DIGITS)
1982 {
1983 /* Overflow. Must declare a NAN. */
1984 (*arg)->digits[0] = '\0';
1985 (*arg)->len = 0;
1986 (*arg)->nan = TRUE;
1987 (*arg)->neg = FALSE;
1988 }
1989 else
1990 {
1991 /* The digit shift will come off alright. Carry it out.
1992 */
1993 unsigned tgt_idx;
1994
1995 for (tgt_idx = (*arg)->len; tgt_idx >= 1; tgt_idx--)
1996 {
1997 (*arg)->digits[tgt_idx] = (*arg)->digits[tgt_idx-1];
1998 }
1999 (*arg)->digits[0] = '0';
2000 (*arg)->digits[(*arg)->len + 1] = '\0';
2001 ((*arg)->len)++;
2002 }
2003 }
2004 }
2005 }
2006
2007
2008 /****************************************************************************/
2009 /* siDivByTen(): */
2010 /*--------------------------------------------------------------------------*/
2011 /* DESCRIPTION */
2012 /* Divides a synthetic integer by 10 using digit-shifting (remainders */
2013 /* are discarded. This function is used in division of arbitrary */
2014 /* integers. */
2015 /****************************************************************************/
2016 void siDivByTen(SYNTHETIC_INTEGER **arg)
2017 {
2018 asAssert(arg != NULL, __LINE__);
2019 asAssert(*arg != NULL, __LINE__);
2020
2021 /* If the integer is already NAN, NAN it stays.
2022 */
2023 if (!((*arg)->nan))
2024 {
2025 /* If the integer is a single digit, it must go to zero.
2026 */
2027 if ((*arg)->len == 1)
2028 {
2029 (*arg)->len = 0;
2030 (*arg)->digits[0] = '\0';
2031 (*arg)->neg = FALSE;
2032 }
2033 else
2034 {
2035 unsigned i;
2036
2037 asAssert((*arg)->len <= INTERMEDIATE_CALC_MAX_DIGITS, __LINE__);
2038
2039 /* This is just a normal digit shift. */
2040 for (i=0; i<((*arg)->len); i++)
2041 {
2042 (*arg)->digits[i] = (*arg)->digits[i+1];
2043 }
2044
2045 ((*arg)->len)--;
2046 }
2047 }
2048 }
2049
2050
2051 /****************************************************************************/
2052 /* siMulByDigit(): */
2053 /*--------------------------------------------------------------------------*/
2054 /* DESCRIPTION */
2055 /* Multiplies a synthetic integer by an arbitrary digit, producing a */
2056 /* result that may be zero, the argument, or an integer of larger mag- */
2057 /* nitude. A NAN is declared on overflow. This is a primitive operation */
2058 /* used in multiplication of arbitrary integers. */
2059 /****************************************************************************/
2060 void siMulByDigit(SYNTHETIC_INTEGER **arg, char digit)
2061 {
2062 asAssert(arg != NULL, __LINE__);
2063 asAssert(*arg != NULL, __LINE__);
2064 asAssert(ddIsDigit(digit), __LINE__);
2065
2066 /* If the integer is already NAN, NAN it stays.
2067 */
2068 if (!((*arg)->nan))
2069 {
2070 /* If the integer is 0 or the digit is '0', force the result
2071 ** to 0.
2072 */
2073 if (!((*arg)->len) || (digit == '0'))
2074 {
2075 (*arg)->digits[0] = '\0';
2076 (*arg)->len = 0;
2077 (*arg)->nan = FALSE;
2078 (*arg)->neg = FALSE;
2079 }
2080 else
2081 {
2082 /* This is now a valid multiplication. Regrettably, we can't
2083 ** determine an overflow or lack of decisively except by carrying
2084 ** the multiplication out to its end.
2085 */
2086 char carry;
2087 char new_digit;
2088 unsigned cur_digit;
2089
2090 carry = '0';
2091
2092 asAssert((*arg)->len <= INTERMEDIATE_CALC_MAX_DIGITS, __LINE__);
2093
2094 for (cur_digit=0; cur_digit < (*arg)->len; cur_digit++)
2095 {
2096 ddFundamentalMultiplicationCell((*arg)->digits[cur_digit],
2097 digit,
2098 carry,
2099 &new_digit,
2100 &carry);
2101
2102 if (cur_digit == ((*arg)->len - 1)) /* If last digit in loop. */
2103 {
2104 if (cur_digit == (INTERMEDIATE_CALC_MAX_DIGITS-1)) /* arg was max len. */
2105 {
2106 if (carry != '0')
2107 {
2108 /* We have an SI that was at the length limit, we've processed.
2109 ** the last digit, and there is a carry out. Must declare a NAN.
2110 */
2111 (*arg)->digits[0] = '\0';
2112 (*arg)->len = 0;
2113 (*arg)->nan = TRUE;
2114 (*arg)->neg = FALSE;
2115 }
2116 else
2117 {
2118 /* We have an SI that was max length, but did not overflow.
2119 ** Close it up normally.
2120 */
2121 (*arg)->digits[cur_digit] = new_digit;
2122 /* Nothing else to do. Everything is preset. */
2123 }
2124 }
2125 else
2126 {
2127 /* We are at the last digit of multiplication, but not at the
2128 ** maximum length of a string of digits. Cleanup without fear
2129 ** of overflow.
2130 */
2131 if (carry == '0')
2132 {
2133 /* Number stayed same length. Just assign digit. Terminator
2134 ** and other info is still valid.
2135 */
2136 (*arg)->digits[cur_digit] = new_digit;
2137 }
2138 else
2139 {
2140 /* At last digit of multiplication. Number grew by one digit.
2141 ** Clean up.
2142 */
2143 (*arg)->digits[cur_digit] = new_digit;
2144 (*arg)->digits[cur_digit+1] = carry;
2145 (*arg)->digits[cur_digit+2] = '\0';
2146 ((*arg)->len)++;
2147
2148 /* Must break out of the for() loop. Otherwise, modifying
2149 ** the length above will keep us going.
2150 */
2151 break;
2152 }
2153 }
2154 }
2155 else
2156 {
2157 /* Not the last digit in the loop. Just assign digit.
2158 */
2159 (*arg)->digits[cur_digit] = new_digit;
2160 }
2161 } /* End for() each digit. */
2162 }
2163 }
2164 }
2165
2166
2167 /****************************************************************************/
2168 /* siCompareAbs(): */
2169 /*--------------------------------------------------------------------------*/
2170 /* DESCRIPTION */
2171 /* Compares the absolute value of two synthetic integers (this involves */
2172 /* comparing only the string representation without considering the */
2173 /* sign). This function is useful from within the full compare function */
2174 /* to avoid duplication of code--it isn't very useful in any other */
2175 /* context. */
2176 /* */
2177 /* INPUTS */
2178 /* *arg1, *arg2 : Two synthetic integers whose absolute values should */
2179 /* be compared. */
2180 /* */
2181 /* OUTPUT */
2182 /* <-- : (-1) : ABS(*arg1) < ABS(*arg2) */
2183 /* (0) : ABS(*arg1) = ABS(*arg2) */
2184 /* (1) : ABS(*arg1) > ABS(*arg2) */
2185 /****************************************************************************/
2186 int siCompareAbs(SYNTHETIC_INTEGER **arg1, SYNTHETIC_INTEGER **arg2)
2187 {
2188 int i;
2189
2190 asAssert(arg1 != NULL, __LINE__);
2191 asAssert(*arg1 != NULL, __LINE__);
2192 asAssert(arg2 != NULL, __LINE__);
2193 asAssert(*arg2 != NULL, __LINE__);
2194
2195 if ((*arg1)->len < (*arg2)->len)
2196 {
2197 return(-1);
2198 }
2199 else if ((*arg1)->len > (*arg2)->len)
2200 {
2201 return(1);
2202 }
2203 else if (!((*arg1)->len) && !((*arg2)->len))
2204 {
2205 /* Both are zero, return equal. */
2206 return(0);
2207 }
2208 else
2209 {
2210 /* Lengths of strings are equal--must look at the strings in
2211 ** more detail.
2212 */
2213 for (i = (*arg1)->len; i >= 0; i--)
2214 {
2215 if ((*arg1)->digits[i] < (*arg2)->digits[i])
2216 {
2217 return(-1);
2218 }
2219 else if ((*arg1)->digits[i] > (*arg2)->digits[i])
2220 {
2221 return(1);
2222 }
2223 }
2224
2225 /* Have iterated through the strings--couldn't find any differences.
2226 ** They are equal. This also covers the zero case.
2227 */
2228 return(0);
2229 }
2230 }
2231
2232
2233 /****************************************************************************/
2234 /* siCompare(): */
2235 /*--------------------------------------------------------------------------*/
2236 /* DESCRIPTION */
2237 /* Establishes the logical ordering of two synthetic integers. */
2238 /* */
2239 /* INPUTS */
2240 /* *arg1, *arg2 : Two synthetic integers to compare. */
2241 /* */
2242 /* OUTPUT */
2243 /* <-- : (-1) : *arg1 < *arg2. */
2244 /* (0) : *arg1 = *arg2 */
2245 /* (1) : *arg1 > *arg2 */
2246 /****************************************************************************/
2247 int siCompare(SYNTHETIC_INTEGER **arg1, SYNTHETIC_INTEGER **arg2)
2248 {
2249 asAssert(arg1 != NULL, __LINE__);
2250 asAssert(*arg1 != NULL, __LINE__);
2251 asAssert(arg2 != NULL, __LINE__);
2252 asAssert(*arg2 != NULL, __LINE__);
2253
2254 /* If either integer has been marked NAN, we shouldn't be
2255 ** comparing, and there is no reason to handle this case,
2256 ** as it is a minority case and harmless whatever happens.
2257 */
2258 /* Cover the two easiest cases, which are where one operand is
2259 ** positive and the other is negative.
2260 */
2261 if (((*arg1)->neg) && (!((*arg2)->neg)))
2262 {
2263 return(-1);
2264 }
2265 else if ((!((*arg1)->neg)) && ((*arg2)->neg))
2266 {
2267 return(1);
2268 }
2269 /* We know both integers are of the same sign. We can call the
2270 ** absolute value compare function to get their ordering.
2271 */
2272 else if ((*arg1)->neg)
2273 {
2274 return(siCompareAbs(arg2, arg1)); /* Reverse the order to negate the
2275 ** results provided by
2276 ** siCompareAbs().
2277 */
2278 }
2279 else if (!((*arg1)->neg))
2280 {
2281 return(siCompareAbs(arg1, arg2)); /* Normal non-neg compare.
2282 */
2283 }
2284 else
2285 {
2286 /* It should be impossible to reach this case.
2287 */
2288 asAssert(0, __LINE__); /* Fatal. */
2289 return(0); /* Suppress compiler warning. */
2290 }
2291 }
2292
2293
2294 /****************************************************************************/
2295 /* siDump(): */
2296 /*--------------------------------------------------------------------------*/
2297 /* DESCRIPTION */
2298 /* Outputs a synthetic integer to the standard output stream. The output */
2299 /* includes a title, and provisions are made for NAN, for a description, */
2300 /* and prints commas. It is the caller's responsibility to provide lines */
2301 /* before and lines after if desired. Ths function assumes that it */
2302 /* starts with the cursor in column 1. */
2303 /* */
2304 /* INPUTS */
2305 /* **si : The synthetic integer which is being output. */
2306 /* */
2307 /* *desc : The description to use for the integer. It will be */
2308 /* right-justified up against the start of the integer, */
2309 /* and this function will automatically include a */
2310 /* colon. If the description is too long, this function */
2311 /* will truncate it to fit the space available. */
2312 /****************************************************************************/
2313 void siDump(SYNTHETIC_INTEGER **si, const char *desc)
2314 {
2315 unsigned cur_line;
2316 unsigned nlines;
2317 unsigned digits_per_line;
2318
2319 /* Make sure the caller isn't doing something bad for the program's health.
2320 */
2321 asAssert(si != NULL, __LINE__);
2322 asAssert(*si != NULL, __LINE__);
2323 asAssert(desc != NULL, __LINE__);
2324
2325 /* The number of digits per line that we assume must be a multiple of
2326 ** three. Round this up in case the preprocessor constant was set
2327 ** dubiously.
2328 */
2329 digits_per_line = ddUmax(3, ((DIGITS_PER_LINE + 2) /3) * 3);
2330
2331 /* As the first order of business, figure out how many lines the beast
2332 ** will require.
2333 */
2334 if ((*si)->nan)
2335 {
2336 nlines = 1; /* Only one line required for NAN verbeage. */
2337 }
2338 else if (!((*si)->len))
2339 {
2340 nlines = 1; /* The zero value requires one line. */
2341 }
2342 else
2343 {
2344 /* In any other case, have a formula.
2345 */
2346 nlines = 1 + ((*si)->len - 1) / digits_per_line;
2347 }
2348
2349 /* Iterate through each line, spitting out whatever is appropriate. */
2350 for (cur_line = 0; cur_line < nlines; cur_line++)
2351 {
2352 unsigned cur_digit_on_line;
2353
2354 /* If this is the first line, spit out the description, right-aligned.
2355 ** Otherwise, spit spaces.
2356 */
2357 if (!cur_line)
2358 {
2359 /* First line. */
2360 unsigned len;
2361
2362 len = strlen(desc);
2363
2364 if (len <= NUMBER_DESC_WIDTH)
2365 {
2366 /* Description is shorter or equal, pad on left. */
2367 gfRepChar(' ', NUMBER_DESC_WIDTH - len);
2368 printf("%s", desc);
2369 }
2370 else
2371 {
2372 /* Description is too long, truncate. */
2373 unsigned i;
2374
2375 for (i=0; i<len; i++)
2376 printf("%c", desc[i]);
2377 }
2378
2379 printf(": ");
2380
2381 /* If the number is negative, throw in a minus sign. */
2382 if ((*si)->neg && !(*si)->nan)
2383 {
2384 printf("- ");
2385 }
2386 else
2387 {
2388 printf(" ");
2389 }
2390 }
2391 else
2392 {
2393 /* Every line but first line. */
2394 gfRepChar(' ', NUMBER_DESC_WIDTH+4);
2395 }
2396
2397 for(cur_digit_on_line=0; cur_digit_on_line < digits_per_line; cur_digit_on_line++)
2398 {
2399 unsigned idx_into_string;
2400 /* Index into the string which is our digit of interest.
2401 */
2402
2403 /* Compute the index. The equation is based on the ordering
2404 ** of presentation, for example,
2405 **
2406 ** 7 6
2407 ** 5 4 3
2408 ** 2 1 0.
2409 **
2410 ** With a little thought, the equation should make sense.
2411 ** The index won't always be used to index into the string.
2412 */
2413 idx_into_string =
2414 (((nlines-1) - cur_line) * digits_per_line)
2415 +
2416 (digits_per_line - 1 - cur_digit_on_line);
2417
2418 /* Print the appropriate digit or a space. The NAN case and the
2419 ** zero case need to be treated specially.
2420 */
2421 if ((*si)->nan)
2422 {
2423 /* Not a number. Everything is blank, except spell out NAN
2424 ** at the end of the string of digits.
2425 */
2426 if (cur_digit_on_line == (digits_per_line - 3))
2427 {
2428 printf("N");
2429 }
2430 else if (cur_digit_on_line == (digits_per_line - 2))
2431 {
2432 printf("A");
2433 }
2434 else if (cur_digit_on_line == (digits_per_line - 1))
2435 {
2436 printf("N");
2437 }
2438 else
2439 {
2440 printf(" ");
2441 }
2442 }
2443 else if (!(*si)->len)
2444 {
2445 /* This is the zero case. For zero, there is only one line,
2446 ** and every character except the last one is a blank.
2447 */
2448 if (cur_digit_on_line == (digits_per_line - 1))
2449 {
2450 printf("0");
2451 }
2452 else
2453 {
2454 printf(" ");
2455 }
2456 }
2457 else
2458 {
2459 /* This is a valid number which is not zero. Need to print
2460 ** the digits.
2461 */
2462
2463 if (idx_into_string < (*si)->len)
2464 {
2465 printf("%c", (*si)->digits[idx_into_string]);
2466 }
2467 else
2468 {
2469 printf(" ");
2470 }
2471 } /* End of digit case.
2472
2473 /* Now handle the commas. The rules for commas are straightforward.
2474 ** a)NAN never has a comma.
2475 ** b)Zeros never have a comma.
2476 ** c)The final line, last digit never has a comma.
2477 ** d)Everything else in multiples of three ...
2478 */
2479 if (!(idx_into_string % 3) && (idx_into_string))
2480 {
2481 if ((*si)->nan)
2482 {
2483 printf(" ");
2484 }
2485 else if (!(*si)->len)
2486 {
2487 printf(" ");
2488 }
2489 else
2490 {
2491 if (idx_into_string < (*si)->len)
2492 {
2493 printf(",");
2494 }
2495 else
2496 {
2497 printf(" ");
2498 }
2499 }
2500 }
2501 } /* End for each digit on the current line. */
2502
2503 /* For the first line, print out an informative message
2504 ** advising of the number of digits. For all other lines
2505 ** print nothing.
2506 */
2507 if (!cur_line && !((*si)->nan))
2508 {
2509 if (nlines == 1)
2510 printf(" ");
2511
2512 if ((*si)->len <= 1)
2513 {
2514 printf(" ( 1 digit)\n");
2515 }
2516 else if ((*si)->len < 1000)
2517 {
2518 printf(" (%5u digits)\n", (*si)->len);
2519 }
2520 else
2521 {
2522 printf(" (%u,%03u digits)\n", (*si)->len / 1000, (*si)->len % 1000);
2523 }
2524 }
2525 else
2526 {
2527 printf("\n");
2528 }
2529 } /* End for each line. */
2530 }
2531
2532
2533 /****************************************************************************/
2534 /* siSetToLong(): */
2535 /*--------------------------------------------------------------------------*/
2536 /* DESCRIPTION */
2537 /* Sets a synthetic integer (which must already be created) to a long */
2538 /* value. This is used primarily in preliminary unit testing. */
2539 /* */
2540 /* INPUTS */
2541 /* **si : The synthetic integer to operate on. */
2542 /* */
2543 /* val : The value to set the synthetic integer to. */
2544 /****************************************************************************/
2545 void siSetToLong(SYNTHETIC_INTEGER **si, long val)
2546 {
2547 char buf[100];
2548 char *p;
2549 unsigned len;
2550 unsigned idx;
2551
2552 asAssert(si != NULL, __LINE__);
2553 asAssert(*si != NULL, __LINE__);
2554
2555 sprintf(buf, "%ld", val);
2556
2557 if (buf[0] == '-')
2558 p = buf+1;
2559 else
2560 p = buf;
2561
2562 len = strlen(p);
2563
2564 (*si)->nan = FALSE;
2565
2566 if (val == 0)
2567 {
2568 (*si)->nan = FALSE;
2569 (*si)->neg = FALSE;
2570 (*si)->len = 0;
2571 (*si)->digits[0] = '\0';
2572 }
2573 else
2574 {
2575 if (val < 0)
2576 {
2577 (*si)->neg = TRUE;
2578 }
2579 else
2580 {
2581 (*si)->neg = FALSE;
2582 }
2583
2584 (*si)->len = len;
2585
2586 for (idx=0; idx<len; idx++)
2587 {
2588 (*si)->digits[idx] = p[len - idx - 1];
2589 }
2590
2591 (*si)->digits[len] = '\0';
2592 }
2593 }
2594
2595
2596 /****************************************************************************/
2597 /* siSetToNan(): */
2598 /*--------------------------------------------------------------------------*/
2599 /* DESCRIPTION */
2600 /* Sets a synthetic integer (which must already be created) to NAN (not */
2601 /* a number). */
2602 /* */
2603 /* INPUTS */
2604 /* **si : The synthetic integer to set to NAN. */
2605 /* */
2606 /* NOTES */
2607 /* This program "evolved", and this function evolved after many of the */
2608 /* functions that set a number to NAN. There are may places in the code */
2609 /* where an integer is set to NAN without the use of this function. */
2610 /****************************************************************************/
2611 void siSetToNan(SYNTHETIC_INTEGER **si)
2612 {
2613 asAssert(si != NULL, __LINE__);
2614 asAssert(*si != NULL, __LINE__);
2615
2616 (*si)->digits[0] = '\0';
2617 (*si)->len = 0;
2618 (*si)->nan = TRUE;
2619 (*si)->neg = FALSE;
2620 }
2621
2622
2623 /****************************************************************************/
2624 /* siSetToPowerOfTen(): */
2625 /*--------------------------------------------------------------------------*/
2626 /* DESCRIPTION */
2627 /* Sets a synthetic integer (which must already be created) to an */
2628 /* integral power of ten. This function is helpful for math in many */
2629 /* cases. */
2630 /* */
2631 /* INPUTS */
2632 /* **si : The synthetic integer to operate on. */
2633 /* */
2634 /* exp : The integral exponent value (non-negative). For */
2635 /* example, a value of 0 here will result in the */
2636 /* assignment of 1, 1 here will result in the assignment */
2637 /* of 10, 2 here will result in the assignment of 100. */
2638 /* */
2639 /* ERRORS */
2640 /* A negative exponent will result in an assertion failure. An exponent */
2641 /* too large will result in the assignment of NAN. */
2642 /* */
2643 /* NOTE */
2644 /* This program "evolved", and this function evolved after many of the */
2645 /* functions that set a number to a power of 10 "directly". There may be */
2646 /* many places in the code where an integer is set to a power of 10 */
2647 /* without the use of this function. */
2648 /****************************************************************************/
2649 void siSetToPowerOfTen(SYNTHETIC_INTEGER **si, int exp)
2650 {
2651 int i;
2652
2653 asAssert(si != NULL, __LINE__);
2654 asAssert(*si != NULL, __LINE__);
2655 asAssert(exp >= 0, __LINE__);
2656
2657 if (exp < INTERMEDIATE_CALC_MAX_DIGITS)
2658 {
2659 (*si)->len = exp+1;
2660 (*si)->nan = FALSE;
2661 (*si)->neg = FALSE;
2662 (*si)->digits[exp+1] = '\0';
2663 (*si)->digits[exp] = '1';
2664 for (i=0; i<exp; i++)
2665 (*si)->digits[i] = '0';
2666 }
2667 else
2668 {
2669 siSetToNan(si);
2670 }
2671 }
2672
2673
2674 /****************************************************************************/
2675 /* siAddTwoNonnegative(): */
2676 /*--------------------------------------------------------------------------*/
2677 /* DESCRIPTION */
2678 /* Adds two synthetic integers which are guaranteed to be non-negative. */
2679 /* The result may be set NAN if there is an overflow. This is a low- */
2680 /* level function called by other higher-level functions to do more */
2681 /* complex arithmetic. */
2682 /* */
2683 /* INPUTS */
2684 /* **arg1, **arg2 : The two operands to add. Both operands must be */
2685 /* non-negative. It is legal for both SI's to */
2686 /* use the same storage or to be the same variable. */
2687 /* */
2688 /* OUTPUTS */
2689 /* **result : The synthetic integer where the output result is */
2690 /* placed. This may be the same SI as either or both */
2691 /* of the inputs. */
2692 /****************************************************************************/
2693 void siAddTwoNonnegative(SYNTHETIC_INTEGER **arg1,
2694 SYNTHETIC_INTEGER **arg2,
2695 SYNTHETIC_INTEGER **result)
2696 {
2697 SYNTHETIC_INTEGER *callers_orig_value = NULL;
2698 unsigned i;
2699 unsigned len1, len2, lenmax;
2700 char carry;
2701 char operand1, operand2, digitresult;
2702
2703 /* Be sure the caller isn't doing anything silly. */
2704 asAssert(arg1 != NULL, __LINE__);
2705 asAssert(*arg1 != NULL, __LINE__);
2706 asAssert(!((*arg1)->neg), __LINE__);
2707 asAssert(arg2 != NULL, __LINE__);
2708 asAssert(*arg2 != NULL, __LINE__);
2709 asAssert(!((*arg2)->neg), __LINE__);
2710 asAssert(result != NULL, __LINE__);
2711 asAssert(*result != NULL, __LINE__);
2712 asAssert((arg1 != arg2) && (arg2 != result) && (result != arg1), __LINE__);
2713
2714 /* If either input is NAN, the output is NAN by definition.
2715 */
2716 if (((*arg1)->nan) || ((*arg2)->nan))
2717 {
2718 (*result)->nan = TRUE;
2719 }
2720 else
2721 {
2722 /* The two input arguments don't matter because they aren't written,
2723 ** but if the caller has allowed the result to be the same as the
2724 ** either or both of the two inputs, must use a different memory
2725 ** location. However, only do this if need to, as will slow things
2726 ** down to create and destroy.
2727 */
2728 if ((*arg1 == *result) || (*arg2 == *result))
2729 {
2730 /* Caller has allowed result to be the same as either
2731 ** or both inputs. Must replace caller's pointer temporarily.
2732 */
2733 callers_orig_value = *result;
2734 siCreate(result);
2735 }
2736
2737 /* Zero out the potential result.
2738 */
2739 (*result)->neg = FALSE;
2740 (*result)->nan = FALSE;
2741 (*result)->len = 0;
2742 (*result)->digits[0] = '\0';
2743
2744 /* Buffer important handy values.
2745 */
2746 len1 = (*arg1)->len;
2747 len2 = (*arg2)->len;
2748 lenmax = ddUmax(len1, len2);
2749
2750 /* Be absolutely sure that both lengths are permissible values. Memory
2751 ** reference errors can be hard to track down.
2752 */
2753 asAssert(lenmax <= INTERMEDIATE_CALC_MAX_DIGITS, __LINE__);
2754
2755 /* Start off with an LSD carry input of '0', as there is no carry into the
2756 ** first digit.
2757 */
2758 carry = '0';
2759
2760 /* Iterate through, performing the addition, character by character.
2761 ** characters that are unpopulated are treated as zero.
2762 */
2763 for (i=0; i<lenmax; i++)
2764 {
2765 /* Grab the right character from the arguments. */
2766 if (i < len1)
2767 operand1 = (*arg1)->digits[i];
2768 else
2769 operand1 = '0';
2770 if (i < len2)
2771 operand2 = (*arg2)->digits[i];
2772 else
2773 operand2 = '0';
2774
2775 /* Perform the actual addition. Note that the carry value is copied
2776 ** copied onto the stack for the function call, so carry can double
2777 ** as both input and output.
2778 */
2779 ddFundamentalAdditionCell(operand1, operand2, carry, &digitresult, &carry);
2780
2781 /* Stuff the result digit in the right place. */
2782 (*result)->digits[i] = digitresult;
2783 }
2784
2785 /* After we're out of the loop, there are a few possible outcomes. If the
2786 ** carry is zero, then there is no risk of any kind of overflow.
2787 */
2788 if (carry == '0')
2789 {
2790 /* No risk of overflow. */
2791 (*result)->digits[i] = '\0';
2792 (*result)->len = i;
2793 }
2794 else
2795 {
2796 /* carry == '1' */
2797 /* There are two possibilities here. Either the result has grown one
2798 ** digit more than the longest input operand, and this is legal, or the
2799 ** result has grown one digit more and there is an overflow,
2800 ** forcing declaration of a NAN.
2801 */
2802 if (i == INTERMEDIATE_CALC_MAX_DIGITS)
2803 {
2804 (*result)->nan = TRUE;
2805 (*result)->len = 0;
2806 (*result)->digits[0] = '\0';
2807 }
2808 else
2809 {
2810 (*result)->len = i+1;
2811 (*result)->digits[i] = carry;
2812 (*result)->digits[i+1] = '\0';
2813 }
2814 }
2815
2816 /* If it was necessary to evacuate the caller's result area, swap it back
2817 ** and deallocate memory.
2818 */
2819 if (callers_orig_value)
2820 {
2821 siCopy(result, &callers_orig_value);
2822 siDestroy(result);
2823 *result = callers_orig_value;
2824 }
2825 }
2826 }
2827
2828
2829 /****************************************************************************/
2830 /* siSubtractToProduceNonnegativeResult(): */
2831 /*--------------------------------------------------------------------------*/
2832 /* DESCRIPTION */
2833 /* Subtracts two synthetic integers, with the understanding that the */
2834 /* result will be non-negative. This function is used as a building */
2835 /* block for subtraction which can span zero. */
2836 /* */
2837 /* INPUTS */
2838 /* **arg1, **arg2 : The two operands to subtract. Both must be non- */
2839 /* negative. */
2840 /* */
2841 /* OUTPUTS */
2842 /* **result : **arg1 - **arg2, or a fatal error if the result */
2843 /* would be negative. */
2844 /****************************************************************************/
2845 void siSubtractToProduceNonnegativeResult(SYNTHETIC_INTEGER **arg1,
2846 SYNTHETIC_INTEGER **arg2,
2847 SYNTHETIC_INTEGER **result)
2848 {
2849 SYNTHETIC_INTEGER *callers_orig_value = NULL;
2850 unsigned i;
2851 unsigned len;
2852 char borrow;
2853 char operand1, operand2, digitresult;
2854
2855 /* Be sure the caller isn't doing anything silly. */
2856 asAssert(arg1 != NULL, __LINE__);
2857 asAssert(*arg1 != NULL, __LINE__);
2858 asAssert(!((*arg1)->neg), __LINE__);
2859 asAssert(arg2 != NULL, __LINE__);
2860 asAssert(*arg2 != NULL, __LINE__);
2861 asAssert(!((*arg2)->neg), __LINE__);
2862 asAssert(result != NULL, __LINE__);
2863 asAssert(*result != NULL, __LINE__);
2864 asAssert((arg1 != arg2) && (arg2 != result) && (result != arg1), __LINE__);
2865
2866 /* If either input is NAN, the output is NAN by definition.
2867 */
2868 if (((*arg1)->nan) || ((*arg2)->nan))
2869 {
2870 (*result)->nan = TRUE;
2871 }
2872 else
2873 {
2874 /* The two input arguments don't matter because they aren't written,
2875 ** but if the caller has allowed the result to be the same as the
2876 ** either or both of the two inputs, must use a different memory
2877 ** location. However, only do this if need to, as will slow things
2878 ** down to create and destroy.
2879 */
2880 if ((*arg1 == *result) || (*arg2 == *result))
2881 {
2882 /* Caller has allowed result to be the same as either
2883 ** or both inputs. Must replace caller's pointer temporarily.
2884 */
2885 callers_orig_value = *result;
2886 siCreate(result);
2887 }
2888
2889 /* Zero out the potential result.
2890 */
2891 (*result)->neg = FALSE;
2892 (*result)->nan = FALSE;
2893 (*result)->len = 0;
2894 (*result)->digits[0] = '\0';
2895
2896 /* Buffer important handy values.
2897 */
2898 len = (*arg1)->len; /* By definition, this one is the max. */
2899
2900 /* Be absolutely sure that the length used for iteration is a
2901 ** permissible value.
2902 */
2903 asAssert(len <= INTERMEDIATE_CALC_MAX_DIGITS, __LINE__);
2904
2905 /* Start off with an LSD borrow input of '0', as there is no borrow into the
2906 ** first digit.
2907 */
2908 borrow = '0';
2909
2910 /* Iterate through, performing the subtraction, character by character.
2911 ** Characters that are unpopulated are treated as zero.
2912 */
2913 for (i=0; i<len; i++)
2914 {
2915 /* Grab the right character from the arguments. */
2916 operand1 = (*arg1)->digits[i];
2917 if (i < (*arg2)->len)
2918 operand2 = (*arg2)->digits[i];
2919 else
2920 operand2 = '0';
2921
2922 /* Perform the actual subtraction. Note that the borrow value is
2923 ** copied onto the stack for the function call, so double can double
2924 ** as both input and output.
2925 */
2926 /* printf("Idx: %u, borrow in: %c, ", i, borrow); */
2927
2928 ddFundamentalSubtractionCell(operand1, operand2, borrow, &digitresult, &borrow);
2929
2930 /* printf("op1: %c, op2: %c, borrow out: %c, result out: %c.\n",
2931 operand1,
2932 operand2,
2933 borrow,
2934 digitresult); */
2935
2936 /* Stuff the result digit in the right place. */
2937 (*result)->digits[i] = digitresult;
2938 }
2939
2940 /* Trim the leading zeros from the subtraction result. It would be more
2941 ** elegant to just identify the ripstop during the subtraction, but
2942 ** this will work, too.
2943 */
2944 if (!i)
2945 {
2946 /* We had a 0-0 subtraction. */
2947 (*result)->digits[0] = '\0';
2948 (*result)->len = 0;
2949 }
2950 else
2951 {
2952 (*result)->digits[i] = '\0';
2953 (*result)->len = i;
2954 while ((i >= 1) && ((*result)->digits[i-1] == '0'))
2955 {
2956 (*result)->digits[i-1] = '\0';
2957 (*result)->len = i-1;
2958 i--;
2959 }
2960 }
2961
2962 /* If it was necessary to evacuate the caller's result area, swap it back
2963 ** and deallocate memory.
2964 */
2965 if (callers_orig_value)
2966 {
2967 siCopy(result, &callers_orig_value);
2968 siDestroy(result);
2969 *result = callers_orig_value;
2970 }
2971 }
2972 }
2973
2974
2975 /****************************************************************************/
2976 /* siUnrestrictedAddition(): */
2977 /*--------------------------------------------------------------------------*/
2978 /* DESCRIPTION */
2979 /* Adds two integers of any sign. NAN is produced if anything overflows. */
2980 /* */
2981 /* INPUTS */
2982 /* **arg1, **arg2 : The two synthetic integer operand to add. It is */
2983 /* permitted for both to point to the same place. */
2984 /* */
2985 /* OUTPUTS */
2986 /* **result : The result. This may point to the same place as */
2987 /* either or both of arg1, arg2. */
2988 /****************************************************************************/
2989 void siUnrestrictedAddition(SYNTHETIC_INTEGER **arg1,
2990 SYNTHETIC_INTEGER **arg2,
2991 SYNTHETIC_INTEGER **result)
2992 {
2993 SYNTHETIC_INTEGER *callers_orig_value = NULL;
2994 int arg1_rel_arg2;
2995 unsigned arg1_is_neg;
2996 unsigned arg2_is_neg;
2997 unsigned case_number;
2998
2999 /* Be sure the caller isn't doing anything silly. Because double-
3000 ** indirection is involved, another word of explanation is needed.
3001 ** The caller is passing a pointer to his pointer. This isn't necessary
3002 ** in this circumstance (we'll never need to reallocate his object, for
3003 ** example), but it is just simpler to keep everthing consistent
3004 ** throughout the program. When I say that the caller can have pointers
3005 ** the same for the args and the result, I mean that the caller can have
3006 ** separate physical pointers which point to the same thing. However, the
3007 ** caller may not have one physical pointer only and pass us three identical
3008 ** pointers to the same physical pointer. This is illegal. The caller must
3009 ** have three seperate pointers, even if they point to the same place.
3010 */
3011 asAssert(arg1 != NULL, __LINE__);
3012 asAssert(*arg1 != NULL, __LINE__);
3013 asAssert(arg2 != NULL, __LINE__);
3014 asAssert(*arg2 != NULL, __LINE__);
3015 asAssert(result != NULL, __LINE__);
3016 asAssert(*result != NULL, __LINE__);
3017 asAssert((arg1 != arg2) && (arg2 != result) && (result != arg1), __LINE__);
3018
3019 /* The two input arguments don't matter because they aren't written,
3020 ** but if the caller has allowed the result to be the same as the
3021 ** either or both of the two inputs, must use a different memory
3022 ** location. However, only do this if need to, as will slow things
3023 ** down to create and destroy.
3024 */
3025 if ((*arg1 == *result) || (*arg2 == *result))
3026 {
3027 /* Caller has allowed result to be the same as either
3028 ** or both inputs. Must replace caller's pointer temporarily.
3029 */
3030 callers_orig_value = *result;
3031 siCreate(result);
3032 }
3033
3034 /* Zero out the potential result.
3035 */
3036 (*result)->neg = FALSE;
3037 (*result)->nan = FALSE;
3038 (*result)->len = 0;
3039 (*result)->digits[0] = '\0';
3040
3041 /* If either operand is NAN, the result is NAN. That is all the
3042 ** needs to be said.
3043 */
3044 if (((*arg1)->nan) || ((*arg2)->nan))
3045 {
3046 (*result)->nan = TRUE;
3047 }
3048 else
3049 {
3050 /* Gather some vital statistics about the two numbers passed. These
3051 ** will be used to break into cases.
3052 */
3053 arg1_rel_arg2 = siCompareAbs(arg1, arg2) + 1;
3054 arg1_is_neg = (*arg1)->neg;
3055 arg2_is_neg = (*arg2)->neg;
3056
3057 /* Zero out the signs of the two numbers. They will be restored
3058 ** later.
3059 */
3060 (*arg1)->neg = FALSE;
3061 (*arg2)->neg = FALSE;
3062
3063 /* Create a case number based on the above examination. It is easier
3064 ** to do it this way so there is only one switch statement.
3065 */
3066 case_number = ((unsigned)arg1_rel_arg2 * 4)
3067 + arg1_is_neg * 2
3068 + arg2_is_neg;
3069
3070 /* printf("Case number: %u.\n", case_number); */
3071
3072 switch(case_number)
3073 {
3074 /*********************************************************************/
3075 case 0:
3076 /* abs(arg1) < abs(arg2) */
3077 /* arg1 >= 0 */
3078 /* arg2 >= 0 */
3079 /* Both arguments were non-negative. The result will be non-
3080 ** negative, perhaps NAN. Just add the two numbers, perhaps
3081 ** resulting in NAN.
3082 */
3083 siAddTwoNonnegative(arg1, arg2, result);
3084 break;
3085 /*********************************************************************/
3086 case 1:
3087 /* abs(arg1) < abs(arg2) */
3088 /* arg1 >= 0 */
3089 /* arg2 < 0 */
3090 /* arg2 is negative, and will overwhelm arg1 and produce a negative
3091 ** result. Get the positive result and flip the sign.
3092 */
3093 siSubtractToProduceNonnegativeResult(arg2, arg1, result);
3094 if (!((*result)->nan))
3095 (*result)->neg = TRUE;
3096 break;
3097 /*********************************************************************/
3098 case 2:
3099 /* abs(arg1) < abs(arg2) */
3100 /* arg1 < 0 */
3101 /* arg2 >= 0 */
3102 /* Result will be positive, dominated by arg2. */
3103 siSubtractToProduceNonnegativeResult(arg2, arg1, result);
3104 break;
3105 /*********************************************************************/
3106 case 3:
3107 /* abs(arg1) < abs(arg2) */
3108 /* arg1 < 0 */
3109 /* arg2 < 0 */
3110 /* arg1 and arg2 both negative. Add them in a positive sense and
3111 ** negate the result.
3112 */
3113 siAddTwoNonnegative(arg1, arg2, result);
3114 if (!((*result)->nan))
3115 (*result)->neg = TRUE;
3116 break;
3117 /*********************************************************************/
3118 case 4:
3119 /* abs(arg1) == abs(arg2) */
3120 /* arg1 >= 0 */
3121 /* arg2 >= 0 */
3122 /* Two are equal and non-negative. Just add.
3123 */
3124 siAddTwoNonnegative(arg1, arg2, result);
3125 break;
3126 /*********************************************************************/
3127 case 5:
3128 /* abs(arg1) == abs(arg2) */
3129 /* arg1 >= 0 */
3130 /* arg2 < 0 */
3131 /* Result is zero. Just leave the result the way it is, as we
3132 ** set the result to zero higher up in the code.
3133 */
3134 break;
3135 /*********************************************************************/
3136 case 6:
3137 /* abs(arg1) == abs(arg2) */
3138 /* arg1 < 0 */
3139 /* arg2 >= 0 */
3140 /* Result is zero. Just leave the result the way it is, as we
3141 ** set the result to zero higher up in the code.
3142 */
3143 break;
3144 /*********************************************************************/
3145 case 7:
3146 /* abs(arg1) == abs(arg2) */
3147 /* arg1 < 0 */
3148 /* arg2 < 0 */
3149 /* Two are equal and negative. Add and negate.
3150 */
3151 siAddTwoNonnegative(arg1, arg2, result);
3152 if (!((*result)->nan))
3153 (*result)->neg = TRUE;
3154 break;
3155 /*********************************************************************/
3156 case 8:
3157 /* abs(arg1) > abs(arg2) */
3158 /* arg1 >= 0 */
3159 /* arg2 >= 0 */
3160 /* Both non-negative. Just add.
3161 */
3162 siAddTwoNonnegative(arg1, arg2, result);
3163 break;
3164 /*********************************************************************/
3165 case 9:
3166 /* abs(arg1) > abs(arg2) */
3167 /* arg1 >= 0 */
3168 /* arg2 < 0 */
3169 /* Result is positive and driven by arg1. Subtract. */
3170 siSubtractToProduceNonnegativeResult(arg1, arg2, result);
3171 break;
3172 /*********************************************************************/
3173 case 10:
3174 /* abs(arg1) > abs(arg2) */
3175 /* arg1 < 0 */
3176 /* arg2 >= 0 */
3177 /* Result is negative and driven by arg1. Subtract and negate.
3178 */
3179 siSubtractToProduceNonnegativeResult(arg1, arg2, result);
3180 if (!((*result)->nan))
3181 (*result)->neg = TRUE;
3182 break;
3183 /*********************************************************************/
3184 case 11:
3185 /* abs(arg1) > abs(arg2) */
3186 /* arg1 < 0 */
3187 /* arg2 < 0 */
3188 /* Result is negative. Add and negate.
3189 */
3190 siAddTwoNonnegative(arg1, arg2, result);
3191 if (!((*result)->nan))
3192 (*result)->neg = TRUE;
3193 break;
3194 /*********************************************************************/
3195 default:
3196 /* Should never be here. Fatal out. */
3197 asAssert(0, __LINE__);
3198 break;
3199 /*********************************************************************/
3200 }
3201
3202 /* Restore the results of the input arguments. We will really mess up
3203 ** the caller if we don't.
3204 */
3205 (*arg1)->neg = arg1_is_neg;
3206 (*arg2)->neg = arg2_is_neg;
3207 }
3208
3209
3210 /* If it was necessary to evacuate the caller's result area, swap it back
3211 ** and deallocate memory.
3212 */
3213 if (callers_orig_value)
3214 {
3215 siCopy(result, &callers_orig_value);
3216 siDestroy(result);
3217 *result = callers_orig_value;
3218 }
3219 }
3220
3221 /****************************************************************************/
3222 /* siUnrestrictedSubtraction(): */
3223 /*--------------------------------------------------------------------------*/
3224 /* DESCRIPTION */
3225 /* Subtracts two integers of any sign. NAN is produced if anything */
3226 /* overflows. */
3227 /* */
3228 /* INPUTS */
3229 /* **arg1, **arg2 : The two synthetic integer operand to subtract. */
3230 /* Both may point to the same place. */
3231 /* */
3232 /* OUTPUTS */
3233 /* **result : The result, arg1-arg2. May point to the same */
3234 /* place as either or both of arg1, arg2. */
3235 /****************************************************************************/
3236 void siUnrestrictedSubtraction(SYNTHETIC_INTEGER **arg1,
3237 SYNTHETIC_INTEGER **arg2,
3238 SYNTHETIC_INTEGER **result)
3239 {
3240 unsigned neg;
3241
3242 /* Be sure the caller is doing nothing silly. */
3243 asAssert(arg1 != NULL, __LINE__);
3244 asAssert(*arg1 != NULL, __LINE__);
3245 asAssert(arg2 != NULL, __LINE__);
3246 asAssert(*arg2 != NULL, __LINE__);
3247 asAssert(result != NULL, __LINE__);
3248 asAssert(*result != NULL, __LINE__);
3249 asAssert((arg1 != arg2) && (arg2 != result) && (result != arg1), __LINE__);
3250
3251 /* If either operand is NAN, the result is NAN. */
3252 if ((*arg1)->nan || (*arg2)->nan)
3253 {
3254 (*result)->digits[0] = '\0';
3255 (*result)->len = 0;
3256 (*result)->nan = TRUE;
3257 (*result)->neg = FALSE;
3258 }
3259 else
3260 {
3261 /* Subtraction is easy to express in terms of addition, since the
3262 ** addition function already handles both operands of both signs.
3263 */
3264 if ((*arg2)->len) /* Can't negate zero in this way. */
3265 {
3266 neg = (*arg2)->neg;
3267 (*arg2)->neg = !((*arg2)->neg);
3268 }
3269
3270 siUnrestrictedAddition(arg1, arg2, result);
3271
3272 if ((*arg2)->len)
3273 (*arg2)->neg = neg;
3274 }
3275 }
3276
3277
3278 /****************************************************************************/
3279 /* siUnrestrictedMultiplication(): */
3280 /*--------------------------------------------------------------------------*/
3281 /* DESCRIPTION */
3282 /* Muiltiplies two integers of any sign. NAN is produced if anything */
3283 /* overflows. */
3284 /* */
3285 /* INPUTS */
3286 /* **arg1, **arg2 : The two synthetic integer operands to multiply. */
3287 /* Both may point to the same place. */
3288 /* */
3289 /* OUTPUTS */
3290 /* **result : The result, arg1*arg2. May point to the same */
3291 /* place as either or both of arg1, arg2. */
3292 /****************************************************************************/
3293 void siUnrestrictedMultiplication(SYNTHETIC_INTEGER **arg1,
3294 SYNTHETIC_INTEGER **arg2,
3295 SYNTHETIC_INTEGER **result)
3296 {
3297 /* Be sure the caller is doing nothing silly. */
3298 asAssert(arg1 != NULL, __LINE__);
3299 asAssert(*arg1 != NULL, __LINE__);
3300 asAssert(arg2 != NULL, __LINE__);
3301 asAssert(*arg2 != NULL, __LINE__);
3302 asAssert(result != NULL, __LINE__);
3303 asAssert(*result != NULL, __LINE__);
3304 asAssert((arg1 != arg2) && (arg2 != result) && (result != arg1), __LINE__);
3305
3306 /* If either argument is NAN, the result is NAN.
3307 */
3308 if ((*arg1)->nan || (*arg2)->nan)
3309 {
3310 (*result)->digits[0] = '\0';
3311 (*result)->len = 0;
3312 (*result)->nan = TRUE;
3313 (*result)->neg = FALSE;
3314 }
3315 /* If either argument is zero, result is zero. */
3316 else if (!((*arg1)->len) || !((*arg2)->len))
3317 {
3318 (*result)->digits[0] = '\0';
3319 (*result)->len = 0;
3320 (*result)->nan = FALSE;
3321 (*result)->neg = FALSE;
3322 }
3323 else
3324 {
3325 /* We have two non-zero operands, fit to be multiplied.
3326 */
3327 SYNTHETIC_INTEGER *rt, *temp, *rt2;
3328 int cidx, len;
3329 char cur_digit;
3330 unsigned negarg1, negarg2;
3331
3332 /* Must save the signs of the arguments and restore. */
3333 negarg1 = (*arg1)->neg;
3334 negarg2 = (*arg2)->neg;
3335 (*arg1)->neg = FALSE;
3336 (*arg2)->neg = FALSE;
3337
3338 /* Create (allocate) a synthetic integer to contain the result
3339 ** that will be returned to the caller.
3340 */
3341 siCreate(&rt);
3342
3343 /* Must create an alias. The reasons for this are complex. I coded
3344 ** myself into a corner and have to live with it.
3345 */
3346 rt2 = rt;
3347
3348 /* Create (allocate) a synthetic integer that will be used to hold
3349 ** the result of multiplying arg2 by a digit.
3350 */
3351 siCreate(&temp);
3352
3353 /* Go through, multiplying in much the same way as one would by hand.
3354 */
3355 len = (*arg1)->len;
3356
3357 for (cidx = len-1; cidx >= 0; cidx--)
3358 {
3359 #if 0
3360 printf("cidx: %d\n", cidx);
3361 printf("rt before * 10 multiply\n");
3362 siDump(&rt, "rt before");
3363 /* Multiply the pending result by 10 */
3364 #endif
3365 siMulByTen(&rt);
3366 /* siDump(&rt, "rt after"); */
3367
3368 /* Grab the current digit of interest and multiply arg2 by it. */
3369 cur_digit = (*arg1)->digits[cidx];
3370 /* printf("cur digit: %c\n", cur_digit); */
3371
3372 siCopy(arg2, &temp);
3373 /* siDump(&temp, "copy of arg2"); */
3374 siMulByDigit(&temp, cur_digit);
3375 /* siDump(&temp, "arg2 * digit"); */
3376
3377 /* Add the result of the multiplication to the pending
3378 ** result.
3379 */
3380 siUnrestrictedAddition(&rt2, &temp, &rt);
3381
3382 #if 0
3383 siDump(&rt2, "rt2");
3384 siDump(&rt, "rt");
3385 siDump(&temp, "temp");
3386 #endif
3387 }
3388
3389 /* We're done with the mathematical operation. Signs should be a self-
3390 ** healing matter.
3391 */
3392 /* Copy the result back to caller's area. */
3393 siCopy(&rt, result);
3394
3395 /* Destroy temporary areas. */
3396 siDestroy(&rt);
3397 siDestroy(&temp);
3398
3399 /* Restore the signs of the integers that were arguments, then the
3400 ** sign of the result.
3401 */
3402 (*arg1)->neg = negarg1;
3403 (*arg2)->neg = negarg2;
3404
3405 if ((negarg1 && negarg2) || (!negarg1 && !negarg2))
3406 (*result)->neg = FALSE;
3407 else
3408 (*result)->neg = TRUE;
3409
3410 /* siDump(result, "result"); */
3411 }
3412 }
3413
3414
3415 /****************************************************************************/
3416 /* siUnrestrictedDivision(): */
3417 /*--------------------------------------------------------------------------*/
3418 /* DESCRIPTION */
3419 /* Divides two synthetic integers of any sign, producing an integer */
3420 /* quotient and integer remainder. NAN is assigned to both the quotient */
3421 /* and remainder on invalid inputs. NAN due to overflow is not possible */
3422 /* in this function, as any integer divided by 1 or -1 yields an integer */
3423 /* of the same magnitude. */
3424 /* */
3425 /* INPUTS */
3426 /* **dividend : The dividend of the division. May be any value. */
3427 /* */
3428 /* **divisor : The divisor of the division. May be any value */
3429 /* except zero. */
3430 /* */
3431 /* OUTPUTS */
3432 /* **quotient : The integer quotient of the division. This should */
3433 /* behave identically to the C "/" operator when */
3434 /* applied to integers. */
3435 /* */
3436 /* **remainder : The remainder of the division. This should behave */
3437 /* identically to the C "%" operator. There was some */
3438 /* question in my mind about the best way to define a */
3439 /* remainder with a negative dividend or divisor, but */
3440 /* I simply used the behavior of the "%" operator in */
3441 /* C as a guide. */
3442 /* */
3443 /* USAGE NOTES */
3444 /* The functions in this program are inconsistent about whether they */
3445 /* allow the inputs and the outputs to be pointers to the same memory */
3446 /* locations, etc. This program was constructed impromptu, and I made */
3447 /* up the rules as I went along. I've now decided that it isn't that */
3448 /* useful to allow this, so for this function I'll require uniqueness */
3449 /* between the four parameters. This doesn't affect the correctness */
3450 /* of the program--just its internal elegance. These inconsistent */
3451 /* decisions are not visible by using the program. */
3452 /****************************************************************************/
3453 void siUnrestrictedDivision(SYNTHETIC_INTEGER **dividend,
3454 SYNTHETIC_INTEGER **divisor,
3455 SYNTHETIC_INTEGER **quotient,
3456 SYNTHETIC_INTEGER **remainder)
3457 {
3458 /* Be sure the caller is doing nothing silly. */
3459 /* No first- or second-level pointers may be NULL. */
3460 asAssert(dividend != NULL, __LINE__);
3461 asAssert(*dividend != NULL, __LINE__);
3462 asAssert(divisor != NULL, __LINE__);
3463 asAssert(*divisor != NULL, __LINE__);
3464 asAssert(quotient != NULL, __LINE__);
3465 asAssert(*quotient != NULL, __LINE__);
3466 asAssert(remainder != NULL, __LINE__);
3467 asAssert(*remainder != NULL, __LINE__);
3468 /* All pointers must be mutually exclusive. */
3469 asAssert((dividend != divisor) && (dividend != quotient) && (dividend != remainder), __LINE__);
3470 asAssert((*dividend != *divisor) && (*dividend != *quotient) && (*dividend != *remainder), __LINE__);
3471 asAssert((divisor != quotient) && (divisor != remainder), __LINE__);
3472 asAssert((*divisor != *quotient) && (*divisor != *remainder), __LINE__);
3473 asAssert(quotient != remainder, __LINE__);
3474 asAssert(*quotient != *remainder, __LINE__);
3475
3476 /* If either argument is NAN, the results are NAN. Also, if the divisor is zero,
3477 ** that causes two NAN's, as well.
3478 */
3479 if ((*dividend)->nan || (*divisor)->nan || !((*divisor)->len))
3480 {
3481 (*quotient)->digits[0] = '\0';
3482 (*quotient)->len = 0;
3483 (*quotient)->nan = TRUE;
3484 (*quotient)->neg = FALSE;
3485 (*remainder)->digits[0] = '\0';
3486 (*remainder)->len = 0;
3487 (*remainder)->nan = TRUE;
3488 (*remainder)->neg = FALSE;
3489 }
3490 /* Zero in the numerator always gets us zero on both outputs.
3491 */
3492 else if (!((*dividend)->len))
3493 {
3494 siSetToLong(quotient, 0);
3495 siSetToLong(remainder, 0);
3496 }
3497 /* Must do a legitimate long division. We know for sure that
3498 ** both dividend and divisor are non-zero.
3499 */
3500 else
3501 {
3502 unsigned dividend_is_neg;
3503 unsigned divisor_is_neg;
3504 /* Signs of dividend and divisor, saved so we only
3505 ** operate on positive numbers.
3506 */
3507 int quotient_ndigits;
3508 /* The number of digits in the quotient.
3509 */
3510 int i;
3511 /* General-purpose iteration variable.
3512 */
3513 char j;
3514 /* Trial digit for trial multiplication.
3515 */
3516 SYNTHETIC_INTEGER *si_temp1 = NULL,
3517 *si_temp2 = NULL,
3518 *si_temp3 = NULL;
3519 /* Temporary large integers. These need to be set
3520 ** to NULL here, because in the event of an
3521 ** error or unexpected condition, need to know
3522 ** which ones to release.
3523 */
3524
3525 /* Remember and reset the signs of the passed dividend and
3526 ** divisor. It makes it simpler just to consider positive
3527 ** numbers.
3528 */
3529 dividend_is_neg = (*dividend)->neg;
3530 divisor_is_neg = (*divisor)->neg;
3531 (*dividend)->neg = 0;
3532 (*divisor)->neg = 0;
3533
3534 /* If the dividend is less (in magnitude) than the divisor,
3535 ** the quotient is zero and the remainder is the
3536 ** dividend.
3537 */
3538 if (siCompare(dividend, divisor) == -1)
3539 {
3540 siSetToLong(quotient, 0);
3541 siCopy(dividend, remainder);
3542 (*remainder)->neg = dividend_is_neg;
3543 }
3544 else
3545 {
3546 /* Allocate all of the temporary integers.
3547 ** Done all in one place to eliminate paths
3548 ** through the code where may allocate something
3549 ** already allocated and cause a memory leak.
3550 */
3551 siCreate(&si_temp1);
3552 siCreate(&si_temp2);
3553 siCreate(&si_temp3);
3554
3555 /* Establish the number of digits in the
3556 ** quotient. There is a window near the maximum
3557 ** number of digits where we won't be able to
3558 ** successfully start the division because we
3559 ** can't form an upper bound which is a power
3560 ** of 10 times the divisor. In this case,
3561 ** just return NAN. This window won't be a problem
3562 ** in practice. It could be worked around, but
3563 ** no need to close it.
3564 */
3565 siCopy(divisor, &si_temp1);
3566 siMulByTen(&si_temp1);
3567 quotient_ndigits = 1;
3568 while(siCompare(&si_temp1, dividend) <= 0)
3569 {
3570 siMulByTen(&si_temp1);
3571 if (si_temp1->nan)
3572 goto nan_return;
3573 quotient_ndigits++;
3574 }
3575
3576 siDivByTen(&si_temp1);
3577
3578 /* printf("quotient number of digits: %d\n",
3579 quotient_ndigits);
3580 siDump(&si_temp1, "trial divisor"); */
3581
3582 /* We now know the number of digits that the
3583 ** quotient will contain. We also know the
3584 ** starting point to use for trial subtraction.
3585 ** Count down from the highest order digit to the
3586 ** lowest-order digit, subtracting the maximum
3587 ** amount each time.
3588 */
3589 /* si_temp1 is the trial divisor reference
3590 ** copy.
3591 */
3592 /* si_temp2 is a copy of the trial divisor,
3593 ** used to see what happens as we try multiplying
3594 ** by various trial digits.
3595 */
3596 /* remainder (in the caller's area) is used for
3597 ** staging the dividend after subtractions made.
3598 ** This will end up with the remainder in the
3599 ** end.
3600 */
3601 /* quotient (in the caller's area) contains the
3602 ** quotient. We'll stage it directly there.
3603 */
3604 (*quotient)->len = (unsigned)quotient_ndigits;
3605 (*quotient)->digits[(*quotient)->len] = '\0';
3606 siCopy(dividend, remainder);
3607
3608 /* For each digit in the result, going from most
3609 ** significant to least significant.
3610 */
3611 for (i=quotient_ndigits-1; i>=0; i--)
3612 {
3613 /* Try to find the largest digit for the spot
3614 ** that will not overflow the remainder.
3615 ** This is the right digit.
3616 */
3617 /* For each digit we might try.
3618 */
3619 for (j='0'; j<='9'; j++)
3620 {
3621 siCopy(&si_temp1, &si_temp2);
3622 /* Buffer the value so we can do a trial
3623 ** multiplication.
3624 */
3625 siMulByDigit(&si_temp2, j);
3626 /* Perform the trial multiplication
3627 ** by a digit.
3628 */
3629 siUnrestrictedSubtraction(remainder,
3630 &si_temp2,
3631 &si_temp3);
3632 /* Perform a trial subtraction involving the trial
3633 ** digit.
3634 */
3635
3636 /* We have success if what is left over after
3637 ** the trial subtraction is less than the
3638 ** trial divisor.
3639 */
3640 if (siCompare(&si_temp3, &si_temp1) < 0)
3641 break;
3642
3643 /* It is a fatal internal software error if
3644 ** we are at the digit '9' and the constraint
3645 ** still is not met.
3646 */
3647 asAssert(j != '9', __LINE__);
3648 } /* End for each possible digit. */
3649
3650 /* OK, we have the digit, and it is in the
3651 ** variable 'j'. We also have the value
3652 ** we should subtract and the result.
3653 ** Stuff the digit, and the result.
3654 */
3655 (*quotient)->digits[i] = j;
3656 siCopy(&si_temp3, remainder);
3657
3658 /* Divide the trial divisor by 10 for the
3659 ** next iteration.
3660 */
3661 siDivByTen(&si_temp1);
3662 } /* End for each digit position. */
3663
3664 /* We now need to figure out what the sign
3665 ** of the quotient and the remainder are.
3666 */
3667 if ((dividend_is_neg && !divisor_is_neg) ||
3668 (!dividend_is_neg && divisor_is_neg))
3669 (*quotient)->neg = TRUE;
3670 else
3671 (*quotient)->neg = FALSE;
3672
3673 if (dividend_is_neg && (*remainder)->len)
3674 (*remainder)->neg = TRUE;
3675 else
3676 (*remainder)->neg = FALSE;
3677 }
3678
3679 goto normal_return;
3680 nan_return: ;
3681 /* This is the return point where the quotient
3682 ** and remainder are marked NAN. Thank goodness
3683 ** they didn't forget about the "goto" in 'C'.
3684 */
3685
3686 normal_return:
3687 /* Restore the signs of the input arguments.
3688 */
3689 (*dividend)->neg = dividend_is_neg;
3690 (*divisor)->neg = divisor_is_neg;
3691
3692 /* Deallocate all allocated memory.
3693 */
3694 if (si_temp1)
3695 siDestroy(&si_temp1);
3696 if (si_temp2)
3697 siDestroy(&si_temp2);
3698 if (si_temp3)
3699 siDestroy(&si_temp3);
3700 }
3701 }
3702
3703
3704 /****************************************************************************/
3705 /* siGcd(): */
3706 /*--------------------------------------------------------------------------*/
3707 /* DESCRIPTION */
3708 /* Applies Euclid's algorithm to obtain the GCD of two positive integers. */
3709 /* Any unexpected input operands will generate a NAN for the GCD. */
3710 /* */
3711 /* INPUTS */
3712 /* **arg1, arg2 : The two positive integers whose GCD is to be found. */
3713 /* */
3714 /* OUTPUTS */
3715 /* **result : gcd(**arg1, **arg2). */
3716 /****************************************************************************/
3717 void siGcd(SYNTHETIC_INTEGER **arg1,
3718 SYNTHETIC_INTEGER **arg2,
3719 SYNTHETIC_INTEGER **result)
3720 {
3721
3722 /* Be sure the caller isn't doing anything silly. */
3723 asAssert(arg1 != NULL, __LINE__);
3724 asAssert(*arg1 != NULL, __LINE__);
3725 asAssert(arg2 != NULL, __LINE__);
3726 asAssert(*arg2 != NULL, __LINE__);
3727 asAssert(result != NULL, __LINE__);
3728 asAssert(*result != NULL, __LINE__);
3729
3730 /* A NAN input or zero or negative integers gets a NAN result.
3731 */
3732 if ((*arg1)->nan || (*arg2)->nan || !(*arg1)->len || !(*arg2)->len
3733 || (*arg1)->neg || (*arg2)->neg)
3734 {
3735 (*result)->digits[0] = '\0';
3736 (*result)->len = 0;
3737 (*result)->nan = TRUE;
3738 (*result)->neg = FALSE;
3739 }
3740 else
3741 {
3742 /* This algorithm is so well known and documented that I won't insult
3743 ** the reader with comments.
3744 */
3745 SYNTHETIC_INTEGER *h, *k, *q, *r;
3746
3747 siCreate(&h);
3748 siCreate(&k);
3749 siCreate(&q);
3750 siCreate(&r);
3751
3752 if (siCompare(arg1, arg2) == -1)
3753 {
3754 siCopy(arg1, &h);
3755 siCopy(arg2, &k);
3756 }
3757 else
3758 {
3759 siCopy(arg1, &k);
3760 siCopy(arg2, &h);
3761 }
3762
3763 siCopy(&h, &r);
3764
3765 do
3766 {
3767 siCopy(&r, result);
3768 siUnrestrictedDivision(&h,&k,&q,&r);
3769 siCopy(&k, &h);
3770 siCopy(&r, &k);
3771 } while (r->len);
3772
3773 siDestroy(&h);
3774 siDestroy(&k);
3775 siDestroy(&q);
3776 siDestroy(&r);
3777 }
3778 }
3779
3780
3781 /****************************************************************************/
3782 /* siIntegerExponentiation(): */
3783 /*--------------------------------------------------------------------------*/
3784 /* DESCRIPTION */
3785 /* Exponentiates one integer to the integral power of another. The */
3786 /* integer to be exponentiated may be of any sign, but the exponent must */
3787 /* be non-negative. Invalid or overflow conditions result in the */
3788 /* assignment of NAN. */
3789 /* */
3790 /* INPUTS */
3791 /* **arg : Integer to be exponentiated. */
3792 /* */
3793 /* **exponent : Exponent to use. Must be non-negative. */
3794 /* */
3795 /* OUTPUTS */
3796 /* **result : The result, arg1**arg2. */
3797 /* */
3798 /* NOTE */
3799 /* In other functions (written chronologically earlier), it was allowed */
3800 /* for the arguments and the result to be the same physical object. This */
3801 /* didn't prove to be a useful feature, so it is disallowed in this */
3802 /* function. */
3803 /****************************************************************************/
3804 void siIntegerExponentiation(SYNTHETIC_INTEGER **arg,
3805 SYNTHETIC_INTEGER **exponent,
3806 SYNTHETIC_INTEGER **result)
3807 {
3808 /* Be sure the caller is doing nothing silly. */
3809 asAssert(arg != NULL, __LINE__);
3810 asAssert(*arg != NULL, __LINE__);
3811 asAssert(exponent != NULL, __LINE__);
3812 asAssert(*exponent != NULL, __LINE__);
3813 asAssert(result != NULL, __LINE__);
3814 asAssert(*result != NULL, __LINE__);
3815 asAssert((arg != exponent) && (exponent != result) && (result != arg), __LINE__);
3816 asAssert((*arg != *exponent) && (*exponent != *result) && (*result != *arg), __LINE__);
3817
3818 /* If either argument is NAN, the result is NAN. */
3819 if (((*arg)->nan) || ((*exponent)->nan))
3820 {
3821 (*result)->digits[0] = '\0';
3822 (*result)->len = 0;
3823 (*result)->nan = TRUE;
3824 (*result)->neg = FALSE;
3825 }
3826 /* If we're trying to raise 0 to the 0th power, this is a no-no,
3827 ** as well.
3828 */
3829 else if (!((*arg)->len) && !((*exponent)->len))
3830 {
3831 (*result)->digits[0] = '\0';
3832 (*result)->len = 0;
3833 (*result)->nan = TRUE;
3834 (*result)->neg = FALSE;
3835 }
3836 /* A negative exponent is a no-no, as well.
3837 */
3838 else if ((*exponent)->neg)
3839 {
3840 (*result)->digits[0] = '\0';
3841 (*result)->len = 0;
3842 (*result)->nan = TRUE;
3843 (*result)->neg = FALSE;
3844 }
3845 /* Zero to any power but zero is zero.
3846 */
3847 else if (!((*arg)->len))
3848 {
3849 siSetToLong(result, 0);
3850 }
3851 /* Any number but zero to the zeroth power is one. */
3852 else if (!((*exponent)->len))
3853 {
3854 siSetToLong(result, 1);
3855 }
3856 else
3857 {
3858 unsigned binary_exponent;
3859 SYNTHETIC_INTEGER *temp_si1, *result_copy1, *temp_si2, *temp_si3;
3860
3861 /* Here we have a non-zero integer raised to a non-zero power.
3862 ** The best algorithm to do this is to examine the bit pattern
3863 ** corresponding to the exponent--we can generate arg**2,
3864 ** arg**4, arg**8, etc., just by repeatedly squaring it. NAN's
3865 ** are picked up automatically.
3866 */
3867 /* First, it is convenient convert the exponent to an
3868 ** unsigned integer, so we can examine the
3869 ** bit pattern directly. Will agree that anything over
3870 ** 32000 is treated as 32000, to avoid platform issues.
3871 */
3872 siCreate(&temp_si1);
3873 siCreate(&temp_si2);
3874 siCreate(&temp_si3);
3875 siCreate(&result_copy1);
3876
3877 siSetToLong(&temp_si1, 32000);
3878
3879 if (siCompare(exponent, &temp_si1) > 0)
3880 {
3881 asFatal("exponent too large (max is 32,000)");
3882 }
3883 else
3884 {
3885 /* Must convert from the string representation
3886 ** buried in the synthetic integer to a binary
3887 ** unsigned integer. This is a bit tricky because the
3888 ** string is in reverse order from the traditional.
3889 */
3890 {
3891 int sidx;
3892
3893 sidx = (*exponent)->len - 1;
3894 binary_exponent = 0;
3895
3896 while (sidx >= 0)
3897 {
3898 binary_exponent *= 10;
3899 binary_exponent += ddDigitToValue((*exponent)->digits[sidx]);
3900 sidx--;
3901 }
3902 }
3903 }
3904
3905 /* Start off with a result of 1 */
3906 siSetToLong(result, 1);
3907 siSetToLong(&result_copy1, 1);
3908
3909 /* Start off with arg**1 */
3910 siCopy(arg, &temp_si1);
3911 siCopy(arg, &temp_si2);
3912 siCopy(arg, &temp_si3);
3913
3914 while (binary_exponent)
3915 {
3916 /* Multiply result by the working register iff we have a 1 as the
3917 ** LSB of the exponent.
3918 */
3919 if (binary_exponent & 1)
3920 {
3921 siUnrestrictedMultiplication(
3922 &result_copy1,
3923 &temp_si1,
3924 result);
3925
3926 /* Clone out the result, because we're keeping an additional copy. */
3927 siCopy(result, &result_copy1);
3928 }
3929
3930
3931 /* Square the quantity cloned from the argument, and clone the copies
3932 ** back.
3933 */
3934 siUnrestrictedMultiplication(
3935 &temp_si1,
3936 &temp_si2,
3937 &temp_si3);
3938 siCopy(&temp_si3, &temp_si1);
3939 siCopy(&temp_si3, &temp_si2);
3940
3941 /* Shift the exponent down one bit. */
3942 binary_exponent >>= 1;
3943 }
3944
3945 /* Destroy all of the data structures created on the fly. */
3946 siDestroy(&temp_si1);
3947 siDestroy(&temp_si2);
3948 siDestroy(&temp_si3);
3949 siDestroy(&result_copy1);
3950
3951 /* At this point the result should contain the right value and
3952 ** we should be ready to return.
3953 */
3954 }
3955 }
3956
3957
3958 /****************************************************************************/
3959 /****************************************************************************/
3960 /********** R A T I O N A L N U M B E R F U N C T I O N S *********/
3961 /****************************************************************************/
3962 /****************************************************************************/
3963 /* This section is reserved for functions which operate on rational numbers.
3964 ** For directness, rational numbers are represented as integer pairs (no
3965 ** sense adding more data structures to this program.
3966 */
3967
3968 /****************************************************************************/
3969 /* rnSum(): */
3970 /*--------------------------------------------------------------------------*/
3971 /* DESCRIPTION */
3972 /* Calculates the sum of two rational numbers, supplying the results in */
3973 /* lowest terms. */
3974 /* */
3975 /* INPUTS */
3976 /* **h1_formal_par_in, */
3977 /* **k1_formal_par_in, */
3978 /* **h2_formal_par_in, */
3979 /* **k2_formal_par_in : The numerators and denominators of the two */
3980 /* rational numbers to add. Zero denominators */
3981 /* are not allowed, but duplicate pointers of all */
3982 /* types are. */
3983 /* **h_result, */
3984 /* **k_result : The result, in lowest terms. Zero is repre- */
3985 /* sented canonically as 0/1. The memory must be */
3986 /* allocated in the caller's area, and the two */
3987 /* data items must be distinct. */
3988 /****************************************************************************/
3989 void rnSum(SYNTHETIC_INTEGER **h1_formal_par_in,
3990 SYNTHETIC_INTEGER **k1_formal_par_in,
3991 SYNTHETIC_INTEGER **h2_formal_par_in,
3992 SYNTHETIC_INTEGER **k2_formal_par_in,
3993 SYNTHETIC_INTEGER **h_result,
3994 SYNTHETIC_INTEGER **k_result)
3995 {
3996 SYNTHETIC_INTEGER *arg1_h,
3997 *arg1_k,
3998 *arg2_h,
3999 *arg2_k,
4000 *common_denominator,
4001 *arg1_numerator,
4002 *arg2_numerator,
4003 *cumulative_numerator,
4004 *result_gcd,
4005 *trash_remainder;
4006
4007 unsigned is_neg = FALSE;
4008
4009 /* Be sure the caller isn't doing anything silly with pointers.
4010 */
4011 asAssert(h1_formal_par_in != NULL, __LINE__);
4012 asAssert(*h1_formal_par_in != NULL, __LINE__);
4013 asAssert(k1_formal_par_in != NULL, __LINE__);
4014 asAssert(*k1_formal_par_in != NULL, __LINE__);
4015 asAssert(h2_formal_par_in != NULL, __LINE__);
4016 asAssert(*h2_formal_par_in != NULL, __LINE__);
4017 asAssert(k2_formal_par_in != NULL, __LINE__);
4018 asAssert(*k2_formal_par_in != NULL, __LINE__);
4019 asAssert(h_result != NULL, __LINE__);
4020 asAssert(*h_result != NULL, __LINE__);
4021 asAssert(k_result != NULL, __LINE__);
4022 asAssert(*k_result != NULL, __LINE__);
4023 asAssert(h_result != k_result, __LINE__);
4024 asAssert(*h_result != *k_result, __LINE__);
4025
4026 /* Allocate space for temporary variables.
4027 */
4028 siCreate(&arg1_h);
4029 siCreate(&arg1_k);
4030 siCreate(&arg2_h);
4031 siCreate(&arg2_k);
4032 siCreate(&common_denominator);
4033 siCreate(&arg1_numerator);
4034 siCreate(&arg2_numerator);
4035 siCreate(&cumulative_numerator);
4036 siCreate(&result_gcd);
4037 siCreate(&trash_remainder);
4038
4039 /* Copy over the formal parameters to local variables. This
4040 ** means we can modify the inputs without worry.
4041 */
4042 siCopy(h1_formal_par_in, &arg1_h);
4043 siCopy(k1_formal_par_in, &arg1_k);
4044 siCopy(h2_formal_par_in, &arg2_h);
4045 siCopy(k2_formal_par_in, &arg2_k);
4046
4047 /* If any of the four inputs are NAN, the results must be
4048 ** NAN.
4049 */
4050 if (arg1_h->nan || arg1_k->nan || arg2_h->nan || arg2_k->nan)
4051 {
4052 goto nan_return;
4053 }
4054
4055 /* If either denominator is zero, the result is NAN.
4056 */
4057 if (!(arg1_k->len) || !(arg2_k->len))
4058 {
4059 goto nan_return;
4060 }
4061
4062 /* Adjust the signs of the the arguments so that the denominators are
4063 ** always positive.
4064 */
4065 if (arg1_h->neg && arg1_k->neg)
4066 {
4067 arg1_h->neg = FALSE;
4068 arg1_k->neg = FALSE;
4069 }
4070 else if (!(arg1_h->neg) && arg1_k->neg)
4071 {
4072 arg1_h->neg = TRUE;
4073 arg1_k->neg = FALSE;
4074 }
4075
4076 if (arg2_h->neg && arg2_k->neg)
4077 {
4078 arg2_h->neg = FALSE;
4079 arg2_k->neg = FALSE;
4080 }
4081 else if (!(arg2_h->neg) && arg2_k->neg)
4082 {
4083 arg2_h->neg = TRUE;
4084 arg2_k->neg = FALSE;
4085 }
4086
4087 /* Calculate the common denominator.
4088 */
4089 siUnrestrictedMultiplication(&arg1_k, &arg2_k, &common_denominator);
4090
4091 /* Calculate the arg1 numerator.
4092 */
4093 siUnrestrictedMultiplication(&arg1_h, &arg2_k, &arg1_numerator);
4094
4095 /* Calculate the arg2 numerator.
4096 */
4097 siUnrestrictedMultiplication(&arg2_h, &arg1_k, &arg2_numerator);
4098
4099 /* Add the numerators to get the additive result. */
4100 siUnrestrictedAddition(&arg1_numerator,
4101 &arg2_numerator,
4102 &cumulative_numerator);
4103
4104 /* If we NAN'd out ...
4105 */
4106 if (cumulative_numerator->nan)
4107 goto nan_return;
4108
4109 /* If we've reached a result of zero, it won't be legal to form
4110 ** a gcd(). Assign the canonical form of zero.
4111 */
4112 if (!(cumulative_numerator->len))
4113 {
4114 siSetToLong(h_result, 0);
4115 siSetToLong(k_result, 1);
4116 goto normal_return;
4117 }
4118
4119 /* Snatch the sign temporarily.
4120 */
4121 if (cumulative_numerator->neg)
4122 {
4123 is_neg = TRUE;
4124 cumulative_numerator->neg = FALSE;
4125 }
4126
4127 /* Form the gcd. */
4128 siGcd(&cumulative_numerator,
4129 &common_denominator,
4130 &result_gcd);
4131
4132 /* Set the sign back. */
4133 cumulative_numerator->neg = is_neg;
4134
4135 /* Divide both numerator and denominator by
4136 ** the gcd().
4137 */
4138 siUnrestrictedDivision(&cumulative_numerator,
4139 &result_gcd,
4140 h_result,
4141 &trash_remainder);
4142 siUnrestrictedDivision(&common_denominator,
4143 &result_gcd,
4144 k_result,
4145 &trash_remainder);
4146
4147 goto normal_return;
4148 nan_return: ;
4149 siSetToNan(h_result);
4150 siSetToNan(k_result);
4151 normal_return: ;
4152
4153 /* Destroy temporary variables.
4154 */
4155 siDestroy(&arg1_h);
4156 siDestroy(&arg1_k);
4157 siDestroy(&arg2_h);
4158 siDestroy(&arg2_k);
4159 siDestroy(&common_denominator);
4160 siDestroy(&arg1_numerator);
4161 siDestroy(&arg2_numerator);
4162 siDestroy(&cumulative_numerator);
4163 siDestroy(&result_gcd);
4164 siDestroy(&trash_remainder);
4165 }
4166
4167
4168 /****************************************************************************/
4169 /* rnDifference(): */
4170 /*--------------------------------------------------------------------------*/
4171 /* DESCRIPTION */
4172 /* Calculates the difference of two rational numbers, returning the */
4173 /* results in lowest terms. */
4174 /* */
4175 /* INPUTS */
4176 /* **h1_formal_par_in, */
4177 /* **k1_formal_par_in, */
4178 /* **h2_formal_par_in, */
4179 /* **k2_formal_par_in : The numerators and denominators of the two */
4180 /* rational numbers to subtract. Zero denominators */
4181 /* are not allowed, but duplicate pointers of all */
4182 /* types are. */
4183 /* **h_result, */
4184 /* **k_result : The result, in lowest terms. Zero is repre- */
4185 /* sented canonically as 0/1. The memory must be */
4186 /* allocated in the caller's area, and the two */
4187 /* data items must be distinct. */
4188 /****************************************************************************/
4189 void rnDifference(SYNTHETIC_INTEGER **h1_formal_par_in,
4190 SYNTHETIC_INTEGER **k1_formal_par_in,
4191 SYNTHETIC_INTEGER **h2_formal_par_in,
4192 SYNTHETIC_INTEGER **k2_formal_par_in,
4193 SYNTHETIC_INTEGER **h_result,
4194 SYNTHETIC_INTEGER **k_result)
4195 {
4196 SYNTHETIC_INTEGER *arg1_h,
4197 *arg1_k,
4198 *arg2_h,
4199 *arg2_k,
4200 *common_denominator,
4201 *arg1_numerator,
4202 *arg2_numerator,
4203 *cumulative_numerator,
4204 *result_gcd,
4205 *trash_remainder;
4206
4207 unsigned is_neg = FALSE;
4208
4209 /* Be sure the caller isn't doing anything silly with pointers.
4210 */
4211 asAssert(h1_formal_par_in != NULL, __LINE__);
4212 asAssert(*h1_formal_par_in != NULL, __LINE__);
4213 asAssert(k1_formal_par_in != NULL, __LINE__);
4214 asAssert(*k1_formal_par_in != NULL, __LINE__);
4215 asAssert(h2_formal_par_in != NULL, __LINE__);
4216 asAssert(*h2_formal_par_in != NULL, __LINE__);
4217 asAssert(k2_formal_par_in != NULL, __LINE__);
4218 asAssert(*k2_formal_par_in != NULL, __LINE__);
4219 asAssert(h_result != NULL, __LINE__);
4220 asAssert(*h_result != NULL, __LINE__);
4221 asAssert(k_result != NULL, __LINE__);
4222 asAssert(*k_result != NULL, __LINE__);
4223 asAssert(h_result != k_result, __LINE__);
4224 asAssert(*h_result != *k_result, __LINE__);
4225
4226 /* Allocate space for temporary variables.
4227 */
4228 siCreate(&arg1_h);
4229 siCreate(&arg1_k);
4230 siCreate(&arg2_h);
4231 siCreate(&arg2_k);
4232 siCreate(&common_denominator);
4233 siCreate(&arg1_numerator);
4234 siCreate(&arg2_numerator);
4235 siCreate(&cumulative_numerator);
4236 siCreate(&result_gcd);
4237 siCreate(&trash_remainder);
4238
4239 /* Copy over the formal parameters to local variables. This
4240 ** means we can modify the inputs without worry.
4241 */
4242 siCopy(h1_formal_par_in, &arg1_h);
4243 siCopy(k1_formal_par_in, &arg1_k);
4244 siCopy(h2_formal_par_in, &arg2_h);
4245 siCopy(k2_formal_par_in, &arg2_k);
4246
4247 /* If any of the four inputs are NAN, the results must be
4248 ** NAN.
4249 */
4250 if (arg1_h->nan || arg1_k->nan || arg2_h->nan || arg2_k->nan)
4251 {
4252 goto nan_return;
4253 }
4254
4255 /* If either denominator is zero, the result is NAN.
4256 */
4257 if (!(arg1_k->len) || !(arg2_k->len))
4258 {
4259 goto nan_return;
4260 }
4261
4262 /* Adjust the signs of the the arguments so that the denominators are
4263 ** always positive.
4264 */
4265 if (arg1_h->neg && arg1_k->neg)
4266 {
4267 arg1_h->neg = FALSE;
4268 arg1_k->neg = FALSE;
4269 }
4270 else if (!(arg1_h->neg) && arg1_k->neg)
4271 {
4272 arg1_h->neg = TRUE;
4273 arg1_k->neg = FALSE;
4274 }
4275
4276 if (arg2_h->neg && arg2_k->neg)
4277 {
4278 arg2_h->neg = FALSE;
4279 arg2_k->neg = FALSE;
4280 }
4281 else if (!(arg2_h->neg) && arg2_k->neg)
4282 {
4283 arg2_h->neg = TRUE;
4284 arg2_k->neg = FALSE;
4285 }
4286
4287 /* Calculate the common denominator.
4288 */
4289 siUnrestrictedMultiplication(&arg1_k, &arg2_k, &common_denominator);
4290
4291 /* Calculate the arg1 numerator.
4292 */
4293 siUnrestrictedMultiplication(&arg1_h, &arg2_k, &arg1_numerator);
4294
4295 /* Calculate the arg2 numerator.
4296 */
4297 siUnrestrictedMultiplication(&arg2_h, &arg1_k, &arg2_numerator);
4298
4299 /* Subtract the numerators to get the result. */
4300 siUnrestrictedSubtraction(&arg1_numerator,
4301 &arg2_numerator,
4302 &cumulative_numerator);
4303
4304 /* If we NAN'd out ...
4305 */
4306 if (cumulative_numerator->nan)
4307 goto nan_return;
4308
4309 /* If we've reached a result of zero, it won't be legal to form
4310 ** a gcd(). Assign the canonical form of zero.
4311 */
4312 if (!(cumulative_numerator->len))
4313 {
4314 siSetToLong(h_result, 0);
4315 siSetToLong(k_result, 1);
4316 goto normal_return;
4317 }
4318
4319 /* Snatch the sign temporarily.
4320 */
4321 if (cumulative_numerator->neg)
4322 {
4323 is_neg = TRUE;
4324 cumulative_numerator->neg = FALSE;
4325 }
4326
4327 /* Form the gcd. */
4328 siGcd(&cumulative_numerator,
4329 &common_denominator,
4330 &result_gcd);
4331
4332 /* Set the sign back. */
4333 cumulative_numerator->neg = is_neg;
4334
4335 /* Divide both numerator and denominator by
4336 ** the gcd().
4337 */
4338 siUnrestrictedDivision(&cumulative_numerator,
4339 &result_gcd,
4340 h_result,
4341 &trash_remainder);
4342 siUnrestrictedDivision(&common_denominator,
4343 &result_gcd,
4344 k_result,
4345 &trash_remainder);
4346
4347 goto normal_return;
4348 nan_return: ;
4349 siSetToNan(h_result);
4350 siSetToNan(k_result);
4351 normal_return: ;
4352
4353 /* Destroy temporary variables.
4354 */
4355 siDestroy(&arg1_h);
4356 siDestroy(&arg1_k);
4357 siDestroy(&arg2_h);
4358 siDestroy(&arg2_k);
4359 siDestroy(&common_denominator);
4360 siDestroy(&arg1_numerator);
4361 siDestroy(&arg2_numerator);
4362 siDestroy(&cumulative_numerator);
4363 siDestroy(&result_gcd);
4364 siDestroy(&trash_remainder);
4365 }
4366
4367
4368 /****************************************************************************/
4369 /* rnProduct(): */
4370 /*--------------------------------------------------------------------------*/
4371 /* DESCRIPTION */
4372 /* Calculates the product of two rational numbers, returning the */
4373 /* results in lowest terms. */
4374 /* */
4375 /* INPUTS */
4376 /* **h1_formal_par_in, */
4377 /* **k1_formal_par_in, */
4378 /* **h2_formal_par_in, */
4379 /* **k2_formal_par_in : The numerators and denominators of the two */
4380 /* rational numbers to multiply. Zero denominators */
4381 /* are not allowed, but duplicate pointers of all */
4382 /* types are. */
4383 /* **h_result, */
4384 /* **k_result : The result, in lowest terms. Zero is repre- */
4385 /* sented canonically as 0/1. The memory must be */
4386 /* allocated in the caller's area, and the two */
4387 /* data items must be distinct. */
4388 /****************************************************************************/
4389 void rnProduct(SYNTHETIC_INTEGER **h1_formal_par_in,
4390 SYNTHETIC_INTEGER **k1_formal_par_in,
4391 SYNTHETIC_INTEGER **h2_formal_par_in,
4392 SYNTHETIC_INTEGER **k2_formal_par_in,
4393 SYNTHETIC_INTEGER **h_result,
4394 SYNTHETIC_INTEGER **k_result)
4395 {
4396 SYNTHETIC_INTEGER *arg1_h,
4397 *arg1_k,
4398 *arg2_h,
4399 *arg2_k,
4400 *result_numerator,
4401 *result_denominator,
4402 *gcd,
4403 *trash_remainder;
4404
4405 unsigned is_neg = FALSE;
4406
4407 /* Be sure the caller isn't doing anything silly with pointers.
4408 */
4409 asAssert(h1_formal_par_in != NULL, __LINE__);
4410 asAssert(*h1_formal_par_in != NULL, __LINE__);
4411 asAssert(k1_formal_par_in != NULL, __LINE__);
4412 asAssert(*k1_formal_par_in != NULL, __LINE__);
4413 asAssert(h2_formal_par_in != NULL, __LINE__);
4414 asAssert(*h2_formal_par_in != NULL, __LINE__);
4415 asAssert(k2_formal_par_in != NULL, __LINE__);
4416 asAssert(*k2_formal_par_in != NULL, __LINE__);
4417 asAssert(h_result != NULL, __LINE__);
4418 asAssert(*h_result != NULL, __LINE__);
4419 asAssert(k_result != NULL, __LINE__);
4420 asAssert(*k_result != NULL, __LINE__);
4421 asAssert(h_result != k_result, __LINE__);
4422 asAssert(*h_result != *k_result, __LINE__);
4423
4424 /* Allocate space for temporary variables.
4425 */
4426 siCreate(&arg1_h);
4427 siCreate(&arg1_k);
4428 siCreate(&arg2_h);
4429 siCreate(&arg2_k);
4430 siCreate(&result_numerator);
4431 siCreate(&result_denominator);
4432 siCreate(&gcd);
4433 siCreate(&trash_remainder);
4434
4435 /* Copy over the formal parameters to local variables. This
4436 ** means we can modify the inputs without worry.
4437 */
4438 siCopy(h1_formal_par_in, &arg1_h);
4439 siCopy(k1_formal_par_in, &arg1_k);
4440 siCopy(h2_formal_par_in, &arg2_h);
4441 siCopy(k2_formal_par_in, &arg2_k);
4442
4443 /* If any of the four inputs are NAN, the results must be
4444 ** NAN.
4445 */
4446 if (arg1_h->nan || arg1_k->nan || arg2_h->nan || arg2_k->nan)
4447 {
4448 goto nan_return;
4449 }
4450
4451 /* If either denominator is zero, the result is NAN.
4452 */
4453 if (!(arg1_k->len) || !(arg2_k->len))
4454 {
4455 goto nan_return;
4456 }
4457
4458 /* Carry out the multiplication of numerators and denominators to get
4459 ** the two products.
4460 */
4461 siUnrestrictedMultiplication(&arg1_h, &arg2_h, &result_numerator);
4462 siUnrestrictedMultiplication(&arg1_k, &arg2_k, &result_denominator);
4463
4464 /* If either result is NAN, the results are NAN.
4465 */
4466 if (result_numerator->nan || result_denominator->nan)
4467 {
4468 goto nan_return;
4469 }
4470
4471 /* If the numerator is zero, we must return canonical zero.
4472 */
4473 if (!(result_numerator->len))
4474 {
4475 siSetToLong(h_result, 0);
4476 siSetToLong(k_result, 1);
4477 goto normal_return;
4478 }
4479
4480 /* We need to acquire the sign and make both results positive otherwise
4481 ** can't obtain the GCD.
4482 */
4483 if (result_numerator->neg)
4484 {
4485 is_neg = TRUE;
4486 result_numerator->neg = FALSE;
4487 }
4488 if (result_denominator->neg)
4489 {
4490 is_neg = !is_neg;
4491 result_denominator->neg = FALSE;
4492 }
4493
4494 /* Form the gcd. */
4495 siGcd(&result_numerator,
4496 &result_denominator,
4497 &gcd);
4498
4499 /* Set the sign back. */
4500 result_numerator->neg = is_neg;
4501
4502 /* Divide both numerator and denominator by
4503 ** the gcd().
4504 */
4505 siUnrestrictedDivision(&result_numerator,
4506 &gcd,
4507 h_result,
4508 &trash_remainder);
4509 siUnrestrictedDivision(&result_denominator,
4510 &gcd,
4511 k_result,
4512 &trash_remainder);
4513
4514 goto normal_return;
4515 nan_return: ;
4516 siSetToNan(h_result);
4517 siSetToNan(k_result);
4518 normal_return: ;
4519
4520 /* Destroy temporary variables.
4521 */
4522 siDestroy(&arg1_h);
4523 siDestroy(&arg1_k);
4524 siDestroy(&arg2_h);
4525 siDestroy(&arg2_k);
4526 siDestroy(&result_numerator);
4527 siDestroy(&result_denominator);
4528 siDestroy(&gcd);
4529 siDestroy(&trash_remainder);
4530 }
4531
4532
4533 /****************************************************************************/
4534 /* rnQuotient(): */
4535 /*--------------------------------------------------------------------------*/
4536 /* DESCRIPTION */
4537 /* Calculates the quotient of two rational numbers, returning the */
4538 /* results in lowest terms. */
4539 /* */
4540 /* INPUTS */
4541 /* **h1_formal_par_in, */
4542 /* **k1_formal_par_in, */
4543 /* **h2_formal_par_in, */
4544 /* **k2_formal_par_in : The numerators and denominators of the two */
4545 /* rational numbers to divide. Zero denominators */
4546 /* and zero divisors are not allowed, but duplicate */
4547 /* pointers of all types are. */
4548 /* **h_result, */
4549 /* **k_result : The result, in lowest terms. Zero is repre- */
4550 /* sented canonically as 0/1. The memory must be */
4551 /* allocated in the caller's area, and the two */
4552 /* data items must be distinct. */
4553 /****************************************************************************/
4554 void rnQuotient(SYNTHETIC_INTEGER **h1_formal_par_in,
4555 SYNTHETIC_INTEGER **k1_formal_par_in,
4556 SYNTHETIC_INTEGER **h2_formal_par_in,
4557 SYNTHETIC_INTEGER **k2_formal_par_in,
4558 SYNTHETIC_INTEGER **h_result,
4559 SYNTHETIC_INTEGER **k_result)
4560 {
4561 SYNTHETIC_INTEGER *arg1_h,
4562 *arg1_k,
4563 *arg2_h,
4564 *arg2_k,
4565 *result_numerator,
4566 *result_denominator,
4567 *gcd,
4568 *trash_remainder;
4569
4570 unsigned is_neg = FALSE;
4571
4572 /* Be sure the caller isn't doing anything silly with pointers.
4573 */
4574 asAssert(h1_formal_par_in != NULL, __LINE__);
4575 asAssert(*h1_formal_par_in != NULL, __LINE__);
4576 asAssert(k1_formal_par_in != NULL, __LINE__);
4577 asAssert(*k1_formal_par_in != NULL, __LINE__);
4578 asAssert(h2_formal_par_in != NULL, __LINE__);
4579 asAssert(*h2_formal_par_in != NULL, __LINE__);
4580 asAssert(k2_formal_par_in != NULL, __LINE__);
4581 asAssert(*k2_formal_par_in != NULL, __LINE__);
4582 asAssert(h_result != NULL, __LINE__);
4583 asAssert(*h_result != NULL, __LINE__);
4584 asAssert(k_result != NULL, __LINE__);
4585 asAssert(*k_result != NULL, __LINE__);
4586 asAssert(h_result != k_result, __LINE__);
4587 asAssert(*h_result != *k_result, __LINE__);
4588
4589 /* Allocate space for temporary variables.
4590 */
4591 siCreate(&arg1_h);
4592 siCreate(&arg1_k);
4593 siCreate(&arg2_h);
4594 siCreate(&arg2_k);
4595 siCreate(&result_numerator);
4596 siCreate(&result_denominator);
4597 siCreate(&gcd);
4598 siCreate(&trash_remainder);
4599
4600 /* Copy over the formal parameters to local variables. This
4601 ** means we can modify the inputs without worry.
4602 */
4603 siCopy(h1_formal_par_in, &arg1_h);
4604 siCopy(k1_formal_par_in, &arg1_k);
4605 siCopy(h2_formal_par_in, &arg2_h);
4606 siCopy(k2_formal_par_in, &arg2_k);
4607
4608 /* If any of the four inputs are NAN, the results must be
4609 ** NAN.
4610 */
4611 if (arg1_h->nan || arg1_k->nan || arg2_h->nan || arg2_k->nan)
4612 {
4613 goto nan_return;
4614 }
4615
4616 /* If either denominator is zero, the result is NAN.
4617 */
4618 if (!(arg1_k->len) || !(arg2_k->len))
4619 {
4620 goto nan_return;
4621 }
4622
4623 /* Carry out the multiplication of numerators and denominators to get
4624 ** the two products.
4625 */
4626 siUnrestrictedMultiplication(&arg1_h, &arg2_k, &result_numerator);
4627 siUnrestrictedMultiplication(&arg1_k, &arg2_h, &result_denominator);
4628
4629 /* If either result is NAN, the results are NAN.
4630 */
4631 if (result_numerator->nan || result_denominator->nan)
4632 {
4633 goto nan_return;
4634 }
4635
4636 /* If the denominator of the result is zero, this is a no-no-NAN, too.
4637 */
4638 if (!(result_denominator->len))
4639 {
4640 goto nan_return;
4641 }
4642
4643 /* If the numerator is zero, we must return canonical zero.
4644 */
4645 if (!(result_numerator->len))
4646 {
4647 siSetToLong(h_result, 0);
4648 siSetToLong(k_result, 1);
4649 goto normal_return;
4650 }
4651
4652 /* We need to acquire the sign and make both results positive otherwise
4653 ** can't obtain the GCD.
4654 */
4655 if (result_numerator->neg)
4656 {
4657 is_neg = TRUE;
4658 result_numerator->neg = FALSE;
4659 }
4660 if (result_denominator->neg)
4661 {
4662 is_neg = !is_neg;
4663 result_denominator->neg = FALSE;
4664 }
4665
4666 /* Form the gcd. */
4667 siGcd(&result_numerator,
4668 &result_denominator,
4669 &gcd);
4670
4671 /* Set the sign back. */
4672 result_numerator->neg = is_neg;
4673
4674 /* Divide both numerator and denominator by
4675 ** the gcd().
4676 */
4677 siUnrestrictedDivision(&result_numerator,
4678 &gcd,
4679 h_result,
4680 &trash_remainder);
4681 siUnrestrictedDivision(&result_denominator,
4682 &gcd,
4683 k_result,
4684 &trash_remainder);
4685
4686 goto normal_return;
4687 nan_return: ;
4688 siSetToNan(h_result);
4689 siSetToNan(k_result);
4690 normal_return: ;
4691
4692 /* Destroy temporary variables.
4693 */
4694 siDestroy(&arg1_h);
4695 siDestroy(&arg1_k);
4696 siDestroy(&arg2_h);
4697 siDestroy(&arg2_k);
4698 siDestroy(&result_numerator);
4699 siDestroy(&result_denominator);
4700 siDestroy(&gcd);
4701 siDestroy(&trash_remainder);
4702 }
4703
4704
4705 /****************************************************************************/
4706 /* rnCanonize(): */
4707 /*--------------------------------------------------------------------------*/
4708 /* DESCRIPTION */
4709 /* Puts the rational number passed into a canonical form, which means: */
4710 /* a)If either synthetic integer is NAN, both are marked NAN. */
4711 /* b)If the denominator is zero, both synthetic integers are marked */
4712 /* NAN. */
4713 /* c)If the number has a value of zero, it is set to the canonical */
4714 /* form of 0/1. */
4715 /* d)If the number represents a positive value, the signs of both */
4716 /* synthetic integers are set +. If the number represents a */
4717 /* negative value, the numerator will be set - and the denominator */
4718 /* -. */
4719 /* e)Any g.c.d. will be removed so that the number is in lowest */
4720 /* terms. */
4721 /* */
4722 /* INPUTS (AND OUTPUTS) */
4723 /* **h_formal_par_in, */
4724 /* **k_formal_par_in : The numerator and denominator of the number to */
4725 /* operate on. */
4726 /****************************************************************************/
4727 void rnCanonize(SYNTHETIC_INTEGER **h_formal_par_in,
4728 SYNTHETIC_INTEGER **k_formal_par_in)
4729 {
4730 int is_neg = FALSE;
4731 SYNTHETIC_INTEGER *gcd, *trash_remainder, *si_temp;
4732
4733 /* Be sure the caller isn't doing anything silly with pointers.
4734 */
4735 asAssert(h_formal_par_in != NULL, __LINE__);
4736 asAssert(*h_formal_par_in != NULL, __LINE__);
4737 asAssert(k_formal_par_in != NULL, __LINE__);
4738 asAssert(*k_formal_par_in != NULL, __LINE__);
4739 asAssert(h_formal_par_in != k_formal_par_in, __LINE__);
4740 asAssert(*h_formal_par_in != *k_formal_par_in, __LINE__);
4741
4742 /* Create the local integers.
4743 */
4744 siCreate(&gcd);
4745 siCreate(&trash_remainder);
4746 siCreate(&si_temp);
4747
4748 /* If either input is NAN, must mark both NAN.
4749 */
4750 if ((*h_formal_par_in)->nan || (*k_formal_par_in)->nan)
4751 goto nan_return;
4752
4753 /* If the denominator is zero, must also mark both NAN.
4754 */
4755 if (!((*k_formal_par_in)->len))
4756 goto nan_return;
4757
4758 /* If the numerator is zero, the right answer is canonical zero, and
4759 ** must return canonical 0/1.
4760 */
4761 if (!((*h_formal_par_in)->len))
4762 goto zero_return;
4763
4764 /* If we made it to this point, we have two non-zero integers, and the
4765 ** result will be non-zero. Must canonize the sign and factor out
4766 ** any g.c.d.
4767 */
4768 if ((((*h_formal_par_in)->neg) && !((*k_formal_par_in)->neg))
4769 ||
4770 (!((*h_formal_par_in)->neg) && ((*k_formal_par_in)->neg)))
4771 {
4772 is_neg = TRUE;
4773 }
4774
4775 (*h_formal_par_in)->neg = FALSE;
4776 (*k_formal_par_in)->neg = FALSE;
4777
4778 siGcd(h_formal_par_in, k_formal_par_in, &gcd);
4779
4780 siUnrestrictedDivision(h_formal_par_in, &gcd,
4781 &si_temp, &trash_remainder);
4782 siCopy(&si_temp, h_formal_par_in);
4783 siUnrestrictedDivision(k_formal_par_in, &gcd,
4784 &si_temp, &trash_remainder);
4785 siCopy(&si_temp, k_formal_par_in);
4786
4787 if (is_neg)
4788 (*h_formal_par_in)->neg = TRUE;
4789
4790 goto normal_return;
4791 nan_return: ;
4792 siSetToNan(h_formal_par_in);
4793 siSetToNan(k_formal_par_in);
4794 goto normal_return;
4795 zero_return:
4796 siSetToLong(h_formal_par_in, 0);
4797 siSetToLong(k_formal_par_in, 1);
4798 goto normal_return;
4799 normal_return: ;
4800
4801 /* Destroy the local integers.
4802 */
4803 siDestroy(&gcd);
4804 siDestroy(&trash_remainder);
4805 siDestroy(&si_temp);
4806 }
4807
4808
4809 /****************************************************************************/
4810 /* rnCompare(): */
4811 /*--------------------------------------------------------------------------*/
4812 /* DESCRIPTION */
4813 /* Compares two rational numbers to determine thier ranking on the number */
4814 /* line. */
4815 /* */
4816 /* INPUTS . */
4817 /* **h_1, **k_1, */
4818 /* **h_2, **k_2 : The two rational numbers to compare. They are not */
4819 /* required to be in canonical form, but the */
4820 /* denominators may not be zero. */
4821 /* */
4822 /* OUTPUT */
4823 /* <-- : -1 if h1/k1 < h2/k2 */
4824 /* 0 if h1/k1 = h2/k2 */
4825 /* 1 if h1/k1 > h2/k2 */
4826 /****************************************************************************/
4827 int rnCompare(SYNTHETIC_INTEGER **h_1,
4828 SYNTHETIC_INTEGER **k_1,
4829 SYNTHETIC_INTEGER **h_2,
4830 SYNTHETIC_INTEGER **k_2)
4831 {
4832 int rv=0;
4833
4834 SYNTHETIC_INTEGER *h1,
4835 *k1,
4836 *h2,
4837 *k2,
4838 *left_cross_product,
4839 *right_cross_product;
4840
4841 /* Be sure the caller isn't doing anything silly with pointers.
4842 */
4843 asAssert(h_1 != NULL, __LINE__);
4844 asAssert(*h_1 != NULL, __LINE__);
4845 asAssert(k_1 != NULL, __LINE__);
4846 asAssert(*k_1 != NULL, __LINE__);
4847 asAssert(h_2 != NULL, __LINE__);
4848 asAssert(*h_2 != NULL, __LINE__);
4849 asAssert(k_2 != NULL, __LINE__);
4850 asAssert(*k_2 != NULL, __LINE__);
4851
4852 /* Allocate all of our temps.
4853 */
4854 siCreate(&h1);
4855 siCreate(&k1);
4856 siCreate(&h2);
4857 siCreate(&k2);
4858 siCreate(&left_cross_product);
4859 siCreate(&right_cross_product);
4860
4861 /* Copy the formal parameters to the temps so we can mess
4862 ** around with them.
4863 */
4864 siCopy(h_1, &h1);
4865 siCopy(k_1, &k1);
4866 siCopy(h_2, &h2);
4867 siCopy(k_2, &k2);
4868
4869 /* The denominators may not be zero.
4870 */
4871 asAssert((k1->len != 0) && (k2->len != 0) ,__LINE__);
4872
4873 /* We need to normalize the signs on the two fractions.
4874 ** The cross-product inequality utilized breaks down
4875 ** if either denominator is negative.
4876 */
4877 if ((!(h1->neg) && (k1->neg)) || ((h1->neg) && !(k1->neg)))
4878 {
4879 h1->neg = TRUE;
4880 k1->neg = FALSE;
4881 }
4882 else
4883 {
4884 h1->neg = FALSE;
4885 k1->neg = FALSE;
4886 }
4887
4888 if ((!(h2->neg) && (k2->neg)) || ((h2->neg) && !(k2->neg)))
4889 {
4890 h2->neg = TRUE;
4891 k2->neg = FALSE;
4892 }
4893 else
4894 {
4895 h2->neg = FALSE;
4896 k2->neg = FALSE;
4897 }
4898
4899 /* Form the left cross-product and right cross-product. If we get
4900 ** a NAN, we have to kill this function, as it would compromise
4901 ** the integrity of the program (there is no notion of NAN for a
4902 ** comparison result).
4903 */
4904 siUnrestrictedMultiplication(&h1, &k2, &left_cross_product);
4905 siUnrestrictedMultiplication(&h2, &k1, &right_cross_product);
4906 asAssert(!(left_cross_product->nan) && !(right_cross_product->nan), __LINE__);
4907
4908 /* The comparison result is the same as the relationship between the
4909 ** two cross-products. A few words should be said about this.
4910 **
4911 ** Let a/b and c/d be the two rational numbers.
4912 ** Assume that b>0 and d>0.
4913 ** ad < bc
4914 ** -> ad/b < c
4915 ** ->a/b < c/d.
4916 ** and the same logic can be applied to the other relational
4917 ** operators.
4918 */
4919 rv = siCompare(&left_cross_product, &right_cross_product);
4920
4921 #if 0
4922 siDump(&left_cross_product, "left");
4923 siDump(&right_cross_product, "right");
4924 #endif
4925
4926 /* Destroy all of our temps.
4927 */
4928 siDestroy(&h1);
4929 siDestroy(&k1);
4930 siDestroy(&h2);
4931 siDestroy(&k2);
4932 siDestroy(&left_cross_product);
4933 siDestroy(&right_cross_product);
4934
4935 /* Return the return value.
4936 */
4937 return(rv);
4938 }
4939
4940
4941 /****************************************************************************/
4942 /* rnDap(): */
4943 /*--------------------------------------------------------------------------*/
4944 /* DESCRIPTION */
4945 /* Converts a rational number to an approximately equivalent value */
4946 /* with a different denominator. This functionality is the same as */
4947 /* implemented by the DAP command. */
4948 /* */
4949 /* INPUTS . */
4950 /* **h, **k : The rational number to represent differently. */
4951 /* The denominator may not be zero. */
4952 /* */
4953 /* **D : The new denominator. May not be zero. */
4954 /* */
4955 /* OUTPUTS */
4956 /* **N : The new numerator. */
4957 /****************************************************************************/
4958 void rnDap(SYNTHETIC_INTEGER **h,
4959 SYNTHETIC_INTEGER **k,
4960 SYNTHETIC_INTEGER **N,
4961 SYNTHETIC_INTEGER **D)
4962 {
4963 SYNTHETIC_INTEGER *numerator_product,
4964 *quotient,
4965 *trash_remainder;
4966
4967 /* Be sure the caller is doing nothing silly with pointers.
4968 */
4969 asAssert(h != NULL, __LINE__);
4970 asAssert(*h != NULL, __LINE__);
4971 asAssert(k != NULL, __LINE__);
4972 asAssert(*k != NULL, __LINE__);
4973 asAssert(N != NULL, __LINE__);
4974 asAssert(*N != NULL, __LINE__);
4975 asAssert(D != NULL, __LINE__);
4976 asAssert(*D != NULL, __LINE__);
4977
4978 /* Allocate our locals.
4979 */
4980 siCreate(&numerator_product);
4981 siCreate(&quotient);
4982 siCreate(&trash_remainder);
4983
4984 /* If anything is NAN, the result is necessarily NAN.
4985 */
4986 if ((*h)->nan || (*k)->nan || (*D)->nan)
4987 goto nan_return;
4988
4989 /* If the old denominator is zero, the result is necessarily NAN.
4990 */
4991 if (!((*k)->len))
4992 goto nan_return;
4993
4994 /* If the new denominator requested is zero, the result is necessarily NAN.
4995 */
4996 if (!((*D)->len))
4997 goto nan_return;
4998
4999 /* Calculate the numerator as specified in the manual under the DAP
5000 ** command.
5001 */
5002 siUnrestrictedMultiplication(h, D, &numerator_product);
5003
5004 /* Divide to get the value.
5005 */
5006 siUnrestrictedDivision(&numerator_product, k, &quotient, &trash_remainder);
5007
5008 /* Copy to caller's area.
5009 */
5010 siCopy(&quotient, N);
5011
5012 goto normal_return;
5013 nan_return:
5014 siSetToNan(N);
5015 normal_return: ;
5016
5017 /* Destroy our locals.
5018 */
5019 siDestroy(&numerator_product);
5020 siDestroy(&quotient);
5021 siDestroy(&trash_remainder);
5022 }
5023
5024
5025 /****************************************************************************/
5026 /* rnFareyTraverse(): */
5027 /*--------------------------------------------------------------------------*/
5028 /* DESCRIPTION */
5029 /* Uses the standard recursive formulas to traverse the Farey series */
5030 /* in either direction. Two successive terms, in lowest terms, are */
5031 /* needed. */
5032 /* */
5033 /* INPUTS . */
5034 /* **h1in, **k1in: The first rational number in the series of interest, */
5035 /* which must have a positive denominator and a non- */
5036 /* negative numerator. */
5037 /* */
5038 /* **h2in, **k2in: The second rational number in the series of interest, */
5039 /* same rules as above and must be greater than first */
5040 /* term h1in/k1in. */
5041 /* */
5042 /* **N : The order of the series to form. */
5043 /* */
5044 /* dir : (-1): The series is advanced backwards. r(2)=r(1), */
5045 /* and r(1) = new term < r(2). */
5046 /* (+1): The series is advanced forwards. r(1)=r(2), */
5047 /* and r(2) = new term > r(1). */
5048 /****************************************************************************/
5049 void rnFareyTraverse(SYNTHETIC_INTEGER **h1in,
5050 SYNTHETIC_INTEGER **k1in,
5051 SYNTHETIC_INTEGER **h2in,
5052 SYNTHETIC_INTEGER **k2in,
5053 SYNTHETIC_INTEGER **N,
5054 int dir)
5055 {
5056 SYNTHETIC_INTEGER *t1, *t2, *t3, *new_h, *new_k;
5057
5058 /* Be sure the caller isn't doing anything silly with pointers.
5059 */
5060 asAssert(h1in != NULL, __LINE__);
5061 asAssert(*h1in != NULL, __LINE__);
5062 asAssert(k1in != NULL, __LINE__);
5063 asAssert(*k1in != NULL, __LINE__);
5064 asAssert(h2in != NULL, __LINE__);
5065 asAssert(*h2in != NULL, __LINE__);
5066 asAssert(k2in != NULL, __LINE__);
5067 asAssert(*k2in != NULL, __LINE__);
5068 asAssert(N != NULL, __LINE__);
5069 asAssert(*N != NULL, __LINE__);
5070
5071 /* It is also critical that none of the pointers be duplicates,
5072 ** but this isn't checked.
5073 */
5074
5075 /* Allocate local variables.
5076 */
5077 siCreate(&t1);
5078 siCreate(&t2);
5079 siCreate(&t3);
5080 siCreate(&new_h);
5081 siCreate(&new_k);
5082
5083 /* Split into cases based on the direction.
5084 */
5085 if (dir > 0)
5086 {
5087 /* Forward
5088 */
5089 /* Calculate the term floor((k[j-2] + N)/k[j-1]), which we'll need
5090 ** twice. The result is left in "t2".
5091 */
5092 siUnrestrictedAddition(k1in, N, &t1);
5093 siUnrestrictedDivision(&t1, k2in, &t2, &t3);
5094
5095 /* Multiply by h[j-1] and place in "t1".
5096 */
5097 siUnrestrictedMultiplication(&t2, h2in, &t1);
5098
5099 /* Subtract off h[j-2] and this is our new h.
5100 */
5101 siUnrestrictedSubtraction(&t1, h1in, &new_h);
5102
5103 /* Multiply intermediate term by k[j-1] and place in "t1".
5104 */
5105 siUnrestrictedMultiplication(&t2, k2in, &t1);
5106
5107 /* Subtract off k[j-2] and this is our new k.
5108 */
5109 siUnrestrictedSubtraction(&t1, k1in, &new_k);
5110
5111 /* Place the new results.
5112 */
5113 siCopy(h2in, h1in);
5114 siCopy(k2in, k1in);
5115 siCopy(&new_h, h2in);
5116 siCopy(&new_k, k2in);
5117 }
5118 else
5119 {
5120 /* Reverse: steps symmetrical with forward.
5121 */
5122 siUnrestrictedAddition(k2in, N, &t1);
5123 siUnrestrictedDivision(&t1, k1in, &t2, &t3);
5124 siUnrestrictedMultiplication(&t2, h1in, &t1);
5125 siUnrestrictedSubtraction(&t1, h2in, &new_h);
5126 siUnrestrictedMultiplication(&t2, k1in, &t1);
5127 siUnrestrictedSubtraction(&t1, k2in, &new_k);
5128
5129 /* Place the new results.
5130 */
5131 siCopy(h1in, h2in);
5132 siCopy(k1in, k2in);
5133 siCopy(&new_h, h1in);
5134 siCopy(&new_k, k1in);
5135 }
5136
5137
5138 /* Destroy local variables.
5139 */
5140 siDestroy(&t1);
5141 siDestroy(&t2);
5142 siDestroy(&t3);
5143 siDestroy(&new_h);
5144 siDestroy(&new_k);
5145 }
5146
5147
5148 /****************************************************************************/
5149 /****************************************************************************/
5150 /******* C O N T I N U E D F R A C T I O N F U N C T I O N S ******/
5151 /****************************************************************************/
5152 /****************************************************************************/
5153 /* This section is reserved for functions which form and manipulate
5154 ** continued fractions and convergents. Note that every number has at
5155 ** least a 0th order CF partial quotient and at least a 0th order
5156 ** convergent (the integer part).
5157 */
5158 typedef struct
5159 {
5160 SYNTHETIC_INTEGER *raw_numerator;
5161 SYNTHETIC_INTEGER *raw_denominator;
5162 /* The raw numerator and denominator passed to the function which
5163 ** calculates partial quotients and convergents. This might
5164 ** not be in lowest terms. No negative integers are allowed,
5165 ** and zero must be represented canonically as 0/(D>0).
5166 */
5167 SYNTHETIC_INTEGER *numerator;
5168 SYNTHETIC_INTEGER *denominator;
5169 /* The numerator and denominator, in lowest terms, of the
5170 ** rational number whose continued fraction expansion we
5171 ** are forming. No negative integers are allowed, and
5172 ** zero must be represented canonically as 0/1.
5173 */
5174 int n;
5175 /* The number of elements in the parallel arrays of partial
5176 ** quotients, etc., which are maintained. This must be
5177 ** at least 1, which would mean that only the 0th-order
5178 ** items are filled in.
5179 */
5180 SYNTHETIC_INTEGER **a;
5181 /* Pointer to a dynamically allocated array of n pointers,
5182 ** each of which points to a synthetic integer. This
5183 ** pointer may be shifted on any operation on this data
5184 ** structure (due to the behavior of "realloc()"), so
5185 ** a caller should never retain internal pointers when
5186 ** making function calls which might resize anything
5187 ** internally in this data structure. The same sizing arguments
5188 ** here apply to all the other parallel elements, so it won't
5189 ** be described again.
5190 */
5191 SYNTHETIC_INTEGER **p;
5192 SYNTHETIC_INTEGER **q;
5193 /* Convergents of continued fraction expansion of the
5194 ** rational number.
5195 */
5196 } CF_EXPANSION;
5197
5198
5199 /****************************************************************************/
5200 /* pqCreate(): */
5201 /*--------------------------------------------------------------------------*/
5202 /* DESCRIPTION */
5203 /* Creates the continued fraction partial quotient expansion of a non- */
5204 /* negative rational number, and also creates the convergents. */
5205 /* */
5206 /* INPUTS */
5207 /* **h_in */
5208 /* **k_in : The numerator and denominator of the rational */
5209 /* number whose continued fraction expansion and */
5210 /* convergents to form. Both must be positive. */
5211 /* */
5212 /* **expansion : The continued fraction expansion and the */
5213 /* convergents. */
5214 /****************************************************************************/
5215 void pqCreate(SYNTHETIC_INTEGER **h_in,
5216 SYNTHETIC_INTEGER **k_in,
5217 CF_EXPANSION **expansion)
5218 {
5219 SYNTHETIC_INTEGER *dividend,
5220 *divisor,
5221 *quotient,
5222 *remainder,
5223 *p_k_minus_1,
5224 *p_k_minus_2,
5225 *q_k_minus_1,
5226 *q_k_minus_2,
5227 *si_temp1,
5228 *si_temp2,
5229 *si_temp3,
5230 *si_temp4;
5231
5232 /* Be sure that the caller isn't doing anything silly.
5233 */
5234 asAssert(h_in != NULL, __LINE__);
5235 asAssert(*h_in != NULL, __LINE__);
5236 asAssert(k_in != NULL, __LINE__);
5237 asAssert(*k_in != NULL, __LINE__);
5238 asAssert(expansion != NULL, __LINE__);
5239
5240 /* The numerator and denominator in cannot be negative,
5241 ** and the denominator cannot be zero.
5242 */
5243 asAssert(!((*h_in)->neg), __LINE__);
5244 asAssert(!((*k_in)->neg), __LINE__);
5245 asAssert((*k_in)->len != 0, __LINE__);
5246
5247 /* Allocate space for all of the temporary integers
5248 ** we use during the process of forming partial
5249 ** quotients and convergents.
5250 */
5251 siCreate(&dividend);
5252 siCreate(&divisor);
5253 siCreate(&quotient);
5254 siCreate(&remainder);
5255 siCreate(&p_k_minus_1);
5256 siCreate(&p_k_minus_2);
5257 siCreate(&q_k_minus_1);
5258 siCreate(&q_k_minus_2);
5259 siCreate(&si_temp1);
5260 siCreate(&si_temp2);
5261 siCreate(&si_temp3);
5262 siCreate(&si_temp4);
5263
5264 /* printf("Entering function.\n"); */
5265
5266 /* Allocate the memory for the head data block.
5267 */
5268 *expansion = maMalloc(sizeof(CF_EXPANSION));
5269
5270 /* Set all of the data elements of the head data block
5271 ** to known default values.
5272 */
5273 (*expansion)->raw_numerator = NULL;
5274 (*expansion)->raw_denominator = NULL;
5275 (*expansion)->numerator = NULL;
5276 (*expansion)->denominator = NULL;
5277 (*expansion)->n = 0;
5278 (*expansion)->a = NULL;
5279 (*expansion)->p = NULL;
5280 (*expansion)->q = NULL;
5281
5282 /* Assign in the original raw numerator and
5283 ** denominator.
5284 */
5285 siCreate(&((*expansion)->raw_numerator));
5286 siCreate(&((*expansion)->raw_denominator));
5287 siCopy(h_in, &((*expansion)->raw_numerator));
5288 siCopy(k_in, &((*expansion)->raw_denominator));
5289
5290 /* Allocate the space for the lowest-terms numerator
5291 ** and denominator, but let them be zero for now.
5292 */
5293 siCreate(&((*expansion)->numerator));
5294 siCreate(&((*expansion)->denominator));
5295
5296 /* Begin with the dividend and divisor as the
5297 ** numerator and denominator.
5298 */
5299 siCopy(&((*expansion)->raw_numerator), &dividend);
5300 siCopy(&((*expansion)->raw_denominator), &divisor);
5301
5302 /* Enter a do ... while() loop to compute the continued
5303 ** fraction partial quotients and convergents. Because
5304 ** the convergents don't require any "look-ahead" into
5305 ** the partial quotients, they can be computed
5306 ** in parallel
5307 */
5308
5309 do
5310 {
5311 int curidx;
5312 /* Current index.
5313 */
5314
5315 /* Buffer the current index value to the local variable (less
5316 ** typing). The current index is what we're currently
5317 ** operating on.
5318 */
5319 curidx = (*expansion)->n;
5320
5321 /* Increment the number of elements in the
5322 ** three parallel arrays.
5323 */
5324 ((*expansion)->n)++;
5325
5326 /* Allocate the memory for the memory block in the
5327 ** four parallel arrays. There are two cases to
5328 ** consider, either this is the first element or
5329 ** else not the first.
5330 */
5331 if (!((*expansion)->a))
5332 {
5333 /* First time, first element.
5334 */
5335 (*expansion)->a =
5336 maMalloc(sizeof(SYNTHETIC_INTEGER *));
5337 (*expansion)->p =
5338 maMalloc(sizeof(SYNTHETIC_INTEGER *));
5339 (*expansion)->q =
5340 maMalloc(sizeof(SYNTHETIC_INTEGER *));
5341 }
5342 else
5343 {
5344 /* Not the first time. Blow up the arrays of
5345 ** pointers to a larger size to accomodate one more
5346 ** pointer.
5347 */
5348 (*expansion)->a =
5349 maRealloc((*expansion)->a,
5350 (sizeof(SYNTHETIC_INTEGER *)) * (curidx+1));
5351 (*expansion)->p =
5352 maRealloc((*expansion)->p,
5353 (sizeof(SYNTHETIC_INTEGER *)) * (curidx+1));
5354 (*expansion)->q =
5355 maRealloc((*expansion)->q,
5356 (sizeof(SYNTHETIC_INTEGER *)) * (curidx+1));
5357 }
5358
5359 /* Allocate the synthetic integers to go along with
5360 ** blown-up arrays.
5361 */
5362 siCreate((*expansion)->a + curidx);
5363 siCreate((*expansion)->p + curidx);
5364 siCreate((*expansion)->q + curidx);
5365
5366 /* Calculate the current continued fraction partial quotient,
5367 ** and bump the dividend and divisor for the next round.
5368 */
5369 siUnrestrictedDivision(&dividend,
5370 &divisor,
5371 (*expansion)->a + curidx,
5372 &remainder);
5373 /* siDump((*expansion)->a + curidx, "a_k"); */
5374 siCopy(&divisor, &dividend);
5375 siCopy(&remainder, &divisor);
5376
5377 /* Calculate the convergents using the standard
5378 ** recursive formulas.
5379 */
5380 if (curidx == 0)
5381 {
5382 /* p(0) = a(0) */
5383 siCopy((*expansion)->a + 0, (*expansion)->p + 0);
5384 /* q(0) = 1 */
5385 siSetToLong((*expansion)->q + 0, 1);
5386 }
5387 else if (curidx == 1)
5388 {
5389 /* p(1) = a(1)p(0) + 1 */
5390 siSetToLong(&si_temp1, 1);
5391 siUnrestrictedMultiplication((*expansion)->a + 1,
5392 (*expansion)->p + 0,
5393 &si_temp2);
5394 siUnrestrictedAddition(&si_temp2,
5395 &si_temp1,
5396 (*expansion)->p + 1);
5397 /* q(1) = a(1) */
5398 siCopy((*expansion)->a + 1, (*expansion)->q + 1);
5399 }
5400 else /* curidx >= 2 */
5401 {
5402 /* In this case, apply the full recursive formulas. */
5403 /* p(k) = a(k)p(k-1) + p(k-2) */
5404 siUnrestrictedMultiplication((*expansion)->a + curidx,
5405 (*expansion)->p + (curidx-1),
5406 &si_temp2);
5407 siUnrestrictedAddition(&si_temp2,
5408 (*expansion)->p + (curidx-2),
5409 (*expansion)->p + curidx);
5410
5411 /* q(k) = a(k)q(k-1) + q(k-2) */
5412 siUnrestrictedMultiplication((*expansion)->a + curidx,
5413 (*expansion)->q + (curidx-1),
5414 &si_temp2);
5415 siUnrestrictedAddition(&si_temp2,
5416 (*expansion)->q + (curidx-2),
5417 (*expansion)->q + curidx);
5418 }
5419
5420 /* siDump((*expansion)->p + curidx, "p_k"); */
5421 /* siDump((*expansion)->q + curidx, "q_k"); */
5422
5423 /* Put in a safety test for the loop. I've never had this loop fail to
5424 ** terminate. Mathematically, it *can't* fail to terminate, but if there
5425 ** were a bug somewhere in the large integer math or a NAN condition,
5426 ** I wouldn't want to have a machine lockup without a diagnostic message.
5427 ** The value of 32000 is used because that approaches the limits of the
5428 ** minimum that an ANSI 'C' int is required to hold. If we've gone
5429 ** around this loop 32000 times, something is very wrong.
5430 */
5431 asAssert(curidx < 32000, __LINE__);
5432 }
5433 while (remainder->len);
5434
5435 /* The lowest terms representation of the rational number supplied will
5436 ** be the final convergent. This doesn't apply very much to this program,
5437 ** because the parsing functions automatically strip out the gcd() before
5438 ** passing data on, so the "raw" and "final" will be the same. Will assign
5439 ** it anyway.
5440 */
5441 siCopy((*expansion)->p + ((*expansion)->n - 1), &((*expansion)->numerator));
5442 siCopy((*expansion)->q + ((*expansion)->n - 1), &((*expansion)->denominator));
5443
5444 /* Destroy the temporary integers.
5445 */
5446 siDestroy(&dividend);
5447 siDestroy(&divisor);
5448 siDestroy(&quotient);
5449 siDestroy(&remainder);
5450 siDestroy(&p_k_minus_1);
5451 siDestroy(&p_k_minus_2);
5452 siDestroy(&q_k_minus_1);
5453 siDestroy(&q_k_minus_2);
5454 siDestroy(&si_temp1);
5455 siDestroy(&si_temp2);
5456 siDestroy(&si_temp3);
5457 siDestroy(&si_temp4);
5458 }
5459
5460
5461 /****************************************************************************/
5462 /* pqDestroy(): */
5463 /*--------------------------------------------------------------------------*/
5464 /* DESCRIPTION */
5465 /* Deallocates the dynamic data structures associated with the CF */
5466 /* expansion and convergents, and sets the caller's pointer to NULL. */
5467 /* */
5468 /* **expansion : The continued fraction expansion and the */
5469 /* convergents. */
5470 /****************************************************************************/
5471 void pqDestroy(CF_EXPANSION **expansion)
5472 {
5473 int idx;
5474
5475 /* Be sure the caller isn't doing anything silly. with pointers.
5476 */
5477 asAssert(expansion != NULL, __LINE__);
5478 asAssert(*expansion != NULL, __LINE__);
5479
5480 /* The general strategy at this point is to deallocate the data structure
5481 ** from the bottom up. It must be done this way because once a higher
5482 ** data structure is deallocated, the memory ain't yours, so any access
5483 ** even to deallocate "lower" pointers is a violation. Checks all along
5484 ** the way are performed to be sure that nothing looks suspicious.
5485 */
5486
5487 asAssert((*expansion)->n > 0, __LINE__); /* Even a 0th order expansion (an integer)
5488 ** has the "n" at 1.
5489 */
5490 /* Check for suspicious conditions in the base data
5491 ** structure.
5492 */
5493 asAssert((*expansion)->raw_numerator != NULL, __LINE__);
5494 asAssert((*expansion)->raw_denominator != NULL, __LINE__);
5495 asAssert((*expansion)->numerator != NULL, __LINE__);
5496 asAssert((*expansion)->denominator != NULL, __LINE__);
5497 asAssert((*expansion)->a != NULL, __LINE__);
5498 asAssert((*expansion)->p != NULL, __LINE__);
5499 asAssert((*expansion)->q != NULL, __LINE__);
5500
5501
5502 /* Deallocate the directly linked synthetic integers.
5503 */
5504 siDestroy(&((*expansion)->raw_numerator));
5505 siDestroy(&((*expansion)->raw_denominator));
5506 siDestroy(&((*expansion)->numerator));
5507 siDestroy(&((*expansion)->denominator));
5508
5509 /* Deallocate each of the synthetic integers that are the partial
5510 ** quotients and convergents.
5511 */
5512 for (idx = 0; idx < ((*expansion)->n); idx++)
5513 {
5514 asAssert((((*expansion)->a)[idx]) != NULL, __LINE__);
5515 asAssert((((*expansion)->p)[idx]) != NULL, __LINE__);
5516 asAssert((((*expansion)->q)[idx]) != NULL, __LINE__);
5517
5518 siDestroy((*expansion)->a + idx);
5519 siDestroy((*expansion)->p + idx);
5520 siDestroy((*expansion)->q + idx);
5521 }
5522
5523 /* Deallocate the arrays of pointers.
5524 */
5525 maFree((*expansion)->a);
5526 maFree((*expansion)->p);
5527 maFree((*expansion)->q);
5528
5529 /* Deallocate the base data structure and set the caller's pointer
5530 ** to NULL.
5531 */
5532 maFree(*expansion);
5533 *expansion = NULL;
5534 }
5535
5536
5537 /****************************************************************************/
5538 /* pqDump(): */
5539 /*--------------------------------------------------------------------------*/
5540 /* DESCRIPTION */
5541 /* Prints the entire CF expansion and list of convergents to the standard */
5542 /* output stream, with an optional description. */
5543 /* */
5544 /* **expansion : The continued fraction expansion and the */
5545 /* convergents. */
5546 /* *desc : Description to use. If this is a zero-length */
5547 /* string, omits the description. */
5548 /* p_raw : Boolean flag to indicate if the raw numerator and */
5549 /* denominator should be printed distinctly from the */
5550 /* final CF convergent. For most of the application */
5551 /* in this program, the answer is no, because the */
5552 /* rational number is already reduced at the time it */
5553 /* is CF'd, and the raw rational number will be */
5554 /* identical to the final convergent. To print it */
5555 /* would just waste space. */
5556 /****************************************************************************/
5557 void pqDump(CF_EXPANSION **expansion, char *desc, int p_raw)
5558 {
5559 int i;
5560 char buf[100];
5561
5562 /* Be sure the caller isn't doing any pointer suicide.
5563 */
5564 asAssert(expansion != NULL, __LINE__);
5565 asAssert(*expansion != NULL, __LINE__);
5566 asAssert(desc != NULL, __LINE__);
5567
5568 /* If a description was passed print it out as a banner headline.
5569 */
5570 if (strlen(desc))
5571 {
5572 gfBannerHeading(desc, 0);
5573 }
5574
5575 /* Banner announcing inputs. */
5576 gfBannerHeading("Inputs To CF Calculation", 0);
5577 gfHline();
5578
5579 /* Print out the raw numerator and denominator. */
5580 siDump(&((*expansion)->raw_numerator), "h_in");
5581 gfHline();
5582 siDump(&((*expansion)->raw_denominator), "k_in");
5583 gfHline();
5584
5585 /* Print out each of the continued-fraction partial
5586 ** quotients.
5587 */
5588 /* Banner announcing partial quotients. */
5589 gfBannerHeading("CF Partial Quotients", 0);
5590 gfHline();
5591
5592 for (i=0; i<((*expansion)->n); i++)
5593 {
5594 sprintf(buf, "a(%d)", i);
5595 siDump((*expansion)->a + i, buf);
5596 gfHline();
5597 }
5598
5599 /* Priint out the convergents. */
5600 /* Banner announcing partial convergents. */
5601 gfBannerHeading("CF Convergents", 0);
5602 gfHline();
5603
5604 for (i=0; i<((*expansion)->n); i++)
5605 {
5606 sprintf(buf, "p(%d)", i);
5607 siDump((*expansion)->p + i, buf);
5608 sprintf(buf, "q(%d)", i);
5609 siDump((*expansion)->q + i, buf);
5610 gfHline();
5611 }
5612 }
5613
5614
5615 /****************************************************************************/
5616 /* pqBapp(): */
5617 /*--------------------------------------------------------------------------*/
5618 /* DESCRIPTION */
5619 /* Extracts the two best rational approximations to a rational number */
5620 /* in the Farey series of order N, using a CF decomposition that must */
5621 /* have already been done on the rational number. */
5622 /* */
5623 /* The function behaves subtly differently depending on whether the */
5624 /* rational number passed is in the Farey series of order N. If the */
5625 /* number is not in F_N, the two Farey neighbors are returned, in an */
5626 /* order that depends on whether the rational number has an odd or */
5627 /* an even number of partial quotients. If the number is in F_N, the */
5628 /* number itself (in lowest terms) is returned, along with the left or */
5629 /* right Farey neighbor, with which again depending on whether the number */
5630 /* has an odd or even number of partial quotients. */
5631 /* */
5632 /* This function is typically used to get two consecutive Farey terms */
5633 /* so that the recursive formulas can be applied. */
5634 /* */
5635 /* INPUTS */
5636 /* **expansion : The CF expansion that must have already been done on */
5637 /* the [non-negative] number. */
5638 /* **N : The [positive] order of the Farey series being */
5639 /* considered. */
5640 /* */
5641 /* OUTPUTS */
5642 /* **conv_h, */
5643 /* **conv_k : The highest-order convergent with a denominator not */
5644 /* larger than N. */
5645 /* **neigh_h, */
5646 /* **neigh_k : The intermediate fraction as specified by the */
5647 /* equation in the TOMS paper. This will be a Farey */
5648 /* neighbor to the rational number of interest. */
5649 /* *convergent_number */
5650 /* The index of the convergent that was the highest-order */
5651 /* convergent with a denominator not larger than N. */
5652 /****************************************************************************/
5653 void pqBapp(CF_EXPANSION **expansion,
5654 SYNTHETIC_INTEGER **N,
5655 SYNTHETIC_INTEGER **conv_h,
5656 SYNTHETIC_INTEGER **conv_k,
5657 SYNTHETIC_INTEGER **neigh_h,
5658 SYNTHETIC_INTEGER **neigh_k,
5659 int *convergent_number)
5660 {
5661 SYNTHETIC_INTEGER *constant_1,
5662 *t1,
5663 *t2,
5664 *t3;
5665
5666 /* Make sure the caller isn't doing anything silly with pointers.
5667 ** Catastropies are checked, but not duplicate pointers, etc.
5668 */
5669 asAssert(expansion != NULL, __LINE__);
5670 asAssert(*expansion != NULL, __LINE__);
5671 asAssert(N != NULL, __LINE__);
5672 asAssert(*N != NULL, __LINE__);
5673 asAssert(conv_h != NULL, __LINE__);
5674 asAssert(*conv_h != NULL, __LINE__);
5675 asAssert(conv_k != NULL, __LINE__);
5676 asAssert(*conv_k != NULL, __LINE__);
5677 asAssert(neigh_h != NULL, __LINE__);
5678 asAssert(*neigh_h != NULL, __LINE__);
5679 asAssert(neigh_k != NULL, __LINE__);
5680 asAssert(*neigh_k != NULL, __LINE__);
5681 asAssert(convergent_number != NULL, __LINE__);
5682
5683 /* Allocate all temporary variables.
5684 */
5685 siCreate(&constant_1);
5686 siSetToLong(&constant_1, 1);
5687 siCreate(&t1);
5688 siCreate(&t2);
5689 siCreate(&t3);
5690
5691 /* Branch based on the order of the decomposition.
5692 */
5693 if ((*expansion)->n == 1)
5694 {
5695 /* If we have a 0th order expansion, this means that
5696 ** it is an integer. We can't process this using the standard
5697 ** recursive equations because we don't have a p(-1) or a
5698 ** q(-1). However, it can be shown easily that the right
5699 ** value here is always (N * p(0) + 1)/N.
5700 */
5701 siCopy((*expansion)->p + 0, conv_h);
5702 siCopy((*expansion)->q + 0, conv_k);
5703 siUnrestrictedMultiplication(N, (*expansion)->p + 0, &t1);
5704 siUnrestrictedAddition(&constant_1, &t1, neigh_h);
5705 siCopy(N, neigh_k);
5706 *convergent_number = 0;
5707 }
5708 else
5709 {
5710 /* If we have a first-order or greater decomposition, we
5711 ** can apply the standard recursive formulas.
5712 */
5713 int i = 0;
5714
5715 /* We need to locate the convergent with the largest denominator
5716 ** not larger than N.
5717 */
5718 if (siCompare((*expansion)->q + ((*expansion)->n - 1), N) <= 0)
5719 {
5720 /* The final convergent is equal to N or less than N. We must
5721 ** choose the final convergent.
5722 */
5723 *convergent_number = i = (*expansion)->n - 1;
5724 }
5725 else
5726 {
5727 /* Iterate through until we find that the next convergent is too
5728 ** big.
5729 */
5730 while (siCompare((*expansion)->q + (i + 1), N) <= 0)
5731 {
5732 i++;
5733
5734 /* Do a sanity check here. If "i" has grown to where the
5735 ** next convergent to examine isn't valid, something is
5736 ** very wrong.
5737 */
5738 asAssert((i+1) < ((*expansion)->n), __LINE__);
5739 }
5740 }
5741
5742 /* Assign this convergent, advise the caller of which one.
5743 */
5744 siCopy((*expansion)->p + i, conv_h);
5745 siCopy((*expansion)->q + i, conv_k);
5746 *convergent_number = i;
5747
5748 /* We now know the convergent that is the last not greater
5749 ** than the order N. Can apply the standard recursive formulas.
5750 ** Must split into two cases because if the right convergent
5751 ** to use is the zero'th one, we can't apply the recursive
5752 ** formulas.
5753 */
5754 if (i==0)
5755 {
5756 siUnrestrictedMultiplication(N, (*expansion)->p + 0, &t1);
5757 siUnrestrictedAddition(&constant_1, &t1, neigh_h);
5758 siCopy(N, neigh_k);
5759 }
5760 else
5761 {
5762 /* First, calculate the quantity floor((N-q[k-1])/q[k]), as
5763 ** we'll use this more than once. Leave this in "t1".
5764 */
5765 siUnrestrictedSubtraction(N, (*expansion)->q + (i-1), &t2);
5766 siUnrestrictedDivision(&t2, (*expansion)->q + i, &t1, &t3);
5767
5768 /* Calculate the numerator of the neighbor.
5769 */
5770 siUnrestrictedMultiplication(&t1, (*expansion)->p + i, &t2);
5771 siUnrestrictedAddition(&t2, (*expansion)->p + (i-1), neigh_h);
5772
5773 /* Calculate the denominator of the neighbor.
5774 */
5775 siUnrestrictedMultiplication(&t1, (*expansion)->q + i, &t2);
5776 siUnrestrictedAddition(&t2, (*expansion)->q + (i-1), neigh_k);
5777 }
5778 }
5779
5780 /* Destroy all temporary variables.
5781 */
5782 siDestroy(&constant_1);
5783 siDestroy(&t1);
5784 siDestroy(&t2);
5785 siDestroy(&t3);
5786 }
5787
5788
5789 /****************************************************************************/
5790 /****************************************************************************/
5791 /****** N U M E R I C A L A L G O R I T H M F U N C T I O N S *****/
5792 /****************************************************************************/
5793 /****************************************************************************/
5794 /* This section is reserved for functions which apply specific numerical
5795 ** algorithms (GCD, for example).
5796 */
5797 /****************************************************************************/
5798 /* naMind(): */
5799 /*--------------------------------------------------------------------------*/
5800 /* DESCRIPTION */
5801 /* Locates the rational number with the smallest denominator in an */
5802 /* interval, using the continued fraction algorithm presented in the */
5803 /* paper. */
5804 /****************************************************************************/
5805 void naMind(SYNTHETIC_INTEGER **h1par,
5806 SYNTHETIC_INTEGER **k1par,
5807 SYNTHETIC_INTEGER **h2par,
5808 SYNTHETIC_INTEGER **k2par,
5809 SYNTHETIC_INTEGER **result_h,
5810 SYNTHETIC_INTEGER **result_k,
5811 int emit_midpoint,
5812 int emit_cfdata,
5813 int emit_result)
5814 {
5815 SYNTHETIC_INTEGER *h1, *k1, *h2, *k2, *midpoint_h, *midpoint_k,
5816 *t1, *t2, *t3, *t4, *t5, *t6,
5817 *t7, *t8, *t9, *t10, *t11, *t12,
5818 *constant_1, *constant_0, *p_minus_1, *q_minus_1;
5819 CF_EXPANSION *midpoint_expansion;
5820 int k;
5821 int done;
5822
5823 /* Be sure there is no pointer nonsense.
5824 */
5825 asAssert(h1par != NULL, __LINE__);
5826 asAssert(*h1par != NULL, __LINE__);
5827 asAssert(k1par != NULL, __LINE__);
5828 asAssert(*k1par != NULL, __LINE__);
5829 asAssert(h2par != NULL, __LINE__);
5830 asAssert(*h2par != NULL, __LINE__);
5831 asAssert(k2par != NULL, __LINE__);
5832 asAssert(*k2par != NULL, __LINE__);
5833 asAssert(result_h != NULL, __LINE__);
5834 asAssert(*result_h != NULL, __LINE__);
5835 asAssert(result_k != NULL, __LINE__);
5836 asAssert(*result_k != NULL, __LINE__);
5837
5838 /* Allocate locals
5839 */
5840 siCreate(&h1);
5841 siCreate(&k1);
5842 siCreate(&h2);
5843 siCreate(&k2);
5844 siCreate(&midpoint_h);
5845 siCreate(&midpoint_k);
5846 siCreate(&t1);
5847 siCreate(&t2);
5848 siCreate(&t3);
5849 siCreate(&t4);
5850 siCreate(&t5);
5851 siCreate(&t6);
5852 siCreate(&t7);
5853 siCreate(&t8);
5854 siCreate(&t9);
5855 siCreate(&t10);
5856 siCreate(&t11);
5857 siCreate(&t12);
5858 siCreate(&constant_1);
5859 siSetToLong(&constant_1, 1);
5860 siCreate(&constant_0);
5861 siSetToLong(&constant_0, 0);
5862 siCreate(&p_minus_1);
5863 siCreate(&q_minus_1);
5864
5865 /* Copy the input parameters to our locals.
5866 */
5867 siCopy(h1par, &h1);
5868 siCopy(k1par, &k1);
5869 siCopy(h2par, &h2);
5870 siCopy(k2par, &k2);
5871
5872 /* Swap the input parameters if the input parameters
5873 ** are in the wrong order.
5874 */
5875 if (rnCompare(&h1, &k1, &h2, &k2) == 1)
5876 {
5877 SYNTHETIC_INTEGER *temp;
5878
5879 temp = h1;
5880 h1 = h2;
5881 h2 = temp;
5882
5883 temp = k2;
5884 k1 = k2;
5885 k2 = temp;
5886 }
5887
5888 /* Calculate the midpoint of the interval. This
5889 ** is (l+r)/2.
5890 */
5891 rnSum(&h1, &k1, &h2, &k2, &midpoint_h, &midpoint_k);
5892
5893 {
5894 SYNTHETIC_INTEGER *constant_2, *tempresult;
5895
5896 siCreate(&constant_2);
5897 siCreate(&tempresult);
5898
5899 siSetToLong(&constant_2, 2);
5900
5901 siUnrestrictedMultiplication(&midpoint_k, &constant_2, &tempresult);
5902
5903 siCopy(&tempresult, &midpoint_k);
5904
5905 rnCanonize(&midpoint_h, &midpoint_k);
5906
5907 siDestroy(&constant_2);
5908 siDestroy(&tempresult);
5909 }
5910
5911 /* If the midpoint should be printed for informative
5912 ** purposes, print it.
5913 */
5914 if (emit_midpoint)
5915 {
5916 siDump(&midpoint_h, "midpoint_h");
5917 gfHline();
5918 siDump(&midpoint_k, "midpoint_k");
5919 gfHline();
5920 }
5921
5922 /* Form the partial quotients and convergents of the
5923 ** midpoint.
5924 */
5925 pqCreate(&midpoint_h,
5926 &midpoint_k,
5927 &midpoint_expansion);
5928
5929 /* Print out the partial quotients and convergents, if the
5930 ** caller has requested it.
5931 */
5932 if (emit_cfdata)
5933 {
5934 pqDump(&midpoint_expansion, "CF Representation Of Interval Midpoint", FALSE);
5935 }
5936
5937 /* At this point, can apply the algorithm listed in the paper.
5938 */
5939 done = FALSE;
5940 for (k=0; k<midpoint_expansion->n && !done; k++)
5941 /* For each convergent, in order of increasing k.
5942 */
5943 {
5944 /* printf("k is : %d\n", k); */
5945
5946 /* Calculate the p and q one back. Must do this
5947 ** explicitly and can't index into array, because
5948 ** case of [0] not covered.
5949 */
5950 if (k==0)
5951 {
5952 siSetToLong(&p_minus_1, 1);
5953 siSetToLong(&q_minus_1, 0);
5954 }
5955 else
5956 {
5957 siCopy(&(midpoint_expansion->p[k-1]), &p_minus_1);
5958 siCopy(&(midpoint_expansion->q[k-1]), &q_minus_1);
5959 }
5960
5961 /* Test convergent for membership in [l,r]. This means >= l and
5962 ** <= r. If we have membership, we're done.
5963 */
5964 if ((rnCompare(&h1, &k1, &(midpoint_expansion->p[k]), &(midpoint_expansion->q[k])) <= 0) &&
5965 (rnCompare(&h2, &k2, &(midpoint_expansion->p[k]), &(midpoint_expansion->q[k])) >= 0))
5966 {
5967 /* The convergent is in the interval. Assign result and signal done.
5968 */
5969 siCopy(&(midpoint_expansion->p[k]), result_h);
5970 siCopy(&(midpoint_expansion->q[k]), result_k);
5971 done = TRUE;
5972 }
5973 else
5974 {
5975 /* Must look at potential intermediate fractions.
5976 */
5977 if ((k & 0x1) == 0) /* i is even */
5978 {
5979 /* Calculate the value of "i" that will be the minimum
5980 ** required to potentially put the intermediate fraction
5981 ** in the interval [l,r]. This is in accordance with
5982 ** the paper.
5983 */
5984 siUnrestrictedMultiplication(&h2,
5985 &q_minus_1,
5986 &t1);
5987 siUnrestrictedMultiplication(&k2,
5988 &p_minus_1,
5989 &t2);
5990 siUnrestrictedSubtraction(&t1, &t2, &t3);
5991 siUnrestrictedMultiplication(&k2,
5992 &(midpoint_expansion->p[k]),
5993 &t4);
5994 siUnrestrictedMultiplication(&h2,
5995 &(midpoint_expansion->q[k]),
5996 &t5);
5997 siUnrestrictedSubtraction(&t4, &t5, &t6);
5998
5999 /* We have the numerator and denominator. We would like
6000 ** to form the ceiling of the quotient. Using integer math,
6001 ** the best way to do that is to add the denominator to the
6002 ** numerator minus one and use the integer quotient However, first
6003 ** would like to normalize numerator and denominator so
6004 ** both neg or both pos. It should never be possible to
6005 ** have different signs.
6006 */
6007 asAssert((t3->neg && t6->neg) || (!(t3->neg) && !(t6->neg)), __LINE__);
6008 if (t3->neg)
6009 {
6010 t3->neg = FALSE;
6011 t6->neg = FALSE;
6012 }
6013
6014 siUnrestrictedAddition(&t6, &t3, &t8);
6015 siUnrestrictedSubtraction(&t8, &constant_1, &t7);
6016
6017 /* Now get the quotient. This quotient should be the
6018 ** ceiling, because we added the numerator to the
6019 ** denominator minus one. "t8" should contain the "i" as
6020 ** specified in the paper.
6021 */
6022 siUnrestrictedDivision(&t7, &t6, &t8, &t9);
6023
6024 /* siDump(&t8, "i"); */
6025
6026 }
6027 else /* i is odd */
6028 {
6029 /* printf("Odd\n"); */
6030
6031 /* Calculate the value of "i" that will be the minimum
6032 ** required to potentially put the intermediate fraction
6033 ** in the interval [l,r]. This is in accordance with
6034 ** the paper.
6035 */
6036 siUnrestrictedMultiplication(&h1,
6037 &q_minus_1,
6038 &t1);
6039 siUnrestrictedMultiplication(&k1,
6040 &p_minus_1,
6041 &t2);
6042 siUnrestrictedSubtraction(&t1, &t2, &t3);
6043 siUnrestrictedMultiplication(&k1,
6044 &(midpoint_expansion->p[k]),
6045 &t4);
6046 siUnrestrictedMultiplication(&h1,
6047 &(midpoint_expansion->q[k]),
6048 &t5);
6049 siUnrestrictedSubtraction(&t4, &t5, &t6);
6050
6051 /* We have the numerator and denominator. We would like
6052 ** to form the ceiling of the quotient. Using integer math,
6053 ** the best way to do that is to add the denominator to the
6054 ** numerator minus one and use the integer quotient However, first
6055 ** would like to normalize numerator and denominator so
6056 ** both neg or both pos. It should never be possible to
6057 ** have different signs.
6058 */
6059 asAssert((t3->neg && t6->neg) || (!(t3->neg) && !(t6->neg)), __LINE__);
6060 if (t3->neg)
6061 {
6062 t3->neg = FALSE;
6063 t6->neg = FALSE;
6064 }
6065
6066 siUnrestrictedAddition(&t6, &t3, &t8);
6067 siUnrestrictedSubtraction(&t8, &constant_1, &t7);
6068
6069 /* Now get the quotient. This quotient should be the
6070 ** ceiling, because we added the numerator to the
6071 ** denominator minus one. "t8" should contain the "i" as
6072 ** specified in the paper.
6073 */
6074 siUnrestrictedDivision(&t7, &t6, &t8, &t9);
6075
6076 /* siDump(&t8, "i"); */
6077
6078 }
6079
6080 /* At this point, we have a potential coefficient on intermediate fractions.
6081 ** Must examine the result.
6082 */
6083 /* Disregard if >= partial quotient.
6084 */
6085 /* printf("k: %d\n", k); */
6086 /* siDump(&t8, "i"); */
6087 /* siDump(&(midpoint_expansion->a[k]), "ak"); */
6088
6089 /* Need to be extremely careful, because about to index one past k on the
6090 ** assumption that can't be at last place, or convergent would have matched.
6091 */
6092 asAssert((k+1) < midpoint_expansion->n, __LINE__);
6093
6094 if (siCompare(&(midpoint_expansion->a[k+1]), &t8) > 0)
6095 {
6096 /* Form the intermediate fraction involved. It is guaranteed
6097 ** to be irreducible.
6098 */
6099 siUnrestrictedMultiplication(&t8, &(midpoint_expansion->p[k]), &t1);
6100 siUnrestrictedAddition(&t1, &p_minus_1, &t2);
6101 siUnrestrictedMultiplication(&t8, &(midpoint_expansion->q[k]), &t3);
6102 siUnrestrictedAddition(&t3, &q_minus_1, &t4);
6103
6104 /* The fraction is t2/t4.
6105 */
6106 /* siDump(&t2, "potential_h"); */
6107 /* siDump(&t4, "potential_k"); */
6108
6109 /* Evaluate this for membership in [l,r]
6110 */
6111 if (rnCompare(&h1, &k1, &t2, &t4) <= 0) /* >= l */
6112 {
6113 if (rnCompare(&h2, &k2, &t2, &t4) >= 0) /* <= r */
6114 {
6115 siCopy(&t2, result_h);
6116 siCopy(&t4, result_k);
6117 done = TRUE;
6118 }
6119 }
6120 }
6121 } /* End if must look at intermediate fractions. */
6122 } /* End for() */
6123
6124 /* We should have our answer. Mathematically, if nothing else, the final
6125 ** convergent must be in the interval. Will just put this extra paranoid
6126 ** assertion in.
6127 */
6128 asAssert(done != 0, __LINE__);
6129
6130 /* Destroy the continued fraction expansion.
6131 */
6132 pqDestroy(&midpoint_expansion);
6133
6134 /* Copy the caller's inputs to our local variables.
6135 */
6136 siDestroy(&h1);
6137 siDestroy(&k1);
6138 siDestroy(&h2);
6139 siDestroy(&k2);
6140 siDestroy(&midpoint_h);
6141 siDestroy(&midpoint_k);
6142 siDestroy(&t1);
6143 siDestroy(&t2);
6144 siDestroy(&t3);
6145 siDestroy(&t4);
6146 siDestroy(&t5);
6147 siDestroy(&t6);
6148 siDestroy(&t7);
6149 siDestroy(&t8);
6150 siDestroy(&t9);
6151 siDestroy(&t10);
6152 siDestroy(&t11);
6153 siDestroy(&t12);
6154 siDestroy(&constant_1);
6155 siDestroy(&constant_0);
6156 siDestroy(&p_minus_1);
6157 siDestroy(&q_minus_1);
6158 }
6159
6160
6161 /****************************************************************************/
6162 /****************************************************************************/
6163 /****************** C O M M A N D F U N C T I O N S ******************/
6164 /****************************************************************************/
6165 /****************************************************************************/
6166 /* This section is reserved for functions which carry out the commands which
6167 ** are subfunctions of how the RAP program operates. Each of these commands
6168 ** is tabulated to be matched in a template for what it does and the types
6169 ** of operands it will accept.
6170 */
6171 /* The first thing to define is the different types of things that an
6172 ** individual input parameter can be. I don't want to use enum here
6173 ** because there are some potential compiler portability annoyances if somebody
6174 ** sicks a C++ compiler on this deck.
6175 */
6176 #define CMDLINE_PAR_TYPE_UNASSIGNED (0)
6177 /* Not filled in yet.
6178 */
6179 #define CMDLINE_PAR_TYPE_CMD_KEYTOKEN_PLUS (1)
6180 /* The "+" sign alone.
6181 */
6182 #define CMDLINE_PAR_TYPE_CMD_KEYTOKEN_MINUS (2)
6183 /* The "-" sign alone.
6184 */
6185 #define CMDLINE_PAR_TYPE_CMD_KEYTOKEN_TIMES (3)
6186 /* The "*" token alone.
6187 */
6188 #define CMDLINE_PAR_TYPE_CMD_KEYTOKEN_QUOTIENT (4)
6189 /* The "/" token alone.
6190 */
6191 #define CMDLINE_PAR_TYPE_CMD_KEYTOKEN_MODULO (5)
6192 /* The "%" token alone.
6193 */
6194 #define CMDLINE_PAR_TYPE_CMD_KEYTOKEN_POWER (6)
6195 /* The "**" token alone.
6196 */
6197 #define CMDLINE_PAR_TYPE_CMD_KEYTOKEN_GCD (7)
6198 /* The "GCD" token alone.
6199 */
6200 #define CMDLINE_PAR_TYPE_CMD_KEYTOKEN_DAP (8)
6201 /* The "DAP" token alone.
6202 */
6203 #define CMDLINE_PAR_TYPE_CMD_KEYTOKEN_MIND (9)
6204 /* The "MIND" token alone.
6205 */
6206 #define CMDLINE_PAR_TYPE_CMD_KEYTOKEN_CF (10)
6207 /* The "CF" token alone.
6208 */
6209 #define CMDLINE_PAR_TYPE_CMD_KEYTOKEN_FN (11)
6210 /* The "FN" token alone.
6211 */
6212 #define CMDLINE_PAR_TYPE_CMD_KEYTOKEN_FNDMAX (12)
6213 /* The "CF" token alone.
6214 */
6215 #define CMDLINE_PAR_TYPE_CMD_KEYTOKEN_FAB (13)
6216 /* The "FAB" token alone.
6217 */
6218 #define CMDLINE_PAR_TYPE_CMD_KEYTOKEN_FABDMAX (14)
6219 /* The "FABDMAX" token alone.
6220 */
6221 #define CMDLINE_PAR_TYPE_INTNEG (15)
6222 /* A negative integer.
6223 */
6224 #define CMDLINE_PAR_TYPE_INTZERO (16)
6225 /* The integer zero.
6226 */
6227 #define CMDLINE_PAR_TYPE_INTPOS (17)
6228 /* A positive integer.
6229 */
6230 #define CMDLINE_PAR_TYPE_RATNEG (18)
6231 /* A negative rational number.
6232 */
6233 #define CMDLINE_PAR_TYPE_RATZERO (19)
6234 /* A rational number whose value is zero.
6235 */
6236 #define CMDLINE_PAR_TYPE_RATPOS (20)
6237 /* A positive rational number.
6238 */
6239 #define CMDLINE_PAR_TYPE_UNKNOWN (21)
6240 /* Couldn't figure out what it was.
6241 */
6242
6243 /* The next thing to define is the data type which holds a command-line
6244 ** parameter (or parameters from a file, same thing).
6245 */
6246 typedef struct
6247 {
6248 int ftype;
6249 /* The fundamental type, using one of the enumerated constants
6250 ** above.
6251 */
6252 char *orig_string;
6253 /* The string value that was supplied on the command line, after
6254 ** everything was converted to upper case and token concatenation
6255 ** is done. This will be a dynamically allocated string.
6256 */
6257 SYNTHETIC_INTEGER *raw_numerator;
6258 SYNTHETIC_INTEGER *raw_denominator;
6259 /* Filled exactly as specified on the command line. If only an
6260 ** integer was specified, the denominator pointer is NULL. If
6261 ** the caller specified a rational number as a float, the original
6262 ** rational number formed by adding zeros to the numerator and
6263 ** making the denominator a power of ten is placed here.
6264 */
6265 SYNTHETIC_INTEGER *canonical_numerator;
6266 SYNTHETIC_INTEGER *canonical_denominator;
6267 /* The parsing takes steps to put any numerical argument into
6268 ** a canonical form. Here are the steps taken.
6269 **
6270 ** a)Any rational number with a zero denominator will terminate
6271 ** the program with an error message.
6272 **
6273 ** b)Integers are left unchanged (there is really nothing more
6274 ** canonical.
6275 **
6276 ** c)The GCD is always removed from the input argument, using
6277 ** Euclid's algorithm (directly or indirectly). If a rational
6278 ** number supplied is actually an integer (after GCD calculated),
6279 ** it is treated as such (NULL denominator pointer).
6280 **
6281 ** d)If the rational number is positive and was specified as
6282 ** the quotient of two negative integers, the "negs" are
6283 ** removed.
6284 **
6285 ** e)Any negative rational number will be expressed as a negative
6286 ** numerator and positive denominator.
6287 **
6288 ** f)Any rational number which has value 0 (such as 0/-1293981),
6289 ** will be stored canonically as 0/1.
6290 */
6291 } CMD_LINE_PAR;
6292
6293
6294 /* A single data structure which holds the complete set of command-line
6295 ** parameters. It is easier to do it this way rather than dynamically
6296 ** resized arrays, etc.
6297 */
6298 struct ipParBlockStruct
6299 {
6300 int n;
6301 /* The number of array elements filled in the array of
6302 ** command-line parameters.
6303 */
6304 CMD_LINE_PAR pars[MAX_CMDLINE_PARS];
6305 /* Space for the command-line parameters.
6306 */
6307 } par_block;
6308
6309
6310 /****************************************************************************/
6311 /* cfSimple2ParIntegerAddition(): */
6312 /*--------------------------------------------------------------------------*/
6313 /* DESCRIPTION */
6314 /* Handles addition of two arbitrary integers and displaying the result. */
6315 /* Called in response to a template match. */
6316 /****************************************************************************/
6317 void cfSimple2ParIntegerAddition(void)
6318 {
6319 SYNTHETIC_INTEGER *result;
6320
6321 siCreate(&result);
6322 siUnrestrictedAddition(&(par_block.pars[1].canonical_numerator),
6323 &(par_block.pars[2].canonical_numerator),
6324 &result);
6325 siDump(&(par_block.pars[1].canonical_numerator), "arg1");
6326 gfHline();
6327 siDump(&(par_block.pars[2].canonical_numerator), "arg2");
6328 gfHline();
6329 siDump(&result, "arg1 + arg2");
6330 gfHline();
6331 }
6332
6333
6334 /****************************************************************************/
6335 /* cfSimple2ParRationalRationalAddition(): */
6336 /*--------------------------------------------------------------------------*/
6337 /* DESCRIPTION */
6338 /* Handles addition of two arbitrary rational numbers. Called in */
6339 /* response to a template match. */
6340 /****************************************************************************/
6341 void cfSimple2ParRationalRationalAddition(void)
6342 {
6343 SYNTHETIC_INTEGER *arg1_h,
6344 *arg1_k,
6345 *arg2_h,
6346 *arg2_k,
6347 *constant_1,
6348 *result_numerator,
6349 *result_denominator;
6350
6351 siCreate(&arg1_h);
6352 siCreate(&arg1_k);
6353 siCreate(&arg2_h);
6354 siCreate(&arg2_k);
6355 siCreate(&constant_1);
6356 siSetToLong(&constant_1, 1);
6357 siCreate(&result_numerator);
6358 siCreate(&result_denominator);
6359
6360 /* Since this function handles the general case where either
6361 ** or both arguments are rational, we need to watch out and
6362 ** condition any integer argument to be rational. We need
6363 ** to watch out for a missing denominator and assign it to
6364 ** be "1" if it is missing (meaning that the original argument
6365 ** was an integer.
6366 */
6367 /* Copy over to our scratch space, watching out for integers.
6368 */
6369 siCopy(&(par_block.pars[1].canonical_numerator), &arg1_h);
6370 if (par_block.pars[1].canonical_denominator)
6371 siCopy(&(par_block.pars[1].canonical_denominator), &arg1_k);
6372 else
6373 siSetToLong(&arg1_k, 1);
6374
6375 siCopy(&(par_block.pars[2].canonical_numerator), &arg2_h);
6376 if (par_block.pars[2].canonical_denominator)
6377 siCopy(&(par_block.pars[2].canonical_denominator), &arg2_k);
6378 else
6379 siSetToLong(&arg2_k, 1);
6380
6381 /* Make the call to the rational number addition function.
6382 */
6383 rnSum(&arg1_h, &arg1_k, &arg2_h, &arg2_k, &result_numerator, &result_denominator);
6384
6385 /* Print out the first argument. We display it differently
6386 ** depending on if it was rational or integral.
6387 */
6388 if (par_block.pars[1].canonical_denominator)
6389 {
6390 siDump(&(par_block.pars[1].canonical_numerator), "arg1_h");
6391 gfHline();
6392 siDump(&(par_block.pars[1].canonical_denominator), "arg1_k");
6393 gfHline();
6394 }
6395 else
6396 {
6397 siDump(&(par_block.pars[1].canonical_numerator), "arg1");
6398 gfHline();
6399 }
6400
6401 /* Print out the first argument. We display it differently
6402 ** depending on if it was rational or integral.
6403 */
6404 if (par_block.pars[2].canonical_denominator)
6405 {
6406 siDump(&(par_block.pars[2].canonical_numerator), "arg2_h");
6407 gfHline();
6408 siDump(&(par_block.pars[2].canonical_denominator), "arg2_k");
6409 gfHline();
6410 }
6411 else
6412 {
6413 siDump(&(par_block.pars[2].canonical_numerator), "arg2");
6414 gfHline();
6415 }
6416
6417 /* Print out the result. We display it differently, depending
6418 ** on whether it is rational or integral.
6419 */
6420 if (!siCompare(&result_denominator, &constant_1))
6421 {
6422 /* Denominator is equal to 1. This is an integer.
6423 */
6424 siDump(&result_numerator, "result");
6425 gfHline();
6426 }
6427 else
6428 {
6429 siDump(&result_numerator, "result_h");
6430 gfHline();
6431 siDump(&result_denominator, "result_k");
6432 gfHline();
6433 }
6434
6435 siDestroy(&arg1_h);
6436 siDestroy(&arg1_k);
6437 siDestroy(&arg2_h);
6438 siDestroy(&arg2_k);
6439 siDestroy(&constant_1);
6440 siDestroy(&result_numerator);
6441 siDestroy(&result_denominator);
6442 }
6443
6444
6445 /****************************************************************************/
6446 /* cfSimple2ParIntegerSubtraction(): */
6447 /*--------------------------------------------------------------------------*/
6448 /* DESCRIPTION */
6449 /* Handles subtraction of two arbitrary integers and displaying the */
6450 /* result. Called in response to a template match. */
6451 /****************************************************************************/
6452 void cfSimple2ParIntegerSubtraction(void)
6453 {
6454 SYNTHETIC_INTEGER *result;
6455
6456 siCreate(&result);
6457 siUnrestrictedSubtraction(&(par_block.pars[1].canonical_numerator),
6458 &(par_block.pars[2].canonical_numerator),
6459 &result);
6460 siDump(&(par_block.pars[1].canonical_numerator), "arg1");
6461 gfHline();
6462 siDump(&(par_block.pars[2].canonical_numerator), "arg2");
6463 gfHline();
6464 siDump(&result, "arg1 - arg2");
6465 gfHline();
6466 siDestroy(&result);
6467 }
6468
6469
6470 /****************************************************************************/
6471 /* cfSimple2ParRationalRationalSubtraction(): */
6472 /*--------------------------------------------------------------------------*/
6473 /* DESCRIPTION */
6474 /* Handles subtraction of two arbitrary rational numbers. Called in */
6475 /* response to a template match. */
6476 /****************************************************************************/
6477 void cfSimple2ParRationalRationalSubtraction(void)
6478 {
6479 SYNTHETIC_INTEGER *arg1_h,
6480 *arg1_k,
6481 *arg2_h,
6482 *arg2_k,
6483 *constant_1,
6484 *result_numerator,
6485 *result_denominator;
6486
6487 siCreate(&arg1_h);
6488 siCreate(&arg1_k);
6489 siCreate(&arg2_h);
6490 siCreate(&arg2_k);
6491 siCreate(&constant_1);
6492 siSetToLong(&constant_1, 1);
6493 siCreate(&result_numerator);
6494 siCreate(&result_denominator);
6495
6496 /* Since this function handles the general case where either
6497 ** or both arguments are rational, we need to watch out and
6498 ** condition any integer argument to be rational. We need
6499 ** to watch out for a missing denominator and assign it to
6500 ** be "1" if it is missing (meaning that the original argument
6501 ** was an integer.
6502 */
6503 /* Copy over to our scratch space, watching out for integers.
6504 */
6505 siCopy(&(par_block.pars[1].canonical_numerator), &arg1_h);
6506 if (par_block.pars[1].canonical_denominator)
6507 siCopy(&(par_block.pars[1].canonical_denominator), &arg1_k);
6508 else
6509 siSetToLong(&arg1_k, 1);
6510
6511 siCopy(&(par_block.pars[2].canonical_numerator), &arg2_h);
6512 if (par_block.pars[2].canonical_denominator)
6513 siCopy(&(par_block.pars[2].canonical_denominator), &arg2_k);
6514 else
6515 siSetToLong(&arg2_k, 1);
6516
6517 /* Make the call to the rational number addition function.
6518 */
6519 rnDifference(&arg1_h, &arg1_k, &arg2_h, &arg2_k, &result_numerator, &result_denominator);
6520
6521 /* Print out the first argument. We display it differently
6522 ** depending on if it was rational or integral.
6523 */
6524 if (par_block.pars[1].canonical_denominator)
6525 {
6526 siDump(&(par_block.pars[1].canonical_numerator), "arg1_h");
6527 gfHline();
6528 siDump(&(par_block.pars[1].canonical_denominator), "arg1_k");
6529 gfHline();
6530 }
6531 else
6532 {
6533 siDump(&(par_block.pars[1].canonical_numerator), "arg1");
6534 gfHline();
6535 }
6536
6537 /* Print out the first argument. We display it differently
6538 ** depending on if it was rational or integral.
6539 */
6540 if (par_block.pars[2].canonical_denominator)
6541 {
6542 siDump(&(par_block.pars[2].canonical_numerator), "arg2_h");
6543 gfHline();
6544 siDump(&(par_block.pars[2].canonical_denominator), "arg2_k");
6545 gfHline();
6546 }
6547 else
6548 {
6549 siDump(&(par_block.pars[2].canonical_numerator), "arg2");
6550 gfHline();
6551 }
6552
6553 /* Print out the result. We display it differently, depending
6554 ** on whether it is rational or integral.
6555 */
6556 if (!siCompare(&result_denominator, &constant_1))
6557 {
6558 /* Denominator is equal to 1. This is an integer.
6559 */
6560 siDump(&result_numerator, "result");
6561 gfHline();
6562 }
6563 else
6564 {
6565 siDump(&result_numerator, "result_h");
6566 gfHline();
6567 siDump(&result_denominator, "result_k");
6568 gfHline();
6569 }
6570
6571 siDestroy(&arg1_h);
6572 siDestroy(&arg1_k);
6573 siDestroy(&arg2_h);
6574 siDestroy(&arg2_k);
6575 siDestroy(&constant_1);
6576 siDestroy(&result_numerator);
6577 siDestroy(&result_denominator);
6578 }
6579
6580
6581 /****************************************************************************/
6582 /* cfSimple2ParIntegerMultiplication(): */
6583 /*--------------------------------------------------------------------------*/
6584 /* DESCRIPTION */
6585 /* Handles multiplication of two arbitrary integers and displaying the */
6586 /* result. Called in response to a template match. */
6587 /****************************************************************************/
6588 void cfSimple2ParIntegerMultiplication(void)
6589 {
6590 SYNTHETIC_INTEGER *result;
6591
6592 siCreate(&result);
6593 siUnrestrictedMultiplication(&(par_block.pars[1].canonical_numerator),
6594 &(par_block.pars[2].canonical_numerator),
6595 &result);
6596 siDump(&(par_block.pars[1].canonical_numerator), "arg1");
6597 gfHline();
6598 siDump(&(par_block.pars[2].canonical_numerator), "arg2");
6599 gfHline();
6600 siDump(&result, "arg1 * arg2");
6601 gfHline();
6602 siDestroy(&result);
6603 }
6604
6605
6606 /****************************************************************************/
6607 /* cfSimple2ParRationalRationalMultiplication(): */
6608 /*--------------------------------------------------------------------------*/
6609 /* DESCRIPTION */
6610 /* Handles multiplication of two arbitrary rational numbers. Called in */
6611 /* response to a template match. */
6612 /****************************************************************************/
6613 void cfSimple2ParRationalRationalMultiplication(void)
6614 {
6615 SYNTHETIC_INTEGER *arg1_h,
6616 *arg1_k,
6617 *arg2_h,
6618 *arg2_k,
6619 *constant_1,
6620 *result_numerator,
6621 *result_denominator;
6622
6623 siCreate(&arg1_h);
6624 siCreate(&arg1_k);
6625 siCreate(&arg2_h);
6626 siCreate(&arg2_k);
6627 siCreate(&constant_1);
6628 siSetToLong(&constant_1, 1);
6629 siCreate(&result_numerator);
6630 siCreate(&result_denominator);
6631
6632 /* Since this function handles the general case where either
6633 ** or both arguments are rational, we need to watch out and
6634 ** condition any integer argument to be rational. We need
6635 ** to watch out for a missing denominator and assign it to
6636 ** be "1" if it is missing (meaning that the original argument
6637 ** was an integer.
6638 */
6639 /* Copy over to our scratch space, watching out for integers.
6640 */
6641 siCopy(&(par_block.pars[1].canonical_numerator), &arg1_h);
6642 if (par_block.pars[1].canonical_denominator)
6643 siCopy(&(par_block.pars[1].canonical_denominator), &arg1_k);
6644 else
6645 siSetToLong(&arg1_k, 1);
6646
6647 siCopy(&(par_block.pars[2].canonical_numerator), &arg2_h);
6648 if (par_block.pars[2].canonical_denominator)
6649 siCopy(&(par_block.pars[2].canonical_denominator), &arg2_k);
6650 else
6651 siSetToLong(&arg2_k, 1);
6652
6653 /* Call the function to calculate the rational product.
6654 */
6655 rnProduct(&arg1_h, &arg1_k, &arg2_h, &arg2_k, &result_numerator, &result_denominator);
6656
6657 /* Print out the first argument. We display it differently
6658 ** depending on if it was rational or integral.
6659 */
6660 if (par_block.pars[1].canonical_denominator)
6661 {
6662 siDump(&(par_block.pars[1].canonical_numerator), "arg1_h");
6663 gfHline();
6664 siDump(&(par_block.pars[1].canonical_denominator), "arg1_k");
6665 gfHline();
6666 }
6667 else
6668 {
6669 siDump(&(par_block.pars[1].canonical_numerator), "arg1");
6670 gfHline();
6671 }
6672
6673 /* Print out the first argument. We display it differently
6674 ** depending on if it was rational or integral.
6675 */
6676 if (par_block.pars[2].canonical_denominator)
6677 {
6678 siDump(&(par_block.pars[2].canonical_numerator), "arg2_h");
6679 gfHline();
6680 siDump(&(par_block.pars[2].canonical_denominator), "arg2_k");
6681 gfHline();
6682 }
6683 else
6684 {
6685 siDump(&(par_block.pars[2].canonical_numerator), "arg2");
6686 gfHline();
6687 }
6688
6689 /* Print out the result. We display it differently, depending
6690 ** on whether it is rational or integral.
6691 */
6692 if (!siCompare(&result_denominator, &constant_1))
6693 {
6694 /* Denominator is equal to 1. This is an integer.
6695 */
6696 siDump(&result_numerator, "result");
6697 gfHline();
6698 }
6699 else
6700 {
6701 siDump(&result_numerator, "result_h");
6702 gfHline();
6703 siDump(&result_denominator, "result_k");
6704 gfHline();
6705 }
6706
6707 siDestroy(&arg1_h);
6708 siDestroy(&arg1_k);
6709 siDestroy(&arg2_h);
6710 siDestroy(&arg2_k);
6711 siDestroy(&constant_1);
6712 siDestroy(&result_numerator);
6713 siDestroy(&result_denominator);
6714 }
6715
6716
6717 /****************************************************************************/
6718 /* cfSimple2ParIntegerExponentiation(): */
6719 /*--------------------------------------------------------------------------*/
6720 /* DESCRIPTION */
6721 /* Handles simple integer exponentiation. Called in response to a */
6722 /* template match. */
6723 /****************************************************************************/
6724 void cfSimple2ParIntegerExponentiation(void)
6725 {
6726 SYNTHETIC_INTEGER *result;
6727
6728 siCreate(&result);
6729 siIntegerExponentiation(&(par_block.pars[1].canonical_numerator),
6730 &(par_block.pars[2].canonical_numerator),
6731 &result);
6732 siDump(&(par_block.pars[1].canonical_numerator), "arg");
6733 gfHline();
6734 siDump(&(par_block.pars[2].canonical_numerator), "exponent");
6735 gfHline();
6736 siDump(&result, "arg ** exponent");
6737 gfHline();
6738 siDestroy(&result);
6739 }
6740
6741
6742 /****************************************************************************/
6743 /* cfSimple2ParIntegerExponentiationOfRational(): */
6744 /*--------------------------------------------------------------------------*/
6745 /* DESCRIPTION */
6746 /* Handles a rational raised to an integer power. Called in response */
6747 /* to a template match. */
6748 /****************************************************************************/
6749 void cfSimple2ParIntegerExponentiationOfRational(void)
6750 {
6751 /* There isn't a need to do any conversion, before or after. Since
6752 ** the gcd() is removed from numerator and denominator, and since
6753 ** it isn't an integer, then the numerator and denominator have
6754 ** different prime components, exponentiating to any power
6755 ** can't create an integer or even anything that can be reduced.
6756 ** It would be fruitless to GCD the result.
6757 */
6758 SYNTHETIC_INTEGER *result_numerator;
6759 SYNTHETIC_INTEGER *result_denominator;
6760
6761 siCreate(&result_numerator);
6762 siCreate(&result_denominator);
6763
6764 siIntegerExponentiation(&(par_block.pars[1].canonical_numerator),
6765 &(par_block.pars[2].canonical_numerator),
6766 &result_numerator);
6767 siIntegerExponentiation(&(par_block.pars[1].canonical_denominator),
6768 &(par_block.pars[2].canonical_numerator),
6769 &result_denominator);
6770
6771 siDump(&(par_block.pars[1].canonical_numerator), "arg_h");
6772 gfHline();
6773 siDump(&(par_block.pars[1].canonical_denominator), "arg_k");
6774 gfHline();
6775 siDump(&(par_block.pars[2].canonical_numerator), "exponent");
6776 gfHline();
6777 siDump(&result_numerator, "arg_h ** exponent");
6778 gfHline();
6779 siDump(&result_denominator, "arg_k ** exponent");
6780 gfHline();
6781
6782 siDestroy(&result_numerator);
6783 siDestroy(&result_denominator);
6784 }
6785
6786
6787 /****************************************************************************/
6788 /* cfSimple2ParIntegerQuotient(): */
6789 /*--------------------------------------------------------------------------*/
6790 /* DESCRIPTION */
6791 /* Handles simple integer division. As a courtesy, the remainder is */
6792 /* returned as well. */
6793 /****************************************************************************/
6794 void cfSimple2ParIntegerQuotient(void)
6795 {
6796 SYNTHETIC_INTEGER *quotient;
6797 SYNTHETIC_INTEGER *remainder;
6798
6799 siCreate(&quotient);
6800 siCreate(&remainder);
6801 siUnrestrictedDivision(&(par_block.pars[1].canonical_numerator),
6802 &(par_block.pars[2].canonical_numerator),
6803 &quotient,
6804 &remainder);
6805 siDump(&(par_block.pars[1].canonical_numerator), "dividend");
6806 gfHline();
6807 siDump(&(par_block.pars[2].canonical_numerator), "divisor");
6808 gfHline();
6809 siDump(&remainder, "dividend % divisor");
6810 gfHline();
6811 siDump(&quotient, "dividend / divisor");
6812 gfHline();
6813 siDestroy(&quotient);
6814 siDestroy(&remainder);
6815 }
6816
6817
6818 /****************************************************************************/
6819 /* cfSimple2ParIntegerRemainder(): */
6820 /*--------------------------------------------------------------------------*/
6821 /* DESCRIPTION */
6822 /* Handles simple integer remainder. As a courtesy, the quotient is */
6823 /* returned as well. */
6824 /****************************************************************************/
6825 void cfSimple2ParIntegerRemainder(void)
6826 {
6827 SYNTHETIC_INTEGER *quotient;
6828 SYNTHETIC_INTEGER *remainder;
6829
6830 siCreate(&quotient);
6831 siCreate(&remainder);
6832 siUnrestrictedDivision(&(par_block.pars[1].canonical_numerator),
6833 &(par_block.pars[2].canonical_numerator),
6834 &quotient,
6835 &remainder);
6836 siDump(&(par_block.pars[1].canonical_numerator), "dividend");
6837 gfHline();
6838 siDump(&(par_block.pars[2].canonical_numerator), "divisor");
6839 gfHline();
6840 siDump(&quotient, "dividend / divisor");
6841 gfHline();
6842 siDump(&remainder, "dividend % divisor");
6843 gfHline();
6844 siDestroy(&quotient);
6845 siDestroy(&remainder);
6846 }
6847
6848
6849 /****************************************************************************/
6850 /* cfSimple2ParRationalRationalQuotient(): */
6851 /*--------------------------------------------------------------------------*/
6852 /* DESCRIPTION */
6853 /* Handles division of two arbitrary rational numbers. Called in */
6854 /* response to a template match. */
6855 /****************************************************************************/
6856 void cfSimple2ParRationalRationalQuotient(void)
6857 {
6858 SYNTHETIC_INTEGER *arg1_h,
6859 *arg1_k,
6860 *arg2_h,
6861 *arg2_k,
6862 *constant_1,
6863 *result_numerator,
6864 *result_denominator;
6865
6866 siCreate(&arg1_h);
6867 siCreate(&arg1_k);
6868 siCreate(&arg2_h);
6869 siCreate(&arg2_k);
6870 siCreate(&constant_1);
6871 siSetToLong(&constant_1, 1);
6872 siCreate(&result_numerator);
6873 siCreate(&result_denominator);
6874
6875 /* Since this function handles the general case where either
6876 ** or both arguments are rational, we need to watch out and
6877 ** condition any integer argument to be rational. We need
6878 ** to watch out for a missing denominator and assign it to
6879 ** be "1" if it is missing (meaning that the original argument
6880 ** was an integer.
6881 */
6882 /* Copy over to our scratch space, watching out for integers.
6883 */
6884 siCopy(&(par_block.pars[1].canonical_numerator), &arg1_h);
6885 if (par_block.pars[1].canonical_denominator)
6886 siCopy(&(par_block.pars[1].canonical_denominator), &arg1_k);
6887 else
6888 siSetToLong(&arg1_k, 1);
6889
6890 siCopy(&(par_block.pars[2].canonical_numerator), &arg2_h);
6891 if (par_block.pars[2].canonical_denominator)
6892 siCopy(&(par_block.pars[2].canonical_denominator), &arg2_k);
6893 else
6894 siSetToLong(&arg2_k, 1);
6895
6896 /* Call the function to calculate the rational product.
6897 */
6898 rnQuotient(&arg1_h, &arg1_k, &arg2_h, &arg2_k, &result_numerator, &result_denominator);
6899
6900 /* Print out the first argument. We display it differently
6901 ** depending on if it was rational or integral.
6902 */
6903 if (par_block.pars[1].canonical_denominator)
6904 {
6905 siDump(&(par_block.pars[1].canonical_numerator), "arg1_h");
6906 gfHline();
6907 siDump(&(par_block.pars[1].canonical_denominator), "arg1_k");
6908 gfHline();
6909 }
6910 else
6911 {
6912 siDump(&(par_block.pars[1].canonical_numerator), "arg1");
6913 gfHline();
6914 }
6915
6916 /* Print out the first argument. We display it differently
6917 ** depending on if it was rational or integral.
6918 */
6919 if (par_block.pars[2].canonical_denominator)
6920 {
6921 siDump(&(par_block.pars[2].canonical_numerator), "arg2_h");
6922 gfHline();
6923 siDump(&(par_block.pars[2].canonical_denominator), "arg2_k");
6924 gfHline();
6925 }
6926 else
6927 {
6928 siDump(&(par_block.pars[2].canonical_numerator), "arg2");
6929 gfHline();
6930 }
6931
6932 /* Print out the result. We display it differently, depending
6933 ** on whether it is rational or integral.
6934 */
6935 if (!siCompare(&result_denominator, &constant_1))
6936 {
6937 /* Denominator is equal to 1. This is an integer.
6938 */
6939 siDump(&result_numerator, "result");
6940 gfHline();
6941 }
6942 else
6943 {
6944 siDump(&result_numerator, "result_h");
6945 gfHline();
6946 siDump(&result_denominator, "result_k");
6947 gfHline();
6948 }
6949
6950 siDestroy(&arg1_h);
6951 siDestroy(&arg1_k);
6952 siDestroy(&arg2_h);
6953 siDestroy(&arg2_k);
6954 siDestroy(&constant_1);
6955 siDestroy(&result_numerator);
6956 siDestroy(&result_denominator);
6957 }
6958
6959
6960 /****************************************************************************/
6961 /* cfSimple2ParIntegerGcd(): */
6962 /*--------------------------------------------------------------------------*/
6963 /* DESCRIPTION */
6964 /* Applies Euclid's algorithm to obtain the gcd() of two positive */
6965 /* integers. */
6966 /****************************************************************************/
6967 void cfSimple2ParIntegerGcd(void)
6968 {
6969 SYNTHETIC_INTEGER *result;
6970
6971 siCreate(&result);
6972 siGcd(&(par_block.pars[1].canonical_numerator),
6973 &(par_block.pars[2].canonical_numerator),
6974 &result);
6975 siDump(&(par_block.pars[1].canonical_numerator), "arg1");
6976 gfHline();
6977 siDump(&(par_block.pars[2].canonical_numerator), "arg2");
6978 gfHline();
6979 siDump(&result, "gcd(arg1, arg2)");
6980 gfHline();
6981 siDestroy(&result);
6982 }
6983
6984
6985 /****************************************************************************/
6986 /* cfDap(): */
6987 /*--------------------------------------------------------------------------*/
6988 /* DESCRIPTION */
6989 /* Applies the DAP function as outlined in the manual. */
6990 /****************************************************************************/
6991 void cfDap(void)
6992 {
6993 SYNTHETIC_INTEGER *D, /* The denominator chosen. */
6994 *hD, /* Product of input h and D. */
6995 *k, /* Denominator to be used. */
6996 *hD_over_k, /* Final result. */
6997 *trash_remainder; /* Remainder not used. */
6998
6999 /* Create all of our locals.
7000 */
7001 siCreate(&D);
7002 siCreate(&hD);
7003 siCreate(&k);
7004 siCreate(&hD_over_k);
7005 siCreate(&trash_remainder);
7006
7007 /* There are two cases to consider. Either the user has
7008 ** specified a second parameter (the denominator to use),
7009 ** or we use a default. Let's assign the default, then
7010 ** overwrite it with the user's choice.
7011 */
7012 siSetToPowerOfTen(&D, DIGITS_PER_LINE * 4);
7013
7014 /* If the user has specified a second parameter, set D to be
7015 ** that second parameter. This overwrites the default
7016 ** choice of four lines.
7017 */
7018 if (par_block.pars[2].ftype == CMDLINE_PAR_TYPE_INTPOS)
7019 {
7020 asAssert(par_block.pars[2].canonical_numerator != NULL, __LINE__);
7021
7022 siCopy(&(par_block.pars[2].canonical_numerator), &D);
7023 }
7024
7025 /* Assign the value of k, in case the user is trying to DAP an integer,
7026 ** which doesn't make sense.
7027 */
7028 if (par_block.pars[1].canonical_denominator)
7029 siCopy(&(par_block.pars[1].canonical_denominator), &k);
7030 else
7031 siSetToLong(&k, 1);
7032
7033 /* Perform the actual DAP calculation. */
7034 asAssert(par_block.pars[1].canonical_numerator != NULL, __LINE__);
7035 siUnrestrictedMultiplication(&(par_block.pars[1].canonical_numerator),
7036 &D,
7037 &hD);
7038 siUnrestrictedDivision(&hD,
7039 &k,
7040 &hD_over_k,
7041 &trash_remainder);
7042
7043 /* Print the results. */
7044 if (par_block.pars[1].canonical_denominator)
7045 {
7046 siDump(&(par_block.pars[1].canonical_numerator), "arg_h");
7047 gfHline();
7048 siDump(&(par_block.pars[1].canonical_denominator), "arg_k");
7049 gfHline();
7050 }
7051 else
7052 {
7053 siDump(&(par_block.pars[1].canonical_numerator), "arg");
7054 gfHline();
7055 }
7056
7057 siDump(&hD_over_k, "N");
7058 gfHline();
7059 siDump(&D, "D");
7060 gfHline();
7061
7062 /* Destroy all of our locals.
7063 */
7064 siDestroy(&D);
7065 siDestroy(&hD);
7066 siDestroy(&k);
7067 siDestroy(&hD_over_k);
7068 siDestroy(&trash_remainder);
7069 }
7070
7071
7072 /****************************************************************************/
7073 /* cfCf(): */
7074 /*--------------------------------------------------------------------------*/
7075 /* DESCRIPTION */
7076 /* Forms the continued fraction decomposition and convergents of a */
7077 /* non-negative rational number. */
7078 /****************************************************************************/
7079 void cfCf(void)
7080 {
7081 SYNTHETIC_INTEGER *h, *k; /* The numerator and denominator to use
7082 ** for the continued fraction expansion.
7083 */
7084 CF_EXPANSION *e; /* The continued fraction expansion.
7085 */
7086
7087 /* Allocate the integers.
7088 */
7089 siCreate(&h);
7090 siCreate(&k);
7091
7092 /* Be absolutely sure that we have a viable numerator, and
7093 ** copy it to what we are using for our numerator.
7094 */
7095 asAssert(par_block.pars[1].canonical_numerator != NULL, __LINE__);
7096 siCopy(&(par_block.pars[1].canonical_numerator), &h);
7097
7098 /* Use the denominator available, unless it doesn't exist, in
7099 ** which case will use "1".
7100 */
7101 if (par_block.pars[1].canonical_denominator)
7102 {
7103 siCopy(&(par_block.pars[1].canonical_denominator), &k);
7104 }
7105 else
7106 {
7107 siSetToLong(&k, 1);
7108 }
7109
7110 /* Create the CF expansion.
7111 */
7112 pqCreate(&h, &k, &e);
7113
7114 /* Print it out. No description is required.
7115 */
7116 pqDump(&e, "", 0);
7117
7118 /* Destroy the expansion.
7119 */
7120 pqDestroy(&e);
7121
7122 /* Destroy the integers.
7123 */
7124 siDestroy(&h);
7125 siDestroy(&k);
7126 }
7127
7128
7129 /****************************************************************************/
7130 /* cfFn(): */
7131 /*--------------------------------------------------------------------------*/
7132 /* DESCRIPTION */
7133 /* Locates the enclosing Farey neighbors and prints them out. This func- */
7134 /* tion is called in response to a template match. */
7135 /****************************************************************************/
7136 void cfFn(void)
7137 {
7138 int convergent_number;
7139 int nneighbors;
7140 int arg_in_series = FALSE;
7141 int cur_series_term;
7142
7143 SYNTHETIC_INTEGER *D, *h, *k, *N, *conv_h, *conv_k, *neigh_h, *neigh_k,
7144 *hleft, *kleft, *hright, *kright, *error_h, *error_k,
7145 *dap_h, *dap_k, *t1, *t2;
7146 CF_EXPANSION *expansion;
7147 char buf[100];
7148
7149 /* Create all temporary variables.
7150 */
7151 siCreate(&D);
7152 siCreate(&h);
7153 siCreate(&k);
7154 siCreate(&N);
7155 siCreate(&conv_h);
7156 siCreate(&conv_k);
7157 siCreate(&neigh_h);
7158 siCreate(&neigh_k);
7159 siCreate(&hleft);
7160 siCreate(&kleft);
7161 siCreate(&hright);
7162 siCreate(&kright);
7163 siCreate(&error_h);
7164 siCreate(&error_k);
7165 siCreate(&dap_h);
7166 siCreate(&dap_k);
7167 siCreate(&t1);
7168 siCreate(&t2);
7169
7170 /* There are either two or four parameters to this command. For
7171 ** the optional parameters, they override defaults.
7172 ** Assign the defaults first, before the optional parameters are
7173 ** processed.
7174 */
7175
7176 /* By default, just generate one Farey neighbor on each side of
7177 ** the rational number supplied.
7178 */
7179 nneighbors = 1;
7180
7181 /* By default, the denominator used for presentation is good for
7182 ** four lines of zeros.
7183 */
7184 siSetToPowerOfTen(&D, DIGITS_PER_LINE * 4);
7185
7186 /* Copy the rational number specified for this command to our area,
7187 ** and if it is an integer provide a denominator of 1 automatically.
7188 */
7189 siCopy(&(par_block.pars[1].canonical_numerator), &h);
7190 if (par_block.pars[1].canonical_denominator)
7191 siCopy(&(par_block.pars[1].canonical_denominator), &k);
7192 else
7193 siSetToLong(&k, 1);
7194
7195 /* Copy the order of the series to our area.
7196 */
7197 siCopy(&(par_block.pars[2].canonical_numerator), &N);
7198
7199 /* Convert the number of neighbors to an integer if this command has
7200 ** the optional arguments.
7201 */
7202 if (par_block.pars[3].canonical_numerator)
7203 {
7204 SYNTHETIC_INTEGER *n;
7205
7206 siCreate(&n);
7207
7208 siSetToLong(&n, 10000);
7209
7210 if (siCompare(&n, &(par_block.pars[3].canonical_numerator)) <= 0)
7211 {
7212 nneighbors = 10000;
7213 }
7214 else
7215 {
7216 sscanf(par_block.pars[3].orig_string, "%d", &nneighbors);
7217 }
7218
7219 siDestroy(&n);
7220 }
7221
7222 /* Override the denominator if that parameter is present.
7223 */
7224 if (par_block.pars[4].canonical_numerator)
7225 siCopy(&(par_block.pars[4].canonical_numerator), &D);
7226
7227 /* Form the continued fraction representation of the
7228 ** rational number.
7229 */
7230 pqCreate(&h, &k, &expansion);
7231
7232 /* Print out the number and expansion and other input parameters
7233 ** as output.
7234 */
7235 gfBannerHeading("Rational Number h_in/k_in To Approximate", 0);
7236 gfHline();
7237 siDump(&h, "h_in");
7238 gfHline();
7239 siDump(&k, "k_in");
7240 gfHline();
7241 gfBannerHeading("Other Solution Parameters", 0);
7242 gfHline();
7243 siDump(&N, "Order");
7244 gfHline();
7245
7246 {
7247 SYNTHETIC_INTEGER *scratch;
7248
7249 siCreate(&scratch);
7250
7251 siSetToLong(&scratch, nneighbors);
7252
7253 siDump(&scratch, "NNEIGHBORS");
7254
7255 siDestroy(&scratch);
7256 }
7257
7258 gfHline();
7259 siDump(&D, "DAP Denominator");
7260 gfHline();
7261 gfBannerHeading("Continued Fraction Expansion Of h_in/k_in", 0);
7262 gfHline();
7263 pqDump(&expansion, "", 0);
7264
7265 /* Obtain the two best rational approximations to the number.
7266 */
7267 pqBapp(&expansion,
7268 &N,
7269 &conv_h,
7270 &conv_k,
7271 &neigh_h,
7272 &neigh_k,
7273 &convergent_number);
7274
7275 /* Print out the information generated by the call above
7276 */
7277 gfBannerHeading("Highest-Order Convergent With q(i)<=N", 0);
7278 gfHline();
7279 sprintf(buf, "p(%d)", convergent_number);
7280 siDump(&conv_h, buf);
7281 sprintf(buf, "q(%d)", convergent_number);
7282 siDump(&conv_k, buf);
7283 gfHline();
7284 gfBannerHeading("Accompanying Intermediate Fraction", 0);
7285 gfHline();
7286 siDump(&neigh_h, "intermediate_h");
7287 siDump(&neigh_k, "intermediate_k");
7288 gfHline();
7289
7290 /* Decide, remember, and announce if the term of interest is already in
7291 ** the Farey series of interest. This will be true if and only if
7292 ** the convergent chosen has the same value as the rational argument.
7293 */
7294 if (!rnCompare(&conv_h, &conv_k, &h, &k))
7295 {
7296 gfBannerHeading("h_in/k_in IS In Farey Series Of Interest", 1);
7297 arg_in_series = TRUE;
7298 }
7299 else
7300 {
7301 gfBannerHeading("h_in/k_in IS NOT In Farey Series Of Interest", 1);
7302 }
7303 gfHline();
7304
7305 /* We need to sort the convergent and neighbor back from the cfBapp()
7306 ** function. But there is a bit of a catch. We need to know the
7307 ** correct index to go along with the left one. This gets a bit
7308 ** complicated if the convergent was already in the Farey series.
7309 ** We'll only give the subscript of 0 if the rational number is
7310 ** in the Farey series.
7311 */
7312 if (rnCompare(&conv_h, &conv_k, &neigh_h, &neigh_k) < 0)
7313 {
7314 siCopy(&conv_h, &hleft);
7315 siCopy(&conv_k, &kleft);
7316 siCopy(&neigh_h, &hright);
7317 siCopy(&neigh_k, &kright);
7318
7319 if (arg_in_series)
7320 cur_series_term = 0;
7321 else
7322 cur_series_term = -1;
7323 }
7324 else
7325 {
7326 siCopy(&neigh_h, &hleft);
7327 siCopy(&neigh_k, &kleft);
7328 siCopy(&conv_h, &hright);
7329 siCopy(&conv_k, &kright);
7330
7331 cur_series_term = -1;
7332 }
7333
7334 /* Loop backwards through the Farey series until either we hit zero
7335 ** or we hit the number of neighbors we need.
7336 */
7337 while ((hleft->len) && (cur_series_term > -nneighbors))
7338 {
7339 rnFareyTraverse(&hleft, &kleft, &hright, &kright, &N, -1);
7340 cur_series_term--;
7341 }
7342
7343 /* Now, go forward. If the rational number specified was already in
7344 ** the series, we use the subscript zero, otherwise not.
7345 */
7346 while (cur_series_term <= nneighbors)
7347 {
7348 /* Heading */
7349 sprintf(buf, "Farey Neighbor Index %d", cur_series_term);
7350 gfBannerHeading(buf, 0);
7351 gfHline();
7352
7353 /* The actual term. */
7354 sprintf(buf, "h(%d)", cur_series_term);
7355 siDump(&hleft, buf);
7356 gfHline();
7357 buf[0] = 'k';
7358 siDump(&kleft, buf);
7359 gfHline();
7360
7361 /* Also present the rational number as a decimal.
7362 */
7363 siCopy(&D, &dap_k);
7364 rnDap(&hleft, &kleft, &dap_h, &dap_k);
7365 sprintf(buf, "DAP_N(%d)", cur_series_term);
7366 siDump(&dap_h, buf);
7367 gfHline();
7368 sprintf(buf, "DAP_D(%d)", cur_series_term);
7369 siDump(&dap_k, buf);
7370 gfHline();
7371
7372 /* Rational difference between the rational number we're trying
7373 ** to approximate and the approximation we have. Canonically, we
7374 ** want a larger approximation to have a positive error, so we
7375 ** define error as (approximation - actual).
7376 */
7377 /* Calculate the difference as a rational number.
7378 */
7379 rnDifference(&hleft, &kleft, &h, &k, &error_h, &error_k);
7380
7381 /* Present it as a rational number. */
7382 sprintf(buf, "error_h(%d)", cur_series_term);
7383 siDump(&error_h, buf);
7384 gfHline();
7385 sprintf(buf, "error_k(%d)", cur_series_term);
7386 siDump(&error_k, buf);
7387 gfHline();
7388
7389
7390 /* Present it as a DAP. */
7391 siCopy(&D, &dap_k);
7392 rnDap(&error_h, &error_k, &dap_h, &dap_k);
7393 sprintf(buf, "ERROR_DAP_N(%d)", cur_series_term);
7394 siDump(&dap_h, buf);
7395 gfHline();
7396 sprintf(buf, "ERROR_DAP_D(%d)", cur_series_term);
7397 siDump(&dap_k, buf);
7398 gfHline();
7399
7400
7401 rnFareyTraverse(&hleft, &kleft, &hright, &kright, &N, 1);
7402
7403 if (arg_in_series)
7404 {
7405 cur_series_term++;
7406 }
7407 else
7408 {
7409 if (cur_series_term == -1)
7410 cur_series_term = 1;
7411 else
7412 cur_series_term++;
7413 }
7414 }
7415
7416 /* Destroy all local variables.
7417 */
7418 siDestroy(&D);
7419 siDestroy(&h);
7420 siDestroy(&k);
7421 siDestroy(&N);
7422 siDestroy(&conv_h);
7423 siDestroy(&conv_k);
7424 siDestroy(&neigh_h);
7425 siDestroy(&neigh_k);
7426 siDestroy(&hleft);
7427 siDestroy(&kleft);
7428 siDestroy(&hright);
7429 siDestroy(&kright);
7430 siDestroy(&error_h);
7431 siDestroy(&error_k);
7432 siDestroy(&dap_h);
7433 siDestroy(&dap_k);
7434 siDestroy(&t1);
7435 siDestroy(&t2);
7436 }
7437
7438
7439 /****************************************************************************/
7440 /* cfMind(): */
7441 /*--------------------------------------------------------------------------*/
7442 /* DESCRIPTION */
7443 /* Locates the enclosing Farey neighbors and prints them out. This func- */
7444 /* tion is called in response to a template match. */
7445 /****************************************************************************/
7446 void cfMind(void)
7447 {
7448 SYNTHETIC_INTEGER *r1_h, *r1_k, *r2_h, *r2_k,
7449 *result_h, *result_k;
7450
7451 /* Allocate all of our local variables.
7452 */
7453 siCreate(&r1_h);
7454 siCreate(&r1_k);
7455 siCreate(&r2_h);
7456 siCreate(&r2_k);
7457 siCreate(&result_h);
7458 siCreate(&result_k);
7459
7460 /* State the two input parameters as rational numbers, in case
7461 ** on or both are integers.
7462 */
7463 asAssert(par_block.pars[1].canonical_numerator != NULL, __LINE__);
7464 asAssert(par_block.pars[2].canonical_numerator != NULL, __LINE__);
7465 siCopy(&(par_block.pars[1].canonical_numerator), &r1_h);
7466 siCopy(&(par_block.pars[2].canonical_numerator), &r2_h);
7467 if (par_block.pars[1].canonical_denominator)
7468 siCopy(&(par_block.pars[1].canonical_denominator), &r1_k);
7469 else
7470 siSetToLong(&r1_k, 1);
7471 if (par_block.pars[2].canonical_denominator)
7472 siCopy(&(par_block.pars[2].canonical_denominator), &r2_k);
7473 else
7474 siSetToLong(&r2_k, 1);
7475
7476 /* If the parameters for the interval are out of order,
7477 ** swap them.
7478 */
7479 if (rnCompare(&r1_h, &r1_k, &r2_h, &r2_k) == 1)
7480 {
7481 SYNTHETIC_INTEGER *temp;
7482
7483 /* Out of order, swap them. For our application,
7484 ** can just play with pointers.
7485 */
7486 temp = r1_h;
7487 r1_h = r2_h;
7488 r2_h = temp;
7489 temp = r1_k;
7490 r1_k = r2_k;
7491 r2_k = temp;
7492 }
7493
7494 /* Echo back the parameters for the caller.
7495 */
7496 siDump(&r1_h, "l_h");
7497 gfHline();
7498 siDump(&r1_k, "l_k");
7499 gfHline();
7500 siDump(&r2_h, "r_h");
7501 gfHline();
7502 siDump(&r2_k, "r_k");
7503 gfHline();
7504
7505 /* Do the calculation proper.
7506 */
7507 naMind(&r1_h,
7508 &r1_k,
7509 &r2_h,
7510 &r2_k,
7511 &result_h,
7512 &result_k,
7513 TRUE,
7514 TRUE,
7515 FALSE
7516 );
7517
7518 /* Emit the results.
7519 */
7520 gfBannerHeading("A Rational Number With Smallest Denominator In Interval", 0);
7521 gfHline();
7522 siDump(&result_h, "result_h");
7523 gfHline();
7524 siDump(&result_k, "result_k");
7525 gfHline();
7526
7527 /* Destroy the locals.
7528 */
7529 siDestroy(&r1_h);
7530 siDestroy(&r1_k);
7531 siDestroy(&r2_h);
7532 siDestroy(&r2_k);
7533 siDestroy(&result_h);
7534 siDestroy(&result_k);
7535 }
7536
7537
7538 /****************************************************************************/
7539 /* cfFab(): */
7540 /*--------------------------------------------------------------------------*/
7541 /* DESCRIPTION */
7542 /* Locates the enclosing Farey neighbors in the doubly-constrained series */
7543 /* and prints them out. Called in response to a template match. */
7544 /****************************************************************************/
7545 void cfFab(void)
7546 {
7547 int convergent_number;
7548 /* The convergent number we are iterating through.
7549 */
7550 int nneighbors;
7551 /* The number of neighbors on both sides to generate.
7552 */
7553 int arg_in_series = FALSE;
7554 /* TRUE if the rational argument supplied is in the
7555 ** series, or FALSE otherwise.
7556 */
7557 int cur_series_term;
7558 /* The current series term we're iterating through.
7559 ** Terms are indexed backwards and forwards from
7560 ** zero.
7561 */
7562 int done = FALSE;
7563 /* Flag used to exit from the forward-generation loop, as successive
7564 ** Farey terms are displayed.
7565 */
7566
7567 SYNTHETIC_INTEGER *D, /* The denominator that will be used for
7568 ** decimal approximation.
7569 */
7570 *h, *k,
7571 /* Numerator and denominator of rational
7572 ** number that we are bracketing with
7573 ** Farey terms.
7574 */
7575 *hmax,
7576 *kmax,
7577 /* The maximum numerator and denominator,
7578 ** i.e. this defines the rectangular
7579 ** area of the integer lattice we are
7580 ** considering.
7581 */
7582 *canonical_hmax,
7583 *canonical_kmax,
7584 /* The reduced form of hmax and kmax, i.e.
7585 ** with the g.c.d. removed. This is necessary
7586 ** because hmax and kmax proper are used to
7587 ** test denominators, but this value will
7588 ** show up in the Farey series.
7589 */
7590 *normal_corner_predecessor_h,
7591 *normal_corner_predecessor_k,
7592 /* The predecessor to the corner point
7593 ** along the "right" edge of the rectangle.
7594 */
7595 *reciprocal_corner_successor_h,
7596 *reciprocal_corner_successor_k,
7597 /* The successor to the corner point
7598 ** in the series along the "top" of
7599 ** the rectangle.
7600 */
7601 *constant_1,
7602 *constant_0,
7603 /* Numerical constants for easy comparison.
7604 */
7605 *conv_h,
7606 *conv_k,
7607 /* The highest-order convergent with denominator
7608 ** not larger than the order of the Farey series.
7609 ** Used for calls to pqBapp().
7610 */
7611 *neigh_h,
7612 *neigh_k,
7613 /* The neighbor to the number of interest. Used for
7614 ** calls to pqBapp().
7615 */
7616 *hleft,
7617 *kleft,
7618 *hright,
7619 *kright,
7620 /* The left and right numbers used to iterate through the
7621 ** Farey series using the recursive formulas.
7622 */
7623 *error_h,
7624 *error_k,
7625 /* The error for an approximation, as a rational number.
7626 */
7627 *dap_h,
7628 *dap_k,
7629 /* The error for an approximation, expressed with a
7630 ** different denominator, chosen either by default
7631 ** or from the command line.
7632 */
7633 *t1,
7634 *t2;
7635 /* General-purpose temporary variables.
7636 */
7637
7638 CF_EXPANSION *rn_expansion = NULL,
7639 /* The continued fraction and convergent
7640 ** expansion of the rational number to approximate.
7641 */
7642 *rn_reciprocal_expansion = NULL,
7643 /* The continued fraction and convergent expansion
7644 ** of the reciprocal of the number to be
7645 ** approximated. This can only be done if the
7646 ** number is non-zero.
7647 */
7648 *corner_point_expansion = NULL,
7649 /* The CF expansion of the corner point. This is
7650 ** necessary to get the neighbor just to the left
7651 ** in F_N.
7652 */
7653 *corner_point_reciprocal_expansion = NULL;
7654 /* The expansion of the reciprocal of the
7655 ** corner point. This is necessary to get
7656 ** the neighbor along the "top" of the lattice.
7657 */
7658
7659 char buf[100];
7660 /* String buffer, used to stage things to be printed.
7661 */
7662
7663 /* Create all temporary variables.
7664 */
7665 siCreate(&D);
7666 siCreate(&h);
7667 siCreate(&k);
7668 siCreate(&hmax);
7669 siCreate(&kmax);
7670 siCreate(&canonical_hmax);
7671 siCreate(&canonical_kmax);
7672 siCreate(&normal_corner_predecessor_h);
7673 siCreate(&normal_corner_predecessor_k);
7674 siCreate(&reciprocal_corner_successor_h);
7675 siCreate(&reciprocal_corner_successor_k);
7676 siCreate(&constant_1);
7677 siSetToLong(&constant_1, 1);
7678 siCreate(&constant_0);
7679 siSetToLong(&constant_0, 0);
7680 siCreate(&conv_h);
7681 siCreate(&conv_k);
7682 siCreate(&neigh_h);
7683 siCreate(&neigh_k);
7684 siCreate(&hleft);
7685 siCreate(&kleft);
7686 siCreate(&hright);
7687 siCreate(&kright);
7688 siCreate(&error_h);
7689 siCreate(&error_k);
7690 siCreate(&dap_h);
7691 siCreate(&dap_k);
7692 siCreate(&t1);
7693 siCreate(&t2);
7694
7695 /* There are either three or five parameters to this command. For
7696 ** the optional parameters, they override defaults.
7697 ** Assign the defaults first, before the optional parameters are
7698 ** processed.
7699 */
7700
7701 /* By default, just generate one Farey neighbor on each side of
7702 ** the rational number supplied.
7703 */
7704 nneighbors = 1;
7705
7706 /* By default, the denominator used for presentation is good for
7707 ** four lines of zeros.
7708 */
7709 siSetToPowerOfTen(&D, DIGITS_PER_LINE * 4);
7710
7711 /* Copy the rational number specified for this command to our area,
7712 ** and if it is an integer provide a denominator of 1 automatically.
7713 */
7714 siCopy(&(par_block.pars[1].canonical_numerator), &h);
7715 if (par_block.pars[1].canonical_denominator)
7716 siCopy(&(par_block.pars[1].canonical_denominator), &k);
7717 else
7718 siSetToLong(&k, 1);
7719
7720 /* Copy the maximum h and maximum k to our area.
7721 */
7722 siCopy(&(par_block.pars[2].canonical_numerator), &hmax);
7723 siCopy(&(par_block.pars[3].canonical_numerator), &kmax);
7724
7725 /* Copy an extra copy of these to the canonical values,
7726 ** and must remove the GCD.
7727 */
7728 siCopy(&hmax, &canonical_hmax);
7729 siCopy(&kmax, &canonical_kmax);
7730 rnCanonize(&canonical_hmax, &canonical_kmax);
7731
7732 /* Convert the number of neighbors to an integer if this command has
7733 ** the optional arguments.
7734 */
7735 if (par_block.pars[4].canonical_numerator)
7736 {
7737 SYNTHETIC_INTEGER *n;
7738
7739 siCreate(&n);
7740
7741 siSetToLong(&n, 10000);
7742
7743 if (siCompare(&n, &(par_block.pars[4].canonical_numerator)) <= 0)
7744 {
7745 nneighbors = 10000;
7746 }
7747 else
7748 {
7749 sscanf(par_block.pars[4].orig_string, "%d", &nneighbors);
7750 }
7751
7752 siDestroy(&n);
7753 }
7754
7755 /* Override the denominator if that parameter is present.
7756 */
7757 if (par_block.pars[5].canonical_numerator)
7758 siCopy(&(par_block.pars[5].canonical_numerator), &D);
7759
7760 /* Form the continued fraction representation of the
7761 ** rational number.
7762 */
7763 pqCreate(&h, &k, &rn_expansion);
7764
7765 /* Form the continued fraction representation of the
7766 ** reciprocal in any case besides the number
7767 ** zero.
7768 */
7769 if (h->len)
7770 pqCreate(&k, &h, &rn_reciprocal_expansion);
7771
7772 /* Print out the number and expansion and other input parameters
7773 ** as output.
7774 */
7775 gfBannerHeading("Rational Number h_in/k_in To Approximate", 0);
7776 gfHline();
7777 siDump(&h, "h_in");
7778 gfHline();
7779 siDump(&k, "k_in");
7780 gfHline();
7781 gfBannerHeading("Other Solution Parameters", 0);
7782 gfHline();
7783 siDump(&hmax, "hmax");
7784 gfHline();
7785 siDump(&kmax, "kmax");
7786 gfHline();
7787
7788 {
7789 SYNTHETIC_INTEGER *scratch;
7790
7791 siCreate(&scratch);
7792
7793 siSetToLong(&scratch, nneighbors);
7794
7795 siDump(&scratch, "NNEIGHBORS");
7796
7797 siDestroy(&scratch);
7798 }
7799
7800 gfHline();
7801 siDump(&D, "DAP Denominator");
7802 gfHline();
7803 gfBannerHeading("Continued Fraction Expansion Of h_in/k_in", 0);
7804 gfHline();
7805 pqDump(&rn_expansion, "", 0);
7806
7807 if (rn_reciprocal_expansion)
7808 {
7809 gfBannerHeading("Continued Fraction Expansion Of k_in/h_in", 0);
7810 gfHline();
7811 pqDump(&rn_reciprocal_expansion, "", 0);
7812 }
7813
7814 /* Now we need to obtain the neighbors of the "corner point"
7815 ** in both of the Farey series involved. It is more
7816 ** straightforward to generate them in advance.
7817 */
7818 /* First, get the continued fraction expansion of the
7819 ** corner point in normal coordinates, and output the result.
7820 */
7821 pqCreate(&canonical_hmax, &canonical_kmax, &corner_point_expansion);
7822 gfBannerHeading("Continued Fraction Expansion Of Corner Point", 0);
7823 gfHline();
7824 pqDump(&corner_point_expansion, "", 0);
7825
7826 /* Now, get the continued fraction expansion of the
7827 ** corner point in inverted coordinates, and output the result.
7828 */
7829 pqCreate(&canonical_kmax, &canonical_hmax, &corner_point_reciprocal_expansion);
7830 gfBannerHeading("Continued Fraction Expansion Of Corner Point Reciprocal", 0);
7831 gfHline();
7832 pqDump(&corner_point_reciprocal_expansion, "", 0);
7833
7834 /* Find the best approximation along the right edge to the corner
7835 ** point. Depending on whether have even or odd convergents,
7836 ** may get above or below the corner point. If get above,
7837 ** must go down using standard recursive formulas.
7838 */
7839 pqBapp(&corner_point_expansion,
7840 &kmax,
7841 &conv_h,
7842 &conv_k,
7843 &normal_corner_predecessor_h,
7844 &normal_corner_predecessor_k,
7845 &convergent_number);
7846 /* We may have the Farey term either left or right. If right,
7847 ** must backtrack by one.
7848 */
7849 if (rnCompare(&canonical_hmax, &canonical_kmax,
7850 &normal_corner_predecessor_h, &normal_corner_predecessor_k)
7851 < 0)
7852 {
7853 SYNTHETIC_INTEGER *temp_h, *temp_k;
7854
7855 /* printf("REVERSE! (corner point predecessor)\n"); */
7856
7857 /* Must get the predecessor.
7858 */
7859 siCreate(&temp_h);
7860 siCreate(&temp_k);
7861
7862 siCopy(&canonical_hmax, &temp_h);
7863 siCopy(&canonical_kmax, &temp_k);
7864
7865 rnFareyTraverse(&temp_h,
7866 &temp_k,
7867 &normal_corner_predecessor_h,
7868 &normal_corner_predecessor_k,
7869 &kmax,
7870 -1);
7871 siCopy(&temp_h, &normal_corner_predecessor_h);
7872 siCopy(&temp_k, &normal_corner_predecessor_k);
7873
7874 siDestroy(&temp_h);
7875 siDestroy(&temp_k);
7876 }
7877
7878 gfBannerHeading("Corner Point Neighbors", 0);
7879 gfHline();
7880 siDump(&normal_corner_predecessor_h, "corner_pred_h");
7881 siDump(&normal_corner_predecessor_k, "corner_pred_k");
7882 gfHline();
7883
7884 /* Find the best approximation along the top edge to the corner
7885 ** point. Depending on whether have even or odd convergents,
7886 ** may get left or right of the corner point. If get left,
7887 ** must go right using standard recursive formulas. There is, however,
7888 ** one exception. If kmax = 1, there will be nothing to the right
7889 ** of the corner point, and must just keep value as zero over zero
7890 ** as a marker.
7891 */
7892 if (siCompare(&constant_1, &kmax) == 0)
7893 {
7894 /* In this case, there is no point to the right.
7895 ** Assign the successor to be be 0/0, as a marker.
7896 */
7897 siSetToLong(&reciprocal_corner_successor_h, 0);
7898 siSetToLong(&reciprocal_corner_successor_k, 0);
7899 }
7900 else
7901 {
7902 /* There is a successor to the right.
7903 */
7904
7905 SYNTHETIC_INTEGER *temph, *tempk;
7906
7907 siCreate(&temph);
7908 siCreate(&tempk);
7909
7910 /* There is a point to the right. It will take a few
7911 ** contortions to find it.
7912 */
7913 /* What this statement does is to operate in the
7914 ** inverted series along the top edge of the
7915 ** rectangle.
7916 */
7917 pqBapp(&corner_point_reciprocal_expansion,
7918 &hmax,
7919 &conv_k,
7920 &conv_h,
7921 &reciprocal_corner_successor_k,
7922 &reciprocal_corner_successor_h,
7923 &convergent_number);
7924
7925 /* We may have either the left or the right neighbor, but we
7926 ** need the right. This gets messy. We need to invert when finding, including
7927 ** inverting the order.
7928 */
7929 if (rnCompare(&canonical_hmax,
7930 &canonical_kmax,
7931 &reciprocal_corner_successor_h,
7932 &reciprocal_corner_successor_k) == 1)
7933 {
7934 /* We wanted something to the right, but we got it to the left.
7935 ** We need to find the PREDECESSOR (not the successor)
7936 ** in the inverted Farey series.
7937 */
7938
7939 /* printf("REVERSE! (corner point successor)\n"); */
7940 /* Must get the predecessor.
7941 */
7942
7943 siCopy(&canonical_hmax, &temph);
7944 siCopy(&canonical_kmax, &tempk);
7945
7946 rnFareyTraverse(&tempk,
7947 &temph,
7948 &reciprocal_corner_successor_k,
7949 &reciprocal_corner_successor_h,
7950 &hmax,
7951 -1);
7952 siCopy(&temph, &reciprocal_corner_successor_h);
7953 siCopy(&tempk, &reciprocal_corner_successor_k);
7954 }
7955
7956 siDestroy(&temph);
7957 siDestroy(&tempk);
7958 }
7959
7960 siDump(&reciprocal_corner_successor_h, "corner_succ_h");
7961 siDump(&reciprocal_corner_successor_k, "corner_succ_k");
7962 gfHline();
7963
7964 /* Decide, remember, and announce if the term of interest is already in
7965 ** the Farey series of interest. The easiest test for this under two
7966 ** constraints is that both numerator and denominator would be in bounds.
7967 */
7968 if ((siCompare(&h,&hmax) <= 0) && (siCompare(&k, &kmax) <= 0))
7969 {
7970 gfBannerHeading("h_in/k_in IS In Rectangular Farey Series Of Interest", 1);
7971 arg_in_series = TRUE;
7972 }
7973 else
7974 {
7975 gfBannerHeading("h_in/k_in IS NOT In Rectangular Farey Series Of Interest", 1);
7976 }
7977 gfHline();
7978
7979
7980 /* Obtain the two best rational approximations to the number. We want to create
7981 ** two numbers such that the left one is either our number or its left neighbor,
7982 ** and the right one is our numbers's right neighbor, if it has one.
7983 **
7984 ** There are four cases to consider:
7985 **
7986 ** hmax/1 <= h/k
7987 ** In this case, the right neighbor is undefined and the left
7988 ** neighbor is hmax/1.
7989 **
7990 ** hmax/kmax < h/k < hmax/1
7991 ** The neighbors can be found by searching in the "inverted"
7992 ** Farey series.
7993 **
7994 ** h/k = hmax/kmax
7995 ** The left neighbor is h/k, the right is an adjacent point to the
7996 ** corner point.
7997 **
7998 ** 0 <= h/k < hmax/kmax
7999 ** The neighbors can be found by searching in the normal Farey
8000 ** series.
8001 */
8002 if (rnCompare(&hmax, &constant_1, &h, &k) <= 0)
8003 {
8004 /* hmax/1 <= h/k
8005 ** In this case, the right neighbor is undefined and the left
8006 ** neighbor is hmax/1.
8007 */
8008 /* This is a much simpler case. Can just assign.
8009 */
8010 gfBannerHeading("hmax/1 <= h/k", 0);
8011 gfHline();
8012
8013 siCopy(&hmax, &hleft);
8014 siSetToLong(&kleft, 1);
8015 siSetToLong(&hright, 0);
8016 siSetToLong(&kright, 0);
8017
8018 if (arg_in_series)
8019 cur_series_term = 0;
8020 else
8021 cur_series_term = -1;
8022 }
8023 else if (rnCompare(&hmax, &kmax, &h, &k) < 0)
8024 {
8025 /* hmax/kmax < h/k < hmax/1
8026 ** The neighbors can be found by searching in the "inverted"
8027 ** Farey series.
8028 */
8029 pqBapp(&rn_reciprocal_expansion,
8030 &hmax,
8031 &conv_k,
8032 &conv_h,
8033 &neigh_k,
8034 &neigh_h,
8035 &convergent_number);
8036
8037 /* Print out the information generated by the call above
8038 */
8039 gfBannerHeading("hmax/kmax < h/k < hmax/1", 0);
8040 gfHline();
8041 gfBannerHeading("Highest-Order Convergent With q(i)<=N", 0);
8042 gfHline();
8043 sprintf(buf, "p(%d)", convergent_number);
8044 siDump(&conv_h, buf);
8045 sprintf(buf, "q(%d)", convergent_number);
8046 siDump(&conv_k, buf);
8047 gfHline();
8048 gfBannerHeading("Accompanying Intermediate Fraction", 0);
8049 gfHline();
8050 siDump(&neigh_h, "intermediate_h");
8051 siDump(&neigh_k, "intermediate_k");
8052 gfHline();
8053
8054 /* We need to sort the convergent and neighbor back from the cfBapp()
8055 ** function. But there is a bit of a catch. We need to know the
8056 ** correct index to go along with the left one. This gets a bit
8057 ** complicated if the convergent was already in the Farey series.
8058 ** We'll only give the subscript of 0 if the rational number is
8059 ** in the Farey series.
8060 */
8061 if (rnCompare(&conv_h, &conv_k, &neigh_h, &neigh_k) < 0)
8062 {
8063 /* Convergent and neighbor are ascending in order. Can
8064 ** leave exactly as is.
8065 */
8066 siCopy(&conv_h, &hleft);
8067 siCopy(&conv_k, &kleft);
8068 siCopy(&neigh_h, &hright);
8069 siCopy(&neigh_k, &kright);
8070
8071 if (arg_in_series)
8072 cur_series_term = 0;
8073 else
8074 cur_series_term = -1;
8075 }
8076 else
8077 {
8078 /* Convergent and neighbor are descending in order.
8079 ** There are two possibilities. If the number
8080 ** is in the rectangular series, need to traverse.
8081 ** Otherwise, will need to swap, as number is in
8082 ** between.
8083 */
8084 if (arg_in_series)
8085 {
8086 siCopy(&neigh_h, &hleft);
8087 siCopy(&neigh_k, &kleft);
8088 siCopy(&conv_h, &hright);
8089 siCopy(&conv_k, &kright);
8090
8091 rnFareyTraverse(&kright, &hright, &kleft, &hleft, &hmax, -1);
8092
8093 cur_series_term = 0;
8094 }
8095 else
8096 {
8097 siCopy(&neigh_h, &hleft);
8098 siCopy(&neigh_k, &kleft);
8099 siCopy(&conv_h, &hright);
8100 siCopy(&conv_k, &kright);
8101
8102 cur_series_term = -1;
8103 }
8104 }
8105 }
8106 else if (rnCompare(&hmax, &kmax, &h, &k) == 0)
8107 {
8108 /* printf("Reached equality case.\n"); */
8109
8110 /* h/k = hmax/kmax
8111 ** The left neighbor is h/k, the right is an adjacent point to the
8112 ** corner point.
8113 */
8114 /* This is a much simpler case. Can just assign, as we have calculated everything
8115 ** of interest about the corner point already.
8116 */
8117 gfBannerHeading("h_in/k_in == hmax/kmax", 0);
8118 gfHline();
8119 gfBannerHeading("Point To Right Of Corner Point", 0);
8120 gfHline();
8121 siDump(&reciprocal_corner_successor_h, "successor_h");
8122 siDump(&reciprocal_corner_successor_k, "successor_k");
8123 gfHline();
8124
8125 siCopy(&canonical_hmax, &hleft);
8126 siCopy(&canonical_kmax, &kleft);
8127 siCopy(&reciprocal_corner_successor_h, &hright);
8128 siCopy(&reciprocal_corner_successor_k, &kright);
8129
8130 cur_series_term = 0; /* Left member is exactly equal to h/k. */
8131 }
8132 else
8133 {
8134 /* 0 <= h/k < hmax/kmax
8135 ** The neighbors can be found by searching in the normal Farey
8136 ** series.
8137 */
8138 pqBapp(&rn_expansion,
8139 &kmax,
8140 &conv_h,
8141 &conv_k,
8142 &neigh_h,
8143 &neigh_k,
8144 &convergent_number);
8145
8146 /* Print out the information generated by the call above
8147 */
8148 gfBannerHeading("0 <= h_in/k_in < hmax/kmax", 0);
8149 gfHline();
8150 gfBannerHeading("Highest-Order Convergent With q(i)<=N", 0);
8151 gfHline();
8152 sprintf(buf, "p(%d)", convergent_number);
8153 siDump(&conv_h, buf);
8154 sprintf(buf, "q(%d)", convergent_number);
8155 siDump(&conv_k, buf);
8156 gfHline();
8157 gfBannerHeading("Accompanying Intermediate Fraction", 0);
8158 gfHline();
8159 siDump(&neigh_h, "intermediate_h");
8160 siDump(&neigh_k, "intermediate_k");
8161 gfHline();
8162
8163 /* We need to sort the convergent and neighbor back from the cfBapp()
8164 ** function. But there is a bit of a catch. We need to know the
8165 ** correct index to go along with the left one. This gets a bit
8166 ** complicated if the convergent was already in the Farey series.
8167 ** We'll only give the subscript of 0 if the rational number is
8168 ** in the Farey series.
8169 */
8170 if (rnCompare(&conv_h, &conv_k, &neigh_h, &neigh_k) < 0)
8171 {
8172 siCopy(&conv_h, &hleft);
8173 siCopy(&conv_k, &kleft);
8174 siCopy(&neigh_h, &hright);
8175 siCopy(&neigh_k, &kright);
8176
8177 if (arg_in_series)
8178 cur_series_term = 0;
8179 else
8180 cur_series_term = -1;
8181 }
8182 else
8183 {
8184 siCopy(&neigh_h, &hleft);
8185 siCopy(&neigh_k, &kleft);
8186 siCopy(&conv_h, &hright);
8187 siCopy(&conv_k, &kright);
8188
8189 if (arg_in_series)
8190 rnFareyTraverse(&hleft, &kleft, &hright, &kright, &kmax, 1);
8191
8192 if (arg_in_series)
8193 cur_series_term = 0;
8194 else
8195 cur_series_term = -1;
8196 }
8197 }
8198
8199 #if 0
8200 printf ("Past Bap\n");
8201 siDump(&hleft, "hleft");
8202 siDump(&kleft, "kleft");
8203 siDump(&hright, "hright");
8204 siDump(&kright, "kright");
8205 printf("cur_series_term: %d\n", cur_series_term);
8206 #endif
8207
8208 /* At this point we know the neighbors of the corner point, and the neighbors
8209 ** of the h/k. We want to search downward until we exhaust the number of
8210 ** neighbors required or until we hit zero. The complicated thing is that
8211 ** in the rectangular case, there are special cases, especially as we round
8212 ** the corner.
8213 */
8214 while ((hleft->len) && (cur_series_term > -nneighbors))
8215 {
8216 if (rnCompare(&hleft,&kleft,&canonical_hmax,&canonical_kmax)==0)
8217 {
8218 /* The left term is the corner point. Need to "round the corner".
8219 */
8220 siCopy(&hleft, &hright);
8221 siCopy(&kleft, &kright);
8222 siCopy(&normal_corner_predecessor_h, &hleft);
8223 siCopy(&normal_corner_predecessor_k, &kleft);
8224 cur_series_term--;
8225 }
8226 else if (rnCompare(&hleft, &kleft, &hmax, &constant_1) == 0)
8227 {
8228 /* The left term is hmax/1. Need to get the correct right neighbor
8229 ** and go backwards by 1 in the inverted Farey series.
8230 */
8231 siSetToLong(&hright, 1);
8232 siSetToLong(&kright, 0);
8233 rnFareyTraverse(&kright, &hright, &kleft, &hleft, &hmax, 1);
8234 cur_series_term--;
8235 }
8236 else if (rnCompare(&hleft, &kleft, &hmax, &kmax) > 0)
8237 {
8238 /* We are to the right of the corner point. Need to progress
8239 ** in the inverted Farey series.
8240 */
8241 rnFareyTraverse(&kright, &hright, &kleft, &hleft, &hmax, 1);
8242 cur_series_term--;
8243 }
8244 else
8245 {
8246 /* We are to the left of the corner point. Simply go
8247 ** backwards in the Farey series.
8248 */
8249 rnFareyTraverse(&hleft, &kleft, &hright, &kright, &kmax, -1);
8250 cur_series_term--;
8251 }
8252 }
8253
8254 #if 0
8255 printf("Past reverse traversal.\n");
8256 siDump(&hleft, "hleft");
8257 siDump(&kleft, "kleft");
8258 siDump(&hright, "hright");
8259 siDump(&kright, "kright");
8260 printf("cur_series_term: %d\n", cur_series_term);
8261 #endif
8262
8263 /* Now, go forward. If the rational number specified was already in
8264 ** the series, we use the subscript zero, otherwise not.
8265 */
8266 while ((cur_series_term <= nneighbors) && !done)
8267 {
8268 /* Heading */
8269 sprintf(buf, "Rectangular Farey Neighbor Index %d", cur_series_term);
8270 gfBannerHeading(buf, 0);
8271 gfHline();
8272
8273 /* The actual term. */
8274 sprintf(buf, "h(%d)", cur_series_term);
8275 siDump(&hleft, buf);
8276 gfHline();
8277 buf[0] = 'k';
8278 siDump(&kleft, buf);
8279 gfHline();
8280
8281 /* Also present the rational number as a decimal.
8282 */
8283 siCopy(&D, &dap_k);
8284 rnDap(&hleft, &kleft, &dap_h, &dap_k);
8285 sprintf(buf, "DAP_N(%d)", cur_series_term);
8286 siDump(&dap_h, buf);
8287 gfHline();
8288 sprintf(buf, "DAP_D(%d)", cur_series_term);
8289 siDump(&dap_k, buf);
8290 gfHline();
8291
8292 /* Rational difference between the rational number we're trying
8293 ** to approximate and the approximation we have. Canonically, we
8294 ** want a larger approximation to have a positive error, so we
8295 ** define error as (approximation - actual).
8296 */
8297 /* Calculate the difference as a rational number.
8298 */
8299 rnDifference(&hleft, &kleft, &h, &k, &error_h, &error_k);
8300
8301 /* Present it as a rational number. */
8302 sprintf(buf, "error_h(%d)", cur_series_term);
8303 siDump(&error_h, buf);
8304 gfHline();
8305 sprintf(buf, "error_k(%d)", cur_series_term);
8306 siDump(&error_k, buf);
8307 gfHline();
8308
8309 /* Present it as a DAP. */
8310 siCopy(&D, &dap_k);
8311 rnDap(&error_h, &error_k, &dap_h, &dap_k);
8312 sprintf(buf, "ERROR_DAP_N(%d)", cur_series_term);
8313 siDump(&dap_h, buf);
8314 gfHline();
8315 sprintf(buf, "ERROR_DAP_D(%d)", cur_series_term);
8316 siDump(&dap_k, buf);
8317 gfHline();
8318
8319 /* Advance the series counter. We need to skip zero if the
8320 ** number ain't in the series.
8321 */
8322 if (arg_in_series)
8323 {
8324 cur_series_term++;
8325 }
8326 else
8327 {
8328 if (cur_series_term == -1)
8329 cur_series_term = 1;
8330 else
8331 cur_series_term++;
8332 }
8333
8334 /* Advance the rectangular series forward. There are special cases
8335 ** as we "round the corner", plus need to set a "done" flag if can
8336 ** go no further.
8337 */
8338 if (rnCompare(&hleft, &kleft, &hmax, &constant_1) == 0)
8339 {
8340 /* The left term is hmax/1. Can't go any further.
8341 */
8342 done = TRUE;
8343 }
8344 else if (rnCompare(&hright,&kright,&canonical_hmax,&canonical_kmax)==0)
8345 {
8346 /* The right term is the corner point. Need to "round the corner".
8347 */
8348 siCopy(&hright, &hleft);
8349 siCopy(&kright, &kleft);
8350 siCopy(&reciprocal_corner_successor_h, &hright);
8351 siCopy(&reciprocal_corner_successor_k, &kright);
8352 }
8353 else if (rnCompare(&hleft, &kleft, &hmax, &kmax) >= 0)
8354 {
8355 /* We are to the right of the corner point. Need to progress
8356 ** in the inverted Farey series.
8357 */
8358 #if 0
8359 printf("Before.\n");
8360 siDump(&kright, "kright");
8361 siDump(&hright, "hright");
8362 siDump(&kleft, "kleft");
8363 siDump(&hleft, "hleft");
8364 siDump(&hmax, "hmax");
8365 #endif
8366 rnFareyTraverse(&kright, &hright, &kleft, &hleft, &hmax, -1);
8367 #if 0
8368 printf("After.\n");
8369 siDump(&kright, "kright");
8370 siDump(&hright, "hright");
8371 siDump(&kleft, "kleft");
8372 siDump(&hleft, "hleft");
8373 siDump(&hmax, "hmax");
8374 #endif
8375 }
8376 else
8377 {
8378 /* We are left of the corner point. Normal Farey progression.
8379 */
8380 rnFareyTraverse(&hleft, &kleft, &hright, &kright, &kmax, 1);
8381 }
8382 }
8383
8384 /* Destroy CF expansions.
8385 */
8386 if (rn_expansion)
8387 pqDestroy(&rn_expansion);
8388 if (rn_reciprocal_expansion)
8389 pqDestroy(&rn_reciprocal_expansion);
8390 if (corner_point_expansion)
8391 pqDestroy(&corner_point_expansion);
8392 if (corner_point_reciprocal_expansion);
8393 pqDestroy(&corner_point_reciprocal_expansion);
8394
8395 /* Destroy all local variables.
8396 */
8397 siDestroy(&D);
8398 siDestroy(&h);
8399 siDestroy(&k);
8400 siDestroy(&hmax);
8401 siDestroy(&kmax);
8402 siDestroy(&canonical_hmax);
8403 siDestroy(&canonical_kmax);
8404 siDestroy(&normal_corner_predecessor_h);
8405 siDestroy(&normal_corner_predecessor_k);
8406 siDestroy(&reciprocal_corner_successor_h);
8407 siDestroy(&reciprocal_corner_successor_k);
8408 siDestroy(&constant_1);
8409 siDestroy(&constant_0);
8410 siDestroy(&conv_h);
8411 siDestroy(&conv_k);
8412 siDestroy(&neigh_h);
8413 siDestroy(&neigh_k);
8414 siDestroy(&hleft);
8415 siDestroy(&kleft);
8416 siDestroy(&hright);
8417 siDestroy(&kright);
8418 siDestroy(&error_h);
8419 siDestroy(&error_k);
8420 siDestroy(&dap_h);
8421 siDestroy(&dap_k);
8422 siDestroy(&t1);
8423 siDestroy(&t2);
8424 }
8425
8426
8427 /****************************************************************************/
8428 /* cfFndmax(): */
8429 /*--------------------------------------------------------------------------*/
8430 /* DESCRIPTION */
8431 /* Calculates an upper bound between the terms in the Farey series of */
8432 /* a certain order in an interval. */
8433 /****************************************************************************/
8434 void cfFndmax(void)
8435 {
8436 SYNTHETIC_INTEGER
8437 *r1_h, *r1_k,
8438 /* Left interval endpoint.
8439 */
8440 *r2_h, *r2_k,
8441 /* Right interval endpoint.
8442 */
8443 *result_h, *result_k,
8444 /* The fraction in the interval with the
8445 ** smallest denominator.
8446 */
8447 *D,
8448 /* The DAP denominator to be used.
8449 */
8450 *kmax,
8451 /* The maximum denominator (i.e. the order of the
8452 ** Farey series of interest).
8453 */
8454 *kmax_minus_qmin,
8455 /* The order of the Farey series minus the minimum
8456 ** denominator.
8457 */
8458 *error_h, *error_k,
8459 /* The error bound, expressed as a rational
8460 ** number.
8461 */
8462 *dap_N;
8463 /* The DAP numerator.
8464 */
8465
8466 /* Allocate all of our local variables.
8467 */
8468 siCreate(&r1_h);
8469 siCreate(&r1_k);
8470 siCreate(&r2_h);
8471 siCreate(&r2_k);
8472 siCreate(&result_h);
8473 siCreate(&result_k);
8474 siCreate(&D);
8475 siCreate(&kmax);
8476 siCreate(&kmax_minus_qmin);
8477 siCreate(&error_h);
8478 siCreate(&error_k);
8479 siCreate(&dap_N);
8480
8481 /* Record the order of the series in which we are operating.
8482 */
8483 asAssert(par_block.pars[3].canonical_numerator != NULL, __LINE__);
8484 siCopy(&(par_block.pars[3].canonical_numerator), &kmax);
8485
8486 /* If a different DAP denominator is specified, record that.
8487 */
8488 if (par_block.pars[4].canonical_numerator)
8489 {
8490 siCopy(&(par_block.pars[4].canonical_numerator), &D);
8491 }
8492 else
8493 {
8494 siSetToPowerOfTen(&D, DIGITS_PER_LINE * 4);
8495 }
8496
8497 /* State the two interval endpoints as rational numbers, in case
8498 ** one or both are integers.
8499 */
8500 asAssert(par_block.pars[1].canonical_numerator != NULL, __LINE__);
8501 asAssert(par_block.pars[2].canonical_numerator != NULL, __LINE__);
8502 siCopy(&(par_block.pars[1].canonical_numerator), &r1_h);
8503 siCopy(&(par_block.pars[2].canonical_numerator), &r2_h);
8504 if (par_block.pars[1].canonical_denominator)
8505 siCopy(&(par_block.pars[1].canonical_denominator), &r1_k);
8506 else
8507 siSetToLong(&r1_k, 1);
8508 if (par_block.pars[2].canonical_denominator)
8509 siCopy(&(par_block.pars[2].canonical_denominator), &r2_k);
8510 else
8511 siSetToLong(&r2_k, 1);
8512
8513 /* Echo back the parameters for the caller.
8514 */
8515 siDump(&r1_h, "l_h");
8516 gfHline();
8517 siDump(&r1_k, "l_k");
8518 gfHline();
8519 siDump(&r2_h, "r_h");
8520 gfHline();
8521 siDump(&r2_k, "r_k");
8522 gfHline();
8523 siDump(&kmax, "k_max");
8524 gfHline();
8525 siDump(&D, "dap_D");
8526 gfHline();
8527
8528 /* If the parameters for the interval are out of order,
8529 ** declare an error. This probably means that the
8530 ** user of the command is doing something unintended.
8531 */
8532 if (rnCompare(&r1_h, &r1_k, &r2_h, &r2_k) >= 0)
8533 {
8534 asFatal("interval endpoints equal or out of order");
8535 }
8536
8537 /* Be sure that both endpoints are in the Farey series
8538 ** of interest.
8539 */
8540 if ((siCompare(&r1_k, &kmax) > 0) || (siCompare(&r2_k, &kmax) > 0))
8541 {
8542 asFatal("interval endpoints must be in Farey series of interest");
8543 }
8544
8545 /* Do the calculation proper.
8546 */
8547 naMind(&r1_h,
8548 &r1_k,
8549 &r2_h,
8550 &r2_k,
8551 &result_h,
8552 &result_k,
8553 TRUE,
8554 TRUE,
8555 FALSE
8556 );
8557
8558 /* If both endpoints are in the interval, the fraction with
8559 ** the smallest denominator must be in the interval. However,
8560 ** let's just be sure ...
8561 */
8562 asAssert(siCompare(&result_k, &kmax) <= 0, __LINE__);
8563
8564 /* Emit the results from determining the rational number with
8565 ** the smallest denominator.
8566 */
8567 gfBannerHeading("A Rational Number With Smallest Denominator In Interval", 0);
8568 gfHline();
8569 siDump(&result_h, "result_h");
8570 gfHline();
8571 siDump(&result_k, "result_k");
8572 gfHline();
8573
8574 /* Apply the formula in the paper to get the error result
8575 ** as a rational number.
8576 */
8577 siUnrestrictedSubtraction(&kmax, &result_k, &kmax_minus_qmin);
8578
8579 siSetToLong(&error_h, 1);
8580
8581 if (siCompare(&result_k, &kmax_minus_qmin) > 0)
8582 {
8583 SYNTHETIC_INTEGER *temp;
8584
8585 siCreate(&temp);
8586
8587 siCopy(&result_k, &temp);
8588 siUnrestrictedMultiplication(&result_k, &temp, &error_k);
8589
8590 siDestroy(&temp);
8591 }
8592 else
8593 {
8594 siUnrestrictedMultiplication(&result_k, &kmax_minus_qmin, &error_k);
8595 }
8596
8597 /* Print out these results. */
8598 gfBannerHeading("Upper Bound On Distance Between Farey Terms As Rational Number", 0);
8599 gfHline();
8600 siDump(&error_h, "error_ub_h");
8601 gfHline();
8602 siDump(&error_k, "error_up_k");
8603 gfHline();
8604
8605 /* Calculate and display DAP results. */
8606 rnDap(&error_h, &error_k, &dap_N, &D);
8607 gfBannerHeading("Upper Bound On Distance Between Farey Terms As Decimal Approximation", 0);
8608 gfHline();
8609 siDump(&dap_N, "dap_h");
8610 gfHline();
8611 siDump(&D, "dap_k");
8612 gfHline();
8613
8614 /* Destroy the locals.
8615 */
8616 siDestroy(&r1_h);
8617 siDestroy(&r1_k);
8618 siDestroy(&r2_h);
8619 siDestroy(&r2_k);
8620 siDestroy(&result_h);
8621 siDestroy(&result_k);
8622 siDestroy(&D);
8623 siDestroy(&kmax);
8624 siDestroy(&kmax_minus_qmin);
8625 siDestroy(&error_h);
8626 siDestroy(&error_k);
8627 siDestroy(&dap_N);
8628 }
8629
8630
8631 /****************************************************************************/
8632 /* cfFabdmax(): */
8633 /*--------------------------------------------------------------------------*/
8634 /* DESCRIPTION */
8635 /* Calculates an upper bound between the terms in the "rectangular" Farey */
8636 /* series of a certain order (2 constrints) in an interval. */
8637 /****************************************************************************/
8638 void cfFabdmax(void)
8639 {
8640 int case_1_applies = FALSE,
8641 case_2_applies = FALSE,
8642 case_3_applies = FALSE,
8643 /* Boolean variables to record which cases apply.
8644 */
8645 highest = 0;
8646 /* Integer representing the case with the largest error.
8647 ** This should always be the highest-numbered case
8648 ** evaluated. 1=Case I, 2=Case II, 3=Case III.
8649 */
8650
8651 SYNTHETIC_INTEGER
8652 *r1_h, *r1_k,
8653 /* Left interval endpoint.
8654 */
8655 *r2_h, *r2_k,
8656 /* Right interval endpoint.
8657 */
8658 *min_k_h, *min_k_k,
8659 /* The fraction in the interval with the
8660 ** smallest denominator.
8661 */
8662 *D,
8663 /* The DAP denominator to be used.
8664 */
8665 *constant_1h,
8666 /* The constant 1, useful for comparisons.
8667 */
8668 *constant_1k,
8669 /* Second copy of the constant 1, useful for comparisons.
8670 ** The reason for requiring a second copy is that some of the
8671 ** internal functions won't accept two operands which are physically
8672 ** the same.
8673 */
8674 *hmax,
8675 /* The maximum numerator for the "rectangular"
8676 ** Farey series.
8677 */
8678 *kmax,
8679 /* The maximum denominator (i.e. the order of the
8680 ** Farey series of interest).
8681 */
8682 *kmax_minus_qmin,
8683 /* The order of the Farey series minus the minimum
8684 ** denominator.
8685 */
8686 *case_1_error_h,
8687 *case_1_error_k,
8688 /* The error bound from the Case I calculation,
8689 ** expressed as a rational number.
8690 */
8691 *dap_N,
8692 /* The DAP numerator.
8693 */
8694 *case_1_right_h,
8695 *case_1_right_k,
8696 /* The right interval endpoint for application of Case I. Case I
8697 ** does not apply any further than hmax/kmax, so this may be
8698 ** different than the right point of the interval.
8699 */
8700 *case_2_right_limit_h,
8701 *case_2_right_limit_k,
8702 /* The right limit for application of Case II. This is
8703 ** the lesser of 1 and the interval right endpoint.
8704 */
8705 *case_2_error_h,
8706 *case_2_error_k,
8707 /* The error bound from the Case II calculation
8708 ** expressed as a rational number.
8709 */
8710 *case_3_error_h,
8711 *case_3_error_k,
8712 /* The error bound from the Case III calculation
8713 ** expressed as a rational number.
8714 */
8715 *t0, *t1, *t2, *t3, *t4, *t5, *t6, *t7, *t8, *t9;
8716 /* Temporary integers.
8717 */
8718
8719 /* Allocate all of our local variables.
8720 */
8721 siCreate(&r1_h);
8722 siCreate(&r1_k);
8723 siCreate(&r2_h);
8724 siCreate(&r2_k);
8725 siCreate(&min_k_h);
8726 siCreate(&min_k_k);
8727 siCreate(&D);
8728 siCreate(&constant_1h);
8729 siSetToLong(&constant_1h, 1);
8730 siCreate(&constant_1k);
8731 siSetToLong(&constant_1k, 1);
8732 siCreate(&hmax);
8733 siCreate(&kmax);
8734 siCreate(&kmax_minus_qmin);
8735 siCreate(&case_1_error_h);
8736 siCreate(&case_1_error_k);
8737 siCreate(&dap_N);
8738 siCreate(&case_1_right_h);
8739 siCreate(&case_1_right_k);
8740 siCreate(&case_2_right_limit_h);
8741 siCreate(&case_2_right_limit_k);
8742 siCreate(&case_2_error_h);
8743 siCreate(&case_2_error_k);
8744 siCreate(&case_3_error_h);
8745 siCreate(&case_3_error_k);
8746 siCreate(&t0);
8747 siCreate(&t1);
8748 siCreate(&t2);
8749 siCreate(&t3);
8750 siCreate(&t4);
8751 siCreate(&t5);
8752 siCreate(&t6);
8753 siCreate(&t7);
8754 siCreate(&t8);
8755 siCreate(&t9);
8756
8757 /****************************************************************************/
8758 /***************** PROCESS INPUTS *******************************************/
8759 /****************************************************************************/
8760 /* Record the numerator order of the series in which we are
8761 ** operating.
8762 */
8763 asAssert(par_block.pars[3].canonical_numerator != NULL, __LINE__);
8764 siCopy(&(par_block.pars[3].canonical_numerator), &hmax);
8765
8766 /* Record the denominator order of the series in which we are
8767 ** operating.
8768 */
8769 asAssert(par_block.pars[4].canonical_numerator != NULL, __LINE__);
8770 siCopy(&(par_block.pars[4].canonical_numerator), &kmax);
8771
8772 /* If a different DAP denominator is specified, record that.
8773 */
8774 if (par_block.pars[5].canonical_numerator)
8775 {
8776 siCopy(&(par_block.pars[5].canonical_numerator), &D);
8777 }
8778 else
8779 {
8780 siSetToPowerOfTen(&D, DIGITS_PER_LINE * 4);
8781 }
8782
8783 /* State the two interval endpoints as rational numbers, in case
8784 ** one or both are integers.
8785 */
8786 asAssert(par_block.pars[1].canonical_numerator != NULL, __LINE__);
8787 asAssert(par_block.pars[2].canonical_numerator != NULL, __LINE__);
8788 siCopy(&(par_block.pars[1].canonical_numerator), &r1_h);
8789 siCopy(&(par_block.pars[2].canonical_numerator), &r2_h);
8790 if (par_block.pars[1].canonical_denominator)
8791 siCopy(&(par_block.pars[1].canonical_denominator), &r1_k);
8792 else
8793 siSetToLong(&r1_k, 1);
8794 if (par_block.pars[2].canonical_denominator)
8795 siCopy(&(par_block.pars[2].canonical_denominator), &r2_k);
8796 else
8797 siSetToLong(&r2_k, 1);
8798
8799 /* Echo back the parameters for the caller.
8800 */
8801 gfBannerHeading("Input Parameters", 2);
8802 gfHline();
8803 siDump(&r1_h, "l_h");
8804 gfHline();
8805 siDump(&r1_k, "l_k");
8806 gfHline();
8807 siDump(&r2_h, "r_h");
8808 gfHline();
8809 siDump(&r2_k, "r_k");
8810 gfHline();
8811 siDump(&hmax, "h_max");
8812 gfHline();
8813 siDump(&kmax, "k_max");
8814 gfHline();
8815 siDump(&D, "dap_D");
8816 gfHline();
8817
8818 /* If the parameters for the interval are out of order,
8819 ** declare an error. This probably means that the
8820 ** user of the command is doing something unintended.
8821 */
8822 if (rnCompare(&r1_h, &r1_k, &r2_h, &r2_k) >= 0)
8823 {
8824 asFatal("interval endpoints equal or out of order");
8825 }
8826
8827 /* Be sure that both endpoints are in the Farey series
8828 ** of interest.
8829 */
8830 if ((siCompare(&r1_k, &kmax) > 0) || (siCompare(&r2_k, &kmax) > 0)
8831 ||
8832 (siCompare(&r1_h, &hmax) > 0) || (siCompare(&r2_h, &hmax) > 0))
8833 {
8834 asFatal("interval endpoints must be in Farey series of interest");
8835 }
8836
8837 /****************************************************************************/
8838 /***************** DECIDE WHICH CASES APPLY *********************************/
8839 /****************************************************************************/
8840 /* For Case I to apply, the interval must protrude below HMAX/KMAX.
8841 */
8842 if (rnCompare(&r1_h, &r1_k, &hmax, &kmax) < 0)
8843 case_1_applies = TRUE;
8844 else
8845 case_1_applies = FALSE;
8846
8847 /* For Case II to apply, the HMAX/KMAX must be less than 1, and the
8848 ** interval must protrude into [HMAX/KMAX, 1].
8849 */
8850 if ((rnCompare(&hmax, &kmax, &constant_1h, &constant_1k) < 0) &&
8851 (rnCompare(&r2_h, &r2_k, &hmax, &kmax) > 0) &&
8852 (rnCompare(&r1_h, &r1_k, &constant_1h, &constant_1k) < 0))
8853 case_2_applies = TRUE;
8854 else
8855 case_2_applies = FALSE;
8856
8857 /* For Case III to apply, the interval must protrude above 1 and
8858 ** above hmax/kmax.
8859 */
8860 if ((rnCompare(&r2_h, &r2_k, &constant_1h, &constant_1k) > 0)
8861 && (rnCompare(&r2_h, &r2_k, &hmax, &kmax) > 0))
8862 case_3_applies = TRUE;
8863 else
8864 case_3_applies = FALSE;
8865
8866 /* Announce what applies.
8867 */
8868 gfBannerHeading("Case Selection Results", 2);
8869 gfHline();
8870 if (case_1_applies)
8871 printf("Case I applies and will be evaluated.\n");
8872 else
8873 printf("Case I does not apply and will not be evaluated.\n");
8874
8875 if (case_2_applies)
8876 printf("Case II applies and will be evaluated.\n");
8877 else
8878 printf("Case II does not apply and will not be evaluated.\n");
8879
8880 if (case_3_applies)
8881 printf("Case III applies and will be evaluated.\n");
8882 else
8883 printf("Case III does not apply and will not be evaluated.\n");
8884
8885 gfHline();
8886
8887 /* At this point I'm too lazy to go through the Boolean algebra to make
8888 ** sure that for any interval at least one case applies. I *believe* I got
8889 ** it right, but just in case, let's assert that at least one case applies.
8890 */
8891 asAssert(case_1_applies || case_2_applies || case_3_applies, __LINE__);
8892
8893 /****************************************************************************/
8894 /***************** CASE I ***************************************************/
8895 /****************************************************************************/
8896 if (case_1_applies)
8897 {
8898 gfBannerHeading("Start Of Case I Results", 2);
8899 gfHline();
8900
8901 /* Must select an interval over which to operate for Case I. If the
8902 ** right endpoint of the interval is > hmax/kmax, must knock it back
8903 ** to hmax/kmax for evaluation of Case I. For Case I, can only evaluate
8904 ** to the left of hmax/kmax.
8905 */
8906 if (rnCompare(&r2_h, &r2_k, &hmax, &kmax) > 0)
8907 {
8908 siCopy(&hmax, &case_1_right_h);
8909 siCopy(&kmax, &case_1_right_k);
8910 }
8911 else
8912 {
8913 siCopy(&r2_h, &case_1_right_h);
8914 siCopy(&r2_k, &case_1_right_k);
8915 }
8916
8917 gfBannerHeading("Possibly Truncated Interval For Case I", 0);
8918 gfHline();
8919 siDump(&r1_h, "l_h");
8920 gfHline();
8921 siDump(&r1_k, "l_k");
8922 gfHline();
8923 siDump(&case_1_right_h, "r_h");
8924 gfHline();
8925 siDump(&case_1_right_k, "r_k");
8926 gfHline();
8927
8928 /* Do the calculation proper.
8929 */
8930 naMind(&r1_h,
8931 &r1_k,
8932 &case_1_right_h,
8933 &case_1_right_k,
8934 &min_k_h,
8935 &min_k_k,
8936 TRUE,
8937 TRUE,
8938 FALSE
8939 );
8940
8941 /* If both endpoints are in the Farey series, the fraction with
8942 ** the smallest denominator must be in the Farey series. However,
8943 ** let's just be sure ...
8944 */
8945 asAssert(siCompare(&min_k_k, &kmax) <= 0, __LINE__);
8946
8947 /* Emit the results from determining the rational number with
8948 ** the smallest denominator.
8949 */
8950 gfBannerHeading("A Rational Number With Smallest Denominator In Interval", 0);
8951 gfHline();
8952 siDump(&min_k_h, "result_h");
8953 gfHline();
8954 siDump(&min_k_k, "result_k");
8955 gfHline();
8956
8957 /* Apply the formula in the paper to get the error result
8958 ** as a rational number.
8959 */
8960 siUnrestrictedSubtraction(&kmax, &min_k_k, &kmax_minus_qmin);
8961
8962 siSetToLong(&case_1_error_h, 1);
8963
8964 if (siCompare(&min_k_k, &kmax_minus_qmin) > 0)
8965 {
8966 SYNTHETIC_INTEGER *temp;
8967
8968 siCreate(&temp);
8969
8970 siCopy(&min_k_k, &temp);
8971 siUnrestrictedMultiplication(&min_k_k, &temp, &case_1_error_k);
8972
8973 siDestroy(&temp);
8974 }
8975 else
8976 {
8977 siUnrestrictedMultiplication(&min_k_k, &kmax_minus_qmin, &case_1_error_k);
8978 }
8979
8980 /* Print out these results. */
8981 gfBannerHeading("Upper Bound On Distance Between Farey Terms As Rational Number", 0);
8982 gfHline();
8983 siDump(&case_1_error_h, "error_ub_h");
8984 gfHline();
8985 siDump(&case_1_error_k, "error_up_k");
8986 gfHline();
8987
8988 /* Calculate and display DAP results. */
8989 rnDap(&case_1_error_h, &case_1_error_k, &dap_N, &D);
8990 gfBannerHeading("Upper Bound On Distance Between Farey Terms As Decimal Approximation", 0);
8991 gfHline();
8992 siDump(&dap_N, "dap_h");
8993 gfHline();
8994 siDump(&D, "dap_k");
8995 gfHline();
8996 }
8997
8998 /****************************************************************************/
8999 /***************** CASE II **************************************************/
9000 /****************************************************************************/
9001 if (case_2_applies)
9002 {
9003 gfBannerHeading("Start Of Case II Results", 2);
9004 gfHline();
9005
9006 /* If Case II applies, the maximum error will occur at the
9007 ** right limit of the interval or at 1, whichever is less. Can
9008 ** just evaluate the error at this point.
9009 */
9010 if (rnCompare(&r2_h, &r2_k,
9011 &constant_1h, &constant_1k) > 0)
9012 {
9013 siSetToLong(&case_2_right_limit_h, 1);
9014 siSetToLong(&case_2_right_limit_k, 1);
9015 }
9016 else
9017 {
9018 siCopy(&r2_h, &case_2_right_limit_h);
9019 siCopy(&r2_k, &case_2_right_limit_k);
9020 }
9021
9022 /* We know the upper limit to apply. Announce it.
9023 */
9024 gfBannerHeading("Case II Right Limit", 0);
9025 gfHline();
9026 siDump(&case_2_right_limit_h, "case_2_right_h");
9027 gfHline();
9028 siDump(&case_2_right_limit_k, "case_2_right_k");
9029 gfHline();
9030
9031 /* Now evaluate the maximum error per the equations
9032 ** in the TOMS paper, and give that error
9033 ** and the DAP approximation as output.
9034 */
9035 /* Calculate the expression:
9036 ** floor(HMAX/RI)
9037 ** This will require a little fancy footwork.
9038 */
9039 siUnrestrictedMultiplication(&hmax, &case_2_right_limit_k, &t1);
9040 siUnrestrictedDivision(&t1, &case_2_right_limit_h,
9041 &t0, &t2);
9042
9043 /* This quantity should now be in t0. Now square it and add,
9044 ** leave in t1. This is the denominator on the error expression.
9045 */
9046 siCopy(&t0, &t1);
9047 siUnrestrictedMultiplication(&t0, &t1, &t2);
9048 siUnrestrictedAddition(&t0, &t2, &t1);
9049 siCopy(&t1, &case_2_error_k);
9050
9051 /* The numerator is HMAX. */
9052 siCopy(&hmax, &case_2_error_h);
9053
9054 /* Put the rational number in lowest terms.
9055 */
9056 rnCanonize(&case_2_error_h, &case_2_error_k);
9057
9058 /* Print out these results. */
9059 gfBannerHeading("Upper Bound On Distance Between Farey Terms As Rational Number", 0);
9060 gfHline();
9061 siDump(&case_2_error_h, "error_ub_h");
9062 gfHline();
9063 siDump(&case_2_error_k, "error_up_k");
9064 gfHline();
9065
9066 /* Calculate and display DAP results. */
9067 rnDap(&case_2_error_h, &case_2_error_k, &dap_N, &D);
9068 gfBannerHeading("Upper Bound On Distance Between Farey Terms As Decimal Approximation", 0);
9069 gfHline();
9070 siDump(&dap_N, "dap_h");
9071 gfHline();
9072 siDump(&D, "dap_k");
9073 gfHline();
9074 }
9075
9076 /****************************************************************************/
9077 /***************** CASE III *************************************************/
9078 /****************************************************************************/
9079 if (case_3_applies)
9080 {
9081 gfBannerHeading("Start Of Case III Results", 2);
9082 gfHline();
9083
9084 /* Case III is pretty simple. Just 1/(simple_expression).
9085 ** For r_I we should use the upper limit on the interval, if
9086 ** Case III applies at all.
9087 */
9088 /* Calculate the expression:
9089 ** floor(HMAX/RI)
9090 ** This will require a little fancy footwork.
9091 */
9092 siUnrestrictedMultiplication(&hmax, &r2_k, &t1);
9093 siUnrestrictedDivision(&t1, &r2_h,
9094 &t0, &t2);
9095
9096 /* t0 now contains the denominator, and the numerator is 1.
9097 */
9098 siSetToLong(&case_3_error_h, 1);
9099 siCopy(&t0, &case_3_error_k);
9100
9101 /* Present that result and the DAP result.
9102 */
9103 gfBannerHeading("Upper Bound On Distance Between Farey Terms As Rational Number", 0);
9104 gfHline();
9105 siDump(&case_3_error_h, "error_ub_h");
9106 gfHline();
9107 siDump(&case_3_error_k, "error_up_k");
9108 gfHline();
9109
9110 /* Calculate and display DAP results. */
9111 rnDap(&case_3_error_h, &case_3_error_k, &dap_N, &D);
9112 gfBannerHeading("Upper Bound On Distance Between Farey Terms As Decimal Approximation", 0);
9113 gfHline();
9114 siDump(&dap_N, "dap_h");
9115 gfHline();
9116 siDump(&D, "dap_k");
9117 gfHline();
9118 }
9119
9120 /****************************************************************************/
9121 /***************** CUMULATIVE RESULTS ***************************************/
9122 /****************************************************************************/
9123 /* At this point, can compare the results to see which of the active
9124 ** cases generated the largest error. It should always be the
9125 ** highest-numbered case, but can compare anyway.
9126 */
9127 gfBannerHeading("Start Of Cumulative Results", 2);
9128 gfHline();
9129 siSetToLong(&t0, 0);
9130 siSetToLong(&t1, 0);
9131
9132 if (case_1_applies)
9133 {
9134 siCopy(&case_1_error_h, &t0);
9135 siCopy(&case_1_error_k, &t1);
9136 highest = 1;
9137 }
9138 else if (case_2_applies)
9139 {
9140 siCopy(&case_2_error_h, &t0);
9141 siCopy(&case_2_error_k, &t1);
9142 highest = 2;
9143 }
9144 else if (case_3_applies)
9145 {
9146 siCopy(&case_3_error_h, &t0);
9147 siCopy(&case_3_error_k, &t1);
9148 highest = 3;
9149 }
9150 else
9151 {
9152 asAssert(0, __LINE__);
9153 }
9154
9155 /* OK, one case has been copied to t0/t1. Compare
9156 ** to see if there is a larger one.
9157 */
9158 if (case_2_applies)
9159 {
9160 if (rnCompare(&case_2_error_h, &case_2_error_k,
9161 &t0, &t1) > 0)
9162 {
9163 siCopy(&case_2_error_h, &t0);
9164 siCopy(&case_2_error_k, &t1);
9165 highest = 2;
9166 }
9167 }
9168 if (case_3_applies)
9169 {
9170 if (rnCompare(&case_3_error_h, &case_3_error_k,
9171 &t0, &t1) > 0)
9172 {
9173 siCopy(&case_3_error_h, &t0);
9174 siCopy(&case_3_error_k, &t1);
9175 highest = 3;
9176 }
9177 }
9178
9179 /* Announce the results.
9180 */
9181 {
9182 char buf1[100], buf2[100];
9183
9184 switch (highest)
9185 {
9186 case 1 : strcpy(buf1, "I"); break;
9187 case 2 : strcpy(buf1, "II"); break;
9188 case 3 : strcpy(buf1, "III"); break;
9189 default: strcpy(buf1, "???"); break;
9190 }
9191
9192 sprintf(buf2, "Largest Error (Case %s)", buf1);
9193
9194 gfBannerHeading(buf2, 2);
9195 gfHline();
9196 }
9197
9198 /* Present that result and the DAP result.
9199 */
9200 gfBannerHeading("Upper Bound On Distance Between Farey Terms As Rational Number", 0);
9201 gfHline();
9202 siDump(&t0, "error_ub_h");
9203 gfHline();
9204 siDump(&t1, "error_up_k");
9205 gfHline();
9206
9207 /* Calculate and display DAP results. */
9208 rnDap(&t0, &t1, &dap_N, &D);
9209 gfBannerHeading("Upper Bound On Distance Between Farey Terms As Decimal Approximation", 0);
9210 gfHline();
9211 siDump(&dap_N, "dap_h");
9212 gfHline();
9213 siDump(&D, "dap_k");
9214 gfHline();
9215
9216 /* Destroy the locals.
9217 */
9218 siDestroy(&r1_h);
9219 siDestroy(&r1_k);
9220 siDestroy(&r2_h);
9221 siDestroy(&r2_k);
9222 siDestroy(&min_k_h);
9223 siDestroy(&min_k_k);
9224 siDestroy(&D);
9225 siDestroy(&constant_1h);
9226 siDestroy(&constant_1k);
9227 siDestroy(&hmax);
9228 siDestroy(&kmax);
9229 siDestroy(&kmax_minus_qmin);
9230 siDestroy(&case_1_error_h);
9231 siDestroy(&case_1_error_k);
9232 siDestroy(&dap_N);
9233 siDestroy(&case_1_right_h);
9234 siDestroy(&case_1_right_k);
9235 siDestroy(&case_2_right_limit_h);
9236 siDestroy(&case_2_right_limit_k);
9237 siDestroy(&case_2_error_h);
9238 siDestroy(&case_2_error_k);
9239 siDestroy(&case_3_error_h);
9240 siDestroy(&case_3_error_k);
9241 siDestroy(&t0);
9242 siDestroy(&t1);
9243 siDestroy(&t2);
9244 siDestroy(&t3);
9245 siDestroy(&t4);
9246 siDestroy(&t5);
9247 siDestroy(&t6);
9248 siDestroy(&t7);
9249 siDestroy(&t8);
9250 siDestroy(&t9);
9251 }
9252
9253
9254 /****************************************************************************/
9255 /****************************************************************************/
9256 /********** I N P U T P A R A M E T E R F U N C T I O N S *********/
9257 /****************************************************************************/
9258 /****************************************************************************/
9259 /* This section is reserved for functions which process the input parameters
9260 ** and get them properly arranged in a data structure for the program
9261 ** internals to process.
9262 */
9263
9264
9265 /* A simple structure to implement a linked list of strings. This is used
9266 ** to hold the tokens of both the command-line or the processing from the
9267 ** standard input.
9268 */
9269 struct ipSimpleStringLlNodeStruct
9270 {
9271 char *s;
9272 /* Dynamically allocated string.
9273 */
9274 struct ipSimpleStringLlNodeStruct *next;
9275 /* Link to next, or NULL if end of list.
9276 */
9277 };
9278
9279
9280 /****************************************************************************/
9281 /* ipBufferStandardInputStream(): */
9282 /*--------------------------------------------------------------------------*/
9283 /* DESCRIPTION */
9284 /* Buffers the entire standard input stream into an array of characters, */
9285 /* up to a maximum of STDIN_MAX_CHARS. */
9286 /* */
9287 /* OUTPUTS */
9288 /* <-- : Pointer to allocated array, terminated with '\0'. Should */
9289 /* be deallocated at some point. */
9290 /****************************************************************************/
9291 char *ipBufferStandardInputStream(void)
9292 {
9293 char *rv;
9294 char c;
9295 unsigned i;
9296
9297 rv = maMalloc(((unsigned long)(sizeof(char))) * (STDIN_MAX_CHARS + 1));
9298
9299 i = 0;
9300 rv[0] = '\0';
9301
9302 while ((c = getchar()) != EOF)
9303 {
9304 if (i >= STDIN_MAX_CHARS)
9305 {
9306 asFatal("standard input exceeds 32000 characters");
9307 }
9308
9309 rv[i] = c;
9310 rv[i+1] = '\0';
9311 i++;
9312 }
9313
9314 return(rv);
9315 }
9316
9317
9318 /****************************************************************************/
9319 /* ipTranslateStdinToRawTokens(): */
9320 /*--------------------------------------------------------------------------*/
9321 /* DESCRIPTION */
9322 /* Translates from the array of characters buffered from the standard */
9323 /* input to a linked list of raw tokens. By "raw" I mean that the */
9324 /* possibility of concatenation has not been handled. */
9325 /****************************************************************************/
9326 void ipTranslateStdinToRawTokens(
9327 char *stdin_array,
9328 struct ipSimpleStringLlNodeStruct **ptr_to_callers_ptr
9329 )
9330 {
9331 /* Make sure the caller isn't doing anything silly.
9332 */
9333 asAssert(stdin_array != NULL, __LINE__);
9334 asAssert(ptr_to_callers_ptr != NULL, __LINE__);
9335
9336 /* Scan the buffer for unexpected characters that can't be handled.
9337 ** If one exists, generate a fatal error and message.
9338 */
9339 {
9340 char *p;
9341 unsigned i;
9342 char buf[100];
9343
9344 i = 0;
9345 p = stdin_array;
9346
9347 while (*p)
9348 {
9349 if (!ddIsInfoChar(*p) && !ddIsDiscardChar(*p) && !ddIsWhitespaceChar(*p))
9350 {
9351 sprintf( buf,
9352 "illegal char in stdin at offset=%u, val=%u, char=%c",
9353 i,
9354 (int)(*p),
9355 (unsigned)(*p));
9356 asFatal(buf);
9357 }
9358 i++;
9359 p++;
9360 }
9361 }
9362
9363
9364 /* Convert the entire buffer to lower case.
9365 */
9366 {
9367 unsigned len = strlen(stdin_array);
9368 unsigned i;
9369
9370 for (i=0; i<len; i++)
9371 stdin_array[i] = ddCharToLower(stdin_array[i]);
9372 }
9373
9374 /* Delete all the characters from the buffer that are the "ignore"
9375 ** characters.
9376 */
9377 {
9378 char *srcptr, *dstptr;
9379
9380 srcptr = dstptr = stdin_array;
9381
9382 while (*srcptr)
9383 {
9384 if (!ddIsDiscardChar(*srcptr))
9385 {
9386 *dstptr = *srcptr;
9387 dstptr++;
9388 }
9389
9390 srcptr++;
9391 }
9392
9393 *dstptr = '\0';
9394 }
9395
9396
9397 /* Break the stream into tokens, ignoring any concatenation. What will be
9398 ** formed is a linked list.
9399 */
9400 {
9401 char *srcptr;
9402 struct ipSimpleStringLlNodeStruct **insert_point = NULL;
9403 struct ipSimpleStringLlNodeStruct *newnode;
9404
9405 /* Set up to build a linked list. */
9406 *ptr_to_callers_ptr = NULL;
9407
9408 srcptr = stdin_array;
9409
9410 /* Advance pointer past any initial whitespace. */
9411 while ((*srcptr) && (ddIsWhitespaceChar(*srcptr)))
9412 srcptr++;
9413
9414 /* While we're not at the end, get us a new token and put it
9415 ** into the linked list.
9416 */
9417 while (*srcptr)
9418 {
9419 unsigned memblocklen;
9420 char *snipleftptr;
9421 unsigned i;
9422
9423 /* Snapshot the start of the token so we don't forget it. */
9424 snipleftptr = srcptr;
9425
9426 /* Advance the source pointer so that it points one past the
9427 ** last character of the token.
9428 */
9429 while (ddIsInfoChar(*srcptr))
9430 srcptr++;
9431
9432 /* Calculate the size of the memory block to hold the token's string
9433 ** representation. We must add one to include the '\0' terminator.
9434 */
9435 memblocklen = srcptr - snipleftptr + 1;
9436
9437 /* Allocate a new node to be put into the linked list. */
9438 newnode = maMalloc(sizeof(struct ipSimpleStringLlNodeStruct));
9439
9440 /* For now, NEXT points nowhere. */
9441 newnode->next = NULL;
9442
9443 /* Allocate the space to hold the string for the token. */
9444 newnode->s = maMalloc(memblocklen * sizeof(char));
9445
9446 /* Copy the token, not including a terminator. */
9447 for (i=0; i<(memblocklen - 1); i++)
9448 newnode->s[i] = snipleftptr[i];
9449
9450 /* Insert the string terminator. */
9451 newnode->s[memblocklen-1] = '\0';
9452
9453 /* Insert the newly created node into the linked list. There
9454 ** are two different ways to do it, depending on if this is our
9455 ** first element or not.
9456 */
9457 if (*ptr_to_callers_ptr)
9458 {
9459 /* Head of list is not NULL. This is not our first element. */
9460 *insert_point = newnode;
9461 insert_point = &(newnode->next);
9462 }
9463 else
9464 {
9465 /* Head of list is NULL. This is our first element. */
9466 *ptr_to_callers_ptr = newnode;
9467 insert_point = &(newnode->next);
9468 }
9469
9470 /* Advance pointer past any whitespace until next token or end of string. */
9471 while ((*srcptr) && (ddIsWhitespaceChar(*srcptr)))
9472 srcptr++;
9473 } /* End while() */
9474 } /* End block. */
9475 } /* End function. */
9476
9477
9478 /****************************************************************************/
9479 /* ipPackCmdLineArgsIntoLinkedList(): */
9480 /*--------------------------------------------------------------------------*/
9481 /* DESCRIPTION */
9482 /* Translates the command-line arguments into a linked list of strings. */
9483 /* The first argument (the program name) is omitted. */
9484 /****************************************************************************/
9485 void ipPackCmdLineArgsIntoLinkedList(
9486 int argc,
9487 char * argv[],
9488 struct ipSimpleStringLlNodeStruct **ptr_to_callers_ptr)
9489 {
9490 int i;
9491 struct ipSimpleStringLlNodeStruct *newnode;
9492 unsigned len;
9493 struct ipSimpleStringLlNodeStruct **insert_point = NULL;
9494
9495 /* Be sure that the caller isn't doing anything silly. */
9496 asAssert(argv != NULL, __LINE__);
9497 asAssert(ptr_to_callers_ptr != NULL, __LINE__);
9498
9499 /* NULL out the caller's pointer, consistent with an empty linked list. */
9500 *ptr_to_callers_ptr = NULL;
9501
9502 /* For each command-line argument, add it to the linked list. Slightly
9503 ** different actions are necessary if the linked list is empty versus
9504 ** if it has at least one element.
9505 */
9506
9507 for (i=1; i<argc; i++)
9508 {
9509 /* Figure out how long the string will be. */
9510 len = strlen(argv[i]);
9511
9512 /* Allocate the memory for the new node. */
9513 newnode = maMalloc(sizeof(struct ipSimpleStringLlNodeStruct));
9514
9515 /* For now, the node points nowhere. */
9516 newnode->next = NULL;
9517
9518 /* Allocate space for the string. */
9519 newnode->s = maMalloc((len + 1) * sizeof(char));
9520
9521 /* Copy from the argument list to the string. */
9522 strcpy(newnode->s, argv[i]);
9523
9524 /* Insert the node into the list. */
9525 if (*ptr_to_callers_ptr)
9526 {
9527 /* Head of list is not NULL. This is not our first element. */
9528 *insert_point = newnode;
9529 insert_point = &(newnode->next);
9530 }
9531 else
9532 {
9533 /* Head of list is NULL. This is our first element. */
9534 *ptr_to_callers_ptr = newnode;
9535 insert_point = &(newnode->next);
9536 }
9537 }
9538
9539 /* printf("Into check for illegals.\n"); */
9540 /* There are two tasks still to be performed to make the treatment
9541 ** of command-line args consistent with the treatment of the stdin
9542 ** stream. First, check for illegal characters. Second, remove the
9543 ** "ignore" characters.
9544 */
9545 {
9546 struct ipSimpleStringLlNodeStruct *p;
9547 unsigned i;
9548
9549 p = *ptr_to_callers_ptr;
9550 i = 1;
9551
9552 while(p)
9553 {
9554 char *cp;
9555
9556 cp = p->s;
9557
9558 while(*cp)
9559 {
9560 char buf[100];
9561
9562 if (ddIsWhitespaceChar(*cp) || (!ddIsInfoChar(*cp) && !ddIsDiscardChar(*cp)))
9563 {
9564 sprintf( buf,
9565 "illegal char in cmdline arg #%u, val=%u, char=%c",
9566 i,
9567 (unsigned)(*cp),
9568 *cp);
9569 asFatal(buf);
9570 }
9571
9572 cp++;
9573 }
9574
9575 i++;
9576 p = p->next;
9577 }
9578 }
9579
9580 /* printf("into discards\n"); */
9581 /* Now, remove any of the "discard" characters. */
9582 {
9583 struct ipSimpleStringLlNodeStruct *p;
9584
9585 p = *ptr_to_callers_ptr;
9586
9587 while(p)
9588 {
9589 char *srcptr, *dstptr;
9590
9591 srcptr = dstptr = p->s;
9592
9593 while (*srcptr)
9594 {
9595 *srcptr = ddCharToLower(*srcptr);
9596
9597 if (!ddIsDiscardChar(*srcptr))
9598 {
9599 *dstptr = *srcptr;
9600 dstptr++;
9601 }
9602
9603 srcptr++;
9604 }
9605
9606 *dstptr = '\0';
9607
9608 p = p->next;
9609 }
9610 }
9611 }
9612
9613
9614 /****************************************************************************/
9615 /* ipProcessLinkedListParameterContinuationCharacters(): */
9616 /*--------------------------------------------------------------------------*/
9617 /* DESCRIPTION */
9618 /* Processes the continuation characters. If any token ends with a '\', */
9619 /* combines it with next token. */
9620 /****************************************************************************/
9621 void ipProcessLinkedListParameterContinuationCharacters
9622 (struct ipSimpleStringLlNodeStruct **ptr_to_callers_ptr)
9623 {
9624 struct ipSimpleStringLlNodeStruct **p, *removed_node;
9625 unsigned len_a, len_b;
9626
9627 /* Be sure that the caller isn't doing anything silly. */
9628 asAssert(ptr_to_callers_ptr != NULL, __LINE__);
9629
9630 p = ptr_to_callers_ptr;
9631
9632 while (*p)
9633 {
9634 asAssert((*p)->s != NULL, __LINE__);
9635
9636 len_a = strlen((*p)->s);
9637 if (len_a)
9638 {
9639 if ((*p)->s[len_a-1] == '\\')
9640 {
9641 /* Final character of this token is a backslash. Must concatenate it with
9642 ** next token.
9643 */
9644 if (!((*p)->next))
9645 asFatal("final parameter ends in continuation character ('\\')");
9646
9647 removed_node = (*p)->next;
9648
9649 (*p)->next = removed_node->next;
9650
9651 len_b = strlen(removed_node->s);
9652
9653 (*p)->s = maRealloc((*p)->s, (len_a + len_b) * sizeof(char));
9654
9655 (*p)->s[len_a-1] = '\0';
9656 /* Trash the terminating continuation character. This also
9657 ** makes the Realloc() just above valid, don't need to add
9658 ** "+1", because have shorted string containing termination
9659 ** character by 1.
9660 */
9661
9662 strcat((*p)->s, removed_node->s);
9663
9664 maFree(removed_node->s);
9665
9666 maFree(removed_node);
9667 }
9668 }
9669
9670 len_a = strlen((*p)->s);
9671 if (len_a)
9672 {
9673 if ((*p)->s[len_a-1] != '\\')
9674 p = &((*p)->next);
9675 }
9676 }
9677 }
9678
9679
9680 /****************************************************************************/
9681 /* ipParseAsRationalNumber(): */
9682 /*--------------------------------------------------------------------------*/
9683 /* DESCRIPTION */
9684 /* Attempts to parse a string (subscript in par_block passed) as a */
9685 /* rational number. Looks for errors, fills in the raw values, converts */
9686 /* to canonical form, and fills in the ftype fields. */
9687 /****************************************************************************/
9688 void ipParseAsRationalNumber(int i)
9689 {
9690 SYNTHETIC_INTEGER *constant_1 = NULL,
9691 *h_raw = NULL,
9692 *k_raw = NULL,
9693 *h_canonical = NULL,
9694 *k_canonical = NULL,
9695 *si_temp1 = NULL,
9696 *si_temp2 = NULL,
9697 *si_temp3 = NULL,
9698 *si_temp4 = NULL;
9699 int is_neg = FALSE;
9700 char *s, *t;
9701
9702 /* Make sure the caller isn't doing anything silly. */
9703 asAssert(i >= 0, __LINE__);
9704 asAssert(i < MAX_CMDLINE_PARS, __LINE__);
9705
9706 /* Allocate all of the temporary synthetic integers that we'll
9707 ** use, and assign the constant 1.
9708 */
9709 siCreate(&constant_1);
9710 siSetToLong(&constant_1, 1);
9711 siCreate(&h_raw);
9712 siCreate(&k_raw);
9713 siCreate(&h_canonical);
9714 siCreate(&k_canonical);
9715 siCreate(&si_temp1);
9716 siCreate(&si_temp2);
9717 siCreate(&si_temp3);
9718 siCreate(&si_temp4);
9719
9720 /* There are two parsing cases to cover. Either the user is trying to
9721 ** specify a rational number as integer/integer, or as a floating point
9722 ** number. The two cases can be differentiated by the presence of a
9723 ** forward slash in the input.
9724 */
9725 if (ddStringContains(par_block.pars[i].orig_string, "/"))
9726 {
9727 /* Integer/Integer Case */
9728 /* Parse off any leading minus sign. */
9729
9730 /* Form a pointer to the start of the string. */
9731 s = par_block.pars[i].orig_string;
9732
9733 /* Process any leading '-' sign. */
9734 if (*s == '-')
9735 {
9736 s++;
9737 is_neg = TRUE;
9738 }
9739
9740 /* Parse off a group of digits, up to any non-digit character.
9741 ** We'll come to rest one past the last digit.
9742 */
9743 t = s;
9744 while (*t && ddIsDigit(*t))
9745 {
9746 t++;
9747 }
9748
9749 /* Guard against the case where we could find no digits.
9750 */
9751 if (s == t)
9752 {
9753 asFatal("missing numerator in rational number");
9754 }
9755
9756 /* Guard against the case where we have a leading zero on a string
9757 ** of digits that contains more than a zero.
9758 */
9759 if ((*s == '0') && ((t-s) > 1))
9760 {
9761 asFatal("leading zeros on non-zero integers not allowed");
9762 }
9763
9764 /* If we've made it this far, we have a contiguous group of digits,
9765 ** with no leading zeroes. Process it.
9766 */
9767 if (*s=='0')
9768 {
9769 /* Our digit was zero. */
9770 siSetToLong(&h_raw, 0);
9771 if (is_neg)
9772 asFatal("can't negate zero");
9773 }
9774 else if ((t-s) > INPUT_INTEGER_MAX_DIGITS)
9775 {
9776 asFatal("numerator too long");
9777 }
9778 else
9779 {
9780 char *u, *v;
9781
9782 u = s;
9783 v = &(h_raw->digits[0]);
9784 while (u != t)
9785 {
9786 *v = *u;
9787 u++;
9788 v++;
9789 }
9790 *v = '\0';
9791 ddStringReverse(h_raw->digits);
9792 h_raw->len = strlen(h_raw->digits);
9793 h_raw->neg = is_neg;
9794 }
9795
9796 /* OK, the first group of digits is done. Now advance
9797 ** past the slash.
9798 */
9799 s = t;
9800 if (*s != '/')
9801 asFatal("missing '/' in rational number");
9802 s++;
9803
9804 /* Guard against case of being at end of string. */
9805 if (!(*s))
9806 asFatal("missing denominator in rational number");
9807
9808 /* Be sure nothing else left in the string except digits.
9809 */
9810 if (!ddStringContainsOnly(s, "0123456789"))
9811 asFatal("unexpected non-digit character in rational number denominator");
9812
9813 /* As before, parse past digits, copy, etc., except that no
9814 ** '-' sign is allowed.
9815 */
9816 /* Parse off a group of digits, up to any non-digit character.
9817 ** We'll come to rest one past the last digit.
9818 */
9819 t = s;
9820 while (*t && ddIsDigit(*t))
9821 {
9822 t++;
9823 }
9824
9825 /* Guard against the case where we could find no digits.
9826 */
9827 if (s == t)
9828 {
9829 asFatal("missing denominator in rational number");
9830 }
9831
9832 /* Guard against the case where we have a leading zero on a string
9833 ** of digits that contains more than a zero.
9834 */
9835 if ((*s == '0') && ((t-s) > 1))
9836 {
9837 asFatal("leading zeros on non-zero integers not allowed");
9838 }
9839
9840 /* If we've made it this far, we have a contiguous group of digits,
9841 ** with no deading zeroes. Process it.
9842 */
9843 if (*s=='0')
9844 {
9845 /* Our digit was zero. */
9846 asFatal("zero denominator in rational number");
9847 }
9848 else if ((t-s) > INPUT_INTEGER_MAX_DIGITS)
9849 {
9850 asFatal("denominator too long");
9851 }
9852 else
9853 {
9854 char *u, *v;
9855
9856 u = s;
9857 v = &(k_raw->digits[0]);
9858 while (u != t)
9859 {
9860 *v = *u;
9861 u++;
9862 v++;
9863 }
9864 *v = '\0';
9865 ddStringReverse(k_raw->digits);
9866 k_raw->len = strlen(k_raw->digits);
9867 }
9868 #if 0
9869 siDump(&h_raw, "h_raw");
9870 siDump(&k_raw, "k_raw");
9871 #endif
9872 }
9873 else
9874 {
9875 char *before_decimal = NULL;
9876 int decimal_found = FALSE;
9877 char *after_decimal = NULL;
9878 int e_found = FALSE;
9879 char e_sign = '+';
9880 char *exponent_mag = NULL;
9881 char *concat_mantissa = NULL;
9882 int effective_exponent = 0;
9883
9884 /* Floating-Point Constant Case */
9885 /* We've identified this number as a floating point constant of
9886 ** some kind. Parse it out. It will be re-expressed as a rational
9887 ** number.
9888 */
9889 s = par_block.pars[i].orig_string;
9890
9891 /* Process any leading '-' sign. */
9892 if (*s == '-')
9893 {
9894 s++;
9895 is_neg = TRUE;
9896 }
9897
9898 /* Parse off the first group of digits. Keep parsing until hit a
9899 ** non-digit. Form into a string.
9900 */
9901 /* Parse off a group of digits, up to any non-digit character.
9902 ** We'll come to rest one past the last digit.
9903 */
9904 t = s;
9905 while (*t && ddIsDigit(*t))
9906 {
9907 t++;
9908 }
9909
9910 if (t != s)
9911 {
9912 int i;
9913
9914 before_decimal = maMalloc((sizeof(char)) * (t-s+1));
9915
9916 for (i=0; i<(t-s); i++)
9917 before_decimal[i] = s[i];
9918
9919 before_decimal[i] = '\0';
9920 }
9921 else
9922 {
9923 before_decimal = maMalloc((sizeof(char)) * (1));
9924 strcpy(before_decimal, "");
9925 }
9926
9927 s = t;
9928
9929 /* Now, rip off any decimal point that exists. */
9930 if (*s == '.')
9931 {
9932 decimal_found = TRUE;
9933 s++;
9934 t++;
9935 }
9936
9937 /* Rip off any remaining group of digits before
9938 ** the 'e' character.
9939 */
9940 while (*t && ddIsDigit(*t))
9941 {
9942 t++;
9943 }
9944
9945 if (t != s)
9946 {
9947 int i;
9948
9949 after_decimal = maMalloc((sizeof(char)) * (t-s+1));
9950
9951 for (i=0; i<(t-s); i++)
9952 after_decimal[i] = s[i];
9953
9954 after_decimal[i] = '\0';
9955 }
9956 else
9957 {
9958 after_decimal = maMalloc((sizeof(char)) * (1));
9959 strcpy(after_decimal, "");
9960 }
9961
9962 s = t;
9963
9964 /* Rip off any e-character, should it exist. */
9965 if (*s == 'e')
9966 {
9967 e_found = TRUE;
9968 s++;
9969 t++;
9970 }
9971
9972 /* Rip any sign off the e, should it exist. */
9973 if ((*s == '+') || (*s == '-'))
9974 {
9975 e_sign = *s;
9976 s++;
9977 t++;
9978 }
9979
9980 /* Finally, rip off any final digits, which are
9981 ** the exponent.
9982 */
9983 while (*t && ddIsDigit(*t))
9984 {
9985 t++;
9986 }
9987
9988 if (t != s)
9989 {
9990 int i;
9991
9992 exponent_mag = maMalloc((sizeof(char)) * (t-s+1));
9993
9994 for (i=0; i<(t-s); i++)
9995 exponent_mag[i] = s[i];
9996
9997 exponent_mag[i] = '\0';
9998 }
9999 else
10000 {
10001 exponent_mag = maMalloc((sizeof(char)) * (1));
10002 strcpy(exponent_mag, "");
10003 }
10004
10005 s = t;
10006
10007 /* If we're not at the end of the string, something
10008 ** is wrong.
10009 */
10010 if (*s)
10011 asFatal("unable to parse floating-point number");
10012
10013 /* If "e" was specified but no exponent was captured, this is an error.
10014 */
10015 if (!strlen(exponent_mag) && e_found)
10016 asFatal("missing floating-point exponent digits");
10017
10018 /* Parse the exponent into a number. The exponent is about the
10019 ** only place where leading zeros are allowed. Start off believing
10020 ** the exponent is zero.
10021 */
10022 effective_exponent = 0;
10023 while (exponent_mag[0] == '0')
10024 ddStringDeleteLeadingChar(exponent_mag);
10025
10026 if (strlen(exponent_mag) > 3)
10027 asFatal("floating-point exponent magnitude too large");
10028
10029 if (strlen(exponent_mag))
10030 sscanf(exponent_mag, "%d", &effective_exponent);
10031
10032 if (e_sign == '-')
10033 effective_exponent = -effective_exponent;
10034
10035 /* If there was a decimal point but no digits before or no digits
10036 ** after, this is an error.
10037 */
10038 if (decimal_found && (!strlen(before_decimal) || !strlen(after_decimal)))
10039 asFatal("improper floating-point mantissa");
10040
10041 /* If there were no digits at all, this is an error */
10042 if (!strlen(before_decimal) && !strlen(after_decimal))
10043 asFatal("missing floating-point mantissa");
10044
10045 /* Concatenate the before decimal and after decimal
10046 ** parts.
10047 */
10048 concat_mantissa = maMalloc((sizeof(char)) * (strlen(before_decimal) + strlen(after_decimal) + 1));
10049 strcpy(concat_mantissa, before_decimal);
10050 strcat(concat_mantissa, after_decimal);
10051
10052 /* Delete all leading zeroes. */
10053 while (concat_mantissa[0] == '0')
10054 ddStringDeleteLeadingChar(concat_mantissa);
10055
10056 /* If we've depleted the concatenated string, then
10057 ** there are two possibilities. Either the number is zero,
10058 ** or there is an error of a '-' sign was specified.
10059 */
10060 if (!strlen(concat_mantissa))
10061 {
10062 if (is_neg)
10063 {
10064 asFatal("zero cannot be negated");
10065 }
10066 else
10067 {
10068 siSetToLong(&h_raw, 0);
10069 siSetToLong(&k_raw, 1);
10070 goto float_parsing_end;
10071 }
10072 }
10073
10074 /* We start off believing that the exponent is the one given in the
10075 ** exponent field. But we also need to adjust downward for the
10076 ** number of digits after the decimal point.
10077 */
10078 effective_exponent -= strlen(after_decimal);
10079
10080 /* We are now poised to resolve what we have into a
10081 ** rational number. Assign the concatenated string
10082 ** to h_raw, and 1 to k_raw. For each negative
10083 ** count in the exponent, we multiply the denominator
10084 ** by 10. For each postive count in the exponent,
10085 ** we multiply the numerator by 10.
10086 */
10087 if (strlen(concat_mantissa) > INPUT_INTEGER_MAX_DIGITS)
10088 {
10089 asFatal("floating-point mantissa too long");
10090 }
10091
10092 ddStringReverse(concat_mantissa);
10093 strcpy(h_raw->digits, concat_mantissa);
10094 h_raw->len = strlen(h_raw->digits);
10095 h_raw->neg = is_neg;
10096
10097 siSetToLong(&k_raw, 1);
10098 siSetToLong(&si_temp1, 10);
10099
10100 while (effective_exponent)
10101 {
10102 if (effective_exponent < 0)
10103 {
10104 siUnrestrictedMultiplication(&k_raw, &si_temp1, &si_temp2);
10105 if (si_temp2->nan || (si_temp2->len > INPUT_INTEGER_MAX_DIGITS))
10106 asFatal("floating-point number magnitude too small");
10107 siCopy(&si_temp2, &k_raw);
10108 effective_exponent++;
10109 }
10110 else
10111 {
10112 siUnrestrictedMultiplication(&h_raw, &si_temp1, &si_temp2);
10113 if (si_temp2->nan || (si_temp2->len > INPUT_INTEGER_MAX_DIGITS))
10114 asFatal("floating-point number magnitude too large");
10115 siCopy(&si_temp2, &h_raw);
10116 effective_exponent--;
10117 }
10118 }
10119
10120 float_parsing_end: ;
10121 /* Print out information for debugging. */
10122 #if 0
10123 if (before_decimal)
10124 printf("before_decimal: %s\n", before_decimal);
10125 else
10126 printf("before_decimal: NULL\n");
10127
10128 printf("decimal_found: %d\n", decimal_found);
10129
10130 if (after_decimal)
10131 printf("after_decimal: %s\n", after_decimal);
10132 else
10133 printf("after_decimal: NULL\n");
10134
10135 printf("e_found: %d\n", e_found);
10136
10137 printf("e_sign: %c\n", e_sign);
10138
10139 if (exponent_mag)
10140 printf("exponent_mag: %s\n", exponent_mag);
10141 else
10142 printf("exponent_mag: NULL\n");
10143
10144 if (concat_mantissa)
10145 printf("concat_mantissa: %s\n", concat_mantissa);
10146 else
10147 printf("concat_mantissa: NULL\n");
10148 #endif
10149
10150 /* Free all of the memory that was potentially allocated.
10151 */
10152 if (before_decimal)
10153 maFree(before_decimal);
10154 if (after_decimal)
10155 maFree(after_decimal);
10156 if (exponent_mag)
10157 maFree(exponent_mag);
10158 if (concat_mantissa)
10159 maFree(concat_mantissa);
10160 }
10161
10162 /* At this point h_raw and k_raw contain a viable rational number. Now
10163 ** we need to bring it into a normalized form. This involves these steps.
10164 **
10165 ** a)If the number specified was negative, the rational number must
10166 ** have a neg numerator and pos denominator (this is done for us earlier).
10167 **
10168 ** b)If the number is zero, the canonical form of 0 must be used.
10169 **
10170 ** c)If the number is actually an integer, it must be stored in that
10171 ** form (NULL denominator SI).
10172 **
10173 ** d)Any gcd() must be factored out.
10174 */
10175 /* The zero test first. */
10176 if (!(h_raw->len))
10177 {
10178 siSetToLong(&h_canonical, 0);
10179 siDestroy(&k_canonical);
10180 }
10181 else
10182 {
10183 /* The number is not zero. Remove any gcd(). This will have the added
10184 ** benefit of identifying any integers easily.
10185 */
10186 siCopy(&h_raw, &si_temp1);
10187 siCopy(&k_raw, &si_temp2);
10188 si_temp1->neg = FALSE;
10189 siGcd(&si_temp1, &si_temp2, &si_temp3);
10190
10191 #if 0
10192 siDump(&si_temp3, "gcd");
10193 #endif
10194
10195 siUnrestrictedDivision(&h_raw, &si_temp3, &h_canonical, &si_temp4);
10196 siUnrestrictedDivision(&k_raw, &si_temp3, &k_canonical, &si_temp4);
10197
10198 /* The gcd is removed. If the denominator is "1", trash the denominator.
10199 */
10200 if (!siCompare(&constant_1, &k_canonical))
10201 {
10202 siDestroy(&k_canonical);
10203 }
10204 }
10205
10206 /* Assign the raw values and canonical values to the four variables involved.
10207 ** Must NULL any moved pointers to prevent a subsequent FREE of something that
10208 ** now does not belong to us.
10209 */
10210 par_block.pars[i].raw_numerator = h_raw;
10211 h_raw = NULL;
10212 par_block.pars[i].raw_denominator = k_raw;
10213 k_raw = NULL;
10214 par_block.pars[i].canonical_numerator = h_canonical;
10215 h_canonical = NULL;
10216 par_block.pars[i].canonical_denominator = k_canonical;
10217 k_canonical = NULL;
10218
10219 /* Now set the ftype. This is easy to determine. The sign comes from the
10220 ** canonical numerator, and the type comes from the NULLness of the
10221 ** canonical denominator.
10222 */
10223 if (par_block.pars[i].canonical_numerator->neg)
10224 {
10225 /* Neg */
10226 if (par_block.pars[i].canonical_denominator)
10227 {
10228 /* Rational number negative */
10229 par_block.pars[i].ftype = CMDLINE_PAR_TYPE_RATNEG;
10230 }
10231 else
10232 {
10233 /* Integral */
10234 if (par_block.pars[i].canonical_numerator->len)
10235 {
10236 /* Integer negative. */
10237 par_block.pars[i].ftype = CMDLINE_PAR_TYPE_INTNEG;
10238 }
10239 else
10240 {
10241 /* Invalid case. */
10242 asAssert(FALSE, __LINE__);
10243 }
10244 }
10245 }
10246 else
10247 {
10248 /* Pos */
10249 if (par_block.pars[i].canonical_denominator)
10250 {
10251 /* Rational number positive */
10252 par_block.pars[i].ftype = CMDLINE_PAR_TYPE_RATPOS;
10253 }
10254 else
10255 {
10256 /* Integral */
10257 if (par_block.pars[i].canonical_numerator->len)
10258 {
10259 /* Integer positive */
10260 par_block.pars[i].ftype = CMDLINE_PAR_TYPE_INTPOS;
10261 }
10262 else
10263 {
10264 /* Integer zero. */
10265 par_block.pars[i].ftype = CMDLINE_PAR_TYPE_INTZERO;
10266 }
10267 }
10268 }
10269
10270 /* Destroy all of the temporary synthetic integers that were not
10271 ** otherwise destroyed or reassigned.
10272 */
10273 if (constant_1)
10274 siDestroy(&constant_1);
10275 if (h_raw)
10276 siDestroy(&h_raw);
10277 if (k_raw)
10278 siDestroy(&k_raw);
10279 if (h_canonical)
10280 siDestroy(&h_canonical);
10281 if (k_canonical)
10282 siDestroy(&k_canonical);
10283 if (si_temp1)
10284 siDestroy(&si_temp1);
10285 if (si_temp2)
10286 siDestroy(&si_temp2);
10287 if (si_temp3)
10288 siDestroy(&si_temp3);
10289 if (si_temp4)
10290 siDestroy(&si_temp4);
10291
10292 /* Print out diagnostic information */
10293 #if 0
10294 if(par_block.pars[i].raw_numerator)
10295 siDump(&(par_block.pars[i].raw_numerator), "raw_num");
10296 else
10297 printf("raw_num is NULL\n");
10298
10299 if(par_block.pars[i].raw_denominator)
10300 siDump(&(par_block.pars[i].raw_denominator), "raw_den");
10301 else
10302 printf("raw_den is NULL\n");
10303
10304 if(par_block.pars[i].canonical_numerator)
10305 siDump(&(par_block.pars[i].canonical_numerator), "can_num");
10306 else
10307 printf("can_num is NULL\n");
10308
10309 if(par_block.pars[i].canonical_denominator)
10310 siDump(&(par_block.pars[i].canonical_denominator), "can_den");
10311 else
10312 printf("can_den is NULL\n");
10313
10314 printf("ftype is : %d\n", par_block.pars[i].ftype);
10315 #endif
10316 }
10317
10318
10319 /****************************************************************************/
10320 /* ipParseAsSimpleInteger(): */
10321 /*--------------------------------------------------------------------------*/
10322 /* DESCRIPTION */
10323 /* Attempts to parse a string (subscript in par_block passed) as a */
10324 /* simple integer. Looks for errors and fills in the raw integer. There */
10325 /* isn't much to think about with a raw integer, so fills in ftype. */
10326 /****************************************************************************/
10327 void ipParseAsSimpleInteger(int i)
10328 {
10329 int int_is_neg = FALSE;
10330 char *s;
10331
10332 /* Make sure the caller isn't doing anything silly. */
10333 asAssert(i >= 0, __LINE__);
10334 asAssert(i < MAX_CMDLINE_PARS, __LINE__);
10335
10336 s = par_block.pars[i].orig_string;
10337
10338 /* Process any leading '-' sign. */
10339 if (*s == '-')
10340 {
10341 s++;
10342 int_is_neg = TRUE;
10343 }
10344
10345 /* The remainder of the string must a)exist, and b)contain only digits.
10346 */
10347 if (!(*s))
10348 asFatal("bad parameter while expecting simple integer");
10349
10350 if (!ddStringContainsOnly(s, "0123456789"))
10351 asFatal("unexpected non-digit character while expecting simple integer");
10352
10353 /* If there is a leading zero, that must be the only character, and then
10354 ** we can know we have zero.
10355 */
10356 if (*s == '0')
10357 {
10358 if (s[1])
10359 asFatal("leading zeroes not allowed on integers");
10360
10361 if (int_is_neg)
10362 asFatal("can't negate zero");
10363
10364 /* Beavis, we have a zero. Form it.
10365 */
10366 siCreate(&(par_block.pars[i].raw_numerator));
10367 /* Zero is created by default, so no need to go further.
10368 */
10369 }
10370 else
10371 {
10372 /* String contains a non-zero integer, which may or may not be
10373 ** negated. We know it contains only digits and no leading
10374 ** 0.
10375 */
10376 if (strlen(s) > INPUT_INTEGER_MAX_DIGITS)
10377 asFatal("input integer too long");
10378
10379 /* If we're here, we're clean. The string is ready to go as is,
10380 ** except the order must be reversed.
10381 */
10382 siCreate(&(par_block.pars[i].raw_numerator));
10383 par_block.pars[i].raw_numerator->neg = int_is_neg;
10384 strcpy(par_block.pars[i].raw_numerator->digits, s);
10385 par_block.pars[i].raw_numerator->len
10386 = strlen(par_block.pars[i].raw_numerator->digits);
10387
10388 {
10389 /* Reverse the digits. */
10390 int len, idx;
10391 char temp;
10392
10393 len = par_block.pars[i].raw_numerator->len;
10394
10395 for (idx=0; idx < (len/2); idx++)
10396 {
10397 temp = par_block.pars[i].raw_numerator->digits[idx];
10398 par_block.pars[i].raw_numerator->digits[idx]
10399 = par_block.pars[i].raw_numerator->digits[len - 1 - idx];
10400 par_block.pars[i].raw_numerator->digits[len - 1 - idx] = temp;
10401 }
10402 }
10403 }
10404
10405 /* Can also fill in the ftype field.
10406 */
10407 if (!(par_block.pars[i].raw_numerator->len))
10408 par_block.pars[i].ftype = CMDLINE_PAR_TYPE_INTZERO;
10409 else if (par_block.pars[i].raw_numerator->neg)
10410 par_block.pars[i].ftype = CMDLINE_PAR_TYPE_INTNEG;
10411 else
10412 par_block.pars[i].ftype = CMDLINE_PAR_TYPE_INTPOS;
10413
10414 /* In parsing a simple integer, there is no distinction between
10415 ** the raw and the canonical forms. Still, should copy all over
10416 ** to the canonical area.
10417 */
10418
10419 siCreate(&(par_block.pars[i].canonical_numerator));
10420 siCopy(&(par_block.pars[i].raw_numerator), &(par_block.pars[i].canonical_numerator));
10421
10422 /* We know the denominator is NULL, because of the way the parameter block
10423 ** is initialized.
10424 */
10425 }
10426
10427
10428 /****************************************************************************/
10429 /* ipParseCommandLineParameters(): */
10430 /*--------------------------------------------------------------------------*/
10431 /* DESCRIPTION */
10432 /* Parses the command line parameters, as passed in the linked list. */
10433 /* This includes: */
10434 /* a)Checking for an excessive number of parameters. */
10435 /* b)Deciding on the type of the parameters, and converting them to */
10436 /* integers, rational numbers, etc. */
10437 /* c)Placing the quantities into canonical form. */
10438 /****************************************************************************/
10439 void ipParseCommandLineParameters
10440 (
10441 struct ipSimpleStringLlNodeStruct **ptr_to_callers_ptr
10442 )
10443 {
10444 /* Make sure the caller isn't doing anything silly. */
10445 asAssert(ptr_to_callers_ptr != NULL, __LINE__);
10446
10447 /* Completely initialize the array of command-line parameters.
10448 */
10449 {
10450 int i;
10451
10452 par_block.n = 0;
10453
10454 for(i=0; i<MAX_CMDLINE_PARS; i++)
10455 {
10456 par_block.pars[i].ftype = CMDLINE_PAR_TYPE_UNASSIGNED;
10457 par_block.pars[i].orig_string = NULL;
10458 par_block.pars[i].raw_numerator = NULL;
10459 par_block.pars[i].raw_denominator = NULL;
10460 par_block.pars[i].canonical_numerator = NULL;
10461 par_block.pars[i].canonical_denominator = NULL;
10462 }
10463 }
10464
10465 /* Count up the total number of parameters. Crap out of too
10466 ** many.
10467 */
10468 {
10469 unsigned i;
10470 struct ipSimpleStringLlNodeStruct *p;
10471 char buf[100];
10472
10473 p = *ptr_to_callers_ptr;
10474 i = 0;
10475
10476 while(p)
10477 {
10478 p = p->next;
10479 i++;
10480 }
10481
10482 if (i > MAX_CMDLINE_PARS)
10483 {
10484 sprintf(buf, "too many cmd line pars, actual=%u, max=%u",
10485 i,
10486 MAX_CMDLINE_PARS);
10487 asFatal(buf);
10488 }
10489 }
10490
10491 /* Loop through the linked list of parameters, assigning each
10492 ** string into the parameter block, and dismantle the linked list
10493 ** in the process. The strings are kept.
10494 */
10495 {
10496 struct ipSimpleStringLlNodeStruct *node_to_destroy;
10497
10498 par_block.n = 0;
10499
10500 while(*ptr_to_callers_ptr)
10501 {
10502 par_block.pars[par_block.n].orig_string = (*ptr_to_callers_ptr)->s;
10503 node_to_destroy = *ptr_to_callers_ptr;
10504 *ptr_to_callers_ptr = node_to_destroy->next;
10505 maFree(node_to_destroy);
10506 (par_block.n)++;
10507 }
10508 }
10509
10510 /* Parse the first parameter specially. The first parameter must be one of
10511 ** the commands. There must be at least a command.
10512 */
10513 {
10514 static struct
10515 {
10516 char *s;
10517 unsigned v;
10518 } cmdtable[] =
10519 {
10520 {"+", CMDLINE_PAR_TYPE_CMD_KEYTOKEN_PLUS },
10521 {"-", CMDLINE_PAR_TYPE_CMD_KEYTOKEN_MINUS },
10522 {"*", CMDLINE_PAR_TYPE_CMD_KEYTOKEN_TIMES },
10523 {"/", CMDLINE_PAR_TYPE_CMD_KEYTOKEN_QUOTIENT },
10524 {"%", CMDLINE_PAR_TYPE_CMD_KEYTOKEN_MODULO },
10525 {"**", CMDLINE_PAR_TYPE_CMD_KEYTOKEN_POWER },
10526 {"gcd", CMDLINE_PAR_TYPE_CMD_KEYTOKEN_GCD },
10527 {"dap", CMDLINE_PAR_TYPE_CMD_KEYTOKEN_DAP },
10528 {"mind", CMDLINE_PAR_TYPE_CMD_KEYTOKEN_MIND },
10529 {"cf", CMDLINE_PAR_TYPE_CMD_KEYTOKEN_CF },
10530 {"fn", CMDLINE_PAR_TYPE_CMD_KEYTOKEN_FN },
10531 {"fndmax", CMDLINE_PAR_TYPE_CMD_KEYTOKEN_FNDMAX },
10532 {"fab", CMDLINE_PAR_TYPE_CMD_KEYTOKEN_FAB },
10533 {"fabdmax", CMDLINE_PAR_TYPE_CMD_KEYTOKEN_FABDMAX }
10534 };
10535 unsigned i;
10536 char buf[100];
10537
10538 if (par_block.n < 1)
10539 asFatal("too few parameters--at least a command required");
10540
10541 /* Try to match the first parameter against the table above. */
10542 for (i=0; i<sizeof(cmdtable)/sizeof(cmdtable[0]); i++)
10543 {
10544 if (!strcmp(cmdtable[i].s, par_block.pars[0].orig_string))
10545 {
10546 break;
10547 }
10548 }
10549
10550 if (i == sizeof(cmdtable)/sizeof(cmdtable[0]))
10551 {
10552 sprintf(buf, "unknown command \"%s\"", par_block.pars[0].orig_string);
10553 asFatal(buf);
10554 }
10555
10556 par_block.pars[0].ftype = cmdtable[i].v;
10557 }
10558
10559 /* For the remaining parameters, parse them as numbers. The rules are
10560 ** easy. If the number contains a '/', a '.', or an 'e', we must attempt
10561 ** to parse it as a rational number, otherwise we attempt as an
10562 ** integer.
10563 */
10564 {
10565 int i;
10566
10567 for (i=1; i<par_block.n; i++)
10568 {
10569 if (ddStringContains(par_block.pars[i].orig_string, "e/."))
10570 {
10571 /* Attempt to parse as a rational number. */
10572 ipParseAsRationalNumber(i);
10573 }
10574 else
10575 {
10576 /* Attempt to parse as a simple integer. */
10577 ipParseAsSimpleInteger(i);
10578 }
10579 }
10580 }
10581 }
10582
10583
10584 /****************************************************************************/
10585 /* ipExecuteCommand(): */
10586 /*--------------------------------------------------------------------------*/
10587 /* DESCRIPTION */
10588 /* Matches a command against the built-in templates and executes a */
10589 /* command iff the inputs match a template that a command will accept. */
10590 /****************************************************************************/
10591 void ipExecuteCommand(void)
10592 {
10593 /* The structure below gives the "templates" for commands--what is allowed
10594 ** to be passed as parameters, and how it maps to commands. In retrospect,
10595 ** the system for classification could be optimized (it is necessary to
10596 ** spell out too may cases), but the template-matching happens only
10597 ** once.
10598 */
10599 static struct
10600 {
10601 void (*fptr)(void);
10602 /* Function pointer to execute.
10603 */
10604 int template[MAX_CMDLINE_PARS];
10605 /* Template to match.
10606 */
10607 } cmd_templates[]
10608 =
10609 {
10610 /* Simple addition of two integers. Multiple templates are
10611 ** required.
10612 */
10613 {
10614 cfSimple2ParIntegerAddition,
10615 {
10616 CMDLINE_PAR_TYPE_CMD_KEYTOKEN_PLUS,
10617 CMDLINE_PAR_TYPE_INTNEG,
10618 CMDLINE_PAR_TYPE_INTNEG,
10619 CMDLINE_PAR_TYPE_UNASSIGNED,
10620 CMDLINE_PAR_TYPE_UNASSIGNED,
10621 CMDLINE_PAR_TYPE_UNASSIGNED,
10622 CMDLINE_PAR_TYPE_UNASSIGNED,
10623 CMDLINE_PAR_TYPE_UNASSIGNED,
10624 CMDLINE_PAR_TYPE_UNASSIGNED,
10625 CMDLINE_PAR_TYPE_UNASSIGNED
10626 }
10627 },
10628 {
10629 cfSimple2ParIntegerAddition,
10630 {
10631 CMDLINE_PAR_TYPE_CMD_KEYTOKEN_PLUS,
10632 CMDLINE_PAR_TYPE_INTNEG,
10633 CMDLINE_PAR_TYPE_INTZERO,
10634 CMDLINE_PAR_TYPE_UNASSIGNED,
10635 CMDLINE_PAR_TYPE_UNASSIGNED,
10636 CMDLINE_PAR_TYPE_UNASSIGNED,
10637 CMDLINE_PAR_TYPE_UNASSIGNED,
10638 CMDLINE_PAR_TYPE_UNASSIGNED,
10639 CMDLINE_PAR_TYPE_UNASSIGNED,
10640 CMDLINE_PAR_TYPE_UNASSIGNED
10641 }
10642 },
10643 {
10644 cfSimple2ParIntegerAddition,
10645 {
10646 CMDLINE_PAR_TYPE_CMD_KEYTOKEN_PLUS,
10647 CMDLINE_PAR_TYPE_INTNEG,
10648 CMDLINE_PAR_TYPE_INTPOS,
10649 CMDLINE_PAR_TYPE_UNASSIGNED,
10650 CMDLINE_PAR_TYPE_UNASSIGNED,
10651 CMDLINE_PAR_TYPE_UNASSIGNED,
10652 CMDLINE_PAR_TYPE_UNASSIGNED,
10653 CMDLINE_PAR_TYPE_UNASSIGNED,
10654 CMDLINE_PAR_TYPE_UNASSIGNED,
10655 CMDLINE_PAR_TYPE_UNASSIGNED
10656 }
10657 },
10658 {
10659 cfSimple2ParIntegerAddition,
10660 {
10661 CMDLINE_PAR_TYPE_CMD_KEYTOKEN_PLUS,
10662 CMDLINE_PAR_TYPE_INTZERO,
10663 CMDLINE_PAR_TYPE_INTNEG,
10664 CMDLINE_PAR_TYPE_UNASSIGNED,
10665 CMDLINE_PAR_TYPE_UNASSIGNED,
10666 CMDLINE_PAR_TYPE_UNASSIGNED,
10667 CMDLINE_PAR_TYPE_UNASSIGNED,
10668 CMDLINE_PAR_TYPE_UNASSIGNED,
10669 CMDLINE_PAR_TYPE_UNASSIGNED,
10670 CMDLINE_PAR_TYPE_UNASSIGNED
10671 }
10672 },
10673 {
10674 cfSimple2ParIntegerAddition,
10675 {
10676 CMDLINE_PAR_TYPE_CMD_KEYTOKEN_PLUS,
10677 CMDLINE_PAR_TYPE_INTZERO,
10678 CMDLINE_PAR_TYPE_INTZERO,
10679 CMDLINE_PAR_TYPE_UNASSIGNED,
10680 CMDLINE_PAR_TYPE_UNASSIGNED,
10681 CMDLINE_PAR_TYPE_UNASSIGNED,
10682 CMDLINE_PAR_TYPE_UNASSIGNED,
10683 CMDLINE_PAR_TYPE_UNASSIGNED,
10684 CMDLINE_PAR_TYPE_UNASSIGNED,
10685 CMDLINE_PAR_TYPE_UNASSIGNED
10686 }
10687 },
10688 {
10689 cfSimple2ParIntegerAddition,
10690 {
10691 CMDLINE_PAR_TYPE_CMD_KEYTOKEN_PLUS,
10692 CMDLINE_PAR_TYPE_INTZERO,
10693 CMDLINE_PAR_TYPE_INTPOS,
10694 CMDLINE_PAR_TYPE_UNASSIGNED,
10695 CMDLINE_PAR_TYPE_UNASSIGNED,
10696 CMDLINE_PAR_TYPE_UNASSIGNED,
10697 CMDLINE_PAR_TYPE_UNASSIGNED,
10698 CMDLINE_PAR_TYPE_UNASSIGNED,
10699 CMDLINE_PAR_TYPE_UNASSIGNED,
10700 CMDLINE_PAR_TYPE_UNASSIGNED
10701 }
10702 },
10703 {
10704 cfSimple2ParIntegerAddition,
10705 {
10706 CMDLINE_PAR_TYPE_CMD_KEYTOKEN_PLUS,
10707 CMDLINE_PAR_TYPE_INTPOS,
10708 CMDLINE_PAR_TYPE_INTNEG,
10709 CMDLINE_PAR_TYPE_UNASSIGNED,
10710 CMDLINE_PAR_TYPE_UNASSIGNED,
10711 CMDLINE_PAR_TYPE_UNASSIGNED,
10712 CMDLINE_PAR_TYPE_UNASSIGNED,
10713 CMDLINE_PAR_TYPE_UNASSIGNED,
10714 CMDLINE_PAR_TYPE_UNASSIGNED,
10715 CMDLINE_PAR_TYPE_UNASSIGNED
10716 }
10717 },
10718 {
10719 cfSimple2ParIntegerAddition,
10720 {
10721 CMDLINE_PAR_TYPE_CMD_KEYTOKEN_PLUS,
10722 CMDLINE_PAR_TYPE_INTPOS,
10723 CMDLINE_PAR_TYPE_INTZERO,
10724 CMDLINE_PAR_TYPE_UNASSIGNED,
10725 CMDLINE_PAR_TYPE_UNASSIGNED,
10726 CMDLINE_PAR_TYPE_UNASSIGNED,
10727 CMDLINE_PAR_TYPE_UNASSIGNED,
10728 CMDLINE_PAR_TYPE_UNASSIGNED,
10729 CMDLINE_PAR_TYPE_UNASSIGNED,
10730 CMDLINE_PAR_TYPE_UNASSIGNED
10731 }
10732 },
10733 {
10734 cfSimple2ParIntegerAddition,
10735 {
10736 CMDLINE_PAR_TYPE_CMD_KEYTOKEN_PLUS,
10737 CMDLINE_PAR_TYPE_INTPOS,
10738 CMDLINE_PAR_TYPE_INTPOS,
10739 CMDLINE_PAR_TYPE_UNASSIGNED,
10740 CMDLINE_PAR_TYPE_UNASSIGNED,
10741 CMDLINE_PAR_TYPE_UNASSIGNED,
10742 CMDLINE_PAR_TYPE_UNASSIGNED,
10743 CMDLINE_PAR_TYPE_UNASSIGNED,
10744 CMDLINE_PAR_TYPE_UNASSIGNED,
10745 CMDLINE_PAR_TYPE_UNASSIGNED
10746 }
10747 },
10748 /* Simple addition of two rational numbers.
10749 ** Multiple templates are required.
10750 */
10751 {
10752 cfSimple2ParRationalRationalAddition,
10753 {
10754 CMDLINE_PAR_TYPE_CMD_KEYTOKEN_PLUS,
10755 CMDLINE_PAR_TYPE_RATNEG,
10756 CMDLINE_PAR_TYPE_RATNEG,
10757 CMDLINE_PAR_TYPE_UNASSIGNED,
10758 CMDLINE_PAR_TYPE_UNASSIGNED,
10759 CMDLINE_PAR_TYPE_UNASSIGNED,
10760 CMDLINE_PAR_TYPE_UNASSIGNED,
10761 CMDLINE_PAR_TYPE_UNASSIGNED,
10762 CMDLINE_PAR_TYPE_UNASSIGNED,
10763 CMDLINE_PAR_TYPE_UNASSIGNED
10764 }
10765 },
10766 {
10767 cfSimple2ParRationalRationalAddition,
10768 {
10769 CMDLINE_PAR_TYPE_CMD_KEYTOKEN_PLUS,
10770 CMDLINE_PAR_TYPE_RATNEG,
10771 CMDLINE_PAR_TYPE_RATZERO,
10772 CMDLINE_PAR_TYPE_UNASSIGNED,
10773 CMDLINE_PAR_TYPE_UNASSIGNED,
10774 CMDLINE_PAR_TYPE_UNASSIGNED,
10775 CMDLINE_PAR_TYPE_UNASSIGNED,
10776 CMDLINE_PAR_TYPE_UNASSIGNED,
10777 CMDLINE_PAR_TYPE_UNASSIGNED,
10778 CMDLINE_PAR_TYPE_UNASSIGNED
10779 }
10780 },
10781 {
10782 cfSimple2ParRationalRationalAddition,
10783 {
10784 CMDLINE_PAR_TYPE_CMD_KEYTOKEN_PLUS,
10785 CMDLINE_PAR_TYPE_RATNEG,
10786 CMDLINE_PAR_TYPE_RATPOS,
10787 CMDLINE_PAR_TYPE_UNASSIGNED,
10788 CMDLINE_PAR_TYPE_UNASSIGNED,
10789 CMDLINE_PAR_TYPE_UNASSIGNED,
10790 CMDLINE_PAR_TYPE_UNASSIGNED,
10791 CMDLINE_PAR_TYPE_UNASSIGNED,
10792 CMDLINE_PAR_TYPE_UNASSIGNED,
10793 CMDLINE_PAR_TYPE_UNASSIGNED
10794 }
10795 },
10796 {
10797 cfSimple2ParRationalRationalAddition,
10798 {
10799 CMDLINE_PAR_TYPE_CMD_KEYTOKEN_PLUS,
10800 CMDLINE_PAR_TYPE_RATZERO,
10801 CMDLINE_PAR_TYPE_RATNEG,
10802 CMDLINE_PAR_TYPE_UNASSIGNED,
10803 CMDLINE_PAR_TYPE_UNASSIGNED,
10804 CMDLINE_PAR_TYPE_UNASSIGNED,
10805 CMDLINE_PAR_TYPE_UNASSIGNED,
10806 CMDLINE_PAR_TYPE_UNASSIGNED,
10807 CMDLINE_PAR_TYPE_UNASSIGNED,
10808 CMDLINE_PAR_TYPE_UNASSIGNED
10809 }
10810 },
10811 {
10812 cfSimple2ParRationalRationalAddition,
10813 {
10814 CMDLINE_PAR_TYPE_CMD_KEYTOKEN_PLUS,
10815 CMDLINE_PAR_TYPE_RATZERO,
10816 CMDLINE_PAR_TYPE_RATZERO,
10817 CMDLINE_PAR_TYPE_UNASSIGNED,
10818 CMDLINE_PAR_TYPE_UNASSIGNED,
10819 CMDLINE_PAR_TYPE_UNASSIGNED,
10820 CMDLINE_PAR_TYPE_UNASSIGNED,
10821 CMDLINE_PAR_TYPE_UNASSIGNED,
10822 CMDLINE_PAR_TYPE_UNASSIGNED,
10823 CMDLINE_PAR_TYPE_UNASSIGNED
10824 }
10825 },
10826 {
10827 cfSimple2ParRationalRationalAddition,
10828 {
10829 CMDLINE_PAR_TYPE_CMD_KEYTOKEN_PLUS,
10830 CMDLINE_PAR_TYPE_RATZERO,
10831 CMDLINE_PAR_TYPE_RATPOS,
10832 CMDLINE_PAR_TYPE_UNASSIGNED,
10833 CMDLINE_PAR_TYPE_UNASSIGNED,
10834 CMDLINE_PAR_TYPE_UNASSIGNED,
10835 CMDLINE_PAR_TYPE_UNASSIGNED,
10836 CMDLINE_PAR_TYPE_UNASSIGNED,
10837 CMDLINE_PAR_TYPE_UNASSIGNED,
10838 CMDLINE_PAR_TYPE_UNASSIGNED
10839 }
10840 },
10841 {
10842 cfSimple2ParRationalRationalAddition,
10843 {
10844 CMDLINE_PAR_TYPE_CMD_KEYTOKEN_PLUS,
10845 CMDLINE_PAR_TYPE_RATPOS,
10846 CMDLINE_PAR_TYPE_RATNEG,
10847 CMDLINE_PAR_TYPE_UNASSIGNED,
10848 CMDLINE_PAR_TYPE_UNASSIGNED,
10849 CMDLINE_PAR_TYPE_UNASSIGNED,
10850 CMDLINE_PAR_TYPE_UNASSIGNED,
10851 CMDLINE_PAR_TYPE_UNASSIGNED,
10852 CMDLINE_PAR_TYPE_UNASSIGNED,
10853 CMDLINE_PAR_TYPE_UNASSIGNED
10854 }
10855 },
10856 {
10857 cfSimple2ParRationalRationalAddition,
10858 {
10859 CMDLINE_PAR_TYPE_CMD_KEYTOKEN_PLUS,
10860 CMDLINE_PAR_TYPE_RATPOS,
10861 CMDLINE_PAR_TYPE_RATZERO,
10862 CMDLINE_PAR_TYPE_UNASSIGNED,
10863 CMDLINE_PAR_TYPE_UNASSIGNED,
10864 CMDLINE_PAR_TYPE_UNASSIGNED,
10865 CMDLINE_PAR_TYPE_UNASSIGNED,
10866 CMDLINE_PAR_TYPE_UNASSIGNED,
10867 CMDLINE_PAR_TYPE_UNASSIGNED,
10868 CMDLINE_PAR_TYPE_UNASSIGNED
10869 }
10870 },
10871 {
10872 cfSimple2ParRationalRationalAddition,
10873 {
10874 CMDLINE_PAR_TYPE_CMD_KEYTOKEN_PLUS,
10875 CMDLINE_PAR_TYPE_RATPOS,
10876 CMDLINE_PAR_TYPE_RATPOS,
10877 CMDLINE_PAR_TYPE_UNASSIGNED,
10878 CMDLINE_PAR_TYPE_UNASSIGNED,
10879 CMDLINE_PAR_TYPE_UNASSIGNED,
10880 CMDLINE_PAR_TYPE_UNASSIGNED,
10881 CMDLINE_PAR_TYPE_UNASSIGNED,
10882 CMDLINE_PAR_TYPE_UNASSIGNED,
10883 CMDLINE_PAR_TYPE_UNASSIGNED
10884 }
10885 },
10886 {
10887 cfSimple2ParRationalRationalAddition,
10888 {
10889 CMDLINE_PAR_TYPE_CMD_KEYTOKEN_PLUS,
10890 CMDLINE_PAR_TYPE_INTNEG,
10891 CMDLINE_PAR_TYPE_RATNEG,
10892 CMDLINE_PAR_TYPE_UNASSIGNED,
10893 CMDLINE_PAR_TYPE_UNASSIGNED,
10894 CMDLINE_PAR_TYPE_UNASSIGNED,
10895 CMDLINE_PAR_TYPE_UNASSIGNED,
10896 CMDLINE_PAR_TYPE_UNASSIGNED,
10897 CMDLINE_PAR_TYPE_UNASSIGNED,
10898 CMDLINE_PAR_TYPE_UNASSIGNED
10899 }
10900 },
10901 {
10902 cfSimple2ParRationalRationalAddition,
10903 {
10904 CMDLINE_PAR_TYPE_CMD_KEYTOKEN_PLUS,
10905 CMDLINE_PAR_TYPE_INTNEG,
10906 CMDLINE_PAR_TYPE_RATZERO,
10907 CMDLINE_PAR_TYPE_UNASSIGNED,
10908 CMDLINE_PAR_TYPE_UNASSIGNED,
10909 CMDLINE_PAR_TYPE_UNASSIGNED,
10910 CMDLINE_PAR_TYPE_UNASSIGNED,
10911 CMDLINE_PAR_TYPE_UNASSIGNED,
10912 CMDLINE_PAR_TYPE_UNASSIGNED,
10913 CMDLINE_PAR_TYPE_UNASSIGNED
10914 }
10915 },
10916 {
10917 cfSimple2ParRationalRationalAddition,
10918 {
10919 CMDLINE_PAR_TYPE_CMD_KEYTOKEN_PLUS,
10920 CMDLINE_PAR_TYPE_INTNEG,
10921 CMDLINE_PAR_TYPE_RATPOS,
10922 CMDLINE_PAR_TYPE_UNASSIGNED,
10923 CMDLINE_PAR_TYPE_UNASSIGNED,
10924 CMDLINE_PAR_TYPE_UNASSIGNED,
10925 CMDLINE_PAR_TYPE_UNASSIGNED,
10926 CMDLINE_PAR_TYPE_UNASSIGNED,
10927 CMDLINE_PAR_TYPE_UNASSIGNED,
10928 CMDLINE_PAR_TYPE_UNASSIGNED
10929 }
10930 },
10931 {
10932 cfSimple2ParRationalRationalAddition,
10933 {
10934 CMDLINE_PAR_TYPE_CMD_KEYTOKEN_PLUS,
10935 CMDLINE_PAR_TYPE_INTZERO,
10936 CMDLINE_PAR_TYPE_RATNEG,
10937 CMDLINE_PAR_TYPE_UNASSIGNED,
10938 CMDLINE_PAR_TYPE_UNASSIGNED,
10939 CMDLINE_PAR_TYPE_UNASSIGNED,
10940 CMDLINE_PAR_TYPE_UNASSIGNED,
10941 CMDLINE_PAR_TYPE_UNASSIGNED,
10942 CMDLINE_PAR_TYPE_UNASSIGNED,
10943 CMDLINE_PAR_TYPE_UNASSIGNED
10944 }
10945 },
10946 {
10947 cfSimple2ParRationalRationalAddition,
10948 {
10949 CMDLINE_PAR_TYPE_CMD_KEYTOKEN_PLUS,
10950 CMDLINE_PAR_TYPE_INTZERO,
10951 CMDLINE_PAR_TYPE_RATZERO,
10952 CMDLINE_PAR_TYPE_UNASSIGNED,
10953 CMDLINE_PAR_TYPE_UNASSIGNED,
10954 CMDLINE_PAR_TYPE_UNASSIGNED,
10955 CMDLINE_PAR_TYPE_UNASSIGNED,
10956 CMDLINE_PAR_TYPE_UNASSIGNED,
10957 CMDLINE_PAR_TYPE_UNASSIGNED,
10958 CMDLINE_PAR_TYPE_UNASSIGNED
10959 }
10960 },
10961 {
10962 cfSimple2ParRationalRationalAddition,
10963 {
10964 CMDLINE_PAR_TYPE_CMD_KEYTOKEN_PLUS,
10965 CMDLINE_PAR_TYPE_INTZERO,
10966 CMDLINE_PAR_TYPE_RATPOS,
10967 CMDLINE_PAR_TYPE_UNASSIGNED,
10968 CMDLINE_PAR_TYPE_UNASSIGNED,
10969 CMDLINE_PAR_TYPE_UNASSIGNED,
10970 CMDLINE_PAR_TYPE_UNASSIGNED,
10971 CMDLINE_PAR_TYPE_UNASSIGNED,
10972 CMDLINE_PAR_TYPE_UNASSIGNED,
10973 CMDLINE_PAR_TYPE_UNASSIGNED
10974 }
10975 },
10976 {
10977 cfSimple2ParRationalRationalAddition,
10978 {
10979 CMDLINE_PAR_TYPE_CMD_KEYTOKEN_PLUS,
10980 CMDLINE_PAR_TYPE_INTPOS,
10981 CMDLINE_PAR_TYPE_RATNEG,
10982 CMDLINE_PAR_TYPE_UNASSIGNED,
10983 CMDLINE_PAR_TYPE_UNASSIGNED,
10984 CMDLINE_PAR_TYPE_UNASSIGNED,
10985 CMDLINE_PAR_TYPE_UNASSIGNED,
10986 CMDLINE_PAR_TYPE_UNASSIGNED,
10987 CMDLINE_PAR_TYPE_UNASSIGNED,
10988 CMDLINE_PAR_TYPE_UNASSIGNED
10989 }
10990 },
10991 {
10992 cfSimple2ParRationalRationalAddition,
10993 {
10994 CMDLINE_PAR_TYPE_CMD_KEYTOKEN_PLUS,
10995 CMDLINE_PAR_TYPE_INTPOS,
10996 CMDLINE_PAR_TYPE_RATZERO,
10997 CMDLINE_PAR_TYPE_UNASSIGNED,
10998 CMDLINE_PAR_TYPE_UNASSIGNED,
10999 CMDLINE_PAR_TYPE_UNASSIGNED,
11000 CMDLINE_PAR_TYPE_UNASSIGNED,
11001 CMDLINE_PAR_TYPE_UNASSIGNED,
11002 CMDLINE_PAR_TYPE_UNASSIGNED,
11003 CMDLINE_PAR_TYPE_UNASSIGNED
11004 }
11005 },
11006 {
11007 cfSimple2ParRationalRationalAddition,
11008 {
11009 CMDLINE_PAR_TYPE_CMD_KEYTOKEN_PLUS,
11010 CMDLINE_PAR_TYPE_INTPOS,
11011 CMDLINE_PAR_TYPE_RATPOS,
11012 CMDLINE_PAR_TYPE_UNASSIGNED,
11013 CMDLINE_PAR_TYPE_UNASSIGNED,
11014 CMDLINE_PAR_TYPE_UNASSIGNED,
11015 CMDLINE_PAR_TYPE_UNASSIGNED,
11016 CMDLINE_PAR_TYPE_UNASSIGNED,
11017 CMDLINE_PAR_TYPE_UNASSIGNED,
11018 CMDLINE_PAR_TYPE_UNASSIGNED
11019 }
11020 },
11021 {
11022 cfSimple2ParRationalRationalAddition,
11023 {
11024 CMDLINE_PAR_TYPE_CMD_KEYTOKEN_PLUS,
11025 CMDLINE_PAR_TYPE_RATNEG,
11026 CMDLINE_PAR_TYPE_INTNEG,
11027 CMDLINE_PAR_TYPE_UNASSIGNED,
11028 CMDLINE_PAR_TYPE_UNASSIGNED,
11029 CMDLINE_PAR_TYPE_UNASSIGNED,
11030 CMDLINE_PAR_TYPE_UNASSIGNED,
11031 CMDLINE_PAR_TYPE_UNASSIGNED,
11032 CMDLINE_PAR_TYPE_UNASSIGNED,
11033 CMDLINE_PAR_TYPE_UNASSIGNED
11034 }
11035 },
11036 {
11037 cfSimple2ParRationalRationalAddition,
11038 {
11039 CMDLINE_PAR_TYPE_CMD_KEYTOKEN_PLUS,
11040 CMDLINE_PAR_TYPE_RATNEG,
11041 CMDLINE_PAR_TYPE_INTZERO,
11042 CMDLINE_PAR_TYPE_UNASSIGNED,
11043 CMDLINE_PAR_TYPE_UNASSIGNED,
11044 CMDLINE_PAR_TYPE_UNASSIGNED,
11045 CMDLINE_PAR_TYPE_UNASSIGNED,
11046 CMDLINE_PAR_TYPE_UNASSIGNED,
11047 CMDLINE_PAR_TYPE_UNASSIGNED,
11048 CMDLINE_PAR_TYPE_UNASSIGNED
11049 }
11050 },
11051 {
11052 cfSimple2ParRationalRationalAddition,
11053 {
11054 CMDLINE_PAR_TYPE_CMD_KEYTOKEN_PLUS,
11055 CMDLINE_PAR_TYPE_RATNEG,
11056 CMDLINE_PAR_TYPE_INTPOS,
11057 CMDLINE_PAR_TYPE_UNASSIGNED,
11058 CMDLINE_PAR_TYPE_UNASSIGNED,
11059 CMDLINE_PAR_TYPE_UNASSIGNED,
11060 CMDLINE_PAR_TYPE_UNASSIGNED,
11061 CMDLINE_PAR_TYPE_UNASSIGNED,
11062 CMDLINE_PAR_TYPE_UNASSIGNED,
11063 CMDLINE_PAR_TYPE_UNASSIGNED
11064 }
11065 },
11066 {
11067 cfSimple2ParRationalRationalAddition,
11068 {
11069 CMDLINE_PAR_TYPE_CMD_KEYTOKEN_PLUS,
11070 CMDLINE_PAR_TYPE_RATZERO,
11071 CMDLINE_PAR_TYPE_INTNEG,
11072 CMDLINE_PAR_TYPE_UNASSIGNED,
11073 CMDLINE_PAR_TYPE_UNASSIGNED,
11074 CMDLINE_PAR_TYPE_UNASSIGNED,
11075 CMDLINE_PAR_TYPE_UNASSIGNED,
11076 CMDLINE_PAR_TYPE_UNASSIGNED,
11077 CMDLINE_PAR_TYPE_UNASSIGNED,
11078 CMDLINE_PAR_TYPE_UNASSIGNED
11079 }
11080 },
11081 {
11082 cfSimple2ParRationalRationalAddition,
11083 {
11084 CMDLINE_PAR_TYPE_CMD_KEYTOKEN_PLUS,
11085 CMDLINE_PAR_TYPE_RATZERO,
11086 CMDLINE_PAR_TYPE_INTZERO,
11087 CMDLINE_PAR_TYPE_UNASSIGNED,
11088 CMDLINE_PAR_TYPE_UNASSIGNED,
11089 CMDLINE_PAR_TYPE_UNASSIGNED,
11090 CMDLINE_PAR_TYPE_UNASSIGNED,
11091 CMDLINE_PAR_TYPE_UNASSIGNED,
11092 CMDLINE_PAR_TYPE_UNASSIGNED,
11093 CMDLINE_PAR_TYPE_UNASSIGNED
11094 }
11095 },
11096 {
11097 cfSimple2ParRationalRationalAddition,
11098 {
11099 CMDLINE_PAR_TYPE_CMD_KEYTOKEN_PLUS,
11100 CMDLINE_PAR_TYPE_RATZERO,
11101 CMDLINE_PAR_TYPE_INTPOS,
11102 CMDLINE_PAR_TYPE_UNASSIGNED,
11103 CMDLINE_PAR_TYPE_UNASSIGNED,
11104 CMDLINE_PAR_TYPE_UNASSIGNED,
11105 CMDLINE_PAR_TYPE_UNASSIGNED,
11106 CMDLINE_PAR_TYPE_UNASSIGNED,
11107 CMDLINE_PAR_TYPE_UNASSIGNED,
11108 CMDLINE_PAR_TYPE_UNASSIGNED
11109 }
11110 },
11111 {
11112 cfSimple2ParRationalRationalAddition,
11113 {
11114 CMDLINE_PAR_TYPE_CMD_KEYTOKEN_PLUS,
11115 CMDLINE_PAR_TYPE_RATPOS,
11116 CMDLINE_PAR_TYPE_INTNEG,
11117 CMDLINE_PAR_TYPE_UNASSIGNED,
11118 CMDLINE_PAR_TYPE_UNASSIGNED,
11119 CMDLINE_PAR_TYPE_UNASSIGNED,
11120 CMDLINE_PAR_TYPE_UNASSIGNED,
11121 CMDLINE_PAR_TYPE_UNASSIGNED,
11122 CMDLINE_PAR_TYPE_UNASSIGNED,
11123 CMDLINE_PAR_TYPE_UNASSIGNED
11124 }
11125 },
11126 {
11127 cfSimple2ParRationalRationalAddition,
11128 {
11129 CMDLINE_PAR_TYPE_CMD_KEYTOKEN_PLUS,
11130 CMDLINE_PAR_TYPE_RATPOS,
11131 CMDLINE_PAR_TYPE_INTZERO,
11132 CMDLINE_PAR_TYPE_UNASSIGNED,
11133 CMDLINE_PAR_TYPE_UNASSIGNED,
11134 CMDLINE_PAR_TYPE_UNASSIGNED,
11135 CMDLINE_PAR_TYPE_UNASSIGNED,
11136 CMDLINE_PAR_TYPE_UNASSIGNED,
11137 CMDLINE_PAR_TYPE_UNASSIGNED,
11138 CMDLINE_PAR_TYPE_UNASSIGNED
11139 }
11140 },
11141 {
11142 cfSimple2ParRationalRationalAddition,
11143 {
11144 CMDLINE_PAR_TYPE_CMD_KEYTOKEN_PLUS,
11145 CMDLINE_PAR_TYPE_RATPOS,
11146 CMDLINE_PAR_TYPE_INTPOS,
11147 CMDLINE_PAR_TYPE_UNASSIGNED,
11148 CMDLINE_PAR_TYPE_UNASSIGNED,
11149 CMDLINE_PAR_TYPE_UNASSIGNED,
11150 CMDLINE_PAR_TYPE_UNASSIGNED,
11151 CMDLINE_PAR_TYPE_UNASSIGNED,
11152 CMDLINE_PAR_TYPE_UNASSIGNED,
11153 CMDLINE_PAR_TYPE_UNASSIGNED
11154 }
11155 },
11156 /* Simple subtraction of two integers. Multiple templates are
11157 ** required.
11158 */
11159 {
11160 cfSimple2ParIntegerSubtraction,
11161 {
11162 CMDLINE_PAR_TYPE_CMD_KEYTOKEN_MINUS,
11163 CMDLINE_PAR_TYPE_INTNEG,
11164 CMDLINE_PAR_TYPE_INTNEG,
11165 CMDLINE_PAR_TYPE_UNASSIGNED,
11166 CMDLINE_PAR_TYPE_UNASSIGNED,
11167 CMDLINE_PAR_TYPE_UNASSIGNED,
11168 CMDLINE_PAR_TYPE_UNASSIGNED,
11169 CMDLINE_PAR_TYPE_UNASSIGNED,
11170 CMDLINE_PAR_TYPE_UNASSIGNED,
11171 CMDLINE_PAR_TYPE_UNASSIGNED
11172 }
11173 },
11174 {
11175 cfSimple2ParIntegerSubtraction,
11176 {
11177 CMDLINE_PAR_TYPE_CMD_KEYTOKEN_MINUS,
11178 CMDLINE_PAR_TYPE_INTNEG,
11179 CMDLINE_PAR_TYPE_INTZERO,
11180 CMDLINE_PAR_TYPE_UNASSIGNED,
11181 CMDLINE_PAR_TYPE_UNASSIGNED,
11182 CMDLINE_PAR_TYPE_UNASSIGNED,
11183 CMDLINE_PAR_TYPE_UNASSIGNED,
11184 CMDLINE_PAR_TYPE_UNASSIGNED,
11185 CMDLINE_PAR_TYPE_UNASSIGNED,
11186 CMDLINE_PAR_TYPE_UNASSIGNED
11187 }
11188 },
11189 {
11190 cfSimple2ParIntegerSubtraction,
11191 {
11192 CMDLINE_PAR_TYPE_CMD_KEYTOKEN_MINUS,
11193 CMDLINE_PAR_TYPE_INTNEG,
11194 CMDLINE_PAR_TYPE_INTPOS,
11195 CMDLINE_PAR_TYPE_UNASSIGNED,
11196 CMDLINE_PAR_TYPE_UNASSIGNED,
11197 CMDLINE_PAR_TYPE_UNASSIGNED,
11198 CMDLINE_PAR_TYPE_UNASSIGNED,
11199 CMDLINE_PAR_TYPE_UNASSIGNED,
11200 CMDLINE_PAR_TYPE_UNASSIGNED,
11201 CMDLINE_PAR_TYPE_UNASSIGNED
11202 }
11203 },
11204 {
11205 cfSimple2ParIntegerSubtraction,
11206 {
11207 CMDLINE_PAR_TYPE_CMD_KEYTOKEN_MINUS,
11208 CMDLINE_PAR_TYPE_INTZERO,
11209 CMDLINE_PAR_TYPE_INTNEG,
11210 CMDLINE_PAR_TYPE_UNASSIGNED,
11211 CMDLINE_PAR_TYPE_UNASSIGNED,
11212 CMDLINE_PAR_TYPE_UNASSIGNED,
11213 CMDLINE_PAR_TYPE_UNASSIGNED,
11214 CMDLINE_PAR_TYPE_UNASSIGNED,
11215 CMDLINE_PAR_TYPE_UNASSIGNED,
11216 CMDLINE_PAR_TYPE_UNASSIGNED
11217 }
11218 },
11219 {
11220 cfSimple2ParIntegerSubtraction,
11221 {
11222 CMDLINE_PAR_TYPE_CMD_KEYTOKEN_MINUS,
11223 CMDLINE_PAR_TYPE_INTZERO,
11224 CMDLINE_PAR_TYPE_INTZERO,
11225 CMDLINE_PAR_TYPE_UNASSIGNED,
11226 CMDLINE_PAR_TYPE_UNASSIGNED,
11227 CMDLINE_PAR_TYPE_UNASSIGNED,
11228 CMDLINE_PAR_TYPE_UNASSIGNED,
11229 CMDLINE_PAR_TYPE_UNASSIGNED,
11230 CMDLINE_PAR_TYPE_UNASSIGNED,
11231 CMDLINE_PAR_TYPE_UNASSIGNED
11232 }
11233 },
11234 {
11235 cfSimple2ParIntegerSubtraction,
11236 {
11237 CMDLINE_PAR_TYPE_CMD_KEYTOKEN_MINUS,
11238 CMDLINE_PAR_TYPE_INTZERO,
11239 CMDLINE_PAR_TYPE_INTPOS,
11240 CMDLINE_PAR_TYPE_UNASSIGNED,
11241 CMDLINE_PAR_TYPE_UNASSIGNED,
11242 CMDLINE_PAR_TYPE_UNASSIGNED,
11243 CMDLINE_PAR_TYPE_UNASSIGNED,
11244 CMDLINE_PAR_TYPE_UNASSIGNED,
11245 CMDLINE_PAR_TYPE_UNASSIGNED,
11246 CMDLINE_PAR_TYPE_UNASSIGNED
11247 }
11248 },
11249 {
11250 cfSimple2ParIntegerSubtraction,
11251 {
11252 CMDLINE_PAR_TYPE_CMD_KEYTOKEN_MINUS,
11253 CMDLINE_PAR_TYPE_INTPOS,
11254 CMDLINE_PAR_TYPE_INTNEG,
11255 CMDLINE_PAR_TYPE_UNASSIGNED,
11256 CMDLINE_PAR_TYPE_UNASSIGNED,
11257 CMDLINE_PAR_TYPE_UNASSIGNED,
11258 CMDLINE_PAR_TYPE_UNASSIGNED,
11259 CMDLINE_PAR_TYPE_UNASSIGNED,
11260 CMDLINE_PAR_TYPE_UNASSIGNED,
11261 CMDLINE_PAR_TYPE_UNASSIGNED
11262 }
11263 },
11264 {
11265 cfSimple2ParIntegerSubtraction,
11266 {
11267 CMDLINE_PAR_TYPE_CMD_KEYTOKEN_MINUS,
11268 CMDLINE_PAR_TYPE_INTPOS,
11269 CMDLINE_PAR_TYPE_INTZERO,
11270 CMDLINE_PAR_TYPE_UNASSIGNED,
11271 CMDLINE_PAR_TYPE_UNASSIGNED,
11272 CMDLINE_PAR_TYPE_UNASSIGNED,
11273 CMDLINE_PAR_TYPE_UNASSIGNED,
11274 CMDLINE_PAR_TYPE_UNASSIGNED,
11275 CMDLINE_PAR_TYPE_UNASSIGNED,
11276 CMDLINE_PAR_TYPE_UNASSIGNED
11277 }
11278 },
11279 {
11280 cfSimple2ParIntegerSubtraction,
11281 {
11282 CMDLINE_PAR_TYPE_CMD_KEYTOKEN_MINUS,
11283 CMDLINE_PAR_TYPE_INTPOS,
11284 CMDLINE_PAR_TYPE_INTPOS,
11285 CMDLINE_PAR_TYPE_UNASSIGNED,
11286 CMDLINE_PAR_TYPE_UNASSIGNED,
11287 CMDLINE_PAR_TYPE_UNASSIGNED,
11288 CMDLINE_PAR_TYPE_UNASSIGNED,
11289 CMDLINE_PAR_TYPE_UNASSIGNED,
11290 CMDLINE_PAR_TYPE_UNASSIGNED,
11291 CMDLINE_PAR_TYPE_UNASSIGNED
11292 }
11293 },
11294 /* Simple subtraction of two rational numbers.
11295 ** Multiple templates are required.
11296 */
11297 {
11298 cfSimple2ParRationalRationalSubtraction,
11299 {
11300 CMDLINE_PAR_TYPE_CMD_KEYTOKEN_MINUS,
11301 CMDLINE_PAR_TYPE_RATNEG,
11302 CMDLINE_PAR_TYPE_RATNEG,
11303 CMDLINE_PAR_TYPE_UNASSIGNED,
11304 CMDLINE_PAR_TYPE_UNASSIGNED,
11305 CMDLINE_PAR_TYPE_UNASSIGNED,
11306 CMDLINE_PAR_TYPE_UNASSIGNED,
11307 CMDLINE_PAR_TYPE_UNASSIGNED,
11308 CMDLINE_PAR_TYPE_UNASSIGNED,
11309 CMDLINE_PAR_TYPE_UNASSIGNED
11310 }
11311 },
11312 {
11313 cfSimple2ParRationalRationalSubtraction,
11314 {
11315 CMDLINE_PAR_TYPE_CMD_KEYTOKEN_MINUS,
11316 CMDLINE_PAR_TYPE_RATNEG,
11317 CMDLINE_PAR_TYPE_RATZERO,
11318 CMDLINE_PAR_TYPE_UNASSIGNED,
11319 CMDLINE_PAR_TYPE_UNASSIGNED,
11320 CMDLINE_PAR_TYPE_UNASSIGNED,
11321 CMDLINE_PAR_TYPE_UNASSIGNED,
11322 CMDLINE_PAR_TYPE_UNASSIGNED,
11323 CMDLINE_PAR_TYPE_UNASSIGNED,
11324 CMDLINE_PAR_TYPE_UNASSIGNED
11325 }
11326 },
11327 {
11328 cfSimple2ParRationalRationalSubtraction,
11329 {
11330 CMDLINE_PAR_TYPE_CMD_KEYTOKEN_MINUS,
11331 CMDLINE_PAR_TYPE_RATNEG,
11332 CMDLINE_PAR_TYPE_RATPOS,
11333 CMDLINE_PAR_TYPE_UNASSIGNED,
11334 CMDLINE_PAR_TYPE_UNASSIGNED,
11335 CMDLINE_PAR_TYPE_UNASSIGNED,
11336 CMDLINE_PAR_TYPE_UNASSIGNED,
11337 CMDLINE_PAR_TYPE_UNASSIGNED,
11338 CMDLINE_PAR_TYPE_UNASSIGNED,
11339 CMDLINE_PAR_TYPE_UNASSIGNED
11340 }
11341 },
11342 {
11343 cfSimple2ParRationalRationalSubtraction,
11344 {
11345 CMDLINE_PAR_TYPE_CMD_KEYTOKEN_MINUS,
11346 CMDLINE_PAR_TYPE_RATZERO,
11347 CMDLINE_PAR_TYPE_RATNEG,
11348 CMDLINE_PAR_TYPE_UNASSIGNED,
11349 CMDLINE_PAR_TYPE_UNASSIGNED,
11350 CMDLINE_PAR_TYPE_UNASSIGNED,
11351 CMDLINE_PAR_TYPE_UNASSIGNED,
11352 CMDLINE_PAR_TYPE_UNASSIGNED,
11353 CMDLINE_PAR_TYPE_UNASSIGNED,
11354 CMDLINE_PAR_TYPE_UNASSIGNED
11355 }
11356 },
11357 {
11358 cfSimple2ParRationalRationalSubtraction,
11359 {
11360 CMDLINE_PAR_TYPE_CMD_KEYTOKEN_MINUS,
11361 CMDLINE_PAR_TYPE_RATZERO,
11362 CMDLINE_PAR_TYPE_RATZERO,
11363 CMDLINE_PAR_TYPE_UNASSIGNED,
11364 CMDLINE_PAR_TYPE_UNASSIGNED,
11365 CMDLINE_PAR_TYPE_UNASSIGNED,
11366 CMDLINE_PAR_TYPE_UNASSIGNED,
11367 CMDLINE_PAR_TYPE_UNASSIGNED,
11368 CMDLINE_PAR_TYPE_UNASSIGNED,
11369 CMDLINE_PAR_TYPE_UNASSIGNED
11370 }
11371 },
11372 {
11373 cfSimple2ParRationalRationalSubtraction,
11374 {
11375 CMDLINE_PAR_TYPE_CMD_KEYTOKEN_MINUS,
11376 CMDLINE_PAR_TYPE_RATZERO,
11377 CMDLINE_PAR_TYPE_RATPOS,
11378 CMDLINE_PAR_TYPE_UNASSIGNED,
11379 CMDLINE_PAR_TYPE_UNASSIGNED,
11380 CMDLINE_PAR_TYPE_UNASSIGNED,
11381 CMDLINE_PAR_TYPE_UNASSIGNED,
11382 CMDLINE_PAR_TYPE_UNASSIGNED,
11383 CMDLINE_PAR_TYPE_UNASSIGNED,
11384 CMDLINE_PAR_TYPE_UNASSIGNED
11385 }
11386 },
11387 {
11388 cfSimple2ParRationalRationalSubtraction,
11389 {
11390 CMDLINE_PAR_TYPE_CMD_KEYTOKEN_MINUS,
11391 CMDLINE_PAR_TYPE_RATPOS,
11392 CMDLINE_PAR_TYPE_RATNEG,
11393 CMDLINE_PAR_TYPE_UNASSIGNED,
11394 CMDLINE_PAR_TYPE_UNASSIGNED,
11395 CMDLINE_PAR_TYPE_UNASSIGNED,
11396 CMDLINE_PAR_TYPE_UNASSIGNED,
11397 CMDLINE_PAR_TYPE_UNASSIGNED,
11398 CMDLINE_PAR_TYPE_UNASSIGNED,
11399 CMDLINE_PAR_TYPE_UNASSIGNED
11400 }
11401 },
11402 {
11403 cfSimple2ParRationalRationalSubtraction,
11404 {
11405 CMDLINE_PAR_TYPE_CMD_KEYTOKEN_MINUS,
11406 CMDLINE_PAR_TYPE_RATPOS,
11407 CMDLINE_PAR_TYPE_RATZERO,
11408 CMDLINE_PAR_TYPE_UNASSIGNED,
11409 CMDLINE_PAR_TYPE_UNASSIGNED,
11410 CMDLINE_PAR_TYPE_UNASSIGNED,
11411 CMDLINE_PAR_TYPE_UNASSIGNED,
11412 CMDLINE_PAR_TYPE_UNASSIGNED,
11413 CMDLINE_PAR_TYPE_UNASSIGNED,
11414 CMDLINE_PAR_TYPE_UNASSIGNED
11415 }
11416 },
11417 {
11418 cfSimple2ParRationalRationalSubtraction,
11419 {
11420 CMDLINE_PAR_TYPE_CMD_KEYTOKEN_MINUS,
11421 CMDLINE_PAR_TYPE_RATPOS,
11422 CMDLINE_PAR_TYPE_RATPOS,
11423 CMDLINE_PAR_TYPE_UNASSIGNED,
11424 CMDLINE_PAR_TYPE_UNASSIGNED,
11425 CMDLINE_PAR_TYPE_UNASSIGNED,
11426 CMDLINE_PAR_TYPE_UNASSIGNED,
11427 CMDLINE_PAR_TYPE_UNASSIGNED,
11428 CMDLINE_PAR_TYPE_UNASSIGNED,
11429 CMDLINE_PAR_TYPE_UNASSIGNED
11430 }
11431 },
11432 {
11433 cfSimple2ParRationalRationalSubtraction,
11434 {
11435 CMDLINE_PAR_TYPE_CMD_KEYTOKEN_MINUS,
11436 CMDLINE_PAR_TYPE_INTNEG,
11437 CMDLINE_PAR_TYPE_RATNEG,
11438 CMDLINE_PAR_TYPE_UNASSIGNED,
11439 CMDLINE_PAR_TYPE_UNASSIGNED,
11440 CMDLINE_PAR_TYPE_UNASSIGNED,
11441 CMDLINE_PAR_TYPE_UNASSIGNED,
11442 CMDLINE_PAR_TYPE_UNASSIGNED,
11443 CMDLINE_PAR_TYPE_UNASSIGNED,
11444 CMDLINE_PAR_TYPE_UNASSIGNED
11445 }
11446 },
11447 {
11448 cfSimple2ParRationalRationalSubtraction,
11449 {
11450 CMDLINE_PAR_TYPE_CMD_KEYTOKEN_MINUS,
11451 CMDLINE_PAR_TYPE_INTNEG,
11452 CMDLINE_PAR_TYPE_RATZERO,
11453 CMDLINE_PAR_TYPE_UNASSIGNED,
11454 CMDLINE_PAR_TYPE_UNASSIGNED,
11455 CMDLINE_PAR_TYPE_UNASSIGNED,
11456 CMDLINE_PAR_TYPE_UNASSIGNED,
11457 CMDLINE_PAR_TYPE_UNASSIGNED,
11458 CMDLINE_PAR_TYPE_UNASSIGNED,
11459 CMDLINE_PAR_TYPE_UNASSIGNED
11460 }
11461 },
11462 {
11463 cfSimple2ParRationalRationalSubtraction,
11464 {
11465 CMDLINE_PAR_TYPE_CMD_KEYTOKEN_MINUS,
11466 CMDLINE_PAR_TYPE_INTNEG,
11467 CMDLINE_PAR_TYPE_RATPOS,
11468 CMDLINE_PAR_TYPE_UNASSIGNED,
11469 CMDLINE_PAR_TYPE_UNASSIGNED,
11470 CMDLINE_PAR_TYPE_UNASSIGNED,
11471 CMDLINE_PAR_TYPE_UNASSIGNED,
11472 CMDLINE_PAR_TYPE_UNASSIGNED,
11473 CMDLINE_PAR_TYPE_UNASSIGNED,
11474 CMDLINE_PAR_TYPE_UNASSIGNED
11475 }
11476 },
11477 {
11478 cfSimple2ParRationalRationalSubtraction,
11479 {
11480 CMDLINE_PAR_TYPE_CMD_KEYTOKEN_MINUS,
11481 CMDLINE_PAR_TYPE_INTZERO,
11482 CMDLINE_PAR_TYPE_RATNEG,
11483 CMDLINE_PAR_TYPE_UNASSIGNED,
11484 CMDLINE_PAR_TYPE_UNASSIGNED,
11485 CMDLINE_PAR_TYPE_UNASSIGNED,
11486 CMDLINE_PAR_TYPE_UNASSIGNED,
11487 CMDLINE_PAR_TYPE_UNASSIGNED,
11488 CMDLINE_PAR_TYPE_UNASSIGNED,
11489 CMDLINE_PAR_TYPE_UNASSIGNED
11490 }
11491 },
11492 {
11493 cfSimple2ParRationalRationalSubtraction,
11494 {
11495 CMDLINE_PAR_TYPE_CMD_KEYTOKEN_MINUS,
11496 CMDLINE_PAR_TYPE_INTZERO,
11497 CMDLINE_PAR_TYPE_RATZERO,
11498 CMDLINE_PAR_TYPE_UNASSIGNED,
11499 CMDLINE_PAR_TYPE_UNASSIGNED,
11500 CMDLINE_PAR_TYPE_UNASSIGNED,
11501 CMDLINE_PAR_TYPE_UNASSIGNED,
11502 CMDLINE_PAR_TYPE_UNASSIGNED,
11503 CMDLINE_PAR_TYPE_UNASSIGNED,
11504 CMDLINE_PAR_TYPE_UNASSIGNED
11505 }
11506 },
11507 {
11508 cfSimple2ParRationalRationalSubtraction,
11509 {
11510 CMDLINE_PAR_TYPE_CMD_KEYTOKEN_MINUS,
11511 CMDLINE_PAR_TYPE_INTZERO,
11512 CMDLINE_PAR_TYPE_RATPOS,
11513 CMDLINE_PAR_TYPE_UNASSIGNED,
11514 CMDLINE_PAR_TYPE_UNASSIGNED,
11515 CMDLINE_PAR_TYPE_UNASSIGNED,
11516 CMDLINE_PAR_TYPE_UNASSIGNED,
11517 CMDLINE_PAR_TYPE_UNASSIGNED,
11518 CMDLINE_PAR_TYPE_UNASSIGNED,
11519 CMDLINE_PAR_TYPE_UNASSIGNED
11520 }
11521 },
11522 {
11523 cfSimple2ParRationalRationalSubtraction,
11524 {
11525 CMDLINE_PAR_TYPE_CMD_KEYTOKEN_MINUS,
11526 CMDLINE_PAR_TYPE_INTPOS,
11527 CMDLINE_PAR_TYPE_RATNEG,
11528 CMDLINE_PAR_TYPE_UNASSIGNED,
11529 CMDLINE_PAR_TYPE_UNASSIGNED,
11530 CMDLINE_PAR_TYPE_UNASSIGNED,
11531 CMDLINE_PAR_TYPE_UNASSIGNED,
11532 CMDLINE_PAR_TYPE_UNASSIGNED,
11533 CMDLINE_PAR_TYPE_UNASSIGNED,
11534 CMDLINE_PAR_TYPE_UNASSIGNED
11535 }
11536 },
11537 {
11538 cfSimple2ParRationalRationalSubtraction,
11539 {
11540 CMDLINE_PAR_TYPE_CMD_KEYTOKEN_MINUS,
11541 CMDLINE_PAR_TYPE_INTPOS,
11542 CMDLINE_PAR_TYPE_RATZERO,
11543 CMDLINE_PAR_TYPE_UNASSIGNED,
11544 CMDLINE_PAR_TYPE_UNASSIGNED,
11545 CMDLINE_PAR_TYPE_UNASSIGNED,
11546 CMDLINE_PAR_TYPE_UNASSIGNED,
11547 CMDLINE_PAR_TYPE_UNASSIGNED,
11548 CMDLINE_PAR_TYPE_UNASSIGNED,
11549 CMDLINE_PAR_TYPE_UNASSIGNED
11550 }
11551 },
11552 {
11553 cfSimple2ParRationalRationalSubtraction,
11554 {
11555 CMDLINE_PAR_TYPE_CMD_KEYTOKEN_MINUS,
11556 CMDLINE_PAR_TYPE_INTPOS,
11557 CMDLINE_PAR_TYPE_RATPOS,
11558 CMDLINE_PAR_TYPE_UNASSIGNED,
11559 CMDLINE_PAR_TYPE_UNASSIGNED,
11560 CMDLINE_PAR_TYPE_UNASSIGNED,
11561 CMDLINE_PAR_TYPE_UNASSIGNED,
11562 CMDLINE_PAR_TYPE_UNASSIGNED,
11563 CMDLINE_PAR_TYPE_UNASSIGNED,
11564 CMDLINE_PAR_TYPE_UNASSIGNED
11565 }
11566 },
11567 {
11568 cfSimple2ParRationalRationalSubtraction,
11569 {
11570 CMDLINE_PAR_TYPE_CMD_KEYTOKEN_MINUS,
11571 CMDLINE_PAR_TYPE_RATNEG,
11572 CMDLINE_PAR_TYPE_INTNEG,
11573 CMDLINE_PAR_TYPE_UNASSIGNED,
11574 CMDLINE_PAR_TYPE_UNASSIGNED,
11575 CMDLINE_PAR_TYPE_UNASSIGNED,
11576 CMDLINE_PAR_TYPE_UNASSIGNED,
11577 CMDLINE_PAR_TYPE_UNASSIGNED,
11578 CMDLINE_PAR_TYPE_UNASSIGNED,
11579 CMDLINE_PAR_TYPE_UNASSIGNED
11580 }
11581 },
11582 {
11583 cfSimple2ParRationalRationalSubtraction,
11584 {
11585 CMDLINE_PAR_TYPE_CMD_KEYTOKEN_MINUS,
11586 CMDLINE_PAR_TYPE_RATNEG,
11587 CMDLINE_PAR_TYPE_INTZERO,
11588 CMDLINE_PAR_TYPE_UNASSIGNED,
11589 CMDLINE_PAR_TYPE_UNASSIGNED,
11590 CMDLINE_PAR_TYPE_UNASSIGNED,
11591 CMDLINE_PAR_TYPE_UNASSIGNED,
11592 CMDLINE_PAR_TYPE_UNASSIGNED,
11593 CMDLINE_PAR_TYPE_UNASSIGNED,
11594 CMDLINE_PAR_TYPE_UNASSIGNED
11595 }
11596 },
11597 {
11598 cfSimple2ParRationalRationalSubtraction,
11599 {
11600 CMDLINE_PAR_TYPE_CMD_KEYTOKEN_MINUS,
11601 CMDLINE_PAR_TYPE_RATNEG,
11602 CMDLINE_PAR_TYPE_INTPOS,
11603 CMDLINE_PAR_TYPE_UNASSIGNED,
11604 CMDLINE_PAR_TYPE_UNASSIGNED,
11605 CMDLINE_PAR_TYPE_UNASSIGNED,
11606 CMDLINE_PAR_TYPE_UNASSIGNED,
11607 CMDLINE_PAR_TYPE_UNASSIGNED,
11608 CMDLINE_PAR_TYPE_UNASSIGNED,
11609 CMDLINE_PAR_TYPE_UNASSIGNED
11610 }
11611 },
11612 {
11613 cfSimple2ParRationalRationalSubtraction,
11614 {
11615 CMDLINE_PAR_TYPE_CMD_KEYTOKEN_MINUS,
11616 CMDLINE_PAR_TYPE_RATZERO,
11617 CMDLINE_PAR_TYPE_INTNEG,
11618 CMDLINE_PAR_TYPE_UNASSIGNED,
11619 CMDLINE_PAR_TYPE_UNASSIGNED,
11620 CMDLINE_PAR_TYPE_UNASSIGNED,
11621 CMDLINE_PAR_TYPE_UNASSIGNED,
11622 CMDLINE_PAR_TYPE_UNASSIGNED,
11623 CMDLINE_PAR_TYPE_UNASSIGNED,
11624 CMDLINE_PAR_TYPE_UNASSIGNED
11625 }
11626 },
11627 {
11628 cfSimple2ParRationalRationalSubtraction,
11629 {
11630 CMDLINE_PAR_TYPE_CMD_KEYTOKEN_MINUS,
11631 CMDLINE_PAR_TYPE_RATZERO,
11632 CMDLINE_PAR_TYPE_INTZERO,
11633 CMDLINE_PAR_TYPE_UNASSIGNED,
11634 CMDLINE_PAR_TYPE_UNASSIGNED,
11635 CMDLINE_PAR_TYPE_UNASSIGNED,
11636 CMDLINE_PAR_TYPE_UNASSIGNED,
11637 CMDLINE_PAR_TYPE_UNASSIGNED,
11638 CMDLINE_PAR_TYPE_UNASSIGNED,
11639 CMDLINE_PAR_TYPE_UNASSIGNED
11640 }
11641 },
11642 {
11643 cfSimple2ParRationalRationalSubtraction,
11644 {
11645 CMDLINE_PAR_TYPE_CMD_KEYTOKEN_MINUS,
11646 CMDLINE_PAR_TYPE_RATZERO,
11647 CMDLINE_PAR_TYPE_INTPOS,
11648 CMDLINE_PAR_TYPE_UNASSIGNED,
11649 CMDLINE_PAR_TYPE_UNASSIGNED,
11650 CMDLINE_PAR_TYPE_UNASSIGNED,
11651 CMDLINE_PAR_TYPE_UNASSIGNED,
11652 CMDLINE_PAR_TYPE_UNASSIGNED,
11653 CMDLINE_PAR_TYPE_UNASSIGNED,
11654 CMDLINE_PAR_TYPE_UNASSIGNED
11655 }
11656 },
11657 {
11658 cfSimple2ParRationalRationalSubtraction,
11659 {
11660 CMDLINE_PAR_TYPE_CMD_KEYTOKEN_MINUS,
11661 CMDLINE_PAR_TYPE_RATPOS,
11662 CMDLINE_PAR_TYPE_INTNEG,
11663 CMDLINE_PAR_TYPE_UNASSIGNED,
11664 CMDLINE_PAR_TYPE_UNASSIGNED,
11665 CMDLINE_PAR_TYPE_UNASSIGNED,
11666 CMDLINE_PAR_TYPE_UNASSIGNED,
11667 CMDLINE_PAR_TYPE_UNASSIGNED,
11668 CMDLINE_PAR_TYPE_UNASSIGNED,
11669 CMDLINE_PAR_TYPE_UNASSIGNED
11670 }
11671 },
11672 {
11673 cfSimple2ParRationalRationalSubtraction,
11674 {
11675 CMDLINE_PAR_TYPE_CMD_KEYTOKEN_MINUS,
11676 CMDLINE_PAR_TYPE_RATPOS,
11677 CMDLINE_PAR_TYPE_INTZERO,
11678 CMDLINE_PAR_TYPE_UNASSIGNED,
11679 CMDLINE_PAR_TYPE_UNASSIGNED,
11680 CMDLINE_PAR_TYPE_UNASSIGNED,
11681 CMDLINE_PAR_TYPE_UNASSIGNED,
11682 CMDLINE_PAR_TYPE_UNASSIGNED,
11683 CMDLINE_PAR_TYPE_UNASSIGNED,
11684 CMDLINE_PAR_TYPE_UNASSIGNED
11685 }
11686 },
11687 {
11688 cfSimple2ParRationalRationalSubtraction,
11689 {
11690 CMDLINE_PAR_TYPE_CMD_KEYTOKEN_MINUS,
11691 CMDLINE_PAR_TYPE_RATPOS,
11692 CMDLINE_PAR_TYPE_INTPOS,
11693 CMDLINE_PAR_TYPE_UNASSIGNED,
11694 CMDLINE_PAR_TYPE_UNASSIGNED,
11695 CMDLINE_PAR_TYPE_UNASSIGNED,
11696 CMDLINE_PAR_TYPE_UNASSIGNED,
11697 CMDLINE_PAR_TYPE_UNASSIGNED,
11698 CMDLINE_PAR_TYPE_UNASSIGNED,
11699 CMDLINE_PAR_TYPE_UNASSIGNED
11700 }
11701 },
11702 /* Simple multiplication of two integers. Multiple templates are
11703 ** required.
11704 */
11705 {
11706 cfSimple2ParIntegerMultiplication,
11707 {
11708 CMDLINE_PAR_TYPE_CMD_KEYTOKEN_TIMES,
11709 CMDLINE_PAR_TYPE_INTNEG,
11710 CMDLINE_PAR_TYPE_INTNEG,
11711 CMDLINE_PAR_TYPE_UNASSIGNED,
11712 CMDLINE_PAR_TYPE_UNASSIGNED,
11713 CMDLINE_PAR_TYPE_UNASSIGNED,
11714 CMDLINE_PAR_TYPE_UNASSIGNED,
11715 CMDLINE_PAR_TYPE_UNASSIGNED,
11716 CMDLINE_PAR_TYPE_UNASSIGNED,
11717 CMDLINE_PAR_TYPE_UNASSIGNED
11718 }
11719 },
11720 {
11721 cfSimple2ParIntegerMultiplication,
11722 {
11723 CMDLINE_PAR_TYPE_CMD_KEYTOKEN_TIMES,
11724 CMDLINE_PAR_TYPE_INTNEG,
11725 CMDLINE_PAR_TYPE_INTZERO,
11726 CMDLINE_PAR_TYPE_UNASSIGNED,
11727 CMDLINE_PAR_TYPE_UNASSIGNED,
11728 CMDLINE_PAR_TYPE_UNASSIGNED,
11729 CMDLINE_PAR_TYPE_UNASSIGNED,
11730 CMDLINE_PAR_TYPE_UNASSIGNED,
11731 CMDLINE_PAR_TYPE_UNASSIGNED,
11732 CMDLINE_PAR_TYPE_UNASSIGNED
11733 }
11734 },
11735 {
11736 cfSimple2ParIntegerMultiplication,
11737 {
11738 CMDLINE_PAR_TYPE_CMD_KEYTOKEN_TIMES,
11739 CMDLINE_PAR_TYPE_INTNEG,
11740 CMDLINE_PAR_TYPE_INTPOS,
11741 CMDLINE_PAR_TYPE_UNASSIGNED,
11742 CMDLINE_PAR_TYPE_UNASSIGNED,
11743 CMDLINE_PAR_TYPE_UNASSIGNED,
11744 CMDLINE_PAR_TYPE_UNASSIGNED,
11745 CMDLINE_PAR_TYPE_UNASSIGNED,
11746 CMDLINE_PAR_TYPE_UNASSIGNED,
11747 CMDLINE_PAR_TYPE_UNASSIGNED
11748 }
11749 },
11750 {
11751 cfSimple2ParIntegerMultiplication,
11752 {
11753 CMDLINE_PAR_TYPE_CMD_KEYTOKEN_TIMES,
11754 CMDLINE_PAR_TYPE_INTZERO,
11755 CMDLINE_PAR_TYPE_INTNEG,
11756 CMDLINE_PAR_TYPE_UNASSIGNED,
11757 CMDLINE_PAR_TYPE_UNASSIGNED,
11758 CMDLINE_PAR_TYPE_UNASSIGNED,
11759 CMDLINE_PAR_TYPE_UNASSIGNED,
11760 CMDLINE_PAR_TYPE_UNASSIGNED,
11761 CMDLINE_PAR_TYPE_UNASSIGNED,
11762 CMDLINE_PAR_TYPE_UNASSIGNED
11763 }
11764 },
11765 {
11766 cfSimple2ParIntegerMultiplication,
11767 {
11768 CMDLINE_PAR_TYPE_CMD_KEYTOKEN_TIMES,
11769 CMDLINE_PAR_TYPE_INTZERO,
11770 CMDLINE_PAR_TYPE_INTZERO,
11771 CMDLINE_PAR_TYPE_UNASSIGNED,
11772 CMDLINE_PAR_TYPE_UNASSIGNED,
11773 CMDLINE_PAR_TYPE_UNASSIGNED,
11774 CMDLINE_PAR_TYPE_UNASSIGNED,
11775 CMDLINE_PAR_TYPE_UNASSIGNED,
11776 CMDLINE_PAR_TYPE_UNASSIGNED,
11777 CMDLINE_PAR_TYPE_UNASSIGNED
11778 }
11779 },
11780 {
11781 cfSimple2ParIntegerMultiplication,
11782 {
11783 CMDLINE_PAR_TYPE_CMD_KEYTOKEN_TIMES,
11784 CMDLINE_PAR_TYPE_INTZERO,
11785 CMDLINE_PAR_TYPE_INTPOS,
11786 CMDLINE_PAR_TYPE_UNASSIGNED,
11787 CMDLINE_PAR_TYPE_UNASSIGNED,
11788 CMDLINE_PAR_TYPE_UNASSIGNED,
11789 CMDLINE_PAR_TYPE_UNASSIGNED,
11790 CMDLINE_PAR_TYPE_UNASSIGNED,
11791 CMDLINE_PAR_TYPE_UNASSIGNED,
11792 CMDLINE_PAR_TYPE_UNASSIGNED
11793 }
11794 },
11795 {
11796 cfSimple2ParIntegerMultiplication,
11797 {
11798 CMDLINE_PAR_TYPE_CMD_KEYTOKEN_TIMES,
11799 CMDLINE_PAR_TYPE_INTPOS,
11800 CMDLINE_PAR_TYPE_INTNEG,
11801 CMDLINE_PAR_TYPE_UNASSIGNED,
11802 CMDLINE_PAR_TYPE_UNASSIGNED,
11803 CMDLINE_PAR_TYPE_UNASSIGNED,
11804 CMDLINE_PAR_TYPE_UNASSIGNED,
11805 CMDLINE_PAR_TYPE_UNASSIGNED,
11806 CMDLINE_PAR_TYPE_UNASSIGNED,
11807 CMDLINE_PAR_TYPE_UNASSIGNED
11808 }
11809 },
11810 {
11811 cfSimple2ParIntegerMultiplication,
11812 {
11813 CMDLINE_PAR_TYPE_CMD_KEYTOKEN_TIMES,
11814 CMDLINE_PAR_TYPE_INTPOS,
11815 CMDLINE_PAR_TYPE_INTZERO,
11816 CMDLINE_PAR_TYPE_UNASSIGNED,
11817 CMDLINE_PAR_TYPE_UNASSIGNED,
11818 CMDLINE_PAR_TYPE_UNASSIGNED,
11819 CMDLINE_PAR_TYPE_UNASSIGNED,
11820 CMDLINE_PAR_TYPE_UNASSIGNED,
11821 CMDLINE_PAR_TYPE_UNASSIGNED,
11822 CMDLINE_PAR_TYPE_UNASSIGNED
11823 }
11824 },
11825 {
11826 cfSimple2ParIntegerMultiplication,
11827 {
11828 CMDLINE_PAR_TYPE_CMD_KEYTOKEN_TIMES,
11829 CMDLINE_PAR_TYPE_INTPOS,
11830 CMDLINE_PAR_TYPE_INTPOS,
11831 CMDLINE_PAR_TYPE_UNASSIGNED,
11832 CMDLINE_PAR_TYPE_UNASSIGNED,
11833 CMDLINE_PAR_TYPE_UNASSIGNED,
11834 CMDLINE_PAR_TYPE_UNASSIGNED,
11835 CMDLINE_PAR_TYPE_UNASSIGNED,
11836 CMDLINE_PAR_TYPE_UNASSIGNED,
11837 CMDLINE_PAR_TYPE_UNASSIGNED
11838 }
11839 },
11840 /* Simple multiplication of two rational numbers.
11841 ** Multiple templates are required.
11842 */
11843 {
11844 cfSimple2ParRationalRationalMultiplication,
11845 {
11846 CMDLINE_PAR_TYPE_CMD_KEYTOKEN_TIMES,
11847 CMDLINE_PAR_TYPE_RATNEG,
11848 CMDLINE_PAR_TYPE_RATNEG,
11849 CMDLINE_PAR_TYPE_UNASSIGNED,
11850 CMDLINE_PAR_TYPE_UNASSIGNED,
11851 CMDLINE_PAR_TYPE_UNASSIGNED,
11852 CMDLINE_PAR_TYPE_UNASSIGNED,
11853 CMDLINE_PAR_TYPE_UNASSIGNED,
11854 CMDLINE_PAR_TYPE_UNASSIGNED,
11855 CMDLINE_PAR_TYPE_UNASSIGNED
11856 }
11857 },
11858 {
11859 cfSimple2ParRationalRationalMultiplication,
11860 {
11861 CMDLINE_PAR_TYPE_CMD_KEYTOKEN_TIMES,
11862 CMDLINE_PAR_TYPE_RATNEG,
11863 CMDLINE_PAR_TYPE_RATZERO,
11864 CMDLINE_PAR_TYPE_UNASSIGNED,
11865 CMDLINE_PAR_TYPE_UNASSIGNED,
11866 CMDLINE_PAR_TYPE_UNASSIGNED,
11867 CMDLINE_PAR_TYPE_UNASSIGNED,
11868 CMDLINE_PAR_TYPE_UNASSIGNED,
11869 CMDLINE_PAR_TYPE_UNASSIGNED,
11870 CMDLINE_PAR_TYPE_UNASSIGNED
11871 }
11872 },
11873 {
11874 cfSimple2ParRationalRationalMultiplication,
11875 {
11876 CMDLINE_PAR_TYPE_CMD_KEYTOKEN_TIMES,
11877 CMDLINE_PAR_TYPE_RATNEG,
11878 CMDLINE_PAR_TYPE_RATPOS,
11879 CMDLINE_PAR_TYPE_UNASSIGNED,
11880 CMDLINE_PAR_TYPE_UNASSIGNED,
11881 CMDLINE_PAR_TYPE_UNASSIGNED,
11882 CMDLINE_PAR_TYPE_UNASSIGNED,
11883 CMDLINE_PAR_TYPE_UNASSIGNED,
11884 CMDLINE_PAR_TYPE_UNASSIGNED,
11885 CMDLINE_PAR_TYPE_UNASSIGNED
11886 }
11887 },
11888 {
11889 cfSimple2ParRationalRationalMultiplication,
11890 {
11891 CMDLINE_PAR_TYPE_CMD_KEYTOKEN_TIMES,
11892 CMDLINE_PAR_TYPE_RATZERO,
11893 CMDLINE_PAR_TYPE_RATNEG,
11894 CMDLINE_PAR_TYPE_UNASSIGNED,
11895 CMDLINE_PAR_TYPE_UNASSIGNED,
11896 CMDLINE_PAR_TYPE_UNASSIGNED,
11897 CMDLINE_PAR_TYPE_UNASSIGNED,
11898 CMDLINE_PAR_TYPE_UNASSIGNED,
11899 CMDLINE_PAR_TYPE_UNASSIGNED,
11900 CMDLINE_PAR_TYPE_UNASSIGNED
11901 }
11902 },
11903 {
11904 cfSimple2ParRationalRationalMultiplication,
11905 {
11906 CMDLINE_PAR_TYPE_CMD_KEYTOKEN_TIMES,
11907 CMDLINE_PAR_TYPE_RATZERO,
11908 CMDLINE_PAR_TYPE_RATZERO,
11909 CMDLINE_PAR_TYPE_UNASSIGNED,
11910 CMDLINE_PAR_TYPE_UNASSIGNED,
11911 CMDLINE_PAR_TYPE_UNASSIGNED,
11912 CMDLINE_PAR_TYPE_UNASSIGNED,
11913 CMDLINE_PAR_TYPE_UNASSIGNED,
11914 CMDLINE_PAR_TYPE_UNASSIGNED,
11915 CMDLINE_PAR_TYPE_UNASSIGNED
11916 }
11917 },
11918 {
11919 cfSimple2ParRationalRationalMultiplication,
11920 {
11921 CMDLINE_PAR_TYPE_CMD_KEYTOKEN_TIMES,
11922 CMDLINE_PAR_TYPE_RATZERO,
11923 CMDLINE_PAR_TYPE_RATPOS,
11924 CMDLINE_PAR_TYPE_UNASSIGNED,
11925 CMDLINE_PAR_TYPE_UNASSIGNED,
11926 CMDLINE_PAR_TYPE_UNASSIGNED,
11927 CMDLINE_PAR_TYPE_UNASSIGNED,
11928 CMDLINE_PAR_TYPE_UNASSIGNED,
11929 CMDLINE_PAR_TYPE_UNASSIGNED,
11930 CMDLINE_PAR_TYPE_UNASSIGNED
11931 }
11932 },
11933 {
11934 cfSimple2ParRationalRationalMultiplication,
11935 {
11936 CMDLINE_PAR_TYPE_CMD_KEYTOKEN_TIMES,
11937 CMDLINE_PAR_TYPE_RATPOS,
11938 CMDLINE_PAR_TYPE_RATNEG,
11939 CMDLINE_PAR_TYPE_UNASSIGNED,
11940 CMDLINE_PAR_TYPE_UNASSIGNED,
11941 CMDLINE_PAR_TYPE_UNASSIGNED,
11942 CMDLINE_PAR_TYPE_UNASSIGNED,
11943 CMDLINE_PAR_TYPE_UNASSIGNED,
11944 CMDLINE_PAR_TYPE_UNASSIGNED,
11945 CMDLINE_PAR_TYPE_UNASSIGNED
11946 }
11947 },
11948 {
11949 cfSimple2ParRationalRationalMultiplication,
11950 {
11951 CMDLINE_PAR_TYPE_CMD_KEYTOKEN_TIMES,
11952 CMDLINE_PAR_TYPE_RATPOS,
11953 CMDLINE_PAR_TYPE_RATZERO,
11954 CMDLINE_PAR_TYPE_UNASSIGNED,
11955 CMDLINE_PAR_TYPE_UNASSIGNED,
11956 CMDLINE_PAR_TYPE_UNASSIGNED,
11957 CMDLINE_PAR_TYPE_UNASSIGNED,
11958 CMDLINE_PAR_TYPE_UNASSIGNED,
11959 CMDLINE_PAR_TYPE_UNASSIGNED,
11960 CMDLINE_PAR_TYPE_UNASSIGNED
11961 }
11962 },
11963 {
11964 cfSimple2ParRationalRationalMultiplication,
11965 {
11966 CMDLINE_PAR_TYPE_CMD_KEYTOKEN_TIMES,
11967 CMDLINE_PAR_TYPE_RATPOS,
11968 CMDLINE_PAR_TYPE_RATPOS,
11969 CMDLINE_PAR_TYPE_UNASSIGNED,
11970 CMDLINE_PAR_TYPE_UNASSIGNED,
11971 CMDLINE_PAR_TYPE_UNASSIGNED,
11972 CMDLINE_PAR_TYPE_UNASSIGNED,
11973 CMDLINE_PAR_TYPE_UNASSIGNED,
11974 CMDLINE_PAR_TYPE_UNASSIGNED,
11975 CMDLINE_PAR_TYPE_UNASSIGNED
11976 }
11977 },
11978 {
11979 cfSimple2ParRationalRationalMultiplication,
11980 {
11981 CMDLINE_PAR_TYPE_CMD_KEYTOKEN_TIMES,
11982 CMDLINE_PAR_TYPE_INTNEG,
11983 CMDLINE_PAR_TYPE_RATNEG,
11984 CMDLINE_PAR_TYPE_UNASSIGNED,
11985 CMDLINE_PAR_TYPE_UNASSIGNED,
11986 CMDLINE_PAR_TYPE_UNASSIGNED,
11987 CMDLINE_PAR_TYPE_UNASSIGNED,
11988 CMDLINE_PAR_TYPE_UNASSIGNED,
11989 CMDLINE_PAR_TYPE_UNASSIGNED,
11990 CMDLINE_PAR_TYPE_UNASSIGNED
11991 }
11992 },
11993 {
11994 cfSimple2ParRationalRationalMultiplication,
11995 {
11996 CMDLINE_PAR_TYPE_CMD_KEYTOKEN_TIMES,
11997 CMDLINE_PAR_TYPE_INTNEG,
11998 CMDLINE_PAR_TYPE_RATZERO,
11999 CMDLINE_PAR_TYPE_UNASSIGNED,
12000 CMDLINE_PAR_TYPE_UNASSIGNED,
12001 CMDLINE_PAR_TYPE_UNASSIGNED,
12002 CMDLINE_PAR_TYPE_UNASSIGNED,
12003 CMDLINE_PAR_TYPE_UNASSIGNED,
12004 CMDLINE_PAR_TYPE_UNASSIGNED,
12005 CMDLINE_PAR_TYPE_UNASSIGNED
12006 }
12007 },
12008 {
12009 cfSimple2ParRationalRationalMultiplication,
12010 {
12011 CMDLINE_PAR_TYPE_CMD_KEYTOKEN_TIMES,
12012 CMDLINE_PAR_TYPE_INTNEG,
12013 CMDLINE_PAR_TYPE_RATPOS,
12014 CMDLINE_PAR_TYPE_UNASSIGNED,
12015 CMDLINE_PAR_TYPE_UNASSIGNED,
12016 CMDLINE_PAR_TYPE_UNASSIGNED,
12017 CMDLINE_PAR_TYPE_UNASSIGNED,
12018 CMDLINE_PAR_TYPE_UNASSIGNED,
12019 CMDLINE_PAR_TYPE_UNASSIGNED,
12020 CMDLINE_PAR_TYPE_UNASSIGNED
12021 }
12022 },
12023 {
12024 cfSimple2ParRationalRationalMultiplication,
12025 {
12026 CMDLINE_PAR_TYPE_CMD_KEYTOKEN_TIMES,
12027 CMDLINE_PAR_TYPE_INTZERO,
12028 CMDLINE_PAR_TYPE_RATNEG,
12029 CMDLINE_PAR_TYPE_UNASSIGNED,
12030 CMDLINE_PAR_TYPE_UNASSIGNED,
12031 CMDLINE_PAR_TYPE_UNASSIGNED,
12032 CMDLINE_PAR_TYPE_UNASSIGNED,
12033 CMDLINE_PAR_TYPE_UNASSIGNED,
12034 CMDLINE_PAR_TYPE_UNASSIGNED,
12035 CMDLINE_PAR_TYPE_UNASSIGNED
12036 }
12037 },
12038 {
12039 cfSimple2ParRationalRationalMultiplication,
12040 {
12041 CMDLINE_PAR_TYPE_CMD_KEYTOKEN_TIMES,
12042 CMDLINE_PAR_TYPE_INTZERO,
12043 CMDLINE_PAR_TYPE_RATZERO,
12044 CMDLINE_PAR_TYPE_UNASSIGNED,
12045 CMDLINE_PAR_TYPE_UNASSIGNED,
12046 CMDLINE_PAR_TYPE_UNASSIGNED,
12047 CMDLINE_PAR_TYPE_UNASSIGNED,
12048 CMDLINE_PAR_TYPE_UNASSIGNED,
12049 CMDLINE_PAR_TYPE_UNASSIGNED,
12050 CMDLINE_PAR_TYPE_UNASSIGNED
12051 }
12052 },
12053 {
12054 cfSimple2ParRationalRationalMultiplication,
12055 {
12056 CMDLINE_PAR_TYPE_CMD_KEYTOKEN_TIMES,
12057 CMDLINE_PAR_TYPE_INTZERO,
12058 CMDLINE_PAR_TYPE_RATPOS,
12059 CMDLINE_PAR_TYPE_UNASSIGNED,
12060 CMDLINE_PAR_TYPE_UNASSIGNED,
12061 CMDLINE_PAR_TYPE_UNASSIGNED,
12062 CMDLINE_PAR_TYPE_UNASSIGNED,
12063 CMDLINE_PAR_TYPE_UNASSIGNED,
12064 CMDLINE_PAR_TYPE_UNASSIGNED,
12065 CMDLINE_PAR_TYPE_UNASSIGNED
12066 }
12067 },
12068 {
12069 cfSimple2ParRationalRationalMultiplication,
12070 {
12071 CMDLINE_PAR_TYPE_CMD_KEYTOKEN_TIMES,
12072 CMDLINE_PAR_TYPE_INTPOS,
12073 CMDLINE_PAR_TYPE_RATNEG,
12074 CMDLINE_PAR_TYPE_UNASSIGNED,
12075 CMDLINE_PAR_TYPE_UNASSIGNED,
12076 CMDLINE_PAR_TYPE_UNASSIGNED,
12077 CMDLINE_PAR_TYPE_UNASSIGNED,
12078 CMDLINE_PAR_TYPE_UNASSIGNED,
12079 CMDLINE_PAR_TYPE_UNASSIGNED,
12080 CMDLINE_PAR_TYPE_UNASSIGNED
12081 }
12082 },
12083 {
12084 cfSimple2ParRationalRationalMultiplication,
12085 {
12086 CMDLINE_PAR_TYPE_CMD_KEYTOKEN_TIMES,
12087 CMDLINE_PAR_TYPE_INTPOS,
12088 CMDLINE_PAR_TYPE_RATZERO,
12089 CMDLINE_PAR_TYPE_UNASSIGNED,
12090 CMDLINE_PAR_TYPE_UNASSIGNED,
12091 CMDLINE_PAR_TYPE_UNASSIGNED,
12092 CMDLINE_PAR_TYPE_UNASSIGNED,
12093 CMDLINE_PAR_TYPE_UNASSIGNED,
12094 CMDLINE_PAR_TYPE_UNASSIGNED,
12095 CMDLINE_PAR_TYPE_UNASSIGNED
12096 }
12097 },
12098 {
12099 cfSimple2ParRationalRationalMultiplication,
12100 {
12101 CMDLINE_PAR_TYPE_CMD_KEYTOKEN_TIMES,
12102 CMDLINE_PAR_TYPE_INTPOS,
12103 CMDLINE_PAR_TYPE_RATPOS,
12104 CMDLINE_PAR_TYPE_UNASSIGNED,
12105 CMDLINE_PAR_TYPE_UNASSIGNED,
12106 CMDLINE_PAR_TYPE_UNASSIGNED,
12107 CMDLINE_PAR_TYPE_UNASSIGNED,
12108 CMDLINE_PAR_TYPE_UNASSIGNED,
12109 CMDLINE_PAR_TYPE_UNASSIGNED,
12110 CMDLINE_PAR_TYPE_UNASSIGNED
12111 }
12112 },
12113 {
12114 cfSimple2ParRationalRationalMultiplication,
12115 {
12116 CMDLINE_PAR_TYPE_CMD_KEYTOKEN_TIMES,
12117 CMDLINE_PAR_TYPE_RATNEG,
12118 CMDLINE_PAR_TYPE_INTNEG,
12119 CMDLINE_PAR_TYPE_UNASSIGNED,
12120 CMDLINE_PAR_TYPE_UNASSIGNED,
12121 CMDLINE_PAR_TYPE_UNASSIGNED,
12122 CMDLINE_PAR_TYPE_UNASSIGNED,
12123 CMDLINE_PAR_TYPE_UNASSIGNED,
12124 CMDLINE_PAR_TYPE_UNASSIGNED,
12125 CMDLINE_PAR_TYPE_UNASSIGNED
12126 }
12127 },
12128 {
12129 cfSimple2ParRationalRationalMultiplication,
12130 {
12131 CMDLINE_PAR_TYPE_CMD_KEYTOKEN_TIMES,
12132 CMDLINE_PAR_TYPE_RATNEG,
12133 CMDLINE_PAR_TYPE_INTZERO,
12134 CMDLINE_PAR_TYPE_UNASSIGNED,
12135 CMDLINE_PAR_TYPE_UNASSIGNED,
12136 CMDLINE_PAR_TYPE_UNASSIGNED,
12137 CMDLINE_PAR_TYPE_UNASSIGNED,
12138 CMDLINE_PAR_TYPE_UNASSIGNED,
12139 CMDLINE_PAR_TYPE_UNASSIGNED,
12140 CMDLINE_PAR_TYPE_UNASSIGNED
12141 }
12142 },
12143 {
12144 cfSimple2ParRationalRationalMultiplication,
12145 {
12146 CMDLINE_PAR_TYPE_CMD_KEYTOKEN_TIMES,
12147 CMDLINE_PAR_TYPE_RATNEG,
12148 CMDLINE_PAR_TYPE_INTPOS,
12149 CMDLINE_PAR_TYPE_UNASSIGNED,
12150 CMDLINE_PAR_TYPE_UNASSIGNED,
12151 CMDLINE_PAR_TYPE_UNASSIGNED,
12152 CMDLINE_PAR_TYPE_UNASSIGNED,
12153 CMDLINE_PAR_TYPE_UNASSIGNED,
12154 CMDLINE_PAR_TYPE_UNASSIGNED,
12155 CMDLINE_PAR_TYPE_UNASSIGNED
12156 }
12157 },
12158 {
12159 cfSimple2ParRationalRationalMultiplication,
12160 {
12161 CMDLINE_PAR_TYPE_CMD_KEYTOKEN_TIMES,
12162 CMDLINE_PAR_TYPE_RATZERO,
12163 CMDLINE_PAR_TYPE_INTNEG,
12164 CMDLINE_PAR_TYPE_UNASSIGNED,
12165 CMDLINE_PAR_TYPE_UNASSIGNED,
12166 CMDLINE_PAR_TYPE_UNASSIGNED,
12167 CMDLINE_PAR_TYPE_UNASSIGNED,
12168 CMDLINE_PAR_TYPE_UNASSIGNED,
12169 CMDLINE_PAR_TYPE_UNASSIGNED,
12170 CMDLINE_PAR_TYPE_UNASSIGNED
12171 }
12172 },
12173 {
12174 cfSimple2ParRationalRationalMultiplication,
12175 {
12176 CMDLINE_PAR_TYPE_CMD_KEYTOKEN_TIMES,
12177 CMDLINE_PAR_TYPE_RATZERO,
12178 CMDLINE_PAR_TYPE_INTZERO,
12179 CMDLINE_PAR_TYPE_UNASSIGNED,
12180 CMDLINE_PAR_TYPE_UNASSIGNED,
12181 CMDLINE_PAR_TYPE_UNASSIGNED,
12182 CMDLINE_PAR_TYPE_UNASSIGNED,
12183 CMDLINE_PAR_TYPE_UNASSIGNED,
12184 CMDLINE_PAR_TYPE_UNASSIGNED,
12185 CMDLINE_PAR_TYPE_UNASSIGNED
12186 }
12187 },
12188 {
12189 cfSimple2ParRationalRationalMultiplication,
12190 {
12191 CMDLINE_PAR_TYPE_CMD_KEYTOKEN_TIMES,
12192 CMDLINE_PAR_TYPE_RATZERO,
12193 CMDLINE_PAR_TYPE_INTPOS,
12194 CMDLINE_PAR_TYPE_UNASSIGNED,
12195 CMDLINE_PAR_TYPE_UNASSIGNED,
12196 CMDLINE_PAR_TYPE_UNASSIGNED,
12197 CMDLINE_PAR_TYPE_UNASSIGNED,
12198 CMDLINE_PAR_TYPE_UNASSIGNED,
12199 CMDLINE_PAR_TYPE_UNASSIGNED,
12200 CMDLINE_PAR_TYPE_UNASSIGNED
12201 }
12202 },
12203 {
12204 cfSimple2ParRationalRationalMultiplication,
12205 {
12206 CMDLINE_PAR_TYPE_CMD_KEYTOKEN_TIMES,
12207 CMDLINE_PAR_TYPE_RATPOS,
12208 CMDLINE_PAR_TYPE_INTNEG,
12209 CMDLINE_PAR_TYPE_UNASSIGNED,
12210 CMDLINE_PAR_TYPE_UNASSIGNED,
12211 CMDLINE_PAR_TYPE_UNASSIGNED,
12212 CMDLINE_PAR_TYPE_UNASSIGNED,
12213 CMDLINE_PAR_TYPE_UNASSIGNED,
12214 CMDLINE_PAR_TYPE_UNASSIGNED,
12215 CMDLINE_PAR_TYPE_UNASSIGNED
12216 }
12217 },
12218 {
12219 cfSimple2ParRationalRationalMultiplication,
12220 {
12221 CMDLINE_PAR_TYPE_CMD_KEYTOKEN_TIMES,
12222 CMDLINE_PAR_TYPE_RATPOS,
12223 CMDLINE_PAR_TYPE_INTZERO,
12224 CMDLINE_PAR_TYPE_UNASSIGNED,
12225 CMDLINE_PAR_TYPE_UNASSIGNED,
12226 CMDLINE_PAR_TYPE_UNASSIGNED,
12227 CMDLINE_PAR_TYPE_UNASSIGNED,
12228 CMDLINE_PAR_TYPE_UNASSIGNED,
12229 CMDLINE_PAR_TYPE_UNASSIGNED,
12230 CMDLINE_PAR_TYPE_UNASSIGNED
12231 }
12232 },
12233 {
12234 cfSimple2ParRationalRationalMultiplication,
12235 {
12236 CMDLINE_PAR_TYPE_CMD_KEYTOKEN_TIMES,
12237 CMDLINE_PAR_TYPE_RATPOS,
12238 CMDLINE_PAR_TYPE_INTPOS,
12239 CMDLINE_PAR_TYPE_UNASSIGNED,
12240 CMDLINE_PAR_TYPE_UNASSIGNED,
12241 CMDLINE_PAR_TYPE_UNASSIGNED,
12242 CMDLINE_PAR_TYPE_UNASSIGNED,
12243 CMDLINE_PAR_TYPE_UNASSIGNED,
12244 CMDLINE_PAR_TYPE_UNASSIGNED,
12245 CMDLINE_PAR_TYPE_UNASSIGNED
12246 }
12247 },
12248 /* Simple exponentiation of two integers. Multiple templates are
12249 ** required.
12250 */
12251 {
12252 cfSimple2ParIntegerExponentiation,
12253 {
12254 CMDLINE_PAR_TYPE_CMD_KEYTOKEN_POWER,
12255 CMDLINE_PAR_TYPE_INTNEG,
12256 CMDLINE_PAR_TYPE_INTZERO,
12257 CMDLINE_PAR_TYPE_UNASSIGNED,
12258 CMDLINE_PAR_TYPE_UNASSIGNED,
12259 CMDLINE_PAR_TYPE_UNASSIGNED,
12260 CMDLINE_PAR_TYPE_UNASSIGNED,
12261 CMDLINE_PAR_TYPE_UNASSIGNED,
12262 CMDLINE_PAR_TYPE_UNASSIGNED,
12263 CMDLINE_PAR_TYPE_UNASSIGNED
12264 }
12265 },
12266 {
12267 cfSimple2ParIntegerExponentiation,
12268 {
12269 CMDLINE_PAR_TYPE_CMD_KEYTOKEN_POWER,
12270 CMDLINE_PAR_TYPE_INTNEG,
12271 CMDLINE_PAR_TYPE_INTPOS,
12272 CMDLINE_PAR_TYPE_UNASSIGNED,
12273 CMDLINE_PAR_TYPE_UNASSIGNED,
12274 CMDLINE_PAR_TYPE_UNASSIGNED,
12275 CMDLINE_PAR_TYPE_UNASSIGNED,
12276 CMDLINE_PAR_TYPE_UNASSIGNED,
12277 CMDLINE_PAR_TYPE_UNASSIGNED,
12278 CMDLINE_PAR_TYPE_UNASSIGNED
12279 }
12280 },
12281 {
12282 cfSimple2ParIntegerExponentiation,
12283 {
12284 CMDLINE_PAR_TYPE_CMD_KEYTOKEN_POWER,
12285 CMDLINE_PAR_TYPE_INTZERO,
12286 CMDLINE_PAR_TYPE_INTPOS,
12287 CMDLINE_PAR_TYPE_UNASSIGNED,
12288 CMDLINE_PAR_TYPE_UNASSIGNED,
12289 CMDLINE_PAR_TYPE_UNASSIGNED,
12290 CMDLINE_PAR_TYPE_UNASSIGNED,
12291 CMDLINE_PAR_TYPE_UNASSIGNED,
12292 CMDLINE_PAR_TYPE_UNASSIGNED,
12293 CMDLINE_PAR_TYPE_UNASSIGNED
12294 }
12295 },
12296 {
12297 cfSimple2ParIntegerExponentiation,
12298 {
12299 CMDLINE_PAR_TYPE_CMD_KEYTOKEN_POWER,
12300 CMDLINE_PAR_TYPE_INTPOS,
12301 CMDLINE_PAR_TYPE_INTZERO,
12302 CMDLINE_PAR_TYPE_UNASSIGNED,
12303 CMDLINE_PAR_TYPE_UNASSIGNED,
12304 CMDLINE_PAR_TYPE_UNASSIGNED,
12305 CMDLINE_PAR_TYPE_UNASSIGNED,
12306 CMDLINE_PAR_TYPE_UNASSIGNED,
12307 CMDLINE_PAR_TYPE_UNASSIGNED,
12308 CMDLINE_PAR_TYPE_UNASSIGNED
12309 }
12310 },
12311 {
12312 cfSimple2ParIntegerExponentiation,
12313 {
12314 CMDLINE_PAR_TYPE_CMD_KEYTOKEN_POWER,
12315 CMDLINE_PAR_TYPE_INTPOS,
12316 CMDLINE_PAR_TYPE_INTPOS,
12317 CMDLINE_PAR_TYPE_UNASSIGNED,
12318 CMDLINE_PAR_TYPE_UNASSIGNED,
12319 CMDLINE_PAR_TYPE_UNASSIGNED,
12320 CMDLINE_PAR_TYPE_UNASSIGNED,
12321 CMDLINE_PAR_TYPE_UNASSIGNED,
12322 CMDLINE_PAR_TYPE_UNASSIGNED,
12323 CMDLINE_PAR_TYPE_UNASSIGNED
12324 }
12325 },
12326 /* Simple exponentiation of rational number to an
12327 ** integer power. Multiple templates are
12328 ** required.
12329 */
12330 {
12331 cfSimple2ParIntegerExponentiationOfRational,
12332 {
12333 CMDLINE_PAR_TYPE_CMD_KEYTOKEN_POWER,
12334 CMDLINE_PAR_TYPE_RATNEG,
12335 CMDLINE_PAR_TYPE_INTZERO,
12336 CMDLINE_PAR_TYPE_UNASSIGNED,
12337 CMDLINE_PAR_TYPE_UNASSIGNED,
12338 CMDLINE_PAR_TYPE_UNASSIGNED,
12339 CMDLINE_PAR_TYPE_UNASSIGNED,
12340 CMDLINE_PAR_TYPE_UNASSIGNED,
12341 CMDLINE_PAR_TYPE_UNASSIGNED,
12342 CMDLINE_PAR_TYPE_UNASSIGNED
12343 }
12344 },
12345 {
12346 cfSimple2ParIntegerExponentiationOfRational,
12347 {
12348 CMDLINE_PAR_TYPE_CMD_KEYTOKEN_POWER,
12349 CMDLINE_PAR_TYPE_RATNEG,
12350 CMDLINE_PAR_TYPE_INTPOS,
12351 CMDLINE_PAR_TYPE_UNASSIGNED,
12352 CMDLINE_PAR_TYPE_UNASSIGNED,
12353 CMDLINE_PAR_TYPE_UNASSIGNED,
12354 CMDLINE_PAR_TYPE_UNASSIGNED,
12355 CMDLINE_PAR_TYPE_UNASSIGNED,
12356 CMDLINE_PAR_TYPE_UNASSIGNED,
12357 CMDLINE_PAR_TYPE_UNASSIGNED
12358 }
12359 },
12360 {
12361 cfSimple2ParIntegerExponentiationOfRational,
12362 {
12363 CMDLINE_PAR_TYPE_CMD_KEYTOKEN_POWER,
12364 CMDLINE_PAR_TYPE_RATZERO, /* Can't happen because will
12365 ** be converted to integer
12366 ** zero, but no harm in
12367 ** including in table.
12368 */
12369 CMDLINE_PAR_TYPE_INTPOS,
12370 CMDLINE_PAR_TYPE_UNASSIGNED,
12371 CMDLINE_PAR_TYPE_UNASSIGNED,
12372 CMDLINE_PAR_TYPE_UNASSIGNED,
12373 CMDLINE_PAR_TYPE_UNASSIGNED,
12374 CMDLINE_PAR_TYPE_UNASSIGNED,
12375 CMDLINE_PAR_TYPE_UNASSIGNED,
12376 CMDLINE_PAR_TYPE_UNASSIGNED
12377 }
12378 },
12379 {
12380 cfSimple2ParIntegerExponentiationOfRational,
12381 {
12382 CMDLINE_PAR_TYPE_CMD_KEYTOKEN_POWER,
12383 CMDLINE_PAR_TYPE_RATPOS,
12384 CMDLINE_PAR_TYPE_INTZERO,
12385 CMDLINE_PAR_TYPE_UNASSIGNED,
12386 CMDLINE_PAR_TYPE_UNASSIGNED,
12387 CMDLINE_PAR_TYPE_UNASSIGNED,
12388 CMDLINE_PAR_TYPE_UNASSIGNED,
12389 CMDLINE_PAR_TYPE_UNASSIGNED,
12390 CMDLINE_PAR_TYPE_UNASSIGNED,
12391 CMDLINE_PAR_TYPE_UNASSIGNED
12392 }
12393 },
12394 {
12395 cfSimple2ParIntegerExponentiationOfRational,
12396 {
12397 CMDLINE_PAR_TYPE_CMD_KEYTOKEN_POWER,
12398 CMDLINE_PAR_TYPE_RATPOS,
12399 CMDLINE_PAR_TYPE_INTPOS,
12400 CMDLINE_PAR_TYPE_UNASSIGNED,
12401 CMDLINE_PAR_TYPE_UNASSIGNED,
12402 CMDLINE_PAR_TYPE_UNASSIGNED,
12403 CMDLINE_PAR_TYPE_UNASSIGNED,
12404 CMDLINE_PAR_TYPE_UNASSIGNED,
12405 CMDLINE_PAR_TYPE_UNASSIGNED,
12406 CMDLINE_PAR_TYPE_UNASSIGNED
12407 }
12408 },
12409 /* Simple division of two integers. Multiple templates are
12410 ** required.
12411 */
12412 {
12413 cfSimple2ParIntegerQuotient,
12414 {
12415 CMDLINE_PAR_TYPE_CMD_KEYTOKEN_QUOTIENT,
12416 CMDLINE_PAR_TYPE_INTNEG,
12417 CMDLINE_PAR_TYPE_INTNEG,
12418 CMDLINE_PAR_TYPE_UNASSIGNED,
12419 CMDLINE_PAR_TYPE_UNASSIGNED,
12420 CMDLINE_PAR_TYPE_UNASSIGNED,
12421 CMDLINE_PAR_TYPE_UNASSIGNED,
12422 CMDLINE_PAR_TYPE_UNASSIGNED,
12423 CMDLINE_PAR_TYPE_UNASSIGNED,
12424 CMDLINE_PAR_TYPE_UNASSIGNED
12425 }
12426 },
12427 {
12428 cfSimple2ParIntegerQuotient,
12429 {
12430 CMDLINE_PAR_TYPE_CMD_KEYTOKEN_QUOTIENT,
12431 CMDLINE_PAR_TYPE_INTNEG,
12432 CMDLINE_PAR_TYPE_INTZERO,
12433 CMDLINE_PAR_TYPE_UNASSIGNED,
12434 CMDLINE_PAR_TYPE_UNASSIGNED,
12435 CMDLINE_PAR_TYPE_UNASSIGNED,
12436 CMDLINE_PAR_TYPE_UNASSIGNED,
12437 CMDLINE_PAR_TYPE_UNASSIGNED,
12438 CMDLINE_PAR_TYPE_UNASSIGNED,
12439 CMDLINE_PAR_TYPE_UNASSIGNED
12440 }
12441 },
12442 {
12443 cfSimple2ParIntegerQuotient,
12444 {
12445 CMDLINE_PAR_TYPE_CMD_KEYTOKEN_QUOTIENT,
12446 CMDLINE_PAR_TYPE_INTNEG,
12447 CMDLINE_PAR_TYPE_INTPOS,
12448 CMDLINE_PAR_TYPE_UNASSIGNED,
12449 CMDLINE_PAR_TYPE_UNASSIGNED,
12450 CMDLINE_PAR_TYPE_UNASSIGNED,
12451 CMDLINE_PAR_TYPE_UNASSIGNED,
12452 CMDLINE_PAR_TYPE_UNASSIGNED,
12453 CMDLINE_PAR_TYPE_UNASSIGNED,
12454 CMDLINE_PAR_TYPE_UNASSIGNED
12455 }
12456 },
12457 {
12458 cfSimple2ParIntegerQuotient,
12459 {
12460 CMDLINE_PAR_TYPE_CMD_KEYTOKEN_QUOTIENT,
12461 CMDLINE_PAR_TYPE_INTZERO,
12462 CMDLINE_PAR_TYPE_INTNEG,
12463 CMDLINE_PAR_TYPE_UNASSIGNED,
12464 CMDLINE_PAR_TYPE_UNASSIGNED,
12465 CMDLINE_PAR_TYPE_UNASSIGNED,
12466 CMDLINE_PAR_TYPE_UNASSIGNED,
12467 CMDLINE_PAR_TYPE_UNASSIGNED,
12468 CMDLINE_PAR_TYPE_UNASSIGNED,
12469 CMDLINE_PAR_TYPE_UNASSIGNED
12470 }
12471 },
12472 {
12473 cfSimple2ParIntegerQuotient,
12474 {
12475 CMDLINE_PAR_TYPE_CMD_KEYTOKEN_QUOTIENT,
12476 CMDLINE_PAR_TYPE_INTZERO,
12477 CMDLINE_PAR_TYPE_INTZERO,
12478 CMDLINE_PAR_TYPE_UNASSIGNED,
12479 CMDLINE_PAR_TYPE_UNASSIGNED,
12480 CMDLINE_PAR_TYPE_UNASSIGNED,
12481 CMDLINE_PAR_TYPE_UNASSIGNED,
12482 CMDLINE_PAR_TYPE_UNASSIGNED,
12483 CMDLINE_PAR_TYPE_UNASSIGNED,
12484 CMDLINE_PAR_TYPE_UNASSIGNED
12485 }
12486 },
12487 {
12488 cfSimple2ParIntegerQuotient,
12489 {
12490 CMDLINE_PAR_TYPE_CMD_KEYTOKEN_QUOTIENT,
12491 CMDLINE_PAR_TYPE_INTZERO,
12492 CMDLINE_PAR_TYPE_INTPOS,
12493 CMDLINE_PAR_TYPE_UNASSIGNED,
12494 CMDLINE_PAR_TYPE_UNASSIGNED,
12495 CMDLINE_PAR_TYPE_UNASSIGNED,
12496 CMDLINE_PAR_TYPE_UNASSIGNED,
12497 CMDLINE_PAR_TYPE_UNASSIGNED,
12498 CMDLINE_PAR_TYPE_UNASSIGNED,
12499 CMDLINE_PAR_TYPE_UNASSIGNED
12500 }
12501 },
12502 {
12503 cfSimple2ParIntegerQuotient,
12504 {
12505 CMDLINE_PAR_TYPE_CMD_KEYTOKEN_QUOTIENT,
12506 CMDLINE_PAR_TYPE_INTPOS,
12507 CMDLINE_PAR_TYPE_INTNEG,
12508 CMDLINE_PAR_TYPE_UNASSIGNED,
12509 CMDLINE_PAR_TYPE_UNASSIGNED,
12510 CMDLINE_PAR_TYPE_UNASSIGNED,
12511 CMDLINE_PAR_TYPE_UNASSIGNED,
12512 CMDLINE_PAR_TYPE_UNASSIGNED,
12513 CMDLINE_PAR_TYPE_UNASSIGNED,
12514 CMDLINE_PAR_TYPE_UNASSIGNED
12515 }
12516 },
12517 {
12518 cfSimple2ParIntegerQuotient,
12519 {
12520 CMDLINE_PAR_TYPE_CMD_KEYTOKEN_QUOTIENT,
12521 CMDLINE_PAR_TYPE_INTPOS,
12522 CMDLINE_PAR_TYPE_INTZERO,
12523 CMDLINE_PAR_TYPE_UNASSIGNED,
12524 CMDLINE_PAR_TYPE_UNASSIGNED,
12525 CMDLINE_PAR_TYPE_UNASSIGNED,
12526 CMDLINE_PAR_TYPE_UNASSIGNED,
12527 CMDLINE_PAR_TYPE_UNASSIGNED,
12528 CMDLINE_PAR_TYPE_UNASSIGNED,
12529 CMDLINE_PAR_TYPE_UNASSIGNED
12530 }
12531 },
12532 {
12533 cfSimple2ParIntegerQuotient,
12534 {
12535 CMDLINE_PAR_TYPE_CMD_KEYTOKEN_QUOTIENT,
12536 CMDLINE_PAR_TYPE_INTPOS,
12537 CMDLINE_PAR_TYPE_INTPOS,
12538 CMDLINE_PAR_TYPE_UNASSIGNED,
12539 CMDLINE_PAR_TYPE_UNASSIGNED,
12540 CMDLINE_PAR_TYPE_UNASSIGNED,
12541 CMDLINE_PAR_TYPE_UNASSIGNED,
12542 CMDLINE_PAR_TYPE_UNASSIGNED,
12543 CMDLINE_PAR_TYPE_UNASSIGNED,
12544 CMDLINE_PAR_TYPE_UNASSIGNED
12545 }
12546 },
12547 /* Simple modulo of two integers. Multiple templates are
12548 ** required.
12549 */
12550 {
12551 cfSimple2ParIntegerRemainder,
12552 {
12553 CMDLINE_PAR_TYPE_CMD_KEYTOKEN_MODULO,
12554 CMDLINE_PAR_TYPE_INTNEG,
12555 CMDLINE_PAR_TYPE_INTNEG,
12556 CMDLINE_PAR_TYPE_UNASSIGNED,
12557 CMDLINE_PAR_TYPE_UNASSIGNED,
12558 CMDLINE_PAR_TYPE_UNASSIGNED,
12559 CMDLINE_PAR_TYPE_UNASSIGNED,
12560 CMDLINE_PAR_TYPE_UNASSIGNED,
12561 CMDLINE_PAR_TYPE_UNASSIGNED,
12562 CMDLINE_PAR_TYPE_UNASSIGNED
12563 }
12564 },
12565 {
12566 cfSimple2ParIntegerRemainder,
12567 {
12568 CMDLINE_PAR_TYPE_CMD_KEYTOKEN_MODULO,
12569 CMDLINE_PAR_TYPE_INTNEG,
12570 CMDLINE_PAR_TYPE_INTZERO,
12571 CMDLINE_PAR_TYPE_UNASSIGNED,
12572 CMDLINE_PAR_TYPE_UNASSIGNED,
12573 CMDLINE_PAR_TYPE_UNASSIGNED,
12574 CMDLINE_PAR_TYPE_UNASSIGNED,
12575 CMDLINE_PAR_TYPE_UNASSIGNED,
12576 CMDLINE_PAR_TYPE_UNASSIGNED,
12577 CMDLINE_PAR_TYPE_UNASSIGNED
12578 }
12579 },
12580 {
12581 cfSimple2ParIntegerRemainder,
12582 {
12583 CMDLINE_PAR_TYPE_CMD_KEYTOKEN_MODULO,
12584 CMDLINE_PAR_TYPE_INTNEG,
12585 CMDLINE_PAR_TYPE_INTPOS,
12586 CMDLINE_PAR_TYPE_UNASSIGNED,
12587 CMDLINE_PAR_TYPE_UNASSIGNED,
12588 CMDLINE_PAR_TYPE_UNASSIGNED,
12589 CMDLINE_PAR_TYPE_UNASSIGNED,
12590 CMDLINE_PAR_TYPE_UNASSIGNED,
12591 CMDLINE_PAR_TYPE_UNASSIGNED,
12592 CMDLINE_PAR_TYPE_UNASSIGNED
12593 }
12594 },
12595 {
12596 cfSimple2ParIntegerRemainder,
12597 {
12598 CMDLINE_PAR_TYPE_CMD_KEYTOKEN_MODULO,
12599 CMDLINE_PAR_TYPE_INTZERO,
12600 CMDLINE_PAR_TYPE_INTNEG,
12601 CMDLINE_PAR_TYPE_UNASSIGNED,
12602 CMDLINE_PAR_TYPE_UNASSIGNED,
12603 CMDLINE_PAR_TYPE_UNASSIGNED,
12604 CMDLINE_PAR_TYPE_UNASSIGNED,
12605 CMDLINE_PAR_TYPE_UNASSIGNED,
12606 CMDLINE_PAR_TYPE_UNASSIGNED,
12607 CMDLINE_PAR_TYPE_UNASSIGNED
12608 }
12609 },
12610 {
12611 cfSimple2ParIntegerRemainder,
12612 {
12613 CMDLINE_PAR_TYPE_CMD_KEYTOKEN_MODULO,
12614 CMDLINE_PAR_TYPE_INTZERO,
12615 CMDLINE_PAR_TYPE_INTZERO,
12616 CMDLINE_PAR_TYPE_UNASSIGNED,
12617 CMDLINE_PAR_TYPE_UNASSIGNED,
12618 CMDLINE_PAR_TYPE_UNASSIGNED,
12619 CMDLINE_PAR_TYPE_UNASSIGNED,
12620 CMDLINE_PAR_TYPE_UNASSIGNED,
12621 CMDLINE_PAR_TYPE_UNASSIGNED,
12622 CMDLINE_PAR_TYPE_UNASSIGNED
12623 }
12624 },
12625 {
12626 cfSimple2ParIntegerRemainder,
12627 {
12628 CMDLINE_PAR_TYPE_CMD_KEYTOKEN_MODULO,
12629 CMDLINE_PAR_TYPE_INTZERO,
12630 CMDLINE_PAR_TYPE_INTPOS,
12631 CMDLINE_PAR_TYPE_UNASSIGNED,
12632 CMDLINE_PAR_TYPE_UNASSIGNED,
12633 CMDLINE_PAR_TYPE_UNASSIGNED,
12634 CMDLINE_PAR_TYPE_UNASSIGNED,
12635 CMDLINE_PAR_TYPE_UNASSIGNED,
12636 CMDLINE_PAR_TYPE_UNASSIGNED,
12637 CMDLINE_PAR_TYPE_UNASSIGNED
12638 }
12639 },
12640 {
12641 cfSimple2ParIntegerRemainder,
12642 {
12643 CMDLINE_PAR_TYPE_CMD_KEYTOKEN_MODULO,
12644 CMDLINE_PAR_TYPE_INTPOS,
12645 CMDLINE_PAR_TYPE_INTNEG,
12646 CMDLINE_PAR_TYPE_UNASSIGNED,
12647 CMDLINE_PAR_TYPE_UNASSIGNED,
12648 CMDLINE_PAR_TYPE_UNASSIGNED,
12649 CMDLINE_PAR_TYPE_UNASSIGNED,
12650 CMDLINE_PAR_TYPE_UNASSIGNED,
12651 CMDLINE_PAR_TYPE_UNASSIGNED,
12652 CMDLINE_PAR_TYPE_UNASSIGNED
12653 }
12654 },
12655 {
12656 cfSimple2ParIntegerRemainder,
12657 {
12658 CMDLINE_PAR_TYPE_CMD_KEYTOKEN_MODULO,
12659 CMDLINE_PAR_TYPE_INTPOS,
12660 CMDLINE_PAR_TYPE_INTZERO,
12661 CMDLINE_PAR_TYPE_UNASSIGNED,
12662 CMDLINE_PAR_TYPE_UNASSIGNED,
12663 CMDLINE_PAR_TYPE_UNASSIGNED,
12664 CMDLINE_PAR_TYPE_UNASSIGNED,
12665 CMDLINE_PAR_TYPE_UNASSIGNED,
12666 CMDLINE_PAR_TYPE_UNASSIGNED,
12667 CMDLINE_PAR_TYPE_UNASSIGNED
12668 }
12669 },
12670 {
12671 cfSimple2ParIntegerRemainder,
12672 {
12673 CMDLINE_PAR_TYPE_CMD_KEYTOKEN_MODULO,
12674 CMDLINE_PAR_TYPE_INTPOS,
12675 CMDLINE_PAR_TYPE_INTPOS,
12676 CMDLINE_PAR_TYPE_UNASSIGNED,
12677 CMDLINE_PAR_TYPE_UNASSIGNED,
12678 CMDLINE_PAR_TYPE_UNASSIGNED,
12679 CMDLINE_PAR_TYPE_UNASSIGNED,
12680 CMDLINE_PAR_TYPE_UNASSIGNED,
12681 CMDLINE_PAR_TYPE_UNASSIGNED,
12682 CMDLINE_PAR_TYPE_UNASSIGNED
12683 }
12684 },
12685 /* Simple division of two rational numbers.
12686 ** Multiple templates are required.
12687 */
12688 {
12689 cfSimple2ParRationalRationalQuotient,
12690 {
12691 CMDLINE_PAR_TYPE_CMD_KEYTOKEN_QUOTIENT,
12692 CMDLINE_PAR_TYPE_RATNEG,
12693 CMDLINE_PAR_TYPE_RATNEG,
12694 CMDLINE_PAR_TYPE_UNASSIGNED,
12695 CMDLINE_PAR_TYPE_UNASSIGNED,
12696 CMDLINE_PAR_TYPE_UNASSIGNED,
12697 CMDLINE_PAR_TYPE_UNASSIGNED,
12698 CMDLINE_PAR_TYPE_UNASSIGNED,
12699 CMDLINE_PAR_TYPE_UNASSIGNED,
12700 CMDLINE_PAR_TYPE_UNASSIGNED
12701 }
12702 },
12703 {
12704 cfSimple2ParRationalRationalQuotient,
12705 {
12706 CMDLINE_PAR_TYPE_CMD_KEYTOKEN_QUOTIENT,
12707 CMDLINE_PAR_TYPE_RATNEG,
12708 CMDLINE_PAR_TYPE_RATPOS,
12709 CMDLINE_PAR_TYPE_UNASSIGNED,
12710 CMDLINE_PAR_TYPE_UNASSIGNED,
12711 CMDLINE_PAR_TYPE_UNASSIGNED,
12712 CMDLINE_PAR_TYPE_UNASSIGNED,
12713 CMDLINE_PAR_TYPE_UNASSIGNED,
12714 CMDLINE_PAR_TYPE_UNASSIGNED,
12715 CMDLINE_PAR_TYPE_UNASSIGNED
12716 }
12717 },
12718 {
12719 cfSimple2ParRationalRationalQuotient,
12720 {
12721 CMDLINE_PAR_TYPE_CMD_KEYTOKEN_QUOTIENT,
12722 CMDLINE_PAR_TYPE_RATZERO,
12723 CMDLINE_PAR_TYPE_RATNEG,
12724 CMDLINE_PAR_TYPE_UNASSIGNED,
12725 CMDLINE_PAR_TYPE_UNASSIGNED,
12726 CMDLINE_PAR_TYPE_UNASSIGNED,
12727 CMDLINE_PAR_TYPE_UNASSIGNED,
12728 CMDLINE_PAR_TYPE_UNASSIGNED,
12729 CMDLINE_PAR_TYPE_UNASSIGNED,
12730 CMDLINE_PAR_TYPE_UNASSIGNED
12731 }
12732 },
12733 {
12734 cfSimple2ParRationalRationalQuotient,
12735 {
12736 CMDLINE_PAR_TYPE_CMD_KEYTOKEN_QUOTIENT,
12737 CMDLINE_PAR_TYPE_RATZERO,
12738 CMDLINE_PAR_TYPE_RATPOS,
12739 CMDLINE_PAR_TYPE_UNASSIGNED,
12740 CMDLINE_PAR_TYPE_UNASSIGNED,
12741 CMDLINE_PAR_TYPE_UNASSIGNED,
12742 CMDLINE_PAR_TYPE_UNASSIGNED,
12743 CMDLINE_PAR_TYPE_UNASSIGNED,
12744 CMDLINE_PAR_TYPE_UNASSIGNED,
12745 CMDLINE_PAR_TYPE_UNASSIGNED
12746 }
12747 },
12748 {
12749 cfSimple2ParRationalRationalQuotient,
12750 {
12751 CMDLINE_PAR_TYPE_CMD_KEYTOKEN_QUOTIENT,
12752 CMDLINE_PAR_TYPE_RATPOS,
12753 CMDLINE_PAR_TYPE_RATNEG,
12754 CMDLINE_PAR_TYPE_UNASSIGNED,
12755 CMDLINE_PAR_TYPE_UNASSIGNED,
12756 CMDLINE_PAR_TYPE_UNASSIGNED,
12757 CMDLINE_PAR_TYPE_UNASSIGNED,
12758 CMDLINE_PAR_TYPE_UNASSIGNED,
12759 CMDLINE_PAR_TYPE_UNASSIGNED,
12760 CMDLINE_PAR_TYPE_UNASSIGNED
12761 }
12762 },
12763 {
12764 cfSimple2ParRationalRationalQuotient,
12765 {
12766 CMDLINE_PAR_TYPE_CMD_KEYTOKEN_QUOTIENT,
12767 CMDLINE_PAR_TYPE_RATPOS,
12768 CMDLINE_PAR_TYPE_RATPOS,
12769 CMDLINE_PAR_TYPE_UNASSIGNED,
12770 CMDLINE_PAR_TYPE_UNASSIGNED,
12771 CMDLINE_PAR_TYPE_UNASSIGNED,
12772 CMDLINE_PAR_TYPE_UNASSIGNED,
12773 CMDLINE_PAR_TYPE_UNASSIGNED,
12774 CMDLINE_PAR_TYPE_UNASSIGNED,
12775 CMDLINE_PAR_TYPE_UNASSIGNED
12776 }
12777 },
12778 {
12779 cfSimple2ParRationalRationalQuotient,
12780 {
12781 CMDLINE_PAR_TYPE_CMD_KEYTOKEN_QUOTIENT,
12782 CMDLINE_PAR_TYPE_INTNEG,
12783 CMDLINE_PAR_TYPE_RATNEG,
12784 CMDLINE_PAR_TYPE_UNASSIGNED,
12785 CMDLINE_PAR_TYPE_UNASSIGNED,
12786 CMDLINE_PAR_TYPE_UNASSIGNED,
12787 CMDLINE_PAR_TYPE_UNASSIGNED,
12788 CMDLINE_PAR_TYPE_UNASSIGNED,
12789 CMDLINE_PAR_TYPE_UNASSIGNED,
12790 CMDLINE_PAR_TYPE_UNASSIGNED
12791 }
12792 },
12793 {
12794 cfSimple2ParRationalRationalQuotient,
12795 {
12796 CMDLINE_PAR_TYPE_CMD_KEYTOKEN_QUOTIENT,
12797 CMDLINE_PAR_TYPE_INTNEG,
12798 CMDLINE_PAR_TYPE_RATPOS,
12799 CMDLINE_PAR_TYPE_UNASSIGNED,
12800 CMDLINE_PAR_TYPE_UNASSIGNED,
12801 CMDLINE_PAR_TYPE_UNASSIGNED,
12802 CMDLINE_PAR_TYPE_UNASSIGNED,
12803 CMDLINE_PAR_TYPE_UNASSIGNED,
12804 CMDLINE_PAR_TYPE_UNASSIGNED,
12805 CMDLINE_PAR_TYPE_UNASSIGNED
12806 }
12807 },
12808 {
12809 cfSimple2ParRationalRationalQuotient,
12810 {
12811 CMDLINE_PAR_TYPE_CMD_KEYTOKEN_QUOTIENT,
12812 CMDLINE_PAR_TYPE_INTZERO,
12813 CMDLINE_PAR_TYPE_RATNEG,
12814 CMDLINE_PAR_TYPE_UNASSIGNED,
12815 CMDLINE_PAR_TYPE_UNASSIGNED,
12816 CMDLINE_PAR_TYPE_UNASSIGNED,
12817 CMDLINE_PAR_TYPE_UNASSIGNED,
12818 CMDLINE_PAR_TYPE_UNASSIGNED,
12819 CMDLINE_PAR_TYPE_UNASSIGNED,
12820 CMDLINE_PAR_TYPE_UNASSIGNED
12821 }
12822 },
12823 {
12824 cfSimple2ParRationalRationalQuotient,
12825 {
12826 CMDLINE_PAR_TYPE_CMD_KEYTOKEN_QUOTIENT,
12827 CMDLINE_PAR_TYPE_INTZERO,
12828 CMDLINE_PAR_TYPE_RATPOS,
12829 CMDLINE_PAR_TYPE_UNASSIGNED,
12830 CMDLINE_PAR_TYPE_UNASSIGNED,
12831 CMDLINE_PAR_TYPE_UNASSIGNED,
12832 CMDLINE_PAR_TYPE_UNASSIGNED,
12833 CMDLINE_PAR_TYPE_UNASSIGNED,
12834 CMDLINE_PAR_TYPE_UNASSIGNED,
12835 CMDLINE_PAR_TYPE_UNASSIGNED
12836 }
12837 },
12838 {
12839 cfSimple2ParRationalRationalQuotient,
12840 {
12841 CMDLINE_PAR_TYPE_CMD_KEYTOKEN_QUOTIENT,
12842 CMDLINE_PAR_TYPE_INTPOS,
12843 CMDLINE_PAR_TYPE_RATNEG,
12844 CMDLINE_PAR_TYPE_UNASSIGNED,
12845 CMDLINE_PAR_TYPE_UNASSIGNED,
12846 CMDLINE_PAR_TYPE_UNASSIGNED,
12847 CMDLINE_PAR_TYPE_UNASSIGNED,
12848 CMDLINE_PAR_TYPE_UNASSIGNED,
12849 CMDLINE_PAR_TYPE_UNASSIGNED,
12850 CMDLINE_PAR_TYPE_UNASSIGNED
12851 }
12852 },
12853 {
12854 cfSimple2ParRationalRationalQuotient,
12855 {
12856 CMDLINE_PAR_TYPE_CMD_KEYTOKEN_QUOTIENT,
12857 CMDLINE_PAR_TYPE_INTPOS,
12858 CMDLINE_PAR_TYPE_RATPOS,
12859 CMDLINE_PAR_TYPE_UNASSIGNED,
12860 CMDLINE_PAR_TYPE_UNASSIGNED,
12861 CMDLINE_PAR_TYPE_UNASSIGNED,
12862 CMDLINE_PAR_TYPE_UNASSIGNED,
12863 CMDLINE_PAR_TYPE_UNASSIGNED,
12864 CMDLINE_PAR_TYPE_UNASSIGNED,
12865 CMDLINE_PAR_TYPE_UNASSIGNED
12866 }
12867 },
12868 {
12869 cfSimple2ParRationalRationalQuotient,
12870 {
12871 CMDLINE_PAR_TYPE_CMD_KEYTOKEN_QUOTIENT,
12872 CMDLINE_PAR_TYPE_RATNEG,
12873 CMDLINE_PAR_TYPE_INTNEG,
12874 CMDLINE_PAR_TYPE_UNASSIGNED,
12875 CMDLINE_PAR_TYPE_UNASSIGNED,
12876 CMDLINE_PAR_TYPE_UNASSIGNED,
12877 CMDLINE_PAR_TYPE_UNASSIGNED,
12878 CMDLINE_PAR_TYPE_UNASSIGNED,
12879 CMDLINE_PAR_TYPE_UNASSIGNED,
12880 CMDLINE_PAR_TYPE_UNASSIGNED
12881 }
12882 },
12883 {
12884 cfSimple2ParRationalRationalQuotient,
12885 {
12886 CMDLINE_PAR_TYPE_CMD_KEYTOKEN_QUOTIENT,
12887 CMDLINE_PAR_TYPE_RATNEG,
12888 CMDLINE_PAR_TYPE_INTPOS,
12889 CMDLINE_PAR_TYPE_UNASSIGNED,
12890 CMDLINE_PAR_TYPE_UNASSIGNED,
12891 CMDLINE_PAR_TYPE_UNASSIGNED,
12892 CMDLINE_PAR_TYPE_UNASSIGNED,
12893 CMDLINE_PAR_TYPE_UNASSIGNED,
12894 CMDLINE_PAR_TYPE_UNASSIGNED,
12895 CMDLINE_PAR_TYPE_UNASSIGNED
12896 }
12897 },
12898 {
12899 cfSimple2ParRationalRationalQuotient,
12900 {
12901 CMDLINE_PAR_TYPE_CMD_KEYTOKEN_QUOTIENT,
12902 CMDLINE_PAR_TYPE_RATZERO,
12903 CMDLINE_PAR_TYPE_INTNEG,
12904 CMDLINE_PAR_TYPE_UNASSIGNED,
12905 CMDLINE_PAR_TYPE_UNASSIGNED,
12906 CMDLINE_PAR_TYPE_UNASSIGNED,
12907 CMDLINE_PAR_TYPE_UNASSIGNED,
12908 CMDLINE_PAR_TYPE_UNASSIGNED,
12909 CMDLINE_PAR_TYPE_UNASSIGNED,
12910 CMDLINE_PAR_TYPE_UNASSIGNED
12911 }
12912 },
12913 {
12914 cfSimple2ParRationalRationalQuotient,
12915 {
12916 CMDLINE_PAR_TYPE_CMD_KEYTOKEN_QUOTIENT,
12917 CMDLINE_PAR_TYPE_RATZERO,
12918 CMDLINE_PAR_TYPE_INTPOS,
12919 CMDLINE_PAR_TYPE_UNASSIGNED,
12920 CMDLINE_PAR_TYPE_UNASSIGNED,
12921 CMDLINE_PAR_TYPE_UNASSIGNED,
12922 CMDLINE_PAR_TYPE_UNASSIGNED,
12923 CMDLINE_PAR_TYPE_UNASSIGNED,
12924 CMDLINE_PAR_TYPE_UNASSIGNED,
12925 CMDLINE_PAR_TYPE_UNASSIGNED
12926 }
12927 },
12928 {
12929 cfSimple2ParRationalRationalQuotient,
12930 {
12931 CMDLINE_PAR_TYPE_CMD_KEYTOKEN_QUOTIENT,
12932 CMDLINE_PAR_TYPE_RATPOS,
12933 CMDLINE_PAR_TYPE_INTNEG,
12934 CMDLINE_PAR_TYPE_UNASSIGNED,
12935 CMDLINE_PAR_TYPE_UNASSIGNED,
12936 CMDLINE_PAR_TYPE_UNASSIGNED,
12937 CMDLINE_PAR_TYPE_UNASSIGNED,
12938 CMDLINE_PAR_TYPE_UNASSIGNED,
12939 CMDLINE_PAR_TYPE_UNASSIGNED,
12940 CMDLINE_PAR_TYPE_UNASSIGNED
12941 }
12942 },
12943 {
12944 cfSimple2ParRationalRationalQuotient,
12945 {
12946 CMDLINE_PAR_TYPE_CMD_KEYTOKEN_QUOTIENT,
12947 CMDLINE_PAR_TYPE_RATPOS,
12948 CMDLINE_PAR_TYPE_INTPOS,
12949 CMDLINE_PAR_TYPE_UNASSIGNED,
12950 CMDLINE_PAR_TYPE_UNASSIGNED,
12951 CMDLINE_PAR_TYPE_UNASSIGNED,
12952 CMDLINE_PAR_TYPE_UNASSIGNED,
12953 CMDLINE_PAR_TYPE_UNASSIGNED,
12954 CMDLINE_PAR_TYPE_UNASSIGNED,
12955 CMDLINE_PAR_TYPE_UNASSIGNED
12956 }
12957 },
12958 /* GCD
12959 */
12960 {
12961 cfSimple2ParIntegerGcd,
12962 {
12963 CMDLINE_PAR_TYPE_CMD_KEYTOKEN_GCD,
12964 CMDLINE_PAR_TYPE_INTPOS,
12965 CMDLINE_PAR_TYPE_INTPOS,
12966 CMDLINE_PAR_TYPE_UNASSIGNED,
12967 CMDLINE_PAR_TYPE_UNASSIGNED,
12968 CMDLINE_PAR_TYPE_UNASSIGNED,
12969 CMDLINE_PAR_TYPE_UNASSIGNED,
12970 CMDLINE_PAR_TYPE_UNASSIGNED,
12971 CMDLINE_PAR_TYPE_UNASSIGNED,
12972 CMDLINE_PAR_TYPE_UNASSIGNED
12973 }
12974 },
12975 /* DAP */
12976 {
12977 cfDap,
12978 {
12979 CMDLINE_PAR_TYPE_CMD_KEYTOKEN_DAP,
12980 CMDLINE_PAR_TYPE_RATNEG,
12981 CMDLINE_PAR_TYPE_UNASSIGNED,
12982 CMDLINE_PAR_TYPE_UNASSIGNED,
12983 CMDLINE_PAR_TYPE_UNASSIGNED,
12984 CMDLINE_PAR_TYPE_UNASSIGNED,
12985 CMDLINE_PAR_TYPE_UNASSIGNED,
12986 CMDLINE_PAR_TYPE_UNASSIGNED,
12987 CMDLINE_PAR_TYPE_UNASSIGNED,
12988 CMDLINE_PAR_TYPE_UNASSIGNED
12989 }
12990 },
12991 {
12992 cfDap,
12993 {
12994 CMDLINE_PAR_TYPE_CMD_KEYTOKEN_DAP,
12995 CMDLINE_PAR_TYPE_RATNEG,
12996 CMDLINE_PAR_TYPE_INTPOS,
12997 CMDLINE_PAR_TYPE_UNASSIGNED,
12998 CMDLINE_PAR_TYPE_UNASSIGNED,
12999 CMDLINE_PAR_TYPE_UNASSIGNED,
13000 CMDLINE_PAR_TYPE_UNASSIGNED,
13001 CMDLINE_PAR_TYPE_UNASSIGNED,
13002 CMDLINE_PAR_TYPE_UNASSIGNED,
13003 CMDLINE_PAR_TYPE_UNASSIGNED
13004 }
13005 },
13006 {
13007 cfDap,
13008 {
13009 CMDLINE_PAR_TYPE_CMD_KEYTOKEN_DAP,
13010 CMDLINE_PAR_TYPE_RATZERO,
13011 CMDLINE_PAR_TYPE_UNASSIGNED,
13012 CMDLINE_PAR_TYPE_UNASSIGNED,
13013 CMDLINE_PAR_TYPE_UNASSIGNED,
13014 CMDLINE_PAR_TYPE_UNASSIGNED,
13015 CMDLINE_PAR_TYPE_UNASSIGNED,
13016 CMDLINE_PAR_TYPE_UNASSIGNED,
13017 CMDLINE_PAR_TYPE_UNASSIGNED,
13018 CMDLINE_PAR_TYPE_UNASSIGNED
13019 }
13020 },
13021 {
13022 cfDap,
13023 {
13024 CMDLINE_PAR_TYPE_CMD_KEYTOKEN_DAP,
13025 CMDLINE_PAR_TYPE_RATZERO,
13026 CMDLINE_PAR_TYPE_INTPOS,
13027 CMDLINE_PAR_TYPE_UNASSIGNED,
13028 CMDLINE_PAR_TYPE_UNASSIGNED,
13029 CMDLINE_PAR_TYPE_UNASSIGNED,
13030 CMDLINE_PAR_TYPE_UNASSIGNED,
13031 CMDLINE_PAR_TYPE_UNASSIGNED,
13032 CMDLINE_PAR_TYPE_UNASSIGNED,
13033 CMDLINE_PAR_TYPE_UNASSIGNED
13034 }
13035 },
13036 {
13037 cfDap,
13038 {
13039 CMDLINE_PAR_TYPE_CMD_KEYTOKEN_DAP,
13040 CMDLINE_PAR_TYPE_RATPOS,
13041 CMDLINE_PAR_TYPE_UNASSIGNED,
13042 CMDLINE_PAR_TYPE_UNASSIGNED,
13043 CMDLINE_PAR_TYPE_UNASSIGNED,
13044 CMDLINE_PAR_TYPE_UNASSIGNED,
13045 CMDLINE_PAR_TYPE_UNASSIGNED,
13046 CMDLINE_PAR_TYPE_UNASSIGNED,
13047 CMDLINE_PAR_TYPE_UNASSIGNED,
13048 CMDLINE_PAR_TYPE_UNASSIGNED
13049 }
13050 },
13051 {
13052 cfDap,
13053 {
13054 CMDLINE_PAR_TYPE_CMD_KEYTOKEN_DAP,
13055 CMDLINE_PAR_TYPE_RATPOS,
13056 CMDLINE_PAR_TYPE_INTPOS,
13057 CMDLINE_PAR_TYPE_UNASSIGNED,
13058 CMDLINE_PAR_TYPE_UNASSIGNED,
13059 CMDLINE_PAR_TYPE_UNASSIGNED,
13060 CMDLINE_PAR_TYPE_UNASSIGNED,
13061 CMDLINE_PAR_TYPE_UNASSIGNED,
13062 CMDLINE_PAR_TYPE_UNASSIGNED,
13063 CMDLINE_PAR_TYPE_UNASSIGNED
13064 }
13065 },
13066 {
13067 cfDap,
13068 {
13069 CMDLINE_PAR_TYPE_CMD_KEYTOKEN_DAP,
13070 CMDLINE_PAR_TYPE_INTNEG,
13071 CMDLINE_PAR_TYPE_UNASSIGNED,
13072 CMDLINE_PAR_TYPE_UNASSIGNED,
13073 CMDLINE_PAR_TYPE_UNASSIGNED,
13074 CMDLINE_PAR_TYPE_UNASSIGNED,
13075 CMDLINE_PAR_TYPE_UNASSIGNED,
13076 CMDLINE_PAR_TYPE_UNASSIGNED,
13077 CMDLINE_PAR_TYPE_UNASSIGNED,
13078 CMDLINE_PAR_TYPE_UNASSIGNED
13079 }
13080 },
13081 {
13082 cfDap,
13083 {
13084 CMDLINE_PAR_TYPE_CMD_KEYTOKEN_DAP,
13085 CMDLINE_PAR_TYPE_INTNEG,
13086 CMDLINE_PAR_TYPE_INTPOS,
13087 CMDLINE_PAR_TYPE_UNASSIGNED,
13088 CMDLINE_PAR_TYPE_UNASSIGNED,
13089 CMDLINE_PAR_TYPE_UNASSIGNED,
13090 CMDLINE_PAR_TYPE_UNASSIGNED,
13091 CMDLINE_PAR_TYPE_UNASSIGNED,
13092 CMDLINE_PAR_TYPE_UNASSIGNED,
13093 CMDLINE_PAR_TYPE_UNASSIGNED
13094 }
13095 },
13096 {
13097 cfDap,
13098 {
13099 CMDLINE_PAR_TYPE_CMD_KEYTOKEN_DAP,
13100 CMDLINE_PAR_TYPE_INTZERO,
13101 CMDLINE_PAR_TYPE_UNASSIGNED,
13102 CMDLINE_PAR_TYPE_UNASSIGNED,
13103 CMDLINE_PAR_TYPE_UNASSIGNED,
13104 CMDLINE_PAR_TYPE_UNASSIGNED,
13105 CMDLINE_PAR_TYPE_UNASSIGNED,
13106 CMDLINE_PAR_TYPE_UNASSIGNED,
13107 CMDLINE_PAR_TYPE_UNASSIGNED,
13108 CMDLINE_PAR_TYPE_UNASSIGNED
13109 }
13110 },
13111 {
13112 cfDap,
13113 {
13114 CMDLINE_PAR_TYPE_CMD_KEYTOKEN_DAP,
13115 CMDLINE_PAR_TYPE_INTZERO,
13116 CMDLINE_PAR_TYPE_INTPOS,
13117 CMDLINE_PAR_TYPE_UNASSIGNED,
13118 CMDLINE_PAR_TYPE_UNASSIGNED,
13119 CMDLINE_PAR_TYPE_UNASSIGNED,
13120 CMDLINE_PAR_TYPE_UNASSIGNED,
13121 CMDLINE_PAR_TYPE_UNASSIGNED,
13122 CMDLINE_PAR_TYPE_UNASSIGNED,
13123 CMDLINE_PAR_TYPE_UNASSIGNED
13124 }
13125 },
13126 {
13127 cfDap,
13128 {
13129 CMDLINE_PAR_TYPE_CMD_KEYTOKEN_DAP,
13130 CMDLINE_PAR_TYPE_INTPOS,
13131 CMDLINE_PAR_TYPE_UNASSIGNED,
13132 CMDLINE_PAR_TYPE_UNASSIGNED,
13133 CMDLINE_PAR_TYPE_UNASSIGNED,
13134 CMDLINE_PAR_TYPE_UNASSIGNED,
13135 CMDLINE_PAR_TYPE_UNASSIGNED,
13136 CMDLINE_PAR_TYPE_UNASSIGNED,
13137 CMDLINE_PAR_TYPE_UNASSIGNED,
13138 CMDLINE_PAR_TYPE_UNASSIGNED
13139 }
13140 },
13141 {
13142 cfDap,
13143 {
13144 CMDLINE_PAR_TYPE_CMD_KEYTOKEN_DAP,
13145 CMDLINE_PAR_TYPE_INTPOS,
13146 CMDLINE_PAR_TYPE_INTPOS,
13147 CMDLINE_PAR_TYPE_UNASSIGNED,
13148 CMDLINE_PAR_TYPE_UNASSIGNED,
13149 CMDLINE_PAR_TYPE_UNASSIGNED,
13150 CMDLINE_PAR_TYPE_UNASSIGNED,
13151 CMDLINE_PAR_TYPE_UNASSIGNED,
13152 CMDLINE_PAR_TYPE_UNASSIGNED,
13153 CMDLINE_PAR_TYPE_UNASSIGNED
13154 }
13155 },
13156 /* CF--forming the continued fraction partial quotients and
13157 ** convergents of a non-negative rational number.
13158 */
13159 {
13160 cfCf,
13161 {
13162 CMDLINE_PAR_TYPE_CMD_KEYTOKEN_CF,
13163 CMDLINE_PAR_TYPE_RATZERO,
13164 CMDLINE_PAR_TYPE_UNASSIGNED,
13165 CMDLINE_PAR_TYPE_UNASSIGNED,
13166 CMDLINE_PAR_TYPE_UNASSIGNED,
13167 CMDLINE_PAR_TYPE_UNASSIGNED,
13168 CMDLINE_PAR_TYPE_UNASSIGNED,
13169 CMDLINE_PAR_TYPE_UNASSIGNED,
13170 CMDLINE_PAR_TYPE_UNASSIGNED,
13171 CMDLINE_PAR_TYPE_UNASSIGNED
13172 }
13173 },
13174 {
13175 cfCf,
13176 {
13177 CMDLINE_PAR_TYPE_CMD_KEYTOKEN_CF,
13178 CMDLINE_PAR_TYPE_RATPOS,
13179 CMDLINE_PAR_TYPE_UNASSIGNED,
13180 CMDLINE_PAR_TYPE_UNASSIGNED,
13181 CMDLINE_PAR_TYPE_UNASSIGNED,
13182 CMDLINE_PAR_TYPE_UNASSIGNED,
13183 CMDLINE_PAR_TYPE_UNASSIGNED,
13184 CMDLINE_PAR_TYPE_UNASSIGNED,
13185 CMDLINE_PAR_TYPE_UNASSIGNED,
13186 CMDLINE_PAR_TYPE_UNASSIGNED
13187 }
13188 },
13189 {
13190 cfCf,
13191 {
13192 CMDLINE_PAR_TYPE_CMD_KEYTOKEN_CF,
13193 CMDLINE_PAR_TYPE_INTZERO,
13194 CMDLINE_PAR_TYPE_UNASSIGNED,
13195 CMDLINE_PAR_TYPE_UNASSIGNED,
13196 CMDLINE_PAR_TYPE_UNASSIGNED,
13197 CMDLINE_PAR_TYPE_UNASSIGNED,
13198 CMDLINE_PAR_TYPE_UNASSIGNED,
13199 CMDLINE_PAR_TYPE_UNASSIGNED,
13200 CMDLINE_PAR_TYPE_UNASSIGNED,
13201 CMDLINE_PAR_TYPE_UNASSIGNED
13202 }
13203 },
13204 {
13205 cfCf,
13206 {
13207 CMDLINE_PAR_TYPE_CMD_KEYTOKEN_CF,
13208 CMDLINE_PAR_TYPE_INTPOS,
13209 CMDLINE_PAR_TYPE_UNASSIGNED,
13210 CMDLINE_PAR_TYPE_UNASSIGNED,
13211 CMDLINE_PAR_TYPE_UNASSIGNED,
13212 CMDLINE_PAR_TYPE_UNASSIGNED,
13213 CMDLINE_PAR_TYPE_UNASSIGNED,
13214 CMDLINE_PAR_TYPE_UNASSIGNED,
13215 CMDLINE_PAR_TYPE_UNASSIGNED,
13216 CMDLINE_PAR_TYPE_UNASSIGNED
13217 }
13218 },
13219 /* Farey series neighbor functionality. Multiple
13220 ** templates required.
13221 */
13222 {
13223 cfFn,
13224 {
13225 CMDLINE_PAR_TYPE_CMD_KEYTOKEN_FN,
13226 CMDLINE_PAR_TYPE_INTZERO,
13227 CMDLINE_PAR_TYPE_INTPOS,
13228 CMDLINE_PAR_TYPE_UNASSIGNED,
13229 CMDLINE_PAR_TYPE_UNASSIGNED,
13230 CMDLINE_PAR_TYPE_UNASSIGNED,
13231 CMDLINE_PAR_TYPE_UNASSIGNED,
13232 CMDLINE_PAR_TYPE_UNASSIGNED,
13233 CMDLINE_PAR_TYPE_UNASSIGNED,
13234 CMDLINE_PAR_TYPE_UNASSIGNED
13235 }
13236 },
13237 {
13238 cfFn,
13239 {
13240 CMDLINE_PAR_TYPE_CMD_KEYTOKEN_FN,
13241 CMDLINE_PAR_TYPE_INTPOS,
13242 CMDLINE_PAR_TYPE_INTPOS,
13243 CMDLINE_PAR_TYPE_UNASSIGNED,
13244 CMDLINE_PAR_TYPE_UNASSIGNED,
13245 CMDLINE_PAR_TYPE_UNASSIGNED,
13246 CMDLINE_PAR_TYPE_UNASSIGNED,
13247 CMDLINE_PAR_TYPE_UNASSIGNED,
13248 CMDLINE_PAR_TYPE_UNASSIGNED,
13249 CMDLINE_PAR_TYPE_UNASSIGNED
13250 }
13251 },
13252 {
13253 cfFn,
13254 {
13255 CMDLINE_PAR_TYPE_CMD_KEYTOKEN_FN,
13256 CMDLINE_PAR_TYPE_RATZERO,
13257 CMDLINE_PAR_TYPE_INTPOS,
13258 CMDLINE_PAR_TYPE_UNASSIGNED,
13259 CMDLINE_PAR_TYPE_UNASSIGNED,
13260 CMDLINE_PAR_TYPE_UNASSIGNED,
13261 CMDLINE_PAR_TYPE_UNASSIGNED,
13262 CMDLINE_PAR_TYPE_UNASSIGNED,
13263 CMDLINE_PAR_TYPE_UNASSIGNED,
13264 CMDLINE_PAR_TYPE_UNASSIGNED
13265 }
13266 },
13267 {
13268 cfFn,
13269 {
13270 CMDLINE_PAR_TYPE_CMD_KEYTOKEN_FN,
13271 CMDLINE_PAR_TYPE_RATPOS,
13272 CMDLINE_PAR_TYPE_INTPOS,
13273 CMDLINE_PAR_TYPE_UNASSIGNED,
13274 CMDLINE_PAR_TYPE_UNASSIGNED,
13275 CMDLINE_PAR_TYPE_UNASSIGNED,
13276 CMDLINE_PAR_TYPE_UNASSIGNED,
13277 CMDLINE_PAR_TYPE_UNASSIGNED,
13278 CMDLINE_PAR_TYPE_UNASSIGNED,
13279 CMDLINE_PAR_TYPE_UNASSIGNED
13280 }
13281 },
13282 {
13283 cfFn,
13284 {
13285 CMDLINE_PAR_TYPE_CMD_KEYTOKEN_FN,
13286 CMDLINE_PAR_TYPE_INTZERO,
13287 CMDLINE_PAR_TYPE_INTPOS,
13288 CMDLINE_PAR_TYPE_INTPOS,
13289 CMDLINE_PAR_TYPE_INTPOS,
13290 CMDLINE_PAR_TYPE_UNASSIGNED,
13291 CMDLINE_PAR_TYPE_UNASSIGNED,
13292 CMDLINE_PAR_TYPE_UNASSIGNED,
13293 CMDLINE_PAR_TYPE_UNASSIGNED,
13294 CMDLINE_PAR_TYPE_UNASSIGNED
13295 }
13296 },
13297 {
13298 cfFn,
13299 {
13300 CMDLINE_PAR_TYPE_CMD_KEYTOKEN_FN,
13301 CMDLINE_PAR_TYPE_INTPOS,
13302 CMDLINE_PAR_TYPE_INTPOS,
13303 CMDLINE_PAR_TYPE_INTPOS,
13304 CMDLINE_PAR_TYPE_INTPOS,
13305 CMDLINE_PAR_TYPE_UNASSIGNED,
13306 CMDLINE_PAR_TYPE_UNASSIGNED,
13307 CMDLINE_PAR_TYPE_UNASSIGNED,
13308 CMDLINE_PAR_TYPE_UNASSIGNED,
13309 CMDLINE_PAR_TYPE_UNASSIGNED
13310 }
13311 },
13312 {
13313 cfFn,
13314 {
13315 CMDLINE_PAR_TYPE_CMD_KEYTOKEN_FN,
13316 CMDLINE_PAR_TYPE_RATZERO,
13317 CMDLINE_PAR_TYPE_INTPOS,
13318 CMDLINE_PAR_TYPE_INTPOS,
13319 CMDLINE_PAR_TYPE_INTPOS,
13320 CMDLINE_PAR_TYPE_UNASSIGNED,
13321 CMDLINE_PAR_TYPE_UNASSIGNED,
13322 CMDLINE_PAR_TYPE_UNASSIGNED,
13323 CMDLINE_PAR_TYPE_UNASSIGNED,
13324 CMDLINE_PAR_TYPE_UNASSIGNED
13325 }
13326 },
13327 {
13328 cfFn,
13329 {
13330 CMDLINE_PAR_TYPE_CMD_KEYTOKEN_FN,
13331 CMDLINE_PAR_TYPE_RATPOS,
13332 CMDLINE_PAR_TYPE_INTPOS,
13333 CMDLINE_PAR_TYPE_INTPOS,
13334 CMDLINE_PAR_TYPE_INTPOS,
13335 CMDLINE_PAR_TYPE_UNASSIGNED,
13336 CMDLINE_PAR_TYPE_UNASSIGNED,
13337 CMDLINE_PAR_TYPE_UNASSIGNED,
13338 CMDLINE_PAR_TYPE_UNASSIGNED,
13339 CMDLINE_PAR_TYPE_UNASSIGNED
13340 }
13341 },
13342 {
13343 cfMind,
13344 {
13345 CMDLINE_PAR_TYPE_CMD_KEYTOKEN_MIND,
13346 CMDLINE_PAR_TYPE_INTZERO,
13347 CMDLINE_PAR_TYPE_INTZERO,
13348 CMDLINE_PAR_TYPE_UNASSIGNED,
13349 CMDLINE_PAR_TYPE_UNASSIGNED,
13350 CMDLINE_PAR_TYPE_UNASSIGNED,
13351 CMDLINE_PAR_TYPE_UNASSIGNED,
13352 CMDLINE_PAR_TYPE_UNASSIGNED,
13353 CMDLINE_PAR_TYPE_UNASSIGNED,
13354 CMDLINE_PAR_TYPE_UNASSIGNED
13355 }
13356 },
13357 {
13358 cfMind,
13359 {
13360 CMDLINE_PAR_TYPE_CMD_KEYTOKEN_MIND,
13361 CMDLINE_PAR_TYPE_INTZERO,
13362 CMDLINE_PAR_TYPE_INTPOS,
13363 CMDLINE_PAR_TYPE_UNASSIGNED,
13364 CMDLINE_PAR_TYPE_UNASSIGNED,
13365 CMDLINE_PAR_TYPE_UNASSIGNED,
13366 CMDLINE_PAR_TYPE_UNASSIGNED,
13367 CMDLINE_PAR_TYPE_UNASSIGNED,
13368 CMDLINE_PAR_TYPE_UNASSIGNED,
13369 CMDLINE_PAR_TYPE_UNASSIGNED
13370 }
13371 },
13372 {
13373 cfMind,
13374 {
13375 CMDLINE_PAR_TYPE_CMD_KEYTOKEN_MIND,
13376 CMDLINE_PAR_TYPE_INTZERO,
13377 CMDLINE_PAR_TYPE_RATZERO,
13378 CMDLINE_PAR_TYPE_UNASSIGNED,
13379 CMDLINE_PAR_TYPE_UNASSIGNED,
13380 CMDLINE_PAR_TYPE_UNASSIGNED,
13381 CMDLINE_PAR_TYPE_UNASSIGNED,
13382 CMDLINE_PAR_TYPE_UNASSIGNED,
13383 CMDLINE_PAR_TYPE_UNASSIGNED,
13384 CMDLINE_PAR_TYPE_UNASSIGNED
13385 }
13386 },
13387 {
13388 cfMind,
13389 {
13390 CMDLINE_PAR_TYPE_CMD_KEYTOKEN_MIND,
13391 CMDLINE_PAR_TYPE_INTZERO,
13392 CMDLINE_PAR_TYPE_RATPOS,
13393 CMDLINE_PAR_TYPE_UNASSIGNED,
13394 CMDLINE_PAR_TYPE_UNASSIGNED,
13395 CMDLINE_PAR_TYPE_UNASSIGNED,
13396 CMDLINE_PAR_TYPE_UNASSIGNED,
13397 CMDLINE_PAR_TYPE_UNASSIGNED,
13398 CMDLINE_PAR_TYPE_UNASSIGNED,
13399 CMDLINE_PAR_TYPE_UNASSIGNED
13400 }
13401 },
13402 {
13403 cfMind,
13404 {
13405 CMDLINE_PAR_TYPE_CMD_KEYTOKEN_MIND,
13406 CMDLINE_PAR_TYPE_INTPOS,
13407 CMDLINE_PAR_TYPE_INTZERO,
13408 CMDLINE_PAR_TYPE_UNASSIGNED,
13409 CMDLINE_PAR_TYPE_UNASSIGNED,
13410 CMDLINE_PAR_TYPE_UNASSIGNED,
13411 CMDLINE_PAR_TYPE_UNASSIGNED,
13412 CMDLINE_PAR_TYPE_UNASSIGNED,
13413 CMDLINE_PAR_TYPE_UNASSIGNED,
13414 CMDLINE_PAR_TYPE_UNASSIGNED
13415 }
13416 },
13417 {
13418 cfMind,
13419 {
13420 CMDLINE_PAR_TYPE_CMD_KEYTOKEN_MIND,
13421 CMDLINE_PAR_TYPE_INTPOS,
13422 CMDLINE_PAR_TYPE_INTPOS,
13423 CMDLINE_PAR_TYPE_UNASSIGNED,
13424 CMDLINE_PAR_TYPE_UNASSIGNED,
13425 CMDLINE_PAR_TYPE_UNASSIGNED,
13426 CMDLINE_PAR_TYPE_UNASSIGNED,
13427 CMDLINE_PAR_TYPE_UNASSIGNED,
13428 CMDLINE_PAR_TYPE_UNASSIGNED,
13429 CMDLINE_PAR_TYPE_UNASSIGNED
13430 }
13431 },
13432 {
13433 cfMind,
13434 {
13435 CMDLINE_PAR_TYPE_CMD_KEYTOKEN_MIND,
13436 CMDLINE_PAR_TYPE_INTPOS,
13437 CMDLINE_PAR_TYPE_RATZERO,
13438 CMDLINE_PAR_TYPE_UNASSIGNED,
13439 CMDLINE_PAR_TYPE_UNASSIGNED,
13440 CMDLINE_PAR_TYPE_UNASSIGNED,
13441 CMDLINE_PAR_TYPE_UNASSIGNED,
13442 CMDLINE_PAR_TYPE_UNASSIGNED,
13443 CMDLINE_PAR_TYPE_UNASSIGNED,
13444 CMDLINE_PAR_TYPE_UNASSIGNED
13445 }
13446 },
13447 {
13448 cfMind,
13449 {
13450 CMDLINE_PAR_TYPE_CMD_KEYTOKEN_MIND,
13451 CMDLINE_PAR_TYPE_INTPOS,
13452 CMDLINE_PAR_TYPE_RATPOS,
13453 CMDLINE_PAR_TYPE_UNASSIGNED,
13454 CMDLINE_PAR_TYPE_UNASSIGNED,
13455 CMDLINE_PAR_TYPE_UNASSIGNED,
13456 CMDLINE_PAR_TYPE_UNASSIGNED,
13457 CMDLINE_PAR_TYPE_UNASSIGNED,
13458 CMDLINE_PAR_TYPE_UNASSIGNED,
13459 CMDLINE_PAR_TYPE_UNASSIGNED
13460 }
13461 },
13462 {
13463 cfMind,
13464 {
13465 CMDLINE_PAR_TYPE_CMD_KEYTOKEN_MIND,
13466 CMDLINE_PAR_TYPE_RATZERO,
13467 CMDLINE_PAR_TYPE_INTZERO,
13468 CMDLINE_PAR_TYPE_UNASSIGNED,
13469 CMDLINE_PAR_TYPE_UNASSIGNED,
13470 CMDLINE_PAR_TYPE_UNASSIGNED,
13471 CMDLINE_PAR_TYPE_UNASSIGNED,
13472 CMDLINE_PAR_TYPE_UNASSIGNED,
13473 CMDLINE_PAR_TYPE_UNASSIGNED,
13474 CMDLINE_PAR_TYPE_UNASSIGNED
13475 }
13476 },
13477 {
13478 cfMind,
13479 {
13480 CMDLINE_PAR_TYPE_CMD_KEYTOKEN_MIND,
13481 CMDLINE_PAR_TYPE_RATZERO,
13482 CMDLINE_PAR_TYPE_INTPOS,
13483 CMDLINE_PAR_TYPE_UNASSIGNED,
13484 CMDLINE_PAR_TYPE_UNASSIGNED,
13485 CMDLINE_PAR_TYPE_UNASSIGNED,
13486 CMDLINE_PAR_TYPE_UNASSIGNED,
13487 CMDLINE_PAR_TYPE_UNASSIGNED,
13488 CMDLINE_PAR_TYPE_UNASSIGNED,
13489 CMDLINE_PAR_TYPE_UNASSIGNED
13490 }
13491 },
13492 {
13493 cfMind,
13494 {
13495 CMDLINE_PAR_TYPE_CMD_KEYTOKEN_MIND,
13496 CMDLINE_PAR_TYPE_RATZERO,
13497 CMDLINE_PAR_TYPE_RATZERO,
13498 CMDLINE_PAR_TYPE_UNASSIGNED,
13499 CMDLINE_PAR_TYPE_UNASSIGNED,
13500 CMDLINE_PAR_TYPE_UNASSIGNED,
13501 CMDLINE_PAR_TYPE_UNASSIGNED,
13502 CMDLINE_PAR_TYPE_UNASSIGNED,
13503 CMDLINE_PAR_TYPE_UNASSIGNED,
13504 CMDLINE_PAR_TYPE_UNASSIGNED
13505 }
13506 },
13507 {
13508 cfMind,
13509 {
13510 CMDLINE_PAR_TYPE_CMD_KEYTOKEN_MIND,
13511 CMDLINE_PAR_TYPE_RATZERO,
13512 CMDLINE_PAR_TYPE_RATPOS,
13513 CMDLINE_PAR_TYPE_UNASSIGNED,
13514 CMDLINE_PAR_TYPE_UNASSIGNED,
13515 CMDLINE_PAR_TYPE_UNASSIGNED,
13516 CMDLINE_PAR_TYPE_UNASSIGNED,
13517 CMDLINE_PAR_TYPE_UNASSIGNED,
13518 CMDLINE_PAR_TYPE_UNASSIGNED,
13519 CMDLINE_PAR_TYPE_UNASSIGNED
13520 }
13521 },
13522 {
13523 cfMind,
13524 {
13525 CMDLINE_PAR_TYPE_CMD_KEYTOKEN_MIND,
13526 CMDLINE_PAR_TYPE_RATPOS,
13527 CMDLINE_PAR_TYPE_INTZERO,
13528 CMDLINE_PAR_TYPE_UNASSIGNED,
13529 CMDLINE_PAR_TYPE_UNASSIGNED,
13530 CMDLINE_PAR_TYPE_UNASSIGNED,
13531 CMDLINE_PAR_TYPE_UNASSIGNED,
13532 CMDLINE_PAR_TYPE_UNASSIGNED,
13533 CMDLINE_PAR_TYPE_UNASSIGNED,
13534 CMDLINE_PAR_TYPE_UNASSIGNED
13535 }
13536 },
13537 {
13538 cfMind,
13539 {
13540 CMDLINE_PAR_TYPE_CMD_KEYTOKEN_MIND,
13541 CMDLINE_PAR_TYPE_RATPOS,
13542 CMDLINE_PAR_TYPE_INTPOS,
13543 CMDLINE_PAR_TYPE_UNASSIGNED,
13544 CMDLINE_PAR_TYPE_UNASSIGNED,
13545 CMDLINE_PAR_TYPE_UNASSIGNED,
13546 CMDLINE_PAR_TYPE_UNASSIGNED,
13547 CMDLINE_PAR_TYPE_UNASSIGNED,
13548 CMDLINE_PAR_TYPE_UNASSIGNED,
13549 CMDLINE_PAR_TYPE_UNASSIGNED
13550 }
13551 },
13552 {
13553 cfMind,
13554 {
13555 CMDLINE_PAR_TYPE_CMD_KEYTOKEN_MIND,
13556 CMDLINE_PAR_TYPE_RATPOS,
13557 CMDLINE_PAR_TYPE_RATZERO,
13558 CMDLINE_PAR_TYPE_UNASSIGNED,
13559 CMDLINE_PAR_TYPE_UNASSIGNED,
13560 CMDLINE_PAR_TYPE_UNASSIGNED,
13561 CMDLINE_PAR_TYPE_UNASSIGNED,
13562 CMDLINE_PAR_TYPE_UNASSIGNED,
13563 CMDLINE_PAR_TYPE_UNASSIGNED,
13564 CMDLINE_PAR_TYPE_UNASSIGNED
13565 }
13566 },
13567 {
13568 cfMind,
13569 {
13570 CMDLINE_PAR_TYPE_CMD_KEYTOKEN_MIND,
13571 CMDLINE_PAR_TYPE_RATPOS,
13572 CMDLINE_PAR_TYPE_RATPOS,
13573 CMDLINE_PAR_TYPE_UNASSIGNED,
13574 CMDLINE_PAR_TYPE_UNASSIGNED,
13575 CMDLINE_PAR_TYPE_UNASSIGNED,
13576 CMDLINE_PAR_TYPE_UNASSIGNED,
13577 CMDLINE_PAR_TYPE_UNASSIGNED,
13578 CMDLINE_PAR_TYPE_UNASSIGNED,
13579 CMDLINE_PAR_TYPE_UNASSIGNED
13580 }
13581 },
13582 /* Farey series double-constrained neighbor functionality.
13583 ** Multiple templates required.
13584 */
13585 {
13586 cfFab,
13587 {
13588 CMDLINE_PAR_TYPE_CMD_KEYTOKEN_FAB,
13589 CMDLINE_PAR_TYPE_INTZERO,
13590 CMDLINE_PAR_TYPE_INTPOS,
13591 CMDLINE_PAR_TYPE_INTPOS,
13592 CMDLINE_PAR_TYPE_UNASSIGNED,
13593 CMDLINE_PAR_TYPE_UNASSIGNED,
13594 CMDLINE_PAR_TYPE_UNASSIGNED,
13595 CMDLINE_PAR_TYPE_UNASSIGNED,
13596 CMDLINE_PAR_TYPE_UNASSIGNED,
13597 CMDLINE_PAR_TYPE_UNASSIGNED
13598 }
13599 },
13600 {
13601 cfFab,
13602 {
13603 CMDLINE_PAR_TYPE_CMD_KEYTOKEN_FAB,
13604 CMDLINE_PAR_TYPE_INTPOS,
13605 CMDLINE_PAR_TYPE_INTPOS,
13606 CMDLINE_PAR_TYPE_INTPOS,
13607 CMDLINE_PAR_TYPE_UNASSIGNED,
13608 CMDLINE_PAR_TYPE_UNASSIGNED,
13609 CMDLINE_PAR_TYPE_UNASSIGNED,
13610 CMDLINE_PAR_TYPE_UNASSIGNED,
13611 CMDLINE_PAR_TYPE_UNASSIGNED,
13612 CMDLINE_PAR_TYPE_UNASSIGNED
13613 }
13614 },
13615 {
13616 cfFab,
13617 {
13618 CMDLINE_PAR_TYPE_CMD_KEYTOKEN_FAB,
13619 CMDLINE_PAR_TYPE_RATZERO,
13620 CMDLINE_PAR_TYPE_INTPOS,
13621 CMDLINE_PAR_TYPE_INTPOS,
13622 CMDLINE_PAR_TYPE_UNASSIGNED,
13623 CMDLINE_PAR_TYPE_UNASSIGNED,
13624 CMDLINE_PAR_TYPE_UNASSIGNED,
13625 CMDLINE_PAR_TYPE_UNASSIGNED,
13626 CMDLINE_PAR_TYPE_UNASSIGNED,
13627 CMDLINE_PAR_TYPE_UNASSIGNED
13628 }
13629 },
13630 {
13631 cfFab,
13632 {
13633 CMDLINE_PAR_TYPE_CMD_KEYTOKEN_FAB,
13634 CMDLINE_PAR_TYPE_RATPOS,
13635 CMDLINE_PAR_TYPE_INTPOS,
13636 CMDLINE_PAR_TYPE_INTPOS,
13637 CMDLINE_PAR_TYPE_UNASSIGNED,
13638 CMDLINE_PAR_TYPE_UNASSIGNED,
13639 CMDLINE_PAR_TYPE_UNASSIGNED,
13640 CMDLINE_PAR_TYPE_UNASSIGNED,
13641 CMDLINE_PAR_TYPE_UNASSIGNED,
13642 CMDLINE_PAR_TYPE_UNASSIGNED
13643 }
13644 },
13645 {
13646 cfFab,
13647 {
13648 CMDLINE_PAR_TYPE_CMD_KEYTOKEN_FAB,
13649 CMDLINE_PAR_TYPE_INTZERO,
13650 CMDLINE_PAR_TYPE_INTPOS,
13651 CMDLINE_PAR_TYPE_INTPOS,
13652 CMDLINE_PAR_TYPE_INTPOS,
13653 CMDLINE_PAR_TYPE_INTPOS,
13654 CMDLINE_PAR_TYPE_UNASSIGNED,
13655 CMDLINE_PAR_TYPE_UNASSIGNED,
13656 CMDLINE_PAR_TYPE_UNASSIGNED,
13657 CMDLINE_PAR_TYPE_UNASSIGNED
13658 }
13659 },
13660 {
13661 cfFab,
13662 {
13663 CMDLINE_PAR_TYPE_CMD_KEYTOKEN_FAB,
13664 CMDLINE_PAR_TYPE_INTPOS,
13665 CMDLINE_PAR_TYPE_INTPOS,
13666 CMDLINE_PAR_TYPE_INTPOS,
13667 CMDLINE_PAR_TYPE_INTPOS,
13668 CMDLINE_PAR_TYPE_INTPOS,
13669 CMDLINE_PAR_TYPE_UNASSIGNED,
13670 CMDLINE_PAR_TYPE_UNASSIGNED,
13671 CMDLINE_PAR_TYPE_UNASSIGNED,
13672 CMDLINE_PAR_TYPE_UNASSIGNED
13673 }
13674 },
13675 {
13676 cfFab,
13677 {
13678 CMDLINE_PAR_TYPE_CMD_KEYTOKEN_FAB,
13679 CMDLINE_PAR_TYPE_RATZERO,
13680 CMDLINE_PAR_TYPE_INTPOS,
13681 CMDLINE_PAR_TYPE_INTPOS,
13682 CMDLINE_PAR_TYPE_INTPOS,
13683 CMDLINE_PAR_TYPE_INTPOS,
13684 CMDLINE_PAR_TYPE_UNASSIGNED,
13685 CMDLINE_PAR_TYPE_UNASSIGNED,
13686 CMDLINE_PAR_TYPE_UNASSIGNED,
13687 CMDLINE_PAR_TYPE_UNASSIGNED
13688 }
13689 },
13690 {
13691 cfFab,
13692 {
13693 CMDLINE_PAR_TYPE_CMD_KEYTOKEN_FAB,
13694 CMDLINE_PAR_TYPE_RATPOS,
13695 CMDLINE_PAR_TYPE_INTPOS,
13696 CMDLINE_PAR_TYPE_INTPOS,
13697 CMDLINE_PAR_TYPE_INTPOS,
13698 CMDLINE_PAR_TYPE_INTPOS,
13699 CMDLINE_PAR_TYPE_UNASSIGNED,
13700 CMDLINE_PAR_TYPE_UNASSIGNED,
13701 CMDLINE_PAR_TYPE_UNASSIGNED,
13702 CMDLINE_PAR_TYPE_UNASSIGNED
13703 }
13704 },
13705 /* Maximum distance between terms of Farey series.
13706 ** Only two forms possible, one with DAP alternate
13707 ** denominator, one without.
13708 */
13709 {
13710 cfFndmax,
13711 {
13712 CMDLINE_PAR_TYPE_CMD_KEYTOKEN_FNDMAX,
13713 CMDLINE_PAR_TYPE_INTZERO,
13714 CMDLINE_PAR_TYPE_INTZERO,
13715 CMDLINE_PAR_TYPE_INTPOS,
13716 CMDLINE_PAR_TYPE_UNASSIGNED,
13717 CMDLINE_PAR_TYPE_UNASSIGNED,
13718 CMDLINE_PAR_TYPE_UNASSIGNED,
13719 CMDLINE_PAR_TYPE_UNASSIGNED,
13720 CMDLINE_PAR_TYPE_UNASSIGNED,
13721 CMDLINE_PAR_TYPE_UNASSIGNED
13722 }
13723 },
13724 {
13725 cfFndmax,
13726 {
13727 CMDLINE_PAR_TYPE_CMD_KEYTOKEN_FNDMAX,
13728 CMDLINE_PAR_TYPE_INTZERO,
13729 CMDLINE_PAR_TYPE_INTPOS,
13730 CMDLINE_PAR_TYPE_INTPOS,
13731 CMDLINE_PAR_TYPE_UNASSIGNED,
13732 CMDLINE_PAR_TYPE_UNASSIGNED,
13733 CMDLINE_PAR_TYPE_UNASSIGNED,
13734 CMDLINE_PAR_TYPE_UNASSIGNED,
13735 CMDLINE_PAR_TYPE_UNASSIGNED,
13736 CMDLINE_PAR_TYPE_UNASSIGNED
13737 }
13738 },
13739 {
13740 cfFndmax,
13741 {
13742 CMDLINE_PAR_TYPE_CMD_KEYTOKEN_FNDMAX,
13743 CMDLINE_PAR_TYPE_INTZERO,
13744 CMDLINE_PAR_TYPE_RATZERO,
13745 CMDLINE_PAR_TYPE_INTPOS,
13746 CMDLINE_PAR_TYPE_UNASSIGNED,
13747 CMDLINE_PAR_TYPE_UNASSIGNED,
13748 CMDLINE_PAR_TYPE_UNASSIGNED,
13749 CMDLINE_PAR_TYPE_UNASSIGNED,
13750 CMDLINE_PAR_TYPE_UNASSIGNED,
13751 CMDLINE_PAR_TYPE_UNASSIGNED
13752 }
13753 },
13754 {
13755 cfFndmax,
13756 {
13757 CMDLINE_PAR_TYPE_CMD_KEYTOKEN_FNDMAX,
13758 CMDLINE_PAR_TYPE_INTZERO,
13759 CMDLINE_PAR_TYPE_RATPOS,
13760 CMDLINE_PAR_TYPE_INTPOS,
13761 CMDLINE_PAR_TYPE_UNASSIGNED,
13762 CMDLINE_PAR_TYPE_UNASSIGNED,
13763 CMDLINE_PAR_TYPE_UNASSIGNED,
13764 CMDLINE_PAR_TYPE_UNASSIGNED,
13765 CMDLINE_PAR_TYPE_UNASSIGNED,
13766 CMDLINE_PAR_TYPE_UNASSIGNED
13767 }
13768 },
13769 {
13770 cfFndmax,
13771 {
13772 CMDLINE_PAR_TYPE_CMD_KEYTOKEN_FNDMAX,
13773 CMDLINE_PAR_TYPE_INTZERO,
13774 CMDLINE_PAR_TYPE_INTZERO,
13775 CMDLINE_PAR_TYPE_INTPOS,
13776 CMDLINE_PAR_TYPE_UNASSIGNED,
13777 CMDLINE_PAR_TYPE_UNASSIGNED,
13778 CMDLINE_PAR_TYPE_UNASSIGNED,
13779 CMDLINE_PAR_TYPE_UNASSIGNED,
13780 CMDLINE_PAR_TYPE_UNASSIGNED,
13781 CMDLINE_PAR_TYPE_UNASSIGNED
13782 }
13783 },
13784 {
13785 cfFndmax,
13786 {
13787 CMDLINE_PAR_TYPE_CMD_KEYTOKEN_FNDMAX,
13788 CMDLINE_PAR_TYPE_INTZERO,
13789 CMDLINE_PAR_TYPE_INTPOS,
13790 CMDLINE_PAR_TYPE_INTPOS,
13791 CMDLINE_PAR_TYPE_UNASSIGNED,
13792 CMDLINE_PAR_TYPE_UNASSIGNED,
13793 CMDLINE_PAR_TYPE_UNASSIGNED,
13794 CMDLINE_PAR_TYPE_UNASSIGNED,
13795 CMDLINE_PAR_TYPE_UNASSIGNED,
13796 CMDLINE_PAR_TYPE_UNASSIGNED
13797 }
13798 },
13799 {
13800 cfFndmax,
13801 {
13802 CMDLINE_PAR_TYPE_CMD_KEYTOKEN_FNDMAX,
13803 CMDLINE_PAR_TYPE_INTZERO,
13804 CMDLINE_PAR_TYPE_RATZERO,
13805 CMDLINE_PAR_TYPE_INTPOS,
13806 CMDLINE_PAR_TYPE_UNASSIGNED,
13807 CMDLINE_PAR_TYPE_UNASSIGNED,
13808 CMDLINE_PAR_TYPE_UNASSIGNED,
13809 CMDLINE_PAR_TYPE_UNASSIGNED,
13810 CMDLINE_PAR_TYPE_UNASSIGNED,
13811 CMDLINE_PAR_TYPE_UNASSIGNED
13812 }
13813 },
13814 {
13815 cfFndmax,
13816 {
13817 CMDLINE_PAR_TYPE_CMD_KEYTOKEN_FNDMAX,
13818 CMDLINE_PAR_TYPE_INTZERO,
13819 CMDLINE_PAR_TYPE_RATPOS,
13820 CMDLINE_PAR_TYPE_INTPOS,
13821 CMDLINE_PAR_TYPE_UNASSIGNED,
13822 CMDLINE_PAR_TYPE_UNASSIGNED,
13823 CMDLINE_PAR_TYPE_UNASSIGNED,
13824 CMDLINE_PAR_TYPE_UNASSIGNED,
13825 CMDLINE_PAR_TYPE_UNASSIGNED,
13826 CMDLINE_PAR_TYPE_UNASSIGNED
13827 }
13828 },
13829 {
13830 cfFndmax,
13831 {
13832 CMDLINE_PAR_TYPE_CMD_KEYTOKEN_FNDMAX,
13833 CMDLINE_PAR_TYPE_INTPOS,
13834 CMDLINE_PAR_TYPE_INTZERO,
13835 CMDLINE_PAR_TYPE_INTPOS,
13836 CMDLINE_PAR_TYPE_UNASSIGNED,
13837 CMDLINE_PAR_TYPE_UNASSIGNED,
13838 CMDLINE_PAR_TYPE_UNASSIGNED,
13839 CMDLINE_PAR_TYPE_UNASSIGNED,
13840 CMDLINE_PAR_TYPE_UNASSIGNED,
13841 CMDLINE_PAR_TYPE_UNASSIGNED
13842 }
13843 },
13844 {
13845 cfFndmax,
13846 {
13847 CMDLINE_PAR_TYPE_CMD_KEYTOKEN_FNDMAX,
13848 CMDLINE_PAR_TYPE_INTPOS,
13849 CMDLINE_PAR_TYPE_INTPOS,
13850 CMDLINE_PAR_TYPE_INTPOS,
13851 CMDLINE_PAR_TYPE_UNASSIGNED,
13852 CMDLINE_PAR_TYPE_UNASSIGNED,
13853 CMDLINE_PAR_TYPE_UNASSIGNED,
13854 CMDLINE_PAR_TYPE_UNASSIGNED,
13855 CMDLINE_PAR_TYPE_UNASSIGNED,
13856 CMDLINE_PAR_TYPE_UNASSIGNED
13857 }
13858 },
13859 {
13860 cfFndmax,
13861 {
13862 CMDLINE_PAR_TYPE_CMD_KEYTOKEN_FNDMAX,
13863 CMDLINE_PAR_TYPE_INTPOS,
13864 CMDLINE_PAR_TYPE_RATZERO,
13865 CMDLINE_PAR_TYPE_INTPOS,
13866 CMDLINE_PAR_TYPE_UNASSIGNED,
13867 CMDLINE_PAR_TYPE_UNASSIGNED,
13868 CMDLINE_PAR_TYPE_UNASSIGNED,
13869 CMDLINE_PAR_TYPE_UNASSIGNED,
13870 CMDLINE_PAR_TYPE_UNASSIGNED,
13871 CMDLINE_PAR_TYPE_UNASSIGNED
13872 }
13873 },
13874 {
13875 cfFndmax,
13876 {
13877 CMDLINE_PAR_TYPE_CMD_KEYTOKEN_FNDMAX,
13878 CMDLINE_PAR_TYPE_INTPOS,
13879 CMDLINE_PAR_TYPE_RATPOS,
13880 CMDLINE_PAR_TYPE_INTPOS,
13881 CMDLINE_PAR_TYPE_UNASSIGNED,
13882 CMDLINE_PAR_TYPE_UNASSIGNED,
13883 CMDLINE_PAR_TYPE_UNASSIGNED,
13884 CMDLINE_PAR_TYPE_UNASSIGNED,
13885 CMDLINE_PAR_TYPE_UNASSIGNED,
13886 CMDLINE_PAR_TYPE_UNASSIGNED
13887 }
13888 },
13889 {
13890 cfFndmax,
13891 {
13892 CMDLINE_PAR_TYPE_CMD_KEYTOKEN_FNDMAX,
13893 CMDLINE_PAR_TYPE_RATZERO,
13894 CMDLINE_PAR_TYPE_INTZERO,
13895 CMDLINE_PAR_TYPE_INTPOS,
13896 CMDLINE_PAR_TYPE_UNASSIGNED,
13897 CMDLINE_PAR_TYPE_UNASSIGNED,
13898 CMDLINE_PAR_TYPE_UNASSIGNED,
13899 CMDLINE_PAR_TYPE_UNASSIGNED,
13900 CMDLINE_PAR_TYPE_UNASSIGNED,
13901 CMDLINE_PAR_TYPE_UNASSIGNED
13902 }
13903 },
13904 {
13905 cfFndmax,
13906 {
13907 CMDLINE_PAR_TYPE_CMD_KEYTOKEN_FNDMAX,
13908 CMDLINE_PAR_TYPE_RATZERO,
13909 CMDLINE_PAR_TYPE_INTPOS,
13910 CMDLINE_PAR_TYPE_INTPOS,
13911 CMDLINE_PAR_TYPE_UNASSIGNED,
13912 CMDLINE_PAR_TYPE_UNASSIGNED,
13913 CMDLINE_PAR_TYPE_UNASSIGNED,
13914 CMDLINE_PAR_TYPE_UNASSIGNED,
13915 CMDLINE_PAR_TYPE_UNASSIGNED,
13916 CMDLINE_PAR_TYPE_UNASSIGNED
13917 }
13918 },
13919 {
13920 cfFndmax,
13921 {
13922 CMDLINE_PAR_TYPE_CMD_KEYTOKEN_FNDMAX,
13923 CMDLINE_PAR_TYPE_RATZERO,
13924 CMDLINE_PAR_TYPE_RATZERO,
13925 CMDLINE_PAR_TYPE_INTPOS,
13926 CMDLINE_PAR_TYPE_UNASSIGNED,
13927 CMDLINE_PAR_TYPE_UNASSIGNED,
13928 CMDLINE_PAR_TYPE_UNASSIGNED,
13929 CMDLINE_PAR_TYPE_UNASSIGNED,
13930 CMDLINE_PAR_TYPE_UNASSIGNED,
13931 CMDLINE_PAR_TYPE_UNASSIGNED
13932 }
13933 },
13934 {
13935 cfFndmax,
13936 {
13937 CMDLINE_PAR_TYPE_CMD_KEYTOKEN_FNDMAX,
13938 CMDLINE_PAR_TYPE_RATZERO,
13939 CMDLINE_PAR_TYPE_RATPOS,
13940 CMDLINE_PAR_TYPE_INTPOS,
13941 CMDLINE_PAR_TYPE_UNASSIGNED,
13942 CMDLINE_PAR_TYPE_UNASSIGNED,
13943 CMDLINE_PAR_TYPE_UNASSIGNED,
13944 CMDLINE_PAR_TYPE_UNASSIGNED,
13945 CMDLINE_PAR_TYPE_UNASSIGNED,
13946 CMDLINE_PAR_TYPE_UNASSIGNED
13947 }
13948 },
13949 {
13950 cfFndmax,
13951 {
13952 CMDLINE_PAR_TYPE_CMD_KEYTOKEN_FNDMAX,
13953 CMDLINE_PAR_TYPE_RATPOS,
13954 CMDLINE_PAR_TYPE_INTZERO,
13955 CMDLINE_PAR_TYPE_INTPOS,
13956 CMDLINE_PAR_TYPE_UNASSIGNED,
13957 CMDLINE_PAR_TYPE_UNASSIGNED,
13958 CMDLINE_PAR_TYPE_UNASSIGNED,
13959 CMDLINE_PAR_TYPE_UNASSIGNED,
13960 CMDLINE_PAR_TYPE_UNASSIGNED,
13961 CMDLINE_PAR_TYPE_UNASSIGNED
13962 }
13963 },
13964 {
13965 cfFndmax,
13966 {
13967 CMDLINE_PAR_TYPE_CMD_KEYTOKEN_FNDMAX,
13968 CMDLINE_PAR_TYPE_RATPOS,
13969 CMDLINE_PAR_TYPE_INTPOS,
13970 CMDLINE_PAR_TYPE_INTPOS,
13971 CMDLINE_PAR_TYPE_UNASSIGNED,
13972 CMDLINE_PAR_TYPE_UNASSIGNED,
13973 CMDLINE_PAR_TYPE_UNASSIGNED,
13974 CMDLINE_PAR_TYPE_UNASSIGNED,
13975 CMDLINE_PAR_TYPE_UNASSIGNED,
13976 CMDLINE_PAR_TYPE_UNASSIGNED
13977 }
13978 },
13979 {
13980 cfFndmax,
13981 {
13982 CMDLINE_PAR_TYPE_CMD_KEYTOKEN_FNDMAX,
13983 CMDLINE_PAR_TYPE_RATPOS,
13984 CMDLINE_PAR_TYPE_RATZERO,
13985 CMDLINE_PAR_TYPE_INTPOS,
13986 CMDLINE_PAR_TYPE_UNASSIGNED,
13987 CMDLINE_PAR_TYPE_UNASSIGNED,
13988 CMDLINE_PAR_TYPE_UNASSIGNED,
13989 CMDLINE_PAR_TYPE_UNASSIGNED,
13990 CMDLINE_PAR_TYPE_UNASSIGNED,
13991 CMDLINE_PAR_TYPE_UNASSIGNED
13992 }
13993 },
13994 {
13995 cfFndmax,
13996 {
13997 CMDLINE_PAR_TYPE_CMD_KEYTOKEN_FNDMAX,
13998 CMDLINE_PAR_TYPE_RATPOS,
13999 CMDLINE_PAR_TYPE_RATPOS,
14000 CMDLINE_PAR_TYPE_INTPOS,
14001 CMDLINE_PAR_TYPE_UNASSIGNED,
14002 CMDLINE_PAR_TYPE_UNASSIGNED,
14003 CMDLINE_PAR_TYPE_UNASSIGNED,
14004 CMDLINE_PAR_TYPE_UNASSIGNED,
14005 CMDLINE_PAR_TYPE_UNASSIGNED,
14006 CMDLINE_PAR_TYPE_UNASSIGNED
14007 }
14008 },
14009 {
14010 cfFndmax,
14011 {
14012 CMDLINE_PAR_TYPE_CMD_KEYTOKEN_FNDMAX,
14013 CMDLINE_PAR_TYPE_INTZERO,
14014 CMDLINE_PAR_TYPE_INTZERO,
14015 CMDLINE_PAR_TYPE_INTPOS,
14016 CMDLINE_PAR_TYPE_INTPOS,
14017 CMDLINE_PAR_TYPE_UNASSIGNED,
14018 CMDLINE_PAR_TYPE_UNASSIGNED,
14019 CMDLINE_PAR_TYPE_UNASSIGNED,
14020 CMDLINE_PAR_TYPE_UNASSIGNED,
14021 CMDLINE_PAR_TYPE_UNASSIGNED
14022 }
14023 },
14024 {
14025 cfFndmax,
14026 {
14027 CMDLINE_PAR_TYPE_CMD_KEYTOKEN_FNDMAX,
14028 CMDLINE_PAR_TYPE_INTZERO,
14029 CMDLINE_PAR_TYPE_INTPOS,
14030 CMDLINE_PAR_TYPE_INTPOS,
14031 CMDLINE_PAR_TYPE_INTPOS,
14032 CMDLINE_PAR_TYPE_UNASSIGNED,
14033 CMDLINE_PAR_TYPE_UNASSIGNED,
14034 CMDLINE_PAR_TYPE_UNASSIGNED,
14035 CMDLINE_PAR_TYPE_UNASSIGNED,
14036 CMDLINE_PAR_TYPE_UNASSIGNED
14037 }
14038 },
14039 {
14040 cfFndmax,
14041 {
14042 CMDLINE_PAR_TYPE_CMD_KEYTOKEN_FNDMAX,
14043 CMDLINE_PAR_TYPE_INTZERO,
14044 CMDLINE_PAR_TYPE_RATZERO,
14045 CMDLINE_PAR_TYPE_INTPOS,
14046 CMDLINE_PAR_TYPE_INTPOS,
14047 CMDLINE_PAR_TYPE_UNASSIGNED,
14048 CMDLINE_PAR_TYPE_UNASSIGNED,
14049 CMDLINE_PAR_TYPE_UNASSIGNED,
14050 CMDLINE_PAR_TYPE_UNASSIGNED,
14051 CMDLINE_PAR_TYPE_UNASSIGNED
14052 }
14053 },
14054 {
14055 cfFndmax,
14056 {
14057 CMDLINE_PAR_TYPE_CMD_KEYTOKEN_FNDMAX,
14058 CMDLINE_PAR_TYPE_INTZERO,
14059 CMDLINE_PAR_TYPE_RATPOS,
14060 CMDLINE_PAR_TYPE_INTPOS,
14061 CMDLINE_PAR_TYPE_INTPOS,
14062 CMDLINE_PAR_TYPE_UNASSIGNED,
14063 CMDLINE_PAR_TYPE_UNASSIGNED,
14064 CMDLINE_PAR_TYPE_UNASSIGNED,
14065 CMDLINE_PAR_TYPE_UNASSIGNED,
14066 CMDLINE_PAR_TYPE_UNASSIGNED
14067 }
14068 },
14069 {
14070 cfFndmax,
14071 {
14072 CMDLINE_PAR_TYPE_CMD_KEYTOKEN_FNDMAX,
14073 CMDLINE_PAR_TYPE_INTZERO,
14074 CMDLINE_PAR_TYPE_INTZERO,
14075 CMDLINE_PAR_TYPE_INTPOS,
14076 CMDLINE_PAR_TYPE_INTPOS,
14077 CMDLINE_PAR_TYPE_UNASSIGNED,
14078 CMDLINE_PAR_TYPE_UNASSIGNED,
14079 CMDLINE_PAR_TYPE_UNASSIGNED,
14080 CMDLINE_PAR_TYPE_UNASSIGNED,
14081 CMDLINE_PAR_TYPE_UNASSIGNED
14082 }
14083 },
14084 {
14085 cfFndmax,
14086 {
14087 CMDLINE_PAR_TYPE_CMD_KEYTOKEN_FNDMAX,
14088 CMDLINE_PAR_TYPE_INTZERO,
14089 CMDLINE_PAR_TYPE_INTPOS,
14090 CMDLINE_PAR_TYPE_INTPOS,
14091 CMDLINE_PAR_TYPE_INTPOS,
14092 CMDLINE_PAR_TYPE_UNASSIGNED,
14093 CMDLINE_PAR_TYPE_UNASSIGNED,
14094 CMDLINE_PAR_TYPE_UNASSIGNED,
14095 CMDLINE_PAR_TYPE_UNASSIGNED,
14096 CMDLINE_PAR_TYPE_UNASSIGNED
14097 }
14098 },
14099 {
14100 cfFndmax,
14101 {
14102 CMDLINE_PAR_TYPE_CMD_KEYTOKEN_FNDMAX,
14103 CMDLINE_PAR_TYPE_INTZERO,
14104 CMDLINE_PAR_TYPE_RATZERO,
14105 CMDLINE_PAR_TYPE_INTPOS,
14106 CMDLINE_PAR_TYPE_INTPOS,
14107 CMDLINE_PAR_TYPE_UNASSIGNED,
14108 CMDLINE_PAR_TYPE_UNASSIGNED,
14109 CMDLINE_PAR_TYPE_UNASSIGNED,
14110 CMDLINE_PAR_TYPE_UNASSIGNED,
14111 CMDLINE_PAR_TYPE_UNASSIGNED
14112 }
14113 },
14114 {
14115 cfFndmax,
14116 {
14117 CMDLINE_PAR_TYPE_CMD_KEYTOKEN_FNDMAX,
14118 CMDLINE_PAR_TYPE_INTZERO,
14119 CMDLINE_PAR_TYPE_RATPOS,
14120 CMDLINE_PAR_TYPE_INTPOS,
14121 CMDLINE_PAR_TYPE_INTPOS,
14122 CMDLINE_PAR_TYPE_UNASSIGNED,
14123 CMDLINE_PAR_TYPE_UNASSIGNED,
14124 CMDLINE_PAR_TYPE_UNASSIGNED,
14125 CMDLINE_PAR_TYPE_UNASSIGNED,
14126 CMDLINE_PAR_TYPE_UNASSIGNED
14127 }
14128 },
14129 {
14130 cfFndmax,
14131 {
14132 CMDLINE_PAR_TYPE_CMD_KEYTOKEN_FNDMAX,
14133 CMDLINE_PAR_TYPE_INTPOS,
14134 CMDLINE_PAR_TYPE_INTZERO,
14135 CMDLINE_PAR_TYPE_INTPOS,
14136 CMDLINE_PAR_TYPE_INTPOS,
14137 CMDLINE_PAR_TYPE_UNASSIGNED,
14138 CMDLINE_PAR_TYPE_UNASSIGNED,
14139 CMDLINE_PAR_TYPE_UNASSIGNED,
14140 CMDLINE_PAR_TYPE_UNASSIGNED,
14141 CMDLINE_PAR_TYPE_UNASSIGNED
14142 }
14143 },
14144 {
14145 cfFndmax,
14146 {
14147 CMDLINE_PAR_TYPE_CMD_KEYTOKEN_FNDMAX,
14148 CMDLINE_PAR_TYPE_INTPOS,
14149 CMDLINE_PAR_TYPE_INTPOS,
14150 CMDLINE_PAR_TYPE_INTPOS,
14151 CMDLINE_PAR_TYPE_INTPOS,
14152 CMDLINE_PAR_TYPE_UNASSIGNED,
14153 CMDLINE_PAR_TYPE_UNASSIGNED,
14154 CMDLINE_PAR_TYPE_UNASSIGNED,
14155 CMDLINE_PAR_TYPE_UNASSIGNED,
14156 CMDLINE_PAR_TYPE_UNASSIGNED
14157 }
14158 },
14159 {
14160 cfFndmax,
14161 {
14162 CMDLINE_PAR_TYPE_CMD_KEYTOKEN_FNDMAX,
14163 CMDLINE_PAR_TYPE_INTPOS,
14164 CMDLINE_PAR_TYPE_RATZERO,
14165 CMDLINE_PAR_TYPE_INTPOS,
14166 CMDLINE_PAR_TYPE_INTPOS,
14167 CMDLINE_PAR_TYPE_UNASSIGNED,
14168 CMDLINE_PAR_TYPE_UNASSIGNED,
14169 CMDLINE_PAR_TYPE_UNASSIGNED,
14170 CMDLINE_PAR_TYPE_UNASSIGNED,
14171 CMDLINE_PAR_TYPE_UNASSIGNED
14172 }
14173 },
14174 {
14175 cfFndmax,
14176 {
14177 CMDLINE_PAR_TYPE_CMD_KEYTOKEN_FNDMAX,
14178 CMDLINE_PAR_TYPE_INTPOS,
14179 CMDLINE_PAR_TYPE_RATPOS,
14180 CMDLINE_PAR_TYPE_INTPOS,
14181 CMDLINE_PAR_TYPE_INTPOS,
14182 CMDLINE_PAR_TYPE_UNASSIGNED,
14183 CMDLINE_PAR_TYPE_UNASSIGNED,
14184 CMDLINE_PAR_TYPE_UNASSIGNED,
14185 CMDLINE_PAR_TYPE_UNASSIGNED,
14186 CMDLINE_PAR_TYPE_UNASSIGNED
14187 }
14188 },
14189 {
14190 cfFndmax,
14191 {
14192 CMDLINE_PAR_TYPE_CMD_KEYTOKEN_FNDMAX,
14193 CMDLINE_PAR_TYPE_RATZERO,
14194 CMDLINE_PAR_TYPE_INTZERO,
14195 CMDLINE_PAR_TYPE_INTPOS,
14196 CMDLINE_PAR_TYPE_INTPOS,
14197 CMDLINE_PAR_TYPE_UNASSIGNED,
14198 CMDLINE_PAR_TYPE_UNASSIGNED,
14199 CMDLINE_PAR_TYPE_UNASSIGNED,
14200 CMDLINE_PAR_TYPE_UNASSIGNED,
14201 CMDLINE_PAR_TYPE_UNASSIGNED
14202 }
14203 },
14204 {
14205 cfFndmax,
14206 {
14207 CMDLINE_PAR_TYPE_CMD_KEYTOKEN_FNDMAX,
14208 CMDLINE_PAR_TYPE_RATZERO,
14209 CMDLINE_PAR_TYPE_INTPOS,
14210 CMDLINE_PAR_TYPE_INTPOS,
14211 CMDLINE_PAR_TYPE_INTPOS,
14212 CMDLINE_PAR_TYPE_UNASSIGNED,
14213 CMDLINE_PAR_TYPE_UNASSIGNED,
14214 CMDLINE_PAR_TYPE_UNASSIGNED,
14215 CMDLINE_PAR_TYPE_UNASSIGNED,
14216 CMDLINE_PAR_TYPE_UNASSIGNED
14217 }
14218 },
14219 {
14220 cfFndmax,
14221 {
14222 CMDLINE_PAR_TYPE_CMD_KEYTOKEN_FNDMAX,
14223 CMDLINE_PAR_TYPE_RATZERO,
14224 CMDLINE_PAR_TYPE_RATZERO,
14225 CMDLINE_PAR_TYPE_INTPOS,
14226 CMDLINE_PAR_TYPE_INTPOS,
14227 CMDLINE_PAR_TYPE_UNASSIGNED,
14228 CMDLINE_PAR_TYPE_UNASSIGNED,
14229 CMDLINE_PAR_TYPE_UNASSIGNED,
14230 CMDLINE_PAR_TYPE_UNASSIGNED,
14231 CMDLINE_PAR_TYPE_UNASSIGNED
14232 }
14233 },
14234 {
14235 cfFndmax,
14236 {
14237 CMDLINE_PAR_TYPE_CMD_KEYTOKEN_FNDMAX,
14238 CMDLINE_PAR_TYPE_RATZERO,
14239 CMDLINE_PAR_TYPE_RATPOS,
14240 CMDLINE_PAR_TYPE_INTPOS,
14241 CMDLINE_PAR_TYPE_INTPOS,
14242 CMDLINE_PAR_TYPE_UNASSIGNED,
14243 CMDLINE_PAR_TYPE_UNASSIGNED,
14244 CMDLINE_PAR_TYPE_UNASSIGNED,
14245 CMDLINE_PAR_TYPE_UNASSIGNED,
14246 CMDLINE_PAR_TYPE_UNASSIGNED
14247 }
14248 },
14249 {
14250 cfFndmax,
14251 {
14252 CMDLINE_PAR_TYPE_CMD_KEYTOKEN_FNDMAX,
14253 CMDLINE_PAR_TYPE_RATPOS,
14254 CMDLINE_PAR_TYPE_INTZERO,
14255 CMDLINE_PAR_TYPE_INTPOS,
14256 CMDLINE_PAR_TYPE_INTPOS,
14257 CMDLINE_PAR_TYPE_UNASSIGNED,
14258 CMDLINE_PAR_TYPE_UNASSIGNED,
14259 CMDLINE_PAR_TYPE_UNASSIGNED,
14260 CMDLINE_PAR_TYPE_UNASSIGNED,
14261 CMDLINE_PAR_TYPE_UNASSIGNED
14262 }
14263 },
14264 {
14265 cfFndmax,
14266 {
14267 CMDLINE_PAR_TYPE_CMD_KEYTOKEN_FNDMAX,
14268 CMDLINE_PAR_TYPE_RATPOS,
14269 CMDLINE_PAR_TYPE_INTPOS,
14270 CMDLINE_PAR_TYPE_INTPOS,
14271 CMDLINE_PAR_TYPE_INTPOS,
14272 CMDLINE_PAR_TYPE_UNASSIGNED,
14273 CMDLINE_PAR_TYPE_UNASSIGNED,
14274 CMDLINE_PAR_TYPE_UNASSIGNED,
14275 CMDLINE_PAR_TYPE_UNASSIGNED,
14276 CMDLINE_PAR_TYPE_UNASSIGNED
14277 }
14278 },
14279 {
14280 cfFndmax,
14281 {
14282 CMDLINE_PAR_TYPE_CMD_KEYTOKEN_FNDMAX,
14283 CMDLINE_PAR_TYPE_RATPOS,
14284 CMDLINE_PAR_TYPE_RATZERO,
14285 CMDLINE_PAR_TYPE_INTPOS,
14286 CMDLINE_PAR_TYPE_INTPOS,
14287 CMDLINE_PAR_TYPE_UNASSIGNED,
14288 CMDLINE_PAR_TYPE_UNASSIGNED,
14289 CMDLINE_PAR_TYPE_UNASSIGNED,
14290 CMDLINE_PAR_TYPE_UNASSIGNED,
14291 CMDLINE_PAR_TYPE_UNASSIGNED
14292 }
14293 },
14294 {
14295 cfFndmax,
14296 {
14297 CMDLINE_PAR_TYPE_CMD_KEYTOKEN_FNDMAX,
14298 CMDLINE_PAR_TYPE_RATPOS,
14299 CMDLINE_PAR_TYPE_RATPOS,
14300 CMDLINE_PAR_TYPE_INTPOS,
14301 CMDLINE_PAR_TYPE_INTPOS,
14302 CMDLINE_PAR_TYPE_UNASSIGNED,
14303 CMDLINE_PAR_TYPE_UNASSIGNED,
14304 CMDLINE_PAR_TYPE_UNASSIGNED,
14305 CMDLINE_PAR_TYPE_UNASSIGNED,
14306 CMDLINE_PAR_TYPE_UNASSIGNED
14307 }
14308 },
14309 /* Maximum distance between terms of "rectangular" Farey
14310 ** series. Only two forms possible, one with DAP alternate
14311 ** denominator, one without.
14312 */
14313 {
14314 cfFabdmax,
14315 {
14316 CMDLINE_PAR_TYPE_CMD_KEYTOKEN_FABDMAX,
14317 CMDLINE_PAR_TYPE_INTZERO,
14318 CMDLINE_PAR_TYPE_INTZERO,
14319 CMDLINE_PAR_TYPE_INTPOS,
14320 CMDLINE_PAR_TYPE_INTPOS,
14321 CMDLINE_PAR_TYPE_UNASSIGNED,
14322 CMDLINE_PAR_TYPE_UNASSIGNED,
14323 CMDLINE_PAR_TYPE_UNASSIGNED,
14324 CMDLINE_PAR_TYPE_UNASSIGNED,
14325 CMDLINE_PAR_TYPE_UNASSIGNED
14326 }
14327 },
14328 {
14329 cfFabdmax,
14330 {
14331 CMDLINE_PAR_TYPE_CMD_KEYTOKEN_FABDMAX,
14332 CMDLINE_PAR_TYPE_INTZERO,
14333 CMDLINE_PAR_TYPE_INTPOS,
14334 CMDLINE_PAR_TYPE_INTPOS,
14335 CMDLINE_PAR_TYPE_INTPOS,
14336 CMDLINE_PAR_TYPE_UNASSIGNED,
14337 CMDLINE_PAR_TYPE_UNASSIGNED,
14338 CMDLINE_PAR_TYPE_UNASSIGNED,
14339 CMDLINE_PAR_TYPE_UNASSIGNED,
14340 CMDLINE_PAR_TYPE_UNASSIGNED
14341 }
14342 },
14343 {
14344 cfFabdmax,
14345 {
14346 CMDLINE_PAR_TYPE_CMD_KEYTOKEN_FABDMAX,
14347 CMDLINE_PAR_TYPE_INTZERO,
14348 CMDLINE_PAR_TYPE_RATZERO,
14349 CMDLINE_PAR_TYPE_INTPOS,
14350 CMDLINE_PAR_TYPE_INTPOS,
14351 CMDLINE_PAR_TYPE_UNASSIGNED,
14352 CMDLINE_PAR_TYPE_UNASSIGNED,
14353 CMDLINE_PAR_TYPE_UNASSIGNED,
14354 CMDLINE_PAR_TYPE_UNASSIGNED,
14355 CMDLINE_PAR_TYPE_UNASSIGNED
14356 }
14357 },
14358 {
14359 cfFabdmax,
14360 {
14361 CMDLINE_PAR_TYPE_CMD_KEYTOKEN_FABDMAX,
14362 CMDLINE_PAR_TYPE_INTZERO,
14363 CMDLINE_PAR_TYPE_RATPOS,
14364 CMDLINE_PAR_TYPE_INTPOS,
14365 CMDLINE_PAR_TYPE_INTPOS,
14366 CMDLINE_PAR_TYPE_UNASSIGNED,
14367 CMDLINE_PAR_TYPE_UNASSIGNED,
14368 CMDLINE_PAR_TYPE_UNASSIGNED,
14369 CMDLINE_PAR_TYPE_UNASSIGNED,
14370 CMDLINE_PAR_TYPE_UNASSIGNED
14371 }
14372 },
14373 {
14374 cfFabdmax,
14375 {
14376 CMDLINE_PAR_TYPE_CMD_KEYTOKEN_FABDMAX,
14377 CMDLINE_PAR_TYPE_INTZERO,
14378 CMDLINE_PAR_TYPE_INTZERO,
14379 CMDLINE_PAR_TYPE_INTPOS,
14380 CMDLINE_PAR_TYPE_INTPOS,
14381 CMDLINE_PAR_TYPE_UNASSIGNED,
14382 CMDLINE_PAR_TYPE_UNASSIGNED,
14383 CMDLINE_PAR_TYPE_UNASSIGNED,
14384 CMDLINE_PAR_TYPE_UNASSIGNED,
14385 CMDLINE_PAR_TYPE_UNASSIGNED
14386 }
14387 },
14388 {
14389 cfFabdmax,
14390 {
14391 CMDLINE_PAR_TYPE_CMD_KEYTOKEN_FABDMAX,
14392 CMDLINE_PAR_TYPE_INTZERO,
14393 CMDLINE_PAR_TYPE_INTPOS,
14394 CMDLINE_PAR_TYPE_INTPOS,
14395 CMDLINE_PAR_TYPE_INTPOS,
14396 CMDLINE_PAR_TYPE_UNASSIGNED,
14397 CMDLINE_PAR_TYPE_UNASSIGNED,
14398 CMDLINE_PAR_TYPE_UNASSIGNED,
14399 CMDLINE_PAR_TYPE_UNASSIGNED,
14400 CMDLINE_PAR_TYPE_UNASSIGNED
14401 }
14402 },
14403 {
14404 cfFabdmax,
14405 {
14406 CMDLINE_PAR_TYPE_CMD_KEYTOKEN_FABDMAX,
14407 CMDLINE_PAR_TYPE_INTZERO,
14408 CMDLINE_PAR_TYPE_RATZERO,
14409 CMDLINE_PAR_TYPE_INTPOS,
14410 CMDLINE_PAR_TYPE_INTPOS,
14411 CMDLINE_PAR_TYPE_UNASSIGNED,
14412 CMDLINE_PAR_TYPE_UNASSIGNED,
14413 CMDLINE_PAR_TYPE_UNASSIGNED,
14414 CMDLINE_PAR_TYPE_UNASSIGNED,
14415 CMDLINE_PAR_TYPE_UNASSIGNED
14416 }
14417 },
14418 {
14419 cfFabdmax,
14420 {
14421 CMDLINE_PAR_TYPE_CMD_KEYTOKEN_FABDMAX,
14422 CMDLINE_PAR_TYPE_INTZERO,
14423 CMDLINE_PAR_TYPE_RATPOS,
14424 CMDLINE_PAR_TYPE_INTPOS,
14425 CMDLINE_PAR_TYPE_INTPOS,
14426 CMDLINE_PAR_TYPE_UNASSIGNED,
14427 CMDLINE_PAR_TYPE_UNASSIGNED,
14428 CMDLINE_PAR_TYPE_UNASSIGNED,
14429 CMDLINE_PAR_TYPE_UNASSIGNED,
14430 CMDLINE_PAR_TYPE_UNASSIGNED
14431 }
14432 },
14433 {
14434 cfFabdmax,
14435 {
14436 CMDLINE_PAR_TYPE_CMD_KEYTOKEN_FABDMAX,
14437 CMDLINE_PAR_TYPE_INTPOS,
14438 CMDLINE_PAR_TYPE_INTZERO,
14439 CMDLINE_PAR_TYPE_INTPOS,
14440 CMDLINE_PAR_TYPE_INTPOS,
14441 CMDLINE_PAR_TYPE_UNASSIGNED,
14442 CMDLINE_PAR_TYPE_UNASSIGNED,
14443 CMDLINE_PAR_TYPE_UNASSIGNED,
14444 CMDLINE_PAR_TYPE_UNASSIGNED,
14445 CMDLINE_PAR_TYPE_UNASSIGNED
14446 }
14447 },
14448 {
14449 cfFabdmax,
14450 {
14451 CMDLINE_PAR_TYPE_CMD_KEYTOKEN_FABDMAX,
14452 CMDLINE_PAR_TYPE_INTPOS,
14453 CMDLINE_PAR_TYPE_INTPOS,
14454 CMDLINE_PAR_TYPE_INTPOS,
14455 CMDLINE_PAR_TYPE_INTPOS,
14456 CMDLINE_PAR_TYPE_UNASSIGNED,
14457 CMDLINE_PAR_TYPE_UNASSIGNED,
14458 CMDLINE_PAR_TYPE_UNASSIGNED,
14459 CMDLINE_PAR_TYPE_UNASSIGNED,
14460 CMDLINE_PAR_TYPE_UNASSIGNED
14461 }
14462 },
14463 {
14464 cfFabdmax,
14465 {
14466 CMDLINE_PAR_TYPE_CMD_KEYTOKEN_FABDMAX,
14467 CMDLINE_PAR_TYPE_INTPOS,
14468 CMDLINE_PAR_TYPE_RATZERO,
14469 CMDLINE_PAR_TYPE_INTPOS,
14470 CMDLINE_PAR_TYPE_INTPOS,
14471 CMDLINE_PAR_TYPE_UNASSIGNED,
14472 CMDLINE_PAR_TYPE_UNASSIGNED,
14473 CMDLINE_PAR_TYPE_UNASSIGNED,
14474 CMDLINE_PAR_TYPE_UNASSIGNED,
14475 CMDLINE_PAR_TYPE_UNASSIGNED
14476 }
14477 },
14478 {
14479 cfFabdmax,
14480 {
14481 CMDLINE_PAR_TYPE_CMD_KEYTOKEN_FABDMAX,
14482 CMDLINE_PAR_TYPE_INTPOS,
14483 CMDLINE_PAR_TYPE_RATPOS,
14484 CMDLINE_PAR_TYPE_INTPOS,
14485 CMDLINE_PAR_TYPE_INTPOS,
14486 CMDLINE_PAR_TYPE_UNASSIGNED,
14487 CMDLINE_PAR_TYPE_UNASSIGNED,
14488 CMDLINE_PAR_TYPE_UNASSIGNED,
14489 CMDLINE_PAR_TYPE_UNASSIGNED,
14490 CMDLINE_PAR_TYPE_UNASSIGNED
14491 }
14492 },
14493 {
14494 cfFabdmax,
14495 {
14496 CMDLINE_PAR_TYPE_CMD_KEYTOKEN_FABDMAX,
14497 CMDLINE_PAR_TYPE_RATZERO,
14498 CMDLINE_PAR_TYPE_INTZERO,
14499 CMDLINE_PAR_TYPE_INTPOS,
14500 CMDLINE_PAR_TYPE_INTPOS,
14501 CMDLINE_PAR_TYPE_UNASSIGNED,
14502 CMDLINE_PAR_TYPE_UNASSIGNED,
14503 CMDLINE_PAR_TYPE_UNASSIGNED,
14504 CMDLINE_PAR_TYPE_UNASSIGNED,
14505 CMDLINE_PAR_TYPE_UNASSIGNED
14506 }
14507 },
14508 {
14509 cfFabdmax,
14510 {
14511 CMDLINE_PAR_TYPE_CMD_KEYTOKEN_FABDMAX,
14512 CMDLINE_PAR_TYPE_RATZERO,
14513 CMDLINE_PAR_TYPE_INTPOS,
14514 CMDLINE_PAR_TYPE_INTPOS,
14515 CMDLINE_PAR_TYPE_INTPOS,
14516 CMDLINE_PAR_TYPE_UNASSIGNED,
14517 CMDLINE_PAR_TYPE_UNASSIGNED,
14518 CMDLINE_PAR_TYPE_UNASSIGNED,
14519 CMDLINE_PAR_TYPE_UNASSIGNED,
14520 CMDLINE_PAR_TYPE_UNASSIGNED
14521 }
14522 },
14523 {
14524 cfFabdmax,
14525 {
14526 CMDLINE_PAR_TYPE_CMD_KEYTOKEN_FABDMAX,
14527 CMDLINE_PAR_TYPE_RATZERO,
14528 CMDLINE_PAR_TYPE_RATZERO,
14529 CMDLINE_PAR_TYPE_INTPOS,
14530 CMDLINE_PAR_TYPE_INTPOS,
14531 CMDLINE_PAR_TYPE_UNASSIGNED,
14532 CMDLINE_PAR_TYPE_UNASSIGNED,
14533 CMDLINE_PAR_TYPE_UNASSIGNED,
14534 CMDLINE_PAR_TYPE_UNASSIGNED,
14535 CMDLINE_PAR_TYPE_UNASSIGNED
14536 }
14537 },
14538 {
14539 cfFabdmax,
14540 {
14541 CMDLINE_PAR_TYPE_CMD_KEYTOKEN_FABDMAX,
14542 CMDLINE_PAR_TYPE_RATZERO,
14543 CMDLINE_PAR_TYPE_RATPOS,
14544 CMDLINE_PAR_TYPE_INTPOS,
14545 CMDLINE_PAR_TYPE_INTPOS,
14546 CMDLINE_PAR_TYPE_UNASSIGNED,
14547 CMDLINE_PAR_TYPE_UNASSIGNED,
14548 CMDLINE_PAR_TYPE_UNASSIGNED,
14549 CMDLINE_PAR_TYPE_UNASSIGNED,
14550 CMDLINE_PAR_TYPE_UNASSIGNED
14551 }
14552 },
14553 {
14554 cfFabdmax,
14555 {
14556 CMDLINE_PAR_TYPE_CMD_KEYTOKEN_FABDMAX,
14557 CMDLINE_PAR_TYPE_RATPOS,
14558 CMDLINE_PAR_TYPE_INTZERO,
14559 CMDLINE_PAR_TYPE_INTPOS,
14560 CMDLINE_PAR_TYPE_INTPOS,
14561 CMDLINE_PAR_TYPE_UNASSIGNED,
14562 CMDLINE_PAR_TYPE_UNASSIGNED,
14563 CMDLINE_PAR_TYPE_UNASSIGNED,
14564 CMDLINE_PAR_TYPE_UNASSIGNED,
14565 CMDLINE_PAR_TYPE_UNASSIGNED
14566 }
14567 },
14568 {
14569 cfFabdmax,
14570 {
14571 CMDLINE_PAR_TYPE_CMD_KEYTOKEN_FABDMAX,
14572 CMDLINE_PAR_TYPE_RATPOS,
14573 CMDLINE_PAR_TYPE_INTPOS,
14574 CMDLINE_PAR_TYPE_INTPOS,
14575 CMDLINE_PAR_TYPE_INTPOS,
14576 CMDLINE_PAR_TYPE_UNASSIGNED,
14577 CMDLINE_PAR_TYPE_UNASSIGNED,
14578 CMDLINE_PAR_TYPE_UNASSIGNED,
14579 CMDLINE_PAR_TYPE_UNASSIGNED,
14580 CMDLINE_PAR_TYPE_UNASSIGNED
14581 }
14582 },
14583 {
14584 cfFabdmax,
14585 {
14586 CMDLINE_PAR_TYPE_CMD_KEYTOKEN_FABDMAX,
14587 CMDLINE_PAR_TYPE_RATPOS,
14588 CMDLINE_PAR_TYPE_RATZERO,
14589 CMDLINE_PAR_TYPE_INTPOS,
14590 CMDLINE_PAR_TYPE_INTPOS,
14591 CMDLINE_PAR_TYPE_UNASSIGNED,
14592 CMDLINE_PAR_TYPE_UNASSIGNED,
14593 CMDLINE_PAR_TYPE_UNASSIGNED,
14594 CMDLINE_PAR_TYPE_UNASSIGNED,
14595 CMDLINE_PAR_TYPE_UNASSIGNED
14596 }
14597 },
14598 {
14599 cfFabdmax,
14600 {
14601 CMDLINE_PAR_TYPE_CMD_KEYTOKEN_FABDMAX,
14602 CMDLINE_PAR_TYPE_RATPOS,
14603 CMDLINE_PAR_TYPE_RATPOS,
14604 CMDLINE_PAR_TYPE_INTPOS,
14605 CMDLINE_PAR_TYPE_INTPOS,
14606 CMDLINE_PAR_TYPE_UNASSIGNED,
14607 CMDLINE_PAR_TYPE_UNASSIGNED,
14608 CMDLINE_PAR_TYPE_UNASSIGNED,
14609 CMDLINE_PAR_TYPE_UNASSIGNED,
14610 CMDLINE_PAR_TYPE_UNASSIGNED
14611 }
14612 },
14613 {
14614 cfFabdmax,
14615 {
14616 CMDLINE_PAR_TYPE_CMD_KEYTOKEN_FABDMAX,
14617 CMDLINE_PAR_TYPE_INTZERO,
14618 CMDLINE_PAR_TYPE_INTZERO,
14619 CMDLINE_PAR_TYPE_INTPOS,
14620 CMDLINE_PAR_TYPE_INTPOS,
14621 CMDLINE_PAR_TYPE_INTPOS,
14622 CMDLINE_PAR_TYPE_UNASSIGNED,
14623 CMDLINE_PAR_TYPE_UNASSIGNED,
14624 CMDLINE_PAR_TYPE_UNASSIGNED,
14625 CMDLINE_PAR_TYPE_UNASSIGNED
14626 }
14627 },
14628 {
14629 cfFabdmax,
14630 {
14631 CMDLINE_PAR_TYPE_CMD_KEYTOKEN_FABDMAX,
14632 CMDLINE_PAR_TYPE_INTZERO,
14633 CMDLINE_PAR_TYPE_INTPOS,
14634 CMDLINE_PAR_TYPE_INTPOS,
14635 CMDLINE_PAR_TYPE_INTPOS,
14636 CMDLINE_PAR_TYPE_INTPOS,
14637 CMDLINE_PAR_TYPE_UNASSIGNED,
14638 CMDLINE_PAR_TYPE_UNASSIGNED,
14639 CMDLINE_PAR_TYPE_UNASSIGNED,
14640 CMDLINE_PAR_TYPE_UNASSIGNED
14641 }
14642 },
14643 {
14644 cfFabdmax,
14645 {
14646 CMDLINE_PAR_TYPE_CMD_KEYTOKEN_FABDMAX,
14647 CMDLINE_PAR_TYPE_INTZERO,
14648 CMDLINE_PAR_TYPE_RATZERO,
14649 CMDLINE_PAR_TYPE_INTPOS,
14650 CMDLINE_PAR_TYPE_INTPOS,
14651 CMDLINE_PAR_TYPE_INTPOS,
14652 CMDLINE_PAR_TYPE_UNASSIGNED,
14653 CMDLINE_PAR_TYPE_UNASSIGNED,
14654 CMDLINE_PAR_TYPE_UNASSIGNED,
14655 CMDLINE_PAR_TYPE_UNASSIGNED
14656 }
14657 },
14658 {
14659 cfFabdmax,
14660 {
14661 CMDLINE_PAR_TYPE_CMD_KEYTOKEN_FABDMAX,
14662 CMDLINE_PAR_TYPE_INTZERO,
14663 CMDLINE_PAR_TYPE_RATPOS,
14664 CMDLINE_PAR_TYPE_INTPOS,
14665 CMDLINE_PAR_TYPE_INTPOS,
14666 CMDLINE_PAR_TYPE_INTPOS,
14667 CMDLINE_PAR_TYPE_UNASSIGNED,
14668 CMDLINE_PAR_TYPE_UNASSIGNED,
14669 CMDLINE_PAR_TYPE_UNASSIGNED,
14670 CMDLINE_PAR_TYPE_UNASSIGNED
14671 }
14672 },
14673 {
14674 cfFabdmax,
14675 {
14676 CMDLINE_PAR_TYPE_CMD_KEYTOKEN_FABDMAX,
14677 CMDLINE_PAR_TYPE_INTZERO,
14678 CMDLINE_PAR_TYPE_INTZERO,
14679 CMDLINE_PAR_TYPE_INTPOS,
14680 CMDLINE_PAR_TYPE_INTPOS,
14681 CMDLINE_PAR_TYPE_INTPOS,
14682 CMDLINE_PAR_TYPE_UNASSIGNED,
14683 CMDLINE_PAR_TYPE_UNASSIGNED,
14684 CMDLINE_PAR_TYPE_UNASSIGNED,
14685 CMDLINE_PAR_TYPE_UNASSIGNED
14686 }
14687 },
14688 {
14689 cfFabdmax,
14690 {
14691 CMDLINE_PAR_TYPE_CMD_KEYTOKEN_FABDMAX,
14692 CMDLINE_PAR_TYPE_INTZERO,
14693 CMDLINE_PAR_TYPE_INTPOS,
14694 CMDLINE_PAR_TYPE_INTPOS,
14695 CMDLINE_PAR_TYPE_INTPOS,
14696 CMDLINE_PAR_TYPE_INTPOS,
14697 CMDLINE_PAR_TYPE_UNASSIGNED,
14698 CMDLINE_PAR_TYPE_UNASSIGNED,
14699 CMDLINE_PAR_TYPE_UNASSIGNED,
14700 CMDLINE_PAR_TYPE_UNASSIGNED
14701 }
14702 },
14703 {
14704 cfFabdmax,
14705 {
14706 CMDLINE_PAR_TYPE_CMD_KEYTOKEN_FABDMAX,
14707 CMDLINE_PAR_TYPE_INTZERO,
14708 CMDLINE_PAR_TYPE_RATZERO,
14709 CMDLINE_PAR_TYPE_INTPOS,
14710 CMDLINE_PAR_TYPE_INTPOS,
14711 CMDLINE_PAR_TYPE_INTPOS,
14712 CMDLINE_PAR_TYPE_UNASSIGNED,
14713 CMDLINE_PAR_TYPE_UNASSIGNED,
14714 CMDLINE_PAR_TYPE_UNASSIGNED,
14715 CMDLINE_PAR_TYPE_UNASSIGNED
14716 }
14717 },
14718 {
14719 cfFabdmax,
14720 {
14721 CMDLINE_PAR_TYPE_CMD_KEYTOKEN_FABDMAX,
14722 CMDLINE_PAR_TYPE_INTZERO,
14723 CMDLINE_PAR_TYPE_RATPOS,
14724 CMDLINE_PAR_TYPE_INTPOS,
14725 CMDLINE_PAR_TYPE_INTPOS,
14726 CMDLINE_PAR_TYPE_INTPOS,
14727 CMDLINE_PAR_TYPE_UNASSIGNED,
14728 CMDLINE_PAR_TYPE_UNASSIGNED,
14729 CMDLINE_PAR_TYPE_UNASSIGNED,
14730 CMDLINE_PAR_TYPE_UNASSIGNED
14731 }
14732 },
14733 {
14734 cfFabdmax,
14735 {
14736 CMDLINE_PAR_TYPE_CMD_KEYTOKEN_FABDMAX,
14737 CMDLINE_PAR_TYPE_INTPOS,
14738 CMDLINE_PAR_TYPE_INTZERO,
14739 CMDLINE_PAR_TYPE_INTPOS,
14740 CMDLINE_PAR_TYPE_INTPOS,
14741 CMDLINE_PAR_TYPE_INTPOS,
14742 CMDLINE_PAR_TYPE_UNASSIGNED,
14743 CMDLINE_PAR_TYPE_UNASSIGNED,
14744 CMDLINE_PAR_TYPE_UNASSIGNED,
14745 CMDLINE_PAR_TYPE_UNASSIGNED
14746 }
14747 },
14748 {
14749 cfFabdmax,
14750 {
14751 CMDLINE_PAR_TYPE_CMD_KEYTOKEN_FABDMAX,
14752 CMDLINE_PAR_TYPE_INTPOS,
14753 CMDLINE_PAR_TYPE_INTPOS,
14754 CMDLINE_PAR_TYPE_INTPOS,
14755 CMDLINE_PAR_TYPE_INTPOS,
14756 CMDLINE_PAR_TYPE_INTPOS,
14757 CMDLINE_PAR_TYPE_UNASSIGNED,
14758 CMDLINE_PAR_TYPE_UNASSIGNED,
14759 CMDLINE_PAR_TYPE_UNASSIGNED,
14760 CMDLINE_PAR_TYPE_UNASSIGNED
14761 }
14762 },
14763 {
14764 cfFabdmax,
14765 {
14766 CMDLINE_PAR_TYPE_CMD_KEYTOKEN_FABDMAX,
14767 CMDLINE_PAR_TYPE_INTPOS,
14768 CMDLINE_PAR_TYPE_RATZERO,
14769 CMDLINE_PAR_TYPE_INTPOS,
14770 CMDLINE_PAR_TYPE_INTPOS,
14771 CMDLINE_PAR_TYPE_INTPOS,
14772 CMDLINE_PAR_TYPE_UNASSIGNED,
14773 CMDLINE_PAR_TYPE_UNASSIGNED,
14774 CMDLINE_PAR_TYPE_UNASSIGNED,
14775 CMDLINE_PAR_TYPE_UNASSIGNED
14776 }
14777 },
14778 {
14779 cfFabdmax,
14780 {
14781 CMDLINE_PAR_TYPE_CMD_KEYTOKEN_FABDMAX,
14782 CMDLINE_PAR_TYPE_INTPOS,
14783 CMDLINE_PAR_TYPE_RATPOS,
14784 CMDLINE_PAR_TYPE_INTPOS,
14785 CMDLINE_PAR_TYPE_INTPOS,
14786 CMDLINE_PAR_TYPE_INTPOS,
14787 CMDLINE_PAR_TYPE_UNASSIGNED,
14788 CMDLINE_PAR_TYPE_UNASSIGNED,
14789 CMDLINE_PAR_TYPE_UNASSIGNED,
14790 CMDLINE_PAR_TYPE_UNASSIGNED
14791 }
14792 },
14793 {
14794 cfFabdmax,
14795 {
14796 CMDLINE_PAR_TYPE_CMD_KEYTOKEN_FABDMAX,
14797 CMDLINE_PAR_TYPE_RATZERO,
14798 CMDLINE_PAR_TYPE_INTZERO,
14799 CMDLINE_PAR_TYPE_INTPOS,
14800 CMDLINE_PAR_TYPE_INTPOS,
14801 CMDLINE_PAR_TYPE_INTPOS,
14802 CMDLINE_PAR_TYPE_UNASSIGNED,
14803 CMDLINE_PAR_TYPE_UNASSIGNED,
14804 CMDLINE_PAR_TYPE_UNASSIGNED,
14805 CMDLINE_PAR_TYPE_UNASSIGNED
14806 }
14807 },
14808 {
14809 cfFabdmax,
14810 {
14811 CMDLINE_PAR_TYPE_CMD_KEYTOKEN_FABDMAX,
14812 CMDLINE_PAR_TYPE_RATZERO,
14813 CMDLINE_PAR_TYPE_INTPOS,
14814 CMDLINE_PAR_TYPE_INTPOS,
14815 CMDLINE_PAR_TYPE_INTPOS,
14816 CMDLINE_PAR_TYPE_INTPOS,
14817 CMDLINE_PAR_TYPE_UNASSIGNED,
14818 CMDLINE_PAR_TYPE_UNASSIGNED,
14819 CMDLINE_PAR_TYPE_UNASSIGNED,
14820 CMDLINE_PAR_TYPE_UNASSIGNED
14821 }
14822 },
14823 {
14824 cfFabdmax,
14825 {
14826 CMDLINE_PAR_TYPE_CMD_KEYTOKEN_FABDMAX,
14827 CMDLINE_PAR_TYPE_RATZERO,
14828 CMDLINE_PAR_TYPE_RATZERO,
14829 CMDLINE_PAR_TYPE_INTPOS,
14830 CMDLINE_PAR_TYPE_INTPOS,
14831 CMDLINE_PAR_TYPE_INTPOS,
14832 CMDLINE_PAR_TYPE_UNASSIGNED,
14833 CMDLINE_PAR_TYPE_UNASSIGNED,
14834 CMDLINE_PAR_TYPE_UNASSIGNED,
14835 CMDLINE_PAR_TYPE_UNASSIGNED
14836 }
14837 },
14838 {
14839 cfFabdmax,
14840 {
14841 CMDLINE_PAR_TYPE_CMD_KEYTOKEN_FABDMAX,
14842 CMDLINE_PAR_TYPE_RATZERO,
14843 CMDLINE_PAR_TYPE_RATPOS,
14844 CMDLINE_PAR_TYPE_INTPOS,
14845 CMDLINE_PAR_TYPE_INTPOS,
14846 CMDLINE_PAR_TYPE_INTPOS,
14847 CMDLINE_PAR_TYPE_UNASSIGNED,
14848 CMDLINE_PAR_TYPE_UNASSIGNED,
14849 CMDLINE_PAR_TYPE_UNASSIGNED,
14850 CMDLINE_PAR_TYPE_UNASSIGNED
14851 }
14852 },
14853 {
14854 cfFabdmax,
14855 {
14856 CMDLINE_PAR_TYPE_CMD_KEYTOKEN_FABDMAX,
14857 CMDLINE_PAR_TYPE_RATPOS,
14858 CMDLINE_PAR_TYPE_INTZERO,
14859 CMDLINE_PAR_TYPE_INTPOS,
14860 CMDLINE_PAR_TYPE_INTPOS,
14861 CMDLINE_PAR_TYPE_INTPOS,
14862 CMDLINE_PAR_TYPE_UNASSIGNED,
14863 CMDLINE_PAR_TYPE_UNASSIGNED,
14864 CMDLINE_PAR_TYPE_UNASSIGNED,
14865 CMDLINE_PAR_TYPE_UNASSIGNED
14866 }
14867 },
14868 {
14869 cfFabdmax,
14870 {
14871 CMDLINE_PAR_TYPE_CMD_KEYTOKEN_FABDMAX,
14872 CMDLINE_PAR_TYPE_RATPOS,
14873 CMDLINE_PAR_TYPE_INTPOS,
14874 CMDLINE_PAR_TYPE_INTPOS,
14875 CMDLINE_PAR_TYPE_INTPOS,
14876 CMDLINE_PAR_TYPE_INTPOS,
14877 CMDLINE_PAR_TYPE_UNASSIGNED,
14878 CMDLINE_PAR_TYPE_UNASSIGNED,
14879 CMDLINE_PAR_TYPE_UNASSIGNED,
14880 CMDLINE_PAR_TYPE_UNASSIGNED
14881 }
14882 },
14883 {
14884 cfFabdmax,
14885 {
14886 CMDLINE_PAR_TYPE_CMD_KEYTOKEN_FABDMAX,
14887 CMDLINE_PAR_TYPE_RATPOS,
14888 CMDLINE_PAR_TYPE_RATZERO,
14889 CMDLINE_PAR_TYPE_INTPOS,
14890 CMDLINE_PAR_TYPE_INTPOS,
14891 CMDLINE_PAR_TYPE_INTPOS,
14892 CMDLINE_PAR_TYPE_UNASSIGNED,
14893 CMDLINE_PAR_TYPE_UNASSIGNED,
14894 CMDLINE_PAR_TYPE_UNASSIGNED,
14895 CMDLINE_PAR_TYPE_UNASSIGNED
14896 }
14897 },
14898 {
14899 cfFabdmax,
14900 {
14901 CMDLINE_PAR_TYPE_CMD_KEYTOKEN_FABDMAX,
14902 CMDLINE_PAR_TYPE_RATPOS,
14903 CMDLINE_PAR_TYPE_RATPOS,
14904 CMDLINE_PAR_TYPE_INTPOS,
14905 CMDLINE_PAR_TYPE_INTPOS,
14906 CMDLINE_PAR_TYPE_INTPOS,
14907 CMDLINE_PAR_TYPE_UNASSIGNED,
14908 CMDLINE_PAR_TYPE_UNASSIGNED,
14909 CMDLINE_PAR_TYPE_UNASSIGNED,
14910 CMDLINE_PAR_TYPE_UNASSIGNED
14911 }
14912 },
14913 };
14914
14915 int i;
14916 int j;
14917
14918 /* Try to match the par_block against the templates, and call the first
14919 ** function that gives a match. If there isn't a match in the table,
14920 ** this is an error, as the user has specified something that the program
14921 ** isn't prepared to handle.
14922 */
14923
14924 for (i=0; i<sizeof(cmd_templates)/sizeof(cmd_templates[0]); i++)
14925 /* For each template.
14926 */
14927 {
14928 /* printf("Processing table entry: %d\n", i); */
14929
14930 for (j=0; j<MAX_CMDLINE_PARS; j++)
14931 {
14932
14933 /* printf(" Processing template entry: %d, tbl: %d, pars: %d\n", j,
14934 cmd_templates[i].template[j],
14935 par_block.pars[j].ftype); */
14936
14937 if ((cmd_templates[i].template[j]) != (par_block.pars[j].ftype))
14938 break;
14939 }
14940
14941 if (j==MAX_CMDLINE_PARS)
14942 {
14943 (cmd_templates[i].fptr)();
14944 break;
14945 }
14946 }
14947
14948 if (i==sizeof(cmd_templates)/sizeof(cmd_templates[0]))
14949 {
14950 asFatal("no match of command and pars to cmd template");
14951 }
14952 }
14953
14954
14955 /****************************************************************************/
14956 /****************************************************************************/
14957 /**************** U N I T T E S T F U N C T I O N S ***************/
14958 /****************************************************************************/
14959 /****************************************************************************/
14960 /* These functions constitute a crude unit test. This code will be
14961 ** preprocessed out before this is released to the ACM.
14962 */
14963
14964 #if 0
14965 /****************************************************************************/
14966 /* utFunc1(): */
14967 /*--------------------------------------------------------------------------*/
14968 /* DESCRIPTION */
14969 /* Double-checks the way that integers are presented (titles, commas, */
14970 /* etc.). */
14971 /****************************************************************************/
14972 void utFunc1(void)
14973 {
14974 long vectors[] = {-876437264, -10, -9, -2, -1, 0, 1, 2, 3, 10, 99, 29343432};
14975 unsigned i;
14976 SYNTHETIC_INTEGER *si1;
14977 char buf[100];
14978
14979 /* Create a synthetic integer.
14980 */
14981 siCreate(&si1);
14982
14983 /* Run through each of the test vectors.
14984 */
14985 for (i=0; i<sizeof(vectors)/sizeof(vectors[0]); i++)
14986 {
14987 /* Assign it to be the integer 0. */
14988 siSetToLong(&si1, vectors[i]);
14989
14990 /* Print the value. */
14991 sprintf(buf, "Vector[%u]", i);
14992 siDump(&si1, buf);
14993
14994 /* Add a horizontal line. */
14995 gfHline();
14996 }
14997
14998 /* Destroy the synthetic integer. */
14999 siDestroy(&si1 );
15000 }
15001
15002
15003 /****************************************************************************/
15004 /* utFunc2(): */
15005 /*--------------------------------------------------------------------------*/
15006 /* DESCRIPTION */
15007 /* Double-checks the way that integers are added, and also the NAN which */
15008 /* should occur on overflow. Powers of two are generated by doubling. */
15009 /****************************************************************************/
15010 void utFunc2(void)
15011 {
15012 SYNTHETIC_INTEGER *arg1, *arg2, *result;
15013 int i;
15014 char buf[100];
15015
15016 siCreate(&arg1);
15017 siCreate(&arg2);
15018 siCreate(&result);
15019
15020 siSetToLong(&arg1, 0);
15021 siSetToLong(&arg2, 1);
15022 /* Ln(2)/Ln(10) is 0.30, so we should run out of space
15023 ** in around 4000/0.30 = 13,300 or so iterations.
15024 */
15025
15026 for (i=0; i<13300; i++)
15027 {
15028 siAddTwoNonnegative(&arg1, &arg2, &result);
15029 siCopy(&result, &arg1);
15030 siCopy(&result, &arg2);
15031 sprintf(buf, "Iteration %d", i);
15032 siDump(&result, buf);
15033 gfHline();
15034 }
15035
15036 siDestroy(&arg1);
15037 siDestroy(&arg2);
15038 siDestroy(&result);
15039 }
15040
15041
15042 /****************************************************************************/
15043 /* utFunc3(): */
15044 /*--------------------------------------------------------------------------*/
15045 /* DESCRIPTION */
15046 /* Double-checks the behavior of the non-negative result subtraction */
15047 /* function. */
15048 /****************************************************************************/
15049 void utFunc3(void)
15050 {
15051 long vectors[] = { 0, 0, /* zero minus zero should be zero */
15052 1000, 0,
15053 9, 0,
15054 1000, 1,
15055 99, 33,
15056 99, 99,
15057 99, 98,
15058 99, 97,
15059 99, 96,
15060 99, 95,
15061 99, 94,
15062 99, 93,
15063 99, 92,
15064 99, 91,
15065 99, 90,
15066 99, 89,
15067 99, 88,
15068 99, 97,
15069 10101, 101,
15070 10101, 102,
15071 10101, 100,
15072 };
15073
15074 unsigned i;
15075 SYNTHETIC_INTEGER *si1, *si2, *result;
15076 char buf[100];
15077
15078 /* Create the synthetic integers
15079 */
15080 siCreate(&si1);
15081 siCreate(&si2);
15082 siCreate(&result);
15083
15084 /* Run through each of the test vectors.
15085 */
15086 for (i=0; i< sizeof(vectors)/sizeof(vectors[0]); i+=2)
15087 {
15088 /* Assign the value to be subtracted from. */
15089 siSetToLong(&si1, vectors[i]);
15090
15091 /* Assign the value to be subtracted. */
15092 siSetToLong(&si2, vectors[i+1]);
15093
15094 /* Make the subtraction. */
15095 siSubtractToProduceNonnegativeResult(&si1, &si2, &result);
15096
15097 /* Print the values. */
15098 sprintf(buf, "Vector[%u] Arg 1", i/2);
15099 siDump(&si1, buf);
15100 gfHline();
15101 sprintf(buf, "Vector[%u] Arg 2", i/2);
15102 siDump(&si2, buf);
15103 gfHline();
15104 sprintf(buf, "Vector[%u] Result", i/2);
15105 siDump(&result, buf);
15106 gfHline();
15107 }
15108
15109 /* Destroy the synthetic integers. */
15110 siDestroy(&si1 );
15111 siDestroy(&si2 );
15112 siDestroy(&result );
15113 }
15114
15115
15116 /****************************************************************************/
15117 /* utFunc4(): */
15118 /*--------------------------------------------------------------------------*/
15119 /* DESCRIPTION */
15120 /* Double-checks the behavior of the general addition function. */
15121 /****************************************************************************/
15122 void utFunc4(void)
15123 {
15124 long vectors[] = { /* This group is the vectors copied from the
15125 ** table in the function above. These are
15126 ** non-specific, but can do no harm to run them
15127 ** through.
15128 */
15129 0, 0, /* zero minus zero should be zero */
15130 1000, 0,
15131 9, 0,
15132 1000, 1,
15133 99, 33,
15134 99, 99,
15135 99, 98,
15136 99, 97,
15137 99, 96,
15138 99, 95,
15139 99, 94,
15140 99, 93,
15141 99, 92,
15142 99, 91,
15143 99, 90,
15144 99, 89,
15145 99, 88,
15146 99, 97,
15147 10101, 101,
15148 10101, 102,
15149 10101, 100,
15150 /* These are the specific vectors. Want to run them
15151 ** through each of the 12 cases in the function.
15152 */
15153 0, 0,
15154 0, -583,
15155 -583, 0,
15156 0, 583,
15157 583, 0,
15158 583, -12,
15159 -12, 583,
15160 -609, 11,
15161 11, -609,
15162 329, 329,
15163 -329, -329,
15164 327, 252,
15165 252, 329,
15166 -21, -591,
15167 321, -321,
15168 -322, 322,
15169 -42923, -31998,
15170 };
15171
15172 unsigned i;
15173 SYNTHETIC_INTEGER *si1, *si2, *result;
15174 char buf[100];
15175
15176 /* Create the synthetic integers
15177 */
15178 siCreate(&si1);
15179 siCreate(&si2);
15180 siCreate(&result);
15181
15182 /* Run through each of the test vectors.
15183 */
15184 for (i=0; i< sizeof(vectors)/sizeof(vectors[0]); i+=2)
15185 {
15186 /* Assign the value to be subtracted from. */
15187 siSetToLong(&si1, vectors[i]);
15188
15189 /* Assign the value to be subtracted. */
15190 siSetToLong(&si2, vectors[i+1]);
15191
15192 /* Make the addition. */
15193 siUnrestrictedAddition(&si1, &si2, &result);
15194
15195 /* Print the values. */
15196 sprintf(buf, "Vector[%u] Arg 1", i/2);
15197 siDump(&si1, buf);
15198 gfHline();
15199 sprintf(buf, "Vector[%u] Arg 2", i/2);
15200 siDump(&si2, buf);
15201 gfHline();
15202 sprintf(buf, "Vector[%u] Result", i/2);
15203 siDump(&result, buf);
15204 gfHline();
15205 }
15206
15207 /* Destroy the synthetic integers. */
15208 siDestroy(&si1 );
15209 siDestroy(&si2 );
15210 siDestroy(&result );
15211 }
15212
15213
15214 /****************************************************************************/
15215 /* utUnittestAll(): */
15216 /*--------------------------------------------------------------------------*/
15217 /* DESCRIPTION */
15218 /* Sequentially runs all unit tests. */
15219 /****************************************************************************/
15220 void utUnitTestAll(void)
15221 {
15222 /* utFunc1(); */
15223 /* utFunc2(); */
15224 /* utFunc3(); */
15225 /* utFunc4(); */
15226 }
15227 #endif
15228
15229
15230 /****************************************************************************/
15231 /****************************************************************************/
15232 /******************** M A I N F U N C T I O N ************************/
15233 /****************************************************************************/
15234 /****************************************************************************/
15235
15236 /****************************************************************************/
15237 /* main_c(): */
15238 /*--------------------------------------------------------------------------*/
15239 /* DESCRIPTION */
15240 /* Main function of the program. If this program is ported, main_c() */
15241 /* must be renamed to main(). The name of main_c() [different than */
15242 /* main()] was chosen because the main() function of Visual C++ is in */
15243 /* another source file (it is a C++ wrapper), and two functions cannot */
15244 /* both have the name main(). */
15245 /* */
15246 /* INPUTS */
15247 /* argc, argv : The count of command-line parameters and the command- */
15248 /* line parameters. */
15249 /****************************************************************************/
15250 int main_c(int argc, char* argv[])
15251 {
15252 /*************************************************************************/
15253 char *stdin_array = NULL;
15254 /* The characters read from the standard input, verbatim, before
15255 ** further parsing. This pointer, if it is assigned, is a
15256 ** dynamically allocated block, terminated with '\0', and should
15257 ** be free'd at some point.
15258 */
15259 /*************************************************************************/
15260 struct ipSimpleStringLlNodeStruct *raw_tokens_list = NULL;
15261 /* Linked list of raw tokens from either the command-line or
15262 ** the standard input if running in batch mode.
15263 */
15264
15265 #if 0
15266 {
15267 int idx;
15268
15269 SYNTHETIC_INTEGER *h1, *h2, *k1, *k2, *N;
15270
15271 siCreate(&h1);
15272 siCreate(&h2);
15273 siCreate(&k1);
15274 siCreate(&k2);
15275 siCreate(&N);
15276
15277 siSetToLong(&h1, 0);
15278 siSetToLong(&k1, 1);
15279 siSetToLong(&h2, 1);
15280 siSetToLong(&k2, 1000);
15281 siSetToLong(&N, 1000);
15282
15283 for (idx=0; idx<10000; idx++)
15284 {
15285 rnFareyTraverse(&h1, &k1, &h2, &k2, &N, 1);
15286
15287 printf("index: %d\n", idx);
15288 siDump(&h1, "h1");
15289 siDump(&k1, "k1");
15290 siDump(&h2, "h2");
15291 siDump(&k2, "k2");
15292 siDump(&N, "N");
15293 gfHline();
15294 }
15295
15296 for (idx=9999; idx>=0; idx--)
15297 {
15298 rnFareyTraverse(&h1, &k1, &h2, &k2, &N, -1);
15299
15300 printf("index: %d\n", idx);
15301 siDump(&h1, "h1");
15302 siDump(&k1, "k1");
15303 siDump(&h2, "h2");
15304 siDump(&k2, "k2");
15305 siDump(&N, "N");
15306 gfHline();
15307 }
15308
15309 exit(0);
15310 }
15311
15312 #endif
15313 #if 0
15314 {
15315 int i;
15316
15317 for (i=-10; i <= 10; i++)
15318 {
15319 printf("i: %d, i mod 3: %d\n", i, i%3);
15320 }
15321
15322 for (i=-10; i <= 10; i++)
15323 {
15324 printf("i: %d, i mod -3: %d\n", i, i%(-3));
15325 }
15326
15327 exit(0);
15328 }
15329 #endif
15330
15331 /*************************************************************************/
15332 /* Write introductory message, including version control information. */
15333 gfHline();printf("RAP (");{unsigned i = 0;while (vcGetVcData(i)){printf(
15334 "%s",vcGetVcData(i));i++;}}printf(") execution begins.\n");gfHline();
15335 /*************************************************************************/
15336 /* Run all built-in unit tests (used only for development). */
15337 /* utUnitTestAll(); */
15338 /*************************************************************************/
15339 /* Split into two cases. Either the command-line pars are on the
15340 ** command-line, or they are coming from stdin. In this section get to
15341 ** the point of having an array of tokens, before concatenation is
15342 ** performed.
15343 */
15344
15345 #if 0
15346 {
15347 SYNTHETIC_INTEGER *i, *j, *k;
15348
15349 siCreate(&i);
15350
15351 siSetToLong(&i, 788);
15352
15353 siDump(&i, "788");
15354
15355 siMulByDigit(&i, '3');
15356
15357 siDump(&i, "3*788");
15358
15359 }
15360 #endif
15361
15362
15363 if (argc==0)
15364 {
15365 asFatal("argc can't be zero--runtime environment anomaly");
15366 }
15367 if (argc==1)
15368 {
15369 /* "rap" used alone on command line. Probably this is a user trying
15370 ** to figure out what this executable on his hard drive is. Print out
15371 ** an informational message and exit.
15372 */
15373 asInfo();
15374 }
15375 else if (argc==2)
15376 {
15377 /* If there are two arguments, the second one must be "batch" or the
15378 ** program can't process the input.
15379 */
15380 if (_stricmp("batch", argv[1]))
15381 {
15382 asFatal("if only one command-line parameter specified, must be \"batch\"");
15383 }
15384 else
15385 {
15386 /* We're running batch mode. Must take our parameters from a file as if they
15387 ** came from the command line.
15388 */
15389 /* First, buffer the entire standard input stream to a character buffer.
15390 */
15391 stdin_array = ipBufferStandardInputStream();
15392 /* printf("%d\n", strlen(stdin_array)); */
15393 /* printf("%s\n", stdin_array); */
15394
15395 /* Make the transformation from the buffered standard input array to
15396 ** a linked list of tokens.
15397 */
15398 ipTranslateStdinToRawTokens(stdin_array, &raw_tokens_list);
15399
15400 /* At this point, the array of characters taken from the standard
15401 ** input is disposable. Free it up.
15402 */
15403 maFree(stdin_array);
15404 stdin_array = NULL;
15405 }
15406 }
15407 else
15408 {
15409 /* argc > 2. In this case, can take the command-line arguments and
15410 ** pack them into a linked list, same as would do with stdin input.
15411 */
15412 ipPackCmdLineArgsIntoLinkedList(argc, argv, &raw_tokens_list);
15413 }
15414
15415 /* In either case (whether we obtained the linked list from the command-line
15416 ** or from stdin), we must process continuation characters and concatenate tokens.
15417 */
15418 ipProcessLinkedListParameterContinuationCharacters(&raw_tokens_list);
15419
15420 /* Parse the command-line or stdin parameters.
15421 */
15422 ipParseCommandLineParameters(&raw_tokens_list);
15423
15424 #if 1
15425 /* Search for a matching command template and execute the command if appropriate
15426 ** or error out if no template match.
15427 */
15428 ipExecuteCommand();
15429 #endif
15430
15431
15432 #if 0
15433 /* For diagnostic purposes, print out the linked list. */
15434 {
15435 struct ipSimpleStringLlNodeStruct *p;
15436
15437 p = raw_tokens_list;
15438
15439 while (p)
15440 {
15441 printf("%s\n", p->s);
15442
15443 p = p->next;
15444 }
15445
15446 }
15447 #endif
15448 #if 0
15449 gfBannerHeading("Test 21", 2);
15450 #endif
15451
15452 /*************************************************************************/
15453 printf("RAP execution ends.\n");gfHline();
15454 /*************************************************************************/
15455 return(0); /* Return value not set for caller--zero used in all cases. */
15456 /*************************************************************************/
15457 }
15458
15459
15460 /* $History: rap_c.c $
15461 *
15462 * ***************** Version 21 *****************
15463 * User: Dashley1 Date: 11/13/00 Time: 3:59a
15464 * Updated in $/ACM Rational Approximation Paper And Algorithms/C-Language Implementation
15465 * Final versions for submission to the ACM.
15466 *
15467 * ***************** Version 20 *****************
15468 * User: Dashley1 Date: 11/10/00 Time: 10:49a
15469 * Updated in $/ACM Rational Approximation Paper And Algorithms/C-Language Implementation
15470 * Completion of FAB functionality.
15471 *
15472 * ***************** Version 19 *****************
15473 * User: Dashley1 Date: 11/09/00 Time: 1:04a
15474 * Updated in $/ACM Rational Approximation Paper And Algorithms/C-Language Implementation
15475 * Completion of minimum denominator work.
15476 *
15477 * ***************** Version 18 *****************
15478 * User: Dashley1 Date: 11/01/00 Time: 6:21p
15479 * Updated in $/ACM Rational Approximation Paper And Algorithms/C-Language Implementation
15480 * FN functionality completed.
15481 *
15482 * ***************** Version 17 *****************
15483 * User: Dashley1 Date: 11/01/00 Time: 4:42a
15484 * Updated in $/ACM Rational Approximation Paper And Algorithms/C-Language Implementation
15485 * FN functionality mostly complete. Throws an OS exception when rational
15486 * number to approximate is < 1/N, need to proofread and diagnose.
15487 *
15488 * ***************** Version 16 *****************
15489 * User: Dashley1 Date: 10/30/00 Time: 6:40p
15490 * Updated in $/ACM Rational Approximation Paper And Algorithms/C-Language Implementation
15491 * Completion of CF expansion functionality.
15492 *
15493 * ***************** Version 15 *****************
15494 * User: Dashley1 Date: 10/29/00 Time: 10:09p
15495 * Updated in $/ACM Rational Approximation Paper And Algorithms/C-Language Implementation
15496 * DAP function finished and checked.
15497 *
15498 * ***************** Version 14 *****************
15499 * User: Dashley1 Date: 10/29/00 Time: 4:00a
15500 * Updated in $/ACM Rational Approximation Paper And Algorithms/C-Language Implementation
15501 * Safety check-in.
15502 *
15503 * ***************** Version 13 *****************
15504 * User: Dashley1 Date: 10/28/00 Time: 4:23a
15505 * Updated in $/ACM Rational Approximation Paper And Algorithms/C-Language Implementation
15506 * Rational number parsing complete.
15507 *
15508 * ***************** Version 12 *****************
15509 * User: Dashley1 Date: 10/27/00 Time: 4:03a
15510 * Updated in $/ACM Rational Approximation Paper And Algorithms/C-Language Implementation
15511 * gcd() functionality implemented and tested.
15512 *
15513 * ***************** Version 11 *****************
15514 * User: Dashley1 Date: 10/27/00 Time: 3:18a
15515 * Updated in $/ACM Rational Approximation Paper And Algorithms/C-Language Implementation
15516 * Division function checked in and tested. Safety check-in.
15517 *
15518 * ***************** Version 10 *****************
15519 * User: Dashley1 Date: 10/26/00 Time: 3:05a
15520 * Updated in $/ACM Rational Approximation Paper And Algorithms/C-Language Implementation
15521 * Safety check-in. Integer exponentiation complete.
15522 *
15523 * ***************** Version 9 *****************
15524 * User: Dashley1 Date: 10/25/00 Time: 3:28a
15525 * Updated in $/ACM Rational Approximation Paper And Algorithms/C-Language Implementation
15526 * Safety check-in.
15527 *
15528 * ***************** Version 8 *****************
15529 * User: Dashley1 Date: 10/23/00 Time: 7:18p
15530 * Updated in $/ACM Rational Approximation Paper And Algorithms/C-Language Implementation
15531 * Safety check-in.
15532 *
15533 * ***************** Version 7 *****************
15534 * User: Dashley1 Date: 10/23/00 Time: 12:01a
15535 * Updated in $/ACM Rational Approximation Paper And Algorithms/C-Language Implementation
15536 * Major progress, safety check-in.
15537 *
15538 * ***************** Version 6 *****************
15539 * User: Dashley1 Date: 10/20/00 Time: 3:30p
15540 * Updated in $/ACM Rational Approximation Paper And Algorithms/C-Language Implementation
15541 * Safety check-in.
15542 *
15543 * ***************** Version 5 *****************
15544 * User: Dashley1 Date: 10/20/00 Time: 5:12a
15545 * Updated in $/ACM Rational Approximation Paper And Algorithms/C-Language Implementation
15546 * Test of keyword expansion when keywords on same line.
15547 *
15548 * ***************** Version 4 *****************
15549 * User: Dashley1 Date: 10/20/00 Time: 4:35a
15550 * Updated in $/ACM Rational Approximation Paper And Algorithms/C-Language Implementation
15551 * Test checkin to test keyword expansion changes.
15552 *
15553 * ***************** Version 3 *****************
15554 * User: Dashley1 Date: 10/18/00 Time: 4:15a
15555 * Updated in $/ACM Rational Approximation Paper And Algorithms/C-Language Implementation
15556 * Second check-in to test VC embedding.
15557 *
15558 * ***************** Version 2 *****************
15559 * User: Dashley1 Date: 10/18/00 Time: 4:08a
15560 * Updated in $/ACM Rational Approximation Paper And Algorithms/C-Language Implementation
15561 * Check-in to test version embedding functionality.
15562 *
15563 * ***************** Version 1 *****************
15564 * User: Dashley1 Date: 10/18/00 Time: 3:58a
15565 * Created in $/ACM Rational Approximation Paper And Algorithms/C-Language Implementation
15566 * Initial check-in.
15567 */
15568
15569 /* End of file RAP_C.C */

dashley@gmail.com
ViewVC Help
Powered by ViewVC 1.1.25