diff options
author | markm <markm@FreeBSD.org> | 1996-10-20 08:49:26 +0000 |
---|---|---|
committer | markm <markm@FreeBSD.org> | 1996-10-20 08:49:26 +0000 |
commit | 6ec01646dc55b6fa688ed5906e0d52556d174da2 (patch) | |
tree | ecc4c214d76efa8e1b2fb33ac2f0aab18ea03ebf /contrib | |
download | FreeBSD-src-6ec01646dc55b6fa688ed5906e0d52556d174da2.zip FreeBSD-src-6ec01646dc55b6fa688ed5906e0d52556d174da2.tar.gz |
Clean import of libgmp 2.0.2, with only the non-x86 bits removed.
BMakefiles and other bits will follow.
Requested by: Andrey Chernov
Made world by: Chuck Robey
Diffstat (limited to 'contrib')
318 files changed, 48802 insertions, 0 deletions
diff --git a/contrib/libgmp/COPYING.LIB b/contrib/libgmp/COPYING.LIB new file mode 100644 index 0000000..92b8903 --- /dev/null +++ b/contrib/libgmp/COPYING.LIB @@ -0,0 +1,481 @@ + GNU LIBRARY GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1991 Free Software Foundation, Inc. + 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + +[This is the first released version of the library GPL. It is + numbered 2 because it goes with version 2 of the ordinary GPL.] + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +Licenses are intended to guarantee your freedom to share and change +free software--to make sure the software is free for all its users. + + This license, the Library General Public License, applies to some +specially designated Free Software Foundation software, and to any +other libraries whose authors decide to use it. You can use it for +your libraries, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish), that you receive source code or can get it +if you want it, that you can change the software or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if +you distribute copies of the library, or if you modify it. + + For example, if you distribute copies of the library, whether gratis +or for a fee, you must give the recipients all the rights that we gave +you. You must make sure that they, too, receive or can get the source +code. If you link a program with the library, you must provide +complete object files to the recipients so that they can relink them +with the library, after making changes to the library and recompiling +it. And you must show them these terms so they know their rights. + + Our method of protecting your rights has two steps: (1) copyright +the library, and (2) offer you this license which gives you legal +permission to copy, distribute and/or modify the library. + + Also, for each distributor's protection, we want to make certain +that everyone understands that there is no warranty for this free +library. If the library is modified by someone else and passed on, we +want its recipients to know that what they have is not the original +version, so that any problems introduced by others will not reflect on +the original authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that companies distributing free +software will individually obtain patent licenses, thus in effect +transforming the program into proprietary software. To prevent this, +we have made it clear that any patent must be licensed for everyone's +free use or not licensed at all. + + Most GNU software, including some libraries, is covered by the ordinary +GNU General Public License, which was designed for utility programs. This +license, the GNU Library General Public License, applies to certain +designated libraries. This license is quite different from the ordinary +one; be sure to read it in full, and don't assume that anything in it is +the same as in the ordinary license. + + The reason we have a separate public license for some libraries is that +they blur the distinction we usually make between modifying or adding to a +program and simply using it. Linking a program with a library, without +changing the library, is in some sense simply using the library, and is +analogous to running a utility program or application program. However, in +a textual and legal sense, the linked executable is a combined work, a +derivative of the original library, and the ordinary General Public License +treats it as such. + + Because of this blurred distinction, using the ordinary General +Public License for libraries did not effectively promote software +sharing, because most developers did not use the libraries. We +concluded that weaker conditions might promote sharing better. + + However, unrestricted linking of non-free programs would deprive the +users of those programs of all benefit from the free status of the +libraries themselves. This Library General Public License is intended to +permit developers of non-free programs to use free libraries, while +preserving your freedom as a user of such programs to change the free +libraries that are incorporated in them. (We have not seen how to achieve +this as regards changes in header files, but we have achieved it as regards +changes in the actual functions of the Library.) The hope is that this +will lead to faster development of free libraries. + + The precise terms and conditions for copying, distribution and +modification follow. Pay close attention to the difference between a +"work based on the library" and a "work that uses the library". The +former contains code derived from the library, while the latter only +works together with the library. + + Note that it is possible for a library to be covered by the ordinary +General Public License rather than by this special one. + + GNU LIBRARY GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License Agreement applies to any software library which +contains a notice placed by the copyright holder or other authorized +party saying it may be distributed under the terms of this Library +General Public License (also called "this License"). Each licensee is +addressed as "you". + + A "library" means a collection of software functions and/or data +prepared so as to be conveniently linked with application programs +(which use some of those functions and data) to form executables. + + The "Library", below, refers to any such software library or work +which has been distributed under these terms. A "work based on the +Library" means either the Library or any derivative work under +copyright law: that is to say, a work containing the Library or a +portion of it, either verbatim or with modifications and/or translated +straightforwardly into another language. (Hereinafter, translation is +included without limitation in the term "modification".) + + "Source code" for a work means the preferred form of the work for +making modifications to it. For a library, complete source code means +all the source code for all modules it contains, plus any associated +interface definition files, plus the scripts used to control compilation +and installation of the library. + + Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running a program using the Library is not restricted, and output from +such a program is covered only if its contents constitute a work based +on the Library (independent of the use of the Library in a tool for +writing it). Whether that is true depends on what the Library does +and what the program that uses the Library does. + + 1. You may copy and distribute verbatim copies of the Library's +complete source code as you receive it, in any medium, provided that +you conspicuously and appropriately publish on each copy an +appropriate copyright notice and disclaimer of warranty; keep intact +all the notices that refer to this License and to the absence of any +warranty; and distribute a copy of this License along with the +Library. + + You may charge a fee for the physical act of transferring a copy, +and you may at your option offer warranty protection in exchange for a +fee. + + 2. You may modify your copy or copies of the Library or any portion +of it, thus forming a work based on the Library, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) The modified work must itself be a software library. + + b) You must cause the files modified to carry prominent notices + stating that you changed the files and the date of any change. + + c) You must cause the whole of the work to be licensed at no + charge to all third parties under the terms of this License. + + d) If a facility in the modified Library refers to a function or a + table of data to be supplied by an application program that uses + the facility, other than as an argument passed when the facility + is invoked, then you must make a good faith effort to ensure that, + in the event an application does not supply such function or + table, the facility still operates, and performs whatever part of + its purpose remains meaningful. + + (For example, a function in a library to compute square roots has + a purpose that is entirely well-defined independent of the + application. Therefore, Subsection 2d requires that any + application-supplied function or table used by this function must + be optional: if the application does not supply it, the square + root function must still compute square roots.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Library, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Library, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote +it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Library. + +In addition, mere aggregation of another work not based on the Library +with the Library (or with a work based on the Library) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may opt to apply the terms of the ordinary GNU General Public +License instead of this License to a given copy of the Library. To do +this, you must alter all the notices that refer to this License, so +that they refer to the ordinary GNU General Public License, version 2, +instead of to this License. (If a newer version than version 2 of the +ordinary GNU General Public License has appeared, then you can specify +that version instead if you wish.) Do not make any other change in +these notices. + + Once this change is made in a given copy, it is irreversible for +that copy, so the ordinary GNU General Public License applies to all +subsequent copies and derivative works made from that copy. + + This option is useful when you wish to copy part of the code of +the Library into a program that is not a library. + + 4. You may copy and distribute the Library (or a portion or +derivative of it, under Section 2) in object code or executable form +under the terms of Sections 1 and 2 above provided that you accompany +it with the complete corresponding machine-readable source code, which +must be distributed under the terms of Sections 1 and 2 above on a +medium customarily used for software interchange. + + If distribution of object code is made by offering access to copy +from a designated place, then offering equivalent access to copy the +source code from the same place satisfies the requirement to +distribute the source code, even though third parties are not +compelled to copy the source along with the object code. + + 5. A program that contains no derivative of any portion of the +Library, but is designed to work with the Library by being compiled or +linked with it, is called a "work that uses the Library". Such a +work, in isolation, is not a derivative work of the Library, and +therefore falls outside the scope of this License. + + However, linking a "work that uses the Library" with the Library +creates an executable that is a derivative of the Library (because it +contains portions of the Library), rather than a "work that uses the +library". The executable is therefore covered by this License. +Section 6 states terms for distribution of such executables. + + When a "work that uses the Library" uses material from a header file +that is part of the Library, the object code for the work may be a +derivative work of the Library even though the source code is not. +Whether this is true is especially significant if the work can be +linked without the Library, or if the work is itself a library. The +threshold for this to be true is not precisely defined by law. + + If such an object file uses only numerical parameters, data +structure layouts and accessors, and small macros and small inline +functions (ten lines or less in length), then the use of the object +file is unrestricted, regardless of whether it is legally a derivative +work. (Executables containing this object code plus portions of the +Library will still fall under Section 6.) + + Otherwise, if the work is a derivative of the Library, you may +distribute the object code for the work under the terms of Section 6. +Any executables containing that work also fall under Section 6, +whether or not they are linked directly with the Library itself. + + 6. As an exception to the Sections above, you may also compile or +link a "work that uses the Library" with the Library to produce a +work containing portions of the Library, and distribute that work +under terms of your choice, provided that the terms permit +modification of the work for the customer's own use and reverse +engineering for debugging such modifications. + + You must give prominent notice with each copy of the work that the +Library is used in it and that the Library and its use are covered by +this License. You must supply a copy of this License. If the work +during execution displays copyright notices, you must include the +copyright notice for the Library among them, as well as a reference +directing the user to the copy of this License. Also, you must do one +of these things: + + a) Accompany the work with the complete corresponding + machine-readable source code for the Library including whatever + changes were used in the work (which must be distributed under + Sections 1 and 2 above); and, if the work is an executable linked + with the Library, with the complete machine-readable "work that + uses the Library", as object code and/or source code, so that the + user can modify the Library and then relink to produce a modified + executable containing the modified Library. (It is understood + that the user who changes the contents of definitions files in the + Library will not necessarily be able to recompile the application + to use the modified definitions.) + + b) Accompany the work with a written offer, valid for at + least three years, to give the same user the materials + specified in Subsection 6a, above, for a charge no more + than the cost of performing this distribution. + + c) If distribution of the work is made by offering access to copy + from a designated place, offer equivalent access to copy the above + specified materials from the same place. + + d) Verify that the user has already received a copy of these + materials or that you have already sent this user a copy. + + For an executable, the required form of the "work that uses the +Library" must include any data and utility programs needed for +reproducing the executable from it. However, as a special exception, +the source code distributed need not include anything that is normally +distributed (in either source or binary form) with the major +components (compiler, kernel, and so on) of the operating system on +which the executable runs, unless that component itself accompanies +the executable. + + It may happen that this requirement contradicts the license +restrictions of other proprietary libraries that do not normally +accompany the operating system. Such a contradiction means you cannot +use both them and the Library together in an executable that you +distribute. + + 7. You may place library facilities that are a work based on the +Library side-by-side in a single library together with other library +facilities not covered by this License, and distribute such a combined +library, provided that the separate distribution of the work based on +the Library and of the other library facilities is otherwise +permitted, and provided that you do these two things: + + a) Accompany the combined library with a copy of the same work + based on the Library, uncombined with any other library + facilities. This must be distributed under the terms of the + Sections above. + + b) Give prominent notice with the combined library of the fact + that part of it is a work based on the Library, and explaining + where to find the accompanying uncombined form of the same work. + + 8. You may not copy, modify, sublicense, link with, or distribute +the Library except as expressly provided under this License. Any +attempt otherwise to copy, modify, sublicense, link with, or +distribute the Library is void, and will automatically terminate your +rights under this License. However, parties who have received copies, +or rights, from you under this License will not have their licenses +terminated so long as such parties remain in full compliance. + + 9. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Library or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Library (or any work based on the +Library), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Library or works based on it. + + 10. Each time you redistribute the Library (or any work based on the +Library), the recipient automatically receives a license from the +original licensor to copy, distribute, link with or modify the Library +subject to these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 11. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Library at all. For example, if a patent +license would not permit royalty-free redistribution of the Library by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Library. + +If any portion of this section is held invalid or unenforceable under any +particular circumstance, the balance of the section is intended to apply, +and the section as a whole is intended to apply in other circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 12. If the distribution and/or use of the Library is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Library under this License may add +an explicit geographical distribution limitation excluding those countries, +so that distribution is permitted only in or among countries not thus +excluded. In such case, this License incorporates the limitation as if +written in the body of this License. + + 13. The Free Software Foundation may publish revised and/or new +versions of the Library General Public License from time to time. +Such new versions will be similar in spirit to the present version, +but may differ in detail to address new problems or concerns. + +Each version is given a distinguishing version number. If the Library +specifies a version number of this License which applies to it and +"any later version", you have the option of following the terms and +conditions either of that version or of any later version published by +the Free Software Foundation. If the Library does not specify a +license version number, you may choose any version ever published by +the Free Software Foundation. + + 14. If you wish to incorporate parts of the Library into other free +programs whose distribution conditions are incompatible with these, +write to the author to ask for permission. For software which is +copyrighted by the Free Software Foundation, write to the Free +Software Foundation; we sometimes make exceptions for this. Our +decision will be guided by the two goals of preserving the free status +of all derivatives of our free software and of promoting the sharing +and reuse of software generally. + + NO WARRANTY + + 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO +WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. +EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR +OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY +KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE +LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME +THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + + 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN +WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY +AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU +FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR +CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE +LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING +RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A +FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF +SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH +DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Libraries + + If you develop a new library, and you want it to be of the greatest +possible use to the public, we recommend making it free software that +everyone can redistribute and change. You can do so by permitting +redistribution under these terms (or, alternatively, under the terms of the +ordinary General Public License). + + To apply these terms, attach the following notices to the library. It is +safest to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least the +"copyright" line and a pointer to where the full notice is found. + + <one line to give the library's name and a brief idea of what it does.> + Copyright (C) <year> <name of author> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +Also add information on how to contact you by electronic and paper mail. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the library, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the + library `Frob' (a library for tweaking knobs) written by James Random Hacker. + + <signature of Ty Coon>, 1 April 1990 + Ty Coon, President of Vice + +That's all there is to it! diff --git a/contrib/libgmp/ChangeLog b/contrib/libgmp/ChangeLog new file mode 100644 index 0000000..1c29f1e --- /dev/null +++ b/contrib/libgmp/ChangeLog @@ -0,0 +1,3193 @@ +Thu Jun 6 19:00:53 1996 Torbjorn Granlund <tege@noisy.tmg.se> + + * Version 2.0.2 released. + + * install.sh: New file. + * Makefile.in (INSTALL): Use install.sh. + (install-normal): New name for target `install'. + (install): New dummy target. + + * mpz/pow_ui.c: Swap tests for (e == 0) and (bsize == 0). + * mpz/ui_pow_ui.c: Swap tests for (e == 0) and (blimb == 0). + + * config/mt-linux (AR_FLAGS): New file. + * configure.in: Use config/mt-linux for all linux systems. + +Tue Jun 4 03:42:18 1996 Torbjorn Granlund <tege@noisy.tmg.se> + + * Version 2.0.1 released. + + * mpf/tests/ref.c: Cast result of TMP_ALLOC to the right pointer type. + + * extract-double.c: Test _GMP_IEEE_FLOATS with #if, not plain if. + + * insert-double.c: Don't #include stdlib.h. + + * gmp-impl.h (union ieee_double_extract): Test sparc and __sparc. + Do not test __sparc__. + + * mpf/reldiff.c: Change declaration to work around irix5 compiler bug. + * mpq/equal.c: Likewise. + + * mpn/generic/gcd.c: Delete spurious comma at end of enumeration. + + * mpn/generic/gcdext.c: Add K&R declaration syntax. + * stack-alloc.h: Likewise. + * insert-double.c: Likewise. + * extract-double.c: Likewise. + * mpf/tests/reuse.c: Likewise. + * mpz/tests/reuse.c: Likewise. + * mpf/tests/t-sub.c: Likewise. + * mpf/tests/t-add.c: Likewise. + * mpf/tests/t-muldiv.c: Likewise. + * mpf/tests/t-conv.c: Likewise. + * mpf/tests/ref.c: Likewise. + + * mpn/config/t-oldgas: Renamed from t-freebsd. + * mpn/configure.in: Use t-oldgas for freebsd, netbsd, and some linux + configurations. + + * mpn/powerpc32/mul_1.s: Really clear cy before entering loop. + * mpn/powerpc32/*.s: Fix power/powerpc syntax issues. + + * mpn/config/t-ppc-aix: New file. + * mpn/configure.in: Use t-ppc-aix for powerpc like t-pwr-aix for power. + +Wed May 29 02:07:31 1996 Torbjorn Granlund <tege@noisy.tmg.se> + + * gmp.h (mp_bits_per_limb): Change qualifier from `const' to + __gmp_const. + + * gmp.h (mpf_init_set_str): Add `const' qualifier for 2nd parameter. + * mpf/iset_str.c: Likewise. + +Mon May 27 00:15:58 1996 Torbjorn Granlund <tege@noisy.tmg.se> + + * gmp-impl.h: Declare __gmp_extract_double. + + * mpz/set_q.c: Delete unused variables. + + * gmp.h (mpq_equal): Declare. + + * mpf/eq.c: mpf_cmp2 -> mpf_eq. + +Fri May 24 03:20:44 1996 Torbjorn Granlund <tege@noisy.tmg.se> + + * mpz/iset_d.c: Don't include <math.h>. + + * insert-double.c (__gmp_scale2): New name for scal2. + * mpz/get_d.c: Corresponding change. + * mpf/get_d.c: Likewise. + * mpq/get_d.c: Likewise. + * gmp-impl.h: Declare __gmp_scale2. + + * mpn/generic/scan0.c: Clarify comment. + + * mpz/set_q.c: New file. + * Makefile.in: Compile it. + * make.bat: Likewise. + * gmp.h: Declare mpz_set_q. + + * insert-double.c: New file. + * Makefile.in: Compile it. + * make.bat: Likewise. + + * mpz/get_d.c: New file. + * mpz/Makefile.in: Compile it. + * make.bat: Likewise. + * gmp.h: Declare mpz_get_d. + + * mpf/get_d.c: New file. + * mpf/Makefile.in: Compile it. + * make.bat: Likewise. + * gmp.h: Declare mpf_get_d. + + * make.bat: Compile things in alphabetical order. + + * gmp-impl.h (MP_BASE_AS_DOUBLE): New #define. + (LIMBS_PER_DOUBLE): New #define. + + * extract-double.c: New file. + * Makefile.in: Compile it. + * make.bat: Likewise. + * mpz/set_d.c: Rewrite to use __gmp_extract_double. + * mpf/set_d.c: Likewise. + + * mpn/configure.in: Use t-pwr-aix also for aix 3.2.4 and up. + +Wed May 22 02:48:35 1996 Torbjorn Granlund <tege@noisy.tmg.se> + + * gmp-impl.h: Rework code for defining ieee_double_extract. + (IEEE_DOUBLE_BIG_ENDIAN): Macro removed. + (_GMP_IEEE_FLOATS): New macro. + * mpn/vax/gmp-mparam.h: Delete. + + * mpn/config/t-pwr-aix: New file. + * mpn/configure.in: Use t-pwr-aix for aix 4 and later. + +Mon May 20 16:30:31 1996 Torbjorn Granlund <tege@noisy.tmg.se> + + * gmp.h: In code for setting _GMP_H_HAVE_FILE, test more symbols. + + * mpf/tests/t-add.c (oo): Add some `l' printf modifiers. + * mpf/tests/t-sub.c (oo): Likewise. + * mpf/tests/t-conv.c (oo): Likewise. + * mpf/tests/t-sqrt.c (oo): Likewise. + + * mpz/tests/t-mul.c (_mpn_mul_classic): Remove unused variables. + + * mpn/{pyr,i960,clipper}/*.s: Add missing copyright headers. + +Fri May 17 02:24:43 1996 Torbjorn Granlund <tege@noisy.tmg.se> + + * mpz/set_d.c: Call _mpz_realloc. + + * mpq/set_z.c: New file. + * mpq/Makefile.in: Compile it. + * make.bat: Likewise. + * gmp.h: Declare mpq_set_z. + + * mp?/Makefile.in (libmp?.a): Depend on Makefile, not Makefile.in. + * mpf/Makefile.in (test): Delete spurious target. + * mpq/Makefile.in (test): Likewise. + + * mpf/out_str.c: Use `e' to separate exponent when base <= 10. + + * mpn/configure.in: Treat ultrasparc just like sparc v8, + until 64-bit compilers are ready. + + * mpf/set_d.c: Make it work for 64-bit machines. + +Thu May 16 20:53:57 1996 Torbjorn Granlund <tege@noisy.tmg.se> + + * gmp-impl.h: Set IEEE_DOUBLE_BIG_ENDIAN to 0 for little-endian + machines. + * mpn/x86/gmp-mparam.h: Delete file. + + * configure.in: Treat microsparc like sparc8. + + * urandom.h: Test __alpha instead of __alpha__, since the former + is the standard symbol. + * mpn/generic/random2.c: Likewise. + * mpf/random2.c: Likewise. + +Tue May 14 13:42:39 1996 Torbjorn Granlund (tege@tiny.tmg.se) + + * mpz/set_f.c: New file. + * mpz/Makefile.in: Compile it. + * gmp.h: Declare mpz_set_f. + + * mpf/set_q.c: Simplify expression in rsize == nsize if-then-else arms. + +Tue May 14 13:03:07 1996 Torbjorn Granlund (tege@tiny.tmg.se) + + * make.bat: Add all new files. + +Sun May 12 22:24:36 1996 Torbjorn Granlund <tege@noisy.tmg.se> + + * mpf/set_z.c: New file. + * mpf/Makefile.in: Compile it. + * gmp.h: Declare mpf_set_z. + +Sat May 11 19:26:25 1996 Torbjorn Granlund <tege@noisy.tmg.se> + + * gmp.h: Declare mpf_set_q. + + * mpf/set_q.c: Compute prec-1 limbs in mpn_divrem call. + +Fri May 10 17:37:38 1996 Torbjorn Granlund <tege@noisy.tmg.se> + + * mpf/set_q.c: New file. + * mpf/Makefile.in: Compile it. + + * config.sub: Recognize sparc8. + +Wed May 8 09:19:11 1996 Torbjorn Granlund <tege@noisy.tmg.se> + + * mpf/tests/t-dm2exp.c: New file. + + * mpf/tests/t-add.c: Correct header comment. + * mpf/tests/t-sub.c: Likewise. + * mpf/tests/t-sqrt.c: Likewise. + + * mpf/div.c: Misc variable name cleanups. + * mpf/div_ui.c: Base more closely on mpf/div.c. + * mpf/ui_div.c: Likewise. + + * mpz/tests/Makefile.in (check): Depend on Makefile. + * mpq/tests/Makefile.in (check): Likewise. + * mpf/tests/Makefile.in (check): Likewise. + + * mpf/tests/t-muldiv.c: New file. + * mpf/tests/Makefile.in: Compile and run `t-muldiv'. + (t-ref.o): Delete spurious rule. + + * mpf/sqrt.c: Properly detect negative input operand. + + * mpf/sqrt_ui.c: Delete spurious header comment. + * mpf/sqrt.c: Likewise. + * mpz/sqrt.c: Likewise. + + * mpz/tests/reuse.c (main): Read `reps' from command line. + + * mpf/tests/reuse.c: New file. + * mpf/tests/Makefile.in: Compile and run `reuse'. + + * mpf/mul_ui.c: Disable code for removing low zero limbs. + + * mpf/div.c: Fix condition for when vp and qp overlaps. + + * mpf/add_ui.c: When sum equals u, copy up to prec+1 limbs. + + * mpf/out_str.c: Don't output '\n' after exponent. + + * mpf/add_ui.c: New special case for when U is completely cancelled. + +Wed Apr 24 05:33:28 1996 Torbjorn Granlund <tege@noisy.tmg.se> + + * Version 2.0 released. + + * All files: Upfate FSF's address. + + * Makefile.in (gmp_toc.html): New name for gmp.html. + (TAGS): Depend on force. + + * mpf/tests/t-conv.c: Pass -base to mpf_set_str. + +Sat Apr 20 03:54:06 1996 Torbjorn Granlund <tege@noisy.tmg.se> + + * Makefile.in (ps): New target, depend on gmp.ps. + +Fri Apr 19 14:03:15 1996 Torbjorn Granlund <tege@noisy.tmg.se> + + * mpf/out_str.c: Print `@' before exponent, not `e'. + + * make.bat: Update from Makefiles. + +Thu Apr 18 01:22:05 1996 Torbjorn Granlund <tege@noisy.tmg.se> + + * mpf/set_str.c: If parameter `base' is negative, expect exponent + to be decimal, otherwise in the same base as the mantissa. + +Wed Apr 17 17:28:36 1996 Torbjorn Granlund <tege@noisy.tmg.se> + + * mpf/set_dfl_prec.c: Don't return anything. + * gmp.h: Corresponding changes. + + * mpf/set_dfl_prec.c: Use `unsigned long int' for bit counts. + * mpf/init2.c: Likewise. + * mpf/get_prc.c: Likewise. + * mpf/set_prc.c: Likewise. + * mpf/set_prc_raw.c: Likewise. + * mpz/popcount.c: Likewise. + * mpz/hamdist.c: Likewise. + * mpz/scan1.c: Likewise. + * mpz/scan0.c: Likewise. + * mpn/generic/popcount.c: Likewise. + * mpn/generic/hamdist.c: Likewise. + * mpn/generic/scan1.c: Likewise. + * mpn/generic/scan0.c: Likewise. + * gmp.h: Likewise. + + * mpf/eq.c: New file, based on mpf/diff.c. + * mpf/diff.c: Delete. + * mpf/Makefile.in: Corresponding changes. + * gmp.h: Likewise. + + * mpf/reldiff.c: New file. + * mpf/Makefile.in: Compile it. + * gmp.h: Declare mpf_reldiff. + + * mpz/iset_d.c: New file. + * mpz/Makefile.in: Compile it. + * gmp.h: Declare mpz_init_set_d. + +Tue Apr 16 16:28:31 1996 Torbjorn Granlund <tege@noisy.tmg.se> + + * Makefile.in (gmp.html): Pass -acc to texi2html. + +Mon Apr 15 16:20:24 1996 Torbjorn Granlund <tege@noisy.tmg.se> + + * mpf/set_str.c: Switch off code for defaulting the base from the + leading characters. + + * gmp.h (mp?_sign): Delete. + (mp?_sgn): New macros. + +Fri Apr 12 17:23:33 1996 Torbjorn Granlund <tege@noisy.tmg.se> + + * Makefile.in (gmp.dvi): Delete tmp.* at end of rule. + +Wed Apr 10 22:52:02 1996 Torbjorn Granlund (tege@tiny.tmg.se) + + * mpf/random2.c: Change of `exp' param, mp_size_t => mp_exp_t. + * gmp.h: Corresponding change. + + * gmp.h (mp_bits_per_limb): Make it const. + +Sat Mar 30 01:20:23 1996 Torbjorn Granlund <tege@noisy.tmg.se> + + * configure.in: Re-enable recognition of with_gcc. + + * mpf/Makefile.in (.c.o): Pass XCFLAGS. + * mpn/Makefile.in (.c.o): Likewise. + * mpz/Makefile.in (.c.o): Likewise. + * mpq/Makefile.in (.c.o): Likewise. + * mpbsd/Makefile.in (.c.o): Likewise. + * mpf/tests/Makefile.in (.c.o): Likewise. + * mpz/tests/Makefile.in (.c.o): Likewise. + * mpq/tests/Makefile.in (.c.o): Likewise. + + * Makefile.in (XCFLAGS): Default to empty. + (FLAGS_TO_PASS): Pass on XCFLAGS. + (.c.o): Pass XCFLAGS. + + * config/mt-m88110 (XCFLAGS): Define instead of CC. + * config/mt-sprc8-gcc (XCFLAGS): Likewise. + * config/mt-supspc-gcc (XCFLAGS): Likewise. + + * configure: Don't default CC to "gcc -O2" is -with-gcc=no was + specified. + +Mon Mar 25 01:07:54 1996 Torbjorn Granlund <tege@noisy.tmg.se> + + * urandom.h: Test for __SVR4 in addition to __svr4__. + + * mp_bpl.c (mp_bits_per_limb): Declare as `const'. + + * Makefile.in (CFLAGS): `-O2' => `-O'. + * mpn/Makefile.in (CFLAGS): Likewise. + + * gmp-impl.h: Get rid of obsolete field access macros. + + * mpn/mp_bases.c (__mp_bases): 1e39 => 1e38 to work around Solaris + cc compiler bug. + + * gmp.h (__MPN): Make it work also for non-ANSI compilers. + +Thu Mar 21 01:07:54 1996 Torbjorn Granlund <tege@noisy.tmg.se> + + * mpf/sub.c: New special case for ediff <= 1 before generic code. + Simplify generic code for ediff == 0. + Rename uexp => exp. + +Mon Mar 11 18:24:57 1996 Torbjorn Granlund <tege@noisy.tmg.se> + + * mpf/tests/*.c: Use ref_mpf_sub for error calculation. + * mpf/tests/Makefile.in: Link ref.o to all executables. + + * mpf/tests/t-sub.c: Make u = v + 1 with 50% probability. + +Sun Mar 10 21:03:17 1996 Torbjorn Granlund (tege@tiny.tmg.se) + + * mpf/get_str.c: In digit development loop for fractions, change + loop condition from `<' to `<='. + +Thu Mar 7 04:58:11 1996 Torbjorn Granlund <tege@tiny.tmg.se> + + * mpn/mp_bases.c (__mp_bases): 1e100 => 1e39 to avoid overflow warning. + +Wed Mar 6 01:10:42 1996 Torbjorn Granlund <tege@noisy.tmg.se> + + * mpf/tests/t-sqrt.c: New file. + * mpf/tests/Makefile.in: Corresponding changes. + + * mpf/sqrt.c: Special case for square root of zero. + + * mpq/add.c: Clean up variable names. + * mpq/sub.c: Update from mpq/add.c. + + * mpz/divexact.c: abs => ABS. + * mpz/gcd.c: Likewise. Rewrite final fixup code, to decrease + allocation. Misc cleanups. + +Tue Mar 5 22:24:56 1996 Torbjorn Granlund <tege@tmg.se> + + * mpn/configure.in: Recognize linuxoldld as a synonym for linuxaout. + + * gmp.h (mpn_add, mpn_add_1, mpn_sub, mpn_sub_1): Add prototypes. + + * mpn/configure.in: Use t-freebsd also for netbsd. + +Mon Mar 4 15:13:28 1996 Torbjorn Granlund <tege@tmg.se> + + * mpq/Makefile.in (cmp.o): Depend on longlong.h. + + * mpq/equal.c: New file. + * mpq/Makefile.in: Corresponding changes. + + * mpf/tests/t-add.c: New file. + * mpf/tests/t-sub.c: Renamed from t-addsub.c. + * mpf/tests/ref.c: New file. + * mpf/tests/Makefile.in: Corresponding changes. + + * gmp-impl.h (SIZ, ABSIZ, PTR, EXP, PREC, ALLOC): New #defines. + +Sun Mar 3 07:45:46 1996 Torbjorn Granlund <tege@tmg.se> + + * mpf/set_str.c: In exponentialization code, allocate 3 extra + limbs, not just 2. + + * mpf/get_str.c: Allocate sufficient space for tstr. + When calculating exp_in_base, round result down. + + * mpf/tests/t-conv.c: New file. + * mpf/tests/Makefile.in: Corresponding changes. + + * mp_bpl.c: New file. + * gmp.h: Declare it. + * Makefile.in: Corresponding changes. + +Sat Mar 2 06:27:56 1996 Torbjorn Granlund <tege@tmg.se> + + * mpf/set_prc_raw.c: New file. + * mpf/set_prc.c: Renamed from set_prec.c. + * mpf/get_prc.c: New file. + * mpf/Makefile.in: Corresponding changes. + * gmp.h: Declare new functions. + + * mpn/generic/gcdext.c: Add copyright header. + +Fri Mar 1 01:22:24 1996 Torbjorn Granlund <tege@tmg.se> + + * mpn/configure.in: For ppc601, search "power" before "powerpc32". + + * mp?/Makefile.in (AR_FLAGS): New variable. + (libmp?.a): Use it. + + * make.bat: New file. + * mpn/msdos: New directory. + * mpn/msdos/asm-syntax.h: New file. + + * mpn/Makefile.in (distclean maintainer-clean): Delete asm-syntax.h. + + * config.sub: Recognize [ctj]90-cray. + + * mpn/configure.in: Recognize [ctj]90-cray-unicos*. + + * mpn/generic/gcdext.c: Don't use alloca directly, use TMP_* macros. + + * mpn/generic/gcd.c: Split increment from use of USIZE to avoid + undefined behaviour. + +Thu Feb 29 04:11:24 1996 Torbjorn Granlund <tege@tmg.se> + + * Makefile.in (install-info-files): Update for new install-info + behaviour. + + * mpn/power/add_n.s: Rewrite. + * mpn/power/sub_n.s: Rewrite. + +Wed Feb 28 01:34:30 1996 Torbjorn Granlund <tege@tmg.se> + + * mpz/pow_ui.c: Compute allocation more aggressively for small bases. + * mpz/ui_pow_ui.c: Likewise. + + * mpn/mp_bases.c (__mp_bases): Put huge value in 2nd field for index 1. + + * mpn/generic/sqrtrem.c: sizeof (mp_limb_t) => BYTES_PER_MP_LIMB. + * mpn/generic/gcd.c: Likewise. + (SIGN_BIT): Compute differently. + +Mon Feb 26 00:07:36 1996 Torbjorn Granlund <tege@tmg.se> + + * All files: mp_limb => mp_limb_t, mp_limb_signed => mp_limb_signed_t. + + * Makefile.in (install, install-bsdmp, install-info-files): Depend + on installdirs. chmod all installed files. + +Sun Feb 25 01:47:41 1996 Torbjorn Granlund <tege@tmg.se> + + * mpbsd/configure.in: Delete debugging code. + + * All Makefile.in: Update clean targets. + + * Makefile.in (AR_FLAGS): New variable. + (libgmp.a): Use it. + (libmp.a): Likewise. + + * VERSION: Delete file. + + * Makefile.in (installdirs): New target. + * mkinstalldirs: New file (from the texinfo package). + + * Makefile.in (INSTALL, INSTALL_DATA, INSTALL_PROGRAM): New variables. + (MAKEINFO, MAKEINFOFLAGS, TEXI2DVI): New variables. + (install-info): New target. + (install, install-bsdmp): Depend on install-info. + ($(srcdir)/gmp.info): Changed from plain gmp.info; put info files + into source directory. + (distclean, mostlyclean): New targets. + (maintainer-clean): New name for realclean. + (uninstall): New target. + (TAGS): New target. + (info, dvi): New targets. + (.PHONY): Assign. + + * Makefile.in (install, install-bsdmp): Use INSTALL_DATA. + + * mp{n,z,f,bsd}/move-if-change: Delete. + + * mpbsd/Makefile.in (stamp-stddefh): Delete target. + + * Makefile.in (.c.o): Pass CFLAGS last. + * mpbsd/Makefile.in (.c.o): Likewise. + * mpf/Makefile.in (.c.o): Likewise. + * mpq/Makefile.in (.c.o): Likewise. + * mpz/Makefile.in (.c.o): Likewise. + * mpn/Makefile.in (.c.o): Likewise. + (.S.o): Likewise. + + * memory.c: Change allocation error message. + + * Makefile.in (install): Prefix gmp.h with $(srcdir). + (install-bsdmp): Prefix mp.h with $(srcdir). + + * mp{n,z,f,bsd}/{configure,config.sub}: Delete. + + * Makefile.in (gmp.dvi): Set TEXINPUTS also for 2nd tex invocation + (install targets): Install gmp.info-N. + +Sat Feb 24 03:36:52 1996 Torbjorn Granlund <tege@tmg.se> + + * mpf/get_str.c: Fix typo. + + * mpz/legendre.c: Clarify expression with extra parens. + + * version.c (gmp_version): Not static. + + * mpf/iset_str.c: Properly return error code. + + * mpf/add.c: Delete unused variables. + * mpf/inp_str.c: Likewise. + * mpq/get_d.c: Likewise. + + * mpn/generic/dump.c: #include <stdio.h>. + * mpf/dump.c: Likewise. + * mpf/set_str.c: #include <ctype.h>. + (strtol): Declare. + + * gmp.h: mpn_sqrt => mpn_sqrtrem. + + * Makefile.in (clean, realclean): Clean in mpbsd. + (check): Test in mpf. + + * mpf/Makefile.in (clean): Clean in tests. + * mpq/Makefile.in (clean): Clean in tests. + + * mpf/tests/Makefile.in: New file. + * mpf/tests/configure.in: New file. + * mpf/tests/t-addsub.c: New file. + + * mpf/sub_ui.c: Simply call mpf_sub for now. + + * mpf/sub.c: Increase prec by 1. + * mpf/ui_sub.c: Likewise. + +Fri Feb 23 00:59:54 1996 Torbjorn Granlund <tege@tmg.se> + + * mpf/ui_sub.c: Fix typos. + + * mpf/get_str.c: When allocating space for tmp, allow for an extra + limb. In code for fraction conversion, add special case for bases + that are a power of 2. + + * mpf/out_str.c: Output leading "0.". + Default base to 10, before computing string allocation. + + * mpf/get_str.c: Make variables for string size have type size_t. + * gmp.h: Corresponding change. + + * mpf/random2.c: Allow creation of prec+1 large mantissas. + + * mpf/add_ui.c: Don't abort if u < 0; special case for u <= 0. + Fix typo in MPN_COPY offset. + * mpf/sub_ui.c: Analogous changes. + + * mpf/set_prec.c: Rewrite. + + * mpf/init2.c: Compute precision as in set_prec.c. + + * mpf/div_2exp.c: Special case for u == 0. + * mpf/mul_2exp.c: Likewise. Write r->_mp_size always. + + * mpf/sqrt_ui.c: mpn_sqrt => mpn_sqrtrem. + * mpf/sqrt.c: Likewise. When computing new exponent, round quotient + towards -infinity. + + * mpf/add.c: Fix typos. + * mpf/sub.c: Fix typos. + +Thu Feb 22 00:24:48 1996 Torbjorn Granlund <tege@tmg.se> + + * mpz/Makefile.in (stamp-stddefh): Delete target. + (test): Delete target. + * Makefile.in (stamp-stddefh): Delete target. + (cre-stddefh.o): Delete target. + (gmp.dvi): Set TEXINPUTS before invoking tex. + + * cre-stddefh.c: Delete. + + * mpz/sqrt.c: Fix typo. + + * mpz/powm.c: Special case for mod == 0. + * mpz/powm_ui.c: Likewise. + + * mpz/get_si.c: Handle -0x80000000 correctly. + + * mpz/inp_str.c: Now retutns size_t. + Make it return number of bytes read or error indication. + * mpf/inp_str.c: Likewise. + + * mpz/out_raw.c: Replace by mpz/out_binary.c, with modifications. + * mpz/inp_raw.c: Rewrite, using mpz/inp_binary as a base. + * mpz/inp_binary.c: Delete. + + * mpn/Makefile.in (XCFLAGS): Remove variable. + (.c.o): Don't pass XCFLAGS. + (SFLAGS): Set to nothing. + (.S.o): Pass SFLAGS, not XCFLAGS. + + * mpn/config/t-freebsd (SFLAGS): New name for XCFLAGS. + + * mpf/out_str.c: Make return number of bytes written or error + indication. + * mpz/out_str.c: Likewise. + * gmp.h: Corresponding changes. + + * gmp.h (__mpz_struct): mp_size_t => int. + (__mpq_struct): Likewise. + (__mpf_struct): Likewise. + (mp_size_t): int => long int. + + * mpn/cray: New directory. + * mpn/cray/gmp-mparam.h: New file. + * mpn/configure.in: Recognize cray variants. + + * Makefile.in: Set defaults for prefix, libdir, etc. + (install): New target. + (install-bsdmp): New target. + (gmp.html): New target. + + * stack-alloc.c (__tmp_alloc): Cast void ptrs to char * in comparison. + +Wed Feb 21 04:35:02 1996 Torbjorn Granlund <tege@tmg.se> + + * gmp.h: Sort mpn declarations. + (mpn_gcdext): Add declaration. + + * mpn/generic/divrem_1.c: New file. + * mpn/Makefile.in (divrem_1.o): New rule. + * configure.in (functions): Add divrem_1. + + * mpn/generic/divmod.c: Delete file. + * mpn/configure.in (functions): Delete divmod. + * Makefile.in (divmod.o): Delete rule. + * gmp.h (mpn_divmod): New #define. + + * gmp.h (mpn_next_bit_set): Delete spurious declaration. + + * mpn/generic/divrem.c (default case): In code assigning + most_significant_q_limb, move reassignment of n0 into if statement. + + * gmp.h (mpf_inp_str): Fix typo. + (mpf_out_str): Make prototype match reality. + * mpf/inp_str.c: New file. + * mpf/out_str.c: New file. + * mpf/Makefile.in: Compile new files. + + * mpn/Makefile.in (dump.o): Fix dependency path. + (inlines.o): Likewise. + + * mpn/configure.in: Make m68060 be the same as m68000. Clean up + m68k configs. + +Tue Feb 20 01:35:11 1996 Torbjorn Granlund <tege@tmg.se> + + * mpn/generic/sqrtrem.c: Renamed from sqrt. + * mpn/configure.in (functions): Corresponding change. + * mpn/Makefile.in: Likewise. + * mpz/sqrtrem.c: Likewise. + * mpz/sqrt.c: Likewise. + * mpn/generic/perfsqr.c: Likewise. + + * Makefile.in (clean): Also remove libmp.a. + Don't compile cre-conv-tab.c or mp_bases.c. + cre-conv-tab.c: Delete file. + (gmp.ps): New rule. + + * mpn/mp_bases.c: New file. + * mpn/Makefile.in: Compile mp_bases.c. + + * mpz/set_str.c: Skip initial whitespace. + * mpf/set_str.c: Likewise. + * mpbsd/xtom.c: Likewise. + + * gmp.h: Add missing mpz declarations. + Delete all formal parameter names from declarations. + + * mpn/Makefile.in: Add dependencies for .c files. + + * Makefile.in (check): Write recursive make calls separately, not as + a loop. + (FLAGS_TO_PASS): New variable. Use it for most recursive makes. + +Mon Feb 19 01:02:20 1996 Torbjorn Granlund <tege@tmg.se> + + * mpn/Makefile.in (.S.o): Pipe cpp output to grep in order to delete + lines starting with #. + (CPP): Set to $(CC) -E to avoid gcc dependency. + + * mpn/m68k/syntax.h (moveql): Define to moveq for MIT_SYNTAX. + + * mpn/hppa/hppa1_1/pa7100/addmul_1.S: Fix typo in s1_ptr alignment + code. + * mpn/hppa/hppa1_1/pa7100/submul_1.S: Likewise. + + * gmp.h: Fix typos in #defines of recently added mpn functions. + + * mpz/inp_str.c: Skip all whitespace, not just plain space. + * mpbsd/min.c: Likewise. + + * mpn/configure.in (functions): Add gcdext. + * mpn/generic/gcdext.c: New file. + + * mpz/legendre.c: mpz_div_2exp => mpz_tdiv_q_2exp. + + * gmp.h: Surround mpn declarations with extern "C" { ... }. + + * Makefile.in (check): New target. + + * mpq/get_d.c: Update comments. Use rsize instead of dsize + N_QLIMBS + when possible. Add special case for nsize == 0. + + * gmp.h (mpq_get_d): Add declaration. + (mpq_canonicalize): Likewise. + (mpq_cmp_ui): Likewise. + (mpf_diff): Likewise. + (mpf_ui_sub): Likewise. + (mpf_set_prec): Likewise. + (mpf_random2): Likewise. + + * gmp.h (mpz_cmp_ui): New #define. + (mpz_cmp_si): New #define. + (mpq_cmp_ui): New #define. + (mpz_sign): New #define. + (mpq_sign): New #define. + (mpf_sign): New #define. + (mpq_numref): New #define. + (mpq_denref): New #define. + + * mpq/set_z.c: File deleted. + * mpq/Makefile.in: Corresponding changes. + +Sun Feb 18 01:34:47 1996 Torbjorn Granlund <tege@tmg.se> + + * mpbsd/sdiv.c: Use _mp_realloc, not _mpz_realloc. + + * mpz/inp_binary.c: Default stream to stdin. + * mpz/inp_str.c: Likewise. + * mpz/inp_raw.c: Likewise. + * mpz/out_binary.c: Default stream to stdout. + * mpz/out_raw.c: Likewise. + * mpz/out_str.c: Likewise. + + * mpbsd/realloc.c: New file. + * mpbsd/Makefile.in: Corresponding changes. + + * mpbsd/min.c: Rewrite (base on mpz/inp_str.c). + * mpbsd/mtox.c: Rewrite (base on mpz/get_str.c). + + * mpbsd/mout.c: Rewrite (base on mpz/out_str) but make it output + spaces in each 10th position. + * mpbsd/xtom.c: Rewrite (base on mpz/set_str). + + * mpq/tests/Makefile.in (st-cmp): New file. + * mpq/tests/configure.in (srcname): New file. + + * mpz/tests/configure.in (srcname): Fix typo. + + * mpq/cmp.c: Add check using number of significant bits, to avoid + general multiplication. + +Sat Feb 17 11:58:30 1996 Torbjorn Granlund <tege@tmg.se> + + * mpq/cmp_ui.c: Store cy_limb after the mpn_mul_1 calls. + + * mpq/tests: New directory. + * mpq/tests/t-cmp.c: New file. + * mpq/tests/t-cmp_ui.c: New file. + + * mpz/tests/dive.c (main): Generate zero numerator. + (get_random_size) : Delete. + + * mpz/divexact.c: Add special case for 0/x. + + * gmp.h (mpz_mod): Add declaration. + +Fri Feb 16 18:18:39 1996 Andreas Schwab <schwab@informatik.uni-dortmund.de> + + * mpn/m68k/*: Rewrite code not to use the INSN macros. + (L): New macro to properly prefix local labels for ELF. + +Fri Feb 16 00:20:56 1996 Torbjorn Granlund <tege@tmg.se> + + * gmp-impl.h (ieee_double_extract): Use plain `unsigned int' for + fields. + * mpn/generic/inlines.c (_FORCE_INLINES): New #define. Delete + conditional __GNUC__. + * gmp.h (mpn_add, mpn_sub, mpn_add_1, mpn_sub_1): + Only define these if __GNUC__ || _FORCE_INLINES. + * mpf/random2.c: Add missing parameter in non-ANSI header. + * mpn/generic/gcd.c (SIGN_BIT): Do as #define to work around bug + in AIX compilers. + * mpq/get_d.c: #define N_QLIMBS. + * mpz/divexact.c: Obscure division by 0 to silent compiler warnings. + * stack-alloc.c: Cast void* pointer to char* before doing arithmetic + on it. + + * Makefile.in (mpbsd/libmpbsd.a): New rule. + * configure.in (configdirs): Add mpbsd. + + * gmp.h: Add declarations for a few missing mpn functions. + + * Makefile.in (libmp.a): New rule. + + * mpbsd/mdiv.c: #include "dmincl.c", not "mpz_dmincl.c" + * gmp.h: Move #define of __GNU_MP__ into the `#if __GNU_MP__' block. + * mp.h: Likewise. Update typedefs from gmp.h. + * mpbsd/configure.in: New file. + * mpbsd/Makefile.in: New file. + * mpbsd/configure: Link to master configure. + * mpbsd/config.sub: Link to master config.sub. + + * Makefile.in: Set RANLIB_TEST. + * (libgmp.a): Use it. + * (libgmp.a): Do ranlib before moving the libgmp.a to the build + directory. + * mp?/Makefile.in: Don't use or set RANLIB. + +Thu Feb 15 16:38:41 1996 Torbjorn Granlund <tege@tmg.se> + + * mpz/add_ui.c: MP_INT => mpz_t. + * mpz/cmp_ui.c: Likewise. + * mpz/fac_ui.c: Likewise. + * mpz/inp_binary.c: Likewise. + * mpz/inp_raw.c: Likewise. + * mpz/legendre.c: Likewise. + * mpz/jacobi.c: Likewise. + * mpz/out_binary.c: Likewise. + * mpz/out_raw.c: Likewise. + * mpz/random2.c: Likewise. + * mpz/random.c: Likewise. + * mpz/realloc.c: Likewise. + + * mpz/legendre.c: __mpz_2factor(X) => mpz_scan1(X,0), + __mpz_odd_less1_2factor => mpz_scan1(X,1). + * mpz/ntsup.c: File deleted. + * mpz/Makefile.in: Corresponding changes. + + * mpz/pprime_p: Use mpz_scan1 to avoid looping. + + * mpz/fac_ui.c: Type of `k' and `p' is `unsigned long'. + * mpz/pprime_p.c: Pass long to *_ui functions. + * mpz/gcdext.c: Likewise. + * mpz/fdiv_r_2exp.c: Likewise. + * mpz/fac_ui.c: Likewise. + + * mpz/powm.c: Don't use mpn_rshift when mod_shift_cnt is 0. + + * mpz/tests/Makefile.in (st-sqrtrem): Fix typo. + + * mpz/cmp_ui.c: #undef mpz_cmp_ui. + * mpz/cmp_si.c: #undef mpz_cmp_si. + * gmp.h (mpz_cmp_ui): New #define. + (mpz_cmp_si): New #define. + +Wed Feb 14 22:11:24 1996 Torbjorn Granlund <tege@tmg.se> + + * gmp.h: Test __cplusplus in addition to __STDC__. + * gmp-impl.h: Likewise. + + * gmp.h: Surround declarations with extern "C" { ... }. + +Tue Feb 13 15:20:45 1996 Torbjorn Granlund <tege@tmg.se> + + * mpz/fdiv_r_2exp.c: Use MPN_NORMALIZE. + * mpz/tdiv_r_2exp.c: Likewise. + + * mpz/fdiv_r_2exp.c: New file. + * mpz/fdiv_q_2exp.c: New file. + * mpz/tdiv_r_2exp.c: Renamed from mpz/mod_2exp.c. + * mpz/tdiv_q_2exp.c: Renamed from mpz/div_2exp.c + * mpz/Makefile.in: Corresponding changes. + + * mpz/scan0.c,scan1.c: New files. + * mpz/Makefile.in: Compile them. + + * gmp.h (mpn_normal_size): Delete. + + * config.guess: Update from Cygnus version. + + * mpn/m68k/rshift.S: Use INSN2 macro for lea instructions. + * mpn/m68k/lshift.S: Likewise. + + * mpn/configure.in: Fix configuration for plain 68000. + +Mon Feb 12 01:06:06 1996 Torbjorn Granlund <tege@tmg.se> + + * mpz/tests/t-powm.c: Generate negative BASE operand. + + * mpz/powm.c: Make result always positive. + +Sun Feb 11 01:44:56 1996 Torbjorn Granlund <tege@noisy.tmg.se> + + * mpz/tests/*.c: Add t- prefix. + * mpz/tests/Makefile.in: Corresponding changes. + * mpz/tests/configure.in: Update srctrigger. + + * mpz/tests/gcd.c: Generate negative operands. + * mpz/tests/gcd2.c: Likewise. + + * mpz/gcdext.c: At end, if G is negative, negate all G, S, and T. + +Thu Feb 8 17:16:12 UTC 1996 Ken Weber <kweber@mat.ufrgs.br> + + * mp{z,n}/gcd.c: Change mpn_gcd interface. + * gmp.h: Ditto. + * gmp.texi: update documentation. + +Mon Feb 7 23:58:43 1996 Andreas Schwab <schwab@informatik.uni-dortmund.de> + + * mpn/m68k/{lshift,rshift}.S: New files. + * mpn/m68k/syntax.h: New ELF_SYNTAX macros. + (MEM_INDX, R, PROLOG, EPILOG): New macros. + * mpn/m68k/*.S: Use R macro with register name. Use PROLOG and EPILOG + macros. Rename `size' to `s_size' or s1_size to avoid clash with ELF + .size directive. + * mpn/configure.in: New target m68k-*-linux*. + +Wed Feb 7 07:41:31 1996 Torbjorn Granlund <tege@noisy.tmg.se> + + * Makefile.in (cre-conv-tab): Workaround for SunOS make. + + * mpz/tests/reuse.c: New file. + * mpz/tests/Makefile.in: Handle reuse.c. + +Tue Feb 6 11:56:24 UTC 1996 Ken Weber <kweber@mat.ufrgs.br> + + * mpz/gcd.c: Fix g->size when one op is 0 and g == other op. + +Tue Feb 6 01:36:39 1996 Torbjorn Granlund <tege@noisy.tmg.se> + + * gmp.h (mpz_divexact): Delete parameter names. + (mpz_lcm): Delete spurious declaration. + + * mpz/dmincl.c: Fix typo. + +Mon Feb 5 01:11:56 1996 Torbjorn Granlund <tege@noisy.tmg.se> + + * mpn/generic/gcd.c (gcd_2): Declare consistently. + + * mpz/tdiv_q.c: Optimize division by a single-limb divisor. + * mpz/dmincl.c: Likewise. + + * mpz/add.c: Use MPN_NORMALIZE instead of mpn_normal_size. + * mpz/sub.c: Likewise. + * mpn/generic/sqrt.c: Likewise. + + * mpn/tests/{add_n,sub_n,lshift,rshift}.c: Put garbage in the + destination arrays. + +Fri Feb 2 02:21:27 1996 Torbjorn Granlund <tege@noisy.tmg.se> + + * mpz/{jacobi.c,legendre.c,ntsup.c,invert.c}: New files. + * mpz/Makefile.in: Compile them. + + * mpn/Makefile.in (INCLUDES): Don't search in `generic'. + +Thu Feb 1 02:15:11 1996 Torbjorn Granlund <tege@noisy.tmg.se> + + Change from Ken Weber: + * mpz/divexact.c: Make it work when quot is identical to either input. + + * mpf/ui_sub.c: New file. + * mpf/Makefile.in: Compile it. + + * gmp-impl.h (MPZ_TMP_INIT): alloca -> TMP_ALLOC. + * mpz/{c,f}div_{q,qr,r}.c: Use TMP_DECL/TMP_MARK/TMP_FREE since + these use MPZ_TMP_INIT. + * mpz/mod.c: Likewise. + * mpq/{add,sub}.c: Likewise. + * mpq/canonicalize: Likewise. + + * mpq/{add,sub,mul,div}.c: Use mpz_divexact. MP_INT -> mpz_t. + * mpq/canonicalize.c: Likewise. + +Wed Jan 31 01:45:00 1996 Torbjorn Granlund <tege@noisy.tmg.se> + + * mpn/generic/gcd.c: Misc changes from Ken. + + * mpz/tests/gcd2.c: New file. + * mpz/tests/Makefile.in: Handle gcd2.c. + + * mpn/generic/gcd.c (mpn_gcd): When GCD == ORIG_V, return vsize, + not orig_vsize. Fix parameter declaration. + + * mpz/mod_ui.c: Delete file. + * mpz/Makefile.in: Don't try to compile mod_ui. + + * mpz/cdiv_*_ui.c): Make them work right. + * gmp.h: Declare cdiv*. + +Tue Jan 30 02:22:56 1996 Torbjorn Granlund <tege@noisy.tmg.se> + + * mpz/{cdiv_q.c,cdiv_q_ui.c,cdiv_qr.c,cdiv_qr_ui.c,cdiv_r.c, + cdiv_r_ui.c,cdiv_ui.c}: New files. + * mpz/Makefile.in: Compile them. + + * All files: Make file permissions right. + + Changes from Ken Weber: + * mpn/generic/accelgcd.c: Delete. + * mpn/generic/bingcd.c: Delete. + * mpn/generic/numbits.c: Delete. + * mpn/generic/gcd.c: New file. + * mpn/configure.in (functions): Update accordingly. + * mpz/divexact.c: New file. + * mpz/Makefile.in: Compile divexact.c. + * mpz/gcd.c: Rewrite to accommodate for gcd changes in mpn. + * gmp.h: declare new functions, delete obsolete declarations. + * mpz/tests/dive.c: New file. + * mpz/tests/Makefile.in: Handle dive.c. + +Mon Jan 29 03:53:24 1996 Torbjorn Granlund <tege@noisy.tmg.se> + + * mpz/random.c: Handle negative SIZE parameter. + + * mpz/tests/tdiv(_ui).c: New name for tst-dm(_ui).c. + * mpz/tests/tst-mdm(_ui).c: Delete. + * mpz/tests/fdiv(_ui).c: New test based in tst-mdm(_ui). + * mpz/tests/*.c: Get rid of tst- prefix for DOS 8+3 naming. + * mpz/tests/Makefile.in: Corresponding changes. + * mpz/tests/configure.in: Update srctrigger. + + * mpn/generic/divmod.c: Update from divrem. + * mpn/generic/divrem.c: Misc cleanups. + +Sun Jan 28 03:25:08 1996 Torbjorn Granlund <tege@noisy.tmg.se> + + * All files: Use new TMP_ALLOC interface. + + * mpz/powm_ui.c: Make Jan 25 changes to powm.c also here. + + * mpz/tests/powm_ui.c: New file. + * mpz/tests/Makefile.in: Add rules for tst-powm and tst-powm_ui. + + * Makefile.in: Update dependency list. + * mpf/Makefile.in: Likewise. + * mpz/Makefile.in: Likewise. + * mpq/Makefile.in: Likewise. + * Makefile.in: Set RANLIB simply to ranlib, and allow configure + to override it. + + * mpz/Makefile.in (conf): Delete spurious target. + (mp_bases.c): Delete. + (cre-conv-tab rules): Delete. + + * Makefile.in (cre-conv-tab): Greatly simplify. + +Sat Jan 27 13:38:15 1996 Torbjorn Granlund <tege@noisy.tmg.se> + + * stack-alloc.c: New file. + * stack-alloc.h: New file. + + * gmp.h (__gmp_inline): Define using __inline__. + +Thu Jan 25 00:28:37 1996 Torbjorn Granlund <tege@noisy.tmg.se> + + * mpn/generic/scan0.c: New file. + * mpn/generic/scan1.c: Renamed from next_bit.c. + * mpn/configure.in (functions): Include scan0 and scan1. + + * mpn/m68k/*: #include sysdep.h. Use C_GLOBAL_NAME. + + * configure: Update from Cygnus version. + * config.guess: Likewise. + * config.sub: Likewise. + * configure: Pass --nfp to recursive configures. + + * mpz/tests/tst-*.c: Adjust SIZE and reps. + + * mpz/powm.c: Move esize==0 test earlier. + In final reduction of rp,rsize, don't call mpn_divmod unless + reduction is really needed. + + * mpz/tests/tst-powm.c: Fix thinko in checking code. + + * All files: Get rid of `__' prefix from mpn_* calls and declarations. + * gmp.h: #define __MPN. + * gmp.h: Use __MPN in #defines for mpn calls. + + * mpn/generic/mul_n.c: Prepend `i' to internal routines. + * gmp-impl.h: Add #defines using __MPN for those internal routines. + + * mpn/generic/sqrt.c: Change call to mpn_mul to mpn_mul_n. + +Wed Jan 24 13:28:19 1996 Torbjorn Granlund <tege@noisy.tmg.se> + + * mpn/sparc32/udiv_fp.S: New name for udiv_qrnnd.S. + * mpn/sparc32/udiv_nfp.S: New name for v8/udiv_qrnnd.S. + * mpn/sparc32/v8/supersparc: New directory. + * mpn/sparc32/v8/supersparc/udiv.S: New file. + +Tue Jan 23 01:10:11 1996 Torbjorn Granlund <tege@noisy.tmg.se> + + This major contribution is from Ken Weber: + * mpn/generic/accelgcd.c: New file. + * mpn/generic/bdivmod.c: New file. + * mpn/generic/bingcd.c: New file. + * mpn/generic/gcd_1.c: Rewrite. + * mpn/generic/numbits.c: New file (to go away soon). + * mpz/gcd.c: Rewrite. + * mpz/tests/tst-gcd.c (SIZE): Now 128. + * gmp.h: Declare new functions. + * mpn/configure.in (functions): List new files. + * gmp-impl.h (MPN_SWAP): Delete. + (MPN_LESS_BITS_LIMB, MPN_LESS_BITS, MPN_MORE_BITS): Delete. + (MPN_COMPL_INCR, MPN_COMPL): Delete. + +Mon Jan 22 02:04:59 1996 Torbjorn Granlund <tege@noisy.tmg.se> + + * gmp.h (mpn_name): New #define. + + * mpn/m88k/mc88110/addmul_1.s: New file. + * mpn/m88k/mc88110/add_n.S: New file. + * mpn/m88k/mc88110/sub_n.S: New file. + + * mpn/m88k/sub_n.s: Correctly initialize carry. + + * mpn/sparc32/{add_n.S,sub_n.S,lshift.S,rshift.S): `beq' => `be'. + +Sun Jan 21 00:04:35 1996 Torbjorn Granlund <tege@noisy.tmg.se> + + * mpn/sparc64/addmul_1.s: New file. + * mpn/sparc64/submul_1.s: New file. + * mpn/sparc64/rshift.s: New file. + +Sat Jan 20 00:32:54 1996 Torbjorn Granlund <tege@noisy.tmg.se> + + * mpz/iset.c: Fix typo introduced Dec 25. + +Wed Jan 17 13:16:44 1996 Torbjorn Granlund <tege@noisy.tmg.se> + + * config/mt-sprc8-gcc: New name for mt-sparc8-gcc. + * config/mt-sparcv8-gcc: Delete. + * configure.in: Corresponding changes. + +Tue Jan 16 16:31:01 1996 Torbjorn Granlund <tege@noisy.tmg.se> + + * gmp-impl.h: #include alloca.h when necessary. + + * longlong.h: Test __alpha instead of __alpha__, since the former + is the standard symbol. + +Mon Jan 15 18:06:57 1996 Torbjorn Granlund <tege@noisy.tmg.se> + + * mpn/sparc64/mul_1.s: Swap operands of mulx instructions. + * mpn/sparc64/lshift.s: New file. + +Fri Dec 29 17:34:03 1995 Torbjorn Granlund <tege@noisy.tmg.se> + + * mpn/x86/pentium/add_n.S: Get rid of #defines for register names. + * mpn/x86/pentium/sub_n.S: Likewise. + +Thu Dec 28 03:16:57 1995 Torbjorn Granlund <tege@noisy.tmg.se> + + * mpn/x86/pentium/mul_1.S: Rework loop to avoid AGI between update + of loop induction variable and load insn at beginning of loop. + * mpn/x86/pentium/addmul_1.S: Likewise. + * mpn/x86/pentium/submul_1.S: Likewise. + +Mon Dec 25 23:22:55 1995 Torbjorn Granlund <tege@noisy.tmg.se> + + * All files: Prefix user-visible structure fields with _mp_. + +Fri Dec 22 20:42:17 1995 Torbjorn Granlund <tege@noisy.tmg.se> + + * mpn/configure.in (m68k configs): Terminate path variable with + plain "m68k". + +Fri Dec 22 03:29:33 1995 Torbjorn Granlund <tege@noisy.tmg.se> + + * mpn/sparc32/add_n.S: Update from sub_n.S to fix bugs, and to + clean things up. + + * mpn/configure.in (m68k configs): Update #include path for new + mpn directory organization. + +Tue Dec 12 02:53:02 1995 Torbjorn Granlund <tege@noisy.tmg.se> + + * gmp.h: Prefix all structure field with _mp_. + * gmp-impl.h: Define access macros for these fields. + +Sun Dec 10 00:47:17 1995 Torbjorn Granlund <tege@noisy.tmg.se> + + * mpn/alpha/addmul_1.s: Prefix labels with `.'. + * mpn/alpha/submul_1.s: Likewise. + * mpn/alpha/[lr]shift.s: Likewise. + * mpn/alpha/udiv_qrnnd.S: Likewise. + * mpn/alpha/ev5/[lr]shift.s: Likewise. + + * mpn/alpha/ev5/lshift.s: Fix typos. + +Fri Dec 1 14:28:20 1995 Torbjorn Granlund <tege@noisy.tmg.se> + + * mpn/Makefile.in (.SUFFIXES): Define. + +Wed Nov 29 23:11:57 1995 Torbjorn Granlund <tege@noisy.tmg.se> + + * mpn/sparc64/{add_n.s, sub_n.s}: New files. + +Tue Nov 28 06:03:13 1995 Torbjorn Granlund <tege@noisy.tmg.se> + + * mpn/x86/syntax.h: Handle ELF_SYNTAX. + Rename GAS_SYNTAX => BSD_SYNTAX. + + * mpn/configure.in: Handle linuxelf and SysV for x86 variants. + +Mon Nov 27 01:32:12 1995 Torbjorn Granlund <tege@noisy.tmg.se> + + * mpn/hppa/hppa1_1/pa7100/submul_1.S: New file. + +Sun Nov 26 04:30:47 1995 Torbjorn Granlund <tege@noisy.tmg.se> + + * mpn/hppa/hppa1_1/pa7100/addmul_1.S: New file. + + * mpn/sparc32/add_n.S: Rewrite to use 64 bit loads/stores. + * mpn/sparc32/sub_n.S: Likewise. + +Fri Nov 17 00:18:46 1995 Torbjorn Granlund <tege@bozo.tmg.se> + + * mpn/configure.in: Handle m68k on NextStep. + +Thu Nov 16 02:30:26 1995 Torbjorn Granlund <tege@bozo.tmg.se> + + * mpn: Reorganize machine-specific directories. + * mpn/configure.in: Corresponding changes. + (sh, sh2): Handle these. + (m68k targets): Create asm-syntax.h. + +Thu Nov 9 02:20:50 1995 Torbjorn Granlund <tege@bozo.tmg.se> + + * mpn/generic/mul_n.c (____mpn_sqr_n): Delete code that calls abort. + (____mpn_mul_n): Likewise. + +Tue Nov 7 03:25:12 1995 Torbjorn Granlund <tege@bozo.tmg.se> + + * mpf/get_str.c: In exponentiation code (two places), don't swap + input and output areas when calling mpn_mul_1. + * mpf/set_str.c: Likewise. + +Fri Nov 3 02:35:58 1995 Torbjorn Granlund <tege@bozo.tmg.se> + + * mpf/Makefile.in: Make sure all objects are listed in dependency list; + delete spurious entries. + + * mpf/mul.c: Handle U or V being 0. Allow prec+1 for result precision. + + * mpf/set_prec.c: New computation of limb precision. + * mpf/set_dfl_prec.c: Likewise. + + * mpf/random2.c: Fix typo computing exp. + * mpf/get_str.c: In (uexp > usize) case, set n_limbs as a function of + the user-requested number of digits, n_digits. + +Thu Nov 2 16:25:07 1995 Torbjorn Granlund <tege@bozo.tmg.se> + + * mpn/generic/divrem.c (case 2): Don't move np vector back, it is + never read. + (default case): Put most significant limb from np in new variable n2; + decrease size argument for MPN_COPY_DECR; use n2 instead of np[dsize]. + +Wed Nov 1 02:59:53 1995 Torbjorn Granlund <tege@bozo.tmg.se> + + * mpn/sparc/[lr]shift.S: New files. + +Tue Oct 31 00:08:12 1995 Torbjorn Granlund <tege@bozo.tmg.se> + + * mpz/gcd_ui.c: Set w->size unconditionally when v is zero. + + * gmp-impl.h (assert): Delete definition. + + * mpf/sub.c: Delete all assert calls. Delete variable `cy'. + + * mpf/neg.c: Use prec+1 as precision. Optimize for when arguments + are the same. + * mpf/abs.c: Likewise. + * mpf/{set,neg,abs}.c: Make structure and variable names similar. + +Mon Oct 30 12:45:26 1995 Torbjorn Granlund <tege@bozo.tmg.se> + + * mpf/random2.c (random): Test __SVR4 in addition to __svr4__. + * mpn/generic/random2.c (random): Likewise. + +Sun Oct 29 01:54:28 1995 Torbjorn Granlund <tege@bozo.tmg.se> + + * mpf/div.c: Special handle U or V being 0. + + * mpf/random2.c: New file. + + * longlong.h (i860 rshift_rhlc): Define. + (i960 udiv_qrnnd): Define. + (i960 count_leading_zeros): Define. + (i960 add_ssaaaa): Define. + (i960 sub_ddmmss): Define. + (i960 rshift_rhlc): Define. + +Sat Oct 28 19:09:15 1995 Torbjorn Granlund <tege@bozo.tmg.se> + + * mpn/pentium/rshift.S: Fix and generalize condition for when to use + special code for shift by 1. + * mpn/pentium/lshift.S: Likewise. + +Thu Oct 26 00:02:56 1995 Torbjorn Granlund <tege@bozo.tmg.se> + + * gmp.h: #undef __need_size_t. + * mp.h: Update from gmp.h. + +Wed Oct 25 00:17:27 1995 Torbjorn Granlund <tege@bozo.tmg.se> + + * mpf/Makefile.in: Compile set_prec.c. + * mpf/realloc.c: Delete this file. + * mpf/Makefile.in: Delete mentions of realloc.c. + + * gmp.h (__mpf_struct): Get rid of `alloc' field. + * mpf/clear.c: Likewise. + * mpf/init*.c: Likewise. + * mpf/set_prec.c: Likewise. + * mpf/iset*.c: Likewise. + + * mpf/iset_str.c: New file. + + * mpn/configure.in: Handle pyramid. + + * mpf/set.c: Use prec+1 as precision. + + * mpf/set_prec.c: New file. + +Tue Oct 24 00:56:41 1995 Torbjorn Granlund <tege@bozo.tmg.se> + + * mpn/generic/divrem.c: New file. Will replace mpn/generic/divmod.c + when rest of source is converted. + * mpn/configure.in (functions): Add `divrem' + * mpn/generic/set_str.c: Never call __mpn_mul_1 with zero size. + + * mpf/get_str.c: Completely rewritten. + * mpf/add.c: Fix several problems. + * mpf/sub.c: Compare operands from most significant end until + first difference, exclude skipped limbs from computation. + Accordingly simplify normalization code. + * mpf/set_str.c: Fix several problems. + * mpf/dump.c: New file. + * mpf/Makefile.in: Compile dump.c. + * mpf/init2.c: Set prec field correctly. + +Sun Oct 22 03:02:09 1995 Torbjorn Granlund <tege@bozo.tmg.se> + + * cre-conv-tab.c: #include math.h; don't declare log and floor. + +Sat Oct 21 23:04:10 1995 Torbjorn Granlund <tege@bozo.tmg.se> + + * mpf/mul_ui.c: Handle U being 0. + +Wed Oct 18 19:39:27 1995 Torbjorn Granlund <tege@bozo.tmg.se> + + * mpn/generic/set_str.c: Correctly handle input like "000000000000". + Misc cleanups. + +Tue Oct 17 15:14:13 1995 Torbjorn Granlund <tege@bozo.tmg.se> + + * longlong.h: Define COUNT_LEADING_ZEROS_0 for machines where + appropriate. + +Mon Oct 16 19:14:43 1995 Torbjorn Granlund <tege@bozo.tmg.se> + + * mpf/add.c: Rewrite. + * mpf/set_str.c: New file. Needs more work. + +Sat Oct 14 00:14:04 1995 Torbjorn Granlund <tege@bozo.tmg.se> + + * mpf/div_2exp.c: Vastly simplify. + * mpf/mul_2exp.c: Likewise. + + * mpf/sub.c: Rewrite. + + * gmp-impl.h (udiv_qrnnd_preinv2gen): Terminate comment. + + * mpf/dump.c: Free allocated memory. + + * gmp-impl.h (assert): Define. + +Wed Oct 11 13:31:00 1995 Torbjorn Granlund <tege@bozo.tmg.se> + + * mpn/pentium/rshift.S: Install new code to optimize shift-by-1. + +Tue Oct 10 00:37:21 1995 Torbjorn Granlund <tege@bozo.tmg.se> + + * mpn/pentium/lshift.S: Install new code to optimize shift-by-1. + + * mpn/powerpc32/{lshift.s,rshift.s}: New files. + + * configure.in: Fix typo. + +Sat Oct 7 08:17:09 1995 Torbjorn Granlund <tege@bozo.tmg.se> + + * longlong.h (smul_ppmm): Correct type of __m0 and __m1. + +Wed Oct 4 16:31:28 1995 Torbjorn Granlund <tege@bozo.tmg.se> + + * mpn/configure.in: Handle alphaev5. + * mpn/ev4: New name for alpha subdir. + * mpn/ev5: New subdir. + * mpn/ev5/lshift.s: New file. + +Tue Oct 3 15:06:45 1995 Torbjorn Granlund <tege@bozo.tmg.se> + + * mpn/alpha/mul_1.s: Avoid static increments of pointers; use + corresponding offsets in ldq and stq instructions instead. + (Loop): Swap cmpult and stq to save one cycle on EV5. + + * mpn/tests/{add_n.s,sub_n.s,lshift.s,rshift.s,mul_1.s,addmul_1.s, + submul_1.s}: Don't check results if NOCHECK is defined. + +Mon Oct 2 11:40:18 1995 Torbjorn Granlund <tege@bozo.tmg.se> + + * longlong.h (mips umul_ppmm [32 and 64 bit versions]): + Make new variants, based on GCC version number, that use `l' and `h' + constraints instead of explicit mflo and mfhi instructions + +Sun Oct 1 00:17:47 1995 Torbjorn Granlund <tege@bozo.tmg.se> + + * mpn/mc88100/add_n.s: Decrease unrolling factor from 16 to 8. + * mpn/mc88100/sub_n.s: Likewise. + + * config/mt-m88110: New file. + * configure.in: Use it. + + * mpn/mc88110/mul_1.s: Fix thinko. + +Sat Sep 30 21:28:19 1995 Torbjorn Granlund <tege@bozo.tmg.se> + + * mpz/set_d.c: Declare `size' at function start. + + * experimental: New directory for mpx and mpz2. + + * mpz/tdiv_q.c: Clarify comments. + * mpz/{mod.c,mod_ui.c}: New file, for math mod function. + + * mpn/sh2/{mul_1.s,addmul_1.s,submul_1.s}: New files. + + * mpn/sh/{add_n.s,sub_n.s}: New files. + + * mpn/pyr/{add_n.s,sub_n.s,mul_1.s,addmul_1.s}: New files. + + * mpn/i960/{add_n.s,sub_n.s}: New files. + + * mpn/alpha/addmul_1.s (Loop): Move decrement of r18 to before umulh, + to save cycles on EV5. + * mpn/alpha/submul_1.s: Ditto. + * mpn/alpha/mul_1.s: Ditto. + +Thu Sep 28 02:48:59 1995 Torbjorn Granlund <tege@bozo.tmg.se> + + * gmp.h (mp_limb, mp_limb_signed): Define as `long long' if + _LONG_LONG_LIMB is defined. + + * longlong.h (m88110): Test __m88110__, not __mc88110__ + + * mpn/mc88110/mul_1.s: Rewrite. + +Tue Sep 26 23:29:05 1995 Torbjorn Granlund <tege@bozo.tmg.se> + + * config.sub: Update from current Cygnus version. + + * mpn/configure.in: Recognize canonical m88*, not mc88*. + +Fri Sep 22 14:58:05 1995 Torbjorn Granlund <tege@bozo.tmg.se> + + * mpz/set_d.c: New file. + * mpz/Makefile.in: Build new files. + + * mpq/get_d.c: Replace usage of scalbn with ldexp. + + * mpn/{vax,i386}/gmp-mparam.h: New files. + * gmp-impl.h (ieee_double_extract): Define here. + * mpf/set_d.c (ieee_double_extract): Not here. + +Thu Sep 21 00:56:36 1995 Torbjorn Granlund <tege@bozo.tmg.se> + + * longlong.h (C umul_ppmm): Use UWtype, not USItype for temps. + (udiv_qrnnd): For cases implemented with call to __udiv_qrnnd, + protect with new symbol LONGLONG_STANDALONE. + (68000 umul_ppmm): Use %# prefix for immediate constants. + +Wed Sep 20 15:36:23 1995 Torbjorn Granlund <tege@bozo.tmg.se> + + * mpn/generic/divmod_1.c: Handle + divisor_limb == 1 << (BITS_PER_MP_LIMB - 1) + specifically also when normalization_steps != 0. + +Mon Sep 18 15:42:30 1995 Torbjorn Granlund <tege@bozo.tmg.se> + + * mpq/get_d.c: New file. + +Sun Sep 17 02:04:36 1995 Torbjorn Granlund <tege@bozo.tmg.se> + + * longlong.h (pyr): Botch up for now. + +Sat Sep 16 00:11:50 1995 Torbjorn Granlund <tege@bozo.tmg.se> + + * mpn/clipper/mul_1.s: New file. + * mpn/clipper/add_n.s: New file. + * mpn/clipper/sub_n.s: New file. + * mpn/configure.in: Handle clipper*-*-*. + + * mpn/configure.in: Recognize rs6000-*-*. + +Fri Sep 15 00:41:34 1995 Torbjorn Granlund <tege@bozo.tmg.se> + + * mpn/alpha/add_n.s: New file. + * mpn/alpha/sub_n.s: New file. + + * mpn/mips3: New name for mpn/r4000. + * mpn/mips2: New name for mpn/r3000. + * mpn/configure.in: Corresponding changes. + + * mpn/generic/perfsqr.c (primes): Delete. + (residue_map): Delete. + +Thu Sep 14 00:07:58 1995 Torbjorn Granlund <tege@bozo.tmg.se> + + * mpn/r3000/sub_n.s: Fix typo. + + * dm_trunc.c: Delete spurious file. + + * mpz/out_binary.c: Fix typo. + + * mpn/configure.in (per-target): Make mips*-*-irix6* imply r4000. + + * gmp-impl.h: For sparc and sgi, include alloca.h. + + * mpn/z8000/mul_1.s: Replace `test r' with `and r,r'. Replace + `ldk r,#0' with `xor r,r'. + +Wed Sep 6 00:58:38 1995 Torbjorn Granlund <tege@bozo.tmg.se> + + * mpz/inp_binary.c: New file. + * mpz/out_binary.c: New file. + * mpz/Makefile.in: Build new files. + +Tue Sep 5 22:53:51 1995 Torbjorn Granlund <tege@bozo.tmg.se> + + * gmp.h (__mpz_struct): Change `long int' => `mp_size_t' for alloc + and size fields. + +Sat Sep 2 17:47:59 1995 Torbjorn Granlund <tege@bozo.tmg.se> + + * mpn/r4000/{add_n.s,sub_n.s}: Optimize away some pointer arithmetic. + * mpn/r3000/{add_n.s,sub_n.s,lshift.s,rshift.s}: New files, + derived from r4000 code. + +Fri Sep 1 05:35:52 1995 Torbjorn Granlund <tege@bozo.tmg.se> + + * mpn/r3000/mul_1.s: Fix typo. + + * mpn/powerpc32: Fix some old vs new mnemonic issues. + + * mpn/powerpc32/{add_n.s,sub_n.s}: New files. + * mpn/r4000/{add_n.s,sub_n.s,lshift.s,rshift.s}: New files. + +Wed Aug 30 10:43:47 1995 Torbjorn Granlund <tege@bozo.tmg.se> + + * mpn/r3000/mul_1.s ($LC1): Use addiu for immediate add. + * mpn/r4000/{mul_1.s,addmul_1.s,submul_1.s}: New files. + + * config.guess: Update to latest FSF revision. + +Mon Aug 28 02:18:13 1995 Torbjorn Granlund <tege@bozo.tmg.se> + + * mpz/out_str.c: Cast str to char * in fputs call. + + * gmp-impl.h: Define UQItype, SItype, and USItype also + when not __GNUC__. + +Fri Aug 25 01:45:04 1995 Torbjorn Granlund <tege@bozo.tmg.se> + + * mpn/i386/syntax.h: Renamed from asm-syntax.h. + * mpn/mc68020/syntax.h: Renamed from asm-syntax.h. + * mpn/configure.in: Corresponding changes. + +Sun Aug 13 19:20:04 1995 Torbjorn Granlund <tege@bozo.tmg.se> + + * mpn/generic/random2.c: Test __hpux, not hpux. + +Sat Apr 15 20:50:33 1995 Torbjorn Granlund (tege@tiny.cygnus.com) + + * mpn/sparc/add_n.S: Make it work for PIC. + * mpn/sparc/sub_n.s: Likewise. + * mpn/sparc8/addmul_1.S: Likewise. + * mpn/sparc8/mul_1.S: Likewise. + * mpn/i386/add_n.S: Likewise. + * mpn/i386/sub_n.S: Likewise. + +Thu Apr 13 23:15:03 1995 Torbjorn Granlund (tege@tiny.cygnus.com) + + * mpn/configure.in: Don't search power subdir for generic ppc configs. + Add some ppc cpu-specific configs. Misc clean up. + +Mon Apr 10 00:16:35 1995 Torbjorn Granlund (tege@tiny.cygnus.com) + + * mpz/ui_pow_ui.c: Delete spurious code to handle negative results. + +Sun Apr 9 12:38:11 1995 Torbjorn Granlund (tege@tiny.cygnus.com) + + * longlong.h (SPARC v8 udiv_qrnnd): Generate remainder in C, + not in asm. + + * mpn/generic/sqrt.c (SQRT): Test for __SOFT_FLOAT. + +Tue Mar 28 00:19:52 1995 Torbjorn Granlund (tege@tiny.cygnus.com) + + * mpn/generic/hamdist.c (popc_limb): Make Mar 16 change here too. + +Fri Mar 17 23:29:22 1995 Torbjorn Granlund (tege@tiny.cygnus.com) + + * longlong.h (SH umul_ppmm): Define. + +Thu Mar 16 16:40:44 1995 Torbjorn Granlund (tege@tiny.cygnus.com) + + * mpn/generic/popcount.c (popc_limb): Rearrange 32 bit case + to help CSE. + +Fri Mar 10 20:03:49 1995 Torbjorn Granlund (tege@tiny.cygnus.com) + + * mpn/powerpc32/mul_1.s: Clear cy before entering loop. + Rearrange loop to save a cycle. + * mpn/powerpc32/addmul_1.s: New file. + * mpn/powerpc32/submul_1.s: New file. + +Fri Feb 17 22:44:45 1995 Torbjorn Granlund (tege@tiny.cygnus.com) + + * mpn/configure.in: Set target_makefile_frag for freebsd + in new case stmt. + * mpn/config/t-freebsd: New file. + * mpn/Makefile.in: Add #### for frag insertion. + (XCFLAGS): Clear by default. + (.c.o, .S.o rules): Pass XCFLAGS. + +Tue Feb 7 16:27:50 1995 Torbjorn Granlund (tege@tiny.cygnus.com) + + * longlong.h (68000 umul_ppmm): Merge improvements from henderson. + +Tue Jan 24 04:23:20 1995 Torbjorn Granlund (tege@tiny.cygnus.com) + + * longlong.h (default umul_ppmm): Store input parameters in temporaries + to avoid reading them twice. + (default smul_ppmm): New definition. + +Thu Dec 29 04:20:07 1994 Jim Meyering (meyering@comco.com) + + * generic/perfsqr.c (__mpn_perfect_square_p): Remove declaration + of unused variable. + * generic/pre_mod_1.c (__mpn_preinv_mod_1): Likewise. + * mpz/powm.c (pow): Likewise. + + * mpz/and.c (mpz_and): Use {} instead of `;' for empty else clause + to placate `gcc -Wall'. + * mpz/ior.c (mpz_ior): Likewise. + +Wed Dec 28 13:31:40 1994 Torbjorn Granlund (tege@tiny.cygnus.com) + + * mpn/m*68*/*.S: #include asm-syntax.h, not asm.h. + +Mon Dec 26 17:15:36 1994 Torbjorn Granlund (tege@tiny.cygnus.com) + + * longlong.h: Test for more symbols, in __mc68000__ case. + + * mpn/mpn/config.sub: Recognize m68060. + * mpn/configure.in: Change mc* to m* for 68k targets. + * mpn/Makefile.in (.S.o): Delete spurious creation of temp .c file. + +Mon Dec 19 01:56:30 1994 Torbjorn Granlund (tege@tiny.cygnus.com) + + * config.sub: Recognize pentium as a valid CPU. + * mpn/configure.in: Handle pentium specifically, to use new assembly + code. + +Mon Dec 19 00:13:01 1994 Jim Meyering (meyering@comco.com) + + * gmp.h: Define _GMP_H_HAVE_FILE if FILE, __STDIO_H__, or H_STDIO + is defined. + * gmp.h: test _GMP_H_HAVE_FILE instead of FILE everywhere else. + +Mon Dec 19 00:04:54 1994 Kent Boortz (boortz@sics.se) + + * Makefile.in (recursive makes): Pass CFLAGS. + +Sun Dec 18 22:34:49 1994 Torbjorn Granlund (tege@tiny.cygnus.com) + + * mpn/pentium: New directory. + + * mpz/pprime.c: Make sure to mpz_clear all temporaries. + + * longlong.h: Don't use udiv instruction when SUPERSPARC is defined. + * configure.in: Handle supersparc*-. + * config/mt-supspc-gcc: New file. + * config/mt-sparc8-gcc: New name for mt-sparcv8-gcc. + +Mon Dec 12 22:22:10 1994 Torbjorn Granlund (tege@tiny.cygnus.com) + + * mpn/i386/*.S: #include "asm-syntax.h", not "asm.h". + #include sysdep.h before asm-syntax.h. + + * mpn/mc68020/asm-syntax.h: #undef ALIGN before defining it. + * mpn/i386/asm-syntax.h: Likewise. + + * mpn/mc68020/asm-syntax.h: New name for asm.h. + * mpn/i386/asm-syntax.h: New name for asm.h. + +Tue Dec 6 21:55:25 1994 Torbjorn Granlund (tege@tiny.cygnus.com) + + * mpz/array_init.c: Fix typo in declaration. + +Fri Nov 18 19:50:52 1994 Torbjorn Granlund (tege@tiny.cygnus.com) + + * mpn/Makefile.in (.S.o): Pass CFLAGS and INCLUDES. + +Mon Nov 14 00:34:12 1994 Torbjorn Granlund (tege@tiny.cygnus.com) + + * mpn/generic/random2.c (random): Test for __svr4__. + +Wed Oct 12 23:28:16 1994 Torbjorn Granlund (tege@tiny.cygnus.com) + + * cre-conv-tab.c (main): Avoid upper-case X in printf format string. + +Tue Aug 23 17:16:35 1994 Torbjorn Granlund (tege@tiny.cygnus.com) + + * mpz/perfsqr.c: Use mpn_perfect_square_p. + * mpn/generic/perfsqr.c: New file. + +Wed Jul 6 13:46:51 1994 Torbjorn Granlund (tege@tiny.cygnus.com) + + * mpz/array_init.c: New file. + * mpz/Makefile.in: Compile array_init. + * gmp.h: Declare mpz_array_init. + +Mon Jul 4 01:10:03 1994 Torbjorn Granlund (tege@tiny.cygnus.com) + + * mpz/add.c: Fix bogus comment. + * mpz/sub.c: Likewise. + +Sat Jul 2 02:14:56 1994 Torbjorn Granlund (tege@adder.cygnus.com) + + * mpn/generic/pre_mod_1.c: New file. + * mpz/perfsqr.c: Use __mpn_preinv_mod_1 when faster. + +Fri Jul 01 22:10:19 1994 Richard Earnshaw (rwe11@cl.cam.ac.uk) + + * longlong.h (arm umul_ppmm): Fix typos in last change. Mark + hard-coded registers with "%|" + +Thu Jun 30 03:59:33 1994 Torbjorn Granlund (tege@tiny.cygnus.com) + + * mpz/perfsqr.c: Define PP, etc, for machines with 64 bit limbs. + Use __mpn_mod_1. + * mpz/perfsqr.c: Don't clobber REM in quadratic residue check loop. + +Wed Jun 29 18:45:41 1994 Torbjorn Granlund (tege@adder.cygnus.com) + + * mpn/generic/sqrt.c (SQRT): New asm for IBM POWER2. + + * mpz/gcd_ui.c: Return 0 if result does not fit an unsigned long. + + * gmp.h: Use "defined (__STDC__)" consistently. + +Tue Jun 28 18:44:58 1994 Torbjorn Granlund (tege@adder.cygnus.com) + + * gmp.h (mpz_get_si): Don't use "signed" keyword for return type. + + * mpz/tests/Makefile.in: Use CFLAGS for linking. + + * Makefile.in (CFLAGS): Use -O2 here. + * mpn/Makefile (CFLAGS): Not here. + + * mpq/cmp_ui.c: Fix typo. + * mpq/canonicalize.c: Fix typo. + * mpz/gcd_ui.c: Handle gcd(0,v) and gcd(u,0) correctly. + * mpn/generic/gcd_1.c: Fix braino in last change. + +Mon Jun 27 16:10:27 1994 Torbjorn Granlund (tege@rtl.cygnus.com) + + * mpz/gcd_ui.c: Change return type and return result. + Allow destination param to be NULL. + * gmp.h: Corresponding change. + * mpn/generic/gcd_1.c: Handle zero return from mpn_mod_1. + +Tue Jun 14 02:17:43 1994 Torbjorn Granlund (tege@tiny.cygnus.com) + + * mpn/i386/asm.h (ALIGN): Make it take a parameter. + * mpn/i386/*.S: Use ALIGN to align all loops. + + * mpn/i386/*.S: Move colon inside C_GLOBAL_NAME expression. + (Makes old versions of GAS happy.) + +Sat May 28 01:43:54 1994 Torbjorn Granlund (tege@adder.cygnus.com) + + * Many files: Delete unused variables and labels. + * mpn/generic/dump.c: cast printf width argument to int. + +Wed May 25 00:42:37 1994 Torbjorn Granlund (tege@thepub.cygnus.com) + + * mpz/gcd.c (mpz_gcd): Normalize after __mpn_sub calls. + (xmod): Ignore return value of __mpn_divmod. + (xmod): Improve normalization code. + +Sat May 21 01:30:09 1994 Torbjorn Granlund (tege@adder.cygnus.com) + + * mpz/gcdext.c: Cosmetic changes. + + * mpz/fdiv_ui.c: New file. + +Fri May 20 00:24:53 1994 Torbjorn Granlund (tege@adder.cygnus.com) + + * mpz/tests/Makefile.in: Use explicit rules for running tests, + not a shell loop. + (clean): Delete stmp-*. + + * mpz/Makefile.in: Update. + + * mpz/div_ui.c: Don't include longlong.h. + * mpz/dm_ui.c: Likewise. + + * mpz/fdiv_q.c, mpz/fdiv_q_ui.c, mpz/fdiv_qr.c, mpz/fdiv_qr_ui.c, + mpz/fdiv_r.c, mpz/fdiv_r_ui.c: New files. Code partly from deleted + mdm.c, mdm_ui.c, etc, partly rewritten. + * mpz/dm_floor_ui.c, mpz/dm_floor.c: Delete. + * mpz/mdm.c, mpz/mdm_ui.c, mpz/mdiv.c, mpz/mdiv_ui.c, mpz/mmod.c, + mpz/mmod_ui.c: Delete. + + * mpz/tdiv_q.c, mpz/tdiv_q_ui.c, mpz/tdiv_qr.c, mpz/tdiv_qr_ui.c, + mpz/tdiv_r.c, mpz/tdiv_r_ui.c: + New names for files implementing truncating division. + * mpz/div_ui.c, mpz/dm_ui.c, mpz/mod_ui.c: Simplify. + + * mpn/Makefile.in (.S.o): Don't rely on CPP being defined, use CC + instead. + (clean): Delete tmp-*. + +Thu May 19 01:37:44 1994 Torbjorn Granlund (tege@adder.cygnus.com) + + * mpz/cmp.c: Call __mpn_cmp. + + * mpz/popcount.c: Fix typo. + + * mpz/powm_ui.c: Simplify main loop. Keep principal operand size + smaller than MSIZE when possible. + * mpz/powm.c: Likewise. + + * mpn/generic/sqrt.c: Move alloca calls into where the memory is + needed. Simplify. + + * gmp.h: (_PROTO): New macro. + Add many function declarations; use _PROTO macro in all declarations. + + * mpf/*.c: Prepend mpn calls with __. + +Wed May 18 20:57:06 1994 Torbjorn Granlund (tege@adder.cygnus.com) + + * mpf/*ui*.c: Make ui argument `long' for consistency with mpz + functions. + + * mpf/div_ui.c: Simplify. + +Tue May 17 01:05:14 1994 Torbjorn Granlund (tege@adder.cygnus.com) + + * mpz/*.c: Prepend mpn calls with __. + + * mpz/mul_ui.c: Use mpn_mul_1. + +Mon May 16 17:19:41 1994 Torbjorn Granlund (tege@adder.cygnus.com) + + * mpn/i386/mul_1.S: Use C_GLOBAL_NAME. + * mpn/i386/mul_1.S, mpn/i386/addmul_1.S, mpn/i386/submul_1.S: + Nuke use of LAB. + +Sat May 14 14:21:02 1994 Torbjorn Granlund (tege@adder.cygnus.com) + + * gmp-impl.h: Don't define abort here. + + * mpz/pow_ui.c: Increase temporary allocation. + * mpz/ui_pow_ui.c: Likewise. + + * gmp.h (mpz_add_1, mpz_sub_1): Don't call memcpy. + + * All Makefile.in: Delete spurious -I arguments. + Update dependencies. + + * mpz/popcount.c: New file. + * mpz/hamdist.c: New file. + + * All configure: Latest version from Cygnus. + + * mpq/Makefile.in: New file. + * mpq/configure.in: New file. + * Makefile.in, configure.in: Enable compilation of mpq. + + * mpq/set_z.c: Fix typos. + * mpq/canonicalize.c: Fix typos. + * mpq/cmp_ui.c: Fix typos. + + * mpf/add_ui.c: Read U->D into UP always. Delete spurious MPN_COPY. + * mpf/sub_ui.c: Likewise. + + * gmp-impl.h: Don't redefine alloca. + + * COPYING.LIB: Renamed from COPYING. + +Wed May 11 01:45:44 1994 Torbjorn Granlund (tege@adder.cygnus.com) + + * mpz/powm_ui.c: When shifting E left by C+1, handle out-of-range + shift counts. Fix typo when testing negative_result. + * mpz/powm.c: Likewise. + + * mpz/ui_pow_ui.c: New file. + * mpz/Makefile.in: Update. + + * mpz/pow_ui.c: Call __mpn_mul_n instead of __mpn_mul when possible. + + * mpz/div.c, mpz/div_ui.c, mpz/gcd.c: Prefix external mpn calls. + * mpz/gcd.c: Declare mpn_xmod. + + * mpz/powm.c: Major changes to accommodate changed mpn semantics. + * mpz/powm_ui.c: Update from mpz/powm.c. + + * mpz/tests/tst-io.c: New file. + * mpz/tests/tst-logic: New file. + * mpz/tests/Makefile.in: Update. + + * mpz/inp_str.c: Get base right when checking for first digit. + * mpz/inp_str.c: Allocate more space for DEST when needed. + + * mpz/com.c: Use mpn_add_1 and mpn_sub_1. + * mpz/and.c, mpz/ior.c: Likewise. Simplify somewhat. + + * mpz/add_ui.c: Use mpn_add_1 and mpn_sub_1. + Rename parameters to be consistent with mpz/sub_ui. + General simplifications. + * mpz/sub_ui.x: Likewise. + +Tue Aug 10 19:41:16 1993 Torbjorn Granlund (tege@prudens.matematik.su.se) + + * mpf: New directory. + * mpf/*.c: Merge basic set of mpf functions. + + * Many logs missing... + +Sun Apr 25 18:40:26 1993 Torbjorn Granlund (tege@pde.nada.kth.se) + + * memory.c: Use #if instead of #ifdef for __STDC__ for consistency. + * bsd/xtom.c: Likewise. + + * mpz/div.c: Remove free_me and free_me_size and their usage. + Use mpn_divmod for division; corresponding changes in return value + convention. + * mpz/powm.c: `carry_digit' => `carry_limb'. + * bsd/sdiv.c: Clearify comment. + +Sun Apr 25 00:31:28 1993 Torbjorn Granlund (tege@pde.nada.kth.se) + + * longlong.h (__udiv_qrnnd_c): Make all variables `unsigned long int'. + +Sat Apr 24 16:23:33 1993 Torbjorn Granlund (tege@pde.nada.kth.se) + + * longlong.h (__udiv_qrnnd_c): Make all variables `unsigned long int'. + + * gmp-impl.h: #define ABS. + * (Many files): Use ABS instead of abs. + + * mpn/generic/sqrt.c, mpz/clrbit.c, mpz/get_si.c, mpz/mod_2exp.c, + mpz/pow_ui.c: Cast 1 to mp_limb before shifting. + + * mpz/perfsqr.c: Use #if, not plain if for exclusion of code for + non-32-bit machines. + +Tue Apr 20 13:13:58 1993 Torbjorn Granlund (tege@du.nada.kth.se) + + * mpn/generic/sqrt.c: Handle overflow for intermediate quotients by + rounding them down to fit. + + * mpz/perfsqr.c (PP): Define in hexadecimal to avoid GCC warnings. + + * mpz/inp_str.c (char_ok_for_base): New function. + (mpz_inp_str): Use it. + +Sun Mar 28 21:54:06 1993 Torbjorn Granlund (tege@cyklop.nada.kth.se) + + * mpz/inp_raw.c: Allocate x_index, not xsize limbs. + +Mon Mar 15 11:44:06 1993 Torbjorn Granlund (tege@pde.nada.kth.se) + + * mpz/pprime.c: Declare param `const'. + * gmp.h: Add declarations for mpz_com. + +Thu Feb 18 14:10:34 1993 Torbjorn Granlund (tege@pde.nada.kth.se) + + * mpq/add.c, mpq/sub.c: Call mpz_clear for t. + +Fri Feb 12 20:27:34 1993 Torbjorn Granlund (tege@cyklop.nada.kth.se) + + * mpz/inp_str.c: Recog minus sign as first character. + +Wed Feb 3 01:36:02 1993 Torbjorn Granlund (tege@cyklop.nada.kth.se) + + * mpz/iset.c: Handle 0 size. + +Tue Feb 2 13:03:33 1993 Torbjorn Granlund (tege@cyklop.nada.kth.se) + + * mpz/mod_ui.c: Initialize dividend_size before it's used. + +Mon Jan 4 09:11:15 1993 Torbjorn Granlund (tege@sics.se) + + * bsd/itom.c: Declare param explicitly 'signed'. + * bsd/sdiv.c: Likewise. + + * mpq/cmp.c: Remove unused variable tmp_size. + * mpz/powm_ui.c: Fix typo in esize==0 if stmt. + * mpz/powm.c: Likewise. + +Sun Nov 29 01:16:11 1992 Torbjorn Granlund (tege@sics.se) + + * mpn/generic/divmod_1.c (mpn_divmod_1): Handle + divisor_limb == 1 << (BITS_PER_MP_LIMB - 1) + specifically. + + * Reorganize sources. New directories mpn, mpn/MACH, mpn/generic, + mpz, mpq, bsd. Use full file name for change logs hereafter. + +Wed Oct 28 17:40:04 1992 Torbjorn Granlund (tege@jupiter.sics.se) + + * longlong.h (__hppa umul_ppmm): Fix typos. + (__hppa sub_ddmmss): Swap input arguments. + + * mpz_perfsqr.c (mpz_perfect_square_p): Avoid , before } in + initializator. + +Sun Oct 25 20:30:06 1992 Torbjorn Granlund (tege@jupiter.sics.se) + + * mpz_pprime.c (mpz_probab_prime_p): Handle numbers <= 3 + specifically (used to consider all negative numbers prime). + + * mpz_powm_ui: `carry_digit' => `carry_limb'. + + * sdiv: Handle zero dividend specifically. Replace most code in + this function with a call to mpn_divmod_1. + +Fri Sep 11 22:15:55 1992 Torbjorn Granlund (tege@tarrega.sics.se) + + * mpq_clear: Don't free the MP_RAT! + + * mpn_lshift, mpn_rshift, mpn_rshiftci: Remove `long' from 4:th arg. + +Thu Sep 3 01:47:07 1992 Torbjorn Granlund (tege@jupiter.sics.se) + + * All files: Remove leading _ from mpn function names. + +Wed Sep 2 22:21:16 1992 Torbjorn Granlund (tege@jupiter.sics.se) + + Fix from Jan-Hein Buhrman: + * mpz_mdiv.c, mpz_mmod.c, mpz_mdm.c: Make them work as documented. + + * mpz_mmod.c, mpz_mdm.c: Move decl of TEMP_DIVISOR to reflect its + life. + +Sun Aug 30 18:37:15 1992 Torbjorn Granlund (tege@jupiter.sics.se) + + * _mpz_get_str: Use mpz_sizeinbase for computing out_len. + * _mpz_get_str: Don't remove leading zeros. Abort if there are some. + +Wed Mar 4 17:56:56 1992 Torbjorn Granlund (tege@zevs.sics.se) + + * gmp.h: Change definition of MP_INT to make the & before params + optional. Use typedef to define it. + * mp.h: Use typedef to define MINT. + +Tue Feb 18 14:38:39 1992 Torbjorn Granlund (tege@zevs.sics.se) + + longlong.h (hppa umul_ppmm): Add missing semicolon. Declare type + of __w1 and __w0. + +Fri Feb 14 21:33:21 1992 Torbjorn Granlund (tege@zevs.sics.se) + + * longlong.h: Make default count_leading_zeros work for machines > + 32 bits. Prepend `__' before local variables to avoid conflicts + with users' variables. + + * mpn_dm_1.c: Remove udiv_qrnnd_preinv ... + * gmp-impl.h: ... and put it here. + * mpn_mod_1: Use udiv_qrnnd_preinv if it is faster than udiv_qrnnd. + +Tue Feb 11 17:20:12 1992 Torbjorn Granlund (tege@zevs.sics.se) + + * mpn_mul: Enhance base case by handling small multiplicands. + * mpn_dm_1.c: Revert last change. + +Mon Feb 10 11:55:15 1992 Torbjorn Granlund (tege@zevs.sics.se) + + * mpn_dm_1.c: Don't define udiv_qrnnd_preinv unless needed. + +Fri Feb 7 16:26:16 1992 Torbjorn Granlund (tege@zevs.sics.se) + + * mpn_mul: Replace code for base case. + +Thu Feb 6 15:10:42 1992 Torbjorn Granlund (tege@zevs.sics.se) + + * mpn_dm_1.c (_mpn_divmod_1): Add code for avoiding division by + pre-inverting divisor. + +Sun Feb 2 11:10:25 1992 Torbjorn Granlund (tege@zevs.sics.se) + + * longlong.h: Make __LLDEBUG__ work differently. + (_IBMR2): Reinsert old code. + +Sat Feb 1 16:43:00 1992 Torbjorn Granlund (tege@zevs.sics.se) + + * longlong.h (#ifdef _IBMR2): Replace udiv_qrnnd with new code + using floating point operations. Don't define + UDIV_NEEDS_NORMALIZATION any longer. + +Fri Jan 31 15:09:13 1992 Torbjorn Granlund (tege@zevs.sics.se) + + * longlong.h: Define UMUL_TIME and UDIV_TIME for most machines. + * longlong.h (#ifdef __hppa): Define umul_ppmm. + +Wed Jan 29 16:41:36 1992 Torbjorn Granlund (tege@zevs.sics.se) + + * mpn_cmp: Only one length parameter, assume operand lengths are + the same. Don't require normalization. + * mpq_cmp, mpz_add, mpz_sub, mpz_gcd, mpn_mul, mpn_sqrt: Change for + new mpn_cmp definition. + +Tue Jan 28 11:18:55 1992 Torbjorn Granlund (tege@zevs.sics.se) + + * _mpz_get_str: Fix typo in comment. + +Mon Jan 27 09:44:16 1992 Torbjorn Granlund (tege@zevs.sics.se) + + * Makefile.in: Add new files. + + * mpn_dm_1.c: New file with function _mpn_divmod_1. + * mpz_dm_ui.c (mpz_divmod_ui): Use _mpn_divmod_1. + * mpz_div_ui: Likewise. + + * mpn_mod_1.c: New file with function _mpn_mod_1. + * mpz_mod_ui: Use _mpn_mod_1. + +Thu Jan 23 18:54:09 1992 Torbjorn Granlund (tege@zevs.sics.se) + + Bug found by Paul Zimmermann (zimmermann@inria.inria.fr): + * mpz_div_ui.c (mpz_div_ui), mpz_dm_ui.c (mpz_divmod_ui): + Handle dividend == 0. + +Wed Jan 22 12:02:26 1992 Torbjorn Granlund (tege@zevs.sics.se) + + * mpz_pprime.c: Use "" for #include. + +Sun Jan 19 13:36:55 1992 Torbjorn Granlund (tege@zevs.sics.se) + + * mpn_rshiftci.c (header): Correct comment. + +Wed Jan 15 18:56:04 1992 Torbjorn Granlund (tege@zevs.sics.se) + + * mpz_powm, mpz_powm_ui (if (bsize > msize)): Do alloca (bsize + 1) + to make space for ignored quotient at the end. (The quotient might + always be an extra limb.) + +Tue Jan 14 21:28:48 1992 Torbjorn Granlund (tege@zevs.sics.se) + + * mpz_powm_ui: Fix comment. + * mpz_powm: Likewise. + +Mon Jan 13 18:16:25 1992 Torbjorn Granlund (tege@zevs.sics.se) + + * tests/Makefile.in: Prepend $(TEST_PREFIX) to Makefile target. + +Sun Jan 12 13:54:28 1992 Torbjorn Granlund (tege@zevs.sics.se) + + Fixes from Kazumaro Aoki: + * mpz_out_raw: Take abs of size to handle negative values. + * mpz_inp_raw: Reallocate before reading ptr from X. + * mpz_inp_raw: Store, don't read, size to x->size. + +Tue Jan 7 17:50:25 1992 Torbjorn Granlund (tege@zevs.sics.se) + + * gmp.h, mp.h: Remove parameter names from prototypes. + +Sun Dec 15 00:09:36 1991 Torbjorn Granlund (tege@zevs.sics.se) + + * tests/Makefile.in: Prepend "./" to file names when executing + tests. + + * Makefile.in: Fix many problems. + +Sat Dec 14 01:00:02 1991 Torbjorn Granlund (tege@zevs.sics.se) + + * mpn_sqrt.c: New file with _mpn_sqrt. + * mpz_sqrt, mpz_sqrtrem, mpz_perfect_square_p: Use _mpn_sqrt. + * msqrt.c: Delete. Create from mpz_sqrtrem.c in Makefile.in. + * mpz_do_sqrt.c: Delete. + * Makefile.in: Update to reflect these changes. + + * Makefile.in, configure, configure.subr: New files + (from bothner@cygnus.com). + * dist-Makefile: Delete. + + * mpz_fac_ui: Fix comment. + + * mpz_random2: Rewrite a bit to make it possible for the most + significant limb to be == 1. + + * mpz_pprime.c (mpz_probab_prime_p): Remove \t\n. + +Fri Dec 13 23:10:02 1991 Torbjorn Granlund (tege@zevs.sics.se) + + * mpz_do_sqrt: Simplify special case for U == 0. + * m*sqrt*.c, mpz_perfsqr.c (mpz_perfect_square_p): + Rename _mpz_impl_sqrt to _mpz_do_sqrt. + +Fri Dec 13 12:52:28 1991 Torbjorn Granlund (tege@zevs.sics.se) + + * gmp-impl.h (MPZ_TMP_INIT): Cast to the right type. + +Thu Dec 12 22:17:29 1991 Torbjorn Granlund (tege@zevs.sics.se) + + * mpn_add, mpn_sub, mpn_mul, mpn_div: Change type of several + variables to mp_size. + +Wed Dec 11 22:00:34 1991 Torbjorn Granlund (tege@zevs.sics.se) + + * mpn_rshift.c: Fix header comments. + +Mon Dec 9 17:46:10 1991 Torbjorn Granlund (tege@zevs.sics.se) + + Released 1.2. + + * gmp-impl.h (MPZ_TMP_INIT): Cast alloca return value. + + * dist-Makefile: Add missing dependency for cre-mparam. + + * mpz_mdiv.c, mpz_mmod.c, mpz_mdm.c, mpz_mdiv_ui.c, + mpz_mmod_ui.c, mpz_mdm_ui.c: Remove obsolete comment. + + * dist-Makefile (clean): clean in tests subdir too. + * tests/Makefile: Define default values for ROOT and SUB. + + * longlong.h (__a29k__ udiv_qrnnd): Change "q" to "1" for operand + 2 constraint. + +Mon Nov 11 00:06:05 1991 Torbjorn Granlund (tege@zevs.sics.se) + + * mpz_sizeinb.c (mpz_sizeinbase): Special code for size == 0. + +Sat Nov 9 23:47:38 1991 Torbjorn Granlund (tege@zevs.sics.se) + + Released 1.1.94. + + * dist-Makefile, Makefile, tests/Makefile: Merge tests into + distribution. + +Fri Nov 8 22:57:19 1991 Torbjorn Granlund (tege@zevs.sics.se) + + * gmp.h: Don't use keyword `signed' for non-ANSI compilers. + +Thu Nov 7 22:06:46 1991 Torbjorn Granlund (tege@zevs.sics.se) + + * longlong.h: Cosmetic changes to keep it identical to gcc2 version + of longlong.h. + * longlong.h (__ibm032__): Fix operand order for add_ssaaaa and + sub_ddmmss. + +Mon Nov 4 00:36:46 1991 Torbjorn Granlund (tege@zevs.sics.se) + + * mpn_mul: Fix indentation. + + * mpz_do_sqrt: Don't assume 32 bit limbs (had constant + 4294967296.0). + * mpz_do_sqrt: Handle overflow in conversion from double returned + by SQRT to mp_limb. + + * gmp.h: Add missing function definitions. + +Sun Nov 3 18:25:25 1991 Torbjorn Granlund (tege@zevs.sics.se) + + * mpz_pow_ui: Change type of `i' to int. + + * ChangeLog: Add change log entry. + * ChangeLog: Add change log entry. + * ChangeLog: Add change log entry. + * ChangeLog: Add change log entry. + * ChangeLog: Add change log entry. + * ChangeLog: Add change log entry. + * ChangeLog: Add change log entry. + * ChangeLog: Add change log entry. +Stack overflow. + + * mpz_pow_ui.c: Fix typo in comment. + + * dist-Makefile: Create rpow.c from mpz_powm_ui.c. + * mpz_powm_ui.c: Add code for rpow. + * rpow.c: Delete this file. The rpow function is now implemented + in mpz_powm_ui.c. + + * mpz_fac_ui.c: New file. + * gmp.h, dist-Makefile: Add stuff for mpz_fac_ui. + + Bug found by John Amanatides (amana@sasquatch.cs.yorku.ca): + * mpz_powm_ui, mpz_powm: Call _mpn_mul in the right way, with + the first argument not smaller than the second. + +Tue Oct 29 13:56:55 1991 Torbjorn Granlund (tege@zevs.sics.se) + + * cre-conv-tab.c (main), cre-mparam.c (main): Fix typo in output + header text. + +Mon Oct 28 00:35:29 1991 Torbjorn Granlund (tege@zevs.sics.se) + + * mpz_random2: Handle size == 0. + + * gmp-impl.h (struct __mp_bases): Rename chars_per_limb_exactly to + chars_per_bit_exactly, and change its definition. + * cre-conv-tab.c (main): Output field according to its new + definition. + * mpz_out_str, _mpz_get_str, mpz_sizeinb, mout: + Use chars_per_bit_exactly. + + * mpz_random2: Change the loop termination condition in order to + get a large most significant limb with higher probability. + + * gmp.h: Add declaration of new mpz_random2 and mpz_get_si. + * mpz_get_si.c: New file. + * dist-Makefile: Add mpz_random2 and mpz_get_si. + + * mpz_sizeinb.c (mpz_sizeinbase): Special code for base being a + power of 2, giving exact result. + + * mpn_mul: Fix MPN_MUL_VERIFY in various ways. + * mpn_mul: New macro KARATSUBA_THRESHOLD. + * mpn_mul (karatsuba's algorithm): Don't write intermediate results + to prodp, use temporary pp instead. (Intermediate results can be + larger than the final result, possibly writing into hyperspace.) + * mpn_mul: Make smarter choice between Karatsuba's algorithm and the + shortcut algorithm. + * mpn_mul: Fix typo, cy instead of xcy. Unify carry handling code. + +Sun Oct 27 19:57:32 1991 Torbjorn Granlund (tege@zevs.sics.se) + + * mpn_mul: In non-classical case, choose Karatsuba's algorithm only + when usize > 1.5 vsize. + + * mpn_mul: Break between classical and Karatsuba's algorithm at + KARATSUBA_THRESHOLD, if defined. Default to 8. + + * mpn_div: Kludge to fix stray memory read. + +Sat Oct 26 20:06:14 1991 Torbjorn Granlund (tege@zevs.sics.se) + + * mpz_gcdext: Handle a = b = 0. Remove memory leakage by calling + mpz_clear for all temporary variables. + + * mpz_gcd: Reduce w_bcnt in _mpn_lshift call to hold that + function's argument constraints. Compute wsize correctly. + + * mpz_gcd: Fix typo in comment. + + * memory.c (_mp_default_allocate, _mp_default_reallocate): Call + abort if allocation fails, don't just exit. + +Fri Oct 25 22:17:20 1991 Torbjorn Granlund (tege@zevs.sics.se) + + * mpz_random2.c: New file. + +Thu Oct 17 18:06:42 1991 Torbjorn Granlund (tege@zevs.sics.se) + + Bugs found by Pierre-Joseph Gailly (pjg@sunbim.be): + * mpq_cmp: Take sign into account, don't just compare the + magnitudes. + * mpq_cmp: Call _mpn_mul in the right way, with the first argument + not smaller than the second. + +Wed Oct 16 19:27:32 1991 Torbjorn Granlund (tege@zevs.sics.se) + + * mpz_random: Ensure the result is normalized. + +Tue Oct 15 14:55:13 1991 Torbjorn Granlund (tege@zevs.sics.se) + + * mpz_clrbit: Support non-ANSI compilers. + +Wed Oct 9 18:03:28 1991 Torbjorn Granlund (tege@zevs.sics.se) + + * longlong.h (68k add_ssaaaa, sub_ddmmss): Generalize constraints. + +Tue Oct 8 17:42:59 1991 Torbjorn Granlund (tege@zevs.sics.se) + + * mpz_mdm_ui: Add comments. + + * mpz_mdiv: Use MPZ_TMP_INIT instead of mpz_init. + * mpz_init_ui: Change spacing and header comment. + +Thu Oct 3 18:36:13 1991 Torbjorn Granlund (tege@zevs.sics.se) + + * dist-Makefile: Prepend `./' before some filenames. + +Sun Sep 29 14:02:11 1991 Torbjorn Granlund (tege@zevs.sics.se) + + Released 1.1 (public). + + * mpz_com: New name of mpz_not. + * dist-Makefile: Change mpz_not to mpz_com. + +Tue Sep 24 12:44:11 1991 Torbjorn Granlund (tege@zevs.sics.se) + + * longlong.h: Fix header comment. + +Mon Sep 9 15:16:24 1991 Torbjorn Granlund (tege@zevs.sics.se) + + Released 1.0.92. + + * mpn_mul.c (_mpn_mul): Handle leading zero limbs in non-Karatsuba + case. + + * longlong.h (m68000 umul_ppmm): Clobber one register less by + slightly rearranging the code. + +Sun Sep 1 18:53:25 1991 Torbjorn Granlund (tege@zevs.sics.se) + + * dist-Makefile (stamp-stddefh): Fix typo. + +Sat Aug 31 20:41:31 1991 Torbjorn Granlund (tege@zevs.sics.se) + + Released 1.0.91. + + * mpz_mdiv.c, mpz_mmod.c, mpz_mdm.c, mpz_mdiv_ui.c, + mpz_mmod_ui.c, mpz_mdm_ui.c: New files and functions. + * gmp.h, gmp.texi: Define the new functions. + +Fri Aug 30 08:32:56 1991 Torbjorn Granlund (tege@zevs.sics.se) + + * mpz_gcdext: Compute t argument from the other quantities at the + end, of the function, not in the loop. New feature: Allow t to be + NULL. + + * mpz_add.c, mpz_sub.c, mpz_mul.c, mpz_powm.c, mpz_gcd.c: Don't + include "mp.h". Use type name `MP_INT' always. + + * dist-Makefile, mpz_cmp.c: Merge mcmp.c from mpz_cmp.c. + +Wed Aug 28 00:45:11 1991 Torbjorn Granlund (tege@zevs.sics.se) + + * dist-Makefile (documentation): Go via tmp.texi to avoid the + creation of gmp.dvi if any errors occur. Make tex read input + from /dev/null. + +Fri Aug 23 15:58:52 1991 Torbjorn Granlund (tege@zevs.sics.se) + + * longlong.h (68020, i386): Don't define machine-dependent + __umulsidi3 (so the default definition is used). + * longlong.h (all machines): Cast all operands, sources and + destinations, to `unsigned long int'. + * longlong.h: Add gmicro support. + +Thu Aug 22 00:28:29 1991 Torbjorn Granlund (tege@zevs.sics.se) + + * longlong.h: Rename BITS_PER_LONG to LONG_TYPE_SIZE. + * longlong.h (__ibm032__): Define count_leading_zeros and umul_ppmm. + * longlong.h: Define UMUL_TIME and UDIV_TIME for some CPUs. + * _mpz_get_str.c: Add code to do division by big_base using only + umul_qrnnd, if that is faster. Use UMUL_TIME and UDIV_TIME to + decide which variant to use. + +Wed Aug 21 15:45:23 1991 Torbjorn Granlund (tege@zevs.sics.se) + + * longlong.h (__sparc__ umul_ppmm): Move two insn from end to the + nops. (Saves two insn.) + + * longlong.h (__sparc__ umul_ppmm): Rewrite in order to avoid + branch, and to permit input/output register overlap. + + * longlong.h (__29k__): Remove duplicated udiv_qrnnd definition. + * longlong.h (__29k__ umul_ppmm): Split asm instructions into two + asm statements (gives better code if either the upper or lower + part of the product is unused. + +Tue Aug 20 17:57:59 1991 Torbjorn Granlund (tege@zevs.sics.se) + + * _mpz_get_str.c (outside of functions): Remove + num_to_ascii_lower_case and num_to_ascii_upper_case. Use string + constants in the function instead. + +Mon Aug 19 00:37:42 1991 Torbjorn Granlund (tege@zevs.sics.se) + + * cre-conv-tab.c (main): Output table in hex. Output 4 fields, not + 3, for components 0 and 1. + + * gmp.h: Add declaration of mpq_neg. + + Released 1.0beta.13. + + * _mpz_set_str.c (mpz_set_str): Cast EOF and SPC to char before + comparing to enum literals SPC and EOF. This makes the code work + for compilers where `char' is unsigned. (Bug found by Brian + Beuning). + + Released 1.0beta.12. + + * mpz_mod_ui: Remove references to quot. Remove quot_ptr, quot_size + declarations and assignment code. + +Sun Aug 18 14:44:26 1991 Torbjorn Granlund (tege@zevs.sics.se) + + * mpz_mod_ui: Handle dividend < 0. + + Released 1.0beta.11. + + * mpz_dm_ui, mpz_div_ui, mpz_mod_ui, sdiv: Make them share the same + general structure, variable names, etc. + + * sdiv: Un-normalize the remainder in n1 before it is negated. + + * longlong.h: Mention UDIV_NEEDS_NORMALIZATION in description of + udiv_qrnnd. + + * mpz_dm_ui.c (mpz_divmod_ui), mpz_div_ui.c (mpz_div_ui): Increment + the quotient size if the dividend size is incremented. (Bug found + by Brian Beuning.) + + * mpz_mod_ui: Shift back the remainder, if UDIV_NEEDS_NORMALIZATION. + (Bug found by Brian Beuning.) + + * mpz_mod_ui: Replace "digit" by "limb". + + * mpz_perfsqr.c (mpz_perfect_square_p): Disable second test case + for non-32-bit machines (PP is hardwired for such machines). + * mpz_perfsqr.c (outside of functions): Define PP value with an L. + + * mpn_mul.c (_mpn_mul): Add verification code that is activated if + DEBUG is defined. Replace "digit" by "limb". + * mpn_mul.c (_mpn_mul: Karatsuba's algorithm: 4.): Normalize temp + after the addition. + * mpn_mul.c (_mpn_mul: Karatsuba's algorithm: 1.): Compare u0_size + and v0_size, and according to the result, swap arguments in + recursive call. (Don't violate mpn_mul's own argument + constraints.) + +Fri Aug 16 13:47:12 1991 Torbjorn Granlund (tege@zevs.sics.se) + + Released 1.0beta.10. + + * longlong.h (IBMR2): Add udiv_qrnnd. + + * mpz_perfsqr: Remove unused variables. + + * mpz_and (case for different signs): Initialize loop variable i! + + * dist-Makefile: Update automatically generated dependencies. + * dist-Makefile (madd.c, msub.c, pow.c, mult.c, gcd.c): Add mp.h, + etc to dependency file lists. + + * longlong.h (add_ssaaaa, sub_ddmmss [C default versions]): Make __x + `unsigned long int'. + * longlong.h: Add `int' after `unsigned' and `long' everywhere. + +Wed Aug 14 18:06:48 1991 Torbjorn Granlund (tege@zevs.sics.se) + + * longlong.h: Add ARM, i860 support. + + * mpn_lshift, mpn_rshift, mpn_rshiftci: Rename *_word with *_limb. + +Tue Aug 13 21:57:43 1991 Torbjorn Granlund (tege@zevs.sics.se) + + * _mpz_get_str.c, _mpz_set_str.c, mpz_sizeinb.c (mpz_sizeinbase), + mpz_out_str.c, mout.c: Remove declaration of __mp_bases. + * gmp-impl.h: Put it here, and make it `const'. + * cre-conv-tab.c (main): Make struct __mp_bases `const'. + +Mon Aug 12 17:11:46 1991 Torbjorn Granlund (tege@zevs.sics.se) + + * cre-conv-tab.c (main): Use %lu in printf for long ints. + + * dist-Makefile: Fix cre-* dependencies. + + * cre-conv-tab.c (main): Output field big_base_inverted. + + * gmp-impl.h (struct bases): New field big_base_inverted. + * gmp-impl.h (struct bases): Change type of chars_per_limb_exactly + to float (in order to keep the structure smaller). + + * mp.h, gmp.h: Change names of macros for avoiding multiple + includes. + +Fri Aug 9 18:01:36 1991 Torbjorn Granlund (tege@zevs.sics.se) + + * _mpz_get_str: Only shift limb array if normalization_steps != 0 + (optimization). + + * longlong.h (sparc umul_ppmm): Use __asm__, not asm. + * longlong.h (IBMR2 umul_ppmm): Refer to __m0 and __m1, not to m0 + and m1 (overlap between output and input operands did not work). + * longlong.h: Add VAX, ROMP and HP-PA support. + * longlong.h: Sort the machine dependent code in alphabetical order + on the CPU name. + * longlong.h: Hack comments. + +Thu Aug 8 14:13:36 1991 Torbjorn Granlund (tege@zevs.sics.se) + + Released 1.0beta.9. + + * longlong.h: Define BITS_PER_LONG to 32 if it's not already + defined. + * Define __BITS4 to BITS_PER_LONG / 4. + * Don't assume 32 bit word size in "count_leading_zeros" C macro. + Use __BITS4 and BITS_PER_LONG instead. + + * longlong.h: Don't #undef internal macros (reverse change of Aug 3). + + * longlong.h (68k): Define add_ssaaaa sub_ddmmss, and umul_ppmm + even for plain mc68000. + + * mpq_div: Flip the sign of the numerator *and* denominator of the + result if the intermediate denominator is negative. + + * mpz_and.c, mpz_ior.c: Use MPN_COPY for all copying operations. + + * mpz_and.c: Compute the result size more conservatively. + * mpz_ior.c: Likewise. + + * mpz_realloc: Never allocate zero space even if NEW_SIZE == 0. + + * dist-Makefile: Remove madd.c, msub.c, pow.c, mult.c, gcd.c from + BSDMP_SRCS. + + * dist-Makefile: Create mult.c from mpz_mul.c. + * mult.c: Delete this file. + + * _mpz_set_str: Normalize the result (for bases 2, 4, 8... it was + not done properly if the input string had many leading zeros). + +Sun Aug 4 16:54:14 1991 Torbjorn Granlund (tege@zevs.sics.se) + + * dist-Makefile (gcd.c, pow.c, madd.c, msub.c): Make these targets + work with VPATH and GNU MP. + + * mpz_gcd: Don't call mpz_set; inline its functionality. + + * mpq_mul, mpq_div: Fix several serious typos. + + * mpz_dmincl, mpz_div: Don't normalize the quotient if it's already + zero. + + * mpq_neg.c: New file. + + * dist-Makefile: Remove obsolete dependencies. + + * mpz_sub: Fix typo. + + Bugs found by Pierre-Joseph Gailly (pjg@sunbim.be): + * mpq_mul, mpq_div: Initialize tmp[12] variables even when the gcd + is just 1. + * mpz_gcd: Handle gcd(0,v) and gcd(u,0) in special cases. + +Sat Aug 3 23:45:28 1991 Torbjorn Granlund (tege@zevs.sics.se) + + * longlong.h: Clean up comments. + * longlong.h: #undef internal macros. + +Fri Aug 2 18:29:11 1991 Torbjorn Granlund (tege@zevs.sics.se) + + * mpq_set_si, mpq_set_ui: Canonicalize 0/x to 0/1. + * mpq_set_si, mpq_set_ui: Cosmetic formatting changes. + + * mpz_dmincl.c: Normalize the remainder before shifting it back. + + * mpz_dm_ui.c (mpz_divmod_ui): Handle rem == dividend. + + * mpn_div.c: Fix comment. + + * mpz_add.c, mpz_sub.c: Use __MP_INT (not MP_INT) for intermediate + type, in order to work for both GNU and Berkeley functions. + + * dist-Makefile: Create gcd.c from mpz_gcd.c, pow.c from mpz_powm, + madd.c from mpz_add.c, msub.c from mpz_sub.c. + respectively. + * pow.c, gcd.c, mpz_powmincl.c, madd.c, msub.c: Remove these. + * mpz_powm.c, mpz_gcd.c, mpz_add.c, mpz_sub.c: #ifdef for GNU and + Berkeley function name variants. + * dist-Makefile: Add created files to "clean" target. + +Tue Jul 16 15:19:46 1991 Torbjorn Granlund (tege@zevs.sics.se) + + * mpq_get_den: No need for absolute value of the size, the + denominator is always positive. + + * mpz_get_ui: If the operand is zero, return zero. Don't read the + limb array! + + * mpz_dmincl.c: Don't ignore the return value from _mpn_rshift, it + is the size of the remainder. + +Mon Jul 15 11:08:05 1991 Torbjorn Granlund (tege@zevs.sics.se) + + * Several files: Remove unused variables and functions. + + * gmp-impl.h: Declare _mpz_impl_sqrt. + + * mpz_dm_ui (mpz_divmod_ui), sdiv: Shift back the remainder if + UDIV_NEEDS_NORMALIZATION. (Fix from Brian Beuning.) + + * mpz_dm_ui.c, sdiv: Replace *digit with *limb. + + * mpz_ior: Add missing else statement in -OP1 | -OP2 case. + * mpz_ior: Add missing else statement in OP1 | -OP2 case. + * mpz_ior: Swap also OP1 and OP2 pointers in -OP1 & OP2 case. + * mpz_ior: Duplicate _mpz_realloc code. + + * mpz_and: Add missing else statement in -OP1 & -OP2 case. + * mpz_and: Rewrite OP1 & -OP2 case. + * mpz_and: Swap also OP1 and OP2 pointers in -OP1 & OP2 case. + + * mpz_gcdext: Loop in d1.size (not b->size). (Fix from Brian + Beuning.) + + * mpz_perfsqr: Fix argument order in _mpz_impl_sqrt call. (Fix from + Brian Beuning.) + +Fri Jul 12 17:10:33 1991 Torbjorn Granlund (tege@zevs.sics.se) + + * mpq_set.c, mpq_set_ui.c, mpq_set_si.c, mpq_inv.c, + mpq_get_num.c, mpq_get_den.c, mpq_set_num.c, mpq_set_den.c: + New files. + + * mpz_dmincl.c: Remove second re-allocation of rem->d. It + was never executed. + + * dist-Makefile: Use `-r' instead of `-x' for test for ranlib (as + some unixes' test doesn't have the -r option). + + * *.*: Cast allocated pointers to the appropriate type (makes old C + compilers happier). + + * cre-conv-tab.c (main): Divide max_uli by 2 and multiply again + after conversion to double. (Kludge for broken C compilers.) + + * dist-Makefile (stamp-stddefh): New target. Test if "stddef.h" + exists in the system and creates a minimal one if it does not + exist. + * cre-stddefh.c: New file. + * dist-Makefile: Make libgmp.a and libmp.a depend on stamp-stddefh. + * dist-Makefile (clean): Add some more. + * gmp.h, mp.h: Unconditionally include "stddef.h". + +Thu Jul 11 10:08:21 1991 Torbjorn Granlund (tege@zevs.sics.se) + + * min: Do ungetc of last read character. + * min.c: include stdio.h. + + * dist-Makefile: Go via tmp- files for cre* redirection. + * dist-Makefile: Add tmp* to "clean" target. + + * dist-Makefile: Use LOCAL_CC for cre*, to simplyfy cross + compilation. + + * gmp.h, mp.h: Don't define NULL here. + * gmp-impl.h: Define it here. + +Wed Jul 10 14:13:33 1991 Torbjorn Granlund (tege@zevs.sics.se) + + * mpz_mod_2exp: Don't copy too much, overwriting most significant + limb. + + * mpz_and, mpz_ior: Don't read op[12]_ptr from op[12] when + reallocating res, if op[12]_ptr got their value from alloca. + + * mpz_and, mpz_ior: Clear up comments. + + * cre-mparam.c: Output parameters for `short int' and `int'. + + * mpz_and, mpz_ior: Negate negative op[12]_size in several places. + +Tue Jul 9 18:40:30 1991 Torbjorn Granlund (tege@zevs.sics.se) + + * gmp.h, mp.h: Test for _SIZE_T defined before typedef'ing size_t. + (Fix for Sun lossage.) + + * gmp.h: Add declaration of mpq_clear. + + * dist-Makefile: Chack if "ranlib" exists, before using it. + * dist-Makefile: Add mpz_sqrtrem.c and mpz_size.c. + * mpz_powm: Fix typo, "pow" instead of "mpz_powm". + +Fri Jul 5 19:08:09 1991 Torbjorn Granlund (tege@zevs.sics.se) + + * move: Remove incorrect comment. + + * mpz_free, mpq_free: Rename to *_clear. + * dist-Makefile: Likewise. + * mpq_add, mpq_sub, mpq_mul, mpq_div: Likewise. + + * mpz_dmincl.c: Don't call "move", inline its functionality. + +Thu Jul 4 00:06:39 1991 Torbjorn Granlund (tege@zevs.sics.se) + + * Makefile: Include dist-Makefile. Fix dist target to include + dist-Makefile (with the name "Makefile" in the archive). + + * dist-Makefile: New file made from Makefile. Add new mpz_... + functions. + + * mpz_powincl.c New file for mpz_powm (Berkeley MP pow) + functionality. Avoids code duplication. + * pow.c, mpz_powm.c: Include mpz_powincl.c + + * mpz_dmincl.c: New file containing general division code. Avoids + code duplication. + * mpz_dm.c (mpz_divmod), mpz_mod.c (mpz_mod), mdiv.c (mdiv): Include + mpz_dmincl.c. + + * _mpz_get_str: Don't call memmove, unless HAS_MEMMOVE is defined. + Instead, write the overlapping memory copying inline. + + * mpz_dm_ui.c: New name for mpz_divmod_ui.c (SysV file name limit). + + * longlong.h: Don't use #elif. + * mpz_do_sqrt.c: Likewise. + + * longlong.h: Use __asm__ instead of asm. + * longlong.h (sparc udiv_qrnnd): Make it to one string over several + lines. + + * longlong.h: Preend __ll_ to B, highpart, and lowpart. + + * longlong.h: Move array t in count_leading_zeros to the new file + mp_clz_tab.c. Rename the array __clz_tab. + * All files: #ifdef for traditional C compatibility. + +Wed Jul 3 11:42:14 1991 Torbjorn Granlund (tege@zevs.sics.se) + + * mpz_and: Initialize res_ptr always (used to be initialized only + when reallocating). + + * longlong.h (umul_ppmm [C variant]): Make __ul...__vh + `unsigned int', and cast the multiplications. This way + compilers more easily can choose cheaper multiplication + instructions. + + * mpz_mod_2exp: Handle input argument < modulo argument. + * mpz_many: Make sure mp_size is the type for sizes, not int. + + * mpz_init, mpz_init_set*, mpq_init, mpq_add, mpq_sub, mpq_mul, + mpq_div: Change mpz_init* interface. Structure pointer as first + arg to initialization function, no longer *return* struct. + +Sun Jun 30 19:21:44 1991 Torbjorn Granlund (tege@zevs.sics.se) + + * Rename mpz_impl_sqrt.c to mpz_do_sqrt.c to satisfy SysV 14 + character file name length limit. + + * Most files: Rename MINT to MP_INT. Rename MRAT to MP_RAT. + * mpz_sizeinb.c: New file with function mpz_sizeinbase. + * mp_bases.c: New file, with array __mp_bases. + * _mpz_get_str, _mpz_set_str: Remove struct bases, use extern + __mp_bases instead. + * mout, mpz_out_str: Use array __mp_bases instead of function + _mpz_get_cvtlen. + * mpz_get_cvtlen.c: Remove. + * Makefile: Update. + +Sat Jun 29 21:57:28 1991 Torbjorn Granlund (tege@zevs.sics.se) + + * longlong.h (__sparc8__ umul_ppmm): Insert 3 nop:s for wr delay. + * longlong.h (___IBMR2__): Define umul_ppmm, add_ssaaaa, sub_ddmmss. + * longlong.h (__sparc__): Don't call .umul; expand asm instead. + Don't define __umulsidi3 (i.e. use default definition). + +Mon Jun 24 17:37:23 1991 Torbjorn Granlund (tege@amon.sics.se) + + * _mpz_get_str.c (num_to_ascii_lower_case, num_to_ascii_upper_case): + Swap 't' and 's'. + +Sat Jun 22 13:54:01 1991 Torbjorn Granlund (tege@zevs.sics.se) + + * mpz_gcdext.c: New file. + + * mpn_mul: Handle carry and unexpected operand sizes in last + additions/subtractions. (Bug trigged when v1_size == 1.) + + * mp*_alloc*: Rename functions to mp*_init* (files to mp*_iset*.c). + * mpq_*: Call mpz_init*. + + * mpz_pow_ui, rpow: Use _mpn_mul instead of mult. Restructure. + +Wed May 29 20:32:33 1991 Torbjorn Granlund (tege@zevs.sics.se) + + * mpz_get_cvtlen: multiply by size. + +Sun May 26 15:01:15 1991 Torbjorn Granlund (tege@bella.nada.kth.se) + + Alpha-release 0.95. + + Fixes from Doug Lea (dl@g.oswego.edu): + * mpz_mul_ui: Loop to MULT_SIZE (not PROD_SIZE). Adjust PROD_SIZE + correctly. + * mpz_div: Prepend _ to mpz_realloc. + * mpz_set_xs, mpz_set_ds: Fix typos in function name. + +Sat May 25 22:51:16 1991 Torbjorn Granlund (tege@bella.nada.kth.se) + + * mpz_divmod_ui: New function. + + * sdiv: Make the sign of the remainder correct. + +Thu May 23 15:28:24 1991 Torbjorn Granlund (tege@zevs.sics.se) + + * Alpha-release 0.94. + + * mpz_mul_ui: Include longlong.h. + + * mpz_perfsqr.c (mpz_perfect_square_p): Call _mpz_impl_sqrt instead + of msqrt. + + * mpz_impl_sqrt: Don't call "move", inline its functionality. + + * mdiv: Use MPN_COPY instead of memcpy. + * rpow, mpz_mul, mpz_mod_2exp: Likewise. + * pow.c: Likewise, and fix bug in the size arg. + + * xtom: Don't use mpz_alloc, inline needed code instead. Call + _mpz_set_str instead of mpz_set_str. + + * Makefile: Make two libraries, libmp.a and libgmp.a. + +Thu May 22 20:25:29 1991 Torbjorn Granlund (tege@zevs.sics.se) + + * Add manual to distribution. + * Fold in many missing routines descibed in the manual. + * Update Makefile. + +Wed May 22 13:48:46 1991 Torbjorn Granlund (tege@zevs.sics.se) + + * mpz_set_str: Make it handle 0x prefix OK. + +Sat May 18 18:31:02 1991 Torbjorn Granlund (tege@zevs.sics.se) + + * memory.c (_mp_default_reallocate): Swap OLD_SIZE and NEW_SIZE + arguments. + * mpz_realloc (_mpz_realloc): Swap in call to _mp_reallocate_func. + * min: Likewise. + +Thu May 16 20:43:05 1991 Torbjorn Granlund (tege@zevs.sics.se) + + * memory.c: Make the default allocations functions global. + * mp_set_fns (mp_set_memory_functions): Make a NULL pointer mean the + default memory function. + +Wed May 8 20:02:42 1991 Torbjorn Granlund (tege@zevs.sics.se) + + * mpz_div: Handle DEN the same as QUOT correctly by copying DEN->D + even if no normalization is needed. + * mpz_div: Rework reallocation scheme, to avoid excess copying. + + * mpz_sub_ui.c, mpz_add_ui.c: New files. + + * mpz_cmp.c, mpz_cmp_ui.c: New files. + + * mpz_mul_2exp: Handle zero input MINT correctly. + + * mpn_rshiftci: Don't handle shift counts > BITS_PER_MP_DIGIT. + + * mpz_out_raw.c, mpz_inp_raw.c: New files for raw I/O. + +Tue May 7 15:44:58 1991 Torbjorn Granlund (tege@zevs.sics.se) + + * mpn_rshift: Don't handle shift counts > BITS_PER_MP_DIGIT. + * mpz_div_2exp: Don't call _mpn_rshift with cnt > BITS_PER_MP_DIGIT. + * gcd, mpz_gcd: Likewise. + + * gcd, mpz_gcd: Handle common 2 factors correctly. + +Mon May 6 20:22:59 1991 Torbjorn Granlund (tege@zevs.sics.se) + + * gmp-impl.h (MPN_COPY): Inline a loop instead of calling memcpy. + + * gmp-impl.h, mpz_get_str, rpow: Swap DST and SRC in TMPCOPY* macros. + +Sun May 5 15:16:23 1991 Torbjorn Granlund (tege@zevs.sics.se) + + * mpz_div: Remove test for QUOT == 0. + +Sun Apr 28 20:21:04 1991 Torbjorn Granlund (tege@zevs.sics.se) + + * pow: Don't make MOD normalization in place, as it's a bad idea to + write on an input parameter. + * pow: Reduce BASE if it's > MOD. + * pow, mult, mpz_mul: Simplify realloc code. + +Sat Apr 27 21:03:11 1991 Torbjorn Granlund (tege@zevs.sics.se) + + * Install multplication using Karatsuba's algorithm as default. + +Fri Apr 26 01:03:57 1991 Torbjorn Granlund (tege@zevs.sics.se) + + * msqrt: Store in ROOT even for U==0, to make msqrt(0) defined. + + * mpz_div_2exp.c, mpz_mul_2exp.c: New files for shifting right and + left, respectively. + * gmp.h: Add definitions for mpz_div_2exp and mpz_mul_2exp. + + * mlshift.c, mrshift.c: Remove. + +Wed Apr 24 21:39:22 1991 Torbjorn Granlund (tege@zevs.sics.se) + + * mpn_mul: Check only for m2_size == 0 in function header. + +Mon Apr 22 01:31:57 1991 Torbjorn Granlund (tege@zevs.sics.se) + + * karatsuba.c: New file for Karatsuba's multplication algorithm. + + * mpz_random, mpz_init, mpz_mod_2exp: New files and functions. + + * mpn_cmp: Fix header comment. + +Sun Apr 21 00:10:44 1991 Torbjorn Granlund (tege@zevs.sics.se) + + * pow: Switch off initial base reduction. + +Sat Apr 20 22:06:05 1991 Torbjorn Granlund (tege@echnaton.sics.se) + + * mpz_get_str: Don't generate initial zeros for initial word. + Used to write outside of allocated storage. + +Mon Apr 15 15:48:08 1991 Torbjorn Granlund (tege@zevs.sics.se) + + * _mpz_realloc: Make it accept size in number of mp_digits. + * Most functions: Use new _mpz_realloc definition. + + * mpz_set_str: Remove calls _mp_free_func. + + * Most functions: Rename mpn_* to _mpn_*. Rename mpz_realloc to + _mpz_realloc. + * mpn_lshift: Redefine _mpn_lshift to only handle small shifts. + * mdiv, mpz_div, ...: Changes for new definition of _mpn_lshift. + * msqrt, mp*_*shift*: Define cnt as unsigned (for speed). + +Sat Apr 6 14:05:16 1991 Torbjorn Granlund (tege@musta.nada.kth.se) + + * mpn_mul: Multiply by the first digit in M2 in a special + loop instead of zeroing the product area. + + * mpz_abs.c: New file. + + * sdiv: Implement as mpz_div_si for speed. + + * mpn_add: Make it work for second source operand == 0. + + * msub: Negate the correct operand, i.e. V before swapping, not + the smaller of U and V! + * madd, msub: Update abs_* when swapping operands, and not after + (optimization). + +Fri Apr 5 00:19:36 1991 Torbjorn Granlund (tege@black.nada.kth.se) + + * mpn_sub: Make it work for subtrahend == 0. + + * madd, msub: Rewrite to minimize mpn_cmp calls. Ensure + mpn_cmp is called with positive sizes (used to be called + incorrectly with negative sizes sometimes). + + * msqrt: Make it divide by zero if fed with a negative number. + * Remove if statement at end of precision calculation that was + never true. + + * itom, mp.h: The argument is of type short, not int. + + * mpz_realloc, gmp.h: Make mpz_realloc return the new digit pointer. + + * mpz_get_str.c, mpz_set_str.c, mpz_new_str.c: Don't include mp.h. + + * Add COPYING to distribution. + + * mpz_div_ui.c, mpz_div_si.c, mpz_new_ui.c, mpz_new_si.c: New files. + +Fri Mar 15 00:26:29 1991 Torbjorn Granlund (tege@musta.nada.kth.se) + + * Add Copyleft headers to all files. + + * mpn_mul.c, mpn_div.c: Add header comments. + * mult.c, mdiv.c: Update header comments. + + * mpq_add.c, mpq_sub.c, mpq_div.c, mpq_new.c, mpq_new_ui.c, + mpq_free.c: New files for rational arithmetics. + + * mpn_lshift.c: Avoid writing the most significant word if it is 0. + + * mdiv.c: Call mpn_lshift for the normalization. + * mdiv.c: Remove #ifdefs. + + * Makefile: Add ChangeLog to DISTFILES. + + * mpn_div.c: Make the add_back code work (by removing abort()). + * mpn_div.c: Make it return if the quotient is size as compared + with the difference NSIZE - DSIZE. If the stored quotient is + larger than that, return 1, otherwise 0. + * gmp.h: Fix mpn_div declaration. + * mdiv.c: Adopt call to mpn_div. + * mpz_div.c: New file (developed from mdiv.c). + + * README: Update routine names. + +Thu Mar 14 18:45:28 1991 Torbjorn Granlund (tege@musta.nada.kth.se) + + * mpq_mul.c: New file for rational multplication. + + * gmp.h: Add definitions for rational arithmetics. + + * mpn_div: Kludge the case where the high numerator digit > the + high denominator digit. (This code is going to be optimized later.) + + * New files: gmp.h for GNU specific functions, gmp-common.h for + definitions common for mp.h and gmp.h. + + * Ensure mp.h just defines what BSD mp.h defines. + + * pow.c: Fix typo for bp allocation. + + * Rename natural number functions to mpn_*, integer functions to + mpz_*. + +Tue Mar 5 18:47:04 1991 Torbjorn Granlund (tege@musta.nada.kth.se) + + * mdiv.c (_mp_divide, case 2): Change test for estimate of Q from + "n0 >= r" to "n0 > r". + + * msqrt: Tune the increasing precision scheme, to do fewer steps. + +Tue Mar 3 18:50:10 1991 Torbjorn Granlund (tege@musta.nada.kth.se) + + * msqrt: Use the low level routines. Use low precision in the + beginning, and increase the precision as the result converges. + (This optimization gave a 6-fold speedup.) + +Local Variables: +mode: indented-text +left-margin: 8 +fill-column: 75 +version-control: never +End: diff --git a/contrib/libgmp/INSTALL b/contrib/libgmp/INSTALL new file mode 100644 index 0000000..38bfaa8 --- /dev/null +++ b/contrib/libgmp/INSTALL @@ -0,0 +1,154 @@ +INSTALLING GMP +============== + +These instructions are only for the impatient. Others should read the install +instructions in the manual, gmp.info. Use "info -f gmp.info", or, if you +don't have info, use type "C-h i g (gmp.info)Top" in emacs. + +Here are short instructions how to install MP, and some examples that help you +get started using MP. + +First, you need to compile, and optionally install, MP. Since you're +impatient, try this: + + ./configure; make + +If that fails, or you care about the performance of MP, you need to read the +full instructions in the chapter "Installing MP", in the manual. + +Next, you need to try some small test programs, for example the ones below. + +In MP programs, all variables need to be initialized before they are assigned, +and cleared out before program flow leaves the scope in which it was declared. +Here is an example of a program that reads two numbers from the command line, +multiplies them, and prints the result to stdout. + + #include <stdio.h> + #include <gmp.h> /* All MP programs need to include gmp.h */ + + main (int argc, char **argv) + { + mpz_t a, b, p; + + /* Initialize variables */ + mpz_init (a); + mpz_init (b); + mpz_init (p); + + /* Assign a and b from base 10 strings in argv */ + mpz_set_str (a, argv[1], 10); + mpz_set_str (b, argv[2], 10); + + /* Multiply a and b and put the result in p */ + mpz_mul (p, a, b); + + /* Print p in base 10 */ + mpz_out_str (stdout, 10, p); + fputc ('\n', stdout); + + /* Clear out variables */ + mpz_clear (a); + mpz_clear (b); + mpz_clear (p); + exit (0); + } + + +In practice, that example would be written like this instead: + + #include <stdio.h> + #include <gmp.h> + + main (int argc, char **argv) + { + mpz_t a, b, p; + + /* Initialize and assign a and b from base 10 strings in argv */ + mpz_init_set_str (a, argv[1], 10); + mpz_init_set_str (b, argv[2], 10); + /* Initialize p */ + mpz_init (p); + + /* Multiply a and b and put the result in p */ + mpz_mul (p, a, b); + + /* Print p in base 10 */ + mpz_out_str (stdout, 10, p); + fputc ('\n', stdout); + + /* Since we're about to exit, no need to clear out variables */ + exit (0); + } + +Finally, you have to compile your test program, and link it with the MP +library. Assuming your working directory is still the gmp source directory, +type: + + gcc -g -I. example.c libgmp.a + + +Now try to run the example: + + a.out 98365871231256752134 319378318340103345227 + 31415926535897932384618573336104570964418 + +The functions used here all operate on the domain of signed integers. +Functions operating on that domain have names starting with "mpz_". There are +many more such functions than used in these examples. See the chapter +"Integer Functions" in the manual, for a complete list. + +There are two other main classes of functions in MP. They operate on rational +numbers and floating-point numbers, respectively. The chapters "Rational +Number Functions", and "Floating-point Functions" documents these classes. + +To run a set of tests, do "make check". This will take a while. + +To create the printable documentation from the texinfo source, type "make +dvi". This requires the "tex" command to be available in your search path. + +To install the library, do "make install". + +If you decide to use MP, It is a good idea you read at least the chapter "MP +Basics" in the manual. + + +Known Build Problems +-------------------- + +Note that GCC 2.7.2 (as well as 2.6.3) for the RS/6000 and PowerPC can not +be used to compile GMP, due to a bug in GCC. If you want to use GCC, you +need to apply the patch at the end of this file, or use a later version of +the compiler. + +If you are on a Sequent Symmetry, use GAS instead of the system's assembler +due to the latter's serious bugs. + +The system compiler on NeXT is a massacred and old gcc, even if the +compiler calls itself cc. This compiler cannot be used to build GMP. You +need to get a real gcc, and install that before you compile GMP. (NeXT +might have fixed this in newer releases of their system.) + +Please report other problems to bug-gmp@prep.ai.mit.edu. + + +Patch to apply to GCC 2.6.3 and 2.7.2: + +*** config/rs6000/rs6000.md Sun Feb 11 08:22:11 1996 +--- config/rs6000/rs6000.md.new Sun Feb 18 03:33:37 1996 +*************** +*** 920,926 **** + (set (match_operand:SI 0 "gpc_reg_operand" "=r") + (not:SI (match_dup 1)))] + "" +! "nor. %0,%2,%1" + [(set_attr "type" "compare")]) + + (define_insn "" +--- 920,926 ---- + (set (match_operand:SI 0 "gpc_reg_operand" "=r") + (not:SI (match_dup 1)))] + "" +! "nor. %0,%1,%1" + [(set_attr "type" "compare")]) + + (define_insn "" diff --git a/contrib/libgmp/Makefile.in b/contrib/libgmp/Makefile.in new file mode 100644 index 0000000..6d7ff61 --- /dev/null +++ b/contrib/libgmp/Makefile.in @@ -0,0 +1,210 @@ +# Top Makefile for GNU MP +# Copyright (C) 1991, 1993, 1994, 1996 Free Software Foundation, Inc. + +# This file is part of the GNU MP Library. + +# The GNU MP Library is free software; you can redistribute it and/or modify +# it under the terms of the GNU Library General Public License as published by +# the Free Software Foundation; either version 2 of the License, or (at your +# option) any later version. + +# The GNU MP Library is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +# or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public +# License for more details. + +# You should have received a copy of the GNU Library General Public License +# along with the GNU MP Library; see the file COPYING.LIB. If not, write to +# the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, +# MA 02111-1307, USA. + +srcdir = . + +prefix = /usr/local + +exec_prefix = $(prefix) +libdir = $(exec_prefix)/lib +infodir = $(prefix)/info +includedir = $(prefix)/include + +CC = gcc +LOCAL_CC = $(CC) +CFLAGS = -g -O +XCFLAGS = +AR = ar +AR_FLAGS = rc +RANLIB_TEST = [ -f /usr/bin/ranlib -o -f /bin/ranlib ] +RANLIB = ranlib +SHELL = /bin/sh +INSTALL = $(srcdir)/install.sh -c +INSTALL_PROGRAM = $(INSTALL) +INSTALL_DATA = $(INSTALL) +MAKEINFO = makeinfo +MAKEINFOFLAGS = +TEXI2DVI = texi2dvi +LN = ln -s + +#### host and target specific makefile fragments come in here. +### + +SRCS = memory.c mp_set_fns.c mp_clz_tab.c version.c stack-alloc.c mp_bpl.c \ + extract-double.c insert-double.c +OBJS = memory.o mp_set_fns.o mp_clz_tab.o version.o stack-alloc.o mp_bpl.o \ + extract-double.o insert-double.o +FILES = gmp.h mp.h gmp-impl.h longlong.h urandom.h move-if-change \ + mkinstalldirs INSTALL COPYING.LIB ChangeLog Makefile.in \ + NEWS README SPEED TODO config.guess config.sub configure configure.in \ + gmp.info* gmp.texi texinfo.tex $(SRCS) + +INCLUDES = -I. -Impn -I$(srcdir) +FLAGS_TO_PASS = "CC=$(CC)" "CFLAGS=$(CFLAGS)" "XCFLAGS=$(XCFLAGS)" + +all: libgmp.a + +.c.o: + $(CC) -c $(INCLUDES) $(CFLAGS) $(XCFLAGS) $< + +libgmp.a: mpn/libmpn.a mpz/libmpz.a mpf/libmpf.a mpq/libmpq.a $(OBJS) + rm -rf tmpdir + mkdir tmpdir + for i in mpn mpz mpf mpq; \ + do \ + mkdir tmpdir/$$i; \ + ( cd tmpdir/$$i; $(AR) x ../../$$i/lib$$i.a ); \ + done + cp $(OBJS) tmpdir + cd tmpdir; $(AR) $(AR_FLAGS) $@ *.o */*.o + if $(RANLIB_TEST) ; then $(RANLIB) tmpdir/$@; else true; fi + mv tmpdir/$@ . + rm -rf tmpdir + +libmp.a: mpn/libmpn.a mpbsd/libmpbsd.a $(OBJS) + rm -rf tmpdir + mkdir tmpdir + for i in mpn mpbsd; \ + do \ + mkdir tmpdir/$$i; \ + ( cd tmpdir/$$i; $(AR) x ../../$$i/lib$$i.a ); \ + done + cp $(OBJS) tmpdir + cd tmpdir; $(AR) $(AR_FLAGS) $@ *.o */*.o + if $(RANLIB_TEST) ; then $(RANLIB) tmpdir/$@; else true; fi + mv tmpdir/$@ . + rm -rf tmpdir + +mpn/libmpn.a: force + cd mpn; $(MAKE) $(FLAGS_TO_PASS) libmpn.a +mpz/libmpz.a: force + cd mpz; $(MAKE) $(FLAGS_TO_PASS) libmpz.a +mpf/libmpf.a: force + cd mpf; $(MAKE) $(FLAGS_TO_PASS) libmpf.a +mpq/libmpq.a: force + cd mpq; $(MAKE) $(FLAGS_TO_PASS) libmpq.a +mpbsd/libmpbsd.a: force + cd mpbsd; $(MAKE) $(FLAGS_TO_PASS) libmpbsd.a + +check: libgmp.a + cd mpz/tests; $(MAKE) $(FLAGS_TO_PASS) check + cd mpq/tests; $(MAKE) $(FLAGS_TO_PASS) check + cd mpf/tests; $(MAKE) $(FLAGS_TO_PASS) check + +doc: gmp.dvi gmp.info + +info: $(srcdir)/gmp.info +$(srcdir)/gmp.info: $(srcdir)/gmp.texi + cd $(srcdir); $(MAKEINFO) gmp.texi + +dvi: gmp.dvi +gmp.dvi: $(srcdir)/gmp.texi + rm -f tmp.texi + $(LN) $(srcdir)/gmp.texi tmp.texi + TEXINPUTS=.:$(srcdir) $(TEXI2DVI) tmp.texi + rm -f tmp.texi + mv tmp.dvi gmp.dvi + rm -f tmp.* + +ps: gmp.ps +gmp.ps: gmp.dvi + dvips gmp.dvi -o gmp.ps + +html: gmp_toc.html +gmp_toc.html: $(srcdir)/gmp.texi + texi2html -acc -split_chapter $(srcdir)/gmp.texi + +# The semicolon is to prevent the install.sh -> install default rule +# from doing anything. Having it run true helps avoid problems and +# noise from versions of make which don't like to have null commands. +install: install-normal ; @true + +install-strip: install-normal +install-normal: installdirs libgmp.a gmp.info install-info-files + $(INSTALL_DATA) libgmp.a $(libdir)/libgmp.a + -chmod a-x $(libdir)/libgmp.a + $(INSTALL_DATA) $(srcdir)/gmp.h $(includedir)/gmp.h + -chmod a-x $(includedir)/gmp.h +install-bsdmp: installdirs libmp.a gmp.info install-info-files + $(INSTALL_DATA) libmp.a $(libdir)/libmp.a + -chmod a-x $(libdir)/libmp.a + $(INSTALL_DATA) $(srcdir)/mp.h $(includedir)/mp.h + -chmod a-x $(includedir)/mp.h +install-info-files: installdirs $(srcdir)/gmp.info + cd $(srcdir); for f in gmp.info*; \ + do $(INSTALL_DATA) $$f $(infodir)/$$f; done + -chmod a-x $(infodir)/gmp.info* + # Attempt to edit the info directory node + if $(SHELL) -c 'install-info --version' >/dev/null 2>&1; then \ + install-info --dir-file=$(infodir)/dir $(infodir)/gmp.info; \ + else true; fi + +installdirs: $(srcdir)/mkinstalldirs + $(srcdir)/mkinstalldirs $(includedir) $(libdir) $(infodir) + +uninstall: + rm -f $(libdir)/libgmp.a + rm -f $(includedir)/gmp.h + rm -f $(libdir)/libmp.a + rm -f $(includedir)/mp.h + rm -f $(infodir)/gmp.info* + +clean mostlyclean: + rm -f *.o libgmp.a libmp.a gmp.dvi gmp.ps tmp.* tmp-* + rm -f gmp.?? gmp.??s gmp.log gmp.toc gmp.*aux gmp*.html + -cd mpn; $(MAKE) $@ + -cd mpz; $(MAKE) $@ + -cd mpf; $(MAKE) $@ + -cd mpq; $(MAKE) $@ + -cd mpbsd; $(MAKE) $@ +distclean: clean + rm -f Makefile config.status + -cd mpn; $(MAKE) $@ + -cd mpz; $(MAKE) $@ + -cd mpf; $(MAKE) $@ + -cd mpq; $(MAKE) $@ + -cd mpbsd; $(MAKE) $@ +maintainer-clean: distclean + rm -f $(srcdir)/gmp.info* + +TAGS: force + cd $(srcdir); etags *.[ch] mp*/*.c mpn/generic/*.c >TAGS + +dist: + @echo "sorry, not supported target" + @exit 1 + +Makefile: $(srcdir)/Makefile.in $(host_makefile_frag) $(target_makefile_frag) + $(SHELL) ./config.status + +H = $(srcdir)/gmp.h $(srcdir)/gmp-impl.h mpn/gmp-mparam.h + +extract-double.o: $(srcdir)/extract-double.c $(H) +insert-double.o: $(srcdir)/insert-double.c $(H) +memory.o: $(srcdir)/memory.c $(H) +mp_bpl.o: $(srcdir)/mp_bpl.c +mp_clz_tab.o: $(srcdir)/mp_clz_tab.c +mp_set_fns.o: $(srcdir)/mp_set_fns.c $(H) +stack-alloc.o: $(srcdir)/stack-alloc.c $(srcdir)/stack-alloc.h +version.o: $(srcdir)/version.c + +force: +.PNONY: check install install-bsdmp install-info-files install-strip uninstall +.PHONY: doc clean distclean maintainer-clean force info dvi diff --git a/contrib/libgmp/NEWS b/contrib/libgmp/NEWS new file mode 100644 index 0000000..b61c840 --- /dev/null +++ b/contrib/libgmp/NEWS @@ -0,0 +1,56 @@ +NOTEWORTHY CHANGES IN GNU MP IN VERSION 2 + +* Division routines in the mpz class have changed. There are three classes of + functions, that rounds the quotient to -infinity, 0, and +infinity, + respectively. The first class of functions have names that begin with + mpz_fdiv (f is short for floor), the second class' names begin with mpz_tdiv + (t is short for trunc), and the third class' names begin with mpz_cdiv (c is + short for ceil). + + The old division routines beginning with mpz_m are similar to the new + mpz_fdiv, with the exception that some of the new functions return useful + values. + + The old function names can still be used. All the old functions names will + now do floor division, not trunc division as some of them used to. This was + changed to make the functions more compatible with common mathematical + practice. + + The mpz_mod and mpz_mod_ui functions now compute the mathematical mod + function. I.e., the sign of the 2nd argument is ignored. + +* The mpq assignment functions do not canonicalize their results. A new + function, mpq_canonicalize must be called by the user if the result is not + known to be canonical. +* The mpn functions are now documented. These functions are intended for + very time critical applications, or applications that need full control over + memory allocation. Note that the mpn interface is irregular and hard to + use. +* New functions for arbitrary precision floating point arithmetic. Names + begin with `mpf_'. Associated type mpf_t. +* New and improved mpz functions, including much faster GCD, fast exact + division (mpz_divexact), bit scan (mpz_scan0 and mpz_scan1), and number + theoretical functions like Jacobi (mpz_jacobi) and multiplicative inverse + (mpz_invert). +* New variable types (mpz_t and mpq_t) are available that makes syntax of + mpz and mpq calls nicer (no need for & before variables). The MP_INT and + MP_RAT types are still available for compatibility. +* Uses GNU configure. This makes it possible to choose target architecture + and CPU variant, and to compile into a separate object directory. +* Carefully optimized assembly for important inner loops. Support for DEC + Alpha, Amd 29000, HPPA 1.0 and 1.1, Intel pentium and generic x86, Intel + i960, Motorola MC68000, MC68020, MC88100, and MC88110, Motorola/IBM + PowerPC, National NS32000, IBM POWER, MIPS R3000, R4000, SPARCv7, + SuperSPARC, generic SPARCv8, and DEC VAX. Some support also for ARM, + Clipper, IBM ROMP (RT), and Pyramid AP/XP. +* Faster. Thanks to the assembler code, new algorithms, and general tuning. + In particular, the speed on machines without GCC is improved. +* Support for machines without alloca. +* Now under the LGPL. + +INCOMPATIBILITIES BETWEEN GMP 1 AND GMP 2 + +* mpq assignment functions do not canonicalize their results. +* mpz division functions round differently. +* mpz mod functions now really compute mod. +* mpz_powm and mpz_powm_ui now really use mod for reduction. diff --git a/contrib/libgmp/PROJECTS b/contrib/libgmp/PROJECTS new file mode 100644 index 0000000..75016bd --- /dev/null +++ b/contrib/libgmp/PROJECTS @@ -0,0 +1,270 @@ +IDEAS ABOUT THINGS TO WORK ON + +* mpq_cmp: Maybe the most sensible thing to do would be to multiply the, say, + 4 most significant limbs of each operand and compare them. If that is not + sufficient, do the same for 8 limbs, etc. + +* Write mpi, the Multiple Precision Interval Arithmetic layer. + +* Write `mpX_eval' that take lambda-like expressions and a list of operands. + +* As a general rule, recognize special operand values in mpz and mpf, and + use shortcuts for speed. Examples: Recognize (small or all) 2^n in + multiplication and division. Recognize small bases in mpz_pow_ui. + +* Implement lazy allocation? mpz->d == 0 would mean no allocation made yet. + +* Maybe store one-limb numbers according to Per Bothner's idea: + struct { + mp_ptr d; + union { + mp_limb val; /* if (d == NULL). */ + mp_size size; /* Length of data array, if (d != NULL). */ + } u; + }; + Problem: We can't normalize to that format unless we free the space + pointed to by d, and therefore small values will not be stored in a + canonical way. + +* Document complexity of all functions. + +* Add predicate functions mpz_fits_signedlong_p, mpz_fits_unsignedlong_p, + mpz_fits_signedint_p, etc. + + mpz_floor (mpz, mpq), mpz_trunc (mpz, mpq), mpz_round (mpz, mpq). + +* Better random number generators. There should be fast (like mpz_random), + very good (mpz_veryrandom), and special purpose (like mpz_random2). Sizes + in *bits*, not in limbs. + +* It'd be possible to have an interface "s = add(a,b)" with automatic GC. + If the mpz_xinit routine remembers the address of the variable we could + walk-and-mark the list of remembered variables, and free the space + occupied by the remembered variables that didn't get marked. Fairly + standard. + +* Improve speed for non-gcc compilers by defining umul_ppmm, udiv_qrnnd, + etc, to call __umul_ppmm, __udiv_qrnnd. A typical definition for + umul_ppmm would be + #define umul_ppmm(ph,pl,m0,m1) \ + {unsigned long __ph; (pl) = __umul_ppmm (&__ph, (m0), (m1)); (ph) = __ph;} + In order to maintain just one version of longlong.h (gmp and gcc), this + has to be done outside of longlong.h. + +Bennet Yee at CMU proposes: +* mpz_{put,get}_raw for memory oriented I/O like other *_raw functions. +* A function mpfatal that is called for exceptions. Let the user override + a default definition. + +* Make all computation mpz_* functions return a signed int indicating if the + result was zero, positive, or negative? + +* Implement mpz_cmpabs, mpz_xor, mpz_to_double, mpz_to_si, mpz_lcm, mpz_dpb, + mpz_ldb, various bit string operations. Also mpz_@_si for most @?? + +* Add macros for looping efficiently over a number's limbs: + MPZ_LOOP_OVER_LIMBS_INCREASING(num,limb) + { user code manipulating limb} + MPZ_LOOP_OVER_LIMBS_DECREASING(num,limb) + { user code manipulating limb} + +Brian Beuning proposes: + 1. An array of small primes + 3. A function to factor a mpz_t. [How do we return the factors? Maybe + we just return one arbitrary factor? In the latter case, we have to + use a data structure that records the state of the factoring routine.] + 4. A routine to look for "small" divisors of an mpz_t + 5. A 'multiply mod n' routine based on Montgomery's algorithm. + +Dough Lea proposes: + 1. A way to find out if an integer fits into a signed int, and if so, a + way to convert it out. + 2. Similarly for double precision float conversion. + 3. A function to convert the ratio of two integers to a double. This + can be useful for mixed mode operations with integers, rationals, and + doubles. + +Elliptic curve method description in the Chapter `Algorithms in Number +Theory' in the Handbook of Theoretical Computer Science, Elsevier, +Amsterdam, 1990. Also in Carl Pomerance's lecture notes on Cryptology and +Computational Number Theory, 1990. + +* Harald Kirsh suggests: + mpq_set_str (MP_RAT *r, char *numerator, char *denominator). + +* New function: mpq_get_ifstr (int_str, frac_str, base, + precision_in_som_way, rational_number). Convert RATIONAL_NUMBER to a + string in BASE and put the integer part in INT_STR and the fraction part + in FRAC_STR. (This function would do a division of the numerator and the + denominator.) + +* Should mpz_powm* handle negative exponents? + +* udiv_qrnnd: If the denominator is normalized, the n0 argument has very + little effect on the quotient. Maybe we can assume it is 0, and + compensate at a later stage? + +* Better sqrt: First calculate the reciprocal square root, then multiply by + the operand to get the square root. The reciprocal square root can be + obtained through Newton-Raphson without division. To compute sqrt(A), the + iteration is, + + 2 + x = x (3 - A x )/2. + i+1 i i + + The final result can be computed without division using, + + sqrt(A) = A x . + n + +* Newton-Raphson using multiplication: We get twice as many correct digits + in each iteration. So if we square x(k) as part of the iteration, the + result will have the leading digits in common with the entire result from + iteration k-1. A _mpn_mul_lowpart could help us take advantage of this. + +* Peter Montgomery: If 0 <= a, b < p < 2^31 and I want a modular product + a*b modulo p and the long long type is unavailable, then I can write + + typedef signed long slong; + typedef unsigned long ulong; + slong a, b, p, quot, rem; + + quot = (slong) (0.5 + (double)a * (double)b / (double)p); + rem = (slong)((ulong)a * (ulong)b - (ulong)p * (ulong)quot); + if (rem < 0} {rem += p; quot--;} + +* Speed modulo arithmetic, using Montgomery's method or my pre-inversion + method. In either case, special arithmetic calls would be needed, + mpz_mmmul, mpz_mmadd, mpz_mmsub, plus some kind of initialization + functions. Better yet: Write a new mpr layer. + +* mpz_powm* should not use division to reduce the result in the loop, but + instead pre-compute the reciprocal of the MOD argument and do reduced_val + = val-val*reciprocal(MOD)*MOD, or use Montgomery's method. + +* mpz_mod_2expplussi -- to reduce a bignum modulo (2**n)+s + +* It would be a quite important feature never to allocate more memory than + really necessary for a result. Sometimes we can achieve this cheaply, by + deferring reallocation until the result size is known. + +* New macro in longlong.h: shift_rhl that extracts a word by shifting two + words as a unit. (Supported by i386, i860, HP-PA, POWER, 29k.) Useful + for shifting multiple precision numbers. + +* The installation procedure should make a test run of multiplication to + decide the threshold values for algorithm switching between the available + methods. + +* Fast output conversion of x to base B: + 1. Find n, such that (B^n > x). + 2. Set y to (x*2^m)/(B^n), where m large enough to make 2^n ~~ B^n + 3. Multiply the low half of y by B^(n/2), and recursively convert the + result. Truncate the low half of y and convert that recursively. + Complexity: O(M(n)log(n))+O(D(n))! + +* Improve division using Newton-Raphson. Check out "Newton Iteration and + Integer Division" by Stephen Tate in "Synthesis of Parallel Algorithms", + Morgan Kaufmann, 1993 ("beware of some errors"...) + +* Improve implementation of Karatsuba's algorithm. For most operand sizes, + we can reduce the number of operations by splitting differently. + +* Faster multiplication: The best approach is to first implement Toom-Cook. + People report that it beats Karatsuba's algorithm already at about 100 + limbs. FFT would probably never beat a well-written Toom-Cook (not even for + millions of bits). + +FFT: +{ + * Multiplication could be done with Montgomery's method combined with + the "three primes" method described in Lipson. Maybe this would be + faster than to Nussbaumer's method with 3 (simple) moduli? + + * Maybe the modular tricks below are not needed: We are using very + special numbers, Fermat numbers with a small base and a large exponent, + and maybe it's possible to just subtract and add? + + * Modify Nussbaumer's convolution algorithm, to use 3 words for each + coefficient, calculating in 3 relatively prime moduli (e.g. + 0xffffffff, 0x100000000, and 0x7fff on a 32-bit computer). Both all + operations and CRR would be very fast with such numbers. + + * Optimize the Schoenhage-Stassen multiplication algorithm. Take advantage + of the real valued input to save half of the operations and half of the + memory. Use recursive FFT with large base cases, since recursive FFT has + better memory locality. A normal FFT get 100% cache misses for large + enough operands. + + * In the 3-prime convolution method, it might sometimes be a win to use 2, + 3, or 5 primes. Imagine that using 3 primes would require a transform + length of 2^n. But 2 primes might still sometimes give us correct + results with that same transform length, or 5 primes might allow us to + decrease the transform size to 2^(n-1). + + To optimize floating-point based complex FFT we have to think of: + + 1. The normal implementation accesses all input exactly once for each of + the log(n) passes. This means that we will get 0% cache hit when n > + our cache. Remedy: Reorganize computation to compute partial passes, + maybe similar to a standard recursive FFT implementation. Use a large + `base case' to make any extra overhead of this organization negligible. + + 2. Use base-4, base-8 and base-16 FFT instead of just radix-2. This can + reduce the number of operations by 2x. + + 3. Inputs are real-valued. According to Knuth's "Seminumerical + Algorithms", exercise 4.6.4-14, we can save half the memory and half + the operations if we take advantage of that. + + 4. Maybe make it possible to write the innermost loop in assembly, since + that could win us another 2x speedup. (If we write our FFT to avoid + cache-miss (see #1 above) it might be logical to write the `base case' + in assembly.) + + 5. Avoid multiplication by 1, i, -1, -i. Similarly, optimize + multiplication by (+-\/2 +- i\/2). + + 6. Put as many bits as possible in each double (but don't waste time if + that doesn't make the transform size become smaller). + + 7. For n > some large number, we will get accuracy problems because of the + limited precision of our floating point arithmetic. This can easily be + solved by using the Karatsuba trick a few times until our operands + become small enough. + + 8. Precompute the roots-of-unity and store them in a vector. +} + +* When a division result is going to be just one limb, (i.e. nsize-dsize is + small) normalization could be done in the division loop. + +* Never allocate temporary space for a source param that overlaps with a + destination param needing reallocation. Instead malloc a new block for + the destination (and free the source before returning to the caller). + +* Parallel addition. Since each processors have to tell it is ready to the + next processor, we can use simplified synchronization, and actually write + it in C: For each processor (apart from the least significant): + + while (*svar != my_number) + ; + *svar = my_number + 1; + + The least significant processor does this: + + *svar = my_number + 1; /* i.e., *svar = 1 */ + + Before starting the addition, one processor has to store 0 in *svar. + + Other things to think about for parallel addition: To avoid false + (cache-line) sharing, allocate blocks on cache-line boundaries. + + +Local Variables: +mode: text +fill-column: 77 +fill-prefix: " " +version-control: never +End: diff --git a/contrib/libgmp/README b/contrib/libgmp/README new file mode 100644 index 0000000..3afa677 --- /dev/null +++ b/contrib/libgmp/README @@ -0,0 +1,137 @@ + THE GNU MP LIBRARY + + +GNU MP is a library for arbitrary precision arithmetic, operating on signed +integers, rational numbers, and floating point numbers. It has a rich set +of functions, and the functions have a regular interface. + +GNU MP is designed to be as fast as possible, both for small operands and for +huge operands. The speed is achieved by using fullwords as the basic +arithmetic type, by using fast algorithms, by carefully optimized assembly +code for the most common inner loops for a lots of CPUs, and by a general +emphasis on speed (instead of simplicity or elegance). + +The speed of GNU MP is believed to be faster than any other similar library. +The advantage for GNU MP increases with the operand sizes for certain +operations, since GNU MP in many cases has asymptotically faster algorithms. + + + GETTING STARTED + +First, you have to configure and compiler GNU MP. Simply typing + + ./configure; make + +will normally do a reasonable job, but will not give optimal library +execution speed. So unless you're very unpatient, please read the detailed +instructions in the file INSTALL or in gmp.texi. + +Once you have compiled the library, you should write some small example, and +make sure you can compile them. A typical compilation command is this: + + gcc -g your-file.c -I<gmp-source-dir> <gmp-bin-dir>libgmp.a -lm + +If you have installed the library, you can simply do: + + gcc -g your-file.c -lgmp -lm + +The -lm is normally not needed, since only a few functions in GNU MP use the +math library. + +Here is a sample program that declares 2 variables, initializes them as +required, and sets one of them from a signed integer, and the other from a +string of digits. It then prints the product of the two numbers in base 10. + + #include <stdio.h> + #include "gmp.h" + + main () + { + mpz_t a, b, p; + + mpz_init (a); /* initialize variables */ + mpz_init (b); + mpz_init (p); + + mpz_set_si (a, 756839); /* assign variables */ + mpz_set_str (b, "314159265358979323846", 0); + mpz_mul (p, a, b); /* generate product */ + mpz_out_str (stdout, 10, p); /* print number without newline */ + puts (""); /* print newline */ + + mpz_clear (a); /* clear out variables */ + mpz_clear (b); + mpz_clear (p); + + exit (0); + } + +This might look tedious, with all initializing and clearing. Fortunately +some of these operations can be combined, and other operations can often be +avoided. The example above would be written differently by an experienced +GNU MP user: + + #include <stdio.h> + #include "gmp.h" + + main () + { + mpz_t b, p; + + mpz_init (p); + + mpz_init_set_str (b, "314159265358979323846", 0); + mpz_mul_ui (p, b, 756839); /* generate product */ + mpz_out_str (stdout, 10, p); /* print number without newline */ + puts (""); /* print newline */ + + exit (0); + } + + + OVERVIEW OF GNU MP + +There are five classes of functions in GNU MP. + + 1. Signed integer arithmetic functions, mpz_*. These functions are intended + to be easy to use, with their regular interface. The associated type is + `mpz_t'. + + 2. Rational arithmetic functions, mpq_*. For now, just a small set of + functions necessary for basic rational arithmetics. The associated type + is `mpq_t'. + + 3. Floating-point arithmetic functions, mpf_*. If the C type `double' + doesn't give enough precision for your application, declare your + variables as `mpf_t' instead, set the precision to any number desired, + and call the functions in the mpf class for the arithmetic operations. + + 4. Positive-integer, hard-to-use, very low overhead functions are in the + mpn_* class. No memory management is performed. The caller must ensure + enough space is available for the results. The set of functions is not + regular, nor is the calling interface. These functions accept input + arguments in the form of pairs consisting of a pointer to the least + significant word, and a integral size telling how many limbs (= words) + the pointer points to. + + Almost all calculations, in the entire package, are made by calling these + low-level functions. + + 5. Berkeley MP compatible functions. + + To use these functions, include the file "mp.h". You can test if you are + using the GNU version by testing if the symbol __GNU_MP__ is defined. + +For more information on how to use GNU MP, please refer to the documentation. +It is composed from the file gmp.texi, and can be displayed on the screen or +printed. How to do that, as well how to build the library, is described in +the INSTALL file in this directory. + + + REPORTING BUGS + +If you find a bug in the library, please make sure to tell us about it! + +Report bugs and propose modifications and enhancements to +bug-gmp@prep.ai.mit.edu. What information is needed in a good bug report is +described in the manual. diff --git a/contrib/libgmp/SPEED b/contrib/libgmp/SPEED new file mode 100644 index 0000000..e888e17 --- /dev/null +++ b/contrib/libgmp/SPEED @@ -0,0 +1,156 @@ +============================================================================== +Cycle counts and throughput for low-level routines in GNU MP as currently +implemented. + +A range means that the timing is data-dependent. The slower number of such +an interval is usually the best performance estimate. + +The throughput value, measured in Gb/s (gigabits per second) has a meaning +only for comparison between CPUs. + +A star before a line means that all values on that line are estimates. A +star before a number means that that number is an estimate. A `p' before a +number means that the code is not complete, but the timing is believed to be +accurate. + + | mpn_lshift mpn_add_n mpn_mul_1 mpn_addmul_1 + | mpn_rshift mpn_sub_n mpn_submul_1 +------------+----------------------------------------------------------------- +DEC/Alpha | +EV4 | 4.75 cycles/64b 7.75 cycles/64b 42 cycles/64b 42 cycles/64b + 200MHz | 2.7 Gb/s 1.65 Gb/s 20 Gb/s 20 Gb/s +EV5 old code| 4.0 cycles/64b 5.5 cycles/64b 18 cycles/64b 18 cycles/64b + 267MHz | 4.27 Gb/s 3.10 Gb/s 61 Gb/s 61 Gb/s + 417MHz | 6.67 Gb/s 4.85 Gb/s 95 Gb/s 95 Gb/s +EV5 tuned | 3.25 cycles/64b 4.75 cycles/64b + 267MHz | 5.25 Gb/s 3.59 Gb/s as above + 417MHz | 8.21 Gb/s 5.61 Gb/s +------------+----------------------------------------------------------------- +Sun/SPARC | +SPARC v7 | 14.0 cycles/32b 8.5 cycles/32b 37-54 cycl/32b 37-54 cycl/32b +SuperSPARC | 3 cycles/32b 2.5 cycles/32b 8.2 cycles/32b 10.8 cycles/32b + 50MHz | 0.53 Gb/s 0.64 Gb/s 6.2 Gb/s 4.7 Gb/s +**SuperSPARC| tuned addmul and submul will take: 9.25 cycles/32b +MicroSPARC2 | ? 6.65 cycles/32b 30 cycles/32b 31.5 cycles/32b + 110MHz | ? 0.53 Gb/s 3.75 Gb/s 3.58 Gb/s +SuperSPARC2 | ? ? ? ? +Ultra/32 (4)| 2.5 cycles/32b 6.5 cycles/32b 13-27 cyc/32b 16-30 cyc/32b + 182MHz | 2.33 Gb/s 0.896 Gb/s 14.3-6.9 Gb/s +Ultra/64 (5)| 2.5 cycles/64b 10 cycles/64b 40-70 cyc/64b 46-76 cyc/64b + 182MHz | 4.66 Gb/s 1.16 Gb/s 18.6-11 Gb/s +HalSPARC64 | ? ? ? ? +------------+----------------------------------------------------------------- +SGI/MIPS | +R3000 | 6 cycles/32b 9.25 cycles/32b 16 cycles/32b 16 cycles/32b + 40MHz | 0.21 Gb/s 0.14 Gb/s 2.56 Gb/s 2.56 Gb/s +R4400/32 | 8.6 cycles/32b 10 cycles/32b 16-18 19-21 + 200MHz | 0.74 Gb/s 0.64 Gb/s 13-11 Gb/s 11-9.6 Gb/s +*R4400/64 | 8.6 cycles/64b 10 cycles/64b 22 cycles/64b 22 cycles/64b + *200MHz | 1.48 Gb/s 1.28 Gb/s 37 Gb/s 37 Gb/s +R4600/32 | 6 cycles/64b 9.25 cycles/32b 15 cycles/32b 19 cycles/32b + 134MHz | 0.71 Gb/s 0.46 Gb/s 9.1 Gb/s 7.2 Gb/s +R4600/64 | 6 cycles/64b 9.25 cycles/64b ? ? + 134MHz | 1.4 Gb/s 0.93 Gb/s ? ? +R8000/64 | 3 cycles/64b 4.6 cycles/64b 8 cycles/64b 8 cycles/64b + 75MHz | 1.6 Gb/s 1.0 Gb/s 38 Gb/s 38 Gb/s +*R10000/64 | 2 cycles/64b 3 cycles/64b 11 cycles/64b 11 cycles/64b + *200MHz | 6.4 Gb/s 4.27 Gb/s 74 Gb/s 74 Gb/s + *250MHz | 8.0 Gb/s 5.33 Gb/s 93 Gb/s 93 Gb/s +------------+----------------------------------------------------------------- +Motorola | +MC68020 | ? 24 cycles/32b 62 cycles/32b 70 cycles/32b +MC68040 | ? 6 cycles/32b 24 cycles/32b 25 cycles/32b +MC88100 | >5 cycles/32b 4.6 cycles/32b 16/21 cyc/32b p 18/23 cyc/32b +MC88110 wt | ? 3.75 cycles/32b 6 cycles/32b 8.5 cyc/32b +*MC88110 wb | ? 2.25 cycles/32b 4 cycles/32b 5 cycles/32b +------------+----------------------------------------------------------------- +HP/PA-RISC | +PA7000 | 4 cycles/32b 5 cycles/32b 9 cycles/32b 11 cycles/32b + 67MHz | 0.53 Gb/s 0.43 Gb/s 7.6 Gb/s 6.2 Gb/s +PA7100 | 3.25 cycles/32b 4.25 cycles/32b 7 cycles/32b 8 cycles/32b + 99MHz | 0.97 Gb/s 0.75 Gb/s 14 Gb/s 12.8 Gb/s +PA7100LC | ? ? ? ? +PA7200 (3) | 3 cycles/32b 4 cycles/32b 7 cycles/32b 6.5 cycles/32b + 100MHz | 1.07 Gb/s 0.80 14 Gb/s 15.8 Gb/s +PA7300LC | ? ? ? ? +*PA8000 | 3 cycles/64b 4 cycles/64b 7 cycles/64b 6.5 cycles/64b + 180MHz | 3.84 Gb/s 2.88 Gb/s 105 Gb/s 113 Gb/s +------------+----------------------------------------------------------------- +Intel/x86 | +386DX | 20 cycles/32b 17 cycles/32b 41-70 cycl/32b 50-79 cycl/32b + 16.7MHz | 0.027 Gb/s 0.031 Gb/s 0.42-0.24 Gb/s 0.34-0.22 Gb/s +486DX | ? ? ? ? +486DX4 | 9.5 cycles/32b 9.25 cycles/32b 17-23 cycl/32b 20-26 cycl/32b + 100MHz | 0.34 Gb/s 0.35 Gb/s 6.0-4.5 Gb/s 5.1-3.9 Gb/s +Pentium | 2/6 cycles/32b 2.5 cycles/32b 13 cycles/32b 14 cycles/32b + 167MHz | 2.7/0.89 Gb/s 2.1 Gb/s 13.1 Gb/s 12.2 Gb/s +Pentium Pro | 2.5 cycles/32b 3.5 cycles/32b 6 cycles/32b 9 cycles/32b + 200MHz | 2.6 Gb/s 1.8 Gb/s 34 Gb/s 23 Gb/s +------------+----------------------------------------------------------------- +IBM/POWER | +RIOS 1 | 3 cycles/32b 4 cycles/32b 11.5-12.5 c/32b 14.5/15.5 c/32b +RIOS 2 | 2 cycles/32b 2 cycles/32b 7 cycles/32b 8.5 cycles/32b +------------+----------------------------------------------------------------- +PowerPC | +PPC601 (1) | 3 cycles/32b 6 cycles/32b 11-16 cycl/32b 14-19 cycl/32b +PPC601 (2) | 5 cycles/32b 6 cycles/32b 13-22 cycl/32b 16-25 cycl/32b + 67MHz (2) | 0.43 Gb/s 0.36 Gb/s 5.3-3.0 Gb/s 4.3-2.7 Gb/s +PPC603 | ? ? ? ? +*PPC604 | 2 3 2 3 + *167MHz | 57 Gb/s +PPC620 | ? ? ? ? +------------+----------------------------------------------------------------- +Tege | +Model 1 | 2 cycles/64b 3 cycles/64b 2 cycles/64b 3 cycles/64b + 250MHz | 8 Gb/s 5.3 Gb/s 500 Gb/s 340 Gb/s + 500MHz | 16 Gb/s 11 Gb/s 1000 Gb/s 680 Gb/s +____________|_________________________________________________________________ +(1) Using POWER and PowerPC instructions +(2) Using only PowerPC instructions +(3) Actual timing for shift/add/sub depends on code alignment. PA7000 code + is smaller and therefore often faster on this CPU. +(4) Multiplication routines modified for bogus UltraSPARC early-out + optimization. Smaller operand is put in rs1, not rs2 as it should + according to the SPARC architecture manuals. +(5) Preliminary timings, since there is no stable 64-bit environment. +(6) Use mulu.d at least for mpn_lshift. With mak/extu/or, we can only get + to 2 cycles/32b. + +============================================================================= +Estimated theoretical asymptotic cycle counts for low-level routines: + + | mpn_lshift mpn_add_n mpn_mul_1 mpn_addmul_1 + | mpn_rshift mpn_sub_n mpn_submul_1 +------------+----------------------------------------------------------------- +DEC/Alpha | +EV4 | 3 cycles/64b 5 cycles/64b 42 cycles/64b 42 cycles/64b +EV5 | 3 cycles/64b 4 cycles/64b 18 cycles/64b 18 cycles/64b +------------+----------------------------------------------------------------- +Sun/SPARC | +SuperSPARC | 2.5 cycles/32b 2 cycles/32b 8 cycles/32b 9 cycles/32b +------------+----------------------------------------------------------------- +SGI/MIPS | +R4400/32 | 5 cycles/64b 8 cycles/64b 16 cycles/64b 16 cycles/64b +R4400/64 | 5 cycles/64b 8 cycles/64b 22 cycles/64b 22 cycles/64b +R4600 | +------------+----------------------------------------------------------------- +HP/PA-RISC | +PA7100 | 3 cycles/32b 4 cycles/32b 6.5 cycles/32b 7.5 cycles/32b +PA7100LC | +------------+----------------------------------------------------------------- +Motorola | +MC88110 | 1.5 cyc/32b (6) 1.5 cycle/32b 1.5 cycles/32b 2.25 cycles/32b +------------+----------------------------------------------------------------- +Intel/x86 | +486DX4 | +Pentium P5x | 5 cycles/32b 2 cycles/32b 11.5 cycles/32b 13 cycles/32b +Pentium Pro | 2 cycles/32b 3 cycles/32b 4 cycles/32b 6 cycles/32b +------------+----------------------------------------------------------------- +IBM/POWER | +RIOS 1 | 3 cycles/32b 4 cycles/32b +RIOS 2 | 1.5 cycles/32b 2 cycles/32b 4.5 cycles/32b 5.5 cycles/32b +------------+----------------------------------------------------------------- +PowerPC | +PPC601 (1) | 3 cycles/32b ?4 cycles/32b +PPC601 (2) | 4 cycles/32b ?4 cycles/32b +____________|_________________________________________________________________ diff --git a/contrib/libgmp/config.guess b/contrib/libgmp/config.guess new file mode 100755 index 0000000..afd200a --- /dev/null +++ b/contrib/libgmp/config.guess @@ -0,0 +1,592 @@ +#! /bin/sh +# Attempt to guess a canonical system name. +# Copyright (C) 1992, 93, 94, 95, 1996 Free Software Foundation, Inc. +# +# This file is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +# +# As a special exception to the GNU General Public License, if you +# distribute this file as part of a program that contains a +# configuration script generated by Autoconf, you may include it under +# the same distribution terms that you use for the rest of that program. + +# Written by Per Bothner <bothner@cygnus.com>. +# The master version of this file is at the FSF in /home/gd/gnu/lib. +# +# This script attempts to guess a canonical system name similar to +# config.sub. If it succeeds, it prints the system name on stdout, and +# exits with 0. Otherwise, it exits with 1. +# +# The plan is that this can be called by configure scripts if you +# don't specify an explicit system type (host/target name). +# +# Only a few systems have been added to this list; please add others +# (but try to keep the structure clean). +# + +# This is needed to find uname on a Pyramid OSx when run in the BSD universe. +# (ghazi@noc.rutgers.edu 8/24/94.) +if (test -f /.attbin/uname) >/dev/null 2>&1 ; then + PATH=$PATH:/.attbin ; export PATH +fi + +UNAME_MACHINE=`(uname -m) 2>/dev/null` || UNAME_MACHINE=unknown +UNAME_RELEASE=`(uname -r) 2>/dev/null` || UNAME_RELEASE=unknown +UNAME_SYSTEM=`(uname -s) 2>/dev/null` || UNAME_SYSTEM=unknown +UNAME_VERSION=`(uname -v) 2>/dev/null` || UNAME_VERSION=unknown + +trap 'rm -f dummy.c dummy.o dummy; exit 1' 1 2 15 + +# Note: order is significant - the case branches are not exclusive. + +case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in + alpha:OSF1:[VX]*:*) + # After 1.2, OSF1 uses "V1.3" for uname -r. + # After 4.x, OSF1 uses "X4.x" for uname -r. + echo alpha-dec-osf`echo ${UNAME_RELEASE} | sed -e 's/^[VX]//'` + exit 0 ;; + alpha:OSF1:*:*) + # 1.2 uses "1.2" for uname -r. + echo alpha-dec-osf${UNAME_RELEASE} + exit 0 ;; + 21064:Windows_NT:50:3) + echo alpha-dec-winnt3.5 + exit 0 ;; + Amiga*:UNIX_System_V:4.0:*) + echo m68k-cbm-sysv4 + exit 0;; + amiga:NetBSD:*:*) + echo m68k-cbm-netbsd${UNAME_RELEASE} + exit 0 ;; + arm:RISC*:1.[012]*:*|arm:riscix:1.[012]*:*) + echo arm-acorn-riscix${UNAME_RELEASE} + exit 0;; + Pyramid*:OSx*:*:*) + if test "`(/bin/universe) 2>/dev/null`" = att ; then + echo pyramid-pyramid-sysv3 + else + echo pyramid-pyramid-bsd + fi + exit 0 ;; + sun4*:SunOS:5.*:*) + echo sparc-sun-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + exit 0 ;; + i86pc:SunOS:5.*:*) + echo i386-unknown-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + exit 0 ;; + sun4*:SunOS:6*:*) + # According to config.sub, this is the proper way to canonicalize + # SunOS6. Hard to guess exactly what SunOS6 will be like, but + # it's likely to be more like Solaris than SunOS4. + echo sparc-sun-solaris3`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + exit 0 ;; + sun4*:SunOS:*:*) + case "`/usr/bin/arch -k`" in + Series*|S4*) + UNAME_RELEASE=`uname -v` + ;; + esac + # Japanese Language versions have a version number like `4.1.3-JL'. + echo sparc-sun-sunos`echo ${UNAME_RELEASE}|sed -e 's/-/_/'` + exit 0 ;; + sun3*:SunOS:*:*) + echo m68k-sun-sunos${UNAME_RELEASE} + exit 0 ;; + atari*:NetBSD:*:*) + echo m68k-atari-netbsd${UNAME_RELEASE} + exit 0 ;; + sun3*:NetBSD:*:*) + echo m68k-sun-netbsd${UNAME_RELEASE} + exit 0 ;; + mac68k:NetBSD:*:*) + echo m68k-apple-netbsd${UNAME_RELEASE} + exit 0 ;; + RISC*:ULTRIX:*:*) + echo mips-dec-ultrix${UNAME_RELEASE} + exit 0 ;; + VAX*:ULTRIX*:*:*) + echo vax-dec-ultrix${UNAME_RELEASE} + exit 0 ;; + mips:*:4*:UMIPS) + echo mips-mips-riscos4sysv + exit 0 ;; + mips:*:5*:RISCos) + echo mips-mips-riscos${UNAME_RELEASE} + exit 0 ;; + Night_Hawk:Power_UNIX:*:*) + echo powerpc-harris-powerunix + exit 0 ;; + m88k:CX/UX:7*:*) + echo m88k-harris-cxux7 + exit 0 ;; + m88k:*:4*:R4*) + echo m88k-motorola-sysv4 + exit 0 ;; + m88k:*:3*:R3*) + echo m88k-motorola-sysv3 + exit 0 ;; + AViiON:dgux:*:*) + # DG/UX returns AViiON for all architectures + UNAME_PROCESSOR=`uname -p` + if [ $UNAME_PROCESSOR = mc88100 -o $UNAME_PROCESSOR = mc88100 ] ; then + if [ ${TARGET_BINARY_INTERFACE}x = m88kdguxelfx \ + -o ${TARGET_BINARY_INTERFACE}x = x ] ; then + echo m88k-dg-dgux${UNAME_RELEASE} + else + echo m88k-dg-dguxbcs${UNAME_RELEASE} + fi + else echo i586-dg-dgux${UNAME_RELEASE} + fi + exit 0 ;; + M88*:DolphinOS:*:*) # DolphinOS (SVR3) + echo m88k-dolphin-sysv3 + exit 0 ;; + M88*:*:R3*:*) + # Delta 88k system running SVR3 + echo m88k-motorola-sysv3 + exit 0 ;; + XD88*:*:*:*) # Tektronix XD88 system running UTekV (SVR3) + echo m88k-tektronix-sysv3 + exit 0 ;; + Tek43[0-9][0-9]:UTek:*:*) # Tektronix 4300 system running UTek (BSD) + echo m68k-tektronix-bsd + exit 0 ;; + *:IRIX*:*:*) + echo mips-sgi-irix`echo ${UNAME_RELEASE}|sed -e 's/-/_/g'` + exit 0 ;; + ????????:AIX?:[12].1:2) # AIX 2.2.1 or AIX 2.1.1 is RT/PC AIX. + echo romp-ibm-aix # uname -m gives an 8 hex-code CPU id + exit 0 ;; # Note that: echo "'`uname -s`'" gives 'AIX ' + i[34]86:AIX:*:*) + echo i386-ibm-aix + exit 0 ;; + *:AIX:2:3) + if grep bos325 /usr/include/stdio.h >/dev/null 2>&1; then + sed 's/^ //' << EOF >dummy.c + #include <sys/systemcfg.h> + + main() + { + if (!__power_pc()) + exit(1); + puts("powerpc-ibm-aix3.2.5"); + exit(0); + } +EOF + ${CC-cc} dummy.c -o dummy && ./dummy && rm dummy.c dummy && exit 0 + rm -f dummy.c dummy + echo rs6000-ibm-aix3.2.5 + elif grep bos324 /usr/include/stdio.h >/dev/null 2>&1; then + echo rs6000-ibm-aix3.2.4 + else + echo rs6000-ibm-aix3.2 + fi + exit 0 ;; + *:AIX:*:4) + if /usr/sbin/lsattr -EHl proc0 | grep POWER >/dev/null 2>&1; then + IBM_ARCH=rs6000 + else + IBM_ARCH=powerpc + fi + if [ -x /usr/bin/oslevel ] ; then + IBM_REV=`/usr/bin/oslevel` + else + IBM_REV=4.${UNAME_RELEASE} + fi + echo ${IBM_ARCH}-ibm-aix${IBM_REV} + exit 0 ;; + *:AIX:*:*) + echo rs6000-ibm-aix + exit 0 ;; + ibmrt:4.4BSD:*|romp-ibm:BSD:*) + echo romp-ibm-bsd4.4 + exit 0 ;; + ibmrt:*BSD:*|romp-ibm:BSD:*) # covers RT/PC NetBSD and + echo romp-ibm-bsd${UNAME_RELEASE} # 4.3 with uname added to + exit 0 ;; # report: romp-ibm BSD 4.3 + *:BOSX:*:*) + echo rs6000-bull-bosx + exit 0 ;; + DPX/2?00:B.O.S.:*:*) + echo m68k-bull-sysv3 + exit 0 ;; + 9000/[34]??:4.3bsd:1.*:*) + echo m68k-hp-bsd + exit 0 ;; + hp300:4.4BSD:*:* | 9000/[34]??:4.3bsd:2.*:*) + echo m68k-hp-bsd4.4 + exit 0 ;; + 9000/[3478]??:HP-UX:*:*) + case "${UNAME_MACHINE}" in + 9000/31? ) HP_ARCH=m68000 ;; + 9000/[34]?? ) HP_ARCH=m68k ;; + 9000/7?? | 9000/8?[679] ) HP_ARCH=hppa1.1 ;; + 9000/8?? ) HP_ARCH=hppa1.0 ;; + esac + HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'` + echo ${HP_ARCH}-hp-hpux${HPUX_REV} + exit 0 ;; + 3050*:HI-UX:*:*) + sed 's/^ //' << EOF >dummy.c + #include <unistd.h> + int + main () + { + long cpu = sysconf (_SC_CPU_VERSION); + /* The order matters, because CPU_IS_HP_MC68K erroneously returns + true for CPU_PA_RISC1_0. CPU_IS_PA_RISC returns correct + results, however. */ + if (CPU_IS_PA_RISC (cpu)) + { + switch (cpu) + { + case CPU_PA_RISC1_0: puts ("hppa1.0-hitachi-hiuxwe2"); break; + case CPU_PA_RISC1_1: puts ("hppa1.1-hitachi-hiuxwe2"); break; + case CPU_PA_RISC2_0: puts ("hppa2.0-hitachi-hiuxwe2"); break; + default: puts ("hppa-hitachi-hiuxwe2"); break; + } + } + else if (CPU_IS_HP_MC68K (cpu)) + puts ("m68k-hitachi-hiuxwe2"); + else puts ("unknown-hitachi-hiuxwe2"); + exit (0); + } +EOF + ${CC-cc} dummy.c -o dummy && ./dummy && rm dummy.c dummy && exit 0 + rm -f dummy.c dummy + echo unknown-hitachi-hiuxwe2 + exit 0 ;; + 9000/7??:4.3bsd:*:* | 9000/8?[79]:4.3bsd:*:* ) + echo hppa1.1-hp-bsd + exit 0 ;; + 9000/8??:4.3bsd:*:*) + echo hppa1.0-hp-bsd + exit 0 ;; + hp7??:OSF1:*:* | hp8?[79]:OSF1:*:* ) + echo hppa1.1-hp-osf + exit 0 ;; + hp8??:OSF1:*:*) + echo hppa1.0-hp-osf + exit 0 ;; + parisc*:Lites*:*:*) + echo hppa1.1-hp-lites + exit 0 ;; + C1*:ConvexOS:*:* | convex:ConvexOS:C1*:*) + echo c1-convex-bsd + exit 0 ;; + C2*:ConvexOS:*:* | convex:ConvexOS:C2*:*) + if getsysinfo -f scalar_acc + then echo c32-convex-bsd + else echo c2-convex-bsd + fi + exit 0 ;; + C34*:ConvexOS:*:* | convex:ConvexOS:C34*:*) + echo c34-convex-bsd + exit 0 ;; + C38*:ConvexOS:*:* | convex:ConvexOS:C38*:*) + echo c38-convex-bsd + exit 0 ;; + C4*:ConvexOS:*:* | convex:ConvexOS:C4*:*) + echo c4-convex-bsd + exit 0 ;; + CRAY*X-MP:*:*:*) + echo xmp-cray-unicos + exit 0 ;; + CRAY*Y-MP:*:*:*) + echo ymp-cray-unicos${UNAME_RELEASE} + exit 0 ;; + CRAY*C90:*:*:*) + echo c90-cray-unicos${UNAME_RELEASE} + exit 0 ;; + CRAY-2:*:*:*) + echo cray2-cray-unicos + exit 0 ;; + hp3[0-9][05]:NetBSD:*:*) + echo m68k-hp-netbsd${UNAME_RELEASE} + exit 0 ;; + i[34]86:BSD/386:*:* | *:BSD/OS:*:*) + echo ${UNAME_MACHINE}-unknown-bsdi${UNAME_RELEASE} + exit 0 ;; + *:FreeBSD:*:*) + echo ${UNAME_MACHINE}-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` + exit 0 ;; + *:NetBSD:*:*) + echo ${UNAME_MACHINE}-unknown-netbsd`echo ${UNAME_RELEASE}|sed -e 's/[-_].*/\./'` + exit 0 ;; + i*:CYGWIN*:*) + echo i386-unknown-cygwin32 + exit 0 ;; + p*:CYGWIN*:*) + echo powerpcle-unknown-cygwin32 + exit 0 ;; + *:GNU:*:*) + echo `echo ${UNAME_MACHINE}|sed -e 's,/.*$,,'`-unknown-gnu`echo ${UNAME_RELEASE}|sed -e 's,/.*$,,'` + exit 0 ;; + *:Linux:*:*) + # The BFD linker knows what the default object file format is, so + # first see if it will tell us. + ld_help_string=`ld --help 2>&1` + if echo "$ld_help_string" | grep >/dev/null 2>&1 "supported emulations: elf_i[345]86"; then + echo "${UNAME_MACHINE}-unknown-linux" ; exit 0 + elif echo "$ld_help_string" | grep >/dev/null 2>&1 "supported emulations: i[345]86linux"; then + echo "${UNAME_MACHINE}-unknown-linuxaout" ; exit 0 + elif echo "$ld_help_string" | grep >/dev/null 2>&1 "supported emulations: i[345]86coff"; then + echo "${UNAME_MACHINE}-unknown-linuxcoff" ; exit 0 + elif echo "$ld_help_string" | grep >/dev/null 2>&1 "supported emulations: m68kelf"; then + echo "${UNAME_MACHINE}-unknown-linux" ; exit 0 + elif echo "$ld_help_string" | grep >/dev/null 2>&1 "supported emulations: m68klinux"; then + echo "${UNAME_MACHINE}-unknown-linuxaout" ; exit 0 + elif test "${UNAME_MACHINE}" = "alpha" ; then + echo alpha-unknown-linux ; exit 0 + else + # Either a pre-BFD a.out linker (linuxoldld) or one that does not give us + # useful --help. Gcc wants to distinguish between linuxoldld and linuxaout. + test ! -d /usr/lib/ldscripts/. \ + && echo "${UNAME_MACHINE}-unknown-linuxoldld" && exit 0 + # Determine whether the default compiler is a.out or elf + cat >dummy.c <<EOF +main(argc, argv) +int argc; +char *argv[]; +{ +#ifdef __ELF__ + printf ("%s-unknown-linux\n", argv[1]); +#else + printf ("%s-unknown-linuxaout\n", argv[1]); +#endif + return 0; +} +EOF + ${CC-cc} dummy.c -o dummy 2>/dev/null && ./dummy "${UNAME_MACHINE}" && rm dummy.c dummy && exit 0 + rm -f dummy.c dummy + fi ;; +# ptx 4.0 does uname -s correctly, with DYNIX/ptx in there. earlier versions +# are messed up and put the nodename in both sysname and nodename. + i[34]86:DYNIX/ptx:4*:*) + echo i386-sequent-sysv4 + exit 0 ;; + i[34]86:*:4.*:* | i[34]86:SYSTEM_V:4.*:*) + if grep Novell /usr/include/link.h >/dev/null 2>/dev/null; then + echo ${UNAME_MACHINE}-univel-sysv${UNAME_RELEASE} + else + echo ${UNAME_MACHINE}-unknown-sysv${UNAME_RELEASE} + fi + exit 0 ;; + i[34]86:*:3.2:*) + if test -f /usr/options/cb.name; then + UNAME_REL=`sed -n 's/.*Version //p' </usr/options/cb.name` + echo ${UNAME_MACHINE}-unknown-isc$UNAME_REL + elif /bin/uname -X 2>/dev/null >/dev/null ; then + UNAME_REL=`(/bin/uname -X|egrep Release|sed -e 's/.*= //')` + (/bin/uname -X|egrep i80486 >/dev/null) && UNAME_MACHINE=i486 + (/bin/uname -X|egrep '^Machine.*Pentium' >/dev/null) \ + && UNAME_MACHINE=i586 + echo ${UNAME_MACHINE}-unknown-sco$UNAME_REL + else + echo ${UNAME_MACHINE}-unknown-sysv32 + fi + exit 0 ;; + Intel:Mach:3*:*) + echo i386-unknown-mach3 + exit 0 ;; + paragon:*:*:*) + echo i860-intel-osf1 + exit 0 ;; + i860:*:4.*:*) # i860-SVR4 + if grep Stardent /usr/include/sys/uadmin.h >/dev/null 2>&1 ; then + echo i860-stardent-sysv${UNAME_RELEASE} # Stardent Vistra i860-SVR4 + else # Add other i860-SVR4 vendors below as they are discovered. + echo i860-unknown-sysv${UNAME_RELEASE} # Unknown i860-SVR4 + fi + exit 0 ;; + mini*:CTIX:SYS*5:*) + # "miniframe" + echo m68010-convergent-sysv + exit 0 ;; + M680[234]0:*:R3V[567]*:*) + test -r /sysV68 && echo 'm68k-motorola-sysv' && exit 0 ;; + 3[34]??:*:4.0:3.0 | 3[34]??,*:*:4.0:3.0) + uname -p 2>/dev/null | grep 86 >/dev/null \ + && echo i486-ncr-sysv4.3 && exit 0 ;; + 3[34]??:*:4.0:* | 3[34]??,*:*:4.0:*) + uname -p 2>/dev/null | grep 86 >/dev/null \ + && echo i486-ncr-sysv4 && exit 0 ;; + m680[234]0:LynxOS:2.[23]*:*) + echo m68k-lynx-lynxos${UNAME_RELEASE} + exit 0 ;; + mc68030:UNIX_System_V:4.*:*) + echo m68k-atari-sysv4 + exit 0 ;; + i[34]86:LynxOS:2.[23]*:*) + echo i386-lynx-lynxos${UNAME_RELEASE} + exit 0 ;; + TSUNAMI:LynxOS:2.[23]*:*) + echo sparc-lynx-lynxos${UNAME_RELEASE} + exit 0 ;; + rs6000:LynxOS:2.[23]*:*) + echo rs6000-lynx-lynxos${UNAME_RELEASE} + exit 0 ;; + RM*:SINIX-*:*:*) + echo mips-sni-sysv4 + exit 0 ;; + *:SINIX-*:*:*) + if uname -p 2>/dev/null >/dev/null ; then + UNAME_MACHINE=`(uname -p) 2>/dev/null` + echo ${UNAME_MACHINE}-sni-sysv4 + else + echo ns32k-sni-sysv + fi + exit 0 ;; + mc68*:A/UX:*:*) + echo m68k-apple-aux${UNAME_RELEASE} + exit 0 ;; +esac + +#echo '(No uname command or uname output not recognized.)' 1>&2 +#echo "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" 1>&2 + +cat >dummy.c <<EOF +#ifdef _SEQUENT_ +# include <sys/types.h> +# include <sys/utsname.h> +#endif +main () +{ +#if defined (sony) +#if defined (MIPSEB) + /* BFD wants "bsd" instead of "newsos". Perhaps BFD should be changed, + I don't know.... */ + printf ("mips-sony-bsd\n"); exit (0); +#else +#include <sys/param.h> + printf ("m68k-sony-newsos%s\n", +#ifdef NEWSOS4 + "4" +#else + "" +#endif + ); exit (0); +#endif +#endif + +#if defined (__arm) && defined (__acorn) && defined (__unix) + printf ("arm-acorn-riscix"); exit (0); +#endif + +#if defined (hp300) && !defined (hpux) + printf ("m68k-hp-bsd\n"); exit (0); +#endif + +#if defined (NeXT) +#if !defined (__ARCHITECTURE__) +#define __ARCHITECTURE__ "m68k" +#endif + int version; + version=`(hostinfo | sed -n 's/.*NeXT Mach \([0-9]*\).*/\1/p') 2>/dev/null`; + printf ("%s-next-nextstep%s\n", __ARCHITECTURE__, version==2 ? "2" : "3"); + exit (0); +#endif + +#if defined (MULTIMAX) || defined (n16) +#if defined (UMAXV) + printf ("ns32k-encore-sysv\n"); exit (0); +#else +#if defined (CMU) + printf ("ns32k-encore-mach\n"); exit (0); +#else + printf ("ns32k-encore-bsd\n"); exit (0); +#endif +#endif +#endif + +#if defined (__386BSD__) + printf ("i386-unknown-bsd\n"); exit (0); +#endif + +#if defined (sequent) +#if defined (i386) + printf ("i386-sequent-dynix\n"); exit (0); +#endif +#if defined (ns32000) + printf ("ns32k-sequent-dynix\n"); exit (0); +#endif +#endif + +#if defined (_SEQUENT_) + struct utsname un; + + uname(&un); + + if (strncmp(un.version, "V2", 2) == 0) { + printf ("i386-sequent-ptx2\n"); exit (0); + } + if (strncmp(un.version, "V1", 2) == 0) { /* XXX is V1 correct? */ + printf ("i386-sequent-ptx1\n"); exit (0); + } + printf ("i386-sequent-ptx\n"); exit (0); + +#endif + +#if defined (vax) +#if !defined (ultrix) + printf ("vax-dec-bsd\n"); exit (0); +#else + printf ("vax-dec-ultrix\n"); exit (0); +#endif +#endif + +#if defined (alliant) && defined (i860) + printf ("i860-alliant-bsd\n"); exit (0); +#endif + + exit (1); +} +EOF + +${CC-cc} dummy.c -o dummy 2>/dev/null && ./dummy && rm dummy.c dummy && exit 0 +rm -f dummy.c dummy + +# Apollos put the system type in the environment. + +test -d /usr/apollo && { echo ${ISP}-apollo-${SYSTYPE}; exit 0; } + +# Convex versions that predate uname can use getsysinfo(1) + +if [ -x /usr/convex/getsysinfo ] +then + case `getsysinfo -f cpu_type` in + c1*) + echo c1-convex-bsd + exit 0 ;; + c2*) + if getsysinfo -f scalar_acc + then echo c32-convex-bsd + else echo c2-convex-bsd + fi + exit 0 ;; + c34*) + echo c34-convex-bsd + exit 0 ;; + c38*) + echo c38-convex-bsd + exit 0 ;; + c4*) + echo c4-convex-bsd + exit 0 ;; + esac +fi + +#echo '(Unable to guess system type)' 1>&2 + +exit 1 diff --git a/contrib/libgmp/config.sub b/contrib/libgmp/config.sub new file mode 100755 index 0000000..997f9db --- /dev/null +++ b/contrib/libgmp/config.sub @@ -0,0 +1,1094 @@ +#! /bin/sh +# Configuration validation subroutine script, version 1.1. +# Copyright (C) 1991, 1992, 1993, 1994, 1995, 1996 Free Software Foundation, Inc. +# This file is (in principle) common to ALL GNU software. +# The presence of a machine in this file suggests that SOME GNU software +# can handle that machine. It does not imply ALL GNU software can. +# +# This file is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, USA. + +# As a special exception to the GNU General Public License, if you +# distribute this file as part of a program that contains a +# configuration script generated by Autoconf, you may include it under +# the same distribution terms that you use for the rest of that program. + +# Configuration subroutine to validate and canonicalize a configuration type. +# Supply the specified configuration type as an argument. +# If it is invalid, we print an error message on stderr and exit with code 1. +# Otherwise, we print the canonical config type on stdout and succeed. + +# This file is supposed to be the same for all GNU packages +# and recognize all the CPU types, system types and aliases +# that are meaningful with *any* GNU software. +# Each package is responsible for reporting which valid configurations +# it does not support. The user should be able to distinguish +# a failure to support a valid configuration from a meaningless +# configuration. + +# The goal of this file is to map all the various variations of a given +# machine specification into a single specification in the form: +# CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM +# It is wrong to echo any other type of specification. + +if [ x$1 = x ] +then + echo Configuration name missing. 1>&2 + echo "Usage: $0 CPU-MFR-OPSYS" 1>&2 + echo "or $0 ALIAS" 1>&2 + echo where ALIAS is a recognized configuration type. 1>&2 + exit 1 +fi + +# First pass through any local machine types. +case $1 in + *local*) + echo $1 + exit 0 + ;; + *) + ;; +esac + +# Separate what the user gave into CPU-COMPANY and OS (if any). +basic_machine=`echo $1 | sed 's/-[^-]*$//'` +if [ $basic_machine != $1 ] +then os=`echo $1 | sed 's/.*-/-/'` +else os=; fi + +### Let's recognize common machines as not being operating systems so +### that things like config.sub decstation-3100 work. We also +### recognize some manufacturers as not being operating systems, so we +### can provide default operating systems below. +case $os in + -sun*os*) + # Prevent following clause from handling this invalid input. + ;; + -dec* | -mips* | -sequent* | -encore* | -pc532* | -sgi* | -sony* | \ + -att* | -7300* | -3300* | -delta* | -motorola* | -sun[234]* | \ + -unicom* | -ibm* | -next | -hp | -isi* | -apollo | -altos* | \ + -convergent* | -ncr* | -news | -32* | -3600* | -3100* | -hitachi* |\ + -c[123]* | -convex* | -sun | -crds | -omron* | -dg | -ultra | -tti* | \ + -harris | -dolphin | -highlevel | -gould | -cbm | -ns | -masscomp ) + os= + basic_machine=$1 + ;; + -sim | -cisco | -oki | -wec | -winbond ) # CYGNUS LOCAL + os= + basic_machine=$1 + ;; + -apple*) # CYGNUS LOCAL + os= + basic_machine=$1 + ;; + -scout) # CYGNUS LOCAL + ;; + -wrs) # CYGNUS LOCAL + os=vxworks + basic_machine=$1 + ;; + -hiux*) + os=-hiuxwe2 + ;; + -sco4) + os=-sco3.2v4 + basic_machine=`echo $1 | sed -e 's/86-.*/86-unknown/'` + ;; + -sco3.2.[4-9]*) + os=`echo $os | sed -e 's/sco3.2./sco3.2v/'` + basic_machine=`echo $1 | sed -e 's/86-.*/86-unknown/'` + ;; + -sco3.2v[4-9]*) + # Don't forget version if it is 3.2v4 or newer. + basic_machine=`echo $1 | sed -e 's/86-.*/86-unknown/'` + ;; + -sco*) + os=-sco3.2v2 + basic_machine=`echo $1 | sed -e 's/86-.*/86-unknown/'` + ;; + -isc) + os=-isc2.2 + basic_machine=`echo $1 | sed -e 's/86-.*/86-unknown/'` + ;; + -clix*) + basic_machine=clipper-intergraph + ;; + -isc*) + basic_machine=`echo $1 | sed -e 's/86-.*/86-unknown/'` + ;; + -lynx*) + os=-lynxos + ;; + -ptx*) + basic_machine=`echo $1 | sed -e 's/86-.*/86-sequent/'` + ;; + -windowsnt*) + os=`echo $os | sed -e 's/windowsnt/winnt/'` + ;; +esac + +# Decode aliases for certain CPU-COMPANY combinations. +case $basic_machine in + # Recognize the basic CPU types without company name. + # Some are omitted here because they have special meanings below. + tahoe | i[345]86 | i860 | m68k | m68000 | m88k | ns32k | arm | armeb \ + | armel | pyramid \ + | tron | a29k | 580 | i960 | h8300 | hppa1.0 | hppa1.1 \ + | alpha | we32k | ns16k | clipper | sparclite | i370 | sh \ + | powerpc | powerpcle | sparc64 | 1750a | dsp16xx | mips64 | mipsel \ + | pdp11 | mips64el | mips64orion | mips64orionel \ + | sparc | sparc8 | supersparc | microsparc | ultrasparc) + basic_machine=$basic_machine-unknown + ;; + m88110 | m680[012346]0 | m683?2 | m68360 | z8k | v70 | h8500 | w65) # CYGNUS LOCAL + basic_machine=$basic_machine-unknown + ;; + mips64vr4300 | mips64vr4300el) # CYGNUS LOCAL jsmith + basic_machine=$basic_machine-unknown + ;; + # Object if more than one company name word. + *-*-*) + echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2 + exit 1 + ;; + # Recognize the basic CPU types with company name. + vax-* | tahoe-* | i[3456]86-* | i860-* | m68k-* | m68000-* | m88k-* \ + | sparc-* | ns32k-* | fx80-* | arm-* | arme[lb]-* | c[123]* \ + | mips-* | pyramid-* | tron-* | a29k-* | romp-* | rs6000-* | power-* \ + | none-* | 580-* | cray2-* | h8300-* | i960-* | xmp-* | ymp-* \ + | hppa1.0-* | hppa1.1-* | alpha-* | we32k-* | cydra-* | ns16k-* \ + | pn-* | np1-* | xps100-* | clipper-* | orion-* | sparclite-* \ + | pdp11-* | sh-* | powerpc-* | powerpcle-* | sparc64-* \ + | mips64-* | mipsel-* | mips64el-* | mips64orion-* \ + | mips64orionel-* | sparc8-* | supersparc-* | microsparc-* | ultrasparc-*) + ;; + m88110-* | m680[012346]0-* | m683?2-* | m68360-* | z8k-* | h8500-*) # CYGNUS LOCAL + ;; + mips64vr4300-* | mips64vr4300el-*) # CYGNUS LOCAL jsmith + ;; + # Recognize the various machine names and aliases which stand + # for a CPU type and a company and sometimes even an OS. + 386bsd) # CYGNUS LOCAL + basic_machine=i386-unknown + os=-bsd + ;; + 3b1 | 7300 | 7300-att | att-7300 | pc7300 | safari | unixpc) + basic_machine=m68000-att + ;; + 3b*) + basic_machine=we32k-att + ;; + a29khif) # CYGNUS LOCAL + basic_machine=a29k-amd + os=-udi + ;; + adobe68k) # CYGNUS LOCAL + basic_machine=m68010-adobe + os=-scout + ;; + alliant | fx80) + basic_machine=fx80-alliant + ;; + altos | altos3068) + basic_machine=m68k-altos + ;; + am29k) + basic_machine=a29k-none + os=-bsd + ;; + amdahl) + basic_machine=580-amdahl + os=-sysv + ;; + amiga | amiga-*) + basic_machine=m68k-cbm + ;; + amigados) + basic_machine=m68k-cbm + os=-amigados + ;; + amigaunix | amix) + basic_machine=m68k-cbm + os=-sysv4 + ;; + apollo68) + basic_machine=m68k-apollo + os=-sysv + ;; + apollo68bsd) # CYGNUS LOCAL + basic_machine=m68k-apollo + os=-bsd + ;; + arm | armel | armeb) + basic_machine=arm-arm + os=-aout + ;; + balance) + basic_machine=ns32k-sequent + os=-dynix + ;; + [ctj]90-cray) + basic_machine=c90-cray + os=-unicos + ;; + convex-c1) + basic_machine=c1-convex + os=-bsd + ;; + convex-c2) + basic_machine=c2-convex + os=-bsd + ;; + convex-c32) + basic_machine=c32-convex + os=-bsd + ;; + convex-c34) + basic_machine=c34-convex + os=-bsd + ;; + convex-c38) + basic_machine=c38-convex + os=-bsd + ;; + cray | ymp) + basic_machine=ymp-cray + os=-unicos + ;; + cray2) + basic_machine=cray2-cray + os=-unicos + ;; + crds | unos) + basic_machine=m68k-crds + ;; + da30 | da30-*) + basic_machine=m68k-da30 + ;; + decstation | decstation-3100 | pmax | pmax-* | pmin | dec3100 | decstatn) + basic_machine=mips-dec + ;; + delta | 3300 | motorola-3300 | motorola-delta \ + | 3300-motorola | delta-motorola) + basic_machine=m68k-motorola + ;; + delta88) + basic_machine=m88k-motorola + os=-sysv3 + ;; + dpx20 | dpx20-*) + basic_machine=rs6000-bull + os=-bosx + ;; + dpx2* | dpx2*-bull) + basic_machine=m68k-bull + os=-sysv3 + ;; + ebmon29k) + basic_machine=a29k-amd + os=-ebmon + ;; + elxsi) + basic_machine=elxsi-elxsi + os=-bsd + ;; + encore | umax | mmax) + basic_machine=ns32k-encore + ;; + es1800 | OSE68k | ose68k | ose | OSE) # CYGNUS LOCAL + basic_machine=m68k-ericsson + os=-ose + ;; + fx2800) + basic_machine=i860-alliant + ;; + genix) + basic_machine=ns32k-ns + ;; + gmicro) + basic_machine=tron-gmicro + os=-sysv + ;; + h3050r* | hiux*) + basic_machine=hppa1.1-hitachi + os=-hiuxwe2 + ;; + h8300hms) + basic_machine=h8300-hitachi + os=-hms + ;; + h8300xray) # CYGNUS LOCAL + basic_machine=h8300-hitachi + os=-xray + ;; + h8500hms) # CYGNUS LOCAL + basic_machine=h8500-hitachi + os=-hms + ;; + harris) + basic_machine=m88k-harris + os=-sysv3 + ;; + hp300-*) + basic_machine=m68k-hp + ;; + hp300bsd) + basic_machine=m68k-hp + os=-bsd + ;; + hp300hpux) + basic_machine=m68k-hp + os=-hpux + ;; + w89k-*) # CYGNUS LOCAL + basic_machine=hppa1.1-winbond + os=-proelf + ;; + op50n-*) # CYGNUS LOCAL + basic_machine=hppa1.1-oki + os=-proelf + ;; + op60c-*) # CYGNUS LOCAL + basic_machine=hppa1.1-oki + os=-proelf + ;; + hppro) # CYGNUS LOCAL + basic_machine=hppa1.1-hp + os=-proelf + ;; + hp9k2[0-9][0-9] | hp9k31[0-9]) + basic_machine=m68000-hp + ;; + hp9k3[2-9][0-9]) + basic_machine=m68k-hp + ;; + hp9k7[0-9][0-9] | hp7[0-9][0-9] | hp9k8[0-9]7 | hp8[0-9]7) + basic_machine=hppa1.1-hp + ;; + hp9k8[0-9][0-9] | hp8[0-9][0-9]) + basic_machine=hppa1.0-hp + ;; + hppaosf) # CYGNUS LOCAL + basic_machine=hppa1.1-hp + os=-osf + ;; + i370-ibm* | ibm*) + basic_machine=i370-ibm + os=-mvs + ;; +# I'm not sure what "Sysv32" means. Should this be sysv3.2? + i[3456]86v32) + basic_machine=`echo $1 | sed -e 's/86.*/86-unknown/'` + os=-sysv32 + ;; + i[3456]86v4*) + basic_machine=`echo $1 | sed -e 's/86.*/86-unknown/'` + os=-sysv4 + ;; + i[3456]86v) + basic_machine=`echo $1 | sed -e 's/86.*/86-unknown/'` + os=-sysv + ;; + i[3456]86sol2) + basic_machine=`echo $1 | sed -e 's/86.*/86-unknown/'` + os=-solaris2 + ;; + i386mach) # CYGNUS LOCAL + basic_machine=i386-mach + os=-mach + ;; + i386-vsta | vsta) # CYGNUS LOCAL + basic_machine=i386-unknown + os=-vsta + ;; + i386-go32 | go32) # CYGNUS LOCAL + basic_machine=i386-unknown + os=-go32 + ;; + iris | iris4d) + basic_machine=mips-sgi + case $os in + -irix*) + ;; + *) + os=-irix4 + ;; + esac + ;; + isi68 | isi) + basic_machine=m68k-isi + os=-sysv + ;; + m88k-omron*) + basic_machine=m88k-omron + ;; + magnum | m3230) + basic_machine=mips-mips + os=-sysv + ;; + merlin) + basic_machine=ns32k-utek + os=-sysv + ;; + miniframe) + basic_machine=m68000-convergent + ;; + mips3*-*) + basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'` + ;; + mips3*) + basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'`-unknown + ;; + monitor) # CYGNUS LOCAL + basic_machine=m68k-rom68k + os=-coff + ;; + msdos) # CYGNUS LOCAL + basic_machine=i386-unknown + os=-msdos + ;; + ncr3000) + basic_machine=i486-ncr + os=-sysv4 + ;; + netbsd386) + basic_machine=i386-unknown # CYGNUS LOCAL + os=-netbsd + ;; + news | news700 | news800 | news900) + basic_machine=m68k-sony + os=-newsos + ;; + news1000) + basic_machine=m68030-sony + os=-newsos + ;; + news-3600 | risc-news) + basic_machine=mips-sony + os=-newsos + ;; + necv70) # CYGNUS LOCAL + basic_machine=v70-nec + os=-sysv + ;; + next | m*-next ) + basic_machine=m68k-next + case $os in + -nextstep* ) + ;; + -ns2*) + os=-nextstep2 + ;; + *) + os=-nextstep3 + ;; + esac + ;; + nh3000) + basic_machine=m68k-harris + os=-cxux + ;; + nh[45]000) + basic_machine=m88k-harris + os=-cxux + ;; + nindy960) + basic_machine=i960-intel + os=-nindy + ;; + np1) + basic_machine=np1-gould + ;; + OSE68000 | ose68000) # CYGNUS LOCAL + basic_machine=m68000-ericsson + os=-ose + ;; + os68k) # CYGNUS LOCAL + basic_machine=m68k-none + os=-os68k + ;; + pa-hitachi) + basic_machine=hppa1.1-hitachi + os=-hiuxwe2 + ;; + paragon) + basic_machine=i860-intel + os=-osf + ;; + pbd) + basic_machine=sparc-tti + ;; + pbb) + basic_machine=m68k-tti + ;; + pc532 | pc532-*) + basic_machine=ns32k-pc532 + ;; + pentium | p5) + basic_machine=i586-intel + ;; + pentiumpro | p6) + basic_machine=i686-intel + ;; + pentium-* | p5-*) + basic_machine=i586-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + pentiumpro-* | p6-*) + basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + k5) + # We don't have specific support for AMD's K5 yet, so just call it a Pentium + basic_machine=i586-amd + ;; + nexgen) + # We don't have specific support for Nexgen yet, so just call it a Pentium + basic_machine=i586-nexgen + ;; + pn) + basic_machine=pn-gould + ;; + power) basic_machine=rs6000-ibm + ;; + ppc) basic_machine=powerpc-unknown + ;; + ppc-*) basic_machine=powerpc-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + ppcle | powerpclittle | ppc-le | powerpc-little) + basic_machine=powerpcle-unknown + ;; + ppcle-* | powerpclittle-*) + basic_machine=powerpcle-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + ps2) + basic_machine=i386-ibm + ;; + rom68k) # CYGNUS LOCAL + basic_machine=m68k-rom68k + os=-coff + ;; + rm[46]00) + basic_machine=mips-siemens + ;; + rtpc | rtpc-*) + basic_machine=romp-ibm + ;; + sa29200) # CYGNUS LOCAL + basic_machine=a29k-amd + os=-udi + ;; + sequent) + basic_machine=i386-sequent + ;; + sh) + basic_machine=sh-hitachi + os=-hms + ;; + sparclite-wrs) # CYGNUS LOCAL + basic_machine=sparclite-wrs + os=-vxworks + ;; + sparcfrw) # CYGNUS LOCAL + basic_machine=sparcfrw-sun + os=-sunos4 + ;; + sparcfrwcompat) # CYGNUS LOCAL + basic_machine=sparcfrwcompat-sun + os=-sunos4 + ;; + sparclitefrw) # CYGNUS LOCAL + basic_machine=sparclitefrw-fujitsu + ;; + sparclitefrwcompat) # CYGNUS LOCAL + basic_machine=sparclitefrwcompat-fujitsu + ;; + sps7) + basic_machine=m68k-bull + os=-sysv2 + ;; + spur) + basic_machine=spur-unknown + ;; + st2000) # CYGNUS LOCAL + basic_machine=m68k-tandem + ;; + stratus) # CYGNUS LOCAL + basic_machine=i860-stratus + os=-sysv4 + ;; + sun2) + basic_machine=m68000-sun + ;; + sun2os3) + basic_machine=m68000-sun + os=-sunos3 + ;; + sun2os4) + basic_machine=m68000-sun + os=-sunos4 + ;; + sun3os3) + basic_machine=m68k-sun + os=-sunos3 + ;; + sun3os4) + basic_machine=m68k-sun + os=-sunos4 + ;; + sun4os3) + basic_machine=sparc-sun + os=-sunos3 + ;; + sun4os4) + basic_machine=sparc-sun + os=-sunos4 + ;; + sun4sol2) + basic_machine=sparc-sun + os=-solaris2 + ;; + sun3 | sun3-*) + basic_machine=m68k-sun + ;; + sun4) + basic_machine=sparc-sun + ;; + sun386 | sun386i | roadrunner) + basic_machine=i386-sun + ;; + symmetry) + basic_machine=i386-sequent + os=-dynix + ;; + tower | tower-32) + basic_machine=m68k-ncr + ;; + udi29k) + basic_machine=a29k-amd + os=-udi + ;; + ultra3) + basic_machine=a29k-nyu + os=-sym1 + ;; + v810 | necv810) # CYGNUS LOCAL + basic_machine=v810-nec + os=-none + ;; + vaxv) + basic_machine=vax-dec + os=-sysv + ;; + vms) + basic_machine=vax-dec + os=-vms + ;; + vxworks960) + basic_machine=i960-wrs + os=-vxworks + ;; + vxworks68) + basic_machine=m68k-wrs + os=-vxworks + ;; + vxworks29k) # CYGNUS LOCAL + basic_machine=a29k-wrs + os=-vxworks + ;; + w65*) # CYGNUS LOCAL + basic_machine=w65-wdc + os=-none + ;; + xmp) + basic_machine=xmp-cray + os=-unicos + ;; + xps | xps100) + basic_machine=xps100-honeywell + ;; + z8k-*-coff) # CYGNUS LOCAL + basic_machine=z8k-unknown + os=-sim + ;; + none) + basic_machine=none-none + os=-none + ;; + +# Here we handle the default manufacturer of certain CPU types. It is in +# some cases the only manufacturer, in others, it is the most popular. + w89k) # CYGNUS LOCAL + basic_machine=hppa1.1-winbond + ;; + op50n) # CYGNUS LOCAL + basic_machine=hppa1.1-oki + ;; + op60c) # CYGNUS LOCAL + basic_machine=hppa1.1-oki + ;; + mips) + basic_machine=mips-mips + ;; + romp) + basic_machine=romp-ibm + ;; + rs6000) + basic_machine=rs6000-ibm + ;; + vax) + basic_machine=vax-dec + ;; + pdp11) + basic_machine=pdp11-dec + ;; + we32k) + basic_machine=we32k-att + ;; + sparc) + basic_machine=sparc-sun + ;; + cydra) + basic_machine=cydra-cydrome + ;; + orion) + basic_machine=orion-highlevel + ;; + orion105) + basic_machine=clipper-highlevel + ;; + mac | mpw | mac-mpw) # CYGNUS LOCAL + basic_machine=m68k-apple + ;; + pmac | pmac-mpw) # CYGNUS LOCAL + basic_machine=powerpc-apple + ;; + *) + echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2 + exit 1 + ;; +esac + +# Here we canonicalize certain aliases for manufacturers. +case $basic_machine in + *-digital*) + basic_machine=`echo $basic_machine | sed 's/digital.*/dec/'` + ;; + *-commodore*) + basic_machine=`echo $basic_machine | sed 's/commodore.*/cbm/'` + ;; + *) + ;; +esac + +# Decode manufacturer-specific aliases for certain operating systems. + +if [ x"$os" != x"" ] +then +case $os in + # -solaris* is a basic system type, with this one exception. + -solaris1 | -solaris1.*) + os=`echo $os | sed -e 's|solaris1|sunos4|'` + ;; + -solaris) + os=-solaris2 + ;; + -unixware* | svr4*) + os=-sysv4 + ;; + -gnu/linux*) + os=`echo $os | sed -e 's|gnu/linux|linux|'` + ;; + # First accept the basic system types. + # The portable systems comes first. + # Each alternative must end in a *, to match a version number. + # -sysv* is not here because it comes later, after sysvr4. + -gnu* | -bsd* | -mach* | -lites* | -minix* | -genix* | -ultrix* | -irix* \ + | -vms* | -sco* | -esix* | -isc* | -aix* | -sunos | -sunos[3456]* \ + | -hpux* | -unos* | -osf* | -luna* | -dgux* | -solaris* | -sym* \ + | -amigados* | -msdos* | -moss* | -newsos* | -unicos* | -aos* \ + | -nindy* | -vxworks* | -ebmon* | -hms* | -mvs* | -clix* \ + | -riscos* | -linux* | -uniplus* | -iris* | -rtu* | -xenix* \ + | -hiux* | -386bsd* | -netbsd* | -freebsd* | -riscix* | -lites* \ + | -lynxos* | -bosx* | -nextstep* | -cxux* | -aout* | -elf* \ + | -ptx* | -coff* | -ecoff* | -winnt* | -domain* | -vsta | -udi \ + | -eabi* | -ieee*) + ;; + # CYGNUS LOCAL + -go32 | -sim | -es1800* | -hms* | -xray | -os68k* | -none* | -v88r* \ + | -windows* | -osx | -abug | -netware* | -proelf | -os9* \ + | -macos* | -mpw* | -magic* | -pe* | -win32) + ;; + -mac*) # CYGNUS LOCAL + os=`echo $os | sed -e 's|mac|macos|'` + ;; + -sunos5*) + os=`echo $os | sed -e 's|sunos5|solaris2|'` + ;; + -sunos6*) + os=`echo $os | sed -e 's|sunos6|solaris3|'` + ;; + -osfrose*) + os=-osfrose + ;; + -osf*) + os=-osf + ;; + -utek*) + os=-bsd + ;; + -dynix*) + os=-bsd + ;; + -acis*) + os=-aos + ;; + -386bsd) # CYGNUS LOCAL + os=-bsd + ;; + -ctix* | -uts*) + os=-sysv + ;; + # Preserve the version number of sinix5. + -sinix5.*) + os=`echo $os | sed -e 's|sinix|sysv|'` + ;; + -sinix*) + os=-sysv4 + ;; + -triton*) + os=-sysv3 + ;; + -oss*) + os=-sysv3 + ;; + -svr4) + os=-sysv4 + ;; + -svr3) + os=-sysv3 + ;; + -sysvr4) + os=-sysv4 + ;; + # This must come after -sysvr4. + -sysv*) + ;; + -ose*) # CYGNUS LOCAL + os=-ose + ;; + -es1800*) # CYGNUS LOCAL + os=-ose + ;; + -xenix) + os=-xenix + ;; + -none) + ;; + *) + # Get rid of the `-' at the beginning of $os. + os=`echo $os | sed 's/[^-]*-//'` + echo Invalid configuration \`$1\': system \`$os\' not recognized 1>&2 + exit 1 + ;; +esac +else + +# Here we handle the default operating systems that come with various machines. +# The value should be what the vendor currently ships out the door with their +# machine or put another way, the most popular os provided with the machine. + +# Note that if you're going to try to match "-MANUFACTURER" here (say, +# "-sun"), then you have to tell the case statement up towards the top +# that MANUFACTURER isn't an operating system. Otherwise, code above +# will signal an error saying that MANUFACTURER isn't an operating +# system, and we'll never get to this point. + +case $basic_machine in + *-acorn) + os=-riscix1.2 + ;; + pdp11-*) + os=-none + ;; + *-dec | vax-*) + os=-ultrix4.2 + ;; + m68*-apollo) + os=-domain + ;; + i386-sun) + os=-sunos4.0.2 + ;; + m68000-sun) + os=-sunos3 + # This also exists in the configure program, but was not the + # default. + # os=-sunos4 + ;; + m68*-cisco) # CYGNUS LOCAL + os=-aout + ;; + mips*-cisco) # CYGNUS LOCAL + os=-elf + ;; + *-tti) # must be before sparc entry or we get the wrong os. + os=-sysv3 + ;; + sparc-* | *-sun) + os=-sunos4.1.1 + ;; + *-ibm) + os=-aix + ;; + *-wec) # CYGNUS LOCAL + os=-proelf + ;; + *-winbond) # CYGNUS LOCAL + os=-proelf + ;; + *-oki) # CYGNUS LOCAL + os=-proelf + ;; + *-hp) + os=-hpux + ;; + *-hitachi) + os=-hiux + ;; + i860-* | *-att | *-ncr | *-altos | *-motorola | *-convergent) + os=-sysv + ;; + *-cbm) + os=-amigados + ;; + *-dg) + os=-dgux + ;; + *-dolphin) + os=-sysv3 + ;; + m68k-ccur) + os=-rtu + ;; + m88k-omron*) + os=-luna + ;; + *-sequent) + os=-ptx + ;; + *-crds) + os=-unos + ;; + *-ns) + os=-genix + ;; + i370-*) + os=-mvs + ;; + *-next) + os=-nextstep3 + ;; + *-gould) + os=-sysv + ;; + *-highlevel) + os=-bsd + ;; + *-encore) + os=-bsd + ;; + *-sgi) + os=-irix + ;; + *-siemens) + os=-sysv4 + ;; + *-masscomp) + os=-rtu + ;; + *-rom68k) # CYGNUS LOCAL + os=-coff + ;; + *-*bug) # CYGNUS LOCAL + os=-coff + ;; + *-apple) # CYGNUS LOCAL + os=-macos + ;; + *) + os=-none + ;; +esac +fi + +# Here we handle the case where we know the os, and the CPU type, but not the +# manufacturer. We pick the logical manufacturer. +vendor=unknown +case $basic_machine in + *-unknown) + case $os in + -riscix*) + vendor=acorn + ;; + -sunos*) + vendor=sun + ;; + -bosx*) # CYGNUS LOCAL + vendor=bull + ;; + -lynxos*) + vendor=lynx + ;; + -aix*) + vendor=ibm + ;; + -hpux*) + vendor=hp + ;; + -hiux*) + vendor=hitachi + ;; + -unos*) + vendor=crds + ;; + -dgux*) + vendor=dg + ;; + -luna*) + vendor=omron + ;; + -genix*) + vendor=ns + ;; + -mvs*) + vendor=ibm + ;; + -ptx*) + vendor=sequent + ;; + -vxworks*) + vendor=wrs + ;; + -hms*) # CYGNUS LOCAL + vendor=hitachi + ;; + -mpw* | -macos*) # CYGNUS LOCAL + vendor=apple + ;; + esac + basic_machine=`echo $basic_machine | sed "s/unknown/$vendor/"` + ;; +esac + +echo $basic_machine$os diff --git a/contrib/libgmp/config/mt-linux b/contrib/libgmp/config/mt-linux new file mode 100644 index 0000000..476d8b5 --- /dev/null +++ b/contrib/libgmp/config/mt-linux @@ -0,0 +1 @@ +AR_FLAGS = qc diff --git a/contrib/libgmp/config/mt-m88110 b/contrib/libgmp/config/mt-m88110 new file mode 100644 index 0000000..071f8fa --- /dev/null +++ b/contrib/libgmp/config/mt-m88110 @@ -0,0 +1 @@ +XCFLAGS = -m88110 diff --git a/contrib/libgmp/config/mt-sprc8-gcc b/contrib/libgmp/config/mt-sprc8-gcc new file mode 100644 index 0000000..bc706a9 --- /dev/null +++ b/contrib/libgmp/config/mt-sprc8-gcc @@ -0,0 +1 @@ +XCFLAGS = -mv8 diff --git a/contrib/libgmp/config/mt-supspc-gcc b/contrib/libgmp/config/mt-supspc-gcc new file mode 100644 index 0000000..92a0924 --- /dev/null +++ b/contrib/libgmp/config/mt-supspc-gcc @@ -0,0 +1 @@ +XCFLAGS = -mv8 -DSUPERSPARC diff --git a/contrib/libgmp/configure b/contrib/libgmp/configure new file mode 100755 index 0000000..1554506 --- /dev/null +++ b/contrib/libgmp/configure @@ -0,0 +1,1263 @@ +#!/bin/sh + +### WARNING: this file contains embedded tabs. Do not run untabify on this file. + +# Configuration script +# Copyright (C) 1988, 90, 91, 92, 93, 94 Free Software Foundation, Inc. + +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +# This file was originally written by K. Richard Pixley. + +# +# Shell script to create proper links to machine-dependent files in +# preparation for compilation. +# +# If configure succeeds, it leaves its status in config.status. +# If configure fails after disturbing the status quo, +# config.status is removed. +# + +export PATH || (echo "OOPS, this isn't sh. Desperation time. I will feed myself to sh."; sh $0 $argv; kill $$) + +remove=rm +hard_link=ln +symbolic_link='ln -s' + +#for Test +#remove="echo rm" +#hard_link="echo ln" +#symbolic_link="echo ln -s" + +# clear some things potentially inherited from environment. + +Makefile=Makefile +Makefile_in=Makefile.in +arguments= +build_alias= +cache_file= +cache_file_option= +configdirs= +exec_prefix= +exec_prefixoption= +fatal= +floating_point=default +gas=default +host_alias=NOHOST +host_makefile_frag= +moveifchange= +norecursion= +other_options= +package_makefile_frag= +prefix=/usr/local +progname= +program_prefix= +program_prefixoption= +program_suffix= +program_suffixoption= +program_transform_name= +program_transform_nameoption= +redirect=">/dev/null" +removing= +site= +site_makefile_frag= +site_option= +srcdir= +srctrigger= +subdirs= +target_alias=NOTARGET +target_makefile_frag= +undefs=NOUNDEFS +version="$Revision: 1.218 (modified for gmp) $" +x11=default + +### we might need to use some other shell than /bin/sh for running subshells +# +config_shell=${CONFIG_SHELL-/bin/sh} + +NO_EDIT="This file was generated automatically by configure. Do not edit." + +## this is a little touchy and won't always work, but... +## +## if the argv[0] starts with a slash then it is an absolute name that can (and +## must) be used as is. +## +## otherwise, if argv[0] has no slash in it, we can assume that it is on the +## path. Since PATH might include "." we also add `pwd` to the end of PATH. +## + +progname=$0 +# if PWD already has a value, it is probably wrong. +if [ -n "$PWD" ]; then PWD=`pwd`; fi + +case "${progname}" in +/*) ;; +*/*) ;; +*) + PATH=$PATH:${PWD=`pwd`} ; export PATH + ;; +esac + +# Loop over all args + +while : +do + +# Break out if there are no more args + case $# in + 0) + break + ;; + esac + +# Get the first arg, and shuffle + option=$1 + shift + +# Make all options have two hyphens + orig_option=$option # Save original for error messages + case $option in + --*) ;; + -*) option=-$option ;; + esac + +# Split out the argument for options that take them + case $option in + --*=*) + optarg=`echo $option | sed -e 's/^[^=]*=//'` + arguments="$arguments $option" + ;; +# These options have mandatory values. Since we didn't find an = sign, +# the value must be in the next argument + --bu* | --cache* | --ex* | --ho* | --pre* | --program-p* | --program-s* | --program-t* | --si* | --sr* | --ta* | --tm* | --x-* | --bi* | --sb* | --li* | --da* | --sy* | --sh* | --lo* | --in* | --ol* | --ma*) + optarg=$1 + shift + arguments="$arguments $option=$optarg" + ;; + --v) + arguments="$arguments -v" + ;; + --*) + arguments="$arguments $option" + ;; + esac + +# Now, process the options + case $option in + + --build* | --bu*) + case "$build_alias" in + "") build_alias=$optarg ;; + *) echo '***' Can only configure for one build machine at a time. 1>&2 + fatal=yes + ;; + esac + ;; + --cache*) + cache_file=$optarg + ;; + --disable-*) + enableopt=`echo ${option} | sed 's:^--disable-:enable_:;s:-:_:g'` + eval $enableopt=no + disableoptions="$disableoptions $option" + ;; + --enable-*) + case "$option" in + *=*) ;; + *) optarg=yes ;; + esac + + enableopt=`echo ${option} | sed 's:^--::;s:=.*$::;s:-:_:g'` + eval $enableopt="$optarg" + enableoptions="$enableoptions $option" + ;; + --exec-prefix* | --ex*) + exec_prefix=$optarg + exec_prefixoption="--exec-prefix=$optarg" + ;; + --gas | --g*) + gas=yes + ;; + --help | --he*) + fatal=yes + ;; + --host* | --ho*) + case $host_alias in + NOHOST) host_alias=$optarg ;; + *) echo '***' Can only configure for one host at a time. 1>&2 + fatal=yes + ;; + esac + ;; + --nfp | --nf*) + floating_point=no + floating_pointoption="--nfp" + ;; + --norecursion | --no*) + norecursion=yes + ;; + --prefix* | --pre*) + prefix=$optarg + prefixoption="--prefix=$optarg" + ;; + --program-prefix* | --program-p*) + program_prefix=$optarg + program_prefixoption="--program-prefix=$optarg" + ;; + --program-suffix* | --program-s*) + program_suffix=$optarg + program_suffixoption="--program-suffix=$optarg" + ;; + --program-transform-name* | --program-t*) + # Double any backslashes or dollar signs in the argument + program_transform_name="${program_transform_name} -e `echo ${optarg} | sed -e 's/\\\\/\\\\\\\\/g' -e 's/\\\$/$$/g'`" + program_transform_nameoption="${program_transform_nameoption} --program-transform-name='$optarg'" + ;; + --rm) + removing=--rm + ;; + --silent | --sil* | --quiet | --q*) + redirect=">/dev/null" + verbose=--silent + ;; + --site* | --sit*) + site=$optarg + site_option="--site=$optarg" + ;; + --srcdir*/ | --sr*/) + # Remove trailing slashes. Otherwise, when the file name gets + # bolted into an object file as debug info, it has two slashes + # in it. Ordinarily this is ok, but emacs takes double slash + # to mean "forget the first part". + srcdir=`echo $optarg | sed -e 's:/$::'` + ;; + --srcdir* | --sr*) + srcdir=$optarg + ;; + --target* | --ta*) + case $target_alias in + NOTARGET) target_alias=$optarg ;; + *) echo '***' Can only configure for one target at a time. 1>&2 + fatal=yes + ;; + esac + ;; + --tmpdir* | --tm*) + TMPDIR=$optarg + tmpdiroption="--tmpdir=$optarg" + ;; + --verbose | --v | --verb*) + redirect= + verbose=--verbose + ;; + --version | --V | --vers*) + echo "This is Cygnus Configure version" `echo ${version} | sed 's/[ $:]//g'` + exit 0 + ;; + --with-*) + case "$option" in + *=*) ;; + *) optarg=yes ;; + esac + + withopt=`echo ${option} | sed 's:^--::;s:=.*$::;s:-:_:g'` + eval $withopt="$optarg" + withoptions="$withoptions $option" + ;; + --without-*) + withopt=`echo ${option} | sed 's:^--::;s:out::;s:-:_:g'` + eval $withopt=no + withoutoptions="$withoutoptions $option" + ;; + --x) with_x=yes + withoptions="$withoptions --with-x" + ;; + --x-i* | --x-l*) other_options="$other_options $orig_option" + ;; + --bi* | --sb* | --li* | --da* | --sy* | --sh* | --lo* | --in* | --ol* | --ma*) + # These options were added to autoconf for emacs. + ;; + --*) + echo "configure: Unrecognized option: \"$orig_option\"; use --help for usage." >&2 + exit 1 + ;; + *) + case $undefs in + NOUNDEFS) undefs=$option ;; + *) echo '***' Can only configure for one host and one target at a time. 1>&2 + fatal=yes + ;; + esac + ;; + esac +done + +# process host and target + +# Do some error checking and defaulting for the host and target type. +# The inputs are: +# configure --host=HOST --target=TARGET UNDEFS +# +# The rules are: +# 1. You aren't allowed to specify --host, --target, and undefs at the +# same time. +# 2. Host defaults to undefs. +# 3. If undefs is not specified, then host defaults to the current host, +# as determined by config.guess. +# 4. Target defaults to undefs. +# 5. If undefs is not specified, then target defaults to host. + +case "${fatal}" in +"") + # Make sure that host, target & undefs aren't all specified at the + # same time. + case $host_alias---$target_alias---$undefs in + NOHOST---*---* | *---NOTARGET---* | *---*---NOUNDEFS) + ;; + *) echo '***' Can only configure for one host and one target at a time. 1>&2 + fatal=yes + break 2 + ;; + esac + + # Now, do defaulting for host. + case $host_alias in + NOHOST) + case $undefs in + NOUNDEFS) + # Neither --host option nor undefs were present. + # Call config.guess. + guesssys=`echo ${progname} | sed 's/configure$/config.guess/'` + if host_alias=`${guesssys}` + then + # If the string we are going to use for + # the target is a prefix of the string + # we just guessed for the host, then + # assume we are running native, and force + # the same string for both target and host. + case $target_alias in + NOTARGET) ;; + *) + if expr $host_alias : $target_alias >/dev/null + then + host_alias=$target_alias + fi + ;; + esac + echo "Configuring for a ${host_alias} host." 1>&2 + arguments="--host=$host_alias $arguments" + else + echo 'Config.guess failed to determine the host type. You need to specify one.' 1>&2 + fatal=yes + fi + ;; + *) + host_alias=$undefs + arguments="--host=$host_alias $arguments" + undefs=NOUNDEFS + ;; + esac + esac + + # Do defaulting for target. If --target option isn't present, default + # to undefs. If undefs isn't present, default to host. + case $target_alias in + NOTARGET) + case $undefs in + NOUNDEFS) + target_alias=$host_alias + ;; + *) + target_alias=$undefs + arguments="--target=$target_alias $arguments" + ;; + esac + esac + ;; +*) ;; +esac + +if [ -n "${fatal}" -o "${host_alias}" = "help" ] ; then + exec 1>&2 + echo Usage: configure [OPTIONS] [HOST] + echo + echo Options: [defaults in brackets] + echo ' --prefix=MYDIR install into MYDIR [/usr/local]' + echo ' --exec-prefix=MYDIR install host-dependent files into MYDIR [/usr/local]' + echo ' --help print this message [normal config]' + echo ' --build=BUILD configure for building on BUILD [BUILD=HOST]' + echo ' --host=HOST configure for HOST [determined via config.guess]' + echo ' --norecursion configure this directory only [recurse]' + echo ' --program-prefix=FOO prepend FOO to installed program names [""]' + echo ' --program-suffix=FOO append FOO to installed program names [""]' + echo ' --program-transform-name=P transform installed names by sed pattern P [""]' + echo ' --site=SITE configure with site-specific makefile for SITE' + echo ' --srcdir=DIR find the sources in DIR [. or ..]' + echo ' --target=TARGET configure for TARGET [TARGET=HOST]' + echo ' --tmpdir=TMPDIR create temporary files in TMPDIR [/tmp]' + echo ' --nfp configure for software floating point [hard float]' + echo ' --with-FOO, --with-FOO=BAR package FOO is available (parameter BAR)' + echo ' --without-FOO package FOO is NOT available' + echo ' --enable-FOO, --enable-FOO=BAR include feature FOO (parameter BAR)' + echo ' --disable-FOO do not include feature FOO' + echo + echo 'Where HOST and TARGET are something like "sparc-sunos", "mips-sgi-irix5", etc.' + echo + if [ -r config.status ] ; then + cat config.status + fi + + exit 1 +fi + +configsub=`echo ${progname} | sed 's/configure$/config.sub/'` +moveifchange=`echo ${progname} | sed 's/configure$/move-if-change/'` + +# this is a hack. sun4 must always be a valid host alias or this will fail. +if ${configsub} sun4 >/dev/null 2>&1 ; then + true +else + echo '***' cannot find config.sub. 1>&2 + exit 1 +fi + +touch config.junk +if ${moveifchange} config.junk config.trash ; then + true +else + echo '***' cannot find move-if-change. 1>&2 + exit 1 +fi +rm -f config.junk config.trash + +case "${srcdir}" in +"") + if [ -r configure.in ] ; then + srcdir=. + else + if [ -r ${progname}.in ] ; then + srcdir=`echo ${progname} | sed 's:/configure$::'` + else + echo '***' "Can't find configure.in. Try using --srcdir=some_dir" 1>&2 + exit 1 + fi + fi + ;; +*) + # Set srcdir to "." if that's what it is. + # This is important for multilib support. + if [ ! -d ${srcdir} ] ; then + echo "Invalid source directory ${srcdir}" >&2 + exit 1 + fi + pwd=`pwd` + srcpwd=`cd ${srcdir} ; pwd` + if [ "${pwd}" = "${srcpwd}" ] ; then + srcdir=. + fi +esac + +### warn about some conflicting configurations. + +case "${srcdir}" in +".") ;; +*) + if [ -f ${srcdir}/config.status ] ; then + echo '***' Cannot configure here in \"${PWD=`pwd`}\" when \"${srcdir}\" is currently configured. 1>&2 + exit 1 + fi +esac + +# default exec_prefix +case "${exec_prefixoption}" in +"") exec_prefix="\$(prefix)" ;; +*) ;; +esac + +### break up ${srcdir}/configure.in. +case "`grep '^# per\-host:' ${srcdir}/configure.in`" in +"") + echo '***' ${srcdir}/configure.in has no \"per-host:\" line. 1>&2 + # Check for a directory that's been converted to use autoconf since + # it was last configured. + if grep AC_OUTPUT ${srcdir}/configure.in >/dev/null ; then + echo '***' Hmm, looks like this directory has been autoconfiscated. 1>&2 + if [ -r ${srcdir}/configure ] ; then + echo '***' Running the local configure script. 1>&2 + case "${cache_file}" in + "") cache_file_option= ;; + *) cache_file_option="--cache-file=${cache_file}" ;; + esac + srcdiroption="--srcdir=${srcdir}" + case "${build_alias}" in + "") buildopt= ;; + *) buildopt="--build=${build_alias}" ;; + esac + eval exec ${config_shell} ${srcdir}/configure ${verbose} \ + ${buildopt} --host=${host_alias} --target=${target_alias} \ + ${prefixoption} ${tmpdiroption} ${exec_prefixoption} \ + ${srcdiroption} \ + ${program_prefixoption} ${program_suffixoption} \ + ${program_transform_nameoption} ${site_option} \ + ${withoptions} ${withoutoptions} \ + ${enableoptions} ${disableoptions} ${floating_pointoption} \ + ${cache_file_option} ${removing} ${other_options} ${redirect} + else + echo '***' There is no configure script present though. 1>&2 + fi + fi + exit 1 + ;; +*) ;; +esac + +case "`grep '^# per\-target:' ${srcdir}/configure.in`" in +"") + echo '***' ${srcdir}/configure.in has no \"per-target:\" line. 1>&2 + exit 1 + ;; +*) ;; +esac + +case "${TMPDIR}" in +"") TMPDIR=/tmp ; export TMPDIR ;; +*) ;; +esac + +# keep this filename short for &%*%$*# 14 char file names +tmpfile=${TMPDIR}/cONf$$ +# Note that under many versions of sh a trap handler for 0 will *override* any +# exit status you explicitly specify! At this point, the only non-error exit +# is at the end of the script; these actions are duplicated there, minus +# the "exit 1". Don't use "exit 0" anywhere after this without resetting the +# trap handler, or you'll lose. +trap "rm -f Makefile.tem ${tmpfile}.com ${tmpfile}.tgt ${tmpfile}.hst ${tmpfile}.pos; exit 1" 0 1 2 15 + +# split ${srcdir}/configure.in into common, per-host, per-target, +# and post-target parts. Post-target is optional. +sed -e '/^# per\-host:/,$d' ${srcdir}/configure.in > ${tmpfile}.com +sed -e '1,/^# per\-host:/d' -e '/^# per\-target:/,$d' ${srcdir}/configure.in > ${tmpfile}.hst +if grep '^# post-target:' ${srcdir}/configure.in >/dev/null ; then + sed -e '1,/^# per\-target:/d' -e '/^# post\-target:/,$d' ${srcdir}/configure.in > ${tmpfile}.tgt + sed -e '1,/^# post\-target:/d' ${srcdir}/configure.in > ${tmpfile}.pos +else + sed -e '1,/^# per\-target:/d' ${srcdir}/configure.in > ${tmpfile}.tgt + echo >${tmpfile}.pos +fi + +### do common part of configure.in + +. ${tmpfile}.com + +# some sanity checks on configure.in +case "${srctrigger}" in +"") + echo '***' srctrigger not set in ${PWD=`pwd`}/configure.in. 1>&2 + exit 1 + ;; +*) ;; +esac + +case "${build_alias}" in +"") + if result=`${config_shell} ${configsub} ${host_alias}` ; then + build_cpu=`echo $result | sed 's/^\(.*\)-\(.*\)-\(.*\)$/\1/'` + build_vendor=`echo $result | sed 's/^\(.*\)-\(.*\)-\(.*\)$/\2/'` + build_os=`echo $result | sed 's/^\(.*\)-\(.*\)-\(.*\)$/\3/'` + build=${build_cpu}-${build_vendor}-${build_os} + build_alias=${host_alias} + fi + ;; +*) + if result=`${config_shell} ${configsub} ${build_alias}` ; then + buildopt="--build=${build_alias}" + build_cpu=`echo $result | sed 's/^\(.*\)-\(.*\)-\(.*\)$/\1/'` + build_vendor=`echo $result | sed 's/^\(.*\)-\(.*\)-\(.*\)$/\2/'` + build_os=`echo $result | sed 's/^\(.*\)-\(.*\)-\(.*\)$/\3/'` + build=${build_cpu}-${build_vendor}-${build_os} + else + echo "Unrecognized build system name ${build_alias}." 1>&2 + exit 1 + fi + ;; +esac + +if result=`${config_shell} ${configsub} ${host_alias}` ; then + true +else + echo "Unrecognized host system name ${host_alias}." 1>&2 + exit 1 +fi +host_cpu=`echo $result | sed 's/^\(.*\)-\(.*\)-\(.*\)$/\1/'` +host_vendor=`echo $result | sed 's/^\(.*\)-\(.*\)-\(.*\)$/\2/'` +host_os=`echo $result | sed 's/^\(.*\)-\(.*\)-\(.*\)$/\3/'` +host=${host_cpu}-${host_vendor}-${host_os} + +. ${tmpfile}.hst + +if result=`${config_shell} ${configsub} ${target_alias}` ; then + true +else + echo "Unrecognized target system name ${target_alias}." 1>&2 + exit 1 +fi +target_cpu=`echo $result | sed 's/^\(.*\)-\(.*\)-\(.*\)$/\1/'` +target_vendor=`echo $result | sed 's/^\(.*\)-\(.*\)-\(.*\)$/\2/'` +target_os=`echo $result | sed 's/^\(.*\)-\(.*\)-\(.*\)$/\3/'` +target=${target_cpu}-${target_vendor}-${target_os} + +. ${tmpfile}.tgt + +# Find the source files, if location was not specified. +case "${srcdir}" in +"") + srcdirdefaulted=1 + srcdir=. + if [ ! -r ${srctrigger} ] ; then + srcdir=.. + fi + ;; +*) ;; +esac + +if [ ! -r ${srcdir}/${srctrigger} ] ; then + case "${srcdirdefaulted}" in + "") echo '***' "${progname}: Can't find ${srcname} sources in ${PWD=`pwd`}/${srcdir}" 1>&2 ;; + *) echo '***' "${progname}: Can't find ${srcname} sources in ${PWD=`pwd`}/. or ${PWD=`pwd`}/.." 1>&2 ;; + esac + + echo '***' \(At least ${srctrigger} is missing.\) 1>&2 + exit 1 +fi + +# Some systems (e.g., one of the i386-aix systems the gas testers are +# using) don't handle "\$" correctly, so don't use it here. +tooldir='$(exec_prefix)'/${target_alias} + +if [ "${host_alias}" != "${target_alias}" ] ; then + if [ "${program_prefixoption}" = "" ] ; then + if [ "${program_suffixoption}" = "" ] ; then + if [ "${program_transform_nameoption}" = "" ] ; then + program_prefix=${target_alias}- ; + fi + fi + fi +fi + +# Merge program_prefix and program_suffix onto program_transform_name. +# (program_suffix used to use $, but it's hard to preserve $ through both +# make and sh.) +if [ "${program_suffix}" != "" ] ; then + program_transform_name="-e s,\\\\(.*\\\\),\\\\1${program_suffix}, ${program_transform_name}" +fi + +if [ "${program_prefix}" != "" ] ; then + program_transform_name="-e s,^,${program_prefix}, ${program_transform_name}" +fi + +# If CC and CXX are not set in the environment, and the Makefile +# exists, try to extract them from it. This is to handle running +# ./config.status by hand. +if [ -z "${CC}" -a -r Makefile ]; then + sed -n -e ':loop +/\\$/ N +/\\$/ b loop +s/\\\n//g +/^CC[ ]*=/ s/CC[ ]*=[ ]*\(.*\)/\1/p' < Makefile > Makefile.cc + CC=`tail -1 Makefile.cc` + rm -f Makefile.cc +fi + +if [ -z "${CXX}" -a -r Makefile ]; then + sed -n -e ':loop +/\\$/ N +/\\$/ b loop +s/\\\n//g +/^CXX[ ]*=/ s/CXX[ ]*=[ ]*\(.*\)/\1/p' < Makefile > Makefile.cc + CXX=`tail -1 Makefile.cc` + rm -f Makefile.cc +fi + +if [ "${build}" != "${host}" ]; then + # If we are doing a Canadian Cross, in which the host and build systems + # are not the same, we set reasonable default values for the tools. + + tools="AR AR_FOR_TARGET AS AS_FOR_TARGET BISON CC_FOR_BUILD" + tools="${tools} CC_FOR_TARGET CXX_FOR_TARGET" + tools="${tools} DLLTOOL DLLTOOL_FOR_TARGET HOST_PREFIX" + tools="${tools} HOST_PREFIX_1 LD LD_FOR_TARGET LEX MAKEINFO NM" + tools="${tools} NM_FOR_TARGET RANLIB RANLIB_FOR_TARGET" + + for var in ${tools}; do + if [ -z "`eval 'echo $'"${var}"`" -a -r Makefile ]; then + sed -n -e ':loop +/\\$/ N +/\\$/ b loop +s/\\\n//g +/^'"${var}"'[ ]*=/ s/'"${var}"'[ ]*=[ ]*\(.*\)/\1/p' \ + < Makefile > Makefile.v + t=`tail -1 Makefile.v` + if [ -n "${t}" ]; then + eval "${var}='${t}'" + fi + rm -f Makefile.v + fi + done + + AR=${AR-${host_alias}-ar} + AR_FOR_TARGET=${AR_FOR_TARGET-${target_alias}-ar} + AS=${AS-${host_alias}-as} + AS_FOR_TARGET=${AS_FOR_TARGET-${target_alias}-as} + CC=${CC-${host_alias}-gcc} + CXX=${CXX-${host_alias}-gcc} + CC_FOR_BUILD=${CC_FOR_BUILD-gcc} + CC_FOR_TARGET=${CC_FOR_TARGET-${target_alias}-gcc} + CXX_FOR_TARGET=${CXX_FOR_TARGET-${target_alias}-gcc} + DLLTOOL=${DLLTOOL-${host_alias}-dlltool} + DLLTOOL_FOR_TARGET=${DLLTOOL_FOR_TARGET-${target_alias}-dlltool} + HOST_PREFIX=${build_alias}- + HOST_PREFIX_1=${build_alias}- + LD=${LD-${host_alias}-ld} + LD_FOR_TARGET=${LD_FOR_TARGET-${target_alias}-ld} + MAKEINFO=${MAKEINFO-makeinfo} + NM=${NM-${host_alias}-nm} + NM_FOR_TARGET=${NM_FOR_TARGET-${target_alias}-nm} + RANLIB=${RANLIB-${host_alias}-ranlib} + RANLIB_FOR_TARGET=${RANLIB_FOR_TARGET-${target_alias}-ranlib} + + if [ -z "${BISON}" ]; then + IFS="${IFS= }"; save_ifs="$IFS"; IFS="${IFS}:" + for dir in $PATH; do + test -z "$dir" && dir=. + if test -f $dir/byacc; then + BISON=byacc + break + fi + if test -f $dir/bison; then + BISON=bison + break + fi + if test -f $dir/yacc; then + BISON=yacc + break + fi + done + IFS="$save_ifs" + BISON=${BISON-bison} + fi + + if [ -z "${LEX}" ]; then + IFS="${IFS= }"; save_ifs="$IFS"; IFS="${IFS}:" + for dir in $PATH; do + test -z "$dir" && dir=. + if test -f $dir/flex; then + LEX=flex + break + fi + if test -f $dir/lex; then + LEX=lex + break + fi + done + IFS="$save_ifs" + LEX=${LEX-flex} + fi + + # Export variables which autoconf might try to set. + export AS + export AR + export CC_FOR_BUILD + export DLLTOOL + export LD + export NM + export RANLIB +else + # If CC is still not set, try to get gcc. + if [ x$with_gcc != xno -a -z "${CC}" ]; then + IFS="${IFS= }"; save_ifs="$IFS"; IFS="${IFS}:" + for dir in $PATH; do + test -z "$dir" && dir=. + if test -f $dir/gcc; then + CC="gcc -O2" + break + fi + done + IFS="$save_ifs" + CC=${CC-cc} + fi + + CXX=${CXX-"gcc"} +fi + +export CC +export CXX + +case "$host" in + *go32*) + enable_gdbtk=no ;; +esac + +# Determine whether gdb needs tk/tcl or not. +if [ "$enable_gdbtk" != "no" ]; then + GDB_TK="all-tcl all-tk" +else + GDB_TK="" +fi + +for subdir in . ${subdirs} ; do + + # ${subdir} is relative path from . to the directory we're currently + # configuring. + # ${invsubdir} is inverse of ${subdir), *with* trailing /, if needed. + invsubdir=`echo ${subdir}/ | sed -e 's|\./||g' -e 's|[^/]*/|../|g'` + + ### figure out what to do with srcdir + case "${srcdir}" in + ".") # no -srcdir option. We're building in place. + makesrcdir=. ;; + /*) # absolute path + makesrcdir=`echo ${srcdir}/${subdir} | sed -e 's|/\.$||'` + ;; + *) # otherwise relative + case "${subdir}" in + .) makesrcdir=${srcdir} ;; + *) makesrcdir=${invsubdir}${srcdir}/${subdir} ;; + esac + ;; + esac + + if [ "${subdir}/" != "./" ] ; then + Makefile=${subdir}/Makefile + fi + + if [ ! -d ${subdir} ] ; then + if mkdir ${subdir} ; then + true + else + echo '***' "${progname}: could not make ${PWD=`pwd`}/${subdir}" 1>&2 + exit 1 + fi + fi + + case "${removing}" in + "") + case "${subdir}" in + .) ;; + *) eval echo Building in ${subdir} ${redirect} ;; + esac + + # FIXME Should this be done recursively ??? (Useful for e.g. gdbtest) + # Set up the list of links to be made. + # ${links} is the list of link names, and ${files} is the list of names to link to. + + # Make the links. + configlinks="${links}" + if [ -r ${subdir}/config.status ] ; then + mv -f ${subdir}/config.status ${subdir}/config.back + fi + while [ -n "${files}" ] ; do + # set file to car of files, files to cdr of files + set ${files}; file=$1; shift; files=$* + set ${links}; link=$1; shift; links=$* + + if [ ! -r ${srcdir}/${file} ] ; then + echo '***' "${progname}: cannot create a link \"${link}\"," 1>&2 + echo '***' "since the file \"${srcdir}/${file}\" does not exist." 1>&2 + exit 1 + fi + + ${remove} -f ${link} + # Make a symlink if possible, otherwise try a hard link + if ${symbolic_link} ${srcdir}/${file} ${link} >/dev/null 2>&1 ; then + true + else + # We need to re-remove the file because Lynx leaves a + # very strange directory there when it fails an NFS symlink. + ${remove} -r -f ${link} + ${hard_link} ${srcdir}/${file} ${link} + fi + if [ ! -r ${link} ] ; then + echo '***' "${progname}: unable to link \"${link}\" to \"${srcdir}/${file}\"." 1>&2 + exit 1 + fi + + echo "Linked \"${link}\" to \"${srcdir}/${file}\"." + done + + # Create a .gdbinit file which runs the one in srcdir + # and tells GDB to look there for source files. + + if [ -r ${srcdir}/${subdir}/.gdbinit ] ; then + case ${srcdir} in + .) ;; + *) cat > ${subdir}/.gdbinit <<EOF +# ${NO_EDIT} +dir ${makesrcdir} +dir . +source ${makesrcdir}/.gdbinit +EOF + ;; + esac + fi + + # Install a makefile, and make it set VPATH + # if necessary so that the sources are found. + # Also change its value of srcdir. + # NOTE: Makefile generation constitutes the majority of the time in configure. Hence, this section has + # been somewhat optimized and is perhaps a bit twisty. + + # code is order so as to try to sed the smallest input files we know. + + # the four makefile fragments MUST end up in the resulting Makefile in this order: + # package, target, host, and site. so do these separately because I don't trust the + # order of sed -e expressions. + + if [ -f ${srcdir}/${subdir}/${Makefile_in} ] ; then + + # Conditionalize for this site from "Makefile.in" (or whatever it's called) into Makefile.tem + rm -f ${subdir}/Makefile.tem + case "${site}" in + "") cp ${srcdir}/${subdir}/${Makefile_in} ${subdir}/Makefile.tem ;; + *) + site_makefile_frag=${srcdir}/config/ms-${site} + + if [ -f ${site_makefile_frag} ] ; then + sed -e "/^####/ r ${site_makefile_frag}" ${srcdir}/${subdir}/${Makefile_in} \ + > ${subdir}/Makefile.tem + else + cp ${srcdir}/${subdir}/${Makefile_in} ${subdir}/Makefile.tem + site_makefile_frag= + fi + ;; + esac + # working copy now in ${subdir}/Makefile.tem + + # Conditionalize the makefile for this host. + rm -f ${Makefile} + case "${host_makefile_frag}" in + "") mv ${subdir}/Makefile.tem ${Makefile} ;; + *) + if [ ! -f ${host_makefile_frag} ] ; then + host_makefile_frag=${srcdir}/${host_makefile_frag} + fi + if [ -f ${host_makefile_frag} ] ; then + sed -e "/^####/ r ${host_makefile_frag}" ${subdir}/Makefile.tem > ${Makefile} + else + echo '***' Expected host makefile fragment \"${host_makefile_frag}\" 1>&2 + echo '***' is missing in ${PWD=`pwd`}. 1>&2 + mv ${subdir}/Makefile.tem ${Makefile} + fi + esac + # working copy now in ${Makefile} + + # Conditionalize the makefile for this target. + rm -f ${subdir}/Makefile.tem + case "${target_makefile_frag}" in + "") mv ${Makefile} ${subdir}/Makefile.tem ;; + *) + if [ ! -f ${target_makefile_frag} ] ; then + target_makefile_frag=${srcdir}/${target_makefile_frag} + fi + if [ -f ${target_makefile_frag} ] ; then + sed -e "/^####/ r ${target_makefile_frag}" ${Makefile} > ${subdir}/Makefile.tem + else + mv ${Makefile} ${subdir}/Makefile.tem + target_makefile_frag= + fi + ;; + esac + # real copy now in ${subdir}/Makefile.tem + + # Conditionalize the makefile for this package. + rm -f ${Makefile} + case "${package_makefile_frag}" in + "") mv ${subdir}/Makefile.tem ${Makefile} ;; + *) + if [ ! -f ${package_makefile_frag} ] ; then + package_makefile_frag=${srcdir}/${package_makefile_frag} + fi + if [ -f ${package_makefile_frag} ] ; then + sed -e "/^####/ r ${package_makefile_frag}" ${subdir}/Makefile.tem > ${Makefile} + rm -f ${subdir}/Makefile.tem + else + echo '***' Expected package makefile fragment \"${package_makefile_frag}\" 1>&2 + echo '***' is missing in ${PWD=`pwd`}. 1>&2 + mv ${subdir}/Makefile.tem ${Makefile} + fi + esac + # working copy now in ${Makefile} + + mv ${Makefile} ${subdir}/Makefile.tem + + # real copy now in ${subdir}/Makefile.tem + + # prepend warning about editting, and a bunch of variables. + rm -f ${Makefile} + cat > ${Makefile} <<EOF +# ${NO_EDIT} +VPATH = ${makesrcdir} +links = ${configlinks} +host_alias = ${host_alias} +host_cpu = ${host_cpu} +host_vendor = ${host_vendor} +host_os = ${host_os} +host_canonical = ${host_cpu}-${host_vendor}-${host_os} +target_alias = ${target_alias} +target_cpu = ${target_cpu} +target_vendor = ${target_vendor} +target_os = ${target_os} +target_canonical = ${target_cpu}-${target_vendor}-${target_os} +EOF + case "${build}" in + "") ;; + *) cat >> ${Makefile} << EOF +build_alias = ${build_alias} +build_cpu = ${build_cpu} +build_vendor = ${build_vendor} +build_os = ${build_os} +build_canonical = ${build_cpu}-${build_vendor}-${build_os} +EOF + esac + + case "${package_makefile_frag}" in + "") ;; + /*) echo package_makefile_frag = ${package_makefile_frag} >>${Makefile} ;; + *) echo package_makefile_frag = ${invsubdir}${package_makefile_frag} >>${Makefile} ;; + esac + + case "${target_makefile_frag}" in + "") ;; + /*) echo target_makefile_frag = ${target_makefile_frag} >>${Makefile} ;; + *) echo target_makefile_frag = ${invsubdir}${target_makefile_frag} >>${Makefile} ;; + esac + + case "${host_makefile_frag}" in + "") ;; + /*) echo host_makefile_frag = ${host_makefile_frag} >>${Makefile} ;; + *) echo host_makefile_frag = ${invsubdir}${host_makefile_frag} >>${Makefile} ;; + esac + + if [ "${site_makefile_frag}" != "" ] ; then + echo site_makefile_frag = ${invsubdir}${site_makefile_frag} >>${Makefile} + fi + + # reset prefix, exec_prefix, srcdir, SUBDIRS, NONSUBDIRS, + # remove any form feeds. + if [ -z "${subdirs}" ]; then + rm -f ${subdir}/Makefile.tem2 + sed -e "s:^SUBDIRS[ ]*=.*$:SUBDIRS = ${configdirs}:" \ + -e "s:^NONSUBDIRS[ ]*=.*$:NONSUBDIRS = ${noconfigdirs}:" \ + ${subdir}/Makefile.tem > ${subdir}/Makefile.tem2 + rm -f ${subdir}/Makefile.tem + mv ${subdir}/Makefile.tem2 ${subdir}/Makefile.tem + fi + sed -e "s:^prefix[ ]*=.*$:prefix = ${prefix}:" \ + -e "s:^exec_prefix[ ]*=.*$:exec_prefix = ${exec_prefix}:" \ + -e "/^CC[ ]*=/{ + :loop1 + /\\\\$/ N + /\\\\$/ b loop1 + s/\\\\\\n//g + s%^CC[ ]*=.*$%CC = ${CC}% + }" \ + -e "/^CXX[ ]*=/{ + :loop2 + /\\\\$/ N + /\\\\$/ b loop2 + s/\\\\\\n//g + s%^CXX[ ]*=.*$%CXX = ${CXX}% + }" \ + -e "s:^SHELL[ ]*=.*$:SHELL = ${config_shell}:" \ + -e "s:^GDB_TK[ ]*=.*$:GDB_TK = ${GDB_TK}:" \ + -e "s:^srcdir[ ]*=.*$:srcdir = ${makesrcdir}:" \ + -e "s///" \ + -e "s:^program_prefix[ ]*=.*$:program_prefix = ${program_prefix}:" \ + -e "s:^program_suffix[ ]*=.*$:program_suffix = ${program_suffix}:" \ + -e "s:^program_transform_name[ ]*=.*$:program_transform_name = ${program_transform_name}:" \ + -e "s:^tooldir[ ]*=.*$:tooldir = ${tooldir}:" \ + ${subdir}/Makefile.tem >> ${Makefile} + + # If this is a Canadian Cross, preset the values of many more + # tools. + if [ "${build}" != "${host}" ]; then + for var in ${tools}; do + val=`eval 'echo $'"${var}"` + sed -e "/^${var}[ ]*=/{ + :loop1 + /\\\\$/ N + /\\\\$/ b loop1 + s/\\\\\\n//g + s%^${var}[ ]*=.*$%${var} = ${val}% + }" ${Makefile} > ${Makefile}.tem + mv -f ${Makefile}.tem ${Makefile} + done + fi + + # final copy now in ${Makefile} + + else + echo "No Makefile.in found in ${srcdir}/${subdir}, unable to configure" 1>&2 + fi + + rm -f ${subdir}/Makefile.tem + + case "${host_makefile_frag}" in + "") using= ;; + *) using="and \"${host_makefile_frag}\"" ;; + esac + + case "${target_makefile_frag}" in + "") ;; + *) using="${using} and \"${target_makefile_frag}\"" ;; + esac + + case "${site_makefile_frag}" in + "") ;; + *) using="${using} and \"${site_makefile_frag}\"" ;; + esac + + newusing=`echo "${using}" | sed 's/and/using/'` + using=${newusing} + echo "Created \"${Makefile}\" in" ${PWD=`pwd`} ${using} + + . ${tmpfile}.pos + + # describe the chosen configuration in config.status. + # Make that file a shellscript which will reestablish + # the same configuration. Used in Makefiles to rebuild + # Makefiles. + + case "${norecursion}" in + "") arguments="${arguments} --norecursion" ;; + *) ;; + esac + + if [ ${subdir} = . ] ; then + echo "#!/bin/sh +# ${NO_EDIT} +# This directory was configured as follows: +${progname}" ${arguments} " +# ${using}" > ${subdir}/config.new + else + echo "#!/bin/sh +# ${NO_EDIT} +# This directory was configured as follows: +cd ${invsubdir} +${progname}" ${arguments} " +# ${using}" > ${subdir}/config.new + fi + chmod a+x ${subdir}/config.new + if [ -r ${subdir}/config.back ] ; then + mv -f ${subdir}/config.back ${subdir}/config.status + fi + ${moveifchange} ${subdir}/config.new ${subdir}/config.status + ;; + + *) rm -f ${Makefile} ${subdir}/config.status ${links} ;; + esac +done + +# If there are subdirectories, then recur. +if [ -z "${norecursion}" -a -n "${configdirs}" ] ; then + for configdir in ${configdirs} ; do + + if [ -d ${srcdir}/${configdir} ] ; then + eval echo Configuring ${configdir}... ${redirect} + case "${srcdir}" in + ".") ;; + *) + if [ ! -d ./${configdir} ] ; then + if mkdir ./${configdir} ; then + true + else + echo '***' "${progname}: could not make ${PWD=`pwd`}/${configdir}" 1>&2 + exit 1 + fi + fi + ;; + esac + + POPDIR=${PWD=`pwd`} + cd ${configdir} + +### figure out what to do with srcdir + case "${srcdir}" in + ".") newsrcdir=${srcdir} ;; # no -srcdir option. We're building in place. + /*) # absolute path + newsrcdir=${srcdir}/${configdir} + srcdiroption="--srcdir=${newsrcdir}" + ;; + *) # otherwise relative + newsrcdir=../${srcdir}/${configdir} + srcdiroption="--srcdir=${newsrcdir}" + ;; + esac + + # Handle --cache-file=../XXX + case "${cache_file}" in + "") # empty + ;; + /*) # absolute path + cache_file_option="--cache-file=${cache_file}" + ;; + *) # relative path + cache_file_option="--cache-file=../${cache_file}" + ;; + esac + +### check for guested configure, otherwise fix possibly relative progname + if [ -f ${newsrcdir}/configure ] ; then + recprog=${newsrcdir}/configure + elif [ -f ${newsrcdir}/configure.in ] ; then + case "${progname}" in + /*) recprog=${progname} ;; + *) recprog=../${progname} ;; + esac + else + eval echo No configuration information in ${configdir} ${redirect} + recprog= + fi + +### The recursion line is here. + if [ ! -z "${recprog}" ] ; then + if eval ${config_shell} ${recprog} ${verbose} ${buildopt} --host=${host_alias} --target=${target_alias} \ + ${prefixoption} ${tmpdiroption} ${exec_prefixoption} \ + ${srcdiroption} ${program_prefixoption} ${program_suffixoption} ${program_transform_nameoption} ${site_option} ${withoptions} ${withoutoptions} ${enableoptions} ${disableoptions} ${floating_pointoption} ${cache_file_option} ${removing} ${other_options} ${redirect} ; then + true + else + echo Configure in `pwd` failed, exiting. 1>&2 + exit 1 + fi + fi + + cd ${POPDIR} + fi + done +fi + +# Perform the same cleanup as the trap handler, minus the "exit 1" of course, +# and reset the trap handler. +rm -f ${tmpfile}.com ${tmpfile}.tgt ${tmpfile}.hst ${tmpfile}.pos +trap 0 + +exit 0 + +# +# Local Variables: +# fill-column: 131 +# End: +# + +# end of configure diff --git a/contrib/libgmp/configure.in b/contrib/libgmp/configure.in new file mode 100644 index 0000000..42192b5 --- /dev/null +++ b/contrib/libgmp/configure.in @@ -0,0 +1,35 @@ +# This file is a shell script fragment that supplies the information +# necessary for a configure script to process the program in +# this directory. For more information, look at ../configure. + +configdirs="mpn mpz mpf mpq mpbsd" +srctrigger=gmp-impl.h +srcname="GNU Multi-Precision library" + +# per-host: + +# per-target: + +case "${target}" in + sparc8* | microsparc*) + if [ x$with_gcc != xno ] + then + target_makefile_frag=config/mt-sprc8-gcc + fi + ;; + supersparc*) + if [ x$with_gcc != xno ] + then + target_makefile_frag=config/mt-supspc-gcc + fi + ;; + m888110*) + if [ x$with_gcc != xno ] + then + target_makefile_frag=config/mt-m88110 + fi + ;; + *-*-linux*) + target_makefile_frag=config/mt-linux ;; + +esac diff --git a/contrib/libgmp/cre-mparam.c b/contrib/libgmp/cre-mparam.c new file mode 100644 index 0000000..2020c8a --- /dev/null +++ b/contrib/libgmp/cre-mparam.c @@ -0,0 +1,16 @@ +#include "gmp.h" + +main () +{ +printf ("/* gmp-mparam.h -- Compiler/machine parameter header file.\n\n"); +printf (" *** CREATED BY A PROGRAM -- DO NOT EDIT ***\n\n"); +printf ("Copyright (C) 1996 Free Software Foundation, Inc. */\n\n"); + +printf ("#define BITS_PER_MP_LIMB %d\n", 8 * sizeof (mp_limb_t)); +printf ("#define BYTES_PER_MP_LIMB %d\n", sizeof (mp_limb_t)); +printf ("#define BITS_PER_LONGINT %d\n", 8 * sizeof (long)); +printf ("#define BITS_PER_INT %d\n", 8 * sizeof (int)); +printf ("#define BITS_PER_SHORTINT %d\n", 8 * sizeof (short)); +printf ("#define BITS_PER_CHAR 8\n"); +exit (0); +} diff --git a/contrib/libgmp/demos/factorize.c b/contrib/libgmp/demos/factorize.c new file mode 100644 index 0000000..4a965d3 --- /dev/null +++ b/contrib/libgmp/demos/factorize.c @@ -0,0 +1,233 @@ +/* Factoring with Pollard's rho method. + + Copyright (C) 1995 Free Software Foundation, Inc. + +This program is free software; you can redistribute it and/or modify it +under the terms of the GNU General Public License as published by the +Free Software Foundation; either version 2, or (at your option) any +later version. + +This program is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License along +with this program; see the file COPYING. If not, write to the Free Software +Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + +#include <stdio.h> +#include "gmp.h" + +int flag_mersenne = 0; + +static unsigned add[] = {4, 2, 4, 2, 4, 6, 2, 6}; + +factor_using_division (t, limit) + mpz_t t; + unsigned int limit; +{ + mpz_t q, r; + unsigned long int f; + int i, ai; + unsigned *addv = add; + + mpz_init (q); + mpz_init (r); + + if (mpz_probab_prime_p (t, 50)) + goto ready; + + for (;;) + { + mpz_tdiv_qr_ui (q, r, t, 2); + if (mpz_cmp_ui (r, 0) != 0) + break; + mpz_set (t, q); + printf ("2 "); + fflush (stdout); + if (mpz_probab_prime_p (t, 50)) + goto ready; + } + + for (;;) + { + mpz_tdiv_qr_ui (q, r, t, 3); + if (mpz_cmp_ui (r, 0) != 0) + break; + mpz_set (t, q); + printf ("3 "); + fflush (stdout); + if (mpz_probab_prime_p (t, 50)) + goto ready; + } + + for (;;) + { + mpz_tdiv_qr_ui (q, r, t, 5); + if (mpz_cmp_ui (r, 0) != 0) + break; + mpz_set (t, q); + printf ("5 "); + fflush (stdout); + if (mpz_probab_prime_p (t, 50)) + goto ready; + } + + f = 7; + ai = 0; + for (;;) + { + mpz_tdiv_qr_ui (q, r, t, f); + if (mpz_cmp_ui (r, 0) != 0) + { + f += addv[ai]; + if (f > limit) + goto ret; + ai = (ai + 1) & 7; + } + else + { + mpz_set (t, q); + printf ("%lu ", f); + fflush (stdout); + if (mpz_probab_prime_p (t, 50)) + goto ready; + } + } + + ready: + mpz_out_str (stdout, 10, t); + fflush (stdout); + mpz_set_ui (t, 1); + fputc (' ', stdout); + ret: + mpz_clear (q); + mpz_clear (r); +} + +void +factor_using_pollard_rho (m, a_int, x0, p) + mpz_t m; + long a_int; + long x0; + unsigned long p; +{ + mpz_t x, y, q; + mpz_t a; + mpz_t d; + mpz_t tmp; + mpz_t n; + int i = 1; + int j = 1; + + mpz_init_set (n, m); + + mpz_init (d); + mpz_init_set_ui (q, 1); + mpz_init (tmp); + + mpz_init_set_si (a, a_int); + mpz_init_set_si (x, x0); + mpz_init_set_si (y, x0); + + while (mpz_cmp_ui (n, 1) != 0) + { + if (flag_mersenne) + { + mpz_powm_ui (x, x, p, n); mpz_add (x, x, a); + mpz_powm_ui (y, y, p, n); mpz_add (y, y, a); + mpz_powm_ui (y, y, p, n); mpz_add (y, y, a); + } + else + { + mpz_mul (x, x, x); mpz_add (x, x, a); mpz_mod (x, x, n); + mpz_mul (y, y, y); mpz_add (y, y, a); mpz_mod (y, y, n); + mpz_mul (y, y, y); mpz_add (y, y, a); mpz_mod (y, y, n); + } + + if (mpz_cmp (x, y) > 0) + mpz_sub (tmp, x, y); + else + mpz_sub (tmp, y, x); + mpz_mul (q, q, tmp); + mpz_mod (q, q, n); + + if (++i % j == 0) + { + j += 1; + mpz_gcd (d, q, n); + if (mpz_cmp_ui (d, 1) != 0) + { + if (!mpz_probab_prime_p (d, 50)) + factor_using_pollard_rho (d, (random () & 31) - 16, + (random () & 31), p); + else + { + mpz_out_str (stdout, 10, d); + fflush (stdout); + fputc (' ', stdout); + } + mpz_div (n, n, d); + if (mpz_probab_prime_p (n, 50)) + { + mpz_out_str (stdout, 10, n); + fflush (stdout); + fputc (' ', stdout); + break; + } + } + } + } + + mpz_clear (n); + mpz_clear (d); + mpz_clear (q); + mpz_clear (tmp); + mpz_clear (a); + mpz_clear (x); + mpz_clear (y); +} + +factor (t, a, x0, p) + mpz_t t; + long a; + long x0; + unsigned long p; +{ + factor_using_division (t, 1000000); + factor_using_pollard_rho (t, a, x0, p); +} + +main (argc, argv) + int argc; + char *argv[]; +{ + mpz_t t; + long x0, a; + unsigned long p; + int i; + + for (i = 1; i < argc; i++) + { + if (!strncmp (argv[i], "-Mp", 3)) + { + p = atoi (argv[i] + 3); + mpz_init_set_ui (t, 1); + mpz_mul_2exp (t, t, p); + mpz_sub_ui (t, t, 1); + flag_mersenne = 1; + } + else + { + p = 0; + mpz_init_set_str (t, argv[i], 0); + } + + a = -1; + x0 = 3; + + factor (t, a, x0, p); + puts (""); + } +} diff --git a/contrib/libgmp/extract-double.c b/contrib/libgmp/extract-double.c new file mode 100644 index 0000000..052b1a9 --- /dev/null +++ b/contrib/libgmp/extract-double.c @@ -0,0 +1,160 @@ +/* __gmp_extract_double -- convert from double to array of mp_limb_t. + +Copyright (C) 1996 Free Software Foundation, Inc. + +This file is part of the GNU MP Library. + +The GNU MP Library is free software; you can redistribute it and/or modify +it under the terms of the GNU Library General Public License as published by +the Free Software Foundation; either version 2 of the License, or (at your +option) any later version. + +The GNU MP Library is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public +License for more details. + +You should have received a copy of the GNU Library General Public License +along with the GNU MP Library; see the file COPYING.LIB. If not, write to +the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, +MA 02111-1307, USA. */ + +#include "gmp.h" +#include "gmp-impl.h" + +#ifdef XDEBUG +#undef _GMP_IEEE_FLOATS +#endif + +#ifndef _GMP_IEEE_FLOATS +#define _GMP_IEEE_FLOATS 0 +#endif + +#define MP_BASE_AS_DOUBLE (2.0 * ((mp_limb_t) 1 << (BITS_PER_MP_LIMB - 1))) + +/* Extract a non-negative double in d. */ + +int +#if __STDC__ +__gmp_extract_double (mp_ptr rp, double d) +#else +__gmp_extract_double (rp, d) + mp_ptr rp; + double d; +#endif +{ + long exp; + unsigned sc; + mp_limb_t manh, manl; + + /* BUGS + + 1. Should handle Inf and NaN in IEEE specific code. + 2. Handle Inf and NaN also in default code, to avoid hangs. + 3. Generalize to handle all BITS_PER_MP_LIMB >= 32. + 4. This lits is incomplete and misspelled. + */ + + if (d == 0.0) + { + rp[0] = 0; + rp[1] = 0; +#if BITS_PER_MP_LIMB == 32 + rp[2] = 0; +#endif + return 0; + } + +#if _GMP_IEEE_FLOATS + { + union ieee_double_extract x; + x.d = d; + + exp = x.s.exp; + sc = (unsigned) (exp + 2) % BITS_PER_MP_LIMB; +#if BITS_PER_MP_LIMB == 64 + manl = (((mp_limb_t) 1 << 63) + | ((mp_limb_t) x.s.manh << 43) | ((mp_limb_t) x.s.manl << 11)); +#else + manh = ((mp_limb_t) 1 << 31) | (x.s.manh << 11) | (x.s.manl >> 21); + manl = x.s.manl << 11; +#endif + } +#else + { + /* Unknown (or known to be non-IEEE) double format. */ + exp = 0; + if (d >= 1.0) + { + if (d * 0.5 == d) + abort (); + + while (d >= 32768.0) + { + d *= (1.0 / 65536.0); + exp += 16; + } + while (d >= 1.0) + { + d *= 0.5; + exp += 1; + } + } + else if (d < 0.5) + { + while (d < (1.0 / 65536.0)) + { + d *= 65536.0; + exp -= 16; + } + while (d < 0.5) + { + d *= 2.0; + exp -= 1; + } + } + + sc = (unsigned) exp % BITS_PER_MP_LIMB; + + d *= MP_BASE_AS_DOUBLE; +#if BITS_PER_MP_LIMB == 64 + manl = d; +#else + manh = d; + manl = (d - manh) * MP_BASE_AS_DOUBLE; +#endif + + exp += 1022; + } +#endif + + exp = (unsigned) (exp + 1) / BITS_PER_MP_LIMB - 1024 / BITS_PER_MP_LIMB + 1; + +#if BITS_PER_MP_LIMB == 64 + if (sc != 0) + { + rp[1] = manl >> (BITS_PER_MP_LIMB - sc); + rp[0] = manl << sc; + } + else + { + rp[1] = manl; + rp[0] = 0; + } +#else + if (sc != 0) + { + rp[2] = manh >> (BITS_PER_MP_LIMB - sc); + rp[1] = (manl >> (BITS_PER_MP_LIMB - sc)) | (manh << sc); + rp[0] = manl << sc; + } + else + { + rp[2] = manh; + rp[1] = manl; + rp[0] = 0; + } +#endif + + return exp; +} diff --git a/contrib/libgmp/gmp-impl.h b/contrib/libgmp/gmp-impl.h new file mode 100644 index 0000000..7d56846 --- /dev/null +++ b/contrib/libgmp/gmp-impl.h @@ -0,0 +1,367 @@ +/* Include file for internal GNU MP types and definitions. + +Copyright (C) 1991, 1993, 1994, 1995, 1996 Free Software Foundation, Inc. + +This file is part of the GNU MP Library. + +The GNU MP Library is free software; you can redistribute it and/or modify +it under the terms of the GNU Library General Public License as published by +the Free Software Foundation; either version 2 of the License, or (at your +option) any later version. + +The GNU MP Library is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public +License for more details. + +You should have received a copy of the GNU Library General Public License +along with the GNU MP Library; see the file COPYING.LIB. If not, write to +the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, +MA 02111-1307, USA. */ + +/* When using gcc, make sure to use its builtin alloca. */ +#if ! defined (alloca) && defined (__GNUC__) +#define alloca __builtin_alloca +#define HAVE_ALLOCA +#endif + +/* When using cc, do whatever necessary to allow use of alloca. For many + machines, this means including alloca.h. IBM's compilers need a #pragma + in "each module that needs to use alloca". */ +#if ! defined (alloca) +/* We need lots of variants for MIPS, to cover all versions and perversions + of OSes for MIPS. */ +#if defined (__mips) || defined (MIPSEL) || defined (MIPSEB) \ + || defined (_MIPSEL) || defined (_MIPSEB) || defined (__sgi) \ + || defined (__alpha) || defined (__sparc) || defined (sparc) \ + || defined (__ksr__) +#include <alloca.h> +#define HAVE_ALLOCA +#endif +#if defined (_IBMR2) +#pragma alloca +#define HAVE_ALLOCA +#endif +#if defined (__DECC) +#define alloca(x) __ALLOCA(x) +#define HAVE_ALLOCA +#endif +#endif + +#if ! defined (HAVE_ALLOCA) || USE_STACK_ALLOC +#include "stack-alloc.h" +#else +#define TMP_DECL(m) +#define TMP_ALLOC(x) alloca(x) +#define TMP_MARK(m) +#define TMP_FREE(m) +#endif + +#ifndef NULL +#define NULL ((void *) 0) +#endif + +#if ! defined (__GNUC__) +#define inline /* Empty */ +#endif + +#define ABS(x) (x >= 0 ? x : -x) +#define MIN(l,o) ((l) < (o) ? (l) : (o)) +#define MAX(h,i) ((h) > (i) ? (h) : (i)) + +/* Field access macros. */ +#define SIZ(x) ((x)->_mp_size) +#define ABSIZ(x) ABS (SIZ (x)) +#define PTR(x) ((x)->_mp_d) +#define EXP(x) ((x)->_mp_exp) +#define PREC(x) ((x)->_mp_prec) +#define ALLOC(x) ((x)->_mp_alloc) + +#include "gmp-mparam.h" +/* #include "longlong.h" */ + +#if defined (__STDC__) || defined (__cplusplus) +void *malloc (size_t); +void *realloc (void *, size_t); +void free (void *); + +extern void * (*_mp_allocate_func) (size_t); +extern void * (*_mp_reallocate_func) (void *, size_t, size_t); +extern void (*_mp_free_func) (void *, size_t); + +void *_mp_default_allocate (size_t); +void *_mp_default_reallocate (void *, size_t, size_t); +void _mp_default_free (void *, size_t); + +#else + +#define const /* Empty */ +#define signed /* Empty */ + +void *malloc (); +void *realloc (); +void free (); + +extern void * (*_mp_allocate_func) (); +extern void * (*_mp_reallocate_func) (); +extern void (*_mp_free_func) (); + +void *_mp_default_allocate (); +void *_mp_default_reallocate (); +void _mp_default_free (); +#endif + +/* Copy NLIMBS *limbs* from SRC to DST. */ +#define MPN_COPY_INCR(DST, SRC, NLIMBS) \ + do { \ + mp_size_t __i; \ + for (__i = 0; __i < (NLIMBS); __i++) \ + (DST)[__i] = (SRC)[__i]; \ + } while (0) +#define MPN_COPY_DECR(DST, SRC, NLIMBS) \ + do { \ + mp_size_t __i; \ + for (__i = (NLIMBS) - 1; __i >= 0; __i--) \ + (DST)[__i] = (SRC)[__i]; \ + } while (0) +#define MPN_COPY MPN_COPY_INCR + +/* Zero NLIMBS *limbs* AT DST. */ +#define MPN_ZERO(DST, NLIMBS) \ + do { \ + mp_size_t __i; \ + for (__i = 0; __i < (NLIMBS); __i++) \ + (DST)[__i] = 0; \ + } while (0) + +#define MPN_NORMALIZE(DST, NLIMBS) \ + do { \ + while (NLIMBS > 0) \ + { \ + if ((DST)[(NLIMBS) - 1] != 0) \ + break; \ + NLIMBS--; \ + } \ + } while (0) +#define MPN_NORMALIZE_NOT_ZERO(DST, NLIMBS) \ + do { \ + while (1) \ + { \ + if ((DST)[(NLIMBS) - 1] != 0) \ + break; \ + NLIMBS--; \ + } \ + } while (0) + +/* Initialize the MP_INT X with space for NLIMBS limbs. + X should be a temporary variable, and it will be automatically + cleared out when the running function returns. + We use __x here to make it possible to accept both mpz_ptr and mpz_t + arguments. */ +#define MPZ_TMP_INIT(X, NLIMBS) \ + do { \ + mpz_ptr __x = (X); \ + __x->_mp_alloc = (NLIMBS); \ + __x->_mp_d = (mp_ptr) TMP_ALLOC ((NLIMBS) * BYTES_PER_MP_LIMB); \ + } while (0) + +#define MPN_MUL_N_RECURSE(prodp, up, vp, size, tspace) \ + do { \ + if ((size) < KARATSUBA_THRESHOLD) \ + impn_mul_n_basecase (prodp, up, vp, size); \ + else \ + impn_mul_n (prodp, up, vp, size, tspace); \ + } while (0); +#define MPN_SQR_N_RECURSE(prodp, up, size, tspace) \ + do { \ + if ((size) < KARATSUBA_THRESHOLD) \ + impn_sqr_n_basecase (prodp, up, size); \ + else \ + impn_sqr_n (prodp, up, size, tspace); \ + } while (0); + +/* Structure for conversion between internal binary format and + strings in base 2..36. */ +struct bases +{ + /* Number of digits in the conversion base that always fits in an mp_limb_t. + For example, for base 10 on a machine where a mp_limb_t has 32 bits this + is 9, since 10**9 is the largest number that fits into a mp_limb_t. */ + int chars_per_limb; + + /* log(2)/log(conversion_base) */ + float chars_per_bit_exactly; + + /* base**chars_per_limb, i.e. the biggest number that fits a word, built by + factors of base. Exception: For 2, 4, 8, etc, big_base is log2(base), + i.e. the number of bits used to represent each digit in the base. */ + mp_limb_t big_base; + + /* A BITS_PER_MP_LIMB bit approximation to 1/big_base, represented as a + fixed-point number. Instead of dividing by big_base an application can + choose to multiply by big_base_inverted. */ + mp_limb_t big_base_inverted; +}; + +extern const struct bases __mp_bases[]; +extern mp_size_t __gmp_default_fp_limb_precision; + +/* Divide the two-limb number in (NH,,NL) by D, with DI being the largest + limb not larger than (2**(2*BITS_PER_MP_LIMB))/D - (2**BITS_PER_MP_LIMB). + If this would yield overflow, DI should be the largest possible number + (i.e., only ones). For correct operation, the most significant bit of D + has to be set. Put the quotient in Q and the remainder in R. */ +#define udiv_qrnnd_preinv(q, r, nh, nl, d, di) \ + do { \ + mp_limb_t _q, _ql, _r; \ + mp_limb_t _xh, _xl; \ + umul_ppmm (_q, _ql, (nh), (di)); \ + _q += (nh); /* DI is 2**BITS_PER_MP_LIMB too small */\ + umul_ppmm (_xh, _xl, _q, (d)); \ + sub_ddmmss (_xh, _r, (nh), (nl), _xh, _xl); \ + if (_xh != 0) \ + { \ + sub_ddmmss (_xh, _r, _xh, _r, 0, (d)); \ + _q += 1; \ + if (_xh != 0) \ + { \ + sub_ddmmss (_xh, _r, _xh, _r, 0, (d)); \ + _q += 1; \ + } \ + } \ + if (_r >= (d)) \ + { \ + _r -= (d); \ + _q += 1; \ + } \ + (r) = _r; \ + (q) = _q; \ + } while (0) +/* Like udiv_qrnnd_preinv, but for for any value D. DNORM is D shifted left + so that its most significant bit is set. LGUP is ceil(log2(D)). */ +#define udiv_qrnnd_preinv2gen(q, r, nh, nl, d, di, dnorm, lgup) \ + do { \ + mp_limb_t n2, n10, n1, nadj, q1; \ + mp_limb_t _xh, _xl; \ + n2 = ((nh) << (BITS_PER_MP_LIMB - (lgup))) + ((nl) >> 1 >> (l - 1));\ + n10 = (nl) << (BITS_PER_MP_LIMB - (lgup)); \ + n1 = ((mp_limb_signed_t) n10 >> (BITS_PER_MP_LIMB - 1)); \ + nadj = n10 + (n1 & (dnorm)); \ + umul_ppmm (_xh, _xl, di, n2 - n1); \ + add_ssaaaa (_xh, _xl, _xh, _xl, 0, nadj); \ + q1 = ~(n2 + _xh); \ + umul_ppmm (_xh, _xl, q1, d); \ + add_ssaaaa (_xh, _xl, _xh, _xl, nh, nl); \ + _xh -= (d); \ + (r) = _xl + ((d) & _xh); \ + (q) = _xh - q1; \ + } while (0) +/* Exactly like udiv_qrnnd_preinv, but branch-free. It is not clear which + version to use. */ +#define udiv_qrnnd_preinv2norm(q, r, nh, nl, d, di) \ + do { \ + mp_limb_t n2, n10, n1, nadj, q1; \ + mp_limb_t _xh, _xl; \ + n2 = (nh); \ + n10 = (nl); \ + n1 = ((mp_limb_signed_t) n10 >> (BITS_PER_MP_LIMB - 1)); \ + nadj = n10 + (n1 & (d)); \ + umul_ppmm (_xh, _xl, di, n2 - n1); \ + add_ssaaaa (_xh, _xl, _xh, _xl, 0, nadj); \ + q1 = ~(n2 + _xh); \ + umul_ppmm (_xh, _xl, q1, d); \ + add_ssaaaa (_xh, _xl, _xh, _xl, nh, nl); \ + _xh -= (d); \ + (r) = _xl + ((d) & _xh); \ + (q) = _xh - q1; \ + } while (0) + +#if defined (__GNUC__) +/* Define stuff for longlong.h. */ +typedef unsigned int UQItype __attribute__ ((mode (QI))); +typedef int SItype __attribute__ ((mode (SI))); +typedef unsigned int USItype __attribute__ ((mode (SI))); +typedef int DItype __attribute__ ((mode (DI))); +typedef unsigned int UDItype __attribute__ ((mode (DI))); +#else +typedef unsigned char UQItype; +typedef long SItype; +typedef unsigned long USItype; +#endif + +typedef mp_limb_t UWtype; +typedef unsigned int UHWtype; +#define W_TYPE_SIZE BITS_PER_MP_LIMB + +/* Internal mpn calls */ +#define impn_mul_n_basecase __MPN(impn_mul_n_basecase) +#define impn_mul_n __MPN(impn_mul_n) +#define impn_sqr_n_basecase __MPN(impn_sqr_n_basecase) +#define impn_sqr_n __MPN(impn_sqr_n) + +/* Define ieee_double_extract and _GMP_IEEE_FLOATS. */ + +#if defined (_LITTLE_ENDIAN) || defined (__LITTLE_ENDIAN__) \ + || defined (__alpha) \ + || (defined (__arm__) && defined (__ARMWEL__)) \ + || defined (__clipper__) \ + || defined (__cris) \ + || defined (__i386__) \ + || defined (__i860__) \ + || defined (__i960__) \ + || defined (MIPSEL) || defined (_MIPSEL) \ + || defined (__ns32000__) \ + || defined (__WINNT) || defined (_WIN32) +#define _GMP_IEEE_FLOATS 1 +union ieee_double_extract +{ + struct + { + unsigned int manl:32; + unsigned int manh:20; + unsigned int exp:11; + unsigned int sig:1; + } s; + double d; +}; +#else /* Need this as an #else since the tests aren't made exclusive. */ +#if defined (_BIG_ENDIAN) \ + || defined (__a29k__) || defined (_AM29K) \ + || defined (__arm__) \ + || (defined (__convex__) && defined (_IEEE_FLOAT_)) \ + || defined (__i370__) || defined (__mvs__) \ + || defined (__mc68000__) || defined (__mc68020__) || defined (__NeXT__)\ + || defined(mc68020) \ + || defined (__m88000__) \ + || defined (MIPSEB) || defined (_MIPSEB) \ + || defined (__hppa) \ + || defined (__pyr__) \ + || defined (__ibm032__) \ + || defined (_IBMR2) || defined (_ARCH_PPC) \ + || defined (__sh__) \ + || defined (__sparc) || defined (sparc) \ + || defined (__we32k__) +#define _GMP_IEEE_FLOATS 1 +union ieee_double_extract +{ + struct + { + unsigned int sig:1; + unsigned int exp:11; + unsigned int manh:20; + unsigned int manl:32; + } s; + double d; +}; +#endif +#endif + +#define MP_BASE_AS_DOUBLE (2.0 * ((mp_limb_t) 1 << (BITS_PER_MP_LIMB - 1))) +#if BITS_PER_MP_LIMB == 64 +#define LIMBS_PER_DOUBLE 2 +#else +#define LIMBS_PER_DOUBLE 3 +#endif + +double __gmp_scale2 _PROTO ((double, int)); +int __gmp_extract_double _PROTO((mp_ptr, double)); diff --git a/contrib/libgmp/gmp.h b/contrib/libgmp/gmp.h new file mode 100644 index 0000000..a1cc1ac --- /dev/null +++ b/contrib/libgmp/gmp.h @@ -0,0 +1,632 @@ +/* gmp.h -- Definitions for GNU multiple precision functions. + +Copyright (C) 1991, 1993, 1994, 1995, 1996 Free Software Foundation, Inc. + +This file is part of the GNU MP Library. + +The GNU MP Library is free software; you can redistribute it and/or modify +it under the terms of the GNU Library General Public License as published by +the Free Software Foundation; either version 2 of the License, or (at your +option) any later version. + +The GNU MP Library is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public +License for more details. + +You should have received a copy of the GNU Library General Public License +along with the GNU MP Library; see the file COPYING.LIB. If not, write to +the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, +MA 02111-1307, USA. */ + +#ifndef __GMP_H__ + +#ifndef __GNU_MP__ +#define __GNU_MP__ 2 +#define __need_size_t +#include <stddef.h> +#undef __need_size_t + +#if defined (__STDC__) || defined (__cplusplus) +#define __gmp_const const +#else +#define __gmp_const +#endif + +#if defined (__GNUC__) +#define __gmp_inline __inline__ +#else +#define __gmp_inline +#endif + +#ifndef _EXTERN_INLINE +#ifdef __GNUC__ +#define _EXTERN_INLINE extern __inline__ +#else +#define _EXTERN_INLINE static +#endif +#endif + +#ifdef _SHORT_LIMB +typedef unsigned int mp_limb_t; +typedef int mp_limb_signed_t; +#else +#ifdef _LONG_LONG_LIMB +typedef unsigned long long int mp_limb_t; +typedef long long int mp_limb_signed_t; +#else +typedef unsigned long int mp_limb_t; +typedef long int mp_limb_signed_t; +#endif +#endif + +typedef mp_limb_t * mp_ptr; +typedef __gmp_const mp_limb_t * mp_srcptr; +typedef long int mp_size_t; +typedef long int mp_exp_t; + +#ifndef __MP_SMALL__ +typedef struct +{ + int _mp_alloc; /* Number of *limbs* allocated and pointed + to by the D field. */ + int _mp_size; /* abs(SIZE) is the number of limbs + the last field points to. If SIZE + is negative this is a negative + number. */ + mp_limb_t *_mp_d; /* Pointer to the limbs. */ +} __mpz_struct; +#else +typedef struct +{ + short int _mp_alloc; /* Number of *limbs* allocated and pointed + to by the D field. */ + short int _mp_size; /* abs(SIZE) is the number of limbs + the last field points to. If SIZE + is negative this is a negative + number. */ + mp_limb_t *_mp_d; /* Pointer to the limbs. */ +} __mpz_struct; +#endif +#endif /* __GNU_MP__ */ + +/* User-visible types. */ +typedef __mpz_struct MP_INT; +typedef __mpz_struct mpz_t[1]; + +/* Structure for rational numbers. Zero is represented as 0/any, i.e. + the denominator is ignored. Negative numbers have the sign in + the numerator. */ +typedef struct +{ + __mpz_struct _mp_num; + __mpz_struct _mp_den; +#if 0 + int _mp_num_alloc; /* Number of limbs allocated + for the numerator. */ + int _mp_num_size; /* The absolute value of this field is the + length of the numerator; the sign is the + sign of the entire rational number. */ + mp_ptr _mp_num; /* Pointer to the numerator limbs. */ + int _mp_den_alloc; /* Number of limbs allocated + for the denominator. */ + int _mp_den_size; /* Length of the denominator. (This field + should always be positive.) */ + mp_ptr _mp_den; /* Pointer to the denominator limbs. */ +#endif +} __mpq_struct; + +typedef __mpq_struct MP_RAT; +typedef __mpq_struct mpq_t[1]; + +typedef struct +{ + int _mp_prec; /* Max precision, in number of `mp_limb_t's. + Set by mpf_init and modified by + mpf_set_prec. The area pointed to + by the `d' field contains `prec' + 1 + limbs. */ + int _mp_size; /* abs(SIZE) is the number of limbs + the last field points to. If SIZE + is negative this is a negative + number. */ + mp_exp_t _mp_exp; /* Exponent, in the base of `mp_limb_t'. */ + mp_limb_t *_mp_d; /* Pointer to the limbs. */ +} __mpf_struct; + +/* typedef __mpf_struct MP_FLOAT; */ +typedef __mpf_struct mpf_t[1]; + +/* Types for function declarations in gmp files. */ +/* ??? Should not pollute user name space with these ??? */ +typedef __gmp_const __mpz_struct *mpz_srcptr; +typedef __mpz_struct *mpz_ptr; +typedef __gmp_const __mpf_struct *mpf_srcptr; +typedef __mpf_struct *mpf_ptr; +typedef __gmp_const __mpq_struct *mpq_srcptr; +typedef __mpq_struct *mpq_ptr; + +#ifndef _PROTO +#if defined (__STDC__) || defined (__cplusplus) +#define _PROTO(x) x +#else +#define _PROTO(x) () +#endif +#endif + +#ifndef __MPN +#if defined (__STDC__) || defined (__cplusplus) +#define __MPN(x) __mpn_##x +#else +#define __MPN(x) __mpn_/**/x +#endif +#endif + +#if defined (FILE) || defined (H_STDIO) || defined (_H_STDIO) \ + || defined (_STDIO_H) || defined (_STDIO_H_) || defined (__STDIO_H__) \ + || defined (_STDIO_INCLUDED) +#define _GMP_H_HAVE_FILE 1 +#endif + +void mp_set_memory_functions _PROTO ((void *(*) (size_t), + void *(*) (void *, size_t, size_t), + void (*) (void *, size_t))); +extern __gmp_const int mp_bits_per_limb; + +/**************** Integer (i.e. Z) routines. ****************/ + +#if defined (__cplusplus) +extern "C" { +#endif +void *_mpz_realloc _PROTO ((mpz_ptr, mp_size_t)); + +void mpz_abs _PROTO ((mpz_ptr, mpz_srcptr)); +void mpz_add _PROTO ((mpz_ptr, mpz_srcptr, mpz_srcptr)); +void mpz_add_ui _PROTO ((mpz_ptr, mpz_srcptr, unsigned long int)); +void mpz_and _PROTO ((mpz_ptr, mpz_srcptr, mpz_srcptr)); +void mpz_array_init _PROTO ((mpz_ptr, mp_size_t, mp_size_t)); +void mpz_cdiv_q _PROTO ((mpz_ptr, mpz_srcptr, mpz_srcptr)); +unsigned long int mpz_cdiv_q_ui _PROTO ((mpz_ptr, mpz_srcptr, unsigned long int)); +void mpz_cdiv_qr _PROTO ((mpz_ptr, mpz_ptr, mpz_srcptr, mpz_srcptr)); +unsigned long int mpz_cdiv_qr_ui _PROTO ((mpz_ptr, mpz_ptr, mpz_srcptr, unsigned long int)); +void mpz_cdiv_r _PROTO ((mpz_ptr, mpz_srcptr, mpz_srcptr)); +unsigned long int mpz_cdiv_r_ui _PROTO ((mpz_ptr, mpz_srcptr, unsigned long int)); +unsigned long int mpz_cdiv_ui _PROTO ((mpz_srcptr, unsigned long int)); +void mpz_clear _PROTO ((mpz_ptr)); +void mpz_clrbit _PROTO ((mpz_ptr, unsigned long int)); +int mpz_cmp _PROTO ((mpz_srcptr, mpz_srcptr)); +int mpz_cmp_si _PROTO ((mpz_srcptr, signed long int)); +int mpz_cmp_ui _PROTO ((mpz_srcptr, unsigned long int)); +void mpz_com _PROTO ((mpz_ptr, mpz_srcptr)); +void mpz_divexact _PROTO ((mpz_ptr, mpz_srcptr, mpz_srcptr)); +void mpz_fac_ui _PROTO ((mpz_ptr, unsigned long int)); +void mpz_fdiv_q _PROTO ((mpz_ptr, mpz_srcptr, mpz_srcptr)); +void mpz_fdiv_q_2exp _PROTO ((mpz_ptr, mpz_srcptr, unsigned long int)); +unsigned long int mpz_fdiv_q_ui _PROTO ((mpz_ptr, mpz_srcptr, unsigned long int)); +void mpz_fdiv_qr _PROTO ((mpz_ptr, mpz_ptr, mpz_srcptr, mpz_srcptr)); +unsigned long int mpz_fdiv_qr_ui _PROTO ((mpz_ptr, mpz_ptr, mpz_srcptr, unsigned long int)); +void mpz_fdiv_r _PROTO ((mpz_ptr, mpz_srcptr, mpz_srcptr)); +void mpz_fdiv_r_2exp _PROTO ((mpz_ptr, mpz_srcptr, unsigned long int)); +unsigned long int mpz_fdiv_r_ui _PROTO ((mpz_ptr, mpz_srcptr, unsigned long int)); +unsigned long int mpz_fdiv_ui _PROTO ((mpz_srcptr, unsigned long int)); +void mpz_gcd _PROTO ((mpz_ptr, mpz_srcptr, mpz_srcptr)); +unsigned long int mpz_gcd_ui _PROTO ((mpz_ptr, mpz_srcptr, unsigned long int)); +void mpz_gcdext _PROTO ((mpz_ptr, mpz_ptr, mpz_ptr, mpz_srcptr, mpz_srcptr)); +double mpz_get_d _PROTO ((mpz_srcptr)); +/* signed */ long int mpz_get_si _PROTO ((mpz_srcptr)); +char *mpz_get_str _PROTO ((char *, int, mpz_srcptr)); +unsigned long int mpz_get_ui _PROTO ((mpz_srcptr)); +mp_limb_t mpz_getlimbn _PROTO ((mpz_srcptr, mp_size_t)); +unsigned long int mpz_hamdist _PROTO ((mpz_srcptr, mpz_srcptr)); +void mpz_init _PROTO ((mpz_ptr)); +#ifdef _GMP_H_HAVE_FILE +size_t mpz_inp_binary _PROTO ((mpz_ptr, FILE *)); +size_t mpz_inp_raw _PROTO ((mpz_ptr, FILE *)); +size_t mpz_inp_str _PROTO ((mpz_ptr, FILE *, int)); +#endif +void mpz_init_set _PROTO ((mpz_ptr, mpz_srcptr)); +void mpz_init_set_d _PROTO ((mpz_ptr, double)); +void mpz_init_set_si _PROTO ((mpz_ptr, signed long int)); +int mpz_init_set_str _PROTO ((mpz_ptr, const char *, int)); +void mpz_init_set_ui _PROTO ((mpz_ptr, unsigned long int)); +int mpz_invert _PROTO ((mpz_ptr, mpz_srcptr, mpz_srcptr)); +void mpz_ior _PROTO ((mpz_ptr, mpz_srcptr, mpz_srcptr)); +int mpz_jacobi _PROTO ((mpz_srcptr, mpz_srcptr)); +int mpz_legendre _PROTO ((mpz_srcptr, mpz_srcptr)); +void mpz_mod _PROTO ((mpz_ptr, mpz_srcptr, mpz_srcptr)); +void mpz_mul _PROTO ((mpz_ptr, mpz_srcptr, mpz_srcptr)); +void mpz_mul_2exp _PROTO ((mpz_ptr, mpz_srcptr, unsigned long int)); +void mpz_mul_ui _PROTO ((mpz_ptr, mpz_srcptr, unsigned long int)); +void mpz_neg _PROTO ((mpz_ptr, mpz_srcptr)); +#ifdef _GMP_H_HAVE_FILE +size_t mpz_out_binary _PROTO ((FILE *, mpz_srcptr)); +size_t mpz_out_raw _PROTO ((FILE *, mpz_srcptr)); +size_t mpz_out_str _PROTO ((FILE *, int, mpz_srcptr)); +#endif +int mpz_perfect_square_p _PROTO ((mpz_srcptr)); +unsigned long int mpz_popcount _PROTO ((mpz_srcptr)); +void mpz_pow_ui _PROTO ((mpz_ptr, mpz_srcptr, unsigned long int)); +void mpz_powm _PROTO ((mpz_ptr, mpz_srcptr, mpz_srcptr, mpz_srcptr)); +void mpz_powm_ui _PROTO ((mpz_ptr, mpz_srcptr, unsigned long int, mpz_srcptr)); +int mpz_probab_prime_p _PROTO ((mpz_srcptr, int)); +void mpz_random _PROTO ((mpz_ptr, mp_size_t)); +void mpz_random2 _PROTO ((mpz_ptr, mp_size_t)); +unsigned long int mpz_scan0 _PROTO ((mpz_srcptr, unsigned long int)); +unsigned long int mpz_scan1 _PROTO ((mpz_srcptr, unsigned long int)); +void mpz_set _PROTO ((mpz_ptr, mpz_srcptr)); +void mpz_set_d _PROTO ((mpz_ptr, double)); +void mpz_set_f _PROTO ((mpz_ptr, mpf_srcptr)); +void mpz_set_q _PROTO ((mpz_ptr, mpq_srcptr)); +void mpz_set_si _PROTO ((mpz_ptr, signed long int)); +int mpz_set_str _PROTO ((mpz_ptr, const char *, int)); +void mpz_set_ui _PROTO ((mpz_ptr, unsigned long int)); +void mpz_setbit _PROTO ((mpz_ptr, unsigned long int)); +size_t mpz_size _PROTO ((mpz_srcptr)); +size_t mpz_sizeinbase _PROTO ((mpz_srcptr, int)); +void mpz_sqrt _PROTO ((mpz_ptr, mpz_srcptr)); +void mpz_sqrtrem _PROTO ((mpz_ptr, mpz_ptr, mpz_srcptr)); +void mpz_sub _PROTO ((mpz_ptr, mpz_srcptr, mpz_srcptr)); +void mpz_sub_ui _PROTO ((mpz_ptr, mpz_srcptr, unsigned long int)); +void mpz_tdiv_q _PROTO ((mpz_ptr, mpz_srcptr, mpz_srcptr)); +void mpz_tdiv_q_2exp _PROTO ((mpz_ptr, mpz_srcptr, unsigned long int)); +void mpz_tdiv_q_ui _PROTO ((mpz_ptr, mpz_srcptr, unsigned long int)); +void mpz_tdiv_qr _PROTO ((mpz_ptr, mpz_ptr, mpz_srcptr, mpz_srcptr)); +void mpz_tdiv_qr_ui _PROTO ((mpz_ptr, mpz_ptr, mpz_srcptr, unsigned long int)); +void mpz_tdiv_r _PROTO ((mpz_ptr, mpz_srcptr, mpz_srcptr)); +void mpz_tdiv_r_2exp _PROTO ((mpz_ptr, mpz_srcptr, unsigned long int)); +void mpz_tdiv_r_ui _PROTO ((mpz_ptr, mpz_srcptr, unsigned long int)); +void mpz_ui_pow_ui _PROTO ((mpz_ptr, unsigned long int, unsigned long int)); + +/**************** Rational (i.e. Q) routines. ****************/ + +void mpq_init _PROTO ((mpq_ptr)); +void mpq_clear _PROTO ((mpq_ptr)); +void mpq_set _PROTO ((mpq_ptr, mpq_srcptr)); +void mpq_set_ui _PROTO ((mpq_ptr, unsigned long int, unsigned long int)); +void mpq_set_si _PROTO ((mpq_ptr, signed long int, unsigned long int)); +void mpq_set_z _PROTO ((mpq_ptr, mpz_srcptr)); +void mpq_add _PROTO ((mpq_ptr, mpq_srcptr, mpq_srcptr)); +void mpq_sub _PROTO ((mpq_ptr, mpq_srcptr, mpq_srcptr)); +void mpq_mul _PROTO ((mpq_ptr, mpq_srcptr, mpq_srcptr)); +void mpq_div _PROTO ((mpq_ptr, mpq_srcptr, mpq_srcptr)); +void mpq_neg _PROTO ((mpq_ptr, mpq_srcptr)); +int mpq_cmp _PROTO ((mpq_srcptr, mpq_srcptr)); +int mpq_cmp_ui _PROTO ((mpq_srcptr, unsigned long int, unsigned long int)); +int mpq_equal _PROTO ((mpq_srcptr, mpq_srcptr)); +void mpq_inv _PROTO ((mpq_ptr, mpq_srcptr)); +void mpq_set_num _PROTO ((mpq_ptr, mpz_srcptr)); +void mpq_set_den _PROTO ((mpq_ptr, mpz_srcptr)); +void mpq_get_num _PROTO ((mpz_ptr, mpq_srcptr)); +void mpq_get_den _PROTO ((mpz_ptr, mpq_srcptr)); +double mpq_get_d _PROTO ((mpq_srcptr)); +void mpq_canonicalize _PROTO ((mpq_ptr)); + +/**************** Float (i.e. F) routines. ****************/ + +void mpf_abs _PROTO ((mpf_ptr, mpf_srcptr)); +void mpf_add _PROTO ((mpf_ptr, mpf_srcptr, mpf_srcptr)); +void mpf_add_ui _PROTO ((mpf_ptr, mpf_srcptr, unsigned long int)); +void mpf_clear _PROTO ((mpf_ptr)); +int mpf_cmp _PROTO ((mpf_srcptr, mpf_srcptr)); +int mpf_cmp_si _PROTO ((mpf_srcptr, signed long int)); +int mpf_cmp_ui _PROTO ((mpf_srcptr, unsigned long int)); +void mpf_div _PROTO ((mpf_ptr, mpf_srcptr, mpf_srcptr)); +void mpf_div_2exp _PROTO ((mpf_ptr, mpf_srcptr, unsigned long int)); +void mpf_div_ui _PROTO ((mpf_ptr, mpf_srcptr, unsigned long int)); +void mpf_dump _PROTO ((mpf_srcptr)); +int mpf_eq _PROTO ((mpf_srcptr, mpf_srcptr, unsigned long int)); +double mpf_get_d _PROTO ((mpf_srcptr)); +unsigned long int mpf_get_prec _PROTO ((mpf_srcptr)); +char *mpf_get_str _PROTO ((char *, mp_exp_t *, int, size_t, mpf_srcptr)); +void mpf_init _PROTO ((mpf_ptr)); +void mpf_init2 _PROTO ((mpf_ptr, unsigned long int)); +#ifdef _GMP_H_HAVE_FILE +size_t mpf_inp_str _PROTO ((mpf_ptr, FILE *, int)); +#endif +void mpf_init_set _PROTO ((mpf_ptr, mpf_srcptr)); +void mpf_init_set_d _PROTO ((mpf_ptr, double)); +void mpf_init_set_si _PROTO ((mpf_ptr, signed long int)); +int mpf_init_set_str _PROTO ((mpf_ptr, const char *, int)); +void mpf_init_set_ui _PROTO ((mpf_ptr, unsigned long int)); +void mpf_mul _PROTO ((mpf_ptr, mpf_srcptr, mpf_srcptr)); +void mpf_mul_2exp _PROTO ((mpf_ptr, mpf_srcptr, unsigned long int)); +void mpf_mul_ui _PROTO ((mpf_ptr, mpf_srcptr, unsigned long int)); +void mpf_neg _PROTO ((mpf_ptr, mpf_srcptr)); +#ifdef _GMP_H_HAVE_FILE +size_t mpf_out_str _PROTO ((FILE *, int, size_t, mpf_srcptr)); +#endif +void mpf_random2 _PROTO ((mpf_ptr, mp_size_t, mp_exp_t)); +void mpf_reldiff _PROTO ((mpf_ptr, mpf_srcptr, mpf_srcptr)); +void mpf_set _PROTO ((mpf_ptr, mpf_srcptr)); +void mpf_set_d _PROTO ((mpf_ptr, double)); +void mpf_set_default_prec _PROTO ((unsigned long int)); +void mpf_set_prec _PROTO ((mpf_ptr, unsigned long int)); +void mpf_set_prec_raw _PROTO ((mpf_ptr, unsigned long int)); +void mpf_set_q _PROTO ((mpf_ptr, mpq_srcptr)); +void mpf_set_si _PROTO ((mpf_ptr, signed long int)); +int mpf_set_str _PROTO ((mpf_ptr, const char *, int)); +void mpf_set_ui _PROTO ((mpf_ptr, unsigned long int)); +void mpf_set_z _PROTO ((mpf_ptr, mpz_srcptr)); +size_t mpf_size _PROTO ((mpf_srcptr)); +void mpf_sqrt _PROTO ((mpf_ptr, mpf_srcptr)); +void mpf_sqrt_ui _PROTO ((mpf_ptr, unsigned long int)); +void mpf_sub _PROTO ((mpf_ptr, mpf_srcptr, mpf_srcptr)); +void mpf_sub_ui _PROTO ((mpf_ptr, mpf_srcptr, unsigned long int)); +void mpf_ui_div _PROTO ((mpf_ptr, unsigned long int, mpf_srcptr)); +void mpf_ui_sub _PROTO ((mpf_ptr, unsigned long int, mpf_srcptr)); +#if defined (__cplusplus) +} +#endif +/************ Low level positive-integer (i.e. N) routines. ************/ + +/* This is ugly, but we need to make usr calls reach the prefixed function. */ +#define mpn_add __MPN(add) +#define mpn_add_1 __MPN(add_1) +#define mpn_add_n __MPN(add_n) +#define mpn_addmul_1 __MPN(addmul_1) +#define mpn_bdivmod __MPN(bdivmod) +#define mpn_cmp __MPN(cmp) +#define mpn_divmod_1 __MPN(divmod_1) +#define mpn_divrem __MPN(divrem) +#define mpn_divrem_1 __MPN(divrem_1) +#define mpn_dump __MPN(dump) +#define mpn_gcd __MPN(gcd) +#define mpn_gcd_1 __MPN(gcd_1) +#define mpn_gcdext __MPN(gcdext) +#define mpn_get_str __MPN(get_str) +#define mpn_hamdist __MPN(hamdist) +#define mpn_lshift __MPN(lshift) +#define mpn_mod_1 __MPN(mod_1) +#define mpn_mul __MPN(mul) +#define mpn_mul_1 __MPN(mul_1) +#define mpn_mul_n __MPN(mul_n) +#define mpn_perfect_square_p __MPN(perfect_square_p) +#define mpn_popcount __MPN(popcount) +#define mpn_preinv_mod_1 __MPN(preinv_mod_1) +#define mpn_random2 __MPN(random2) +#define mpn_rshift __MPN(rshift) +#define mpn_scan0 __MPN(scan0) +#define mpn_scan1 __MPN(scan1) +#define mpn_set_str __MPN(set_str) +#define mpn_sqrtrem __MPN(sqrtrem) +#define mpn_sub __MPN(sub) +#define mpn_sub_1 __MPN(sub_1) +#define mpn_sub_n __MPN(sub_n) +#define mpn_submul_1 __MPN(submul_1) +#define mpn_udiv_w_sdiv __MPN(udiv_w_sdiv) + +#if defined (__cplusplus) +extern "C" { +#endif +mp_limb_t mpn_add _PROTO ((mp_ptr, mp_srcptr, mp_size_t, mp_srcptr,mp_size_t)); +mp_limb_t mpn_add_1 _PROTO ((mp_ptr, mp_srcptr, mp_size_t, mp_limb_t)); +mp_limb_t mpn_add_n _PROTO ((mp_ptr, mp_srcptr, mp_srcptr, mp_size_t)); +mp_limb_t mpn_addmul_1 _PROTO ((mp_ptr, mp_srcptr, mp_size_t, mp_limb_t)); +mp_limb_t mpn_bdivmod _PROTO ((mp_ptr, mp_ptr, mp_size_t, mp_srcptr, mp_size_t, unsigned long int)); +int mpn_cmp _PROTO ((mp_srcptr, mp_srcptr, mp_size_t)); +mp_limb_t mpn_divmod_1 _PROTO ((mp_ptr, mp_srcptr, mp_size_t, mp_limb_t)); +mp_limb_t mpn_divrem _PROTO ((mp_ptr, mp_size_t, mp_ptr, mp_size_t, mp_srcptr, mp_size_t)); +mp_limb_t mpn_divrem_1 _PROTO ((mp_ptr, mp_size_t, mp_srcptr, mp_size_t, mp_limb_t)); +void mpn_dump _PROTO ((mp_srcptr, mp_size_t)); +mp_size_t mpn_gcd _PROTO ((mp_ptr, mp_ptr, mp_size_t, mp_ptr, mp_size_t)); +mp_limb_t mpn_gcd_1 _PROTO ((mp_srcptr, mp_size_t, mp_limb_t)); +mp_size_t mpn_gcdext _PROTO ((mp_ptr, mp_ptr, mp_ptr, mp_size_t, mp_ptr, mp_size_t)); +size_t mpn_get_str _PROTO ((unsigned char *, int, mp_ptr, mp_size_t)); +unsigned long int mpn_hamdist _PROTO ((mp_srcptr, mp_srcptr, mp_size_t)); +mp_limb_t mpn_lshift _PROTO ((mp_ptr, mp_srcptr, mp_size_t, unsigned int)); +mp_limb_t mpn_mod_1 _PROTO ((mp_srcptr, mp_size_t, mp_limb_t)); +mp_limb_t mpn_mul _PROTO ((mp_ptr, mp_srcptr, mp_size_t, mp_srcptr, mp_size_t)); +mp_limb_t mpn_mul_1 _PROTO ((mp_ptr, mp_srcptr, mp_size_t, mp_limb_t)); +void mpn_mul_n _PROTO ((mp_ptr, mp_srcptr, mp_srcptr, mp_size_t)); +int mpn_perfect_square_p _PROTO ((mp_srcptr, mp_size_t)); +unsigned long int mpn_popcount _PROTO ((mp_srcptr, mp_size_t)); +mp_limb_t mpn_preinv_mod_1 _PROTO ((mp_srcptr, mp_size_t, mp_limb_t, mp_limb_t)); +void mpn_random2 _PROTO ((mp_ptr, mp_size_t)); +mp_limb_t mpn_rshift _PROTO ((mp_ptr, mp_srcptr, mp_size_t, unsigned int)); +unsigned long int mpn_scan0 _PROTO ((mp_srcptr, unsigned long int)); +unsigned long int mpn_scan1 _PROTO ((mp_srcptr, unsigned long int)); +mp_size_t mpn_set_str _PROTO ((mp_ptr, const unsigned char *, size_t, int)); +mp_size_t mpn_sqrtrem _PROTO ((mp_ptr, mp_ptr, mp_srcptr, mp_size_t)); +mp_limb_t mpn_sub _PROTO ((mp_ptr, mp_srcptr, mp_size_t, mp_srcptr,mp_size_t)); +mp_limb_t mpn_sub_1 _PROTO ((mp_ptr, mp_srcptr, mp_size_t, mp_limb_t)); +mp_limb_t mpn_sub_n _PROTO ((mp_ptr, mp_srcptr, mp_srcptr, mp_size_t)); +mp_limb_t mpn_submul_1 _PROTO ((mp_ptr, mp_srcptr, mp_size_t, mp_limb_t)); +#if defined (__cplusplus) +} +#endif + +#if defined (__GNUC__) || defined (_FORCE_INLINES) +_EXTERN_INLINE mp_limb_t +#if defined (__STDC__) || defined (__cplusplus) +mpn_add_1 (register mp_ptr res_ptr, + register mp_srcptr s1_ptr, + register mp_size_t s1_size, + register mp_limb_t s2_limb) +#else +mpn_add_1 (res_ptr, s1_ptr, s1_size, s2_limb) + register mp_ptr res_ptr; + register mp_srcptr s1_ptr; + register mp_size_t s1_size; + register mp_limb_t s2_limb; +#endif +{ + register mp_limb_t x; + + x = *s1_ptr++; + s2_limb = x + s2_limb; + *res_ptr++ = s2_limb; + if (s2_limb < x) + { + while (--s1_size != 0) + { + x = *s1_ptr++ + 1; + *res_ptr++ = x; + if (x != 0) + goto fin; + } + + return 1; + } + + fin: + if (res_ptr != s1_ptr) + { + mp_size_t i; + for (i = 0; i < s1_size - 1; i++) + res_ptr[i] = s1_ptr[i]; + } + return 0; +} + +_EXTERN_INLINE mp_limb_t +#if defined (__STDC__) || defined (__cplusplus) +mpn_add (register mp_ptr res_ptr, + register mp_srcptr s1_ptr, + register mp_size_t s1_size, + register mp_srcptr s2_ptr, + register mp_size_t s2_size) +#else +mpn_add (res_ptr, s1_ptr, s1_size, s2_ptr, s2_size) + register mp_ptr res_ptr; + register mp_srcptr s1_ptr; + register mp_size_t s1_size; + register mp_srcptr s2_ptr; + register mp_size_t s2_size; +#endif +{ + mp_limb_t cy_limb = 0; + + if (s2_size != 0) + cy_limb = mpn_add_n (res_ptr, s1_ptr, s2_ptr, s2_size); + + if (s1_size - s2_size != 0) + cy_limb = mpn_add_1 (res_ptr + s2_size, + s1_ptr + s2_size, + s1_size - s2_size, + cy_limb); + return cy_limb; +} + +_EXTERN_INLINE mp_limb_t +#if defined (__STDC__) || defined (__cplusplus) +mpn_sub_1 (register mp_ptr res_ptr, + register mp_srcptr s1_ptr, + register mp_size_t s1_size, + register mp_limb_t s2_limb) +#else +mpn_sub_1 (res_ptr, s1_ptr, s1_size, s2_limb) + register mp_ptr res_ptr; + register mp_srcptr s1_ptr; + register mp_size_t s1_size; + register mp_limb_t s2_limb; +#endif +{ + register mp_limb_t x; + + x = *s1_ptr++; + s2_limb = x - s2_limb; + *res_ptr++ = s2_limb; + if (s2_limb > x) + { + while (--s1_size != 0) + { + x = *s1_ptr++; + *res_ptr++ = x - 1; + if (x != 0) + goto fin; + } + + return 1; + } + + fin: + if (res_ptr != s1_ptr) + { + mp_size_t i; + for (i = 0; i < s1_size - 1; i++) + res_ptr[i] = s1_ptr[i]; + } + return 0; +} + +_EXTERN_INLINE mp_limb_t +#if defined (__STDC__) || defined (__cplusplus) +mpn_sub (register mp_ptr res_ptr, + register mp_srcptr s1_ptr, + register mp_size_t s1_size, + register mp_srcptr s2_ptr, + register mp_size_t s2_size) +#else +mpn_sub (res_ptr, s1_ptr, s1_size, s2_ptr, s2_size) + register mp_ptr res_ptr; + register mp_srcptr s1_ptr; + register mp_size_t s1_size; + register mp_srcptr s2_ptr; + register mp_size_t s2_size; +#endif +{ + mp_limb_t cy_limb = 0; + + if (s2_size != 0) + cy_limb = mpn_sub_n (res_ptr, s1_ptr, s2_ptr, s2_size); + + if (s1_size - s2_size != 0) + cy_limb = mpn_sub_1 (res_ptr + s2_size, + s1_ptr + s2_size, + s1_size - s2_size, + cy_limb); + return cy_limb; +} +#endif /* __GNUC__ */ + +/* Allow faster testing for negative, zero, and positive. */ +#define mpz_sgn(Z) ((Z)->_mp_size < 0 ? -1 : (Z)->_mp_size > 0) +#define mpf_sgn(F) ((F)->_mp_size < 0 ? -1 : (F)->_mp_size > 0) +#define mpq_sgn(Q) ((Q)->_mp_num._mp_size < 0 ? -1 : (Q)->_mp_num._mp_size > 0) + +/* Allow direct user access to numerator and denominator of a mpq_t object. */ +#define mpq_numref(Q) (&((Q)->_mp_num)) +#define mpq_denref(Q) (&((Q)->_mp_den)) + +/* When using GCC, optimize certain common comparisons. */ +#if defined (__GNUC__) +#define mpz_cmp_ui(Z,UI) \ + (__builtin_constant_p (UI) && (UI) == 0 \ + ? mpz_sgn (Z) : mpz_cmp_ui (Z,UI)) +#define mpz_cmp_si(Z,UI) \ + (__builtin_constant_p (UI) && (UI) == 0 ? mpz_sgn (Z) \ + : __builtin_constant_p (UI) && (UI) > 0 ? mpz_cmp_ui (Z,UI) \ + : mpz_cmp_si (Z,UI)) +#define mpq_cmp_ui(Q,NUI,DUI) \ + (__builtin_constant_p (NUI) && (NUI) == 0 \ + ? mpq_sgn (Q) : mpq_cmp_ui (Q,NUI,DUI)) +#endif + +#define mpn_divmod(qp,np,nsize,dp,dsize) mpn_divrem (qp,0,np,nsize,dp,dsize) +#if 0 +#define mpn_divmod_1(qp,np,nsize,dlimb) mpn_divrem_1 (qp,0,np,nsize,dlimb) +#endif + +/* Compatibility with GMP 1. */ +#define mpz_mdiv mpz_fdiv_q +#define mpz_mdivmod mpz_fdiv_qr +#define mpz_mmod mpz_fdiv_r +#define mpz_mdiv_ui mpz_fdiv_q_ui +#define mpz_mdivmod_ui(q,r,n,d) \ + ((r == 0) ? mpz_fdiv_q_ui (q,n,d) : mpz_fdiv_qr_ui (q,r,n,d)) +#define mpz_mmod_ui(r,n,d) \ + ((r == 0) ? mpz_fdiv_ui (n,d) : mpz_fdiv_r_ui (r,n,d)) + +/* Useful synonyms, but not quite compatible with GMP 1. */ +#define mpz_div mpz_fdiv_q +#define mpz_divmod mpz_fdiv_qr +#define mpz_div_ui mpz_fdiv_q_ui +#define mpz_divmod_ui mpz_fdiv_qr_ui +#define mpz_mod_ui mpz_fdiv_r_ui +#define mpz_div_2exp mpz_fdiv_q_2exp +#define mpz_mod_2exp mpz_fdiv_r_2exp + +#define __GNU_MP_VERSION 2 +#define __GNU_MP_VERSION_MINOR 0 +#define __GMP_H__ +#endif /* __GMP_H__ */ diff --git a/contrib/libgmp/gmp.info-1 b/contrib/libgmp/gmp.info-1 new file mode 100644 index 0000000..4ea9373 --- /dev/null +++ b/contrib/libgmp/gmp.info-1 @@ -0,0 +1,1283 @@ +This is Info file gmp.info, produced by Makeinfo-1.64 from the input +file gmp.texi. + +START-INFO-DIR-ENTRY +* gmp: (gmp.info). GNU Multiple Precision Arithmetic Library. +END-INFO-DIR-ENTRY + + This file documents GNU MP, a library for arbitrary-precision +arithmetic. + + Copyright (C) 1991, 1993, 1994, 1995, 1996 Free Software Foundation, +Inc. + + Permission is granted to make and distribute verbatim copies of this +manual provided the copyright notice and this permission notice are +preserved on all copies. + + Permission is granted to copy and distribute modified versions of +this manual under the conditions for verbatim copying, provided that +the entire resulting derived work is distributed under the terms of a +permission notice identical to this one. + + Permission is granted to copy and distribute translations of this +manual into another language, under the above conditions for modified +versions, except that this permission notice may be stated in a +translation approved by the Foundation. + + +File: gmp.info, Node: Top, Next: Copying, Prev: (dir), Up: (dir) + +GNU MP +****** + + This manual documents how to install and use the GNU multiple +precision arithmetic library, version 2.0.2. + +* Menu: + +* Copying:: GMP Copying Conditions (LGPL). +* Introduction to MP:: Brief introduction to GNU MP. +* Installing MP:: How to configure and compile the MP library. +* MP Basics:: What every MP user should now. +* Reporting Bugs:: How to usefully report bugs. +* Integer Functions:: Functions for arithmetic on signed integers. +* Rational Number Functions:: Functions for arithmetic on rational numbers. +* Floating-point Functions:: Functions for arithmetic on floats. +* Low-level Functions:: Fast functions for natural numbers. +* BSD Compatible Functions:: All functions found in BSD MP. +* Custom Allocation:: How to customize the internal allocation. + +* Contributors:: +* References:: +* Concept Index:: +* Function Index:: + + +File: gmp.info, Node: Copying, Next: Introduction to MP, Prev: Top, Up: Top + +GNU MP Copying Conditions +************************* + + This library is "free"; this means that everyone is free to use it +and free to redistribute it on a free basis. The library is not in the +public domain; it is copyrighted and there are restrictions on its +distribution, but these restrictions are designed to permit everything +that a good cooperating citizen would want to do. What is not allowed +is to try to prevent others from further sharing any version of this +library that they might get from you. + + Specifically, we want to make sure that you have the right to give +away copies of the library, that you receive source code or else can +get it if you want it, that you can change this library or use pieces +of it in new free programs, and that you know you can do these things. + + To make sure that everyone has such rights, we have to forbid you to +deprive anyone else of these rights. For example, if you distribute +copies of the GNU MP library, you must give the recipients all the +rights that you have. You must make sure that they, too, receive or +can get the source code. And you must tell them their rights. + + Also, for our own protection, we must make certain that everyone +finds out that there is no warranty for the GNU MP library. If it is +modified by someone else and passed on, we want their recipients to +know that what they have is not what we distributed, so that any +problems introduced by others will not reflect on our reputation. + + The precise conditions of the license for the GNU MP library are +found in the Library General Public License that accompany the source +code. + + +File: gmp.info, Node: Introduction to MP, Next: Installing MP, Prev: Copying, Up: Top + +Introduction to GNU MP +********************** + + GNU MP is a portable library written in C for arbitrary precision +arithmetic on integers, rational numbers, and floating-point numbers. +It aims to provide the fastest possible arithmetic for all applications +that need higher precision than is directly supported by the basic C +types. + + Many applications use just a few hundred bits of precision; but some +applications may need thousands or even millions of bits. MP is +designed to give good performance for both, by choosing algorithms +based on the sizes of the operands, and by carefully keeping the +overhead at a minimum. + + The speed of MP is achieved by using fullwords as the basic +arithmetic type, by using sophisticated algorithms, by including +carefully optimized assembly code for the most common inner loops for +many different CPUs, and by a general emphasis on speed (as opposed to +simplicity or elegance). + + There is carefully optimized assembly code for these CPUs: DEC +Alpha, Amd 29000, HPPA 1.0 and 1.1, Intel Pentium and generic x86, +Intel i960, Motorola MC68000, MC68020, MC88100, and MC88110, +Motorola/IBM PowerPC, National NS32000, IBM POWER, MIPS R3000, R4000, +SPARCv7, SuperSPARC, generic SPARCv8, and DEC VAX. Some optimizations +also for ARM, Clipper, IBM ROMP (RT), and Pyramid AP/XP. + + This version of MP is released under a more liberal license than +previous versions. It is now permitted to link MP to non-free +programs, as long as MP source code is provided when distributing the +non-free program. + +How to use this Manual +====================== + + Everyone should read *Note MP Basics::. If you need to install the +library yourself, you need to read *Note Installing MP::, too. + + The rest of the manual can be used for later reference, although it +is probably a good idea to glance through it. + + +File: gmp.info, Node: Installing MP, Next: MP Basics, Prev: Introduction to MP, Up: Top + +Installing MP +************* + + To build MP, you first have to configure it for your CPU and +operating system. You need a C compiler, preferably GCC, but any +reasonable compiler should work. And you need a standard Unix `make' +program, plus some other standard Unix utility programs. + + (If you're on an MS-DOS machine, your can build MP using `make.bat'. +It requires that djgpp is installed. It does not require +configuration, nor is `make' needed; `make.bat' both configures and +builds the library.) + + Here are the steps needed to install the library on Unix systems: + + 1. In most cases, `./configure --target=cpu-vendor-os', should work + both for native and cross-compilation. If you get error messages, + your machine might not be supported. + + If you want to compile in a separate object directory, cd to that + directory, and prefix the configure command with the path to the + MP source directory. Not all `make' programs have the necessary + features to support this. In particular, SunOS and Slowaris + `make' have bugs that makes them unable to build from a separate + object directory. Use GNU `make' instead. + + In addition to the standard cpu-vendor-os tuples, MP recognizes + sparc8 and supersparc as valid CPU names. Specifying these CPU + names for relevant systems will improve performance significantly. + + In general, if you want a library that runs as fast as possible, + you should make sure you configure MP for the exact CPU type your + system uses. + + If you have `gcc' in your `PATH', it will be used by default. To + override this, pass `-with-gcc=no' to `configure'. + + 2. `make' + + This will compile MP, and create a library archive file `libgmp.a' + in the working directory. + + 3. `make check' + + This will make sure MP was built correctly. If you get error + messages, please report this to `bug-gmp@prep.ai.mit.edu'. (*Note + Reporting Bugs::, for information on what to include in useful bug + reports.) + + 4. `make install' + + This will copy the file `gmp.h' and `libgmp.a', as well as the info + files, to `/usr/local' (or if you passed the `--prefix' option to + `configure', to the directory given as argument to `--prefix'). + +If you wish to build and install the BSD MP compatible functions, use +`make libmp.a' and `make install-bsdmp'. + + There are some other useful make targets: + + * `doc' + + Create a DVI version of the manual, in `gmp.dvi' and a set of info + files, in `gmp.info', `gmp.info-1', `gmp.info-2', etc. + + * `ps' + + Create a Postscript version of the manual, in `gmp.ps'. + + * `html' + + Create a HTML version of the manual, in `gmp.html'. + + * `clean' + + Delete all object files and archive files, but not the + configuration files. + + * `distclean' + + Delete all files not included in the distribution. + + * `uninstall' + + Delete all files copied by `make install'. + +Known Build Problems +==================== + + GCC 2.7.2 (as well as 2.6.3) for the RS/6000 and PowerPC can not be +used to compile MP, due to a bug in GCC. If you want to use GCC for +these machines, you need to apply the patch below to GCC, or use a +later version of the compiler. + + If you are on a Sequent Symmetry, use the GNU assembler instead of +the system's assembler, since the latter has serious bugs. + + The system compiler on NeXT is a massacred and old gcc, even if the +compiler calls itself `cc'. This compiler cannot be used to build MP. +You need to get a real gcc, and install that before you compile MP. +(NeXT might have fixed this in newer releases of their system.) + + The system C compiler under SunOS 4 has a bug that makes it +miscompile mpq/get_d.c. This will make `make check' fail. + + Please report other problems to `bug-gmp@prep.ai.mit.edu'. *Note +Reporting Bugs::. + + Patch to apply to GCC 2.6.3 and 2.7.2: + + *** config/rs6000/rs6000.md Sun Feb 11 08:22:11 1996 + --- config/rs6000/rs6000.md.new Sun Feb 18 03:33:37 1996 + *************** + *** 920,926 **** + (set (match_operand:SI 0 "gpc_reg_operand" "=r") + (not:SI (match_dup 1)))] + "" + ! "nor. %0,%2,%1" + [(set_attr "type" "compare")]) + + (define_insn "" + --- 920,926 ---- + (set (match_operand:SI 0 "gpc_reg_operand" "=r") + (not:SI (match_dup 1)))] + "" + ! "nor. %0,%1,%1" + [(set_attr "type" "compare")]) + + (define_insn "" + + +File: gmp.info, Node: MP Basics, Next: Reporting Bugs, Prev: Installing MP, Up: Top + +MP Basics +********* + + All declarations needed to use MP are collected in the include file +`gmp.h'. It is designed to work with both C and C++ compilers. + +Nomenclature and Types +====================== + +In this manual, "integer" usually means a multiple precision integer, as +defined by the MP library. The C data type for such integers is +`mpz_t'. Here are some examples of how to declare such integers: + + mpz_t sum; + + struct foo { mpz_t x, y; }; + + mpz_t vec[20]; + +"Rational number" means a multiple precision fraction. The C data type +for these fractions is `mpq_t'. For example: + + mpq_t quotient; + +"Floating point number" or "Float" for short, is an arbitrary precision +mantissa with an limited precision exponent. The C data type for such +objects is `mpf_t'. + +A "limb" means the part of a multi-precision number that fits in a +single word. (We chose this word because a limb of the human body is +analogous to a digit, only larger, and containing several digits.) +Normally a limb contains 32 or 64 bits. The C data type for a limb is +`mp_limb_t'. + +Function Classes +================ + + There are six classes of functions in the MP library: + + 1. Functions for signed integer arithmetic, with names beginning with + `mpz_'. The associated type is `mpz_t'. There are about 100 + functions in this class. + + 2. Functions for rational number arithmetic, with names beginning with + `mpq_'. The associated type is `mpq_t'. There are about 20 + functions in this class, but the functions in the previous class + can be used for performing arithmetic on the numerator and + denominator separately. + + 3. Functions for floating-point arithmetic, with names beginning with + `mpf_'. The associated type is `mpf_t'. There are about 50 + functions is this class. + + 4. Functions compatible with Berkeley MP, such as `itom', `madd', and + `mult'. The associated type is `MINT'. + + 5. Fast low-level functions that operate on natural numbers. These + are used by the functions in the preceding groups, and you can + also call them directly from very time-critical user programs. + These functions' names begin with `mpn_'. There are about 30 + (hard-to-use) functions in this class. + + The associated type is array of `mp_limb_t'. + + 6. Miscellaneous functions. Functions for setting up custom + allocation. + +MP Variable Conventions +======================= + + As a general rule, all MP functions expect output arguments before +input arguments. This notation is based on an analogy with the +assignment operator. (The BSD MP compatibility functions disobey this +rule, having the output argument(s) last.) + + MP allows you to use the same variable for both input and output in +the same expression. For example, the main function for integer +multiplication, `mpz_mul', can be used like this: `mpz_mul (x, x, x)'. +This computes the square of X and puts the result back in X. + + Before you can assign to an MP variable, you need to initialize it +by calling one of the special initialization functions. When you're +done with a variable, you need to clear it out, using one of the +functions for that purpose. Which function to use depends on the type +of variable. See the chapters on integer functions, rational number +functions, and floating-point functions for details. + + A variable should only be initialized once, or at least cleared out +between each initialization. After a variable has been initialized, it +may be assigned to any number of times. + + For efficiency reasons, avoid to initialize and clear out a variable +in loops. Instead, initialize it before entering the loop, and clear +it out after the loop has exited. + + You don't need to be concerned about allocating additional space for +MP variables. All functions in MP automatically allocate additional +space when a variable does not already have enough space. They do not, +however, reduce the space when a smaller number is stored in the +object. Most of the time, this policy is best, since it avoids +frequent re-allocation. + +Useful Macros and Constants +=========================== + + - Global Constant: const int mp_bits_per_limb + The number of bits per limb. + + - Macro: __GNU_MP_VERSION + - Macro: __GNU_MP_VERSION_MINOR + The major and minor MP version, respectively, as integers. + +Compatibility with Version 1.x +============================== + + This version of MP is upward compatible with previous versions of +MP, with a few exceptions. + + 1. Integer division functions round the result differently. The old + functions (`mpz_div', `mpz_divmod', `mpz_mdiv', `mpz_mdivmod', + etc) now all use floor rounding (i.e., they round the quotient to + -infinity). There are a lot of new functions for integer + division, giving the user better control over the rounding. + + 2. The function `mpz_mod' now compute the true *mod* function. + + 3. The functions `mpz_powm' and `mpz_powm_ui' now use *mod* for + reduction. + + 4. The assignment functions for rational numbers do no longer + canonicalize their results. In the case a non-canonical result + could arise from an assignment, the user need to insert an + explicit call to `mpq_canonicalize'. This change was made for + efficiency. + + 5. Output generated by `mpz_out_raw' in this release cannot be read + by `mpz_inp_raw' in previous releases. This change was made for + making the file format truly portable between machines with + different word sizes. + + 6. Several `mpn' functions have changed. But they were intentionally + undocumented in previous releases. + + 7. The functions `mpz_cmp_ui', `mpz_cmp_si', and `mpq_cmp_ui' are now + implementated as macros, and thereby sometimes evaluate their + arguments multiple times. + + 8. The functions `mpz_pow_ui' and `mpz_ui_pow_ui' now yield 1 for + 0^0. (In version 1, they yielded 0.) + + +Getting the Latest Version of MP +================================ + + The latest version of the MP library is available by anonymous ftp +from from `prep.ai.mit.edu'. The file name is +`/pub/gnu/gmp-M.N.tar.gz'. Many sites around the world mirror `prep'; +please use a mirror site near you. + + +File: gmp.info, Node: Reporting Bugs, Next: Integer Functions, Prev: MP Basics, Up: Top + +Reporting Bugs +************** + + If you think you have found a bug in the MP library, please +investigate it and report it. We have made this library available to +you, and it is not to ask too much from you, to ask you to report the +bugs that you find. + + There are a few things you should think about when you put your bug +report together. + + You have to send us a test case that makes it possible for us to +reproduce the bug. Include instructions on how to run the test case. + + You also have to explain what is wrong; if you get a crash, or if +the results printed are incorrect and in that case, in what way. + + It is not uncommon that an observed problem is actually due to a bug +in the compiler used when building MP; the MP code tends to explore +interesting corners in compilers. Therefore, please include compiler +version information in your bug report. This can be extracted using +`what `which cc`', or, if you're using gcc, `gcc -v'. Also, include +the output from `uname -a'. + + If your bug report is good, we will do our best to help you to get a +corrected version of the library; if the bug report is poor, we won't +do anything about it (aside of chiding you to send better bug reports). + + Send your bug report to: `bug-gmp@prep.ai.mit.edu'. + + If you think something in this manual is unclear, or downright +incorrect, or if the language needs to be improved, please send a note +to the same address. + + +File: gmp.info, Node: Integer Functions, Next: Rational Number Functions, Prev: Reporting Bugs, Up: Top + +Integer Functions +***************** + + This chapter describes the MP functions for performing integer +arithmetic. These functions start with the prefix `mpz_'. + + Arbitrary precision integers are stored in objects of type `mpz_t'. + +* Menu: + +* Initializing Integers:: +* Assigning Integers:: +* Simultaneous Integer Init & Assign:: +* Converting Integers:: +* Integer Arithmetic:: +* Comparison Functions:: +* Integer Logic and Bit Fiddling:: +* I/O of Integers:: +* Miscellaneous Integer Functions:: + + +File: gmp.info, Node: Initializing Integers, Next: Assigning Integers, Up: Integer Functions + +Initialization and Assignment Functions +======================================= + + The functions for integer arithmetic assume that all integer objects +are initialized. You do that by calling the function `mpz_init'. + + - Function: void mpz_init (mpz_t INTEGER) + Initialize INTEGER with limb space and set the initial numeric + value to 0. Each variable should normally only be initialized + once, or at least cleared out (using `mpz_clear') between each + initialization. + + Here is an example of using `mpz_init': + + { + mpz_t integ; + mpz_init (integ); + ... + mpz_add (integ, ...); + ... + mpz_sub (integ, ...); + + /* Unless the program is about to exit, do ... */ + mpz_clear (integ); + } + +As you can see, you can store new values any number of times, once an +object is initialized. + + - Function: void mpz_clear (mpz_t INTEGER) + Free the limb space occupied by INTEGER. Make sure to call this + function for all `mpz_t' variables when you are done with them. + + - Function: void * _mpz_realloc (mpz_t INTEGER, mp_size_t NEW_ALLOC) + Change the limb space allocation to NEW_ALLOC limbs. This + function is not normally called from user code, but it can be used + to give memory back to the heap, or to increase the space of a + variable to avoid repeated automatic re-allocation. + + - Function: void mpz_array_init (mpz_t INTEGER_ARRAY[], size_t + ARRAY_SIZE, mp_size_t FIXED_NUM_BITS) + Allocate *fixed* limb space for all ARRAY_SIZE integers in + INTEGER_ARRAY. The fixed allocation for each integer in the array + is enough to store FIXED_NUM_BITS. If the fixed space will be + insufficient for storing the result of a subsequent calculation, + the result is unpredictable. + + This function is useful for decreasing the working set for some + algorithms that use large integer arrays. + + There is no way to de-allocate the storage allocated by this + function. Don't call `mpz_clear'! + + +File: gmp.info, Node: Assigning Integers, Next: Simultaneous Integer Init & Assign, Prev: Initializing Integers, Up: Integer Functions + +Assignment Functions +-------------------- + + These functions assign new values to already initialized integers +(*note Initializing Integers::.). + + - Function: void mpz_set (mpz_t ROP, mpz_t OP) + - Function: void mpz_set_ui (mpz_t ROP, unsigned long int OP) + - Function: void mpz_set_si (mpz_t ROP, signed long int OP) + - Function: void mpz_set_d (mpz_t ROP, double OP) + - Function: void mpz_set_q (mpz_t ROP, mpq_t OP) + - Function: void mpz_set_f (mpz_t ROP, mpf_t OP) + Set the value of ROP from OP. + + - Function: int mpz_set_str (mpz_t ROP, char *STR, int BASE) + Set the value of ROP from STR, a '\0'-terminated C string in base + BASE. White space is allowed in the string, and is simply + ignored. The base may vary from 2 to 36. If BASE is 0, the + actual base is determined from the leading characters: if the + first two characters are `0x' or `0X', hexadecimal is assumed, + otherwise if the first character is `0', octal is assumed, + otherwise decimal is assumed. + + This function returns 0 if the entire string up to the '\0' is a + valid number in base BASE. Otherwise it returns -1. + + +File: gmp.info, Node: Simultaneous Integer Init & Assign, Next: Converting Integers, Prev: Assigning Integers, Up: Integer Functions + +Combined Initialization and Assignment Functions +------------------------------------------------ + + For convenience, MP provides a parallel series of initialize-and-set +functions which initialize the output and then store the value there. +These functions' names have the form `mpz_init_set...' + + Here is an example of using one: + + { + mpz_t pie; + mpz_init_set_str (pie, "3141592653589793238462643383279502884", 10); + ... + mpz_sub (pie, ...); + ... + mpz_clear (pie); + } + +Once the integer has been initialized by any of the `mpz_init_set...' +functions, it can be used as the source or destination operand for the +ordinary integer functions. Don't use an initialize-and-set function +on a variable already initialized! + + - Function: void mpz_init_set (mpz_t ROP, mpz_t OP) + - Function: void mpz_init_set_ui (mpz_t ROP, unsigned long int OP) + - Function: void mpz_init_set_si (mpz_t ROP, signed long int OP) + - Function: void mpz_init_set_d (mpz_t ROP, double OP) + Initialize ROP with limb space and set the initial numeric value + from OP. + + - Function: int mpz_init_set_str (mpz_t ROP, char *STR, int BASE) + Initialize ROP and set its value like `mpz_set_str' (see its + documentation above for details). + + If the string is a correct base BASE number, the function returns + 0; if an error occurs it returns -1. ROP is initialized even if + an error occurs. (I.e., you have to call `mpz_clear' for it.) + + +File: gmp.info, Node: Converting Integers, Next: Integer Arithmetic, Prev: Simultaneous Integer Init & Assign, Up: Integer Functions + +Conversion Functions +==================== + + This section describes functions for converting arbitrary precision +integers to standard C types. Functions for converting *to* arbitrary +precision integers are described in *Note Assigning Integers:: and +*Note I/O of Integers::. + + - Function: unsigned long int mpz_get_ui (mpz_t OP) + Return the least significant part from OP. This function combined + with + `mpz_tdiv_q_2exp(..., OP, CHAR_BIT*sizeof(unsigned long int))' can + be used to extract the limbs of an integer. + + - Function: signed long int mpz_get_si (mpz_t OP) + If OP fits into a `signed long int' return the value of OP. + Otherwise return the least significant part of OP, with the same + sign as OP. + + If OP is too large to fit in a `signed long int', the returned + result is probably not very useful. + + - Function: double mpz_get_d (mpz_t OP) + Convert OP to a double. + + - Function: char * mpz_get_str (char *STR, int BASE, mpz_t OP) + Convert OP to a string of digits in base BASE. The base may vary + from 2 to 36. + + If STR is NULL, space for the result string is allocated using the + default allocation function, and a pointer to the string is + returned. + + If STR is not NULL, it should point to a block of storage enough + large for the result. To find out the right amount of space to + provide for STR, use `mpz_sizeinbase (OP, BASE) + 2'. The two + extra bytes are for a possible minus sign, and for the terminating + null character. + + +File: gmp.info, Node: Integer Arithmetic, Next: Comparison Functions, Prev: Converting Integers, Up: Integer Functions + +Arithmetic Functions +==================== + + - Function: void mpz_add (mpz_t ROP, mpz_t OP1, mpz_t OP2) + - Function: void mpz_add_ui (mpz_t ROP, mpz_t OP1, unsigned long int + OP2) + Set ROP to OP1 + OP2. + + - Function: void mpz_sub (mpz_t ROP, mpz_t OP1, mpz_t OP2) + - Function: void mpz_sub_ui (mpz_t ROP, mpz_t OP1, unsigned long int + OP2) + Set ROP to OP1 - OP2. + + - Function: void mpz_mul (mpz_t ROP, mpz_t OP1, mpz_t OP2) + - Function: void mpz_mul_ui (mpz_t ROP, mpz_t OP1, unsigned long int + OP2) + Set ROP to OP1 times OP2. + + - Function: void mpz_mul_2exp (mpz_t ROP, mpz_t OP1, unsigned long int + OP2) + Set ROP to OP1 times 2 raised to OP2. This operation can also be + defined as a left shift, OP2 steps. + + - Function: void mpz_neg (mpz_t ROP, mpz_t OP) + Set ROP to -OP. + + - Function: void mpz_abs (mpz_t ROP, mpz_t OP) + Set ROP to the absolute value of OP. + + - Function: void mpz_fac_ui (mpz_t ROP, unsigned long int OP) + Set ROP to OP!, the factorial of OP. + +Division functions +------------------ + + Division is undefined if the divisor is zero, and passing a zero +divisor to the divide or modulo functions, as well passing a zero mod +argument to the `mpz_powm' and `mpz_powm_ui' functions, will make these +functions intentionally divide by zero. This gives the user the +possibility to handle arithmetic exceptions in these functions in the +same manner as other arithmetic exceptions. + + There are three main groups of division functions: + * Functions that truncate the quotient towards 0. The names of these + functions start with `mpz_tdiv'. The `t' in the name is short for + `truncate'. + + * Functions that round the quotient towards -infinity. The names of + these routines start with `mpz_fdiv'. The `f' in the name is + short for `floor'. + + * Functions that round the quotient towards +infinity. The names of + these routines start with `mpz_cdiv'. The `c' in the name is + short for `ceil'. + + For each rounding mode, there are a couple of variants. Here `q' +means that the quotient is computed, while `r' means that the remainder +is computed. Functions that compute both the quotient and remainder +have `qr' in the name. + + - Function: void mpz_tdiv_q (mpz_t ROP, mpz_t OP1, mpz_t OP2) + - Function: void mpz_tdiv_q_ui (mpz_t ROP, mpz_t OP1, unsigned long + int OP2) + Set ROP to [OP1/OP2]. The quotient is truncated towards 0. + + - Function: void mpz_tdiv_r (mpz_t ROP, mpz_t OP1, mpz_t OP2) + - Function: void mpz_tdiv_r_ui (mpz_t ROP, mpz_t OP1, unsigned long + int OP2) + Set ROP to (OP1 - [OP1/OP2] * OP2). Unless the remainder is zero, + it has the same sign as the dividend. + + - Function: void mpz_tdiv_qr (mpz_t ROP1, mpz_t ROP2, mpz_t OP1, mpz_t + OP2) + - Function: void mpz_tdiv_qr_ui (mpz_t ROP1, mpz_t ROP2, mpz_t OP1, + unsigned long int OP2) + Divide OP1 by OP2 and put the quotient in ROP1 and the remainder + in ROP2. The quotient is rounded towards 0. Unless the remainder + is zero, it has the same sign as the dividend. + + If ROP1 and ROP2 are the same variable, the results are undefined. + + - Function: void mpz_fdiv_q (mpz_t ROP1, mpz_t OP1, mpz_t OP2) + - Function: void mpz_fdiv_q_ui (mpz_t ROP, mpz_t OP1, unsigned long + int OP2) + Set ROP to OP1/OP2. The quotient is rounded towards -infinity. + + - Function: void mpz_fdiv_r (mpz_t ROP, mpz_t OP1, mpz_t OP2) + - Function: unsigned long int mpz_fdiv_r_ui (mpz_t ROP, mpz_t OP1, + unsigned long int OP2) + Divide OP1 by OP2 and put the remainder in ROP. Unless the + remainder is zero, it has the same sign as the divisor. + + For `mpz_fdiv_r_ui' the remainder is small enough to fit in an + `unsigned long int', and is therefore returned. + + - Function: void mpz_fdiv_qr (mpz_t ROP1, mpz_t ROP2, mpz_t OP1, mpz_t + OP2) + - Function: unsigned long int mpz_fdiv_qr_ui (mpz_t ROP1, mpz_t ROP2, + mpz_t OP1, unsigned long int OP2) + Divide OP1 by OP2 and put the quotient in ROP1 and the remainder + in ROP2. The quotient is rounded towards -infinity. Unless the + remainder is zero, it has the same sign as the divisor. + + For `mpz_fdiv_qr_ui' the remainder is small enough to fit in an + `unsigned long int', and is therefore returned. + + If ROP1 and ROP2 are the same variable, the results are undefined. + + - Function: unsigned long int mpz_fdiv_ui (mpz_t OP1, unsigned long + int OP2) + This function is similar to `mpz_fdiv_r_ui', but the remainder is + only returned; it is not stored anywhere. + + - Function: void mpz_cdiv_q (mpz_t ROP1, mpz_t OP1, mpz_t OP2) + - Function: void mpz_cdiv_q_ui (mpz_t ROP, mpz_t OP1, unsigned long + int OP2) + Set ROP to OP1/OP2. The quotient is rounded towards +infinity. + + - Function: void mpz_cdiv_r (mpz_t ROP, mpz_t OP1, mpz_t OP2) + - Function: unsigned long int mpz_cdiv_r_ui (mpz_t ROP, mpz_t OP1, + unsigned long int OP2) + Divide OP1 by OP2 and put the remainder in ROP. Unless the + remainder is zero, it has the opposite sign as the divisor. + + For `mpz_cdiv_r_ui' the negated remainder is small enough to fit + in an `unsigned long int', and it is therefore returned. + + - Function: void mpz_cdiv_qr (mpz_t ROP1, mpz_t ROP2, mpz_t OP1, mpz_t + OP2) + - Function: unsigned long int mpz_cdiv_qr_ui (mpz_t ROP1, mpz_t ROP2, + mpz_t OP1, unsigned long int OP2) + Divide OP1 by OP2 and put the quotient in ROP1 and the remainder + in ROP2. The quotient is rounded towards +infinity. Unless the + remainder is zero, it has the opposite sign as the divisor. + + For `mpz_cdiv_qr_ui' the negated remainder is small enough to fit + in an `unsigned long int', and it is therefore returned. + + If ROP1 and ROP2 are the same variable, the results are undefined. + + - Function: unsigned long int mpz_cdiv_ui (mpz_t OP1, unsigned long + int OP2) + Return the negated remainder, similar to `mpz_cdiv_r_ui'. (The + difference is that this function doesn't store the remainder + anywhere.) + + - Function: void mpz_mod (mpz_t ROP, mpz_t OP1, mpz_t OP2) + - Function: unsigned long int mpz_mod_ui (mpz_t ROP, mpz_t OP1, + unsigned long int OP2) + Set ROP to OP1 `mod' OP2. The sign of the divisor is ignored, and + the result is always non-negative. + + For `mpz_mod_ui' the remainder is small enough to fit in an + `unsigned long int', and is therefore returned. + + - Function: void mpz_divexact (mpz_t ROP, mpz_t OP1, mpz_t OP2) + Set ROP to OP1/OP2. This function produces correct results only + when it is known in advance that OP2 divides OP1. + + Since mpz_divexact is much faster than any of the other routines + that produce the quotient (*note References::. Jebelean), it is + the best choice for instances in which exact division is known to + occur, such as reducing a rational to lowest terms. + + - Function: void mpz_tdiv_q_2exp (mpz_t ROP, mpz_t OP1, unsigned long + int OP2) + Set ROP to OP1 divided by 2 raised to OP2. The quotient is + rounded towards 0. + + - Function: void mpz_tdiv_r_2exp (mpz_t ROP, mpz_t OP1, unsigned long + int OP2) + Divide OP1 by (2 raised to OP2) and put the remainder in ROP. + Unless it is zero, ROP will have the same sign as OP1. + + - Function: void mpz_fdiv_q_2exp (mpz_t ROP, mpz_t OP1, unsigned long + int OP2) + Set ROP to OP1 divided by 2 raised to OP2. The quotient is + rounded towards -infinity. + + - Function: void mpz_fdiv_r_2exp (mpz_t ROP, mpz_t OP1, unsigned long + int OP2) + Divide OP1 by (2 raised to OP2) and put the remainder in ROP. The + sign of ROP will always be positive. + + This operation can also be defined as masking of the OP2 least + significant bits. + +Exponentialization Functions +---------------------------- + + - Function: void mpz_powm (mpz_t ROP, mpz_t BASE, mpz_t EXP, mpz_t MOD) + - Function: void mpz_powm_ui (mpz_t ROP, mpz_t BASE, unsigned long int + EXP, mpz_t MOD) + Set ROP to (BASE raised to EXP) `mod' MOD. If EXP is negative, + the result is undefined. + + - Function: void mpz_pow_ui (mpz_t ROP, mpz_t BASE, unsigned long int + EXP) + - Function: void mpz_ui_pow_ui (mpz_t ROP, unsigned long int BASE, + unsigned long int EXP) + Set ROP to BASE raised to EXP. The case of 0^0 yields 1. + +Square Root Functions +--------------------- + + - Function: void mpz_sqrt (mpz_t ROP, mpz_t OP) + Set ROP to the truncated integer part of the square root of OP. + + - Function: void mpz_sqrtrem (mpz_t ROP1, mpz_t ROP2, mpz_t OP) + Set ROP1 to the truncated integer part of the square root of OP, + like `mpz_sqrt'. Set ROP2 to OP-ROP1*ROP1, (i.e., zero if OP is a + perfect square). + + If ROP1 and ROP2 are the same variable, the results are undefined. + + - Function: int mpz_perfect_square_p (mpz_t OP) + Return non-zero if OP is a perfect square, i.e., if the square + root of OP is an integer. Return zero otherwise. + +Number Theoretic Functions +-------------------------- + + - Function: int mpz_probab_prime_p (mpz_t OP, int REPS) + If this function returns 0, OP is definitely not prime. If it + returns 1, then OP is `probably' prime. The probability of a + false positive is (1/4)**REPS. A reasonable value of reps is 25. + + An implementation of the probabilistic primality test found in + Seminumerical Algorithms (*note References::. Knuth). + + - Function: void mpz_gcd (mpz_t ROP, mpz_t OP1, mpz_t OP2) + Set ROP to the greatest common divisor of OP1 and OP2. + + - Function: unsigned long int mpz_gcd_ui (mpz_t ROP, mpz_t OP1, + unsigned long int OP2) + Compute the greatest common divisor of OP1 and OP2. If ROP is not + NULL, store the result there. + + If the result is small enough to fit in an `unsigned long int', it + is returned. If the result does not fit, 0 is returned, and the + result is equal to the argument OP1. Note that the result will + always fit if OP2 is non-zero. + + - Function: void mpz_gcdext (mpz_t G, mpz_t S, mpz_t T, mpz_t A, mpz_t + B) + Compute G, S, and T, such that AS + BT = G = `gcd' (A, B). If T is + NULL, that argument is not computed. + + - Function: int mpz_invert (mpz_t ROP, mpz_t OP1, mpz_t OP2) + Compute the inverse of OP1 modulo OP2 and put the result in ROP. + Return non-zero if an inverse exist, zero otherwise. When the + function returns zero, do not assume anything about the value in + ROP. + + - Function: int mpz_jacobi (mpz_t OP1, mpz_t OP2) + - Function: int mpz_legendre (mpz_t OP1, mpz_t OP2) + Compute the Jacobi and Legendre symbols, respectively. + + +File: gmp.info, Node: Comparison Functions, Next: Integer Logic and Bit Fiddling, Prev: Integer Arithmetic, Up: Integer Functions + +Comparison Functions +==================== + + - Function: int mpz_cmp (mpz_t OP1, mpz_t OP2) + Compare OP1 and OP2. Return a positive value if OP1 > OP2, zero + if OP1 = OP2, and a negative value if OP1 < OP2. + + - Macro: int mpz_cmp_ui (mpz_t OP1, unsigned long int OP2) + - Macro: int mpz_cmp_si (mpz_t OP1, signed long int OP2) + Compare OP1 and OP2. Return a positive value if OP1 > OP2, zero + if OP1 = OP2, and a negative value if OP1 < OP2. + + These functions are actually implemented as macros. They evaluate + their arguments multiple times. + + - Macro: int mpz_sgn (mpz_t OP) + Return +1 if OP > 0, 0 if OP = 0, and -1 if OP < 0. + + This function is actually implemented as a macro. It evaluates its + arguments multiple times. + + +File: gmp.info, Node: Integer Logic and Bit Fiddling, Next: I/O of Integers, Prev: Comparison Functions, Up: Integer Functions + +Logical and Bit Manipulation Functions +====================================== + + These functions behave as if two's complement arithmetic were used +(although sign-magnitude is used by the actual implementation). + + - Function: void mpz_and (mpz_t ROP, mpz_t OP1, mpz_t OP2) + Set ROP to OP1 logical-and OP2. + + - Function: void mpz_ior (mpz_t ROP, mpz_t OP1, mpz_t OP2) + Set ROP to OP1 inclusive-or OP2. + + - Function: void mpz_com (mpz_t ROP, mpz_t OP) + Set ROP to the one's complement of OP. + + - Function: unsigned long int mpz_popcount (mpz_t OP) + For non-negative numbers, return the population count of OP. For + negative numbers, return the largest possible value (MAX_ULONG). + + - Function: unsigned long int mpz_hamdist (mpz_t OP1, mpz_t OP2) + If OP1 and OP2 are both non-negative, return the hamming distance + between the two operands. Otherwise, return the largest possible + value (MAX_ULONG). + + It is possible to extend this function to return a useful value + when the operands are both negative, but the current + implementation returns MAX_ULONG in this case. *Do not depend on + this behavior, since it will change in future versions of the + library.* + + - Function: unsigned long int mpz_scan0 (mpz_t OP, unsigned long int + STARTING_BIT) + Scan OP, starting with bit STARTING_BIT, towards more significant + bits, until the first clear bit is found. Return the index of the + found bit. + + - Function: unsigned long int mpz_scan1 (mpz_t OP, unsigned long int + STARTING_BIT) + Scan OP, starting with bit STARTING_BIT, towards more significant + bits, until the first set bit is found. Return the index of the + found bit. + + - Function: void mpz_setbit (mpz_t ROP, unsigned long int BIT_INDEX) + Set bit BIT_INDEX in OP1. + + - Function: void mpz_clrbit (mpz_t ROP, unsigned long int BIT_INDEX) + Clear bit BIT_INDEX in OP1. + + +File: gmp.info, Node: I/O of Integers, Next: Miscellaneous Integer Functions, Prev: Integer Logic and Bit Fiddling, Up: Integer Functions + +Input and Output Functions +========================== + + Functions that perform input from a stdio stream, and functions that +output to a stdio stream. Passing a NULL pointer for a STREAM argument +to any of these functions will make them read from `stdin' and write to +`stdout', respectively. + + When using any of these functions, it is a good idea to include +`stdio.h' before `gmp.h', since that will allow `gmp.h' to define +prototypes for these functions. + + - Function: size_t mpz_out_str (FILE *STREAM, int BASE, mpz_t OP) + Output OP on stdio stream STREAM, as a string of digits in base + BASE. The base may vary from 2 to 36. + + Return the number of bytes written, or if an error occurred, + return 0. + + - Function: size_t mpz_inp_str (mpz_t ROP, FILE *STREAM, int BASE) + Input a possibly white-space preceded string in base BASE from + stdio stream STREAM, and put the read integer in ROP. The base + may vary from 2 to 36. If BASE is 0, the actual base is + determined from the leading characters: if the first two + characters are `0x' or `0X', hexadecimal is assumed, otherwise if + the first character is `0', octal is assumed, otherwise decimal is + assumed. + + Return the number of bytes read, or if an error occurred, return 0. + + - Function: size_t mpz_out_raw (FILE *STREAM, mpz_t OP) + Output OP on stdio stream STREAM, in raw binary format. The + integer is written in a portable format, with 4 bytes of size + information, and that many bytes of limbs. Both the size and the + limbs are written in decreasing significance order (i.e., in + big-endian). + + The output can be read with `mpz_inp_raw'. + + Return the number of bytes written, or if an error occurred, + return 0. + + The output of this can not be read by `mpz_inp_raw' from GMP 1, + because of changes necessary for compatibility between 32-bit and + 64-bit machines. + + - Function: size_t mpz_inp_raw (mpz_t ROP, FILE *STREAM) + Input from stdio stream STREAM in the format written by + `mpz_out_raw', and put the result in ROP. Return the number of + bytes read, or if an error occurred, return 0. + + This routine can read the output from `mpz_out_raw' also from GMP + 1, in spite of changes necessary for compatibility between 32-bit + and 64-bit machines. + + +File: gmp.info, Node: Miscellaneous Integer Functions, Prev: I/O of Integers, Up: Integer Functions + +Miscellaneous Functions +======================= + + - Function: void mpz_random (mpz_t ROP, mp_size_t MAX_SIZE) + Generate a random integer of at most MAX_SIZE limbs. The generated + random number doesn't satisfy any particular requirements of + randomness. Negative random numbers are generated when MAX_SIZE + is negative. + + - Function: void mpz_random2 (mpz_t ROP, mp_size_t MAX_SIZE) + Generate a random integer of at most MAX_SIZE limbs, with long + strings of zeros and ones in the binary representation. Useful + for testing functions and algorithms, since this kind of random + numbers have proven to be more likely to trigger corner-case bugs. + Negative random numbers are generated when MAX_SIZE is negative. + + - Function: size_t mpz_size (mpz_t OP) + Return the size of OP measured in number of limbs. If OP is zero, + the returned value will be zero. + + *This function is obsolete. It will disappear from future MP + releases.* + + - Function: size_t mpz_sizeinbase (mpz_t OP, int BASE) + Return the size of OP measured in number of digits in base BASE. + The base may vary from 2 to 36. The returned value will be exact + or 1 too big. If BASE is a power of 2, the returned value will + always be exact. + + This function is useful in order to allocate the right amount of + space before converting OP to a string. The right amount of + allocation is normally two more than the value returned by + `mpz_sizeinbase' (one extra for a minus sign and one for the + terminating '\0'). + + +File: gmp.info, Node: Rational Number Functions, Next: Floating-point Functions, Prev: Integer Functions, Up: Top + +Rational Number Functions +************************* + + This chapter describes the MP functions for performing arithmetic on +rational numbers. These functions start with the prefix `mpq_'. + + Rational numbers are stored in objects of type `mpq_t'. + + All rational arithmetic functions assume operands have a canonical +form, and canonicalize their result. The canonical from means that the +denominator and the numerator have no common factors, and that the +denominator is positive. Zero has the unique representation 0/1. + + Pure assignment functions do not canonicalize the assigned variable. +It is the responsibility of the user to canonicalize the assigned +variable before any arithmetic operations are performed on that +variable. *Note that this is an incompatible change from version 1 of +the library.* + + - Function: void mpq_canonicalize (mpq_t OP) + Remove any factors that are common to the numerator and + denominator of OP, and make the denominator positive. + +* Menu: + +* Initializing Rationals:: +* Assigning Rationals:: +* Simultaneous Integer Init & Assign:: +* Comparing Rationals:: +* Applying Integer Functions:: +* Miscellaneous Rational Functions:: + + +File: gmp.info, Node: Initializing Rationals, Next: Assigning Rationals, Prev: Rational Number Functions, Up: Rational Number Functions + +Initialization and Assignment Functions +======================================= + + - Function: void mpq_init (mpq_t DEST_RATIONAL) + Initialize DEST_RATIONAL and set it to 0/1. Each variable should + normally only be initialized once, or at least cleared out (using + the function `mpq_clear') between each initialization. + + - Function: void mpq_clear (mpq_t RATIONAL_NUMBER) + Free the space occupied by RATIONAL_NUMBER. Make sure to call this + function for all `mpq_t' variables when you are done with them. + + - Function: void mpq_set (mpq_t ROP, mpq_t OP) + - Function: void mpq_set_z (mpq_t ROP, mpz_t OP) + Assign ROP from OP. + + - Function: void mpq_set_ui (mpq_t ROP, unsigned long int OP1, + unsigned long int OP2) + - Function: void mpq_set_si (mpq_t ROP, signed long int OP1, unsigned + long int OP2) + Set the value of ROP to OP1/OP2. Note that if OP1 and OP2 have + common factors, ROP has to be passed to `mpq_canonicalize' before + any operations are performed on ROP. + + +File: gmp.info, Node: Assigning Rationals, Next: Comparing Rationals, Prev: Initializing Rationals, Up: Rational Number Functions + +Arithmetic Functions +==================== + + - Function: void mpq_add (mpq_t SUM, mpq_t ADDEND1, mpq_t ADDEND2) + Set SUM to ADDEND1 + ADDEND2. + + - Function: void mpq_sub (mpq_t DIFFERENCE, mpq_t MINUEND, mpq_t + SUBTRAHEND) + Set DIFFERENCE to MINUEND - SUBTRAHEND. + + - Function: void mpq_mul (mpq_t PRODUCT, mpq_t MULTIPLIER, mpq_t + MULTIPLICAND) + Set PRODUCT to MULTIPLIER times MULTIPLICAND. + + - Function: void mpq_div (mpq_t QUOTIENT, mpq_t DIVIDEND, mpq_t + DIVISOR) + Set QUOTIENT to DIVIDEND/DIVISOR. + + - Function: void mpq_neg (mpq_t NEGATED_OPERAND, mpq_t OPERAND) + Set NEGATED_OPERAND to -OPERAND. + + - Function: void mpq_inv (mpq_t INVERTED_NUMBER, mpq_t NUMBER) + Set INVERTED_NUMBER to 1/NUMBER. If the new denominator is zero, + this routine will divide by zero. + + +File: gmp.info, Node: Comparing Rationals, Next: Applying Integer Functions, Prev: Assigning Rationals, Up: Rational Number Functions + +Comparison Functions +==================== + + - Function: int mpq_cmp (mpq_t OP1, mpq_t OP2) + Compare OP1 and OP2. Return a positive value if OP1 > OP2, zero + if OP1 = OP2, and a negative value if OP1 < OP2. + + To determine if two rationals are equal, `mpq_equal' is faster than + `mpq_cmp'. + + - Macro: int mpq_cmp_ui (mpq_t OP1, unsigned long int NUM2, unsigned + long int DEN2) + Compare OP1 and NUM2/DEN2. Return a positive value if OP1 > + NUM2/DEN2, zero if OP1 = NUM2/DEN2, and a negative value if OP1 < + NUM2/DEN2. + + This routine allows that NUM2 and DEN2 have common factors. + + This function is actually implemented as a macro. It evaluates its + arguments multiple times. + + - Macro: int mpq_sgn (mpq_t OP) + Return +1 if OP > 0, 0 if OP = 0, and -1 if OP < 0. + + This function is actually implemented as a macro. It evaluates its + arguments multiple times. + + - Function: int mpq_equal (mpq_t OP1, mpq_t OP2) + Return non-zero if OP1 and OP2 are equal, zero if they are + non-equal. Although `mpq_cmp' can be used for the same purpose, + this function is much faster. + + +File: gmp.info, Node: Applying Integer Functions, Next: Miscellaneous Rational Functions, Prev: Comparing Rationals, Up: Rational Number Functions + +Applying Integer Functions to Rationals +======================================= + + The set of `mpq' functions is quite small. In particular, there are +no functions for either input or output. But there are two macros that +allow us to apply any `mpz' function on the numerator or denominator of +a rational number. If these macros are used to assign to the rational +number, `mpq_canonicalize' normally need to be called afterwards. + + - Macro: mpz_t mpq_numref (mpq_t OP) + - Macro: mpz_t mpq_denref (mpq_t OP) + Return a reference to the numerator and denominator of OP, + respectively. The `mpz' functions can be used on the result of + these macros. + + +File: gmp.info, Node: Miscellaneous Rational Functions, Prev: Applying Integer Functions, Up: Rational Number Functions + +Miscellaneous Functions +======================= + + - Function: double mpq_get_d (mpq_t OP) + Convert OP to a double. + + These functions assign between either the numerator or denominator +of a rational, and an integer. Instead of using these functions, it is +preferable to use the more general mechanisms `mpq_numref' and +`mpq_denref', together with `mpz_set'. + + - Function: void mpq_set_num (mpq_t RATIONAL, mpz_t NUMERATOR) + Copy NUMERATOR to the numerator of RATIONAL. When this risks to + make the numerator and denominator of RATIONAL have common + factors, you have to pass RATIONAL to `mpq_canonicalize' before + any operations are performed on RATIONAL. + + This function is equivalent to `mpz_set (mpq_numref (RATIONAL), + NUMERATOR)'. + + - Function: void mpq_set_den (mpq_t RATIONAL, mpz_t DENOMINATOR) + Copy DENOMINATOR to the denominator of RATIONAL. When this risks + to make the numerator and denominator of RATIONAL have common + factors, or if the denominator might be negative, you have to pass + RATIONAL to `mpq_canonicalize' before any operations are performed + on RATIONAL. + + *In version 1 of the library, negative denominators were handled by + copying the sign to the numerator. That is no longer done.* + + This function is equivalent to `mpz_set (mpq_denref (RATIONAL), + DENOMINATORS)'. + + - Function: void mpq_get_num (mpz_t NUMERATOR, mpq_t RATIONAL) + Copy the numerator of RATIONAL to the integer NUMERATOR, to + prepare for integer operations on the numerator. + + This function is equivalent to `mpz_set (NUMERATOR, mpq_numref + (RATIONAL))'. + + - Function: void mpq_get_den (mpz_t DENOMINATOR, mpq_t RATIONAL) + Copy the denominator of RATIONAL to the integer DENOMINATOR, to + prepare for integer operations on the denominator. + + This function is equivalent to `mpz_set (DENOMINATOR, mpq_denref + (RATIONAL))'. + diff --git a/contrib/libgmp/gmp.info-2 b/contrib/libgmp/gmp.info-2 new file mode 100644 index 0000000..7a92755 --- /dev/null +++ b/contrib/libgmp/gmp.info-2 @@ -0,0 +1,1035 @@ +This is Info file gmp.info, produced by Makeinfo-1.64 from the input +file gmp.texi. + +START-INFO-DIR-ENTRY +* gmp: (gmp.info). GNU Multiple Precision Arithmetic Library. +END-INFO-DIR-ENTRY + + This file documents GNU MP, a library for arbitrary-precision +arithmetic. + + Copyright (C) 1991, 1993, 1994, 1995, 1996 Free Software Foundation, +Inc. + + Permission is granted to make and distribute verbatim copies of this +manual provided the copyright notice and this permission notice are +preserved on all copies. + + Permission is granted to copy and distribute modified versions of +this manual under the conditions for verbatim copying, provided that +the entire resulting derived work is distributed under the terms of a +permission notice identical to this one. + + Permission is granted to copy and distribute translations of this +manual into another language, under the above conditions for modified +versions, except that this permission notice may be stated in a +translation approved by the Foundation. + + +File: gmp.info, Node: Floating-point Functions, Next: Low-level Functions, Prev: Rational Number Functions, Up: Top + +Floating-point Functions +************************ + + This is a description of the *preliminary* interface for +floating-point arithmetic in GNU MP 2. + + The floating-point functions expect arguments of type `mpf_t'. + + The MP floating-point functions have an interface that is similar to +the MP integer functions. The function prefix for floating-point +operations is `mpf_'. + + There is one significant characteristic of floating-point numbers +that has motivated a difference between this function class and other +MP function classes: the inherent inexactness of floating point +arithmetic. The user has to specify the precision of each variable. A +computation that assigns a variable will take place with the precision +of the assigned variable; the precision of variables used as input is +ignored. + + The precision of a calculation is defined as follows: Compute the +requested operation exactly (with "infinite precision"), and truncate +the result to the destination variable precision. Even if the user has +asked for a very high precision, MP will not calculate with superfluous +digits. For example, if two low-precision numbers of nearly equal +magnitude are added, the precision of the result will be limited to +what is required to represent the result accurately. + + The MP floating-point functions are *not* intended as a smooth +extension to the IEEE P754 arithmetic. Specifically, the results +obtained on one computer often differs from the results obtained on a +computer with a different word size. + +* Menu: + +* Initializing Floats:: +* Assigning Floats:: +* Simultaneous Float Init & Assign:: +* Converting Floats:: +* Float Arithmetic:: +* Float Comparison:: +* I/O of Floats:: +* Miscellaneous Float Functions:: + + +File: gmp.info, Node: Initializing Floats, Next: Assigning Floats, Up: Floating-point Functions + +Initialization and Assignment Functions +======================================= + + - Function: void mpf_set_default_prec (unsigned long int PREC) + Set the default precision to be *at least* PREC bits. All + subsequent calls to `mpf_init' will use this precision, but + previously initialized variables are unaffected. + + An `mpf_t' object must be initialized before storing the first value +in it. The functions `mpf_init' and `mpf_init2' are used for that +purpose. + + - Function: void mpf_init (mpf_t X) + Initialize X to 0. Normally, a variable should be initialized + once only or at least be cleared, using `mpf_clear', between + initializations. The precision of X is undefined unless a default + precision has already been established by a call to + `mpf_set_default_prec'. + + - Function: void mpf_init2 (mpf_t X, unsigned long int PREC) + Initialize X to 0 and set its precision to be *at least* PREC + bits. Normally, a variable should be initialized once only or at + least be cleared, using `mpf_clear', between initializations. + + - Function: void mpf_clear (mpf_t X) + Free the space occupied by X. Make sure to call this function for + all `mpf_t' variables when you are done with them. + + Here is an example on how to initialize floating-point variables: + { + mpf_t x, y; + mpf_init (x); /* use default precision */ + mpf_init2 (y, 256); /* precision *at least* 256 bits */ + ... + /* Unless the program is about to exit, do ... */ + mpf_clear (x); + mpf_clear (y); + } + + The following three functions are useful for changing the precision +during a calculation. A typical use would be for adjusting the +precision gradually in iterative algorithms like Newton-Raphson, making +the computation precision closely match the actual accurate part of the +numbers. + + - Function: void mpf_set_prec (mpf_t ROP, unsigned long int PREC) + Set the precision of ROP to be *at least* PREC bits. Since + changing the precision involves calls to `realloc', this routine + should not be called in a tight loop. + + - Function: unsigned long int mpf_get_prec (mpf_t OP) + Return the precision actually used for assignments of OP. + + - Function: void mpf_set_prec_raw (mpf_t ROP, unsigned long int PREC) + Set the precision of ROP to be *at least* PREC bits. This is a + low-level function that does not change the allocation. The PREC + argument must not be larger that the precision previously returned + by `mpf_get_prec'. It is crucial that the precision of ROP is + ultimately reset to exactly the value returned by `mpf_get_prec'. + + +File: gmp.info, Node: Assigning Floats, Next: Simultaneous Float Init & Assign, Prev: Initializing Floats, Up: Floating-point Functions + +Assignment Functions +-------------------- + + These functions assign new values to already initialized floats +(*note Initializing Floats::.). + + - Function: void mpf_set (mpf_t ROP, mpf_t OP) + - Function: void mpf_set_ui (mpf_t ROP, unsigned long int OP) + - Function: void mpf_set_si (mpf_t ROP, signed long int OP) + - Function: void mpf_set_d (mpf_t ROP, double OP) + - Function: void mpf_set_z (mpf_t ROP, mpz_t OP) + - Function: void mpf_set_q (mpf_t ROP, mpq_t OP) + Set the value of ROP from OP. + + - Function: int mpf_set_str (mpf_t ROP, char *STR, int BASE) + Set the value of ROP from the string in STR. The string is of the + form `M@N' or, if the base is 10 or less, alternatively `MeN'. + `M' is the mantissa and `N' is the exponent. The mantissa is + always in the specified base. The exponent is either in the + specified base or, if BASE is negative, in decimal. + + The argument BASE may be in the ranges 2 to 36, or -36 to -2. + Negative values are used to specify that the exponent is in + decimal. + + Unlike the corresponding `mpz' function, the base will not be + determined from the leading characters of the string if BASE is 0. + This is so that numbers like `0.23' are not interpreted as octal. + + White space is allowed in the string, and is simply ignored. + + This function returns 0 if the entire string up to the '\0' is a + valid number in base BASE. Otherwise it returns -1. + + +File: gmp.info, Node: Simultaneous Float Init & Assign, Next: Converting Floats, Prev: Assigning Floats, Up: Floating-point Functions + +Combined Initialization and Assignment Functions +------------------------------------------------ + + For convenience, MP provides a parallel series of initialize-and-set +functions which initialize the output and then store the value there. +These functions' names have the form `mpf_init_set...' + + Once the float has been initialized by any of the `mpf_init_set...' +functions, it can be used as the source or destination operand for the +ordinary float functions. Don't use an initialize-and-set function on +a variable already initialized! + + - Function: void mpf_init_set (mpf_t ROP, mpf_t OP) + - Function: void mpf_init_set_ui (mpf_t ROP, unsigned long int OP) + - Function: void mpf_init_set_si (mpf_t ROP, signed long int OP) + - Function: void mpf_init_set_d (mpf_t ROP, double OP) + Initialize ROP and set its value from OP. + + The precision of ROP will be taken from the active default + precision, as set by `mpf_set_default_prec'. + + - Function: int mpf_init_set_str (mpf_t ROP, char *STR, int BASE) + Initialize ROP and set its value from the string in STR. See + `mpf_set_str' above for details on the assignment operation. + + Note that ROP is initialized even if an error occurs. (I.e., you + have to call `mpf_clear' for it.) + + The precision of ROP will be taken from the active default + precision, as set by `mpf_set_default_prec'. + + +File: gmp.info, Node: Converting Floats, Next: Float Arithmetic, Prev: Simultaneous Float Init & Assign, Up: Floating-point Functions + +Conversion Functions +==================== + + - Function: double mpf_get_d (mpf_t OP) + Convert OP to a double. + + - Function: char * mpf_get_str (char *STR, mp_exp_t *EXPPTR, int BASE, + size_t N_DIGITS, mpf_t OP) + Convert OP to a string of digits in base BASE. The base may vary + from 2 to 36. Generate at most N_DIGITS significant digits, or if + N_DIGITS is 0, the maximum number of digits accurately + representable by OP. + + If STR is NULL, space for the mantissa is allocated using the + default allocation function, and a pointer to the string is + returned. + + If STR is not NULL, it should point to a block of storage enough + large for the mantissa, i.e., N_DIGITS + 2. The two extra bytes + are for a possible minus sign, and for the terminating null + character. + + The exponent is written through the pointer EXPPTR. + + If N_DIGITS is 0, the maximum number of digits meaningfully + achievable from the precision of OP will be generated. Note that + the space requirements for STR in this case will be impossible for + the user to predetermine. Therefore, you need to pass NULL for + the string argument whenever N_DIGITS is 0. + + The generated string is a fraction, with an implicit radix point + immediately to the left of the first digit. For example, the + number 3.1416 would be returned as "31416" in the string and 1 + written at EXPPTR. + + +File: gmp.info, Node: Float Arithmetic, Next: Float Comparison, Prev: Converting Floats, Up: Floating-point Functions + +Arithmetic Functions +==================== + + - Function: void mpf_add (mpf_t ROP, mpf_t OP1, mpf_t OP2) + - Function: void mpf_add_ui (mpf_t ROP, mpf_t OP1, unsigned long int + OP2) + Set ROP to OP1 + OP2. + + - Function: void mpf_sub (mpf_t ROP, mpf_t OP1, mpf_t OP2) + - Function: void mpf_ui_sub (mpf_t ROP, unsigned long int OP1, mpf_t + OP2) + - Function: void mpf_sub_ui (mpf_t ROP, mpf_t OP1, unsigned long int + OP2) + Set ROP to OP1 - OP2. + + - Function: void mpf_mul (mpf_t ROP, mpf_t OP1, mpf_t OP2) + - Function: void mpf_mul_ui (mpf_t ROP, mpf_t OP1, unsigned long int + OP2) + Set ROP to OP1 times OP2. + + Division is undefined if the divisor is zero, and passing a zero +divisor to the divide functions will make these functions intentionally +divide by zero. This gives the user the possibility to handle +arithmetic exceptions in these functions in the same manner as other +arithmetic exceptions. + + - Function: void mpf_div (mpf_t ROP, mpf_t OP1, mpf_t OP2) + - Function: void mpf_ui_div (mpf_t ROP, unsigned long int OP1, mpf_t + OP2) + - Function: void mpf_div_ui (mpf_t ROP, mpf_t OP1, unsigned long int + OP2) + Set ROP to OP1/OP2. + + - Function: void mpf_sqrt (mpf_t ROP, mpf_t OP) + - Function: void mpf_sqrt_ui (mpf_t ROP, unsigned long int OP) + Set ROP to the square root of OP. + + - Function: void mpf_neg (mpf_t ROP, mpf_t OP) + Set ROP to -OP. + + - Function: void mpf_abs (mpf_t ROP, mpf_t OP) + Set ROP to the absolute value of OP. + + - Function: void mpf_mul_2exp (mpf_t ROP, mpf_t OP1, unsigned long int + OP2) + Set ROP to OP1 times 2 raised to OP2. + + - Function: void mpf_div_2exp (mpf_t ROP, mpf_t OP1, unsigned long int + OP2) + Set ROP to OP1 divided by 2 raised to OP2. + + +File: gmp.info, Node: Float Comparison, Next: I/O of Floats, Prev: Float Arithmetic, Up: Floating-point Functions + +Comparison Functions +==================== + + - Function: int mpf_cmp (mpf_t OP1, mpf_t OP2) + - Function: int mpf_cmp_ui (mpf_t OP1, unsigned long int OP2) + - Function: int mpf_cmp_si (mpf_t OP1, signed long int OP2) + Compare OP1 and OP2. Return a positive value if OP1 > OP2, zero + if OP1 = OP2, and a negative value if OP1 < OP2. + + - Function: int mpf_eq (mpf_t OP1, mpf_t OP2, unsigned long int op3) + Return non-zero if the first OP3 bits of OP1 and OP2 are equal, + zero otherwise. I.e., test of OP1 and OP2 are approximately equal. + + - Function: void mpf_reldiff (mpf_t ROP, mpf_t OP1, mpf_t OP2) + Compute the relative difference between OP1 and OP2 and store the + result in ROP. + + - Macro: int mpf_sgn (mpf_t OP) + Return +1 if OP > 0, 0 if OP = 0, and -1 if OP < 0. + + This function is actually implemented as a macro. It evaluates its + arguments multiple times. + + +File: gmp.info, Node: I/O of Floats, Next: Miscellaneous Float Functions, Prev: Float Comparison, Up: Floating-point Functions + +Input and Output Functions +========================== + + Functions that perform input from a stdio stream, and functions that +output to a stdio stream. Passing a NULL pointer for a STREAM argument +to any of these functions will make them read from `stdin' and write to +`stdout', respectively. + + When using any of these functions, it is a good idea to include +`stdio.h' before `gmp.h', since that will allow `gmp.h' to define +prototypes for these functions. + + - Function: size_t mpf_out_str (FILE *STREAM, int BASE, size_t + N_DIGITS, mpf_t OP) + Output OP on stdio stream STREAM, as a string of digits in base + BASE. The base may vary from 2 to 36. Print at most N_DIGITS + significant digits, or if N_DIGITS is 0, the maximum number of + digits accurately representable by OP. + + In addition to the significant digits, a leading `0.' and a + trailing exponent, in the form `eNNN', are printed. If BASE is + greater than 10, `@' will be used instead of `e' as exponent + delimiter. + + Return the number of bytes written, or if an error occurred, + return 0. + + - Function: size_t mpf_inp_str (mpf_t ROP, FILE *STREAM, int BASE) + Input a string in base BASE from stdio stream STREAM, and put the + read float in ROP. The string is of the form `M@N' or, if the + base is 10 or less, alternatively `MeN'. `M' is the mantissa and + `N' is the exponent. The mantissa is always in the specified + base. The exponent is either in the specified base or, if BASE is + negative, in decimal. + + The argument BASE may be in the ranges 2 to 36, or -36 to -2. + Negative values are used to specify that the exponent is in + decimal. + + Unlike the corresponding `mpz' function, the base will not be + determined from the leading characters of the string if BASE is 0. + This is so that numbers like `0.23' are not interpreted as octal. + + Return the number of bytes read, or if an error occurred, return 0. + + +File: gmp.info, Node: Miscellaneous Float Functions, Prev: I/O of Floats, Up: Floating-point Functions + +Miscellaneous Functions +======================= + + - Function: void mpf_random2 (mpf_t ROP, mp_size_t MAX_SIZE, mp_exp_t + MAX_EXP) + Generate a random float of at most MAX_SIZE limbs, with long + strings of zeros and ones in the binary representation. The + exponent of the number is in the interval -EXP to EXP. This + function is useful for testing functions and algorithms, since + this kind of random numbers have proven to be more likely to + trigger corner-case bugs. Negative random numbers are generated + when MAX_SIZE is negative. + + +File: gmp.info, Node: Low-level Functions, Next: BSD Compatible Functions, Prev: Floating-point Functions, Up: Top + +Low-level Functions +******************* + + This chapter describes low-level MP functions, used to implement the +high-level MP functions, but also intended for time-critical user code. + + These functions start with the prefix `mpn_'. + + The `mpn' functions are designed to be as fast as possible, *not* to +provide a coherent calling interface. The different functions have +somewhat similar interfaces, but there are variations that make them +hard to use. These functions do as little as possible apart from the +real multiple precision computation, so that no time is spent on things +that not all callers need. + + A source operand is specified by a pointer to the least significant +limb and a limb count. A destination operand is specified by just a +pointer. It is the responsibility of the caller to ensure that the +destination has enough space for storing the result. + + With this way of specifying operands, it is possible to perform +computations on subranges of an argument, and store the result into a +subrange of a destination. + + A common requirement for all functions is that each source area +needs at least one limb. No size argument may be zero. + + The `mpn' functions is the base for the implementation of the `mpz_', +`mpf_', and `mpq_' functions. + + This example adds the number beginning at SRC1_PTR and the number +beginning at SRC2_PTR and writes the sum at DEST_PTR. All areas have +SIZE limbs. + + cy = mpn_add_n (dest_ptr, src1_ptr, src2_ptr, size) + +In the notation used here, a source operand is identified by the +pointer to the least significant limb, and the limb count in braces. +For example, {s1_ptr, s1_size}. + + - Function: mp_limb_t mpn_add_n (mp_limb_t * DEST_PTR, const mp_limb_t + * SRC1_PTR, const mp_limb_t * SRC2_PTR, mp_size_t SIZE) + Add {SRC1_PTR, SIZE} and {SRC2_PTR, SIZE}, and write the SIZE + least significant limbs of the result to DEST_PTR. Return carry, + either 0 or 1. + + This is the lowest-level function for addition. It is the + preferred function for addition, since it is written in assembly + for most targets. For addition of a variable to itself (i.e., + SRC1_PTR equals SRC2_PTR, use `mpn_lshift' with a count of 1 for + optimal speed. + + - Function: mp_limb_t mpn_add_1 (mp_limb_t * DEST_PTR, const mp_limb_t + * SRC1_PTR, mp_size_t SIZE, mp_limb_t SRC2_LIMB) + Add {SRC1_PTR, SIZE} and SRC2_LIMB, and write the SIZE least + significant limbs of the result to DEST_PTR. Return carry, either + 0 or 1. + + - Function: mp_limb_t mpn_add (mp_limb_t * DEST_PTR, const mp_limb_t * + SRC1_PTR, mp_size_t SRC1_SIZE, const mp_limb_t * SRC2_PTR, + mp_size_t SRC2_SIZE) + Add {SRC1_PTR, SRC1_SIZE} and {SRC2_PTR, SRC2_SIZE}, and write the + SRC1_SIZE least significant limbs of the result to DEST_PTR. + Return carry, either 0 or 1. + + This function requires that SRC1_SIZE is greater than or equal to + SRC2_SIZE. + + - Function: mp_limb_t mpn_sub_n (mp_limb_t * DEST_PTR, const mp_limb_t + * SRC1_PTR, const mp_limb_t * SRC2_PTR, mp_size_t SIZE) + Subtract {SRC2_PTR, SRC2_SIZE} from {SRC1_PTR, SIZE}, and write + the SIZE least significant limbs of the result to DEST_PTR. + Return borrow, either 0 or 1. + + This is the lowest-level function for subtraction. It is the + preferred function for subtraction, since it is written in + assembly for most targets. + + - Function: mp_limb_t mpn_sub_1 (mp_limb_t * DEST_PTR, const mp_limb_t + * SRC1_PTR, mp_size_t SIZE, mp_limb_t SRC2_LIMB) + Subtract SRC2_LIMB from {SRC1_PTR, SIZE}, and write the SIZE least + significant limbs of the result to DEST_PTR. Return borrow, + either 0 or 1. + + - Function: mp_limb_t mpn_sub (mp_limb_t * DEST_PTR, const mp_limb_t * + SRC1_PTR, mp_size_t SRC1_SIZE, const mp_limb_t * SRC2_PTR, + mp_size_t SRC2_SIZE) + Subtract {SRC2_PTR, SRC2_SIZE} from {SRC1_PTR, SRC1_SIZE}, and + write the SRC1_SIZE least significant limbs of the result to + DEST_PTR. Return borrow, either 0 or 1. + + This function requires that SRC1_SIZE is greater than or equal to + SRC2_SIZE. + + - Function: void mpn_mul_n (mp_limb_t * DEST_PTR, const mp_limb_t * + SRC1_PTR, const mp_limb_t * SRC2_PTR, mp_size_t SIZE) + Multiply {SRC1_PTR, SIZE} and {SRC2_PTR, SIZE}, and write the + *entire* result to DEST_PTR. + + The destination has to have space for 2SIZE limbs, even if the + significant result might be one limb smaller. + + - Function: mp_limb_t mpn_mul_1 (mp_limb_t * DEST_PTR, const mp_limb_t + * SRC1_PTR, mp_size_t SIZE, mp_limb_t SRC2_LIMB) + Multiply {SRC1_PTR, SIZE} and SRC2_LIMB, and write the SIZE least + significant limbs of the product to DEST_PTR. Return the most + significant limb of the product. + + This is a low-level function that is a building block for general + multiplication as well as other operations in MP. It is written + in assembly for most targets. + + Don't call this function if SRC2_LIMB is a power of 2; use + `mpn_lshift' with a count equal to the logarithm of SRC2_LIMB + instead, for optimal speed. + + - Function: mp_limb_t mpn_addmul_1 (mp_limb_t * DEST_PTR, const + mp_limb_t * SRC1_PTR, mp_size_t SIZE, mp_limb_t SRC2_LIMB) + Multiply {SRC1_PTR, SIZE} and SRC2_LIMB, and add the SIZE least + significant limbs of the product to {DEST_PTR, SIZE} and write the + result to DEST_PTR DEST_PTR. Return the most significant limb of + the product, plus carry-out from the addition. + + This is a low-level function that is a building block for general + multiplication as well as other operations in MP. It is written + in assembly for most targets. + + - Function: mp_limb_t mpn_submul_1 (mp_limb_t * DEST_PTR, const + mp_limb_t * SRC1_PTR, mp_size_t SIZE, mp_limb_t SRC2_LIMB) + Multiply {SRC1_PTR, SIZE} and SRC2_LIMB, and subtract the SIZE + least significant limbs of the product from {DEST_PTR, SIZE} and + write the result to DEST_PTR. Return the most significant limb of + the product, minus borrow-out from the subtraction. + + This is a low-level function that is a building block for general + multiplication and division as well as other operations in MP. It + is written in assembly for most targets. + + - Function: mp_limb_t mpn_mul (mp_limb_t * DEST_PTR, const mp_limb_t * + SRC1_PTR, mp_size_t SRC1_SIZE, const mp_limb_t * SRC2_PTR, + mp_size_t SRC2_SIZE) + Multiply {SRC1_PTR, SRC1_SIZE} and {SRC2_PTR, SRC2_SIZE}, and + write the result to DEST_PTR. Return the most significant limb of + the result. + + The destination has to have space for SRC1_SIZE + SRC1_SIZE limbs, + even if the result might be one limb smaller. + + This function requires that SRC1_SIZE is greater than or equal to + SRC2_SIZE. The destination must be distinct from either input + operands. + + - Function: mp_size_t mpn_divrem (mp_limb_t * R1P, mp_size_t XSIZE, + mp_limb_t * RS2P, mp_size_t RS2SIZE, const mp_limb_t * S3P, + mp_size_t S3SIZE) + Divide {RS2P, RS2SIZE} by {S3P, S3SIZE}, and write the quotient at + R1P, with the exception of the most significant limb, which is + returned. The remainder replaces the dividend at RS2P. + + In addition to an integer quotient, XSIZE fraction limbs are + developed, and stored after the integral limbs. For most usages, + XSIZE will be zero. + + It is required that RS2SIZE is greater than or equal to S3SIZE. + It is required that the most significant bit of the divisor is set. + + If the quotient is not needed, pass RS2P + S3SIZE as R1P. Aside + from that special case, no overlap between arguments is permitted. + + Return the most significant limb of the quotient, either 0 or 1. + + The area at R1P needs to be RS2SIZE - S3SIZE + XSIZE limbs large. + + - Function: mp_limb_t mpn_divrem_1 (mp_limb_t * R1P, mp_size_t XSIZE, + mp_limb_t * S2P, mp_size_t S2SIZE, mp_limb_t S3LIMB) + Divide {S2P, S2SIZE} by S3LIMB, and write the quotient at R1P. + Return the remainder. + + In addition to an integer quotient, XSIZE fraction limbs are + developed, and stored after the integral limbs. For most usages, + XSIZE will be zero. + + The areas at R1P and S2P have to be identical or completely + separate, not partially overlapping. + + - Function: mp_size_t mpn_divmod (mp_limb_t * R1P, mp_limb_t * RS2P, + mp_size_t RS2SIZE, const mp_limb_t * S3P, mp_size_t S3SIZE) + *This interface is obsolete. It will disappear from future + releases. Use `mpn_divrem' in its stead.* + + - Function: mp_limb_t mpn_divmod_1 (mp_limb_t * R1P, mp_limb_t * S2P, + mp_size_t S2SIZE, mp_limb_t S3LIMB) + *This interface is obsolete. It will disappear from future + releases. Use `mpn_divrem_1' in its stead.* + + - Function: mp_limb_t mpn_mod_1 (mp_limb_t * S1P, mp_size_t S1SIZE, + mp_limb_t S2LIMB) + Divide {S1P, S1SIZE} by S2LIMB, and return the remainder. + + - Function: mp_limb_t mpn_preinv_mod_1 (mp_limb_t * S1P, mp_size_t + S1SIZE, mp_limb_t S2LIMB, mp_limb_t S3LIMB) + *This interface is obsolete. It will disappear from future + releases. Use `mpn_mod_1' in its stead.* + + - Function: mp_limb_t mpn_bdivmod (mp_limb_t * DEST_PTR, mp_limb_t * + S1P, mp_size_t S1SIZE, const mp_limb_t * S2P, mp_size_t + S2SIZE, unsigned long int D) + The function puts the low [D/BITS_PER_MP_LIMB] limbs of Q = {S1P, + S1SIZE}/{S2P, S2SIZE} mod 2^D at DEST_PTR, and returns the high D + mod BITS_PER_MP_LIMB bits of Q. + + {S1P, S1SIZE} - Q * {S2P, S2SIZE} mod 2^(S1SIZE*BITS_PER_MP_LIMB) + is placed at S1P. Since the low [D/BITS_PER_MP_LIMB] limbs of + this difference are zero, it is possible to overwrite the low + limbs at S1P with this difference, provided DEST_PTR <= S1P. + + This function requires that S1SIZE * BITS_PER_MP_LIMB >= D, and + that {S2P, S2SIZE} is odd. + + *This interface is preliminary. It might change incompatibly in + future revisions.* + + - Function: mp_limb_t mpn_lshift (mp_limb_t * DEST_PTR, const + mp_limb_t * SRC_PTR, mp_size_t SRC_SIZE, unsigned long int + COUNT) + Shift {SRC_PTR, SRC_SIZE} COUNT bits to the left, and write the + SRC_SIZE least significant limbs of the result to DEST_PTR. COUNT + might be in the range 1 to n - 1, on an n-bit machine. The bits + shifted out to the left are returned. + + Overlapping of the destination space and the source space is + allowed in this function, provided DEST_PTR >= SRC_PTR. + + This function is written in assembly for most targets. + + - Function: mp_limp_t mpn_rshift (mp_limb_t * DEST_PTR, const + mp_limb_t * SRC_PTR, mp_size_t SRC_SIZE, unsigned long int + COUNT) + Shift {SRC_PTR, SRC_SIZE} COUNT bits to the right, and write the + SRC_SIZE most significant limbs of the result to DEST_PTR. COUNT + might be in the range 1 to n - 1, on an n-bit machine. The bits + shifted out to the right are returned. + + Overlapping of the destination space and the source space is + allowed in this function, provided DEST_PTR <= SRC_PTR. + + This function is written in assembly for most targets. + + - Function: int mpn_cmp (const mp_limb_t * SRC1_PTR, const mp_limb_t * + SRC2_PTR, mp_size_t SIZE) + Compare {SRC1_PTR, SIZE} and {SRC2_PTR, SIZE} and return a + positive value if src1 > src2, 0 of they are equal, and a negative + value if src1 < src2. + + - Function: mp_size_t mpn_gcd (mp_limb_t * DEST_PTR, mp_limb_t * + SRC1_PTR, mp_size_t SRC1_SIZE, mp_limb_t * SRC2_PTR, + mp_size_t SRC2_SIZE) + Puts at DEST_PTR the greatest common divisor of {SRC1_PTR, + SRC1_SIZE} and {SRC2_PTR, SRC2_SIZE}; both source operands are + destroyed by the operation. The size in limbs of the greatest + common divisor is returned. + + {SRC1_PTR, SRC1_SIZE} must be odd, and {SRC2_PTR, SRC2_SIZE} must + have at least as many bits as {SRC1_PTR, SRC1_SIZE}. + + *This interface is preliminary. It might change incompatibly in + future revisions.* + + - Function: mp_limb_t mpn_gcd_1 (const mp_limb_t * SRC1_PTR, mp_size_t + SRC1_SIZE, mp_limb_t SRC2_LIMB) + Return the greatest common divisor of {SRC1_PTR, SRC1_SIZE} and + SRC2_LIMB, where SRC2_LIMB (as well as SRC1_SIZE) must be + different from 0. + + - Function: mp_size_t mpn_gcdext (mp_limb_t * R1P, mp_limb_t * R2P, + mp_limb_t * S1P, mp_size_t S1SIZE, mp_limb_t * S2P, mp_size_t + S2SIZE) + Puts at R1P the greatest common divisor of {S1P, S1SIZE} and {S2P, + S2SIZE}. The first cofactor is written at R2P. Both source + operands are destroyed by the operation. The size in limbs of the + greatest common divisor is returned. + + *This interface is preliminary. It might change incompatibly in + future revisions.* + + - Function: mp_size_t mpn_sqrtrem (mp_limb_t * R1P, mp_limb_t * R2P, + const mp_limb_t * SP, mp_size_t SIZE) + Compute the square root of {SP, SIZE} and put the result at R1P. + Write the remainder at R2P, unless R2P is NULL. + + Return the size of the remainder, whether R2P was NULL or non-NULL. + Iff the operand was a perfect square, the return value will be 0. + + The areas at R1P and SP have to be distinct. The areas at R2P and + SP have to be identical or completely separate, not partially + overlapping. + + The area at R1P needs to have space for ceil(SIZE/2) limbs. The + area at R2P needs to be SIZE limbs large. + + *This interface is preliminary. It might change incompatibly in + future revisions.* + + - Function: mp_size_t mpn_get_str (unsigned char *STR, int BASE, + mp_limb_t * S1P, mp_size_t S1SIZE) + Convert {S1P, S1SIZE} to a raw unsigned char array in base BASE. + The string is not in ASCII; to convert it to printable format, add + the ASCII codes for `0' or `A', depending on the base and range. + There may be leading zeros in the string. + + The area at S1P is clobbered. + + Return the number of characters in STR. + + The area at STR has to have space for the largest possible number + represented by a S1SIZE long limb array, plus one extra character. + + - Function: mp_size_t mpn_set_str (mp_limb_t * R1P, const char *STR, + size_t strsize, int BASE) + Convert the raw unsigned char array at STR of length STRSIZE to a + limb array {S1P, S1SIZE}. The base of STR is BASE. + + Return the number of limbs stored in R1P. + + - Function: unsigned long int mpn_scan0 (const mp_limb_t * S1P, + unsigned long int BIT) + Scan S1P from bit position BIT for the next clear bit. + + It is required that there be a clear bit within the area at S1P at + or beyond bit position BIT, so that the function has something to + return. + + *This interface is preliminary. It might change incompatibly in + future revisions.* + + - Function: unsigned long int mpn_scan1 (const mp_limb_t * S1P, + unsigned long int BIT) + Scan S1P from bit position BIT for the next set bit. + + It is required that there be a set bit within the area at S1P at or + beyond bit position BIT, so that the function has something to + return. + + *This interface is preliminary. It might change incompatibly in + future revisions.* + + - Function: void mpn_random2 (mp_limb_t * R1P, mp_size_t R1SIZE) + Generate a random number of length R1SIZE with long strings of + zeros and ones in the binary representation, and store it at R1P. + + The generated random numbers are intended for testing the + correctness of the implementation of the `mpn' routines. + + - Function: unsigned long int mpn_popcount (const mp_limb_t * S1P, + unsigned long int SIZE) + Count the number of set bits in {S1P, SIZE}. + + - Function: unsigned long int mpn_hamdist (const mp_limb_t * S1P, + const mp_limb_t * S2P, unsigned long int SIZE) + Compute the hamming distance between {S1P, SIZE} and {S2P, SIZE}. + + - Function: int mpn_perfect_square_p (const mp_limb_t * S1P, mp_size_t + SIZE) + Return non-zero iff {S1P, SIZE} is a perfect square. + + +File: gmp.info, Node: BSD Compatible Functions, Next: Custom Allocation, Prev: Low-level Functions, Up: Top + +Berkeley MP Compatible Functions +******************************** + + These functions are intended to be fully compatible with the +Berkeley MP library which is available on many BSD derived U*ix systems. + + The original Berkeley MP library has a usage restriction: you cannot +use the same variable as both source and destination in a single +function call. The compatible functions in GNU MP do not share this +restriction--inputs and outputs may overlap. + + It is not recommended that new programs are written using these +functions. Apart from the incomplete set of functions, the interface +for initializing `MINT' objects is more error prone, and the `pow' +function collides with `pow' in `libm.a'. + + Include the header `mp.h' to get the definition of the necessary +types and functions. If you are on a BSD derived system, make sure to +include GNU `mp.h' if you are going to link the GNU `libmp.a' to you +program. This means that you probably need to give the -I<dir> option +to the compiler, where <dir> is the directory where you have GNU `mp.h'. + + - Function: MINT * itom (signed short int INITIAL_VALUE) + Allocate an integer consisting of a `MINT' object and dynamic limb + space. Initialize the integer to INITIAL_VALUE. Return a pointer + to the `MINT' object. + + - Function: MINT * xtom (char *INITIAL_VALUE) + Allocate an integer consisting of a `MINT' object and dynamic limb + space. Initialize the integer from INITIAL_VALUE, a hexadecimal, + '\0'-terminate C string. Return a pointer to the `MINT' object. + + - Function: void move (MINT *SRC, MINT *DEST) + Set DEST to SRC by copying. Both variables must be previously + initialized. + + - Function: void madd (MINT *SRC_1, MINT *SRC_2, MINT *DESTINATION) + Add SRC_1 and SRC_2 and put the sum in DESTINATION. + + - Function: void msub (MINT *SRC_1, MINT *SRC_2, MINT *DESTINATION) + Subtract SRC_2 from SRC_1 and put the difference in DESTINATION. + + - Function: void mult (MINT *SRC_1, MINT *SRC_2, MINT *DESTINATION) + Multiply SRC_1 and SRC_2 and put the product in DESTINATION. + + - Function: void mdiv (MINT *DIVIDEND, MINT *DIVISOR, MINT *QUOTIENT, + MINT *REMAINDER) + - Function: void sdiv (MINT *DIVIDEND, signed short int DIVISOR, MINT + *QUOTIENT, signed short int *REMAINDER) + Set QUOTIENT to DIVIDEND/DIVISOR, and REMAINDER to DIVIDEND mod + DIVISOR. The quotient is rounded towards zero; the remainder has + the same sign as the dividend unless it is zero. + + Some implementations of these functions work differently--or not + at all--for negative arguments. + + - Function: void msqrt (MINT *OPERAND, MINT *ROOT, MINT *REMAINDER) + Set ROOT to the truncated integer part of the square root of + OPERAND. Set REMAINDER to OPERAND-ROOT*ROOT, (i.e., zero if + OPERAND is a perfect square). + + If ROOT and REMAINDER are the same variable, the results are + undefined. + + - Function: void pow (MINT *BASE, MINT *EXP, MINT *MOD, MINT *DEST) + Set DEST to (BASE raised to EXP) modulo MOD. + + - Function: void rpow (MINT *BASE, signed short int EXP, MINT *DEST) + Set DEST to BASE raised to EXP. + + - Function: void gcd (MINT *OPERAND1, MINT *OPERAND2, MINT *RES) + Set RES to the greatest common divisor of OPERAND1 and OPERAND2. + + - Function: int mcmp (MINT *OPERAND1, MINT *OPERAND2) + Compare OPERAND1 and OPERAND2. Return a positive value if + OPERAND1 > OPERAND2, zero if OPERAND1 = OPERAND2, and a negative + value if OPERAND1 < OPERAND2. + + - Function: void min (MINT *DEST) + Input a decimal string from `stdin', and put the read integer in + DEST. SPC and TAB are allowed in the number string, and are + ignored. + + - Function: void mout (MINT *SRC) + Output SRC to `stdout', as a decimal string. Also output a + newline. + + - Function: char * mtox (MINT *OPERAND) + Convert OPERAND to a hexadecimal string, and return a pointer to + the string. The returned string is allocated using the default + memory allocation function, `malloc' by default. + + - Function: void mfree (MINT *OPERAND) + De-allocate, the space used by OPERAND. *This function should + only be passed a value returned by `itom' or `xtom'.* + + +File: gmp.info, Node: Custom Allocation, Next: Contributors, Prev: BSD Compatible Functions, Up: Top + +Custom Allocation +***************** + + By default, the MP functions use `malloc', `realloc', and `free' for +memory allocation. If `malloc' or `realloc' fails, the MP library +terminates execution after printing a fatal error message to standard +error. + + For some applications, you may wish to allocate memory in other +ways, or you may not want to have a fatal error when there is no more +memory available. To accomplish this, you can specify alternative +memory allocation functions. + + - Function: void mp_set_memory_functions ( + void *(*ALLOC_FUNC_PTR) (size_t), + void *(*REALLOC_FUNC_PTR) (void *, size_t, size_t), + void (*FREE_FUNC_PTR) (void *, size_t)) + Replace the current allocation functions from the arguments. If + an argument is NULL, the corresponding default function is + retained. + + *Make sure to call this function in such a way that there are no + active MP objects that were allocated using the previously active + allocation function! Usually, that means that you have to call + this function before any other MP function.* + + The functions you supply should fit the following declarations: + + - Function: void * allocate_function (size_t ALLOC_SIZE) + This function should return a pointer to newly allocated space + with at least ALLOC_SIZE storage units. + + - Function: void * reallocate_function (void *PTR, size_t OLD_SIZE, + size_t NEW_SIZE) + This function should return a pointer to newly allocated space of + at least NEW_SIZE storage units, after copying at least the first + OLD_SIZE storage units from PTR. It should also de-allocate the + space at PTR. + + You can assume that the space at PTR was formerly returned from + `allocate_function' or `reallocate_function', for a request for + OLD_SIZE storage units. + + - Function: void deallocate_function (void *PTR, size_t SIZE) + De-allocate the space pointed to by PTR. + + You can assume that the space at PTR was formerly returned from + `allocate_function' or `reallocate_function', for a request for + SIZE storage units. + + (A "storage unit" is the unit in which the `sizeof' operator returns +the size of an object, normally an 8 bit byte.) + + +File: gmp.info, Node: Contributors, Next: References, Prev: Custom Allocation, Up: Top + +Contributors +************ + + I would like to thank Gunnar Sjoedin and Hans Riesel for their help +with mathematical problems, Richard Stallman for his help with design +issues and for revising the first version of this manual, Brian Beuning +and Doug Lea for their testing of early versions of the library. + + John Amanatides of York University in Canada contributed the function +`mpz_probab_prime_p'. + + Paul Zimmermann of Inria sparked the development of GMP 2, with his +comparisons between bignum packages. + + Ken Weber (Kent State University, Universidade Federal do Rio Grande +do Sul) contributed `mpz_gcd', `mpz_divexact', `mpn_gcd', and +`mpn_bdivmod', partially supported by CNPq (Brazil) grant 301314194-2. + + Per Bothner of Cygnus Support helped to set up MP to use Cygnus' +configure. He has also made valuable suggestions and tested numerous +intermediary releases. + + Joachim Hollman was involved in the design of the `mpf' interface, +and in the `mpz' design revisions for version 2. + + Bennet Yee contributed the functions `mpz_jacobi' and `mpz_legendre'. + + Andreas Schwab contributed the files `mpn/m68k/lshift.S' and +`mpn/m68k/rshift.S'. + + The development of floating point functions of GNU MP 2, were +supported in part by the ESPRIT-BRA (Basic Research Activities) 6846 +project POSSO (POlynomial System SOlving). + + GNU MP 2 was finished and released by TMG Datakonsult, +Sodermannagatan 5, 116 23 STOCKHOLM, SWEDEN, in cooperation with the +IDA Center for Computing Sciences, USA. + + +File: gmp.info, Node: References, Prev: Contributors, Up: Top + +References +********** + + * Donald E. Knuth, "The Art of Computer Programming", vol 2, + "Seminumerical Algorithms", 2nd edition, Addison-Wesley, 1981. + + * John D. Lipson, "Elements of Algebra and Algebraic Computing", The + Benjamin Cummings Publishing Company Inc, 1981. + + * Richard M. Stallman, "Using and Porting GCC", Free Software + Foundation, 1995. + + * Peter L. Montgomery, "Modular Multiplication Without Trial + Division", in Mathematics of Computation, volume 44, number 170, + April 1985. + + * Torbjorn Granlund and Peter L. Montgomery, "Division by Invariant + Integers using Multiplication", in Proceedings of the SIGPLAN + PLDI'94 Conference, June 1994. + + * Tudor Jebelean, "An algorithm for exact division", Journal of + Symbolic Computation, v. 15, 1993, pp. 169-180. + + * Kenneth Weber, "The accelerated integer GCD algorithm", ACM + Transactions on Mathematical Software, v. 21 (March), 1995, pp. + 111-122. + + +File: gmp.info, Node: Concept Index, Up: Top + +Concept Index +************* + +* Menu: + +* gmp.h: MP Basics. +* mp.h: BSD Compatible Functions. +* Arithmetic functions <1>: Float Arithmetic. +* Arithmetic functions: Integer Arithmetic. +* Bit manipulation functions: Integer Logic and Bit Fiddling. +* BSD MP compatible functions: BSD Compatible Functions. +* Comparison functions: Float Comparison. +* Conditions for copying GNU MP: Copying. +* Conversion functions <1>: Converting Integers. +* Conversion functions: Converting Floats. +* Copying conditions: Copying. +* Float arithmetic functions: Float Arithmetic. +* Float assignment functions: Assigning Floats. +* Float comparisons functions: Float Comparison. +* Float functions: Floating-point Functions. +* Float input and output functions: I/O of Floats. +* Floating-point functions: Floating-point Functions. +* Floating-point number: MP Basics. +* I/O functions <1>: I/O of Floats. +* I/O functions: I/O of Integers. +* Initialization and assignment functions <1>: Simultaneous Float Init & Assign. +* Initialization and assignment functions: Simultaneous Integer Init & Assign. +* Input functions <1>: I/O of Integers. +* Input functions: I/O of Floats. +* Installation: Installing MP. +* Integer: MP Basics. +* Integer arithmetic functions: Integer Arithmetic. +* Integer assignment functions: Assigning Integers. +* Integer conversion functions: Converting Integers. +* Integer functions: Integer Functions. +* Integer input and output functions: I/O of Integers. +* Limb: MP Basics. +* Logical functions: Integer Logic and Bit Fiddling. +* Low-level functions: Low-level Functions. +* Miscellaneous float functions: Miscellaneous Float Functions. +* Miscellaneous integer functions: Miscellaneous Integer Functions. +* Output functions <1>: I/O of Floats. +* Output functions: I/O of Integers. +* Rational number: MP Basics. +* Rational number functions: Rational Number Functions. +* Reporting bugs: Reporting Bugs. +* User-defined precision: Floating-point Functions. + diff --git a/contrib/libgmp/gmp.info-3 b/contrib/libgmp/gmp.info-3 new file mode 100644 index 0000000..a3020a7 --- /dev/null +++ b/contrib/libgmp/gmp.info-3 @@ -0,0 +1,259 @@ +This is Info file gmp.info, produced by Makeinfo-1.64 from the input +file gmp.texi. + +START-INFO-DIR-ENTRY +* gmp: (gmp.info). GNU Multiple Precision Arithmetic Library. +END-INFO-DIR-ENTRY + + This file documents GNU MP, a library for arbitrary-precision +arithmetic. + + Copyright (C) 1991, 1993, 1994, 1995, 1996 Free Software Foundation, +Inc. + + Permission is granted to make and distribute verbatim copies of this +manual provided the copyright notice and this permission notice are +preserved on all copies. + + Permission is granted to copy and distribute modified versions of +this manual under the conditions for verbatim copying, provided that +the entire resulting derived work is distributed under the terms of a +permission notice identical to this one. + + Permission is granted to copy and distribute translations of this +manual into another language, under the above conditions for modified +versions, except that this permission notice may be stated in a +translation approved by the Foundation. + + +File: gmp.info, Node: Function Index, Up: Top + +Function and Type Index +*********************** + +* Menu: + +* mp_limb_t: MP Basics. +* mpf_t: MP Basics. +* mpq_t: MP Basics. +* mpz_t: MP Basics. +* __GNU_MP_VERSION: MP Basics. +* __GNU_MP_VERSION_MINOR: MP Basics. +* _mpz_realloc: Initializing Integers. +* allocate_function: Custom Allocation. +* deallocate_function: Custom Allocation. +* gcd: BSD Compatible Functions. +* itom: BSD Compatible Functions. +* madd: BSD Compatible Functions. +* mcmp: BSD Compatible Functions. +* mdiv: BSD Compatible Functions. +* mfree: BSD Compatible Functions. +* min: BSD Compatible Functions. +* mout: BSD Compatible Functions. +* move: BSD Compatible Functions. +* mp_set_memory_functions: Custom Allocation. +* mpf_abs: Float Arithmetic. +* mpf_add: Float Arithmetic. +* mpf_add_ui: Float Arithmetic. +* mpf_clear: Initializing Floats. +* mpf_cmp: Float Comparison. +* mpf_cmp_si: Float Comparison. +* mpf_cmp_ui: Float Comparison. +* mpf_div: Float Arithmetic. +* mpf_div_2exp: Float Arithmetic. +* mpf_div_ui: Float Arithmetic. +* mpf_eq: Float Comparison. +* mpf_get_d: Converting Floats. +* mpf_get_prec: Initializing Floats. +* mpf_get_str: Converting Floats. +* mpf_init: Initializing Floats. +* mpf_init2: Initializing Floats. +* mpf_init_set: Simultaneous Float Init & Assign. +* mpf_init_set_d: Simultaneous Float Init & Assign. +* mpf_init_set_si: Simultaneous Float Init & Assign. +* mpf_init_set_str: Simultaneous Float Init & Assign. +* mpf_init_set_ui: Simultaneous Float Init & Assign. +* mpf_inp_str: I/O of Floats. +* mpf_mul: Float Arithmetic. +* mpf_mul_2exp: Float Arithmetic. +* mpf_mul_ui: Float Arithmetic. +* mpf_neg: Float Arithmetic. +* mpf_out_str: I/O of Floats. +* mpf_random2: Miscellaneous Float Functions. +* mpf_reldiff: Float Comparison. +* mpf_set: Assigning Floats. +* mpf_set_d: Assigning Floats. +* mpf_set_default_prec: Initializing Floats. +* mpf_set_prec: Initializing Floats. +* mpf_set_prec_raw: Initializing Floats. +* mpf_set_q: Assigning Floats. +* mpf_set_si: Assigning Floats. +* mpf_set_str: Assigning Floats. +* mpf_set_ui: Assigning Floats. +* mpf_set_z: Assigning Floats. +* mpf_sgn: Float Comparison. +* mpf_sqrt: Float Arithmetic. +* mpf_sqrt_ui: Float Arithmetic. +* mpf_sub: Float Arithmetic. +* mpf_sub_ui: Float Arithmetic. +* mpf_ui_div: Float Arithmetic. +* mpf_ui_sub: Float Arithmetic. +* mpn_add: Low-level Functions. +* mpn_add_1: Low-level Functions. +* mpn_add_n: Low-level Functions. +* mpn_addmul_1: Low-level Functions. +* mpn_bdivmod: Low-level Functions. +* mpn_cmp: Low-level Functions. +* mpn_divmod: Low-level Functions. +* mpn_divmod_1: Low-level Functions. +* mpn_divrem: Low-level Functions. +* mpn_divrem_1: Low-level Functions. +* mpn_gcd: Low-level Functions. +* mpn_gcd_1: Low-level Functions. +* mpn_gcdext: Low-level Functions. +* mpn_get_str: Low-level Functions. +* mpn_hamdist: Low-level Functions. +* mpn_lshift: Low-level Functions. +* mpn_mod_1: Low-level Functions. +* mpn_mul: Low-level Functions. +* mpn_mul_1: Low-level Functions. +* mpn_mul_n: Low-level Functions. +* mpn_perfect_square_p: Low-level Functions. +* mpn_popcount: Low-level Functions. +* mpn_preinv_mod_1: Low-level Functions. +* mpn_random2: Low-level Functions. +* mpn_rshift: Low-level Functions. +* mpn_scan0: Low-level Functions. +* mpn_scan1: Low-level Functions. +* mpn_set_str: Low-level Functions. +* mpn_sqrtrem: Low-level Functions. +* mpn_sub: Low-level Functions. +* mpn_sub_1: Low-level Functions. +* mpn_sub_n: Low-level Functions. +* mpn_submul_1: Low-level Functions. +* mpq_add: Assigning Rationals. +* mpq_canonicalize: Rational Number Functions. +* mpq_clear: Initializing Rationals. +* mpq_cmp: Comparing Rationals. +* mpq_cmp_ui: Comparing Rationals. +* mpq_denref: Applying Integer Functions. +* mpq_div: Assigning Rationals. +* mpq_equal: Comparing Rationals. +* mpq_get_d: Miscellaneous Rational Functions. +* mpq_get_den: Miscellaneous Rational Functions. +* mpq_get_num: Miscellaneous Rational Functions. +* mpq_init: Initializing Rationals. +* mpq_inv: Assigning Rationals. +* mpq_mul: Assigning Rationals. +* mpq_neg: Assigning Rationals. +* mpq_numref: Applying Integer Functions. +* mpq_set: Initializing Rationals. +* mpq_set_den: Miscellaneous Rational Functions. +* mpq_set_num: Miscellaneous Rational Functions. +* mpq_set_si: Initializing Rationals. +* mpq_set_ui: Initializing Rationals. +* mpq_set_z: Initializing Rationals. +* mpq_sgn: Comparing Rationals. +* mpq_sub: Assigning Rationals. +* mpz_abs: Integer Arithmetic. +* mpz_add: Integer Arithmetic. +* mpz_add_ui: Integer Arithmetic. +* mpz_and: Integer Logic and Bit Fiddling. +* mpz_array_init: Initializing Integers. +* mpz_cdiv_q: Integer Arithmetic. +* mpz_cdiv_q_ui: Integer Arithmetic. +* mpz_cdiv_qr: Integer Arithmetic. +* mpz_cdiv_qr_ui: Integer Arithmetic. +* mpz_cdiv_r: Integer Arithmetic. +* mpz_cdiv_r_ui: Integer Arithmetic. +* mpz_cdiv_ui: Integer Arithmetic. +* mpz_clear: Initializing Integers. +* mpz_clrbit: Integer Logic and Bit Fiddling. +* mpz_cmp: Comparison Functions. +* mpz_cmp_si: Comparison Functions. +* mpz_cmp_ui: Comparison Functions. +* mpz_com: Integer Logic and Bit Fiddling. +* mpz_divexact: Integer Arithmetic. +* mpz_fac_ui: Integer Arithmetic. +* mpz_fdiv_q: Integer Arithmetic. +* mpz_fdiv_q_2exp: Integer Arithmetic. +* mpz_fdiv_q_ui: Integer Arithmetic. +* mpz_fdiv_qr: Integer Arithmetic. +* mpz_fdiv_qr_ui: Integer Arithmetic. +* mpz_fdiv_r: Integer Arithmetic. +* mpz_fdiv_r_2exp: Integer Arithmetic. +* mpz_fdiv_r_ui: Integer Arithmetic. +* mpz_fdiv_ui: Integer Arithmetic. +* mpz_gcd: Integer Arithmetic. +* mpz_gcd_ui: Integer Arithmetic. +* mpz_gcdext: Integer Arithmetic. +* mpz_get_d: Converting Integers. +* mpz_get_si: Converting Integers. +* mpz_get_str: Converting Integers. +* mpz_get_ui: Converting Integers. +* mpz_hamdist: Integer Logic and Bit Fiddling. +* mpz_init: Initializing Integers. +* mpz_init_set: Simultaneous Integer Init & Assign. +* mpz_init_set_d: Simultaneous Integer Init & Assign. +* mpz_init_set_si: Simultaneous Integer Init & Assign. +* mpz_init_set_str: Simultaneous Integer Init & Assign. +* mpz_init_set_ui: Simultaneous Integer Init & Assign. +* mpz_inp_raw: I/O of Integers. +* mpz_inp_str: I/O of Integers. +* mpz_invert: Integer Arithmetic. +* mpz_ior: Integer Logic and Bit Fiddling. +* mpz_jacobi: Integer Arithmetic. +* mpz_legendre: Integer Arithmetic. +* mpz_mod: Integer Arithmetic. +* mpz_mod_ui: Integer Arithmetic. +* mpz_mul: Integer Arithmetic. +* mpz_mul_2exp: Integer Arithmetic. +* mpz_mul_ui: Integer Arithmetic. +* mpz_neg: Integer Arithmetic. +* mpz_out_raw: I/O of Integers. +* mpz_out_str: I/O of Integers. +* mpz_perfect_square_p: Integer Arithmetic. +* mpz_popcount: Integer Logic and Bit Fiddling. +* mpz_pow_ui: Integer Arithmetic. +* mpz_powm: Integer Arithmetic. +* mpz_powm_ui: Integer Arithmetic. +* mpz_probab_prime_p: Integer Arithmetic. +* mpz_random: Miscellaneous Integer Functions. +* mpz_random2: Miscellaneous Integer Functions. +* mpz_scan0: Integer Logic and Bit Fiddling. +* mpz_scan1: Integer Logic and Bit Fiddling. +* mpz_set: Assigning Integers. +* mpz_set_d: Assigning Integers. +* mpz_set_f: Assigning Integers. +* mpz_set_q: Assigning Integers. +* mpz_set_si: Assigning Integers. +* mpz_set_str: Assigning Integers. +* mpz_set_ui: Assigning Integers. +* mpz_setbit: Integer Logic and Bit Fiddling. +* mpz_sgn: Comparison Functions. +* mpz_size: Miscellaneous Integer Functions. +* mpz_sizeinbase: Miscellaneous Integer Functions. +* mpz_sqrt: Integer Arithmetic. +* mpz_sqrtrem: Integer Arithmetic. +* mpz_sub: Integer Arithmetic. +* mpz_sub_ui: Integer Arithmetic. +* mpz_tdiv_q: Integer Arithmetic. +* mpz_tdiv_q_2exp: Integer Arithmetic. +* mpz_tdiv_q_ui: Integer Arithmetic. +* mpz_tdiv_qr: Integer Arithmetic. +* mpz_tdiv_qr_ui: Integer Arithmetic. +* mpz_tdiv_r: Integer Arithmetic. +* mpz_tdiv_r_2exp: Integer Arithmetic. +* mpz_tdiv_r_ui: Integer Arithmetic. +* mpz_ui_pow_ui: Integer Arithmetic. +* msqrt: BSD Compatible Functions. +* msub: BSD Compatible Functions. +* mtox: BSD Compatible Functions. +* mult: BSD Compatible Functions. +* pow: BSD Compatible Functions. +* reallocate_function: Custom Allocation. +* rpow: BSD Compatible Functions. +* sdiv: BSD Compatible Functions. +* xtom: BSD Compatible Functions. + + diff --git a/contrib/libgmp/gmp.texi b/contrib/libgmp/gmp.texi new file mode 100644 index 0000000..7e6884e --- /dev/null +++ b/contrib/libgmp/gmp.texi @@ -0,0 +1,2697 @@ +\input texinfo @c -*-texinfo-*- +@c %**start of header +@setfilename gmp.info +@settitle GNU MP 2.0.2 +@synindex tp fn +@iftex +@afourpaper +@end iftex +@comment %**end of header + +@ifinfo +@format +START-INFO-DIR-ENTRY +* gmp: (gmp.info). GNU Multiple Precision Arithmetic Library. +END-INFO-DIR-ENTRY +@end format +@end ifinfo + +@c smallbook + +@iftex +@finalout +@end iftex + +@c Note: the edition number is listed in *three* places; please update +@c all three. Also, update the month and year where appropriate. + +@c ==> Update edition number for settitle and subtitle, and in the +@c ==> following paragraph; update date, too. + + +@ifinfo +This file documents GNU MP, a library for arbitrary-precision arithmetic. + +Copyright (C) 1991, 1993, 1994, 1995, 1996 Free Software Foundation, Inc. + +Permission is granted to make and distribute verbatim copies of +this manual provided the copyright notice and this permission notice +are preserved on all copies. + +@ignore +Permission is granted to process this file through TeX and print the +results, provided the printed document carries copying permission +notice identical to this one except for the removal of this paragraph +(this paragraph not being relevant to the printed manual). + +@end ignore +Permission is granted to copy and distribute modified versions of this +manual under the conditions for verbatim copying, provided that the entire +resulting derived work is distributed under the terms of a permission +notice identical to this one. + +Permission is granted to copy and distribute translations of this manual +into another language, under the above conditions for modified versions, +except that this permission notice may be stated in a translation approved +by the Foundation. +@end ifinfo + +@setchapternewpage on +@titlepage +@c use the new format for titles + +@title GNU MP +@subtitle The GNU Multiple Precision Arithmetic Library +@subtitle Edition 2.0.2 +@subtitle June 1996 + +@author by Torbj@"orn Granlund, TMG Datakonsult + +@c Include the Distribution inside the titlepage so +@c that headings are turned off. + +@tex +\global\parindent=0pt +\global\parskip=8pt +\global\baselineskip=13pt +@end tex + +@page +@vskip 0pt plus 1filll +Copyright @copyright{} 1991, 1993, 1994, 1995, 1996 Free Software Foundation, Inc. + +@sp 2 + +Published by the Free Software Foundation @* +59 Temple Place - Suite 330 @* +Boston, MA 02111-1307, USA @* + +Permission is granted to make and distribute verbatim copies of +this manual provided the copyright notice and this permission notice +are preserved on all copies. + +Permission is granted to copy and distribute modified versions of this +manual under the conditions for verbatim copying, provided that the entire +resulting derived work is distributed under the terms of a permission +notice identical to this one. + +Permission is granted to copy and distribute translations of this manual +into another language, under the above conditions for modified versions, +except that this permission notice may be stated in a translation approved +by the Foundation. +@end titlepage +@headings double + +@ifinfo +@node Top, Copying, (dir), (dir) + +@top GNU MP + +This manual documents how to install and use the GNU multiple precision +arithmetic library, version 2.0.2. + +@end ifinfo + +@menu +* Copying:: GMP Copying Conditions (LGPL). +* Introduction to MP:: Brief introduction to GNU MP. +* Installing MP:: How to configure and compile the MP library. +* MP Basics:: What every MP user should now. +* Reporting Bugs:: How to usefully report bugs. +* Integer Functions:: Functions for arithmetic on signed integers. +* Rational Number Functions:: Functions for arithmetic on rational numbers. +* Floating-point Functions:: Functions for arithmetic on floats. +* Low-level Functions:: Fast functions for natural numbers. +* BSD Compatible Functions:: All functions found in BSD MP. +* Custom Allocation:: How to customize the internal allocation. + +* Contributors:: +* References:: +* Concept Index:: +* Function Index:: +@end menu + +@node Copying, Introduction to MP, Top, Top +@comment node-name, next, previous, up +@unnumbered GNU MP Copying Conditions +@cindex Copying conditions +@cindex Conditions for copying GNU MP + +This library is @dfn{free}; this means that everyone is free to use it and +free to redistribute it on a free basis. The library is not in the public +domain; it is copyrighted and there are restrictions on its distribution, but +these restrictions are designed to permit everything that a good cooperating +citizen would want to do. What is not allowed is to try to prevent others +from further sharing any version of this library that they might get from +you.@refill + +Specifically, we want to make sure that you have the right to give away copies +of the library, that you receive source code or else can get it if you want +it, that you can change this library or use pieces of it in new free programs, +and that you know you can do these things.@refill + +To make sure that everyone has such rights, we have to forbid you to deprive +anyone else of these rights. For example, if you distribute copies of the GNU +MP library, you must give the recipients all the rights that you have. You +must make sure that they, too, receive or can get the source code. And you +must tell them their rights.@refill + +Also, for our own protection, we must make certain that everyone finds out +that there is no warranty for the GNU MP library. If it is modified by +someone else and passed on, we want their recipients to know that what they +have is not what we distributed, so that any problems introduced by others +will not reflect on our reputation.@refill + +The precise conditions of the license for the GNU MP library are found in the +Library General Public License that accompany the source code.@refill + +@node Introduction to MP, Installing MP, Copying, Top +@comment node-name, next, previous, up +@chapter Introduction to GNU MP + + +GNU MP is a portable library written in C for arbitrary precision arithmetic +on integers, rational numbers, and floating-point numbers. It aims to provide +the fastest possible arithmetic for all applications that need higher +precision than is directly supported by the basic C types. + +Many applications use just a few hundred bits of precision; but some +applications may need thousands or even millions of bits. MP is designed to +give good performance for both, by choosing algorithms based on the sizes of +the operands, and by carefully keeping the overhead at a minimum. + +The speed of MP is achieved by using fullwords as the basic arithmetic type, +by using sophisticated algorithms, by including carefully optimized assembly +code for the most common inner loops for many different CPUs, and by a general +emphasis on speed (as opposed to simplicity or elegance). + +There is carefully optimized assembly code for these CPUs: DEC Alpha, Amd +29000, HPPA 1.0 and 1.1, Intel Pentium and generic x86, Intel i960, Motorola +MC68000, MC68020, MC88100, and MC88110, Motorola/IBM PowerPC, National +NS32000, IBM POWER, MIPS R3000, R4000, SPARCv7, SuperSPARC, generic SPARCv8, +and DEC VAX. Some optimizations also for ARM, Clipper, IBM ROMP (RT), and +Pyramid AP/XP. + +This version of MP is released under a more liberal license than previous +versions. It is now permitted to link MP to non-free programs, as long as MP +source code is provided when distributing the non-free program. + + +@section How to use this Manual + +Everyone should read @ref{MP Basics}. If you need to install the library +yourself, you need to read @ref{Installing MP}, too. + +The rest of the manual can be used for later reference, although it is +probably a good idea to glance through it. + + +@node Installing MP, MP Basics, Introduction to MP, Top +@comment node-name, next, previous, up +@chapter Installing MP +@cindex Installation + +To build MP, you first have to configure it for your CPU and operating system. +You need a C compiler, preferably GCC, but any reasonable compiler should +work. And you need a standard Unix @samp{make} program, plus some other +standard Unix utility programs. + +(If you're on an MS-DOS machine, your can build MP using @file{make.bat}. It +requires that djgpp is installed. It does not require configuration, nor is +@samp{make} needed; @file{make.bat} both configures and builds the library.) + +Here are the steps needed to install the library on Unix systems: + +@enumerate +@item +In most cases, @samp{./configure --target=cpu-vendor-os}, should work both for +native and cross-compilation. If you get error messages, your machine might +not be supported. + +If you want to compile in a separate object directory, cd to that directory, +and prefix the configure command with the path to the MP source directory. +Not all @samp{make} programs have the necessary features to support this. In +particular, SunOS and Slowaris @samp{make} have bugs that makes them unable to +build from a separate object directory. Use GNU @samp{make} instead. + +In addition to the standard cpu-vendor-os tuples, MP recognizes sparc8 and +supersparc as valid CPU names. Specifying these CPU names for relevant +systems will improve performance significantly. + +In general, if you want a library that runs as fast as possible, you should +make sure you configure MP for the exact CPU type your system uses. + +If you have @code{gcc} in your @code{PATH}, it will be used by default. To +override this, pass @samp{-with-gcc=no} to @file{configure}. + +@item +@samp{make} + +This will compile MP, and create a library archive file @file{libgmp.a} in the +working directory. + +@item +@samp{make check} + +This will make sure MP was built correctly. If you get error messages, please +report this to @samp{bug-gmp@@prep.ai.mit.edu}. (@xref{Reporting Bugs}, for +information on what to include in useful bug reports.) + +@item +@samp{make install} + +This will copy the file @file{gmp.h} and @file{libgmp.a}, as well as the info +files, to @file{/usr/local} (or if you passed the @samp{--prefix} option to +@file{configure}, to the directory given as argument to @samp{--prefix}). +@end enumerate + +@noindent +If you wish to build and install the BSD MP compatible functions, use +@samp{make libmp.a} and @samp{make install-bsdmp}. + +There are some other useful make targets: + +@itemize @bullet +@item +@samp{doc} + +Create a DVI version of the manual, in @file{gmp.dvi} and a set of info files, +in @file{gmp.info}, @file{gmp.info-1}, @file{gmp.info-2}, etc. + +@item +@samp{ps} + +Create a Postscript version of the manual, in @file{gmp.ps}. + +@item +@samp{html} + +Create a HTML version of the manual, in @file{gmp.html}. + +@item +@samp{clean} + +Delete all object files and archive files, but not the configuration files. + +@item +@samp{distclean} + +Delete all files not included in the distribution. + +@item +@samp{uninstall} + +Delete all files copied by @samp{make install}. +@end itemize + + +@section Known Build Problems + +GCC 2.7.2 (as well as 2.6.3) for the RS/6000 and PowerPC can not be used to +compile MP, due to a bug in GCC. If you want to use GCC for these machines, +you need to apply the patch below to GCC, or use a later version of the +compiler. + +If you are on a Sequent Symmetry, use the GNU assembler instead of the +system's assembler, since the latter has serious bugs. + +The system compiler on NeXT is a massacred and old gcc, even if the compiler +calls itself @file{cc}. This compiler cannot be used to build MP. You need +to get a real gcc, and install that before you compile MP. (NeXT might have +fixed this in newer releases of their system.) + +The system C compiler under SunOS 4 has a bug that makes it miscompile +mpq/get_d.c. This will make @samp{make check} fail. + +Please report other problems to @samp{bug-gmp@@prep.ai.mit.edu}. +@xref{Reporting Bugs}. + + +Patch to apply to GCC 2.6.3 and 2.7.2: + +@example +*** config/rs6000/rs6000.md Sun Feb 11 08:22:11 1996 +--- config/rs6000/rs6000.md.new Sun Feb 18 03:33:37 1996 +*************** +*** 920,926 **** + (set (match_operand:SI 0 "gpc_reg_operand" "=r") + (not:SI (match_dup 1)))] + "" +! "nor. %0,%2,%1" + [(set_attr "type" "compare")]) + + (define_insn "" +--- 920,926 ---- + (set (match_operand:SI 0 "gpc_reg_operand" "=r") + (not:SI (match_dup 1)))] + "" +! "nor. %0,%1,%1" + [(set_attr "type" "compare")]) + + (define_insn "" +@end example + +@node MP Basics, Reporting Bugs, Installing MP, Top +@comment node-name, next, previous, up +@chapter MP Basics + + +@cindex @file{gmp.h} +All declarations needed to use MP are collected in the include file +@file{gmp.h}. It is designed to work with both C and C++ compilers. + + +@section Nomenclature and Types + +@cindex Integer +@tindex @code{mpz_t} +@noindent +In this manual, @dfn{integer} usually means a multiple precision integer, as +defined by the MP library. The C data type for such integers is @code{mpz_t}. +Here are some examples of how to declare such integers: + +@example +mpz_t sum; + +struct foo @{ mpz_t x, y; @}; + +mpz_t vec[20]; +@end example + +@cindex Rational number +@tindex @code{mpq_t} +@noindent +@dfn{Rational number} means a multiple precision fraction. The C data type +for these fractions is @code{mpq_t}. For example: + +@example +mpq_t quotient; +@end example + +@cindex Floating-point number +@tindex @code{mpf_t} +@noindent +@dfn{Floating point number} or @dfn{Float} for short, is an arbitrary precision +mantissa with an limited precision exponent. The C data type for such objects +is @code{mpf_t}. + +@cindex Limb +@tindex @code{mp_limb_t} +@noindent +A @dfn{limb} means the part of a multi-precision number that fits in a single +word. (We chose this word because a limb of the human body is analogous to a +digit, only larger, and containing several digits.) Normally a limb contains +32 or 64 bits. The C data type for a limb is @code{mp_limb_t}. + + +@section Function Classes + +There are six classes of functions in the MP library: + +@enumerate +@item +Functions for signed integer arithmetic, with names beginning with +@code{mpz_}. The associated type is @code{mpz_t}. There are about 100 +functions in this class. + +@item +Functions for rational number arithmetic, with names beginning with +@code{mpq_}. The associated type is @code{mpq_t}. There are about 20 +functions in this class, but the functions in the previous class can be used +for performing arithmetic on the numerator and denominator separately. + +@item +Functions for floating-point arithmetic, with names beginning with +@code{mpf_}. The associated type is @code{mpf_t}. There are about 50 +functions is this class. + +@item +Functions compatible with Berkeley MP, such as @code{itom}, @code{madd}, and +@code{mult}. The associated type is @code{MINT}. + +@item +Fast low-level functions that operate on natural numbers. These are used by +the functions in the preceding groups, and you can also call them directly +from very time-critical user programs. These functions' names begin with +@code{mpn_}. There are about 30 (hard-to-use) functions in this class. + +The associated type is array of @code{mp_limb_t}. + +@item +Miscellaneous functions. Functions for setting up custom allocation. +@end enumerate + + +@section MP Variable Conventions + +As a general rule, all MP functions expect output arguments before input +arguments. This notation is based on an analogy with the assignment operator. +(The BSD MP compatibility functions disobey this rule, having the output +argument(s) last.) + +MP allows you to use the same variable for both input and output in the same +expression. For example, the main function for integer multiplication, +@code{mpz_mul}, can be used like this: @code{mpz_mul (x, x, x)}. This +computes the square of @var{x} and puts the result back in @var{x}. + +Before you can assign to an MP variable, you need to initialize it by calling +one of the special initialization functions. When you're done with a +variable, you need to clear it out, using one of the functions for that +purpose. Which function to use depends on the type of variable. See the +chapters on integer functions, rational number functions, and floating-point +functions for details. + +A variable should only be initialized once, or at least cleared out between +each initialization. After a variable has been initialized, it may be +assigned to any number of times. + +For efficiency reasons, avoid to initialize and clear out a variable in loops. +Instead, initialize it before entering the loop, and clear it out after the +loop has exited. + +You don't need to be concerned about allocating additional space for MP +variables. All functions in MP automatically allocate additional space when a +variable does not already have enough space. They do not, however, reduce the +space when a smaller number is stored in the object. Most of the time, this +policy is best, since it avoids frequent re-allocation. + + +@section Useful Macros and Constants + +@deftypevr {Global Constant} {const int} mp_bits_per_limb +The number of bits per limb. +@end deftypevr + +@defmac __GNU_MP_VERSION +@defmacx __GNU_MP_VERSION_MINOR +The major and minor MP version, respectively, as integers. +@end defmac + +@section Compatibility with Version 1.x + +This version of MP is upward compatible with previous versions of MP, with a +few exceptions. + +@enumerate +@item Integer division functions round the result differently. The old +functions (@code{mpz_div}, @code{mpz_divmod}, @code{mpz_mdiv}, +@code{mpz_mdivmod}, etc) now all use floor rounding (i.e., they round the +quotient to @minus{}infinity). There are a lot of new functions for integer +division, giving the user better control over the rounding. + +@item The function @code{mpz_mod} now compute the true @strong{mod} function. + +@item The functions @code{mpz_powm} and @code{mpz_powm_ui} now use +@strong{mod} for reduction. + +@item The assignment functions for rational numbers do no longer canonicalize +their results. In the case a non-canonical result could arise from an +assignment, the user need to insert an explicit call to +@code{mpq_canonicalize}. This change was made for efficiency. + +@item Output generated by @code{mpz_out_raw} in this release cannot be read +by @code{mpz_inp_raw} in previous releases. This change was made for making +the file format truly portable between machines with different word sizes. + +@item Several @code{mpn} functions have changed. But they were intentionally +undocumented in previous releases. + +@item The functions @code{mpz_cmp_ui}, @code{mpz_cmp_si}, and @code{mpq_cmp_ui} +are now implementated as macros, and thereby sometimes evaluate their +arguments multiple times. + +@item The functions @code{mpz_pow_ui} and @code{mpz_ui_pow_ui} now yield 1 +for 0^0. (In version 1, they yielded 0.) + +@end enumerate + + +@section Getting the Latest Version of MP + +The latest version of the MP library is available by anonymous ftp from +from @samp{prep.ai.mit.edu}. The file name is +@file{/pub/gnu/gmp-M.N.tar.gz}. Many sites around the world mirror +@samp{prep}; please use a mirror site near you. + +@node Reporting Bugs, Integer Functions, MP Basics, Top +@comment node-name, next, previous, up +@chapter Reporting Bugs +@cindex Reporting bugs + +If you think you have found a bug in the MP library, please investigate it and +report it. We have made this library available to you, and it is not to ask +too much from you, to ask you to report the bugs that you find. + +There are a few things you should think about when you put your bug report +together. + +You have to send us a test case that makes it possible for us to reproduce the +bug. Include instructions on how to run the test case. + +You also have to explain what is wrong; if you get a crash, or if the results +printed are incorrect and in that case, in what way. + +It is not uncommon that an observed problem is actually due to a bug in the +compiler used when building MP; the MP code tends to explore interesting +corners in compilers. Therefore, please include compiler version information +in your bug report. This can be extracted using @samp{what `which cc`}, or, +if you're using gcc, @samp{gcc -v}. Also, include the output from @samp{uname +-a}. + +If your bug report is good, we will do our best to help you to get a corrected +version of the library; if the bug report is poor, we won't do anything about +it (aside of chiding you to send better bug reports). + +Send your bug report to: @samp{bug-gmp@@prep.ai.mit.edu}. + +If you think something in this manual is unclear, or downright incorrect, or if +the language needs to be improved, please send a note to the same address. + + +@node Integer Functions, Rational Number Functions, Reporting Bugs, Top +@comment node-name, next, previous, up +@chapter Integer Functions +@cindex Integer functions + +This chapter describes the MP functions for performing integer arithmetic. +These functions start with the prefix @code{mpz_}. + +Arbitrary precision integers are stored in objects of type @code{mpz_t}. + +@menu +* Initializing Integers:: +* Assigning Integers:: +* Simultaneous Integer Init & Assign:: +* Converting Integers:: +* Integer Arithmetic:: +* Comparison Functions:: +* Integer Logic and Bit Fiddling:: +* I/O of Integers:: +* Miscellaneous Integer Functions:: +@end menu + +@node Initializing Integers, Assigning Integers, , Integer Functions +@comment node-name, next, previous, up +@section Initialization and Assignment Functions + +The functions for integer arithmetic assume that all integer objects are +initialized. You do that by calling the function @code{mpz_init}. + +@deftypefun void mpz_init (mpz_t @var{integer}) +Initialize @var{integer} with limb space and set the initial numeric value to +0. Each variable should normally only be initialized once, or at least cleared +out (using @code{mpz_clear}) between each initialization. +@end deftypefun + +Here is an example of using @code{mpz_init}: + +@example +@{ + mpz_t integ; + mpz_init (integ); + @dots{} + mpz_add (integ, @dots{}); + @dots{} + mpz_sub (integ, @dots{}); + + /* Unless the program is about to exit, do ... */ + mpz_clear (integ); +@} +@end example + +@noindent +As you can see, you can store new values any number of times, once an +object is initialized. + +@deftypefun void mpz_clear (mpz_t @var{integer}) +Free the limb space occupied by @var{integer}. Make sure to call this +function for all @code{mpz_t} variables when you are done with them. +@end deftypefun + +@deftypefun {void *} _mpz_realloc (mpz_t @var{integer}, mp_size_t @var{new_alloc}) +Change the limb space allocation to @var{new_alloc} limbs. This function is +not normally called from user code, but it can be used to give memory back to +the heap, or to increase the space of a variable to avoid repeated automatic +re-allocation. +@end deftypefun + +@deftypefun void mpz_array_init (mpz_t @var{integer_array}[], size_t @var{array_size}, mp_size_t @var{fixed_num_bits}) +Allocate @strong{fixed} limb space for all @var{array_size} integers in +@var{integer_array}. The fixed allocation for each integer in the array is +enough to store @var{fixed_num_bits}. If the fixed space will be insufficient +for storing the result of a subsequent calculation, the result is +unpredictable. + +This function is useful for decreasing the working set for some algorithms +that use large integer arrays. + +There is no way to de-allocate the storage allocated by this function. +Don't call @code{mpz_clear}! +@end deftypefun + + +@node Assigning Integers, Simultaneous Integer Init & Assign, Initializing Integers, Integer Functions +@comment node-name, next, previous, up +@subsection Assignment Functions +@cindex Integer assignment functions + +These functions assign new values to already initialized integers +(@pxref{Initializing Integers}). + +@deftypefun void mpz_set (mpz_t @var{rop}, mpz_t @var{op}) +@deftypefunx void mpz_set_ui (mpz_t @var{rop}, unsigned long int @var{op}) +@deftypefunx void mpz_set_si (mpz_t @var{rop}, signed long int @var{op}) +@deftypefunx void mpz_set_d (mpz_t @var{rop}, double @var{op}) +@deftypefunx void mpz_set_q (mpz_t @var{rop}, mpq_t @var{op}) +@deftypefunx void mpz_set_f (mpz_t @var{rop}, mpf_t @var{op}) +Set the value of @var{rop} from @var{op}. +@end deftypefun + +@deftypefun int mpz_set_str (mpz_t @var{rop}, char *@var{str}, int @var{base}) +Set the value of @var{rop} from @var{str}, a '\0'-terminated C string in base +@var{base}. White space is allowed in the string, and is simply ignored. The +base may vary from 2 to 36. If @var{base} is 0, the actual base is determined +from the leading characters: if the first two characters are `0x' or `0X', +hexadecimal is assumed, otherwise if the first character is `0', octal is +assumed, otherwise decimal is assumed. + +This function returns 0 if the entire string up to the '\0' is a valid +number in base @var{base}. Otherwise it returns @minus{}1. +@end deftypefun + + +@node Simultaneous Integer Init & Assign, Converting Integers, Assigning Integers, Integer Functions +@comment node-name, next, previous, up +@subsection Combined Initialization and Assignment Functions +@cindex Initialization and assignment functions + +For convenience, MP provides a parallel series of initialize-and-set functions +which initialize the output and then store the value there. These functions' +names have the form @code{mpz_init_set@dots{}} + +Here is an example of using one: + +@example +@{ + mpz_t pie; + mpz_init_set_str (pie, "3141592653589793238462643383279502884", 10); + @dots{} + mpz_sub (pie, @dots{}); + @dots{} + mpz_clear (pie); +@} +@end example + +@noindent +Once the integer has been initialized by any of the @code{mpz_init_set@dots{}} +functions, it can be used as the source or destination operand for the ordinary +integer functions. Don't use an initialize-and-set function on a variable +already initialized! + +@deftypefun void mpz_init_set (mpz_t @var{rop}, mpz_t @var{op}) +@deftypefunx void mpz_init_set_ui (mpz_t @var{rop}, unsigned long int @var{op}) +@deftypefunx void mpz_init_set_si (mpz_t @var{rop}, signed long int @var{op}) +@deftypefunx void mpz_init_set_d (mpz_t @var{rop}, double @var{op}) +Initialize @var{rop} with limb space and set the initial numeric value from +@var{op}. +@end deftypefun + +@deftypefun int mpz_init_set_str (mpz_t @var{rop}, char *@var{str}, int @var{base}) +Initialize @var{rop} and set its value like @code{mpz_set_str} (see its +documentation above for details). + +If the string is a correct base @var{base} number, the function returns 0; +if an error occurs it returns @minus{}1. @var{rop} is initialized even if +an error occurs. (I.e., you have to call @code{mpz_clear} for it.) +@end deftypefun + + +@node Converting Integers, Integer Arithmetic, Simultaneous Integer Init & Assign, Integer Functions +@comment node-name, next, previous, up +@section Conversion Functions +@cindex Integer conversion functions +@cindex Conversion functions + +This section describes functions for converting arbitrary precision integers +to standard C types. Functions for converting @emph{to} arbitrary +precision integers are described in @ref{Assigning Integers} and @ref{I/O of +Integers}. + +@deftypefun {unsigned long int} mpz_get_ui (mpz_t @var{op}) +Return the least significant part from @var{op}. This function combined +with @* @code{mpz_tdiv_q_2exp(@dots{}, @var{op}, CHAR_BIT*sizeof(unsigned +long int))} can be used to extract the limbs of an integer. +@end deftypefun + +@deftypefun {signed long int} mpz_get_si (mpz_t @var{op}) +If @var{op} fits into a @code{signed long int} return the value of @var{op}. +Otherwise return the least significant part of @var{op}, with the same sign +as @var{op}. + +If @var{op} is too large to fit in a @code{signed long int}, the returned +result is probably not very useful. @c To find out if the value will fit, use +@c the function @code{mpz_fits_si}. +@end deftypefun + +@deftypefun double mpz_get_d (mpz_t @var{op}) +Convert @var{op} to a double. +@end deftypefun + +@deftypefun {char *} mpz_get_str (char *@var{str}, int @var{base}, mpz_t @var{op}) +Convert @var{op} to a string of digits in base @var{base}. The base may vary +from 2 to 36. + +If @var{str} is NULL, space for the result string is allocated using the +default allocation function, and a pointer to the string is returned. + +If @var{str} is not NULL, it should point to a block of storage enough large +for the result. To find out the right amount of space to provide for +@var{str}, use @code{mpz_sizeinbase (@var{op}, @var{base}) + 2}. The two +extra bytes are for a possible minus sign, and for the terminating null +character. +@end deftypefun + + +@node Integer Arithmetic, Comparison Functions, Converting Integers, Integer Functions +@comment node-name, next, previous, up +@section Arithmetic Functions +@cindex Integer arithmetic functions +@cindex Arithmetic functions + +@deftypefun void mpz_add (mpz_t @var{rop}, mpz_t @var{op1}, mpz_t @var{op2}) +@deftypefunx void mpz_add_ui (mpz_t @var{rop}, mpz_t @var{op1}, unsigned long int @var{op2}) +@ifinfo +Set @var{rop} to @var{op1} + @var{op2}. +@end ifinfo +@iftex +@tex +Set @var{rop} to $@var{op1} + @var{op2}$. +@end tex +@end iftex +@end deftypefun + +@deftypefun void mpz_sub (mpz_t @var{rop}, mpz_t @var{op1}, mpz_t @var{op2}) +@deftypefunx void mpz_sub_ui (mpz_t @var{rop}, mpz_t @var{op1}, unsigned long int @var{op2}) +Set @var{rop} to @var{op1} @minus{} @var{op2}. +@end deftypefun + +@deftypefun void mpz_mul (mpz_t @var{rop}, mpz_t @var{op1}, mpz_t @var{op2}) +@deftypefunx void mpz_mul_ui (mpz_t @var{rop}, mpz_t @var{op1}, unsigned long int @var{op2}) +@ifinfo +Set @var{rop} to @var{op1} times @var{op2}. +@end ifinfo +@iftex +@tex +Set @var{rop} to $@var{op1} \times @var{op2}$. +@end tex +@end iftex +@end deftypefun + +@deftypefun void mpz_mul_2exp (mpz_t @var{rop}, mpz_t @var{op1}, unsigned long int @var{op2}) +@ifinfo +Set @var{rop} to @var{op1} times 2 raised to @var{op2}. This operation can +also be defined as a left shift, @var{op2} steps. +@end ifinfo +@iftex +@tex +Set @var{rop} to $@var{op1} \times 2^{op2}$. This operation can also be +defined as a left shift, @var{op2} steps. +@end tex +@end iftex +@end deftypefun + +@deftypefun void mpz_neg (mpz_t @var{rop}, mpz_t @var{op}) +Set @var{rop} to @minus{}@var{op}. +@end deftypefun + +@deftypefun void mpz_abs (mpz_t @var{rop}, mpz_t @var{op}) +Set @var{rop} to the absolute value of @var{op}. +@end deftypefun + +@deftypefun void mpz_fac_ui (mpz_t @var{rop}, unsigned long int @var{op}) +Set @var{rop} to @var{op}!, the factorial of @var{op}. +@end deftypefun + +@subsection Division functions + +Division is undefined if the divisor is zero, and passing a zero divisor to +the divide or modulo functions, as well passing a zero mod argument to the +@code{mpz_powm} and @code{mpz_powm_ui} functions, will make these functions +intentionally divide by zero. This gives the user the possibility to handle +arithmetic exceptions in these functions in the same manner as other +arithmetic exceptions. + +There are three main groups of division functions: +@itemize @bullet +@item +Functions that truncate the quotient towards 0. The names of these +functions start with @code{mpz_tdiv}. The @samp{t} in the name is short for +@samp{truncate}. +@item +Functions that round the quotient towards @minus{}infinity. The names of +these routines start with @code{mpz_fdiv}. The @samp{f} in the name is +short for @samp{floor}. +@item +Functions that round the quotient towards +infinity. The names of +these routines start with @code{mpz_cdiv}. The @samp{c} in the name is +short for @samp{ceil}. +@end itemize + +For each rounding mode, there are a couple of variants. Here @samp{q} means +that the quotient is computed, while @samp{r} means that the remainder is +computed. Functions that compute both the quotient and remainder have +@samp{qr} in the name. + +@deftypefun void mpz_tdiv_q (mpz_t @var{rop}, mpz_t @var{op1}, mpz_t @var{op2}) +@deftypefunx void mpz_tdiv_q_ui (mpz_t @var{rop}, mpz_t @var{op1}, unsigned long int @var{op2}) +Set @var{rop} to [@var{op1}/@var{op2}]. The quotient is truncated towards +0. +@end deftypefun + +@deftypefun void mpz_tdiv_r (mpz_t @var{rop}, mpz_t @var{op1}, mpz_t @var{op2}) +@deftypefunx void mpz_tdiv_r_ui (mpz_t @var{rop}, mpz_t @var{op1}, unsigned long int @var{op2}) +Set @var{rop} to (@var{op1} - [@var{op1}/@var{op2}] * @var{op2}). +Unless the remainder is zero, it has the same sign as the dividend. +@end deftypefun + +@deftypefun void mpz_tdiv_qr (mpz_t @var{rop1}, mpz_t @var{rop2}, mpz_t @var{op1}, mpz_t @var{op2}) +@deftypefunx void mpz_tdiv_qr_ui (mpz_t @var{rop1}, mpz_t @var{rop2}, mpz_t @var{op1}, unsigned long int @var{op2}) +Divide @var{op1} by @var{op2} and put the quotient in @var{rop1} and the +remainder in @var{rop2}. The quotient is rounded towards 0. Unless the +remainder is zero, it has the same sign as the dividend. + +If @var{rop1} and @var{rop2} are the same variable, the results are +undefined. +@end deftypefun + +@deftypefun void mpz_fdiv_q (mpz_t @var{rop1}, mpz_t @var{op1}, mpz_t @var{op2}) +@deftypefunx void mpz_fdiv_q_ui (mpz_t @var{rop}, mpz_t @var{op1}, unsigned long int @var{op2}) +@ifinfo +Set @var{rop} to @var{op1}/@var{op2}. The quotient is rounded towards +@minus{}infinity. +@end ifinfo +@iftex +@tex +Set @var{rop} to $\lfloor@var{op1}/@var{op2}\rfloor$. (I.e., round +the quotient towards $-\infty$.) +@end tex +@end iftex +@end deftypefun + +@deftypefun void mpz_fdiv_r (mpz_t @var{rop}, mpz_t @var{op1}, mpz_t @var{op2}) +@deftypefunx {unsigned long int} mpz_fdiv_r_ui (mpz_t @var{rop}, mpz_t @var{op1}, unsigned long int @var{op2}) +Divide @var{op1} by @var{op2} and put the remainder in @var{rop}. Unless +the remainder is zero, it has the same sign as the divisor. + +For @code{mpz_fdiv_r_ui} the remainder is small enough to fit in an +@code{unsigned long int}, and is therefore returned. +@end deftypefun + +@deftypefun void mpz_fdiv_qr (mpz_t @var{rop1}, mpz_t @var{rop2}, mpz_t @var{op1}, mpz_t @var{op2}) +@deftypefunx {unsigned long int} mpz_fdiv_qr_ui (mpz_t @var{rop1}, mpz_t @var{rop2}, mpz_t @var{op1}, unsigned long int @var{op2}) +Divide @var{op1} by @var{op2} and put the quotient in @var{rop1} and the +remainder in @var{rop2}. The quotient is rounded towards @minus{}infinity. +Unless the remainder is zero, it has the same sign as the divisor. + +For @code{mpz_fdiv_qr_ui} the remainder is small enough to fit in an +@code{unsigned long int}, and is therefore returned. + +If @var{rop1} and @var{rop2} are the same variable, the results are +undefined. +@end deftypefun + +@deftypefun {unsigned long int} mpz_fdiv_ui (mpz_t @var{op1}, unsigned long int @var{op2}) +This function is similar to @code{mpz_fdiv_r_ui}, but the remainder is only +returned; it is not stored anywhere. +@end deftypefun + +@deftypefun void mpz_cdiv_q (mpz_t @var{rop1}, mpz_t @var{op1}, mpz_t @var{op2}) +@deftypefunx void mpz_cdiv_q_ui (mpz_t @var{rop}, mpz_t @var{op1}, unsigned long int @var{op2}) +@ifinfo +Set @var{rop} to @var{op1}/@var{op2}. The quotient is rounded towards ++infinity. +@end ifinfo +@iftex +@tex +Set @var{rop} to $\lceil@var{op1}/@var{op2}\rceil$. (I.e., round the +quotient towards $+\infty$.) +@end tex +@end iftex +@end deftypefun + +@deftypefun void mpz_cdiv_r (mpz_t @var{rop}, mpz_t @var{op1}, mpz_t @var{op2}) +@deftypefunx {unsigned long int} mpz_cdiv_r_ui (mpz_t @var{rop}, mpz_t @var{op1}, unsigned long int @var{op2}) +Divide @var{op1} by @var{op2} and put the remainder in @var{rop}. Unless +the remainder is zero, it has the opposite sign as the divisor. + +For @code{mpz_cdiv_r_ui} the negated remainder is small enough to fit in an +@code{unsigned long int}, and it is therefore returned. +@end deftypefun + +@deftypefun void mpz_cdiv_qr (mpz_t @var{rop1}, mpz_t @var{rop2}, mpz_t @var{op1}, mpz_t @var{op2}) +@deftypefunx {unsigned long int} mpz_cdiv_qr_ui (mpz_t @var{rop1}, mpz_t @var{rop2}, mpz_t @var{op1}, unsigned long int @var{op2}) +Divide @var{op1} by @var{op2} and put the quotient in @var{rop1} and the +remainder in @var{rop2}. The quotient is rounded towards +infinity. Unless +the remainder is zero, it has the opposite sign as the divisor. + +For @code{mpz_cdiv_qr_ui} the negated remainder is small enough to fit in an +@code{unsigned long int}, and it is therefore returned. + +If @var{rop1} and @var{rop2} are the same variable, the results are +undefined. +@end deftypefun + +@deftypefun {unsigned long int} mpz_cdiv_ui (mpz_t @var{op1}, unsigned long int @var{op2}) +Return the negated remainder, similar to @code{mpz_cdiv_r_ui}. (The +difference is that this function doesn't store the remainder anywhere.) +@end deftypefun + +@deftypefun void mpz_mod (mpz_t @var{rop}, mpz_t @var{op1}, mpz_t @var{op2}) +@deftypefunx {unsigned long int} mpz_mod_ui (mpz_t @var{rop}, mpz_t @var{op1}, unsigned long int @var{op2}) +Set @var{rop} to @var{op1} @code{mod} @var{op2}. The sign of the divisor is +ignored, and the result is always non-negative. + +For @code{mpz_mod_ui} the remainder is small enough to fit in an +@code{unsigned long int}, and is therefore returned. +@end deftypefun + +@deftypefun void mpz_divexact (mpz_t @var{rop}, mpz_t @var{op1}, mpz_t @var{op2}) +Set @var{rop} to @var{op1}/@var{op2}. This function produces correct +results only when it is known in advance that @var{op2} divides +@var{op1}. + +Since mpz_divexact is much faster than any of the other routines that produce +the quotient (@pxref{References} Jebelean), it is the best choice for +instances in which exact division is known to occur, such as reducing a +rational to lowest terms. +@end deftypefun + +@deftypefun void mpz_tdiv_q_2exp (mpz_t @var{rop}, mpz_t @var{op1}, unsigned long int @var{op2}) +@ifinfo +Set @var{rop} to @var{op1} divided by 2 raised to @var{op2}. The quotient is +rounded towards 0. +@end ifinfo +@iftex +@tex +Set @var{rop} to $@var{op1}/2^{op2}$. The quotient is rounded towards 0. +@end tex +@end iftex +@end deftypefun + +@deftypefun void mpz_tdiv_r_2exp (mpz_t @var{rop}, mpz_t @var{op1}, unsigned long int @var{op2}) +@ifinfo +Divide @var{op1} by (2 raised to @var{op2}) and put the remainder in +@var{rop}. Unless it is zero, @var{rop} will have the same sign as @var{op1}. +@end ifinfo +@iftex +@tex +Divide @var{op1} by $2^{op2}$ and put the remainder in @var{rop}. Unless it is +zero, @var{rop} will have the same sign as @var{op1}. +@end tex +@end iftex +@end deftypefun + +@deftypefun void mpz_fdiv_q_2exp (mpz_t @var{rop}, mpz_t @var{op1}, unsigned long int @var{op2}) +@ifinfo +Set @var{rop} to @var{op1} divided by 2 raised to @var{op2}. The quotient is +rounded towards @minus{}infinity. +@end ifinfo +@iftex +@tex +Set @var{rop} to $\lfloor@var{op1}/2^{op2}\rfloor$. The quotient is rounded +towards $-\infty$. +@end tex +@end iftex +@end deftypefun + +@deftypefun void mpz_fdiv_r_2exp (mpz_t @var{rop}, mpz_t @var{op1}, unsigned long int @var{op2}) +@ifinfo +Divide @var{op1} by (2 raised to @var{op2}) and put the remainder in +@var{rop}. The sign of @var{rop} will always be positive. +@end ifinfo +@iftex +@tex +Divide @var{op1} by $2^{op2}$ and put the remainder in @var{rop}. The sign of +@var{rop} will always be positive. +@end tex +@end iftex + +This operation can also be defined as masking of the @var{op2} least +significant bits. +@end deftypefun + +@subsection Exponentialization Functions + +@deftypefun void mpz_powm (mpz_t @var{rop}, mpz_t @var{base}, mpz_t @var{exp}, mpz_t @var{mod}) +@deftypefunx void mpz_powm_ui (mpz_t @var{rop}, mpz_t @var{base}, unsigned long int @var{exp}, mpz_t @var{mod}) +Set @var{rop} to (@var{base} raised to @var{exp}) @code{mod} @var{mod}. If +@var{exp} is negative, the result is undefined. +@end deftypefun + +@deftypefun void mpz_pow_ui (mpz_t @var{rop}, mpz_t @var{base}, unsigned long int @var{exp}) +@deftypefunx void mpz_ui_pow_ui (mpz_t @var{rop}, unsigned long int @var{base}, unsigned long int @var{exp}) +Set @var{rop} to @var{base} raised to @var{exp}. +@ifinfo +The case of 0^0 yields 1. +@end ifinfo +@iftex +@tex +The case of $0^0$ yields 1. +@end tex +@end iftex +@end deftypefun + +@subsection Square Root Functions + +@deftypefun void mpz_sqrt (mpz_t @var{rop}, mpz_t @var{op}) +@ifinfo +Set @var{rop} to the truncated integer part of the square root of +@var{op}. +@end ifinfo +@iftex +@tex +Set @var{rop} to $\lfloor\sqrt{@var{op}}\rfloor$, the truncated integer +part of the square root of @var{op}. +@end tex +@end iftex +@end deftypefun + +@deftypefun void mpz_sqrtrem (mpz_t @var{rop1}, mpz_t @var{rop2}, mpz_t @var{op}) +@ifinfo +Set @var{rop1} to the truncated integer part of the square root of @var{op}, +like @code{mpz_sqrt}. Set @var{rop2} to +@var{op}@minus{}@var{rop1}*@var{rop1}, +@end ifinfo +@iftex +@tex +Set @var{rop1} to $\lfloor\sqrt{@var{op}}\rfloor$, like @code{mpz_sqrt}. +Set @var{rop2} to $(@var{op} - @var{rop1}^2)$, +@end tex +@end iftex +(i.e., zero if @var{op} is a perfect square). + +If @var{rop1} and @var{rop2} are the same variable, the results are +undefined. +@end deftypefun + +@deftypefun int mpz_perfect_square_p (mpz_t @var{op}) +Return non-zero if @var{op} is a perfect square, i.e., if the square root of +@var{op} is an integer. Return zero otherwise. +@end deftypefun + +@subsection Number Theoretic Functions + +@deftypefun int mpz_probab_prime_p (mpz_t @var{op}, int @var{reps}) +@ifinfo +If this function returns 0, @var{op} is definitely not prime. If it returns +1, then @var{op} is `probably' prime. The probability of a false positive is +(1/4)**@var{reps}. +@end ifinfo +@iftex +@tex +If this function returns 0, @var{op} is definitely not prime. If it returns +1, then @var{op} is `probably' prime. The probability of a false positive is +$(1/4)^{{reps}}$. +@end tex +@end iftex +A reasonable value of reps is 25. + +An implementation of the probabilistic primality test found in Seminumerical +Algorithms (@pxref{References} Knuth). +@end deftypefun + +@deftypefun void mpz_gcd (mpz_t @var{rop}, mpz_t @var{op1}, mpz_t @var{op2}) +Set @var{rop} to the greatest common divisor of @var{op1} and @var{op2}. +@end deftypefun + +@deftypefun {unsigned long int} mpz_gcd_ui (mpz_t @var{rop}, mpz_t @var{op1}, unsigned long int @var{op2}) +Compute the greatest common divisor of @var{op1} and @var{op2}. If +@var{rop} is not NULL, store the result there. + +If the result is small enough to fit in an @code{unsigned long int}, it is +returned. If the result does not fit, 0 is returned, and the result is equal +to the argument @var{op1}. Note that the result will always fit if @var{op2} +is non-zero. +@end deftypefun + +@deftypefun void mpz_gcdext (mpz_t @var{g}, mpz_t @var{s}, mpz_t @var{t}, mpz_t @var{a}, mpz_t @var{b}) +Compute @var{g}, @var{s}, and @var{t}, such that @var{a}@var{s} + +@var{b}@var{t} = @var{g} = @code{gcd} (@var{a}, @var{b}). If @var{t} is +NULL, that argument is not computed. +@end deftypefun + +@deftypefun int mpz_invert (mpz_t @var{rop}, mpz_t @var{op1}, mpz_t @var{op2}) +Compute the inverse of @var{op1} modulo @var{op2} and put the result in +@var{rop}. Return non-zero if an inverse exist, zero otherwise. When the +function returns zero, do not assume anything about the value in @var{rop}. +@end deftypefun + +@deftypefun int mpz_jacobi (mpz_t @var{op1}, mpz_t @var{op2}) +@deftypefunx int mpz_legendre (mpz_t @var{op1}, mpz_t @var{op2}) +Compute the Jacobi and Legendre symbols, respectively. +@end deftypefun + +@need 2000 +@node Comparison Functions, Integer Logic and Bit Fiddling, Integer Arithmetic, Integer Functions +@comment node-name, next, previous, up +@section Comparison Functions + +@deftypefun int mpz_cmp (mpz_t @var{op1}, mpz_t @var{op2}) +@ifinfo +Compare @var{op1} and @var{op2}. Return a positive value if @var{op1} > +@var{op2}, zero if @var{op1} = @var{op2}, and a negative value if @var{op1} < +@var{op2}. +@end ifinfo +@iftex +@tex +Compare @var{op1} and @var{op2}. Return a positive value if $@var{op1} > +@var{op2}$, zero if $@var{op1} = @var{op2}$, and a negative value if $@var{op1} +< @var{op2}$. +@end tex +@end iftex +@end deftypefun + +@deftypefn Macro int mpz_cmp_ui (mpz_t @var{op1}, unsigned long int @var{op2}) +@deftypefnx Macro int mpz_cmp_si (mpz_t @var{op1}, signed long int @var{op2}) +@ifinfo +Compare @var{op1} and @var{op2}. Return a positive value if @var{op1} > +@var{op2}, zero if @var{op1} = @var{op2}, and a negative value if @var{op1} < +@var{op2}. +@end ifinfo +@iftex +@tex +Compare @var{op1} and @var{op2}. Return a positive value if $@var{op1} > +@var{op2}$, zero if $@var{op1} = @var{op2}$, and a negative value if $@var{op1} +< @var{op2}$. +@end tex +@end iftex + +These functions are actually implemented as macros. They evaluate their +arguments multiple times. +@end deftypefn + +@deftypefn Macro int mpz_sgn (mpz_t @var{op}) +@ifinfo +Return +1 if @var{op} > 0, 0 if @var{op} = 0, and @minus{}1 if @var{op} < 0. +@end ifinfo +@iftex +@tex +Return $+1$ if $@var{op} > 0$, 0 if $@var{op} = 0$, and $-1$ if $@var{op} < 0$. +@end tex +@end iftex + +This function is actually implemented as a macro. It evaluates its +arguments multiple times. +@end deftypefn + +@node Integer Logic and Bit Fiddling, I/O of Integers, Comparison Functions, Integer Functions +@comment node-name, next, previous, up +@section Logical and Bit Manipulation Functions +@cindex Logical functions +@cindex Bit manipulation functions + +These functions behave as if two's complement arithmetic were used (although +sign-magnitude is used by the actual implementation). + +@deftypefun void mpz_and (mpz_t @var{rop}, mpz_t @var{op1}, mpz_t @var{op2}) +Set @var{rop} to @var{op1} logical-and @var{op2}. +@end deftypefun + +@deftypefun void mpz_ior (mpz_t @var{rop}, mpz_t @var{op1}, mpz_t @var{op2}) +Set @var{rop} to @var{op1} inclusive-or @var{op2}. +@end deftypefun + +@c @deftypefun void mpz_xor (mpz_t @var{rop}, mpz_t @var{op1}, mpz_t @var{op2}) +@c Set @var{rop} to @var{op1} exclusive-or @var{op2}. +@c @end deftypefun + +@deftypefun void mpz_com (mpz_t @var{rop}, mpz_t @var{op}) +Set @var{rop} to the one's complement of @var{op}. +@end deftypefun + +@deftypefun {unsigned long int} mpz_popcount (mpz_t @var{op}) +For non-negative numbers, return the population count of @var{op}. For +negative numbers, return the largest possible value (@var{MAX_ULONG}). +@end deftypefun + +@deftypefun {unsigned long int} mpz_hamdist (mpz_t @var{op1}, mpz_t @var{op2}) +If @var{op1} and @var{op2} are both non-negative, return the hamming distance +between the two operands. Otherwise, return the largest possible value +(@var{MAX_ULONG}). + +It is possible to extend this function to return a useful value when the +operands are both negative, but the current implementation returns +@var{MAX_ULONG} in this case. @strong{Do not depend on this behavior, since +it will change in future versions of the library.} +@end deftypefun + +@deftypefun {unsigned long int} mpz_scan0 (mpz_t @var{op}, unsigned long int @var{starting_bit}) +Scan @var{op}, starting with bit @var{starting_bit}, towards more significant +bits, until the first clear bit is found. Return the index of the found bit. +@end deftypefun + +@deftypefun {unsigned long int} mpz_scan1 (mpz_t @var{op}, unsigned long int @var{starting_bit}) +Scan @var{op}, starting with bit @var{starting_bit}, towards more significant +bits, until the first set bit is found. Return the index of the found bit. +@end deftypefun + +@deftypefun void mpz_setbit (mpz_t @var{rop}, unsigned long int @var{bit_index}) +Set bit @var{bit_index} in @var{op1}. +@end deftypefun + +@deftypefun void mpz_clrbit (mpz_t @var{rop}, unsigned long int @var{bit_index}) +Clear bit @var{bit_index} in @var{op1}. +@end deftypefun + +@node I/O of Integers, Miscellaneous Integer Functions, Integer Logic and Bit Fiddling, Integer Functions +@comment node-name, next, previous, up +@section Input and Output Functions +@cindex Integer input and output functions +@cindex Input functions +@cindex Output functions +@cindex I/O functions + +Functions that perform input from a stdio stream, and functions that output to +a stdio stream. Passing a NULL pointer for a @var{stream} argument to any of +these functions will make them read from @code{stdin} and write to +@code{stdout}, respectively. + +When using any of these functions, it is a good idea to include @file{stdio.h} +before @file{gmp.h}, since that will allow @file{gmp.h} to define prototypes +for these functions. + +@deftypefun size_t mpz_out_str (FILE *@var{stream}, int @var{base}, mpz_t @var{op}) +Output @var{op} on stdio stream @var{stream}, as a string of digits in base +@var{base}. The base may vary from 2 to 36. + +Return the number of bytes written, or if an error occurred, return 0. +@end deftypefun + +@deftypefun size_t mpz_inp_str (mpz_t @var{rop}, FILE *@var{stream}, int @var{base}) +Input a possibly white-space preceded string in base @var{base} from stdio +stream @var{stream}, and put the read integer in @var{rop}. The base may vary +from 2 to 36. If @var{base} is 0, the actual base is determined from the +leading characters: if the first two characters are `0x' or `0X', hexadecimal +is assumed, otherwise if the first character is `0', octal is assumed, +otherwise decimal is assumed. + +Return the number of bytes read, or if an error occurred, return 0. +@end deftypefun + +@deftypefun size_t mpz_out_raw (FILE *@var{stream}, mpz_t @var{op}) +Output @var{op} on stdio stream @var{stream}, in raw binary format. The +integer is written in a portable format, with 4 bytes of size information, and +that many bytes of limbs. Both the size and the limbs are written in +decreasing significance order (i.e., in big-endian). + +The output can be read with @code{mpz_inp_raw}. + +Return the number of bytes written, or if an error occurred, return 0. + +The output of this can not be read by @code{mpz_inp_raw} from GMP 1, because +of changes necessary for compatibility between 32-bit and 64-bit machines. +@end deftypefun + +@deftypefun size_t mpz_inp_raw (mpz_t @var{rop}, FILE *@var{stream}) +Input from stdio stream @var{stream} in the format written by +@code{mpz_out_raw}, and put the result in @var{rop}. Return the number of +bytes read, or if an error occurred, return 0. + +This routine can read the output from @code{mpz_out_raw} also from GMP 1, in +spite of changes necessary for compatibility between 32-bit and 64-bit +machines. +@end deftypefun + + +@need 2000 +@node Miscellaneous Integer Functions,, I/O of Integers, Integer Functions +@comment node-name, next, previous, up +@section Miscellaneous Functions +@cindex Miscellaneous integer functions + +@deftypefun void mpz_random (mpz_t @var{rop}, mp_size_t @var{max_size}) +Generate a random integer of at most @var{max_size} limbs. The generated +random number doesn't satisfy any particular requirements of randomness. +Negative random numbers are generated when @var{max_size} is negative. +@end deftypefun + +@deftypefun void mpz_random2 (mpz_t @var{rop}, mp_size_t @var{max_size}) +Generate a random integer of at most @var{max_size} limbs, with long strings +of zeros and ones in the binary representation. Useful for testing functions +and algorithms, since this kind of random numbers have proven to be more +likely to trigger corner-case bugs. Negative random numbers are generated +when @var{max_size} is negative. +@end deftypefun + +@deftypefun size_t mpz_size (mpz_t @var{op}) +Return the size of @var{op} measured in number of limbs. If @var{op} is zero, +the returned value will be zero. +@c (@xref{Nomenclature}, for an explanation of the concept @dfn{limb}.) + +@strong{This function is obsolete. It will disappear from future MP +releases.} +@end deftypefun + +@deftypefun size_t mpz_sizeinbase (mpz_t @var{op}, int @var{base}) +Return the size of @var{op} measured in number of digits in base @var{base}. +The base may vary from 2 to 36. The returned value will be exact or 1 too +big. If @var{base} is a power of 2, the returned value will always be exact. + +This function is useful in order to allocate the right amount of space before +converting @var{op} to a string. The right amount of allocation is normally +two more than the value returned by @code{mpz_sizeinbase} (one extra for a +minus sign and one for the terminating '\0'). +@end deftypefun + + +@node Rational Number Functions, Floating-point Functions, Integer Functions, Top +@comment node-name, next, previous, up +@chapter Rational Number Functions +@cindex Rational number functions + +This chapter describes the MP functions for performing arithmetic on rational +numbers. These functions start with the prefix @code{mpq_}. + +Rational numbers are stored in objects of type @code{mpq_t}. + +All rational arithmetic functions assume operands have a canonical form, and +canonicalize their result. The canonical from means that the denominator and +the numerator have no common factors, and that the denominator is positive. +Zero has the unique representation 0/1. + +Pure assignment functions do not canonicalize the assigned variable. It is +the responsibility of the user to canonicalize the assigned variable before +any arithmetic operations are performed on that variable. @strong{Note that +this is an incompatible change from version 1 of the library.} + +@deftypefun void mpq_canonicalize (mpq_t @var{op}) +Remove any factors that are common to the numerator and denominator of +@var{op}, and make the denominator positive. +@end deftypefun + +@menu +* Initializing Rationals:: +* Assigning Rationals:: +* Simultaneous Integer Init & Assign:: +* Comparing Rationals:: +* Applying Integer Functions:: +* Miscellaneous Rational Functions:: +@end menu + +@node Initializing Rationals, Assigning Rationals, Rational Number Functions, Rational Number Functions +@comment node-name, next, previous, up +@section Initialization and Assignment Functions + +@deftypefun void mpq_init (mpq_t @var{dest_rational}) +Initialize @var{dest_rational} and set it to 0/1. Each variable should +normally only be initialized once, or at least cleared out (using the function +@code{mpq_clear}) between each initialization. +@end deftypefun + +@deftypefun void mpq_clear (mpq_t @var{rational_number}) +Free the space occupied by @var{rational_number}. Make sure to call this +function for all @code{mpq_t} variables when you are done with them. +@end deftypefun + +@deftypefun void mpq_set (mpq_t @var{rop}, mpq_t @var{op}) +@deftypefunx void mpq_set_z (mpq_t @var{rop}, mpz_t @var{op}) +Assign @var{rop} from @var{op}. +@end deftypefun + +@deftypefun void mpq_set_ui (mpq_t @var{rop}, unsigned long int @var{op1}, unsigned long int @var{op2}) +@deftypefunx void mpq_set_si (mpq_t @var{rop}, signed long int @var{op1}, unsigned long int @var{op2}) +Set the value of @var{rop} to @var{op1}/@var{op2}. Note that if @var{op1} and +@var{op2} have common factors, @var{rop} has to be passed to +@code{mpq_canonicalize} before any operations are performed on @var{rop}. +@end deftypefun + +@node Assigning Rationals, Comparing Rationals, Initializing Rationals, Rational Number Functions +@comment node-name, next, previous, up +@section Arithmetic Functions + +@deftypefun void mpq_add (mpq_t @var{sum}, mpq_t @var{addend1}, mpq_t @var{addend2}) +Set @var{sum} to @var{addend1} + @var{addend2}. +@end deftypefun + +@deftypefun void mpq_sub (mpq_t @var{difference}, mpq_t @var{minuend}, mpq_t @var{subtrahend}) +Set @var{difference} to @var{minuend} @minus{} @var{subtrahend}. +@end deftypefun + +@deftypefun void mpq_mul (mpq_t @var{product}, mpq_t @var{multiplier}, mpq_t @var{multiplicand}) +@ifinfo +Set @var{product} to @var{multiplier} times @var{multiplicand}. +@end ifinfo +@iftex +@tex +Set @var{product} to $@var{multiplier} \times @var{multiplicand}$. +@end tex +@end iftex +@end deftypefun + +@deftypefun void mpq_div (mpq_t @var{quotient}, mpq_t @var{dividend}, mpq_t @var{divisor}) +Set @var{quotient} to @var{dividend}/@var{divisor}. +@end deftypefun + +@deftypefun void mpq_neg (mpq_t @var{negated_operand}, mpq_t @var{operand}) +Set @var{negated_operand} to @minus{}@var{operand}. +@end deftypefun + +@deftypefun void mpq_inv (mpq_t @var{inverted_number}, mpq_t @var{number}) +Set @var{inverted_number} to 1/@var{number}. If the new denominator is +zero, this routine will divide by zero. +@end deftypefun + +@node Comparing Rationals, Applying Integer Functions, Assigning Rationals, Rational Number Functions +@comment node-name, next, previous, up +@section Comparison Functions + +@deftypefun int mpq_cmp (mpq_t @var{op1}, mpq_t @var{op2}) +@ifinfo +Compare @var{op1} and @var{op2}. Return a positive value if @var{op1} > +@var{op2}, zero if @var{op1} = @var{op2}, and a negative value if @var{op1} < +@var{op2}. +@end ifinfo +@iftex +@tex +Compare @var{op1} and @var{op2}. Return a positive value if $@var{op1} > +@var{op2}$, zero if $@var{op1} = @var{op2}$, and a negative value if $@var{op1} +< @var{op2}$. +@end tex +@end iftex + +To determine if two rationals are equal, @code{mpq_equal} is faster than +@code{mpq_cmp}. +@end deftypefun + +@deftypefn Macro int mpq_cmp_ui (mpq_t @var{op1}, unsigned long int @var{num2}, unsigned long int @var{den2}) +@ifinfo +Compare @var{op1} and @var{num2}/@var{den2}. Return a positive value if +@var{op1} > @var{num2}/@var{den2}, zero if @var{op1} = @var{num2}/@var{den2}, +and a negative value if @var{op1} < @var{num2}/@var{den2}. +@end ifinfo +@iftex +@tex +Compare @var{op1} and @var{num2}/@var{den2}. Return a positive value if +$@var{op1} > @var{num2}/@var{den2}$, zero if $@var{op1} = +@var{num2}/@var{den2}$, and a negative value if $@var{op1} < +@var{num2}/@var{den2}$. +@end tex +@end iftex + +This routine allows that @var{num2} and @var{den2} have common factors. + +This function is actually implemented as a macro. It evaluates its +arguments multiple times. +@end deftypefn + +@deftypefn Macro int mpq_sgn (mpq_t @var{op}) +@ifinfo +Return +1 if @var{op} > 0, 0 if @var{op} = 0, and @minus{}1 if @var{op} < 0. +@end ifinfo +@iftex +@tex +Return $+1$ if $@var{op} > 0$, 0 if $@var{op} = 0$, and $-1$ if $@var{op} < 0$. +@end tex +@end iftex + +This function is actually implemented as a macro. It evaluates its +arguments multiple times. +@end deftypefn + +@deftypefun int mpq_equal (mpq_t @var{op1}, mpq_t @var{op2}) +Return non-zero if @var{op1} and @var{op2} are equal, zero if they are +non-equal. Although @code{mpq_cmp} can be used for the same purpose, this +function is much faster. +@end deftypefun + +@node Applying Integer Functions, Miscellaneous Rational Functions, Comparing Rationals, Rational Number Functions +@comment node-name, next, previous, up +@section Applying Integer Functions to Rationals + +The set of @code{mpq} functions is quite small. In particular, there are no +functions for either input or output. But there are two macros that allow us +to apply any @code{mpz} function on the numerator or denominator of a rational +number. If these macros are used to assign to the rational number, +@code{mpq_canonicalize} normally need to be called afterwards. + +@deftypefn Macro mpz_t mpq_numref (mpq_t @var{op}) +@deftypefnx Macro mpz_t mpq_denref (mpq_t @var{op}) +Return a reference to the numerator and denominator of @var{op}, respectively. +The @code{mpz} functions can be used on the result of these macros. +@end deftypefn + +@need 2000 +@node Miscellaneous Rational Functions, , Applying Integer Functions, Rational Number Functions +@comment node-name, next, previous, up +@section Miscellaneous Functions + +@deftypefun double mpq_get_d (mpq_t @var{op}) +Convert @var{op} to a double. +@end deftypefun + +These functions assign between either the numerator or denominator of a +rational, and an integer. Instead of using these functions, it is preferable +to use the more general mechanisms @code{mpq_numref} and @code{mpq_denref}, +together with @code{mpz_set}. + +@deftypefun void mpq_set_num (mpq_t @var{rational}, mpz_t @var{numerator}) +Copy @var{numerator} to the numerator of @var{rational}. When this risks to +make the numerator and denominator of @var{rational} have common factors, you +have to pass @var{rational} to @code{mpq_canonicalize} before any operations +are performed on @var{rational}. + +This function is equivalent to +@code{mpz_set (mpq_numref (@var{rational}), @var{numerator})}. +@end deftypefun + +@deftypefun void mpq_set_den (mpq_t @var{rational}, mpz_t @var{denominator}) +Copy @var{denominator} to the denominator of @var{rational}. When this risks +to make the numerator and denominator of @var{rational} have common factors, +or if the denominator might be negative, you have to pass @var{rational} to +@code{mpq_canonicalize} before any operations are performed on @var{rational}. + +@strong{In version 1 of the library, negative denominators were handled by +copying the sign to the numerator. That is no longer done.} + +This function is equivalent to +@code{mpz_set (mpq_denref (@var{rational}), @var{denominators})}. +@end deftypefun + +@deftypefun void mpq_get_num (mpz_t @var{numerator}, mpq_t @var{rational}) +Copy the numerator of @var{rational} to the integer @var{numerator}, to +prepare for integer operations on the numerator. + +This function is equivalent to +@code{mpz_set (@var{numerator}, mpq_numref (@var{rational}))}. +@end deftypefun + +@deftypefun void mpq_get_den (mpz_t @var{denominator}, mpq_t @var{rational}) +Copy the denominator of @var{rational} to the integer @var{denominator}, to +prepare for integer operations on the denominator. + +This function is equivalent to +@code{mpz_set (@var{denominator}, mpq_denref (@var{rational}))}. +@end deftypefun + + +@node Floating-point Functions, Low-level Functions, Rational Number Functions, Top +@comment node-name, next, previous, up +@chapter Floating-point Functions +@cindex Floating-point functions +@cindex Float functions + +This is a description of the @emph{preliminary} interface for floating-point +arithmetic in GNU MP 2. + +The floating-point functions expect arguments of type @code{mpf_t}. + +The MP floating-point functions have an interface that is similar to the MP +integer functions. The function prefix for floating-point operations is +@code{mpf_}. + +There is one significant characteristic of floating-point numbers that has +motivated a difference between this function class and other MP function +classes: the inherent inexactness of floating point arithmetic. The user has +to specify the precision of each variable. A computation that assigns a +variable will take place with the precision of the assigned variable; the +precision of variables used as input is ignored. + +@cindex User-defined precision +The precision of a calculation is defined as follows: Compute the requested +operation exactly (with ``infinite precision''), and truncate the result to +the destination variable precision. Even if the user has asked for a very +high precision, MP will not calculate with superfluous digits. For example, +if two low-precision numbers of nearly equal magnitude are added, the +precision of the result will be limited to what is required to represent the +result accurately. + +The MP floating-point functions are @emph{not} intended as a smooth extension +to the IEEE P754 arithmetic. Specifically, the results obtained on one +computer often differs from the results obtained on a computer with a +different word size. + +@menu +* Initializing Floats:: +* Assigning Floats:: +* Simultaneous Float Init & Assign:: +* Converting Floats:: +* Float Arithmetic:: +* Float Comparison:: +* I/O of Floats:: +* Miscellaneous Float Functions:: +@end menu + +@node Initializing Floats, Assigning Floats, , Floating-point Functions +@comment node-name, next, previous, up +@section Initialization and Assignment Functions + +@deftypefun void mpf_set_default_prec (unsigned long int @var{prec}) +Set the default precision to be @strong{at least} @var{prec} bits. All +subsequent calls to @code{mpf_init} will use this precision, but previously +initialized variables are unaffected. +@end deftypefun + +An @code{mpf_t} object must be initialized before storing the first value in +it. The functions @code{mpf_init} and @code{mpf_init2} are used for that +purpose. + +@deftypefun void mpf_init (mpf_t @var{x}) +Initialize @var{x} to 0. Normally, a variable should be initialized once only +or at least be cleared, using @code{mpf_clear}, between initializations. The +precision of @var{x} is undefined unless a default precision has already been +established by a call to @code{mpf_set_default_prec}. +@end deftypefun + +@deftypefun void mpf_init2 (mpf_t @var{x}, unsigned long int @var{prec}) +Initialize @var{x} to 0 and set its precision to be @strong{at least} +@var{prec} bits. Normally, a variable should be initialized once only or at +least be cleared, using @code{mpf_clear}, between initializations. +@end deftypefun + +@deftypefun void mpf_clear (mpf_t @var{x}) +Free the space occupied by @var{x}. Make sure to call this function for all +@code{mpf_t} variables when you are done with them. +@end deftypefun + +@need 2000 +Here is an example on how to initialize floating-point variables: +@example +@{ + mpf_t x, y; + mpf_init (x); /* use default precision */ + mpf_init2 (y, 256); /* precision @emph{at least} 256 bits */ + @dots{} + /* Unless the program is about to exit, do ... */ + mpf_clear (x); + mpf_clear (y); +@} +@end example + +The following three functions are useful for changing the precision during a +calculation. A typical use would be for adjusting the precision gradually in +iterative algorithms like Newton-Raphson, making the computation precision +closely match the actual accurate part of the numbers. + +@deftypefun void mpf_set_prec (mpf_t @var{rop}, unsigned long int @var{prec}) +Set the precision of @var{rop} to be @strong{at least} @var{prec} bits. +Since changing the precision involves calls to @code{realloc}, this routine +should not be called in a tight loop. +@end deftypefun + +@deftypefun {unsigned long int} mpf_get_prec (mpf_t @var{op}) +Return the precision actually used for assignments of @var{op}. +@end deftypefun + +@deftypefun void mpf_set_prec_raw (mpf_t @var{rop}, unsigned long int @var{prec}) +Set the precision of @var{rop} to be @strong{at least} @var{prec} bits. This +is a low-level function that does not change the allocation. The @var{prec} +argument must not be larger that the precision previously returned by +@code{mpf_get_prec}. It is crucial that the precision of @var{rop} is +ultimately reset to exactly the value returned by @code{mpf_get_prec}. +@end deftypefun + + +@node Assigning Floats, Simultaneous Float Init & Assign, Initializing Floats, Floating-point Functions +@comment node-name, next, previous, up +@subsection Assignment Functions +@cindex Float assignment functions + +These functions assign new values to already initialized floats +(@pxref{Initializing Floats}). + +@deftypefun void mpf_set (mpf_t @var{rop}, mpf_t @var{op}) +@deftypefunx void mpf_set_ui (mpf_t @var{rop}, unsigned long int @var{op}) +@deftypefunx void mpf_set_si (mpf_t @var{rop}, signed long int @var{op}) +@deftypefunx void mpf_set_d (mpf_t @var{rop}, double @var{op}) +@deftypefunx void mpf_set_z (mpf_t @var{rop}, mpz_t @var{op}) +@deftypefunx void mpf_set_q (mpf_t @var{rop}, mpq_t @var{op}) +Set the value of @var{rop} from @var{op}. +@end deftypefun + +@deftypefun int mpf_set_str (mpf_t @var{rop}, char *@var{str}, int @var{base}) +Set the value of @var{rop} from the string in @var{str}. The string is of the +form @samp{M@@N} or, if the base is 10 or less, alternatively @samp{MeN}. +@samp{M} is the mantissa and @samp{N} is the exponent. The mantissa is always +in the specified base. The exponent is either in the specified base or, if +@var{base} is negative, in decimal. + +The argument @var{base} may be in the ranges 2 to 36, or @minus{}36 to +@minus{}2. Negative values are used to specify that the exponent is in +decimal. + +Unlike the corresponding @code{mpz} function, the base will not be determined +from the leading characters of the string if @var{base} is 0. This is so that +numbers like @samp{0.23} are not interpreted as octal. + +White space is allowed in the string, and is simply ignored. + +This function returns 0 if the entire string up to the '\0' is a valid number +in base @var{base}. Otherwise it returns @minus{}1. +@end deftypefun + + +@node Simultaneous Float Init & Assign, Converting Floats, Assigning Floats, Floating-point Functions +@comment node-name, next, previous, up +@subsection Combined Initialization and Assignment Functions +@cindex Initialization and assignment functions + +For convenience, MP provides a parallel series of initialize-and-set functions +which initialize the output and then store the value there. These functions' +names have the form @code{mpf_init_set@dots{}} + +Once the float has been initialized by any of the @code{mpf_init_set@dots{}} +functions, it can be used as the source or destination operand for the ordinary +float functions. Don't use an initialize-and-set function on a variable +already initialized! + +@deftypefun void mpf_init_set (mpf_t @var{rop}, mpf_t @var{op}) +@deftypefunx void mpf_init_set_ui (mpf_t @var{rop}, unsigned long int @var{op}) +@deftypefunx void mpf_init_set_si (mpf_t @var{rop}, signed long int @var{op}) +@deftypefunx void mpf_init_set_d (mpf_t @var{rop}, double @var{op}) +Initialize @var{rop} and set its value from @var{op}. + +The precision of @var{rop} will be taken from the active default precision, as +set by @code{mpf_set_default_prec}. +@end deftypefun + +@deftypefun int mpf_init_set_str (mpf_t @var{rop}, char *@var{str}, int @var{base}) +Initialize @var{rop} and set its value from the string in @var{str}. See +@code{mpf_set_str} above for details on the assignment operation. + +Note that @var{rop} is initialized even if an error occurs. (I.e., you have to +call @code{mpf_clear} for it.) + +The precision of @var{rop} will be taken from the active default precision, as +set by @code{mpf_set_default_prec}. +@end deftypefun + + +@node Converting Floats, Float Arithmetic, Simultaneous Float Init & Assign, Floating-point Functions +@comment node-name, next, previous, up +@section Conversion Functions +@cindex Conversion functions + +@deftypefun double mpf_get_d (mpf_t @var{op}) +Convert @var{op} to a double. +@end deftypefun + +@deftypefun {char *} mpf_get_str (char *@var{str}, mp_exp_t *@var{expptr}, int @var{base}, size_t @var{n_digits}, mpf_t @var{op}) +Convert @var{op} to a string of digits in base @var{base}. The base may vary +from 2 to 36. Generate at most @var{n_digits} significant digits, or if +@var{n_digits} is 0, the maximum number of digits accurately representable by +@var{op}. + +If @var{str} is NULL, space for the mantissa is allocated using the default +allocation function, and a pointer to the string is returned. + +If @var{str} is not NULL, it should point to a block of storage enough large +for the mantissa, i.e., @var{n_digits} + 2. The two extra bytes are for a +possible minus sign, and for the terminating null character. + +The exponent is written through the pointer @var{expptr}. + +If @var{n_digits} is 0, the maximum number of digits meaningfully achievable +from the precision of @var{op} will be generated. Note that the space +requirements for @var{str} in this case will be impossible for the user to +predetermine. Therefore, you need to pass NULL for the string argument +whenever @var{n_digits} is 0. + +The generated string is a fraction, with an implicit radix point immediately +to the left of the first digit. For example, the number 3.1416 would be +returned as "31416" in the string and 1 written at @var{expptr}. +@end deftypefun + + +@node Float Arithmetic, Float Comparison, Converting Floats, Floating-point Functions +@comment node-name, next, previous, up +@section Arithmetic Functions +@cindex Float arithmetic functions +@cindex Arithmetic functions + +@deftypefun void mpf_add (mpf_t @var{rop}, mpf_t @var{op1}, mpf_t @var{op2}) +@deftypefunx void mpf_add_ui (mpf_t @var{rop}, mpf_t @var{op1}, unsigned long int @var{op2}) +@ifinfo +Set @var{rop} to @var{op1} + @var{op2}. +@end ifinfo +@iftex +@tex +Set @var{rop} to $@var{op1} + @var{op2}$. +@end tex +@end iftex +@end deftypefun + +@deftypefun void mpf_sub (mpf_t @var{rop}, mpf_t @var{op1}, mpf_t @var{op2}) +@deftypefunx void mpf_ui_sub (mpf_t @var{rop}, unsigned long int @var{op1}, mpf_t @var{op2}) +@deftypefunx void mpf_sub_ui (mpf_t @var{rop}, mpf_t @var{op1}, unsigned long int @var{op2}) +Set @var{rop} to @var{op1} @minus{} @var{op2}. +@end deftypefun + +@deftypefun void mpf_mul (mpf_t @var{rop}, mpf_t @var{op1}, mpf_t @var{op2}) +@deftypefunx void mpf_mul_ui (mpf_t @var{rop}, mpf_t @var{op1}, unsigned long int @var{op2}) +@ifinfo +Set @var{rop} to @var{op1} times @var{op2}. +@end ifinfo +@iftex +@tex +Set @var{rop} to $@var{op1} \times @var{op2}$. +@end tex +@end iftex +@end deftypefun + +Division is undefined if the divisor is zero, and passing a zero divisor to +the divide functions will make these functions intentionally divide by zero. +This gives the user the possibility to handle arithmetic exceptions in these +functions in the same manner as other arithmetic exceptions. + +@deftypefun void mpf_div (mpf_t @var{rop}, mpf_t @var{op1}, mpf_t @var{op2}) +@deftypefunx void mpf_ui_div (mpf_t @var{rop}, unsigned long int @var{op1}, mpf_t @var{op2}) +@deftypefunx void mpf_div_ui (mpf_t @var{rop}, mpf_t @var{op1}, unsigned long int @var{op2}) +Set @var{rop} to @var{op1}/@var{op2}. +@end deftypefun + +@deftypefun void mpf_sqrt (mpf_t @var{rop}, mpf_t @var{op}) +@deftypefunx void mpf_sqrt_ui (mpf_t @var{rop}, unsigned long int @var{op}) +@ifinfo +Set @var{rop} to the square root of @var{op}. +@end ifinfo +@iftex +@tex +Set @var{rop} to $\sqrt{@var{op}}$. +@end tex +@end iftex +@end deftypefun + +@c @deftypefun void mpf_pow_ui (mpf_t @var{rop}, mpf_t @var{op1}, unsigned long int @var{op2}) +@c Set @var{rop} to @var{op1} raised to @var{op2}. +@c @end deftypefun + +@deftypefun void mpf_neg (mpf_t @var{rop}, mpf_t @var{op}) +Set @var{rop} to @minus{}@var{op}. +@end deftypefun + +@deftypefun void mpf_abs (mpf_t @var{rop}, mpf_t @var{op}) +Set @var{rop} to the absolute value of @var{op}. +@end deftypefun + +@deftypefun void mpf_mul_2exp (mpf_t @var{rop}, mpf_t @var{op1}, unsigned long int @var{op2}) +@ifinfo +Set @var{rop} to @var{op1} times 2 raised to @var{op2}. +@end ifinfo +@iftex +@tex +Set @var{rop} to $@var{op1} \times 2^{op2}$. +@end tex +@end iftex +@end deftypefun + +@deftypefun void mpf_div_2exp (mpf_t @var{rop}, mpf_t @var{op1}, unsigned long int @var{op2}) +@ifinfo +Set @var{rop} to @var{op1} divided by 2 raised to @var{op2}. +@end ifinfo +@iftex +@tex +Set @var{rop} to $@var{op1}/2^{op2}$. +@end tex +@end iftex +@end deftypefun + +@node Float Comparison, I/O of Floats, Float Arithmetic, Floating-point Functions +@comment node-name, next, previous, up +@section Comparison Functions +@cindex Float comparisons functions +@cindex Comparison functions + +@deftypefun int mpf_cmp (mpf_t @var{op1}, mpf_t @var{op2}) +@deftypefunx int mpf_cmp_ui (mpf_t @var{op1}, unsigned long int @var{op2}) +@deftypefunx int mpf_cmp_si (mpf_t @var{op1}, signed long int @var{op2}) +@ifinfo +Compare @var{op1} and @var{op2}. Return a positive value if @var{op1} > +@var{op2}, zero if @var{op1} = @var{op2}, and a negative value if @var{op1} < +@var{op2}. +@end ifinfo +@iftex +@tex +Compare @var{op1} and @var{op2}. Return a positive value if $@var{op1} > +@var{op2}$, zero if $@var{op1} = @var{op2}$, and a negative value if $@var{op1} +< @var{op2}$. +@end tex +@end iftex +@end deftypefun + +@deftypefun int mpf_eq (mpf_t @var{op1}, mpf_t @var{op2}, unsigned long int op3) +Return non-zero if the first @var{op3} bits of @var{op1} and @var{op2} are +equal, zero otherwise. I.e., test of @var{op1} and @var{op2} are +approximately equal. +@end deftypefun + +@deftypefun void mpf_reldiff (mpf_t @var{rop}, mpf_t @var{op1}, mpf_t @var{op2}) +Compute the relative difference between @var{op1} and @var{op2} and store the +result in @var{rop}. +@end deftypefun + +@deftypefn Macro int mpf_sgn (mpf_t @var{op}) +@ifinfo +Return +1 if @var{op} > 0, 0 if @var{op} = 0, and @minus{}1 if @var{op} < 0. +@end ifinfo +@iftex +@tex +Return $+1$ if $@var{op} > 0$, 0 if $@var{op} = 0$, and $-1$ if $@var{op} < 0$. +@end tex +@end iftex + +This function is actually implemented as a macro. It evaluates its +arguments multiple times. +@end deftypefn + +@node I/O of Floats, Miscellaneous Float Functions, Float Comparison, Floating-point Functions +@comment node-name, next, previous, up +@section Input and Output Functions +@cindex Float input and output functions +@cindex Input functions +@cindex Output functions +@cindex I/O functions + +Functions that perform input from a stdio stream, and functions that output to +a stdio stream. Passing a NULL pointer for a @var{stream} argument to any of +these functions will make them read from @code{stdin} and write to +@code{stdout}, respectively. + +When using any of these functions, it is a good idea to include @file{stdio.h} +before @file{gmp.h}, since that will allow @file{gmp.h} to define prototypes +for these functions. + +@deftypefun size_t mpf_out_str (FILE *@var{stream}, int @var{base}, size_t @var{n_digits}, mpf_t @var{op}) +Output @var{op} on stdio stream @var{stream}, as a string of digits in +base @var{base}. The base may vary from 2 to 36. Print at most +@var{n_digits} significant digits, or if @var{n_digits} is 0, the maximum +number of digits accurately representable by @var{op}. + +In addition to the significant digits, a leading @samp{0.} and a +trailing exponent, in the form @samp{eNNN}, are printed. If @var{base} +is greater than 10, @samp{@@} will be used instead of @samp{e} as +exponent delimiter. + +Return the number of bytes written, or if an error occurred, return 0. +@end deftypefun + +@deftypefun size_t mpf_inp_str (mpf_t @var{rop}, FILE *@var{stream}, int @var{base}) +Input a string in base @var{base} from stdio stream @var{stream}, and put the +read float in @var{rop}. The string is of the form @samp{M@@N} or, if the +base is 10 or less, alternatively @samp{MeN}. @samp{M} is the mantissa and +@samp{N} is the exponent. The mantissa is always in the specified base. The +exponent is either in the specified base or, if @var{base} is negative, in +decimal. + +The argument @var{base} may be in the ranges 2 to 36, or @minus{}36 to +@minus{}2. Negative values are used to specify that the exponent is in +decimal. + +Unlike the corresponding @code{mpz} function, the base will not be determined +from the leading characters of the string if @var{base} is 0. This is so that +numbers like @samp{0.23} are not interpreted as octal. + +Return the number of bytes read, or if an error occurred, return 0. +@end deftypefun + +@c @deftypefun void mpf_out_raw (FILE *@var{stream}, mpf_t @var{float}) +@c Output @var{float} on stdio stream @var{stream}, in raw binary +@c format. The float is written in a portable format, with 4 bytes of +@c size information, and that many bytes of limbs. Both the size and the +@c limbs are written in decreasing significance order. +@c @end deftypefun + +@c @deftypefun void mpf_inp_raw (mpf_t @var{float}, FILE *@var{stream}) +@c Input from stdio stream @var{stream} in the format written by +@c @code{mpf_out_raw}, and put the result in @var{float}. +@c @end deftypefun + + +@node Miscellaneous Float Functions, , I/O of Floats, Floating-point Functions +@comment node-name, next, previous, up +@section Miscellaneous Functions +@cindex Miscellaneous float functions + +@deftypefun void mpf_random2 (mpf_t @var{rop}, mp_size_t @var{max_size}, mp_exp_t @var{max_exp}) +Generate a random float of at most @var{max_size} limbs, with long strings of +zeros and ones in the binary representation. The exponent of the number is in +the interval @minus{}@var{exp} to @var{exp}. This function is useful for +testing functions and algorithms, since this kind of random numbers have +proven to be more likely to trigger corner-case bugs. Negative random numbers +are generated when @var{max_size} is negative. +@end deftypefun + +@c @deftypefun size_t mpf_size (mpf_t @var{op}) +@c Return the size of @var{op} measured in number of limbs. If @var{op} is +@c zero, the returned value will be zero. (@xref{Nomenclature}, for an +@c explanation of the concept @dfn{limb}.) +@c +@c @strong{This function is obsolete. It will disappear from future MP +@c releases.} +@c @end deftypefun + +@node Low-level Functions, BSD Compatible Functions, Floating-point Functions, Top +@comment node-name, next, previous, up +@chapter Low-level Functions +@cindex Low-level functions + +This chapter describes low-level MP functions, used to implement the high-level +MP functions, but also intended for time-critical user code. + +These functions start with the prefix @code{mpn_}. + +@c 1. Some of these function clobber input operands. +@c + +The @code{mpn} functions are designed to be as fast as possible, @strong{not} +to provide a coherent calling interface. The different functions have somewhat +similar interfaces, but there are variations that make them hard to use. These +functions do as little as possible apart from the real multiple precision +computation, so that no time is spent on things that not all callers need. + +A source operand is specified by a pointer to the least significant limb and a +limb count. A destination operand is specified by just a pointer. It is the +responsibility of the caller to ensure that the destination has enough space +for storing the result. + +With this way of specifying operands, it is possible to perform computations +on subranges of an argument, and store the result into a subrange of a +destination. + +A common requirement for all functions is that each source area needs at least +one limb. No size argument may be zero. + +The @code{mpn} functions is the base for the implementation of the @code{mpz_}, +@code{mpf_}, and @code{mpq_} functions. + +This example adds the number beginning at @var{src1_ptr} and the number +beginning at @var{src2_ptr} and writes the sum at @var{dest_ptr}. All areas +have @var{size} limbs. + +@example +cy = mpn_add_n (dest_ptr, src1_ptr, src2_ptr, size) +@end example + +@noindent +In the notation used here, a source operand is identified by the pointer to +the least significant limb, and the limb count in braces. For example, +@{s1_ptr, s1_size@}. + +@deftypefun mp_limb_t mpn_add_n (mp_limb_t * @var{dest_ptr}, const mp_limb_t * @var{src1_ptr}, const mp_limb_t * @var{src2_ptr}, mp_size_t @var{size}) +Add @{@var{src1_ptr}, @var{size}@} and @{@var{src2_ptr}, @var{size}@}, and +write the @var{size} least significant limbs of the result to @var{dest_ptr}. +Return carry, either 0 or 1. + +This is the lowest-level function for addition. It is the preferred function +for addition, since it is written in assembly for most targets. For addition +of a variable to itself (i.e., @var{src1_ptr} equals @var{src2_ptr}, use +@code{mpn_lshift} with a count of 1 for optimal speed. +@end deftypefun + +@deftypefun mp_limb_t mpn_add_1 (mp_limb_t * @var{dest_ptr}, const mp_limb_t * @var{src1_ptr}, mp_size_t @var{size}, mp_limb_t @var{src2_limb}) +Add @{@var{src1_ptr}, @var{size}@} and @var{src2_limb}, and write the +@var{size} least significant limbs of the result to @var{dest_ptr}. Return +carry, either 0 or 1. +@end deftypefun + +@deftypefun mp_limb_t mpn_add (mp_limb_t * @var{dest_ptr}, const mp_limb_t * @var{src1_ptr}, mp_size_t @var{src1_size}, const mp_limb_t * @var{src2_ptr}, mp_size_t @var{src2_size}) +Add @{@var{src1_ptr}, @var{src1_size}@} and @{@var{src2_ptr}, +@var{src2_size}@}, and write the @var{src1_size} least significant limbs of +the result to @var{dest_ptr}. Return carry, either 0 or 1. + +This function requires that @var{src1_size} is greater than or equal to +@var{src2_size}. +@end deftypefun + +@deftypefun mp_limb_t mpn_sub_n (mp_limb_t * @var{dest_ptr}, const mp_limb_t * @var{src1_ptr}, const mp_limb_t * @var{src2_ptr}, mp_size_t @var{size}) +Subtract @{@var{src2_ptr}, @var{src2_size}@} from @{@var{src1_ptr}, +@var{size}@}, and write the @var{size} least significant limbs of the result +to @var{dest_ptr}. Return borrow, either 0 or 1. + +This is the lowest-level function for subtraction. It is the preferred +function for subtraction, since it is written in assembly for most targets. +@end deftypefun + +@deftypefun mp_limb_t mpn_sub_1 (mp_limb_t * @var{dest_ptr}, const mp_limb_t * @var{src1_ptr}, mp_size_t @var{size}, mp_limb_t @var{src2_limb}) +Subtract @var{src2_limb} from @{@var{src1_ptr}, @var{size}@}, and write the +@var{size} least significant limbs of the result to @var{dest_ptr}. Return +borrow, either 0 or 1. +@end deftypefun + +@deftypefun mp_limb_t mpn_sub (mp_limb_t * @var{dest_ptr}, const mp_limb_t * @var{src1_ptr}, mp_size_t @var{src1_size}, const mp_limb_t * @var{src2_ptr}, mp_size_t @var{src2_size}) +Subtract @{@var{src2_ptr}, @var{src2_size}@} from @{@var{src1_ptr}, +@var{src1_size}@}, and write the @var{src1_size} least significant limbs of +the result to @var{dest_ptr}. Return borrow, either 0 or 1. + +This function requires that @var{src1_size} is greater than or equal to +@var{src2_size}. +@end deftypefun + +@deftypefun void mpn_mul_n (mp_limb_t * @var{dest_ptr}, const mp_limb_t * @var{src1_ptr}, const mp_limb_t * @var{src2_ptr}, mp_size_t @var{size}) +Multiply @{@var{src1_ptr}, @var{size}@} and @{@var{src2_ptr}, @var{size}@}, +and write the @strong{entire} result to @var{dest_ptr}. + +The destination has to have space for 2@var{size} limbs, even if the +significant result might be one limb smaller. +@end deftypefun + +@deftypefun mp_limb_t mpn_mul_1 (mp_limb_t * @var{dest_ptr}, const mp_limb_t * @var{src1_ptr}, mp_size_t @var{size}, mp_limb_t @var{src2_limb}) +Multiply @{@var{src1_ptr}, @var{size}@} and @var{src2_limb}, and write the +@var{size} least significant limbs of the product to @var{dest_ptr}. Return +the most significant limb of the product. + +This is a low-level function that is a building block for general +multiplication as well as other operations in MP. It is written in assembly +for most targets. + +Don't call this function if @var{src2_limb} is a power of 2; use +@code{mpn_lshift} with a count equal to the logarithm of @var{src2_limb} +instead, for optimal speed. +@end deftypefun + +@deftypefun mp_limb_t mpn_addmul_1 (mp_limb_t * @var{dest_ptr}, const mp_limb_t * @var{src1_ptr}, mp_size_t @var{size}, mp_limb_t @var{src2_limb}) +Multiply @{@var{src1_ptr}, @var{size}@} and @var{src2_limb}, and add the +@var{size} least significant limbs of the product to @{@var{dest_ptr}, +@var{size}@} and write the result to @var{dest_ptr} @var{dest_ptr}. Return +the most significant limb of the product, plus carry-out from the addition. + +This is a low-level function that is a building block for general +multiplication as well as other operations in MP. It is written in assembly +for most targets. +@end deftypefun + +@deftypefun mp_limb_t mpn_submul_1 (mp_limb_t * @var{dest_ptr}, const mp_limb_t * @var{src1_ptr}, mp_size_t @var{size}, mp_limb_t @var{src2_limb}) +Multiply @{@var{src1_ptr}, @var{size}@} and @var{src2_limb}, and subtract the +@var{size} least significant limbs of the product from @{@var{dest_ptr}, +@var{size}@} and write the result to @var{dest_ptr}. Return the most +significant limb of the product, minus borrow-out from the subtraction. + +This is a low-level function that is a building block for general +multiplication and division as well as other operations in MP. It is written +in assembly for most targets. +@end deftypefun + +@deftypefun mp_limb_t mpn_mul (mp_limb_t * @var{dest_ptr}, const mp_limb_t * @var{src1_ptr}, mp_size_t @var{src1_size}, const mp_limb_t * @var{src2_ptr}, mp_size_t @var{src2_size}) +Multiply @{@var{src1_ptr}, @var{src1_size}@} and @{@var{src2_ptr}, +@var{src2_size}@}, and write the result to @var{dest_ptr}. Return the most +significant limb of the result. + +The destination has to have space for @var{src1_size} + @var{src1_size} +limbs, even if the result might be one limb smaller. + +This function requires that @var{src1_size} is greater than or equal to +@var{src2_size}. The destination must be distinct from either input operands. +@end deftypefun + +@deftypefun mp_size_t mpn_divrem (mp_limb_t * @var{r1p}, mp_size_t @var{xsize}, mp_limb_t * @var{rs2p}, mp_size_t @var{rs2size}, const mp_limb_t * @var{s3p}, mp_size_t @var{s3size}) +Divide @{@var{rs2p}, @var{rs2size}@} by @{@var{s3p}, @var{s3size}@}, and +write the quotient at @var{r1p}, with the exception of the most significant +limb, which is returned. The remainder replaces the dividend at @var{rs2p}. + +In addition to an integer quotient, @var{xsize} fraction limbs are developed, +and stored after the integral limbs. For most usages, @var{xsize} will be +zero. + +It is required that @var{rs2size} is greater than or equal to @var{s3size}. +It is required that the most significant bit of the divisor is set. + +If the quotient is not needed, pass @var{rs2p} + @var{s3size} as @var{r1p}. +Aside from that special case, no overlap between arguments is permitted. + +Return the most significant limb of the quotient, either 0 or 1. + +The area at @var{r1p} needs to be @var{rs2size} @minus{} @var{s3size} + +@var{xsize} limbs large. +@end deftypefun + +@deftypefun mp_limb_t mpn_divrem_1 (mp_limb_t * @var{r1p}, mp_size_t @var{xsize}, mp_limb_t * @var{s2p}, mp_size_t @var{s2size}, mp_limb_t @var{s3limb}) +Divide @{@var{s2p}, @var{s2size}@} by @var{s3limb}, and write the quotient +at @var{r1p}. Return the remainder. + +In addition to an integer quotient, @var{xsize} fraction limbs are developed, +and stored after the integral limbs. For most usages, @var{xsize} will be +zero. + +The areas at @var{r1p} and @var{s2p} have to be identical or completely +separate, not partially overlapping. +@end deftypefun + +@deftypefun mp_size_t mpn_divmod (mp_limb_t * @var{r1p}, mp_limb_t * @var{rs2p}, mp_size_t @var{rs2size}, const mp_limb_t * @var{s3p}, mp_size_t @var{s3size}) +@strong{This interface is obsolete. It will disappear from future releases. +Use @code{mpn_divrem} in its stead.} +@end deftypefun + +@deftypefun mp_limb_t mpn_divmod_1 (mp_limb_t * @var{r1p}, mp_limb_t * @var{s2p}, mp_size_t @var{s2size}, mp_limb_t @var{s3limb}) +@strong{This interface is obsolete. It will disappear from future releases. +Use @code{mpn_divrem_1} in its stead.} +@end deftypefun + +@deftypefun mp_limb_t mpn_mod_1 (mp_limb_t * @var{s1p}, mp_size_t @var{s1size}, mp_limb_t @var{s2limb}) +Divide @{@var{s1p}, @var{s1size}@} by @var{s2limb}, and return the remainder. +@end deftypefun + +@deftypefun mp_limb_t mpn_preinv_mod_1 (mp_limb_t * @var{s1p}, mp_size_t @var{s1size}, mp_limb_t @var{s2limb}, mp_limb_t @var{s3limb}) +@strong{This interface is obsolete. It will disappear from future releases. +Use @code{mpn_mod_1} in its stead.} +@end deftypefun + +@deftypefun mp_limb_t mpn_bdivmod (mp_limb_t * @var{dest_ptr}, mp_limb_t * @var{s1p}, mp_size_t @var{s1size}, const mp_limb_t * @var{s2p}, mp_size_t @var{s2size}, unsigned long int @var{d}) +The function puts the low [@var{d}/@var{BITS_PER_MP_LIMB}] limbs of +@var{q} = +@{@var{s1p}, @var{s1size}@}/@{@var{s2p}, @var{s2size}@} +mod 2^@var{d} +at @var{dest_ptr}, +and returns the high @var{d} mod @var{BITS_PER_MP_LIMB} bits of @var{q}. + +@{@var{s1p}, @var{s1size}@} - @var{q} * @{@var{s2p}, @var{s2size}@} +mod 2^(@var{s1size}*@var{BITS_PER_MP_LIMB}) +is placed at @var{s1p}. +Since the low [@var{d}/@var{BITS_PER_MP_LIMB}] limbs of +this difference are zero, it is possible to overwrite the low limbs at +@var{s1p} with this difference, +provided @var{dest_ptr} <= @var{s1p}. + +This function requires that @var{s1size} * @var{BITS_PER_MP_LIMB} >= @var{D}, +and that @{@var{s2p}, @var{s2size}@} is odd. + +@strong{This interface is preliminary. It might change incompatibly in +future revisions.} +@end deftypefun + +@deftypefun mp_limb_t mpn_lshift (mp_limb_t * @var{dest_ptr}, const mp_limb_t * @var{src_ptr}, mp_size_t @var{src_size}, unsigned long int @var{count}) +Shift @{@var{src_ptr}, @var{src_size}@} @var{count} bits to the left, and +write the @var{src_size} least significant limbs of the result to +@var{dest_ptr}. @var{count} might be in the range 1 to n @minus{} 1, on an +n-bit machine. The bits shifted out to the left are returned. + +Overlapping of the destination space and the source space is allowed in this +function, provided @var{dest_ptr} >= @var{src_ptr}. + +This function is written in assembly for most targets. +@end deftypefun + +@deftypefun mp_limp_t mpn_rshift (mp_limb_t * @var{dest_ptr}, const mp_limb_t * @var{src_ptr}, mp_size_t @var{src_size}, unsigned long int @var{count}) +Shift @{@var{src_ptr}, @var{src_size}@} @var{count} bits to the right, and +write the @var{src_size} most significant limbs of the result to +@var{dest_ptr}. @var{count} might be in the range 1 to n @minus{} 1, on an +n-bit machine. The bits shifted out to the right are returned. + +Overlapping of the destination space and the source space is allowed in this +function, provided @var{dest_ptr} <= @var{src_ptr}. + +This function is written in assembly for most targets. +@end deftypefun + +@deftypefun int mpn_cmp (const mp_limb_t * @var{src1_ptr}, const mp_limb_t * @var{src2_ptr}, mp_size_t @var{size}) +Compare @{@var{src1_ptr}, @var{size}@} and @{@var{src2_ptr}, @var{size}@} and +return a positive value if src1 > src2, 0 of they are equal, and a negative +value if src1 < src2. +@end deftypefun + +@deftypefun mp_size_t mpn_gcd (mp_limb_t * @var{dest_ptr}, mp_limb_t * @var{src1_ptr}, mp_size_t @var{src1_size}, mp_limb_t * @var{src2_ptr}, mp_size_t @var{src2_size}) +Puts at @var{dest_ptr} the greatest common divisor of @{@var{src1_ptr}, +@var{src1_size}@} and @{@var{src2_ptr}, @var{src2_size}@}; both source +operands are destroyed by the operation. The size in limbs of the greatest +common divisor is returned. + +@{@var{src1_ptr}, @var{src1_size}@} must be odd, and @{@var{src2_ptr}, +@var{src2_size}@} must have at least as many bits as @{@var{src1_ptr}, +@var{src1_size}@}. + +@strong{This interface is preliminary. It might change incompatibly in +future revisions.} +@end deftypefun + +@deftypefun mp_limb_t mpn_gcd_1 (const mp_limb_t * @var{src1_ptr}, mp_size_t @var{src1_size}, mp_limb_t @var{src2_limb}) +Return the greatest common divisor of @{@var{src1_ptr}, @var{src1_size}@} +and @var{src2_limb}, where @var{src2_limb} (as well as @var{src1_size}) +must be different from 0. +@end deftypefun + +@deftypefun mp_size_t mpn_gcdext (mp_limb_t * @var{r1p}, mp_limb_t * @var{r2p}, mp_limb_t * @var{s1p}, mp_size_t @var{s1size}, mp_limb_t * @var{s2p}, mp_size_t @var{s2size}) +Puts at @var{r1p} the greatest common divisor of @{@var{s1p}, @var{s1size}@} +and @{@var{s2p}, @var{s2size}@}. The first cofactor is written at +@var{r2p}. Both source operands are destroyed by the operation. The size +in limbs of the greatest common divisor is returned. + +@strong{This interface is preliminary. It might change incompatibly in +future revisions.} +@end deftypefun + +@deftypefun mp_size_t mpn_sqrtrem (mp_limb_t * @var{r1p}, mp_limb_t * @var{r2p}, const mp_limb_t * @var{sp}, mp_size_t @var{size}) +Compute the square root of @{@var{sp}, @var{size}@} and put the result at +@var{r1p}. Write the remainder at @var{r2p}, unless @var{r2p} is NULL. + +Return the size of the remainder, whether @var{r2p} was NULL or non-NULL. +Iff the operand was a perfect square, the return value will be 0. + +The areas at @var{r1p} and @var{sp} have to be distinct. The areas at +@var{r2p} and @var{sp} have to be identical or completely separate, not +partially overlapping. + +@ifinfo +The area at @var{r1p} needs to have space for ceil(@var{size}/2) limbs. +@end ifinfo +@iftex +@tex +The area at @var{r1p} needs to have space for $\lceil@var{size}/2\rceil$ limbs. +@end tex +@end iftex +The area at @var{r2p} needs to be @var{size} limbs large. + +@strong{This interface is preliminary. It might change incompatibly in +future revisions.} +@end deftypefun + +@deftypefun mp_size_t mpn_get_str (unsigned char *@var{str}, int @var{base}, mp_limb_t * @var{s1p}, mp_size_t @var{s1size}) +Convert @{@var{s1p}, @var{s1size}@} to a raw unsigned char array in base +@var{base}. The string is not in ASCII; to convert it to printable format, +add the ASCII codes for @samp{0} or @samp{A}, depending on the base and +range. There may be leading zeros in the string. + +The area at @var{s1p} is clobbered. + +Return the number of characters in @var{str}. + +The area at @var{str} has to have space for the largest possible number +represented by a @var{s1size} long limb array, plus one extra character. +@end deftypefun + +@deftypefun mp_size_t mpn_set_str (mp_limb_t * @var{r1p}, const char *@var{str}, size_t {strsize}, int @var{base}) +Convert the raw unsigned char array at @var{str} of length @var{strsize} to +a limb array @{@var{s1p}, @var{s1size}@}. The base of @var{str} is +@var{base}. + +Return the number of limbs stored in @var{r1p}. +@end deftypefun + +@deftypefun {unsigned long int} mpn_scan0 (const mp_limb_t * @var{s1p}, unsigned long int @var{bit}) +Scan @var{s1p} from bit position @var{bit} for the next clear bit. + +It is required that there be a clear bit within the area at @var{s1p} at or +beyond bit position @var{bit}, so that the function has something to return. + +@strong{This interface is preliminary. It might change incompatibly in +future revisions.} +@end deftypefun + +@deftypefun {unsigned long int} mpn_scan1 (const mp_limb_t * @var{s1p}, unsigned long int @var{bit}) +Scan @var{s1p} from bit position @var{bit} for the next set bit. + +It is required that there be a set bit within the area at @var{s1p} at or +beyond bit position @var{bit}, so that the function has something to return. + +@strong{This interface is preliminary. It might change incompatibly in +future revisions.} +@end deftypefun + +@deftypefun void mpn_random2 (mp_limb_t * @var{r1p}, mp_size_t @var{r1size}) +Generate a random number of length @var{r1size} with long strings of zeros +and ones in the binary representation, and store it at @var{r1p}. + +The generated random numbers are intended for testing the correctness of the +implementation of the @code{mpn} routines. +@end deftypefun + +@deftypefun {unsigned long int} mpn_popcount (const mp_limb_t * @var{s1p}, unsigned long int @var{size}) +Count the number of set bits in @{@var{s1p}, @var{size}@}. +@end deftypefun + +@deftypefun {unsigned long int} mpn_hamdist (const mp_limb_t * @var{s1p}, const mp_limb_t * @var{s2p}, unsigned long int @var{size}) +Compute the hamming distance between @{@var{s1p}, @var{size}@} and +@{@var{s2p}, @var{size}@}. +@end deftypefun + +@deftypefun int mpn_perfect_square_p (const mp_limb_t * @var{s1p}, mp_size_t @var{size}) +Return non-zero iff @{@var{s1p}, @var{size}@} is a perfect square. +@end deftypefun + + +@node BSD Compatible Functions, Custom Allocation, Low-level Functions, Top +@comment node-name, next, previous, up +@chapter Berkeley MP Compatible Functions +@cindex BSD MP compatible functions + +These functions are intended to be fully compatible with the Berkeley MP +library which is available on many BSD derived U*ix systems. + +The original Berkeley MP library has a usage restriction: you cannot use the +same variable as both source and destination in a single function call. The +compatible functions in GNU MP do not share this restriction---inputs and +outputs may overlap. + +It is not recommended that new programs are written using these functions. +Apart from the incomplete set of functions, the interface for initializing +@code{MINT} objects is more error prone, and the @code{pow} function collides +with @code{pow} in @file{libm.a}. + +@cindex @file{mp.h} +Include the header @file{mp.h} to get the definition of the necessary types +and functions. If you are on a BSD derived system, make sure to include GNU +@file{mp.h} if you are going to link the GNU @file{libmp.a} to you program. +This means that you probably need to give the -I<dir> option to the compiler, +where <dir> is the directory where you have GNU @file{mp.h}. + +@deftypefun {MINT *} itom (signed short int @var{initial_value}) +Allocate an integer consisting of a @code{MINT} object and dynamic limb space. +Initialize the integer to @var{initial_value}. Return a pointer to the +@code{MINT} object. +@end deftypefun + +@deftypefun {MINT *} xtom (char *@var{initial_value}) +Allocate an integer consisting of a @code{MINT} object and dynamic limb space. +Initialize the integer from @var{initial_value}, a hexadecimal, '\0'-terminate +C string. Return a pointer to the @code{MINT} object. +@end deftypefun + +@deftypefun void move (MINT *@var{src}, MINT *@var{dest}) +Set @var{dest} to @var{src} by copying. Both variables must be previously +initialized. +@end deftypefun + +@deftypefun void madd (MINT *@var{src_1}, MINT *@var{src_2}, MINT *@var{destination}) +Add @var{src_1} and @var{src_2} and put the sum in @var{destination}. +@end deftypefun + +@deftypefun void msub (MINT *@var{src_1}, MINT *@var{src_2}, MINT *@var{destination}) +Subtract @var{src_2} from @var{src_1} and put the difference in +@var{destination}. +@end deftypefun + +@deftypefun void mult (MINT *@var{src_1}, MINT *@var{src_2}, MINT *@var{destination}) +Multiply @var{src_1} and @var{src_2} and put the product in +@var{destination}. +@end deftypefun + +@deftypefun void mdiv (MINT *@var{dividend}, MINT *@var{divisor}, MINT *@var{quotient}, MINT *@var{remainder}) +@deftypefunx void sdiv (MINT *@var{dividend}, signed short int @var{divisor}, MINT *@var{quotient}, signed short int *@var{remainder}) +Set @var{quotient} to @var{dividend}/@var{divisor}, and @var{remainder} to +@var{dividend} mod @var{divisor}. The quotient is rounded towards zero; the +remainder has the same sign as the dividend unless it is zero. + +Some implementations of these functions work differently---or not at all---for +negative arguments. +@end deftypefun + +@deftypefun void msqrt (MINT *@var{operand}, MINT *@var{root}, MINT *@var{remainder}) +@ifinfo +Set @var{root} to the truncated integer part of the square root of +@var{operand}. Set @var{remainder} to +@var{operand}@minus{}@var{root}*@var{root}, +@end ifinfo +@iftex +@tex +Set @var{root} to $\lfloor\sqrt{@var{operand}}\rfloor$, like +@code{mpz_sqrt}. Set @var{remainder} to $(operand - root^2)$, +@end tex +@end iftex +(i.e., zero if @var{operand} is a perfect square). + +If @var{root} and @var{remainder} are the same variable, the results are +undefined. +@end deftypefun + +@deftypefun void pow (MINT *@var{base}, MINT *@var{exp}, MINT *@var{mod}, MINT *@var{dest}) +Set @var{dest} to (@var{base} raised to @var{exp}) modulo @var{mod}. +@end deftypefun + +@deftypefun void rpow (MINT *@var{base}, signed short int @var{exp}, MINT *@var{dest}) +Set @var{dest} to @var{base} raised to @var{exp}. +@end deftypefun + +@deftypefun void gcd (MINT *@var{operand1}, MINT *@var{operand2}, MINT *@var{res}) +Set @var{res} to the greatest common divisor of @var{operand1} and +@var{operand2}. +@end deftypefun + +@deftypefun int mcmp (MINT *@var{operand1}, MINT *@var{operand2}) +Compare @var{operand1} and @var{operand2}. Return a positive value if +@var{operand1} > @var{operand2}, zero if @var{operand1} = +@var{operand2}, and a negative value if @var{operand1} < @var{operand2}. +@end deftypefun + +@deftypefun void min (MINT *@var{dest}) +Input a decimal string from @code{stdin}, and put the read integer in +@var{dest}. SPC and TAB are allowed in the number string, and are ignored. +@end deftypefun + +@deftypefun void mout (MINT *@var{src}) +Output @var{src} to @code{stdout}, as a decimal string. Also output a newline. +@end deftypefun + +@deftypefun {char *} mtox (MINT *@var{operand}) +Convert @var{operand} to a hexadecimal string, and return a pointer to the +string. The returned string is allocated using the default memory allocation +function, @code{malloc} by default. +@end deftypefun + +@deftypefun void mfree (MINT *@var{operand}) +De-allocate, the space used by @var{operand}. @strong{This function should +only be passed a value returned by @code{itom} or @code{xtom}.} +@end deftypefun + +@node Custom Allocation, Contributors, BSD Compatible Functions, Top +@comment node-name, next, previous, up +@chapter Custom Allocation + +By default, the MP functions use @code{malloc}, @code{realloc}, and +@code{free} for memory allocation. If @code{malloc} or @code{realloc} fails, +the MP library terminates execution after printing a fatal error message to +standard error. + +For some applications, you may wish to allocate memory in other ways, or you +may not want to have a fatal error when there is no more memory available. To +accomplish this, you can specify alternative memory allocation functions. + +@deftypefun void mp_set_memory_functions (@* void *(*@var{alloc_func_ptr}) (size_t), @* void *(*@var{realloc_func_ptr}) (void *, size_t, size_t), @* void (*@var{free_func_ptr}) (void *, size_t)) +Replace the current allocation functions from the arguments. If an argument +is NULL, the corresponding default function is retained. + +@strong{Make sure to call this function in such a way that there are no active +MP objects that were allocated using the previously active allocation +function! Usually, that means that you have to call this function before any +other MP function.} +@end deftypefun + +The functions you supply should fit the following declarations: + +@deftypefun {void *} allocate_function (size_t @var{alloc_size}) +This function should return a pointer to newly allocated space with at least +@var{alloc_size} storage units. +@end deftypefun + +@deftypefun {void *} reallocate_function (void *@var{ptr}, size_t @var{old_size}, size_t @var{new_size}) +This function should return a pointer to newly allocated space of at least +@var{new_size} storage units, after copying at least the first @var{old_size} +storage units from @var{ptr}. It should also de-allocate the space at +@var{ptr}. + +You can assume that the space at @var{ptr} was formerly returned from +@code{allocate_function} or @code{reallocate_function}, for a request for +@var{old_size} storage units. +@end deftypefun + +@deftypefun void deallocate_function (void *@var{ptr}, size_t @var{size}) +De-allocate the space pointed to by @var{ptr}. + +You can assume that the space at @var{ptr} was formerly returned from +@code{allocate_function} or @code{reallocate_function}, for a request for +@var{size} storage units. +@end deftypefun + +(A @dfn{storage unit} is the unit in which the @code{sizeof} operator returns +the size of an object, normally an 8 bit byte.) + + +@node Contributors, References, Custom Allocation, Top +@comment node-name, next, previous, up +@unnumbered Contributors + +I would like to thank Gunnar Sjoedin and Hans Riesel for their help with +mathematical problems, Richard Stallman for his help with design issues and +for revising the first version of this manual, Brian Beuning and Doug Lea for +their testing of early versions of the library. + +John Amanatides of York University in Canada contributed the function +@code{mpz_probab_prime_p}. + +Paul Zimmermann of Inria sparked the development of GMP 2, with his +comparisons between bignum packages. + +Ken Weber (Kent State University, Universidade Federal do Rio Grande do Sul) +contributed @code{mpz_gcd}, @code{mpz_divexact}, @code{mpn_gcd}, and +@code{mpn_bdivmod}, partially supported by CNPq (Brazil) grant 301314194-2. + +Per Bothner of Cygnus Support helped to set up MP to use Cygnus' configure. +He has also made valuable suggestions and tested numerous intermediary +releases. + +Joachim Hollman was involved in the design of the @code{mpf} interface, and in +the @code{mpz} design revisions for version 2. + +Bennet Yee contributed the functions @code{mpz_jacobi} and +@code{mpz_legendre}. + +Andreas Schwab contributed the files @file{mpn/m68k/lshift.S} and +@file{mpn/m68k/rshift.S}. + +The development of floating point functions of GNU MP 2, were supported in +part by the ESPRIT-BRA (Basic Research Activities) 6846 project POSSO +(POlynomial System SOlving). + +GNU MP 2 was finished and released by TMG Datakonsult, Sodermannagatan 5, 116 +23 STOCKHOLM, SWEDEN, in cooperation with the IDA Center for Computing +Sciences, USA. + + +@node References, , Contributors, Top +@comment node-name, next, previous, up +@unnumbered References + +@itemize @bullet + +@item +Donald E. Knuth, "The Art of Computer Programming", vol 2, +"Seminumerical Algorithms", 2nd edition, Addison-Wesley, 1981. + +@item +John D. Lipson, "Elements of Algebra and Algebraic Computing", +The Benjamin Cummings Publishing Company Inc, 1981. + +@item +Richard M. Stallman, "Using and Porting GCC", Free Software Foundation, +1995. + +@item +Peter L. Montgomery, "Modular Multiplication Without Trial Division", in +Mathematics of Computation, volume 44, number 170, April 1985. + +@item +Torbjorn Granlund and Peter L. Montgomery, "Division by Invariant +Integers using Multiplication", in Proceedings of the SIGPLAN +PLDI'94 Conference, June 1994. + +@item +Tudor Jebelean, +"An algorithm for exact division", +Journal of Symbolic Computation, +v. 15, 1993, pp. 169-180. + +@item +Kenneth Weber, "The accelerated integer GCD algorithm", +ACM Transactions on Mathematical Software, +v. 21 (March), 1995, pp. 111-122. +@end itemize + +@node Concept Index, , , Top +@comment node-name, next, previous, up +@unnumbered Concept Index +@printindex cp + +@node Function Index, , , Top +@comment node-name, next, previous, up +@unnumbered Function and Type Index +@printindex fn + + +@contents +@bye diff --git a/contrib/libgmp/insert-double.c b/contrib/libgmp/insert-double.c new file mode 100644 index 0000000..1ce2571 --- /dev/null +++ b/contrib/libgmp/insert-double.c @@ -0,0 +1,70 @@ +/* __gmp_insert_double -- convert from array of mp_limb_t to double. + +Copyright (C) 1996 Free Software Foundation, Inc. + +This file is part of the GNU MP Library. + +The GNU MP Library is free software; you can redistribute it and/or modify +it under the terms of the GNU Library General Public License as published by +the Free Software Foundation; either version 2 of the License, or (at your +option) any later version. + +The GNU MP Library is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public +License for more details. + +You should have received a copy of the GNU Library General Public License +along with the GNU MP Library; see the file COPYING.LIB. If not, write to +the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, +MA 02111-1307, USA. */ + +#include "gmp.h" +#include "gmp-impl.h" + +#ifdef XDEBUG +#undef _GMP_IEEE_FLOATS +#endif + +#ifndef _GMP_IEEE_FLOATS +#define _GMP_IEEE_FLOATS 0 +#endif + +double +#if __STDC__ +__gmp_scale2 (double d, int exp) +#else +__gmp_scale2 (d, exp) + double d; + int exp; +#endif +{ +#if _GMP_IEEE_FLOATS + { + union ieee_double_extract x; + x.d = d; + x.s.exp += exp; + return x.d; + } +#else + { + double factor, r; + + factor = 2.0; + if (exp < 0) + { + factor = 0.5; + exp = -exp; + } + r = d; + while (exp != 0) + { + if ((exp & 1) != 0) + r *= factor; + factor *= factor; + exp >>= 1; + } + return r; + } +#endif +} diff --git a/contrib/libgmp/install.sh b/contrib/libgmp/install.sh new file mode 100755 index 0000000..5871924 --- /dev/null +++ b/contrib/libgmp/install.sh @@ -0,0 +1,238 @@ +#! /bin/sh +# +# install - install a program, script, or datafile +# This comes from X11R5. +# +# Calling this script install-sh is preferred over install.sh, to prevent +# `make' implicit rules from creating a file called install from it +# when there is no Makefile. +# +# This script is compatible with the BSD install script, but was written +# from scratch. +# + + +# set DOITPROG to echo to test this script + +# Don't use :- since 4.3BSD and earlier shells don't like it. +doit="${DOITPROG-}" + + +# put in absolute paths if you don't have them in your path; or use env. vars. + +mvprog="${MVPROG-mv}" +cpprog="${CPPROG-cp}" +chmodprog="${CHMODPROG-chmod}" +chownprog="${CHOWNPROG-chown}" +chgrpprog="${CHGRPPROG-chgrp}" +stripprog="${STRIPPROG-strip}" +rmprog="${RMPROG-rm}" +mkdirprog="${MKDIRPROG-mkdir}" + +transformbasename="" +transform_arg="" +instcmd="$mvprog" +chmodcmd="$chmodprog 0755" +chowncmd="" +chgrpcmd="" +stripcmd="" +rmcmd="$rmprog -f" +mvcmd="$mvprog" +src="" +dst="" +dir_arg="" + +while [ x"$1" != x ]; do + case $1 in + -c) instcmd="$cpprog" + shift + continue;; + + -d) dir_arg=true + shift + continue;; + + -m) chmodcmd="$chmodprog $2" + shift + shift + continue;; + + -o) chowncmd="$chownprog $2" + shift + shift + continue;; + + -g) chgrpcmd="$chgrpprog $2" + shift + shift + continue;; + + -s) stripcmd="$stripprog" + shift + continue;; + + -t=*) transformarg=`echo $1 | sed 's/-t=//'` + shift + continue;; + + -b=*) transformbasename=`echo $1 | sed 's/-b=//'` + shift + continue;; + + *) if [ x"$src" = x ] + then + src=$1 + else + # this colon is to work around a 386BSD /bin/sh bug + : + dst=$1 + fi + shift + continue;; + esac +done + +if [ x"$src" = x ] +then + echo "install: no input file specified" + exit 1 +else + true +fi + +if [ x"$dir_arg" != x ]; then + dst=$src + src="" + + if [ -d $dst ]; then + instcmd=: + else + instcmd=mkdir + fi +else + +# Waiting for this to be detected by the "$instcmd $src $dsttmp" command +# might cause directories to be created, which would be especially bad +# if $src (and thus $dsttmp) contains '*'. + + if [ -f $src -o -d $src ] + then + true + else + echo "install: $src does not exist" + exit 1 + fi + + if [ x"$dst" = x ] + then + echo "install: no destination specified" + exit 1 + else + true + fi + +# If destination is a directory, append the input filename; if your system +# does not like double slashes in filenames, you may need to add some logic + + if [ -d $dst ] + then + dst="$dst"/`basename $src` + else + true + fi +fi + +## this sed command emulates the dirname command +dstdir=`echo $dst | sed -e 's,[^/]*$,,;s,/$,,;s,^$,.,'` + +# Make sure that the destination directory exists. +# this part is taken from Noah Friedman's mkinstalldirs script + +# Skip lots of stat calls in the usual case. +if [ ! -d "$dstdir" ]; then +defaultIFS=' +' +IFS="${IFS-${defaultIFS}}" + +oIFS="${IFS}" +# Some sh's can't handle IFS=/ for some reason. +IFS='%' +set - `echo ${dstdir} | sed -e 's@/@%@g' -e 's@^%@/@'` +IFS="${oIFS}" + +pathcomp='' + +while [ $# -ne 0 ] ; do + pathcomp="${pathcomp}${1}" + shift + + if [ ! -d "${pathcomp}" ] ; + then + $mkdirprog "${pathcomp}" + else + true + fi + + pathcomp="${pathcomp}/" +done +fi + +if [ x"$dir_arg" != x ] +then + $doit $instcmd $dst && + + if [ x"$chowncmd" != x ]; then $doit $chowncmd $dst; else true ; fi && + if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd $dst; else true ; fi && + if [ x"$stripcmd" != x ]; then $doit $stripcmd $dst; else true ; fi && + if [ x"$chmodcmd" != x ]; then $doit $chmodcmd $dst; else true ; fi +else + +# If we're going to rename the final executable, determine the name now. + + if [ x"$transformarg" = x ] + then + dstfile=`basename $dst` + else + dstfile=`basename $dst $transformbasename | + sed $transformarg`$transformbasename + fi + +# don't allow the sed command to completely eliminate the filename + + if [ x"$dstfile" = x ] + then + dstfile=`basename $dst` + else + true + fi + +# Make a temp file name in the proper directory. + + dsttmp=$dstdir/#inst.$$# + +# Move or copy the file name to the temp name + + $doit $instcmd $src $dsttmp && + + trap "rm -f ${dsttmp}" 0 && + +# and set any options; do chmod last to preserve setuid bits + +# If any of these fail, we abort the whole thing. If we want to +# ignore errors from any of these, just make sure not to ignore +# errors from the above "$doit $instcmd $src $dsttmp" command. + + if [ x"$chowncmd" != x ]; then $doit $chowncmd $dsttmp; else true;fi && + if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd $dsttmp; else true;fi && + if [ x"$stripcmd" != x ]; then $doit $stripcmd $dsttmp; else true;fi && + if [ x"$chmodcmd" != x ]; then $doit $chmodcmd $dsttmp; else true;fi && + +# Now rename the file to the real destination. + + $doit $rmcmd -f $dstdir/$dstfile && + $doit $mvcmd $dsttmp $dstdir/$dstfile + +fi && + + +exit 0 diff --git a/contrib/libgmp/longlong.h b/contrib/libgmp/longlong.h new file mode 100644 index 0000000..382fcc0 --- /dev/null +++ b/contrib/libgmp/longlong.h @@ -0,0 +1,1404 @@ +/* longlong.h -- definitions for mixed size 32/64 bit arithmetic. + +Copyright (C) 1991, 1992, 1993, 1994, 1996 Free Software Foundation, Inc. + +This file is free software; you can redistribute it and/or modify +it under the terms of the GNU Library General Public License as published by +the Free Software Foundation; either version 2 of the License, or (at your +option) any later version. + +This file is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public +License for more details. + +You should have received a copy of the GNU Library General Public License +along with this file; see the file COPYING.LIB. If not, write to +the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, +MA 02111-1307, USA. */ + +/* You have to define the following before including this file: + + UWtype -- An unsigned type, default type for operations (typically a "word") + UHWtype -- An unsigned type, at least half the size of UWtype. + UDWtype -- An unsigned type, at least twice as large a UWtype + W_TYPE_SIZE -- size in bits of UWtype + + SItype, USItype -- Signed and unsigned 32 bit types. + DItype, UDItype -- Signed and unsigned 64 bit types. + + On a 32 bit machine UWtype should typically be USItype; + on a 64 bit machine, UWtype should typically be UDItype. +*/ + +#define __BITS4 (W_TYPE_SIZE / 4) +#define __ll_B ((UWtype) 1 << (W_TYPE_SIZE / 2)) +#define __ll_lowpart(t) ((UWtype) (t) & (__ll_B - 1)) +#define __ll_highpart(t) ((UWtype) (t) >> (W_TYPE_SIZE / 2)) + +/* This is used to make sure no undesirable sharing between different libraries + that use this file takes place. */ +#ifndef __MPN +#define __MPN(x) __##x +#endif + +/* Define auxiliary asm macros. + + 1) umul_ppmm(high_prod, low_prod, multipler, multiplicand) multiplies two + UWtype integers MULTIPLER and MULTIPLICAND, and generates a two UWtype + word product in HIGH_PROD and LOW_PROD. + + 2) __umulsidi3(a,b) multiplies two UWtype integers A and B, and returns a + UDWtype product. This is just a variant of umul_ppmm. + + 3) udiv_qrnnd(quotient, remainder, high_numerator, low_numerator, + denominator) divides a UDWtype, composed by the UWtype integers + HIGH_NUMERATOR and LOW_NUMERATOR, by DENOMINATOR and places the quotient + in QUOTIENT and the remainder in REMAINDER. HIGH_NUMERATOR must be less + than DENOMINATOR for correct operation. If, in addition, the most + significant bit of DENOMINATOR must be 1, then the pre-processor symbol + UDIV_NEEDS_NORMALIZATION is defined to 1. + + 4) sdiv_qrnnd(quotient, remainder, high_numerator, low_numerator, + denominator). Like udiv_qrnnd but the numbers are signed. The quotient + is rounded towards 0. + + 5) count_leading_zeros(count, x) counts the number of zero-bits from the + msb to the first non-zero bit in the UWtype X. This is the number of + steps X needs to be shifted left to set the msb. Undefined for X == 0, + unless the symbol COUNT_LEADING_ZEROS_0 is defined to some value. + + 6) count_trailing_zeros(count, x) like count_leading_zeros, but counts + from the least significant end. + + 7) add_ssaaaa(high_sum, low_sum, high_addend_1, low_addend_1, + high_addend_2, low_addend_2) adds two UWtype integers, composed by + HIGH_ADDEND_1 and LOW_ADDEND_1, and HIGH_ADDEND_2 and LOW_ADDEND_2 + respectively. The result is placed in HIGH_SUM and LOW_SUM. Overflow + (i.e. carry out) is not stored anywhere, and is lost. + + 8) sub_ddmmss(high_difference, low_difference, high_minuend, low_minuend, + high_subtrahend, low_subtrahend) subtracts two two-word UWtype integers, + composed by HIGH_MINUEND_1 and LOW_MINUEND_1, and HIGH_SUBTRAHEND_2 and + LOW_SUBTRAHEND_2 respectively. The result is placed in HIGH_DIFFERENCE + and LOW_DIFFERENCE. Overflow (i.e. carry out) is not stored anywhere, + and is lost. + + If any of these macros are left undefined for a particular CPU, + C macros are used. */ + +/* The CPUs come in alphabetical order below. + + Please add support for more CPUs here, or improve the current support + for the CPUs below! */ + +#if defined (__GNUC__) && !defined (NO_ASM) + +/* We sometimes need to clobber "cc" with gcc2, but that would not be + understood by gcc1. Use cpp to avoid major code duplication. */ +#if __GNUC__ < 2 +#define __CLOBBER_CC +#define __AND_CLOBBER_CC +#else /* __GNUC__ >= 2 */ +#define __CLOBBER_CC : "cc" +#define __AND_CLOBBER_CC , "cc" +#endif /* __GNUC__ < 2 */ + +#if (defined (__a29k__) || defined (_AM29K)) && W_TYPE_SIZE == 32 +#define add_ssaaaa(sh, sl, ah, al, bh, bl) \ + __asm__ ("add %1,%4,%5 + addc %0,%2,%3" \ + : "=r" ((USItype)(sh)), \ + "=&r" ((USItype)(sl)) \ + : "%r" ((USItype)(ah)), \ + "rI" ((USItype)(bh)), \ + "%r" ((USItype)(al)), \ + "rI" ((USItype)(bl))) +#define sub_ddmmss(sh, sl, ah, al, bh, bl) \ + __asm__ ("sub %1,%4,%5 + subc %0,%2,%3" \ + : "=r" ((USItype)(sh)), \ + "=&r" ((USItype)(sl)) \ + : "r" ((USItype)(ah)), \ + "rI" ((USItype)(bh)), \ + "r" ((USItype)(al)), \ + "rI" ((USItype)(bl))) +#define umul_ppmm(xh, xl, m0, m1) \ + do { \ + USItype __m0 = (m0), __m1 = (m1); \ + __asm__ ("multiplu %0,%1,%2" \ + : "=r" ((USItype)(xl)) \ + : "r" (__m0), \ + "r" (__m1)); \ + __asm__ ("multmu %0,%1,%2" \ + : "=r" ((USItype)(xh)) \ + : "r" (__m0), \ + "r" (__m1)); \ + } while (0) +#define udiv_qrnnd(q, r, n1, n0, d) \ + __asm__ ("dividu %0,%3,%4" \ + : "=r" ((USItype)(q)), \ + "=q" ((USItype)(r)) \ + : "1" ((USItype)(n1)), \ + "r" ((USItype)(n0)), \ + "r" ((USItype)(d))) +#define count_leading_zeros(count, x) \ + __asm__ ("clz %0,%1" \ + : "=r" ((USItype)(count)) \ + : "r" ((USItype)(x))) +#define COUNT_LEADING_ZEROS_0 32 +#endif /* __a29k__ */ + +#if defined (__alpha) && W_TYPE_SIZE == 64 +#define umul_ppmm(ph, pl, m0, m1) \ + do { \ + UDItype __m0 = (m0), __m1 = (m1); \ + __asm__ ("umulh %r1,%2,%0" \ + : "=r" ((UDItype) ph) \ + : "%rJ" (__m0), \ + "rI" (__m1)); \ + (pl) = __m0 * __m1; \ + } while (0) +#define UMUL_TIME 46 +#ifndef LONGLONG_STANDALONE +#define udiv_qrnnd(q, r, n1, n0, d) \ + do { UDItype __r; \ + (q) = __udiv_qrnnd (&__r, (n1), (n0), (d)); \ + (r) = __r; \ + } while (0) +extern UDItype __udiv_qrnnd (); +#define UDIV_TIME 220 +#endif /* LONGLONG_STANDALONE */ +#endif /* __alpha */ + +#if defined (__arm__) && W_TYPE_SIZE == 32 +#define add_ssaaaa(sh, sl, ah, al, bh, bl) \ + __asm__ ("adds %1, %4, %5 + adc %0, %2, %3" \ + : "=r" ((USItype)(sh)), \ + "=&r" ((USItype)(sl)) \ + : "%r" ((USItype)(ah)), \ + "rI" ((USItype)(bh)), \ + "%r" ((USItype)(al)), \ + "rI" ((USItype)(bl))) +#define sub_ddmmss(sh, sl, ah, al, bh, bl) \ + __asm__ ("subs %1, %4, %5 + sbc %0, %2, %3" \ + : "=r" ((USItype)(sh)), \ + "=&r" ((USItype)(sl)) \ + : "r" ((USItype)(ah)), \ + "rI" ((USItype)(bh)), \ + "r" ((USItype)(al)), \ + "rI" ((USItype)(bl))) +#define umul_ppmm(xh, xl, a, b) \ + __asm__ ("%@ Inlined umul_ppmm + mov %|r0, %2, lsr #16 + mov %|r2, %3, lsr #16 + bic %|r1, %2, %|r0, lsl #16 + bic %|r2, %3, %|r2, lsl #16 + mul %1, %|r1, %|r2 + mul %|r2, %|r0, %|r2 + mul %|r1, %0, %|r1 + mul %0, %|r0, %0 + adds %|r1, %|r2, %|r1 + addcs %0, %0, #65536 + adds %1, %1, %|r1, lsl #16 + adc %0, %0, %|r1, lsr #16" \ + : "=&r" ((USItype)(xh)), \ + "=r" ((USItype)(xl)) \ + : "r" ((USItype)(a)), \ + "r" ((USItype)(b)) \ + : "r0", "r1", "r2") +#define UMUL_TIME 20 +#define UDIV_TIME 100 +#endif /* __arm__ */ + +#if defined (__clipper__) && W_TYPE_SIZE == 32 +#define umul_ppmm(w1, w0, u, v) \ + ({union {UDItype __ll; \ + struct {USItype __l, __h;} __i; \ + } __xx; \ + __asm__ ("mulwux %2,%0" \ + : "=r" (__xx.__ll) \ + : "%0" ((USItype)(u)), \ + "r" ((USItype)(v))); \ + (w1) = __xx.__i.__h; (w0) = __xx.__i.__l;}) +#define smul_ppmm(w1, w0, u, v) \ + ({union {DItype __ll; \ + struct {SItype __l, __h;} __i; \ + } __xx; \ + __asm__ ("mulwx %2,%0" \ + : "=r" (__xx.__ll) \ + : "%0" ((SItype)(u)), \ + "r" ((SItype)(v))); \ + (w1) = __xx.__i.__h; (w0) = __xx.__i.__l;}) +#define __umulsidi3(u, v) \ + ({UDItype __w; \ + __asm__ ("mulwux %2,%0" \ + : "=r" (__w) \ + : "%0" ((USItype)(u)), \ + "r" ((USItype)(v))); \ + __w; }) +#endif /* __clipper__ */ + +#if defined (__gmicro__) && W_TYPE_SIZE == 32 +#define add_ssaaaa(sh, sl, ah, al, bh, bl) \ + __asm__ ("add.w %5,%1 + addx %3,%0" \ + : "=g" ((USItype)(sh)), \ + "=&g" ((USItype)(sl)) \ + : "%0" ((USItype)(ah)), \ + "g" ((USItype)(bh)), \ + "%1" ((USItype)(al)), \ + "g" ((USItype)(bl))) +#define sub_ddmmss(sh, sl, ah, al, bh, bl) \ + __asm__ ("sub.w %5,%1 + subx %3,%0" \ + : "=g" ((USItype)(sh)), \ + "=&g" ((USItype)(sl)) \ + : "0" ((USItype)(ah)), \ + "g" ((USItype)(bh)), \ + "1" ((USItype)(al)), \ + "g" ((USItype)(bl))) +#define umul_ppmm(ph, pl, m0, m1) \ + __asm__ ("mulx %3,%0,%1" \ + : "=g" ((USItype)(ph)), \ + "=r" ((USItype)(pl)) \ + : "%0" ((USItype)(m0)), \ + "g" ((USItype)(m1))) +#define udiv_qrnnd(q, r, nh, nl, d) \ + __asm__ ("divx %4,%0,%1" \ + : "=g" ((USItype)(q)), \ + "=r" ((USItype)(r)) \ + : "1" ((USItype)(nh)), \ + "0" ((USItype)(nl)), \ + "g" ((USItype)(d))) +#define count_leading_zeros(count, x) \ + __asm__ ("bsch/1 %1,%0" \ + : "=g" (count) \ + : "g" ((USItype)(x)), \ + "0" ((USItype)0)) +#endif + +#if defined (__hppa) && W_TYPE_SIZE == 32 +#define add_ssaaaa(sh, sl, ah, al, bh, bl) \ + __asm__ ("add %4,%5,%1 + addc %2,%3,%0" \ + : "=r" ((USItype)(sh)), \ + "=&r" ((USItype)(sl)) \ + : "%rM" ((USItype)(ah)), \ + "rM" ((USItype)(bh)), \ + "%rM" ((USItype)(al)), \ + "rM" ((USItype)(bl))) +#define sub_ddmmss(sh, sl, ah, al, bh, bl) \ + __asm__ ("sub %4,%5,%1 + subb %2,%3,%0" \ + : "=r" ((USItype)(sh)), \ + "=&r" ((USItype)(sl)) \ + : "rM" ((USItype)(ah)), \ + "rM" ((USItype)(bh)), \ + "rM" ((USItype)(al)), \ + "rM" ((USItype)(bl))) +#if defined (_PA_RISC1_1) +#define umul_ppmm(wh, wl, u, v) \ + do { \ + union {UDItype __ll; \ + struct {USItype __h, __l;} __i; \ + } __xx; \ + __asm__ ("xmpyu %1,%2,%0" \ + : "=*f" (__xx.__ll) \ + : "*f" ((USItype)(u)), \ + "*f" ((USItype)(v))); \ + (wh) = __xx.__i.__h; \ + (wl) = __xx.__i.__l; \ + } while (0) +#define UMUL_TIME 8 +#define UDIV_TIME 60 +#else +#define UMUL_TIME 40 +#define UDIV_TIME 80 +#endif +#ifndef LONGLONG_STANDALONE +#define udiv_qrnnd(q, r, n1, n0, d) \ + do { USItype __r; \ + (q) = __udiv_qrnnd (&__r, (n1), (n0), (d)); \ + (r) = __r; \ + } while (0) +extern USItype __udiv_qrnnd (); +#endif /* LONGLONG_STANDALONE */ +#define count_leading_zeros(count, x) \ + do { \ + USItype __tmp; \ + __asm__ ( \ + "ldi 1,%0 + extru,= %1,15,16,%%r0 ; Bits 31..16 zero? + extru,tr %1,15,16,%1 ; No. Shift down, skip add. + ldo 16(%0),%0 ; Yes. Perform add. + extru,= %1,23,8,%%r0 ; Bits 15..8 zero? + extru,tr %1,23,8,%1 ; No. Shift down, skip add. + ldo 8(%0),%0 ; Yes. Perform add. + extru,= %1,27,4,%%r0 ; Bits 7..4 zero? + extru,tr %1,27,4,%1 ; No. Shift down, skip add. + ldo 4(%0),%0 ; Yes. Perform add. + extru,= %1,29,2,%%r0 ; Bits 3..2 zero? + extru,tr %1,29,2,%1 ; No. Shift down, skip add. + ldo 2(%0),%0 ; Yes. Perform add. + extru %1,30,1,%1 ; Extract bit 1. + sub %0,%1,%0 ; Subtract it. + " : "=r" (count), "=r" (__tmp) : "1" (x)); \ + } while (0) +#endif /* hppa */ + +#if (defined (__i370__) || defined (__mvs__)) && W_TYPE_SIZE == 32 +#define umul_ppmm(xh, xl, m0, m1) \ + do { \ + union {UDItype __ll; \ + struct {USItype __h, __l;} __i; \ + } __xx; \ + USItype __m0 = (m0), __m1 = (m1); \ + __asm__ ("mr %0,%3" \ + : "=r" (__xx.__i.__h), \ + "=r" (__xx.__i.__l) \ + : "%1" (__m0), \ + "r" (__m1)); \ + (xh) = __xx.__i.__h; (xl) = __xx.__i.__l; \ + (xh) += ((((SItype) __m0 >> 31) & __m1) \ + + (((SItype) __m1 >> 31) & __m0)); \ + } while (0) +#define smul_ppmm(xh, xl, m0, m1) \ + do { \ + union {DItype __ll; \ + struct {USItype __h, __l;} __i; \ + } __xx; \ + __asm__ ("mr %0,%3" \ + : "=r" (__xx.__i.__h), \ + "=r" (__xx.__i.__l) \ + : "%1" (m0), \ + "r" (m1)); \ + (xh) = __xx.__i.__h; (xl) = __xx.__i.__l; \ + } while (0) +#define sdiv_qrnnd(q, r, n1, n0, d) \ + do { \ + union {DItype __ll; \ + struct {USItype __h, __l;} __i; \ + } __xx; \ + __xx.__i.__h = n1; __xx.__i.__l = n0; \ + __asm__ ("dr %0,%2" \ + : "=r" (__xx.__ll) \ + : "0" (__xx.__ll), "r" (d)); \ + (q) = __xx.__i.__l; (r) = __xx.__i.__h; \ + } while (0) +#endif + +#if (defined (__i386__) || defined (__i486__)) && W_TYPE_SIZE == 32 +#define add_ssaaaa(sh, sl, ah, al, bh, bl) \ + __asm__ ("addl %5,%1 + adcl %3,%0" \ + : "=r" ((USItype)(sh)), \ + "=&r" ((USItype)(sl)) \ + : "%0" ((USItype)(ah)), \ + "g" ((USItype)(bh)), \ + "%1" ((USItype)(al)), \ + "g" ((USItype)(bl))) +#define sub_ddmmss(sh, sl, ah, al, bh, bl) \ + __asm__ ("subl %5,%1 + sbbl %3,%0" \ + : "=r" ((USItype)(sh)), \ + "=&r" ((USItype)(sl)) \ + : "0" ((USItype)(ah)), \ + "g" ((USItype)(bh)), \ + "1" ((USItype)(al)), \ + "g" ((USItype)(bl))) +#define umul_ppmm(w1, w0, u, v) \ + __asm__ ("mull %3" \ + : "=a" ((USItype)(w0)), \ + "=d" ((USItype)(w1)) \ + : "%0" ((USItype)(u)), \ + "rm" ((USItype)(v))) +#define udiv_qrnnd(q, r, n1, n0, d) \ + __asm__ ("divl %4" \ + : "=a" ((USItype)(q)), \ + "=d" ((USItype)(r)) \ + : "0" ((USItype)(n0)), \ + "1" ((USItype)(n1)), \ + "rm" ((USItype)(d))) +#define count_leading_zeros(count, x) \ + do { \ + USItype __cbtmp; \ + __asm__ ("bsrl %1,%0" \ + : "=r" (__cbtmp) : "rm" ((USItype)(x))); \ + (count) = __cbtmp ^ 31; \ + } while (0) +#define count_trailing_zeros(count, x) \ + __asm__ ("bsfl %1,%0" : "=r" (count) : "rm" ((USItype)(x))) +#ifndef UMUL_TIME +#define UMUL_TIME 40 +#endif +#ifndef UDIV_TIME +#define UDIV_TIME 40 +#endif +#endif /* 80x86 */ + +#if defined (__i860__) && W_TYPE_SIZE == 32 +#define rshift_rhlc(r,h,l,c) \ + __asm__ ("shr %3,r0,r0\;shrd %1,%2,%0" \ + "=r" (r) : "r" (h), "r" (l), "rn" (c)) +#endif /* i860 */ + +#if defined (__i960__) && W_TYPE_SIZE == 32 +#define add_ssaaaa(sh, sl, ah, al, bh, bl) \ + __asm__ ("cmpo 1,0\;addc %5,%4,%1\;addc %3,%2,%0" \ + : "=r" ((USItype)(sh)), \ + "=&r" ((USItype)(sl)) \ + : "%dI" ((USItype)(ah)), \ + "dI" ((USItype)(bh)), \ + "%dI" ((USItype)(al)), \ + "dI" ((USItype)(bl))) +#define sub_ddmmss(sh, sl, ah, al, bh, bl) \ + __asm__ ("cmpo 0,0\;subc %5,%4,%1\;subc %3,%2,%0" \ + : "=r" ((USItype)(sh)), \ + "=&r" ((USItype)(sl)) \ + : "dI" ((USItype)(ah)), \ + "dI" ((USItype)(bh)), \ + "dI" ((USItype)(al)), \ + "dI" ((USItype)(bl))) +#define umul_ppmm(w1, w0, u, v) \ + ({union {UDItype __ll; \ + struct {USItype __l, __h;} __i; \ + } __xx; \ + __asm__ ("emul %2,%1,%0" \ + : "=d" (__xx.__ll) \ + : "%dI" ((USItype)(u)), \ + "dI" ((USItype)(v))); \ + (w1) = __xx.__i.__h; (w0) = __xx.__i.__l;}) +#define __umulsidi3(u, v) \ + ({UDItype __w; \ + __asm__ ("emul %2,%1,%0" \ + : "=d" (__w) \ + : "%dI" ((USItype)(u)), \ + "dI" ((USItype)(v))); \ + __w; }) +#define udiv_qrnnd(q, r, nh, nl, d) \ + do { \ + union {UDItype __ll; \ + struct {USItype __l, __h;} __i; \ + } __nn; \ + __nn.__i.__h = (nh); __nn.__i.__l = (nl); \ + __asm__ ("ediv %d,%n,%0" \ + : "=d" (__rq.__ll) \ + : "dI" (__nn.__ll), \ + "dI" ((USItype)(d))); \ + (r) = __rq.__i.__l; (q) = __rq.__i.__h; \ + } while (0) +#define count_leading_zeros(count, x) \ + do { \ + USItype __cbtmp; \ + __asm__ ("scanbit %1,%0" \ + : "=r" (__cbtmp) \ + : "r" ((USItype)(x))); \ + (count) = __cbtmp ^ 31; \ + } while (0) +#define COUNT_LEADING_ZEROS_0 (-32) /* sic */ +#if defined (__i960mx) /* what is the proper symbol to test??? */ +#define rshift_rhlc(r,h,l,c) \ + do { \ + union {UDItype __ll; \ + struct {USItype __l, __h;} __i; \ + } __nn; \ + __nn.__i.__h = (h); __nn.__i.__l = (l); \ + __asm__ ("shre %2,%1,%0" \ + : "=d" (r) : "dI" (__nn.__ll), "dI" (c)); \ + } +#endif /* i960mx */ +#endif /* i960 */ + +#if (defined (__mc68000__) || defined (__mc68020__) || defined (__NeXT__) || defined(mc68020)) && W_TYPE_SIZE == 32 +#define add_ssaaaa(sh, sl, ah, al, bh, bl) \ + __asm__ ("add%.l %5,%1 + addx%.l %3,%0" \ + : "=d" ((USItype)(sh)), \ + "=&d" ((USItype)(sl)) \ + : "%0" ((USItype)(ah)), \ + "d" ((USItype)(bh)), \ + "%1" ((USItype)(al)), \ + "g" ((USItype)(bl))) +#define sub_ddmmss(sh, sl, ah, al, bh, bl) \ + __asm__ ("sub%.l %5,%1 + subx%.l %3,%0" \ + : "=d" ((USItype)(sh)), \ + "=&d" ((USItype)(sl)) \ + : "0" ((USItype)(ah)), \ + "d" ((USItype)(bh)), \ + "1" ((USItype)(al)), \ + "g" ((USItype)(bl))) +#if (defined (__mc68020__) || defined (__NeXT__) || defined(mc68020)) +#define umul_ppmm(w1, w0, u, v) \ + __asm__ ("mulu%.l %3,%1:%0" \ + : "=d" ((USItype)(w0)), \ + "=d" ((USItype)(w1)) \ + : "%0" ((USItype)(u)), \ + "dmi" ((USItype)(v))) +#define UMUL_TIME 45 +#define udiv_qrnnd(q, r, n1, n0, d) \ + __asm__ ("divu%.l %4,%1:%0" \ + : "=d" ((USItype)(q)), \ + "=d" ((USItype)(r)) \ + : "0" ((USItype)(n0)), \ + "1" ((USItype)(n1)), \ + "dmi" ((USItype)(d))) +#define UDIV_TIME 90 +#define sdiv_qrnnd(q, r, n1, n0, d) \ + __asm__ ("divs%.l %4,%1:%0" \ + : "=d" ((USItype)(q)), \ + "=d" ((USItype)(r)) \ + : "0" ((USItype)(n0)), \ + "1" ((USItype)(n1)), \ + "dmi" ((USItype)(d))) +#define count_leading_zeros(count, x) \ + __asm__ ("bfffo %1{%b2:%b2},%0" \ + : "=d" ((USItype)(count)) \ + : "od" ((USItype)(x)), "n" (0)) +#define COUNT_LEADING_ZEROS_0 32 +#else /* not mc68020 */ +#define umul_ppmm(xh, xl, a, b) \ + do { USItype __umul_tmp1, __umul_tmp2; \ + __asm__ ("| Inlined umul_ppmm + move%.l %5,%3 + move%.l %2,%0 + move%.w %3,%1 + swap %3 + swap %0 + mulu %2,%1 + mulu %3,%0 + mulu %2,%3 + swap %2 + mulu %5,%2 + add%.l %3,%2 + jcc 1f + add%.l %#0x10000,%0 +1: move%.l %2,%3 + clr%.w %2 + swap %2 + swap %3 + clr%.w %3 + add%.l %3,%1 + addx%.l %2,%0 + | End inlined umul_ppmm" \ + : "=&d" ((USItype)(xh)), "=&d" ((USItype)(xl)), \ + "=d" (__umul_tmp1), "=&d" (__umul_tmp2) \ + : "%2" ((USItype)(a)), "d" ((USItype)(b))); \ + } while (0) +#define UMUL_TIME 100 +#define UDIV_TIME 400 +#endif /* not mc68020 */ +#endif /* mc68000 */ + +#if defined (__m88000__) && W_TYPE_SIZE == 32 +#define add_ssaaaa(sh, sl, ah, al, bh, bl) \ + __asm__ ("addu.co %1,%r4,%r5 + addu.ci %0,%r2,%r3" \ + : "=r" ((USItype)(sh)), \ + "=&r" ((USItype)(sl)) \ + : "%rJ" ((USItype)(ah)), \ + "rJ" ((USItype)(bh)), \ + "%rJ" ((USItype)(al)), \ + "rJ" ((USItype)(bl))) +#define sub_ddmmss(sh, sl, ah, al, bh, bl) \ + __asm__ ("subu.co %1,%r4,%r5 + subu.ci %0,%r2,%r3" \ + : "=r" ((USItype)(sh)), \ + "=&r" ((USItype)(sl)) \ + : "rJ" ((USItype)(ah)), \ + "rJ" ((USItype)(bh)), \ + "rJ" ((USItype)(al)), \ + "rJ" ((USItype)(bl))) +#define count_leading_zeros(count, x) \ + do { \ + USItype __cbtmp; \ + __asm__ ("ff1 %0,%1" \ + : "=r" (__cbtmp) \ + : "r" ((USItype)(x))); \ + (count) = __cbtmp ^ 31; \ + } while (0) +#define COUNT_LEADING_ZEROS_0 63 /* sic */ +#if defined (__m88110__) +#define umul_ppmm(wh, wl, u, v) \ + do { \ + union {UDItype __ll; \ + struct {USItype __h, __l;} __i; \ + } __xx; \ + __asm__ ("mulu.d %0,%1,%2" \ + : "=r" (__xx.__ll) \ + : "r" ((USItype)(u)), \ + "r" ((USItype)(v))); \ + (wh) = __xx.__i.__h; \ + (wl) = __xx.__i.__l; \ + } while (0) +#define udiv_qrnnd(q, r, n1, n0, d) \ + ({union {UDItype __ll; \ + struct {USItype __h, __l;} __i; \ + } __xx; \ + USItype __q; \ + __xx.__i.__h = (n1); __xx.__i.__l = (n0); \ + __asm__ ("divu.d %0,%1,%2" \ + : "=r" (__q) \ + : "r" (__xx.__ll), \ + "r" ((USItype)(d))); \ + (r) = (n0) - __q * (d); (q) = __q; }) +#define UMUL_TIME 5 +#define UDIV_TIME 25 +#else +#define UMUL_TIME 17 +#define UDIV_TIME 150 +#endif /* __m88110__ */ +#endif /* __m88000__ */ + +#if defined (__mips__) && W_TYPE_SIZE == 32 +#if __GNUC__ > 2 || __GNUC_MINOR__ >= 7 +#define umul_ppmm(w1, w0, u, v) \ + __asm__ ("multu %2,%3" \ + : "=l" ((USItype)(w0)), \ + "=h" ((USItype)(w1)) \ + : "d" ((USItype)(u)), \ + "d" ((USItype)(v))) +#else +#define umul_ppmm(w1, w0, u, v) \ + __asm__ ("multu %2,%3 + mflo %0 + mfhi %1" \ + : "=d" ((USItype)(w0)), \ + "=d" ((USItype)(w1)) \ + : "d" ((USItype)(u)), \ + "d" ((USItype)(v))) +#endif +#define UMUL_TIME 10 +#define UDIV_TIME 100 +#endif /* __mips__ */ + +#if (defined (__mips) && __mips >= 3) && W_TYPE_SIZE == 64 +#if __GNUC__ > 2 || __GNUC_MINOR__ >= 7 +#define umul_ppmm(w1, w0, u, v) \ + __asm__ ("dmultu %2,%3" \ + : "=l" ((UDItype)(w0)), \ + "=h" ((UDItype)(w1)) \ + : "d" ((UDItype)(u)), \ + "d" ((UDItype)(v))) +#else +#define umul_ppmm(w1, w0, u, v) \ + __asm__ ("dmultu %2,%3 + mflo %0 + mfhi %1" \ + : "=d" ((UDItype)(w0)), \ + "=d" ((UDItype)(w1)) \ + : "d" ((UDItype)(u)), \ + "d" ((UDItype)(v))) +#endif +#define UMUL_TIME 20 +#define UDIV_TIME 140 +#endif /* __mips__ */ + +#if defined (__ns32000__) && W_TYPE_SIZE == 32 +#define umul_ppmm(w1, w0, u, v) \ + ({union {UDItype __ll; \ + struct {USItype __l, __h;} __i; \ + } __xx; \ + __asm__ ("meid %2,%0" \ + : "=g" (__xx.__ll) \ + : "%0" ((USItype)(u)), \ + "g" ((USItype)(v))); \ + (w1) = __xx.__i.__h; (w0) = __xx.__i.__l;}) +#define __umulsidi3(u, v) \ + ({UDItype __w; \ + __asm__ ("meid %2,%0" \ + : "=g" (__w) \ + : "%0" ((USItype)(u)), \ + "g" ((USItype)(v))); \ + __w; }) +#define udiv_qrnnd(q, r, n1, n0, d) \ + ({union {UDItype __ll; \ + struct {USItype __l, __h;} __i; \ + } __xx; \ + __xx.__i.__h = (n1); __xx.__i.__l = (n0); \ + __asm__ ("deid %2,%0" \ + : "=g" (__xx.__ll) \ + : "0" (__xx.__ll), \ + "g" ((USItype)(d))); \ + (r) = __xx.__i.__l; (q) = __xx.__i.__h; }) +#define count_trailing_zeros(count,x) \ + do { + __asm__ ("ffsd %2,%0" \ + : "=r" ((USItype) (count)) \ + : "0" ((USItype) 0), \ + "r" ((USItype) (x))); \ + } while (0) +#endif /* __ns32000__ */ + +#if (defined (_ARCH_PPC) || defined (_IBMR2)) && W_TYPE_SIZE == 32 +#define add_ssaaaa(sh, sl, ah, al, bh, bl) \ + do { \ + if (__builtin_constant_p (bh) && (bh) == 0) \ + __asm__ ("{a%I4|add%I4c} %1,%3,%4\n\t{aze|addze} %0,%2" \ + : "=r" ((USItype)(sh)), \ + "=&r" ((USItype)(sl)) \ + : "%r" ((USItype)(ah)), \ + "%r" ((USItype)(al)), \ + "rI" ((USItype)(bl))); \ + else if (__builtin_constant_p (bh) && (bh) ==~(USItype) 0) \ + __asm__ ("{a%I4|add%I4c} %1,%3,%4\n\t{ame|addme} %0,%2" \ + : "=r" ((USItype)(sh)), \ + "=&r" ((USItype)(sl)) \ + : "%r" ((USItype)(ah)), \ + "%r" ((USItype)(al)), \ + "rI" ((USItype)(bl))); \ + else \ + __asm__ ("{a%I5|add%I5c} %1,%4,%5\n\t{ae|adde} %0,%2,%3" \ + : "=r" ((USItype)(sh)), \ + "=&r" ((USItype)(sl)) \ + : "%r" ((USItype)(ah)), \ + "r" ((USItype)(bh)), \ + "%r" ((USItype)(al)), \ + "rI" ((USItype)(bl))); \ + } while (0) +#define sub_ddmmss(sh, sl, ah, al, bh, bl) \ + do { \ + if (__builtin_constant_p (ah) && (ah) == 0) \ + __asm__ ("{sf%I3|subf%I3c} %1,%4,%3\n\t{sfze|subfze} %0,%2" \ + : "=r" ((USItype)(sh)), \ + "=&r" ((USItype)(sl)) \ + : "r" ((USItype)(bh)), \ + "rI" ((USItype)(al)), \ + "r" ((USItype)(bl))); \ + else if (__builtin_constant_p (ah) && (ah) ==~(USItype) 0) \ + __asm__ ("{sf%I3|subf%I3c} %1,%4,%3\n\t{sfme|subfme} %0,%2" \ + : "=r" ((USItype)(sh)), \ + "=&r" ((USItype)(sl)) \ + : "r" ((USItype)(bh)), \ + "rI" ((USItype)(al)), \ + "r" ((USItype)(bl))); \ + else if (__builtin_constant_p (bh) && (bh) == 0) \ + __asm__ ("{sf%I3|subf%I3c} %1,%4,%3\n\t{ame|addme} %0,%2" \ + : "=r" ((USItype)(sh)), \ + "=&r" ((USItype)(sl)) \ + : "r" ((USItype)(ah)), \ + "rI" ((USItype)(al)), \ + "r" ((USItype)(bl))); \ + else if (__builtin_constant_p (bh) && (bh) ==~(USItype) 0) \ + __asm__ ("{sf%I3|subf%I3c} %1,%4,%3\n\t{aze|addze} %0,%2" \ + : "=r" ((USItype)(sh)), \ + "=&r" ((USItype)(sl)) \ + : "r" ((USItype)(ah)), \ + "rI" ((USItype)(al)), \ + "r" ((USItype)(bl))); \ + else \ + __asm__ ("{sf%I4|subf%I4c} %1,%5,%4\n\t{sfe|subfe} %0,%3,%2" \ + : "=r" ((USItype)(sh)), \ + "=&r" ((USItype)(sl)) \ + : "r" ((USItype)(ah)), \ + "r" ((USItype)(bh)), \ + "rI" ((USItype)(al)), \ + "r" ((USItype)(bl))); \ + } while (0) +#define count_leading_zeros(count, x) \ + __asm__ ("{cntlz|cntlzw} %0,%1" \ + : "=r" ((USItype)(count)) \ + : "r" ((USItype)(x))) +#define COUNT_LEADING_ZEROS_0 32 +#if defined (_ARCH_PPC) +#define umul_ppmm(ph, pl, m0, m1) \ + do { \ + USItype __m0 = (m0), __m1 = (m1); \ + __asm__ ("mulhwu %0,%1,%2" \ + : "=r" ((USItype) ph) \ + : "%r" (__m0), \ + "r" (__m1)); \ + (pl) = __m0 * __m1; \ + } while (0) +#define UMUL_TIME 15 +#define smul_ppmm(ph, pl, m0, m1) \ + do { \ + SItype __m0 = (m0), __m1 = (m1); \ + __asm__ ("mulhw %0,%1,%2" \ + : "=r" ((SItype) ph) \ + : "%r" (__m0), \ + "r" (__m1)); \ + (pl) = __m0 * __m1; \ + } while (0) +#define SMUL_TIME 14 +#define UDIV_TIME 120 +#else +#define umul_ppmm(xh, xl, m0, m1) \ + do { \ + USItype __m0 = (m0), __m1 = (m1); \ + __asm__ ("mul %0,%2,%3" \ + : "=r" ((USItype)(xh)), \ + "=q" ((USItype)(xl)) \ + : "r" (__m0), \ + "r" (__m1)); \ + (xh) += ((((SItype) __m0 >> 31) & __m1) \ + + (((SItype) __m1 >> 31) & __m0)); \ + } while (0) +#define UMUL_TIME 8 +#define smul_ppmm(xh, xl, m0, m1) \ + __asm__ ("mul %0,%2,%3" \ + : "=r" ((SItype)(xh)), \ + "=q" ((SItype)(xl)) \ + : "r" (m0), \ + "r" (m1)) +#define SMUL_TIME 4 +#define sdiv_qrnnd(q, r, nh, nl, d) \ + __asm__ ("div %0,%2,%4" \ + : "=r" ((SItype)(q)), "=q" ((SItype)(r)) \ + : "r" ((SItype)(nh)), "1" ((SItype)(nl)), "r" ((SItype)(d))) +#define UDIV_TIME 100 +#endif +#endif /* Power architecture variants. */ + +#if defined (__pyr__) && W_TYPE_SIZE == 32 +#define add_ssaaaa(sh, sl, ah, al, bh, bl) \ + __asm__ ("addw %5,%1 + addwc %3,%0" \ + : "=r" ((USItype)(sh)), \ + "=&r" ((USItype)(sl)) \ + : "%0" ((USItype)(ah)), \ + "g" ((USItype)(bh)), \ + "%1" ((USItype)(al)), \ + "g" ((USItype)(bl))) +#define sub_ddmmss(sh, sl, ah, al, bh, bl) \ + __asm__ ("subw %5,%1 + subwb %3,%0" \ + : "=r" ((USItype)(sh)), \ + "=&r" ((USItype)(sl)) \ + : "0" ((USItype)(ah)), \ + "g" ((USItype)(bh)), \ + "1" ((USItype)(al)), \ + "g" ((USItype)(bl))) +/* This insn works on Pyramids with AP, XP, or MI CPUs, but not with SP. */ +#define umul_ppmm(w1, w0, u, v) \ + ({union {UDItype __ll; \ + struct {USItype __h, __l;} __i; \ + } __xx; \ + __asm__ ("movw %1,%R0 + uemul %2,%0" \ + : "=&r" (__xx.__ll) \ + : "g" ((USItype) (u)), \ + "g" ((USItype)(v))); \ + (w1) = __xx.__i.__h; (w0) = __xx.__i.__l;}) +#endif /* __pyr__ */ + +#if defined (__ibm032__) /* RT/ROMP */ && W_TYPE_SIZE == 32 +#define add_ssaaaa(sh, sl, ah, al, bh, bl) \ + __asm__ ("a %1,%5 + ae %0,%3" \ + : "=r" ((USItype)(sh)), \ + "=&r" ((USItype)(sl)) \ + : "%0" ((USItype)(ah)), \ + "r" ((USItype)(bh)), \ + "%1" ((USItype)(al)), \ + "r" ((USItype)(bl))) +#define sub_ddmmss(sh, sl, ah, al, bh, bl) \ + __asm__ ("s %1,%5 + se %0,%3" \ + : "=r" ((USItype)(sh)), \ + "=&r" ((USItype)(sl)) \ + : "0" ((USItype)(ah)), \ + "r" ((USItype)(bh)), \ + "1" ((USItype)(al)), \ + "r" ((USItype)(bl))) +#define umul_ppmm(ph, pl, m0, m1) \ + do { \ + USItype __m0 = (m0), __m1 = (m1); \ + __asm__ ( \ + "s r2,r2 + mts r10,%2 + m r2,%3 + m r2,%3 + m r2,%3 + m r2,%3 + m r2,%3 + m r2,%3 + m r2,%3 + m r2,%3 + m r2,%3 + m r2,%3 + m r2,%3 + m r2,%3 + m r2,%3 + m r2,%3 + m r2,%3 + m r2,%3 + cas %0,r2,r0 + mfs r10,%1" \ + : "=r" ((USItype)(ph)), \ + "=r" ((USItype)(pl)) \ + : "%r" (__m0), \ + "r" (__m1) \ + : "r2"); \ + (ph) += ((((SItype) __m0 >> 31) & __m1) \ + + (((SItype) __m1 >> 31) & __m0)); \ + } while (0) +#define UMUL_TIME 20 +#define UDIV_TIME 200 +#define count_leading_zeros(count, x) \ + do { \ + if ((x) >= 0x10000) \ + __asm__ ("clz %0,%1" \ + : "=r" ((USItype)(count)) \ + : "r" ((USItype)(x) >> 16)); \ + else \ + { \ + __asm__ ("clz %0,%1" \ + : "=r" ((USItype)(count)) \ + : "r" ((USItype)(x))); \ + (count) += 16; \ + } \ + } while (0) +#endif /* RT/ROMP */ + +#if defined (__sh2__) && W_TYPE_SIZE == 32 +#define umul_ppmm(w1, w0, u, v) \ + __asm__ ( \ + "dmulu.l %2,%3 + sts macl,%1 + sts mach,%0" \ + : "=r" ((USItype)(w1)), \ + "=r" ((USItype)(w0)) \ + : "r" ((USItype)(u)), \ + "r" ((USItype)(v)) \ + : "macl", "mach") +#define UMUL_TIME 5 +#endif + +#if defined (__sparc__) && W_TYPE_SIZE == 32 +#define add_ssaaaa(sh, sl, ah, al, bh, bl) \ + __asm__ ("addcc %r4,%5,%1 + addx %r2,%3,%0" \ + : "=r" ((USItype)(sh)), \ + "=&r" ((USItype)(sl)) \ + : "%rJ" ((USItype)(ah)), \ + "rI" ((USItype)(bh)), \ + "%rJ" ((USItype)(al)), \ + "rI" ((USItype)(bl)) \ + __CLOBBER_CC) +#define sub_ddmmss(sh, sl, ah, al, bh, bl) \ + __asm__ ("subcc %r4,%5,%1 + subx %r2,%3,%0" \ + : "=r" ((USItype)(sh)), \ + "=&r" ((USItype)(sl)) \ + : "rJ" ((USItype)(ah)), \ + "rI" ((USItype)(bh)), \ + "rJ" ((USItype)(al)), \ + "rI" ((USItype)(bl)) \ + __CLOBBER_CC) +#if defined (__sparc_v8__) +/* Don't match immediate range because, 1) it is not often useful, + 2) the 'I' flag thinks of the range as a 13 bit signed interval, + while we want to match a 13 bit interval, sign extended to 32 bits, + but INTERPRETED AS UNSIGNED. */ +#define umul_ppmm(w1, w0, u, v) \ + __asm__ ("umul %2,%3,%1;rd %%y,%0" \ + : "=r" ((USItype)(w1)), \ + "=r" ((USItype)(w0)) \ + : "r" ((USItype)(u)), \ + "r" ((USItype)(v))) +#define UMUL_TIME 5 +#ifndef SUPERSPARC /* SuperSPARC's udiv only handles 53 bit dividends */ +#define udiv_qrnnd(q, r, n1, n0, d) \ + do { \ + USItype __q; \ + __asm__ ("mov %1,%%y;nop;nop;nop;udiv %2,%3,%0" \ + : "=r" ((USItype)(__q)) \ + : "r" ((USItype)(n1)), \ + "r" ((USItype)(n0)), \ + "r" ((USItype)(d))); \ + (r) = (n0) - __q * (d); \ + (q) = __q; \ + } while (0) +#define UDIV_TIME 25 +#endif /* SUPERSPARC */ +#else /* ! __sparc_v8__ */ +#if defined (__sparclite__) +/* This has hardware multiply but not divide. It also has two additional + instructions scan (ffs from high bit) and divscc. */ +#define umul_ppmm(w1, w0, u, v) \ + __asm__ ("umul %2,%3,%1;rd %%y,%0" \ + : "=r" ((USItype)(w1)), \ + "=r" ((USItype)(w0)) \ + : "r" ((USItype)(u)), \ + "r" ((USItype)(v))) +#define UMUL_TIME 5 +#define udiv_qrnnd(q, r, n1, n0, d) \ + __asm__ ("! Inlined udiv_qrnnd + wr %%g0,%2,%%y ! Not a delayed write for sparclite + tst %%g0 + divscc %3,%4,%%g1 + divscc %%g1,%4,%%g1 + divscc %%g1,%4,%%g1 + divscc %%g1,%4,%%g1 + divscc %%g1,%4,%%g1 + divscc %%g1,%4,%%g1 + divscc %%g1,%4,%%g1 + divscc %%g1,%4,%%g1 + divscc %%g1,%4,%%g1 + divscc %%g1,%4,%%g1 + divscc %%g1,%4,%%g1 + divscc %%g1,%4,%%g1 + divscc %%g1,%4,%%g1 + divscc %%g1,%4,%%g1 + divscc %%g1,%4,%%g1 + divscc %%g1,%4,%%g1 + divscc %%g1,%4,%%g1 + divscc %%g1,%4,%%g1 + divscc %%g1,%4,%%g1 + divscc %%g1,%4,%%g1 + divscc %%g1,%4,%%g1 + divscc %%g1,%4,%%g1 + divscc %%g1,%4,%%g1 + divscc %%g1,%4,%%g1 + divscc %%g1,%4,%%g1 + divscc %%g1,%4,%%g1 + divscc %%g1,%4,%%g1 + divscc %%g1,%4,%%g1 + divscc %%g1,%4,%%g1 + divscc %%g1,%4,%%g1 + divscc %%g1,%4,%%g1 + divscc %%g1,%4,%0 + rd %%y,%1 + bl,a 1f + add %1,%4,%1 +1: ! End of inline udiv_qrnnd" \ + : "=r" ((USItype)(q)), \ + "=r" ((USItype)(r)) \ + : "r" ((USItype)(n1)), \ + "r" ((USItype)(n0)), \ + "rI" ((USItype)(d)) \ + : "%g1" __AND_CLOBBER_CC) +#define UDIV_TIME 37 +#define count_leading_zeros(count, x) \ + __asm__ ("scan %1,0,%0" \ + : "=r" ((USItype)(x)) \ + : "r" ((USItype)(count))) +/* Early sparclites return 63 for an argument of 0, but they warn that future + implementations might change this. Therefore, leave COUNT_LEADING_ZEROS_0 + undefined. */ +#endif /* __sparclite__ */ +#endif /* __sparc_v8__ */ +/* Default to sparc v7 versions of umul_ppmm and udiv_qrnnd. */ +#ifndef umul_ppmm +#define umul_ppmm(w1, w0, u, v) \ + __asm__ ("! Inlined umul_ppmm + wr %%g0,%2,%%y ! SPARC has 0-3 delay insn after a wr + sra %3,31,%%g2 ! Don't move this insn + and %2,%%g2,%%g2 ! Don't move this insn + andcc %%g0,0,%%g1 ! Don't move this insn + mulscc %%g1,%3,%%g1 + mulscc %%g1,%3,%%g1 + mulscc %%g1,%3,%%g1 + mulscc %%g1,%3,%%g1 + mulscc %%g1,%3,%%g1 + mulscc %%g1,%3,%%g1 + mulscc %%g1,%3,%%g1 + mulscc %%g1,%3,%%g1 + mulscc %%g1,%3,%%g1 + mulscc %%g1,%3,%%g1 + mulscc %%g1,%3,%%g1 + mulscc %%g1,%3,%%g1 + mulscc %%g1,%3,%%g1 + mulscc %%g1,%3,%%g1 + mulscc %%g1,%3,%%g1 + mulscc %%g1,%3,%%g1 + mulscc %%g1,%3,%%g1 + mulscc %%g1,%3,%%g1 + mulscc %%g1,%3,%%g1 + mulscc %%g1,%3,%%g1 + mulscc %%g1,%3,%%g1 + mulscc %%g1,%3,%%g1 + mulscc %%g1,%3,%%g1 + mulscc %%g1,%3,%%g1 + mulscc %%g1,%3,%%g1 + mulscc %%g1,%3,%%g1 + mulscc %%g1,%3,%%g1 + mulscc %%g1,%3,%%g1 + mulscc %%g1,%3,%%g1 + mulscc %%g1,%3,%%g1 + mulscc %%g1,%3,%%g1 + mulscc %%g1,%3,%%g1 + mulscc %%g1,0,%%g1 + add %%g1,%%g2,%0 + rd %%y,%1" \ + : "=r" ((USItype)(w1)), \ + "=r" ((USItype)(w0)) \ + : "%rI" ((USItype)(u)), \ + "r" ((USItype)(v)) \ + : "%g1", "%g2" __AND_CLOBBER_CC) +#define UMUL_TIME 39 /* 39 instructions */ +#endif +#ifndef udiv_qrnnd +#ifndef LONGLONG_STANDALONE +#define udiv_qrnnd(q, r, n1, n0, d) \ + do { USItype __r; \ + (q) = __udiv_qrnnd (&__r, (n1), (n0), (d)); \ + (r) = __r; \ + } while (0) +extern USItype __udiv_qrnnd (); +#define UDIV_TIME 140 +#endif /* LONGLONG_STANDALONE */ +#endif /* udiv_qrnnd */ +#endif /* __sparc__ */ + +#if defined (__vax__) && W_TYPE_SIZE == 32 +#define add_ssaaaa(sh, sl, ah, al, bh, bl) \ + __asm__ ("addl2 %5,%1 + adwc %3,%0" \ + : "=g" ((USItype)(sh)), \ + "=&g" ((USItype)(sl)) \ + : "%0" ((USItype)(ah)), \ + "g" ((USItype)(bh)), \ + "%1" ((USItype)(al)), \ + "g" ((USItype)(bl))) +#define sub_ddmmss(sh, sl, ah, al, bh, bl) \ + __asm__ ("subl2 %5,%1 + sbwc %3,%0" \ + : "=g" ((USItype)(sh)), \ + "=&g" ((USItype)(sl)) \ + : "0" ((USItype)(ah)), \ + "g" ((USItype)(bh)), \ + "1" ((USItype)(al)), \ + "g" ((USItype)(bl))) +#define umul_ppmm(xh, xl, m0, m1) \ + do { \ + union {UDItype __ll; \ + struct {USItype __l, __h;} __i; \ + } __xx; \ + USItype __m0 = (m0), __m1 = (m1); \ + __asm__ ("emul %1,%2,$0,%0" \ + : "=g" (__xx.__ll) \ + : "g" (__m0), \ + "g" (__m1)); \ + (xh) = __xx.__i.__h; (xl) = __xx.__i.__l; \ + (xh) += ((((SItype) __m0 >> 31) & __m1) \ + + (((SItype) __m1 >> 31) & __m0)); \ + } while (0) +#define sdiv_qrnnd(q, r, n1, n0, d) \ + do { \ + union {DItype __ll; \ + struct {SItype __l, __h;} __i; \ + } __xx; \ + __xx.__i.__h = n1; __xx.__i.__l = n0; \ + __asm__ ("ediv %3,%2,%0,%1" \ + : "=g" (q), "=g" (r) \ + : "g" (__xx.ll), "g" (d)); \ + } while (0) +#endif /* __vax__ */ + +#if defined (__z8000__) && W_TYPE_SIZE == 16 +#define add_ssaaaa(sh, sl, ah, al, bh, bl) \ + __asm__ ("add %H1,%H5\n\tadc %H0,%H3" \ + : "=r" ((unsigned int)(sh)), \ + "=&r" ((unsigned int)(sl)) \ + : "%0" ((unsigned int)(ah)), \ + "r" ((unsigned int)(bh)), \ + "%1" ((unsigned int)(al)), \ + "rQR" ((unsigned int)(bl))) +#define sub_ddmmss(sh, sl, ah, al, bh, bl) \ + __asm__ ("sub %H1,%H5\n\tsbc %H0,%H3" \ + : "=r" ((unsigned int)(sh)), \ + "=&r" ((unsigned int)(sl)) \ + : "0" ((unsigned int)(ah)), \ + "r" ((unsigned int)(bh)), \ + "1" ((unsigned int)(al)), \ + "rQR" ((unsigned int)(bl))) +#define umul_ppmm(xh, xl, m0, m1) \ + do { \ + union {long int __ll; \ + struct {unsigned int __h, __l;} __i; \ + } __xx; \ + unsigned int __m0 = (m0), __m1 = (m1); \ + __asm__ ("mult %S0,%H3" \ + : "=r" (__xx.__i.__h), \ + "=r" (__xx.__i.__l) \ + : "%1" (__m0), \ + "rQR" (__m1)); \ + (xh) = __xx.__i.__h; (xl) = __xx.__i.__l; \ + (xh) += ((((signed int) __m0 >> 15) & __m1) \ + + (((signed int) __m1 >> 15) & __m0)); \ + } while (0) +#endif /* __z8000__ */ + +#endif /* __GNUC__ */ + + +#if !defined (umul_ppmm) && defined (__umulsidi3) +#define umul_ppmm(ph, pl, m0, m1) \ + { \ + UDWtype __ll = __umulsidi3 (m0, m1); \ + ph = (UWtype) (__ll >> W_TYPE_SIZE); \ + pl = (UWtype) __ll; \ + } +#endif + +#if !defined (__umulsidi3) +#define __umulsidi3(u, v) \ + ({UWtype __hi, __lo; \ + umul_ppmm (__hi, __lo, u, v); \ + ((UDWtype) __hi << W_TYPE_SIZE) | __lo; }) +#endif + +/* If this machine has no inline assembler, use C macros. */ + +#if !defined (add_ssaaaa) +#define add_ssaaaa(sh, sl, ah, al, bh, bl) \ + do { \ + UWtype __x; \ + __x = (al) + (bl); \ + (sh) = (ah) + (bh) + (__x < (al)); \ + (sl) = __x; \ + } while (0) +#endif + +#if !defined (sub_ddmmss) +#define sub_ddmmss(sh, sl, ah, al, bh, bl) \ + do { \ + UWtype __x; \ + __x = (al) - (bl); \ + (sh) = (ah) - (bh) - (__x > (al)); \ + (sl) = __x; \ + } while (0) +#endif + +#if !defined (umul_ppmm) +#define umul_ppmm(w1, w0, u, v) \ + do { \ + UWtype __x0, __x1, __x2, __x3; \ + UHWtype __ul, __vl, __uh, __vh; \ + UWtype __u = (u), __v = (v); \ + \ + __ul = __ll_lowpart (__u); \ + __uh = __ll_highpart (__u); \ + __vl = __ll_lowpart (__v); \ + __vh = __ll_highpart (__v); \ + \ + __x0 = (UWtype) __ul * __vl; \ + __x1 = (UWtype) __ul * __vh; \ + __x2 = (UWtype) __uh * __vl; \ + __x3 = (UWtype) __uh * __vh; \ + \ + __x1 += __ll_highpart (__x0);/* this can't give carry */ \ + __x1 += __x2; /* but this indeed can */ \ + if (__x1 < __x2) /* did we get it? */ \ + __x3 += __ll_B; /* yes, add it in the proper pos. */ \ + \ + (w1) = __x3 + __ll_highpart (__x1); \ + (w0) = (__ll_lowpart (__x1) << W_TYPE_SIZE/2) + __ll_lowpart (__x0);\ + } while (0) +#endif + +#if !defined (umul_ppmm) +#define smul_ppmm(w1, w0, u, v) \ + do { \ + UWtype __w1; \ + UWtype __m0 = (u), __m1 = (v); \ + umul_ppmm (__w1, w0, __m0, __m1); \ + (w1) = __w1 - (-(__m0 >> (W_TYPE_SIZE - 1)) & __m1) \ + - (-(__m1 >> (W_TYPE_SIZE - 1)) & __m0); \ + } while (0) +#endif + +/* Define this unconditionally, so it can be used for debugging. */ +#define __udiv_qrnnd_c(q, r, n1, n0, d) \ + do { \ + UWtype __d1, __d0, __q1, __q0, __r1, __r0, __m; \ + __d1 = __ll_highpart (d); \ + __d0 = __ll_lowpart (d); \ + \ + __r1 = (n1) % __d1; \ + __q1 = (n1) / __d1; \ + __m = (UWtype) __q1 * __d0; \ + __r1 = __r1 * __ll_B | __ll_highpart (n0); \ + if (__r1 < __m) \ + { \ + __q1--, __r1 += (d); \ + if (__r1 >= (d)) /* i.e. we didn't get carry when adding to __r1 */\ + if (__r1 < __m) \ + __q1--, __r1 += (d); \ + } \ + __r1 -= __m; \ + \ + __r0 = __r1 % __d1; \ + __q0 = __r1 / __d1; \ + __m = (UWtype) __q0 * __d0; \ + __r0 = __r0 * __ll_B | __ll_lowpart (n0); \ + if (__r0 < __m) \ + { \ + __q0--, __r0 += (d); \ + if (__r0 >= (d)) \ + if (__r0 < __m) \ + __q0--, __r0 += (d); \ + } \ + __r0 -= __m; \ + \ + (q) = (UWtype) __q1 * __ll_B | __q0; \ + (r) = __r0; \ + } while (0) + +/* If the processor has no udiv_qrnnd but sdiv_qrnnd, go through + __udiv_w_sdiv (defined in libgcc or elsewhere). */ +#if !defined (udiv_qrnnd) && defined (sdiv_qrnnd) +#define udiv_qrnnd(q, r, nh, nl, d) \ + do { \ + UWtype __r; \ + (q) = __MPN(udiv_w_sdiv) (&__r, nh, nl, d); \ + (r) = __r; \ + } while (0) +#endif + +/* If udiv_qrnnd was not defined for this processor, use __udiv_qrnnd_c. */ +#if !defined (udiv_qrnnd) +#define UDIV_NEEDS_NORMALIZATION 1 +#define udiv_qrnnd __udiv_qrnnd_c +#endif + +#if !defined (count_leading_zeros) +extern +#ifdef __STDC__ +const +#endif +unsigned char __clz_tab[]; +#define count_leading_zeros(count, x) \ + do { \ + UWtype __xr = (x); \ + UWtype __a; \ + \ + if (W_TYPE_SIZE <= 32) \ + { \ + __a = __xr < ((UWtype) 1 << 2*__BITS4) \ + ? (__xr < ((UWtype) 1 << __BITS4) ? 0 : __BITS4) \ + : (__xr < ((UWtype) 1 << 3*__BITS4) ? 2*__BITS4 : 3*__BITS4);\ + } \ + else \ + { \ + for (__a = W_TYPE_SIZE - 8; __a > 0; __a -= 8) \ + if (((__xr >> __a) & 0xff) != 0) \ + break; \ + } \ + \ + (count) = W_TYPE_SIZE - (__clz_tab[__xr >> __a] + __a); \ + } while (0) +/* This version gives a well-defined value for zero. */ +#define COUNT_LEADING_ZEROS_0 W_TYPE_SIZE +#endif + +#if !defined (count_trailing_zeros) +/* Define count_trailing_zeros using count_leading_zeros. The latter might be + defined in asm, but if it is not, the C version above is good enough. */ +#define count_trailing_zeros(count, x) \ + do { \ + UWtype __ctz_x = (x); \ + UWtype __ctz_c; \ + count_leading_zeros (__ctz_c, __ctz_x & -__ctz_x); \ + (count) = W_TYPE_SIZE - 1 - __ctz_c; \ + } while (0) +#endif + +#ifndef UDIV_NEEDS_NORMALIZATION +#define UDIV_NEEDS_NORMALIZATION 0 +#endif diff --git a/contrib/libgmp/make.bat b/contrib/libgmp/make.bat new file mode 100755 index 0000000..2a79c48 --- /dev/null +++ b/contrib/libgmp/make.bat @@ -0,0 +1,315 @@ +cd mpn
+copy msdos\asm-synt.h asm-synt.h
+copy bsd.h sysdep.h
+copy generic\inlines.c inlines.c
+copy x86\pentium\add_n.S add_n.S
+copy x86\pentium\addmul_1.S addmul_1.S
+copy generic\cmp.c cmp.c
+copy generic\divmod_1.c divmod_1.c
+copy generic\divrem.c divrem.c
+copy generic\divrem_1.c divrem_1.c
+copy generic\dump.c dump.c
+copy x86\pentium\lshift.S lshift.S
+copy generic\mod_1.c mod_1.c
+copy generic\mul.c mul.c
+copy x86\pentium\mul_1.S mul_1.S
+copy generic\mul_n.c mul_n.c
+copy generic\random2.c random2.c
+copy x86\pentium\rshift.S rshift.S
+copy generic\sqrtrem.c sqrtrem.c
+copy x86\pentium\sub_n.S sub_n.S
+copy x86\pentium\submul_1.S submul_1.S
+copy generic\get_str.c get_str.c
+copy generic\set_str.c set_str.c
+copy generic\scan0.c scan0.c
+copy generic\scan1.c scan1.c
+copy generic\popcount.c popcount.c
+copy generic\hamdist.c hamdist.c
+copy generic\gcd_1.c gcd_1.c
+copy generic\pre_mod_1.c pre_mod_1.c
+copy generic\perfsqr.c perfsqr.c
+copy generic\bdivmod.c bdivmod.c
+copy generic\gcd.c gcd.c
+copy generic\gcdext.c gcdext.c
+copy x86\gmp-mpar.h gmp-mpar.h
+cd ..
+
+cd mpbsd
+copy ..\mpz\add.c add.c
+copy ..\mpz\cmp.c cmp.c
+copy ..\mpz\gcd.c gcd.c
+copy ..\mpz\mul.c mul.c
+copy ..\mpz\pow_ui.c pow_ui.c
+copy ..\mpz\powm.c powm.c
+copy ..\mpz\sqrtrem.c sqrtrem.c
+copy ..\mpz\sub.c sub.c
+cd ..
+
+cd mpn
+gcc -c -I. -I.. -g -O mp_bases.c
+gcc -c -I. -I.. -g -O inlines.c
+gcc -E -I. -I.. -g -O add_n.S | grep -v '^#' >tmp-add_n.s
+gcc -c tmp-add_n.s -o add_n.o
+del tmp-add_n.s
+gcc -E -I. -I.. -g -O addmul_1.S | grep -v '^#' >tmp-addmul_1.s
+gcc -c tmp-addmul_1.s -o addmul_1.o
+del tmp-addmul_1.s
+gcc -c -I. -I.. -g -O cmp.c
+gcc -c -I. -I.. -g -O divmod_1.c
+gcc -c -I. -I.. -g -O divrem.c
+gcc -c -I. -I.. -g -O divrem_1.c
+gcc -c -I. -I.. -g -O dump.c
+gcc -E -I. -I.. -g -O lshift.S | grep -v '^#' >tmp-lshift.s
+gcc -c tmp-lshift.s -o lshift.o
+del tmp-lshift.s
+gcc -c -I. -I.. -g -O mod_1.c
+gcc -c -I. -I.. -g -O mul.c
+gcc -E -I. -I.. -g -O mul_1.S | grep -v '^#' >tmp-mul_1.s
+gcc -c tmp-mul_1.s -o mul_1.o
+del tmp-mul_1.s
+gcc -c -I. -I.. -g -O mul_n.c
+gcc -c -I. -I.. -g -O random2.c
+gcc -E -I. -I.. -g -O rshift.S | grep -v '^#' >tmp-rshift.s
+gcc -c tmp-rshift.s -o rshift.o
+del tmp-rshift.s
+gcc -c -I. -I.. -g -O sqrtrem.c
+gcc -E -I. -I.. -g -O sub_n.S | grep -v '^#' >tmp-sub_n.s
+gcc -c tmp-sub_n.s -o sub_n.o
+del tmp-sub_n.s
+gcc -E -I. -I.. -g -O submul_1.S | grep -v '^#' >tmp-submul_1.s
+gcc -c tmp-submul_1.s -o submul_1.o
+del tmp-submul_1.s
+gcc -c -I. -I.. -g -O get_str.c
+gcc -c -I. -I.. -g -O set_str.c
+gcc -c -I. -I.. -g -O scan0.c
+gcc -c -I. -I.. -g -O scan1.c
+gcc -c -I. -I.. -g -O popcount.c
+gcc -c -I. -I.. -g -O hamdist.c
+gcc -c -I. -I.. -g -O gcd_1.c
+gcc -c -I. -I.. -g -O pre_mod_1.c
+gcc -c -I. -I.. -g -O perfsqr.c
+gcc -c -I. -I.. -g -O bdivmod.c
+gcc -c -I. -I.. -g -O gcd.c
+gcc -c -I. -I.. -g -O gcdext.c
+del libmpn.a
+ar rc libmpn.a *.o
+cd ..
+
+cd mpz
+gcc -c -I. -I.. -I../mpn -g -O abs.c
+gcc -c -I. -I.. -I../mpn -g -O add.c
+gcc -c -I. -I.. -I../mpn -g -O add_ui.c
+gcc -c -I. -I.. -I../mpn -g -O and.c
+gcc -c -I. -I.. -I../mpn -g -O array_init.c
+gcc -c -I. -I.. -I../mpn -g -O cdiv_q.c
+gcc -c -I. -I.. -I../mpn -g -O cdiv_q_ui.c
+gcc -c -I. -I.. -I../mpn -g -O cdiv_qr.c
+gcc -c -I. -I.. -I../mpn -g -O cdiv_qr_ui.c
+gcc -c -I. -I.. -I../mpn -g -O cdiv_r.c
+gcc -c -I. -I.. -I../mpn -g -O cdiv_r_ui.c
+gcc -c -I. -I.. -I../mpn -g -O cdiv_ui.c
+gcc -c -I. -I.. -I../mpn -g -O clear.c
+gcc -c -I. -I.. -I../mpn -g -O clrbit.c
+gcc -c -I. -I.. -I../mpn -g -O cmp.c
+gcc -c -I. -I.. -I../mpn -g -O cmp_si.c
+gcc -c -I. -I.. -I../mpn -g -O cmp_ui.c
+gcc -c -I. -I.. -I../mpn -g -O com.c
+gcc -c -I. -I.. -I../mpn -g -O divexact.c
+gcc -c -I. -I.. -I../mpn -g -O fac_ui.c
+gcc -c -I. -I.. -I../mpn -g -O fdiv_q.c
+gcc -c -I. -I.. -I../mpn -g -O fdiv_q_2exp.c
+gcc -c -I. -I.. -I../mpn -g -O fdiv_q_ui.c
+gcc -c -I. -I.. -I../mpn -g -O fdiv_qr.c
+gcc -c -I. -I.. -I../mpn -g -O fdiv_qr_ui.c
+gcc -c -I. -I.. -I../mpn -g -O fdiv_r.c
+gcc -c -I. -I.. -I../mpn -g -O fdiv_r_2exp.c
+gcc -c -I. -I.. -I../mpn -g -O fdiv_r_ui.c
+gcc -c -I. -I.. -I../mpn -g -O fdiv_ui.c
+gcc -c -I. -I.. -I../mpn -g -O gcd.c
+gcc -c -I. -I.. -I../mpn -g -O gcd_ui.c
+gcc -c -I. -I.. -I../mpn -g -O gcdext.c
+gcc -c -I. -I.. -I../mpn -g -O get_d.c
+gcc -c -I. -I.. -I../mpn -g -O get_si.c
+gcc -c -I. -I.. -I../mpn -g -O get_str.c
+gcc -c -I. -I.. -I../mpn -g -O get_ui.c
+gcc -c -I. -I.. -I../mpn -g -O getlimbn.c
+gcc -c -I. -I.. -I../mpn -g -O hamdist.c
+gcc -c -I. -I.. -I../mpn -g -O init.c
+gcc -c -I. -I.. -I../mpn -g -O inp_raw.c
+gcc -c -I. -I.. -I../mpn -g -O inp_str.c
+gcc -c -I. -I.. -I../mpn -g -O invert.c
+gcc -c -I. -I.. -I../mpn -g -O ior.c
+gcc -c -I. -I.. -I../mpn -g -O iset.c
+gcc -c -I. -I.. -I../mpn -g -O iset_d.c
+gcc -c -I. -I.. -I../mpn -g -O iset_si.c
+gcc -c -I. -I.. -I../mpn -g -O iset_str.c
+gcc -c -I. -I.. -I../mpn -g -O iset_ui.c
+gcc -c -I. -I.. -I../mpn -g -O jacobi.c
+gcc -c -I. -I.. -I../mpn -g -O legendre.c
+gcc -c -I. -I.. -I../mpn -g -O mod.c
+gcc -c -I. -I.. -I../mpn -g -O mul.c
+gcc -c -I. -I.. -I../mpn -g -O mul_2exp.c
+gcc -c -I. -I.. -I../mpn -g -O mul_ui.c
+gcc -c -I. -I.. -I../mpn -g -O neg.c
+gcc -c -I. -I.. -I../mpn -g -O out_raw.c
+gcc -c -I. -I.. -I../mpn -g -O out_str.c
+gcc -c -I. -I.. -I../mpn -g -O perfsqr.c
+gcc -c -I. -I.. -I../mpn -g -O popcount.c
+gcc -c -I. -I.. -I../mpn -g -O pow_ui.c
+gcc -c -I. -I.. -I../mpn -g -O powm.c
+gcc -c -I. -I.. -I../mpn -g -O powm_ui.c
+gcc -c -I. -I.. -I../mpn -g -O pprime_p.c
+gcc -c -I. -I.. -I../mpn -g -O random.c
+gcc -c -I. -I.. -I../mpn -g -O random2.c
+gcc -c -I. -I.. -I../mpn -g -O realloc.c
+gcc -c -I. -I.. -I../mpn -g -O scan0.c
+gcc -c -I. -I.. -I../mpn -g -O scan1.c
+gcc -c -I. -I.. -I../mpn -g -O set.c
+gcc -c -I. -I.. -I../mpn -g -O set_d.c
+gcc -c -I. -I.. -I../mpn -g -O set_f.c
+gcc -c -I. -I.. -I../mpn -g -O set_q.c
+gcc -c -I. -I.. -I../mpn -g -O set_si.c
+gcc -c -I. -I.. -I../mpn -g -O set_str.c
+gcc -c -I. -I.. -I../mpn -g -O set_ui.c
+gcc -c -I. -I.. -I../mpn -g -O setbit.c
+gcc -c -I. -I.. -I../mpn -g -O size.c
+gcc -c -I. -I.. -I../mpn -g -O sizeinbase.c
+gcc -c -I. -I.. -I../mpn -g -O sqrt.c
+gcc -c -I. -I.. -I../mpn -g -O sqrtrem.c
+gcc -c -I. -I.. -I../mpn -g -O sub.c
+gcc -c -I. -I.. -I../mpn -g -O sub_ui.c
+gcc -c -I. -I.. -I../mpn -g -O tdiv_q.c
+gcc -c -I. -I.. -I../mpn -g -O tdiv_q_2exp.c
+gcc -c -I. -I.. -I../mpn -g -O tdiv_q_ui.c
+gcc -c -I. -I.. -I../mpn -g -O tdiv_qr.c
+gcc -c -I. -I.. -I../mpn -g -O tdiv_qr_ui.c
+gcc -c -I. -I.. -I../mpn -g -O tdiv_r.c
+gcc -c -I. -I.. -I../mpn -g -O tdiv_r_2exp.c
+gcc -c -I. -I.. -I../mpn -g -O tdiv_r_ui.c
+gcc -c -I. -I.. -I../mpn -g -O ui_pow_ui.c
+del libmpz.a
+ar rc libmpz.a *.o
+cd ..
+
+cd mpf
+gcc -c -I. -I.. -I../mpn -g -O abs.c
+gcc -c -I. -I.. -I../mpn -g -O add.c
+gcc -c -I. -I.. -I../mpn -g -O add_ui.c
+gcc -c -I. -I.. -I../mpn -g -O clear.c
+gcc -c -I. -I.. -I../mpn -g -O cmp.c
+gcc -c -I. -I.. -I../mpn -g -O cmp_si.c
+gcc -c -I. -I.. -I../mpn -g -O cmp_ui.c
+gcc -c -I. -I.. -I../mpn -g -O div.c
+gcc -c -I. -I.. -I../mpn -g -O div_2exp.c
+gcc -c -I. -I.. -I../mpn -g -O div_ui.c
+gcc -c -I. -I.. -I../mpn -g -O dump.c
+gcc -c -I. -I.. -I../mpn -g -O eq.c
+gcc -c -I. -I.. -I../mpn -g -O get_d.c
+gcc -c -I. -I.. -I../mpn -g -O get_prc.c
+gcc -c -I. -I.. -I../mpn -g -O get_str.c
+gcc -c -I. -I.. -I../mpn -g -O init.c
+gcc -c -I. -I.. -I../mpn -g -O init2.c
+gcc -c -I. -I.. -I../mpn -g -O inp_str.c
+gcc -c -I. -I.. -I../mpn -g -O iset.c
+gcc -c -I. -I.. -I../mpn -g -O iset_d.c
+gcc -c -I. -I.. -I../mpn -g -O iset_si.c
+gcc -c -I. -I.. -I../mpn -g -O iset_str.c
+gcc -c -I. -I.. -I../mpn -g -O iset_ui.c
+gcc -c -I. -I.. -I../mpn -g -O mul.c
+gcc -c -I. -I.. -I../mpn -g -O mul_2exp.c
+gcc -c -I. -I.. -I../mpn -g -O mul_ui.c
+gcc -c -I. -I.. -I../mpn -g -O neg.c
+gcc -c -I. -I.. -I../mpn -g -O out_str.c
+gcc -c -I. -I.. -I../mpn -g -O random2.c
+gcc -c -I. -I.. -I../mpn -g -O reldiff.c
+gcc -c -I. -I.. -I../mpn -g -O set.c
+gcc -c -I. -I.. -I../mpn -g -O set_d.c
+gcc -c -I. -I.. -I../mpn -g -O set_dfl_prc.c
+gcc -c -I. -I.. -I../mpn -g -O set_prc.c
+gcc -c -I. -I.. -I../mpn -g -O set_prc_raw.c
+gcc -c -I. -I.. -I../mpn -g -O set_q.c
+gcc -c -I. -I.. -I../mpn -g -O set_si.c
+gcc -c -I. -I.. -I../mpn -g -O set_str.c
+gcc -c -I. -I.. -I../mpn -g -O set_ui.c
+gcc -c -I. -I.. -I../mpn -g -O set_z.c
+gcc -c -I. -I.. -I../mpn -g -O size.c
+gcc -c -I. -I.. -I../mpn -g -O sqrt.c
+gcc -c -I. -I.. -I../mpn -g -O sqrt_ui.c
+gcc -c -I. -I.. -I../mpn -g -O sub.c
+gcc -c -I. -I.. -I../mpn -g -O sub_ui.c
+gcc -c -I. -I.. -I../mpn -g -O ui_div.c
+gcc -c -I. -I.. -I../mpn -g -O ui_sub.c
+del libmpf.a
+ar cr libmpf.a *.o
+cd ..
+
+cd mpq
+gcc -c -I. -I.. -I../mpn -g -O add.c
+gcc -c -I. -I.. -I../mpn -g -O canonicalize.c
+gcc -c -I. -I.. -I../mpn -g -O clear.c
+gcc -c -I. -I.. -I../mpn -g -O cmp.c
+gcc -c -I. -I.. -I../mpn -g -O cmp_ui.c
+gcc -c -I. -I.. -I../mpn -g -O div.c
+gcc -c -I. -I.. -I../mpn -g -O equal.c
+gcc -c -I. -I.. -I../mpn -g -O get_d.c
+gcc -c -I. -I.. -I../mpn -g -O get_den.c
+gcc -c -I. -I.. -I../mpn -g -O get_num.c
+gcc -c -I. -I.. -I../mpn -g -O init.c
+gcc -c -I. -I.. -I../mpn -g -O inv.c
+gcc -c -I. -I.. -I../mpn -g -O mul.c
+gcc -c -I. -I.. -I../mpn -g -O neg.c
+gcc -c -I. -I.. -I../mpn -g -O set.c
+gcc -c -I. -I.. -I../mpn -g -O set_den.c
+gcc -c -I. -I.. -I../mpn -g -O set_num.c
+gcc -c -I. -I.. -I../mpn -g -O set_si.c
+gcc -c -I. -I.. -I../mpn -g -O set_ui.c
+gcc -c -I. -I.. -I../mpn -g -O set_z.c
+gcc -c -I. -I.. -I../mpn -g -O sub.c
+del libmpq.a
+ar cr libmpq.a *.o
+cd ..
+
+gcc -c -I. -Impn -I.. -g -O extract-double.c
+gcc -c -I. -Impn -I.. -g -O insert-double.c
+gcc -c -I. -Impn -I.. -g -O memory.c
+gcc -c -I. -Impn -I.. -g -O mp_clz_tab.c
+gcc -c -I. -Impn -I.. -g -O mp_set_fns.c
+gcc -c -I. -Impn -I.. -g -O stack-alloc.c
+gcc -c -I. -Impn -I.. -g -O version.c
+deltree/y tmpdir
+
+md tmpdir
+
+md tmpdir\mpn
+cd tmpdir\mpn
+ar x ../../mpn/libmpn.a
+cd ..\..
+
+md tmpdir\mpz
+cd tmpdir\mpz
+ar x ../../mpz/libmpz.a
+cd ..\..
+
+md tmpdir\mpq
+cd tmpdir\mpq
+ar x ../../mpq/libmpq.a
+cd ..\..
+
+md tmpdir\mpf
+cd tmpdir\mpf
+ar x ../../mpf/libmpf.a
+cd ..\..
+
+copy memory.o tmpdir
+copy mp_set_fns.o tmpdir
+copy mp_clz_tab.o tmpdir
+copy version.o tmpdir
+copy stack-alloc.o tmpdir
+
+cd tmpdir
+ar rc libgmp.a *.o */*.o
+ranlib libgmp.a
+cd ..
+
+move/y tmpdir\libgmp.a libgmp.a
+deltree/y tmpdir
diff --git a/contrib/libgmp/memory.c b/contrib/libgmp/memory.c new file mode 100644 index 0000000..9ee1da8 --- /dev/null +++ b/contrib/libgmp/memory.c @@ -0,0 +1,97 @@ +/* Memory allocation routines. + +Copyright (C) 1991, 1993, 1994 Free Software Foundation, Inc. + +This file is part of the GNU MP Library. + +The GNU MP Library is free software; you can redistribute it and/or modify +it under the terms of the GNU Library General Public License as published by +the Free Software Foundation; either version 2 of the License, or (at your +option) any later version. + +The GNU MP Library is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public +License for more details. + +You should have received a copy of the GNU Library General Public License +along with the GNU MP Library; see the file COPYING.LIB. If not, write to +the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, +MA 02111-1307, USA. */ + +#include <stdio.h> + +#include "gmp.h" +#include "gmp-impl.h" + +#ifdef __NeXT__ +#define static +#endif + +#if __STDC__ +void * (*_mp_allocate_func) (size_t) = _mp_default_allocate; +void * (*_mp_reallocate_func) (void *, size_t, size_t) + = _mp_default_reallocate; +void (*_mp_free_func) (void *, size_t) = _mp_default_free; +#else +void * (*_mp_allocate_func) () = _mp_default_allocate; +void * (*_mp_reallocate_func) () = _mp_default_reallocate; +void (*_mp_free_func) () = _mp_default_free; +#endif + +/* Default allocation functions. In case of failure to allocate/reallocate + an error message is written to stderr and the program aborts. */ + +void * +#if __STDC__ +_mp_default_allocate (size_t size) +#else +_mp_default_allocate (size) + size_t size; +#endif +{ + void *ret; + + ret = malloc (size); + if (ret == 0) + { + perror ("cannot allocate in gmp"); + abort (); + } + + return ret; +} + +void * +#if __STDC__ +_mp_default_reallocate (void *oldptr, size_t old_size, size_t new_size) +#else +_mp_default_reallocate (oldptr, old_size, new_size) + void *oldptr; + size_t old_size; + size_t new_size; +#endif +{ + void *ret; + + ret = realloc (oldptr, new_size); + if (ret == 0) + { + perror ("cannot allocate in gmp"); + abort (); + } + + return ret; +} + +void +#if __STDC__ +_mp_default_free (void *blk_ptr, size_t blk_size) +#else +_mp_default_free (blk_ptr, blk_size) + void *blk_ptr; + size_t blk_size; +#endif +{ + free (blk_ptr); +} diff --git a/contrib/libgmp/mkinstalldirs b/contrib/libgmp/mkinstalldirs new file mode 100755 index 0000000..cd1fe0a --- /dev/null +++ b/contrib/libgmp/mkinstalldirs @@ -0,0 +1,32 @@ +#! /bin/sh +# mkinstalldirs --- make directory hierarchy +# Author: Noah Friedman <friedman@prep.ai.mit.edu> +# Created: 1993-05-16 +# Public domain + +errstatus=0 + +for file +do + set fnord `echo ":$file" | sed -ne 's/^:\//#/;s/^://;s/\// /g;s/^#/\//;p'` + shift + + pathcomp= + for d in ${1+"$@"} ; do + pathcomp="$pathcomp$d" + case "$pathcomp" in + -* ) pathcomp=./$pathcomp ;; + esac + + if test ! -d "$pathcomp"; then + echo "mkdir $pathcomp" 1>&2 + mkdir "$pathcomp" || errstatus=$? + fi + + pathcomp="$pathcomp/" + done +done + +exit $errstatus + +# mkinstalldirs ends here diff --git a/contrib/libgmp/move-if-change b/contrib/libgmp/move-if-change new file mode 100755 index 0000000..ee9e355 --- /dev/null +++ b/contrib/libgmp/move-if-change @@ -0,0 +1,15 @@ +#!/bin/sh +if +test -r $2 +then +if +cmp $1 $2 > /dev/null +then +echo $2 is unchanged +rm -f $1 +else +mv -f $1 $2 +fi +else +mv -f $1 $2 +fi diff --git a/contrib/libgmp/mp.h b/contrib/libgmp/mp.h new file mode 100644 index 0000000..830b26b --- /dev/null +++ b/contrib/libgmp/mp.h @@ -0,0 +1,141 @@ +/* mp.h -- Definitions for Berkeley compatible multiple precision functions. + +Copyright (C) 1991, 1993, 1994, 1995, 1996 Free Software Foundation, Inc. + +This file is part of the GNU MP Library. + +The GNU MP Library is free software; you can redistribute it and/or modify +it under the terms of the GNU Library General Public License as published by +the Free Software Foundation; either version 2 of the License, or (at your +option) any later version. + +The GNU MP Library is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public +License for more details. + +You should have received a copy of the GNU Library General Public License +along with the GNU MP Library; see the file COPYING.LIB. If not, write to +the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, +MA 02111-1307, USA. */ + +#ifndef __MP_H__ + +#ifndef __GNU_MP__ +#define __GNU_MP__ 2 +#define __need_size_t +#include <stddef.h> +#undef __need_size_t + +#if defined (__STDC__) || defined (__cplusplus) +#define __gmp_const const +#else +#define __gmp_const +#endif + +#if defined (__GNUC__) +#define __gmp_inline __inline__ +#else +#define __gmp_inline +#endif + +#ifndef _EXTERN_INLINE +#ifdef __GNUC__ +#define _EXTERN_INLINE extern __inline__ +#else +#define _EXTERN_INLINE static +#endif +#endif + +#ifdef _SHORT_LIMB +typedef unsigned int mp_limb_t; +typedef int mp_limb_signed_t; +#else +#ifdef _LONG_LONG_LIMB +typedef unsigned long long int mp_limb_t; +typedef long long int mp_limb_signed_t; +#else +typedef unsigned long int mp_limb_t; +typedef long int mp_limb_signed_t; +#endif +#endif + +typedef mp_limb_t * mp_ptr; +typedef __gmp_const mp_limb_t * mp_srcptr; +typedef int mp_size_t; +typedef long int mp_exp_t; + +#ifndef __MP_SMALL__ +typedef struct +{ + mp_size_t _mp_alloc; /* Number of *limbs* allocated and pointed + to by the D field. */ + mp_size_t _mp_size; /* abs(SIZE) is the number of limbs + the last field points to. If SIZE + is negative this is a negative + number. */ + mp_limb_t *_mp_d; /* Pointer to the limbs. */ +} __mpz_struct; +#else +typedef struct +{ + short int _mp_alloc; /* Number of *limbs* allocated and pointed + to by the D field. */ + short int _mp_size; /* abs(SIZE) is the number of limbs + the last field points to. If SIZE + is negative this is a negative + number. */ + mp_limb_t *_mp_d; /* Pointer to the limbs. */ +} __mpz_struct; +#endif +#endif /* __GNU_MP__ */ + +/* User-visible types. */ +typedef __mpz_struct MINT; + +#ifdef __STDC__ +void mp_set_memory_functions (void *(*) (size_t), + void *(*) (void *, size_t, size_t), + void (*) (void *, size_t)); +MINT *itom (signed short int); +MINT *xtom (const char *); +void move (const MINT *, MINT *); +void madd (const MINT *, const MINT *, MINT *); +void msub (const MINT *, const MINT *, MINT *); +void mult (const MINT *, const MINT *, MINT *); +void mdiv (const MINT *, const MINT *, MINT *, MINT *); +void sdiv (const MINT *, signed short int, MINT *, signed short int *); +void msqrt (const MINT *, MINT *, MINT *); +void pow (const MINT *, const MINT *, const MINT *, MINT *); +void rpow (const MINT *, signed short int, MINT *); +void gcd (const MINT *, const MINT *, MINT *); +int mcmp (const MINT *, const MINT *); +void min (MINT *); +void mout (const MINT *); +char *mtox (const MINT *); +void mfree (MINT *); + +#else + +void mp_set_memory_functions (); +MINT *itom (); +MINT *xtom (); +void move (); +void madd (); +void msub (); +void mult (); +void mdiv (); +void sdiv (); +void msqrt (); +void pow (); +void rpow (); +void gcd (); +int mcmp (); +void min (); +void mout (); +char *mtox (); +void mfree (); +#endif + +#define __MP_H__ +#endif /* __MP_H__ */ diff --git a/contrib/libgmp/mp_bpl.c b/contrib/libgmp/mp_bpl.c new file mode 100644 index 0000000..d817ac8 --- /dev/null +++ b/contrib/libgmp/mp_bpl.c @@ -0,0 +1,4 @@ +#include "gmp.h" +#include "gmp-impl.h" + +const int mp_bits_per_limb = BITS_PER_MP_LIMB; diff --git a/contrib/libgmp/mp_clz_tab.c b/contrib/libgmp/mp_clz_tab.c new file mode 100644 index 0000000..6fd7e90 --- /dev/null +++ b/contrib/libgmp/mp_clz_tab.c @@ -0,0 +1,40 @@ +/* __clz_tab -- support for longlong.h + +Copyright (C) 1991, 1993, 1994, 1996 Free Software Foundation, Inc. + +This file is part of the GNU MP Library. + +The GNU MP Library is free software; you can redistribute it and/or modify +it under the terms of the GNU Library General Public License as published by +the Free Software Foundation; either version 2 of the License, or (at your +option) any later version. + +The GNU MP Library is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public +License for more details. + +You should have received a copy of the GNU Library General Public License +along with the GNU MP Library; see the file COPYING.LIB. If not, write to +the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, +MA 02111-1307, USA. */ + +#if 0 +#include "gmp.h" +#include "gmp-impl.h" +#endif + +#if 0 +const +#endif +unsigned char __clz_tab[] = +{ + 0,1,2,2,3,3,3,3,4,4,4,4,4,4,4,4,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6, + 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7, + 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7, + 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, + 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, + 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, + 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, +}; diff --git a/contrib/libgmp/mp_set_fns.c b/contrib/libgmp/mp_set_fns.c new file mode 100644 index 0000000..35a462c --- /dev/null +++ b/contrib/libgmp/mp_set_fns.c @@ -0,0 +1,48 @@ +/* mp_set_memory_functions -- Set the allocate, reallocate, and free functions + for use by the mp package. + +Copyright (C) 1991, 1993, 1994 Free Software Foundation, Inc. + +This file is part of the GNU MP Library. + +The GNU MP Library is free software; you can redistribute it and/or modify +it under the terms of the GNU Library General Public License as published by +the Free Software Foundation; either version 2 of the License, or (at your +option) any later version. + +The GNU MP Library is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public +License for more details. + +You should have received a copy of the GNU Library General Public License +along with the GNU MP Library; see the file COPYING.LIB. If not, write to +the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, +MA 02111-1307, USA. */ + +#include "gmp.h" +#include "gmp-impl.h" + +void +#if __STDC__ +mp_set_memory_functions (void *(*alloc_func) (size_t), + void *(*realloc_func) (void *, size_t, size_t), + void (*free_func) (void *, size_t)) +#else +mp_set_memory_functions (alloc_func, realloc_func, free_func) + void *(*alloc_func) (); + void *(*realloc_func) (); + void (*free_func) (); +#endif +{ + if (alloc_func == 0) + alloc_func = _mp_default_allocate; + if (realloc_func == 0) + realloc_func = _mp_default_reallocate; + if (free_func == 0) + free_func = _mp_default_free; + + _mp_allocate_func = alloc_func; + _mp_reallocate_func = realloc_func; + _mp_free_func = free_func; +} diff --git a/contrib/libgmp/mpbsd/Makefile.in b/contrib/libgmp/mpbsd/Makefile.in new file mode 100644 index 0000000..a517c1a --- /dev/null +++ b/contrib/libgmp/mpbsd/Makefile.in @@ -0,0 +1,84 @@ +# Makefile for GNU MP/mpbsd functions +# Copyright (C) 1991, 1993, 1994, 1996 Free Software Foundation, Inc. + +# This file is part of the GNU MP Library. + +# The GNU MP Library is free software; you can redistribute it and/or modify +# it under the terms of the GNU Library General Public License as published by +# the Free Software Foundation; either version 2 of the License, or (at your +# option) any later version. + +# The GNU MP Library is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +# or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public +# License for more details. + +# You should have received a copy of the GNU Library General Public License +# along with the GNU MP Library; see the file COPYING.LIB. If not, write to +# the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, +# MA 02111-1307, USA. + +srcdir = . + +CC = gcc + +# If you cross compile on a machine with the same sizes of the integral +# types ("int", "long int", "short int", and "char") define this as the +# local compiler. Otherwise, you need to look for the uses of LOCAL_CC below, +# and handle those cases manually. +LOCAL_CC = $(CC) +CFLAGS = -g -O +AR = ar +SHELL = /bin/sh + +#### host and target specific makefile fragments come in here. +### + +MPBSD_LINKS = add.c cmp.c gcd.c mul.c pow_ui.c powm.c sqrtrem.c sub.c +MPBSD_SRCS = itom.c mdiv.c mfree.c min.c mout.c move.c mtox.c sdiv.c xtom.c \ + realloc.c $(MPBSD_LINKS) + +MPBSD_OBJS = itom.o mdiv.o mfree.o min.o mout.o move.o mtox.o sdiv.o xtom.o \ + realloc.o add.o cmp.o gcd.o mul.o pow_ui.o powm.o sqrtrem.o sub.o + +INCLUDES = -I. -I.. -I$(srcdir)/../mpz -I../mpn -I$(srcdir)/.. + +libmpbsd.a: Makefile.in $(MPBSD_OBJS) + rm -f $@ + $(AR) cr $@ $(MPBSD_OBJS) + +.c.o: + $(CC) -c $(INCLUDES) -DBERKELEY_MP $(CFLAGS) $(XCFLAGS) $< + +check: + true + +clean mostlyclean: + rm -f *.o libmpbsd.a +distclean maintainer-clean: clean + rm -f Makefile config.status $(MPBSD_LINKS) + +Makefile: $(srcdir)/Makefile.in + $(SHELL) ./config.status + +H = $(srcdir)/../gmp.h $(srcdir)/../gmp-impl.h ../mpn/gmp-mparam.h +L = $(srcdir)/../longlong.h + +itom.o: $(srcdir)/itom.c ../mp.h $(H) +mdiv.o: $(srcdir)/mdiv.c ../mp.h $(H) $(L) $(srcdir)/../mpz/dmincl.c +mfree.o: $(srcdir)/mfree.c ../mp.h $(H) +min.o: $(srcdir)/min.c ../mp.h $(H) +mout.o: $(srcdir)/mout.c ../mp.h $(H) +move.o: $(srcdir)/move.c ../mp.h $(H) +mtox.o: $(srcdir)/mtox.c ../mp.h $(H) +sdiv.o: $(srcdir)/sdiv.c ../mp.h $(H) $(L) +xtom.o: $(srcdir)/xtom.c ../mp.h $(H) +add.o: $(srcdir)/../mpz/add.c $(H) +cmp.o: $(srcdir)/../mpz/cmp.c $(H) +gcd.o: $(srcdir)/../mpz/gcd.c $(H) $(L) +mul.o: $(srcdir)/../mpz/mul.c $(H) +pow_ui.o: $(srcdir)/../mpz/pow_ui.c $(H) $(L) +powm.o: $(srcdir)/../mpz/powm.c $(H) $(L) +realloc.o: $(srcdir)/realloc.c $(H) +sqrtrem.o: $(srcdir)/../mpz/sqrtrem.c $(H) +sub.o: $(srcdir)/../mpz/sub.c $(H) diff --git a/contrib/libgmp/mpbsd/configure.in b/contrib/libgmp/mpbsd/configure.in new file mode 100644 index 0000000..ec22075 --- /dev/null +++ b/contrib/libgmp/mpbsd/configure.in @@ -0,0 +1,20 @@ +# This file is a shell script fragment that supplies the information +# necessary for a configure script to process the program in +# this directory. For more information, look at ../configure. + +configdirs= +srctrigger=itom.c +srcname="GNU Multi-Precision library/mpbsd" + +# per-host: + +# per-target: + +mpzfiles="add.c cmp.c gcd.c mul.c pow_ui.c powm.c sqrtrem.c sub.c" + +for fn in $mpzfiles + do + rm -f $fn + files="$files ../mpz/$fn" + links="$links $fn" + done diff --git a/contrib/libgmp/mpbsd/itom.c b/contrib/libgmp/mpbsd/itom.c new file mode 100644 index 0000000..719a4dc --- /dev/null +++ b/contrib/libgmp/mpbsd/itom.c @@ -0,0 +1,54 @@ +/* itom -- BSD compatible allocate and initiate a MINT. + +Copyright (C) 1991, 1994, 1995 Free Software Foundation, Inc. + +This file is part of the GNU MP Library. + +The GNU MP Library is free software; you can redistribute it and/or modify +it under the terms of the GNU Library General Public License as published by +the Free Software Foundation; either version 2 of the License, or (at your +option) any later version. + +The GNU MP Library is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public +License for more details. + +You should have received a copy of the GNU Library General Public License +along with the GNU MP Library; see the file COPYING.LIB. If not, write to +the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, +MA 02111-1307, USA. */ + +#include "mp.h" +#include "gmp.h" +#include "gmp-impl.h" + +MINT * +#if __STDC__ +itom (signed short int n) +#else +itom (n) + short int n; +#endif +{ + MINT *x; + mp_ptr xp; + + x = (MINT *) (*_mp_allocate_func) (sizeof (MINT)); + x->_mp_alloc = 1; + x->_mp_d = xp = (mp_ptr) (*_mp_allocate_func) (BYTES_PER_MP_LIMB); + if (n > 0) + { + x->_mp_size = 1; + xp[0] = n; + } + else if (n < 0) + { + x->_mp_size = -1; + xp[0] = -n; + } + else + x->_mp_size = 0; + + return x; +} diff --git a/contrib/libgmp/mpbsd/mdiv.c b/contrib/libgmp/mpbsd/mdiv.c new file mode 100644 index 0000000..103c2c3 --- /dev/null +++ b/contrib/libgmp/mpbsd/mdiv.c @@ -0,0 +1,39 @@ +/* mdiv -- BSD compatible divide producing both remainder and quotient. + +Copyright (C) 1991, 1994, 1996 Free Software Foundation, Inc. + +This file is part of the GNU MP Library. + +The GNU MP Library is free software; you can redistribute it and/or modify +it under the terms of the GNU Library General Public License as published by +the Free Software Foundation; either version 2 of the License, or (at your +option) any later version. + +The GNU MP Library is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public +License for more details. + +You should have received a copy of the GNU Library General Public License +along with the GNU MP Library; see the file COPYING.LIB. If not, write to +the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, +MA 02111-1307, USA. */ + +#include "mp.h" +#include "gmp.h" +#include "gmp-impl.h" +#include "longlong.h" + +void +#if __STDC__ +mdiv (const MINT *num, const MINT *den, MINT *quot, MINT *rem) +#else +mdiv (num, den, quot, rem) + const MINT *num; + const MINT *den; + MINT *quot; + MINT *rem; +#endif + +#define COMPUTE_QUOTIENT +#include "dmincl.c" diff --git a/contrib/libgmp/mpbsd/mfree.c b/contrib/libgmp/mpbsd/mfree.c new file mode 100644 index 0000000..ef931e3 --- /dev/null +++ b/contrib/libgmp/mpbsd/mfree.c @@ -0,0 +1,36 @@ +/* mfree -- BSD compatible mfree. + +Copyright (C) 1991, 1994, 1995 Free Software Foundation, Inc. + +This file is part of the GNU MP Library. + +The GNU MP Library is free software; you can redistribute it and/or modify +it under the terms of the GNU Library General Public License as published by +the Free Software Foundation; either version 2 of the License, or (at your +option) any later version. + +The GNU MP Library is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public +License for more details. + +You should have received a copy of the GNU Library General Public License +along with the GNU MP Library; see the file COPYING.LIB. If not, write to +the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, +MA 02111-1307, USA. */ + +#include "mp.h" +#include "gmp.h" +#include "gmp-impl.h" + +void +#if __STDC__ +mfree (MINT *m) +#else +mfree (m) + MINT *m; +#endif +{ + (*_mp_free_func) (m->_mp_d, m->_mp_alloc * BYTES_PER_MP_LIMB); + (*_mp_free_func) (m, sizeof (MINT)); +} diff --git a/contrib/libgmp/mpbsd/min.c b/contrib/libgmp/mpbsd/min.c new file mode 100644 index 0000000..6edb171 --- /dev/null +++ b/contrib/libgmp/mpbsd/min.c @@ -0,0 +1,89 @@ +/* min(MINT) -- Do decimal input from standard input and store result in + MINT. + +Copyright (C) 1991, 1994 Free Software Foundation, Inc. + +This file is part of the GNU MP Library. + +The GNU MP Library is free software; you can redistribute it and/or modify +it under the terms of the GNU Library General Public License as published by +the Free Software Foundation; either version 2 of the License, or (at your +option) any later version. + +The GNU MP Library is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public +License for more details. + +You should have received a copy of the GNU Library General Public License +along with the GNU MP Library; see the file COPYING.LIB. If not, write to +the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, +MA 02111-1307, USA. */ + +#include <stdio.h> +#include <ctype.h> +#include "mp.h" +#include "gmp.h" +#include "gmp-impl.h" + +void +#if __STDC__ +min (MINT *dest) +#else +min (dest) + MINT *dest; +#endif +{ + char *str; + size_t alloc_size, str_size; + int c; + int negative; + mp_size_t dest_size; + + alloc_size = 100; + str = (char *) (*_mp_allocate_func) (alloc_size); + str_size = 0; + + /* Skip whitespace. */ + do + c = getc (stdin); + while (isspace (c)); + + negative = 0; + if (c == '-') + { + negative = 1; + c = getc (stdin); + } + + if (digit_value_in_base (c, 10) < 0) + return; /* error if no digits */ + + for (;;) + { + int dig; + if (str_size >= alloc_size) + { + size_t old_alloc_size = alloc_size; + alloc_size = alloc_size * 3 / 2; + str = (char *) (*_mp_reallocate_func) (str, old_alloc_size, alloc_size); + } + dig = digit_value_in_base (c, 10); + if (dig < 0) + break; + str[str_size++] = dig; + c = getc (stdin); + } + + ungetc (c, stdin); + + dest_size = str_size / __mp_bases[10].chars_per_limb + 1; + if (dest->_mp_alloc < dest_size) + _mp_realloc (dest, dest_size); + + dest_size = mpn_set_str (dest->_mp_d, (unsigned char *) str, str_size, 10); + dest->_mp_size = negative ? -dest_size : dest_size; + + (*_mp_free_func) (str, alloc_size); + return; +} diff --git a/contrib/libgmp/mpbsd/mout.c b/contrib/libgmp/mpbsd/mout.c new file mode 100644 index 0000000..a6b62be --- /dev/null +++ b/contrib/libgmp/mpbsd/mout.c @@ -0,0 +1,96 @@ +/* mout(MINT) -- Do decimal output of MINT to standard output. + +Copyright (C) 1991, 1994, 1996 Free Software Foundation, Inc. + +This file is part of the GNU MP Library. + +The GNU MP Library is free software; you can redistribute it and/or modify +it under the terms of the GNU Library General Public License as published by +the Free Software Foundation; either version 2 of the License, or (at your +option) any later version. + +The GNU MP Library is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public +License for more details. + +You should have received a copy of the GNU Library General Public License +along with the GNU MP Library; see the file COPYING.LIB. If not, write to +the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, +MA 02111-1307, USA. */ + +#include <stdio.h> +#include "mp.h" +#include "gmp.h" +#include "gmp-impl.h" + +void +#if __STDC__ +mout (const MINT *x) +#else +mout (x) + const MINT *x; +#endif +{ + mp_ptr xp; + mp_size_t x_size = x->_mp_size; + unsigned char *str; + size_t str_size; + char *num_to_text; + int i; + TMP_DECL (marker); + + if (x_size == 0) + { + fputc ('0', stdout); + return; + } + if (x_size < 0) + { + fputc ('-', stdout); + x_size = -x_size; + } + + TMP_MARK (marker); + str_size = ((size_t) (x_size * BITS_PER_MP_LIMB + * __mp_bases[10].chars_per_bit_exactly)) + 3; + str = (unsigned char *) TMP_ALLOC (str_size); + + /* Move the number to convert into temporary space, since mpn_get_str + clobbers its argument + needs one extra high limb.... */ + xp = (mp_ptr) TMP_ALLOC ((x_size + 1) * BYTES_PER_MP_LIMB); + MPN_COPY (xp, x->_mp_d, x_size); + + str_size = mpn_get_str (str, 10, xp, x_size); + + /* mpn_get_str might make some leading zeros. Skip them. */ + while (*str == 0) + { + str_size--; + str++; + } + + /* Translate to printable chars. */ + for (i = 0; i < str_size; i++) + str[i] = "0123456789"[str[i]]; + str[str_size] = 0; + + str_size = strlen (str); + if (str_size % 10 != 0) + { + fwrite (str, 1, str_size % 10, stdout); + str += str_size % 10; + str_size -= str_size % 10; + if (str_size != 0) + fputc (' ', stdout); + } + for (i = 0; i < str_size; i += 10) + { + fwrite (str, 1, 10, stdout); + str += 10; + if (i + 10 < str_size) + fputc (' ', stdout); + } + fputc ('\n', stdout); + TMP_FREE (marker); +} diff --git a/contrib/libgmp/mpbsd/move.c b/contrib/libgmp/mpbsd/move.c new file mode 100644 index 0000000..8256cc7 --- /dev/null +++ b/contrib/libgmp/mpbsd/move.c @@ -0,0 +1,46 @@ +/* move -- BSD compatible assignment. + +Copyright (C) 1991, 1994, 1995 Free Software Foundation, Inc. + +This file is part of the GNU MP Library. + +The GNU MP Library is free software; you can redistribute it and/or modify +it under the terms of the GNU Library General Public License as published by +the Free Software Foundation; either version 2 of the License, or (at your +option) any later version. + +The GNU MP Library is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public +License for more details. + +You should have received a copy of the GNU Library General Public License +along with the GNU MP Library; see the file COPYING.LIB. If not, write to +the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, +MA 02111-1307, USA. */ + +#include "mp.h" +#include "gmp.h" +#include "gmp-impl.h" + +void +#if __STDC__ +move (const MINT *u, MINT *w) +#else +move (u, w) + const MINT *u; + MINT *w; +#endif +{ + mp_size_t usize; + mp_size_t abs_usize; + + usize = u->_mp_size; + abs_usize = ABS (usize); + + if (w->_mp_alloc < abs_usize) + _mp_realloc (w, abs_usize); + + w->_mp_size = usize; + MPN_COPY (w->_mp_d, u->_mp_d, abs_usize); +} diff --git a/contrib/libgmp/mpbsd/mtox.c b/contrib/libgmp/mpbsd/mtox.c new file mode 100644 index 0000000..8baec2a --- /dev/null +++ b/contrib/libgmp/mpbsd/mtox.c @@ -0,0 +1,81 @@ +/* mtox -- Convert OPERAND to hexadecimal and return a malloc'ed string + with the result of the conversion. + +Copyright (C) 1991, 1994 Free Software Foundation, Inc. + +This file is part of the GNU MP Library. + +The GNU MP Library is free software; you can redistribute it and/or modify +it under the terms of the GNU Library General Public License as published by +the Free Software Foundation; either version 2 of the License, or (at your +option) any later version. + +The GNU MP Library is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public +License for more details. + +You should have received a copy of the GNU Library General Public License +along with the GNU MP Library; see the file COPYING.LIB. If not, write to +the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, +MA 02111-1307, USA. */ + +#include "mp.h" +#include "gmp.h" +#include "gmp-impl.h" + +char * +#if __STDC__ +mtox (const MINT *x) +#else +mtox (x) + const MINT *x; +#endif +{ + mp_ptr xp; + mp_size_t xsize = x->_mp_size; + mp_size_t xsign; + unsigned char *str, *s; + size_t str_size, i; + int zeros; + char *num_to_text; + TMP_DECL (marker); + + if (xsize == 0) + { + str = (unsigned char *) (*_mp_allocate_func) (2); + str[0] = '0'; + str[1] = 0; + return str; + } + xsign = xsize; + if (xsize < 0) + xsize = -xsize; + + TMP_MARK (marker); + str_size = ((size_t) (xsize * BITS_PER_MP_LIMB + * __mp_bases[16].chars_per_bit_exactly)) + 3; + str = (unsigned char *) (*_mp_allocate_func) (str_size); + s = str; + + if (xsign < 0) + *s++ = '-'; + + /* Move the number to convert into temporary space, since mpn_get_str + clobbers its argument + needs one extra high limb.... */ + xp = (mp_ptr) TMP_ALLOC ((xsize + 1) * BYTES_PER_MP_LIMB); + MPN_COPY (xp, x->_mp_d, xsize); + + str_size = mpn_get_str (s, 16, xp, xsize); + + /* mpn_get_str might make some leading zeros. Skip them. */ + for (zeros = 0; s[zeros] == 0; zeros++) + str_size--; + + /* Translate to printable chars and move string down. */ + for (i = 0; i < str_size; i++) + s[i] = "0123456789abcdef"[s[zeros + i]]; + s[str_size] = 0; + + return str; +} diff --git a/contrib/libgmp/mpbsd/realloc.c b/contrib/libgmp/mpbsd/realloc.c new file mode 100644 index 0000000..64bee76 --- /dev/null +++ b/contrib/libgmp/mpbsd/realloc.c @@ -0,0 +1,44 @@ +/* _mp_realloc -- make the MINT* have NEW_SIZE digits allocated. + +Copyright (C) 1991, 1993, 1994, 1995 Free Software Foundation, Inc. + +This file is part of the GNU MP Library. + +The GNU MP Library is free software; you can redistribute it and/or modify +it under the terms of the GNU Library General Public License as published by +the Free Software Foundation; either version 2 of the License, or (at your +option) any later version. + +The GNU MP Library is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public +License for more details. + +You should have received a copy of the GNU Library General Public License +along with the GNU MP Library; see the file COPYING.LIB. If not, write to +the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, +MA 02111-1307, USA. */ + +#include "mp.h" +#include "gmp.h" +#include "gmp-impl.h" + +void * +#if __STDC__ +_mp_realloc (MINT *m, mp_size_t new_size) +#else +_mp_realloc (m, new_size) + MINT *m; + mp_size_t new_size; +#endif +{ + /* Never allocate zero space. */ + if (new_size == 0) + new_size = 1; + + m->_mp_d = (mp_ptr) (*_mp_reallocate_func) (m->_mp_d, + m->_mp_alloc * BYTES_PER_MP_LIMB, + new_size * BYTES_PER_MP_LIMB); + m->_mp_alloc = new_size; + return (void *) m->_mp_d; +} diff --git a/contrib/libgmp/mpbsd/sdiv.c b/contrib/libgmp/mpbsd/sdiv.c new file mode 100644 index 0000000..6982e20 --- /dev/null +++ b/contrib/libgmp/mpbsd/sdiv.c @@ -0,0 +1,77 @@ +/* sdiv -- Divide a MINT by a short integer. Produce a MINT quotient + and a short remainder. + +Copyright (C) 1991, 1994, 1995 Free Software Foundation, Inc. + +This file is part of the GNU MP Library. + +The GNU MP Library is free software; you can redistribute it and/or modify +it under the terms of the GNU Library General Public License as published by +the Free Software Foundation; either version 2 of the License, or (at your +option) any later version. + +The GNU MP Library is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public +License for more details. + +You should have received a copy of the GNU Library General Public License +along with the GNU MP Library; see the file COPYING.LIB. If not, write to +the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, +MA 02111-1307, USA. */ + +#include "mp.h" +#include "gmp.h" +#include "gmp-impl.h" +#include "longlong.h" + +void +#if __STDC__ +sdiv (const MINT *dividend, signed short int divisor_short, MINT *quot, short *rem_ptr) +#else +sdiv (dividend, divisor_short, quot, rem_ptr) + const MINT *dividend; + short int divisor_short; + MINT *quot; + short *rem_ptr; +#endif +{ + mp_size_t sign_dividend; + signed long int sign_divisor; + mp_size_t dividend_size, quot_size; + mp_ptr dividend_ptr, quot_ptr; + mp_limb_t divisor_limb; + mp_limb_t remainder_limb; + + sign_dividend = dividend->_mp_size; + dividend_size = ABS (dividend->_mp_size); + + if (dividend_size == 0) + { + quot->_mp_size = 0; + *rem_ptr = 0; + return; + } + + sign_divisor = divisor_short; + divisor_limb = ABS (divisor_short); + + /* No need for temporary allocation and copying even if QUOT == DIVIDEND + as the divisor is just one limb, and thus no intermediate remainders + need to be stored. */ + + if (quot->_mp_alloc < dividend_size) + _mp_realloc (quot, dividend_size); + + quot_ptr = quot->_mp_d; + dividend_ptr = dividend->_mp_d; + + remainder_limb = mpn_divmod_1 (quot_ptr, + dividend_ptr, dividend_size, divisor_limb); + + *rem_ptr = sign_dividend >= 0 ? remainder_limb : -remainder_limb; + /* The quotient is DIVIDEND_SIZE limbs, but the most significant + might be zero. Set QUOT_SIZE properly. */ + quot_size = dividend_size - (quot_ptr[dividend_size - 1] == 0); + quot->_mp_size = (sign_divisor ^ sign_dividend) >= 0 ? quot_size : -quot_size; +} diff --git a/contrib/libgmp/mpbsd/xtom.c b/contrib/libgmp/mpbsd/xtom.c new file mode 100644 index 0000000..5a529e8 --- /dev/null +++ b/contrib/libgmp/mpbsd/xtom.c @@ -0,0 +1,110 @@ +/* xtom -- convert a hexadecimal string to a MINT, and return a pointer to + the MINT. + +Copyright (C) 1991, 1994, 1995 Free Software Foundation, Inc. + +This file is part of the GNU MP Library. + +The GNU MP Library is free software; you can redistribute it and/or modify +it under the terms of the GNU Library General Public License as published by +the Free Software Foundation; either version 2 of the License, or (at your +option) any later version. + +The GNU MP Library is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public +License for more details. + +You should have received a copy of the GNU Library General Public License +along with the GNU MP Library; see the file COPYING.LIB. If not, write to +the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, +MA 02111-1307, USA. */ + +#include "mp.h" +#include "gmp.h" +#include "gmp-impl.h" + +static int +digit_value_in_base (c, base) + int c; + int base; +{ + int digit; + + if (isdigit (c)) + digit = c - '0'; + else if (islower (c)) + digit = c - 'a' + 10; + else if (isupper (c)) + digit = c - 'A' + 10; + else + return -1; + + if (digit < base) + return digit; + return -1; +} + +MINT * +#if __STDC__ +xtom (const char *str) +#else +xtom (str) + const char *str; +#endif +{ + size_t str_size; + char *s, *begs; + size_t i; + mp_size_t xsize; + int c; + int negative; + MINT *x = (MINT *) (*_mp_allocate_func) (sizeof (MINT)); + TMP_DECL (marker); + + /* Skip whitespace. */ + do + c = *str++; + while (isspace (c)); + + negative = 0; + if (c == '-') + { + negative = 1; + c = *str++; + } + + if (digit_value_in_base (c, 16) < 0) + return 0; /* error if no digits */ + + TMP_MARK (marker); + str_size = strlen (str - 1); + s = begs = (char *) TMP_ALLOC (str_size + 1); + + for (i = 0; i < str_size; i++) + { + if (!isspace (c)) + { + int dig = digit_value_in_base (c, 16); + if (dig < 0) + { + TMP_FREE (marker); + return 0; + } + *s++ = dig; + } + c = *str++; + } + + str_size = s - begs; + + xsize = str_size / __mp_bases[16].chars_per_limb + 1; + x->_mp_alloc = xsize; + x->_mp_d = (mp_ptr) (*_mp_allocate_func) (xsize * BYTES_PER_MP_LIMB); + + xsize = mpn_set_str (x->_mp_d, (unsigned char *) begs, str_size, 16); + x->_mp_size = negative ? -xsize : xsize; + + TMP_FREE (marker); + return x; +} diff --git a/contrib/libgmp/mpf/Makefile.in b/contrib/libgmp/mpf/Makefile.in new file mode 100644 index 0000000..598fa72 --- /dev/null +++ b/contrib/libgmp/mpf/Makefile.in @@ -0,0 +1,115 @@ +# Makefile for GNU MP/mpf functions +# Copyright (C) 1991, 1993, 1994, 1996 Free Software Foundation, Inc. + +# This file is part of the GNU MP Library. + +# The GNU MP Library is free software; you can redistribute it and/or modify +# it under the terms of the GNU Library General Public License as published by +# the Free Software Foundation; either version 2 of the License, or (at your +# option) any later version. + +# The GNU MP Library is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +# or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public +# License for more details. + +# You should have received a copy of the GNU Library General Public License +# along with the GNU MP Library; see the file COPYING.LIB. If not, write to +# the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, +# MA 02111-1307, USA. + +srcdir = . + +CC = gcc + +CFLAGS = -g -O +AR = ar +AR_FLAGS = rc +SHELL = /bin/sh + +#### host and target specific makefile fragments come in here. +### + +MPF_SRCS = init.c init2.c set.c set_ui.c set_si.c set_str.c set_d.c set_z.c \ + iset.c iset_ui.c iset_si.c iset_str.c iset_d.c clear.c get_str.c \ + dump.c size.c eq.c reldiff.c sqrt.c random2.c inp_str.c out_str.c \ + add.c add_ui.c sub.c sub_ui.c ui_sub.c mul.c mul_ui.c div.c div_ui.c \ + cmp.c cmp_ui.c cmp_si.c mul_2exp.c div_2exp.c abs.c neg.c set_q.c get_d.c \ + set_dfl_prec.c set_prc.c set_prc_raw.c get_prc.c ui_div.c sqrt_ui.c +MPF_OBJS = init.o init2.o set.o set_ui.o set_si.o set_str.o set_d.o set_z.o \ + iset.o iset_ui.o iset_si.o iset_str.o iset_d.o clear.o get_str.o \ + dump.o size.o eq.o reldiff.o sqrt.o random2.o inp_str.o out_str.o \ + add.o add_ui.o sub.o sub_ui.o ui_sub.o mul.o mul_ui.o div.o div_ui.o \ + cmp.o cmp_ui.o cmp_si.o mul_2exp.o div_2exp.o abs.o neg.o set_q.o get_d.o \ + set_dfl_prec.o set_prc.o set_prc_raw.o get_prc.o ui_div.o sqrt_ui.o + +LATER_OBJS = inp_raw.o out_raw.o random.o pow_ui.o fac_ui.o + +INCLUDES = -I. -I.. -I../mpn -I$(srcdir)/.. + +libmpf.a: Makefile $(MPF_OBJS) + rm -f $@ + $(AR) $(AR_FLAGS) $@ $(MPF_OBJS) + +.c.o: + $(CC) -c $(INCLUDES) $(CFLAGS) $(XCFLAGS) $< + +clean mostlyclean: + rm -f *.o libmpf.a + -cd tests; $(MAKE) $@ +distclean maintainer-clean: clean + rm -f Makefile config.status + -cd tests; $(MAKE) $@ + +Makefile: $(srcdir)/Makefile.in + $(SHELL) ./config.status + +H = $(srcdir)/../gmp.h $(srcdir)/../gmp-impl.h ../mpn/gmp-mparam.h + +abs.o: $(srcdir)/abs.c $(H) +add.o: $(srcdir)/add.c $(H) +add_ui.o: $(srcdir)/add_ui.c $(H) +clear.o: $(srcdir)/clear.c $(H) +cmp.o: $(srcdir)/cmp.c $(H) +cmp_si.o: $(srcdir)/cmp_si.c $(H) +cmp_ui.o: $(srcdir)/cmp_ui.c $(H) +eq.o: $(srcdir)/eq.c $(H) +div.o: $(srcdir)/div.c $(H) $(srcdir)/../longlong.h +div_2exp.o: $(srcdir)/div_2exp.c $(H) +div_ui.o: $(srcdir)/div_ui.c $(H) $(srcdir)/../longlong.h +dump.o: $(srcdir)/dump.c $(H) +get_d.o: $(srcdir)/get_d.c $(H) +get_prc.o: $(srcdir)/get_prc.c $(H) +get_str.o: $(srcdir)/get_str.c $(H) $(srcdir)/../longlong.h +init.o: $(srcdir)/init.c $(H) +init2.o: $(srcdir)/init2.c $(H) +inp_str.o: $(srcdir)/inp_str.c $(H) +iset.o: $(srcdir)/iset.c $(H) +iset_d.o: $(srcdir)/iset_d.c $(H) +iset_si.o: $(srcdir)/iset_si.c $(H) +iset_str.o: $(srcdir)/iset_str.c $(H) +iset_ui.o: $(srcdir)/iset_ui.c $(H) +mul.o: $(srcdir)/mul.c $(H) +mul_2exp.o: $(srcdir)/mul_2exp.c $(H) +mul_ui.o: $(srcdir)/mul_ui.c $(H) +neg.o: $(srcdir)/neg.c $(H) +out_str.o: $(srcdir)/out_str.c $(H) +random2.o: $(srcdir)/random2.c $(H) +reldiff.o: $(srcdir)/reldiff.c $(H) +set.o: $(srcdir)/set.c $(H) +set_d.o: $(srcdir)/set_d.c $(H) +set_dfl_prec.o: $(srcdir)/set_dfl_prec.c $(H) +set_prc.o: $(srcdir)/set_prc.c $(H) +set_prc_raw.o: $(srcdir)/set_prc_raw.c $(H) +set_q.o: $(srcdir)/set_q.c $(H) +set_si.o: $(srcdir)/set_si.c $(H) +set_str.o: $(srcdir)/set_str.c $(H) $(srcdir)/../longlong.h +set_ui.o: $(srcdir)/set_ui.c $(H) +set_z.o: $(srcdir)/set_z.c $(H) +size.o: $(srcdir)/size.c $(H) +sqrt.o: $(srcdir)/sqrt.c $(H) +sqrt_ui.o: $(srcdir)/sqrt_ui.c $(H) +sub.o: $(srcdir)/sub.c $(H) +sub_ui.o: $(srcdir)/sub_ui.c $(H) +ui_div.o: $(srcdir)/ui_div.c $(H) $(srcdir)/../longlong.h +ui_sub.o: $(srcdir)/ui_sub.c $(H) diff --git a/contrib/libgmp/mpf/abs.c b/contrib/libgmp/mpf/abs.c new file mode 100644 index 0000000..029007a --- /dev/null +++ b/contrib/libgmp/mpf/abs.c @@ -0,0 +1,56 @@ +/* mpf_abs -- Compute the absolute value of a float. + +Copyright (C) 1993, 1994, 1995 Free Software Foundation, Inc. + +This file is part of the GNU MP Library. + +The GNU MP Library is free software; you can redistribute it and/or modify +it under the terms of the GNU Library General Public License as published by +the Free Software Foundation; either version 2 of the License, or (at your +option) any later version. + +The GNU MP Library is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public +License for more details. + +You should have received a copy of the GNU Library General Public License +along with the GNU MP Library; see the file COPYING.LIB. If not, write to +the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, +MA 02111-1307, USA. */ + +#include "gmp.h" +#include "gmp-impl.h" + +void +#if __STDC__ +mpf_abs (mpf_ptr r, mpf_srcptr u) +#else +mpf_abs (r, u) + mpf_ptr r; + mpf_srcptr u; +#endif +{ + mp_size_t size; + + size = ABS (u->_mp_size); + if (r != u) + { + mp_size_t prec; + mp_ptr rp, up; + + prec = r->_mp_prec + 1; /* lie not to lose precision in assignment */ + rp = r->_mp_d; + up = u->_mp_d; + + if (size > prec) + { + up += size - prec; + size = prec; + } + + MPN_COPY (rp, up, size); + r->_mp_exp = u->_mp_exp; + } + r->_mp_size = size; +} diff --git a/contrib/libgmp/mpf/add.c b/contrib/libgmp/mpf/add.c new file mode 100644 index 0000000..2db876f --- /dev/null +++ b/contrib/libgmp/mpf/add.c @@ -0,0 +1,180 @@ +/* mpf_add -- Add two floats. + +Copyright (C) 1993, 1994, 1996 Free Software Foundation, Inc. + +This file is part of the GNU MP Library. + +The GNU MP Library is free software; you can redistribute it and/or modify +it under the terms of the GNU Library General Public License as published by +the Free Software Foundation; either version 2 of the License, or (at your +option) any later version. + +The GNU MP Library is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public +License for more details. + +You should have received a copy of the GNU Library General Public License +along with the GNU MP Library; see the file COPYING.LIB. If not, write to +the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, +MA 02111-1307, USA. */ + +#include "gmp.h" +#include "gmp-impl.h" + +void +#if __STDC__ +mpf_add (mpf_ptr r, mpf_srcptr u, mpf_srcptr v) +#else +mpf_add (r, u, v) + mpf_ptr r; + mpf_srcptr u; + mpf_srcptr v; +#endif +{ + mp_srcptr up, vp; + mp_ptr rp, tp; + mp_size_t usize, vsize, rsize; + mp_size_t prec; + mp_exp_t uexp; + mp_size_t ediff; + mp_limb_t cy; + int negate; + TMP_DECL (marker); + + usize = u->_mp_size; + vsize = v->_mp_size; + + /* Handle special cases that don't work in generic code below. */ + if (usize == 0) + { + mpf_set (r, v); + return; + } + if (vsize == 0) + { + mpf_set (r, u); + return; + } + + /* If signs of U and V are different, perform subtraction. */ + if ((usize ^ vsize) < 0) + { + __mpf_struct v_negated; + v_negated._mp_size = -vsize; + v_negated._mp_exp = v->_mp_exp; + v_negated._mp_d = v->_mp_d; + mpf_sub (r, u, &v_negated); + return; + } + + TMP_MARK (marker); + + /* Signs are now known to be the same. */ + negate = usize < 0; + + /* Make U be the operand with the largest exponent. */ + if (u->_mp_exp < v->_mp_exp) + { + mpf_srcptr t; + t = u; u = v; v = t; + usize = u->_mp_size; + vsize = v->_mp_size; + } + + usize = ABS (usize); + vsize = ABS (vsize); + up = u->_mp_d; + vp = v->_mp_d; + rp = r->_mp_d; + prec = r->_mp_prec; + uexp = u->_mp_exp; + ediff = u->_mp_exp - v->_mp_exp; + + /* If U extends beyond PREC, ignore the part that does. */ + if (usize > prec) + { + up += usize - prec; + usize = prec; + } + + /* If V extends beyond PREC, ignore the part that does. + Note that this may make vsize negative. */ + if (vsize + ediff > prec) + { + vp += vsize + ediff - prec; + vsize = prec - ediff; + } + +#if 0 + /* Locate the least significant non-zero limb in (the needed parts + of) U and V, to simplify the code below. */ + while (up[0] == 0) + up++, usize--; + while (vp[0] == 0) + vp++, vsize--; +#endif + + /* Allocate temp space for the result. Allocate + just vsize + ediff later??? */ + tp = (mp_ptr) TMP_ALLOC (prec * BYTES_PER_MP_LIMB); + + if (ediff >= prec) + { + /* V completely cancelled. */ + if (tp != up) + MPN_COPY (rp, up, usize); + rsize = usize; + } + else + { + /* uuuu | uuuu | uuuu | uuuu | uuuu */ + /* vvvvvvv | vv | vvvvv | v | vv */ + + if (usize > ediff) + { + /* U and V partially overlaps. */ + if (vsize + ediff <= usize) + { + /* uuuu */ + /* v */ + mp_size_t size; + size = usize - ediff - vsize; + MPN_COPY (tp, up, size); + cy = mpn_add (tp + size, up + size, usize - size, vp, vsize); + rsize = usize; + } + else + { + /* uuuu */ + /* vvvvv */ + mp_size_t size; + size = vsize + ediff - usize; + MPN_COPY (tp, vp, size); + cy = mpn_add (tp + size, up, usize, vp + size, usize - ediff); + rsize = vsize + ediff; + } + } + else + { + /* uuuu */ + /* vv */ + mp_size_t size; + size = vsize + ediff - usize; + MPN_COPY (tp, vp, vsize); + MPN_ZERO (tp + vsize, ediff - usize); + MPN_COPY (tp + size, up, usize); + cy = 0; + rsize = size + usize; + } + + MPN_COPY (rp, tp, rsize); + rp[rsize] = cy; + rsize += cy; + uexp += cy; + } + + r->_mp_size = negate ? -rsize : rsize; + r->_mp_exp = uexp; + TMP_FREE (marker); +} diff --git a/contrib/libgmp/mpf/add_ui.c b/contrib/libgmp/mpf/add_ui.c new file mode 100644 index 0000000..f181df4 --- /dev/null +++ b/contrib/libgmp/mpf/add_ui.c @@ -0,0 +1,151 @@ +/* mpf_add_ui -- Add a float and an unsigned integer. + +Copyright (C) 1993, 1994, 1996 Free Software Foundation, Inc. + +This file is part of the GNU MP Library. + +The GNU MP Library is free software; you can redistribute it and/or modify +it under the terms of the GNU Library General Public License as published by +the Free Software Foundation; either version 2 of the License, or (at your +option) any later version. + +The GNU MP Library is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public +License for more details. + +You should have received a copy of the GNU Library General Public License +along with the GNU MP Library; see the file COPYING.LIB. If not, write to +the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, +MA 02111-1307, USA. */ + +#include "gmp.h" +#include "gmp-impl.h" + +void +#if __STDC__ +mpf_add_ui (mpf_ptr sum, mpf_srcptr u, unsigned long int v) +#else +mpf_add_ui (sum, u, v) + mpf_ptr sum; + mpf_srcptr u; + unsigned long int v; +#endif +{ + mp_srcptr up = u->_mp_d; + mp_ptr sump = sum->_mp_d; + mp_size_t usize, sumsize; + mp_size_t prec = sum->_mp_prec; + mp_exp_t uexp = u->_mp_exp; + + usize = u->_mp_size; + if (usize <= 0) + { + if (usize == 0) + { + mpf_set_ui (sum, v); + return; + } + else + { + __mpf_struct u_negated; + u_negated._mp_size = -usize; + u_negated._mp_exp = u->_mp_exp; + u_negated._mp_d = u->_mp_d; + mpf_sub_ui (sum, &u_negated, v); + sum->_mp_size = -(sum->_mp_size); + return; + } + } + + if (v == 0) + { + sum_is_u: + if (u != sum) + { + sumsize = MIN (usize, prec + 1); + MPN_COPY (sum->_mp_d, up + usize - sumsize, sumsize); + sum->_mp_size = sumsize; + sum->_mp_exp = u->_mp_exp; + } + return; + } + + if (uexp > 0) + { + /* U >= 1. */ + if (uexp > prec) + { + /* U >> V, V is not part of final result. */ + goto sum_is_u; + } + else + { + /* U's "limb point" is somewhere between the first limb + and the PREC:th limb. + Both U and V are part of the final result. */ + if (uexp > usize) + { + /* uuuuuu0000. */ + /* + v. */ + /* We begin with moving U to the top of SUM, to handle + samevar(U,SUM). */ + MPN_COPY_DECR (sump + uexp - usize, up, usize); + sump[0] = v; + MPN_ZERO (sump + 1, uexp - usize - 1); +#if 0 /* What is this??? */ + if (sum == u) + MPN_COPY (sum->_mp_d, sump, uexp); +#endif + sum->_mp_size = uexp; + sum->_mp_exp = uexp; + } + else + { + /* uuuuuu.uuuu */ + /* + v. */ + mp_limb_t cy_limb; + if (usize > prec) + { + /* Ignore excess limbs in U. */ + up += usize - prec; + usize -= usize - prec; /* Eq. usize = prec */ + } + if (sump != up) + MPN_COPY (sump, up, usize - uexp); + cy_limb = mpn_add_1 (sump + usize - uexp, up + usize - uexp, + uexp, (mp_limb_t) v); + sump[usize] = cy_limb; + sum->_mp_size = usize + cy_limb; + sum->_mp_exp = uexp + cy_limb; + } + } + } + else + { + /* U < 1, so V > U for sure. */ + /* v. */ + /* .0000uuuu */ + if ((-uexp) >= prec) + { + sump[0] = v; + sum->_mp_size = 1; + sum->_mp_exp = 1; + } + else + { + if (usize + (-uexp) + 1 > prec) + { + /* Ignore excess limbs in U. */ + up += usize + (-uexp) + 1 - prec; + usize -= usize + (-uexp) + 1 - prec; + } + if (sump != up) + MPN_COPY (sump, up, usize); + MPN_ZERO (sump + usize, -uexp); + sump[usize + (-uexp)] = v; + sum->_mp_size = usize + (-uexp) + 1; + sum->_mp_exp = 1; + } + } +} diff --git a/contrib/libgmp/mpf/clear.c b/contrib/libgmp/mpf/clear.c new file mode 100644 index 0000000..beaf4ee --- /dev/null +++ b/contrib/libgmp/mpf/clear.c @@ -0,0 +1,35 @@ +/* mpf_clear -- de-allocate the space occupied by the dynamic digit space of + an integer. + +Copyright (C) 1993, 1994, 1995 Free Software Foundation, Inc. + +This file is part of the GNU MP Library. + +The GNU MP Library is free software; you can redistribute it and/or modify +it under the terms of the GNU Library General Public License as published by +the Free Software Foundation; either version 2 of the License, or (at your +option) any later version. + +The GNU MP Library is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public +License for more details. + +You should have received a copy of the GNU Library General Public License +along with the GNU MP Library; see the file COPYING.LIB. If not, write to +the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, +MA 02111-1307, USA. */ + +#include "gmp.h" +#include "gmp-impl.h" + +void +#if __STDC__ +mpf_clear (mpf_ptr m) +#else +mpf_clear (m) + mpf_ptr m; +#endif +{ + (*_mp_free_func) (m->_mp_d, (m->_mp_prec + 1) * BYTES_PER_MP_LIMB); +} diff --git a/contrib/libgmp/mpf/cmp.c b/contrib/libgmp/mpf/cmp.c new file mode 100644 index 0000000..d440e11 --- /dev/null +++ b/contrib/libgmp/mpf/cmp.c @@ -0,0 +1,114 @@ +/* mpf_cmp -- Compare two floats. + +Copyright (C) 1993, 1994, 1996 Free Software Foundation, Inc. + +This file is part of the GNU MP Library. + +The GNU MP Library is free software; you can redistribute it and/or modify +it under the terms of the GNU Library General Public License as published by +the Free Software Foundation; either version 2 of the License, or (at your +option) any later version. + +The GNU MP Library is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public +License for more details. + +You should have received a copy of the GNU Library General Public License +along with the GNU MP Library; see the file COPYING.LIB. If not, write to +the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, +MA 02111-1307, USA. */ + +#include "gmp.h" +#include "gmp-impl.h" + +int +#if __STDC__ +mpf_cmp (mpf_srcptr u, mpf_srcptr v) +#else +mpf_cmp (u, v) + mpf_srcptr u; + mpf_srcptr v; +#endif +{ + mp_srcptr up, vp; + mp_size_t usize, vsize; + mp_exp_t uexp, vexp; + int cmp; + int usign; + + uexp = u->_mp_exp; + vexp = v->_mp_exp; + + usize = u->_mp_size; + vsize = v->_mp_size; + + /* 1. Are the signs different? */ + if ((usize ^ vsize) >= 0) + { + /* U and V are both non-negative or both negative. */ + if (usize == 0) + /* vsize >= 0 */ + return -(vsize != 0); + if (vsize == 0) + /* usize >= 0 */ + return usize != 0; + /* Fall out. */ + } + else + { + /* Either U or V is negative, but not both. */ + return usize >= 0 ? 1 : -1; + } + + /* U and V have the same sign and are both non-zero. */ + + usign = usize >= 0 ? 1 : -1; + + /* 2. Are the exponents different? */ + if (uexp > vexp) + return usign; + if (uexp < vexp) + return -usign; + + usize = ABS (usize); + vsize = ABS (vsize); + + up = u->_mp_d; + vp = v->_mp_d; + +#define STRICT_MPF_NORMALIZATION 0 +#if ! STRICT_MPF_NORMALIZATION + /* Ignore zeroes at the low end of U and V. */ + while (up[0] == 0) + { + up++; + usize--; + } + while (vp[0] == 0) + { + vp++; + vsize--; + } +#endif + + if (usize > vsize) + { + cmp = mpn_cmp (up + usize - vsize, vp, vsize); + if (cmp == 0) + return usign; + } + else if (vsize > usize) + { + cmp = mpn_cmp (up, vp + vsize - usize, usize); + if (cmp == 0) + return -usign; + } + else + { + cmp = mpn_cmp (up, vp, usize); + if (cmp == 0) + return 0; + } + return cmp > 0 ? usign : -usign; +} diff --git a/contrib/libgmp/mpf/cmp_si.c b/contrib/libgmp/mpf/cmp_si.c new file mode 100644 index 0000000..01f9708 --- /dev/null +++ b/contrib/libgmp/mpf/cmp_si.c @@ -0,0 +1,98 @@ +/* mpf_cmp_si -- Compare a float with a signed integer. + +Copyright (C) 1993, 1994, 1995 Free Software Foundation, Inc. + +This file is part of the GNU MP Library. + +The GNU MP Library is free software; you can redistribute it and/or modify +it under the terms of the GNU Library General Public License as published by +the Free Software Foundation; either version 2 of the License, or (at your +option) any later version. + +The GNU MP Library is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public +License for more details. + +You should have received a copy of the GNU Library General Public License +along with the GNU MP Library; see the file COPYING.LIB. If not, write to +the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, +MA 02111-1307, USA. */ + +#include "gmp.h" +#include "gmp-impl.h" + +int +#if __STDC__ +mpf_cmp_si (mpf_srcptr u, long int vslimb) +#else +mpf_cmp_si (u, vslimb) + mpf_srcptr u; + long int vslimb; +#endif +{ + mp_srcptr up; + mp_size_t usize; + mp_exp_t uexp; + int usign; + + uexp = u->_mp_exp; + usize = u->_mp_size; + + /* 1. Are the signs different? */ + if ((usize < 0) == (vslimb < 0)) /* don't use xor, type size may differ */ + { + /* U and V are both non-negative or both negative. */ + if (usize == 0) + /* vslimb >= 0 */ + return -(vslimb != 0); + if (vslimb == 0) + /* usize >= 0 */ + return usize != 0; + /* Fall out. */ + } + else + { + /* Either U or V is negative, but not both. */ + return usize >= 0 ? 1 : -1; + } + + /* U and V have the same sign and are both non-zero. */ + + usign = usize >= 0 ? 1 : -1; + + /* 2. Are the exponents different (V's exponent == 1)? */ + if (uexp > 1) + return usign; + if (uexp < 1) + return -usign; + + usize = ABS (usize); + vslimb = ABS (vslimb); + + up = u->_mp_d; + +#define STRICT_MPF_NORMALIZATION 0 +#if ! STRICT_MPF_NORMALIZATION + /* Ignore zeroes at the low end of U and V. */ + while (*up == 0) + { + up++; + usize--; + } +#endif + + /* 3. Now, if the number of limbs are different, we have a difference + since we have made sure the trailing limbs are not zero. */ + if (usize > 1) + return usign; + + /* 4. Compare the mantissas. */ + if (*up > vslimb) + return usign; + else if (*up < vslimb) + return -usign; + + /* Wow, we got zero even if we tried hard to avoid it. */ + return 0; +} diff --git a/contrib/libgmp/mpf/cmp_ui.c b/contrib/libgmp/mpf/cmp_ui.c new file mode 100644 index 0000000..3a4911b --- /dev/null +++ b/contrib/libgmp/mpf/cmp_ui.c @@ -0,0 +1,80 @@ +/* mpf_cmp_ui -- Compare a float with an unsigned integer. + +Copyright (C) 1993, 1994, 1995 Free Software Foundation, Inc. + +This file is part of the GNU MP Library. + +The GNU MP Library is free software; you can redistribute it and/or modify +it under the terms of the GNU Library General Public License as published by +the Free Software Foundation; either version 2 of the License, or (at your +option) any later version. + +The GNU MP Library is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public +License for more details. + +You should have received a copy of the GNU Library General Public License +along with the GNU MP Library; see the file COPYING.LIB. If not, write to +the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, +MA 02111-1307, USA. */ + +#include "gmp.h" +#include "gmp-impl.h" + +int +#if __STDC__ +mpf_cmp_ui (mpf_srcptr u, unsigned long int vlimb) +#else +mpf_cmp_ui (u, vlimb) + mpf_srcptr u; + unsigned long int vlimb; +#endif +{ + mp_srcptr up; + mp_size_t usize; + mp_exp_t uexp; + + uexp = u->_mp_exp; + usize = u->_mp_size; + + /* 1. Is U negative? */ + if (usize < 0) + return -1; + /* We rely on usize being non-negative in the code that follows. */ + + if (vlimb == 0) + return usize != 0; + + /* 2. Are the exponents different (V's exponent == 1)? */ + if (uexp > 1) + return 1; + if (uexp < 1) + return -1; + + up = u->_mp_d; + +#define STRICT_MPF_NORMALIZATION 0 +#if ! STRICT_MPF_NORMALIZATION + /* Ignore zeroes at the low end of U. */ + while (*up == 0) + { + up++; + usize--; + } +#endif + + /* 3. Now, if the number of limbs are different, we have a difference + since we have made sure the trailing limbs are not zero. */ + if (usize > 1) + return 1; + + /* 4. Compare the mantissas. */ + if (*up > vlimb) + return 1; + else if (*up < vlimb) + return -1; + + /* Wow, we got zero even if we tried hard to avoid it. */ + return 0; +} diff --git a/contrib/libgmp/mpf/configure.in b/contrib/libgmp/mpf/configure.in new file mode 100644 index 0000000..b6ecf8b --- /dev/null +++ b/contrib/libgmp/mpf/configure.in @@ -0,0 +1,12 @@ +# This file is a shell script fragment that supplies the information +# necessary for a configure script to process the program in +# this directory. For more information, look at ../configure. + +configdirs=tests +srctrigger=add_ui.c +srcname="GNU Multi-Precision library/mpf" + +# per-host: + +# per-target: + diff --git a/contrib/libgmp/mpf/div.c b/contrib/libgmp/mpf/div.c new file mode 100644 index 0000000..9ba6922 --- /dev/null +++ b/contrib/libgmp/mpf/div.c @@ -0,0 +1,144 @@ +/* mpf_div -- Divide two floats. + +Copyright (C) 1993, 1994, 1996 Free Software Foundation, Inc. + +This file is part of the GNU MP Library. + +The GNU MP Library is free software; you can redistribute it and/or modify +it under the terms of the GNU Library General Public License as published by +the Free Software Foundation; either version 2 of the License, or (at your +option) any later version. + +The GNU MP Library is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public +License for more details. + +You should have received a copy of the GNU Library General Public License +along with the GNU MP Library; see the file COPYING.LIB. If not, write to +the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, +MA 02111-1307, USA. */ + +#include "gmp.h" +#include "gmp-impl.h" +#include "longlong.h" + +void +#if __STDC__ +mpf_div (mpf_ptr r, mpf_srcptr u, mpf_srcptr v) +#else +mpf_div (r, u, v) + mpf_ptr r; + mpf_srcptr u; + mpf_srcptr v; +#endif +{ + mp_srcptr up, vp; + mp_ptr rp, tp, rtp; + mp_size_t usize, vsize; + mp_size_t rsize, tsize; + mp_size_t sign_quotient; + mp_size_t prec; + unsigned normalization_steps; + mp_limb_t q_limb; + mp_exp_t rexp; + TMP_DECL (marker); + + usize = u->_mp_size; + vsize = v->_mp_size; + sign_quotient = usize ^ vsize; + usize = ABS (usize); + vsize = ABS (vsize); + prec = r->_mp_prec; + + if (vsize == 0) + vsize = 1 / vsize; /* divide by zero as directed */ + if (usize == 0) + { + r->_mp_size = 0; + r->_mp_exp = 0; + return; + } + + TMP_MARK (marker); + rexp = u->_mp_exp - v->_mp_exp; + + rp = r->_mp_d; + up = u->_mp_d; + vp = v->_mp_d; + + if (vsize > prec) + { + vp += vsize - prec; + vsize = prec; + } + + tsize = vsize + prec; + tp = (mp_ptr) TMP_ALLOC ((tsize + 1) * BYTES_PER_MP_LIMB); + + if (usize > tsize) + { + up += usize - tsize; + usize = tsize; + rtp = tp; + } + else + { + MPN_ZERO (tp, tsize - usize); + rtp = tp + (tsize - usize); + } + + count_leading_zeros (normalization_steps, vp[vsize - 1]); + + /* Normalize the divisor and the dividend. */ + if (normalization_steps != 0) + { + mp_ptr tmp; + mp_limb_t nlimb; + + /* Shift up the divisor setting the most significant bit of + the most significant limb. Use temporary storage not to clobber + the original contents of the divisor. */ + tmp = (mp_ptr) TMP_ALLOC (vsize * BYTES_PER_MP_LIMB); + mpn_lshift (tmp, vp, vsize, normalization_steps); + vp = tmp; + + /* Shift up the dividend, possibly introducing a new most + significant word. Move the shifted dividend in the remainder + at the same time. */ + nlimb = mpn_lshift (rtp, up, usize, normalization_steps); + if (nlimb != 0) + { + rtp[usize] = nlimb; + tsize++; + rexp++; + } + } + else + { + /* The divisor is already normalized, as required. + Copy it to temporary space if it overlaps with the quotient. */ + if (vp - rp <= tsize - vsize) + { + mp_ptr tmp = (mp_ptr) TMP_ALLOC (vsize * BYTES_PER_MP_LIMB); + MPN_COPY (tmp, vp, vsize); + vp = (mp_srcptr) tmp; + } + + /* Move the dividend to the remainder. */ + MPN_COPY (rtp, up, usize); + } + + q_limb = mpn_divmod (rp, tp, tsize, vp, vsize); + rsize = tsize - vsize; + if (q_limb) + { + rp[rsize] = q_limb; + rsize++; + rexp++; + } + + r->_mp_size = sign_quotient >= 0 ? rsize : -rsize; + r->_mp_exp = rexp; + TMP_FREE (marker); +} diff --git a/contrib/libgmp/mpf/div_2exp.c b/contrib/libgmp/mpf/div_2exp.c new file mode 100644 index 0000000..d729625 --- /dev/null +++ b/contrib/libgmp/mpf/div_2exp.c @@ -0,0 +1,79 @@ +/* mpf_div_2exp -- Divide a float by 2^n. + +Copyright (C) 1993, 1994, 1996 Free Software Foundation, Inc. + +This file is part of the GNU MP Library. + +The GNU MP Library is free software; you can redistribute it and/or modify +it under the terms of the GNU Library General Public License as published by +the Free Software Foundation; either version 2 of the License, or (at your +option) any later version. + +The GNU MP Library is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public +License for more details. + +You should have received a copy of the GNU Library General Public License +along with the GNU MP Library; see the file COPYING.LIB. If not, write to +the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, +MA 02111-1307, USA. */ + +#include "gmp.h" +#include "gmp-impl.h" + +void +#if __STDC__ +mpf_div_2exp (mpf_ptr r, mpf_srcptr u, unsigned long int exp) +#else +mpf_div_2exp (r, u, exp) + mpf_ptr r; + mpf_srcptr u; + unsigned long int exp; +#endif +{ + mp_srcptr up; + mp_ptr rp = r->_mp_d; + mp_size_t usize; + mp_size_t abs_usize; + mp_size_t prec = r->_mp_prec; + mp_exp_t uexp = u->_mp_exp; + + usize = u->_mp_size; + + if (usize == 0) + { + r->_mp_size = 0; + r->_mp_exp = 0; + return; + } + + abs_usize = ABS (usize); + up = u->_mp_d; + + if (abs_usize > prec) + { + up += abs_usize - prec; + abs_usize = prec; + } + + if (exp % BITS_PER_MP_LIMB == 0) + { + if (rp != up) + MPN_COPY (rp, up, abs_usize); + r->_mp_exp = uexp - exp / BITS_PER_MP_LIMB; + } + else + { + /* Use mpn_lshift since mpn_rshift operates upwards, and we therefore + would clobber part of U before using that part, when R == U. */ + mp_limb_t cy_limb; + cy_limb = mpn_lshift (rp, up, abs_usize, -exp % BITS_PER_MP_LIMB); + rp[abs_usize] = cy_limb; + cy_limb = cy_limb != 0; + + abs_usize += cy_limb; + r->_mp_exp = uexp - exp / BITS_PER_MP_LIMB - 1 + cy_limb; + } + r->_mp_size = usize >= 0 ? abs_usize : -abs_usize; +} diff --git a/contrib/libgmp/mpf/div_ui.c b/contrib/libgmp/mpf/div_ui.c new file mode 100644 index 0000000..050a6f0 --- /dev/null +++ b/contrib/libgmp/mpf/div_ui.c @@ -0,0 +1,91 @@ +/* mpf_div_ui -- Divide a float with an unsigned integer. + +Copyright (C) 1993, 1994, 1996 Free Software Foundation, Inc. + +This file is part of the GNU MP Library. + +The GNU MP Library is free software; you can redistribute it and/or modify +it under the terms of the GNU Library General Public License as published by +the Free Software Foundation; either version 2 of the License, or (at your +option) any later version. + +The GNU MP Library is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public +License for more details. + +You should have received a copy of the GNU Library General Public License +along with the GNU MP Library; see the file COPYING.LIB. If not, write to +the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, +MA 02111-1307, USA. */ + +#include "gmp.h" +#include "gmp-impl.h" +#include "longlong.h" + +void +#if __STDC__ +mpf_div_ui (mpf_ptr r, mpf_srcptr u, unsigned long int v) +#else +mpf_div_ui (r, u, v) + mpf_ptr r; + mpf_srcptr u; + unsigned long int v; +#endif +{ + mp_srcptr up; + mp_ptr rp, tp, rtp; + mp_size_t usize; + mp_size_t rsize, tsize; + mp_size_t sign_quotient; + mp_size_t prec; + mp_limb_t q_limb; + mp_exp_t rexp; + TMP_DECL (marker); + + usize = u->_mp_size; + sign_quotient = usize; + usize = ABS (usize); + prec = r->_mp_prec; + + if (v == 0) + v = 1 / v; /* divide by zero as directed */ + if (usize == 0) + { + r->_mp_size = 0; + r->_mp_exp = 0; + return; + } + + TMP_MARK (marker); + + rp = r->_mp_d; + up = u->_mp_d; + + tsize = 1 + prec; + tp = (mp_ptr) TMP_ALLOC ((tsize + 1) * BYTES_PER_MP_LIMB); + + if (usize > tsize) + { + up += usize - tsize; + usize = tsize; + rtp = tp; + } + else + { + MPN_ZERO (tp, tsize - usize); + rtp = tp + (tsize - usize); + } + + /* Move the dividend to the remainder. */ + MPN_COPY (rtp, up, usize); + + mpn_divmod_1 (rp, tp, tsize, (mp_limb_t) v); + q_limb = rp[tsize - 1]; + + rsize = tsize - (q_limb == 0); + rexp = u->_mp_exp - (q_limb == 0); + r->_mp_size = sign_quotient >= 0 ? rsize : -rsize; + r->_mp_exp = rexp; + TMP_FREE (marker); +} diff --git a/contrib/libgmp/mpf/dump.c b/contrib/libgmp/mpf/dump.c new file mode 100644 index 0000000..46d5c05 --- /dev/null +++ b/contrib/libgmp/mpf/dump.c @@ -0,0 +1,43 @@ +/* mpf_dump -- Dump a float to stdout. + +Copyright (C) 1993, 1994, 1995 Free Software Foundation, Inc. + +This file is part of the GNU MP Library. + +The GNU MP Library is free software; you can redistribute it and/or modify +it under the terms of the GNU Library General Public License as published by +the Free Software Foundation; either version 2 of the License, or (at your +option) any later version. + +The GNU MP Library is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public +License for more details. + +You should have received a copy of the GNU Library General Public License +along with the GNU MP Library; see the file COPYING.LIB. If not, write to +the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, +MA 02111-1307, USA. */ + +#include <stdio.h> +#include "gmp.h" +#include "gmp-impl.h" + +void +#if __STDC__ +mpf_dump (mpf_srcptr u) +#else +mpf_dump (u) + mpf_srcptr u; +#endif +{ + mp_exp_t exp; + char *str; + + str = mpf_get_str (0, &exp, 10, 0, u); + if (str[0] == '-') + printf ("-0.%se%ld\n", str + 1, exp); + else + printf ("0.%se%ld\n", str, exp); + (*_mp_free_func) (str, 0);/* ??? broken alloc interface, pass what size ??? */ +} diff --git a/contrib/libgmp/mpf/eq.c b/contrib/libgmp/mpf/eq.c new file mode 100644 index 0000000..e6630ad --- /dev/null +++ b/contrib/libgmp/mpf/eq.c @@ -0,0 +1,121 @@ +/* mpf_eq -- Compare two floats up to a specified bit #. + +Copyright (C) 1993, 1995, 1996 Free Software Foundation, Inc. + +This file is part of the GNU MP Library. + +The GNU MP Library is free software; you can redistribute it and/or modify +it under the terms of the GNU Library General Public License as published by +the Free Software Foundation; either version 2 of the License, or (at your +option) any later version. + +The GNU MP Library is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public +License for more details. + +You should have received a copy of the GNU Library General Public License +along with the GNU MP Library; see the file COPYING.LIB. If not, write to +the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, +MA 02111-1307, USA. */ + +#include "gmp.h" +#include "gmp-impl.h" + +int +#if __STDC__ +mpf_eq (mpf_srcptr u, mpf_srcptr v, unsigned long int n_bits) +#else +mpf_eq (u, v, n_bits) + mpf_srcptr u; + mpf_srcptr v; + unsigned long int n_bits; +#endif +{ + mp_srcptr up, vp; + mp_size_t usize, vsize, size, i; + mp_exp_t uexp, vexp; + int usign; + + uexp = u->_mp_exp; + vexp = v->_mp_exp; + + usize = u->_mp_size; + vsize = v->_mp_size; + + /* 1. Are the signs different? */ + if ((usize ^ vsize) >= 0) + { + /* U and V are both non-negative or both negative. */ + if (usize == 0) + return vsize == 0; + if (vsize == 0) + return 0; + + /* Fall out. */ + } + else + { + /* Either U or V is negative, but not both. */ + return 0; + } + + /* U and V have the same sign and are both non-zero. */ + + usign = usize >= 0 ? 1 : -1; + + /* 2. Are the exponents different? */ + if (uexp > vexp) + return 0; /* ??? handle (uexp = vexp + 1) */ + if (vexp > uexp) + return 0; /* ??? handle (vexp = uexp + 1) */ + + usize = ABS (usize); + vsize = ABS (vsize); + + up = u->_mp_d; + vp = v->_mp_d; + + /* Ignore zeroes at the low end of U and V. */ + while (up[0] == 0) + { + up++; + usize--; + } + while (vp[0] == 0) + { + vp++; + vsize--; + } + + if (usize > vsize) + { + if (vsize * BITS_PER_MP_LIMB < n_bits) + return 0; /* surely too different */ + size = vsize; + } + else if (vsize > usize) + { + if (usize * BITS_PER_MP_LIMB < n_bits) + return 0; /* surely too different */ + size = usize; + } + else + { + size = usize; + } + + if (size > (n_bits + BITS_PER_MP_LIMB - 1) / BITS_PER_MP_LIMB) + size = (n_bits + BITS_PER_MP_LIMB - 1) / BITS_PER_MP_LIMB; + + up += usize - size; + vp += vsize - size; + + for (i = size - 1; i >= 0; i--) + { + if (up[i] != vp[i]) + return 0; + } + + return 1; +} diff --git a/contrib/libgmp/mpf/get_d.c b/contrib/libgmp/mpf/get_d.c new file mode 100644 index 0000000..a10b366 --- /dev/null +++ b/contrib/libgmp/mpf/get_d.c @@ -0,0 +1,54 @@ +/* double mpf_get_d (mpf_t src) -- Return the double approximation to SRC. + +Copyright (C) 1996 Free Software Foundation, Inc. + +This file is part of the GNU MP Library. + +The GNU MP Library is free software; you can redistribute it and/or modify +it under the terms of the GNU Library General Public License as published by +the Free Software Foundation; either version 2 of the License, or (at your +option) any later version. + +The GNU MP Library is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public +License for more details. + +You should have received a copy of the GNU Library General Public License +along with the GNU MP Library; see the file COPYING.LIB. If not, write to +the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, +MA 02111-1307, USA. */ + +#include "gmp.h" +#include "gmp-impl.h" + +double +#if __STDC__ +mpf_get_d (mpf_srcptr src) +#else +mpf_get_d (src) + mpf_srcptr src; +#endif +{ + double res; + mp_size_t size, i, n_limbs_to_use; + int negative; + mp_ptr qp; + + size = SIZ(src); + if (size == 0) + return 0.0; + + negative = size < 0; + size = ABS (size); + qp = PTR(src); + + res = qp[size - 1]; + n_limbs_to_use = MIN (LIMBS_PER_DOUBLE, size); + for (i = 2; i <= n_limbs_to_use; i++) + res = res * MP_BASE_AS_DOUBLE + qp[size - i]; + + res = __gmp_scale2 (res, (EXP(src) - n_limbs_to_use) * BITS_PER_MP_LIMB); + + return negative ? -res : res; +} diff --git a/contrib/libgmp/mpf/get_prc.c b/contrib/libgmp/mpf/get_prc.c new file mode 100644 index 0000000..7f7e41f --- /dev/null +++ b/contrib/libgmp/mpf/get_prc.c @@ -0,0 +1,34 @@ +/* mpf_get_prec(x) -- Return the precision in bits of x. + +Copyright (C) 1996 Free Software Foundation, Inc. + +This file is part of the GNU MP Library. + +The GNU MP Library is free software; you can redistribute it and/or modify +it under the terms of the GNU Library General Public License as published by +the Free Software Foundation; either version 2 of the License, or (at your +option) any later version. + +The GNU MP Library is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public +License for more details. + +You should have received a copy of the GNU Library General Public License +along with the GNU MP Library; see the file COPYING.LIB. If not, write to +the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, +MA 02111-1307, USA. */ + +#include "gmp.h" +#include "gmp-impl.h" + +unsigned long int +#if __STDC__ +mpf_get_prec (mpf_srcptr x) +#else +mpf_get_prec (x) + mpf_srcptr x; +#endif +{ + return (unsigned long int) x->_mp_prec * BITS_PER_MP_LIMB - BITS_PER_MP_LIMB; +} diff --git a/contrib/libgmp/mpf/get_str.c b/contrib/libgmp/mpf/get_str.c new file mode 100644 index 0000000..bfee18d --- /dev/null +++ b/contrib/libgmp/mpf/get_str.c @@ -0,0 +1,500 @@ +/* mpf_get_str (digit_ptr, exp, base, n_digits, a) -- Convert the floating + point number A to a base BASE number and store N_DIGITS raw digits at + DIGIT_PTR, and the base BASE exponent in the word pointed to by EXP. For + example, the number 3.1416 would be returned as "31416" in DIGIT_PTR and + 1 in EXP. + +Copyright (C) 1993, 1994, 1995, 1996 Free Software Foundation, Inc. + +This file is part of the GNU MP Library. + +The GNU MP Library is free software; you can redistribute it and/or modify +it under the terms of the GNU Library General Public License as published by +the Free Software Foundation; either version 2 of the License, or (at your +option) any later version. + +The GNU MP Library is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public +License for more details. + +You should have received a copy of the GNU Library General Public License +along with the GNU MP Library; see the file COPYING.LIB. If not, write to +the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, +MA 02111-1307, USA. */ + +#include "gmp.h" +#include "gmp-impl.h" +#include "longlong.h" + +/* + New algorithm for converting fractions (951019): + 0. Call the fraction to convert F. + 1. Compute [exp * log(2^BITS_PER_MP_LIMB)/log(B)], i.e., + [exp * BITS_PER_MP_LIMB * __mp_bases[B].chars_per_bit_exactly]. Exp is + the number of limbs between the limb point and the most significant + non-zero limb. Call this result n. + 2. Compute B^n. + 3. F*B^n will now be just below 1, which can be converted easily. (Just + multiply by B repeatedly, and see the digits fall out as integers.) + We should interrupt the conversion process of F*B^n as soon as the number + of digits requested have been generated. + + New algorithm for converting integers (951019): + 0. Call the integer to convert I. + 1. Compute [exp * log(2^BITS_PER_MP_LIMB)/log(B)], i.e., + [exp BITS_PER_MP_LIMB * __mp_bases[B].chars_per_bit_exactly]. Exp is + the number of limbs between the limb point and the least significant + non-zero limb. Call this result n. + 2. Compute B^n. + 3. I/B^n can be converted easily. (Just divide by B repeatedly. In GMP, + this is best done by calling mpn_get_str.) + Note that converting I/B^n could yield more digits than requested. For + efficiency, the variable n above should be set larger in such cases, to + kill all undesired digits in the division in step 3. +*/ + +char * +#if __STDC__ +mpf_get_str (char *digit_ptr, mp_exp_t *exp, int base, size_t n_digits, mpf_srcptr u) +#else +mpf_get_str (digit_ptr, exp, base, n_digits, u) + char *digit_ptr; + mp_exp_t *exp; + int base; + size_t n_digits; + mpf_srcptr u; +#endif +{ + mp_size_t usize; + mp_exp_t uexp; + unsigned char *str; + size_t str_size; + char *num_to_text; + long i; /* should be size_t */ + mp_ptr rp; + mp_limb_t big_base; + size_t digits_computed_so_far; + int dig_per_u; + mp_srcptr up; + unsigned char *tstr; + mp_exp_t exp_in_base; + TMP_DECL (marker); + + TMP_MARK (marker); + usize = u->_mp_size; + uexp = u->_mp_exp; + + if (base >= 0) + { + if (base == 0) + base = 10; + num_to_text = "0123456789abcdefghijklmnopqrstuvwxyz"; + } + else + { + base = -base; + num_to_text = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"; + } + + /* Don't compute more digits than U can accurately represent. + Also, if 0 digits were requested, give *exactly* as many digits + as can be accurately represented. */ + { + size_t max_digits = (((u->_mp_prec - 1) * BITS_PER_MP_LIMB) + * __mp_bases[base].chars_per_bit_exactly); + if (n_digits == 0 || n_digits > max_digits) + n_digits = max_digits; + } + + if (digit_ptr == 0) + { + /* We didn't get a string from the user. Allocate one (and return + a pointer to it) with space for `-' and terminating null. */ + digit_ptr = (char *) (*_mp_allocate_func) (n_digits + 2); + } + + if (usize == 0) + { + *exp = 0; + *digit_ptr = 0; + return digit_ptr; + } + + str = (unsigned char *) digit_ptr; + + /* Allocate temporary digit space. We can't put digits directly in the user + area, since we almost always generate more digits than requested. */ + tstr = (unsigned char *) TMP_ALLOC (n_digits + 3 * BITS_PER_MP_LIMB); + + if (usize < 0) + { + *digit_ptr = '-'; + str++; + usize = -usize; + } + + digits_computed_so_far = 0; + + if (uexp > usize) + { + /* The number has just an integral part. */ + mp_size_t rsize; + mp_size_t exp_in_limbs; + mp_size_t msize; + mp_ptr tp, xp, mp; + int cnt; + mp_limb_t cy; + mp_size_t start_str; + mp_size_t n_limbs; + + n_limbs = 2 + ((mp_size_t) (n_digits / __mp_bases[base].chars_per_bit_exactly) + / BITS_PER_MP_LIMB); + + /* Compute n such that [u/B^n] contains (somewhat) more than n_digits + digits. (We compute less than that only if that is an exact number, + i.e., exp is small enough.) */ + + exp_in_limbs = uexp; + + if (n_limbs >= exp_in_limbs) + { + /* The number is so small that we convert the entire number. */ + exp_in_base = 0; + rp = (mp_ptr) TMP_ALLOC (exp_in_limbs * BYTES_PER_MP_LIMB); + MPN_ZERO (rp, exp_in_limbs - usize); + MPN_COPY (rp + (exp_in_limbs - usize), u->_mp_d, usize); + rsize = exp_in_limbs; + } + else + { + exp_in_limbs -= n_limbs; + exp_in_base = (((exp_in_limbs * BITS_PER_MP_LIMB - 1)) + * __mp_bases[base].chars_per_bit_exactly); + + rsize = exp_in_limbs + 1; + rp = (mp_ptr) TMP_ALLOC (rsize * BYTES_PER_MP_LIMB); + tp = (mp_ptr) TMP_ALLOC (rsize * BYTES_PER_MP_LIMB); + + rp[0] = base; + rsize = 1; + + count_leading_zeros (cnt, exp_in_base); + for (i = BITS_PER_MP_LIMB - cnt - 2; i >= 0; i--) + { + mpn_mul_n (tp, rp, rp, rsize); + rsize = 2 * rsize; + rsize -= tp[rsize - 1] == 0; + xp = tp; tp = rp; rp = xp; + + if (((exp_in_base >> i) & 1) != 0) + { + cy = mpn_mul_1 (rp, rp, rsize, (mp_limb_t) base); + rp[rsize] = cy; + rsize += cy != 0; + } + } + + mp = u->_mp_d; + msize = usize; + + { + mp_ptr qp; + mp_limb_t qflag; + mp_size_t xtra; + if (msize < rsize) + { + mp_ptr tmp = (mp_ptr) TMP_ALLOC ((rsize+1)* BYTES_PER_MP_LIMB); + MPN_ZERO (tmp, rsize - msize); + MPN_COPY (tmp + rsize - msize, mp, msize); + mp = tmp; + msize = rsize; + } + else + { + mp_ptr tmp = (mp_ptr) TMP_ALLOC ((msize+1)* BYTES_PER_MP_LIMB); + MPN_COPY (tmp, mp, msize); + mp = tmp; + } + count_leading_zeros (cnt, rp[rsize - 1]); + cy = 0; + if (cnt != 0) + { + mpn_lshift (rp, rp, rsize, cnt); + cy = mpn_lshift (mp, mp, msize, cnt); + if (cy) + mp[msize++] = cy; + } + + { + mp_size_t qsize = n_limbs + (cy != 0); + qp = (mp_ptr) TMP_ALLOC ((qsize + 1) * BYTES_PER_MP_LIMB); + xtra = qsize - (msize - rsize); + qflag = mpn_divrem (qp, xtra, mp, msize, rp, rsize); + qp[qsize] = qflag; + rsize = qsize + qflag; + rp = qp; + } + } + } + + str_size = mpn_get_str (tstr, base, rp, rsize); + + if (str_size > n_digits + 3 * BITS_PER_MP_LIMB) + abort (); + + start_str = 0; + while (tstr[start_str] == 0) + start_str++; + + for (i = start_str; i < str_size; i++) + { + tstr[digits_computed_so_far++] = tstr[i]; + if (digits_computed_so_far > n_digits) + break; + } + exp_in_base = exp_in_base + str_size - start_str; + goto finish_up; + } + + exp_in_base = 0; + + if (uexp > 0) + { + /* The number has an integral part, convert that first. + If there is a fractional part too, it will be handled later. */ + mp_size_t start_str; + + rp = (mp_ptr) TMP_ALLOC (uexp * BYTES_PER_MP_LIMB); + up = u->_mp_d + usize - uexp; + MPN_COPY (rp, up, uexp); + + str_size = mpn_get_str (tstr, base, rp, uexp); + + start_str = 0; + while (tstr[start_str] == 0) + start_str++; + + for (i = start_str; i < str_size; i++) + { + tstr[digits_computed_so_far++] = tstr[i]; + if (digits_computed_so_far > n_digits) + { + exp_in_base = str_size - start_str; + goto finish_up; + } + } + + exp_in_base = str_size - start_str; + /* Modify somewhat and fall out to convert fraction... */ + usize -= uexp; + uexp = 0; + } + + if (usize <= 0) + goto finish_up; + + /* Convert the fraction. */ + { + mp_size_t rsize, msize; + mp_ptr rp, tp, xp, mp; + int cnt; + mp_limb_t cy; + mp_exp_t nexp; + + big_base = __mp_bases[base].big_base; + dig_per_u = __mp_bases[base].chars_per_limb; + + /* Hack for correctly (although not efficiently) converting to bases that + are powers of 2. If we deem it important, we could handle powers of 2 + by shifting and masking (just like mpn_get_str). */ + if (big_base < 10) /* logarithm of base when power of two */ + { + int logbase = big_base; + if (dig_per_u * logbase == BITS_PER_MP_LIMB) + dig_per_u--; + big_base = (mp_limb_t) 1 << (dig_per_u * logbase); + /* fall out to general code... */ + } + +#if 0 + if (0 && uexp == 0) + { + rp = (mp_ptr) TMP_ALLOC (usize * BYTES_PER_MP_LIMB); + up = u->_mp_d; + MPN_COPY (rp, up, usize); + rsize = usize; + nexp = 0; + } + else + {} +#endif + uexp = -uexp; + if (u->_mp_d[usize - 1] == 0) + cnt = 0; + else + count_leading_zeros (cnt, u->_mp_d[usize - 1]); + + nexp = ((uexp * BITS_PER_MP_LIMB) + cnt) + * __mp_bases[base].chars_per_bit_exactly; + + if (nexp == 0) + { + rp = (mp_ptr) TMP_ALLOC (usize * BYTES_PER_MP_LIMB); + up = u->_mp_d; + MPN_COPY (rp, up, usize); + rsize = usize; + } + else + { + rsize = uexp + 2; + rp = (mp_ptr) TMP_ALLOC (rsize * BYTES_PER_MP_LIMB); + tp = (mp_ptr) TMP_ALLOC (rsize * BYTES_PER_MP_LIMB); + + rp[0] = base; + rsize = 1; + + count_leading_zeros (cnt, nexp); + for (i = BITS_PER_MP_LIMB - cnt - 2; i >= 0; i--) + { + mpn_mul_n (tp, rp, rp, rsize); + rsize = 2 * rsize; + rsize -= tp[rsize - 1] == 0; + xp = tp; tp = rp; rp = xp; + + if (((nexp >> i) & 1) != 0) + { + cy = mpn_mul_1 (rp, rp, rsize, (mp_limb_t) base); + rp[rsize] = cy; + rsize += cy != 0; + } + } + + /* Did our multiplier (base^nexp) cancel with uexp? */ +#if 0 + if (uexp != rsize) + { + do + { + cy = mpn_mul_1 (rp, rp, rsize, big_base); + nexp += dig_per_u; + } + while (cy == 0); + rp[rsize++] = cy; + } +#endif + mp = u->_mp_d; + msize = usize; + + tp = (mp_ptr) TMP_ALLOC ((rsize + msize) * BYTES_PER_MP_LIMB); + if (rsize > msize) + cy = mpn_mul (tp, rp, rsize, mp, msize); + else + cy = mpn_mul (tp, mp, msize, rp, rsize); + rsize += msize; + rsize -= cy == 0; + rp = tp; + + /* If we already output digits (for an integral part) pad + leading zeros. */ + if (digits_computed_so_far != 0) + for (i = 0; i < nexp; i++) + tstr[digits_computed_so_far++] = 0; + } + + while (digits_computed_so_far <= n_digits) + { + /* For speed: skip trailing zeroes. */ + if (rp[0] == 0) + { + rp++; + rsize--; + if (rsize == 0) + { + n_digits = digits_computed_so_far; + break; + } + } + + cy = mpn_mul_1 (rp, rp, rsize, big_base); + if (digits_computed_so_far == 0 && cy == 0) + { + abort (); + nexp += dig_per_u; + continue; + } + /* Convert N1 from BIG_BASE to a string of digits in BASE + using single precision operations. */ + { + unsigned char *s = tstr + digits_computed_so_far + dig_per_u; + for (i = dig_per_u - 1; i >= 0; i--) + { + *--s = cy % base; + cy /= base; + } + } + digits_computed_so_far += dig_per_u; + } + if (exp_in_base == 0) + exp_in_base = -nexp; + } + + finish_up: + + /* We can have at most one leading 0. Remove it. */ + if (tstr[0] == 0) + { + tstr++; + digits_computed_so_far--; + exp_in_base--; + } + + /* We should normally have computed too many digits. Round the result + at the point indicated by n_digits. */ + if (digits_computed_so_far > n_digits) + { + /* Round the result. */ + if (tstr[n_digits] * 2 >= base) + { + digits_computed_so_far = n_digits; + for (i = n_digits - 1; i >= 0; i--) + { + unsigned int x; + x = ++(tstr[i]); + if (x < base) + goto rounded_ok; + digits_computed_so_far--; + } + tstr[0] = 1; + digits_computed_so_far = 1; + exp_in_base++; + rounded_ok:; + } + } + + /* We might have fewer digits than requested as a result of rounding above, + (i.e. 0.999999 => 1.0) or because we have a number that simply doesn't + need many digits in this base (i.e., 0.125 in base 10). */ + if (n_digits > digits_computed_so_far) + n_digits = digits_computed_so_far; + + /* Remove trailing 0. There can be many zeros. */ + while (n_digits != 0 && tstr[n_digits - 1] == 0) + n_digits--; + + /* Translate to ascii and null-terminate. */ + for (i = 0; i < n_digits; i++) + *str++ = num_to_text[tstr[i]]; + *str = 0; + *exp = exp_in_base; + TMP_FREE (marker); + return digit_ptr; +} + +#if COPY_THIS_TO_OTHER_PLACES + /* Use this expression in lots of places in the library instead of the + count_leading_zeros+expression that is used currently. This expression + is much more accurate and will save odles of memory. */ + rsize = ((mp_size_t) (exp_in_base / __mp_bases[base].chars_per_bit_exactly) + + BITS_PER_MP_LIMB) / BITS_PER_MP_LIMB; +#endif diff --git a/contrib/libgmp/mpf/init.c b/contrib/libgmp/mpf/init.c new file mode 100644 index 0000000..5370121 --- /dev/null +++ b/contrib/libgmp/mpf/init.c @@ -0,0 +1,38 @@ +/* mpf_init() -- Make a new multiple precision number with value 0. + +Copyright (C) 1993, 1994, 1995 Free Software Foundation, Inc. + +This file is part of the GNU MP Library. + +The GNU MP Library is free software; you can redistribute it and/or modify +it under the terms of the GNU Library General Public License as published by +the Free Software Foundation; either version 2 of the License, or (at your +option) any later version. + +The GNU MP Library is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public +License for more details. + +You should have received a copy of the GNU Library General Public License +along with the GNU MP Library; see the file COPYING.LIB. If not, write to +the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, +MA 02111-1307, USA. */ + +#include "gmp.h" +#include "gmp-impl.h" + +void +#if __STDC__ +mpf_init (mpf_ptr r) +#else +mpf_init (r) + mpf_ptr r; +#endif +{ + mp_size_t prec = __gmp_default_fp_limb_precision; + r->_mp_d = (mp_ptr) (*_mp_allocate_func) ((prec + 1) * BYTES_PER_MP_LIMB); + r->_mp_prec = prec; + r->_mp_size = 0; + r->_mp_exp = 0; +} diff --git a/contrib/libgmp/mpf/init2.c b/contrib/libgmp/mpf/init2.c new file mode 100644 index 0000000..a3e5752 --- /dev/null +++ b/contrib/libgmp/mpf/init2.c @@ -0,0 +1,41 @@ +/* mpf_init2() -- Make a new multiple precision number with value 0. + +Copyright (C) 1993, 1994, 1995 Free Software Foundation, Inc. + +This file is part of the GNU MP Library. + +The GNU MP Library is free software; you can redistribute it and/or modify +it under the terms of the GNU Library General Public License as published by +the Free Software Foundation; either version 2 of the License, or (at your +option) any later version. + +The GNU MP Library is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public +License for more details. + +You should have received a copy of the GNU Library General Public License +along with the GNU MP Library; see the file COPYING.LIB. If not, write to +the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, +MA 02111-1307, USA. */ + +#include "gmp.h" +#include "gmp-impl.h" + +void +#if __STDC__ +mpf_init2 (mpf_ptr r, unsigned long int prec_in_bits) +#else +mpf_init2 (r, prec_in_bits) + mpf_ptr r; + unsigned long int prec_in_bits; +#endif +{ + mp_size_t prec; + + prec = (MAX (53, prec_in_bits) + 2 * BITS_PER_MP_LIMB - 1)/BITS_PER_MP_LIMB; + r->_mp_d = (mp_ptr) (*_mp_allocate_func) ((prec + 1) * BYTES_PER_MP_LIMB); + r->_mp_prec = prec; + r->_mp_size = 0; + r->_mp_exp = 0; +} diff --git a/contrib/libgmp/mpf/inp_str.c b/contrib/libgmp/mpf/inp_str.c new file mode 100644 index 0000000..1d3cd4c --- /dev/null +++ b/contrib/libgmp/mpf/inp_str.c @@ -0,0 +1,89 @@ +/* mpf_inp_str(dest_float, stream, base) -- Input a number in base + BASE from stdio stream STREAM and store the result in DEST_FLOAT. + +Copyright (C) 1996 Free Software Foundation, Inc. + +This file is part of the GNU MP Library. + +The GNU MP Library is free software; you can redistribute it and/or modify +it under the terms of the GNU Library General Public License as published by +the Free Software Foundation; either version 2 of the License, or (at your +option) any later version. + +The GNU MP Library is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public +License for more details. + +You should have received a copy of the GNU Library General Public License +along with the GNU MP Library; see the file COPYING.LIB. If not, write to +the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, +MA 02111-1307, USA. */ + +#include <stdio.h> +#include <ctype.h> +#include "gmp.h" +#include "gmp-impl.h" + +size_t +#if __STDC__ +mpf_inp_str (mpf_ptr rop, FILE *stream, int base) +#else +mpf_inp_str (rop, stream, base) + mpf_ptr rop; + FILE *stream; + int base; +#endif +{ + char *str; + size_t alloc_size, str_size; + int c; + size_t retval; + size_t nread; + + if (stream == 0) + stream = stdin; + + alloc_size = 100; + str = (char *) (*_mp_allocate_func) (alloc_size); + str_size = 0; + nread = 0; + + /* Skip whitespace. */ + do + { + c = getc (stream); + nread++; + } + while (isspace (c)); + + for (;;) + { + if (str_size >= alloc_size) + { + size_t old_alloc_size = alloc_size; + alloc_size = alloc_size * 3 / 2; + str = (char *) (*_mp_reallocate_func) (str, old_alloc_size, alloc_size); + } + if (c == EOF || isspace (c)) + break; + str[str_size++] = c; + c = getc (stream); + } + ungetc (c, stream); + + if (str_size >= alloc_size) + { + size_t old_alloc_size = alloc_size; + alloc_size = alloc_size * 3 / 2; + str = (char *) (*_mp_reallocate_func) (str, old_alloc_size, alloc_size); + } + str[str_size] = 0; + + retval = mpf_set_str (rop, str, base); + if (retval == -1) + return 0; /* error */ + + (*_mp_free_func) (str, alloc_size); + return str_size + nread; +} diff --git a/contrib/libgmp/mpf/iset.c b/contrib/libgmp/mpf/iset.c new file mode 100644 index 0000000..c2362e1 --- /dev/null +++ b/contrib/libgmp/mpf/iset.c @@ -0,0 +1,59 @@ +/* mpf_init_set -- Initialize a float and assign it from another float. + +Copyright (C) 1993, 1994, 1995 Free Software Foundation, Inc. + +This file is part of the GNU MP Library. + +The GNU MP Library is free software; you can redistribute it and/or modify +it under the terms of the GNU Library General Public License as published by +the Free Software Foundation; either version 2 of the License, or (at your +option) any later version. + +The GNU MP Library is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public +License for more details. + +You should have received a copy of the GNU Library General Public License +along with the GNU MP Library; see the file COPYING.LIB. If not, write to +the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, +MA 02111-1307, USA. */ + +#include "gmp.h" +#include "gmp-impl.h" + +void +#if __STDC__ +mpf_init_set (mpf_ptr r, mpf_srcptr s) +#else +mpf_init_set (r, s) + mpf_ptr r; + mpf_srcptr s; +#endif +{ + mp_ptr rp, sp; + mp_size_t ssize, size; + mp_size_t prec; + + prec = __gmp_default_fp_limb_precision; + r->_mp_d = (mp_ptr) (*_mp_allocate_func) ((prec + 1) * BYTES_PER_MP_LIMB); + r->_mp_prec = prec; + + prec++; /* lie not to lose precision in assignment */ + ssize = s->_mp_size; + size = ABS (ssize); + + rp = r->_mp_d; + sp = s->_mp_d; + + if (size > prec) + { + sp += size - prec; + size = prec; + } + + MPN_COPY (rp, sp, size); + + r->_mp_exp = s->_mp_exp; + r->_mp_size = ssize >= 0 ? size : -size; +} diff --git a/contrib/libgmp/mpf/iset_d.c b/contrib/libgmp/mpf/iset_d.c new file mode 100644 index 0000000..d09e8b8 --- /dev/null +++ b/contrib/libgmp/mpf/iset_d.c @@ -0,0 +1,39 @@ +/* mpf_init_set_d -- Initialize a float and assign it from a double. + +Copyright (C) 1993, 1994, 1995 Free Software Foundation, Inc. + +This file is part of the GNU MP Library. + +The GNU MP Library is free software; you can redistribute it and/or modify +it under the terms of the GNU Library General Public License as published by +the Free Software Foundation; either version 2 of the License, or (at your +option) any later version. + +The GNU MP Library is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public +License for more details. + +You should have received a copy of the GNU Library General Public License +along with the GNU MP Library; see the file COPYING.LIB. If not, write to +the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, +MA 02111-1307, USA. */ + +#include "gmp.h" +#include "gmp-impl.h" + +void +#if __STDC__ +mpf_init_set_d (mpf_ptr r, double val) +#else +mpf_init_set_d (r, val) + mpf_ptr r; + double val; +#endif +{ + mp_size_t prec = __gmp_default_fp_limb_precision; + r->_mp_d = (mp_ptr) (*_mp_allocate_func) ((prec + 1) * BYTES_PER_MP_LIMB); + r->_mp_prec = prec; + + mpf_set_d (r, val); +} diff --git a/contrib/libgmp/mpf/iset_si.c b/contrib/libgmp/mpf/iset_si.c new file mode 100644 index 0000000..e67eef4 --- /dev/null +++ b/contrib/libgmp/mpf/iset_si.c @@ -0,0 +1,55 @@ +/* mpf_init_set_si() -- Initialize a float and assign it from a signed int. + +Copyright (C) 1993, 1994, 1995 Free Software Foundation, Inc. + +This file is part of the GNU MP Library. + +The GNU MP Library is free software; you can redistribute it and/or modify +it under the terms of the GNU Library General Public License as published by +the Free Software Foundation; either version 2 of the License, or (at your +option) any later version. + +The GNU MP Library is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public +License for more details. + +You should have received a copy of the GNU Library General Public License +along with the GNU MP Library; see the file COPYING.LIB. If not, write to +the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, +MA 02111-1307, USA. */ + +#include "gmp.h" +#include "gmp-impl.h" + +void +#if __STDC__ +mpf_init_set_si (mpf_ptr r, long int val) +#else +mpf_init_set_si (r, val) + mpf_ptr r; + long int val; +#endif +{ + mp_size_t prec = __gmp_default_fp_limb_precision; + r->_mp_d = (mp_ptr) (*_mp_allocate_func) ((prec + 1) * BYTES_PER_MP_LIMB); + r->_mp_prec = prec; + + if (val > 0) + { + r->_mp_d[0] = val; + r->_mp_size = 1; + r->_mp_exp = 1; + } + else if (val < 0) + { + r->_mp_d[0] = -val; + r->_mp_size = -1; + r->_mp_exp = 1; + } + else + { + r->_mp_size = 0; + r->_mp_exp = 0; + } +} diff --git a/contrib/libgmp/mpf/iset_str.c b/contrib/libgmp/mpf/iset_str.c new file mode 100644 index 0000000..40bfe7c --- /dev/null +++ b/contrib/libgmp/mpf/iset_str.c @@ -0,0 +1,40 @@ +/* mpf_init_set_str -- Initialize a float and assign it from a string. + +Copyright (C) 1995 Free Software Foundation, Inc. + +This file is part of the GNU MP Library. + +The GNU MP Library is free software; you can redistribute it and/or modify +it under the terms of the GNU Library General Public License as published by +the Free Software Foundation; either version 2 of the License, or (at your +option) any later version. + +The GNU MP Library is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public +License for more details. + +You should have received a copy of the GNU Library General Public License +along with the GNU MP Library; see the file COPYING.LIB. If not, write to +the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, +MA 02111-1307, USA. */ + +#include "gmp.h" +#include "gmp-impl.h" + +int +#if __STDC__ +mpf_init_set_str (mpf_ptr r, const char *s, int base) +#else +mpf_init_set_str (r, s, base) + mpf_ptr r; + const char *s; + int base; +#endif +{ + mp_size_t prec = __gmp_default_fp_limb_precision; + r->_mp_d = (mp_ptr) (*_mp_allocate_func) ((prec + 1) * BYTES_PER_MP_LIMB); + r->_mp_prec = prec; + + return mpf_set_str (r, s, base); +} diff --git a/contrib/libgmp/mpf/iset_ui.c b/contrib/libgmp/mpf/iset_ui.c new file mode 100644 index 0000000..c6c24af --- /dev/null +++ b/contrib/libgmp/mpf/iset_ui.c @@ -0,0 +1,40 @@ +/* mpf_init_set_ui() -- Initialize a float and assign it from an unsigned int. + +Copyright (C) 1993, 1994, 1995 Free Software Foundation, Inc. + +This file is part of the GNU MP Library. + +The GNU MP Library is free software; you can redistribute it and/or modify +it under the terms of the GNU Library General Public License as published by +the Free Software Foundation; either version 2 of the License, or (at your +option) any later version. + +The GNU MP Library is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public +License for more details. + +You should have received a copy of the GNU Library General Public License +along with the GNU MP Library; see the file COPYING.LIB. If not, write to +the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, +MA 02111-1307, USA. */ + +#include "gmp.h" +#include "gmp-impl.h" + +void +#if __STDC__ +mpf_init_set_ui (mpf_ptr r, unsigned long int val) +#else +mpf_init_set_ui (r, val) + mpf_ptr r; + unsigned long int val; +#endif +{ + mp_size_t prec = __gmp_default_fp_limb_precision; + r->_mp_d = (mp_ptr) (*_mp_allocate_func) ((prec + 1) * BYTES_PER_MP_LIMB); + r->_mp_prec = prec; + r->_mp_d[0] = val; + r->_mp_size = val != 0; + r->_mp_exp = val != 0; +} diff --git a/contrib/libgmp/mpf/mul.c b/contrib/libgmp/mpf/mul.c new file mode 100644 index 0000000..8f1a2a9 --- /dev/null +++ b/contrib/libgmp/mpf/mul.c @@ -0,0 +1,94 @@ +/* mpf_mul -- Multiply two floats. + +Copyright (C) 1993, 1994, 1996 Free Software Foundation, Inc. + +This file is part of the GNU MP Library. + +The GNU MP Library is free software; you can redistribute it and/or modify +it under the terms of the GNU Library General Public License as published by +the Free Software Foundation; either version 2 of the License, or (at your +option) any later version. + +The GNU MP Library is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public +License for more details. + +You should have received a copy of the GNU Library General Public License +along with the GNU MP Library; see the file COPYING.LIB. If not, write to +the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, +MA 02111-1307, USA. */ + +#include "gmp.h" +#include "gmp-impl.h" + +void +#if __STDC__ +mpf_mul (mpf_ptr r, mpf_srcptr u, mpf_srcptr v) +#else +mpf_mul (r, u, v) + mpf_ptr r; + mpf_srcptr u; + mpf_srcptr v; +#endif +{ + mp_srcptr up, vp; + mp_size_t usize, vsize; + mp_size_t sign_product; + mp_size_t prec = r->_mp_prec; + TMP_DECL (marker); + + TMP_MARK (marker); + usize = u->_mp_size; + vsize = v->_mp_size; + sign_product = usize ^ vsize; + + usize = ABS (usize); + vsize = ABS (vsize); + + up = u->_mp_d; + vp = v->_mp_d; + if (usize > prec) + { + up += usize - prec; + usize = prec; + } + if (vsize > prec) + { + vp += vsize - prec; + vsize = prec; + } + + if (usize == 0 || vsize == 0) + { + r->_mp_size = 0; + r->_mp_exp = 0; /* ??? */ + } + else + { + mp_size_t rsize; + mp_limb_t cy_limb; + mp_ptr rp, tp; + mp_size_t adj; + + rsize = usize + vsize; + tp = (mp_ptr) TMP_ALLOC (rsize * BYTES_PER_MP_LIMB); + cy_limb = (usize >= vsize + ? mpn_mul (tp, up, usize, vp, vsize) + : mpn_mul (tp, vp, vsize, up, usize)); + + adj = cy_limb == 0; + rsize -= adj; + prec++; + if (rsize > prec) + { + tp += rsize - prec; + rsize = prec; + } + rp = r->_mp_d; + MPN_COPY (rp, tp, rsize); + r->_mp_exp = u->_mp_exp + v->_mp_exp - adj; + r->_mp_size = sign_product >= 0 ? rsize : -rsize; + } + TMP_FREE (marker); +} diff --git a/contrib/libgmp/mpf/mul_2exp.c b/contrib/libgmp/mpf/mul_2exp.c new file mode 100644 index 0000000..0ed35a0 --- /dev/null +++ b/contrib/libgmp/mpf/mul_2exp.c @@ -0,0 +1,89 @@ +/* mpf_mul_2exp -- Multiply a float by 2^n. + +Copyright (C) 1993, 1994, 1996 Free Software Foundation, Inc. + +This file is part of the GNU MP Library. + +The GNU MP Library is free software; you can redistribute it and/or modify +it under the terms of the GNU Library General Public License as published by +the Free Software Foundation; either version 2 of the License, or (at your +option) any later version. + +The GNU MP Library is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public +License for more details. + +You should have received a copy of the GNU Library General Public License +along with the GNU MP Library; see the file COPYING.LIB. If not, write to +the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, +MA 02111-1307, USA. */ + +#include "gmp.h" +#include "gmp-impl.h" + +void +#if __STDC__ +mpf_mul_2exp (mpf_ptr r, mpf_srcptr u, unsigned long int exp) +#else +mpf_mul_2exp (r, u, exp) + mpf_ptr r; + mpf_srcptr u; + unsigned long int exp; +#endif +{ + mp_srcptr up; + mp_ptr rp = r->_mp_d; + mp_size_t usize; + mp_size_t abs_usize; + mp_size_t prec = r->_mp_prec; + mp_exp_t uexp = u->_mp_exp; + + usize = u->_mp_size; + + if (usize == 0) + { + r->_mp_size = 0; + r->_mp_exp = 0; + return; + } + + abs_usize = ABS (usize); + up = u->_mp_d; + + if (abs_usize > prec) + { + up += abs_usize - prec; + abs_usize = prec; + } + + if (exp % BITS_PER_MP_LIMB == 0) + { + if (rp != up) + MPN_COPY (rp, up, abs_usize); + r->_mp_size = usize >= 0 ? abs_usize : -abs_usize; + r->_mp_exp = uexp + exp / BITS_PER_MP_LIMB; + } + else + { + mp_limb_t cy_limb; + if (r != u) + { + cy_limb = mpn_lshift (rp, up, abs_usize, exp % BITS_PER_MP_LIMB); + rp[abs_usize] = cy_limb; + cy_limb = cy_limb != 0; + } + else + { + /* Use mpn_rshift since mpn_lshift operates downwards, and we + therefore would clobber part of U before using that part. */ + cy_limb = mpn_rshift (rp + 1, up, abs_usize, -exp % BITS_PER_MP_LIMB); + rp[0] = cy_limb; + cy_limb = rp[abs_usize] != 0; + } + + abs_usize += cy_limb; + r->_mp_size = usize >= 0 ? abs_usize : -abs_usize; + r->_mp_exp = uexp + exp / BITS_PER_MP_LIMB + cy_limb; + } +} diff --git a/contrib/libgmp/mpf/mul_ui.c b/contrib/libgmp/mpf/mul_ui.c new file mode 100644 index 0000000..fc87cb5 --- /dev/null +++ b/contrib/libgmp/mpf/mul_ui.c @@ -0,0 +1,74 @@ +/* mpf_mul_ui -- Multiply a float and an unsigned integer. + +Copyright (C) 1993, 1994, 1996 Free Software Foundation, Inc. + +This file is part of the GNU MP Library. + +The GNU MP Library is free software; you can redistribute it and/or modify +it under the terms of the GNU Library General Public License as published by +the Free Software Foundation; either version 2 of the License, or (at your +option) any later version. + +The GNU MP Library is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public +License for more details. + +You should have received a copy of the GNU Library General Public License +along with the GNU MP Library; see the file COPYING.LIB. If not, write to +the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, +MA 02111-1307, USA. */ + +#include "gmp.h" +#include "gmp-impl.h" + +void +#if __STDC__ +mpf_mul_ui (mpf_ptr r, mpf_srcptr u, unsigned long int v) +#else +mpf_mul_ui (r, u, v) + mpf_ptr r; + mpf_srcptr u; + unsigned long int v; +#endif +{ + mp_srcptr up; + mp_size_t usize; + mp_size_t size; + mp_size_t prec = r->_mp_prec; + mp_limb_t cy_limb; + mp_ptr rp; + + usize = u->_mp_size; + size = ABS (usize); + + rp = r->_mp_d; + up = u->_mp_d; + if (size > prec) + { + up += size - prec; + size = prec; + } + +#if 0 + /* Since we can do it at almost no cost, remove zero limbs at low end of + result. */ + if (up[0] == 0) + up++, size--; +#endif + + if (size == 0 || v == 0) + { + r->_mp_size = 0; + r->_mp_exp = 0; /* ??? */ + } + else + { + cy_limb = mpn_mul_1 (rp, up, size, (mp_limb_t) v); + rp[size] = cy_limb; + cy_limb = cy_limb != 0; + r->_mp_exp = u->_mp_exp + cy_limb; + size += cy_limb; + r->_mp_size = usize >= 0 ? size : -size; + } +} diff --git a/contrib/libgmp/mpf/neg.c b/contrib/libgmp/mpf/neg.c new file mode 100644 index 0000000..a4139fb --- /dev/null +++ b/contrib/libgmp/mpf/neg.c @@ -0,0 +1,59 @@ +/* mpf_neg -- Negate a float. + +Copyright (C) 1993, 1994, 1995 Free Software Foundation, Inc. + +This file is part of the GNU MP Library. + +The GNU MP Library is free software; you can redistribute it and/or modify +it under the terms of the GNU Library General Public License as published by +the Free Software Foundation; either version 2 of the License, or (at your +option) any later version. + +The GNU MP Library is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public +License for more details. + +You should have received a copy of the GNU Library General Public License +along with the GNU MP Library; see the file COPYING.LIB. If not, write to +the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, +MA 02111-1307, USA. */ + +#include "gmp.h" +#include "gmp-impl.h" + +void +#if __STDC__ +mpf_neg (mpf_ptr r, mpf_srcptr u) +#else +mpf_neg (r, u) + mpf_ptr r; + mpf_srcptr u; +#endif +{ + mp_size_t size; + + size = -u->_mp_size; + if (r != u) + { + mp_size_t prec; + mp_size_t asize; + mp_ptr rp, up; + + prec = r->_mp_prec + 1; /* lie not to lose precision in assignment */ + asize = ABS (size); + rp = r->_mp_d; + up = u->_mp_d; + + if (asize > prec) + { + up += asize - prec; + asize = prec; + } + + MPN_COPY (rp, up, asize); + r->_mp_exp = u->_mp_exp; + size = size >= 0 ? asize : -asize; + } + r->_mp_size = size; +} diff --git a/contrib/libgmp/mpf/out_str.c b/contrib/libgmp/mpf/out_str.c new file mode 100644 index 0000000..2a7a954 --- /dev/null +++ b/contrib/libgmp/mpf/out_str.c @@ -0,0 +1,89 @@ +/* mpf_out_str (stream, base, n_digits, op) -- Print N_DIGITS digits from + the float OP to STREAM in base BASE. Return the number of characters + written, or 0 if an error occurred. + +Copyright (C) 1996 Free Software Foundation, Inc. + +This file is part of the GNU MP Library. + +The GNU MP Library is free software; you can redistribute it and/or modify +it under the terms of the GNU Library General Public License as published by +the Free Software Foundation; either version 2 of the License, or (at your +option) any later version. + +The GNU MP Library is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public +License for more details. + +You should have received a copy of the GNU Library General Public License +along with the GNU MP Library; see the file COPYING.LIB. If not, write to +the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, +MA 02111-1307, USA. */ + +#include <stdio.h> +#include "gmp.h" +#include "gmp-impl.h" + +size_t +#if __STDC__ +mpf_out_str (FILE *stream, int base, size_t n_digits, mpf_srcptr op) +#else +mpf_out_str (stream, base, n_digits, op) + FILE *stream; + int base; + size_t n_digits; + mpf_srcptr op; +#endif +{ + char *str; + mp_exp_t exp; + size_t written; + TMP_DECL (marker); + + TMP_MARK (marker); + + if (base == 0) + base = 10; + if (n_digits == 0) + n_digits = (((op->_mp_prec - 1) * BITS_PER_MP_LIMB) + * __mp_bases[base].chars_per_bit_exactly); + + if (stream == 0) + stream = stdout; + + str = (char *) TMP_ALLOC (n_digits + 2); /* extra for minus sign and \0 */ + + mpf_get_str (str, &exp, base, n_digits, op); + n_digits = strlen (str); + + written = 0; + + /* Write sign */ + if (str[0] == '-') + { + str++; + fputc ('-', stream); + written = 1; + } + + fwrite ("0.", 1, 2, stream); + written += 2; + + /* Write mantissa */ + { + size_t fwret; + fwret = fwrite (str, 1, n_digits, stream); + written += fwret; + } + + /* Write exponent */ + { + int fpret; + fpret = fprintf (stream, (base <= 10 ? "e%ld" : "@%ld"), exp); + written += fpret; + } + + TMP_FREE (marker); + return ferror (stream) ? 0 : written; +} diff --git a/contrib/libgmp/mpf/random2.c b/contrib/libgmp/mpf/random2.c new file mode 100644 index 0000000..8e67b11 --- /dev/null +++ b/contrib/libgmp/mpf/random2.c @@ -0,0 +1,65 @@ +/* mpf_random2 -- Generate a positive random mpf_t of specified size, with + long runs of consecutive ones and zeros in the binary representation. + Intended for testing of other MP routines. + +Copyright (C) 1995, 1996 Free Software Foundation, Inc. + +This file is part of the GNU MP Library. + +The GNU MP Library is free software; you can redistribute it and/or modify +it under the terms of the GNU Library General Public License as published by +the Free Software Foundation; either version 2 of the License, or (at your +option) any later version. + +The GNU MP Library is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public +License for more details. + +You should have received a copy of the GNU Library General Public License +along with the GNU MP Library; see the file COPYING.LIB. If not, write to +the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, +MA 02111-1307, USA. */ + +#include "gmp.h" +#include "gmp-impl.h" + +#if defined (__hpux) || defined (alpha__) || defined (__svr4__) || defined (__SVR4) +/* HPUX lacks random(). DEC OSF/1 1.2 random() returns a double. */ +long mrand48 (); +static inline long +random () +{ + return mrand48 (); +} +#else +long random (); +#endif + +void +#if __STDC__ +mpf_random2 (mpf_ptr x, mp_size_t size, mp_exp_t exp) +#else +mpf_random2 (x, size, exp) + mpf_ptr x; + mp_size_t size; + mp_exp_t exp; +#endif +{ + mp_size_t asize; + mp_size_t prec = x->_mp_prec; + + asize = ABS (size); + if (asize != 0) + { + if (asize > prec + 1) + asize = prec + 1; + + mpn_random2 (x->_mp_d, asize); + } + + if (exp != 0) + exp = random () % (2 * exp) - exp; + x->_mp_exp = asize == 0 ? 0 : exp; + x->_mp_size = size < 0 ? -asize : asize; +} diff --git a/contrib/libgmp/mpf/reldiff.c b/contrib/libgmp/mpf/reldiff.c new file mode 100644 index 0000000..c846466 --- /dev/null +++ b/contrib/libgmp/mpf/reldiff.c @@ -0,0 +1,52 @@ +/* mpf_reldiff -- Generate the relative difference of two floats. + +Copyright (C) 1996 Free Software Foundation, Inc. + +This file is part of the GNU MP Library. + +The GNU MP Library is free software; you can redistribute it and/or modify +it under the terms of the GNU Library General Public License as published by +the Free Software Foundation; either version 2 of the License, or (at your +option) any later version. + +The GNU MP Library is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public +License for more details. + +You should have received a copy of the GNU Library General Public License +along with the GNU MP Library; see the file COPYING.LIB. If not, write to +the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, +MA 02111-1307, USA. */ + +#include "gmp.h" +#include "gmp-impl.h" + +void +#if __STDC__ +mpf_reldiff (mpf_t rdiff, mpf_srcptr x, mpf_srcptr y) +#else +mpf_reldiff (rdiff, x, y) + mpf_t rdiff; + mpf_srcptr x; + mpf_srcptr y; +#endif +{ + if (mpf_cmp_ui (x, 0) == 0) + { + mpf_set_ui (rdiff, (unsigned long int) (mpf_sgn (y) != 0)); + } + else + { + mpf_t d; + mp_limb_t tmp_limb[2]; + + d->_mp_prec = 1; + d->_mp_d = tmp_limb; + + mpf_sub (d, x, y); + mpf_abs (d, d); + mpf_div (rdiff, d, x); + } +} + diff --git a/contrib/libgmp/mpf/set.c b/contrib/libgmp/mpf/set.c new file mode 100644 index 0000000..5778b85 --- /dev/null +++ b/contrib/libgmp/mpf/set.c @@ -0,0 +1,53 @@ +/* mpf_set -- Assign a float from another float. + +Copyright (C) 1993, 1994, 1995 Free Software Foundation, Inc. + +This file is part of the GNU MP Library. + +The GNU MP Library is free software; you can redistribute it and/or modify +it under the terms of the GNU Library General Public License as published by +the Free Software Foundation; either version 2 of the License, or (at your +option) any later version. + +The GNU MP Library is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public +License for more details. + +You should have received a copy of the GNU Library General Public License +along with the GNU MP Library; see the file COPYING.LIB. If not, write to +the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, +MA 02111-1307, USA. */ + +#include "gmp.h" +#include "gmp-impl.h" + +void +#if __STDC__ +mpf_set (mpf_ptr r, mpf_srcptr u) +#else +mpf_set (r, u) + mpf_ptr r; + mpf_srcptr u; +#endif +{ + mp_ptr rp, up; + mp_size_t size, asize; + mp_size_t prec; + + prec = r->_mp_prec + 1; /* lie not to lose precision in assignment */ + size = u->_mp_size; + asize = ABS (size); + rp = r->_mp_d; + up = u->_mp_d; + + if (asize > prec) + { + up += asize - prec; + asize = prec; + } + + MPN_COPY (rp, up, asize); + r->_mp_exp = u->_mp_exp; + r->_mp_size = size >= 0 ? asize : -asize; +} diff --git a/contrib/libgmp/mpf/set_d.c b/contrib/libgmp/mpf/set_d.c new file mode 100644 index 0000000..43eb157 --- /dev/null +++ b/contrib/libgmp/mpf/set_d.c @@ -0,0 +1,47 @@ +/* mpf_set_d -- Assign a float from a IEEE double. + +Copyright (C) 1993, 1994, 1995, 1996 Free Software Foundation, Inc. + +This file is part of the GNU MP Library. + +The GNU MP Library is free software; you can redistribute it and/or modify +it under the terms of the GNU Library General Public License as published by +the Free Software Foundation; either version 2 of the License, or (at your +option) any later version. + +The GNU MP Library is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public +License for more details. + +You should have received a copy of the GNU Library General Public License +along with the GNU MP Library; see the file COPYING.LIB. If not, write to +the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, +MA 02111-1307, USA. */ + +#include "gmp.h" +#include "gmp-impl.h" + +void +#if __STDC__ +mpf_set_d (mpf_ptr r, double d) +#else +mpf_set_d (r, d) + mpf_ptr r; + double d; +#endif +{ + int negative; + + if (d == 0) + { + SIZ(r) = 0; + EXP(r) = 0; + return; + } + negative = d < 0; + d = ABS (d); + + EXP(r) = __gmp_extract_double (PTR(r), d); + SIZ(r) = negative ? -LIMBS_PER_DOUBLE : LIMBS_PER_DOUBLE; +} diff --git a/contrib/libgmp/mpf/set_dfl_prec.c b/contrib/libgmp/mpf/set_dfl_prec.c new file mode 100644 index 0000000..55069e4 --- /dev/null +++ b/contrib/libgmp/mpf/set_dfl_prec.c @@ -0,0 +1,40 @@ +/* mpf_set_default_prec -- + +Copyright (C) 1993, 1994, 1995 Free Software Foundation, Inc. + +This file is part of the GNU MP Library. + +The GNU MP Library is free software; you can redistribute it and/or modify +it under the terms of the GNU Library General Public License as published by +the Free Software Foundation; either version 2 of the License, or (at your +option) any later version. + +The GNU MP Library is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public +License for more details. + +You should have received a copy of the GNU Library General Public License +along with the GNU MP Library; see the file COPYING.LIB. If not, write to +the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, +MA 02111-1307, USA. */ + +#include "gmp.h" +#include "gmp-impl.h" + +mp_size_t __gmp_default_fp_limb_precision + = (53 + 2 * BITS_PER_MP_LIMB - 1) / BITS_PER_MP_LIMB; + +void +#if __STDC__ +mpf_set_default_prec (unsigned long int prec_in_bits) +#else +mpf_set_default_prec (prec_in_bits) + unsigned long int prec_in_bits; +#endif +{ + mp_size_t prec; + + prec = (MAX (53, prec_in_bits) + 2 * BITS_PER_MP_LIMB - 1)/BITS_PER_MP_LIMB; + __gmp_default_fp_limb_precision = prec; +} diff --git a/contrib/libgmp/mpf/set_prc.c b/contrib/libgmp/mpf/set_prc.c new file mode 100644 index 0000000..10f2b06 --- /dev/null +++ b/contrib/libgmp/mpf/set_prc.c @@ -0,0 +1,57 @@ +/* mpf_set_prec(x) -- Change the precision of x. + +Copyright (C) 1993, 1994, 1995 Free Software Foundation, Inc. + +This file is part of the GNU MP Library. + +The GNU MP Library is free software; you can redistribute it and/or modify +it under the terms of the GNU Library General Public License as published by +the Free Software Foundation; either version 2 of the License, or (at your +option) any later version. + +The GNU MP Library is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public +License for more details. + +You should have received a copy of the GNU Library General Public License +along with the GNU MP Library; see the file COPYING.LIB. If not, write to +the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, +MA 02111-1307, USA. */ + +#include "gmp.h" +#include "gmp-impl.h" + +void +#if __STDC__ +mpf_set_prec (mpf_ptr x, unsigned long int prec_in_bits) +#else +mpf_set_prec (x, prec_in_bits) + mpf_ptr x; + unsigned long int prec_in_bits; +#endif +{ + mp_size_t prec; + mp_size_t size = ABS (x->_mp_size); + + prec = (MAX (53, prec_in_bits) + 2 * BITS_PER_MP_LIMB - 1)/BITS_PER_MP_LIMB; + + /* We want the most significant limbs, so move the limbs down if we are + about to truncate the value. */ + if (size > prec + 1) + { + mp_size_t offset = size - (prec + 1); + mp_ptr xp = x->_mp_d; + + MPN_COPY (xp, xp + offset, prec + 1); + } + + x->_mp_d = (mp_ptr) (*_mp_reallocate_func) + (x->_mp_d, + (x->_mp_prec + 1) * BYTES_PER_MP_LIMB, (prec + 1) * BYTES_PER_MP_LIMB); + x->_mp_prec = prec; + + /* If the precision decreased, truncate the number. */ + if (size > prec + 1) + x->_mp_size = x->_mp_size >= 0 ? (prec + 1) : -(prec + 1); +} diff --git a/contrib/libgmp/mpf/set_prc_raw.c b/contrib/libgmp/mpf/set_prc_raw.c new file mode 100644 index 0000000..f55188a --- /dev/null +++ b/contrib/libgmp/mpf/set_prc_raw.c @@ -0,0 +1,39 @@ +/* mpf_set_prec_raw(x,bits) -- Change the precision of x without changing + allocation. For proper operation, the original precision need to be reset + sooner or later. + +Copyright (C) 1996 Free Software Foundation, Inc. + +This file is part of the GNU MP Library. + +The GNU MP Library is free software; you can redistribute it and/or modify +it under the terms of the GNU Library General Public License as published by +the Free Software Foundation; either version 2 of the License, or (at your +option) any later version. + +The GNU MP Library is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public +License for more details. + +You should have received a copy of the GNU Library General Public License +along with the GNU MP Library; see the file COPYING.LIB. If not, write to +the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, +MA 02111-1307, USA. */ + +#include "gmp.h" +#include "gmp-impl.h" + +void +#if __STDC__ +mpf_set_prec_raw (mpf_ptr x, unsigned long int prec_in_bits) +#else +mpf_set_prec_raw (x, prec_in_bits) + mpf_ptr x; + unsigned long int prec_in_bits; +#endif +{ + mp_size_t prec; + prec = (MAX (53, prec_in_bits) + 2 * BITS_PER_MP_LIMB - 1)/BITS_PER_MP_LIMB; + x->_mp_prec = prec; +} diff --git a/contrib/libgmp/mpf/set_q.c b/contrib/libgmp/mpf/set_q.c new file mode 100644 index 0000000..69d81e3 --- /dev/null +++ b/contrib/libgmp/mpf/set_q.c @@ -0,0 +1,170 @@ +/* mpf_set_q (mpf_t rop, mpq_t op) -- Convert the rational op to the float rop. + +Copyright (C) 1996 Free Software Foundation, Inc. + +This file is part of the GNU MP Library. + +The GNU MP Library is free software; you can redistribute it and/or modify +it under the terms of the GNU Library General Public License as published by +the Free Software Foundation; either version 2 of the License, or (at your +option) any later version. + +The GNU MP Library is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public +License for more details. + +You should have received a copy of the GNU Library General Public License +along with the GNU MP Library; see the file COPYING.LIB. If not, write to +the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, +MA 02111-1307, USA. */ + +#include "gmp.h" +#include "gmp-impl.h" +#include "longlong.h" + +/* Algorithm: + 1. Develop >= n bits of src.num / src.den, where n is the number of bits + in a double. This (partial) division will use all bits from the + denominator. + 2. Use the remainder to determine how to round the result. + 3. Assign the integral result to a temporary double. + 4. Scale the temporary double, and return the result. + + An alternative algorithm, that would be faster: + 0. Let n be somewhat larger than the number of significant bits in a double. + 1. Extract the most significant n bits of the denominator, and an equal + number of bits from the numerator. + 2. Interpret the extracted numbers as integers, call them a and b + respectively, and develop n bits of the fractions ((a + 1) / b) and + (a / (b + 1)) using mpn_divrem. + 3. If the computed values are identical UP TO THE POSITION WE CARE ABOUT, + we are done. If they are different, repeat the algorithm from step 1, + but first let n = n * 2. + 4. If we end up using all bits from the numerator and denominator, fall + back to the first algorithm above. + 5. Just to make life harder, The computation of a + 1 and b + 1 above + might give carry-out... Needs special handling. It might work to + subtract 1 in both cases instead. +*/ + +void +#if __STDC__ +mpf_set_q (mpf_t r, mpq_srcptr q) +#else +mpf_set_q (r, q) + mpf_t r; + mpq_srcptr q; +#endif +{ + mp_ptr np, dp; + mp_ptr rp; + mp_size_t nsize, dsize; + mp_size_t qsize, rsize; + mp_size_t sign_quotient; + unsigned normalization_steps; + mp_limb_t qlimb; + mp_ptr qp; + mp_size_t prec; + mp_exp_t exp; + TMP_DECL (marker); + + nsize = SIZ (&q->_mp_num); + dsize = SIZ (&q->_mp_den); + + if (nsize == 0) + { + SIZ (r) = 0; + EXP (r) = 0; + return; + } + + prec = PREC (r) + 1; + + TMP_MARK (marker); + + qp = PTR (r); + + sign_quotient = nsize ^ dsize; + nsize = ABS (nsize); + dsize = ABS (dsize); + np = PTR (&q->_mp_num); + dp = PTR (&q->_mp_den); + + exp = nsize - dsize; + + if (nsize > prec) + { + np += nsize - prec; + nsize = prec; + } + if (dsize > prec) + { + dp += dsize - prec; + dsize = prec; + } + + rsize = MAX (nsize, dsize); + rp = (mp_ptr) TMP_ALLOC ((rsize + 1) * BYTES_PER_MP_LIMB); + + count_leading_zeros (normalization_steps, dp[dsize - 1]); + + /* Normalize the denominator, i.e. make its most significant bit set by + shifting it NORMALIZATION_STEPS bits to the left. Also shift the + numerator the same number of steps (to keep the quotient the same!). */ + if (normalization_steps != 0) + { + mp_ptr tp; + mp_limb_t nlimb; + + /* Shift up the denominator setting the most significant bit of + the most significant limb. Use temporary storage not to clobber + the original contents of the denominator. */ + tp = (mp_ptr) TMP_ALLOC (dsize * BYTES_PER_MP_LIMB); + mpn_lshift (tp, dp, dsize, normalization_steps); + dp = tp; + + if (rsize != nsize) + { + MPN_ZERO (rp, rsize - nsize); + nlimb = mpn_lshift (rp + (rsize - nsize), + np, nsize, normalization_steps); + } + else + { + nlimb = mpn_lshift (rp, np, nsize, normalization_steps); + } + if (nlimb != 0) + { + rp[rsize] = nlimb; + rsize++; + exp++; + } + } + else + { + if (rsize != nsize) + { + MPN_ZERO (rp, rsize - nsize); + MPN_COPY (rp + (rsize - nsize), np, nsize); + } + else + { + MPN_COPY (rp, np, rsize); + } + } + + qlimb = mpn_divrem (qp, prec - 1 - (rsize - dsize), rp, rsize, dp, dsize); + qsize = prec - 1; + if (qlimb) + { + qp[qsize] = qlimb; + qsize++; + exp++; + } + + EXP (r) = exp; + SIZ (r) = qsize; + + TMP_FREE (marker); +} diff --git a/contrib/libgmp/mpf/set_si.c b/contrib/libgmp/mpf/set_si.c new file mode 100644 index 0000000..f9b4b55 --- /dev/null +++ b/contrib/libgmp/mpf/set_si.c @@ -0,0 +1,51 @@ +/* mpf_set_si() -- Assign a float from a signed int. + +Copyright (C) 1993, 1994, 1995 Free Software Foundation, Inc. + +This file is part of the GNU MP Library. + +The GNU MP Library is free software; you can redistribute it and/or modify +it under the terms of the GNU Library General Public License as published by +the Free Software Foundation; either version 2 of the License, or (at your +option) any later version. + +The GNU MP Library is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public +License for more details. + +You should have received a copy of the GNU Library General Public License +along with the GNU MP Library; see the file COPYING.LIB. If not, write to +the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, +MA 02111-1307, USA. */ + +#include "gmp.h" +#include "gmp-impl.h" + +void +#if __STDC__ +mpf_set_si (mpf_ptr x, long int val) +#else +mpf_set_si (x, val) + mpf_ptr x; + long int val; +#endif +{ + if (val > 0) + { + x->_mp_d[0] = val; + x->_mp_size = 1; + x->_mp_exp = 1; + } + else if (val < 0) + { + x->_mp_d[0] = -val; + x->_mp_size = -1; + x->_mp_exp = 1; + } + else + { + x->_mp_size = 0; + x->_mp_exp = 0; + } +} diff --git a/contrib/libgmp/mpf/set_str.c b/contrib/libgmp/mpf/set_str.c new file mode 100644 index 0000000..2ab9fae --- /dev/null +++ b/contrib/libgmp/mpf/set_str.c @@ -0,0 +1,302 @@ +/* mpf_set_str (dest, string, base) -- Convert the string STRING + in base BASE to a float in dest. If BASE is zero, the leading characters + of STRING is used to figure out the base. + +Copyright (C) 1993, 1994, 1995, 1996 Free Software Foundation, Inc. + +This file is part of the GNU MP Library. + +The GNU MP Library is free software; you can redistribute it and/or modify +it under the terms of the GNU Library General Public License as published by +the Free Software Foundation; either version 2 of the License, or (at your +option) any later version. + +The GNU MP Library is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public +License for more details. + +You should have received a copy of the GNU Library General Public License +along with the GNU MP Library; see the file COPYING.LIB. If not, write to +the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, +MA 02111-1307, USA. */ + +#include <string.h> +#include <ctype.h> +#include "gmp.h" +#include "gmp-impl.h" +#include "longlong.h" + +long int strtol _PROTO ((const char *, char **ptr, int)); + +static int +digit_value_in_base (c, base) + int c; + int base; +{ + int digit; + + if (isdigit (c)) + digit = c - '0'; + else if (islower (c)) + digit = c - 'a' + 10; + else if (isupper (c)) + digit = c - 'A' + 10; + else + return -1; + + if (digit < base) + return digit; + return -1; +} + +int +#if __STDC__ +mpf_set_str (mpf_ptr x, const char *str, int base) +#else +mpf_set_str (x, str, base) + mpf_ptr x; + char *str; + int base; +#endif +{ + size_t str_size; + char *s, *begs; + size_t i; + mp_size_t xsize; + int c; + int negative; + char *dotpos = 0; + int expflag; + int decimal_exponent_flag; + TMP_DECL (marker); + + TMP_MARK (marker); + + c = *str; + + /* Skip whitespace. */ + while (isspace (c)) + c = *++str; + + negative = 0; + if (c == '-') + { + negative = 1; + c = *++str; + } + + decimal_exponent_flag = base < 0; + base = ABS (base); + + if (digit_value_in_base (c, base == 0 ? 10 : base) < 0) + return -1; /* error if no digits */ + + /* If BASE is 0, try to find out the base by looking at the initial + characters. */ + if (base == 0) + { + base = 10; +#if 0 + if (c == '0') + { + base = 8; + c = *++str; + if (c == 'x' || c == 'X') + base = 16; + } +#endif + } + + expflag = 0; + str_size = strlen (str); + for (i = 0; i < str_size; i++) + { + c = str[i]; + if (c == '@' || (base <= 10 && (c == 'e' || c == 'E'))) + { + expflag = 1; + str_size = i; + break; + } + + } + + s = begs = (char *) TMP_ALLOC (str_size + 1); + + for (i = 0; i < str_size; i++) + { + c = *str; + if (!isspace (c)) + { + int dig; + + if (c == '.') + { + if (dotpos != 0) + { + TMP_FREE (marker); + return -1; + } + dotpos = s; + } + else + { + dig = digit_value_in_base (c, base); + if (dig < 0) + { + TMP_FREE (marker); + return -1; + } + *s++ = dig; + } + } + c = *++str; + } + + str_size = s - begs; + + xsize = str_size / __mp_bases[base].chars_per_limb + 2; + { + long exp_in_base; + mp_size_t rsize, msize; + int cnt, i; + mp_ptr mp, xp, tp, rp; + mp_limb_t cy; + mp_exp_t exp_in_limbs; + mp_size_t prec = x->_mp_prec; + int divflag; + mp_size_t xxx = 0; + + mp = (mp_ptr) TMP_ALLOC (xsize * BYTES_PER_MP_LIMB); + msize = mpn_set_str (mp, (unsigned char *) begs, str_size, base); + + if (msize == 0) + { + x->_mp_size = 0; + x->_mp_exp = 0; + TMP_FREE (marker); + return 0; + } + + if (expflag != 0) + exp_in_base = strtol (str + 1, (char **) 0, + decimal_exponent_flag ? 10 : base); + else + exp_in_base = 0; + if (dotpos != 0) + exp_in_base -= s - dotpos; + divflag = exp_in_base < 0; + exp_in_base = ABS (exp_in_base); + + if (exp_in_base == 0) + { + MPN_COPY (x->_mp_d, mp, msize); + x->_mp_size = negative ? -msize : msize; + x->_mp_exp = msize; + TMP_FREE (marker); + return 0; + } + +#if 1 + rsize = (((mp_size_t) (exp_in_base / __mp_bases[base].chars_per_bit_exactly)) + / BITS_PER_MP_LIMB + 3); +#else + count_leading_zeros (cnt, (mp_limb_t) base); + rsize = exp_in_base - cnt * exp_in_base / BITS_PER_MP_LIMB + 1; +#endif + rp = (mp_ptr) TMP_ALLOC (rsize * BYTES_PER_MP_LIMB); + tp = (mp_ptr) TMP_ALLOC (rsize * BYTES_PER_MP_LIMB); + + rp[0] = base; + rsize = 1; + + count_leading_zeros (cnt, exp_in_base); + + for (i = BITS_PER_MP_LIMB - cnt - 2; i >= 0; i--) + { + mpn_mul_n (tp, rp, rp, rsize); + rsize = 2 * rsize; + rsize -= tp[rsize - 1] == 0; + xp = tp; tp = rp; rp = xp; + + if (((exp_in_base >> i) & 1) != 0) + { + cy = mpn_mul_1 (rp, rp, rsize, (mp_limb_t) base); + rp[rsize] = cy; + rsize += cy != 0; + } + } + + if (rsize > prec) + { + xxx += rsize - prec; + rp += rsize - prec; + rsize = prec; + } +#if 0 + if (msize > prec) + { + xxx -= msize - prec; + mp += msize - prec; + msize = prec; + } +#endif + if (divflag) + { + mp_ptr qp; + mp_limb_t qflag; + mp_size_t xtra; + if (msize <= rsize) + { + /* Allocate extra limb for current divrem sematics. */ + mp_ptr tmp = (mp_ptr) TMP_ALLOC ((rsize + 1) * BYTES_PER_MP_LIMB); + MPN_ZERO (tmp, rsize - msize); + MPN_COPY (tmp + rsize - msize, mp, msize); + mp = tmp; + xxx += rsize - msize; + msize = rsize; + } + count_leading_zeros (cnt, rp[rsize - 1]); + if (cnt != 0) + { + mpn_lshift (rp, rp, rsize, cnt); + cy = mpn_lshift (mp, mp, msize, cnt); + if (cy) + mp[msize++] = cy; + } + qp = (mp_ptr) TMP_ALLOC ((prec + 1) * BYTES_PER_MP_LIMB); + xtra = prec - (msize - rsize); + qflag = mpn_divrem (qp, xtra, mp, msize, rp, rsize); + qp[prec] = qflag; + tp = qp; + rsize = prec + qflag; + exp_in_limbs = rsize - xtra - xxx; + } + else + { + tp = (mp_ptr) TMP_ALLOC ((rsize + msize) * BYTES_PER_MP_LIMB); + if (rsize > msize) + mpn_mul (tp, rp, rsize, mp, msize); + else + mpn_mul (tp, mp, msize, rp, rsize); + rsize += msize; + rsize -= tp[rsize - 1] == 0; + exp_in_limbs = rsize + xxx; + + if (rsize > prec) + { + xxx = rsize - prec; + tp += rsize - prec; + rsize = prec; + exp_in_limbs += 0; + } + } + + MPN_COPY (x->_mp_d, tp, rsize); + x->_mp_size = negative ? -rsize : rsize; + x->_mp_exp = exp_in_limbs; + TMP_FREE (marker); + return 0; + } +} diff --git a/contrib/libgmp/mpf/set_ui.c b/contrib/libgmp/mpf/set_ui.c new file mode 100644 index 0000000..ead0498 --- /dev/null +++ b/contrib/libgmp/mpf/set_ui.c @@ -0,0 +1,45 @@ +/* mpf_set_ui() -- Assign a float from an unsigned int. + +Copyright (C) 1993, 1994, 1995 Free Software Foundation, Inc. + +This file is part of the GNU MP Library. + +The GNU MP Library is free software; you can redistribute it and/or modify +it under the terms of the GNU Library General Public License as published by +the Free Software Foundation; either version 2 of the License, or (at your +option) any later version. + +The GNU MP Library is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public +License for more details. + +You should have received a copy of the GNU Library General Public License +along with the GNU MP Library; see the file COPYING.LIB. If not, write to +the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, +MA 02111-1307, USA. */ + +#include "gmp.h" +#include "gmp-impl.h" + +void +#if __STDC__ +mpf_set_ui (mpf_ptr x, unsigned long int val) +#else +mpf_set_ui (x, val) + mpf_ptr x; + unsigned long int val; +#endif +{ + if (val != 0) + { + x->_mp_d[0] = val; + x->_mp_size = 1; + x->_mp_exp = 1; + } + else + { + x->_mp_size = 0; + x->_mp_exp = 0; + } +} diff --git a/contrib/libgmp/mpf/set_z.c b/contrib/libgmp/mpf/set_z.c new file mode 100644 index 0000000..4fff86e --- /dev/null +++ b/contrib/libgmp/mpf/set_z.c @@ -0,0 +1,54 @@ +/* mpf_set_z -- Assign a float from an integer. + +Copyright (C) 1996 Free Software Foundation, Inc. + +This file is part of the GNU MP Library. + +The GNU MP Library is free software; you can redistribute it and/or modify +it under the terms of the GNU Library General Public License as published by +the Free Software Foundation; either version 2 of the License, or (at your +option) any later version. + +The GNU MP Library is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public +License for more details. + +You should have received a copy of the GNU Library General Public License +along with the GNU MP Library; see the file COPYING.LIB. If not, write to +the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, +MA 02111-1307, USA. */ + +#include "gmp.h" +#include "gmp-impl.h" + +void +#if __STDC__ +mpf_set_z (mpf_ptr r, mpz_srcptr u) +#else +mpf_set_z (r, u) + mpf_ptr r; + mpz_srcptr u; +#endif +{ + mp_ptr rp, up; + mp_size_t size, asize; + mp_size_t prec; + + prec = PREC (r) + 1; + size = SIZ (u); + asize = ABS (size); + rp = PTR (r); + up = PTR (u); + + EXP (r) = asize; + + if (asize > prec) + { + up += asize - prec; + asize = prec; + } + + MPN_COPY (rp, up, asize); + SIZ (r) = size >= 0 ? asize : -asize; +} diff --git a/contrib/libgmp/mpf/size.c b/contrib/libgmp/mpf/size.c new file mode 100644 index 0000000..23a57ec --- /dev/null +++ b/contrib/libgmp/mpf/size.c @@ -0,0 +1,35 @@ +/* mpf_size(x) -- return the number of limbs currently used by the + value of the float X. + +Copyright (C) 1993, 1994, 1995 Free Software Foundation, Inc. + +This file is part of the GNU MP Library. + +The GNU MP Library is free software; you can redistribute it and/or modify +it under the terms of the GNU Library General Public License as published by +the Free Software Foundation; either version 2 of the License, or (at your +option) any later version. + +The GNU MP Library is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public +License for more details. + +You should have received a copy of the GNU Library General Public License +along with the GNU MP Library; see the file COPYING.LIB. If not, write to +the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, +MA 02111-1307, USA. */ + +#include "gmp.h" +#include "gmp-impl.h" + +size_t +#if __STDC__ +mpf_size (mpf_srcptr x) +#else +mpf_size (x) + mpf_srcptr x; +#endif +{ + return ABS (x->_mp_size); +} diff --git a/contrib/libgmp/mpf/sqrt.c b/contrib/libgmp/mpf/sqrt.c new file mode 100644 index 0000000..6d115e4 --- /dev/null +++ b/contrib/libgmp/mpf/sqrt.c @@ -0,0 +1,75 @@ +/* mpf_sqrt -- Compute the square root of a float. + +Copyright (C) 1993, 1994, 1996 Free Software Foundation, Inc. + +This file is part of the GNU MP Library. + +The GNU MP Library is free software; you can redistribute it and/or modify +it under the terms of the GNU Library General Public License as published by +the Free Software Foundation; either version 2 of the License, or (at your +option) any later version. + +The GNU MP Library is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public +License for more details. + +You should have received a copy of the GNU Library General Public License +along with the GNU MP Library; see the file COPYING.LIB. If not, write to +the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, +MA 02111-1307, USA. */ + +#include "gmp.h" +#include "gmp-impl.h" + +void +#if __STDC__ +mpf_sqrt (mpf_ptr r, mpf_srcptr u) +#else +mpf_sqrt (r, u) + mpf_ptr r; + mpf_srcptr u; +#endif +{ + mp_size_t usize; + mp_ptr up, tp; + mp_size_t prec; + mp_exp_t tsize, rexp; + TMP_DECL (marker); + + usize = u->_mp_size; + if (usize <= 0) + { + usize = 1 - 1 / (usize == 0); /* Divide by zero for negative OP. */ + r->_mp_size = usize; /* cheat flow by using usize here */ + r->_mp_exp = 0; + return; + } + + TMP_MARK (marker); + + prec = r->_mp_prec; + rexp = (u->_mp_exp + 1) >> 1; /* round towards -inf */ + tsize = 2 * prec + (u->_mp_exp & 1); + + up = u->_mp_d; + tp = (mp_ptr) TMP_ALLOC (tsize * BYTES_PER_MP_LIMB); + + if (usize > tsize) + { + up += usize - tsize; + usize = tsize; + MPN_COPY (tp, up, tsize); + } + else + { + MPN_ZERO (tp, tsize - usize); + MPN_COPY (tp + (tsize - usize), up, usize); + } + + mpn_sqrtrem (r->_mp_d, NULL, tp, tsize); + + r->_mp_size = (tsize + 1) / 2; + r->_mp_exp = rexp; + TMP_FREE (marker); +} diff --git a/contrib/libgmp/mpf/sqrt_ui.c b/contrib/libgmp/mpf/sqrt_ui.c new file mode 100644 index 0000000..421aa021 --- /dev/null +++ b/contrib/libgmp/mpf/sqrt_ui.c @@ -0,0 +1,61 @@ +/* mpf_sqrt_ui -- Compute the square root of an unsigned integer. + +Copyright (C) 1993, 1994, 1996 Free Software Foundation, Inc. + +This file is part of the GNU MP Library. + +The GNU MP Library is free software; you can redistribute it and/or modify +it under the terms of the GNU Library General Public License as published by +the Free Software Foundation; either version 2 of the License, or (at your +option) any later version. + +The GNU MP Library is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public +License for more details. + +You should have received a copy of the GNU Library General Public License +along with the GNU MP Library; see the file COPYING.LIB. If not, write to +the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, +MA 02111-1307, USA. */ + +#include "gmp.h" +#include "gmp-impl.h" + +void +#if __STDC__ +mpf_sqrt_ui (mpf_ptr r, unsigned long int u) +#else +mpf_sqrt_ui (r, u) + mpf_ptr r; + unsigned long int u; +#endif +{ + mp_size_t rsize; + mp_ptr tp; + mp_size_t prec; + TMP_DECL (marker); + + if (u == 0) + { + r->_mp_size = 0; + r->_mp_exp = 0; + return; + } + + TMP_MARK (marker); + + prec = r->_mp_prec; + rsize = 2 * prec + 1; + + tp = (mp_ptr) TMP_ALLOC (rsize * BYTES_PER_MP_LIMB); + + MPN_ZERO (tp, rsize - 1); + tp[rsize - 1] = u; + + mpn_sqrtrem (r->_mp_d, NULL, tp, rsize); + + r->_mp_size = prec + 1; + r->_mp_exp = 1; + TMP_FREE (marker); +} diff --git a/contrib/libgmp/mpf/sub.c b/contrib/libgmp/mpf/sub.c new file mode 100644 index 0000000..b871982 --- /dev/null +++ b/contrib/libgmp/mpf/sub.c @@ -0,0 +1,402 @@ +/* mpf_sub -- Subtract two floats. + +Copyright (C) 1993, 1994, 1995, 1996 Free Software Foundation, Inc. + +This file is part of the GNU MP Library. + +The GNU MP Library is free software; you can redistribute it and/or modify +it under the terms of the GNU Library General Public License as published by +the Free Software Foundation; either version 2 of the License, or (at your +option) any later version. + +The GNU MP Library is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public +License for more details. + +You should have received a copy of the GNU Library General Public License +along with the GNU MP Library; see the file COPYING.LIB. If not, write to +the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, +MA 02111-1307, USA. */ + +#include "gmp.h" +#include "gmp-impl.h" + +void +#if __STDC__ +mpf_sub (mpf_ptr r, mpf_srcptr u, mpf_srcptr v) +#else +mpf_sub (r, u, v) + mpf_ptr r; + mpf_srcptr u; + mpf_srcptr v; +#endif +{ + mp_srcptr up, vp; + mp_ptr rp, tp; + mp_size_t usize, vsize, rsize; + mp_size_t prec; + mp_exp_t exp; + mp_size_t ediff; + int negate; + TMP_DECL (marker); + + usize = u->_mp_size; + vsize = v->_mp_size; + + /* Handle special cases that don't work in generic code below. */ + if (usize == 0) + { + mpf_neg (r, v); + return; + } + if (vsize == 0) + { + mpf_set (r, u); + return; + } + + /* If signs of U and V are different, perform addition. */ + if ((usize ^ vsize) < 0) + { + __mpf_struct v_negated; + v_negated._mp_size = -vsize; + v_negated._mp_exp = v->_mp_exp; + v_negated._mp_d = v->_mp_d; + mpf_add (r, u, &v_negated); + return; + } + + TMP_MARK (marker); + + /* Signs are now known to be the same. */ + negate = usize < 0; + + /* Make U be the operand with the largest exponent. */ + if (u->_mp_exp < v->_mp_exp) + { + mpf_srcptr t; + t = u; u = v; v = t; + negate ^= 1; + usize = u->_mp_size; + vsize = v->_mp_size; + } + + usize = ABS (usize); + vsize = ABS (vsize); + up = u->_mp_d; + vp = v->_mp_d; + rp = r->_mp_d; + prec = r->_mp_prec + 1; + exp = u->_mp_exp; + ediff = u->_mp_exp - v->_mp_exp; + + /* If ediff is 0 or 1, we might have a situation where the operands are + extremely close. We need to scan the operands from the most significant + end ignore the initial parts that are equal. */ + if (ediff <= 1) + { + if (ediff == 0) + { + /* Skip leading limbs in U and V that are equal. */ + if (up[usize - 1] == vp[vsize - 1]) + { + /* This loop normally exits immediately. Optimize for that. */ + do + { + usize--; + vsize--; + exp--; + + if (usize == 0) + { + rsize = vsize; + tp = (mp_ptr) vp; + negate ^= 1; + goto normalize; + } + if (vsize == 0) + { + rsize = usize; + tp = (mp_ptr) up; + goto normalize; + } + } + while (up[usize - 1] == vp[vsize - 1]); + } + + if (up[usize - 1] < vp[vsize - 1]) + { + /* For simplicity, swap U and V. Note that since the loop above + wouldn't have exited unless up[usize - 1] and vp[vsize - 1] + were non-equal, this if-statement catches all cases where U + is smaller than V. */ + { mp_srcptr tp = up; up = vp; vp = tp; } + { mp_size_t tsize = usize; usize = vsize; vsize = tsize; } + negate ^= 1; + /* negating ediff not necessary since it is 0. */ + } + + /* Check for + x+1 00000000 ... + x ffffffff ... */ + if (up[usize - 1] != vp[vsize - 1] + 1) + goto general_case; + usize--; + vsize--; + exp--; + } + else /* ediff == 1 */ + { + /* Check for + 1 00000000 ... + 0 ffffffff ... */ + + if (up[usize - 1] != 1 || vp[vsize - 1] != ~(mp_limb_t) 0 + || (usize >= 2 && up[usize - 2] != 0)) + goto general_case; + + usize--; + exp--; + } + + /* Skip sequences of 00000000/ffffffff */ + while (vsize != 0 && usize != 0 && up[usize - 1] == 0 + && vp[vsize - 1] == ~(mp_limb_t) 0) + { + usize--; + vsize--; + exp--; + } + + if (usize == 0) + { + while (vsize != 0 && vp[vsize - 1] == ~(mp_limb_t) 0) + { + vsize--; + exp--; + } + } + + if (usize > prec - 1) + { + up += usize - (prec - 1); + usize = prec - 1; + } + if (vsize > prec - 1) + { + vp += vsize - (prec - 1); + vsize = prec - 1; + } + + tp = (mp_ptr) TMP_ALLOC (prec * BYTES_PER_MP_LIMB); + { + mp_limb_t cy_limb; + if (vsize == 0) + { + mp_size_t size, i; + size = usize; + for (i = 0; i < size; i++) + tp[i] = up[i]; + tp[size] = 1; + rsize = size + 1; + exp++; + goto normalize; + } + if (usize == 0) + { + mp_size_t size, i; + size = vsize; + for (i = 0; i < size; i++) + tp[i] = ~vp[i]; + cy_limb = 1 - mpn_add_1 (tp, tp, vsize, (mp_limb_t) 1); + rsize = vsize; + if (cy_limb == 0) + { + tp[rsize] = 1; + rsize++; + exp++; + } + goto normalize; + } + if (usize >= vsize) + { + /* uuuu */ + /* vv */ + mp_size_t size; + size = usize - vsize; + MPN_COPY (tp, up, size); + cy_limb = mpn_sub_n (tp + size, up + size, vp, vsize); + rsize = usize; + } + else /* (usize < vsize) */ + { + /* uuuu */ + /* vvvvvvv */ + mp_size_t size, i; + size = vsize - usize; + for (i = 0; i < size; i++) + tp[i] = ~vp[i]; + cy_limb = mpn_sub_n (tp + size, up, vp + size, usize); + cy_limb+= mpn_sub_1 (tp + size, tp + size, usize, (mp_limb_t) 1); + cy_limb-= mpn_add_1 (tp, tp, vsize, (mp_limb_t) 1); + rsize = vsize; + } + if (cy_limb == 0) + { + tp[rsize] = 1; + rsize++; + exp++; + } + goto normalize; + } + } + +general_case: + /* If U extends beyond PREC, ignore the part that does. */ + if (usize > prec) + { + up += usize - prec; + usize = prec; + } + + /* If V extends beyond PREC, ignore the part that does. + Note that this may make vsize negative. */ + if (vsize + ediff > prec) + { + vp += vsize + ediff - prec; + vsize = prec - ediff; + } + + /* Allocate temp space for the result. Allocate + just vsize + ediff later??? */ + tp = (mp_ptr) TMP_ALLOC (prec * BYTES_PER_MP_LIMB); + + if (ediff >= prec) + { + /* V completely cancelled. */ + if (tp != up) + MPN_COPY (rp, up, usize); + rsize = usize; + } + else + { + /* Locate the least significant non-zero limb in (the needed + parts of) U and V, to simplify the code below. */ + for (;;) + { + if (vsize == 0) + { + MPN_COPY (rp, up, usize); + rsize = usize; + goto done; + } + if (vp[0] != 0) + break; + vp++, vsize--; + } + for (;;) + { + if (usize == 0) + { + MPN_COPY (rp, vp, vsize); + rsize = vsize; + negate ^= 1; + goto done; + } + if (up[0] != 0) + break; + up++, usize--; + } + + /* uuuu | uuuu | uuuu | uuuu | uuuu */ + /* vvvvvvv | vv | vvvvv | v | vv */ + + if (usize > ediff) + { + /* U and V partially overlaps. */ + if (ediff == 0) + { + /* Have to compare the leading limbs of u and v + to determine whether to compute u - v or v - u. */ + if (usize >= vsize) + { + /* uuuu */ + /* vv */ + mp_size_t size; + size = usize - vsize; + MPN_COPY (tp, up, size); + mpn_sub_n (tp + size, up + size, vp, vsize); + rsize = usize; + } + else /* (usize < vsize) */ + { + /* uuuu */ + /* vvvvvvv */ + mp_size_t size, i; + size = vsize - usize; + tp[0] = -vp[0]; + for (i = 1; i < size; i++) + tp[i] = ~vp[i]; + mpn_sub_n (tp + size, up, vp + size, usize); + mpn_sub_1 (tp + size, tp + size, usize, (mp_limb_t) 1); + rsize = vsize; + } + } + else + { + if (vsize + ediff <= usize) + { + /* uuuu */ + /* v */ + mp_size_t size; + size = usize - ediff - vsize; + MPN_COPY (tp, up, size); + mpn_sub (tp + size, up + size, usize - size, vp, vsize); + rsize = usize; + } + else + { + /* uuuu */ + /* vvvvv */ + mp_size_t size, i; + size = vsize + ediff - usize; + tp[0] = -vp[0]; + for (i = 1; i < size; i++) + tp[i] = ~vp[i]; + mpn_sub (tp + size, up, usize, vp + size, usize - ediff); + mpn_sub_1 (tp + size, tp + size, usize, (mp_limb_t) 1); + rsize = vsize + ediff; + } + } + } + else + { + /* uuuu */ + /* vv */ + mp_size_t size, i; + size = vsize + ediff - usize; + tp[0] = -vp[0]; + for (i = 1; i < vsize; i++) + tp[i] = ~vp[i]; + for (i = vsize; i < size; i++) + tp[i] = ~(mp_limb_t) 0; + mpn_sub_1 (tp + size, up, usize, (mp_limb_t) 1); + rsize = size + usize; + } + + normalize: + /* Full normalize. Optimize later. */ + while (rsize != 0 && tp[rsize - 1] == 0) + { + rsize--; + exp--; + } + MPN_COPY (rp, tp, rsize); + } + + done: + r->_mp_size = negate ? -rsize : rsize; + r->_mp_exp = exp; + TMP_FREE (marker); +} diff --git a/contrib/libgmp/mpf/sub_ui.c b/contrib/libgmp/mpf/sub_ui.c new file mode 100644 index 0000000..7806213 --- /dev/null +++ b/contrib/libgmp/mpf/sub_ui.c @@ -0,0 +1,49 @@ +/* mpf_sub_ui -- Subtract an unsigned integer from a float. + +Copyright (C) 1993, 1994, 1996 Free Software Foundation, Inc. + +This file is part of the GNU MP Library. + +The GNU MP Library is free software; you can redistribute it and/or modify +it under the terms of the GNU Library General Public License as published by +the Free Software Foundation; either version 2 of the License, or (at your +option) any later version. + +The GNU MP Library is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public +License for more details. + +You should have received a copy of the GNU Library General Public License +along with the GNU MP Library; see the file COPYING.LIB. If not, write to +the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, +MA 02111-1307, USA. */ + +#include "gmp.h" +#include "gmp-impl.h" + +void +#if __STDC__ +mpf_sub_ui (mpf_ptr sum, mpf_srcptr u, unsigned long int v) +#else +mpf_sub_ui (sum, u, v) + mpf_ptr sum; + mpf_srcptr u; + unsigned long int v; +#endif +{ + __mpf_struct vv; + mp_limb_t vl; + + if (v == 0) + { + mpf_set (sum, u); + return; + } + + vl = v; + vv._mp_size = 1; + vv._mp_d = &vl; + vv._mp_exp = 1; + mpf_sub (sum, u, &vv); +} diff --git a/contrib/libgmp/mpf/tests/Makefile.in b/contrib/libgmp/mpf/tests/Makefile.in new file mode 100644 index 0000000..e108b9e --- /dev/null +++ b/contrib/libgmp/mpf/tests/Makefile.in @@ -0,0 +1,75 @@ +# Makefile for mpf/tests for GNU MP + +srcdir = . + +CC = gcc + +TEST_LIBS = ../../libgmp.a +INCLUDES = -I../../mpn -I$(srcdir)/../.. +CFLAGS = -g -O + +.c.o: + $(CC) -c $(INCLUDES) $(CFLAGS) $(XCFLAGS) $< + +TEST_SRCS = t-add.c t-sub.c t-conv.c t-sqrt.c t-muldiv.c t-dm2exp.c t-reuse.c ref.c +TEST_OBJS = t-add.o t-sub.o t-conv.o t-sqrt.o t-muldiv.o t-dm2exp.c reuse.o +TESTS = t-add t-sub t-conv t-sqrt t-muldiv t-dm2exp reuse + +check: Makefile st-add st-sub st-conv st-sqrt st-muldiv st-dm2exp st-reuse + @echo "The tests passed." + +st-add: t-add + ./t-add + touch $@ +st-sub: t-sub + ./t-sub + touch $@ +st-conv: t-conv + ./t-conv + touch $@ +st-sqrt: t-sqrt + ./t-sqrt + touch $@ +st-muldiv: t-muldiv + ./t-muldiv + touch $@ +st-dm2exp: t-dm2exp + ./t-dm2exp + touch $@ +st-reuse: reuse + ./reuse + touch $@ + +H = $(srcdir)/../../gmp.h $(srcdir)/../../gmp-impl.h \ + $(srcdir)/../../urandom.h ../../mpn/gmp-mparam.h + +t-add: t-add.o ref.o $(TEST_LIBS) + $(CC) -o $@ $@.o ref.o $(TEST_LIBS) $(CFLAGS) +t-sub: t-sub.o ref.o $(TEST_LIBS) + $(CC) -o $@ $@.o ref.o $(TEST_LIBS) $(CFLAGS) +t-conv: t-conv.o $(TEST_LIBS) + $(CC) -o $@ $@.o $(TEST_LIBS) $(CFLAGS) +t-sqrt: t-sqrt.o $(TEST_LIBS) + $(CC) -o $@ $@.o $(TEST_LIBS) $(CFLAGS) +t-muldiv: t-muldiv.o $(TEST_LIBS) + $(CC) -o $@ $@.o $(TEST_LIBS) $(CFLAGS) +t-dm2exp: t-dm2exp.o $(TEST_LIBS) + $(CC) -o $@ $@.o $(TEST_LIBS) $(CFLAGS) +reuse: reuse.o $(TEST_LIBS) + $(CC) -o $@ $@.o $(TEST_LIBS) $(CFLAGS) + +t-add.o: $(srcdir)/t-add.c +t-sub.o: $(srcdir)/t-sub.c +t-conv.o: $(srcdir)/t-conv.c +t-sqrt.o: $(srcdir)/t-sqrt.c +t-muldiv.o: $(srcdir)/t-muldiv.c +t-dm2exp.o: $(srcdir)/t-dm2exp.c +reuse.o: $(srcdir)/reuse.c + +clean mostlyclean: + rm -f *.o st-* $(TESTS) +distclean maintainer-clean: clean + rm -f Makefile config.status + +Makefile: $(srcdir)/Makefile.in + $(SHELL) ./config.status diff --git a/contrib/libgmp/mpf/tests/configure.in b/contrib/libgmp/mpf/tests/configure.in new file mode 100644 index 0000000..319219c --- /dev/null +++ b/contrib/libgmp/mpf/tests/configure.in @@ -0,0 +1,11 @@ +# This file is a shell script that supplies the information necessary +# to tailor a template configure script into the configure script +# appropriate for this directory. For more information, check any +# existing configure script. + +srctrigger=t-add.c +srcname="gmp/mpf/tests" + +# per-host: + +# per-target: diff --git a/contrib/libgmp/mpf/tests/ref.c b/contrib/libgmp/mpf/tests/ref.c new file mode 100644 index 0000000..b2c3e6c --- /dev/null +++ b/contrib/libgmp/mpf/tests/ref.c @@ -0,0 +1,203 @@ +/* Reference floating point routines. + +Copyright (C) 1996 Free Software Foundation, Inc. + +This file is part of the GNU MP Library. + +The GNU MP Library is free software; you can redistribute it and/or modify +it under the terms of the GNU Library General Public License as published by +the Free Software Foundation; either version 2 of the License, or (at your +option) any later version. + +The GNU MP Library is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public +License for more details. + +You should have received a copy of the GNU Library General Public License +along with the GNU MP Library; see the file COPYING.LIB. If not, write to +the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, +MA 02111-1307, USA. */ + +#include "gmp.h" +#include "gmp-impl.h" + +#if __STDC__ +void ref_mpf_add (mpf_t, const mpf_t, const mpf_t); +void ref_mpf_sub (mpf_t, const mpf_t, const mpf_t); +#else +void ref_mpf_add (); +void ref_mpf_sub (); +#endif + +void +#if __STDC__ +ref_mpf_add (mpf_t w, const mpf_t u, const mpf_t v) +#else +ref_mpf_add (w, u, v) + mpf_t w; + const mpf_t u; + const mpf_t v; +#endif +{ + mp_size_t hi, lo, size; + mp_ptr ut, vt, wt; + int neg; + mp_exp_t exp; + mp_limb_t cy; + TMP_DECL (mark); + + TMP_MARK (mark); + + if (SIZ (u) == 0) + { + size = ABSIZ (v); + wt = (mp_ptr) TMP_ALLOC (size * BYTES_PER_MP_LIMB); + MPN_COPY (wt, PTR (v), size); + exp = EXP (v); + neg = SIZ (v) < 0; + goto done; + } + if (SIZ (v) == 0) + { + size = ABSIZ (u); + wt = (mp_ptr) TMP_ALLOC (size * BYTES_PER_MP_LIMB); + MPN_COPY (wt, PTR (u), size); + exp = EXP (u); + neg = SIZ (u) < 0; + goto done; + } + if ((SIZ (u) ^ SIZ (v)) < 0) + { + mpf_t tmp; + SIZ (tmp) = -SIZ (v); + EXP (tmp) = EXP (v); + PTR (tmp) = PTR (v); + ref_mpf_sub (w, u, tmp); + return; + } + neg = SIZ (u) < 0; + + /* Compute the significance of the hi and lo end of the result. */ + hi = MAX (EXP (u), EXP (v)); + lo = MIN (EXP (u) - ABSIZ (u), EXP (v) - ABSIZ (v)); + size = hi - lo; + ut = (mp_ptr) TMP_ALLOC ((size + 1) * BYTES_PER_MP_LIMB); + vt = (mp_ptr) TMP_ALLOC ((size + 1) * BYTES_PER_MP_LIMB); + wt = (mp_ptr) TMP_ALLOC ((size + 1) * BYTES_PER_MP_LIMB); + MPN_ZERO (ut, size); + MPN_ZERO (vt, size); + {int off; + off = size + (EXP (u) - hi) - ABSIZ (u); + MPN_COPY (ut + off, PTR (u), ABSIZ (u)); + off = size + (EXP (v) - hi) - ABSIZ (v); + MPN_COPY (vt + off, PTR (v), ABSIZ (v)); + } + + cy = mpn_add_n (wt, ut, vt, size); + wt[size] = cy; + size += cy; + exp = hi + cy; + +done: + if (size > PREC (w)) + { + wt += size - PREC (w); + size = PREC (w); + } + MPN_COPY (PTR (w), wt, size); + SIZ (w) = neg == 0 ? size : -size; + EXP (w) = exp; + TMP_FREE (mark); +} + +void +#if __STDC__ +ref_mpf_sub (mpf_t w, const mpf_t u, const mpf_t v) +#else +ref_mpf_sub (w, u, v) + mpf_t w; + const mpf_t u; + const mpf_t v; +#endif +{ + mp_size_t hi, lo, size; + mp_ptr ut, vt, wt; + int neg; + mp_exp_t exp; + TMP_DECL (mark); + + TMP_MARK (mark); + + if (SIZ (u) == 0) + { + size = ABSIZ (v); + wt = (mp_ptr) TMP_ALLOC (size * BYTES_PER_MP_LIMB); + MPN_COPY (wt, PTR (v), size); + exp = EXP (v); + neg = SIZ (v) > 0; + goto done; + } + if (SIZ (v) == 0) + { + size = ABSIZ (u); + wt = (mp_ptr) TMP_ALLOC (size * BYTES_PER_MP_LIMB); + MPN_COPY (wt, PTR (u), size); + exp = EXP (u); + neg = SIZ (u) < 0; + goto done; + } + if ((SIZ (u) ^ SIZ (v)) < 0) + { + mpf_t tmp; + SIZ (tmp) = -SIZ (v); + EXP (tmp) = EXP (v); + PTR (tmp) = PTR (v); + ref_mpf_add (w, u, tmp); + if (SIZ (u) < 0) + mpf_neg (w, w); + return; + } + neg = SIZ (u) < 0; + + /* Compute the significance of the hi and lo end of the result. */ + hi = MAX (EXP (u), EXP (v)); + lo = MIN (EXP (u) - ABSIZ (u), EXP (v) - ABSIZ (v)); + size = hi - lo; + ut = (mp_ptr) TMP_ALLOC ((size + 1) * BYTES_PER_MP_LIMB); + vt = (mp_ptr) TMP_ALLOC ((size + 1) * BYTES_PER_MP_LIMB); + wt = (mp_ptr) TMP_ALLOC ((size + 1) * BYTES_PER_MP_LIMB); + MPN_ZERO (ut, size); + MPN_ZERO (vt, size); + {int off; + off = size + (EXP (u) - hi) - ABSIZ (u); + MPN_COPY (ut + off, PTR (u), ABSIZ (u)); + off = size + (EXP (v) - hi) - ABSIZ (v); + MPN_COPY (vt + off, PTR (v), ABSIZ (v)); + } + + if (mpn_cmp (ut, vt, size) >= 0) + mpn_sub_n (wt, ut, vt, size); + else + { + mpn_sub_n (wt, vt, ut, size); + neg ^= 1; + } + exp = hi; + while (size != 0 && wt[size - 1] == 0) + { + size--; + exp--; + } + +done: + if (size > PREC (w)) + { + wt += size - PREC (w); + size = PREC (w); + } + MPN_COPY (PTR (w), wt, size); + SIZ (w) = neg == 0 ? size : -size; + EXP (w) = exp; + TMP_FREE (mark); +} diff --git a/contrib/libgmp/mpf/tests/reuse.c b/contrib/libgmp/mpf/tests/reuse.c new file mode 100644 index 0000000..6829cc4 --- /dev/null +++ b/contrib/libgmp/mpf/tests/reuse.c @@ -0,0 +1,186 @@ +/* Test that routines allow reusing a source variable as destination. */ + +#include <stdio.h> +#include "gmp.h" +#include "gmp-impl.h" +#include "urandom.h" + +#ifndef SIZE +#define SIZE 16 +#endif + +#ifndef EXPO +#define EXPO 32 +#endif + +#if __STDC__ +typedef void (*dss_func) (mpf_ptr, mpf_srcptr, mpf_srcptr); +#else +typedef void (*dss_func) (); +#endif + +dss_func dss_funcs[] = +{ + mpf_div, mpf_add, mpf_mul, mpf_sub, +}; + +char *dss_func_names[] = +{ + "mpf_div", "mpf_add", "mpf_mul", "mpf_sub", +}; + +#if __STDC__ +typedef void (*dsi_func) (mpf_ptr, mpf_srcptr, unsigned long int); +#else +typedef void (*dsi_func) (); +#endif + +dsi_func dsi_funcs[] = +{ + mpf_div_ui, mpf_add_ui, mpf_mul_ui, mpf_sub_ui, +}; + +char *dsi_func_names[] = +{ + "mpf_div_ui", "mpf_add_ui", "mpf_mul_ui", "mpf_sub_ui", +}; + +#if __STDC__ +typedef void (*dis_func) (mpf_ptr, unsigned long int, mpf_srcptr); +#else +typedef void (*dis_func) (); +#endif + +dis_func dis_funcs[] = +{ + mpf_ui_div, mpf_ui_sub, +}; + +char *dis_func_names[] = +{ + "mpf_ui_div", "mpf_ui_sub", +}; + +main (argc, argv) + int argc; + char **argv; +{ + int i; + int pass, reps = 100000; + mpf_t in1, in2, out1; + unsigned long int in1i, in2i; + mpf_t res1, res2, res3; + mp_size_t bprec = 100; + + if (argc > 1) + { + reps = strtol (argv[1], 0, 0); + if (argc > 2) + bprec = strtol (argv[2], 0, 0); + } + + mpf_set_default_prec (bprec); + + mpf_init (in1); + mpf_init (in2); + mpf_init (out1); + mpf_init (res1); + mpf_init (res2); + mpf_init (res3); + + for (pass = 1; pass <= reps; pass++) + { + mpf_random2 (in1, urandom () % SIZE - SIZE/2, urandom () % EXPO); + mpf_random2 (in2, urandom () % SIZE - SIZE/2, urandom () % EXPO); + + for (i = 0; i < sizeof (dss_funcs) / sizeof (dss_func); i++) + { + /* Don't divide by 0. */ + if (i == 0 && mpf_cmp_ui (in2, 0) == 0) + continue; + + (dss_funcs[i]) (res1, in1, in2); + + mpf_set (out1, in1); + (dss_funcs[i]) (out1, out1, in2); + mpf_set (res2, out1); + + mpf_set (out1, in2); + (dss_funcs[i]) (out1, in1, out1); + mpf_set (res3, out1); + + if (mpf_cmp (res1, res2) != 0) + dump_abort (dss_func_names[i], res1, res2); + if (mpf_cmp (res1, res3) != 0) + dump_abort (dss_func_names[i], res1, res3); + } + + in2i = urandom (); + for (i = 0; i < sizeof (dsi_funcs) / sizeof (dsi_func); i++) + { + /* Don't divide by 0. */ + if (i == 0 && in2i == 0) + continue; + + (dsi_funcs[i]) (res1, in1, in2i); + + mpf_set (out1, in1); + (dsi_funcs[i]) (out1, out1, in2i); + mpf_set (res2, out1); + + if (mpf_cmp (res1, res2) != 0) + dump_abort (dsi_func_names[i], res1, res2); + } + + in1i = urandom (); + for (i = 0; i < sizeof (dis_funcs) / sizeof (dis_func); i++) + { + /* Don't divide by 0. */ + if (i == 0 && mpf_cmp_ui (in2, 0) == 0) + continue; + + (dis_funcs[i]) (res1, in1i, in2); + + mpf_set (out1, in2); + (dis_funcs[i]) (out1, in1i, in2); + mpf_set (res2, out1); + + if (mpf_cmp (res1, res2) != 0) + dump_abort (dis_func_names[i], res1, res2); + } + + } + + exit (0); +} + +dump_abort (name, res1, res2) + char *name; + mpf_t res1, res2; +{ + printf ("failure in %s:", name); + oo (res1); + oo (res2); + abort (); +} + +oo (x) + mpf_t x; +{ + mp_size_t i; + printf (" exp = %ld\n", x->_mp_exp); + printf ("size = %d\n", x->_mp_size); + for (i = ABS (x->_mp_size) - 1; i >= 0; i--) + printf ("%08lX ", x->_mp_d[i]); + printf ("\n"); + mpf_dump (x); +} + +#if 0 +void mpf_div_2exp _PROTO ((mpf_ptr, mpf_srcptr, unsigned long int)); +void mpf_mul_2exp _PROTO ((mpf_ptr, mpf_srcptr, unsigned long int)); + +void mpf_abs _PROTO ((mpf_ptr, mpf_srcptr)); +void mpf_sqrt _PROTO ((mpf_ptr, mpf_srcptr)); +void mpf_neg _PROTO ((mpf_ptr, mpf_srcptr)); +#endif diff --git a/contrib/libgmp/mpf/tests/t-add.c b/contrib/libgmp/mpf/tests/t-add.c new file mode 100644 index 0000000..6f985bb --- /dev/null +++ b/contrib/libgmp/mpf/tests/t-add.c @@ -0,0 +1,117 @@ +/* Test mpf_add. + +Copyright (C) 1996 Free Software Foundation, Inc. + +This file is part of the GNU MP Library. + +The GNU MP Library is free software; you can redistribute it and/or modify +it under the terms of the GNU Library General Public License as published by +the Free Software Foundation; either version 2 of the License, or (at your +option) any later version. + +The GNU MP Library is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public +License for more details. + +You should have received a copy of the GNU Library General Public License +along with the GNU MP Library; see the file COPYING.LIB. If not, write to +the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, +MA 02111-1307, USA. */ + +#include <stdio.h> +#include "gmp.h" +#include "gmp-impl.h" +#include "urandom.h" + +#ifndef SIZE +#define SIZE 16 +#endif + +#if __STDC__ +void ref_mpf_add (mpf_t, const mpf_t, const mpf_t); +void ref_mpf_sub (mpf_t, const mpf_t, const mpf_t); +#else +void ref_mpf_add (); +void ref_mpf_sub (); +#endif + +main (argc, argv) + int argc; + char **argv; +{ + mp_size_t size; + mp_exp_t exp; + int reps = 100000; + int i; + mpf_t u, v, w, wref; + mp_size_t bprec = 100; + mpf_t rerr, max_rerr, limit_rerr; + + if (argc > 1) + { + reps = strtol (argv[1], 0, 0); + if (argc > 2) + bprec = strtol (argv[2], 0, 0); + } + + mpf_set_default_prec (bprec); + + mpf_init_set_ui (limit_rerr, 1); + mpf_div_2exp (limit_rerr, limit_rerr, bprec); +#if VERBOSE + mpf_dump (limit_rerr); +#endif + mpf_init (rerr); + mpf_init_set_ui (max_rerr, 0); + + mpf_init (u); + mpf_init (v); + mpf_init (w); + mpf_init (wref); + for (i = 0; i < reps; i++) + { + size = urandom () % (2 * SIZE) - SIZE; + exp = urandom () % SIZE; + mpf_random2 (u, size, exp); + + size = urandom () % (2 * SIZE) - SIZE; + exp = urandom () % SIZE; + mpf_random2 (v, size, exp); + + mpf_add (w, u, v); + ref_mpf_add (wref, u, v); + + mpf_reldiff (rerr, w, wref); + if (mpf_cmp (rerr, max_rerr) > 0) + { + mpf_set (max_rerr, rerr); +#if VERBOSE + mpf_dump (max_rerr); +#endif + if (mpf_cmp (rerr, limit_rerr) > 0) + { + printf ("ERROR after %d tests\n", i); + printf (" u = "); mpf_dump (u); + printf (" v = "); mpf_dump (v); + printf ("wref = "); mpf_dump (wref); + printf (" w = "); mpf_dump (w); + abort (); + } + } + } + + exit (0); +} + +oo (x) + mpf_t x; +{ + mp_size_t i; + printf (" exp = %ld\n", x->_mp_exp); + printf ("size = %d\n", x->_mp_size); + for (i = ABS (x->_mp_size) - 1; i >= 0; i--) + printf ("%08lX ", x->_mp_d[i]); + printf ("\n"); + mpf_dump (x); +} diff --git a/contrib/libgmp/mpf/tests/t-conv.c b/contrib/libgmp/mpf/tests/t-conv.c new file mode 100644 index 0000000..00d461d --- /dev/null +++ b/contrib/libgmp/mpf/tests/t-conv.c @@ -0,0 +1,120 @@ +/* Test mpf_get_str and mpf_set_str. + +Copyright (C) 1996 Free Software Foundation, Inc. + +This file is part of the GNU MP Library. + +The GNU MP Library is free software; you can redistribute it and/or modify +it under the terms of the GNU Library General Public License as published by +the Free Software Foundation; either version 2 of the License, or (at your +option) any later version. + +The GNU MP Library is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public +License for more details. + +You should have received a copy of the GNU Library General Public License +along with the GNU MP Library; see the file COPYING.LIB. If not, write to +the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, +MA 02111-1307, USA. */ + +#include <stdio.h> +#include "gmp.h" +#include "gmp-impl.h" +#include "urandom.h" + +#ifndef SIZE +#define SIZE 10 +#endif + +#ifndef EXPO +#define EXPO 20 +#endif + +main (argc, argv) + int argc; + char **argv; +{ + mpf_t x, y; + int reps = 20000; + int i; + mp_size_t bprec = 100; + mpf_t d, rerr, max_rerr, limit_rerr; + char *str; + long bexp; + long size, exp; + int base; + char buf[SIZE * BITS_PER_MP_LIMB + 5]; + + if (argc > 1) + { + reps = strtol (argv[1], 0, 0); + if (argc > 2) + bprec = strtol (argv[2], 0, 0); + } + + mpf_set_default_prec (bprec); + + mpf_init_set_ui (limit_rerr, 1); + mpf_div_2exp (limit_rerr, limit_rerr, bprec); +#if VERBOSE + mpf_dump (limit_rerr); +#endif + mpf_init (rerr); + mpf_init_set_ui (max_rerr, 0); + + mpf_init (x); + mpf_init (y); + mpf_init (d); + + for (i = 0; i < reps; i++) + { + size = urandom () % (2 * SIZE) - SIZE; + exp = urandom () % EXPO; + mpf_random2 (x, size, exp); + + base = urandom () % 35 + 2; + + str = mpf_get_str (0, &bexp, base, 0, x); + + if (str[0] == '-') + sprintf (buf, "-0.%s@%ld", str + 1, bexp); + else + sprintf (buf, "0.%s@%ld", str, bexp); + + mpf_set_str (y, buf, -base); + free (str); + + mpf_reldiff (rerr, x, y); + if (mpf_cmp (rerr, max_rerr) > 0) + { + mpf_set (max_rerr, rerr); +#if VERBOSE + mpf_dump (max_rerr); +#endif + if (mpf_cmp (rerr, limit_rerr) > 0) + { + printf ("ERROR after %d tests\n", i); + printf ("base = %d\n", base); + printf (" x = "); mpf_dump (x); + printf (" y = "); mpf_dump (y); + abort (); + } + } + } + + exit (0); +} + +oo (x) + mpf_t x; +{ + int i; + printf (" exp = %ld\n", x->_mp_exp); + printf ("size = %d\n", x->_mp_size); + for (i = ABS (x->_mp_size) - 1; i >= 0; i--) + printf ("%08lX ", x->_mp_d[i]); + printf ("\n"); + mpf_dump (x); +} diff --git a/contrib/libgmp/mpf/tests/t-dm2exp.c b/contrib/libgmp/mpf/tests/t-dm2exp.c new file mode 100644 index 0000000..a8c4e8f --- /dev/null +++ b/contrib/libgmp/mpf/tests/t-dm2exp.c @@ -0,0 +1,101 @@ +/* Test mpf_div, mpf_div_2exp, mpf_mul_2exp. + +Copyright (C) 1996 Free Software Foundation, Inc. + +This file is part of the GNU MP Library. + +The GNU MP Library is free software; you can redistribute it and/or modify +it under the terms of the GNU Library General Public License as published by +the Free Software Foundation; either version 2 of the License, or (at your +option) any later version. + +The GNU MP Library is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public +License for more details. + +You should have received a copy of the GNU Library General Public License +along with the GNU MP Library; see the file COPYING.LIB. If not, write to +the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, +MA 02111-1307, USA. */ + +#include <stdio.h> +#include "gmp.h" +#include "gmp-impl.h" +#include "urandom.h" + +#ifndef SIZE +#define SIZE 16 +#endif + +main (argc, argv) + int argc; + char **argv; +{ + int reps = 500000; + int i; + mpf_t u, v, w1, w2; + mp_size_t bprec = 100; + mpf_t rerr, limit_rerr; + + if (argc > 1) + { + reps = strtol (argv[1], 0, 0); + if (argc > 2) + bprec = strtol (argv[2], 0, 0); + } + + mpf_set_default_prec (bprec); + + mpf_init (rerr); + mpf_init (limit_rerr); + + mpf_init (u); + mpf_init (v); + mpf_init (w1); + mpf_init (w2); + + for (i = 0; i < reps; i++) + { + mp_size_t res_prec; + unsigned long int pow2; + + res_prec = urandom () % (bprec + 100); + mpf_set_prec (w1, res_prec); + mpf_set_prec (w2, res_prec); + + mpf_set_ui (limit_rerr, 1); + mpf_div_2exp (limit_rerr, limit_rerr, res_prec); + + pow2 = urandom () % 0x10000; + mpf_set_ui (v, 1); + mpf_mul_2exp (v, v, pow2); + + mpf_div_2exp (w1, u, pow2); + mpf_div (w2, u, v); + mpf_reldiff (rerr, w1, w2); + if (mpf_cmp (rerr, limit_rerr) > 0) + { + printf ("ERROR in mpf_div or mpf_div_2exp after %d tests\n", i); + printf (" u = "); mpf_dump (u); + printf (" v = "); mpf_dump (v); + printf (" w1 = "); mpf_dump (w1); + printf (" w2 = "); mpf_dump (w2); + abort (); + } + } + + exit (0); +} + +oo (x) + mpf_t x; +{ + mp_size_t i; + printf (" exp = %ld\n", x->_mp_exp); + printf ("size = %d\n", x->_mp_size); + for (i = ABS (x->_mp_size) - 1; i >= 0; i--) + printf ("%08lX ", x->_mp_d[i]); + printf ("\n"); + mpf_dump (x); +} diff --git a/contrib/libgmp/mpf/tests/t-muldiv.c b/contrib/libgmp/mpf/tests/t-muldiv.c new file mode 100644 index 0000000..d1721e8 --- /dev/null +++ b/contrib/libgmp/mpf/tests/t-muldiv.c @@ -0,0 +1,161 @@ +/* Test mpf_mul, mpf_div, mpf_ui_div, and mpf_div_ui. + +Copyright (C) 1996 Free Software Foundation, Inc. + +This file is part of the GNU MP Library. + +The GNU MP Library is free software; you can redistribute it and/or modify +it under the terms of the GNU Library General Public License as published by +the Free Software Foundation; either version 2 of the License, or (at your +option) any later version. + +The GNU MP Library is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public +License for more details. + +You should have received a copy of the GNU Library General Public License +along with the GNU MP Library; see the file COPYING.LIB. If not, write to +the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, +MA 02111-1307, USA. */ + +#include <stdio.h> +#include "gmp.h" +#include "gmp-impl.h" +#include "urandom.h" + +#ifndef SIZE +#define SIZE 16 +#endif + +main (argc, argv) + int argc; + char **argv; +{ + mp_size_t size; + mp_exp_t exp; + int reps = 100000; + int i; + mpf_t u, v, w, x; + mp_size_t bprec = 100; + mpf_t rerr, limit_rerr; + mp_limb_t ulimb, vlimb; + int single_flag; + + if (argc > 1) + { + reps = strtol (argv[1], 0, 0); + if (argc > 2) + bprec = strtol (argv[2], 0, 0); + } + + mpf_set_default_prec (bprec); + + mpf_init (rerr); + mpf_init (limit_rerr); + + mpf_init (u); + mpf_init (v); + mpf_init (w); + mpf_init (x); + + for (i = 0; i < reps; i++) + { + mp_size_t res_prec; + + res_prec = urandom () % (bprec + 100); + mpf_set_prec (w, res_prec); + mpf_set_prec (x, res_prec); + + mpf_set_ui (limit_rerr, 1); + mpf_div_2exp (limit_rerr, limit_rerr, res_prec); + + single_flag = 0; + + if ((urandom () & 1) != 0) + { + size = urandom () % (2 * SIZE) - SIZE; + exp = urandom () % SIZE; + mpf_random2 (u, size, exp); + } + else + { + ulimb = urandom (); + mpf_set_ui (u, ulimb); + single_flag = 1; + } + + if ((urandom () & 1) != 0) + { + size = urandom () % (2 * SIZE) - SIZE; + exp = urandom () % SIZE; + mpf_random2 (v, size, exp); + } + else + { + vlimb = urandom (); + mpf_set_ui (v, vlimb); + single_flag = 2; + } + + if (mpf_sgn (v) == 0) + continue; + + mpf_div (w, u, v); + mpf_mul (x, w, v); + mpf_reldiff (rerr, u, x); + if (mpf_cmp (rerr, limit_rerr) > 0) + { + printf ("ERROR in mpf_mul or mpf_div after %d tests\n", i); + printf (" u = "); mpf_dump (u); + printf (" v = "); mpf_dump (v); + printf (" x = "); mpf_dump (x); + printf (" w = "); mpf_dump (w); + abort (); + } + + if (single_flag == 2) + { + mpf_div_ui (x, u, vlimb); + mpf_reldiff (rerr, w, x); + if (mpf_cmp (rerr, limit_rerr) > 0) + { + printf ("ERROR in mpf_div or mpf_div_ui after %d tests\n", i); + printf (" u = "); mpf_dump (u); + printf (" v = "); mpf_dump (v); + printf (" x = "); mpf_dump (x); + printf (" w = "); mpf_dump (w); + abort (); + } + } + + if (single_flag == 1) + { + mpf_ui_div (x, ulimb, v); + mpf_reldiff (rerr, w, x); + if (mpf_cmp (rerr, limit_rerr) > 0) + { + printf ("ERROR in mpf_div or mpf_ui_div after %d tests\n", i); + printf (" u = "); mpf_dump (u); + printf (" v = "); mpf_dump (v); + printf (" x = "); mpf_dump (x); + printf (" w = "); mpf_dump (w); + abort (); + } + } + } + + exit (0); +} + +oo (x) + mpf_t x; +{ + mp_size_t i; + printf (" exp = %ld\n", x->_mp_exp); + printf ("size = %d\n", x->_mp_size); + for (i = ABS (x->_mp_size) - 1; i >= 0; i--) + printf ("%08lX ", x->_mp_d[i]); + printf ("\n"); + mpf_dump (x); +} diff --git a/contrib/libgmp/mpf/tests/t-sqrt.c b/contrib/libgmp/mpf/tests/t-sqrt.c new file mode 100644 index 0000000..5c72ab5 --- /dev/null +++ b/contrib/libgmp/mpf/tests/t-sqrt.c @@ -0,0 +1,103 @@ +/* Test mpf_sqrt, mpf_mul. + +Copyright (C) 1996 Free Software Foundation, Inc. + +This file is part of the GNU MP Library. + +The GNU MP Library is free software; you can redistribute it and/or modify +it under the terms of the GNU Library General Public License as published by +the Free Software Foundation; either version 2 of the License, or (at your +option) any later version. + +The GNU MP Library is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public +License for more details. + +You should have received a copy of the GNU Library General Public License +along with the GNU MP Library; see the file COPYING.LIB. If not, write to +the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, +MA 02111-1307, USA. */ + +#include <stdio.h> +#include "gmp.h" +#include "gmp-impl.h" +#include "urandom.h" + +#ifndef SIZE +#define SIZE 16 +#endif + +main (argc, argv) + int argc; + char **argv; +{ + mp_size_t size; + mp_exp_t exp; + int reps = 100000; + int i; + mpf_t x, y, y2; + mp_size_t bprec = 100; + mpf_t rerr, max_rerr, limit_rerr; + + if (argc > 1) + { + reps = strtol (argv[1], 0, 0); + if (argc > 2) + bprec = strtol (argv[2], 0, 0); + } + + mpf_set_default_prec (bprec); + + mpf_init_set_ui (limit_rerr, 1); + mpf_div_2exp (limit_rerr, limit_rerr, bprec); +#if VERBOSE + mpf_dump (limit_rerr); +#endif + mpf_init (rerr); + mpf_init_set_ui (max_rerr, 0); + + mpf_init (x); + mpf_init (y); + mpf_init (y2); + for (i = 0; i < reps; i++) + { + size = urandom () % SIZE; + exp = urandom () % SIZE; + mpf_random2 (x, size, exp); + + mpf_sqrt (y, x); + mpf_mul (y2, y, y); + + mpf_reldiff (rerr, x, y2); + if (mpf_cmp (rerr, max_rerr) > 0) + { + mpf_set (max_rerr, rerr); +#if VERBOSE + mpf_dump (max_rerr); +#endif + if (mpf_cmp (rerr, limit_rerr) > 0) + { + printf ("ERROR after %d tests\n", i); + printf (" x = "); mpf_dump (x); + printf (" y = "); mpf_dump (y); + printf (" y2 = "); mpf_dump (y2); + abort (); + } + } + } + + exit (0); +} + +oo (x) + mpf_t x; +{ + mp_size_t i; + printf (" exp = %ld\n", x->_mp_exp); + printf ("size = %d\n", x->_mp_size); + for (i = ABS (x->_mp_size) - 1; i >= 0; i--) + printf ("%08lX ", x->_mp_d[i]); + printf ("\n"); + mpf_dump (x); +} diff --git a/contrib/libgmp/mpf/tests/t-sub.c b/contrib/libgmp/mpf/tests/t-sub.c new file mode 100644 index 0000000..6918866 --- /dev/null +++ b/contrib/libgmp/mpf/tests/t-sub.c @@ -0,0 +1,122 @@ +/* Test mpf_sub. + +Copyright (C) 1996 Free Software Foundation, Inc. + +This file is part of the GNU MP Library. + +The GNU MP Library is free software; you can redistribute it and/or modify +it under the terms of the GNU Library General Public License as published by +the Free Software Foundation; either version 2 of the License, or (at your +option) any later version. + +The GNU MP Library is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public +License for more details. + +You should have received a copy of the GNU Library General Public License +along with the GNU MP Library; see the file COPYING.LIB. If not, write to +the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, +MA 02111-1307, USA. */ + +#include <stdio.h> +#include "gmp.h" +#include "gmp-impl.h" +#include "urandom.h" + +#ifndef SIZE +#define SIZE 16 +#endif + +#if __STDC__ +void ref_mpf_add (mpf_t, const mpf_t, const mpf_t); +void ref_mpf_sub (mpf_t, const mpf_t, const mpf_t); +#else +void ref_mpf_add (); +void ref_mpf_sub (); +#endif + +main (argc, argv) + int argc; + char **argv; +{ + mp_size_t size; + mp_exp_t exp; + int reps = 500000; + int i; + mpf_t u, v, w, wref; + mp_size_t bprec = 100; + mpf_t rerr, max_rerr, limit_rerr; + + if (argc > 1) + { + reps = strtol (argv[1], 0, 0); + if (argc > 2) + bprec = strtol (argv[2], 0, 0); + } + + mpf_set_default_prec (bprec); + + mpf_init_set_ui (limit_rerr, 1); + mpf_div_2exp (limit_rerr, limit_rerr, bprec); +#if VERBOSE + mpf_dump (limit_rerr); +#endif + mpf_init (rerr); + mpf_init_set_ui (max_rerr, 0); + + mpf_init (u); + mpf_init (v); + mpf_init (w); + mpf_init (wref); + for (i = 0; i < reps; i++) + { + size = urandom () % (2 * SIZE) - SIZE; + exp = urandom () % SIZE; + mpf_random2 (u, size, exp); + + size = urandom () % (2 * SIZE) - SIZE; + exp = urandom () % SIZE; + mpf_random2 (v, size, exp); + + if ((urandom () & 1) != 0) + mpf_add_ui (u, v, 1); + else if ((urandom () & 1) != 0) + mpf_sub_ui (u, v, 1); + + mpf_sub (w, u, v); + ref_mpf_sub (wref, u, v); + + mpf_reldiff (rerr, w, wref); + if (mpf_cmp (rerr, max_rerr) > 0) + { + mpf_set (max_rerr, rerr); +#if VERBOSE + mpf_dump (max_rerr); +#endif + if (mpf_cmp (rerr, limit_rerr) > 0) + { + printf ("ERROR after %d tests\n", i); + printf (" u = "); mpf_dump (u); + printf (" v = "); mpf_dump (v); + printf ("wref = "); mpf_dump (wref); + printf (" w = "); mpf_dump (w); + abort (); + } + } + } + + exit (0); +} + +oo (x) + mpf_t x; +{ + mp_size_t i; + printf (" exp = %ld\n", x->_mp_exp); + printf ("size = %d\n", x->_mp_size); + for (i = ABS (x->_mp_size) - 1; i >= 0; i--) + printf ("%08lX ", x->_mp_d[i]); + printf ("\n"); + mpf_dump (x); +} diff --git a/contrib/libgmp/mpf/ui_div.c b/contrib/libgmp/mpf/ui_div.c new file mode 100644 index 0000000..a49a952 --- /dev/null +++ b/contrib/libgmp/mpf/ui_div.c @@ -0,0 +1,131 @@ +/* mpf_ui_div -- Divide an unsigned integer with a float. + +Copyright (C) 1993, 1994, 1995, 1996 Free Software Foundation, Inc. + +This file is part of the GNU MP Library. + +The GNU MP Library is free software; you can redistribute it and/or modify +it under the terms of the GNU Library General Public License as published by +the Free Software Foundation; either version 2 of the License, or (at your +option) any later version. + +The GNU MP Library is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public +License for more details. + +You should have received a copy of the GNU Library General Public License +along with the GNU MP Library; see the file COPYING.LIB. If not, write to +the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, +MA 02111-1307, USA. */ + +#include "gmp.h" +#include "gmp-impl.h" +#include "longlong.h" + +void +#if __STDC__ +mpf_ui_div (mpf_ptr r, unsigned long int u, mpf_srcptr v) +#else +mpf_ui_div (r, u, v) + mpf_ptr r; + unsigned long int u; + mpf_srcptr v; +#endif +{ + mp_srcptr vp; + mp_ptr rp, tp; + mp_size_t vsize; + mp_size_t rsize, tsize; + mp_size_t sign_quotient; + mp_size_t prec; + unsigned normalization_steps; + mp_limb_t q_limb; + mp_exp_t rexp; + TMP_DECL (marker); + + vsize = v->_mp_size; + sign_quotient = vsize; + vsize = ABS (vsize); + prec = r->_mp_prec; + + if (vsize == 0) + vsize = 1 / vsize; /* divide by zero as directed */ + if (u == 0) + { + r->_mp_size = 0; + r->_mp_exp = 0; + return; + } + + TMP_MARK (marker); + rexp = 1 - v->_mp_exp; + + rp = r->_mp_d; + vp = v->_mp_d; + + if (vsize > prec) + { + vp += vsize - prec; + vsize = prec; + } + + tsize = vsize + prec; + tp = (mp_ptr) TMP_ALLOC ((tsize + 1) * BYTES_PER_MP_LIMB); + MPN_ZERO (tp, tsize); + + count_leading_zeros (normalization_steps, vp[vsize - 1]); + + /* Normalize the divisor and the dividend. */ + if (normalization_steps != 0) + { + mp_ptr tmp; + mp_limb_t dividend_high, dividend_low; + + /* Shift up the divisor setting the most significant bit of + the most significant limb. Use temporary storage not to clobber + the original contents of the divisor. */ + tmp = (mp_ptr) TMP_ALLOC (vsize * BYTES_PER_MP_LIMB); + mpn_lshift (tmp, vp, vsize, normalization_steps); + vp = tmp; + + /* Shift up the dividend, possibly introducing a new most + significant word. */ + dividend_high = (mp_limb_t) u >> (BITS_PER_MP_LIMB - normalization_steps); + dividend_low = (mp_limb_t) u << normalization_steps; + + tp[tsize - 1] = dividend_low; + if (dividend_high != 0) + { + tp[tsize] = dividend_high; + tsize++; + rexp++; + } + } + else + { + /* The divisor is already normalized, as required. + Copy it to temporary space if it overlaps with the quotient. */ + if (vp - rp <= tsize - vsize) + { + mp_ptr tmp = (mp_ptr) TMP_ALLOC (vsize * BYTES_PER_MP_LIMB); + MPN_COPY (tmp, vp, vsize); + vp = (mp_srcptr) tmp; + } + + tp[tsize - 1] = u; + } + + q_limb = mpn_divmod (rp, tp, tsize, vp, vsize); + rsize = tsize - vsize; + if (q_limb) + { + rp[rsize] = q_limb; + rsize++; + rexp++; + } + + r->_mp_size = sign_quotient >= 0 ? rsize : -rsize; + r->_mp_exp = rexp; + TMP_FREE (marker); +} diff --git a/contrib/libgmp/mpf/ui_sub.c b/contrib/libgmp/mpf/ui_sub.c new file mode 100644 index 0000000..acb9210 --- /dev/null +++ b/contrib/libgmp/mpf/ui_sub.c @@ -0,0 +1,334 @@ +/* mpf_ui_sub -- Subtract a float from an unsigned long int. + +Copyright (C) 1993, 1994, 1995, 1996 Free Software Foundation, Inc. + +This file is part of the GNU MP Library. + +The GNU MP Library is free software; you can redistribute it and/or modify +it under the terms of the GNU Library General Public License as published by +the Free Software Foundation; either version 2 of the License, or (at your +option) any later version. + +The GNU MP Library is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public +License for more details. + +You should have received a copy of the GNU Library General Public License +along with the GNU MP Library; see the file COPYING.LIB. If not, write to +the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, +MA 02111-1307, USA. */ + +#include "gmp.h" +#include "gmp-impl.h" + +void +#if __STDC__ +mpf_ui_sub (mpf_ptr r, unsigned long int u, mpf_srcptr v) +#else +mpf_ui_sub (r, u, v) + mpf_ptr r; + unsigned long int u; + mpf_srcptr v; +#endif +{ + mp_srcptr up, vp; + mp_ptr rp, tp; + mp_size_t usize, vsize, rsize; + mp_size_t prec; + mp_exp_t uexp; + mp_size_t ediff; + int negate; + mp_limb_t ulimb; + TMP_DECL (marker); + + vsize = v->_mp_size; + + /* Handle special cases that don't work in generic code below. */ + if (u == 0) + { + mpf_neg (r, v); + return; + } + if (vsize == 0) + { + mpf_set_ui (r, u); + return; + } + + /* If signs of U and V are different, perform addition. */ + if (vsize < 0) + { + __mpf_struct v_negated; + v_negated._mp_size = -vsize; + v_negated._mp_exp = v->_mp_exp; + v_negated._mp_d = v->_mp_d; + mpf_add_ui (r, &v_negated, u); + return; + } + + TMP_MARK (marker); + + /* Signs are now known to be the same. */ + + ulimb = u; + /* Make U be the operand with the largest exponent. */ + if (1 < v->_mp_exp) + { + negate = 1; + usize = ABS (vsize); + vsize = 1; + up = v->_mp_d; + vp = &ulimb; + rp = r->_mp_d; + prec = r->_mp_prec + 1; + uexp = v->_mp_exp; + ediff = uexp - 1; + } + else + { + negate = 0; + usize = 1; + vsize = ABS (vsize); + up = &ulimb; + vp = v->_mp_d; + rp = r->_mp_d; + prec = r->_mp_prec; + uexp = 1; + ediff = 1 - v->_mp_exp; + } + + /* Ignore leading limbs in U and V that are equal. Doing + this helps increase the precision of the result. */ + if (ediff == 0) + { + /* This loop normally exits immediately. Optimize for that. */ + for (;;) + { + usize--; + vsize--; + if (up[usize] != vp[vsize]) + break; + uexp--; + if (usize == 0) + goto Lu0; + if (vsize == 0) + goto Lv0; + } + usize++; + vsize++; + /* Note that either operand (but not both operands) might now have + leading zero limbs. It matters only that U is unnormalized if + vsize is now zero, and vice versa. And it is only in that case + that we have to adjust uexp. */ + if (vsize == 0) + Lv0: + while (usize != 0 && up[usize - 1] == 0) + usize--, uexp--; + if (usize == 0) + Lu0: + while (vsize != 0 && vp[vsize - 1] == 0) + vsize--, uexp--; + } + + /* If U extends beyond PREC, ignore the part that does. */ + if (usize > prec) + { + up += usize - prec; + usize = prec; + } + + /* If V extends beyond PREC, ignore the part that does. + Note that this may make vsize negative. */ + if (vsize + ediff > prec) + { + vp += vsize + ediff - prec; + vsize = prec - ediff; + } + + /* Allocate temp space for the result. Allocate + just vsize + ediff later??? */ + tp = (mp_ptr) TMP_ALLOC (prec * BYTES_PER_MP_LIMB); + + if (ediff >= prec) + { + /* V completely cancelled. */ + if (tp != up) + MPN_COPY (rp, up, usize); + rsize = usize; + } + else + { + /* Locate the least significant non-zero limb in (the needed + parts of) U and V, to simplify the code below. */ + for (;;) + { + if (vsize == 0) + { + MPN_COPY (rp, up, usize); + rsize = usize; + goto done; + } + if (vp[0] != 0) + break; + vp++, vsize--; + } + for (;;) + { + if (usize == 0) + { + MPN_COPY (rp, vp, vsize); + rsize = vsize; + negate ^= 1; + goto done; + } + if (up[0] != 0) + break; + up++, usize--; + } + + /* uuuu | uuuu | uuuu | uuuu | uuuu */ + /* vvvvvvv | vv | vvvvv | v | vv */ + + if (usize > ediff) + { + /* U and V partially overlaps. */ + if (ediff == 0) + { + /* Have to compare the leading limbs of u and v + to determine whether to compute u - v or v - u. */ + if (usize > vsize) + { + /* uuuu */ + /* vv */ + int cmp; + cmp = mpn_cmp (up + usize - vsize, vp, vsize); + if (cmp >= 0) + { + mp_size_t size; + size = usize - vsize; + MPN_COPY (tp, up, size); + mpn_sub_n (tp + size, up + size, vp, vsize); + rsize = usize; + } + else + { + /* vv */ /* Swap U and V. */ + /* uuuu */ + mp_size_t size, i; + size = usize - vsize; + tp[0] = -up[0]; + for (i = 1; i < size; i++) + tp[i] = ~up[i]; + mpn_sub_n (tp + size, vp, up + size, vsize); + mpn_sub_1 (tp + size, tp + size, vsize, (mp_limb_t) 1); + negate ^= 1; + rsize = usize; + } + } + else if (usize < vsize) + { + /* uuuu */ + /* vvvvvvv */ + int cmp; + cmp = mpn_cmp (up, vp + vsize - usize, usize); + if (cmp > 0) + { + mp_size_t size, i; + size = vsize - usize; + tp[0] = -vp[0]; + for (i = 1; i < size; i++) + tp[i] = ~vp[i]; + mpn_sub_n (tp + size, up, vp + size, usize); + mpn_sub_1 (tp + size, tp + size, usize, (mp_limb_t) 1); + rsize = vsize; + } + else + { + /* vvvvvvv */ /* Swap U and V. */ + /* uuuu */ + /* This is the only place we can get 0.0. */ + mp_size_t size; + size = vsize - usize; + MPN_COPY (tp, vp, size); + mpn_sub_n (tp + size, vp + size, up, usize); + negate ^= 1; + rsize = vsize; + } + } + else + { + /* uuuu */ + /* vvvv */ + int cmp; + cmp = mpn_cmp (up, vp + vsize - usize, usize); + if (cmp > 0) + { + mpn_sub_n (tp, up, vp, usize); + rsize = usize; + } + else + { + mpn_sub_n (tp, vp, up, usize); + negate ^= 1; + rsize = usize; + /* can give zero */ + } + } + } + else + { + if (vsize + ediff <= usize) + { + /* uuuu */ + /* v */ + mp_size_t size; + size = usize - ediff - vsize; + MPN_COPY (tp, up, size); + mpn_sub (tp + size, up + size, usize - size, vp, vsize); + rsize = usize; + } + else + { + /* uuuu */ + /* vvvvv */ + mp_size_t size, i; + size = vsize + ediff - usize; + tp[0] = -vp[0]; + for (i = 1; i < size; i++) + tp[i] = ~vp[i]; + mpn_sub (tp + size, up, usize, vp + size, usize - ediff); + mpn_sub_1 (tp + size, tp + size, usize, (mp_limb_t) 1); + rsize = vsize + ediff; + } + } + } + else + { + /* uuuu */ + /* vv */ + mp_size_t size, i; + size = vsize + ediff - usize; + tp[0] = -vp[0]; + for (i = 1; i < vsize; i++) + tp[i] = ~vp[i]; + for (i = vsize; i < size; i++) + tp[i] = ~(mp_limb_t) 0; + mpn_sub_1 (tp + size, up, usize, (mp_limb_t) 1); + rsize = size + usize; + } + + /* Full normalize. Optimize later. */ + while (rsize != 0 && tp[rsize - 1] == 0) + { + rsize--; + uexp--; + } + MPN_COPY (rp, tp, rsize); + } + + done: + r->_mp_size = negate ? -rsize : rsize; + r->_mp_exp = uexp; + TMP_FREE (marker); +} diff --git a/contrib/libgmp/mpn/Makefile.in b/contrib/libgmp/mpn/Makefile.in new file mode 100644 index 0000000..132159b --- /dev/null +++ b/contrib/libgmp/mpn/Makefile.in @@ -0,0 +1,92 @@ +# Makefile for GNU MP/mpn functions +# Copyright (C) 1991, 1993, 1994, 1996 Free Software Foundation, Inc. + +# This file is part of the GNU MP Library. + +# The GNU MP Library is free software; you can redistribute it and/or modify +# it under the terms of the GNU Library General Public License as published by +# the Free Software Foundation; either version 2 of the License, or (at your +# option) any later version. + +# The GNU MP Library is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +# or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public +# License for more details. + +# You should have received a copy of the GNU Library General Public License +# along with the GNU MP Library; see the file COPYING.LIB. If not, write to +# the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, +# MA 02111-1307, USA. + +srcdir = . + +MPN_OBJECTS = This gets filled in by configure.in. +MPN_LINKS = This gets filled in by configure.in. +CC = gcc +CPP = $(CC) -E +CFLAGS = -g -O +INCLUDES = -I. -I.. -I$(srcdir) -I$(srcdir)/.. +AR = ar +AR_FLAGS = rc +SFLAGS= + +#### host and target specific makefile fragments come in here. +### + +libmpn.a: Makefile mp_bases.o $(MPN_OBJECTS) + rm -f $@ + $(AR) $(AR_FLAGS) $@ mp_bases.o $(MPN_OBJECTS) + +.SUFFIXES: .c .s .S + +.c.o: + $(CC) -c $(INCLUDES) $(CFLAGS) $(XCFLAGS) $< + +.s.o: + $(CC) -c $(CFLAGS) $< + +.S.o: + $(CPP) $(SFLAGS) $(INCLUDES) $(CFLAGS) $< | grep -v '^#' >tmp-$*.s + $(CC) -c tmp-$*.s -o $@ + rm -f tmp-$*.s + +clean mostlyclean: + rm -f *.o tmp-* libmpn.a + #-cd tests; $(MAKE) $@ +distclean maintainer-clean: clean + rm -f asm-syntax.h Makefile config.status $(MPN_LINKS) + -cd tests; $(MAKE) $@ + +Makefile: $(srcdir)/Makefile.in + $(SHELL) ./config.status + + +# Maybe configure could add dependencies here..? + +H = $(srcdir)/../gmp.h $(srcdir)/../gmp-impl.h gmp-mparam.h +L = $(srcdir)/../longlong.h + +mp_bases.o: $(srcdir)/mp_bases.c $(H) +bdivmod.o: bdivmod.c $(H) $(L) +cmp.o: cmp.c $(H) +divmod_1.o: divmod_1.c $(H) $(L) +divrem.o: divrem.c $(H) $(L) +divrem_1.o: divrem_1.c $(H) $(L) +dump.o: dump.c $(H) +gcd.o: gcd.c $(H) $(L) +gcd_1.o: gcd_1.c $(H) $(L) +gcdext.o: gcdext.c $(H) $(L) +get_str.o: get_str.c $(H) $(L) +hamdist.o: hamdist.c $(H) +inlines.o: inlines.c $(srcdir)/../gmp.h +mod_1.o: mod_1.c $(H) $(L) +mul.o: mul.c $(H) +mul_n.o: mul_n.c $(H) +perfsqr.o: perfsqr.c $(H) $(L) +popcount.o: popcount.c $(H) +pre_mod_1.o: pre_mod_1.c $(H) $(L) +random2.o: random2.c $(H) +scan0.o: scan0.c $(H) $(L) +scan1.o: scan1.c $(H) $(L) +set_str.o: set_str.c $(H) +sqrtrem.o: sqrtrem.c $(H) $(L) diff --git a/contrib/libgmp/mpn/README b/contrib/libgmp/mpn/README new file mode 100644 index 0000000..3da559e --- /dev/null +++ b/contrib/libgmp/mpn/README @@ -0,0 +1,15 @@ +This directory contains all code for the mpn layer of GMP. + +Most subdirectories contain machine-dependent code, written in assembly or +C. The `generic' subdirectory contains default code, used when there is no +machine-dependent replacement for a particular machine. + +There is one subdirectory for each architecture. Note that e.g., 32-bit +sparc and 64-bit sparc cannot share any code, and are therefore considered +completely different architecture. + +A particular machine will only use code from one such subdirectory, and the +`generic' subdirectory. The architecture-specific subdirectory contains a +hierachy of directories for various architecture variants and +implementations; the top-most level contains code that runs correctly on all +variants. diff --git a/contrib/libgmp/mpn/bsd.h b/contrib/libgmp/mpn/bsd.h new file mode 100644 index 0000000..8a0cbce --- /dev/null +++ b/contrib/libgmp/mpn/bsd.h @@ -0,0 +1,5 @@ +#if __STDC__ +#define C_SYMBOL_NAME(name) _##name +#else +#define C_SYMBOL_NAME(name) _/**/name +#endif diff --git a/contrib/libgmp/mpn/config/t-oldgas b/contrib/libgmp/mpn/config/t-oldgas new file mode 100644 index 0000000..ba02fa7 --- /dev/null +++ b/contrib/libgmp/mpn/config/t-oldgas @@ -0,0 +1 @@ +SFLAGS=-DBROKEN_ALIGN diff --git a/contrib/libgmp/mpn/config/t-ppc-aix b/contrib/libgmp/mpn/config/t-ppc-aix new file mode 100644 index 0000000..a31ce0d --- /dev/null +++ b/contrib/libgmp/mpn/config/t-ppc-aix @@ -0,0 +1 @@ +SFLAGS=-Wa,-mppc diff --git a/contrib/libgmp/mpn/config/t-pwr-aix b/contrib/libgmp/mpn/config/t-pwr-aix new file mode 100644 index 0000000..3e11d9f --- /dev/null +++ b/contrib/libgmp/mpn/config/t-pwr-aix @@ -0,0 +1 @@ +SFLAGS=-Wa,-mpwr diff --git a/contrib/libgmp/mpn/configure.in b/contrib/libgmp/mpn/configure.in new file mode 100644 index 0000000..90c2626 --- /dev/null +++ b/contrib/libgmp/mpn/configure.in @@ -0,0 +1,178 @@ +# This file is a shell script fragment that supplies the information +# necessary for a configure script to process the program in +# this directory. For more information, look at ../configure. + +configdirs= +srctrigger=powerpc32 +srcname="GNU Multi-Precision library/mpn" + +# per-host: + +# per-target: + +case "${target}" in + sparc9*-*-* | sparc64*-*-* | ultrasparc*-*-*) + #path="sparc64" ;; Don't use this until compilers are ready + path="sparc32/v8 sparc" ;; + sparc8*-*-* | microsparc*-*-*) + path="sparc32/v8 sparc" ;; + supersparc*-*-*) + path="sparc32/v8/supersparc sparc32/v8 sparc" + extra_functions="udiv" ;; + sparc*-*-*) path="sparc32" + if [ x$floating_point = xno ] + then extra_functions="udiv_nfp" + else extra_functions="udiv_fp" + fi + ;; + hppa7000*-*-*) path="hppa/hppa1_1 hppa"; extra_functions="udiv_qrnnd" ;; + hppa1.0*-*-*) path="hppa"; extra_functions="udiv_qrnnd" ;; + hppa*-*-*) # assume pa7100 + path="hppa/hppa1_1/pa7100 hppa/hppa1_1 hppa" + extra_functions="udiv_qrnnd" ;; + cray2-cray-unicos* | [xy]mp-cray-unicos* | [ctj]90-cray-unicos*) + path="cray" ;; + alphaev5-*-*) path="alpha/ev5 alpha"; extra_functions="udiv_qrnnd" ;; + alpha*-*-*) path="alpha"; extra_functions="udiv_qrnnd" ;; + am29000*-*-*) path="am29000" ;; + a29k*-*-*) path="am29000" ;; + +# Intel x86 configurations + i[34]86*-*-linuxaout* | i[34]86*-*-linuxoldld* | \ + i[34]86*-*-*bsd*) # x86 running BSD or Linux with a.out + echo '#define BSD_SYNTAX' >asm-syntax.h + echo '#include "'$srcdir'/x86/syntax.h"' >>asm-syntax.h + path="x86" ;; + i[56]86*-*-linuxaout* | pentium-*-linuxaout* | pentiumpro-*-linuxaout* | \ + i[56]86*-*-linuxoldld* | pentium-*-linuxoldld* | pentiumpro-*-linuxoldld* | \ + i[56]86*-*-*bsd* | pentium-*-*bsd* | pentiumpro-*-*bsd*) + echo '#define BSD_SYNTAX' >asm-syntax.h + echo '#include "'$srcdir'/x86/syntax.h"' >>asm-syntax.h + path="x86/pentium x86" ;; + i[34]86*-*-*) # x86 with ELF/SysV format + echo '#define ELF_SYNTAX' >asm-syntax.h + echo '#include "'$srcdir'/x86/syntax.h"' >>asm-syntax.h + path="x86" ;; + i[56]86*-*-* | pentium-*-* | pentiumpro-*-*) # x86 with ELF/SysV format + echo '#define ELF_SYNTAX' >asm-syntax.h + echo '#include "'$srcdir'/x86/syntax.h"' >>asm-syntax.h + path="x86/pentium x86" ;; + +# Motorola 68k configurations. Let m68k mean 68020-68040. +# mc68000 or mc68060 configurations need to be specified explicitly + m680[234]0*-*-linuxaout* | m68k*-*-linuxaout*) + echo '#define MIT_SYNTAX' >asm-syntax.h + echo '#include "'$srcdir'/m68k/syntax.h"' >>asm-syntax.h + path="m68k/mc68020 m68k" ;; + m68060*-*-linuxaout*) + echo '#define MIT_SYNTAX' >asm-syntax.h + echo '#include "'$srcdir'/m68k/syntax.h"' >>asm-syntax.h + path="m68k" ;; + m680[234]0*-*-linux* | m68k*-*-linux*) + echo '#define ELF_SYNTAX' >asm-syntax.h + echo '#include "'$srcdir'/m68k/syntax.h"' >>asm-syntax.h + path="m68k/mc68020 m68k" ;; + m68060*-*-linux*) + echo '#define ELF_SYNTAX' >asm-syntax.h + echo '#include "'$srcdir'/m68k/syntax.h"' >>asm-syntax.h + path="m68k" ;; + m68000*-*-* | m68060*-*-*) + echo '#define MIT_SYNTAX' >asm-syntax.h + echo '#include "'$srcdir'/m68k/syntax.h"' >>asm-syntax.h + path="m68k/mc68000" ;; + m680[234]0*-*-* | m68k*-*-*) + echo '#define MIT_SYNTAX' >asm-syntax.h + echo '#include "'$srcdir'/m68k/syntax.h"' >>asm-syntax.h + path="m68k/mc68020 m68k" ;; + + i960*-*-*) path="i960" ;; + m88k*-*-* | m88k*-*-*) path="m88k" ;; + m88110*-*-*) path="m88k/mc88110 m88k" ;; + ns32k*-*-*) path="n32k" ;; + ppc601-*-*) path="power powerpc32" ;; + ppc620-*-* | powerpc64*-*-*) path="powerpc64" ;; + ppc60[234]*-*-* | powerpc*-*-*) path="powerpc32" ;; + pyramid-*-*) path="pyr" ;; + rs6000-*-* | power-*-* | power2-*-*) + path="power"; extra_functions="udiv_w_sdiv" ;; + sh-*-*) path="sh" ;; + sh2-*-*) path="sh/sh2 sh" ;; + mips[34]*-*-*) path="mips3" ;; + mips*-*-irix6*) path="mips3" ;; + mips*-*-*) path="mips2" ;; + vax*-*-*) path="vax"; extra_functions="udiv_w_sdiv" ;; + z8000x*-*-*) path="z8000x"; extra_functions="udiv_w_sdiv" ;; + z8000*-*-*) path="z8000"; extra_functions="udiv_w_sdiv" ;; + clipper*-*-*) path="clipper" ;; + *-*-*) ;; +esac + +case "${target}" in + *-*-linuxaout* | *-*-linuxoldld*) config=bsd.h ;; + *-sysv* | *-solaris* | *-*-linux*) config="sysv.h" ;; + *) config="bsd.h" ;; +esac + +case "${target}" in + i[3456]86*-*-*bsd* | i[3456]86*-*-linuxaout* | i[3456]86*-*-linuxoldld* | \ + pentium-*-*bsd* | pentium-*-linuxaout* | pentium-*-linuxoldld* | \ + pentiumpro-*-*bsd* | pentiumpro-*-linuxaout* | pentiumpro-*-linuxoldld*) + target_makefile_frag=config/t-oldgas ;; + rs6000-*-aix[456789]* | rs6000-*-aix3.2.[456789]) + target_makefile_frag=config/t-pwr-aix ;; + ppc601-*-aix[456789]* | ppc601-*-aix3.2.[456789] | \ + ppc60[234]*-*-aix[456789]* | ppc60[234]*-*-aix3.2.[456789] | \ + powerpc*-*-aix[456789]* | powerpc*-*-aix3.2.[456789]) + target_makefile_frag=config/t-ppc-aix ;; +esac + + +functions="${extra_functions} inlines add_n addmul_1 cmp divmod_1 \ + divrem divrem_1 dump lshift mod_1 mul mul_1 mul_n random2 rshift sqrtrem \ + sub_n submul_1 get_str set_str scan0 scan1 popcount hamdist gcd_1 \ + pre_mod_1 perfsqr bdivmod gcd gcdext" + +path="$path generic" +mpn_objects= + +for fn in $functions ; do + mpn_objects="$mpn_objects $fn.o" + for dir in $path ; do + rm -f $fn.[Ssc] + if test -f $srcdir/$dir/$fn.S ; then + files="$files $dir/$fn.S" + links="$links $fn.S" + break + elif test -f $srcdir/$dir/$fn.s ; then + files="$files $dir/$fn.s" + links="$links $fn.s" + break + elif test -f $srcdir/$dir/$fn.c ; then + files="$files $dir/$fn.c" + links="$links $fn.c" + break + fi + done +done + +for dir in $path ; do + rm -f gmp-mparam.h + if test -f $srcdir/$dir/gmp-mparam.h ; then + files="$files $dir/gmp-mparam.h" + links="$links gmp-mparam.h" + break + fi +done + +links="sysdep.h $links" +files="$config $files" + +mpn_links=$links + +# post-target: + +sed <Makefile >Makefile.tmp \ + -e "s/MPN_LINKS = .*/MPN_LINKS =${mpn_links}/" \ + -e "s/MPN_OBJECTS = .*/MPN_OBJECTS =${mpn_objects}/" + +mv Makefile.tmp Makefile diff --git a/contrib/libgmp/mpn/generic/add_n.c b/contrib/libgmp/mpn/generic/add_n.c new file mode 100644 index 0000000..9d71df1 --- /dev/null +++ b/contrib/libgmp/mpn/generic/add_n.c @@ -0,0 +1,62 @@ +/* mpn_add_n -- Add two limb vectors of equal, non-zero length. + +Copyright (C) 1992, 1993, 1994, 1996 Free Software Foundation, Inc. + +This file is part of the GNU MP Library. + +The GNU MP Library is free software; you can redistribute it and/or modify +it under the terms of the GNU Library General Public License as published by +the Free Software Foundation; either version 2 of the License, or (at your +option) any later version. + +The GNU MP Library is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public +License for more details. + +You should have received a copy of the GNU Library General Public License +along with the GNU MP Library; see the file COPYING.LIB. If not, write to +the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, +MA 02111-1307, USA. */ + +#include "gmp.h" +#include "gmp-impl.h" + +mp_limb_t +#if __STDC__ +mpn_add_n (mp_ptr res_ptr, mp_srcptr s1_ptr, mp_srcptr s2_ptr, mp_size_t size) +#else +mpn_add_n (res_ptr, s1_ptr, s2_ptr, size) + register mp_ptr res_ptr; + register mp_srcptr s1_ptr; + register mp_srcptr s2_ptr; + mp_size_t size; +#endif +{ + register mp_limb_t x, y, cy; + register mp_size_t j; + + /* The loop counter and index J goes from -SIZE to -1. This way + the loop becomes faster. */ + j = -size; + + /* Offset the base pointers to compensate for the negative indices. */ + s1_ptr -= j; + s2_ptr -= j; + res_ptr -= j; + + cy = 0; + do + { + y = s2_ptr[j]; + x = s1_ptr[j]; + y += cy; /* add previous carry to one addend */ + cy = (y < cy); /* get out carry from that addition */ + y = x + y; /* add other addend */ + cy = (y < x) + cy; /* get out carry from that add, combine */ + res_ptr[j] = y; + } + while (++j != 0); + + return cy; +} diff --git a/contrib/libgmp/mpn/generic/addmul_1.c b/contrib/libgmp/mpn/generic/addmul_1.c new file mode 100644 index 0000000..3a5e214 --- /dev/null +++ b/contrib/libgmp/mpn/generic/addmul_1.c @@ -0,0 +1,65 @@ +/* mpn_addmul_1 -- multiply the S1_SIZE long limb vector pointed to by S1_PTR + by S2_LIMB, add the S1_SIZE least significant limbs of the product to the + limb vector pointed to by RES_PTR. Return the most significant limb of + the product, adjusted for carry-out from the addition. + +Copyright (C) 1992, 1993, 1994, 1996 Free Software Foundation, Inc. + +This file is part of the GNU MP Library. + +The GNU MP Library is free software; you can redistribute it and/or modify +it under the terms of the GNU Library General Public License as published by +the Free Software Foundation; either version 2 of the License, or (at your +option) any later version. + +The GNU MP Library is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public +License for more details. + +You should have received a copy of the GNU Library General Public License +along with the GNU MP Library; see the file COPYING.LIB. If not, write to +the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, +MA 02111-1307, USA. */ + +#include "gmp.h" +#include "gmp-impl.h" +#include "longlong.h" + +mp_limb_t +mpn_addmul_1 (res_ptr, s1_ptr, s1_size, s2_limb) + register mp_ptr res_ptr; + register mp_srcptr s1_ptr; + mp_size_t s1_size; + register mp_limb_t s2_limb; +{ + register mp_limb_t cy_limb; + register mp_size_t j; + register mp_limb_t prod_high, prod_low; + register mp_limb_t x; + + /* The loop counter and index J goes from -SIZE to -1. This way + the loop becomes faster. */ + j = -s1_size; + + /* Offset the base pointers to compensate for the negative indices. */ + res_ptr -= j; + s1_ptr -= j; + + cy_limb = 0; + do + { + umul_ppmm (prod_high, prod_low, s1_ptr[j], s2_limb); + + prod_low += cy_limb; + cy_limb = (prod_low < cy_limb) + prod_high; + + x = res_ptr[j]; + prod_low = x + prod_low; + cy_limb += (prod_low < x); + res_ptr[j] = prod_low; + } + while (++j != 0); + + return cy_limb; +} diff --git a/contrib/libgmp/mpn/generic/bdivmod.c b/contrib/libgmp/mpn/generic/bdivmod.c new file mode 100644 index 0000000..f095288 --- /dev/null +++ b/contrib/libgmp/mpn/generic/bdivmod.c @@ -0,0 +1,129 @@ +/* mpn/bdivmod.c: mpn_bdivmod for computing U/V mod 2^d. + +Copyright (C) 1991, 1993, 1994, 1995, 1996 Free Software Foundation, Inc. + +This file is part of the GNU MP Library. + +The GNU MP Library is free software; you can redistribute it and/or modify +it under the terms of the GNU Library General Public License as published by +the Free Software Foundation; either version 2 of the License, or (at your +option) any later version. + +The GNU MP Library is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public +License for more details. + +You should have received a copy of the GNU Library General Public License +along with the GNU MP Library; see the file COPYING.LIB. If not, write to +the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, +MA 02111-1307, USA. */ + +/* q_high = mpn_bdivmod (qp, up, usize, vp, vsize, d). + + Puts the low d/BITS_PER_MP_LIMB limbs of Q = U / V mod 2^d at qp, and + returns the high d%BITS_PER_MP_LIMB bits of Q as the result. + + Also, U - Q * V mod 2^(usize*BITS_PER_MP_LIMB) is placed at up. Since the + low d/BITS_PER_MP_LIMB limbs of this difference are zero, the code allows + the limb vectors at qp to overwrite the low limbs at up, provided qp <= up. + + Preconditions: + 1. V is odd. + 2. usize * BITS_PER_MP_LIMB >= d. + 3. If Q and U overlap, qp <= up. + + Ken Weber (kweber@mat.ufrgs.br, kweber@mcs.kent.edu) + + Funding for this work has been partially provided by Conselho Nacional + de Desenvolvimento Cienti'fico e Tecnolo'gico (CNPq) do Brazil, Grant + 301314194-2, and was done while I was a visiting reseacher in the Instituto + de Matema'tica at Universidade Federal do Rio Grande do Sul (UFRGS). + + References: + T. Jebelean, An algorithm for exact division, Journal of Symbolic + Computation, v. 15, 1993, pp. 169-180. + + K. Weber, The accelerated integer GCD algorithm, ACM Transactions on + Mathematical Software, v. 21 (March), 1995, pp. 111-122. */ + +#include "gmp.h" +#include "gmp-impl.h" +#include "longlong.h" + +mp_limb_t +#if __STDC__ +mpn_bdivmod (mp_ptr qp, mp_ptr up, mp_size_t usize, + mp_srcptr vp, mp_size_t vsize, unsigned long int d) +#else +mpn_bdivmod (qp, up, usize, vp, vsize, d) + mp_ptr qp; + mp_ptr up; + mp_size_t usize; + mp_srcptr vp; + mp_size_t vsize; + unsigned long int d; +#endif +{ + /* Cache for v_inv is used to make mpn_accelgcd faster. */ + static mp_limb_t previous_low_vlimb = 0; + static mp_limb_t v_inv; /* 1/V mod 2^BITS_PER_MP_LIMB. */ + + if (vp[0] != previous_low_vlimb) /* Cache miss; compute v_inv. */ + { + mp_limb_t v = previous_low_vlimb = vp[0]; + mp_limb_t make_zero = 1; + mp_limb_t two_i = 1; + v_inv = 0; + do + { + while ((two_i & make_zero) == 0) + two_i <<= 1, v <<= 1; + v_inv += two_i; + make_zero -= v; + } + while (make_zero); + } + + /* Need faster computation for some common cases in mpn_accelgcd. */ + if (usize == 2 && vsize == 2 && + (d == BITS_PER_MP_LIMB || d == 2*BITS_PER_MP_LIMB)) + { + mp_limb_t hi, lo; + mp_limb_t q = up[0] * v_inv; + umul_ppmm (hi, lo, q, vp[0]); + up[0] = 0, up[1] -= hi + q*vp[1], qp[0] = q; + if (d == 2*BITS_PER_MP_LIMB) + q = up[1] * v_inv, up[1] = 0, qp[1] = q; + return 0; + } + + /* Main loop. */ + while (d >= BITS_PER_MP_LIMB) + { + mp_limb_t q = up[0] * v_inv; + mp_limb_t b = mpn_submul_1 (up, vp, MIN (usize, vsize), q); + if (usize > vsize) + mpn_sub_1 (up + vsize, up + vsize, usize - vsize, b); + d -= BITS_PER_MP_LIMB; + up += 1, usize -= 1; + *qp++ = q; + } + + if (d) + { + mp_limb_t b; + mp_limb_t q = (up[0] * v_inv) & (((mp_limb_t)1<<d) - 1); + switch (q) + { + case 0: return 0; + case 1: b = mpn_sub_n (up, up, vp, MIN (usize, vsize)); break; + default: b = mpn_submul_1 (up, vp, MIN (usize, vsize), q); break; + } + if (usize > vsize) + mpn_sub_1 (up + vsize, up + vsize, usize - vsize, b); + return q; + } + + return 0; +} diff --git a/contrib/libgmp/mpn/generic/cmp.c b/contrib/libgmp/mpn/generic/cmp.c new file mode 100644 index 0000000..4e9c60d --- /dev/null +++ b/contrib/libgmp/mpn/generic/cmp.c @@ -0,0 +1,56 @@ +/* mpn_cmp -- Compare two low-level natural-number integers. + +Copyright (C) 1991, 1993, 1994, 1996 Free Software Foundation, Inc. + +This file is part of the GNU MP Library. + +The GNU MP Library is free software; you can redistribute it and/or modify +it under the terms of the GNU Library General Public License as published by +the Free Software Foundation; either version 2 of the License, or (at your +option) any later version. + +The GNU MP Library is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public +License for more details. + +You should have received a copy of the GNU Library General Public License +along with the GNU MP Library; see the file COPYING.LIB. If not, write to +the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, +MA 02111-1307, USA. */ + +#include "gmp.h" +#include "gmp-impl.h" + +/* Compare OP1_PTR/OP1_SIZE with OP2_PTR/OP2_SIZE. + There are no restrictions on the relative sizes of + the two arguments. + Return 1 if OP1 > OP2, 0 if they are equal, and -1 if OP1 < OP2. */ + +int +#if __STDC__ +mpn_cmp (mp_srcptr op1_ptr, mp_srcptr op2_ptr, mp_size_t size) +#else +mpn_cmp (op1_ptr, op2_ptr, size) + mp_srcptr op1_ptr; + mp_srcptr op2_ptr; + mp_size_t size; +#endif +{ + mp_size_t i; + mp_limb_t op1_word, op2_word; + + for (i = size - 1; i >= 0; i--) + { + op1_word = op1_ptr[i]; + op2_word = op2_ptr[i]; + if (op1_word != op2_word) + goto diff; + } + return 0; + diff: + /* This can *not* be simplified to + op2_word - op2_word + since that expression might give signed overflow. */ + return (op1_word > op2_word) ? 1 : -1; +} diff --git a/contrib/libgmp/mpn/generic/divmod_1.c b/contrib/libgmp/mpn/generic/divmod_1.c new file mode 100644 index 0000000..f93841f --- /dev/null +++ b/contrib/libgmp/mpn/generic/divmod_1.c @@ -0,0 +1,208 @@ +/* mpn_divmod_1(quot_ptr, dividend_ptr, dividend_size, divisor_limb) -- + Divide (DIVIDEND_PTR,,DIVIDEND_SIZE) by DIVISOR_LIMB. + Write DIVIDEND_SIZE limbs of quotient at QUOT_PTR. + Return the single-limb remainder. + There are no constraints on the value of the divisor. + + QUOT_PTR and DIVIDEND_PTR might point to the same limb. + +Copyright (C) 1991, 1993, 1994, 1996 Free Software Foundation, Inc. + +This file is part of the GNU MP Library. + +The GNU MP Library is free software; you can redistribute it and/or modify +it under the terms of the GNU Library General Public License as published by +the Free Software Foundation; either version 2 of the License, or (at your +option) any later version. + +The GNU MP Library is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public +License for more details. + +You should have received a copy of the GNU Library General Public License +along with the GNU MP Library; see the file COPYING.LIB. If not, write to +the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, +MA 02111-1307, USA. */ + +#include "gmp.h" +#include "gmp-impl.h" +#include "longlong.h" + +#ifndef UMUL_TIME +#define UMUL_TIME 1 +#endif + +#ifndef UDIV_TIME +#define UDIV_TIME UMUL_TIME +#endif + +/* FIXME: We should be using invert_limb (or invert_normalized_limb) + here (not udiv_qrnnd). */ + +mp_limb_t +#if __STDC__ +mpn_divmod_1 (mp_ptr quot_ptr, + mp_srcptr dividend_ptr, mp_size_t dividend_size, + mp_limb_t divisor_limb) +#else +mpn_divmod_1 (quot_ptr, dividend_ptr, dividend_size, divisor_limb) + mp_ptr quot_ptr; + mp_srcptr dividend_ptr; + mp_size_t dividend_size; + mp_limb_t divisor_limb; +#endif +{ + mp_size_t i; + mp_limb_t n1, n0, r; + int dummy; + + /* ??? Should this be handled at all? Rely on callers? */ + if (dividend_size == 0) + return 0; + + /* If multiplication is much faster than division, and the + dividend is large, pre-invert the divisor, and use + only multiplications in the inner loop. */ + + /* This test should be read: + Does it ever help to use udiv_qrnnd_preinv? + && Does what we save compensate for the inversion overhead? */ + if (UDIV_TIME > (2 * UMUL_TIME + 6) + && (UDIV_TIME - (2 * UMUL_TIME + 6)) * dividend_size > UDIV_TIME) + { + int normalization_steps; + + count_leading_zeros (normalization_steps, divisor_limb); + if (normalization_steps != 0) + { + mp_limb_t divisor_limb_inverted; + + divisor_limb <<= normalization_steps; + + /* Compute (2**2N - 2**N * DIVISOR_LIMB) / DIVISOR_LIMB. The + result is a (N+1)-bit approximation to 1/DIVISOR_LIMB, with the + most significant bit (with weight 2**N) implicit. */ + + /* Special case for DIVISOR_LIMB == 100...000. */ + if (divisor_limb << 1 == 0) + divisor_limb_inverted = ~(mp_limb_t) 0; + else + udiv_qrnnd (divisor_limb_inverted, dummy, + -divisor_limb, 0, divisor_limb); + + n1 = dividend_ptr[dividend_size - 1]; + r = n1 >> (BITS_PER_MP_LIMB - normalization_steps); + + /* Possible optimization: + if (r == 0 + && divisor_limb > ((n1 << normalization_steps) + | (dividend_ptr[dividend_size - 2] >> ...))) + ...one division less... */ + + for (i = dividend_size - 2; i >= 0; i--) + { + n0 = dividend_ptr[i]; + udiv_qrnnd_preinv (quot_ptr[i + 1], r, r, + ((n1 << normalization_steps) + | (n0 >> (BITS_PER_MP_LIMB - normalization_steps))), + divisor_limb, divisor_limb_inverted); + n1 = n0; + } + udiv_qrnnd_preinv (quot_ptr[0], r, r, + n1 << normalization_steps, + divisor_limb, divisor_limb_inverted); + return r >> normalization_steps; + } + else + { + mp_limb_t divisor_limb_inverted; + + /* Compute (2**2N - 2**N * DIVISOR_LIMB) / DIVISOR_LIMB. The + result is a (N+1)-bit approximation to 1/DIVISOR_LIMB, with the + most significant bit (with weight 2**N) implicit. */ + + /* Special case for DIVISOR_LIMB == 100...000. */ + if (divisor_limb << 1 == 0) + divisor_limb_inverted = ~(mp_limb_t) 0; + else + udiv_qrnnd (divisor_limb_inverted, dummy, + -divisor_limb, 0, divisor_limb); + + i = dividend_size - 1; + r = dividend_ptr[i]; + + if (r >= divisor_limb) + r = 0; + else + { + quot_ptr[i] = 0; + i--; + } + + for (; i >= 0; i--) + { + n0 = dividend_ptr[i]; + udiv_qrnnd_preinv (quot_ptr[i], r, r, + n0, divisor_limb, divisor_limb_inverted); + } + return r; + } + } + else + { + if (UDIV_NEEDS_NORMALIZATION) + { + int normalization_steps; + + count_leading_zeros (normalization_steps, divisor_limb); + if (normalization_steps != 0) + { + divisor_limb <<= normalization_steps; + + n1 = dividend_ptr[dividend_size - 1]; + r = n1 >> (BITS_PER_MP_LIMB - normalization_steps); + + /* Possible optimization: + if (r == 0 + && divisor_limb > ((n1 << normalization_steps) + | (dividend_ptr[dividend_size - 2] >> ...))) + ...one division less... */ + + for (i = dividend_size - 2; i >= 0; i--) + { + n0 = dividend_ptr[i]; + udiv_qrnnd (quot_ptr[i + 1], r, r, + ((n1 << normalization_steps) + | (n0 >> (BITS_PER_MP_LIMB - normalization_steps))), + divisor_limb); + n1 = n0; + } + udiv_qrnnd (quot_ptr[0], r, r, + n1 << normalization_steps, + divisor_limb); + return r >> normalization_steps; + } + } + /* No normalization needed, either because udiv_qrnnd doesn't require + it, or because DIVISOR_LIMB is already normalized. */ + + i = dividend_size - 1; + r = dividend_ptr[i]; + + if (r >= divisor_limb) + r = 0; + else + { + quot_ptr[i] = 0; + i--; + } + + for (; i >= 0; i--) + { + n0 = dividend_ptr[i]; + udiv_qrnnd (quot_ptr[i], r, r, n0, divisor_limb); + } + return r; + } +} diff --git a/contrib/libgmp/mpn/generic/divrem.c b/contrib/libgmp/mpn/generic/divrem.c new file mode 100644 index 0000000..1fe865a --- /dev/null +++ b/contrib/libgmp/mpn/generic/divrem.c @@ -0,0 +1,245 @@ +/* mpn_divrem -- Divide natural numbers, producing both remainder and + quotient. + +Copyright (C) 1993, 1994, 1995, 1996 Free Software Foundation, Inc. + +This file is part of the GNU MP Library. + +The GNU MP Library is free software; you can redistribute it and/or modify +it under the terms of the GNU Library General Public License as published by +the Free Software Foundation; either version 2 of the License, or (at your +option) any later version. + +The GNU MP Library is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public +License for more details. + +You should have received a copy of the GNU Library General Public License +along with the GNU MP Library; see the file COPYING.LIB. If not, write to +the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, +MA 02111-1307, USA. */ + +#include "gmp.h" +#include "gmp-impl.h" +#include "longlong.h" + +/* Divide num (NP/NSIZE) by den (DP/DSIZE) and write + the NSIZE-DSIZE least significant quotient limbs at QP + and the DSIZE long remainder at NP. If QEXTRA_LIMBS is + non-zero, generate that many fraction bits and append them after the + other quotient limbs. + Return the most significant limb of the quotient, this is always 0 or 1. + + Preconditions: + 0. NSIZE >= DSIZE. + 1. The most significant bit of the divisor must be set. + 2. QP must either not overlap with the input operands at all, or + QP + DSIZE >= NP must hold true. (This means that it's + possible to put the quotient in the high part of NUM, right after the + remainder in NUM. + 3. NSIZE >= DSIZE, even if QEXTRA_LIMBS is non-zero. */ + +mp_limb_t +#if __STDC__ +mpn_divrem (mp_ptr qp, mp_size_t qextra_limbs, + mp_ptr np, mp_size_t nsize, + mp_srcptr dp, mp_size_t dsize) +#else +mpn_divrem (qp, qextra_limbs, np, nsize, dp, dsize) + mp_ptr qp; + mp_size_t qextra_limbs; + mp_ptr np; + mp_size_t nsize; + mp_srcptr dp; + mp_size_t dsize; +#endif +{ + mp_limb_t most_significant_q_limb = 0; + + switch (dsize) + { + case 0: + /* We are asked to divide by zero, so go ahead and do it! (To make + the compiler not remove this statement, return the value.) */ + return 1 / dsize; + + case 1: + { + mp_size_t i; + mp_limb_t n1; + mp_limb_t d; + + d = dp[0]; + n1 = np[nsize - 1]; + + if (n1 >= d) + { + n1 -= d; + most_significant_q_limb = 1; + } + + qp += qextra_limbs; + for (i = nsize - 2; i >= 0; i--) + udiv_qrnnd (qp[i], n1, n1, np[i], d); + qp -= qextra_limbs; + + for (i = qextra_limbs - 1; i >= 0; i--) + udiv_qrnnd (qp[i], n1, n1, 0, d); + + np[0] = n1; + } + break; + + case 2: + { + mp_size_t i; + mp_limb_t n1, n0, n2; + mp_limb_t d1, d0; + + np += nsize - 2; + d1 = dp[1]; + d0 = dp[0]; + n1 = np[1]; + n0 = np[0]; + + if (n1 >= d1 && (n1 > d1 || n0 >= d0)) + { + sub_ddmmss (n1, n0, n1, n0, d1, d0); + most_significant_q_limb = 1; + } + + for (i = qextra_limbs + nsize - 2 - 1; i >= 0; i--) + { + mp_limb_t q; + mp_limb_t r; + + if (i >= qextra_limbs) + np--; + else + np[0] = 0; + + if (n1 == d1) + { + /* Q should be either 111..111 or 111..110. Need special + treatment of this rare case as normal division would + give overflow. */ + q = ~(mp_limb_t) 0; + + r = n0 + d1; + if (r < d1) /* Carry in the addition? */ + { + add_ssaaaa (n1, n0, r - d0, np[0], 0, d0); + qp[i] = q; + continue; + } + n1 = d0 - (d0 != 0); + n0 = -d0; + } + else + { + udiv_qrnnd (q, r, n1, n0, d1); + umul_ppmm (n1, n0, d0, q); + } + + n2 = np[0]; + q_test: + if (n1 > r || (n1 == r && n0 > n2)) + { + /* The estimated Q was too large. */ + q--; + + sub_ddmmss (n1, n0, n1, n0, 0, d0); + r += d1; + if (r >= d1) /* If not carry, test Q again. */ + goto q_test; + } + + qp[i] = q; + sub_ddmmss (n1, n0, r, n2, n1, n0); + } + np[1] = n1; + np[0] = n0; + } + break; + + default: + { + mp_size_t i; + mp_limb_t dX, d1, n0; + + np += nsize - dsize; + dX = dp[dsize - 1]; + d1 = dp[dsize - 2]; + n0 = np[dsize - 1]; + + if (n0 >= dX) + { + if (n0 > dX || mpn_cmp (np, dp, dsize - 1) >= 0) + { + mpn_sub_n (np, np, dp, dsize); + n0 = np[dsize - 1]; + most_significant_q_limb = 1; + } + } + + for (i = qextra_limbs + nsize - dsize - 1; i >= 0; i--) + { + mp_limb_t q; + mp_limb_t n1, n2; + mp_limb_t cy_limb; + + if (i >= qextra_limbs) + { + np--; + n2 = np[dsize]; + } + else + { + n2 = np[dsize - 1]; + MPN_COPY_DECR (np + 1, np, dsize); + np[0] = 0; + } + + if (n0 == dX) + /* This might over-estimate q, but it's probably not worth + the extra code here to find out. */ + q = ~(mp_limb_t) 0; + else + { + mp_limb_t r; + + udiv_qrnnd (q, r, n0, np[dsize - 1], dX); + umul_ppmm (n1, n0, d1, q); + + while (n1 > r || (n1 == r && n0 > np[dsize - 2])) + { + q--; + r += dX; + if (r < dX) /* I.e. "carry in previous addition?" */ + break; + n1 -= n0 < d1; + n0 -= d1; + } + } + + /* Possible optimization: We already have (q * n0) and (1 * n1) + after the calculation of q. Taking advantage of that, we + could make this loop make two iterations less. */ + + cy_limb = mpn_submul_1 (np, dp, dsize, q); + + if (n2 != cy_limb) + { + mpn_add_n (np, np, dp, dsize); + q--; + } + + qp[i] = q; + n0 = np[dsize - 1]; + } + } + } + + return most_significant_q_limb; +} diff --git a/contrib/libgmp/mpn/generic/divrem_1.c b/contrib/libgmp/mpn/generic/divrem_1.c new file mode 100644 index 0000000..d213267 --- /dev/null +++ b/contrib/libgmp/mpn/generic/divrem_1.c @@ -0,0 +1,58 @@ +/* mpn_divrem_1(quot_ptr, qsize, dividend_ptr, dividend_size, divisor_limb) -- + Divide (DIVIDEND_PTR,,DIVIDEND_SIZE) by DIVISOR_LIMB. + Write DIVIDEND_SIZE limbs of quotient at QUOT_PTR. + Return the single-limb remainder. + There are no constraints on the value of the divisor. + + QUOT_PTR and DIVIDEND_PTR might point to the same limb. + +Copyright (C) 1996 Free Software Foundation, Inc. + +This file is part of the GNU MP Library. + +The GNU MP Library is free software; you can redistribute it and/or modify +it under the terms of the GNU Library General Public License as published by +the Free Software Foundation; either version 2 of the License, or (at your +option) any later version. + +The GNU MP Library is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public +License for more details. + +You should have received a copy of the GNU Library General Public License +along with the GNU MP Library; see the file COPYING.LIB. If not, write to +the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, +MA 02111-1307, USA. */ + +#include "gmp.h" +#include "gmp-impl.h" +#include "longlong.h" + +mp_limb_t +#if __STDC__ +mpn_divrem_1 (mp_ptr qp, mp_size_t qsize, + mp_srcptr dividend_ptr, mp_size_t dividend_size, + mp_limb_t divisor_limb) +#else +mpn_divrem_1 (qp, qsize, dividend_ptr, dividend_size, divisor_limb) + mp_ptr qp; + mp_size_t qsize; + mp_srcptr dividend_ptr; + mp_size_t dividend_size; + mp_limb_t divisor_limb; +#endif +{ + mp_limb_t rlimb; + long i; + + /* Develop integer part of quotient. */ + rlimb = mpn_divmod_1 (qp + qsize, dividend_ptr, dividend_size, divisor_limb); + + if (qsize != 0) + { + for (i = qsize - 1; i >= 0; i--) + udiv_qrnnd (qp[i], rlimb, rlimb, 0, divisor_limb); + } + return rlimb; +} diff --git a/contrib/libgmp/mpn/generic/dump.c b/contrib/libgmp/mpn/generic/dump.c new file mode 100644 index 0000000..a5831c4 --- /dev/null +++ b/contrib/libgmp/mpn/generic/dump.c @@ -0,0 +1,20 @@ +#include <stdio.h> +#include "gmp.h" +#include "gmp-impl.h" + +void +mpn_dump (ptr, size) + mp_srcptr ptr; + mp_size_t size; +{ + if (size == 0) + printf ("0\n"); + { + while (size) + { + size--; + printf ("%0*lX", (int) (2 * BYTES_PER_MP_LIMB), ptr[size]); + } + printf ("\n"); + } +} diff --git a/contrib/libgmp/mpn/generic/gcd.c b/contrib/libgmp/mpn/generic/gcd.c new file mode 100644 index 0000000..8c2bbf0 --- /dev/null +++ b/contrib/libgmp/mpn/generic/gcd.c @@ -0,0 +1,402 @@ +/* mpn/gcd.c: mpn_gcd for gcd of two odd integers. + +Copyright (C) 1991, 1993, 1994, 1995, 1996 Free Software Foundation, Inc. + +This file is part of the GNU MP Library. + +The GNU MP Library is free software; you can redistribute it and/or modify +it under the terms of the GNU Library General Public License as published by +the Free Software Foundation; either version 2 of the License, or (at your +option) any later version. + +The GNU MP Library is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public +License for more details. + +You should have received a copy of the GNU Library General Public License +along with the GNU MP Library; see the file COPYING.LIB. If not, write to +the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, +MA 02111-1307, USA. */ + +/* Integer greatest common divisor of two unsigned integers, using + the accelerated algorithm (see reference below). + + mp_size_t mpn_gcd (vp, vsize, up, usize). + + Preconditions [U = (up, usize) and V = (vp, vsize)]: + + 1. V is odd. + 2. numbits(U) >= numbits(V). + + Both U and V are destroyed by the operation. The result is left at vp, + and its size is returned. + + Ken Weber (kweber@mat.ufrgs.br, kweber@mcs.kent.edu) + + Funding for this work has been partially provided by Conselho Nacional + de Desenvolvimento Cienti'fico e Tecnolo'gico (CNPq) do Brazil, Grant + 301314194-2, and was done while I was a visiting reseacher in the Instituto + de Matema'tica at Universidade Federal do Rio Grande do Sul (UFRGS). + + Refer to + K. Weber, The accelerated integer GCD algorithm, ACM Transactions on + Mathematical Software, v. 21 (March), 1995, pp. 111-122. */ + +#include "gmp.h" +#include "gmp-impl.h" +#include "longlong.h" + +/* If MIN (usize, vsize) > ACCEL_THRESHOLD, then the accelerated algorithm is + used, otherwise the binary algorithm is used. This may be adjusted for + different architectures. */ +#ifndef ACCEL_THRESHOLD +#define ACCEL_THRESHOLD 4 +#endif + +/* When U and V differ in size by more than BMOD_THRESHOLD, the accelerated + algorithm reduces using the bmod operation. Otherwise, the k-ary reduction + is used. 0 <= BMOD_THRESHOLD < BITS_PER_MP_LIMB. */ +enum + { + BMOD_THRESHOLD = BITS_PER_MP_LIMB/2 + }; + +#define SIGN_BIT (~(~(mp_limb_t)0 >> 1)) + + +#define SWAP_LIMB(UL, VL) do{mp_limb_t __l=(UL);(UL)=(VL);(VL)=__l;}while(0) +#define SWAP_PTR(UP, VP) do{mp_ptr __p=(UP);(UP)=(VP);(VP)=__p;}while(0) +#define SWAP_SZ(US, VS) do{mp_size_t __s=(US);(US)=(VS);(VS)=__s;}while(0) +#define SWAP_MPN(UP, US, VP, VS) do{SWAP_PTR(UP,VP);SWAP_SZ(US,VS);}while(0) + +/* Use binary algorithm to compute V <-- GCD (V, U) for usize, vsize == 2. + Both U and V must be odd. */ +static __gmp_inline mp_size_t +#if __STDC__ +gcd_2 (mp_ptr vp, mp_srcptr up) +#else +gcd_2 (vp, up) + mp_ptr vp; + mp_srcptr up; +#endif +{ + mp_limb_t u0, u1, v0, v1; + mp_size_t vsize; + + u0 = up[0], u1 = up[1], v0 = vp[0], v1 = vp[1]; + + while (u1 != v1 && u0 != v0) + { + unsigned long int r; + if (u1 > v1) + { + u1 -= v1 + (u0 < v0), u0 -= v0; + count_trailing_zeros (r, u0); + u0 = u1 << (BITS_PER_MP_LIMB - r) | u0 >> r; + u1 >>= r; + } + else /* u1 < v1. */ + { + v1 -= u1 + (v0 < u0), v0 -= u0; + count_trailing_zeros (r, v0); + v0 = v1 << (BITS_PER_MP_LIMB - r) | v0 >> r; + v1 >>= r; + } + } + + vp[0] = v0, vp[1] = v1, vsize = 1 + (v1 != 0); + + /* If U == V == GCD, done. Otherwise, compute GCD (V, |U - V|). */ + if (u1 == v1 && u0 == v0) + return vsize; + + v0 = (u0 == v0) ? (u1 > v1) ? u1-v1 : v1-u1 : (u0 > v0) ? u0-v0 : v0-u0; + vp[0] = mpn_gcd_1 (vp, vsize, v0); + + return 1; +} + +/* The function find_a finds 0 < N < 2^BITS_PER_MP_LIMB such that there exists + 0 < |D| < 2^BITS_PER_MP_LIMB, and N == D * C mod 2^(2*BITS_PER_MP_LIMB). + In the reference article, D was computed along with N, but it is better to + compute D separately as D <-- N / C mod 2^(BITS_PER_MP_LIMB + 1), treating + the result as a twos' complement signed integer. + + Initialize N1 to C mod 2^(2*BITS_PER_MP_LIMB). According to the reference + article, N2 should be initialized to 2^(2*BITS_PER_MP_LIMB), but we use + 2^(2*BITS_PER_MP_LIMB) - N1 to start the calculations within double + precision. If N2 > N1 initially, the first iteration of the while loop + will swap them. In all other situations, N1 >= N2 is maintained. */ + +static __gmp_inline mp_limb_t +#if __STDC__ +find_a (mp_srcptr cp) +#else +find_a (cp) + mp_srcptr cp; +#endif +{ + unsigned long int leading_zero_bits = 0; + + mp_limb_t n1_l = cp[0]; /* N1 == n1_h * 2^BITS_PER_MP_LIMB + n1_l. */ + mp_limb_t n1_h = cp[1]; + + mp_limb_t n2_l = -n1_l; /* N2 == n2_h * 2^BITS_PER_MP_LIMB + n2_l. */ + mp_limb_t n2_h = ~n1_h; + + /* Main loop. */ + while (n2_h) /* While N2 >= 2^BITS_PER_MP_LIMB. */ + { + /* N1 <-- N1 % N2. */ + if ((SIGN_BIT >> leading_zero_bits & n2_h) == 0) + { + unsigned long int i; + count_leading_zeros (i, n2_h); + i -= leading_zero_bits, leading_zero_bits += i; + n2_h = n2_h<<i | n2_l>>(BITS_PER_MP_LIMB - i), n2_l <<= i; + do + { + if (n1_h > n2_h || (n1_h == n2_h && n1_l >= n2_l)) + n1_h -= n2_h + (n1_l < n2_l), n1_l -= n2_l; + n2_l = n2_l>>1 | n2_h<<(BITS_PER_MP_LIMB - 1), n2_h >>= 1; + i -= 1; + } + while (i); + } + if (n1_h > n2_h || (n1_h == n2_h && n1_l >= n2_l)) + n1_h -= n2_h + (n1_l < n2_l), n1_l -= n2_l; + + SWAP_LIMB (n1_h, n2_h); + SWAP_LIMB (n1_l, n2_l); + } + + return n2_l; +} + +mp_size_t +#if __STDC__ +mpn_gcd (mp_ptr gp, mp_ptr vp, mp_size_t vsize, mp_ptr up, mp_size_t usize) +#else +mpn_gcd (gp, vp, vsize, up, usize) + mp_ptr gp; + mp_ptr vp; + mp_size_t vsize; + mp_ptr up; + mp_size_t usize; +#endif +{ + mp_ptr orig_vp = vp; + mp_size_t orig_vsize = vsize; + int binary_gcd_ctr; /* Number of times binary gcd will execute. */ + TMP_DECL (marker); + + TMP_MARK (marker); + + /* Use accelerated algorithm if vsize is over ACCEL_THRESHOLD. + Two EXTRA limbs for U and V are required for kary reduction. */ + if (vsize > ACCEL_THRESHOLD) + { + unsigned long int vbitsize, d; + mp_ptr orig_up = up; + mp_size_t orig_usize = usize; + mp_ptr anchor_up = (mp_ptr) TMP_ALLOC ((usize + 2) * BYTES_PER_MP_LIMB); + + MPN_COPY (anchor_up, orig_up, usize); + up = anchor_up; + + count_leading_zeros (d, up[usize-1]); + d = usize * BITS_PER_MP_LIMB - d; + count_leading_zeros (vbitsize, vp[vsize-1]); + vbitsize = vsize * BITS_PER_MP_LIMB - vbitsize; + d = d - vbitsize + 1; + + /* Use bmod reduction to quickly discover whether V divides U. */ + up[usize++] = 0; /* Insert leading zero. */ + mpn_bdivmod (up, up, usize, vp, vsize, d); + + /* Now skip U/V mod 2^d and any low zero limbs. */ + d /= BITS_PER_MP_LIMB, up += d, usize -= d; + while (usize != 0 && up[0] == 0) + up++, usize--; + + if (usize == 0) /* GCD == ORIG_V. */ + goto done; + + vp = (mp_ptr) TMP_ALLOC ((vsize + 2) * BYTES_PER_MP_LIMB); + MPN_COPY (vp, orig_vp, vsize); + + do /* Main loop. */ + { + if (up[usize-1] & SIGN_BIT) /* U < 0; take twos' compl. */ + { + mp_size_t i; + anchor_up[0] = -up[0]; + for (i = 1; i < usize; i++) + anchor_up[i] = ~up[i]; + up = anchor_up; + } + + MPN_NORMALIZE_NOT_ZERO (up, usize); + + if ((up[0] & 1) == 0) /* Result even; remove twos. */ + { + unsigned long int r; + count_trailing_zeros (r, up[0]); + mpn_rshift (anchor_up, up, usize, r); + usize -= (anchor_up[usize-1] == 0); + } + else if (anchor_up != up) + MPN_COPY (anchor_up, up, usize); + + SWAP_MPN (anchor_up, usize, vp, vsize); + up = anchor_up; + + if (vsize <= 2) /* Kary can't handle < 2 limbs and */ + break; /* isn't efficient for == 2 limbs. */ + + d = vbitsize; + count_leading_zeros (vbitsize, vp[vsize-1]); + vbitsize = vsize * BITS_PER_MP_LIMB - vbitsize; + d = d - vbitsize + 1; + + if (d > BMOD_THRESHOLD) /* Bmod reduction. */ + { + up[usize++] = 0; + mpn_bdivmod (up, up, usize, vp, vsize, d); + d /= BITS_PER_MP_LIMB, up += d, usize -= d; + } + else /* Kary reduction. */ + { + mp_limb_t bp[2], cp[2]; + + /* C <-- V/U mod 2^(2*BITS_PER_MP_LIMB). */ + cp[0] = vp[0], cp[1] = vp[1]; + mpn_bdivmod (cp, cp, 2, up, 2, 2*BITS_PER_MP_LIMB); + + /* U <-- find_a (C) * U. */ + up[usize] = mpn_mul_1 (up, up, usize, find_a (cp)); + usize++; + + /* B <-- A/C == U/V mod 2^(BITS_PER_MP_LIMB + 1). + bp[0] <-- U/V mod 2^BITS_PER_MP_LIMB and + bp[1] <-- ( (U - bp[0] * V)/2^BITS_PER_MP_LIMB ) / V mod 2 */ + bp[0] = up[0], bp[1] = up[1]; + mpn_bdivmod (bp, bp, 2, vp, 2, BITS_PER_MP_LIMB); + bp[1] &= 1; /* Since V is odd, division is unnecessary. */ + + up[usize++] = 0; + if (bp[1]) /* B < 0: U <-- U + (-B) * V. */ + { + mp_limb_t c = mpn_addmul_1 (up, vp, vsize, -bp[0]); + mpn_add_1 (up + vsize, up + vsize, usize - vsize, c); + } + else /* B >= 0: U <-- U - B * V. */ + { + mp_limb_t b = mpn_submul_1 (up, vp, vsize, bp[0]); + mpn_sub_1 (up + vsize, up + vsize, usize - vsize, b); + } + + up += 2, usize -= 2; /* At least two low limbs are zero. */ + } + + /* Must remove low zero limbs before complementing. */ + while (usize != 0 && up[0] == 0) + up++, usize--; + } + while (usize); + + /* Compute GCD (ORIG_V, GCD (ORIG_U, V)). Binary will execute twice. */ + up = orig_up, usize = orig_usize; + binary_gcd_ctr = 2; + } + else + binary_gcd_ctr = 1; + + /* Finish up with the binary algorithm. Executes once or twice. */ + for ( ; binary_gcd_ctr--; up = orig_vp, usize = orig_vsize) + { + if (usize > 2) /* First make U close to V in size. */ + { + unsigned long int vbitsize, d; + count_leading_zeros (d, up[usize-1]); + d = usize * BITS_PER_MP_LIMB - d; + count_leading_zeros (vbitsize, vp[vsize-1]); + vbitsize = vsize * BITS_PER_MP_LIMB - vbitsize; + d = d - vbitsize - 1; + if (d != -(unsigned long int)1 && d > 2) + { + mpn_bdivmod (up, up, usize, vp, vsize, d); /* Result > 0. */ + d /= (unsigned long int)BITS_PER_MP_LIMB, up += d, usize -= d; + } + } + + /* Start binary GCD. */ + do + { + mp_size_t zeros; + + /* Make sure U is odd. */ + MPN_NORMALIZE (up, usize); + while (up[0] == 0) + up += 1, usize -= 1; + if ((up[0] & 1) == 0) + { + unsigned long int r; + count_trailing_zeros (r, up[0]); + mpn_rshift (up, up, usize, r); + usize -= (up[usize-1] == 0); + } + + /* Keep usize >= vsize. */ + if (usize < vsize) + SWAP_MPN (up, usize, vp, vsize); + + if (usize <= 2) /* Double precision. */ + { + if (vsize == 1) + vp[0] = mpn_gcd_1 (up, usize, vp[0]); + else + vsize = gcd_2 (vp, up); + break; /* Binary GCD done. */ + } + + /* Count number of low zero limbs of U - V. */ + for (zeros = 0; up[zeros] == vp[zeros] && ++zeros != vsize; ) + continue; + + /* If U < V, swap U and V; in any case, subtract V from U. */ + if (zeros == vsize) /* Subtract done. */ + up += zeros, usize -= zeros; + else if (usize == vsize) + { + mp_size_t size = vsize; + do + size--; + while (up[size] == vp[size]); + if (up[size] < vp[size]) /* usize == vsize. */ + SWAP_PTR (up, vp); + up += zeros, usize = size + 1 - zeros; + mpn_sub_n (up, up, vp + zeros, usize); + } + else + { + mp_size_t size = vsize - zeros; + up += zeros, usize -= zeros; + if (mpn_sub_n (up, up, vp + zeros, size)) + { + while (up[size] == 0) /* Propagate borrow. */ + up[size++] = -(mp_limb_t)1; + up[size] -= 1; + } + } + } + while (usize); /* End binary GCD. */ + } + +done: + if (vp != gp) + MPN_COPY (gp, vp, vsize); + TMP_FREE (marker); + return vsize; +} diff --git a/contrib/libgmp/mpn/generic/gcd_1.c b/contrib/libgmp/mpn/generic/gcd_1.c new file mode 100644 index 0000000..ebcdfb5 --- /dev/null +++ b/contrib/libgmp/mpn/generic/gcd_1.c @@ -0,0 +1,73 @@ +/* mpn_gcd_1 -- + +Copyright (C) 1994, 1996 Free Software Foundation, Inc. + +This file is part of the GNU MP Library. + +The GNU MP Library is free software; you can redistribute it and/or modify +it under the terms of the GNU Library General Public License as published by +the Free Software Foundation; either version 2 of the License, or (at your +option) any later version. + +The GNU MP Library is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public +License for more details. + +You should have received a copy of the GNU Library General Public License +along with the GNU MP Library; see the file COPYING.LIB. If not, write to +the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, +MA 02111-1307, USA. */ + +#include "gmp.h" +#include "gmp-impl.h" +#include "longlong.h" + +/* Does not work for U == 0 or V == 0. It would be tough to make it work for + V == 0 since gcd(x,0) = x, and U does not generally fit in an mp_limb_t. */ + +mp_limb_t +mpn_gcd_1 (up, size, vlimb) + mp_srcptr up; + mp_size_t size; + mp_limb_t vlimb; +{ + mp_limb_t ulimb; + unsigned long int u_low_zero_bits, v_low_zero_bits; + + if (size > 1) + { + ulimb = mpn_mod_1 (up, size, vlimb); + if (ulimb == 0) + return vlimb; + } + else + ulimb = up[0]; + + /* Need to eliminate low zero bits. */ + count_trailing_zeros (u_low_zero_bits, ulimb); + ulimb >>= u_low_zero_bits; + + count_trailing_zeros (v_low_zero_bits, vlimb); + vlimb >>= v_low_zero_bits; + + while (ulimb != vlimb) + { + if (ulimb > vlimb) + { + ulimb -= vlimb; + do + ulimb >>= 1; + while ((ulimb & 1) == 0); + } + else /* vlimb > ulimb. */ + { + vlimb -= ulimb; + do + vlimb >>= 1; + while ((vlimb & 1) == 0); + } + } + + return ulimb << MIN (u_low_zero_bits, v_low_zero_bits); +} diff --git a/contrib/libgmp/mpn/generic/gcdext.c b/contrib/libgmp/mpn/generic/gcdext.c new file mode 100644 index 0000000..245e20a --- /dev/null +++ b/contrib/libgmp/mpn/generic/gcdext.c @@ -0,0 +1,441 @@ +/* mpn_gcdext -- Extended Greatest Common Divisor. + +Copyright (C) 1996 Free Software Foundation, Inc. + +This file is part of the GNU MP Library. + +The GNU MP Library is free software; you can redistribute it and/or modify +it under the terms of the GNU Library General Public License as published by +the Free Software Foundation; either version 2 of the License, or (at your +option) any later version. + +The GNU MP Library is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public +License for more details. + +You should have received a copy of the GNU Library General Public License +along with the GNU MP Library; see the file COPYING.LIB. If not, write to +the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, +MA 02111-1307, USA. */ + +#include "gmp.h" +#include "gmp-impl.h" +#include "longlong.h" + +#ifndef EXTEND +#define EXTEND 1 +#endif + +#if STAT +int arr[BITS_PER_MP_LIMB]; +#endif + +#define SGN(A) (((A) < 0) ? -1 : ((A) > 0)) + +/* Idea 1: After we have performed a full division, don't shift operands back, + but instead account for the extra factors-of-2 thus introduced. + Idea 2: Simple generalization to use divide-and-conquer would give us an + algorithm that runs faster than O(n^2). + Idea 3: The input numbers need less space as the computation progresses, + while the s0 and s1 variables need more space. To save space, we + could make them share space, and have the latter variables grow + into the former. */ + +/* Precondition: U >= V. */ + +mp_size_t +#if EXTEND +#if __STDC__ +mpn_gcdext (mp_ptr gp, mp_ptr s0p, + mp_ptr up, mp_size_t size, mp_ptr vp, mp_size_t vsize) +#else +mpn_gcdext (gp, s0p, up, size, vp, vsize) + mp_ptr gp; + mp_ptr s0p; + mp_ptr up; + mp_size_t size; + mp_ptr vp; + mp_size_t vsize; +#endif +#else +#if __STDC__ +mpn_gcd (mp_ptr gp, + mp_ptr up, mp_size_t size, mp_ptr vp, mp_size_t vsize) +#else +mpn_gcd (gp, up, size, vp, vsize) + mp_ptr gp; + mp_ptr up; + mp_size_t size; + mp_ptr vp; + mp_size_t vsize; +#endif +#endif +{ + mp_limb_t uh, vh; + mp_limb_signed_t A, B, C, D; + int cnt; + mp_ptr tp, wp; +#if RECORD + mp_limb_signed_t min = 0, max = 0; +#endif +#if EXTEND + mp_ptr s1p; + mp_ptr orig_s0p = s0p; + mp_size_t ssize, orig_size = size; + TMP_DECL (mark); + + TMP_MARK (mark); + + tp = (mp_ptr) TMP_ALLOC ((size + 1) * BYTES_PER_MP_LIMB); + wp = (mp_ptr) TMP_ALLOC ((size + 1) * BYTES_PER_MP_LIMB); + s1p = (mp_ptr) TMP_ALLOC (size * BYTES_PER_MP_LIMB); + + MPN_ZERO (s0p, size); + MPN_ZERO (s1p, size); + + s0p[0] = 1; + s1p[0] = 0; + ssize = 1; +#endif + + if (size > vsize) + { + /* Normalize V (and shift up U the same amount). */ + count_leading_zeros (cnt, vp[vsize - 1]); + if (cnt != 0) + { + mp_limb_t cy; + mpn_lshift (vp, vp, vsize, cnt); + cy = mpn_lshift (up, up, size, cnt); + up[size] = cy; + size += cy != 0; + } + + mpn_divmod (up + vsize, up, size, vp, vsize); +#if EXTEND + /* This is really what it boils down to in this case... */ + s0p[0] = 0; + s1p[0] = 1; +#endif + size = vsize; + if (cnt != 0) + { + mpn_rshift (up, up, size, cnt); + mpn_rshift (vp, vp, size, cnt); + } + { + mp_ptr xp; + xp = up; up = vp; vp = xp; + } + } + + for (;;) + { + /* Figure out exact size of V. */ + vsize = size; + MPN_NORMALIZE (vp, vsize); + if (vsize <= 1) + break; + + /* Make UH be the most significant limb of U, and make VH be + corresponding bits from V. */ + uh = up[size - 1]; + vh = vp[size - 1]; + count_leading_zeros (cnt, uh); + if (cnt != 0) + { + uh = (uh << cnt) | (up[size - 2] >> (BITS_PER_MP_LIMB - cnt)); + vh = (vh << cnt) | (vp[size - 2] >> (BITS_PER_MP_LIMB - cnt)); + } + +#if 0 + /* For now, only handle BITS_PER_MP_LIMB-1 bits. This makes + room for sign bit. */ + uh >>= 1; + vh >>= 1; +#endif + A = 1; + B = 0; + C = 0; + D = 1; + + for (;;) + { + mp_limb_signed_t q, T; + if (vh + C == 0 || vh + D == 0) + break; + + q = (uh + A) / (vh + C); + if (q != (uh + B) / (vh + D)) + break; + + T = A - q * C; + A = C; + C = T; + T = B - q * D; + B = D; + D = T; + T = uh - q * vh; + uh = vh; + vh = T; + } + +#if RECORD + min = MIN (A, min); min = MIN (B, min); + min = MIN (C, min); min = MIN (D, min); + max = MAX (A, max); max = MAX (B, max); + max = MAX (C, max); max = MAX (D, max); +#endif + + if (B == 0) + { + mp_limb_t qh; + mp_size_t i; + + /* This is quite rare. I.e., optimize something else! */ + + /* Normalize V (and shift up U the same amount). */ + count_leading_zeros (cnt, vp[vsize - 1]); + if (cnt != 0) + { + mp_limb_t cy; + mpn_lshift (vp, vp, vsize, cnt); + cy = mpn_lshift (up, up, size, cnt); + up[size] = cy; + size += cy != 0; + } + + qh = mpn_divmod (up + vsize, up, size, vp, vsize); +#if EXTEND + MPN_COPY (tp, s0p, ssize); + for (i = 0; i < size - vsize; i++) + { + mp_limb_t cy; + cy = mpn_addmul_1 (tp + i, s1p, ssize, up[vsize + i]); + if (cy != 0) + tp[ssize++] = cy; + } + if (qh != 0) + { + mp_limb_t cy; + abort (); + /* XXX since qh == 1, mpn_addmul_1 is overkill */ + cy = mpn_addmul_1 (tp + size - vsize, s1p, ssize, qh); + if (cy != 0) + tp[ssize++] = cy; + } +#if 0 + MPN_COPY (s0p, s1p, ssize); /* should be old ssize, kind of */ + MPN_COPY (s1p, tp, ssize); +#else + { + mp_ptr xp; + xp = s0p; s0p = s1p; s1p = xp; + xp = s1p; s1p = tp; tp = xp; + } +#endif +#endif + size = vsize; + if (cnt != 0) + { + mpn_rshift (up, up, size, cnt); + mpn_rshift (vp, vp, size, cnt); + } + + { + mp_ptr xp; + xp = up; up = vp; vp = xp; + } + MPN_NORMALIZE (up, size); + } + else + { + /* T = U*A + V*B + W = U*C + V*D + U = T + V = W */ + + if (SGN(A) == SGN(B)) /* should be different sign */ + abort (); + if (SGN(C) == SGN(D)) /* should be different sign */ + abort (); +#if STAT + { mp_limb_t x; + x = ABS (A) | ABS (B) | ABS (C) | ABS (D); + count_leading_zeros (cnt, x); + arr[BITS_PER_MP_LIMB - cnt]++; } +#endif + if (A == 0) + { + if (B != 1) abort (); + MPN_COPY (tp, vp, size); + } + else + { + if (A < 0) + { + mpn_mul_1 (tp, vp, size, B); + mpn_submul_1 (tp, up, size, -A); + } + else + { + mpn_mul_1 (tp, up, size, A); + mpn_submul_1 (tp, vp, size, -B); + } + } + if (C < 0) + { + mpn_mul_1 (wp, vp, size, D); + mpn_submul_1 (wp, up, size, -C); + } + else + { + mpn_mul_1 (wp, up, size, C); + mpn_submul_1 (wp, vp, size, -D); + } + + { + mp_ptr xp; + xp = tp; tp = up; up = xp; + xp = wp; wp = vp; vp = xp; + } + +#if EXTEND + { mp_limb_t cy; + MPN_ZERO (tp, orig_size); + if (A == 0) + { + if (B != 1) abort (); + MPN_COPY (tp, s1p, ssize); + } + else + { + if (A < 0) + { + cy = mpn_mul_1 (tp, s1p, ssize, B); + cy += mpn_addmul_1 (tp, s0p, ssize, -A); + } + else + { + cy = mpn_mul_1 (tp, s0p, ssize, A); + cy += mpn_addmul_1 (tp, s1p, ssize, -B); + } + if (cy != 0) + tp[ssize++] = cy; + } + MPN_ZERO (wp, orig_size); + if (C < 0) + { + cy = mpn_mul_1 (wp, s1p, ssize, D); + cy += mpn_addmul_1 (wp, s0p, ssize, -C); + } + else + { + cy = mpn_mul_1 (wp, s0p, ssize, C); + cy += mpn_addmul_1 (wp, s1p, ssize, -D); + } + if (cy != 0) + wp[ssize++] = cy; + } + { + mp_ptr xp; + xp = tp; tp = s0p; s0p = xp; + xp = wp; wp = s1p; s1p = xp; + } +#endif +#if 0 /* Is it a win to remove multiple zeros here? */ + MPN_NORMALIZE (up, size); +#else + if (up[size - 1] == 0) + size--; +#endif + } + } + +#if RECORD + printf ("min: %ld\n", min); + printf ("max: %ld\n", max); +#endif + + if (vsize == 0) + { + if (gp != up) + MPN_COPY (gp, up, size); +#if EXTEND + if (orig_s0p != s0p) + MPN_COPY (orig_s0p, s0p, ssize); +#endif + TMP_FREE (mark); + return size; + } + else + { + mp_limb_t vl, ul, t; +#if EXTEND + mp_limb_t cy; + mp_size_t i; +#endif + vl = vp[0]; +#if EXTEND + t = mpn_divmod_1 (wp, up, size, vl); + MPN_COPY (tp, s0p, ssize); + for (i = 0; i < size; i++) + { + cy = mpn_addmul_1 (tp + i, s1p, ssize, wp[i]); + if (cy != 0) + tp[ssize++] = cy; + } +#if 0 + MPN_COPY (s0p, s1p, ssize); + MPN_COPY (s1p, tp, ssize); +#else + { + mp_ptr xp; + xp = s0p; s0p = s1p; s1p = xp; + xp = s1p; s1p = tp; tp = xp; + } +#endif +#else + t = mpn_mod_1 (up, size, vl); +#endif + ul = vl; + vl = t; + while (vl != 0) + { + mp_limb_t t; +#if EXTEND + mp_limb_t q, cy; + q = ul / vl; + t = ul - q*vl; + + MPN_COPY (tp, s0p, ssize); + cy = mpn_addmul_1 (tp, s1p, ssize, q); + if (cy != 0) + tp[ssize++] = cy; +#if 0 + MPN_COPY (s0p, s1p, ssize); + MPN_COPY (s1p, tp, ssize); +#else + { + mp_ptr xp; + xp = s0p; s0p = s1p; s1p = xp; + xp = s1p; s1p = tp; tp = xp; + } +#endif + +#else + t = ul % vl; +#endif + ul = vl; + vl = t; + } + gp[0] = ul; +#if EXTEND + if (orig_s0p != s0p) + MPN_COPY (orig_s0p, s0p, ssize); +#endif + TMP_FREE (mark); + return 1; + } +} diff --git a/contrib/libgmp/mpn/generic/get_str.c b/contrib/libgmp/mpn/generic/get_str.c new file mode 100644 index 0000000..0e7fc60 --- /dev/null +++ b/contrib/libgmp/mpn/generic/get_str.c @@ -0,0 +1,211 @@ +/* mpn_get_str -- Convert a MSIZE long limb vector pointed to by MPTR + to a printable string in STR in base BASE. + +Copyright (C) 1991, 1992, 1993, 1994, 1996 Free Software Foundation, Inc. + +This file is part of the GNU MP Library. + +The GNU MP Library is free software; you can redistribute it and/or modify +it under the terms of the GNU Library General Public License as published by +the Free Software Foundation; either version 2 of the License, or (at your +option) any later version. + +The GNU MP Library is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public +License for more details. + +You should have received a copy of the GNU Library General Public License +along with the GNU MP Library; see the file COPYING.LIB. If not, write to +the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, +MA 02111-1307, USA. */ + +#include "gmp.h" +#include "gmp-impl.h" +#include "longlong.h" + +/* Convert the limb vector pointed to by MPTR and MSIZE long to a + char array, using base BASE for the result array. Store the + result in the character array STR. STR must point to an array with + space for the largest possible number represented by a MSIZE long + limb vector + 1 extra character. + + The result is NOT in Ascii, to convert it to printable format, add + '0' or 'A' depending on the base and range. + + Return the number of digits in the result string. + This may include some leading zeros. + + The limb vector pointed to by MPTR is clobbered. */ + +size_t +mpn_get_str (str, base, mptr, msize) + unsigned char *str; + int base; + mp_ptr mptr; + mp_size_t msize; +{ + mp_limb_t big_base; +#if UDIV_NEEDS_NORMALIZATION || UDIV_TIME > 2 * UMUL_TIME + int normalization_steps; +#endif +#if UDIV_TIME > 2 * UMUL_TIME + mp_limb_t big_base_inverted; +#endif + unsigned int dig_per_u; + mp_size_t out_len; + register unsigned char *s; + + big_base = __mp_bases[base].big_base; + + s = str; + + /* Special case zero, as the code below doesn't handle it. */ + if (msize == 0) + { + s[0] = 0; + return 1; + } + + if ((base & (base - 1)) == 0) + { + /* The base is a power of 2. Make conversion from most + significant side. */ + mp_limb_t n1, n0; + register int bits_per_digit = big_base; + register int x; + register int bit_pos; + register int i; + + n1 = mptr[msize - 1]; + count_leading_zeros (x, n1); + + /* BIT_POS should be R when input ends in least sign. nibble, + R + bits_per_digit * n when input ends in n:th least significant + nibble. */ + + { + int bits; + + bits = BITS_PER_MP_LIMB * msize - x; + x = bits % bits_per_digit; + if (x != 0) + bits += bits_per_digit - x; + bit_pos = bits - (msize - 1) * BITS_PER_MP_LIMB; + } + + /* Fast loop for bit output. */ + i = msize - 1; + for (;;) + { + bit_pos -= bits_per_digit; + while (bit_pos >= 0) + { + *s++ = (n1 >> bit_pos) & ((1 << bits_per_digit) - 1); + bit_pos -= bits_per_digit; + } + i--; + if (i < 0) + break; + n0 = (n1 << -bit_pos) & ((1 << bits_per_digit) - 1); + n1 = mptr[i]; + bit_pos += BITS_PER_MP_LIMB; + *s++ = n0 | (n1 >> bit_pos); + } + + *s = 0; + + return s - str; + } + else + { + /* General case. The base is not a power of 2. Make conversion + from least significant end. */ + + /* If udiv_qrnnd only handles divisors with the most significant bit + set, prepare BIG_BASE for being a divisor by shifting it to the + left exactly enough to set the most significant bit. */ +#if UDIV_NEEDS_NORMALIZATION || UDIV_TIME > 2 * UMUL_TIME + count_leading_zeros (normalization_steps, big_base); + big_base <<= normalization_steps; +#if UDIV_TIME > 2 * UMUL_TIME + /* Get the fixed-point approximation to 1/(BIG_BASE << NORMALIZATION_STEPS). */ + big_base_inverted = __mp_bases[base].big_base_inverted; +#endif +#endif + + dig_per_u = __mp_bases[base].chars_per_limb; + out_len = ((size_t) msize * BITS_PER_MP_LIMB + * __mp_bases[base].chars_per_bit_exactly) + 1; + s += out_len; + + while (msize != 0) + { + int i; + mp_limb_t n0, n1; + +#if UDIV_NEEDS_NORMALIZATION || UDIV_TIME > 2 * UMUL_TIME + /* If we shifted BIG_BASE above, shift the dividend too, to get + the right quotient. We need to do this every loop, + since the intermediate quotients are OK, but the quotient from + one turn in the loop is going to be the dividend in the + next turn, and the dividend needs to be up-shifted. */ + if (normalization_steps != 0) + { + n0 = mpn_lshift (mptr, mptr, msize, normalization_steps); + + /* If the shifting gave a carry out limb, store it and + increase the length. */ + if (n0 != 0) + { + mptr[msize] = n0; + msize++; + } + } +#endif + + /* Divide the number at TP with BIG_BASE to get a quotient and a + remainder. The remainder is our new digit in base BIG_BASE. */ + i = msize - 1; + n1 = mptr[i]; + + if (n1 >= big_base) + n1 = 0; + else + { + msize--; + i--; + } + + for (; i >= 0; i--) + { + n0 = mptr[i]; +#if UDIV_TIME > 2 * UMUL_TIME + udiv_qrnnd_preinv (mptr[i], n1, n1, n0, big_base, big_base_inverted); +#else + udiv_qrnnd (mptr[i], n1, n1, n0, big_base); +#endif + } + +#if UDIV_NEEDS_NORMALIZATION || UDIV_TIME > 2 * UMUL_TIME + /* If we shifted above (at previous UDIV_NEEDS_NORMALIZATION tests) + the remainder will be up-shifted here. Compensate. */ + n1 >>= normalization_steps; +#endif + + /* Convert N1 from BIG_BASE to a string of digits in BASE + using single precision operations. */ + for (i = dig_per_u - 1; i >= 0; i--) + { + *--s = n1 % base; + n1 /= base; + if (n1 == 0 && msize == 0) + break; + } + } + + while (s != str) + *--s = 0; + return out_len; + } +} diff --git a/contrib/libgmp/mpn/generic/gmp-mparam.h b/contrib/libgmp/mpn/generic/gmp-mparam.h new file mode 100644 index 0000000..7c88557 --- /dev/null +++ b/contrib/libgmp/mpn/generic/gmp-mparam.h @@ -0,0 +1,27 @@ +/* gmp-mparam.h -- Compiler/machine parameter header file. + +Copyright (C) 1991, 1993, 1994 Free Software Foundation, Inc. + +This file is part of the GNU MP Library. + +The GNU MP Library is free software; you can redistribute it and/or modify +it under the terms of the GNU Library General Public License as published by +the Free Software Foundation; either version 2 of the License, or (at your +option) any later version. + +The GNU MP Library is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public +License for more details. + +You should have received a copy of the GNU Library General Public License +along with the GNU MP Library; see the file COPYING.LIB. If not, write to +the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, +MA 02111-1307, USA. */ + +#define BITS_PER_MP_LIMB 32 +#define BYTES_PER_MP_LIMB 4 +#define BITS_PER_LONGINT 32 +#define BITS_PER_INT 32 +#define BITS_PER_SHORTINT 16 +#define BITS_PER_CHAR 8 diff --git a/contrib/libgmp/mpn/generic/hamdist.c b/contrib/libgmp/mpn/generic/hamdist.c new file mode 100644 index 0000000..2190b63 --- /dev/null +++ b/contrib/libgmp/mpn/generic/hamdist.c @@ -0,0 +1,88 @@ +/* mpn_hamdist -- + +Copyright (C) 1994, 1996 Free Software Foundation, Inc. + +This file is part of the GNU MP Library. + +The GNU MP Library is free software; you can redistribute it and/or modify +it under the terms of the GNU Library General Public License as published by +the Free Software Foundation; either version 2 of the License, or (at your +option) any later version. + +The GNU MP Library is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public +License for more details. + +You should have received a copy of the GNU Library General Public License +along with the GNU MP Library; see the file COPYING.LIB. If not, write to +the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, +MA 02111-1307, USA. */ + +#include "gmp.h" +#include "gmp-impl.h" + +#if defined __GNUC__ +#if defined __sparc_v9__ && BITS_PER_MP_LIMB == 64 +#define popc_limb(a) \ + ({ \ + DItype __res; \ + asm ("popc %1,%0" : "=r" (__res) : "rI" (a)); \ + __res; \ + }) +#endif +#endif + +#ifndef popc_limb + +/* Cool population count of a mp_limb_t. + You have to figure out how this works, I won't tell you! */ + +static inline unsigned int +popc_limb (x) + mp_limb_t x; +{ +#if BITS_PER_MP_LIMB == 64 + /* We have to go into some trouble to define these constants. + (For mp_limb_t being `long long'.) */ + mp_limb_t cnst; + cnst = 0x55555555L | ((mp_limb_t) 0x55555555L << BITS_PER_MP_LIMB/2); + x = ((x & ~cnst) >> 1) + (x & cnst); + cnst = 0x33333333L | ((mp_limb_t) 0x33333333L << BITS_PER_MP_LIMB/2); + x = ((x & ~cnst) >> 2) + (x & cnst); + cnst = 0x0f0f0f0fL | ((mp_limb_t) 0x0f0f0f0fL << BITS_PER_MP_LIMB/2); + x = ((x >> 4) + x) & cnst; + x = ((x >> 8) + x); + x = ((x >> 16) + x); + x = ((x >> 32) + x) & 0xff; +#endif +#if BITS_PER_MP_LIMB == 32 + x = ((x >> 1) & 0x55555555L) + (x & 0x55555555L); + x = ((x >> 2) & 0x33333333L) + (x & 0x33333333L); + x = ((x >> 4) + x) & 0x0f0f0f0fL; + x = ((x >> 8) + x); + x = ((x >> 16) + x) & 0xff; +#endif + return x; +} +#endif + +unsigned long int +#if __STDC__ +mpn_hamdist (mp_srcptr up, mp_srcptr vp, mp_size_t size) +#else +mpn_hamdist (up, vp, size) + register mp_srcptr up; + register mp_srcptr vp; + register mp_size_t size; +#endif +{ + unsigned long int hamdist; + mp_size_t i; + + hamdist = 0; + for (i = 0; i < size; i++) + hamdist += popc_limb (up[i] ^ vp[i]); + + return hamdist; +} diff --git a/contrib/libgmp/mpn/generic/inlines.c b/contrib/libgmp/mpn/generic/inlines.c new file mode 100644 index 0000000..dca305e --- /dev/null +++ b/contrib/libgmp/mpn/generic/inlines.c @@ -0,0 +1,3 @@ +#define _FORCE_INLINES +#define _EXTERN_INLINE /* empty */ +#include "gmp.h" diff --git a/contrib/libgmp/mpn/generic/lshift.c b/contrib/libgmp/mpn/generic/lshift.c new file mode 100644 index 0000000..e244bc5 --- /dev/null +++ b/contrib/libgmp/mpn/generic/lshift.c @@ -0,0 +1,87 @@ +/* mpn_lshift -- Shift left low level. + +Copyright (C) 1991, 1993, 1994, 1996 Free Software Foundation, Inc. + +This file is part of the GNU MP Library. + +The GNU MP Library is free software; you can redistribute it and/or modify +it under the terms of the GNU Library General Public License as published by +the Free Software Foundation; either version 2 of the License, or (at your +option) any later version. + +The GNU MP Library is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public +License for more details. + +You should have received a copy of the GNU Library General Public License +along with the GNU MP Library; see the file COPYING.LIB. If not, write to +the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, +MA 02111-1307, USA. */ + +#include "gmp.h" +#include "gmp-impl.h" + +/* Shift U (pointed to by UP and USIZE digits long) CNT bits to the left + and store the USIZE least significant digits of the result at WP. + Return the bits shifted out from the most significant digit. + + Argument constraints: + 1. 0 < CNT < BITS_PER_MP_LIMB + 2. If the result is to be written over the input, WP must be >= UP. +*/ + +mp_limb_t +#if __STDC__ +mpn_lshift (register mp_ptr wp, + register mp_srcptr up, mp_size_t usize, + register unsigned int cnt) +#else +mpn_lshift (wp, up, usize, cnt) + register mp_ptr wp; + register mp_srcptr up; + mp_size_t usize; + register unsigned int cnt; +#endif +{ + register mp_limb_t high_limb, low_limb; + register unsigned sh_1, sh_2; + register mp_size_t i; + mp_limb_t retval; + +#ifdef DEBUG + if (usize == 0 || cnt == 0) + abort (); +#endif + + sh_1 = cnt; +#if 0 + if (sh_1 == 0) + { + if (wp != up) + { + /* Copy from high end to low end, to allow specified input/output + overlapping. */ + for (i = usize - 1; i >= 0; i--) + wp[i] = up[i]; + } + return 0; + } +#endif + + wp += 1; + sh_2 = BITS_PER_MP_LIMB - sh_1; + i = usize - 1; + low_limb = up[i]; + retval = low_limb >> sh_2; + high_limb = low_limb; + while (--i >= 0) + { + low_limb = up[i]; + wp[i] = (high_limb << sh_1) | (low_limb >> sh_2); + high_limb = low_limb; + } + wp[i] = high_limb << sh_1; + + return retval; +} diff --git a/contrib/libgmp/mpn/generic/mod_1.c b/contrib/libgmp/mpn/generic/mod_1.c new file mode 100644 index 0000000..314d11b --- /dev/null +++ b/contrib/libgmp/mpn/generic/mod_1.c @@ -0,0 +1,197 @@ +/* mpn_mod_1(dividend_ptr, dividend_size, divisor_limb) -- + Divide (DIVIDEND_PTR,,DIVIDEND_SIZE) by DIVISOR_LIMB. + Return the single-limb remainder. + There are no constraints on the value of the divisor. + +Copyright (C) 1991, 1993, 1994, Free Software Foundation, Inc. + +This file is part of the GNU MP Library. + +The GNU MP Library is free software; you can redistribute it and/or modify +it under the terms of the GNU Library General Public License as published by +the Free Software Foundation; either version 2 of the License, or (at your +option) any later version. + +The GNU MP Library is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public +License for more details. + +You should have received a copy of the GNU Library General Public License +along with the GNU MP Library; see the file COPYING.LIB. If not, write to +the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, +MA 02111-1307, USA. */ + +#include "gmp.h" +#include "gmp-impl.h" +#include "longlong.h" + +#ifndef UMUL_TIME +#define UMUL_TIME 1 +#endif + +#ifndef UDIV_TIME +#define UDIV_TIME UMUL_TIME +#endif + +/* FIXME: We should be using invert_limb (or invert_normalized_limb) + here (not udiv_qrnnd). */ + +mp_limb_t +#if __STDC__ +mpn_mod_1 (mp_srcptr dividend_ptr, mp_size_t dividend_size, + mp_limb_t divisor_limb) +#else +mpn_mod_1 (dividend_ptr, dividend_size, divisor_limb) + mp_srcptr dividend_ptr; + mp_size_t dividend_size; + mp_limb_t divisor_limb; +#endif +{ + mp_size_t i; + mp_limb_t n1, n0, r; + int dummy; + + /* Botch: Should this be handled at all? Rely on callers? */ + if (dividend_size == 0) + return 0; + + /* If multiplication is much faster than division, and the + dividend is large, pre-invert the divisor, and use + only multiplications in the inner loop. */ + + /* This test should be read: + Does it ever help to use udiv_qrnnd_preinv? + && Does what we save compensate for the inversion overhead? */ + if (UDIV_TIME > (2 * UMUL_TIME + 6) + && (UDIV_TIME - (2 * UMUL_TIME + 6)) * dividend_size > UDIV_TIME) + { + int normalization_steps; + + count_leading_zeros (normalization_steps, divisor_limb); + if (normalization_steps != 0) + { + mp_limb_t divisor_limb_inverted; + + divisor_limb <<= normalization_steps; + + /* Compute (2**2N - 2**N * DIVISOR_LIMB) / DIVISOR_LIMB. The + result is a (N+1)-bit approximation to 1/DIVISOR_LIMB, with the + most significant bit (with weight 2**N) implicit. */ + + /* Special case for DIVISOR_LIMB == 100...000. */ + if (divisor_limb << 1 == 0) + divisor_limb_inverted = ~(mp_limb_t) 0; + else + udiv_qrnnd (divisor_limb_inverted, dummy, + -divisor_limb, 0, divisor_limb); + + n1 = dividend_ptr[dividend_size - 1]; + r = n1 >> (BITS_PER_MP_LIMB - normalization_steps); + + /* Possible optimization: + if (r == 0 + && divisor_limb > ((n1 << normalization_steps) + | (dividend_ptr[dividend_size - 2] >> ...))) + ...one division less... */ + + for (i = dividend_size - 2; i >= 0; i--) + { + n0 = dividend_ptr[i]; + udiv_qrnnd_preinv (dummy, r, r, + ((n1 << normalization_steps) + | (n0 >> (BITS_PER_MP_LIMB - normalization_steps))), + divisor_limb, divisor_limb_inverted); + n1 = n0; + } + udiv_qrnnd_preinv (dummy, r, r, + n1 << normalization_steps, + divisor_limb, divisor_limb_inverted); + return r >> normalization_steps; + } + else + { + mp_limb_t divisor_limb_inverted; + + /* Compute (2**2N - 2**N * DIVISOR_LIMB) / DIVISOR_LIMB. The + result is a (N+1)-bit approximation to 1/DIVISOR_LIMB, with the + most significant bit (with weight 2**N) implicit. */ + + /* Special case for DIVISOR_LIMB == 100...000. */ + if (divisor_limb << 1 == 0) + divisor_limb_inverted = ~(mp_limb_t) 0; + else + udiv_qrnnd (divisor_limb_inverted, dummy, + -divisor_limb, 0, divisor_limb); + + i = dividend_size - 1; + r = dividend_ptr[i]; + + if (r >= divisor_limb) + r = 0; + else + i--; + + for (; i >= 0; i--) + { + n0 = dividend_ptr[i]; + udiv_qrnnd_preinv (dummy, r, r, + n0, divisor_limb, divisor_limb_inverted); + } + return r; + } + } + else + { + if (UDIV_NEEDS_NORMALIZATION) + { + int normalization_steps; + + count_leading_zeros (normalization_steps, divisor_limb); + if (normalization_steps != 0) + { + divisor_limb <<= normalization_steps; + + n1 = dividend_ptr[dividend_size - 1]; + r = n1 >> (BITS_PER_MP_LIMB - normalization_steps); + + /* Possible optimization: + if (r == 0 + && divisor_limb > ((n1 << normalization_steps) + | (dividend_ptr[dividend_size - 2] >> ...))) + ...one division less... */ + + for (i = dividend_size - 2; i >= 0; i--) + { + n0 = dividend_ptr[i]; + udiv_qrnnd (dummy, r, r, + ((n1 << normalization_steps) + | (n0 >> (BITS_PER_MP_LIMB - normalization_steps))), + divisor_limb); + n1 = n0; + } + udiv_qrnnd (dummy, r, r, + n1 << normalization_steps, + divisor_limb); + return r >> normalization_steps; + } + } + /* No normalization needed, either because udiv_qrnnd doesn't require + it, or because DIVISOR_LIMB is already normalized. */ + + i = dividend_size - 1; + r = dividend_ptr[i]; + + if (r >= divisor_limb) + r = 0; + else + i--; + + for (; i >= 0; i--) + { + n0 = dividend_ptr[i]; + udiv_qrnnd (dummy, r, r, n0, divisor_limb); + } + return r; + } +} diff --git a/contrib/libgmp/mpn/generic/mul.c b/contrib/libgmp/mpn/generic/mul.c new file mode 100644 index 0000000..dcf8cb4 --- /dev/null +++ b/contrib/libgmp/mpn/generic/mul.c @@ -0,0 +1,152 @@ +/* mpn_mul -- Multiply two natural numbers. + +Copyright (C) 1991, 1993, 1994, 1996 Free Software Foundation, Inc. + +This file is part of the GNU MP Library. + +The GNU MP Library is free software; you can redistribute it and/or modify +it under the terms of the GNU Library General Public License as published by +the Free Software Foundation; either version 2 of the License, or (at your +option) any later version. + +The GNU MP Library is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public +License for more details. + +You should have received a copy of the GNU Library General Public License +along with the GNU MP Library; see the file COPYING.LIB. If not, write to +the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, +MA 02111-1307, USA. */ + +#include "gmp.h" +#include "gmp-impl.h" + +/* Multiply the natural numbers u (pointed to by UP, with USIZE limbs) + and v (pointed to by VP, with VSIZE limbs), and store the result at + PRODP. USIZE + VSIZE limbs are always stored, but if the input + operands are normalized. Return the most significant limb of the + result. + + NOTE: The space pointed to by PRODP is overwritten before finished + with U and V, so overlap is an error. + + Argument constraints: + 1. USIZE >= VSIZE. + 2. PRODP != UP and PRODP != VP, i.e. the destination + must be distinct from the multiplier and the multiplicand. */ + +/* If KARATSUBA_THRESHOLD is not already defined, define it to a + value which is good on most machines. */ +#ifndef KARATSUBA_THRESHOLD +#define KARATSUBA_THRESHOLD 32 +#endif + +mp_limb_t +#if __STDC__ +mpn_mul (mp_ptr prodp, + mp_srcptr up, mp_size_t usize, + mp_srcptr vp, mp_size_t vsize) +#else +mpn_mul (prodp, up, usize, vp, vsize) + mp_ptr prodp; + mp_srcptr up; + mp_size_t usize; + mp_srcptr vp; + mp_size_t vsize; +#endif +{ + mp_ptr prod_endp = prodp + usize + vsize - 1; + mp_limb_t cy; + mp_ptr tspace; + TMP_DECL (marker); + + if (vsize < KARATSUBA_THRESHOLD) + { + /* Handle simple cases with traditional multiplication. + + This is the most critical code of the entire function. All + multiplies rely on this, both small and huge. Small ones arrive + here immediately. Huge ones arrive here as this is the base case + for Karatsuba's recursive algorithm below. */ + mp_size_t i; + mp_limb_t cy_limb; + mp_limb_t v_limb; + + if (vsize == 0) + return 0; + + /* Multiply by the first limb in V separately, as the result can be + stored (not added) to PROD. We also avoid a loop for zeroing. */ + v_limb = vp[0]; + if (v_limb <= 1) + { + if (v_limb == 1) + MPN_COPY (prodp, up, usize); + else + MPN_ZERO (prodp, usize); + cy_limb = 0; + } + else + cy_limb = mpn_mul_1 (prodp, up, usize, v_limb); + + prodp[usize] = cy_limb; + prodp++; + + /* For each iteration in the outer loop, multiply one limb from + U with one limb from V, and add it to PROD. */ + for (i = 1; i < vsize; i++) + { + v_limb = vp[i]; + if (v_limb <= 1) + { + cy_limb = 0; + if (v_limb == 1) + cy_limb = mpn_add_n (prodp, prodp, up, usize); + } + else + cy_limb = mpn_addmul_1 (prodp, up, usize, v_limb); + + prodp[usize] = cy_limb; + prodp++; + } + return cy_limb; + } + + TMP_MARK (marker); + + tspace = (mp_ptr) TMP_ALLOC (2 * vsize * BYTES_PER_MP_LIMB); + MPN_MUL_N_RECURSE (prodp, up, vp, vsize, tspace); + + prodp += vsize; + up += vsize; + usize -= vsize; + if (usize >= vsize) + { + mp_ptr tp = (mp_ptr) TMP_ALLOC (2 * vsize * BYTES_PER_MP_LIMB); + do + { + MPN_MUL_N_RECURSE (tp, up, vp, vsize, tspace); + cy = mpn_add_n (prodp, prodp, tp, vsize); + mpn_add_1 (prodp + vsize, tp + vsize, vsize, cy); + prodp += vsize; + up += vsize; + usize -= vsize; + } + while (usize >= vsize); + } + + /* True: usize < vsize. */ + + /* Make life simple: Recurse. */ + + if (usize != 0) + { + mpn_mul (tspace, vp, vsize, up, usize); + cy = mpn_add_n (prodp, prodp, tspace, vsize); + mpn_add_1 (prodp + vsize, tspace + vsize, usize, cy); + } + + TMP_FREE (marker); + return *prod_endp; +} diff --git a/contrib/libgmp/mpn/generic/mul_1.c b/contrib/libgmp/mpn/generic/mul_1.c new file mode 100644 index 0000000..2de680a --- /dev/null +++ b/contrib/libgmp/mpn/generic/mul_1.c @@ -0,0 +1,59 @@ +/* mpn_mul_1 -- Multiply a limb vector with a single limb and + store the product in a second limb vector. + +Copyright (C) 1991, 1992, 1993, 1994, 1996 Free Software Foundation, Inc. + +This file is part of the GNU MP Library. + +The GNU MP Library is free software; you can redistribute it and/or modify +it under the terms of the GNU Library General Public License as published by +the Free Software Foundation; either version 2 of the License, or (at your +option) any later version. + +The GNU MP Library is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public +License for more details. + +You should have received a copy of the GNU Library General Public License +along with the GNU MP Library; see the file COPYING.LIB. If not, write to +the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, +MA 02111-1307, USA. */ + +#include "gmp.h" +#include "gmp-impl.h" +#include "longlong.h" + +mp_limb_t +mpn_mul_1 (res_ptr, s1_ptr, s1_size, s2_limb) + register mp_ptr res_ptr; + register mp_srcptr s1_ptr; + mp_size_t s1_size; + register mp_limb_t s2_limb; +{ + register mp_limb_t cy_limb; + register mp_size_t j; + register mp_limb_t prod_high, prod_low; + + /* The loop counter and index J goes from -S1_SIZE to -1. This way + the loop becomes faster. */ + j = -s1_size; + + /* Offset the base pointers to compensate for the negative indices. */ + s1_ptr -= j; + res_ptr -= j; + + cy_limb = 0; + do + { + umul_ppmm (prod_high, prod_low, s1_ptr[j], s2_limb); + + prod_low += cy_limb; + cy_limb = (prod_low < cy_limb) + prod_high; + + res_ptr[j] = prod_low; + } + while (++j != 0); + + return cy_limb; +} diff --git a/contrib/libgmp/mpn/generic/mul_n.c b/contrib/libgmp/mpn/generic/mul_n.c new file mode 100644 index 0000000..b38e8ad --- /dev/null +++ b/contrib/libgmp/mpn/generic/mul_n.c @@ -0,0 +1,401 @@ +/* mpn_mul_n -- Multiply two natural numbers of length n. + +Copyright (C) 1991, 1992, 1993, 1994, 1996 Free Software Foundation, Inc. + +This file is part of the GNU MP Library. + +The GNU MP Library is free software; you can redistribute it and/or modify +it under the terms of the GNU Library General Public License as published by +the Free Software Foundation; either version 2 of the License, or (at your +option) any later version. + +The GNU MP Library is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public +License for more details. + +You should have received a copy of the GNU Library General Public License +along with the GNU MP Library; see the file COPYING.LIB. If not, write to +the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, +MA 02111-1307, USA. */ + +#include "gmp.h" +#include "gmp-impl.h" + +/* Multiply the natural numbers u (pointed to by UP) and v (pointed to by VP), + both with SIZE limbs, and store the result at PRODP. 2 * SIZE limbs are + always stored. Return the most significant limb. + + Argument constraints: + 1. PRODP != UP and PRODP != VP, i.e. the destination + must be distinct from the multiplier and the multiplicand. */ + +/* If KARATSUBA_THRESHOLD is not already defined, define it to a + value which is good on most machines. */ +#ifndef KARATSUBA_THRESHOLD +#define KARATSUBA_THRESHOLD 32 +#endif + +/* The code can't handle KARATSUBA_THRESHOLD smaller than 2. */ +#if KARATSUBA_THRESHOLD < 2 +#undef KARATSUBA_THRESHOLD +#define KARATSUBA_THRESHOLD 2 +#endif + +/* Handle simple cases with traditional multiplication. + + This is the most critical code of multiplication. All multiplies rely + on this, both small and huge. Small ones arrive here immediately. Huge + ones arrive here as this is the base case for Karatsuba's recursive + algorithm below. */ + +void +#if __STDC__ +impn_mul_n_basecase (mp_ptr prodp, mp_srcptr up, mp_srcptr vp, mp_size_t size) +#else +impn_mul_n_basecase (prodp, up, vp, size) + mp_ptr prodp; + mp_srcptr up; + mp_srcptr vp; + mp_size_t size; +#endif +{ + mp_size_t i; + mp_limb_t cy_limb; + mp_limb_t v_limb; + + /* Multiply by the first limb in V separately, as the result can be + stored (not added) to PROD. We also avoid a loop for zeroing. */ + v_limb = vp[0]; + if (v_limb <= 1) + { + if (v_limb == 1) + MPN_COPY (prodp, up, size); + else + MPN_ZERO (prodp, size); + cy_limb = 0; + } + else + cy_limb = mpn_mul_1 (prodp, up, size, v_limb); + + prodp[size] = cy_limb; + prodp++; + + /* For each iteration in the outer loop, multiply one limb from + U with one limb from V, and add it to PROD. */ + for (i = 1; i < size; i++) + { + v_limb = vp[i]; + if (v_limb <= 1) + { + cy_limb = 0; + if (v_limb == 1) + cy_limb = mpn_add_n (prodp, prodp, up, size); + } + else + cy_limb = mpn_addmul_1 (prodp, up, size, v_limb); + + prodp[size] = cy_limb; + prodp++; + } +} + +void +#if __STDC__ +impn_mul_n (mp_ptr prodp, + mp_srcptr up, mp_srcptr vp, mp_size_t size, mp_ptr tspace) +#else +impn_mul_n (prodp, up, vp, size, tspace) + mp_ptr prodp; + mp_srcptr up; + mp_srcptr vp; + mp_size_t size; + mp_ptr tspace; +#endif +{ + if ((size & 1) != 0) + { + /* The size is odd, the code code below doesn't handle that. + Multiply the least significant (size - 1) limbs with a recursive + call, and handle the most significant limb of S1 and S2 + separately. */ + /* A slightly faster way to do this would be to make the Karatsuba + code below behave as if the size were even, and let it check for + odd size in the end. I.e., in essence move this code to the end. + Doing so would save us a recursive call, and potentially make the + stack grow a lot less. */ + + mp_size_t esize = size - 1; /* even size */ + mp_limb_t cy_limb; + + MPN_MUL_N_RECURSE (prodp, up, vp, esize, tspace); + cy_limb = mpn_addmul_1 (prodp + esize, up, esize, vp[esize]); + prodp[esize + esize] = cy_limb; + cy_limb = mpn_addmul_1 (prodp + esize, vp, size, up[esize]); + + prodp[esize + size] = cy_limb; + } + else + { + /* Anatolij Alekseevich Karatsuba's divide-and-conquer algorithm. + + Split U in two pieces, U1 and U0, such that + U = U0 + U1*(B**n), + and V in V1 and V0, such that + V = V0 + V1*(B**n). + + UV is then computed recursively using the identity + + 2n n n n + UV = (B + B )U V + B (U -U )(V -V ) + (B + 1)U V + 1 1 1 0 0 1 0 0 + + Where B = 2**BITS_PER_MP_LIMB. */ + + mp_size_t hsize = size >> 1; + mp_limb_t cy; + int negflg; + + /*** Product H. ________________ ________________ + |_____U1 x V1____||____U0 x V0_____| */ + /* Put result in upper part of PROD and pass low part of TSPACE + as new TSPACE. */ + MPN_MUL_N_RECURSE (prodp + size, up + hsize, vp + hsize, hsize, tspace); + + /*** Product M. ________________ + |_(U1-U0)(V0-V1)_| */ + if (mpn_cmp (up + hsize, up, hsize) >= 0) + { + mpn_sub_n (prodp, up + hsize, up, hsize); + negflg = 0; + } + else + { + mpn_sub_n (prodp, up, up + hsize, hsize); + negflg = 1; + } + if (mpn_cmp (vp + hsize, vp, hsize) >= 0) + { + mpn_sub_n (prodp + hsize, vp + hsize, vp, hsize); + negflg ^= 1; + } + else + { + mpn_sub_n (prodp + hsize, vp, vp + hsize, hsize); + /* No change of NEGFLG. */ + } + /* Read temporary operands from low part of PROD. + Put result in low part of TSPACE using upper part of TSPACE + as new TSPACE. */ + MPN_MUL_N_RECURSE (tspace, prodp, prodp + hsize, hsize, tspace + size); + + /*** Add/copy product H. */ + MPN_COPY (prodp + hsize, prodp + size, hsize); + cy = mpn_add_n (prodp + size, prodp + size, prodp + size + hsize, hsize); + + /*** Add product M (if NEGFLG M is a negative number). */ + if (negflg) + cy -= mpn_sub_n (prodp + hsize, prodp + hsize, tspace, size); + else + cy += mpn_add_n (prodp + hsize, prodp + hsize, tspace, size); + + /*** Product L. ________________ ________________ + |________________||____U0 x V0_____| */ + /* Read temporary operands from low part of PROD. + Put result in low part of TSPACE using upper part of TSPACE + as new TSPACE. */ + MPN_MUL_N_RECURSE (tspace, up, vp, hsize, tspace + size); + + /*** Add/copy Product L (twice). */ + + cy += mpn_add_n (prodp + hsize, prodp + hsize, tspace, size); + if (cy) + mpn_add_1 (prodp + hsize + size, prodp + hsize + size, hsize, cy); + + MPN_COPY (prodp, tspace, hsize); + cy = mpn_add_n (prodp + hsize, prodp + hsize, tspace + hsize, hsize); + if (cy) + mpn_add_1 (prodp + size, prodp + size, size, 1); + } +} + +void +#if __STDC__ +impn_sqr_n_basecase (mp_ptr prodp, mp_srcptr up, mp_size_t size) +#else +impn_sqr_n_basecase (prodp, up, size) + mp_ptr prodp; + mp_srcptr up; + mp_size_t size; +#endif +{ + mp_size_t i; + mp_limb_t cy_limb; + mp_limb_t v_limb; + + /* Multiply by the first limb in V separately, as the result can be + stored (not added) to PROD. We also avoid a loop for zeroing. */ + v_limb = up[0]; + if (v_limb <= 1) + { + if (v_limb == 1) + MPN_COPY (prodp, up, size); + else + MPN_ZERO (prodp, size); + cy_limb = 0; + } + else + cy_limb = mpn_mul_1 (prodp, up, size, v_limb); + + prodp[size] = cy_limb; + prodp++; + + /* For each iteration in the outer loop, multiply one limb from + U with one limb from V, and add it to PROD. */ + for (i = 1; i < size; i++) + { + v_limb = up[i]; + if (v_limb <= 1) + { + cy_limb = 0; + if (v_limb == 1) + cy_limb = mpn_add_n (prodp, prodp, up, size); + } + else + cy_limb = mpn_addmul_1 (prodp, up, size, v_limb); + + prodp[size] = cy_limb; + prodp++; + } +} + +void +#if __STDC__ +impn_sqr_n (mp_ptr prodp, + mp_srcptr up, mp_size_t size, mp_ptr tspace) +#else +impn_sqr_n (prodp, up, size, tspace) + mp_ptr prodp; + mp_srcptr up; + mp_size_t size; + mp_ptr tspace; +#endif +{ + if ((size & 1) != 0) + { + /* The size is odd, the code code below doesn't handle that. + Multiply the least significant (size - 1) limbs with a recursive + call, and handle the most significant limb of S1 and S2 + separately. */ + /* A slightly faster way to do this would be to make the Karatsuba + code below behave as if the size were even, and let it check for + odd size in the end. I.e., in essence move this code to the end. + Doing so would save us a recursive call, and potentially make the + stack grow a lot less. */ + + mp_size_t esize = size - 1; /* even size */ + mp_limb_t cy_limb; + + MPN_SQR_N_RECURSE (prodp, up, esize, tspace); + cy_limb = mpn_addmul_1 (prodp + esize, up, esize, up[esize]); + prodp[esize + esize] = cy_limb; + cy_limb = mpn_addmul_1 (prodp + esize, up, size, up[esize]); + + prodp[esize + size] = cy_limb; + } + else + { + mp_size_t hsize = size >> 1; + mp_limb_t cy; + + /*** Product H. ________________ ________________ + |_____U1 x U1____||____U0 x U0_____| */ + /* Put result in upper part of PROD and pass low part of TSPACE + as new TSPACE. */ + MPN_SQR_N_RECURSE (prodp + size, up + hsize, hsize, tspace); + + /*** Product M. ________________ + |_(U1-U0)(U0-U1)_| */ + if (mpn_cmp (up + hsize, up, hsize) >= 0) + { + mpn_sub_n (prodp, up + hsize, up, hsize); + } + else + { + mpn_sub_n (prodp, up, up + hsize, hsize); + } + + /* Read temporary operands from low part of PROD. + Put result in low part of TSPACE using upper part of TSPACE + as new TSPACE. */ + MPN_SQR_N_RECURSE (tspace, prodp, hsize, tspace + size); + + /*** Add/copy product H. */ + MPN_COPY (prodp + hsize, prodp + size, hsize); + cy = mpn_add_n (prodp + size, prodp + size, prodp + size + hsize, hsize); + + /*** Add product M (if NEGFLG M is a negative number). */ + cy -= mpn_sub_n (prodp + hsize, prodp + hsize, tspace, size); + + /*** Product L. ________________ ________________ + |________________||____U0 x U0_____| */ + /* Read temporary operands from low part of PROD. + Put result in low part of TSPACE using upper part of TSPACE + as new TSPACE. */ + MPN_SQR_N_RECURSE (tspace, up, hsize, tspace + size); + + /*** Add/copy Product L (twice). */ + + cy += mpn_add_n (prodp + hsize, prodp + hsize, tspace, size); + if (cy) + mpn_add_1 (prodp + hsize + size, prodp + hsize + size, hsize, cy); + + MPN_COPY (prodp, tspace, hsize); + cy = mpn_add_n (prodp + hsize, prodp + hsize, tspace + hsize, hsize); + if (cy) + mpn_add_1 (prodp + size, prodp + size, size, 1); + } +} + +/* This should be made into an inline function in gmp.h. */ +inline void +#if __STDC__ +mpn_mul_n (mp_ptr prodp, mp_srcptr up, mp_srcptr vp, mp_size_t size) +#else +mpn_mul_n (prodp, up, vp, size) + mp_ptr prodp; + mp_srcptr up; + mp_srcptr vp; + mp_size_t size; +#endif +{ + TMP_DECL (marker); + TMP_MARK (marker); + if (up == vp) + { + if (size < KARATSUBA_THRESHOLD) + { + impn_sqr_n_basecase (prodp, up, size); + } + else + { + mp_ptr tspace; + tspace = (mp_ptr) TMP_ALLOC (2 * size * BYTES_PER_MP_LIMB); + impn_sqr_n (prodp, up, size, tspace); + } + } + else + { + if (size < KARATSUBA_THRESHOLD) + { + impn_mul_n_basecase (prodp, up, vp, size); + } + else + { + mp_ptr tspace; + tspace = (mp_ptr) TMP_ALLOC (2 * size * BYTES_PER_MP_LIMB); + impn_mul_n (prodp, up, vp, size, tspace); + } + } + TMP_FREE (marker); +} diff --git a/contrib/libgmp/mpn/generic/perfsqr.c b/contrib/libgmp/mpn/generic/perfsqr.c new file mode 100644 index 0000000..5a6e2af --- /dev/null +++ b/contrib/libgmp/mpn/generic/perfsqr.c @@ -0,0 +1,138 @@ +/* mpn_perfect_square_p(u,usize) -- Return non-zero if U is a perfect square, + zero otherwise. + +Copyright (C) 1991, 1993, 1994, 1996 Free Software Foundation, Inc. + +This file is part of the GNU MP Library. + +The GNU MP Library is free software; you can redistribute it and/or modify +it under the terms of the GNU Library General Public License as published by +the Free Software Foundation; either version 2 of the License, or (at your +option) any later version. + +The GNU MP Library is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public +License for more details. + +You should have received a copy of the GNU Library General Public License +along with the GNU MP Library; see the file COPYING.LIB. If not, write to +the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, +MA 02111-1307, USA. */ + +#include "gmp.h" +#include "gmp-impl.h" +#include "longlong.h" + +#ifndef UMUL_TIME +#define UMUL_TIME 1 +#endif + +#ifndef UDIV_TIME +#define UDIV_TIME UMUL_TIME +#endif + +#if BITS_PER_MP_LIMB == 32 +#define PP 0xC0CFD797L /* 3 x 5 x 7 x 11 x 13 x ... x 29 */ +#define PP_INVERTED 0x53E5645CL +#endif + +#if BITS_PER_MP_LIMB == 64 +#define PP 0xE221F97C30E94E1DL /* 3 x 5 x 7 x 11 x 13 x ... x 53 */ +#define PP_INVERTED 0x21CFE6CFC938B36BL +#endif + +/* sq_res_0x100[x mod 0x100] == 1 iff x mod 0x100 is a quadratic residue + modulo 0x100. */ +static unsigned char const sq_res_0x100[0x100] = +{ + 1,1,0,0,1,0,0,0,0,1,0,0,0,0,0,0,1,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0, + 0,1,0,0,1,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0, + 1,1,0,0,1,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0, + 0,1,0,0,1,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0, + 0,1,0,0,1,0,0,0,0,1,0,0,0,0,0,0,1,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0, + 0,1,0,0,1,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0, + 0,1,0,0,1,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0, + 0,1,0,0,1,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0, +}; + +int +#if __STDC__ +mpn_perfect_square_p (mp_srcptr up, mp_size_t usize) +#else +mpn_perfect_square_p (up, usize) + mp_srcptr up; + mp_size_t usize; +#endif +{ + mp_limb_t rem; + mp_ptr root_ptr; + int res; + TMP_DECL (marker); + + /* The first test excludes 55/64 (85.9%) of the perfect square candidates + in O(1) time. */ + if ((sq_res_0x100[(unsigned int) up[0] % 0x100] & 1) == 0) + return 0; + +#if defined (PP) + /* The second test excludes 30652543/30808063 (99.5%) of the remaining + perfect square candidates in O(n) time. */ + + /* Firstly, compute REM = A mod PP. */ + if (UDIV_TIME > (2 * UMUL_TIME + 6)) + rem = mpn_preinv_mod_1 (up, usize, (mp_limb_t) PP, (mp_limb_t) PP_INVERTED); + else + rem = mpn_mod_1 (up, usize, (mp_limb_t) PP); + + /* Now decide if REM is a quadratic residue modulo the factors in PP. */ + + /* If A is just a few limbs, computing the square root does not take long + time, so things might run faster if we limit this loop according to the + size of A. */ + +#if BITS_PER_MP_LIMB == 64 + if (((0x12DD703303AED3L >> rem % 53) & 1) == 0) + return 0; + if (((0x4351B2753DFL >> rem % 47) & 1) == 0) + return 0; + if (((0x35883A3EE53L >> rem % 43) & 1) == 0) + return 0; + if (((0x1B382B50737L >> rem % 41) & 1) == 0) + return 0; + if (((0x165E211E9BL >> rem % 37) & 1) == 0) + return 0; + if (((0x121D47B7L >> rem % 31) & 1) == 0) + return 0; +#endif + if (((0x13D122F3L >> rem % 29) & 1) == 0) + return 0; + if (((0x5335FL >> rem % 23) & 1) == 0) + return 0; + if (((0x30AF3L >> rem % 19) & 1) == 0) + return 0; + if (((0x1A317L >> rem % 17) & 1) == 0) + return 0; + if (((0x161BL >> rem % 13) & 1) == 0) + return 0; + if (((0x23BL >> rem % 11) & 1) == 0) + return 0; + if (((0x017L >> rem % 7) & 1) == 0) + return 0; + if (((0x13L >> rem % 5) & 1) == 0) + return 0; + if (((0x3L >> rem % 3) & 1) == 0) + return 0; +#endif + + TMP_MARK (marker); + + /* For the third and last test, we finally compute the square root, + to make sure we've really got a perfect square. */ + root_ptr = (mp_ptr) TMP_ALLOC ((usize + 1) / 2 * BYTES_PER_MP_LIMB); + + /* Iff mpn_sqrtrem returns zero, the square is perfect. */ + res = ! mpn_sqrtrem (root_ptr, NULL, up, usize); + TMP_FREE (marker); + return res; +} diff --git a/contrib/libgmp/mpn/generic/popcount.c b/contrib/libgmp/mpn/generic/popcount.c new file mode 100644 index 0000000..c48573a --- /dev/null +++ b/contrib/libgmp/mpn/generic/popcount.c @@ -0,0 +1,87 @@ +/* popcount.c + +Copyright (C) 1994, 1996 Free Software Foundation, Inc. + +This file is part of the GNU MP Library. + +The GNU MP Library is free software; you can redistribute it and/or modify +it under the terms of the GNU Library General Public License as published by +the Free Software Foundation; either version 2 of the License, or (at your +option) any later version. + +The GNU MP Library is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public +License for more details. + +You should have received a copy of the GNU Library General Public License +along with the GNU MP Library; see the file COPYING.LIB. If not, write to +the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, +MA 02111-1307, USA. */ + +#include "gmp.h" +#include "gmp-impl.h" + +#if defined __GNUC__ +#if defined __sparc_v9__ && BITS_PER_MP_LIMB == 64 +#define popc_limb(a) \ + ({ \ + DItype __res; \ + asm ("popc %1,%0" : "=r" (__res) : "rI" (a)); \ + __res; \ + }) +#endif +#endif + +#ifndef popc_limb + +/* Cool population count of a mp_limb_t. + You have to figure out how this works, I won't tell you! */ + +static inline unsigned int +popc_limb (x) + mp_limb_t x; +{ +#if BITS_PER_MP_LIMB == 64 + /* We have to go into some trouble to define these constants. + (For mp_limb_t being `long long'.) */ + mp_limb_t cnst; + cnst = 0x55555555L | ((mp_limb_t) 0x55555555L << BITS_PER_MP_LIMB/2); + x = ((x & ~cnst) >> 1) + (x & cnst); + cnst = 0x33333333L | ((mp_limb_t) 0x33333333L << BITS_PER_MP_LIMB/2); + x = ((x & ~cnst) >> 2) + (x & cnst); + cnst = 0x0f0f0f0fL | ((mp_limb_t) 0x0f0f0f0fL << BITS_PER_MP_LIMB/2); + x = ((x >> 4) + x) & cnst; + x = ((x >> 8) + x); + x = ((x >> 16) + x); + x = ((x >> 32) + x) & 0xff; +#endif +#if BITS_PER_MP_LIMB == 32 + x = ((x >> 1) & 0x55555555L) + (x & 0x55555555L); + x = ((x >> 2) & 0x33333333L) + (x & 0x33333333L); + x = ((x >> 4) + x) & 0x0f0f0f0fL; + x = ((x >> 8) + x); + x = ((x >> 16) + x) & 0xff; +#endif + return x; +} +#endif + +unsigned long int +#if __STDC__ +mpn_popcount (register mp_srcptr p, register mp_size_t size) +#else +mpn_popcount (p, size) + register mp_srcptr p; + register mp_size_t size; +#endif +{ + unsigned long int popcnt; + mp_size_t i; + + popcnt = 0; + for (i = 0; i < size; i++) + popcnt += popc_limb (p[i]); + + return popcnt; +} diff --git a/contrib/libgmp/mpn/generic/pre_mod_1.c b/contrib/libgmp/mpn/generic/pre_mod_1.c new file mode 100644 index 0000000..92d413b --- /dev/null +++ b/contrib/libgmp/mpn/generic/pre_mod_1.c @@ -0,0 +1,69 @@ +/* mpn_preinv_mod_1 (dividend_ptr, dividend_size, divisor_limb, + divisor_limb_inverted) -- + Divide (DIVIDEND_PTR,,DIVIDEND_SIZE) by the normalized DIVISOR_LIMB. + DIVISOR_LIMB_INVERTED should be 2^(2*BITS_PER_MP_LIMB) / DIVISOR_LIMB + + - 2^BITS_PER_MP_LIMB. + Return the single-limb remainder. + +Copyright (C) 1991, 1993, 1994, Free Software Foundation, Inc. + +This file is part of the GNU MP Library. + +The GNU MP Library is free software; you can redistribute it and/or modify +it under the terms of the GNU Library General Public License as published by +the Free Software Foundation; either version 2 of the License, or (at your +option) any later version. + +The GNU MP Library is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public +License for more details. + +You should have received a copy of the GNU Library General Public License +along with the GNU MP Library; see the file COPYING.LIB. If not, write to +the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, +MA 02111-1307, USA. */ + +#include "gmp.h" +#include "gmp-impl.h" +#include "longlong.h" + +#ifndef UMUL_TIME +#define UMUL_TIME 1 +#endif + +#ifndef UDIV_TIME +#define UDIV_TIME UMUL_TIME +#endif + +mp_limb_t +#if __STDC__ +mpn_preinv_mod_1 (mp_srcptr dividend_ptr, mp_size_t dividend_size, + mp_limb_t divisor_limb, mp_limb_t divisor_limb_inverted) +#else +mpn_preinv_mod_1 (dividend_ptr, dividend_size, divisor_limb, divisor_limb_inverted) + mp_srcptr dividend_ptr; + mp_size_t dividend_size; + mp_limb_t divisor_limb; + mp_limb_t divisor_limb_inverted; +#endif +{ + mp_size_t i; + mp_limb_t n0, r; + int dummy; + + i = dividend_size - 1; + r = dividend_ptr[i]; + + if (r >= divisor_limb) + r = 0; + else + i--; + + for (; i >= 0; i--) + { + n0 = dividend_ptr[i]; + udiv_qrnnd_preinv (dummy, r, r, n0, divisor_limb, divisor_limb_inverted); + } + return r; +} diff --git a/contrib/libgmp/mpn/generic/random2.c b/contrib/libgmp/mpn/generic/random2.c new file mode 100644 index 0000000..2954608 --- /dev/null +++ b/contrib/libgmp/mpn/generic/random2.c @@ -0,0 +1,93 @@ +/* mpn_random2 -- Generate random numbers with relatively long strings + of ones and zeroes. Suitable for border testing. + +Copyright (C) 1992, 1993, 1994, 1996 Free Software Foundation, Inc. + +This file is part of the GNU MP Library. + +The GNU MP Library is free software; you can redistribute it and/or modify +it under the terms of the GNU Library General Public License as published by +the Free Software Foundation; either version 2 of the License, or (at your +option) any later version. + +The GNU MP Library is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public +License for more details. + +You should have received a copy of the GNU Library General Public License +along with the GNU MP Library; see the file COPYING.LIB. If not, write to +the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, +MA 02111-1307, USA. */ + +#include "gmp.h" +#include "gmp-impl.h" + +#if defined (__hpux) || defined (alpha__) || defined (__svr4__) || defined (__SVR4) +/* HPUX lacks random(). DEC OSF/1 1.2 random() returns a double. */ +long mrand48 (); +static inline long +random () +{ + return mrand48 (); +} +#else +long random (); +#endif + +/* It's a bit tricky to get this right, so please test the code well + if you hack with it. Some early versions of the function produced + random numbers with the leading limb == 0, and some versions never + made the most significant bit set. */ + +void +mpn_random2 (res_ptr, size) + mp_ptr res_ptr; + mp_size_t size; +{ + int n_bits; + int bit_pos; + mp_size_t limb_pos; + unsigned int ran; + mp_limb_t limb; + + limb = 0; + + /* Start off in a random bit position in the most significant limb. */ + bit_pos = random () & (BITS_PER_MP_LIMB - 1); + + /* Least significant bit of RAN chooses string of ones/string of zeroes. + Make most significant limb be non-zero by setting bit 0 of RAN. */ + ran = random () | 1; + + for (limb_pos = size - 1; limb_pos >= 0; ) + { + n_bits = (ran >> 1) % BITS_PER_MP_LIMB + 1; + if ((ran & 1) != 0) + { + /* Generate a string of ones. */ + if (n_bits >= bit_pos) + { + res_ptr[limb_pos--] = limb | ((((mp_limb_t) 2) << bit_pos) - 1); + bit_pos += BITS_PER_MP_LIMB; + limb = (~(mp_limb_t) 0) << (bit_pos - n_bits); + } + else + { + limb |= ((((mp_limb_t) 1) << n_bits) - 1) << (bit_pos - n_bits + 1); + } + } + else + { + /* Generate a string of zeroes. */ + if (n_bits >= bit_pos) + { + res_ptr[limb_pos--] = limb; + limb = 0; + bit_pos += BITS_PER_MP_LIMB; + } + } + bit_pos -= n_bits; + ran = random (); + } +} diff --git a/contrib/libgmp/mpn/generic/rshift.c b/contrib/libgmp/mpn/generic/rshift.c new file mode 100644 index 0000000..804f9be --- /dev/null +++ b/contrib/libgmp/mpn/generic/rshift.c @@ -0,0 +1,88 @@ +/* mpn_rshift -- Shift right a low-level natural-number integer. + +Copyright (C) 1991, 1993, 1994, 1996 Free Software Foundation, Inc. + +This file is part of the GNU MP Library. + +The GNU MP Library is free software; you can redistribute it and/or modify +it under the terms of the GNU Library General Public License as published by +the Free Software Foundation; either version 2 of the License, or (at your +option) any later version. + +The GNU MP Library is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public +License for more details. + +You should have received a copy of the GNU Library General Public License +along with the GNU MP Library; see the file COPYING.LIB. If not, write to +the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, +MA 02111-1307, USA. */ + +#include "gmp.h" +#include "gmp-impl.h" + +/* Shift U (pointed to by UP and USIZE limbs long) CNT bits to the right + and store the USIZE least significant limbs of the result at WP. + The bits shifted out to the right are returned. + + Argument constraints: + 1. 0 < CNT < BITS_PER_MP_LIMB + 2. If the result is to be written over the input, WP must be <= UP. +*/ + +mp_limb_t +#if __STDC__ +mpn_rshift (register mp_ptr wp, + register mp_srcptr up, mp_size_t usize, + register unsigned int cnt) +#else +mpn_rshift (wp, up, usize, cnt) + register mp_ptr wp; + register mp_srcptr up; + mp_size_t usize; + register unsigned int cnt; +#endif +{ + register mp_limb_t high_limb, low_limb; + register unsigned sh_1, sh_2; + register mp_size_t i; + mp_limb_t retval; + +#ifdef DEBUG + if (usize == 0 || cnt == 0) + abort (); +#endif + + sh_1 = cnt; + +#if 0 + if (sh_1 == 0) + { + if (wp != up) + { + /* Copy from low end to high end, to allow specified input/output + overlapping. */ + for (i = 0; i < usize; i++) + wp[i] = up[i]; + } + return usize; + } +#endif + + wp -= 1; + sh_2 = BITS_PER_MP_LIMB - sh_1; + high_limb = up[0]; + retval = high_limb << sh_2; + low_limb = high_limb; + + for (i = 1; i < usize; i++) + { + high_limb = up[i]; + wp[i] = (low_limb >> sh_1) | (high_limb << sh_2); + low_limb = high_limb; + } + wp[i] = low_limb >> sh_1; + + return retval; +} diff --git a/contrib/libgmp/mpn/generic/scan0.c b/contrib/libgmp/mpn/generic/scan0.c new file mode 100644 index 0000000..d6f6580 --- /dev/null +++ b/contrib/libgmp/mpn/generic/scan0.c @@ -0,0 +1,62 @@ +/* mpn_scan0 -- Scan from a given bit position for the next clear bit. + +Copyright (C) 1994, 1996 Free Software Foundation, Inc. + +This file is part of the GNU MP Library. + +The GNU MP Library is free software; you can redistribute it and/or modify +it under the terms of the GNU Library General Public License as published by +the Free Software Foundation; either version 2 of the License, or (at your +option) any later version. + +The GNU MP Library is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public +License for more details. + +You should have received a copy of the GNU Library General Public License +along with the GNU MP Library; see the file COPYING.LIB. If not, write to +the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, +MA 02111-1307, USA. */ + +#include "gmp.h" +#include "gmp-impl.h" +#include "longlong.h" + +/* Design issues: + 1. What if starting_bit is not within U? Caller's problem? + 2. Bit index should be 'unsigned'? + + Argument constraints: + 1. U must sooner ot later have a limb with a clear bit. + */ + +unsigned long int +#if __STDC__ +mpn_scan0 (register mp_srcptr up, + register unsigned long int starting_bit) +#else +mpn_scan0 (up, starting_bit) + register mp_srcptr up; + register unsigned long int starting_bit; +#endif +{ + mp_size_t starting_word; + mp_limb_t alimb; + int cnt; + mp_srcptr p; + + /* Start at the word implied by STARTING_BIT. */ + starting_word = starting_bit / BITS_PER_MP_LIMB; + p = up + starting_word; + alimb = ~*p++; + + /* Mask off any bits before STARTING_BIT in the first limb. */ + alimb &= - (mp_limb_t) 1 << (starting_bit % BITS_PER_MP_LIMB); + + while (alimb == 0) + alimb = ~*p++; + + count_leading_zeros (cnt, alimb & -alimb); + return (p - up) * BITS_PER_MP_LIMB - 1 - cnt; +} diff --git a/contrib/libgmp/mpn/generic/scan1.c b/contrib/libgmp/mpn/generic/scan1.c new file mode 100644 index 0000000..c95d090 --- /dev/null +++ b/contrib/libgmp/mpn/generic/scan1.c @@ -0,0 +1,62 @@ +/* mpn_scan1 -- Scan from a given bit position for the next set bit. + +Copyright (C) 1994, 1996 Free Software Foundation, Inc. + +This file is part of the GNU MP Library. + +The GNU MP Library is free software; you can redistribute it and/or modify +it under the terms of the GNU Library General Public License as published by +the Free Software Foundation; either version 2 of the License, or (at your +option) any later version. + +The GNU MP Library is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public +License for more details. + +You should have received a copy of the GNU Library General Public License +along with the GNU MP Library; see the file COPYING.LIB. If not, write to +the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, +MA 02111-1307, USA. */ + +#include "gmp.h" +#include "gmp-impl.h" +#include "longlong.h" + +/* Design issues: + 1. What if starting_bit is not within U? Caller's problem? + 2. Bit index should be 'unsigned'? + + Argument constraints: + 1. U must sooner ot later have a limb != 0. + */ + +unsigned long int +#if __STDC__ +mpn_scan1 (register mp_srcptr up, + register unsigned long int starting_bit) +#else +mpn_scan1 (up, starting_bit) + register mp_srcptr up; + register unsigned long int starting_bit; +#endif +{ + mp_size_t starting_word; + mp_limb_t alimb; + int cnt; + mp_srcptr p; + + /* Start at the word implied by STARTING_BIT. */ + starting_word = starting_bit / BITS_PER_MP_LIMB; + p = up + starting_word; + alimb = *p++; + + /* Mask off any bits before STARTING_BIT in the first limb. */ + alimb &= - (mp_limb_t) 1 << (starting_bit % BITS_PER_MP_LIMB); + + while (alimb == 0) + alimb = *p++; + + count_leading_zeros (cnt, alimb & -alimb); + return (p - up) * BITS_PER_MP_LIMB - 1 - cnt; +} diff --git a/contrib/libgmp/mpn/generic/set_str.c b/contrib/libgmp/mpn/generic/set_str.c new file mode 100644 index 0000000..424fad3 --- /dev/null +++ b/contrib/libgmp/mpn/generic/set_str.c @@ -0,0 +1,154 @@ +/* mpn_set_str (mp_ptr res_ptr, const char *str, size_t str_len, int base) + -- Convert a STR_LEN long base BASE byte string pointed to by STR to a + limb vector pointed to by RES_PTR. Return the number of limbs in + RES_PTR. + +Copyright (C) 1991, 1992, 1993, 1994, 1996 Free Software Foundation, Inc. + +This file is part of the GNU MP Library. + +The GNU MP Library is free software; you can redistribute it and/or modify +it under the terms of the GNU Library General Public License as published by +the Free Software Foundation; either version 2 of the License, or (at your +option) any later version. + +The GNU MP Library is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public +License for more details. + +You should have received a copy of the GNU Library General Public License +along with the GNU MP Library; see the file COPYING.LIB. If not, write to +the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, +MA 02111-1307, USA. */ + +#include "gmp.h" +#include "gmp-impl.h" + +mp_size_t +mpn_set_str (xp, str, str_len, base) + mp_ptr xp; + const unsigned char *str; + size_t str_len; + int base; +{ + mp_size_t size; + mp_limb_t big_base; + int indigits_per_limb; + mp_limb_t res_digit; + + big_base = __mp_bases[base].big_base; + indigits_per_limb = __mp_bases[base].chars_per_limb; + +/* size = str_len / indigits_per_limb + 1; */ + + size = 0; + + if ((base & (base - 1)) == 0) + { + /* The base is a power of 2. Read the input string from + least to most significant character/digit. */ + + const unsigned char *s; + int next_bitpos; + int bits_per_indigit = big_base; + + res_digit = 0; + next_bitpos = 0; + + for (s = str + str_len - 1; s >= str; s--) + { + int inp_digit = *s; + + res_digit |= (mp_limb_t) inp_digit << next_bitpos; + next_bitpos += bits_per_indigit; + if (next_bitpos >= BITS_PER_MP_LIMB) + { + xp[size++] = res_digit; + next_bitpos -= BITS_PER_MP_LIMB; + res_digit = inp_digit >> (bits_per_indigit - next_bitpos); + } + } + + if (res_digit != 0) + xp[size++] = res_digit; + } + else + { + /* General case. The base is not a power of 2. */ + + size_t i; + int j; + mp_limb_t cy_limb; + + for (i = indigits_per_limb; i < str_len; i += indigits_per_limb) + { + res_digit = *str++; + if (base == 10) + { /* This is a common case. + Help the compiler to avoid multiplication. */ + for (j = 1; j < indigits_per_limb; j++) + res_digit = res_digit * 10 + *str++; + } + else + { + for (j = 1; j < indigits_per_limb; j++) + res_digit = res_digit * base + *str++; + } + + if (size == 0) + { + if (res_digit != 0) + { + xp[0] = res_digit; + size = 1; + } + } + else + { + cy_limb = mpn_mul_1 (xp, xp, size, big_base); + cy_limb += mpn_add_1 (xp, xp, size, res_digit); + if (cy_limb != 0) + xp[size++] = cy_limb; + } + } + + big_base = base; + res_digit = *str++; + if (base == 10) + { /* This is a common case. + Help the compiler to avoid multiplication. */ + for (j = 1; j < str_len - (i - indigits_per_limb); j++) + { + res_digit = res_digit * 10 + *str++; + big_base *= 10; + } + } + else + { + for (j = 1; j < str_len - (i - indigits_per_limb); j++) + { + res_digit = res_digit * base + *str++; + big_base *= base; + } + } + + if (size == 0) + { + if (res_digit != 0) + { + xp[0] = res_digit; + size = 1; + } + } + else + { + cy_limb = mpn_mul_1 (xp, xp, size, big_base); + cy_limb += mpn_add_1 (xp, xp, size, res_digit); + if (cy_limb != 0) + xp[size++] = cy_limb; + } + } + + return size; +} diff --git a/contrib/libgmp/mpn/generic/sqrtrem.c b/contrib/libgmp/mpn/generic/sqrtrem.c new file mode 100644 index 0000000..539480d --- /dev/null +++ b/contrib/libgmp/mpn/generic/sqrtrem.c @@ -0,0 +1,498 @@ +/* mpn_sqrtrem (root_ptr, rem_ptr, op_ptr, op_size) + + Write the square root of {OP_PTR, OP_SIZE} at ROOT_PTR. + Write the remainder at REM_PTR, if REM_PTR != NULL. + Return the size of the remainder. + (The size of the root is always half of the size of the operand.) + + OP_PTR and ROOT_PTR may not point to the same object. + OP_PTR and REM_PTR may point to the same object. + + If REM_PTR is NULL, only the root is computed and the return value of + the function is 0 if OP is a perfect square, and *any* non-zero number + otherwise. + +Copyright (C) 1993, 1994, 1996 Free Software Foundation, Inc. + +This file is part of the GNU MP Library. + +The GNU MP Library is free software; you can redistribute it and/or modify +it under the terms of the GNU Library General Public License as published by +the Free Software Foundation; either version 2 of the License, or (at your +option) any later version. + +The GNU MP Library is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public +License for more details. + +You should have received a copy of the GNU Library General Public License +along with the GNU MP Library; see the file COPYING.LIB. If not, write to +the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, +MA 02111-1307, USA. */ + +/* This code is just correct if "unsigned char" has at least 8 bits. It + doesn't help to use CHAR_BIT from limits.h, as the real problem is + the static arrays. */ + +#include "gmp.h" +#include "gmp-impl.h" +#include "longlong.h" + +/* Square root algorithm: + + 1. Shift OP (the input) to the left an even number of bits s.t. there + are an even number of words and either (or both) of the most + significant bits are set. This way, sqrt(OP) has exactly half as + many words as OP, and has its most significant bit set. + + 2. Get a 9-bit approximation to sqrt(OP) using the pre-computed tables. + This approximation is used for the first single-precision + iterations of Newton's method, yielding a full-word approximation + to sqrt(OP). + + 3. Perform multiple-precision Newton iteration until we have the + exact result. Only about half of the input operand is used in + this calculation, as the square root is perfectly determinable + from just the higher half of a number. */ + +/* Define this macro for IEEE P854 machines with a fast sqrt instruction. */ +#if defined __GNUC__ && ! defined __SOFT_FLOAT + +#if defined __sparc__ +#define SQRT(a) \ + ({ \ + double __sqrt_res; \ + asm ("fsqrtd %1,%0" : "=f" (__sqrt_res) : "f" (a)); \ + __sqrt_res; \ + }) +#endif + +#if defined __HAVE_68881__ +#define SQRT(a) \ + ({ \ + double __sqrt_res; \ + asm ("fsqrtx %1,%0" : "=f" (__sqrt_res) : "f" (a)); \ + __sqrt_res; \ + }) +#endif + +#if defined __hppa +#define SQRT(a) \ + ({ \ + double __sqrt_res; \ + asm ("fsqrt,dbl %1,%0" : "=fx" (__sqrt_res) : "fx" (a)); \ + __sqrt_res; \ + }) +#endif + +#if defined _ARCH_PWR2 +#define SQRT(a) \ + ({ \ + double __sqrt_res; \ + asm ("fsqrt %0,%1" : "=f" (__sqrt_res) : "f" (a)); \ + __sqrt_res; \ + }) +#endif + +#endif + +#ifndef SQRT + +/* Tables for initial approximation of the square root. These are + indexed with bits 1-8 of the operand for which the square root is + calculated, where bit 0 is the most significant non-zero bit. I.e. + the most significant one-bit is not used, since that per definition + is one. Likewise, the tables don't return the highest bit of the + result. That bit must be inserted by or:ing the returned value with + 0x100. This way, we get a 9-bit approximation from 8-bit tables! */ + +/* Table to be used for operands with an even total number of bits. + (Exactly as in the decimal system there are similarities between the + square root of numbers with the same initial digits and an even + difference in the total number of digits. Consider the square root + of 1, 10, 100, 1000, ...) */ +static unsigned char even_approx_tab[256] = +{ + 0x6a, 0x6a, 0x6b, 0x6c, 0x6c, 0x6d, 0x6e, 0x6e, + 0x6f, 0x70, 0x71, 0x71, 0x72, 0x73, 0x73, 0x74, + 0x75, 0x75, 0x76, 0x77, 0x77, 0x78, 0x79, 0x79, + 0x7a, 0x7b, 0x7b, 0x7c, 0x7d, 0x7d, 0x7e, 0x7f, + 0x80, 0x80, 0x81, 0x81, 0x82, 0x83, 0x83, 0x84, + 0x85, 0x85, 0x86, 0x87, 0x87, 0x88, 0x89, 0x89, + 0x8a, 0x8b, 0x8b, 0x8c, 0x8d, 0x8d, 0x8e, 0x8f, + 0x8f, 0x90, 0x90, 0x91, 0x92, 0x92, 0x93, 0x94, + 0x94, 0x95, 0x96, 0x96, 0x97, 0x97, 0x98, 0x99, + 0x99, 0x9a, 0x9b, 0x9b, 0x9c, 0x9c, 0x9d, 0x9e, + 0x9e, 0x9f, 0xa0, 0xa0, 0xa1, 0xa1, 0xa2, 0xa3, + 0xa3, 0xa4, 0xa4, 0xa5, 0xa6, 0xa6, 0xa7, 0xa7, + 0xa8, 0xa9, 0xa9, 0xaa, 0xaa, 0xab, 0xac, 0xac, + 0xad, 0xad, 0xae, 0xaf, 0xaf, 0xb0, 0xb0, 0xb1, + 0xb2, 0xb2, 0xb3, 0xb3, 0xb4, 0xb5, 0xb5, 0xb6, + 0xb6, 0xb7, 0xb7, 0xb8, 0xb9, 0xb9, 0xba, 0xba, + 0xbb, 0xbb, 0xbc, 0xbd, 0xbd, 0xbe, 0xbe, 0xbf, + 0xc0, 0xc0, 0xc1, 0xc1, 0xc2, 0xc2, 0xc3, 0xc3, + 0xc4, 0xc5, 0xc5, 0xc6, 0xc6, 0xc7, 0xc7, 0xc8, + 0xc9, 0xc9, 0xca, 0xca, 0xcb, 0xcb, 0xcc, 0xcc, + 0xcd, 0xce, 0xce, 0xcf, 0xcf, 0xd0, 0xd0, 0xd1, + 0xd1, 0xd2, 0xd3, 0xd3, 0xd4, 0xd4, 0xd5, 0xd5, + 0xd6, 0xd6, 0xd7, 0xd7, 0xd8, 0xd9, 0xd9, 0xda, + 0xda, 0xdb, 0xdb, 0xdc, 0xdc, 0xdd, 0xdd, 0xde, + 0xde, 0xdf, 0xe0, 0xe0, 0xe1, 0xe1, 0xe2, 0xe2, + 0xe3, 0xe3, 0xe4, 0xe4, 0xe5, 0xe5, 0xe6, 0xe6, + 0xe7, 0xe7, 0xe8, 0xe8, 0xe9, 0xea, 0xea, 0xeb, + 0xeb, 0xec, 0xec, 0xed, 0xed, 0xee, 0xee, 0xef, + 0xef, 0xf0, 0xf0, 0xf1, 0xf1, 0xf2, 0xf2, 0xf3, + 0xf3, 0xf4, 0xf4, 0xf5, 0xf5, 0xf6, 0xf6, 0xf7, + 0xf7, 0xf8, 0xf8, 0xf9, 0xf9, 0xfa, 0xfa, 0xfb, + 0xfb, 0xfc, 0xfc, 0xfd, 0xfd, 0xfe, 0xfe, 0xff, +}; + +/* Table to be used for operands with an odd total number of bits. + (Further comments before previous table.) */ +static unsigned char odd_approx_tab[256] = +{ + 0x00, 0x00, 0x00, 0x01, 0x01, 0x02, 0x02, 0x03, + 0x03, 0x04, 0x04, 0x05, 0x05, 0x06, 0x06, 0x07, + 0x07, 0x08, 0x08, 0x09, 0x09, 0x0a, 0x0a, 0x0b, + 0x0b, 0x0c, 0x0c, 0x0d, 0x0d, 0x0e, 0x0e, 0x0f, + 0x0f, 0x10, 0x10, 0x10, 0x11, 0x11, 0x12, 0x12, + 0x13, 0x13, 0x14, 0x14, 0x15, 0x15, 0x16, 0x16, + 0x16, 0x17, 0x17, 0x18, 0x18, 0x19, 0x19, 0x1a, + 0x1a, 0x1b, 0x1b, 0x1b, 0x1c, 0x1c, 0x1d, 0x1d, + 0x1e, 0x1e, 0x1f, 0x1f, 0x20, 0x20, 0x20, 0x21, + 0x21, 0x22, 0x22, 0x23, 0x23, 0x23, 0x24, 0x24, + 0x25, 0x25, 0x26, 0x26, 0x27, 0x27, 0x27, 0x28, + 0x28, 0x29, 0x29, 0x2a, 0x2a, 0x2a, 0x2b, 0x2b, + 0x2c, 0x2c, 0x2d, 0x2d, 0x2d, 0x2e, 0x2e, 0x2f, + 0x2f, 0x30, 0x30, 0x30, 0x31, 0x31, 0x32, 0x32, + 0x32, 0x33, 0x33, 0x34, 0x34, 0x35, 0x35, 0x35, + 0x36, 0x36, 0x37, 0x37, 0x37, 0x38, 0x38, 0x39, + 0x39, 0x39, 0x3a, 0x3a, 0x3b, 0x3b, 0x3b, 0x3c, + 0x3c, 0x3d, 0x3d, 0x3d, 0x3e, 0x3e, 0x3f, 0x3f, + 0x40, 0x40, 0x40, 0x41, 0x41, 0x41, 0x42, 0x42, + 0x43, 0x43, 0x43, 0x44, 0x44, 0x45, 0x45, 0x45, + 0x46, 0x46, 0x47, 0x47, 0x47, 0x48, 0x48, 0x49, + 0x49, 0x49, 0x4a, 0x4a, 0x4b, 0x4b, 0x4b, 0x4c, + 0x4c, 0x4c, 0x4d, 0x4d, 0x4e, 0x4e, 0x4e, 0x4f, + 0x4f, 0x50, 0x50, 0x50, 0x51, 0x51, 0x51, 0x52, + 0x52, 0x53, 0x53, 0x53, 0x54, 0x54, 0x54, 0x55, + 0x55, 0x56, 0x56, 0x56, 0x57, 0x57, 0x57, 0x58, + 0x58, 0x59, 0x59, 0x59, 0x5a, 0x5a, 0x5a, 0x5b, + 0x5b, 0x5b, 0x5c, 0x5c, 0x5d, 0x5d, 0x5d, 0x5e, + 0x5e, 0x5e, 0x5f, 0x5f, 0x60, 0x60, 0x60, 0x61, + 0x61, 0x61, 0x62, 0x62, 0x62, 0x63, 0x63, 0x63, + 0x64, 0x64, 0x65, 0x65, 0x65, 0x66, 0x66, 0x66, + 0x67, 0x67, 0x67, 0x68, 0x68, 0x68, 0x69, 0x69, +}; +#endif + + +mp_size_t +#if __STDC__ +mpn_sqrtrem (mp_ptr root_ptr, mp_ptr rem_ptr, mp_srcptr op_ptr, mp_size_t op_size) +#else +mpn_sqrtrem (root_ptr, rem_ptr, op_ptr, op_size) + mp_ptr root_ptr; + mp_ptr rem_ptr; + mp_srcptr op_ptr; + mp_size_t op_size; +#endif +{ + /* R (root result) */ + mp_ptr rp; /* Pointer to least significant word */ + mp_size_t rsize; /* The size in words */ + + /* T (OP shifted to the left a.k.a. normalized) */ + mp_ptr tp; /* Pointer to least significant word */ + mp_size_t tsize; /* The size in words */ + mp_ptr t_end_ptr; /* Pointer right beyond most sign. word */ + mp_limb_t t_high0, t_high1; /* The two most significant words */ + + /* TT (temporary for numerator/remainder) */ + mp_ptr ttp; /* Pointer to least significant word */ + + /* X (temporary for quotient in main loop) */ + mp_ptr xp; /* Pointer to least significant word */ + mp_size_t xsize; /* The size in words */ + + unsigned cnt; + mp_limb_t initial_approx; /* Initially made approximation */ + mp_size_t tsizes[BITS_PER_MP_LIMB]; /* Successive calculation precisions */ + mp_size_t tmp; + mp_size_t i; + + mp_limb_t cy_limb; + TMP_DECL (marker); + + /* If OP is zero, both results are zero. */ + if (op_size == 0) + return 0; + + count_leading_zeros (cnt, op_ptr[op_size - 1]); + tsize = op_size; + if ((tsize & 1) != 0) + { + cnt += BITS_PER_MP_LIMB; + tsize++; + } + + rsize = tsize / 2; + rp = root_ptr; + + TMP_MARK (marker); + + /* Shift OP an even number of bits into T, such that either the most or + the second most significant bit is set, and such that the number of + words in T becomes even. This way, the number of words in R=sqrt(OP) + is exactly half as many as in OP, and the most significant bit of R + is set. + + Also, the initial approximation is simplified by this up-shifted OP. + + Finally, the Newtonian iteration which is the main part of this + program performs division by R. The fast division routine expects + the divisor to be "normalized" in exactly the sense of having the + most significant bit set. */ + + tp = (mp_ptr) TMP_ALLOC (tsize * BYTES_PER_MP_LIMB); + + if ((cnt & ~1) % BITS_PER_MP_LIMB != 0) + t_high0 = mpn_lshift (tp + cnt / BITS_PER_MP_LIMB, op_ptr, op_size, + (cnt & ~1) % BITS_PER_MP_LIMB); + else + MPN_COPY (tp + cnt / BITS_PER_MP_LIMB, op_ptr, op_size); + + if (cnt >= BITS_PER_MP_LIMB) + tp[0] = 0; + + t_high0 = tp[tsize - 1]; + t_high1 = tp[tsize - 2]; /* Never stray. TSIZE is >= 2. */ + +/* Is there a fast sqrt instruction defined for this machine? */ +#ifdef SQRT + { + initial_approx = SQRT (t_high0 * 2.0 + * ((mp_limb_t) 1 << (BITS_PER_MP_LIMB - 1)) + + t_high1); + /* If t_high0,,t_high1 is big, the result in INITIAL_APPROX might have + become incorrect due to overflow in the conversion from double to + mp_limb_t above. It will typically be zero in that case, but might be + a small number on some machines. The most significant bit of + INITIAL_APPROX should be set, so that bit is a good overflow + indication. */ + if ((mp_limb_signed_t) initial_approx >= 0) + initial_approx = ~(mp_limb_t)0; + } +#else + /* Get a 9 bit approximation from the tables. The tables expect to + be indexed with the 8 high bits right below the highest bit. + Also, the highest result bit is not returned by the tables, and + must be or:ed into the result. The scheme gives 9 bits of start + approximation with just 256-entry 8 bit tables. */ + + if ((cnt & 1) == 0) + { + /* The most sign bit of t_high0 is set. */ + initial_approx = t_high0 >> (BITS_PER_MP_LIMB - 8 - 1); + initial_approx &= 0xff; + initial_approx = even_approx_tab[initial_approx]; + } + else + { + /* The most significant bit of T_HIGH0 is unset, + the second most significant is set. */ + initial_approx = t_high0 >> (BITS_PER_MP_LIMB - 8 - 2); + initial_approx &= 0xff; + initial_approx = odd_approx_tab[initial_approx]; + } + initial_approx |= 0x100; + initial_approx <<= BITS_PER_MP_LIMB - 8 - 1; + + /* Perform small precision Newtonian iterations to get a full word + approximation. For small operands, these iteration will make the + entire job. */ + if (t_high0 == ~(mp_limb_t)0) + initial_approx = t_high0; + else + { + mp_limb_t quot; + + if (t_high0 >= initial_approx) + initial_approx = t_high0 + 1; + + /* First get about 18 bits with pure C arithmetics. */ + quot = t_high0 / (initial_approx >> BITS_PER_MP_LIMB/2) << BITS_PER_MP_LIMB/2; + initial_approx = (initial_approx + quot) / 2; + initial_approx |= (mp_limb_t) 1 << (BITS_PER_MP_LIMB - 1); + + /* Now get a full word by one (or for > 36 bit machines) several + iterations. */ + for (i = 16; i < BITS_PER_MP_LIMB; i <<= 1) + { + mp_limb_t ignored_remainder; + + udiv_qrnnd (quot, ignored_remainder, + t_high0, t_high1, initial_approx); + initial_approx = (initial_approx + quot) / 2; + initial_approx |= (mp_limb_t) 1 << (BITS_PER_MP_LIMB - 1); + } + } +#endif + + rp[0] = initial_approx; + rsize = 1; + +#ifdef DEBUG + printf ("\n\nT = "); + mpn_dump (tp, tsize); +#endif + + if (tsize > 2) + { + /* Determine the successive precisions to use in the iteration. We + minimize the precisions, beginning with the highest (i.e. last + iteration) to the lowest (i.e. first iteration). */ + + xp = (mp_ptr) TMP_ALLOC (tsize * BYTES_PER_MP_LIMB); + ttp = (mp_ptr) TMP_ALLOC (tsize * BYTES_PER_MP_LIMB); + + t_end_ptr = tp + tsize; + + tmp = tsize / 2; + for (i = 0;; i++) + { + tsize = (tmp + 1) / 2; + if (tmp == tsize) + break; + tsizes[i] = tsize + tmp; + tmp = tsize; + } + + /* Main Newton iteration loop. For big arguments, most of the + time is spent here. */ + + /* It is possible to do a great optimization here. The successive + divisors in the mpn_divmod call below has more and more leading + words equal to its predecessor. Therefore the beginning of + each division will repeat the same work as did the last + division. If we could guarantee that the leading words of two + consecutive divisors are the same (i.e. in this case, a later + divisor has just more digits at the end) it would be a simple + matter of just using the old remainder of the last division in + a subsequent division, to take care of this optimization. This + idea would surely make a difference even for small arguments. */ + + /* Loop invariants: + + R <= shiftdown_to_same_size(floor(sqrt(OP))) < R + 1. + X - 1 < shiftdown_to_same_size(floor(sqrt(OP))) <= X. + R <= shiftdown_to_same_size(X). */ + + while (--i >= 0) + { + mp_limb_t cy; +#ifdef DEBUG + mp_limb_t old_least_sign_r = rp[0]; + mp_size_t old_rsize = rsize; + + printf ("R = "); + mpn_dump (rp, rsize); +#endif + tsize = tsizes[i]; + + /* Need to copy the numerator into temporary space, as + mpn_divmod overwrites its numerator argument with the + remainder (which we currently ignore). */ + MPN_COPY (ttp, t_end_ptr - tsize, tsize); + cy = mpn_divmod (xp, ttp, tsize, rp, rsize); + xsize = tsize - rsize; + +#ifdef DEBUG + printf ("X =%d ", cy); + mpn_dump (xp, xsize); +#endif + + /* Add X and R with the most significant limbs aligned, + temporarily ignoring at least one limb at the low end of X. */ + tmp = xsize - rsize; + cy += mpn_add_n (xp + tmp, rp, xp + tmp, rsize); + + /* If T begins with more than 2 x BITS_PER_MP_LIMB of ones, we get + intermediate roots that'd need an extra bit. We don't want to + handle that since it would make the subsequent divisor + non-normalized, so round such roots down to be only ones in the + current precision. */ + if (cy == 2) + { + mp_size_t j; + for (j = xsize; j >= 0; j--) + xp[j] = ~(mp_limb_t)0; + } + + /* Divide X by 2 and put the result in R. This is the new + approximation. Shift in the carry from the addition. */ + mpn_rshift (rp, xp, xsize, 1); + rp[xsize - 1] |= ((mp_limb_t) 1 << (BITS_PER_MP_LIMB - 1)); + rsize = xsize; +#ifdef DEBUG + if (old_least_sign_r != rp[rsize - old_rsize]) + printf (">>>>>>>> %d: %0*lX, %0*lX <<<<<<<<\n", + i, 2 * BYTES_PER_MP_LIMB, old_least_sign_r, + 2 * BYTES_PER_MP_LIMB, rp[rsize - old_rsize]); +#endif + } + } + +#ifdef DEBUG + printf ("(final) R = "); + mpn_dump (rp, rsize); +#endif + + /* We computed the square root of OP * 2**(2*floor(cnt/2)). + This has resulted in R being 2**floor(cnt/2) to large. + Shift it down here to fix that. */ + if (cnt / 2 != 0) + { + mpn_rshift (rp, rp, rsize, cnt/2); + rsize -= rp[rsize - 1] == 0; + } + + /* Calculate the remainder. */ + mpn_mul_n (tp, rp, rp, rsize); + tsize = rsize + rsize; + tsize -= tp[tsize - 1] == 0; + if (op_size < tsize + || (op_size == tsize && mpn_cmp (op_ptr, tp, op_size) < 0)) + { + /* R is too large. Decrement it. */ + + /* These operations can't overflow. */ + cy_limb = mpn_sub_n (tp, tp, rp, rsize); + cy_limb += mpn_sub_n (tp, tp, rp, rsize); + mpn_sub_1 (tp + rsize, tp + rsize, tsize - rsize, cy_limb); + mpn_add_1 (tp, tp, tsize, (mp_limb_t) 1); + + mpn_sub_1 (rp, rp, rsize, (mp_limb_t) 1); + +#ifdef DEBUG + printf ("(adjusted) R = "); + mpn_dump (rp, rsize); +#endif + } + + if (rem_ptr != NULL) + { + cy_limb = mpn_sub (rem_ptr, op_ptr, op_size, tp, tsize); + MPN_NORMALIZE (rem_ptr, op_size); + TMP_FREE (marker); + return op_size; + } + else + { + int res; + res = op_size != tsize || mpn_cmp (op_ptr, tp, op_size); + TMP_FREE (marker); + return res; + } +} diff --git a/contrib/libgmp/mpn/generic/sub_n.c b/contrib/libgmp/mpn/generic/sub_n.c new file mode 100644 index 0000000..9d4b216 --- /dev/null +++ b/contrib/libgmp/mpn/generic/sub_n.c @@ -0,0 +1,62 @@ +/* mpn_sub_n -- Subtract two limb vectors of equal, non-zero length. + +Copyright (C) 1992, 1993, 1994, 1996 Free Software Foundation, Inc. + +This file is part of the GNU MP Library. + +The GNU MP Library is free software; you can redistribute it and/or modify +it under the terms of the GNU Library General Public License as published by +the Free Software Foundation; either version 2 of the License, or (at your +option) any later version. + +The GNU MP Library is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public +License for more details. + +You should have received a copy of the GNU Library General Public License +along with the GNU MP Library; see the file COPYING.LIB. If not, write to +the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, +MA 02111-1307, USA. */ + +#include "gmp.h" +#include "gmp-impl.h" + +mp_limb_t +#if __STDC__ +mpn_sub_n (mp_ptr res_ptr, mp_srcptr s1_ptr, mp_srcptr s2_ptr, mp_size_t size) +#else +mpn_sub_n (res_ptr, s1_ptr, s2_ptr, size) + register mp_ptr res_ptr; + register mp_srcptr s1_ptr; + register mp_srcptr s2_ptr; + mp_size_t size; +#endif +{ + register mp_limb_t x, y, cy; + register mp_size_t j; + + /* The loop counter and index J goes from -SIZE to -1. This way + the loop becomes faster. */ + j = -size; + + /* Offset the base pointers to compensate for the negative indices. */ + s1_ptr -= j; + s2_ptr -= j; + res_ptr -= j; + + cy = 0; + do + { + y = s2_ptr[j]; + x = s1_ptr[j]; + y += cy; /* add previous carry to subtrahend */ + cy = (y < cy); /* get out carry from that addition */ + y = x - y; /* main subtract */ + cy = (y > x) + cy; /* get out carry from the subtract, combine */ + res_ptr[j] = y; + } + while (++j != 0); + + return cy; +} diff --git a/contrib/libgmp/mpn/generic/submul_1.c b/contrib/libgmp/mpn/generic/submul_1.c new file mode 100644 index 0000000..b144283 --- /dev/null +++ b/contrib/libgmp/mpn/generic/submul_1.c @@ -0,0 +1,65 @@ +/* mpn_submul_1 -- multiply the S1_SIZE long limb vector pointed to by S1_PTR + by S2_LIMB, subtract the S1_SIZE least significant limbs of the product + from the limb vector pointed to by RES_PTR. Return the most significant + limb of the product, adjusted for carry-out from the subtraction. + +Copyright (C) 1992, 1993, 1994, 1996 Free Software Foundation, Inc. + +This file is part of the GNU MP Library. + +The GNU MP Library is free software; you can redistribute it and/or modify +it under the terms of the GNU Library General Public License as published by +the Free Software Foundation; either version 2 of the License, or (at your +option) any later version. + +The GNU MP Library is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public +License for more details. + +You should have received a copy of the GNU Library General Public License +along with the GNU MP Library; see the file COPYING.LIB. If not, write to +the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, +MA 02111-1307, USA. */ + +#include "gmp.h" +#include "gmp-impl.h" +#include "longlong.h" + +mp_limb_t +mpn_submul_1 (res_ptr, s1_ptr, s1_size, s2_limb) + register mp_ptr res_ptr; + register mp_srcptr s1_ptr; + mp_size_t s1_size; + register mp_limb_t s2_limb; +{ + register mp_limb_t cy_limb; + register mp_size_t j; + register mp_limb_t prod_high, prod_low; + register mp_limb_t x; + + /* The loop counter and index J goes from -SIZE to -1. This way + the loop becomes faster. */ + j = -s1_size; + + /* Offset the base pointers to compensate for the negative indices. */ + res_ptr -= j; + s1_ptr -= j; + + cy_limb = 0; + do + { + umul_ppmm (prod_high, prod_low, s1_ptr[j], s2_limb); + + prod_low += cy_limb; + cy_limb = (prod_low < cy_limb) + prod_high; + + x = res_ptr[j]; + prod_low = x - prod_low; + cy_limb += (prod_low > x); + res_ptr[j] = prod_low; + } + while (++j != 0); + + return cy_limb; +} diff --git a/contrib/libgmp/mpn/generic/udiv_w_sdiv.c b/contrib/libgmp/mpn/generic/udiv_w_sdiv.c new file mode 100644 index 0000000..d9e71b7 --- /dev/null +++ b/contrib/libgmp/mpn/generic/udiv_w_sdiv.c @@ -0,0 +1,125 @@ +/* mpn_udiv_w_sdiv -- implement udiv_qrnnd on machines with only signed + division. + + Contributed by Peter L. Montgomery. + +Copyright (C) 1992, 1994, 1996 Free Software Foundation, Inc. + +This file is part of the GNU MP Library. + +The GNU MP Library is free software; you can redistribute it and/or modify +it under the terms of the GNU Library General Public License as published by +the Free Software Foundation; either version 2 of the License, or (at your +option) any later version. + +The GNU MP Library is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public +License for more details. + +You should have received a copy of the GNU Library General Public License +along with the GNU MP Library; see the file COPYING.LIB. If not, write to +the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, +MA 02111-1307, USA. */ + +#include "gmp.h" +#include "gmp-impl.h" +#include "longlong.h" + +mp_limb_t +mpn_udiv_w_sdiv (rp, a1, a0, d) + mp_limb_t *rp, a1, a0, d; +{ + mp_limb_t q, r; + mp_limb_t c0, c1, b1; + + if ((mp_limb_signed_t) d >= 0) + { + if (a1 < d - a1 - (a0 >> (BITS_PER_MP_LIMB - 1))) + { + /* dividend, divisor, and quotient are nonnegative */ + sdiv_qrnnd (q, r, a1, a0, d); + } + else + { + /* Compute c1*2^32 + c0 = a1*2^32 + a0 - 2^31*d */ + sub_ddmmss (c1, c0, a1, a0, d >> 1, d << (BITS_PER_MP_LIMB - 1)); + /* Divide (c1*2^32 + c0) by d */ + sdiv_qrnnd (q, r, c1, c0, d); + /* Add 2^31 to quotient */ + q += (mp_limb_t) 1 << (BITS_PER_MP_LIMB - 1); + } + } + else + { + b1 = d >> 1; /* d/2, between 2^30 and 2^31 - 1 */ + c1 = a1 >> 1; /* A/2 */ + c0 = (a1 << (BITS_PER_MP_LIMB - 1)) + (a0 >> 1); + + if (a1 < b1) /* A < 2^32*b1, so A/2 < 2^31*b1 */ + { + sdiv_qrnnd (q, r, c1, c0, b1); /* (A/2) / (d/2) */ + + r = 2*r + (a0 & 1); /* Remainder from A/(2*b1) */ + if ((d & 1) != 0) + { + if (r >= q) + r = r - q; + else if (q - r <= d) + { + r = r - q + d; + q--; + } + else + { + r = r - q + 2*d; + q -= 2; + } + } + } + else if (c1 < b1) /* So 2^31 <= (A/2)/b1 < 2^32 */ + { + c1 = (b1 - 1) - c1; + c0 = ~c0; /* logical NOT */ + + sdiv_qrnnd (q, r, c1, c0, b1); /* (A/2) / (d/2) */ + + q = ~q; /* (A/2)/b1 */ + r = (b1 - 1) - r; + + r = 2*r + (a0 & 1); /* A/(2*b1) */ + + if ((d & 1) != 0) + { + if (r >= q) + r = r - q; + else if (q - r <= d) + { + r = r - q + d; + q--; + } + else + { + r = r - q + 2*d; + q -= 2; + } + } + } + else /* Implies c1 = b1 */ + { /* Hence a1 = d - 1 = 2*b1 - 1 */ + if (a0 >= -d) + { + q = -1; + r = a0 + d; + } + else + { + q = -2; + r = a0 + 2*d; + } + } + } + + *rp = r; + return q; +} diff --git a/contrib/libgmp/mpn/mp_bases.c b/contrib/libgmp/mpn/mp_bases.c new file mode 100644 index 0000000..bbe39b0 --- /dev/null +++ b/contrib/libgmp/mpn/mp_bases.c @@ -0,0 +1,549 @@ +/* __mp_bases -- Structure for conversion between internal binary + format and strings in base 2..255. The fields are explained in + gmp-impl.h. + + +Copyright (C) 1991, 1993, 1994, 1996 Free Software Foundation, Inc. + +This file is part of the GNU MP Library. + +The GNU MP Library is free software; you can redistribute it and/or modify +it under the terms of the GNU Library General Public License as published by +the Free Software Foundation; either version 2 of the License, or (at your +option) any later version. + +The GNU MP Library is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public +License for more details. + +You should have received a copy of the GNU Library General Public License +along with the GNU MP Library; see the file COPYING.LIB. If not, write to +the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, +MA 02111-1307, USA. */ + +#include "gmp.h" +#include "gmp-impl.h" + +#if BITS_PER_MP_LIMB == 32 +const struct bases __mp_bases[256] = +{ + /* 0 */ {0, 0.0, 0, 0}, + /* 1 */ {0, 1e38, 0, 0}, + /* 2 */ {32, 1.00000000, 0x1, 0x0}, + /* 3 */ {20, 0.63092975, 0xcfd41b91, 0x3b563c24}, + /* 4 */ {16, 0.50000000, 0x2, 0x0}, + /* 5 */ {13, 0.43067656, 0x48c27395, 0xc25c2684}, + /* 6 */ {12, 0.38685281, 0x81bf1000, 0xf91bd1b6}, + /* 7 */ {11, 0.35620719, 0x75db9c97, 0x1607a2cb}, + /* 8 */ {10, 0.33333333, 0x3, 0x0}, + /* 9 */ {10, 0.31546488, 0xcfd41b91, 0x3b563c24}, + /* 10 */ {9, 0.30103000, 0x3b9aca00, 0x12e0be82}, + /* 11 */ {9, 0.28906483, 0x8c8b6d2b, 0xd24cde04}, + /* 12 */ {8, 0.27894295, 0x19a10000, 0x3fa39ab5}, + /* 13 */ {8, 0.27023815, 0x309f1021, 0x50f8ac5f}, + /* 14 */ {8, 0.26264954, 0x57f6c100, 0x74843b1e}, + /* 15 */ {8, 0.25595802, 0x98c29b81, 0xad0326c2}, + /* 16 */ {8, 0.25000000, 0x4, 0x0}, + /* 17 */ {7, 0.24465054, 0x18754571, 0x4ef0b6bd}, + /* 18 */ {7, 0.23981247, 0x247dbc80, 0xc0fc48a1}, + /* 19 */ {7, 0.23540891, 0x3547667b, 0x33838942}, + /* 20 */ {7, 0.23137821, 0x4c4b4000, 0xad7f29ab}, + /* 21 */ {7, 0.22767025, 0x6b5a6e1d, 0x313c3d15}, + /* 22 */ {7, 0.22424382, 0x94ace180, 0xb8cca9e0}, + /* 23 */ {7, 0.22106473, 0xcaf18367, 0x42ed6de9}, + /* 24 */ {6, 0.21810429, 0xb640000, 0x67980e0b}, + /* 25 */ {6, 0.21533828, 0xe8d4a51, 0x19799812}, + /* 26 */ {6, 0.21274605, 0x1269ae40, 0xbce85396}, + /* 27 */ {6, 0.21030992, 0x17179149, 0x62c103a9}, + /* 28 */ {6, 0.20801460, 0x1cb91000, 0x1d353d43}, + /* 29 */ {6, 0.20584683, 0x23744899, 0xce1decea}, + /* 30 */ {6, 0.20379505, 0x2b73a840, 0x790fc511}, + /* 31 */ {6, 0.20184909, 0x34e63b41, 0x35b865a0}, + /* 32 */ {6, 0.20000000, 0x5, 0x0}, + /* 33 */ {6, 0.19823986, 0x4cfa3cc1, 0xa9aed1b3}, + /* 34 */ {6, 0.19656163, 0x5c13d840, 0x63dfc229}, + /* 35 */ {6, 0.19495902, 0x6d91b519, 0x2b0fee30}, + /* 36 */ {6, 0.19342640, 0x81bf1000, 0xf91bd1b6}, + /* 37 */ {6, 0.19195872, 0x98ede0c9, 0xac89c3a9}, + /* 38 */ {6, 0.19055141, 0xb3773e40, 0x6d2c32fe}, + /* 39 */ {6, 0.18920036, 0xd1bbc4d1, 0x387907c9}, + /* 40 */ {6, 0.18790182, 0xf4240000, 0xc6f7a0b}, + /* 41 */ {5, 0.18665241, 0x6e7d349, 0x28928154}, + /* 42 */ {5, 0.18544902, 0x7ca30a0, 0x6e8629d}, + /* 43 */ {5, 0.18428883, 0x8c32bbb, 0xd373dca0}, + /* 44 */ {5, 0.18316925, 0x9d46c00, 0xa0b17895}, + /* 45 */ {5, 0.18208790, 0xaffacfd, 0x746811a5}, + /* 46 */ {5, 0.18104260, 0xc46bee0, 0x4da6500f}, + /* 47 */ {5, 0.18003133, 0xdab86ef, 0x2ba23582}, + /* 48 */ {5, 0.17905223, 0xf300000, 0xdb20a88}, + /* 49 */ {5, 0.17810359, 0x10d63af1, 0xe68d5ce4}, + /* 50 */ {5, 0.17718382, 0x12a05f20, 0xb7cdfd9d}, + /* 51 */ {5, 0.17629143, 0x1490aae3, 0x8e583933}, + /* 52 */ {5, 0.17542506, 0x16a97400, 0x697cc3ea}, + /* 53 */ {5, 0.17458343, 0x18ed2825, 0x48a5ca6c}, + /* 54 */ {5, 0.17376534, 0x1b5e4d60, 0x2b52db16}, + /* 55 */ {5, 0.17296969, 0x1dff8297, 0x111586a6}, + /* 56 */ {5, 0.17219543, 0x20d38000, 0xf31d2b36}, + /* 57 */ {5, 0.17144160, 0x23dd1799, 0xc8d76d19}, + /* 58 */ {5, 0.17070728, 0x271f35a0, 0xa2cb1eb4}, + /* 59 */ {5, 0.16999162, 0x2a9ce10b, 0x807c3ec3}, + /* 60 */ {5, 0.16929381, 0x2e593c00, 0x617ec8bf}, + /* 61 */ {5, 0.16861310, 0x3257844d, 0x45746cbe}, + /* 62 */ {5, 0.16794878, 0x369b13e0, 0x2c0aa273}, + /* 63 */ {5, 0.16730018, 0x3b27613f, 0x14f90805}, + /* 64 */ {5, 0.16666667, 0x6, 0x0}, + /* 65 */ {5, 0.16604765, 0x4528a141, 0xd9cf0829}, + /* 66 */ {5, 0.16544255, 0x4aa51420, 0xb6fc4841}, + /* 67 */ {5, 0.16485086, 0x50794633, 0x973054cb}, + /* 68 */ {5, 0.16427205, 0x56a94400, 0x7a1dbe4b}, + /* 69 */ {5, 0.16370566, 0x5d393975, 0x5f7fcd7f}, + /* 70 */ {5, 0.16315122, 0x642d7260, 0x47196c84}, + /* 71 */ {5, 0.16260831, 0x6b8a5ae7, 0x30b43635}, + /* 72 */ {5, 0.16207652, 0x73548000, 0x1c1fa5f6}, + /* 73 */ {5, 0.16155547, 0x7b908fe9, 0x930634a}, + /* 74 */ {5, 0.16104477, 0x84435aa0, 0xef7f4a3c}, + /* 75 */ {5, 0.16054409, 0x8d71d25b, 0xcf5552d2}, + /* 76 */ {5, 0.16005307, 0x97210c00, 0xb1a47c8e}, + /* 77 */ {5, 0.15957142, 0xa1563f9d, 0x9634b43e}, + /* 78 */ {5, 0.15909881, 0xac16c8e0, 0x7cd3817d}, + /* 79 */ {5, 0.15863496, 0xb768278f, 0x65536761}, + /* 80 */ {5, 0.15817959, 0xc3500000, 0x4f8b588e}, + /* 81 */ {5, 0.15773244, 0xcfd41b91, 0x3b563c24}, + /* 82 */ {5, 0.15729325, 0xdcfa6920, 0x28928154}, + /* 83 */ {5, 0.15686177, 0xeac8fd83, 0x1721bfb0}, + /* 84 */ {5, 0.15643779, 0xf9461400, 0x6e8629d}, + /* 85 */ {4, 0.15602107, 0x31c84b1, 0x491cc17c}, + /* 86 */ {4, 0.15561139, 0x342ab10, 0x3a11d83b}, + /* 87 */ {4, 0.15520856, 0x36a2c21, 0x2be074cd}, + /* 88 */ {4, 0.15481238, 0x3931000, 0x1e7a02e7}, + /* 89 */ {4, 0.15442266, 0x3bd5ee1, 0x11d10edd}, + /* 90 */ {4, 0.15403922, 0x3e92110, 0x5d92c68}, + /* 91 */ {4, 0.15366189, 0x4165ef1, 0xf50dbfb2}, + /* 92 */ {4, 0.15329049, 0x4452100, 0xdf9f1316}, + /* 93 */ {4, 0.15292487, 0x4756fd1, 0xcb52a684}, + /* 94 */ {4, 0.15256487, 0x4a75410, 0xb8163e97}, + /* 95 */ {4, 0.15221035, 0x4dad681, 0xa5d8f269}, + /* 96 */ {4, 0.15186115, 0x5100000, 0x948b0fcd}, + /* 97 */ {4, 0.15151715, 0x546d981, 0x841e0215}, + /* 98 */ {4, 0.15117821, 0x57f6c10, 0x74843b1e}, + /* 99 */ {4, 0.15084420, 0x5b9c0d1, 0x65b11e6e}, + /* 100 */ {4, 0.15051500, 0x5f5e100, 0x5798ee23}, + /* 101 */ {4, 0.15019048, 0x633d5f1, 0x4a30b99b}, + /* 102 */ {4, 0.14987054, 0x673a910, 0x3d6e4d94}, + /* 103 */ {4, 0.14955506, 0x6b563e1, 0x314825b0}, + /* 104 */ {4, 0.14924394, 0x6f91000, 0x25b55f2e}, + /* 105 */ {4, 0.14893706, 0x73eb721, 0x1aadaccb}, + /* 106 */ {4, 0.14863434, 0x7866310, 0x10294ba2}, + /* 107 */ {4, 0.14833567, 0x7d01db1, 0x620f8f6}, + /* 108 */ {4, 0.14804096, 0x81bf100, 0xf91bd1b6}, + /* 109 */ {4, 0.14775011, 0x869e711, 0xe6d37b2a}, + /* 110 */ {4, 0.14746305, 0x8ba0a10, 0xd55cff6e}, + /* 111 */ {4, 0.14717969, 0x90c6441, 0xc4ad2db2}, + /* 112 */ {4, 0.14689994, 0x9610000, 0xb4b985cf}, + /* 113 */ {4, 0.14662372, 0x9b7e7c1, 0xa5782bef}, + /* 114 */ {4, 0.14635096, 0xa112610, 0x96dfdd2a}, + /* 115 */ {4, 0.14608158, 0xa6cc591, 0x88e7e509}, + /* 116 */ {4, 0.14581551, 0xacad100, 0x7b8813d3}, + /* 117 */ {4, 0.14555268, 0xb2b5331, 0x6eb8b595}, + /* 118 */ {4, 0.14529302, 0xb8e5710, 0x627289db}, + /* 119 */ {4, 0.14503647, 0xbf3e7a1, 0x56aebc07}, + /* 120 */ {4, 0.14478295, 0xc5c1000, 0x4b66dc33}, + /* 121 */ {4, 0.14453241, 0xcc6db61, 0x4094d8a3}, + /* 122 */ {4, 0.14428479, 0xd345510, 0x3632f7a5}, + /* 123 */ {4, 0.14404003, 0xda48871, 0x2c3bd1f0}, + /* 124 */ {4, 0.14379807, 0xe178100, 0x22aa4d5f}, + /* 125 */ {4, 0.14355885, 0xe8d4a51, 0x19799812}, + /* 126 */ {4, 0.14332233, 0xf05f010, 0x10a523e5}, + /* 127 */ {4, 0.14308844, 0xf817e01, 0x828a237}, + /* 128 */ {4, 0.14285714, 0x7, 0x0}, + /* 129 */ {4, 0.14262838, 0x10818201, 0xf04ec452}, + /* 130 */ {4, 0.14240211, 0x11061010, 0xe136444a}, + /* 131 */ {4, 0.14217828, 0x118db651, 0xd2af9589}, + /* 132 */ {4, 0.14195685, 0x12188100, 0xc4b42a83}, + /* 133 */ {4, 0.14173777, 0x12a67c71, 0xb73dccf5}, + /* 134 */ {4, 0.14152100, 0x1337b510, 0xaa4698c5}, + /* 135 */ {4, 0.14130649, 0x13cc3761, 0x9dc8f729}, + /* 136 */ {4, 0.14109421, 0x14641000, 0x91bf9a30}, + /* 137 */ {4, 0.14088412, 0x14ff4ba1, 0x86257887}, + /* 138 */ {4, 0.14067617, 0x159df710, 0x7af5c98c}, + /* 139 */ {4, 0.14047033, 0x16401f31, 0x702c01a0}, + /* 140 */ {4, 0.14026656, 0x16e5d100, 0x65c3ceb1}, + /* 141 */ {4, 0.14006482, 0x178f1991, 0x5bb91502}, + /* 142 */ {4, 0.13986509, 0x183c0610, 0x5207ec23}, + /* 143 */ {4, 0.13966731, 0x18eca3c1, 0x48ac9c19}, + /* 144 */ {4, 0.13947147, 0x19a10000, 0x3fa39ab5}, + /* 145 */ {4, 0.13927753, 0x1a592841, 0x36e98912}, + /* 146 */ {4, 0.13908545, 0x1b152a10, 0x2e7b3140}, + /* 147 */ {4, 0.13889521, 0x1bd51311, 0x2655840b}, + /* 148 */ {4, 0.13870677, 0x1c98f100, 0x1e7596ea}, + /* 149 */ {4, 0.13852011, 0x1d60d1b1, 0x16d8a20d}, + /* 150 */ {4, 0.13833519, 0x1e2cc310, 0xf7bfe87}, + /* 151 */ {4, 0.13815199, 0x1efcd321, 0x85d2492}, + /* 152 */ {4, 0.13797047, 0x1fd11000, 0x179a9f4}, + /* 153 */ {4, 0.13779062, 0x20a987e1, 0xf59e80eb}, + /* 154 */ {4, 0.13761241, 0x21864910, 0xe8b768db}, + /* 155 */ {4, 0.13743580, 0x226761f1, 0xdc39d6d5}, + /* 156 */ {4, 0.13726078, 0x234ce100, 0xd021c5d1}, + /* 157 */ {4, 0.13708732, 0x2436d4d1, 0xc46b5e37}, + /* 158 */ {4, 0.13691539, 0x25254c10, 0xb912f39c}, + /* 159 */ {4, 0.13674498, 0x26185581, 0xae150294}, + /* 160 */ {4, 0.13657605, 0x27100000, 0xa36e2eb1}, + /* 161 */ {4, 0.13640859, 0x280c5a81, 0x991b4094}, + /* 162 */ {4, 0.13624257, 0x290d7410, 0x8f19241e}, + /* 163 */ {4, 0.13607797, 0x2a135bd1, 0x8564e6b7}, + /* 164 */ {4, 0.13591477, 0x2b1e2100, 0x7bfbb5b4}, + /* 165 */ {4, 0.13575295, 0x2c2dd2f1, 0x72dadcc8}, + /* 166 */ {4, 0.13559250, 0x2d428110, 0x69ffc498}, + /* 167 */ {4, 0.13543338, 0x2e5c3ae1, 0x6167f154}, + /* 168 */ {4, 0.13527558, 0x2f7b1000, 0x5911016e}, + /* 169 */ {4, 0.13511908, 0x309f1021, 0x50f8ac5f}, + /* 170 */ {4, 0.13496386, 0x31c84b10, 0x491cc17c}, + /* 171 */ {4, 0.13480991, 0x32f6d0b1, 0x417b26d8}, + /* 172 */ {4, 0.13465720, 0x342ab100, 0x3a11d83b}, + /* 173 */ {4, 0.13450572, 0x3563fc11, 0x32dee622}, + /* 174 */ {4, 0.13435545, 0x36a2c210, 0x2be074cd}, + /* 175 */ {4, 0.13420637, 0x37e71341, 0x2514bb58}, + /* 176 */ {4, 0.13405847, 0x39310000, 0x1e7a02e7}, + /* 177 */ {4, 0.13391173, 0x3a8098c1, 0x180ea5d0}, + /* 178 */ {4, 0.13376614, 0x3bd5ee10, 0x11d10edd}, + /* 179 */ {4, 0.13362168, 0x3d311091, 0xbbfb88e}, + /* 180 */ {4, 0.13347832, 0x3e921100, 0x5d92c68}, + /* 181 */ {4, 0.13333607, 0x3ff90031, 0x1c024c}, + /* 182 */ {4, 0.13319491, 0x4165ef10, 0xf50dbfb2}, + /* 183 */ {4, 0.13305481, 0x42d8eea1, 0xea30efa3}, + /* 184 */ {4, 0.13291577, 0x44521000, 0xdf9f1316}, + /* 185 */ {4, 0.13277777, 0x45d16461, 0xd555c0c9}, + /* 186 */ {4, 0.13264079, 0x4756fd10, 0xcb52a684}, + /* 187 */ {4, 0.13250483, 0x48e2eb71, 0xc193881f}, + /* 188 */ {4, 0.13236988, 0x4a754100, 0xb8163e97}, + /* 189 */ {4, 0.13223591, 0x4c0e0f51, 0xaed8b724}, + /* 190 */ {4, 0.13210292, 0x4dad6810, 0xa5d8f269}, + /* 191 */ {4, 0.13197089, 0x4f535d01, 0x9d15039d}, + /* 192 */ {4, 0.13183981, 0x51000000, 0x948b0fcd}, + /* 193 */ {4, 0.13170967, 0x52b36301, 0x8c394d1d}, + /* 194 */ {4, 0.13158046, 0x546d9810, 0x841e0215}, + /* 195 */ {4, 0.13145216, 0x562eb151, 0x7c3784f8}, + /* 196 */ {4, 0.13132477, 0x57f6c100, 0x74843b1e}, + /* 197 */ {4, 0.13119827, 0x59c5d971, 0x6d02985d}, + /* 198 */ {4, 0.13107265, 0x5b9c0d10, 0x65b11e6e}, + /* 199 */ {4, 0.13094791, 0x5d796e61, 0x5e8e5c64}, + /* 200 */ {4, 0.13082402, 0x5f5e1000, 0x5798ee23}, + /* 201 */ {4, 0.13070099, 0x614a04a1, 0x50cf7bde}, + /* 202 */ {4, 0.13057879, 0x633d5f10, 0x4a30b99b}, + /* 203 */ {4, 0.13045743, 0x65383231, 0x43bb66bd}, + /* 204 */ {4, 0.13033688, 0x673a9100, 0x3d6e4d94}, + /* 205 */ {4, 0.13021715, 0x69448e91, 0x374842ee}, + /* 206 */ {4, 0.13009822, 0x6b563e10, 0x314825b0}, + /* 207 */ {4, 0.12998007, 0x6d6fb2c1, 0x2b6cde75}, + /* 208 */ {4, 0.12986271, 0x6f910000, 0x25b55f2e}, + /* 209 */ {4, 0.12974613, 0x71ba3941, 0x2020a2c5}, + /* 210 */ {4, 0.12963031, 0x73eb7210, 0x1aadaccb}, + /* 211 */ {4, 0.12951524, 0x7624be11, 0x155b891f}, + /* 212 */ {4, 0.12940092, 0x78663100, 0x10294ba2}, + /* 213 */ {4, 0.12928734, 0x7aafdeb1, 0xb160fe9}, + /* 214 */ {4, 0.12917448, 0x7d01db10, 0x620f8f6}, + /* 215 */ {4, 0.12906235, 0x7f5c3a21, 0x14930ef}, + /* 216 */ {4, 0.12895094, 0x81bf1000, 0xf91bd1b6}, + /* 217 */ {4, 0.12884022, 0x842a70e1, 0xefdcb0c7}, + /* 218 */ {4, 0.12873021, 0x869e7110, 0xe6d37b2a}, + /* 219 */ {4, 0.12862089, 0x891b24f1, 0xddfeb94a}, + /* 220 */ {4, 0.12851224, 0x8ba0a100, 0xd55cff6e}, + /* 221 */ {4, 0.12840428, 0x8e2ef9d1, 0xcceced50}, + /* 222 */ {4, 0.12829698, 0x90c64410, 0xc4ad2db2}, + /* 223 */ {4, 0.12819034, 0x93669481, 0xbc9c75f9}, + /* 224 */ {4, 0.12808435, 0x96100000, 0xb4b985cf}, + /* 225 */ {4, 0.12797901, 0x98c29b81, 0xad0326c2}, + /* 226 */ {4, 0.12787431, 0x9b7e7c10, 0xa5782bef}, + /* 227 */ {4, 0.12777024, 0x9e43b6d1, 0x9e1771a9}, + /* 228 */ {4, 0.12766680, 0xa1126100, 0x96dfdd2a}, + /* 229 */ {4, 0.12756398, 0xa3ea8ff1, 0x8fd05c41}, + /* 230 */ {4, 0.12746176, 0xa6cc5910, 0x88e7e509}, + /* 231 */ {4, 0.12736016, 0xa9b7d1e1, 0x8225759d}, + /* 232 */ {4, 0.12725915, 0xacad1000, 0x7b8813d3}, + /* 233 */ {4, 0.12715874, 0xafac2921, 0x750eccf9}, + /* 234 */ {4, 0.12705891, 0xb2b53310, 0x6eb8b595}, + /* 235 */ {4, 0.12695967, 0xb5c843b1, 0x6884e923}, + /* 236 */ {4, 0.12686100, 0xb8e57100, 0x627289db}, + /* 237 */ {4, 0.12676290, 0xbc0cd111, 0x5c80c07b}, + /* 238 */ {4, 0.12666537, 0xbf3e7a10, 0x56aebc07}, + /* 239 */ {4, 0.12656839, 0xc27a8241, 0x50fbb19b}, + /* 240 */ {4, 0.12647197, 0xc5c10000, 0x4b66dc33}, + /* 241 */ {4, 0.12637609, 0xc91209c1, 0x45ef7c7c}, + /* 242 */ {4, 0.12628075, 0xcc6db610, 0x4094d8a3}, + /* 243 */ {4, 0.12618595, 0xcfd41b91, 0x3b563c24}, + /* 244 */ {4, 0.12609168, 0xd3455100, 0x3632f7a5}, + /* 245 */ {4, 0.12599794, 0xd6c16d31, 0x312a60c3}, + /* 246 */ {4, 0.12590471, 0xda488710, 0x2c3bd1f0}, + /* 247 */ {4, 0.12581200, 0xdddab5a1, 0x2766aa45}, + /* 248 */ {4, 0.12571980, 0xe1781000, 0x22aa4d5f}, + /* 249 */ {4, 0.12562811, 0xe520ad61, 0x1e06233c}, + /* 250 */ {4, 0.12553692, 0xe8d4a510, 0x19799812}, + /* 251 */ {4, 0.12544622, 0xec940e71, 0x15041c33}, + /* 252 */ {4, 0.12535601, 0xf05f0100, 0x10a523e5}, + /* 253 */ {4, 0.12526629, 0xf4359451, 0xc5c2749}, + /* 254 */ {4, 0.12517705, 0xf817e010, 0x828a237}, + /* 255 */ {4, 0.12508829, 0xfc05fc01, 0x40a1423}, +}; +#endif +#if BITS_PER_MP_LIMB == 64 +const struct bases __mp_bases[256] = +{ + /* 0 */ {0, 0.0, 0, 0}, + /* 1 */ {0, 1e38, 0, 0}, + /* 2 */ {64, 1.00000000, 0x1, 0x0}, + /* 3 */ {40, 0.63092975, 0xa8b8b452291fe821L, 0x846d550e37b5063dL}, + /* 4 */ {32, 0.50000000, 0x2L, 0x0L}, + /* 5 */ {27, 0.43067656, 0x6765c793fa10079dL, 0x3ce9a36f23c0fc90L}, + /* 6 */ {24, 0.38685281, 0x41c21cb8e1000000L, 0xf24f62335024a295L}, + /* 7 */ {22, 0.35620719, 0x3642798750226111L, 0x2df495ccaa57147bL}, + /* 8 */ {21, 0.33333333, 0x3L, 0x0L}, + /* 9 */ {20, 0.31546488, 0xa8b8b452291fe821L, 0x846d550e37b5063dL}, + /* 10 */ {19, 0.30103000, 0x8ac7230489e80000L, 0xd83c94fb6d2ac34aL}, + /* 11 */ {18, 0.28906483, 0x4d28cb56c33fa539L, 0xa8adf7ae45e7577bL}, + /* 12 */ {17, 0.27894295, 0x1eca170c00000000L, 0xa10c2bec5da8f8fL}, + /* 13 */ {17, 0.27023815, 0x780c7372621bd74dL, 0x10f4becafe412ec3L}, + /* 14 */ {16, 0.26264954, 0x1e39a5057d810000L, 0xf08480f672b4e86L}, + /* 15 */ {16, 0.25595802, 0x5b27ac993df97701L, 0x6779c7f90dc42f48L}, + /* 16 */ {16, 0.25000000, 0x4L, 0x0L}, + /* 17 */ {15, 0.24465054, 0x27b95e997e21d9f1L, 0x9c71e11bab279323L}, + /* 18 */ {15, 0.23981247, 0x5da0e1e53c5c8000L, 0x5dfaa697ec6f6a1cL}, + /* 19 */ {15, 0.23540891, 0xd2ae3299c1c4aedbL, 0x3711783f6be7e9ecL}, + /* 20 */ {14, 0.23137821, 0x16bcc41e90000000L, 0x6849b86a12b9b01eL}, + /* 21 */ {14, 0.22767025, 0x2d04b7fdd9c0ef49L, 0x6bf097ba5ca5e239L}, + /* 22 */ {14, 0.22424382, 0x5658597bcaa24000L, 0x7b8015c8d7af8f08L}, + /* 23 */ {14, 0.22106473, 0xa0e2073737609371L, 0x975a24b3a3151b38L}, + /* 24 */ {13, 0.21810429, 0xc29e98000000000L, 0x50bd367972689db1L}, + /* 25 */ {13, 0.21533828, 0x14adf4b7320334b9L, 0x8c240c4aecb13bb5L}, + /* 26 */ {13, 0.21274605, 0x226ed36478bfa000L, 0xdbd2e56854e118c9L}, + /* 27 */ {13, 0.21030992, 0x383d9170b85ff80bL, 0x2351ffcaa9c7c4aeL}, + /* 28 */ {13, 0.20801460, 0x5a3c23e39c000000L, 0x6b24188ca33b0636L}, + /* 29 */ {13, 0.20584683, 0x8e65137388122bcdL, 0xcc3dceaf2b8ba99dL}, + /* 30 */ {13, 0.20379505, 0xdd41bb36d259e000L, 0x2832e835c6c7d6b6L}, + /* 31 */ {12, 0.20184909, 0xaee5720ee830681L, 0x76b6aa272e1873c5L}, + /* 32 */ {12, 0.20000000, 0x5L, 0x0L}, + /* 33 */ {12, 0.19823986, 0x172588ad4f5f0981L, 0x61eaf5d402c7bf4fL}, + /* 34 */ {12, 0.19656163, 0x211e44f7d02c1000L, 0xeeb658123ffb27ecL}, + /* 35 */ {12, 0.19495902, 0x2ee56725f06e5c71L, 0x5d5e3762e6fdf509L}, + /* 36 */ {12, 0.19342640, 0x41c21cb8e1000000L, 0xf24f62335024a295L}, + /* 37 */ {12, 0.19195872, 0x5b5b57f8a98a5dd1L, 0x66ae7831762efb6fL}, + /* 38 */ {12, 0.19055141, 0x7dcff8986ea31000L, 0x47388865a00f544L}, + /* 39 */ {12, 0.18920036, 0xabd4211662a6b2a1L, 0x7d673c33a123b54cL}, + /* 40 */ {12, 0.18790182, 0xe8d4a51000000000L, 0x19799812dea11197L}, + /* 41 */ {11, 0.18665241, 0x7a32956ad081b79L, 0xc27e62e0686feaeL}, + /* 42 */ {11, 0.18544902, 0x9f49aaff0e86800L, 0x9b6e7507064ce7c7L}, + /* 43 */ {11, 0.18428883, 0xce583bb812d37b3L, 0x3d9ac2bf66cfed94L}, + /* 44 */ {11, 0.18316925, 0x109b79a654c00000L, 0xed46bc50ce59712aL}, + /* 45 */ {11, 0.18208790, 0x1543beff214c8b95L, 0x813d97e2c89b8d46L}, + /* 46 */ {11, 0.18104260, 0x1b149a79459a3800L, 0x2e81751956af8083L}, + /* 47 */ {11, 0.18003133, 0x224edfb5434a830fL, 0xdd8e0a95e30c0988L}, + /* 48 */ {11, 0.17905223, 0x2b3fb00000000000L, 0x7ad4dd48a0b5b167L}, + /* 49 */ {11, 0.17810359, 0x3642798750226111L, 0x2df495ccaa57147bL}, + /* 50 */ {11, 0.17718382, 0x43c33c1937564800L, 0xe392010175ee5962L}, + /* 51 */ {11, 0.17629143, 0x54411b2441c3cd8bL, 0x84eaf11b2fe7738eL}, + /* 52 */ {11, 0.17542506, 0x6851455acd400000L, 0x3a1e3971e008995dL}, + /* 53 */ {11, 0.17458343, 0x80a23b117c8feb6dL, 0xfd7a462344ffce25L}, + /* 54 */ {11, 0.17376534, 0x9dff7d32d5dc1800L, 0x9eca40b40ebcef8aL}, + /* 55 */ {11, 0.17296969, 0xc155af6faeffe6a7L, 0x52fa161a4a48e43dL}, + /* 56 */ {11, 0.17219543, 0xebb7392e00000000L, 0x1607a2cbacf930c1L}, + /* 57 */ {10, 0.17144160, 0x50633659656d971L, 0x97a014f8e3be55f1L}, + /* 58 */ {10, 0.17070728, 0x5fa8624c7fba400L, 0x568df8b76cbf212cL}, + /* 59 */ {10, 0.16999162, 0x717d9faa73c5679L, 0x20ba7c4b4e6ef492L}, + /* 60 */ {10, 0.16929381, 0x86430aac6100000L, 0xe81ee46b9ef492f5L}, + /* 61 */ {10, 0.16861310, 0x9e64d9944b57f29L, 0x9dc0d10d51940416L}, + /* 62 */ {10, 0.16794878, 0xba5ca5392cb0400L, 0x5fa8ed2f450272a5L}, + /* 63 */ {10, 0.16730018, 0xdab2ce1d022cd81L, 0x2ba9eb8c5e04e641L}, + /* 64 */ {10, 0.16666667, 0x6L, 0x0L}, + /* 65 */ {10, 0.16604765, 0x12aeed5fd3e2d281L, 0xb67759cc00287bf1L}, + /* 66 */ {10, 0.16544255, 0x15c3da1572d50400L, 0x78621feeb7f4ed33L}, + /* 67 */ {10, 0.16485086, 0x194c05534f75ee29L, 0x43d55b5f72943bc0L}, + /* 68 */ {10, 0.16427205, 0x1d56299ada100000L, 0x173decb64d1d4409L}, + /* 69 */ {10, 0.16370566, 0x21f2a089a4ff4f79L, 0xe29fb54fd6b6074fL}, + /* 70 */ {10, 0.16315122, 0x2733896c68d9a400L, 0xa1f1f5c210d54e62L}, + /* 71 */ {10, 0.16260831, 0x2d2cf2c33b533c71L, 0x6aac7f9bfafd57b2L}, + /* 72 */ {10, 0.16207652, 0x33f506e440000000L, 0x3b563c2478b72ee2L}, + /* 73 */ {10, 0.16155547, 0x3ba43bec1d062211L, 0x12b536b574e92d1bL}, + /* 74 */ {10, 0.16104477, 0x4455872d8fd4e400L, 0xdf86c03020404fa5L}, + /* 75 */ {10, 0.16054409, 0x4e2694539f2f6c59L, 0xa34adf02234eea8eL}, + /* 76 */ {10, 0.16005307, 0x5938006c18900000L, 0x6f46eb8574eb59ddL}, + /* 77 */ {10, 0.15957142, 0x65ad9912474aa649L, 0x42459b481df47cecL}, + /* 78 */ {10, 0.15909881, 0x73ae9ff4241ec400L, 0x1b424b95d80ca505L}, + /* 79 */ {10, 0.15863496, 0x836612ee9c4ce1e1L, 0xf2c1b982203a0dacL}, + /* 80 */ {10, 0.15817959, 0x9502f90000000000L, 0xb7cdfd9d7bdbab7dL}, + /* 81 */ {10, 0.15773244, 0xa8b8b452291fe821L, 0x846d550e37b5063dL}, + /* 82 */ {10, 0.15729325, 0xbebf59a07dab4400L, 0x57931eeaf85cf64fL}, + /* 83 */ {10, 0.15686177, 0xd7540d4093bc3109L, 0x305a944507c82f47L}, + /* 84 */ {10, 0.15643779, 0xf2b96616f1900000L, 0xe007ccc9c22781aL}, + /* 85 */ {9, 0.15602107, 0x336de62af2bca35L, 0x3e92c42e000eeed4L}, + /* 86 */ {9, 0.15561139, 0x39235ec33d49600L, 0x1ebe59130db2795eL}, + /* 87 */ {9, 0.15520856, 0x3f674e539585a17L, 0x268859e90f51b89L}, + /* 88 */ {9, 0.15481238, 0x4645b6958000000L, 0xd24cde0463108cfaL}, + /* 89 */ {9, 0.15442266, 0x4dcb74afbc49c19L, 0xa536009f37adc383L}, + /* 90 */ {9, 0.15403922, 0x56064e1d18d9a00L, 0x7cea06ce1c9ace10L}, + /* 91 */ {9, 0.15366189, 0x5f04fe2cd8a39fbL, 0x58db032e72e8ba43L}, + /* 92 */ {9, 0.15329049, 0x68d74421f5c0000L, 0x388cc17cae105447L}, + /* 93 */ {9, 0.15292487, 0x738df1f6ab4827dL, 0x1b92672857620ce0L}, + /* 94 */ {9, 0.15256487, 0x7f3afbc9cfb5e00L, 0x18c6a9575c2ade4L}, + /* 95 */ {9, 0.15221035, 0x8bf187fba88f35fL, 0xd44da7da8e44b24fL}, + /* 96 */ {9, 0.15186115, 0x99c600000000000L, 0xaa2f78f1b4cc6794L}, + /* 97 */ {9, 0.15151715, 0xa8ce21eb6531361L, 0x843c067d091ee4ccL}, + /* 98 */ {9, 0.15117821, 0xb92112c1a0b6200L, 0x62005e1e913356e3L}, + /* 99 */ {9, 0.15084420, 0xcad7718b8747c43L, 0x4316eed01dedd518L}, + /* 100 */ {9, 0.15051500, 0xde0b6b3a7640000L, 0x2725dd1d243aba0eL}, + /* 101 */ {9, 0.15019048, 0xf2d8cf5fe6d74c5L, 0xddd9057c24cb54fL}, + /* 102 */ {9, 0.14987054, 0x1095d25bfa712600L, 0xedeee175a736d2a1L}, + /* 103 */ {9, 0.14955506, 0x121b7c4c3698faa7L, 0xc4699f3df8b6b328L}, + /* 104 */ {9, 0.14924394, 0x13c09e8d68000000L, 0x9ebbe7d859cb5a7cL}, + /* 105 */ {9, 0.14893706, 0x15876ccb0b709ca9L, 0x7c828b9887eb2179L}, + /* 106 */ {9, 0.14863434, 0x17723c2976da2a00L, 0x5d652ab99001adcfL}, + /* 107 */ {9, 0.14833567, 0x198384e9c259048bL, 0x4114f1754e5d7b32L}, + /* 108 */ {9, 0.14804096, 0x1bbde41dfeec0000L, 0x274b7c902f7e0188L}, + /* 109 */ {9, 0.14775011, 0x1e241d6e3337910dL, 0xfc9e0fbb32e210cL}, + /* 110 */ {9, 0.14746305, 0x20b91cee9901ee00L, 0xf4afa3e594f8ea1fL}, + /* 111 */ {9, 0.14717969, 0x237ff9079863dfefL, 0xcd85c32e9e4437b0L}, + /* 112 */ {9, 0.14689994, 0x267bf47000000000L, 0xa9bbb147e0dd92a8L}, + /* 113 */ {9, 0.14662372, 0x29b08039fbeda7f1L, 0x8900447b70e8eb82L}, + /* 114 */ {9, 0.14635096, 0x2d213df34f65f200L, 0x6b0a92adaad5848aL}, + /* 115 */ {9, 0.14608158, 0x30d201d957a7c2d3L, 0x4f990ad8740f0ee5L}, + /* 116 */ {9, 0.14581551, 0x34c6d52160f40000L, 0x3670a9663a8d3610L}, + /* 117 */ {9, 0.14555268, 0x3903f855d8f4c755L, 0x1f5c44188057be3cL}, + /* 118 */ {9, 0.14529302, 0x3d8de5c8ec59b600L, 0xa2bea956c4e4977L}, + /* 119 */ {9, 0.14503647, 0x4269541d1ff01337L, 0xed68b23033c3637eL}, + /* 120 */ {9, 0.14478295, 0x479b38e478000000L, 0xc99cf624e50549c5L}, + /* 121 */ {9, 0.14453241, 0x4d28cb56c33fa539L, 0xa8adf7ae45e7577bL}, + /* 122 */ {9, 0.14428479, 0x5317871fa13aba00L, 0x8a5bc740b1c113e5L}, + /* 123 */ {9, 0.14404003, 0x596d2f44de9fa71bL, 0x6e6c7efb81cfbb9bL}, + /* 124 */ {9, 0.14379807, 0x602fd125c47c0000L, 0x54aba5c5cada5f10L}, + /* 125 */ {9, 0.14355885, 0x6765c793fa10079dL, 0x3ce9a36f23c0fc90L}, + /* 126 */ {9, 0.14332233, 0x6f15be069b847e00L, 0x26fb43de2c8cd2a8L}, + /* 127 */ {9, 0.14308844, 0x7746b3e82a77047fL, 0x12b94793db8486a1L}, + /* 128 */ {9, 0.14285714, 0x7L, 0x0L}, + /* 129 */ {9, 0.14262838, 0x894953f7ea890481L, 0xdd5deca404c0156dL}, + /* 130 */ {9, 0.14240211, 0x932abffea4848200L, 0xbd51373330291de0L}, + /* 131 */ {9, 0.14217828, 0x9dacb687d3d6a163L, 0x9fa4025d66f23085L}, + /* 132 */ {9, 0.14195685, 0xa8d8102a44840000L, 0x842530ee2db4949dL}, + /* 133 */ {9, 0.14173777, 0xb4b60f9d140541e5L, 0x6aa7f2766b03dc25L}, + /* 134 */ {9, 0.14152100, 0xc15065d4856e4600L, 0x53035ba7ebf32e8dL}, + /* 135 */ {9, 0.14130649, 0xceb1363f396d23c7L, 0x3d12091fc9fb4914L}, + /* 136 */ {9, 0.14109421, 0xdce31b2488000000L, 0x28b1cb81b1ef1849L}, + /* 137 */ {9, 0.14088412, 0xebf12a24bca135c9L, 0x15c35be67ae3e2c9L}, + /* 138 */ {9, 0.14067617, 0xfbe6f8dbf88f4a00L, 0x42a17bd09be1ff0L}, + /* 139 */ {8, 0.14047033, 0x1ef156c084ce761L, 0x8bf461f03cf0bbfL}, + /* 140 */ {8, 0.14026656, 0x20c4e3b94a10000L, 0xf3fbb43f68a32d05L}, + /* 141 */ {8, 0.14006482, 0x22b0695a08ba421L, 0xd84f44c48564dc19L}, + /* 142 */ {8, 0.13986509, 0x24b4f35d7a4c100L, 0xbe58ebcce7956abeL}, + /* 143 */ {8, 0.13966731, 0x26d397284975781L, 0xa5fac463c7c134b7L}, + /* 144 */ {8, 0.13947147, 0x290d74100000000L, 0x8f19241e28c7d757L}, + /* 145 */ {8, 0.13927753, 0x2b63b3a37866081L, 0x799a6d046c0ae1aeL}, + /* 146 */ {8, 0.13908545, 0x2dd789f4d894100L, 0x6566e37d746a9e40L}, + /* 147 */ {8, 0.13889521, 0x306a35e51b58721L, 0x526887dbfb5f788fL}, + /* 148 */ {8, 0.13870677, 0x331d01712e10000L, 0x408af3382b8efd3dL}, + /* 149 */ {8, 0.13852011, 0x35f14200a827c61L, 0x2fbb374806ec05f1L}, + /* 150 */ {8, 0.13833519, 0x38e858b62216100L, 0x1fe7c0f0afce87feL}, + /* 151 */ {8, 0.13815199, 0x3c03b2c13176a41L, 0x11003d517540d32eL}, + /* 152 */ {8, 0.13797047, 0x3f44c9b21000000L, 0x2f5810f98eff0dcL}, + /* 153 */ {8, 0.13779062, 0x42ad23cef3113c1L, 0xeb72e35e7840d910L}, + /* 154 */ {8, 0.13761241, 0x463e546b19a2100L, 0xd27de19593dc3614L}, + /* 155 */ {8, 0.13743580, 0x49f9fc3f96684e1L, 0xbaf391fd3e5e6fc2L}, + /* 156 */ {8, 0.13726078, 0x4de1c9c5dc10000L, 0xa4bd38c55228c81dL}, + /* 157 */ {8, 0.13708732, 0x51f77994116d2a1L, 0x8fc5a8de8e1de782L}, + /* 158 */ {8, 0.13691539, 0x563cd6bb3398100L, 0x7bf9265bea9d3a3bL}, + /* 159 */ {8, 0.13674498, 0x5ab3bb270beeb01L, 0x69454b325983dccdL}, + /* 160 */ {8, 0.13657605, 0x5f5e10000000000L, 0x5798ee2308c39df9L}, + /* 161 */ {8, 0.13640859, 0x643dce0ec16f501L, 0x46e40ba0fa66a753L}, + /* 162 */ {8, 0.13624257, 0x6954fe21e3e8100L, 0x3717b0870b0db3a7L}, + /* 163 */ {8, 0.13607797, 0x6ea5b9755f440a1L, 0x2825e6775d11cdebL}, + /* 164 */ {8, 0.13591477, 0x74322a1c0410000L, 0x1a01a1c09d1b4dacL}, + /* 165 */ {8, 0.13575295, 0x79fc8b6ae8a46e1L, 0xc9eb0a8bebc8f3eL}, + /* 166 */ {8, 0.13559250, 0x80072a66d512100L, 0xffe357ff59e6a004L}, + /* 167 */ {8, 0.13543338, 0x86546633b42b9c1L, 0xe7dfd1be05fa61a8L}, + /* 168 */ {8, 0.13527558, 0x8ce6b0861000000L, 0xd11ed6fc78f760e5L}, + /* 169 */ {8, 0.13511908, 0x93c08e16a022441L, 0xbb8db609dd29ebfeL}, + /* 170 */ {8, 0.13496386, 0x9ae49717f026100L, 0xa71aec8d1813d532L}, + /* 171 */ {8, 0.13480991, 0xa25577ae24c1a61L, 0x93b612a9f20fbc02L}, + /* 172 */ {8, 0.13465720, 0xaa15f068e610000L, 0x814fc7b19a67d317L}, + /* 173 */ {8, 0.13450572, 0xb228d6bf7577921L, 0x6fd9a03f2e0a4b7cL}, + /* 174 */ {8, 0.13435545, 0xba91158ef5c4100L, 0x5f4615a38d0d316eL}, + /* 175 */ {8, 0.13420637, 0xc351ad9aec0b681L, 0x4f8876863479a286L}, + /* 176 */ {8, 0.13405847, 0xcc6db6100000000L, 0x4094d8a3041b60ebL}, + /* 177 */ {8, 0.13391173, 0xd5e85d09025c181L, 0x32600b8ed883a09bL}, + /* 178 */ {8, 0.13376614, 0xdfc4e816401c100L, 0x24df8c6eb4b6d1f1L}, + /* 179 */ {8, 0.13362168, 0xea06b4c72947221L, 0x18097a8ee151acefL}, + /* 180 */ {8, 0.13347832, 0xf4b139365210000L, 0xbd48cc8ec1cd8e3L}, + /* 181 */ {8, 0.13333607, 0xffc80497d520961L, 0x3807a8d67485fbL}, + /* 182 */ {8, 0.13319491, 0x10b4ebfca1dee100L, 0xea5768860b62e8d8L}, + /* 183 */ {8, 0.13305481, 0x117492de921fc141L, 0xd54faf5b635c5005L}, + /* 184 */ {8, 0.13291577, 0x123bb2ce41000000L, 0xc14a56233a377926L}, + /* 185 */ {8, 0.13277777, 0x130a8b6157bdecc1L, 0xae39a88db7cd329fL}, + /* 186 */ {8, 0.13264079, 0x13e15dede0e8a100L, 0x9c10bde69efa7ab6L}, + /* 187 */ {8, 0.13250483, 0x14c06d941c0ca7e1L, 0x8ac36c42a2836497L}, + /* 188 */ {8, 0.13236988, 0x15a7ff487a810000L, 0x7a463c8b84f5ef67L}, + /* 189 */ {8, 0.13223591, 0x169859ddc5c697a1L, 0x6a8e5f5ad090fd4bL}, + /* 190 */ {8, 0.13210292, 0x1791c60f6fed0100L, 0x5b91a2943596fc56L}, + /* 191 */ {8, 0.13197089, 0x18948e8c0e6fba01L, 0x4d4667b1c468e8f0L}, + /* 192 */ {8, 0.13183981, 0x19a1000000000000L, 0x3fa39ab547994dafL}, + /* 193 */ {8, 0.13170967, 0x1ab769203dafc601L, 0x32a0a9b2faee1e2aL}, + /* 194 */ {8, 0.13158046, 0x1bd81ab557f30100L, 0x26357ceac0e96962L}, + /* 195 */ {8, 0.13145216, 0x1d0367a69fed1ba1L, 0x1a5a6f65caa5859eL}, + /* 196 */ {8, 0.13132477, 0x1e39a5057d810000L, 0xf08480f672b4e86L}, + /* 197 */ {8, 0.13119827, 0x1f7b2a18f29ac3e1L, 0x4383340615612caL}, + /* 198 */ {8, 0.13107265, 0x20c850694c2aa100L, 0xf3c77969ee4be5a2L}, + /* 199 */ {8, 0.13094791, 0x222173cc014980c1L, 0xe00993cc187c5ec9L}, + /* 200 */ {8, 0.13082402, 0x2386f26fc1000000L, 0xcd2b297d889bc2b6L}, + /* 201 */ {8, 0.13070099, 0x24f92ce8af296d41L, 0xbb214d5064862b22L}, + /* 202 */ {8, 0.13057879, 0x2678863cd0ece100L, 0xa9e1a7ca7ea10e20L}, + /* 203 */ {8, 0.13045743, 0x280563f0a9472d61L, 0x99626e72b39ea0cfL}, + /* 204 */ {8, 0.13033688, 0x29a02e1406210000L, 0x899a5ba9c13fafd9L}, + /* 205 */ {8, 0.13021715, 0x2b494f4efe6d2e21L, 0x7a80a705391e96ffL}, + /* 206 */ {8, 0.13009822, 0x2d0134ef21cbc100L, 0x6c0cfe23de23042aL}, + /* 207 */ {8, 0.12998007, 0x2ec84ef4da2ef581L, 0x5e377df359c944ddL}, + /* 208 */ {8, 0.12986271, 0x309f102100000000L, 0x50f8ac5fc8f53985L}, + /* 209 */ {8, 0.12974613, 0x3285ee02a1420281L, 0x44497266278e35b7L}, + /* 210 */ {8, 0.12963031, 0x347d6104fc324100L, 0x382316831f7ee175L}, + /* 211 */ {8, 0.12951524, 0x3685e47dade53d21L, 0x2c7f377833b8946eL}, + /* 212 */ {8, 0.12940092, 0x389ff6bb15610000L, 0x2157c761ab4163efL}, + /* 213 */ {8, 0.12928734, 0x3acc1912ebb57661L, 0x16a7071803cc49a9L}, + /* 214 */ {8, 0.12917448, 0x3d0acff111946100L, 0xc6781d80f8224fcL}, + /* 215 */ {8, 0.12906235, 0x3f5ca2e692eaf841L, 0x294092d370a900bL}, + /* 216 */ {8, 0.12895094, 0x41c21cb8e1000000L, 0xf24f62335024a295L}, + /* 217 */ {8, 0.12884022, 0x443bcb714399a5c1L, 0xe03b98f103fad6d2L}, + /* 218 */ {8, 0.12873021, 0x46ca406c81af2100L, 0xcee3d32cad2a9049L}, + /* 219 */ {8, 0.12862089, 0x496e106ac22aaae1L, 0xbe3f9df9277fdadaL}, + /* 220 */ {8, 0.12851224, 0x4c27d39fa5410000L, 0xae46f0d94c05e933L}, + /* 221 */ {8, 0.12840428, 0x4ef825c296e43ca1L, 0x9ef2280fb437a33dL}, + /* 222 */ {8, 0.12829698, 0x51dfa61f5ad88100L, 0x9039ff426d3f284bL}, + /* 223 */ {8, 0.12819034, 0x54def7a6d2f16901L, 0x82178c6d6b51f8f4L}, + /* 224 */ {8, 0.12808435, 0x57f6c10000000000L, 0x74843b1ee4c1e053L}, + /* 225 */ {8, 0.12797901, 0x5b27ac993df97701L, 0x6779c7f90dc42f48L}, + /* 226 */ {8, 0.12787431, 0x5e7268b9bbdf8100L, 0x5af23c74f9ad9fe9L}, + /* 227 */ {8, 0.12777024, 0x61d7a7932ff3d6a1L, 0x4ee7eae2acdc617eL}, + /* 228 */ {8, 0.12766680, 0x65581f53c8c10000L, 0x43556aa2ac262a0bL}, + /* 229 */ {8, 0.12756398, 0x68f48a385b8320e1L, 0x3835949593b8ddd1L}, + /* 230 */ {8, 0.12746176, 0x6cada69ed07c2100L, 0x2d837fbe78458762L}, + /* 231 */ {8, 0.12736016, 0x70843718cdbf27c1L, 0x233a7e150a54a555L}, + /* 232 */ {8, 0.12725915, 0x7479027ea1000000L, 0x19561984a50ff8feL}, + /* 233 */ {8, 0.12715874, 0x788cd40268f39641L, 0xfd211159fe3490fL}, + /* 234 */ {8, 0.12705891, 0x7cc07b437ecf6100L, 0x6aa563e655033e3L}, + /* 235 */ {8, 0.12695967, 0x8114cc6220762061L, 0xfbb614b3f2d3b14cL}, + /* 236 */ {8, 0.12686100, 0x858aa0135be10000L, 0xeac0f8837fb05773L}, + /* 237 */ {8, 0.12676290, 0x8a22d3b53c54c321L, 0xda6e4c10e8615ca5L}, + /* 238 */ {8, 0.12666537, 0x8ede496339f34100L, 0xcab755a8d01fa67fL}, + /* 239 */ {8, 0.12656839, 0x93bde80aec3a1481L, 0xbb95a9ae71aa3e0cL}, + /* 240 */ {8, 0.12647197, 0x98c29b8100000000L, 0xad0326c296b4f529L}, + /* 241 */ {8, 0.12637609, 0x9ded549671832381L, 0x9ef9f21eed31b7c1L}, + /* 242 */ {8, 0.12628075, 0xa33f092e0b1ac100L, 0x91747422be14b0b2L}, + /* 243 */ {8, 0.12618595, 0xa8b8b452291fe821L, 0x846d550e37b5063dL}, + /* 244 */ {8, 0.12609168, 0xae5b564ac3a10000L, 0x77df79e9a96c06f6L}, + /* 245 */ {8, 0.12599794, 0xb427f4b3be74c361L, 0x6bc6019636c7d0c2L}, + /* 246 */ {8, 0.12590471, 0xba1f9a938041e100L, 0x601c4205aebd9e47L}, + /* 247 */ {8, 0.12581200, 0xc0435871d1110f41L, 0x54ddc59756f05016L}, + /* 248 */ {8, 0.12571980, 0xc694446f01000000L, 0x4a0648979c838c18L}, + /* 249 */ {8, 0.12562811, 0xcd137a5b57ac3ec1L, 0x3f91b6e0bb3a053dL}, + /* 250 */ {8, 0.12553692, 0xd3c21bcecceda100L, 0x357c299a88ea76a5L}, + /* 251 */ {8, 0.12544622, 0xdaa150410b788de1L, 0x2bc1e517aecc56e3L}, + /* 252 */ {8, 0.12535601, 0xe1b24521be010000L, 0x225f56ceb3da9f5dL}, + /* 253 */ {8, 0.12526629, 0xe8f62df12777c1a1L, 0x1951136d53ad63acL}, + /* 254 */ {8, 0.12517705, 0xf06e445906fc0100L, 0x1093d504b3cd7d93L}, + /* 255 */ {8, 0.12508829, 0xf81bc845c81bf801L, 0x824794d1ec1814fL}, +}; +#endif diff --git a/contrib/libgmp/mpn/tests/add_n.c b/contrib/libgmp/mpn/tests/add_n.c new file mode 100644 index 0000000..c27d347 --- /dev/null +++ b/contrib/libgmp/mpn/tests/add_n.c @@ -0,0 +1,211 @@ +#include <stdio.h> +#include "gmp.h" +#include "gmp-impl.h" + +#ifndef USG +#include <sys/time.h> +#include <sys/resource.h> + +unsigned long +cputime () +{ + struct rusage rus; + + getrusage (0, &rus); + return rus.ru_utime.tv_sec * 1000 + rus.ru_utime.tv_usec / 1000; +} +#else +#include <time.h> + +#ifndef CLOCKS_PER_SEC +#define CLOCKS_PER_SEC 1000000 +#endif + +#if CLOCKS_PER_SEC >= 10000 +#define CLOCK_TO_MILLISEC(cl) ((cl) / (CLOCKS_PER_SEC / 1000)) +#else +#define CLOCK_TO_MILLISEC(cl) ((cl) * 1000 / CLOCKS_PER_SEC) +#endif + +unsigned long +cputime () +{ + return CLOCK_TO_MILLISEC (clock ()); +} +#endif + +#define M * 1000000 + +#ifndef CLOCK +#if defined (__m88k__) +#define CLOCK 20 M +#elif defined (__i386__) +#define CLOCK (16.666667 M) +#elif defined (__m68k__) +#define CLOCK (20 M) +#elif defined (_IBMR2) +#define CLOCK (25 M) +#elif defined (__sparc__) +#define CLOCK (20 M) +#elif defined (__sun__) +#define CLOCK (20 M) +#elif defined (__mips) +#define CLOCK (40 M) +#elif defined (__hppa__) +#define CLOCK (50 M) +#elif defined (__alpha) +#define CLOCK (133 M) +#else +#error "Don't know CLOCK of your machine" +#endif +#endif + +#ifndef OPS +#define OPS 10000000 +#endif +#ifndef SIZE +#define SIZE 328 +#endif +#ifndef TIMES +#define TIMES OPS/SIZE +#else +#undef OPS +#define OPS (SIZE*TIMES) +#endif + + +mp_limb_t +#if __STDC__ +refmpn_add_n (mp_ptr res_ptr, + mp_srcptr s1_ptr, mp_srcptr s2_ptr, mp_size_t size) +#else +refmpn_add_n (res_ptr, s1_ptr, s2_ptr, size) + register mp_ptr res_ptr; + register mp_srcptr s1_ptr; + register mp_srcptr s2_ptr; + mp_size_t size; +#endif +{ + register mp_limb_t x, y, cy; + register mp_size_t j; + + /* The loop counter and index J goes from -SIZE to -1. This way + the loop becomes faster. */ + j = -size; + + /* Offset the base pointers to compensate for the negative indices. */ + s1_ptr -= j; + s2_ptr -= j; + res_ptr -= j; + + cy = 0; + do + { + y = s2_ptr[j]; + x = s1_ptr[j]; + y += cy; /* add previous carry to one addend */ + cy = (y < cy); /* get out carry from that addition */ + y = x + y; /* add other addend */ + cy = (y < x) + cy; /* get out carry from that add, combine */ + res_ptr[j] = y; + } + while (++j != 0); + + return cy; +} + +main (argc, argv) + int argc; + char **argv; +{ + mp_limb_t s1[SIZE]; + mp_limb_t s2[SIZE]; + mp_limb_t dx[SIZE+1]; + mp_limb_t dy[SIZE+1]; + int cyx, cyy; + int i; + long t0, t; + int test; + mp_size_t size; + + for (test = 0; ; test++) + { +#ifdef RANDOM + size = (random () % SIZE + 1); +#else + size = SIZE; +#endif + + mpn_random2 (s1, size); + mpn_random2 (s2, size); + + dx[size] = 0x12345678; + dy[size] = 0x12345678; + +#ifdef PRINT + mpn_print (s1, size); + mpn_print (s2, size); +#endif + t0 = cputime(); + for (i = 0; i < TIMES; i++) + cyx = refmpn_add_n (dx, s1, s2, size); + t = cputime() - t0; +#if TIMES != 1 + printf ("refmpn_add_n: %ldms (%.2f cycles/limb)\n", + t, + ((double) t * CLOCK) / (OPS * 1000.0)); +#endif +#ifdef PRINT + printf ("%d ", cyx); mpn_print (dx, size); +#endif + + t0 = cputime(); + for (i = 0; i < TIMES; i++) + cyx = mpn_add_n (dx, s1, s2, size); + t = cputime() - t0; +#if TIMES != 1 + printf ("mpn_add_n: %ldms (%.2f cycles/limb)\n", + t, + ((double) t * CLOCK) / (OPS * 1000.0)); +#endif +#ifdef PRINT + printf ("%d ", cyx); mpn_print (dx, size); +#endif + +#ifndef NOCHECK + /* Put garbage in the destination. */ + for (i = 0; i < size; i++) + { + dx[i] = 0x7654321; + dy[i] = 0x1234567; + } + + cyx = refmpn_add_n (dx, s1, s2, size); + cyy = mpn_add_n (dy, s1, s2, size); + if (cyx != cyy || mpn_cmp (dx, dy, size) != 0 + || dx[size] != 0x12345678 || dy[size] != 0x12345678) + { +#ifndef PRINT + printf ("%d ", cyx); mpn_print (dx, size); + printf ("%d ", cyy); mpn_print (dy, size); +#endif + abort(); + } +#endif + } +} + +mpn_print (mp_ptr p, mp_size_t size) +{ + mp_size_t i; + + for (i = size - 1; i >= 0; i--) + { + printf ("%0*lX", (int) (2 * sizeof(mp_limb_t)), p[i]); +#ifdef SPACE + if (i != 0) + printf (" "); +#endif + } + puts (""); +} diff --git a/contrib/libgmp/mpn/tests/addmul_1.c b/contrib/libgmp/mpn/tests/addmul_1.c new file mode 100644 index 0000000..23952a1 --- /dev/null +++ b/contrib/libgmp/mpn/tests/addmul_1.c @@ -0,0 +1,223 @@ +#include <stdio.h> +#include "gmp.h" +#include "gmp-impl.h" +#include "longlong.h" + +#ifndef USG +#include <sys/time.h> +#include <sys/resource.h> + +unsigned long +cputime () +{ + struct rusage rus; + + getrusage (0, &rus); + return rus.ru_utime.tv_sec * 1000 + rus.ru_utime.tv_usec / 1000; +} +#else +#include <time.h> + +#ifndef CLOCKS_PER_SEC +#define CLOCKS_PER_SEC 1000000 +#endif + +#if CLOCKS_PER_SEC >= 10000 +#define CLOCK_TO_MILLISEC(cl) ((cl) / (CLOCKS_PER_SEC / 1000)) +#else +#define CLOCK_TO_MILLISEC(cl) ((cl) * 1000 / CLOCKS_PER_SEC) +#endif + +unsigned long +cputime () +{ + return CLOCK_TO_MILLISEC (clock ()); +} +#endif + +#define M * 1000000 + +#ifndef CLOCK +#if defined (__m88k__) +#define CLOCK 20 M +#elif defined (__i386__) +#define CLOCK (16.666667 M) +#elif defined (__m68k__) +#define CLOCK (20 M) +#elif defined (_IBMR2) +#define CLOCK (25 M) +#elif defined (__sparc__) +#define CLOCK (20 M) +#elif defined (__sun__) +#define CLOCK (20 M) +#elif defined (__mips) +#define CLOCK (40 M) +#elif defined (__hppa__) +#define CLOCK (50 M) +#elif defined (__alpha) +#define CLOCK (133 M) +#else +#error "Don't know CLOCK of your machine" +#endif +#endif + +#ifndef OPS +#define OPS 20000000 +#endif +#ifndef SIZE +#define SIZE 496 +#endif +#ifndef TIMES +#define TIMES OPS/SIZE +#else +#undef OPS +#define OPS (SIZE*TIMES) +#endif + +mp_limb_t +refmpn_addmul_1 (res_ptr, s1_ptr, s1_size, s2_limb) + register mp_ptr res_ptr; + register mp_srcptr s1_ptr; + mp_size_t s1_size; + register mp_limb_t s2_limb; +{ + register mp_limb_t cy_limb; + register mp_size_t j; + register mp_limb_t prod_high, prod_low; + register mp_limb_t x; + + /* The loop counter and index J goes from -SIZE to -1. This way + the loop becomes faster. */ + j = -s1_size; + + /* Offset the base pointers to compensate for the negative indices. */ + res_ptr -= j; + s1_ptr -= j; + + cy_limb = 0; + do + { + umul_ppmm (prod_high, prod_low, s1_ptr[j], s2_limb); + + prod_low += cy_limb; + cy_limb = (prod_low < cy_limb) + prod_high; + + x = res_ptr[j]; + prod_low = x + prod_low; + cy_limb += (prod_low < x); + res_ptr[j] = prod_low; + } + while (++j != 0); + + return cy_limb; +} + +main (argc, argv) + int argc; + char **argv; +{ + mp_limb_t s1[SIZE]; + mp_limb_t dx[SIZE+2]; + mp_limb_t dy[SIZE+2]; + mp_limb_t cyx, cyy; + int i; + long t0, t; + int test; + mp_limb_t xlimb; + mp_size_t size; + double cyc; + + for (test = 0; ; test++) + { +#ifdef RANDOM + size = (random () % SIZE + 1); +#else + size = SIZE; +#endif + + mpn_random2 (s1, size); + mpn_random2 (dy+1, size); + + if (random () % 0x100 == 0) + xlimb = 0; + else + mpn_random2 (&xlimb, 1); + + dy[size+1] = 0x12345678; + dy[0] = 0x87654321; + +#if defined (PRINT) || defined (XPRINT) + printf ("xlimb=%*lX\n", (int) (2 * sizeof(mp_limb_t)), xlimb); +#endif +#ifdef PRINT + mpn_print (dy+1, size); + mpn_print (s1, size); +#endif + + MPN_COPY (dx, dy, size+2); + t0 = cputime(); + for (i = 0; i < TIMES; i++) + cyx = refmpn_addmul_1 (dx+1, s1, size, xlimb); + t = cputime() - t0; +#if TIMES != 1 + cyc = ((double) t * CLOCK) / (OPS * 1000.0); + printf ("refmpn_addmul_1: %5ldms (%.2f cycles/limb) [%.2f Gb/s]\n", + t, + cyc, + CLOCK/cyc*BITS_PER_MP_LIMB*BITS_PER_MP_LIMB); +#endif + + MPN_COPY (dx, dy, size+2); + t0 = cputime(); + for (i = 0; i < TIMES; i++) + cyy = mpn_addmul_1 (dx+1, s1, size, xlimb); + t = cputime() - t0; +#if TIMES != 1 + cyc = ((double) t * CLOCK) / (OPS * 1000.0); + printf ("mpn_addmul_1: %5ldms (%.2f cycles/limb) [%.2f Gb/s]\n", + t, + cyc, + CLOCK/cyc*BITS_PER_MP_LIMB*BITS_PER_MP_LIMB); +#endif + + MPN_COPY (dx, dy, size+2); + cyx = refmpn_addmul_1 (dx+1, s1, size, xlimb); + cyy = mpn_addmul_1 (dy+1, s1, size, xlimb); + +#ifdef PRINT + printf ("%*lX ", (int) (2 * sizeof(mp_limb_t)), cyx); + mpn_print (dx+1, size); + printf ("%*lX ", (int) (2 * sizeof(mp_limb_t)), cyy); + mpn_print (dy+1, size); +#endif + +#ifndef NOCHECK + if (cyx != cyy || mpn_cmp (dx, dy, size+2) != 0 + || dx[size+1] != 0x12345678 || dx[0] != 0x87654321) + { +#ifndef PRINT + printf ("%*lX ", (int) (2 * sizeof(mp_limb_t)), cyx); + mpn_print (dx+1, size); + printf ("%*lX ", (int) (2 * sizeof(mp_limb_t)), cyy); + mpn_print (dy+1, size); +#endif + abort(); + } +#endif + } +} + +mpn_print (mp_ptr p, mp_size_t size) +{ + mp_size_t i; + + for (i = size - 1; i >= 0; i--) + { + printf ("%0*lX", (int) (2 * sizeof(mp_limb_t)), p[i]); +#ifdef SPACE + if (i != 0) + printf (" "); +#endif + } + puts (""); +} diff --git a/contrib/libgmp/mpn/tests/divmod_1.c b/contrib/libgmp/mpn/tests/divmod_1.c new file mode 100644 index 0000000..f6b541e --- /dev/null +++ b/contrib/libgmp/mpn/tests/divmod_1.c @@ -0,0 +1,120 @@ +#include <stdio.h> +#include "gmp.h" +#include "gmp-impl.h" +#include "longlong.h" + +#ifndef USG +#include <sys/time.h> +#include <sys/resource.h> + +unsigned long +cputime () +{ + struct rusage rus; + + getrusage (0, &rus); + return rus.ru_utime.tv_sec * 1000 + rus.ru_utime.tv_usec / 1000; +} +#else +#include <time.h> + +#ifndef CLOCKS_PER_SEC +#define CLOCKS_PER_SEC 1000000 +#endif + +#if CLOCKS_PER_SEC >= 10000 +#define CLOCK_TO_MILLISEC(cl) ((cl) / (CLOCKS_PER_SEC / 1000)) +#else +#define CLOCK_TO_MILLISEC(cl) ((cl) * 1000 / CLOCKS_PER_SEC) +#endif + +unsigned long +cputime () +{ + return CLOCK_TO_MILLISEC (clock ()); +} +#endif + +#define M * 1000000 + +#ifndef CLOCK +#if defined (__m88k__) +#define CLOCK 20 M +#elif defined (__i386__) +#define CLOCK (16.666667 M) +#elif defined (__m68k__) +#define CLOCK (20 M) +#elif defined (_IBMR2) +#define CLOCK (25 M) +#elif defined (__sparc__) +#define CLOCK (20 M) +#elif defined (__sun__) +#define CLOCK (20 M) +#elif defined (__mips) +#define CLOCK (40 M) +#elif defined (__hppa__) +#define CLOCK (50 M) +#elif defined (__alpha) +#define CLOCK (133 M) +#else +#error "Don't know CLOCK of your machine" +#endif +#endif + +#ifndef OPS +#define OPS 20000000 +#endif +#ifndef SIZE +#define SIZE 1000 +#endif +#ifndef TIMES +#define TIMES OPS/SIZE +#else +#undef OPS +#define OPS (SIZE*TIMES) +#endif + +main () +{ + mp_limb_t nptr[SIZE]; + mp_limb_t qptr[SIZE]; + mp_limb_t pptr[SIZE]; + mp_limb_t dlimb, rlimb, plimb; + mp_size_t nsize, qsize, psize; + int test; + + for (test = 0; ; test++) + { +#ifdef RANDOM + nsize = random () % SIZE + 1; +#else + nsize = SIZE; +#endif + + mpn_random2 (nptr, nsize); + + mpn_random2 (&dlimb, 1); + if (dlimb == 0) + abort (); + + rlimb = mpn_divmod_1 (qptr, nptr, nsize, dlimb); + qsize = nsize - (qptr[nsize - 1] == 0); + if (qsize == 0) + { + plimb = rlimb; + psize = qsize; + } + else + { + plimb = mpn_mul_1 (pptr, qptr, qsize, dlimb); + psize = qsize; + plimb += mpn_add_1 (pptr, pptr, psize, rlimb); + } + if (plimb != 0) + pptr[psize++] = plimb; + + + if (nsize != psize || mpn_cmp (nptr, pptr, nsize) != 0) + abort (); + } +} diff --git a/contrib/libgmp/mpn/tests/divrem.c b/contrib/libgmp/mpn/tests/divrem.c new file mode 100644 index 0000000..6eafc99 --- /dev/null +++ b/contrib/libgmp/mpn/tests/divrem.c @@ -0,0 +1,129 @@ +#include <stdio.h> +#include "gmp.h" +#include "gmp-impl.h" +#include "longlong.h" + +#ifndef USG +#include <sys/time.h> +#include <sys/resource.h> + +unsigned long +cputime () +{ + struct rusage rus; + + getrusage (0, &rus); + return rus.ru_utime.tv_sec * 1000 + rus.ru_utime.tv_usec / 1000; +} +#else +#include <time.h> + +#ifndef CLOCKS_PER_SEC +#define CLOCKS_PER_SEC 1000000 +#endif + +#if CLOCKS_PER_SEC >= 10000 +#define CLOCK_TO_MILLISEC(cl) ((cl) / (CLOCKS_PER_SEC / 1000)) +#else +#define CLOCK_TO_MILLISEC(cl) ((cl) * 1000 / CLOCKS_PER_SEC) +#endif + +unsigned long +cputime () +{ + return CLOCK_TO_MILLISEC (clock ()); +} +#endif + +#define M * 1000000 + +#ifndef CLOCK +#if defined (__m88k__) +#define CLOCK 20 M +#elif defined (__i386__) +#define CLOCK (16.666667 M) +#elif defined (__m68k__) +#define CLOCK (20 M) +#elif defined (_IBMR2) +#define CLOCK (25 M) +#elif defined (__sparc__) +#define CLOCK (20 M) +#elif defined (__sun__) +#define CLOCK (20 M) +#elif defined (__mips) +#define CLOCK (40 M) +#elif defined (__hppa__) +#define CLOCK (50 M) +#elif defined (__alpha) +#define CLOCK (133 M) +#else +#error "Don't know CLOCK of your machine" +#endif +#endif + +#ifndef OPS +#define OPS 20000000 +#endif +#ifndef SIZE +#define SIZE 100 +#endif +#ifndef TIMES +#define TIMES OPS/SIZE +#else +#undef OPS +#define OPS (SIZE*TIMES) +#endif + +main () +{ + mp_limb_t nptr[2 * SIZE]; + mp_limb_t dptr[SIZE]; + mp_limb_t qptr[2 * SIZE]; + mp_limb_t pptr[2 * SIZE]; + mp_limb_t rptr[2 * SIZE]; + mp_size_t nsize, dsize, qsize, rsize, psize; + int test; + mp_limb_t qlimb; + + for (test = 0; ; test++) + { +#ifdef RANDOM + nsize = random () % (2 * SIZE) + 1; + dsize = random () % nsize + 1; +#else + nsize = 2 * SIZE; + dsize = SIZE; +#endif + + mpn_random2 (nptr, nsize); + mpn_random2 (dptr, dsize); + dptr[dsize - 1] |= (mp_limb_t) 1 << (BITS_PER_MP_LIMB - 1); + + MPN_COPY (rptr, nptr, nsize); + qlimb = mpn_divrem (qptr, (mp_size_t) 0, rptr, nsize, dptr, dsize); + rsize = dsize; + qsize = nsize - dsize; + qptr[qsize] = qlimb; + qsize += qlimb; + if (qsize == 0 || qsize > 2 * SIZE) + { + continue; /* bogus */ + } + else + { + mp_limb_t cy; + if (qsize > dsize) + mpn_mul (pptr, qptr, qsize, dptr, dsize); + else + mpn_mul (pptr, dptr, dsize, qptr, qsize); + psize = qsize + dsize; + psize -= pptr[psize - 1] == 0; + cy = mpn_add (pptr, pptr, psize, rptr, rsize); + pptr[psize] = cy; + psize += cy; + } + + if (nsize != psize || mpn_cmp (nptr, pptr, nsize) != 0) + abort (); + } +} diff --git a/contrib/libgmp/mpn/tests/lshift.c b/contrib/libgmp/mpn/tests/lshift.c new file mode 100644 index 0000000..f50c5dc --- /dev/null +++ b/contrib/libgmp/mpn/tests/lshift.c @@ -0,0 +1,226 @@ +#include <stdio.h> +#include "gmp.h" +#include "gmp-impl.h" +#include "longlong.h" + +#ifndef USG +#include <sys/time.h> +#include <sys/resource.h> + +unsigned long +cputime () +{ + struct rusage rus; + + getrusage (0, &rus); + return rus.ru_utime.tv_sec * 1000 + rus.ru_utime.tv_usec / 1000; +} +#else +#include <time.h> + +#ifndef CLOCKS_PER_SEC +#define CLOCKS_PER_SEC 1000000 +#endif + +#if CLOCKS_PER_SEC >= 10000 +#define CLOCK_TO_MILLISEC(cl) ((cl) / (CLOCKS_PER_SEC / 1000)) +#else +#define CLOCK_TO_MILLISEC(cl) ((cl) * 1000 / CLOCKS_PER_SEC) +#endif + +unsigned long +cputime () +{ + return CLOCK_TO_MILLISEC (clock ()); +} +#endif + +#define M * 1000000 + +#ifndef CLOCK +#if defined (__m88k__) +#define CLOCK 20 M +#elif defined (__i386__) +#define CLOCK (16.666667 M) +#elif defined (__m68k__) +#define CLOCK (20 M) +#elif defined (_IBMR2) +#define CLOCK (25 M) +#elif defined (__sparc__) +#define CLOCK (20 M) +#elif defined (__sun__) +#define CLOCK (20 M) +#elif defined (__mips) +#define CLOCK (40 M) +#elif defined (__hppa__) +#define CLOCK (50 M) +#elif defined (__alpha) +#define CLOCK (133 M) +#else +#error "Don't know CLOCK of your machine" +#endif +#endif + +#ifndef OPS +#define OPS 10000000 +#endif +#ifndef SIZE +#define SIZE 496 +#endif +#ifndef TIMES +#define TIMES OPS/SIZE +#else +#undef OPS +#define OPS (SIZE*TIMES) +#endif + +mp_limb_t +refmpn_lshift (wp, up, usize, cnt) + register mp_ptr wp; + register mp_srcptr up; + mp_size_t usize; + register unsigned int cnt; +{ + register mp_limb_t high_limb, low_limb; + register unsigned sh_1, sh_2; + register mp_size_t i; + mp_limb_t retval; + +#ifdef DEBUG + if (usize == 0 || cnt == 0) + abort (); +#endif + + sh_1 = cnt; +#if 0 + if (sh_1 == 0) + { + if (wp != up) + { + /* Copy from high end to low end, to allow specified input/output + overlapping. */ + for (i = usize - 1; i >= 0; i--) + wp[i] = up[i]; + } + return 0; + } +#endif + + wp += 1; + sh_2 = BITS_PER_MP_LIMB - sh_1; + i = usize - 1; + low_limb = up[i]; + retval = low_limb >> sh_2; + high_limb = low_limb; + while (--i >= 0) + { + low_limb = up[i]; + wp[i] = (high_limb << sh_1) | (low_limb >> sh_2); + high_limb = low_limb; + } + wp[i] = high_limb << sh_1; + + return retval; +} + +#ifndef CNT +#define CNT 4 +#endif + +main (argc, argv) + int argc; + char **argv; +{ + mp_limb_t s1[SIZE]; + mp_limb_t dx[SIZE+2]; + mp_limb_t dy[SIZE+2]; + mp_limb_t cyx, cyy; + int i; + long t0, t; + int test; + int cnt = CNT; + mp_size_t size; + + for (test = 0; ; test++) + { +#ifdef RANDOM + size = (random () % SIZE + 1); +#else + size = SIZE; +#endif + mpn_random2 (s1, size); + + dx[size+1] = 0x12345678; + dy[size+1] = 0x12345678; + dx[0] = 0x87654321; + dy[0] = 0x87654321; + +#ifdef PRINT + mpn_print (s1, size); +#endif + t0 = cputime(); + for (i = 0; i < TIMES; i++) + cyx = refmpn_lshift (dx+1, s1, size, cnt); + t = cputime() - t0; +#if TIMES != 1 + printf ("refmpn_lshift: %5ldms (%.2f cycles/limb)\n", + t, + ((double) t * CLOCK) / (OPS * 1000.0)); +#endif +#ifdef PRINT + printf ("%*lX ", (int) (2 * sizeof(mp_limb_t)), cyx); mpn_print (dx+1, size); +#endif + + t0 = cputime(); + for (i = 0; i < TIMES; i++) + cyy = mpn_lshift (dx+1, s1, size, cnt); + t = cputime() - t0; +#if TIMES != 1 + printf ("mpn_lshift: %5ldms (%.2f cycles/limb)\n", + t, + ((double) t * CLOCK) / (OPS * 1000.0)); +#endif +#ifdef PRINT + printf ("%*lX ", (int) (2 * sizeof(mp_limb_t)), cyy); mpn_print (dx+1, size); +#endif + +#ifndef NOCHECK + /* Put garbage in the destination. */ + for (i = 1; i <= size; i++) + { + dx[i] = 0x7654321; + dy[i] = 0x1234567; + } + + cyx = refmpn_lshift (dx+1, s1, size, cnt); + cyy = mpn_lshift (dy+1, s1, size, cnt); + + if (cyx != cyy || mpn_cmp (dx, dy, size+2) != 0 + || dx[size+1] != 0x12345678 || dx[0] != 0x87654321) + { +#ifndef PRINT + printf ("%*lX ", (int) (2 * sizeof(mp_limb_t)), cyx); + mpn_print (dx+1, size); + printf ("%*lX ", (int) (2 * sizeof(mp_limb_t)), cyy); + mpn_print (dy+1, size); +#endif + abort(); + } +#endif + } +} + +mpn_print (mp_ptr p, mp_size_t size) +{ + mp_size_t i; + + for (i = size - 1; i >= 0; i--) + { + printf ("%0*lX", (int) (2 * sizeof(mp_limb_t)), p[i]); +#ifdef SPACE + if (i != 0) + printf (" "); +#endif + } + puts (""); +} diff --git a/contrib/libgmp/mpn/tests/mul_1.c b/contrib/libgmp/mpn/tests/mul_1.c new file mode 100644 index 0000000..2b522fa --- /dev/null +++ b/contrib/libgmp/mpn/tests/mul_1.c @@ -0,0 +1,212 @@ +#include <stdio.h> +#include "gmp.h" +#include "gmp-impl.h" +#include "longlong.h" + +#ifndef USG +#include <sys/time.h> +#include <sys/resource.h> + +unsigned long +cputime () +{ + struct rusage rus; + + getrusage (0, &rus); + return rus.ru_utime.tv_sec * 1000 + rus.ru_utime.tv_usec / 1000; +} +#else +#include <time.h> + +#ifndef CLOCKS_PER_SEC +#define CLOCKS_PER_SEC 1000000 +#endif + +#if CLOCKS_PER_SEC >= 10000 +#define CLOCK_TO_MILLISEC(cl) ((cl) / (CLOCKS_PER_SEC / 1000)) +#else +#define CLOCK_TO_MILLISEC(cl) ((cl) * 1000 / CLOCKS_PER_SEC) +#endif + +unsigned long +cputime () +{ + return CLOCK_TO_MILLISEC (clock ()); +} +#endif + +#define M * 1000000 + +#ifndef CLOCK +#if defined (__m88k__) +#define CLOCK 20 M +#elif defined (__i386__) +#define CLOCK (16.666667 M) +#elif defined (__m68k__) +#define CLOCK (20 M) +#elif defined (_IBMR2) +#define CLOCK (25 M) +#elif defined (__sparc__) +#define CLOCK (20 M) +#elif defined (__sun__) +#define CLOCK (20 M) +#elif defined (__mips) +#define CLOCK (40 M) +#elif defined (__hppa__) +#define CLOCK (50 M) +#elif defined (__alpha) +#define CLOCK (133 M) +#else +#error "Don't know CLOCK of your machine" +#endif +#endif + +#ifndef OPS +#define OPS 20000000 +#endif +#ifndef SIZE +#define SIZE 496 +#endif +#ifndef TIMES +#define TIMES OPS/SIZE +#else +#undef OPS +#define OPS (SIZE*TIMES) +#endif + +mp_limb_t +refmpn_mul_1 (res_ptr, s1_ptr, s1_size, s2_limb) + register mp_ptr res_ptr; + register mp_srcptr s1_ptr; + mp_size_t s1_size; + register mp_limb_t s2_limb; +{ + register mp_limb_t cy_limb; + register mp_size_t j; + register mp_limb_t prod_high, prod_low; + + /* The loop counter and index J goes from -S1_SIZE to -1. This way + the loop becomes faster. */ + j = -s1_size; + + /* Offset the base pointers to compensate for the negative indices. */ + s1_ptr -= j; + res_ptr -= j; + + cy_limb = 0; + do + { + umul_ppmm (prod_high, prod_low, s1_ptr[j], s2_limb); + + prod_low += cy_limb; + cy_limb = (prod_low < cy_limb) + prod_high; + + res_ptr[j] = prod_low; + } + while (++j != 0); + + return cy_limb; +} + +main (argc, argv) + int argc; + char **argv; +{ + mp_limb_t s1[SIZE]; + mp_limb_t dx[SIZE+2]; + mp_limb_t dy[SIZE+2]; + mp_limb_t cyx, cyy; + int i; + long t0, t; + int test; + mp_limb_t xlimb; + mp_size_t size; + + for (test = 0; ; test++) + { +#ifdef RANDOM + size = (random () % SIZE + 1); +#else + size = SIZE; +#endif + + mpn_random2 (s1, size); + mpn_random2 (dy+1, size); + + if (random () % 0x100 == 0) + xlimb = 0; + else + mpn_random2 (&xlimb, 1); + + dy[size+1] = 0x12345678; + dy[0] = 0x87654321; + +#if defined (PRINT) || defined (XPRINT) + printf ("xlimb=%*lX\n", (int) (2 * sizeof(mp_limb_t)), xlimb); +#endif +#ifdef PRINT + mpn_print (s1, size); +#endif + + MPN_COPY (dx, dy, size+2); + t0 = cputime(); + for (i = 0; i < TIMES; i++) + cyx = refmpn_mul_1 (dx+1, s1, size, xlimb); + t = cputime() - t0; +#if TIMES != 1 + printf ("refmpn_mul_1: %5ldms (%.2f cycles/limb)\n", + t, + ((double) t * CLOCK) / (OPS * 1000.0)); +#endif + + MPN_COPY (dx, dy, size+2); + t0 = cputime(); + for (i = 0; i < TIMES; i++) + cyy = mpn_mul_1 (dx+1, s1, size, xlimb); + t = cputime() - t0; +#if TIMES != 1 + printf ("mpn_mul_1: %5ldms (%.2f cycles/limb)\n", + t, + ((double) t * CLOCK) / (OPS * 1000.0)); +#endif + + cyx = refmpn_mul_1 (dx+1, s1, size, xlimb); + cyy = mpn_mul_1 (dy+1, s1, size, xlimb); + +#ifdef PRINT + printf ("%*lX ", (int) (2 * sizeof(mp_limb_t)), cyx); + mpn_print (dx+1, size); + printf ("%*lX ", (int) (2 * sizeof(mp_limb_t)), cyy); + mpn_print (dy+1, size); +#endif + +#ifndef NOCHECK + if (cyx != cyy || mpn_cmp (dx, dy, size+2) != 0 + || dx[size+1] != 0x12345678 || dx[0] != 0x87654321) + { +#ifndef PRINT + printf ("%*lX ", (int) (2 * sizeof(mp_limb_t)), cyx); + mpn_print (dx+1, size); + printf ("%*lX ", (int) (2 * sizeof(mp_limb_t)), cyy); + mpn_print (dy+1, size); +#endif + abort(); + } +#endif + } +} + +mpn_print (mp_ptr p, mp_size_t size) +{ + mp_size_t i; + + for (i = size - 1; i >= 0; i--) + { + printf ("%0*lX", (int) (2 * sizeof(mp_limb_t)), p[i]); +#ifdef SPACE + if (i != 0) + printf (" "); +#endif + } + puts (""); +} diff --git a/contrib/libgmp/mpn/tests/rshift.c b/contrib/libgmp/mpn/tests/rshift.c new file mode 100644 index 0000000..2482bf3 --- /dev/null +++ b/contrib/libgmp/mpn/tests/rshift.c @@ -0,0 +1,227 @@ +#include <stdio.h> +#include "gmp.h" +#include "gmp-impl.h" +#include "longlong.h" + +#ifndef USG +#include <sys/time.h> +#include <sys/resource.h> + +unsigned long +cputime () +{ + struct rusage rus; + + getrusage (0, &rus); + return rus.ru_utime.tv_sec * 1000 + rus.ru_utime.tv_usec / 1000; +} +#else +#include <time.h> + +#ifndef CLOCKS_PER_SEC +#define CLOCKS_PER_SEC 1000000 +#endif + +#if CLOCKS_PER_SEC >= 10000 +#define CLOCK_TO_MILLISEC(cl) ((cl) / (CLOCKS_PER_SEC / 1000)) +#else +#define CLOCK_TO_MILLISEC(cl) ((cl) * 1000 / CLOCKS_PER_SEC) +#endif + +unsigned long +cputime () +{ + return CLOCK_TO_MILLISEC (clock ()); +} +#endif + +#define M * 1000000 + +#ifndef CLOCK +#if defined (__m88k__) +#define CLOCK 20 M +#elif defined (__i386__) +#define CLOCK (16.666667 M) +#elif defined (__m68k__) +#define CLOCK (20 M) +#elif defined (_IBMR2) +#define CLOCK (25 M) +#elif defined (__sparc__) +#define CLOCK (20 M) +#elif defined (__sun__) +#define CLOCK (20 M) +#elif defined (__mips) +#define CLOCK (40 M) +#elif defined (__hppa__) +#define CLOCK (50 M) +#elif defined (__alpha) +#define CLOCK (133 M) +#else +#error "Don't know CLOCK of your machine" +#endif +#endif + +#ifndef OPS +#define OPS 10000000 +#endif +#ifndef SIZE +#define SIZE 496 +#endif +#ifndef TIMES +#define TIMES OPS/SIZE +#else +#undef OPS +#define OPS (SIZE*TIMES) +#endif + +mp_limb_t +refmpn_rshift (wp, up, usize, cnt) + register mp_ptr wp; + register mp_srcptr up; + mp_size_t usize; + register unsigned int cnt; +{ + register mp_limb_t high_limb, low_limb; + register unsigned sh_1, sh_2; + register mp_size_t i; + mp_limb_t retval; + +#ifdef DEBUG + if (usize == 0 || cnt == 0) + abort (); +#endif + + sh_1 = cnt; +#if 0 + if (sh_1 == 0) + { + if (wp != up) + { + /* Copy from low end to high end, to allow specified input/output + overlapping. */ + for (i = 0; i < usize; i++) + wp[i] = up[i]; + } + return 0; + } +#endif + + wp -= 1; + sh_2 = BITS_PER_MP_LIMB - sh_1; + high_limb = up[0]; + retval = high_limb << sh_2; + low_limb = high_limb; + + for (i = 1; i < usize; i++) + { + high_limb = up[i]; + wp[i] = (low_limb >> sh_1) | (high_limb << sh_2); + low_limb = high_limb; + } + low_limb >>= sh_1; + wp[i] = low_limb; + + return retval; +} + +#ifndef CNT +#define CNT 4 +#endif + +main (argc, argv) + int argc; + char **argv; +{ + mp_limb_t s1[SIZE]; + mp_limb_t dx[SIZE+2]; + mp_limb_t dy[SIZE+2]; + mp_limb_t cyx, cyy; + int i; + long t0, t; + int test; + int cnt = CNT; + mp_size_t size; + + for (test = 0; ; test++) + { +#ifdef RANDOM + size = (random () % SIZE + 1); +#else + size = SIZE; +#endif + mpn_random2 (s1, size); + + dx[size+1] = 0x12345678; + dy[size+1] = 0x12345678; + dx[0] = 0x87654321; + dy[0] = 0x87654321; + +#ifdef PRINT + mpn_print (s1, size); +#endif + t0 = cputime(); + for (i = 0; i < TIMES; i++) + cyx = refmpn_rshift (dx+1, s1, size, cnt); + t = cputime() - t0; +#if TIMES != 1 + printf ("refmpn_rshift: %5ldms (%.2f cycles/limb)\n", + t, + ((double) t * CLOCK) / (OPS * 1000.0)); +#endif +#ifdef PRINT + printf ("%*lX ", (int) (2 * sizeof(mp_limb_t)), cyx); mpn_print (dx+1, size); +#endif + + t0 = cputime(); + for (i = 0; i < TIMES; i++) + cyy = mpn_rshift (dx+1, s1, size, cnt); + t = cputime() - t0; +#if TIMES != 1 + printf ("mpn_rshift: %5ldms (%.2f cycles/limb)\n", + t, + ((double) t * CLOCK) / (OPS * 1000.0)); +#endif +#ifdef PRINT + printf ("%*lX ", (int) (2 * sizeof(mp_limb_t)), cyy); mpn_print (dx+1, size); +#endif + +#ifndef NOCHECK + /* Put garbage in the destination. */ + for (i = 1; i <= size; i++) + { + dx[i] = 0x7654321; + dy[i] = 0x1234567; + } + + cyx = refmpn_rshift (dx+1, s1, size, cnt); + cyy = mpn_rshift (dy+1, s1, size, cnt); + + if (cyx != cyy || mpn_cmp (dx, dy, size+2) != 0 + || dx[size+1] != 0x12345678 || dx[0] != 0x87654321) + { +#ifndef PRINT + printf ("%*lX ", (int) (2 * sizeof(mp_limb_t)), cyx); + mpn_print (dx+1, size); + printf ("%*lX ", (int) (2 * sizeof(mp_limb_t)), cyy); + mpn_print (dy+1, size); +#endif + abort(); + } +#endif + } +} + +mpn_print (mp_ptr p, mp_size_t size) +{ + mp_size_t i; + + for (i = size - 1; i >= 0; i--) + { + printf ("%0*lX", (int) (2 * sizeof(mp_limb_t)), p[i]); +#ifdef SPACE + if (i != 0) + printf (" "); +#endif + } + puts (""); +} diff --git a/contrib/libgmp/mpn/tests/sub_n.c b/contrib/libgmp/mpn/tests/sub_n.c new file mode 100644 index 0000000..2b9031b --- /dev/null +++ b/contrib/libgmp/mpn/tests/sub_n.c @@ -0,0 +1,211 @@ +#include <stdio.h> +#include "gmp.h" +#include "gmp-impl.h" + +#ifndef USG +#include <sys/time.h> +#include <sys/resource.h> + +unsigned long +cputime () +{ + struct rusage rus; + + getrusage (0, &rus); + return rus.ru_utime.tv_sec * 1000 + rus.ru_utime.tv_usec / 1000; +} +#else +#include <time.h> + +#ifndef CLOCKS_PER_SEC +#define CLOCKS_PER_SEC 1000000 +#endif + +#if CLOCKS_PER_SEC >= 10000 +#define CLOCK_TO_MILLISEC(cl) ((cl) / (CLOCKS_PER_SEC / 1000)) +#else +#define CLOCK_TO_MILLISEC(cl) ((cl) * 1000 / CLOCKS_PER_SEC) +#endif + +unsigned long +cputime () +{ + return CLOCK_TO_MILLISEC (clock ()); +} +#endif + +#define M * 1000000 + +#ifndef CLOCK +#if defined (__m88k__) +#define CLOCK 20 M +#elif defined (__i386__) +#define CLOCK (16.666667 M) +#elif defined (__m68k__) +#define CLOCK (20 M) +#elif defined (_IBMR2) +#define CLOCK (25 M) +#elif defined (__sparc__) +#define CLOCK (20 M) +#elif defined (__sun__) +#define CLOCK (20 M) +#elif defined (__mips) +#define CLOCK (40 M) +#elif defined (__hppa__) +#define CLOCK (50 M) +#elif defined (__alpha) +#define CLOCK (133 M) +#else +#error "Don't know CLOCK of your machine" +#endif +#endif + +#ifndef OPS +#define OPS 10000000 +#endif +#ifndef SIZE +#define SIZE 328 +#endif +#ifndef TIMES +#define TIMES OPS/SIZE +#else +#undef OPS +#define OPS (SIZE*TIMES) +#endif + + +mp_limb_t +#if __STDC__ +refmpn_sub_n (mp_ptr res_ptr, + mp_srcptr s1_ptr, mp_srcptr s2_ptr, mp_size_t size) +#else +refmpn_sub_n (res_ptr, s1_ptr, s2_ptr, size) + register mp_ptr res_ptr; + register mp_srcptr s1_ptr; + register mp_srcptr s2_ptr; + mp_size_t size; +#endif +{ + register mp_limb_t x, y, cy; + register mp_size_t j; + + /* The loop counter and index J goes from -SIZE to -1. This way + the loop becomes faster. */ + j = -size; + + /* Offset the base pointers to compensate for the negative indices. */ + s1_ptr -= j; + s2_ptr -= j; + res_ptr -= j; + + cy = 0; + do + { + y = s2_ptr[j]; + x = s1_ptr[j]; + y += cy; /* add previous carry to subtrahend */ + cy = (y < cy); /* get out carry from that addition */ + y = x - y; /* main subtract */ + cy = (y > x) + cy; /* get out carry from the subtract, combine */ + res_ptr[j] = y; + } + while (++j != 0); + + return cy; +} + +main (argc, argv) + int argc; + char **argv; +{ + mp_limb_t s1[SIZE]; + mp_limb_t s2[SIZE]; + mp_limb_t dx[SIZE+1]; + mp_limb_t dy[SIZE+1]; + int cyx, cyy; + int i; + long t0, t; + int test; + mp_size_t size; + + for (test = 0; ; test++) + { +#ifdef RANDOM + size = (random () % SIZE + 1); +#else + size = SIZE; +#endif + + mpn_random2 (s1, size); + mpn_random2 (s2, size); + + dx[size] = 0x12345678; + dy[size] = 0x12345678; + +#ifdef PRINT + mpn_print (s1, size); + mpn_print (s2, size); +#endif + t0 = cputime(); + for (i = 0; i < TIMES; i++) + cyx = refmpn_sub_n (dx, s1, s2, size); + t = cputime() - t0; +#if TIMES != 1 + printf ("refmpn_sub_n: %ldms (%.2f cycles/limb)\n", + t, + ((double) t * CLOCK) / (OPS * 1000.0)); +#endif +#ifdef PRINT + printf ("%d ", cyx); mpn_print (dx, size); +#endif + + t0 = cputime(); + for (i = 0; i < TIMES; i++) + cyx = mpn_sub_n (dx, s1, s2, size); + t = cputime() - t0; +#if TIMES != 1 + printf ("mpn_sub_n: %ldms (%.2f cycles/limb)\n", + t, + ((double) t * CLOCK) / (OPS * 1000.0)); +#endif +#ifdef PRINT + printf ("%d ", cyx); mpn_print (dx, size); +#endif + +#ifndef NOCHECK + /* Put garbage in the destination. */ + for (i = 0; i < size; i++) + { + dx[i] = 0x7654321; + dy[i] = 0x1234567; + } + + cyx = refmpn_sub_n (dx, s1, s2, size); + cyy = mpn_sub_n (dy, s1, s2, size); + if (cyx != cyy || mpn_cmp (dx, dy, size) != 0 + || dx[size] != 0x12345678 || dy[size] != 0x12345678) + { +#ifndef PRINT + printf ("%d ", cyx); mpn_print (dx, size); + printf ("%d ", cyy); mpn_print (dy, size); +#endif + abort(); + } +#endif + } +} + +mpn_print (mp_ptr p, mp_size_t size) +{ + mp_size_t i; + + for (i = size - 1; i >= 0; i--) + { + printf ("%0*lX", (int) (2 * sizeof(mp_limb_t)), p[i]); +#ifdef SPACE + if (i != 0) + printf (" "); +#endif + } + puts (""); +} diff --git a/contrib/libgmp/mpn/tests/submul_1.c b/contrib/libgmp/mpn/tests/submul_1.c new file mode 100644 index 0000000..0e464e6 --- /dev/null +++ b/contrib/libgmp/mpn/tests/submul_1.c @@ -0,0 +1,218 @@ +#include <stdio.h> +#include "gmp.h" +#include "gmp-impl.h" +#include "longlong.h" + +#ifndef USG +#include <sys/time.h> +#include <sys/resource.h> + +unsigned long +cputime () +{ + struct rusage rus; + + getrusage (0, &rus); + return rus.ru_utime.tv_sec * 1000 + rus.ru_utime.tv_usec / 1000; +} +#else +#include <time.h> + +#ifndef CLOCKS_PER_SEC +#define CLOCKS_PER_SEC 1000000 +#endif + +#if CLOCKS_PER_SEC >= 10000 +#define CLOCK_TO_MILLISEC(cl) ((cl) / (CLOCKS_PER_SEC / 1000)) +#else +#define CLOCK_TO_MILLISEC(cl) ((cl) * 1000 / CLOCKS_PER_SEC) +#endif + +unsigned long +cputime () +{ + return CLOCK_TO_MILLISEC (clock ()); +} +#endif + +#define M * 1000000 + +#ifndef CLOCK +#if defined (__m88k__) +#define CLOCK 20 M +#elif defined (__i386__) +#define CLOCK (16.666667 M) +#elif defined (__m68k__) +#define CLOCK (20 M) +#elif defined (_IBMR2) +#define CLOCK (25 M) +#elif defined (__sparc__) +#define CLOCK (20 M) +#elif defined (__sun__) +#define CLOCK (20 M) +#elif defined (__mips) +#define CLOCK (40 M) +#elif defined (__hppa__) +#define CLOCK (50 M) +#elif defined (__alpha) +#define CLOCK (133 M) +#else +#error "Don't know CLOCK of your machine" +#endif +#endif + +#ifndef OPS +#define OPS 20000000 +#endif +#ifndef SIZE +#define SIZE 496 +#endif +#ifndef TIMES +#define TIMES OPS/SIZE +#else +#undef OPS +#define OPS (SIZE*TIMES) +#endif + +mp_limb_t +refmpn_submul_1 (res_ptr, s1_ptr, s1_size, s2_limb) + register mp_ptr res_ptr; + register mp_srcptr s1_ptr; + mp_size_t s1_size; + register mp_limb_t s2_limb; +{ + register mp_limb_t cy_limb; + register mp_size_t j; + register mp_limb_t prod_high, prod_low; + register mp_limb_t x; + + /* The loop counter and index J goes from -SIZE to -1. This way + the loop becomes faster. */ + j = -s1_size; + + /* Offset the base pointers to compensate for the negative indices. */ + res_ptr -= j; + s1_ptr -= j; + + cy_limb = 0; + do + { + umul_ppmm (prod_high, prod_low, s1_ptr[j], s2_limb); + + prod_low += cy_limb; + cy_limb = (prod_low < cy_limb) + prod_high; + + x = res_ptr[j]; + prod_low = x - prod_low; + cy_limb += (prod_low > x); + res_ptr[j] = prod_low; + } + while (++j != 0); + + return cy_limb; +} + +main (argc, argv) + int argc; + char **argv; +{ + mp_limb_t s1[SIZE]; + mp_limb_t dx[SIZE+2]; + mp_limb_t dy[SIZE+2]; + mp_limb_t cyx, cyy; + int i; + long t0, t; + int test; + mp_limb_t xlimb; + mp_size_t size; + + for (test = 0; ; test++) + { +#ifdef RANDOM + size = (random () % SIZE + 1); +#else + size = SIZE; +#endif + + mpn_random2 (s1, size); + mpn_random2 (dy+1, size); + + if (random () % 0x100 == 0) + xlimb = 0; + else + mpn_random2 (&xlimb, 1); + + dy[size+1] = 0x12345678; + dy[0] = 0x87654321; + +#if defined (PRINT) || defined (XPRINT) + printf ("xlimb=%*lX\n", (int) (2 * sizeof(mp_limb_t)), xlimb); +#endif +#ifdef PRINT + mpn_print (dy+1, size); + mpn_print (s1, size); +#endif + + MPN_COPY (dx, dy, size+2); + t0 = cputime(); + for (i = 0; i < TIMES; i++) + cyx = refmpn_submul_1 (dx+1, s1, size, xlimb); + t = cputime() - t0; +#if TIMES != 1 + printf ("refmpn_submul_1: %5ldms (%.2f cycles/limb)\n", + t, + ((double) t * CLOCK) / (OPS * 1000.0)); +#endif + + MPN_COPY (dx, dy, size+2); + t0 = cputime(); + for (i = 0; i < TIMES; i++) + cyy = mpn_submul_1 (dx+1, s1, size, xlimb); + t = cputime() - t0; +#if TIMES != 1 + printf ("mpn_submul_1: %5ldms (%.2f cycles/limb)\n", + t, + ((double) t * CLOCK) / (OPS * 1000.0)); +#endif + + MPN_COPY (dx, dy, size+2); + cyx = refmpn_submul_1 (dx+1, s1, size, xlimb); + cyy = mpn_submul_1 (dy+1, s1, size, xlimb); + +#ifdef PRINT + printf ("%*lX ", (int) (2 * sizeof(mp_limb_t)), cyx); + mpn_print (dx+1, size); + printf ("%*lX ", (int) (2 * sizeof(mp_limb_t)), cyy); + mpn_print (dy+1, size); +#endif + +#ifndef NOCHECK + if (cyx != cyy || mpn_cmp (dx, dy, size+2) != 0 + || dx[size+1] != 0x12345678 || dx[0] != 0x87654321) + { +#ifndef PRINT + printf ("%*lX ", (int) (2 * sizeof(mp_limb_t)), cyx); + mpn_print (dx+1, size); + printf ("%*lX ", (int) (2 * sizeof(mp_limb_t)), cyy); + mpn_print (dy+1, size); +#endif + abort(); + } +#endif + } +} + +mpn_print (mp_ptr p, mp_size_t size) +{ + mp_size_t i; + + for (i = size - 1; i >= 0; i--) + { + printf ("%0*lX", (int) (2 * sizeof(mp_limb_t)), p[i]); +#ifdef SPACE + if (i != 0) + printf (" "); +#endif + } + puts (""); +} diff --git a/contrib/libgmp/mpn/tests/tst-addsub.c b/contrib/libgmp/mpn/tests/tst-addsub.c new file mode 100644 index 0000000..e02b9d5 --- /dev/null +++ b/contrib/libgmp/mpn/tests/tst-addsub.c @@ -0,0 +1,164 @@ +#include <stdio.h> +#include <stdlib.h> +#include "gmp.h" +#include "gmp-impl.h" + +#define ADD 1 +#define SUB 2 + +#ifndef METHOD +#define METHOD ADD +#endif + +#if METHOD == ADD +#define REFCALL refmpn_add_n +#define TESTCALL mpn_add_n +#endif + +#if METHOD == SUB +#define REFCALL refmpn_sub_n +#define TESTCALL mpn_sub_n +#endif + +mp_limb_t refmpn_add_n (); +mp_limb_t refmpn_sub_n (); + +#define SIZE 100 + +main (argc, argv) + int argc; + char **argv; +{ + mp_size_t alloc_size, max_size, size, i, cumul_size; + mp_ptr s1, s2, dx, dy; + int s1_align, s2_align, d_align; + long pass, n_passes; + mp_limb_t cx, cy; + + max_size = SIZE; + n_passes = 1000000; + + argc--; argv++; + if (argc) + { + max_size = atol (*argv); + argc--; argv++; + } + + alloc_size = max_size + 32; + s1 = malloc (alloc_size * BYTES_PER_MP_LIMB); + s2 = malloc (alloc_size * BYTES_PER_MP_LIMB); + dx = malloc (alloc_size * BYTES_PER_MP_LIMB); + dy = malloc (alloc_size * BYTES_PER_MP_LIMB); + + cumul_size = 0; + for (pass = 0; pass < n_passes; pass++) + { + cumul_size += size; + if (cumul_size >= 1000000) + { + cumul_size -= 1000000; + printf ("%d ", pass); fflush (stdout); + } + s1_align = random () % 32; + s2_align = random () % 32; + d_align = random () % 32; + + size = random () % max_size + 1; + + mpn_random2 (s1 + s1_align, size); + mpn_random2 (s2 + s2_align, size); + + for (i = 0; i < alloc_size; i++) + dx[i] = dy[i] = i + 0x9876500; + + cx = TESTCALL (dx + d_align, s1 + s1_align, s2 + s2_align, size); + cy = REFCALL (dy + d_align, s1 + s1_align, s2 + s2_align, size); + + if (cx != cy || mpn_cmp (dx, dy, alloc_size) != 0) + abort (); + } + + printf ("%d passes OK\n", n_passes); + exit (0); +} + +mp_limb_t +#if __STDC__ +refmpn_add_n (mp_ptr res_ptr, + mp_srcptr s1_ptr, mp_srcptr s2_ptr, mp_size_t size) +#else +refmpn_add_n (res_ptr, s1_ptr, s2_ptr, size) + register mp_ptr res_ptr; + register mp_srcptr s1_ptr; + register mp_srcptr s2_ptr; + mp_size_t size; +#endif +{ + register mp_limb_t x, y, cy; + register mp_size_t j; + + /* The loop counter and index J goes from -SIZE to -1. This way + the loop becomes faster. */ + j = -size; + + /* Offset the base pointers to compensate for the negative indices. */ + s1_ptr -= j; + s2_ptr -= j; + res_ptr -= j; + + cy = 0; + do + { + y = s2_ptr[j]; + x = s1_ptr[j]; + y += cy; /* add previous carry to one addend */ + cy = (y < cy); /* get out carry from that addition */ + y = x + y; /* add other addend */ + cy = (y < x) + cy; /* get out carry from that add, combine */ + res_ptr[j] = y; + } + while (++j != 0); + + return cy; +} + +mp_limb_t +#if __STDC__ +refmpn_sub_n (mp_ptr res_ptr, + mp_srcptr s1_ptr, mp_srcptr s2_ptr, mp_size_t size) +#else +refmpn_sub_n (res_ptr, s1_ptr, s2_ptr, size) + register mp_ptr res_ptr; + register mp_srcptr s1_ptr; + register mp_srcptr s2_ptr; + mp_size_t size; +#endif +{ + register mp_limb_t x, y, cy; + register mp_size_t j; + + /* The loop counter and index J goes from -SIZE to -1. This way + the loop becomes faster. */ + j = -size; + + /* Offset the base pointers to compensate for the negative indices. */ + s1_ptr -= j; + s2_ptr -= j; + res_ptr -= j; + + cy = 0; + do + { + y = s2_ptr[j]; + x = s1_ptr[j]; + y += cy; /* add previous carry to subtrahend */ + cy = (y < cy); /* get out carry from that addition */ + y = x - y; /* main subtract */ + cy = (y > x) + cy; /* get out carry from the subtract, combine */ + res_ptr[j] = y; + } + while (++j != 0); + + return cy; +} diff --git a/contrib/libgmp/mpn/x86/add_n.S b/contrib/libgmp/mpn/x86/add_n.S new file mode 100644 index 0000000..5bbbd0d --- /dev/null +++ b/contrib/libgmp/mpn/x86/add_n.S @@ -0,0 +1,106 @@ +/* i80386 __mpn_add_n -- Add two limb vectors of the same length > 0 and store +sum in a third limb vector. + +Copyright (C) 1992, 1994, 1995 Free Software Foundation, Inc. + +This file is part of the GNU MP Library. + +The GNU MP Library is free software; you can redistribute it and/or modify +it under the terms of the GNU Library General Public License as published by +the Free Software Foundation; either version 2 of the License, or (at your +option) any later version. + +The GNU MP Library is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public +License for more details. + +You should have received a copy of the GNU Library General Public License +along with the GNU MP Library; see the file COPYING.LIB. If not, write to +the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, +MA 02111-1307, USA. */ + +/* + INPUT PARAMETERS + res_ptr (sp + 4) + s1_ptr (sp + 8) + s2_ptr (sp + 12) + size (sp + 16) +*/ + +#include "sysdep.h" +#include "asm-syntax.h" + +.text + ALIGN (3) + .globl C_SYMBOL_NAME(__mpn_add_n) +C_SYMBOL_NAME(__mpn_add_n:) + pushl %edi + pushl %esi + + movl 12(%esp),%edi /* res_ptr */ + movl 16(%esp),%esi /* s1_ptr */ + movl 20(%esp),%edx /* s2_ptr */ + movl 24(%esp),%ecx /* size */ + + movl %ecx,%eax + shrl $3,%ecx /* compute count for unrolled loop */ + negl %eax + andl $7,%eax /* get index where to start loop */ + jz Loop /* necessary special case for 0 */ + incl %ecx /* adjust loop count */ + shll $2,%eax /* adjustment for pointers... */ + subl %eax,%edi /* ... since they are offset ... */ + subl %eax,%esi /* ... by a constant when we ... */ + subl %eax,%edx /* ... enter the loop */ + shrl $2,%eax /* restore previous value */ +#ifdef PIC +/* Calculate start address in loop for PIC. Due to limitations in some + assemblers, Loop-L0-3 cannot be put into the leal */ + call L0 +L0: leal (%eax,%eax,8),%eax + addl (%esp),%eax + addl $(Loop-L0-3),%eax + addl $4,%esp +#else +/* Calculate start address in loop for non-PIC. */ + leal (Loop - 3)(%eax,%eax,8),%eax +#endif + jmp *%eax /* jump into loop */ + ALIGN (3) +Loop: movl (%esi),%eax + adcl (%edx),%eax + movl %eax,(%edi) + movl 4(%esi),%eax + adcl 4(%edx),%eax + movl %eax,4(%edi) + movl 8(%esi),%eax + adcl 8(%edx),%eax + movl %eax,8(%edi) + movl 12(%esi),%eax + adcl 12(%edx),%eax + movl %eax,12(%edi) + movl 16(%esi),%eax + adcl 16(%edx),%eax + movl %eax,16(%edi) + movl 20(%esi),%eax + adcl 20(%edx),%eax + movl %eax,20(%edi) + movl 24(%esi),%eax + adcl 24(%edx),%eax + movl %eax,24(%edi) + movl 28(%esi),%eax + adcl 28(%edx),%eax + movl %eax,28(%edi) + leal 32(%edi),%edi + leal 32(%esi),%esi + leal 32(%edx),%edx + decl %ecx + jnz Loop + + sbbl %eax,%eax + negl %eax + + popl %esi + popl %edi + ret diff --git a/contrib/libgmp/mpn/x86/addmul_1.S b/contrib/libgmp/mpn/x86/addmul_1.S new file mode 100644 index 0000000..c11209d --- /dev/null +++ b/contrib/libgmp/mpn/x86/addmul_1.S @@ -0,0 +1,76 @@ +/* i80386 __mpn_addmul_1 -- Multiply a limb vector with a limb and add + the result to a second limb vector. + +Copyright (C) 1992, 1994 Free Software Foundation, Inc. + +This file is part of the GNU MP Library. + +The GNU MP Library is free software; you can redistribute it and/or modify +it under the terms of the GNU Library General Public License as published by +the Free Software Foundation; either version 2 of the License, or (at your +option) any later version. + +The GNU MP Library is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public +License for more details. + +You should have received a copy of the GNU Library General Public License +along with the GNU MP Library; see the file COPYING.LIB. If not, write to +the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, +MA 02111-1307, USA. */ + +/* + INPUT PARAMETERS + res_ptr (sp + 4) + s1_ptr (sp + 8) + size (sp + 12) + s2_limb (sp + 16) +*/ + +#include "sysdep.h" +#include "asm-syntax.h" + +#define res_ptr edi +#define s1_ptr esi +#define size ecx +#define s2_limb ebp + + TEXT + ALIGN (3) + GLOBL C_SYMBOL_NAME(__mpn_addmul_1) +C_SYMBOL_NAME(__mpn_addmul_1:) + + INSN1(push,l ,R(edi)) + INSN1(push,l ,R(esi)) + INSN1(push,l ,R(ebx)) + INSN1(push,l ,R(ebp)) + + INSN2(mov,l ,R(res_ptr),MEM_DISP(esp,20)) + INSN2(mov,l ,R(s1_ptr),MEM_DISP(esp,24)) + INSN2(mov,l ,R(size),MEM_DISP(esp,28)) + INSN2(mov,l ,R(s2_limb),MEM_DISP(esp,32)) + + INSN2(lea,l ,R(res_ptr),MEM_INDEX(res_ptr,size,4)) + INSN2(lea,l ,R(s1_ptr),MEM_INDEX(s1_ptr,size,4)) + INSN1(neg,l ,R(size)) + INSN2(xor,l ,R(ebx),R(ebx)) + ALIGN (3) +Loop: + INSN2(mov,l ,R(eax),MEM_INDEX(s1_ptr,size,4)) + INSN1(mul,l ,R(s2_limb)) + INSN2(add,l ,R(eax),R(ebx)) + INSN2(adc,l ,R(edx),$0) + INSN2(add,l ,MEM_INDEX(res_ptr,size,4),R(eax)) + INSN2(adc,l ,R(edx),$0) + INSN2(mov,l ,R(ebx),R(edx)) + + INSN1(inc,l ,R(size)) + INSN1(jnz, ,Loop) + INSN2(mov,l ,R(eax),R(ebx)) + + INSN1(pop,l ,R(ebp)) + INSN1(pop,l ,R(ebx)) + INSN1(pop,l ,R(esi)) + INSN1(pop,l ,R(edi)) + ret diff --git a/contrib/libgmp/mpn/x86/lshift.S b/contrib/libgmp/mpn/x86/lshift.S new file mode 100644 index 0000000..8173b92 --- /dev/null +++ b/contrib/libgmp/mpn/x86/lshift.S @@ -0,0 +1,85 @@ +/* i80386 __mpn_lshift -- + +Copyright (C) 1992, 1994 Free Software Foundation, Inc. + +This file is part of the GNU MP Library. + +The GNU MP Library is free software; you can redistribute it and/or modify +it under the terms of the GNU Library General Public License as published by +the Free Software Foundation; either version 2 of the License, or (at your +option) any later version. + +The GNU MP Library is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public +License for more details. + +You should have received a copy of the GNU Library General Public License +along with the GNU MP Library; see the file COPYING.LIB. If not, write to +the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, +MA 02111-1307, USA. */ + +/* + INPUT PARAMETERS + res_ptr (sp + 4) + s_ptr (sp + 8) + size (sp + 12) + cnt (sp + 16) +*/ + +#include "sysdep.h" +#include "asm-syntax.h" + +.text + ALIGN (3) + .globl C_SYMBOL_NAME(__mpn_lshift) +C_SYMBOL_NAME(__mpn_lshift:) + pushl %edi + pushl %esi + pushl %ebx + + movl 16(%esp),%edi /* res_ptr */ + movl 20(%esp),%esi /* s_ptr */ + movl 24(%esp),%edx /* size */ + movl 28(%esp),%ecx /* cnt */ + + subl $4,%esi /* adjust s_ptr */ + + movl (%esi,%edx,4),%ebx /* read most significant limb */ + xorl %eax,%eax + shldl %cl,%ebx,%eax /* compute carry limb */ + decl %edx + jz Lend + pushl %eax /* push carry limb onto stack */ + testb $1,%edx + jnz L1 /* enter loop in the middle */ + movl %ebx,%eax + + ALIGN (3) +Loop: movl (%esi,%edx,4),%ebx /* load next lower limb */ + shldl %cl,%ebx,%eax /* compute result limb */ + movl %eax,(%edi,%edx,4) /* store it */ + decl %edx +L1: movl (%esi,%edx,4),%eax + shldl %cl,%eax,%ebx + movl %ebx,(%edi,%edx,4) + decl %edx + jnz Loop + + shll %cl,%eax /* compute least significant limb */ + movl %eax,(%edi) /* store it */ + + popl %eax /* pop carry limb */ + + popl %ebx + popl %esi + popl %edi + ret + +Lend: shll %cl,%ebx /* compute least significant limb */ + movl %ebx,(%edi) /* store it */ + + popl %ebx + popl %esi + popl %edi + ret diff --git a/contrib/libgmp/mpn/x86/mul_1.S b/contrib/libgmp/mpn/x86/mul_1.S new file mode 100644 index 0000000..b271399 --- /dev/null +++ b/contrib/libgmp/mpn/x86/mul_1.S @@ -0,0 +1,75 @@ +/* i80386 __mpn_mul_1 -- Multiply a limb vector with a limb and store + the result in a second limb vector. + +Copyright (C) 1992, 1994 Free Software Foundation, Inc. + +This file is part of the GNU MP Library. + +The GNU MP Library is free software; you can redistribute it and/or modify +it under the terms of the GNU Library General Public License as published by +the Free Software Foundation; either version 2 of the License, or (at your +option) any later version. + +The GNU MP Library is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public +License for more details. + +You should have received a copy of the GNU Library General Public License +along with the GNU MP Library; see the file COPYING.LIB. If not, write to +the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, +MA 02111-1307, USA. */ + +/* + INPUT PARAMETERS + res_ptr (sp + 4) + s1_ptr (sp + 8) + size (sp + 12) + s2_limb (sp + 16) +*/ + +#include "sysdep.h" +#include "asm-syntax.h" + +#define res_ptr edi +#define s1_ptr esi +#define size ecx +#define s2_limb ebp + + TEXT + ALIGN (3) + GLOBL C_SYMBOL_NAME(__mpn_mul_1) +C_SYMBOL_NAME(__mpn_mul_1:) + + INSN1(push,l ,R(edi)) + INSN1(push,l ,R(esi)) + INSN1(push,l ,R(ebx)) + INSN1(push,l ,R(ebp)) + + INSN2(mov,l ,R(res_ptr),MEM_DISP(esp,20)) + INSN2(mov,l ,R(s1_ptr),MEM_DISP(esp,24)) + INSN2(mov,l ,R(size),MEM_DISP(esp,28)) + INSN2(mov,l ,R(s2_limb),MEM_DISP(esp,32)) + + INSN2(lea,l ,R(res_ptr),MEM_INDEX(res_ptr,size,4)) + INSN2(lea,l ,R(s1_ptr),MEM_INDEX(s1_ptr,size,4)) + INSN1(neg,l ,R(size)) + INSN2(xor,l ,R(ebx),R(ebx)) + ALIGN (3) +Loop: + INSN2(mov,l ,R(eax),MEM_INDEX(s1_ptr,size,4)) + INSN1(mul,l ,R(s2_limb)) + INSN2(add,l ,R(eax),R(ebx)) + INSN2(mov,l ,MEM_INDEX(res_ptr,size,4),R(eax)) + INSN2(adc,l ,R(edx),$0) + INSN2(mov,l ,R(ebx),R(edx)) + + INSN1(inc,l ,R(size)) + INSN1(jnz, ,Loop) + INSN2(mov,l ,R(eax),R(ebx)) + + INSN1(pop,l ,R(ebp)) + INSN1(pop,l ,R(ebx)) + INSN1(pop,l ,R(esi)) + INSN1(pop,l ,R(edi)) + ret diff --git a/contrib/libgmp/mpn/x86/pentium/README b/contrib/libgmp/mpn/x86/pentium/README new file mode 100644 index 0000000..d73b082 --- /dev/null +++ b/contrib/libgmp/mpn/x86/pentium/README @@ -0,0 +1,26 @@ +This directory contains mpn functions optimized for Intel Pentium +processors. + +RELEVANT OPTIMIZATION ISSUES + +1. Pentium doesn't allocate cache lines on writes, unlike most other modern +processors. Since the functions in the mpn class do array writes, we have to +handle allocating the destination cache lines by reading a word from it in the +loops, to achieve the best performance. + +2. Pairing of memory operations requires that the two issued operations refer +to different cache banks. The simplest way to insure this is to read/write +two words from the same object. If we make operations on different objects, +they might or might not be to the same cache bank. + +STATUS + +1. mpn_lshift and mpn_rshift run at about 6 cycles/limb, but the Pentium +documentation indicates that they should take only 43/8 = 5.375 cycles/limb, +or 5 cycles/limb asymptotically. + +2. mpn_add_n and mpn_sub_n run at asymptotically 2 cycles/limb. Due to loop +overhead and other delays (cache refill?), they run at or near 2.5 cycles/limb. + +3. mpn_mul_1, mpn_addmul_1, mpn_submul_1 all run 1 cycle faster than they +should... diff --git a/contrib/libgmp/mpn/x86/pentium/add_n.S b/contrib/libgmp/mpn/x86/pentium/add_n.S new file mode 100644 index 0000000..ac6f281 --- /dev/null +++ b/contrib/libgmp/mpn/x86/pentium/add_n.S @@ -0,0 +1,130 @@ +/* Pentium __mpn_add_n -- Add two limb vectors of the same length > 0 and store + sum in a third limb vector. + +Copyright (C) 1992, 1994, 1995, 1996 Free Software Foundation, Inc. + +This file is part of the GNU MP Library. + +The GNU MP Library is free software; you can redistribute it and/or modify +it under the terms of the GNU Library General Public License as published by +the Free Software Foundation; either version 2 of the License, or (at your +option) any later version. + +The GNU MP Library is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public +License for more details. + +You should have received a copy of the GNU Library General Public License +along with the GNU MP Library; see the file COPYING.LIB. If not, write to +the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, +MA 02111-1307, USA. */ + +/* + INPUT PARAMETERS + res_ptr (sp + 4) + s1_ptr (sp + 8) + s2_ptr (sp + 12) + size (sp + 16) +*/ + +#include "sysdep.h" +#include "asm-syntax.h" + +.text + ALIGN (3) + .globl C_SYMBOL_NAME(__mpn_add_n) +C_SYMBOL_NAME(__mpn_add_n:) + pushl %edi + pushl %esi + pushl %ebx + pushl %ebp + + movl 20(%esp),%edi /* res_ptr */ + movl 24(%esp),%esi /* s1_ptr */ + movl 28(%esp),%ebp /* s2_ptr */ + movl 32(%esp),%ecx /* size */ + + movl (%ebp),%ebx + + decl %ecx + movl %ecx,%edx + shrl $3,%ecx + andl $7,%edx + testl %ecx,%ecx /* zero carry flag */ + jz Lend + pushl %edx + + ALIGN (3) +Loop: movl 28(%edi),%eax /* fetch destination cache line */ + leal 32(%edi),%edi + +L1: movl (%esi),%eax + movl 4(%esi),%edx + adcl %ebx,%eax + movl 4(%ebp),%ebx + adcl %ebx,%edx + movl 8(%ebp),%ebx + movl %eax,-32(%edi) + movl %edx,-28(%edi) + +L2: movl 8(%esi),%eax + movl 12(%esi),%edx + adcl %ebx,%eax + movl 12(%ebp),%ebx + adcl %ebx,%edx + movl 16(%ebp),%ebx + movl %eax,-24(%edi) + movl %edx,-20(%edi) + +L3: movl 16(%esi),%eax + movl 20(%esi),%edx + adcl %ebx,%eax + movl 20(%ebp),%ebx + adcl %ebx,%edx + movl 24(%ebp),%ebx + movl %eax,-16(%edi) + movl %edx,-12(%edi) + +L4: movl 24(%esi),%eax + movl 28(%esi),%edx + adcl %ebx,%eax + movl 28(%ebp),%ebx + adcl %ebx,%edx + movl 32(%ebp),%ebx + movl %eax,-8(%edi) + movl %edx,-4(%edi) + + leal 32(%esi),%esi + leal 32(%ebp),%ebp + decl %ecx + jnz Loop + + popl %edx +Lend: + decl %edx /* test %edx w/o clobbering carry */ + js Lend2 + incl %edx +Loop2: + leal 4(%edi),%edi + movl (%esi),%eax + adcl %ebx,%eax + movl 4(%ebp),%ebx + movl %eax,-4(%edi) + leal 4(%esi),%esi + leal 4(%ebp),%ebp + decl %edx + jnz Loop2 +Lend2: + movl (%esi),%eax + adcl %ebx,%eax + movl %eax,(%edi) + + sbbl %eax,%eax + negl %eax + + popl %ebp + popl %ebx + popl %esi + popl %edi + ret diff --git a/contrib/libgmp/mpn/x86/pentium/addmul_1.S b/contrib/libgmp/mpn/x86/pentium/addmul_1.S new file mode 100644 index 0000000..7cfa5db --- /dev/null +++ b/contrib/libgmp/mpn/x86/pentium/addmul_1.S @@ -0,0 +1,83 @@ +/* Pentium __mpn_addmul_1 -- Multiply a limb vector with a limb and add + the result to a second limb vector. + +Copyright (C) 1992, 1994, 1996 Free Software Foundation, Inc. + +This file is part of the GNU MP Library. + +The GNU MP Library is free software; you can redistribute it and/or modify +it under the terms of the GNU Library General Public License as published by +the Free Software Foundation; either version 2 of the License, or (at your +option) any later version. + +The GNU MP Library is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public +License for more details. + +You should have received a copy of the GNU Library General Public License +along with the GNU MP Library; see the file COPYING.LIB. If not, write to +the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, +MA 02111-1307, USA. */ + +/* + INPUT PARAMETERS + res_ptr (sp + 4) + s1_ptr (sp + 8) + size (sp + 12) + s2_limb (sp + 16) +*/ + +#include "sysdep.h" +#include "asm-syntax.h" + +#define res_ptr edi +#define s1_ptr esi +#define size ecx +#define s2_limb ebp + + TEXT + ALIGN (3) + GLOBL C_SYMBOL_NAME(__mpn_addmul_1) +C_SYMBOL_NAME(__mpn_addmul_1:) + + INSN1(push,l ,R(edi)) + INSN1(push,l ,R(esi)) + INSN1(push,l ,R(ebx)) + INSN1(push,l ,R(ebp)) + + INSN2(mov,l ,R(res_ptr),MEM_DISP(esp,20)) + INSN2(mov,l ,R(s1_ptr),MEM_DISP(esp,24)) + INSN2(mov,l ,R(size),MEM_DISP(esp,28)) + INSN2(mov,l ,R(s2_limb),MEM_DISP(esp,32)) + + INSN2(lea,l ,R(res_ptr),MEM_INDEX(res_ptr,size,4)) + INSN2(lea,l ,R(s1_ptr),MEM_INDEX(s1_ptr,size,4)) + INSN1(neg,l ,R(size)) + INSN2(xor,l ,R(ebx),R(ebx)) + ALIGN (3) + +Loop: INSN2(adc,l ,R(ebx),$0) + INSN2(mov,l ,R(eax),MEM_INDEX(s1_ptr,size,4)) + + INSN1(mul,l ,R(s2_limb)) + + INSN2(add,l ,R(eax),R(ebx)) + INSN2(mov,l ,R(ebx),MEM_INDEX(res_ptr,size,4)) + + INSN2(adc,l ,R(edx),$0) + INSN2(add,l ,R(ebx),R(eax)) + + INSN2(mov,l ,MEM_INDEX(res_ptr,size,4),R(ebx)) + INSN1(inc,l ,R(size)) + + INSN2(mov,l ,R(ebx),R(edx)) + INSN1(jnz, ,Loop) + + INSN2(adc,l ,R(ebx),$0) + INSN2(mov,l ,R(eax),R(ebx)) + INSN1(pop,l ,R(ebp)) + INSN1(pop,l ,R(ebx)) + INSN1(pop,l ,R(esi)) + INSN1(pop,l ,R(edi)) + ret diff --git a/contrib/libgmp/mpn/x86/pentium/lshift.S b/contrib/libgmp/mpn/x86/pentium/lshift.S new file mode 100644 index 0000000..b298983 --- /dev/null +++ b/contrib/libgmp/mpn/x86/pentium/lshift.S @@ -0,0 +1,217 @@ +/* Pentium optimized __mpn_lshift -- + +Copyright (C) 1992, 1994, 1995 Free Software Foundation, Inc. + +This file is part of the GNU MP Library. + +The GNU MP Library is free software; you can redistribute it and/or modify +it under the terms of the GNU Library General Public License as published by +the Free Software Foundation; either version 2 of the License, or (at your +option) any later version. + +The GNU MP Library is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public +License for more details. + +You should have received a copy of the GNU Library General Public License +along with the GNU MP Library; see the file COPYING.LIB. If not, write to +the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, +MA 02111-1307, USA. */ + +/* + INPUT PARAMETERS + res_ptr (sp + 4) + s_ptr (sp + 8) + size (sp + 12) + cnt (sp + 16) +*/ + +#include "sysdep.h" +#include "asm-syntax.h" + +.text + ALIGN (3) + .globl C_SYMBOL_NAME(__mpn_lshift) +C_SYMBOL_NAME(__mpn_lshift:) + pushl %edi + pushl %esi + pushl %ebx + pushl %ebp + + movl 20(%esp),%edi /* res_ptr */ + movl 24(%esp),%esi /* s_ptr */ + movl 28(%esp),%ebp /* size */ + movl 32(%esp),%ecx /* cnt */ + +/* We can use faster code for shift-by-1 under certain conditions. */ + cmp $1,%ecx + jne Lnormal + leal 4(%esi),%eax + cmpl %edi,%eax + jnc Lspecial /* jump if s_ptr + 1 >= res_ptr */ + leal (%esi,%ebp,4),%eax + cmpl %eax,%edi + jnc Lspecial /* jump if res_ptr >= s_ptr + size */ + +Lnormal: + leal -4(%edi,%ebp,4),%edi + leal -4(%esi,%ebp,4),%esi + + movl (%esi),%edx + subl $4,%esi + xorl %eax,%eax + shldl %cl,%edx,%eax /* compute carry limb */ + pushl %eax /* push carry limb onto stack */ + + decl %ebp + pushl %ebp + shrl $3,%ebp + jz Lend + + movl (%edi),%eax /* fetch destination cache line */ + + ALIGN (2) +Loop: movl -28(%edi),%eax /* fetch destination cache line */ + movl %edx,%ebx + + movl (%esi),%eax + movl -4(%esi),%edx + shldl %cl,%eax,%ebx + shldl %cl,%edx,%eax + movl %ebx,(%edi) + movl %eax,-4(%edi) + + movl -8(%esi),%ebx + movl -12(%esi),%eax + shldl %cl,%ebx,%edx + shldl %cl,%eax,%ebx + movl %edx,-8(%edi) + movl %ebx,-12(%edi) + + movl -16(%esi),%edx + movl -20(%esi),%ebx + shldl %cl,%edx,%eax + shldl %cl,%ebx,%edx + movl %eax,-16(%edi) + movl %edx,-20(%edi) + + movl -24(%esi),%eax + movl -28(%esi),%edx + shldl %cl,%eax,%ebx + shldl %cl,%edx,%eax + movl %ebx,-24(%edi) + movl %eax,-28(%edi) + + subl $32,%esi + subl $32,%edi + decl %ebp + jnz Loop + +Lend: popl %ebp + andl $7,%ebp + jz Lend2 +Loop2: movl (%esi),%eax + shldl %cl,%eax,%edx + movl %edx,(%edi) + movl %eax,%edx + subl $4,%esi + subl $4,%edi + decl %ebp + jnz Loop2 + +Lend2: shll %cl,%edx /* compute least significant limb */ + movl %edx,(%edi) /* store it */ + + popl %eax /* pop carry limb */ + + popl %ebp + popl %ebx + popl %esi + popl %edi + ret + +/* We loop from least significant end of the arrays, which is only + permissable if the source and destination don't overlap, since the + function is documented to work for overlapping source and destination. +*/ + +Lspecial: + movl (%esi),%edx + addl $4,%esi + + decl %ebp + pushl %ebp + shrl $3,%ebp + + addl %edx,%edx + incl %ebp + decl %ebp + jz LLend + + movl (%edi),%eax /* fetch destination cache line */ + + ALIGN (2) +LLoop: movl 28(%edi),%eax /* fetch destination cache line */ + movl %edx,%ebx + + movl (%esi),%eax + movl 4(%esi),%edx + adcl %eax,%eax + movl %ebx,(%edi) + adcl %edx,%edx + movl %eax,4(%edi) + + movl 8(%esi),%ebx + movl 12(%esi),%eax + adcl %ebx,%ebx + movl %edx,8(%edi) + adcl %eax,%eax + movl %ebx,12(%edi) + + movl 16(%esi),%edx + movl 20(%esi),%ebx + adcl %edx,%edx + movl %eax,16(%edi) + adcl %ebx,%ebx + movl %edx,20(%edi) + + movl 24(%esi),%eax + movl 28(%esi),%edx + adcl %eax,%eax + movl %ebx,24(%edi) + adcl %edx,%edx + movl %eax,28(%edi) + + leal 32(%esi),%esi /* use leal not to clobber carry */ + leal 32(%edi),%edi + decl %ebp + jnz LLoop + +LLend: popl %ebp + sbbl %eax,%eax /* save carry in %eax */ + andl $7,%ebp + jz LLend2 + addl %eax,%eax /* restore carry from eax */ +LLoop2: movl %edx,%ebx + movl (%esi),%edx + adcl %edx,%edx + movl %ebx,(%edi) + + leal 4(%esi),%esi /* use leal not to clobber carry */ + leal 4(%edi),%edi + decl %ebp + jnz LLoop2 + + jmp LL1 +LLend2: addl %eax,%eax /* restore carry from eax */ +LL1: movl %edx,(%edi) /* store last limb */ + + sbbl %eax,%eax + negl %eax + + popl %ebp + popl %ebx + popl %esi + popl %edi + ret diff --git a/contrib/libgmp/mpn/x86/pentium/mul_1.S b/contrib/libgmp/mpn/x86/pentium/mul_1.S new file mode 100644 index 0000000..4ac3050 --- /dev/null +++ b/contrib/libgmp/mpn/x86/pentium/mul_1.S @@ -0,0 +1,79 @@ +/* Pentium __mpn_mul_1 -- Multiply a limb vector with a limb and store + the result in a second limb vector. + +Copyright (C) 1992, 1994, 1996 Free Software Foundation, Inc. + +This file is part of the GNU MP Library. + +The GNU MP Library is free software; you can redistribute it and/or modify +it under the terms of the GNU Library General Public License as published by +the Free Software Foundation; either version 2 of the License, or (at your +option) any later version. + +The GNU MP Library is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public +License for more details. + +You should have received a copy of the GNU Library General Public License +along with the GNU MP Library; see the file COPYING.LIB. If not, write to +the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, +MA 02111-1307, USA. */ + +/* + INPUT PARAMETERS + res_ptr (sp + 4) + s1_ptr (sp + 8) + size (sp + 12) + s2_limb (sp + 16) +*/ + +#include "sysdep.h" +#include "asm-syntax.h" + +#define res_ptr edi +#define s1_ptr esi +#define size ecx +#define s2_limb ebp + + TEXT + ALIGN (3) + GLOBL C_SYMBOL_NAME(__mpn_mul_1) +C_SYMBOL_NAME(__mpn_mul_1:) + + INSN1(push,l ,R(edi)) + INSN1(push,l ,R(esi)) + INSN1(push,l ,R(ebx)) + INSN1(push,l ,R(ebp)) + + INSN2(mov,l ,R(res_ptr),MEM_DISP(esp,20)) + INSN2(mov,l ,R(s1_ptr),MEM_DISP(esp,24)) + INSN2(mov,l ,R(size),MEM_DISP(esp,28)) + INSN2(mov,l ,R(s2_limb),MEM_DISP(esp,32)) + + INSN2(lea,l ,R(res_ptr),MEM_INDEX(res_ptr,size,4)) + INSN2(lea,l ,R(s1_ptr),MEM_INDEX(s1_ptr,size,4)) + INSN1(neg,l ,R(size)) + INSN2(xor,l ,R(ebx),R(ebx)) + ALIGN (3) + +Loop: INSN2(adc,l ,R(ebx),$0) + INSN2(mov,l ,R(eax),MEM_INDEX(s1_ptr,size,4)) + + INSN1(mul,l ,R(s2_limb)) + + INSN2(add,l ,R(ebx),R(eax)) + + INSN2(mov,l ,MEM_INDEX(res_ptr,size,4),R(ebx)) + INSN1(inc,l ,R(size)) + + INSN2(mov,l ,R(ebx),R(edx)) + INSN1(jnz, ,Loop) + + INSN2(adc,l ,R(ebx),$0) + INSN2(mov,l ,R(eax),R(ebx)) + INSN1(pop,l ,R(ebp)) + INSN1(pop,l ,R(ebx)) + INSN1(pop,l ,R(esi)) + INSN1(pop,l ,R(edi)) + ret diff --git a/contrib/libgmp/mpn/x86/pentium/rshift.S b/contrib/libgmp/mpn/x86/pentium/rshift.S new file mode 100644 index 0000000..38398ed --- /dev/null +++ b/contrib/libgmp/mpn/x86/pentium/rshift.S @@ -0,0 +1,217 @@ +/* Pentium optimized __mpn_rshift -- + +Copyright (C) 1992, 1994, 1995 Free Software Foundation, Inc. + +This file is part of the GNU MP Library. + +The GNU MP Library is free software; you can redistribute it and/or modify +it under the terms of the GNU Library General Public License as published by +the Free Software Foundation; either version 2 of the License, or (at your +option) any later version. + +The GNU MP Library is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public +License for more details. + +You should have received a copy of the GNU Library General Public License +along with the GNU MP Library; see the file COPYING.LIB. If not, write to +the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, +MA 02111-1307, USA. */ + +/* + INPUT PARAMETERS + res_ptr (sp + 4) + s_ptr (sp + 8) + size (sp + 12) + cnt (sp + 16) +*/ + +#include "sysdep.h" +#include "asm-syntax.h" + +.text + ALIGN (3) + .globl C_SYMBOL_NAME(__mpn_rshift) +C_SYMBOL_NAME(__mpn_rshift:) + pushl %edi + pushl %esi + pushl %ebx + pushl %ebp + + movl 20(%esp),%edi /* res_ptr */ + movl 24(%esp),%esi /* s_ptr */ + movl 28(%esp),%ebp /* size */ + movl 32(%esp),%ecx /* cnt */ + +/* We can use faster code for shift-by-1 under certain conditions. */ + cmp $1,%ecx + jne Lnormal + leal 4(%edi),%eax + cmpl %esi,%eax + jnc Lspecial /* jump if res_ptr + 1 >= s_ptr */ + leal (%edi,%ebp,4),%eax + cmpl %eax,%esi + jnc Lspecial /* jump if s_ptr >= res_ptr + size */ + +Lnormal: + movl (%esi),%edx + addl $4,%esi + xorl %eax,%eax + shrdl %cl,%edx,%eax /* compute carry limb */ + pushl %eax /* push carry limb onto stack */ + + decl %ebp + pushl %ebp + shrl $3,%ebp + jz Lend + + movl (%edi),%eax /* fetch destination cache line */ + + ALIGN (2) +Loop: movl 28(%edi),%eax /* fetch destination cache line */ + movl %edx,%ebx + + movl (%esi),%eax + movl 4(%esi),%edx + shrdl %cl,%eax,%ebx + shrdl %cl,%edx,%eax + movl %ebx,(%edi) + movl %eax,4(%edi) + + movl 8(%esi),%ebx + movl 12(%esi),%eax + shrdl %cl,%ebx,%edx + shrdl %cl,%eax,%ebx + movl %edx,8(%edi) + movl %ebx,12(%edi) + + movl 16(%esi),%edx + movl 20(%esi),%ebx + shrdl %cl,%edx,%eax + shrdl %cl,%ebx,%edx + movl %eax,16(%edi) + movl %edx,20(%edi) + + movl 24(%esi),%eax + movl 28(%esi),%edx + shrdl %cl,%eax,%ebx + shrdl %cl,%edx,%eax + movl %ebx,24(%edi) + movl %eax,28(%edi) + + addl $32,%esi + addl $32,%edi + decl %ebp + jnz Loop + +Lend: popl %ebp + andl $7,%ebp + jz Lend2 +Loop2: movl (%esi),%eax + shrdl %cl,%eax,%edx /* compute result limb */ + movl %edx,(%edi) + movl %eax,%edx + addl $4,%esi + addl $4,%edi + decl %ebp + jnz Loop2 + +Lend2: shrl %cl,%edx /* compute most significant limb */ + movl %edx,(%edi) /* store it */ + + popl %eax /* pop carry limb */ + + popl %ebp + popl %ebx + popl %esi + popl %edi + ret + +/* We loop from least significant end of the arrays, which is only + permissable if the source and destination don't overlap, since the + function is documented to work for overlapping source and destination. +*/ + +Lspecial: + leal -4(%edi,%ebp,4),%edi + leal -4(%esi,%ebp,4),%esi + + movl (%esi),%edx + subl $4,%esi + + decl %ebp + pushl %ebp + shrl $3,%ebp + + shrl $1,%edx + incl %ebp + decl %ebp + jz LLend + + movl (%edi),%eax /* fetch destination cache line */ + + ALIGN (2) +LLoop: movl -28(%edi),%eax /* fetch destination cache line */ + movl %edx,%ebx + + movl (%esi),%eax + movl -4(%esi),%edx + rcrl $1,%eax + movl %ebx,(%edi) + rcrl $1,%edx + movl %eax,-4(%edi) + + movl -8(%esi),%ebx + movl -12(%esi),%eax + rcrl $1,%ebx + movl %edx,-8(%edi) + rcrl $1,%eax + movl %ebx,-12(%edi) + + movl -16(%esi),%edx + movl -20(%esi),%ebx + rcrl $1,%edx + movl %eax,-16(%edi) + rcrl $1,%ebx + movl %edx,-20(%edi) + + movl -24(%esi),%eax + movl -28(%esi),%edx + rcrl $1,%eax + movl %ebx,-24(%edi) + rcrl $1,%edx + movl %eax,-28(%edi) + + leal -32(%esi),%esi /* use leal not to clobber carry */ + leal -32(%edi),%edi + decl %ebp + jnz LLoop + +LLend: popl %ebp + sbbl %eax,%eax /* save carry in %eax */ + andl $7,%ebp + jz LLend2 + addl %eax,%eax /* restore carry from eax */ +LLoop2: movl %edx,%ebx + movl (%esi),%edx + rcrl $1,%edx + movl %ebx,(%edi) + + leal -4(%esi),%esi /* use leal not to clobber carry */ + leal -4(%edi),%edi + decl %ebp + jnz LLoop2 + + jmp LL1 +LLend2: addl %eax,%eax /* restore carry from eax */ +LL1: movl %edx,(%edi) /* store last limb */ + + movl $0,%eax + rcrl $1,%eax + + popl %ebp + popl %ebx + popl %esi + popl %edi + ret diff --git a/contrib/libgmp/mpn/x86/pentium/sub_n.S b/contrib/libgmp/mpn/x86/pentium/sub_n.S new file mode 100644 index 0000000..d1a2bc0 --- /dev/null +++ b/contrib/libgmp/mpn/x86/pentium/sub_n.S @@ -0,0 +1,130 @@ +/* Pentium __mpn_sub_n -- Subtract two limb vectors of the same length > 0 + and store difference in a third limb vector. + +Copyright (C) 1992, 1994, 1995, 1996 Free Software Foundation, Inc. + +This file is part of the GNU MP Library. + +The GNU MP Library is free software; you can redistribute it and/or modify +it under the terms of the GNU Library General Public License as published by +the Free Software Foundation; either version 2 of the License, or (at your +option) any later version. + +The GNU MP Library is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public +License for more details. + +You should have received a copy of the GNU Library General Public License +along with the GNU MP Library; see the file COPYING.LIB. If not, write to +the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, +MA 02111-1307, USA. */ + +/* + INPUT PARAMETERS + res_ptr (sp + 4) + s1_ptr (sp + 8) + s2_ptr (sp + 12) + size (sp + 16) +*/ + +#include "sysdep.h" +#include "asm-syntax.h" + +.text + ALIGN (3) + .globl C_SYMBOL_NAME(__mpn_sub_n) +C_SYMBOL_NAME(__mpn_sub_n:) + pushl %edi + pushl %esi + pushl %ebx + pushl %ebp + + movl 20(%esp),%edi /* res_ptr */ + movl 24(%esp),%esi /* s1_ptr */ + movl 28(%esp),%ebp /* s2_ptr */ + movl 32(%esp),%ecx /* size */ + + movl (%ebp),%ebx + + decl %ecx + movl %ecx,%edx + shrl $3,%ecx + andl $7,%edx + testl %ecx,%ecx /* zero carry flag */ + jz Lend + pushl %edx + + ALIGN (3) +Loop: movl 28(%edi),%eax /* fetch destination cache line */ + leal 32(%edi),%edi + +L1: movl (%esi),%eax + movl 4(%esi),%edx + sbbl %ebx,%eax + movl 4(%ebp),%ebx + sbbl %ebx,%edx + movl 8(%ebp),%ebx + movl %eax,-32(%edi) + movl %edx,-28(%edi) + +L2: movl 8(%esi),%eax + movl 12(%esi),%edx + sbbl %ebx,%eax + movl 12(%ebp),%ebx + sbbl %ebx,%edx + movl 16(%ebp),%ebx + movl %eax,-24(%edi) + movl %edx,-20(%edi) + +L3: movl 16(%esi),%eax + movl 20(%esi),%edx + sbbl %ebx,%eax + movl 20(%ebp),%ebx + sbbl %ebx,%edx + movl 24(%ebp),%ebx + movl %eax,-16(%edi) + movl %edx,-12(%edi) + +L4: movl 24(%esi),%eax + movl 28(%esi),%edx + sbbl %ebx,%eax + movl 28(%ebp),%ebx + sbbl %ebx,%edx + movl 32(%ebp),%ebx + movl %eax,-8(%edi) + movl %edx,-4(%edi) + + leal 32(%esi),%esi + leal 32(%ebp),%ebp + decl %ecx + jnz Loop + + popl %edx +Lend: + decl %edx /* test %edx w/o clobbering carry */ + js Lend2 + incl %edx +Loop2: + leal 4(%edi),%edi + movl (%esi),%eax + sbbl %ebx,%eax + movl 4(%ebp),%ebx + movl %eax,-4(%edi) + leal 4(%esi),%esi + leal 4(%ebp),%ebp + decl %edx + jnz Loop2 +Lend2: + movl (%esi),%eax + sbbl %ebx,%eax + movl %eax,(%edi) + + sbbl %eax,%eax + negl %eax + + popl %ebp + popl %ebx + popl %esi + popl %edi + ret diff --git a/contrib/libgmp/mpn/x86/pentium/submul_1.S b/contrib/libgmp/mpn/x86/pentium/submul_1.S new file mode 100644 index 0000000..adf2d63 --- /dev/null +++ b/contrib/libgmp/mpn/x86/pentium/submul_1.S @@ -0,0 +1,83 @@ +/* Pentium __mpn_submul_1 -- Multiply a limb vector with a limb and subtract + the result from a second limb vector. + +Copyright (C) 1992, 1994, 1996 Free Software Foundation, Inc. + +This file is part of the GNU MP Library. + +The GNU MP Library is free software; you can redistribute it and/or modify +it under the terms of the GNU Library General Public License as published by +the Free Software Foundation; either version 2 of the License, or (at your +option) any later version. + +The GNU MP Library is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public +License for more details. + +You should have received a copy of the GNU Library General Public License +along with the GNU MP Library; see the file COPYING.LIB. If not, write to +the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, +MA 02111-1307, USA. */ + +/* + INPUT PARAMETERS + res_ptr (sp + 4) + s1_ptr (sp + 8) + size (sp + 12) + s2_limb (sp + 16) +*/ + +#include "sysdep.h" +#include "asm-syntax.h" + +#define res_ptr edi +#define s1_ptr esi +#define size ecx +#define s2_limb ebp + + TEXT + ALIGN (3) + GLOBL C_SYMBOL_NAME(__mpn_submul_1) +C_SYMBOL_NAME(__mpn_submul_1:) + + INSN1(push,l ,R(edi)) + INSN1(push,l ,R(esi)) + INSN1(push,l ,R(ebx)) + INSN1(push,l ,R(ebp)) + + INSN2(mov,l ,R(res_ptr),MEM_DISP(esp,20)) + INSN2(mov,l ,R(s1_ptr),MEM_DISP(esp,24)) + INSN2(mov,l ,R(size),MEM_DISP(esp,28)) + INSN2(mov,l ,R(s2_limb),MEM_DISP(esp,32)) + + INSN2(lea,l ,R(res_ptr),MEM_INDEX(res_ptr,size,4)) + INSN2(lea,l ,R(s1_ptr),MEM_INDEX(s1_ptr,size,4)) + INSN1(neg,l ,R(size)) + INSN2(xor,l ,R(ebx),R(ebx)) + ALIGN (3) + +Loop: INSN2(adc,l ,R(ebx),$0) + INSN2(mov,l ,R(eax),MEM_INDEX(s1_ptr,size,4)) + + INSN1(mul,l ,R(s2_limb)) + + INSN2(add,l ,R(eax),R(ebx)) + INSN2(mov,l ,R(ebx),MEM_INDEX(res_ptr,size,4)) + + INSN2(adc,l ,R(edx),$0) + INSN2(sub,l ,R(ebx),R(eax)) + + INSN2(mov,l ,MEM_INDEX(res_ptr,size,4),R(ebx)) + INSN1(inc,l ,R(size)) + + INSN2(mov,l ,R(ebx),R(edx)) + INSN1(jnz, ,Loop) + + INSN2(adc,l ,R(ebx),$0) + INSN2(mov,l ,R(eax),R(ebx)) + INSN1(pop,l ,R(ebp)) + INSN1(pop,l ,R(ebx)) + INSN1(pop,l ,R(esi)) + INSN1(pop,l ,R(edi)) + ret diff --git a/contrib/libgmp/mpn/x86/rshift.S b/contrib/libgmp/mpn/x86/rshift.S new file mode 100644 index 0000000..9abbf9a --- /dev/null +++ b/contrib/libgmp/mpn/x86/rshift.S @@ -0,0 +1,87 @@ +/* i80386 __mpn_rshift -- + +Copyright (C) 1992, 1994 Free Software Foundation, Inc. + +This file is part of the GNU MP Library. + +The GNU MP Library is free software; you can redistribute it and/or modify +it under the terms of the GNU Library General Public License as published by +the Free Software Foundation; either version 2 of the License, or (at your +option) any later version. + +The GNU MP Library is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public +License for more details. + +You should have received a copy of the GNU Library General Public License +along with the GNU MP Library; see the file COPYING.LIB. If not, write to +the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, +MA 02111-1307, USA. */ + +/* + INPUT PARAMETERS + res_ptr (sp + 4) + s_ptr (sp + 8) + size (sp + 12) + cnt (sp + 16) +*/ + +#include "sysdep.h" +#include "asm-syntax.h" + +.text + ALIGN (3) + .globl C_SYMBOL_NAME(__mpn_rshift) +C_SYMBOL_NAME(__mpn_rshift:) + pushl %edi + pushl %esi + pushl %ebx + + movl 16(%esp),%edi /* res_ptr */ + movl 20(%esp),%esi /* s_ptr */ + movl 24(%esp),%edx /* size */ + movl 28(%esp),%ecx /* cnt */ + + leal -4(%edi,%edx,4),%edi + leal (%esi,%edx,4),%esi + negl %edx + + movl (%esi,%edx,4),%ebx /* read least significant limb */ + xorl %eax,%eax + shrdl %cl,%ebx,%eax /* compute carry limb */ + incl %edx + jz Lend + pushl %eax /* push carry limb onto stack */ + testb $1,%edx + jnz L1 /* enter loop in the middle */ + movl %ebx,%eax + + ALIGN (3) +Loop: movl (%esi,%edx,4),%ebx /* load next higher limb */ + shrdl %cl,%ebx,%eax /* compute result limb */ + movl %eax,(%edi,%edx,4) /* store it */ + incl %edx +L1: movl (%esi,%edx,4),%eax + shrdl %cl,%eax,%ebx + movl %ebx,(%edi,%edx,4) + incl %edx + jnz Loop + + shrl %cl,%eax /* compute most significant limb */ + movl %eax,(%edi) /* store it */ + + popl %eax /* pop carry limb */ + + popl %ebx + popl %esi + popl %edi + ret + +Lend: shrl %cl,%ebx /* compute most significant limb */ + movl %ebx,(%edi) /* store it */ + + popl %ebx + popl %esi + popl %edi + ret diff --git a/contrib/libgmp/mpn/x86/sub_n.S b/contrib/libgmp/mpn/x86/sub_n.S new file mode 100644 index 0000000..1774f3a --- /dev/null +++ b/contrib/libgmp/mpn/x86/sub_n.S @@ -0,0 +1,106 @@ +/* i80386 __mpn_sub_n -- Add two limb vectors of the same length > 0 and store + sum in a third limb vector. + +Copyright (C) 1992, 1994, 1995 Free Software Foundation, Inc. + +This file is part of the GNU MP Library. + +The GNU MP Library is free software; you can redistribute it and/or modify +it under the terms of the GNU Library General Public License as published by +the Free Software Foundation; either version 2 of the License, or (at your +option) any later version. + +The GNU MP Library is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public +License for more details. + +You should have received a copy of the GNU Library General Public License +along with the GNU MP Library; see the file COPYING.LIB. If not, write to +the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, +MA 02111-1307, USA. */ + +/* + INPUT PARAMETERS + res_ptr (sp + 4) + s1_ptr (sp + 8) + s2_ptr (sp + 12) + size (sp + 16) +*/ + +#include "sysdep.h" +#include "asm-syntax.h" + +.text + ALIGN (3) + .globl C_SYMBOL_NAME(__mpn_sub_n) +C_SYMBOL_NAME(__mpn_sub_n:) + pushl %edi + pushl %esi + + movl 12(%esp),%edi /* res_ptr */ + movl 16(%esp),%esi /* s1_ptr */ + movl 20(%esp),%edx /* s2_ptr */ + movl 24(%esp),%ecx /* size */ + + movl %ecx,%eax + shrl $3,%ecx /* compute count for unrolled loop */ + negl %eax + andl $7,%eax /* get index where to start loop */ + jz Loop /* necessary special case for 0 */ + incl %ecx /* adjust loop count */ + shll $2,%eax /* adjustment for pointers... */ + subl %eax,%edi /* ... since they are offset ... */ + subl %eax,%esi /* ... by a constant when we ... */ + subl %eax,%edx /* ... enter the loop */ + shrl $2,%eax /* restore previous value */ +#ifdef PIC +/* Calculate start address in loop for PIC. Due to limitations in some + assemblers, Loop-L0-3 cannot be put into the leal */ + call L0 +L0: leal (%eax,%eax,8),%eax + addl (%esp),%eax + addl $(Loop-L0-3),%eax + addl $4,%esp +#else +/* Calculate start address in loop for non-PIC. */ + leal (Loop - 3)(%eax,%eax,8),%eax +#endif + jmp *%eax /* jump into loop */ + ALIGN (3) +Loop: movl (%esi),%eax + sbbl (%edx),%eax + movl %eax,(%edi) + movl 4(%esi),%eax + sbbl 4(%edx),%eax + movl %eax,4(%edi) + movl 8(%esi),%eax + sbbl 8(%edx),%eax + movl %eax,8(%edi) + movl 12(%esi),%eax + sbbl 12(%edx),%eax + movl %eax,12(%edi) + movl 16(%esi),%eax + sbbl 16(%edx),%eax + movl %eax,16(%edi) + movl 20(%esi),%eax + sbbl 20(%edx),%eax + movl %eax,20(%edi) + movl 24(%esi),%eax + sbbl 24(%edx),%eax + movl %eax,24(%edi) + movl 28(%esi),%eax + sbbl 28(%edx),%eax + movl %eax,28(%edi) + leal 32(%edi),%edi + leal 32(%esi),%esi + leal 32(%edx),%edx + decl %ecx + jnz Loop + + sbbl %eax,%eax + negl %eax + + popl %esi + popl %edi + ret diff --git a/contrib/libgmp/mpn/x86/submul_1.S b/contrib/libgmp/mpn/x86/submul_1.S new file mode 100644 index 0000000..730e732 --- /dev/null +++ b/contrib/libgmp/mpn/x86/submul_1.S @@ -0,0 +1,76 @@ +/* i80386 __mpn_submul_1 -- Multiply a limb vector with a limb and subtract + the result from a second limb vector. + +Copyright (C) 1992, 1994 Free Software Foundation, Inc. + +This file is part of the GNU MP Library. + +The GNU MP Library is free software; you can redistribute it and/or modify +it under the terms of the GNU Library General Public License as published by +the Free Software Foundation; either version 2 of the License, or (at your +option) any later version. + +The GNU MP Library is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public +License for more details. + +You should have received a copy of the GNU Library General Public License +along with the GNU MP Library; see the file COPYING.LIB. If not, write to +the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, +MA 02111-1307, USA. */ + +/* + INPUT PARAMETERS + res_ptr (sp + 4) + s1_ptr (sp + 8) + size (sp + 12) + s2_limb (sp + 16) +*/ + +#include "sysdep.h" +#include "asm-syntax.h" + +#define res_ptr edi +#define s1_ptr esi +#define size ecx +#define s2_limb ebp + + TEXT + ALIGN (3) + GLOBL C_SYMBOL_NAME(__mpn_submul_1) +C_SYMBOL_NAME(__mpn_submul_1:) + + INSN1(push,l ,R(edi)) + INSN1(push,l ,R(esi)) + INSN1(push,l ,R(ebx)) + INSN1(push,l ,R(ebp)) + + INSN2(mov,l ,R(res_ptr),MEM_DISP(esp,20)) + INSN2(mov,l ,R(s1_ptr),MEM_DISP(esp,24)) + INSN2(mov,l ,R(size),MEM_DISP(esp,28)) + INSN2(mov,l ,R(s2_limb),MEM_DISP(esp,32)) + + INSN2(lea,l ,R(res_ptr),MEM_INDEX(res_ptr,size,4)) + INSN2(lea,l ,R(s1_ptr),MEM_INDEX(s1_ptr,size,4)) + INSN1(neg,l ,R(size)) + INSN2(xor,l ,R(ebx),R(ebx)) + ALIGN (3) +Loop: + INSN2(mov,l ,R(eax),MEM_INDEX(s1_ptr,size,4)) + INSN1(mul,l ,R(s2_limb)) + INSN2(add,l ,R(eax),R(ebx)) + INSN2(adc,l ,R(edx),$0) + INSN2(sub,l ,MEM_INDEX(res_ptr,size,4),R(eax)) + INSN2(adc,l ,R(edx),$0) + INSN2(mov,l ,R(ebx),R(edx)) + + INSN1(inc,l ,R(size)) + INSN1(jnz, ,Loop) + INSN2(mov,l ,R(eax),R(ebx)) + + INSN1(pop,l ,R(ebp)) + INSN1(pop,l ,R(ebx)) + INSN1(pop,l ,R(esi)) + INSN1(pop,l ,R(edi)) + ret diff --git a/contrib/libgmp/mpn/x86/syntax.h b/contrib/libgmp/mpn/x86/syntax.h new file mode 100644 index 0000000..c53c73c --- /dev/null +++ b/contrib/libgmp/mpn/x86/syntax.h @@ -0,0 +1,62 @@ +/* asm.h -- Definitions for x86 syntax variations. + +Copyright (C) 1992, 1994, 1995 Free Software Foundation, Inc. + +This file is part of the GNU MP Library. + +The GNU MP Library is free software; you can redistribute it and/or modify +it under the terms of the GNU Library General Public License as published by +the Free Software Foundation; either version 2 of the License, or (at your +option) any later version. + +The GNU MP Library is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public +License for more details. + +You should have received a copy of the GNU Library General Public License +along with the GNU MP Library; see the file COPYING.LIB. If not, write to +the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, +MA 02111-1307, USA. */ + + +#undef ALIGN + +#if defined (BSD_SYNTAX) || defined (ELF_SYNTAX) +#define R(r) %r +#define MEM(base)(base) +#define MEM_DISP(base,displacement)displacement(R(base)) +#define MEM_INDEX(base,index,size)(R(base),R(index),size) +#ifdef __STDC__ +#define INSN1(mnemonic,size_suffix,dst)mnemonic##size_suffix dst +#define INSN2(mnemonic,size_suffix,dst,src)mnemonic##size_suffix src,dst +#else +#define INSN1(mnemonic,size_suffix,dst)mnemonic/**/size_suffix dst +#define INSN2(mnemonic,size_suffix,dst,src)mnemonic/**/size_suffix src,dst +#endif +#define TEXT .text +#if defined (BSD_SYNTAX) +#define ALIGN(log) .align log +#endif +#if defined (ELF_SYNTAX) +#define ALIGN(log) .align 1<<(log) +#endif +#define GLOBL .globl +#endif + +#ifdef INTEL_SYNTAX +#define R(r) r +#define MEM(base)[base] +#define MEM_DISP(base,displacement)[base+(displacement)] +#define MEM_INDEX(base,index,size)[base+index*size] +#define INSN1(mnemonic,size_suffix,dst)mnemonic dst +#define INSN2(mnemonic,size_suffix,dst,src)mnemonic dst,src +#define TEXT .text +#define ALIGN(log) .align log +#define GLOBL .globl +#endif + +#ifdef BROKEN_ALIGN +#undef ALIGN +#define ALIGN(log) .align log,0x90 +#endif diff --git a/contrib/libgmp/mpq/Makefile.in b/contrib/libgmp/mpq/Makefile.in new file mode 100644 index 0000000..f34ffb9 --- /dev/null +++ b/contrib/libgmp/mpq/Makefile.in @@ -0,0 +1,81 @@ +# Makefile for GNU MP/mpq functions +# Copyright (C) 1991, 1993, 1994, 1996 Free Software Foundation, Inc. + +# This file is part of the GNU MP Library. + +# The GNU MP Library is free software; you can redistribute it and/or modify +# it under the terms of the GNU Library General Public License as published by +# the Free Software Foundation; either version 2 of the License, or (at your +# option) any later version. + +# The GNU MP Library is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +# or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public +# License for more details. + +# You should have received a copy of the GNU Library General Public License +# along with the GNU MP Library; see the file COPYING.LIB. If not, write to +# the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, +# MA 02111-1307, USA. + +srcdir = . + +CC = gcc + +CFLAGS = -g -O +AR = ar +AR_FLAGS = rc +SHELL = /bin/sh + +#### host and target specific makefile fragments come in here. +### + +MPQ_SRCS = add.c canonicalize.c clear.c cmp.c cmp_ui.c div.c get_d.c \ + get_den.c get_num.c init.c inv.c mul.c neg.c set.c set_den.c set_num.c \ + set_si.c set_ui.c sub.c equal.c set_z.c +MPQ_OBJS = add.o canonicalize.o clear.o cmp.o cmp_ui.o div.o get_d.o \ + get_den.o get_num.o init.o inv.o mul.o neg.o set.o set_den.o set_num.o \ + set_si.o set_ui.o sub.o equal.o set_z.o + +INCLUDES = -I. -I.. -I../mpn -I$(srcdir)/.. + +libmpq.a: Makefile $(MPQ_OBJS) + rm -f $@ + $(AR) $(AR_FLAGS) $@ $(MPQ_OBJS) + +.c.o: + $(CC) -c $(INCLUDES) $(CFLAGS) $(XCFLAGS) $< + +clean mostlyclean: + rm -f *.o libmpq.a + -cd tests; $(MAKE) $@ +distclean maintainer-clean: clean + rm -f Makefile config.status + -cd tests; $(MAKE) $@ + +Makefile: $(srcdir)/Makefile.in + $(SHELL) ./config.status + +H = $(srcdir)/../gmp.h $(srcdir)/../gmp-impl.h ../mpn/gmp-mparam.h + +add.o: $(srcdir)/add.c $(H) +canonicalize.o: $(srcdir)/canonicalize.c $(H) +clear.o: $(srcdir)/clear.c $(H) +cmp.o: $(srcdir)/cmp.c $(H) $(srcdir)/../longlong.h +cmp_ui.o: $(srcdir)/cmp_ui.c $(H) +div.o: $(srcdir)/div.c $(H) +equal.o: $(srcdir)/equal.c $(H) +get_d.o: $(srcdir)/get_d.c $(H) $(srcdir)/../longlong.h +get_den.o: $(srcdir)/get_den.c $(H) +get_num.o: $(srcdir)/get_num.c $(H) +init.o: $(srcdir)/init.c $(H) +inv.o: $(srcdir)/inv.c $(H) +mul.o: $(srcdir)/mul.c $(H) +neg.o: $(srcdir)/neg.c $(H) +set.o: $(srcdir)/set.c $(H) +set_den.o: $(srcdir)/set_den.c $(H) +set_num.o: $(srcdir)/set_num.c $(H) +set_si.o: $(srcdir)/set_si.c $(H) +set_ui.o: $(srcdir)/set_ui.c $(H) +set_z.o: $(srcdir)/set_z.c $(H) +sub.o: $(srcdir)/sub.c $(H) diff --git a/contrib/libgmp/mpq/add.c b/contrib/libgmp/mpq/add.c new file mode 100644 index 0000000..6b98b46 --- /dev/null +++ b/contrib/libgmp/mpq/add.c @@ -0,0 +1,85 @@ +/* mpq_add -- add two rational numbers. + +Copyright (C) 1991, 1994, 1995, 1996 Free Software Foundation, Inc. + +This file is part of the GNU MP Library. + +The GNU MP Library is free software; you can redistribute it and/or modify +it under the terms of the GNU Library General Public License as published by +the Free Software Foundation; either version 2 of the License, or (at your +option) any later version. + +The GNU MP Library is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public +License for more details. + +You should have received a copy of the GNU Library General Public License +along with the GNU MP Library; see the file COPYING.LIB. If not, write to +the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, +MA 02111-1307, USA. */ + +#include "gmp.h" +#include "gmp-impl.h" + +void +#if __STDC__ +mpq_add (mpq_ptr rop, mpq_srcptr op1, mpq_srcptr op2) +#else +mpq_add (rop, op1, op2) + mpq_ptr rop; + mpq_srcptr op1; + mpq_srcptr op2; +#endif +{ + mpz_t gcd; + mpz_t tmp1, tmp2; + mp_size_t op1_num_size = ABS (op1->_mp_num._mp_size); + mp_size_t op1_den_size = ABS (op1->_mp_den._mp_size); + mp_size_t op2_num_size = ABS (op2->_mp_num._mp_size); + mp_size_t op2_den_size = ABS (op2->_mp_den._mp_size); + TMP_DECL (marker); + + TMP_MARK (marker); + MPZ_TMP_INIT (gcd, MIN (op1_den_size, op2_den_size)); + MPZ_TMP_INIT (tmp1, op1_num_size + op2_den_size); + MPZ_TMP_INIT (tmp2, op2_num_size + op1_den_size); + + /* ROP might be identical to either operand, so don't store the + result there until we are finished with the input operands. We + dare to overwrite the numerator of ROP when we are finished + with the numerators of OP1 and OP2. */ + + mpz_gcd (gcd, &(op1->_mp_den), &(op2->_mp_den)); + if (gcd->_mp_size > 1 || gcd->_mp_d[0] != 1) + { + mpz_t t; + + mpz_divexact (tmp1, &(op2->_mp_den), gcd); + mpz_mul (tmp1, &(op1->_mp_num), tmp1); + + mpz_divexact (tmp2, &(op1->_mp_den), gcd); + mpz_mul (tmp2, &(op2->_mp_num), tmp2); + + MPZ_TMP_INIT (t, MAX (ABS (tmp1->_mp_size), ABS (tmp2->_mp_size)) + 1); + + mpz_add (t, tmp1, tmp2); + mpz_divexact (tmp1, &(op1->_mp_den), gcd); + mpz_gcd (gcd, t, gcd); + + mpz_divexact (&(rop->_mp_num), t, gcd); + + mpz_divexact (tmp2, &(op2->_mp_den), gcd); + mpz_mul (&(rop->_mp_den), tmp1, tmp2); + } + else + { + /* The common divisor is 1. This is the case (for random input) with + probability 6/(pi**2). */ + mpz_mul (tmp1, &(op1->_mp_num), &(op2->_mp_den)); + mpz_mul (tmp2, &(op2->_mp_num), &(op1->_mp_den)); + mpz_add (&(rop->_mp_num), tmp1, tmp2); + mpz_mul (&(rop->_mp_den), &(op1->_mp_den), &(op2->_mp_den)); + } + TMP_FREE (marker); +} diff --git a/contrib/libgmp/mpq/canonicalize.c b/contrib/libgmp/mpq/canonicalize.c new file mode 100644 index 0000000..901e6eb --- /dev/null +++ b/contrib/libgmp/mpq/canonicalize.c @@ -0,0 +1,53 @@ +/* mpq_canonicalize(op) -- Remove common factors of the denominator and + numerator in OP. + +Copyright (C) 1991, 1994, 1995, 1996 Free Software Foundation, Inc. + +This file is part of the GNU MP Library. + +The GNU MP Library is free software; you can redistribute it and/or modify +it under the terms of the GNU Library General Public License as published by +the Free Software Foundation; either version 2 of the License, or (at your +option) any later version. + +The GNU MP Library is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public +License for more details. + +You should have received a copy of the GNU Library General Public License +along with the GNU MP Library; see the file COPYING.LIB. If not, write to +the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, +MA 02111-1307, USA. */ + +#include "gmp.h" +#include "gmp-impl.h" + +void +#if __STDC__ +mpq_canonicalize (MP_RAT *op) +#else +mpq_canonicalize (op) + MP_RAT *op; +#endif +{ + mpz_t gcd; + TMP_DECL (marker); + + TMP_MARK (marker); + + /* ??? Dunno if the 1+ is needed. */ + MPZ_TMP_INIT (gcd, 1 + MAX (ABS (op->_mp_num._mp_size), + ABS (op->_mp_den._mp_size))); + + mpz_gcd (gcd, &(op->_mp_num), &(op->_mp_den)); + mpz_divexact (&(op->_mp_num), &(op->_mp_num), gcd); + mpz_divexact (&(op->_mp_den), &(op->_mp_den), gcd); + + if (op->_mp_den._mp_size < 0) + { + op->_mp_num._mp_size = -op->_mp_num._mp_size; + op->_mp_den._mp_size = -op->_mp_den._mp_size; + } + TMP_FREE (marker); +} diff --git a/contrib/libgmp/mpq/clear.c b/contrib/libgmp/mpq/clear.c new file mode 100644 index 0000000..2837cf2 --- /dev/null +++ b/contrib/libgmp/mpq/clear.c @@ -0,0 +1,37 @@ +/* mpq_clear -- free the space occupied by a MP_RAT. + +Copyright (C) 1991, 1994, 1995 Free Software Foundation, Inc. + +This file is part of the GNU MP Library. + +The GNU MP Library is free software; you can redistribute it and/or modify +it under the terms of the GNU Library General Public License as published by +the Free Software Foundation; either version 2 of the License, or (at your +option) any later version. + +The GNU MP Library is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public +License for more details. + +You should have received a copy of the GNU Library General Public License +along with the GNU MP Library; see the file COPYING.LIB. If not, write to +the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, +MA 02111-1307, USA. */ + +#include "gmp.h" +#include "gmp-impl.h" + +void +#if __STDC__ +mpq_clear (MP_RAT *m) +#else +mpq_clear (m) + MP_RAT *m; +#endif +{ + (*_mp_free_func) (m->_mp_num._mp_d, + m->_mp_num._mp_alloc * BYTES_PER_MP_LIMB); + (*_mp_free_func) (m->_mp_den._mp_d, + m->_mp_den._mp_alloc * BYTES_PER_MP_LIMB); +} diff --git a/contrib/libgmp/mpq/cmp.c b/contrib/libgmp/mpq/cmp.c new file mode 100644 index 0000000..fc530e3 --- /dev/null +++ b/contrib/libgmp/mpq/cmp.c @@ -0,0 +1,120 @@ +/* mpq_cmp(u,v) -- Compare U, V. Return postive, zero, or negative + based on if U > V, U == V, or U < V. + +Copyright (C) 1991, 1994, 1996 Free Software Foundation, Inc. + +This file is part of the GNU MP Library. + +The GNU MP Library is free software; you can redistribute it and/or modify +it under the terms of the GNU Library General Public License as published by +the Free Software Foundation; either version 2 of the License, or (at your +option) any later version. + +The GNU MP Library is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public +License for more details. + +You should have received a copy of the GNU Library General Public License +along with the GNU MP Library; see the file COPYING.LIB. If not, write to +the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, +MA 02111-1307, USA. */ + +#include "gmp.h" +#include "gmp-impl.h" +#include "longlong.h" + +int +#if __STDC__ +mpq_cmp (const MP_RAT *op1, const MP_RAT *op2) +#else +mpq_cmp (op1, op2) + const MP_RAT *op1; + const MP_RAT *op2; +#endif +{ + mp_size_t num1_size = op1->_mp_num._mp_size; + mp_size_t den1_size = op1->_mp_den._mp_size; + mp_size_t num2_size = op2->_mp_num._mp_size; + mp_size_t den2_size = op2->_mp_den._mp_size; + mp_size_t tmp1_size, tmp2_size; + mp_ptr tmp1_ptr, tmp2_ptr; + mp_size_t num1_sign; + int cc; + TMP_DECL (marker); + + if (num1_size == 0) + return -num2_size; + if (num2_size == 0) + return num1_size; + if ((num1_size ^ num2_size) < 0) /* I.e. are the signs different? */ + return num1_size; + + num1_sign = num1_size; + num1_size = ABS (num1_size); + num2_size = ABS (num2_size); + + tmp1_size = num1_size + den2_size; + tmp2_size = num2_size + den1_size; + + /* 1. Check to see if we can tell which operand is larger by just looking at + the number of limbs. */ + + /* NUM1 x DEN2 is either TMP1_SIZE limbs or TMP1_SIZE-1 limbs. + Same for NUM1 x DEN1 with respect to TMP2_SIZE. */ + if (tmp1_size > tmp2_size + 1) + /* NUM1 x DEN2 is surely larger in magnitude than NUM2 x DEN1. */ + return num1_sign; + if (tmp2_size > tmp1_size + 1) + /* NUM1 x DEN2 is surely smaller in magnitude than NUM2 x DEN1. */ + return -num1_sign; + + /* 2. Same, but compare the number of significant bits. */ + { + int cnt1, cnt2; + unsigned long int bits1, bits2; + + count_leading_zeros (cnt1, op1->_mp_num._mp_d[num1_size - 1]); + count_leading_zeros (cnt2, op2->_mp_den._mp_d[den2_size - 1]); + bits1 = tmp1_size * BITS_PER_MP_LIMB - cnt1 - cnt2; + + count_leading_zeros (cnt1, op2->_mp_num._mp_d[num2_size - 1]); + count_leading_zeros (cnt2, op1->_mp_den._mp_d[den1_size - 1]); + bits2 = tmp2_size * BITS_PER_MP_LIMB - cnt1 - cnt2; + + if (bits1 > bits2 + 1) + return num1_sign; + if (bits2 > bits1 + 1) + return -num1_sign; + } + + /* 3. Finally, cross multiply and compare. */ + + TMP_MARK (marker); + tmp1_ptr = (mp_ptr) TMP_ALLOC (tmp1_size * BYTES_PER_MP_LIMB); + tmp2_ptr = (mp_ptr) TMP_ALLOC (tmp2_size * BYTES_PER_MP_LIMB); + + if (num1_size >= den2_size) + tmp1_size -= 0 == mpn_mul (tmp1_ptr, + op1->_mp_num._mp_d, num1_size, + op2->_mp_den._mp_d, den2_size); + else + tmp1_size -= 0 == mpn_mul (tmp1_ptr, + op2->_mp_den._mp_d, den2_size, + op1->_mp_num._mp_d, num1_size); + + if (num2_size >= den1_size) + tmp2_size -= 0 == mpn_mul (tmp2_ptr, + op2->_mp_num._mp_d, num2_size, + op1->_mp_den._mp_d, den1_size); + else + tmp2_size -= 0 == mpn_mul (tmp2_ptr, + op1->_mp_den._mp_d, den1_size, + op2->_mp_num._mp_d, num2_size); + + + cc = tmp1_size - tmp2_size != 0 + ? tmp1_size - tmp2_size : mpn_cmp (tmp1_ptr, tmp2_ptr, tmp1_size); + TMP_FREE (marker); + return num1_sign < 0 ? -cc : cc; +} diff --git a/contrib/libgmp/mpq/cmp_ui.c b/contrib/libgmp/mpq/cmp_ui.c new file mode 100644 index 0000000..bdecec5 --- /dev/null +++ b/contrib/libgmp/mpq/cmp_ui.c @@ -0,0 +1,84 @@ +/* mpq_cmp_ui(u,vn,vd) -- Compare U with Vn/Vd. Return positive, zero, or + negative based on if U > V, U == V, or U < V. Vn and Vd may have + common factors. + +Copyright (C) 1993, 1994, 1996 Free Software Foundation, Inc. + +This file is part of the GNU MP Library. + +The GNU MP Library is free software; you can redistribute it and/or modify +it under the terms of the GNU Library General Public License as published by +the Free Software Foundation; either version 2 of the License, or (at your +option) any later version. + +The GNU MP Library is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public +License for more details. + +You should have received a copy of the GNU Library General Public License +along with the GNU MP Library; see the file COPYING.LIB. If not, write to +the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, +MA 02111-1307, USA. */ + +#include "gmp.h" +#include "gmp-impl.h" + +/* gmp.h defines a macro for mpq_cmp_ui. */ +#undef mpq_cmp_ui + +int +#if __STDC__ +mpq_cmp_ui (const MP_RAT *op1, unsigned long int num2, unsigned long int den2) +#else +mpq_cmp_ui (op1, num2, den2) + const MP_RAT *op1; + unsigned long int num2; + unsigned long int den2; +#endif +{ + mp_size_t num1_size = op1->_mp_num._mp_size; + mp_size_t den1_size = op1->_mp_den._mp_size; + mp_size_t tmp1_size, tmp2_size; + mp_ptr tmp1_ptr, tmp2_ptr; + mp_size_t num1_sign; + mp_limb_t cy_limb; + int cc; + TMP_DECL (marker); + + if (num1_size == 0) + return -(num2 != 0); + if (num1_size < 0) + return num1_size; + if (num2 == 0) + return num1_size; + + num1_sign = num1_size; + num1_size = ABS (num1_size); + + /* NUM1 x DEN2 is either TMP1_SIZE limbs or TMP1_SIZE-1 limbs. + Same for NUM1 x DEN1 with respect to TMP2_SIZE. */ + if (num1_size > den1_size + 1) + /* NUM1 x DEN2 is surely larger in magnitude than NUM2 x DEN1. */ + return num1_sign; + if (den1_size > num1_sign + 1) + /* NUM1 x DEN2 is surely smaller in magnitude than NUM2 x DEN1. */ + return -num1_sign; + + TMP_MARK (marker); + tmp1_ptr = (mp_ptr) TMP_ALLOC ((num1_size + 1) * BYTES_PER_MP_LIMB); + tmp2_ptr = (mp_ptr) TMP_ALLOC ((den1_size + 1) * BYTES_PER_MP_LIMB); + + cy_limb = mpn_mul_1 (tmp1_ptr, op1->_mp_num._mp_d, num1_size, den2); + tmp1_ptr[num1_size] = cy_limb; + tmp1_size = num1_size + (cy_limb != 0); + + cy_limb = mpn_mul_1 (tmp2_ptr, op1->_mp_den._mp_d, den1_size, num2); + tmp2_ptr[den1_size] = cy_limb; + tmp2_size = den1_size + (cy_limb != 0); + + cc = tmp1_size - tmp2_size != 0 + ? tmp1_size - tmp2_size : mpn_cmp (tmp1_ptr, tmp2_ptr, tmp1_size); + TMP_FREE (marker); + return (num1_sign < 0) ? -cc : cc; +} diff --git a/contrib/libgmp/mpq/configure.in b/contrib/libgmp/mpq/configure.in new file mode 100644 index 0000000..b5d501c --- /dev/null +++ b/contrib/libgmp/mpq/configure.in @@ -0,0 +1,12 @@ +# This file is a shell script fragment that supplies the information +# necessary for a configure script to process the program in +# this directory. For more information, look at ../configure. + +configdirs=tests +srctrigger=cmp_ui.c +srcname="GNU Multi-Precision library/mpq" + +# per-host: + +# per-target: + diff --git a/contrib/libgmp/mpq/div.c b/contrib/libgmp/mpq/div.c new file mode 100644 index 0000000..cd1f3881 --- /dev/null +++ b/contrib/libgmp/mpq/div.c @@ -0,0 +1,93 @@ +/* mpq_div -- divide two rational numbers. + +Copyright (C) 1991, 1994, 1995, 1996 Free Software Foundation, Inc. + +This file is part of the GNU MP Library. + +The GNU MP Library is free software; you can redistribute it and/or modify +it under the terms of the GNU Library General Public License as published by +the Free Software Foundation; either version 2 of the License, or (at your +option) any later version. + +The GNU MP Library is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public +License for more details. + +You should have received a copy of the GNU Library General Public License +along with the GNU MP Library; see the file COPYING.LIB. If not, write to +the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, +MA 02111-1307, USA. */ + +#include "gmp.h" +#include "gmp-impl.h" + +void +#if __STDC__ +mpq_div (mpq_ptr quot, mpq_srcptr op1, mpq_srcptr op2) +#else +mpq_div (quot, op1, op2) + mpq_ptr quot; + mpq_srcptr op1; + mpq_srcptr op2; +#endif +{ + mpz_t gcd1, gcd2; + mpz_t tmp1, tmp2; + mpz_t numtmp; + + mpz_init (gcd1); + mpz_init (gcd2); + mpz_init (tmp1); + mpz_init (tmp2); + mpz_init (numtmp); + + /* QUOT might be identical to either operand, so don't store the + result there until we are finished with the input operands. We + dare to overwrite the numerator of QUOT when we are finished + with the numerators of OP1 and OP2. */ + + mpz_gcd (gcd1, &(op1->_mp_num), &(op2->_mp_num)); + mpz_gcd (gcd2, &(op2->_mp_den), &(op1->_mp_den)); + + if (gcd1->_mp_size > 1 || gcd1->_mp_d[0] != 1) + mpz_divexact (tmp1, &(op1->_mp_num), gcd1); + else + mpz_set (tmp1, &(op1->_mp_num)); + + if (gcd2->_mp_size > 1 || gcd2->_mp_d[0] != 1) + mpz_divexact (tmp2, &(op2->_mp_den), gcd2); + else + mpz_set (tmp2, &(op2->_mp_den)); + + mpz_mul (numtmp, tmp1, tmp2); + + if (gcd1->_mp_size > 1 || gcd1->_mp_d[0] != 1) + mpz_divexact (tmp1, &(op2->_mp_num), gcd1); + else + mpz_set (tmp1, &(op2->_mp_num)); + + if (gcd2->_mp_size > 1 || gcd2->_mp_d[0] != 1) + mpz_divexact (tmp2, &(op1->_mp_den), gcd2); + else + mpz_set (tmp2, &(op1->_mp_den)); + + mpz_mul (&(quot->_mp_den), tmp1, tmp2); + + /* We needed to go via NUMTMP to take care of QUOT being the same + as either input operands. Now move NUMTMP to QUOT->_mp_num. */ + mpz_set (&(quot->_mp_num), numtmp); + + /* Keep the denominator positive. */ + if (quot->_mp_den._mp_size < 0) + { + quot->_mp_den._mp_size = -quot->_mp_den._mp_size; + quot->_mp_num._mp_size = -quot->_mp_num._mp_size; + } + + mpz_clear (numtmp); + mpz_clear (tmp2); + mpz_clear (tmp1); + mpz_clear (gcd2); + mpz_clear (gcd1); +} diff --git a/contrib/libgmp/mpq/equal.c b/contrib/libgmp/mpq/equal.c new file mode 100644 index 0000000..2b4bb5b --- /dev/null +++ b/contrib/libgmp/mpq/equal.c @@ -0,0 +1,43 @@ +/* mpq_equal(u,v) -- Compare U, V. Return non-zero if they are equal, zero + if they are non-equal. + +Copyright (C) 1996 Free Software Foundation, Inc. + +This file is part of the GNU MP Library. + +The GNU MP Library is free software; you can redistribute it and/or modify +it under the terms of the GNU Library General Public License as published by +the Free Software Foundation; either version 2 of the License, or (at your +option) any later version. + +The GNU MP Library is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public +License for more details. + +You should have received a copy of the GNU Library General Public License +along with the GNU MP Library; see the file COPYING.LIB. If not, write to +the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, +MA 02111-1307, USA. */ + +#include "gmp.h" +#include "gmp-impl.h" + +int +#if __STDC__ +mpq_equal (mpq_srcptr op1, mpq_srcptr op2) +#else +mpq_equal (op1, op2) + mpq_srcptr op1; + mpq_srcptr op2; +#endif +{ + mp_size_t num1_size = op1->_mp_num._mp_size; + mp_size_t den1_size = op1->_mp_den._mp_size; + mp_size_t num2_size = op2->_mp_num._mp_size; + mp_size_t den2_size = op2->_mp_den._mp_size; + + return (num1_size == num2_size && den1_size == den2_size + && mpn_cmp (op1->_mp_num._mp_d, op2->_mp_num._mp_d, num1_size) == 0 + && mpn_cmp (op1->_mp_den._mp_d, op2->_mp_den._mp_d, den1_size) == 0); +} diff --git a/contrib/libgmp/mpq/get_d.c b/contrib/libgmp/mpq/get_d.c new file mode 100644 index 0000000..cb4e800 --- /dev/null +++ b/contrib/libgmp/mpq/get_d.c @@ -0,0 +1,151 @@ +/* double mpq_get_d (mpq_t src) -- Return the double approximation to SRC. + +Copyright (C) 1995, 1996 Free Software Foundation, Inc. + +This file is part of the GNU MP Library. + +The GNU MP Library is free software; you can redistribute it and/or modify +it under the terms of the GNU Library General Public License as published by +the Free Software Foundation; either version 2 of the License, or (at your +option) any later version. + +The GNU MP Library is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public +License for more details. + +You should have received a copy of the GNU Library General Public License +along with the GNU MP Library; see the file COPYING.LIB. If not, write to +the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, +MA 02111-1307, USA. */ + +#include "gmp.h" +#include "gmp-impl.h" +#include "longlong.h" + +/* Algorithm: + 1. Develop >= n bits of src.num / src.den, where n is the number of bits + in a double. This (partial) division will use all bits from the + denominator. + 2. Use the remainder to determine how to round the result. + 3. Assign the integral result to a temporary double. + 4. Scale the temporary double, and return the result. + + An alternative algorithm, that would be faster: + 0. Let n be somewhat larger than the number of significant bits in a double. + 1. Extract the most significant n bits of the denominator, and an equal + number of bits from the numerator. + 2. Interpret the extracted numbers as integers, call them a and b + respectively, and develop n bits of the fractions ((a + 1) / b) and + (a / (b + 1)) using mpn_divrem. + 3. If the computed values are identical UP TO THE POSITION WE CARE ABOUT, + we are done. If they are different, repeat the algorithm from step 1, + but first let n = n * 2. + 4. If we end up using all bits from the numerator and denominator, fall + back to the first algorithm above. + 5. Just to make life harder, The computation of a + 1 and b + 1 above + might give carry-out... Needs special handling. It might work to + subtract 1 in both cases instead. +*/ + +double +#if __STDC__ +mpq_get_d (const MP_RAT *src) +#else +mpq_get_d (src) + const MP_RAT *src; +#endif +{ + mp_ptr np, dp; + mp_ptr rp; + mp_size_t nsize = src->_mp_num._mp_size; + mp_size_t dsize = src->_mp_den._mp_size; + mp_size_t qsize, rsize; + mp_size_t sign_quotient = nsize ^ dsize; + unsigned normalization_steps; + mp_limb_t qlimb; +#define N_QLIMBS (1 + (sizeof (double) + BYTES_PER_MP_LIMB-1) / BYTES_PER_MP_LIMB) + mp_limb_t qp[N_QLIMBS + 1]; + TMP_DECL (marker); + + if (nsize == 0) + return 0.0; + + TMP_MARK (marker); + nsize = ABS (nsize); + dsize = ABS (dsize); + np = src->_mp_num._mp_d; + dp = src->_mp_den._mp_d; + + rsize = dsize + N_QLIMBS; + rp = (mp_ptr) TMP_ALLOC ((rsize + 1) * BYTES_PER_MP_LIMB); + + count_leading_zeros (normalization_steps, dp[dsize - 1]); + + /* Normalize the denominator, i.e. make its most significant bit set by + shifting it NORMALIZATION_STEPS bits to the left. Also shift the + numerator the same number of steps (to keep the quotient the same!). */ + if (normalization_steps != 0) + { + mp_ptr tp; + mp_limb_t nlimb; + + /* Shift up the denominator setting the most significant bit of + the most significant limb. Use temporary storage not to clobber + the original contents of the denominator. */ + tp = (mp_ptr) TMP_ALLOC (dsize * BYTES_PER_MP_LIMB); + mpn_lshift (tp, dp, dsize, normalization_steps); + dp = tp; + + if (rsize > nsize) + { + MPN_ZERO (rp, rsize - nsize); + nlimb = mpn_lshift (rp + (rsize - nsize), + np, nsize, normalization_steps); + } + else + { + nlimb = mpn_lshift (rp, np + (nsize - rsize), + rsize, normalization_steps); + } + if (nlimb != 0) + { + rp[rsize] = nlimb; + rsize++; + } + } + else + { + if (rsize > nsize) + { + MPN_ZERO (rp, rsize - nsize); + MPN_COPY (rp + (rsize - nsize), np, nsize); + } + else + { + MPN_COPY (rp, np + (nsize - rsize), rsize); + } + } + + qlimb = mpn_divmod (qp, rp, rsize, dp, dsize); + qsize = rsize - dsize; + if (qlimb) + { + qp[qsize] = qlimb; + qsize++; + } + + { + double res; + mp_size_t i; + + res = qp[qsize - 1]; + for (i = qsize - 2; i >= 0; i--) + res = res * MP_BASE_AS_DOUBLE + qp[i]; + + res = __gmp_scale2 (res, BITS_PER_MP_LIMB * (nsize - dsize - N_QLIMBS)); + + TMP_FREE (marker); + return sign_quotient >= 0 ? res : -res; + } +} diff --git a/contrib/libgmp/mpq/get_den.c b/contrib/libgmp/mpq/get_den.c new file mode 100644 index 0000000..fc5e387 --- /dev/null +++ b/contrib/libgmp/mpq/get_den.c @@ -0,0 +1,41 @@ +/* mpq_get_den(den,rat_src) -- Set DEN to the denominator of RAT_SRC. + +Copyright (C) 1991, 1994, 1995 Free Software Foundation, Inc. + +This file is part of the GNU MP Library. + +The GNU MP Library is free software; you can redistribute it and/or modify +it under the terms of the GNU Library General Public License as published by +the Free Software Foundation; either version 2 of the License, or (at your +option) any later version. + +The GNU MP Library is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public +License for more details. + +You should have received a copy of the GNU Library General Public License +along with the GNU MP Library; see the file COPYING.LIB. If not, write to +the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, +MA 02111-1307, USA. */ + +#include "gmp.h" +#include "gmp-impl.h" + +void +#if __STDC__ +mpq_get_den (MP_INT *den, const MP_RAT *src) +#else +mpq_get_den (den, src) + MP_INT *den; + const MP_RAT *src; +#endif +{ + mp_size_t size = src->_mp_den._mp_size; + + if (den->_mp_alloc < size) + _mpz_realloc (den, size); + + MPN_COPY (den->_mp_d, src->_mp_den._mp_d, size); + den->_mp_size = size; +} diff --git a/contrib/libgmp/mpq/get_num.c b/contrib/libgmp/mpq/get_num.c new file mode 100644 index 0000000..61f812f --- /dev/null +++ b/contrib/libgmp/mpq/get_num.c @@ -0,0 +1,42 @@ + /* mpq_get_num(num,rat_src) -- Set NUM to the numerator of RAT_SRC. + +Copyright (C) 1991, 1994, 1995 Free Software Foundation, Inc. + +This file is part of the GNU MP Library. + +The GNU MP Library is free software; you can redistribute it and/or modify +it under the terms of the GNU Library General Public License as published by +the Free Software Foundation; either version 2 of the License, or (at your +option) any later version. + +The GNU MP Library is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public +License for more details. + +You should have received a copy of the GNU Library General Public License +along with the GNU MP Library; see the file COPYING.LIB. If not, write to +the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, +MA 02111-1307, USA. */ + +#include "gmp.h" +#include "gmp-impl.h" + +void +#if __STDC__ +mpq_get_num (MP_INT *num, const MP_RAT *src) +#else +mpq_get_num (num, src) + MP_INT *num; + const MP_RAT *src; +#endif +{ + mp_size_t size = src->_mp_num._mp_size; + mp_size_t abs_size = ABS (size); + + if (num->_mp_alloc < abs_size) + _mpz_realloc (num, abs_size); + + MPN_COPY (num->_mp_d, src->_mp_num._mp_d, abs_size); + num->_mp_size = size; +} diff --git a/contrib/libgmp/mpq/init.c b/contrib/libgmp/mpq/init.c new file mode 100644 index 0000000..ae6d8b3 --- /dev/null +++ b/contrib/libgmp/mpq/init.c @@ -0,0 +1,40 @@ +/* mpq_init -- Make a new rational number with value 0/1. + +Copyright (C) 1991, 1994, 1995 Free Software Foundation, Inc. + +This file is part of the GNU MP Library. + +The GNU MP Library is free software; you can redistribute it and/or modify +it under the terms of the GNU Library General Public License as published by +the Free Software Foundation; either version 2 of the License, or (at your +option) any later version. + +The GNU MP Library is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public +License for more details. + +You should have received a copy of the GNU Library General Public License +along with the GNU MP Library; see the file COPYING.LIB. If not, write to +the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, +MA 02111-1307, USA. */ + +#include "gmp.h" +#include "gmp-impl.h" + +void +#if __STDC__ +mpq_init (MP_RAT *x) +#else +mpq_init (x) + MP_RAT *x; +#endif +{ + x->_mp_num._mp_alloc = 1; + x->_mp_num._mp_d = (mp_ptr) (*_mp_allocate_func) (BYTES_PER_MP_LIMB); + x->_mp_num._mp_size = 0; + x->_mp_den._mp_alloc = 1; + x->_mp_den._mp_d = (mp_ptr) (*_mp_allocate_func) (BYTES_PER_MP_LIMB); + x->_mp_den._mp_d[0] = 1; + x->_mp_den._mp_size = 1; +} diff --git a/contrib/libgmp/mpq/inv.c b/contrib/libgmp/mpq/inv.c new file mode 100644 index 0000000..745c78d --- /dev/null +++ b/contrib/libgmp/mpq/inv.c @@ -0,0 +1,75 @@ +/* mpq_inv(dest,src) -- invert a rational number, i.e. set DEST to SRC + with the numerator and denominator swapped. + +Copyright (C) 1991, 1994, 1995 Free Software Foundation, Inc. + +This file is part of the GNU MP Library. + +The GNU MP Library is free software; you can redistribute it and/or modify +it under the terms of the GNU Library General Public License as published by +the Free Software Foundation; either version 2 of the License, or (at your +option) any later version. + +The GNU MP Library is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public +License for more details. + +You should have received a copy of the GNU Library General Public License +along with the GNU MP Library; see the file COPYING.LIB. If not, write to +the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, +MA 02111-1307, USA. */ + +#include "gmp.h" +#include "gmp-impl.h" + +void +#if __STDC__ +mpq_inv (MP_RAT *dest, const MP_RAT *src) +#else +mpq_inv (dest, src) + MP_RAT *dest; + const MP_RAT *src; +#endif +{ + mp_size_t num_size = src->_mp_num._mp_size; + mp_size_t den_size = src->_mp_den._mp_size; + + if (num_size == 0) + num_size = 1 / num_size; /* Divide by zero! */ + + if (num_size < 0) + { + num_size = -num_size; + den_size = -den_size; + } + dest->_mp_den._mp_size = num_size; + dest->_mp_num._mp_size = den_size; + + /* If dest == src we may just swap the numerator and denominator, but + we have to ensure the new denominator is positive. */ + + if (dest == src) + { + mp_size_t alloc = dest->_mp_num._mp_alloc; + mp_ptr limb_ptr = dest->_mp_num._mp_d; + + dest->_mp_num._mp_alloc = dest->_mp_den._mp_alloc; + dest->_mp_num._mp_d = dest->_mp_den._mp_d; + + dest->_mp_den._mp_alloc = alloc; + dest->_mp_den._mp_d = limb_ptr; + } + else + { + den_size = ABS (den_size); + if (dest->_mp_num._mp_alloc < den_size) + _mpz_realloc (&(dest->_mp_num), den_size); + + if (dest->_mp_den._mp_alloc < num_size) + _mpz_realloc (&(dest->_mp_den), num_size); + + MPN_COPY (dest->_mp_num._mp_d, src->_mp_den._mp_d, den_size); + MPN_COPY (dest->_mp_den._mp_d, src->_mp_num._mp_d, num_size); + } +} diff --git a/contrib/libgmp/mpq/mul.c b/contrib/libgmp/mpq/mul.c new file mode 100644 index 0000000..35f960c --- /dev/null +++ b/contrib/libgmp/mpq/mul.c @@ -0,0 +1,79 @@ +/* mpq_mul -- mutiply two rational numbers. + +Copyright (C) 1991, 1994, 1995, 1996 Free Software Foundation, Inc. + +This file is part of the GNU MP Library. + +The GNU MP Library is free software; you can redistribute it and/or modify +it under the terms of the GNU Library General Public License as published by +the Free Software Foundation; either version 2 of the License, or (at your +option) any later version. + +The GNU MP Library is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public +License for more details. + +You should have received a copy of the GNU Library General Public License +along with the GNU MP Library; see the file COPYING.LIB. If not, write to +the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, +MA 02111-1307, USA. */ + +#include "gmp.h" +#include "gmp-impl.h" + +void +#if __STDC__ +mpq_mul (mpq_ptr prod, mpq_srcptr op1, mpq_srcptr op2) +#else +mpq_mul (prod, op1, op2) + mpq_ptr prod; + mpq_srcptr op1; + mpq_srcptr op2; +#endif +{ + mpz_t gcd1, gcd2; + mpz_t tmp1, tmp2; + + mpz_init (gcd1); + mpz_init (gcd2); + mpz_init (tmp1); + mpz_init (tmp2); + + /* PROD might be identical to either operand, so don't store the + result there until we are finished with the input operands. We + dare to overwrite the numerator of PROD when we are finished + with the numerators of OP1 and OP2. */ + + mpz_gcd (gcd1, &(op1->_mp_num), &(op2->_mp_den)); + mpz_gcd (gcd2, &(op2->_mp_num), &(op1->_mp_den)); + + if (gcd1->_mp_size > 1 || gcd1->_mp_d[0] != 1) + mpz_divexact (tmp1, &(op1->_mp_num), gcd1); + else + mpz_set (tmp1, &(op1->_mp_num)); + + if (gcd2->_mp_size > 1 || gcd2->_mp_d[0] != 1) + mpz_divexact (tmp2, &(op2->_mp_num), gcd2); + else + mpz_set (tmp2, &(op2->_mp_num)); + + mpz_mul (&(prod->_mp_num), tmp1, tmp2); + + if (gcd1->_mp_size > 1 || gcd1->_mp_d[0] != 1) + mpz_divexact (tmp1, &(op2->_mp_den), gcd1); + else + mpz_set (tmp1, &(op2->_mp_den)); + + if (gcd2->_mp_size > 1 || gcd2->_mp_d[0] != 1) + mpz_divexact (tmp2, &(op1->_mp_den), gcd2); + else + mpz_set (tmp2, &(op1->_mp_den)); + + mpz_mul (&(prod->_mp_den), tmp1, tmp2); + + mpz_clear (tmp2); + mpz_clear (tmp1); + mpz_clear (gcd2); + mpz_clear (gcd1); +} diff --git a/contrib/libgmp/mpq/neg.c b/contrib/libgmp/mpq/neg.c new file mode 100644 index 0000000..ac54d27 --- /dev/null +++ b/contrib/libgmp/mpq/neg.c @@ -0,0 +1,36 @@ +/* mpq_neg(dst, src) -- Assign the negated value of SRC to DST. + +Copyright (C) 1991, 1994, 1995 Free Software Foundation, Inc. + +This file is part of the GNU MP Library. + +The GNU MP Library is free software; you can redistribute it and/or modify +it under the terms of the GNU Library General Public License as published by +the Free Software Foundation; either version 2 of the License, or (at your +option) any later version. + +The GNU MP Library is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public +License for more details. + +You should have received a copy of the GNU Library General Public License +along with the GNU MP Library; see the file COPYING.LIB. If not, write to +the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, +MA 02111-1307, USA. */ + +#include "gmp.h" +#include "gmp-impl.h" + +void +#if __STDC__ +mpq_neg (MP_RAT *dst, const MP_RAT *src) +#else +mpq_neg (dst, src) + MP_RAT *dst; + const MP_RAT *src; +#endif +{ + mpz_neg (&dst->_mp_num, &src->_mp_num); + mpz_set (&dst->_mp_den, &src->_mp_den); +} diff --git a/contrib/libgmp/mpq/set.c b/contrib/libgmp/mpq/set.c new file mode 100644 index 0000000..ef85639 --- /dev/null +++ b/contrib/libgmp/mpq/set.c @@ -0,0 +1,49 @@ +/* mpq_set(dest,src) -- Set DEST to SRC. + +Copyright (C) 1991, 1994, 1995 Free Software Foundation, Inc. + +This file is part of the GNU MP Library. + +The GNU MP Library is free software; you can redistribute it and/or modify +it under the terms of the GNU Library General Public License as published by +the Free Software Foundation; either version 2 of the License, or (at your +option) any later version. + +The GNU MP Library is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public +License for more details. + +You should have received a copy of the GNU Library General Public License +along with the GNU MP Library; see the file COPYING.LIB. If not, write to +the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, +MA 02111-1307, USA. */ + +#include "gmp.h" +#include "gmp-impl.h" + +void +#if __STDC__ +mpq_set (MP_RAT *dest, const MP_RAT *src) +#else +mpq_set (dest, src) + MP_RAT *dest; + const MP_RAT *src; +#endif +{ + mp_size_t num_size, den_size; + mp_size_t abs_num_size; + + num_size = src->_mp_num._mp_size; + abs_num_size = ABS (num_size); + if (dest->_mp_num._mp_alloc < abs_num_size) + _mpz_realloc (&(dest->_mp_num), abs_num_size); + MPN_COPY (dest->_mp_num._mp_d, src->_mp_num._mp_d, abs_num_size); + dest->_mp_num._mp_size = num_size; + + den_size = src->_mp_den._mp_size; + if (dest->_mp_den._mp_alloc < den_size) + _mpz_realloc (&(dest->_mp_den), den_size); + MPN_COPY (dest->_mp_den._mp_d, src->_mp_den._mp_d, den_size); + dest->_mp_den._mp_size = den_size; +} diff --git a/contrib/libgmp/mpq/set_den.c b/contrib/libgmp/mpq/set_den.c new file mode 100644 index 0000000..4586c89 --- /dev/null +++ b/contrib/libgmp/mpq/set_den.c @@ -0,0 +1,42 @@ +/* mpq_set_den(dest,den) -- Set the denominator of DEST from DEN. + +Copyright (C) 1991, 1994, 1995, 1996 Free Software Foundation, Inc. + +This file is part of the GNU MP Library. + +The GNU MP Library is free software; you can redistribute it and/or modify +it under the terms of the GNU Library General Public License as published by +the Free Software Foundation; either version 2 of the License, or (at your +option) any later version. + +The GNU MP Library is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public +License for more details. + +You should have received a copy of the GNU Library General Public License +along with the GNU MP Library; see the file COPYING.LIB. If not, write to +the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, +MA 02111-1307, USA. */ + +#include "gmp.h" +#include "gmp-impl.h" + +void +#if __STDC__ +mpq_set_den (MP_RAT *dest, const MP_INT *den) +#else +mpq_set_den (dest, den) + MP_RAT *dest; + const MP_INT *den; +#endif +{ + mp_size_t size = den->_mp_size; + mp_size_t abs_size = ABS (size); + + if (dest->_mp_den._mp_alloc < abs_size) + _mpz_realloc (&(dest->_mp_den), abs_size); + + MPN_COPY (dest->_mp_den._mp_d, den->_mp_d, abs_size); + dest->_mp_den._mp_size = abs_size; +} diff --git a/contrib/libgmp/mpq/set_num.c b/contrib/libgmp/mpq/set_num.c new file mode 100644 index 0000000..ce918ce --- /dev/null +++ b/contrib/libgmp/mpq/set_num.c @@ -0,0 +1,42 @@ +/* mpq_set_num(dest,num) -- Set the numerator of DEST from NUM. + +Copyright (C) 1991, 1994, 1995 Free Software Foundation, Inc. + +This file is part of the GNU MP Library. + +The GNU MP Library is free software; you can redistribute it and/or modify +it under the terms of the GNU Library General Public License as published by +the Free Software Foundation; either version 2 of the License, or (at your +option) any later version. + +The GNU MP Library is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public +License for more details. + +You should have received a copy of the GNU Library General Public License +along with the GNU MP Library; see the file COPYING.LIB. If not, write to +the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, +MA 02111-1307, USA. */ + +#include "gmp.h" +#include "gmp-impl.h" + +void +#if __STDC__ +mpq_set_num (MP_RAT *dest, const MP_INT *num) +#else +mpq_set_num (dest, num) + MP_RAT *dest; + const MP_INT *num; +#endif +{ + mp_size_t size = num->_mp_size; + mp_size_t abs_size = ABS (size); + + if (dest->_mp_num._mp_alloc < abs_size) + _mpz_realloc (&(dest->_mp_num), abs_size); + + MPN_COPY (dest->_mp_num._mp_d, num->_mp_d, abs_size); + dest->_mp_num._mp_size = size; +} diff --git a/contrib/libgmp/mpq/set_si.c b/contrib/libgmp/mpq/set_si.c new file mode 100644 index 0000000..cf1f9f0 --- /dev/null +++ b/contrib/libgmp/mpq/set_si.c @@ -0,0 +1,54 @@ +/* mpq_set_si(dest,ulong_num,ulong_den) -- Set DEST to the retional number + ULONG_NUM/ULONG_DEN. + +Copyright (C) 1991, 1994, 1995 Free Software Foundation, Inc. + +This file is part of the GNU MP Library. + +The GNU MP Library is free software; you can redistribute it and/or modify +it under the terms of the GNU Library General Public License as published by +the Free Software Foundation; either version 2 of the License, or (at your +option) any later version. + +The GNU MP Library is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public +License for more details. + +You should have received a copy of the GNU Library General Public License +along with the GNU MP Library; see the file COPYING.LIB. If not, write to +the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, +MA 02111-1307, USA. */ + +#include "gmp.h" +#include "gmp-impl.h" + +void +#if __STDC__ +mpq_set_si (MP_RAT *dest, signed long int num, unsigned long int den) +#else +mpq_set_si (dest, num, den) + MP_RAT *dest; + signed long int num; + unsigned long int den; +#endif +{ + unsigned long int abs_num; + + abs_num = ABS (num); + + if (num == 0) + { + /* Canonicalize 0/d to 0/1. */ + den = 1; + dest->_mp_num._mp_size = 0; + } + else + { + dest->_mp_num._mp_d[0] = abs_num; + dest->_mp_num._mp_size = num > 0 ? 1 : -1; + } + + dest->_mp_den._mp_d[0] = den; + dest->_mp_den._mp_size = 1; +} diff --git a/contrib/libgmp/mpq/set_ui.c b/contrib/libgmp/mpq/set_ui.c new file mode 100644 index 0000000..aaa9fc2 --- /dev/null +++ b/contrib/libgmp/mpq/set_ui.c @@ -0,0 +1,50 @@ +/* mpq_set_ui(dest,ulong_num,ulong_den) -- Set DEST to the retional number + ULONG_NUM/ULONG_DEN. + +Copyright (C) 1991, 1994, 1995 Free Software Foundation, Inc. + +This file is part of the GNU MP Library. + +The GNU MP Library is free software; you can redistribute it and/or modify +it under the terms of the GNU Library General Public License as published by +the Free Software Foundation; either version 2 of the License, or (at your +option) any later version. + +The GNU MP Library is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public +License for more details. + +You should have received a copy of the GNU Library General Public License +along with the GNU MP Library; see the file COPYING.LIB. If not, write to +the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, +MA 02111-1307, USA. */ + +#include "gmp.h" +#include "gmp-impl.h" + +void +#if __STDC__ +mpq_set_ui (MP_RAT *dest, unsigned long int num, unsigned long int den) +#else +mpq_set_ui (dest, num, den) + MP_RAT *dest; + unsigned long int num; + unsigned long int den; +#endif +{ + if (num == 0) + { + /* Canonicalize 0/n to 0/1. */ + den = 1; + dest->_mp_num._mp_size = 0; + } + else + { + dest->_mp_num._mp_d[0] = num; + dest->_mp_num._mp_size = 1; + } + + dest->_mp_den._mp_d[0] = den; + dest->_mp_den._mp_size = 1; +} diff --git a/contrib/libgmp/mpq/set_z.c b/contrib/libgmp/mpq/set_z.c new file mode 100644 index 0000000..ca638f3 --- /dev/null +++ b/contrib/libgmp/mpq/set_z.c @@ -0,0 +1,46 @@ +/* mpq_set_z (dest,src) -- Set DEST to SRC. + +Copyright (C) 1996 Free Software Foundation, Inc. + +This file is part of the GNU MP Library. + +The GNU MP Library is free software; you can redistribute it and/or modify +it under the terms of the GNU Library General Public License as published by +the Free Software Foundation; either version 2 of the License, or (at your +option) any later version. + +The GNU MP Library is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public +License for more details. + +You should have received a copy of the GNU Library General Public License +along with the GNU MP Library; see the file COPYING.LIB. If not, write to +the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, +MA 02111-1307, USA. */ + +#include "gmp.h" +#include "gmp-impl.h" + +void +#if __STDC__ +mpq_set_z (mpq_ptr dest, mpz_srcptr src) +#else +mpq_set_z (dest, src) + mpq_ptr dest; + mpz_srcptr src; +#endif +{ + mp_size_t num_size; + mp_size_t abs_num_size; + + num_size = src->_mp_size; + abs_num_size = ABS (num_size); + if (dest->_mp_num._mp_alloc < abs_num_size) + _mpz_realloc (&(dest->_mp_num), abs_num_size); + MPN_COPY (dest->_mp_num._mp_d, src->_mp_d, abs_num_size); + dest->_mp_num._mp_size = num_size; + + dest->_mp_den._mp_d[0] = 1; + dest->_mp_den._mp_size = 1; +} diff --git a/contrib/libgmp/mpq/sub.c b/contrib/libgmp/mpq/sub.c new file mode 100644 index 0000000..9274ff8 --- /dev/null +++ b/contrib/libgmp/mpq/sub.c @@ -0,0 +1,85 @@ +/* mpq_sub -- subtract two rational numbers. + +Copyright (C) 1991, 1994, 1995, 1996 Free Software Foundation, Inc. + +This file is part of the GNU MP Library. + +The GNU MP Library is free software; you can redistribute it and/or modify +it under the terms of the GNU Library General Public License as published by +the Free Software Foundation; either version 2 of the License, or (at your +option) any later version. + +The GNU MP Library is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public +License for more details. + +You should have received a copy of the GNU Library General Public License +along with the GNU MP Library; see the file COPYING.LIB. If not, write to +the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, +MA 02111-1307, USA. */ + +#include "gmp.h" +#include "gmp-impl.h" + +void +#if __STDC__ +mpq_sub (mpq_ptr rop, mpq_srcptr op1, mpq_srcptr op2) +#else +mpq_sub (rop, op1, op2) + mpq_ptr rop; + mpq_srcptr op1; + mpq_srcptr op2; +#endif +{ + mpz_t gcd; + mpz_t tmp1, tmp2; + mp_size_t op1_num_size = ABS (op1->_mp_num._mp_size); + mp_size_t op1_den_size = ABS (op1->_mp_den._mp_size); + mp_size_t op2_num_size = ABS (op2->_mp_num._mp_size); + mp_size_t op2_den_size = ABS (op2->_mp_den._mp_size); + TMP_DECL (marker); + + TMP_MARK (marker); + MPZ_TMP_INIT (gcd, MIN (op1_den_size, op2_den_size)); + MPZ_TMP_INIT (tmp1, op1_num_size + op2_den_size); + MPZ_TMP_INIT (tmp2, op2_num_size + op1_den_size); + + /* ROP might be identical to either operand, so don't store the + result there until we are finished with the input operands. We + dare to overwrite the numerator of ROP when we are finished + with the numerators of OP1 and OP2. */ + + mpz_gcd (gcd, &(op1->_mp_den), &(op2->_mp_den)); + if (gcd->_mp_size > 1 || gcd->_mp_d[0] != 1) + { + mpz_t t; + + mpz_divexact (tmp1, &(op2->_mp_den), gcd); + mpz_mul (tmp1, &(op1->_mp_num), tmp1); + + mpz_divexact (tmp2, &(op1->_mp_den), gcd); + mpz_mul (tmp2, &(op2->_mp_num), tmp2); + + MPZ_TMP_INIT (t, MAX (ABS (tmp1->_mp_size), ABS (tmp2->_mp_size)) + 1); + + mpz_sub (t, tmp1, tmp2); + mpz_divexact (tmp1, &(op1->_mp_den), gcd); + mpz_gcd (gcd, t, gcd); + + mpz_divexact (&(rop->_mp_num), t, gcd); + + mpz_divexact (tmp2, &(op2->_mp_den), gcd); + mpz_mul (&(rop->_mp_den), tmp1, tmp2); + } + else + { + /* The common divisor is 1. This is the case (for random input) with + probability 6/(pi**2). */ + mpz_mul (tmp1, &(op1->_mp_num), &(op2->_mp_den)); + mpz_mul (tmp2, &(op2->_mp_num), &(op1->_mp_den)); + mpz_sub (&(rop->_mp_num), tmp1, tmp2); + mpz_mul (&(rop->_mp_den), &(op1->_mp_den), &(op2->_mp_den)); + } + TMP_FREE (marker); +} diff --git a/contrib/libgmp/mpq/tests/Makefile.in b/contrib/libgmp/mpq/tests/Makefile.in new file mode 100644 index 0000000..d7921c0 --- /dev/null +++ b/contrib/libgmp/mpq/tests/Makefile.in @@ -0,0 +1,48 @@ +# Makefile for mpq/tests for GNU MP + +srcdir = . + +CC = gcc + +TEST_LIBS = ../../libgmp.a +INCLUDES = -I../../mpn -I$(srcdir)/../.. +CFLAGS = -g -O + +.c.o: + $(CC) -c $(INCLUDES) $(CFLAGS) $(XCFLAGS) $< + +TEST_SRCS = t-cmp.c t-cmp_ui.c t-get_d.c +TEST_OBJS = t-cmp.o t-cmp_ui.o t-get_d.o +TESTS = t-cmp t-cmp_ui t-get_d + +check: Makefile st-cmp st-cmp_ui st-get_d + @echo "The tests passed." + +st-cmp: t-cmp + ./t-cmp + touch $@ +st-cmp_ui: t-cmp_ui + ./t-cmp_ui + touch $@ +st-get_d: t-get_d + ./t-get_d + touch $@ + +t-cmp: t-cmp.o $(TEST_LIBS) + $(CC) -o $@ $@.o $(TEST_LIBS) $(CFLAGS) +t-cmp_ui: t-cmp_ui.o $(TEST_LIBS) + $(CC) -o $@ $@.o $(TEST_LIBS) $(CFLAGS) +t-get_d: t-get_d.o $(TEST_LIBS) + $(CC) -o $@ $@.o $(TEST_LIBS) $(CFLAGS) + +t-cmp.o: $(srcdir)/t-cmp.c +t-cmp_ui.o: $(srcdir)/t-cmp_ui.c +t-get_d.o: $(srcdir)/t-get_d.c + +clean mostlyclean: + rm -f *.o st-* $(TESTS) +distclean maintainer-clean: clean + rm -f Makefile config.status + +Makefile: $(srcdir)/Makefile.in + $(SHELL) ./config.status diff --git a/contrib/libgmp/mpq/tests/configure.in b/contrib/libgmp/mpq/tests/configure.in new file mode 100644 index 0000000..5ee2138 --- /dev/null +++ b/contrib/libgmp/mpq/tests/configure.in @@ -0,0 +1,11 @@ +# This file is a shell script that supplies the information necessary +# to tailor a template configure script into the configure script +# appropriate for this directory. For more information, check any +# existing configure script. + +srctrigger=t-cmp.c +srcname="gmp/mpq/tests" + +# per-host: + +# per-target: diff --git a/contrib/libgmp/mpq/tests/t-cmp.c b/contrib/libgmp/mpq/tests/t-cmp.c new file mode 100644 index 0000000..77e46f2 --- /dev/null +++ b/contrib/libgmp/mpq/tests/t-cmp.c @@ -0,0 +1,109 @@ +/* Test mpq_cmp. + +Copyright (C) 1996 Free Software Foundation, Inc. + +This file is part of the GNU MP Library. + +The GNU MP Library is free software; you can redistribute it and/or modify +it under the terms of the GNU Library General Public License as published by +the Free Software Foundation; either version 2 of the License, or (at your +option) any later version. + +The GNU MP Library is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public +License for more details. + +You should have received a copy of the GNU Library General Public License +along with the GNU MP Library; see the file COPYING.LIB. If not, write to +the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, +MA 02111-1307, USA. */ + +#include <stdio.h> +#include "gmp.h" +#include "gmp-impl.h" +#include "urandom.h" + +#define NUM(x) (&((x)->_mp_num)) +#define DEN(x) (&((x)->_mp_den)) + +#define SGN(x) ((x) < 0 ? -1 : (x) > 0 ? 1 : 0) + +ref_mpq_cmp (a, b) + mpq_t a, b; +{ + mpz_t ai, bi; + int cc; + + mpz_init (ai); + mpz_init (bi); + + mpz_mul (ai, NUM (a), DEN (b)); + mpz_mul (bi, NUM (b), DEN (a)); + cc = mpz_cmp (ai, bi); + mpz_clear (ai); + mpz_clear (bi); + return cc; +} + +#ifndef SIZE +#define SIZE 8 /* increasing this lowers the probabilty of finding an error */ +#endif + +main (argc, argv) + int argc; + char **argv; +{ + mpq_t a, b; + mp_size_t size; + int reps = 100000; + int i; + int cc, ccref; + + if (argc == 2) + reps = atoi (argv[1]); + + mpq_init (a); + mpq_init (b); + + for (i = 0; i < reps; i++) + { + size = urandom () % SIZE - SIZE/2; + mpz_random2 (NUM (a), size); + do + { + size = urandom () % SIZE - SIZE/2; + mpz_random2 (DEN (a), size); + } + while (mpz_cmp_ui (DEN (a), 0) == 0); + + size = urandom () % SIZE - SIZE/2; + mpz_random2 (NUM (b), size); + do + { + size = urandom () % SIZE - SIZE/2; + mpz_random2 (DEN (b), size); + } + while (mpz_cmp_ui (DEN (b), 0) == 0); + + mpq_canonicalize (a); + mpq_canonicalize (b); + + ccref = ref_mpq_cmp (a, b); + cc = mpq_cmp (a, b); + + if (SGN (ccref) != SGN (cc)) + abort (); + } + + exit (0); +} + +dump (x) + mpq_t x; +{ + mpz_out_str (stdout, 10, NUM (x)); + printf ("/"); + mpz_out_str (stdout, 10, DEN (x)); + printf ("\n"); +} diff --git a/contrib/libgmp/mpq/tests/t-cmp_ui.c b/contrib/libgmp/mpq/tests/t-cmp_ui.c new file mode 100644 index 0000000..f7b92ad --- /dev/null +++ b/contrib/libgmp/mpq/tests/t-cmp_ui.c @@ -0,0 +1,102 @@ +/* Test mpq_cmp_ui. + +Copyright (C) 1996 Free Software Foundation, Inc. + +This file is part of the GNU MP Library. + +The GNU MP Library is free software; you can redistribute it and/or modify +it under the terms of the GNU Library General Public License as published by +the Free Software Foundation; either version 2 of the License, or (at your +option) any later version. + +The GNU MP Library is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public +License for more details. + +You should have received a copy of the GNU Library General Public License +along with the GNU MP Library; see the file COPYING.LIB. If not, write to +the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, +MA 02111-1307, USA. */ + +#include "gmp.h" +#include "gmp-impl.h" +#include "urandom.h" + +#define NUM(x) (&((x)->_mp_num)) +#define DEN(x) (&((x)->_mp_den)) + +#define SGN(x) ((x) < 0 ? -1 : (x) > 0 ? 1 : 0) + +ref_mpq_cmp_ui (a, bn, bd) + mpq_t a; + unsigned long int bn, bd; +{ + mpz_t ai, bi; + int cc; + + mpz_init (ai); + mpz_init (bi); + + mpz_mul_ui (ai, NUM (a), bd); + mpz_mul_ui (bi, DEN (a), bn); + cc = mpz_cmp (ai, bi); + mpz_clear (ai); + mpz_clear (bi); + return cc; +} + +#ifndef SIZE +#define SIZE 8 /* increasing this lowers the probabilty of finding an error */ +#endif + +main (argc, argv) + int argc; + char **argv; +{ + mpq_t a, b; + mp_size_t size; + int reps = 100000; + int i; + int cc, ccref; + unsigned long int bn, bd; + + if (argc == 2) + reps = atoi (argv[1]); + + mpq_init (a); + mpq_init (b); + + for (i = 0; i < reps; i++) + { + size = urandom () % SIZE - SIZE/2; + mpz_random2 (NUM (a), size); + do + { + size = urandom () % SIZE - SIZE/2; + mpz_random2 (DEN (a), size); + } + while (mpz_cmp_ui (DEN (a), 0) == 0); + + mpz_random2 (NUM (b), 1); + do + { + mpz_random2 (DEN (b), 1); + } + while (mpz_cmp_ui (DEN (b), 0) == 0); + + mpq_canonicalize (a); + mpq_canonicalize (b); + + bn = mpz_get_ui (NUM (b)); + bd = mpz_get_ui (DEN (b)); + + ccref = ref_mpq_cmp_ui (a, bn, bd); + cc = mpq_cmp_ui (a, bn, bd); + + if (SGN (ccref) != SGN (cc)) + abort (); + } + + exit (0); +} diff --git a/contrib/libgmp/mpq/tests/t-get_d.c b/contrib/libgmp/mpq/tests/t-get_d.c new file mode 100644 index 0000000..db4f926 --- /dev/null +++ b/contrib/libgmp/mpq/tests/t-get_d.c @@ -0,0 +1,88 @@ +/* Test mpq_get_d + +Copyright (C) 1991, 1993, 1994, 1996 Free Software Foundation, Inc. + +This file is part of the GNU MP Library. + +The GNU MP Library is free software; you can redistribute it and/or modify +it under the terms of the GNU Library General Public License as published by +the Free Software Foundation; either version 2 of the License, or (at your +option) any later version. + +The GNU MP Library is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public +License for more details. + +You should have received a copy of the GNU Library General Public License +along with the GNU MP Library; see the file COPYING.LIB. If not, write to +the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, +MA 02111-1307, USA. */ + +#include <stdio.h> +#include "gmp.h" +#include "gmp-impl.h" +#include "urandom.h" + +#ifndef SIZE +#define SIZE 8 +#endif + +main (argc, argv) + int argc; + char **argv; +{ + mpq_t a; + mp_size_t size; + int reps = 10000; + int i, j; + double last_d, new_d; + mpz_t eps; + + if (argc == 2) + reps = atoi (argv[1]); + + /* The idea here is to test the monotonousness of mpq_get_d by adding + numbers to the numerator and denominator. */ + + mpq_init (a); + mpz_init (eps); + + for (i = 0; i < reps; i++) + { + size = urandom () % SIZE - SIZE/2; + mpz_random2 (mpq_numref (a), size); + do + { + size = urandom () % SIZE - SIZE/2; + mpz_random2 (mpq_denref (a), size); + } + while (mpz_cmp_ui (mpq_denref (a), 0) == 0); + + mpq_canonicalize (a); + + last_d = mpq_get_d (a); + for (j = 0; j < 10; j++) + { + size = urandom () % SIZE; + mpz_random2 (eps, size); + mpz_add (mpq_numref (a), mpq_numref (a), eps); + mpq_canonicalize (a); + new_d = mpq_get_d (a); + if (last_d > new_d) + abort (); + last_d = new_d; + } + } + + exit (0); +} + +dump (x) + mpq_t x; +{ + mpz_out_str (stdout, 10, mpq_numref (x)); + printf ("/"); + mpz_out_str (stdout, 10, mpq_denref (x)); + printf ("\n"); +} diff --git a/contrib/libgmp/mpz/Makefile.in b/contrib/libgmp/mpz/Makefile.in new file mode 100644 index 0000000..497f09c --- /dev/null +++ b/contrib/libgmp/mpz/Makefile.in @@ -0,0 +1,180 @@ +# Makefile for GNU MP/mpz functions +# Copyright (C) 1991, 1993, 1994, 1996 Free Software Foundation, Inc. + +# This file is part of the GNU MP Library. + +# The GNU MP Library is free software; you can redistribute it and/or modify +# it under the terms of the GNU Library General Public License as published by +# the Free Software Foundation; either version 2 of the License, or (at your +# option) any later version. + +# The GNU MP Library is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +# or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public +# License for more details. + +# You should have received a copy of the GNU Library General Public License +# along with the GNU MP Library; see the file COPYING.LIB. If not, write to +# the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, +# MA 02111-1307, USA. + +srcdir = . + +CC = gcc + +# If you cross compile on a machine with the same sizes of the integral +# types ("int", "long int", "short int", and "char") define this as the +# local compiler. Otherwise, you need to look for the uses of LOCAL_CC below, +# and handle those cases manually. +LOCAL_CC = $(CC) +CFLAGS = -g -O +AR = ar +AR_FLAGS = rc +SHELL = /bin/sh + +#### host and target specific makefile fragments come in here. +### + +MPZ_SRCS = init.c set.c set_ui.c set_si.c set_str.c set_d.c set_f.c set_q.c \ + iset.c iset_ui.c iset_si.c iset_str.c iset_d.c clear.c \ + get_ui.c get_si.c get_str.c get_d.c size.c sizeinbase.c \ + add.c add_ui.c sub.c sub_ui.c mul.c mul_ui.c \ + gcd.c gcd_ui.c gcdext.c sqrt.c sqrtrem.c powm.c powm_ui.c \ + cmp.c cmp_ui.c cmp_si.c mul_2exp.c fdiv_q_2exp.c fdiv_r_2exp.c \ + tdiv_q_2exp.c tdiv_r_2exp.c abs.c neg.c com.c and.c ior.c \ + inp_raw.c inp_str.c out_raw.c out_str.c \ + perfsqr.c random.c random2.c pow_ui.c ui_pow_ui.c setbit.c \ + clrbit.c fac_ui.c pprime_p.c realloc.c getlimbn.c popcount.c hamdist.c \ + cdiv_qr.c cdiv_q.c cdiv_r.c cdiv_qr_ui.c cdiv_q_ui.c cdiv_r_ui.c cdiv_ui.c \ + fdiv_qr.c fdiv_q.c fdiv_r.c fdiv_qr_ui.c fdiv_q_ui.c fdiv_r_ui.c fdiv_ui.c \ + tdiv_qr.c tdiv_q.c tdiv_r.c tdiv_qr_ui.c tdiv_q_ui.c tdiv_r_ui.c \ + mod.c divexact.c array_init.c scan0.c scan1.c \ + jacobi.c legendre.c invert.c +MPZ_OBJS = init.o set.o set_ui.o set_si.o set_str.o set_d.o set_f.o set_q.o \ + iset.o iset_ui.o iset_si.o iset_str.o iset_d.o clear.o \ + get_ui.o get_si.o get_str.o get_d.o size.o sizeinbase.o \ + add.o add_ui.o sub.o sub_ui.o mul.o mul_ui.o \ + gcd.o gcd_ui.o gcdext.o sqrt.o sqrtrem.o powm.o powm_ui.o \ + cmp.o cmp_ui.o cmp_si.o mul_2exp.o fdiv_q_2exp.o fdiv_r_2exp.o \ + tdiv_q_2exp.o tdiv_r_2exp.o abs.o neg.o com.o and.o ior.o \ + inp_raw.o inp_str.o out_raw.o out_str.o \ + perfsqr.o random.o random2.o pow_ui.o ui_pow_ui.o setbit.o \ + clrbit.o fac_ui.o pprime_p.o realloc.o getlimbn.o popcount.o hamdist.o \ + cdiv_qr.o cdiv_q.o cdiv_r.o cdiv_qr_ui.o cdiv_q_ui.o cdiv_r_ui.o cdiv_ui.o \ + fdiv_qr.o fdiv_q.o fdiv_r.o fdiv_qr_ui.o fdiv_q_ui.o fdiv_r_ui.o fdiv_ui.o \ + tdiv_qr.o tdiv_q.o tdiv_r.o tdiv_qr_ui.o tdiv_q_ui.o tdiv_r_ui.o \ + mod.o divexact.o array_init.o scan0.o scan1.o \ + jacobi.o legendre.o invert.o + +INCLUDES = -I. -I.. -I../mpn -I$(srcdir)/.. + +libmpz.a: Makefile $(MPZ_OBJS) + rm -f $@ + $(AR) $(AR_FLAGS) $@ $(MPZ_OBJS) + +.c.o: + $(CC) -c $(INCLUDES) $(CFLAGS) $(XCFLAGS) $< + +clean mostlyclean: + rm -f *.o libmpz.a + -cd tests; $(MAKE) $@ +distclean maintainer-clean: clean + rm -f Makefile config.status + -cd tests; $(MAKE) $@ + +Makefile: $(srcdir)/Makefile.in + $(SHELL) ./config.status + +H = $(srcdir)/../gmp.h $(srcdir)/../gmp-impl.h ../mpn/gmp-mparam.h + +abs.o: $(srcdir)/abs.c $(H) +add.o: $(srcdir)/add.c $(H) +add_ui.o: $(srcdir)/add_ui.c $(H) +and.o: $(srcdir)/and.c $(H) +array_init.o: $(srcdir)/array_init.c $(H) +cdiv_q.o: $(srcdir)/cdiv_q.c $(H) +cdiv_q_ui.o: $(srcdir)/cdiv_q_ui.c $(H) +cdiv_qr.o: $(srcdir)/cdiv_qr.c $(H) +cdiv_qr_ui.o: $(srcdir)/cdiv_qr_ui.c $(H) +cdiv_r.o: $(srcdir)/cdiv_r.c $(H) +cdiv_r_ui.o: $(srcdir)/cdiv_r_ui.c $(H) +cdiv_ui.o: $(srcdir)/cdiv_ui.c $(H) +clear.o: $(srcdir)/clear.c $(H) +clrbit.o: $(srcdir)/clrbit.c $(H) +cmp.o: $(srcdir)/cmp.c $(H) +cmp_si.o: $(srcdir)/cmp_si.c $(H) +cmp_ui.o: $(srcdir)/cmp_ui.c $(H) +com.o: $(srcdir)/com.c $(H) +fdiv_q_2exp.o: $(srcdir)/fdiv_q_2exp.c $(H) +fdiv_r_2exp.o: $(srcdir)/fdiv_r_2exp.c $(H) +divexact.o: $(srcdir)/divexact.c $(H) $(srcdir)/../longlong.h +fac_ui.o: $(srcdir)/fac_ui.c $(H) $(srcdir)/../longlong.h +fdiv_q.o: $(srcdir)/fdiv_q.c $(H) +fdiv_q_ui.o: $(srcdir)/fdiv_q_ui.c $(H) +fdiv_qr.o: $(srcdir)/fdiv_qr.c $(H) +fdiv_qr_ui.o: $(srcdir)/fdiv_qr_ui.c $(H) +fdiv_r.o: $(srcdir)/fdiv_r.c $(H) +fdiv_r_ui.o: $(srcdir)/fdiv_r_ui.c $(H) +fdiv_ui.o: $(srcdir)/fdiv_ui.c $(H) +gcd.o: $(srcdir)/gcd.c $(H) $(srcdir)/../longlong.h +gcd_ui.o: $(srcdir)/gcd_ui.c $(H) +gcdext.o: $(srcdir)/gcdext.c $(H) +get_d.o: $(srcdir)/get_d.c $(H) +get_si.o: $(srcdir)/get_si.c $(H) +get_str.o: $(srcdir)/get_str.c $(H) +get_ui.o: $(srcdir)/get_ui.c $(H) +getlimbn.o: $(srcdir)/getlimbn.c $(H) +hamdist.o: $(srcdir)/hamdist.c $(H) +init.o: $(srcdir)/init.c $(H) +inp_raw.o: $(srcdir)/inp_raw.c $(H) +inp_str.o: $(srcdir)/inp_str.c $(H) +invert.o: $(srcdir)/invert.c $(H) +ior.o: $(srcdir)/ior.c $(H) +iset.o: $(srcdir)/iset.c $(H) +iset_d.o: $(srcdir)/iset_d.c $(H) +iset_si.o: $(srcdir)/iset_si.c $(H) +iset_str.o: $(srcdir)/iset_str.c $(H) +iset_ui.o: $(srcdir)/iset_ui.c $(H) +jacobi.o: $(srcdir)/jacobi.c $(H) +legendre.o: $(srcdir)/legendre.c $(H) +mod.o: $(srcdir)/mod.c $(H) +tdiv_q_2exp.o: $(srcdir)/tdiv_q_2exp.c $(H) +tdiv_r_2exp.o: $(srcdir)/tdiv_r_2exp.c $(H) +mul.o: $(srcdir)/mul.c $(H) +mul_2exp.o: $(srcdir)/mul_2exp.c $(H) +mul_ui.o: $(srcdir)/mul_ui.c $(H) +neg.o: $(srcdir)/neg.c $(H) +out_raw.o: $(srcdir)/out_raw.c $(H) +out_str.o: $(srcdir)/out_str.c $(H) +perfsqr.o: $(srcdir)/perfsqr.c $(H) +popcount.o: $(srcdir)/popcount.c $(H) +pow_ui.o: $(srcdir)/pow_ui.c $(H) $(srcdir)/../longlong.h +powm.o: $(srcdir)/powm.c $(H) $(srcdir)/../longlong.h +powm_ui.o: $(srcdir)/powm_ui.c $(H) $(srcdir)/../longlong.h +pprime_p.o: $(srcdir)/pprime_p.c $(H) +random.o: $(srcdir)/random.c $(H) $(srcdir)/../urandom.h +random2.o: $(srcdir)/random2.c $(H) +realloc.o: $(srcdir)/realloc.c $(H) +scan0.o: $(srcdir)/scan0.c $(H) +scan1.o: $(srcdir)/scan1.c $(H) +set.o: $(srcdir)/set.c $(H) +set_d.o: $(srcdir)/set_d.c $(H) +set_f.o: $(srcdir)/set_f.c $(H) +set_q.o: $(srcdir)/set_q.c $(H) +set_si.o: $(srcdir)/set_si.c $(H) +set_str.o: $(srcdir)/set_str.c $(H) $(srcdir)/../longlong.h +set_ui.o: $(srcdir)/set_ui.c $(H) +setbit.o: $(srcdir)/setbit.c $(H) +size.o: $(srcdir)/size.c $(H) +sizeinbase.o: $(srcdir)/sizeinbase.c $(H) $(srcdir)/../longlong.h +sqrt.o: $(srcdir)/sqrt.c $(H) +sqrtrem.o: $(srcdir)/sqrtrem.c $(H) +sub.o: $(srcdir)/sub.c $(H) +sub_ui.o: $(srcdir)/sub_ui.c $(H) +tdiv_q.o: $(srcdir)/tdiv_q.c $(H) $(srcdir)/../longlong.h +tdiv_q_ui.o: $(srcdir)/tdiv_q_ui.c $(H) +tdiv_qr.o: $(srcdir)/tdiv_qr.c $(H) $(srcdir)/../longlong.h $(srcdir)/dmincl.c $(H) +tdiv_qr_ui.o: $(srcdir)/tdiv_qr_ui.c $(H) +tdiv_r.o: $(srcdir)/tdiv_r.c $(H) $(srcdir)/../longlong.h $(srcdir)/dmincl.c $(H) +tdiv_r_ui.o: $(srcdir)/tdiv_r_ui.c $(H) +ui_pow_ui.o: $(srcdir)/ui_pow_ui.c $(H) $(srcdir)/../longlong.h diff --git a/contrib/libgmp/mpz/abs.c b/contrib/libgmp/mpz/abs.c new file mode 100644 index 0000000..080cac6 --- /dev/null +++ b/contrib/libgmp/mpz/abs.c @@ -0,0 +1,51 @@ +/* mpz_abs(dst, src) -- Assign the absolute value of SRC to DST. + +Copyright (C) 1991, 1993, 1994, 1995 Free Software Foundation, Inc. + +This file is part of the GNU MP Library. + +The GNU MP Library is free software; you can redistribute it and/or modify +it under the terms of the GNU Library General Public License as published by +the Free Software Foundation; either version 2 of the License, or (at your +option) any later version. + +The GNU MP Library is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public +License for more details. + +You should have received a copy of the GNU Library General Public License +along with the GNU MP Library; see the file COPYING.LIB. If not, write to +the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, +MA 02111-1307, USA. */ + +#include "gmp.h" +#include "gmp-impl.h" + +void +#if __STDC__ +mpz_abs (mpz_ptr w, mpz_srcptr u) +#else +mpz_abs (w, u) + mpz_ptr w; + mpz_srcptr u; +#endif +{ + mp_ptr wp, up; + mp_size_t size; + + size = ABS (u->_mp_size); + + if (u != w) + { + if (w->_mp_alloc < size) + _mpz_realloc (w, size); + + wp = w->_mp_d; + up = u->_mp_d; + + MPN_COPY (wp, up, size); + } + + w->_mp_size = size; +} diff --git a/contrib/libgmp/mpz/add.c b/contrib/libgmp/mpz/add.c new file mode 100644 index 0000000..10dd970 --- /dev/null +++ b/contrib/libgmp/mpz/add.c @@ -0,0 +1,120 @@ +/* mpz_add -- Add two integers. + +Copyright (C) 1991, 1993, 1994, 1996 Free Software Foundation, Inc. + +This file is part of the GNU MP Library. + +The GNU MP Library is free software; you can redistribute it and/or modify +it under the terms of the GNU Library General Public License as published by +the Free Software Foundation; either version 2 of the License, or (at your +option) any later version. + +The GNU MP Library is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public +License for more details. + +You should have received a copy of the GNU Library General Public License +along with the GNU MP Library; see the file COPYING.LIB. If not, write to +the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, +MA 02111-1307, USA. */ + +#include "gmp.h" +#include "gmp-impl.h" + +#ifndef BERKELEY_MP +void +#if __STDC__ +mpz_add (mpz_ptr w, mpz_srcptr u, mpz_srcptr v) +#else +mpz_add (w, u, v) + mpz_ptr w; + mpz_srcptr u; + mpz_srcptr v; +#endif +#else /* BERKELEY_MP */ +void +#if __STDC__ +madd (mpz_srcptr u, mpz_srcptr v, mpz_ptr w) +#else +madd (u, v, w) + mpz_srcptr u; + mpz_srcptr v; + mpz_ptr w; +#endif +#endif /* BERKELEY_MP */ +{ + mp_srcptr up, vp; + mp_ptr wp; + mp_size_t usize, vsize, wsize; + mp_size_t abs_usize; + mp_size_t abs_vsize; + + usize = u->_mp_size; + vsize = v->_mp_size; + abs_usize = ABS (usize); + abs_vsize = ABS (vsize); + + if (abs_usize < abs_vsize) + { + /* Swap U and V. */ + {const __mpz_struct *t = u; u = v; v = t;} + {mp_size_t t = usize; usize = vsize; vsize = t;} + {mp_size_t t = abs_usize; abs_usize = abs_vsize; abs_vsize = t;} + } + + /* True: ABS_USIZE >= ABS_VSIZE. */ + + /* If not space for w (and possible carry), increase space. */ + wsize = abs_usize + 1; + if (w->_mp_alloc < wsize) + _mpz_realloc (w, wsize); + + /* These must be after realloc (u or v may be the same as w). */ + up = u->_mp_d; + vp = v->_mp_d; + wp = w->_mp_d; + + if ((usize ^ vsize) < 0) + { + /* U and V have different sign. Need to compare them to determine + which operand to subtract from which. */ + + /* This test is right since ABS_USIZE >= ABS_VSIZE. */ + if (abs_usize != abs_vsize) + { + mpn_sub (wp, up, abs_usize, vp, abs_vsize); + wsize = abs_usize; + MPN_NORMALIZE (wp, wsize); + if (usize < 0) + wsize = -wsize; + } + else if (mpn_cmp (up, vp, abs_usize) < 0) + { + mpn_sub_n (wp, vp, up, abs_usize); + wsize = abs_usize; + MPN_NORMALIZE (wp, wsize); + if (usize >= 0) + wsize = -wsize; + } + else + { + mpn_sub_n (wp, up, vp, abs_usize); + wsize = abs_usize; + MPN_NORMALIZE (wp, wsize); + if (usize < 0) + wsize = -wsize; + } + } + else + { + /* U and V have same sign. Add them. */ + mp_limb_t cy_limb = mpn_add (wp, up, abs_usize, vp, abs_vsize); + wp[abs_usize] = cy_limb; + wsize = abs_usize + cy_limb; + if (usize < 0) + wsize = -wsize; + } + + w->_mp_size = wsize; +} diff --git a/contrib/libgmp/mpz/add_ui.c b/contrib/libgmp/mpz/add_ui.c new file mode 100644 index 0000000..a1e4306 --- /dev/null +++ b/contrib/libgmp/mpz/add_ui.c @@ -0,0 +1,84 @@ +/* mpz_add_ui -- Add an mpz_t and an unsigned one-word integer. + +Copyright (C) 1991, 1993, 1994, 1996 Free Software Foundation, Inc. + +This file is part of the GNU MP Library. + +The GNU MP Library is free software; you can redistribute it and/or modify +it under the terms of the GNU Library General Public License as published by +the Free Software Foundation; either version 2 of the License, or (at your +option) any later version. + +The GNU MP Library is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public +License for more details. + +You should have received a copy of the GNU Library General Public License +along with the GNU MP Library; see the file COPYING.LIB. If not, write to +the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, +MA 02111-1307, USA. */ + +#include "gmp.h" +#include "gmp-impl.h" + +void +#if __STDC__ +mpz_add_ui (mpz_ptr w, mpz_srcptr u, unsigned long int v) +#else +mpz_add_ui (w, u, v) + mpz_ptr w; + mpz_srcptr u; + unsigned long int v; +#endif +{ + mp_srcptr up; + mp_ptr wp; + mp_size_t usize, wsize; + mp_size_t abs_usize; + + usize = u->_mp_size; + abs_usize = ABS (usize); + + /* If not space for W (and possible carry), increase space. */ + wsize = abs_usize + 1; + if (w->_mp_alloc < wsize) + _mpz_realloc (w, wsize); + + /* These must be after realloc (U may be the same as W). */ + up = u->_mp_d; + wp = w->_mp_d; + + if (abs_usize == 0) + { + wp[0] = v; + w->_mp_size = v != 0; + return; + } + + if (usize >= 0) + { + mp_limb_t cy; + cy = mpn_add_1 (wp, up, abs_usize, v); + wp[abs_usize] = cy; + wsize = abs_usize + cy; + } + else + { + /* The signs are different. Need exact comparison to determine + which operand to subtract from which. */ + if (abs_usize == 1 && up[0] < v) + { + wp[0] = v - up[0]; + wsize = 1; + } + else + { + mpn_sub_1 (wp, up, abs_usize, v); + /* Size can decrease with at most one limb. */ + wsize = -(abs_usize - (wp[abs_usize - 1] == 0)); + } + } + + w->_mp_size = wsize; +} diff --git a/contrib/libgmp/mpz/and.c b/contrib/libgmp/mpz/and.c new file mode 100644 index 0000000..838d4b1 --- /dev/null +++ b/contrib/libgmp/mpz/and.c @@ -0,0 +1,278 @@ +/* mpz_and -- Logical and. + +Copyright (C) 1991, 1993, 1994, 1996 Free Software Foundation, Inc. + +This file is part of the GNU MP Library. + +The GNU MP Library is free software; you can redistribute it and/or modify +it under the terms of the GNU Library General Public License as published by +the Free Software Foundation; either version 2 of the License, or (at your +option) any later version. + +The GNU MP Library is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public +License for more details. + +You should have received a copy of the GNU Library General Public License +along with the GNU MP Library; see the file COPYING.LIB. If not, write to +the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, +MA 02111-1307, USA. */ + +#include "gmp.h" +#include "gmp-impl.h" + +void +#if __STDC__ +mpz_and (mpz_ptr res, mpz_srcptr op1, mpz_srcptr op2) +#else +mpz_and (res, op1, op2) + mpz_ptr res; + mpz_srcptr op1; + mpz_srcptr op2; +#endif +{ + mp_srcptr op1_ptr, op2_ptr; + mp_size_t op1_size, op2_size; + mp_ptr res_ptr; + mp_size_t res_size; + mp_size_t i; + TMP_DECL (marker); + + TMP_MARK (marker); + op1_size = op1->_mp_size; + op2_size = op2->_mp_size; + + op1_ptr = op1->_mp_d; + op2_ptr = op2->_mp_d; + res_ptr = res->_mp_d; + + if (op1_size >= 0) + { + if (op2_size >= 0) + { + res_size = MIN (op1_size, op2_size); + /* First loop finds the size of the result. */ + for (i = res_size - 1; i >= 0; i--) + if ((op1_ptr[i] & op2_ptr[i]) != 0) + break; + res_size = i + 1; + + /* Handle allocation, now then we know exactly how much space is + needed for the result. */ + if (res->_mp_alloc < res_size) + { + _mpz_realloc (res, res_size); + op1_ptr = op1->_mp_d; + op2_ptr = op2->_mp_d; + res_ptr = res->_mp_d; + } + + /* Second loop computes the real result. */ + for (i = res_size - 1; i >= 0; i--) + res_ptr[i] = op1_ptr[i] & op2_ptr[i]; + + res->_mp_size = res_size; + return; + } + else /* op2_size < 0 */ + { + /* Fall through to the code at the end of the function. */ + } + } + else + { + if (op2_size < 0) + { + mp_ptr opx; + mp_limb_t cy; + mp_size_t res_alloc; + + /* Both operands are negative, so will be the result. + -((-OP1) & (-OP2)) = -(~(OP1 - 1) & ~(OP2 - 1)) = + = ~(~(OP1 - 1) & ~(OP2 - 1)) + 1 = + = ((OP1 - 1) | (OP2 - 1)) + 1 */ + + /* It might seem as we could end up with an (invalid) result with + a leading zero-limb here when one of the operands is of the + type 1,,0,,..,,.0. But some analysis shows that we surely + would get carry into the zero-limb in this situation... */ + + op1_size = -op1_size; + op2_size = -op2_size; + + res_alloc = 1 + MAX (op1_size, op2_size); + + opx = (mp_ptr) TMP_ALLOC (op1_size * BYTES_PER_MP_LIMB); + mpn_sub_1 (opx, op1_ptr, op1_size, (mp_limb_t) 1); + op1_ptr = opx; + + opx = (mp_ptr) TMP_ALLOC (op2_size * BYTES_PER_MP_LIMB); + mpn_sub_1 (opx, op2_ptr, op2_size, (mp_limb_t) 1); + op2_ptr = opx; + + if (res->_mp_alloc < res_alloc) + { + _mpz_realloc (res, res_alloc); + res_ptr = res->_mp_d; + /* Don't re-read OP1_PTR and OP2_PTR. They point to + temporary space--never to the space RES->_mp_D used + to point to before reallocation. */ + } + + if (op1_size >= op2_size) + { + MPN_COPY (res_ptr + op2_size, op1_ptr + op2_size, + op1_size - op2_size); + for (i = op2_size - 1; i >= 0; i--) + res_ptr[i] = op1_ptr[i] | op2_ptr[i]; + res_size = op1_size; + } + else + { + MPN_COPY (res_ptr + op1_size, op2_ptr + op1_size, + op2_size - op1_size); + for (i = op1_size - 1; i >= 0; i--) + res_ptr[i] = op1_ptr[i] | op2_ptr[i]; + res_size = op2_size; + } + + cy = mpn_add_1 (res_ptr, res_ptr, res_size, (mp_limb_t) 1); + if (cy) + { + res_ptr[res_size] = cy; + res_size++; + } + + res->_mp_size = -res_size; + TMP_FREE (marker); + return; + } + else + { + /* We should compute -OP1 & OP2. Swap OP1 and OP2 and fall + through to the code that handles OP1 & -OP2. */ + {mpz_srcptr t = op1; op1 = op2; op2 = t;} + {mp_srcptr t = op1_ptr; op1_ptr = op2_ptr; op2_ptr = t;} + {mp_size_t t = op1_size; op1_size = op2_size; op2_size = t;} + } + + } + + { +#if ANDNEW + mp_size_t op2_lim; + mp_size_t count; + + /* OP2 must be negated as with infinite precision. + + Scan from the low end for a non-zero limb. The first non-zero + limb is simply negated (two's complement). Any subsequent + limbs are one's complemented. Of course, we don't need to + handle more limbs than there are limbs in the other, positive + operand as the result for those limbs is going to become zero + anyway. */ + + /* Scan for the least significant. non-zero OP2 limb, and zero the + result meanwhile for those limb positions. (We will surely + find a non-zero limb, so we can write the loop with one + termination condition only.) */ + for (i = 0; op2_ptr[i] == 0; i++) + res_ptr[i] = 0; + op2_lim = i; + + op2_size = -op2_size; + + if (op1_size <= op2_size) + { + /* The ones-extended OP2 is >= than the zero-extended OP1. + RES_SIZE <= OP1_SIZE. Find the exact size. */ + for (i = op1_size - 1; i > op2_lim; i--) + if ((op1_ptr[i] & ~op2_ptr[i]) != 0) + break; + res_size = i + 1; + for (i = res_size - 1; i > op2_lim; i--) + res_ptr[i] = op1_ptr[i] & ~op2_ptr[i]; + res_ptr[op2_lim] = op1_ptr[op2_lim] & -op2_ptr[op2_lim]; + /* Yes, this *can* happen! */ + MPN_NORMALIZE (res_ptr, res_size); + } + else + { + /* The ones-extended OP2 is < than the zero-extended OP1. + RES_SIZE == OP1_SIZE, since OP1 is normalized. */ + res_size = op1_size; + MPN_COPY (res_ptr + op2_size, op1_ptr + op2_size, op1_size - op2_size); + for (i = op2_size - 1; i > op2_lim; i--) + res_ptr[i] = op1_ptr[i] & ~op2_ptr[i]; + res_ptr[op2_lim] = op1_ptr[op2_lim] & -op2_ptr[op2_lim]; + } + + res->_mp_size = res_size; +#else + + /* OP1 is positive and zero-extended, + OP2 is negative and ones-extended. + The result will be positive. + OP1 & -OP2 = OP1 & ~(OP2 - 1). */ + + mp_ptr opx; + + op2_size = -op2_size; + opx = (mp_ptr) TMP_ALLOC (op2_size * BYTES_PER_MP_LIMB); + mpn_sub_1 (opx, op2_ptr, op2_size, (mp_limb_t) 1); + op2_ptr = opx; + + if (op1_size > op2_size) + { + /* The result has the same size as OP1, since OP1 is normalized + and longer than the ones-extended OP2. */ + res_size = op1_size; + + /* Handle allocation, now then we know exactly how much space is + needed for the result. */ + if (res->_mp_alloc < res_size) + { + _mpz_realloc (res, res_size); + res_ptr = res->_mp_d; + op1_ptr = op1->_mp_d; + /* Don't re-read OP2_PTR. It points to temporary space--never + to the space RES->_mp_D used to point to before reallocation. */ + } + + MPN_COPY (res_ptr + op2_size, op1_ptr + op2_size, + res_size - op2_size); + for (i = op2_size - 1; i >= 0; i--) + res_ptr[i] = op1_ptr[i] & ~op2_ptr[i]; + + res->_mp_size = res_size; + } + else + { + /* Find out the exact result size. Ignore the high limbs of OP2, + OP1 is zero-extended and would make the result zero. */ + for (i = op1_size - 1; i >= 0; i--) + if ((op1_ptr[i] & ~op2_ptr[i]) != 0) + break; + res_size = i + 1; + + /* Handle allocation, now then we know exactly how much space is + needed for the result. */ + if (res->_mp_alloc < res_size) + { + _mpz_realloc (res, res_size); + res_ptr = res->_mp_d; + op1_ptr = op1->_mp_d; + /* Don't re-read OP2_PTR. It points to temporary space--never + to the space RES->_mp_D used to point to before reallocation. */ + } + + for (i = res_size - 1; i >= 0; i--) + res_ptr[i] = op1_ptr[i] & ~op2_ptr[i]; + + res->_mp_size = res_size; + } +#endif + } + TMP_FREE (marker); +} diff --git a/contrib/libgmp/mpz/array_init.c b/contrib/libgmp/mpz/array_init.c new file mode 100644 index 0000000..8b2e85c --- /dev/null +++ b/contrib/libgmp/mpz/array_init.c @@ -0,0 +1,48 @@ +/* mpz_array_init (array, array_size, size_per_elem) -- + +Copyright (C) 1991, 1993, 1994, 1995 Free Software Foundation, Inc. + +This file is part of the GNU MP Library. + +The GNU MP Library is free software; you can redistribute it and/or modify +it under the terms of the GNU Library General Public License as published by +the Free Software Foundation; either version 2 of the License, or (at your +option) any later version. + +The GNU MP Library is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public +License for more details. + +You should have received a copy of the GNU Library General Public License +along with the GNU MP Library; see the file COPYING.LIB. If not, write to +the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, +MA 02111-1307, USA. */ + +#include "gmp.h" +#include "gmp-impl.h" + +void +#if __STDC__ +mpz_array_init (mpz_ptr arr, mp_size_t arr_size, mp_size_t nbits) +#else +mpz_array_init (arr, arr_size, nbits) + mpz_ptr arr; + mp_size_t arr_size; + mp_size_t nbits; +#endif +{ + register mp_ptr p; + register size_t i; + mp_size_t nlimbs; + + nlimbs = (nbits + BITS_PER_MP_LIMB - 1) / BITS_PER_MP_LIMB; + p = (mp_ptr) (*_mp_allocate_func) (arr_size * nlimbs * BYTES_PER_MP_LIMB); + + for (i = 0; i < arr_size; i++) + { + arr[i]._mp_alloc = nlimbs + 1; /* Yes, lie a little... */ + arr[i]._mp_size = 0; + arr[i]._mp_d = p + i * nlimbs; + } +} diff --git a/contrib/libgmp/mpz/cdiv_q.c b/contrib/libgmp/mpz/cdiv_q.c new file mode 100644 index 0000000..860a232 --- /dev/null +++ b/contrib/libgmp/mpz/cdiv_q.c @@ -0,0 +1,51 @@ +/* mpz_cdiv_q -- Division rounding the quotient towards +infinity. The + remainder gets the opposite sign as the denominator. + +Copyright (C) 1994, 1995, 1996 Free Software Foundation, Inc. + +This file is part of the GNU MP Library. + +The GNU MP Library is free software; you can redistribute it and/or modify +it under the terms of the GNU Library General Public License as published by +the Free Software Foundation; either version 2 of the License, or (at your +option) any later version. + +The GNU MP Library is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public +License for more details. + +You should have received a copy of the GNU Library General Public License +along with the GNU MP Library; see the file COPYING.LIB. If not, write to +the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, +MA 02111-1307, USA. */ + +#include "gmp.h" +#include "gmp-impl.h" + +void +#if __STDC__ +mpz_cdiv_q (mpz_ptr quot, mpz_srcptr dividend, mpz_srcptr divisor) +#else +mpz_cdiv_q (quot, dividend, divisor) + mpz_ptr quot; + mpz_srcptr dividend; + mpz_srcptr divisor; +#endif +{ + mp_size_t dividend_size = dividend->_mp_size; + mp_size_t divisor_size = divisor->_mp_size; + mpz_t rem; + TMP_DECL (marker); + + TMP_MARK (marker); + + MPZ_TMP_INIT (rem, 1 + ABS (dividend_size)); + + mpz_tdiv_qr (quot, rem, dividend, divisor); + + if ((divisor_size ^ dividend_size) >= 0 && rem->_mp_size != 0) + mpz_add_ui (quot, quot, 1L); + + TMP_FREE (marker); +} diff --git a/contrib/libgmp/mpz/cdiv_q_ui.c b/contrib/libgmp/mpz/cdiv_q_ui.c new file mode 100644 index 0000000..7b6cfd7 --- /dev/null +++ b/contrib/libgmp/mpz/cdiv_q_ui.c @@ -0,0 +1,64 @@ +/* mpz_cdiv_q_ui -- Division rounding the quotient towards +infinity. The + remainder gets the opposite sign as the denominator. In order to make it + always fit into the return type, the negative of the true remainder is + returned. + +Copyright (C) 1994, 1996 Free Software Foundation, Inc. + +This file is part of the GNU MP Library. + +The GNU MP Library is free software; you can redistribute it and/or modify +it under the terms of the GNU Library General Public License as published by +the Free Software Foundation; either version 2 of the License, or (at your +option) any later version. + +The GNU MP Library is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public +License for more details. + +You should have received a copy of the GNU Library General Public License +along with the GNU MP Library; see the file COPYING.LIB. If not, write to +the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, +MA 02111-1307, USA. */ + +#include "gmp.h" +#include "gmp-impl.h" + +unsigned long int +#if __STDC__ +mpz_cdiv_q_ui (mpz_ptr quot, mpz_srcptr dividend, unsigned long int divisor) +#else +mpz_cdiv_q_ui (quot, dividend, divisor) + mpz_ptr quot; + mpz_srcptr dividend; + unsigned long int divisor; +#endif +{ + mp_size_t dividend_size; + mp_size_t size; + mp_ptr quot_ptr; + mp_limb_t remainder_limb; + + dividend_size = dividend->_mp_size; + size = ABS (dividend_size); + + if (quot->_mp_alloc < size) + _mpz_realloc (quot, size); + + quot_ptr = quot->_mp_d; + + remainder_limb = mpn_divmod_1 (quot_ptr, dividend->_mp_d, size, + (mp_limb_t) divisor); + + if (remainder_limb != 0 && dividend_size >= 0) + { + mpn_add_1 (quot_ptr, quot_ptr, size, (mp_limb_t) 1); + remainder_limb = divisor - remainder_limb; + } + + size -= size != 0 && quot_ptr[size - 1] == 0; + quot->_mp_size = dividend_size >= 0 ? size : -size; + + return remainder_limb; +} diff --git a/contrib/libgmp/mpz/cdiv_qr.c b/contrib/libgmp/mpz/cdiv_qr.c new file mode 100644 index 0000000..bf7d6da --- /dev/null +++ b/contrib/libgmp/mpz/cdiv_qr.c @@ -0,0 +1,62 @@ +/* mpz_cdiv_qr -- Division rounding the quotient towards +infinity. The + remainder gets the opposite sign as the denominator. + +Copyright (C) 1994, 1995, 1996 Free Software Foundation, Inc. + +This file is part of the GNU MP Library. + +The GNU MP Library is free software; you can redistribute it and/or modify +it under the terms of the GNU Library General Public License as published by +the Free Software Foundation; either version 2 of the License, or (at your +option) any later version. + +The GNU MP Library is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public +License for more details. + +You should have received a copy of the GNU Library General Public License +along with the GNU MP Library; see the file COPYING.LIB. If not, write to +the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, +MA 02111-1307, USA. */ + +#include "gmp.h" +#include "gmp-impl.h" + +void +#if __STDC__ +mpz_cdiv_qr (mpz_ptr quot, mpz_ptr rem, mpz_srcptr dividend, mpz_srcptr divisor) +#else +mpz_cdiv_qr (quot, rem, dividend, divisor) + mpz_ptr quot; + mpz_ptr rem; + mpz_srcptr dividend; + mpz_srcptr divisor; +#endif +{ + mp_size_t divisor_size = divisor->_mp_size; + mpz_t temp_divisor; /* N.B.: lives until function returns! */ + TMP_DECL (marker); + + TMP_MARK (marker); + + /* We need the original value of the divisor after the quotient and + remainder have been preliminary calculated. We have to copy it to + temporary space if it's the same variable as either QUOT or REM. */ + if (quot == divisor || rem == divisor) + { + MPZ_TMP_INIT (temp_divisor, ABS (divisor_size)); + mpz_set (temp_divisor, divisor); + divisor = temp_divisor; + } + + mpz_tdiv_qr (quot, rem, dividend, divisor); + + if ((divisor_size ^ dividend->_mp_size) >= 0 && rem->_mp_size != 0) + { + mpz_add_ui (quot, quot, 1L); + mpz_sub (rem, rem, divisor); + } + + TMP_FREE (marker); +} diff --git a/contrib/libgmp/mpz/cdiv_qr_ui.c b/contrib/libgmp/mpz/cdiv_qr_ui.c new file mode 100644 index 0000000..a780e77 --- /dev/null +++ b/contrib/libgmp/mpz/cdiv_qr_ui.c @@ -0,0 +1,68 @@ +/* mpz_cdiv_qr_ui -- Division rounding the quotient towards +infinity. The + remainder gets the opposite sign as the denominator. In order to make it + always fit into the return type, the negative of the true remainder is + returned. + +Copyright (C) 1994, 1995, 1996 Free Software Foundation, Inc. + +This file is part of the GNU MP Library. + +The GNU MP Library is free software; you can redistribute it and/or modify +it under the terms of the GNU Library General Public License as published by +the Free Software Foundation; either version 2 of the License, or (at your +option) any later version. + +The GNU MP Library is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public +License for more details. + +You should have received a copy of the GNU Library General Public License +along with the GNU MP Library; see the file COPYING.LIB. If not, write to +the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, +MA 02111-1307, USA. */ + +#include "gmp.h" +#include "gmp-impl.h" + +unsigned long int +#if __STDC__ +mpz_cdiv_qr_ui (mpz_ptr quot, mpz_ptr rem, mpz_srcptr dividend, unsigned long int divisor) +#else +mpz_cdiv_qr_ui (quot, rem, dividend, divisor) + mpz_ptr quot; + mpz_ptr rem; + mpz_srcptr dividend; + unsigned long int divisor; +#endif +{ + mp_size_t dividend_size; + mp_size_t size; + mp_ptr quot_ptr; + mp_limb_t remainder_limb; + + dividend_size = dividend->_mp_size; + size = ABS (dividend_size); + + if (quot->_mp_alloc < size) + _mpz_realloc (quot, size); + + quot_ptr = quot->_mp_d; + + remainder_limb = mpn_divmod_1 (quot_ptr, dividend->_mp_d, size, + (mp_limb_t) divisor); + + if (remainder_limb != 0 && dividend_size >= 0) + { + mpn_add_1 (quot_ptr, quot_ptr, size, (mp_limb_t) 1); + remainder_limb = divisor - remainder_limb; + } + + size -= size != 0 && quot_ptr[size - 1] == 0; + quot->_mp_size = dividend_size >= 0 ? size : -size; + + rem->_mp_d[0] = remainder_limb; + rem->_mp_size = -(remainder_limb != 0); + + return remainder_limb; +} diff --git a/contrib/libgmp/mpz/cdiv_r.c b/contrib/libgmp/mpz/cdiv_r.c new file mode 100644 index 0000000..d34d138 --- /dev/null +++ b/contrib/libgmp/mpz/cdiv_r.c @@ -0,0 +1,59 @@ +/* mpz_cdiv_r -- Division rounding the quotient towards +infinity. The + remainder gets the opposite sign as the denominator. + +Copyright (C) 1994, 1995, 1996 Free Software Foundation, Inc. + +This file is part of the GNU MP Library. + +The GNU MP Library is free software; you can redistribute it and/or modify +it under the terms of the GNU Library General Public License as published by +the Free Software Foundation; either version 2 of the License, or (at your +option) any later version. + +The GNU MP Library is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public +License for more details. + +You should have received a copy of the GNU Library General Public License +along with the GNU MP Library; see the file COPYING.LIB. If not, write to +the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, +MA 02111-1307, USA. */ + +#include "gmp.h" +#include "gmp-impl.h" + +void +#if __STDC__ +mpz_cdiv_r (mpz_ptr rem, mpz_srcptr dividend, mpz_srcptr divisor) +#else +mpz_cdiv_r (rem, dividend, divisor) + mpz_ptr rem; + mpz_srcptr dividend; + mpz_srcptr divisor; +#endif +{ + mp_size_t divisor_size = divisor->_mp_size; + mpz_t temp_divisor; /* N.B.: lives until function returns! */ + TMP_DECL (marker); + + TMP_MARK (marker); + + /* We need the original value of the divisor after the remainder has been + preliminary calculated. We have to copy it to temporary space if it's + the same variable as REM. */ + if (rem == divisor) + { + + MPZ_TMP_INIT (temp_divisor, ABS (divisor_size)); + mpz_set (temp_divisor, divisor); + divisor = temp_divisor; + } + + mpz_tdiv_r (rem, dividend, divisor); + + if ((divisor_size ^ dividend->_mp_size) >= 0 && rem->_mp_size != 0) + mpz_sub (rem, rem, divisor); + + TMP_FREE (marker); +} diff --git a/contrib/libgmp/mpz/cdiv_r_ui.c b/contrib/libgmp/mpz/cdiv_r_ui.c new file mode 100644 index 0000000..757a3f5 --- /dev/null +++ b/contrib/libgmp/mpz/cdiv_r_ui.c @@ -0,0 +1,54 @@ +/* mpz_cdiv_r_ui -- Division rounding the quotient towards +infinity. The + remainder gets the opposite sign as the denominator. In order to make it + always fit into the return type, the negative of the true remainder is + returned. + +Copyright (C) 1994, 1995, 1996 Free Software Foundation, Inc. + +This file is part of the GNU MP Library. + +The GNU MP Library is free software; you can redistribute it and/or modify +it under the terms of the GNU Library General Public License as published by +the Free Software Foundation; either version 2 of the License, or (at your +option) any later version. + +The GNU MP Library is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public +License for more details. + +You should have received a copy of the GNU Library General Public License +along with the GNU MP Library; see the file COPYING.LIB. If not, write to +the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, +MA 02111-1307, USA. */ + +#include "gmp.h" +#include "gmp-impl.h" + +unsigned long int +#if __STDC__ +mpz_cdiv_r_ui (mpz_ptr rem, mpz_srcptr dividend, unsigned long int divisor) +#else +mpz_cdiv_r_ui (rem, dividend, divisor) + mpz_ptr rem; + mpz_srcptr dividend; + unsigned long int divisor; +#endif +{ + mp_size_t dividend_size; + mp_size_t size; + mp_limb_t remainder_limb; + + dividend_size = dividend->_mp_size; + size = ABS (dividend_size); + + remainder_limb = mpn_mod_1 (dividend->_mp_d, size, (mp_limb_t) divisor); + + if (remainder_limb != 0 && dividend_size >= 0) + remainder_limb = divisor - remainder_limb; + + rem->_mp_d[0] = remainder_limb; + rem->_mp_size = -(remainder_limb != 0); + + return remainder_limb; +} diff --git a/contrib/libgmp/mpz/cdiv_ui.c b/contrib/libgmp/mpz/cdiv_ui.c new file mode 100644 index 0000000..df841ed --- /dev/null +++ b/contrib/libgmp/mpz/cdiv_ui.c @@ -0,0 +1,50 @@ +/* mpz_cdiv_ui -- Division rounding the quotient towards +infinity. The + remainder gets the opposite sign as the denominator. In order to make it + always fit into the return type, the negative of the true remainder is + returned. + +Copyright (C) 1994, 1995, 1996 Free Software Foundation, Inc. + +This file is part of the GNU MP Library. + +The GNU MP Library is free software; you can redistribute it and/or modify +it under the terms of the GNU Library General Public License as published by +the Free Software Foundation; either version 2 of the License, or (at your +option) any later version. + +The GNU MP Library is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public +License for more details. + +You should have received a copy of the GNU Library General Public License +along with the GNU MP Library; see the file COPYING.LIB. If not, write to +the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, +MA 02111-1307, USA. */ + +#include "gmp.h" +#include "gmp-impl.h" + +unsigned long int +#if __STDC__ +mpz_cdiv_ui (mpz_srcptr dividend, unsigned long int divisor) +#else +mpz_cdiv_ui (dividend, divisor) + mpz_srcptr dividend; + unsigned long int divisor; +#endif +{ + mp_size_t dividend_size; + mp_size_t size; + mp_limb_t remainder_limb; + + dividend_size = dividend->_mp_size; + size = ABS (dividend_size); + + remainder_limb = mpn_mod_1 (dividend->_mp_d, size, (mp_limb_t) divisor); + + if (remainder_limb != 0 && dividend_size >= 0) + remainder_limb = divisor - remainder_limb; + + return remainder_limb; +} diff --git a/contrib/libgmp/mpz/clear.c b/contrib/libgmp/mpz/clear.c new file mode 100644 index 0000000..00f3cfd --- /dev/null +++ b/contrib/libgmp/mpz/clear.c @@ -0,0 +1,35 @@ +/* mpz_clear -- de-allocate the space occupied by the dynamic digit space of + an integer. + +Copyright (C) 1991, 1993, 1994, 1995 Free Software Foundation, Inc. + +This file is part of the GNU MP Library. + +The GNU MP Library is free software; you can redistribute it and/or modify +it under the terms of the GNU Library General Public License as published by +the Free Software Foundation; either version 2 of the License, or (at your +option) any later version. + +The GNU MP Library is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public +License for more details. + +You should have received a copy of the GNU Library General Public License +along with the GNU MP Library; see the file COPYING.LIB. If not, write to +the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, +MA 02111-1307, USA. */ + +#include "gmp.h" +#include "gmp-impl.h" + +void +#if __STDC__ +mpz_clear (mpz_ptr m) +#else +mpz_clear (m) + mpz_ptr m; +#endif +{ + (*_mp_free_func) (m->_mp_d, m->_mp_alloc * BYTES_PER_MP_LIMB); +} diff --git a/contrib/libgmp/mpz/clrbit.c b/contrib/libgmp/mpz/clrbit.c new file mode 100644 index 0000000..59d9565 --- /dev/null +++ b/contrib/libgmp/mpz/clrbit.c @@ -0,0 +1,114 @@ +/* mpz_clrbit -- clear a specified bit. + +Copyright (C) 1991, 1993, 1994, 1995 Free Software Foundation, Inc. + +This file is part of the GNU MP Library. + +The GNU MP Library is free software; you can redistribute it and/or modify +it under the terms of the GNU Library General Public License as published by +the Free Software Foundation; either version 2 of the License, or (at your +option) any later version. + +The GNU MP Library is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public +License for more details. + +You should have received a copy of the GNU Library General Public License +along with the GNU MP Library; see the file COPYING.LIB. If not, write to +the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, +MA 02111-1307, USA. */ + +#include "gmp.h" +#include "gmp-impl.h" + +void +#if __STDC__ +mpz_clrbit (mpz_ptr d, unsigned long int bit_index) +#else +mpz_clrbit (d, bit_index) + mpz_ptr d; + unsigned long int bit_index; +#endif +{ + mp_size_t dsize = d->_mp_size; + mp_ptr dp = d->_mp_d; + mp_size_t limb_index; + + limb_index = bit_index / BITS_PER_MP_LIMB; + if (dsize >= 0) + { + if (limb_index < dsize) + { + dp[limb_index] &= ~((mp_limb_t) 1 << (bit_index % BITS_PER_MP_LIMB)); + MPN_NORMALIZE (dp, dsize); + d->_mp_size = dsize; + } + else + ; + } + else + { + mp_size_t zero_bound; + + /* Simulate two's complement arithmetic, i.e. simulate + 1. Set OP = ~(OP - 1) [with infinitely many leading ones]. + 2. clear the bit. + 3. Set OP = ~OP + 1. */ + + dsize = -dsize; + + /* No upper bound on this loop, we're sure there's a non-zero limb + sooner ot later. */ + for (zero_bound = 0; ; zero_bound++) + if (dp[zero_bound] != 0) + break; + + if (limb_index > zero_bound) + { + if (limb_index < dsize) + dp[limb_index] |= (mp_limb_t) 1 << (bit_index % BITS_PER_MP_LIMB); + else + { + /* Ugh. The bit should be cleared outside of the end of the + number. We have to increase the size of the number. */ + if (d->_mp_alloc < limb_index + 1) + { + _mpz_realloc (d, limb_index + 1); + dp = d->_mp_d; + } + MPN_ZERO (dp + dsize, limb_index - dsize); + dp[limb_index] = (mp_limb_t) 1 << (bit_index % BITS_PER_MP_LIMB); + d->_mp_size = -(limb_index + 1); + } + } + else if (limb_index == zero_bound) + { + dp[limb_index] = ((dp[limb_index] - 1) + | ((mp_limb_t) 1 << (bit_index % BITS_PER_MP_LIMB))) + 1; + if (dp[limb_index] == 0) + { + mp_size_t i; + for (i = limb_index + 1; i < dsize; i++) + { + dp[i] += 1; + if (dp[i] != 0) + goto fin; + } + /* We got carry all way out beyond the end of D. Increase + its size (and allocation if necessary). */ + dsize++; + if (d->_mp_alloc < dsize) + { + _mpz_realloc (d, dsize); + dp = d->_mp_d; + } + dp[i] = 1; + d->_mp_size = -dsize; + fin:; + } + } + else + ; + } +} diff --git a/contrib/libgmp/mpz/cmp.c b/contrib/libgmp/mpz/cmp.c new file mode 100644 index 0000000..37be334 --- /dev/null +++ b/contrib/libgmp/mpz/cmp.c @@ -0,0 +1,75 @@ +/* mpz_cmp(u,v) -- Compare U, V. Return postive, zero, or negative + based on if U > V, U == V, or U < V. + +Copyright (C) 1991, 1993, 1994, 1996 Free Software Foundation, Inc. + +This file is part of the GNU MP Library. + +The GNU MP Library is free software; you can redistribute it and/or modify +it under the terms of the GNU Library General Public License as published by +the Free Software Foundation; either version 2 of the License, or (at your +option) any later version. + +The GNU MP Library is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public +License for more details. + +You should have received a copy of the GNU Library General Public License +along with the GNU MP Library; see the file COPYING.LIB. If not, write to +the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, +MA 02111-1307, USA. */ + +#ifdef BERKELEY_MP +#include "mp.h" +#endif +#include "gmp.h" +#include "gmp-impl.h" + +#ifndef BERKELEY_MP +int +#if __STDC__ +mpz_cmp (mpz_srcptr u, mpz_srcptr v) +#else +mpz_cmp (u, v) + mpz_srcptr u; + mpz_srcptr v; +#endif +#else /* BERKELEY_MP */ +int +#if __STDC__ +mcmp (mpz_srcptr u, mpz_srcptr v) +#else +mcmp (u, v) + mpz_srcptr u; + mpz_srcptr v; +#endif +#endif /* BERKELEY_MP */ +{ + mp_size_t usize = u->_mp_size; + mp_size_t vsize = v->_mp_size; + mp_size_t size; + mp_srcptr up, vp; + int cmp; + + if (usize != vsize) + return usize - vsize; + + if (usize == 0) + return 0; + + size = ABS (usize); + + up = u->_mp_d; + vp = v->_mp_d; + + cmp = mpn_cmp (up, vp, size); + + if (cmp == 0) + return 0; + + if ((cmp < 0) == (usize < 0)) + return 1; + else + return -1; +} diff --git a/contrib/libgmp/mpz/cmp_si.c b/contrib/libgmp/mpz/cmp_si.c new file mode 100644 index 0000000..8063fd3 --- /dev/null +++ b/contrib/libgmp/mpz/cmp_si.c @@ -0,0 +1,66 @@ +/* mpz_cmp_si(u,v) -- Compare an integer U with a single-word int V. + Return positive, zero, or negative based on if U > V, U == V, or U < V. + +Copyright (C) 1991, 1993, 1994, 1995 Free Software Foundation, Inc. + +This file is part of the GNU MP Library. + +The GNU MP Library is free software; you can redistribute it and/or modify +it under the terms of the GNU Library General Public License as published by +the Free Software Foundation; either version 2 of the License, or (at your +option) any later version. + +The GNU MP Library is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public +License for more details. + +You should have received a copy of the GNU Library General Public License +along with the GNU MP Library; see the file COPYING.LIB. If not, write to +the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, +MA 02111-1307, USA. */ + +#include "gmp.h" +#include "gmp-impl.h" + +/* gmp.h defines a macro for mpz_cmp_si. */ +#undef mpz_cmp_si + +int +#if __STDC__ +mpz_cmp_si (mpz_srcptr u, signed long int v_digit) +#else +mpz_cmp_si (u, v_digit) + mpz_srcptr u; + signed long int v_digit; +#endif +{ + mp_size_t usize = u->_mp_size; + mp_size_t vsize; + mp_limb_t u_digit; + + vsize = 0; + if (v_digit > 0) + vsize = 1; + else if (v_digit < 0) + { + vsize = -1; + v_digit = -v_digit; + } + + if (usize != vsize) + return usize - vsize; + + if (usize == 0) + return 0; + + u_digit = u->_mp_d[0]; + + if (u_digit == v_digit) + return 0; + + if (u_digit > v_digit) + return usize; + else + return -usize; +} diff --git a/contrib/libgmp/mpz/cmp_ui.c b/contrib/libgmp/mpz/cmp_ui.c new file mode 100644 index 0000000..1a50b96 --- /dev/null +++ b/contrib/libgmp/mpz/cmp_ui.c @@ -0,0 +1,56 @@ +/* mpz_cmp_ui.c -- Compare a mpz_t a with an mp_limb_t b. Return positive, + zero, or negative based on if a > b, a == b, or a < b. + +Copyright (C) 1991, 1993, 1994, 1995 Free Software Foundation, Inc. + +This file is part of the GNU MP Library. + +The GNU MP Library is free software; you can redistribute it and/or modify +it under the terms of the GNU Library General Public License as published by +the Free Software Foundation; either version 2 of the License, or (at your +option) any later version. + +The GNU MP Library is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public +License for more details. + +You should have received a copy of the GNU Library General Public License +along with the GNU MP Library; see the file COPYING.LIB. If not, write to +the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, +MA 02111-1307, USA. */ + +#include "gmp.h" +#include "gmp-impl.h" + +/* gmp.h defines a macro for mpz_cmp_ui. */ +#undef mpz_cmp_ui + +int +#if __STDC__ +mpz_cmp_ui (mpz_srcptr u, unsigned long int v_digit) +#else +mpz_cmp_ui (u, v_digit) + mpz_srcptr u; + unsigned long int v_digit; +#endif +{ + mp_size_t usize = u->_mp_size; + + if (usize == 0) + return -(v_digit != 0); + + if (usize == 1) + { + mp_limb_t u_digit; + + u_digit = u->_mp_d[0]; + if (u_digit > v_digit) + return 1; + if (u_digit < v_digit) + return -1; + return 0; + } + + return (usize > 0) ? 1 : -1; +} diff --git a/contrib/libgmp/mpz/com.c b/contrib/libgmp/mpz/com.c new file mode 100644 index 0000000..559f2b6 --- /dev/null +++ b/contrib/libgmp/mpz/com.c @@ -0,0 +1,93 @@ +/* mpz_com(mpz_ptr dst, mpz_ptr src) -- Assign the bit-complemented value of + SRC to DST. + +Copyright (C) 1991, 1993, 1994, 1996 Free Software Foundation, Inc. + +This file is part of the GNU MP Library. + +The GNU MP Library is free software; you can redistribute it and/or modify +it under the terms of the GNU Library General Public License as published by +the Free Software Foundation; either version 2 of the License, or (at your +option) any later version. + +The GNU MP Library is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public +License for more details. + +You should have received a copy of the GNU Library General Public License +along with the GNU MP Library; see the file COPYING.LIB. If not, write to +the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, +MA 02111-1307, USA. */ + +#include "gmp.h" +#include "gmp-impl.h" + +void +#if __STDC__ +mpz_com (mpz_ptr dst, mpz_srcptr src) +#else +mpz_com (dst, src) + mpz_ptr dst; + mpz_srcptr src; +#endif +{ + mp_size_t size = src->_mp_size; + mp_srcptr src_ptr; + mp_ptr dst_ptr; + + if (size >= 0) + { + /* As with infinite precision: one's complement, two's complement. + But this can be simplified using the identity -x = ~x + 1. + So we're going to compute (~~x) + 1 = x + 1! */ + + if (dst->_mp_alloc < size + 1) + _mpz_realloc (dst, size + 1); + + src_ptr = src->_mp_d; + dst_ptr = dst->_mp_d; + + if (size == 0) + { + /* Special case, as mpn_add wants the first arg's size >= the + second arg's size. */ + dst_ptr[0] = 1; + dst->_mp_size = -1; + return; + } + + { + mp_limb_t cy; + + cy = mpn_add_1 (dst_ptr, src_ptr, size, (mp_limb_t) 1); + if (cy) + { + dst_ptr[size] = cy; + size++; + } + } + + /* Store a negative size, to indicate ones-extension. */ + dst->_mp_size = -size; + } + else + { + /* As with infinite precision: two's complement, then one's complement. + But that can be simplified using the identity -x = ~(x - 1). + So we're going to compute ~~(x - 1) = x - 1! */ + size = -size; + + if (dst->_mp_alloc < size) + _mpz_realloc (dst, size); + + src_ptr = src->_mp_d; + dst_ptr = dst->_mp_d; + + mpn_sub_1 (dst_ptr, src_ptr, size, (mp_limb_t) 1); + size -= dst_ptr[size - 1] == 0; + + /* Store a positive size, to indicate zero-extension. */ + dst->_mp_size = size; + } +} diff --git a/contrib/libgmp/mpz/configure.in b/contrib/libgmp/mpz/configure.in new file mode 100644 index 0000000..ed84461 --- /dev/null +++ b/contrib/libgmp/mpz/configure.in @@ -0,0 +1,12 @@ +# This file is a shell script fragment that supplies the information +# necessary for a configure script to process the program in +# this directory. For more information, look at ../configure. + +configdirs=tests +srctrigger=add_ui.c +srcname="GNU Multi-Precision library/mpz" + +# per-host: + +# per-target: + diff --git a/contrib/libgmp/mpz/divexact.c b/contrib/libgmp/mpz/divexact.c new file mode 100644 index 0000000..b897448 --- /dev/null +++ b/contrib/libgmp/mpz/divexact.c @@ -0,0 +1,112 @@ +/* mpz_divexact -- finds quotient when known that quot * den == num && den != 0. + +Copyright (C) 1991, 1993, 1994, 1995 Free Software Foundation, Inc. + +This file is part of the GNU MP Library. + +The GNU MP Library is free software; you can redistribute it and/or modify +it under the terms of the GNU Library General Public License as published by +the Free Software Foundation; either version 2 of the License, or (at your +option) any later version. + +The GNU MP Library is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public +License for more details. + +You should have received a copy of the GNU Library General Public License +along with the GNU MP Library; see the file COPYING.LIB. If not, write to +the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, +MA 02111-1307, USA. */ + +/* Ken Weber (kweber@mat.ufrgs.br, kweber@mcs.kent.edu) + + Funding for this work has been partially provided by Conselho Nacional + de Desenvolvimento Cienti'fico e Tecnolo'gico (CNPq) do Brazil, Grant + 301314194-2, and was done while I was a visiting reseacher in the Instituto + de Matema'tica at Universidade Federal do Rio Grande do Sul (UFRGS). + + References: + T. Jebelean, An algorithm for exact division, Journal of Symbolic + Computation, v. 15, 1993, pp. 169-180. */ + +#include "gmp.h" +#include "gmp-impl.h" +#include "longlong.h" + +void +#if __STDC__ +mpz_divexact (mpz_ptr quot, mpz_srcptr num, mpz_srcptr den) +#else +mpz_divexact (quot, num, den) + mpz_ptr quot; + mpz_srcptr num; + mpz_srcptr den; +#endif +{ + mp_ptr qp, tp; + mp_size_t qsize, tsize; + + mp_srcptr np = num->_mp_d; + mp_srcptr dp = den->_mp_d; + mp_size_t nsize = ABS (num->_mp_size); + mp_size_t dsize = ABS (den->_mp_size); + TMP_DECL (marker); + + /* Generate divide-by-zero error if dsize == 0. */ + if (dsize == 0) + { + quot->_mp_size = 1 / dsize; + return; + } + + if (nsize == 0) + { + quot->_mp_size = 0; + return; + } + + qsize = nsize - dsize + 1; + if (quot->_mp_alloc < qsize) + _mpz_realloc (quot, qsize); + qp = quot->_mp_d; + + TMP_MARK (marker); + + /* QUOT <-- NUM/2^r, T <-- DEN/2^r where = r number of twos in DEN. */ + while (dp[0] == 0) + np += 1, nsize -= 1, dp += 1, dsize -= 1; + tsize = MIN (qsize, dsize); + if (dp[0] & 1) + { + if (qp != dp) + MPN_COPY (qp, np, qsize); + if (qp == dp) /* QUOT and DEN overlap. */ + { + tp = (mp_ptr) TMP_ALLOC (sizeof (mp_limb_t) * tsize); + MPN_COPY (tp, dp, tsize); + } + else + tp = (mp_ptr) dp; + } + else + { + unsigned long int r; + tp = (mp_ptr) TMP_ALLOC (sizeof (mp_limb_t) * tsize); + count_trailing_zeros (r, dp[0]); + mpn_rshift (tp, dp, tsize, r); + if (dsize > tsize) + tp[tsize-1] |= dp[tsize] << (BITS_PER_MP_LIMB - r); + mpn_rshift (qp, np, qsize, r); + if (nsize > qsize) + qp[qsize-1] |= np[qsize] << (BITS_PER_MP_LIMB - r); + } + + /* Now QUOT <-- QUOT/T. */ + mpn_bdivmod (qp, qp, qsize, tp, tsize, qsize * BITS_PER_MP_LIMB); + MPN_NORMALIZE (qp, qsize); + + quot->_mp_size = (num->_mp_size < 0) == (den->_mp_size < 0) ? qsize : -qsize; + + TMP_FREE (marker); +} diff --git a/contrib/libgmp/mpz/dmincl.c b/contrib/libgmp/mpz/dmincl.c new file mode 100644 index 0000000..51bd084 --- /dev/null +++ b/contrib/libgmp/mpz/dmincl.c @@ -0,0 +1,201 @@ +/* dmincl.c -- include file for tdiv_qr.c, tdiv_r.c. + +Copyright (C) 1991, 1993, 1994, 1996 Free Software Foundation, Inc. + +This file is part of the GNU MP Library. + +The GNU MP Library is free software; you can redistribute it and/or modify +it under the terms of the GNU Library General Public License as published by +the Free Software Foundation; either version 2 of the License, or (at your +option) any later version. + +The GNU MP Library is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public +License for more details. + +You should have received a copy of the GNU Library General Public License +along with the GNU MP Library; see the file COPYING.LIB. If not, write to +the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, +MA 02111-1307, USA. */ + +/* If den == quot, den needs temporary storage. + If den == rem, den needs temporary storage. + If num == quot, num needs temporary storage. + If den has temporary storage, it can be normalized while being copied, + i.e no extra storage should be allocated. */ + +/* This is the function body of mdiv, mpz_divmod, and mpz_mod. + + If COMPUTE_QUOTIENT is defined, the quotient is put in the MP_INT + object quot, otherwise that variable is not referenced at all. + + The remainder is always computed, and the result is put in the MP_INT + object rem. */ + +{ + mp_ptr np, dp; + mp_ptr qp, rp; + mp_size_t nsize = num->_mp_size; + mp_size_t dsize = den->_mp_size; + mp_size_t qsize, rsize; + mp_size_t sign_remainder = nsize; +#ifdef COMPUTE_QUOTIENT + mp_size_t sign_quotient = nsize ^ dsize; +#endif + unsigned normalization_steps; + mp_limb_t q_limb; + TMP_DECL (marker); + + nsize = ABS (nsize); + dsize = ABS (dsize); + + /* Ensure space is enough for quotient and remainder. */ + + /* We need space for an extra limb in the remainder, because it's + up-shifted (normalized) below. */ + rsize = nsize + 1; + if (rem->_mp_alloc < rsize) + _mpz_realloc (rem, rsize); + + qsize = rsize - dsize; /* qsize cannot be bigger than this. */ + if (qsize <= 0) + { + if (num != rem) + { + rem->_mp_size = num->_mp_size; + MPN_COPY (rem->_mp_d, num->_mp_d, nsize); + } +#ifdef COMPUTE_QUOTIENT + /* This needs to follow the assignment to rem, in case the + numerator and quotient are the same. */ + quot->_mp_size = 0; +#endif + return; + } + +#ifdef COMPUTE_QUOTIENT + if (quot->_mp_alloc < qsize) + _mpz_realloc (quot, qsize); +#endif + + /* Read pointers here, when reallocation is finished. */ + np = num->_mp_d; + dp = den->_mp_d; + rp = rem->_mp_d; + + /* Optimize division by a single-limb divisor. */ + if (dsize == 1) + { + mp_limb_t rlimb; +#ifdef COMPUTE_QUOTIENT + qp = quot->_mp_d; + rlimb = mpn_divmod_1 (qp, np, nsize, dp[0]); + qsize -= qp[qsize - 1] == 0; + quot->_mp_size = sign_quotient >= 0 ? qsize : -qsize; +#else + rlimb = mpn_mod_1 (np, nsize, dp[0]); +#endif + rp[0] = rlimb; + rsize = rlimb != 0; + rem->_mp_size = sign_remainder >= 0 ? rsize : -rsize; + return; + } + + TMP_MARK (marker); + +#ifdef COMPUTE_QUOTIENT + qp = quot->_mp_d; + + /* Make sure QP and NP point to different objects. Otherwise the + numerator would be gradually overwritten by the quotient limbs. */ + if (qp == np) + { + /* Copy NP object to temporary space. */ + np = (mp_ptr) TMP_ALLOC (nsize * BYTES_PER_MP_LIMB); + MPN_COPY (np, qp, nsize); + } + +#else + /* Put quotient at top of remainder. */ + qp = rp + dsize; +#endif + + count_leading_zeros (normalization_steps, dp[dsize - 1]); + + /* Normalize the denominator, i.e. make its most significant bit set by + shifting it NORMALIZATION_STEPS bits to the left. Also shift the + numerator the same number of steps (to keep the quotient the same!). */ + if (normalization_steps != 0) + { + mp_ptr tp; + mp_limb_t nlimb; + + /* Shift up the denominator setting the most significant bit of + the most significant word. Use temporary storage not to clobber + the original contents of the denominator. */ + tp = (mp_ptr) TMP_ALLOC (dsize * BYTES_PER_MP_LIMB); + mpn_lshift (tp, dp, dsize, normalization_steps); + dp = tp; + + /* Shift up the numerator, possibly introducing a new most + significant word. Move the shifted numerator in the remainder + meanwhile. */ + nlimb = mpn_lshift (rp, np, nsize, normalization_steps); + if (nlimb != 0) + { + rp[nsize] = nlimb; + rsize = nsize + 1; + } + else + rsize = nsize; + } + else + { + /* The denominator is already normalized, as required. Copy it to + temporary space if it overlaps with the quotient or remainder. */ +#ifdef COMPUTE_QUOTIENT + if (dp == rp || dp == qp) +#else + if (dp == rp) +#endif + { + mp_ptr tp; + + tp = (mp_ptr) TMP_ALLOC (dsize * BYTES_PER_MP_LIMB); + MPN_COPY (tp, dp, dsize); + dp = tp; + } + + /* Move the numerator to the remainder. */ + if (rp != np) + MPN_COPY (rp, np, nsize); + + rsize = nsize; + } + + q_limb = mpn_divmod (qp, rp, rsize, dp, dsize); + +#ifdef COMPUTE_QUOTIENT + qsize = rsize - dsize; + if (q_limb) + { + qp[qsize] = q_limb; + qsize += 1; + } + + quot->_mp_size = sign_quotient >= 0 ? qsize : -qsize; +#endif + + rsize = dsize; + MPN_NORMALIZE (rp, rsize); + + if (normalization_steps != 0 && rsize != 0) + { + mpn_rshift (rp, rp, rsize, normalization_steps); + rsize -= rp[rsize - 1] == 0; + } + + rem->_mp_size = sign_remainder >= 0 ? rsize : -rsize; + TMP_FREE (marker); +} diff --git a/contrib/libgmp/mpz/fac_ui.c b/contrib/libgmp/mpz/fac_ui.c new file mode 100644 index 0000000..a170060 --- /dev/null +++ b/contrib/libgmp/mpz/fac_ui.c @@ -0,0 +1,157 @@ +/* mpz_fac_ui(result, n) -- Set RESULT to N!. + +Copyright (C) 1991, 1993, 1994, 1995 Free Software Foundation, Inc. + +This file is part of the GNU MP Library. + +The GNU MP Library is free software; you can redistribute it and/or modify +it under the terms of the GNU Library General Public License as published by +the Free Software Foundation; either version 2 of the License, or (at your +option) any later version. + +The GNU MP Library is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public +License for more details. + +You should have received a copy of the GNU Library General Public License +along with the GNU MP Library; see the file COPYING.LIB. If not, write to +the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, +MA 02111-1307, USA. */ + +#ifdef DBG +#include <stdio.h> +#endif + +#include "gmp.h" +#include "gmp-impl.h" +#include "longlong.h" + +void +#if __STDC__ +mpz_fac_ui (mpz_ptr result, unsigned long int n) +#else +mpz_fac_ui (result, n) + mpz_ptr result; + unsigned long int n; +#endif +{ +#if SIMPLE_FAC + + /* Be silly. Just multiply the numbers in ascending order. O(n**2). */ + + unsigned long int k; + + mpz_set_ui (result, 1L); + + for (k = 2; k <= n; k++) + mpz_mul_ui (result, result, k); +#else + + /* Be smarter. Multiply groups of numbers in ascending order until the + product doesn't fit in a limb. Multiply these partial product in a + balanced binary tree fashion, to make the operand have as equal sizes + as possible. When the operands have about the same size, mpn_mul + becomes faster. */ + + unsigned long int p, k; + mp_limb_t p1, p0; + + /* Stack of partial products, used to make the computation balanced + (i.e. make the sizes of the multiplication operands equal). The + topmost position of MP_STACK will contain a one-limb partial product, + the second topmost will contain a two-limb partial product, and so + on. MP_STACK[0] will contain a partial product with 2**t limbs. + To compute n! MP_STACK needs to be less than + log(n)**2/log(BITS_PER_MP_LIMB), so 30 is surely enough. */ +#define MP_STACK_SIZE 30 + mpz_t mp_stack[MP_STACK_SIZE]; + + /* TOP is an index into MP_STACK, giving the topmost element. + TOP_LIMIT_SO_FAR is the largets value it has taken so far. */ + int top, top_limit_so_far; + + /* Count of the total number of limbs put on MP_STACK so far. This + variable plays an essential role in making the compututation balanced. + See below. */ + unsigned int tree_cnt; + + top = top_limit_so_far = -1; + tree_cnt = 0; + p = 1; + for (k = 2; k <= n; k++) + { + /* Multiply the partial product in P with K. */ + umul_ppmm (p1, p0, (mp_limb_t) p, (mp_limb_t) k); + + /* Did we get overflow into the high limb, i.e. is the partial + product now more than one limb? */ + if (p1 != 0) + { + tree_cnt++; + + if (tree_cnt % 2 == 0) + { + mp_size_t i; + + /* TREE_CNT is even (i.e. we have generated an even number of + one-limb partial products), which means that we have a + single-limb product on the top of MP_STACK. */ + + mpz_mul_ui (mp_stack[top], mp_stack[top], p); + + /* If TREE_CNT is divisable by 4, 8,..., we have two + similar-sized partial products with 2, 4,... limbs at + the topmost two positions of MP_STACK. Multiply them + to form a new partial product with 4, 8,... limbs. */ + for (i = 4; (tree_cnt & (i - 1)) == 0; i <<= 1) + { + mpz_mul (mp_stack[top - 1], + mp_stack[top], mp_stack[top - 1]); + top--; + } + } + else + { + /* Put the single-limb partial product in P on the stack. + (The next time we get a single-limb product, we will + multiply the two together.) */ + top++; + if (top > top_limit_so_far) + { + if (top > MP_STACK_SIZE) + abort(); + /* The stack is now bigger than ever, initialize the top + element. */ + mpz_init_set_ui (mp_stack[top], p); + top_limit_so_far++; + } + else + mpz_set_ui (mp_stack[top], p); + } + + /* We ignored the last result from umul_ppmm. Put K in P as the + first component of the next single-limb partial product. */ + p = k; + } + else + /* We didn't get overflow in umul_ppmm. Put p0 in P and try + with one more value of K. */ + p = p0; /* bogus if long != mp_limb_t */ + } + + /* We have partial products in mp_stack[0..top], in descending order. + We also have a small partial product in p. + Their product is the final result. */ + if (top < 0) + mpz_set_ui (result, p); + else + mpz_mul_ui (result, mp_stack[top--], p); + while (top >= 0) + mpz_mul (result, result, mp_stack[top--]); + + /* Free the storage allocated for MP_STACK. */ + for (top = top_limit_so_far; top >= 0; top--) + mpz_clear (mp_stack[top]); +#endif +} diff --git a/contrib/libgmp/mpz/fdiv_q.c b/contrib/libgmp/mpz/fdiv_q.c new file mode 100644 index 0000000..3da943a --- /dev/null +++ b/contrib/libgmp/mpz/fdiv_q.c @@ -0,0 +1,51 @@ +/* mpz_fdiv_q -- Division rounding the quotient towards -infinity. + The remainder gets the same sign as the denominator. + +Copyright (C) 1994, 1995, 1996 Free Software Foundation, Inc. + +This file is part of the GNU MP Library. + +The GNU MP Library is free software; you can redistribute it and/or modify +it under the terms of the GNU Library General Public License as published by +the Free Software Foundation; either version 2 of the License, or (at your +option) any later version. + +The GNU MP Library is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public +License for more details. + +You should have received a copy of the GNU Library General Public License +along with the GNU MP Library; see the file COPYING.LIB. If not, write to +the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, +MA 02111-1307, USA. */ + +#include "gmp.h" +#include "gmp-impl.h" + +void +#if __STDC__ +mpz_fdiv_q (mpz_ptr quot, mpz_srcptr dividend, mpz_srcptr divisor) +#else +mpz_fdiv_q (quot, dividend, divisor) + mpz_ptr quot; + mpz_srcptr dividend; + mpz_srcptr divisor; +#endif +{ + mp_size_t dividend_size = dividend->_mp_size; + mp_size_t divisor_size = divisor->_mp_size; + mpz_t rem; + TMP_DECL (marker); + + TMP_MARK (marker); + + MPZ_TMP_INIT (rem, 1 + ABS (dividend_size)); + + mpz_tdiv_qr (quot, rem, dividend, divisor); + + if ((divisor_size ^ dividend_size) < 0 && rem->_mp_size != 0) + mpz_sub_ui (quot, quot, 1L); + + TMP_FREE (marker); +} diff --git a/contrib/libgmp/mpz/fdiv_q_2exp.c b/contrib/libgmp/mpz/fdiv_q_2exp.c new file mode 100644 index 0000000..3f56baf --- /dev/null +++ b/contrib/libgmp/mpz/fdiv_q_2exp.c @@ -0,0 +1,94 @@ +/* mpz_fdiv_q_2exp -- Divide an integer by 2**CNT. Round the quotient + towards -infinity. + +Copyright (C) 1991, 1993, 1994, 1996 Free Software Foundation, Inc. + +This file is part of the GNU MP Library. + +The GNU MP Library is free software; you can redistribute it and/or modify +it under the terms of the GNU Library General Public License as published by +the Free Software Foundation; either version 2 of the License, or (at your +option) any later version. + +The GNU MP Library is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public +License for more details. + +You should have received a copy of the GNU Library General Public License +along with the GNU MP Library; see the file COPYING.LIB. If not, write to +the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, +MA 02111-1307, USA. */ + +#include "gmp.h" +#include "gmp-impl.h" + +void +#if __STDC__ +mpz_fdiv_q_2exp (mpz_ptr w, mpz_srcptr u, unsigned long int cnt) +#else +mpz_fdiv_q_2exp (w, u, cnt) + mpz_ptr w; + mpz_srcptr u; + unsigned long int cnt; +#endif +{ + mp_size_t usize = u->_mp_size; + mp_size_t wsize; + mp_size_t abs_usize = ABS (usize); + mp_size_t limb_cnt; + mp_ptr wp; + mp_limb_t round = 0; + + limb_cnt = cnt / BITS_PER_MP_LIMB; + wsize = abs_usize - limb_cnt; + if (wsize <= 0) + { + wp = w->_mp_d; + wsize = 0; + /* Set ROUND since we know we skip some non-zero words in this case. + Well, if U is zero, we don't, but then this will be taken care of + below, since rounding only really takes place for negative U. */ + round = 1; + wp[0] = 1; + w->_mp_size = -(usize < 0); + return; + } + else + { + mp_size_t i; + mp_ptr up; + + /* Make sure there is enough space. We make an extra limb + here to account for possible rounding at the end. */ + if (w->_mp_alloc < wsize + 1) + _mpz_realloc (w, wsize + 1); + + wp = w->_mp_d; + up = u->_mp_d; + + /* Set ROUND if we are about skip some non-zero limbs. */ + for (i = 0; i < limb_cnt && round == 0; i++) + round = up[i]; + + cnt %= BITS_PER_MP_LIMB; + if (cnt != 0) + { + round |= mpn_rshift (wp, up + limb_cnt, wsize, cnt); + wsize -= wp[wsize - 1] == 0; + } + else + { + MPN_COPY_INCR (wp, up + limb_cnt, wsize); + } + } + + if (usize < 0 && round != 0) + { + mp_limb_t cy; + cy = mpn_add_1 (wp, wp, wsize, 1); + wp[wsize] = cy; + wsize += cy; + } + w->_mp_size = usize >= 0 ? wsize : -wsize; +} diff --git a/contrib/libgmp/mpz/fdiv_q_ui.c b/contrib/libgmp/mpz/fdiv_q_ui.c new file mode 100644 index 0000000..3d6825d --- /dev/null +++ b/contrib/libgmp/mpz/fdiv_q_ui.c @@ -0,0 +1,62 @@ +/* mpz_fdiv_q_ui -- Division rounding the quotient towards -infinity. + The remainder gets the same sign as the denominator. + +Copyright (C) 1994, 1995, 1996 Free Software Foundation, Inc. + +This file is part of the GNU MP Library. + +The GNU MP Library is free software; you can redistribute it and/or modify +it under the terms of the GNU Library General Public License as published by +the Free Software Foundation; either version 2 of the License, or (at your +option) any later version. + +The GNU MP Library is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public +License for more details. + +You should have received a copy of the GNU Library General Public License +along with the GNU MP Library; see the file COPYING.LIB. If not, write to +the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, +MA 02111-1307, USA. */ + +#include "gmp.h" +#include "gmp-impl.h" + +unsigned long int +#if __STDC__ +mpz_fdiv_q_ui (mpz_ptr quot, mpz_srcptr dividend, unsigned long int divisor) +#else +mpz_fdiv_q_ui (quot, dividend, divisor) + mpz_ptr quot; + mpz_srcptr dividend; + unsigned long int divisor; +#endif +{ + mp_size_t dividend_size; + mp_size_t size; + mp_ptr quot_ptr; + mp_limb_t remainder_limb; + + dividend_size = dividend->_mp_size; + size = ABS (dividend_size); + + if (quot->_mp_alloc < size) + _mpz_realloc (quot, size); + + quot_ptr = quot->_mp_d; + + remainder_limb = mpn_divmod_1 (quot_ptr, dividend->_mp_d, size, + (mp_limb_t) divisor); + + if (remainder_limb != 0 && dividend_size < 0) + { + mpn_add_1 (quot_ptr, quot_ptr, size, (mp_limb_t) 1); + remainder_limb = divisor - remainder_limb; + } + + size -= size != 0 && quot_ptr[size - 1] == 0; + quot->_mp_size = dividend_size >= 0 ? size : -size; + + return remainder_limb; +} diff --git a/contrib/libgmp/mpz/fdiv_qr.c b/contrib/libgmp/mpz/fdiv_qr.c new file mode 100644 index 0000000..2abb16c --- /dev/null +++ b/contrib/libgmp/mpz/fdiv_qr.c @@ -0,0 +1,62 @@ +/* mpz_fdiv_qr -- Division rounding the quotient towards -infinity. + The remainder gets the same sign as the denominator. + +Copyright (C) 1994, 1995, 1996 Free Software Foundation, Inc. + +This file is part of the GNU MP Library. + +The GNU MP Library is free software; you can redistribute it and/or modify +it under the terms of the GNU Library General Public License as published by +the Free Software Foundation; either version 2 of the License, or (at your +option) any later version. + +The GNU MP Library is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public +License for more details. + +You should have received a copy of the GNU Library General Public License +along with the GNU MP Library; see the file COPYING.LIB. If not, write to +the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, +MA 02111-1307, USA. */ + +#include "gmp.h" +#include "gmp-impl.h" + +void +#if __STDC__ +mpz_fdiv_qr (mpz_ptr quot, mpz_ptr rem, mpz_srcptr dividend, mpz_srcptr divisor) +#else +mpz_fdiv_qr (quot, rem, dividend, divisor) + mpz_ptr quot; + mpz_ptr rem; + mpz_srcptr dividend; + mpz_srcptr divisor; +#endif +{ + mp_size_t divisor_size = divisor->_mp_size; + mpz_t temp_divisor; /* N.B.: lives until function returns! */ + TMP_DECL (marker); + + TMP_MARK (marker); + + /* We need the original value of the divisor after the quotient and + remainder have been preliminary calculated. We have to copy it to + temporary space if it's the same variable as either QUOT or REM. */ + if (quot == divisor || rem == divisor) + { + MPZ_TMP_INIT (temp_divisor, ABS (divisor_size)); + mpz_set (temp_divisor, divisor); + divisor = temp_divisor; + } + + mpz_tdiv_qr (quot, rem, dividend, divisor); + + if ((divisor_size ^ dividend->_mp_size) < 0 && rem->_mp_size != 0) + { + mpz_sub_ui (quot, quot, 1L); + mpz_add (rem, rem, divisor); + } + + TMP_FREE (marker); +} diff --git a/contrib/libgmp/mpz/fdiv_qr_ui.c b/contrib/libgmp/mpz/fdiv_qr_ui.c new file mode 100644 index 0000000..a22b702 --- /dev/null +++ b/contrib/libgmp/mpz/fdiv_qr_ui.c @@ -0,0 +1,66 @@ +/* mpz_fdiv_qr_ui -- Division rounding the quotient towards -infinity. + The remainder gets the same sign as the denominator. + +Copyright (C) 1994, 1995, 1996 Free Software Foundation, Inc. + +This file is part of the GNU MP Library. + +The GNU MP Library is free software; you can redistribute it and/or modify +it under the terms of the GNU Library General Public License as published by +the Free Software Foundation; either version 2 of the License, or (at your +option) any later version. + +The GNU MP Library is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public +License for more details. + +You should have received a copy of the GNU Library General Public License +along with the GNU MP Library; see the file COPYING.LIB. If not, write to +the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, +MA 02111-1307, USA. */ + +#include "gmp.h" +#include "gmp-impl.h" + +unsigned long int +#if __STDC__ +mpz_fdiv_qr_ui (mpz_ptr quot, mpz_ptr rem, mpz_srcptr dividend, unsigned long int divisor) +#else +mpz_fdiv_qr_ui (quot, rem, dividend, divisor) + mpz_ptr quot; + mpz_ptr rem; + mpz_srcptr dividend; + unsigned long int divisor; +#endif +{ + mp_size_t dividend_size; + mp_size_t size; + mp_ptr quot_ptr; + mp_limb_t remainder_limb; + + dividend_size = dividend->_mp_size; + size = ABS (dividend_size); + + if (quot->_mp_alloc < size) + _mpz_realloc (quot, size); + + quot_ptr = quot->_mp_d; + + remainder_limb = mpn_divmod_1 (quot_ptr, dividend->_mp_d, size, + (mp_limb_t) divisor); + + if (remainder_limb != 0 && dividend_size < 0) + { + mpn_add_1 (quot_ptr, quot_ptr, size, (mp_limb_t) 1); + remainder_limb = divisor - remainder_limb; + } + + size -= size != 0 && quot_ptr[size - 1] == 0; + quot->_mp_size = dividend_size >= 0 ? size : -size; + + rem->_mp_d[0] = remainder_limb; + rem->_mp_size = remainder_limb != 0; + + return remainder_limb; +} diff --git a/contrib/libgmp/mpz/fdiv_r.c b/contrib/libgmp/mpz/fdiv_r.c new file mode 100644 index 0000000..14e045b --- /dev/null +++ b/contrib/libgmp/mpz/fdiv_r.c @@ -0,0 +1,58 @@ +/* mpz_fdiv_r -- Division rounding the quotient towards -infinity. + The remainder gets the same sign as the denominator. + +Copyright (C) 1994, 1995, 1996 Free Software Foundation, Inc. + +This file is part of the GNU MP Library. + +The GNU MP Library is free software; you can redistribute it and/or modify +it under the terms of the GNU Library General Public License as published by +the Free Software Foundation; either version 2 of the License, or (at your +option) any later version. + +The GNU MP Library is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public +License for more details. + +You should have received a copy of the GNU Library General Public License +along with the GNU MP Library; see the file COPYING.LIB. If not, write to +the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, +MA 02111-1307, USA. */ + +#include "gmp.h" +#include "gmp-impl.h" + +void +#if __STDC__ +mpz_fdiv_r (mpz_ptr rem, mpz_srcptr dividend, mpz_srcptr divisor) +#else +mpz_fdiv_r (rem, dividend, divisor) + mpz_ptr rem; + mpz_srcptr dividend; + mpz_srcptr divisor; +#endif +{ + mp_size_t divisor_size = divisor->_mp_size; + mpz_t temp_divisor; /* N.B.: lives until function returns! */ + TMP_DECL (marker); + + TMP_MARK (marker); + + /* We need the original value of the divisor after the remainder has been + preliminary calculated. We have to copy it to temporary space if it's + the same variable as REM. */ + if (rem == divisor) + { + MPZ_TMP_INIT (temp_divisor, ABS (divisor_size)); + mpz_set (temp_divisor, divisor); + divisor = temp_divisor; + } + + mpz_tdiv_r (rem, dividend, divisor); + + if ((divisor_size ^ dividend->_mp_size) < 0 && rem->_mp_size != 0) + mpz_add (rem, rem, divisor); + + TMP_FREE (marker); +} diff --git a/contrib/libgmp/mpz/fdiv_r_2exp.c b/contrib/libgmp/mpz/fdiv_r_2exp.c new file mode 100644 index 0000000..04190b1 --- /dev/null +++ b/contrib/libgmp/mpz/fdiv_r_2exp.c @@ -0,0 +1,88 @@ +/* mpz_fdiv_r_2exp -- Divide a integer by 2**CNT and produce a remainder. + +Copyright (C) 1991, 1993, 1994, 1995 Free Software Foundation, Inc. + +This file is part of the GNU MP Library. + +The GNU MP Library is free software; you can redistribute it and/or modify +it under the terms of the GNU Library General Public License as published by +the Free Software Foundation; either version 2 of the License, or (at your +option) any later version. + +The GNU MP Library is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public +License for more details. + +You should have received a copy of the GNU Library General Public License +along with the GNU MP Library; see the file COPYING.LIB. If not, write to +the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, +MA 02111-1307, USA. */ + +#include "gmp.h" +#include "gmp-impl.h" + +void +#if __STDC__ +mpz_fdiv_r_2exp (mpz_ptr res, mpz_srcptr in, unsigned long int cnt) +#else +mpz_fdiv_r_2exp (res, in, cnt) + mpz_ptr res; + mpz_srcptr in; + unsigned long int cnt; +#endif +{ + mp_size_t in_size = ABS (in->_mp_size); + mp_size_t res_size; + mp_size_t limb_cnt = cnt / BITS_PER_MP_LIMB; + mp_srcptr in_ptr = in->_mp_d; + + if (in_size > limb_cnt) + { + /* The input operand is (probably) greater than 2**CNT. */ + mp_limb_t x; + + x = in_ptr[limb_cnt] & (((mp_limb_t) 1 << cnt % BITS_PER_MP_LIMB) - 1); + if (x != 0) + { + res_size = limb_cnt + 1; + if (res->_mp_alloc < res_size) + _mpz_realloc (res, res_size); + + res->_mp_d[limb_cnt] = x; + } + else + { + res_size = limb_cnt; + MPN_NORMALIZE (in_ptr, res_size); + + if (res->_mp_alloc < res_size) + _mpz_realloc (res, res_size); + + limb_cnt = res_size; + } + } + else + { + /* The input operand is smaller than 2**CNT. We perform a no-op, + apart from that we might need to copy IN to RES. */ + res_size = in_size; + if (res->_mp_alloc < res_size) + _mpz_realloc (res, res_size); + + limb_cnt = res_size; + } + + if (res != in) + MPN_COPY (res->_mp_d, in->_mp_d, limb_cnt); + res->_mp_size = res_size; + if (in->_mp_size < 0 && res_size != 0) + { + /* Result should be 2^CNT - RES */ + mpz_t tmp; + MPZ_TMP_INIT (tmp, limb_cnt + 1); + mpz_set_ui (tmp, 1L); + mpz_mul_2exp (tmp, tmp, cnt); + mpz_sub (res, tmp, res); + } +} diff --git a/contrib/libgmp/mpz/fdiv_r_ui.c b/contrib/libgmp/mpz/fdiv_r_ui.c new file mode 100644 index 0000000..c4c3749 --- /dev/null +++ b/contrib/libgmp/mpz/fdiv_r_ui.c @@ -0,0 +1,52 @@ +/* mpz_fdiv_r_ui -- Division rounding the quotient towards -infinity. + The remainder gets the same sign as the denominator. + +Copyright (C) 1994, 1995, 1996 Free Software Foundation, Inc. + +This file is part of the GNU MP Library. + +The GNU MP Library is free software; you can redistribute it and/or modify +it under the terms of the GNU Library General Public License as published by +the Free Software Foundation; either version 2 of the License, or (at your +option) any later version. + +The GNU MP Library is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public +License for more details. + +You should have received a copy of the GNU Library General Public License +along with the GNU MP Library; see the file COPYING.LIB. If not, write to +the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, +MA 02111-1307, USA. */ + +#include "gmp.h" +#include "gmp-impl.h" + +unsigned long int +#if __STDC__ +mpz_fdiv_r_ui (mpz_ptr rem, mpz_srcptr dividend, unsigned long int divisor) +#else +mpz_fdiv_r_ui (rem, dividend, divisor) + mpz_ptr rem; + mpz_srcptr dividend; + unsigned long int divisor; +#endif +{ + mp_size_t dividend_size; + mp_size_t size; + mp_limb_t remainder_limb; + + dividend_size = dividend->_mp_size; + size = ABS (dividend_size); + + remainder_limb = mpn_mod_1 (dividend->_mp_d, size, (mp_limb_t) divisor); + + if (remainder_limb != 0 && dividend_size < 0) + remainder_limb = divisor - remainder_limb; + + rem->_mp_d[0] = remainder_limb; + rem->_mp_size = remainder_limb != 0; + + return remainder_limb; +} diff --git a/contrib/libgmp/mpz/fdiv_ui.c b/contrib/libgmp/mpz/fdiv_ui.c new file mode 100644 index 0000000..4d018a2 --- /dev/null +++ b/contrib/libgmp/mpz/fdiv_ui.c @@ -0,0 +1,48 @@ +/* mpz_fdiv_ui -- Division rounding the quotient towards -infinity. + The remainder gets the same sign as the denominator. + +Copyright (C) 1994, 1995, 1996 Free Software Foundation, Inc. + +This file is part of the GNU MP Library. + +The GNU MP Library is free software; you can redistribute it and/or modify +it under the terms of the GNU Library General Public License as published by +the Free Software Foundation; either version 2 of the License, or (at your +option) any later version. + +The GNU MP Library is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public +License for more details. + +You should have received a copy of the GNU Library General Public License +along with the GNU MP Library; see the file COPYING.LIB. If not, write to +the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, +MA 02111-1307, USA. */ + +#include "gmp.h" +#include "gmp-impl.h" + +unsigned long int +#if __STDC__ +mpz_fdiv_ui (mpz_srcptr dividend, unsigned long int divisor) +#else +mpz_fdiv_ui (dividend, divisor) + mpz_srcptr dividend; + unsigned long int divisor; +#endif +{ + mp_size_t dividend_size; + mp_size_t size; + mp_limb_t remainder_limb; + + dividend_size = dividend->_mp_size; + size = ABS (dividend_size); + + remainder_limb = mpn_mod_1 (dividend->_mp_d, size, (mp_limb_t) divisor); + + if (remainder_limb != 0 && dividend_size < 0) + remainder_limb = divisor - remainder_limb; + + return remainder_limb; +} diff --git a/contrib/libgmp/mpz/gcd.c b/contrib/libgmp/mpz/gcd.c new file mode 100644 index 0000000..f93030c --- /dev/null +++ b/contrib/libgmp/mpz/gcd.c @@ -0,0 +1,178 @@ +/* mpz/gcd.c: Calculate the greatest common divisor of two integers. + +Copyright (C) 1991, 1993, 1994, 1996 Free Software Foundation, Inc. + +This file is part of the GNU MP Library. + +The GNU MP Library is free software; you can redistribute it and/or modify +it under the terms of the GNU Library General Public License as published by +the Free Software Foundation; either version 2 of the License, or (at your +option) any later version. + +The GNU MP Library is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public +License for more details. + +You should have received a copy of the GNU Library General Public License +along with the GNU MP Library; see the file COPYING.LIB. If not, write to +the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, +MA 02111-1307, USA. */ + +#include "gmp.h" +#include "gmp-impl.h" +#include "longlong.h" + +void *_mpz_realloc (); + +#ifndef BERKELEY_MP +void +#if __STDC__ +mpz_gcd (mpz_ptr g, mpz_srcptr u, mpz_srcptr v) +#else +mpz_gcd (g, u, v) + mpz_ptr g; + mpz_srcptr u; + mpz_srcptr v; +#endif +#else /* BERKELEY_MP */ +void +#if __STDC__ +gcd (mpz_srcptr u, mpz_srcptr v, mpz_ptr g) +#else +gcd (u, v, g) + mpz_ptr g; + mpz_srcptr u; + mpz_srcptr v; +#endif +#endif /* BERKELEY_MP */ + +{ + unsigned long int g_zero_bits, u_zero_bits, v_zero_bits; + mp_size_t g_zero_limbs, u_zero_limbs, v_zero_limbs; + mp_ptr tp; + mp_ptr up = u->_mp_d; + mp_size_t usize = ABS (u->_mp_size); + mp_ptr vp = v->_mp_d; + mp_size_t vsize = ABS (v->_mp_size); + mp_size_t gsize; + TMP_DECL (marker); + + /* GCD(0, V) == V. */ + if (usize == 0) + { + g->_mp_size = vsize; + if (g == v) + return; + if (g->_mp_alloc < vsize) + _mpz_realloc (g, vsize); + MPN_COPY (g->_mp_d, vp, vsize); + return; + } + + /* GCD(U, 0) == U. */ + if (vsize == 0) + { + g->_mp_size = usize; + if (g == u) + return; + if (g->_mp_alloc < usize) + _mpz_realloc (g, usize); + MPN_COPY (g->_mp_d, up, usize); + return; + } + + if (usize == 1) + { + g->_mp_size = 1; + g->_mp_d[0] = mpn_gcd_1 (vp, vsize, up[0]); + return; + } + + if (vsize == 1) + { + g->_mp_size = 1; + g->_mp_d[0] = mpn_gcd_1 (up, usize, vp[0]); + return; + } + + TMP_MARK (marker); + + /* Eliminate low zero bits from U and V and move to temporary storage. */ + while (*up == 0) + up++; + u_zero_limbs = up - u->_mp_d; + usize -= u_zero_limbs; + count_trailing_zeros (u_zero_bits, *up); + tp = up; + up = (mp_ptr) TMP_ALLOC (usize * BYTES_PER_MP_LIMB); + if (u_zero_bits != 0) + { + mpn_rshift (up, tp, usize, u_zero_bits); + usize -= up[usize - 1] == 0; + } + else + MPN_COPY (up, tp, usize); + + while (*vp == 0) + vp++; + v_zero_limbs = vp - v->_mp_d; + vsize -= v_zero_limbs; + count_trailing_zeros (v_zero_bits, *vp); + tp = vp; + vp = (mp_ptr) TMP_ALLOC (vsize * BYTES_PER_MP_LIMB); + if (v_zero_bits != 0) + { + mpn_rshift (vp, tp, vsize, v_zero_bits); + vsize -= vp[vsize - 1] == 0; + } + else + MPN_COPY (vp, tp, vsize); + + if (u_zero_limbs > v_zero_limbs) + { + g_zero_limbs = v_zero_limbs; + g_zero_bits = v_zero_bits; + } + else if (u_zero_limbs < v_zero_limbs) + { + g_zero_limbs = u_zero_limbs; + g_zero_bits = u_zero_bits; + } + else /* Equal. */ + { + g_zero_limbs = u_zero_limbs; + g_zero_bits = MIN (u_zero_bits, v_zero_bits); + } + + /* Call mpn_gcd. The 1st argument must not have more bits than the 2nd. */ + vsize = (usize < vsize || (usize == vsize && up[usize-1] < vp[vsize-1])) + ? mpn_gcd (vp, up, usize, vp, vsize) + : mpn_gcd (vp, vp, vsize, up, usize); + + /* Here G <-- V << (g_zero_limbs*BITS_PER_MP_LIMB + g_zero_bits). */ + gsize = vsize + g_zero_limbs; + if (g_zero_bits != 0) + { + mp_limb_t cy_limb; + gsize += (vp[vsize - 1] >> (BITS_PER_MP_LIMB - g_zero_bits)) != 0; + if (g->_mp_alloc < gsize) + _mpz_realloc (g, gsize); + MPN_ZERO (g->_mp_d, g_zero_limbs); + + tp = g->_mp_d + g_zero_limbs; + cy_limb = mpn_lshift (tp, vp, vsize, g_zero_bits); + if (cy_limb != 0) + tp[vsize] = cy_limb; + } + else + { + if (g->_mp_alloc < gsize) + _mpz_realloc (g, gsize); + MPN_ZERO (g->_mp_d, g_zero_limbs); + MPN_COPY (g->_mp_d + g_zero_limbs, vp, vsize); + } + + g->_mp_size = gsize; + TMP_FREE (marker); +} diff --git a/contrib/libgmp/mpz/gcd_ui.c b/contrib/libgmp/mpz/gcd_ui.c new file mode 100644 index 0000000..388ab05 --- /dev/null +++ b/contrib/libgmp/mpz/gcd_ui.c @@ -0,0 +1,64 @@ +/* mpz_gcd_ui -- Calculate the greatest common divisior of two integers. + +Copyright (C) 1994, 1996 Free Software Foundation, Inc. + +This file is part of the GNU MP Library. + +The GNU MP Library is free software; you can redistribute it and/or modify +it under the terms of the GNU Library General Public License as published by +the Free Software Foundation; either version 2 of the License, or (at your +option) any later version. + +The GNU MP Library is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public +License for more details. + +You should have received a copy of the GNU Library General Public License +along with the GNU MP Library; see the file COPYING.LIB. If not, write to +the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, +MA 02111-1307, USA. */ + +#include "gmp.h" +#include "gmp-impl.h" + +unsigned long int +#if __STDC__ +mpz_gcd_ui (mpz_ptr w, mpz_srcptr u, unsigned long int v) +#else +mpz_gcd_ui (w, u, v) + mpz_ptr w; + mpz_srcptr u; + unsigned long int v; +#endif +{ + mp_size_t size; + mp_limb_t res; + + size = ABS (u->_mp_size); + + if (size == 0) + res = v; + else if (v == 0) + { + if (w != NULL && u != w) + { + if (w->_mp_alloc < size) + _mpz_realloc (w, size); + + MPN_COPY (w->_mp_d, u->_mp_d, size); + } + w->_mp_size = size; + /* We can't return any useful result for gcd(big,0). */ + return size > 1 ? 0 : w->_mp_d[0]; + } + else + res = mpn_gcd_1 (u->_mp_d, size, v); + + if (w != NULL) + { + w->_mp_d[0] = res; + w->_mp_size = 1; + } + return res; +} diff --git a/contrib/libgmp/mpz/gcdext.c b/contrib/libgmp/mpz/gcdext.c new file mode 100644 index 0000000..adf66b0 --- /dev/null +++ b/contrib/libgmp/mpz/gcdext.c @@ -0,0 +1,88 @@ +/* mpz_gcdext(g, s, t, a, b) -- Set G to gcd(a, b), and S and T such that + g = as + bt. + +Copyright (C) 1991, 1993, 1994, 1995 Free Software Foundation, Inc. + +This file is part of the GNU MP Library. + +The GNU MP Library is free software; you can redistribute it and/or modify +it under the terms of the GNU Library General Public License as published by +the Free Software Foundation; either version 2 of the License, or (at your +option) any later version. + +The GNU MP Library is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public +License for more details. + +You should have received a copy of the GNU Library General Public License +along with the GNU MP Library; see the file COPYING.LIB. If not, write to +the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, +MA 02111-1307, USA. */ + +#include "gmp.h" +#include "gmp-impl.h" + +/* Botch: SLOW! */ + +void +#if __STDC__ +mpz_gcdext (mpz_ptr g, mpz_ptr s, mpz_ptr t, mpz_srcptr a, mpz_srcptr b) +#else +mpz_gcdext (g, s, t, a, b) + mpz_ptr g; + mpz_ptr s; + mpz_ptr t; + mpz_srcptr a; + mpz_srcptr b; +#endif +{ + mpz_t s0, s1, q, r, x, d0, d1; + + mpz_init_set_ui (s0, 1L); + mpz_init_set_ui (s1, 0L); + mpz_init (q); + mpz_init (r); + mpz_init (x); + mpz_init_set (d0, a); + mpz_init_set (d1, b); + + while (d1->_mp_size != 0) + { + mpz_tdiv_qr (q, r, d0, d1); + mpz_set (d0, d1); + mpz_set (d1, r); + + mpz_mul (x, s1, q); + mpz_sub (x, s0, x); + mpz_set (s0, s1); + mpz_set (s1, x); + } + + if (t != NULL) + { + mpz_mul (x, s0, a); + mpz_sub (x, d0, x); + if (b->_mp_size == 0) + t->_mp_size = 0; + else + mpz_tdiv_q (t, x, b); + } + mpz_set (s, s0); + mpz_set (g, d0); + if (g->_mp_size < 0) + { + g->_mp_size = -g->_mp_size; + s->_mp_size = -s->_mp_size; + if (t != NULL) + t->_mp_size = -t->_mp_size; + } + + mpz_clear (s0); + mpz_clear (s1); + mpz_clear (q); + mpz_clear (r); + mpz_clear (x); + mpz_clear (d0); + mpz_clear (d1); +} diff --git a/contrib/libgmp/mpz/get_d.c b/contrib/libgmp/mpz/get_d.c new file mode 100644 index 0000000..0fd7916 --- /dev/null +++ b/contrib/libgmp/mpz/get_d.c @@ -0,0 +1,54 @@ +/* double mpz_get_d (mpz_t src) -- Return the double approximation to SRC. + +Copyright (C) 1996 Free Software Foundation, Inc. + +This file is part of the GNU MP Library. + +The GNU MP Library is free software; you can redistribute it and/or modify +it under the terms of the GNU Library General Public License as published by +the Free Software Foundation; either version 2 of the License, or (at your +option) any later version. + +The GNU MP Library is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public +License for more details. + +You should have received a copy of the GNU Library General Public License +along with the GNU MP Library; see the file COPYING.LIB. If not, write to +the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, +MA 02111-1307, USA. */ + +#include "gmp.h" +#include "gmp-impl.h" + +double +#if __STDC__ +mpz_get_d (mpz_srcptr src) +#else +mpz_get_d (src) + mpz_srcptr src; +#endif +{ + double res; + mp_size_t size, i, n_limbs_to_use; + int negative; + mp_ptr qp; + + size = SIZ(src); + if (size == 0) + return 0.0; + + negative = size < 0; + size = ABS (size); + qp = PTR(src); + + res = qp[size - 1]; + n_limbs_to_use = MIN (LIMBS_PER_DOUBLE, size); + for (i = 2; i <= n_limbs_to_use; i++) + res = res * MP_BASE_AS_DOUBLE + qp[size - i]; + + res = __gmp_scale2 (res, (size - n_limbs_to_use) * BITS_PER_MP_LIMB); + + return negative ? -res : res; +} diff --git a/contrib/libgmp/mpz/get_si.c b/contrib/libgmp/mpz/get_si.c new file mode 100644 index 0000000..45e0e5a --- /dev/null +++ b/contrib/libgmp/mpz/get_si.c @@ -0,0 +1,43 @@ +/* mpz_get_si(integer) -- Return the least significant digit from INTEGER. + +Copyright (C) 1991, 1993, 1994, 1995 Free Software Foundation, Inc. + +This file is part of the GNU MP Library. + +The GNU MP Library is free software; you can redistribute it and/or modify +it under the terms of the GNU Library General Public License as published by +the Free Software Foundation; either version 2 of the License, or (at your +option) any later version. + +The GNU MP Library is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public +License for more details. + +You should have received a copy of the GNU Library General Public License +along with the GNU MP Library; see the file COPYING.LIB. If not, write to +the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, +MA 02111-1307, USA. */ + +#include "gmp.h" +#include "gmp-impl.h" + +signed long int +#if __STDC__ +mpz_get_si (mpz_srcptr op) +#else +mpz_get_si (op) + mpz_srcptr op; +#endif +{ + mp_size_t size = op->_mp_size; + mp_limb_t low_limb = op->_mp_d[0]; + + if (size > 0) + return low_limb % ((mp_limb_t) 1 << (BITS_PER_MP_LIMB - 1)); + else if (size < 0) + /* This convoluted expression is necessary to properly handle 0x80000000 */ + return ~((low_limb - 1) % ((mp_limb_t) 1 << (BITS_PER_MP_LIMB - 1))); + else + return 0; +} diff --git a/contrib/libgmp/mpz/get_str.c b/contrib/libgmp/mpz/get_str.c new file mode 100644 index 0000000..8ccf3ef --- /dev/null +++ b/contrib/libgmp/mpz/get_str.c @@ -0,0 +1,118 @@ +/* mpz_get_str (string, base, mp_src) -- Convert the multiple precision + number MP_SRC to a string STRING of base BASE. If STRING is NULL + allocate space for the result. In any case, return a pointer to the + result. If STRING is not NULL, the caller must ensure enough space is + available to store the result. + +Copyright (C) 1991, 1993, 1994, 1996 Free Software Foundation, Inc. + +This file is part of the GNU MP Library. + +The GNU MP Library is free software; you can redistribute it and/or modify +it under the terms of the GNU Library General Public License as published by +the Free Software Foundation; either version 2 of the License, or (at your +option) any later version. + +The GNU MP Library is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public +License for more details. + +You should have received a copy of the GNU Library General Public License +along with the GNU MP Library; see the file COPYING.LIB. If not, write to +the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, +MA 02111-1307, USA. */ + +#include "gmp.h" +#include "gmp-impl.h" + +char * +#if __STDC__ +mpz_get_str (char *res_str, int base, mpz_srcptr x) +#else +mpz_get_str (res_str, base, x) + char *res_str; + int base; + mpz_srcptr x; +#endif +{ + mp_ptr xp; + mp_size_t x_size = x->_mp_size; + unsigned char *str; + char *return_str; + size_t str_size; + char *num_to_text; + int i; + TMP_DECL (marker); + + TMP_MARK (marker); + if (base >= 0) + { + if (base == 0) + base = 10; + num_to_text = "0123456789abcdefghijklmnopqrstuvwxyz"; + } + else + { + base = -base; + num_to_text = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"; + } + + /* We allways allocate space for the string. If the caller passed a + NULL pointer for RES_STR, we allocate permanent space and return + a pointer to that to the caller. */ + str_size = ((size_t) (ABS (x_size) * BITS_PER_MP_LIMB + * __mp_bases[base].chars_per_bit_exactly)) + 3; + if (res_str == 0) + { + /* We didn't get a string from the user. Allocate one (and return + a pointer to it). */ + res_str = (char *) (*_mp_allocate_func) (str_size); + /* Make str, the variable used for raw result from mpn_get_str, + point to the same string, but just after a possible minus sign. */ + str = (unsigned char *) res_str + 1; + } + else + { + /* Use TMP_ALLOC to get temporary space, since we need a few extra bytes + that we can't expect to caller to supply us with. */ + str = (unsigned char *) TMP_ALLOC (str_size); + } + + return_str = res_str; + + if (x_size == 0) + { + res_str[0] = '0'; + res_str[1] = 0; + TMP_FREE (marker); + return res_str; + } + if (x_size < 0) + { + *res_str++ = '-'; + x_size = -x_size; + } + + /* Move the number to convert into temporary space, since mpn_get_str + clobbers its argument + needs one extra high limb.... */ + xp = (mp_ptr) TMP_ALLOC ((x_size + 1) * BYTES_PER_MP_LIMB); + MPN_COPY (xp, x->_mp_d, x_size); + + str_size = mpn_get_str (str, base, xp, x_size); + + /* mpn_get_str might make some leading zeros. Skip them. */ + while (*str == 0) + { + str_size--; + str++; + } + + /* Translate result to printable chars and move result to RES_STR. */ + for (i = 0; i < str_size; i++) + res_str[i] = num_to_text[str[i]]; + res_str[str_size] = 0; + + TMP_FREE (marker); + return return_str; +} diff --git a/contrib/libgmp/mpz/get_ui.c b/contrib/libgmp/mpz/get_ui.c new file mode 100644 index 0000000..4bfb5e1 --- /dev/null +++ b/contrib/libgmp/mpz/get_ui.c @@ -0,0 +1,37 @@ +/* mpz_get_ui(integer) -- Return the least significant digit from INTEGER. + +Copyright (C) 1991, 1993, 1994, 1995 Free Software Foundation, Inc. + +This file is part of the GNU MP Library. + +The GNU MP Library is free software; you can redistribute it and/or modify +it under the terms of the GNU Library General Public License as published by +the Free Software Foundation; either version 2 of the License, or (at your +option) any later version. + +The GNU MP Library is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public +License for more details. + +You should have received a copy of the GNU Library General Public License +along with the GNU MP Library; see the file COPYING.LIB. If not, write to +the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, +MA 02111-1307, USA. */ + +#include "gmp.h" +#include "gmp-impl.h" + +unsigned long int +#if __STDC__ +mpz_get_ui (mpz_srcptr integer) +#else +mpz_get_ui (integer) + mpz_srcptr integer; +#endif +{ + if (integer->_mp_size == 0) + return 0; + else + return integer->_mp_d[0]; +} diff --git a/contrib/libgmp/mpz/getlimbn.c b/contrib/libgmp/mpz/getlimbn.c new file mode 100644 index 0000000..c7a234b --- /dev/null +++ b/contrib/libgmp/mpz/getlimbn.c @@ -0,0 +1,38 @@ +/* mpz_getlimbn(integer,n) -- Return the N:th limb from INTEGER. + +Copyright (C) 1993, 1994, 1995 Free Software Foundation, Inc. + +This file is part of the GNU MP Library. + +The GNU MP Library is free software; you can redistribute it and/or modify +it under the terms of the GNU Library General Public License as published by +the Free Software Foundation; either version 2 of the License, or (at your +option) any later version. + +The GNU MP Library is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public +License for more details. + +You should have received a copy of the GNU Library General Public License +along with the GNU MP Library; see the file COPYING.LIB. If not, write to +the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, +MA 02111-1307, USA. */ + +#include "gmp.h" +#include "gmp-impl.h" + +mp_limb_t +#if __STDC__ +mpz_getlimbn (mpz_srcptr integer, mp_size_t n) +#else +mpz_getlimbn (integer, n) + mpz_srcptr integer; + mp_size_t n; +#endif +{ + if (integer->_mp_size <= n || n < 0) + return 0; + else + return integer->_mp_d[n]; +} diff --git a/contrib/libgmp/mpz/hamdist.c b/contrib/libgmp/mpz/hamdist.c new file mode 100644 index 0000000..58c9273 --- /dev/null +++ b/contrib/libgmp/mpz/hamdist.c @@ -0,0 +1,62 @@ +/* mpz_hamdist(mpz_ptr op1, mpz_ptr op2) -- Compute the hamming distance + between OP1 and OP2. If one of the operands is negative, return ~0. (We + could make the function well-defined when both operands are negative, but + that would probably not be worth the trouble. + +Copyright (C) 1994, 1996 Free Software Foundation, Inc. + +This file is part of the GNU MP Library. + +The GNU MP Library is free software; you can redistribute it and/or modify +it under the terms of the GNU Library General Public License as published by +the Free Software Foundation; either version 2 of the License, or (at your +option) any later version. + +The GNU MP Library is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public +License for more details. + +You should have received a copy of the GNU Library General Public License +along with the GNU MP Library; see the file COPYING.LIB. If not, write to +the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, +MA 02111-1307, USA. */ + +#include "gmp.h" +#include "gmp-impl.h" + +unsigned long int +#if __STDC__ +mpz_hamdist (mpz_srcptr u, mpz_srcptr v) +#else +mpz_hamdist (u, v) + mpz_srcptr u; + mpz_srcptr v; +#endif +{ + mp_srcptr up, vp; + mp_size_t usize, vsize, size; + unsigned long int count; + + usize = u->_mp_size; + vsize = v->_mp_size; + + if ((usize | vsize) < 0) + return ~ (unsigned long int) 0; + + up = u->_mp_d; + vp = v->_mp_d; + + if (usize > vsize) + { + count = mpn_popcount (up + vsize, usize - vsize); + size = vsize; + } + else + { + count = mpn_popcount (vp + usize, vsize - usize); + size = usize; + } + + return count + mpn_hamdist (up, vp, size); +} diff --git a/contrib/libgmp/mpz/init.c b/contrib/libgmp/mpz/init.c new file mode 100644 index 0000000..f8d8e20 --- /dev/null +++ b/contrib/libgmp/mpz/init.c @@ -0,0 +1,36 @@ +/* mpz_init() -- Make a new multiple precision number with value 0. + +Copyright (C) 1991, 1993, 1994, 1995 Free Software Foundation, Inc. + +This file is part of the GNU MP Library. + +The GNU MP Library is free software; you can redistribute it and/or modify +it under the terms of the GNU Library General Public License as published by +the Free Software Foundation; either version 2 of the License, or (at your +option) any later version. + +The GNU MP Library is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public +License for more details. + +You should have received a copy of the GNU Library General Public License +along with the GNU MP Library; see the file COPYING.LIB. If not, write to +the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, +MA 02111-1307, USA. */ + +#include "gmp.h" +#include "gmp-impl.h" + +void +#if __STDC__ +mpz_init (mpz_ptr x) +#else +mpz_init (x) + mpz_ptr x; +#endif +{ + x->_mp_alloc = 1; + x->_mp_d = (mp_ptr) (*_mp_allocate_func) (BYTES_PER_MP_LIMB); + x->_mp_size = 0; +} diff --git a/contrib/libgmp/mpz/inp_raw.c b/contrib/libgmp/mpz/inp_raw.c new file mode 100644 index 0000000..e1cec1d --- /dev/null +++ b/contrib/libgmp/mpz/inp_raw.c @@ -0,0 +1,101 @@ +/* mpz_inp_raw -- Input a mpz_t in raw, but endianess, and wordsize + independent format (as output by mpz_out_raw). + +Copyright (C) 1991, 1993, 1994, 1995 Free Software Foundation, Inc. + +This file is part of the GNU MP Library. + +The GNU MP Library is free software; you can redistribute it and/or modify +it under the terms of the GNU Library General Public License as published by +the Free Software Foundation; either version 2 of the License, or (at your +option) any later version. + +The GNU MP Library is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public +License for more details. + +You should have received a copy of the GNU Library General Public License +along with the GNU MP Library; see the file COPYING.LIB. If not, write to +the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, +MA 02111-1307, USA. */ + +#include <stdio.h> + +#include "gmp.h" +#include "gmp-impl.h" + +size_t +#if __STDC__ +mpz_inp_raw (mpz_ptr x, FILE *stream) +#else +mpz_inp_raw (x, stream) + mpz_ptr x; + FILE *stream; +#endif +{ + int i; + mp_size_t s; + mp_size_t xsize; + mp_ptr xp; + unsigned int c; + mp_limb_t x_limb; + mp_size_t in_bytesize; + int neg_flag; + + if (stream == 0) + stream = stdin; + + /* Read 4-byte size */ + in_bytesize = 0; + for (i = 4 - 1; i >= 0; i--) + { + c = fgetc (stream); + in_bytesize = (in_bytesize << BITS_PER_CHAR) | c; + } + + /* Size is stored as a 32 bit word; sign extend in_bytesize for non-32 bit + machines. */ + if (sizeof (mp_size_t) > 4) + in_bytesize |= (-(in_bytesize < 0)) << 31; + + neg_flag = in_bytesize < 0; + in_bytesize = ABS (in_bytesize); + xsize = (in_bytesize + BYTES_PER_MP_LIMB - 1) / BYTES_PER_MP_LIMB; + + if (xsize == 0) + { + x->_mp_size = 0; + return 4; /* we've read 4 bytes */ + } + + if (x->_mp_alloc < xsize) + _mpz_realloc (x, xsize); + xp = x->_mp_d; + + x_limb = 0; + for (i = (in_bytesize - 1) % BYTES_PER_MP_LIMB; i >= 0; i--) + { + c = fgetc (stream); + x_limb = (x_limb << BITS_PER_CHAR) | c; + } + xp[xsize - 1] = x_limb; + + for (s = xsize - 2; s >= 0; s--) + { + x_limb = 0; + for (i = BYTES_PER_MP_LIMB - 1; i >= 0; i--) + { + c = fgetc (stream); + x_limb = (x_limb << BITS_PER_CHAR) | c; + } + xp[s] = x_limb; + } + + if (c == EOF) + return 0; /* error */ + + MPN_NORMALIZE (xp, xsize); + x->_mp_size = neg_flag ? -xsize : xsize; + return in_bytesize + 4; +} diff --git a/contrib/libgmp/mpz/inp_str.c b/contrib/libgmp/mpz/inp_str.c new file mode 100644 index 0000000..7159062 --- /dev/null +++ b/contrib/libgmp/mpz/inp_str.c @@ -0,0 +1,138 @@ +/* mpz_inp_str(dest_integer, stream, base) -- Input a number in base + BASE from stdio stream STREAM and store the result in DEST_INTEGER. + +Copyright (C) 1991, 1993, 1994, 1996 Free Software Foundation, Inc. + +This file is part of the GNU MP Library. + +The GNU MP Library is free software; you can redistribute it and/or modify +it under the terms of the GNU Library General Public License as published by +the Free Software Foundation; either version 2 of the License, or (at your +option) any later version. + +The GNU MP Library is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public +License for more details. + +You should have received a copy of the GNU Library General Public License +along with the GNU MP Library; see the file COPYING.LIB. If not, write to +the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, +MA 02111-1307, USA. */ + +#include <stdio.h> +#include <ctype.h> +#include "gmp.h" +#include "gmp-impl.h" + +static int +digit_value_in_base (c, base) + int c; + int base; +{ + int digit; + + if (isdigit (c)) + digit = c - '0'; + else if (islower (c)) + digit = c - 'a' + 10; + else if (isupper (c)) + digit = c - 'A' + 10; + else + return -1; + + if (digit < base) + return digit; + return -1; +} + +size_t +#if __STDC__ +mpz_inp_str (mpz_ptr dest, FILE *stream, int base) +#else +mpz_inp_str (dest, stream, base) + mpz_ptr dest; + FILE *stream; + int base; +#endif +{ + char *str; + size_t alloc_size, str_size; + int c; + int negative; + mp_size_t dest_size; + size_t nread; + + if (stream == 0) + stream = stdin; + + alloc_size = 100; + str = (char *) (*_mp_allocate_func) (alloc_size); + str_size = 0; + nread = 0; + + /* Skip whitespace. */ + do + { + c = getc (stream); + nread++; + } + while (isspace (c)); + + negative = 0; + if (c == '-') + { + negative = 1; + c = getc (stream); + } + + if (digit_value_in_base (c, base == 0 ? 10 : base) < 0) + return 0; /* error if no digits */ + + /* If BASE is 0, try to find out the base by looking at the initial + characters. */ + if (base == 0) + { + base = 10; + if (c == '0') + { + base = 8; + c = getc (stream); + nread++; + if (c == 'x' || c == 'X') + { + base = 16; + c = getc (stream); + nread++; + } + } + } + + for (;;) + { + int dig; + if (str_size >= alloc_size) + { + size_t old_alloc_size = alloc_size; + alloc_size = alloc_size * 3 / 2; + str = (char *) (*_mp_reallocate_func) (str, old_alloc_size, alloc_size); + } + dig = digit_value_in_base (c, base); + if (dig < 0) + break; + str[str_size++] = dig; + c = getc (stream); + } + + ungetc (c, stream); + + dest_size = str_size / __mp_bases[base].chars_per_limb + 1; + if (dest->_mp_alloc < dest_size) + _mpz_realloc (dest, dest_size); + + dest_size = mpn_set_str (dest->_mp_d, (unsigned char *) str, str_size, base); + dest->_mp_size = negative ? -dest_size : dest_size; + + (*_mp_free_func) (str, alloc_size); + return str_size + nread; +} diff --git a/contrib/libgmp/mpz/invert.c b/contrib/libgmp/mpz/invert.c new file mode 100644 index 0000000..ff1d6d9 --- /dev/null +++ b/contrib/libgmp/mpz/invert.c @@ -0,0 +1,43 @@ +/* mpz_invert (inv, x, n). Find multiplicative inverse of X in Z(N). + If X has an inverse, return non-zero and store inverse in INVERSE, + otherwise, return 0 and put garbage in X. + +Copyright (C) 1996 Free Software Foundation, Inc. + +This file is part of the GNU MP Library. + +The GNU MP Library is free software; you can redistribute it and/or modify +it under the terms of the GNU Library General Public License as published by +the Free Software Foundation; either version 2 of the License, or (at your +option) any later version. + +The GNU MP Library is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public +License for more details. + +You should have received a copy of the GNU Library General Public License +along with the GNU MP Library; see the file COPYING.LIB. If not, write to +the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, +MA 02111-1307, USA. */ + +#include "gmp.h" + +int +#if __STDC__ +mpz_invert (mpz_ptr inverse, mpz_srcptr x, mpz_srcptr n) +#else +mpz_invert (inverse, x, n) + mpz_ptr inverse; + mpz_srcptr x, n; +#endif +{ + mpz_t gcd; + int rv; + + mpz_init (gcd); + mpz_gcdext (gcd, inverse, (mpz_ptr) 0, x, n); + rv = gcd->_mp_size == 1 && (gcd->_mp_d)[0] == 1; + mpz_clear (gcd); + return rv; +} diff --git a/contrib/libgmp/mpz/ior.c b/contrib/libgmp/mpz/ior.c new file mode 100644 index 0000000..77facfd --- /dev/null +++ b/contrib/libgmp/mpz/ior.c @@ -0,0 +1,243 @@ +/* mpz_ior -- Logical inclusive or. + +Copyright (C) 1991, 1993, 1994, 1996 Free Software Foundation, Inc. + +This file is part of the GNU MP Library. + +The GNU MP Library is free software; you can redistribute it and/or modify +it under the terms of the GNU Library General Public License as published by +the Free Software Foundation; either version 2 of the License, or (at your +option) any later version. + +The GNU MP Library is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public +License for more details. + +You should have received a copy of the GNU Library General Public License +along with the GNU MP Library; see the file COPYING.LIB. If not, write to +the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, +MA 02111-1307, USA. */ + +#include "gmp.h" +#include "gmp-impl.h" + +void +#if __STDC__ +mpz_ior (mpz_ptr res, mpz_srcptr op1, mpz_srcptr op2) +#else +mpz_ior (res, op1, op2) + mpz_ptr res; + mpz_srcptr op1; + mpz_srcptr op2; +#endif +{ + mp_srcptr op1_ptr, op2_ptr; + mp_size_t op1_size, op2_size; + mp_ptr res_ptr; + mp_size_t res_size; + mp_size_t i; + TMP_DECL (marker); + + TMP_MARK (marker); + op1_size = op1->_mp_size; + op2_size = op2->_mp_size; + + op1_ptr = op1->_mp_d; + op2_ptr = op2->_mp_d; + res_ptr = res->_mp_d; + + if (op1_size >= 0) + { + if (op2_size >= 0) + { + if (op1_size >= op2_size) + { + if (res->_mp_alloc < op1_size) + { + _mpz_realloc (res, op1_size); + op1_ptr = op1->_mp_d; + op2_ptr = op2->_mp_d; + res_ptr = res->_mp_d; + } + + if (res_ptr != op1_ptr) + MPN_COPY (res_ptr + op2_size, op1_ptr + op2_size, + op1_size - op2_size); + for (i = op2_size - 1; i >= 0; i--) + res_ptr[i] = op1_ptr[i] | op2_ptr[i]; + res_size = op1_size; + } + else + { + if (res->_mp_alloc < op2_size) + { + _mpz_realloc (res, op2_size); + op1_ptr = op1->_mp_d; + op2_ptr = op2->_mp_d; + res_ptr = res->_mp_d; + } + + if (res_ptr != op2_ptr) + MPN_COPY (res_ptr + op1_size, op2_ptr + op1_size, + op2_size - op1_size); + for (i = op1_size - 1; i >= 0; i--) + res_ptr[i] = op1_ptr[i] | op2_ptr[i]; + res_size = op2_size; + } + + res->_mp_size = res_size; + return; + } + else /* op2_size < 0 */ + { + /* Fall through to the code at the end of the function. */ + } + } + else + { + if (op2_size < 0) + { + mp_ptr opx; + mp_limb_t cy; + + /* Both operands are negative, so will be the result. + -((-OP1) | (-OP2)) = -(~(OP1 - 1) | ~(OP2 - 1)) = + = ~(~(OP1 - 1) | ~(OP2 - 1)) + 1 = + = ((OP1 - 1) & (OP2 - 1)) + 1 */ + + op1_size = -op1_size; + op2_size = -op2_size; + + res_size = MIN (op1_size, op2_size); + + /* Possible optimization: Decrease mpn_sub precision, + as we won't use the entire res of both. */ + opx = (mp_ptr) TMP_ALLOC (res_size * BYTES_PER_MP_LIMB); + mpn_sub_1 (opx, op1_ptr, res_size, (mp_limb_t) 1); + op1_ptr = opx; + + opx = (mp_ptr) TMP_ALLOC (res_size * BYTES_PER_MP_LIMB); + mpn_sub_1 (opx, op2_ptr, res_size, (mp_limb_t) 1); + op2_ptr = opx; + + if (res->_mp_alloc < res_size) + { + _mpz_realloc (res, res_size); + res_ptr = res->_mp_d; + /* Don't re-read OP1_PTR and OP2_PTR. They point to + temporary space--never to the space RES->_mp_D used + to point to before reallocation. */ + } + + /* First loop finds the size of the result. */ + for (i = res_size - 1; i >= 0; i--) + if ((op1_ptr[i] & op2_ptr[i]) != 0) + break; + res_size = i + 1; + + if (res_size != 0) + { + /* Second loop computes the real result. */ + for (i = res_size - 1; i >= 0; i--) + res_ptr[i] = op1_ptr[i] & op2_ptr[i]; + + cy = mpn_add_1 (res_ptr, res_ptr, res_size, (mp_limb_t) 1); + if (cy) + { + res_ptr[res_size] = cy; + res_size++; + } + } + else + { + res_ptr[0] = 1; + res_size = 1; + } + + res->_mp_size = -res_size; + TMP_FREE (marker); + return; + } + else + { + /* We should compute -OP1 | OP2. Swap OP1 and OP2 and fall + through to the code that handles OP1 | -OP2. */ + {mpz_srcptr t = op1; op1 = op2; op2 = t;} + {mp_srcptr t = op1_ptr; op1_ptr = op2_ptr; op2_ptr = t;} + {mp_size_t t = op1_size; op1_size = op2_size; op2_size = t;} + } + } + + { + mp_ptr opx; + mp_limb_t cy; + mp_size_t res_alloc; + mp_size_t count; + + /* Operand 2 negative, so will be the result. + -(OP1 | (-OP2)) = -(OP1 | ~(OP2 - 1)) = + = ~(OP1 | ~(OP2 - 1)) + 1 = + = (~OP1 & (OP2 - 1)) + 1 */ + + op2_size = -op2_size; + + res_alloc = op2_size; + + opx = (mp_ptr) TMP_ALLOC (op2_size * BYTES_PER_MP_LIMB); + mpn_sub_1 (opx, op2_ptr, op2_size, (mp_limb_t) 1); + op2_ptr = opx; + + if (res->_mp_alloc < res_alloc) + { + _mpz_realloc (res, res_alloc); + op1_ptr = op1->_mp_d; + res_ptr = res->_mp_d; + /* Don't re-read OP2_PTR. It points to temporary space--never + to the space RES->_mp_D used to point to before reallocation. */ + } + + if (op1_size >= op2_size) + { + /* We can just ignore the part of OP1 that stretches above OP2, + because the result limbs are zero there. */ + + /* First loop finds the size of the result. */ + for (i = op2_size - 1; i >= 0; i--) + if ((~op1_ptr[i] & op2_ptr[i]) != 0) + break; + res_size = i + 1; + count = res_size; + } + else + { + res_size = op2_size; + + /* Copy the part of OP2 that stretches above OP1, to RES. */ + MPN_COPY (res_ptr + op1_size, op2_ptr + op1_size, op2_size - op1_size); + count = op1_size; + } + + if (res_size != 0) + { + /* Second loop computes the real result. */ + for (i = count - 1; i >= 0; i--) + res_ptr[i] = ~op1_ptr[i] & op2_ptr[i]; + + cy = mpn_add_1 (res_ptr, res_ptr, res_size, (mp_limb_t) 1); + if (cy) + { + res_ptr[res_size] = cy; + res_size++; + } + } + else + { + res_ptr[0] = 1; + res_size = 1; + } + + res->_mp_size = -res_size; + } + TMP_FREE (marker); +} diff --git a/contrib/libgmp/mpz/iset.c b/contrib/libgmp/mpz/iset.c new file mode 100644 index 0000000..c8a17dc --- /dev/null +++ b/contrib/libgmp/mpz/iset.c @@ -0,0 +1,49 @@ +/* mpz_init_set (src_integer) -- Make a new multiple precision number with + a value copied from SRC_INTEGER. + +Copyright (C) 1991, 1993, 1994, 1996 Free Software Foundation, Inc. + +This file is part of the GNU MP Library. + +The GNU MP Library is free software; you can redistribute it and/or modify +it under the terms of the GNU Library General Public License as published by +the Free Software Foundation; either version 2 of the License, or (at your +option) any later version. + +The GNU MP Library is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public +License for more details. + +You should have received a copy of the GNU Library General Public License +along with the GNU MP Library; see the file COPYING.LIB. If not, write to +the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, +MA 02111-1307, USA. */ + +#include "gmp.h" +#include "gmp-impl.h" + +void +#if __STDC__ +mpz_init_set (mpz_ptr w, mpz_srcptr u) +#else +mpz_init_set (w, u) + mpz_ptr w; + mpz_srcptr u; +#endif +{ + mp_ptr wp, up; + mp_size_t usize, size; + + usize = u->_mp_size; + size = ABS (usize); + + w->_mp_alloc = MAX (size, 1); + w->_mp_d = (mp_ptr) (*_mp_allocate_func) (w->_mp_alloc * BYTES_PER_MP_LIMB); + + wp = w->_mp_d; + up = u->_mp_d; + + MPN_COPY (wp, up, size); + w->_mp_size = usize; +} diff --git a/contrib/libgmp/mpz/iset_d.c b/contrib/libgmp/mpz/iset_d.c new file mode 100644 index 0000000..41e5c4f --- /dev/null +++ b/contrib/libgmp/mpz/iset_d.c @@ -0,0 +1,39 @@ +/* mpz_init_set_d(integer, val) -- Initialize and assign INTEGER with a double + value VAL. + +Copyright (C) 1996 Free Software Foundation, Inc. + +This file is part of the GNU MP Library. + +The GNU MP Library is free software; you can redistribute it and/or modify +it under the terms of the GNU Library General Public License as published by +the Free Software Foundation; either version 2 of the License, or (at your +option) any later version. + +The GNU MP Library is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public +License for more details. + +You should have received a copy of the GNU Library General Public License +along with the GNU MP Library; see the file COPYING.LIB. If not, write to +the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, +MA 02111-1307, USA. */ + +#include "gmp.h" +#include "gmp-impl.h" + +void +#if __STDC__ +mpz_init_set_d (mpz_ptr dest, double val) +#else +mpz_init_set_d (dest, val) + mpz_ptr dest; + double val; +#endif +{ + dest->_mp_alloc = 1; + dest->_mp_d = (mp_ptr) (*_mp_allocate_func) (BYTES_PER_MP_LIMB); + dest->_mp_size = 0; + mpz_set_d (dest, val); +} diff --git a/contrib/libgmp/mpz/iset_si.c b/contrib/libgmp/mpz/iset_si.c new file mode 100644 index 0000000..af51f05 --- /dev/null +++ b/contrib/libgmp/mpz/iset_si.c @@ -0,0 +1,49 @@ +/* mpz_init_set_si(val) -- Make a new multiple precision number with + value val. + +Copyright (C) 1991, 1993, 1994, 1995 Free Software Foundation, Inc. + +This file is part of the GNU MP Library. + +The GNU MP Library is free software; you can redistribute it and/or modify +it under the terms of the GNU Library General Public License as published by +the Free Software Foundation; either version 2 of the License, or (at your +option) any later version. + +The GNU MP Library is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public +License for more details. + +You should have received a copy of the GNU Library General Public License +along with the GNU MP Library; see the file COPYING.LIB. If not, write to +the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, +MA 02111-1307, USA. */ + +#include "gmp.h" +#include "gmp-impl.h" + +void +#if __STDC__ +mpz_init_set_si (mpz_ptr x, signed long int val) +#else +mpz_init_set_si (x, val) + mpz_ptr x; + signed long int val; +#endif +{ + x->_mp_alloc = 1; + x->_mp_d = (mp_ptr) (*_mp_allocate_func) (BYTES_PER_MP_LIMB); + if (val > 0) + { + x->_mp_d[0] = val; + x->_mp_size = 1; + } + else if (val < 0) + { + x->_mp_d[0] = -val; + x->_mp_size = -1; + } + else + x->_mp_size = 0; +} diff --git a/contrib/libgmp/mpz/iset_str.c b/contrib/libgmp/mpz/iset_str.c new file mode 100644 index 0000000..e04ad5d --- /dev/null +++ b/contrib/libgmp/mpz/iset_str.c @@ -0,0 +1,44 @@ +/* mpz_init_set_str(string, base) -- Convert the \0-terminated string + STRING in base BASE to a multiple precision integer. Return a MP_INT + structure representing the integer. Allow white space in the + string. If BASE == 0 determine the base in the C standard way, + i.e. 0xhh...h means base 16, 0oo...o means base 8, otherwise + assume base 10. + +Copyright (C) 1991, 1993, 1994, 1995 Free Software Foundation, Inc. + +This file is part of the GNU MP Library. + +The GNU MP Library is free software; you can redistribute it and/or modify +it under the terms of the GNU Library General Public License as published by +the Free Software Foundation; either version 2 of the License, or (at your +option) any later version. + +The GNU MP Library is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public +License for more details. + +You should have received a copy of the GNU Library General Public License +along with the GNU MP Library; see the file COPYING.LIB. If not, write to +the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, +MA 02111-1307, USA. */ + +#include "gmp.h" +#include "gmp-impl.h" + +int +#if __STDC__ +mpz_init_set_str (mpz_ptr x, const char *str, int base) +#else +mpz_init_set_str (x, str, base) + mpz_ptr x; + const char *str; + int base; +#endif +{ + x->_mp_alloc = 1; + x->_mp_d = (mp_ptr) (*_mp_allocate_func) (BYTES_PER_MP_LIMB); + + return mpz_set_str (x, str, base); +} diff --git a/contrib/libgmp/mpz/iset_ui.c b/contrib/libgmp/mpz/iset_ui.c new file mode 100644 index 0000000..dc39f59 --- /dev/null +++ b/contrib/libgmp/mpz/iset_ui.c @@ -0,0 +1,39 @@ +/* mpz_init_set_ui(val) -- Make a new multiple precision number with + value val. + +Copyright (C) 1991, 1993, 1994, 1995 Free Software Foundation, Inc. + +This file is part of the GNU MP Library. + +The GNU MP Library is free software; you can redistribute it and/or modify +it under the terms of the GNU Library General Public License as published by +the Free Software Foundation; either version 2 of the License, or (at your +option) any later version. + +The GNU MP Library is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public +License for more details. + +You should have received a copy of the GNU Library General Public License +along with the GNU MP Library; see the file COPYING.LIB. If not, write to +the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, +MA 02111-1307, USA. */ + +#include "gmp.h" +#include "gmp-impl.h" + +void +#if __STDC__ +mpz_init_set_ui (mpz_ptr x, unsigned long int val) +#else +mpz_init_set_ui (x, val) + mpz_ptr x; + unsigned long int val; +#endif +{ + x->_mp_alloc = 1; + x->_mp_d = (mp_ptr) (*_mp_allocate_func) (BYTES_PER_MP_LIMB); + x->_mp_d[0] = val; + x->_mp_size = val != 0; +} diff --git a/contrib/libgmp/mpz/jacobi.c b/contrib/libgmp/mpz/jacobi.c new file mode 100644 index 0000000..409f622 --- /dev/null +++ b/contrib/libgmp/mpz/jacobi.c @@ -0,0 +1,53 @@ +/* mpz_jacobi (op1, op2). + Contributed by Bennet Yee (bsy) at Carnegie-Mellon University + +Copyright (C) 1991, 1996 Free Software Foundation, Inc. + +This file is part of the GNU MP Library. + +The GNU MP Library is free software; you can redistribute it and/or modify +it under the terms of the GNU Library General Public License as published by +the Free Software Foundation; either version 2 of the License, or (at your +option) any later version. + +The GNU MP Library is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public +License for more details. + +You should have received a copy of the GNU Library General Public License +along with the GNU MP Library; see the file COPYING.LIB. If not, write to +the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, +MA 02111-1307, USA. */ + +#include "gmp.h" + +/* Precondition: both p and q are positive */ + +int +#if __STDC__ +mpz_jacobi (mpz_srcptr pi, mpz_srcptr qi) +#else +mpz_jacobi (pi, qi) + mpz_srcptr pi, qi; +#endif +{ +#if GCDCHECK + int retval; + mpz_t gcdval; + + mpz_init (gcdval); + mpz_gcd (gcdval, pi, qi); + if (!mpz_cmp_ui (gcdval, 1L)) + { + /* J(ab,cb) = J(ab,c)J(ab,b) = J(ab,c)J(0,b) = J(ab,c)*0 */ + retval = 0; + } + else + retval = mpz_legendre (pi, qi); + mpz_clear (gcdval); + return retval; +#else + return mpz_legendre (pi, qi); +#endif +} diff --git a/contrib/libgmp/mpz/legendre.c b/contrib/libgmp/mpz/legendre.c new file mode 100644 index 0000000..4de16a6 --- /dev/null +++ b/contrib/libgmp/mpz/legendre.c @@ -0,0 +1,184 @@ +/* mpz_legendre (op1, op2). + Contributed by Bennet Yee (bsy) at Carnegie-Mellon University + +Copyright (C) 1992, 1996 Free Software Foundation, Inc. + +This file is part of the GNU MP Library. + +The GNU MP Library is free software; you can redistribute it and/or modify +it under the terms of the GNU Library General Public License as published by +the Free Software Foundation; either version 2 of the License, or (at your +option) any later version. + +The GNU MP Library is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public +License for more details. + +You should have received a copy of the GNU Library General Public License +along with the GNU MP Library; see the file COPYING.LIB. If not, write to +the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, +MA 02111-1307, USA. */ + +#include "gmp.h" + +#if defined (DEBUG) +#include <stdio.h> +#endif + +/* Precondition: both p and q are positive */ + +int +#if __STDC__ +mpz_legendre (mpz_srcptr pi, mpz_srcptr qi) +#else +mpz_legendre (pi, qi) +mpz_srcptr pi, qi; +#endif +{ + mpz_t p, q, qdiv2; +#ifdef Q_MINUS_1 + mpz_t q_minus_1; +#endif + mpz_ptr mtmp; + register mpz_ptr pptr, qptr; + register int retval = 1; + register unsigned long int s; + + pptr = p; + mpz_init_set (pptr, pi); + qptr = q; + mpz_init_set (qptr, qi); + +#ifdef Q_MINUS_1 + mpz_init (q_minus_1); +#endif + mpz_init (qdiv2); + +tail_recurse2: +#ifdef DEBUG + printf ("tail_recurse2: p="); + mpz_out_str (stdout, 10, pptr); + printf ("\nq="); + mpz_out_str (stdout, 10, qptr); + putchar ('\n'); +#endif + s = mpz_scan1 (qptr, 0); + if (s) mpz_tdiv_q_2exp (qptr, qptr, s); /* J(a,2) = 1 */ +#ifdef DEBUG + printf ("2 factor decomposition: p="); + mpz_out_str (stdout, 10, pptr); + printf ("\nq="); + mpz_out_str (stdout, 10, qptr); + putchar ('\n'); +#endif + /* postcondition q odd */ + if (!mpz_cmp_ui (qptr, 1L)) /* J(a,1) = 1 */ + goto done; + mpz_mod (pptr, pptr, qptr); /* J(a,q) = J(b,q) when a == b mod q */ +#ifdef DEBUG + printf ("mod out by q: p="); + mpz_out_str (stdout, 10, pptr); + printf ("\nq="); + mpz_out_str (stdout, 10, qptr); + putchar ('\n'); +#endif + /* quick calculation to get approximate size first */ + /* precondition: p < q */ + if ((mpz_sizeinbase (pptr, 2) + 1 >= mpz_sizeinbase (qptr,2)) + && (mpz_tdiv_q_2exp (qdiv2, qptr, 1L), mpz_cmp (pptr, qdiv2) > 0)) + { + /* p > q/2 */ + mpz_sub (pptr, qptr, pptr); + /* J(-1,q) = (-1)^((q-1)/2), q odd */ + if (mpz_get_ui (qptr) & 2) + retval = -retval; + } + /* p < q/2 */ +#ifdef Q_MINUS_1 + mpz_sub_ui (q_minus_q, qptr, 1L); +#endif +tail_recurse: /* we use tail_recurse only if q has not changed */ +#ifdef DEBUG + printf ("tail_recurse1: p="); + mpz_out_str (stdout, 10, pptr); + printf ("\nq="); + mpz_out_str (stdout, 10, qptr); + putchar ('\n'); +#endif + /* + * J(0,q) = 0 + * this occurs only if gcd(p,q) != 1 which is never true for + * Legendre function. + */ + if (!mpz_cmp_ui (pptr, 0L)) + { + retval = 0; + goto done; + } + + if (!mpz_cmp_ui (pptr, 1L)) + { + /* J(1,q) = 1 */ + /* retval *= 1; */ + goto done; + } +#ifdef Q_MINUS_1 + if (!mpz_cmp (pptr, q_minus_1)) + { + /* J(-1,q) = (-1)^((q-1)/2) */ + if (mpz_get_ui (qptr) & 2) + retval = -retval; + /* else retval *= 1; */ + goto done; + } +#endif + /* + * we do not handle J(xy,q) except for x==2 + * since we do not want to factor + */ + if ((s = mpz_scan1 (pptr, 0)) != 0) + { + /* + * J(2,q) = (-1)^((q^2-1)/8) + * + * Note that q odd guarantees that q^2-1 is divisible by 8: + * Let a: q=2a+1. q^2 = 4a^2+4a+1, (q^2-1)/8 = a(a+1)/2, qed + * + * Now, note that this means that the low two bits of _a_ + * (or the low bits of q shifted over by 1 determines + * the factor). + */ + mpz_tdiv_q_2exp (pptr, pptr, s); + + /* even powers of 2 gives J(2,q)^{2n} = 1 */ + if (s & 1) + { + s = mpz_get_ui (qptr) >> 1; + s = s * (s + 1); + if (s & 2) + retval = -retval; + } + goto tail_recurse; + } + /* + * we know p is odd since we have cast out 2s + * precondition that q is odd guarantees both odd. + * + * quadratic reciprocity + * J(p,q) = (-1)^((p-1)(q-1)/4) * J(q,p) + */ + if ((s = mpz_scan1 (pptr, 1)) <= 2 && (s + mpz_scan1 (qptr, 1)) <= 2) + retval = -retval; + + mtmp = pptr; pptr = qptr; qptr = mtmp; + goto tail_recurse2; +done: + mpz_clear (p); + mpz_clear (q); + mpz_clear (qdiv2); +#ifdef Q_MINUS_1 + mpz_clear (q_minus_1); +#endif + return retval; +} diff --git a/contrib/libgmp/mpz/mod.c b/contrib/libgmp/mpz/mod.c new file mode 100644 index 0000000..b2b8b39 --- /dev/null +++ b/contrib/libgmp/mpz/mod.c @@ -0,0 +1,63 @@ +/* mpz_mod -- The mathematical mod function. + +Copyright (C) 1991, 1993, 1994, 1995, 1996 Free Software Foundation, Inc. + +This file is part of the GNU MP Library. + +The GNU MP Library is free software; you can redistribute it and/or modify +it under the terms of the GNU Library General Public License as published by +the Free Software Foundation; either version 2 of the License, or (at your +option) any later version. + +The GNU MP Library is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public +License for more details. + +You should have received a copy of the GNU Library General Public License +along with the GNU MP Library; see the file COPYING.LIB. If not, write to +the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, +MA 02111-1307, USA. */ + +#include "gmp.h" +#include "gmp-impl.h" + +void +#if __STDC__ +mpz_mod (mpz_ptr rem, mpz_srcptr dividend, mpz_srcptr divisor) +#else +mpz_mod (rem, dividend, divisor) + mpz_ptr rem; + mpz_srcptr dividend; + mpz_srcptr divisor; +#endif +{ + mp_size_t divisor_size = divisor->_mp_size; + mpz_t temp_divisor; /* N.B.: lives until function returns! */ + TMP_DECL (marker); + + TMP_MARK (marker); + + /* We need the original value of the divisor after the remainder has been + preliminary calculated. We have to copy it to temporary space if it's + the same variable as REM. */ + if (rem == divisor) + { + MPZ_TMP_INIT (temp_divisor, ABS (divisor_size)); + mpz_set (temp_divisor, divisor); + divisor = temp_divisor; + } + + mpz_tdiv_r (rem, dividend, divisor); + + if (rem->_mp_size != 0) + { + if (dividend->_mp_size < 0) + if (divisor->_mp_size < 0) + mpz_sub (rem, rem, divisor); + else + mpz_add (rem, rem, divisor); + } + + TMP_FREE (marker); +} diff --git a/contrib/libgmp/mpz/mul.c b/contrib/libgmp/mpz/mul.c new file mode 100644 index 0000000..47ce8e3 --- /dev/null +++ b/contrib/libgmp/mpz/mul.c @@ -0,0 +1,127 @@ +/* mpz_mul -- Multiply two integers. + +Copyright (C) 1991, 1993, 1994, 1996 Free Software Foundation, Inc. + +This file is part of the GNU MP Library. + +The GNU MP Library is free software; you can redistribute it and/or modify +it under the terms of the GNU Library General Public License as published by +the Free Software Foundation; either version 2 of the License, or (at your +option) any later version. + +The GNU MP Library is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public +License for more details. + +You should have received a copy of the GNU Library General Public License +along with the GNU MP Library; see the file COPYING.LIB. If not, write to +the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, +MA 02111-1307, USA. */ + +#include "gmp.h" +#include "gmp-impl.h" + +#ifndef BERKELEY_MP +void +#if __STDC__ +mpz_mul (mpz_ptr w, mpz_srcptr u, mpz_srcptr v) +#else +mpz_mul (w, u, v) + mpz_ptr w; + mpz_srcptr u; + mpz_srcptr v; +#endif +#else /* BERKELEY_MP */ +void +#if __STDC__ +mult (mpz_srcptr u, mpz_srcptr v, mpz_ptr w) +#else +mult (u, v, w) + mpz_srcptr u; + mpz_srcptr v; + mpz_ptr w; +#endif +#endif /* BERKELEY_MP */ +{ + mp_size_t usize = u->_mp_size; + mp_size_t vsize = v->_mp_size; + mp_size_t wsize; + mp_size_t sign_product; + mp_ptr up, vp; + mp_ptr wp; + mp_ptr free_me = NULL; + size_t free_me_size; + mp_limb_t cy_limb; + TMP_DECL (marker); + + TMP_MARK (marker); + sign_product = usize ^ vsize; + usize = ABS (usize); + vsize = ABS (vsize); + + if (usize < vsize) + { + /* Swap U and V. */ + {const __mpz_struct *t = u; u = v; v = t;} + {mp_size_t t = usize; usize = vsize; vsize = t;} + } + + up = u->_mp_d; + vp = v->_mp_d; + wp = w->_mp_d; + + /* Ensure W has space enough to store the result. */ + wsize = usize + vsize; + if (w->_mp_alloc < wsize) + { + if (wp == up || wp == vp) + { + free_me = wp; + free_me_size = w->_mp_alloc; + } + else + (*_mp_free_func) (wp, w->_mp_alloc * BYTES_PER_MP_LIMB); + + w->_mp_alloc = wsize; + wp = (mp_ptr) (*_mp_allocate_func) (wsize * BYTES_PER_MP_LIMB); + w->_mp_d = wp; + } + else + { + /* Make U and V not overlap with W. */ + if (wp == up) + { + /* W and U are identical. Allocate temporary space for U. */ + up = (mp_ptr) TMP_ALLOC (usize * BYTES_PER_MP_LIMB); + /* Is V identical too? Keep it identical with U. */ + if (wp == vp) + vp = up; + /* Copy to the temporary space. */ + MPN_COPY (up, wp, usize); + } + else if (wp == vp) + { + /* W and V are identical. Allocate temporary space for V. */ + vp = (mp_ptr) TMP_ALLOC (vsize * BYTES_PER_MP_LIMB); + /* Copy to the temporary space. */ + MPN_COPY (vp, wp, vsize); + } + } + + if (vsize == 0) + { + wsize = 0; + } + else + { + cy_limb = mpn_mul (wp, up, usize, vp, vsize); + wsize = usize + vsize; + wsize -= cy_limb == 0; + } + + w->_mp_size = sign_product < 0 ? -wsize : wsize; + if (free_me != NULL) + (*_mp_free_func) (free_me, free_me_size * BYTES_PER_MP_LIMB); + TMP_FREE (marker); +} diff --git a/contrib/libgmp/mpz/mul_2exp.c b/contrib/libgmp/mpz/mul_2exp.c new file mode 100644 index 0000000..4d66a98 --- /dev/null +++ b/contrib/libgmp/mpz/mul_2exp.c @@ -0,0 +1,76 @@ +/* mpz_mul_2exp -- Multiply a bignum by 2**CNT + +Copyright (C) 1991, 1993, 1994, 1996 Free Software Foundation, Inc. + +This file is part of the GNU MP Library. + +The GNU MP Library is free software; you can redistribute it and/or modify +it under the terms of the GNU Library General Public License as published by +the Free Software Foundation; either version 2 of the License, or (at your +option) any later version. + +The GNU MP Library is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public +License for more details. + +You should have received a copy of the GNU Library General Public License +along with the GNU MP Library; see the file COPYING.LIB. If not, write to +the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, +MA 02111-1307, USA. */ + +#include "gmp.h" +#include "gmp-impl.h" + +void +#if __STDC__ +mpz_mul_2exp (mpz_ptr w, mpz_srcptr u, unsigned long int cnt) +#else +mpz_mul_2exp (w, u, cnt) + mpz_ptr w; + mpz_srcptr u; + unsigned long int cnt; +#endif +{ + mp_size_t usize = u->_mp_size; + mp_size_t abs_usize = ABS (usize); + mp_size_t wsize; + mp_size_t limb_cnt; + mp_ptr wp; + mp_limb_t wlimb; + + if (usize == 0) + { + w->_mp_size = 0; + return; + } + + limb_cnt = cnt / BITS_PER_MP_LIMB; + wsize = abs_usize + limb_cnt + 1; + if (w->_mp_alloc < wsize) + _mpz_realloc (w, wsize); + + wp = w->_mp_d; + wsize = abs_usize + limb_cnt; + + cnt %= BITS_PER_MP_LIMB; + if (cnt != 0) + { + wlimb = mpn_lshift (wp + limb_cnt, u->_mp_d, abs_usize, cnt); + if (wlimb != 0) + { + wp[wsize] = wlimb; + wsize++; + } + } + else + { + MPN_COPY_DECR (wp + limb_cnt, u->_mp_d, abs_usize); + } + + /* Zero all whole limbs at low end. Do it here and not before calling + mpn_lshift, not to lose for U == W. */ + MPN_ZERO (wp, limb_cnt); + + w->_mp_size = usize >= 0 ? wsize : -wsize; +} diff --git a/contrib/libgmp/mpz/mul_ui.c b/contrib/libgmp/mpz/mul_ui.c new file mode 100644 index 0000000..f1f7269 --- /dev/null +++ b/contrib/libgmp/mpz/mul_ui.c @@ -0,0 +1,64 @@ +/* mpz_mul_ui(product, multiplier, small_multiplicand) -- Set + PRODUCT to MULTIPLICATOR times SMALL_MULTIPLICAND. + +Copyright (C) 1991, 1993, 1994, 1996 Free Software Foundation, Inc. + +This file is part of the GNU MP Library. + +The GNU MP Library is free software; you can redistribute it and/or modify +it under the terms of the GNU Library General Public License as published by +the Free Software Foundation; either version 2 of the License, or (at your +option) any later version. + +The GNU MP Library is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public +License for more details. + +You should have received a copy of the GNU Library General Public License +along with the GNU MP Library; see the file COPYING.LIB. If not, write to +the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, +MA 02111-1307, USA. */ + +#include "gmp.h" +#include "gmp-impl.h" + +void +#if __STDC__ +mpz_mul_ui (mpz_ptr prod, mpz_srcptr mult, unsigned long int small_mult) +#else +mpz_mul_ui (prod, mult, small_mult) + mpz_ptr prod; + mpz_srcptr mult; + unsigned long int small_mult; +#endif +{ + mp_size_t size = mult->_mp_size; + mp_size_t sign_product = size; + mp_limb_t cy; + mp_size_t prod_size; + mp_ptr prod_ptr; + + size = ABS (size); + + if (size == 0 || small_mult == 0) + { + prod->_mp_size = 0; + return; + } + + prod_size = size + 1; + if (prod->_mp_alloc < prod_size) + _mpz_realloc (prod, prod_size); + + prod_ptr = prod->_mp_d; + + cy = mpn_mul_1 (prod_ptr, mult->_mp_d, size, (mp_limb_t) small_mult); + if (cy != 0) + { + prod_ptr[size] = cy; + size++; + } + + prod->_mp_size = sign_product >= 0 ? size : -size; +} diff --git a/contrib/libgmp/mpz/neg.c b/contrib/libgmp/mpz/neg.c new file mode 100644 index 0000000..0b48e5c --- /dev/null +++ b/contrib/libgmp/mpz/neg.c @@ -0,0 +1,53 @@ +/* mpz_neg(mpz_ptr dst, mpz_ptr src) -- Assign the negated value of SRC to DST. + +Copyright (C) 1991, 1993, 1994, 1995 Free Software Foundation, Inc. + +This file is part of the GNU MP Library. + +The GNU MP Library is free software; you can redistribute it and/or modify +it under the terms of the GNU Library General Public License as published by +the Free Software Foundation; either version 2 of the License, or (at your +option) any later version. + +The GNU MP Library is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public +License for more details. + +You should have received a copy of the GNU Library General Public License +along with the GNU MP Library; see the file COPYING.LIB. If not, write to +the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, +MA 02111-1307, USA. */ + +#include "gmp.h" +#include "gmp-impl.h" + +void +#if __STDC__ +mpz_neg (mpz_ptr w, mpz_srcptr u) +#else +mpz_neg (w, u) + mpz_ptr w; + mpz_srcptr u; +#endif +{ + mp_ptr wp, up; + mp_size_t usize, size; + + usize = u->_mp_size; + + if (u != w) + { + size = ABS (usize); + + if (w->_mp_alloc < size) + _mpz_realloc (w, size); + + wp = w->_mp_d; + up = u->_mp_d; + + MPN_COPY (wp, up, size); + } + + w->_mp_size = -usize; +} diff --git a/contrib/libgmp/mpz/out_raw.c b/contrib/libgmp/mpz/out_raw.c new file mode 100644 index 0000000..35d311b --- /dev/null +++ b/contrib/libgmp/mpz/out_raw.c @@ -0,0 +1,89 @@ +/* mpz_out_raw -- Output a mpz_t in binary. Use an endianess and word size + independent format. + +Copyright (C) 1995 Free Software Foundation, Inc. + +This file is part of the GNU MP Library. + +The GNU MP Library is free software; you can redistribute it and/or modify +it under the terms of the GNU Library General Public License as published by +the Free Software Foundation; either version 2 of the License, or (at your +option) any later version. + +The GNU MP Library is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public +License for more details. + +You should have received a copy of the GNU Library General Public License +along with the GNU MP Library; see the file COPYING.LIB. If not, write to +the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, +MA 02111-1307, USA. */ + +#include <stdio.h> + +#include "gmp.h" +#include "gmp-impl.h" + +size_t +#if __STDC__ +mpz_out_raw (FILE *stream, mpz_srcptr x) +#else +mpz_out_raw (stream, x) + FILE *stream; + mpz_srcptr x; +#endif +{ + int i; + mp_size_t s; + mp_size_t xsize = ABS (x->_mp_size); + mp_srcptr xp = x->_mp_d; + mp_size_t out_bytesize; + mp_limb_t hi_limb; + int n_bytes_in_hi_limb; + + if (stream == 0) + stream = stdout; + + if (xsize == 0) + { + for (i = 4 - 1; i >= 0; i--) + fputc (0, stream); + return ferror (stream) ? 0 : 4; + } + + hi_limb = xp[xsize - 1]; + for (i = BYTES_PER_MP_LIMB - 1; i > 0; i--) + { + if ((hi_limb >> i * BITS_PER_CHAR) != 0) + break; + } + n_bytes_in_hi_limb = i + 1; + out_bytesize = BYTES_PER_MP_LIMB * (xsize - 1) + n_bytes_in_hi_limb; + if (x->_mp_size < 0) + out_bytesize = -out_bytesize; + + /* Make the size 4 bytes on all machines, to make the format portable. */ + for (i = 4 - 1; i >= 0; i--) + fputc ((out_bytesize >> (i * BITS_PER_CHAR)) % (1 << BITS_PER_CHAR), + stream); + + /* Output from the most significant limb to the least significant limb, + with each limb also output in decreasing significance order. */ + + /* Output the most significant limb separately, since we will only + output some of its bytes. */ + for (i = n_bytes_in_hi_limb - 1; i >= 0; i--) + fputc ((hi_limb >> (i * BITS_PER_CHAR)) % (1 << BITS_PER_CHAR), stream); + + /* Output the remaining limbs. */ + for (s = xsize - 2; s >= 0; s--) + { + mp_limb_t x_limb; + + x_limb = xp[s]; + for (i = BYTES_PER_MP_LIMB - 1; i >= 0; i--) + fputc ((x_limb >> (i * BITS_PER_CHAR)) % (1 << BITS_PER_CHAR), stream); + } + return ferror (stream) ? 0 : ABS (out_bytesize) + 4; +} diff --git a/contrib/libgmp/mpz/out_str.c b/contrib/libgmp/mpz/out_str.c new file mode 100644 index 0000000..909f533 --- /dev/null +++ b/contrib/libgmp/mpz/out_str.c @@ -0,0 +1,108 @@ +/* mpz_out_str(stream, base, integer) -- Output to STREAM the multi prec. + integer INTEGER in base BASE. + +Copyright (C) 1991, 1993, 1994, 1996 Free Software Foundation, Inc. + +This file is part of the GNU MP Library. + +The GNU MP Library is free software; you can redistribute it and/or modify +it under the terms of the GNU Library General Public License as published by +the Free Software Foundation; either version 2 of the License, or (at your +option) any later version. + +The GNU MP Library is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public +License for more details. + +You should have received a copy of the GNU Library General Public License +along with the GNU MP Library; see the file COPYING.LIB. If not, write to +the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, +MA 02111-1307, USA. */ + +#include <stdio.h> +#include "gmp.h" +#include "gmp-impl.h" + +size_t +#if __STDC__ +mpz_out_str (FILE *stream, int base, mpz_srcptr x) +#else +mpz_out_str (stream, base, x) + FILE *stream; + int base; + mpz_srcptr x; +#endif +{ + mp_ptr xp; + mp_size_t x_size = x->_mp_size; + unsigned char *str; + size_t str_size; + size_t i; + size_t written; + char *num_to_text; + TMP_DECL (marker); + + if (stream == 0) + stream = stdout; + + if (base >= 0) + { + if (base == 0) + base = 10; + num_to_text = "0123456789abcdefghijklmnopqrstuvwxyz"; + } + else + { + base = -base; + num_to_text = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"; + } + + if (x_size == 0) + { + fputc ('0', stream); + return ferror (stream) ? 0 : 1; + } + + written = 0; + + if (x_size < 0) + { + fputc ('-', stream); + x_size = -x_size; + written = 1; + } + + TMP_MARK (marker); + str_size = ((size_t) (x_size * BITS_PER_MP_LIMB + * __mp_bases[base].chars_per_bit_exactly)) + 3; + str = (unsigned char *) TMP_ALLOC (str_size); + + /* Move the number to convert into temporary space, since mpn_get_str + clobbers its argument + needs one extra high limb.... */ + xp = (mp_ptr) TMP_ALLOC ((x_size + 1) * BYTES_PER_MP_LIMB); + MPN_COPY (xp, x->_mp_d, x_size); + + str_size = mpn_get_str (str, base, xp, x_size); + + /* mpn_get_str might make some leading zeros. Skip them. */ + while (*str == 0) + { + str_size--; + str++; + } + + /* Translate to printable chars. */ + for (i = 0; i < str_size; i++) + str[i] = num_to_text[str[i]]; + str[str_size] = 0; + + { + size_t fwret; + fwret = fwrite ((char *) str, 1, str_size, stream); + written += fwret; + } + + TMP_FREE (marker); + return ferror (stream) ? 0 : written; +} diff --git a/contrib/libgmp/mpz/perfsqr.c b/contrib/libgmp/mpz/perfsqr.c new file mode 100644 index 0000000..cdf1b5a --- /dev/null +++ b/contrib/libgmp/mpz/perfsqr.c @@ -0,0 +1,41 @@ +/* mpz_perfect_square_p(arg) -- Return non-zero if ARG is a perfect square, + zero otherwise. + +Copyright (C) 1991, 1993, 1994, 1996 Free Software Foundation, Inc. + +This file is part of the GNU MP Library. + +The GNU MP Library is free software; you can redistribute it and/or modify +it under the terms of the GNU Library General Public License as published by +the Free Software Foundation; either version 2 of the License, or (at your +option) any later version. + +The GNU MP Library is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public +License for more details. + +You should have received a copy of the GNU Library General Public License +along with the GNU MP Library; see the file COPYING.LIB. If not, write to +the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, +MA 02111-1307, USA. */ + +#include "gmp.h" +#include "gmp-impl.h" + +int +#if __STDC__ +mpz_perfect_square_p (mpz_srcptr a) +#else +mpz_perfect_square_p (a) + mpz_srcptr a; +#endif +{ + mp_size_t asize = a->_mp_size; + + /* No negative numbers are perfect squares. */ + if (asize < 0) + return 0; + + return mpn_perfect_square_p (a->_mp_d, asize); +} diff --git a/contrib/libgmp/mpz/popcount.c b/contrib/libgmp/mpz/popcount.c new file mode 100644 index 0000000..a979380 --- /dev/null +++ b/contrib/libgmp/mpz/popcount.c @@ -0,0 +1,42 @@ +/* mpz_popcount(mpz_ptr op) -- Population count of OP. If the operand is + negative, return ~0 (a novel representation of infinity). + +Copyright (C) 1994, 1996 Free Software Foundation, Inc. + +This file is part of the GNU MP Library. + +The GNU MP Library is free software; you can redistribute it and/or modify +it under the terms of the GNU Library General Public License as published by +the Free Software Foundation; either version 2 of the License, or (at your +option) any later version. + +The GNU MP Library is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public +License for more details. + +You should have received a copy of the GNU Library General Public License +along with the GNU MP Library; see the file COPYING.LIB. If not, write to +the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, +MA 02111-1307, USA. */ + +#include "gmp.h" +#include "gmp-impl.h" + +unsigned long int +#if __STDC__ +mpz_popcount (mpz_srcptr u) +#else +mpz_popcount (u) + mpz_srcptr u; +#endif +{ + mp_size_t usize; + + usize = u->_mp_size; + + if ((usize) < 0) + return ~ (unsigned long int) 0; + + return mpn_popcount (u->_mp_d, usize); +} diff --git a/contrib/libgmp/mpz/pow_ui.c b/contrib/libgmp/mpz/pow_ui.c new file mode 100644 index 0000000..d8cf7a6 --- /dev/null +++ b/contrib/libgmp/mpz/pow_ui.c @@ -0,0 +1,129 @@ +/* mpz_pow_ui(res, base, exp) -- Set RES to BASE**EXP. + +Copyright (C) 1991, 1993, 1994, 1996 Free Software Foundation, Inc. + +This file is part of the GNU MP Library. + +The GNU MP Library is free software; you can redistribute it and/or modify +it under the terms of the GNU Library General Public License as published by +the Free Software Foundation; either version 2 of the License, or (at your +option) any later version. + +The GNU MP Library is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public +License for more details. + +You should have received a copy of the GNU Library General Public License +along with the GNU MP Library; see the file COPYING.LIB. If not, write to +the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, +MA 02111-1307, USA. */ + +#ifdef BERKELEY_MP +#include "mp.h" +#endif +#include "gmp.h" +#include "gmp-impl.h" +#include "longlong.h" + +#ifndef BERKELEY_MP +void +#if __STDC__ +mpz_pow_ui (mpz_ptr r, mpz_srcptr b, unsigned long int e) +#else +mpz_pow_ui (r, b, e) + mpz_ptr r; + mpz_srcptr b; + unsigned long int e; +#endif +#else /* BERKELEY_MP */ +void +#if __STDC__ +rpow (const MINT *b, signed short int e, MINT *r) +#else +rpow (b, e, r) + const MINT *b; + signed short int e; + MINT *r; +#endif +#endif /* BERKELEY_MP */ +{ + mp_ptr rp, bp, tp, xp; + mp_size_t rsize, bsize; + int cnt, i; + mp_limb_t blimb; + TMP_DECL (marker); + + bsize = ABS (b->_mp_size); + + /* Single out cases that give result == 0 or 1. These tests are here + to simplify the general code below, not to optimize. */ + if (e == 0) + { + r->_mp_d[0] = 1; + r->_mp_size = 1; + return; + } + if (bsize == 0 +#ifdef BERKELEY_MP + || e < 0 +#endif + ) + { + r->_mp_size = 0; + return; + } + + bp = b->_mp_d; + + blimb = bp[bsize - 1]; + if (bsize == 1 && blimb < 0x100) + { + /* Estimate space requirements accurately. Using the code from the + `else' path would over-estimate space requirements wildly. */ + float lb = __mp_bases[blimb].chars_per_bit_exactly; + rsize = 2 + ((mp_size_t) (e / lb) / BITS_PER_MP_LIMB); + } + else + { + /* Over-estimate space requirements somewhat. */ + count_leading_zeros (cnt, blimb); + rsize = bsize * e - cnt * e / BITS_PER_MP_LIMB + 1; + } + + TMP_MARK (marker); + + /* The two areas are used to alternatingly hold the input and recieve the + product for mpn_mul. (This scheme is used to fulfill the requirements + of mpn_mul; that the product space may not be the same as any of the + input operands.) */ + rp = (mp_ptr) TMP_ALLOC (rsize * BYTES_PER_MP_LIMB); + tp = (mp_ptr) TMP_ALLOC (rsize * BYTES_PER_MP_LIMB); + + MPN_COPY (rp, bp, bsize); + rsize = bsize; + count_leading_zeros (cnt, e); + + for (i = BITS_PER_MP_LIMB - cnt - 2; i >= 0; i--) + { + mpn_mul_n (tp, rp, rp, rsize); + rsize = 2 * rsize; + rsize -= tp[rsize - 1] == 0; + xp = tp; tp = rp; rp = xp; + + if ((e & ((mp_limb_t) 1 << i)) != 0) + { + rsize = rsize + bsize - (mpn_mul (tp, rp, rsize, bp, bsize) == 0); + xp = tp; tp = rp; rp = xp; + } + } + + /* Now then we know the exact space requirements, reallocate if + necessary. */ + if (r->_mp_alloc < rsize) + _mpz_realloc (r, rsize); + + MPN_COPY (r->_mp_d, rp, rsize); + r->_mp_size = (e & 1) == 0 || b->_mp_size >= 0 ? rsize : -rsize; + TMP_FREE (marker); +} diff --git a/contrib/libgmp/mpz/powm.c b/contrib/libgmp/mpz/powm.c new file mode 100644 index 0000000..5dcd1b1 --- /dev/null +++ b/contrib/libgmp/mpz/powm.c @@ -0,0 +1,276 @@ +/* mpz_powm(res,base,exp,mod) -- Set RES to (base**exp) mod MOD. + +Copyright (C) 1991, 1993, 1994, 1996 Free Software Foundation, Inc. + +This file is part of the GNU MP Library. + +The GNU MP Library is free software; you can redistribute it and/or modify +it under the terms of the GNU Library General Public License as published by +the Free Software Foundation; either version 2 of the License, or (at your +option) any later version. + +The GNU MP Library is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public +License for more details. + +You should have received a copy of the GNU Library General Public License +along with the GNU MP Library; see the file COPYING.LIB. If not, write to +the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, +MA 02111-1307, USA. */ + +#include "gmp.h" +#include "gmp-impl.h" +#include "longlong.h" + +#ifndef BERKELEY_MP +void +#if __STDC__ +mpz_powm (mpz_ptr res, mpz_srcptr base, mpz_srcptr exp, mpz_srcptr mod) +#else +mpz_powm (res, base, exp, mod) + mpz_ptr res; + mpz_srcptr base; + mpz_srcptr exp; + mpz_srcptr mod; +#endif +#else /* BERKELEY_MP */ +void +#if __STDC__ +pow (mpz_srcptr base, mpz_srcptr exp, mpz_srcptr mod, mpz_ptr res) +#else +pow (base, exp, mod, res) + mpz_srcptr base; + mpz_srcptr exp; + mpz_srcptr mod; + mpz_ptr res; +#endif +#endif /* BERKELEY_MP */ +{ + mp_ptr rp, ep, mp, bp; + mp_size_t esize, msize, bsize, rsize; + mp_size_t size; + int mod_shift_cnt; + int negative_result; + mp_limb_t *free_me = NULL; + size_t free_me_size; + TMP_DECL (marker); + + esize = ABS (exp->_mp_size); + msize = ABS (mod->_mp_size); + size = 2 * msize; + + rp = res->_mp_d; + ep = exp->_mp_d; + + if (msize == 0) + msize = 1 / msize; /* provoke a signal */ + + if (esize == 0) + { + /* Exponent is zero, result is 1 mod MOD, i.e., 1 or 0 + depending on if MOD equals 1. */ + rp[0] = 1; + res->_mp_size = (msize == 1 && (mod->_mp_d)[0] == 1) ? 0 : 1; + return; + } + + TMP_MARK (marker); + + /* Normalize MOD (i.e. make its most significant bit set) as required by + mpn_divmod. This will make the intermediate values in the calculation + slightly larger, but the correct result is obtained after a final + reduction using the original MOD value. */ + + mp = (mp_ptr) TMP_ALLOC (msize * BYTES_PER_MP_LIMB); + count_leading_zeros (mod_shift_cnt, mod->_mp_d[msize - 1]); + if (mod_shift_cnt != 0) + mpn_lshift (mp, mod->_mp_d, msize, mod_shift_cnt); + else + MPN_COPY (mp, mod->_mp_d, msize); + + bsize = ABS (base->_mp_size); + if (bsize > msize) + { + /* The base is larger than the module. Reduce it. */ + + /* Allocate (BSIZE + 1) with space for remainder and quotient. + (The quotient is (bsize - msize + 1) limbs.) */ + bp = (mp_ptr) TMP_ALLOC ((bsize + 1) * BYTES_PER_MP_LIMB); + MPN_COPY (bp, base->_mp_d, bsize); + /* We don't care about the quotient, store it above the remainder, + at BP + MSIZE. */ + mpn_divmod (bp + msize, bp, bsize, mp, msize); + bsize = msize; + /* Canonicalize the base, since we are going to multiply with it + quite a few times. */ + MPN_NORMALIZE (bp, bsize); + } + else + bp = base->_mp_d; + + if (bsize == 0) + { + res->_mp_size = 0; + TMP_FREE (marker); + return; + } + + if (res->_mp_alloc < size) + { + /* We have to allocate more space for RES. If any of the input + parameters are identical to RES, defer deallocation of the old + space. */ + + if (rp == ep || rp == mp || rp == bp) + { + free_me = rp; + free_me_size = res->_mp_alloc; + } + else + (*_mp_free_func) (rp, res->_mp_alloc * BYTES_PER_MP_LIMB); + + rp = (mp_ptr) (*_mp_allocate_func) (size * BYTES_PER_MP_LIMB); + res->_mp_alloc = size; + res->_mp_d = rp; + } + else + { + /* Make BASE, EXP and MOD not overlap with RES. */ + if (rp == bp) + { + /* RES and BASE are identical. Allocate temp. space for BASE. */ + bp = (mp_ptr) TMP_ALLOC (bsize * BYTES_PER_MP_LIMB); + MPN_COPY (bp, rp, bsize); + } + if (rp == ep) + { + /* RES and EXP are identical. Allocate temp. space for EXP. */ + ep = (mp_ptr) TMP_ALLOC (esize * BYTES_PER_MP_LIMB); + MPN_COPY (ep, rp, esize); + } + if (rp == mp) + { + /* RES and MOD are identical. Allocate temporary space for MOD. */ + mp = (mp_ptr) TMP_ALLOC (msize * BYTES_PER_MP_LIMB); + MPN_COPY (mp, rp, msize); + } + } + + MPN_COPY (rp, bp, bsize); + rsize = bsize; + + { + mp_size_t i; + mp_ptr xp = (mp_ptr) TMP_ALLOC (2 * (msize + 1) * BYTES_PER_MP_LIMB); + int c; + mp_limb_t e; + mp_limb_t carry_limb; + + negative_result = (ep[0] & 1) && base->_mp_size < 0; + + i = esize - 1; + e = ep[i]; + count_leading_zeros (c, e); + e = (e << c) << 1; /* shift the exp bits to the left, lose msb */ + c = BITS_PER_MP_LIMB - 1 - c; + + /* Main loop. + + Make the result be pointed to alternately by XP and RP. This + helps us avoid block copying, which would otherwise be necessary + with the overlap restrictions of mpn_divmod. With 50% probability + the result after this loop will be in the area originally pointed + by RP (==RES->_mp_d), and with 50% probability in the area originally + pointed to by XP. */ + + for (;;) + { + while (c != 0) + { + mp_ptr tp; + mp_size_t xsize; + + mpn_mul_n (xp, rp, rp, rsize); + xsize = 2 * rsize; + if (xsize > msize) + { + mpn_divmod (xp + msize, xp, xsize, mp, msize); + xsize = msize; + } + + tp = rp; rp = xp; xp = tp; + rsize = xsize; + + if ((mp_limb_signed_t) e < 0) + { + mpn_mul (xp, rp, rsize, bp, bsize); + xsize = rsize + bsize; + if (xsize > msize) + { + mpn_divmod (xp + msize, xp, xsize, mp, msize); + xsize = msize; + } + + tp = rp; rp = xp; xp = tp; + rsize = xsize; + } + e <<= 1; + c--; + } + + i--; + if (i < 0) + break; + e = ep[i]; + c = BITS_PER_MP_LIMB; + } + + /* We shifted MOD, the modulo reduction argument, left MOD_SHIFT_CNT + steps. Adjust the result by reducing it with the original MOD. + + Also make sure the result is put in RES->_mp_d (where it already + might be, see above). */ + + if (mod_shift_cnt != 0) + { + carry_limb = mpn_lshift (res->_mp_d, rp, rsize, mod_shift_cnt); + rp = res->_mp_d; + if (carry_limb != 0) + { + rp[rsize] = carry_limb; + rsize++; + } + } + else + { + MPN_COPY (res->_mp_d, rp, rsize); + rp = res->_mp_d; + } + + if (rsize >= msize) + { + mpn_divmod (rp + msize, rp, rsize, mp, msize); + rsize = msize; + } + + /* Remove any leading zero words from the result. */ + if (mod_shift_cnt != 0) + mpn_rshift (rp, rp, rsize, mod_shift_cnt); + MPN_NORMALIZE (rp, rsize); + } + + if (negative_result && rsize != 0) + { + if (mod_shift_cnt != 0) + mpn_rshift (mp, mp, msize, mod_shift_cnt); + mpn_sub (rp, mp, msize, rp, rsize); + rsize = msize; + MPN_NORMALIZE (rp, rsize); + } + res->_mp_size = rsize; + + if (free_me != NULL) + (*_mp_free_func) (free_me, free_me_size * BYTES_PER_MP_LIMB); + TMP_FREE (marker); +} diff --git a/contrib/libgmp/mpz/powm_ui.c b/contrib/libgmp/mpz/powm_ui.c new file mode 100644 index 0000000..596815a --- /dev/null +++ b/contrib/libgmp/mpz/powm_ui.c @@ -0,0 +1,234 @@ +/* mpz_powm_ui(res,base,exp,mod) -- Set RES to (base**exp) mod MOD. + +Copyright (C) 1991, 1993, 1994, 1996 Free Software Foundation, Inc. + +This file is part of the GNU MP Library. + +The GNU MP Library is free software; you can redistribute it and/or modify +it under the terms of the GNU Library General Public License as published by +the Free Software Foundation; either version 2 of the License, or (at your +option) any later version. + +The GNU MP Library is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public +License for more details. + +You should have received a copy of the GNU Library General Public License +along with the GNU MP Library; see the file COPYING.LIB. If not, write to +the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, +MA 02111-1307, USA. */ + +#include "gmp.h" +#include "gmp-impl.h" +#include "longlong.h" + +void +#if __STDC__ +mpz_powm_ui (mpz_ptr res, mpz_srcptr base, unsigned long int exp, mpz_srcptr mod) +#else +mpz_powm_ui (res, base, exp, mod) + mpz_ptr res; + mpz_srcptr base; + unsigned long int exp; + mpz_srcptr mod; +#endif +{ + mp_ptr rp, mp, bp; + mp_size_t msize, bsize, rsize; + mp_size_t size; + int mod_shift_cnt; + int negative_result; + mp_limb_t *free_me = NULL; + size_t free_me_size; + TMP_DECL (marker); + + msize = ABS (mod->_mp_size); + size = 2 * msize; + + rp = res->_mp_d; + + if (msize == 0) + msize = 1 / msize; /* provoke a signal */ + + if (exp == 0) + { + rp[0] = 1; + res->_mp_size = (msize == 1 && (mod->_mp_d)[0] == 1) ? 0 : 1; + return; + } + + TMP_MARK (marker); + + /* Normalize MOD (i.e. make its most significant bit set) as required by + mpn_divmod. This will make the intermediate values in the calculation + slightly larger, but the correct result is obtained after a final + reduction using the original MOD value. */ + + mp = (mp_ptr) TMP_ALLOC (msize * BYTES_PER_MP_LIMB); + count_leading_zeros (mod_shift_cnt, mod->_mp_d[msize - 1]); + if (mod_shift_cnt != 0) + mpn_lshift (mp, mod->_mp_d, msize, mod_shift_cnt); + else + MPN_COPY (mp, mod->_mp_d, msize); + + bsize = ABS (base->_mp_size); + if (bsize > msize) + { + /* The base is larger than the module. Reduce it. */ + + /* Allocate (BSIZE + 1) with space for remainder and quotient. + (The quotient is (bsize - msize + 1) limbs.) */ + bp = (mp_ptr) TMP_ALLOC ((bsize + 1) * BYTES_PER_MP_LIMB); + MPN_COPY (bp, base->_mp_d, bsize); + /* We don't care about the quotient, store it above the remainder, + at BP + MSIZE. */ + mpn_divmod (bp + msize, bp, bsize, mp, msize); + bsize = msize; + /* Canonicalize the base, since we are going to multiply with it + quite a few times. */ + MPN_NORMALIZE (bp, bsize); + } + else + bp = base->_mp_d; + + if (bsize == 0) + { + res->_mp_size = 0; + TMP_FREE (marker); + return; + } + + if (res->_mp_alloc < size) + { + /* We have to allocate more space for RES. If any of the input + parameters are identical to RES, defer deallocation of the old + space. */ + + if (rp == mp || rp == bp) + { + free_me = rp; + free_me_size = res->_mp_alloc; + } + else + (*_mp_free_func) (rp, res->_mp_alloc * BYTES_PER_MP_LIMB); + + rp = (mp_ptr) (*_mp_allocate_func) (size * BYTES_PER_MP_LIMB); + res->_mp_alloc = size; + res->_mp_d = rp; + } + else + { + /* Make BASE, EXP and MOD not overlap with RES. */ + if (rp == bp) + { + /* RES and BASE are identical. Allocate temp. space for BASE. */ + bp = (mp_ptr) TMP_ALLOC (bsize * BYTES_PER_MP_LIMB); + MPN_COPY (bp, rp, bsize); + } + if (rp == mp) + { + /* RES and MOD are identical. Allocate temporary space for MOD. */ + mp = (mp_ptr) TMP_ALLOC (msize * BYTES_PER_MP_LIMB); + MPN_COPY (mp, rp, msize); + } + } + + MPN_COPY (rp, bp, bsize); + rsize = bsize; + + { + mp_ptr xp = (mp_ptr) TMP_ALLOC (2 * (msize + 1) * BYTES_PER_MP_LIMB); + int c; + mp_limb_t e; + mp_limb_t carry_limb; + + negative_result = (exp & 1) && base->_mp_size < 0; + + e = exp; + count_leading_zeros (c, e); + e = (e << c) << 1; /* shift the exp bits to the left, lose msb */ + c = BITS_PER_MP_LIMB - 1 - c; + + /* Main loop. + + Make the result be pointed to alternately by XP and RP. This + helps us avoid block copying, which would otherwise be necessary + with the overlap restrictions of mpn_divmod. With 50% probability + the result after this loop will be in the area originally pointed + by RP (==RES->_mp_d), and with 50% probability in the area originally + pointed to by XP. */ + + while (c != 0) + { + mp_ptr tp; + mp_size_t xsize; + + mpn_mul_n (xp, rp, rp, rsize); + xsize = 2 * rsize; + if (xsize > msize) + { + mpn_divmod (xp + msize, xp, xsize, mp, msize); + xsize = msize; + } + + tp = rp; rp = xp; xp = tp; + rsize = xsize; + + if ((mp_limb_signed_t) e < 0) + { + mpn_mul (xp, rp, rsize, bp, bsize); + xsize = rsize + bsize; + if (xsize > msize) + { + mpn_divmod (xp + msize, xp, xsize, mp, msize); + xsize = msize; + } + + tp = rp; rp = xp; xp = tp; + rsize = xsize; + } + e <<= 1; + c--; + } + + /* We shifted MOD, the modulo reduction argument, left MOD_SHIFT_CNT + steps. Adjust the result by reducing it with the original MOD. + + Also make sure the result is put in RES->_mp_d (where it already + might be, see above). */ + + if (mod_shift_cnt != 0) + { + carry_limb = mpn_lshift (res->_mp_d, rp, rsize, mod_shift_cnt); + rp = res->_mp_d; + if (carry_limb != 0) + { + rp[rsize] = carry_limb; + rsize++; + } + } + else + { + MPN_COPY (res->_mp_d, rp, rsize); + rp = res->_mp_d; + } + + if (rsize >= msize) + { + mpn_divmod (rp + msize, rp, rsize, mp, msize); + rsize = msize; + } + + /* Remove any leading zero words from the result. */ + if (mod_shift_cnt != 0) + mpn_rshift (rp, rp, rsize, mod_shift_cnt); + MPN_NORMALIZE (rp, rsize); + } + + res->_mp_size = negative_result == 0 ? rsize : -rsize; + + if (free_me != NULL) + (*_mp_free_func) (free_me, free_me_size * BYTES_PER_MP_LIMB); + TMP_FREE (marker); +} diff --git a/contrib/libgmp/mpz/pprime_p.c b/contrib/libgmp/mpz/pprime_p.c new file mode 100644 index 0000000..494de14 --- /dev/null +++ b/contrib/libgmp/mpz/pprime_p.c @@ -0,0 +1,115 @@ +/* mpz_probab_prime_p -- + An implementation of the probabilistic primality test found in Knuth's + Seminumerical Algorithms book. If the function mpz_probab_prime_p() + returns 0 then n is not prime. If it returns 1, then n is 'probably' + prime. The probability of a false positive is (1/4)**reps, where + reps is the number of internal passes of the probabilistic algorithm. + Knuth indicates that 25 passes are reasonable. + +Copyright (C) 1991, 1993, 1994 Free Software Foundation, Inc. +Contributed by John Amanatides. + +This file is part of the GNU MP Library. + +The GNU MP Library is free software; you can redistribute it and/or modify +it under the terms of the GNU Library General Public License as published by +the Free Software Foundation; either version 2 of the License, or (at your +option) any later version. + +The GNU MP Library is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public +License for more details. + +You should have received a copy of the GNU Library General Public License +along with the GNU MP Library; see the file COPYING.LIB. If not, write to +the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, +MA 02111-1307, USA. */ + +#include "gmp.h" + +static int +possibly_prime (n, n_minus_1, x, y, q, k) + mpz_srcptr n; + mpz_srcptr n_minus_1; + mpz_ptr x; + mpz_ptr y; + mpz_srcptr q; + unsigned long int k; +{ + unsigned long int i; + + /* find random x s.t. 1 < x < n */ + do + { + mpz_random (x, mpz_size (n)); + mpz_mmod (x, x, n); + } + while (mpz_cmp_ui (x, 1L) <= 0); + + mpz_powm (y, x, q, n); + + if (mpz_cmp_ui (y, 1L) == 0 || mpz_cmp (y, n_minus_1) == 0) + return 1; + + for (i = 1; i < k; i++) + { + mpz_powm_ui (y, y, 2L, n); + if (mpz_cmp (y, n_minus_1) == 0) + return 1; + if (mpz_cmp_ui (y, 1L) == 0) + return 0; + } + return 0; +} + +int +#if __STDC__ +mpz_probab_prime_p (mpz_srcptr m, int reps) +#else +mpz_probab_prime_p (m, reps) + mpz_srcptr m; + int reps; +#endif +{ + mpz_t n, n_minus_1, x, y, q; + int i, is_prime; + unsigned long int k; + + mpz_init (n); + /* Take the absolute value of M, to handle positive and negative primes. */ + mpz_abs (n, m); + + if (mpz_cmp_ui (n, 3L) <= 0) + { + mpz_clear (n); + return mpz_cmp_ui (n, 1L) > 0; + } + + if ((mpz_get_ui (n) & 1) == 0) + { + mpz_clear (n); + return 0; /* even */ + } + + mpz_init (n_minus_1); + mpz_sub_ui (n_minus_1, n, 1L); + mpz_init (x); + mpz_init (y); + + /* find q and k, s.t. n = 1 + 2**k * q */ + mpz_init_set (q, n_minus_1); + k = mpz_scan1 (q, 0); + mpz_tdiv_q_2exp (q, q, k); + + is_prime = 1; + for (i = 0; i < reps && is_prime; i++) + is_prime &= possibly_prime (n, n_minus_1, x, y, q, k); + + mpz_clear (n_minus_1); + mpz_clear (n); + mpz_clear (x); + mpz_clear (y); + mpz_clear (q); + return is_prime; +} diff --git a/contrib/libgmp/mpz/random.c b/contrib/libgmp/mpz/random.c new file mode 100644 index 0000000..ab41eef --- /dev/null +++ b/contrib/libgmp/mpz/random.c @@ -0,0 +1,56 @@ +/* mpz_random -- Generate a random mpz_t of specified size. + This function is non-portable and generates poor random numbers. + +Copyright (C) 1991, 1993, 1994, 1995 Free Software Foundation, Inc. + +This file is part of the GNU MP Library. + +The GNU MP Library is free software; you can redistribute it and/or modify +it under the terms of the GNU Library General Public License as published by +the Free Software Foundation; either version 2 of the License, or (at your +option) any later version. + +The GNU MP Library is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public +License for more details. + +You should have received a copy of the GNU Library General Public License +along with the GNU MP Library; see the file COPYING.LIB. If not, write to +the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, +MA 02111-1307, USA. */ + +#include "gmp.h" +#include "gmp-impl.h" +#include "urandom.h" + +void +#if __STDC__ +mpz_random (mpz_ptr x, mp_size_t size) +#else +mpz_random (x, size) + mpz_ptr x; + mp_size_t size; +#endif +{ + mp_size_t i; + mp_limb_t ran; + mp_ptr xp; + mp_size_t abs_size; + + abs_size = ABS (size); + + if (x->_mp_alloc < abs_size) + _mpz_realloc (x, abs_size); + + xp = x->_mp_d; + + for (i = 0; i < abs_size; i++) + { + ran = urandom (); + xp[i] = ran; + } + + MPN_NORMALIZE (xp, abs_size); + x->_mp_size = size < 0 ? -abs_size : abs_size; +} diff --git a/contrib/libgmp/mpz/random2.c b/contrib/libgmp/mpz/random2.c new file mode 100644 index 0000000..725a8b4 --- /dev/null +++ b/contrib/libgmp/mpz/random2.c @@ -0,0 +1,48 @@ +/* mpz_random2 -- Generate a positive random mpz_t of specified size, with + long runs of consecutive ones and zeros in the binary representation. + Meant for testing of other MP routines. + +Copyright (C) 1991, 1993, 1994, 1996 Free Software Foundation, Inc. + +This file is part of the GNU MP Library. + +The GNU MP Library is free software; you can redistribute it and/or modify +it under the terms of the GNU Library General Public License as published by +the Free Software Foundation; either version 2 of the License, or (at your +option) any later version. + +The GNU MP Library is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public +License for more details. + +You should have received a copy of the GNU Library General Public License +along with the GNU MP Library; see the file COPYING.LIB. If not, write to +the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, +MA 02111-1307, USA. */ + +#include "gmp.h" +#include "gmp-impl.h" + +void +#if __STDC__ +mpz_random2 (mpz_ptr x, mp_size_t size) +#else +mpz_random2 (x, size) + mpz_ptr x; + mp_size_t size; +#endif +{ + mp_size_t abs_size; + + abs_size = ABS (size); + if (abs_size != 0) + { + if (x->_mp_alloc < abs_size) + _mpz_realloc (x, abs_size); + + mpn_random2 (x->_mp_d, abs_size); + } + + x->_mp_size = size; +} diff --git a/contrib/libgmp/mpz/realloc.c b/contrib/libgmp/mpz/realloc.c new file mode 100644 index 0000000..2c2a5da --- /dev/null +++ b/contrib/libgmp/mpz/realloc.c @@ -0,0 +1,52 @@ +/* _mpz_realloc -- make the mpz_t have NEW_SIZE digits allocated. + +Copyright (C) 1991, 1993, 1994, 1995 Free Software Foundation, Inc. + +This file is part of the GNU MP Library. + +The GNU MP Library is free software; you can redistribute it and/or modify +it under the terms of the GNU Library General Public License as published by +the Free Software Foundation; either version 2 of the License, or (at your +option) any later version. + +The GNU MP Library is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public +License for more details. + +You should have received a copy of the GNU Library General Public License +along with the GNU MP Library; see the file COPYING.LIB. If not, write to +the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, +MA 02111-1307, USA. */ + +#include "gmp.h" +#include "gmp-impl.h" + +void * +#if __STDC__ +_mpz_realloc (mpz_ptr m, mp_size_t new_size) +#else +_mpz_realloc (m, new_size) + mpz_ptr m; + mp_size_t new_size; +#endif +{ + /* Never allocate zero space. */ + if (new_size == 0) + new_size = 1; + + m->_mp_d = (mp_ptr) (*_mp_reallocate_func) (m->_mp_d, + m->_mp_alloc * BYTES_PER_MP_LIMB, + new_size * BYTES_PER_MP_LIMB); + m->_mp_alloc = new_size; + +#if 0 + /* This might break some code that reads the size field after + reallocation, in the case the reallocated destination and a + source argument are identical. */ + if (ABS (m->_mp_size) > new_size) + m->_mp_size = 0; +#endif + + return (void *) m->_mp_d; +} diff --git a/contrib/libgmp/mpz/scan0.c b/contrib/libgmp/mpz/scan0.c new file mode 100644 index 0000000..8e45aa3 --- /dev/null +++ b/contrib/libgmp/mpz/scan0.c @@ -0,0 +1,35 @@ +/* mpz_scan0(op, startbit) -- Scan for the next set bit, starting at startbit. + +Copyright (C) 1996 Free Software Foundation, Inc. + +This file is part of the GNU MP Library. + +The GNU MP Library is free software; you can redistribute it and/or modify +it under the terms of the GNU Library General Public License as published by +the Free Software Foundation; either version 2 of the License, or (at your +option) any later version. + +The GNU MP Library is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public +License for more details. + +You should have received a copy of the GNU Library General Public License +along with the GNU MP Library; see the file COPYING.LIB. If not, write to +the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, +MA 02111-1307, USA. */ + +#include "gmp.h" +#include "gmp-impl.h" + +unsigned long int +#if __STDC__ +mpz_scan0 (mpz_srcptr u, unsigned long int starting_bit) +#else +mpz_scan0 (u, starting_bit) + mpz_srcptr u; + unsigned long int starting_bit; +#endif +{ + return mpn_scan0 (u->_mp_d, starting_bit); +} diff --git a/contrib/libgmp/mpz/scan1.c b/contrib/libgmp/mpz/scan1.c new file mode 100644 index 0000000..6ecb0aa --- /dev/null +++ b/contrib/libgmp/mpz/scan1.c @@ -0,0 +1,35 @@ +/* mpz_scan1(op, startbit) -- Scan for the next set bit, starting at startbit. + +Copyright (C) 1996 Free Software Foundation, Inc. + +This file is part of the GNU MP Library. + +The GNU MP Library is free software; you can redistribute it and/or modify +it under the terms of the GNU Library General Public License as published by +the Free Software Foundation; either version 2 of the License, or (at your +option) any later version. + +The GNU MP Library is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public +License for more details. + +You should have received a copy of the GNU Library General Public License +along with the GNU MP Library; see the file COPYING.LIB. If not, write to +the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, +MA 02111-1307, USA. */ + +#include "gmp.h" +#include "gmp-impl.h" + +unsigned long int +#if __STDC__ +mpz_scan1 (mpz_srcptr u, unsigned long int starting_bit) +#else +mpz_scan1 (u, starting_bit) + mpz_srcptr u; + unsigned long int starting_bit; +#endif +{ + return mpn_scan1 (u->_mp_d, starting_bit); +} diff --git a/contrib/libgmp/mpz/set.c b/contrib/libgmp/mpz/set.c new file mode 100644 index 0000000..d94ab74 --- /dev/null +++ b/contrib/libgmp/mpz/set.c @@ -0,0 +1,48 @@ +/* mpz_set (dest_integer, src_integer) -- Assign DEST_INTEGER from SRC_INTEGER. + +Copyright (C) 1991, 1993, 1994, 1995 Free Software Foundation, Inc. + +This file is part of the GNU MP Library. + +The GNU MP Library is free software; you can redistribute it and/or modify +it under the terms of the GNU Library General Public License as published by +the Free Software Foundation; either version 2 of the License, or (at your +option) any later version. + +The GNU MP Library is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public +License for more details. + +You should have received a copy of the GNU Library General Public License +along with the GNU MP Library; see the file COPYING.LIB. If not, write to +the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, +MA 02111-1307, USA. */ + +#include "gmp.h" +#include "gmp-impl.h" + +void +#if __STDC__ +mpz_set (mpz_ptr w, mpz_srcptr u) +#else +mpz_set (w, u) + mpz_ptr w; + mpz_srcptr u; +#endif +{ + mp_ptr wp, up; + mp_size_t usize, size; + + usize = u->_mp_size; + size = ABS (usize); + + if (w->_mp_alloc < size) + _mpz_realloc (w, size); + + wp = w->_mp_d; + up = u->_mp_d; + + MPN_COPY (wp, up, size); + w->_mp_size = usize; +} diff --git a/contrib/libgmp/mpz/set_d.c b/contrib/libgmp/mpz/set_d.c new file mode 100644 index 0000000..c09b1d9 --- /dev/null +++ b/contrib/libgmp/mpz/set_d.c @@ -0,0 +1,93 @@ +/* mpz_set_d(integer, val) -- Assign INTEGER with a double value VAL. + +Copyright (C) 1995 Free Software Foundation, Inc. + +This file is part of the GNU MP Library. + +The GNU MP Library is free software; you can redistribute it and/or modify +it under the terms of the GNU Library General Public License as published by +the Free Software Foundation; either version 2 of the License, or (at your +option) any later version. + +The GNU MP Library is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public +License for more details. + +You should have received a copy of the GNU Library General Public License +along with the GNU MP Library; see the file COPYING.LIB. If not, write to +the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, +MA 02111-1307, USA. */ + +#include "gmp.h" +#include "gmp-impl.h" + +void +#if __STDC__ +mpz_set_d (mpz_ptr r, double d) +#else +mpz_set_d (r, d) + mpz_ptr r; + double d; +#endif +{ + int negative; + mp_size_t size; + mp_limb_t tp[3]; + mp_ptr rp; + + negative = d < 0; + d = ABS (d); + + /* Handle small arguments quickly. */ + if (d < MP_BASE_AS_DOUBLE) + { + mp_limb_t tmp; + tmp = d; + PTR(r)[0] = tmp; + SIZ(r) = negative ? -(tmp != 0) : (tmp != 0); + return; + } + + size = __gmp_extract_double (tp, d); + + if (ALLOC(r) < size) + _mpz_realloc (r, size); + + rp = PTR (r); + +#if BITS_PER_MP_LIMB == 32 + switch (size) + { + default: + MPN_ZERO (rp, size - 3); + rp += size - 3; + case 3: + rp[2] = tp[2]; + rp[1] = tp[1]; + rp[0] = tp[0]; + break; + case 2: + rp[1] = tp[2]; + rp[0] = tp[1]; + break; + case 1: + abort (); + } +#else + switch (size) + { + default: + MPN_ZERO (rp, size - 2); + rp += size - 2; + case 2: + rp[1] = tp[1]; + rp[0] = tp[0]; + break; + case 1: + abort (); + } +#endif + + SIZ(r) = negative ? -size : size; +} diff --git a/contrib/libgmp/mpz/set_f.c b/contrib/libgmp/mpz/set_f.c new file mode 100644 index 0000000..9547907 --- /dev/null +++ b/contrib/libgmp/mpz/set_f.c @@ -0,0 +1,64 @@ +/* mpz_set_f (dest_integer, src_float) -- Assign DEST_INTEGER from SRC_FLOAT. + +Copyright (C) 1996 Free Software Foundation, Inc. + +This file is part of the GNU MP Library. + +The GNU MP Library is free software; you can redistribute it and/or modify +it under the terms of the GNU Library General Public License as published by +the Free Software Foundation; either version 2 of the License, or (at your +option) any later version. + +The GNU MP Library is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public +License for more details. + +You should have received a copy of the GNU Library General Public License +along with the GNU MP Library; see the file COPYING.LIB. If not, write to +the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, +MA 02111-1307, USA. */ + +#include "gmp.h" +#include "gmp-impl.h" + +void +#if __STDC__ +mpz_set_f (mpz_ptr w, mpf_srcptr u) +#else +mpz_set_f (w, u) + mpz_ptr w; + mpf_srcptr u; +#endif +{ + mp_ptr wp, up; + mp_size_t usize, size; + mp_exp_t exp; + + usize = SIZ (u); + size = ABS (usize); + exp = EXP (u); + + if (w->_mp_alloc < exp) + _mpz_realloc (w, exp); + + wp = w->_mp_d; + up = u->_mp_d; + + if (exp <= 0) + { + SIZ (w) = 0; + return; + } + if (exp < size) + { + MPN_COPY (wp, up + size - exp, exp); + } + else + { + MPN_ZERO (wp, exp - size); + MPN_COPY (wp + exp - size, up, size); + } + + w->_mp_size = usize >= 0 ? exp : -exp; +} diff --git a/contrib/libgmp/mpz/set_q.c b/contrib/libgmp/mpz/set_q.c new file mode 100644 index 0000000..61bd5c7 --- /dev/null +++ b/contrib/libgmp/mpz/set_q.c @@ -0,0 +1,36 @@ +/* mpz_set_q (dest_integer, src_rational) -- Assign DEST_INTEGER from + SRC_rational. + +Copyright (C) 1996 Free Software Foundation, Inc. + +This file is part of the GNU MP Library. + +The GNU MP Library is free software; you can redistribute it and/or modify +it under the terms of the GNU Library General Public License as published by +the Free Software Foundation; either version 2 of the License, or (at your +option) any later version. + +The GNU MP Library is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public +License for more details. + +You should have received a copy of the GNU Library General Public License +along with the GNU MP Library; see the file COPYING.LIB. If not, write to +the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, +MA 02111-1307, USA. */ + +#include "gmp.h" +#include "gmp-impl.h" + +void +#if __STDC__ +mpz_set_q (mpz_ptr w, mpq_srcptr u) +#else +mpz_set_q (w, u) + mpz_ptr w; + mpq_srcptr u; +#endif +{ + mpz_tdiv_q (w, mpq_numref (u), mpq_denref (u)); +} diff --git a/contrib/libgmp/mpz/set_si.c b/contrib/libgmp/mpz/set_si.c new file mode 100644 index 0000000..82a90a3 --- /dev/null +++ b/contrib/libgmp/mpz/set_si.c @@ -0,0 +1,48 @@ +/* mpz_set_si(integer, val) -- Assign INTEGER with a small value VAL. + +Copyright (C) 1991, 1993, 1994, 1995 Free Software Foundation, Inc. + +This file is part of the GNU MP Library. + +The GNU MP Library is free software; you can redistribute it and/or modify +it under the terms of the GNU Library General Public License as published by +the Free Software Foundation; either version 2 of the License, or (at your +option) any later version. + +The GNU MP Library is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public +License for more details. + +You should have received a copy of the GNU Library General Public License +along with the GNU MP Library; see the file COPYING.LIB. If not, write to +the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, +MA 02111-1307, USA. */ + +#include "gmp.h" +#include "gmp-impl.h" + +void +#if __STDC__ +mpz_set_si (mpz_ptr dest, signed long int val) +#else +mpz_set_si (dest, val) + mpz_ptr dest; + signed long int val; +#endif +{ + /* We don't check if the allocation is enough, since the rest of the + package ensures it's at least 1, which is what we need here. */ + if (val > 0) + { + dest->_mp_d[0] = val; + dest->_mp_size = 1; + } + else if (val < 0) + { + dest->_mp_d[0] = -val; + dest->_mp_size = -1; + } + else + dest->_mp_size = 0; +} diff --git a/contrib/libgmp/mpz/set_str.c b/contrib/libgmp/mpz/set_str.c new file mode 100644 index 0000000..d1334b1 --- /dev/null +++ b/contrib/libgmp/mpz/set_str.c @@ -0,0 +1,132 @@ +/* mpz_set_str(mp_dest, string, base) -- Convert the \0-terminated + string STRING in base BASE to multiple precision integer in + MP_DEST. Allow white space in the string. If BASE == 0 determine + the base in the C standard way, i.e. 0xhh...h means base 16, + 0oo...o means base 8, otherwise assume base 10. + +Copyright (C) 1991, 1993, 1994, Free Software Foundation, Inc. + +This file is part of the GNU MP Library. + +The GNU MP Library is free software; you can redistribute it and/or modify +it under the terms of the GNU Library General Public License as published by +the Free Software Foundation; either version 2 of the License, or (at your +option) any later version. + +The GNU MP Library is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public +License for more details. + +You should have received a copy of the GNU Library General Public License +along with the GNU MP Library; see the file COPYING.LIB. If not, write to +the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, +MA 02111-1307, USA. */ + +#include <ctype.h> +#include "gmp.h" +#include "gmp-impl.h" +#include "longlong.h" + +static int +digit_value_in_base (c, base) + int c; + int base; +{ + int digit; + + if (isdigit (c)) + digit = c - '0'; + else if (islower (c)) + digit = c - 'a' + 10; + else if (isupper (c)) + digit = c - 'A' + 10; + else + return -1; + + if (digit < base) + return digit; + return -1; +} + +int +#if __STDC__ +mpz_set_str (mpz_ptr x, const char *str, int base) +#else +mpz_set_str (x, str, base) + mpz_ptr x; + const char *str; + int base; +#endif +{ + size_t str_size; + char *s, *begs; + size_t i; + mp_size_t xsize; + int c; + int negative; + TMP_DECL (marker); + + /* Skip whitespace. */ + do + c = *str++; + while (isspace (c)); + + negative = 0; + if (c == '-') + { + negative = 1; + c = *str++; + } + + if (digit_value_in_base (c, base == 0 ? 10 : base) < 0) + return -1; /* error if no digits */ + + /* If BASE is 0, try to find out the base by looking at the initial + characters. */ + if (base == 0) + { + base = 10; + if (c == '0') + { + base = 8; + c = *str++; + if (c == 'x' || c == 'X') + { + base = 16; + c = *str++; + } + } + } + + TMP_MARK (marker); + str_size = strlen (str - 1); + s = begs = (char *) TMP_ALLOC (str_size + 1); + + for (i = 0; i < str_size; i++) + { + if (!isspace (c)) + { + int dig = digit_value_in_base (c, base); + if (dig < 0) + { + TMP_FREE (marker); + return -1; + } + *s++ = dig; + } + c = *str++; + } + + str_size = s - begs; + + xsize = str_size / __mp_bases[base].chars_per_limb + 1; + if (x->_mp_alloc < xsize) + _mpz_realloc (x, xsize); + + xsize = mpn_set_str (x->_mp_d, (unsigned char *) begs, str_size, base); + x->_mp_size = negative ? -xsize : xsize; + + TMP_FREE (marker); + return 0; +} diff --git a/contrib/libgmp/mpz/set_ui.c b/contrib/libgmp/mpz/set_ui.c new file mode 100644 index 0000000..73f6cf5 --- /dev/null +++ b/contrib/libgmp/mpz/set_ui.c @@ -0,0 +1,43 @@ +/* mpz_set_ui(integer, val) -- Assign INTEGER with a small value VAL. + +Copyright (C) 1991, 1993, 1994, 1995 Free Software Foundation, Inc. + +This file is part of the GNU MP Library. + +The GNU MP Library is free software; you can redistribute it and/or modify +it under the terms of the GNU Library General Public License as published by +the Free Software Foundation; either version 2 of the License, or (at your +option) any later version. + +The GNU MP Library is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public +License for more details. + +You should have received a copy of the GNU Library General Public License +along with the GNU MP Library; see the file COPYING.LIB. If not, write to +the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, +MA 02111-1307, USA. */ + +#include "gmp.h" +#include "gmp-impl.h" + +void +#if __STDC__ +mpz_set_ui (mpz_ptr dest, unsigned long int val) +#else +mpz_set_ui (dest, val) + mpz_ptr dest; + unsigned long int val; +#endif +{ + /* We don't check if the allocation is enough, since the rest of the + package ensures it's at least 1, which is what we need here. */ + if (val > 0) + { + dest->_mp_d[0] = val; + dest->_mp_size = 1; + } + else + dest->_mp_size = 0; +} diff --git a/contrib/libgmp/mpz/setbit.c b/contrib/libgmp/mpz/setbit.c new file mode 100644 index 0000000..af59e2c --- /dev/null +++ b/contrib/libgmp/mpz/setbit.c @@ -0,0 +1,113 @@ +/* mpz_setbit -- set a specified bit. + +Copyright (C) 1991, 1993, 1994, 1995 Free Software Foundation, Inc. + +This file is part of the GNU MP Library. + +The GNU MP Library is free software; you can redistribute it and/or modify +it under the terms of the GNU Library General Public License as published by +the Free Software Foundation; either version 2 of the License, or (at your +option) any later version. + +The GNU MP Library is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public +License for more details. + +You should have received a copy of the GNU Library General Public License +along with the GNU MP Library; see the file COPYING.LIB. If not, write to +the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, +MA 02111-1307, USA. */ + +#include "gmp.h" +#include "gmp-impl.h" + +void +#if __STDC__ +mpz_setbit (mpz_ptr d, unsigned long int bit_index) +#else +mpz_setbit (d, bit_index) + mpz_ptr d; + unsigned long int bit_index; +#endif +{ + mp_size_t dsize = d->_mp_size; + mp_ptr dp = d->_mp_d; + mp_size_t limb_index; + + limb_index = bit_index / BITS_PER_MP_LIMB; + if (dsize >= 0) + { + if (limb_index < dsize) + { + dp[limb_index] |= (mp_limb_t) 1 << (bit_index % BITS_PER_MP_LIMB); + d->_mp_size = dsize; + } + else + { + /* Ugh. The bit should be set outside of the end of the + number. We have to increase the size of the number. */ + if (d->_mp_alloc < limb_index + 1) + { + _mpz_realloc (d, limb_index + 1); + dp = d->_mp_d; + } + MPN_ZERO (dp + dsize, limb_index - dsize); + dp[limb_index] = (mp_limb_t) 1 << (bit_index % BITS_PER_MP_LIMB); + d->_mp_size = limb_index + 1; + } + } + else + { + mp_size_t zero_bound; + + /* Simulate two's complement arithmetic, i.e. simulate + 1. Set OP = ~(OP - 1) [with infinitely many leading ones]. + 2. set the bit. + 3. Set OP = ~OP + 1. */ + + dsize = -dsize; + + /* No upper bound on this loop, we're sure there's a non-zero limb + sooner ot later. */ + for (zero_bound = 0; ; zero_bound++) + if (dp[zero_bound] != 0) + break; + + if (limb_index > zero_bound) + { + if (limb_index < dsize) + dp[limb_index] &= ~((mp_limb_t) 1 << (bit_index % BITS_PER_MP_LIMB)); + else + ; + } + else if (limb_index == zero_bound) + { + dp[limb_index] = ((dp[limb_index] - 1) + & ~((mp_limb_t) 1 << (bit_index % BITS_PER_MP_LIMB))) + 1; + if (dp[limb_index] == 0) + { + mp_size_t i; + for (i = limb_index + 1; i < dsize; i++) + { + dp[i] += 1; + if (dp[i] != 0) + goto fin; + } + /* We got carry all way out beyond the end of D. Increase + its size (and allocation if necessary). */ + dsize++; + if (d->_mp_alloc < dsize) + { + _mpz_realloc (d, dsize); + dp = d->_mp_d; + } + dp[i] = 1; + d->_mp_size = -dsize; + fin:; + } + } + else + ; + } +} diff --git a/contrib/libgmp/mpz/size.c b/contrib/libgmp/mpz/size.c new file mode 100644 index 0000000..0b09fbe --- /dev/null +++ b/contrib/libgmp/mpz/size.c @@ -0,0 +1,35 @@ +/* mpz_size(x) -- return the number of lims currently used by the + value of integer X. + +Copyright (C) 1991, 1993, 1994, 1995 Free Software Foundation, Inc. + +This file is part of the GNU MP Library. + +The GNU MP Library is free software; you can redistribute it and/or modify +it under the terms of the GNU Library General Public License as published by +the Free Software Foundation; either version 2 of the License, or (at your +option) any later version. + +The GNU MP Library is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public +License for more details. + +You should have received a copy of the GNU Library General Public License +along with the GNU MP Library; see the file COPYING.LIB. If not, write to +the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, +MA 02111-1307, USA. */ + +#include "gmp.h" +#include "gmp-impl.h" + +size_t +#if __STDC__ +mpz_size (mpz_srcptr x) +#else +mpz_size (x) + mpz_srcptr x; +#endif +{ + return ABS (x->_mp_size); +} diff --git a/contrib/libgmp/mpz/sizeinbase.c b/contrib/libgmp/mpz/sizeinbase.c new file mode 100644 index 0000000..51bd555 --- /dev/null +++ b/contrib/libgmp/mpz/sizeinbase.c @@ -0,0 +1,60 @@ +/* mpz_sizeinbase(x, base) -- return an approximation to the number of + character the integer X would have printed in base BASE. The + approximation is never too small. + +Copyright (C) 1991, 1993, 1994, 1995 Free Software Foundation, Inc. + +This file is part of the GNU MP Library. + +The GNU MP Library is free software; you can redistribute it and/or modify +it under the terms of the GNU Library General Public License as published by +the Free Software Foundation; either version 2 of the License, or (at your +option) any later version. + +The GNU MP Library is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public +License for more details. + +You should have received a copy of the GNU Library General Public License +along with the GNU MP Library; see the file COPYING.LIB. If not, write to +the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, +MA 02111-1307, USA. */ + +#include "gmp.h" +#include "gmp-impl.h" +#include "longlong.h" + +size_t +#if __STDC__ +mpz_sizeinbase (mpz_srcptr x, int base) +#else +mpz_sizeinbase (x, base) + mpz_srcptr x; + int base; +#endif +{ + mp_size_t size = ABS (x->_mp_size); + int lb_base, cnt; + size_t totbits; + + /* Special case for X == 0. */ + if (size == 0) + return 1; + + /* Calculate the total number of significant bits of X. */ + count_leading_zeros (cnt, x->_mp_d[size - 1]); + totbits = size * BITS_PER_MP_LIMB - cnt; + + if ((base & (base - 1)) == 0) + { + /* Special case for powers of 2, giving exact result. */ + + count_leading_zeros (lb_base, base); + lb_base = BITS_PER_MP_LIMB - lb_base - 1; + + return (totbits + lb_base - 1) / lb_base; + } + else + return (size_t) (totbits * __mp_bases[base].chars_per_bit_exactly) + 1; +} diff --git a/contrib/libgmp/mpz/sqrt.c b/contrib/libgmp/mpz/sqrt.c new file mode 100644 index 0000000..44c554e --- /dev/null +++ b/contrib/libgmp/mpz/sqrt.c @@ -0,0 +1,85 @@ +/* mpz_sqrt(root, u) -- Set ROOT to floor(sqrt(U)). + +Copyright (C) 1991, 1993, 1994, 1996 Free Software Foundation, Inc. + +This file is part of the GNU MP Library. + +The GNU MP Library is free software; you can redistribute it and/or modify +it under the terms of the GNU Library General Public License as published by +the Free Software Foundation; either version 2 of the License, or (at your +option) any later version. + +The GNU MP Library is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public +License for more details. + +You should have received a copy of the GNU Library General Public License +along with the GNU MP Library; see the file COPYING.LIB. If not, write to +the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, +MA 02111-1307, USA. */ + +#include "gmp.h" +#include "gmp-impl.h" + +void +#if __STDC__ +mpz_sqrt (mpz_ptr root, mpz_srcptr op) +#else +mpz_sqrt (root, op) + mpz_ptr root; + mpz_srcptr op; +#endif +{ + mp_size_t op_size, root_size; + mp_ptr root_ptr, op_ptr; + mp_ptr free_me = NULL; + mp_size_t free_me_size; + TMP_DECL (marker); + + TMP_MARK (marker); + op_size = op->_mp_size; + if (op_size < 0) + op_size = 1 / (op_size > 0); /* Divide by zero for negative OP. */ + + /* The size of the root is accurate after this simple calculation. */ + root_size = (op_size + 1) / 2; + + root_ptr = root->_mp_d; + op_ptr = op->_mp_d; + + if (root->_mp_alloc < root_size) + { + if (root_ptr == op_ptr) + { + free_me = root_ptr; + free_me_size = root->_mp_alloc; + } + else + (*_mp_free_func) (root_ptr, root->_mp_alloc * BYTES_PER_MP_LIMB); + + root->_mp_alloc = root_size; + root_ptr = (mp_ptr) (*_mp_allocate_func) (root_size * BYTES_PER_MP_LIMB); + root->_mp_d = root_ptr; + } + else + { + /* Make OP not overlap with ROOT. */ + if (root_ptr == op_ptr) + { + /* ROOT and OP are identical. Allocate temporary space for OP. */ + op_ptr = (mp_ptr) TMP_ALLOC (op_size * BYTES_PER_MP_LIMB); + /* Copy to the temporary space. Hack: Avoid temporary variable + by using ROOT_PTR. */ + MPN_COPY (op_ptr, root_ptr, op_size); + } + } + + mpn_sqrtrem (root_ptr, NULL, op_ptr, op_size); + + root->_mp_size = root_size; + + if (free_me != NULL) + (*_mp_free_func) (free_me, free_me_size * BYTES_PER_MP_LIMB); + TMP_FREE (marker); +} diff --git a/contrib/libgmp/mpz/sqrtrem.c b/contrib/libgmp/mpz/sqrtrem.c new file mode 100644 index 0000000..757cc5d --- /dev/null +++ b/contrib/libgmp/mpz/sqrtrem.c @@ -0,0 +1,107 @@ +/* mpz_sqrtrem(root,rem,x) -- Set ROOT to floor(sqrt(X)) and REM + to the remainder, i.e. X - ROOT**2. + +Copyright (C) 1991, 1993, 1994, 1996 Free Software Foundation, Inc. + +This file is part of the GNU MP Library. + +The GNU MP Library is free software; you can redistribute it and/or modify +it under the terms of the GNU Library General Public License as published by +the Free Software Foundation; either version 2 of the License, or (at your +option) any later version. + +The GNU MP Library is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public +License for more details. + +You should have received a copy of the GNU Library General Public License +along with the GNU MP Library; see the file COPYING.LIB. If not, write to +the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, +MA 02111-1307, USA. */ + +#include "gmp.h" +#include "gmp-impl.h" + +#ifndef BERKELEY_MP +void +#if __STDC__ +mpz_sqrtrem (mpz_ptr root, mpz_ptr rem, mpz_srcptr op) +#else +mpz_sqrtrem (root, rem, op) + mpz_ptr root; + mpz_ptr rem; + mpz_srcptr op; +#endif +#else /* BERKELEY_MP */ +void +#if __STDC__ +msqrt (mpz_srcptr op, mpz_ptr root, mpz_ptr rem) +#else +msqrt (op, root, rem) + mpz_srcptr op; + mpz_ptr root; + mpz_ptr rem; +#endif +#endif /* BERKELEY_MP */ +{ + mp_size_t op_size, root_size, rem_size; + mp_ptr root_ptr, op_ptr; + mp_ptr free_me = NULL; + mp_size_t free_me_size; + TMP_DECL (marker); + + TMP_MARK (marker); + op_size = op->_mp_size; + if (op_size < 0) + op_size = 1 / (op_size > 0); /* Divide by zero for negative OP. */ + + if (rem->_mp_alloc < op_size) + _mpz_realloc (rem, op_size); + + /* The size of the root is accurate after this simple calculation. */ + root_size = (op_size + 1) / 2; + + root_ptr = root->_mp_d; + op_ptr = op->_mp_d; + + if (root->_mp_alloc < root_size) + { + if (root_ptr == op_ptr) + { + free_me = root_ptr; + free_me_size = root->_mp_alloc; + } + else + (*_mp_free_func) (root_ptr, root->_mp_alloc * BYTES_PER_MP_LIMB); + + root->_mp_alloc = root_size; + root_ptr = (mp_ptr) (*_mp_allocate_func) (root_size * BYTES_PER_MP_LIMB); + root->_mp_d = root_ptr; + } + else + { + /* Make OP not overlap with ROOT. */ + if (root_ptr == op_ptr) + { + /* ROOT and OP are identical. Allocate temporary space for OP. */ + op_ptr = (mp_ptr) TMP_ALLOC (op_size * BYTES_PER_MP_LIMB); + /* Copy to the temporary space. Hack: Avoid temporary variable + by using ROOT_PTR. */ + MPN_COPY (op_ptr, root_ptr, op_size); + } + } + + rem_size = mpn_sqrtrem (root_ptr, rem->_mp_d, op_ptr, op_size); + + root->_mp_size = root_size; + + /* Write remainder size last, to enable us to define this function to + give only the square root remainder, if the user calls if with + ROOT == REM. */ + rem->_mp_size = rem_size; + + if (free_me != NULL) + (*_mp_free_func) (free_me, free_me_size * BYTES_PER_MP_LIMB); + TMP_FREE (marker); +} diff --git a/contrib/libgmp/mpz/sub.c b/contrib/libgmp/mpz/sub.c new file mode 100644 index 0000000..56ef1a1 --- /dev/null +++ b/contrib/libgmp/mpz/sub.c @@ -0,0 +1,120 @@ +/* mpz_sub -- Subtract two integers. + +Copyright (C) 1991, 1993, 1994, 1996 Free Software Foundation, Inc. + +This file is part of the GNU MP Library. + +The GNU MP Library is free software; you can redistribute it and/or modify +it under the terms of the GNU Library General Public License as published by +the Free Software Foundation; either version 2 of the License, or (at your +option) any later version. + +The GNU MP Library is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public +License for more details. + +You should have received a copy of the GNU Library General Public License +along with the GNU MP Library; see the file COPYING.LIB. If not, write to +the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, +MA 02111-1307, USA. */ + +#include "gmp.h" +#include "gmp-impl.h" + +#ifndef BERKELEY_MP +void +#if __STDC__ +mpz_sub (mpz_ptr w, mpz_srcptr u, mpz_srcptr v) +#else +mpz_sub (w, u, v) + mpz_ptr w; + mpz_srcptr u; + mpz_srcptr v; +#endif +#else /* BERKELEY_MP */ +void +#if __STDC__ +msub (mpz_srcptr u, mpz_srcptr v, mpz_ptr w) +#else +msub (u, v, w) + mpz_srcptr u; + mpz_srcptr v; + mpz_ptr w; +#endif +#endif /* BERKELEY_MP */ +{ + mp_srcptr up, vp; + mp_ptr wp; + mp_size_t usize, vsize, wsize; + mp_size_t abs_usize; + mp_size_t abs_vsize; + + usize = u->_mp_size; + vsize = -v->_mp_size; /* The "-" makes the difference from mpz_add */ + abs_usize = ABS (usize); + abs_vsize = ABS (vsize); + + if (abs_usize < abs_vsize) + { + /* Swap U and V. */ + {const __mpz_struct *t = u; u = v; v = t;} + {mp_size_t t = usize; usize = vsize; vsize = t;} + {mp_size_t t = abs_usize; abs_usize = abs_vsize; abs_vsize = t;} + } + + /* True: ABS_USIZE >= ABS_VSIZE. */ + + /* If not space for w (and possible carry), increase space. */ + wsize = abs_usize + 1; + if (w->_mp_alloc < wsize) + _mpz_realloc (w, wsize); + + /* These must be after realloc (u or v may be the same as w). */ + up = u->_mp_d; + vp = v->_mp_d; + wp = w->_mp_d; + + if ((usize ^ vsize) < 0) + { + /* U and V have different sign. Need to compare them to determine + which operand to subtract from which. */ + + /* This test is right since ABS_USIZE >= ABS_VSIZE. */ + if (abs_usize != abs_vsize) + { + mpn_sub (wp, up, abs_usize, vp, abs_vsize); + wsize = abs_usize; + MPN_NORMALIZE (wp, wsize); + if (usize < 0) + wsize = -wsize; + } + else if (mpn_cmp (up, vp, abs_usize) < 0) + { + mpn_sub_n (wp, vp, up, abs_usize); + wsize = abs_usize; + MPN_NORMALIZE (wp, wsize); + if (usize >= 0) + wsize = -wsize; + } + else + { + mpn_sub_n (wp, up, vp, abs_usize); + wsize = abs_usize; + MPN_NORMALIZE (wp, wsize); + if (usize < 0) + wsize = -wsize; + } + } + else + { + /* U and V have same sign. Add them. */ + mp_limb_t cy_limb = mpn_add (wp, up, abs_usize, vp, abs_vsize); + wp[abs_usize] = cy_limb; + wsize = abs_usize + cy_limb; + if (usize < 0) + wsize = -wsize; + } + + w->_mp_size = wsize; +} diff --git a/contrib/libgmp/mpz/sub_ui.c b/contrib/libgmp/mpz/sub_ui.c new file mode 100644 index 0000000..7dea4b6 --- /dev/null +++ b/contrib/libgmp/mpz/sub_ui.c @@ -0,0 +1,84 @@ +/* mpz_sub_ui -- Subtract an unsigned one-word integer from an MP_INT. + +Copyright (C) 1991, 1993, 1994, 1996 Free Software Foundation, Inc. + +This file is part of the GNU MP Library. + +The GNU MP Library is free software; you can redistribute it and/or modify +it under the terms of the GNU Library General Public License as published by +the Free Software Foundation; either version 2 of the License, or (at your +option) any later version. + +The GNU MP Library is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public +License for more details. + +You should have received a copy of the GNU Library General Public License +along with the GNU MP Library; see the file COPYING.LIB. If not, write to +the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, +MA 02111-1307, USA. */ + +#include "gmp.h" +#include "gmp-impl.h" + +void +#if __STDC__ +mpz_sub_ui (mpz_ptr w, mpz_srcptr u, unsigned long int v) +#else +mpz_sub_ui (w, u, v) + mpz_ptr w; + mpz_srcptr u; + unsigned long int v; +#endif +{ + mp_srcptr up; + mp_ptr wp; + mp_size_t usize, wsize; + mp_size_t abs_usize; + + usize = u->_mp_size; + abs_usize = ABS (usize); + + /* If not space for W (and possible carry), increase space. */ + wsize = abs_usize + 1; + if (w->_mp_alloc < wsize) + _mpz_realloc (w, wsize); + + /* These must be after realloc (U may be the same as W). */ + up = u->_mp_d; + wp = w->_mp_d; + + if (abs_usize == 0) + { + wp[0] = v; + w->_mp_size = -(v != 0); + return; + } + + if (usize < 0) + { + mp_limb_t cy; + cy = mpn_add_1 (wp, up, abs_usize, v); + wp[abs_usize] = cy; + wsize = -(abs_usize + cy); + } + else + { + /* The signs are different. Need exact comparison to determine + which operand to subtract from which. */ + if (abs_usize == 1 && up[0] < v) + { + wp[0] = v - up[0]; + wsize = -1; + } + else + { + mpn_sub_1 (wp, up, abs_usize, v); + /* Size can decrease with at most one limb. */ + wsize = abs_usize - (wp[abs_usize - 1] == 0); + } + } + + w->_mp_size = wsize; +} diff --git a/contrib/libgmp/mpz/tdiv_q.c b/contrib/libgmp/mpz/tdiv_q.c new file mode 100644 index 0000000..b4d3636 --- /dev/null +++ b/contrib/libgmp/mpz/tdiv_q.c @@ -0,0 +1,133 @@ +/* mpz_tdiv_q -- divide two integers and produce a quotient. + +Copyright (C) 1991, 1993, 1994, 1996 Free Software Foundation, Inc. + +This file is part of the GNU MP Library. + +The GNU MP Library is free software; you can redistribute it and/or modify +it under the terms of the GNU Library General Public License as published by +the Free Software Foundation; either version 2 of the License, or (at your +option) any later version. + +The GNU MP Library is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public +License for more details. + +You should have received a copy of the GNU Library General Public License +along with the GNU MP Library; see the file COPYING.LIB. If not, write to +the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, +MA 02111-1307, USA. */ + +#include "gmp.h" +#include "gmp-impl.h" +#include "longlong.h" + +void +#if __STDC__ +mpz_tdiv_q (mpz_ptr quot, mpz_srcptr num, mpz_srcptr den) +#else +mpz_tdiv_q (quot, num, den) + mpz_ptr quot; + mpz_srcptr num; + mpz_srcptr den; +#endif +{ + mp_srcptr np, dp; + mp_ptr qp, rp; + mp_size_t nsize = num->_mp_size; + mp_size_t dsize = den->_mp_size; + mp_size_t qsize, rsize; + mp_size_t sign_quotient = nsize ^ dsize; + unsigned normalization_steps; + mp_limb_t q_limb; + TMP_DECL (marker); + + nsize = ABS (nsize); + dsize = ABS (dsize); + + /* Ensure space is enough for quotient. */ + + qsize = nsize - dsize + 1; /* qsize cannot be bigger than this. */ + if (qsize <= 0) + { + quot->_mp_size = 0; + return; + } + + if (quot->_mp_alloc < qsize) + _mpz_realloc (quot, qsize); + + qp = quot->_mp_d; + np = num->_mp_d; + dp = den->_mp_d; + + /* Optimize division by a single-limb divisor. */ + if (dsize == 1) + { + mpn_divmod_1 (qp, np, nsize, dp[0]); + qsize -= qp[qsize - 1] == 0; + quot->_mp_size = sign_quotient >= 0 ? qsize : -qsize; + return; + } + + TMP_MARK (marker); + + rp = (mp_ptr) TMP_ALLOC ((nsize + 1) * BYTES_PER_MP_LIMB); + + count_leading_zeros (normalization_steps, dp[dsize - 1]); + + /* Normalize the denominator, i.e. make its most significant bit set by + shifting it NORMALIZATION_STEPS bits to the left. Also shift the + numerator the same number of steps (to keep the quotient the same!). */ + if (normalization_steps != 0) + { + mp_ptr tp; + mp_limb_t nlimb; + + /* Shift up the denominator setting the most significant bit of + the most significant word. Use temporary storage not to clobber + the original contents of the denominator. */ + tp = (mp_ptr) TMP_ALLOC (dsize * BYTES_PER_MP_LIMB); + mpn_lshift (tp, dp, dsize, normalization_steps); + dp = tp; + + /* Shift up the numerator, possibly introducing a new most + significant word. Move the shifted numerator in the remainder + meanwhile. */ + nlimb = mpn_lshift (rp, np, nsize, normalization_steps); + if (nlimb != 0) + { + rp[nsize] = nlimb; + rsize = nsize + 1; + } + else + rsize = nsize; + } + else + { + /* The denominator is already normalized, as required. Copy it to + temporary space if it overlaps with the quotient. */ + if (dp == qp) + { + dp = (mp_ptr) TMP_ALLOC (dsize * BYTES_PER_MP_LIMB); + MPN_COPY ((mp_ptr) dp, qp, dsize); + } + + /* Move the numerator to the remainder. */ + MPN_COPY (rp, np, nsize); + rsize = nsize; + } + + q_limb = mpn_divmod (qp, rp, rsize, dp, dsize); + + qsize = rsize - dsize; + if (q_limb) + { + qp[qsize] = q_limb; + qsize += 1; + } + + quot->_mp_size = sign_quotient >= 0 ? qsize : -qsize; + TMP_FREE (marker); +} diff --git a/contrib/libgmp/mpz/tdiv_q_2exp.c b/contrib/libgmp/mpz/tdiv_q_2exp.c new file mode 100644 index 0000000..e70d810 --- /dev/null +++ b/contrib/libgmp/mpz/tdiv_q_2exp.c @@ -0,0 +1,68 @@ +/* mpz_tdiv_q_2exp -- Divide an integer by 2**CNT. Round the quotient + towards -infinity. + +Copyright (C) 1991, 1993, 1994, 1996 Free Software Foundation, Inc. + +This file is part of the GNU MP Library. + +The GNU MP Library is free software; you can redistribute it and/or modify +it under the terms of the GNU Library General Public License as published by +the Free Software Foundation; either version 2 of the License, or (at your +option) any later version. + +The GNU MP Library is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public +License for more details. + +You should have received a copy of the GNU Library General Public License +along with the GNU MP Library; see the file COPYING.LIB. If not, write to +the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, +MA 02111-1307, USA. */ + +#include "gmp.h" +#include "gmp-impl.h" + +void +#if __STDC__ +mpz_tdiv_q_2exp (mpz_ptr w, mpz_srcptr u, unsigned long int cnt) +#else +mpz_tdiv_q_2exp (w, u, cnt) + mpz_ptr w; + mpz_srcptr u; + unsigned long int cnt; +#endif +{ + mp_size_t usize, wsize; + mp_size_t limb_cnt; + + usize = u->_mp_size; + limb_cnt = cnt / BITS_PER_MP_LIMB; + wsize = ABS (usize) - limb_cnt; + if (wsize <= 0) + w->_mp_size = 0; + else + { + mp_ptr wp; + mp_srcptr up; + + if (w->_mp_alloc < wsize) + _mpz_realloc (w, wsize); + + wp = w->_mp_d; + up = u->_mp_d; + + cnt %= BITS_PER_MP_LIMB; + if (cnt != 0) + { + mpn_rshift (wp, up + limb_cnt, wsize, cnt); + wsize -= wp[wsize - 1] == 0; + } + else + { + MPN_COPY_INCR (wp, up + limb_cnt, wsize); + } + + w->_mp_size = usize >= 0 ? wsize : -wsize; + } +} diff --git a/contrib/libgmp/mpz/tdiv_q_ui.c b/contrib/libgmp/mpz/tdiv_q_ui.c new file mode 100644 index 0000000..9048e0a --- /dev/null +++ b/contrib/libgmp/mpz/tdiv_q_ui.c @@ -0,0 +1,63 @@ +/* mpz_tdiv_q_ui(quot, dividend, divisor_limb) + -- Divide DIVIDEND by DIVISOR_LIMB and store the result in QUOT. + +Copyright (C) 1991, 1993, 1994, 1996 Free Software Foundation, Inc. + +This file is part of the GNU MP Library. + +The GNU MP Library is free software; you can redistribute it and/or modify +it under the terms of the GNU Library General Public License as published by +the Free Software Foundation; either version 2 of the License, or (at your +option) any later version. + +The GNU MP Library is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public +License for more details. + +You should have received a copy of the GNU Library General Public License +along with the GNU MP Library; see the file COPYING.LIB. If not, write to +the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, +MA 02111-1307, USA. */ + +#include "gmp.h" +#include "gmp-impl.h" + +void +#if __STDC__ +mpz_tdiv_q_ui (mpz_ptr quot, mpz_srcptr dividend, unsigned long int divisor) +#else +mpz_tdiv_q_ui (quot, dividend, divisor) + mpz_ptr quot; + mpz_srcptr dividend; + unsigned long int divisor; +#endif +{ + mp_size_t dividend_size; + mp_size_t size; + mp_ptr quot_ptr; + + dividend_size = dividend->_mp_size; + size = ABS (dividend_size); + + if (size == 0) + { + quot->_mp_size = 0; + return; + } + + /* No need for temporary allocation and copying if QUOT == DIVIDEND as + the divisor is just one limb, and thus no intermediate remainders + need to be stored. */ + + if (quot->_mp_alloc < size) + _mpz_realloc (quot, size); + + quot_ptr = quot->_mp_d; + + mpn_divmod_1 (quot_ptr, dividend->_mp_d, size, (mp_limb_t) divisor); + + /* The quotient is SIZE limbs, but the most significant might be zero. */ + size -= quot_ptr[size - 1] == 0; + quot->_mp_size = dividend_size >= 0 ? size : -size; +} diff --git a/contrib/libgmp/mpz/tdiv_qr.c b/contrib/libgmp/mpz/tdiv_qr.c new file mode 100644 index 0000000..500e199 --- /dev/null +++ b/contrib/libgmp/mpz/tdiv_qr.c @@ -0,0 +1,39 @@ +/* mpz_tdiv_qr(quot,rem,dividend,divisor) -- Set QUOT to DIVIDEND/DIVISOR, + and REM to DIVIDEND mod DIVISOR. + +Copyright (C) 1991, 1993, 1994 Free Software Foundation, Inc. + +This file is part of the GNU MP Library. + +The GNU MP Library is free software; you can redistribute it and/or modify +it under the terms of the GNU Library General Public License as published by +the Free Software Foundation; either version 2 of the License, or (at your +option) any later version. + +The GNU MP Library is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public +License for more details. + +You should have received a copy of the GNU Library General Public License +along with the GNU MP Library; see the file COPYING.LIB. If not, write to +the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, +MA 02111-1307, USA. */ + +#include "gmp.h" +#include "gmp-impl.h" +#include "longlong.h" + +void +#if __STDC__ +mpz_tdiv_qr (mpz_ptr quot, mpz_ptr rem, mpz_srcptr num, mpz_srcptr den) +#else +mpz_tdiv_qr (quot, rem, num, den) + mpz_ptr quot; + mpz_ptr rem; + mpz_srcptr num; + mpz_srcptr den; +#endif + +#define COMPUTE_QUOTIENT +#include "dmincl.c" diff --git a/contrib/libgmp/mpz/tdiv_qr_ui.c b/contrib/libgmp/mpz/tdiv_qr_ui.c new file mode 100644 index 0000000..cb5041c --- /dev/null +++ b/contrib/libgmp/mpz/tdiv_qr_ui.c @@ -0,0 +1,78 @@ +/* mpz_tdiv_qr_ui(quot,rem,dividend,short_divisor) -- + Set QUOT to DIVIDEND / SHORT_DIVISOR + and REM to DIVIDEND mod SHORT_DIVISOR. + +Copyright (C) 1991, 1993, 1994, 1996 Free Software Foundation, Inc. + +This file is part of the GNU MP Library. + +The GNU MP Library is free software; you can redistribute it and/or modify +it under the terms of the GNU Library General Public License as published by +the Free Software Foundation; either version 2 of the License, or (at your +option) any later version. + +The GNU MP Library is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public +License for more details. + +You should have received a copy of the GNU Library General Public License +along with the GNU MP Library; see the file COPYING.LIB. If not, write to +the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, +MA 02111-1307, USA. */ + +#include "gmp.h" +#include "gmp-impl.h" + +void +#if __STDC__ +mpz_tdiv_qr_ui (mpz_ptr quot, mpz_ptr rem, mpz_srcptr dividend, unsigned long int divisor) +#else +mpz_tdiv_qr_ui (quot, rem, dividend, divisor) + mpz_ptr quot; + mpz_ptr rem; + mpz_srcptr dividend; + unsigned long int divisor; +#endif +{ + mp_size_t dividend_size; + mp_size_t size; + mp_ptr quot_ptr; + mp_limb_t remainder_limb; + + dividend_size = dividend->_mp_size; + size = ABS (dividend_size); + + if (size == 0) + { + quot->_mp_size = 0; + rem->_mp_size = 0; + return; + } + + /* No need for temporary allocation and copying if QUOT == DIVIDEND as + the divisor is just one limb, and thus no intermediate remainders + need to be stored. */ + + if (quot->_mp_alloc < size) + _mpz_realloc (quot, size); + + quot_ptr = quot->_mp_d; + + remainder_limb = mpn_divmod_1 (quot_ptr, dividend->_mp_d, size, + (mp_limb_t) divisor); + + if (remainder_limb == 0) + rem->_mp_size = 0; + else + { + /* Store the single-limb remainder. We don't check if there's space + for just one limb, since no function ever makes zero space. */ + rem->_mp_size = dividend_size >= 0 ? 1 : -1; + rem->_mp_d[0] = remainder_limb; + } + + /* The quotient is SIZE limbs, but the most significant might be zero. */ + size -= quot_ptr[size - 1] == 0; + quot->_mp_size = dividend_size >= 0 ? size : -size; +} diff --git a/contrib/libgmp/mpz/tdiv_r.c b/contrib/libgmp/mpz/tdiv_r.c new file mode 100644 index 0000000..813a0d4 --- /dev/null +++ b/contrib/libgmp/mpz/tdiv_r.c @@ -0,0 +1,37 @@ +/* mpz_tdiv_r(rem, dividend, divisor) -- Set REM to DIVIDEND mod DIVISOR. + +Copyright (C) 1991, 1993, 1994 Free Software Foundation, Inc. + +This file is part of the GNU MP Library. + +The GNU MP Library is free software; you can redistribute it and/or modify +it under the terms of the GNU Library General Public License as published by +the Free Software Foundation; either version 2 of the License, or (at your +option) any later version. + +The GNU MP Library is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public +License for more details. + +You should have received a copy of the GNU Library General Public License +along with the GNU MP Library; see the file COPYING.LIB. If not, write to +the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, +MA 02111-1307, USA. */ + +#include "gmp.h" +#include "gmp-impl.h" +#include "longlong.h" + +void +#if __STDC__ +mpz_tdiv_r (mpz_ptr rem, mpz_srcptr num, mpz_srcptr den) +#else +mpz_tdiv_r (rem, num, den) + mpz_ptr rem; + mpz_srcptr num; + mpz_srcptr den; +#endif + +#undef COMPUTE_QUOTIENT +#include "dmincl.c" diff --git a/contrib/libgmp/mpz/tdiv_r_2exp.c b/contrib/libgmp/mpz/tdiv_r_2exp.c new file mode 100644 index 0000000..99d617e --- /dev/null +++ b/contrib/libgmp/mpz/tdiv_r_2exp.c @@ -0,0 +1,79 @@ +/* mpz_tdiv_r_2exp -- Divide a integer by 2**CNT and produce a remainder. + +Copyright (C) 1991, 1993, 1994, 1995 Free Software Foundation, Inc. + +This file is part of the GNU MP Library. + +The GNU MP Library is free software; you can redistribute it and/or modify +it under the terms of the GNU Library General Public License as published by +the Free Software Foundation; either version 2 of the License, or (at your +option) any later version. + +The GNU MP Library is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public +License for more details. + +You should have received a copy of the GNU Library General Public License +along with the GNU MP Library; see the file COPYING.LIB. If not, write to +the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, +MA 02111-1307, USA. */ + +#include "gmp.h" +#include "gmp-impl.h" + +void +#if __STDC__ +mpz_tdiv_r_2exp (mpz_ptr res, mpz_srcptr in, unsigned long int cnt) +#else +mpz_tdiv_r_2exp (res, in, cnt) + mpz_ptr res; + mpz_srcptr in; + unsigned long int cnt; +#endif +{ + mp_size_t in_size = ABS (in->_mp_size); + mp_size_t res_size; + mp_size_t limb_cnt = cnt / BITS_PER_MP_LIMB; + mp_srcptr in_ptr = in->_mp_d; + + if (in_size > limb_cnt) + { + /* The input operand is (probably) greater than 2**CNT. */ + mp_limb_t x; + + x = in_ptr[limb_cnt] & (((mp_limb_t) 1 << cnt % BITS_PER_MP_LIMB) - 1); + if (x != 0) + { + res_size = limb_cnt + 1; + if (res->_mp_alloc < res_size) + _mpz_realloc (res, res_size); + + res->_mp_d[limb_cnt] = x; + } + else + { + res_size = limb_cnt; + MPN_NORMALIZE (in_ptr, res_size); + + if (res->_mp_alloc < res_size) + _mpz_realloc (res, res_size); + + limb_cnt = res_size; + } + } + else + { + /* The input operand is smaller than 2**CNT. We perform a no-op, + apart from that we might need to copy IN to RES. */ + res_size = in_size; + if (res->_mp_alloc < res_size) + _mpz_realloc (res, res_size); + + limb_cnt = res_size; + } + + if (res != in) + MPN_COPY (res->_mp_d, in->_mp_d, limb_cnt); + res->_mp_size = in->_mp_size >= 0 ? res_size : -res_size; +} diff --git a/contrib/libgmp/mpz/tdiv_r_ui.c b/contrib/libgmp/mpz/tdiv_r_ui.c new file mode 100644 index 0000000..0428b52 --- /dev/null +++ b/contrib/libgmp/mpz/tdiv_r_ui.c @@ -0,0 +1,64 @@ +/* mpz_tdiv_r_ui(rem, dividend, divisor_limb) + -- Set REM to DIVDEND mod DIVISOR_LIMB. + +Copyright (C) 1991, 1993, 1994, 1996 Free Software Foundation, Inc. + +This file is part of the GNU MP Library. + +The GNU MP Library is free software; you can redistribute it and/or modify +it under the terms of the GNU Library General Public License as published by +the Free Software Foundation; either version 2 of the License, or (at your +option) any later version. + +The GNU MP Library is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public +License for more details. + +You should have received a copy of the GNU Library General Public License +along with the GNU MP Library; see the file COPYING.LIB. If not, write to +the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, +MA 02111-1307, USA. */ + +#include "gmp.h" +#include "gmp-impl.h" + +void +#if __STDC__ +mpz_tdiv_r_ui (mpz_ptr rem, mpz_srcptr dividend, unsigned long int divisor) +#else +mpz_tdiv_r_ui (rem, dividend, divisor) + mpz_ptr rem; + mpz_srcptr dividend; + unsigned long int divisor; +#endif +{ + mp_size_t dividend_size; + mp_size_t size; + mp_limb_t remainder_limb; + + dividend_size = dividend->_mp_size; + size = ABS (dividend_size); + + if (size == 0) + { + rem->_mp_size = 0; + return; + } + + /* No need for temporary allocation and copying if QUOT == DIVIDEND as + the divisor is just one limb, and thus no intermediate remainders + need to be stored. */ + + remainder_limb = mpn_mod_1 (dividend->_mp_d, size, (mp_limb_t) divisor); + + if (remainder_limb == 0) + rem->_mp_size = 0; + else + { + /* Store the single-limb remainder. We don't check if there's space + for just one limb, since no function ever makes zero space. */ + rem->_mp_size = dividend_size >= 0 ? 1 : -1; + rem->_mp_d[0] = remainder_limb; + } +} diff --git a/contrib/libgmp/mpz/tests/Makefile.in b/contrib/libgmp/mpz/tests/Makefile.in new file mode 100644 index 0000000..5a0cf59 --- /dev/null +++ b/contrib/libgmp/mpz/tests/Makefile.in @@ -0,0 +1,126 @@ +# Makefile for mpz/tests for GNU MP + +srcdir = . + +CC = gcc + +TEST_LIBS = ../../libgmp.a +INCLUDES = -I../../mpn -I$(srcdir)/../.. +CFLAGS = -g -O + +.c.o: + $(CC) -c $(INCLUDES) $(CFLAGS) $(XCFLAGS) $< + +TEST_SRCS = t-mul.c t-tdiv.c t-tdiv_ui.c t-fdiv.c t-fdiv_ui.c t-gcd.c \ + t-gcd2.c dive.c t-sqrtrem.c convert.c io.c logic.c t-powm.c t-powm_ui.c \ + reuse.c +TEST_OBJS = t-mul.o t-tdiv.o t-tdiv_ui.o t-fdiv.o t-fdiv_ui.o t-gcd.o \ + t-gcd2.o dive.o t-sqrtrem.o convert.o io.o logic.o t-powm.o t-powm_ui.o \ + reuse.o +TESTS = t-mul t-tdiv t-tdiv_ui t-fdiv t-fdiv_ui t-gcd t-gcd2 \ + dive t-sqrtrem convert io logic t-powm t-powm_ui reuse + +check: Makefile st-mul st-tdiv st-tdiv_ui st-fdiv st-fdiv_ui st-gcd st-gcd2 st-dive \ + st-sqrtrem st-convert st-io st-logic st-powm st-powm_ui st-reuse + @echo "The tests passed." + +st-mul: t-mul + ./t-mul + touch $@ +st-tdiv: t-tdiv + ./t-tdiv + touch $@ +st-tdiv_ui: t-tdiv_ui + ./t-tdiv_ui + touch $@ +st-fdiv: t-fdiv + ./t-fdiv + touch $@ +st-fdiv_ui: t-fdiv_ui + ./t-fdiv_ui + touch $@ +st-gcd: t-gcd + ./t-gcd + touch $@ +st-gcd2: t-gcd2 + ./t-gcd2 + touch $@ +st-dive: dive + ./dive + touch $@ +st-sqrtrem: t-sqrtrem + ./t-sqrtrem + touch $@ +st-convert: convert + ./convert + touch $@ +st-io: io + ./io + touch $@ +st-logic: logic + ./logic + touch $@ +st-powm: t-powm + ./t-powm + touch $@ +st-powm_ui: t-powm_ui + ./t-powm_ui + touch $@ +st-reuse: reuse + ./reuse + touch $@ + +t-mul: t-mul.o $(TEST_LIBS) + $(CC) -o $@ $@.o $(TEST_LIBS) $(CFLAGS) +t-tdiv: t-tdiv.o $(TEST_LIBS) + $(CC) -o $@ $@.o $(TEST_LIBS) $(CFLAGS) +t-tdiv_ui: t-tdiv_ui.o $(TEST_LIBS) + $(CC) -o $@ $@.o $(TEST_LIBS) $(CFLAGS) +t-fdiv: t-fdiv.o $(TEST_LIBS) + $(CC) -o $@ $@.o $(TEST_LIBS) $(CFLAGS) +t-fdiv_ui: t-fdiv_ui.o $(TEST_LIBS) + $(CC) -o $@ $@.o $(TEST_LIBS) $(CFLAGS) +t-gcd: t-gcd.o $(TEST_LIBS) + $(CC) -o $@ $@.o $(TEST_LIBS) $(CFLAGS) +t-gcd2: t-gcd2.o $(TEST_LIBS) + $(CC) -o $@ $@.o $(TEST_LIBS) $(CFLAGS) +dive: dive.o $(TEST_LIBS) + $(CC) -o $@ $@.o $(TEST_LIBS) $(CFLAGS) +t-sqrtrem: t-sqrtrem.o $(TEST_LIBS) + $(CC) -o $@ $@.o $(TEST_LIBS) $(CFLAGS) +convert: convert.o $(TEST_LIBS) + $(CC) -o $@ $@.o $(TEST_LIBS) $(CFLAGS) +io: io.o $(TEST_LIBS) + $(CC) -o $@ $@.o $(TEST_LIBS) $(CFLAGS) +logic: logic.o $(TEST_LIBS) + $(CC) -o $@ $@.o $(TEST_LIBS) $(CFLAGS) +t-powm: t-powm.o $(TEST_LIBS) + $(CC) -o $@ $@.o $(TEST_LIBS) $(CFLAGS) +t-powm_ui: t-powm_ui.o $(TEST_LIBS) + $(CC) -o $@ $@.o $(TEST_LIBS) $(CFLAGS) +reuse: reuse.o $(TEST_LIBS) + $(CC) -o $@ $@.o $(TEST_LIBS) $(CFLAGS) + +t-mul.o: $(srcdir)/t-mul.c +t-tdiv.o: $(srcdir)/t-tdiv.c +t-tdiv_ui.o: $(srcdir)/t-tdiv_ui.c +t-fdiv.o: $(srcdir)/t-fdiv.c +t-fdiv_ui.o: $(srcdir)/t-fdiv_ui.c +t-gcd.o: $(srcdir)/t-gcd.c +t-gcd2.o: $(srcdir)/t-gcd2.c +dive.o: $(srcdir)/dive.c +t-sqrtrem.o: $(srcdir)/t-sqrtrem.c +convert.o: $(srcdir)/convert.c +io.o: $(srcdir)/io.c +logic.o: $(srcdir)/logic.c +t-powm.o: $(srcdir)/t-powm.c +t-powm_ui.o: $(srcdir)/t-powm_ui.c +reuse.o: $(srcdir)/reuse.c + +clean mostlyclean: + rm -f *.o st-* $(TESTS) +distclean maintainer-clean: clean + rm -f Makefile config.status + +Makefile: $(srcdir)/Makefile.in + $(SHELL) ./config.status diff --git a/contrib/libgmp/mpz/tests/configure.in b/contrib/libgmp/mpz/tests/configure.in new file mode 100644 index 0000000..dacc177 --- /dev/null +++ b/contrib/libgmp/mpz/tests/configure.in @@ -0,0 +1,11 @@ +# This file is a shell script that supplies the information necessary +# to tailor a template configure script into the configure script +# appropriate for this directory. For more information, check any +# existing configure script. + +srctrigger=t-mul.c +srcname="gmp/mpz/tests" + +# per-host: + +# per-target: diff --git a/contrib/libgmp/mpz/tests/convert.c b/contrib/libgmp/mpz/tests/convert.c new file mode 100644 index 0000000..1d82370 --- /dev/null +++ b/contrib/libgmp/mpz/tests/convert.c @@ -0,0 +1,80 @@ +/* Test conversion using mpz_get_str and mpz_set_str. + +Copyright (C) 1993, 1994, 1996 Free Software Foundation, Inc. + +This file is part of the GNU MP Library. + +The GNU MP Library is free software; you can redistribute it and/or modify +it under the terms of the GNU Library General Public License as published by +the Free Software Foundation; either version 2 of the License, or (at your +option) any later version. + +The GNU MP Library is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public +License for more details. + +You should have received a copy of the GNU Library General Public License +along with the GNU MP Library; see the file COPYING.LIB. If not, write to +the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, +MA 02111-1307, USA. */ + +#include <stdio.h> +#include "gmp.h" +#include "gmp-impl.h" +#include "urandom.h" + +void debug_mp (); + +#ifndef SIZE +#define SIZE 32 +#endif + +main (argc, argv) + int argc; + char **argv; +{ + MP_INT op1, op2; + mp_size_t size; + int i; + int reps = 100000; + char *str; + int base; + + if (argc == 2) + reps = atoi (argv[1]); + + mpz_init (&op1); + mpz_init (&op2); + + for (i = 0; i < reps; i++) + { + size = urandom () % SIZE - SIZE/2; + + mpz_random2 (&op1, size); + base = urandom () % 36 + 1; + if (base == 1) + base = 0; + + str = mpz_get_str ((char *) 0, base, &op1); + mpz_set_str (&op2, str, base); + free (str); + + if (mpz_cmp (&op1, &op2)) + { + fprintf (stderr, "ERROR\n"); + fprintf (stderr, "op1 = "); debug_mp (&op1, -16); + fprintf (stderr, "base = %d\n", base); + abort (); + } + } + + exit (0); +} + +void +debug_mp (x, base) + MP_INT *x; +{ + mpz_out_str (stderr, base, x); fputc ('\n', stderr); +} diff --git a/contrib/libgmp/mpz/tests/dive.c b/contrib/libgmp/mpz/tests/dive.c new file mode 100644 index 0000000..8d3516d --- /dev/null +++ b/contrib/libgmp/mpz/tests/dive.c @@ -0,0 +1,87 @@ +/* Test mpz_mul, mpz_divexact. + +Copyright (C) 1996 Free Software Foundation, Inc. + +This file is part of the GNU MP Library. + +The GNU MP Library is free software; you can redistribute it and/or modify +it under the terms of the GNU Library General Public License as published by +the Free Software Foundation; either version 2 of the License, or (at your +option) any later version. + +The GNU MP Library is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public +License for more details. + +You should have received a copy of the GNU Library General Public License +along with the GNU MP Library; see the file COPYING.LIB. If not, write to +the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, +MA 02111-1307, USA. */ + +#include <stdio.h> +#include "gmp.h" +#include "gmp-impl.h" +#include "urandom.h" + +void debug_mp (); + +#ifndef SIZE +#define SIZE 32 +#endif + +main (argc, argv) + int argc; + char **argv; +{ + mpz_t op1, op2; + mpz_t prod, quot; + mp_size_t size; + int i; + int reps = 100000; + + if (argc == 2) + reps = atoi (argv[1]); + + mpz_init (op1); + mpz_init (op2); + mpz_init (prod); + mpz_init (quot); + + for (i = 0; i < reps; i++) + { + size = urandom () % SIZE - SIZE/2; + mpz_random2 (op1, size); + + do + { + size = urandom () % SIZE - SIZE/2; + mpz_random2 (op2, size); + } + while (mpz_cmp_ui (op2, 0) == 0); + + mpz_mul (prod, op1, op2); + + mpz_divexact (quot, prod, op2); + if (mpz_cmp (quot, op1) != 0) + dump_abort (quot, op1); + } + + exit (0); +} + +dump_abort (op1, op2) + mpz_t op1, op2; +{ + fprintf (stderr, "ERROR\n"); + fprintf (stderr, "ref = "); debug_mp (op1, -16); + fprintf (stderr, "wrong = "); debug_mp (op2, -16); + abort(); +} + +void +debug_mp (x, base) + mpz_t x; +{ + mpz_out_str (stderr, base, x); fputc ('\n', stderr); +} diff --git a/contrib/libgmp/mpz/tests/io-binary.c b/contrib/libgmp/mpz/tests/io-binary.c new file mode 100644 index 0000000..c28f2a5 --- /dev/null +++ b/contrib/libgmp/mpz/tests/io-binary.c @@ -0,0 +1,76 @@ +/* Test mpz_inp_binary and mpz_out_binary. + + We write and read back some test strings, and both compare + the numerical result, and make sure the pattern on file is + what we expect. The latter is important for compatibility + between machines with different word sizes. */ + +#include <stdio.h> +#include "gmp.h" + +FILE *file; + +test (str, binary_len, binary_str) + char *str; + int binary_len; + char *binary_str; +{ + mpz_t x, y; + int n_written; + char buf[100]; + + mpz_init_set_str (x, str, 0); + mpz_init (y); + + fseek (file, 0, SEEK_SET); + mpz_out_binary (file, x); + n_written = ftell (file); + if (n_written != binary_len) + abort (); + + fseek (file, 0, SEEK_SET); + mpz_inp_binary (y, file); + if (n_written != ftell (file)) + abort (); + if (mpz_cmp (x, y) != 0) + abort (); + + fseek (file, 0, SEEK_SET); + fread (buf, n_written, 1, file); + if (memcmp (buf, binary_str, binary_len) != 0) + abort (); + + mpz_clear (x); +} + +main () +{ + file = fopen ("xtmpfile", "w+"); + + test ("0", 4, + "\000\000\000\000"); + + test ("1", 5, + "\000\000\000\001\001"); + test ("0x123", 6, + "\000\000\000\002\001\043"); + test ("0xdeadbeef", 8, + "\000\000\000\004\336\255\276\357"); + test ("0xbabefaced", 9, + "\000\000\000\005\013\253\357\254\355"); + test ("0x123456789facade0", 12, + "\000\000\000\010\022\064\126\170\237\254\255\340"); + + test ("-1", 5, + "\377\377\377\377\001"); + test ("-0x123", 6, + "\377\377\377\376\001\043"); + test ("-0xdeadbeef", 8, + "\377\377\377\374\336\255\276\357"); + test ("-0xbabefaced", 9, + "\377\377\377\373\013\253\357\254\355"); + test ("-0x123456789facade0", 12, + "\377\377\377\370\022\064\126\170\237\254\255\340"); + + exit (0); +} diff --git a/contrib/libgmp/mpz/tests/io.c b/contrib/libgmp/mpz/tests/io.c new file mode 100644 index 0000000..3dfa9a5 --- /dev/null +++ b/contrib/libgmp/mpz/tests/io.c @@ -0,0 +1,86 @@ +/* Test conversion and I/O using mpz_out_str and mpz_inp_str. + +Copyright (C) 1993, 1994, 1996 Free Software Foundation, Inc. + +This file is part of the GNU MP Library. + +The GNU MP Library is free software; you can redistribute it and/or modify +it under the terms of the GNU Library General Public License as published by +the Free Software Foundation; either version 2 of the License, or (at your +option) any later version. + +The GNU MP Library is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public +License for more details. + +You should have received a copy of the GNU Library General Public License +along with the GNU MP Library; see the file COPYING.LIB. If not, write to +the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, +MA 02111-1307, USA. */ + +#include <stdio.h> +#include "gmp.h" +#include "gmp-impl.h" +#include "urandom.h" + +void debug_mp (); + +#ifndef SIZE +#define SIZE 16 +#endif + +main (argc, argv) + int argc; + char **argv; +{ + MP_INT op1, op2; + mp_size_t size; + int i; + int reps = 10000; + FILE *fsin, *fsout; + int fd[2]; + int base; + + if (argc == 2) + reps = atoi (argv[1]); + + mpz_init (&op1); + mpz_init (&op2); + + pipe (fd); + fsin = fdopen (fd[0], "r"); + fsout = fdopen (fd[1], "w"); + + for (i = 0; i < reps; i++) + { + size = urandom () % SIZE - SIZE/2; + + mpz_random2 (&op1, size); + base = urandom () % 36 + 1; + if (base == 1) + base = 0; + + mpz_out_str (fsout, base, &op1); + putc (' ', fsout); + fflush (fsout); + mpz_inp_str (&op2, fsin, base); + + if (mpz_cmp (&op1, &op2)) + { + fprintf (stderr, "ERROR\n"); + fprintf (stderr, "op1 = "); debug_mp (&op1, -16); + fprintf (stderr, "base = %d\n", base); + abort (); + } + } + + exit (0); +} + +void +debug_mp (x, base) + MP_INT *x; +{ + mpz_out_str (stderr, base, x); fputc ('\n', stderr); +} diff --git a/contrib/libgmp/mpz/tests/logic.c b/contrib/libgmp/mpz/tests/logic.c new file mode 100644 index 0000000..41a8cac --- /dev/null +++ b/contrib/libgmp/mpz/tests/logic.c @@ -0,0 +1,103 @@ +/* Test mpz_com, mpz_and, and mpz_ior. + +Copyright (C) 1993, 1994, 1996 Free Software Foundation, Inc. + +This file is part of the GNU MP Library. + +The GNU MP Library is free software; you can redistribute it and/or modify +it under the terms of the GNU Library General Public License as published by +the Free Software Foundation; either version 2 of the License, or (at your +option) any later version. + +The GNU MP Library is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public +License for more details. + +You should have received a copy of the GNU Library General Public License +along with the GNU MP Library; see the file COPYING.LIB. If not, write to +the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, +MA 02111-1307, USA. */ + +#include <stdio.h> +#include "gmp.h" +#include "gmp-impl.h" +#include "urandom.h" + +void debug_mp (); + +#ifndef SIZE +#define SIZE 16 +#endif + +main (argc, argv) + int argc; + char **argv; +{ + mpz_t x, y, r1, r2; + mpz_t t1, t2, t3, t4; + mp_size_t xsize, ysize; + int i; + int reps = 100000; + + if (argc == 2) + reps = atoi (argv[1]); + + mpz_init (x); + mpz_init (y); + mpz_init (r1); + mpz_init (r2); + mpz_init (t1); + mpz_init (t2); + mpz_init (t3); + mpz_init (t4); + + for (i = 0; i < reps; i++) + { + xsize = urandom () % SIZE - SIZE/2; + mpz_random2 (x, xsize); + + ysize = urandom () % SIZE - SIZE/2; + mpz_random2 (y, ysize); + + mpz_com (r1, x); + mpz_com (r1, r1); + if (mpz_cmp (r1, x) != 0) + dump_abort (); + + mpz_com (r1, y); + mpz_com (r2, r1); + if (mpz_cmp (r2, y) != 0) + dump_abort (); + + mpz_com (t1, x); + mpz_com (t2, y); + mpz_and (t3, t1, t2); + mpz_com (r1, t3); + mpz_ior (r2, x, y); + if (mpz_cmp (r1, r2) != 0) + dump_abort (); + + mpz_com (t1, x); + mpz_com (t2, y); + mpz_ior (t3, t1, t2); + mpz_com (r1, t3); + mpz_and (r2, x, y); + if (mpz_cmp (r1, r2) != 0) + dump_abort (); + } + + exit (0); +} + +dump_abort () +{ + abort(); +} + +void +debug_mp (x, base) + MP_INT *x; +{ + mpz_out_str (stderr, base, x); fputc ('\n', stderr); +} diff --git a/contrib/libgmp/mpz/tests/reuse.c b/contrib/libgmp/mpz/tests/reuse.c new file mode 100644 index 0000000..52fc5a5 --- /dev/null +++ b/contrib/libgmp/mpz/tests/reuse.c @@ -0,0 +1,135 @@ +/* Test that routines allow reusing a source variable as destination. */ + +#include <stdio.h> +#include "gmp.h" +#include "gmp-impl.h" +#include "urandom.h" + +#ifndef SIZE +#define SIZE 16 +#endif + +#if __STDC__ +typedef void (*dss_func) (mpz_ptr, mpz_srcptr, mpz_srcptr); +#else +typedef void (*dss_func) (); +#endif + +dss_func dss_funcs[] = +{ + mpz_add, mpz_and, mpz_cdiv_q, mpz_cdiv_r, mpz_fdiv_q, mpz_fdiv_r, + mpz_gcd, mpz_ior, mpz_mul, mpz_sub, mpz_tdiv_q, mpz_tdiv_r +}; + +char *dss_func_names[] = +{ + "mpz_add", "mpz_and", "mpz_cdiv_q", "mpz_cdiv_r", "mpz_fdiv_q", "mpz_fdiv_r", + "mpz_gcd", "mpz_ior", "mpz_mul", "mpz_sub", "mpz_tdiv_q", "mpz_tdiv_r" +}; + +char dss_func_division[] = {0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1}; + +#if 0 +mpz_divexact /* requires special operands */ +#endif + +main (argc, argv) + int argc; + char **argv; +{ + int i; + int pass, reps = 10000; + mpz_t in1, in2, out1; + mpz_t res1, res2, res3; + + if (argc == 2) + reps = atoi (argv[1]); + + mpz_init (in1); + mpz_init (in2); + mpz_init (out1); + mpz_init (res1); + mpz_init (res2); + mpz_init (res3); + + for (pass = 1; pass <= reps; pass++) + { + mpz_random (in1, urandom () % SIZE - SIZE/2); + mpz_random (in2, urandom () % SIZE - SIZE/2); + + for (i = 0; i < sizeof (dss_funcs) / sizeof (dss_func); i++) + { + if (dss_func_division[i] && mpz_cmp_ui (in2, 0) == 0) + continue; + + (dss_funcs[i]) (res1, in1, in2); + + mpz_set (out1, in1); + (dss_funcs[i]) (out1, out1, in2); + mpz_set (res2, out1); + + mpz_set (out1, in2); + (dss_funcs[i]) (out1, in1, out1); + mpz_set (res3, out1); + + if (mpz_cmp (res1, res2) != 0) + dump_abort (dss_func_names[i], in1, in2); + if (mpz_cmp (res1, res3) != 0) + dump_abort (dss_func_names[i], in1, in2); + } + } + + exit (0); +} + +dump_abort (name, in1, in2) + char *name; + mpz_t in1, in2; +{ + printf ("failure in %s (", name); + mpz_out_str (stdout, -16, in1); + printf (" "); + mpz_out_str (stdout, -16, in2); + printf (")\n"); + abort (); +} + +#if 0 +void mpz_add_ui _PROTO ((mpz_ptr, mpz_srcptr, unsigned long int)); +void mpz_div_2exp _PROTO ((mpz_ptr, mpz_srcptr, unsigned long int)); +void mpz_mod_2exp _PROTO ((mpz_ptr, mpz_srcptr, unsigned long int)); +void mpz_mul_2exp _PROTO ((mpz_ptr, mpz_srcptr, unsigned long int)); +void mpz_mul_ui _PROTO ((mpz_ptr, mpz_srcptr, unsigned long int)); +void mpz_pow_ui _PROTO ((mpz_ptr, mpz_srcptr, unsigned long int)); +void mpz_sub_ui _PROTO ((mpz_ptr, mpz_srcptr, unsigned long int)); +void mpz_tdiv_q_ui _PROTO ((mpz_ptr, mpz_srcptr, unsigned long int)); +void mpz_tdiv_r_ui _PROTO ((mpz_ptr, mpz_srcptr, unsigned long int)); + +void mpz_abs _PROTO ((mpz_ptr, mpz_srcptr)); +void mpz_com _PROTO ((mpz_ptr, mpz_srcptr)); +void mpz_sqrt _PROTO ((mpz_ptr, mpz_srcptr)); +void mpz_neg _PROTO ((mpz_ptr, mpz_srcptr)); + +void mpz_tdiv_qr_ui _PROTO ((mpz_ptr, mpz_ptr, mpz_srcptr, unsigned long int)); + +void mpz_powm_ui _PROTO ((mpz_ptr, mpz_srcptr, unsigned long int, mpz_srcptr)); + +void mpz_gcdext _PROTO ((mpz_ptr, mpz_ptr, mpz_ptr, mpz_srcptr, mpz_srcptr)); + +void mpz_cdiv_qr _PROTO ((mpz_ptr, mpz_ptr, mpz_srcptr, mpz_srcptr)); +void mpz_fdiv_qr _PROTO ((mpz_ptr, mpz_ptr, mpz_srcptr, mpz_srcptr)); +void mpz_tdiv_qr _PROTO ((mpz_ptr, mpz_ptr, mpz_srcptr, mpz_srcptr)); + +void mpz_powm _PROTO ((mpz_ptr, mpz_srcptr, mpz_srcptr, mpz_srcptr)); + +void mpz_sqrtrem _PROTO ((mpz_ptr, mpz_ptr, mpz_srcptr)); + +unsigned long int mpz_cdiv_qr_ui _PROTO ((mpz_ptr, mpz_ptr, mpz_srcptr, unsigned long int)); +unsigned long int mpz_fdiv_qr_ui _PROTO ((mpz_ptr, mpz_ptr, mpz_srcptr, unsigned long int)); + +unsigned long int mpz_cdiv_q_ui _PROTO ((mpz_ptr, mpz_srcptr, unsigned long int)); +unsigned long int mpz_cdiv_r_ui _PROTO ((mpz_ptr, mpz_srcptr, unsigned long int)); +unsigned long int mpz_fdiv_q_ui _PROTO ((mpz_ptr, mpz_srcptr, unsigned long int)); +unsigned long int mpz_fdiv_r_ui _PROTO ((mpz_ptr, mpz_srcptr, unsigned long int)); +unsigned long int mpz_gcd_ui _PROTO ((mpz_ptr, mpz_srcptr, unsigned long int)); +#endif diff --git a/contrib/libgmp/mpz/tests/t-fdiv.c b/contrib/libgmp/mpz/tests/t-fdiv.c new file mode 100644 index 0000000..9de22d7 --- /dev/null +++ b/contrib/libgmp/mpz/tests/t-fdiv.c @@ -0,0 +1,118 @@ +/* Test mpz_abs, mpz_add, mpz_cmp, mpz_cmp_ui, mpz_fdiv_qr, mpz_fdiv_q, + mpz_fdiv_r, mpz_mul. + +Copyright (C) 1993, 1994, 1996 Free Software Foundation, Inc. + +This file is part of the GNU MP Library. + +The GNU MP Library is free software; you can redistribute it and/or modify +it under the terms of the GNU Library General Public License as published by +the Free Software Foundation; either version 2 of the License, or (at your +option) any later version. + +The GNU MP Library is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public +License for more details. + +You should have received a copy of the GNU Library General Public License +along with the GNU MP Library; see the file COPYING.LIB. If not, write to +the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, +MA 02111-1307, USA. */ + +#include <stdio.h> +#include "gmp.h" +#include "gmp-impl.h" +#include "urandom.h" + +void debug_mp (); + +#ifndef SIZE +#define SIZE 16 +#endif + +main (argc, argv) + int argc; + char **argv; +{ + mpz_t dividend, divisor; + mpz_t quotient, remainder; + mpz_t quotient2, remainder2; + mpz_t temp; + mp_size_t dividend_size, divisor_size; + int i; + int reps = 100000; + + if (argc == 2) + reps = atoi (argv[1]); + + mpz_init (dividend); + mpz_init (divisor); + mpz_init (quotient); + mpz_init (remainder); + mpz_init (quotient2); + mpz_init (remainder2); + mpz_init (temp); + + for (i = 0; i < reps; i++) + { + dividend_size = urandom () % SIZE - SIZE/2; + mpz_random2 (dividend, dividend_size); + + divisor_size = urandom () % SIZE - SIZE/2; + mpz_random2 (divisor, divisor_size); + if (mpz_cmp_ui (divisor, 0) == 0) + continue; + + mpz_fdiv_qr (quotient, remainder, dividend, divisor); + mpz_fdiv_q (quotient2, dividend, divisor); + mpz_fdiv_r (remainder2, dividend, divisor); + + /* First determine that the quotients and remainders computed + with different functions are equal. */ + if (mpz_cmp (quotient, quotient2) != 0) + dump_abort (dividend, divisor); + if (mpz_cmp (remainder, remainder2) != 0) + dump_abort (dividend, divisor); + + /* Check if the sign of the quotient is correct. */ + if (mpz_cmp_ui (quotient, 0) != 0) + if ((mpz_cmp_ui (quotient, 0) < 0) + != ((mpz_cmp_ui (dividend, 0) ^ mpz_cmp_ui (divisor, 0)) < 0)) + dump_abort (dividend, divisor); + + /* Check if the remainder has the same sign as the divisor + (quotient rounded towards minus infinity). */ + if (mpz_cmp_ui (remainder, 0) != 0) + if ((mpz_cmp_ui (remainder, 0) < 0) != (mpz_cmp_ui (divisor, 0) < 0)) + dump_abort (dividend, divisor); + + mpz_mul (temp, quotient, divisor); + mpz_add (temp, temp, remainder); + if (mpz_cmp (temp, dividend) != 0) + dump_abort (dividend, divisor); + + mpz_abs (temp, divisor); + mpz_abs (remainder, remainder); + if (mpz_cmp (remainder, temp) >= 0) + dump_abort (dividend, divisor); + } + + exit (0); +} + +dump_abort (dividend, divisor) + mpz_t dividend, divisor; +{ + fprintf (stderr, "ERROR\n"); + fprintf (stderr, "dividend = "); debug_mp (dividend, -16); + fprintf (stderr, "divisor = "); debug_mp (divisor, -16); + abort(); +} + +void +debug_mp (x, base) + mpz_t x; +{ + mpz_out_str (stderr, base, x); fputc ('\n', stderr); +} diff --git a/contrib/libgmp/mpz/tests/t-fdiv_ui.c b/contrib/libgmp/mpz/tests/t-fdiv_ui.c new file mode 100644 index 0000000..74ba9fc --- /dev/null +++ b/contrib/libgmp/mpz/tests/t-fdiv_ui.c @@ -0,0 +1,117 @@ +/* Test mpz_abs, mpz_add, mpz_cmp, mpz_cmp_ui, mpz_fdiv_qr_ui, mpz_fdiv_q_ui, + mpz_fdiv_r_ui, mpz_mul, mpz_mul_ui. + +Copyright (C) 1993, 1994, 1996 Free Software Foundation, Inc. + +This file is part of the GNU MP Library. + +The GNU MP Library is free software; you can redistribute it and/or modify +it under the terms of the GNU Library General Public License as published by +the Free Software Foundation; either version 2 of the License, or (at your +option) any later version. + +The GNU MP Library is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public +License for more details. + +You should have received a copy of the GNU Library General Public License +along with the GNU MP Library; see the file COPYING.LIB. If not, write to +the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, +MA 02111-1307, USA. */ + +#include <stdio.h> +#include "gmp.h" +#include "gmp-impl.h" +#include "urandom.h" + +void debug_mp (); + +#ifndef SIZE +#define SIZE 16 +#endif + +main (argc, argv) + int argc; + char **argv; +{ + mpz_t dividend; + mpz_t quotient, remainder; + mpz_t quotient2, remainder2; + mpz_t temp; + mp_size_t dividend_size; + mp_limb_t divisor; + int i; + int reps = 100000; + + if (argc == 2) + reps = atoi (argv[1]); + + mpz_init (dividend); + mpz_init (quotient); + mpz_init (remainder); + mpz_init (quotient2); + mpz_init (remainder2); + mpz_init (temp); + + for (i = 0; i < reps; i++) + { + dividend_size = urandom () % SIZE - SIZE/2; + mpz_random2 (dividend, dividend_size); + + divisor = urandom (); + if (divisor == 0) + continue; + + mpz_fdiv_qr_ui (quotient, remainder, dividend, divisor); + mpz_fdiv_q_ui (quotient2, dividend, divisor); + mpz_fdiv_r_ui (remainder2, dividend, divisor); + + /* First determine that the quotients and remainders computed + with different functions are equal. */ + if (mpz_cmp (quotient, quotient2) != 0) + dump_abort (dividend, divisor); + if (mpz_cmp (remainder, remainder2) != 0) + dump_abort (dividend, divisor); + + /* Check if the sign of the quotient is correct. */ + if (mpz_cmp_ui (quotient, 0) != 0) + if ((mpz_cmp_ui (quotient, 0) < 0) + != (mpz_cmp_ui (dividend, 0) < 0)) + dump_abort (dividend, divisor); + + /* Check if the remainder has the same sign as the divisor + (quotient rounded towards minus infinity). */ + if (mpz_cmp_ui (remainder, 0) != 0) + if (mpz_cmp_ui (remainder, 0) < 0) + dump_abort (dividend, divisor); + + mpz_mul_ui (temp, quotient, divisor); + mpz_add (temp, temp, remainder); + if (mpz_cmp (temp, dividend) != 0) + dump_abort (dividend, divisor); + + mpz_abs (remainder, remainder); + if (mpz_cmp_ui (remainder, divisor) >= 0) + dump_abort (dividend, divisor); + } + + exit (0); +} + +dump_abort (dividend, divisor) + mpz_t dividend; + mp_limb_t divisor; +{ + fprintf (stderr, "ERROR\n"); + fprintf (stderr, "dividend = "); debug_mp (dividend, -16); + fprintf (stderr, "divisor = %lX\n", divisor); + abort(); +} + +void +debug_mp (x, base) + mpz_t x; +{ + mpz_out_str (stderr, base, x); fputc ('\n', stderr); +} diff --git a/contrib/libgmp/mpz/tests/t-gcd.c b/contrib/libgmp/mpz/tests/t-gcd.c new file mode 100644 index 0000000..d9a7884 --- /dev/null +++ b/contrib/libgmp/mpz/tests/t-gcd.c @@ -0,0 +1,132 @@ +/* Test mpz_gcd, mpz_gcdext, mpz_mul, mpz_tdiv_r, mpz_add, mpz_cmp, + mpz_cmp_ui, mpz_init_set, mpz_set, mpz_clear. + +Copyright (C) 1991, 1993, 1994, 1996 Free Software Foundation, Inc. + +This file is part of the GNU MP Library. + +The GNU MP Library is free software; you can redistribute it and/or modify +it under the terms of the GNU Library General Public License as published by +the Free Software Foundation; either version 2 of the License, or (at your +option) any later version. + +The GNU MP Library is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public +License for more details. + +You should have received a copy of the GNU Library General Public License +along with the GNU MP Library; see the file COPYING.LIB. If not, write to +the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, +MA 02111-1307, USA. */ + +#include <stdio.h> +#include "gmp.h" +#include "gmp-impl.h" +#include "urandom.h" + +void mpz_refgcd (), debug_mp (); + +#ifndef SIZE +#define SIZE 256 /* really needs to be this large to exercise corner cases! */ +#endif + +main (argc, argv) + int argc; + char **argv; +{ + mpz_t op1, op2; + mpz_t refgcd, gcd, s, t; + mpz_t temp1, temp2; + mp_size_t op1_size, op2_size; + int i; + int reps = 1000; + + if (argc == 2) + reps = atoi (argv[1]); + + mpz_init (op1); + mpz_init (op2); + mpz_init (refgcd); + mpz_init (gcd); + mpz_init (temp1); + mpz_init (temp2); + mpz_init (s); + mpz_init (t); + + for (i = 0; i < reps; i++) + { + op1_size = urandom () % SIZE - SIZE/2; + op2_size = urandom () % SIZE - SIZE/2; + + mpz_random2 (op1, op1_size); + mpz_random2 (op2, op2_size); + + mpz_refgcd (refgcd, op1, op2); + + mpz_gcd (gcd, op1, op2); + if (mpz_cmp (refgcd, gcd)) + dump_abort (op1, op2); + + mpz_gcdext (gcd, s, t, op1, op2); + if (mpz_cmp (refgcd, gcd)) + dump_abort (op1, op2); + + mpz_mul (temp1, s, op1); + mpz_mul (temp2, t, op2); + mpz_add (gcd, temp1, temp2); + if (mpz_cmp (refgcd, gcd)) + dump_abort (op1, op2); + } + + exit (0); +} + +void +mpz_refgcd (g, x, y) + mpz_t g; + mpz_t x, y; +{ + mpz_t xx, yy; + + mpz_init (xx); + mpz_init (yy); + + mpz_abs (xx, x); + mpz_abs (yy, y); + + for (;;) + { + if (mpz_cmp_ui (yy, 0) == 0) + { + mpz_set (g, xx); + break; + } + mpz_tdiv_r (xx, xx, yy); + if (mpz_cmp_ui (xx, 0) == 0) + { + mpz_set (g, yy); + break; + } + mpz_tdiv_r (yy, yy, xx); + } + + mpz_clear (xx); + mpz_clear (yy); +} + +dump_abort (op1, op2) + mpz_t op1, op2; +{ + fprintf (stderr, "ERROR\n"); + fprintf (stderr, "op1 = "); debug_mp (op1, -16); + fprintf (stderr, "op2 = "); debug_mp (op2, -16); + abort(); +} + +void +debug_mp (x, base) + mpz_t x; +{ + mpz_out_str (stderr, base, x); fputc ('\n', stderr); +} diff --git a/contrib/libgmp/mpz/tests/t-gcd2.c b/contrib/libgmp/mpz/tests/t-gcd2.c new file mode 100644 index 0000000..b7ad67c --- /dev/null +++ b/contrib/libgmp/mpz/tests/t-gcd2.c @@ -0,0 +1,137 @@ +/* Test mpz_gcd, mpz_gcdext, mpz_mul, mpz_tdiv_r, mpz_add, mpz_cmp, + mpz_cmp_ui, mpz_init_set, mpz_set, mpz_clear. + +Copyright (C) 1991, 1993, 1994, 1996 Free Software Foundation, Inc. + +This file is part of the GNU MP Library. + +The GNU MP Library is free software; you can redistribute it and/or modify +it under the terms of the GNU Library General Public License as published by +the Free Software Foundation; either version 2 of the License, or (at your +option) any later version. + +The GNU MP Library is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public +License for more details. + +You should have received a copy of the GNU Library General Public License +along with the GNU MP Library; see the file COPYING.LIB. If not, write to +the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, +MA 02111-1307, USA. */ + +#include <stdio.h> +#include "gmp.h" +#include "gmp-impl.h" +#include "urandom.h" + +void mpz_refgcd (), debug_mp (); + +#ifndef SIZE +#define SIZE 128 +#endif + +main (argc, argv) + int argc; + char **argv; +{ + mpz_t op1, op2, x; + mpz_t refgcd, gcd, s, t; + mpz_t temp1, temp2; + mp_size_t op1_size, op2_size, x_size; + int i; + int reps = 1000; + + if (argc == 2) + reps = atoi (argv[1]); + + mpz_init (op1); + mpz_init (op2); + mpz_init (x); + mpz_init (refgcd); + mpz_init (gcd); + mpz_init (temp1); + mpz_init (temp2); + mpz_init (s); + mpz_init (t); + + for (i = 0; i < reps; i++) + { + op1_size = urandom () % SIZE - SIZE/2; + op2_size = urandom () % SIZE - SIZE/2; + x_size = urandom () % SIZE/2; + + mpz_random2 (op1, op1_size); + mpz_random2 (op2, op2_size); + mpz_random2 (x, x_size); + mpz_mul (op1, op1, x); + mpz_mul (op2, op2, x); + + mpz_refgcd (refgcd, op1, op2); + + mpz_gcd (gcd, op1, op2); + if (mpz_cmp (refgcd, gcd)) + dump_abort (op1, op2); + + mpz_gcdext (gcd, s, t, op1, op2); + if (mpz_cmp (refgcd, gcd)) + dump_abort (op1, op2); + + mpz_mul (temp1, s, op1); + mpz_mul (temp2, t, op2); + mpz_add (gcd, temp1, temp2); + if (mpz_cmp (refgcd, gcd)) + dump_abort (op1, op2); + } + + exit (0); +} + +void +mpz_refgcd (g, x, y) + mpz_t g; + mpz_t x, y; +{ + mpz_t xx, yy; + + mpz_init (xx); + mpz_init (yy); + + mpz_abs (xx, x); + mpz_abs (yy, y); + + for (;;) + { + if (mpz_cmp_ui (yy, 0) == 0) + { + mpz_set (g, xx); + break; + } + mpz_tdiv_r (xx, xx, yy); + if (mpz_cmp_ui (xx, 0) == 0) + { + mpz_set (g, yy); + break; + } + mpz_tdiv_r (yy, yy, xx); + } + + mpz_clear (xx); + mpz_clear (yy); +} + +dump_abort (op1, op2) + mpz_t op1, op2; +{ + fprintf (stderr, "ERROR\n"); + fprintf (stderr, "op1 = "); debug_mp (op1, -16); + fprintf (stderr, "op2 = "); debug_mp (op2, -16); + abort(); +} + +void +debug_mp (x, base) + mpz_t x; +{ + mpz_out_str (stderr, base, x); fputc ('\n', stderr); +} diff --git a/contrib/libgmp/mpz/tests/t-mul.c b/contrib/libgmp/mpz/tests/t-mul.c new file mode 100644 index 0000000..b200cd7 --- /dev/null +++ b/contrib/libgmp/mpz/tests/t-mul.c @@ -0,0 +1,261 @@ +/* Test mpz_add, mpz_cmp, mpz_cmp_ui, mpz_divmod, mpz_mul. + +Copyright (C) 1991, 1993, 1994, 1996 Free Software Foundation, Inc. + +This file is part of the GNU MP Library. + +The GNU MP Library is free software; you can redistribute it and/or modify +it under the terms of the GNU Library General Public License as published by +the Free Software Foundation; either version 2 of the License, or (at your +option) any later version. + +The GNU MP Library is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public +License for more details. + +You should have received a copy of the GNU Library General Public License +along with the GNU MP Library; see the file COPYING.LIB. If not, write to +the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, +MA 02111-1307, USA. */ + +#include <stdio.h> +#include "gmp.h" +#include "gmp-impl.h" +#include "longlong.h" +#include "urandom.h" + +void debug_mp (); +mp_size_t _mpn_mul_classic (); +void mpz_refmul (); + +#ifndef SIZE +#define SIZE 128 +#endif + +main (argc, argv) + int argc; + char **argv; +{ + mpz_t multiplier, multiplicand; + mpz_t product, ref_product; + mpz_t quotient, remainder; + mp_size_t multiplier_size, multiplicand_size; + int i; + int reps = 10000; + + if (argc == 2) + reps = atoi (argv[1]); + + mpz_init (multiplier); + mpz_init (multiplicand); + mpz_init (product); + mpz_init (ref_product); + mpz_init (quotient); + mpz_init (remainder); + + for (i = 0; i < reps; i++) + { + multiplier_size = urandom () % SIZE - SIZE/2; + multiplicand_size = urandom () % SIZE - SIZE/2; + + mpz_random2 (multiplier, multiplier_size); + mpz_random2 (multiplicand, multiplicand_size); + + mpz_mul (product, multiplier, multiplicand); + mpz_refmul (ref_product, multiplier, multiplicand); + if (mpz_cmp_ui (multiplicand, 0) != 0) + mpz_divmod (quotient, remainder, product, multiplicand); + + if (mpz_cmp (product, ref_product)) + dump_abort (multiplier, multiplicand); + + if (mpz_cmp_ui (multiplicand, 0) != 0) + if (mpz_cmp_ui (remainder, 0) || mpz_cmp (quotient, multiplier)) + dump_abort (multiplier, multiplicand); + } + + exit (0); +} + +void +mpz_refmul (w, u, v) + mpz_t w; + const mpz_t u; + const mpz_t v; +{ + mp_size_t usize = u->_mp_size; + mp_size_t vsize = v->_mp_size; + mp_size_t wsize; + mp_size_t sign_product; + mp_ptr up, vp; + mp_ptr wp; + mp_ptr free_me = NULL; + size_t free_me_size; + TMP_DECL (marker); + + TMP_MARK (marker); + sign_product = usize ^ vsize; + usize = ABS (usize); + vsize = ABS (vsize); + + if (usize < vsize) + { + /* Swap U and V. */ + {const __mpz_struct *t = u; u = v; v = t;} + {mp_size_t t = usize; usize = vsize; vsize = t;} + } + + up = u->_mp_d; + vp = v->_mp_d; + wp = w->_mp_d; + + /* Ensure W has space enough to store the result. */ + wsize = usize + vsize; + if (w->_mp_alloc < wsize) + { + if (wp == up || wp == vp) + { + free_me = wp; + free_me_size = w->_mp_alloc; + } + else + (*_mp_free_func) (wp, w->_mp_alloc * BYTES_PER_MP_LIMB); + + w->_mp_alloc = wsize; + wp = (mp_ptr) (*_mp_allocate_func) (wsize * BYTES_PER_MP_LIMB); + w->_mp_d = wp; + } + else + { + /* Make U and V not overlap with W. */ + if (wp == up) + { + /* W and U are identical. Allocate temporary space for U. */ + up = (mp_ptr) TMP_ALLOC (usize * BYTES_PER_MP_LIMB); + /* Is V identical too? Keep it identical with U. */ + if (wp == vp) + vp = up; + /* Copy to the temporary space. */ + MPN_COPY (up, wp, usize); + } + else if (wp == vp) + { + /* W and V are identical. Allocate temporary space for V. */ + vp = (mp_ptr) TMP_ALLOC (vsize * BYTES_PER_MP_LIMB); + /* Copy to the temporary space. */ + MPN_COPY (vp, wp, vsize); + } + } + + wsize = _mpn_mul_classic (wp, up, usize, vp, vsize); + w->_mp_size = sign_product < 0 ? -wsize : wsize; + if (free_me != NULL) + (*_mp_free_func) (free_me, free_me_size * BYTES_PER_MP_LIMB); + + TMP_FREE (marker); +} + +mp_size_t +_mpn_mul_classic (prodp, up, usize, vp, vsize) + mp_ptr prodp; + mp_srcptr up; + mp_size_t usize; + mp_srcptr vp; + mp_size_t vsize; +{ + mp_size_t i, j; + mp_limb_t prod_low, prod_high; + mp_limb_t cy_dig; + mp_limb_t v_limb, c; + + if (vsize == 0) + return 0; + + /* Offset UP and PRODP so that the inner loop can be faster. */ + up += usize; + prodp += usize; + + /* Multiply by the first limb in V separately, as the result can + be stored (not added) to PROD. We also avoid a loop for zeroing. */ + v_limb = vp[0]; + cy_dig = 0; + j = -usize; + do + { + umul_ppmm (prod_high, prod_low, up[j], v_limb); + add_ssaaaa (cy_dig, prodp[j], prod_high, prod_low, 0, cy_dig); + j++; + } + while (j < 0); + + prodp[j] = cy_dig; + prodp++; + + /* For each iteration in the outer loop, multiply one limb from + U with one limb from V, and add it to PROD. */ + for (i = 1; i < vsize; i++) + { + v_limb = vp[i]; + cy_dig = 0; + j = -usize; + + /* Inner loops. Simulate the carry flag by jumping between + these loops. The first is used when there was no carry + in the previois iteration; the second when there was carry. */ + + do + { + umul_ppmm (prod_high, prod_low, up[j], v_limb); + add_ssaaaa (cy_dig, prod_low, prod_high, prod_low, 0, cy_dig); + c = prodp[j]; + prod_low += c; + prodp[j] = prod_low; + if (prod_low < c) + goto cy_loop; + ncy_loop: + j++; + } + while (j < 0); + + prodp[j] = cy_dig; + prodp++; + continue; + + do + { + umul_ppmm (prod_high, prod_low, up[j], v_limb); + add_ssaaaa (cy_dig, prod_low, prod_high, prod_low, 0, cy_dig); + c = prodp[j]; + prod_low += c + 1; + prodp[j] = prod_low; + if (prod_low > c) + goto ncy_loop; + cy_loop: + j++; + } + while (j < 0); + + cy_dig += 1; + prodp[j] = cy_dig; + prodp++; + } + + return usize + vsize - (cy_dig == 0); +} + +dump_abort (multiplier, multiplicand) + mpz_t multiplier, multiplicand; +{ + fprintf (stderr, "ERROR\n"); + fprintf (stderr, "multiplier = "); debug_mp (multiplier, -16); + fprintf (stderr, "multiplicand = "); debug_mp (multiplicand, -16); + abort(); +} + +void +debug_mp (x, base) + mpz_t x; +{ + mpz_out_str (stderr, base, x); fputc ('\n', stderr); +} diff --git a/contrib/libgmp/mpz/tests/t-powm.c b/contrib/libgmp/mpz/tests/t-powm.c new file mode 100644 index 0000000..02d7ca5 --- /dev/null +++ b/contrib/libgmp/mpz/tests/t-powm.c @@ -0,0 +1,125 @@ +/* Test mpz_powm, mpz_mul. mpz_mod, mpz_mod_ui, mpz_div_ui. + +Copyright (C) 1991, 1993, 1994, 1996 Free Software Foundation, Inc. + +This file is part of the GNU MP Library. + +The GNU MP Library is free software; you can redistribute it and/or modify +it under the terms of the GNU Library General Public License as published by +the Free Software Foundation; either version 2 of the License, or (at your +option) any later version. + +The GNU MP Library is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public +License for more details. + +You should have received a copy of the GNU Library General Public License +along with the GNU MP Library; see the file COPYING.LIB. If not, write to +the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, +MA 02111-1307, USA. */ + +#include <stdio.h> +#include "gmp.h" +#include "gmp-impl.h" +#include "urandom.h" + +void debug_mp (); + +#ifndef SIZE +#define SIZE 8 +#endif + +main (argc, argv) + int argc; + char **argv; +{ + mpz_t base, exp, mod; + mpz_t r1, r2, t1, exp2, base2; + mp_size_t base_size, exp_size, mod_size; + int i; + int reps = 10000; + + if (argc == 2) + reps = atoi (argv[1]); + + mpz_init (base); + mpz_init (exp); + mpz_init (mod); + mpz_init (r1); + mpz_init (r2); + mpz_init (t1); + mpz_init (exp2); + mpz_init (base2); + + for (i = 0; i < reps; i++) + { + base_size = urandom () % SIZE - SIZE/2; + mpz_random2 (base, base_size); + + exp_size = urandom () % SIZE; + mpz_random2 (exp, exp_size); + + mod_size = urandom () % SIZE /* - SIZE/2 */; + mpz_random2 (mod, mod_size); + if (mpz_cmp_ui (mod, 0) == 0) + continue; + + /* This is mathematically undefined. */ + if (mpz_cmp_ui (base, 0) == 0 && mpz_cmp_ui (exp, 0) == 0) + continue; + +#if 0 + putc ('\n', stderr); + debug_mp (base, -16); + debug_mp (exp, -16); + debug_mp (mod, -16); +#endif + + mpz_powm (r1, base, exp, mod); + + mpz_set_ui (r2, 1); + mpz_set (base2, base); + mpz_set (exp2, exp); + + mpz_mod (r2, r2, mod); /* needed when exp==0 and mod==1 */ + while (mpz_cmp_ui (exp2, 0) != 0) + { + mpz_mod_ui (t1, exp2, 2); + if (mpz_cmp_ui (t1, 0) != 0) + { + mpz_mul (r2, r2, base2); + mpz_mod (r2, r2, mod); + } + mpz_mul (base2, base2, base2); + mpz_mod (base2, base2, mod); + mpz_div_ui (exp2, exp2, 2); + } + +#if 0 + debug_mp (r1, -16); + debug_mp (r2, -16); +#endif + + if (mpz_cmp (r1, r2) != 0) + abort (); + } + + exit (0); +} + +dump_abort (dividend, divisor) + MP_INT *dividend, *divisor; +{ + fprintf (stderr, "ERROR\n"); + fprintf (stderr, "dividend = "); debug_mp (dividend, -16); + fprintf (stderr, "divisor = "); debug_mp (divisor, -16); + abort(); +} + +void +debug_mp (x, base) + MP_INT *x; +{ + mpz_out_str (stderr, base, x); fputc ('\n', stderr); +} diff --git a/contrib/libgmp/mpz/tests/t-powm_ui.c b/contrib/libgmp/mpz/tests/t-powm_ui.c new file mode 100644 index 0000000..b88fa98 --- /dev/null +++ b/contrib/libgmp/mpz/tests/t-powm_ui.c @@ -0,0 +1,120 @@ +/* Test mpz_powm_ui, mpz_mul. mpz_mod, mpz_mod_ui, mpz_div_ui. + +Copyright (C) 1991, 1993, 1994, 1996 Free Software Foundation, Inc. + +This file is part of the GNU MP Library. + +The GNU MP Library is free software; you can redistribute it and/or modify +it under the terms of the GNU Library General Public License as published by +the Free Software Foundation; either version 2 of the License, or (at your +option) any later version. + +The GNU MP Library is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public +License for more details. + +You should have received a copy of the GNU Library General Public License +along with the GNU MP Library; see the file COPYING.LIB. If not, write to +the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, +MA 02111-1307, USA. */ + +#include <stdio.h> +#include "gmp.h" +#include "gmp-impl.h" +#include "urandom.h" + +void debug_mp (); + +#ifndef SIZE +#define SIZE 8 +#endif + +main (argc, argv) + int argc; + char **argv; +{ + mpz_t base, mod; + mpz_t r1, r2, base2; + mp_size_t base_size, mod_size; + mp_limb_t exp, exp2; + int i; + int reps = 10000; + + if (argc == 2) + reps = atoi (argv[1]); + + mpz_init (base); + mpz_init (mod); + mpz_init (r1); + mpz_init (r2); + mpz_init (base2); + + for (i = 0; i < reps; i++) + { + base_size = urandom () % SIZE /* - SIZE/2 */; + mpz_random2 (base, base_size); + + mpn_random2 (&exp, 1); + + mod_size = urandom () % SIZE /* - SIZE/2 */; + mpz_random2 (mod, mod_size); + if (mpz_cmp_ui (mod, 0) == 0) + continue; + + /* This is mathematically undefined. */ + if (mpz_cmp_ui (base, 0) == 0 && exp == 0) + continue; + +#if 0 + putc ('\n', stderr); + debug_mp (base, -16); + debug_mp (mod, -16); +#endif + + mpz_powm_ui (r1, base, (unsigned long int) exp, mod); + + mpz_set_ui (r2, 1); + mpz_set (base2, base); + exp2 = exp; + + mpz_mod (r2, r2, mod); /* needed when exp==0 and mod==1 */ + while (exp2 != 0) + { + if (exp2 % 2 != 0) + { + mpz_mul (r2, r2, base2); + mpz_mod (r2, r2, mod); + } + mpz_mul (base2, base2, base2); + mpz_mod (base2, base2, mod); + exp2 = exp2 / 2; + } + +#if 0 + debug_mp (r1, -16); + debug_mp (r2, -16); +#endif + + if (mpz_cmp (r1, r2) != 0) + abort (); + } + + exit (0); +} + +dump_abort (dividend, divisor) + MP_INT *dividend, *divisor; +{ + fprintf (stderr, "ERROR\n"); + fprintf (stderr, "dividend = "); debug_mp (dividend, -16); + fprintf (stderr, "divisor = "); debug_mp (divisor, -16); + abort(); +} + +void +debug_mp (x, base) + MP_INT *x; +{ + mpz_out_str (stderr, base, x); fputc ('\n', stderr); +} diff --git a/contrib/libgmp/mpz/tests/t-sqrtrem.c b/contrib/libgmp/mpz/tests/t-sqrtrem.c new file mode 100644 index 0000000..f5fcd09 --- /dev/null +++ b/contrib/libgmp/mpz/tests/t-sqrtrem.c @@ -0,0 +1,98 @@ +/* Test mpz_add, mpz_add_ui, mpz_cmp, mpz_cmp, mpz_mul, mpz_sqrtrem. + +Copyright (C) 1991, 1993, 1994, 1996 Free Software Foundation, Inc. + +This file is part of the GNU MP Library. + +The GNU MP Library is free software; you can redistribute it and/or modify +it under the terms of the GNU Library General Public License as published by +the Free Software Foundation; either version 2 of the License, or (at your +option) any later version. + +The GNU MP Library is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public +License for more details. + +You should have received a copy of the GNU Library General Public License +along with the GNU MP Library; see the file COPYING.LIB. If not, write to +the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, +MA 02111-1307, USA. */ + +#include <stdio.h> +#include "gmp.h" +#include "gmp-impl.h" +#include "urandom.h" + +void debug_mp (); + +#ifndef SIZE +#define SIZE 16 +#endif + +main (argc, argv) + int argc; + char **argv; +{ + mpz_t x2; + mpz_t x, rem; + mpz_t temp, temp2; + mp_size_t x2_size; + int i; + int reps = 100000; + + if (argc == 2) + reps = atoi (argv[1]); + + mpz_init (x2); + mpz_init (x); + mpz_init (rem); + mpz_init (temp); + mpz_init (temp2); + + for (i = 0; i < reps; i++) + { + x2_size = urandom () % SIZE; + + mpz_random2 (x2, x2_size); + + mpz_sqrtrem (x, rem, x2); + mpz_mul (temp, x, x); + + /* Is square of result > argument? */ + if (mpz_cmp (temp, x2) > 0) + dump_abort (x2, x, rem); + + mpz_add_ui (temp2, x, 1); + mpz_mul (temp2, temp2, temp2); + + /* Is square of (result + 1) <= argument? */ + if (mpz_cmp (temp2, x2) <= 0) + dump_abort (x2, x, rem); + + mpz_add (temp2, temp, rem); + + /* Is the remainder wrong? */ + if (mpz_cmp (x2, temp2) != 0) + dump_abort (x2, x, rem); + } + + exit (0); +} + +dump_abort (x2, x, rem) + mpz_t x2, x, rem; +{ + fprintf (stderr, "ERROR\n"); + fprintf (stderr, "x2 = "); debug_mp (x2, -16); + fprintf (stderr, "x = "); debug_mp (x, -16); + fprintf (stderr, "remainder = "); debug_mp (rem, -16); + abort(); +} + +void +debug_mp (x, base) + mpz_t x; +{ + mpz_out_str (stderr, base, x); fputc ('\n', stderr); +} diff --git a/contrib/libgmp/mpz/tests/t-tdiv.c b/contrib/libgmp/mpz/tests/t-tdiv.c new file mode 100644 index 0000000..d646ed8 --- /dev/null +++ b/contrib/libgmp/mpz/tests/t-tdiv.c @@ -0,0 +1,118 @@ +/* Test mpz_abs, mpz_add, mpz_cmp, mpz_cmp_ui, mpz_tdiv_qr, mpz_tdiv_q, + mpz_tdiv_r, mpz_mul. + +Copyright (C) 1991, 1993, 1994, 1996 Free Software Foundation, Inc. + +This file is part of the GNU MP Library. + +The GNU MP Library is free software; you can redistribute it and/or modify +it under the terms of the GNU Library General Public License as published by +the Free Software Foundation; either version 2 of the License, or (at your +option) any later version. + +The GNU MP Library is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public +License for more details. + +You should have received a copy of the GNU Library General Public License +along with the GNU MP Library; see the file COPYING.LIB. If not, write to +the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, +MA 02111-1307, USA. */ + +#include <stdio.h> +#include "gmp.h" +#include "gmp-impl.h" +#include "urandom.h" + +void debug_mp (); + +#ifndef SIZE +#define SIZE 16 +#endif + +main (argc, argv) + int argc; + char **argv; +{ + mpz_t dividend, divisor; + mpz_t quotient, remainder; + mpz_t quotient2, remainder2; + mpz_t temp; + mp_size_t dividend_size, divisor_size; + int i; + int reps = 100000; + + if (argc == 2) + reps = atoi (argv[1]); + + mpz_init (dividend); + mpz_init (divisor); + mpz_init (quotient); + mpz_init (remainder); + mpz_init (quotient2); + mpz_init (remainder2); + mpz_init (temp); + + for (i = 0; i < reps; i++) + { + dividend_size = urandom () % SIZE - SIZE/2; + mpz_random2 (dividend, dividend_size); + + divisor_size = urandom () % SIZE - SIZE/2; + mpz_random2 (divisor, divisor_size); + if (mpz_cmp_ui (divisor, 0) == 0) + continue; + + mpz_tdiv_qr (quotient, remainder, dividend, divisor); + mpz_tdiv_q (quotient2, dividend, divisor); + mpz_tdiv_r (remainder2, dividend, divisor); + + /* First determine that the quotients and remainders computed + with different functions are equal. */ + if (mpz_cmp (quotient, quotient2) != 0) + dump_abort (dividend, divisor); + if (mpz_cmp (remainder, remainder2) != 0) + dump_abort (dividend, divisor); + + /* Check if the sign of the quotient is correct. */ + if (mpz_cmp_ui (quotient, 0) != 0) + if ((mpz_cmp_ui (quotient, 0) < 0) + != ((mpz_cmp_ui (dividend, 0) ^ mpz_cmp_ui (divisor, 0)) < 0)) + dump_abort (dividend, divisor); + + /* Check if the remainder has the same sign as the dividend + (quotient rounded towards 0). */ + if (mpz_cmp_ui (remainder, 0) != 0) + if ((mpz_cmp_ui (remainder, 0) < 0) != (mpz_cmp_ui (dividend, 0) < 0)) + dump_abort (dividend, divisor); + + mpz_mul (temp, quotient, divisor); + mpz_add (temp, temp, remainder); + if (mpz_cmp (temp, dividend) != 0) + dump_abort (dividend, divisor); + + mpz_abs (temp, divisor); + mpz_abs (remainder, remainder); + if (mpz_cmp (remainder, temp) >= 0) + dump_abort (dividend, divisor); + } + + exit (0); +} + +dump_abort (dividend, divisor) + mpz_t dividend, divisor; +{ + fprintf (stderr, "ERROR\n"); + fprintf (stderr, "dividend = "); debug_mp (dividend, -16); + fprintf (stderr, "divisor = "); debug_mp (divisor, -16); + abort(); +} + +void +debug_mp (x, base) + mpz_t x; +{ + mpz_out_str (stderr, base, x); fputc ('\n', stderr); +} diff --git a/contrib/libgmp/mpz/tests/t-tdiv_ui.c b/contrib/libgmp/mpz/tests/t-tdiv_ui.c new file mode 100644 index 0000000..8d73b11 --- /dev/null +++ b/contrib/libgmp/mpz/tests/t-tdiv_ui.c @@ -0,0 +1,117 @@ +/* Test mpz_abs, mpz_add, mpz_cmp, mpz_cmp_ui, mpz_tdiv_qr_ui, mpz_tdiv_q_ui, + mpz_tdiv_r_ui, mpz_mul_ui. + +Copyright (C) 1993, 1994, 1996 Free Software Foundation, Inc. + +This file is part of the GNU MP Library. + +The GNU MP Library is free software; you can redistribute it and/or modify +it under the terms of the GNU Library General Public License as published by +the Free Software Foundation; either version 2 of the License, or (at your +option) any later version. + +The GNU MP Library is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public +License for more details. + +You should have received a copy of the GNU Library General Public License +along with the GNU MP Library; see the file COPYING.LIB. If not, write to +the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, +MA 02111-1307, USA. */ + +#include <stdio.h> +#include "gmp.h" +#include "gmp-impl.h" +#include "urandom.h" + +void debug_mp (); + +#ifndef SIZE +#define SIZE 16 +#endif + +main (argc, argv) + int argc; + char **argv; +{ + mpz_t dividend; + mpz_t quotient, remainder; + mpz_t quotient2, remainder2; + mpz_t temp; + mp_size_t dividend_size; + mp_limb_t divisor; + int i; + int reps = 100000; + + if (argc == 2) + reps = atoi (argv[1]); + + mpz_init (dividend); + mpz_init (quotient); + mpz_init (remainder); + mpz_init (quotient2); + mpz_init (remainder2); + mpz_init (temp); + + for (i = 0; i < reps; i++) + { + dividend_size = urandom () % SIZE - SIZE/2; + mpz_random2 (dividend, dividend_size); + + divisor = urandom (); + if (divisor == 0) + continue; + + mpz_tdiv_qr_ui (quotient, remainder, dividend, divisor); + mpz_tdiv_q_ui (quotient2, dividend, divisor); + mpz_tdiv_r_ui (remainder2, dividend, divisor); + + /* First determine that the quotients and remainders computed + with different functions are equal. */ + if (mpz_cmp (quotient, quotient2) != 0) + dump_abort (dividend, divisor); + if (mpz_cmp (remainder, remainder2) != 0) + dump_abort (dividend, divisor); + + /* Check if the sign of the quotient is correct. */ + if (mpz_cmp_ui (quotient, 0) != 0) + if ((mpz_cmp_ui (quotient, 0) < 0) + != (mpz_cmp_ui (dividend, 0) < 0)) + dump_abort (dividend, divisor); + + /* Check if the remainder has the same sign as the dividend + (quotient rounded towards 0). */ + if (mpz_cmp_ui (remainder, 0) != 0) + if ((mpz_cmp_ui (remainder, 0) < 0) != (mpz_cmp_ui (dividend, 0) < 0)) + dump_abort (dividend, divisor); + + mpz_mul_ui (temp, quotient, divisor); + mpz_add (temp, temp, remainder); + if (mpz_cmp (temp, dividend) != 0) + dump_abort (dividend, divisor); + + mpz_abs (remainder, remainder); + if (mpz_cmp_ui (remainder, divisor) >= 0) + dump_abort (dividend, divisor); + } + + exit (0); +} + +dump_abort (dividend, divisor) + mpz_t dividend; + mp_limb_t divisor; +{ + fprintf (stderr, "ERROR\n"); + fprintf (stderr, "dividend = "); debug_mp (dividend, -16); + fprintf (stderr, "divisor = %lX\n", divisor); + abort(); +} + +void +debug_mp (x, base) + mpz_t x; +{ + mpz_out_str (stderr, base, x); fputc ('\n', stderr); +} diff --git a/contrib/libgmp/mpz/ui_pow_ui.c b/contrib/libgmp/mpz/ui_pow_ui.c new file mode 100644 index 0000000..19baca1 --- /dev/null +++ b/contrib/libgmp/mpz/ui_pow_ui.c @@ -0,0 +1,111 @@ +/* mpz_ui_pow_ui(res, base, exp) -- Set RES to BASE**EXP. + +Copyright (C) 1991, 1993, 1994, 1996 Free Software Foundation, Inc. + +This file is part of the GNU MP Library. + +The GNU MP Library is free software; you can redistribute it and/or modify +it under the terms of the GNU Library General Public License as published by +the Free Software Foundation; either version 2 of the License, or (at your +option) any later version. + +The GNU MP Library is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public +License for more details. + +You should have received a copy of the GNU Library General Public License +along with the GNU MP Library; see the file COPYING.LIB. If not, write to +the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, +MA 02111-1307, USA. */ + +#include "gmp.h" +#include "gmp-impl.h" +#include "longlong.h" + +void +#if __STDC__ +mpz_ui_pow_ui (mpz_ptr r, unsigned long int b, unsigned long int e) +#else +mpz_ui_pow_ui (r, b, e) + mpz_ptr r; + unsigned long int b; + unsigned long int e; +#endif +{ + mp_ptr rp, tp, xp; + mp_size_t rsize; + int cnt, i; + mp_limb_t blimb = b; + TMP_DECL (marker); + + /* Single out cases that give result == 0 or 1. These tests are here + to simplify the general code below, not to optimize. */ + if (e == 0) + { + r->_mp_d[0] = 1; + r->_mp_size = 1; + return; + } + if (blimb == 0) + { + r->_mp_size = 0; + return; + } + + if (blimb < 0x100) + { + /* Estimate space requirements accurately. Using the code from the + `else' path would over-estimate space requirements wildly. */ + float lb = __mp_bases[blimb].chars_per_bit_exactly; + rsize = 2 + ((mp_size_t) (e / lb) / BITS_PER_MP_LIMB); + } + else + { + /* Over-estimate space requirements somewhat. */ + count_leading_zeros (cnt, blimb); + rsize = e - cnt * e / BITS_PER_MP_LIMB + 1; + } + + TMP_MARK (marker); + + /* The two areas are used to alternatingly hold the input and recieve the + product for mpn_mul. (This scheme is used to fulfill the requirements + of mpn_mul; that the product space may not be the same as any of the + input operands.) */ + rp = (mp_ptr) TMP_ALLOC (rsize * BYTES_PER_MP_LIMB); + tp = (mp_ptr) TMP_ALLOC (rsize * BYTES_PER_MP_LIMB); + + rp[0] = blimb; + rsize = 1; + count_leading_zeros (cnt, e); + + for (i = BITS_PER_MP_LIMB - cnt - 2; i >= 0; i--) + { + mpn_mul_n (tp, rp, rp, rsize); + rsize = 2 * rsize; + rsize -= tp[rsize - 1] == 0; + xp = tp; tp = rp; rp = xp; + + if ((e & ((mp_limb_t) 1 << i)) != 0) + { + mp_limb_t cy; + cy = mpn_mul_1 (tp, rp, rsize, blimb); + if (cy != 0) + { + tp[rsize] = cy; + rsize++; + } + xp = tp; tp = rp; rp = xp; + } + } + + /* Now then we know the exact space requirements, reallocate if + necessary. */ + if (r->_mp_alloc < rsize) + _mpz_realloc (r, rsize); + + MPN_COPY (r->_mp_d, rp, rsize); + r->_mp_size = rsize; + TMP_FREE (marker); +} diff --git a/contrib/libgmp/stack-alloc.c b/contrib/libgmp/stack-alloc.c new file mode 100644 index 0000000..d9619f6 --- /dev/null +++ b/contrib/libgmp/stack-alloc.c @@ -0,0 +1,108 @@ +/* Stack allocation routines. This is intended for machines without support + for the `alloca' function. + +Copyright (C) 1996 Free Software Foundation, Inc. + +This file is part of the GNU MP Library. + +The GNU MP Library is free software; you can redistribute it and/or modify +it under the terms of the GNU Library General Public License as published by +the Free Software Foundation; either version 2 of the License, or (at your +option) any later version. + +The GNU MP Library is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public +License for more details. + +You should have received a copy of the GNU Library General Public License +along with the GNU MP Library; see the file COPYING.LIB. If not, write to +the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, +MA 02111-1307, USA. */ + +#include "stack-alloc.h" + +typedef struct tmp_stack tmp_stack; + +void *malloc (); +static unsigned long max_total_allocation = 0; +static unsigned long current_total_allocation = 0; + +static tmp_stack xxx = {&xxx, &xxx, 0}; +static tmp_stack *current = &xxx; + +/* Allocate a block of exactly <size> bytes. This should only be called + through the TMP_ALLOC macro, which takes care of rounding/alignment. */ +void * +__tmp_alloc (size) + unsigned long size; +{ + void *this; + + if (size > (char *) current->end - (char *) current->alloc_point) + { + void *chunk; + tmp_stack *header; + unsigned long chunk_size; + unsigned long now; + + /* Allocate a chunk that makes the total current allocation somewhat + larger than the maximum allocation ever. If size is very large, we + allocate that much. */ + + now = current_total_allocation + size; + if (now > max_total_allocation) + { + /* We need more temporary memory than ever before. Increase + for future needs. */ + now = now * 3 / 2; + chunk_size = now - current_total_allocation + sizeof (tmp_stack); + current_total_allocation = now; + max_total_allocation = current_total_allocation; + } + else + { + chunk_size = max_total_allocation - current_total_allocation + sizeof (tmp_stack); + current_total_allocation = max_total_allocation; + } + + chunk = malloc (chunk_size); + header = chunk; + header->end = (char *) chunk + chunk_size; + header->alloc_point = (char *) chunk + sizeof (tmp_stack); + header->prev = current; + current = header; + } + + this = current->alloc_point; + current->alloc_point = (char *) this + size; + return this; +} + +/* Typically called at function entry. <mark> is assigned so that __tmp_free + can later be used to reclaim all subsecuently allocated storage. */ +void +__tmp_mark (mark) + tmp_marker *mark; +{ + mark->which_chunk = current; + mark->alloc_point = current->alloc_point; +} + +/* Free everything allocated since <mark> was assigned by __tmp_mark */ +void +__tmp_free (mark) + tmp_marker *mark; +{ + while (mark->which_chunk != current) + { + tmp_stack *tmp; + + tmp = current; + current = tmp->prev; + current_total_allocation -= (((char *) (tmp->end) - (char *) tmp) + - sizeof (tmp_stack)); + free (tmp); + } + current->alloc_point = mark->alloc_point; +} diff --git a/contrib/libgmp/stack-alloc.h b/contrib/libgmp/stack-alloc.h new file mode 100644 index 0000000..a84eeff --- /dev/null +++ b/contrib/libgmp/stack-alloc.h @@ -0,0 +1,56 @@ +/* Stack allocation routines. This is intended for machines without support + for the `alloca' function. + +Copyright (C) 1996 Free Software Foundation, Inc. + +This file is part of the GNU MP Library. + +The GNU MP Library is free software; you can redistribute it and/or modify +it under the terms of the GNU Library General Public License as published by +the Free Software Foundation; either version 2 of the License, or (at your +option) any later version. + +The GNU MP Library is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public +License for more details. + +You should have received a copy of the GNU Library General Public License +along with the GNU MP Library; see the file COPYING.LIB. If not, write to +the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, +MA 02111-1307, USA. */ + +struct tmp_stack +{ + void *end; + void *alloc_point; + struct tmp_stack *prev; +}; + +struct tmp_marker +{ + struct tmp_stack *which_chunk; + void *alloc_point; +}; + +typedef struct tmp_marker tmp_marker; + +#if __STDC__ +void *__tmp_alloc (unsigned long); +void __tmp_mark (tmp_marker *); +void __tmp_free (tmp_marker *); +#else +void *__tmp_alloc (); +void __tmp_mark (); +void __tmp_free (); +#endif + +#ifndef __TMP_ALIGN +#define __TMP_ALIGN 8 +#endif + +#define TMP_DECL(marker) tmp_marker marker +#define TMP_ALLOC(size) \ + __tmp_alloc (((unsigned long) (size) + __TMP_ALIGN - 1) & -__TMP_ALIGN) +#define TMP_MARK(marker) __tmp_mark (&marker) +#define TMP_FREE(marker) __tmp_free (&marker) diff --git a/contrib/libgmp/texinfo.tex b/contrib/libgmp/texinfo.tex new file mode 100644 index 0000000..1536ac3 --- /dev/null +++ b/contrib/libgmp/texinfo.tex @@ -0,0 +1,4585 @@ +%% TeX macros to handle texinfo files + +% Copyright (C) 1985, 86, 88, 90, 91, 92, 93, +% 94, 95, 1996 Free Software Foundation, Inc. + +%This texinfo.tex file is free software; you can redistribute it and/or +%modify it under the terms of the GNU General Public License as +%published by the Free Software Foundation; either version 2, or (at +%your option) any later version. + +%This texinfo.tex file is distributed in the hope that it will be +%useful, but WITHOUT ANY WARRANTY; without even the implied warranty +%of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +%General Public License for more details. + +%You should have received a copy of the GNU General Public License +%along with this texinfo.tex file; see the file COPYING. If not, write +%to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +%Boston, MA 02111-1307, USA. + + +%In other words, you are welcome to use, share and improve this program. +%You are forbidden to forbid anyone else to use, share and improve +%what you give them. Help stamp out software-hoarding! + + +% Send bug reports to bug-texinfo@prep.ai.mit.edu. +% Please include a *precise* test case in each bug report. + + +% Make it possible to create a .fmt file just by loading this file: +% if the underlying format is not loaded, start by loading it now. +% Added by gildea November 1993. +\expandafter\ifx\csname fmtname\endcsname\relax\input plain\fi + +% This automatically updates the version number based on RCS. +\def\deftexinfoversion$#1: #2 ${\def\texinfoversion{#2}} +\deftexinfoversion$Revision: 2.172 $ +\message{Loading texinfo package [Version \texinfoversion]:} + +% If in a .fmt file, print the version number +% and turn on active characters that we couldn't do earlier because +% they might have appeared in the input file name. +\everyjob{\message{[Texinfo version \texinfoversion]}\message{} + \catcode`+=\active \catcode`\_=\active} + +% Save some parts of plain tex whose names we will redefine. + +\let\ptextilde=\~ +\let\ptexlbrace=\{ +\let\ptexrbrace=\} +\let\ptexdots=\dots +\let\ptexdot=\. +\let\ptexstar=\* +\let\ptexend=\end +\let\ptexbullet=\bullet +\let\ptexb=\b +\let\ptexc=\c +\let\ptexi=\i +\let\ptext=\t +\let\ptexl=\l +\let\ptexL=\L + +% Be sure we're in horizontal mode when doing a tie, since we make space +% equivalent to this in @example-like environments. Otherwise, a space +% at the beginning of a line will start with \penalty -- and +% since \penalty is valid in vertical mode, we'd end up putting the +% penalty on the vertical list instead of in the new paragraph. +{\catcode`@ = 11 + % Avoid using \@M directly, because that causes trouble + % if the definition is written into an index file. + \global\let\tiepenalty = \@M + \gdef\tie{\leavevmode\penalty\tiepenalty\ } +} +\let\~ = \tie % And make it available as @~. + +\message{Basics,} +\chardef\other=12 + +% If this character appears in an error message or help string, it +% starts a new line in the output. +\newlinechar = `^^J + +% Set up fixed words for English. +\ifx\putwordChapter\undefined{\gdef\putwordChapter{Chapter}}\fi% +\def\putwordInfo{Info}% +\ifx\putwordSee\undefined{\gdef\putwordSee{See}}\fi% +\ifx\putwordsee\undefined{\gdef\putwordsee{see}}\fi% +\ifx\putwordfile\undefined{\gdef\putwordfile{file}}\fi% +\ifx\putwordpage\undefined{\gdef\putwordpage{page}}\fi% +\ifx\putwordsection\undefined{\gdef\putwordsection{section}}\fi% +\ifx\putwordSection\undefined{\gdef\putwordSection{Section}}\fi% +\ifx\putwordTableofContents\undefined{\gdef\putwordTableofContents{Table of Contents}}\fi% +\ifx\putwordShortContents\undefined{\gdef\putwordShortContents{Short Contents}}\fi% +\ifx\putwordAppendix\undefined{\gdef\putwordAppendix{Appendix}}\fi% + +% Ignore a token. +% +\def\gobble#1{} + +\hyphenation{ap-pen-dix} +\hyphenation{mini-buf-fer mini-buf-fers} +\hyphenation{eshell} + +% Margin to add to right of even pages, to left of odd pages. +\newdimen \bindingoffset \bindingoffset=0pt +\newdimen \normaloffset \normaloffset=\hoffset +\newdimen\pagewidth \newdimen\pageheight +\pagewidth=\hsize \pageheight=\vsize + +% Sometimes it is convenient to have everything in the transcript file +% and nothing on the terminal. We don't just call \tracingall here, +% since that produces some useless output on the terminal. +% +\def\gloggingall{\begingroup \globaldefs = 1 \loggingall \endgroup}% +\def\loggingall{\tracingcommands2 \tracingstats2 + \tracingpages1 \tracingoutput1 \tracinglostchars1 + \tracingmacros2 \tracingparagraphs1 \tracingrestores1 + \showboxbreadth\maxdimen\showboxdepth\maxdimen +}% + +%---------------------Begin change----------------------- +% +%%%% For @cropmarks command. +% Dimensions to add cropmarks at corners Added by P. A. MacKay, 12 Nov. 1986 +% +\newdimen\cornerlong \newdimen\cornerthick +\newdimen \topandbottommargin +\newdimen \outerhsize \newdimen \outervsize +\cornerlong=1pc\cornerthick=.3pt % These set size of cropmarks +\outerhsize=7in +%\outervsize=9.5in +% Alternative @smallbook page size is 9.25in +\outervsize=9.25in +\topandbottommargin=.75in +% +%---------------------End change----------------------- + +% \onepageout takes a vbox as an argument. Note that \pagecontents +% does insertions itself, but you have to call it yourself. +\chardef\PAGE=255 \output={\onepageout{\pagecontents\PAGE}} +\def\onepageout#1{\hoffset=\normaloffset +\ifodd\pageno \advance\hoffset by \bindingoffset +\else \advance\hoffset by -\bindingoffset\fi +{\escapechar=`\\\relax % makes sure backslash is used in output files. +\shipout\vbox{{\let\hsize=\pagewidth \makeheadline} \pagebody{#1}% +{\let\hsize=\pagewidth \makefootline}}}% +\advancepageno \ifnum\outputpenalty>-20000 \else\dosupereject\fi} + +%%%% For @cropmarks command %%%% + +% Here is a modification of the main output routine for Near East Publications +% This provides right-angle cropmarks at all four corners. +% The contents of the page are centerlined into the cropmarks, +% and any desired binding offset is added as an \hskip on either +% site of the centerlined box. (P. A. MacKay, 12 November, 1986) +% +\def\croppageout#1{\hoffset=0pt % make sure this doesn't mess things up +{\escapechar=`\\\relax % makes sure backslash is used in output files. + \shipout + \vbox to \outervsize{\hsize=\outerhsize + \vbox{\line{\ewtop\hfill\ewtop}} + \nointerlineskip + \line{\vbox{\moveleft\cornerthick\nstop} + \hfill + \vbox{\moveright\cornerthick\nstop}} + \vskip \topandbottommargin + \centerline{\ifodd\pageno\hskip\bindingoffset\fi + \vbox{ + {\let\hsize=\pagewidth \makeheadline} + \pagebody{#1} + {\let\hsize=\pagewidth \makefootline}} + \ifodd\pageno\else\hskip\bindingoffset\fi} + \vskip \topandbottommargin plus1fill minus1fill + \boxmaxdepth\cornerthick + \line{\vbox{\moveleft\cornerthick\nsbot} + \hfill + \vbox{\moveright\cornerthick\nsbot}} + \nointerlineskip + \vbox{\line{\ewbot\hfill\ewbot}} + }} + \advancepageno + \ifnum\outputpenalty>-20000 \else\dosupereject\fi} +% +% Do @cropmarks to get crop marks +\def\cropmarks{\let\onepageout=\croppageout } + +\newinsert\margin \dimen\margin=\maxdimen + +\def\pagebody#1{\vbox to\pageheight{\boxmaxdepth=\maxdepth #1}} +{\catcode`\@ =11 +\gdef\pagecontents#1{\ifvoid\topins\else\unvbox\topins\fi +% marginal hacks, juha@viisa.uucp (Juha Takala) +\ifvoid\margin\else % marginal info is present + \rlap{\kern\hsize\vbox to\z@{\kern1pt\box\margin \vss}}\fi +\dimen@=\dp#1 \unvbox#1 +\ifvoid\footins\else\vskip\skip\footins\footnoterule \unvbox\footins\fi +\ifr@ggedbottom \kern-\dimen@ \vfil \fi} +} + +% +% Here are the rules for the cropmarks. Note that they are +% offset so that the space between them is truly \outerhsize or \outervsize +% (P. A. MacKay, 12 November, 1986) +% +\def\ewtop{\vrule height\cornerthick depth0pt width\cornerlong} +\def\nstop{\vbox + {\hrule height\cornerthick depth\cornerlong width\cornerthick}} +\def\ewbot{\vrule height0pt depth\cornerthick width\cornerlong} +\def\nsbot{\vbox + {\hrule height\cornerlong depth\cornerthick width\cornerthick}} + +% Parse an argument, then pass it to #1. The argument is the rest of +% the input line (except we remove a trailing comment). #1 should be a +% macro which expects an ordinary undelimited TeX argument. +% +\def\parsearg#1{% + \let\next = #1% + \begingroup + \obeylines + \futurelet\temp\parseargx +} + +% If the next token is an obeyed space (from an @example environment or +% the like), remove it and recurse. Otherwise, we're done. +\def\parseargx{% + % \obeyedspace is defined far below, after the definition of \sepspaces. + \ifx\obeyedspace\temp + \expandafter\parseargdiscardspace + \else + \expandafter\parseargline + \fi +} + +% Remove a single space (as the delimiter token to the macro call). +{\obeyspaces % + \gdef\parseargdiscardspace {\futurelet\temp\parseargx}} + +{\obeylines % + \gdef\parseargline#1^^M{% + \endgroup % End of the group started in \parsearg. + % + % First remove any @c comment, then any @comment. + % Result of each macro is put in \toks0. + \argremovec #1\c\relax % + \expandafter\argremovecomment \the\toks0 \comment\relax % + % + % Call the caller's macro, saved as \next in \parsearg. + \expandafter\next\expandafter{\the\toks0}% + }% +} + +% Since all \c{,omment} does is throw away the argument, we can let TeX +% do that for us. The \relax here is matched by the \relax in the call +% in \parseargline; it could be more or less anything, its purpose is +% just to delimit the argument to the \c. +\def\argremovec#1\c#2\relax{\toks0 = {#1}} +\def\argremovecomment#1\comment#2\relax{\toks0 = {#1}} + +% \argremovec{,omment} might leave us with trailing spaces, though; e.g., +% @end itemize @c foo +% will have two active spaces as part of the argument with the +% `itemize'. Here we remove all active spaces from #1, and assign the +% result to \toks0. +% +% This loses if there are any *other* active characters besides spaces +% in the argument -- _ ^ +, for example -- since they get expanded. +% Fortunately, Texinfo does not define any such commands. (If it ever +% does, the catcode of the characters in questionwill have to be changed +% here.) But this means we cannot call \removeactivespaces as part of +% \argremovec{,omment}, since @c uses \parsearg, and thus the argument +% that \parsearg gets might well have any character at all in it. +% +\def\removeactivespaces#1{% + \begingroup + \ignoreactivespaces + \edef\temp{#1}% + \global\toks0 = \expandafter{\temp}% + \endgroup +} + +% Change the active space to expand to nothing. +% +\begingroup + \obeyspaces + \gdef\ignoreactivespaces{\obeyspaces\let =\empty} +\endgroup + + +\def\flushcr{\ifx\par\lisppar \def\next##1{}\else \let\next=\relax \fi \next} + +%% These are used to keep @begin/@end levels from running away +%% Call \inENV within environments (after a \begingroup) +\newif\ifENV \ENVfalse \def\inENV{\ifENV\relax\else\ENVtrue\fi} +\def\ENVcheck{% +\ifENV\errmessage{Still within an environment. Type Return to continue.} +\endgroup\fi} % This is not perfect, but it should reduce lossage + +% @begin foo is the same as @foo, for now. +\newhelp\EMsimple{Type <Return> to continue.} + +\outer\def\begin{\parsearg\beginxxx} + +\def\beginxxx #1{% +\expandafter\ifx\csname #1\endcsname\relax +{\errhelp=\EMsimple \errmessage{Undefined command @begin #1}}\else +\csname #1\endcsname\fi} + +% @end foo executes the definition of \Efoo. +% +\def\end{\parsearg\endxxx} +\def\endxxx #1{% + \removeactivespaces{#1}% + \edef\endthing{\the\toks0}% + % + \expandafter\ifx\csname E\endthing\endcsname\relax + \expandafter\ifx\csname \endthing\endcsname\relax + % There's no \foo, i.e., no ``environment'' foo. + \errhelp = \EMsimple + \errmessage{Undefined command `@end \endthing'}% + \else + \unmatchedenderror\endthing + \fi + \else + % Everything's ok; the right environment has been started. + \csname E\endthing\endcsname + \fi +} + +% There is an environment #1, but it hasn't been started. Give an error. +% +\def\unmatchedenderror#1{% + \errhelp = \EMsimple + \errmessage{This `@end #1' doesn't have a matching `@#1'}% +} + +% Define the control sequence \E#1 to give an unmatched @end error. +% +\def\defineunmatchedend#1{% + \expandafter\def\csname E#1\endcsname{\unmatchedenderror{#1}}% +} + + +% Single-spacing is done by various environments (specifically, in +% \nonfillstart and \quotations). +\newskip\singlespaceskip \singlespaceskip = 12.5pt +\def\singlespace{% + % Why was this kern here? It messes up equalizing space above and below + % environments. --karl, 6may93 + %{\advance \baselineskip by -\singlespaceskip + %\kern \baselineskip}% + \setleading \singlespaceskip +} + +%% Simple single-character @ commands + +% @@ prints an @ +% Kludge this until the fonts are right (grr). +\def\@{{\tt \char '100}} + +% This is turned off because it was never documented +% and you can use @w{...} around a quote to suppress ligatures. +%% Define @` and @' to be the same as ` and ' +%% but suppressing ligatures. +%\def\`{{`}} +%\def\'{{'}} + +% Used to generate quoted braces. + +\def\mylbrace {{\tt \char '173}} +\def\myrbrace {{\tt \char '175}} +\let\{=\mylbrace +\let\}=\myrbrace + +% @: forces normal size whitespace following. +\def\:{\spacefactor=1000 } + +% @* forces a line break. +\def\*{\hfil\break\hbox{}\ignorespaces} + +% @. is an end-of-sentence period. +\def\.{.\spacefactor=3000 } + +% @enddots{} is an end-of-sentence ellipsis. +\gdef\enddots{$\mathinner{\ldotp\ldotp\ldotp\ldotp}$\spacefactor=3000} + +% @! is an end-of-sentence bang. +\gdef\!{!\spacefactor=3000 } + +% @? is an end-of-sentence query. +\gdef\?{?\spacefactor=3000 } + +% @w prevents a word break. Without the \leavevmode, @w at the +% beginning of a paragraph, when TeX is still in vertical mode, would +% produce a whole line of output instead of starting the paragraph. +\def\w#1{\leavevmode\hbox{#1}} + +% @group ... @end group forces ... to be all on one page, by enclosing +% it in a TeX vbox. We use \vtop instead of \vbox to construct the box +% to keep its height that of a normal line. According to the rules for +% \topskip (p.114 of the TeXbook), the glue inserted is +% max (\topskip - \ht (first item), 0). If that height is large, +% therefore, no glue is inserted, and the space between the headline and +% the text is small, which looks bad. +% +\def\group{\begingroup + \ifnum\catcode13=\active \else + \errhelp = \groupinvalidhelp + \errmessage{@group invalid in context where filling is enabled}% + \fi + % + % The \vtop we start below produces a box with normal height and large + % depth; thus, TeX puts \baselineskip glue before it, and (when the + % next line of text is done) \lineskip glue after it. (See p.82 of + % the TeXbook.) Thus, space below is not quite equal to space + % above. But it's pretty close. + \def\Egroup{% + \egroup % End the \vtop. + \endgroup % End the \group. + }% + % + \vtop\bgroup + % We have to put a strut on the last line in case the @group is in + % the midst of an example, rather than completely enclosing it. + % Otherwise, the interline space between the last line of the group + % and the first line afterwards is too small. But we can't put the + % strut in \Egroup, since there it would be on a line by itself. + % Hence this just inserts a strut at the beginning of each line. + \everypar = {\strut}% + % + % Since we have a strut on every line, we don't need any of TeX's + % normal interline spacing. + \offinterlineskip + % + % OK, but now we have to do something about blank + % lines in the input in @example-like environments, which normally + % just turn into \lisppar, which will insert no space now that we've + % turned off the interline space. Simplest is to make them be an + % empty paragraph. + \ifx\par\lisppar + \edef\par{\leavevmode \par}% + % + % Reset ^^M's definition to new definition of \par. + \obeylines + \fi + % + % Do @comment since we are called inside an environment such as + % @example, where each end-of-line in the input causes an + % end-of-line in the output. We don't want the end-of-line after + % the `@group' to put extra space in the output. Since @group + % should appear on a line by itself (according to the Texinfo + % manual), we don't worry about eating any user text. + \comment +} +% +% TeX puts in an \escapechar (i.e., `@') at the beginning of the help +% message, so this ends up printing `@group can only ...'. +% +\newhelp\groupinvalidhelp{% +group can only be used in environments such as @example,^^J% +where each line of input produces a line of output.} + +% @need space-in-mils +% forces a page break if there is not space-in-mils remaining. + +\newdimen\mil \mil=0.001in + +\def\need{\parsearg\needx} + +% Old definition--didn't work. +%\def\needx #1{\par % +%% This method tries to make TeX break the page naturally +%% if the depth of the box does not fit. +%{\baselineskip=0pt% +%\vtop to #1\mil{\vfil}\kern -#1\mil\penalty 10000 +%\prevdepth=-1000pt +%}} + +\def\needx#1{% + % Go into vertical mode, so we don't make a big box in the middle of a + % paragraph. + \par + % + % Don't add any leading before our big empty box, but allow a page + % break, since the best break might be right here. + \allowbreak + \nointerlineskip + \vtop to #1\mil{\vfil}% + % + % TeX does not even consider page breaks if a penalty added to the + % main vertical list is 10000 or more. But in order to see if the + % empty box we just added fits on the page, we must make it consider + % page breaks. On the other hand, we don't want to actually break the + % page after the empty box. So we use a penalty of 9999. + % + % There is an extremely small chance that TeX will actually break the + % page at this \penalty, if there are no other feasible breakpoints in + % sight. (If the user is using lots of big @group commands, which + % almost-but-not-quite fill up a page, TeX will have a hard time doing + % good page breaking, for example.) However, I could not construct an + % example where a page broke at this \penalty; if it happens in a real + % document, then we can reconsider our strategy. + \penalty9999 + % + % Back up by the size of the box, whether we did a page break or not. + \kern -#1\mil + % + % Do not allow a page break right after this kern. + \nobreak +} + +% @br forces paragraph break + +\let\br = \par + +% @dots{} output some dots + +\def\dots{$\ldots$} + +% @page forces the start of a new page + +\def\page{\par\vfill\supereject} + +% @exdent text.... +% outputs text on separate line in roman font, starting at standard page margin + +% This records the amount of indent in the innermost environment. +% That's how much \exdent should take out. +\newskip\exdentamount + +% This defn is used inside fill environments such as @defun. +\def\exdent{\parsearg\exdentyyy} +\def\exdentyyy #1{{\hfil\break\hbox{\kern -\exdentamount{\rm#1}}\hfil\break}} + +% This defn is used inside nofill environments such as @example. +\def\nofillexdent{\parsearg\nofillexdentyyy} +\def\nofillexdentyyy #1{{\advance \leftskip by -\exdentamount +\leftline{\hskip\leftskip{\rm#1}}}} + +% @inmargin{TEXT} puts TEXT in the margin next to the current paragraph. + +\def\inmargin#1{% +\strut\vadjust{\nobreak\kern-\strutdepth + \vtop to \strutdepth{\baselineskip\strutdepth\vss + \llap{\rightskip=\inmarginspacing \vbox{\noindent #1}}\null}}} +\newskip\inmarginspacing \inmarginspacing=1cm +\def\strutdepth{\dp\strutbox} + +%\hbox{{\rm#1}}\hfil\break}} + +% @include file insert text of that file as input. +% Allow normal characters that we make active in the argument (a file name). +\def\include{\begingroup + \catcode`\\=12 + \catcode`~=12 + \catcode`^=12 + \catcode`_=12 + \catcode`|=12 + \catcode`<=12 + \catcode`>=12 + \catcode`+=12 + \parsearg\includezzz} +% Restore active chars for included file. +\def\includezzz#1{\endgroup\begingroup + % Read the included file in a group so nested @include's work. + \def\thisfile{#1}% + \input\thisfile +\endgroup} + +\def\thisfile{} + +% @center line outputs that line, centered + +\def\center{\parsearg\centerzzz} +\def\centerzzz #1{{\advance\hsize by -\leftskip +\advance\hsize by -\rightskip +\centerline{#1}}} + +% @sp n outputs n lines of vertical space + +\def\sp{\parsearg\spxxx} +\def\spxxx #1{\par \vskip #1\baselineskip} + +% @comment ...line which is ignored... +% @c is the same as @comment +% @ignore ... @end ignore is another way to write a comment + +\def\comment{\catcode 64=\other \catcode 123=\other \catcode 125=\other% +\parsearg \commentxxx} + +\def\commentxxx #1{\catcode 64=0 \catcode 123=1 \catcode 125=2 } + +\let\c=\comment + +% Prevent errors for section commands. +% Used in @ignore and in failing conditionals. +\def\ignoresections{% +\let\chapter=\relax +\let\unnumbered=\relax +\let\top=\relax +\let\unnumberedsec=\relax +\let\unnumberedsection=\relax +\let\unnumberedsubsec=\relax +\let\unnumberedsubsection=\relax +\let\unnumberedsubsubsec=\relax +\let\unnumberedsubsubsection=\relax +\let\section=\relax +\let\subsec=\relax +\let\subsubsec=\relax +\let\subsection=\relax +\let\subsubsection=\relax +\let\appendix=\relax +\let\appendixsec=\relax +\let\appendixsection=\relax +\let\appendixsubsec=\relax +\let\appendixsubsection=\relax +\let\appendixsubsubsec=\relax +\let\appendixsubsubsection=\relax +\let\contents=\relax +\let\smallbook=\relax +\let\titlepage=\relax +} + +% Used in nested conditionals, where we have to parse the Texinfo source +% and so want to turn off most commands, in case they are used +% incorrectly. +% +\def\ignoremorecommands{% + \let\defcv = \relax + \let\deffn = \relax + \let\deffnx = \relax + \let\defindex = \relax + \let\defivar = \relax + \let\defmac = \relax + \let\defmethod = \relax + \let\defop = \relax + \let\defopt = \relax + \let\defspec = \relax + \let\deftp = \relax + \let\deftypefn = \relax + \let\deftypefun = \relax + \let\deftypevar = \relax + \let\deftypevr = \relax + \let\defun = \relax + \let\defvar = \relax + \let\defvr = \relax + \let\ref = \relax + \let\xref = \relax + \let\printindex = \relax + \let\pxref = \relax + \let\settitle = \relax + \let\setchapternewpage = \relax + \let\setchapterstyle = \relax + \let\everyheading = \relax + \let\evenheading = \relax + \let\oddheading = \relax + \let\everyfooting = \relax + \let\evenfooting = \relax + \let\oddfooting = \relax + \let\headings = \relax + \let\include = \relax + \let\lowersections = \relax + \let\down = \relax + \let\raisesections = \relax + \let\up = \relax + \let\set = \relax + \let\clear = \relax + \let\item = \relax + \let\message = \relax +} + +% Ignore @ignore ... @end ignore. +% +\def\ignore{\doignore{ignore}} + +% Also ignore @ifinfo, @ifhtml, @html, @menu, and @direntry text. +% +\def\ifinfo{\doignore{ifinfo}} +\def\ifhtml{\doignore{ifhtml}} +\def\html{\doignore{html}} +\def\menu{\doignore{menu}} +\def\direntry{\doignore{direntry}} + +% @dircategory CATEGORY -- specify a category of the dir file +% which this file should belong to. Ignore this in TeX. + +\def\dircategory{\comment} + +% Ignore text until a line `@end #1'. +% +\def\doignore#1{\begingroup + % Don't complain about control sequences we have declared \outer. + \ignoresections + % + % Define a command to swallow text until we reach `@end #1'. + \long\def\doignoretext##1\end #1{\enddoignore}% + % + % Make sure that spaces turn into tokens that match what \doignoretext wants. + \catcode32 = 10 + % + % And now expand that command. + \doignoretext +} + +% What we do to finish off ignored text. +% +\def\enddoignore{\endgroup\ignorespaces}% + +\newif\ifwarnedobs\warnedobsfalse +\def\obstexwarn{% + \ifwarnedobs\relax\else + % We need to warn folks that they may have trouble with TeX 3.0. + % This uses \immediate\write16 rather than \message to get newlines. + \immediate\write16{} + \immediate\write16{***WARNING*** for users of Unix TeX 3.0!} + \immediate\write16{This manual trips a bug in TeX version 3.0 (tex hangs).} + \immediate\write16{If you are running another version of TeX, relax.} + \immediate\write16{If you are running Unix TeX 3.0, kill this TeX process.} + \immediate\write16{ Then upgrade your TeX installation if you can.} + \immediate\write16{If you are stuck with version 3.0, run the} + \immediate\write16{ script ``tex3patch'' from the Texinfo distribution} + \immediate\write16{ to use a workaround.} + \immediate\write16{} + \global\warnedobstrue + \fi +} + +% **In TeX 3.0, setting text in \nullfont hangs tex. For a +% workaround (which requires the file ``dummy.tfm'' to be installed), +% uncomment the following line: +%%%%%\font\nullfont=dummy\let\obstexwarn=\relax + +% Ignore text, except that we keep track of conditional commands for +% purposes of nesting, up to an `@end #1' command. +% +\def\nestedignore#1{% + \obstexwarn + % We must actually expand the ignored text to look for the @end + % command, so that nested ignore constructs work. Thus, we put the + % text into a \vbox and then do nothing with the result. To minimize + % the change of memory overflow, we follow the approach outlined on + % page 401 of the TeXbook: make the current font be a dummy font. + % + \setbox0 = \vbox\bgroup + % Don't complain about control sequences we have declared \outer. + \ignoresections + % + % Define `@end #1' to end the box, which will in turn undefine the + % @end command again. + \expandafter\def\csname E#1\endcsname{\egroup\ignorespaces}% + % + % We are going to be parsing Texinfo commands. Most cause no + % trouble when they are used incorrectly, but some commands do + % complicated argument parsing or otherwise get confused, so we + % undefine them. + % + % We can't do anything about stray @-signs, unfortunately; + % they'll produce `undefined control sequence' errors. + \ignoremorecommands + % + % Set the current font to be \nullfont, a TeX primitive, and define + % all the font commands to also use \nullfont. We don't use + % dummy.tfm, as suggested in the TeXbook, because not all sites + % might have that installed. Therefore, math mode will still + % produce output, but that should be an extremely small amount of + % stuff compared to the main input. + % + \nullfont + \let\tenrm = \nullfont \let\tenit = \nullfont \let\tensl = \nullfont + \let\tenbf = \nullfont \let\tentt = \nullfont \let\smallcaps = \nullfont + \let\tensf = \nullfont + % Similarly for index fonts (mostly for their use in + % smallexample) + \let\indrm = \nullfont \let\indit = \nullfont \let\indsl = \nullfont + \let\indbf = \nullfont \let\indtt = \nullfont \let\indsc = \nullfont + \let\indsf = \nullfont + % + % Don't complain when characters are missing from the fonts. + \tracinglostchars = 0 + % + % Don't bother to do space factor calculations. + \frenchspacing + % + % Don't report underfull hboxes. + \hbadness = 10000 + % + % Do minimal line-breaking. + \pretolerance = 10000 + % + % Do not execute instructions in @tex + \def\tex{\doignore{tex}} +} + +% @set VAR sets the variable VAR to an empty value. +% @set VAR REST-OF-LINE sets VAR to the value REST-OF-LINE. +% +% Since we want to separate VAR from REST-OF-LINE (which might be +% empty), we can't just use \parsearg; we have to insert a space of our +% own to delimit the rest of the line, and then take it out again if we +% didn't need it. Make sure the catcode of space is correct to avoid +% losing inside @example, for instance. +% +\def\set{\begingroup\catcode` =10 \parsearg\setxxx} +\def\setxxx#1{\setyyy#1 \endsetyyy} +\def\setyyy#1 #2\endsetyyy{% + \def\temp{#2}% + \ifx\temp\empty \global\expandafter\let\csname SET#1\endcsname = \empty + \else \setzzz{#1}#2\endsetzzz % Remove the trailing space \setxxx inserted. + \fi + \endgroup +} +% Can't use \xdef to pre-expand #2 and save some time, since \temp or +% \next or other control sequences that we've defined might get us into +% an infinite loop. Consider `@set foo @cite{bar}'. +\def\setzzz#1#2 \endsetzzz{\expandafter\gdef\csname SET#1\endcsname{#2}} + +% @clear VAR clears (i.e., unsets) the variable VAR. +% +\def\clear{\parsearg\clearxxx} +\def\clearxxx#1{\global\expandafter\let\csname SET#1\endcsname=\relax} + +% @value{foo} gets the text saved in variable foo. +% +\def\value#1{\expandafter + \ifx\csname SET#1\endcsname\relax + {\{No value for ``#1''\}} + \else \csname SET#1\endcsname \fi} + +% @ifset VAR ... @end ifset reads the `...' iff VAR has been defined +% with @set. +% +\def\ifset{\parsearg\ifsetxxx} +\def\ifsetxxx #1{% + \expandafter\ifx\csname SET#1\endcsname\relax + \expandafter\ifsetfail + \else + \expandafter\ifsetsucceed + \fi +} +\def\ifsetsucceed{\conditionalsucceed{ifset}} +\def\ifsetfail{\nestedignore{ifset}} +\defineunmatchedend{ifset} + +% @ifclear VAR ... @end ifclear reads the `...' iff VAR has never been +% defined with @set, or has been undefined with @clear. +% +\def\ifclear{\parsearg\ifclearxxx} +\def\ifclearxxx #1{% + \expandafter\ifx\csname SET#1\endcsname\relax + \expandafter\ifclearsucceed + \else + \expandafter\ifclearfail + \fi +} +\def\ifclearsucceed{\conditionalsucceed{ifclear}} +\def\ifclearfail{\nestedignore{ifclear}} +\defineunmatchedend{ifclear} + +% @iftex always succeeds; we read the text following, through @end +% iftex). But `@end iftex' should be valid only after an @iftex. +% +\def\iftex{\conditionalsucceed{iftex}} +\defineunmatchedend{iftex} + +% We can't just want to start a group at @iftex (for example) and end it +% at @end iftex, since then @set commands inside the conditional have no +% effect (they'd get reverted at the end of the group). So we must +% define \Eiftex to redefine itself to be its previous value. (We can't +% just define it to fail again with an ``unmatched end'' error, since +% the @ifset might be nested.) +% +\def\conditionalsucceed#1{% + \edef\temp{% + % Remember the current value of \E#1. + \let\nece{prevE#1} = \nece{E#1}% + % + % At the `@end #1', redefine \E#1 to be its previous value. + \def\nece{E#1}{\let\nece{E#1} = \nece{prevE#1}}% + }% + \temp +} + +% We need to expand lots of \csname's, but we don't want to expand the +% control sequences after we've constructed them. +% +\def\nece#1{\expandafter\noexpand\csname#1\endcsname} + +% @asis just yields its argument. Used with @table, for example. +% +\def\asis#1{#1} + +% @math means output in math mode. +% We don't use $'s directly in the definition of \math because control +% sequences like \math are expanded when the toc file is written. Then, +% we read the toc file back, the $'s will be normal characters (as they +% should be, according to the definition of Texinfo). So we must use a +% control sequence to switch into and out of math mode. +% +% This isn't quite enough for @math to work properly in indices, but it +% seems unlikely it will ever be needed there. +% +\let\implicitmath = $ +\def\math#1{\implicitmath #1\implicitmath} + +% @bullet and @minus need the same treatment as @math, just above. +\def\bullet{\implicitmath\ptexbullet\implicitmath} +\def\minus{\implicitmath-\implicitmath} + +\def\node{\ENVcheck\parsearg\nodezzz} +\def\nodezzz#1{\nodexxx [#1,]} +\def\nodexxx[#1,#2]{\gdef\lastnode{#1}} +\let\nwnode=\node +\let\lastnode=\relax + +\def\donoderef{\ifx\lastnode\relax\else +\expandafter\expandafter\expandafter\setref{\lastnode}\fi +\global\let\lastnode=\relax} + +\def\unnumbnoderef{\ifx\lastnode\relax\else +\expandafter\expandafter\expandafter\unnumbsetref{\lastnode}\fi +\global\let\lastnode=\relax} + +\def\appendixnoderef{\ifx\lastnode\relax\else +\expandafter\expandafter\expandafter\appendixsetref{\lastnode}\fi +\global\let\lastnode=\relax} + +\let\refill=\relax + +% @setfilename is done at the beginning of every texinfo file. +% So open here the files we need to have open while reading the input. +% This makes it possible to make a .fmt file for texinfo. +\def\setfilename{% + \readauxfile + \opencontents + \openindices + \fixbackslash % Turn off hack to swallow `\input texinfo'. + \global\let\setfilename=\comment % Ignore extra @setfilename cmds. + \comment % Ignore the actual filename. +} + +\outer\def\bye{\pagealignmacro\tracingstats=1\ptexend} + +\def\inforef #1{\inforefzzz #1,,,,**} +\def\inforefzzz #1,#2,#3,#4**{\putwordSee{} \putwordInfo{} \putwordfile{} \file{\ignorespaces #3{}}, + node \samp{\ignorespaces#1{}}} + +\def\macro#1{\begingroup\ignoresections\catcode`\#=6\def\macrotemp{#1}\parsearg\macroxxx} +\def\macroxxx#1#2 \end macro{% +\expandafter\gdef\macrotemp#1{#2}% +\endgroup} + +%\def\linemacro#1{\begingroup\ignoresections\catcode`\#=6\def\macrotemp{#1}\parsearg\linemacroxxx} +%\def\linemacroxxx#1#2 \end linemacro{% +%\let\parsearg=\relax +%\edef\macrotempx{\csname M\butfirst\expandafter\string\macrotemp\endcsname}% +%\expandafter\xdef\macrotemp{\parsearg\macrotempx}% +%\expandafter\gdef\macrotempx#1{#2}% +%\endgroup} + +%\def\butfirst#1{} + +\message{fonts,} + +% Font-change commands. + +% Texinfo supports the sans serif font style, which plain TeX does not. +% So we set up a \sf analogous to plain's \rm, etc. +\newfam\sffam +\def\sf{\fam=\sffam \tensf} +\let\li = \sf % Sometimes we call it \li, not \sf. + +% We don't need math for this one. +\def\ttsl{\tenttsl} + +%% Try out Computer Modern fonts at \magstephalf +\let\mainmagstep=\magstephalf + +% Set the font macro #1 to the font named #2, adding on the +% specified font prefix (normally `cm'). +% #3 is the font's design size, #4 is a scale factor +\def\setfont#1#2#3#4{\font#1=\fontprefix#2#3 scaled #4} + +% Use cm as the default font prefix. +% To specify the font prefix, you must define \fontprefix +% before you read in texinfo.tex. +\ifx\fontprefix\undefined +\def\fontprefix{cm} +\fi +% Support font families that don't use the same naming scheme as CM. +\def\rmshape{r} +\def\rmbshape{bx} %where the normal face is bold +\def\bfshape{b} +\def\bxshape{bx} +\def\ttshape{tt} +\def\ttbshape{tt} +\def\ttslshape{sltt} +\def\itshape{ti} +\def\itbshape{bxti} +\def\slshape{sl} +\def\slbshape{bxsl} +\def\sfshape{ss} +\def\sfbshape{ss} +\def\scshape{csc} +\def\scbshape{csc} + +\ifx\bigger\relax +\let\mainmagstep=\magstep1 +\setfont\textrm\rmshape{12}{1000} +\setfont\texttt\ttshape{12}{1000} +\else +\setfont\textrm\rmshape{10}{\mainmagstep} +\setfont\texttt\ttshape{10}{\mainmagstep} +\fi +% Instead of cmb10, you many want to use cmbx10. +% cmbx10 is a prettier font on its own, but cmb10 +% looks better when embedded in a line with cmr10. +\setfont\textbf\bfshape{10}{\mainmagstep} +\setfont\textit\itshape{10}{\mainmagstep} +\setfont\textsl\slshape{10}{\mainmagstep} +\setfont\textsf\sfshape{10}{\mainmagstep} +\setfont\textsc\scshape{10}{\mainmagstep} +\setfont\textttsl\ttslshape{10}{\mainmagstep} +\font\texti=cmmi10 scaled \mainmagstep +\font\textsy=cmsy10 scaled \mainmagstep + +% A few fonts for @defun, etc. +\setfont\defbf\bxshape{10}{\magstep1} %was 1314 +\setfont\deftt\ttshape{10}{\magstep1} +\def\df{\let\tentt=\deftt \let\tenbf = \defbf \bf} + +% Fonts for indices and small examples. +% We actually use the slanted font rather than the italic, +% because texinfo normally uses the slanted fonts for that. +% Do not make many font distinctions in general in the index, since they +% aren't very useful. +\setfont\ninett\ttshape{9}{1000} +\setfont\indrm\rmshape{9}{1000} +\setfont\indit\slshape{9}{1000} +\let\indsl=\indit +\let\indtt=\ninett +\let\indttsl=\ninett +\let\indsf=\indrm +\let\indbf=\indrm +\setfont\indsc\scshape{10}{900} +\font\indi=cmmi9 +\font\indsy=cmsy9 + +% Fonts for headings +\setfont\chaprm\rmbshape{12}{\magstep2} +\setfont\chapit\itbshape{10}{\magstep3} +\setfont\chapsl\slbshape{10}{\magstep3} +\setfont\chaptt\ttbshape{12}{\magstep2} +\setfont\chapttsl\ttslshape{10}{\magstep3} +\setfont\chapsf\sfbshape{12}{\magstep2} +\let\chapbf=\chaprm +\setfont\chapsc\scbshape{10}{\magstep3} +\font\chapi=cmmi12 scaled \magstep2 +\font\chapsy=cmsy10 scaled \magstep3 + +\setfont\secrm\rmbshape{12}{\magstep1} +\setfont\secit\itbshape{10}{\magstep2} +\setfont\secsl\slbshape{10}{\magstep2} +\setfont\sectt\ttbshape{12}{\magstep1} +\setfont\secttsl\ttslshape{10}{\magstep2} +\setfont\secsf\sfbshape{12}{\magstep1} +\let\secbf\secrm +\setfont\secsc\scbshape{10}{\magstep2} +\font\seci=cmmi12 scaled \magstep1 +\font\secsy=cmsy10 scaled \magstep2 + +% \setfont\ssecrm\bxshape{10}{\magstep1} % This size an font looked bad. +% \setfont\ssecit\itshape{10}{\magstep1} % The letters were too crowded. +% \setfont\ssecsl\slshape{10}{\magstep1} +% \setfont\ssectt\ttshape{10}{\magstep1} +% \setfont\ssecsf\sfshape{10}{\magstep1} + +%\setfont\ssecrm\bfshape{10}{1315} % Note the use of cmb rather than cmbx. +%\setfont\ssecit\itshape{10}{1315} % Also, the size is a little larger than +%\setfont\ssecsl\slshape{10}{1315} % being scaled magstep1. +%\setfont\ssectt\ttshape{10}{1315} +%\setfont\ssecsf\sfshape{10}{1315} + +%\let\ssecbf=\ssecrm + +\setfont\ssecrm\rmbshape{12}{\magstephalf} +\setfont\ssecit\itbshape{10}{1315} +\setfont\ssecsl\slbshape{10}{1315} +\setfont\ssectt\ttbshape{12}{\magstephalf} +\setfont\ssecttsl\ttslshape{10}{\magstep1} +\setfont\ssecsf\sfbshape{12}{\magstephalf} +\let\ssecbf\ssecrm +\setfont\ssecsc\scbshape{10}{\magstep1} +\font\sseci=cmmi12 scaled \magstephalf +\font\ssecsy=cmsy10 scaled \magstep1 +% The smallcaps and symbol fonts should actually be scaled \magstep1.5, +% but that is not a standard magnification. + +% Fonts for title page: +\setfont\titlerm\rmbshape{12}{\magstep3} +\let\authorrm = \secrm + +% In order for the font changes to affect most math symbols and letters, +% we have to define the \textfont of the standard families. Since +% texinfo doesn't allow for producing subscripts and superscripts, we +% don't bother to reset \scriptfont and \scriptscriptfont (which would +% also require loading a lot more fonts). +% +\def\resetmathfonts{% + \textfont0 = \tenrm \textfont1 = \teni \textfont2 = \tensy + \textfont\itfam = \tenit \textfont\slfam = \tensl \textfont\bffam = \tenbf + \textfont\ttfam = \tentt \textfont\sffam = \tensf +} + + +% The font-changing commands redefine the meanings of \tenSTYLE, instead +% of just \STYLE. We do this so that font changes will continue to work +% in math mode, where it is the current \fam that is relevant in most +% cases, not the current font. Plain TeX does \def\bf{\fam=\bffam +% \tenbf}, for example. By redefining \tenbf, we obviate the need to +% redefine \bf itself. +\def\textfonts{% + \let\tenrm=\textrm \let\tenit=\textit \let\tensl=\textsl + \let\tenbf=\textbf \let\tentt=\texttt \let\smallcaps=\textsc + \let\tensf=\textsf \let\teni=\texti \let\tensy=\textsy \let\tenttsl=\textttsl + \resetmathfonts} +\def\chapfonts{% + \let\tenrm=\chaprm \let\tenit=\chapit \let\tensl=\chapsl + \let\tenbf=\chapbf \let\tentt=\chaptt \let\smallcaps=\chapsc + \let\tensf=\chapsf \let\teni=\chapi \let\tensy=\chapsy \let\tenttsl=\chapttsl + \resetmathfonts} +\def\secfonts{% + \let\tenrm=\secrm \let\tenit=\secit \let\tensl=\secsl + \let\tenbf=\secbf \let\tentt=\sectt \let\smallcaps=\secsc + \let\tensf=\secsf \let\teni=\seci \let\tensy=\secsy \let\tenttsl=\secttsl + \resetmathfonts} +\def\subsecfonts{% + \let\tenrm=\ssecrm \let\tenit=\ssecit \let\tensl=\ssecsl + \let\tenbf=\ssecbf \let\tentt=\ssectt \let\smallcaps=\ssecsc + \let\tensf=\ssecsf \let\teni=\sseci \let\tensy=\ssecsy \let\tenttsl=\ssecttsl + \resetmathfonts} +\def\indexfonts{% + \let\tenrm=\indrm \let\tenit=\indit \let\tensl=\indsl + \let\tenbf=\indbf \let\tentt=\indtt \let\smallcaps=\indsc + \let\tensf=\indsf \let\teni=\indi \let\tensy=\indsy \let\tenttsl=\indttsl + \resetmathfonts} + +% Set up the default fonts, so we can use them for creating boxes. +% +\textfonts + +% Count depth in font-changes, for error checks +\newcount\fontdepth \fontdepth=0 + +% Fonts for short table of contents. +\setfont\shortcontrm\rmshape{12}{1000} +\setfont\shortcontbf\bxshape{12}{1000} +\setfont\shortcontsl\slshape{12}{1000} + +%% Add scribe-like font environments, plus @l for inline lisp (usually sans +%% serif) and @ii for TeX italic + +% \smartitalic{ARG} outputs arg in italics, followed by an italic correction +% unless the following character is such as not to need one. +\def\smartitalicx{\ifx\next,\else\ifx\next-\else\ifx\next.\else\/\fi\fi\fi} +\def\smartitalic#1{{\sl #1}\futurelet\next\smartitalicx} + +\let\i=\smartitalic +\let\var=\smartitalic +\let\dfn=\smartitalic +\let\emph=\smartitalic +\let\cite=\smartitalic + +\def\b#1{{\bf #1}} +\let\strong=\b + +% We can't just use \exhyphenpenalty, because that only has effect at +% the end of a paragraph. Restore normal hyphenation at the end of the +% group within which \nohyphenation is presumably called. +% +\def\nohyphenation{\hyphenchar\font = -1 \aftergroup\restorehyphenation} +\def\restorehyphenation{\hyphenchar\font = `- } + +\def\t#1{% + {\tt \rawbackslash \frenchspacing #1}% + \null +} +\let\ttfont=\t +\def\samp #1{`\tclose{#1}'\null} +\def\key #1{{\ttsl \nohyphenation \uppercase{#1}}\null} +\def\ctrl #1{{\tt \rawbackslash \hat}#1} + +\let\file=\samp +\let\url=\samp % perhaps include a hypertex \special eventually + +% @code is a modification of @t, +% which makes spaces the same size as normal in the surrounding text. +\def\tclose#1{% + {% + % Change normal interword space to be same as for the current font. + \spaceskip = \fontdimen2\font + % + % Switch to typewriter. + \tt + % + % But `\ ' produces the large typewriter interword space. + \def\ {{\spaceskip = 0pt{} }}% + % + % Turn off hyphenation. + \nohyphenation + % + \rawbackslash + \frenchspacing + #1% + }% + \null +} + +% We *must* turn on hyphenation at `-' and `_' in \code. +% Otherwise, it is too hard to avoid overfull hboxes +% in the Emacs manual, the Library manual, etc. + +% Unfortunately, TeX uses one parameter (\hyphenchar) to control +% both hyphenation at - and hyphenation within words. +% We must therefore turn them both off (\tclose does that) +% and arrange explicitly to hyphenate an a dash. +% -- rms. +{ +\catcode`\-=\active +\catcode`\_=\active +\global\def\code{\begingroup \catcode`\-=\active \let-\codedash \catcode`\_=\active \let_\codeunder \codex} +% The following is used by \doprintindex to insure that long function names +% wrap around. It is necessary for - and _ to be active before the index is +% read from the file, as \entry parses the arguments long before \code is +% ever called. -- mycroft +\global\def\indexbreaks{\catcode`\-=\active \let-\realdash \catcode`\_=\active \let_\realunder} +} + +\def\realdash{-} +\def\realunder{_} +\def\codedash{-\discretionary{}{}{}} +\def\codeunder{\normalunderscore\discretionary{}{}{}} +\def\codex #1{\tclose{#1}\endgroup} + +%\let\exp=\tclose %Was temporary + +% @kbd is like @code, except that if the argument is just one @key command, +% then @kbd has no effect. +% +\def\xkey{\key} +\def\kbdfoo#1#2#3\par{\def\one{#1}\def\three{#3}\def\threex{??}% +\ifx\one\xkey\ifx\threex\three \key{#2}% +\else{\tclose{\ttsl\look}}\fi +\else{\tclose{\ttsl\look}}\fi} + +% Check if we are currently using a typewriter font. Since all the +% Computer Modern typewriter fonts have zero interword stretch (and +% shrink), and it is reasonable to expect all typewriter fonts to have +% this property, we can check that font parameter. +% +\def\ifmonospace{\ifdim\fontdimen3\font=0pt } + +% Typeset a dimension, e.g., `in' or `pt'. The only reason for the +% argument is to make the input look right: @dmn{pt} instead of +% @dmn{}pt. +% +\def\dmn#1{\thinspace #1} + +\def\kbd#1{\def\look{#1}\expandafter\kbdfoo\look??\par} + +\def\l#1{{\li #1}\null} % + +\def\r#1{{\rm #1}} % roman font +% Use of \lowercase was suggested. +\def\sc#1{{\smallcaps#1}} % smallcaps font +\def\ii#1{{\it #1}} % italic font + +\message{page headings,} + +\newskip\titlepagetopglue \titlepagetopglue = 1.5in +\newskip\titlepagebottomglue \titlepagebottomglue = 2pc + +% First the title page. Must do @settitle before @titlepage. +\def\titlefont#1{{\titlerm #1}} + +\newif\ifseenauthor +\newif\iffinishedtitlepage + +\def\shorttitlepage{\parsearg\shorttitlepagezzz} +\def\shorttitlepagezzz #1{\begingroup\hbox{}\vskip 1.5in \chaprm \centerline{#1}% + \endgroup\page\hbox{}\page} + +\def\titlepage{\begingroup \parindent=0pt \textfonts + \let\subtitlerm=\tenrm +% I deinstalled the following change because \cmr12 is undefined. +% This change was not in the ChangeLog anyway. --rms. +% \let\subtitlerm=\cmr12 + \def\subtitlefont{\subtitlerm \normalbaselineskip = 13pt \normalbaselines}% + % + \def\authorfont{\authorrm \normalbaselineskip = 16pt \normalbaselines}% + % + % Leave some space at the very top of the page. + \vglue\titlepagetopglue + % + % Now you can print the title using @title. + \def\title{\parsearg\titlezzz}% + \def\titlezzz##1{\leftline{\titlefont{##1}} + % print a rule at the page bottom also. + \finishedtitlepagefalse + \vskip4pt \hrule height 4pt width \hsize \vskip4pt}% + % No rule at page bottom unless we print one at the top with @title. + \finishedtitlepagetrue + % + % Now you can put text using @subtitle. + \def\subtitle{\parsearg\subtitlezzz}% + \def\subtitlezzz##1{{\subtitlefont \rightline{##1}}}% + % + % @author should come last, but may come many times. + \def\author{\parsearg\authorzzz}% + \def\authorzzz##1{\ifseenauthor\else\vskip 0pt plus 1filll\seenauthortrue\fi + {\authorfont \leftline{##1}}}% + % + % Most title ``pages'' are actually two pages long, with space + % at the top of the second. We don't want the ragged left on the second. + \let\oldpage = \page + \def\page{% + \iffinishedtitlepage\else + \finishtitlepage + \fi + \oldpage + \let\page = \oldpage + \hbox{}}% +% \def\page{\oldpage \hbox{}} +} + +\def\Etitlepage{% + \iffinishedtitlepage\else + \finishtitlepage + \fi + % It is important to do the page break before ending the group, + % because the headline and footline are only empty inside the group. + % If we use the new definition of \page, we always get a blank page + % after the title page, which we certainly don't want. + \oldpage + \endgroup + \HEADINGSon +} + +\def\finishtitlepage{% + \vskip4pt \hrule height 2pt width \hsize + \vskip\titlepagebottomglue + \finishedtitlepagetrue +} + +%%% Set up page headings and footings. + +\let\thispage=\folio + +\newtoks \evenheadline % Token sequence for heading line of even pages +\newtoks \oddheadline % Token sequence for heading line of odd pages +\newtoks \evenfootline % Token sequence for footing line of even pages +\newtoks \oddfootline % Token sequence for footing line of odd pages + +% Now make Tex use those variables +\headline={{\textfonts\rm \ifodd\pageno \the\oddheadline + \else \the\evenheadline \fi}} +\footline={{\textfonts\rm \ifodd\pageno \the\oddfootline + \else \the\evenfootline \fi}\HEADINGShook} +\let\HEADINGShook=\relax + +% Commands to set those variables. +% For example, this is what @headings on does +% @evenheading @thistitle|@thispage|@thischapter +% @oddheading @thischapter|@thispage|@thistitle +% @evenfooting @thisfile|| +% @oddfooting ||@thisfile + +\def\evenheading{\parsearg\evenheadingxxx} +\def\oddheading{\parsearg\oddheadingxxx} +\def\everyheading{\parsearg\everyheadingxxx} + +\def\evenfooting{\parsearg\evenfootingxxx} +\def\oddfooting{\parsearg\oddfootingxxx} +\def\everyfooting{\parsearg\everyfootingxxx} + +{\catcode`\@=0 % + +\gdef\evenheadingxxx #1{\evenheadingyyy #1@|@|@|@|\finish} +\gdef\evenheadingyyy #1@|#2@|#3@|#4\finish{% +\global\evenheadline={\rlap{\centerline{#2}}\line{#1\hfil#3}}} + +\gdef\oddheadingxxx #1{\oddheadingyyy #1@|@|@|@|\finish} +\gdef\oddheadingyyy #1@|#2@|#3@|#4\finish{% +\global\oddheadline={\rlap{\centerline{#2}}\line{#1\hfil#3}}} + +\gdef\everyheadingxxx #1{\everyheadingyyy #1@|@|@|@|\finish} +\gdef\everyheadingyyy #1@|#2@|#3@|#4\finish{% +\global\evenheadline={\rlap{\centerline{#2}}\line{#1\hfil#3}} +\global\oddheadline={\rlap{\centerline{#2}}\line{#1\hfil#3}}} + +\gdef\evenfootingxxx #1{\evenfootingyyy #1@|@|@|@|\finish} +\gdef\evenfootingyyy #1@|#2@|#3@|#4\finish{% +\global\evenfootline={\rlap{\centerline{#2}}\line{#1\hfil#3}}} + +\gdef\oddfootingxxx #1{\oddfootingyyy #1@|@|@|@|\finish} +\gdef\oddfootingyyy #1@|#2@|#3@|#4\finish{% +\global\oddfootline={\rlap{\centerline{#2}}\line{#1\hfil#3}}} + +\gdef\everyfootingxxx #1{\everyfootingyyy #1@|@|@|@|\finish} +\gdef\everyfootingyyy #1@|#2@|#3@|#4\finish{% +\global\evenfootline={\rlap{\centerline{#2}}\line{#1\hfil#3}} +\global\oddfootline={\rlap{\centerline{#2}}\line{#1\hfil#3}}} +% +}% unbind the catcode of @. + +% @headings double turns headings on for double-sided printing. +% @headings single turns headings on for single-sided printing. +% @headings off turns them off. +% @headings on same as @headings double, retained for compatibility. +% @headings after turns on double-sided headings after this page. +% @headings doubleafter turns on double-sided headings after this page. +% @headings singleafter turns on single-sided headings after this page. +% By default, they are off. + +\def\headings #1 {\csname HEADINGS#1\endcsname} + +\def\HEADINGSoff{ +\global\evenheadline={\hfil} \global\evenfootline={\hfil} +\global\oddheadline={\hfil} \global\oddfootline={\hfil}} +\HEADINGSoff +% When we turn headings on, set the page number to 1. +% For double-sided printing, put current file name in lower left corner, +% chapter name on inside top of right hand pages, document +% title on inside top of left hand pages, and page numbers on outside top +% edge of all pages. +\def\HEADINGSdouble{ +%\pagealignmacro +\global\pageno=1 +\global\evenfootline={\hfil} +\global\oddfootline={\hfil} +\global\evenheadline={\line{\folio\hfil\thistitle}} +\global\oddheadline={\line{\thischapter\hfil\folio}} +} +% For single-sided printing, chapter title goes across top left of page, +% page number on top right. +\def\HEADINGSsingle{ +%\pagealignmacro +\global\pageno=1 +\global\evenfootline={\hfil} +\global\oddfootline={\hfil} +\global\evenheadline={\line{\thischapter\hfil\folio}} +\global\oddheadline={\line{\thischapter\hfil\folio}} +} +\def\HEADINGSon{\HEADINGSdouble} + +\def\HEADINGSafter{\let\HEADINGShook=\HEADINGSdoublex} +\let\HEADINGSdoubleafter=\HEADINGSafter +\def\HEADINGSdoublex{% +\global\evenfootline={\hfil} +\global\oddfootline={\hfil} +\global\evenheadline={\line{\folio\hfil\thistitle}} +\global\oddheadline={\line{\thischapter\hfil\folio}} +} + +\def\HEADINGSsingleafter{\let\HEADINGShook=\HEADINGSsinglex} +\def\HEADINGSsinglex{% +\global\evenfootline={\hfil} +\global\oddfootline={\hfil} +\global\evenheadline={\line{\thischapter\hfil\folio}} +\global\oddheadline={\line{\thischapter\hfil\folio}} +} + +% Subroutines used in generating headings +% Produces Day Month Year style of output. +\def\today{\number\day\space +\ifcase\month\or +January\or February\or March\or April\or May\or June\or +July\or August\or September\or October\or November\or December\fi +\space\number\year} + +% Use this if you want the Month Day, Year style of output. +%\def\today{\ifcase\month\or +%January\or February\or March\or April\or May\or June\or +%July\or August\or September\or October\or November\or December\fi +%\space\number\day, \number\year} + +% @settitle line... specifies the title of the document, for headings +% It generates no output of its own + +\def\thistitle{No Title} +\def\settitle{\parsearg\settitlezzz} +\def\settitlezzz #1{\gdef\thistitle{#1}} + +\message{tables,} + +% @tabs -- simple alignment + +% These don't work. For one thing, \+ is defined as outer. +% So these macros cannot even be defined. + +%\def\tabs{\parsearg\tabszzz} +%\def\tabszzz #1{\settabs\+#1\cr} +%\def\tabline{\parsearg\tablinezzz} +%\def\tablinezzz #1{\+#1\cr} +%\def\&{&} + +% Tables -- @table, @ftable, @vtable, @item(x), @kitem(x), @xitem(x). + +% default indentation of table text +\newdimen\tableindent \tableindent=.8in +% default indentation of @itemize and @enumerate text +\newdimen\itemindent \itemindent=.3in +% margin between end of table item and start of table text. +\newdimen\itemmargin \itemmargin=.1in + +% used internally for \itemindent minus \itemmargin +\newdimen\itemmax + +% Note @table, @vtable, and @vtable define @item, @itemx, etc., with +% these defs. +% They also define \itemindex +% to index the item name in whatever manner is desired (perhaps none). + +\newif\ifitemxneedsnegativevskip + +\def\itemxpar{\par\ifitemxneedsnegativevskip\nobreak\vskip-\parskip\nobreak\fi} + +\def\internalBitem{\smallbreak \parsearg\itemzzz} +\def\internalBitemx{\itemxpar \parsearg\itemzzz} + +\def\internalBxitem "#1"{\def\xitemsubtopix{#1} \smallbreak \parsearg\xitemzzz} +\def\internalBxitemx "#1"{\def\xitemsubtopix{#1} \itemxpar \parsearg\xitemzzz} + +\def\internalBkitem{\smallbreak \parsearg\kitemzzz} +\def\internalBkitemx{\itemxpar \parsearg\kitemzzz} + +\def\kitemzzz #1{\dosubind {kw}{\code{#1}}{for {\bf \lastfunction}}% + \itemzzz {#1}} + +\def\xitemzzz #1{\dosubind {kw}{\code{#1}}{for {\bf \xitemsubtopic}}% + \itemzzz {#1}} + +\def\itemzzz #1{\begingroup % + \advance\hsize by -\rightskip + \advance\hsize by -\tableindent + \setbox0=\hbox{\itemfont{#1}}% + \itemindex{#1}% + \nobreak % This prevents a break before @itemx. + % + % Be sure we are not still in the middle of a paragraph. + %{\parskip = 0in + %\par + %}% + % + % If the item text does not fit in the space we have, put it on a line + % by itself, and do not allow a page break either before or after that + % line. We do not start a paragraph here because then if the next + % command is, e.g., @kindex, the whatsit would get put into the + % horizontal list on a line by itself, resulting in extra blank space. + \ifdim \wd0>\itemmax + % + % Make this a paragraph so we get the \parskip glue and wrapping, + % but leave it ragged-right. + \begingroup + \advance\leftskip by-\tableindent + \advance\hsize by\tableindent + \advance\rightskip by0pt plus1fil + \leavevmode\unhbox0\par + \endgroup + % + % We're going to be starting a paragraph, but we don't want the + % \parskip glue -- logically it's part of the @item we just started. + \nobreak \vskip-\parskip + % + % Stop a page break at the \parskip glue coming up. Unfortunately + % we can't prevent a possible page break at the following + % \baselineskip glue. + \nobreak + \endgroup + \itemxneedsnegativevskipfalse + \else + % The item text fits into the space. Start a paragraph, so that the + % following text (if any) will end up on the same line. Since that + % text will be indented by \tableindent, we make the item text be in + % a zero-width box. + \noindent + \rlap{\hskip -\tableindent\box0}\ignorespaces% + \endgroup% + \itemxneedsnegativevskiptrue% + \fi +} + +\def\item{\errmessage{@item while not in a table}} +\def\itemx{\errmessage{@itemx while not in a table}} +\def\kitem{\errmessage{@kitem while not in a table}} +\def\kitemx{\errmessage{@kitemx while not in a table}} +\def\xitem{\errmessage{@xitem while not in a table}} +\def\xitemx{\errmessage{@xitemx while not in a table}} + +%% Contains a kludge to get @end[description] to work +\def\description{\tablez{\dontindex}{1}{}{}{}{}} + +\def\table{\begingroup\inENV\obeylines\obeyspaces\tablex} +{\obeylines\obeyspaces% +\gdef\tablex #1^^M{% +\tabley\dontindex#1 \endtabley}} + +\def\ftable{\begingroup\inENV\obeylines\obeyspaces\ftablex} +{\obeylines\obeyspaces% +\gdef\ftablex #1^^M{% +\tabley\fnitemindex#1 \endtabley +\def\Eftable{\endgraf\afterenvbreak\endgroup}% +\let\Etable=\relax}} + +\def\vtable{\begingroup\inENV\obeylines\obeyspaces\vtablex} +{\obeylines\obeyspaces% +\gdef\vtablex #1^^M{% +\tabley\vritemindex#1 \endtabley +\def\Evtable{\endgraf\afterenvbreak\endgroup}% +\let\Etable=\relax}} + +\def\dontindex #1{} +\def\fnitemindex #1{\doind {fn}{\code{#1}}}% +\def\vritemindex #1{\doind {vr}{\code{#1}}}% + +{\obeyspaces % +\gdef\tabley#1#2 #3 #4 #5 #6 #7\endtabley{\endgroup% +\tablez{#1}{#2}{#3}{#4}{#5}{#6}}} + +\def\tablez #1#2#3#4#5#6{% +\aboveenvbreak % +\begingroup % +\def\Edescription{\Etable}% Necessary kludge. +\let\itemindex=#1% +\ifnum 0#3>0 \advance \leftskip by #3\mil \fi % +\ifnum 0#4>0 \tableindent=#4\mil \fi % +\ifnum 0#5>0 \advance \rightskip by #5\mil \fi % +\def\itemfont{#2}% +\itemmax=\tableindent % +\advance \itemmax by -\itemmargin % +\advance \leftskip by \tableindent % +\exdentamount=\tableindent +\parindent = 0pt +\parskip = \smallskipamount +\ifdim \parskip=0pt \parskip=2pt \fi% +\def\Etable{\endgraf\afterenvbreak\endgroup}% +\let\item = \internalBitem % +\let\itemx = \internalBitemx % +\let\kitem = \internalBkitem % +\let\kitemx = \internalBkitemx % +\let\xitem = \internalBxitem % +\let\xitemx = \internalBxitemx % +} + +% This is the counter used by @enumerate, which is really @itemize + +\newcount \itemno + +\def\itemize{\parsearg\itemizezzz} + +\def\itemizezzz #1{% + \begingroup % ended by the @end itemsize + \itemizey {#1}{\Eitemize} +} + +\def\itemizey #1#2{% +\aboveenvbreak % +\itemmax=\itemindent % +\advance \itemmax by -\itemmargin % +\advance \leftskip by \itemindent % +\exdentamount=\itemindent +\parindent = 0pt % +\parskip = \smallskipamount % +\ifdim \parskip=0pt \parskip=2pt \fi% +\def#2{\endgraf\afterenvbreak\endgroup}% +\def\itemcontents{#1}% +\let\item=\itemizeitem} + +% Set sfcode to normal for the chars that usually have another value. +% These are `.?!:;,' +\def\frenchspacing{\sfcode46=1000 \sfcode63=1000 \sfcode33=1000 + \sfcode58=1000 \sfcode59=1000 \sfcode44=1000 } + +% \splitoff TOKENS\endmark defines \first to be the first token in +% TOKENS, and \rest to be the remainder. +% +\def\splitoff#1#2\endmark{\def\first{#1}\def\rest{#2}}% + +% Allow an optional argument of an uppercase letter, lowercase letter, +% or number, to specify the first label in the enumerated list. No +% argument is the same as `1'. +% +\def\enumerate{\parsearg\enumeratezzz} +\def\enumeratezzz #1{\enumeratey #1 \endenumeratey} +\def\enumeratey #1 #2\endenumeratey{% + \begingroup % ended by the @end enumerate + % + % If we were given no argument, pretend we were given `1'. + \def\thearg{#1}% + \ifx\thearg\empty \def\thearg{1}\fi + % + % Detect if the argument is a single token. If so, it might be a + % letter. Otherwise, the only valid thing it can be is a number. + % (We will always have one token, because of the test we just made. + % This is a good thing, since \splitoff doesn't work given nothing at + % all -- the first parameter is undelimited.) + \expandafter\splitoff\thearg\endmark + \ifx\rest\empty + % Only one token in the argument. It could still be anything. + % A ``lowercase letter'' is one whose \lccode is nonzero. + % An ``uppercase letter'' is one whose \lccode is both nonzero, and + % not equal to itself. + % Otherwise, we assume it's a number. + % + % We need the \relax at the end of the \ifnum lines to stop TeX from + % continuing to look for a <number>. + % + \ifnum\lccode\expandafter`\thearg=0\relax + \numericenumerate % a number (we hope) + \else + % It's a letter. + \ifnum\lccode\expandafter`\thearg=\expandafter`\thearg\relax + \lowercaseenumerate % lowercase letter + \else + \uppercaseenumerate % uppercase letter + \fi + \fi + \else + % Multiple tokens in the argument. We hope it's a number. + \numericenumerate + \fi +} + +% An @enumerate whose labels are integers. The starting integer is +% given in \thearg. +% +\def\numericenumerate{% + \itemno = \thearg + \startenumeration{\the\itemno}% +} + +% The starting (lowercase) letter is in \thearg. +\def\lowercaseenumerate{% + \itemno = \expandafter`\thearg + \startenumeration{% + % Be sure we're not beyond the end of the alphabet. + \ifnum\itemno=0 + \errmessage{No more lowercase letters in @enumerate; get a bigger + alphabet}% + \fi + \char\lccode\itemno + }% +} + +% The starting (uppercase) letter is in \thearg. +\def\uppercaseenumerate{% + \itemno = \expandafter`\thearg + \startenumeration{% + % Be sure we're not beyond the end of the alphabet. + \ifnum\itemno=0 + \errmessage{No more uppercase letters in @enumerate; get a bigger + alphabet} + \fi + \char\uccode\itemno + }% +} + +% Call itemizey, adding a period to the first argument and supplying the +% common last two arguments. Also subtract one from the initial value in +% \itemno, since @item increments \itemno. +% +\def\startenumeration#1{% + \advance\itemno by -1 + \itemizey{#1.}\Eenumerate\flushcr +} + +% @alphaenumerate and @capsenumerate are abbreviations for giving an arg +% to @enumerate. +% +\def\alphaenumerate{\enumerate{a}} +\def\capsenumerate{\enumerate{A}} +\def\Ealphaenumerate{\Eenumerate} +\def\Ecapsenumerate{\Eenumerate} + +% Definition of @item while inside @itemize. + +\def\itemizeitem{% +\advance\itemno by 1 +{\let\par=\endgraf \smallbreak}% +\ifhmode \errmessage{\in hmode at itemizeitem}\fi +{\parskip=0in \hskip 0pt +\hbox to 0pt{\hss \itemcontents\hskip \itemmargin}% +\vadjust{\penalty 1200}}% +\flushcr} + +% @multitable macros +% Amy Hendrickson, 8/18/94, 3/6/96 +% +% @multitable ... @end multitable will make as many columns as desired. +% Contents of each column will wrap at width given in preamble. Width +% can be specified either with sample text given in a template line, +% or in percent of \hsize, the current width of text on page. + +% Table can continue over pages but will only break between lines. + +% To make preamble: +% +% Either define widths of columns in terms of percent of \hsize: +% @multitable @columnfractions .25 .3 .45 +% @item ... +% +% Numbers following @columnfractions are the percent of the total +% current hsize to be used for each column. You may use as many +% columns as desired. + +% Or use a template: +% @multitable {Column 1 template} {Column 2 template} {Column 3 template} +% @item ... +% using the widest term desired in each column. +% +% For those who want to use more than one line's worth of words in +% the preamble, break the line within one argument and it +% will parse correctly, i.e., +% +% @multitable {Column 1 template} {Column 2 template} {Column 3 +% template} +% Not: +% @multitable {Column 1 template} {Column 2 template} +% {Column 3 template} + +% Each new table line starts with @item, each subsequent new column +% starts with @tab. Empty columns may be produced by supplying @tab's +% with nothing between them for as many times as empty columns are needed, +% ie, @tab@tab@tab will produce two empty columns. + +% @item, @tab, @multicolumn or @endmulticolumn do not need to be on their +% own lines, but it will not hurt if they are. + +% Sample multitable: + +% @multitable {Column 1 template} {Column 2 template} {Column 3 template} +% @item first col stuff @tab second col stuff @tab third col +% @item +% first col stuff +% @tab +% second col stuff +% @tab +% third col +% @item first col stuff @tab second col stuff +% @tab Many paragraphs of text may be used in any column. +% +% They will wrap at the width determined by the template. +% @item@tab@tab This will be in third column. +% @end multitable + +% Default dimensions may be reset by user. +% @multitableparskip is vertical space between paragraphs in table. +% @multitableparindent is paragraph indent in table. +% @multitablecolmargin is horizontal space to be left between columns. +% @multitablelinespace is space to leave between table items, baseline +% to baseline. +% 0pt means it depends on current normal line spacing. + +%%%% +% Dimensions + +\newskip\multitableparskip +\newskip\multitableparindent +\newdimen\multitablecolspace +\newskip\multitablelinespace +\multitableparskip=0pt +\multitableparindent=6pt +\multitablecolspace=12pt +\multitablelinespace=0pt + +%%%% +% Macros used to set up halign preamble: +\let\endsetuptable\relax +\def\xendsetuptable{\endsetuptable} +\let\columnfractions\relax +\def\xcolumnfractions{\columnfractions} +\newif\ifsetpercent + +%% 2/1/96, to allow fractions to be given with more than one digit. +\def\pickupwholefraction#1 {\global\advance\colcount by1 % +\expandafter\xdef\csname col\the\colcount\endcsname{.#1\hsize}% +\setuptable} + +\newcount\colcount +\def\setuptable#1{\def\firstarg{#1}% +\ifx\firstarg\xendsetuptable\let\go\relax% +\else + \ifx\firstarg\xcolumnfractions\global\setpercenttrue% + \else + \ifsetpercent + \let\go\pickupwholefraction % In this case arg of setuptable + % is the decimal point before the + % number given in percent of hsize. + % We don't need this so we don't use it. + \else + \global\advance\colcount by1 + \setbox0=\hbox{#1}% + \expandafter\xdef\csname col\the\colcount\endcsname{\the\wd0}% + \fi% + \fi% +\ifx\go\pickupwholefraction\else\let\go\setuptable\fi% +\fi\go} + +%%%% +% multitable syntax +\def\tab{&\hskip1sp\relax} % 2/2/96 + % tiny skip here makes sure this column space is + % maintained, even if it is never used. + + +%%%% +% @multitable ... @end multitable definitions: + +\def\multitable{\parsearg\dotable} + +\def\dotable#1{\bgroup +\let\item\cr +\tolerance=9500 +\hbadness=9500 +\setmultitablespacing +\parskip=\multitableparskip +\parindent=\multitableparindent +\overfullrule=0pt +\global\colcount=0\relax% +\def\Emultitable{\global\setpercentfalse\global\everycr{}\cr\egroup\egroup}% + % To parse everything between @multitable and @item : +\setuptable#1 \endsetuptable + % Need to reset this to 0 after \setuptable. +\global\colcount=0\relax% + % + % This preamble sets up a generic column definition, which will + % be used as many times as user calls for columns. + % \vtop will set a single line and will also let text wrap and + % continue for many paragraphs if desired. +\halign\bgroup&\global\advance\colcount by 1\relax% +\multistrut\vtop{\hsize=\expandafter\csname col\the\colcount\endcsname + % In order to keep entries from bumping into each other + % we will add a \leftskip of \multitablecolspace to all columns after + % the first one. + % If a template has been used, we will add \multitablecolspace + % to the width of each template entry. + % If user has set preamble in terms of percent of \hsize + % we will use that dimension as the width of the column, and + % the \leftskip will keep entries from bumping into each other. + % Table will start at left margin and final column will justify at + % right margin. +\ifnum\colcount=1 +\else + \ifsetpercent + \else + % If user has <not> set preamble in terms of percent of \hsize + % we will advance \hsize by \multitablecolspace + \advance\hsize by \multitablecolspace + \fi + % In either case we will make \leftskip=\multitablecolspace: +\leftskip=\multitablecolspace +\fi +\noindent##}\cr% + % \everycr will reset column counter, \colcount, at the end of + % each line. Every column entry will cause \colcount to advance by one. + % The table preamble + % looks at the current \colcount to find the correct column width. +\global\everycr{\noalign{% +\filbreak%% keeps underfull box messages off when table breaks over pages. +\global\colcount=0\relax}} +} + +\def\setmultitablespacing{% test to see if user has set \multitablelinespace. +% If so, do nothing. If not, give it an appropriate dimension based on +% current baselineskip. +\setbox0=\vbox{Xy} +\ifdim\multitablelinespace=0pt +%% strut to put in table in case some entry doesn't have descenders, +%% to keep lines equally spaced +\gdef\multistrut{\vrule height\ht0 depth\dp0 width0pt\relax} +%% Test to see if parskip is larger than space between lines of +%% table. If not, do nothing. +%% If so, set to same dimension as multitablelinespace. +\else +\gdef\multistrut{\vrule height\multitablelinespace depth\dp0 +width0pt\relax} \fi +\ifdim\multitableparskip>\multitablelinespace +\global\multitableparskip=\multitablelinespace +\global\advance\multitableparskip-7pt %% to keep parskip somewhat smaller + %% than skip between lines in the table. +\fi% +\ifdim\multitableparskip=0pt +\global\multitableparskip=\multitablelinespace +\global\advance\multitableparskip-7pt %% to keep parskip somewhat smaller + %% than skip between lines in the table. +\fi} +\message{indexing,} +% Index generation facilities + +% Define \newwrite to be identical to plain tex's \newwrite +% except not \outer, so it can be used within \newindex. +{\catcode`\@=11 +\gdef\newwrite{\alloc@7\write\chardef\sixt@@n}} + +% \newindex {foo} defines an index named foo. +% It automatically defines \fooindex such that +% \fooindex ...rest of line... puts an entry in the index foo. +% It also defines \fooindfile to be the number of the output channel for +% the file that accumulates this index. The file's extension is foo. +% The name of an index should be no more than 2 characters long +% for the sake of vms. + +\def\newindex #1{ +\expandafter\newwrite \csname#1indfile\endcsname% Define number for output file +\openout \csname#1indfile\endcsname \jobname.#1 % Open the file +\expandafter\xdef\csname#1index\endcsname{% % Define \xxxindex +\noexpand\doindex {#1}} +} + +% @defindex foo == \newindex{foo} + +\def\defindex{\parsearg\newindex} + +% Define @defcodeindex, like @defindex except put all entries in @code. + +\def\newcodeindex #1{ +\expandafter\newwrite \csname#1indfile\endcsname% Define number for output file +\openout \csname#1indfile\endcsname \jobname.#1 % Open the file +\expandafter\xdef\csname#1index\endcsname{% % Define \xxxindex +\noexpand\docodeindex {#1}} +} + +\def\defcodeindex{\parsearg\newcodeindex} + +% @synindex foo bar makes index foo feed into index bar. +% Do this instead of @defindex foo if you don't want it as a separate index. +\def\synindex #1 #2 {% +\expandafter\let\expandafter\synindexfoo\expandafter=\csname#2indfile\endcsname +\expandafter\let\csname#1indfile\endcsname=\synindexfoo +\expandafter\xdef\csname#1index\endcsname{% % Define \xxxindex +\noexpand\doindex {#2}}% +} + +% @syncodeindex foo bar similar, but put all entries made for index foo +% inside @code. +\def\syncodeindex #1 #2 {% +\expandafter\let\expandafter\synindexfoo\expandafter=\csname#2indfile\endcsname +\expandafter\let\csname#1indfile\endcsname=\synindexfoo +\expandafter\xdef\csname#1index\endcsname{% % Define \xxxindex +\noexpand\docodeindex {#2}}% +} + +% Define \doindex, the driver for all \fooindex macros. +% Argument #1 is generated by the calling \fooindex macro, +% and it is "foo", the name of the index. + +% \doindex just uses \parsearg; it calls \doind for the actual work. +% This is because \doind is more useful to call from other macros. + +% There is also \dosubind {index}{topic}{subtopic} +% which makes an entry in a two-level index such as the operation index. + +\def\doindex#1{\edef\indexname{#1}\parsearg\singleindexer} +\def\singleindexer #1{\doind{\indexname}{#1}} + +% like the previous two, but they put @code around the argument. +\def\docodeindex#1{\edef\indexname{#1}\parsearg\singlecodeindexer} +\def\singlecodeindexer #1{\doind{\indexname}{\code{#1}}} + +\def\indexdummies{% +% Take care of the plain tex accent commands. +\def\"{\realbackslash "}% +\def\`{\realbackslash `}% +\def\'{\realbackslash '}% +\def\^{\realbackslash ^}% +\def\~{\realbackslash ~}% +\def\={\realbackslash =}% +\def\b{\realbackslash b}% +\def\c{\realbackslash c}% +\def\d{\realbackslash d}% +\def\u{\realbackslash u}% +\def\v{\realbackslash v}% +\def\H{\realbackslash H}% +% Take care of the plain tex special European modified letters. +\def\oe{\realbackslash oe}% +\def\ae{\realbackslash ae}% +\def\aa{\realbackslash aa}% +\def\OE{\realbackslash OE}% +\def\AE{\realbackslash AE}% +\def\AA{\realbackslash AA}% +\def\o{\realbackslash o}% +\def\O{\realbackslash O}% +\def\l{\realbackslash l}% +\def\L{\realbackslash L}% +\def\ss{\realbackslash ss}% +% Take care of texinfo commands likely to appear in an index entry. +\def\_{{\realbackslash _}}% +\def\w{\realbackslash w }% +\def\bf{\realbackslash bf }% +\def\rm{\realbackslash rm }% +\def\sl{\realbackslash sl }% +\def\sf{\realbackslash sf}% +\def\tt{\realbackslash tt}% +\def\gtr{\realbackslash gtr}% +\def\less{\realbackslash less}% +\def\hat{\realbackslash hat}% +\def\char{\realbackslash char}% +\def\TeX{\realbackslash TeX}% +\def\dots{\realbackslash dots }% +\def\copyright{\realbackslash copyright }% +\def\tclose##1{\realbackslash tclose {##1}}% +\def\code##1{\realbackslash code {##1}}% +\def\samp##1{\realbackslash samp {##1}}% +\def\t##1{\realbackslash r {##1}}% +\def\r##1{\realbackslash r {##1}}% +\def\i##1{\realbackslash i {##1}}% +\def\b##1{\realbackslash b {##1}}% +\def\cite##1{\realbackslash cite {##1}}% +\def\key##1{\realbackslash key {##1}}% +\def\file##1{\realbackslash file {##1}}% +\def\var##1{\realbackslash var {##1}}% +\def\kbd##1{\realbackslash kbd {##1}}% +\def\dfn##1{\realbackslash dfn {##1}}% +\def\emph##1{\realbackslash emph {##1}}% +\unsepspaces +} + +% If an index command is used in an @example environment, any spaces +% therein should become regular spaces in the raw index file, not the +% expansion of \tie (\\leavevmode \penalty \@M \ ). +{\obeyspaces + \gdef\unsepspaces{\obeyspaces\let =\space}} + +% \indexnofonts no-ops all font-change commands. +% This is used when outputting the strings to sort the index by. +\def\indexdummyfont#1{#1} +\def\indexdummytex{TeX} +\def\indexdummydots{...} + +\def\indexnofonts{% +% Just ignore accents. +\let\"=\indexdummyfont +\let\`=\indexdummyfont +\let\'=\indexdummyfont +\let\^=\indexdummyfont +\let\~=\indexdummyfont +\let\==\indexdummyfont +\let\b=\indexdummyfont +\let\c=\indexdummyfont +\let\d=\indexdummyfont +\let\u=\indexdummyfont +\let\v=\indexdummyfont +\let\H=\indexdummyfont +% Take care of the plain tex special European modified letters. +\def\oe{oe}% +\def\ae{ae}% +\def\aa{aa}% +\def\OE{OE}% +\def\AE{AE}% +\def\AA{AA}% +\def\o{o}% +\def\O{O}% +\def\l{l}% +\def\L{L}% +\def\ss{ss}% +\let\w=\indexdummyfont +\let\t=\indexdummyfont +\let\r=\indexdummyfont +\let\i=\indexdummyfont +\let\b=\indexdummyfont +\let\emph=\indexdummyfont +\let\strong=\indexdummyfont +\let\cite=\indexdummyfont +\let\sc=\indexdummyfont +%Don't no-op \tt, since it isn't a user-level command +% and is used in the definitions of the active chars like <, >, |... +%\let\tt=\indexdummyfont +\let\tclose=\indexdummyfont +\let\code=\indexdummyfont +\let\file=\indexdummyfont +\let\samp=\indexdummyfont +\let\kbd=\indexdummyfont +\let\key=\indexdummyfont +\let\var=\indexdummyfont +\let\TeX=\indexdummytex +\let\dots=\indexdummydots +} + +% To define \realbackslash, we must make \ not be an escape. +% We must first make another character (@) an escape +% so we do not become unable to do a definition. + +{\catcode`\@=0 \catcode`\\=\other +@gdef@realbackslash{\}} + +\let\indexbackslash=0 %overridden during \printindex. + +\let\SETmarginindex=\relax %initialize! +% workhorse for all \fooindexes +% #1 is name of index, #2 is stuff to put there +\def\doind #1#2{% +% Put the index entry in the margin if desired. +\ifx\SETmarginindex\relax\else% +\insert\margin{\hbox{\vrule height8pt depth3pt width0pt #2}}% +\fi% +{\count10=\lastpenalty % +{\indexdummies % Must do this here, since \bf, etc expand at this stage +\escapechar=`\\% +{\let\folio=0% Expand all macros now EXCEPT \folio +\def\rawbackslashxx{\indexbackslash}% \indexbackslash isn't defined now +% so it will be output as is; and it will print as backslash in the indx. +% +% Now process the index-string once, with all font commands turned off, +% to get the string to sort the index by. +{\indexnofonts +\xdef\temp1{#2}% +}% +% Now produce the complete index entry. We process the index-string again, +% this time with font commands expanded, to get what to print in the index. +\edef\temp{% +\write \csname#1indfile\endcsname{% +\realbackslash entry {\temp1}{\folio}{#2}}}% +\temp }% +}\penalty\count10}} + +\def\dosubind #1#2#3{% +{\count10=\lastpenalty % +{\indexdummies % Must do this here, since \bf, etc expand at this stage +\escapechar=`\\% +{\let\folio=0% +\def\rawbackslashxx{\indexbackslash}% +% +% Now process the index-string once, with all font commands turned off, +% to get the string to sort the index by. +{\indexnofonts +\xdef\temp1{#2 #3}% +}% +% Now produce the complete index entry. We process the index-string again, +% this time with font commands expanded, to get what to print in the index. +\edef\temp{% +\write \csname#1indfile\endcsname{% +\realbackslash entry {\temp1}{\folio}{#2}{#3}}}% +\temp }% +}\penalty\count10}} + +% The index entry written in the file actually looks like +% \entry {sortstring}{page}{topic} +% or +% \entry {sortstring}{page}{topic}{subtopic} +% The texindex program reads in these files and writes files +% containing these kinds of lines: +% \initial {c} +% before the first topic whose initial is c +% \entry {topic}{pagelist} +% for a topic that is used without subtopics +% \primary {topic} +% for the beginning of a topic that is used with subtopics +% \secondary {subtopic}{pagelist} +% for each subtopic. + +% Define the user-accessible indexing commands +% @findex, @vindex, @kindex, @cindex. + +\def\findex {\fnindex} +\def\kindex {\kyindex} +\def\cindex {\cpindex} +\def\vindex {\vrindex} +\def\tindex {\tpindex} +\def\pindex {\pgindex} + +\def\cindexsub {\begingroup\obeylines\cindexsub} +{\obeylines % +\gdef\cindexsub "#1" #2^^M{\endgroup % +\dosubind{cp}{#2}{#1}}} + +% Define the macros used in formatting output of the sorted index material. + +% This is what you call to cause a particular index to get printed. +% Write +% @unnumbered Function Index +% @printindex fn + +\def\printindex{\parsearg\doprintindex} + +\def\doprintindex#1{% + \tex + \dobreak \chapheadingskip {10000} + \catcode`\%=\other\catcode`\&=\other\catcode`\#=\other + \catcode`\$=\other + \catcode`\~=\other + \indexbreaks + % + % The following don't help, since the chars were translated + % when the raw index was written, and their fonts were discarded + % due to \indexnofonts. + %\catcode`\"=\active + %\catcode`\^=\active + %\catcode`\_=\active + %\catcode`\|=\active + %\catcode`\<=\active + %\catcode`\>=\active + % % + \def\indexbackslash{\rawbackslashxx} + \indexfonts\rm \tolerance=9500 \advance\baselineskip -1pt + \begindoublecolumns + % + % See if the index file exists and is nonempty. + \openin 1 \jobname.#1s + \ifeof 1 + % \enddoublecolumns gets confused if there is no text in the index, + % and it loses the chapter title and the aux file entries for the + % index. The easiest way to prevent this problem is to make sure + % there is some text. + (Index is nonexistent) + \else + % + % If the index file exists but is empty, then \openin leaves \ifeof + % false. We have to make TeX try to read something from the file, so + % it can discover if there is anything in it. + \read 1 to \temp + \ifeof 1 + (Index is empty) + \else + \input \jobname.#1s + \fi + \fi + \closein 1 + \enddoublecolumns + \Etex +} + +% These macros are used by the sorted index file itself. +% Change them to control the appearance of the index. + +% Same as \bigskipamount except no shrink. +% \balancecolumns gets confused if there is any shrink. +\newskip\initialskipamount \initialskipamount 12pt plus4pt + +\def\initial #1{% +{\let\tentt=\sectt \let\tt=\sectt \let\sf=\sectt +\ifdim\lastskip<\initialskipamount +\removelastskip \penalty-200 \vskip \initialskipamount\fi +\line{\secbf#1\hfill}\kern 2pt\penalty10000}} + +% This typesets a paragraph consisting of #1, dot leaders, and then #2 +% flush to the right margin. It is used for index and table of contents +% entries. The paragraph is indented by \leftskip. +% +\def\entry #1#2{\begingroup + % + % Start a new paragraph if necessary, so our assignments below can't + % affect previous text. + \par + % + % Do not fill out the last line with white space. + \parfillskip = 0in + % + % No extra space above this paragraph. + \parskip = 0in + % + % Do not prefer a separate line ending with a hyphen to fewer lines. + \finalhyphendemerits = 0 + % + % \hangindent is only relevant when the entry text and page number + % don't both fit on one line. In that case, bob suggests starting the + % dots pretty far over on the line. Unfortunately, a large + % indentation looks wrong when the entry text itself is broken across + % lines. So we use a small indentation and put up with long leaders. + % + % \hangafter is reset to 1 (which is the value we want) at the start + % of each paragraph, so we need not do anything with that. + \hangindent=2em + % + % When the entry text needs to be broken, just fill out the first line + % with blank space. + \rightskip = 0pt plus1fil + % + % Start a ``paragraph'' for the index entry so the line breaking + % parameters we've set above will have an effect. + \noindent + % + % Insert the text of the index entry. TeX will do line-breaking on it. + #1% + % The following is kludged to not output a line of dots in the index if + % there are no page numbers. The next person who breaks this will be + % cursed by a Unix daemon. + \def\tempa{{\rm }}% + \def\tempb{#2}% + \edef\tempc{\tempa}% + \edef\tempd{\tempb}% + \ifx\tempc\tempd\ \else% + % + % If we must, put the page number on a line of its own, and fill out + % this line with blank space. (The \hfil is overwhelmed with the + % fill leaders glue in \indexdotfill if the page number does fit.) + \hfil\penalty50 + \null\nobreak\indexdotfill % Have leaders before the page number. + % + % The `\ ' here is removed by the implicit \unskip that TeX does as + % part of (the primitive) \par. Without it, a spurious underfull + % \hbox ensues. + \ #2% The page number ends the paragraph. + \fi% + \par +\endgroup} + +% Like \dotfill except takes at least 1 em. +\def\indexdotfill{\cleaders + \hbox{$\mathsurround=0pt \mkern1.5mu ${\it .}$ \mkern1.5mu$}\hskip 1em plus 1fill} + +\def\primary #1{\line{#1\hfil}} + +\newskip\secondaryindent \secondaryindent=0.5cm + +\def\secondary #1#2{ +{\parfillskip=0in \parskip=0in +\hangindent =1in \hangafter=1 +\noindent\hskip\secondaryindent\hbox{#1}\indexdotfill #2\par +}} + +%% Define two-column mode, which is used in indexes. +%% Adapted from the TeXbook, page 416. +\catcode `\@=11 + +\newbox\partialpage + +\newdimen\doublecolumnhsize + +\def\begindoublecolumns{\begingroup + % Grab any single-column material above us. + \output = {\global\setbox\partialpage + =\vbox{\unvbox255\kern -\topskip \kern \baselineskip}}% + \eject + % + % Now switch to the double-column output routine. + \output={\doublecolumnout}% + % + % Change the page size parameters. We could do this once outside this + % routine, in each of @smallbook, @afourpaper, and the default 8.5x11 + % format, but then we repeat the same computation. Repeating a couple + % of assignments once per index is clearly meaningless for the + % execution time, so we may as well do it once. + % + % First we halve the line length, less a little for the gutter between + % the columns. We compute the gutter based on the line length, so it + % changes automatically with the paper format. The magic constant + % below is chosen so that the gutter has the same value (well, +- < + % 1pt) as it did when we hard-coded it. + % + % We put the result in a separate register, \doublecolumhsize, so we + % can restore it in \pagesofar, after \hsize itself has (potentially) + % been clobbered. + % + \doublecolumnhsize = \hsize + \advance\doublecolumnhsize by -.04154\hsize + \divide\doublecolumnhsize by 2 + \hsize = \doublecolumnhsize + % + % Double the \vsize as well. (We don't need a separate register here, + % since nobody clobbers \vsize.) + \vsize = 2\vsize + \doublecolumnpagegoal +} + +\def\enddoublecolumns{\eject \endgroup \pagegoal=\vsize \unvbox\partialpage} + +\def\doublecolumnsplit{\splittopskip=\topskip \splitmaxdepth=\maxdepth + \global\dimen@=\pageheight \global\advance\dimen@ by-\ht\partialpage + \global\setbox1=\vsplit255 to\dimen@ \global\setbox0=\vbox{\unvbox1} + \global\setbox3=\vsplit255 to\dimen@ \global\setbox2=\vbox{\unvbox3} + \ifdim\ht0>\dimen@ \setbox255=\vbox{\unvbox0\unvbox2} \global\setbox255=\copy5 \fi + \ifdim\ht2>\dimen@ \setbox255=\vbox{\unvbox0\unvbox2} \global\setbox255=\copy5 \fi +} +\def\doublecolumnpagegoal{% + \dimen@=\vsize \advance\dimen@ by-2\ht\partialpage \global\pagegoal=\dimen@ +} +\def\pagesofar{\unvbox\partialpage % + \hsize=\doublecolumnhsize % have to restore this since output routine + \wd0=\hsize \wd2=\hsize \hbox to\pagewidth{\box0\hfil\box2}} +\def\doublecolumnout{% + \setbox5=\copy255 + {\vbadness=10000 \doublecolumnsplit} + \ifvbox255 + \setbox0=\vtop to\dimen@{\unvbox0} + \setbox2=\vtop to\dimen@{\unvbox2} + \onepageout\pagesofar \unvbox255 \penalty\outputpenalty + \else + \setbox0=\vbox{\unvbox5} + \ifvbox0 + \dimen@=\ht0 \advance\dimen@ by\topskip \advance\dimen@ by-\baselineskip + \divide\dimen@ by2 \splittopskip=\topskip \splitmaxdepth=\maxdepth + {\vbadness=10000 + \loop \global\setbox5=\copy0 + \setbox1=\vsplit5 to\dimen@ + \setbox3=\vsplit5 to\dimen@ + \ifvbox5 \global\advance\dimen@ by1pt \repeat + \setbox0=\vbox to\dimen@{\unvbox1} + \setbox2=\vbox to\dimen@{\unvbox3} + \global\setbox\partialpage=\vbox{\pagesofar} + \doublecolumnpagegoal + } + \fi + \fi +} + +\catcode `\@=\other +\message{sectioning,} +% Define chapters, sections, etc. + +\newcount \chapno +\newcount \secno \secno=0 +\newcount \subsecno \subsecno=0 +\newcount \subsubsecno \subsubsecno=0 + +% This counter is funny since it counts through charcodes of letters A, B, ... +\newcount \appendixno \appendixno = `\@ +\def\appendixletter{\char\the\appendixno} + +\newwrite \contentsfile +% This is called from \setfilename. +\def\opencontents{\openout \contentsfile = \jobname.toc} + +% Each @chapter defines this as the name of the chapter. +% page headings and footings can use it. @section does likewise + +\def\thischapter{} \def\thissection{} +\def\seccheck#1{\if \pageno<0 % +\errmessage{@#1 not allowed after generating table of contents}\fi +% +} + +\def\chapternofonts{% +\let\rawbackslash=\relax% +\let\frenchspacing=\relax% +\def\result{\realbackslash result} +\def\equiv{\realbackslash equiv} +\def\expansion{\realbackslash expansion} +\def\print{\realbackslash print} +\def\TeX{\realbackslash TeX} +\def\dots{\realbackslash dots} +\def\copyright{\realbackslash copyright} +\def\tt{\realbackslash tt} +\def\bf{\realbackslash bf } +\def\w{\realbackslash w} +\def\less{\realbackslash less} +\def\gtr{\realbackslash gtr} +\def\hat{\realbackslash hat} +\def\char{\realbackslash char} +\def\tclose##1{\realbackslash tclose {##1}} +\def\code##1{\realbackslash code {##1}} +\def\samp##1{\realbackslash samp {##1}} +\def\r##1{\realbackslash r {##1}} +\def\b##1{\realbackslash b {##1}} +\def\key##1{\realbackslash key {##1}} +\def\file##1{\realbackslash file {##1}} +\def\kbd##1{\realbackslash kbd {##1}} +% These are redefined because @smartitalic wouldn't work inside xdef. +\def\i##1{\realbackslash i {##1}} +\def\cite##1{\realbackslash cite {##1}} +\def\var##1{\realbackslash var {##1}} +\def\emph##1{\realbackslash emph {##1}} +\def\dfn##1{\realbackslash dfn {##1}} +} + +\newcount\absseclevel % used to calculate proper heading level +\newcount\secbase\secbase=0 % @raise/lowersections modify this count + +% @raisesections: treat @section as chapter, @subsection as section, etc. +\def\raisesections{\global\advance\secbase by -1} +\let\up=\raisesections % original BFox name + +% @lowersections: treat @chapter as section, @section as subsection, etc. +\def\lowersections{\global\advance\secbase by 1} +\let\down=\lowersections % original BFox name + +% Choose a numbered-heading macro +% #1 is heading level if unmodified by @raisesections or @lowersections +% #2 is text for heading +\def\numhead#1#2{\absseclevel=\secbase\advance\absseclevel by #1 +\ifcase\absseclevel + \chapterzzz{#2} +\or + \seczzz{#2} +\or + \numberedsubseczzz{#2} +\or + \numberedsubsubseczzz{#2} +\else + \ifnum \absseclevel<0 + \chapterzzz{#2} + \else + \numberedsubsubseczzz{#2} + \fi +\fi +} + +% like \numhead, but chooses appendix heading levels +\def\apphead#1#2{\absseclevel=\secbase\advance\absseclevel by #1 +\ifcase\absseclevel + \appendixzzz{#2} +\or + \appendixsectionzzz{#2} +\or + \appendixsubseczzz{#2} +\or + \appendixsubsubseczzz{#2} +\else + \ifnum \absseclevel<0 + \appendixzzz{#2} + \else + \appendixsubsubseczzz{#2} + \fi +\fi +} + +% like \numhead, but chooses numberless heading levels +\def\unnmhead#1#2{\absseclevel=\secbase\advance\absseclevel by #1 +\ifcase\absseclevel + \unnumberedzzz{#2} +\or + \unnumberedseczzz{#2} +\or + \unnumberedsubseczzz{#2} +\or + \unnumberedsubsubseczzz{#2} +\else + \ifnum \absseclevel<0 + \unnumberedzzz{#2} + \else + \unnumberedsubsubseczzz{#2} + \fi +\fi +} + + +\def\thischaptername{No Chapter Title} +\outer\def\chapter{\parsearg\chapteryyy} +\def\chapteryyy #1{\numhead0{#1}} % normally numhead0 calls chapterzzz +\def\chapterzzz #1{\seccheck{chapter}% +\secno=0 \subsecno=0 \subsubsecno=0 +\global\advance \chapno by 1 \message{\putwordChapter \the\chapno}% +\chapmacro {#1}{\the\chapno}% +\gdef\thissection{#1}% +\gdef\thischaptername{#1}% +% We don't substitute the actual chapter name into \thischapter +% because we don't want its macros evaluated now. +\xdef\thischapter{\putwordChapter{} \the\chapno: \noexpand\thischaptername}% +{\chapternofonts% +\edef\temp{{\realbackslash chapentry {#1}{\the\chapno}{\noexpand\folio}}}% +\escapechar=`\\% +\write \contentsfile \temp % +\donoderef % +\global\let\section = \numberedsec +\global\let\subsection = \numberedsubsec +\global\let\subsubsection = \numberedsubsubsec +}} + +\outer\def\appendix{\parsearg\appendixyyy} +\def\appendixyyy #1{\apphead0{#1}} % normally apphead0 calls appendixzzz +\def\appendixzzz #1{\seccheck{appendix}% +\secno=0 \subsecno=0 \subsubsecno=0 +\global\advance \appendixno by 1 \message{Appendix \appendixletter}% +\chapmacro {#1}{\putwordAppendix{} \appendixletter}% +\gdef\thissection{#1}% +\gdef\thischaptername{#1}% +\xdef\thischapter{\putwordAppendix{} \appendixletter: \noexpand\thischaptername}% +{\chapternofonts% +\edef\temp{{\realbackslash chapentry + {#1}{\putwordAppendix{} \appendixletter}{\noexpand\folio}}}% +\escapechar=`\\% +\write \contentsfile \temp % +\appendixnoderef % +\global\let\section = \appendixsec +\global\let\subsection = \appendixsubsec +\global\let\subsubsection = \appendixsubsubsec +}} + +% @centerchap is like @unnumbered, but the heading is centered. +\outer\def\centerchap{\parsearg\centerchapyyy} +\def\centerchapyyy #1{{\let\unnumbchapmacro=\centerchapmacro \unnumberedyyy{#1}}} + +\outer\def\top{\parsearg\unnumberedyyy} +\outer\def\unnumbered{\parsearg\unnumberedyyy} +\def\unnumberedyyy #1{\unnmhead0{#1}} % normally unnmhead0 calls unnumberedzzz +\def\unnumberedzzz #1{\seccheck{unnumbered}% +\secno=0 \subsecno=0 \subsubsecno=0 +% +% This used to be simply \message{#1}, but TeX fully expands the +% argument to \message. Therefore, if #1 contained @-commands, TeX +% expanded them. For example, in `@unnumbered The @cite{Book}', TeX +% expanded @cite (which turns out to cause errors because \cite is meant +% to be executed, not expanded). +% +% Anyway, we don't want the fully-expanded definition of @cite to appear +% as a result of the \message, we just want `@cite' itself. We use +% \the<toks register> to achieve this: TeX expands \the<toks> only once, +% simply yielding the contents of the <toks register>. +\toks0 = {#1}\message{(\the\toks0)}% +% +\unnumbchapmacro {#1}% +\gdef\thischapter{#1}\gdef\thissection{#1}% +{\chapternofonts% +\edef\temp{{\realbackslash unnumbchapentry {#1}{\noexpand\folio}}}% +\escapechar=`\\% +\write \contentsfile \temp % +\unnumbnoderef % +\global\let\section = \unnumberedsec +\global\let\subsection = \unnumberedsubsec +\global\let\subsubsection = \unnumberedsubsubsec +}} + +\outer\def\numberedsec{\parsearg\secyyy} +\def\secyyy #1{\numhead1{#1}} % normally calls seczzz +\def\seczzz #1{\seccheck{section}% +\subsecno=0 \subsubsecno=0 \global\advance \secno by 1 % +\gdef\thissection{#1}\secheading {#1}{\the\chapno}{\the\secno}% +{\chapternofonts% +\edef\temp{{\realbackslash secentry % +{#1}{\the\chapno}{\the\secno}{\noexpand\folio}}}% +\escapechar=`\\% +\write \contentsfile \temp % +\donoderef % +\penalty 10000 % +}} + +\outer\def\appendixsection{\parsearg\appendixsecyyy} +\outer\def\appendixsec{\parsearg\appendixsecyyy} +\def\appendixsecyyy #1{\apphead1{#1}} % normally calls appendixsectionzzz +\def\appendixsectionzzz #1{\seccheck{appendixsection}% +\subsecno=0 \subsubsecno=0 \global\advance \secno by 1 % +\gdef\thissection{#1}\secheading {#1}{\appendixletter}{\the\secno}% +{\chapternofonts% +\edef\temp{{\realbackslash secentry % +{#1}{\appendixletter}{\the\secno}{\noexpand\folio}}}% +\escapechar=`\\% +\write \contentsfile \temp % +\appendixnoderef % +\penalty 10000 % +}} + +\outer\def\unnumberedsec{\parsearg\unnumberedsecyyy} +\def\unnumberedsecyyy #1{\unnmhead1{#1}} % normally calls unnumberedseczzz +\def\unnumberedseczzz #1{\seccheck{unnumberedsec}% +\plainsecheading {#1}\gdef\thissection{#1}% +{\chapternofonts% +\edef\temp{{\realbackslash unnumbsecentry{#1}{\noexpand\folio}}}% +\escapechar=`\\% +\write \contentsfile \temp % +\unnumbnoderef % +\penalty 10000 % +}} + +\outer\def\numberedsubsec{\parsearg\numberedsubsecyyy} +\def\numberedsubsecyyy #1{\numhead2{#1}} % normally calls numberedsubseczzz +\def\numberedsubseczzz #1{\seccheck{subsection}% +\gdef\thissection{#1}\subsubsecno=0 \global\advance \subsecno by 1 % +\subsecheading {#1}{\the\chapno}{\the\secno}{\the\subsecno}% +{\chapternofonts% +\edef\temp{{\realbackslash subsecentry % +{#1}{\the\chapno}{\the\secno}{\the\subsecno}{\noexpand\folio}}}% +\escapechar=`\\% +\write \contentsfile \temp % +\donoderef % +\penalty 10000 % +}} + +\outer\def\appendixsubsec{\parsearg\appendixsubsecyyy} +\def\appendixsubsecyyy #1{\apphead2{#1}} % normally calls appendixsubseczzz +\def\appendixsubseczzz #1{\seccheck{appendixsubsec}% +\gdef\thissection{#1}\subsubsecno=0 \global\advance \subsecno by 1 % +\subsecheading {#1}{\appendixletter}{\the\secno}{\the\subsecno}% +{\chapternofonts% +\edef\temp{{\realbackslash subsecentry % +{#1}{\appendixletter}{\the\secno}{\the\subsecno}{\noexpand\folio}}}% +\escapechar=`\\% +\write \contentsfile \temp % +\appendixnoderef % +\penalty 10000 % +}} + +\outer\def\unnumberedsubsec{\parsearg\unnumberedsubsecyyy} +\def\unnumberedsubsecyyy #1{\unnmhead2{#1}} %normally calls unnumberedsubseczzz +\def\unnumberedsubseczzz #1{\seccheck{unnumberedsubsec}% +\plainsecheading {#1}\gdef\thissection{#1}% +{\chapternofonts% +\edef\temp{{\realbackslash unnumbsubsecentry{#1}{\noexpand\folio}}}% +\escapechar=`\\% +\write \contentsfile \temp % +\unnumbnoderef % +\penalty 10000 % +}} + +\outer\def\numberedsubsubsec{\parsearg\numberedsubsubsecyyy} +\def\numberedsubsubsecyyy #1{\numhead3{#1}} % normally numberedsubsubseczzz +\def\numberedsubsubseczzz #1{\seccheck{subsubsection}% +\gdef\thissection{#1}\global\advance \subsubsecno by 1 % +\subsubsecheading {#1} + {\the\chapno}{\the\secno}{\the\subsecno}{\the\subsubsecno}% +{\chapternofonts% +\edef\temp{{\realbackslash subsubsecentry % + {#1} + {\the\chapno}{\the\secno}{\the\subsecno}{\the\subsubsecno} + {\noexpand\folio}}}% +\escapechar=`\\% +\write \contentsfile \temp % +\donoderef % +\penalty 10000 % +}} + +\outer\def\appendixsubsubsec{\parsearg\appendixsubsubsecyyy} +\def\appendixsubsubsecyyy #1{\apphead3{#1}} % normally appendixsubsubseczzz +\def\appendixsubsubseczzz #1{\seccheck{appendixsubsubsec}% +\gdef\thissection{#1}\global\advance \subsubsecno by 1 % +\subsubsecheading {#1} + {\appendixletter}{\the\secno}{\the\subsecno}{\the\subsubsecno}% +{\chapternofonts% +\edef\temp{{\realbackslash subsubsecentry{#1}% + {\appendixletter} + {\the\secno}{\the\subsecno}{\the\subsubsecno}{\noexpand\folio}}}% +\escapechar=`\\% +\write \contentsfile \temp % +\appendixnoderef % +\penalty 10000 % +}} + +\outer\def\unnumberedsubsubsec{\parsearg\unnumberedsubsubsecyyy} +\def\unnumberedsubsubsecyyy #1{\unnmhead3{#1}} %normally unnumberedsubsubseczzz +\def\unnumberedsubsubseczzz #1{\seccheck{unnumberedsubsubsec}% +\plainsecheading {#1}\gdef\thissection{#1}% +{\chapternofonts% +\edef\temp{{\realbackslash unnumbsubsubsecentry{#1}{\noexpand\folio}}}% +\escapechar=`\\% +\write \contentsfile \temp % +\unnumbnoderef % +\penalty 10000 % +}} + +% These are variants which are not "outer", so they can appear in @ifinfo. +% Actually, they should now be obsolete; ordinary section commands should work. +\def\infotop{\parsearg\unnumberedzzz} +\def\infounnumbered{\parsearg\unnumberedzzz} +\def\infounnumberedsec{\parsearg\unnumberedseczzz} +\def\infounnumberedsubsec{\parsearg\unnumberedsubseczzz} +\def\infounnumberedsubsubsec{\parsearg\unnumberedsubsubseczzz} + +\def\infoappendix{\parsearg\appendixzzz} +\def\infoappendixsec{\parsearg\appendixseczzz} +\def\infoappendixsubsec{\parsearg\appendixsubseczzz} +\def\infoappendixsubsubsec{\parsearg\appendixsubsubseczzz} + +\def\infochapter{\parsearg\chapterzzz} +\def\infosection{\parsearg\sectionzzz} +\def\infosubsection{\parsearg\subsectionzzz} +\def\infosubsubsection{\parsearg\subsubsectionzzz} + +% These macros control what the section commands do, according +% to what kind of chapter we are in (ordinary, appendix, or unnumbered). +% Define them by default for a numbered chapter. +\global\let\section = \numberedsec +\global\let\subsection = \numberedsubsec +\global\let\subsubsection = \numberedsubsubsec + +% Define @majorheading, @heading and @subheading + +% NOTE on use of \vbox for chapter headings, section headings, and +% such: +% 1) We use \vbox rather than the earlier \line to permit +% overlong headings to fold. +% 2) \hyphenpenalty is set to 10000 because hyphenation in a +% heading is obnoxious; this forbids it. +% 3) Likewise, headings look best if no \parindent is used, and +% if justification is not attempted. Hence \raggedright. + + +\def\majorheading{\parsearg\majorheadingzzz} +\def\majorheadingzzz #1{% +{\advance\chapheadingskip by 10pt \chapbreak }% +{\chapfonts \vbox{\hyphenpenalty=10000\tolerance=5000 + \parindent=0pt\raggedright + \rm #1\hfill}}\bigskip \par\penalty 200} + +\def\chapheading{\parsearg\chapheadingzzz} +\def\chapheadingzzz #1{\chapbreak % +{\chapfonts \vbox{\hyphenpenalty=10000\tolerance=5000 + \parindent=0pt\raggedright + \rm #1\hfill}}\bigskip \par\penalty 200} + +\def\heading{\parsearg\secheadingi} + +\def\subheading{\parsearg\subsecheadingi} + +\def\subsubheading{\parsearg\subsubsecheadingi} + +% These macros generate a chapter, section, etc. heading only +% (including whitespace, linebreaking, etc. around it), +% given all the information in convenient, parsed form. + +%%% Args are the skip and penalty (usually negative) +\def\dobreak#1#2{\par\ifdim\lastskip<#1\removelastskip\penalty#2\vskip#1\fi} + +\def\setchapterstyle #1 {\csname CHAPF#1\endcsname} + +%%% Define plain chapter starts, and page on/off switching for it +% Parameter controlling skip before chapter headings (if needed) + +\newskip \chapheadingskip \chapheadingskip = 30pt plus 8pt minus 4pt + +\def\chapbreak{\dobreak \chapheadingskip {-4000}} +\def\chappager{\par\vfill\supereject} +\def\chapoddpage{\chappager \ifodd\pageno \else \hbox to 0pt{} \chappager\fi} + +\def\setchapternewpage #1 {\csname CHAPPAG#1\endcsname} + +\def\CHAPPAGoff{ +\global\let\pchapsepmacro=\chapbreak +\global\let\pagealignmacro=\chappager} + +\def\CHAPPAGon{ +\global\let\pchapsepmacro=\chappager +\global\let\pagealignmacro=\chappager +\global\def\HEADINGSon{\HEADINGSsingle}} + +\def\CHAPPAGodd{ +\global\let\pchapsepmacro=\chapoddpage +\global\let\pagealignmacro=\chapoddpage +\global\def\HEADINGSon{\HEADINGSdouble}} + +\CHAPPAGon + +\def\CHAPFplain{ +\global\let\chapmacro=\chfplain +\global\let\unnumbchapmacro=\unnchfplain +\global\let\centerchapmacro=\centerchfplain} + +\def\chfplain #1#2{% + \pchapsepmacro + {% + \chapfonts \vbox{\hyphenpenalty=10000\tolerance=5000 + \parindent=0pt\raggedright + \rm #2\enspace #1}% + }% + \bigskip + \penalty5000 +} + +\def\unnchfplain #1{% +\pchapsepmacro % +{\chapfonts \vbox{\hyphenpenalty=10000\tolerance=5000 + \parindent=0pt\raggedright + \rm #1\hfill}}\bigskip \par\penalty 10000 % +} + +\def\centerchfplain #1{% +\pchapsepmacro % +{\chapfonts \vbox{\hyphenpenalty=10000\tolerance=5000 + \parindent=0pt + {\rm #1}\hfill}}\bigskip \par\penalty 10000 % +} + +\CHAPFplain % The default + +\def\unnchfopen #1{% +\chapoddpage {\chapfonts \vbox{\hyphenpenalty=10000\tolerance=5000 + \parindent=0pt\raggedright + \rm #1\hfill}}\bigskip \par\penalty 10000 % +} + +\def\chfopen #1#2{\chapoddpage {\chapfonts +\vbox to 3in{\vfil \hbox to\hsize{\hfil #2} \hbox to\hsize{\hfil #1} \vfil}}% +\par\penalty 5000 % +} + +\def\centerchfopen #1{% +\chapoddpage {\chapfonts \vbox{\hyphenpenalty=10000\tolerance=5000 + \parindent=0pt + \hfill {\rm #1}\hfill}}\bigskip \par\penalty 10000 % +} + +\def\CHAPFopen{ +\global\let\chapmacro=\chfopen +\global\let\unnumbchapmacro=\unnchfopen +\global\let\centerchapmacro=\centerchfopen} + +% Parameter controlling skip before section headings. + +\newskip \subsecheadingskip \subsecheadingskip = 17pt plus 8pt minus 4pt +\def\subsecheadingbreak{\dobreak \subsecheadingskip {-500}} + +\newskip \secheadingskip \secheadingskip = 21pt plus 8pt minus 4pt +\def\secheadingbreak{\dobreak \secheadingskip {-1000}} + +% @paragraphindent is defined for the Info formatting commands only. +\let\paragraphindent=\comment + +% Section fonts are the base font at magstep2, which produces +% a size a bit more than 14 points in the default situation. + +\def\secheading #1#2#3{\secheadingi {#2.#3\enspace #1}} +\def\plainsecheading #1{\secheadingi {#1}} +\def\secheadingi #1{{\advance \secheadingskip by \parskip % +\secheadingbreak}% +{\secfonts \vbox{\hyphenpenalty=10000\tolerance=5000 + \parindent=0pt\raggedright + \rm #1\hfill}}% +\ifdim \parskip<10pt \kern 10pt\kern -\parskip\fi \penalty 10000 } + + +% Subsection fonts are the base font at magstep1, +% which produces a size of 12 points. + +\def\subsecheading #1#2#3#4{\subsecheadingi {#2.#3.#4\enspace #1}} +\def\subsecheadingi #1{{\advance \subsecheadingskip by \parskip % +\subsecheadingbreak}% +{\subsecfonts \vbox{\hyphenpenalty=10000\tolerance=5000 + \parindent=0pt\raggedright + \rm #1\hfill}}% +\ifdim \parskip<10pt \kern 10pt\kern -\parskip\fi \penalty 10000 } + +\def\subsubsecfonts{\subsecfonts} % Maybe this should change: + % Perhaps make sssec fonts scaled + % magstep half +\def\subsubsecheading #1#2#3#4#5{\subsubsecheadingi {#2.#3.#4.#5\enspace #1}} +\def\subsubsecheadingi #1{{\advance \subsecheadingskip by \parskip % +\subsecheadingbreak}% +{\subsubsecfonts \vbox{\hyphenpenalty=10000\tolerance=5000 + \parindent=0pt\raggedright + \rm #1\hfill}}% +\ifdim \parskip<10pt \kern 10pt\kern -\parskip\fi \penalty 10000} + + +\message{toc printing,} + +% Finish up the main text and prepare to read what we've written +% to \contentsfile. + +\newskip\contentsrightmargin \contentsrightmargin=1in +\def\startcontents#1{% + \pagealignmacro + \immediate\closeout \contentsfile + \ifnum \pageno>0 + \pageno = -1 % Request roman numbered pages. + \fi + % Don't need to put `Contents' or `Short Contents' in the headline. + % It is abundantly clear what they are. + \unnumbchapmacro{#1}\def\thischapter{}% + \begingroup % Set up to handle contents files properly. + \catcode`\\=0 \catcode`\{=1 \catcode`\}=2 \catcode`\@=11 + \catcode`\^=7 % to see ^^e4 as \"a etc. juha@piuha.ydi.vtt.fi + \raggedbottom % Worry more about breakpoints than the bottom. + \advance\hsize by -\contentsrightmargin % Don't use the full line length. +} + + +% Normal (long) toc. +\outer\def\contents{% + \startcontents{\putwordTableofContents}% + \input \jobname.toc + \endgroup + \vfill \eject +} + +% And just the chapters. +\outer\def\summarycontents{% + \startcontents{\putwordShortContents}% + % + \let\chapentry = \shortchapentry + \let\unnumbchapentry = \shortunnumberedentry + % We want a true roman here for the page numbers. + \secfonts + \let\rm=\shortcontrm \let\bf=\shortcontbf \let\sl=\shortcontsl + \rm + \advance\baselineskip by 1pt % Open it up a little. + \def\secentry ##1##2##3##4{} + \def\unnumbsecentry ##1##2{} + \def\subsecentry ##1##2##3##4##5{} + \def\unnumbsubsecentry ##1##2{} + \def\subsubsecentry ##1##2##3##4##5##6{} + \def\unnumbsubsubsecentry ##1##2{} + \input \jobname.toc + \endgroup + \vfill \eject +} +\let\shortcontents = \summarycontents + +% These macros generate individual entries in the table of contents. +% The first argument is the chapter or section name. +% The last argument is the page number. +% The arguments in between are the chapter number, section number, ... + +% Chapter-level things, for both the long and short contents. +\def\chapentry#1#2#3{\dochapentry{#2\labelspace#1}{#3}} + +% See comments in \dochapentry re vbox and related settings +\def\shortchapentry#1#2#3{% + \tocentry{\shortchaplabel{#2}\labelspace #1}{\doshortpageno{#3}}% +} + +% Typeset the label for a chapter or appendix for the short contents. +% The arg is, e.g. `Appendix A' for an appendix, or `3' for a chapter. +% We could simplify the code here by writing out an \appendixentry +% command in the toc file for appendices, instead of using \chapentry +% for both, but it doesn't seem worth it. +\setbox0 = \hbox{\shortcontrm \putwordAppendix } +\newdimen\shortappendixwidth \shortappendixwidth = \wd0 + +\def\shortchaplabel#1{% + % We typeset #1 in a box of constant width, regardless of the text of + % #1, so the chapter titles will come out aligned. + \setbox0 = \hbox{#1}% + \dimen0 = \ifdim\wd0 > \shortappendixwidth \shortappendixwidth \else 0pt \fi + % + % This space should be plenty, since a single number is .5em, and the + % widest letter (M) is 1em, at least in the Computer Modern fonts. + % (This space doesn't include the extra space that gets added after + % the label; that gets put in in \shortchapentry above.) + \advance\dimen0 by 1.1em + \hbox to \dimen0{#1\hfil}% +} + +\def\unnumbchapentry#1#2{\dochapentry{#1}{#2}} +\def\shortunnumberedentry#1#2{\tocentry{#1}{\doshortpageno{#2}}} + +% Sections. +\def\secentry#1#2#3#4{\dosecentry{#2.#3\labelspace#1}{#4}} +\def\unnumbsecentry#1#2{\dosecentry{#1}{#2}} + +% Subsections. +\def\subsecentry#1#2#3#4#5{\dosubsecentry{#2.#3.#4\labelspace#1}{#5}} +\def\unnumbsubsecentry#1#2{\dosubsecentry{#1}{#2}} + +% And subsubsections. +\def\subsubsecentry#1#2#3#4#5#6{% + \dosubsubsecentry{#2.#3.#4.#5\labelspace#1}{#6}} +\def\unnumbsubsubsecentry#1#2{\dosubsubsecentry{#1}{#2}} + + +% This parameter controls the indentation of the various levels. +\newdimen\tocindent \tocindent = 3pc + +% Now for the actual typesetting. In all these, #1 is the text and #2 is the +% page number. +% +% If the toc has to be broken over pages, we would want to be at chapters +% if at all possible; hence the \penalty. +\def\dochapentry#1#2{% + \penalty-300 \vskip\baselineskip + \begingroup + \chapentryfonts + \tocentry{#1}{\dopageno{#2}}% + \endgroup + \nobreak\vskip .25\baselineskip +} + +\def\dosecentry#1#2{\begingroup + \secentryfonts \leftskip=\tocindent + \tocentry{#1}{\dopageno{#2}}% +\endgroup} + +\def\dosubsecentry#1#2{\begingroup + \subsecentryfonts \leftskip=2\tocindent + \tocentry{#1}{\dopageno{#2}}% +\endgroup} + +\def\dosubsubsecentry#1#2{\begingroup + \subsubsecentryfonts \leftskip=3\tocindent + \tocentry{#1}{\dopageno{#2}}% +\endgroup} + +% Final typesetting of a toc entry; we use the same \entry macro as for +% the index entries, but we want to suppress hyphenation here. (We +% can't do that in the \entry macro, since index entries might consist +% of hyphenated-identifiers-that-do-not-fit-on-a-line-and-nothing-else.) +% +% \turnoffactive is for the sake of @" used for umlauts. +\def\tocentry#1#2{\begingroup + \hyphenpenalty = 10000 + \entry{\turnoffactive #1}{\turnoffactive #2}% +\endgroup} + +% Space between chapter (or whatever) number and the title. +\def\labelspace{\hskip1em \relax} + +\def\dopageno#1{{\rm #1}} +\def\doshortpageno#1{{\rm #1}} + +\def\chapentryfonts{\secfonts \rm} +\def\secentryfonts{\textfonts} +\let\subsecentryfonts = \textfonts +\let\subsubsecentryfonts = \textfonts + + +\message{environments,} + +% Since these characters are used in examples, it should be an even number of +% \tt widths. Each \tt character is 1en, so two makes it 1em. +% Furthermore, these definitions must come after we define our fonts. +\newbox\dblarrowbox \newbox\longdblarrowbox +\newbox\pushcharbox \newbox\bullbox +\newbox\equivbox \newbox\errorbox + +\let\ptexequiv = \equiv + +%{\tentt +%\global\setbox\dblarrowbox = \hbox to 1em{\hfil$\Rightarrow$\hfil} +%\global\setbox\longdblarrowbox = \hbox to 1em{\hfil$\mapsto$\hfil} +%\global\setbox\pushcharbox = \hbox to 1em{\hfil$\dashv$\hfil} +%\global\setbox\equivbox = \hbox to 1em{\hfil$\ptexequiv$\hfil} +% Adapted from the manmac format (p.420 of TeXbook) +%\global\setbox\bullbox = \hbox to 1em{\kern.15em\vrule height .75ex width .85ex +% depth .1ex\hfil} +%} + +\def\point{$\star$} + +\def\result{\leavevmode\raise.15ex\hbox to 1em{\hfil$\Rightarrow$\hfil}} +\def\expansion{\leavevmode\raise.1ex\hbox to 1em{\hfil$\mapsto$\hfil}} +\def\print{\leavevmode\lower.1ex\hbox to 1em{\hfil$\dashv$\hfil}} + +\def\equiv{\leavevmode\lower.1ex\hbox to 1em{\hfil$\ptexequiv$\hfil}} + +% Adapted from the TeXbook's \boxit. +{\tentt \global\dimen0 = 3em}% Width of the box. +\dimen2 = .55pt % Thickness of rules +% The text. (`r' is open on the right, `e' somewhat less so on the left.) +\setbox0 = \hbox{\kern-.75pt \tensf error\kern-1.5pt} + +\global\setbox\errorbox=\hbox to \dimen0{\hfil + \hsize = \dimen0 \advance\hsize by -5.8pt % Space to left+right. + \advance\hsize by -2\dimen2 % Rules. + \vbox{ + \hrule height\dimen2 + \hbox{\vrule width\dimen2 \kern3pt % Space to left of text. + \vtop{\kern2.4pt \box0 \kern2.4pt}% Space above/below. + \kern3pt\vrule width\dimen2}% Space to right. + \hrule height\dimen2} + \hfil} + +% The @error{} command. +\def\error{\leavevmode\lower.7ex\copy\errorbox} + +% @tex ... @end tex escapes into raw Tex temporarily. +% One exception: @ is still an escape character, so that @end tex works. +% But \@ or @@ will get a plain tex @ character. + +\def\tex{\begingroup +\catcode `\\=0 \catcode `\{=1 \catcode `\}=2 +\catcode `\$=3 \catcode `\&=4 \catcode `\#=6 +\catcode `\^=7 \catcode `\_=8 \catcode `\~=13 \let~=\tie +\catcode `\%=14 +\catcode 43=12 +\catcode`\"=12 +\catcode`\==12 +\catcode`\|=12 +\catcode`\<=12 +\catcode`\>=12 +\escapechar=`\\ +% +\let\~=\ptextilde +\let\{=\ptexlbrace +\let\}=\ptexrbrace +\let\.=\ptexdot +\let\*=\ptexstar +\let\dots=\ptexdots +\def\endldots{\mathinner{\ldots\ldots\ldots\ldots}} +\def\enddots{\relax\ifmmode\endldots\else$\mathsurround=0pt \endldots\,$\fi} +\def\@{@}% +\let\bullet=\ptexbullet +\let\b=\ptexb \let\c=\ptexc \let\i=\ptexi \let\t=\ptext \let\l=\ptexl +\let\L=\ptexL +% +\let\Etex=\endgroup} + +% Define @lisp ... @endlisp. +% @lisp does a \begingroup so it can rebind things, +% including the definition of @endlisp (which normally is erroneous). + +% Amount to narrow the margins by for @lisp. +\newskip\lispnarrowing \lispnarrowing=0.4in + +% This is the definition that ^^M gets inside @lisp, @example, and other +% such environments. \null is better than a space, since it doesn't +% have any width. +\def\lisppar{\null\endgraf} + +% Make each space character in the input produce a normal interword +% space in the output. Don't allow a line break at this space, as this +% is used only in environments like @example, where each line of input +% should produce a line of output anyway. +% +{\obeyspaces % +\gdef\sepspaces{\obeyspaces\let =\tie}} + +% Define \obeyedspace to be our active space, whatever it is. This is +% for use in \parsearg. +{\sepspaces% +\global\let\obeyedspace= } + +% This space is always present above and below environments. +\newskip\envskipamount \envskipamount = 0pt + +% Make spacing and below environment symmetrical. We use \parskip here +% to help in doing that, since in @example-like environments \parskip +% is reset to zero; thus the \afterenvbreak inserts no space -- but the +% start of the next paragraph will insert \parskip +% +\def\aboveenvbreak{{\advance\envskipamount by \parskip +\endgraf \ifdim\lastskip<\envskipamount +\removelastskip \penalty-50 \vskip\envskipamount \fi}} + +\let\afterenvbreak = \aboveenvbreak + +% \nonarrowing is a flag. If "set", @lisp etc don't narrow margins. +\let\nonarrowing=\relax + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% \cartouche: draw rectangle w/rounded corners around argument +\font\circle=lcircle10 +\newdimen\circthick +\newdimen\cartouter\newdimen\cartinner +\newskip\normbskip\newskip\normpskip\newskip\normlskip +\circthick=\fontdimen8\circle +% +\def\ctl{{\circle\char'013\hskip -6pt}}% 6pt from pl file: 1/2charwidth +\def\ctr{{\hskip 6pt\circle\char'010}} +\def\cbl{{\circle\char'012\hskip -6pt}} +\def\cbr{{\hskip 6pt\circle\char'011}} +\def\carttop{\hbox to \cartouter{\hskip\lskip + \ctl\leaders\hrule height\circthick\hfil\ctr + \hskip\rskip}} +\def\cartbot{\hbox to \cartouter{\hskip\lskip + \cbl\leaders\hrule height\circthick\hfil\cbr + \hskip\rskip}} +% +\newskip\lskip\newskip\rskip + +\long\def\cartouche{% +\begingroup + \lskip=\leftskip \rskip=\rightskip + \leftskip=0pt\rightskip=0pt %we want these *outside*. + \cartinner=\hsize \advance\cartinner by-\lskip + \advance\cartinner by-\rskip + \cartouter=\hsize + \advance\cartouter by 18pt % allow for 3pt kerns on either +% side, and for 6pt waste from +% each corner char + \normbskip=\baselineskip \normpskip=\parskip \normlskip=\lineskip + % Flag to tell @lisp, etc., not to narrow margin. + \let\nonarrowing=\comment + \vbox\bgroup + \baselineskip=0pt\parskip=0pt\lineskip=0pt + \carttop + \hbox\bgroup + \hskip\lskip + \vrule\kern3pt + \vbox\bgroup + \hsize=\cartinner + \kern3pt + \begingroup + \baselineskip=\normbskip + \lineskip=\normlskip + \parskip=\normpskip + \vskip -\parskip +\def\Ecartouche{% + \endgroup + \kern3pt + \egroup + \kern3pt\vrule + \hskip\rskip + \egroup + \cartbot + \egroup +\endgroup +}} + + +% This macro is called at the beginning of all the @example variants, +% inside a group. +\def\nonfillstart{% + \aboveenvbreak + \inENV % This group ends at the end of the body + \hfuzz = 12pt % Don't be fussy + \sepspaces % Make spaces be word-separators rather than space tokens. + \singlespace + \let\par = \lisppar % don't ignore blank lines + \obeylines % each line of input is a line of output + \parskip = 0pt + \parindent = 0pt + \emergencystretch = 0pt % don't try to avoid overfull boxes + % @cartouche defines \nonarrowing to inhibit narrowing + % at next level down. + \ifx\nonarrowing\relax + \advance \leftskip by \lispnarrowing + \exdentamount=\lispnarrowing + \let\exdent=\nofillexdent + \let\nonarrowing=\relax + \fi +} + +% To ending an @example-like environment, we first end the paragraph +% (via \afterenvbreak's vertical glue), and then the group. That way we +% keep the zero \parskip that the environments set -- \parskip glue +% will be inserted at the beginning of the next paragraph in the +% document, after the environment. +% +\def\nonfillfinish{\afterenvbreak\endgroup}% + +% This macro is +\def\lisp{\begingroup + \nonfillstart + \let\Elisp = \nonfillfinish + \tt + \rawbackslash % have \ input char produce \ char from current font + \gobble +} + +% Define the \E... control sequence only if we are inside the +% environment, so the error checking in \end will work. +% +% We must call \lisp last in the definition, since it reads the +% return following the @example (or whatever) command. +% +\def\example{\begingroup \def\Eexample{\nonfillfinish\endgroup}\lisp} +\def\smallexample{\begingroup \def\Esmallexample{\nonfillfinish\endgroup}\lisp} +\def\smalllisp{\begingroup \def\Esmalllisp{\nonfillfinish\endgroup}\lisp} + +% @smallexample and @smalllisp. This is not used unless the @smallbook +% command is given. Originally contributed by Pavel@xerox. +% +\def\smalllispx{\begingroup + \nonfillstart + \let\Esmalllisp = \nonfillfinish + \let\Esmallexample = \nonfillfinish + % + % Smaller interline space and fonts for small examples. + \setleading{10pt}% + \indexfonts \tt + \rawbackslash % make \ output the \ character from the current font (tt) + \gobble +} + +% This is @display; same as @lisp except use roman font. +% +\def\display{\begingroup + \nonfillstart + \let\Edisplay = \nonfillfinish + \gobble +} + +% This is @format; same as @display except don't narrow margins. +% +\def\format{\begingroup + \let\nonarrowing = t + \nonfillstart + \let\Eformat = \nonfillfinish + \gobble +} + +% @flushleft (same as @format) and @flushright. +% +\def\flushleft{\begingroup + \let\nonarrowing = t + \nonfillstart + \let\Eflushleft = \nonfillfinish + \gobble +} +\def\flushright{\begingroup + \let\nonarrowing = t + \nonfillstart + \let\Eflushright = \nonfillfinish + \advance\leftskip by 0pt plus 1fill + \gobble} + +% @quotation does normal linebreaking (hence we can't use \nonfillstart) +% and narrows the margins. +% +\def\quotation{% + \begingroup\inENV %This group ends at the end of the @quotation body + {\parskip=0pt \aboveenvbreak}% because \aboveenvbreak inserts \parskip + \singlespace + \parindent=0pt + % We have retained a nonzero parskip for the environment, since we're + % doing normal filling. So to avoid extra space below the environment... + \def\Equotation{\parskip = 0pt \nonfillfinish}% + % + % @cartouche defines \nonarrowing to inhibit narrowing at next level down. + \ifx\nonarrowing\relax + \advance\leftskip by \lispnarrowing + \advance\rightskip by \lispnarrowing + \exdentamount = \lispnarrowing + \let\nonarrowing = \relax + \fi +} + +\message{defuns,} +% Define formatter for defuns +% First, allow user to change definition object font (\df) internally +\def\setdeffont #1 {\csname DEF#1\endcsname} + +\newskip\defbodyindent \defbodyindent=.4in +\newskip\defargsindent \defargsindent=50pt +\newskip\deftypemargin \deftypemargin=12pt +\newskip\deflastargmargin \deflastargmargin=18pt + +\newcount\parencount +% define \functionparens, which makes ( and ) and & do special things. +% \functionparens affects the group it is contained in. +\def\activeparens{% +\catcode`\(=\active \catcode`\)=\active \catcode`\&=\active +\catcode`\[=\active \catcode`\]=\active} + +% Make control sequences which act like normal parenthesis chars. +\let\lparen = ( \let\rparen = ) + +{\activeparens % Now, smart parens don't turn on until &foo (see \amprm) + +% Be sure that we always have a definition for `(', etc. For example, +% if the fn name has parens in it, \boldbrax will not be in effect yet, +% so TeX would otherwise complain about undefined control sequence. +\global\let(=\lparen \global\let)=\rparen +\global\let[=\lbrack \global\let]=\rbrack + +\gdef\functionparens{\boldbrax\let&=\amprm\parencount=0 } +\gdef\boldbrax{\let(=\opnr\let)=\clnr\let[=\lbrb\let]=\rbrb} +% This is used to turn on special parens +% but make & act ordinary (given that it's active). +\gdef\boldbraxnoamp{\let(=\opnr\let)=\clnr\let[=\lbrb\let]=\rbrb\let&=\ampnr} + +% Definitions of (, ) and & used in args for functions. +% This is the definition of ( outside of all parentheses. +\gdef\oprm#1 {{\rm\char`\(}#1 \bf \let(=\opnested % +\global\advance\parencount by 1 } +% +% This is the definition of ( when already inside a level of parens. +\gdef\opnested{\char`\(\global\advance\parencount by 1 } +% +\gdef\clrm{% Print a paren in roman if it is taking us back to depth of 0. +% also in that case restore the outer-level definition of (. +\ifnum \parencount=1 {\rm \char `\)}\sl \let(=\oprm \else \char `\) \fi +\global\advance \parencount by -1 } +% If we encounter &foo, then turn on ()-hacking afterwards +\gdef\amprm#1 {{\rm\}\let(=\oprm \let)=\clrm\ } +% +\gdef\normalparens{\boldbrax\let&=\ampnr} +} % End of definition inside \activeparens +%% These parens (in \boldbrax) actually are a little bolder than the +%% contained text. This is especially needed for [ and ] +\def\opnr{{\sf\char`\(}} \def\clnr{{\sf\char`\)}} \def\ampnr{\&} +\def\lbrb{{\bf\char`\[}} \def\rbrb{{\bf\char`\]}} + +% First, defname, which formats the header line itself. +% #1 should be the function name. +% #2 should be the type of definition, such as "Function". + +\def\defname #1#2{% +% Get the values of \leftskip and \rightskip as they were +% outside the @def... +\dimen2=\leftskip +\advance\dimen2 by -\defbodyindent +\dimen3=\rightskip +\advance\dimen3 by -\defbodyindent +\noindent % +\setbox0=\hbox{\hskip \deflastargmargin{\rm #2}\hskip \deftypemargin}% +\dimen0=\hsize \advance \dimen0 by -\wd0 % compute size for first line +\dimen1=\hsize \advance \dimen1 by -\defargsindent %size for continuations +\parshape 2 0in \dimen0 \defargsindent \dimen1 % +% Now output arg 2 ("Function" or some such) +% ending at \deftypemargin from the right margin, +% but stuck inside a box of width 0 so it does not interfere with linebreaking +{% Adjust \hsize to exclude the ambient margins, +% so that \rightline will obey them. +\advance \hsize by -\dimen2 \advance \hsize by -\dimen3 +\rlap{\rightline{{\rm #2}\hskip \deftypemargin}}}% +% Make all lines underfull and no complaints: +\tolerance=10000 \hbadness=10000 +\advance\leftskip by -\defbodyindent +\exdentamount=\defbodyindent +{\df #1}\enskip % Generate function name +} + +% Actually process the body of a definition +% #1 should be the terminating control sequence, such as \Edefun. +% #2 should be the "another name" control sequence, such as \defunx. +% #3 should be the control sequence that actually processes the header, +% such as \defunheader. + +\def\defparsebody #1#2#3{\begingroup\inENV% Environment for definitionbody +\medbreak % +% Define the end token that this defining construct specifies +% so that it will exit this group. +\def#1{\endgraf\endgroup\medbreak}% +\def#2{\begingroup\obeylines\activeparens\spacesplit#3}% +\parindent=0in +\advance\leftskip by \defbodyindent \advance \rightskip by \defbodyindent +\exdentamount=\defbodyindent +\begingroup % +\catcode 61=\active % 61 is `=' +\obeylines\activeparens\spacesplit#3} + +\def\defmethparsebody #1#2#3#4 {\begingroup\inENV % +\medbreak % +% Define the end token that this defining construct specifies +% so that it will exit this group. +\def#1{\endgraf\endgroup\medbreak}% +\def#2##1 {\begingroup\obeylines\activeparens\spacesplit{#3{##1}}}% +\parindent=0in +\advance\leftskip by \defbodyindent \advance \rightskip by \defbodyindent +\exdentamount=\defbodyindent +\begingroup\obeylines\activeparens\spacesplit{#3{#4}}} + +\def\defopparsebody #1#2#3#4#5 {\begingroup\inENV % +\medbreak % +% Define the end token that this defining construct specifies +% so that it will exit this group. +\def#1{\endgraf\endgroup\medbreak}% +\def#2##1 ##2 {\def#4{##1}% +\begingroup\obeylines\activeparens\spacesplit{#3{##2}}}% +\parindent=0in +\advance\leftskip by \defbodyindent \advance \rightskip by \defbodyindent +\exdentamount=\defbodyindent +\begingroup\obeylines\activeparens\spacesplit{#3{#5}}} + +% These parsing functions are similar to the preceding ones +% except that they do not make parens into active characters. +% These are used for "variables" since they have no arguments. + +\def\defvarparsebody #1#2#3{\begingroup\inENV% Environment for definitionbody +\medbreak % +% Define the end token that this defining construct specifies +% so that it will exit this group. +\def#1{\endgraf\endgroup\medbreak}% +\def#2{\begingroup\obeylines\spacesplit#3}% +\parindent=0in +\advance\leftskip by \defbodyindent \advance \rightskip by \defbodyindent +\exdentamount=\defbodyindent +\begingroup % +\catcode 61=\active % +\obeylines\spacesplit#3} + +% This is used for \def{tp,vr}parsebody. It could probably be used for +% some of the others, too, with some judicious conditionals. +% +\def\parsebodycommon#1#2#3{% + \begingroup\inENV % + \medbreak % + % Define the end token that this defining construct specifies + % so that it will exit this group. + \def#1{\endgraf\endgroup\medbreak}% + \def#2##1 {\begingroup\obeylines\spacesplit{#3{##1}}}% + \parindent=0in + \advance\leftskip by \defbodyindent \advance \rightskip by \defbodyindent + \exdentamount=\defbodyindent + \begingroup\obeylines +} + +\def\defvrparsebody#1#2#3#4 {% + \parsebodycommon{#1}{#2}{#3}% + \spacesplit{#3{#4}}% +} + +% This loses on `@deftp {Data Type} {struct termios}' -- it thinks the +% type is just `struct', because we lose the braces in `{struct +% termios}' when \spacesplit reads its undelimited argument. Sigh. +% \let\deftpparsebody=\defvrparsebody +% +% So, to get around this, we put \empty in with the type name. That +% way, TeX won't find exactly `{...}' as an undelimited argument, and +% won't strip off the braces. +% +\def\deftpparsebody #1#2#3#4 {% + \parsebodycommon{#1}{#2}{#3}% + \spacesplit{\parsetpheaderline{#3{#4}}}\empty +} + +% Fine, but then we have to eventually remove the \empty *and* the +% braces (if any). That's what this does, putting the result in \tptemp. +% +\def\removeemptybraces\empty#1\relax{\def\tptemp{#1}}% + +% After \spacesplit has done its work, this is called -- #1 is the final +% thing to call, #2 the type name (which starts with \empty), and #3 +% (which might be empty) the arguments. +% +\def\parsetpheaderline#1#2#3{% + \removeemptybraces#2\relax + #1{\tptemp}{#3}% +}% + +\def\defopvarparsebody #1#2#3#4#5 {\begingroup\inENV % +\medbreak % +% Define the end token that this defining construct specifies +% so that it will exit this group. +\def#1{\endgraf\endgroup\medbreak}% +\def#2##1 ##2 {\def#4{##1}% +\begingroup\obeylines\spacesplit{#3{##2}}}% +\parindent=0in +\advance\leftskip by \defbodyindent \advance \rightskip by \defbodyindent +\exdentamount=\defbodyindent +\begingroup\obeylines\spacesplit{#3{#5}}} + +% Split up #2 at the first space token. +% call #1 with two arguments: +% the first is all of #2 before the space token, +% the second is all of #2 after that space token. +% If #2 contains no space token, all of it is passed as the first arg +% and the second is passed as empty. + +{\obeylines +\gdef\spacesplit#1#2^^M{\endgroup\spacesplitfoo{#1}#2 \relax\spacesplitfoo}% +\long\gdef\spacesplitfoo#1#2 #3#4\spacesplitfoo{% +\ifx\relax #3% +#1{#2}{}\else #1{#2}{#3#4}\fi}} + +% So much for the things common to all kinds of definitions. + +% Define @defun. + +% First, define the processing that is wanted for arguments of \defun +% Use this to expand the args and terminate the paragraph they make up + +\def\defunargs #1{\functionparens \sl +% Expand, preventing hyphenation at `-' chars. +% Note that groups don't affect changes in \hyphenchar. +\hyphenchar\tensl=0 +#1% +\hyphenchar\tensl=45 +\ifnum\parencount=0 \else \errmessage{unbalanced parens in @def arguments}\fi% +\interlinepenalty=10000 +\advance\rightskip by 0pt plus 1fil +\endgraf\penalty 10000\vskip -\parskip\penalty 10000% +} + +\def\deftypefunargs #1{% +% Expand, preventing hyphenation at `-' chars. +% Note that groups don't affect changes in \hyphenchar. +% Use \boldbraxnoamp, not \functionparens, so that & is not special. +\boldbraxnoamp +\tclose{#1}% avoid \code because of side effects on active chars +\interlinepenalty=10000 +\advance\rightskip by 0pt plus 1fil +\endgraf\penalty 10000\vskip -\parskip\penalty 10000% +} + +% Do complete processing of one @defun or @defunx line already parsed. + +% @deffn Command forward-char nchars + +\def\deffn{\defmethparsebody\Edeffn\deffnx\deffnheader} + +\def\deffnheader #1#2#3{\doind {fn}{\code{#2}}% +\begingroup\defname {#2}{#1}\defunargs{#3}\endgroup % +\catcode 61=\other % Turn off change made in \defparsebody +} + +% @defun == @deffn Function + +\def\defun{\defparsebody\Edefun\defunx\defunheader} + +\def\defunheader #1#2{\doind {fn}{\code{#1}}% Make entry in function index +\begingroup\defname {#1}{Function}% +\defunargs {#2}\endgroup % +\catcode 61=\other % Turn off change made in \defparsebody +} + +% @deftypefun int foobar (int @var{foo}, float @var{bar}) + +\def\deftypefun{\defparsebody\Edeftypefun\deftypefunx\deftypefunheader} + +% #1 is the data type. #2 is the name and args. +\def\deftypefunheader #1#2{\deftypefunheaderx{#1}#2 \relax} +% #1 is the data type, #2 the name, #3 the args. +\def\deftypefunheaderx #1#2 #3\relax{% +\doind {fn}{\code{#2}}% Make entry in function index +\begingroup\defname {\defheaderxcond#1\relax$$$#2}{Function}% +\deftypefunargs {#3}\endgroup % +\catcode 61=\other % Turn off change made in \defparsebody +} + +% @deftypefn {Library Function} int foobar (int @var{foo}, float @var{bar}) + +\def\deftypefn{\defmethparsebody\Edeftypefn\deftypefnx\deftypefnheader} + +% \defheaderxcond#1\relax$$$ +% puts #1 in @code, followed by a space, but does nothing if #1 is null. +\def\defheaderxcond#1#2$$${\ifx#1\relax\else\code{#1#2} \fi} + +% #1 is the classification. #2 is the data type. #3 is the name and args. +\def\deftypefnheader #1#2#3{\deftypefnheaderx{#1}{#2}#3 \relax} +% #1 is the classification, #2 the data type, #3 the name, #4 the args. +\def\deftypefnheaderx #1#2#3 #4\relax{% +\doind {fn}{\code{#3}}% Make entry in function index +\begingroup +\normalparens % notably, turn off `&' magic, which prevents +% at least some C++ text from working +\defname {\defheaderxcond#2\relax$$$#3}{#1}% +\deftypefunargs {#4}\endgroup % +\catcode 61=\other % Turn off change made in \defparsebody +} + +% @defmac == @deffn Macro + +\def\defmac{\defparsebody\Edefmac\defmacx\defmacheader} + +\def\defmacheader #1#2{\doind {fn}{\code{#1}}% Make entry in function index +\begingroup\defname {#1}{Macro}% +\defunargs {#2}\endgroup % +\catcode 61=\other % Turn off change made in \defparsebody +} + +% @defspec == @deffn Special Form + +\def\defspec{\defparsebody\Edefspec\defspecx\defspecheader} + +\def\defspecheader #1#2{\doind {fn}{\code{#1}}% Make entry in function index +\begingroup\defname {#1}{Special Form}% +\defunargs {#2}\endgroup % +\catcode 61=\other % Turn off change made in \defparsebody +} + +% This definition is run if you use @defunx +% anywhere other than immediately after a @defun or @defunx. + +\def\deffnx #1 {\errmessage{@deffnx in invalid context}} +\def\defunx #1 {\errmessage{@defunx in invalid context}} +\def\defmacx #1 {\errmessage{@defmacx in invalid context}} +\def\defspecx #1 {\errmessage{@defspecx in invalid context}} +\def\deftypefnx #1 {\errmessage{@deftypefnx in invalid context}} +\def\deftypeunx #1 {\errmessage{@deftypeunx in invalid context}} + +% @defmethod, and so on + +% @defop {Funny Method} foo-class frobnicate argument + +\def\defop #1 {\def\defoptype{#1}% +\defopparsebody\Edefop\defopx\defopheader\defoptype} + +\def\defopheader #1#2#3{% +\dosubind {fn}{\code{#2}}{on #1}% Make entry in function index +\begingroup\defname {#2}{\defoptype{} on #1}% +\defunargs {#3}\endgroup % +} + +% @defmethod == @defop Method + +\def\defmethod{\defmethparsebody\Edefmethod\defmethodx\defmethodheader} + +\def\defmethodheader #1#2#3{% +\dosubind {fn}{\code{#2}}{on #1}% entry in function index +\begingroup\defname {#2}{Method on #1}% +\defunargs {#3}\endgroup % +} + +% @defcv {Class Option} foo-class foo-flag + +\def\defcv #1 {\def\defcvtype{#1}% +\defopvarparsebody\Edefcv\defcvx\defcvarheader\defcvtype} + +\def\defcvarheader #1#2#3{% +\dosubind {vr}{\code{#2}}{of #1}% Make entry in var index +\begingroup\defname {#2}{\defcvtype{} of #1}% +\defvarargs {#3}\endgroup % +} + +% @defivar == @defcv {Instance Variable} + +\def\defivar{\defvrparsebody\Edefivar\defivarx\defivarheader} + +\def\defivarheader #1#2#3{% +\dosubind {vr}{\code{#2}}{of #1}% Make entry in var index +\begingroup\defname {#2}{Instance Variable of #1}% +\defvarargs {#3}\endgroup % +} + +% These definitions are run if you use @defmethodx, etc., +% anywhere other than immediately after a @defmethod, etc. + +\def\defopx #1 {\errmessage{@defopx in invalid context}} +\def\defmethodx #1 {\errmessage{@defmethodx in invalid context}} +\def\defcvx #1 {\errmessage{@defcvx in invalid context}} +\def\defivarx #1 {\errmessage{@defivarx in invalid context}} + +% Now @defvar + +% First, define the processing that is wanted for arguments of @defvar. +% This is actually simple: just print them in roman. +% This must expand the args and terminate the paragraph they make up +\def\defvarargs #1{\normalparens #1% +\interlinepenalty=10000 +\endgraf\penalty 10000\vskip -\parskip\penalty 10000} + +% @defvr Counter foo-count + +\def\defvr{\defvrparsebody\Edefvr\defvrx\defvrheader} + +\def\defvrheader #1#2#3{\doind {vr}{\code{#2}}% +\begingroup\defname {#2}{#1}\defvarargs{#3}\endgroup} + +% @defvar == @defvr Variable + +\def\defvar{\defvarparsebody\Edefvar\defvarx\defvarheader} + +\def\defvarheader #1#2{\doind {vr}{\code{#1}}% Make entry in var index +\begingroup\defname {#1}{Variable}% +\defvarargs {#2}\endgroup % +} + +% @defopt == @defvr {User Option} + +\def\defopt{\defvarparsebody\Edefopt\defoptx\defoptheader} + +\def\defoptheader #1#2{\doind {vr}{\code{#1}}% Make entry in var index +\begingroup\defname {#1}{User Option}% +\defvarargs {#2}\endgroup % +} + +% @deftypevar int foobar + +\def\deftypevar{\defvarparsebody\Edeftypevar\deftypevarx\deftypevarheader} + +% #1 is the data type. #2 is the name. +\def\deftypevarheader #1#2{% +\doind {vr}{\code{#2}}% Make entry in variables index +\begingroup\defname {\defheaderxcond#1\relax$$$#2}{Variable}% +\interlinepenalty=10000 +\endgraf\penalty 10000\vskip -\parskip\penalty 10000 +\endgroup} + +% @deftypevr {Global Flag} int enable + +\def\deftypevr{\defvrparsebody\Edeftypevr\deftypevrx\deftypevrheader} + +\def\deftypevrheader #1#2#3{\doind {vr}{\code{#3}}% +\begingroup\defname {\defheaderxcond#2\relax$$$#3}{#1} +\interlinepenalty=10000 +\endgraf\penalty 10000\vskip -\parskip\penalty 10000 +\endgroup} + +% This definition is run if you use @defvarx +% anywhere other than immediately after a @defvar or @defvarx. + +\def\defvrx #1 {\errmessage{@defvrx in invalid context}} +\def\defvarx #1 {\errmessage{@defvarx in invalid context}} +\def\defoptx #1 {\errmessage{@defoptx in invalid context}} +\def\deftypevarx #1 {\errmessage{@deftypevarx in invalid context}} +\def\deftypevrx #1 {\errmessage{@deftypevrx in invalid context}} + +% Now define @deftp +% Args are printed in bold, a slight difference from @defvar. + +\def\deftpargs #1{\bf \defvarargs{#1}} + +% @deftp Class window height width ... + +\def\deftp{\deftpparsebody\Edeftp\deftpx\deftpheader} + +\def\deftpheader #1#2#3{\doind {tp}{\code{#2}}% +\begingroup\defname {#2}{#1}\deftpargs{#3}\endgroup} + +% This definition is run if you use @deftpx, etc +% anywhere other than immediately after a @deftp, etc. + +\def\deftpx #1 {\errmessage{@deftpx in invalid context}} + +\message{cross reference,} +% Define cross-reference macros +\newwrite \auxfile + +\newif\ifhavexrefs % True if xref values are known. +\newif\ifwarnedxrefs % True if we warned once that they aren't known. + +% \setref{foo} defines a cross-reference point named foo. + +\def\setref#1{% +\dosetq{#1-title}{Ytitle}% +\dosetq{#1-pg}{Ypagenumber}% +\dosetq{#1-snt}{Ysectionnumberandtype}} + +\def\unnumbsetref#1{% +\dosetq{#1-title}{Ytitle}% +\dosetq{#1-pg}{Ypagenumber}% +\dosetq{#1-snt}{Ynothing}} + +\def\appendixsetref#1{% +\dosetq{#1-title}{Ytitle}% +\dosetq{#1-pg}{Ypagenumber}% +\dosetq{#1-snt}{Yappendixletterandtype}} + +% \xref, \pxref, and \ref generate cross-references to specified points. +% For \xrefX, #1 is the node name, #2 the name of the Info +% cross-reference, #3 the printed node name, #4 the name of the Info +% file, #5 the name of the printed manual. All but the node name can be +% omitted. +% +\def\pxref#1{\putwordsee{} \xrefX[#1,,,,,,,]} +\def\xref#1{\putwordSee{} \xrefX[#1,,,,,,,]} +\def\ref#1{\xrefX[#1,,,,,,,]} +\def\xrefX[#1,#2,#3,#4,#5,#6]{\begingroup + \def\printedmanual{\ignorespaces #5}% + \def\printednodename{\ignorespaces #3}% + \setbox1=\hbox{\printedmanual}% + \setbox0=\hbox{\printednodename}% + \ifdim \wd0 = 0pt + % No printed node name was explicitly given. + \expandafter\ifx\csname SETxref-automatic-section-title\endcsname\relax + % Use the node name inside the square brackets. + \def\printednodename{\ignorespaces #1}% + \else + % Use the actual chapter/section title appear inside + % the square brackets. Use the real section title if we have it. + \ifdim \wd1>0pt% + % It is in another manual, so we don't have it. + \def\printednodename{\ignorespaces #1}% + \else + \ifhavexrefs + % We know the real title if we have the xref values. + \def\printednodename{\refx{#1-title}{}}% + \else + % Otherwise just copy the Info node name. + \def\printednodename{\ignorespaces #1}% + \fi% + \fi + \fi + \fi + % + % If we use \unhbox0 and \unhbox1 to print the node names, TeX does not + % insert empty discretionaries after hyphens, which means that it will + % not find a line break at a hyphen in a node names. Since some manuals + % are best written with fairly long node names, containing hyphens, this + % is a loss. Therefore, we give the text of the node name again, so it + % is as if TeX is seeing it for the first time. + \ifdim \wd1 > 0pt + \putwordsection{} ``\printednodename'' in \cite{\printedmanual}% + \else + % _ (for example) has to be the character _ for the purposes of the + % control sequence corresponding to the node, but it has to expand + % into the usual \leavevmode...\vrule stuff for purposes of + % printing. So we \turnoffactive for the \refx-snt, back on for the + % printing, back off for the \refx-pg. + {\turnoffactive \refx{#1-snt}{}}% + \space [\printednodename],\space + \turnoffactive \putwordpage\tie\refx{#1-pg}{}% + \fi +\endgroup} + +% \dosetq is the interface for calls from other macros + +% Use \turnoffactive so that punctuation chars such as underscore +% work in node names. +\def\dosetq #1#2{{\let\folio=0 \turnoffactive \auxhat% +\edef\next{\write\auxfile{\internalsetq {#1}{#2}}}% +\next}} + +% \internalsetq {foo}{page} expands into +% CHARACTERS 'xrdef {foo}{...expansion of \Ypage...} +% When the aux file is read, ' is the escape character + +\def\internalsetq #1#2{'xrdef {#1}{\csname #2\endcsname}} + +% Things to be expanded by \internalsetq + +\def\Ypagenumber{\folio} + +\def\Ytitle{\thissection} + +\def\Ynothing{} + +\def\Ysectionnumberandtype{% +\ifnum\secno=0 \putwordChapter\xreftie\the\chapno % +\else \ifnum \subsecno=0 \putwordSection\xreftie\the\chapno.\the\secno % +\else \ifnum \subsubsecno=0 % +\putwordSection\xreftie\the\chapno.\the\secno.\the\subsecno % +\else % +\putwordSection\xreftie\the\chapno.\the\secno.\the\subsecno.\the\subsubsecno % +\fi \fi \fi } + +\def\Yappendixletterandtype{% +\ifnum\secno=0 \putwordAppendix\xreftie'char\the\appendixno{}% +\else \ifnum \subsecno=0 \putwordSection\xreftie'char\the\appendixno.\the\secno % +\else \ifnum \subsubsecno=0 % +\putwordSection\xreftie'char\the\appendixno.\the\secno.\the\subsecno % +\else % +\putwordSection\xreftie'char\the\appendixno.\the\secno.\the\subsecno.\the\subsubsecno % +\fi \fi \fi } + +\gdef\xreftie{'tie} + +% Use TeX 3.0's \inputlineno to get the line number, for better error +% messages, but if we're using an old version of TeX, don't do anything. +% +\ifx\inputlineno\thisisundefined + \let\linenumber = \empty % Non-3.0. +\else + \def\linenumber{\the\inputlineno:\space} +\fi + +% Define \refx{NAME}{SUFFIX} to reference a cross-reference string named NAME. +% If its value is nonempty, SUFFIX is output afterward. + +\def\refx#1#2{% + \expandafter\ifx\csname X#1\endcsname\relax + % If not defined, say something at least. + $\langle$un\-de\-fined$\rangle$% + \ifhavexrefs + \message{\linenumber Undefined cross reference `#1'.}% + \else + \ifwarnedxrefs\else + \global\warnedxrefstrue + \message{Cross reference values unknown; you must run TeX again.}% + \fi + \fi + \else + % It's defined, so just use it. + \csname X#1\endcsname + \fi + #2% Output the suffix in any case. +} + +% Read the last existing aux file, if any. No error if none exists. + +% This is the macro invoked by entries in the aux file. +\def\xrdef #1#2{ +{\catcode`\'=\other\expandafter \gdef \csname X#1\endcsname {#2}}} + +\def\readauxfile{% +\begingroup +\catcode `\^^@=\other +\catcode `\=\other +\catcode `\=\other +\catcode `\^^C=\other +\catcode `\^^D=\other +\catcode `\^^E=\other +\catcode `\^^F=\other +\catcode `\^^G=\other +\catcode `\^^H=\other +\catcode `\=\other +\catcode `\^^L=\other +\catcode `\=\other +\catcode `\=\other +\catcode `\=\other +\catcode `\=\other +\catcode `\=\other +\catcode `\=\other +\catcode `\=\other +\catcode `\=\other +\catcode `\=\other +\catcode `\=\other +\catcode `\=\other +\catcode `\=\other +\catcode 26=\other +\catcode `\^^[=\other +\catcode `\^^\=\other +\catcode `\^^]=\other +\catcode `\^^^=\other +\catcode `\^^_=\other +\catcode `\@=\other +\catcode `\^=\other +\catcode `\~=\other +\catcode `\[=\other +\catcode `\]=\other +\catcode`\"=\other +\catcode`\_=\other +\catcode`\|=\other +\catcode`\<=\other +\catcode`\>=\other +\catcode `\$=\other +\catcode `\#=\other +\catcode `\&=\other +% `\+ does not work, so use 43. +\catcode 43=\other +% Make the characters 128-255 be printing characters +{% + \count 1=128 + \def\loop{% + \catcode\count 1=\other + \advance\count 1 by 1 + \ifnum \count 1<256 \loop \fi + }% +}% +% the aux file uses ' as the escape. +% Turn off \ as an escape so we do not lose on +% entries which were dumped with control sequences in their names. +% For example, 'xrdef {$\leq $-fun}{page ...} made by @defun ^^ +% Reference to such entries still does not work the way one would wish, +% but at least they do not bomb out when the aux file is read in. +\catcode `\{=1 \catcode `\}=2 +\catcode `\%=\other +\catcode `\'=0 +\catcode`\^=7 % to make ^^e4 etc usable in xref tags +\catcode `\\=\other +\openin 1 \jobname.aux +\ifeof 1 \else \closein 1 \input \jobname.aux \global\havexrefstrue +\global\warnedobstrue +\fi +% Open the new aux file. Tex will close it automatically at exit. +\openout \auxfile=\jobname.aux +\endgroup} + + +% Footnotes. + +\newcount \footnoteno + +% The trailing space in the following definition for supereject is +% vital for proper filling; pages come out unaligned when you do a +% pagealignmacro call if that space before the closing brace is +% removed. +\def\supereject{\par\penalty -20000\footnoteno =0 } + +% @footnotestyle is meaningful for info output only.. +\let\footnotestyle=\comment + +\let\ptexfootnote=\footnote + +{\catcode `\@=11 +% +% Auto-number footnotes. Otherwise like plain. +\gdef\footnote{% + \global\advance\footnoteno by \@ne + \edef\thisfootno{$^{\the\footnoteno}$}% + % + % In case the footnote comes at the end of a sentence, preserve the + % extra spacing after we do the footnote number. + \let\@sf\empty + \ifhmode\edef\@sf{\spacefactor\the\spacefactor}\/\fi + % + % Remove inadvertent blank space before typesetting the footnote number. + \unskip + \thisfootno\@sf + \footnotezzz +}% + +% Don't bother with the trickery in plain.tex to not require the +% footnote text as a parameter. Our footnotes don't need to be so general. +% +\long\gdef\footnotezzz#1{\insert\footins{% + % We want to typeset this text as a normal paragraph, even if the + % footnote reference occurs in (for example) a display environment. + % So reset some parameters. + \interlinepenalty\interfootnotelinepenalty + \splittopskip\ht\strutbox % top baseline for broken footnotes + \splitmaxdepth\dp\strutbox + \floatingpenalty\@MM + \leftskip\z@skip + \rightskip\z@skip + \spaceskip\z@skip + \xspaceskip\z@skip + \parindent\defaultparindent + % + % Hang the footnote text off the number. + \hang + \textindent{\thisfootno}% + % + % Don't crash into the line above the footnote text. Since this + % expands into a box, it must come within the paragraph, lest it + % provide a place where TeX can split the footnote. + \footstrut + #1\strut}% +} + +}%end \catcode `\@=11 + +% Set the baselineskip to #1, and the lineskip and strut size +% correspondingly. There is no deep meaning behind these magic numbers +% used as factors; they just match (closely enough) what Knuth defined. +% +\def\lineskipfactor{.08333} +\def\strutheightpercent{.70833} +\def\strutdepthpercent {.29167} +% +\def\setleading#1{% + \normalbaselineskip = #1\relax + \normallineskip = \lineskipfactor\normalbaselineskip + \normalbaselines + \setbox\strutbox =\hbox{% + \vrule width0pt height\strutheightpercent\baselineskip + depth \strutdepthpercent \baselineskip + }% +} + +% @| inserts a changebar to the left of the current line. It should +% surround any changed text. This approach does *not* work if the +% change spans more than two lines of output. To handle that, we would +% have adopt a much more difficult approach (putting marks into the main +% vertical list for the beginning and end of each change). +% +\def\|{% + % \vadjust can only be used in horizontal mode. + \leavevmode + % + % Append this vertical mode material after the current line in the output. + \vadjust{% + % We want to insert a rule with the height and depth of the current + % leading; that is exactly what \strutbox is supposed to record. + \vskip-\baselineskip + % + % \vadjust-items are inserted at the left edge of the type. So + % the \llap here moves out into the left-hand margin. + \llap{% + % + % For a thicker or thinner bar, change the `1pt'. + \vrule height\baselineskip width1pt + % + % This is the space between the bar and the text. + \hskip 12pt + }% + }% +} + +% For a final copy, take out the rectangles +% that mark overfull boxes (in case you have decided +% that the text looks ok even though it passes the margin). +% +\def\finalout{\overfullrule=0pt} + + +% End of control word definitions. + +\message{and turning on texinfo input format.} + +\def\openindices{% + \newindex{cp}% + \newcodeindex{fn}% + \newcodeindex{vr}% + \newcodeindex{tp}% + \newcodeindex{ky}% + \newcodeindex{pg}% +} + +% Set some numeric style parameters, for 8.5 x 11 format. + +%\hsize = 6.5in +\newdimen\defaultparindent \defaultparindent = 15pt +\parindent = \defaultparindent +\parskip 18pt plus 1pt +\setleading{15pt} +\advance\topskip by 1.2cm + +% Prevent underfull vbox error messages. +\vbadness=10000 + +% Following George Bush, just get rid of widows and orphans. +\widowpenalty=10000 +\clubpenalty=10000 + +% Use TeX 3.0's \emergencystretch to help line breaking, but if we're +% using an old version of TeX, don't do anything. We want the amount of +% stretch added to depend on the line length, hence the dependence on +% \hsize. This makes it come to about 9pt for the 8.5x11 format. +% +\ifx\emergencystretch\thisisundefined + % Allow us to assign to \emergencystretch anyway. + \def\emergencystretch{\dimen0}% +\else + \emergencystretch = \hsize + \divide\emergencystretch by 45 +\fi + +% Use @smallbook to reset parameters for 7x9.5 format (or else 7x9.25) +\def\smallbook{ + +% These values for secheadingskip and subsecheadingskip are +% experiments. RJC 7 Aug 1992 +\global\secheadingskip = 17pt plus 6pt minus 3pt +\global\subsecheadingskip = 14pt plus 6pt minus 3pt + +\global\lispnarrowing = 0.3in +\setleading{12pt} +\advance\topskip by -1cm +\global\parskip 3pt plus 1pt +\global\hsize = 5in +\global\vsize=7.5in +\global\tolerance=700 +\global\hfuzz=1pt +\global\contentsrightmargin=0pt +\global\deftypemargin=0pt +\global\defbodyindent=.5cm + +\global\pagewidth=\hsize +\global\pageheight=\vsize + +\global\let\smalllisp=\smalllispx +\global\let\smallexample=\smalllispx +\global\def\Esmallexample{\Esmalllisp} +} + +% Use @afourpaper to print on European A4 paper. +\def\afourpaper{ +\global\tolerance=700 +\global\hfuzz=1pt +\setleading{12pt} +\global\parskip 15pt plus 1pt + +\global\vsize= 53\baselineskip +\advance\vsize by \topskip +%\global\hsize= 5.85in % A4 wide 10pt +\global\hsize= 6.5in +\global\outerhsize=\hsize +\global\advance\outerhsize by 0.5in +\global\outervsize=\vsize +\global\advance\outervsize by 0.6in + +\global\pagewidth=\hsize +\global\pageheight=\vsize +} + +% Allow control of the text dimensions. Parameters in order: textheight; +% textwidth; voffset; hoffset; binding offset; topskip. +% All require a dimension; +% header is additional; added length extends the bottom of the page. + +\def\changepagesizes#1#2#3#4#5#6{ + \global\vsize= #1 + \global\topskip= #6 + \advance\vsize by \topskip + \global\voffset= #3 + \global\hsize= #2 + \global\outerhsize=\hsize + \global\advance\outerhsize by 0.5in + \global\outervsize=\vsize + \global\advance\outervsize by 0.6in + \global\pagewidth=\hsize + \global\pageheight=\vsize + \global\normaloffset= #4 + \global\bindingoffset= #5} + +% A specific text layout, 24x15cm overall, intended for A4 paper. Top margin +% 29mm, hence bottom margin 28mm, nominal side margin 3cm. +\def\afourlatex + {\global\tolerance=700 + \global\hfuzz=1pt + \setleading{12pt} + \global\parskip 15pt plus 1pt + \advance\baselineskip by 1.6pt + \changepagesizes{237mm}{150mm}{3.6mm}{3.6mm}{3mm}{7mm} + } + +% Use @afourwide to print on European A4 paper in wide format. +\def\afourwide{\afourpaper +\changepagesizes{9.5in}{6.5in}{\hoffset}{\normaloffset}{\bindingoffset}{7mm}} + +% Define macros to output various characters with catcode for normal text. +\catcode`\"=\other +\catcode`\~=\other +\catcode`\^=\other +\catcode`\_=\other +\catcode`\|=\other +\catcode`\<=\other +\catcode`\>=\other +\catcode`\+=\other +\def\normaldoublequote{"} +\def\normaltilde{~} +\def\normalcaret{^} +\def\normalunderscore{_} +\def\normalverticalbar{|} +\def\normalless{<} +\def\normalgreater{>} +\def\normalplus{+} + +% This macro is used to make a character print one way in ttfont +% where it can probably just be output, and another way in other fonts, +% where something hairier probably needs to be done. +% +% #1 is what to print if we are indeed using \tt; #2 is what to print +% otherwise. Since all the Computer Modern typewriter fonts have zero +% interword stretch (and shrink), and it is reasonable to expect all +% typewriter fonts to have this, we can check that font parameter. +% +\def\ifusingtt#1#2{\ifdim \fontdimen3\the\font=0pt #1\else #2\fi} + +% Turn off all special characters except @ +% (and those which the user can use as if they were ordinary). +% Most of these we simply print from the \tt font, but for some, we can +% use math or other variants that look better in normal text. + +\catcode`\"=\active +\def\activedoublequote{{\tt \char '042}} +\let"=\activedoublequote +\catcode`\~=\active +\def~{{\tt \char '176}} +\chardef\hat=`\^ +\catcode`\^=\active +\def\auxhat{\def^{'hat}} +\def^{{\tt \hat}} + +\catcode`\_=\active +\def_{\ifusingtt\normalunderscore\_} +% Subroutine for the previous macro. +\def\_{\leavevmode \kern.06em \vbox{\hrule width.3em height.1ex}} + +\catcode`\|=\active +\def|{{\tt \char '174}} +\chardef \less=`\< +\catcode`\<=\active +\def<{{\tt \less}} +\chardef \gtr=`\> +\catcode`\>=\active +\def>{{\tt \gtr}} +\catcode`\+=\active +\def+{{\tt \char 43}} +%\catcode 27=\active +%\def^^[{$\diamondsuit$} + +% Set up an active definition for =, but don't enable it most of the time. +{\catcode`\==\active +\global\def={{\tt \char 61}}} + +\catcode`+=\active +\catcode`\_=\active + +% If a .fmt file is being used, characters that might appear in a file +% name cannot be active until we have parsed the command line. +% So turn them off again, and have \everyjob (or @setfilename) turn them on. +% \otherifyactive is called near the end of this file. +\def\otherifyactive{\catcode`+=\other \catcode`\_=\other} + +\catcode`\@=0 + +% \rawbackslashxx output one backslash character in current font +\global\chardef\rawbackslashxx=`\\ +%{\catcode`\\=\other +%@gdef@rawbackslashxx{\}} + +% \rawbackslash redefines \ as input to do \rawbackslashxx. +{\catcode`\\=\active +@gdef@rawbackslash{@let\=@rawbackslashxx }} + +% \normalbackslash outputs one backslash in fixed width font. +\def\normalbackslash{{\tt\rawbackslashxx}} + +% Say @foo, not \foo, in error messages. +\escapechar=`\@ + +% \catcode 17=0 % Define control-q +\catcode`\\=\active + +% Used sometimes to turn off (effectively) the active characters +% even after parsing them. +@def@turnoffactive{@let"=@normaldoublequote +@let\=@realbackslash +@let~=@normaltilde +@let^=@normalcaret +@let_=@normalunderscore +@let|=@normalverticalbar +@let<=@normalless +@let>=@normalgreater +@let+=@normalplus} + +@def@normalturnoffactive{@let"=@normaldoublequote +@let\=@normalbackslash +@let~=@normaltilde +@let^=@normalcaret +@let_=@normalunderscore +@let|=@normalverticalbar +@let<=@normalless +@let>=@normalgreater +@let+=@normalplus} + +% Make _ and + \other characters, temporarily. +% This is canceled by @fixbackslash. +@otherifyactive + +% If a .fmt file is being used, we don't want the `\input texinfo' to show up. +% That is what \eatinput is for; after that, the `\' should revert to printing +% a backslash. +% +@gdef@eatinput input texinfo{@fixbackslash} +@global@let\ = @eatinput + +% On the other hand, perhaps the file did not have a `\input texinfo'. Then +% the first `\{ in the file would cause an error. This macro tries to fix +% that, assuming it is called before the first `\' could plausibly occur. +% Also back turn on active characters that might appear in the input +% file name, in case not using a pre-dumped format. +% +@gdef@fixbackslash{@ifx\@eatinput @let\ = @normalbackslash @fi + @catcode`+=@active @catcode`@_=@active} + +%% These look ok in all fonts, so just make them not special. The @rm below +%% makes sure that the current font starts out as the newly loaded cmr10 +@catcode`@$=@other @catcode`@%=@other @catcode`@&=@other @catcode`@#=@other + +@textfonts +@rm + +@c Local variables: +@c page-delimiter: "^\\\\message" +@c End: diff --git a/contrib/libgmp/urandom.h b/contrib/libgmp/urandom.h new file mode 100644 index 0000000..994e7bd --- /dev/null +++ b/contrib/libgmp/urandom.h @@ -0,0 +1,64 @@ +/* urandom.h -- define urandom returning a full unsigned long random value. + +Copyright (C) 1995, 1996 Free Software Foundation, Inc. + +This file is part of the GNU MP Library. + +The GNU MP Library is free software; you can redistribute it and/or modify +it under the terms of the GNU Library General Public License as published by +the Free Software Foundation; either version 2 of the License, or (at your +option) any later version. + +The GNU MP Library is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public +License for more details. + +You should have received a copy of the GNU Library General Public License +along with the GNU MP Library; see the file COPYING.LIB. If not, write to +the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, +MA 02111-1307, USA. */ + +#if defined (__hpux) || defined (__svr4__) || defined (__SVR4) +/* HPUX lacks random(). */ +static inline unsigned long +urandom () +{ + return mrand48 (); +} +#define __URANDOM +#endif + +#if defined (__alpha) && !defined (__URANDOM) +/* DEC OSF/1 1.2 random() returns a double. */ +long mrand48 (); +static inline unsigned long +urandom () +{ + return mrand48 () | (mrand48 () << 32); +} +#define __URANDOM +#endif + +#if BITS_PER_MP_LIMB == 32 && !defined (__URANDOM) +long random (); +static inline unsigned long +urandom () +{ + /* random() returns 31 bits, we want 32. */ + return random () ^ (random () << 1); +} +#define __URANDOM +#endif + +#if BITS_PER_MP_LIMB == 64 && !defined (__URANDOM) +long random (); +static inline unsigned long +urandom () +{ + /* random() returns 31 bits, we want 64. */ + return random () ^ (random () << 31) ^ (random () << 62); +} +#define __URANDOM +#endif + diff --git a/contrib/libgmp/version.c b/contrib/libgmp/version.c new file mode 100644 index 0000000..7050239 --- /dev/null +++ b/contrib/libgmp/version.c @@ -0,0 +1 @@ +static char *gmp_version = "2.0.1"; |