diff --git a/gnu/lib/libgmp/COPYING.LIB b/gnu/lib/libgmp/COPYING.LIB new file mode 100644 index 000000000000..92b8903ff3fe --- /dev/null +++ b/gnu/lib/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. + + + Copyright (C) + + 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. + + , 1 April 1990 + Ty Coon, President of Vice + +That's all there is to it! diff --git a/gnu/lib/libgmp/ChangeLog b/gnu/lib/libgmp/ChangeLog index 0a8f9ed54bd6..1c29f1ec05d3 100644 --- a/gnu/lib/libgmp/ChangeLog +++ b/gnu/lib/libgmp/ChangeLog @@ -1,241 +1,2079 @@ -Wed May 19 12:14:19 1993 Torbjorn Granlund (tege@nada.kth.se) +Thu Jun 6 19:00:53 1996 Torbjorn Granlund - * Many files: Call alloca(0) before function return. - * alloca.c: New file. - * Makefile (IMPL_SRCS): Add alloca.c. - (IMPL_OBJS): Add alloca.o. + * Version 2.0.2 released. -Fri May 14 00:52:01 1993 Torbjorn Granlund (tege@nada.kth.se) + * install.sh: New file. + * Makefile.in (INSTALL): Use install.sh. + (install-normal): New name for target `install'. + (install): New dummy target. - * mpz_iset_str.c: Fix header comment. + * 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). - * gmp.h: Don't test just FILE, tests some variants of _STDIO_H for - machines were FILE is a typedef. + * config/mt-linux (AR_FLAGS): New file. + * configure.in: Use config/mt-linux for all linux systems. -Tue May 11 21:20:07 1993 Torbjorn Granlund (tege@nada.kth.se) +Tue Jun 4 03:42:18 1996 Torbjorn Granlund - * Makefile (realclean): Make it just be like clean. - (In particular, don't delete Makefile...) + * Version 2.0.1 released. -Thu May 6 14:31:02 1993 Torbjorn Granlund (tege@nada.kth.se) + * mpf/tests/ref.c: Cast result of TMP_ALLOC to the right pointer type. - * mpn_mul.c (vsize < KARATSUBA_THRESHOLD): Eliminate unused - variable `c'. + * extract-double.c: Test _GMP_IEEE_FLOATS with #if, not plain if. - * longlong.h (#if mc88110): Use local union to avoid explicit mov - insns. - * longlong.h (All union defs): Prepend __ before tags to avoid - conflicts. Cleanup union definitions to look the same. + * insert-double.c: Don't #include stdlib.h. - * mpz_inp_str.c: Pass BASE to char_ok_for_base. + * gmp-impl.h (union ieee_double_extract): Test sparc and __sparc. + Do not test __sparc__. -Wed May 5 01:25:23 1993 Torbjorn Granlund (tege@nada.kth.se) + * mpf/reldiff.c: Change declaration to work around irix5 compiler bug. + * mpq/equal.c: Likewise. - * tests/tst-convert.c: Try base == 0. + * mpn/generic/gcd.c: Delete spurious comma at end of enumeration. - * mpz_inp_str.c: Fix typo in assignment. + * 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. - * longlong.h: Adjust UMUL_TIME and UDIV_TIME for several archs. - (#if hppa): Remove udiv_qrnnd. - (#if vax): Define sdiv_qrnnd. Use "g" constraint for umul_ppmm's - operand 0. + * mpn/config/t-oldgas: Renamed from t-freebsd. + * mpn/configure.in: Use t-oldgas for freebsd, netbsd, and some linux + configurations. -Tue May 4 17:11:55 1993 Torbjorn Granlund (tege@du.nada.kth.se) + * mpn/powerpc32/mul_1.s: Really clear cy before entering loop. + * mpn/powerpc32/*.s: Fix power/powerpc syntax issues. - * longlong.h (#if ns32000): Fix typo, udiv_qrnnd was div_qrnnd. + * mpn/config/t-ppc-aix: New file. + * mpn/configure.in: Use t-ppc-aix for powerpc like t-pwr-aix for power. -Mon May 3 00:20:52 1993 Torbjorn Granlund (tege@cyklop.nada.kth.se) +Wed May 29 02:07:31 1996 Torbjorn Granlund - * Makefile: Add rule for mp_bases.o. + * gmp.h (mp_bits_per_limb): Change qualifier from `const' to + __gmp_const. - * _mpz_set_str.c: Make inp_digit an mp_limb. Remove casts of - inp_digit to unsigned. + * gmp.h (mpf_init_set_str): Add `const' qualifier for 2nd parameter. + * mpf/iset_str.c: Likewise. - * mpn_dm_1.c: Use BITS_PER_MP_LIMB instead of 32. - * mpn_mod_1.c: Likewise. - * mpn_dm_1.c (udiv_qrnnd_preinv): Delete testing of overflow that - Peter Montgomery proved can't happen. +Mon May 27 00:15:58 1996 Torbjorn Granlund - * tests/*.c: Include gmp-impl.h to make `inline' and `const' be - #define'd. + * gmp-impl.h: Declare __gmp_extract_double. - * Makefile: Update automatically generated dependencies. + * mpz/set_q.c: Delete unused variables. - * mpz_pow_ui: Don't include mp.h. - Use MP_INT instead of MINT even for rpow. + * gmp.h (mpq_equal): Declare. -Sun May 2 16:35:53 1993 Torbjorn Granlund (tege@cyklop.nada.kth.se) + * mpf/eq.c: mpf_cmp2 -> mpf_eq. - * tests/tst-convert.c, tests/tst-dm_ui.c, tests/tst-mdm.c, - tests/tst-mdm_ui.c: New files. - * tests/tst-dm.c: New name for tests/tst-divmod.c. - * tests/*.c: Include urandom.h. Use urandom(), never random(). - Restructure test code to be more consistent, define and use - dump_abort(), only dump input operands, generate negative operands - when allowed by the tested function, etc. - * tests/urandom.h: New file. - * tests/Makefile: Add new tests. Update dependencies. - (CFLAGS): Pass `-I.'. - (tests) Don't print "The tests passed" since we don't correctly - detect failures. +Fri May 24 03:20:44 1996 Torbjorn Granlund - * mpz_fac_ui: Fix some comments. + * mpz/iset_d.c: Don't include . - * mpz_random.c, mpz_random2.c: Declare random(); - Define random to call mrand48 for __alpha__. + * 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. - * All files: Use #ifdef instead if #if for testing __STDC__. + * mpn/generic/scan0.c: Clarify comment. - * longlong.h (#if sparc_v8): Define UMUL_TIME and UDIV_TIME. + * mpz/set_q.c: New file. + * Makefile.in: Compile it. + * make.bat: Likewise. + * gmp.h: Declare mpz_set_q. - * mpz_inp_str.c: If BASE is 0, try to determine the base from the - leading characters. Restructure code. + * insert-double.c: New file. + * Makefile.in: Compile it. + * make.bat: Likewise. - * mpz_pprime_p.c: Include gmp-impl.h. + * mpz/get_d.c: New file. + * mpz/Makefile.in: Compile it. + * make.bat: Likewise. + * gmp.h: Declare mpz_get_d. -Fri Apr 30 09:35:03 1993 Torbjorn Granlund (tege@du.nada.kth.se) + * mpf/get_d.c: New file. + * mpf/Makefile.in: Compile it. + * make.bat: Likewise. + * gmp.h: Declare mpf_get_d. - * tests/Makefile: Set CC and OPT as in main Makefile. - Add copyright notice. + * make.bat: Compile things in alphabetical order. - * gmp.h: Remove declaration of mpz_not. + * gmp-impl.h (MP_BASE_AS_DOUBLE): New #define. + (LIMBS_PER_DOUBLE): New #define. -Thu Apr 29 19:51:34 1993 Torbjorn Granlund (tege@du.nada.kth.se) + * 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. - * mpq_cmp.c: Fix header comment. + * mpn/configure.in: Use t-pwr-aix also for aix 3.2.4 and up. - From Anders Thulin: - * mpz_inp_str.c: Get condition for char_ok_for_base right. +Wed May 22 02:48:35 1996 Torbjorn Granlund -Tue Apr 27 12:30:48 1993 Torbjorn Granlund (tege@du.nada.kth.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. - * Makefile (check): Pass OPT to recursive make. - * tests/Makefile (OPT): Set to default value. - (CFLAGS): Don't include -g. - (tst-mul): Pass $(CFLAGS) to $(CC). - (tst-divmod): Likewise. - (tst-gcd): Likewise. - (tst-sqrtrem): Likewise. + * mpn/config/t-pwr-aix: New file. + * mpn/configure.in: Use t-pwr-aix for aix 4 and later. - * mpz_gcd.c: Fix typo in comments. +Mon May 20 16:30:31 1996 Torbjorn Granlund - * mpz_sqrtrem.c: Really divide by zero for negative operands. + * gmp.h: In code for setting _GMP_H_HAVE_FILE, test more symbols. - * mpz_mul_ui.c: Fix header comment. + * 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_get_si.c: Fix type typo in cast. + * 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 + + * 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 + + * 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 + + * 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 + + * 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 + + * mpf/set_q.c: New file. + * mpf/Makefile.in: Compile it. + + * config.sub: Recognize sparc8. + +Wed May 8 09:19:11 1996 Torbjorn Granlund + + * 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 + + * 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 + + * Makefile.in (ps): New target, depend on gmp.ps. + +Fri Apr 19 14:03:15 1996 Torbjorn Granlund + + * mpf/out_str.c: Print `@' before exponent, not `e'. + + * make.bat: Update from Makefiles. + +Thu Apr 18 01:22:05 1996 Torbjorn Granlund + + * 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 + + * 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 + + * Makefile.in (gmp.html): Pass -acc to texi2html. + +Mon Apr 15 16:20:24 1996 Torbjorn Granlund + + * 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 + + * 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 + + * 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 + + * 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 + + * 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 + + * 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 + + * mpn/mp_bases.c (__mp_bases): 1e100 => 1e39 to avoid overflow warning. + +Wed Mar 6 01:10:42 1996 Torbjorn Granlund + + * 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 + + * 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 + + * 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 + + * 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 + + * 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 + + * 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 + + * 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 + + * 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 + + * 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 + + * 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 + + * 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 . + * mpf/dump.c: Likewise. + * mpf/set_str.c: #include . + (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 + + * 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 + + * 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 + + * 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 + + * 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 + + * 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 + + * 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 + + * 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 + + * 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 + + * 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 + + * 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 + + * 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 + + * 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 + + * 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 + + * 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 + + * 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 + + * 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 + + * 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 + + * mpz/gcd.c: Fix g->size when one op is 0 and g == other op. + +Tue Feb 6 01:36:39 1996 Torbjorn Granlund + + * 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 + + * 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 + + * 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 + + 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 + + * 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 + + * 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 + + * 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 + + * 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 + + * 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 + + * 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 + + * 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 + + 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 + + * 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 + + * 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 + + * mpz/iset.c: Fix typo introduced Dec 25. + +Wed Jan 17 13:16:44 1996 Torbjorn Granlund + + * 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 + + * 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 + + * 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 + + * 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 + + * 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 + + * All files: Prefix user-visible structure fields with _mp_. + +Fri Dec 22 20:42:17 1995 Torbjorn Granlund + + * mpn/configure.in (m68k configs): Terminate path variable with + plain "m68k". + +Fri Dec 22 03:29:33 1995 Torbjorn Granlund + + * 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 + + * 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 + + * 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 + + * mpn/Makefile.in (.SUFFIXES): Define. + +Wed Nov 29 23:11:57 1995 Torbjorn Granlund + + * mpn/sparc64/{add_n.s, sub_n.s}: New files. + +Tue Nov 28 06:03:13 1995 Torbjorn Granlund + + * 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 + + * mpn/hppa/hppa1_1/pa7100/submul_1.S: New file. + +Sun Nov 26 04:30:47 1995 Torbjorn Granlund + + * 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 + + * mpn/configure.in: Handle m68k on NextStep. + +Thu Nov 16 02:30:26 1995 Torbjorn Granlund + + * 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 + + * 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 + + * 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 + + * 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 + + * 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 + + * mpn/sparc/[lr]shift.S: New files. + +Tue Oct 31 00:08:12 1995 Torbjorn Granlund + + * 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 + + * 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 + + * 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 + + * 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 + + * gmp.h: #undef __need_size_t. + * mp.h: Update from gmp.h. + +Wed Oct 25 00:17:27 1995 Torbjorn Granlund + + * 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 + + * 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 + + * cre-conv-tab.c: #include math.h; don't declare log and floor. + +Sat Oct 21 23:04:10 1995 Torbjorn Granlund + + * mpf/mul_ui.c: Handle U being 0. + +Wed Oct 18 19:39:27 1995 Torbjorn Granlund + + * mpn/generic/set_str.c: Correctly handle input like "000000000000". + Misc cleanups. + +Tue Oct 17 15:14:13 1995 Torbjorn Granlund + + * longlong.h: Define COUNT_LEADING_ZEROS_0 for machines where + appropriate. + +Mon Oct 16 19:14:43 1995 Torbjorn Granlund + + * mpf/add.c: Rewrite. + * mpf/set_str.c: New file. Needs more work. + +Sat Oct 14 00:14:04 1995 Torbjorn Granlund + + * 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 + + * mpn/pentium/rshift.S: Install new code to optimize shift-by-1. + +Tue Oct 10 00:37:21 1995 Torbjorn Granlund + + * 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 + + * longlong.h (smul_ppmm): Correct type of __m0 and __m1. + +Wed Oct 4 16:31:28 1995 Torbjorn Granlund + + * 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 + + * 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 + + * 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 + + * 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 + + * 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 + + * 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 + + * config.sub: Update from current Cygnus version. + + * mpn/configure.in: Recognize canonical m88*, not mc88*. + +Fri Sep 22 14:58:05 1995 Torbjorn Granlund + + * 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 + + * 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 + + * 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 + + * mpq/get_d.c: New file. + +Sun Sep 17 02:04:36 1995 Torbjorn Granlund + + * longlong.h (pyr): Botch up for now. + +Sat Sep 16 00:11:50 1995 Torbjorn Granlund + + * 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 + + * 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 + + * 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 + + * 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 + + * gmp.h (__mpz_struct): Change `long int' => `mp_size_t' for alloc + and size fields. + +Sat Sep 2 17:47:59 1995 Torbjorn Granlund + + * 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 + + * 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 + + * 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 + + * 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 + + * 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 + + * 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. - * cre-conv-tab.c: #include gmp.h and gmp-impl.h to get bit size - right for longlong.h. - * Makefile: Add new deps for `cre-conv-tab'. + * 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. - * Makefile, tests/Makefile: Don't define or use srcdir. +Sun Apr 25 00:31:28 1993 Torbjorn Granlund (tege@pde.nada.kth.se) - * longlong.h (#if alpha): Define umul_ppmm. - Define UMUL_TIME and UDIV_TIME. - (#if i960): Define umul_ppmm and __umulsidi3. - (#if hppa): Define count_leading_zeros. - (#if IBMR2): Remove umul_ppmm. Define smul_ppmm. - (#if 68020): Define smul_ppmm. - (#if mc88110): Define umul_ppmm and udiv_qrnnd. - (#if ns32000): Define umul_ppmm. - (#if pyr): Rewrite umul_ppmm. - - * mpz_powm: `carry_digit' => `carry_limb'. - * sdiv.c: Clearify comment. + * 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) - * tests: Update header comments. Make default sizes 8, use SIZE - symbol to allow user override. Increase default repetitions. - - * longlong.h (__udiv_qrnnd_c): Define this always. - Make all variables `unsigned long int'. - (__LLDEBUG__): Remove this conditional. + * longlong.h (__udiv_qrnnd_c): Make all variables `unsigned long int'. * gmp-impl.h: #define ABS. * (Many files): Use ABS instead of abs. - * _mpz_get_str, mpn_sqrt, mpz_clrbit, mpz_get_si, mpz_mod_2exp, - mpz_pow_ui, mpz_random2: Cast 1 to mp_limb before shifting. + * 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. - * gmp.h: mpn_add returns mp_limb. - - * mpz_perfsqr: Use #if, not plain if for exclusion of code for + * 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_sqrt: Handle overflow for intermediate quotients by rounding - them down to fit. + * mpn/generic/sqrt.c: Handle overflow for intermediate quotients by + rounding them down to fit. - * mpz_random2: Back to random(); rand() is so bad we get into cycles. + * mpz/perfsqr.c (PP): Define in hexadecimal to avoid GCC warnings. - * mpz_perfsqr.c (PP): Define in hexadecimal to avoid GCC warnings. - - * mpz_inp_str.c (char_ok_for_base): New function. + * mpz/inp_str.c (char_ok_for_base): New function. (mpz_inp_str): Use it. - * gmp.h: Add `const' to decl of mpz_probab_pripe_p. - - * _mpz_set_str.c (char_type): Remove final `,'. - (ascii_to_num): Likewise. - Sun Mar 28 21:54:06 1993 Torbjorn Granlund (tege@cyklop.nada.kth.se) - * mpz_inp_raw: Allocate x_index, not xsize limbs. + * 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_p.c: Declare param `const'. + * 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, mpq_sub: Call mpz_clear for t. + * 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: Recog minus sign as first character. + * 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_random.c (urandom): New conditionally defined local function. - Use it instead of random(). - * mpz_random2: Use rand() instead of random() here, since we don't - care how many bits we get. - - * mpz_iset: Handle 0 size. + * mpz/iset.c: Handle 0 size. Tue Feb 2 13:03:33 1993 Torbjorn Granlund (tege@cyklop.nada.kth.se) - * _mpz_get_str: Adjust for negative msize when returning str. - - * mpz_mod_ui: Initialize dividend_size before it's used. + * mpz/mod_ui.c: Initialize dividend_size before it's used. Mon Jan 4 09:11:15 1993 Torbjorn Granlund (tege@sics.se) - * itom: Declare param explicitly 'signed'. - * sdiv: Likewise. + * bsd/itom.c: Declare param explicitly 'signed'. + * bsd/sdiv.c: Likewise. - * mpq_cmp: Remove unused variable tmp_size. - * mpz_powm_ui: Fix typo in esize==0 if stmt. - * mpz_powm: 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_dm_1.c (mpn_divmod_1): Handle + * mpn/generic/divmod_1.c (mpn_divmod_1): Handle divisor_limb == 1 << (BITS_PER_MP_LIMB - 1) specifically. -Sat Nov 28 17:19:40 1992 Torbjorn Granlund (tege@sics.se) - - * mpz_div: Remove free_me and free_me_size and their usage. + * 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) @@ -247,7 +2085,7 @@ Wed Oct 28 17:40:04 1992 Torbjorn Granlund (tege@jupiter.sics.se) Sun Oct 25 20:30:06 1992 Torbjorn Granlund (tege@jupiter.sics.se) - * mpz_pprime_p.c (mpz_probab_prime_p): Handle numbers <= 3 + * 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'. @@ -255,19 +2093,6 @@ Sun Oct 25 20:30:06 1992 Torbjorn Granlund (tege@jupiter.sics.se) * sdiv: Handle zero dividend specifically. Replace most code in this function with a call to mpn_divmod_1. - * mpn_add: Return type is mp_limb. - - * _mpz_get_str: Assign and use MSIZE smarter, to avoid using - m->size. - * _mpz_get_str: Allocate extra STR space if (MSIZE < 0) for minus - sign. - * _mpz_get_str: Move string backwards smarter, avoid copying when - not needed. - - * gmp.h (mpn_lshift, mpn_rshift, mpn_rshiftci): Remove `long' from - 4:th arg. - * Makefile.in (MP_OBJS) : Include mpz_sizeinb.o. - Fri Sep 11 22:15:55 1992 Torbjorn Granlund (tege@tarrega.sics.se) * mpq_clear: Don't free the MP_RAT! @@ -276,8 +2101,6 @@ Fri Sep 11 22:15:55 1992 Torbjorn Granlund (tege@tarrega.sics.se) Thu Sep 3 01:47:07 1992 Torbjorn Granlund (tege@jupiter.sics.se) - * mpn_mul: Rewrite code jumping between `carry case' and `noncarry - case' to avoid jumping. Special case for V_LIMB being 0 ot 1. * All files: Remove leading _ from mpn function names. Wed Sep 2 22:21:16 1992 Torbjorn Granlund (tege@jupiter.sics.se) @@ -293,6 +2116,12 @@ 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 @@ -304,39 +2133,56 @@ Fri Feb 14 21:33:21 1992 Torbjorn Granlund (tege@zevs.sics.se) 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@sics.se) +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@sics.se) +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@sics.se) +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@sics.se) +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@sics.se) +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@sics.se) +Mon Jan 27 09:44:16 1992 Torbjorn Granlund (tege@zevs.sics.se) * Makefile.in: Add new files. @@ -347,54 +2193,54 @@ Mon Jan 27 09:44:16 1992 Torbjorn Granlund (tege@sics.se) * 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@sics.se) +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@sics.se) +Wed Jan 22 12:02:26 1992 Torbjorn Granlund (tege@zevs.sics.se) - * mpz_pprime_p.c: Use "" for #include. + * mpz_pprime.c: Use "" for #include. -Sun Jan 19 13:36:55 1992 Torbjorn Granlund (tege@sics.se) +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@sics.se) +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@sics.se) +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@sics.se) +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@sics.se) +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@sics.se) +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@sics.se) +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@sics.se) +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. @@ -408,31 +2254,31 @@ Sat Dec 14 01:00:02 1991 Torbjorn Granlund (tege@sics.se) * mpz_fac_ui: Fix comment. - * mpz_random2: Rewrite to make it possible for the most significant - limb to be == 1. + * mpz_random2: Rewrite a bit to make it possible for the most + significant limb to be == 1. - * mpz_pprime_p.c (mpz_probab_prime_p): Remove \t\n. + * mpz_pprime.c (mpz_probab_prime_p): Remove \t\n. -Fri Dec 13 23:10:02 1991 Torbjorn Granlund (tege@sics.se) +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@sics.se) +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@sics.se) +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@sics.se) +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@sics.se) +Mon Dec 9 17:46:10 1991 Torbjorn Granlund (tege@zevs.sics.se) Released 1.2. @@ -449,29 +2295,29 @@ Mon Dec 9 17:46:10 1991 Torbjorn Granlund (tege@sics.se) * longlong.h (__a29k__ udiv_qrnnd): Change "q" to "1" for operand 2 constraint. -Mon Nov 11 00:06:05 1991 Torbjorn Granlund (tege@sics.se) +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@sics.se) +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@sics.se) +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@sics.se) +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@sics.se) +Mon Nov 4 00:36:46 1991 Torbjorn Granlund (tege@zevs.sics.se) * mpn_mul: Fix indentation. @@ -482,7 +2328,7 @@ Mon Nov 4 00:36:46 1991 Torbjorn Granlund (tege@sics.se) * gmp.h: Add missing function definitions. -Sun Nov 3 18:25:25 1991 Torbjorn Granlund (tege@sics.se) +Sun Nov 3 18:25:25 1991 Torbjorn Granlund (tege@zevs.sics.se) * mpz_pow_ui: Change type of `i' to int. @@ -510,12 +2356,12 @@ Stack overflow. * 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@sics.se) +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@sics.se) +Mon Oct 28 00:35:29 1991 Torbjorn Granlund (tege@zevs.sics.se) * mpz_random2: Handle size == 0. @@ -545,7 +2391,7 @@ Mon Oct 28 00:35:29 1991 Torbjorn Granlund (tege@sics.se) shortcut algorithm. * mpn_mul: Fix typo, cy instead of xcy. Unify carry handling code. -Sun Oct 27 19:57:32 1991 Torbjorn Granlund (tege@sics.se) +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. @@ -555,7 +2401,7 @@ Sun Oct 27 19:57:32 1991 Torbjorn Granlund (tege@sics.se) * mpn_div: Kludge to fix stray memory read. -Sat Oct 26 20:06:14 1991 Torbjorn Granlund (tege@sics.se) +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. @@ -568,11 +2414,11 @@ Sat Oct 26 20:06:14 1991 Torbjorn Granlund (tege@sics.se) * 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@sics.se) +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@sics.se) +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 @@ -580,41 +2426,41 @@ Thu Oct 17 18:06:42 1991 Torbjorn Granlund (tege@sics.se) * 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@sics.se) +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@sics.se) +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@sics.se) +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@sics.se) +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@sics.se) +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@sics.se) +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@sics.se) +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@sics.se) +Mon Sep 9 15:16:24 1991 Torbjorn Granlund (tege@zevs.sics.se) Released 1.0.92. @@ -624,11 +2470,11 @@ Mon Sep 9 15:16:24 1991 Torbjorn Granlund (tege@sics.se) * longlong.h (m68000 umul_ppmm): Clobber one register less by slightly rearranging the code. -Sun Sep 1 18:53:25 1991 Torbjorn Granlund (tege@sics.se) +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@sics.se) +Sat Aug 31 20:41:31 1991 Torbjorn Granlund (tege@zevs.sics.se) Released 1.0.91. @@ -636,7 +2482,7 @@ Sat Aug 31 20:41:31 1991 Torbjorn Granlund (tege@sics.se) 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@sics.se) +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 @@ -647,13 +2493,13 @@ Fri Aug 30 08:32:56 1991 Torbjorn Granlund (tege@sics.se) * dist-Makefile, mpz_cmp.c: Merge mcmp.c from mpz_cmp.c. -Wed Aug 28 00:45:11 1991 Torbjorn Granlund (tege@sics.se) +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@sics.se) +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). @@ -661,7 +2507,7 @@ Fri Aug 23 15:58:52 1991 Torbjorn Granlund (tege@sics.se) destinations, to `unsigned long int'. * longlong.h: Add gmicro support. -Thu Aug 22 00:28:29 1991 Torbjorn Granlund (tege@sics.se) +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. @@ -670,7 +2516,7 @@ Thu Aug 22 00:28:29 1991 Torbjorn Granlund (tege@sics.se) 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@sics.se) +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.) @@ -683,13 +2529,13 @@ Wed Aug 21 15:45:23 1991 Torbjorn Granlund (tege@sics.se) 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@sics.se) +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@sics.se) +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. @@ -708,7 +2554,7 @@ Mon Aug 19 00:37:42 1991 Torbjorn Granlund (tege@sics.se) * 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@sics.se) +Sun Aug 18 14:44:26 1991 Torbjorn Granlund (tege@zevs.sics.se) * mpz_mod_ui: Handle dividend < 0. @@ -744,7 +2590,7 @@ Sun Aug 18 14:44:26 1991 Torbjorn Granlund (tege@sics.se) recursive call. (Don't violate mpn_mul's own argument constraints.) -Fri Aug 16 13:47:12 1991 Torbjorn Granlund (tege@sics.se) +Fri Aug 16 13:47:12 1991 Torbjorn Granlund (tege@zevs.sics.se) Released 1.0beta.10. @@ -762,20 +2608,20 @@ Fri Aug 16 13:47:12 1991 Torbjorn Granlund (tege@sics.se) `unsigned long int'. * longlong.h: Add `int' after `unsigned' and `long' everywhere. -Wed Aug 14 18:06:48 1991 Torbjorn Granlund (tege@sics.se) +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@sics.se) +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@sics.se) +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. @@ -790,7 +2636,7 @@ Mon Aug 12 17:11:46 1991 Torbjorn Granlund (tege@sics.se) * mp.h, gmp.h: Change names of macros for avoiding multiple includes. -Fri Aug 9 18:01:36 1991 Torbjorn Granlund (tege@sics.se) +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). @@ -803,7 +2649,7 @@ Fri Aug 9 18:01:36 1991 Torbjorn Granlund (tege@sics.se) on the CPU name. * longlong.h: Hack comments. -Thu Aug 8 14:13:36 1991 Torbjorn Granlund (tege@sics.se) +Thu Aug 8 14:13:36 1991 Torbjorn Granlund (tege@zevs.sics.se) Released 1.0beta.9. @@ -837,7 +2683,7 @@ Thu Aug 8 14:13:36 1991 Torbjorn Granlund (tege@sics.se) * _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@sics.se) +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. @@ -860,12 +2706,12 @@ Sun Aug 4 16:54:14 1991 Torbjorn Granlund (tege@sics.se) 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@sics.se) +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@sics.se) +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. @@ -887,7 +2733,7 @@ Fri Aug 2 18:29:11 1991 Torbjorn Granlund (tege@sics.se) Berkeley function name variants. * dist-Makefile: Add created files to "clean" target. -Tue Jul 16 15:19:46 1991 Torbjorn Granlund (tege@sics.se) +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. @@ -898,7 +2744,7 @@ Tue Jul 16 15:19:46 1991 Torbjorn Granlund (tege@sics.se) * 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@sics.se) +Mon Jul 15 11:08:05 1991 Torbjorn Granlund (tege@zevs.sics.se) * Several files: Remove unused variables and functions. @@ -909,8 +2755,8 @@ Mon Jul 15 11:08:05 1991 Torbjorn Granlund (tege@sics.se) * 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: 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. @@ -924,7 +2770,7 @@ Mon Jul 15 11:08:05 1991 Torbjorn Granlund (tege@sics.se) * mpz_perfsqr: Fix argument order in _mpz_impl_sqrt call. (Fix from Brian Beuning.) -Fri Jul 12 17:10:33 1991 Torbjorn Granlund (tege@sics.se) +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: @@ -950,7 +2796,7 @@ Fri Jul 12 17:10:33 1991 Torbjorn Granlund (tege@sics.se) * dist-Makefile (clean): Add some more. * gmp.h, mp.h: Unconditionally include "stddef.h". -Thu Jul 11 10:08:21 1991 Torbjorn Granlund (tege@sics.se) +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. @@ -964,7 +2810,7 @@ Thu Jul 11 10:08:21 1991 Torbjorn Granlund (tege@sics.se) * 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@sics.se) +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. @@ -978,7 +2824,7 @@ Wed Jul 10 14:13:33 1991 Torbjorn Granlund (tege@sics.se) * mpz_and, mpz_ior: Negate negative op[12]_size in several places. -Tue Jul 9 18:40:30 1991 Torbjorn Granlund (tege@sics.se) +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.) @@ -989,7 +2835,7 @@ Tue Jul 9 18:40:30 1991 Torbjorn Granlund (tege@sics.se) * 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@sics.se) +Fri Jul 5 19:08:09 1991 Torbjorn Granlund (tege@zevs.sics.se) * move: Remove incorrect comment. @@ -999,7 +2845,7 @@ Fri Jul 5 19:08:09 1991 Torbjorn Granlund (tege@sics.se) * mpz_dmincl.c: Don't call "move", inline its functionality. -Thu Jul 4 00:06:39 1991 Torbjorn Granlund (tege@sics.se) +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). @@ -1032,9 +2878,9 @@ Thu Jul 4 00:06:39 1991 Torbjorn Granlund (tege@sics.se) * 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 compatibillity. + * All files: #ifdef for traditional C compatibility. -Wed Jul 3 11:42:14 1991 Torbjorn Granlund (tege@sics.se) +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). @@ -1051,7 +2897,7 @@ Wed Jul 3 11:42:14 1991 Torbjorn Granlund (tege@sics.se) 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@sics.se) +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. diff --git a/gnu/lib/libgmp/INSTALL b/gnu/lib/libgmp/INSTALL index a8927b15e943..38bfaa8b46bc 100644 --- a/gnu/lib/libgmp/INSTALL +++ b/gnu/lib/libgmp/INSTALL @@ -1,34 +1,154 @@ -Here is how to compile GNU MP. +INSTALLING GMP +============== -You probably want to use the GNU C compiler to build this library. -With other compilers the speed of the library will be 3-10 times -slower for many CPU:s. The reason for this is that the GNU C compiler -will use inline assembler for some important operations, while other C -compilers will have to stick to plain C code. +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. -This is how to build the library: +Here are short instructions how to install MP, and some examples that help you +get started using MP. - Type "make" to build libgmp.a and libmp.a. The former is the main - GNU MP library. The latter is the Berkeley MP compatible library. +First, you need to compile, and optionally install, MP. Since you're +impatient, try this: - If you don't have GCC, type "make CC=cc". The compilation should, at - least with GCC, proceed without any kind of warnings from the compiler - programs. On the DEC Alpha, you have to use GCC because of bugs in DEC's - own compiler. GCC 2.3.3 for x86, Alpha, and HP-PA has bugs that make - several functions be mis-optimized. Later version of GCC does not have - this problem. + ./configure; make - To build and run the tests, do "make check". +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. -The documentation is an a texinfo file, gmp.texi. +Next, you need to try some small test programs, for example the ones below. -To create the documentation from the texinfo source, type "make doc". -This requires the "tex" and "makeinfo" commands to be available in -your search path. If you have only one of them, you can create the -dvi file (for the paper manual) with "make gmp.dvi", and the info file -(for the GNU online manual facility) with "make gmp.info". +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. -You need version 2.06 or later of texinfo in order to build the -documentation. + #include + #include /* All MP programs need to include gmp.h */ -Please report problems to tege@gnu.ai.mit.edu. + 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 + #include + + 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/gnu/lib/libgmp/Makefile.in b/gnu/lib/libgmp/Makefile.in new file mode 100644 index 000000000000..6d7ff619fa41 --- /dev/null +++ b/gnu/lib/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/gnu/lib/libgmp/NEWS b/gnu/lib/libgmp/NEWS new file mode 100644 index 000000000000..b61c8406966b --- /dev/null +++ b/gnu/lib/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/gnu/lib/libgmp/PROJECTS b/gnu/lib/libgmp/PROJECTS new file mode 100644 index 000000000000..75016bdbd21e --- /dev/null +++ b/gnu/lib/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/gnu/lib/libgmp/README b/gnu/lib/libgmp/README index b31e7b3104b8..3afa67745e90 100644 --- a/gnu/lib/libgmp/README +++ b/gnu/lib/libgmp/README @@ -1,61 +1,137 @@ THE GNU MP LIBRARY -GNU MP is a library for arbitrary precision arithmetic, operating on -signed integers and rational numbers. It has a rich set of functions, -and the functions have a regular interface. +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. -I have tried to make these functions 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 defining inline -assembler for mixed sized multiplication and division (i.e 32*32->64 bit -multiplication and 64/32->32,32 bit division), and by hacking the code -with emphasis on speed (and not simplicity and elegance). +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 about 5 to 100 times that of Berkeley MP for -small operands. The speed-up increases with the operand sizes for -certain operations, for which GNU MP has asymptotically faster algorithms. +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. -There are four classes of functions in GNU MP. + GETTING STARTED - 1. Signed integer arithmetic functions, mpz_*. The set of functions are - intended to be easy to use, being rich and regular. +First, you have to configure and compiler GNU MP. Simply typing - To use these functions, include the file "gmp.h". + ./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 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 + #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 + #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. + functions necessary for basic rational arithmetics. The associated type + is `mpq_t'. - To use these functions, include the file "gmp.h". + 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. - 3. Positive-integer, low-level, harder-to-use, but for small operands - about twice as fast than the mpz_* functions are the functions 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 quite 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. + 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 in these + Almost all calculations, in the entire package, are made by calling these low-level functions. - These functions are not fully documented in this release. They will - probably be so in a future release. + 5. Berkeley MP compatible functions. - 4. 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. - 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! -You can report bugs, and propose modifications and enhancements to -tege@gnu.ai.mit.edu. How to report a bug is further described in -the texinfo documentation, see the file gmp.texi. - +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/gnu/lib/libgmp/SPEED b/gnu/lib/libgmp/SPEED new file mode 100644 index 000000000000..e888e17e5b42 --- /dev/null +++ b/gnu/lib/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/gnu/lib/libgmp/config.guess b/gnu/lib/libgmp/config.guess new file mode 100755 index 000000000000..afd200a33d35 --- /dev/null +++ b/gnu/lib/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 . +# 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 + + 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 + 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 </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' /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 < +# include +#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 + 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/gnu/lib/libgmp/config.sub b/gnu/lib/libgmp/config.sub new file mode 100755 index 000000000000..997f9dbb02d6 --- /dev/null +++ b/gnu/lib/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/gnu/lib/libgmp/config/mt-linux b/gnu/lib/libgmp/config/mt-linux new file mode 100644 index 000000000000..476d8b590d57 --- /dev/null +++ b/gnu/lib/libgmp/config/mt-linux @@ -0,0 +1 @@ +AR_FLAGS = qc diff --git a/gnu/lib/libgmp/config/mt-m88110 b/gnu/lib/libgmp/config/mt-m88110 new file mode 100644 index 000000000000..071f8fa1bd86 --- /dev/null +++ b/gnu/lib/libgmp/config/mt-m88110 @@ -0,0 +1 @@ +XCFLAGS = -m88110 diff --git a/gnu/lib/libgmp/config/mt-sprc8-gcc b/gnu/lib/libgmp/config/mt-sprc8-gcc new file mode 100644 index 000000000000..bc706a961ca8 --- /dev/null +++ b/gnu/lib/libgmp/config/mt-sprc8-gcc @@ -0,0 +1 @@ +XCFLAGS = -mv8 diff --git a/gnu/lib/libgmp/config/mt-supspc-gcc b/gnu/lib/libgmp/config/mt-supspc-gcc new file mode 100644 index 000000000000..92a0924d4390 --- /dev/null +++ b/gnu/lib/libgmp/config/mt-supspc-gcc @@ -0,0 +1 @@ +XCFLAGS = -mv8 -DSUPERSPARC diff --git a/gnu/lib/libgmp/configure b/gnu/lib/libgmp/configure new file mode 100755 index 000000000000..1554506225e1 --- /dev/null +++ b/gnu/lib/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 < ${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} <> ${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/gnu/lib/libgmp/configure.in b/gnu/lib/libgmp/configure.in new file mode 100644 index 000000000000..42192b507e3a --- /dev/null +++ b/gnu/lib/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/gnu/lib/libgmp/cre-mparam.c b/gnu/lib/libgmp/cre-mparam.c index db0c99227e99..2020c8a82cbe 100644 --- a/gnu/lib/libgmp/cre-mparam.c +++ b/gnu/lib/libgmp/cre-mparam.c @@ -1,118 +1,16 @@ -/* cre-mparam.c -- Create machine-depedent parameter file. - -Copyright (C) 1991 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 General Public License as published by -the Free Software Foundation; either version 2, or (at your option) -any later version. - -The GNU MP Library is distributed in the hope that 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 the GNU MP Library; see the file COPYING. If not, write to -the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ - #include "gmp.h" -unsigned int -ulog2 (x) - unsigned long int x; -{ - unsigned int i; - for (i = 0; x != 0; i++) - x >>= 1; - return i; -} - main () { - int i; +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"); - unsigned long int max_uli; - int bits_uli; - - unsigned long int max_ui; - int bits_ui; - - unsigned long int max_usi; - int bits_usi; - - unsigned long int max_uc; - int bits_uc; - - max_uli = 1; - for (i = 0; ; i++) - { - if (max_uli == 0) - break; - max_uli <<= 1; - } - bits_uli = i; - - max_ui = 1; - for (i = 0; ; i++) - { - if ((unsigned int) max_ui == 0) - break; - max_ui <<= 1; - } - bits_ui = i; - - max_usi = 1; - for (i = 0; ; i++) - { - if ((unsigned short int) max_usi == 0) - break; - max_usi <<= 1; - } - bits_usi = i; - - max_uc = 1; - for (i = 0; ; i++) - { - if ((unsigned char) max_uc == 0) - break; - max_uc <<= 1; - } - bits_uc = i; - - puts ("/* gmp-mparam.h -- Compiler/machine parameter header file."); - puts (""); - puts (" ***** THIS FILE WAS CREATED BY A PROGRAM. DON'T EDIT IT! *****"); - puts (""); - puts ("Copyright (C) 1991 Free Software Foundation, Inc."); - puts (""); - puts ("This file is part of the GNU MP Library."); - puts (""); - puts ("The GNU MP Library is free software; you can redistribute it and/or"); - puts ("modify it under the terms of the GNU General Public License as"); - puts ("published by the Free Software Foundation; either version 2, or"); - puts ("(at your option) any later version."); - puts (""); - puts ("The GNU MP Library is distributed in the hope that it will be"); - puts ("useful, but WITHOUT ANY WARRANTY; without even the implied warranty"); - puts ("of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the"); - puts ("GNU General Public License for more details."); - puts (""); - puts ("You should have received a copy of the GNU General Public License"); - puts ("along with the GNU MP Library; see the file COPYING. If not, write"); - puts ("to the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139,"); - puts ("USA. */"); - puts (""); - - printf ("#define BITS_PER_MP_LIMB %d\n", bits_uli); - printf ("#define BYTES_PER_MP_LIMB %d\n", sizeof(mp_limb)); - - printf ("#define BITS_PER_LONGINT %d\n", bits_uli); - printf ("#define BITS_PER_INT %d\n", bits_ui); - printf ("#define BITS_PER_SHORTINT %d\n", bits_usi); - printf ("#define BITS_PER_CHAR %d\n", bits_uc); - - exit (0); +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/gnu/lib/libgmp/demos/factorize.c b/gnu/lib/libgmp/demos/factorize.c new file mode 100644 index 000000000000..4a965d316004 --- /dev/null +++ b/gnu/lib/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 +#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/gnu/lib/libgmp/extract-double.c b/gnu/lib/libgmp/extract-double.c new file mode 100644 index 000000000000..052b1a9c647f --- /dev/null +++ b/gnu/lib/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/gnu/lib/libgmp/gmp-impl.h b/gnu/lib/libgmp/gmp-impl.h index e02691f926c8..7d5684613d45 100644 --- a/gnu/lib/libgmp/gmp-impl.h +++ b/gnu/lib/libgmp/gmp-impl.h @@ -1,43 +1,86 @@ /* Include file for internal GNU MP types and definitions. -Copyright (C) 1991 Free Software Foundation, Inc. +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 General Public License as published by -the Free Software Foundation; either version 2, or (at your option) -any later version. +it under the terms of the GNU Library General Public License as published by +the Free Software Foundation; either version 2 of the License, or (at your +option) any later version. -The GNU MP Library is distributed in the hope that 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. +The GNU MP Library is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public +License for more details. -You should have received a copy of the GNU General Public License -along with the GNU MP Library; see the file COPYING. If not, write to -the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ +You should have received a copy of the GNU Library General Public License +along with the GNU MP Library; 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 (__GNUC__) || defined (__sparc__) || defined (sparc) +/* 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 +#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 0L +#define NULL ((void *) 0) #endif -#if defined (__GNUC__) -volatile void abort (void); -#else +#if ! defined (__GNUC__) #define inline /* Empty */ -void *alloca(); #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" */ -#ifdef __STDC__ +#if defined (__STDC__) || defined (__cplusplus) void *malloc (size_t); void *realloc (void *, size_t); void free (void *); @@ -50,10 +93,8 @@ void *_mp_default_allocate (size_t); void *_mp_default_reallocate (void *, size_t, size_t); void _mp_default_free (void *, size_t); -char *_mpz_get_str (char *, int, const MP_INT *); -int _mpz_set_str (MP_INT *, const char *, int); -void _mpz_impl_sqrt (MP_INT *, MP_INT *, const MP_INT *); #else + #define const /* Empty */ #define signed /* Empty */ @@ -68,59 +109,259 @@ extern void (*_mp_free_func) (); void *_mp_default_allocate (); void *_mp_default_reallocate (); void _mp_default_free (); - -char *_mpz_get_str (); -int _mpz_set_str (); -void _mpz_impl_sqrt (); #endif /* Copy NLIMBS *limbs* from SRC to DST. */ -#define MPN_COPY(DST, SRC, NLIMBS) \ +#define MPN_COPY_INCR(DST, SRC, NLIMBS) \ do { \ - mp_size i; \ - for (i = 0; i < (NLIMBS); i++) \ - (DST)[i] = (SRC)[i]; \ + 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 i; \ - for (i = 0; i < (NLIMBS); i++) \ - (DST)[i] = 0; \ + 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. */ + 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 { \ - (X)->alloc = (NLIMBS); \ - (X)->d = (mp_ptr) alloca ((NLIMBS) * BYTES_PER_MP_LIMB); \ + 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. For example, for base 10 this is 10, since - 2**32 = 4294967296 has ten digits. */ + /* 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; - /* big_base is conversion_base**chars_per_limb, i.e. the biggest - number that fits a word, built by factors of conversion_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 big_base; - - /* big_base_inverted is 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 big_base_inverted; - /* 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[37]; +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/gnu/lib/libgmp/gmp.h b/gnu/lib/libgmp/gmp.h index 91ee7af1a8ac..a1cc1ac7cd2e 100644 --- a/gnu/lib/libgmp/gmp.h +++ b/gnu/lib/libgmp/gmp.h @@ -1,302 +1,632 @@ /* gmp.h -- Definitions for GNU multiple precision functions. -Copyright (C) 1991, 1993 Free Software Foundation, Inc. +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 General Public License as published by -the Free Software Foundation; either version 2, or (at your option) -any later version. +it under the terms of the GNU Library General Public License as published by +the Free Software Foundation; either version 2 of the License, or (at your +option) any later version. -The GNU MP Library is distributed in the hope that 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. +The GNU MP Library is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public +License for more details. -You should have received a copy of the GNU General Public License -along with the GNU MP Library; see the file COPYING. If not, write to -the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ +You should have received a copy of the GNU Library General Public License +along with the GNU MP Library; 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__ -#define __GMP_H__ -#define __GNU_MP__ - -#ifndef __MP_H__ +#ifndef __GNU_MP__ +#define __GNU_MP__ 2 #define __need_size_t #include +#undef __need_size_t + +#if defined (__STDC__) || defined (__cplusplus) +#define __gmp_const const +#else +#define __gmp_const #endif -#ifndef MINT +#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 { - long int alloc; /* Number of *limbs* allocated and pointed + int _mp_alloc; /* Number of *limbs* allocated and pointed to by the D field. */ - long int size; /* abs(SIZE) is the number of 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. */ - unsigned long int *d; /* Pointer to the limbs. */ -} __MP_INT; + mp_limb_t *_mp_d; /* Pointer to the limbs. */ +} __mpz_struct; #else typedef struct { - short int alloc; /* Number of *limbs* allocated and pointed + short int _mp_alloc; /* Number of *limbs* allocated and pointed to by the D field. */ - short int size; /* abs(SIZE) is the number of limbs + 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. */ - unsigned long int *d; /* Pointer to the limbs. */ -} __MP_INT; -#endif + mp_limb_t *_mp_d; /* Pointer to the limbs. */ +} __mpz_struct; #endif +#endif /* __GNU_MP__ */ -#define MP_INT __MP_INT - -typedef unsigned long int mp_limb; -typedef long int mp_limb_signed; -typedef mp_limb * mp_ptr; -#ifdef __STDC__ -typedef const mp_limb * mp_srcptr; -#else -typedef mp_limb * mp_srcptr; -#endif -typedef long int mp_size; +/* 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 { - MP_INT num; - MP_INT den; + __mpz_struct _mp_num; + __mpz_struct _mp_den; #if 0 - long int num_alloc; /* Number of limbs allocated + int _mp_num_alloc; /* Number of limbs allocated for the numerator. */ - long int num_size; /* The absolute value of this field is the + 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 num; /* Pointer to the numerator limbs. */ - long int den_alloc; /* Number of limbs allocated + mp_ptr _mp_num; /* Pointer to the numerator limbs. */ + int _mp_den_alloc; /* Number of limbs allocated for the denominator. */ - long int den_size; /* Length of the denominator. (This field + int _mp_den_size; /* Length of the denominator. (This field should always be positive.) */ - mp_ptr den; /* Pointer to the denominator limbs. */ + mp_ptr _mp_den; /* Pointer to the denominator limbs. */ #endif -} MP_RAT; +} __mpq_struct; -#ifdef __STDC__ -void mp_set_memory_functions (void *(*) (size_t), - void *(*) (void *, size_t, size_t), - void (*) (void *, size_t)); +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. ****************/ -void mpz_init (MP_INT *); -void mpz_set (MP_INT *, const MP_INT *); -void mpz_set_ui (MP_INT *, unsigned long int); -void mpz_set_si (MP_INT *, signed long int); -int mpz_set_str (MP_INT *, const char *, int); -void mpz_init_set (MP_INT *, const MP_INT *); -void mpz_init_set_ui (MP_INT *, unsigned long int); -void mpz_init_set_si (MP_INT *, signed long int); -int mpz_init_set_str (MP_INT *, const char *, int); -unsigned long int mpz_get_ui (const MP_INT *); -signed long int mpz_get_si (const MP_INT *); -char * mpz_get_str (char *, int, const MP_INT *); -void mpz_clear (MP_INT *); -void * _mpz_realloc (MP_INT *, mp_size); -void mpz_add (MP_INT *, const MP_INT *, const MP_INT *); -void mpz_add_ui (MP_INT *, const MP_INT *, unsigned long int); -void mpz_sub (MP_INT *, const MP_INT *, const MP_INT *); -void mpz_sub_ui (MP_INT *, const MP_INT *, unsigned long int); -void mpz_mul (MP_INT *, const MP_INT *, const MP_INT *); -void mpz_mul_ui (MP_INT *, const MP_INT *, unsigned long int); -void mpz_div (MP_INT *, const MP_INT *, const MP_INT *); -void mpz_div_ui (MP_INT *, const MP_INT *, unsigned long int); -void mpz_mod (MP_INT *, const MP_INT *, const MP_INT *); -void mpz_mod_ui (MP_INT *, const MP_INT *, unsigned long int); -void mpz_divmod (MP_INT *, MP_INT *, const MP_INT *, const MP_INT *); -void mpz_divmod_ui (MP_INT *, MP_INT *, const MP_INT *, unsigned long int); -void mpz_mdiv (MP_INT *, const MP_INT *, const MP_INT *); -void mpz_mdiv_ui (MP_INT *, const MP_INT *, unsigned long int); -void mpz_mmod (MP_INT *, const MP_INT *, const MP_INT *); -unsigned long int mpz_mmod_ui (MP_INT *, const MP_INT *, unsigned long int); -void mpz_mdivmod (MP_INT *, MP_INT *, const MP_INT *, const MP_INT *); -unsigned long int mpz_mdivmod_ui (MP_INT *, MP_INT *, const MP_INT *, - unsigned long int); -void mpz_sqrt (MP_INT *, const MP_INT *); -void mpz_sqrtrem (MP_INT *, MP_INT *, const MP_INT *); -int mpz_perfect_square_p (const MP_INT *); -int mpz_probab_prime_p (const MP_INT *, int); -void mpz_powm (MP_INT *, const MP_INT *, const MP_INT *, const MP_INT *); -void mpz_powm_ui (MP_INT *, const MP_INT *, unsigned long int, const MP_INT *); -void mpz_pow_ui (MP_INT *, const MP_INT *, unsigned long int); -void mpz_fac_ui (MP_INT *, unsigned long int); -void mpz_gcd (MP_INT *, const MP_INT *, const MP_INT *); -void mpz_gcdext (MP_INT *, MP_INT *, MP_INT *, const MP_INT *, const MP_INT *); -void mpz_neg (MP_INT *, const MP_INT *); -void mpz_com (MP_INT *, const MP_INT *); -void mpz_abs (MP_INT *, const MP_INT *); -int mpz_cmp (const MP_INT *, const MP_INT *); -int mpz_cmp_ui (const MP_INT *, unsigned long int); -int mpz_cmp_si (const MP_INT *, signed long int); -void mpz_mul_2exp (MP_INT *, const MP_INT *, unsigned long int); -void mpz_div_2exp (MP_INT *, const MP_INT *, unsigned long int); -void mpz_mod_2exp (MP_INT *, const MP_INT *, unsigned long int); -void mpz_and (MP_INT *, const MP_INT *, const MP_INT *); -void mpz_ior (MP_INT *, const MP_INT *, const MP_INT *); -void mpz_xor (MP_INT *, const MP_INT *, const MP_INT *); +#if defined (__cplusplus) +extern "C" { +#endif +void *_mpz_realloc _PROTO ((mpz_ptr, mp_size_t)); -#if defined (FILE) || defined (_STDIO_H) || defined (__STDIO_H__) -void mpz_inp_raw (MP_INT *, FILE *); -void mpz_inp_str (MP_INT *, FILE *, int); -void mpz_out_raw (FILE *, const MP_INT *); -void mpz_out_str (FILE *, int, const MP_INT *); +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 -void mpz_array_init (MP_INT [], size_t, mp_size); -void mpz_random (MP_INT *, mp_size); -void mpz_random2 (MP_INT *, mp_size); -size_t mpz_size (const MP_INT *); -size_t mpz_sizeinbase (const MP_INT *, int); +#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; -/**************** Rational (i.e. Q) routines. ****************/ + 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; + } -void mpq_init (MP_RAT *); -void mpq_clear (MP_RAT *); -void mpq_set (MP_RAT *, const MP_RAT *); -void mpq_set_ui (MP_RAT *, unsigned long int, unsigned long int); -void mpq_set_si (MP_RAT *, signed long int, unsigned long int); -void mpq_add (MP_RAT *, const MP_RAT *, const MP_RAT *); -void mpq_sub (MP_RAT *, const MP_RAT *, const MP_RAT *); -void mpq_mul (MP_RAT *, const MP_RAT *, const MP_RAT *); -void mpq_div (MP_RAT *, const MP_RAT *, const MP_RAT *); -void mpq_neg (MP_RAT *, const MP_RAT *); -int mpq_cmp (const MP_RAT *, const MP_RAT *); -void mpq_inv (MP_RAT *, const MP_RAT *); -void mpq_set_num (MP_RAT *, const MP_INT *); -void mpq_set_den (MP_RAT *, const MP_INT *); -void mpq_get_num (MP_INT *, const MP_RAT *); -void mpq_get_den (MP_INT *, const MP_RAT *); + return 1; + } -/************ Low level positive-integer (i.e. N) routines. ************/ + 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; +} -mp_limb mpn_add (mp_ptr, mp_srcptr, mp_size, mp_srcptr, mp_size); -mp_size mpn_sub (mp_ptr, mp_srcptr, mp_size, mp_srcptr, mp_size); -mp_size mpn_mul (mp_ptr, mp_srcptr, mp_size, mp_srcptr, mp_size); -mp_size mpn_div (mp_ptr, mp_ptr, mp_size, mp_srcptr, mp_size); -mp_limb mpn_divmod_1 (mp_ptr, mp_srcptr, mp_size, mp_limb); -mp_limb mpn_mod_1 (mp_srcptr, mp_size, mp_limb); -mp_limb mpn_lshift (mp_ptr, mp_srcptr, mp_size, unsigned int); -mp_size mpn_rshift (mp_ptr, mp_srcptr, mp_size, unsigned int); -mp_size mpn_rshiftci (mp_ptr, mp_srcptr, mp_size, unsigned int, mp_limb); -mp_size mpn_sqrt (mp_ptr, mp_ptr, mp_srcptr, mp_size); -int mpn_cmp (mp_srcptr, mp_srcptr, mp_size); +_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; -#else /* ! __STDC__ */ -void mp_set_memory_functions (); + if (s2_size != 0) + cy_limb = mpn_add_n (res_ptr, s1_ptr, s2_ptr, s2_size); -/**************** Integer (i.e. Z) routines. ****************/ + 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; +} -void mpz_init (); -void mpz_set (); -void mpz_set_ui (); -void mpz_set_si (); -int mpz_set_str (); -void mpz_init_set (); -void mpz_init_set_ui (); -void mpz_init_set_si (); -int mpz_init_set_str (); -unsigned long int mpz_get_ui (); -long int mpz_get_si (); -char * mpz_get_str (); -void mpz_clear (); -void * _mpz_realloc (); -void mpz_add (); -void mpz_add_ui (); -void mpz_sub (); -void mpz_sub_ui (); -void mpz_mul (); -void mpz_mul_ui (); -void mpz_div (); -void mpz_div_ui (); -void mpz_mod (); -void mpz_mod_ui (); -void mpz_divmod (); -void mpz_divmod_ui (); -void mpz_mdiv (); -void mpz_mdiv_ui (); -void mpz_mmod (); -unsigned long int mpz_mmod_ui (); -void mpz_mdivmod (); -unsigned long int mpz_mdivmod_ui (); -void mpz_sqrt (); -void mpz_sqrtrem (); -int mpz_perfect_square_p (); -int mpz_probab_prime_p (); -void mpz_powm (); -void mpz_powm_ui (); -void mpz_pow_ui (); -void mpz_fac_ui (); -void mpz_gcd (); -void mpz_gcdext (); -void mpz_neg (); -void mpz_com (); -void mpz_abs (); -int mpz_cmp (); -int mpz_cmp_ui (); -int mpz_cmp_si (); -void mpz_mul_2exp (); -void mpz_div_2exp (); -void mpz_mod_2exp (); -void mpz_and (); -void mpz_ior (); -void mpz_xor (); +_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; -void mpz_inp_raw (); -void mpz_inp_str (); -void mpz_out_raw (); -void mpz_out_str (); + 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; + } -void mpz_array_init (); -void mpz_random (); -void mpz_random2 (); -size_t mpz_size (); -size_t mpz_sizeinbase (); + return 1; + } -/**************** Rational (i.e. Q) routines. ****************/ + 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; +} -void mpq_init (); -void mpq_clear (); -void mpq_set (); -void mpq_set_ui (); -void mpq_set_si (); -void mpq_add (); -void mpq_sub (); -void mpq_mul (); -void mpq_div (); -void mpq_neg (); -int mpq_cmp (); -void mpq_inv (); -void mpq_set_num (); -void mpq_set_den (); -void mpq_get_num (); -void mpq_get_den (); +_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; -/************ Low level positive-integer (i.e. N) routines. ************/ + if (s2_size != 0) + cy_limb = mpn_sub_n (res_ptr, s1_ptr, s2_ptr, s2_size); -mp_limb mpn_add (); -mp_size mpn_sub (); -mp_size mpn_mul (); -mp_size mpn_div (); -mp_limb mpn_lshift (); -mp_size mpn_rshift (); -mp_size mpn_rshiftci (); -int mpn_cmp (); -#endif /* __STDC__ */ + 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/gnu/lib/libgmp/gmp.info-1 b/gnu/lib/libgmp/gmp.info-1 new file mode 100644 index 000000000000..4ea9373fb73b --- /dev/null +++ b/gnu/lib/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/gnu/lib/libgmp/gmp.info-2 b/gnu/lib/libgmp/gmp.info-2 new file mode 100644 index 000000000000..7a92755c63e1 --- /dev/null +++ b/gnu/lib/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 option +to the compiler, where 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/gnu/lib/libgmp/gmp.info-3 b/gnu/lib/libgmp/gmp.info-3 new file mode 100644 index 000000000000..a3020a79210e --- /dev/null +++ b/gnu/lib/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/gnu/lib/libgmp/gmp.texi b/gnu/lib/libgmp/gmp.texi index 7aaa88bf2ab2..7e6884eab74a 100644 --- a/gnu/lib/libgmp/gmp.texi +++ b/gnu/lib/libgmp/gmp.texi @@ -1,12 +1,21 @@ \input texinfo @c -*-texinfo-*- -@comment %**start of header +@c %**start of header @setfilename gmp.info -@settitle GNU MP 1.3.2 +@settitle GNU MP 2.0.2 @synindex tp fn -@c footnotestyle separate -@c paragraphindent 2 +@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 @@ -19,13 +28,11 @@ @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 integer -and rational number arithmetic. +This file documents GNU MP, a library for arbitrary-precision arithmetic. -This is a draft edition of the documentation, last updated May 20 1993. - -Copyright (C) 1991, 1993 Free Software Foundation, Inc. +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 @@ -49,29 +56,35 @@ except that this permission notice may be stated in a translation approved by the Foundation. @end ifinfo -@setchapternewpage odd +@setchapternewpage on @titlepage @c use the new format for titles @title GNU MP @subtitle The GNU Multiple Precision Arithmetic Library -@subtitle Edition 1.3.2 -@subtitle May 1993 +@subtitle Edition 2.0.2 +@subtitle June 1996 -@author by Torbj@"orn Granlund +@author by Torbj@"orn Granlund, TMG Datakonsult -@comment Include the Distribution inside the titlepage so +@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 Free Software Foundation, Inc. +Copyright @copyright{} 1991, 1993, 1994, 1995, 1996 Free Software Foundation, Inc. @sp 2 Published by the Free Software Foundation @* -675 Massachusetts Avenue, @* -Cambridge, MA 02139 USA @* +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 @@ -87,245 +100,483 @@ 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. -* Intro:: Introduction to GMP. -* Nomenclature:: Terminology and basic data types. -* Initialization:: Initialization of multi-precision number objects. -* Integer Functions:: Functions for arithmetic on signed integers. +* 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. -* Low-level Functions:: Fast functions for natural numbers. -* BSD Compatible Functions:: All functions found in BSD MP (somewhat faster). -* Miscellaneous Functions:: Functions that do particular things. -* Custom Allocation:: How to customize the internal allocation. -* Reporting Bugs:: Help us to improve this library. +* 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, Intro, Top, Top +@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 +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 +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 GMP 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 +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 GMP 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 +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 GMP library are found in -the General Public License that accompany the source code.@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 Intro, Initialization, Copying, Top +@node Introduction to MP, Installing MP, Copying, Top @comment node-name, next, previous, up -@chapter Introduction to MP -@cindex Introduction -@cindex Overview +@chapter Introduction to GNU MP -GNU MP is a portable library for arbitrary precision integer and -rational number arithmetic.@footnote{The limit of the precision is set by the -available memory in your computer.} It aims to provide the fastest -possible arithmetic for all applications that need more than two words -of integer precision. -Most often, applications tend to use just a few words of precision; -but some applications may need thousands of words. GNU MP is designed -to give good performance for both kinds of applications, by choosing -algorithms based on the sizes of the operands. +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. -There are five groups of functions in the MP library: +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 -Functions for signed integer arithmetic, with names -beginning with @code{mpz_}. +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_}. +@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 compatible with Berkeley MP, such as @code{itom}, @code{madd}, -and @code{mult}. +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 -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_}. +Functions compatible with Berkeley MP, such as @code{itom}, @code{madd}, and +@code{mult}. The associated type is @code{MINT}. @item -Miscellaneous functions. +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.) Multi-precision numbers, whether -output or input, are always passed as addresses to the declared type. +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.) -@menu -* Nomenclature:: -* Thanks:: -@end menu +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}. -@node Nomenclature, Thanks, Intro, Intro +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 -@section Nomenclature and Data Types -@cindex nomenclature +@chapter Reporting Bugs +@cindex Reporting bugs -@cindex integer -@tindex @code{MP_INT} -In this manual, @dfn{integer} means a multiple precision integer, as -used in the MP package. The C data type for such integers is -@code{MP_INT}. For example: +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. -@example -MP_INT sum; +There are a few things you should think about when you put your bug report +together. -struct foo @{ MP_INT x, y; @}; +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. -MP_INT vec[20]; -@end example +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. -@cindex rational number -@tindex @code{MP_RAT} -@dfn{Rational number} means a multiple precision fraction. The C data -type for these fractions is @code{MP_RAT}. For example: +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}. -@example -MP_RAT quotient; -@end example +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). -@cindex limb -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 bits. +Send your bug report to: @samp{bug-gmp@@prep.ai.mit.edu}. -@node Thanks,, Nomenclature, Intro -@comment node-name, next, previous, up -@section Thanks +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. -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 this manual, Brian Beuning and Doug Lea for their -testing of various versions of the library, and Joachim Hollman for -his many valuable suggestions. -Special thanks to Brian Beuning, he has shaked out many bugs from early -versions of the code! - -John Amanatides of York University in Canada contributed the function -@code{mpz_probab_prime_p}. - -@node Initialization, Integer Functions, Intro, Top -@comment node-name, next, previous, up -@chapter Initialization - -Before you can use a variable or object of type @code{MP_INT} or -@code{MP_RAT}, you must initialize it. This fills in the components -that point to dynamically allocated space for the limbs of the number. - -When you are finished using the object, you should clear out the object. -This frees the dynamic space that it points to, so the space can be used -again. - -Once you have initialized the object, you need not be concerned about -allocating additional space. The functions in the MP package -automatically allocate additional space when the object does not already -have enough space. They do not, however, reduce the space in use when a -smaller number is stored in the object. Most of the time, this policy -is best, since it avoids frequent re-allocation. If you want to reduce -the space in an object to the minimum needed, you can do -@code{_mpz_realloc (&@var{object}, mpz_size (&@var{object}))}. - -The functions to initialize numbers are @code{mpz_init} (for @code{MP_INT}) and -@code{mpq_init} (for @code{MP_RAT}). - -@code{mpz_init} allocates space for the limbs, and stores a pointer -to that space in the @code{MP_INT} object. It also stores the value 0 -in the object. - -In the same manner, @code{mpq_init} allocates space for the numerator -and denominator limbs, and stores pointers to these spaces in the @code{MP_RAT} -object. - -To clear out a number object, use @code{mpz_clear} and @code{mpq_clear}, -respectively. - -Here is an example of use: - -@example -@{ - MP_INT temp; - mpz_init (&temp); - - @dots{} @r{store and read values in @code{temp} zero or more times} @dots{} - - mpz_clear (&temp): -@} -@end example - -You might be tempted to copy an integer from one object to another like -this: - -@example -MP_INT x, y; - -x = y; -@end example - -Although valid C, @strong{this is an error.} Rather than copying the -integer value from @code{y} to @code{x} it will make the two variables -share storage. Subsequent assignments to one variable would change the -other mysteriously. And if you were to clear out both variables -subsequently, you would confuse @code{malloc} and cause your program to -crash. - -To copy the value properly, you must use the function @code{mpz_set}. -(@pxref{Assigning Integers}) - -@node Integer Functions, Rational Number Functions, Initialization, Top +@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_}. -The integer functions use arguments and values of type -pointer-to-@code{MP_INT} (@pxref{Nomenclature}). The type @code{MP_INT} -is a structure, but applications should not refer directly to its -components. Include the header @file{gmp.h} to get the definition of -@code{MP_INT}. +Arbitrary precision integers are stored in objects of type @code{mpz_t}. @menu * Initializing Integers:: @@ -333,39 +584,38 @@ components. Include the header @file{gmp.h} to get the definition of * Simultaneous Integer Init & Assign:: * Converting Integers:: * Integer Arithmetic:: -* Logic on Integers:: +* 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 Initializing Integer Objects +@section Initialization and Assignment Functions -Most of the functions for integer arithmetic assume that the output is -stored in an object already initialized. For example, @code{mpz_add} -stores the result of addition (@pxref{Integer Arithmetic}). Thus, you -must initialize the object before storing the first value in it. You -can do this separately by calling the function @code{mpz_init}. +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 (MP_INT *@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. +@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 @{ - MP_INT integ; - mpz_init (&integ); + mpz_t integ; + mpz_init (integ); @dots{} - mpz_add (&integ, @dots{}); + mpz_add (integ, @dots{}); @dots{} - mpz_sub (&integ, @dots{}); + mpz_sub (integ, @dots{}); - /* Unless you are now exiting the program, do ... */ - mpz_clear (&integ); + /* Unless the program is about to exit, do ... */ + mpz_clear (integ); @} @end example @@ -373,59 +623,57 @@ Here is an example of using @code{mpz_init}: As you can see, you can store new values any number of times, once an object is initialized. -@deftypefun void mpz_clear (MP_INT *@var{integer}) +@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{MP_INT} variables when you are done with them. +function for all @code{mpz_t} variables when you are done with them. @end deftypefun -@deftypefun {void *} _mpz_realloc (MP_INT *@var{integer}, mp_size @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. +@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 (MP_INT @var{integer_array}[], size_t @var{array_size}, mp_size @var{fixed_num_limbs}) +@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 @var{fixed_num_limbs}. This function is useful for decreasing the -working set for some algorithms that use large integer arrays. If the -fixed space will be insufficient for storing the result of a subsequent -calculation, the result is unpredictable. +@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. -There is no way to de-allocate the storage allocated by this function. Don't -call @code{mpz_clear}! +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 Integer Assignment Functions +@subsection Assignment Functions @cindex Integer assignment functions These functions assign new values to already initialized integers (@pxref{Initializing Integers}). -@deftypefun void mpz_set (MP_INT *@var{dest_integer}, MP_INT *@var{src_integer}) -Assign @var{dest_integer} from @var{src_integer}. +@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 void mpz_set_ui (MP_INT *@var{integer}, unsigned long int @var{initial_value}) -Set the value of @var{integer} from @var{initial_value}. -@end deftypefun - -@deftypefun void mpz_set_si (MP_INT *@var{integer}, signed long int @var{initial_value}) -Set the value of @var{integer} from @var{initial_value}. -@end deftypefun - -@deftypefun int mpz_set_str (MP_INT *@var{integer}, char *@var{initial_value}, int @var{base}) -Set the value of @var{integer} from @var{initial_value}, -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. +@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. @@ -435,577 +683,1750 @@ number in base @var{base}. Otherwise it returns @minus{}1. @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, combined +@cindex Initialization and assignment functions -For your convenience, MP provides a parallel series of -initialize-and-set arithmetic functions which initialize the output and -then store the value there. These functions' names have the form -@code{mpz_init_set@dots{}}. +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 @{ - MP_INT integ; - mpz_init_set_str (&integ, "3141592653589793238462643383279502884", 10); + mpz_t pie; + mpz_init_set_str (pie, "3141592653589793238462643383279502884", 10); @dots{} - mpz_sub (&integ, @dots{}); - - mpz_clear (&integ); + mpz_sub (pie, @dots{}); + @dots{} + mpz_clear (pie); @} @end example -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! +@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 (MP_INT *@var{dest_integer}, MP_INT *@var{src_integer}) -Initialize @var{dest_integer} with limb space and set the initial numeric -value from @var{src_integer}. +@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 void mpz_init_set_ui (MP_INT *@var{dest_integer}, unsigned long int @var{src_ulong}) -Initialize @var{dest_integer} with limb space and set the initial numeric -value from @var{src_ulong}. -@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). -@deftypefun void mpz_init_set_si (MP_INT *@var{dest_integer}, signed long int @var{src_slong}) -Initialize @var{dest_integer} with limb space and set the initial numeric -value from @var{src_slong}. -@end deftypefun - -@deftypefun int mpz_init_set_str (MP_INT *@var{dest_integer}, char *@var{src_cstring}, int @var{base}) -Initialize @var{dest_integer} with limb space and set the initial -numeric value from @var{src_cstring}, a '\0'-terminated C string in base -@var{base}. The base may vary from 2 to 36. There may be white space -in the string. - -If the string is a correct base @var{base} number, the function returns -0; if an error occurs it returns @minus{}1. @var{dest_integer} is -initialized even if an error occurs. (I.e., you have to call mpz_clear -for it.) +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 -@deftypefun {unsigned long int} mpz_get_ui (MP_INT *@var{src_integer}) -Return the least significant limb from @var{src_integer}. This -function together with @* -@code{mpz_div_2exp(@dots{}, @var{src_integer}, CHAR_BIT*sizeof(unsigned -long int))} can be used to extract the limbs of an integer efficiently. +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 (MP_INT *@var{src_integer}) -If @var{src_integer} fits into a @code{signed long int} return the value -of @var{src_integer}. Otherwise return the least significant bits of -@var{src_integer}, with the same sign as @var{src_integer}. +@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 {char *} mpz_get_str (char *@var{string}, int @var{base}, MP_INT *@var{integer}) -Convert @var{integer} to a '\0'-terminated C string in @var{string}, -using base @var{base}. The base may vary from 2 to 36. If @var{string} -is NULL, space for the string is allocated using the default allocation -function. +@deftypefun double mpz_get_d (mpz_t @var{op}) +Convert @var{op} to a double. +@end deftypefun -If @var{string} 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{string}, use @code{mpz_sizeinbase (@var{integer}, -@var{base}) + 2}. The "+ 2" is for a possible minus sign, and for the -terminating null character. (@pxref{Miscellaneous Functions}). +@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. -This function returns a pointer to the result string. +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, Logic on Integers, Converting Integers, Integer Functions +@node Integer Arithmetic, Comparison Functions, Converting Integers, Integer Functions @comment node-name, next, previous, up -@section Integer Arithmetic Functions +@section Arithmetic Functions @cindex Integer arithmetic functions @cindex Arithmetic functions -@deftypefun void mpz_add (MP_INT *@var{sum}, MP_INT *@var{addend1}, MP_INT *@var{addend2}) -@end deftypefun -@deftypefun void mpz_add_ui (MP_INT *@var{sum}, MP_INT *@var{addend1}, unsigned long int @var{addend2}) -Set @var{sum} to @var{addend1} + @var{addend2}. -@end deftypefun - -@deftypefun void mpz_sub (MP_INT *@var{difference}, MP_INT *@var{minuend}, MP_INT *@var{subtrahend}) -@end deftypefun -@deftypefun void mpz_sub_ui (MP_INT *@var{difference}, MP_INT *@var{minuend}, unsigned long int @var{subtrahend}) -Set @var{difference} to @var{minuend} @minus{} @var{subtrahend}. -@end deftypefun - -@deftypefun void mpz_mul (MP_INT *@var{product}, MP_INT *@var{multiplicator}, MP_INT *@var{multiplicand}) -@end deftypefun -@deftypefun void mpz_mul_ui (MP_INT *@var{product}, MP_INT *@var{multiplicator}, unsigned long int @var{multiplicand}) -Set @var{product} to @var{multiplicator} times @var{multiplicand}. -@end deftypefun - -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 powm 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 mpz_div (MP_INT *@var{quotient}, MP_INT *@var{dividend}, MP_INT *@var{divisor}) -@end deftypefun -@deftypefun void mpz_div_ui (MP_INT *@var{quotient}, MP_INT *@var{dividend}, unsigned long int @var{divisor}) -Set @var{quotient} to @var{dividend} / @var{divisor}. The quotient is -rounded towards 0. -@end deftypefun - -@deftypefun void mpz_mod (MP_INT *@var{remainder}, MP_INT *@var{divdend}, MP_INT *@var{divisor}) -@end deftypefun -@deftypefun void mpz_mod_ui (MP_INT *@var{remainder}, MP_INT *@var{divdend}, unsigned long int @var{divisor}) -Divide @var{dividend} and @var{divisor} and put the remainder in -@var{remainder}. The remainder has the same sign as the dividend, and -its absolute value is less than the absolute value of the divisor. -@end deftypefun - -@deftypefun void mpz_divmod (MP_INT *@var{quotient}, MP_INT *@var{remainder}, MP_INT *@var{dividend}, MP_INT *@var{divisor}) -@end deftypefun -@deftypefun void mpz_divmod_ui (MP_INT *@var{quotient}, MP_INT *@var{remainder}, MP_INT *@var{dividend}, unsigned long int @var{divisor}) -Divide @var{dividend} and @var{divisor} and put the quotient in -@var{quotient} and the remainder in @var{remainder}. The quotient is -rounded towards 0. The remainder has the same sign as the dividend, -and its absolute value is less than the absolute value of the divisor. - -If @var{quotient} and @var{remainder} are the same variable, the results -are not defined. -@end deftypefun - -@deftypefun void mpz_mdiv (MP_INT *@var{quotient}, MP_INT *@var{dividend}, MP_INT *@var{divisor}) -@end deftypefun -@deftypefun void mpz_mdiv_ui (MP_INT *@var{quotient}, MP_INT *@var{dividend}, unsigned long int @var{divisor}) -Set @var{quotient} to @var{dividend} / @var{divisor}. The quotient is -rounded towards @minus{}infinity. -@end deftypefun - -@deftypefun void mpz_mmod (MP_INT *@var{remainder}, MP_INT *@var{divdend}, MP_INT *@var{divisor}) -@end deftypefun -@deftypefun {unsigned long int} mpz_mmod_ui (MP_INT *@var{remainder}, MP_INT *@var{divdend}, unsigned long int @var{divisor}) -Divide @var{dividend} and @var{divisor} and put the remainder in -@var{remainder}. The remainder is always positive, and its value is -less than the value of the divisor. - -For @code{mpz_mmod_ui} the remainder is returned, and if @var{remainder} is -not NULL, also stored there. -@end deftypefun - -@deftypefun void mpz_mdivmod (MP_INT *@var{quotient}, MP_INT *@var{remainder}, MP_INT *@var{dividend}, MP_INT *@var{divisor}) -@end deftypefun -@deftypefun {unsigned long int} mpz_mdivmod_ui (MP_INT *@var{quotient}, MP_INT *@var{remainder}, MP_INT *@var{dividend}, unsigned long int @var{divisor}) -Divide @var{dividend} and @var{divisor} and put the quotient in -@var{quotient} and the remainder in @var{remainder}. The quotient is -rounded towards @minus{}infinity. The remainder is always positive, and its -value is less than the value of the divisor. - -For @code{mpz_mdivmod_ui} the remainder is small enough to fit in an -@code{unsigned long int}, and is therefore returned. If @var{remainder} -is not NULL, the remainder is also stored there. - -If @var{quotient} and @var{remainder} are the same variable, the results -are not defined. -@end deftypefun - -@deftypefun void mpz_sqrt (MP_INT *@var{root}, MP_INT *@var{operand}) -Set @var{root} to the square root of @var{operand}. The result is -rounded towards zero. -@end deftypefun - -@deftypefun void mpz_sqrtrem (MP_INT *@var{root}, MP_INT *@var{remainder}, MP_INT *@var{operand}) -Set @var{root} to the square root of @var{operand}, as with -@code{mpz_sqrt}. Set @var{remainder} to +@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 -@var{operand}@minus{}@var{root}*@var{root}, +Set @var{rop} to @var{op1} + @var{op2}. @end ifinfo @iftex @tex -$operand - root^2$, +Set @var{rop} to $@var{op1} + @var{op2}$. @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 -not defined. @end deftypefun -@deftypefun int mpz_perfect_square_p (MP_INT *@var{square}) -Return non-zero if @var{square} is perfect, i.e@. if the square root of -@var{square} is integral. Return zero otherwise. +@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 int mpz_probab_prime_p (MP_INT *@var{n}, int @var{reps}) -An implementation of the probabilistic primality test found in Knuth's -Seminumerical Algorithms book. If the function -@code{mpz_probab_prime_p(@var{n}, @var{reps})} returns 0 then @var{n} is -not prime. If it returns 1, then @var{n} is `probably' prime. The -probability of a false positive is (1/4)**@var{reps}, where @var{reps} -is the number of internal passes of the probabilistic algorithm. Knuth -indicates that 25 passes are reasonable. +@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_powm (MP_INT *@var{res}, MP_INT *@var{base}, MP_INT *@var{exp}, MP_INT *@var{mod}) -@end deftypefun -@deftypefun void mpz_powm_ui (MP_INT *@var{res}, MP_INT *@var{base}, unsigned long int @var{exp}, MP_INT *@var{mod}) -Set @var{res} to (@var{base} raised to @var{exp}) modulo @var{mod}. -If @var{exp} is negative, the result is undefined. +@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_pow_ui (MP_INT *@var{res}, MP_INT *@var{base}, unsigned long int @var{exp}) -Set @var{res} to @var{base} raised to @var{exp}. +@deftypefun void mpz_neg (mpz_t @var{rop}, mpz_t @var{op}) +Set @var{rop} to @minus{}@var{op}. @end deftypefun -@deftypefun void mpz_fac_ui (MP_INT *@var{res}, unsigned long int @var{n}) -Set @var{res} @var{n}!, the factorial of n. +@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_gcd (MP_INT *@var{res}, MP_INT *@var{operand1}, MP_INT *@var{operand2}) -Set @var{res} to the greatest common divisor of @var{operand1} and -@var{operand2}. +@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 -@deftypefun void mpz_gcdext (MP_INT *@var{g}, MP_INT *@var{s}, MP_INT *@var{t}, MP_INT *@var{a}, MP_INT *@var{b}) +@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 void mpz_neg (MP_INT *@var{negated_operand}, MP_INT *@var{operand}) -Set @var{negated_operand} to @minus{}@var{operand}. +@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 void mpz_abs (MP_INT *@var{positive_operand}, MP_INT *@var{signed_operand}) -Set @var{positive_operand} to the absolute value of @var{signed_operand}. +@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 -@deftypefun int mpz_cmp (MP_INT *@var{operand1}, MP_INT *@var{operand2}) -@end deftypefun -@deftypefun int mpz_cmp_ui (MP_INT *@var{operand1}, unsigned long int @var{operand2}) -@end deftypefun -@deftypefun int mpz_cmp_si (MP_INT *@var{operand1}, signed long int @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 mpz_mul_2exp (MP_INT *@var{product}, MP_INT *@var{multiplicator}, unsigned long int @var{exponent_of_2}) -Set @var{product} to @var{multiplicator} times 2 raised to -@var{exponent_of_2}. This operation can also be defined as a left shift, -@var{exponent_of_2} steps. -@end deftypefun - -@deftypefun void mpz_div_2exp (MP_INT *@var{quotient}, MP_INT *@var{dividend}, unsigned long int @var{exponent_of_2}) -Set @var{quotient} to @var{dividend} divided by 2 raised to -@var{exponent_of_2}. This operation can also be defined as a right -shift, @var{exponent_of_2} steps, but unlike the >> operator in -C, the result is rounded towards 0. -@end deftypefun - -@deftypefun void mpz_mod_2exp (MP_INT *@var{remainder}, MP_INT *@var{dividend}, unsigned long int @var{exponent_of_2}) -Set @var{remainder} to @var{dividend} mod (2 raised to -@var{exponent_of_2}). The sign of @var{remainder} will have the same sign -as @var{dividend}. - -This operation can also be defined as a masking of the -@var{exponent_of_2} least significant bits. -@end deftypefun - -@node Logic on Integers, I/O of Integers, Integer Arithmetic, Integer Functions +@need 2000 +@node Comparison Functions, Integer Logic and Bit Fiddling, Integer Arithmetic, Integer Functions @comment node-name, next, previous, up -@section Logical Functions +@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 -@deftypefun void mpz_and (MP_INT *@var{conjunction}, MP_INT *@var{operand1}, MP_INT *@var{operand2}) -Set @var{conjunction} to @var{operand1} logical-and @var{operand2}. +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 (MP_INT *@var{disjunction}, MP_INT *@var{operand1}, MP_INT *@var{operand2}) -Set @var{disjunction} to @var{operand1} inclusive-or @var{operand2}. +@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 -@deftypefun void mpz_xor (MP_INT *@var{disjunction}, MP_INT *@var{operand1}, MP_INT *@var{operand2}) -Set @var{disjunction} to @var{operand1} exclusive-or @var{operand2}. +@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 -This function is missing in the current release. +@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 void mpz_com (MP_INT *@var{complemented_operand}, MP_INT *@var{operand}) -Set @var{complemented_operand} to the one's complement of @var{operand}. +@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 -@node I/O of Integers,, Logic on Integers, Integer Functions +@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 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 standard I/O stream, and functions for -output conversion. +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. -@deftypefun void mpz_inp_raw (MP_INT *@var{integer}, FILE *@var{stream}) -Input from standard I/O stream @var{stream} in the format written by -@code{mpz_out_raw}, and put the result in @var{integer}. +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 void mpz_inp_str (MP_INT *@var{integer}, FILE *@var{stream}, int @var{base}) -Input a string in base @var{base} from standard I/O stream @var{stream}, -and put the read integer in @var{integer}. 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, +@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 -@deftypefun void mpz_out_raw (FILE *@var{stream}, MP_INT *@var{integer}) -Output @var{integer} on standard I/O 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. +@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_out_str (FILE *@var{stream}, int @var{base}, MP_INT *@var{integer}) -Output @var{integer} on standard I/O stream @var{stream}, as a string of -digits in base @var{base}. The base may vary from 2 to 36. +@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, Low-level Functions, Integer Functions, Top +@node Rational Number Functions, Floating-point Functions, Integer Functions, Top @comment node-name, next, previous, up @chapter Rational Number Functions @cindex Rational number functions -All rational arithmetic functions canonicalize the result, so that the -denominator and the numerator have no common factors. Zero has the -unique representation 0/1. +This chapter describes the MP functions for performing arithmetic on rational +numbers. These functions start with the prefix @code{mpq_}. -The set of functions is quite small. Maybe it will be extended in a -future release. +Rational numbers are stored in objects of type @code{mpq_t}. -@deftypefun void mpq_init (MP_RAT *@var{dest_rational}) -Initialize @var{dest_rational} with limb space and set the initial -numeric value 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. +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 -@deftypefun void mpq_clear (MP_RAT *@var{rational_number}) -Free the limb space occupied by @var{rational_number}. Make sure to -call this function for all @code{MP_RAT} variables when you are done -with them. +@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_set (MP_RAT *@var{dest_rational}, MP_RAT *@var{src_rational}) -Assign @var{dest_rational} from @var{src_rational}. +@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_ui (MP_RAT *@var{rational_number}, unsigned long int @var{numerator}, unsigned long int @var{denominator}) -Set the value of @var{rational_number} to -@var{numerator}/@var{denominator}. If @var{numerator} and -@var{denominator} have common factors, they are divided out before -@var{rational_number} is assigned. +@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_si (MP_RAT *@var{rational_number}, signed long int @var{numerator}, unsigned long int @var{denominator}) -Like @code{mpq_set_ui}, but @var{numerator} is signed. +@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 -@deftypefun void mpq_add (MP_RAT *@var{sum}, MP_RAT *@var{addend1}, MP_RAT *@var{addend2}) +@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 (MP_RAT *@var{difference}, MP_RAT *@var{minuend}, MP_RAT *@var{subtrahend}) +@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 (MP_RAT *@var{product}, MP_RAT *@var{multiplicator}, MP_RAT *@var{multiplicand}) -Set @var{product} to @var{multiplicator} * @var{multiplicand} +@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 (MP_RAT *@var{quotient}, MP_RAT *@var{dividend}, MP_RAT *@var{divisor}) -Set @var{quotient} to @var{dividend} / @var{divisor}. +@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 (MP_RAT *@var{negated_operand}, MP_RAT *@var{operand}) +@deftypefun void mpq_neg (mpq_t @var{negated_operand}, mpq_t @var{operand}) Set @var{negated_operand} to @minus{}@var{operand}. @end deftypefun -@deftypefun int mpq_cmp (MP_RAT *@var{operand1}, MP_RAT *@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}. +@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 -@deftypefun void mpq_inv (MP_RAT *@var{inverted_number}, MP_RAT *@var{number}) -Invert @var{number} by swapping the numerator and denominator. If the -new denominator becomes zero, this routine will divide by zero. +@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 -@deftypefun void mpq_set_num (MP_RAT *@var{rational_number}, MP_INT *@var{numerator}) -Make @var{numerator} become the numerator of @var{rational_number} by -copying. +@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 -@deftypefun void mpq_set_den (MP_RAT *@var{rational_number}, MP_INT *@var{denominator}) -Make @var{denominator} become the denominator of @var{rational_number} -by copying. If @var{denominator} < 0 the denominator of -@var{rational_number} is set to the absolute value of @var{denominator}, -and the sign of the numerator of @var{rational_number} is changed. +@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 -@deftypefun void mpq_get_num (MP_INT *@var{numerator}, MP_RAT *@var{rational_number}) -Copy the numerator of @var{rational_number} to the integer -@var{numerator}, to prepare for integer operations on the numerator. +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_get_den (MP_INT *@var{denominator}, MP_RAT *@var{rational_number}) -Copy the denominator of @var{rational_number} to the integer -@var{denominator}, to prepare for integer operations on the denominator. +@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 Low-level Functions, BSD Compatible Functions, Rational Number Functions, Top +@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 +@c -@strong{The next release of the GNU MP library (2.0) will include -changes to some mpn functions. Programs that use these functions -according to the descriptions below will therefore not work with the -next release.} +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. -The low-level function layer is designed to be as fast as possible, -@strong{not} to provide a coherent calling interface. The different -functions have similar interfaces, but there are variations that might -be confusing. 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. -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 responsability 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. -With this way of specifying source 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. -All these functions require that the operands are normalized in the -sense that the most significant limb must be non-zero. (A future release -of might drop this requirement.) +The @code{mpn} functions is the base for the implementation of the @code{mpz_}, +@code{mpf_}, and @code{mpq_} functions. -The low-level layer is the base for the implementation of the -@code{mpz_} and @code{mpq_} layers. - -The code below adds the number beginning at @var{src1_ptr} and the -number beginning at @var{src2_ptr} and writes the sum at @var{dest_ptr}. -A constraint for @code{mpn_add} is that @var{src1_size} must not be -smaller that @var{src2_size}. +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 -mpn_add (dest_ptr, src1_ptr, src1_size, src2_ptr, src2_size) +cy = mpn_add_n (dest_ptr, src1_ptr, src2_ptr, size) @end example -In the description below, a source operand is identified by the pointer -to the least significant limb, and the limb count in braces. +@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_size mpn_add (mp_ptr @var{dest_ptr}, mp_srcptr @var{src1_ptr}, mp_size @var{src1_size}, mp_srcptr @var{src2_ptr}, mp_size @var{src2_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}. Carry-out, either 0 or 1, is returned. +@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_size mpn_sub (mp_ptr @var{dest_ptr}, mp_srcptr @var{src1_ptr}, mp_size @var{src1_size}, mp_srcptr @var{src2_ptr}, mp_size @var{src2_size}) -Subtarct @{@var{src2_ptr}, @var{src2_size}@} from @{@var{src1_ptr}, -@var{src1_size}@}, and write the result to @var{dest_ptr}. +@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. -Return 1 if the minuend < the subtrahend. Otherwise, return the -negative difference between the number of words in the result and the -minuend. I.e@. return 0 if the result has @var{src1_size} words, @minus{}1 if -it has @var{src1_size} @minus{} 1 words, etc. +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 mp_size mpn_mul (mp_ptr @var{dest_ptr}, mp_srcptr @var{src1_ptr}, mp_size @var{src1_size}, mp_srcptr @var{src2_ptr}, mp_size @var{src2_size}) +@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}. The exact -size of the result is returned. +@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. +@var{src2_size}. The destination must be distinct from either input operands. @end deftypefun -@deftypefun mp_size mpn_div (mp_ptr @var{dest_ptr}, mp_ptr @var{src1_ptr}, mp_size @var{src1_size}, mp_srcptr @var{src2_ptr}, mp_size @var{src2_size}) -Divide @{@var{src1_ptr}, @var{src1_size}@} by @{@var{src2_ptr}, -@var{src2_size}@}, and write the quotient to @var{dest_ptr}, and the -remainder to @var{src1_ptr}. +@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}. -Return 0 if the quotient size is at most (@var{src1_size} @minus{} -@var{src2_size}), and 1 if the quotient size is at most (@var{src1_size} -@minus{} @var{src2_size} + 1). The caller has to check the most significant limb -to find out the exact size. +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 most significant bit of the most significant limb of the divisor -has to be set. +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. -This function requires that @var{src1_size} is greater than or equal to -@var{src2_size}. The quotient, pointed to by @var{dest_ptr}, must be -distinct from either input operands. +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 mpn_lshift (mp_ptr @var{dest_ptr}, mp_srcptr @var{src_ptr}, mp_size @var{src_size}, unsigned long int @var{count}) +@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 limb shifted out is returned. +@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, provdied @var{dest_ptr} >= @var{src_ptr}. +function, provided @var{dest_ptr} >= @var{src_ptr}. + +This function is written in assembly for most targets. @end deftypefun -@deftypefun mp_size mpn_rshift (mp_ptr @var{dest_ptr}, mp_srcptr @var{src_ptr}, mp_size @var{src_size}, unsigned long int @var{count}) +@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} 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 size of the result is returned. +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. -Overlaping of the destination space and the source space is allowed in this -function, provdied @var{dest_ptr} <= @var{src_ptr}. +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_size mpn_rshiftci (mp_ptr @var{dest_ptr}, mp_srcptr @var{src_ptr}, mp_size @var{src_size}, unsigned long int @var{count}, mp_limb @var{inlimb}) -Like mpn_rshift, but use @var{inlimb} to feed the least significant end -of the destination. +@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 int mpn_cmp (mp_srcptr @var{src1_ptr}, mp_srcptr @var{src2_ptr}, mp_size @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. +@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, Miscellaneous Functions, Low-level Functions, Top +@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 @@ -1013,38 +2434,38 @@ and a negative value if src1 < src2. 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. +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}. +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}. -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 -option to the compiler, where is the directory where you have GNU -@file{mp.h}. +@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 option to the compiler, +where 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. +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. +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. +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}) @@ -1062,30 +2483,31 @@ Multiply @var{src_1} and @var{src_2} and put the product in @end deftypefun @deftypefun void mdiv (MINT *@var{dividend}, MINT *@var{divisor}, MINT *@var{quotient}, MINT *@var{remainder}) -@end deftypefun -@deftypefun 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. +@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 this function return a remainder whose sign is -inverted if the divisor is negative. Such a definition makes little -sense from a mathematical point of view. GNU MP might be considered -incompatible with the traditional MP in this respect. +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}) -Set @var{root} to the square root of @var{operand}, as with -@code{mpz_sqrt}. Set @var{remainder} to @ifinfo -@var{operand}-@var{root}*@var{root}, +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 -$operand - root^2$, +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). +(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}) @@ -1108,172 +2530,156 @@ Compare @var{operand1} and @var{operand2}. Return a positive value if @end deftypefun @deftypefun void min (MINT *@var{dest}) -Input a decimal string from stdin, and put the read integer in -@var{dest}. SPC and TAB are allowed in the number string, and are -ignored. +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 stdout, as a decimal string. Also output a newline. +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. (@xref{Initialization}, -for an explanation of the memory allocation in MP). +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}.} +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 Miscellaneous Functions, Custom Allocation, BSD Compatible Functions, Top +@node Custom Allocation, Contributors, BSD Compatible Functions, Top @comment node-name, next, previous, up -@chapter Miscellaneous Functions -@cindex Miscellaneous functions +@chapter Custom Allocation -@deftypefun void mpz_random (MP_INT *@var{random_integer}, mp_size @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. +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 -@deftypefun void mpz_random2 (MP_INT *@var{random_integer}, mp_size @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 bugs. -@end deftypefun - -@deftypefun size_t mpz_size (MP_INT *@var{integer}) -Return the size of @var{integer} measured in number of limbs. If -@var{integer} is zero, the returned value will be zero, if @var{integer} -has one limb, the returned value will be one, etc. -(@xref{Nomenclature}, for an explanation of the concept @dfn{limb}.) -@end deftypefun - -@deftypefun size_t mpz_sizeinbase (MP_INT *@var{integer}, int @var{base}) -Return the size of @var{integer} 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{integer} 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 Custom Allocation, Reporting Bugs, Miscellaneous Functions, Top -@comment node-name, next, previous, up -@section Custom Allocation - -By default, the initialization functions use @code{malloc}, -@code{realloc}, and @code{free} to do their work. If @code{malloc} or -@code{realloc} fails, the MP package terminates execution after a -printing fatal error message on standard error. - -In 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 functions -for allocating and de-allocating memory. Use -@code{mp_set_memory_functions} to do this. - -@findex mp_set_memory_functions -@code{mp_set_memory_functions} has three arguments, -@var{allocate_function}, @var{reallocate_function}, and -@var{deallocate_function}, in that order. If an argument is NULL, -the corresponding default function is retained. - The functions you supply should fit the following declarations: -@table @code -@item void * @var{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. +@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 -@item void * @var{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 the first -@var{old_size} storage units from @var{ptr}. It should also de-allocate the -space at @var{ptr}. +@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 formely returned from -@var{allocate_function} or @var{reallocate_function}, for a -request for @var{old_size} storage units. +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 -@item void @var{deallocate_function} (void *@var{ptr}, size_t @var{size}) +@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 formely returned from -@var{allocate_function} or @var{reallocate_function}, for a -request for @var{size} storage units. -@end table +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.) +(A @dfn{storage unit} is the unit in which the @code{sizeof} operator returns +the size of an object, normally an 8 bit byte.) -@strong{NOTE: call @code{mp_set_memory_functions} only before calling -any other MP functions.} Otherwise, the user-defined allocation -functions may be asked to re-allocate or de-allocate something -previously allocated by the default allocation functions. -@node Reporting Bugs, , Custom Allocation, Top +@node Contributors, References, Custom Allocation, Top @comment node-name, next, previous, up -@chapter Reporting Bugs -@cindex Reporting bugs +@unnumbered Contributors -If you think you have found a bug in the GNU 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. +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. -Please make sure that the bug is really in the GNU MP library. +John Amanatides of York University in Canada contributed the function +@code{mpz_probab_prime_p}. -You have to send us a test case that makes it possible for us to -reproduce the bug. +Paul Zimmermann of Inria sparked the development of GMP 2, with his +comparisons between bignum packages. -You also have to explain what is wrong; if you get a crash, or if the -results printed are not good and in that case, in what way. +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. -Make sure that the bug report includes all information you would -need to fix this kind of bug for someone else. Think twice. +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. -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). +Joachim Hollman was involved in the design of the @code{mpf} interface, and in +the @code{mpz} design revisions for version 2. -Send your bug report to: tege@@gnu.ai.mit.edu. +Bennet Yee contributed the functions @code{mpz_jacobi} and +@code{mpz_legendre}. -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. +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, , , Top +@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, +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 Cummins Publishing Company Inc, 1981. +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, -1993. +Richard M. Stallman, "Using and Porting GCC", Free Software Foundation, +1995. @item -Peter L@. Montgomery, "Modular Multiplication Without Trial Division", +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 diff --git a/gnu/lib/libgmp/insert-double.c b/gnu/lib/libgmp/insert-double.c new file mode 100644 index 000000000000..1ce25718503d --- /dev/null +++ b/gnu/lib/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/gnu/lib/libgmp/install.sh b/gnu/lib/libgmp/install.sh new file mode 100755 index 000000000000..58719246f040 --- /dev/null +++ b/gnu/lib/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/gnu/lib/libgmp/longlong.h b/gnu/lib/libgmp/longlong.h index fd7b4cc064ff..382fcc0db073 100644 --- a/gnu/lib/libgmp/longlong.h +++ b/gnu/lib/libgmp/longlong.h @@ -1,72 +1,87 @@ /* longlong.h -- definitions for mixed size 32/64 bit arithmetic. - Copyright (C) 1991, 1992, 1993 Free Software Foundation, Inc. - This definition 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. +Copyright (C) 1991, 1992, 1993, 1994, 1996 Free Software Foundation, Inc. - This definition 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. +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. - 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., 675 Mass Ave, Cambridge, MA 02139, USA. */ +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. -#ifndef LONG_TYPE_SIZE -#ifdef BITS_PER_LONGINT -#define LONG_TYPE_SIZE BITS_PER_LONGINT -#else -#define LONG_TYPE_SIZE 32 +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 -#endif - -#define __BITS4 (LONG_TYPE_SIZE / 4) -#define __ll_B (1L << (LONG_TYPE_SIZE / 2)) -#define __ll_lowpart(t) ((unsigned long int) (t) % __ll_B) -#define __ll_highpart(t) ((unsigned long int) (t) / __ll_B) /* Define auxiliary asm macros. - 1) umul_ppmm(high_prod, low_prod, multipler, multiplicand) - multiplies two unsigned long integers MULTIPLER and MULTIPLICAND, - and generates a two unsigned word product in HIGH_PROD and - LOW_PROD. + 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 unsigned long integers A and B, - and returns a long long product. This is just a variant of umul_ppmm. + 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 two-word unsigned integer, composed by the - 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. + 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. + 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. This is the number of steps X - needs to be shifted left to set the msb. Undefined for X == 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) add_ssaaaa(high_sum, low_sum, high_addend_1, low_addend_1, - high_addend_2, low_addend_2) adds two two-word unsigned 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. + 6) count_trailing_zeros(count, x) like count_leading_zeros, but counts + from the least significant end. - 7) sub_ddmmss(high_difference, low_difference, high_minuend, - low_minuend, high_subtrahend, low_subtrahend) subtracts two - two-word unsigned 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, + 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, @@ -89,153 +104,211 @@ #define __AND_CLOBBER_CC , "cc" #endif /* __GNUC__ < 2 */ -#if defined (__a29k__) || defined (___AM29K__) +#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" ((unsigned long int)(sh)), \ - "=&r" ((unsigned long int)(sl)) \ - : "%r" ((unsigned long int)(ah)), \ - "rI" ((unsigned long int)(bh)), \ - "%r" ((unsigned long int)(al)), \ - "rI" ((unsigned long int)(bl))) + : "=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" ((unsigned long int)(sh)), \ - "=&r" ((unsigned long int)(sl)) \ - : "r" ((unsigned long int)(ah)), \ - "rI" ((unsigned long int)(bh)), \ - "r" ((unsigned long int)(al)), \ - "rI" ((unsigned long int)(bl))) + : "=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 { \ - unsigned long int __m0 = (m0), __m1 = (m1); \ + USItype __m0 = (m0), __m1 = (m1); \ __asm__ ("multiplu %0,%1,%2" \ - : "=r" ((unsigned long int)(xl)) \ + : "=r" ((USItype)(xl)) \ : "r" (__m0), \ "r" (__m1)); \ __asm__ ("multmu %0,%1,%2" \ - : "=r" ((unsigned long int)(xh)) \ + : "=r" ((USItype)(xh)) \ : "r" (__m0), \ "r" (__m1)); \ } while (0) #define udiv_qrnnd(q, r, n1, n0, d) \ __asm__ ("dividu %0,%3,%4" \ - : "=r" ((unsigned long int)(q)), \ - "=q" ((unsigned long int)(r)) \ - : "1" ((unsigned long int)(n1)), \ - "r" ((unsigned long int)(n0)), \ - "r" ((unsigned long int)(d))) + : "=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" ((unsigned long int)(count)) \ - : "r" ((unsigned long int)(x))) + : "=r" ((USItype)(count)) \ + : "r" ((USItype)(x))) +#define COUNT_LEADING_ZEROS_0 32 #endif /* __a29k__ */ -#if defined (__alpha__) +#if defined (__alpha) && W_TYPE_SIZE == 64 #define umul_ppmm(ph, pl, m0, m1) \ do { \ - unsigned long int __m0 = (m0), __m1 = (m1); \ + UDItype __m0 = (m0), __m1 = (m1); \ __asm__ ("umulh %r1,%2,%0" \ - : "=r" ((unsigned long int) ph) \ + : "=r" ((UDItype) ph) \ : "%rJ" (__m0), \ "rI" (__m1)); \ - (pl) = (unsigned long int) (__m0) * (unsigned long int) (__m1); \ + (pl) = __m0 * __m1; \ } while (0) #define UMUL_TIME 46 -#define UDIV_TIME 500 -#endif +#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__) +#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" ((unsigned long int)(sh)), \ - "=&r" ((unsigned long int)(sl)) \ - : "%r" ((unsigned long int)(ah)), \ - "rI" ((unsigned long int)(bh)), \ - "%r" ((unsigned long int)(al)), \ - "rI" ((unsigned long int)(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" ((unsigned long int)(sh)), \ - "=&r" ((unsigned long int)(sl)) \ - : "r" ((unsigned long int)(ah)), \ - "rI" ((unsigned long int)(bh)), \ - "r" ((unsigned long int)(al)), \ - "rI" ((unsigned long int)(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 (__gmicro__) +#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" ((unsigned long int)(sh)), \ - "=&g" ((unsigned long int)(sl)) \ - : "%0" ((unsigned long int)(ah)), \ - "g" ((unsigned long int)(bh)), \ - "%1" ((unsigned long int)(al)), \ - "g" ((unsigned long int)(bl))) + : "=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" ((unsigned long int)(sh)), \ - "=&g" ((unsigned long int)(sl)) \ - : "0" ((unsigned long int)(ah)), \ - "g" ((unsigned long int)(bh)), \ - "1" ((unsigned long int)(al)), \ - "g" ((unsigned long int)(bl))) + : "=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" ((unsigned long int)(ph)), \ - "=r" ((unsigned long int)(pl)) \ - : "%0" ((unsigned long int)(m0)), \ - "g" ((unsigned long int)(m1))) + : "=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" ((unsigned long int)(q)), \ - "=r" ((unsigned long int)(r)) \ - : "1" ((unsigned long int)(nh)), \ - "0" ((unsigned long int)(nl)), \ - "g" ((unsigned long int)(d))) + : "=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" ((unsigned long int)(x)), \ - "0" (0UL)) + : "g" ((USItype)(x)), \ + "0" ((USItype)0)) #endif -#if defined (__hppa) +#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" ((unsigned long int)(sh)), \ - "=&r" ((unsigned long int)(sl)) \ - : "%rM" ((unsigned long int)(ah)), \ - "rM" ((unsigned long int)(bh)), \ - "%rM" ((unsigned long int)(al)), \ - "rM" ((unsigned long int)(bl))) + : "=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" ((unsigned long int)(sh)), \ - "=&r" ((unsigned long int)(sl)) \ - : "rM" ((unsigned long int)(ah)), \ - "rM" ((unsigned long int)(bh)), \ - "rM" ((unsigned long int)(al)), \ - "rM" ((unsigned long int)(bl))) + : "=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 {long long int __ll; \ - struct {unsigned long int __h, __l;} __i; \ + union {UDItype __ll; \ + struct {USItype __h, __l;} __i; \ } __xx; \ __asm__ ("xmpyu %1,%2,%0" \ - : "=x" (__xx.__ll) \ - : "x" ((unsigned long int)(u)), \ - "x" ((unsigned long int)(v))); \ + : "=*f" (__xx.__ll) \ + : "*f" ((USItype)(u)), \ + "*f" ((USItype)(v))); \ (wh) = __xx.__i.__h; \ (wl) = __xx.__i.__l; \ } while (0) @@ -245,9 +318,17 @@ #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 { \ - unsigned long int __tmp; \ + USItype __tmp; \ __asm__ ( \ "ldi 1,%0 extru,= %1,15,16,%%r0 ; Bits 31..16 zero? @@ -266,407 +347,566 @@ 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__) +#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" ((unsigned long int)(sh)), \ - "=&r" ((unsigned long int)(sl)) \ - : "%0" ((unsigned long int)(ah)), \ - "g" ((unsigned long int)(bh)), \ - "%1" ((unsigned long int)(al)), \ - "g" ((unsigned long int)(bl))) + : "=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" ((unsigned long int)(sh)), \ - "=&r" ((unsigned long int)(sl)) \ - : "0" ((unsigned long int)(ah)), \ - "g" ((unsigned long int)(bh)), \ - "1" ((unsigned long int)(al)), \ - "g" ((unsigned long int)(bl))) + : "=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" ((unsigned long int)(w0)), \ - "=d" ((unsigned long int)(w1)) \ - : "%0" ((unsigned long int)(u)), \ - "rm" ((unsigned long int)(v))) + : "=a" ((USItype)(w0)), \ + "=d" ((USItype)(w1)) \ + : "%0" ((USItype)(u)), \ + "rm" ((USItype)(v))) #define udiv_qrnnd(q, r, n1, n0, d) \ __asm__ ("divl %4" \ - : "=a" ((unsigned long int)(q)), \ - "=d" ((unsigned long int)(r)) \ - : "0" ((unsigned long int)(n0)), \ - "1" ((unsigned long int)(n1)), \ - "rm" ((unsigned long int)(d))) + : "=a" ((USItype)(q)), \ + "=d" ((USItype)(r)) \ + : "0" ((USItype)(n0)), \ + "1" ((USItype)(n1)), \ + "rm" ((USItype)(d))) #define count_leading_zeros(count, x) \ do { \ - unsigned long int __cbtmp; \ + USItype __cbtmp; \ __asm__ ("bsrl %1,%0" \ - : "=r" (__cbtmp) : "rm" ((unsigned long int)(x))); \ + : "=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__) -#if 0 -/* Make sure these patterns really improve the code before - switching them on. */ -#define add_ssaaaa(sh, sl, ah, al, bh, bl) \ - do { \ - union \ - { \ - long long int ll; \ - struct {unsigned long int l, h;} i; \ - } __a, __b, __s; \ - __a.i.l = (al); __a.i.h = (ah); \ - __b.i.l = (bl); __b.i.h = (bh); \ - __asm__ ("fiadd.dd %1,%2,%0" \ - : "=f" (__s.ll) \ - : "%f" (__a.ll), "f" (__b.ll)); \ - (sh) = __s.i.h; (sl) = __s.i.l; \ - } while (0) -#define sub_ddmmss(sh, sl, ah, al, bh, bl) \ - do { \ - union \ - { \ - long long int ll; \ - struct {unsigned long int l, h;} i; \ - } __a, __b, __s; \ - __a.i.l = (al); __a.i.h = (ah); \ - __b.i.l = (bl); __b.i.h = (bh); \ - __asm__ ("fisub.dd %1,%2,%0" \ - : "=f" (__s.ll) \ - : "%f" (__a.ll), "f" (__b.ll)); \ - (sh) = __s.i.h; (sl) = __s.i.l; \ - } while (0) -#endif -#endif /* __i860__ */ +#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__) +#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 {long long int __ll; \ - struct {unsigned long int __l, __h;} __i; \ + ({union {UDItype __ll; \ + struct {USItype __l, __h;} __i; \ } __xx; \ __asm__ ("emul %2,%1,%0" \ : "=d" (__xx.__ll) \ - : "%dI" ((unsigned long int)(u)), \ - "dI" ((unsigned long int)(v))); \ + : "%dI" ((USItype)(u)), \ + "dI" ((USItype)(v))); \ (w1) = __xx.__i.__h; (w0) = __xx.__i.__l;}) #define __umulsidi3(u, v) \ - ({long long int __w; \ + ({UDItype __w; \ __asm__ ("emul %2,%1,%0" \ : "=d" (__w) \ - : "%dI" ((unsigned long int)(u)), \ - "dI" ((unsigned long int)(v))); \ - __w; }) -#endif /* __i960__ */ - -#if defined (___IBMR2__) /* IBM RS6000 */ -#define add_ssaaaa(sh, sl, ah, al, bh, bl) \ - __asm__ ("a%I5 %1,%4,%5 - ae %0,%2,%3" \ - : "=r" ((unsigned long int)(sh)), \ - "=&r" ((unsigned long int)(sl)) \ - : "%r" ((unsigned long int)(ah)), \ - "r" ((unsigned long int)(bh)), \ - "%r" ((unsigned long int)(al)), \ - "rI" ((unsigned long int)(bl))) -#define sub_ddmmss(sh, sl, ah, al, bh, bl) \ - __asm__ ("sf%I4 %1,%5,%4 - sfe %0,%3,%2" \ - : "=r" ((unsigned long int)(sh)), \ - "=&r" ((unsigned long int)(sl)) \ - : "r" ((unsigned long int)(ah)), \ - "r" ((unsigned long int)(bh)), \ - "rI" ((unsigned long int)(al)), \ - "r" ((unsigned long int)(bl))) -#define umul_ppmm(xh, xl, m0, m1) \ + : "%dI" ((USItype)(u)), \ + "dI" ((USItype)(v))); \ + __w; }) +#define udiv_qrnnd(q, r, nh, nl, d) \ do { \ - unsigned long int __m0 = (m0), __m1 = (m1); \ - __asm__ ("mul %0,%2,%3" \ - : "=r" ((unsigned long int)(xh)), \ - "=q" ((unsigned long int)(xl)) \ - : "r" (__m0), \ - "r" (__m1)); \ - (xh) += ((((signed long int) __m0 >> 31) & __m1) \ - + (((signed long int) __m1 >> 31) & __m0)); \ + 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 smul_ppmm(xh, xl, m0, m1) \ - __asm__ ("mul %0,%2,%3" \ - : "=r" ((unsigned long int)(xh)), \ - "=q" ((unsigned long int)(xl)) \ - : "r" (m0), \ - "r" (m1)) -#define UMUL_TIME 8 -#define sdiv_qrnnd(q, r, nh, nl, d) \ - __asm__ ("div %0,%2,%4" \ - : "=r" (q), "=q" (r) \ - : "r" (nh), "1" (nl), "r" (d)) -#define UDIV_TIME 100 #define count_leading_zeros(count, x) \ - __asm__ ("cntlz %0,%1" \ - : "=r" ((unsigned long int)(count)) \ - : "r" ((unsigned long int)(x))) -#endif /* ___IBMR2__ */ + 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__) +#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" ((unsigned long int)(sh)), \ - "=&d" ((unsigned long int)(sl)) \ - : "%0" ((unsigned long int)(ah)), \ - "d" ((unsigned long int)(bh)), \ - "%1" ((unsigned long int)(al)), \ - "g" ((unsigned long int)(bl))) + : "=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" ((unsigned long int)(sh)), \ - "=&d" ((unsigned long int)(sl)) \ - : "0" ((unsigned long int)(ah)), \ - "d" ((unsigned long int)(bh)), \ - "1" ((unsigned long int)(al)), \ - "g" ((unsigned long int)(bl))) -#if defined (__mc68020__) || defined (__NeXT__) || defined(mc68020) + : "=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" ((unsigned long int)(w0)), \ - "=d" ((unsigned long int)(w1)) \ - : "%0" ((unsigned long int)(u)), \ - "dmi" ((unsigned long int)(v))) + : "=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" ((unsigned long int)(q)), \ - "=d" ((unsigned long int)(r)) \ - : "0" ((unsigned long int)(n0)), \ - "1" ((unsigned long int)(n1)), \ - "dmi" ((unsigned long int)(d))) + : "=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" ((unsigned long int)(q)), \ - "=d" ((unsigned long int)(r)) \ - : "0" ((unsigned long int)(n0)), \ - "1" ((unsigned long int)(n1)), \ - "dmi" ((unsigned long int)(d))) + : "=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" ((unsigned long int)(count)) \ - : "od" ((unsigned long int)(x)), "n" (0)) + : "=d" ((USItype)(count)) \ + : "od" ((USItype)(x)), "n" (0)) +#define COUNT_LEADING_ZEROS_0 32 #else /* not mc68020 */ -/* This ought to be improved by relying on reload to move inputs and - outputs to their positions. */ #define umul_ppmm(xh, xl, a, b) \ - __asm__ ("| Inlined umul_ppmm - movel %2,d0 - movel %3,d1 - movel d0,d2 - swap d0 - movel d1,d3 - swap d1 - movew d2,d4 - mulu d3,d4 - mulu d1,d2 - mulu d0,d3 - mulu d0,d1 - movel d4,d0 - eorw d0,d0 - swap d0 - addl d0,d2 - addl d3,d2 + 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 - addl #65536,d1 -1: swap d2 - moveq #0,d0 - movew d2,d0 - movew d4,d2 - movel d2,%1 - addl d1,d0 - movel d0,%0" \ - : "=g" ((unsigned long int)(xh)), \ - "=g" ((unsigned long int)(xl)) \ - : "g" ((unsigned long int)(a)), \ - "g" ((unsigned long int)(b)) \ - : "d0", "d1", "d2", "d3", "d4") + 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__) +#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" ((unsigned long int)(sh)), \ - "=&r" ((unsigned long int)(sl)) \ - : "%rJ" ((unsigned long int)(ah)), \ - "rJ" ((unsigned long int)(bh)), \ - "%rJ" ((unsigned long int)(al)), \ - "rJ" ((unsigned long int)(bl))) + : "=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" ((unsigned long int)(sh)), \ - "=&r" ((unsigned long int)(sl)) \ - : "rJ" ((unsigned long int)(ah)), \ - "rJ" ((unsigned long int)(bh)), \ - "rJ" ((unsigned long int)(al)), \ - "rJ" ((unsigned long int)(bl))) -#define UMUL_TIME 17 -#define UDIV_TIME 150 + : "=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 { \ - unsigned long int __cbtmp; \ + USItype __cbtmp; \ __asm__ ("ff1 %0,%1" \ : "=r" (__cbtmp) \ - : "r" ((unsigned long int)(x))); \ + : "r" ((USItype)(x))); \ (count) = __cbtmp ^ 31; \ } while (0) -#if defined (__mc88110__) +#define COUNT_LEADING_ZEROS_0 63 /* sic */ +#if defined (__m88110__) #define umul_ppmm(wh, wl, u, v) \ do { \ - union {long long int __ll; \ - struct {unsigned long int __h, __l;} __i; \ + union {UDItype __ll; \ + struct {USItype __h, __l;} __i; \ } __xx; \ __asm__ ("mulu.d %0,%1,%2" \ : "=r" (__xx.__ll) \ - : "r" ((unsigned long int)(u)), \ - "r" ((unsigned long int)(v))); \ + : "r" ((USItype)(u)), \ + "r" ((USItype)(v))); \ (wh) = __xx.__i.__h; \ (wl) = __xx.__i.__l; \ } while (0) - #define udiv_qrnnd(q, r, n1, n0, d) \ - __asm__ ("or r10,%2,0 - or r11,%3,0 - divu.d r10,r10,%4 - mulu %1,%4,r11 - subu %1,%3,%1 - or %0,r11,0" \ - : "=r" (q), \ - "=&r" (r) \ - : "r" (n1), \ - "r" (n0), \ - "r" (d) \ - : "r10", "r11") -#endif + ({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__) -/* The LO and HI registers are fixed in gcc/mips.h, for some reason. */ -#if 0 && __GNUC__ >= 2 +#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" ((unsigned long int)(w0)), \ - "=h" ((unsigned long int)(w1)) \ - : "d" ((unsigned long int)(u)), \ - "d" ((unsigned long int)(v))) + : "=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" ((unsigned long int)(w0)), \ - "=d" ((unsigned long int)(w1)) \ - : "d" ((unsigned long int)(u)), \ - "d" ((unsigned long int)(v))) + : "=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 (__ns32000__) +#if (defined (__mips) && __mips >= 3) && W_TYPE_SIZE == 64 +#if __GNUC__ > 2 || __GNUC_MINOR__ >= 7 #define umul_ppmm(w1, w0, u, v) \ - ({union {long long int __ll; \ - struct {unsigned long int __l, __h;} __i; \ + __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" ((unsigned long int)(u)), \ - "g" ((unsigned long int)(v))); \ + : "%0" ((USItype)(u)), \ + "g" ((USItype)(v))); \ (w1) = __xx.__i.__h; (w0) = __xx.__i.__l;}) #define __umulsidi3(u, v) \ - ({long long int __w; \ + ({UDItype __w; \ __asm__ ("meid %2,%0" \ : "=g" (__w) \ - : "%0" ((unsigned long int)(u)), \ - "g" ((unsigned long int)(v))); \ + : "%0" ((USItype)(u)), \ + "g" ((USItype)(v))); \ __w; }) #define udiv_qrnnd(q, r, n1, n0, d) \ - __asm__ ("movd %2,r0 - movd %3,r1 - deid %4,r0 - movd r1,%0 - movd r0,%1" \ - : "=g" ((unsigned long int)(q)), \ - "=g" ((unsigned long int)(r)) \ - : "g" ((unsigned long int)(n0)), \ - "g" ((unsigned long int)(n1)), \ - "g" ((unsigned long int)(d)) \ - : "r0", "r1") + ({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 (__pyr__) +#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" ((unsigned long int)(sh)), \ - "=&r" ((unsigned long int)(sl)) \ - : "%0" ((unsigned long int)(ah)), \ - "g" ((unsigned long int)(bh)), \ - "%1" ((unsigned long int)(al)), \ - "g" ((unsigned long int)(bl))) + : "=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" ((unsigned long int)(sh)), \ - "=&r" ((unsigned long int)(sl)) \ - : "0" ((unsigned long int)(ah)), \ - "g" ((unsigned long int)(bh)), \ - "1" ((unsigned long int)(al)), \ - "g" ((unsigned long int)(bl))) -/* This insn doesn't work on ancient pyramids. */ + : "=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 {long long int __ll; \ - struct {unsigned long int __h, __l;} __i; \ + ({union {UDItype __ll; \ + struct {USItype __h, __l;} __i; \ } __xx; \ - __xx.__i.__l = u; \ - __asm__ ("uemul %3,%0" \ - : "=r" (__xx.__i.__h), \ - "=r" (__xx.__i.__l) \ - : "1" (__xx.__i.__l), \ - "g" (v)); \ + __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 */ +#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" ((unsigned long int)(sh)), \ - "=&r" ((unsigned long int)(sl)) \ - : "%0" ((unsigned long int)(ah)), \ - "r" ((unsigned long int)(bh)), \ - "%1" ((unsigned long int)(al)), \ - "r" ((unsigned long int)(bl))) + : "=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" ((unsigned long int)(sh)), \ - "=&r" ((unsigned long int)(sl)) \ - : "0" ((unsigned long int)(ah)), \ - "r" ((unsigned long int)(bh)), \ - "1" ((unsigned long int)(al)), \ - "r" ((unsigned long int)(bl))) + : "=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 { \ - unsigned long int __m0 = (m0), __m1 = (m1); \ + USItype __m0 = (m0), __m1 = (m1); \ __asm__ ( \ "s r2,r2 mts r10,%2 @@ -688,13 +928,13 @@ m r2,%3 cas %0,r2,r0 mfs r10,%1" \ - : "=r" ((unsigned long int)(ph)), \ - "=r" ((unsigned long int)(pl)) \ + : "=r" ((USItype)(ph)), \ + "=r" ((USItype)(pl)) \ : "%r" (__m0), \ "r" (__m1) \ : "r2"); \ - (ph) += ((((signed long int) __m0 >> 31) & __m1) \ - + (((signed long int) __m1 >> 31) & __m0)); \ + (ph) += ((((SItype) __m0 >> 31) & __m1) \ + + (((SItype) __m1 >> 31) & __m0)); \ } while (0) #define UMUL_TIME 20 #define UDIV_TIME 200 @@ -702,60 +942,148 @@ do { \ if ((x) >= 0x10000) \ __asm__ ("clz %0,%1" \ - : "=r" ((unsigned long int)(count)) \ - : "r" ((unsigned long int)(x) >> 16)); \ + : "=r" ((USItype)(count)) \ + : "r" ((USItype)(x) >> 16)); \ else \ { \ __asm__ ("clz %0,%1" \ - : "=r" ((unsigned long int)(count)) \ - : "r" ((unsigned long int)(x))); \ + : "=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__) +#if defined (__sparc__) && W_TYPE_SIZE == 32 #define add_ssaaaa(sh, sl, ah, al, bh, bl) \ - __asm__ ("addcc %4,%5,%1 - addx %2,%3,%0" \ - : "=r" ((unsigned long int)(sh)), \ - "=&r" ((unsigned long int)(sl)) \ - : "%r" ((unsigned long int)(ah)), \ - "rI" ((unsigned long int)(bh)), \ - "%r" ((unsigned long int)(al)), \ - "rI" ((unsigned long int)(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 %4,%5,%1 - subx %2,%3,%0" \ - : "=r" ((unsigned long int)(sh)), \ - "=&r" ((unsigned long int)(sl)) \ - : "r" ((unsigned long int)(ah)), \ - "rI" ((unsigned long int)(bh)), \ - "r" ((unsigned long int)(al)), \ - "rI" ((unsigned long int)(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" ((unsigned long int)(w1)), \ - "=r" ((unsigned long int)(w0)) \ - : "r" ((unsigned long int)(u)), \ - "r" ((unsigned long int)(v))) -/* We might want to leave this undefined for `SuperSPARC (tm)' since - its implementation is crippled and often traps. */ + : "=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) \ - __asm__ ("mov %2,%%y;nop;nop;nop;udiv %3,%4,%0;umul %0,%4,%1;sub %3,%1,%1"\ - : "=&r" ((unsigned long int)(q)), \ - "=&r" ((unsigned long int)(r)) \ - : "r" ((unsigned long int)(n1)), \ - "r" ((unsigned long int)(n0)), \ - "r" ((unsigned long int)(d))) -#define UMUL_TIME 6 + 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 -#else -/* SPARC without integer multiplication and divide instructions. - (i.e. at least Sun4/20,40,60,65,75,110,260,280,330,360,380,470,490) */ +#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 @@ -797,110 +1125,122 @@ mulscc %%g1,0,%%g1 add %%g1,%%g2,%0 rd %%y,%1" \ - : "=r" ((unsigned long int)(w1)), \ - "=r" ((unsigned long int)(w0)) \ - : "%rI" ((unsigned long int)(u)), \ - "r" ((unsigned long int)(v)) \ + : "=r" ((USItype)(w1)), \ + "=r" ((USItype)(w0)) \ + : "%rI" ((USItype)(u)), \ + "r" ((USItype)(v)) \ : "%g1", "%g2" __AND_CLOBBER_CC) #define UMUL_TIME 39 /* 39 instructions */ -/* It's quite necessary to add this much assembler for the sparc. - The default udiv_qrnnd (in C) is more than 10 times slower! */ +#endif +#ifndef udiv_qrnnd +#ifndef LONGLONG_STANDALONE #define udiv_qrnnd(q, r, n1, n0, d) \ - __asm__ ("! Inlined udiv_qrnnd - mov 32,%%g1 - subcc %1,%2,%%g0 -1: bcs 5f - addxcc %0,%0,%0 ! shift n1n0 and a q-bit in lsb - sub %1,%2,%1 ! this kills msb of n - addx %1,%1,%1 ! so this can't give carry - subcc %%g1,1,%%g1 -2: bne 1b - subcc %1,%2,%%g0 - bcs 3f - addxcc %0,%0,%0 ! shift n1n0 and a q-bit in lsb - b 3f - sub %1,%2,%1 ! this kills msb of n -4: sub %1,%2,%1 -5: addxcc %1,%1,%1 - bcc 2b - subcc %%g1,1,%%g1 -! Got carry from n. Subtract next step to cancel this carry. - bne 4b - addcc %0,%0,%0 ! shift n1n0 and a 0-bit in lsb - sub %1,%2,%1 -3: xnor %0,0,%0 - ! End of inline udiv_qrnnd" \ - : "=&r" ((unsigned long int)(q)), \ - "=&r" ((unsigned long int)(r)) \ - : "r" ((unsigned long int)(d)), \ - "1" ((unsigned long int)(n1)), \ - "0" ((unsigned long int)(n0)) : "%g1" __AND_CLOBBER_CC) -#define UDIV_TIME (3+7*32) /* 7 instructions/iteration. 32 iterations. */ -#endif /* __sparc8__ */ + 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__) +#if defined (__vax__) && W_TYPE_SIZE == 32 #define add_ssaaaa(sh, sl, ah, al, bh, bl) \ __asm__ ("addl2 %5,%1 adwc %3,%0" \ - : "=g" ((unsigned long int)(sh)), \ - "=&g" ((unsigned long int)(sl)) \ - : "%0" ((unsigned long int)(ah)), \ - "g" ((unsigned long int)(bh)), \ - "%1" ((unsigned long int)(al)), \ - "g" ((unsigned long int)(bl))) + : "=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" ((unsigned long int)(sh)), \ - "=&g" ((unsigned long int)(sl)) \ - : "0" ((unsigned long int)(ah)), \ - "g" ((unsigned long int)(bh)), \ - "1" ((unsigned long int)(al)), \ - "g" ((unsigned long int)(bl))) + : "=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 {long long int __ll; \ - struct {unsigned long int __l, __h;} __i; \ + union {UDItype __ll; \ + struct {USItype __l, __h;} __i; \ } __xx; \ - unsigned long int __m0 = (m0), __m1 = (m1); \ + 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) += ((((signed long int) __m0 >> 31) & __m1) \ - + (((signed long int) __m1 >> 31) & __m0)); \ + (xh) += ((((SItype) __m0 >> 31) & __m1) \ + + (((SItype) __m1 >> 31) & __m0)); \ } while (0) #define sdiv_qrnnd(q, r, n1, n0, d) \ do { \ - union {long long int __ll; \ - struct {unsigned long int __l, __h;} __i; \ + 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" (__n1n0.ll), "g" (d)); \ + : "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) \ { \ - unsigned long long int __ll = __umulsidi3 (m0, m1); \ - ph = (unsigned long int) (__ll >> LONG_TYPE_SIZE); \ - pl = (unsigned long int) __ll; \ + UDWtype __ll = __umulsidi3 (m0, m1); \ + ph = (UWtype) (__ll >> W_TYPE_SIZE); \ + pl = (UWtype) __ll; \ } #endif #if !defined (__umulsidi3) #define __umulsidi3(u, v) \ - ({long __hi, __lo; \ + ({UWtype __hi, __lo; \ umul_ppmm (__hi, __lo, u, v); \ - ((unsigned long long) __hi << LONG_TYPE_SIZE) | __lo; }) + ((UDWtype) __hi << W_TYPE_SIZE) | __lo; }) #endif /* If this machine has no inline assembler, use C macros. */ @@ -908,7 +1248,7 @@ #if !defined (add_ssaaaa) #define add_ssaaaa(sh, sl, ah, al, bh, bl) \ do { \ - unsigned long int __x; \ + UWtype __x; \ __x = (al) + (bl); \ (sh) = (ah) + (bh) + (__x < (al)); \ (sl) = __x; \ @@ -918,7 +1258,7 @@ #if !defined (sub_ddmmss) #define sub_ddmmss(sh, sl, ah, al, bh, bl) \ do { \ - unsigned long int __x; \ + UWtype __x; \ __x = (al) - (bl); \ (sh) = (ah) - (bh) - (__x > (al)); \ (sl) = __x; \ @@ -928,18 +1268,19 @@ #if !defined (umul_ppmm) #define umul_ppmm(w1, w0, u, v) \ do { \ - unsigned long int __x0, __x1, __x2, __x3; \ - unsigned int __ul, __vl, __uh, __vh; \ + 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); \ + __ul = __ll_lowpart (__u); \ + __uh = __ll_highpart (__u); \ + __vl = __ll_lowpart (__v); \ + __vh = __ll_highpart (__v); \ \ - __x0 = (unsigned long int) __ul * __vl; \ - __x1 = (unsigned long int) __ul * __vh; \ - __x2 = (unsigned long int) __uh * __vl; \ - __x3 = (unsigned long int) __uh * __vh; \ + __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 */ \ @@ -947,20 +1288,31 @@ __x3 += __ll_B; /* yes, add it in the proper pos. */ \ \ (w1) = __x3 + __ll_highpart (__x1); \ - (w0) = __ll_lowpart (__x1) * __ll_B + __ll_lowpart (__x0); \ + (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 { \ - unsigned long int __d1, __d0, __q1, __q0, __r1, __r0, __m; \ + UWtype __d1, __d0, __q1, __q0, __r1, __r0, __m; \ __d1 = __ll_highpart (d); \ __d0 = __ll_lowpart (d); \ \ __r1 = (n1) % __d1; \ __q1 = (n1) / __d1; \ - __m = (unsigned long int) __q1 * __d0; \ + __m = (UWtype) __q1 * __d0; \ __r1 = __r1 * __ll_B | __ll_highpart (n0); \ if (__r1 < __m) \ { \ @@ -973,7 +1325,7 @@ \ __r0 = __r1 % __d1; \ __q0 = __r1 / __d1; \ - __m = (unsigned long int) __q0 * __d0; \ + __m = (UWtype) __q0 * __d0; \ __r0 = __r0 * __ll_B | __ll_lowpart (n0); \ if (__r0 < __m) \ { \ @@ -984,10 +1336,21 @@ } \ __r0 -= __m; \ \ - (q) = (unsigned long int) __q1 * __ll_B | __q0; \ + (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 @@ -1002,23 +1365,37 @@ const unsigned char __clz_tab[]; #define count_leading_zeros(count, x) \ do { \ - unsigned long int __xr = (x); \ - unsigned int __a; \ + UWtype __xr = (x); \ + UWtype __a; \ \ - if (LONG_TYPE_SIZE <= 32) \ + if (W_TYPE_SIZE <= 32) \ { \ - __a = __xr < (1<<2*__BITS4) \ - ? (__xr < (1<<__BITS4) ? 0 : __BITS4) \ - : (__xr < (1<<3*__BITS4) ? 2*__BITS4 : 3*__BITS4); \ + __a = __xr < ((UWtype) 1 << 2*__BITS4) \ + ? (__xr < ((UWtype) 1 << __BITS4) ? 0 : __BITS4) \ + : (__xr < ((UWtype) 1 << 3*__BITS4) ? 2*__BITS4 : 3*__BITS4);\ } \ else \ { \ - for (__a = LONG_TYPE_SIZE - 8; __a > 0; __a -= 8) \ + for (__a = W_TYPE_SIZE - 8; __a > 0; __a -= 8) \ if (((__xr >> __a) & 0xff) != 0) \ break; \ } \ \ - (count) = LONG_TYPE_SIZE - (__clz_tab[__xr >> __a] + __a); \ + (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 diff --git a/gnu/lib/libgmp/make.bat b/gnu/lib/libgmp/make.bat new file mode 100755 index 000000000000..2a79c48649a6 --- /dev/null +++ b/gnu/lib/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/gnu/lib/libgmp/memory.c b/gnu/lib/libgmp/memory.c index cdbe52edd552..9ee1da8a1d61 100644 --- a/gnu/lib/libgmp/memory.c +++ b/gnu/lib/libgmp/memory.c @@ -1,22 +1,23 @@ /* Memory allocation routines. -Copyright (C) 1991 Free Software Foundation, Inc. +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 General Public License as published by -the Free Software Foundation; either version 2, or (at your option) -any later version. +it under the terms of the GNU Library General Public License as published by +the Free Software Foundation; either version 2 of the License, or (at your +option) any later version. -The GNU MP Library is distributed in the hope that 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. +The GNU MP Library is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public +License for more details. -You should have received a copy of the GNU General Public License -along with the GNU MP Library; see the file COPYING. If not, write to -the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ +You should have received a copy of the GNU Library General Public License +along with the GNU MP Library; 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 @@ -27,7 +28,7 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ #define static #endif -#ifdef __STDC__ +#if __STDC__ void * (*_mp_allocate_func) (size_t) = _mp_default_allocate; void * (*_mp_reallocate_func) (void *, size_t, size_t) = _mp_default_reallocate; @@ -42,7 +43,7 @@ void (*_mp_free_func) () = _mp_default_free; an error message is written to stderr and the program aborts. */ void * -#ifdef __STDC__ +#if __STDC__ _mp_default_allocate (size_t size) #else _mp_default_allocate (size) @@ -54,7 +55,7 @@ _mp_default_allocate (size) ret = malloc (size); if (ret == 0) { - perror ("cannot allocate in libmp"); + perror ("cannot allocate in gmp"); abort (); } @@ -62,7 +63,7 @@ _mp_default_allocate (size) } void * -#ifdef __STDC__ +#if __STDC__ _mp_default_reallocate (void *oldptr, size_t old_size, size_t new_size) #else _mp_default_reallocate (oldptr, old_size, new_size) @@ -76,7 +77,7 @@ _mp_default_reallocate (oldptr, old_size, new_size) ret = realloc (oldptr, new_size); if (ret == 0) { - perror ("cannot allocate in libmp"); + perror ("cannot allocate in gmp"); abort (); } @@ -84,7 +85,7 @@ _mp_default_reallocate (oldptr, old_size, new_size) } void -#ifdef __STDC__ +#if __STDC__ _mp_default_free (void *blk_ptr, size_t blk_size) #else _mp_default_free (blk_ptr, blk_size) diff --git a/gnu/lib/libgmp/mkinstalldirs b/gnu/lib/libgmp/mkinstalldirs new file mode 100755 index 000000000000..cd1fe0a7947c --- /dev/null +++ b/gnu/lib/libgmp/mkinstalldirs @@ -0,0 +1,32 @@ +#! /bin/sh +# mkinstalldirs --- make directory hierarchy +# Author: Noah Friedman +# 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/gnu/lib/libgmp/move-if-change b/gnu/lib/libgmp/move-if-change new file mode 100755 index 000000000000..ee9e355e3e61 --- /dev/null +++ b/gnu/lib/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/gnu/lib/libgmp/mp.h b/gnu/lib/libgmp/mp.h index 8836e0cb0e09..830b26b3abe9 100644 --- a/gnu/lib/libgmp/mp.h +++ b/gnu/lib/libgmp/mp.h @@ -1,60 +1,97 @@ /* mp.h -- Definitions for Berkeley compatible multiple precision functions. -Copyright (C) 1991, 1993 Free Software Foundation, Inc. +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 General Public License as published by -the Free Software Foundation; either version 2, or (at your option) -any later version. +it under the terms of the GNU Library General Public License as published by +the Free Software Foundation; either version 2 of the License, or (at your +option) any later version. -The GNU MP Library is distributed in the hope that 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. +The GNU MP Library is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public +License for more details. -You should have received a copy of the GNU General Public License -along with the GNU MP Library; see the file COPYING. If not, write to -the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ +You should have received a copy of the GNU Library General Public License +along with the GNU MP Library; 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__ -#define __MP_H__ -#define __GNU_MP__ - -#ifndef __GMP_H__ +#ifndef __GNU_MP__ +#define __GNU_MP__ 2 #define __need_size_t #include +#undef __need_size_t + +#if defined (__STDC__) || defined (__cplusplus) +#define __gmp_const const +#else +#define __gmp_const #endif -#ifndef MP_INT +#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 { - long int alloc; /* Number of *limbs* allocated and pointed + mp_size_t _mp_alloc; /* Number of *limbs* allocated and pointed to by the D field. */ - long int size; /* abs(SIZE) is the number of limbs + 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. */ - unsigned long int *d; /* Pointer to the limbs. */ -} __MP_INT; + mp_limb_t *_mp_d; /* Pointer to the limbs. */ +} __mpz_struct; #else typedef struct { - short int alloc; /* Number of *limbs* allocated and pointed + short int _mp_alloc; /* Number of *limbs* allocated and pointed to by the D field. */ - short int size; /* abs(SIZE) is the number of limbs + 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. */ - unsigned long int *d; /* Pointer to the limbs. */ -} __MP_INT; -#endif + mp_limb_t *_mp_d; /* Pointer to the limbs. */ +} __mpz_struct; #endif +#endif /* __GNU_MP__ */ -#define MINT __MP_INT +/* User-visible types. */ +typedef __mpz_struct MINT; #ifdef __STDC__ void mp_set_memory_functions (void *(*) (size_t), @@ -100,4 +137,5 @@ char *mtox (); void mfree (); #endif +#define __MP_H__ #endif /* __MP_H__ */ diff --git a/gnu/lib/libgmp/mp_bpl.c b/gnu/lib/libgmp/mp_bpl.c new file mode 100644 index 000000000000..d817ac82379b --- /dev/null +++ b/gnu/lib/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/gnu/lib/libgmp/mp_clz_tab.c b/gnu/lib/libgmp/mp_clz_tab.c index c27b96939ec8..6fd7e90811b5 100644 --- a/gnu/lib/libgmp/mp_clz_tab.c +++ b/gnu/lib/libgmp/mp_clz_tab.c @@ -1,29 +1,33 @@ /* __clz_tab -- support for longlong.h -Copyright (C) 1991 Free Software Foundation, Inc. +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 General Public License as published by -the Free Software Foundation; either version 2, or (at your option) -any later version. +it under the terms of the GNU Library General Public License as published by +the Free Software Foundation; either version 2 of the License, or (at your +option) any later version. -The GNU MP Library is distributed in the hope that 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. +The GNU MP Library is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public +License for more details. -You should have received a copy of the GNU General Public License -along with the GNU MP Library; see the file COPYING. If not, write to -the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ +You should have received a copy of the GNU Library General Public License +along with the GNU MP Library; 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 -/* BOTCH: This ought to be made machine-independent. */ - -const unsigned char __clz_tab[] = +#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, diff --git a/gnu/lib/libgmp/mp_set_fns.c b/gnu/lib/libgmp/mp_set_fns.c index 04bb37ae9472..35a462c11d46 100644 --- a/gnu/lib/libgmp/mp_set_fns.c +++ b/gnu/lib/libgmp/mp_set_fns.c @@ -1,29 +1,30 @@ /* mp_set_memory_functions -- Set the allocate, reallocate, and free functions for use by the mp package. -Copyright (C) 1991 Free Software Foundation, Inc. +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 General Public License as published by -the Free Software Foundation; either version 2, or (at your option) -any later version. +it under the terms of the GNU Library General Public License as published by +the Free Software Foundation; either version 2 of the License, or (at your +option) any later version. -The GNU MP Library is distributed in the hope that 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. +The GNU MP Library is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public +License for more details. -You should have received a copy of the GNU General Public License -along with the GNU MP Library; see the file COPYING. If not, write to -the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ +You should have received a copy of the GNU Library General Public License +along with the GNU MP Library; 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 -#ifdef __STDC__ +#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)) diff --git a/gnu/lib/libgmp/mpbsd/Makefile.in b/gnu/lib/libgmp/mpbsd/Makefile.in new file mode 100644 index 000000000000..a517c1aba1cb --- /dev/null +++ b/gnu/lib/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/gnu/lib/libgmp/mpbsd/configure.in b/gnu/lib/libgmp/mpbsd/configure.in new file mode 100644 index 000000000000..ec220753b079 --- /dev/null +++ b/gnu/lib/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/gnu/lib/libgmp/mpbsd/itom.c b/gnu/lib/libgmp/mpbsd/itom.c new file mode 100644 index 000000000000..719a4dcdcb21 --- /dev/null +++ b/gnu/lib/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/gnu/lib/libgmp/mpbsd/mdiv.c b/gnu/lib/libgmp/mpbsd/mdiv.c new file mode 100644 index 000000000000..103c2c307adc --- /dev/null +++ b/gnu/lib/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/gnu/lib/libgmp/mpbsd/mfree.c b/gnu/lib/libgmp/mpbsd/mfree.c new file mode 100644 index 000000000000..ef931e3f42ff --- /dev/null +++ b/gnu/lib/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/gnu/lib/libgmp/mpbsd/min.c b/gnu/lib/libgmp/mpbsd/min.c new file mode 100644 index 000000000000..6edb1716628a --- /dev/null +++ b/gnu/lib/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 +#include +#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/gnu/lib/libgmp/mpbsd/mout.c b/gnu/lib/libgmp/mpbsd/mout.c new file mode 100644 index 000000000000..a6b62be8516d --- /dev/null +++ b/gnu/lib/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 +#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/gnu/lib/libgmp/mpbsd/move.c b/gnu/lib/libgmp/mpbsd/move.c new file mode 100644 index 000000000000..8256cc704c52 --- /dev/null +++ b/gnu/lib/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/gnu/lib/libgmp/mpbsd/mtox.c b/gnu/lib/libgmp/mpbsd/mtox.c new file mode 100644 index 000000000000..8baec2a1ec8a --- /dev/null +++ b/gnu/lib/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/gnu/lib/libgmp/mpbsd/realloc.c b/gnu/lib/libgmp/mpbsd/realloc.c new file mode 100644 index 000000000000..64bee76f1f1c --- /dev/null +++ b/gnu/lib/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/gnu/lib/libgmp/mpbsd/sdiv.c b/gnu/lib/libgmp/mpbsd/sdiv.c new file mode 100644 index 000000000000..6982e200949e --- /dev/null +++ b/gnu/lib/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/gnu/lib/libgmp/mpbsd/xtom.c b/gnu/lib/libgmp/mpbsd/xtom.c new file mode 100644 index 000000000000..5a529e8e46ea --- /dev/null +++ b/gnu/lib/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/gnu/lib/libgmp/mpf/Makefile.in b/gnu/lib/libgmp/mpf/Makefile.in new file mode 100644 index 000000000000..598fa72fc193 --- /dev/null +++ b/gnu/lib/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/gnu/lib/libgmp/mpf/abs.c b/gnu/lib/libgmp/mpf/abs.c new file mode 100644 index 000000000000..029007a5f87d --- /dev/null +++ b/gnu/lib/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/gnu/lib/libgmp/mpf/add.c b/gnu/lib/libgmp/mpf/add.c new file mode 100644 index 000000000000..2db876fc657f --- /dev/null +++ b/gnu/lib/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/gnu/lib/libgmp/mpf/add_ui.c b/gnu/lib/libgmp/mpf/add_ui.c new file mode 100644 index 000000000000..f181df48e620 --- /dev/null +++ b/gnu/lib/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/gnu/lib/libgmp/mpf/clear.c b/gnu/lib/libgmp/mpf/clear.c new file mode 100644 index 000000000000..beaf4ee3a3c4 --- /dev/null +++ b/gnu/lib/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/gnu/lib/libgmp/mpf/cmp.c b/gnu/lib/libgmp/mpf/cmp.c new file mode 100644 index 000000000000..d440e1152bd2 --- /dev/null +++ b/gnu/lib/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/gnu/lib/libgmp/mpf/cmp_si.c b/gnu/lib/libgmp/mpf/cmp_si.c new file mode 100644 index 000000000000..01f970812c9f --- /dev/null +++ b/gnu/lib/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/gnu/lib/libgmp/mpf/cmp_ui.c b/gnu/lib/libgmp/mpf/cmp_ui.c new file mode 100644 index 000000000000..3a4911ba716f --- /dev/null +++ b/gnu/lib/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/gnu/lib/libgmp/mpf/configure.in b/gnu/lib/libgmp/mpf/configure.in new file mode 100644 index 000000000000..b6ecf8b3e8eb --- /dev/null +++ b/gnu/lib/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/gnu/lib/libgmp/mpf/div.c b/gnu/lib/libgmp/mpf/div.c new file mode 100644 index 000000000000..9ba6922cd634 --- /dev/null +++ b/gnu/lib/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/gnu/lib/libgmp/mpf/div_2exp.c b/gnu/lib/libgmp/mpf/div_2exp.c new file mode 100644 index 000000000000..d7296254e9ed --- /dev/null +++ b/gnu/lib/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/gnu/lib/libgmp/mpf/div_ui.c b/gnu/lib/libgmp/mpf/div_ui.c new file mode 100644 index 000000000000..050a6f0b70e7 --- /dev/null +++ b/gnu/lib/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/gnu/lib/libgmp/mpf/dump.c b/gnu/lib/libgmp/mpf/dump.c new file mode 100644 index 000000000000..46d5c05f20ad --- /dev/null +++ b/gnu/lib/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 +#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/gnu/lib/libgmp/mpf/eq.c b/gnu/lib/libgmp/mpf/eq.c new file mode 100644 index 000000000000..e6630ad6e9fa --- /dev/null +++ b/gnu/lib/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/gnu/lib/libgmp/mpf/get_d.c b/gnu/lib/libgmp/mpf/get_d.c new file mode 100644 index 000000000000..a10b366a9522 --- /dev/null +++ b/gnu/lib/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/gnu/lib/libgmp/mpf/get_prc.c b/gnu/lib/libgmp/mpf/get_prc.c new file mode 100644 index 000000000000..7f7e41f673f2 --- /dev/null +++ b/gnu/lib/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/gnu/lib/libgmp/mpf/get_str.c b/gnu/lib/libgmp/mpf/get_str.c new file mode 100644 index 000000000000..bfee18d076b0 --- /dev/null +++ b/gnu/lib/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/gnu/lib/libgmp/mpf/init.c b/gnu/lib/libgmp/mpf/init.c new file mode 100644 index 000000000000..53701218f1cf --- /dev/null +++ b/gnu/lib/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/gnu/lib/libgmp/mpf/init2.c b/gnu/lib/libgmp/mpf/init2.c new file mode 100644 index 000000000000..a3e5752b24f7 --- /dev/null +++ b/gnu/lib/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/gnu/lib/libgmp/mpf/inp_str.c b/gnu/lib/libgmp/mpf/inp_str.c new file mode 100644 index 000000000000..1d3cd4cc2b5b --- /dev/null +++ b/gnu/lib/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 +#include +#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/gnu/lib/libgmp/mpf/iset.c b/gnu/lib/libgmp/mpf/iset.c new file mode 100644 index 000000000000..c2362e1729a0 --- /dev/null +++ b/gnu/lib/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/gnu/lib/libgmp/mpf/iset_d.c b/gnu/lib/libgmp/mpf/iset_d.c new file mode 100644 index 000000000000..d09e8b89a5f0 --- /dev/null +++ b/gnu/lib/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/gnu/lib/libgmp/mpf/iset_si.c b/gnu/lib/libgmp/mpf/iset_si.c new file mode 100644 index 000000000000..e67eef4cdb5d --- /dev/null +++ b/gnu/lib/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/gnu/lib/libgmp/mpf/iset_str.c b/gnu/lib/libgmp/mpf/iset_str.c new file mode 100644 index 000000000000..40bfe7cf27ed --- /dev/null +++ b/gnu/lib/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/gnu/lib/libgmp/mpf/iset_ui.c b/gnu/lib/libgmp/mpf/iset_ui.c new file mode 100644 index 000000000000..c6c24afaf1a1 --- /dev/null +++ b/gnu/lib/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/gnu/lib/libgmp/mpf/mul.c b/gnu/lib/libgmp/mpf/mul.c new file mode 100644 index 000000000000..8f1a2a9aca1d --- /dev/null +++ b/gnu/lib/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/gnu/lib/libgmp/mpf/mul_2exp.c b/gnu/lib/libgmp/mpf/mul_2exp.c new file mode 100644 index 000000000000..0ed35a0b1c1a --- /dev/null +++ b/gnu/lib/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/gnu/lib/libgmp/mpf/mul_ui.c b/gnu/lib/libgmp/mpf/mul_ui.c new file mode 100644 index 000000000000..fc87cb50750a --- /dev/null +++ b/gnu/lib/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/gnu/lib/libgmp/mpf/neg.c b/gnu/lib/libgmp/mpf/neg.c new file mode 100644 index 000000000000..a4139fb90549 --- /dev/null +++ b/gnu/lib/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/gnu/lib/libgmp/mpf/out_str.c b/gnu/lib/libgmp/mpf/out_str.c new file mode 100644 index 000000000000..2a7a954efdea --- /dev/null +++ b/gnu/lib/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 +#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/gnu/lib/libgmp/mpf/random2.c b/gnu/lib/libgmp/mpf/random2.c new file mode 100644 index 000000000000..8e67b11facbb --- /dev/null +++ b/gnu/lib/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/gnu/lib/libgmp/mpf/reldiff.c b/gnu/lib/libgmp/mpf/reldiff.c new file mode 100644 index 000000000000..c8464660753c --- /dev/null +++ b/gnu/lib/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/gnu/lib/libgmp/mpf/set.c b/gnu/lib/libgmp/mpf/set.c new file mode 100644 index 000000000000..5778b85b0938 --- /dev/null +++ b/gnu/lib/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/gnu/lib/libgmp/mpf/set_d.c b/gnu/lib/libgmp/mpf/set_d.c new file mode 100644 index 000000000000..43eb15774576 --- /dev/null +++ b/gnu/lib/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/gnu/lib/libgmp/mpf/set_dfl_prec.c b/gnu/lib/libgmp/mpf/set_dfl_prec.c new file mode 100644 index 000000000000..55069e4e4f19 --- /dev/null +++ b/gnu/lib/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/gnu/lib/libgmp/mpf/set_prc.c b/gnu/lib/libgmp/mpf/set_prc.c new file mode 100644 index 000000000000..10f2b0671f52 --- /dev/null +++ b/gnu/lib/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/gnu/lib/libgmp/mpf/set_prc_raw.c b/gnu/lib/libgmp/mpf/set_prc_raw.c new file mode 100644 index 000000000000..f55188a12481 --- /dev/null +++ b/gnu/lib/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/gnu/lib/libgmp/mpf/set_q.c b/gnu/lib/libgmp/mpf/set_q.c new file mode 100644 index 000000000000..69d81e33e435 --- /dev/null +++ b/gnu/lib/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/gnu/lib/libgmp/mpf/set_si.c b/gnu/lib/libgmp/mpf/set_si.c new file mode 100644 index 000000000000..f9b4b55eb25d --- /dev/null +++ b/gnu/lib/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/gnu/lib/libgmp/mpf/set_str.c b/gnu/lib/libgmp/mpf/set_str.c new file mode 100644 index 000000000000..2ab9faebe48d --- /dev/null +++ b/gnu/lib/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 +#include +#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/gnu/lib/libgmp/mpf/set_ui.c b/gnu/lib/libgmp/mpf/set_ui.c new file mode 100644 index 000000000000..ead0498aa73f --- /dev/null +++ b/gnu/lib/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/gnu/lib/libgmp/mpf/set_z.c b/gnu/lib/libgmp/mpf/set_z.c new file mode 100644 index 000000000000..4fff86edc3bc --- /dev/null +++ b/gnu/lib/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/gnu/lib/libgmp/mpf/size.c b/gnu/lib/libgmp/mpf/size.c new file mode 100644 index 000000000000..23a57ec72c94 --- /dev/null +++ b/gnu/lib/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/gnu/lib/libgmp/mpf/sqrt.c b/gnu/lib/libgmp/mpf/sqrt.c new file mode 100644 index 000000000000..6d115e411125 --- /dev/null +++ b/gnu/lib/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/gnu/lib/libgmp/mpf/sqrt_ui.c b/gnu/lib/libgmp/mpf/sqrt_ui.c new file mode 100644 index 000000000000..421aa021993b --- /dev/null +++ b/gnu/lib/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/gnu/lib/libgmp/mpf/sub.c b/gnu/lib/libgmp/mpf/sub.c new file mode 100644 index 000000000000..b87198263006 --- /dev/null +++ b/gnu/lib/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/gnu/lib/libgmp/mpf/sub_ui.c b/gnu/lib/libgmp/mpf/sub_ui.c new file mode 100644 index 000000000000..7806213788d1 --- /dev/null +++ b/gnu/lib/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/gnu/lib/libgmp/mpf/tests/Makefile.in b/gnu/lib/libgmp/mpf/tests/Makefile.in new file mode 100644 index 000000000000..e108b9e6800e --- /dev/null +++ b/gnu/lib/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/gnu/lib/libgmp/mpf/tests/configure.in b/gnu/lib/libgmp/mpf/tests/configure.in new file mode 100644 index 000000000000..319219cd75ae --- /dev/null +++ b/gnu/lib/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/gnu/lib/libgmp/mpf/tests/ref.c b/gnu/lib/libgmp/mpf/tests/ref.c new file mode 100644 index 000000000000..b2c3e6c2011b --- /dev/null +++ b/gnu/lib/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/gnu/lib/libgmp/mpf/tests/reuse.c b/gnu/lib/libgmp/mpf/tests/reuse.c new file mode 100644 index 000000000000..6829cc46de1a --- /dev/null +++ b/gnu/lib/libgmp/mpf/tests/reuse.c @@ -0,0 +1,186 @@ +/* Test that routines allow reusing a source variable as destination. */ + +#include +#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/gnu/lib/libgmp/mpf/tests/t-add.c b/gnu/lib/libgmp/mpf/tests/t-add.c new file mode 100644 index 000000000000..6f985bb1853e --- /dev/null +++ b/gnu/lib/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 +#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/gnu/lib/libgmp/mpf/tests/t-conv.c b/gnu/lib/libgmp/mpf/tests/t-conv.c new file mode 100644 index 000000000000..00d461d064ca --- /dev/null +++ b/gnu/lib/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 +#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/gnu/lib/libgmp/mpf/tests/t-dm2exp.c b/gnu/lib/libgmp/mpf/tests/t-dm2exp.c new file mode 100644 index 000000000000..a8c4e8f519ed --- /dev/null +++ b/gnu/lib/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 +#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/gnu/lib/libgmp/mpf/tests/t-muldiv.c b/gnu/lib/libgmp/mpf/tests/t-muldiv.c new file mode 100644 index 000000000000..d1721e8db786 --- /dev/null +++ b/gnu/lib/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 +#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/gnu/lib/libgmp/mpf/tests/t-sqrt.c b/gnu/lib/libgmp/mpf/tests/t-sqrt.c new file mode 100644 index 000000000000..5c72ab5fefee --- /dev/null +++ b/gnu/lib/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 +#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/gnu/lib/libgmp/mpf/tests/t-sub.c b/gnu/lib/libgmp/mpf/tests/t-sub.c new file mode 100644 index 000000000000..69188665577c --- /dev/null +++ b/gnu/lib/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 +#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/gnu/lib/libgmp/mpf/ui_div.c b/gnu/lib/libgmp/mpf/ui_div.c new file mode 100644 index 000000000000..a49a952048b5 --- /dev/null +++ b/gnu/lib/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/gnu/lib/libgmp/mpf/ui_sub.c b/gnu/lib/libgmp/mpf/ui_sub.c new file mode 100644 index 000000000000..acb9210a641d --- /dev/null +++ b/gnu/lib/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/gnu/lib/libgmp/mpn/Makefile.in b/gnu/lib/libgmp/mpn/Makefile.in new file mode 100644 index 000000000000..132159b9465e --- /dev/null +++ b/gnu/lib/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/gnu/lib/libgmp/mpn/README b/gnu/lib/libgmp/mpn/README new file mode 100644 index 000000000000..3da559e509ac --- /dev/null +++ b/gnu/lib/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/gnu/lib/libgmp/mpn/bsd.h b/gnu/lib/libgmp/mpn/bsd.h new file mode 100644 index 000000000000..8a0cbced256a --- /dev/null +++ b/gnu/lib/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/gnu/lib/libgmp/mpn/config/t-oldgas b/gnu/lib/libgmp/mpn/config/t-oldgas new file mode 100644 index 000000000000..ba02fa768472 --- /dev/null +++ b/gnu/lib/libgmp/mpn/config/t-oldgas @@ -0,0 +1 @@ +SFLAGS=-DBROKEN_ALIGN diff --git a/gnu/lib/libgmp/mpn/config/t-ppc-aix b/gnu/lib/libgmp/mpn/config/t-ppc-aix new file mode 100644 index 000000000000..a31ce0d7093c --- /dev/null +++ b/gnu/lib/libgmp/mpn/config/t-ppc-aix @@ -0,0 +1 @@ +SFLAGS=-Wa,-mppc diff --git a/gnu/lib/libgmp/mpn/config/t-pwr-aix b/gnu/lib/libgmp/mpn/config/t-pwr-aix new file mode 100644 index 000000000000..3e11d9f9d9fb --- /dev/null +++ b/gnu/lib/libgmp/mpn/config/t-pwr-aix @@ -0,0 +1 @@ +SFLAGS=-Wa,-mpwr diff --git a/gnu/lib/libgmp/mpn/configure.in b/gnu/lib/libgmp/mpn/configure.in new file mode 100644 index 000000000000..90c262638117 --- /dev/null +++ b/gnu/lib/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.tmp \ + -e "s/MPN_LINKS = .*/MPN_LINKS =${mpn_links}/" \ + -e "s/MPN_OBJECTS = .*/MPN_OBJECTS =${mpn_objects}/" + +mv Makefile.tmp Makefile diff --git a/gnu/lib/libgmp/mpn/generic/add_n.c b/gnu/lib/libgmp/mpn/generic/add_n.c new file mode 100644 index 000000000000..9d71df110c5a --- /dev/null +++ b/gnu/lib/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/gnu/lib/libgmp/mpn/generic/addmul_1.c b/gnu/lib/libgmp/mpn/generic/addmul_1.c new file mode 100644 index 000000000000..3a5e21400ada --- /dev/null +++ b/gnu/lib/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/gnu/lib/libgmp/mpn/generic/bdivmod.c b/gnu/lib/libgmp/mpn/generic/bdivmod.c new file mode 100644 index 000000000000..f095288b8bbc --- /dev/null +++ b/gnu/lib/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< vsize) + mpn_sub_1 (up + vsize, up + vsize, usize - vsize, b); + return q; + } + + return 0; +} diff --git a/gnu/lib/libgmp/mpn/generic/cmp.c b/gnu/lib/libgmp/mpn/generic/cmp.c new file mode 100644 index 000000000000..4e9c60d86e56 --- /dev/null +++ b/gnu/lib/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/gnu/lib/libgmp/mpn/generic/divmod_1.c b/gnu/lib/libgmp/mpn/generic/divmod_1.c new file mode 100644 index 000000000000..f93841f63fed --- /dev/null +++ b/gnu/lib/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/gnu/lib/libgmp/mpn/generic/divrem.c b/gnu/lib/libgmp/mpn/generic/divrem.c new file mode 100644 index 000000000000..1fe865a10bd1 --- /dev/null +++ b/gnu/lib/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/gnu/lib/libgmp/mpn/generic/divrem_1.c b/gnu/lib/libgmp/mpn/generic/divrem_1.c new file mode 100644 index 000000000000..d21326738823 --- /dev/null +++ b/gnu/lib/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/gnu/lib/libgmp/mpn/generic/dump.c b/gnu/lib/libgmp/mpn/generic/dump.c new file mode 100644 index 000000000000..a5831c4cc95c --- /dev/null +++ b/gnu/lib/libgmp/mpn/generic/dump.c @@ -0,0 +1,20 @@ +#include +#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/gnu/lib/libgmp/mpn/generic/gcd.c b/gnu/lib/libgmp/mpn/generic/gcd.c new file mode 100644 index 000000000000..8c2bbf0bea84 --- /dev/null +++ b/gnu/lib/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<>(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/gnu/lib/libgmp/mpn/generic/gcd_1.c b/gnu/lib/libgmp/mpn/generic/gcd_1.c new file mode 100644 index 000000000000..ebcdfb591591 --- /dev/null +++ b/gnu/lib/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/gnu/lib/libgmp/mpn/generic/gcdext.c b/gnu/lib/libgmp/mpn/generic/gcdext.c new file mode 100644 index 000000000000..245e20a4d528 --- /dev/null +++ b/gnu/lib/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/gnu/lib/libgmp/mpn/generic/get_str.c b/gnu/lib/libgmp/mpn/generic/get_str.c new file mode 100644 index 000000000000..0e7fc60ef66d --- /dev/null +++ b/gnu/lib/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/gnu/lib/libgmp/mpn/generic/gmp-mparam.h b/gnu/lib/libgmp/mpn/generic/gmp-mparam.h new file mode 100644 index 000000000000..7c885575b333 --- /dev/null +++ b/gnu/lib/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/gnu/lib/libgmp/mpn/generic/hamdist.c b/gnu/lib/libgmp/mpn/generic/hamdist.c new file mode 100644 index 000000000000..2190b636f907 --- /dev/null +++ b/gnu/lib/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/gnu/lib/libgmp/mpn/generic/inlines.c b/gnu/lib/libgmp/mpn/generic/inlines.c new file mode 100644 index 000000000000..dca305e6e49e --- /dev/null +++ b/gnu/lib/libgmp/mpn/generic/inlines.c @@ -0,0 +1,3 @@ +#define _FORCE_INLINES +#define _EXTERN_INLINE /* empty */ +#include "gmp.h" diff --git a/gnu/lib/libgmp/mpn/generic/lshift.c b/gnu/lib/libgmp/mpn/generic/lshift.c new file mode 100644 index 000000000000..e244bc52f108 --- /dev/null +++ b/gnu/lib/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/gnu/lib/libgmp/mpn/generic/mod_1.c b/gnu/lib/libgmp/mpn/generic/mod_1.c new file mode 100644 index 000000000000..314d11b3013b --- /dev/null +++ b/gnu/lib/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/gnu/lib/libgmp/mpn/generic/mul.c b/gnu/lib/libgmp/mpn/generic/mul.c new file mode 100644 index 000000000000..dcf8cb4da073 --- /dev/null +++ b/gnu/lib/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/gnu/lib/libgmp/mpn/generic/mul_1.c b/gnu/lib/libgmp/mpn/generic/mul_1.c new file mode 100644 index 000000000000..2de680a64b02 --- /dev/null +++ b/gnu/lib/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/gnu/lib/libgmp/mpn/generic/mul_n.c b/gnu/lib/libgmp/mpn/generic/mul_n.c new file mode 100644 index 000000000000..b38e8ad17ead --- /dev/null +++ b/gnu/lib/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/gnu/lib/libgmp/mpn/generic/perfsqr.c b/gnu/lib/libgmp/mpn/generic/perfsqr.c new file mode 100644 index 000000000000..5a6e2afe2862 --- /dev/null +++ b/gnu/lib/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/gnu/lib/libgmp/mpn/generic/popcount.c b/gnu/lib/libgmp/mpn/generic/popcount.c new file mode 100644 index 000000000000..c48573a4799c --- /dev/null +++ b/gnu/lib/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/gnu/lib/libgmp/mpn/generic/pre_mod_1.c b/gnu/lib/libgmp/mpn/generic/pre_mod_1.c new file mode 100644 index 000000000000..92d413b1342e --- /dev/null +++ b/gnu/lib/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/gnu/lib/libgmp/mpn/generic/random2.c b/gnu/lib/libgmp/mpn/generic/random2.c new file mode 100644 index 000000000000..29546083fcd8 --- /dev/null +++ b/gnu/lib/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/gnu/lib/libgmp/mpn/generic/rshift.c b/gnu/lib/libgmp/mpn/generic/rshift.c new file mode 100644 index 000000000000..804f9be582e2 --- /dev/null +++ b/gnu/lib/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/gnu/lib/libgmp/mpn/generic/scan0.c b/gnu/lib/libgmp/mpn/generic/scan0.c new file mode 100644 index 000000000000..d6f6580d047e --- /dev/null +++ b/gnu/lib/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/gnu/lib/libgmp/mpn/generic/scan1.c b/gnu/lib/libgmp/mpn/generic/scan1.c new file mode 100644 index 000000000000..c95d090daf6f --- /dev/null +++ b/gnu/lib/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/gnu/lib/libgmp/mpn/generic/set_str.c b/gnu/lib/libgmp/mpn/generic/set_str.c new file mode 100644 index 000000000000..424fad30e165 --- /dev/null +++ b/gnu/lib/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/gnu/lib/libgmp/mpn/generic/sqrtrem.c b/gnu/lib/libgmp/mpn/generic/sqrtrem.c new file mode 100644 index 000000000000..539480d37a25 --- /dev/null +++ b/gnu/lib/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/gnu/lib/libgmp/mpn/generic/sub_n.c b/gnu/lib/libgmp/mpn/generic/sub_n.c new file mode 100644 index 000000000000..9d4b216758b8 --- /dev/null +++ b/gnu/lib/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/gnu/lib/libgmp/mpn/generic/submul_1.c b/gnu/lib/libgmp/mpn/generic/submul_1.c new file mode 100644 index 000000000000..b144283bd988 --- /dev/null +++ b/gnu/lib/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/gnu/lib/libgmp/mpn/generic/udiv_w_sdiv.c b/gnu/lib/libgmp/mpn/generic/udiv_w_sdiv.c new file mode 100644 index 000000000000..d9e71b78a0f4 --- /dev/null +++ b/gnu/lib/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/gnu/lib/libgmp/mpn/mp_bases.c b/gnu/lib/libgmp/mpn/mp_bases.c new file mode 100644 index 000000000000..bbe39b029761 --- /dev/null +++ b/gnu/lib/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/gnu/lib/libgmp/mpn/tests/add_n.c b/gnu/lib/libgmp/mpn/tests/add_n.c new file mode 100644 index 000000000000..c27d34710a10 --- /dev/null +++ b/gnu/lib/libgmp/mpn/tests/add_n.c @@ -0,0 +1,211 @@ +#include +#include "gmp.h" +#include "gmp-impl.h" + +#ifndef USG +#include +#include + +unsigned long +cputime () +{ + struct rusage rus; + + getrusage (0, &rus); + return rus.ru_utime.tv_sec * 1000 + rus.ru_utime.tv_usec / 1000; +} +#else +#include + +#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/gnu/lib/libgmp/mpn/tests/addmul_1.c b/gnu/lib/libgmp/mpn/tests/addmul_1.c new file mode 100644 index 000000000000..23952a1cc996 --- /dev/null +++ b/gnu/lib/libgmp/mpn/tests/addmul_1.c @@ -0,0 +1,223 @@ +#include +#include "gmp.h" +#include "gmp-impl.h" +#include "longlong.h" + +#ifndef USG +#include +#include + +unsigned long +cputime () +{ + struct rusage rus; + + getrusage (0, &rus); + return rus.ru_utime.tv_sec * 1000 + rus.ru_utime.tv_usec / 1000; +} +#else +#include + +#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/gnu/lib/libgmp/mpn/tests/divmod_1.c b/gnu/lib/libgmp/mpn/tests/divmod_1.c new file mode 100644 index 000000000000..f6b541ee4722 --- /dev/null +++ b/gnu/lib/libgmp/mpn/tests/divmod_1.c @@ -0,0 +1,120 @@ +#include +#include "gmp.h" +#include "gmp-impl.h" +#include "longlong.h" + +#ifndef USG +#include +#include + +unsigned long +cputime () +{ + struct rusage rus; + + getrusage (0, &rus); + return rus.ru_utime.tv_sec * 1000 + rus.ru_utime.tv_usec / 1000; +} +#else +#include + +#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/gnu/lib/libgmp/mpn/tests/divrem.c b/gnu/lib/libgmp/mpn/tests/divrem.c new file mode 100644 index 000000000000..6eafc99e8da5 --- /dev/null +++ b/gnu/lib/libgmp/mpn/tests/divrem.c @@ -0,0 +1,129 @@ +#include +#include "gmp.h" +#include "gmp-impl.h" +#include "longlong.h" + +#ifndef USG +#include +#include + +unsigned long +cputime () +{ + struct rusage rus; + + getrusage (0, &rus); + return rus.ru_utime.tv_sec * 1000 + rus.ru_utime.tv_usec / 1000; +} +#else +#include + +#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/gnu/lib/libgmp/mpn/tests/lshift.c b/gnu/lib/libgmp/mpn/tests/lshift.c new file mode 100644 index 000000000000..f50c5dcebed9 --- /dev/null +++ b/gnu/lib/libgmp/mpn/tests/lshift.c @@ -0,0 +1,226 @@ +#include +#include "gmp.h" +#include "gmp-impl.h" +#include "longlong.h" + +#ifndef USG +#include +#include + +unsigned long +cputime () +{ + struct rusage rus; + + getrusage (0, &rus); + return rus.ru_utime.tv_sec * 1000 + rus.ru_utime.tv_usec / 1000; +} +#else +#include + +#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/gnu/lib/libgmp/mpn/tests/mul_1.c b/gnu/lib/libgmp/mpn/tests/mul_1.c new file mode 100644 index 000000000000..2b522fa79295 --- /dev/null +++ b/gnu/lib/libgmp/mpn/tests/mul_1.c @@ -0,0 +1,212 @@ +#include +#include "gmp.h" +#include "gmp-impl.h" +#include "longlong.h" + +#ifndef USG +#include +#include + +unsigned long +cputime () +{ + struct rusage rus; + + getrusage (0, &rus); + return rus.ru_utime.tv_sec * 1000 + rus.ru_utime.tv_usec / 1000; +} +#else +#include + +#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/gnu/lib/libgmp/mpn/tests/rshift.c b/gnu/lib/libgmp/mpn/tests/rshift.c new file mode 100644 index 000000000000..2482bf3407e5 --- /dev/null +++ b/gnu/lib/libgmp/mpn/tests/rshift.c @@ -0,0 +1,227 @@ +#include +#include "gmp.h" +#include "gmp-impl.h" +#include "longlong.h" + +#ifndef USG +#include +#include + +unsigned long +cputime () +{ + struct rusage rus; + + getrusage (0, &rus); + return rus.ru_utime.tv_sec * 1000 + rus.ru_utime.tv_usec / 1000; +} +#else +#include + +#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/gnu/lib/libgmp/mpn/tests/sub_n.c b/gnu/lib/libgmp/mpn/tests/sub_n.c new file mode 100644 index 000000000000..2b9031bbfefd --- /dev/null +++ b/gnu/lib/libgmp/mpn/tests/sub_n.c @@ -0,0 +1,211 @@ +#include +#include "gmp.h" +#include "gmp-impl.h" + +#ifndef USG +#include +#include + +unsigned long +cputime () +{ + struct rusage rus; + + getrusage (0, &rus); + return rus.ru_utime.tv_sec * 1000 + rus.ru_utime.tv_usec / 1000; +} +#else +#include + +#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/gnu/lib/libgmp/mpn/tests/submul_1.c b/gnu/lib/libgmp/mpn/tests/submul_1.c new file mode 100644 index 000000000000..0e464e61328f --- /dev/null +++ b/gnu/lib/libgmp/mpn/tests/submul_1.c @@ -0,0 +1,218 @@ +#include +#include "gmp.h" +#include "gmp-impl.h" +#include "longlong.h" + +#ifndef USG +#include +#include + +unsigned long +cputime () +{ + struct rusage rus; + + getrusage (0, &rus); + return rus.ru_utime.tv_sec * 1000 + rus.ru_utime.tv_usec / 1000; +} +#else +#include + +#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/gnu/lib/libgmp/mpn/tests/tst-addsub.c b/gnu/lib/libgmp/mpn/tests/tst-addsub.c new file mode 100644 index 000000000000..e02b9d5cc76e --- /dev/null +++ b/gnu/lib/libgmp/mpn/tests/tst-addsub.c @@ -0,0 +1,164 @@ +#include +#include +#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/gnu/lib/libgmp/mpn/x86/add_n.S b/gnu/lib/libgmp/mpn/x86/add_n.S new file mode 100644 index 000000000000..5bbbd0d88c07 --- /dev/null +++ b/gnu/lib/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/gnu/lib/libgmp/mpn/x86/addmul_1.S b/gnu/lib/libgmp/mpn/x86/addmul_1.S new file mode 100644 index 000000000000..c11209d925ef --- /dev/null +++ b/gnu/lib/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/gnu/lib/libgmp/mpn/x86/lshift.S b/gnu/lib/libgmp/mpn/x86/lshift.S new file mode 100644 index 000000000000..8173b92cbe41 --- /dev/null +++ b/gnu/lib/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/gnu/lib/libgmp/mpn/x86/mul_1.S b/gnu/lib/libgmp/mpn/x86/mul_1.S new file mode 100644 index 000000000000..b27139998017 --- /dev/null +++ b/gnu/lib/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/gnu/lib/libgmp/mpn/x86/pentium/README b/gnu/lib/libgmp/mpn/x86/pentium/README new file mode 100644 index 000000000000..d73b0826848a --- /dev/null +++ b/gnu/lib/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/gnu/lib/libgmp/mpn/x86/pentium/add_n.S b/gnu/lib/libgmp/mpn/x86/pentium/add_n.S new file mode 100644 index 000000000000..ac6f2819b258 --- /dev/null +++ b/gnu/lib/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/gnu/lib/libgmp/mpn/x86/pentium/addmul_1.S b/gnu/lib/libgmp/mpn/x86/pentium/addmul_1.S new file mode 100644 index 000000000000..7cfa5db6877a --- /dev/null +++ b/gnu/lib/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/gnu/lib/libgmp/mpn/x86/pentium/lshift.S b/gnu/lib/libgmp/mpn/x86/pentium/lshift.S new file mode 100644 index 000000000000..b29898356318 --- /dev/null +++ b/gnu/lib/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/gnu/lib/libgmp/mpn/x86/pentium/mul_1.S b/gnu/lib/libgmp/mpn/x86/pentium/mul_1.S new file mode 100644 index 000000000000..4ac3050a6116 --- /dev/null +++ b/gnu/lib/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/gnu/lib/libgmp/mpn/x86/pentium/rshift.S b/gnu/lib/libgmp/mpn/x86/pentium/rshift.S new file mode 100644 index 000000000000..38398edb13bf --- /dev/null +++ b/gnu/lib/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/gnu/lib/libgmp/mpn/x86/pentium/sub_n.S b/gnu/lib/libgmp/mpn/x86/pentium/sub_n.S new file mode 100644 index 000000000000..d1a2bc08403b --- /dev/null +++ b/gnu/lib/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/gnu/lib/libgmp/mpn/x86/pentium/submul_1.S b/gnu/lib/libgmp/mpn/x86/pentium/submul_1.S new file mode 100644 index 000000000000..adf2d63e6843 --- /dev/null +++ b/gnu/lib/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/gnu/lib/libgmp/mpn/x86/rshift.S b/gnu/lib/libgmp/mpn/x86/rshift.S new file mode 100644 index 000000000000..9abbf9a45d29 --- /dev/null +++ b/gnu/lib/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/gnu/lib/libgmp/mpn/x86/sub_n.S b/gnu/lib/libgmp/mpn/x86/sub_n.S new file mode 100644 index 000000000000..1774f3abe60c --- /dev/null +++ b/gnu/lib/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/gnu/lib/libgmp/mpn/x86/submul_1.S b/gnu/lib/libgmp/mpn/x86/submul_1.S new file mode 100644 index 000000000000..730e732045cb --- /dev/null +++ b/gnu/lib/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/gnu/lib/libgmp/mpn/x86/syntax.h b/gnu/lib/libgmp/mpn/x86/syntax.h new file mode 100644 index 000000000000..c53c73c03f3c --- /dev/null +++ b/gnu/lib/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/gnu/lib/libgmp/mpq/Makefile.in b/gnu/lib/libgmp/mpq/Makefile.in new file mode 100644 index 000000000000..f34ffb928a33 --- /dev/null +++ b/gnu/lib/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/gnu/lib/libgmp/mpq/add.c b/gnu/lib/libgmp/mpq/add.c new file mode 100644 index 000000000000..6b98b469e833 --- /dev/null +++ b/gnu/lib/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/gnu/lib/libgmp/mpq/canonicalize.c b/gnu/lib/libgmp/mpq/canonicalize.c new file mode 100644 index 000000000000..901e6eb6c099 --- /dev/null +++ b/gnu/lib/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/gnu/lib/libgmp/mpq/clear.c b/gnu/lib/libgmp/mpq/clear.c new file mode 100644 index 000000000000..2837cf2ad9fe --- /dev/null +++ b/gnu/lib/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/gnu/lib/libgmp/mpq/cmp.c b/gnu/lib/libgmp/mpq/cmp.c new file mode 100644 index 000000000000..fc530e39540a --- /dev/null +++ b/gnu/lib/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/gnu/lib/libgmp/mpq/cmp_ui.c b/gnu/lib/libgmp/mpq/cmp_ui.c new file mode 100644 index 000000000000..bdecec5f8e39 --- /dev/null +++ b/gnu/lib/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/gnu/lib/libgmp/mpq/configure.in b/gnu/lib/libgmp/mpq/configure.in new file mode 100644 index 000000000000..b5d501ccfd9a --- /dev/null +++ b/gnu/lib/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/gnu/lib/libgmp/mpq/div.c b/gnu/lib/libgmp/mpq/div.c new file mode 100644 index 000000000000..cd1f38817845 --- /dev/null +++ b/gnu/lib/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/gnu/lib/libgmp/mpq/equal.c b/gnu/lib/libgmp/mpq/equal.c new file mode 100644 index 000000000000..2b4bb5b9fc6b --- /dev/null +++ b/gnu/lib/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/gnu/lib/libgmp/mpq/get_d.c b/gnu/lib/libgmp/mpq/get_d.c new file mode 100644 index 000000000000..cb4e800d381f --- /dev/null +++ b/gnu/lib/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/gnu/lib/libgmp/mpq/get_den.c b/gnu/lib/libgmp/mpq/get_den.c new file mode 100644 index 000000000000..fc5e3871e75f --- /dev/null +++ b/gnu/lib/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/gnu/lib/libgmp/mpq/get_num.c b/gnu/lib/libgmp/mpq/get_num.c new file mode 100644 index 000000000000..61f812fa7e56 --- /dev/null +++ b/gnu/lib/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/gnu/lib/libgmp/mpq/init.c b/gnu/lib/libgmp/mpq/init.c new file mode 100644 index 000000000000..ae6d8b396e54 --- /dev/null +++ b/gnu/lib/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/gnu/lib/libgmp/mpq/inv.c b/gnu/lib/libgmp/mpq/inv.c new file mode 100644 index 000000000000..745c78d058ed --- /dev/null +++ b/gnu/lib/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/gnu/lib/libgmp/mpq/mul.c b/gnu/lib/libgmp/mpq/mul.c new file mode 100644 index 000000000000..35f960c85a14 --- /dev/null +++ b/gnu/lib/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/gnu/lib/libgmp/mpq/neg.c b/gnu/lib/libgmp/mpq/neg.c new file mode 100644 index 000000000000..ac54d271f9c5 --- /dev/null +++ b/gnu/lib/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/gnu/lib/libgmp/mpq/set.c b/gnu/lib/libgmp/mpq/set.c new file mode 100644 index 000000000000..ef85639c5989 --- /dev/null +++ b/gnu/lib/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/gnu/lib/libgmp/mpq/set_den.c b/gnu/lib/libgmp/mpq/set_den.c new file mode 100644 index 000000000000..4586c89f6463 --- /dev/null +++ b/gnu/lib/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/gnu/lib/libgmp/mpq/set_num.c b/gnu/lib/libgmp/mpq/set_num.c new file mode 100644 index 000000000000..ce918ce2a6ff --- /dev/null +++ b/gnu/lib/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/gnu/lib/libgmp/mpq/set_si.c b/gnu/lib/libgmp/mpq/set_si.c new file mode 100644 index 000000000000..cf1f9f0a12ec --- /dev/null +++ b/gnu/lib/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/gnu/lib/libgmp/mpq/set_ui.c b/gnu/lib/libgmp/mpq/set_ui.c new file mode 100644 index 000000000000..aaa9fc282900 --- /dev/null +++ b/gnu/lib/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/gnu/lib/libgmp/mpq/set_z.c b/gnu/lib/libgmp/mpq/set_z.c new file mode 100644 index 000000000000..ca638f3aa140 --- /dev/null +++ b/gnu/lib/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/gnu/lib/libgmp/mpq/sub.c b/gnu/lib/libgmp/mpq/sub.c new file mode 100644 index 000000000000..9274ff8cb502 --- /dev/null +++ b/gnu/lib/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/gnu/lib/libgmp/mpq/tests/Makefile.in b/gnu/lib/libgmp/mpq/tests/Makefile.in new file mode 100644 index 000000000000..d7921c0f36c8 --- /dev/null +++ b/gnu/lib/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/gnu/lib/libgmp/mpq/tests/configure.in b/gnu/lib/libgmp/mpq/tests/configure.in new file mode 100644 index 000000000000..5ee2138acd53 --- /dev/null +++ b/gnu/lib/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/gnu/lib/libgmp/mpq/tests/t-cmp.c b/gnu/lib/libgmp/mpq/tests/t-cmp.c new file mode 100644 index 000000000000..77e46f208514 --- /dev/null +++ b/gnu/lib/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 +#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/gnu/lib/libgmp/mpq/tests/t-cmp_ui.c b/gnu/lib/libgmp/mpq/tests/t-cmp_ui.c new file mode 100644 index 000000000000..f7b92ada39a9 --- /dev/null +++ b/gnu/lib/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/gnu/lib/libgmp/mpq/tests/t-get_d.c b/gnu/lib/libgmp/mpq/tests/t-get_d.c new file mode 100644 index 000000000000..db4f92633582 --- /dev/null +++ b/gnu/lib/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 +#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/gnu/lib/libgmp/mpz/Makefile.in b/gnu/lib/libgmp/mpz/Makefile.in new file mode 100644 index 000000000000..497f09ca8ec4 --- /dev/null +++ b/gnu/lib/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/gnu/lib/libgmp/mpz/abs.c b/gnu/lib/libgmp/mpz/abs.c new file mode 100644 index 000000000000..080cac60aa25 --- /dev/null +++ b/gnu/lib/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/gnu/lib/libgmp/mpz/add.c b/gnu/lib/libgmp/mpz/add.c new file mode 100644 index 000000000000..10dd9704c2f4 --- /dev/null +++ b/gnu/lib/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/gnu/lib/libgmp/mpz/add_ui.c b/gnu/lib/libgmp/mpz/add_ui.c new file mode 100644 index 000000000000..a1e430631970 --- /dev/null +++ b/gnu/lib/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/gnu/lib/libgmp/mpz/and.c b/gnu/lib/libgmp/mpz/and.c new file mode 100644 index 000000000000..838d4b1db16f --- /dev/null +++ b/gnu/lib/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/gnu/lib/libgmp/mpz/array_init.c b/gnu/lib/libgmp/mpz/array_init.c new file mode 100644 index 000000000000..8b2e85c90baf --- /dev/null +++ b/gnu/lib/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/gnu/lib/libgmp/mpz/cdiv_q.c b/gnu/lib/libgmp/mpz/cdiv_q.c new file mode 100644 index 000000000000..860a232f0535 --- /dev/null +++ b/gnu/lib/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/gnu/lib/libgmp/mpz/cdiv_q_ui.c b/gnu/lib/libgmp/mpz/cdiv_q_ui.c new file mode 100644 index 000000000000..7b6cfd7af8e4 --- /dev/null +++ b/gnu/lib/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/gnu/lib/libgmp/mpz/cdiv_qr.c b/gnu/lib/libgmp/mpz/cdiv_qr.c new file mode 100644 index 000000000000..bf7d6dacb1f2 --- /dev/null +++ b/gnu/lib/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/gnu/lib/libgmp/mpz/cdiv_qr_ui.c b/gnu/lib/libgmp/mpz/cdiv_qr_ui.c new file mode 100644 index 000000000000..a780e772ecd0 --- /dev/null +++ b/gnu/lib/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/gnu/lib/libgmp/mpz/cdiv_r.c b/gnu/lib/libgmp/mpz/cdiv_r.c new file mode 100644 index 000000000000..d34d138ce786 --- /dev/null +++ b/gnu/lib/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/gnu/lib/libgmp/mpz/cdiv_r_ui.c b/gnu/lib/libgmp/mpz/cdiv_r_ui.c new file mode 100644 index 000000000000..757a3f5f7ba4 --- /dev/null +++ b/gnu/lib/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/gnu/lib/libgmp/mpz/cdiv_ui.c b/gnu/lib/libgmp/mpz/cdiv_ui.c new file mode 100644 index 000000000000..df841ede8851 --- /dev/null +++ b/gnu/lib/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/gnu/lib/libgmp/mpz/clear.c b/gnu/lib/libgmp/mpz/clear.c new file mode 100644 index 000000000000..00f3cfdc62ec --- /dev/null +++ b/gnu/lib/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/gnu/lib/libgmp/mpz/clrbit.c b/gnu/lib/libgmp/mpz/clrbit.c new file mode 100644 index 000000000000..59d956535831 --- /dev/null +++ b/gnu/lib/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/gnu/lib/libgmp/mpz/cmp.c b/gnu/lib/libgmp/mpz/cmp.c new file mode 100644 index 000000000000..37be3349a6a1 --- /dev/null +++ b/gnu/lib/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/gnu/lib/libgmp/mpz/cmp_si.c b/gnu/lib/libgmp/mpz/cmp_si.c new file mode 100644 index 000000000000..8063fd386e34 --- /dev/null +++ b/gnu/lib/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/gnu/lib/libgmp/mpz/cmp_ui.c b/gnu/lib/libgmp/mpz/cmp_ui.c new file mode 100644 index 000000000000..1a50b96e1ac9 --- /dev/null +++ b/gnu/lib/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/gnu/lib/libgmp/mpz/com.c b/gnu/lib/libgmp/mpz/com.c new file mode 100644 index 000000000000..559f2b6b2b03 --- /dev/null +++ b/gnu/lib/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/gnu/lib/libgmp/mpz/configure.in b/gnu/lib/libgmp/mpz/configure.in new file mode 100644 index 000000000000..ed84461c1d2d --- /dev/null +++ b/gnu/lib/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/gnu/lib/libgmp/mpz/divexact.c b/gnu/lib/libgmp/mpz/divexact.c new file mode 100644 index 000000000000..b8974480468c --- /dev/null +++ b/gnu/lib/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/gnu/lib/libgmp/mpz/dmincl.c b/gnu/lib/libgmp/mpz/dmincl.c new file mode 100644 index 000000000000..51bd084870c3 --- /dev/null +++ b/gnu/lib/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/gnu/lib/libgmp/mpz/fac_ui.c b/gnu/lib/libgmp/mpz/fac_ui.c new file mode 100644 index 000000000000..a170060a544e --- /dev/null +++ b/gnu/lib/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 +#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/gnu/lib/libgmp/mpz/fdiv_q.c b/gnu/lib/libgmp/mpz/fdiv_q.c new file mode 100644 index 000000000000..3da943af9164 --- /dev/null +++ b/gnu/lib/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/gnu/lib/libgmp/mpz/fdiv_q_2exp.c b/gnu/lib/libgmp/mpz/fdiv_q_2exp.c new file mode 100644 index 000000000000..3f56baff2c5a --- /dev/null +++ b/gnu/lib/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/gnu/lib/libgmp/mpz/fdiv_q_ui.c b/gnu/lib/libgmp/mpz/fdiv_q_ui.c new file mode 100644 index 000000000000..3d6825d4fee2 --- /dev/null +++ b/gnu/lib/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/gnu/lib/libgmp/mpz/fdiv_qr.c b/gnu/lib/libgmp/mpz/fdiv_qr.c new file mode 100644 index 000000000000..2abb16ccbd7c --- /dev/null +++ b/gnu/lib/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/gnu/lib/libgmp/mpz/fdiv_qr_ui.c b/gnu/lib/libgmp/mpz/fdiv_qr_ui.c new file mode 100644 index 000000000000..a22b702a8def --- /dev/null +++ b/gnu/lib/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/gnu/lib/libgmp/mpz/fdiv_r.c b/gnu/lib/libgmp/mpz/fdiv_r.c new file mode 100644 index 000000000000..14e045bbe597 --- /dev/null +++ b/gnu/lib/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/gnu/lib/libgmp/mpz/fdiv_r_2exp.c b/gnu/lib/libgmp/mpz/fdiv_r_2exp.c new file mode 100644 index 000000000000..04190b1b0aae --- /dev/null +++ b/gnu/lib/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/gnu/lib/libgmp/mpz/fdiv_r_ui.c b/gnu/lib/libgmp/mpz/fdiv_r_ui.c new file mode 100644 index 000000000000..c4c37498ced7 --- /dev/null +++ b/gnu/lib/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/gnu/lib/libgmp/mpz/fdiv_ui.c b/gnu/lib/libgmp/mpz/fdiv_ui.c new file mode 100644 index 000000000000..4d018a2291bf --- /dev/null +++ b/gnu/lib/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/gnu/lib/libgmp/mpz/gcd.c b/gnu/lib/libgmp/mpz/gcd.c new file mode 100644 index 000000000000..f93030c8f4c5 --- /dev/null +++ b/gnu/lib/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/gnu/lib/libgmp/mpz/gcd_ui.c b/gnu/lib/libgmp/mpz/gcd_ui.c new file mode 100644 index 000000000000..388ab05cc9cc --- /dev/null +++ b/gnu/lib/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/gnu/lib/libgmp/mpz/gcdext.c b/gnu/lib/libgmp/mpz/gcdext.c new file mode 100644 index 000000000000..adf66b04af26 --- /dev/null +++ b/gnu/lib/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/gnu/lib/libgmp/mpz/get_d.c b/gnu/lib/libgmp/mpz/get_d.c new file mode 100644 index 000000000000..0fd7916eafd0 --- /dev/null +++ b/gnu/lib/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/gnu/lib/libgmp/mpz/get_si.c b/gnu/lib/libgmp/mpz/get_si.c new file mode 100644 index 000000000000..45e0e5aecf68 --- /dev/null +++ b/gnu/lib/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/gnu/lib/libgmp/mpz/get_str.c b/gnu/lib/libgmp/mpz/get_str.c new file mode 100644 index 000000000000..8ccf3efcd0eb --- /dev/null +++ b/gnu/lib/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/gnu/lib/libgmp/mpz/get_ui.c b/gnu/lib/libgmp/mpz/get_ui.c new file mode 100644 index 000000000000..4bfb5e14db53 --- /dev/null +++ b/gnu/lib/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/gnu/lib/libgmp/mpz/getlimbn.c b/gnu/lib/libgmp/mpz/getlimbn.c new file mode 100644 index 000000000000..c7a234b5ab24 --- /dev/null +++ b/gnu/lib/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/gnu/lib/libgmp/mpz/hamdist.c b/gnu/lib/libgmp/mpz/hamdist.c new file mode 100644 index 000000000000..58c927316a5d --- /dev/null +++ b/gnu/lib/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/gnu/lib/libgmp/mpz/init.c b/gnu/lib/libgmp/mpz/init.c new file mode 100644 index 000000000000..f8d8e207e4b2 --- /dev/null +++ b/gnu/lib/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/gnu/lib/libgmp/mpz/inp_raw.c b/gnu/lib/libgmp/mpz/inp_raw.c new file mode 100644 index 000000000000..e1cec1d743c0 --- /dev/null +++ b/gnu/lib/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 + +#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/gnu/lib/libgmp/mpz/inp_str.c b/gnu/lib/libgmp/mpz/inp_str.c new file mode 100644 index 000000000000..715906237ee0 --- /dev/null +++ b/gnu/lib/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 +#include +#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/gnu/lib/libgmp/mpz/invert.c b/gnu/lib/libgmp/mpz/invert.c new file mode 100644 index 000000000000..ff1d6d937dd6 --- /dev/null +++ b/gnu/lib/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/gnu/lib/libgmp/mpz/ior.c b/gnu/lib/libgmp/mpz/ior.c new file mode 100644 index 000000000000..77facfd3d48d --- /dev/null +++ b/gnu/lib/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/gnu/lib/libgmp/mpz/iset.c b/gnu/lib/libgmp/mpz/iset.c new file mode 100644 index 000000000000..c8a17dc67a88 --- /dev/null +++ b/gnu/lib/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/gnu/lib/libgmp/mpz/iset_d.c b/gnu/lib/libgmp/mpz/iset_d.c new file mode 100644 index 000000000000..41e5c4f963bb --- /dev/null +++ b/gnu/lib/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/gnu/lib/libgmp/mpz/iset_si.c b/gnu/lib/libgmp/mpz/iset_si.c new file mode 100644 index 000000000000..af51f0578ab8 --- /dev/null +++ b/gnu/lib/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/gnu/lib/libgmp/mpz/iset_str.c b/gnu/lib/libgmp/mpz/iset_str.c new file mode 100644 index 000000000000..e04ad5da22df --- /dev/null +++ b/gnu/lib/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/gnu/lib/libgmp/mpz/iset_ui.c b/gnu/lib/libgmp/mpz/iset_ui.c new file mode 100644 index 000000000000..dc39f59ff442 --- /dev/null +++ b/gnu/lib/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/gnu/lib/libgmp/mpz/jacobi.c b/gnu/lib/libgmp/mpz/jacobi.c new file mode 100644 index 000000000000..409f622fcef3 --- /dev/null +++ b/gnu/lib/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/gnu/lib/libgmp/mpz/legendre.c b/gnu/lib/libgmp/mpz/legendre.c new file mode 100644 index 000000000000..4de16a63143a --- /dev/null +++ b/gnu/lib/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 +#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/gnu/lib/libgmp/mpz/mod.c b/gnu/lib/libgmp/mpz/mod.c new file mode 100644 index 000000000000..b2b8b39bbed2 --- /dev/null +++ b/gnu/lib/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/gnu/lib/libgmp/mpz/mul.c b/gnu/lib/libgmp/mpz/mul.c new file mode 100644 index 000000000000..47ce8e3548d7 --- /dev/null +++ b/gnu/lib/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/gnu/lib/libgmp/mpz/mul_2exp.c b/gnu/lib/libgmp/mpz/mul_2exp.c new file mode 100644 index 000000000000..4d66a9877e3a --- /dev/null +++ b/gnu/lib/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/gnu/lib/libgmp/mpz/mul_ui.c b/gnu/lib/libgmp/mpz/mul_ui.c new file mode 100644 index 000000000000..f1f72695904b --- /dev/null +++ b/gnu/lib/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/gnu/lib/libgmp/mpz/neg.c b/gnu/lib/libgmp/mpz/neg.c new file mode 100644 index 000000000000..0b48e5c7b4fb --- /dev/null +++ b/gnu/lib/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/gnu/lib/libgmp/mpz/out_raw.c b/gnu/lib/libgmp/mpz/out_raw.c new file mode 100644 index 000000000000..35d311b43874 --- /dev/null +++ b/gnu/lib/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 + +#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/gnu/lib/libgmp/mpz/out_str.c b/gnu/lib/libgmp/mpz/out_str.c new file mode 100644 index 000000000000..909f53346d23 --- /dev/null +++ b/gnu/lib/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 +#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/gnu/lib/libgmp/mpz/perfsqr.c b/gnu/lib/libgmp/mpz/perfsqr.c new file mode 100644 index 000000000000..cdf1b5a27114 --- /dev/null +++ b/gnu/lib/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/gnu/lib/libgmp/mpz/popcount.c b/gnu/lib/libgmp/mpz/popcount.c new file mode 100644 index 000000000000..a97938030938 --- /dev/null +++ b/gnu/lib/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/gnu/lib/libgmp/mpz/pow_ui.c b/gnu/lib/libgmp/mpz/pow_ui.c new file mode 100644 index 000000000000..d8cf7a610684 --- /dev/null +++ b/gnu/lib/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/gnu/lib/libgmp/mpz/powm.c b/gnu/lib/libgmp/mpz/powm.c new file mode 100644 index 000000000000..5dcd1b128248 --- /dev/null +++ b/gnu/lib/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/gnu/lib/libgmp/mpz/powm_ui.c b/gnu/lib/libgmp/mpz/powm_ui.c new file mode 100644 index 000000000000..596815a0ea4c --- /dev/null +++ b/gnu/lib/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/gnu/lib/libgmp/mpz/pprime_p.c b/gnu/lib/libgmp/mpz/pprime_p.c new file mode 100644 index 000000000000..494de14cae56 --- /dev/null +++ b/gnu/lib/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/gnu/lib/libgmp/mpz/random.c b/gnu/lib/libgmp/mpz/random.c new file mode 100644 index 000000000000..ab41eef92664 --- /dev/null +++ b/gnu/lib/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/gnu/lib/libgmp/mpz/random2.c b/gnu/lib/libgmp/mpz/random2.c new file mode 100644 index 000000000000..725a8b49143d --- /dev/null +++ b/gnu/lib/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/gnu/lib/libgmp/mpz/realloc.c b/gnu/lib/libgmp/mpz/realloc.c new file mode 100644 index 000000000000..2c2a5da927e8 --- /dev/null +++ b/gnu/lib/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/gnu/lib/libgmp/mpz/scan0.c b/gnu/lib/libgmp/mpz/scan0.c new file mode 100644 index 000000000000..8e45aa32482e --- /dev/null +++ b/gnu/lib/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/gnu/lib/libgmp/mpz/scan1.c b/gnu/lib/libgmp/mpz/scan1.c new file mode 100644 index 000000000000..6ecb0aab3866 --- /dev/null +++ b/gnu/lib/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/gnu/lib/libgmp/mpz/set.c b/gnu/lib/libgmp/mpz/set.c new file mode 100644 index 000000000000..d94ab7485b74 --- /dev/null +++ b/gnu/lib/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/gnu/lib/libgmp/mpz/set_d.c b/gnu/lib/libgmp/mpz/set_d.c new file mode 100644 index 000000000000..c09b1d97e6f3 --- /dev/null +++ b/gnu/lib/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/gnu/lib/libgmp/mpz/set_f.c b/gnu/lib/libgmp/mpz/set_f.c new file mode 100644 index 000000000000..9547907bb3df --- /dev/null +++ b/gnu/lib/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/gnu/lib/libgmp/mpz/set_q.c b/gnu/lib/libgmp/mpz/set_q.c new file mode 100644 index 000000000000..61bd5c70d9c7 --- /dev/null +++ b/gnu/lib/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/gnu/lib/libgmp/mpz/set_si.c b/gnu/lib/libgmp/mpz/set_si.c new file mode 100644 index 000000000000..82a90a3cc19a --- /dev/null +++ b/gnu/lib/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/gnu/lib/libgmp/mpz/set_str.c b/gnu/lib/libgmp/mpz/set_str.c new file mode 100644 index 000000000000..d1334b1e0070 --- /dev/null +++ b/gnu/lib/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 +#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/gnu/lib/libgmp/mpz/set_ui.c b/gnu/lib/libgmp/mpz/set_ui.c new file mode 100644 index 000000000000..73f6cf54adb0 --- /dev/null +++ b/gnu/lib/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/gnu/lib/libgmp/mpz/setbit.c b/gnu/lib/libgmp/mpz/setbit.c new file mode 100644 index 000000000000..af59e2cc786b --- /dev/null +++ b/gnu/lib/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/gnu/lib/libgmp/mpz/size.c b/gnu/lib/libgmp/mpz/size.c new file mode 100644 index 000000000000..0b09fbeb0770 --- /dev/null +++ b/gnu/lib/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/gnu/lib/libgmp/mpz/sizeinbase.c b/gnu/lib/libgmp/mpz/sizeinbase.c new file mode 100644 index 000000000000..51bd5558acb5 --- /dev/null +++ b/gnu/lib/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/gnu/lib/libgmp/mpz/sqrt.c b/gnu/lib/libgmp/mpz/sqrt.c new file mode 100644 index 000000000000..44c554eb5c9d --- /dev/null +++ b/gnu/lib/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/gnu/lib/libgmp/mpz/sqrtrem.c b/gnu/lib/libgmp/mpz/sqrtrem.c new file mode 100644 index 000000000000..757cc5dd569c --- /dev/null +++ b/gnu/lib/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/gnu/lib/libgmp/mpz/sub.c b/gnu/lib/libgmp/mpz/sub.c new file mode 100644 index 000000000000..56ef1a12a2b0 --- /dev/null +++ b/gnu/lib/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/gnu/lib/libgmp/mpz/sub_ui.c b/gnu/lib/libgmp/mpz/sub_ui.c new file mode 100644 index 000000000000..7dea4b6c03ef --- /dev/null +++ b/gnu/lib/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/gnu/lib/libgmp/mpz/tdiv_q.c b/gnu/lib/libgmp/mpz/tdiv_q.c new file mode 100644 index 000000000000..b4d36368b8c9 --- /dev/null +++ b/gnu/lib/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/gnu/lib/libgmp/mpz/tdiv_q_2exp.c b/gnu/lib/libgmp/mpz/tdiv_q_2exp.c new file mode 100644 index 000000000000..e70d810e7ffc --- /dev/null +++ b/gnu/lib/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/gnu/lib/libgmp/mpz/tdiv_q_ui.c b/gnu/lib/libgmp/mpz/tdiv_q_ui.c new file mode 100644 index 000000000000..9048e0aef560 --- /dev/null +++ b/gnu/lib/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/gnu/lib/libgmp/mpz/tdiv_qr.c b/gnu/lib/libgmp/mpz/tdiv_qr.c new file mode 100644 index 000000000000..500e19939a78 --- /dev/null +++ b/gnu/lib/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/gnu/lib/libgmp/mpz/tdiv_qr_ui.c b/gnu/lib/libgmp/mpz/tdiv_qr_ui.c new file mode 100644 index 000000000000..cb5041cdc598 --- /dev/null +++ b/gnu/lib/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/gnu/lib/libgmp/mpz/tdiv_r.c b/gnu/lib/libgmp/mpz/tdiv_r.c new file mode 100644 index 000000000000..813a0d4d79cd --- /dev/null +++ b/gnu/lib/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/gnu/lib/libgmp/mpz/tdiv_r_2exp.c b/gnu/lib/libgmp/mpz/tdiv_r_2exp.c new file mode 100644 index 000000000000..99d617e9f34e --- /dev/null +++ b/gnu/lib/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/gnu/lib/libgmp/mpz/tdiv_r_ui.c b/gnu/lib/libgmp/mpz/tdiv_r_ui.c new file mode 100644 index 000000000000..0428b52c3aa9 --- /dev/null +++ b/gnu/lib/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/gnu/lib/libgmp/mpz/tests/Makefile.in b/gnu/lib/libgmp/mpz/tests/Makefile.in new file mode 100644 index 000000000000..5a0cf599e109 --- /dev/null +++ b/gnu/lib/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/gnu/lib/libgmp/mpz/tests/configure.in b/gnu/lib/libgmp/mpz/tests/configure.in new file mode 100644 index 000000000000..dacc177418d8 --- /dev/null +++ b/gnu/lib/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/gnu/lib/libgmp/mpz/tests/convert.c b/gnu/lib/libgmp/mpz/tests/convert.c new file mode 100644 index 000000000000..1d8237099cad --- /dev/null +++ b/gnu/lib/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 +#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/gnu/lib/libgmp/mpz/tests/dive.c b/gnu/lib/libgmp/mpz/tests/dive.c new file mode 100644 index 000000000000..8d3516d83a68 --- /dev/null +++ b/gnu/lib/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 +#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/gnu/lib/libgmp/mpz/tests/io-binary.c b/gnu/lib/libgmp/mpz/tests/io-binary.c new file mode 100644 index 000000000000..c28f2a5ba735 --- /dev/null +++ b/gnu/lib/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 +#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/gnu/lib/libgmp/mpz/tests/io.c b/gnu/lib/libgmp/mpz/tests/io.c new file mode 100644 index 000000000000..3dfa9a569e9d --- /dev/null +++ b/gnu/lib/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 +#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/gnu/lib/libgmp/mpz/tests/logic.c b/gnu/lib/libgmp/mpz/tests/logic.c new file mode 100644 index 000000000000..41a8cac90831 --- /dev/null +++ b/gnu/lib/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 +#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/gnu/lib/libgmp/mpz/tests/reuse.c b/gnu/lib/libgmp/mpz/tests/reuse.c new file mode 100644 index 000000000000..52fc5a516772 --- /dev/null +++ b/gnu/lib/libgmp/mpz/tests/reuse.c @@ -0,0 +1,135 @@ +/* Test that routines allow reusing a source variable as destination. */ + +#include +#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/gnu/lib/libgmp/mpz/tests/t-fdiv.c b/gnu/lib/libgmp/mpz/tests/t-fdiv.c new file mode 100644 index 000000000000..9de22d703f38 --- /dev/null +++ b/gnu/lib/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 +#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/gnu/lib/libgmp/mpz/tests/t-fdiv_ui.c b/gnu/lib/libgmp/mpz/tests/t-fdiv_ui.c new file mode 100644 index 000000000000..74ba9fcf7b2b --- /dev/null +++ b/gnu/lib/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 +#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/gnu/lib/libgmp/mpz/tests/t-gcd.c b/gnu/lib/libgmp/mpz/tests/t-gcd.c new file mode 100644 index 000000000000..d9a78843a27b --- /dev/null +++ b/gnu/lib/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 +#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/gnu/lib/libgmp/mpz/tests/t-gcd2.c b/gnu/lib/libgmp/mpz/tests/t-gcd2.c new file mode 100644 index 000000000000..b7ad67c034df --- /dev/null +++ b/gnu/lib/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 +#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/gnu/lib/libgmp/mpz/tests/t-mul.c b/gnu/lib/libgmp/mpz/tests/t-mul.c new file mode 100644 index 000000000000..b200cd7585d5 --- /dev/null +++ b/gnu/lib/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 +#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/gnu/lib/libgmp/mpz/tests/t-powm.c b/gnu/lib/libgmp/mpz/tests/t-powm.c new file mode 100644 index 000000000000..02d7ca5d0548 --- /dev/null +++ b/gnu/lib/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 +#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/gnu/lib/libgmp/mpz/tests/t-powm_ui.c b/gnu/lib/libgmp/mpz/tests/t-powm_ui.c new file mode 100644 index 000000000000..b88fa982077d --- /dev/null +++ b/gnu/lib/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 +#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/gnu/lib/libgmp/mpz/tests/t-sqrtrem.c b/gnu/lib/libgmp/mpz/tests/t-sqrtrem.c new file mode 100644 index 000000000000..f5fcd09bcdde --- /dev/null +++ b/gnu/lib/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 +#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/gnu/lib/libgmp/mpz/tests/t-tdiv.c b/gnu/lib/libgmp/mpz/tests/t-tdiv.c new file mode 100644 index 000000000000..d646ed8c59dd --- /dev/null +++ b/gnu/lib/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 +#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/gnu/lib/libgmp/mpz/tests/t-tdiv_ui.c b/gnu/lib/libgmp/mpz/tests/t-tdiv_ui.c new file mode 100644 index 000000000000..8d73b1108162 --- /dev/null +++ b/gnu/lib/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 +#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/gnu/lib/libgmp/mpz/ui_pow_ui.c b/gnu/lib/libgmp/mpz/ui_pow_ui.c new file mode 100644 index 000000000000..19baca14b48f --- /dev/null +++ b/gnu/lib/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/gnu/lib/libgmp/stack-alloc.c b/gnu/lib/libgmp/stack-alloc.c new file mode 100644 index 000000000000..d9619f6222c9 --- /dev/null +++ b/gnu/lib/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 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. 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 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/gnu/lib/libgmp/stack-alloc.h b/gnu/lib/libgmp/stack-alloc.h new file mode 100644 index 000000000000..a84eeff58da4 --- /dev/null +++ b/gnu/lib/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/gnu/lib/libgmp/texinfo.tex b/gnu/lib/libgmp/texinfo.tex new file mode 100644 index 000000000000..1536ac3f0845 --- /dev/null +++ b/gnu/lib/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 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 . + % + \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 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 to achieve this: TeX expands \the only once, +% simply yielding the contents of the . +\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/gnu/lib/libgmp/urandom.h b/gnu/lib/libgmp/urandom.h new file mode 100644 index 000000000000..994e7bd2b5ca --- /dev/null +++ b/gnu/lib/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/gnu/lib/libgmp/version.c b/gnu/lib/libgmp/version.c new file mode 100644 index 000000000000..70502394b3ec --- /dev/null +++ b/gnu/lib/libgmp/version.c @@ -0,0 +1 @@ +static char *gmp_version = "2.0.1";