From d938bb78837327b46dc34873a6eb60c002605808 Mon Sep 17 00:00:00 2001 From: markm Date: Sun, 12 Nov 1995 14:40:41 +0000 Subject: GNU MP (Multiprecision) library. This is needed by secure RPC (being done by Bill Paul) and various other BSD programs. Obtained from:FSF --- gnu/lib/libgmp/COPYING | 339 +++++++++ gnu/lib/libgmp/ChangeLog | 1347 ++++++++++++++++++++++++++++++++++++ gnu/lib/libgmp/INSTALL | 34 + gnu/lib/libgmp/README | 61 ++ gnu/lib/libgmp/TODO | 184 +++++ gnu/lib/libgmp/VERSION | 1 + gnu/lib/libgmp/_mpz_get_str.c | 309 +++++++++ gnu/lib/libgmp/_mpz_set_str.c | 258 +++++++ gnu/lib/libgmp/alloca.c | 466 +++++++++++++ gnu/lib/libgmp/cre-conv-tab.c | 141 ++++ gnu/lib/libgmp/cre-mparam.c | 118 ++++ gnu/lib/libgmp/cre-stddefh.c | 42 ++ gnu/lib/libgmp/gmp-impl.h | 126 ++++ gnu/lib/libgmp/gmp.h | 302 ++++++++ gnu/lib/libgmp/gmp.texi | 1291 ++++++++++++++++++++++++++++++++++ gnu/lib/libgmp/itom.c | 53 ++ gnu/lib/libgmp/longlong.h | 1027 +++++++++++++++++++++++++++ gnu/lib/libgmp/mdiv.c | 38 + gnu/lib/libgmp/memory.c | 96 +++ gnu/lib/libgmp/mfree.c | 35 + gnu/lib/libgmp/min.c | 64 ++ gnu/lib/libgmp/mout.c | 42 ++ gnu/lib/libgmp/move.c | 45 ++ gnu/lib/libgmp/mp.h | 103 +++ gnu/lib/libgmp/mp_clz_tab.c | 36 + gnu/lib/libgmp/mp_set_fns.c | 47 ++ gnu/lib/libgmp/mpn_add.c | 141 ++++ gnu/lib/libgmp/mpn_cmp.c | 52 ++ gnu/lib/libgmp/mpn_div.c | 321 +++++++++ gnu/lib/libgmp/mpn_dm_1.c | 185 +++++ gnu/lib/libgmp/mpn_lshift.c | 83 +++ gnu/lib/libgmp/mpn_mod_1.c | 104 +++ gnu/lib/libgmp/mpn_mul.c | 414 +++++++++++ gnu/lib/libgmp/mpn_rshift.c | 90 +++ gnu/lib/libgmp/mpn_rshiftci.c | 86 +++ gnu/lib/libgmp/mpn_sqrt.c | 479 +++++++++++++ gnu/lib/libgmp/mpn_sub.c | 162 +++++ gnu/lib/libgmp/mpq_add.c | 85 +++ gnu/lib/libgmp/mpq_clear.c | 34 + gnu/lib/libgmp/mpq_cmp.c | 76 ++ gnu/lib/libgmp/mpq_div.c | 92 +++ gnu/lib/libgmp/mpq_get_den.c | 40 ++ gnu/lib/libgmp/mpq_get_num.c | 41 ++ gnu/lib/libgmp/mpq_init.c | 39 ++ gnu/lib/libgmp/mpq_inv.c | 74 ++ gnu/lib/libgmp/mpq_mul.c | 78 +++ gnu/lib/libgmp/mpq_neg.c | 35 + gnu/lib/libgmp/mpq_set.c | 48 ++ gnu/lib/libgmp/mpq_set_den.c | 46 ++ gnu/lib/libgmp/mpq_set_num.c | 41 ++ gnu/lib/libgmp/mpq_set_si.c | 76 ++ gnu/lib/libgmp/mpq_set_ui.c | 73 ++ gnu/lib/libgmp/mpq_sub.c | 85 +++ gnu/lib/libgmp/mpz_abs.c | 44 ++ gnu/lib/libgmp/mpz_add.c | 121 ++++ gnu/lib/libgmp/mpz_add_ui.c | 84 +++ gnu/lib/libgmp/mpz_and.c | 267 +++++++ gnu/lib/libgmp/mpz_clear.c | 34 + gnu/lib/libgmp/mpz_clrbit.c | 124 ++++ gnu/lib/libgmp/mpz_cmp.c | 84 +++ gnu/lib/libgmp/mpz_cmp_si.c | 62 ++ gnu/lib/libgmp/mpz_cmp_ui.c | 52 ++ gnu/lib/libgmp/mpz_com.c | 96 +++ gnu/lib/libgmp/mpz_div.c | 117 ++++ gnu/lib/libgmp/mpz_div_2exp.c | 53 ++ gnu/lib/libgmp/mpz_div_ui.c | 65 ++ gnu/lib/libgmp/mpz_dm.c | 38 + gnu/lib/libgmp/mpz_dm_ui.c | 81 +++ gnu/lib/libgmp/mpz_dmincl.c | 172 +++++ gnu/lib/libgmp/mpz_fac_ui.c | 156 +++++ gnu/lib/libgmp/mpz_gcd.c | 169 +++++ gnu/lib/libgmp/mpz_gcdext.c | 80 +++ gnu/lib/libgmp/mpz_get_si.c | 40 ++ gnu/lib/libgmp/mpz_get_str.c | 39 ++ gnu/lib/libgmp/mpz_get_ui.c | 36 + gnu/lib/libgmp/mpz_init.c | 35 + gnu/lib/libgmp/mpz_inp_raw.c | 72 ++ gnu/lib/libgmp/mpz_inp_str.c | 105 +++ gnu/lib/libgmp/mpz_ior.c | 242 +++++++ gnu/lib/libgmp/mpz_iset.c | 45 ++ gnu/lib/libgmp/mpz_iset_si.c | 48 ++ gnu/lib/libgmp/mpz_iset_str.c | 42 ++ gnu/lib/libgmp/mpz_iset_ui.c | 43 ++ gnu/lib/libgmp/mpz_mdiv.c | 52 ++ gnu/lib/libgmp/mpz_mdiv_ui.c | 43 ++ gnu/lib/libgmp/mpz_mdm.c | 64 ++ gnu/lib/libgmp/mpz_mdm_ui.c | 58 ++ gnu/lib/libgmp/mpz_mmod.c | 60 ++ gnu/lib/libgmp/mpz_mmod_ui.c | 52 ++ gnu/lib/libgmp/mpz_mod.c | 36 + gnu/lib/libgmp/mpz_mod_2exp.c | 82 +++ gnu/lib/libgmp/mpz_mod_ui.c | 65 ++ gnu/lib/libgmp/mpz_mul.c | 114 +++ gnu/lib/libgmp/mpz_mul_2exp.c | 68 ++ gnu/lib/libgmp/mpz_mul_ui.c | 78 +++ gnu/lib/libgmp/mpz_neg.c | 46 ++ gnu/lib/libgmp/mpz_out_raw.c | 55 ++ gnu/lib/libgmp/mpz_out_str.c | 45 ++ gnu/lib/libgmp/mpz_perfsqr.c | 118 ++++ gnu/lib/libgmp/mpz_pow_ui.c | 110 +++ gnu/lib/libgmp/mpz_powm.c | 251 +++++++ gnu/lib/libgmp/mpz_powm_ui.c | 219 ++++++ gnu/lib/libgmp/mpz_pprime_p.c | 108 +++ gnu/lib/libgmp/mpz_random.c | 68 ++ gnu/lib/libgmp/mpz_random2.c | 88 +++ gnu/lib/libgmp/mpz_realloc.c | 50 ++ gnu/lib/libgmp/mpz_set.c | 45 ++ gnu/lib/libgmp/mpz_set_si.c | 47 ++ gnu/lib/libgmp/mpz_set_str.c | 41 ++ gnu/lib/libgmp/mpz_set_ui.c | 42 ++ gnu/lib/libgmp/mpz_size.c | 34 + gnu/lib/libgmp/mpz_sizeinb.c | 59 ++ gnu/lib/libgmp/mpz_sqrt.c | 87 +++ gnu/lib/libgmp/mpz_sqrtrem.c | 105 +++ gnu/lib/libgmp/mpz_sub.c | 117 ++++ gnu/lib/libgmp/mpz_sub_ui.c | 84 +++ gnu/lib/libgmp/mtox.c | 37 + gnu/lib/libgmp/sdiv.c | 76 ++ gnu/lib/libgmp/tests/Makefile | 64 ++ gnu/lib/libgmp/tests/tst-convert.c | 80 +++ gnu/lib/libgmp/tests/tst-dm.c | 117 ++++ gnu/lib/libgmp/tests/tst-dm_ui.c | 116 ++++ gnu/lib/libgmp/tests/tst-gcd.c | 131 ++++ gnu/lib/libgmp/tests/tst-mdm.c | 117 ++++ gnu/lib/libgmp/tests/tst-mdm_ui.c | 116 ++++ gnu/lib/libgmp/tests/tst-mul.c | 261 +++++++ gnu/lib/libgmp/tests/tst-pow_ui.c | 120 ++++ gnu/lib/libgmp/tests/tst-sqrtrem.c | 97 +++ gnu/lib/libgmp/tests/urandom.h | 17 + gnu/lib/libgmp/xtom.c | 41 ++ 130 files changed, 16312 insertions(+) create mode 100644 gnu/lib/libgmp/COPYING create mode 100644 gnu/lib/libgmp/ChangeLog create mode 100644 gnu/lib/libgmp/INSTALL create mode 100644 gnu/lib/libgmp/README create mode 100644 gnu/lib/libgmp/TODO create mode 100644 gnu/lib/libgmp/VERSION create mode 100644 gnu/lib/libgmp/_mpz_get_str.c create mode 100644 gnu/lib/libgmp/_mpz_set_str.c create mode 100644 gnu/lib/libgmp/alloca.c create mode 100644 gnu/lib/libgmp/cre-conv-tab.c create mode 100644 gnu/lib/libgmp/cre-mparam.c create mode 100644 gnu/lib/libgmp/cre-stddefh.c create mode 100644 gnu/lib/libgmp/gmp-impl.h create mode 100644 gnu/lib/libgmp/gmp.h create mode 100644 gnu/lib/libgmp/gmp.texi create mode 100644 gnu/lib/libgmp/itom.c create mode 100644 gnu/lib/libgmp/longlong.h create mode 100644 gnu/lib/libgmp/mdiv.c create mode 100644 gnu/lib/libgmp/memory.c create mode 100644 gnu/lib/libgmp/mfree.c create mode 100644 gnu/lib/libgmp/min.c create mode 100644 gnu/lib/libgmp/mout.c create mode 100644 gnu/lib/libgmp/move.c create mode 100644 gnu/lib/libgmp/mp.h create mode 100644 gnu/lib/libgmp/mp_clz_tab.c create mode 100644 gnu/lib/libgmp/mp_set_fns.c create mode 100644 gnu/lib/libgmp/mpn_add.c create mode 100644 gnu/lib/libgmp/mpn_cmp.c create mode 100644 gnu/lib/libgmp/mpn_div.c create mode 100644 gnu/lib/libgmp/mpn_dm_1.c create mode 100644 gnu/lib/libgmp/mpn_lshift.c create mode 100644 gnu/lib/libgmp/mpn_mod_1.c create mode 100644 gnu/lib/libgmp/mpn_mul.c create mode 100644 gnu/lib/libgmp/mpn_rshift.c create mode 100644 gnu/lib/libgmp/mpn_rshiftci.c create mode 100644 gnu/lib/libgmp/mpn_sqrt.c create mode 100644 gnu/lib/libgmp/mpn_sub.c create mode 100644 gnu/lib/libgmp/mpq_add.c create mode 100644 gnu/lib/libgmp/mpq_clear.c create mode 100644 gnu/lib/libgmp/mpq_cmp.c create mode 100644 gnu/lib/libgmp/mpq_div.c create mode 100644 gnu/lib/libgmp/mpq_get_den.c create mode 100644 gnu/lib/libgmp/mpq_get_num.c create mode 100644 gnu/lib/libgmp/mpq_init.c create mode 100644 gnu/lib/libgmp/mpq_inv.c create mode 100644 gnu/lib/libgmp/mpq_mul.c create mode 100644 gnu/lib/libgmp/mpq_neg.c create mode 100644 gnu/lib/libgmp/mpq_set.c create mode 100644 gnu/lib/libgmp/mpq_set_den.c create mode 100644 gnu/lib/libgmp/mpq_set_num.c create mode 100644 gnu/lib/libgmp/mpq_set_si.c create mode 100644 gnu/lib/libgmp/mpq_set_ui.c create mode 100644 gnu/lib/libgmp/mpq_sub.c create mode 100644 gnu/lib/libgmp/mpz_abs.c create mode 100644 gnu/lib/libgmp/mpz_add.c create mode 100644 gnu/lib/libgmp/mpz_add_ui.c create mode 100644 gnu/lib/libgmp/mpz_and.c create mode 100644 gnu/lib/libgmp/mpz_clear.c create mode 100644 gnu/lib/libgmp/mpz_clrbit.c create mode 100644 gnu/lib/libgmp/mpz_cmp.c create mode 100644 gnu/lib/libgmp/mpz_cmp_si.c create mode 100644 gnu/lib/libgmp/mpz_cmp_ui.c create mode 100644 gnu/lib/libgmp/mpz_com.c create mode 100644 gnu/lib/libgmp/mpz_div.c create mode 100644 gnu/lib/libgmp/mpz_div_2exp.c create mode 100644 gnu/lib/libgmp/mpz_div_ui.c create mode 100644 gnu/lib/libgmp/mpz_dm.c create mode 100644 gnu/lib/libgmp/mpz_dm_ui.c create mode 100644 gnu/lib/libgmp/mpz_dmincl.c create mode 100644 gnu/lib/libgmp/mpz_fac_ui.c create mode 100644 gnu/lib/libgmp/mpz_gcd.c create mode 100644 gnu/lib/libgmp/mpz_gcdext.c create mode 100644 gnu/lib/libgmp/mpz_get_si.c create mode 100644 gnu/lib/libgmp/mpz_get_str.c create mode 100644 gnu/lib/libgmp/mpz_get_ui.c create mode 100644 gnu/lib/libgmp/mpz_init.c create mode 100644 gnu/lib/libgmp/mpz_inp_raw.c create mode 100644 gnu/lib/libgmp/mpz_inp_str.c create mode 100644 gnu/lib/libgmp/mpz_ior.c create mode 100644 gnu/lib/libgmp/mpz_iset.c create mode 100644 gnu/lib/libgmp/mpz_iset_si.c create mode 100644 gnu/lib/libgmp/mpz_iset_str.c create mode 100644 gnu/lib/libgmp/mpz_iset_ui.c create mode 100644 gnu/lib/libgmp/mpz_mdiv.c create mode 100644 gnu/lib/libgmp/mpz_mdiv_ui.c create mode 100644 gnu/lib/libgmp/mpz_mdm.c create mode 100644 gnu/lib/libgmp/mpz_mdm_ui.c create mode 100644 gnu/lib/libgmp/mpz_mmod.c create mode 100644 gnu/lib/libgmp/mpz_mmod_ui.c create mode 100644 gnu/lib/libgmp/mpz_mod.c create mode 100644 gnu/lib/libgmp/mpz_mod_2exp.c create mode 100644 gnu/lib/libgmp/mpz_mod_ui.c create mode 100644 gnu/lib/libgmp/mpz_mul.c create mode 100644 gnu/lib/libgmp/mpz_mul_2exp.c create mode 100644 gnu/lib/libgmp/mpz_mul_ui.c create mode 100644 gnu/lib/libgmp/mpz_neg.c create mode 100644 gnu/lib/libgmp/mpz_out_raw.c create mode 100644 gnu/lib/libgmp/mpz_out_str.c create mode 100644 gnu/lib/libgmp/mpz_perfsqr.c create mode 100644 gnu/lib/libgmp/mpz_pow_ui.c create mode 100644 gnu/lib/libgmp/mpz_powm.c create mode 100644 gnu/lib/libgmp/mpz_powm_ui.c create mode 100644 gnu/lib/libgmp/mpz_pprime_p.c create mode 100644 gnu/lib/libgmp/mpz_random.c create mode 100644 gnu/lib/libgmp/mpz_random2.c create mode 100644 gnu/lib/libgmp/mpz_realloc.c create mode 100644 gnu/lib/libgmp/mpz_set.c create mode 100644 gnu/lib/libgmp/mpz_set_si.c create mode 100644 gnu/lib/libgmp/mpz_set_str.c create mode 100644 gnu/lib/libgmp/mpz_set_ui.c create mode 100644 gnu/lib/libgmp/mpz_size.c create mode 100644 gnu/lib/libgmp/mpz_sizeinb.c create mode 100644 gnu/lib/libgmp/mpz_sqrt.c create mode 100644 gnu/lib/libgmp/mpz_sqrtrem.c create mode 100644 gnu/lib/libgmp/mpz_sub.c create mode 100644 gnu/lib/libgmp/mpz_sub_ui.c create mode 100644 gnu/lib/libgmp/mtox.c create mode 100644 gnu/lib/libgmp/sdiv.c create mode 100644 gnu/lib/libgmp/tests/Makefile create mode 100644 gnu/lib/libgmp/tests/tst-convert.c create mode 100644 gnu/lib/libgmp/tests/tst-dm.c create mode 100644 gnu/lib/libgmp/tests/tst-dm_ui.c create mode 100644 gnu/lib/libgmp/tests/tst-gcd.c create mode 100644 gnu/lib/libgmp/tests/tst-mdm.c create mode 100644 gnu/lib/libgmp/tests/tst-mdm_ui.c create mode 100644 gnu/lib/libgmp/tests/tst-mul.c create mode 100644 gnu/lib/libgmp/tests/tst-pow_ui.c create mode 100644 gnu/lib/libgmp/tests/tst-sqrtrem.c create mode 100644 gnu/lib/libgmp/tests/urandom.h create mode 100644 gnu/lib/libgmp/xtom.c (limited to 'gnu/lib/libgmp') diff --git a/gnu/lib/libgmp/COPYING b/gnu/lib/libgmp/COPYING new file mode 100644 index 0000000..a43ea21 --- /dev/null +++ b/gnu/lib/libgmp/COPYING @@ -0,0 +1,339 @@ + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc. + 675 Mass Ave, Cambridge, MA 02139, USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Library General Public License instead.) You can apply it to +your programs, 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 software, or if you modify it. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, 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 show them these terms so they know their +rights. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, 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 redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and +modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + + 1. You may copy and distribute verbatim copies of the Program's +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 give any other recipients of the Program a copy of this License +along with the Program. + +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 Program or any portion +of it, thus forming a work based on the Program, 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) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +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 Program, 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 Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + a) 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; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, 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 executable. 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. + +If distribution of executable or 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 counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program 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. + + 5. 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 Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program 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. + + 7. 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 Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program 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 Program. + +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. + + 8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program 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. + + 9. The Free Software Foundation may publish revised and/or new versions +of the 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 Program +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 Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + + 10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, 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 + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +PROVIDE THE PROGRAM "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 PROGRAM IS WITH YOU. SHOULD THE +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, +REPAIR OR CORRECTION. + + 12. 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 PROGRAM 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 PROGRAM (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 PROGRAM TO OPERATE WITH ANY OTHER +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + + END OF TERMS AND CONDITIONS + + Appendix: How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. 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) 19yy + + 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., 675 Mass Ave, Cambridge, MA 02139, USA. + +Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this +when it starts in an interactive mode: + + Gnomovision version 69, Copyright (C) 19yy name of author + Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, the commands you use may +be called something other than `show w' and `show c'; they could even be +mouse-clicks or menu items--whatever suits your program. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the program, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the program + `Gnomovision' (which makes passes at compilers) written by James Hacker. + + , 1 April 1989 + Ty Coon, President of Vice + +This General Public License does not permit incorporating your program into +proprietary programs. If your program is a subroutine library, you may +consider it more useful to permit linking proprietary applications with the +library. If this is what you want to do, use the GNU Library General +Public License instead of this License. diff --git a/gnu/lib/libgmp/ChangeLog b/gnu/lib/libgmp/ChangeLog new file mode 100644 index 0000000..0a8f9ed --- /dev/null +++ b/gnu/lib/libgmp/ChangeLog @@ -0,0 +1,1347 @@ +Wed May 19 12:14:19 1993 Torbjorn Granlund (tege@nada.kth.se) + + * Many files: Call alloca(0) before function return. + * alloca.c: New file. + * Makefile (IMPL_SRCS): Add alloca.c. + (IMPL_OBJS): Add alloca.o. + +Fri May 14 00:52:01 1993 Torbjorn Granlund (tege@nada.kth.se) + + * mpz_iset_str.c: Fix header comment. + + * gmp.h: Don't test just FILE, tests some variants of _STDIO_H for + machines were FILE is a typedef. + +Tue May 11 21:20:07 1993 Torbjorn Granlund (tege@nada.kth.se) + + * Makefile (realclean): Make it just be like clean. + (In particular, don't delete Makefile...) + +Thu May 6 14:31:02 1993 Torbjorn Granlund (tege@nada.kth.se) + + * mpn_mul.c (vsize < KARATSUBA_THRESHOLD): Eliminate unused + variable `c'. + + * 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. + + * mpz_inp_str.c: Pass BASE to char_ok_for_base. + +Wed May 5 01:25:23 1993 Torbjorn Granlund (tege@nada.kth.se) + + * tests/tst-convert.c: Try base == 0. + + * mpz_inp_str.c: Fix typo in assignment. + + * 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. + +Tue May 4 17:11:55 1993 Torbjorn Granlund (tege@du.nada.kth.se) + + * longlong.h (#if ns32000): Fix typo, udiv_qrnnd was div_qrnnd. + +Mon May 3 00:20:52 1993 Torbjorn Granlund (tege@cyklop.nada.kth.se) + + * Makefile: Add rule for mp_bases.o. + + * _mpz_set_str.c: Make inp_digit an mp_limb. Remove casts of + inp_digit to unsigned. + + * 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. + + * tests/*.c: Include gmp-impl.h to make `inline' and `const' be + #define'd. + + * Makefile: Update automatically generated dependencies. + + * mpz_pow_ui: Don't include mp.h. + Use MP_INT instead of MINT even for rpow. + +Sun May 2 16:35:53 1993 Torbjorn Granlund (tege@cyklop.nada.kth.se) + + * 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. + + * mpz_fac_ui: Fix some comments. + + * mpz_random.c, mpz_random2.c: Declare random(); + Define random to call mrand48 for __alpha__. + + * All files: Use #ifdef instead if #if for testing __STDC__. + + * longlong.h (#if sparc_v8): Define UMUL_TIME and UDIV_TIME. + + * mpz_inp_str.c: If BASE is 0, try to determine the base from the + leading characters. Restructure code. + + * mpz_pprime_p.c: Include gmp-impl.h. + +Fri Apr 30 09:35:03 1993 Torbjorn Granlund (tege@du.nada.kth.se) + + * tests/Makefile: Set CC and OPT as in main Makefile. + Add copyright notice. + + * gmp.h: Remove declaration of mpz_not. + +Thu Apr 29 19:51:34 1993 Torbjorn Granlund (tege@du.nada.kth.se) + + * mpq_cmp.c: Fix header comment. + + From Anders Thulin: + * mpz_inp_str.c: Get condition for char_ok_for_base right. + +Tue Apr 27 12:30:48 1993 Torbjorn Granlund (tege@du.nada.kth.se) + + * 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. + + * mpz_gcd.c: Fix typo in comments. + + * mpz_sqrtrem.c: Really divide by zero for negative operands. + + * mpz_mul_ui.c: Fix header comment. + + * mpz_get_si.c: Fix type typo in cast. + +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'. + + * Makefile, tests/Makefile: Don't define or use srcdir. + + * 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. + +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. + + * 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. + + * gmp.h: mpn_add returns mp_limb. + + * mpz_perfsqr: 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. + + * 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_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. + +Mon Mar 15 11:44:06 1993 Torbjorn Granlund (tege@pde.nada.kth.se) + + * mpz_pprime_p.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. + +Fri Feb 12 20:27:34 1993 Torbjorn Granlund (tege@cyklop.nada.kth.se) + + * mpz_inp_str: 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. + +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. + +Mon Jan 4 09:11:15 1993 Torbjorn Granlund (tege@sics.se) + + * itom: Declare param explicitly 'signed'. + * sdiv: Likewise. + + * mpq_cmp: Remove unused variable tmp_size. + * mpz_powm_ui: Fix typo in esize==0 if stmt. + * mpz_powm: Likewise. + +Sun Nov 29 01:16:11 1992 Torbjorn Granlund (tege@sics.se) + + * mpn_dm_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. + +Wed Oct 28 17:40:04 1992 Torbjorn Granlund (tege@jupiter.sics.se) + + * longlong.h (__hppa umul_ppmm): Fix typos. + (__hppa sub_ddmmss): Swap input arguments. + + * mpz_perfsqr.c (mpz_perfect_square_p): Avoid , before } in + initializator. + +Sun Oct 25 20:30:06 1992 Torbjorn Granlund (tege@jupiter.sics.se) + + * mpz_pprime_p.c (mpz_probab_prime_p): Handle numbers <= 3 + specifically (used to consider all negative numbers prime). + + * mpz_powm_ui: `carry_digit' => `carry_limb'. + + * sdiv: Handle zero dividend specifically. Replace most code in + this function with a call to mpn_divmod_1. + + * 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! + + * mpn_lshift, mpn_rshift, mpn_rshiftci: Remove `long' from 4:th arg. + +Thu Sep 3 01:47:07 1992 Torbjorn Granlund (tege@jupiter.sics.se) + + * 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) + + Fix from Jan-Hein Buhrman: + * mpz_mdiv.c, mpz_mmod.c, mpz_mdm.c: Make them work as documented. + + * mpz_mmod.c, mpz_mdm.c: Move decl of TEMP_DIVISOR to reflect its + life. + +Sun Aug 30 18:37:15 1992 Torbjorn Granlund (tege@jupiter.sics.se) + + * _mpz_get_str: Use mpz_sizeinbase for computing out_len. + * _mpz_get_str: Don't remove leading zeros. Abort if there are some. + +Tue Feb 18 14:38:39 1992 Torbjorn Granlund (tege@zevs.sics.se) + + longlong.h (hppa umul_ppmm): Add missing semicolon. Declare type + of __w1 and __w0. + +Fri Feb 14 21:33:21 1992 Torbjorn Granlund (tege@zevs.sics.se) + + * longlong.h: Make default count_leading_zeros work for machines > + 32 bits. Prepend `__' before local variables to avoid conflicts + with users' variables. + +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) + + * longlong.h: Make __LLDEBUG__ work differently. + (_IBMR2): Reinsert old code. + +Sat Feb 1 16:43:00 1992 Torbjorn Granlund (tege@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) + + * 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) + + * 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) + + * _mpz_get_str: Fix typo in comment. + +Mon Jan 27 09:44:16 1992 Torbjorn Granlund (tege@sics.se) + + * Makefile.in: Add new files. + + * mpn_dm_1.c: New file with function _mpn_divmod_1. + * mpz_dm_ui.c (mpz_divmod_ui): Use _mpn_divmod_1. + * mpz_div_ui: Likewise. + + * mpn_mod_1.c: New file with function _mpn_mod_1. + * mpz_mod_ui: Use _mpn_mod_1. + +Thu Jan 23 18:54:09 1992 Torbjorn Granlund (tege@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) + + * mpz_pprime_p.c: Use "" for #include. + +Sun Jan 19 13:36:55 1992 Torbjorn Granlund (tege@sics.se) + + * mpn_rshiftci.c (header): Correct comment. + +Wed Jan 15 18:56:04 1992 Torbjorn Granlund (tege@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) + + * mpz_powm_ui: Fix comment. + * mpz_powm: Likewise. + +Mon Jan 13 18:16:25 1992 Torbjorn Granlund (tege@sics.se) + + * tests/Makefile.in: Prepend $(TEST_PREFIX) to Makefile target. + +Sun Jan 12 13:54:28 1992 Torbjorn Granlund (tege@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) + + * gmp.h, mp.h: Remove parameter names from prototypes. + +Sun Dec 15 00:09:36 1991 Torbjorn Granlund (tege@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) + + * mpn_sqrt.c: New file with _mpn_sqrt. + * mpz_sqrt, mpz_sqrtrem, mpz_perfect_square_p: Use _mpn_sqrt. + * msqrt.c: Delete. Create from mpz_sqrtrem.c in Makefile.in. + * mpz_do_sqrt.c: Delete. + * Makefile.in: Update to reflect these changes. + + * Makefile.in, configure, configure.subr: New files + (from bothner@cygnus.com). + * dist-Makefile: Delete. + + * mpz_fac_ui: Fix comment. + + * mpz_random2: Rewrite to make it possible for the most significant + limb to be == 1. + + * mpz_pprime_p.c (mpz_probab_prime_p): Remove \t\n. + +Fri Dec 13 23:10:02 1991 Torbjorn Granlund (tege@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) + + * gmp-impl.h (MPZ_TMP_INIT): Cast to the right type. + +Thu Dec 12 22:17:29 1991 Torbjorn Granlund (tege@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) + + * mpn_rshift.c: Fix header comments. + +Mon Dec 9 17:46:10 1991 Torbjorn Granlund (tege@sics.se) + + Released 1.2. + + * gmp-impl.h (MPZ_TMP_INIT): Cast alloca return value. + + * dist-Makefile: Add missing dependency for cre-mparam. + + * mpz_mdiv.c, mpz_mmod.c, mpz_mdm.c, mpz_mdiv_ui.c, + mpz_mmod_ui.c, mpz_mdm_ui.c: Remove obsolete comment. + + * dist-Makefile (clean): clean in tests subdir too. + * tests/Makefile: Define default values for ROOT and SUB. + + * longlong.h (__a29k__ udiv_qrnnd): Change "q" to "1" for operand + 2 constraint. + +Mon Nov 11 00:06:05 1991 Torbjorn Granlund (tege@sics.se) + + * mpz_sizeinb.c (mpz_sizeinbase): Special code for size == 0. + +Sat Nov 9 23:47:38 1991 Torbjorn Granlund (tege@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) + + * gmp.h: Don't use keyword `signed' for non-ANSI compilers. + +Thu Nov 7 22:06:46 1991 Torbjorn Granlund (tege@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) + + * mpn_mul: Fix indentation. + + * mpz_do_sqrt: Don't assume 32 bit limbs (had constant + 4294967296.0). + * mpz_do_sqrt: Handle overflow in conversion from double returned + by SQRT to mp_limb. + + * gmp.h: Add missing function definitions. + +Sun Nov 3 18:25:25 1991 Torbjorn Granlund (tege@sics.se) + + * mpz_pow_ui: Change type of `i' to int. + + * ChangeLog: Add change log entry. + * ChangeLog: Add change log entry. + * ChangeLog: Add change log entry. + * ChangeLog: Add change log entry. + * ChangeLog: Add change log entry. + * ChangeLog: Add change log entry. + * ChangeLog: Add change log entry. + * ChangeLog: Add change log entry. +Stack overflow. + + * mpz_pow_ui.c: Fix typo in comment. + + * dist-Makefile: Create rpow.c from mpz_powm_ui.c. + * mpz_powm_ui.c: Add code for rpow. + * rpow.c: Delete this file. The rpow function is now implemented + in mpz_powm_ui.c. + + * mpz_fac_ui.c: New file. + * gmp.h, dist-Makefile: Add stuff for mpz_fac_ui. + + Bug found by John Amanatides (amana@sasquatch.cs.yorku.ca): + * mpz_powm_ui, mpz_powm: Call _mpn_mul in the right way, with + the first argument not smaller than the second. + +Tue Oct 29 13:56:55 1991 Torbjorn Granlund (tege@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) + + * mpz_random2: Handle size == 0. + + * gmp-impl.h (struct __mp_bases): Rename chars_per_limb_exactly to + chars_per_bit_exactly, and change its definition. + * cre-conv-tab.c (main): Output field according to its new + definition. + * mpz_out_str, _mpz_get_str, mpz_sizeinb, mout: + Use chars_per_bit_exactly. + + * mpz_random2: Change the loop termination condition in order to + get a large most significant limb with higher probability. + + * gmp.h: Add declaration of new mpz_random2 and mpz_get_si. + * mpz_get_si.c: New file. + * dist-Makefile: Add mpz_random2 and mpz_get_si. + + * mpz_sizeinb.c (mpz_sizeinbase): Special code for base being a + power of 2, giving exact result. + + * mpn_mul: Fix MPN_MUL_VERIFY in various ways. + * mpn_mul: New macro KARATSUBA_THRESHOLD. + * mpn_mul (karatsuba's algorithm): Don't write intermediate results + to prodp, use temporary pp instead. (Intermediate results can be + larger than the final result, possibly writing into hyperspace.) + * mpn_mul: Make smarter choice between Karatsuba's algorithm and the + shortcut algorithm. + * mpn_mul: Fix typo, cy instead of xcy. Unify carry handling code. + +Sun Oct 27 19:57:32 1991 Torbjorn Granlund (tege@sics.se) + + * mpn_mul: In non-classical case, choose Karatsuba's algorithm only + when usize > 1.5 vsize. + + * mpn_mul: Break between classical and Karatsuba's algorithm at + KARATSUBA_THRESHOLD, if defined. Default to 8. + + * mpn_div: Kludge to fix stray memory read. + +Sat Oct 26 20:06:14 1991 Torbjorn Granlund (tege@sics.se) + + * mpz_gcdext: Handle a = b = 0. Remove memory leakage by calling + mpz_clear for all temporary variables. + + * mpz_gcd: Reduce w_bcnt in _mpn_lshift call to hold that + function's argument constraints. Compute wsize correctly. + + * mpz_gcd: Fix typo in comment. + + * memory.c (_mp_default_allocate, _mp_default_reallocate): Call + abort if allocation fails, don't just exit. + +Fri Oct 25 22:17:20 1991 Torbjorn Granlund (tege@sics.se) + + * mpz_random2.c: New file. + +Thu Oct 17 18:06:42 1991 Torbjorn Granlund (tege@sics.se) + + Bugs found by Pierre-Joseph Gailly (pjg@sunbim.be): + * mpq_cmp: Take sign into account, don't just compare the + magnitudes. + * mpq_cmp: Call _mpn_mul in the right way, with the first argument + not smaller than the second. + +Wed Oct 16 19:27:32 1991 Torbjorn Granlund (tege@sics.se) + + * mpz_random: Ensure the result is normalized. + +Tue Oct 15 14:55:13 1991 Torbjorn Granlund (tege@sics.se) + + * mpz_clrbit: Support non-ANSI compilers. + +Wed Oct 9 18:03:28 1991 Torbjorn Granlund (tege@sics.se) + + * longlong.h (68k add_ssaaaa, sub_ddmmss): Generalize constraints. + +Tue Oct 8 17:42:59 1991 Torbjorn Granlund (tege@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) + + * dist-Makefile: Prepend `./' before some filenames. + +Sun Sep 29 14:02:11 1991 Torbjorn Granlund (tege@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) + + * longlong.h: Fix header comment. + +Mon Sep 9 15:16:24 1991 Torbjorn Granlund (tege@sics.se) + + Released 1.0.92. + + * mpn_mul.c (_mpn_mul): Handle leading zero limbs in non-Karatsuba + case. + + * longlong.h (m68000 umul_ppmm): Clobber one register less by + slightly rearranging the code. + +Sun Sep 1 18:53:25 1991 Torbjorn Granlund (tege@sics.se) + + * dist-Makefile (stamp-stddefh): Fix typo. + +Sat Aug 31 20:41:31 1991 Torbjorn Granlund (tege@sics.se) + + Released 1.0.91. + + * mpz_mdiv.c, mpz_mmod.c, mpz_mdm.c, mpz_mdiv_ui.c, + mpz_mmod_ui.c, mpz_mdm_ui.c: New files and functions. + * gmp.h, gmp.texi: Define the new functions. + +Fri Aug 30 08:32:56 1991 Torbjorn Granlund (tege@sics.se) + + * mpz_gcdext: Compute t argument from the other quantities at the + end, of the function, not in the loop. New feature: Allow t to be + NULL. + + * mpz_add.c, mpz_sub.c, mpz_mul.c, mpz_powm.c, mpz_gcd.c: Don't + include "mp.h". Use type name `MP_INT' always. + + * dist-Makefile, mpz_cmp.c: Merge mcmp.c from mpz_cmp.c. + +Wed Aug 28 00:45:11 1991 Torbjorn Granlund (tege@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) + + * longlong.h (68020, i386): Don't define machine-dependent + __umulsidi3 (so the default definition is used). + * longlong.h (all machines): Cast all operands, sources and + destinations, to `unsigned long int'. + * longlong.h: Add gmicro support. + +Thu Aug 22 00:28:29 1991 Torbjorn Granlund (tege@sics.se) + + * longlong.h: Rename BITS_PER_LONG to LONG_TYPE_SIZE. + * longlong.h (__ibm032__): Define count_leading_zeros and umul_ppmm. + * longlong.h: Define UMUL_TIME and UDIV_TIME for some CPUs. + * _mpz_get_str.c: Add code to do division by big_base using only + umul_qrnnd, if that is faster. Use UMUL_TIME and UDIV_TIME to + decide which variant to use. + +Wed Aug 21 15:45:23 1991 Torbjorn Granlund (tege@sics.se) + + * longlong.h (__sparc__ umul_ppmm): Move two insn from end to the + nops. (Saves two insn.) + + * longlong.h (__sparc__ umul_ppmm): Rewrite in order to avoid + branch, and to permit input/output register overlap. + + * longlong.h (__29k__): Remove duplicated udiv_qrnnd definition. + * longlong.h (__29k__ umul_ppmm): Split asm instructions into two + asm statements (gives better code if either the upper or lower + part of the product is unused. + +Tue Aug 20 17:57:59 1991 Torbjorn Granlund (tege@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) + + * cre-conv-tab.c (main): Output table in hex. Output 4 fields, not + 3, for components 0 and 1. + + * gmp.h: Add declaration of mpq_neg. + + Released 1.0beta.13. + + * _mpz_set_str.c (mpz_set_str): Cast EOF and SPC to char before + comparing to enum literals SPC and EOF. This makes the code work + for compilers where `char' is unsigned. (Bug found by Brian + Beuning). + + Released 1.0beta.12. + + * mpz_mod_ui: Remove references to quot. Remove quot_ptr, quot_size + declarations and assignment code. + +Sun Aug 18 14:44:26 1991 Torbjorn Granlund (tege@sics.se) + + * mpz_mod_ui: Handle dividend < 0. + + Released 1.0beta.11. + + * mpz_dm_ui, mpz_div_ui, mpz_mod_ui, sdiv: Make them share the same + general structure, variable names, etc. + + * sdiv: Un-normalize the remainder in n1 before it is negated. + + * longlong.h: Mention UDIV_NEEDS_NORMALIZATION in description of + udiv_qrnnd. + + * mpz_dm_ui.c (mpz_divmod_ui), mpz_div_ui.c (mpz_div_ui): Increment + the quotient size if the dividend size is incremented. (Bug found + by Brian Beuning.) + + * mpz_mod_ui: Shift back the remainder, if UDIV_NEEDS_NORMALIZATION. + (Bug found by Brian Beuning.) + + * mpz_mod_ui: Replace "digit" by "limb". + + * mpz_perfsqr.c (mpz_perfect_square_p): Disable second test case + for non-32-bit machines (PP is hardwired for such machines). + * mpz_perfsqr.c (outside of functions): Define PP value with an L. + + * mpn_mul.c (_mpn_mul): Add verification code that is activated if + DEBUG is defined. Replace "digit" by "limb". + * mpn_mul.c (_mpn_mul: Karatsuba's algorithm: 4.): Normalize temp + after the addition. + * mpn_mul.c (_mpn_mul: Karatsuba's algorithm: 1.): Compare u0_size + and v0_size, and according to the result, swap arguments in + recursive call. (Don't violate mpn_mul's own argument + constraints.) + +Fri Aug 16 13:47:12 1991 Torbjorn Granlund (tege@sics.se) + + Released 1.0beta.10. + + * longlong.h (IBMR2): Add udiv_qrnnd. + + * mpz_perfsqr: Remove unused variables. + + * mpz_and (case for different signs): Initialize loop variable i! + + * dist-Makefile: Update automatically generated dependencies. + * dist-Makefile (madd.c, msub.c, pow.c, mult.c, gcd.c): Add mp.h, + etc to dependency file lists. + + * longlong.h (add_ssaaaa, sub_ddmmss [C default versions]): Make __x + `unsigned long int'. + * longlong.h: Add `int' after `unsigned' and `long' everywhere. + +Wed Aug 14 18:06:48 1991 Torbjorn Granlund (tege@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) + + * _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) + + * cre-conv-tab.c (main): Use %lu in printf for long ints. + + * dist-Makefile: Fix cre-* dependencies. + + * cre-conv-tab.c (main): Output field big_base_inverted. + + * gmp-impl.h (struct bases): New field big_base_inverted. + * gmp-impl.h (struct bases): Change type of chars_per_limb_exactly + to float (in order to keep the structure smaller). + + * mp.h, gmp.h: Change names of macros for avoiding multiple + includes. + +Fri Aug 9 18:01:36 1991 Torbjorn Granlund (tege@sics.se) + + * _mpz_get_str: Only shift limb array if normalization_steps != 0 + (optimization). + + * longlong.h (sparc umul_ppmm): Use __asm__, not asm. + * longlong.h (IBMR2 umul_ppmm): Refer to __m0 and __m1, not to m0 + and m1 (overlap between output and input operands did not work). + * longlong.h: Add VAX, ROMP and HP-PA support. + * longlong.h: Sort the machine dependent code in alphabetical order + on the CPU name. + * longlong.h: Hack comments. + +Thu Aug 8 14:13:36 1991 Torbjorn Granlund (tege@sics.se) + + Released 1.0beta.9. + + * longlong.h: Define BITS_PER_LONG to 32 if it's not already + defined. + * Define __BITS4 to BITS_PER_LONG / 4. + * Don't assume 32 bit word size in "count_leading_zeros" C macro. + Use __BITS4 and BITS_PER_LONG instead. + + * longlong.h: Don't #undef internal macros (reverse change of Aug 3). + + * longlong.h (68k): Define add_ssaaaa sub_ddmmss, and umul_ppmm + even for plain mc68000. + + * mpq_div: Flip the sign of the numerator *and* denominator of the + result if the intermediate denominator is negative. + + * mpz_and.c, mpz_ior.c: Use MPN_COPY for all copying operations. + + * mpz_and.c: Compute the result size more conservatively. + * mpz_ior.c: Likewise. + + * mpz_realloc: Never allocate zero space even if NEW_SIZE == 0. + + * dist-Makefile: Remove madd.c, msub.c, pow.c, mult.c, gcd.c from + BSDMP_SRCS. + + * dist-Makefile: Create mult.c from mpz_mul.c. + * mult.c: Delete this file. + + * _mpz_set_str: Normalize the result (for bases 2, 4, 8... it was + not done properly if the input string had many leading zeros). + +Sun Aug 4 16:54:14 1991 Torbjorn Granlund (tege@sics.se) + + * dist-Makefile (gcd.c, pow.c, madd.c, msub.c): Make these targets + work with VPATH and GNU MP. + + * mpz_gcd: Don't call mpz_set; inline its functionality. + + * mpq_mul, mpq_div: Fix several serious typos. + + * mpz_dmincl, mpz_div: Don't normalize the quotient if it's already + zero. + + * mpq_neg.c: New file. + + * dist-Makefile: Remove obsolete dependencies. + + * mpz_sub: Fix typo. + + Bugs found by Pierre-Joseph Gailly (pjg@sunbim.be): + * mpq_mul, mpq_div: Initialize tmp[12] variables even when the gcd + is just 1. + * mpz_gcd: Handle gcd(0,v) and gcd(u,0) in special cases. + +Sat Aug 3 23:45:28 1991 Torbjorn Granlund (tege@sics.se) + + * longlong.h: Clean up comments. + * longlong.h: #undef internal macros. + +Fri Aug 2 18:29:11 1991 Torbjorn Granlund (tege@sics.se) + + * mpq_set_si, mpq_set_ui: Canonicalize 0/x to 0/1. + * mpq_set_si, mpq_set_ui: Cosmetic formatting changes. + + * mpz_dmincl.c: Normalize the remainder before shifting it back. + + * mpz_dm_ui.c (mpz_divmod_ui): Handle rem == dividend. + + * mpn_div.c: Fix comment. + + * mpz_add.c, mpz_sub.c: Use __MP_INT (not MP_INT) for intermediate + type, in order to work for both GNU and Berkeley functions. + + * dist-Makefile: Create gcd.c from mpz_gcd.c, pow.c from mpz_powm, + madd.c from mpz_add.c, msub.c from mpz_sub.c. + respectively. + * pow.c, gcd.c, mpz_powmincl.c, madd.c, msub.c: Remove these. + * mpz_powm.c, mpz_gcd.c, mpz_add.c, mpz_sub.c: #ifdef for GNU and + Berkeley function name variants. + * dist-Makefile: Add created files to "clean" target. + +Tue Jul 16 15:19:46 1991 Torbjorn Granlund (tege@sics.se) + + * mpq_get_den: No need for absolute value of the size, the + denominator is always positive. + + * mpz_get_ui: If the operand is zero, return zero. Don't read the + limb array! + + * mpz_dmincl.c: Don't ignore the return value from _mpn_rshift, it + is the size of the remainder. + +Mon Jul 15 11:08:05 1991 Torbjorn Granlund (tege@sics.se) + + * Several files: Remove unused variables and functions. + + * gmp-impl.h: Declare _mpz_impl_sqrt. + + * mpz_dm_ui (mpz_divmod_ui), sdiv: Shift back the remainder if + UDIV_NEEDS_NORMALIZATION. (Fix from Brian Beuning.) + + * mpz_dm_ui.c, sdiv: Replace *digit with *limb. + + * mpz_ior: Add missing else statement in -OP1 | -OP2 case. + * mpz_ior: Add missing else statement in OP1 | -OP2 case. + * mpz_ior: Swap also OP1 and OP2 pointers in -OP1 & OP2 case. + * mpz_ior: Duplicate _mpz_realloc code. + + * mpz_and: Add missing else statement in -OP1 & -OP2 case. + * mpz_and: Rewrite OP1 & -OP2 case. + * mpz_and: Swap also OP1 and OP2 pointers in -OP1 & OP2 case. + + * mpz_gcdext: Loop in d1.size (not b->size). (Fix from Brian + Beuning.) + + * mpz_perfsqr: Fix argument order in _mpz_impl_sqrt call. (Fix from + Brian Beuning.) + +Fri Jul 12 17:10:33 1991 Torbjorn Granlund (tege@sics.se) + + * mpq_set.c, mpq_set_ui.c, mpq_set_si.c, mpq_inv.c, + mpq_get_num.c, mpq_get_den.c, mpq_set_num.c, mpq_set_den.c: + New files. + + * mpz_dmincl.c: Remove second re-allocation of rem->d. It + was never executed. + + * dist-Makefile: Use `-r' instead of `-x' for test for ranlib (as + some unixes' test doesn't have the -r option). + + * *.*: Cast allocated pointers to the appropriate type (makes old C + compilers happier). + + * cre-conv-tab.c (main): Divide max_uli by 2 and multiply again + after conversion to double. (Kludge for broken C compilers.) + + * dist-Makefile (stamp-stddefh): New target. Test if "stddef.h" + exists in the system and creates a minimal one if it does not + exist. + * cre-stddefh.c: New file. + * dist-Makefile: Make libgmp.a and libmp.a depend on stamp-stddefh. + * dist-Makefile (clean): Add some more. + * gmp.h, mp.h: Unconditionally include "stddef.h". + +Thu Jul 11 10:08:21 1991 Torbjorn Granlund (tege@sics.se) + + * min: Do ungetc of last read character. + * min.c: include stdio.h. + + * dist-Makefile: Go via tmp- files for cre* redirection. + * dist-Makefile: Add tmp* to "clean" target. + + * dist-Makefile: Use LOCAL_CC for cre*, to simplyfy cross + compilation. + + * gmp.h, mp.h: Don't define NULL here. + * gmp-impl.h: Define it here. + +Wed Jul 10 14:13:33 1991 Torbjorn Granlund (tege@sics.se) + + * mpz_mod_2exp: Don't copy too much, overwriting most significant + limb. + + * mpz_and, mpz_ior: Don't read op[12]_ptr from op[12] when + reallocating res, if op[12]_ptr got their value from alloca. + + * mpz_and, mpz_ior: Clear up comments. + + * cre-mparam.c: Output parameters for `short int' and `int'. + + * mpz_and, mpz_ior: Negate negative op[12]_size in several places. + +Tue Jul 9 18:40:30 1991 Torbjorn Granlund (tege@sics.se) + + * gmp.h, mp.h: Test for _SIZE_T defined before typedef'ing size_t. + (Fix for Sun lossage.) + + * gmp.h: Add declaration of mpq_clear. + + * dist-Makefile: Chack if "ranlib" exists, before using it. + * dist-Makefile: Add mpz_sqrtrem.c and mpz_size.c. + * mpz_powm: Fix typo, "pow" instead of "mpz_powm". + +Fri Jul 5 19:08:09 1991 Torbjorn Granlund (tege@sics.se) + + * move: Remove incorrect comment. + + * mpz_free, mpq_free: Rename to *_clear. + * dist-Makefile: Likewise. + * mpq_add, mpq_sub, mpq_mul, mpq_div: Likewise. + + * mpz_dmincl.c: Don't call "move", inline its functionality. + +Thu Jul 4 00:06:39 1991 Torbjorn Granlund (tege@sics.se) + + * Makefile: Include dist-Makefile. Fix dist target to include + dist-Makefile (with the name "Makefile" in the archive). + + * dist-Makefile: New file made from Makefile. Add new mpz_... + functions. + + * mpz_powincl.c New file for mpz_powm (Berkeley MP pow) + functionality. Avoids code duplication. + * pow.c, mpz_powm.c: Include mpz_powincl.c + + * mpz_dmincl.c: New file containing general division code. Avoids + code duplication. + * mpz_dm.c (mpz_divmod), mpz_mod.c (mpz_mod), mdiv.c (mdiv): Include + mpz_dmincl.c. + + * _mpz_get_str: Don't call memmove, unless HAS_MEMMOVE is defined. + Instead, write the overlapping memory copying inline. + + * mpz_dm_ui.c: New name for mpz_divmod_ui.c (SysV file name limit). + + * longlong.h: Don't use #elif. + * mpz_do_sqrt.c: Likewise. + + * longlong.h: Use __asm__ instead of asm. + * longlong.h (sparc udiv_qrnnd): Make it to one string over several + lines. + + * longlong.h: Preend __ll_ to B, highpart, and lowpart. + + * longlong.h: Move array t in count_leading_zeros to the new file + mp_clz_tab.c. Rename the array __clz_tab. + * All files: #ifdef for traditional C compatibillity. + +Wed Jul 3 11:42:14 1991 Torbjorn Granlund (tege@sics.se) + + * mpz_and: Initialize res_ptr always (used to be initialized only + when reallocating). + + * longlong.h (umul_ppmm [C variant]): Make __ul...__vh + `unsigned int', and cast the multiplications. This way + compilers more easily can choose cheaper multiplication + instructions. + + * mpz_mod_2exp: Handle input argument < modulo argument. + * mpz_many: Make sure mp_size is the type for sizes, not int. + + * mpz_init, mpz_init_set*, mpq_init, mpq_add, mpq_sub, mpq_mul, + mpq_div: Change mpz_init* interface. Structure pointer as first + arg to initialization function, no longer *return* struct. + +Sun Jun 30 19:21:44 1991 Torbjorn Granlund (tege@sics.se) + + * Rename mpz_impl_sqrt.c to mpz_do_sqrt.c to satisfy SysV 14 + character file name length limit. + + * Most files: Rename MINT to MP_INT. Rename MRAT to MP_RAT. + * mpz_sizeinb.c: New file with function mpz_sizeinbase. + * mp_bases.c: New file, with array __mp_bases. + * _mpz_get_str, _mpz_set_str: Remove struct bases, use extern + __mp_bases instead. + * mout, mpz_out_str: Use array __mp_bases instead of function + _mpz_get_cvtlen. + * mpz_get_cvtlen.c: Remove. + * Makefile: Update. + +Sat Jun 29 21:57:28 1991 Torbjorn Granlund (tege@zevs.sics.se) + + * longlong.h (__sparc8__ umul_ppmm): Insert 3 nop:s for wr delay. + * longlong.h (___IBMR2__): Define umul_ppmm, add_ssaaaa, sub_ddmmss. + * longlong.h (__sparc__): Don't call .umul; expand asm instead. + Don't define __umulsidi3 (i.e. use default definition). + +Mon Jun 24 17:37:23 1991 Torbjorn Granlund (tege@amon.sics.se) + + * _mpz_get_str.c (num_to_ascii_lower_case, num_to_ascii_upper_case): + Swap 't' and 's'. + +Sat Jun 22 13:54:01 1991 Torbjorn Granlund (tege@zevs.sics.se) + + * mpz_gcdext.c: New file. + + * mpn_mul: Handle carry and unexpected operand sizes in last + additions/subtractions. (Bug trigged when v1_size == 1.) + + * mp*_alloc*: Rename functions to mp*_init* (files to mp*_iset*.c). + * mpq_*: Call mpz_init*. + + * mpz_pow_ui, rpow: Use _mpn_mul instead of mult. Restructure. + +Wed May 29 20:32:33 1991 Torbjorn Granlund (tege@zevs.sics.se) + + * mpz_get_cvtlen: multiply by size. + +Sun May 26 15:01:15 1991 Torbjorn Granlund (tege@bella.nada.kth.se) + + Alpha-release 0.95. + + Fixes from Doug Lea (dl@g.oswego.edu): + * mpz_mul_ui: Loop to MULT_SIZE (not PROD_SIZE). Adjust PROD_SIZE + correctly. + * mpz_div: Prepend _ to mpz_realloc. + * mpz_set_xs, mpz_set_ds: Fix typos in function name. + +Sat May 25 22:51:16 1991 Torbjorn Granlund (tege@bella.nada.kth.se) + + * mpz_divmod_ui: New function. + + * sdiv: Make the sign of the remainder correct. + +Thu May 23 15:28:24 1991 Torbjorn Granlund (tege@zevs.sics.se) + + * Alpha-release 0.94. + + * mpz_mul_ui: Include longlong.h. + + * mpz_perfsqr.c (mpz_perfect_square_p): Call _mpz_impl_sqrt instead + of msqrt. + + * mpz_impl_sqrt: Don't call "move", inline its functionality. + + * mdiv: Use MPN_COPY instead of memcpy. + * rpow, mpz_mul, mpz_mod_2exp: Likewise. + * pow.c: Likewise, and fix bug in the size arg. + + * xtom: Don't use mpz_alloc, inline needed code instead. Call + _mpz_set_str instead of mpz_set_str. + + * Makefile: Make two libraries, libmp.a and libgmp.a. + +Thu May 22 20:25:29 1991 Torbjorn Granlund (tege@zevs.sics.se) + + * Add manual to distribution. + * Fold in many missing routines descibed in the manual. + * Update Makefile. + +Wed May 22 13:48:46 1991 Torbjorn Granlund (tege@zevs.sics.se) + + * mpz_set_str: Make it handle 0x prefix OK. + +Sat May 18 18:31:02 1991 Torbjorn Granlund (tege@zevs.sics.se) + + * memory.c (_mp_default_reallocate): Swap OLD_SIZE and NEW_SIZE + arguments. + * mpz_realloc (_mpz_realloc): Swap in call to _mp_reallocate_func. + * min: Likewise. + +Thu May 16 20:43:05 1991 Torbjorn Granlund (tege@zevs.sics.se) + + * memory.c: Make the default allocations functions global. + * mp_set_fns (mp_set_memory_functions): Make a NULL pointer mean the + default memory function. + +Wed May 8 20:02:42 1991 Torbjorn Granlund (tege@zevs.sics.se) + + * mpz_div: Handle DEN the same as QUOT correctly by copying DEN->D + even if no normalization is needed. + * mpz_div: Rework reallocation scheme, to avoid excess copying. + + * mpz_sub_ui.c, mpz_add_ui.c: New files. + + * mpz_cmp.c, mpz_cmp_ui.c: New files. + + * mpz_mul_2exp: Handle zero input MINT correctly. + + * mpn_rshiftci: Don't handle shift counts > BITS_PER_MP_DIGIT. + + * mpz_out_raw.c, mpz_inp_raw.c: New files for raw I/O. + +Tue May 7 15:44:58 1991 Torbjorn Granlund (tege@zevs.sics.se) + + * mpn_rshift: Don't handle shift counts > BITS_PER_MP_DIGIT. + * mpz_div_2exp: Don't call _mpn_rshift with cnt > BITS_PER_MP_DIGIT. + * gcd, mpz_gcd: Likewise. + + * gcd, mpz_gcd: Handle common 2 factors correctly. + +Mon May 6 20:22:59 1991 Torbjorn Granlund (tege@zevs.sics.se) + + * gmp-impl.h (MPN_COPY): Inline a loop instead of calling memcpy. + + * gmp-impl.h, mpz_get_str, rpow: Swap DST and SRC in TMPCOPY* macros. + +Sun May 5 15:16:23 1991 Torbjorn Granlund (tege@zevs.sics.se) + + * mpz_div: Remove test for QUOT == 0. + +Sun Apr 28 20:21:04 1991 Torbjorn Granlund (tege@zevs.sics.se) + + * pow: Don't make MOD normalization in place, as it's a bad idea to + write on an input parameter. + * pow: Reduce BASE if it's > MOD. + * pow, mult, mpz_mul: Simplify realloc code. + +Sat Apr 27 21:03:11 1991 Torbjorn Granlund (tege@zevs.sics.se) + + * Install multplication using Karatsuba's algorithm as default. + +Fri Apr 26 01:03:57 1991 Torbjorn Granlund (tege@zevs.sics.se) + + * msqrt: Store in ROOT even for U==0, to make msqrt(0) defined. + + * mpz_div_2exp.c, mpz_mul_2exp.c: New files for shifting right and + left, respectively. + * gmp.h: Add definitions for mpz_div_2exp and mpz_mul_2exp. + + * mlshift.c, mrshift.c: Remove. + +Wed Apr 24 21:39:22 1991 Torbjorn Granlund (tege@zevs.sics.se) + + * mpn_mul: Check only for m2_size == 0 in function header. + +Mon Apr 22 01:31:57 1991 Torbjorn Granlund (tege@zevs.sics.se) + + * karatsuba.c: New file for Karatsuba's multplication algorithm. + + * mpz_random, mpz_init, mpz_mod_2exp: New files and functions. + + * mpn_cmp: Fix header comment. + +Sun Apr 21 00:10:44 1991 Torbjorn Granlund (tege@zevs.sics.se) + + * pow: Switch off initial base reduction. + +Sat Apr 20 22:06:05 1991 Torbjorn Granlund (tege@echnaton.sics.se) + + * mpz_get_str: Don't generate initial zeros for initial word. + Used to write outside of allocated storage. + +Mon Apr 15 15:48:08 1991 Torbjorn Granlund (tege@zevs.sics.se) + + * _mpz_realloc: Make it accept size in number of mp_digits. + * Most functions: Use new _mpz_realloc definition. + + * mpz_set_str: Remove calls _mp_free_func. + + * Most functions: Rename mpn_* to _mpn_*. Rename mpz_realloc to + _mpz_realloc. + * mpn_lshift: Redefine _mpn_lshift to only handle small shifts. + * mdiv, mpz_div, ...: Changes for new definition of _mpn_lshift. + * msqrt, mp*_*shift*: Define cnt as unsigned (for speed). + +Sat Apr 6 14:05:16 1991 Torbjorn Granlund (tege@musta.nada.kth.se) + + * mpn_mul: Multiply by the first digit in M2 in a special + loop instead of zeroing the product area. + + * mpz_abs.c: New file. + + * sdiv: Implement as mpz_div_si for speed. + + * mpn_add: Make it work for second source operand == 0. + + * msub: Negate the correct operand, i.e. V before swapping, not + the smaller of U and V! + * madd, msub: Update abs_* when swapping operands, and not after + (optimization). + +Fri Apr 5 00:19:36 1991 Torbjorn Granlund (tege@black.nada.kth.se) + + * mpn_sub: Make it work for subtrahend == 0. + + * madd, msub: Rewrite to minimize mpn_cmp calls. Ensure + mpn_cmp is called with positive sizes (used to be called + incorrectly with negative sizes sometimes). + + * msqrt: Make it divide by zero if fed with a negative number. + * Remove if statement at end of precision calculation that was + never true. + + * itom, mp.h: The argument is of type short, not int. + + * mpz_realloc, gmp.h: Make mpz_realloc return the new digit pointer. + + * mpz_get_str.c, mpz_set_str.c, mpz_new_str.c: Don't include mp.h. + + * Add COPYING to distribution. + + * mpz_div_ui.c, mpz_div_si.c, mpz_new_ui.c, mpz_new_si.c: New files. + +Fri Mar 15 00:26:29 1991 Torbjorn Granlund (tege@musta.nada.kth.se) + + * Add Copyleft headers to all files. + + * mpn_mul.c, mpn_div.c: Add header comments. + * mult.c, mdiv.c: Update header comments. + + * mpq_add.c, mpq_sub.c, mpq_div.c, mpq_new.c, mpq_new_ui.c, + mpq_free.c: New files for rational arithmetics. + + * mpn_lshift.c: Avoid writing the most significant word if it is 0. + + * mdiv.c: Call mpn_lshift for the normalization. + * mdiv.c: Remove #ifdefs. + + * Makefile: Add ChangeLog to DISTFILES. + + * mpn_div.c: Make the add_back code work (by removing abort()). + * mpn_div.c: Make it return if the quotient is size as compared + with the difference NSIZE - DSIZE. If the stored quotient is + larger than that, return 1, otherwise 0. + * gmp.h: Fix mpn_div declaration. + * mdiv.c: Adopt call to mpn_div. + * mpz_div.c: New file (developed from mdiv.c). + + * README: Update routine names. + +Thu Mar 14 18:45:28 1991 Torbjorn Granlund (tege@musta.nada.kth.se) + + * mpq_mul.c: New file for rational multplication. + + * gmp.h: Add definitions for rational arithmetics. + + * mpn_div: Kludge the case where the high numerator digit > the + high denominator digit. (This code is going to be optimized later.) + + * New files: gmp.h for GNU specific functions, gmp-common.h for + definitions common for mp.h and gmp.h. + + * Ensure mp.h just defines what BSD mp.h defines. + + * pow.c: Fix typo for bp allocation. + + * Rename natural number functions to mpn_*, integer functions to + mpz_*. + +Tue Mar 5 18:47:04 1991 Torbjorn Granlund (tege@musta.nada.kth.se) + + * mdiv.c (_mp_divide, case 2): Change test for estimate of Q from + "n0 >= r" to "n0 > r". + + * msqrt: Tune the increasing precision scheme, to do fewer steps. + +Tue Mar 3 18:50:10 1991 Torbjorn Granlund (tege@musta.nada.kth.se) + + * msqrt: Use the low level routines. Use low precision in the + beginning, and increase the precision as the result converges. + (This optimization gave a 6-fold speedup.) + +Local Variables: +mode: indented-text +left-margin: 8 +fill-column: 75 +version-control: never +End: diff --git a/gnu/lib/libgmp/INSTALL b/gnu/lib/libgmp/INSTALL new file mode 100644 index 0000000..a8927b1 --- /dev/null +++ b/gnu/lib/libgmp/INSTALL @@ -0,0 +1,34 @@ +Here is how to compile GNU MP. + +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. + +This is how to build the library: + + 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. + + 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. + + To build and run the tests, do "make check". + +The documentation is an a texinfo file, gmp.texi. + +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". + +You need version 2.06 or later of texinfo in order to build the +documentation. + +Please report problems to tege@gnu.ai.mit.edu. diff --git a/gnu/lib/libgmp/README b/gnu/lib/libgmp/README new file mode 100644 index 0000000..b31e7b3 --- /dev/null +++ b/gnu/lib/libgmp/README @@ -0,0 +1,61 @@ + 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. + +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). + +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. + + +There are four classes of functions in GNU MP. + + 1. Signed integer arithmetic functions, mpz_*. The set of functions are + intended to be easy to use, being rich and regular. + + To use these functions, include the file "gmp.h". + + 2. Rational arithmetic functions, mpq_*. For now, just a small set of + functions necessary for basic rational arithmetics. + + To use these functions, include the file "gmp.h". + + 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. + + Almost all calculations, in the entire package, are made in these + low-level functions. + + These functions are not fully documented in this release. They will + probably be so in a future release. + + 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. + + + 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. + diff --git a/gnu/lib/libgmp/TODO b/gnu/lib/libgmp/TODO new file mode 100644 index 0000000..6612d8b --- /dev/null +++ b/gnu/lib/libgmp/TODO @@ -0,0 +1,184 @@ +THINGS TO WORK ON + +Note that many of these things mentioned here are already fixed in GMP 2.0. + +* 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. + +* Change mpn-routines to not deal with normalisation? + mpn_add: Unchanged. + mpn_sub: Remove normalization loop. Does it assume normalised input? + mpn_mul: Make it return most sign limb, to simplify normalisation. + Karatsubas algorith will be greatly simplified if mpn_add and + mpn_sub doesn't normalise their results. + mpn_div: Still requires strict normalisation. + Beware of problems with mpn_cmp (and similar), a larger size does not + ensure that an operand is larger, since it may be "less normalised". + Normalization has to be moved into mpz-functions. + +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. The user may override + the default definition. + +* mout should group in 10-digit groups. +* ASCII dependence? +* Error reporting from I/O functions (linkoping)? + +* 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 like mpz_cntbits. Also + mpz_@_si for most @?? + +Brian Beuning proposes: + 1. An array of small primes + 3. A function to factor an MINT + 4. A routine to look for "small" divisors of an MINT + 5. A 'multiply mod n' routine based on Montgomery's algorithm. + +Doug 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. + 5. Bit-setting, clearing, and testing operations, as in + mpz_setbit(MP_INT* dest, MP_INT* src, unsigned long bit_number), + and used, for example in + mpz_setbit(x, x, 123) + to directly set the 123rd bit of x. + If these are supported, you don't first have to set up + an otherwise unnecessary mpz holding a shifted value, then + do an "or" operation. + +Elliptic curve method descrition 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. + +* 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. The iteration is x := + x*(3-a*x^2)/2, where a is the operand. + +* 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 implement 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)q); + if (rem < 0} {rem += p; quot--;} + +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 Shoenhage-Stassen multiplication algorithm. Take + advantage of the real valued input to save half of the operations and + half of the memory. Try recursive variants with large, optimized base + cases. Use recursive FFT with large base cases, since recursive FFT + has better memory locality. A normal FFT get 100% cache miss. +} + +* Speed modulo arithmetic, using Montgomery's method or my pre-invertion + method. In either case, special arithmetic calls would be needed, + mpz_mmmul, mpz_mmadd, mpz_mmsub, plus some kind of initialization + functions. + +* 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, RS6000, 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. + +* The gcd algorithm could probably be improved with a divide-and-conquer + (DAC) approach. At least the bulk of the operations should be done with + single precision. + +* 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))! + +* Extensions for floating-point arithmetic. + +* Improve special cases for division. + + 1. When the divisor is just one word, normalization is not needed for + most CPUs, and can be done in the division loop for CPUs that need + normalization. + + 2. Even when the result is going to be very small, (i.e. nsize-dsize is + small) normalization should also be done in the division loop. + + To fix this, a new routine mpn_div_unnormalized is needed. + +* 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). + +* When any of the source operands overlap with the destination, mult (and + other routines) slow down. This is so because the need of temporary + allocation (with alloca) and copying. If a new destination were + malloc'ed instead (and the overlapping source free'd before return) no + copying would be needed. Is GNU malloc quick enough to make this faster + even for reasonably small operands? + +Local Variables: +mode: text +fill-column: 75 +version-control: never +End: diff --git a/gnu/lib/libgmp/VERSION b/gnu/lib/libgmp/VERSION new file mode 100644 index 0000000..bf76b46 --- /dev/null +++ b/gnu/lib/libgmp/VERSION @@ -0,0 +1 @@ +GNU MP version 1.3.2 diff --git a/gnu/lib/libgmp/_mpz_get_str.c b/gnu/lib/libgmp/_mpz_get_str.c new file mode 100644 index 0000000..a83e690 --- /dev/null +++ b/gnu/lib/libgmp/_mpz_get_str.c @@ -0,0 +1,309 @@ +/* _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 Free Software Foundation, Inc. + +This file is part of the 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" +#include "gmp-impl.h" +#include "longlong.h" + +#ifndef UMUL_TIME +#define UMUL_TIME 1 +#endif + +#ifndef UDIV_TIME +#define UDIV_TIME UMUL_TIME +#endif + +#define udiv_qrnndx(q, r, nh, nl, d, di) \ + do { \ + unsigned long int _q, _ql, _r; \ + unsigned long int _xh, _xl; \ + umul_ppmm (_q, _ql, (nh), (di)); \ + _q += (nh); /* DI is 2**32 too small. Compensate */\ + if (_q < (nh)) \ + { \ + /* Got carry. Propagate it in the multiplication. */ \ + umul_ppmm (_xh, _xl, (d), _q); \ + _xh += (d); \ + } \ + else \ + umul_ppmm (_xh, _xl, (d), _q); \ + 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) + +char * +#ifdef __STDC__ +_mpz_get_str (char *str, int base, const MP_INT *m) +#else +_mpz_get_str (str, base, m) + char *str; + int base; + const MP_INT *m; +#endif +{ + mp_ptr tp; + mp_size msize; + mp_limb big_base; +#if UDIV_NEEDS_NORMALIZATION || UDIV_TIME > 2 * UMUL_TIME + + int normalization_steps; +#if UDIV_TIME > 2 * UMUL_TIME + mp_limb big_base_inverted; +#endif +#endif + unsigned int dig_per_u; + mp_size out_len; + char *s; + char *num_to_ascii; + + if (base >= 0) + { + if (base == 0) + base = 10; + num_to_ascii = "0123456789abcdefghijklmnopqrstuvwxyz"; + } + else + { + base = -base; + num_to_ascii = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"; + } + + dig_per_u = __mp_bases[base].chars_per_limb; + out_len = mpz_sizeinbase (m, base) + 1; + big_base = __mp_bases[base].big_base; + + msize = m->size; + + if (str == NULL) + str = (char *) (*_mp_allocate_func) (out_len + (msize < 0)); + + if (msize < 0) + *str++ = '-'; + s = str; + + msize = ABS (msize); + + /* Special case zero, as the code below doesn't handle it. */ + if (msize == 0) + { + s[0] = '0'; + s[1] = 0; + return str; + } + + if ((base & (base - 1)) == 0) + { + /* The base is a power of 2. Make conversion from most + significant side. */ + mp_limb n1, n0; + int bits_per_digit = big_base; + int x; + int bit_pos; + int i; + unsigned mask = (1 << bits_per_digit) - 1; + + tp = m->d; + n1 = tp[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++ = num_to_ascii[(n1 >> bit_pos) & mask]; + bit_pos -= bits_per_digit; + } + i--; + if (i < 0) + break; + n0 = (n1 << -bit_pos) & mask; + n1 = tp[i]; + bit_pos += BITS_PER_MP_LIMB; + *s++ = num_to_ascii[n0 | (n1 >> bit_pos)]; + } + + *s = 0; + } + 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. */ + big_base_inverted = __mp_bases[base].big_base_inverted; +#endif +#endif + + out_len--; /* now not include terminating \0 */ + s += out_len; + + /* Allocate temporary space and move the multi prec number to + convert there, as we need to overwrite it below, while + computing the successive remainders. */ + tp = (mp_ptr) alloca ((msize + 1) * BYTES_PER_MP_LIMB); + MPN_COPY (tp, m->d, msize); + + while (msize != 0) + { + int i; + mp_limb 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, + as 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 (tp, tp, msize, normalization_steps); + + /* If the shifting gave a carry out limb, store it and + increase the length. */ + if (n0 != 0) + { + tp[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 = tp[i]; + + if (n1 >= big_base) + n1 = 0; + else + { + msize--; + i--; + } + + for (; i >= 0; i--) + { + n0 = tp[i]; +#if UDIV_TIME > 2 * UMUL_TIME + udiv_qrnndx (tp[i], n1, n1, n0, big_base, big_base_inverted); +#else + udiv_qrnnd (tp[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 = num_to_ascii[n1 % base]; + n1 /= base; + /* Break from the loop as soon as we would only write zeros. */ + if (n1 == 0 && msize == 0) + break; + } + } + + /* There should be no leading zeros. */ + if (*s == '0') + abort (); + + if (s == str) + { + /* This should be the common case. */ + s[out_len] = 0; + } + else if (s == str + 1) + { + /* The string became 1 digit shorter than its maximum. */ + /* Need to copy it back one char pos. */ + out_len--; +#ifndef HAS_MEMMOVE + { + size_t i; + + for (i = 0; i < out_len; i++) + str[i] = s[i]; + } +#else + memmove (str, s, out_len); +#endif + str[out_len] = 0; + } + else + { + /* Hopefully never. */ + abort (); + } + } + + alloca (0); + /* Ugly, we incremented str for negative numbers. Fix that here. */ + return str - (m->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 0000000..987f981 --- /dev/null +++ b/gnu/lib/libgmp/_mpz_set_str.c @@ -0,0 +1,258 @@ +/* _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 Free Software Foundation, Inc. + +This file is part of the 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" +#include "gmp-impl.h" +#include "longlong.h" + +enum char_type +{ + XX = -3, + SPC = -2, + EOF = -1 +}; + +static signed char ascii_to_num[256] = +{ + EOF,XX, XX, XX, XX, XX, XX, XX, XX, SPC,SPC,XX, XX, XX, XX, XX, + XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, + SPC,XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, XX, XX, XX, XX, XX, XX, + XX, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, + 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, XX, XX, XX, XX, XX, + XX, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, + 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, XX, XX, XX, XX, XX, + XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, + XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, + XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, + XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, + XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, + XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, + XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, + XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX +}; + +int +#ifdef __STDC__ +_mpz_set_str (MP_INT *x, const char *str, int base) +#else +_mpz_set_str (x, str, base) + MP_INT *x; + const char *str; + int base; +#endif +{ + mp_ptr xp; + mp_size size; + mp_limb big_base; + int indigits_per_limb; + int negative = 0; + int inp_rawchar; + mp_limb inp_digit; + mp_limb res_digit; + size_t str_len; + mp_size i; + + if (str[0] == '-') + { + negative = 1; + str++; + } + + if (base == 0) + { + if (str[0] == '0') + { + if (str[1] == 'x' || str[1] == 'X') + base = 16; + else + base = 8; + } + else + base = 10; + } + + big_base = __mp_bases[base].big_base; + indigits_per_limb = __mp_bases[base].chars_per_limb; + + str_len = strlen (str); + + size = str_len / indigits_per_limb + 1; + if (x->alloc < size) + _mpz_realloc (x, size); + xp = x->d; + + 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 char *s; + int next_bitpos; + int bits_per_indigit = big_base; + + /* Accept and ignore 0x or 0X before hexadecimal numbers. */ + if (base == 16 && str[0] == '0' && (str[1] == 'x' || str[1] == 'X')) + { + str += 2; + str_len -= 2; + } + + res_digit = 0; + next_bitpos = 0; + + for (s = str + str_len - 1; s >= str; s--) + { + inp_rawchar = *s; + inp_digit = ascii_to_num[inp_rawchar]; + + if (inp_digit >= base) + { + /* Was it white space? Just ignore it. */ + if ((char) inp_digit == (char) SPC) + continue; + + /* We found rubbish in the string. Return -1 to indicate + the error. */ + return -1; + } + + res_digit |= inp_digit << next_bitpos; + next_bitpos += bits_per_indigit; + if (next_bitpos >= BITS_PER_MP_LIMB) + { + xp[size] = res_digit; + size++; + next_bitpos -= BITS_PER_MP_LIMB; + res_digit = inp_digit >> (bits_per_indigit - next_bitpos); + } + } + + xp[size] = res_digit; + size++; + for (i = size - 1; i >= 0; i--) + { + if (xp[i] != 0) + break; + } + size = i + 1; + } + else + { + /* General case. The base is not a power of 2. */ + + mp_size i; + int j; + mp_limb cy; + + for (;;) + { + res_digit = 0; + for (j = 0; j < indigits_per_limb; ) + { + inp_rawchar = (unsigned char) *str++; + inp_digit = ascii_to_num[inp_rawchar]; + + /* Negative means that the character was not a proper digit. */ + if (inp_digit >= base) + { + /* Was it white space? Just ignore it. */ + if ((char) inp_digit == (char) SPC) + continue; + + goto end_or_error; + } + + res_digit = res_digit * base + inp_digit; + + /* Increment the loop counter here, since it mustn't be + incremented when we do "continue" above. */ + j++; + } + + cy = res_digit; + + /* Insert RES_DIGIT into the result multi prec integer. */ + for (i = 0; i < size; i++) + { + mp_limb p1, p0; + umul_ppmm (p1, p0, big_base, xp[i]); + p0 += cy; + cy = p1 + (p0 < cy); + xp[i] = p0; + } + if (cy != 0) + { + xp[size] = cy; + size++; + } + } + + end_or_error: + /* We probably have some digits in RES_DIGIT (J tells how many). */ + if ((char) inp_digit != (char) EOF) + { + /* Error return. */ + return -1; + } + + /* J contains number of digits (in base BASE) remaining in + RES_DIGIT. */ + if (j > 0) + { + big_base = 1; + do + { + big_base *= base; + j--; + } + while (j > 0); + + cy = res_digit; + + /* Insert ultimate RES_DIGIT into the result multi prec integer. */ + for (i = 0; i < size; i++) + { + mp_limb p1, p0; + umul_ppmm (p1, p0, big_base, xp[i]); + p0 += cy; + cy = p1 + (p0 < cy); + xp[i] = p0; + } + if (cy != 0) + { + xp[size] = cy; + size++; + } + } + } + + if (negative) + size = -size; + x->size = size; + + return 0; +} diff --git a/gnu/lib/libgmp/alloca.c b/gnu/lib/libgmp/alloca.c new file mode 100644 index 0000000..91d64bb --- /dev/null +++ b/gnu/lib/libgmp/alloca.c @@ -0,0 +1,466 @@ +/* alloca.c -- allocate automatically reclaimed memory + (Mostly) portable public-domain implementation -- D A Gwyn + + This implementation of the PWB library alloca function, + which is used to allocate space off the run-time stack so + that it is automatically reclaimed upon procedure exit, + was inspired by discussions with J. Q. Johnson of Cornell. + J.Otto Tennant contributed the Cray support. + + There are some preprocessor constants that can + be defined when compiling for your specific system, for + improved efficiency; however, the defaults should be okay. + + The general concept of this implementation is to keep + track of all alloca-allocated blocks, and reclaim any + that are found to be deeper in the stack than the current + invocation. This heuristic does not reclaim storage as + soon as it becomes invalid, but it will do so eventually. + + As a special case, alloca(0) reclaims storage without + allocating any. It is a good idea to use alloca(0) in + your main control loop, etc. to force garbage collection. */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +/* If compiling with GCC, this file's not needed. */ +#ifndef alloca + +#ifdef emacs +#ifdef static +/* actually, only want this if static is defined as "" + -- this is for usg, in which emacs must undefine static + in order to make unexec workable + */ +#ifndef STACK_DIRECTION +you +lose +-- must know STACK_DIRECTION at compile-time +#endif /* STACK_DIRECTION undefined */ +#endif /* static */ +#endif /* emacs */ + +#ifdef emacs +#define free xfree +#endif + +/* If your stack is a linked list of frames, you have to + provide an "address metric" ADDRESS_FUNCTION macro. */ + +#ifdef CRAY +long i00afunc (); +#define ADDRESS_FUNCTION(arg) (char *) i00afunc (&(arg)) +#else +#define ADDRESS_FUNCTION(arg) &(arg) +#endif + +#if __STDC__ +typedef void *pointer; +#else +typedef char *pointer; +#endif + +#define NULL 0 + +extern pointer (*_mp_allocate_func) (); + +/* Define STACK_DIRECTION if you know the direction of stack + growth for your system; otherwise it will be automatically + deduced at run-time. + + STACK_DIRECTION > 0 => grows toward higher addresses + STACK_DIRECTION < 0 => grows toward lower addresses + STACK_DIRECTION = 0 => direction of growth unknown */ + +#ifndef STACK_DIRECTION +#define STACK_DIRECTION 0 /* Direction unknown. */ +#endif + +#if STACK_DIRECTION != 0 + +#define STACK_DIR STACK_DIRECTION /* Known at compile-time. */ + +#else /* STACK_DIRECTION == 0; need run-time code. */ + +static int stack_dir; /* 1 or -1 once known. */ +#define STACK_DIR stack_dir + +static void +find_stack_direction () +{ + static char *addr = NULL; /* Address of first `dummy', once known. */ + auto char dummy; /* To get stack address. */ + + if (addr == NULL) + { /* Initial entry. */ + addr = ADDRESS_FUNCTION (dummy); + + find_stack_direction (); /* Recurse once. */ + } + else + { + /* Second entry. */ + if (ADDRESS_FUNCTION (dummy) > addr) + stack_dir = 1; /* Stack grew upward. */ + else + stack_dir = -1; /* Stack grew downward. */ + } +} + +#endif /* STACK_DIRECTION == 0 */ + +/* An "alloca header" is used to: + (a) chain together all alloca'ed blocks; + (b) keep track of stack depth. + + It is very important that sizeof(header) agree with malloc + alignment chunk size. The following default should work okay. */ + +#ifndef ALIGN_SIZE +#define ALIGN_SIZE sizeof(double) +#endif + +typedef union hdr +{ + char align[ALIGN_SIZE]; /* To force sizeof(header). */ + struct + { + union hdr *next; /* For chaining headers. */ + char *deep; /* For stack depth measure. */ + } h; +} header; + +static header *last_alloca_header = NULL; /* -> last alloca header. */ + +/* Return a pointer to at least SIZE bytes of storage, + which will be automatically reclaimed upon exit from + the procedure that called alloca. Originally, this space + was supposed to be taken from the current stack frame of the + caller, but that method cannot be made to work for some + implementations of C, for example under Gould's UTX/32. */ + +pointer +alloca (size) + unsigned size; +{ + auto char probe; /* Probes stack depth: */ + register char *depth = ADDRESS_FUNCTION (probe); + +#if STACK_DIRECTION == 0 + if (STACK_DIR == 0) /* Unknown growth direction. */ + find_stack_direction (); +#endif + + /* Reclaim garbage, defined as all alloca'd storage that + was allocated from deeper in the stack than currently. */ + + { + register header *hp; /* Traverses linked list. */ + + for (hp = last_alloca_header; hp != NULL;) + if ((STACK_DIR > 0 && hp->h.deep > depth) + || (STACK_DIR < 0 && hp->h.deep < depth)) + { + register header *np = hp->h.next; + + free ((pointer) hp); /* Collect garbage. */ + + hp = np; /* -> next header. */ + } + else + break; /* Rest are not deeper. */ + + last_alloca_header = hp; /* -> last valid storage. */ + } + + if (size == 0) + return NULL; /* No allocation required. */ + + /* Allocate combined header + user data storage. */ + + { + register pointer new = (*_mp_allocate_func) (sizeof (header) + size); + /* Address of header. */ + + ((header *) new)->h.next = last_alloca_header; + ((header *) new)->h.deep = depth; + + last_alloca_header = (header *) new; + + /* User storage begins just after header. */ + + return (pointer) ((char *) new + sizeof (header)); + } +} + +#ifdef CRAY + +#ifdef DEBUG_I00AFUNC +#include +#endif + +#ifndef CRAY_STACK +#define CRAY_STACK +#ifndef CRAY2 +/* Stack structures for CRAY-1, CRAY X-MP, and CRAY Y-MP */ +struct stack_control_header + { + long shgrow:32; /* Number of times stack has grown. */ + long shaseg:32; /* Size of increments to stack. */ + long shhwm:32; /* High water mark of stack. */ + long shsize:32; /* Current size of stack (all segments). */ + }; + +/* The stack segment linkage control information occurs at + the high-address end of a stack segment. (The stack + grows from low addresses to high addresses.) The initial + part of the stack segment linkage control information is + 0200 (octal) words. This provides for register storage + for the routine which overflows the stack. */ + +struct stack_segment_linkage + { + long ss[0200]; /* 0200 overflow words. */ + long sssize:32; /* Number of words in this segment. */ + long ssbase:32; /* Offset to stack base. */ + long:32; + long sspseg:32; /* Offset to linkage control of previous + segment of stack. */ + long:32; + long sstcpt:32; /* Pointer to task common address block. */ + long sscsnm; /* Private control structure number for + microtasking. */ + long ssusr1; /* Reserved for user. */ + long ssusr2; /* Reserved for user. */ + long sstpid; /* Process ID for pid based multi-tasking. */ + long ssgvup; /* Pointer to multitasking thread giveup. */ + long sscray[7]; /* Reserved for Cray Research. */ + long ssa0; + long ssa1; + long ssa2; + long ssa3; + long ssa4; + long ssa5; + long ssa6; + long ssa7; + long sss0; + long sss1; + long sss2; + long sss3; + long sss4; + long sss5; + long sss6; + long sss7; + }; + +#else /* CRAY2 */ +/* The following structure defines the vector of words + returned by the STKSTAT library routine. */ +struct stk_stat + { + long now; /* Current total stack size. */ + long maxc; /* Amount of contiguous space which would + be required to satisfy the maximum + stack demand to date. */ + long high_water; /* Stack high-water mark. */ + long overflows; /* Number of stack overflow ($STKOFEN) calls. */ + long hits; /* Number of internal buffer hits. */ + long extends; /* Number of block extensions. */ + long stko_mallocs; /* Block allocations by $STKOFEN. */ + long underflows; /* Number of stack underflow calls ($STKRETN). */ + long stko_free; /* Number of deallocations by $STKRETN. */ + long stkm_free; /* Number of deallocations by $STKMRET. */ + long segments; /* Current number of stack segments. */ + long maxs; /* Maximum number of stack segments so far. */ + long pad_size; /* Stack pad size. */ + long current_address; /* Current stack segment address. */ + long current_size; /* Current stack segment size. This + number is actually corrupted by STKSTAT to + include the fifteen word trailer area. */ + long initial_address; /* Address of initial segment. */ + long initial_size; /* Size of initial segment. */ + }; + +/* The following structure describes the data structure which trails + any stack segment. I think that the description in 'asdef' is + out of date. I only describe the parts that I am sure about. */ + +struct stk_trailer + { + long this_address; /* Address of this block. */ + long this_size; /* Size of this block (does not include + this trailer). */ + long unknown2; + long unknown3; + long link; /* Address of trailer block of previous + segment. */ + long unknown5; + long unknown6; + long unknown7; + long unknown8; + long unknown9; + long unknown10; + long unknown11; + long unknown12; + long unknown13; + long unknown14; + }; + +#endif /* CRAY2 */ +#endif /* not CRAY_STACK */ + +#ifdef CRAY2 +/* Determine a "stack measure" for an arbitrary ADDRESS. + I doubt that "lint" will like this much. */ + +static long +i00afunc (long *address) +{ + struct stk_stat status; + struct stk_trailer *trailer; + long *block, size; + long result = 0; + + /* We want to iterate through all of the segments. The first + step is to get the stack status structure. We could do this + more quickly and more directly, perhaps, by referencing the + $LM00 common block, but I know that this works. */ + + STKSTAT (&status); + + /* Set up the iteration. */ + + trailer = (struct stk_trailer *) (status.current_address + + status.current_size + - 15); + + /* There must be at least one stack segment. Therefore it is + a fatal error if "trailer" is null. */ + + if (trailer == 0) + abort (); + + /* Discard segments that do not contain our argument address. */ + + while (trailer != 0) + { + block = (long *) trailer->this_address; + size = trailer->this_size; + if (block == 0 || size == 0) + abort (); + trailer = (struct stk_trailer *) trailer->link; + if ((block <= address) && (address < (block + size))) + break; + } + + /* Set the result to the offset in this segment and add the sizes + of all predecessor segments. */ + + result = address - block; + + if (trailer == 0) + { + return result; + } + + do + { + if (trailer->this_size <= 0) + abort (); + result += trailer->this_size; + trailer = (struct stk_trailer *) trailer->link; + } + while (trailer != 0); + + /* We are done. Note that if you present a bogus address (one + not in any segment), you will get a different number back, formed + from subtracting the address of the first block. This is probably + not what you want. */ + + return (result); +} + +#else /* not CRAY2 */ +/* Stack address function for a CRAY-1, CRAY X-MP, or CRAY Y-MP. + Determine the number of the cell within the stack, + given the address of the cell. The purpose of this + routine is to linearize, in some sense, stack addresses + for alloca. */ + +static long +i00afunc (long address) +{ + long stkl = 0; + + long size, pseg, this_segment, stack; + long result = 0; + + struct stack_segment_linkage *ssptr; + + /* Register B67 contains the address of the end of the + current stack segment. If you (as a subprogram) store + your registers on the stack and find that you are past + the contents of B67, you have overflowed the segment. + + B67 also points to the stack segment linkage control + area, which is what we are really interested in. */ + + stkl = CRAY_STACKSEG_END (); + ssptr = (struct stack_segment_linkage *) stkl; + + /* If one subtracts 'size' from the end of the segment, + one has the address of the first word of the segment. + + If this is not the first segment, 'pseg' will be + nonzero. */ + + pseg = ssptr->sspseg; + size = ssptr->sssize; + + this_segment = stkl - size; + + /* It is possible that calling this routine itself caused + a stack overflow. Discard stack segments which do not + contain the target address. */ + + while (!(this_segment <= address && address <= stkl)) + { +#ifdef DEBUG_I00AFUNC + fprintf (stderr, "%011o %011o %011o\n", this_segment, address, stkl); +#endif + if (pseg == 0) + break; + stkl = stkl - pseg; + ssptr = (struct stack_segment_linkage *) stkl; + size = ssptr->sssize; + pseg = ssptr->sspseg; + this_segment = stkl - size; + } + + result = address - this_segment; + + /* If you subtract pseg from the current end of the stack, + you get the address of the previous stack segment's end. + This seems a little convoluted to me, but I'll bet you save + a cycle somewhere. */ + + while (pseg != 0) + { +#ifdef DEBUG_I00AFUNC + fprintf (stderr, "%011o %011o\n", pseg, size); +#endif + stkl = stkl - pseg; + ssptr = (struct stack_segment_linkage *) stkl; + size = ssptr->sssize; + pseg = ssptr->sspseg; + result += size; + } + return (result); +} + +#endif /* not CRAY2 */ +#endif /* CRAY */ + +#endif /* no alloca */ diff --git a/gnu/lib/libgmp/cre-conv-tab.c b/gnu/lib/libgmp/cre-conv-tab.c new file mode 100644 index 0000000..bbb6e82 --- /dev/null +++ b/gnu/lib/libgmp/cre-conv-tab.c @@ -0,0 +1,141 @@ +/* cre-conv-tab.c -- Create conversion table in a wordsize-dependent way. + +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" +#include "gmp-impl.h" +#include "longlong.h" + +extern double floor (); +extern double log (); + +static unsigned long int +upow (b, e) + unsigned long int b; + unsigned int e; +{ + unsigned long int y = 1; + + while (e != 0) + { + while ((e & 1) == 0) + { + b = b * b; + e >>= 1; + } + y = y * b; + e -= 1; + } + + return y; +} + +unsigned int +ulog2 (x) + unsigned long int x; +{ + unsigned int i; + for (i = 0; x != 0; i++) + x >>= 1; + return i; +} + +main () +{ + int i; + unsigned long idig; + unsigned long big_base, big_base_inverted; + double fdig; + int dummy; + int normalization_steps; + + unsigned long int max_uli; + int bits_uli; + + max_uli = 1; + for (i = 1; ; i++) + { + if ((max_uli << 1) == 0) + break; + max_uli <<= 1; + } + bits_uli = i; + + puts ("/* __mp_bases -- Structure for conversion between internal binary"); + puts (" format and strings in base 2..36. The fields are explained in"); + puts (" gmp-impl.h."); + 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 (""); + puts ("#include \"gmp.h\""); + puts ("#include \"gmp-impl.h\""); + puts (""); + + puts ("const struct bases __mp_bases[37] =\n{"); + puts (" /* 0 */ {0, 0, 0, 0.0},"); + puts (" /* 1 */ {0, 0, 0, 0.0},"); + for (i = 2; i <= 36; i++) + { + /* The weird expression here is because many /bin/cc compilers + generate incorrect code for conversions from large unsigned + integers to double. */ + fdig = log(2.0)/log((double) i); + idig = floor(bits_uli * fdig); + if ((i & (i - 1)) == 0) + { + big_base = ulog2 (i) - 1; + big_base_inverted = 0; + } + else + { + big_base = upow (i, idig); + for (normalization_steps = 0; + (long int) (big_base << normalization_steps) >= 0; + normalization_steps++) + ; + udiv_qrnnd (big_base_inverted, dummy, + -(big_base << normalization_steps), 0, + big_base << normalization_steps); + } + printf (" /* %2u */ {%lu, 0x%lX, 0x%lX, %.8f},\n", + i, idig, big_base, big_base_inverted, fdig); + } + puts ("};"); + + exit (0); +} diff --git a/gnu/lib/libgmp/cre-mparam.c b/gnu/lib/libgmp/cre-mparam.c new file mode 100644 index 0000000..db0c992 --- /dev/null +++ b/gnu/lib/libgmp/cre-mparam.c @@ -0,0 +1,118 @@ +/* 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; + + 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); +} diff --git a/gnu/lib/libgmp/cre-stddefh.c b/gnu/lib/libgmp/cre-stddefh.c new file mode 100644 index 0000000..4e1f862 --- /dev/null +++ b/gnu/lib/libgmp/cre-stddefh.c @@ -0,0 +1,42 @@ +/* cre-stddefh.c -- Check the size of a pointer and output an + appropriate size_t declaration. + +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 + +main (argc, argv) + int argc; + char **argv; +{ + if (sizeof (int *) == sizeof (unsigned long int)) + puts ("typedef unsigned long int size_t;"); + else + if (sizeof (int *) == sizeof (unsigned int)) + puts ("typedef unsigned int size_t;"); + else + { + fprintf (stderr, + "%s: Can't find a reasonable definition for \"size_t\".\n", + argv[0]); + exit (1); + } + + exit (0); +} diff --git a/gnu/lib/libgmp/gmp-impl.h b/gnu/lib/libgmp/gmp-impl.h new file mode 100644 index 0000000..e02691f --- /dev/null +++ b/gnu/lib/libgmp/gmp-impl.h @@ -0,0 +1,126 @@ +/* Include file for internal GNU MP types and definitions. + +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. */ + +#if defined (__GNUC__) || defined (__sparc__) || defined (sparc) +#define alloca __builtin_alloca +#endif + +#ifndef NULL +#define NULL 0L +#endif + +#if defined (__GNUC__) +volatile void abort (void); +#else +#define inline /* Empty */ +void *alloca(); +#endif + +#define ABS(x) (x >= 0 ? x : -x) + +#include "gmp-mparam.h" + +#ifdef __STDC__ +void *malloc (size_t); +void *realloc (void *, size_t); +void free (void *); + +extern void * (*_mp_allocate_func) (size_t); +extern void * (*_mp_reallocate_func) (void *, size_t, size_t); +extern void (*_mp_free_func) (void *, size_t); + +void *_mp_default_allocate (size_t); +void *_mp_default_reallocate (void *, size_t, size_t); +void _mp_default_free (void *, size_t); + +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 */ + +void *malloc (); +void *realloc (); +void free (); + +extern void * (*_mp_allocate_func) (); +extern void * (*_mp_reallocate_func) (); +extern void (*_mp_free_func) (); + +void *_mp_default_allocate (); +void *_mp_default_reallocate (); +void _mp_default_free (); + +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) \ + do { \ + mp_size i; \ + for (i = 0; i < (NLIMBS); i++) \ + (DST)[i] = (SRC)[i]; \ + } while (0) +/* Zero NLIMBS *limbs* AT DST. */ +#define MPN_ZERO(DST, NLIMBS) \ + do { \ + mp_size i; \ + for (i = 0; i < (NLIMBS); i++) \ + (DST)[i] = 0; \ + } 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. */ +#define MPZ_TMP_INIT(X, NLIMBS) \ + do { \ + (X)->alloc = (NLIMBS); \ + (X)->d = (mp_ptr) alloca ((NLIMBS) * BYTES_PER_MP_LIMB); \ + } 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. */ + 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; +}; + +extern const struct bases __mp_bases[37]; diff --git a/gnu/lib/libgmp/gmp.h b/gnu/lib/libgmp/gmp.h new file mode 100644 index 0000000..91ee7af --- /dev/null +++ b/gnu/lib/libgmp/gmp.h @@ -0,0 +1,302 @@ +/* gmp.h -- Definitions for GNU multiple precision functions. + +Copyright (C) 1991, 1993 Free Software Foundation, Inc. + +This file is part of the 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. */ + +#ifndef __GMP_H__ +#define __GMP_H__ + +#define __GNU_MP__ + +#ifndef __MP_H__ +#define __need_size_t +#include +#endif + +#ifndef MINT +#ifndef __MP_SMALL__ +typedef struct +{ + long int alloc; /* Number of *limbs* allocated and pointed + to by the D field. */ + long int 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; +#else +typedef struct +{ + short int alloc; /* Number of *limbs* allocated and pointed + to by the D field. */ + short int 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 +#endif + +#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; + +/* 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; +#if 0 + long int num_alloc; /* Number of limbs allocated + for the numerator. */ + long int 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 + for the denominator. */ + long int den_size; /* Length of the denominator. (This field + should always be positive.) */ + mp_ptr den; /* Pointer to the denominator limbs. */ +#endif +} MP_RAT; + +#ifdef __STDC__ +void mp_set_memory_functions (void *(*) (size_t), + void *(*) (void *, size_t, size_t), + void (*) (void *, size_t)); + +/**************** 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 (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 *); +#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); + +/**************** Rational (i.e. Q) routines. ****************/ + +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 *); + +/************ Low level positive-integer (i.e. N) routines. ************/ + +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); + +#else /* ! __STDC__ */ +void mp_set_memory_functions (); + +/**************** Integer (i.e. Z) routines. ****************/ + +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 (); + +void mpz_inp_raw (); +void mpz_inp_str (); +void mpz_out_raw (); +void mpz_out_str (); + +void mpz_array_init (); +void mpz_random (); +void mpz_random2 (); +size_t mpz_size (); +size_t mpz_sizeinbase (); + +/**************** Rational (i.e. Q) routines. ****************/ + +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 (); + +/************ Low level positive-integer (i.e. N) routines. ************/ + +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__ */ + +#endif /* __GMP_H__ */ diff --git a/gnu/lib/libgmp/gmp.texi b/gnu/lib/libgmp/gmp.texi new file mode 100644 index 0000000..7aaa88b --- /dev/null +++ b/gnu/lib/libgmp/gmp.texi @@ -0,0 +1,1291 @@ +\input texinfo @c -*-texinfo-*- +@comment %**start of header +@setfilename gmp.info +@settitle GNU MP 1.3.2 +@synindex tp fn +@c footnotestyle separate +@c paragraphindent 2 +@comment %**end of header + +@c smallbook + +@iftex +@finalout +@end iftex + +@c Note: the edition number is listed in *three* places; please update +@c all three. Also, update the month and year where appropriate. + +@c ==> Update edition number for settitle and subtitle, and in the +@c ==> following paragraph; update date, too. + +@ifinfo +This file documents GNU MP, a library for arbitrary-precision integer +and rational number arithmetic. + +This is a draft edition of the documentation, last updated May 20 1993. + +Copyright (C) 1991, 1993 Free Software Foundation, Inc. + +Permission is granted to make and distribute verbatim copies of +this manual provided the copyright notice and this permission notice +are preserved on all copies. + +@ignore +Permission is granted to process this file through TeX and print the +results, provided the printed document carries copying permission +notice identical to this one except for the removal of this paragraph +(this paragraph not being relevant to the printed manual). + +@end ignore +Permission is granted to copy and distribute modified versions of this +manual under the conditions for verbatim copying, provided that the entire +resulting derived work is distributed under the terms of a permission +notice identical to this one. + +Permission is granted to copy and distribute translations of this manual +into another language, under the above conditions for modified versions, +except that this permission notice may be stated in a translation approved +by the Foundation. +@end ifinfo + +@setchapternewpage odd +@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 + +@author by Torbj@"orn Granlund + +@comment Include the Distribution inside the titlepage so +@c that headings are turned off. + +@page +@vskip 0pt plus 1filll +Copyright @copyright{} 1991, 1993 Free Software Foundation, Inc. + +@sp 2 + +Published by the Free Software Foundation @* +675 Massachusetts Avenue, @* +Cambridge, MA 02139 USA @* + +Permission is granted to make and distribute verbatim copies of +this manual provided the copyright notice and this permission notice +are preserved on all copies. + +Permission is granted to copy and distribute modified versions of this +manual under the conditions for verbatim copying, provided that the entire +resulting derived work is distributed under the terms of a permission +notice identical to this one. + +Permission is granted to copy and distribute translations of this manual +into another language, under the above conditions for modified versions, +except that this permission notice may be stated in a translation approved +by the Foundation. +@end titlepage + +@ifinfo +@node Top, Copying, (dir), (dir) +@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. +* 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. + +* References:: +* Concept Index:: +* Function Index:: +@end menu + +@node Copying, Intro, Top, Top +@comment node-name, next, previous, up +@unnumbered GNU MP Copying Conditions +@cindex Copying conditions +@cindex Conditions for copying GNU MP + +This library is @dfn{free}; this means that everyone is free to use it +and free to redistribute it on a free basis. The library is not in the +public domain; it is copyrighted and there are restrictions on its +distribution, but these restrictions are designed to permit everything +that a good cooperating citizen would want to do. What is not allowed +is to try to prevent others from further sharing any version of this +library that they might get from you.@refill + + Specifically, we want to make sure that you have the right to give +away copies of the library, that you receive source code or else can get +it if you want it, that you can change this library or use pieces of it +in new free programs, and that you know you can do these things.@refill + + To make sure that everyone has such rights, we have to forbid you to +deprive anyone else of these rights. For example, if you distribute +copies of the 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 + + 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 + + The precise conditions of the license for the GMP library are found in +the General Public License that accompany the source code.@refill + +@node Intro, Initialization, Copying, Top +@comment node-name, next, previous, up +@chapter Introduction to MP +@cindex Introduction +@cindex Overview + +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. + +There are five groups of functions in the MP library: + +@enumerate +@item +Functions for signed integer arithmetic, with names +beginning with @code{mpz_}. + +@item +Functions for rational number arithmetic, with names beginning with +@code{mpq_}. + +@item +Functions compatible with Berkeley MP, such as @code{itom}, @code{madd}, +and @code{mult}. + +@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_}. + +@item +Miscellaneous functions. +@end enumerate + +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. + +@menu +* Nomenclature:: +* Thanks:: +@end menu + +@node Nomenclature, Thanks, Intro, Intro +@comment node-name, next, previous, up +@section Nomenclature and Data Types +@cindex nomenclature + +@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: + +@example +MP_INT sum; + +struct foo @{ MP_INT x, y; @}; + +MP_INT vec[20]; +@end example + +@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: + +@example +MP_RAT quotient; +@end example + +@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. + +@node Thanks,, Nomenclature, Intro +@comment node-name, next, previous, up +@section Thanks + +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 +@comment node-name, next, previous, up +@chapter Integer Functions +@cindex Integer functions + +This chapter describes the MP functions for performing integer arithmetic. + +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}. + +@menu +* Initializing Integers:: +* Assigning Integers:: +* Simultaneous Integer Init & Assign:: +* Converting Integers:: +* Integer Arithmetic:: +* Logic on Integers:: +* I/O of Integers:: +@end menu + +@node Initializing Integers, Assigning Integers, , Integer Functions +@comment node-name, next, previous, up +@section Initializing Integer Objects + +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}. + +@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. +@end deftypefun + +Here is an example of using @code{mpz_init}: + +@example +@{ + MP_INT integ; + mpz_init (&integ); + @dots{} + mpz_add (&integ, @dots{}); + @dots{} + mpz_sub (&integ, @dots{}); + + /* Unless you are now exiting the program, do ... */ + mpz_clear (&integ); +@} +@end example + +@noindent +As you can see, you can store new values any number of times, once an +object is initialized. + +@deftypefun void mpz_clear (MP_INT *@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. +@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. +@end deftypefun + +@deftypefun void mpz_array_init (MP_INT @var{integer_array}[], size_t @var{array_size}, mp_size @var{fixed_num_limbs}) +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. + +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 +@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}. +@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. + +This function returns 0 if the entire string up to the '\0' is a valid +number in base @var{base}. Otherwise it returns @minus{}1. +@end deftypefun + + +@node Simultaneous Integer Init & Assign, Converting Integers, Assigning Integers, Integer Functions +@comment node-name, next, previous, up +@subsection Combined Initialization and Assignment Functions +@cindex Initialization and assignment functions, combined + +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{}}. + +Here is an example of using one: + +@example +@{ + MP_INT integ; + mpz_init_set_str (&integ, "3141592653589793238462643383279502884", 10); + @dots{} + mpz_sub (&integ, @dots{}); + + mpz_clear (&integ); +@} +@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! + +@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}. +@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 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.) +@end deftypefun + + +@node Converting Integers, Integer Arithmetic, Simultaneous Integer Init & Assign, Integer Functions +@comment node-name, next, previous, up +@section 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. +@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}. +@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. + +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}). + +This function returns a pointer to the result string. +@end deftypefun + + +@node Integer Arithmetic, Logic on Integers, Converting Integers, Integer Functions +@comment node-name, next, previous, up +@section Integer 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 +@ifinfo +@var{operand}@minus{}@var{root}*@var{root}, +@end ifinfo +@iftex +@tex +$operand - root^2$, +@end tex +@end iftex +(i.e@. zero if @var{operand} is a perfect square). + +If @var{root} and @var{remainder} are the same variable, the results are +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. +@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. +@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. +@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}. +@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. +@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}. +@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}) +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}. +@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}. +@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 +@comment node-name, next, previous, up +@section Logical Functions +@cindex Logical 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}. +@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}. +@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}. + +This function is missing in the current release. +@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}. +@end deftypefun + +@node I/O of Integers,, Logic on Integers, Integer Functions +@comment node-name, next, previous, up +@section Input and Output Functions +@cindex Input and output functions +@cindex Output functions +@cindex I/O functions + +Functions that perform input from a standard I/O stream, and functions for +output conversion. + +@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}. +@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, +otherwise decimal is assumed. +@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. +@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. +@end deftypefun + + +@node Rational Number Functions, Low-level 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. + +The set of functions is quite small. Maybe it will be extended in a +future release. + +@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. +@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. +@end deftypefun + +@deftypefun void mpq_set (MP_RAT *@var{dest_rational}, MP_RAT *@var{src_rational}) +Assign @var{dest_rational} from @var{src_rational}. +@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. +@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. +@end deftypefun + +@deftypefun void mpq_add (MP_RAT *@var{sum}, MP_RAT *@var{addend1}, MP_RAT *@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}) +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} +@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}. +@end deftypefun + +@deftypefun void mpq_neg (MP_RAT *@var{negated_operand}, MP_RAT *@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}. +@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. +@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. +@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. +@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. +@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. +@end deftypefun + + +@node Low-level Functions, BSD Compatible Functions, Rational Number Functions, Top +@comment node-name, next, previous, up +@chapter Low-level Functions +@cindex Low-level functions + +@c 1. Some of these function clobber input operands. +@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 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 responsability of the caller to ensure that the destination +has enough space for storing the result. + +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. + +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 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}. + +@example +mpn_add (dest_ptr, src1_ptr, src1_size, src2_ptr, src2_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. + +@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}) +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. + +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}. + +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 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}) +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. + +The destination has to have space for @var{src1_size} + @var{src1_size} +limbs, even if the result might be one limb smaller. + +This function requires that @var{src1_size} is greater than or equal to +@var{src2_size}. The destination must be distinct from either input +operands. +@end deftypefun + +@deftypefun mp_size 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}. + +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. + +The most significant bit of the most significant limb of the divisor +has to be 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. +@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}) +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. + +Overlapping of the destination space and the source space is allowed in this +function, provdied @var{dest_ptr} >= @var{src_ptr}. +@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}) +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. + +Overlaping of the destination space and the source space is allowed in this +function, provdied @var{dest_ptr} <= @var{src_ptr}. +@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. +@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. +@end deftypefun + + +@node BSD Compatible Functions, Miscellaneous Functions, Low-level Functions, Top +@comment node-name, next, previous, up +@chapter Berkeley MP Compatible Functions +@cindex BSD MP compatible functions + +These functions are intended to be fully compatible with the Berkeley MP +library which is available on many BSD derived U*ix systems. + +The original Berkeley MP library has a usage restriction: you cannot use +the same variable as both source and destination in a single function +call. The compatible functions in GNU MP do not share this +restriction---inputs and outputs may overlap. + +It is not recommended that new programs are written using these +functions. Apart from the incomplete set of functions, the interface +for initializing @code{MINT} objects is more error prone, and the +@code{pow} function collides with @code{pow} in @file{libm.a}. + +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. +@end deftypefun + +@deftypefun {MINT *} xtom (char *@var{initial_value}) +Allocate an integer consisting of a @code{MINT} object and dynamic limb +space. Initialize the integer from @var{initial_value}, a hexadecimal, +'\0'-terminate C string. Return a pointer to the @code{MINT} object. +@end deftypefun + +@deftypefun void move (MINT *@var{src}, MINT *@var{dest}) +Set @var{dest} to @var{src} by copying. Both variables must be +previously initialized. +@end deftypefun + +@deftypefun void madd (MINT *@var{src_1}, MINT *@var{src_2}, MINT *@var{destination}) +Add @var{src_1} and @var{src_2} and put the sum in @var{destination}. +@end deftypefun + +@deftypefun void msub (MINT *@var{src_1}, MINT *@var{src_2}, MINT *@var{destination}) +Subtract @var{src_2} from @var{src_1} and put the difference in +@var{destination}. +@end deftypefun + +@deftypefun void mult (MINT *@var{src_1}, MINT *@var{src_2}, MINT *@var{destination}) +Multiply @var{src_1} and @var{src_2} and put the product in +@var{destination}. +@end deftypefun + +@deftypefun void mdiv (MINT *@var{dividend}, MINT *@var{divisor}, MINT *@var{quotient}, MINT *@var{remainder}) +@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. + +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. +@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}, +@end ifinfo +@iftex +@tex +$operand - root^2$, +@end tex +@end iftex +(i.e@. zero if @var{operand} is a perfect square). +@end deftypefun + +@deftypefun void pow (MINT *@var{base}, MINT *@var{exp}, MINT *@var{mod}, MINT *@var{dest}) +Set @var{dest} to (@var{base} raised to @var{exp}) modulo @var{mod}. +@end deftypefun + +@deftypefun void rpow (MINT *@var{base}, signed short int @var{exp}, MINT *@var{dest}) +Set @var{dest} to @var{base} raised to @var{exp}. +@end deftypefun + +@deftypefun void gcd (MINT *@var{operand1}, MINT *@var{operand2}, MINT *@var{res}) +Set @var{res} to the greatest common divisor of @var{operand1} and +@var{operand2}. +@end deftypefun + +@deftypefun int mcmp (MINT *@var{operand1}, MINT *@var{operand2}) +Compare @var{operand1} and @var{operand2}. Return a positive value if +@var{operand1} > @var{operand2}, zero if @var{operand1} = +@var{operand2}, and a negative value if @var{operand1} < @var{operand2}. +@end deftypefun + +@deftypefun void min (MINT *@var{dest}) +Input a decimal string from 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. +@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). +@end deftypefun + +@deftypefun void mfree (MINT *@var{operand}) +De-allocate, the space used by @var{operand}. @strong{This function +should only be passed a value returned by @code{itom} or @code{xtom}.} +@end deftypefun + +@node Miscellaneous Functions, Custom Allocation, BSD Compatible Functions, Top +@comment node-name, next, previous, up +@chapter Miscellaneous Functions +@cindex Miscellaneous functions + +@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. +@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. + +@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}. + +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. + +@item void @var{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 + +(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 +@comment node-name, next, previous, up +@chapter Reporting Bugs +@cindex Reporting bugs + +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. + +Please make sure that the bug is really in the GNU MP library. + +You have to send us a test case that makes it possible for us to +reproduce the bug. + +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. + +Make sure that the bug report includes all information you would +need to fix this kind of bug for someone else. Think twice. + +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: tege@@gnu.ai.mit.edu. + +If you think something in this manual is unclear, or downright +incorrect, or if the language needs to be improved, please send a note +to the same address. + + +@node References, , , Top +@comment node-name, next, previous, up +@unnumbered References + +@itemize @bullet + +@item +Donald E@. Knuth, "The Art of Computer Programming", vol 2, +"Seminumerical Algorithms", 2nd edition, Addison-Wesley, 1981. + +@item +John D@. Lipson, "Elements of Algebra and Algebraic Computing", +The Benjamin Cummins Publishing Company Inc, 1981. + +@item +Richard M@. Stallman, "Using and Porting GCC", Free Software Foundation, +1993. + +@item +Peter L@. Montgomery, "Modular Multiplication Without Trial Division", +Mathematics of Computation, volume 44, number 170, April 1985. + +@end itemize + +@node Concept Index, , , Top +@comment node-name, next, previous, up +@unnumbered Concept Index +@printindex cp + +@node Function Index, , , Top +@comment node-name, next, previous, up +@unnumbered Function and Type Index +@printindex fn + + +@contents +@bye diff --git a/gnu/lib/libgmp/itom.c b/gnu/lib/libgmp/itom.c new file mode 100644 index 0000000..64502fc --- /dev/null +++ b/gnu/lib/libgmp/itom.c @@ -0,0 +1,53 @@ +/* itom -- BSD compatible allocate and initiate a MINT. + +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 "mp.h" +#include "gmp.h" +#include "gmp-impl.h" + +MINT * +#ifdef __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->alloc = 1; + x->d = xp = (mp_ptr) (*_mp_allocate_func) (x->alloc * BYTES_PER_MP_LIMB); + if (n > 0) + { + x->size = 1; + xp[0] = n; + } + else if (n < 0) + { + x->size = -1; + xp[0] = -n; + } + else + x->size = 0; + + return x; +} diff --git a/gnu/lib/libgmp/longlong.h b/gnu/lib/libgmp/longlong.h new file mode 100644 index 0000000..fd7b4cc --- /dev/null +++ b/gnu/lib/libgmp/longlong.h @@ -0,0 +1,1027 @@ +/* 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. + + 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. + + 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. */ + +#ifndef LONG_TYPE_SIZE +#ifdef BITS_PER_LONGINT +#define LONG_TYPE_SIZE BITS_PER_LONGINT +#else +#define LONG_TYPE_SIZE 32 +#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. + + 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. + + 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. + + 4) sdiv_qrnnd(quotient, remainder, high_numerator, low_numerator, + denominator). Like udiv_qrnnd but the numbers are signed. The + quotient is rounded towards 0. + + 5) count_leading_zeros(count, x) counts the number of zero-bits from + the msb to the first non-zero bit. This is the number of steps X + needs to be shifted left to set the msb. Undefined for X == 0. + + 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. + + 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, + and is lost. + + If any of these macros are left undefined for a particular CPU, + C macros are used. */ + +/* The CPUs come in alphabetical order below. + + Please add support for more CPUs here, or improve the current support + for the CPUs below! */ + +#if defined (__GNUC__) && !defined (NO_ASM) + +/* We sometimes need to clobber "cc" with gcc2, but that would not be + understood by gcc1. Use cpp to avoid major code duplication. */ +#if __GNUC__ < 2 +#define __CLOBBER_CC +#define __AND_CLOBBER_CC +#else /* __GNUC__ >= 2 */ +#define __CLOBBER_CC : "cc" +#define __AND_CLOBBER_CC , "cc" +#endif /* __GNUC__ < 2 */ + +#if defined (__a29k__) || defined (___AM29K__) +#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))) +#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))) +#define umul_ppmm(xh, xl, m0, m1) \ + do { \ + unsigned long int __m0 = (m0), __m1 = (m1); \ + __asm__ ("multiplu %0,%1,%2" \ + : "=r" ((unsigned long int)(xl)) \ + : "r" (__m0), \ + "r" (__m1)); \ + __asm__ ("multmu %0,%1,%2" \ + : "=r" ((unsigned long int)(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))) +#define count_leading_zeros(count, x) \ + __asm__ ("clz %0,%1" \ + : "=r" ((unsigned long int)(count)) \ + : "r" ((unsigned long int)(x))) +#endif /* __a29k__ */ + +#if defined (__alpha__) +#define umul_ppmm(ph, pl, m0, m1) \ + do { \ + unsigned long int __m0 = (m0), __m1 = (m1); \ + __asm__ ("umulh %r1,%2,%0" \ + : "=r" ((unsigned long int) ph) \ + : "%rJ" (__m0), \ + "rI" (__m1)); \ + (pl) = (unsigned long int) (__m0) * (unsigned long int) (__m1); \ + } while (0) +#define UMUL_TIME 46 +#define UDIV_TIME 500 +#endif + +#if defined (__arm__) +#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))) +#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))) +#endif /* __arm__ */ + +#if defined (__gmicro__) +#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))) +#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))) +#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))) +#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))) +#define count_leading_zeros(count, x) \ + __asm__ ("bsch/1 %1,%0" \ + : "=g" (count) \ + : "g" ((unsigned long int)(x)), \ + "0" (0UL)) +#endif + +#if defined (__hppa) +#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))) +#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))) +#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; \ + } __xx; \ + __asm__ ("xmpyu %1,%2,%0" \ + : "=x" (__xx.__ll) \ + : "x" ((unsigned long int)(u)), \ + "x" ((unsigned long int)(v))); \ + (wh) = __xx.__i.__h; \ + (wl) = __xx.__i.__l; \ + } while (0) +#define UMUL_TIME 8 +#define UDIV_TIME 60 +#else +#define UMUL_TIME 40 +#define UDIV_TIME 80 +#endif +#define count_leading_zeros(count, x) \ + do { \ + unsigned long int __tmp; \ + __asm__ ( \ + "ldi 1,%0 + extru,= %1,15,16,%%r0 ; Bits 31..16 zero? + extru,tr %1,15,16,%1 ; No. Shift down, skip add. + ldo 16(%0),%0 ; Yes. Perform add. + extru,= %1,23,8,%%r0 ; Bits 15..8 zero? + extru,tr %1,23,8,%1 ; No. Shift down, skip add. + ldo 8(%0),%0 ; Yes. Perform add. + extru,= %1,27,4,%%r0 ; Bits 7..4 zero? + extru,tr %1,27,4,%1 ; No. Shift down, skip add. + ldo 4(%0),%0 ; Yes. Perform add. + extru,= %1,29,2,%%r0 ; Bits 3..2 zero? + extru,tr %1,29,2,%1 ; No. Shift down, skip add. + ldo 2(%0),%0 ; Yes. Perform add. + extru %1,30,1,%1 ; Extract bit 1. + sub %0,%1,%0 ; Subtract it. + " : "=r" (count), "=r" (__tmp) : "1" (x)); \ + } while (0) +#endif + +#if defined (__i386__) || defined (__i486__) +#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))) +#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))) +#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))) +#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))) +#define count_leading_zeros(count, x) \ + do { \ + unsigned long int __cbtmp; \ + __asm__ ("bsrl %1,%0" \ + : "=r" (__cbtmp) : "rm" ((unsigned long int)(x))); \ + (count) = __cbtmp ^ 31; \ + } while (0) +#define UMUL_TIME 40 +#define UDIV_TIME 40 +#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 (__i960__) +#define umul_ppmm(w1, w0, u, v) \ + ({union {long long int __ll; \ + struct {unsigned long int __l, __h;} __i; \ + } __xx; \ + __asm__ ("emul %2,%1,%0" \ + : "=d" (__xx.__ll) \ + : "%dI" ((unsigned long int)(u)), \ + "dI" ((unsigned long int)(v))); \ + (w1) = __xx.__i.__h; (w0) = __xx.__i.__l;}) +#define __umulsidi3(u, v) \ + ({long long int __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) \ + 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)); \ + } 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__ */ + +#if defined (__mc68000__) +#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))) +#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) +#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))) +#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))) +#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))) +#define count_leading_zeros(count, x) \ + __asm__ ("bfffo %1{%b2:%b2},%0" \ + : "=d" ((unsigned long int)(count)) \ + : "od" ((unsigned long int)(x)), "n" (0)) +#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 + 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") +#define UMUL_TIME 100 +#define UDIV_TIME 400 +#endif /* not mc68020 */ +#endif /* mc68000 */ + +#if defined (__m88000__) +#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))) +#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 +#define count_leading_zeros(count, x) \ + do { \ + unsigned long int __cbtmp; \ + __asm__ ("ff1 %0,%1" \ + : "=r" (__cbtmp) \ + : "r" ((unsigned long int)(x))); \ + (count) = __cbtmp ^ 31; \ + } while (0) +#if defined (__mc88110__) +#define umul_ppmm(wh, wl, u, v) \ + do { \ + union {long long int __ll; \ + struct {unsigned long int __h, __l;} __i; \ + } __xx; \ + __asm__ ("mulu.d %0,%1,%2" \ + : "=r" (__xx.__ll) \ + : "r" ((unsigned long int)(u)), \ + "r" ((unsigned long int)(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 +#endif /* __m88000__ */ + +#if defined (__mips__) +/* The LO and HI registers are fixed in gcc/mips.h, for some reason. */ +#if 0 && __GNUC__ >= 2 +#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))) +#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))) +#endif +#define UMUL_TIME 10 +#define UDIV_TIME 100 +#endif /* __mips__ */ + +#if defined (__ns32000__) +#define umul_ppmm(w1, w0, u, v) \ + ({union {long long int __ll; \ + struct {unsigned long int __l, __h;} __i; \ + } __xx; \ + __asm__ ("meid %2,%0" \ + : "=g" (__xx.__ll) \ + : "%0" ((unsigned long int)(u)), \ + "g" ((unsigned long int)(v))); \ + (w1) = __xx.__i.__h; (w0) = __xx.__i.__l;}) +#define __umulsidi3(u, v) \ + ({long long int __w; \ + __asm__ ("meid %2,%0" \ + : "=g" (__w) \ + : "%0" ((unsigned long int)(u)), \ + "g" ((unsigned long int)(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") +#endif /* __ns32000__ */ + +#if defined (__pyr__) +#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))) +#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. */ +#define umul_ppmm(w1, w0, u, v) \ + ({union {long long int __ll; \ + struct {unsigned long int __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)); \ + (w1) = __xx.__i.__h; (w0) = __xx.__i.__l;}) +#endif /* __pyr__ */ + +#if defined (__ibm032__) /* RT/ROMP */ +#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))) +#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))) +#define umul_ppmm(ph, pl, m0, m1) \ + do { \ + unsigned long int __m0 = (m0), __m1 = (m1); \ + __asm__ ( \ + "s r2,r2 + mts r10,%2 + m r2,%3 + m r2,%3 + m r2,%3 + m r2,%3 + m r2,%3 + m r2,%3 + m r2,%3 + m r2,%3 + m r2,%3 + m r2,%3 + m r2,%3 + m r2,%3 + m r2,%3 + m r2,%3 + m r2,%3 + m r2,%3 + cas %0,r2,r0 + mfs r10,%1" \ + : "=r" ((unsigned long int)(ph)), \ + "=r" ((unsigned long int)(pl)) \ + : "%r" (__m0), \ + "r" (__m1) \ + : "r2"); \ + (ph) += ((((signed long int) __m0 >> 31) & __m1) \ + + (((signed long int) __m1 >> 31) & __m0)); \ + } while (0) +#define UMUL_TIME 20 +#define UDIV_TIME 200 +#define count_leading_zeros(count, x) \ + do { \ + if ((x) >= 0x10000) \ + __asm__ ("clz %0,%1" \ + : "=r" ((unsigned long int)(count)) \ + : "r" ((unsigned long int)(x) >> 16)); \ + else \ + { \ + __asm__ ("clz %0,%1" \ + : "=r" ((unsigned long int)(count)) \ + : "r" ((unsigned long int)(x))); \ + (count) += 16; \ + } \ + } while (0) +#endif + +#if defined (__sparc__) +#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)) \ + __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)) \ + __CLOBBER_CC) +#if defined (__sparc_v8__) +#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. */ +#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 +#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) */ +#define umul_ppmm(w1, w0, u, v) \ + __asm__ ("! Inlined umul_ppmm + wr %%g0,%2,%%y ! SPARC has 0-3 delay insn after a wr + sra %3,31,%%g2 ! Don't move this insn + and %2,%%g2,%%g2 ! Don't move this insn + andcc %%g0,0,%%g1 ! Don't move this insn + mulscc %%g1,%3,%%g1 + mulscc %%g1,%3,%%g1 + mulscc %%g1,%3,%%g1 + mulscc %%g1,%3,%%g1 + mulscc %%g1,%3,%%g1 + mulscc %%g1,%3,%%g1 + mulscc %%g1,%3,%%g1 + mulscc %%g1,%3,%%g1 + mulscc %%g1,%3,%%g1 + mulscc %%g1,%3,%%g1 + mulscc %%g1,%3,%%g1 + mulscc %%g1,%3,%%g1 + mulscc %%g1,%3,%%g1 + mulscc %%g1,%3,%%g1 + mulscc %%g1,%3,%%g1 + mulscc %%g1,%3,%%g1 + mulscc %%g1,%3,%%g1 + mulscc %%g1,%3,%%g1 + mulscc %%g1,%3,%%g1 + mulscc %%g1,%3,%%g1 + mulscc %%g1,%3,%%g1 + mulscc %%g1,%3,%%g1 + mulscc %%g1,%3,%%g1 + mulscc %%g1,%3,%%g1 + mulscc %%g1,%3,%%g1 + mulscc %%g1,%3,%%g1 + mulscc %%g1,%3,%%g1 + mulscc %%g1,%3,%%g1 + mulscc %%g1,%3,%%g1 + mulscc %%g1,%3,%%g1 + mulscc %%g1,%3,%%g1 + mulscc %%g1,%3,%%g1 + mulscc %%g1,0,%%g1 + add %%g1,%%g2,%0 + rd %%y,%1" \ + : "=r" ((unsigned long int)(w1)), \ + "=r" ((unsigned long int)(w0)) \ + : "%rI" ((unsigned long int)(u)), \ + "r" ((unsigned long int)(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! */ +#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__ */ +#endif /* __sparc__ */ + +#if defined (__vax__) +#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))) +#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))) +#define umul_ppmm(xh, xl, m0, m1) \ + do { \ + union {long long int __ll; \ + struct {unsigned long int __l, __h;} __i; \ + } __xx; \ + unsigned long int __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)); \ + } while (0) +#define sdiv_qrnnd(q, r, n1, n0, d) \ + do { \ + union {long long int __ll; \ + struct {unsigned long int __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)); \ + } while (0) +#endif /* __vax__ */ + +#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; \ + } +#endif + +#if !defined (__umulsidi3) +#define __umulsidi3(u, v) \ + ({long __hi, __lo; \ + umul_ppmm (__hi, __lo, u, v); \ + ((unsigned long long) __hi << LONG_TYPE_SIZE) | __lo; }) +#endif + +/* If this machine has no inline assembler, use C macros. */ + +#if !defined (add_ssaaaa) +#define add_ssaaaa(sh, sl, ah, al, bh, bl) \ + do { \ + unsigned long int __x; \ + __x = (al) + (bl); \ + (sh) = (ah) + (bh) + (__x < (al)); \ + (sl) = __x; \ + } while (0) +#endif + +#if !defined (sub_ddmmss) +#define sub_ddmmss(sh, sl, ah, al, bh, bl) \ + do { \ + unsigned long int __x; \ + __x = (al) - (bl); \ + (sh) = (ah) - (bh) - (__x > (al)); \ + (sl) = __x; \ + } while (0) +#endif + +#if !defined (umul_ppmm) +#define umul_ppmm(w1, w0, u, v) \ + do { \ + unsigned long int __x0, __x1, __x2, __x3; \ + unsigned int __ul, __vl, __uh, __vh; \ + \ + __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; \ + \ + __x1 += __ll_highpart (__x0);/* this can't give carry */ \ + __x1 += __x2; /* but this indeed can */ \ + if (__x1 < __x2) /* did we get it? */ \ + __x3 += __ll_B; /* yes, add it in the proper pos. */ \ + \ + (w1) = __x3 + __ll_highpart (__x1); \ + (w0) = __ll_lowpart (__x1) * __ll_B + __ll_lowpart (__x0); \ + } 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; \ + __d1 = __ll_highpart (d); \ + __d0 = __ll_lowpart (d); \ + \ + __r1 = (n1) % __d1; \ + __q1 = (n1) / __d1; \ + __m = (unsigned long int) __q1 * __d0; \ + __r1 = __r1 * __ll_B | __ll_highpart (n0); \ + if (__r1 < __m) \ + { \ + __q1--, __r1 += (d); \ + if (__r1 >= (d)) /* i.e. we didn't get carry when adding to __r1 */\ + if (__r1 < __m) \ + __q1--, __r1 += (d); \ + } \ + __r1 -= __m; \ + \ + __r0 = __r1 % __d1; \ + __q0 = __r1 / __d1; \ + __m = (unsigned long int) __q0 * __d0; \ + __r0 = __r0 * __ll_B | __ll_lowpart (n0); \ + if (__r0 < __m) \ + { \ + __q0--, __r0 += (d); \ + if (__r0 >= (d)) \ + if (__r0 < __m) \ + __q0--, __r0 += (d); \ + } \ + __r0 -= __m; \ + \ + (q) = (unsigned long int) __q1 * __ll_B | __q0; \ + (r) = __r0; \ + } while (0) + +/* If udiv_qrnnd was not defined for this processor, use __udiv_qrnnd_c. */ +#if !defined (udiv_qrnnd) +#define UDIV_NEEDS_NORMALIZATION 1 +#define udiv_qrnnd __udiv_qrnnd_c +#endif + +#if !defined (count_leading_zeros) +extern +#ifdef __STDC__ +const +#endif +unsigned char __clz_tab[]; +#define count_leading_zeros(count, x) \ + do { \ + unsigned long int __xr = (x); \ + unsigned int __a; \ + \ + if (LONG_TYPE_SIZE <= 32) \ + { \ + __a = __xr < (1<<2*__BITS4) \ + ? (__xr < (1<<__BITS4) ? 0 : __BITS4) \ + : (__xr < (1<<3*__BITS4) ? 2*__BITS4 : 3*__BITS4); \ + } \ + else \ + { \ + for (__a = LONG_TYPE_SIZE - 8; __a > 0; __a -= 8) \ + if (((__xr >> __a) & 0xff) != 0) \ + break; \ + } \ + \ + (count) = LONG_TYPE_SIZE - (__clz_tab[__xr >> __a] + __a); \ + } while (0) +#endif + +#ifndef UDIV_NEEDS_NORMALIZATION +#define UDIV_NEEDS_NORMALIZATION 0 +#endif diff --git a/gnu/lib/libgmp/mdiv.c b/gnu/lib/libgmp/mdiv.c new file mode 100644 index 0000000..950aa50 --- /dev/null +++ b/gnu/lib/libgmp/mdiv.c @@ -0,0 +1,38 @@ +/* mdiv -- BSD compatible divide producing both remainder and quotient. + +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 "mp.h" +#include "gmp.h" +#include "gmp-impl.h" +#include "longlong.h" + +void +#ifdef __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 "mpz_dmincl.c" diff --git a/gnu/lib/libgmp/memory.c b/gnu/lib/libgmp/memory.c new file mode 100644 index 0000000..cdbe52e --- /dev/null +++ b/gnu/lib/libgmp/memory.c @@ -0,0 +1,96 @@ +/* Memory allocation routines. + +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 + +#include "gmp.h" +#include "gmp-impl.h" + +#ifdef __NeXT__ +#define static +#endif + +#ifdef __STDC__ +void * (*_mp_allocate_func) (size_t) = _mp_default_allocate; +void * (*_mp_reallocate_func) (void *, size_t, size_t) + = _mp_default_reallocate; +void (*_mp_free_func) (void *, size_t) = _mp_default_free; +#else +void * (*_mp_allocate_func) () = _mp_default_allocate; +void * (*_mp_reallocate_func) () = _mp_default_reallocate; +void (*_mp_free_func) () = _mp_default_free; +#endif + +/* Default allocation functions. In case of failure to allocate/reallocate + an error message is written to stderr and the program aborts. */ + +void * +#ifdef __STDC__ +_mp_default_allocate (size_t size) +#else +_mp_default_allocate (size) + size_t size; +#endif +{ + void *ret; + + ret = malloc (size); + if (ret == 0) + { + perror ("cannot allocate in libmp"); + abort (); + } + + return ret; +} + +void * +#ifdef __STDC__ +_mp_default_reallocate (void *oldptr, size_t old_size, size_t new_size) +#else +_mp_default_reallocate (oldptr, old_size, new_size) + void *oldptr; + size_t old_size; + size_t new_size; +#endif +{ + void *ret; + + ret = realloc (oldptr, new_size); + if (ret == 0) + { + perror ("cannot allocate in libmp"); + abort (); + } + + return ret; +} + +void +#ifdef __STDC__ +_mp_default_free (void *blk_ptr, size_t blk_size) +#else +_mp_default_free (blk_ptr, blk_size) + void *blk_ptr; + size_t blk_size; +#endif +{ + free (blk_ptr); +} diff --git a/gnu/lib/libgmp/mfree.c b/gnu/lib/libgmp/mfree.c new file mode 100644 index 0000000..de4bee5 --- /dev/null +++ b/gnu/lib/libgmp/mfree.c @@ -0,0 +1,35 @@ +/* mfree -- BSD compatible mfree. + +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 "mp.h" +#include "gmp.h" +#include "gmp-impl.h" + +void +#ifdef __STDC__ +mfree (MINT *m) +#else +mfree (m) + MINT *m; +#endif +{ + (*_mp_free_func) (m->d, m->alloc * BYTES_PER_MP_LIMB); + (*_mp_free_func) (m, sizeof (MINT)); +} diff --git a/gnu/lib/libgmp/min.c b/gnu/lib/libgmp/min.c new file mode 100644 index 0000000..2bc7d6d --- /dev/null +++ b/gnu/lib/libgmp/min.c @@ -0,0 +1,64 @@ +/* min(MINT) -- Do decimal input from standard input and store result in + MINT. + +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 +#include +#include "mp.h" +#include "gmp.h" +#include "gmp-impl.h" + +void +#ifdef __STDC__ +min (MINT *x) +#else +min (x) + MINT *x; +#endif +{ + char *str; + size_t str_size; + size_t i; + int c; + + str_size = 100; + str = (char *) (*_mp_allocate_func) (str_size); + + for (i = 0; ; i++) + { + if (i >= str_size) + { + size_t old_str_size = str_size; + str_size = str_size * 3 / 2; + str = (char *) (*_mp_reallocate_func) (str, old_str_size, str_size); + } + c = getc (stdin); + if (!(isdigit(c) || c == ' ' || c == '\t')) + break; + str[i] = c; + } + + ungetc (c, stdin); + + str[i] = 0; + _mpz_set_str (x, str, 10); + + (*_mp_free_func) (str, str_size); +} diff --git a/gnu/lib/libgmp/mout.c b/gnu/lib/libgmp/mout.c new file mode 100644 index 0000000..7aeaa16 --- /dev/null +++ b/gnu/lib/libgmp/mout.c @@ -0,0 +1,42 @@ +/* mout(MINT) -- Do decimal output of MINT to standard output. + +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 "mp.h" +#include "gmp.h" +#include "gmp-impl.h" + +void +#ifdef __STDC__ +mout (const MINT *x) +#else +mout (x) + const MINT *x; +#endif +{ + char *str; + size_t str_size; + + str_size = ((size_t) (ABS (x->size) * BITS_PER_MP_LIMB + * __mp_bases[10].chars_per_bit_exactly)) + 3; + str = (char *) alloca (str_size); + _mpz_get_str (str, 10, x); + puts (str); + alloca (0); +} diff --git a/gnu/lib/libgmp/move.c b/gnu/lib/libgmp/move.c new file mode 100644 index 0000000..82b9cc3 --- /dev/null +++ b/gnu/lib/libgmp/move.c @@ -0,0 +1,45 @@ +/* move -- BSD compatible assignment. + +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 "mp.h" +#include "gmp.h" +#include "gmp-impl.h" + +void +#ifdef __STDC__ +move (const MINT *u, MINT *w) +#else +move (u, w) + const MINT *u; + MINT *w; +#endif +{ + mp_size usize; + mp_size abs_usize; + + usize = u->size; + abs_usize = ABS (usize); + + if (w->alloc < abs_usize) + _mpz_realloc (w, abs_usize); + + w->size = usize; + MPN_COPY (w->d, u->d, abs_usize); +} diff --git a/gnu/lib/libgmp/mp.h b/gnu/lib/libgmp/mp.h new file mode 100644 index 0000000..8836e0c --- /dev/null +++ b/gnu/lib/libgmp/mp.h @@ -0,0 +1,103 @@ +/* mp.h -- Definitions for Berkeley compatible multiple precision functions. + +Copyright (C) 1991, 1993 Free Software Foundation, Inc. + +This file is part of the 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. */ + +#ifndef __MP_H__ +#define __MP_H__ + +#define __GNU_MP__ + +#ifndef __GMP_H__ +#define __need_size_t +#include +#endif + +#ifndef MP_INT +#ifndef __MP_SMALL__ +typedef struct +{ + long int alloc; /* Number of *limbs* allocated and pointed + to by the D field. */ + long int 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; +#else +typedef struct +{ + short int alloc; /* Number of *limbs* allocated and pointed + to by the D field. */ + short int 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 +#endif + +#define MINT __MP_INT + +#ifdef __STDC__ +void mp_set_memory_functions (void *(*) (size_t), + void *(*) (void *, size_t, size_t), + void (*) (void *, size_t)); +MINT *itom (signed short int); +MINT *xtom (const char *); +void move (const MINT *, MINT *); +void madd (const MINT *, const MINT *, MINT *); +void msub (const MINT *, const MINT *, MINT *); +void mult (const MINT *, const MINT *, MINT *); +void mdiv (const MINT *, const MINT *, MINT *, MINT *); +void sdiv (const MINT *, signed short int, MINT *, signed short int *); +void msqrt (const MINT *, MINT *, MINT *); +void pow (const MINT *, const MINT *, const MINT *, MINT *); +void rpow (const MINT *, signed short int, MINT *); +void gcd (const MINT *, const MINT *, MINT *); +int mcmp (const MINT *, const MINT *); +void min (MINT *); +void mout (const MINT *); +char *mtox (const MINT *); +void mfree (MINT *); + +#else + +void mp_set_memory_functions (); +MINT *itom (); +MINT *xtom (); +void move (); +void madd (); +void msub (); +void mult (); +void mdiv (); +void sdiv (); +void msqrt (); +void pow (); +void rpow (); +void gcd (); +int mcmp (); +void min (); +void mout (); +char *mtox (); +void mfree (); +#endif + +#endif /* __MP_H__ */ diff --git a/gnu/lib/libgmp/mp_clz_tab.c b/gnu/lib/libgmp/mp_clz_tab.c new file mode 100644 index 0000000..c27b969 --- /dev/null +++ b/gnu/lib/libgmp/mp_clz_tab.c @@ -0,0 +1,36 @@ +/* __clz_tab -- support for longlong.h + +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" +#include "gmp-impl.h" + +/* BOTCH: This ought to be made machine-independent. */ + +const unsigned char __clz_tab[] = +{ + 0,1,2,2,3,3,3,3,4,4,4,4,4,4,4,4,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6, + 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7, + 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7, + 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, + 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, + 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, + 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, +}; diff --git a/gnu/lib/libgmp/mp_set_fns.c b/gnu/lib/libgmp/mp_set_fns.c new file mode 100644 index 0000000..04bb37a --- /dev/null +++ b/gnu/lib/libgmp/mp_set_fns.c @@ -0,0 +1,47 @@ +/* mp_set_memory_functions -- Set the allocate, reallocate, and free functions + for use by the mp package. + +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" +#include "gmp-impl.h" + +void +#ifdef __STDC__ +mp_set_memory_functions (void *(*alloc_func) (size_t), + void *(*realloc_func) (void *, size_t, size_t), + void (*free_func) (void *, size_t)) +#else +mp_set_memory_functions (alloc_func, realloc_func, free_func) + void *(*alloc_func) (); + void *(*realloc_func) (); + void (*free_func) (); +#endif +{ + if (alloc_func == 0) + alloc_func = _mp_default_allocate; + if (realloc_func == 0) + realloc_func = _mp_default_reallocate; + if (free_func == 0) + free_func = _mp_default_free; + + _mp_allocate_func = alloc_func; + _mp_reallocate_func = realloc_func; + _mp_free_func = free_func; +} diff --git a/gnu/lib/libgmp/mpn_add.c b/gnu/lib/libgmp/mpn_add.c new file mode 100644 index 0000000..10502a8 --- /dev/null +++ b/gnu/lib/libgmp/mpn_add.c @@ -0,0 +1,141 @@ +/* mpn_add -- Add two low-level integers. + +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" +#include "gmp-impl.h" + +/* Add ADD1_PTR/ADD1_SIZE and ADD2_PTR/ADD2_SIZE and store the first + ADD1_SIZE words of the result at SUM_PTR. + + Return 1 if carry out was generated, return 0 otherwise. + + Argument constraint: ADD1_SIZE >= ADD2_SIZE. + + The size of SUM can be calculated as ADD1_SIZE + the return value. */ + +mp_limb +#ifdef __STDC__ +mpn_add (mp_ptr sum_ptr, + mp_srcptr add1_ptr, mp_size add1_size, + mp_srcptr add2_ptr, mp_size add2_size) +#else +mpn_add (sum_ptr, add1_ptr, add1_size, add2_ptr, add2_size) + mp_ptr sum_ptr; + mp_srcptr add1_ptr; + mp_size add1_size; + mp_srcptr add2_ptr; + mp_size add2_size; +#endif +{ + mp_limb a1, a2, sum; + mp_size j; + + /* The loop counter and index J goes from some negative value to zero. + This way the loops become faster. Need to offset the base pointers + to take care of the negative indices. */ + + j = -add2_size; + if (j == 0) + goto add2_finished; + + add1_ptr -= j; + add2_ptr -= j; + sum_ptr -= j; + + /* There are two do-loops, marked NON-CARRY LOOP and CARRY LOOP that + jump between each other. The first loop is for when the previous + addition didn't produce a carry-out; the second is for the + complementary case. */ + + /* NON-CARRY LOOP */ + do + { + a1 = add1_ptr[j]; + a2 = add2_ptr[j]; + sum = a1 + a2; + sum_ptr[j] = sum; + if (sum < a2) + goto cy_loop; + ncy_loop: + j++; + } + while (j < 0); + + /* We have exhausted ADD2. Just copy ADD1 to SUM, and return + 0 as an indication of no carry-out. */ + + add2_finished: + /* Immediate return if the copy would be a no-op. */ + if (sum_ptr == add1_ptr) + return 0; + + j = add2_size - add1_size; + add1_ptr -= j; + sum_ptr -= j; + + while (j < 0) + { + sum_ptr[j] = add1_ptr[j]; + j++; + } + return 0; + + /* CARRY LOOP */ + do + { + a1 = add1_ptr[j]; + a2 = add2_ptr[j]; + sum = a1 + a2 + 1; + sum_ptr[j] = sum; + if (sum > a2) + goto ncy_loop; + cy_loop: + j++; + } + while (j < 0); + + j = add2_size - add1_size; + add1_ptr -= j; + sum_ptr -= j; + + while (j < 0) + { + a1 = add1_ptr[j]; + sum = a1 + 1; + sum_ptr[j] = sum; + if (sum > 0) + goto copy_add1; + j++; + } + return 1; + + copy_add1: + if (sum_ptr == add1_ptr) + return 0; + + j++; + while (j < 0) + { + sum_ptr[j] = add1_ptr[j]; + j++; + } + + return 0; +} diff --git a/gnu/lib/libgmp/mpn_cmp.c b/gnu/lib/libgmp/mpn_cmp.c new file mode 100644 index 0000000..11f39ca --- /dev/null +++ b/gnu/lib/libgmp/mpn_cmp.c @@ -0,0 +1,52 @@ +/* mpn_cmp -- Compare two low-level natural-number integers. + +Copyright (C) 1991, 1992 Free Software Foundation, Inc. + +This file is part of the 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" +#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 +#ifdef __STDC__ +mpn_cmp (mp_srcptr op1_ptr, mp_srcptr op2_ptr, mp_size size) +#else +mpn_cmp (op1_ptr, op2_ptr, size) + mp_srcptr op1_ptr; + mp_srcptr op2_ptr; + mp_size size; +#endif +{ + mp_size i; + mp_limb 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: + return (op1_word > op2_word) ? 1 : -1; +} diff --git a/gnu/lib/libgmp/mpn_div.c b/gnu/lib/libgmp/mpn_div.c new file mode 100644 index 0000000..8609206 --- /dev/null +++ b/gnu/lib/libgmp/mpn_div.c @@ -0,0 +1,321 @@ +/* mpn_div -- Divide natural numbers, producing both remainder and + quotient. + +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" +#include "gmp-impl.h" +#include "longlong.h" + +/* Divide num (NUM_PTR/NUM_SIZE) by den (DEN_PTR/DEN_SIZE) and write + the quotient at QUOT_PTR and the remainder at NUM_PTR. + + Return 0 or 1, depending on if the quotient size is (NSIZE - DSIZE) + or (NSIZE - DSIZE + 1). + + Argument constraints: + 1. The most significant bit of d must be set. + 2. QUOT_PTR != DEN_PTR and QUOT_PTR != NUM_PTR, i.e. the quotient storage + area must be distinct from either input operands. + + The exact sizes of the quotient and remainder must be determined + by the caller, in spite of the return value. The return value just + informs the caller about if the highest digit is written or not, and + it may very well be 0. */ + +/* THIS WILL BE IMPROVED SOON. MORE COMMENTS AND FASTER CODE. */ + +mp_size +#ifdef __STDC__ +mpn_div (mp_ptr quot_ptr, + mp_ptr num_ptr, mp_size num_size, + mp_srcptr den_ptr, mp_size den_size) +#else +mpn_div (quot_ptr, num_ptr, num_size, den_ptr, den_size) + mp_ptr quot_ptr; + mp_ptr num_ptr; + mp_size num_size; + mp_srcptr den_ptr; + mp_size den_size; +#endif +{ + mp_size q_is_long = 0; + + switch (den_size) + { + case 0: + /* We are asked to divide by zero, so go ahead and do it! + (To make the compiler not remove this statement, assign NUM_SIZE + and fall through.) */ + num_size = 1 / den_size; + + case 1: + { + mp_size i; + mp_limb n1, n0; + mp_limb d; + + d = den_ptr[0]; + i = num_size - 1; + n1 = num_ptr[i]; + i--; + + if (n1 >= d) + { + q_is_long = 1; + n1 = 0; + i++; + } + + for (; i >= 0; i--) + { + n0 = num_ptr[i]; + udiv_qrnnd (quot_ptr[i], n1, n1, n0, d); + } + + num_ptr[0] = n1; + } + break; + + case 2: + { + mp_size i; + mp_limb n0, n1, n2; + mp_limb d0, d1; + + num_ptr += num_size - 2; + d0 = den_ptr[1]; + d1 = den_ptr[0]; + n0 = num_ptr[1]; + n1 = num_ptr[0]; + + if (n0 >= d0) + { + q_is_long = 1; + n1 = n0; + n0 = 0; + num_ptr++; + num_size++; + } + + for (i = num_size - den_size - 1; i >= 0; i--) + { + mp_limb q; + mp_limb r; + + num_ptr--; + if (n0 == d0) + { + /* Q should be either 111..111 or 111..110. Need special + treatment of this rare case as normal division would + give overflow. */ + q = ~0; + + r = n1 + d0; + if (r < d0) /* Carry in the addition? */ + { + n2 = num_ptr[0]; + + add_ssaaaa (n0, n1, r - d1, n2, 0, d1); + quot_ptr[i] = q; + continue; + } + n0 = d1 - (d1 != 0); + n1 = -d1; + } + else + { + udiv_qrnnd (q, r, n0, n1, d0); + umul_ppmm (n0, n1, d1, q); + } + + n2 = num_ptr[0]; + q_test: + if (n0 > r || (n0 == r && n1 > n2)) + { + /* The estimated Q was too large. */ + q--; + + sub_ddmmss (n0, n1, n0, n1, 0, d1); + r += d0; + if (r >= d0) /* If not carry, test q again. */ + goto q_test; + } + + quot_ptr[i] = q; + sub_ddmmss (n0, n1, r, n2, n0, n1); + } + num_ptr[1] = n0; + num_ptr[0] = n1; + } + break; + + default: + { + mp_size i; + mp_limb d0 = den_ptr[den_size - 1]; + mp_limb d1 = den_ptr[den_size - 2]; + mp_limb n0 = num_ptr[num_size - 1]; + int ugly_hack_flag = 0; + + if (n0 >= d0) + { + + /* There's a problem with this case, which shows up later in the + code. q becomes 1 (and sometimes 0) the first time when + we've been here, and w_cy == 0 after the main do-loops below. + But c = num_ptr[j] reads rubbish outside the num_ptr vector! + Maybe I can solve this cleanly when I fix the early-end + optimization here in the default case. For now, I change the + add_back entering condition, to kludge. Leaving the stray + memref behind! + + HACK: Added ugly_hack_flag to make it work. */ + + q_is_long = 1; + n0 = 0; + num_size++; + ugly_hack_flag = 1; + } + + num_ptr += num_size; + den_ptr += den_size; + for (i = num_size - den_size - 1; i >= 0; i--) + { + mp_limb q; + mp_limb n1; + mp_limb w_cy; + mp_limb d, c; + mp_size j; + + num_ptr--; + if (n0 == d0) + /* This might over-estimate q, but it's probably not worth + the extra code here to find out. */ + q = ~0; + else + { + mp_limb r; + + udiv_qrnnd (q, r, n0, num_ptr[-1], d0); + umul_ppmm (n1, n0, d1, q); + + while (n1 > r || (n1 == r && n0 > num_ptr[-2])) + { + q--; + r += d0; + if (r < d0) /* I.e. "carry in previous addition?" */ + break; + n1 -= n0 < d1; + n0 -= d1; + } + } + + w_cy = 0; + j = -den_size; + do + { + d = den_ptr[j]; + c = num_ptr[j]; + umul_ppmm (n1, n0, d, q); + n0 += w_cy; + w_cy = (n0 < w_cy) + n1; + n0 = c - n0; + num_ptr[j] = n0; + if (n0 > c) + goto cy_loop; + ncy_loop: + j++; + } + while (j < 0); + + if (ugly_hack_flag) + { + c = 0; + ugly_hack_flag = 0; + } + else + c = num_ptr[j]; + if (c >= w_cy) + goto store_q; + goto add_back; + + do + { + d = den_ptr[j]; + c = num_ptr[j]; + umul_ppmm (n1, n0, d, q); + n0 += w_cy; + w_cy = (n0 < w_cy) + n1; + n0 = c - n0 - 1; + num_ptr[j] = n0; + if (n0 < c) + goto ncy_loop; + cy_loop: + j++; + } + while (j < 0); + + if (ugly_hack_flag) + { + c = 0; + ugly_hack_flag = 0; + } + else + c = num_ptr[j]; + w_cy++; + if (c >= w_cy) + goto store_q; + + add_back: + j = -den_size; + do + { + d = den_ptr[j]; + n0 = num_ptr[j] + d; + num_ptr[j] = n0; + if (n0 < d) + goto ab_cy_loop; + ab_ncy_loop: + j++; + } + while (j < 0); + abort (); /* We should always have a carry out! */ + + do + { + d = den_ptr[j]; + n0 = num_ptr[j] + d + 1; + num_ptr[j] = n0; + if (n0 > d) + goto ab_ncy_loop; + ab_cy_loop: + j++; + } + while (j < 0); + q--; + + store_q: + quot_ptr[i] = q; + } + } + } + + return q_is_long; +} diff --git a/gnu/lib/libgmp/mpn_dm_1.c b/gnu/lib/libgmp/mpn_dm_1.c new file mode 100644 index 0000000..af39124 --- /dev/null +++ b/gnu/lib/libgmp/mpn_dm_1.c @@ -0,0 +1,185 @@ +/* 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 Free Software Foundation, Inc. + +This file is part of the 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" +#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 UDIV_TIME > 2 * UMUL_TIME +#undef UDIV_NEEDS_NORMALIZATION +#define UDIV_NEEDS_NORMALIZATION 1 +#endif + +#define udiv_qrnnd_preinv(q, r, nh, nl, d, di) \ + do { \ + unsigned long int _q, _ql, _r; \ + unsigned long int _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) + +mp_limb +#ifdef __STDC__ +mpn_divmod_1 (mp_ptr quot_ptr, + mp_srcptr dividend_ptr, mp_size dividend_size, + unsigned long int divisor_limb) +#else +mpn_divmod_1 (quot_ptr, dividend_ptr, dividend_size, divisor_limb) + mp_ptr quot_ptr; + mp_srcptr dividend_ptr; + mp_size dividend_size; + unsigned long int divisor_limb; +#endif +{ + mp_size i; + mp_limb n1, n0, r; + + /* Botch: Should this be handled at all? Rely on callers? */ + if (dividend_size == 0) + return 0; + + 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... + [Don't forget to zero most sign. quotient limb!] */ + + /* If multiplication is much faster than division, and the + dividend is large, pre-invert the divisor, and use + only multiplications in the inner loop. */ + if (UDIV_TIME > 2 * UMUL_TIME && dividend_size >= 4) + { + mp_limb divisor_limb_inverted; + int dummy; + /* Compute (2**64 - 2**32 * DIVISOR_LIMB) / DIVISOR_LIMB. + The result is an 33-bit approximation to 1/DIVISOR_LIMB, + with the most significant bit (weight 2**32) implicit. */ + + /* Special case for DIVISOR_LIMB == 100...000. */ + if (divisor_limb << 1 == 0) + divisor_limb_inverted = ~0; + else + udiv_qrnnd (divisor_limb_inverted, dummy, + -divisor_limb, 0, divisor_limb); + + 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 + { + 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 + { + /* Callers expect the quotient to be DIVIDEND_SIZE limbs. Store + a leading zero to make that expectation come true. */ + 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_lshift.c b/gnu/lib/libgmp/mpn_lshift.c new file mode 100644 index 0000000..b89a736 --- /dev/null +++ b/gnu/lib/libgmp/mpn_lshift.c @@ -0,0 +1,83 @@ +/* mpn_lshift -- Shift left low level. + +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" +#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: + 0. U must be normalized (i.e. it's most significant digit != 0). + 1. 0 <= CNT < BITS_PER_MP_LIMB + 2. If the result is to be written over the input, WP must be >= UP. +*/ + +mp_limb +#ifdef __STDC__ +mpn_lshift (mp_ptr wp, + mp_srcptr up, mp_size usize, + unsigned cnt) +#else +mpn_lshift (wp, up, usize, cnt) + mp_ptr wp; + mp_srcptr up; + mp_size usize; + unsigned cnt; +#endif +{ + mp_limb high_limb, low_limb; + unsigned sh_1, sh_2; + mp_size i; + mp_limb retval; + + if (usize == 0) + return 0; + + sh_1 = cnt; + 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; + } + + 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_mod_1.c b/gnu/lib/libgmp/mpn_mod_1.c new file mode 100644 index 0000000..19fcefd --- /dev/null +++ b/gnu/lib/libgmp/mpn_mod_1.c @@ -0,0 +1,104 @@ +/* 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. + + QUOT_PTR and DIVIDEND_PTR might point to the same limb. + +Copyright (C) 1991, 1992 Free Software Foundation, Inc. + +This file is part of the 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" +#include "gmp-impl.h" +#include "longlong.h" + +mp_limb +#ifdef __STDC__ +mpn_mod_1 (mp_srcptr dividend_ptr, mp_size dividend_size, + unsigned long int divisor_limb) +#else +mpn_mod_1 (dividend_ptr, dividend_size, divisor_limb) + mp_srcptr dividend_ptr; + mp_size dividend_size; + unsigned long int divisor_limb; +#endif +{ + int normalization_steps; + mp_size i; + mp_limb n1, n0, r; + int dummy; + + /* Botch: Should this be handled at all? Rely on callers? */ + if (dividend_size == 0) + return 0; + + if (UDIV_NEEDS_NORMALIZATION) + { + 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_mul.c b/gnu/lib/libgmp/mpn_mul.c new file mode 100644 index 0000000..8455f1d --- /dev/null +++ b/gnu/lib/libgmp/mpn_mul.c @@ -0,0 +1,414 @@ +/* mpn_mul -- Multiply two natural numbers. + +Copyright (C) 1991, 1992 Free Software Foundation, Inc. + +This file is part of the 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" +#include "gmp-impl.h" +#include "longlong.h" + +#ifdef DEBUG +#define MPN_MUL_VERIFY(res_ptr,res_size,op1_ptr,op1_size,op2_ptr,op2_size) \ + mpn_mul_verify (res_ptr, res_size, op1_ptr, op1_size, op2_ptr, op2_size) + +#include +static void +mpn_mul_verify (res_ptr, res_size, op1_ptr, op1_size, op2_ptr, op2_size) + mp_ptr res_ptr, op1_ptr, op2_ptr; + mp_size res_size, op1_size, op2_size; +{ + mp_ptr tmp_ptr; + mp_size tmp_size; + tmp_ptr = alloca ((op1_size + op2_size) * BYTES_PER_MP_LIMB); + if (op1_size >= op2_size) + tmp_size = mpn_mul_classic (tmp_ptr, + op1_ptr, op1_size, op2_ptr, op2_size); + else + tmp_size = mpn_mul_classic (tmp_ptr, + op2_ptr, op2_size, op1_ptr, op1_size); + if (tmp_size != res_size + || mpn_cmp (tmp_ptr, res_ptr, tmp_size) != 0) + { + fprintf (stderr, "GNU MP internal error: Wrong result in mpn_mul.\n"); + fprintf (stderr, "op1{%d} = ", op1_size); mpn_dump (op1_ptr, op1_size); + fprintf (stderr, "op2{%d} = ", op2_size); mpn_dump (op2_ptr, op2_size); + abort (); + } +} +#else +#define MPN_MUL_VERIFY(a,b,c,d,e,f) +#endif + +/* 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, the return value will reflect the true + result size (which is either USIZE + VSIZE, or USIZE + VSIZE -1). + + 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 8 +#endif + +/* The code can't handle KARATSUBA_THRESHOLD smaller than 4. */ +#if KARATSUBA_THRESHOLD < 4 +#undef KARATSUBA_THRESHOLD +#define KARATSUBA_THRESHOLD 4 +#endif + +mp_size +#ifdef __STDC__ +mpn_mul (mp_ptr prodp, + mp_srcptr up, mp_size usize, + mp_srcptr vp, mp_size vsize) +#else +mpn_mul (prodp, up, usize, vp, vsize) + mp_ptr prodp; + mp_srcptr up; + mp_size usize; + mp_srcptr vp; + mp_size vsize; +#endif +{ + mp_size n; + mp_size prod_size; + mp_limb cy; + + 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 the recursive algorithm below. */ + mp_size i, j; + mp_limb prod_low, prod_high; + mp_limb cy_limb; + mp_limb v_limb; + + 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]; + if (v_limb <= 1) + { + if (v_limb == 1) + MPN_COPY (prodp - usize, up - usize, usize); + else + MPN_ZERO (prodp - usize, usize); + cy_limb = 0; + } + else + { + cy_limb = 0; + j = -usize; + do + { + umul_ppmm (prod_high, prod_low, up[j], v_limb); + add_ssaaaa (cy_limb, prodp[j], prod_high, prod_low, 0, cy_limb); + j++; + } + while (j < 0); + } + + prodp[0] = 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 (prodp - usize, + prodp - usize, usize, up - usize, usize); + } + else + { + cy_limb = 0; + j = -usize; + + do + { + umul_ppmm (prod_high, prod_low, up[j], v_limb); + add_ssaaaa (cy_limb, prod_low, + prod_high, prod_low, 0, cy_limb); + add_ssaaaa (cy_limb, prodp[j], + cy_limb, prod_low, 0, prodp[j]); + j++; + } + while (j < 0); + } + + prodp[0] = cy_limb; + prodp++; + } + + return usize + vsize - (cy_limb == 0); + } + + n = (usize + 1) / 2; + + /* Is USIZE larger than 1.5 times VSIZE? Avoid Karatsuba's algorithm. */ + if (2 * usize > 3 * vsize) + { + /* If U has at least twice as many limbs as V. Split U in two + pieces, U1 and U0, such that U = U0 + U1*(2**BITS_PER_MP_LIMB)**N, + and recursively multiply the two pieces separately with V. */ + + mp_size u0_size; + mp_ptr tmp; + mp_size tmp_size; + + /* V1 (the high part of V) is zero. */ + + /* Calculate the length of U0. It is normally equal to n, but + of course not for sure. */ + for (u0_size = n; u0_size > 0 && up[u0_size - 1] == 0; u0_size--) + ; + + /* Perform (U0 * V). */ + if (u0_size >= vsize) + prod_size = mpn_mul (prodp, up, u0_size, vp, vsize); + else + prod_size = mpn_mul (prodp, vp, vsize, up, u0_size); + MPN_MUL_VERIFY (prodp, prod_size, up, u0_size, vp, vsize); + + /* We have to zero-extend the lower partial product to n limbs, + since the mpn_add some lines below expect the first n limbs + to be well defined. (This is normally a no-op. It may + do something when U1 has many leading 0 limbs.) */ + while (prod_size < n) + prodp[prod_size++] = 0; + + tmp = (mp_ptr) alloca ((usize + vsize - n) * BYTES_PER_MP_LIMB); + + /* Perform (U1 * V). Make sure the first source argument to mpn_mul + is not less than the second source argument. */ + if (vsize <= usize - n) + tmp_size = mpn_mul (tmp, up + n, usize - n, vp, vsize); + else + tmp_size = mpn_mul (tmp, vp, vsize, up + n, usize - n); + MPN_MUL_VERIFY (tmp, tmp_size, up + n, usize - n, vp, vsize); + + /* In this addition hides a potentially large copying of TMP. */ + if (prod_size - n >= tmp_size) + cy = mpn_add (prodp + n, prodp + n, prod_size - n, tmp, tmp_size); + else + cy = mpn_add (prodp + n, tmp, tmp_size, prodp + n, prod_size - n); + if (cy) + abort (); /* prodp[prod_size] = cy; */ + + alloca (0); + return tmp_size + n; + } + else + { + /* 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. + */ + + /* It's possible to decrease the temporary allocation by using the + prodp area for temporary storage of the middle term, and doing + that recursive multiplication first. (Do this later.) */ + + mp_size u0_size; + mp_size v0_size; + mp_size u0v0_size; + mp_size u1v1_size; + mp_ptr temp; + mp_size temp_size; + mp_size utem_size; + mp_size vtem_size; + mp_ptr ptem; + mp_size ptem_size; + int negflg; + mp_ptr pp; + + pp = (mp_ptr) alloca (4 * n * BYTES_PER_MP_LIMB); + + /* Calculate the lengths of U0 and V0. They are normally equal + to n, but of course not for sure. */ + for (u0_size = n; u0_size > 0 && up[u0_size - 1] == 0; u0_size--) + ; + for (v0_size = n; v0_size > 0 && vp[v0_size - 1] == 0; v0_size--) + ; + + /*** 1. PROD]2n..0] := U0 x V0 + (Recursive call to mpn_mul may NOT overwrite input operands.) + ________________ ________________ + |________________||____U0 x V0_____| */ + + if (u0_size >= v0_size) + u0v0_size = mpn_mul (pp, up, u0_size, vp, v0_size); + else + u0v0_size = mpn_mul (pp, vp, v0_size, up, u0_size); + MPN_MUL_VERIFY (pp, u0v0_size, up, u0_size, vp, v0_size); + + /* Zero-extend to 2n limbs. */ + while (u0v0_size < 2 * n) + pp[u0v0_size++] = 0; + + + /*** 2. PROD]4n..2n] := U1 x V1 + (Recursive call to mpn_mul may NOT overwrite input operands.) + ________________ ________________ + |_____U1 x V1____||____U0 x V0_____| */ + + u1v1_size = mpn_mul (pp + 2*n, + up + n, usize - n, + vp + n, vsize - n); + MPN_MUL_VERIFY (pp + 2*n, u1v1_size, + up + n, usize - n, vp + n, vsize - n); + prod_size = 2 * n + u1v1_size; + + + /*** 3. PTEM]2n..0] := (U1-U0) x (V0-V1) + (Recursive call to mpn_mul may overwrite input operands.) + ________________ + |_(U1-U0)(V0-V1)_| */ + + temp = (mp_ptr) alloca ((2 * n + 1) * BYTES_PER_MP_LIMB); + if (usize - n > u0_size + || (usize - n == u0_size + && mpn_cmp (up + n, up, u0_size) >= 0)) + { + utem_size = usize - n + + mpn_sub (temp, up + n, usize - n, up, u0_size); + negflg = 0; + } + else + { + utem_size = u0_size + + mpn_sub (temp, up, u0_size, up + n, usize - n); + negflg = 1; + } + if (vsize - n > v0_size + || (vsize - n == v0_size + && mpn_cmp (vp + n, vp, v0_size) >= 0)) + { + vtem_size = vsize - n + + mpn_sub (temp + n, vp + n, vsize - n, vp, v0_size); + negflg ^= 1; + } + else + { + vtem_size = v0_size + + mpn_sub (temp + n, vp, v0_size, vp + n, vsize - n); + /* No change of NEGFLG. */ + } + ptem = (mp_ptr) alloca (2 * n * BYTES_PER_MP_LIMB); + if (utem_size >= vtem_size) + ptem_size = mpn_mul (ptem, temp, utem_size, temp + n, vtem_size); + else + ptem_size = mpn_mul (ptem, temp + n, vtem_size, temp, utem_size); + MPN_MUL_VERIFY (ptem, ptem_size, temp, utem_size, temp + n, vtem_size); + + /*** 4. TEMP]2n..0] := PROD]2n..0] + PROD]4n..2n] + ________________ + |_____U1 x V1____| + ________________ + |_____U0_x_V0____| */ + + cy = mpn_add (temp, pp, 2*n, pp + 2*n, u1v1_size); + if (cy != 0) + { + temp[2*n] = cy; + temp_size = 2*n + 1; + } + else + { + /* Normalize temp. pp[2*n-1] might have been zero in the + mpn_add call above, and thus temp might be unnormalized. */ + for (temp_size = 2*n; temp_size > 0 && temp[temp_size - 1] == 0; + temp_size--) + ; + } + + if (prod_size - n >= temp_size) + cy = mpn_add (pp + n, pp + n, prod_size - n, temp, temp_size); + else + { + /* This is a weird special case that should not happen (often)! */ + cy = mpn_add (pp + n, temp, temp_size, pp + n, prod_size - n); + prod_size = temp_size + n; + } + if (cy != 0) + { + pp[prod_size] = cy; + prod_size++; + } +#ifdef DEBUG + if (prod_size > 4 * n) + abort(); +#endif + if (negflg) + prod_size = prod_size + + mpn_sub (pp + n, pp + n, prod_size - n, ptem, ptem_size); + else + { + if (prod_size - n < ptem_size) + abort(); + cy = mpn_add (pp + n, pp + n, prod_size - n, ptem, ptem_size); + if (cy != 0) + { + pp[prod_size] = cy; + prod_size++; +#ifdef DEBUG + if (prod_size > 4 * n) + abort(); +#endif + } + } + + MPN_COPY (prodp, pp, prod_size); + alloca (0); + return prod_size; + } +} diff --git a/gnu/lib/libgmp/mpn_rshift.c b/gnu/lib/libgmp/mpn_rshift.c new file mode 100644 index 0000000..a4d00e8 --- /dev/null +++ b/gnu/lib/libgmp/mpn_rshift.c @@ -0,0 +1,90 @@ +/* mpn_rshift -- Shift right a low-level natural-number integer. + +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" +#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. + Return the size of the result. + + Argument constraints: + 0. U must be normalized (i.e. it's most significant limb != 0). + 1. 0 <= CNT < BITS_PER_MP_LIMB + 2. If the result is to be written over the input, WP must be <= UP. +*/ + +mp_size +#ifdef __STDC__ +mpn_rshift (mp_ptr wp, + mp_srcptr up, mp_size usize, + unsigned cnt) +#else +mpn_rshift (wp, up, usize, cnt) + mp_ptr wp; + mp_srcptr up; + mp_size usize; + unsigned cnt; +#endif +{ + mp_limb high_limb, low_limb; + unsigned sh_1, sh_2; + mp_size i; + + if (usize == 0) + return 0; + + sh_1 = cnt; + 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; + } + + wp -= 1; + sh_2 = BITS_PER_MP_LIMB - sh_1; + high_limb = up[0]; +#if 0 + if (cy_limb != NULL) + *cy_limb = high_limb << sh_2; +#endif + 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; + if (low_limb != 0) + { + wp[i] = low_limb; + return usize; + } + + return usize - 1; +} diff --git a/gnu/lib/libgmp/mpn_rshiftci.c b/gnu/lib/libgmp/mpn_rshiftci.c new file mode 100644 index 0000000..b072d02 --- /dev/null +++ b/gnu/lib/libgmp/mpn_rshiftci.c @@ -0,0 +1,86 @@ +/* mpn_rshiftci -- Shift a low level natural-number integer with carry in. + +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" +#include "gmp-impl.h" + +/* Shift U (pointed to by UP and USIZE digits long) CNT bits to the right + and store the USIZE least significant digits of the result at WP. + Return the size of the result. + + Argument constraints: + 0. U must be normalized (i.e. it's most significant digit != 0). + 1. 0 <= CNT < BITS_PER_MP_LIMB + 2. If the result is to be written over the input, WP must be <= UP. +*/ + +mp_size +#ifdef __STDC__ +mpn_rshiftci (mp_ptr wp, + mp_srcptr up, mp_size usize, + unsigned cnt, + mp_limb carry_in) +#else +mpn_rshiftci (wp, up, usize, cnt, carry_in) + mp_ptr wp; + mp_srcptr up; + mp_size usize; + unsigned cnt; + mp_limb carry_in; +#endif +{ + mp_limb high_limb, low_limb; + unsigned sh_1, sh_2; + mp_size i; + + if (usize <= 0) + return 0; + + sh_1 = cnt; + 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; + } + + wp -= 1; + sh_2 = BITS_PER_MP_LIMB - sh_1; + low_limb = up[0]; + 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 = (low_limb >> sh_1) | (carry_in << sh_2); + if (low_limb != 0) + { + wp[i] = low_limb; + return usize; + } + + return usize - 1; +} diff --git a/gnu/lib/libgmp/mpn_sqrt.c b/gnu/lib/libgmp/mpn_sqrt.c new file mode 100644 index 0000000..7dda9e4 --- /dev/null +++ b/gnu/lib/libgmp/mpn_sqrt.c @@ -0,0 +1,479 @@ +/* mpn_sqrt(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) 1991, 1993 Free Software Foundation, Inc. + +This file is part of the 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. */ + +/* 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__ + +#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 + +#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 +#ifdef __STDC__ +mpn_sqrt (mp_ptr root_ptr, mp_ptr rem_ptr, mp_srcptr op_ptr, mp_size op_size) +#else +mpn_sqrt (root_ptr, rem_ptr, op_ptr, op_size) + mp_ptr root_ptr; + mp_ptr rem_ptr; + mp_srcptr op_ptr; + mp_size op_size; +#endif +{ + /* R (root result) */ + mp_ptr rp; /* Pointer to least significant word */ + mp_size 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 tsize; /* The size in words */ + mp_ptr t_end_ptr; /* Pointer right beyond most sign. word */ + mp_limb 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 xsize; /* The size in words */ + + unsigned cnt; + mp_limb initial_approx; /* Initially made approximation */ + mp_size tsizes[BITS_PER_MP_LIMB]; /* Successive calculation precisions */ + mp_size tmp; + mp_size i; + + /* 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; + + /* 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) alloca (tsize * BYTES_PER_MP_LIMB); + + t_high0 = mpn_lshift (tp + cnt / BITS_PER_MP_LIMB, op_ptr, op_size, + (cnt & ~1) % BITS_PER_MP_LIMB); + 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) 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 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) initial_approx >= 0) + initial_approx = ~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 == ~0) + initial_approx = t_high0; + else + { + mp_limb 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) 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 ignored_remainder; + + udiv_qrnnd (quot, ignored_remainder, + t_high0, t_high1, initial_approx); + initial_approx = (initial_approx + quot) / 2; + initial_approx |= (mp_limb) 1 << (BITS_PER_MP_LIMB - 1); + } + } +#endif + + rp[0] = initial_approx; + rsize = 1; + + xp = (mp_ptr) alloca (tsize * BYTES_PER_MP_LIMB); + ttp = (mp_ptr) alloca (tsize * BYTES_PER_MP_LIMB); + + t_end_ptr = tp + tsize; + +#ifdef DEBUG + printf ("\n\nT = "); + _mp_mout (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). */ + + 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_div 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 cy; +#ifdef DEBUG + mp_limb old_least_sign_r = rp[0]; + mp_size old_rsize = rsize; + + printf ("R = "); + _mp_mout (rp, rsize); +#endif + tsize = tsizes[i]; + + /* Need to copy the numerator into temporary space, as + mpn_div overwrites its numerator argument with the + remainder (which we currently ignore). */ + MPN_COPY (ttp, t_end_ptr - tsize, tsize); + cy = mpn_div (xp, ttp, tsize, rp, rsize); + xsize = tsize - rsize; + cy = cy ? xp[xsize] : 0; + +#ifdef DEBUG + printf ("X =%d", cy); + _mp_mout (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 (xp + tmp, rp, rsize, 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 j; + for (j = xsize; j >= 0; j--) + xp[j] = ~(mp_limb)0; + } + + /* Divide X by 2 and put the result in R. This is the new + approximation. Shift in the carry from the addition. */ + rsize = mpn_rshiftci (rp, xp, xsize, 1, (mp_limb) 1); +#ifdef DEBUG + if (old_least_sign_r != rp[rsize - old_rsize]) + printf (">>>>>>>> %d: %08x, %08x <<<<<<<<\n", + i, old_least_sign_r, rp[rsize - old_rsize]); +#endif + } + } + +#ifdef DEBUG + printf ("(final) R = "); + _mp_mout (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. */ + rsize = mpn_rshift (rp, rp, rsize, cnt/2); + + /* Calculate the remainder. */ + tsize = mpn_mul (tp, rp, rsize, rp, rsize); + if (op_size < tsize + || (op_size == tsize && mpn_cmp (op_ptr, tp, op_size) < 0)) + { + /* R is too large. Decrement it. */ + mp_limb one = 1; + + tsize = tsize + mpn_sub (tp, tp, tsize, rp, rsize); + tsize = tsize + mpn_sub (tp, tp, tsize, rp, rsize); + tsize = tsize + mpn_add (tp, tp, tsize, &one, 1); + + (void) mpn_sub (rp, rp, rsize, &one, 1); + +#ifdef DEBUG + printf ("(adjusted) R = "); + _mp_mout (rp, rsize); +#endif + } + + if (rem_ptr != NULL) + { + mp_size retval = op_size + mpn_sub (rem_ptr, op_ptr, op_size, tp, tsize); + alloca (0); + return retval; + } + else + { + mp_size retval = (op_size != tsize || mpn_cmp (op_ptr, tp, op_size)); + alloca (0); + return retval; + } +} + +#ifdef DEBUG +_mp_mout (mp_srcptr p, mp_size size) +{ + mp_size ii; + for (ii = size - 1; ii >= 0; ii--) + printf ("%08X", p[ii]); + + puts (""); +} +#endif diff --git a/gnu/lib/libgmp/mpn_sub.c b/gnu/lib/libgmp/mpn_sub.c new file mode 100644 index 0000000..3ba8afd --- /dev/null +++ b/gnu/lib/libgmp/mpn_sub.c @@ -0,0 +1,162 @@ +/* mpn_sub -- Subtract two low-level natural-number integers. + +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" +#include "gmp-impl.h" + +/* Subtract SUB_PTR/SUB_SIZE from MIN_PTR/MIN_SIZE and store the + result (MIN_SIZE words) at DIF_PTR. + + Return 1 if min < sub (result is negative). Otherwise, return the + negative difference between the number of words in dif and min. + (I.e. return 0 if the result has MIN_SIZE words, -1 if it has + MIN_SIZE - 1 words, etc.) + + Argument constraint: MIN_SIZE >= SUB_SIZE. + + The size of DIF can be calculated as MIN_SIZE + the return value. */ + +mp_size +#ifdef __STDC__ +mpn_sub (mp_ptr dif_ptr, + mp_srcptr min_ptr, mp_size min_size, + mp_srcptr sub_ptr, mp_size sub_size) +#else +mpn_sub (dif_ptr, min_ptr, min_size, sub_ptr, sub_size) + mp_ptr dif_ptr; + mp_srcptr min_ptr; + mp_size min_size; + mp_srcptr sub_ptr; + mp_size sub_size; +#endif +{ + mp_limb m, s, dif; + mp_size j; + + /* The loop counter and index J goes from some negative value to zero. + This way the loops are faster. Need to offset the base pointers + to take care of the negative indices. */ + + j = -sub_size; + if (j == 0) + goto sub_finished; + + min_ptr -= j; + sub_ptr -= j; + dif_ptr -= j; + + /* There are two do-loops, marked NON-CARRY LOOP and CARRY LOOP that + jump between each other. The first loop is for when the previous + subtraction didn't produce a carry-out; the second is for the + complementary case. */ + + /* NON-CARRY LOOP */ + do + { + m = min_ptr[j]; + s = sub_ptr[j]; + dif = m - s; + dif_ptr[j] = dif; + if (dif > m) + goto cy_loop; + ncy_loop: + j++; + } + while (j < 0); + + /* We have exhausted SUB, with no carry out. Copy remaining part of + MIN to DIF. */ + + sub_finished: + j = sub_size - min_size; + + /* If there's no difference between the length of the operands, the + last words might have become zero, and re-normalization is needed. */ + if (j == 0) + goto normalize; + + min_ptr -= j; + dif_ptr -= j; + + goto copy; + + /* CARRY LOOP */ + do + { + m = min_ptr[j]; + s = sub_ptr[j]; + dif = m - s - 1; + dif_ptr[j] = dif; + if (dif < m) + goto ncy_loop; + cy_loop: + j++; + } + while (j < 0); + + /* We have exhausted SUB, but need to propagate carry. */ + + j = sub_size - min_size; + if (j == 0) + return 1; /* min < sub. Flag it to the caller */ + + min_ptr -= j; + dif_ptr -= j; + + /* Propagate carry. Sooner or later the carry will cancel with a + non-zero word, because the minuend is normalized. Considering this, + there's no need to test the index J. */ + for (;;) + { + m = min_ptr[j]; + dif = m - 1; + dif_ptr[j] = dif; + j++; + if (dif < m) + break; + } + + if (j == 0) + goto normalize; + + copy: + /* Don't copy the remaining words of MIN to DIF if MIN_PTR and DIF_PTR + are equal. It would just be a no-op copying. Return 0, as the length + of the result equals that of the minuend. */ + if (dif_ptr == min_ptr) + return 0; + + do + { + dif_ptr[j] = min_ptr[j]; + j++; + } + while (j < 0); + return 0; + + normalize: + for (j = -1; j >= -min_size; j--) + { + if (dif_ptr[j] != 0) + return j + 1; + } + + return -min_size; +} diff --git a/gnu/lib/libgmp/mpq_add.c b/gnu/lib/libgmp/mpq_add.c new file mode 100644 index 0000000..10cc12e --- /dev/null +++ b/gnu/lib/libgmp/mpq_add.c @@ -0,0 +1,85 @@ +/* mpq_add -- add two rational numbers. + +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" +#include "gmp-impl.h" + +void +#ifdef __STDC__ +mpq_add (MP_RAT *sum, const MP_RAT *a1, const MP_RAT *a2) +#else +mpq_add (sum, a1, a2) + MP_RAT *sum; + const MP_RAT *a1; + const MP_RAT *a2; +#endif +{ + MP_INT gcd1, gcd2; + MP_INT tmp1, tmp2; + + mpz_init (&gcd1); + mpz_init (&gcd2); + mpz_init (&tmp1); + mpz_init (&tmp2); + + /* SUM 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 SUM when we are finished + with the numerators of A1 and A2. */ + + mpz_gcd (&gcd1, &(a1->den), &(a2->den)); + if (gcd1.size > 1 || gcd1.d[0] != 1) + { + MP_INT t; + + mpz_init (&t); + + mpz_div (&tmp1, &(a2->den), &gcd1); + mpz_mul (&tmp1, &(a1->num), &tmp1); + + mpz_div (&tmp2, &(a1->den), &gcd1); + mpz_mul (&tmp2, &(a2->num), &tmp2); + + mpz_add (&t, &tmp1, &tmp2); + mpz_gcd (&gcd2, &t, &gcd1); + + mpz_div (&(sum->num), &t, &gcd2); + + mpz_div (&tmp1, &(a1->den), &gcd1); + mpz_div (&tmp2, &(a2->den), &gcd2); + mpz_mul (&(sum->den), &tmp1, &tmp2); + + mpz_clear (&t); + } + else + { + /* The common divisior is 1. This is the case (for random input) with + probability 6/(pi**2). */ + mpz_mul (&tmp1, &(a1->num), &(a2->den)); + mpz_mul (&tmp2, &(a2->num), &(a1->den)); + mpz_add (&(sum->num), &tmp1, &tmp2); + mpz_mul (&(sum->den), &(a1->den), &(a2->den)); + } + + mpz_clear (&tmp2); + mpz_clear (&tmp1); + mpz_clear (&gcd2); + mpz_clear (&gcd1); +} diff --git a/gnu/lib/libgmp/mpq_clear.c b/gnu/lib/libgmp/mpq_clear.c new file mode 100644 index 0000000..3266463 --- /dev/null +++ b/gnu/lib/libgmp/mpq_clear.c @@ -0,0 +1,34 @@ +/* mpq_clear -- free the space occupied by a MP_RAT. + +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" +#include "gmp-impl.h" + +void +#ifdef __STDC__ +mpq_clear (MP_RAT *m) +#else +mpq_clear (m) + MP_RAT *m; +#endif +{ + (*_mp_free_func) (m->num.d, m->num.alloc * BYTES_PER_MP_LIMB); + (*_mp_free_func) (m->den.d, m->den.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 0000000..fd6abcc --- /dev/null +++ b/gnu/lib/libgmp/mpq_cmp.c @@ -0,0 +1,76 @@ +/* mpq_cmp(u,v) -- Compare U, V. Return positive, zero, or negative + based on if U > V, U == V, or U < V. + +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" +#include "gmp-impl.h" + +int +#ifdef __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 num1_size = op1->num.size; + mp_size den1_size = op1->den.size; + mp_size num2_size = op2->num.size; + mp_size den2_size = op2->den.size; + mp_size tmp1_size, tmp2_size; + mp_ptr tmp1_ptr, tmp2_ptr; + mp_size num1_sign; + int cc; + + 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; + + if (tmp1_size != tmp2_size) + return (tmp1_size - tmp2_size) ^ num1_sign; + + tmp1_ptr = (mp_ptr) alloca (tmp1_size * BYTES_PER_MP_LIMB); + tmp2_ptr = (mp_ptr) alloca (tmp2_size * BYTES_PER_MP_LIMB); + + tmp1_size = (num1_size >= den2_size) + ? mpn_mul (tmp1_ptr, op1->num.d, num1_size, op2->den.d, den2_size) + : mpn_mul (tmp1_ptr, op2->den.d, den2_size, op1->num.d, num1_size); + + tmp2_size = (num2_size >= den1_size) + ? mpn_mul (tmp2_ptr, op2->num.d, num2_size, op1->den.d, den1_size) + : mpn_mul (tmp2_ptr, op1->den.d, den1_size, op2->num.d, num2_size); + + cc = tmp1_size - tmp2_size != 0 + ? tmp1_size - tmp2_size : mpn_cmp (tmp1_ptr, tmp2_ptr, tmp1_size); + + alloca (0); + return (num1_sign < 0) ? -cc : cc; +} diff --git a/gnu/lib/libgmp/mpq_div.c b/gnu/lib/libgmp/mpq_div.c new file mode 100644 index 0000000..f08aa27 --- /dev/null +++ b/gnu/lib/libgmp/mpq_div.c @@ -0,0 +1,92 @@ +/* mpq_div -- divide two rational numbers. + +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" +#include "gmp-impl.h" + +void +#ifdef __STDC__ +mpq_div (MP_RAT *quot, const MP_RAT *dividend, const MP_RAT *divisor) +#else +mpq_div (quot, dividend, divisor) + MP_RAT *quot; + const MP_RAT *dividend; + const MP_RAT *divisor; +#endif +{ + MP_INT gcd1, gcd2; + MP_INT tmp1, tmp2; + MP_INT 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 DIVIDEND and DIVISOR. */ + + mpz_gcd (&gcd1, &(dividend->num), &(divisor->num)); + mpz_gcd (&gcd2, &(divisor->den), &(dividend->den)); + + if (gcd1.size > 1 || gcd1.d[0] != 1) + mpz_div (&tmp1, &(dividend->num), &gcd1); + else + mpz_set (&tmp1, &(dividend->num)); + + if (gcd2.size > 1 || gcd2.d[0] != 1) + mpz_div (&tmp2, &(divisor->den), &gcd2); + else + mpz_set (&tmp2, &(divisor->den)); + + mpz_mul (&numtmp, &tmp1, &tmp2); + + if (gcd1.size > 1 || gcd1.d[0] != 1) + mpz_div (&tmp1, &(divisor->num), &gcd1); + else + mpz_set (&tmp1, &(divisor->num)); + + if (gcd2.size > 1 || gcd2.d[0] != 1) + mpz_div (&tmp2, &(dividend->den), &gcd2); + else + mpz_set (&tmp2, &(dividend->den)); + + mpz_mul (&(quot->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->NUM. */ + mpz_set (&(quot->num), &numtmp); + + /* Keep the denominator positive. */ + if (quot->den.size < 0) + { + quot->den.size = -quot->den.size; + quot->num.size = -quot->num.size; + } + + mpz_clear (&numtmp); + mpz_clear (&tmp2); + mpz_clear (&tmp1); + mpz_clear (&gcd2); + mpz_clear (&gcd1); +} diff --git a/gnu/lib/libgmp/mpq_get_den.c b/gnu/lib/libgmp/mpq_get_den.c new file mode 100644 index 0000000..12b9fe2 --- /dev/null +++ b/gnu/lib/libgmp/mpq_get_den.c @@ -0,0 +1,40 @@ +/* mpq_get_den(den,rat_src) -- Set DEN to the denominator of RAT_SRC. + +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" +#include "gmp-impl.h" + +void +#ifdef __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 size = src->den.size; + + if (den->alloc < size) + _mpz_realloc (den, size); + + MPN_COPY (den->d, src->den.d, size); + den->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 0000000..4240652 --- /dev/null +++ b/gnu/lib/libgmp/mpq_get_num.c @@ -0,0 +1,41 @@ + /* mpq_get_num(num,rat_src) -- Set NUM to the numerator of RAT_SRC. + +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" +#include "gmp-impl.h" + +void +#ifdef __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 size = src->num.size; + mp_size abs_size = ABS (size); + + if (num->alloc < abs_size) + _mpz_realloc (num, abs_size); + + MPN_COPY (num->d, src->num.d, abs_size); + num->size = size; +} diff --git a/gnu/lib/libgmp/mpq_init.c b/gnu/lib/libgmp/mpq_init.c new file mode 100644 index 0000000..fcb0bd2 --- /dev/null +++ b/gnu/lib/libgmp/mpq_init.c @@ -0,0 +1,39 @@ +/* mpq_init -- Make a new rational number with value 0/1. + +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" +#include "gmp-impl.h" + +void +#ifdef __STDC__ +mpq_init (MP_RAT *x) +#else +mpq_init (x) + MP_RAT *x; +#endif +{ + x->num.alloc = 1; + x->num.d = (mp_ptr) (*_mp_allocate_func) (BYTES_PER_MP_LIMB * x->num.alloc); + x->num.size = 0; + x->den.alloc = 1; + x->den.d = (mp_ptr) (*_mp_allocate_func) (BYTES_PER_MP_LIMB * x->den.alloc); + x->den.d[0] = 1; + x->den.size = 1; +} diff --git a/gnu/lib/libgmp/mpq_inv.c b/gnu/lib/libgmp/mpq_inv.c new file mode 100644 index 0000000..07fcaa1 --- /dev/null +++ b/gnu/lib/libgmp/mpq_inv.c @@ -0,0 +1,74 @@ +/* mpq_inv(dest,src) -- invert a rational number, i.e. set DEST to SRC + with the numerator and denominator swapped. + +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" +#include "gmp-impl.h" + +void +#ifdef __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 num_size = src->num.size; + mp_size den_size = src->den.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->den.size = num_size; + dest->num.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 alloc = dest->num.alloc; + mp_ptr limb_ptr = dest->num.d; + + dest->num.alloc = dest->den.alloc; + dest->num.d = dest->den.d; + + dest->den.alloc = alloc; + dest->den.d = limb_ptr; + } + else + { + den_size = ABS (den_size); + if (dest->num.alloc < den_size) + _mpz_realloc (&(dest->num), den_size); + + if (dest->den.alloc < num_size) + _mpz_realloc (&(dest->den), num_size); + + MPN_COPY (dest->num.d, src->den.d, den_size); + MPN_COPY (dest->den.d, src->num.d, num_size); + } +} diff --git a/gnu/lib/libgmp/mpq_mul.c b/gnu/lib/libgmp/mpq_mul.c new file mode 100644 index 0000000..003d6ca --- /dev/null +++ b/gnu/lib/libgmp/mpq_mul.c @@ -0,0 +1,78 @@ +/* mpq_mul -- mutiply two rational numbers. + +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" +#include "gmp-impl.h" + +void +#ifdef __STDC__ +mpq_mul (MP_RAT *prod, const MP_RAT *m1, const MP_RAT *m2) +#else +mpq_mul (prod, m1, m2) + MP_RAT *prod; + const MP_RAT *m1; + const MP_RAT *m2; +#endif +{ + MP_INT gcd1, gcd2; + MP_INT 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 M1 and M1. */ + + mpz_gcd (&gcd1, &(m1->num), &(m2->den)); + mpz_gcd (&gcd2, &(m2->num), &(m1->den)); + + if (gcd1.size > 1 || gcd1.d[0] != 1) + mpz_div (&tmp1, &(m1->num), &gcd1); + else + mpz_set (&tmp1, &(m1->num)); + + if (gcd2.size > 1 || gcd2.d[0] != 1) + mpz_div (&tmp2, &(m2->num), &gcd2); + else + mpz_set (&tmp2, &(m2->num)); + + mpz_mul (&(prod->num), &tmp1, &tmp2); + + if (gcd1.size > 1 || gcd1.d[0] != 1) + mpz_div (&tmp1, &(m2->den), &gcd1); + else + mpz_set (&tmp1, &(m2->den)); + + if (gcd2.size > 1 || gcd2.d[0] != 1) + mpz_div (&tmp2, &(m1->den), &gcd2); + else + mpz_set (&tmp2, &(m1->den)); + + mpz_mul (&(prod->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 0000000..2141e25 --- /dev/null +++ b/gnu/lib/libgmp/mpq_neg.c @@ -0,0 +1,35 @@ +/* mpq_neg(dst, src) -- Assign the negated value of SRC to DST. + +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" +#include "gmp-impl.h" + +void +#ifdef __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->num, &src->num); + mpz_set (&dst->den, &src->den); +} diff --git a/gnu/lib/libgmp/mpq_set.c b/gnu/lib/libgmp/mpq_set.c new file mode 100644 index 0000000..1d0cf3e --- /dev/null +++ b/gnu/lib/libgmp/mpq_set.c @@ -0,0 +1,48 @@ +/* mpq_set(dest,src) -- Set DEST to SRC. + +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" +#include "gmp-impl.h" + +void +#ifdef __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 num_size, den_size; + mp_size abs_num_size; + + num_size = src->num.size; + abs_num_size = ABS (num_size); + if (dest->num.alloc < abs_num_size) + _mpz_realloc (&(dest->num), abs_num_size); + MPN_COPY (dest->num.d, src->num.d, abs_num_size); + dest->num.size = num_size; + + den_size = src->den.size; + if (dest->den.alloc < den_size) + _mpz_realloc (&(dest->den), den_size); + MPN_COPY (dest->den.d, src->den.d, den_size); + dest->den.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 0000000..d532f1a --- /dev/null +++ b/gnu/lib/libgmp/mpq_set_den.c @@ -0,0 +1,46 @@ +/* mpq_set_den(dest,den) -- Set the denominator of DEST from DEN. + If DEN < 0 change the sign of the numerator of DEST. + +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" +#include "gmp-impl.h" + +void +#ifdef __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 size = den->size; + mp_size abs_size = ABS (size); + + if (dest->den.alloc < abs_size) + _mpz_realloc (&(dest->den), abs_size); + + MPN_COPY (dest->den.d, den->d, abs_size); + dest->den.size = abs_size; + + /* The denominator is always positive; move the sign to the numerator. */ + if (size < 0) + dest->num.size = -dest->num.size; +} diff --git a/gnu/lib/libgmp/mpq_set_num.c b/gnu/lib/libgmp/mpq_set_num.c new file mode 100644 index 0000000..609f16b --- /dev/null +++ b/gnu/lib/libgmp/mpq_set_num.c @@ -0,0 +1,41 @@ +/* mpq_set_num(dest,num) -- Set the numerator of DEST from NUM. + +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" +#include "gmp-impl.h" + +void +#ifdef __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 size = num->size; + mp_size abs_size = ABS (size); + + if (dest->num.alloc < abs_size) + _mpz_realloc (&(dest->num), abs_size); + + MPN_COPY (dest->num.d, num->d, abs_size); + dest->num.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 0000000..f108b6c --- /dev/null +++ b/gnu/lib/libgmp/mpq_set_si.c @@ -0,0 +1,76 @@ +/* mpq_set_si(dest,ulong_num,ulong_den) -- Set DEST to the retional number + ULONG_NUM/ULONG_DEN. + +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" +#include "gmp-impl.h" + +static unsigned long int +gcd (x, y) + unsigned long int x, y; +{ + for (;;) + { + x = x % y; + if (x == 0) + return y; + y = y % x; + if (y == 0) + return x; + } +} + +void +#ifdef __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 g; + unsigned long int abs_num; + + abs_num = ABS (num); + + if (num == 0) + { + /* Canonicalize 0/d to 0/1. */ + den = 1; + dest->num.size = 0; + } + else + { + /* Remove any common factor in NUM and DEN. */ + /* Pass DEN as the second argument to gcd, in order to make the + gcd function divide by zero if DEN is zero. */ + g = gcd (abs_num, den); + abs_num /= g; + den /= g; + + dest->num.d[0] = abs_num; + dest->num.size = num > 0 ? 1 : -1; + } + + dest->den.d[0] = den; + dest->den.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 0000000..54b69ee --- /dev/null +++ b/gnu/lib/libgmp/mpq_set_ui.c @@ -0,0 +1,73 @@ +/* mpq_set_ui(dest,ulong_num,ulong_den) -- Set DEST to the retional number + ULONG_NUM/ULONG_DEN. + +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" +#include "gmp-impl.h" + +static unsigned long int +gcd (x, y) + unsigned long int x, y; +{ + for (;;) + { + x = x % y; + if (x == 0) + return y; + y = y % x; + if (y == 0) + return x; + } +} + +void +#ifdef __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 +{ + unsigned long int g; + + if (num == 0) + { + /* Canonicalize 0/n to 0/1. */ + den = 1; + dest->num.size = 0; + } + else + { + /* Remove any common factor in NUM and DEN. */ + /* Pass DEN as the second argument to gcd, in order to make the + gcd function divide by zero if DEN is zero. */ + g = gcd (num, den); + num /= g; + den /= g; + + dest->num.d[0] = num; + dest->num.size = 1; + } + + dest->den.d[0] = den; + dest->den.size = 1; +} diff --git a/gnu/lib/libgmp/mpq_sub.c b/gnu/lib/libgmp/mpq_sub.c new file mode 100644 index 0000000..a512705 --- /dev/null +++ b/gnu/lib/libgmp/mpq_sub.c @@ -0,0 +1,85 @@ +/* mpq_sub -- subtract two rational numbers. + +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" +#include "gmp-impl.h" + +void +#ifdef __STDC__ +mpq_sub (MP_RAT *dif, const MP_RAT *min, const MP_RAT *sub) +#else +mpq_sub (dif, min, sub) + MP_RAT *dif; + const MP_RAT *min; + const MP_RAT *sub; +#endif +{ + MP_INT gcd1, gcd2; + MP_INT tmp1, tmp2; + + mpz_init (&gcd1); + mpz_init (&gcd2); + mpz_init (&tmp1); + mpz_init (&tmp2); + + /* DIF 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 DIF when we are finished + with the numerators of MIN and SUB. */ + + mpz_gcd (&gcd1, &(min->den), &(sub->den)); + if (gcd1.size > 1 || gcd1.d[0] != 1) + { + MP_INT t; + + mpz_init (&t); + + mpz_div (&tmp1, &(sub->den), &gcd1); + mpz_mul (&tmp1, &(min->num), &tmp1); + + mpz_div (&tmp2, &(min->den), &gcd1); + mpz_mul (&tmp2, &(sub->num), &tmp2); + + mpz_sub (&t, &tmp1, &tmp2); + mpz_gcd (&gcd2, &t, &gcd1); + + mpz_div (&(dif->num), &t, &gcd2); + + mpz_div (&tmp1, &(min->den), &gcd1); + mpz_div (&tmp2, &(sub->den), &gcd2); + mpz_mul (&(dif->den), &tmp1, &tmp2); + + mpz_clear (&t); + } + else + { + /* The common divisior is 1. This is the case (for random input) with + probability 6/(pi**2). */ + mpz_mul (&tmp1, &(min->num), &(sub->den)); + mpz_mul (&tmp2, &(sub->num), &(min->den)); + mpz_sub (&(dif->num), &tmp1, &tmp2); + mpz_mul (&(dif->den), &(min->den), &(sub->den)); + } + + mpz_clear (&tmp2); + mpz_clear (&tmp1); + mpz_clear (&gcd2); + mpz_clear (&gcd1); +} diff --git a/gnu/lib/libgmp/mpz_abs.c b/gnu/lib/libgmp/mpz_abs.c new file mode 100644 index 0000000..39c1433 --- /dev/null +++ b/gnu/lib/libgmp/mpz_abs.c @@ -0,0 +1,44 @@ +/* mpz_abs(MP_INT *dst, MP_INT *src) -- Assign the absolute value of SRC to DST. + +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" +#include "gmp-impl.h" + +void +#ifdef __STDC__ +mpz_abs (MP_INT *dst, const MP_INT *src) +#else +mpz_abs (dst, src) + MP_INT *dst; + const MP_INT *src; +#endif +{ + mp_size src_size = ABS (src->size); + + if (src != dst) + { + if (dst->alloc < src_size) + _mpz_realloc (dst, src_size); + + MPN_COPY (dst->d, src->d, src_size); + } + + dst->size = src_size; +} diff --git a/gnu/lib/libgmp/mpz_add.c b/gnu/lib/libgmp/mpz_add.c new file mode 100644 index 0000000..52639cc --- /dev/null +++ b/gnu/lib/libgmp/mpz_add.c @@ -0,0 +1,121 @@ +/* mpz_add -- Add two integers. + +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" +#include "gmp-impl.h" + +#ifndef BERKELEY_MP +void +#ifdef __STDC__ +mpz_add (MP_INT *sum, const MP_INT *u, const MP_INT *v) +#else +mpz_add (sum, u, v) + MP_INT *sum; + const MP_INT *u; + const MP_INT *v; +#endif +#else /* BERKELEY_MP */ +void +#ifdef __STDC__ +madd (const MP_INT *u, const MP_INT *v, MP_INT *sum) +#else +madd (u, v, sum) + const MP_INT *u; + const MP_INT *v; + MP_INT *sum; +#endif +#endif /* BERKELEY_MP */ +{ + mp_srcptr up, vp; + mp_ptr sump; + mp_size usize, vsize, sumsize; + mp_size abs_usize; + mp_size abs_vsize; + + usize = u->size; + vsize = v->size; + abs_usize = ABS (usize); + abs_vsize = ABS (vsize); + + if (abs_usize < abs_vsize) + { + /* Swap U and V. */ + {const MP_INT *t = u; u = v; v = t;} + {mp_size t = usize; usize = vsize; vsize = t;} + {mp_size t = abs_usize; abs_usize = abs_vsize; abs_vsize = t;} + } + + /* True: abs(USIZE) >= abs(VSIZE) */ + + /* If not space for sum (and possible carry), increase space. */ + sumsize = abs_usize + 1; + if (sum->alloc < sumsize) + _mpz_realloc (sum, sumsize); + + /* These must be after realloc (u or v may be the same as sum). */ + up = u->d; + vp = v->d; + sump = sum->d; + + if (usize >= 0) + { + if (vsize >= 0) + { + sumsize = mpn_add (sump, up, abs_usize, vp, abs_vsize); + if (sumsize != 0) + sump[abs_usize] = 1; + sumsize = sumsize + abs_usize; + } + else + { + /* The signs are different. Need exact comparision to determine + which operand to subtract from which. */ + if (abs_usize == abs_vsize && mpn_cmp (up, vp, abs_usize) < 0) + sumsize = -(abs_usize + + mpn_sub (sump, vp, abs_usize, up, abs_usize)); + else + sumsize = (abs_usize + + mpn_sub (sump, up, abs_usize, vp, abs_vsize)); + } + } + else + { + if (vsize >= 0) + { + /* The signs are different. Need exact comparision to determine + which operand to subtract from which. */ + if (abs_usize == abs_vsize && mpn_cmp (up, vp, abs_usize) < 0) + sumsize = (abs_usize + + mpn_sub (sump, vp, abs_usize, up, abs_usize)); + else + sumsize = -(abs_usize + + mpn_sub (sump, up, abs_usize, vp, abs_vsize)); + } + else + { + sumsize = mpn_add (sump, up, abs_usize, vp, abs_vsize); + if (sumsize != 0) + sump[abs_usize] = 1; + sumsize = -(sumsize + abs_usize); + } + } + + sum->size = sumsize; +} diff --git a/gnu/lib/libgmp/mpz_add_ui.c b/gnu/lib/libgmp/mpz_add_ui.c new file mode 100644 index 0000000..34f754b --- /dev/null +++ b/gnu/lib/libgmp/mpz_add_ui.c @@ -0,0 +1,84 @@ +/* mpz_add_ui -- Add an MP_INT and an unsigned one-word integer. + +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" +#include "gmp-impl.h" + +void +#ifdef __STDC__ +mpz_add_ui (MP_INT *sum, const MP_INT *add1, mp_limb add2) +#else +mpz_add_ui (sum, add1, add2) + MP_INT *sum; + const MP_INT *add1; + mp_limb add2; +#endif +{ + mp_srcptr add1p; + mp_ptr sump; + mp_size add1size, sumsize; + mp_size abs_add1size; + + add1size = add1->size; + abs_add1size = ABS (add1size); + + /* If not space for SUM (and possible carry), increase space. */ + sumsize = abs_add1size + 1; + if (sum->alloc < sumsize) + _mpz_realloc (sum, sumsize); + + /* These must be after realloc (ADD1 may be the same as SUM). */ + add1p = add1->d; + sump = sum->d; + + if (add2 == 0) + { + MPN_COPY (sump, add1p, abs_add1size); + sum->size = add1size; + return; + } + if (abs_add1size == 0) + { + sump[0] = add2; + sum->size = 1; + return; + } + + if (add1size >= 0) + { + sumsize = mpn_add (sump, add1p, abs_add1size, &add2, 1); + if (sumsize != 0) + sump[abs_add1size] = 1; + sumsize = sumsize + abs_add1size; + } + else + { + /* The signs are different. Need exact comparision to determine + which operand to subtract from which. */ + if (abs_add1size == 1 && add1p[0] < add2) + sumsize = (abs_add1size + + mpn_sub (sump, &add2, 1, add1p, 1)); + else + sumsize = -(abs_add1size + + mpn_sub (sump, add1p, abs_add1size, &add2, 1)); + } + + sum->size = sumsize; +} diff --git a/gnu/lib/libgmp/mpz_and.c b/gnu/lib/libgmp/mpz_and.c new file mode 100644 index 0000000..f5b39ed --- /dev/null +++ b/gnu/lib/libgmp/mpz_and.c @@ -0,0 +1,267 @@ +/* mpz_and -- Logical and. + +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" +#include "gmp-impl.h" + +#define min(l,o) ((l) < (o) ? (l) : (o)) +#define max(h,i) ((h) > (i) ? (h) : (i)) + +void +#ifdef __STDC__ +mpz_and (MP_INT *res, const MP_INT *op1, const MP_INT *op2) +#else +mpz_and (res, op1, op2) + MP_INT *res; + const MP_INT *op1; + const MP_INT *op2; +#endif +{ + mp_srcptr op1_ptr, op2_ptr; + mp_size op1_size, op2_size; + mp_ptr res_ptr; + mp_size res_size; + mp_size i; + + op1_size = op1->size; + op2_size = op2->size; + + op1_ptr = op1->d; + op2_ptr = op2->d; + res_ptr = res->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 when we know exactly how much space is + needed for the result. */ + if (res->alloc < res_size) + { + _mpz_realloc (res, res_size); + op1_ptr = op1->d; + op2_ptr = op2->d; + res_ptr = res->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->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 cy; + mp_limb one = 1; + mp_size 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 */ + + op1_size = -op1_size; + op2_size = -op2_size; + + res_alloc = 1 + max (op1_size, op2_size); + + opx = (mp_ptr) alloca (op1_size * BYTES_PER_MP_LIMB); + op1_size += mpn_sub (opx, op1_ptr, op1_size, &one, 1); + op1_ptr = opx; + + opx = (mp_ptr) alloca (op2_size * BYTES_PER_MP_LIMB); + op2_size += mpn_sub (opx, op2_ptr, op2_size, &one, 1); + op2_ptr = opx; + + if (res->alloc < res_alloc) + { + _mpz_realloc (res, res_alloc); + res_ptr = res->d; + /* Don't re-read OP1_PTR and OP2_PTR. They point to + temporary space--never to the space RES->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; + } + + if (res_size != 0) + { + cy = mpn_add (res_ptr, res_ptr, res_size, &one, 1); + if (cy) + { + res_ptr[res_size] = cy; + res_size++; + } + } + else + { + res_ptr[0] = 1; + res_size = 1; + } + + res->size = -res_size; + return; + } + else + { + /* We should compute -OP1 & OP2. Swap OP1 and OP2 and fall + through to the code that handles OP1 & -OP2. */ + {const MP_INT *t = op1; op1 = op2; op2 = t;} + {mp_srcptr t = op1_ptr; op1_ptr = op2_ptr; op2_ptr = t;} + {mp_size t = op1_size; op1_size = op2_size; op2_size = t;} + } + + } + + { +#if 0 + mp_size op2_lim; + + /* 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; + } + else + { + /* The ones-extended OP2 is < than the zero-extended OP1. + RES_SIZE == OP1_SIZE, since OP1 is normalized. */ + res_size = op1_size; + } +#endif + + /* 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; + const mp_limb one = 1; + + op2_size = -op2_size; + opx = (mp_ptr) alloca (op2_size * BYTES_PER_MP_LIMB); + op2_size += mpn_sub (opx, op2_ptr, op2_size, &one, 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 when we know exactly how much space is + needed for the result. */ + if (res->alloc < res_size) + { + _mpz_realloc (res, res_size); + res_ptr = res->d; + op1_ptr = op1->d; + /* Don't re-read OP2_PTR. It points to temporary space--never + to the space RES->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->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 when we know exactly how much space is + needed for the result. */ + if (res->alloc < res_size) + { + _mpz_realloc (res, res_size); + res_ptr = res->d; + op1_ptr = op1->d; + /* Don't re-read OP2_PTR. It points to temporary space--never + to the space RES->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->size = res_size; + } + } +} diff --git a/gnu/lib/libgmp/mpz_clear.c b/gnu/lib/libgmp/mpz_clear.c new file mode 100644 index 0000000..f95b009 --- /dev/null +++ b/gnu/lib/libgmp/mpz_clear.c @@ -0,0 +1,34 @@ +/* mpz_clear -- de-allocate the space occupied by the dynamic digit space of + an integer. + +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" +#include "gmp-impl.h" + +void +#ifdef __STDC__ +mpz_clear (MP_INT *m) +#else +mpz_clear (m) + MP_INT *m; +#endif +{ + (*_mp_free_func) (m->d, m->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 0000000..7fde814 --- /dev/null +++ b/gnu/lib/libgmp/mpz_clrbit.c @@ -0,0 +1,124 @@ +/* mpz_clrbit -- clear a specified bit. + +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" +#include "gmp-impl.h" + +#define MPN_NORMALIZE(p, size) \ + do { \ + mp_size i; \ + for (i = (size) - 1; i >= 0; i--) \ + if ((p)[i] != 0) \ + break; \ + (size) = i + 1; \ + } while (0) + +void +#ifdef __STDC__ +mpz_clrbit (MP_INT *d, unsigned long int bit_index) +#else +mpz_clrbit (d, bit_index) + MP_INT *d; + unsigned long int bit_index; +#endif +{ + mp_size dsize = d->size; + mp_ptr dp = d->d; + mp_size limb_index; + + limb_index = bit_index / BITS_PER_MP_LIMB; + if (dsize >= 0) + { + if (limb_index < dsize) + { + dp[limb_index] &= ~((mp_limb) 1 << (bit_index % BITS_PER_MP_LIMB)); + MPN_NORMALIZE (dp, dsize); + d->size = dsize; + } + else + ; + } + else + { + mp_size 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) 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->alloc < limb_index + 1) + { + _mpz_realloc (d, limb_index + 1); + dp = d->d; + } + MPN_ZERO (dp + dsize, limb_index - dsize); + dp[limb_index] = ((mp_limb) 1 << (bit_index % BITS_PER_MP_LIMB)); + d->size = -(limb_index + 1); + } + } + else if (limb_index == zero_bound) + { + dp[limb_index] = ((dp[limb_index] - 1) + | ((mp_limb) 1 << (bit_index % BITS_PER_MP_LIMB))) + 1; + if (dp[limb_index] == 0) + { + mp_size 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->alloc < dsize) + { + _mpz_realloc (d, dsize); + dp = d->d; + } + dp[i] = 1; + d->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 0000000..b76b494 --- /dev/null +++ b/gnu/lib/libgmp/mpz_cmp.c @@ -0,0 +1,84 @@ +/* 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 Free Software Foundation, Inc. + +This file is part of the 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. */ + +#ifdef BERKELEY_MP +#include "mp.h" +#endif +#include "gmp.h" +#include "gmp-impl.h" + +#ifndef BERKELEY_MP +int +#ifdef __STDC__ +mpz_cmp (const MP_INT *u, const MP_INT *v) +#else +mpz_cmp (u, v) + const MP_INT *u; + const MP_INT *v; +#endif +#else /* BERKELEY_MP */ +int +#ifdef __STDC__ +mcmp (const MP_INT *u, const MP_INT *v) +#else +mcmp (u, v) + const MP_INT *u; + const MP_INT *v; +#endif +#endif /* BERKELEY_MP */ +{ + mp_size usize = u->size; + mp_size vsize = v->size; + mp_size size; + mp_size i; + mp_limb a, b; + mp_srcptr up, vp; + + if (usize != vsize) + return usize - vsize; + + if (usize == 0) + return 0; + + size = ABS (usize); + + up = u->d; + vp = v->d; + + i = size - 1; + do + { + a = up[i]; + b = vp[i]; + i--; + if (i < 0) + break; + } + while (a == b); + + if (a == b) + return 0; + + if ((a < b) == (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 0000000..c7073be --- /dev/null +++ b/gnu/lib/libgmp/mpz_cmp_si.c @@ -0,0 +1,62 @@ +/* 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 Free Software Foundation, Inc. + +This file is part of the 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" +#include "gmp-impl.h" + +int +#ifdef __STDC__ +mpz_cmp_si (const MP_INT *u, signed long int v_digit) +#else +mpz_cmp_si (u, v_digit) + const MP_INT *u; + signed long int v_digit; +#endif +{ + mp_size usize = u->size; + mp_size vsize; + mp_limb 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->d[0]; + + if (u_digit == v_digit) + return 0; + + if ((u_digit < v_digit) == (usize < 0)) + return 1; + else + return -1; +} diff --git a/gnu/lib/libgmp/mpz_cmp_ui.c b/gnu/lib/libgmp/mpz_cmp_ui.c new file mode 100644 index 0000000..79a41db --- /dev/null +++ b/gnu/lib/libgmp/mpz_cmp_ui.c @@ -0,0 +1,52 @@ +/* mpz_cmp_ui.c -- Compare a MP_INT a with an mp_limb b. Return positive, + zero, or negative based on if a > b, a == b, or a < b. + +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" +#include "gmp-impl.h" + +int +#ifdef __STDC__ +mpz_cmp_ui (const MP_INT *u, mp_limb v_digit) +#else +mpz_cmp_ui (u, v_digit) + const MP_INT *u; + mp_limb v_digit; +#endif +{ + mp_size usize = u->size; + + if (usize == 0) + return -(v_digit != 0); + + if (usize == 1) + { + mp_limb u_digit; + + u_digit = u->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 0000000..3c0d3b1 --- /dev/null +++ b/gnu/lib/libgmp/mpz_com.c @@ -0,0 +1,96 @@ +/* mpz_com(MP_INT *dst, MP_INT *src) -- Assign the bit-complemented value of + SRC to DST. + +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" +#include "gmp-impl.h" + +void +#ifdef __STDC__ +mpz_com (MP_INT *dst, const MP_INT *src) +#else +mpz_com (dst, src) + MP_INT *dst; + const MP_INT *src; +#endif +{ + mp_size size = src->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->alloc < size + 1) + _mpz_realloc (dst, size + 1); + + src_ptr = src->d; + dst_ptr = dst->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->size = -1; + return; + } + + { + mp_limb one = 1; + int cy; + + cy = mpn_add (dst_ptr, src_ptr, size, &one, 1); + if (cy) + { + dst_ptr[size] = cy; + size++; + } + } + + /* Store a negative size, to indicate ones-extension. */ + dst->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->alloc < size) + _mpz_realloc (dst, size); + + src_ptr = src->d; + dst_ptr = dst->d; + + { + mp_limb one = 1; + + size += mpn_sub (dst_ptr, src_ptr, size, &one, 1); + } + + /* Store a positive size, to indicate zero-extension. */ + dst->size = size; + } +} diff --git a/gnu/lib/libgmp/mpz_div.c b/gnu/lib/libgmp/mpz_div.c new file mode 100644 index 0000000..a27cde9 --- /dev/null +++ b/gnu/lib/libgmp/mpz_div.c @@ -0,0 +1,117 @@ +/* mpz_div -- divide two integers and produce a quotient. + +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" +#include "gmp-impl.h" +#include "longlong.h" + +void +#ifdef __STDC__ +mpz_div (MP_INT *quot, const MP_INT *num, const MP_INT *den) +#else +mpz_div (quot, num, den) + MP_INT *quot; + const MP_INT *num; + const MP_INT *den; +#endif +{ + mp_srcptr np, dp; + mp_ptr qp, rp; + mp_size nsize = num->size; + mp_size dsize = den->size; + mp_size qsize, rsize; + mp_size sign_quotient = nsize ^ dsize; + unsigned normalization_steps; + + 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->size = 0; + return; + } + + if (quot->alloc < qsize) + _mpz_realloc (quot, qsize); + + qp = quot->d; + np = num->d; + dp = den->d; + rp = (mp_ptr) alloca ((nsize + 1) * BYTES_PER_MP_LIMB); + + count_leading_zeros (normalization_steps, dp[dsize - 1]); + + /* Normalize the denominator and the numerator. */ + if (normalization_steps != 0) + { + mp_ptr tp; + mp_limb ndigit; + + /* 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) alloca (dsize * BYTES_PER_MP_LIMB); + (void) 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. */ + ndigit = mpn_lshift (rp, np, nsize, normalization_steps); + if (ndigit != 0) + { + rp[nsize] = ndigit; + 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) alloca (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; + } + + qsize = rsize - dsize + mpn_div (qp, rp, rsize, dp, dsize); + + /* Normalize the quotient. We may have at most one leading + zero-word, so no loop is needed. */ + if (qsize > 0) + qsize -= (qp[qsize - 1] == 0); + + if (sign_quotient < 0) + qsize = -qsize; + quot->size = qsize; + + alloca (0); +} diff --git a/gnu/lib/libgmp/mpz_div_2exp.c b/gnu/lib/libgmp/mpz_div_2exp.c new file mode 100644 index 0000000..de67f2f --- /dev/null +++ b/gnu/lib/libgmp/mpz_div_2exp.c @@ -0,0 +1,53 @@ +/* mpz_div_2exp -- Divide a bignum by 2**CNT + +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" +#include "gmp-impl.h" + +void +#ifdef __STDC__ +mpz_div_2exp (MP_INT *w, const MP_INT *u, unsigned long int cnt) +#else +mpz_div_2exp (w, u, cnt) + MP_INT *w; + const MP_INT *u; + unsigned long int cnt; +#endif +{ + mp_size usize = u->size; + mp_size wsize; + mp_size abs_usize = ABS (usize); + mp_size limb_cnt; + + limb_cnt = cnt / BITS_PER_MP_LIMB; + wsize = abs_usize - limb_cnt; + if (wsize <= 0) + wsize = 0; + else + { + if (w->alloc < wsize) + _mpz_realloc (w, wsize); + + wsize = mpn_rshift (w->d, u->d + limb_cnt, abs_usize - limb_cnt, + cnt % BITS_PER_MP_LIMB); + } + + w->size = (usize >= 0) ? wsize : -wsize; +} diff --git a/gnu/lib/libgmp/mpz_div_ui.c b/gnu/lib/libgmp/mpz_div_ui.c new file mode 100644 index 0000000..93c2552 --- /dev/null +++ b/gnu/lib/libgmp/mpz_div_ui.c @@ -0,0 +1,65 @@ +/* mpz_div_ui(quot, dividend, divisor_limb) + -- Divide DIVIDEND by DIVISOR_LIMB and store the result in QUOT. + +Copyright (C) 1991, 1992 Free Software Foundation, Inc. + +This file is part of the 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" +#include "gmp-impl.h" +#include "longlong.h" + +void +#ifdef __STDC__ +mpz_div_ui (MP_INT *quot, const MP_INT *dividend, unsigned long int divisor_limb) +#else +mpz_div_ui (quot, dividend, divisor_limb) + MP_INT *quot; + const MP_INT *dividend; + unsigned long int divisor_limb; +#endif +{ + mp_size sign_dividend; + mp_size dividend_size, quot_size; + mp_ptr dividend_ptr, quot_ptr; + + sign_dividend = dividend->size; + dividend_size = ABS (dividend->size); + + if (dividend_size == 0) + { + quot->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->alloc < dividend_size) + _mpz_realloc (quot, dividend_size); + + quot_ptr = quot->d; + dividend_ptr = dividend->d; + + mpn_divmod_1 (quot_ptr, dividend_ptr, dividend_size, divisor_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->size = sign_dividend >= 0 ? quot_size : -quot_size; +} diff --git a/gnu/lib/libgmp/mpz_dm.c b/gnu/lib/libgmp/mpz_dm.c new file mode 100644 index 0000000..26fda05 --- /dev/null +++ b/gnu/lib/libgmp/mpz_dm.c @@ -0,0 +1,38 @@ +/* mpz_divmod(quot,rem,dividend,divisor) -- Set QUOT to DIVIDEND/DIVISOR, + and REM to DIVIDEND mod DIVISOR. + +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" +#include "gmp-impl.h" +#include "longlong.h" + +void +#ifdef __STDC__ +mpz_divmod (MP_INT *quot, MP_INT *rem, const MP_INT *num, const MP_INT *den) +#else +mpz_divmod (quot, rem, num, den) + MP_INT *quot; + MP_INT *rem; + const MP_INT *num; + const MP_INT *den; +#endif + +#define COMPUTE_QUOTIENT +#include "mpz_dmincl.c" diff --git a/gnu/lib/libgmp/mpz_dm_ui.c b/gnu/lib/libgmp/mpz_dm_ui.c new file mode 100644 index 0000000..e8c3cf6 --- /dev/null +++ b/gnu/lib/libgmp/mpz_dm_ui.c @@ -0,0 +1,81 @@ +/* mpz_divmod_ui(quot,rem,dividend,short_divisor) -- + Set QUOT to DIVIDEND / SHORT_DIVISOR + and REM to DIVIDEND mod SHORT_DIVISOR. + +Copyright (C) 1991, 1992 Free Software Foundation, Inc. + +This file is part of the 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" +#include "gmp-impl.h" +#include "longlong.h" + +void +#ifdef __STDC__ +mpz_divmod_ui (MP_INT *quot, MP_INT *rem, + const MP_INT *dividend, unsigned long int divisor_limb) +#else +mpz_divmod_ui (quot, rem, dividend, divisor_limb) + MP_INT *quot; + MP_INT *rem; + const MP_INT *dividend; + unsigned long int divisor_limb; +#endif +{ + mp_size sign_dividend; + mp_size dividend_size, quot_size; + mp_ptr dividend_ptr, quot_ptr; + mp_limb remainder_limb; + + sign_dividend = dividend->size; + dividend_size = ABS (dividend->size); + + if (dividend_size == 0) + { + quot->size = 0; + rem->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->alloc < dividend_size) + _mpz_realloc (quot, dividend_size); + + quot_ptr = quot->d; + dividend_ptr = dividend->d; + + remainder_limb = mpn_divmod_1 (quot_ptr, + dividend_ptr, dividend_size, divisor_limb); + + if (remainder_limb == 0) + rem->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->size = sign_dividend >= 0 ? 1 : -1; + rem->d[0] = 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->size = sign_dividend >= 0 ? quot_size : -quot_size; +} diff --git a/gnu/lib/libgmp/mpz_dmincl.c b/gnu/lib/libgmp/mpz_dmincl.c new file mode 100644 index 0000000..dde7981 --- /dev/null +++ b/gnu/lib/libgmp/mpz_dmincl.c @@ -0,0 +1,172 @@ +/* mpz_dmincl.c -- include file for mpz_dm.c, mpz_mod.c, mdiv.c. + +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. */ + +/* THIS CODE IS OBSOLETE. IT WILL SOON BE REPLACED BY CLEANER CODE WITH + LESS MEMORY ALLOCATION OVERHEAD. */ + +/* 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 nsize = num->size; + mp_size dsize = den->size; + mp_size qsize, rsize; + mp_size sign_remainder = nsize; +#ifdef COMPUTE_QUOTIENT + mp_size sign_quotient = nsize ^ dsize; +#endif + unsigned normalization_steps; + + 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->alloc < rsize) + _mpz_realloc (rem, rsize); + + qsize = nsize - dsize + 1; /* qsize cannot be bigger than this. */ + if (qsize <= 0) + { +#ifdef COMPUTE_QUOTIENT + quot->size = 0; +#endif + if (num != rem) + { + rem->size = num->size; + MPN_COPY (rem->d, num->d, nsize); + } + return; + } + +#ifdef COMPUTE_QUOTIENT + if (quot->alloc < qsize) + _mpz_realloc (quot, qsize); + qp = quot->d; +#else + qp = (mp_ptr) alloca (qsize * BYTES_PER_MP_LIMB); +#endif + np = num->d; + dp = den->d; + rp = rem->d; + + /* Make sure quot and num are different. Otherwise the numerator + would be successively overwritten by the quotient digits. */ + if (qp == np) + { + np = (mp_ptr) alloca (nsize * BYTES_PER_MP_LIMB); + MPN_COPY (np, qp, nsize); + } + + 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 ndigit; + + /* 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) alloca (dsize * BYTES_PER_MP_LIMB); + (void) 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. */ + ndigit = mpn_lshift (rp, np, nsize, normalization_steps); + if (ndigit != 0) + { + rp[nsize] = ndigit; + rsize = nsize + 1; + } + else + rsize = nsize; + } + else + { +#ifdef COMPUTE_QUOTIENT + if (rem == den || quot == den) +#else + if (rem == den) +#endif + { + mp_ptr tp; + + tp = (mp_ptr) alloca (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; + } + + qsize = rsize - dsize + mpn_div (qp, rp, rsize, dp, dsize); + + rsize = dsize; + + /* Normalize the remainder. */ + while (rsize > 0) + { + if (rp[rsize - 1] != 0) + break; + rsize--; + } + + if (normalization_steps != 0) + rsize = mpn_rshift (rp, rp, rsize, normalization_steps); + + rem->size = (sign_remainder >= 0) ? rsize : -rsize; + +#ifdef COMPUTE_QUOTIENT + /* Normalize the quotient. We may have at most one leading + zero-word, so no loop is needed. */ + if (qsize > 0) + qsize -= (qp[qsize - 1] == 0); + + quot->size = (sign_quotient >= 0) ? qsize : -qsize; +#endif + + alloca (0); +} diff --git a/gnu/lib/libgmp/mpz_fac_ui.c b/gnu/lib/libgmp/mpz_fac_ui.c new file mode 100644 index 0000000..9cdc785 --- /dev/null +++ b/gnu/lib/libgmp/mpz_fac_ui.c @@ -0,0 +1,156 @@ +/* mpz_fac_ui(result, n) -- Set RESULT to N!. + +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. */ + +#ifdef DBG +#include +#endif + +#include "gmp.h" +#include "gmp-impl.h" +#include "longlong.h" + +void +#ifdef __STDC__ +mpz_fac_ui (MP_INT *result, unsigned long int n) +#else +mpz_fac_ui (result, n) + MP_INT *result; + unsigned long int n; +#endif +{ +#if SIMPLE_FAC + + /* Be silly. Just multiply the numbers in ascending order. O(n**2). */ + + mp_limb k; + + mpz_set_ui (result, (mp_limb) 1); + + 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 products 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.) */ + + mp_limb k; + mp_limb p1, p0, p; + + /* 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 + MP_INT 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, p, 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 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; + } + + /* 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_gcd.c b/gnu/lib/libgmp/mpz_gcd.c new file mode 100644 index 0000000..090c8c5 --- /dev/null +++ b/gnu/lib/libgmp/mpz_gcd.c @@ -0,0 +1,169 @@ +/* mpz_gcd -- Calculate the greatest common divisior of two integers. + +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" +#include "gmp-impl.h" +#include "longlong.h" + +#ifndef BERKELEY_MP +void +#ifdef __STDC__ +mpz_gcd (MP_INT *w, const MP_INT *u, const MP_INT *v) +#else +mpz_gcd (w, u, v) + MP_INT *w; + const MP_INT *u; + const MP_INT *v; +#endif +#else /* BERKELEY_MP */ +void +#ifdef __STDC__ +gcd (const MP_INT *u, const MP_INT *v, MP_INT *w) +#else +gcd (u, v, w) + const MP_INT *u; + const MP_INT *v; + MP_INT *w; +#endif +#endif /* BERKELEY_MP */ +{ + mp_size usize, vsize, wsize; + mp_ptr up_in, vp_in; + mp_ptr up, vp; + mp_ptr wp; + mp_size i; + mp_limb d; + int bcnt; + mp_size w_bcnt; + mp_limb cy_digit; + + usize = ABS (u->size); + vsize = ABS (v->size); + + /* GCD(0,v) == v. */ + if (usize == 0) + { + if (w->alloc < vsize) + _mpz_realloc (w, vsize); + + w->size = vsize; + MPN_COPY (w->d, v->d, vsize); + return; + } + + /* GCD(0,u) == u. */ + if (vsize == 0) + { + if (w->alloc < usize) + _mpz_realloc (w, usize); + + w->size = usize; + MPN_COPY (w->d, u->d, usize); + return; + } + + /* Make U odd by shifting it down as many bit positions as there + are zero bits. Put the result in temporary space. */ + up = (mp_ptr) alloca (usize * BYTES_PER_MP_LIMB); + up_in = u->d; + for (i = 0; (d = up_in[i]) == 0; i++) + ; + count_leading_zeros (bcnt, d & -d); + bcnt = BITS_PER_MP_LIMB - 1 - bcnt; + usize = mpn_rshift (up, up_in + i, usize - i, bcnt); + + bcnt += i * BITS_PER_MP_LIMB; + w_bcnt = bcnt; + + /* Make V odd by shifting it down as many bit positions as there + are zero bits. Put the result in temporary space. */ + vp = (mp_ptr) alloca (vsize * BYTES_PER_MP_LIMB); + vp_in = v->d; + for (i = 0; (d = vp_in[i]) == 0; i++) + ; + count_leading_zeros (bcnt, d & -d); + bcnt = BITS_PER_MP_LIMB - 1 - bcnt; + vsize = mpn_rshift (vp, vp_in + i, vsize - i, bcnt); + + /* W_BCNT is set to the minimum of the number of zero bits in U and V. + Thus it represents the number of common 2 factors. */ + bcnt += i * BITS_PER_MP_LIMB; + if (bcnt < w_bcnt) + w_bcnt = bcnt; + + for (;;) + { + int cmp; + + cmp = usize - vsize != 0 ? usize - vsize : mpn_cmp (up, vp, usize); + + /* If U and V have become equal, we have found the GCD. */ + if (cmp == 0) + break; + + if (cmp > 0) + { + /* Replace U by (U - V) >> cnt, with cnt being the least value + making U odd again. */ + + usize += mpn_sub (up, up, usize, vp, vsize); + for (i = 0; (d = up[i]) == 0; i++) + ; + count_leading_zeros (bcnt, d & -d); + bcnt = BITS_PER_MP_LIMB - 1 - bcnt; + usize = mpn_rshift (up, up + i, usize - i, bcnt); + } + else + { + /* Replace V by (V - U) >> cnt, with cnt being the least value + making V odd again. */ + + vsize += mpn_sub (vp, vp, vsize, up, usize); + for (i = 0; (d = vp[i]) == 0; i++) + ; + count_leading_zeros (bcnt, d & -d); + bcnt = BITS_PER_MP_LIMB - 1 - bcnt; + vsize = mpn_rshift (vp, vp + i, vsize - i, bcnt); + } + } + + /* GCD(U_IN, V_IN) now is U * 2**W_BCNT. */ + + wsize = usize + w_bcnt / BITS_PER_MP_LIMB + 1; + if (w->alloc < wsize) + _mpz_realloc (w, wsize); + + wp = w->d; + + MPN_ZERO (wp, w_bcnt / BITS_PER_MP_LIMB); + + cy_digit = mpn_lshift (wp + w_bcnt / BITS_PER_MP_LIMB, up, usize, + w_bcnt % BITS_PER_MP_LIMB); + wsize = usize + w_bcnt / BITS_PER_MP_LIMB; + if (cy_digit != 0) + { + wp[wsize] = cy_digit; + wsize++; + } + + w->size = wsize; + + alloca (0); +} diff --git a/gnu/lib/libgmp/mpz_gcdext.c b/gnu/lib/libgmp/mpz_gcdext.c new file mode 100644 index 0000000..183b9bd --- /dev/null +++ b/gnu/lib/libgmp/mpz_gcdext.c @@ -0,0 +1,80 @@ +/* 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 Free Software Foundation, Inc. + +This file is part of the 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" +#include "gmp-impl.h" + +/* Botch: SLOW! */ + +void +#ifdef __STDC__ +mpz_gcdext (MP_INT *g, MP_INT *s, MP_INT *t, const MP_INT *a, const MP_INT *b) +#else +mpz_gcdext (g, s, t, a, b) + MP_INT *g; + MP_INT *s; + MP_INT *t; + const MP_INT *a; + const MP_INT *b; +#endif +{ + MP_INT s0, s1, q, r, x, d0, d1; + + mpz_init_set_ui (&s0, 1); + mpz_init_set_ui (&s1, 0); + mpz_init (&q); + mpz_init (&r); + mpz_init (&x); + mpz_init_set (&d0, a); + mpz_init_set (&d1, b); + + while (d1.size != 0) + { + mpz_divmod (&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->size == 0) + t->size = 0; + else + mpz_div (t, &x, b); + } + mpz_set (s, &s0); + mpz_set (g, &d0); + + 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_si.c b/gnu/lib/libgmp/mpz_get_si.c new file mode 100644 index 0000000..9cddf4b --- /dev/null +++ b/gnu/lib/libgmp/mpz_get_si.c @@ -0,0 +1,40 @@ +/* mpz_get_si(integer) -- Return the least significant digit from INTEGER. + +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" +#include "gmp-impl.h" + +signed long int +#ifdef __STDC__ +mpz_get_si (const MP_INT *integer) +#else +mpz_get_si (integer) + const MP_INT *integer; +#endif +{ + mp_size size = integer->size; + + if (size > 0) + return integer->d[0] % ((mp_limb) 1 << (BITS_PER_MP_LIMB - 1)); + else if (size < 0) + return -(integer->d[0] % ((mp_limb) 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 0000000..ac5ee65 --- /dev/null +++ b/gnu/lib/libgmp/mpz_get_str.c @@ -0,0 +1,39 @@ +/* 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 Free Software Foundation, Inc. + +This file is part of the 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" +#include "gmp-impl.h" + +char * +#ifdef __STDC__ +mpz_get_str (char *str, int base, const MP_INT *m) +#else +mpz_get_str (str, base, m) + char *str; + int base; + const MP_INT *m; +#endif +{ + return _mpz_get_str (str, base, m); +} diff --git a/gnu/lib/libgmp/mpz_get_ui.c b/gnu/lib/libgmp/mpz_get_ui.c new file mode 100644 index 0000000..118f249 --- /dev/null +++ b/gnu/lib/libgmp/mpz_get_ui.c @@ -0,0 +1,36 @@ +/* mpz_get_ui(integer) -- Return the least significant digit from INTEGER. + +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" +#include "gmp-impl.h" + +unsigned long int +#ifdef __STDC__ +mpz_get_ui (const MP_INT *integer) +#else +mpz_get_ui (integer) + const MP_INT *integer; +#endif +{ + if (integer->size == 0) + return 0; + else + return integer->d[0]; +} diff --git a/gnu/lib/libgmp/mpz_init.c b/gnu/lib/libgmp/mpz_init.c new file mode 100644 index 0000000..5766a41 --- /dev/null +++ b/gnu/lib/libgmp/mpz_init.c @@ -0,0 +1,35 @@ +/* mpz_init() -- Make a new multiple precision number with value 0. + +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" +#include "gmp-impl.h" + +void +#ifdef __STDC__ +mpz_init (MP_INT *x) +#else +mpz_init (x) + MP_INT *x; +#endif +{ + x->alloc = 1; + x->d = (mp_ptr) (*_mp_allocate_func) (BYTES_PER_MP_LIMB * x->alloc); + x->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 0000000..576f4b6 --- /dev/null +++ b/gnu/lib/libgmp/mpz_inp_raw.c @@ -0,0 +1,72 @@ +/* mpz_inp_raw -- Input a MP_INT in raw, but endianess, and wordsize + independent format (as output by mpz_out_raw). + +Copyright (C) 1991, 1992 Free Software Foundation, Inc. + +This file is part of the 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 + +#include "gmp.h" +#include "gmp-impl.h" + +void +#ifdef __STDC__ +mpz_inp_raw (MP_INT *x, FILE *file) +#else +mpz_inp_raw (x, file) + MP_INT *x; + FILE *file; +#endif +{ + int i; + mp_size s; + mp_size xsize; + mp_ptr xp; + unsigned int c; + mp_limb x_digit; + mp_size x_index; + + xsize = 0; + for (i = 4 - 1; i >= 0; i--) + { + c = fgetc (file); + xsize = (xsize << BITS_PER_CHAR) | c; + } + + /* ??? Sign extend xsize for non-32 bit machines? */ + + x_index = (ABS (xsize) + BYTES_PER_MP_LIMB - 1) / BYTES_PER_MP_LIMB - 1; + + if (x->alloc < x_index) + _mpz_realloc (x, x_index); + + xp = x->d; + x->size = xsize / BYTES_PER_MP_LIMB; + x_digit = 0; + for (s = ABS (xsize) - 1; s >= 0; s--) + { + i = s % BYTES_PER_MP_LIMB; + c = fgetc (file); + x_digit = (x_digit << BITS_PER_CHAR) | c; + if (i == 0) + { + xp[x_index--] = x_digit; + x_digit = 0; + } + } +} diff --git a/gnu/lib/libgmp/mpz_inp_str.c b/gnu/lib/libgmp/mpz_inp_str.c new file mode 100644 index 0000000..a775996 --- /dev/null +++ b/gnu/lib/libgmp/mpz_inp_str.c @@ -0,0 +1,105 @@ +/* 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 Free Software Foundation, Inc. + +This file is part of the 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 +#include +#include "gmp.h" +#include "gmp-impl.h" + +static int +char_ok_for_base (c, base) + int c; + int base; +{ + if (isdigit (c)) + return (unsigned) c - '0' < base; + if (islower (c)) + return (unsigned) c - 'a' + 10 < base; + if (isupper (c)) + return (unsigned) c - 'A' + 10 < base; + + return 0; +} + +void +#ifdef __STDC__ +mpz_inp_str (MP_INT *dest, FILE *stream, int base) +#else +mpz_inp_str (dest, stream, base) + MP_INT *dest; + FILE *stream; + int base; +#endif +{ + char *str; + size_t str_size; + size_t i; + int c; + int negative = 0; + + str_size = 100; + str = (char *) (*_mp_allocate_func) (str_size); + + c = getc (stream); + if (c == '-') + { + negative = 1; + c = getc (stream); + } + + /* 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); + if (c == 'x' || c == 'X') + { + base = 16; + c = getc (stream); + } + } + } + + for (i = 0; char_ok_for_base (c, base); i++) + { + if (i >= str_size) + { + size_t old_str_size = str_size; + str_size = str_size * 3 / 2; + str = (char *) (*_mp_reallocate_func) (str, old_str_size, str_size); + } + str[i] = c; + c = getc (stream); + } + + ungetc (c, stream); + + str[i] = 0; + _mpz_set_str (dest, str, base); + if (negative) + dest->size = -dest->size; + + (*_mp_free_func) (str, str_size); +} diff --git a/gnu/lib/libgmp/mpz_ior.c b/gnu/lib/libgmp/mpz_ior.c new file mode 100644 index 0000000..bf7b1c1 --- /dev/null +++ b/gnu/lib/libgmp/mpz_ior.c @@ -0,0 +1,242 @@ +/* mpz_ior -- Logical inclusive or. + +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" +#include "gmp-impl.h" + +#define min(l,o) ((l) < (o) ? (l) : (o)) +#define max(h,i) ((h) > (i) ? (h) : (i)) + +void +#ifdef __STDC__ +mpz_ior (MP_INT *res, const MP_INT *op1, const MP_INT *op2) +#else +mpz_ior (res, op1, op2) + MP_INT *res; + const MP_INT *op1; + const MP_INT *op2; +#endif +{ + mp_srcptr op1_ptr, op2_ptr; + mp_size op1_size, op2_size; + mp_ptr res_ptr; + mp_size res_size; + mp_size i; + + op1_size = op1->size; + op2_size = op2->size; + + op1_ptr = op1->d; + op2_ptr = op2->d; + res_ptr = res->d; + + if (op1_size >= 0) + { + if (op2_size >= 0) + { + if (op1_size >= op2_size) + { + if (res->alloc < op1_size) + { + _mpz_realloc (res, op1_size); + op1_ptr = op1->d; + op2_ptr = op2->d; + res_ptr = res->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->alloc < op2_size) + { + _mpz_realloc (res, op2_size); + op1_ptr = op1->d; + op2_ptr = op2->d; + res_ptr = res->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->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 cy; + mp_limb one = 1; + + /* 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) alloca (op1_size * BYTES_PER_MP_LIMB); + op1_size += mpn_sub (opx, op1_ptr, op1_size, &one, 1); + op1_ptr = opx; + + opx = (mp_ptr) alloca (op2_size * BYTES_PER_MP_LIMB); + op2_size += mpn_sub (opx, op2_ptr, op2_size, &one, 1); + op2_ptr = opx; + + if (res->alloc < res_size) + { + _mpz_realloc (res, res_size); + res_ptr = res->d; + /* Don't re-read OP1_PTR and OP2_PTR. They point to + temporary space--never to the space RES->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; + + /* Second loop computes the real result. */ + for (i = res_size - 1; i >= 0; i--) + res_ptr[i] = op1_ptr[i] & op2_ptr[i]; + + if (res_size != 0) + { + cy = mpn_add (res_ptr, res_ptr, res_size, &one, 1); + if (cy) + { + res_ptr[res_size] = cy; + res_size++; + } + } + else + { + res_ptr[0] = 1; + res_size = 1; + } + + res->size = -res_size; + return; + } + else + { + /* We should compute -OP1 | OP2. Swap OP1 and OP2 and fall + through to the code that handles OP1 | -OP2. */ + {const MP_INT *t = op1; op1 = op2; op2 = t;} + {mp_srcptr t = op1_ptr; op1_ptr = op2_ptr; op2_ptr = t;} + {mp_size t = op1_size; op1_size = op2_size; op2_size = t;} + } + } + + { + mp_ptr opx; + mp_limb cy; + mp_limb one = 1; + mp_size res_alloc; + + /* 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) alloca (op2_size * BYTES_PER_MP_LIMB); + op2_size += mpn_sub (opx, op2_ptr, op2_size, &one, 1); + op2_ptr = opx; + + if (res->alloc < res_alloc) + { + _mpz_realloc (res, res_alloc); + op1_ptr = op1->d; + res_ptr = res->d; + /* Don't re-read OP2_PTR. It points to temporary space--never + to the space RES->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; + } + 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); + } + + /* Second loop computes the real result. */ + for (i = res_size - 1; i >= 0; i--) + res_ptr[i] = ~op1_ptr[i] & op2_ptr[i]; + + if (res_size != 0) + { + cy = mpn_add (res_ptr, res_ptr, res_size, &one, 1); + if (cy) + { + res_ptr[res_size] = cy; + res_size++; + } + } + else + { + res_ptr[0] = 1; + res_size = 1; + } + + res->size = -res_size; + alloca (0); + return; + } +} diff --git a/gnu/lib/libgmp/mpz_iset.c b/gnu/lib/libgmp/mpz_iset.c new file mode 100644 index 0000000..53c9d3e --- /dev/null +++ b/gnu/lib/libgmp/mpz_iset.c @@ -0,0 +1,45 @@ +/* mpz_init_set (src_integer) -- Make a new multiple precision number with + a value copied from SRC_INTEGER. + +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" +#include "gmp-impl.h" + +void +#ifdef __STDC__ +mpz_init_set (MP_INT *x, const MP_INT *src) +#else +mpz_init_set (x, src) + MP_INT *x; + const MP_INT *src; +#endif +{ + mp_size size; + mp_size abs_size; + + size = src->size; + abs_size = ABS (size); + + x->alloc = abs_size == 0 ? 1 : abs_size; + x->d = (mp_ptr) (*_mp_allocate_func) (BYTES_PER_MP_LIMB * x->alloc); + + MPN_COPY (x->d, src->d, abs_size); + x->size = size; +} diff --git a/gnu/lib/libgmp/mpz_iset_si.c b/gnu/lib/libgmp/mpz_iset_si.c new file mode 100644 index 0000000..66bbda1 --- /dev/null +++ b/gnu/lib/libgmp/mpz_iset_si.c @@ -0,0 +1,48 @@ +/* mpz_init_set_si(val) -- Make a new multiple precision number with + value val. + +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" +#include "gmp-impl.h" + +void +#ifdef __STDC__ +mpz_init_set_si (MP_INT *x, signed long int val) +#else +mpz_init_set_si (x, val) + MP_INT *x; + signed long int val; +#endif +{ + x->alloc = 1; + x->d = (mp_ptr) (*_mp_allocate_func) (BYTES_PER_MP_LIMB * x->alloc); + if (val > 0) + { + x->d[0] = val; + x->size = 1; + } + else if (val < 0) + { + x->d[0] = -val; + x->size = -1; + } + else + x->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 0000000..b110b11 --- /dev/null +++ b/gnu/lib/libgmp/mpz_iset_str.c @@ -0,0 +1,42 @@ +/* mpz_init_set_str(mpz, string, base) -- Initialize MPZ and set it to the + value in the \0-terminated ascii string STRING in base BASE. Return 0 if + the string was accepted, -1 if an error occured. 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 Free Software Foundation, Inc. + +This file is part of the 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" +#include "gmp-impl.h" + +int +#ifdef __STDC__ +mpz_init_set_str (MP_INT *x, const char *str, int base) +#else +mpz_init_set_str (x, str, base) + MP_INT *x; + const char *str; + int base; +#endif +{ + x->alloc = 1; + x->d = (mp_ptr) (*_mp_allocate_func) (BYTES_PER_MP_LIMB * x->alloc); + + 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 0000000..bd52640 --- /dev/null +++ b/gnu/lib/libgmp/mpz_iset_ui.c @@ -0,0 +1,43 @@ +/* mpz_init_set_ui(val) -- Make a new multiple precision number with + value val. + +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" +#include "gmp-impl.h" + +void +#ifdef __STDC__ +mpz_init_set_ui (MP_INT *x, unsigned long int val) +#else +mpz_init_set_ui (x, val) + MP_INT *x; + unsigned long int val; +#endif +{ + x->alloc = 1; + x->d = (mp_ptr) (*_mp_allocate_func) (BYTES_PER_MP_LIMB * x->alloc); + if (val > 0) + { + x->d[0] = val; + x->size = 1; + } + else + x->size = 0; +} diff --git a/gnu/lib/libgmp/mpz_mdiv.c b/gnu/lib/libgmp/mpz_mdiv.c new file mode 100644 index 0000000..bb8b9de --- /dev/null +++ b/gnu/lib/libgmp/mpz_mdiv.c @@ -0,0 +1,52 @@ +/* mpz_mdiv -- Mathematical DIVision and MODulo, i.e. division that rounds + the quotient towards -infinity. + +Copyright (C) 1991, 1992 Free Software Foundation, Inc. + +This file is part of the 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" +#include "gmp-impl.h" + +void +#ifdef __STDC__ +mpz_mdiv (MP_INT *quot, + const MP_INT *dividend, const MP_INT *divisor) +#else +mpz_mdiv (quot, dividend, divisor) + MP_INT *quot; + const MP_INT *dividend; + const MP_INT *divisor; +#endif +{ + if ((dividend->size ^ divisor->size) >= 0) + { + /* When the dividend and the divisor has same sign, this function + gives same result as mpz_div. */ + mpz_div (quot, dividend, divisor); + } + else + { + MP_INT rem; + + MPZ_TMP_INIT (&rem, 1 + ABS (dividend->size)); + + mpz_divmod (quot, &rem, dividend, divisor); + if (rem.size != 0) + mpz_sub_ui (quot, quot, 1); + } +} diff --git a/gnu/lib/libgmp/mpz_mdiv_ui.c b/gnu/lib/libgmp/mpz_mdiv_ui.c new file mode 100644 index 0000000..fbf127f --- /dev/null +++ b/gnu/lib/libgmp/mpz_mdiv_ui.c @@ -0,0 +1,43 @@ +/* mpz_mdiv_ui -- Mathematical DIVision and MODulo, i.e. division that rounds + the quotient towards -infinity. + +Copyright (C) 1991, 1992 Free Software Foundation, Inc. + +This file is part of the 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" +#include "gmp-impl.h" + +void +#ifdef __STDC__ +mpz_mdiv_ui (MP_INT *quot, + const MP_INT *dividend, unsigned long int divisor) +#else +mpz_mdiv_ui (quot, dividend, divisor) + MP_INT *quot; + const MP_INT *dividend; + unsigned long int divisor; +#endif +{ + MP_INT rem; + + MPZ_TMP_INIT (&rem, 1 + ABS (dividend->size)); + + mpz_divmod_ui (quot, &rem, dividend, divisor); + if (rem.size < 0) + mpz_sub_ui (quot, quot, 1); +} diff --git a/gnu/lib/libgmp/mpz_mdm.c b/gnu/lib/libgmp/mpz_mdm.c new file mode 100644 index 0000000..0844643 --- /dev/null +++ b/gnu/lib/libgmp/mpz_mdm.c @@ -0,0 +1,64 @@ +/* mpz_mdivmod -- Mathematical DIVision and MODulo, i.e. division that rounds + the quotient towards -infinity, and with the remainder non-negative. + +Copyright (C) 1991, 1992 Free Software Foundation, Inc. + +This file is part of the 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" +#include "gmp-impl.h" + +void +#ifdef __STDC__ +mpz_mdivmod (MP_INT *quot, MP_INT *rem, + const MP_INT *dividend, const MP_INT *divisor) +#else +mpz_mdivmod (quot, rem, dividend, divisor) + MP_INT *quot; + MP_INT *rem; + const MP_INT *dividend; + const MP_INT *divisor; +#endif +{ + if ((dividend->size ^ divisor->size) >= 0) + { + /* When the dividend and the divisor has same sign, this function + gives same result as mpz_divmod. */ + mpz_divmod (quot, rem, dividend, divisor); + } + else + { + MP_INT temp_divisor; /* N.B.: lives until function returns! */ + + /* 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_divmod (quot, rem, dividend, divisor); + if (rem->size != 0) + { + mpz_sub_ui (quot, quot, 1); + mpz_add (rem, rem, divisor); + } + } +} diff --git a/gnu/lib/libgmp/mpz_mdm_ui.c b/gnu/lib/libgmp/mpz_mdm_ui.c new file mode 100644 index 0000000..cf41912 --- /dev/null +++ b/gnu/lib/libgmp/mpz_mdm_ui.c @@ -0,0 +1,58 @@ +/* mpz_mdivmod -- Mathematical DIVision and MODulo, i.e. division that rounds + the quotient towards -infinity, and with the remainder non-negative. + +Copyright (C) 1991, 1992 Free Software Foundation, Inc. + +This file is part of the 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" +#include "gmp-impl.h" + +unsigned long int +#ifdef __STDC__ +mpz_mdivmod_ui (MP_INT *quot, MP_INT *rem, + const MP_INT *dividend, unsigned long int divisor) +#else +mpz_mdivmod_ui (quot, rem, dividend, divisor) + MP_INT *quot; + MP_INT *rem; + const MP_INT *dividend; + unsigned long int divisor; +#endif +{ + MP_INT temp_rem; /* N.B.: lives until function returns! */ + + /* If the user doesn't want the remainder to be stored in an integer + object, allocate a scratch variable for it. */ + if (rem == NULL) + { + MPZ_TMP_INIT (&temp_rem, 1 + ABS (dividend->size)); + rem = &temp_rem; + } + + mpz_divmod_ui (quot, rem, dividend, divisor); + + if (rem->size < 0) + { + mpz_sub_ui (quot, quot, 1); + mpz_add_ui (rem, rem, divisor); + } + + if (rem->size == 0) + return 0; + return rem->d[0]; +} diff --git a/gnu/lib/libgmp/mpz_mmod.c b/gnu/lib/libgmp/mpz_mmod.c new file mode 100644 index 0000000..c1d3d3f --- /dev/null +++ b/gnu/lib/libgmp/mpz_mmod.c @@ -0,0 +1,60 @@ +/* mpz_mmod -- Mathematical MODulo, i.e. with the remainder + non-negative. + +Copyright (C) 1991, 1992 Free Software Foundation, Inc. + +This file is part of the 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" +#include "gmp-impl.h" + +void +#ifdef __STDC__ +mpz_mmod (MP_INT *rem, + const MP_INT *dividend, const MP_INT *divisor) +#else +mpz_mmod (rem, dividend, divisor) + MP_INT *rem; + const MP_INT *dividend; + const MP_INT *divisor; +#endif +{ + if ((dividend->size ^ divisor->size) >= 0) + { + /* When the dividend and the divisor has same sign, this function + gives same result as mpz_mod. */ + mpz_mod (rem, dividend, divisor); + } + else + { + MP_INT temp_divisor; /* N.B.: lives until function returns! */ + + /* 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_mod (rem, dividend, divisor); + if (rem->size != 0) + mpz_add (rem, rem, divisor); + } +} diff --git a/gnu/lib/libgmp/mpz_mmod_ui.c b/gnu/lib/libgmp/mpz_mmod_ui.c new file mode 100644 index 0000000..0fdbee2 --- /dev/null +++ b/gnu/lib/libgmp/mpz_mmod_ui.c @@ -0,0 +1,52 @@ +/* mpz_mmod -- Mathematical MODulo, i.e. with the remainder + non-negative. + +Copyright (C) 1991, 1992 Free Software Foundation, Inc. + +This file is part of the 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" +#include "gmp-impl.h" + +unsigned long int +#ifdef __STDC__ +mpz_mmod_ui (MP_INT *rem, + const MP_INT *dividend, unsigned long int divisor) +#else +mpz_mmod_ui (rem, dividend, divisor) + MP_INT *rem; + const MP_INT *dividend; + unsigned long int divisor; +#endif +{ + MP_INT temp_rem; /* N.B.: lives until function returns! */ + + if (rem == NULL) + { + MPZ_TMP_INIT (&temp_rem, 1 + ABS (dividend->size)); + rem = &temp_rem; + } + + mpz_mod_ui (rem, dividend, divisor); + + if (rem->size < 0) + mpz_add_ui (rem, rem, divisor); + + if (rem->size == 0) + return 0; + return rem->d[0]; +} diff --git a/gnu/lib/libgmp/mpz_mod.c b/gnu/lib/libgmp/mpz_mod.c new file mode 100644 index 0000000..276bee0 --- /dev/null +++ b/gnu/lib/libgmp/mpz_mod.c @@ -0,0 +1,36 @@ +/* mpz_mod(rem, dividend, divisor) -- Set REM to DIVIDEND mod DIVISOR. + +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" +#include "gmp-impl.h" +#include "longlong.h" + +void +#ifdef __STDC__ +mpz_mod (MP_INT *rem, const MP_INT *num, const MP_INT *den) +#else +mpz_mod (rem, num, den) + MP_INT *rem; + const MP_INT *num; + const MP_INT *den; +#endif + +#undef COMPUTE_QUOTIENT +#include "mpz_dmincl.c" diff --git a/gnu/lib/libgmp/mpz_mod_2exp.c b/gnu/lib/libgmp/mpz_mod_2exp.c new file mode 100644 index 0000000..696acd4 --- /dev/null +++ b/gnu/lib/libgmp/mpz_mod_2exp.c @@ -0,0 +1,82 @@ +/* mpz_mod_2exp -- divide a MP_INT by 2**n and produce a remainder. + +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" +#include "gmp-impl.h" + +void +#ifdef __STDC__ +mpz_mod_2exp (MP_INT *res, const MP_INT *in, unsigned long int cnt) +#else +mpz_mod_2exp (res, in, cnt) + MP_INT *res; + const MP_INT *in; + unsigned long int cnt; +#endif +{ + mp_size in_size = ABS (in->size); + mp_size res_size; + mp_size limb_cnt = cnt / BITS_PER_MP_LIMB; + mp_srcptr in_ptr = in->d; + + if (in_size > limb_cnt) + { + /* The input operand is (probably) greater than 2**CNT. */ + mp_limb x; + + x = in_ptr[limb_cnt] & (((mp_limb) 1 << cnt % BITS_PER_MP_LIMB) - 1); + if (x != 0) + { + res_size = limb_cnt + 1; + if (res->alloc < res_size) + _mpz_realloc (res, res_size); + + res->d[limb_cnt] = x; + } + else + { + mp_size i; + + for (i = limb_cnt - 1; i >= 0; i--) + if (in_ptr[i] != 0) + break; + res_size = i + 1; + + if (res->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->alloc < res_size) + _mpz_realloc (res, res_size); + + limb_cnt = res_size; + } + + if (res != in) + MPN_COPY (res->d, in->d, limb_cnt); + res->size = (in->size >= 0) ? res_size : -res_size; +} diff --git a/gnu/lib/libgmp/mpz_mod_ui.c b/gnu/lib/libgmp/mpz_mod_ui.c new file mode 100644 index 0000000..35a4d7d --- /dev/null +++ b/gnu/lib/libgmp/mpz_mod_ui.c @@ -0,0 +1,65 @@ +/* mpz_mod_ui(rem, dividend, divisor_limb) + -- Set REM to DIVDEND mod DIVISOR_LIMB. + +Copyright (C) 1991, 1992 Free Software Foundation, Inc. + +This file is part of the 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" +#include "gmp-impl.h" +#include "longlong.h" + +void +#ifdef __STDC__ +mpz_mod_ui (MP_INT *rem, const MP_INT *dividend, + unsigned long int divisor_limb) +#else +mpz_mod_ui (rem, dividend, divisor_limb) + MP_INT *rem; + const MP_INT *dividend; + unsigned long int divisor_limb; +#endif +{ + mp_size sign_dividend; + mp_size dividend_size; + mp_limb remainder_limb; + + sign_dividend = dividend->size; + dividend_size = ABS (dividend->size); + + if (dividend_size == 0) + { + rem->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->d, dividend_size, divisor_limb); + + if (remainder_limb == 0) + rem->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->size = sign_dividend >= 0 ? 1 : -1; + rem->d[0] = remainder_limb; + } +} diff --git a/gnu/lib/libgmp/mpz_mul.c b/gnu/lib/libgmp/mpz_mul.c new file mode 100644 index 0000000..7bb2b90 --- /dev/null +++ b/gnu/lib/libgmp/mpz_mul.c @@ -0,0 +1,114 @@ +/* mpz_mul -- Multiply two integers. + +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" +#include "gmp-impl.h" + +#ifndef BERKELEY_MP +void +#ifdef __STDC__ +mpz_mul (MP_INT *w, const MP_INT *u, const MP_INT *v) +#else +mpz_mul (w, u, v) + MP_INT *w; + const MP_INT *u; + const MP_INT *v; +#endif +#else /* BERKELEY_MP */ +void +#ifdef __STDC__ +mult (const MP_INT *u, const MP_INT *v, MP_INT *w) +#else +mult (u, v, w) + const MP_INT *u; + const MP_INT *v; + MP_INT *w; +#endif +#endif /* BERKELEY_MP */ +{ + mp_size usize = u->size; + mp_size vsize = v->size; + mp_size wsize; + mp_size sign_product; + mp_ptr up, vp; + mp_ptr wp; + mp_ptr free_me = NULL; + size_t free_me_size; + + sign_product = usize ^ vsize; + usize = ABS (usize); + vsize = ABS (vsize); + + if (usize < vsize) + { + /* Swap U and V. */ + {const MP_INT *t = u; u = v; v = t;} + {mp_size t = usize; usize = vsize; vsize = t;} + } + + up = u->d; + vp = v->d; + wp = w->d; + + /* Ensure W has space enough to store the result. */ + wsize = usize + vsize; + if (w->alloc < wsize) + { + if (wp == up || wp == vp) + { + free_me = wp; + free_me_size = w->alloc; + } + else + (*_mp_free_func) (wp, w->alloc * BYTES_PER_MP_LIMB); + + w->alloc = wsize; + wp = (mp_ptr) (*_mp_allocate_func) (wsize * BYTES_PER_MP_LIMB); + w->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) alloca (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) alloca (vsize * BYTES_PER_MP_LIMB); + /* Copy to the temporary space. */ + MPN_COPY (vp, wp, vsize); + } + } + + wsize = mpn_mul (wp, up, usize, vp, vsize); + w->size = sign_product < 0 ? -wsize : wsize; + if (free_me != NULL) + (*_mp_free_func) (free_me, free_me_size * BYTES_PER_MP_LIMB); + + alloca (0); +} diff --git a/gnu/lib/libgmp/mpz_mul_2exp.c b/gnu/lib/libgmp/mpz_mul_2exp.c new file mode 100644 index 0000000..1a9767a --- /dev/null +++ b/gnu/lib/libgmp/mpz_mul_2exp.c @@ -0,0 +1,68 @@ +/* mpz_mul_2exp -- Multiply a bignum by 2**CNT + +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" +#include "gmp-impl.h" + +void +#ifdef __STDC__ +mpz_mul_2exp (MP_INT *w, const MP_INT *u, unsigned long int cnt) +#else +mpz_mul_2exp (w, u, cnt) + MP_INT *w; + const MP_INT *u; + unsigned long int cnt; +#endif +{ + mp_size usize = u->size; + mp_size abs_usize = ABS (usize); + mp_size wsize; + mp_size limb_cnt; + mp_ptr wp; + mp_limb wdigit; + + if (usize == 0) + { + w->size = 0; + return; + } + + limb_cnt = cnt / BITS_PER_MP_LIMB; + wsize = abs_usize + limb_cnt + 1; + if (w->alloc < wsize) + _mpz_realloc (w, wsize); + wp = w->d; + + wdigit = mpn_lshift (wp + limb_cnt, u->d, abs_usize, + cnt % BITS_PER_MP_LIMB); + wsize = abs_usize + limb_cnt; + + if (wdigit != 0) + { + wp[wsize] = wdigit; + wsize++; + } + + /* Zero all whole digits at low end. Do it here and not before calling + mpn_lshift, not to loose for U == W. */ + MPN_ZERO (wp, limb_cnt); + + w->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 0000000..f35eb4b --- /dev/null +++ b/gnu/lib/libgmp/mpz_mul_ui.c @@ -0,0 +1,78 @@ +/* mpz_mul_ui(product, multiplier, small_multiplicand) -- Set + PRODUCT to MULTIPLICATOR times SMALL_MULTIPLICAND. + +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" +#include "gmp-impl.h" +#include "longlong.h" + +void +#ifdef __STDC__ +mpz_mul_ui (MP_INT *prod, const MP_INT *mult, + unsigned long int small_mult) +#else +mpz_mul_ui (prod, mult, small_mult) + MP_INT *prod; + const MP_INT *mult; + unsigned long int small_mult; +#endif +{ + mp_size mult_size = mult->size; + mp_size sign_product = mult_size; + mp_size i; + mp_limb cy; + mp_size prod_size; + mp_srcptr mult_ptr; + mp_ptr prod_ptr; + + mult_size = ABS (mult_size); + + if (mult_size == 0 || small_mult == 0) + { + prod->size = 0; + return; + } + + prod_size = mult_size + 1; + if (prod->alloc < prod_size) + _mpz_realloc (prod, prod_size); + + mult_ptr = mult->d; + prod_ptr = prod->d; + + cy = 0; + for (i = 0; i < mult_size; i++) + { + mp_limb p1, p0; + umul_ppmm (p1, p0, small_mult, mult_ptr[i]); + p0 += cy; + cy = p1 + (p0 < cy); + prod_ptr[i] = p0; + } + + prod_size = mult_size; + if (cy != 0) + { + prod_ptr[mult_size] = cy; + prod_size++; + } + + prod->size = sign_product > 0 ? prod_size : -prod_size; +} diff --git a/gnu/lib/libgmp/mpz_neg.c b/gnu/lib/libgmp/mpz_neg.c new file mode 100644 index 0000000..560077f --- /dev/null +++ b/gnu/lib/libgmp/mpz_neg.c @@ -0,0 +1,46 @@ +/* mpz_neg(MP_INT *dst, MP_INT *src) -- Assign the negated value of SRC to DST. + +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" +#include "gmp-impl.h" + +void +#ifdef __STDC__ +mpz_neg (MP_INT *dst, const MP_INT *src) +#else +mpz_neg (dst, src) + MP_INT *dst; + const MP_INT *src; +#endif +{ + mp_size src_size = src->size; + + if (src != dst) + { + mp_size abs_src_size = ABS (src_size); + + if (dst->alloc < abs_src_size) + _mpz_realloc (dst, abs_src_size); + + MPN_COPY (dst->d, src->d, abs_src_size); + } + + dst->size = -src_size; +} diff --git a/gnu/lib/libgmp/mpz_out_raw.c b/gnu/lib/libgmp/mpz_out_raw.c new file mode 100644 index 0000000..27d425c --- /dev/null +++ b/gnu/lib/libgmp/mpz_out_raw.c @@ -0,0 +1,55 @@ +/* mpz_out_raw -- Output a MP_INT in raw, but endianess-independent format. + +Copyright (C) 1991, 1992 Free Software Foundation, Inc. + +This file is part of the 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 + +#include "gmp.h" +#include "gmp-impl.h" + +void +#ifdef __STDC__ +mpz_out_raw (FILE *file, const MP_INT *x) +#else +mpz_out_raw (file, x) + FILE *file; + const MP_INT *x; +#endif +{ + int i; + mp_size s; + mp_size xsize = x->size; + mp_srcptr xp = x->d; + mp_size out_size = xsize * BYTES_PER_MP_LIMB; + + /* Make the size 4 bytes on all machines, to make the format portable. */ + for (i = 4 - 1; i >= 0; i--) + fputc ((out_size >> (i * BITS_PER_CHAR)) % (1 << BITS_PER_CHAR), file); + + /* Output from the most significant digit to the least significant digit, + with each digit also output in decreasing significance order. */ + for (s = ABS (xsize) - 1; s >= 0; s--) + { + mp_limb x_digit; + + x_digit = xp[s]; + for (i = BYTES_PER_MP_LIMB - 1; i >= 0; i--) + fputc ((x_digit >> (i * BITS_PER_CHAR)) % (1 << BITS_PER_CHAR), file); + } +} diff --git a/gnu/lib/libgmp/mpz_out_str.c b/gnu/lib/libgmp/mpz_out_str.c new file mode 100644 index 0000000..8e4d08e --- /dev/null +++ b/gnu/lib/libgmp/mpz_out_str.c @@ -0,0 +1,45 @@ +/* mpz_out_str(stream, base, integer) -- Output to STREAM the multi prec. + integer INTEGER in base BASE. + +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 +#include "gmp.h" +#include "gmp-impl.h" + +void +#ifdef __STDC__ +mpz_out_str (FILE *stream, int base, const MP_INT *x) +#else +mpz_out_str (stream, base, x) + FILE *stream; + int base; + const MP_INT *x; +#endif +{ + char *str; + size_t str_size; + + str_size = ((size_t) (ABS (x->size) * BITS_PER_MP_LIMB + * __mp_bases[ABS (base)].chars_per_bit_exactly)) + 3; + str = (char *) alloca (str_size); + _mpz_get_str (str, base, x); + fputs (str, stream); + alloca (0); +} diff --git a/gnu/lib/libgmp/mpz_perfsqr.c b/gnu/lib/libgmp/mpz_perfsqr.c new file mode 100644 index 0000000..4f14c06 --- /dev/null +++ b/gnu/lib/libgmp/mpz_perfsqr.c @@ -0,0 +1,118 @@ +/* mpz_perfect_square_p(arg) -- Return non-zero if ARG is a pefect square, + zero otherwise. + +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" +#include "gmp-impl.h" +#include "longlong.h" + +#if BITS_PER_MP_LIMB == 32 +static unsigned int primes[] = {3, 5, 7, 11, 13, 17, 19, 23, 29}; +static unsigned long int residue_map[] = +{0x3, 0x13, 0x17, 0x23b, 0x161b, 0x1a317, 0x30af3, 0x5335f, 0x13d122f3}; + +#define PP 0xC0CFD797L /* 3 x 5 x 7 x 11 x 13 x ... x 29 */ +#endif + +/* sq_res_0x100[x mod 0x100] == 1 iff x mod 0x100 is a quadratic residue + modulo 0x100. */ +static char 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 +#ifdef __STDC__ +mpz_perfect_square_p (const MP_INT *a) +#else +mpz_perfect_square_p (a) + const MP_INT *a; +#endif +{ + mp_limb n1, n0; + mp_size i; + mp_size asize = a->size; + mp_srcptr aptr = a->d; + mp_limb rem; + mp_ptr root_ptr; + + /* No negative numbers are perfect squares. */ + if (asize < 0) + return 0; + + /* The first test excludes 55/64 (85.9%) of the perfect square candidates + in O(1) time. */ + if (sq_res_0x100[aptr[0] % 0x100] == 0) + return 0; + +#if BITS_PER_MP_LIMB == 32 + /* The second test excludes 30652543/30808063 (99.5%) of the remaining + perfect square candidates in O(n) time. */ + + /* Firstly, compute REM = A mod PP. */ + n1 = aptr[asize - 1]; + if (n1 >= PP) + { + n1 = 0; + i = asize - 1; + } + else + i = asize - 2; + + for (; i >= 0; i--) + { + mp_limb dummy; + + n0 = aptr[i]; + udiv_qrnnd (dummy, n1, n1, n0, PP); + } + rem = n1; + + /* We have A mod PP in REM. Now decide if REM is a quadratic residue + modulo the factors in PP. */ + for (i = 0; i < (sizeof primes) / sizeof (int); i++) + { + unsigned int p; + + p = primes[i]; + rem %= p; + if ((residue_map[i] & (1L << rem)) == 0) + return 0; + } +#endif + + /* 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) alloca ((asize + 1) / 2 * BYTES_PER_MP_LIMB); + + /* Iff mpn_sqrt returns zero, the square is perfect. */ + { + int retval = !mpn_sqrt (root_ptr, NULL, aptr, asize); + alloca (0); + return retval; + } +} diff --git a/gnu/lib/libgmp/mpz_pow_ui.c b/gnu/lib/libgmp/mpz_pow_ui.c new file mode 100644 index 0000000..85ba720 --- /dev/null +++ b/gnu/lib/libgmp/mpz_pow_ui.c @@ -0,0 +1,110 @@ +/* mpz_pow_ui(res, base, exp) -- Set RES to BASE**EXP. + +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" +#include "gmp-impl.h" +#include "longlong.h" + +#ifndef BERKELEY_MP +void +#ifdef __STDC__ +mpz_pow_ui (MP_INT *r, const MP_INT *b, unsigned long int e) +#else +mpz_pow_ui (r, b, e) + MP_INT *r; + const MP_INT *b; + unsigned long int e; +#endif +#else /* BERKELEY_MP */ +void +#ifdef __STDC__ +rpow (const MP_INT *b, signed short int e, MP_INT *r) +#else +rpow (b, e, r) + const MP_INT *b; + signed short int e; + MP_INT *r; +#endif +#endif /* BERKELEY_MP */ +{ + mp_ptr rp, bp, tp, xp; + mp_size rsize, bsize; + int cnt, i; + + bsize = ABS (b->size); + + /* Single out cases that give result == 0 or 1. These tests are here + to simplify the general code below, not to optimize. */ + if (bsize == 0 +#ifdef BERKELEY_MP + || e < 0 +#endif + ) + { + r->size = 0; + return; + } + if (e == 0) + { + r->d[0] = 1; + r->size = 1; + return; + } + + /* Count the number of leading zero bits of the base's most + significant limb. */ + count_leading_zeros (cnt, b->d[bsize - 1]); + + /* Over-estimate space requirements and allocate enough space for the + final result in two temporary areas. The two areas are used to + alternately 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.) */ + rsize = bsize * e - cnt * e / BITS_PER_MP_LIMB; + + rp = (mp_ptr) alloca (rsize * BYTES_PER_MP_LIMB); + tp = (mp_ptr) alloca (rsize * BYTES_PER_MP_LIMB); + bp = b->d; + + MPN_COPY (rp, bp, bsize); + rsize = bsize; + count_leading_zeros (cnt, e); + + for (i = BITS_PER_MP_LIMB - cnt - 2; i >= 0; i--) + { + rsize = mpn_mul (tp, rp, rsize, rp, rsize); + xp = tp; tp = rp; rp = xp; + + if ((e & ((mp_limb) 1 << i)) != 0) + { + rsize = mpn_mul (tp, rp, rsize, bp, bsize); + xp = tp; tp = rp; rp = xp; + } + } + + /* Now then we know the exact space requirements, reallocate if + necessary. */ + if (r->alloc < rsize) + _mpz_realloc (r, rsize); + + MPN_COPY (r->d, rp, rsize); + r->size = (e & 1) == 0 || b->size >= 0 ? rsize : -rsize; + alloca (0); +} diff --git a/gnu/lib/libgmp/mpz_powm.c b/gnu/lib/libgmp/mpz_powm.c new file mode 100644 index 0000000..75949ec --- /dev/null +++ b/gnu/lib/libgmp/mpz_powm.c @@ -0,0 +1,251 @@ +/* mpz_powm(res,base,exp,mod) -- Set RES to (base**exp) mod MOD. + +Copyright (C) 1991, 1992 Free Software Foundation, Inc. + +This file is part of the 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" +#include "gmp-impl.h" +#include "longlong.h" + +#ifndef BERKELEY_MP +void +#ifdef __STDC__ +mpz_powm (MP_INT *res, const MP_INT *base, const MP_INT *exp, + const MP_INT *mod) +#else +mpz_powm (res, base, exp, mod) + MP_INT *res; + const MP_INT *base; + const MP_INT *exp; + const MP_INT *mod; +#endif +#else /* BERKELEY_MP */ +void +#ifdef __STDC__ +pow (const MP_INT *base, const MP_INT *exp, const MP_INT *mod, MP_INT *res) +#else +pow (base, exp, mod, res) + const MP_INT *base; + const MP_INT *exp; + const MP_INT *mod; + MP_INT *res; +#endif +#endif /* BERKELEY_MP */ +{ + mp_ptr rp, ep, mp, bp; + mp_size esize, msize, bsize, rsize; + mp_size size; + int mod_shift_cnt; + int negative_result; + mp_limb *free_me = NULL; + size_t free_me_size; + + esize = ABS (exp->size); + msize = ABS (mod->size); + size = 2 * msize; + + rp = res->d; + ep = exp->d; + + /* Normalize MOD (i.e. make its most significant bit set) as required by + mpn_div. 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) alloca (msize * BYTES_PER_MP_LIMB); + count_leading_zeros (mod_shift_cnt, mod->d[msize - 1]); + if (mod_shift_cnt != 0) + (void) mpn_lshift (mp, mod->d, msize, mod_shift_cnt); + else + MPN_COPY (mp, mod->d, msize); + + bsize = ABS (base->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) alloca ((bsize + 1) * BYTES_PER_MP_LIMB); + MPN_COPY (bp, base->d, bsize); + /* We don't care about the quotient, store it above the remainder, + at BP + MSIZE. */ + mpn_div (bp + msize, bp, bsize, mp, msize); + bsize = msize; + while (bsize > 0 && bp[bsize - 1] == 0) + bsize--; + } + else + { + bp = base->d; + bsize = ABS (base->size); + } + + if (res->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->alloc; + } + else + (*_mp_free_func) (rp, res->alloc * BYTES_PER_MP_LIMB); + + rp = (mp_ptr) (*_mp_allocate_func) (size * BYTES_PER_MP_LIMB); + res->alloc = size; + res->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) alloca (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) alloca (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) alloca (msize * BYTES_PER_MP_LIMB); + MPN_COPY (mp, rp, msize); + } + } + + if (esize == 0) + { + rp[0] = 1; + res->size = 1; + return; + } + + MPN_COPY (rp, bp, bsize); + rsize = bsize; + + { + mp_size i; + mp_size xsize; + mp_ptr dummyp = (mp_ptr) alloca ((msize + 1) * BYTES_PER_MP_LIMB); + mp_ptr xp = (mp_ptr) alloca (2 * (msize + 1) * BYTES_PER_MP_LIMB); + int c; + mp_limb e; + mp_limb carry_limb; + + negative_result = (ep[0] & 1) && base->size < 0; + + i = esize - 1; + e = ep[i]; + count_leading_zeros (c, e); + e <<= (c + 1); /* shift the exp bits to the left, loose msb */ + c = BITS_PER_MP_LIMB - 1 - c; + + /* Main loop. + + Make the result be pointed to alternatingly by XP and RP. This + helps us avoid block copying, which would otherwise be necessary + with the overlap restrictions of mpn_div. With 50% probability + the result after this loop will be in the area originally pointed + by RP (==RES->D), and with 50% probability in the area originally + pointed to by XP. */ + + for (;;) + { + while (c != 0) + { + mp_ptr tp; + mp_size tsize; + + xsize = mpn_mul (xp, rp, rsize, rp, rsize); + mpn_div (dummyp, xp, xsize, mp, msize); + + /* Remove any leading zero words from the result. */ + if (xsize > msize) + xsize = msize; + while (xsize > 0 && xp[xsize - 1] == 0) + xsize--; + + tp = rp; rp = xp; xp = tp; + tsize = rsize; rsize = xsize; xsize = tsize; + + if ((mp_limb_signed) e < 0) + { + if (rsize > bsize) + xsize = mpn_mul (xp, rp, rsize, bp, bsize); + else + xsize = mpn_mul (xp, bp, bsize, rp, rsize); + mpn_div (dummyp, xp, xsize, mp, msize); + + /* Remove any leading zero words from the result. */ + if (xsize > msize) + xsize = msize; + while (xsize > 0 && xp[xsize - 1] == 0) + xsize--; + + tp = rp; rp = xp; xp = tp; + tsize = rsize; rsize = xsize; xsize = tsize; + } + 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->D (where it already + might be, see above). */ + + carry_limb = mpn_lshift (res->d, rp, rsize, mod_shift_cnt); + rp = res->d; + if (carry_limb != 0) + { + rp[rsize] = carry_limb; + rsize++; + } + mpn_div (dummyp, rp, rsize, mp, msize); + /* Remove any leading zero words from the result. */ + if (rsize > msize) + rsize = msize; + while (rsize > 0 && rp[rsize - 1] == 0) + rsize--; + rsize = mpn_rshift (rp, rp, rsize, mod_shift_cnt); + } + + res->size = negative_result >= 0 ? rsize : -rsize; + + if (free_me != NULL) + (*_mp_free_func) (free_me, free_me_size * BYTES_PER_MP_LIMB); + + alloca (0); +} diff --git a/gnu/lib/libgmp/mpz_powm_ui.c b/gnu/lib/libgmp/mpz_powm_ui.c new file mode 100644 index 0000000..3aa9b03 --- /dev/null +++ b/gnu/lib/libgmp/mpz_powm_ui.c @@ -0,0 +1,219 @@ +/* mpz_powm_ui(res,base,exp,mod) -- Set RES to (base**exp) mod MOD. + +Copyright (C) 1991, 1992 Free Software Foundation, Inc. + +This file is part of the 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" +#include "gmp-impl.h" +#include "longlong.h" + +void +#ifdef __STDC__ +mpz_powm_ui (MP_INT *res, const MP_INT *base, unsigned long int exp, + const MP_INT *mod) +#else +mpz_powm_ui (res, base, exp, mod) + MP_INT *res; + const MP_INT *base; + unsigned long int exp; + const MP_INT *mod; +#endif +{ + mp_ptr rp, mp, bp; + mp_size msize, bsize, rsize; + mp_size size; + int mod_shift_cnt; + int negative_result; + mp_limb *free_me = NULL; + size_t free_me_size; + + msize = ABS (mod->size); + size = 2 * msize; + + rp = res->d; + + /* Normalize MOD (i.e. make its most significant bit set) as required by + mpn_div. 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) alloca (msize * BYTES_PER_MP_LIMB); + count_leading_zeros (mod_shift_cnt, mod->d[msize - 1]); + if (mod_shift_cnt != 0) + (void) mpn_lshift (mp, mod->d, msize, mod_shift_cnt); + else + MPN_COPY (mp, mod->d, msize); + + bsize = ABS (base->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) alloca ((bsize + 1) * BYTES_PER_MP_LIMB); + MPN_COPY (bp, base->d, bsize); + /* We don't care about the quotient, store it above the remainder, + at BP + MSIZE. */ + mpn_div (bp + msize, bp, bsize, mp, msize); + bsize = msize; + while (bsize > 0 && bp[bsize - 1] == 0) + bsize--; + } + else + { + bp = base->d; + bsize = ABS (base->size); + } + + if (res->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->alloc; + } + else + (*_mp_free_func) (rp, res->alloc * BYTES_PER_MP_LIMB); + + rp = (mp_ptr) (*_mp_allocate_func) (size * BYTES_PER_MP_LIMB); + res->alloc = size; + res->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) alloca (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) alloca (msize * BYTES_PER_MP_LIMB); + MPN_COPY (mp, rp, msize); + } + } + + if (exp == 0) + { + rp[0] = 1; + res->size = 1; + return; + } + + MPN_COPY (rp, bp, bsize); + rsize = bsize; + + { + mp_size xsize; + mp_ptr dummyp = (mp_ptr) alloca ((msize + 1) * BYTES_PER_MP_LIMB); + mp_ptr xp = (mp_ptr) alloca (2 * (msize + 1) * BYTES_PER_MP_LIMB); + int c; + mp_limb e; + mp_limb carry_limb; + + negative_result = (exp & 1) && base->size < 0; + + e = exp; + count_leading_zeros (c, e); + e <<= (c + 1); /* shift the exp bits to the left, loose 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_div. With 50% probability + the result after this loop will be in the area originally pointed + by RP (==RES->D), and with 50% probability in the area originally + pointed to by XP. */ + + while (c != 0) + { + mp_ptr tp; + mp_size tsize; + + xsize = mpn_mul (xp, rp, rsize, rp, rsize); + mpn_div (dummyp, xp, xsize, mp, msize); + + /* Remove any leading zero words from the result. */ + if (xsize > msize) + xsize = msize; + while (xsize > 0 && xp[xsize - 1] == 0) + xsize--; + + tp = rp; rp = xp; xp = tp; + tsize = rsize; rsize = xsize; xsize = tsize; + + if ((mp_limb_signed) e < 0) + { + if (rsize > bsize) + xsize = mpn_mul (xp, rp, rsize, bp, bsize); + else + xsize = mpn_mul (xp, bp, bsize, rp, rsize); + mpn_div (dummyp, xp, xsize, mp, msize); + + /* Remove any leading zero words from the result. */ + if (xsize > msize) + xsize = msize; + while (xsize > 0 && xp[xsize - 1] == 0) + xsize--; + + tp = rp; rp = xp; xp = tp; + tsize = rsize; rsize = xsize; xsize = tsize; + } + 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->D (where it already + might be, see above). */ + + carry_limb = mpn_lshift (res->d, rp, rsize, mod_shift_cnt); + rp = res->d; + if (carry_limb != 0) + { + rp[rsize] = carry_limb; + rsize++; + } + mpn_div (dummyp, rp, rsize, mp, msize); + /* Remove any leading zero words from the result. */ + if (rsize > msize) + rsize = msize; + while (rsize > 0 && rp[rsize - 1] == 0) + rsize--; + rsize = mpn_rshift (rp, rp, rsize, mod_shift_cnt); + } + + res->size = negative_result >= 0 ? rsize : -rsize; + + if (free_me != NULL) + (*_mp_free_func) (free_me, free_me_size * BYTES_PER_MP_LIMB); + + alloca (0); +} diff --git a/gnu/lib/libgmp/mpz_pprime_p.c b/gnu/lib/libgmp/mpz_pprime_p.c new file mode 100644 index 0000000..9d08803 --- /dev/null +++ b/gnu/lib/libgmp/mpz_pprime_p.c @@ -0,0 +1,108 @@ +/* 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 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 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" +#include "gmp-impl.h" + +static int +possibly_prime (n, n_minus_1, x, y, q, k) + MP_INT *n, *n_minus_1, *x, *y, *q; + int k; +{ + 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, 1) <= 0); + + mpz_powm (y, x, q, n); + + if (mpz_cmp_ui (y, 1) == 0 || mpz_cmp (y, n_minus_1) == 0) + return 1; + + for (i = 1; i < k; i++) + { + mpz_powm_ui (y, y, 2, n); + if (mpz_cmp (y, n_minus_1) == 0) + return 1; + if (mpz_cmp_ui (y, 1) == 0) + return 0; + } + return 0; +} + +int +mpz_probab_prime_p (m, reps) + const MP_INT *m; + int reps; +{ + MP_INT n, n_minus_1, x, y, q; + int i, k, is_prime; + + mpz_init (&n); + /* Take the absolute value of M, to handle positive and negative primes. */ + mpz_abs (&n, m); + + if (mpz_cmp_ui (&n, 3) <= 0) + { + if (mpz_cmp_ui (&n, 1) <= 0) + return 0; /* smallest prime is 2 */ + else + return 1; + } + if ((mpz_get_ui (&n) & 1) == 0) + return 0; /* even */ + + mpz_init (&n_minus_1); + mpz_sub_ui (&n_minus_1, &n, 1); + 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 = 0; + while ((mpz_get_ui (&q) & 1) == 0) + { + k++; + mpz_div_2exp (&q, &q, 1); + } + + 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 0000000..c97bbff --- /dev/null +++ b/gnu/lib/libgmp/mpz_random.c @@ -0,0 +1,68 @@ +/* mpz_random -- Generate a random MP_INT of specified size. + +Copyright (C) 1991, 1993 Free Software Foundation, Inc. + +This file is part of the 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" +#include "gmp-impl.h" + +#if defined (hpux) || defined (__alpha__) +/* HPUX lacks random(). DEC Alpha's random() returns a double. */ +static inline long +urandom () +{ + return mrand48 (); +} +#else +long random (); + +static inline long +urandom () +{ + /* random() returns 31 bits, we want 32. */ + return random() ^ (random() << 1); +} +#endif + +void +#ifdef __STDC__ +mpz_random (MP_INT *x, mp_size size) +#else +mpz_random (x, size) + MP_INT *x; + mp_size size; +#endif +{ + mp_size i; + mp_limb ran; + + if (x->alloc < size) + _mpz_realloc (x, size); + + for (i = 0; i < size; i++) + { + ran = urandom (); + x->d[i] = ran; + } + + for (i = size - 1; i >= 0; i--) + if (x->d[i] != 0) + break; + + x->size = i + 1; +} diff --git a/gnu/lib/libgmp/mpz_random2.c b/gnu/lib/libgmp/mpz_random2.c new file mode 100644 index 0000000..6011528 --- /dev/null +++ b/gnu/lib/libgmp/mpz_random2.c @@ -0,0 +1,88 @@ +/* mpz_random2 -- Generate a positive random MP_INT 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 Free Software Foundation, Inc. + +This file is part of the 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" +#include "gmp-impl.h" + +#if defined (hpux) || defined (__alpha__) +/* HPUX lacks random(). DEC Alpha's random() returns a double. */ +static inline long +random () +{ + return mrand48 (); +} +#else +long random (); +#endif + +void +#ifdef __STDC__ +mpz_random2 (MP_INT *x, mp_size size) +#else +mpz_random2 (x, size) + MP_INT *x; + mp_size size; +#endif +{ + mp_limb ran, cy_limb; + mp_ptr xp; + mp_size xsize, abs_size; + int n_bits; + + abs_size = ABS (size); + + if (abs_size != 0) + { + if (x->alloc < abs_size) + _mpz_realloc (x, abs_size); + xp = x->d; + + xp[0] = 1; + for (xsize = 1;; ) + { + ran = random (); + n_bits = (ran >> 1) % BITS_PER_MP_LIMB; + + if (n_bits == 0) + { + if (xsize == abs_size) + break; + } + else + { + /* Would we get a too large result in mpn_lshift? */ + if (xsize == abs_size + && (xp[xsize - 1] >> (BITS_PER_MP_LIMB - n_bits)) != 0) + break; + + cy_limb = mpn_lshift (xp, xp, xsize, n_bits); + if (cy_limb != 0) + xp[xsize++] = cy_limb; + + if (ran & 1) + xp[0] |= ((mp_limb) 1 << n_bits) - 1; + } + } + } + + x->size = size; +} diff --git a/gnu/lib/libgmp/mpz_realloc.c b/gnu/lib/libgmp/mpz_realloc.c new file mode 100644 index 0000000..11a4df3 --- /dev/null +++ b/gnu/lib/libgmp/mpz_realloc.c @@ -0,0 +1,50 @@ +/* _mpz_realloc -- make the MP_INT have NEW_SIZE digits allocated. + +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" +#include "gmp-impl.h" + +void * +#ifdef __STDC__ +_mpz_realloc (MP_INT *m, mp_size new_size) +#else +_mpz_realloc (m, new_size) + MP_INT *m; + mp_size new_size; +#endif +{ + /* Never allocate zero space. */ + if (new_size == 0) + new_size = 1; + + m->d = (mp_ptr) (*_mp_reallocate_func) (m->d, m->alloc * BYTES_PER_MP_LIMB, + new_size * BYTES_PER_MP_LIMB); + m->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->size) > new_size) + m->size = 0; +#endif + + return (void *) m->d; +} diff --git a/gnu/lib/libgmp/mpz_set.c b/gnu/lib/libgmp/mpz_set.c new file mode 100644 index 0000000..2441e48 --- /dev/null +++ b/gnu/lib/libgmp/mpz_set.c @@ -0,0 +1,45 @@ +/* mpz_set (dest_integer, src_integer) -- Assign DEST_INTEGER from SRC_INTEGER. + +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" +#include "gmp-impl.h" + +void +#ifdef __STDC__ +mpz_set (MP_INT *w, const MP_INT *u) +#else +mpz_set (w, u) + MP_INT *w; + const MP_INT *u; +#endif +{ + mp_size usize; + mp_size abs_usize; + + usize = u->size; + abs_usize = ABS (usize); + + /* If not space for sum (and possible carry), increase space. */ + if (w->alloc < abs_usize) + _mpz_realloc (w, abs_usize); + + w->size = usize; + MPN_COPY (w->d, u->d, abs_usize); +} diff --git a/gnu/lib/libgmp/mpz_set_si.c b/gnu/lib/libgmp/mpz_set_si.c new file mode 100644 index 0000000..f6d11e7 --- /dev/null +++ b/gnu/lib/libgmp/mpz_set_si.c @@ -0,0 +1,47 @@ +/* mpz_set_si(integer, val) -- Assign INTEGER with a small value VAL. + +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" +#include "gmp-impl.h" + +void +#ifdef __STDC__ +mpz_set_si (MP_INT *dest, signed long int val) +#else +mpz_set_si (dest, val) + MP_INT *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->d[0] = val; + dest->size = 1; + } + else if (val < 0) + { + dest->d[0] = -val; + dest->size = -1; + } + else + dest->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 0000000..2596d8b --- /dev/null +++ b/gnu/lib/libgmp/mpz_set_str.c @@ -0,0 +1,41 @@ +/* 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 Free Software Foundation, Inc. + +This file is part of the 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" +#include "gmp-impl.h" +#include "longlong.h" + +int +#ifdef __STDC__ +mpz_set_str (MP_INT *x, const char *str, int base) +#else +mpz_set_str (x, str, base) + MP_INT *x; + const char *str; + int base; +#endif +{ + /* Go via _mpz_set_str, as that can be used by BSD compatible functions. */ + return _mpz_set_str (x, str, base); +} diff --git a/gnu/lib/libgmp/mpz_set_ui.c b/gnu/lib/libgmp/mpz_set_ui.c new file mode 100644 index 0000000..c2e06c9 --- /dev/null +++ b/gnu/lib/libgmp/mpz_set_ui.c @@ -0,0 +1,42 @@ +/* mpz_set_ui(integer, val) -- Assign INTEGER with a small value VAL. + +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" +#include "gmp-impl.h" + +void +#ifdef __STDC__ +mpz_set_ui (MP_INT *dest, unsigned long int val) +#else +mpz_set_ui (dest, val) + MP_INT *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->d[0] = val; + dest->size = 1; + } + else + dest->size = 0; +} diff --git a/gnu/lib/libgmp/mpz_size.c b/gnu/lib/libgmp/mpz_size.c new file mode 100644 index 0000000..8b9ff91 --- /dev/null +++ b/gnu/lib/libgmp/mpz_size.c @@ -0,0 +1,34 @@ +/* mpz_size(x) -- return the number of lims currently used by the + value of integer X. + +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" +#include "gmp-impl.h" + +size_t +#ifdef __STDC__ +mpz_size (const MP_INT *x) +#else +mpz_size (x) + const MP_INT *x; +#endif +{ + return ABS (x->size); +} diff --git a/gnu/lib/libgmp/mpz_sizeinb.c b/gnu/lib/libgmp/mpz_sizeinb.c new file mode 100644 index 0000000..75a0108 --- /dev/null +++ b/gnu/lib/libgmp/mpz_sizeinb.c @@ -0,0 +1,59 @@ +/* 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 Free Software Foundation, Inc. + +This file is part of the 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" +#include "gmp-impl.h" +#include "longlong.h" + +size_t +#ifdef __STDC__ +mpz_sizeinbase (const MP_INT *x, int base) +#else +mpz_sizeinbase (x, base) + const MP_INT *x; + int base; +#endif +{ + mp_size size = ABS (x->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->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 0000000..38408b8 --- /dev/null +++ b/gnu/lib/libgmp/mpz_sqrt.c @@ -0,0 +1,87 @@ +/* mpz_sqrt(root, u) -- Set ROOT to floor(sqrt(U)). + +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. */ + +/* 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" + +void +#ifdef __STDC__ +mpz_sqrt (MP_INT *root, const MP_INT *op) +#else +mpz_sqrt (root, op) + MP_INT *root; + const MP_INT *op; +#endif +{ + mp_size op_size, root_size; + mp_ptr root_ptr, op_ptr; + mp_ptr free_me = NULL; + mp_size free_me_size; + + op_size = op->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->d; + op_ptr = op->d; + + if (root->alloc < root_size) + { + if (root_ptr == op_ptr) + { + free_me = root_ptr; + free_me_size = root->alloc; + } + else + (*_mp_free_func) (root_ptr, root->alloc * BYTES_PER_MP_LIMB); + + root->alloc = root_size; + root_ptr = (mp_ptr) (*_mp_allocate_func) (root_size * BYTES_PER_MP_LIMB); + root->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) alloca (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_sqrt (root_ptr, NULL, op_ptr, op_size); + + root->size = root_size; + + if (free_me != NULL) + (*_mp_free_func) (free_me, free_me_size * BYTES_PER_MP_LIMB); + + alloca (0); +} diff --git a/gnu/lib/libgmp/mpz_sqrtrem.c b/gnu/lib/libgmp/mpz_sqrtrem.c new file mode 100644 index 0000000..c846c95 --- /dev/null +++ b/gnu/lib/libgmp/mpz_sqrtrem.c @@ -0,0 +1,105 @@ +/* mpz_sqrtrem(root,rem,x) -- Set ROOT to floor(sqrt(X)) and REM + to the remainder, i.e. X - ROOT**2. + +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" +#include "gmp-impl.h" + +#ifndef BERKELEY_MP +void +#ifdef __STDC__ +mpz_sqrtrem (MP_INT *root, MP_INT *rem, const MP_INT *op) +#else +mpz_sqrtrem (root, rem, op) + MP_INT *root; + MP_INT *rem; + const MP_INT *op; +#endif +#else /* BERKELEY_MP */ +void +#ifdef __STDC__ +msqrt (const MP_INT *op, MP_INT *root, MP_INT *rem) +#else +msqrt (op, root, rem) + const MP_INT *op; + MP_INT *root; + MP_INT *rem; +#endif +#endif /* BERKELEY_MP */ +{ + mp_size op_size, root_size, rem_size; + mp_ptr root_ptr, op_ptr; + mp_ptr free_me = NULL; + mp_size free_me_size; + + op_size = op->size; + if (op_size < 0) + op_size = 1 / (op_size > 0); /* Divide by zero for negative OP. */ + + if (rem->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->d; + op_ptr = op->d; + + if (root->alloc < root_size) + { + if (root_ptr == op_ptr) + { + free_me = root_ptr; + free_me_size = root->alloc; + } + else + (*_mp_free_func) (root_ptr, root->alloc * BYTES_PER_MP_LIMB); + + root->alloc = root_size; + root_ptr = (mp_ptr) (*_mp_allocate_func) (root_size * BYTES_PER_MP_LIMB); + root->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) alloca (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_sqrt (root_ptr, rem->d, op_ptr, op_size); + + root->size = root_size; + + /* Write remainder size last, to enable us to define this function to + give only the square root remainder, if the user calles if with + ROOT == REM. */ + rem->size = rem_size; + + if (free_me != NULL) + (*_mp_free_func) (free_me, free_me_size * BYTES_PER_MP_LIMB); + + alloca (0); +} diff --git a/gnu/lib/libgmp/mpz_sub.c b/gnu/lib/libgmp/mpz_sub.c new file mode 100644 index 0000000..f75f06c --- /dev/null +++ b/gnu/lib/libgmp/mpz_sub.c @@ -0,0 +1,117 @@ +/* mpz_sub -- Subtract two integers. + +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" +#include "gmp-impl.h" + +#ifndef BERKELEY_MP +void +#ifdef __STDC__ +mpz_sub (MP_INT *w, const MP_INT *u, const MP_INT *v) +#else +mpz_sub (w, u, v) + MP_INT *w; + const MP_INT *u; + const MP_INT *v; +#endif +#else /* BERKELEY_MP */ +void +#ifdef __STDC__ +msub (const MP_INT *u, const MP_INT *v, MP_INT *w) +#else +msub (u, v, w) + const MP_INT *u; + const MP_INT *v; + MP_INT *w; +#endif +#endif /* BERKELEY_MP */ +{ + mp_srcptr up, vp; + mp_ptr wp; + mp_size usize, vsize, wsize; + mp_size abs_usize; + mp_size abs_vsize; + + usize = u->size; + vsize = -v->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 MP_INT *t = u; u = v; v = t;} + {mp_size t = usize; usize = vsize; vsize = t;} + {mp_size t = abs_usize; abs_usize = abs_vsize; abs_vsize = t;} + } + + /* True: abs(USIZE) >= abs(VSIZE) */ + + /* If not space for sum (and possible carry), increase space. */ + wsize = abs_usize + 1; + if (w->alloc < wsize) + _mpz_realloc (w, wsize); + + /* These must be after realloc (u or v may be the same as w). */ + up = u->d; + vp = v->d; + wp = w->d; + + if (usize >= 0) + { + if (vsize >= 0) + { + wsize = mpn_add (wp, up, abs_usize, vp, abs_vsize); + if (wsize != 0) + wp[abs_usize] = 1; + wsize = wsize + abs_usize; + } + else + { + /* The signs are different. Need exact comparision to determine + which operand to subtract from which. */ + if (abs_usize == abs_vsize && mpn_cmp (up, vp, abs_usize) < 0) + wsize = -(abs_usize + mpn_sub (wp, vp, abs_usize, up, abs_usize)); + else + wsize = abs_usize + mpn_sub (wp, up, abs_usize, vp, abs_vsize); + } + } + else + { + if (vsize >= 0) + { + /* The signs are different. Need exact comparision to determine + which operand to subtract from which. */ + if (abs_usize == abs_vsize && mpn_cmp (up, vp, abs_usize) < 0) + wsize = abs_usize + mpn_sub (wp, vp, abs_usize, up, abs_usize); + else + wsize = -(abs_usize + mpn_sub (wp, up, abs_usize, vp, abs_vsize)); + } + else + { + wsize = mpn_add (wp, up, abs_usize, vp, abs_vsize); + if (wsize != 0) + wp[abs_usize] = 1; + wsize = -(wsize + abs_usize); + } + } + + w->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 0000000..cd9a04b --- /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 Free Software Foundation, Inc. + +This file is part of the 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" +#include "gmp-impl.h" + +void +#ifdef __STDC__ +mpz_sub_ui (MP_INT *dif, const MP_INT *min, mp_limb sub) +#else +mpz_sub_ui (dif, min, sub) + MP_INT *dif; + const MP_INT *min; + mp_limb sub; +#endif +{ + mp_srcptr minp; + mp_ptr difp; + mp_size minsize, difsize; + mp_size abs_minsize; + + minsize = min->size; + abs_minsize = ABS (minsize); + + /* If not space for SUM (and possible carry), increase space. */ + difsize = abs_minsize + 1; + if (dif->alloc < difsize) + _mpz_realloc (dif, difsize); + + /* These must be after realloc (ADD1 may be the same as SUM). */ + minp = min->d; + difp = dif->d; + + if (sub == 0) + { + MPN_COPY (difp, minp, abs_minsize); + dif->size = minsize; + return; + } + if (abs_minsize == 0) + { + difp[0] = sub; + dif->size = -1; + return; + } + + if (minsize < 0) + { + difsize = mpn_add (difp, minp, abs_minsize, &sub, 1); + if (difsize != 0) + difp[abs_minsize] = 1; + difsize = -(difsize + abs_minsize); + } + else + { + /* The signs are different. Need exact comparision to determine + which operand to subtract from which. */ + if (abs_minsize == 1 && minp[0] < sub) + difsize = -(abs_minsize + + mpn_sub (difp, &sub, 1, minp, 1)); + else + difsize = (abs_minsize + + mpn_sub (difp, minp, abs_minsize, &sub, 1)); + } + + dif->size = difsize; +} diff --git a/gnu/lib/libgmp/mtox.c b/gnu/lib/libgmp/mtox.c new file mode 100644 index 0000000..22708e5 --- /dev/null +++ b/gnu/lib/libgmp/mtox.c @@ -0,0 +1,37 @@ +/* mtox -- Convert OPERAND to hexadecimal and return a malloc'ed string + with the result of the conversion. + +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 "mp.h" +#include "gmp.h" +#include "gmp-impl.h" + +char * +#ifdef __STDC__ +mtox (const MINT *operand) +#else +mtox (operand) + const MINT *operand; +#endif +{ + /* Call MP_GET_STR with a NULL pointer as string argument, so that it + allocates space for the result. */ + return _mpz_get_str ((char *) 0, 16, operand); +} diff --git a/gnu/lib/libgmp/sdiv.c b/gnu/lib/libgmp/sdiv.c new file mode 100644 index 0000000..ab83dcd --- /dev/null +++ b/gnu/lib/libgmp/sdiv.c @@ -0,0 +1,76 @@ +/* sdiv -- Divide a MINT by a short integer. Produce a MINT quotient + and a short remainder. + +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 "mp.h" +#include "gmp.h" +#include "gmp-impl.h" +#include "longlong.h" + +void +#ifdef __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 sign_dividend; + signed long int sign_divisor; + mp_size dividend_size, quot_size; + mp_ptr dividend_ptr, quot_ptr; + mp_limb divisor_limb; + mp_limb remainder_limb; + + sign_dividend = dividend->size; + dividend_size = ABS (dividend->size); + + if (dividend_size == 0) + { + quot->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->alloc < dividend_size) + _mpz_realloc (quot, dividend_size); + + quot_ptr = quot->d; + dividend_ptr = dividend->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->size = (sign_divisor ^ sign_dividend) >= 0 ? quot_size : -quot_size; +} diff --git a/gnu/lib/libgmp/tests/Makefile b/gnu/lib/libgmp/tests/Makefile new file mode 100644 index 0000000..aa18015 --- /dev/null +++ b/gnu/lib/libgmp/tests/Makefile @@ -0,0 +1,64 @@ +# Makefile for tests for GNU MP + +# Copyright (C) 1991, 1993 Free Software Foundation, Inc. + +# This file is part of the 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. + +CC = gcc + +TEST_LIBS = ../libgmp.a +OPT = -O -g +CFLAGS = -I. -I.. $(OPT) + +TEST_SRCS = tst-mul.c tst-dm.c tst-dm_ui.c tst-mdm.c tst-mdm_ui.c tst-gcd.c \ + tst-sqrtrem.c tst-convert.c +TEST_OBJS = tst-mul.o tst-dm.o tst-dm_ui.o tst-mdm.o tst-mdm_ui.o tst-gcd.o \ + tst-sqrtrem.o tst-convert.o +TESTS = tst-mul tst-dm tst-dm_ui tst-mdm tst-mdm_ui tst-gcd \ + tst-sqrtrem tst-convert + +tests: $(TESTS) + for i in $(TESTS); do echo $$i; ./$$i; done + +tst-mul: tst-mul.o $(TEST_LIBS) + $(CC) $(CFLAGS) -o $@ $@.o $(TEST_LIBS) +tst-dm: tst-dm.o $(TEST_LIBS) + $(CC) $(CFLAGS) -o $@ $@.o $(TEST_LIBS) +tst-dm_ui: tst-dm_ui.o $(TEST_LIBS) + $(CC) $(CFLAGS) -o $@ $@.o $(TEST_LIBS) +tst-mdm: tst-mdm.o $(TEST_LIBS) + $(CC) $(CFLAGS) -o $@ $@.o $(TEST_LIBS) +tst-mdm_ui: tst-mdm_ui.o $(TEST_LIBS) + $(CC) $(CFLAGS) -o $@ $@.o $(TEST_LIBS) +tst-gcd: tst-gcd.o $(TEST_LIBS) + $(CC) $(CFLAGS) -o $@ $@.o $(TEST_LIBS) +tst-sqrtrem: tst-sqrtrem.o $(TEST_LIBS) + $(CC) $(CFLAGS) -o $@ $@.o $(TEST_LIBS) +tst-convert: tst-convert.o $(TEST_LIBS) + $(CC) $(CFLAGS) -o $@ $@.o $(TEST_LIBS) + +$(TEST_PREFIX)clean: + rm -f $(TESTS) $(TEST_OBJS) core + +tst-convert.o : tst-convert.c ../gmp.h urandom.h +tst-dm.o : tst-dm.c ../gmp.h urandom.h +tst-dm_ui.o : tst-dm_ui.c ../gmp.h urandom.h +tst-gcd.o : tst-gcd.c ../gmp.h urandom.h +tst-mdm.o : tst-mdm.c ../gmp.h urandom.h +tst-mdm_ui.o : tst-mdm_ui.c ../gmp.h urandom.h +tst-mul.o : tst-mul.c ../gmp.h ../gmp-impl.h ../gmp-mparam.h ../longlong.h urandom.h +tst-sqrtrem.o : tst-sqrtrem.c ../gmp.h urandom.h diff --git a/gnu/lib/libgmp/tests/tst-convert.c b/gnu/lib/libgmp/tests/tst-convert.c new file mode 100644 index 0000000..bbc0dab --- /dev/null +++ b/gnu/lib/libgmp/tests/tst-convert.c @@ -0,0 +1,80 @@ +/* Test mpz_add, mpz_cmp, mpz_cmp_ui, mpz_gcd, mpz_gcdext, mpz_get_str, + mpz_mod, mpz_mul, mpz_set_str. + +Copyright (C) 1993 Free Software Foundation, Inc. + +This file is part of the 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 +#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; +{ + MP_INT op1, op2; + mp_size 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/tests/tst-dm.c b/gnu/lib/libgmp/tests/tst-dm.c new file mode 100644 index 0000000..92c4194 --- /dev/null +++ b/gnu/lib/libgmp/tests/tst-dm.c @@ -0,0 +1,117 @@ +/* Test mpz_abs, mpz_add, mpz_cmp, mpz_cmp_ui, mpz_div, mpz_divmod, mpz_mod, + mpz_mul. + +Copyright (C) 1991, 1993 Free Software Foundation, Inc. + +This file is part of the 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 +#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; +{ + MP_INT dividend, divisor; + MP_INT quotient, remainder; + MP_INT quotient2, remainder2; + MP_INT temp; + mp_size dividend_size, divisor_size; + int i; + int reps = 100000; + + if (argc == 2) + reps = atoi (argv[1]); + + mpz_init (÷nd); + mpz_init (&divisor); + mpz_init ("ient); + mpz_init (&remainder); + mpz_init ("ient2); + mpz_init (&remainder2); + mpz_init (&temp); + + for (i = 0; i < reps; i++) + { + dividend_size = urandom () % SIZE - SIZE/2; + mpz_random2 (÷nd, dividend_size); + + divisor_size = urandom () % SIZE - SIZE/2; + mpz_random2 (&divisor, divisor_size); + if (mpz_cmp_ui (&divisor, 0) == 0) + continue; + + mpz_divmod ("ient, &remainder, ÷nd, &divisor); + mpz_div ("ient2, ÷nd, &divisor); + mpz_mod (&remainder2, ÷nd, &divisor); + + /* First determine that the quotients and remainders computed + with different functions are equal. */ + if (mpz_cmp ("ient, "ient2) != 0) + dump_abort (÷nd, &divisor); + if (mpz_cmp (&remainder, &remainder2) != 0) + dump_abort (÷nd, &divisor); + + /* Check if the sign of the quotient is correct. */ + if (mpz_cmp_ui ("ient, 0) != 0) + if ((mpz_cmp_ui ("ient, 0) < 0) + != ((mpz_cmp_ui (÷nd, 0) ^ mpz_cmp_ui (&divisor, 0)) < 0)) + dump_abort (÷nd, &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 (÷nd, 0) < 0)) + dump_abort (÷nd, &divisor); + + mpz_mul (&temp, "ient, &divisor); + mpz_add (&temp, &temp, &remainder); + if (mpz_cmp (&temp, ÷nd) != 0) + dump_abort (÷nd, &divisor); + + mpz_abs (&temp, &divisor); + mpz_abs (&remainder, &remainder); + if (mpz_cmp (&remainder, &temp) >= 0) + dump_abort (÷nd, &divisor); + } + + 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/tests/tst-dm_ui.c b/gnu/lib/libgmp/tests/tst-dm_ui.c new file mode 100644 index 0000000..9f69841 --- /dev/null +++ b/gnu/lib/libgmp/tests/tst-dm_ui.c @@ -0,0 +1,116 @@ +/* Test mpz_abs, mpz_add, mpz_cmp, mpz_cmp_ui, mpz_div, mpz_div_ui, + mpz_divmod, mpz_divmod_ui, mpz_mod, mpz_mod_ui, mpz_mul, mpz_mul_ui. + +Copyright (C) 1993 Free Software Foundation, Inc. + +This file is part of the 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 +#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; +{ + MP_INT dividend; + MP_INT quotient, remainder; + MP_INT quotient2, remainder2; + MP_INT temp; + mp_size dividend_size; + mp_limb divisor; + int i; + int reps = 100000; + + if (argc == 2) + reps = atoi (argv[1]); + + mpz_init (÷nd); + mpz_init ("ient); + mpz_init (&remainder); + mpz_init ("ient2); + mpz_init (&remainder2); + mpz_init (&temp); + + for (i = 0; i < reps; i++) + { + dividend_size = urandom () % SIZE - SIZE/2; + mpz_random2 (÷nd, dividend_size); + + divisor = urandom (); + if (divisor == 0) + continue; + + mpz_divmod_ui ("ient, &remainder, ÷nd, divisor); + mpz_div_ui ("ient2, ÷nd, divisor); + mpz_mod_ui (&remainder2, ÷nd, divisor); + + /* First determine that the quotients and remainders computed + with different functions are equal. */ + if (mpz_cmp ("ient, "ient2) != 0) + dump_abort (÷nd, divisor); + if (mpz_cmp (&remainder, &remainder2) != 0) + dump_abort (÷nd, divisor); + + /* Check if the sign of the quotient is correct. */ + if (mpz_cmp_ui ("ient, 0) != 0) + if ((mpz_cmp_ui ("ient, 0) < 0) + != (mpz_cmp_ui (÷nd, 0) < 0)) + dump_abort (÷nd, 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 (÷nd, 0) < 0)) + dump_abort (÷nd, divisor); + + mpz_mul_ui (&temp, "ient, divisor); + mpz_add (&temp, &temp, &remainder); + if (mpz_cmp (&temp, ÷nd) != 0) + dump_abort (÷nd, divisor); + + mpz_abs (&remainder, &remainder); + if (mpz_cmp_ui (&remainder, divisor) >= 0) + dump_abort (÷nd, divisor); + } + + exit (0); +} + +dump_abort (dividend, divisor) + MP_INT *dividend; + mp_limb divisor; +{ + fprintf (stderr, "ERROR\n"); + fprintf (stderr, "dividend = "); debug_mp (dividend, -16); + fprintf (stderr, "divisor = %lX\n", divisor); + abort(); +} + +void +debug_mp (x, base) + MP_INT *x; +{ + mpz_out_str (stderr, base, x); fputc ('\n', stderr); +} diff --git a/gnu/lib/libgmp/tests/tst-gcd.c b/gnu/lib/libgmp/tests/tst-gcd.c new file mode 100644 index 0000000..166aa56 --- /dev/null +++ b/gnu/lib/libgmp/tests/tst-gcd.c @@ -0,0 +1,131 @@ +/* Test mpz_gcd, mpz_gcdext, mpz_mul, mpz_mod, mpz_add, mpz_cmp, + mpz_cmp_ui. mpz_init_set, mpz_set, mpz_clear. + +Copyright (C) 1991, 1993 Free Software Foundation, Inc. + +This file is part of the 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 +#include "gmp.h" +#include "gmp-impl.h" +#include "urandom.h" + +void mpz_refgcd (), debug_mp (); + +#ifndef SIZE +#define SIZE 8 +#endif + +main (argc, argv) + int argc; + char **argv; +{ + MP_INT op1, op2; + MP_INT refgcd, gcd, s, t; + MP_INT temp1, temp2; + mp_size op1_size, op2_size; + int i; + int reps = 10000; + + 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; + op2_size = urandom () % SIZE; + + 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) + MP_INT *g; + MP_INT *x, *y; +{ + MP_INT 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_mod (&xx, &xx, &yy); + if (mpz_cmp_ui (&xx, 0) == 0) + { + mpz_set (g, &yy); + break; + } + mpz_mod (&yy, &yy, &xx); + } + + mpz_clear (&xx); + mpz_clear (&yy); +} + +dump_abort (op1, op2) + MP_INT *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) + MP_INT *x; +{ + mpz_out_str (stderr, base, x); fputc ('\n', stderr); +} diff --git a/gnu/lib/libgmp/tests/tst-mdm.c b/gnu/lib/libgmp/tests/tst-mdm.c new file mode 100644 index 0000000..a515ddf --- /dev/null +++ b/gnu/lib/libgmp/tests/tst-mdm.c @@ -0,0 +1,117 @@ +/* Test mpz_abs, mpz_add, mpz_cmp, mpz_cmp_ui, mpz_divmod, mpz_mdiv, + mpz_mdivmod, mpz_mmod, mpz_mul. + +Copyright (C) 1993 Free Software Foundation, Inc. + +This file is part of the 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 +#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; +{ + MP_INT dividend, divisor; + MP_INT quotient, remainder; + MP_INT quotient2, remainder2; + MP_INT temp; + mp_size dividend_size, divisor_size; + int i; + int reps = 100000; + + if (argc == 2) + reps = atoi (argv[1]); + + mpz_init (÷nd); + mpz_init (&divisor); + mpz_init ("ient); + mpz_init (&remainder); + mpz_init ("ient2); + mpz_init (&remainder2); + mpz_init (&temp); + + for (i = 0; i < reps; i++) + { + dividend_size = urandom () % SIZE - SIZE/2; + mpz_random2 (÷nd, dividend_size); + + divisor_size = urandom () % SIZE - SIZE/2; + mpz_random2 (&divisor, divisor_size); + if (mpz_cmp_ui (&divisor, 0) == 0) + continue; + + mpz_mdivmod ("ient, &remainder, ÷nd, &divisor); + mpz_mdiv ("ient2, ÷nd, &divisor); + mpz_mmod (&remainder2, ÷nd, &divisor); + + /* First determine that the quotients and remainders computed + with different functions are equal. */ + if (mpz_cmp ("ient, "ient2) != 0) + dump_abort (÷nd, &divisor); + if (mpz_cmp (&remainder, &remainder2) != 0) + dump_abort (÷nd, &divisor); + + /* Check if the sign of the quotient is correct. */ + if (mpz_cmp_ui ("ient, 0) != 0) + if ((mpz_cmp_ui ("ient, 0) < 0) + != ((mpz_cmp_ui (÷nd, 0) ^ mpz_cmp_ui (&divisor, 0)) < 0)) + dump_abort (÷nd, &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 (÷nd, &divisor); + + mpz_mul (&temp, "ient, &divisor); + mpz_add (&temp, &temp, &remainder); + if (mpz_cmp (&temp, ÷nd) != 0) + dump_abort (÷nd, &divisor); + + mpz_abs (&temp, &divisor); + mpz_abs (&remainder, &remainder); + if (mpz_cmp (&remainder, &temp) >= 0) + dump_abort (÷nd, &divisor); + } + + 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/tests/tst-mdm_ui.c b/gnu/lib/libgmp/tests/tst-mdm_ui.c new file mode 100644 index 0000000..26befbe --- /dev/null +++ b/gnu/lib/libgmp/tests/tst-mdm_ui.c @@ -0,0 +1,116 @@ +/* Test mpz_abs, mpz_add, mpz_cmp. mpz_cmp_si, mpz_cmp_ui, mpz_divmod, + mpz_mdiv_ui, mpz_mdivmod_ui, mpz_mmod_ui, mpz_mul, mpz_mul_ui. + +Copyright (C) 1993 Free Software Foundation, Inc. + +This file is part of the 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 +#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; +{ + MP_INT dividend; + MP_INT quotient, remainder; + MP_INT quotient2, remainder2; + MP_INT temp; + mp_size dividend_size; + mp_limb divisor; + int i; + int reps = 100000; + + if (argc == 2) + reps = atoi (argv[1]); + + mpz_init (÷nd); + mpz_init ("ient); + mpz_init (&remainder); + mpz_init ("ient2); + mpz_init (&remainder2); + mpz_init (&temp); + + for (i = 0; i < reps; i++) + { + dividend_size = urandom () % SIZE - SIZE/2; + mpz_random2 (÷nd, dividend_size); + + divisor = urandom (); + if (divisor == 0) + continue; + + mpz_mdivmod_ui ("ient, &remainder, ÷nd, divisor); + mpz_mdiv_ui ("ient2, ÷nd, divisor); + mpz_mmod_ui (&remainder2, ÷nd, divisor); + + /* First determine that the quotients and remainders computed + with different functions are equal. */ + if (mpz_cmp ("ient, "ient2) != 0) + dump_abort (÷nd, divisor); + if (mpz_cmp (&remainder, &remainder2) != 0) + dump_abort (÷nd, divisor); + + /* Check if the sign of the quotient is correct. */ + if (mpz_cmp_ui ("ient, 0) != 0) + if ((mpz_cmp_ui ("ient, 0) < 0) + != (mpz_cmp_ui (÷nd, 0) < 0)) + dump_abort (÷nd, 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 (÷nd, divisor); + + mpz_mul_ui (&temp, "ient, divisor); + mpz_add (&temp, &temp, &remainder); + if (mpz_cmp (&temp, ÷nd) != 0) + dump_abort (÷nd, divisor); + + mpz_abs (&remainder, &remainder); + if (mpz_cmp_ui (&remainder, divisor) >= 0) + dump_abort (÷nd, divisor); + } + + exit (0); +} + +dump_abort (dividend, divisor) + MP_INT *dividend; + mp_limb divisor; +{ + fprintf (stderr, "ERROR\n"); + fprintf (stderr, "dividend = "); debug_mp (dividend, -16); + fprintf (stderr, "divisor = %lX\n", divisor); + abort(); +} + +void +debug_mp (x, base) + MP_INT *x; +{ + mpz_out_str (stderr, base, x); fputc ('\n', stderr); +} diff --git a/gnu/lib/libgmp/tests/tst-mul.c b/gnu/lib/libgmp/tests/tst-mul.c new file mode 100644 index 0000000..0eab422 --- /dev/null +++ b/gnu/lib/libgmp/tests/tst-mul.c @@ -0,0 +1,261 @@ +/* Test mpz_add, mpz_cmp, mpz_cmp_ui, mpz_divmod, mpz_mul. + +Copyright (C) 1991, 1993 Free Software Foundation, Inc. + +This file is part of the 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 +#include "gmp.h" +#include "gmp-impl.h" +#include "longlong.h" +#include "urandom.h" + +void debug_mp (); +mp_size _mpn_mul_classic (); +void mpz_refmul (); + +#ifndef SIZE +#define SIZE 8 +#endif + +main (argc, argv) + int argc; + char **argv; +{ + MP_INT multiplier, multiplicand; + MP_INT product, ref_product; + MP_INT quotient, remainder; + mp_size multiplier_size, multiplicand_size; + int i; + int reps = 100000; + + if (argc == 2) + reps = atoi (argv[1]); + + mpz_init (&multiplier); + mpz_init (&multiplicand); + mpz_init (&product); + mpz_init (&ref_product); + mpz_init ("ient); + 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 ("ient, &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 ("ient, &multiplier)) + dump_abort (&multiplier, &multiplicand); + } + + exit (0); +} + +void +mpz_refmul (w, u, v) + MP_INT *w; + const MP_INT *u; + const MP_INT *v; +{ + mp_size usize = u->size; + mp_size vsize = v->size; + mp_size wsize; + mp_size sign_product; + mp_ptr up, vp; + mp_ptr wp; + mp_ptr free_me = NULL; + size_t free_me_size; + + sign_product = usize ^ vsize; + usize = ABS (usize); + vsize = ABS (vsize); + + if (usize < vsize) + { + /* Swap U and V. */ + {const MP_INT *t = u; u = v; v = t;} + {mp_size t = usize; usize = vsize; vsize = t;} + } + + up = u->d; + vp = v->d; + wp = w->d; + + /* Ensure W has space enough to store the result. */ + wsize = usize + vsize; + if (w->alloc < wsize) + { + if (wp == up || wp == vp) + { + free_me = wp; + free_me_size = w->alloc; + } + else + (*_mp_free_func) (wp, w->alloc * BYTES_PER_MP_LIMB); + + w->alloc = wsize; + wp = (mp_ptr) (*_mp_allocate_func) (wsize * BYTES_PER_MP_LIMB); + w->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) alloca (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) alloca (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->size = sign_product < 0 ? -wsize : wsize; + if (free_me != NULL) + (*_mp_free_func) (free_me, free_me_size * BYTES_PER_MP_LIMB); + + alloca (0); +} + +mp_size +_mpn_mul_classic (prodp, up, usize, vp, vsize) + mp_ptr prodp; + mp_srcptr up; + mp_size usize; + mp_srcptr vp; + mp_size vsize; +{ + mp_size n; + mp_size prod_size; + mp_limb cy; + mp_size i, j; + mp_limb prod_low, prod_high; + mp_limb cy_dig; + mp_limb 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) + MP_INT *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) + MP_INT *x; +{ + mpz_out_str (stderr, base, x); fputc ('\n', stderr); +} diff --git a/gnu/lib/libgmp/tests/tst-pow_ui.c b/gnu/lib/libgmp/tests/tst-pow_ui.c new file mode 100644 index 0000000..c7d929a --- /dev/null +++ b/gnu/lib/libgmp/tests/tst-pow_ui.c @@ -0,0 +1,120 @@ +/* Test mpz_abs, mpz_add, mpz_cmp, mpz_cmp_ui, mpz_div, mpz_divmod, mpz_mod, + mpz_mul. + +Copyright (C) 1991, 1993 Free Software Foundation, Inc. + +This file is part of the 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 +#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; +{ + MP_INT dividend, divisor; + MP_INT quotient, remainder; + MP_INT quotient2, remainder2; + MP_INT temp; + mp_size dividend_size, divisor_size; + int i; + int reps = 100000; + + if (argc == 2) + reps = atoi (argv[1]); + + mpz_init (÷nd); + mpz_init (&divisor); + mpz_init ("ient); + mpz_init (&remainder); + mpz_init ("ient2); + mpz_init (&remainder2); + mpz_init (&temp); + + for (i = 0; i < reps; i++) + { + base_size = urandom () % SIZE - SIZE/2; + mpz_random2 (&base, base_size); + + divisor_size = urandom () % SIZE - SIZE/2; + mpz_random2 (&divisor, divisor_size); + if (mpz_cmp_ui (&divisor, 0) == 0) + continue; + + exp_size = urandom () % SIZE/2; + mpz_random2 (&exp, exp_size); + + mpz_powm (&result1, &base, &exp, &divisor); + mpz_div ("ient2, ÷nd, &divisor); + mpz_mod (&remainder2, ÷nd, &divisor); + + /* First determine that the quotients and remainders computed + with different functions are equal. */ + if (mpz_cmp ("ient, "ient2) != 0) + dump_abort (÷nd, &divisor); + if (mpz_cmp (&remainder, &remainder2) != 0) + dump_abort (÷nd, &divisor); + + /* Check if the sign of the quotient is correct. */ + if (mpz_cmp_ui ("ient, 0) != 0) + if ((mpz_cmp_ui ("ient, 0) < 0) + != ((mpz_cmp_ui (÷nd, 0) ^ mpz_cmp_ui (&divisor, 0)) < 0)) + dump_abort (÷nd, &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 (÷nd, 0) < 0)) + dump_abort (÷nd, &divisor); + + mpz_mul (&temp, "ient, &divisor); + mpz_add (&temp, &temp, &remainder); + if (mpz_cmp (&temp, ÷nd) != 0) + dump_abort (÷nd, &divisor); + + mpz_abs (&temp, &divisor); + mpz_abs (&remainder, &remainder); + if (mpz_cmp (&remainder, &temp) >= 0) + dump_abort (÷nd, &divisor); + } + + 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/tests/tst-sqrtrem.c b/gnu/lib/libgmp/tests/tst-sqrtrem.c new file mode 100644 index 0000000..b62350a --- /dev/null +++ b/gnu/lib/libgmp/tests/tst-sqrtrem.c @@ -0,0 +1,97 @@ +/* Test mpz_add, mpz_add_ui, mpz_cmp, mpz_cmp, mpz_mul, mpz_sqrtrem. + +Copyright (C) 1991, 1993 Free Software Foundation, Inc. + +This file is part of the 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 +#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; +{ + MP_INT x2; + MP_INT x, rem; + MP_INT temp, temp2; + mp_size 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) + MP_INT *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) + MP_INT *x; +{ + mpz_out_str (stderr, base, x); fputc ('\n', stderr); +} diff --git a/gnu/lib/libgmp/tests/urandom.h b/gnu/lib/libgmp/tests/urandom.h new file mode 100644 index 0000000..e018580 --- /dev/null +++ b/gnu/lib/libgmp/tests/urandom.h @@ -0,0 +1,17 @@ +#if defined (hpux) || defined (__alpha__) +/* HPUX lacks random(). DEC Alpha's random() returns a double. */ +static inline unsigned long +urandom () +{ + return mrand48 (); +} +#else +long random (); + +static inline unsigned long +urandom () +{ + /* random() returns 31 bits, we want 32. */ + return random() ^ (random() << 1); +} +#endif diff --git a/gnu/lib/libgmp/xtom.c b/gnu/lib/libgmp/xtom.c new file mode 100644 index 0000000..13f31c8 --- /dev/null +++ b/gnu/lib/libgmp/xtom.c @@ -0,0 +1,41 @@ +/* xtom -- convert a hexadecimal string to a MINT, and return a pointer to + the MINT. + +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 "mp.h" +#include "gmp.h" +#include "gmp-impl.h" + +MINT * +#ifdef __STDC__ +xtom (const char *hex_str) +#else +xtom (hex_str) + const char *hex_str; +#endif +{ + MINT *x = (MINT *) (*_mp_allocate_func) (sizeof (MINT)); + + x->alloc = 1; + x->d = (mp_ptr) (*_mp_allocate_func) (x->alloc * BYTES_PER_MP_LIMB); + + _mpz_set_str (x, hex_str, 16); + return x; +} -- cgit v1.1