././@PaxHeader 0000000 0000000 0000000 00000000034 00000000000 010212 x ustar 00 28 mtime=1721563243.6844618
gmpy2-2.2.1/ 0000755 0001750 0001750 00000000000 14647174154 011237 5 ustar 00case case ././@PaxHeader 0000000 0000000 0000000 00000000026 00000000000 010213 x ustar 00 22 mtime=1710307256.0
gmpy2-2.2.1/COPYING 0000644 0001750 0001750 00000104513 14574233670 012274 0 ustar 00case case GNU GENERAL PUBLIC LICENSE
Version 3, 29 June 2007
Copyright (C) 2007 Free Software Foundation, Inc.
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
Preamble
The GNU General Public License is a free, copyleft license for
software and other kinds of works.
The licenses for most software and other practical works are designed
to take away your freedom to share and change the works. By contrast,
the GNU General Public License is intended to guarantee your freedom to
share and change all versions of a program--to make sure it remains free
software for all its users. We, the Free Software Foundation, use the
GNU General Public License for most of our software; it applies also to
any other work released this way by its authors. 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
them 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 prevent others from denying you
these rights or asking you to surrender the rights. Therefore, you have
certain responsibilities if you distribute copies of the software, or if
you modify it: responsibilities to respect the freedom of others.
For example, if you distribute copies of such a program, whether
gratis or for a fee, you must pass on to the recipients the same
freedoms that you received. 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.
Developers that use the GNU GPL protect your rights with two steps:
(1) assert copyright on the software, and (2) offer you this License
giving you legal permission to copy, distribute and/or modify it.
For the developers' and authors' protection, the GPL clearly explains
that there is no warranty for this free software. For both users' and
authors' sake, the GPL requires that modified versions be marked as
changed, so that their problems will not be attributed erroneously to
authors of previous versions.
Some devices are designed to deny users access to install or run
modified versions of the software inside them, although the manufacturer
can do so. This is fundamentally incompatible with the aim of
protecting users' freedom to change the software. The systematic
pattern of such abuse occurs in the area of products for individuals to
use, which is precisely where it is most unacceptable. Therefore, we
have designed this version of the GPL to prohibit the practice for those
products. If such problems arise substantially in other domains, we
stand ready to extend this provision to those domains in future versions
of the GPL, as needed to protect the freedom of users.
Finally, every program is threatened constantly by software patents.
States should not allow patents to restrict development and use of
software on general-purpose computers, but in those that do, we wish to
avoid the special danger that patents applied to a free program could
make it effectively proprietary. To prevent this, the GPL assures that
patents cannot be used to render the program non-free.
The precise terms and conditions for copying, distribution and
modification follow.
TERMS AND CONDITIONS
0. Definitions.
"This License" refers to version 3 of the GNU General Public License.
"Copyright" also means copyright-like laws that apply to other kinds of
works, such as semiconductor masks.
"The Program" refers to any copyrightable work licensed under this
License. Each licensee is addressed as "you". "Licensees" and
"recipients" may be individuals or organizations.
To "modify" a work means to copy from or adapt all or part of the work
in a fashion requiring copyright permission, other than the making of an
exact copy. The resulting work is called a "modified version" of the
earlier work or a work "based on" the earlier work.
A "covered work" means either the unmodified Program or a work based
on the Program.
To "propagate" a work means to do anything with it that, without
permission, would make you directly or secondarily liable for
infringement under applicable copyright law, except executing it on a
computer or modifying a private copy. Propagation includes copying,
distribution (with or without modification), making available to the
public, and in some countries other activities as well.
To "convey" a work means any kind of propagation that enables other
parties to make or receive copies. Mere interaction with a user through
a computer network, with no transfer of a copy, is not conveying.
An interactive user interface displays "Appropriate Legal Notices"
to the extent that it includes a convenient and prominently visible
feature that (1) displays an appropriate copyright notice, and (2)
tells the user that there is no warranty for the work (except to the
extent that warranties are provided), that licensees may convey the
work under this License, and how to view a copy of this License. If
the interface presents a list of user commands or options, such as a
menu, a prominent item in the list meets this criterion.
1. Source Code.
The "source code" for a work means the preferred form of the work
for making modifications to it. "Object code" means any non-source
form of a work.
A "Standard Interface" means an interface that either is an official
standard defined by a recognized standards body, or, in the case of
interfaces specified for a particular programming language, one that
is widely used among developers working in that language.
The "System Libraries" of an executable work include anything, other
than the work as a whole, that (a) is included in the normal form of
packaging a Major Component, but which is not part of that Major
Component, and (b) serves only to enable use of the work with that
Major Component, or to implement a Standard Interface for which an
implementation is available to the public in source code form. A
"Major Component", in this context, means a major essential component
(kernel, window system, and so on) of the specific operating system
(if any) on which the executable work runs, or a compiler used to
produce the work, or an object code interpreter used to run it.
The "Corresponding Source" for a work in object code form means all
the source code needed to generate, install, and (for an executable
work) run the object code and to modify the work, including scripts to
control those activities. However, it does not include the work's
System Libraries, or general-purpose tools or generally available free
programs which are used unmodified in performing those activities but
which are not part of the work. For example, Corresponding Source
includes interface definition files associated with source files for
the work, and the source code for shared libraries and dynamically
linked subprograms that the work is specifically designed to require,
such as by intimate data communication or control flow between those
subprograms and other parts of the work.
The Corresponding Source need not include anything that users
can regenerate automatically from other parts of the Corresponding
Source.
The Corresponding Source for a work in source code form is that
same work.
2. Basic Permissions.
All rights granted under this License are granted for the term of
copyright on the Program, and are irrevocable provided the stated
conditions are met. This License explicitly affirms your unlimited
permission to run the unmodified Program. The output from running a
covered work is covered by this License only if the output, given its
content, constitutes a covered work. This License acknowledges your
rights of fair use or other equivalent, as provided by copyright law.
You may make, run and propagate covered works that you do not
convey, without conditions so long as your license otherwise remains
in force. You may convey covered works to others for the sole purpose
of having them make modifications exclusively for you, or provide you
with facilities for running those works, provided that you comply with
the terms of this License in conveying all material for which you do
not control copyright. Those thus making or running the covered works
for you must do so exclusively on your behalf, under your direction
and control, on terms that prohibit them from making any copies of
your copyrighted material outside their relationship with you.
Conveying under any other circumstances is permitted solely under
the conditions stated below. Sublicensing is not allowed; section 10
makes it unnecessary.
3. Protecting Users' Legal Rights From Anti-Circumvention Law.
No covered work shall be deemed part of an effective technological
measure under any applicable law fulfilling obligations under article
11 of the WIPO copyright treaty adopted on 20 December 1996, or
similar laws prohibiting or restricting circumvention of such
measures.
When you convey a covered work, you waive any legal power to forbid
circumvention of technological measures to the extent such circumvention
is effected by exercising rights under this License with respect to
the covered work, and you disclaim any intention to limit operation or
modification of the work as a means of enforcing, against the work's
users, your or third parties' legal rights to forbid circumvention of
technological measures.
4. Conveying Verbatim Copies.
You may convey 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;
keep intact all notices stating that this License and any
non-permissive terms added in accord with section 7 apply to the code;
keep intact all notices of the absence of any warranty; and give all
recipients a copy of this License along with the Program.
You may charge any price or no price for each copy that you convey,
and you may offer support or warranty protection for a fee.
5. Conveying Modified Source Versions.
You may convey a work based on the Program, or the modifications to
produce it from the Program, in the form of source code under the
terms of section 4, provided that you also meet all of these conditions:
a) The work must carry prominent notices stating that you modified
it, and giving a relevant date.
b) The work must carry prominent notices stating that it is
released under this License and any conditions added under section
7. This requirement modifies the requirement in section 4 to
"keep intact all notices".
c) You must license the entire work, as a whole, under this
License to anyone who comes into possession of a copy. This
License will therefore apply, along with any applicable section 7
additional terms, to the whole of the work, and all its parts,
regardless of how they are packaged. This License gives no
permission to license the work in any other way, but it does not
invalidate such permission if you have separately received it.
d) If the work has interactive user interfaces, each must display
Appropriate Legal Notices; however, if the Program has interactive
interfaces that do not display Appropriate Legal Notices, your
work need not make them do so.
A compilation of a covered work with other separate and independent
works, which are not by their nature extensions of the covered work,
and which are not combined with it such as to form a larger program,
in or on a volume of a storage or distribution medium, is called an
"aggregate" if the compilation and its resulting copyright are not
used to limit the access or legal rights of the compilation's users
beyond what the individual works permit. Inclusion of a covered work
in an aggregate does not cause this License to apply to the other
parts of the aggregate.
6. Conveying Non-Source Forms.
You may convey a covered work in object code form under the terms
of sections 4 and 5, provided that you also convey the
machine-readable Corresponding Source under the terms of this License,
in one of these ways:
a) Convey the object code in, or embodied in, a physical product
(including a physical distribution medium), accompanied by the
Corresponding Source fixed on a durable physical medium
customarily used for software interchange.
b) Convey the object code in, or embodied in, a physical product
(including a physical distribution medium), accompanied by a
written offer, valid for at least three years and valid for as
long as you offer spare parts or customer support for that product
model, to give anyone who possesses the object code either (1) a
copy of the Corresponding Source for all the software in the
product that is covered by this License, on a durable physical
medium customarily used for software interchange, for a price no
more than your reasonable cost of physically performing this
conveying of source, or (2) access to copy the
Corresponding Source from a network server at no charge.
c) Convey individual copies of the object code with a copy of the
written offer to provide the Corresponding Source. This
alternative is allowed only occasionally and noncommercially, and
only if you received the object code with such an offer, in accord
with subsection 6b.
d) Convey the object code by offering access from a designated
place (gratis or for a charge), and offer equivalent access to the
Corresponding Source in the same way through the same place at no
further charge. You need not require recipients to copy the
Corresponding Source along with the object code. If the place to
copy the object code is a network server, the Corresponding Source
may be on a different server (operated by you or a third party)
that supports equivalent copying facilities, provided you maintain
clear directions next to the object code saying where to find the
Corresponding Source. Regardless of what server hosts the
Corresponding Source, you remain obligated to ensure that it is
available for as long as needed to satisfy these requirements.
e) Convey the object code using peer-to-peer transmission, provided
you inform other peers where the object code and Corresponding
Source of the work are being offered to the general public at no
charge under subsection 6d.
A separable portion of the object code, whose source code is excluded
from the Corresponding Source as a System Library, need not be
included in conveying the object code work.
A "User Product" is either (1) a "consumer product", which means any
tangible personal property which is normally used for personal, family,
or household purposes, or (2) anything designed or sold for incorporation
into a dwelling. In determining whether a product is a consumer product,
doubtful cases shall be resolved in favor of coverage. For a particular
product received by a particular user, "normally used" refers to a
typical or common use of that class of product, regardless of the status
of the particular user or of the way in which the particular user
actually uses, or expects or is expected to use, the product. A product
is a consumer product regardless of whether the product has substantial
commercial, industrial or non-consumer uses, unless such uses represent
the only significant mode of use of the product.
"Installation Information" for a User Product means any methods,
procedures, authorization keys, or other information required to install
and execute modified versions of a covered work in that User Product from
a modified version of its Corresponding Source. The information must
suffice to ensure that the continued functioning of the modified object
code is in no case prevented or interfered with solely because
modification has been made.
If you convey an object code work under this section in, or with, or
specifically for use in, a User Product, and the conveying occurs as
part of a transaction in which the right of possession and use of the
User Product is transferred to the recipient in perpetuity or for a
fixed term (regardless of how the transaction is characterized), the
Corresponding Source conveyed under this section must be accompanied
by the Installation Information. But this requirement does not apply
if neither you nor any third party retains the ability to install
modified object code on the User Product (for example, the work has
been installed in ROM).
The requirement to provide Installation Information does not include a
requirement to continue to provide support service, warranty, or updates
for a work that has been modified or installed by the recipient, or for
the User Product in which it has been modified or installed. Access to a
network may be denied when the modification itself materially and
adversely affects the operation of the network or violates the rules and
protocols for communication across the network.
Corresponding Source conveyed, and Installation Information provided,
in accord with this section must be in a format that is publicly
documented (and with an implementation available to the public in
source code form), and must require no special password or key for
unpacking, reading or copying.
7. Additional Terms.
"Additional permissions" are terms that supplement the terms of this
License by making exceptions from one or more of its conditions.
Additional permissions that are applicable to the entire Program shall
be treated as though they were included in this License, to the extent
that they are valid under applicable law. If additional permissions
apply only to part of the Program, that part may be used separately
under those permissions, but the entire Program remains governed by
this License without regard to the additional permissions.
When you convey a copy of a covered work, you may at your option
remove any additional permissions from that copy, or from any part of
it. (Additional permissions may be written to require their own
removal in certain cases when you modify the work.) You may place
additional permissions on material, added by you to a covered work,
for which you have or can give appropriate copyright permission.
Notwithstanding any other provision of this License, for material you
add to a covered work, you may (if authorized by the copyright holders of
that material) supplement the terms of this License with terms:
a) Disclaiming warranty or limiting liability differently from the
terms of sections 15 and 16 of this License; or
b) Requiring preservation of specified reasonable legal notices or
author attributions in that material or in the Appropriate Legal
Notices displayed by works containing it; or
c) Prohibiting misrepresentation of the origin of that material, or
requiring that modified versions of such material be marked in
reasonable ways as different from the original version; or
d) Limiting the use for publicity purposes of names of licensors or
authors of the material; or
e) Declining to grant rights under trademark law for use of some
trade names, trademarks, or service marks; or
f) Requiring indemnification of licensors and authors of that
material by anyone who conveys the material (or modified versions of
it) with contractual assumptions of liability to the recipient, for
any liability that these contractual assumptions directly impose on
those licensors and authors.
All other non-permissive additional terms are considered "further
restrictions" within the meaning of section 10. If the Program as you
received it, or any part of it, contains a notice stating that it is
governed by this License along with a term that is a further
restriction, you may remove that term. If a license document contains
a further restriction but permits relicensing or conveying under this
License, you may add to a covered work material governed by the terms
of that license document, provided that the further restriction does
not survive such relicensing or conveying.
If you add terms to a covered work in accord with this section, you
must place, in the relevant source files, a statement of the
additional terms that apply to those files, or a notice indicating
where to find the applicable terms.
Additional terms, permissive or non-permissive, may be stated in the
form of a separately written license, or stated as exceptions;
the above requirements apply either way.
8. Termination.
You may not propagate or modify a covered work except as expressly
provided under this License. Any attempt otherwise to propagate or
modify it is void, and will automatically terminate your rights under
this License (including any patent licenses granted under the third
paragraph of section 11).
However, if you cease all violation of this License, then your
license from a particular copyright holder is reinstated (a)
provisionally, unless and until the copyright holder explicitly and
finally terminates your license, and (b) permanently, if the copyright
holder fails to notify you of the violation by some reasonable means
prior to 60 days after the cessation.
Moreover, your license from a particular copyright holder is
reinstated permanently if the copyright holder notifies you of the
violation by some reasonable means, this is the first time you have
received notice of violation of this License (for any work) from that
copyright holder, and you cure the violation prior to 30 days after
your receipt of the notice.
Termination of your rights under this section does not terminate the
licenses of parties who have received copies or rights from you under
this License. If your rights have been terminated and not permanently
reinstated, you do not qualify to receive new licenses for the same
material under section 10.
9. Acceptance Not Required for Having Copies.
You are not required to accept this License in order to receive or
run a copy of the Program. Ancillary propagation of a covered work
occurring solely as a consequence of using peer-to-peer transmission
to receive a copy likewise does not require acceptance. However,
nothing other than this License grants you permission to propagate or
modify any covered work. These actions infringe copyright if you do
not accept this License. Therefore, by modifying or propagating a
covered work, you indicate your acceptance of this License to do so.
10. Automatic Licensing of Downstream Recipients.
Each time you convey a covered work, the recipient automatically
receives a license from the original licensors, to run, modify and
propagate that work, subject to this License. You are not responsible
for enforcing compliance by third parties with this License.
An "entity transaction" is a transaction transferring control of an
organization, or substantially all assets of one, or subdividing an
organization, or merging organizations. If propagation of a covered
work results from an entity transaction, each party to that
transaction who receives a copy of the work also receives whatever
licenses to the work the party's predecessor in interest had or could
give under the previous paragraph, plus a right to possession of the
Corresponding Source of the work from the predecessor in interest, if
the predecessor has it or can get it with reasonable efforts.
You may not impose any further restrictions on the exercise of the
rights granted or affirmed under this License. For example, you may
not impose a license fee, royalty, or other charge for exercise of
rights granted under this License, and you may not initiate litigation
(including a cross-claim or counterclaim in a lawsuit) alleging that
any patent claim is infringed by making, using, selling, offering for
sale, or importing the Program or any portion of it.
11. Patents.
A "contributor" is a copyright holder who authorizes use under this
License of the Program or a work on which the Program is based. The
work thus licensed is called the contributor's "contributor version".
A contributor's "essential patent claims" are all patent claims
owned or controlled by the contributor, whether already acquired or
hereafter acquired, that would be infringed by some manner, permitted
by this License, of making, using, or selling its contributor version,
but do not include claims that would be infringed only as a
consequence of further modification of the contributor version. For
purposes of this definition, "control" includes the right to grant
patent sublicenses in a manner consistent with the requirements of
this License.
Each contributor grants you a non-exclusive, worldwide, royalty-free
patent license under the contributor's essential patent claims, to
make, use, sell, offer for sale, import and otherwise run, modify and
propagate the contents of its contributor version.
In the following three paragraphs, a "patent license" is any express
agreement or commitment, however denominated, not to enforce a patent
(such as an express permission to practice a patent or covenant not to
sue for patent infringement). To "grant" such a patent license to a
party means to make such an agreement or commitment not to enforce a
patent against the party.
If you convey a covered work, knowingly relying on a patent license,
and the Corresponding Source of the work is not available for anyone
to copy, free of charge and under the terms of this License, through a
publicly available network server or other readily accessible means,
then you must either (1) cause the Corresponding Source to be so
available, or (2) arrange to deprive yourself of the benefit of the
patent license for this particular work, or (3) arrange, in a manner
consistent with the requirements of this License, to extend the patent
license to downstream recipients. "Knowingly relying" means you have
actual knowledge that, but for the patent license, your conveying the
covered work in a country, or your recipient's use of the covered work
in a country, would infringe one or more identifiable patents in that
country that you have reason to believe are valid.
If, pursuant to or in connection with a single transaction or
arrangement, you convey, or propagate by procuring conveyance of, a
covered work, and grant a patent license to some of the parties
receiving the covered work authorizing them to use, propagate, modify
or convey a specific copy of the covered work, then the patent license
you grant is automatically extended to all recipients of the covered
work and works based on it.
A patent license is "discriminatory" if it does not include within
the scope of its coverage, prohibits the exercise of, or is
conditioned on the non-exercise of one or more of the rights that are
specifically granted under this License. You may not convey a covered
work if you are a party to an arrangement with a third party that is
in the business of distributing software, under which you make payment
to the third party based on the extent of your activity of conveying
the work, and under which the third party grants, to any of the
parties who would receive the covered work from you, a discriminatory
patent license (a) in connection with copies of the covered work
conveyed by you (or copies made from those copies), or (b) primarily
for and in connection with specific products or compilations that
contain the covered work, unless you entered into that arrangement,
or that patent license was granted, prior to 28 March 2007.
Nothing in this License shall be construed as excluding or limiting
any implied license or other defenses to infringement that may
otherwise be available to you under applicable patent law.
12. No Surrender of Others' Freedom.
If 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 convey a
covered work so as to satisfy simultaneously your obligations under this
License and any other pertinent obligations, then as a consequence you may
not convey it at all. For example, if you agree to terms that obligate you
to collect a royalty for further conveying from those to whom you convey
the Program, the only way you could satisfy both those terms and this
License would be to refrain entirely from conveying the Program.
13. Use with the GNU Affero General Public License.
Notwithstanding any other provision of this License, you have
permission to link or combine any covered work with a work licensed
under version 3 of the GNU Affero General Public License into a single
combined work, and to convey the resulting work. The terms of this
License will continue to apply to the part which is the covered work,
but the special requirements of the GNU Affero General Public License,
section 13, concerning interaction through a network will apply to the
combination as such.
14. Revised Versions of this License.
The Free Software Foundation may publish revised and/or new versions of
the GNU 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 that a certain numbered version of the GNU General
Public License "or any later version" applies to it, you have the
option of following the terms and conditions either of that numbered
version or of any later version published by the Free Software
Foundation. If the Program does not specify a version number of the
GNU General Public License, you may choose any version ever published
by the Free Software Foundation.
If the Program specifies that a proxy can decide which future
versions of the GNU General Public License can be used, that proxy's
public statement of acceptance of a version permanently authorizes you
to choose that version for the Program.
Later license versions may give you additional or different
permissions. However, no additional obligations are imposed on any
author or copyright holder as a result of your choosing to follow a
later version.
15. Disclaimer of Warranty.
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.
16. Limitation of Liability.
IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
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.
17. Interpretation of Sections 15 and 16.
If the disclaimer of warranty and limitation of liability provided
above cannot be given local legal effect according to their terms,
reviewing courts shall apply local law that most closely approximates
an absolute waiver of all civil liability in connection with the
Program, unless a warranty or assumption of liability accompanies a
copy of the Program in return for a fee.
END OF TERMS AND CONDITIONS
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
state the exclusion of warranty; and each file should have at least
the "copyright" line and a pointer to where the full notice is found.
Copyright (C)
This 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 3 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, see .
Also add information on how to contact you by electronic and paper mail.
If the program does terminal interaction, make it output a short
notice like this when it starts in an interactive mode:
Copyright (C)
This program 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, your program's commands
might be different; for a GUI interface, you would use an "about box".
You should also get your employer (if you work as a programmer) or school,
if any, to sign a "copyright disclaimer" for the program, if necessary.
For more information on this, and how to apply and follow the GNU GPL, see
.
The GNU 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 Lesser General
Public License instead of this License. But first, please read
.
././@PaxHeader 0000000 0000000 0000000 00000000026 00000000000 010213 x ustar 00 22 mtime=1710307256.0
gmpy2-2.2.1/COPYING.LESSER 0000644 0001750 0001750 00000016743 14574233670 013277 0 ustar 00case case GNU LESSER GENERAL PUBLIC LICENSE
Version 3, 29 June 2007
Copyright (C) 2007 Free Software Foundation, Inc.
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
This version of the GNU Lesser General Public License incorporates
the terms and conditions of version 3 of the GNU General Public
License, supplemented by the additional permissions listed below.
0. Additional Definitions.
As used herein, "this License" refers to version 3 of the GNU Lesser
General Public License, and the "GNU GPL" refers to version 3 of the GNU
General Public License.
"The Library" refers to a covered work governed by this License,
other than an Application or a Combined Work as defined below.
An "Application" is any work that makes use of an interface provided
by the Library, but which is not otherwise based on the Library.
Defining a subclass of a class defined by the Library is deemed a mode
of using an interface provided by the Library.
A "Combined Work" is a work produced by combining or linking an
Application with the Library. The particular version of the Library
with which the Combined Work was made is also called the "Linked
Version".
The "Minimal Corresponding Source" for a Combined Work means the
Corresponding Source for the Combined Work, excluding any source code
for portions of the Combined Work that, considered in isolation, are
based on the Application, and not on the Linked Version.
The "Corresponding Application Code" for a Combined Work means the
object code and/or source code for the Application, including any data
and utility programs needed for reproducing the Combined Work from the
Application, but excluding the System Libraries of the Combined Work.
1. Exception to Section 3 of the GNU GPL.
You may convey a covered work under sections 3 and 4 of this License
without being bound by section 3 of the GNU GPL.
2. Conveying Modified Versions.
If you modify a copy of the Library, and, in your modifications, a
facility refers to a function or data to be supplied by an Application
that uses the facility (other than as an argument passed when the
facility is invoked), then you may convey a copy of the modified
version:
a) under this License, provided that you make a good faith effort to
ensure that, in the event an Application does not supply the
function or data, the facility still operates, and performs
whatever part of its purpose remains meaningful, or
b) under the GNU GPL, with none of the additional permissions of
this License applicable to that copy.
3. Object Code Incorporating Material from Library Header Files.
The object code form of an Application may incorporate material from
a header file that is part of the Library. You may convey such object
code under terms of your choice, provided that, if the incorporated
material is not limited to numerical parameters, data structure
layouts and accessors, or small macros, inline functions and templates
(ten or fewer lines in length), you do both of the following:
a) Give prominent notice with each copy of the object code that the
Library is used in it and that the Library and its use are
covered by this License.
b) Accompany the object code with a copy of the GNU GPL and this license
document.
4. Combined Works.
You may convey a Combined Work under terms of your choice that,
taken together, effectively do not restrict modification of the
portions of the Library contained in the Combined Work and reverse
engineering for debugging such modifications, if you also do each of
the following:
a) Give prominent notice with each copy of the Combined Work that
the Library is used in it and that the Library and its use are
covered by this License.
b) Accompany the Combined Work with a copy of the GNU GPL and this license
document.
c) For a Combined Work that displays copyright notices during
execution, include the copyright notice for the Library among
these notices, as well as a reference directing the user to the
copies of the GNU GPL and this license document.
d) Do one of the following:
0) Convey the Minimal Corresponding Source under the terms of this
License, and the Corresponding Application Code in a form
suitable for, and under terms that permit, the user to
recombine or relink the Application with a modified version of
the Linked Version to produce a modified Combined Work, in the
manner specified by section 6 of the GNU GPL for conveying
Corresponding Source.
1) Use a suitable shared library mechanism for linking with the
Library. A suitable mechanism is one that (a) uses at run time
a copy of the Library already present on the user's computer
system, and (b) will operate properly with a modified version
of the Library that is interface-compatible with the Linked
Version.
e) Provide Installation Information, but only if you would otherwise
be required to provide such information under section 6 of the
GNU GPL, and only to the extent that such information is
necessary to install and execute a modified version of the
Combined Work produced by recombining or relinking the
Application with a modified version of the Linked Version. (If
you use option 4d0, the Installation Information must accompany
the Minimal Corresponding Source and Corresponding Application
Code. If you use option 4d1, you must provide the Installation
Information in the manner specified by section 6 of the GNU GPL
for conveying Corresponding Source.)
5. Combined Libraries.
You may place library facilities that are a work based on the
Library side by side in a single library together with other library
facilities that are not Applications and are not covered by this
License, and convey such a combined library under terms of your
choice, if you do both of the following:
a) Accompany the combined library with a copy of the same work based
on the Library, uncombined with any other library facilities,
conveyed under the terms of this License.
b) Give prominent notice with the combined library that part of it
is a work based on the Library, and explaining where to find the
accompanying uncombined form of the same work.
6. Revised Versions of the GNU Lesser General Public License.
The Free Software Foundation may publish revised and/or new versions
of the GNU Lesser General Public License from time to time. Such new
versions will be similar in spirit to the present version, but may
differ in detail to address new problems or concerns.
Each version is given a distinguishing version number. If the
Library as you received it specifies that a certain numbered version
of the GNU Lesser General Public License "or any later version"
applies to it, you have the option of following the terms and
conditions either of that published version or of any later version
published by the Free Software Foundation. If the Library as you
received it does not specify a version number of the GNU Lesser
General Public License, you may choose any version of the GNU Lesser
General Public License ever published by the Free Software Foundation.
If the Library as you received it specifies that a proxy can decide
whether future versions of the GNU Lesser General Public License shall
apply, that proxy's public statement of acceptance of any version is
permanent authorization for you to choose that version for the
Library.
././@PaxHeader 0000000 0000000 0000000 00000000026 00000000000 010213 x ustar 00 22 mtime=1710307256.0
gmpy2-2.2.1/INSTALL 0000644 0001750 0001750 00000005560 14574233670 012274 0 ustar 00case case Installing gmpy2 on Unix/Linux
------------------------------
Many Linux distributions provide gmpy2 in their repositories. Please check
your distribution's repositories first.
Requirements
------------
gmpy2 requires recent versions of GMP, MPFR and MPC. Specifically, gmpy2
requires GMP 5.0.0 or later, MPFR 3.1.0 or later, and MPC 1.0.0 or later.
Quick Instructions
------------------
To manually compile gmpy2, you will need to install the development libraries
for Python, GMP, MPFR, and MPC are installed. The package names vary between
distributions. "python-dev" or "python3.4-dev" are typical
package names for the Python development files. Installing the MPC development
package should automatically install the GMP and MPFR development packages.
"libmpc-dev" is a typical name for the MPC development package.
Once the required development libraries have been installed, compiling should
be as simple as:
$ cd
$ python setup.py build_ext
$ sudo python setup.py install
If this fails, read on.
Detailed Instructions
---------------------
If your Linux distribution does not support recent versions of GMP, MPFR and
MPC, you will need to compile your own versions. To avoid any possible conflict
with existing libraries on your system, it is recommended to build a statically
linked version of gmpy2. The following instructions assume the GMP, MPFR, MPC,
and gmpy2 source files are all located in $HOME/src and the static libraries
are installed into $HOME/static
1. Create the desired destination directory for the GMP, MPFR, and MPC
libraries.
$ mkdir $HOME/static
2. Download and un-tar the GMP source code. Change to GMP source directory and
compile GMP.
$ cd $HOME/src/gmp-6.0.0
$ ./configure --prefix=$HOME/static --enable-static --disable-shared --with-pic
$ make
$ make check
$ make install
3. Download and un-tar the MPFR source code. Change to MPFR source directory
and compile MPFR.
$ cd $HOME/src/mpfr-3.1.2
$ ./configure --prefix=$HOME/static --enable-static --disable-shared --with-pic --with-gmp=$HOME/static
$ make
$ make check
$ make install
4. Download and un-tar the MPC source code. Change to MPC source directory
and compile MPC.
$ cd $HOME/src/mpc-1.0.3
$ ./configure --prefix=$HOME/static --enable-static --disable-shared --with-pic --with-gmp=$HOME/static --with-mpfr=$HOME/static
$ make
$ make check
$ make install
5. Compile gmpy2 and specify the location of GMP, MPFR and MPC.
$ cd $HOME/src/gmpy2-2.1.0
$ python setup.py build_ext --static=$HOME/static install
If you get a "permission denied" error message, you may need to use:
$ python setup.py build_ext --static=$HOME/static
$ sudo python setup.py install
Installing gmpy2 on Windows
---------------------------
Please see windows_build.txt (preferred) or msys2_build.txt (alpha).
././@PaxHeader 0000000 0000000 0000000 00000000026 00000000000 010213 x ustar 00 22 mtime=1710307256.0
gmpy2-2.2.1/MANIFEST.in 0000644 0001750 0001750 00000000234 14574233670 012772 0 ustar 00case case include README.rst
include INSTALL
include COPYING
include docs/*
include test/*
include COPYING.LESSER
include src/*
include gmpy2/*.h
include gmpy2/*.pxd
././@PaxHeader 0000000 0000000 0000000 00000000034 00000000000 010212 x ustar 00 28 mtime=1721563243.6844618
gmpy2-2.2.1/PKG-INFO 0000644 0001750 0001750 00000005426 14647174154 012343 0 ustar 00case case Metadata-Version: 2.1
Name: gmpy2
Version: 2.2.1
Summary: gmpy2 interface to GMP, MPFR, and MPC for Python 3.7+
Author: Case Van Horsen
Maintainer-email: Case Van Horsen
License: LGPL-3.0+
Project-URL: Homepage, https://github.com/aleaxit/gmpy
Keywords: gmp,mpfr,mpc,multiple-precision,arbitrary-precision,precision,bignum
Classifier: Development Status :: 5 - Production/Stable
Classifier: Intended Audience :: Developers
Classifier: Intended Audience :: Science/Research
Classifier: License :: OSI Approved :: GNU Lesser General Public License v3 or later (LGPLv3+)
Classifier: Natural Language :: English
Classifier: Operating System :: MacOS :: MacOS X
Classifier: Operating System :: Microsoft :: Windows
Classifier: Operating System :: POSIX
Classifier: Programming Language :: C
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.7
Classifier: Programming Language :: Python :: 3.8
Classifier: Programming Language :: Python :: 3.9
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Programming Language :: Python :: Implementation :: CPython
Classifier: Topic :: Scientific/Engineering :: Mathematics
Classifier: Topic :: Software Development :: Libraries :: Python Modules
Requires-Python: >=3.7
Description-Content-Type: text/x-rst
License-File: COPYING
License-File: COPYING.LESSER
Provides-Extra: docs
Requires-Dist: sphinx>=4; extra == "docs"
Requires-Dist: sphinx-rtd-theme>=1; extra == "docs"
Provides-Extra: tests
Requires-Dist: pytest; extra == "tests"
Requires-Dist: hypothesis; extra == "tests"
Requires-Dist: cython; extra == "tests"
Requires-Dist: mpmath; extra == "tests"
Requires-Dist: setuptools; extra == "tests"
gmpy2 is an optimized, C-coded Python extension module that supports fast
multiple-precision arithmetic. gmpy2 is based on the original gmpy module.
gmpy2 adds support for correctly rounded multiple-precision real arithmetic
(using the MPFR library) and complex arithmetic (using the MPC library).
Version 2.2
-----------
gmpy2 2.2.1
-----------
* Bug fix: use C int instead of C char for some internal code. Issue
* Bug fix: add xmpz.bit_count method.
gmpy2 2.2.0
-----------
gmpy2 2.2.0 is now available with support for Python 3.7 to 3.13.
* Support for thread-safe contexts and context methods has been improved.
* Interoperability with Cython extensions has been updated.
* Extensive improvements have been made to the build and testing processes.
* Many bug fixes.
* Extensive documentation cleanup.
Availability
------------
gmpy2 is available at https://pypi.python.org/pypi/gmpy2/
Documentation is available at https://gmpy2.readthedocs.io/en/latest/
././@PaxHeader 0000000 0000000 0000000 00000000026 00000000000 010213 x ustar 00 22 mtime=1721552285.0
gmpy2-2.2.1/README.rst 0000644 0001750 0001750 00000001712 14647146635 012732 0 ustar 00case case gmpy2 is an optimized, C-coded Python extension module that supports fast
multiple-precision arithmetic. gmpy2 is based on the original gmpy module.
gmpy2 adds support for correctly rounded multiple-precision real arithmetic
(using the MPFR library) and complex arithmetic (using the MPC library).
Version 2.2
-----------
gmpy2 2.2.1
-----------
* Bug fix: use C int instead of C char for some internal code. Issue
* Bug fix: add xmpz.bit_count method.
gmpy2 2.2.0
-----------
gmpy2 2.2.0 is now available with support for Python 3.7 to 3.13.
* Support for thread-safe contexts and context methods has been improved.
* Interoperability with Cython extensions has been updated.
* Extensive improvements have been made to the build and testing processes.
* Many bug fixes.
* Extensive documentation cleanup.
Availability
------------
gmpy2 is available at https://pypi.python.org/pypi/gmpy2/
Documentation is available at https://gmpy2.readthedocs.io/en/latest/
././@PaxHeader 0000000 0000000 0000000 00000000034 00000000000 010212 x ustar 00 28 mtime=1721563243.6661284
gmpy2-2.2.1/docs/ 0000755 0001750 0001750 00000000000 14647174154 012167 5 ustar 00case case ././@PaxHeader 0000000 0000000 0000000 00000000026 00000000000 010213 x ustar 00 22 mtime=1710307256.0
gmpy2-2.2.1/docs/Makefile 0000644 0001750 0001750 00000011263 14574233670 013630 0 ustar 00case case # Makefile for Sphinx documentation
#
# You can set these variables from the command line.
SPHINXOPTS =
SPHINXBUILD = sphinx-build
PAPER =
BUILDDIR = _build
# Internal variables.
PAPEROPT_a4 = -D latex_paper_size=a4
PAPEROPT_letter = -D latex_paper_size=letter
ALLSPHINXOPTS = -d $(BUILDDIR)/doctrees $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) .
.PHONY: help clean html dirhtml singlehtml pickle json htmlhelp qthelp devhelp epub latex latexpdf text man changes linkcheck doctest
help:
@echo "Please use \`make ' where is one of"
@echo " html to make standalone HTML files"
@echo " dirhtml to make HTML files named index.html in directories"
@echo " singlehtml to make a single large HTML file"
@echo " pickle to make pickle files"
@echo " json to make JSON files"
@echo " htmlhelp to make HTML files and a HTML help project"
@echo " qthelp to make HTML files and a qthelp project"
@echo " devhelp to make HTML files and a Devhelp project"
@echo " epub to make an epub"
@echo " latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter"
@echo " latexpdf to make LaTeX files and run them through pdflatex"
@echo " text to make text files"
@echo " man to make manual pages"
@echo " changes to make an overview of all changed/added/deprecated items"
@echo " linkcheck to check all external links for integrity"
@echo " doctest to run all doctests embedded in the documentation (if enabled)"
create_static:
if [ ! -d _static ]; then mkdir _static; fi
clean:
-rm -rf $(BUILDDIR)/*
html: create_static
$(SPHINXBUILD) -b html $(ALLSPHINXOPTS) $(BUILDDIR)/html
@echo
@echo "Build finished. The HTML pages are in $(BUILDDIR)/html."
dirhtml: create_static
$(SPHINXBUILD) -b dirhtml $(ALLSPHINXOPTS) $(BUILDDIR)/dirhtml
@echo
@echo "Build finished. The HTML pages are in $(BUILDDIR)/dirhtml."
singlehtml: create_static
$(SPHINXBUILD) -b singlehtml $(ALLSPHINXOPTS) $(BUILDDIR)/singlehtml
@echo
@echo "Build finished. The HTML page is in $(BUILDDIR)/singlehtml."
pickle: create_static
$(SPHINXBUILD) -b pickle $(ALLSPHINXOPTS) $(BUILDDIR)/pickle
@echo
@echo "Build finished; now you can process the pickle files."
json: create_static
$(SPHINXBUILD) -b json $(ALLSPHINXOPTS) $(BUILDDIR)/json
@echo
@echo "Build finished; now you can process the JSON files."
htmlhelp:
$(SPHINXBUILD) -b htmlhelp $(ALLSPHINXOPTS) $(BUILDDIR)/htmlhelp
@echo
@echo "Build finished; now you can run HTML Help Workshop with the" \
".hhp project file in $(BUILDDIR)/htmlhelp."
qthelp:
$(SPHINXBUILD) -b qthelp $(ALLSPHINXOPTS) $(BUILDDIR)/qthelp
@echo
@echo "Build finished; now you can run "qcollectiongenerator" with the" \
".qhcp project file in $(BUILDDIR)/qthelp, like this:"
@echo "# qcollectiongenerator $(BUILDDIR)/qthelp/GMPY2.qhcp"
@echo "To view the help file:"
@echo "# assistant -collectionFile $(BUILDDIR)/qthelp/GMPY2.qhc"
devhelp:
$(SPHINXBUILD) -b devhelp $(ALLSPHINXOPTS) $(BUILDDIR)/devhelp
@echo
@echo "Build finished."
@echo "To view the help file:"
@echo "# mkdir -p $$HOME/.local/share/devhelp/GMPY2"
@echo "# ln -s $(BUILDDIR)/devhelp $$HOME/.local/share/devhelp/GMPY2"
@echo "# devhelp"
epub: create_static
$(SPHINXBUILD) -b epub $(ALLSPHINXOPTS) $(BUILDDIR)/epub
@echo
@echo "Build finished. The epub file is in $(BUILDDIR)/epub."
latex: create_static
$(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex
@echo
@echo "Build finished; the LaTeX files are in $(BUILDDIR)/latex."
@echo "Run \`make' in that directory to run these through (pdf)latex" \
"(use \`make latexpdf' here to do that automatically)."
latexpdf: create_static
$(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex
@echo "Running LaTeX files through pdflatex..."
make -C $(BUILDDIR)/latex all-pdf
@echo "pdflatex finished; the PDF files are in $(BUILDDIR)/latex."
text: create_static
$(SPHINXBUILD) -b text $(ALLSPHINXOPTS) $(BUILDDIR)/text
@echo
@echo "Build finished. The text files are in $(BUILDDIR)/text."
man: create_static
$(SPHINXBUILD) -b man $(ALLSPHINXOPTS) $(BUILDDIR)/man
@echo
@echo "Build finished. The manual pages are in $(BUILDDIR)/man."
changes:
$(SPHINXBUILD) -b changes $(ALLSPHINXOPTS) $(BUILDDIR)/changes
@echo
@echo "The overview file is in $(BUILDDIR)/changes."
linkcheck:
$(SPHINXBUILD) -b linkcheck $(ALLSPHINXOPTS) $(BUILDDIR)/linkcheck
@echo
@echo "Link check complete; look for any errors in the above output " \
"or in $(BUILDDIR)/linkcheck/output.txt."
doctest:
$(SPHINXBUILD) -b doctest $(ALLSPHINXOPTS) $(BUILDDIR)/doctest
@echo "Testing of doctests in the sources finished, look at the " \
"results in $(BUILDDIR)/doctest/output.txt."
././@PaxHeader 0000000 0000000 0000000 00000000026 00000000000 010213 x ustar 00 22 mtime=1710307256.0
gmpy2-2.2.1/docs/advmpz.rst 0000644 0001750 0001750 00000010415 14574233670 014221 0 ustar 00case case Integers (Advanced topics)
==========================
.. currentmodule:: gmpy2
gmpy2 provides access to an experimental integer type called `xmpz`. The
`xmpz` type is a mutable integer type. In-place operations (+=, //=,
etc.) modify the original object and do not create a new object. Instances of
`xmpz` cannot be used as dictionary keys.
.. doctest::
>>> from gmpy2 import xmpz
>>> a = xmpz(123)
>>> b = a
>>> a += 1
>>> a
xmpz(124)
>>> b
xmpz(124)
The ability to change an `xmpz` object in-place allows for efficient and
rapid bit manipulation.
Individual bits can be set or cleared:
.. doctest::
>>> a[10]=1
>>> a
xmpz(1148)
Slice notation is supported. The bits referenced by a slice can be either 'read
from' or 'written to'. To clear a slice of bits, use a source value of 0. In
2s-complement format, 0 is represented by an arbitrary number of 0-bits. To set
a slice of bits, use a source value of ~0. The *tilde* operator inverts, or
complements the bits in an integer. (~0 is -1 so you can also use -1.) In
2s-complement format, -1 is represented by an arbitrary number of 1-bits.
If a value for *stop* is specified in a slice assignment and the actual
bit-length of the `xmpz` is less than *stop*, then the destination
`xmpz` is logically padded with 0-bits to length *stop*.
.. doctest::
>>> a=xmpz(0)
>>> a[8:16] = ~0
>>> bin(a)
'0b1111111100000000'
>>> a[4:12] = ~a[4:12]
>>> bin(a)
'0b1111000011110000'
Bits can be reversed:
.. doctest::
>>> a = xmpz(1148)
>>> bin(a)
'0b10001111100'
>>> a[::] = a[::-1]
>>> bin(a)
'0b111110001'
The `~xmpz.iter_bits()` method returns a generator that returns True or
False for each bit position. The methods `~xmpz.iter_clear()`, and
`~xmpz.iter_set()` return generators that return the bit positions that are
1 or 0. The methods support arguments *start* and *stop* that define the
beginning and ending bit positions that are used. To mimic the behavior of
slices. the bit positions checked include *start* but the last position checked
is *stop* - 1.
.. doctest::
>>> a=xmpz(117)
>>> bin(a)
'0b1110101'
>>> list(a.iter_bits())
[True, False, True, False, True, True, True]
>>> list(a.iter_clear())
[1, 3]
>>> list(a.iter_set())
[0, 2, 4, 5, 6]
>>> list(a.iter_bits(stop=12))
[True, False, True, False, True, True, True, False, False, False, False, False]
The following program uses the Sieve of Eratosthenes to generate a list of
prime numbers.
.. code-block:: python
import time
import gmpy2
def sieve(limit=1000000):
'''Returns a generator that yields the prime numbers up to limit.'''
# Increment by 1 to account for the fact that slices do not include
# the last index value but we do want to include the last value for
# calculating a list of primes.
sieve_limit = gmpy2.isqrt(limit) + 1
limit += 1
# Mark bit positions 0 and 1 as not prime.
bitmap = gmpy2.xmpz(3)
# Process 2 separately. This allows us to use p+p for the step size
# when sieving the remaining primes.
bitmap[4 : limit : 2] = -1
# Sieve the remaining primes.
for p in bitmap.iter_clear(3, sieve_limit):
bitmap[p*p : limit : p+p] = -1
return bitmap.iter_clear(2, limit)
if __name__ == "__main__":
start = time.time()
result = list(sieve())
print(time.time() - start)
print(len(result))
The xmpz type
-------------
.. autoclass:: xmpz
:special-members: __format__
Advanced Number Theory Functions
--------------------------------
The following functions are based on mpz_lucas.c and mpz_prp.c by David
Cleaver.
A good reference for probable prime testing is
http://www.pseudoprime.com/pseudo.html
.. autofunction:: is_bpsw_prp
.. autofunction:: is_euler_prp
.. autofunction:: is_extra_strong_lucas_prp
.. autofunction:: is_fermat_prp
.. autofunction:: is_fibonacci_prp
.. autofunction:: is_lucas_prp
.. autofunction:: is_selfridge_prp
.. autofunction:: is_strong_bpsw_prp
.. autofunction:: is_strong_lucas_prp
.. autofunction:: is_strong_prp
.. autofunction:: is_strong_selfridge_prp
.. autofunction:: lucasu
.. autofunction:: lucasu_mod
.. autofunction:: lucasv
.. autofunction:: lucasv_mod
././@PaxHeader 0000000 0000000 0000000 00000000026 00000000000 010213 x ustar 00 22 mtime=1710307256.0
gmpy2-2.2.1/docs/conf.py 0000644 0001750 0001750 00000005615 14574233670 013473 0 ustar 00case case """
gmpy2 documentation build configuration file.
This file is execfile()d with the current directory set to its containing dir.
The contents of this file are pickled, so don't put values in the namespace
that aren't pickleable (module imports are okay, they're removed
automatically).
"""
import os
import sys
import packaging.version
import gmpy2
if sys.version_info < (3, 9):
raise RuntimeError("Python version >= 3.9 required to build docs.")
# Add any Sphinx extension module names here, as strings. They can be extensions
# coming with Sphinx (named 'sphinx.ext.*') or your custom ones.
extensions = ['sphinx.ext.autodoc', 'sphinx.ext.imgmath', 'sphinx.ext.doctest',
'sphinx.ext.intersphinx', 'sphinx_rtd_theme']
# The name of a reST role (builtin or Sphinx extension) to use as the
# default role, that is, for text marked up `like this`.
default_role = 'py:obj'
# Sphinx will warn about all references where the target cannot be found.
nitpicky = True
# This value selects if automatically documented members are sorted
# alphabetical (value 'alphabetical'), by member type (value 'groupwise')
# or by source order (value 'bysource').
autodoc_member_order = 'groupwise'
# The default options for autodoc directives. They are applied to all
# autodoc directives automatically.
autodoc_default_options = {'members': True}
# Contains mapping the locations and names of other projects that
# should be linked to in this documentation.
intersphinx_mapping = {'python': ('https://docs.python.org/3/', None)}
# Add any paths that contain templates here, relative to this directory.
templates_path = ['_templates']
# General information about the project.
project = gmpy2.__package__
copyright = '2012 - 2024, Case Van Horsen'
gmpy2_version = packaging.version.parse(gmpy2.__version__)
# The version info for the project you're documenting, acts as replacement for
# |version| and |release|, also used in various other places throughout the
# built documents.
#
# The short X.Y version.
version = f"{gmpy2_version.major}.{gmpy2_version.minor}"
# The full version, including alpha/beta/rc tags.
release = gmpy2.__version__
# The theme to use for HTML and HTML Help pages. See the documentation for
# a list of builtin themes.
html_theme = 'sphinx_rtd_theme'
# Grouping the document tree into LaTeX files. List of tuples
# (source start file, target name, title, author, documentclass [howto/manual]).
latex_documents = [('index', 'gmpy2.tex', 'gmpy2 Documentation',
'Case Van Horsen', 'manual')]
# One entry per manual page. List of tuples
# (source start file, name, description, authors, manual section).
man_pages = [('index', 'gmpy2', 'gmpy2 Documentation', ['Case Van Horsen'], 3)]
# Python code that is treated like it were put in a testcleanup directive
# for *every* file that is tested, and for every group.
doctest_global_cleanup = """
import gmpy2
gmpy2.set_context(gmpy2.context())
"""
././@PaxHeader 0000000 0000000 0000000 00000000026 00000000000 010213 x ustar 00 22 mtime=1710307256.0
gmpy2-2.2.1/docs/contexts.rst 0000644 0001750 0001750 00000001412 14574233670 014564 0 ustar 00case case .. _contexts:
Contexts
========
.. currentmodule:: gmpy2
`context()` creates a new context. `set_context()` will set the active
context. `get_context()` will return a reference to the active context. Note
that contexts are mutable: modifying the reference returned by `get_context()`
will modify the active context until a new context is enabled with
`set_context()`. The `context.copy()` method will return a copy of the
context. Contexts that implement the standard *single*, *double*, and
*quadruple* precision floating point types can be created using `ieee()`.
Context Type
------------
.. autoclass:: context
Context Functions
-----------------
.. autofunction:: get_context
.. autofunction:: ieee
.. autofunction:: local_context
.. autofunction:: set_context
././@PaxHeader 0000000 0000000 0000000 00000000026 00000000000 010213 x ustar 00 22 mtime=1710307256.0
gmpy2-2.2.1/docs/conversion.rst 0000644 0001750 0001750 00000003216 14574233670 015106 0 ustar 00case case .. currentmodule:: gmpy2
Conversion Methods
==================
A python object could interact with gmpy2 if it implements one of the following methods:
- ``__mpz__`` : return an object of type `mpz`.
- ``__mpq__`` : return an object of type `mpq`.
- ``__mpfr__`` : return an object of type `mpfr`.
- ``__mpc__`` : return an object of type `mpc`.
Implementing on of these methods allow gmpy2 to convert a python object into a gmpy2 type.
Example:
.. doctest::
>>> from gmpy2 import mpz
>>> class CustInt:
... def __init__(self, x):
... self.x = x
... def __mpz__(self):
... return mpz(self.x)
...
>>> ci = CustInt(5)
>>> z = mpz(ci); z
mpz(5)
>>> type(z)
Arithmetic operations
---------------------
gmpy2 allow arithmetic operations between gmpy2 numbers and objects with
conversion methods. Operation with object that implements floating conversion
and exact conversion methods are not supported. That means that only the
following cases are supported:
- An integer type have to implement ``__mpz__``
- A rational type have to implement ``__mpq__`` and can implement ``__mpz__``
- A real type have to implement ``__mpfr__``
- A complex type have to implement ``__mpc__`` and can implement ``__mpfr__``
Examples:
.. doctest::
>>> import gmpy2
>>> from gmpy2 import mpz, mpq, mpfr, mpc
>>> gmpy2.set_context(gmpy2.context())
>>> class Q:
... def __mpz__(self): return mpz(1)
... def __mpq__(self): return mpq(3,2)
>>> q = Q()
>>> mpz(2) + q
mpq(7,2)
>>> mpq(1,2) * q
mpq(3,4)
>>> mpfr(10) * q
mpfr('15.0')
././@PaxHeader 0000000 0000000 0000000 00000000026 00000000000 010213 x ustar 00 22 mtime=1710307256.0
gmpy2-2.2.1/docs/cython.rst 0000644 0001750 0001750 00000010221 14574233670 014217 0 ustar 00case case Cython usage
============
.. currentmodule:: gmpy2
The gmpy2 module provides a C-API that can be conveniently used from Cython.
All types and functions are declared in the header gmpy2.pxd that is installed
automatically in your Python path together with the library.
Initialization
--------------
In order to use the C-API you need to make one call to the function **void import_gmpy2(void)**.
Types
-----
The types `mpz`, `mpq`, `mpfr` and `mpc` are
declared as extension types in gmpy2.pxd. They correspond respectively to the C
structures **MPZ_Object**, **MPQ_Object**, **MPFR_Object** and **MPC_Object**.
Fast type checking can be done with the following C functions
**bint MPZ_Check(object)**
equivalent to **isinstance(obj, mpz)**
**bint MPQ_Check(object)**
equivalent to **isinstance(obj, mpq)**
**bint MPFR_Check(object)**
equivalent to **isinstance(obj, mpfr)**
**bint MPC_Check(object)**
equivalent to **isinstance(obj, mpc)**
Object creation
---------------
To create a new gmpy2 types there are four basic functions
**mpz GMPy_MPZ_New(void * ctx)**
create a new mpz object from a given context ctx
**mpq GMPy_MPQ_New(void * ctx)**
create a new mpq object from a given context ctx
**mpfr MPFR_New(void * ctx, mpfr_prec_t prec)**
create a new mpfr object with given context ctx and precision prec
**mpc MPC_New(void * ctx, mpfr_prec_t rprec, mpfr_prec_t iprec)**
create a new mpc object with given context ctx, precisions rprec and iprec of
respectively real and imaginary parts
The context can be set to **NULL** and controls the default behavior (e.g. precision).
The gmpy2.pxd header also provides convenience macro to wrap a (copy of) a mpz_t, mpq_t, mpfr_t
or a mpc_t object into the corresponding gmpy2 type.
**mpz GMPy_MPZ_From_mpz(mpz_srcptr z)**
return a new mpz object with a given mpz_t value z
**mpq GMPy_MPQ_From_mpq(mpq_srcptr q)**
return a new mpq object from a given mpq_t value q
**mpq GMPy_MPQ_From_mpz(mpz_srcptr num, mpz_srcptr den)**
return a new mpq object with a given mpz_t numerator num and mpz_t denominator den
**mpfr GMPy_MPFR_From_mpfr(mpfr_srcptr x)**
return a new mpfr object with a given mpfr_t value x
**mpc GMPy_MPC_From_mpc(mpc_srcptr c)**
return a new mpc object with a given mpc_t value c
**mpc GMPy_MPC_From_mpfr(mpfr_srcptr re, mpfr_srcptr im)**
return a new mpc object with a given mpfr_t real part re and mpfr_t imaginary part im
Access to the underlying C type
--------------------------------
Each of the gmpy2 objects has a field corresponding to the underlying C
type. The following functions give access to this field
**mpz_t MPZ(mpz)**
**mpq_t MPQ(mpq)**
**mpfr_t MPFR(mpfr)**
**mpc_t MPC(mpc)**
Compilation
------------
The header gmpy2.pxd as well as the C header gmpy2.h from which it depends
are installed in the Python path. In order to make Cython and the C compiler aware
of the existence of these files, the Python path should be part of the include
directories.
Recall that **import_gmpy2()** needs to be called *before* any other function of
the C-API.
Here is a minimal example of a Cython file test_gmpy2.pyx:
.. code-block:: cython
"A minimal cython file test_gmpy2.pyx"
from gmpy2 cimport *
cdef extern from "gmp.h":
void mpz_set_si(mpz_t, long)
import_gmpy2() # needed to initialize the C-API
cdef mpz z = GMPy_MPZ_New(NULL)
mpz_set_si(MPZ(z), -7)
print(z + 3)
The corresponding setup.py is given below.
.. code-block:: python
"A minimal setup.py for compiling test_gmpy2.pyx"
import sys
from setuptools import Extension, setup
from Cython.Build import cythonize
ext = Extension("test_gmpy2", ["test_gmpy2.pyx"],
include_dirs=sys.path, libraries=['gmp', 'mpfr', 'mpc'])
setup(name="cython_gmpy_test",
ext_modules=cythonize([ext], include_path=sys.path))
With these two files in the same repository, you should be able to compile your
module using
.. code-block:: shell
$ python setup.py build_ext --inplace
For more about compilation and installation of cython files and extension
modules, please refer to the official documentation of Cython and distutils.
././@PaxHeader 0000000 0000000 0000000 00000000026 00000000000 010213 x ustar 00 22 mtime=1710307256.0
gmpy2-2.2.1/docs/exceptions.rst 0000644 0001750 0001750 00000000424 14574233670 015100 0 ustar 00case case Exceptions
----------
.. currentmodule:: gmpy2
.. autoexception:: RangeError
.. autoexception:: InexactResultError
.. autoexception:: OverflowResultError
.. autoexception:: UnderflowResultError
.. autoexception:: InvalidOperationError
.. autoexception:: DivisionByZeroError
././@PaxHeader 0000000 0000000 0000000 00000000026 00000000000 010213 x ustar 00 22 mtime=1710307256.0
gmpy2-2.2.1/docs/generic.rst 0000644 0001750 0001750 00000000420 14574233670 014327 0 ustar 00case case Generic Functions
-----------------
.. currentmodule:: gmpy2
.. autofunction:: add
.. autofunction:: div
.. autofunction:: mul
.. autofunction:: sub
.. autofunction:: square
.. autofunction:: f2q
.. autofunction:: fma
.. autofunction:: fms
.. autofunction:: cmp_abs
././@PaxHeader 0000000 0000000 0000000 00000000026 00000000000 010213 x ustar 00 22 mtime=1721370662.0
gmpy2-2.2.1/docs/history.rst 0000644 0001750 0001750 00000054044 14646404046 014424 0 ustar 00case case Release Notes
=============
.. currentmodule:: gmpy2
Changes in gmpy2 2.2.1
----------------------
* Fix internal use of char when int should be used. (jamesjer)
* Add :meth:`xmpz.bit_count`. (skirpichev)
Changes in gmpy2 2.2.0
----------------------
* Remove support for versions of Python < 3.7. (skirpichev)
* Support more modern build tools. (skirpichev)
* Use contextvars to manage gmpy2 contexts. (casevh)
* _mpmath functions now use vectorcall protocol. (casevh)
* Many documentation updates. (skirpichev)
* Add :meth:`mpz.as_integer_ratio()` / :meth:`mpz.to_bytes()` and
:meth:`mpz.from_bytes()`. (skirpichev)
* Add :func:`is_probab_prime()` to directly expose the GMP
behavior. (skirpichev)
* :func:`gcd()`/:func:`lcm()` now uses vectorcall protocol. (skirpichev)
* Expose :class:`context` type. (skirpichev)
* Correct error in :func:`is_strong_bpsw_prp()`. (casevh)
* Added :func:`prev_prime()` when GMP >= 6.3. (sethtroisi)
* Change argument order of :func:`jn()` and :func:`yn()` to match
MPFR. (casevh)
* Fix documentation and code for
:func:`is_extra_strong_lucas_prp()`. (casevh)
Changes in gmpy2 2.1.5
----------------------
* Version bump to fix wheel issues. No code changes.
Changes in gmpy2 2.1.4
----------------------
* Version bump to fix wheel issues. No code changes.
Changes in gmpy2 2.1.3
----------------------
* Fix mpz(-3).is_prime().
* Add powmod_sec().
* Fix mpfr('inf') and mpfr('nan') if subnormalization is enabled.
* powmod() and powmod_sec() release the GIL.
* Fix error messages for iroot(x,n) for large n.
* Add powmod_base_list() and powmod_exp_list() (experimental).
* Fix gmpy2.mpq(mpq, int).
* Fix issues with INF, NAN, and mpfr("-0") when subnormalization is True
Changes in gmpy2 2.1.2
----------------------
* Code cleanup.
* Support Apple Silicon binary wheels.
* is_prime(-2) now returns False. Issue #312.
Changes in gmpy2 2.1.1
----------------------
* Code cleanup.
* Properly return NOTIMPLEMENTED for unsupported arguments in
``**``. Issue #319.
Changes in gmpy2 2.1.0
----------------------
* Improvements to setup.py.
* Add thread-safe contexts.
* MPFR and MPC are now required.
* Invalid Operation exception now raised for addition, etc.
* inverse() now raises exception if inverse does not exist.
* Add context methods.
* Major code refactoring required to properly support thread-safe contexts.
* `` __str__`` and ``__repr__`` no longer append "L" on Python 2.
* mpq(mpfr) now returns the exact result.
* Fix repr(mpc) for precision >325 bits.
* Intermediate conversions of Integer to mpfr are now done with the
full precision of the Integer.
* Remove support for interaction with Decimal type.
* No longer attempt to override the memory allocation functions.
* Register gmpy2 types into the numeric tower.
* mpz(x) call int(x) if mpz() does not know how to convert x directly.
* Convert `mpz` to a type using ``__new__`` instead of a factory function.
* Bug fix for ``<> ** <>``.
* Compile with Python 3.11.
Changes in gmpy2 2.1.0rc2
-------------------------
* Documentation updates.
* Improvements to build environment.
Changes in gmpy2 2.1.0rc1
-------------------------
* Added support for embedded underscore characters in string literals.
* Allow GIL release for `mpz`/`xmpz`/`mpq` types only.
Changes in gmpy2 2.1.0b6
------------------------
* Improve argument type processing by saving type information to
decrease the number of type check calls. Especially helpful
for `mpfr` and `mpc` types. (Not complete but common operations
are done.)
* Resolve bug in `mpfr` to `mpq` conversion; issue #287.
* Added limited support for releasing the GIL; disabled by default;
see `context.allow_release_gil`.
* Refactored handling of inplace operations for `mpz` and `xmpz` types;
inplace operations on `xmpz` will only return an `xmpz` result.
* Refactored handling of conversion to C integer types. Some
exception types changes to reflect Python types.
* `gcd()` and `lcm()` now support more than two arguments to align with
the corresponding functions in the math module.
Changes in gmpy2 2.1.0b5
------------------------
* Avoid MPFR bug in mfr_fac_ui (`factorial()`) on platforms where
long is 32-bits and argument is >= 44787929.
* Fixed testing bugs with Python 2.7.
* Fixed ``mpz(0)`` to C long or long long.
* Fixed incorrect results in `f2q()`.
* Adjust test suite to reflect changes in output in MPFR 4.1.0.
Changes in gmpy2 2.1.0b4
------------------------
* Fix comparisons with `mpq` and custom rational objects.
* Fixes for some uncommon integer conversions scenarios.
Changes in gmpy2 2.1.0b3
------------------------
* Version bump only.
Changes in gmpy2 2.1.0b2
------------------------
* Many bug fixes.
Changes in gmpy2 2.1.0b1
------------------------
* Added `cmp()` and `cmp_abs()`.
* Improved compatibility with the :mod:`numbers` module protocol.
* Many bug fixes.
Changes in gmpy2 2.1.a05
------------------------
* Fix `qdiv()` not returning `mpz` when it should.
* Added `root_of_unity()`.
Changes in gmpy2 2.1.0a4
------------------------
* Fix issue 204; missing file for Cython.
* Additional support for MPFR 4
- Add `fmma()` and `fmms()`.
Changes in gmpy2 2.1.0a3
------------------------
* Updates to ``setup.py``.
* Initial support for MPFR4
- Add `mpfr_nrandom()`
- `mpfr_grandom()` now calls nrandom twice; may return different values
versus MPFR3.
- Add `rootn()`; same as `root()` except different sign when taking even
root of -0.0.
Changes in gmpy2 2.1.0a2
------------------------
* Revised build process.
* Removal of unused code/macros.
* Cleanup of Cython interface.
Changes in gmpy2 2.1.0a1
------------------------
* Thread-safe contexts are now supported. Properly integrating thread-safe
contexts required an extensive rewrite of almost all internal functions.
* MPFR and MPC are now required. It is no longer possible to build a version
of gmpy2 that only supports the GMP library.
* The function ``inverse()`` now raises an exception if the inverse does not
exist.
* Context methods have been added for MPFR/MPC related functions.
* A new context option (`~context.rational_division`) has been added that
changes the behavior of integer division involving `mpz` instances to return
a rational result instead of a floating point result.
* gmpy2 types are now registered in the numeric tower of the
:mod:`numbers` module.
* In previous versions of gmpy2, ``mpz()`` was a factory function that
returned an `mpz` instance. It is now an actual type. The same
is true for the other gmpy2 types.
* If a Python object has an ``__mpz__`` method, it will be called bye ``mpz()``
to allow an unrecognized type to be converted to an mpz instance. The same is
true for the other gmpy2 types.
* A new C-API and Cython interface has been added.
Changes in gmpy2 2.0.4
----------------------
* Fix `bit_scan0()` for negative values.
* Changes to ``setup.py`` to allow static linking.
* Fix performance regression with mpmath and Python 3.
Changes in gmpy2 2.0.3
----------------------
* Fix `lucas2()` and `atanh()`; they were returning incorrect values.
Changes in gmpy2 2.0.2
----------------------
* Rebuild Windows binary installers due to MPIR 2.6.0 bug in `next_prime()`.
* Another fix for `is_extra_strong_lucas_prp()`.
Changes in gmpy2 2.0.1
----------------------
* Updated ``setup.py`` to work in more situations.
* Corrected exception handling in basic operations with `mpfr` type.
* Correct ``InvalidOperation`` exception not raised in certain circumstances.
* `invert()` now raises an exception if the modular inverse does not exist.
* Fixed internal exception in `is_bpsw_prp()` and `is_strong_bpsw_prp()`.
* Updated `is_extra_strong_lucas_prp()` to latest version.
Changes in gmpy2 2.0.0
----------------------
* Fix segmentation fault in ``_mpmath_normalize()`` (an undocumented helper
function for mpmath). (casevh)
* Fix issues when compiled without support for MPFR. (casevh)
* Conversion of too large an `mpz` to `float` now raises `OverflowError`
instead of returning ``inf``. (casevh)
* Renamed ``min2()/max2()`` to `minnum()`/`maxnum()`. (casevh)
* The build and install process (i.e. ``setup.py``) has been completely
rewritten. See the Installation section for more information. (casevh)
* `get_context()` no longer accepts keyword arguments. (casevh)
Known issues in gmpy2 2.0.0
-----------------------------
* The test suite is still incomplete.
Changes in gmpy2 2.0.0b4
------------------------
* Added ``__ceil__()``, ``__floor__()``, ``__trunc__()``, and ``__round__()``
methods to `mpz` and `mpq` types. (casevh)
* Added ``__complex__()`` to `mpc` type. (casevh)
* ``round(mpfr)`` now correctly returns an `mpz` type. (casevh)
* Add mpz.denominator and mpz.numerator. (casevh)
* If no arguments are given to `mpz`, `mpq`, `mpfr`, `mpc`, and `xmpz`,
return 0 of the appropriate type. (casevh)
* Fix broken comparison between `mpz` and `mpq` when `mpz` is on
the left. (casevh)
* Added ``__sizeof__()`` to all types. Note: :func:`sys.getsizeof` calls
``__sizeof__()`` to get the memory size of a gmpy2 object. The returned
value reflects the size of the allocated memory which may be larger than
the actual minimum memory required by the object. (casevh)
Known issues in gmpy2 2.0.0b4
-----------------------------
* The new test suite (``test/runtest.py``) is incomplete and some tests fail on
Python 2.x due to formatting issues.
Changes in gmpy2 2.0.0b3
------------------------
* `mp_version()`, `mpc_version()`, and `mpfr_version()` now return normal
strings on Python 2.x instead of Unicode strings. (casevh)
* Fix warnings when shifting 32-bit integer by 32 bits. (casevh)
* Faster conversion of the standard library `~fractions.Fraction` type
to `mpq`. (casevh)
* Improved conversion of the `~decimal.Decimal` type to `mpfr`. (casevh)
* Consistently return `OverflowError` when converting ``inf``. (casevh)
* Fix `mpz.__format__()` when the format code includes "#". (casevh)
* Add `is_infinite()` and deprecate ``is_inf()``. (casevh)
* Add `is_finite()` and deprecate ``is_number()``. (casevh)
* Fixed the various ``is_XXX()`` tests when used with `mpc`. (casevh)
* Fixed error handling with mpc(); mpc(1,"nan") is properly handled. (casevh)
* Added caching for `mpc` objects. (casevh)
* Faster code path for basic operation is both operands are `mpfr`
or `mpc`. (casevh)
* Fix `mpfr` + `float` segmentation fault. (casevh)
Changes in gmpy2 2.0.0b2
------------------------
* Allow `xmpz` slice assignment to increase length of `xmpz` instance by
specifying a value for stop. (casevh)
* Fixed reference counting bug in several ``is_xxx_prp()`` tests. (casevh)
* Added `~xmpz.iter_bits()`, `~xmpz.iter_clear()`, `~xmpz.iter_set()` methods
to `xmpz`. (casevh)
* Added `powmod()` for easy access to three argument :func:`pow()`. (casevh)
* Removed ``addmul()`` and ``submul()`` which were added in 2.0.0b1 since they
are slower than just using Python code. (casevh)
* Bug fix in gcd_ext when both arguments are not `mpz`. (casevh)
* Added `ieee()` to create contexts for 32, 64, or 128 bit `float`'s. (casevh)
* Bug fix in `context()` not setting `~context.emax`/`~context.emin` correctly
if they had been changed earlier. (casevh)
* Contexts can be directly used in with statement without requiring
`set_context()`/`local_context()` sequence. (casevh)
* `local_context()` now accepts an optional context. (casevh)
Changes in gmpy2 2.0.0b1
------------------------
* Rename to gmpy2 to allow backwards incompatible changes (casevh)
* Renamed 'mpf' to 'mpfr' to reflect use of MPFR (casevh)
* Renamed functions that manipulate individual bits to ``bit_XXX()`` to align
with :meth:`~int.bit_length()`.
* Added caching for `mpq`. (casevh)
* Added ``rootrem()``, `fib2()`, `lucas()`, `lucas2()`. (casevh)
* Support changed hash function in Python 3.2. (casevh)
* Added `is_even()`, `is_odd()`. (casevh)
* Add caching of the calculated hash value. (casevh)
* Add `xmpz` (mutable `mpz`) type. (casevh)
* Fix `mpq` formatting issue. (casevh)
* Add read/write bit access using slices to `xmpz`. (casevh)
* Add read-only bit access using slices to `mpz`. (casevh)
* Add `pack()`/`unpack()` methods to split/join an integer into n-bit
chunks. (casevh)
* Add support for MPFR (casevh)
* Removed fcoform float conversion modifier. (casevh)
* Add support for MPC. (casevh)
* Added context manager. (casevh)
* Allow building with just GMP/MPIR if MPFR not available. (casevh)
* Allow building with GMP/MPIR and MPFR if MPC not available. (casevh)
* Removed most instance methods in favor of gmpy2.function. The general
guideline is that *properties* of an instance can be done via instance
methods but *functions* that return a new result are done using
gmpy2.function. (casevh)
* Added ``__ceil__()``, ``__floor__()``, and ``__trunc__()`` methods since they
are called by :func:`math.ceil()`, :func:`math.floor()`, and
:func:`math.trunc()`. (casevh)
* Removed ``gmpy2.pow()`` to avoid conflicts. (casevh)
* Removed ``gmpy2._copy()`` and added `xmpz.copy()`. (casevh)
* Added support for ``__format__()``. (casevh)
* Added ``as_integer_ratio()``, ``as_mantissa_exp()``,
``as_simple_fraction()``. (casevh)
* Updated rich_compare. (casevh)
* Require MPFR 3.1.0+ to get divby0 support. (casevh)
* Added `fsum()`, `degrees()`, `radians()`. (casevh)
* Updated random number generation support. (casevh)
* Changed license to LGPL 3+. (casevh)
* Added `lucasu()`, `lucasu_mod()`, `lucasv()`, and `lucasv_mod()`. (casevh)
*Based on code contributed by David Cleaver.*
* Added probable-prime tests. (casevh)
*Based on code contributed by David Cleaver.*
* Added `to_binary()`/`from_binary()`. (casevh)
* Renamed ``numdigits()`` to `~mpz.num_digits()`. (casevh)
* Added keyword precision to constants. (casevh)
* Added ``addmul()`` and ``submul()``. (casevh)
* Added ``__round__()``, `round2()`, `round_away()` for `mpfr`. (casevh)
* ``round()`` is no longer a module level function. (casevh)
* Renamed module functions ``min()/max()`` to ``min2()/max2()``. (casevh)
No longer conflicts with builtin :func:`min()` and :func:`max()`
* Removed ``set_debug()`` and related functionality. (casevh)
* Removed mpf.setprec(), use mpf.round() (casevh)
* Fix test compatibility with Python 3.1.2 and 3.2 (casevh)
* Remove old random number functions, to be replaced later (casevh)
* Remove tagoff option (casevh)
* Debug messages only available if compiled with -DDEBUG (casevh)
* Renamed context() -> local_context(), new_context() -> context() (casevh)
* Added get_context() (casevh)
Changes in gmpy 1.11
--------------------
* Recognize True/False (bug in 1.10) (casevh)
* Optimize argument handling (casevh)
* Added caching for mpz (casevh)
Changes in gmpy 1.10
--------------------
* Remove dependancy on pymemcompat.h (casevh)
* Remove callback (casevh)
* Added support for -DMPIR to include MPIR instead of GMP (casevh)
* Major code revisions to add support for Python 3.x (casevh)
* Fixed bug in binary() and qbinary() (casevh)
* Fixed bug in rich comparisons (casevh)
* Added % and divmod support to mpq and mpf (casevh)
* Changed memory allocation functions to use PyMem (casevh)
* Removed small number interning (casevh)
* Added tdivmod, cdivmod, and fdivmod (casevh)
* Added more helper functions for mpmath (casevh)
* Faster mpz<>PyLong conversion (casevh)
* Faster hash(mpz) (casevh)
Changes in gmpy 1.04
--------------------
* Avoid GMP/mingw32 bug when converting very small floats to mpz. (casevh)
* Significant performance improvement for long->mpz and mpz->long. (casevh)
* Added "rich comparisons" to mpz, mpq and mpf types (aleaxit)
* Added additional tests (casevh, aleaxit)
* Fixed bug when converting very large mpz to str (casevh)
* Faster conversion from mpz->binary and binary->mpz (casevh)
* Added support for pickling (casevh)
* Added divexact (casevh)
* Fixed mpf comparisons by rounding mpf results when GMP returns
a longer result. Added fround() (casevh)
* Added bit_length (Thanks Mario Pernici)
* Added helper functions for mpmath (casevh)
* Faster conversion from mpq->binary and binary->mpq (casevh)
* Recognize MPIR, mpir_version() (casevh)
Changes in gmpy 1.03
--------------------
* Fixed the bug that caused crashes on gmpy.mpf(float('inf')) and
other such conversions, implicit and explicit
* Fixed a bug in get_zconst's prototype affecting 64-bit machines,
thanks to Gary Bunting
* Fixed a bug in hashing on 64-bit systems. hash(long) now equals
hash(mpz) for large values. (casevh)
* Changed int() to return a long value instead of OverFlowError.
Complies with PEP 237. (casevh)
* Added support in setup.py for darwinports/macports build of GMP
on MacOSX. (aleaxit)
Changes in gmpy 1.02
--------------------
* fix warning in comparison of mpq's
* added support of mpq('12.34') [[string w/o a slash, but with a dot]]
* fixes for 64-bit build (thanks to a patch by dmcooke)
* added experimental support for decimal.Decimal (and user-coded types)
via wider use of special conversion methods (if present) and their
sly insertion on-the-fly into the decimal.Decimal class (!)
* two bugfixes, thanks to Simon Burton
* Brought back into C89 compliance (thanks to Chip Turner), had
drifted to C99 (declarations in the middle of the code).
* Python 2.5 support (Py_ssize_t, __index__) thanks to Chip Turner
* Pushed coverage to 93.3% (missing only "sanity check" level error
tests [mostly for out-of-memory conditions], output to stderr
conditioned by global.debug, & a couple of very obscure cases)
Changes in gmpy 1.01
--------------------
* cleanups, ensure support for Python 2.4.1 on MacOSX 10.4/XCode 2.1
as well as Python 2.2 and 2.3 (on MacOSX and Linux)
* fixed memory leak on divm (thanks to mensanator@aol.com)
* fixed bug on mpq('123') [[str2mpq on string w/o a slash]]
* added floordiv and truediv operators, and tests for them
* NOT tested on GMP 3 (have none left around...), ONLY on GMP 4.*
Changes in gmpy 1.0
-------------------
* minor cleanups, ensure support for Python 2.3
* fixed misdiagnosis of some argument counts in macro
* SELF_ONE_ARG_CONVERTED (tx to Paul Rubin!)
Changes in gmpy 0.9
-------------------
* change ValueError to OverflowError for 'too-large' errors
* fix bug in mpq_pow (negative base, exp. with odd denominator)
(fix now corrected -- _even_ denominator is the error!)
* fixed gcc warnings reported by K. Briggs
* support GMP 4 (but added no GMP4-only functionality yet)
* updated tests to 0.9, better coverage
Changes in gmpy 0.8
-------------------
(again, requests & suggestions by great Pearu!)
* raise test coverage 72.5% -> 90.0%
* introduced callbacks (not documented/tested for now;
Pearu will test/support/document in PySymbolic)
* some errors went undiagnosed, caused crash: now fixed
* workaround for GMP bug(?s?) in mpz_fits\_... (?)
* added exposure of mpf\_ sqrt and pow_ui
Changes in gmpy 0.7
-------------------
Good feedback from Keith Briggs, some advice from Tim Peters and Fred Lundh ---
thanks all!
* fixed bug of '"%d" where "%ld" was meant' in many places
and other sundry minor warnings given by gcc
* fixed hash (delegating to Python) so mp[nqz](x) will
produce the same value as hash(x) for any Python number x
* workaround for GMP 3.1.1 bug, mpz_root wrongly returning
'exact' for non-exact root if dest==source, which stopped
needed value-error for inexact mpq**mpq operations
* determined correct 'actual precision' of floats
* explicitly stored precision with binary-form mpf's
* extended explicit-bits request to all ->mpf operations
(good in itself, plus, preparing for future MPFR)
* removed the limitation of no binary-form for <0 mpz
* introduced macros to parse args, for conciseness
Changes in gmpy 0.6
-------------------
(lots of good ideas from Pearu once more!-)
* fixed silly bugs in kronecker and mpq_abs
* gmpy-level workaround for scan0/scan1 bugs (?) in gmp 3.1.1
* added qdiv; anynum->mpq substituted for all such conversions
(also anynum->mpz and anynum->mpf by analogy, with care!)
* added global.fcoform for optional use of intermediate string in
float2mpf (used for any float->mpf conversion)
* added set_fcoform function for global.fcoform access
* general cleanup of sources; added alloca for msvc++;
- many sundry minor bugfixes & uniformization;
- a little useful refactoring (more would be good...)
* added caching of mpq objects
* power for mpq
* stern-brocot algorithm for mpf->mpq (also exposed as f2q)
- also used for float->mpq
- with stricter tracking of mpf's requested-precision
- added getrprec method to mpf, getrprec module-function
* exposed ceil, floor and trunc methods/functions for mpf's
* changed a couple exceptions from value to zerodivision
* added 'qual' and 'floa' options to gmpy.rand
Changes in gmpy 0.5
-------------------
* added jacobi, legendre, kronecker
* added random-number generation, seed set/save, shuffling
* added mpq (at last!-)
Changes in gmpy 0.4
-------------------
* split gmpy.c/gmpy.h introducing C-API interface (Pearu's suggestion)
* cleanup some casts using Pearu's new macros
* further cache-tweaks at Pearu's suggestion (macros introduced)
* added sign (Pearu's request), getbit, setbit
* added docstrings
* renamed copy functions to start with _ ('internal, private')
* added .comb as a synonym of .bincoef
Changes in gmpy 0.3
-------------------
* performance tweaks via mpz-caching & fixed-constants
* added get/set functions for zcache, zco min/max
* added get-only function for versions (of gmp, and of gmpy)
* removed all 'traces' of mutability (to be re-done... much later!)
* cleaned up all of the mpz_cmp_ui(X,0) to mpz_sgn(X)
* cleaned up Py_BuildValue usage (N vs O, explicit-() for tuples)
* added numdigits, lowbits, root, next_prime, invert, popcount,
* hamdist, scan0, scan1
* renamed bin to bincoef
Changes in gmpy 0.2
-------------------
15 Nov 2000
* pre-alpha: bugfixes re formatting (tx, Peanu!)
* no tags on oct() and hex() of mpz's
* insert 'tagoff' in options (gmpy.mpz() vs mpz() in repr) (for Peanu!)
* speedups for _nonzero & _cmp (tx, Peanu!)
* slight speedup (7/8%?) for excess reallocs 4<->8 bytes (Peanu's help!)
* added copy/fcopy; bin; fib; remove
Changes in gmpy 0.1
-------------------
6 Nov 2000
* pre-alpha --- first placed on sourceforge
././@PaxHeader 0000000 0000000 0000000 00000000026 00000000000 010213 x ustar 00 22 mtime=1710307256.0
gmpy2-2.2.1/docs/index.rst 0000644 0001750 0001750 00000002070 14574233670 014025 0 ustar 00case case Welcome to gmpy2's documentation!
=================================
gmpy2 is a C-coded Python extension module that supports multiple-precision
arithmetic. It is the successor to the original gmpy module (supported only
the GMP library). gmpy2 adds support for the MPFR (correctly rounded real
floating-point arithmetic) and MPC (correctly rounded complex floating-point
arithmetic) libraries.
The following libraries are supported:
* GMP for integer and rational arithmetic (https://gmplib.org)
* MPFR (https://www.mpfr.org)
* MPC (https://www.multiprecision.org/mpc/)
* Generalized Lucas sequences and primality tests are based on the following
code:
* mpz_lucas: https://sourceforge.net/projects/mpzlucas/
* mpz_prp: https://sourceforge.net/projects/mpzprp/
Contents
--------
.. toctree::
:maxdepth: 2
overview
install
tutorial
mpz
advmpz
mpq
contexts
exceptions
mpfr
mpc
generic
misc
cython
conversion
history
Indices and tables
==================
* :ref:`genindex`
* :ref:`search`
.. * :ref:`modindex`
././@PaxHeader 0000000 0000000 0000000 00000000026 00000000000 010213 x ustar 00 22 mtime=1711300127.0
gmpy2-2.2.1/docs/install.rst 0000644 0001750 0001750 00000002466 14600057037 014364 0 ustar 00case case Installation
============
gmpy2 requires CPython 3.7 or above. Pre-compiled binary wheels are available
on PyPI. You can install latest release with pip::
pip install gmpy2
or some specific version with::
pip install gmpy2==2.1.5
From Sources
------------
If pre-compiled binary wheels aren't available for your platform, the pip will
fallback to installation from sources. In this case you will need to have
required libraries (GMP, MPFR and MPC) already installed on your system, along
with the include files for those libraries. On Debian you can install them
systed-wide with::
sudo apt install libgmp-dev libmpfr-dev libmpc-dev
.. tip::
On Windows we recommend using `MSYS2 `_ to build
the gmpy2 from sources. To install required dependencies before, run::
pacman -S gcc gmp-devel mpfr-devel mpc-devel python-setuptools python-pip
If you are a developer or like to get the latest updates as they come, be sure
to install from the git repository and include required extra dependencies,
for example the optional "tests" list, which include packages required
for testing::
git clone git://github.com/aleaxit/gmpy.git
cd gmpy
pip install -e .[tests]
Next you may want to run full set of unit tests to make sure everything works::
pytest test/
././@PaxHeader 0000000 0000000 0000000 00000000026 00000000000 010213 x ustar 00 22 mtime=1710307256.0
gmpy2-2.2.1/docs/make.bat 0000755 0001750 0001750 00000010635 14574233670 013602 0 ustar 00case case @ECHO OFF
REM Command file for Sphinx documentation
if "%SPHINXBUILD%" == "" (
set SPHINXBUILD=sphinx-build
)
set BUILDDIR=_build
set ALLSPHINXOPTS=-d %BUILDDIR%/doctrees %SPHINXOPTS% .
if NOT "%PAPER%" == "" (
set ALLSPHINXOPTS=-D latex_paper_size=%PAPER% %ALLSPHINXOPTS%
)
if "%1" == "" goto help
if "%1" == "help" (
:help
echo.Please use `make ^` where ^ is one of
echo. html to make standalone HTML files
echo. dirhtml to make HTML files named index.html in directories
echo. singlehtml to make a single large HTML file
echo. pickle to make pickle files
echo. json to make JSON files
echo. htmlhelp to make HTML files and a HTML help project
echo. qthelp to make HTML files and a qthelp project
echo. devhelp to make HTML files and a Devhelp project
echo. epub to make an epub
echo. latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter
echo. text to make text files
echo. man to make manual pages
echo. changes to make an overview over all changed/added/deprecated items
echo. linkcheck to check all external links for integrity
echo. doctest to run all doctests embedded in the documentation if enabled
goto end
)
if "%1" == "clean" (
for /d %%i in (%BUILDDIR%\*) do rmdir /q /s %%i
del /q /s %BUILDDIR%\*
goto end
)
if "%1" == "html" (
%SPHINXBUILD% -b html %ALLSPHINXOPTS% %BUILDDIR%/html
if errorlevel 1 exit /b 1
echo.
echo.Build finished. The HTML pages are in %BUILDDIR%/html.
goto end
)
if "%1" == "dirhtml" (
%SPHINXBUILD% -b dirhtml %ALLSPHINXOPTS% %BUILDDIR%/dirhtml
if errorlevel 1 exit /b 1
echo.
echo.Build finished. The HTML pages are in %BUILDDIR%/dirhtml.
goto end
)
if "%1" == "singlehtml" (
%SPHINXBUILD% -b singlehtml %ALLSPHINXOPTS% %BUILDDIR%/singlehtml
if errorlevel 1 exit /b 1
echo.
echo.Build finished. The HTML pages are in %BUILDDIR%/singlehtml.
goto end
)
if "%1" == "pickle" (
%SPHINXBUILD% -b pickle %ALLSPHINXOPTS% %BUILDDIR%/pickle
if errorlevel 1 exit /b 1
echo.
echo.Build finished; now you can process the pickle files.
goto end
)
if "%1" == "json" (
%SPHINXBUILD% -b json %ALLSPHINXOPTS% %BUILDDIR%/json
if errorlevel 1 exit /b 1
echo.
echo.Build finished; now you can process the JSON files.
goto end
)
if "%1" == "htmlhelp" (
%SPHINXBUILD% -b htmlhelp %ALLSPHINXOPTS% %BUILDDIR%/htmlhelp
if errorlevel 1 exit /b 1
echo.
echo.Build finished; now you can run HTML Help Workshop with the ^
.hhp project file in %BUILDDIR%/htmlhelp.
goto end
)
if "%1" == "qthelp" (
%SPHINXBUILD% -b qthelp %ALLSPHINXOPTS% %BUILDDIR%/qthelp
if errorlevel 1 exit /b 1
echo.
echo.Build finished; now you can run "qcollectiongenerator" with the ^
.qhcp project file in %BUILDDIR%/qthelp, like this:
echo.^> qcollectiongenerator %BUILDDIR%\qthelp\GMPY2.qhcp
echo.To view the help file:
echo.^> assistant -collectionFile %BUILDDIR%\qthelp\GMPY2.ghc
goto end
)
if "%1" == "devhelp" (
%SPHINXBUILD% -b devhelp %ALLSPHINXOPTS% %BUILDDIR%/devhelp
if errorlevel 1 exit /b 1
echo.
echo.Build finished.
goto end
)
if "%1" == "epub" (
%SPHINXBUILD% -b epub %ALLSPHINXOPTS% %BUILDDIR%/epub
if errorlevel 1 exit /b 1
echo.
echo.Build finished. The epub file is in %BUILDDIR%/epub.
goto end
)
if "%1" == "latex" (
%SPHINXBUILD% -b latex %ALLSPHINXOPTS% %BUILDDIR%/latex
if errorlevel 1 exit /b 1
echo.
echo.Build finished; the LaTeX files are in %BUILDDIR%/latex.
goto end
)
if "%1" == "text" (
%SPHINXBUILD% -b text %ALLSPHINXOPTS% %BUILDDIR%/text
if errorlevel 1 exit /b 1
echo.
echo.Build finished. The text files are in %BUILDDIR%/text.
goto end
)
if "%1" == "man" (
%SPHINXBUILD% -b man %ALLSPHINXOPTS% %BUILDDIR%/man
if errorlevel 1 exit /b 1
echo.
echo.Build finished. The manual pages are in %BUILDDIR%/man.
goto end
)
if "%1" == "changes" (
%SPHINXBUILD% -b changes %ALLSPHINXOPTS% %BUILDDIR%/changes
if errorlevel 1 exit /b 1
echo.
echo.The overview file is in %BUILDDIR%/changes.
goto end
)
if "%1" == "linkcheck" (
%SPHINXBUILD% -b linkcheck %ALLSPHINXOPTS% %BUILDDIR%/linkcheck
if errorlevel 1 exit /b 1
echo.
echo.Link check complete; look for any errors in the above output ^
or in %BUILDDIR%/linkcheck/output.txt.
goto end
)
if "%1" == "doctest" (
%SPHINXBUILD% -b doctest %ALLSPHINXOPTS% %BUILDDIR%/doctest
if errorlevel 1 exit /b 1
echo.
echo.Testing of doctests in the sources finished, look at the ^
results in %BUILDDIR%/doctest/output.txt.
goto end
)
:end
././@PaxHeader 0000000 0000000 0000000 00000000026 00000000000 010213 x ustar 00 22 mtime=1710307256.0
gmpy2-2.2.1/docs/misc.rst 0000644 0001750 0001750 00000000553 14574233670 013655 0 ustar 00case case Miscellaneous Functions
-----------------------
.. currentmodule:: gmpy2
.. autofunction:: digits
.. autofunction:: from_binary
.. autofunction:: license
.. autofunction:: mp_limbsize
.. autofunction:: mp_version
.. autofunction:: mpc_version
.. autofunction:: mpfr_version
.. autofunction:: random_state
.. autofunction:: to_binary
.. autofunction:: version
././@PaxHeader 0000000 0000000 0000000 00000000026 00000000000 010213 x ustar 00 22 mtime=1710307256.0
gmpy2-2.2.1/docs/mpc.rst 0000644 0001750 0001750 00000001531 14574233670 013476 0 ustar 00case case Multiple-precision Complex
==========================
.. currentmodule:: gmpy2
mpc Type
--------
.. autoclass:: mpc
:special-members: __format__
mpc Functions
-------------
.. autofunction:: acos
.. autofunction:: acosh
.. autofunction:: asin
.. autofunction:: asinh
.. autofunction:: atan
.. autofunction:: atanh
.. autofunction:: cos
.. autofunction:: cosh
.. autofunction:: div_2exp
.. autofunction:: exp
.. autofunction:: is_nan
.. autofunction:: is_zero
.. autofunction:: log
.. autofunction:: log10
.. autofunction:: mpc_random
.. autofunction:: mul_2exp
.. autofunction:: norm
.. autofunction:: phase
.. autofunction:: polar
.. autofunction:: proj
.. autofunction:: rect
.. autofunction:: root_of_unity
.. autofunction:: sin
.. autofunction:: sin_cos
.. autofunction:: sinh
.. autofunction:: sqrt
.. autofunction:: tan
.. autofunction:: tanh
././@PaxHeader 0000000 0000000 0000000 00000000026 00000000000 010213 x ustar 00 22 mtime=1710307256.0
gmpy2-2.2.1/docs/mpfr.rst 0000644 0001750 0001750 00000004716 14574233670 013673 0 ustar 00case case Multiple-precision Reals
========================
.. currentmodule:: gmpy2
mpfr Type
---------
.. autoclass:: mpfr
:special-members: __format__
mpfr Functions
--------------
.. autofunction:: agm
.. autofunction:: ai
.. autofunction:: atan2
.. autofunction:: cbrt
.. autofunction:: ceil
.. autofunction:: check_range
.. autofunction:: cmp
.. autofunction:: const_catalan
.. autofunction:: const_euler
.. autofunction:: const_log2
.. autofunction:: const_pi
.. autofunction:: cot
.. autofunction:: coth
.. autofunction:: csc
.. autofunction:: csch
.. autofunction:: degrees
.. autofunction:: digamma
.. autofunction:: eint
.. autofunction:: erf
.. autofunction:: erfc
.. autofunction:: exp10
.. autofunction:: exp2
.. autofunction:: expm1
.. autofunction:: factorial
.. autofunction:: floor
.. autofunction:: fmma
.. autofunction:: fmms
.. autofunction:: fmod
.. autofunction:: frac
.. autofunction:: frexp
.. autofunction:: fsum
.. autofunction:: gamma
.. autofunction:: gamma_inc
.. autofunction:: get_exp
.. autofunction:: hypot
.. autofunction:: inf
.. autofunction:: is_finite
.. autofunction:: is_infinite
.. autofunction:: is_regular
.. autofunction:: is_signed
.. autofunction:: is_unordered
.. autofunction:: j0
.. autofunction:: j1
.. autofunction:: jn
.. autofunction:: lgamma
.. autofunction:: li2
.. autofunction:: lngamma
.. autofunction:: log1p
.. autofunction:: log2
.. autofunction:: maxnum
.. autofunction:: minnum
.. autofunction:: modf
.. autofunction:: mpfr_from_old_binary
.. autofunction:: mpfr_grandom
.. autofunction:: mpfr_nrandom
.. autofunction:: mpfr_random
.. autofunction:: nan
.. autofunction:: next_above
.. autofunction:: next_below
.. autofunction:: radians
.. autofunction:: rec_sqrt
.. autofunction:: reldiff
.. autofunction:: remainder
.. autofunction:: remquo
.. autofunction:: rint
.. autofunction:: rint_ceil
.. autofunction:: rint_floor
.. autofunction:: rint_round
.. autofunction:: rint_trunc
.. autofunction:: root
.. autofunction:: rootn
.. autofunction:: round2
.. autofunction:: round_away
.. autofunction:: sec
.. autofunction:: sech
.. autofunction:: set_exp
.. autofunction:: set_sign
.. autofunction:: sign
.. autofunction:: sinh_cosh
.. autofunction:: trunc
.. autofunction:: y0
.. autofunction:: y1
.. autofunction:: yn
.. autofunction:: zero
.. autofunction:: zeta
.. autofunction:: get_max_precision
.. autofunction:: get_emax_max
.. autofunction:: get_emin_min
.. autofunction:: copy_sign
.. autofunction:: can_round
.. autofunction:: free_cache
././@PaxHeader 0000000 0000000 0000000 00000000026 00000000000 010213 x ustar 00 22 mtime=1710307256.0
gmpy2-2.2.1/docs/mpq.rst 0000644 0001750 0001750 00000000212 14574233670 013507 0 ustar 00case case Rationals
=========
.. currentmodule:: gmpy2
mpq type
--------
.. autoclass:: mpq
mpq Functions
-------------
.. autofunction:: qdiv
././@PaxHeader 0000000 0000000 0000000 00000000026 00000000000 010213 x ustar 00 22 mtime=1710307256.0
gmpy2-2.2.1/docs/mpz.rst 0000644 0001750 0001750 00000004300 14574233670 013522 0 ustar 00case case Integers
========
.. currentmodule:: gmpy2
mpz type
--------
.. autoclass:: mpz
:special-members: __format__
mpz Functions
-------------
.. autofunction:: bincoef
.. autofunction:: bit_clear
.. autofunction:: bit_count
.. autofunction:: bit_flip
.. autofunction:: bit_length
.. autofunction:: bit_mask
.. autofunction:: bit_scan0
.. autofunction:: bit_scan1
.. autofunction:: bit_set
.. autofunction:: bit_test
.. autofunction:: c_div
.. autofunction:: c_div_2exp
.. autofunction:: c_divmod
.. autofunction:: c_divmod_2exp
.. autofunction:: c_mod
.. autofunction:: c_mod_2exp
.. autofunction:: comb
.. autofunction:: divexact
.. autofunction:: divm
.. autofunction:: double_fac
.. autofunction:: f_div
.. autofunction:: f_div_2exp
.. autofunction:: f_divmod
.. autofunction:: f_divmod_2exp
.. autofunction:: f_mod
.. autofunction:: f_mod_2exp
.. autofunction:: fac
.. autofunction:: fib
.. autofunction:: fib2
.. autofunction:: gcd
.. autofunction:: gcdext
.. autofunction:: hamdist
.. autofunction:: invert
.. autofunction:: iroot
.. autofunction:: iroot_rem
.. autofunction:: is_congruent
.. autofunction:: is_divisible
.. autofunction:: is_even
.. autofunction:: is_odd
.. autofunction:: is_power
.. autofunction:: is_prime
.. autofunction:: is_probab_prime
.. autofunction:: is_square
.. autofunction:: isqrt
.. autofunction:: isqrt_rem
.. autofunction:: jacobi
.. autofunction:: kronecker
.. autofunction:: lcm
.. autofunction:: legendre
.. autofunction:: lucas
.. autofunction:: lucas2
.. autofunction:: mpz_random
.. autofunction:: mpz_rrandomb
.. autofunction:: mpz_urandomb
.. autofunction:: multi_fac
.. autofunction:: next_prime
.. autofunction:: num_digits
.. autofunction:: pack
.. autofunction:: popcount
.. autofunction:: powmod
.. autofunction:: powmod_exp_list
.. autofunction:: powmod_base_list
.. autofunction:: powmod_sec
.. function:: prev_prime(x, /) -> mpz
Return the previous *probable* prime number < x.
Only present when compiled with GMP 6.3.0 or later.
.. autofunction:: primorial
.. autofunction:: remove
.. autofunction:: t_div
.. autofunction:: t_div_2exp
.. autofunction:: t_divmod
.. autofunction:: t_divmod_2exp
.. autofunction:: t_mod
.. autofunction:: t_mod_2exp
.. autofunction:: unpack
././@PaxHeader 0000000 0000000 0000000 00000000026 00000000000 010213 x ustar 00 22 mtime=1710307256.0
gmpy2-2.2.1/docs/overview.rst 0000644 0001750 0001750 00000002507 14574233670 014571 0 ustar 00case case Overview
========
.. currentmodule:: gmpy2
The `mpz` and `mpq` types support arbitrary precision integers and rationals
via the GMP library. These types should be drop-in replacements for Python's
`int`'s and `~fractions.Fraction`'s, but are significantly faster for large
values. The cutover point for performance varies, but can be as low as 20 to
40 digits. All the special integer functions in the GMP are supported.
.. warning::
gmpy2 can crash the Python interpreter in case of memory allocation
failure. To mitigate this feature of memory management in the GMP library,
you should estimate the size of all results and prevent calculations that
can exaust available memory.
The `mpfr` and `mpc` types provide support for correctly rounded multiple
precision real and complex arithmetic via the MPFR and MPC libraries. The
`context` type is used to control precision, rounding modes, and exceptional
conditions. For example, division by zero can either return an Infinity or
raise an exception. It is possible to specify different precision and rounding
modes for both the real and imaginary components of an `mpc`. The default
precision is 53 bits --- just same as for Python's `float` and `complex` types.
Operator overloading is fully supported. Coversion from native Python types is
optimized for performance.
././@PaxHeader 0000000 0000000 0000000 00000000026 00000000000 010213 x ustar 00 22 mtime=1710307256.0
gmpy2-2.2.1/docs/tutorial.rst 0000644 0001750 0001750 00000011162 14574233670 014563 0 ustar 00case case Tutorial
========
.. currentmodule:: gmpy2
Start by importing the contents of the package with:
.. doctest::
>>> from gmpy2 import *
.. note::
The use of ``from gmpy2 import *`` is not recommended in real code. The
names in gmpy2 have been chosen to avoid conflict with Python's builtin
names but gmpy2 does use names that may conflict with other modules or
variable names. In normal usage you’ll probably only want to import the
classes and functions that you actually need.
Lets look first on some examples of arbitrary precision arithmetic with
integer and rational types:
.. doctest::
>>> mpz(99) * 43
mpz(4257)
>>> pow(mpz(99), 37, 59)
mpz(18)
>>> isqrt(99)
mpz(9)
>>> isqrt_rem(99)
(mpz(9), mpz(18))
>>> gcd(123, 27)
mpz(3)
>>> lcm(123, 27)
mpz(1107)
>>> (mpz(123) + 12) / 5
mpfr('27.0')
>>> (mpz(123) + 12) // 5
mpz(27)
>>> (mpz(123) + 12) / 5.0
mpfr('27.0')
>>> mpz('123') + 1
mpz(124)
>>> 10 - mpz(1)
mpz(9)
>>> is_prime(17)
True
>>> mpz('1_000_000')
mpz(1000000)
>>> mpq(3, 7)/7
mpq(3,49)
>>> mpq(45, 3) * mpq(11, 8)
mpq(165,8)
>>> mpq(1, 7) * 11
mpq(11,7)
But gmpy2 also supports correctly rounded multiple precision real and complex
arithmetic. The following example shows how to control precision settings and
rounding modes:
.. doctest::
>>> mpfr('1.2')
mpfr('1.2')
>>> mpfr(float('1.2'))
mpfr('1.2')
>>> ctx = get_context()
>>> ctx.precision
53
>>> ctx.precision = 100
>>> mpfr('1.2')
mpfr('1.2000000000000000000000000000006',100)
>>> mpfr(float('1.2'))
mpfr('1.1999999999999999555910790149937',100)
>>> ctx.precision = 53
>>> ctx.round = RoundUp
>>> const_pi()
mpfr('3.1415926535897936')
>>> ctx.round = RoundToNearest
>>> const_pi()
mpfr('3.1415926535897931')
You have seen, that if the precision is changed, then ``mpfr(float('1.2'))``
differs from ``mpfr('1.2')``. To take advantage of the higher precision
provided by the `mpfr` type, always pass constants as strings.
Floating point contexts also are used to control exceptional conditions. For
example, division by zero can either return a floating-point positive infinity
(default) or raise an exception.
.. doctest::
>>> ctx.divzero
False
>>> mpfr(1)/0
mpfr('inf')
>>> ctx.trap_divzero = True
>>> mpfr(1)/0
Traceback (most recent call last):
...
gmpy2.DivisionByZeroError: division by zero
>>> ctx.divzero
True
Exceptions are normally raised in Python when the result of a real operation is
not defined over the reals; for example, ``math.sqrt(-2)`` will raise a
:exc:`ValueError` exception. The default context in gmpy2 implements similar
behavior, but by setting :attr:`~context.allow_complex` flag, complex results
will be returned.
.. doctest::
>>> sqrt(mpfr(-2))
mpfr('nan')
>>> ctx.allow_complex = True
>>> sqrt(mpfr(-2))
mpc('0.0+1.4142135623730951j')
Contexts can also be used as context managers in conjunction with Python's
:keyword:`with` statement to temporarily change the current context settings
for a block of code.
.. doctest::
>>> print(const_pi())
3.1415926535897931
>>> with context(precision=100) as ctx:
... print(const_pi())
... ctx.precision += 20
... print(const_pi())
...
3.1415926535897932384626433832793
3.1415926535897932384626433832795028847
>>> print(const_pi())
3.1415926535897931
It's possible to set different precision settings for real and imaginary
components.
.. doctest::
>>> ctx = get_context()
>>> ctx.real_prec = 60
>>> ctx.imag_prec = 70
>>> sqrt(mpc('1+2j'))
mpc('1.272019649514068965+0.78615137775742328606947j',(60,70))
All gmpy2 numeric types support Python's "new style" string formatting
available in `formatted string literals
`_ or with
:meth:`str.format`; see `Format Specification Mini-Language
`_ for a description
of the standard formatting syntax. The precision value optionally can be
followed by the rounding mode type ('U' to round toward plus infinity, 'D' to
round toward minus infinity, 'Y' to round away from zero, 'Z' to round toward
zero and 'N' - round to the nearest value.
.. doctest::
>>> a = mpfr("1.23456")
>>> "{0:15.3f}".format(a)
' 1.235'
>>> "{0:15.3Uf}".format(a)
' 1.235'
>>> "{0:15.3Df}".format(a)
' 1.234'
>>> "{0:.3Df}".format(a)
'1.234'
>>> "{0:+.3Df}".format(a)
'+1.234'
././@PaxHeader 0000000 0000000 0000000 00000000026 00000000000 010213 x ustar 00 22 mtime=1714352810.0
gmpy2-2.2.1/docs/win_build.rst 0000644 0001750 0001750 00000003776 14613571252 014703 0 ustar 00case case :orphan:
Building for Windows
====================
A new build approach is being tested for the final gmpy2 v2.2.x release.
The GMP, MPFR, and MPC DLLs are created using the MinGW64 compiler suite and
are linked to UCRT. The final gmpy2 binaries are created using Visual Studio.
MSYS2 Steps
-----------
1. Install MSYS2
1. Upgrade the initial installation::
pacman -Syuu
2. Reboot and launch the "MSYS2 UCRT" terminal window. Upgrade the user
system::
pacman -Syu
3. Install the MinGW64 compiler suite that links with ucrt::
pacman -Sy mingw-w64-ucrt-x86_64-gcc
4. Install rquired tools::
pacman -Sy patch m4 lzip wget tar make diffutils git
2. Create a temporary working directory for the build::
mkdir ~/temp
3. Clone (or download) the full gmpy2 source code::
cd ~/temp
git clone https://github.com/aleaxit/gmpy.git
cd gmpy
4. Download and compile GMP, MPFR, and MPC:
bash scripts/cibw_before_all.sh
Visual Studio Steps
-------------------
1. Launch the "Visual Studio x64 Native Tools Command Prompt" shell.
2. Change to location of the build directory::
cd c:\msys64\home\\temp\gmpy
3. Run::
scripts\cibw_before_all_windows.bat
4. Compile and install Windows binary wheels, e.g. for CPython 3.12::
py -3.12 -m pip install --upgrade build pytest hypothesis cython mpmath
set CIBUILDWHEEL=1
py -3.12 -m build --wheel --no-isolation
py -3.12 -m pip install dist\gmpy2-*312-*.whl --force-reinstall
5. Run the test suite::
py -3.12 -m pytest test/
6. Compile the C-API demo program::
cd demo
py -3.12 setup.py build_ext
cd build\lib.win-amd64-cpython-312
py -3.12
>>> import gmpy2
>>> import gmpy2_demo
>>> dir(gmpy2_demo)
['__doc__', '__file__', '__loader__', '__name__', '__package__', '__spec__', 'factor']
>>> gmpy2_demo.factor(123456789)
[(mpz(3), mpz(2)), (mpz(3607), mpz(1)), (mpz(3803), mpz(1))]
././@PaxHeader 0000000 0000000 0000000 00000000034 00000000000 010212 x ustar 00 28 mtime=1721563243.6661284
gmpy2-2.2.1/gmpy2/ 0000755 0001750 0001750 00000000000 14647174154 012275 5 ustar 00case case ././@PaxHeader 0000000 0000000 0000000 00000000026 00000000000 010213 x ustar 00 22 mtime=1710307256.0
gmpy2-2.2.1/gmpy2/__init__.pxd 0000644 0001750 0001750 00000000033 14574233670 014543 0 ustar 00case case from gmpy2.gmpy2 cimport *
././@PaxHeader 0000000 0000000 0000000 00000000026 00000000000 010213 x ustar 00 22 mtime=1710307256.0
gmpy2-2.2.1/gmpy2/__init__.py 0000644 0001750 0001750 00000000634 14574233670 014407 0 ustar 00case case from .gmpy2 import *
from .gmpy2 import __version__
# Internal variables/functions are not imported by * above.
# These are used by some python level functions and are needed
# at the top level.
# Use try...except to for static builds were _C_API is not available.
try:
from .gmpy2 import _C_API, _mpmath_normalize, _mpmath_create
except ImportError:
from .gmpy2 import _mpmath_normalize, _mpmath_create
././@PaxHeader 0000000 0000000 0000000 00000000026 00000000000 010213 x ustar 00 22 mtime=1710307256.0
gmpy2-2.2.1/gmpy2/gmpy2.h 0000644 0001750 0001750 00000044465 14574233670 013517 0 ustar 00case case /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* gmpy2.h *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Python interface to the GMP, MPFR, and MPC multiple precision *
* libraries. *
* *
* Copyright 2000 - 2009 Alex Martelli *
* *
* Copyright 2008 - 2024 Case Van Horsen *
* *
* This file is part of GMPY2. *
* *
* GMPY2 is free software: you can redistribute it and/or modify it under *
* the terms of the GNU Lesser General Public License as published by the *
* Free Software Foundation, either version 3 of the License, or (at your *
* option) any later version. *
* *
* GMPY2 is distributed in the hope that it will be useful, but WITHOUT *
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or *
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public *
* License for more details. *
* *
* You should have received a copy of the GNU Lesser General Public *
* License along with GMPY2; if not, see *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
/*
gmpy C API extension header file.
Part of Python's gmpy module since version 0.4
Created by Pearu Peterson , November 2000.
Edited by A. Martelli , December 2000.
Edited by Case Van Horsen , 2009, 2010, 2011.
Version 1.02, February 2007.
Version 1.03, June 2008
Version 1.04, June 2008 (no changes)
Version 1.05, February 2009 (support MPIR)
Version 1.20, January 2010 (remove obsolete MS hacks) casevh
Version 2.00, April 2010 (change to gmpy2) casevh
October 2010 (added Py_hash_t) casevh
December 2010 (added mpfr, mpc) casevh
January 2011 (add Pygmpy_context) casevh
April 2011 (split into multiple files) casevh
Version 2.10 August 2014 (reflect major rewrite during 2013/2014) casevh
*/
#ifndef Py_GMPYMODULE_H
#define Py_GMPYMODULE_H
#ifdef __cplusplus
extern "C" {
#endif
/* Structure of gmpy2.h
*
* Revised 17-APR-2017 casevh
*
* 1. Checks for specific Python versions.
* 2. Include headers for GMP/MPIR, MPFR, and MPC.
* 3. Define public C-API.
* 1. Define gmpy2 types.
* 2. Define the public API.
*
*/
/* Check for minimum Python version requirements. */
#if PY_VERSION_HEX < 0x03070000
# error "GMPY2 requires Python 3.7 or later."
#endif
/* Include headers for GMP, MPFR, and MPC. */
#include
#include
#include
/* Check MPFR and MPC versions. */
/* gmpy2 supports the two most recent major versions of MPFR and MPC.
*
* As of gmpy2 2.2.0, the code assumes the MPFR version is at least 4.1.0
* and new features included in 4.2.0 are guarded by #ifdef MPFR_420.
* For MPC, the minumum version is assumed to 1.2.1 and new features
* included in 1.3.0 are guarded by #ifdef MPC_130.
*
*/
#if (!defined(MPFR_VERSION) || (MPFR_VERSION < MPFR_VERSION_NUM(4,1,0)))
# error "GMPY2 requires MPFR 4.1.0 or later."
#endif
#if (defined(MPFR_VERSION) && (MPFR_VERSION >= MPFR_VERSION_NUM(4,2,0)))
# define MPFR_420
#endif
#if (!defined(MPC_VERSION) || (MPC_VERSION < MPC_VERSION_NUM(1,2,1)))
# error "GMPY2 requires MPC 1.2.1 or later."
#endif
#if (defined(MPC_VERSION) && (MPC_VERSION == MPC_VERSION_NUM(1,3,0)))
# define MPC_130
#endif
/* GMPY2 Public API */
/* Types
* MPZ_Object
* XMPZ_Object (mutable version of MPZ_Object)
* MPQ_Object
* XMPQ_Object (mutable version of MPQ_Object)
* MPFR_Object
* XMPFR_Object (mutable version of MPFR_Object)
* MPC_Object
* XMPC_Object (mutable version of MPC_Object)
* CTXT_Object
* RandomState_Object
*/
typedef struct {
PyObject_HEAD
mpz_t z;
Py_hash_t hash_cache;
} MPZ_Object;
typedef struct {
PyObject_HEAD
mpz_t z;
} XMPZ_Object;
typedef struct {
PyObject_HEAD
mpq_t q;
Py_hash_t hash_cache;
} MPQ_Object;
typedef struct {
PyObject_HEAD
mpfr_t f;
Py_hash_t hash_cache;
int rc;
} MPFR_Object;
typedef struct {
PyObject_HEAD
mpc_t c;
Py_hash_t hash_cache;
int rc;
} MPC_Object;
typedef struct {
PyObject_HEAD
gmp_randstate_t state;
} RandomState_Object;
typedef struct {
mpfr_prec_t mpfr_prec; /* current precision in bits, for MPFR */
mpfr_rnd_t mpfr_round; /* current rounding mode for float (MPFR) */
mpfr_exp_t emax; /* maximum exponent */
mpfr_exp_t emin; /* minimum exponent */
int subnormalize; /* if 1, subnormalization is performed */
int underflow; /* did an underflow occur? */
int overflow; /* did an overflow occur? */
int inexact; /* was the result inexact? */
int invalid; /* invalid operation (i.e. NaN)? */
int erange; /* did a range error occur? */
int divzero; /* divided by zero? */
int traps; /* if 0, do not trap any exceptions */
/* if not 0, then raise traps per bits above */
mpfr_prec_t real_prec; /* current precision in bits, for Re(MPC) */
mpfr_prec_t imag_prec; /* current precision in bits, for Im(MPC) */
mpfr_rnd_t real_round; /* current rounding mode for Re(MPC) */
mpfr_rnd_t imag_round; /* current rounding mode for Im(MPC) */
int allow_complex; /* if 1, allow mpfr functions to return an mpc */
int rational_division; /* if 1, mpz/mpz returns an mpq result */
int allow_release_gil; /* if 1, allow mpz functions to release the GIL */
} gmpy_context;
typedef struct {
PyObject_HEAD
gmpy_context ctx;
PyObject *token;
} CTXT_Object;
#define MPZ(obj) (((MPZ_Object*)(obj))->z)
#define MPQ(obj) (((MPQ_Object*)(obj))->q)
#define MPFR(obj) (((MPFR_Object*)(obj))->f)
#define MPC(obj) (((MPC_Object*)(obj))->c)
/* Start of the C-API definitions */
#define MPZ_Type_NUM 0
#define XMPZ_Type_NUM 1
#define MPQ_Type_NUM 2
#define XMPQ_Type_NUM 3
#define MPFR_Type_NUM 4
#define XMPFR_Type_NUM 5
#define MPC_Type_NUM 6
#define XMPC_Type_NUM 7
#define CTXT_Type_NUM 8
#define RandomState_Type_NUM 10
/* The following functions are found in gmpy2_cache. */
#define GMPy_MPZ_New_NUM 11
#define GMPy_MPZ_New_RETURN MPZ_Object *
#define GMPy_MPZ_New_PROTO (CTXT_Object *context)
#define GMPy_MPZ_NewInit_NUM 12
#define GMPy_MPZ_NewInit_RETURN PyObject *
#define GMPy_MPZ_NewInit_PROTO (PyTypeObject *type, PyObject *args, PyObject *keywds)
#define GMPy_MPZ_Dealloc_NUM 13
#define GMPy_MPZ_Dealloc_RETURN void
#define GMPy_MPZ_Dealloc_PROTO (MPZ_Object *self)
/* The following function is found in gmpy2_convert_gmp. */
#define GMPy_MPZ_ConvertArg_NUM 14
#define GMPy_MPZ_ConvertArg_RETURN int
#define GMPy_MPZ_ConvertArg_PROTO (PyObject *arg, PyObject **ptr)
/* The following functions are found in gmpy2_cache. */
#define GMPy_XMPZ_New_NUM 15
#define GMPy_XMPZ_New_RETURN XMPZ_Object *
#define GMPy_XMPZ_New_PROTO (CTXT_Object *context)
#define GMPy_XMPZ_NewInit_NUM 16
#define GMPy_XMPZ_NewInit_RETURN PyObject *
#define GMPy_XMPZ_NewInit_PROTO (PyTypeObject *type, PyObject *args, PyObject *keywds)
#define GMPy_XMPZ_Dealloc_NUM 17
#define GMPy_XMPZ_Dealloc_RETURN void
#define GMPy_XMPZ_Dealloc_PROTO (XMPZ_Object *self)
/* The following functions are found in gmpy2_cache. */
#define GMPy_MPQ_New_NUM 18
#define GMPy_MPQ_New_RETURN MPQ_Object *
#define GMPy_MPQ_New_PROTO (CTXT_Object *context)
#define GMPy_MPQ_NewInit_NUM 19
#define GMPy_MPQ_NewInit_RETURN PyObject *
#define GMPy_MPQ_NewInit_PROTO (PyTypeObject *type, PyObject *args, PyObject *keywds)
#define GMPy_MPQ_Dealloc_NUM 20
#define GMPy_MPQ_Dealloc_RETURN void
#define GMPy_MPQ_Dealloc_PROTO (MPQ_Object *self)
/* The following function is found in gmpy2_convert_gmp. */
#define GMPy_MPQ_ConvertArg_NUM 21
#define GMPy_MPQ_ConvertArg_RETURN int
#define GMPy_MPQ_ConvertArg_PROTO (PyObject *arg, PyObject **ptr)
/* The following functions are found in gmpy2_cache. */
#define GMPy_MPFR_New_NUM 22
#define GMPy_MPFR_New_RETURN MPFR_Object *
#define GMPy_MPFR_New_PROTO (mpfr_prec_t bits, CTXT_Object *context)
#define GMPy_MPFR_NewInit_NUM 23
#define GMPy_MPFR_NewInit_RETURN PyObject *
#define GMPy_MPFR_NewInit_PROTO (PyTypeObject *type, PyObject *args, PyObject *keywds)
#define GMPy_MPFR_Dealloc_NUM 24
#define GMPy_MPFR_Dealloc_RETURN void
#define GMPy_MPFR_Dealloc_PROTO (MPFR_Object *self)
/* The following function is found in gmpy2_convert_gmp. */
#define GMPy_MPFR_ConvertArg_NUM 25
#define GMPy_MPFR_ConvertArg_RETURN int
#define GMPy_MPFR_ConvertArg_PROTO (PyObject *arg, PyObject **ptr)
/* The following functions are found in gmpy2_cache. */
#define GMPy_MPC_New_NUM 26
#define GMPy_MPC_New_RETURN MPC_Object *
#define GMPy_MPC_New_PROTO (mpfr_prec_t rprec, mpfr_prec_t iprec, CTXT_Object *context)
#define GMPy_MPC_NewInit_NUM 27
#define GMPy_MPC_NewInit_RETURN PyObject *
#define GMPy_MPC_NewInit_PROTO (PyTypeObject *type, PyObject *args, PyObject *keywds)
#define GMPy_MPC_Dealloc_NUM 28
#define GMPy_MPC_Dealloc_RETURN void
#define GMPy_MPC_Dealloc_PROTO (MPC_Object *self)
/* The following function is found in gmpy2_convert_gmp. */
#define GMPy_MPC_ConvertArg_NUM 29
#define GMPy_MPC_ConvertArg_RETURN int
#define GMPy_MPC_ConvertArg_PROTO (PyObject *arg, PyObject **ptr)
/* Total number of C-API pointers. */
#define GMPy_API_pointers 30
/* End of C-API definitions. */
#ifdef GMPY2_MODULE
#define PyString_1Char(obj) (PyUnicode_READY(obj) ? (Py_UCS4)0 : PyUnicode_READ_CHAR(obj, 0))
#define PyStrOrUnicode_Check(op) (PyBytes_Check(op) || PyUnicode_Check(op))
#ifndef ABS
# define ABS(a) (((a) < 0) ? -(a) : (a))
#endif
#if defined(MS_WIN32) && defined(_MSC_VER)
/* so one won't need to link explicitly to gmp.lib...: */
# pragma comment(lib,"gmp.lib")
# define USE_ALLOCA 1
# define inline __inline
#endif
#ifdef __GNUC__
# define USE_ALLOCA 1
#endif
#ifndef alloca
# ifdef __GNUC__
# define alloca __builtin_alloca
# else
# ifdef _MSC_VER
# include
# define alloca _alloca
# else
# if HAVE_ALLOCA_H
# include
# else
char *alloca ();
# endif
# endif
# endif
#endif
#define ALLOC_THRESHOLD 8192
#define INDEX_ERROR(msg) PyErr_SetString(PyExc_IndexError, msg)
#define TYPE_ERROR(msg) PyErr_SetString(PyExc_TypeError, msg)
#define VALUE_ERROR(msg) PyErr_SetString(PyExc_ValueError, msg)
#define ZERO_ERROR(msg) PyErr_SetString(PyExc_ZeroDivisionError, msg)
#define SYSTEM_ERROR(msg) PyErr_SetString(PyExc_SystemError, msg)
#define OVERFLOW_ERROR(msg) PyErr_SetString(PyExc_OverflowError, msg)
#define RUNTIME_ERROR(msg) PyErr_SetString(PyExc_RuntimeError, msg)
#define GMPY_DEFAULT -1
/* To prevent excessive memory usage, we don't want to save very large
* numbers in the cache. The default value specified in the options
* structure is 128 words (512 bytes on 32-bit platforms, 1024 bytes on
* 64-bit platforms).
*/
#define MAX_CACHE_LIMBS 16384
/* The maximum number of objects that can be saved in a cache is specified
* here. The default value is 100.*/
#define MAX_CACHE 1000
#ifdef USE_ALLOCA
# define TEMP_ALLOC(B, S) \
if(S < ALLOC_THRESHOLD) { \
B = alloca(S); \
} else { \
if(!(B = malloc(S))) { \
PyErr_NoMemory(); \
return NULL; \
} \
}
# define TEMP_FREE(B, S) if(S >= ALLOC_THRESHOLD) free(B)
#else
# define TEMP_ALLOC(B, S) \
if(!(B = malloc(S))) { \
PyErr_NoMemory(); \
return NULL; \
}
# define TEMP_FREE(B, S) free(B)
#endif
#ifndef Py_SIZE
# define Py_SIZE(ob) (((PyVarObject*)(ob))->ob_size)
#endif
#ifndef Py_TYPE
# define Py_TYPE(ob) (((PyObject*)(ob))->ob_type)
#endif
/* Import a collection of general purpose macros. */
#include "gmpy2_macros.h"
/* Import the files that complete the definition of the types defined above. */
#include "gmpy2_mpz.h"
#include "gmpy2_xmpz.h"
#include "gmpy2_mpq.h"
#include "gmpy2_mpfr.h"
#include "gmpy2_mpc.h"
#include "gmpy2_context.h"
#include "gmpy2_random.h"
/* Import the header files that provide the various functions. */
/* Support object caching, creation, and deletion. */
#include "gmpy2_cache.h"
/* Suport for miscellaneous functions (ie. version, license, etc.). */
#include "gmpy2_misc.h"
/* Support conversion to/from binary format. */
#include "gmpy2_binary.h"
/* Support for mpz/xmpz specific functions. */
#include "gmpy2_convert.h"
#include "gmpy2_convert_utils.h"
#include "gmpy2_convert_gmp.h"
#include "gmpy2_convert_mpfr.h"
#include "gmpy2_convert_mpc.h"
#include "gmpy2_mpz_divmod.h"
#include "gmpy2_mpz_divmod2exp.h"
#include "gmpy2_mpz_pack.h"
#include "gmpy2_mpz_bitops.h"
#include "gmpy2_mpz_misc.h"
#include "gmpy2_xmpz_inplace.h"
#include "gmpy2_xmpz_misc.h"
#include "gmpy2_xmpz_limbs.h"
/* Support for mpq specific functions. */
#include "gmpy2_mpq_misc.h"
/* Support for mpfr specific functions. */
#include "gmpy2_mpfr_misc.h"
/* Support for mpc specific functions. */
#include "gmpy2_mpc_misc.h"
/* Support Lucas sequences. */
#include "gmpy_mpz_lucas.h"
/* Support probable-prime tests. */
#include "gmpy_mpz_prp.h"
/* Support higher-level Python methods and functions; generally not
* specific to a single type.
*/
#include "gmpy2_abs.h"
#include "gmpy2_add.h"
#include "gmpy2_divmod.h"
#include "gmpy2_floordiv.h"
#include "gmpy2_minus.h"
#include "gmpy2_mod.h"
#include "gmpy2_mul.h"
#include "gmpy2_plus.h"
#include "gmpy2_pow.h"
#include "gmpy2_sub.h"
#include "gmpy2_truediv.h"
#include "gmpy2_math.h"
#include "gmpy2_const.h"
#include "gmpy2_square.h"
#include "gmpy2_format.h"
#include "gmpy2_hash.h"
#include "gmpy2_fused.h"
#include "gmpy2_muldiv_2exp.h"
#include "gmpy2_predicate.h"
#include "gmpy2_sign.h"
#include "gmpy2_richcompare.h"
#include "gmpy2_cmp.h"
#ifdef VECTOR
# include "gmpy2_vector.h"
#endif /* defined(VECTOR) */
#else /* defined(GMPY2_MODULE) */
/* This section is used for other C-coded modules that use gmpy2's API. */
static void **GMPy_C_API;
#define MPZ_Check(op) ((op)->ob_type == (PyTypeObject*)GMPy_C_API[MPZ_Type_NUM])
#define XMPZ_Check(op) ((op)->ob_type == (PyTypeObject*)GMPy_C_API[XMPZ_Type_NUM])
#define MPQ_Check(op) ((op)->ob_type == (PyTypeObject*)GMPy_C_API[MPQ_Type_NUM])
#define XMPQ_Check(op) ((op)->ob_type == (PyTypeObject*)GMPy_C_API[XMPQ_Type_NUM])
#define MPFR_Check(op) ((op)->ob_type == (PyTypeObject*)GMPy_C_API[MPFR_Type_NUM])
#define XMPFR_Check(op) ((op)->ob_type == (PyTypeObject*)GMPy_C_API[XMPFR_Type_NUM])
#define MPC_Check(op) ((op)->ob_type == (PyTypeObject*)GMPy_C_API[MPC_Type_NUM])
#define XMPC_Check(op) ((op)->ob_type == (PyTypeObject*)GMPy_C_API[XMPC_Type_NUM])
#define GMPy_MPZ_New (*(GMPy_MPZ_New_RETURN (*)GMPy_MPZ_New_PROTO) GMPy_C_API[GMPy_MPZ_New_NUM])
#define GMPy_MPZ_NewInit (*(GMPy_MPZ_NewInit_RETURN (*)GMPy_MPZ_NewInit_PROTO) GMPy_C_API[GMPy_MPZ_NewInit_NUM])
#define GMPy_MPZ_Dealloc (*(GMPy_MPZ_Dealloc_RETURN (*)GMPy_MPZ_Dealloc_PROTO) GMPy_C_API[GMPy_MPZ_Dealloc_NUM])
#define GMPy_MPZ_ConvertArg (*(GMPy_MPZ_ConvertArg_RETURN (*)GMPy_MPZ_ConvertArg_PROTO) GMPy_C_API[GMPy_MPZ_ConvertArg_NUM])
#define GMPy_XMPZ_New (*(GMPy_XMPZ_New_RETURN (*)GMPy_XMPZ_New_PROTO) GMPy_C_API[GMPy_XMPZ_New_NUM])
#define GMPy_XMPZ_NewInit (*(GMPy_XMPZ_NewInit_RETURN (*)GMPy_XMPZ_NewInit_PROTO) GMPy_C_API[GMPy_XMPZ_NewInit_NUM])
#define GMPy_XMPZ_Dealloc (*(GMPy_XMPZ_Dealloc_RETURN (*)GMPy_XMPZ_Dealloc_PROTO) GMPy_C_API[GMPy_XMPZ_Dealloc_NUM])
#define GMPy_MPQ_New (*(GMPy_MPQ_New_RETURN (*)GMPy_MPQ_New_PROTO) GMPy_C_API[GMPy_MPQ_New_NUM])
#define GMPy_MPQ_NewInit (*(GMPy_MPQ_NewInit_RETURN (*)GMPy_MPQ_NewInit_PROTO) GMPy_C_API[GMPy_MPQ_NewInit_NUM])
#define GMPy_MPQ_Dealloc (*(GMPy_MPQ_Dealloc_RETURN (*)GMPy_MPQ_Dealloc_PROTO) GMPy_C_API[GMPy_MPQ_Dealloc_NUM])
#define GMPy_MPQ_ConvertArg (*(GMPy_MPQ_ConvertArg_RETURN (*)GMPy_MPQ_ConvertArg_PROTO) GMPy_C_API[GMPy_MPQ_ConvertArg_NUM])
#define GMPy_MPFR_New (*(GMPy_MPFR_New_RETURN (*)GMPy_MPFR_New_PROTO) GMPy_C_API[GMPy_MPFR_New_NUM])
#define GMPy_MPFR_NewInit (*(GMPy_MPFR_NewInit_RETURN (*)GMPy_MPFR_NewInit_PROTO) GMPy_C_API[GMPy_MPFR_NewInit_NUM])
#define GMPy_MPFR_Dealloc (*(GMPy_MPFR_Dealloc_RETURN (*)GMPy_MPFR_Dealloc_PROTO) GMPy_C_API[GMPy_MPFR_Dealloc_NUM])
#define GMPy_MPFR_ConvertArg (*(GMPy_MPFR_ConvertArg_RETURN (*)GMPy_MPFR_ConvertArg_PROTO) GMPy_C_API[GMPy_MPFR_ConvertArg_NUM])
#define GMPy_MPC_New (*(GMPy_MPC_New_RETURN (*)GMPy_MPC_New_PROTO) GMPy_C_API[GMPy_MPC_New_NUM])
#define GMPy_MPC_NewInit (*(GMPy_MPC_NewInit_RETURN (*)GMPy_MPC_NewInit_PROTO) GMPy_C_API[GMPy_MPC_NewInit_NUM])
#define GMPy_MPC_Dealloc (*(GMPy_MPC_Dealloc_RETURN (*)GMPy_MPC_Dealloc_PROTO) GMPy_C_API[GMPy_MPC_Dealloc_NUM])
#define GMPy_MPC_ConvertArg (*(GMPy_MPC_ConvertArg_RETURN (*)GMPy_MPC_ConvertArg_PROTO) GMPy_C_API[GMPy_MPC_ConvertArg_NUM])
static int
import_gmpy2(void)
{
GMPy_C_API = (void **)PyCapsule_Import("gmpy2._C_API", 0);
return (GMPy_C_API != NULL) ? 0 : -1;
}
#endif /* defined(GMPY2_MODULE) */
#ifdef __cplusplus
}
#endif /* defined(__cplusplus */
#endif /* !defined(Py_GMPYMODULE_H */
././@PaxHeader 0000000 0000000 0000000 00000000026 00000000000 010213 x ustar 00 22 mtime=1710307256.0
gmpy2-2.2.1/gmpy2/gmpy2.pxd 0000644 0001750 0001750 00000011111 14574233670 014041 0 ustar 00case case cdef extern from "gmp.h":
# gmp integers
ctypedef long mp_limb_t
ctypedef struct __mpz_struct:
int _mp_alloc
int _mp_size
mp_limb_t* _mp_d
ctypedef __mpz_struct mpz_t[1]
ctypedef __mpz_struct *mpz_ptr
ctypedef const __mpz_struct *mpz_srcptr
# gmp rationals
ctypedef struct __mpq_struct:
__mpz_struct _mp_num
__mpz_struct _mp_den
ctypedef __mpq_struct mpq_t[1]
ctypedef __mpq_struct *mpq_ptr
ctypedef const __mpq_struct *mpq_srcptr
void mpz_set(mpz_t rop, mpz_t op)
void mpq_set(mpq_ptr rop, mpq_srcptr op)
void mpq_set_num(mpq_t rational, mpz_t numerator)
void mpq_set_den(mpq_t rational, mpz_t denominator)
cdef extern from "mpfr.h":
# mpfr reals
ctypedef int mpfr_sign_t
ctypedef long mpfr_prec_t
ctypedef long mpfr_exp_t
ctypedef struct __mpfr_struct:
mpfr_prec_t _mpfr_prec
mpfr_sign_t _mpfr_sign
mpfr_exp_t _mpfr_exp
mp_limb_t* _mpfr_d
ctypedef __mpfr_struct mpfr_t[1]
ctypedef __mpfr_struct *mpfr_ptr
ctypedef const __mpfr_struct *mpfr_srcptr
ctypedef enum mpfr_rnd_t:
MPFR_RNDN
MPFR_RNDZ
MPFR_RNDU
MPFR_RNDD
MPFR_RNDA
MPFR_RNDF
MPFR_RNDNA
mpfr_prec_t mpfr_get_prec(mpfr_t x)
int mpfr_set(mpfr_t rop, mpfr_t op, mpfr_rnd_t rnd)
cdef extern from "mpc.h":
# mpc complexes
ctypedef struct __mpc_struct:
mpfr_t re
mpfr_t im
ctypedef __mpc_struct mpc_t[1];
ctypedef __mpc_struct *mpc_ptr;
ctypedef const __mpc_struct *mpc_srcptr;
ctypedef enum mpc_rnd_t:
MPC_RNDNN
MPC_RNDNZ
MPC_RNDNU
MPC_RNDND
MPC_RNDZN
MPC_RNDZZ
MPC_RNDZU
MPC_RNDZD
MPC_RNDUN
MPC_RNDUZ
MPC_RNDUU
MPC_RNDUD
MPC_RNDDN
MPC_RNDDZ
MPC_RNDDU
MPC_RNDDD
mpfr_prec_t mpc_get_prec(mpc_srcptr x)
void mpc_get_prec2(mpfr_prec_t *pr, mpfr_prec_t *pi, mpc_srcptr x)
int mpc_set(mpc_ptr rop, mpc_srcptr op, mpc_rnd_t rnd)
int mpc_set_fr_fr(mpc_ptr rop, mpfr_srcptr rp, mpfr_srcptr ip, mpc_rnd_t rnd)
cdef extern from "gmpy2.h":
# Initialize the C-API
# This must be called before any other functions, but not to access
# the types.
cdef int import_gmpy2() except -1
# Object types
ctypedef class gmpy2.mpz [object MPZ_Object]:
cdef mpz_t z
ctypedef class gmpy2.mpq [object MPQ_Object]:
cdef mpq_t q
ctypedef class gmpy2.mpfr [object MPFR_Object]:
cdef mpfr_t f
cdef int rc
ctypedef class gmpy2.mpc [object MPC_Object]:
cdef mpc_t c
cdef int rc
# Object creation
cdef mpz GMPy_MPZ_New(void *)
cdef mpq GMPy_MPQ_New(void *)
cdef mpfr GMPy_MPFR_New(mpfr_prec_t prec, void *)
cdef mpc GMPy_MPC_New(mpfr_prec_t rprec, mpfr_prec_t iprec, void *)
# C field access
cdef mpz_t MPZ(mpz)
cdef mpq_t MPQ(mpq)
cdef mpfr_t MPFR(mpfr)
cdef mpc_t MPC(mpc)
# Type check
cdef bint MPZ_Check(object)
cdef bint MPQ_Check(object)
cdef bint MPFR_Check(object)
cdef bint MPC_Check(object)
# Build a gmpy2 mpz from a gmp mpz
cdef inline mpz GMPy_MPZ_From_mpz(mpz_srcptr z):
cdef mpz res = GMPy_MPZ_New(NULL)
mpz_set(res.z, z)
return res
# Build a gmpy2 mpq from a gmp mpq
cdef inline mpq GMPy_MPQ_From_mpq(mpq_srcptr q):
cdef mpq res = GMPy_MPQ_New(NULL)
mpq_set(res.q, q)
return res
# Build a gmpy2 mpq from gmp mpz numerator and denominator
cdef inline mpq GMPy_MPQ_From_mpz(mpz_srcptr num, mpz_srcptr den):
cdef mpq res = GMPy_MPQ_New(NULL)
mpq_set_num(res.q, num)
mpq_set_den(res.q, den)
return res
# Build a gmpy2 mpfr from a mpfr
cdef inline mpfr GMPy_MPFR_From_mpfr(mpfr_srcptr x):
cdef mpfr res = GMPy_MPFR_New(mpfr_get_prec(x), NULL)
mpfr_set(res.f, x, MPFR_RNDN)
return res
# Build a gmpy2 mpc from a mpc
cdef inline mpc GMPy_MPC_From_mpc(mpc_srcptr c):
cdef mpfr_prec_t pr
cdef mpfr_prec_t pi
mpc_get_prec2(&pr, &pi, c)
cdef mpc res = GMPy_MPC_New(pr, pi, NULL)
mpc_set(res.c, c, MPC_RNDNN)
return res
# Build a gmpy2 mpc from a real part mpfr and an imaginary part mpfr
cdef inline mpc GMPy_MPC_From_mpfr(mpfr_srcptr re, mpfr_srcptr im):
cdef mpc res = GMPy_MPC_New(mpfr_get_prec(re), mpfr_get_prec(im), NULL)
# We intentionally use MPFR funtions instead of MPC functions here
# in order not to add an unneeded dependency on MPC. It's probably
# faster too this way.
mpfr_set(res.c.re, re, MPFR_RNDN)
mpfr_set(res.c.im, im, MPFR_RNDN)
return res
././@PaxHeader 0000000 0000000 0000000 00000000034 00000000000 010212 x ustar 00 28 mtime=1721563243.6844618
gmpy2-2.2.1/gmpy2.egg-info/ 0000755 0001750 0001750 00000000000 14647174154 013767 5 ustar 00case case ././@PaxHeader 0000000 0000000 0000000 00000000026 00000000000 010213 x ustar 00 22 mtime=1721563243.0
gmpy2-2.2.1/gmpy2.egg-info/PKG-INFO 0000644 0001750 0001750 00000005426 14647174153 015072 0 ustar 00case case Metadata-Version: 2.1
Name: gmpy2
Version: 2.2.1
Summary: gmpy2 interface to GMP, MPFR, and MPC for Python 3.7+
Author: Case Van Horsen
Maintainer-email: Case Van Horsen
License: LGPL-3.0+
Project-URL: Homepage, https://github.com/aleaxit/gmpy
Keywords: gmp,mpfr,mpc,multiple-precision,arbitrary-precision,precision,bignum
Classifier: Development Status :: 5 - Production/Stable
Classifier: Intended Audience :: Developers
Classifier: Intended Audience :: Science/Research
Classifier: License :: OSI Approved :: GNU Lesser General Public License v3 or later (LGPLv3+)
Classifier: Natural Language :: English
Classifier: Operating System :: MacOS :: MacOS X
Classifier: Operating System :: Microsoft :: Windows
Classifier: Operating System :: POSIX
Classifier: Programming Language :: C
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.7
Classifier: Programming Language :: Python :: 3.8
Classifier: Programming Language :: Python :: 3.9
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Programming Language :: Python :: Implementation :: CPython
Classifier: Topic :: Scientific/Engineering :: Mathematics
Classifier: Topic :: Software Development :: Libraries :: Python Modules
Requires-Python: >=3.7
Description-Content-Type: text/x-rst
License-File: COPYING
License-File: COPYING.LESSER
Provides-Extra: docs
Requires-Dist: sphinx>=4; extra == "docs"
Requires-Dist: sphinx-rtd-theme>=1; extra == "docs"
Provides-Extra: tests
Requires-Dist: pytest; extra == "tests"
Requires-Dist: hypothesis; extra == "tests"
Requires-Dist: cython; extra == "tests"
Requires-Dist: mpmath; extra == "tests"
Requires-Dist: setuptools; extra == "tests"
gmpy2 is an optimized, C-coded Python extension module that supports fast
multiple-precision arithmetic. gmpy2 is based on the original gmpy module.
gmpy2 adds support for correctly rounded multiple-precision real arithmetic
(using the MPFR library) and complex arithmetic (using the MPC library).
Version 2.2
-----------
gmpy2 2.2.1
-----------
* Bug fix: use C int instead of C char for some internal code. Issue
* Bug fix: add xmpz.bit_count method.
gmpy2 2.2.0
-----------
gmpy2 2.2.0 is now available with support for Python 3.7 to 3.13.
* Support for thread-safe contexts and context methods has been improved.
* Interoperability with Cython extensions has been updated.
* Extensive improvements have been made to the build and testing processes.
* Many bug fixes.
* Extensive documentation cleanup.
Availability
------------
gmpy2 is available at https://pypi.python.org/pypi/gmpy2/
Documentation is available at https://gmpy2.readthedocs.io/en/latest/
././@PaxHeader 0000000 0000000 0000000 00000000026 00000000000 010213 x ustar 00 22 mtime=1721563243.0
gmpy2-2.2.1/gmpy2.egg-info/SOURCES.txt 0000644 0001750 0001750 00000005700 14647174153 015654 0 ustar 00case case COPYING
COPYING.LESSER
INSTALL
MANIFEST.in
README.rst
pyproject.toml
setup.py
docs/Makefile
docs/advmpz.rst
docs/conf.py
docs/contexts.rst
docs/conversion.rst
docs/cython.rst
docs/exceptions.rst
docs/generic.rst
docs/history.rst
docs/index.rst
docs/install.rst
docs/make.bat
docs/misc.rst
docs/mpc.rst
docs/mpfr.rst
docs/mpq.rst
docs/mpz.rst
docs/overview.rst
docs/tutorial.rst
docs/win_build.rst
gmpy2/__init__.pxd
gmpy2/__init__.py
gmpy2/gmpy2.h
gmpy2/gmpy2.pxd
gmpy2.egg-info/PKG-INFO
gmpy2.egg-info/SOURCES.txt
gmpy2.egg-info/dependency_links.txt
gmpy2.egg-info/not-zip-safe
gmpy2.egg-info/requires.txt
gmpy2.egg-info/top_level.txt
src/gmpy2.c
src/gmpy2.h
src/gmpy2.pxd
src/gmpy2_abs.c
src/gmpy2_abs.h
src/gmpy2_add.c
src/gmpy2_add.h
src/gmpy2_binary.c
src/gmpy2_binary.h
src/gmpy2_cache.c
src/gmpy2_cache.h
src/gmpy2_cmp.c
src/gmpy2_cmp.h
src/gmpy2_const.c
src/gmpy2_const.h
src/gmpy2_context.c
src/gmpy2_context.h
src/gmpy2_convert.c
src/gmpy2_convert.h
src/gmpy2_convert_gmp.c
src/gmpy2_convert_gmp.h
src/gmpy2_convert_mpc.c
src/gmpy2_convert_mpc.h
src/gmpy2_convert_mpfr.c
src/gmpy2_convert_mpfr.h
src/gmpy2_convert_utils.c
src/gmpy2_convert_utils.h
src/gmpy2_divmod.c
src/gmpy2_divmod.h
src/gmpy2_floordiv.c
src/gmpy2_floordiv.h
src/gmpy2_format.c
src/gmpy2_format.h
src/gmpy2_fused.c
src/gmpy2_fused.h
src/gmpy2_hash.c
src/gmpy2_hash.h
src/gmpy2_macros.h
src/gmpy2_math.c
src/gmpy2_math.h
src/gmpy2_minus.c
src/gmpy2_minus.h
src/gmpy2_misc.c
src/gmpy2_misc.h
src/gmpy2_mod.c
src/gmpy2_mod.h
src/gmpy2_mpc.c
src/gmpy2_mpc.h
src/gmpy2_mpc_misc.c
src/gmpy2_mpc_misc.h
src/gmpy2_mpfr.c
src/gmpy2_mpfr.h
src/gmpy2_mpfr_misc.c
src/gmpy2_mpfr_misc.h
src/gmpy2_mpmath.c
src/gmpy2_mpq.c
src/gmpy2_mpq.h
src/gmpy2_mpq_misc.c
src/gmpy2_mpq_misc.h
src/gmpy2_mpz.c
src/gmpy2_mpz.h
src/gmpy2_mpz_bitops.c
src/gmpy2_mpz_bitops.h
src/gmpy2_mpz_divmod.c
src/gmpy2_mpz_divmod.h
src/gmpy2_mpz_divmod2exp.c
src/gmpy2_mpz_divmod2exp.h
src/gmpy2_mpz_misc.c
src/gmpy2_mpz_misc.h
src/gmpy2_mpz_pack.c
src/gmpy2_mpz_pack.h
src/gmpy2_mul.c
src/gmpy2_mul.h
src/gmpy2_muldiv_2exp.c
src/gmpy2_muldiv_2exp.h
src/gmpy2_plus.c
src/gmpy2_plus.h
src/gmpy2_pow.c
src/gmpy2_pow.h
src/gmpy2_predicate.c
src/gmpy2_predicate.h
src/gmpy2_random.c
src/gmpy2_random.h
src/gmpy2_richcompare.c
src/gmpy2_richcompare.h
src/gmpy2_sign.c
src/gmpy2_sign.h
src/gmpy2_square.c
src/gmpy2_square.h
src/gmpy2_sub.c
src/gmpy2_sub.h
src/gmpy2_truediv.c
src/gmpy2_truediv.h
src/gmpy2_types.h
src/gmpy2_vector.c
src/gmpy2_vector.h
src/gmpy2_xmpz.c
src/gmpy2_xmpz.h
src/gmpy2_xmpz_inplace.c
src/gmpy2_xmpz_inplace.h
src/gmpy2_xmpz_limbs.c
src/gmpy2_xmpz_limbs.h
src/gmpy2_xmpz_misc.c
src/gmpy2_xmpz_misc.h
src/gmpy_mpz_lucas.c
src/gmpy_mpz_lucas.h
src/gmpy_mpz_prp.c
src/gmpy_mpz_prp.h
src/mpz_pylong.c
src/pythoncapi_compat.h
test/conftest.py
test/supportclasses.py
test/test_consts.py
test/test_context.py
test/test_functions.py
test/test_generic.py
test/test_misc.py
test/test_mpc.py
test/test_mpfr.py
test/test_mpq.py
test/test_mpz.py
test/test_xmpz.py ././@PaxHeader 0000000 0000000 0000000 00000000026 00000000000 010213 x ustar 00 22 mtime=1721563243.0
gmpy2-2.2.1/gmpy2.egg-info/dependency_links.txt 0000644 0001750 0001750 00000000001 14647174153 020034 0 ustar 00case case
././@PaxHeader 0000000 0000000 0000000 00000000026 00000000000 010213 x ustar 00 22 mtime=1711300207.0
gmpy2-2.2.1/gmpy2.egg-info/not-zip-safe 0000644 0001750 0001750 00000000001 14600057157 016205 0 ustar 00case case
././@PaxHeader 0000000 0000000 0000000 00000000026 00000000000 010213 x ustar 00 22 mtime=1721563243.0
gmpy2-2.2.1/gmpy2.egg-info/requires.txt 0000644 0001750 0001750 00000000132 14647174153 016362 0 ustar 00case case
[docs]
sphinx>=4
sphinx-rtd-theme>=1
[tests]
pytest
hypothesis
cython
mpmath
setuptools
././@PaxHeader 0000000 0000000 0000000 00000000026 00000000000 010213 x ustar 00 22 mtime=1721563243.0
gmpy2-2.2.1/gmpy2.egg-info/top_level.txt 0000644 0001750 0001750 00000000006 14647174153 016514 0 ustar 00case case gmpy2
././@PaxHeader 0000000 0000000 0000000 00000000026 00000000000 010213 x ustar 00 22 mtime=1721552289.0
gmpy2-2.2.1/pyproject.toml 0000644 0001750 0001750 00000004314 14647146641 014155 0 ustar 00case case [build-system]
requires = ['setuptools>=61']
build-backend = 'setuptools.build_meta'
[project]
name = 'gmpy2'
version = '2.2.1'
description = 'gmpy2 interface to GMP, MPFR, and MPC for Python 3.7+'
keywords = ['gmp', 'mpfr', 'mpc', 'multiple-precision',
'arbitrary-precision', 'precision', 'bignum']
license = {text = 'LGPL-3.0+'}
authors = [{name = 'Case Van Horsen'}]
maintainers = [{name = 'Case Van Horsen', email = 'casevh@gmail.com'}]
classifiers = ['Development Status :: 5 - Production/Stable',
'Intended Audience :: Developers',
'Intended Audience :: Science/Research',
'License :: OSI Approved :: GNU Lesser General Public License v3 or later (LGPLv3+)',
'Natural Language :: English',
'Operating System :: MacOS :: MacOS X',
'Operating System :: Microsoft :: Windows',
'Operating System :: POSIX',
'Programming Language :: C',
'Programming Language :: Python :: 3',
'Programming Language :: Python :: 3.7',
'Programming Language :: Python :: 3.8',
'Programming Language :: Python :: 3.9',
'Programming Language :: Python :: 3.10',
'Programming Language :: Python :: 3.11',
'Programming Language :: Python :: 3.12',
'Programming Language :: Python :: 3.13',
'Programming Language :: Python :: Implementation :: CPython',
'Topic :: Scientific/Engineering :: Mathematics',
'Topic :: Software Development :: Libraries :: Python Modules']
requires-python = '>=3.7'
[project.readme]
file = 'README.rst'
content-type = 'text/x-rst'
[project.optional-dependencies]
docs = ['sphinx>=4', 'sphinx-rtd-theme>=1']
tests = ['pytest', 'hypothesis', 'cython', 'mpmath', 'setuptools']
[project.urls]
Homepage = 'https://github.com/aleaxit/gmpy'
[tool.setuptools]
zip-safe = false
include-package-data = true
[tool.setuptools.packages]
find = {namespaces = false}
[tool.setuptools.package-data]
gmpy2 = ['*.pxd', '*.h', '*.dll', '*.lib']
[tool.pytest.ini_options]
addopts = "--durations=10"
norecursedirs = ['build', '.eggs', '.git']
xfail_strict = true
././@PaxHeader 0000000 0000000 0000000 00000000034 00000000000 010212 x ustar 00 28 mtime=1721563243.6844618
gmpy2-2.2.1/setup.cfg 0000644 0001750 0001750 00000000046 14647174154 013060 0 ustar 00case case [egg_info]
tag_build =
tag_date = 0
././@PaxHeader 0000000 0000000 0000000 00000000026 00000000000 010213 x ustar 00 22 mtime=1711216875.0
gmpy2-2.2.1/setup.py 0000644 0001750 0001750 00000005716 14577614353 012764 0 ustar 00case case import os
import platform
from setuptools import setup, Extension
from setuptools.command.build_ext import build_ext
from pathlib import Path
ON_WINDOWS = platform.system() == 'Windows'
_comp_args = ["DSHARED=1"]
sources = ['src/gmpy2.c']
if os.getenv('CIBUILDWHEEL'):
include_dirs = [os.path.join(os.path.dirname(__file__), '.local', 'include')]
library_dirs = [os.path.join(os.path.dirname(__file__), '.local',
'bin' if ON_WINDOWS else 'lib')]
else:
include_dirs = []
library_dirs = []
class Gmpy2Build(build_ext):
description = "Build gmpy2 with custom build options"
user_options = build_ext.user_options + [
('fast', None,
"Depend on MPFR and MPC internal implementations details"
"(even more than the standard build)"),
('gcov', None, "Enable GCC code coverage collection"),
('vector', None, "Include the vector_XXX() functions;"
"they are unstable and under active development"),
('static', None, "Enable static linking compile time options."),
('static-dir=', None, "Enable static linking and specify location."),
('gdb', None, "Build with debug symbols."),
]
def initialize_options(self):
build_ext.initialize_options(self)
self.fast = False
self.gcov = False
self.vector = False
self.static = False
self.static_dir = False
self.gdb = False
def finalize_options(self):
build_ext.finalize_options(self)
self.force = 1
if self.fast:
_comp_args.append('DFAST=1')
if self.gcov:
if ON_WINDOWS:
raise ValueError("Cannot enable GCC code coverage on Windows")
_comp_args.append('DGCOV=1')
_comp_args.append('O0')
_comp_args.append('-coverage')
self.libraries.append('gcov')
if self.vector:
_comp_args.append('DVECTOR=1')
if self.static:
_comp_args.remove('DSHARED=1')
_comp_args.append('DSTATIC=1')
if self.gdb:
_comp_args.append('ggdb')
if self.static_dir:
_comp_args.remove('DSHARED=1')
_comp_args.append('DSTATIC=1')
self.include_dirs.append(self.static_dir + '/include')
self.library_dirs.append(self.static_dir + '/lib')
def build_extensions(self):
compiler = self.compiler.compiler_type
_prefix = '-' if compiler != 'msvc' else '/'
for i in range(len(_comp_args)):
_comp_args[i] = ''.join([_prefix, _comp_args[i]])
build_ext.build_extensions(self)
extensions = [
Extension('gmpy2.gmpy2',
sources=sources,
include_dirs=include_dirs,
libraries=['mpc','mpfr','gmp'],
library_dirs=library_dirs,
extra_compile_args=_comp_args,
)
]
cmdclass = {'build_ext': Gmpy2Build}
setup(
cmdclass=cmdclass,
ext_modules=extensions,
)
././@PaxHeader 0000000 0000000 0000000 00000000034 00000000000 010212 x ustar 00 28 mtime=1721563243.6844618
gmpy2-2.2.1/src/ 0000755 0001750 0001750 00000000000 14647174154 012026 5 ustar 00case case ././@PaxHeader 0000000 0000000 0000000 00000000026 00000000000 010213 x ustar 00 22 mtime=1721552313.0
gmpy2-2.2.1/src/gmpy2.c 0000644 0001750 0001750 00000122530 14647146671 013236 0 ustar 00case case /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* gmpy2.c *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Python interface to the GMP, MPFR, and MPC multiple precision *
* libraries. *
* *
* Copyright 2000 - 2009 Alex Martelli *
* *
* Copyright 2008 - 2024 Case Van Horsen *
* *
* This file is part of GMPY2. *
* *
* GMPY2 is free software: you can redistribute it and/or modify it under *
* the terms of the GNU Lesser General Public License as published by the *
* Free Software Foundation, either version 3 of the License, or (at your *
* option) any later version. *
* *
* GMPY2 is distributed in the hope that it will be useful, but WITHOUT *
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or *
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public *
* License for more details. *
* *
* You should have received a copy of the GNU Lesser General Public *
* License along with GMPY2; if not, see *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
/* Todo list
* ---------
* Add all MPFR and MPC functions as context methods.
* All MPFR and MPC functions need to set exponent range on entry. The
* current approach where only set_context() and context.__enter__ set
* the exponent range fails for context methods.
* Should a read-only (or template) context prevent the setting of
* exception flags?
* Add context option to control the result of integer division:
* integer (mpz), exact (mpq), or true (mpfr).
* Add modular arithmetic functions.
* Implement Chinese Remainder Theorem.
* Update PRP code.
*/
/*
* originally written for GMP-2.0 (by AMK...?)
* Rewritten by Niels Möller, May 1996
*
* Version for GMP-4, Python 2.X, with support for MSVC++6,
* addition of mpf's, &c: Alex Martelli (now aleaxit@gmail.com, Nov 2000).
* cleanups & reorgs leading to 1.0: Alex Martelli (until Aug 2003)
* further cleanups and bugfixes leading to 1.01, Alex Martelli (Nov 2005)
* minor bugfixes+new decimal (&c) support to 1.02, Alex Martelli (Feb 2006)
* various bugfixes for 64-bit platforms, 1.03, aleaxit and casevh (Jun 2008)
* rich comparisons, 1.04, aleaxit and casevh (Jan 2009)
* support for Python 3.x, 1.10, casevh (Oct 2009)
*
* Some hacks by Gustavo Niemeyer .
*
************************************************************************
*
* Discussion on sizes of C integer types.
*
* GMP, MPFR, and MPC use typedef to create integer objects with
* different sizes. It can become confusing to map the different types
* onto the standard C types used by Python's C API. Below are external
* types and how they map to C types. The assumptions are verified when
* the module is initialized.
*
* mp_limb_t: This is usually an 'unsigned long' but is an 'unsigned
* long long' on certain 64-bit Windows builds.
*
* mp_bitcnt_t: This is usually an 'unsigned long' but is an 'unsigned
* long long' on MPIR/64-bit Windows. 'size_t' is the best match.
*
* mp_size_t: This is a 'long'.
*
* mpfr_rnd_t: This is an 'int'.
*
* mpfr_prec_t: This is a 'long'.
*
* mpfr_sign_t: This is an 'int'.
*
* mpfr_exp_t: This is currently the same as mp_exp_t but will change
* to a signed 64-bit integer in the future.
*
* mpc_rnd_t: This is an 'int'.
*
* mpc_prec_t: See mpfr_exp_t.
*
************************************************************************
*/
#define PY_SSIZE_T_CLEAN
#include
#include
#include
#include
#include
#include
#include
/*
* we do have a dependence on Python's internals, specifically:
* how Python "long int"s are internally represented.
*/
#if PY_VERSION_HEX < 0x030B0000
# include
#else
# include
#endif
#define GMPY2_MODULE
#include "gmpy2.h"
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Global data declarations begin here. *
* NOTE: Because of these global declarations, GMPY2 is not thread-safe! *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
/* The following global strings are used by gmpy_misc.c. */
char gmpy_version[] = "2.2.1";
char gmpy_license[] = "\
The GMPY2 source code is licensed under LGPL 3 or later. The supported \
versions of the GMP, MPFR, and MPC libraries are also licensed under \
LGPL 3 or later.";
/* The following global structures are used by gmpy_cache.c.
*/
#define CACHE_SIZE (100)
#define MAX_CACHE_MPZ_LIMBS (64)
#define MAX_CACHE_MPFR_BITS (1024)
typedef struct {
mpz_t tempz; /* Temporary variable used for integer conversions */
MPZ_Object *gmpympzcache[CACHE_SIZE];
int in_gmpympzcache;
XMPZ_Object *gmpyxmpzcache[CACHE_SIZE];
int in_gmpyxmpzcache;
MPQ_Object *gmpympqcache[CACHE_SIZE];
int in_gmpympqcache;
MPFR_Object *gmpympfrcache[CACHE_SIZE];
int in_gmpympfrcache;
MPC_Object *gmpympccache[CACHE_SIZE];
int in_gmpympccache;
} gmpy_global;
static gmpy_global global = {
.in_gmpympzcache = 0,
.in_gmpyxmpzcache = 0,
.in_gmpympqcache = 0,
.in_gmpympfrcache = 0,
.in_gmpympccache = 0,
};
/* Support for context manager using context vars.
* Requires Python 3.7 or later.
*/
static PyObject *current_context_var = NULL;
/* Define gmpy2 specific errors for mpfr and mpc data types. No change will
* be made the exceptions raised by mpz, xmpz, and mpq.
*/
static PyObject *GMPyExc_GmpyError = NULL;
static PyObject *GMPyExc_DivZero = NULL;
static PyObject *GMPyExc_Inexact = NULL;
static PyObject *GMPyExc_Invalid = NULL;
static PyObject *GMPyExc_Overflow = NULL;
static PyObject *GMPyExc_Underflow = NULL;
static PyObject *GMPyExc_Erange = NULL;
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* End of global data declarations. *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
/* The code for object creation, deletion, and caching is in gmpy_cache.c. */
#include "gmpy2_cache.c"
/* Miscellaneous helper functions and simple methods are in gmpy_misc.c. */
#include "gmpy2_misc.c"
/* Support for conversion to/from binary representation. */
#include "gmpy2_binary.c"
/* Support for conversions to/from numeric types. */
#include "gmpy2_convert.c"
#include "gmpy2_convert_utils.c"
#include "gmpy2_convert_gmp.c"
#include "gmpy2_convert_mpfr.c"
#include "gmpy2_convert_mpc.c"
/* Support for random numbers. */
#include "gmpy2_random.c"
/* Support for Lucas sequences. */
#include "gmpy_mpz_lucas.c"
/* Support for probable-prime tests. */
#include "gmpy_mpz_prp.c"
/* Include helper functions for mpmath. */
#include "gmpy2_mpmath.c"
#include "gmpy2_mpz_divmod.c"
#include "gmpy2_mpz_divmod2exp.c"
#include "gmpy2_mpz_pack.c"
#include "gmpy2_mpz_bitops.c"
#include "gmpy2_xmpz_inplace.c"
/* Begin includes of refactored code. */
#include "gmpy2_abs.c"
#include "gmpy2_add.c"
#include "gmpy2_divmod.c"
#include "gmpy2_floordiv.c"
#include "gmpy2_minus.c"
#include "gmpy2_mod.c"
#include "gmpy2_mul.c"
#include "gmpy2_plus.c"
#include "gmpy2_pow.c"
#include "gmpy2_sub.c"
#include "gmpy2_truediv.c"
#include "gmpy2_math.c"
#include "gmpy2_const.c"
#include "gmpy2_square.c"
#include "gmpy2_format.c"
#include "gmpy2_hash.c"
#include "gmpy2_fused.c"
#include "gmpy2_muldiv_2exp.c"
#include "gmpy2_predicate.c"
#include "gmpy2_sign.c"
#include "gmpy2_richcompare.c"
#include "gmpy2_cmp.c"
#include "gmpy2_mpc_misc.c"
#include "gmpy2_mpfr_misc.c"
#include "gmpy2_mpq_misc.c"
#include "gmpy2_mpz_misc.c"
#include "gmpy2_xmpz_misc.c"
#include "gmpy2_xmpz_limbs.c"
#ifdef VECTOR
#include "gmpy2_vector.c"
#endif
/* Include gmpy_context last to avoid adding doc names to .h files. */
#include "gmpy2_mpz.c"
#include "gmpy2_xmpz.c"
#include "gmpy2_mpq.c"
#include "gmpy2_mpfr.c"
#include "gmpy2_mpc.c"
#include "gmpy2_context.c"
static PyMethodDef Pygmpy_methods [] =
{
{ "add", GMPy_Context_Add, METH_VARARGS, GMPy_doc_function_add },
{ "bit_clear", GMPy_MPZ_bit_clear_function, METH_VARARGS, doc_bit_clear_function },
{ "bit_count", GMPy_MPZ_bit_count, METH_O, doc_bit_count },
{ "bit_flip", GMPy_MPZ_bit_flip_function, METH_VARARGS, doc_bit_flip_function },
{ "bit_length", GMPy_MPZ_bit_length_function, METH_O, doc_bit_length_function },
{ "bit_mask", GMPy_MPZ_bit_mask, METH_O, doc_bit_mask },
{ "bit_scan0", (PyCFunction)GMPy_MPZ_bit_scan0_function, METH_FASTCALL, doc_bit_scan0_function },
{ "bit_scan1", (PyCFunction)GMPy_MPZ_bit_scan1_function, METH_FASTCALL, doc_bit_scan1_function },
{ "bit_set", GMPy_MPZ_bit_set_function, METH_VARARGS, doc_bit_set_function },
{ "bit_test", (PyCFunction)GMPy_MPZ_bit_test_function, METH_FASTCALL, doc_bit_test_function },
{ "bincoef", (PyCFunction)GMPy_MPZ_Function_Bincoef, METH_FASTCALL, GMPy_doc_mpz_function_bincoef },
{ "cmp", GMPy_MPANY_cmp, METH_VARARGS, GMPy_doc_mpany_cmp },
{ "cmp_abs", GMPy_MPANY_cmp_abs, METH_VARARGS, GMPy_doc_mpany_cmp_abs },
{ "comb", (PyCFunction)GMPy_MPZ_Function_Bincoef, METH_FASTCALL, GMPy_doc_mpz_function_comb },
{ "c_div", GMPy_MPZ_c_div, METH_VARARGS, doc_c_div },
{ "c_div_2exp", GMPy_MPZ_c_div_2exp, METH_VARARGS, doc_c_div_2exp },
{ "c_divmod", GMPy_MPZ_c_divmod, METH_VARARGS, doc_c_divmod },
{ "c_divmod_2exp", GMPy_MPZ_c_divmod_2exp, METH_VARARGS, doc_c_divmod_2exp },
{ "c_mod", GMPy_MPZ_c_mod, METH_VARARGS, doc_c_mod },
{ "c_mod_2exp", GMPy_MPZ_c_mod_2exp, METH_VARARGS, doc_c_mod_2exp },
{ "denom", GMPy_MPQ_Function_Denom, METH_O, GMPy_doc_mpq_function_denom },
{ "digits", GMPy_Context_Digits, METH_VARARGS, GMPy_doc_context_digits },
{ "div", GMPy_Context_TrueDiv, METH_VARARGS, GMPy_doc_truediv },
{ "divexact", (PyCFunction)GMPy_MPZ_Function_Divexact, METH_FASTCALL, GMPy_doc_mpz_function_divexact },
{ "divm", (PyCFunction)GMPy_MPZ_Function_Divm, METH_FASTCALL, GMPy_doc_mpz_function_divm },
{ "double_fac", GMPy_MPZ_Function_DoubleFac, METH_O, GMPy_doc_mpz_function_double_fac },
{ "fac", GMPy_MPZ_Function_Fac, METH_O, GMPy_doc_mpz_function_fac },
{ "fib", GMPy_MPZ_Function_Fib, METH_O, GMPy_doc_mpz_function_fib },
{ "fib2", GMPy_MPZ_Function_Fib2, METH_O, GMPy_doc_mpz_function_fib2 },
{ "floor_div", GMPy_Context_FloorDiv, METH_VARARGS, GMPy_doc_floordiv },
{ "from_binary", GMPy_MPANY_From_Binary, METH_O, doc_from_binary },
{ "f_div", GMPy_MPZ_f_div, METH_VARARGS, doc_f_div },
{ "f_div_2exp", GMPy_MPZ_f_div_2exp, METH_VARARGS, doc_f_div_2exp },
{ "f_divmod", GMPy_MPZ_f_divmod, METH_VARARGS, doc_f_divmod },
{ "f_divmod_2exp", GMPy_MPZ_f_divmod_2exp, METH_VARARGS, doc_f_divmod_2exp },
{ "f_mod", GMPy_MPZ_f_mod, METH_VARARGS, doc_f_mod },
{ "f_mod_2exp", GMPy_MPZ_f_mod_2exp, METH_VARARGS, doc_f_mod_2exp },
{ "gcd", (PyCFunction)GMPy_MPZ_Function_GCD, METH_FASTCALL, GMPy_doc_mpz_function_gcd },
{ "gcdext", (PyCFunction)GMPy_MPZ_Function_GCDext, METH_FASTCALL, GMPy_doc_mpz_function_gcdext },
{ "hamdist", GMPy_MPZ_hamdist, METH_VARARGS, doc_hamdist },
{ "invert", (PyCFunction)GMPy_MPZ_Function_Invert, METH_FASTCALL, GMPy_doc_mpz_function_invert },
{ "iroot", (PyCFunction)GMPy_MPZ_Function_Iroot, METH_FASTCALL, GMPy_doc_mpz_function_iroot },
{ "iroot_rem", (PyCFunction)GMPy_MPZ_Function_IrootRem, METH_FASTCALL, GMPy_doc_mpz_function_iroot_rem },
{ "isqrt", GMPy_MPZ_Function_Isqrt, METH_O, GMPy_doc_mpz_function_isqrt },
{ "isqrt_rem", GMPy_MPZ_Function_IsqrtRem, METH_O, GMPy_doc_mpz_function_isqrt_rem },
{ "is_bpsw_prp", GMPY_mpz_is_bpsw_prp, METH_VARARGS, doc_mpz_is_bpsw_prp },
{ "is_congruent", (PyCFunction)GMPy_MPZ_Function_IsCongruent, METH_FASTCALL, GMPy_doc_mpz_function_is_congruent },
{ "is_divisible", (PyCFunction)GMPy_MPZ_Function_IsDivisible, METH_FASTCALL, GMPy_doc_mpz_function_is_divisible },
{ "is_even", GMPy_MPZ_Function_IsEven, METH_O, GMPy_doc_mpz_function_is_even },
{ "is_euler_prp", GMPY_mpz_is_euler_prp, METH_VARARGS, doc_mpz_is_euler_prp },
{ "is_extra_strong_lucas_prp", GMPY_mpz_is_extrastronglucas_prp, METH_VARARGS, doc_mpz_is_extrastronglucas_prp },
{ "is_fermat_prp", GMPY_mpz_is_fermat_prp, METH_VARARGS, doc_mpz_is_fermat_prp },
{ "is_fibonacci_prp", GMPY_mpz_is_fibonacci_prp, METH_VARARGS, doc_mpz_is_fibonacci_prp },
{ "is_lucas_prp", GMPY_mpz_is_lucas_prp, METH_VARARGS, doc_mpz_is_lucas_prp },
{ "is_odd", GMPy_MPZ_Function_IsOdd, METH_O, GMPy_doc_mpz_function_is_odd },
{ "is_power", GMPy_MPZ_Function_IsPower, METH_O, GMPy_doc_mpz_function_is_power },
{ "is_prime", (PyCFunction)GMPy_MPZ_Function_IsPrime, METH_FASTCALL, GMPy_doc_mpz_function_is_prime },
{ "is_probab_prime", (PyCFunction)GMPy_MPZ_Function_IsProbabPrime, METH_FASTCALL, GMPy_doc_mpz_function_is_probab_prime },
{ "is_selfridge_prp", GMPY_mpz_is_selfridge_prp, METH_VARARGS, doc_mpz_is_selfridge_prp },
{ "is_square", GMPy_MPZ_Function_IsSquare, METH_O, GMPy_doc_mpz_function_is_square },
{ "is_strong_prp", GMPY_mpz_is_strong_prp, METH_VARARGS, doc_mpz_is_strong_prp },
{ "is_strong_bpsw_prp", GMPY_mpz_is_strongbpsw_prp, METH_VARARGS, doc_mpz_is_strongbpsw_prp },
{ "is_strong_lucas_prp", GMPY_mpz_is_stronglucas_prp, METH_VARARGS, doc_mpz_is_stronglucas_prp },
{ "is_strong_selfridge_prp", GMPY_mpz_is_strongselfridge_prp, METH_VARARGS, doc_mpz_is_strongselfridge_prp },
{ "jacobi", (PyCFunction)GMPy_MPZ_Function_Jacobi, METH_FASTCALL, GMPy_doc_mpz_function_jacobi },
{ "kronecker", (PyCFunction)GMPy_MPZ_Function_Kronecker, METH_FASTCALL, GMPy_doc_mpz_function_kronecker },
{ "lcm", (PyCFunction)GMPy_MPZ_Function_LCM, METH_FASTCALL, GMPy_doc_mpz_function_lcm },
{ "legendre", (PyCFunction)GMPy_MPZ_Function_Legendre, METH_FASTCALL, GMPy_doc_mpz_function_legendre },
{ "license", GMPy_get_license, METH_NOARGS, GMPy_doc_license },
{ "lucas", GMPy_MPZ_Function_Lucas, METH_O, GMPy_doc_mpz_function_lucas },
{ "lucasu", GMPY_mpz_lucasu, METH_VARARGS, doc_mpz_lucasu },
{ "lucasu_mod", GMPY_mpz_lucasu_mod, METH_VARARGS, doc_mpz_lucasu_mod },
{ "lucasv", GMPY_mpz_lucasv, METH_VARARGS, doc_mpz_lucasv },
{ "lucasv_mod", GMPY_mpz_lucasv_mod, METH_VARARGS, doc_mpz_lucasv_mod },
{ "lucas2", GMPy_MPZ_Function_Lucas2, METH_O, GMPy_doc_mpz_function_lucas2 },
{ "mod", GMPy_Context_Mod, METH_VARARGS, GMPy_doc_mod },
{ "mp_version", GMPy_get_mp_version, METH_NOARGS, GMPy_doc_mp_version },
{ "mp_limbsize", GMPy_get_mp_limbsize, METH_NOARGS, GMPy_doc_mp_limbsize },
{ "mpc_version", GMPy_get_mpc_version, METH_NOARGS, GMPy_doc_mpc_version },
{ "mpfr_version", GMPy_get_mpfr_version, METH_NOARGS, GMPy_doc_mpfr_version },
{ "mpq_from_old_binary", GMPy_MPQ_From_Old_Binary, METH_O, doc_mpq_from_old_binary },
{ "mpz_from_old_binary", GMPy_MPZ_From_Old_Binary, METH_O, doc_mpz_from_old_binary },
{ "mpz_random", GMPy_MPZ_random_Function, METH_VARARGS, GMPy_doc_mpz_random_function },
{ "mpz_rrandomb", GMPy_MPZ_rrandomb_Function, METH_VARARGS, GMPy_doc_mpz_rrandomb_function },
{ "mpz_urandomb", GMPy_MPZ_urandomb_Function, METH_VARARGS, GMPy_doc_mpz_urandomb_function },
{ "mul", GMPy_Context_Mul, METH_VARARGS, GMPy_doc_function_mul },
{ "multi_fac", (PyCFunction)GMPy_MPZ_Function_MultiFac, METH_FASTCALL, GMPy_doc_mpz_function_multi_fac },
{ "next_prime", GMPy_MPZ_Function_NextPrime, METH_O, GMPy_doc_mpz_function_next_prime },
#if (__GNU_MP_VERSION > 6) || (__GNU_MP_VERSION == 6 && __GNU_MP_VERSION_MINOR >= 3)
{ "prev_prime", GMPy_MPZ_Function_PrevPrime, METH_O, GMPy_doc_mpz_function_prev_prime },
#endif
{ "numer", GMPy_MPQ_Function_Numer, METH_O, GMPy_doc_mpq_function_numer },
{ "num_digits", (PyCFunction)GMPy_MPZ_Function_NumDigits, METH_FASTCALL, GMPy_doc_mpz_function_num_digits },
{ "pack", GMPy_MPZ_pack, METH_VARARGS, doc_pack },
{ "popcount", GMPy_MPZ_popcount, METH_O, doc_popcount },
{ "powmod", GMPy_Integer_PowMod, METH_VARARGS, GMPy_doc_integer_powmod },
{ "powmod_base_list", GMPy_Integer_PowMod_Base_List, METH_VARARGS, GMPy_doc_integer_powmod_base_list },
{ "powmod_exp_list", GMPy_Integer_PowMod_Exp_List, METH_VARARGS, GMPy_doc_integer_powmod_exp_list },
{ "powmod_sec", GMPy_Integer_PowMod_Sec, METH_VARARGS, GMPy_doc_integer_powmod_sec },
{ "primorial", GMPy_MPZ_Function_Primorial, METH_O, GMPy_doc_mpz_function_primorial },
{ "qdiv", GMPy_MPQ_Function_Qdiv, METH_VARARGS, GMPy_doc_function_qdiv },
{ "remove", (PyCFunction)GMPy_MPZ_Function_Remove, METH_FASTCALL, GMPy_doc_mpz_function_remove },
{ "random_state", GMPy_RandomState_Factory, METH_VARARGS, GMPy_doc_random_state_factory },
{ "sign", GMPy_Context_Sign, METH_O, GMPy_doc_function_sign },
{ "square", GMPy_Context_Square, METH_O, GMPy_doc_function_square },
{ "sub", GMPy_Context_Sub, METH_VARARGS, GMPy_doc_sub },
{ "to_binary", GMPy_MPANY_To_Binary, METH_O, doc_to_binary },
{ "t_div", GMPy_MPZ_t_div, METH_VARARGS, doc_t_div },
{ "t_div_2exp", GMPy_MPZ_t_div_2exp, METH_VARARGS, doc_t_div_2exp },
{ "t_divmod", GMPy_MPZ_t_divmod, METH_VARARGS, doc_t_divmod },
{ "t_divmod_2exp", GMPy_MPZ_t_divmod_2exp, METH_VARARGS, doc_t_divmod_2exp },
{ "t_mod", GMPy_MPZ_t_mod, METH_VARARGS, doc_t_mod },
{ "t_mod_2exp", GMPy_MPZ_t_mod_2exp, METH_VARARGS, doc_t_mod_2exp },
{ "unpack", GMPy_MPZ_unpack, METH_VARARGS, doc_unpack },
{ "version", GMPy_get_version, METH_NOARGS, GMPy_doc_version },
{ "xbit_mask", GMPy_XMPZ_Function_XbitMask, METH_O, GMPy_doc_xmpz_function_xbit_mask },
{ "_mpmath_normalize", (PyCFunction)Pympz_mpmath_normalize_fast, METH_FASTCALL, doc_mpmath_normalizeg },
{ "_mpmath_create", (PyCFunction)Pympz_mpmath_create_fast, METH_FASTCALL, doc_mpmath_create },
{ "acos", GMPy_Context_Acos, METH_O, GMPy_doc_function_acos },
{ "acosh", GMPy_Context_Acosh, METH_O, GMPy_doc_function_acosh },
{ "ai", GMPy_Context_Ai, METH_O, GMPy_doc_function_ai },
{ "agm", GMPy_Context_AGM, METH_VARARGS, GMPy_doc_function_agm },
{ "asin", GMPy_Context_Asin, METH_O, GMPy_doc_function_asin },
{ "asinh", GMPy_Context_Asinh, METH_O, GMPy_doc_function_asinh },
{ "atan", GMPy_Context_Atan, METH_O, GMPy_doc_function_atan },
{ "atanh", GMPy_Context_Atanh, METH_O, GMPy_doc_function_atanh },
{ "atan2", GMPy_Context_Atan2, METH_VARARGS, GMPy_doc_function_atan2 },
{ "can_round", GMPy_MPFR_Can_Round, METH_VARARGS, GMPy_doc_mpfr_can_round },
{ "cbrt", GMPy_Context_Cbrt, METH_O, GMPy_doc_function_cbrt },
{ "ceil", GMPy_Context_Ceil, METH_O, GMPy_doc_function_ceil },
{ "check_range", GMPy_Context_CheckRange, METH_O, GMPy_doc_function_check_range },
{ "const_catalan", (PyCFunction)GMPy_Function_Const_Catalan, METH_VARARGS | METH_KEYWORDS, GMPy_doc_function_const_catalan },
{ "const_euler", (PyCFunction)GMPy_Function_Const_Euler, METH_VARARGS | METH_KEYWORDS, GMPy_doc_function_const_euler },
{ "const_log2", (PyCFunction)GMPy_Function_Const_Log2, METH_VARARGS | METH_KEYWORDS, GMPy_doc_function_const_log2 },
{ "const_pi", (PyCFunction)GMPy_Function_Const_Pi, METH_VARARGS | METH_KEYWORDS, GMPy_doc_function_const_pi },
{ "copy_sign", GMPy_MPFR_copy_sign, METH_VARARGS, GMPy_doc_mpfr_copy_sign },
{ "cos", GMPy_Context_Cos, METH_O, GMPy_doc_function_cos },
{ "cosh", GMPy_Context_Cosh, METH_O, GMPy_doc_function_cosh },
{ "cot", GMPy_Context_Cot, METH_O, GMPy_doc_function_cot },
{ "coth", GMPy_Context_Coth, METH_O, GMPy_doc_function_coth },
{ "csc", GMPy_Context_Csc, METH_O, GMPy_doc_function_csc },
{ "csch", GMPy_Context_Csch, METH_O, GMPy_doc_function_csch },
{ "degrees", GMPy_Context_Degrees, METH_O, GMPy_doc_function_degrees },
{ "digamma", GMPy_Context_Digamma, METH_O, GMPy_doc_function_digamma },
{ "div_2exp", GMPy_Context_Div_2exp, METH_VARARGS, GMPy_doc_function_div_2exp },
{ "eint", GMPy_Context_Eint, METH_O, GMPy_doc_function_eint },
{ "erf", GMPy_Context_Erf, METH_O, GMPy_doc_function_erf },
{ "erfc", GMPy_Context_Erfc, METH_O, GMPy_doc_function_erfc },
{ "exp", GMPy_Context_Exp, METH_O, GMPy_doc_function_exp },
{ "expm1", GMPy_Context_Expm1, METH_O, GMPy_doc_function_expm1 },
{ "exp10", GMPy_Context_Exp10, METH_O, GMPy_doc_function_exp10 },
{ "exp2", GMPy_Context_Exp2, METH_O, GMPy_doc_function_exp2 },
{ "f2q", GMPy_Context_F2Q, METH_VARARGS, GMPy_doc_function_f2q },
{ "factorial", GMPy_Context_Factorial, METH_O, GMPy_doc_function_factorial },
{ "floor", GMPy_Context_Floor, METH_O, GMPy_doc_function_floor },
{ "fma", GMPy_Context_FMA, METH_VARARGS, GMPy_doc_function_fma },
{ "fms", GMPy_Context_FMS, METH_VARARGS, GMPy_doc_function_fms },
{ "fmma", GMPy_Context_FMMA, METH_VARARGS, GMPy_doc_function_fmma },
{ "fmms", GMPy_Context_FMMS, METH_VARARGS, GMPy_doc_function_fmms },
{ "fmod", GMPy_Context_Fmod, METH_VARARGS, GMPy_doc_function_fmod },
{ "frac", GMPy_Context_Frac, METH_O, GMPy_doc_function_frac },
{ "free_cache", GMPy_MPFR_Free_Cache, METH_NOARGS, GMPy_doc_mpfr_free_cache },
{ "frexp", GMPy_Context_Frexp, METH_O, GMPy_doc_function_frexp },
{ "fsum", GMPy_Context_Fsum, METH_O, GMPy_doc_function_fsum },
{ "gamma", GMPy_Context_Gamma, METH_O, GMPy_doc_function_gamma },
{ "gamma_inc", GMPy_Context_Gamma_Inc, METH_VARARGS, GMPy_doc_function_gamma_inc },
{ "get_context", GMPy_CTXT_Get, METH_NOARGS, GMPy_doc_get_context },
{ "get_emax_max", GMPy_MPFR_get_emax_max, METH_NOARGS, GMPy_doc_mpfr_get_emax_max },
{ "get_emin_min", GMPy_MPFR_get_emin_min, METH_NOARGS, GMPy_doc_mpfr_get_emin_min },
{ "get_exp", GMPy_MPFR_get_exp, METH_O, GMPy_doc_mpfr_get_exp },
{ "get_max_precision", GMPy_MPFR_get_max_precision, METH_NOARGS, GMPy_doc_mpfr_get_max_precision },
{ "hypot", GMPy_Context_Hypot, METH_VARARGS, GMPy_doc_function_hypot },
{ "ieee", (PyCFunction)GMPy_CTXT_ieee, METH_VARARGS | METH_KEYWORDS, GMPy_doc_context_ieee },
{ "inf", GMPy_MPFR_set_inf, METH_VARARGS, GMPy_doc_mpfr_set_inf },
{ "is_finite", GMPy_Context_Is_Finite, METH_O, GMPy_doc_function_is_finite },
{ "is_infinite", GMPy_Context_Is_Infinite, METH_O, GMPy_doc_function_is_infinite },
{ "is_integer", GMPy_Context_Is_Integer, METH_O, GMPy_doc_function_is_integer },
{ "is_lessgreater", GMPy_Context_Is_LessGreater, METH_VARARGS, GMPy_doc_function_is_lessgreater },
{ "is_nan", GMPy_Context_Is_NAN, METH_O, GMPy_doc_function_is_nan },
{ "is_regular", GMPy_Context_Is_Regular, METH_O, GMPy_doc_function_is_regular },
{ "is_signed", GMPy_Context_Is_Signed, METH_O, GMPy_doc_function_is_signed },
{ "is_unordered", GMPy_Context_Is_Unordered, METH_VARARGS, GMPy_doc_function_is_unordered },
{ "is_zero", GMPy_Context_Is_Zero, METH_O, GMPy_doc_function_is_zero },
{ "jn", GMPy_Context_Jn, METH_VARARGS, GMPy_doc_function_jn },
{ "j0", GMPy_Context_J0, METH_O, GMPy_doc_function_j0 },
{ "j1", GMPy_Context_J1, METH_O, GMPy_doc_function_j1 },
{ "lgamma", GMPy_Context_Lgamma, METH_O, GMPy_doc_function_lgamma },
{ "li2", GMPy_Context_Li2, METH_O, GMPy_doc_function_li2 },
{ "lngamma", GMPy_Context_Lngamma, METH_O, GMPy_doc_function_lngamma },
{ "local_context", (PyCFunction)GMPy_CTXT_Local, METH_VARARGS | METH_KEYWORDS, GMPy_doc_local_context },
{ "log", GMPy_Context_Log, METH_O, GMPy_doc_function_log },
{ "log1p", GMPy_Context_Log1p, METH_O, GMPy_doc_function_log1p },
{ "log10", GMPy_Context_Log10, METH_O, GMPy_doc_function_log10 },
{ "log2", GMPy_Context_Log2, METH_O, GMPy_doc_function_log2 },
{ "maxnum", GMPy_Context_Maxnum, METH_VARARGS, GMPy_doc_function_maxnum },
{ "minnum", GMPy_Context_Minnum, METH_VARARGS, GMPy_doc_function_minnum },
{ "modf", GMPy_Context_Modf, METH_O, GMPy_doc_function_modf },
{ "mpfr_from_old_binary", GMPy_MPFR_From_Old_Binary, METH_O, doc_mpfr_from_old_binary },
{ "mpfr_random", GMPy_MPFR_random_Function, METH_VARARGS, GMPy_doc_mpfr_random_function },
{ "mpfr_grandom", GMPy_MPFR_grandom_Function, METH_VARARGS, GMPy_doc_mpfr_grandom_function },
{ "mpfr_nrandom", GMPy_MPFR_nrandom_Function, METH_VARARGS, GMPy_doc_mpfr_nrandom_function },
{ "mul_2exp", GMPy_Context_Mul_2exp, METH_VARARGS, GMPy_doc_function_mul_2exp },
{ "nan", GMPy_MPFR_set_nan, METH_NOARGS, GMPy_doc_mpfr_set_nan },
{ "next_above", GMPy_Context_NextAbove, METH_O, GMPy_doc_function_next_above },
{ "next_below", GMPy_Context_NextBelow, METH_O, GMPy_doc_function_next_below },
{ "next_toward", GMPy_Context_NextToward, METH_VARARGS, GMPy_doc_function_next_toward },
{ "radians", GMPy_Context_Radians, METH_O, GMPy_doc_function_radians },
{ "rec_sqrt", GMPy_Context_RecSqrt, METH_O, GMPy_doc_function_rec_sqrt },
{ "reldiff", GMPy_Context_RelDiff, METH_VARARGS, GMPy_doc_function_reldiff },
{ "remainder", GMPy_Context_Remainder, METH_VARARGS, GMPy_doc_function_remainder },
{ "remquo", GMPy_Context_RemQuo, METH_VARARGS, GMPy_doc_function_remquo },
{ "rint", GMPy_Context_Rint, METH_O, GMPy_doc_function_rint },
{ "rint_ceil", GMPy_Context_RintCeil, METH_O, GMPy_doc_function_rint_ceil },
{ "rint_floor", GMPy_Context_RintFloor, METH_O, GMPy_doc_function_rint_floor },
{ "rint_round", GMPy_Context_RintRound, METH_O, GMPy_doc_function_rint_round },
{ "rint_trunc", GMPy_Context_RintTrunc, METH_O, GMPy_doc_function_rint_trunc },
{ "root", GMPy_Context_Root, METH_VARARGS, GMPy_doc_function_root },
{ "rootn", GMPy_Context_Rootn, METH_VARARGS, GMPy_doc_function_rootn },
{ "round_away", GMPy_Context_RoundAway, METH_O, GMPy_doc_function_round_away },
{ "round2", GMPy_Context_Round2, METH_VARARGS, GMPy_doc_function_round2 },
{ "sec", GMPy_Context_Sec, METH_O, GMPy_doc_function_sec },
{ "sech", GMPy_Context_Sech, METH_O, GMPy_doc_function_sech },
{ "set_context", GMPy_CTXT_Set, METH_O, GMPy_doc_set_context },
{ "set_exp", GMPy_MPFR_set_exp, METH_VARARGS, GMPy_doc_mpfr_set_exp },
{ "set_sign", GMPy_MPFR_set_sign, METH_VARARGS, GMPy_doc_mpfr_set_sign },
{ "sin", GMPy_Context_Sin, METH_O, GMPy_doc_function_sin },
{ "sin_cos", GMPy_Context_Sin_Cos, METH_O, GMPy_doc_function_sin_cos },
{ "sinh", GMPy_Context_Sinh, METH_O, GMPy_doc_function_sinh },
{ "sinh_cosh", GMPy_Context_Sinh_Cosh, METH_O, GMPy_doc_function_sinh_cosh },
{ "sqrt", GMPy_Context_Sqrt, METH_O, GMPy_doc_function_sqrt },
{ "tan", GMPy_Context_Tan, METH_O, GMPy_doc_function_tan },
{ "tanh", GMPy_Context_Tanh, METH_O, GMPy_doc_function_tanh },
{ "trunc", GMPy_Context_Trunc, METH_O, GMPy_doc_function_trunc},
#ifdef VECTOR
{ "vector", GMPy_Context_Vector, METH_O, GMPy_doc_function_vector},
{ "vector2", GMPy_Context_Vector2, METH_VARARGS, GMPy_doc_function_vector2},
#endif
{ "yn", GMPy_Context_Yn, METH_VARARGS, GMPy_doc_function_yn },
{ "y0", GMPy_Context_Y0, METH_O, GMPy_doc_function_y0 },
{ "y1", GMPy_Context_Y1, METH_O, GMPy_doc_function_y1 },
{ "zero", GMPy_MPFR_set_zero, METH_VARARGS, GMPy_doc_mpfr_set_zero },
{ "zeta", GMPy_Context_Zeta, METH_O, GMPy_doc_function_zeta },
{ "mpc_random", GMPy_MPC_random_Function, METH_VARARGS, GMPy_doc_mpc_random_function },
{ "norm", GMPy_Context_Norm, METH_O, GMPy_doc_function_norm },
{ "polar", GMPy_Context_Polar, METH_O, GMPy_doc_function_polar },
{ "phase", GMPy_Context_Phase, METH_O, GMPy_doc_function_phase },
{ "proj", GMPy_Context_Proj, METH_O, GMPy_doc_function_proj },
{ "root_of_unity", GMPy_Context_Root_Of_Unity, METH_VARARGS, GMPy_doc_function_root_of_unity },
{ "rect", GMPy_Context_Rect, METH_VARARGS, GMPy_doc_function_rect },
{ NULL, NULL, 1}
};
static char _gmpy_docs[] =
"gmpy2 2.2.1 - General Multiple-precision arithmetic for Python\n"
"\n"
"gmpy2 supports several multiple-precision libraries. Integer and\n"
"rational arithmetic is provided by the GMP library. Real floating-\n"
"point arithmetic is provided by the MPFR library. Complex floating-\n"
"point arithmetic is provided by the MPC library.\n"
"\n"
"The integer type 'mpz' has comparable functionality to Python's\n"
"builtin integers, but is faster for operations on large numbers.\n"
"A wide variety of additional functions are provided:\n"
" - bit manipulations\n"
" - GCD, Extended GCD, LCM\n"
" - Fibonacci and Lucas sequences\n"
" - primality testing\n"
" - powers and integer Nth roots\n"
"\n"
"The rational type 'mpq' is equivalent to Python's fractions\n"
"module, but is faster.\n"
"\n"
"The real type 'mpfr' and complex type 'mpc' provide multiple-\n"
"precision real and complex numbers with user-definable precision,\n"
"rounding, and exponent range. All the advanced functions from the\n"
"MPFR and MPC libraries are available.\n\
";
/* Notes on Python 3.x support: Full support for PEP-3121 has not been
* implemented. No per-module state has been defined.
*/
static struct PyModuleDef moduledef = {
PyModuleDef_HEAD_INIT,
"gmpy2",
_gmpy_docs,
-1, /*sizeof(struct module_state) */
Pygmpy_methods,
NULL,
NULL, /* gmpy_traverse */
NULL, /* gmpy_clear */
NULL
};
PyMODINIT_FUNC PyInit_gmpy2(void)
{
PyObject *result = NULL;
PyObject *namespace = NULL;
PyObject *gmpy_module = NULL;
PyObject *copy_reg_module = NULL;
PyObject *temp = NULL;
PyObject *numbers_module = NULL;
PyObject* xmpz = NULL;
PyObject* limb_size = NULL;
#ifndef STATIC
static void *GMPy_C_API[GMPy_API_pointers];
PyObject *c_api_object;
#endif
/* Validate the sizes of the various typedef'ed integer types. */
if (sizeof(mpfr_prec_t) != sizeof(long)) {
/* LCOV_EXCL_START */
SYSTEM_ERROR("Size of mpfr_prec_t and long not compatible");
return NULL;;
/* LCOV_EXCL_STOP */
}
if (sizeof(mpfr_exp_t) != sizeof(long)) {
/* LCOV_EXCL_START */
SYSTEM_ERROR("Size of mpfr_exp_t and long not compatible");
return NULL;;
/* LCOV_EXCL_STOP */
}
/* Initialize the types. */
if (PyType_Ready(&MPZ_Type) < 0) {
/* LCOV_EXCL_START */
return NULL;;
/* LCOV_EXCL_STOP */
}
if (PyType_Ready(&MPQ_Type) < 0) {
/* LCOV_EXCL_START */
return NULL;;
/* LCOV_EXCL_STOP */
}
if (PyType_Ready(&XMPZ_Type) < 0) {
/* LCOV_EXCL_START */
return NULL;;
/* LCOV_EXCL_STOP */
}
if (PyType_Ready(&GMPy_Iter_Type) < 0) {
/* LCOV_EXCL_START */
return NULL;;
/* LCOV_EXCL_STOP */
}
if (PyType_Ready(&MPFR_Type) < 0) {
/* LCOV_EXCL_START */
return NULL;;
/* LCOV_EXCL_STOP */
}
if (PyType_Ready(&CTXT_Type) < 0) {
/* LCOV_EXCL_START */
return NULL;;
/* LCOV_EXCL_STOP */
}
if (PyType_Ready(&MPC_Type) < 0) {
/* LCOV_EXCL_START */
return NULL;;
/* LCOV_EXCL_STOP */
}
if (PyType_Ready(&RandomState_Type) < 0) {
/* LCOV_EXCL_START */
return NULL;;
/* LCOV_EXCL_STOP */
}
/* Initialize exceptions. */
GMPyExc_GmpyError = PyErr_NewException("gmpy2.gmpy2Error", PyExc_ArithmeticError, NULL);
if (!GMPyExc_GmpyError) {
/* LCOV_EXCL_START */
return NULL;;
/* LCOV_EXCL_STOP */
}
GMPyExc_Erange = PyErr_NewException("gmpy2.RangeError", GMPyExc_GmpyError, NULL);
if (!GMPyExc_Erange) {
/* LCOV_EXCL_START */
return NULL;;
/* LCOV_EXCL_STOP */
}
GMPyExc_Inexact = PyErr_NewException("gmpy2.InexactResultError", GMPyExc_GmpyError, NULL);
if (!GMPyExc_Inexact) {
/* LCOV_EXCL_START */
return NULL;;
/* LCOV_EXCL_STOP */
}
GMPyExc_Overflow = PyErr_NewException("gmpy2.OverflowResultError", GMPyExc_Inexact, NULL);
if (!GMPyExc_Overflow) {
/* LCOV_EXCL_START */
return NULL;;
/* LCOV_EXCL_STOP */
}
GMPyExc_Underflow = PyErr_NewException("gmpy2.UnderflowResultError", GMPyExc_Inexact, NULL);
if (!GMPyExc_Underflow) {
/* LCOV_EXCL_START */
return NULL;;
/* LCOV_EXCL_STOP */
}
temp = PyTuple_Pack(2, GMPyExc_GmpyError, PyExc_ValueError);
if (!temp) {
/* LCOV_EXCL_START */
return NULL;;
/* LCOV_EXCL_STOP */
}
GMPyExc_Invalid = PyErr_NewException("gmpy2.InvalidOperationError", temp, NULL);
Py_DECREF(temp);
if (!GMPyExc_Invalid) {
/* LCOV_EXCL_START */
return NULL;;
/* LCOV_EXCL_STOP */
}
temp = PyTuple_Pack(2, GMPyExc_GmpyError, PyExc_ZeroDivisionError);
if (!temp) {
/* LCOV_EXCL_START */
return NULL;;
/* LCOV_EXCL_STOP */
}
GMPyExc_DivZero = PyErr_NewException("gmpy2.DivisionByZeroError", temp, NULL);
Py_DECREF(temp);
if (!GMPyExc_DivZero) {
/* LCOV_EXCL_START */
return NULL;;
/* LCOV_EXCL_STOP */
}
gmpy_module = PyModule_Create(&moduledef);
if (gmpy_module == NULL) {
/* LCOV_EXCL_START */
return NULL;;
/* LCOV_EXCL_STOP */
}
/* Add the context type to the module namespace. */
Py_INCREF(&CTXT_Type);
PyModule_AddObject(gmpy_module, "context", (PyObject*)&CTXT_Type);
/* Add the mpz type to the module namespace. */
Py_INCREF(&MPZ_Type);
PyModule_AddObject(gmpy_module, "mpz", (PyObject*)&MPZ_Type);
/* Add the xmpz type to the module namespace. */
Py_INCREF(&XMPZ_Type);
PyModule_AddObject(gmpy_module, "xmpz", (PyObject*)&XMPZ_Type);
xmpz = XMPZ_Type.tp_dict;
limb_size = PyLong_FromSize_t(sizeof(mp_limb_t));
PyDict_SetItemString(xmpz, "limb_size", limb_size);
Py_DECREF(limb_size);
/* Add the MPQ type to the module namespace. */
Py_INCREF(&MPQ_Type);
PyModule_AddObject(gmpy_module, "mpq", (PyObject*)&MPQ_Type);
/* Add the MPFR type to the module namespace. */
Py_INCREF(&MPFR_Type);
PyModule_AddObject(gmpy_module, "mpfr", (PyObject*)&MPFR_Type);
/* Add the MPC type to the module namespace. */
Py_INCREF(&MPC_Type);
PyModule_AddObject(gmpy_module, "mpc", (PyObject*)&MPC_Type);
/* Initialize context var. */
if (!(current_context_var = PyContextVar_New("gmpy2_context", NULL))) {
return NULL;
}
/* Add the constants for defining rounding modes. */
if (PyModule_AddIntConstant(gmpy_module, "RoundToNearest", MPFR_RNDN) < 0) {
/* LCOV_EXCL_START */
return NULL;;
/* LCOV_EXCL_STOP */
}
if (PyModule_AddIntConstant(gmpy_module, "RoundToZero", MPFR_RNDZ) < 0) {
/* LCOV_EXCL_START */
return NULL;;
/* LCOV_EXCL_STOP */
}
if (PyModule_AddIntConstant(gmpy_module, "RoundUp", MPFR_RNDU) < 0) {
/* LCOV_EXCL_START */
return NULL;;
/* LCOV_EXCL_STOP */
}
if (PyModule_AddIntConstant(gmpy_module, "RoundDown", MPFR_RNDD) < 0) {
/* LCOV_EXCL_START */
return NULL;;
/* LCOV_EXCL_STOP */
}
if (PyModule_AddIntConstant(gmpy_module, "RoundAwayZero", MPFR_RNDA) < 0) {
/* LCOV_EXCL_START */
return NULL;;
/* LCOV_EXCL_STOP */
}
if (PyModule_AddIntConstant(gmpy_module, "Default", GMPY_DEFAULT) < 0) {
/* LCOV_EXCL_START */
return NULL;;
/* LCOV_EXCL_STOP */
}
if (PyModule_AddStringConstant(gmpy_module, "__version__", gmpy_version) < 0) {
/* LCOV_EXCL_START */
return NULL;
/* LCOV_EXCL_STOP */
}
/* Add the exceptions. */
Py_INCREF(GMPyExc_DivZero);
if (PyModule_AddObject(gmpy_module, "DivisionByZeroError", GMPyExc_DivZero) < 0) {
/* LCOV_EXCL_START */
Py_DECREF(GMPyExc_DivZero);
return NULL;;
/* LCOV_EXCL_STOP */
}
Py_INCREF(GMPyExc_Inexact);
if (PyModule_AddObject(gmpy_module, "InexactResultError", GMPyExc_Inexact) < 0) {
/* LCOV_EXCL_START */
Py_DECREF(GMPyExc_Inexact);
return NULL;;
/* LCOV_EXCL_STOP */
}
Py_INCREF(GMPyExc_Invalid);
if (PyModule_AddObject(gmpy_module, "InvalidOperationError", GMPyExc_Invalid) < 0 ) {
/* LCOV_EXCL_START */
Py_DECREF(GMPyExc_Invalid);
return NULL;;
/* LCOV_EXCL_STOP */
}
Py_INCREF(GMPyExc_Overflow);
if (PyModule_AddObject(gmpy_module, "OverflowResultError", GMPyExc_Overflow) < 0) {
/* LCOV_EXCL_START */
Py_DECREF(GMPyExc_Overflow);
return NULL;;
/* LCOV_EXCL_STOP */
}
Py_INCREF(GMPyExc_Underflow);
if (PyModule_AddObject(gmpy_module, "UnderflowResultError", GMPyExc_Underflow) < 0) {
/* LCOV_EXCL_START */
Py_DECREF(GMPyExc_Underflow);
return NULL;;
/* LCOV_EXCL_STOP */
}
Py_INCREF(GMPyExc_Erange);
if (PyModule_AddObject(gmpy_module, "RangeError", GMPyExc_Erange) < 0) {
/* LCOV_EXCL_START */
Py_DECREF(GMPyExc_Erange);
return NULL;;
/* LCOV_EXCL_STOP */
}
#ifdef SHARED
/* Create the Capsule for the C-API. */
GMPy_C_API[MPZ_Type_NUM] = (void*)&MPZ_Type;
GMPy_C_API[XMPZ_Type_NUM] = (void*)&XMPZ_Type;
GMPy_C_API[MPQ_Type_NUM] = (void*)&MPQ_Type;
GMPy_C_API[XMPQ_Type_NUM] = (void*)&MPQ_Type;
GMPy_C_API[MPFR_Type_NUM] = (void*)&MPFR_Type;
GMPy_C_API[XMPFR_Type_NUM] = (void*)&MPFR_Type;
GMPy_C_API[MPC_Type_NUM] = (void*)&MPC_Type;
GMPy_C_API[XMPC_Type_NUM] = (void*)&MPC_Type;
GMPy_C_API[CTXT_Type_NUM] = (void*)&CTXT_Type;
GMPy_C_API[RandomState_Type_NUM] = (void*)&RandomState_Type;
GMPy_C_API[GMPy_MPZ_New_NUM] = (void*)GMPy_MPZ_New;
GMPy_C_API[GMPy_MPZ_NewInit_NUM] = (void*)GMPy_MPZ_NewInit;
GMPy_C_API[GMPy_MPZ_Dealloc_NUM] = (void*)GMPy_MPZ_Dealloc;
GMPy_C_API[GMPy_MPZ_ConvertArg_NUM] = (void*)GMPy_MPZ_ConvertArg;
GMPy_C_API[GMPy_XMPZ_New_NUM] = (void*)GMPy_XMPZ_New;
GMPy_C_API[GMPy_XMPZ_NewInit_NUM] = (void*)GMPy_XMPZ_NewInit;
GMPy_C_API[GMPy_XMPZ_Dealloc_NUM] = (void*)GMPy_XMPZ_Dealloc;
GMPy_C_API[GMPy_MPQ_New_NUM] = (void*)GMPy_MPQ_New;
GMPy_C_API[GMPy_MPQ_NewInit_NUM] = (void*)GMPy_MPQ_NewInit;
GMPy_C_API[GMPy_MPQ_Dealloc_NUM] = (void*)GMPy_MPQ_Dealloc;
GMPy_C_API[GMPy_MPQ_ConvertArg_NUM] = (void*)GMPy_MPQ_ConvertArg;
GMPy_C_API[GMPy_MPFR_New_NUM] = (void*)GMPy_MPFR_New;
GMPy_C_API[GMPy_MPFR_NewInit_NUM] = (void*)GMPy_MPFR_NewInit;
GMPy_C_API[GMPy_MPFR_Dealloc_NUM] = (void*)GMPy_MPFR_Dealloc;
GMPy_C_API[GMPy_MPFR_ConvertArg_NUM] = (void*)GMPy_MPFR_ConvertArg;
GMPy_C_API[GMPy_MPC_New_NUM] = (void*)GMPy_MPC_New;
GMPy_C_API[GMPy_MPC_NewInit_NUM] = (void*)GMPy_MPC_NewInit;
GMPy_C_API[GMPy_MPC_Dealloc_NUM] = (void*)GMPy_MPC_Dealloc;
GMPy_C_API[GMPy_MPC_ConvertArg_NUM] = (void*)GMPy_MPC_ConvertArg;
c_api_object = PyCapsule_New((void *)GMPy_C_API, "gmpy2._C_API", NULL);
if (c_api_object != NULL) {
PyModule_AddObject(gmpy_module, "_C_API", c_api_object);
}
#endif
/* Add support for pickling. */
copy_reg_module = PyImport_ImportModule("copyreg");
if (copy_reg_module) {
char* enable_pickle =
"def gmpy2_reducer(x): return (gmpy2.from_binary, (gmpy2.to_binary(x),))\n"
"copyreg.pickle(gmpy2.mpz, gmpy2_reducer)\n"
"copyreg.pickle(gmpy2.xmpz, gmpy2_reducer)\n"
"copyreg.pickle(gmpy2.mpq, gmpy2_reducer)\n"
"copyreg.pickle(gmpy2.mpfr, gmpy2_reducer)\n"
"copyreg.pickle(gmpy2.mpc, gmpy2_reducer)\n";
namespace = PyDict_New();
result = NULL;
PyDict_SetItemString(namespace, "copyreg", copy_reg_module);
PyDict_SetItemString(namespace, "gmpy2", gmpy_module);
result = PyRun_String(enable_pickle, Py_file_input, namespace, namespace);
if (!result) {
/* LCOV_EXCL_START */
PyErr_Clear();
/* LCOV_EXCL_STOP */
}
Py_DECREF(namespace);
Py_DECREF(copy_reg_module);
Py_XDECREF(result);
}
else {
/* LCOV_EXCL_START */
PyErr_Clear();
/* LCOV_EXCL_STOP */
}
/* Register the gmpy2 types with the numeric tower. */
numbers_module = PyImport_ImportModule("numbers");
if (numbers_module) {
char* register_numbers =
"numbers.Integral.register(gmpy2.mpz)\n"
"numbers.Rational.register(gmpy2.mpq)\n"
"numbers.Real.register(gmpy2.mpfr)\n"
"numbers.Complex.register(gmpy2.mpc)\n"
;
namespace = PyDict_New();
result = NULL;
PyDict_SetItemString(namespace, "numbers", numbers_module);
PyDict_SetItemString(namespace, "gmpy2", gmpy_module);
result = PyRun_String(register_numbers, Py_file_input,
namespace, namespace);
if (!result) {
/* LCOV_EXCL_START */
PyErr_Clear();
/* LCOV_EXCL_STOP */
}
Py_DECREF(namespace);
Py_DECREF(numbers_module);
Py_XDECREF(result);
}
else {
/* LCOV_EXCL_START */
PyErr_Clear();
/* LCOV_EXCL_STOP */
}
return gmpy_module;
}
././@PaxHeader 0000000 0000000 0000000 00000000026 00000000000 010213 x ustar 00 22 mtime=1710307256.0
gmpy2-2.2.1/src/gmpy2.h 0000644 0001750 0001750 00000044465 14574233670 013250 0 ustar 00case case /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* gmpy2.h *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Python interface to the GMP, MPFR, and MPC multiple precision *
* libraries. *
* *
* Copyright 2000 - 2009 Alex Martelli *
* *
* Copyright 2008 - 2024 Case Van Horsen *
* *
* This file is part of GMPY2. *
* *
* GMPY2 is free software: you can redistribute it and/or modify it under *
* the terms of the GNU Lesser General Public License as published by the *
* Free Software Foundation, either version 3 of the License, or (at your *
* option) any later version. *
* *
* GMPY2 is distributed in the hope that it will be useful, but WITHOUT *
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or *
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public *
* License for more details. *
* *
* You should have received a copy of the GNU Lesser General Public *
* License along with GMPY2; if not, see *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
/*
gmpy C API extension header file.
Part of Python's gmpy module since version 0.4
Created by Pearu Peterson , November 2000.
Edited by A. Martelli , December 2000.
Edited by Case Van Horsen , 2009, 2010, 2011.
Version 1.02, February 2007.
Version 1.03, June 2008
Version 1.04, June 2008 (no changes)
Version 1.05, February 2009 (support MPIR)
Version 1.20, January 2010 (remove obsolete MS hacks) casevh
Version 2.00, April 2010 (change to gmpy2) casevh
October 2010 (added Py_hash_t) casevh
December 2010 (added mpfr, mpc) casevh
January 2011 (add Pygmpy_context) casevh
April 2011 (split into multiple files) casevh
Version 2.10 August 2014 (reflect major rewrite during 2013/2014) casevh
*/
#ifndef Py_GMPYMODULE_H
#define Py_GMPYMODULE_H
#ifdef __cplusplus
extern "C" {
#endif
/* Structure of gmpy2.h
*
* Revised 17-APR-2017 casevh
*
* 1. Checks for specific Python versions.
* 2. Include headers for GMP/MPIR, MPFR, and MPC.
* 3. Define public C-API.
* 1. Define gmpy2 types.
* 2. Define the public API.
*
*/
/* Check for minimum Python version requirements. */
#if PY_VERSION_HEX < 0x03070000
# error "GMPY2 requires Python 3.7 or later."
#endif
/* Include headers for GMP, MPFR, and MPC. */
#include
#include
#include
/* Check MPFR and MPC versions. */
/* gmpy2 supports the two most recent major versions of MPFR and MPC.
*
* As of gmpy2 2.2.0, the code assumes the MPFR version is at least 4.1.0
* and new features included in 4.2.0 are guarded by #ifdef MPFR_420.
* For MPC, the minumum version is assumed to 1.2.1 and new features
* included in 1.3.0 are guarded by #ifdef MPC_130.
*
*/
#if (!defined(MPFR_VERSION) || (MPFR_VERSION < MPFR_VERSION_NUM(4,1,0)))
# error "GMPY2 requires MPFR 4.1.0 or later."
#endif
#if (defined(MPFR_VERSION) && (MPFR_VERSION >= MPFR_VERSION_NUM(4,2,0)))
# define MPFR_420
#endif
#if (!defined(MPC_VERSION) || (MPC_VERSION < MPC_VERSION_NUM(1,2,1)))
# error "GMPY2 requires MPC 1.2.1 or later."
#endif
#if (defined(MPC_VERSION) && (MPC_VERSION == MPC_VERSION_NUM(1,3,0)))
# define MPC_130
#endif
/* GMPY2 Public API */
/* Types
* MPZ_Object
* XMPZ_Object (mutable version of MPZ_Object)
* MPQ_Object
* XMPQ_Object (mutable version of MPQ_Object)
* MPFR_Object
* XMPFR_Object (mutable version of MPFR_Object)
* MPC_Object
* XMPC_Object (mutable version of MPC_Object)
* CTXT_Object
* RandomState_Object
*/
typedef struct {
PyObject_HEAD
mpz_t z;
Py_hash_t hash_cache;
} MPZ_Object;
typedef struct {
PyObject_HEAD
mpz_t z;
} XMPZ_Object;
typedef struct {
PyObject_HEAD
mpq_t q;
Py_hash_t hash_cache;
} MPQ_Object;
typedef struct {
PyObject_HEAD
mpfr_t f;
Py_hash_t hash_cache;
int rc;
} MPFR_Object;
typedef struct {
PyObject_HEAD
mpc_t c;
Py_hash_t hash_cache;
int rc;
} MPC_Object;
typedef struct {
PyObject_HEAD
gmp_randstate_t state;
} RandomState_Object;
typedef struct {
mpfr_prec_t mpfr_prec; /* current precision in bits, for MPFR */
mpfr_rnd_t mpfr_round; /* current rounding mode for float (MPFR) */
mpfr_exp_t emax; /* maximum exponent */
mpfr_exp_t emin; /* minimum exponent */
int subnormalize; /* if 1, subnormalization is performed */
int underflow; /* did an underflow occur? */
int overflow; /* did an overflow occur? */
int inexact; /* was the result inexact? */
int invalid; /* invalid operation (i.e. NaN)? */
int erange; /* did a range error occur? */
int divzero; /* divided by zero? */
int traps; /* if 0, do not trap any exceptions */
/* if not 0, then raise traps per bits above */
mpfr_prec_t real_prec; /* current precision in bits, for Re(MPC) */
mpfr_prec_t imag_prec; /* current precision in bits, for Im(MPC) */
mpfr_rnd_t real_round; /* current rounding mode for Re(MPC) */
mpfr_rnd_t imag_round; /* current rounding mode for Im(MPC) */
int allow_complex; /* if 1, allow mpfr functions to return an mpc */
int rational_division; /* if 1, mpz/mpz returns an mpq result */
int allow_release_gil; /* if 1, allow mpz functions to release the GIL */
} gmpy_context;
typedef struct {
PyObject_HEAD
gmpy_context ctx;
PyObject *token;
} CTXT_Object;
#define MPZ(obj) (((MPZ_Object*)(obj))->z)
#define MPQ(obj) (((MPQ_Object*)(obj))->q)
#define MPFR(obj) (((MPFR_Object*)(obj))->f)
#define MPC(obj) (((MPC_Object*)(obj))->c)
/* Start of the C-API definitions */
#define MPZ_Type_NUM 0
#define XMPZ_Type_NUM 1
#define MPQ_Type_NUM 2
#define XMPQ_Type_NUM 3
#define MPFR_Type_NUM 4
#define XMPFR_Type_NUM 5
#define MPC_Type_NUM 6
#define XMPC_Type_NUM 7
#define CTXT_Type_NUM 8
#define RandomState_Type_NUM 10
/* The following functions are found in gmpy2_cache. */
#define GMPy_MPZ_New_NUM 11
#define GMPy_MPZ_New_RETURN MPZ_Object *
#define GMPy_MPZ_New_PROTO (CTXT_Object *context)
#define GMPy_MPZ_NewInit_NUM 12
#define GMPy_MPZ_NewInit_RETURN PyObject *
#define GMPy_MPZ_NewInit_PROTO (PyTypeObject *type, PyObject *args, PyObject *keywds)
#define GMPy_MPZ_Dealloc_NUM 13
#define GMPy_MPZ_Dealloc_RETURN void
#define GMPy_MPZ_Dealloc_PROTO (MPZ_Object *self)
/* The following function is found in gmpy2_convert_gmp. */
#define GMPy_MPZ_ConvertArg_NUM 14
#define GMPy_MPZ_ConvertArg_RETURN int
#define GMPy_MPZ_ConvertArg_PROTO (PyObject *arg, PyObject **ptr)
/* The following functions are found in gmpy2_cache. */
#define GMPy_XMPZ_New_NUM 15
#define GMPy_XMPZ_New_RETURN XMPZ_Object *
#define GMPy_XMPZ_New_PROTO (CTXT_Object *context)
#define GMPy_XMPZ_NewInit_NUM 16
#define GMPy_XMPZ_NewInit_RETURN PyObject *
#define GMPy_XMPZ_NewInit_PROTO (PyTypeObject *type, PyObject *args, PyObject *keywds)
#define GMPy_XMPZ_Dealloc_NUM 17
#define GMPy_XMPZ_Dealloc_RETURN void
#define GMPy_XMPZ_Dealloc_PROTO (XMPZ_Object *self)
/* The following functions are found in gmpy2_cache. */
#define GMPy_MPQ_New_NUM 18
#define GMPy_MPQ_New_RETURN MPQ_Object *
#define GMPy_MPQ_New_PROTO (CTXT_Object *context)
#define GMPy_MPQ_NewInit_NUM 19
#define GMPy_MPQ_NewInit_RETURN PyObject *
#define GMPy_MPQ_NewInit_PROTO (PyTypeObject *type, PyObject *args, PyObject *keywds)
#define GMPy_MPQ_Dealloc_NUM 20
#define GMPy_MPQ_Dealloc_RETURN void
#define GMPy_MPQ_Dealloc_PROTO (MPQ_Object *self)
/* The following function is found in gmpy2_convert_gmp. */
#define GMPy_MPQ_ConvertArg_NUM 21
#define GMPy_MPQ_ConvertArg_RETURN int
#define GMPy_MPQ_ConvertArg_PROTO (PyObject *arg, PyObject **ptr)
/* The following functions are found in gmpy2_cache. */
#define GMPy_MPFR_New_NUM 22
#define GMPy_MPFR_New_RETURN MPFR_Object *
#define GMPy_MPFR_New_PROTO (mpfr_prec_t bits, CTXT_Object *context)
#define GMPy_MPFR_NewInit_NUM 23
#define GMPy_MPFR_NewInit_RETURN PyObject *
#define GMPy_MPFR_NewInit_PROTO (PyTypeObject *type, PyObject *args, PyObject *keywds)
#define GMPy_MPFR_Dealloc_NUM 24
#define GMPy_MPFR_Dealloc_RETURN void
#define GMPy_MPFR_Dealloc_PROTO (MPFR_Object *self)
/* The following function is found in gmpy2_convert_gmp. */
#define GMPy_MPFR_ConvertArg_NUM 25
#define GMPy_MPFR_ConvertArg_RETURN int
#define GMPy_MPFR_ConvertArg_PROTO (PyObject *arg, PyObject **ptr)
/* The following functions are found in gmpy2_cache. */
#define GMPy_MPC_New_NUM 26
#define GMPy_MPC_New_RETURN MPC_Object *
#define GMPy_MPC_New_PROTO (mpfr_prec_t rprec, mpfr_prec_t iprec, CTXT_Object *context)
#define GMPy_MPC_NewInit_NUM 27
#define GMPy_MPC_NewInit_RETURN PyObject *
#define GMPy_MPC_NewInit_PROTO (PyTypeObject *type, PyObject *args, PyObject *keywds)
#define GMPy_MPC_Dealloc_NUM 28
#define GMPy_MPC_Dealloc_RETURN void
#define GMPy_MPC_Dealloc_PROTO (MPC_Object *self)
/* The following function is found in gmpy2_convert_gmp. */
#define GMPy_MPC_ConvertArg_NUM 29
#define GMPy_MPC_ConvertArg_RETURN int
#define GMPy_MPC_ConvertArg_PROTO (PyObject *arg, PyObject **ptr)
/* Total number of C-API pointers. */
#define GMPy_API_pointers 30
/* End of C-API definitions. */
#ifdef GMPY2_MODULE
#define PyString_1Char(obj) (PyUnicode_READY(obj) ? (Py_UCS4)0 : PyUnicode_READ_CHAR(obj, 0))
#define PyStrOrUnicode_Check(op) (PyBytes_Check(op) || PyUnicode_Check(op))
#ifndef ABS
# define ABS(a) (((a) < 0) ? -(a) : (a))
#endif
#if defined(MS_WIN32) && defined(_MSC_VER)
/* so one won't need to link explicitly to gmp.lib...: */
# pragma comment(lib,"gmp.lib")
# define USE_ALLOCA 1
# define inline __inline
#endif
#ifdef __GNUC__
# define USE_ALLOCA 1
#endif
#ifndef alloca
# ifdef __GNUC__
# define alloca __builtin_alloca
# else
# ifdef _MSC_VER
# include
# define alloca _alloca
# else
# if HAVE_ALLOCA_H
# include
# else
char *alloca ();
# endif
# endif
# endif
#endif
#define ALLOC_THRESHOLD 8192
#define INDEX_ERROR(msg) PyErr_SetString(PyExc_IndexError, msg)
#define TYPE_ERROR(msg) PyErr_SetString(PyExc_TypeError, msg)
#define VALUE_ERROR(msg) PyErr_SetString(PyExc_ValueError, msg)
#define ZERO_ERROR(msg) PyErr_SetString(PyExc_ZeroDivisionError, msg)
#define SYSTEM_ERROR(msg) PyErr_SetString(PyExc_SystemError, msg)
#define OVERFLOW_ERROR(msg) PyErr_SetString(PyExc_OverflowError, msg)
#define RUNTIME_ERROR(msg) PyErr_SetString(PyExc_RuntimeError, msg)
#define GMPY_DEFAULT -1
/* To prevent excessive memory usage, we don't want to save very large
* numbers in the cache. The default value specified in the options
* structure is 128 words (512 bytes on 32-bit platforms, 1024 bytes on
* 64-bit platforms).
*/
#define MAX_CACHE_LIMBS 16384
/* The maximum number of objects that can be saved in a cache is specified
* here. The default value is 100.*/
#define MAX_CACHE 1000
#ifdef USE_ALLOCA
# define TEMP_ALLOC(B, S) \
if(S < ALLOC_THRESHOLD) { \
B = alloca(S); \
} else { \
if(!(B = malloc(S))) { \
PyErr_NoMemory(); \
return NULL; \
} \
}
# define TEMP_FREE(B, S) if(S >= ALLOC_THRESHOLD) free(B)
#else
# define TEMP_ALLOC(B, S) \
if(!(B = malloc(S))) { \
PyErr_NoMemory(); \
return NULL; \
}
# define TEMP_FREE(B, S) free(B)
#endif
#ifndef Py_SIZE
# define Py_SIZE(ob) (((PyVarObject*)(ob))->ob_size)
#endif
#ifndef Py_TYPE
# define Py_TYPE(ob) (((PyObject*)(ob))->ob_type)
#endif
/* Import a collection of general purpose macros. */
#include "gmpy2_macros.h"
/* Import the files that complete the definition of the types defined above. */
#include "gmpy2_mpz.h"
#include "gmpy2_xmpz.h"
#include "gmpy2_mpq.h"
#include "gmpy2_mpfr.h"
#include "gmpy2_mpc.h"
#include "gmpy2_context.h"
#include "gmpy2_random.h"
/* Import the header files that provide the various functions. */
/* Support object caching, creation, and deletion. */
#include "gmpy2_cache.h"
/* Suport for miscellaneous functions (ie. version, license, etc.). */
#include "gmpy2_misc.h"
/* Support conversion to/from binary format. */
#include "gmpy2_binary.h"
/* Support for mpz/xmpz specific functions. */
#include "gmpy2_convert.h"
#include "gmpy2_convert_utils.h"
#include "gmpy2_convert_gmp.h"
#include "gmpy2_convert_mpfr.h"
#include "gmpy2_convert_mpc.h"
#include "gmpy2_mpz_divmod.h"
#include "gmpy2_mpz_divmod2exp.h"
#include "gmpy2_mpz_pack.h"
#include "gmpy2_mpz_bitops.h"
#include "gmpy2_mpz_misc.h"
#include "gmpy2_xmpz_inplace.h"
#include "gmpy2_xmpz_misc.h"
#include "gmpy2_xmpz_limbs.h"
/* Support for mpq specific functions. */
#include "gmpy2_mpq_misc.h"
/* Support for mpfr specific functions. */
#include "gmpy2_mpfr_misc.h"
/* Support for mpc specific functions. */
#include "gmpy2_mpc_misc.h"
/* Support Lucas sequences. */
#include "gmpy_mpz_lucas.h"
/* Support probable-prime tests. */
#include "gmpy_mpz_prp.h"
/* Support higher-level Python methods and functions; generally not
* specific to a single type.
*/
#include "gmpy2_abs.h"
#include "gmpy2_add.h"
#include "gmpy2_divmod.h"
#include "gmpy2_floordiv.h"
#include "gmpy2_minus.h"
#include "gmpy2_mod.h"
#include "gmpy2_mul.h"
#include "gmpy2_plus.h"
#include "gmpy2_pow.h"
#include "gmpy2_sub.h"
#include "gmpy2_truediv.h"
#include "gmpy2_math.h"
#include "gmpy2_const.h"
#include "gmpy2_square.h"
#include "gmpy2_format.h"
#include "gmpy2_hash.h"
#include "gmpy2_fused.h"
#include "gmpy2_muldiv_2exp.h"
#include "gmpy2_predicate.h"
#include "gmpy2_sign.h"
#include "gmpy2_richcompare.h"
#include "gmpy2_cmp.h"
#ifdef VECTOR
# include "gmpy2_vector.h"
#endif /* defined(VECTOR) */
#else /* defined(GMPY2_MODULE) */
/* This section is used for other C-coded modules that use gmpy2's API. */
static void **GMPy_C_API;
#define MPZ_Check(op) ((op)->ob_type == (PyTypeObject*)GMPy_C_API[MPZ_Type_NUM])
#define XMPZ_Check(op) ((op)->ob_type == (PyTypeObject*)GMPy_C_API[XMPZ_Type_NUM])
#define MPQ_Check(op) ((op)->ob_type == (PyTypeObject*)GMPy_C_API[MPQ_Type_NUM])
#define XMPQ_Check(op) ((op)->ob_type == (PyTypeObject*)GMPy_C_API[XMPQ_Type_NUM])
#define MPFR_Check(op) ((op)->ob_type == (PyTypeObject*)GMPy_C_API[MPFR_Type_NUM])
#define XMPFR_Check(op) ((op)->ob_type == (PyTypeObject*)GMPy_C_API[XMPFR_Type_NUM])
#define MPC_Check(op) ((op)->ob_type == (PyTypeObject*)GMPy_C_API[MPC_Type_NUM])
#define XMPC_Check(op) ((op)->ob_type == (PyTypeObject*)GMPy_C_API[XMPC_Type_NUM])
#define GMPy_MPZ_New (*(GMPy_MPZ_New_RETURN (*)GMPy_MPZ_New_PROTO) GMPy_C_API[GMPy_MPZ_New_NUM])
#define GMPy_MPZ_NewInit (*(GMPy_MPZ_NewInit_RETURN (*)GMPy_MPZ_NewInit_PROTO) GMPy_C_API[GMPy_MPZ_NewInit_NUM])
#define GMPy_MPZ_Dealloc (*(GMPy_MPZ_Dealloc_RETURN (*)GMPy_MPZ_Dealloc_PROTO) GMPy_C_API[GMPy_MPZ_Dealloc_NUM])
#define GMPy_MPZ_ConvertArg (*(GMPy_MPZ_ConvertArg_RETURN (*)GMPy_MPZ_ConvertArg_PROTO) GMPy_C_API[GMPy_MPZ_ConvertArg_NUM])
#define GMPy_XMPZ_New (*(GMPy_XMPZ_New_RETURN (*)GMPy_XMPZ_New_PROTO) GMPy_C_API[GMPy_XMPZ_New_NUM])
#define GMPy_XMPZ_NewInit (*(GMPy_XMPZ_NewInit_RETURN (*)GMPy_XMPZ_NewInit_PROTO) GMPy_C_API[GMPy_XMPZ_NewInit_NUM])
#define GMPy_XMPZ_Dealloc (*(GMPy_XMPZ_Dealloc_RETURN (*)GMPy_XMPZ_Dealloc_PROTO) GMPy_C_API[GMPy_XMPZ_Dealloc_NUM])
#define GMPy_MPQ_New (*(GMPy_MPQ_New_RETURN (*)GMPy_MPQ_New_PROTO) GMPy_C_API[GMPy_MPQ_New_NUM])
#define GMPy_MPQ_NewInit (*(GMPy_MPQ_NewInit_RETURN (*)GMPy_MPQ_NewInit_PROTO) GMPy_C_API[GMPy_MPQ_NewInit_NUM])
#define GMPy_MPQ_Dealloc (*(GMPy_MPQ_Dealloc_RETURN (*)GMPy_MPQ_Dealloc_PROTO) GMPy_C_API[GMPy_MPQ_Dealloc_NUM])
#define GMPy_MPQ_ConvertArg (*(GMPy_MPQ_ConvertArg_RETURN (*)GMPy_MPQ_ConvertArg_PROTO) GMPy_C_API[GMPy_MPQ_ConvertArg_NUM])
#define GMPy_MPFR_New (*(GMPy_MPFR_New_RETURN (*)GMPy_MPFR_New_PROTO) GMPy_C_API[GMPy_MPFR_New_NUM])
#define GMPy_MPFR_NewInit (*(GMPy_MPFR_NewInit_RETURN (*)GMPy_MPFR_NewInit_PROTO) GMPy_C_API[GMPy_MPFR_NewInit_NUM])
#define GMPy_MPFR_Dealloc (*(GMPy_MPFR_Dealloc_RETURN (*)GMPy_MPFR_Dealloc_PROTO) GMPy_C_API[GMPy_MPFR_Dealloc_NUM])
#define GMPy_MPFR_ConvertArg (*(GMPy_MPFR_ConvertArg_RETURN (*)GMPy_MPFR_ConvertArg_PROTO) GMPy_C_API[GMPy_MPFR_ConvertArg_NUM])
#define GMPy_MPC_New (*(GMPy_MPC_New_RETURN (*)GMPy_MPC_New_PROTO) GMPy_C_API[GMPy_MPC_New_NUM])
#define GMPy_MPC_NewInit (*(GMPy_MPC_NewInit_RETURN (*)GMPy_MPC_NewInit_PROTO) GMPy_C_API[GMPy_MPC_NewInit_NUM])
#define GMPy_MPC_Dealloc (*(GMPy_MPC_Dealloc_RETURN (*)GMPy_MPC_Dealloc_PROTO) GMPy_C_API[GMPy_MPC_Dealloc_NUM])
#define GMPy_MPC_ConvertArg (*(GMPy_MPC_ConvertArg_RETURN (*)GMPy_MPC_ConvertArg_PROTO) GMPy_C_API[GMPy_MPC_ConvertArg_NUM])
static int
import_gmpy2(void)
{
GMPy_C_API = (void **)PyCapsule_Import("gmpy2._C_API", 0);
return (GMPy_C_API != NULL) ? 0 : -1;
}
#endif /* defined(GMPY2_MODULE) */
#ifdef __cplusplus
}
#endif /* defined(__cplusplus */
#endif /* !defined(Py_GMPYMODULE_H */
././@PaxHeader 0000000 0000000 0000000 00000000026 00000000000 010213 x ustar 00 22 mtime=1710307256.0
gmpy2-2.2.1/src/gmpy2.pxd 0000644 0001750 0001750 00000011111 14574233670 013572 0 ustar 00case case cdef extern from "gmp.h":
# gmp integers
ctypedef long mp_limb_t
ctypedef struct __mpz_struct:
int _mp_alloc
int _mp_size
mp_limb_t* _mp_d
ctypedef __mpz_struct mpz_t[1]
ctypedef __mpz_struct *mpz_ptr
ctypedef const __mpz_struct *mpz_srcptr
# gmp rationals
ctypedef struct __mpq_struct:
__mpz_struct _mp_num
__mpz_struct _mp_den
ctypedef __mpq_struct mpq_t[1]
ctypedef __mpq_struct *mpq_ptr
ctypedef const __mpq_struct *mpq_srcptr
void mpz_set(mpz_t rop, mpz_t op)
void mpq_set(mpq_ptr rop, mpq_srcptr op)
void mpq_set_num(mpq_t rational, mpz_t numerator)
void mpq_set_den(mpq_t rational, mpz_t denominator)
cdef extern from "mpfr.h":
# mpfr reals
ctypedef int mpfr_sign_t
ctypedef long mpfr_prec_t
ctypedef long mpfr_exp_t
ctypedef struct __mpfr_struct:
mpfr_prec_t _mpfr_prec
mpfr_sign_t _mpfr_sign
mpfr_exp_t _mpfr_exp
mp_limb_t* _mpfr_d
ctypedef __mpfr_struct mpfr_t[1]
ctypedef __mpfr_struct *mpfr_ptr
ctypedef const __mpfr_struct *mpfr_srcptr
ctypedef enum mpfr_rnd_t:
MPFR_RNDN
MPFR_RNDZ
MPFR_RNDU
MPFR_RNDD
MPFR_RNDA
MPFR_RNDF
MPFR_RNDNA
mpfr_prec_t mpfr_get_prec(mpfr_t x)
int mpfr_set(mpfr_t rop, mpfr_t op, mpfr_rnd_t rnd)
cdef extern from "mpc.h":
# mpc complexes
ctypedef struct __mpc_struct:
mpfr_t re
mpfr_t im
ctypedef __mpc_struct mpc_t[1];
ctypedef __mpc_struct *mpc_ptr;
ctypedef const __mpc_struct *mpc_srcptr;
ctypedef enum mpc_rnd_t:
MPC_RNDNN
MPC_RNDNZ
MPC_RNDNU
MPC_RNDND
MPC_RNDZN
MPC_RNDZZ
MPC_RNDZU
MPC_RNDZD
MPC_RNDUN
MPC_RNDUZ
MPC_RNDUU
MPC_RNDUD
MPC_RNDDN
MPC_RNDDZ
MPC_RNDDU
MPC_RNDDD
mpfr_prec_t mpc_get_prec(mpc_srcptr x)
void mpc_get_prec2(mpfr_prec_t *pr, mpfr_prec_t *pi, mpc_srcptr x)
int mpc_set(mpc_ptr rop, mpc_srcptr op, mpc_rnd_t rnd)
int mpc_set_fr_fr(mpc_ptr rop, mpfr_srcptr rp, mpfr_srcptr ip, mpc_rnd_t rnd)
cdef extern from "gmpy2.h":
# Initialize the C-API
# This must be called before any other functions, but not to access
# the types.
cdef int import_gmpy2() except -1
# Object types
ctypedef class gmpy2.mpz [object MPZ_Object]:
cdef mpz_t z
ctypedef class gmpy2.mpq [object MPQ_Object]:
cdef mpq_t q
ctypedef class gmpy2.mpfr [object MPFR_Object]:
cdef mpfr_t f
cdef int rc
ctypedef class gmpy2.mpc [object MPC_Object]:
cdef mpc_t c
cdef int rc
# Object creation
cdef mpz GMPy_MPZ_New(void *)
cdef mpq GMPy_MPQ_New(void *)
cdef mpfr GMPy_MPFR_New(mpfr_prec_t prec, void *)
cdef mpc GMPy_MPC_New(mpfr_prec_t rprec, mpfr_prec_t iprec, void *)
# C field access
cdef mpz_t MPZ(mpz)
cdef mpq_t MPQ(mpq)
cdef mpfr_t MPFR(mpfr)
cdef mpc_t MPC(mpc)
# Type check
cdef bint MPZ_Check(object)
cdef bint MPQ_Check(object)
cdef bint MPFR_Check(object)
cdef bint MPC_Check(object)
# Build a gmpy2 mpz from a gmp mpz
cdef inline mpz GMPy_MPZ_From_mpz(mpz_srcptr z):
cdef mpz res = GMPy_MPZ_New(NULL)
mpz_set(res.z, z)
return res
# Build a gmpy2 mpq from a gmp mpq
cdef inline mpq GMPy_MPQ_From_mpq(mpq_srcptr q):
cdef mpq res = GMPy_MPQ_New(NULL)
mpq_set(res.q, q)
return res
# Build a gmpy2 mpq from gmp mpz numerator and denominator
cdef inline mpq GMPy_MPQ_From_mpz(mpz_srcptr num, mpz_srcptr den):
cdef mpq res = GMPy_MPQ_New(NULL)
mpq_set_num(res.q, num)
mpq_set_den(res.q, den)
return res
# Build a gmpy2 mpfr from a mpfr
cdef inline mpfr GMPy_MPFR_From_mpfr(mpfr_srcptr x):
cdef mpfr res = GMPy_MPFR_New(mpfr_get_prec(x), NULL)
mpfr_set(res.f, x, MPFR_RNDN)
return res
# Build a gmpy2 mpc from a mpc
cdef inline mpc GMPy_MPC_From_mpc(mpc_srcptr c):
cdef mpfr_prec_t pr
cdef mpfr_prec_t pi
mpc_get_prec2(&pr, &pi, c)
cdef mpc res = GMPy_MPC_New(pr, pi, NULL)
mpc_set(res.c, c, MPC_RNDNN)
return res
# Build a gmpy2 mpc from a real part mpfr and an imaginary part mpfr
cdef inline mpc GMPy_MPC_From_mpfr(mpfr_srcptr re, mpfr_srcptr im):
cdef mpc res = GMPy_MPC_New(mpfr_get_prec(re), mpfr_get_prec(im), NULL)
# We intentionally use MPFR funtions instead of MPC functions here
# in order not to add an unneeded dependency on MPC. It's probably
# faster too this way.
mpfr_set(res.c.re, re, MPFR_RNDN)
mpfr_set(res.c.im, im, MPFR_RNDN)
return res
././@PaxHeader 0000000 0000000 0000000 00000000026 00000000000 010213 x ustar 00 22 mtime=1710307256.0
gmpy2-2.2.1/src/gmpy2_abs.c 0000644 0001750 0001750 00000016144 14574233670 014061 0 ustar 00case case /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* gmpy2_abs.c *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Python interface to the GMP, MPFR, and MPC multiple precision *
* libraries. *
* *
* Copyright 2000 - 2009 Alex Martelli *
* *
* Copyright 2008 - 2024 Case Van Horsen *
* *
* This file is part of GMPY2. *
* *
* GMPY2 is free software: you can redistribute it and/or modify it under *
* the terms of the GNU Lesser General Public License as published by the *
* Free Software Foundation, either version 3 of the License, or (at your *
* option) any later version. *
* *
* GMPY2 is distributed in the hope that it will be useful, but WITHOUT *
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or *
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public *
* License for more details. *
* *
* You should have received a copy of the GNU Lesser General Public *
* License along with GMPY2; if not, see *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
/* This file implements __abs__, gmpy2.abs(), and context.abs().
*
* Public API
* ==========
* The following function is available as part of GMPY2's C API. If the value
* of context is NULL, then the function should use the currently active
* context.
*
* GMPy_Number_Abs(Number, context)
*
* Private API
* ===========
* GMPy_MPZ_Abs_Slot
* GMPy_MPQ_Abs_Slot
* GMPy_MPFR_Abs_Slot
* GMPy_MPC_Abs_Slot
*
* GMPy_Integer_AbsWithType(Integer, xtype, context|NULL)
* GMPy_Rational_AbsWithType(Rational, xtype, context|NULL)
* GMPy_Real_AbsWithType(Real, xtype, context|NULL)
* GMPy_Complex_AbsWithType(Complex, xtype, context|NULL)
*
* GMPy_Context_Abs(context, obj)
*/
static PyObject *
GMPy_Integer_AbsWithType(PyObject *x, int xtype, CTXT_Object *context)
{
MPZ_Object *result = NULL;
if (IS_TYPE_MPZ(xtype)) {
if (mpz_sgn(MPZ(x)) >= 0) {
Py_INCREF(x);
return x;
}
else {
if ((result = GMPy_MPZ_New(context)))
mpz_abs(result->z, MPZ(x));
return (PyObject*)result;
}
}
/* This is safe because result is not an incremented reference to an
* existing value. Why?
* 1) No values are interned like Python's integers.
* 2) MPZ is already handled so GMPy_MPZ_From_IntegerWithType() can't
* return an incremented reference to an existing value (which it
* would do if passed an MPZ).
*/
if ((result = GMPy_MPZ_From_IntegerWithType(x, xtype, context))) {
mpz_abs(result->z, result->z);
}
return (PyObject*)result;
}
static PyObject *
GMPy_MPZ_Abs_Slot(MPZ_Object *x)
{
return GMPy_Integer_AbsWithType((PyObject*)x, OBJ_TYPE_MPZ, NULL);
}
static PyObject *
GMPy_Rational_AbsWithType(PyObject *x, int xtype, CTXT_Object *context)
{
MPQ_Object *result = NULL;
if (IS_TYPE_MPQ(xtype)) {
if (mpz_sgn(mpq_numref(MPQ(x))) >= 0) {
Py_INCREF(x);
return x;
}
else {
if ((result = GMPy_MPQ_New(context))) {
mpq_set(result->q, MPQ(x));
mpz_abs(mpq_numref(result->q), mpq_numref(result->q));
}
return (PyObject*)result;
}
}
/* This is safe because result is not an incremented reference to an
* existing value. MPQ is already handled so GMPy_MPQ_From_Rational()
* can't return an incremented reference to an existing value (which it
* would do if passed an MPQ).
*/
if ((result = GMPy_MPQ_From_RationalWithType(x, xtype, context))) {
mpz_abs(mpq_numref(result->q), mpq_numref(result->q));
}
return (PyObject*)result;
}
static PyObject *
GMPy_MPQ_Abs_Slot(MPQ_Object *x)
{
return GMPy_Rational_AbsWithType((PyObject*)x, OBJ_TYPE_MPQ, NULL);
}
static PyObject *
GMPy_Real_AbsWithType(PyObject *x, int xtype, CTXT_Object *context)
{
MPFR_Object *result = NULL, *tempx = NULL;
CHECK_CONTEXT(context);
if (!(tempx = GMPy_MPFR_From_RealWithType(x, xtype, 1, context)) ||
!(result = GMPy_MPFR_New(0, context))) {
/* LCOV_EXCL_START */
Py_XDECREF((PyObject*)tempx);
Py_XDECREF((PyObject*)result);
return NULL;
/* LCOV_EXCL_STOP */
}
mpfr_clear_flags();
result->rc = mpfr_abs(result->f, tempx->f, GET_MPFR_ROUND(context));
Py_DECREF((PyObject*)tempx);
_GMPy_MPFR_Cleanup(&result, context);
return (PyObject*)result;
}
static PyObject *
GMPy_MPFR_Abs_Slot(MPFR_Object *x)
{
return GMPy_Real_AbsWithType((PyObject*)x, OBJ_TYPE_MPFR, NULL);
}
static PyObject *
GMPy_Complex_AbsWithType(PyObject *x, int xtype, CTXT_Object *context)
{
MPFR_Object *result = NULL;
MPC_Object *tempx = NULL;
CHECK_CONTEXT(context);
if (!(tempx = GMPy_MPC_From_ComplexWithType(x, xtype, 1, 1, context)) ||
!(result = GMPy_MPFR_New(0, context))) {
/* LCOV_EXCL_START */
Py_XDECREF((PyObject*)tempx);
Py_XDECREF((PyObject*)result);
return NULL;
/* LCOV_EXCL_STOP */
}
mpfr_clear_flags();
result->rc = mpc_abs(result->f, tempx->c, GET_MPC_ROUND(context));
Py_DECREF((PyObject*)tempx);
_GMPy_MPFR_Cleanup(&result, context);
return (PyObject*)result;
}
static PyObject *
GMPy_MPC_Abs_Slot(MPC_Object *x)
{
return GMPy_Complex_AbsWithType((PyObject*)x, OBJ_TYPE_MPC, NULL);
}
static PyObject *
GMPy_Number_Abs(PyObject *x, CTXT_Object *context)
{
int xtype = GMPy_ObjectType(x);
if (IS_TYPE_INTEGER(xtype))
return GMPy_Integer_AbsWithType(x, xtype, context);
if (IS_TYPE_RATIONAL(xtype))
return GMPy_Rational_AbsWithType(x, xtype, context);
if (IS_TYPE_REAL(xtype))
return GMPy_Real_AbsWithType(x, xtype, context);
if (IS_TYPE_COMPLEX(xtype))
return GMPy_Complex_AbsWithType(x, xtype, context);
TYPE_ERROR("abs() argument type not supported");
return NULL;
}
/* Implement context.abs(). The following code assumes it used a as method of
* a context. */
PyDoc_STRVAR(GMPy_doc_context_abs,
"context.abs(x, /) -> mpz | mpq | mpfr\n\n"
"Return abs(x), the context is applied to the result.");
static PyObject *
GMPy_Context_Abs(PyObject *self, PyObject *other)
{
return GMPy_Number_Abs(other, (CTXT_Object*)self);
}
././@PaxHeader 0000000 0000000 0000000 00000000026 00000000000 010213 x ustar 00 22 mtime=1710307256.0
gmpy2-2.2.1/src/gmpy2_abs.h 0000644 0001750 0001750 00000005346 14574233670 014070 0 ustar 00case case /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* gmpy2_abs.h *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Python interface to the GMP, MPFR, and MPC multiple precision *
* libraries. *
* *
* Copyright 2000 - 2009 Alex Martelli *
* *
* Copyright 2008 - 2024 Case Van Horsen *
* *
* This file is part of GMPY2. *
* *
* GMPY2 is free software: you can redistribute it and/or modify it under *
* the terms of the GNU Lesser General Public License as published by the *
* Free Software Foundation, either version 3 of the License, or (at your *
* option) any later version. *
* *
* GMPY2 is distributed in the hope that it will be useful, but WITHOUT *
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or *
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public *
* License for more details. *
* *
* You should have received a copy of the GNU Lesser General Public *
* License along with GMPY2; if not, see *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
#ifndef GMPY2_ABS_H
#define GMPY2_ABS_H
#ifdef __cplusplus
extern "C" {
#endif
/* Public API */
static PyObject * GMPy_Number_Abs(PyObject *x, CTXT_Object *context);
/* Private API */
static PyObject * GMPy_Integer_AbsWithType(PyObject *x, int xtype, CTXT_Object *context);
static PyObject * GMPy_Rational_AbsWithType(PyObject *x, int xtype, CTXT_Object *context);
static PyObject * GMPy_Real_AbsWithType(PyObject *x, int xtype, CTXT_Object *context);
static PyObject * GMPy_Complex_AbsWithType(PyObject *x, int xtype, CTXT_Object *context);
static PyObject * GMPy_MPZ_Abs_Slot(MPZ_Object *x);
static PyObject * GMPy_MPQ_Abs_Slot(MPQ_Object *x);
static PyObject * GMPy_MPFR_Abs_Slot(MPFR_Object *x);
static PyObject * GMPy_MPC_Abs_Slot(MPC_Object *x);
static PyObject * GMPy_Context_Abs(PyObject *self, PyObject *args);
#ifdef __cplusplus
}
#endif
#endif
././@PaxHeader 0000000 0000000 0000000 00000000026 00000000000 010213 x ustar 00 22 mtime=1710307256.0
gmpy2-2.2.1/src/gmpy2_add.c 0000644 0001750 0001750 00000030575 14574233670 014050 0 ustar 00case case /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* gmpy2_add.c *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Python interface to the GMP, MPFR, and MPC multiple precision *
* libraries. *
* *
* Copyright 2000 - 2009 Alex Martelli *
* *
* Copyright 2008 - 2024 Case Van Horsen *
* *
* This file is part of GMPY2. *
* *
* GMPY2 is free software: you can redistribute it and/or modify it under *
* the terms of the GNU Lesser General Public License as published by the *
* Free Software Foundation, either version 3 of the License, or (at your *
* option) any later version. *
* *
* GMPY2 is distributed in the hope that it will be useful, but WITHOUT *
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or *
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public *
* License for more details. *
* *
* You should have received a copy of the GNU Lesser General Public *
* License along with GMPY2; if not, see *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
/* This file implements the + operator, gmpy2.add(), and context.add().
*/
/* Add two Integer objects (see gmpy2_convert.h). If an error occurs, NULL
* is returned and an exception is set. If either x or y can't be converted
* into an mpz, a type error is returned.
*/
static PyObject *
GMPy_Integer_AddWithType(PyObject *x, int xtype, PyObject *y, int ytype,
CTXT_Object *context)
{
MPZ_Object *result = NULL;
if (!(result = GMPy_MPZ_New(context))) {
/* LCOV_EXCL_START */
return NULL;
/* LCOV_EXCL_STOP */
}
if (IS_TYPE_MPZANY(xtype)) {
if (IS_TYPE_MPZANY(ytype)) {
GMPY_MAYBE_BEGIN_ALLOW_THREADS(context);
mpz_add(result->z, MPZ(x), MPZ(y));
GMPY_MAYBE_END_ALLOW_THREADS(context);
return (PyObject*)result;
}
if (IS_TYPE_PyInteger(ytype)) {
int error;
long temp = PyLong_AsLongAndOverflow(y, &error);
if (!error) {
if (temp >= 0) {
mpz_add_ui(result->z, MPZ(x), temp);
}
else {
mpz_sub_ui(result->z, MPZ(x), -temp);
}
}
else {
mpz_set_PyLong(result->z, y);
GMPY_MAYBE_BEGIN_ALLOW_THREADS(context);
mpz_add(result->z, MPZ(x), result->z);
GMPY_MAYBE_END_ALLOW_THREADS(context);
}
return (PyObject*)result;
}
}
if (IS_TYPE_MPZANY(ytype)) {
if (IS_TYPE_PyInteger(xtype)) {
int error;
long temp = PyLong_AsLongAndOverflow(x, &error);
if (!error) {
if (temp >= 0) {
mpz_add_ui(result->z, MPZ(y), temp);
}
else {
mpz_sub_ui(result->z, MPZ(y), -temp);
}
}
else {
mpz_set_PyLong(result->z, x);
GMPY_MAYBE_BEGIN_ALLOW_THREADS(context);
mpz_add(result->z, result->z, MPZ(y));
GMPY_MAYBE_END_ALLOW_THREADS(context);
}
return (PyObject*)result;
}
}
if (IS_TYPE_INTEGER(xtype) && (IS_TYPE_INTEGER(ytype))) {
MPZ_Object *tempx = NULL, *tempy = NULL;
if (!(tempx = GMPy_MPZ_From_IntegerWithType(x, xtype, context)) ||
!(tempy = GMPy_MPZ_From_IntegerWithType(y, ytype, context))) {
/* LCOV_EXCL_START */
Py_XDECREF((PyObject*)tempx);
Py_XDECREF((PyObject*)tempy);
Py_DECREF((PyObject*)result);
return NULL;
/* LCOV_EXCL_STOP */
}
GMPY_MAYBE_BEGIN_ALLOW_THREADS(context);
mpz_add(result->z, tempx->z, tempy->z);
GMPY_MAYBE_END_ALLOW_THREADS(context);
Py_DECREF((PyObject*)tempx);
Py_DECREF((PyObject*)tempy);
return (PyObject*)result;
}
/* LCOV_EXCL_START */
Py_DECREF((PyObject*)result);
TYPE_ERROR("add() argument type not supported");
return NULL;
/* LCOV_EXCL_STOP */
}
static PyObject *
GMPy_Rational_AddWithType(PyObject *x, int xtype, PyObject *y, int ytype,
CTXT_Object *context)
{
MPQ_Object *result = NULL;
if (!(result = GMPy_MPQ_New(context))) {
/* LCOV_EXCL_START */
return NULL;
/* LCOV_EXCL_STOP */
}
if (IS_TYPE_MPQ(xtype) && IS_TYPE_MPQ(ytype)) {
GMPY_MAYBE_BEGIN_ALLOW_THREADS(context);
mpq_add(result->q, MPQ(x), MPQ(y));
GMPY_MAYBE_END_ALLOW_THREADS(context);
return (PyObject*)result;
}
if (IS_TYPE_RATIONAL(xtype) && IS_TYPE_RATIONAL(ytype)) {
MPQ_Object *tempx = NULL, *tempy = NULL;
if (!(tempx = GMPy_MPQ_From_RationalWithType(x, xtype, context)) ||
!(tempy = GMPy_MPQ_From_RationalWithType(y, ytype, context))) {
/* LCOV_EXCL_START */
Py_XDECREF((PyObject*)tempx);
Py_XDECREF((PyObject*)tempy);
Py_DECREF((PyObject*)result);
return NULL;
/* LCOV_EXCL_STOP */
}
GMPY_MAYBE_BEGIN_ALLOW_THREADS(context);
mpq_add(result->q, tempx->q, tempy->q);
GMPY_MAYBE_END_ALLOW_THREADS(context);
Py_DECREF((PyObject*)tempx);
Py_DECREF((PyObject*)tempy);
return (PyObject*)result;
}
/* LCOV_EXCL_START */
Py_DECREF((PyObject*)result);
TYPE_ERROR("add() argument type not supported");
return NULL;
/* LCOV_EXCL_STOP */
}
/* Addition can be performed by the equivalent of mpfr.__add__ or by
* gmpy2.add().
*
* GMPy_Real_Add(x, y, context) returns x+y using the provided context. If
* provided context is NULL, then the current context is used. If an error
* occurs, NULL is returned and an exception is set. If either x or y can't
* be converted to an mpfr, then Py_NotImplemented is returned.
* GMPy_Real_Add() will not try to promote the result to a different type
* (i.e. mpc).
*/
/* Attempt to add two numbers and return an mpfr. The code path is optimized by
* checking for mpfr objects first. Returns Py_NotImplemented if both objects
* are not valid reals. */
static PyObject *
GMPy_Real_AddWithType(PyObject *x, int xtype, PyObject *y, int ytype,
CTXT_Object *context)
{
MPFR_Object *result = NULL;
if (!(result = GMPy_MPFR_New(0, context))) {
/* LCOV_EXCL_START */
return NULL;
/* LCOV_EXCL_STOP */
}
if (IS_TYPE_MPFR(xtype) && IS_TYPE_MPFR(ytype)) {
mpfr_clear_flags();
result->rc = mpfr_add(result->f, MPFR(x), MPFR(y), GET_MPFR_ROUND(context));
_GMPy_MPFR_Cleanup(&result, context);
return (PyObject*)result;
}
if (IS_TYPE_REAL(xtype) && IS_TYPE_REAL(ytype)) {
MPFR_Object *tempx = NULL, *tempy = NULL;
if (!(tempx = GMPy_MPFR_From_RealWithType(x, xtype, 1, context)) ||
!(tempy = GMPy_MPFR_From_RealWithType(y, ytype, 1, context))) {
/* LCOV_EXCL_START */
Py_XDECREF((PyObject*)tempx);
Py_XDECREF((PyObject*)tempy);
Py_DECREF((PyObject*)result);
return NULL;
/* LCOV_EXCL_STOP */
}
mpfr_clear_flags();
result->rc = mpfr_add(result->f, MPFR(tempx), MPFR(tempy), GET_MPFR_ROUND(context));
Py_DECREF((PyObject*)tempx);
Py_DECREF((PyObject*)tempy);
_GMPy_MPFR_Cleanup(&result, context);
return (PyObject*)result;
}
/* LCOV_EXCL_START */
Py_DECREF((PyObject*)result);
TYPE_ERROR("add() argument type not supported");
return NULL;
/* LCOV_EXCL_STOP */
}
/* GMPy_Complex_Add(x, y, context) returns x+y using the provided context. If
* context is NULL, then the current context is used. If an error occurs, NULL
* is returned and an exception is set. If either x or y can't be converted to
* an mpc, then Py_NotImplemented is returned. */
static PyObject *
GMPy_Complex_AddWithType(PyObject *x, int xtype, PyObject *y, int ytype,
CTXT_Object *context)
{
MPC_Object *result = NULL;
if (!(result = GMPy_MPC_New(0, 0, context))) {
/* LCOV_EXCL_START */
return NULL;
/* LCOV_EXCL_STOP */
}
if (IS_TYPE_MPC(xtype) && IS_TYPE_MPC(ytype)) {
result->rc = mpc_add(result->c, MPC(x), MPC(y), GET_MPC_ROUND(context));
_GMPy_MPC_Cleanup(&result, context);
return (PyObject*)result;
}
if (IS_TYPE_COMPLEX(xtype) && IS_TYPE_COMPLEX(ytype)) {
MPC_Object *tempx = NULL, *tempy = NULL;
if (!(tempx = GMPy_MPC_From_ComplexWithType(x, xtype, 1, 1, context)) ||
!(tempy = GMPy_MPC_From_ComplexWithType(y, ytype, 1, 1, context))) {
/* LCOV_EXCL_START */
Py_XDECREF((PyObject*)tempx);
Py_XDECREF((PyObject*)tempy);
Py_DECREF((PyObject*)result);
return NULL;
/* LCOV_EXCL_STOP */
}
result->rc = mpc_add(result->c, tempx->c, tempy->c, GET_MPC_ROUND(context));
Py_DECREF((PyObject*)tempx);
Py_DECREF((PyObject*)tempy);
_GMPy_MPC_Cleanup(&result, context);
return (PyObject*)result;
}
/* LCOV_EXCL_START */
Py_DECREF((PyObject*)result);
TYPE_ERROR("add() argument type not supported");
return NULL;
/* LCOV_EXCL_STOP */
}
/* Implement all the slot methods here. */
static PyObject *
GMPy_Number_Add_Slot(PyObject *x, PyObject *y)
{
CTXT_Object *context = NULL;
CHECK_CONTEXT(context);
int xtype = GMPy_ObjectType(x);
int ytype = GMPy_ObjectType(y);
if (IS_TYPE_INTEGER(xtype) && IS_TYPE_INTEGER(ytype))
return GMPy_Integer_AddWithType(x, xtype, y, ytype, context);
if (IS_TYPE_RATIONAL(xtype) && IS_TYPE_RATIONAL(ytype))
return GMPy_Rational_AddWithType(x, xtype, y, ytype, context);
if (IS_TYPE_REAL(xtype) && IS_TYPE_REAL(ytype))
return GMPy_Real_AddWithType(x, xtype, y, ytype, context);
if (IS_TYPE_COMPLEX(xtype) && IS_TYPE_COMPLEX(ytype))
return GMPy_Complex_AddWithType(x, xtype, y, ytype, context);
Py_RETURN_NOTIMPLEMENTED;
}
/* Implement context.add() and gmpy2.add(). */
PyDoc_STRVAR(GMPy_doc_function_add,
"add(x, y, /) -> mpz | mpq | mpfr | mpc\n\n"
"Return x + y.");
static PyObject *
GMPy_Number_Add(PyObject *x, PyObject *y, CTXT_Object *context)
{
int xtype = GMPy_ObjectType(x);
int ytype = GMPy_ObjectType(y);
if (IS_TYPE_INTEGER(xtype) && IS_TYPE_INTEGER(ytype))
return GMPy_Integer_AddWithType(x, xtype, y, ytype, context);
if (IS_TYPE_RATIONAL(xtype) && IS_TYPE_RATIONAL(ytype))
return GMPy_Rational_AddWithType(x, xtype, y, ytype, context);
if (IS_TYPE_REAL(xtype) && IS_TYPE_REAL(ytype))
return GMPy_Real_AddWithType(x, xtype, y, ytype, context);
if (IS_TYPE_COMPLEX(xtype) && IS_TYPE_COMPLEX(ytype))
return GMPy_Complex_AddWithType(x, xtype, y, ytype, context);
TYPE_ERROR("add() argument type not supported");
return NULL;
}
PyDoc_STRVAR(GMPy_doc_context_add,
"context.add(x, y, /) -> mpz | mpq | mpfr | mpc\n\n"
"Return x + y.");
static PyObject *
GMPy_Context_Add(PyObject *self, PyObject *args)
{
CTXT_Object *context = NULL;
if (PyTuple_GET_SIZE(args) != 2) {
TYPE_ERROR("add() requires 2 arguments");
return NULL;
}
if (self && CTXT_Check(self)) {
context = (CTXT_Object*)self;
}
else {
CHECK_CONTEXT(context);
}
return GMPy_Number_Add(PyTuple_GET_ITEM(args, 0),
PyTuple_GET_ITEM(args, 1),
context);
}
././@PaxHeader 0000000 0000000 0000000 00000000026 00000000000 010213 x ustar 00 22 mtime=1710307256.0
gmpy2-2.2.1/src/gmpy2_add.h 0000644 0001750 0001750 00000005301 14574233670 014042 0 ustar 00case case /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* gmpy2_add.h *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Python interface to the GMP, MPFR, and MPC multiple precision *
* libraries. *
* *
* Copyright 2000 - 2009 Alex Martelli *
* *
* Copyright 2008 - 2024 Case Van Horsen *
* *
* This file is part of GMPY2. *
* *
* GMPY2 is free software: you can redistribute it and/or modify it under *
* the terms of the GNU Lesser General Public License as published by the *
* Free Software Foundation, either version 3 of the License, or (at your *
* option) any later version. *
* *
* GMPY2 is distributed in the hope that it will be useful, but WITHOUT *
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or *
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public *
* License for more details. *
* *
* You should have received a copy of the GNU Lesser General Public *
* License along with GMPY2; if not, see *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
#ifndef GMPY2_ADD_H
#define GMPY2_ADD_H
#ifdef __cplusplus
extern "C" {
#endif
/* Public API */
static PyObject * GMPy_Number_Add(PyObject *x, PyObject *y, CTXT_Object *context);
/* Private API */
static PyObject * GMPy_Integer_AddWithType(PyObject *x, int xtype, PyObject *y, int ytype, CTXT_Object *context);
static PyObject * GMPy_Rational_AddWithType(PyObject *x, int xtype, PyObject *y, int ytype, CTXT_Object *context);
static PyObject * GMPy_Real_AddWithType(PyObject *x, int xtype, PyObject *y, int ytype, CTXT_Object *context);
static PyObject * GMPy_Complex_AddWithType(PyObject *x, int xtype, PyObject *y, int ytype, CTXT_Object *context);
static PyObject * GMPy_Number_Add_Slot(PyObject *x, PyObject *y);
static PyObject * GMPy_Context_Add(PyObject *self, PyObject *args);
#ifdef __cplusplus
}
#endif
#endif
././@PaxHeader 0000000 0000000 0000000 00000000026 00000000000 010213 x ustar 00 22 mtime=1710307256.0
gmpy2-2.2.1/src/gmpy2_binary.c 0000644 0001750 0001750 00000122055 14574233670 014577 0 ustar 00case case /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* gmpy2_binary.c *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Python interface to the GMP, MPFR, and MPC multiple precision *
* libraries. *
* *
* Copyright 2000 - 2009 Alex Martelli *
* *
* Copyright 2008 - 2024 Case Van Horsen *
* *
* This file is part of GMPY2. *
* *
* GMPY2 is free software: you can redistribute it and/or modify it under *
* the terms of the GNU Lesser General Public License as published by the *
* Free Software Foundation, either version 3 of the License, or (at your *
* option) any later version. *
* *
* GMPY2 is distributed in the hope that it will be useful, but WITHOUT *
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or *
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public *
* License for more details. *
* *
* You should have received a copy of the GNU Lesser General Public *
* License along with GMPY2; if not, see *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
/* Conversion routines between GMPY2 objects and a compact, portable
* binary representation. The binary format of GMPY2 is not compatible
* with GMPY 1.x. Methods to read the old format are provided.
*/
/* Provide functions to access the old binary formats. */
PyDoc_STRVAR(doc_mpz_from_old_binary,
"mpz_from_old_binary(string, /) -> mpz\n\n"
"Return an 'mpz' from a GMPY 1.x binary format.");
static PyObject *
GMPy_MPZ_From_Old_Binary(PyObject *self, PyObject *other)
{
unsigned char *cp;
Py_ssize_t len;
int negative = 0;
MPZ_Object *result;
if (!(PyBytes_Check(other))) {
TYPE_ERROR("mpz_from_old_binary() requires bytes argument");
return NULL;
}
if (!(result = GMPy_MPZ_New(NULL))) {
/* LCOV_EXCL_START */
return NULL;
/* LCOV_EXCL_STOP */
}
len = PyBytes_Size(other);
cp = (unsigned char*)PyBytes_AsString(other);
if (cp[len-1] == 0xFF) {
negative = 1;
--len;
}
mpz_import(result->z, len, -1, sizeof(char), 0, 0, cp);
if (negative)
mpz_neg(result->z, result->z);
return (PyObject*)result;
}
PyDoc_STRVAR(doc_mpq_from_old_binary,
"mpq_from_old_binary(string, /) -> mpq\n\n"
"Return an 'mpq' from a GMPY 1.x binary format.");
static PyObject *
GMPy_MPQ_From_Old_Binary(PyObject *self, PyObject *other)
{
unsigned char *cp;
Py_ssize_t len;
int topper, negative, numlen;
mpz_t numerator, denominator;
MPQ_Object *result;
if (!(PyBytes_Check(other))) {
TYPE_ERROR("mpq_from_old_binary() requires bytes argument");
return NULL;
}
if (!(result = GMPy_MPQ_New(NULL))) {
/* LCOV_EXCL_START */
return NULL;
/* LCOV_EXCL_STOP */
}
len = PyBytes_Size(other);
cp = (unsigned char*)PyBytes_AsString(other);
if (len < 6) {
VALUE_ERROR("invalid mpq binary (too short)");
Py_DECREF((PyObject*)result);
return NULL;
}
topper = cp[3] & 0x7f;
negative = cp[3] & 0x80;
numlen = cp[0] + 256 * (cp[1] + 256 * (cp[2] + 256 * topper));
if (len < (4 + numlen + 1)) {
VALUE_ERROR("invalid mpq binary (num len)");
Py_DECREF((PyObject*)result);
return NULL;
}
mpz_init(numerator);
mpz_init(denominator);
mpz_import(numerator, numlen, -1, sizeof(char), 0, 0, cp+4);
mpz_import(denominator, len-4-numlen, -1, sizeof(char), 0, 0, cp+4+numlen);
if (negative)
mpz_neg(numerator, numerator);
mpq_set_num(result->q, numerator);
mpq_set_den(result->q, denominator);
mpq_canonicalize(result->q);
mpz_clear(numerator);
mpz_clear(denominator);
return (PyObject*)result;
}
PyDoc_STRVAR(doc_mpfr_from_old_binary,
"mpfr_from_old_binary(string, /) -> mpfr\n\n"
"Return an `mpfr` from a GMPY 1.x binary mpf format.");
static PyObject *
GMPy_MPFR_From_Old_Binary(PyObject *self, PyObject *other)
{
unsigned char *cp;
Py_ssize_t len;
MPFR_Object *result;
mpfr_t digit;
mpfr_prec_t prec;
int i, codebyte, resusign, exposign, resuzero, precilen;
unsigned int expomag = 0;
CTXT_Object *context = NULL;
CHECK_CONTEXT(context);
if (!(PyBytes_Check(other))) {
TYPE_ERROR("mpfr_from_old_binary() requires bytes argument");
return NULL;
}
len = PyBytes_Size(other);
cp = (unsigned char*)PyBytes_AsString(other);
if (len == 1) {
prec = 0;
}
else {
prec = (mpfr_prec_t)(8 * (len - 5));
if ((len>=5) && (cp[0]&8)) {
prec = 0;
for (i=4; i>0; --i) {
prec = (prec << 8) | cp[i];
}
}
}
/*
* binary format for MP floats: first, a code-byte, then, a LSB
* 4-byte unsigned int (exponent magnitude), then the "mantissa"
* (actually, "significand", but "mantissa" is the usual term...)
* in MSB form.
*
* The codebyte encodes both the signs, exponent and result, or
* also the zeroness of the result (in which case, nothing more).
*/
codebyte = cp[0];
resusign = codebyte & 1;
exposign = codebyte & 2;
resuzero = codebyte & 4;
precilen = (codebyte & 8)?4:0;
/* mpfr zero has a very compact (1-byte) binary encoding!-) */
if (resuzero) {
if (!(result = GMPy_MPFR_New(prec, context))) {
/* LCOV_EXCL_START */
return NULL;
/* LCOV_EXCL_STOP */
}
result->rc = mpfr_set_ui(result->f, 0, MPFR_RNDN);
return (PyObject*)result;
}
/* all other numbers are 6+ bytes: codebyte, 4-byte exp, 1+
* bytes for the mantissa; check this string is 6+ bytes
*/
if (len < 6 + precilen) {
VALUE_ERROR("invalid mpf binary encoding (too short)");
return NULL;
}
if (!(result = GMPy_MPFR_New(prec, context))) {
/* LCOV_EXCL_START */
return NULL;
/* LCOV_EXCL_STOP */
}
/* reconstruct exponent */
for (i = 4 + precilen; i > precilen; --i) {
expomag = (expomag<<8) | cp[i];
}
/* reconstruct 'mantissa' (significand) */
mpfr_set_si(result->f, 0, MPFR_RNDN);
mpfr_init2(digit, prec);
for (i = 5 + precilen; ictx.mpfr_round);
mpfr_add(result->f, result->f, digit, MPFR_RNDN);
}
mpfr_clear(digit);
/* apply exponent, with its appropriate sign */
if (exposign)
mpfr_div_2ui(result->f, result->f, 8*expomag, MPFR_RNDN);
else
mpfr_mul_2ui(result->f, result->f, 8*expomag, MPFR_RNDN);
/* apply significand-sign (sign of the overall number) */
if (resusign)
mpfr_neg(result->f, result->f, MPFR_RNDN);
return (PyObject*)result;
}
/* Format of the binary representation of an mpz/xmpz.
*
* byte[0]: 1 => mpz
* 2 => xmpz
* 3 => mpq (see Pympq_To_Binary)
* 4 => mpfr (see Pympfr_To_Binary)
* 5 => mpc (see Pympc_To_Binary)
* byte[1:0-1]: 0 => value is 0
* 1 => value is > 0
* 2 => value is < 0
* 3 => unassigned
* byte[2]+: value
*/
static PyObject *
GMPy_MPZ_To_Binary(MPZ_Object *self)
{
size_t size = 2;
int sgn;
char *buffer;
PyObject *result;
sgn = mpz_sgn(self->z);
if (sgn == 0) {
TEMP_ALLOC(buffer, size);
buffer[0] = 0x01;
buffer[1] = 0x00;
goto done;
}
size = ((mpz_sizeinbase(self->z, 2) + 7) / 8) + 2;
TEMP_ALLOC(buffer, size);
buffer[0] = 0x01;
if (sgn > 0)
buffer[1] = 0x01;
else
buffer[1] = 0x02;
mpz_export(buffer+2, NULL, -1, sizeof(char), 0, 0, self->z);
done:
result = PyBytes_FromStringAndSize(buffer, size);
TEMP_FREE(buffer, size);
return result;
}
static PyObject *
GMPy_XMPZ_To_Binary(XMPZ_Object *self)
{
size_t size = 2;
int sgn;
char *buffer;
PyObject *result;
sgn = mpz_sgn(self->z);
if (sgn == 0) {
TEMP_ALLOC(buffer, size);
buffer[0] = 0x02;
buffer[1] = 0x00;
goto done;
}
size = ((mpz_sizeinbase(self->z, 2) + 7) / 8) + 2;
TEMP_ALLOC(buffer, size);
buffer[0] = 0x02;
if (sgn > 0)
buffer[1] = 0x01;
else
buffer[1] = 0x02;
mpz_export(buffer+2, NULL, -1, sizeof(char), 0, 0, self->z);
done:
result = PyBytes_FromStringAndSize(buffer, size);
TEMP_FREE(buffer, size);
return result;
}
/* Format of the binary representation of an mpq.
*
* byte[0]: 1 => mpz (see Pympz_To_Binary)
* 2 => xmpz (see Pyxmpz_To_Binary)
* 3 => mpq
* 4 => mpfr (see Pympfr_To_Binary)
* 5 => mpc (see Pympc_To_Binary)
* byte[1:0-1]: 0 => value is 0
* 1 => value is > 0
* 2 => value is < 0
* 3 => unassigned
* byte[1:2-2]: 0 => 32-bit length (n=4)
* 1 => 64-bit length (n=8)
* byte[2+]: numerator length, using either 4 or 8 bytes
* byte[2+n]+: numerator, followed by denominator
*/
static PyObject *
GMPy_MPQ_To_Binary(MPQ_Object *self)
{
size_t sizenum, sizeden, sizesize = 4, size = 2, sizetemp, i;
size_t count = 0;
int sgn;
char *buffer, large = 0x00;
PyObject *result = 0;
sgn = mpq_sgn(self->q);
if (sgn == 0) {
TEMP_ALLOC(buffer, size);
buffer[0] = 0x03;
buffer[1] = 0x00;
goto done;
}
sizenum = (mpz_sizeinbase(mpq_numref(self->q), 2) + 7) / 8;
sizeden = (mpz_sizeinbase(mpq_denref(self->q), 2) + 7) / 8;
size = sizenum + sizeden + 2;
/* Check if sizenum larger than 32 bits. */
if ((sizenum >> 16) >> 16) {
/* Current versions of GMP do not allow values to be this large. The
* test is left to (possibly) support future versions that support
* larger values.
*/
/* LCOV_EXCL_START */
large = 0x04;
sizesize = 8;
/* LCOV_EXCL_STOP */
}
size += sizesize;
TEMP_ALLOC(buffer, size);
buffer[0] = 0x03;
if (sgn > 0)
buffer[1] = 0x01 | large;
else
buffer[1] = 0x02 | large;
/* Copy sizenum to the buffer. */
sizetemp = sizenum;
for (i=0; i>= 8;
}
mpz_export(buffer+sizesize+2, &count, -1,
sizeof(char), 0, 0, mpq_numref(self->q));
if (count != sizenum) {
/* LCOV_EXCL_START */
SYSTEM_ERROR("internal error in Pympq_To_Binary");
TEMP_FREE(buffer, size);
return NULL;
/* LCOV_EXCL_STOP */
}
count = 0;
mpz_export(buffer+sizenum+sizesize+2, &count, -1,
sizeof(char), 0, 0, mpq_denref(self->q));
if (count != sizeden) {
/* LCOV_EXCL_START */
SYSTEM_ERROR("internal error in Pympq_To_Binary");
TEMP_FREE(buffer, size);
return NULL;
/* LCOV_EXCL_STOP */
}
done:
result = PyBytes_FromStringAndSize(buffer, size);
TEMP_FREE(buffer, size);
return result;
}
/* Format of the binary representation of an mpfr.
*
* byte[0]: 1 => mpz (see Pympz_To_Binary)
* 2 => xmpz (see Pyxmpz_To_Binary)
* 3 => mpq (see Pympq_To_Binary)
* 4 => mpfr
* 5 => mpc (see Pympc_To_Binary)
* byte[1:0]: 0 => value is "special"
* 1 => value is an actual number
* byte[1:1]: 0 => signbit is clear
* 1 => signbit is set
* byte[1:2-2]: 0 => 32-bit lengths (n=4)
* 1 => 64-bit lengths (n=8)
* byte[1:3-4]: 0 => 0 (see signbit)
* 1 => value is NaN
* 2 => value is Inf (see signbit)
* 3 => unassigned
* byte[1:5]: 0 => exponent is positive
* 1 => exponent is negative
* byte[1:6]: 0 => 4 byte limbs
* 1 => 8 byte limbs
* byte[2]: 0 => rc = 0
* 1 => rc > 0
* 2 => rc < 0
* byte[3]: mpfr.round_mode
* byte[4]+: precision, saved in 4 or 8 bytes
* byte[4+n]+: exponent, saved in 4 or 8 bytes
* byte[4+2n]+: mantissa
*/
static PyObject *
GMPy_MPFR_To_Binary(MPFR_Object *self)
{
size_t sizemant = 0, sizesize = 4, size = 4, sizetemp, i;
mp_limb_t templimb;
mpfr_prec_t precision;
mpfr_exp_t exponent = 0;
int sgn;
char *buffer, *cp, large = 0x00, expsgn = 0x00;
PyObject *result = 0;
/* Check if the precision, exponent and mantissa length can fit in
* 32 bits.
*/
sgn = mpfr_signbit(self->f);
precision = mpfr_get_prec(self->f);
/* Exponent and mantiss are only valid for regular numbers
* (not 0, Nan, Inf, -Inf).
*/
if (mpfr_regular_p(self->f)) {
exponent = self->f->_mpfr_exp;
if (exponent < 0) {
exponent = -exponent;
expsgn = 0x20;
}
/* Calculate the size of mantissa in limbs */
sizemant = (self->f->_mpfr_prec + mp_bits_per_limb - 1)/mp_bits_per_limb;
}
if (((exponent >> 16) >> 16) ||
((precision >> 16) >> 16) ||
((sizemant >> 16) >> 16)) {
/* This can only be tested on 64-bit platforms. lcov will report the
* code as not tested until 64-bit specific tests are created.
*/
sizesize = 8;
large = 0x04;
}
if (!mpfr_regular_p(self->f)) {
/* Only need to save the precision. */
size += sizesize;
TEMP_ALLOC(buffer, size);
buffer[0] = 0x04;
/* Set to all 0 since we are special. */
buffer[1] = 0x00;
/* Set the sign bit. */
if (sgn) buffer[1] |= 0x02;
/* 4 or 8 byte values. */
buffer[1] |= large;
/* Check if NaN. */
if (mpfr_nan_p(self->f)) buffer[1] |= 0x08;
/* Check if Infinity. */
if (mpfr_inf_p(self->f)) buffer[1] |= 0x10;
/* Save the result code */
if (self->rc == 0) buffer[2] = 0x00;
else if (self->rc > 0) buffer[2] = 0x01;
else buffer[2] = 0x02;
/* Save the precision */
sizetemp = precision;
for (i=0; i>= 8;
}
goto done;
}
/* Now process all actual numbers. */
size += (2 * sizesize) + (sizemant * (mp_bits_per_limb >> 3));
TEMP_ALLOC(buffer, size);
buffer[0] = 0x04;
/* Set bit 0 to 1 since we are an actual number. */
buffer[1] = 0x01;
/* Save the sign bit. */
if (sgn) buffer[1] |= 0x02;
/* Save the size of the values. */
buffer[1] |= large;
/* Save the exponent sign. */
buffer[1] |= expsgn;
/* Save the limb size. */
if ((mp_bits_per_limb >> 3) == 8)
buffer[1] |= 0x40;
/* This branch can only be reached on 32-bit platforms. */
else if ((mp_bits_per_limb >> 3) != 4) {
/* LCOV_EXCL_START */
SYSTEM_ERROR("cannot support current limb size");
TEMP_FREE(buffer, size);
return NULL;
/* LCOV_EXCL_STOP */
}
/* Save the result code. */
if (self->rc == 0) buffer[2] = 0x00;
else if (self->rc > 0) buffer[2] = 0x01;
else buffer[2] = 0x02;
/* Rounding mode is no longer used, so just store a null byte. */
buffer[3] = 0x00;
/* Save the precision */
cp = buffer + 4;
sizetemp = precision;
for (i=0; i>= 8;
}
/* Save the exponenet */
cp += sizesize;
sizetemp = exponent;
for (i=0; i>= 8;
}
/* Save the actual mantissa */
cp += sizesize;
for (i=0; if->_mpfr_d[i];
#if GMP_LIMB_BITS == 64
cp[0] = (char)(templimb & 0xff);
templimb >>= 8;
cp[1] = (char)(templimb & 0xff);
templimb >>= 8;
cp[2] = (char)(templimb & 0xff);
templimb >>= 8;
cp[3] = (char)(templimb & 0xff);
templimb >>= 8;
cp[4] = (char)(templimb & 0xff);
templimb >>= 8;
cp[5] = (char)(templimb & 0xff);
templimb >>= 8;
cp[6] = (char)(templimb & 0xff);
templimb >>= 8;
cp[7] = (char)(templimb & 0xff);
cp += 8;
#endif
#if GMP_LIMB_BITS == 32
cp[0] = (char)(templimb & 0xff);
templimb >>= 8;
cp[1] = (char)(templimb & 0xff);
templimb >>= 8;
cp[2] = (char)(templimb & 0xff);
templimb >>= 8;
cp[3] = (char)(templimb & 0xff);
cp += 4;
#endif
}
done:
result = PyBytes_FromStringAndSize(buffer, size);
TEMP_FREE(buffer, size);
return result;
}
/* Format of the binary representation of an mpc.
*
* The format consists of the concatenation of mpfrs (real and imaginary)
* converted to binary format. The 0x04 leading byte of each binary string
* is replaced by 0x05.
*/
static PyObject *
GMPy_MPC_To_Binary(MPC_Object *obj)
{
MPFR_Object *real = NULL, *imag = NULL;
PyObject *result = NULL, *temp = NULL;
mpfr_prec_t rprec = 0, iprec = 0;
CTXT_Object *context = NULL;
CHECK_CONTEXT(context);
mpc_get_prec2(&rprec, &iprec, obj->c);
if (!(real = GMPy_MPFR_New(rprec, context)) ||
!(imag = GMPy_MPFR_New(iprec, context))) {
/* LCOV_EXCL_START */
Py_XDECREF((PyObject*)real);
Py_XDECREF((PyObject*)imag);
return NULL;
/* LCOV_EXCL_STOP */
}
mpfr_set(real->f, mpc_realref(obj->c), MPFR_RNDN);
mpfr_set(imag->f, mpc_imagref(obj->c), MPFR_RNDN);
real->rc = obj->rc;
if (!(result = GMPy_MPFR_To_Binary(real)) ||
!(temp = GMPy_MPFR_To_Binary(imag))) {
/* LCOV_EXCL_START */
Py_XDECREF((PyObject*)result);
Py_XDECREF((PyObject*)temp);
Py_DECREF((PyObject*)real);
Py_DECREF((PyObject*)imag);
return NULL;
/* LCOV_EXCL_STOP */
}
Py_DECREF((PyObject*)real);
Py_DECREF((PyObject*)imag);
PyBytes_AS_STRING(result)[0] = 0x05;
PyBytes_AS_STRING(temp)[0] = 0x05;
PyBytes_ConcatAndDel(&result, temp);
return result;
}
PyDoc_STRVAR(doc_from_binary,
"from_binary(bytes, /) -> mpz | xmpz | mpq | mpfr | mpc\n\n"
"Return a Python object from a byte sequence created by `to_binary()`.");
static PyObject *
GMPy_MPANY_From_Binary(PyObject *self, PyObject *other)
{
unsigned char *buffer, *cp;
Py_ssize_t len;
CTXT_Object *context = NULL;
CHECK_CONTEXT(context);
if (!(PyBytes_Check(other))) {
TYPE_ERROR("from_binary() requires bytes argument");
return NULL;
}
len = PyBytes_Size(other);
if (len < 2) {
VALUE_ERROR("byte sequence too short for from_binary()");
return NULL;
}
buffer = (unsigned char*)PyBytes_AsString(other);
cp = buffer;
switch (cp[0]) {
case 0x01: {
MPZ_Object *result;
if (!(result = GMPy_MPZ_New(NULL))) {
/* LCOV_EXCL_START */
return NULL;
/* LCOV_EXCL_STOP */
}
if (cp[1] == 0x00) {
mpz_set_ui(result->z, 0);
return (PyObject*)result;
}
mpz_import(result->z, len-2, -1, sizeof(char), 0, 0, cp+2);
if (cp[1] == 0x02)
mpz_neg(result->z, result->z);
return (PyObject*)result;
break;
}
case 0x02: {
XMPZ_Object *result;
if (!(result = GMPy_XMPZ_New(NULL))) {
/* LCOV_EXCL_START */
return NULL;
/* LCOV_EXCL_STOP */
}
if (cp[1] == 0x00) {
mpz_set_ui(result->z, 0);
return (PyObject*)result;
}
mpz_import(result->z, len-2, -1, sizeof(char), 0, 0, cp+2);
if (cp[1] == 0x02)
mpz_neg(result->z, result->z);
return (PyObject*)result;
break;
}
case 0x03: {
MPQ_Object *result;
Py_ssize_t numlen = 0, sizesize = 4, i;
mpz_t num, den;
if (!(result = GMPy_MPQ_New(NULL))) {
/* LCOV_EXCL_START */
return NULL;
/* LCOV_EXCL_STOP */
}
if (cp[1] == 0x00) {
mpq_set_ui(result->q, 0, 1);
return (PyObject*)result;
}
if (cp[1] & 0x04)
sizesize = 8;
if (len < 2 + sizesize) {
VALUE_ERROR("byte sequence too short for from_binary()");
return NULL;
}
for (i=sizesize; i>0; --i) {
numlen = (numlen << 8) + cp[i+1];
}
if (len < 2 + sizesize + numlen + 1) {
VALUE_ERROR("byte sequence too short for from_binary()");
return NULL;
}
mpz_init(num);
mpz_init(den);
mpz_import(num, numlen, -1,
sizeof(char), 0, 0, cp+sizesize+2);
mpz_import(den, len-numlen-sizesize-2, -1,
sizeof(char), 0, 0, cp+sizesize+numlen+2);
mpq_set_num(result->q, num);
mpq_set_den(result->q, den);
mpq_canonicalize(result->q);
mpz_clear(num);
mpz_clear(den);
if (cp[1] == 0x02)
mpq_neg(result->q, result->q);
return (PyObject*)result;
break;
}
case 0x04: {
MPFR_Object *result;
Py_ssize_t sizemant = 0, sizesize = 4, i, newmant;
mpfr_prec_t precision = 0;
mpfr_exp_t exponent = 0;
mp_limb_t templimb;
int sgn = 1, expsgn = 1, limbsize = 4;
int newlimbsize = (mp_bits_per_limb >> 3);
if (len < 4) {
VALUE_ERROR("byte sequence too short for from_binary()");
return NULL;
}
/* Get size of values. */
if (cp[1] & 0x04) sizesize = 8;
/* Get the original precision. */
for (i=sizesize; i>0; --i) {
precision = (precision << 8) + cp[i+3];
}
/* Get the original sign bit. */
if (cp[1] & 0x02) sgn = -1;
/* Get the original exponent sign. */
if (cp[1] & 0x20) expsgn = -1;
/* Get the limb size of the originating system. */
if (cp[1] & 0x40) limbsize = 8;
if (!(result = GMPy_MPFR_New(precision, context))) {
/* LCOV_EXCL_START */
return NULL;
/* LCOV_EXCL_STOP */
}
/* Restore the original result code and rounding mode. */
/* Get the original result code. */
if (cp[2] == 0) result->rc = 0;
else if (cp[2] == 1) result->rc = 1;
else result->rc = -1;
if (!(cp[1] & 0x01)) {
/* Process special numbers. */
if ((cp[1] & 0x18) == 0x00)
mpfr_set_zero(result->f, sgn);
else if ((cp[1] & 0x18) == 0x08)
mpfr_set_nan(result->f);
else
mpfr_set_inf(result->f, sgn);
return (PyObject*)result;
}
/* Process actual numbers. */
/* Calculate the number of limbs on the original system. */
if (limbsize == 8) sizemant = ((precision + 63) / 64);
else sizemant = ((precision + 31) / 32);
/* Calculate the number of limbs on the current system. */
newmant = (precision + mp_bits_per_limb - 1) / mp_bits_per_limb;
/* Get the original exponent. */
cp = buffer + 4 + sizesize - 1;
for (i=sizesize; i>0; --i) {
exponent = (exponent << 8) + cp[i];
}
if (len < 2 + sizesize) {
VALUE_ERROR("byte sequence too short for from_binary()");
return NULL;
}
/* Check if the mantissa occupies the same number of bytes
* on both the source and target system. */
if (limbsize * sizemant == newmant * newlimbsize) {
mpfr_set_ui(result->f, 1, MPFR_RNDN);
cp = buffer + 4 + (2 * sizesize);
for (i=0; if->_mpfr_d[i] = templimb;
cp += newlimbsize;
}
result->f->_mpfr_exp = expsgn * exponent;
if (sgn == -1)
mpfr_neg(result->f, result->f, MPFR_RNDN);
return (PyObject*)result;
}
else if (limbsize * sizemant > newmant * newlimbsize) {
/* Since the amount of saved data is greater than the amount of
* data needed on the new system, we skip the first 32 bits
* since they must be 0.
*/
/* Verify we are on a 32-bit system and the source was 64-bit. */
if ((limbsize == 8) && (newlimbsize == 4)) {
VALUE_ERROR("byte sequence invalid for from_binary()");
return NULL;
}
mpfr_set_ui(result->f, 1, MPFR_RNDN);
cp = buffer + 4 + (2 * sizesize) + 4;
for (i=0; if->_mpfr_d[i] = templimb;
cp += newlimbsize;
}
result->f->_mpfr_exp = expsgn * exponent;
if (sgn == -1)
mpfr_neg(result->f, result->f, MPFR_RNDN);
return (PyObject*)result;
}
else {
/* Since the amount of saved data is less than the amount of
* data needed on the new system, we must "add" 32 0-bits at
* the low end.
*/
/* Verify we are on a 64-bit system and the source was 32-bit. */
if ((limbsize == 4) && (newlimbsize == 8)) {
VALUE_ERROR("byte sequence invalid for from_binary()");
return NULL;
}
mpfr_set_ui(result->f, 1, MPFR_RNDN);
cp = buffer + 4 + (2 * sizesize);
templimb = cp[3];
templimb = (templimb << 8) + cp[2];
templimb = (templimb << 8) + cp[1];
templimb = (templimb << 8) + cp[0];
result->f->_mpfr_d[i] = ((templimb << 16) << 16);
cp += 4;
for (i=0; if->_mpfr_d[i] = templimb;
cp += newlimbsize;
}
result->f->_mpfr_exp = expsgn * exponent;
if (sgn == -1)
mpfr_neg(result->f, result->f, MPFR_RNDN);
return (PyObject*)result;
}
}
case 0x05: {
MPC_Object *result;
MPFR_Object *real = 0, *imag = 0;
Py_ssize_t sizemant = 0, sizesize = 4, i, newmant;
mpfr_prec_t precision = 0;
mpfr_exp_t exponent = 0;
mp_limb_t templimb;
int sgn = 1, expsgn = 1, limbsize = 4;
int newlimbsize = (mp_bits_per_limb >> 3);
unsigned char *tempbuf;
if (len < 4) {
VALUE_ERROR("byte sequence too short for from_binary()");
return NULL;
}
/* read the real part first */
if (cp[1] & 0x04) sizesize = 8;
for (i=sizesize; i>0; --i) {
precision = (precision << 8) + cp[i+3];
}
if (cp[1] & 0x02) sgn = -1;
if (cp[1] & 0x20) expsgn = -1;
if (cp[1] & 0x40) limbsize = 8;
if (!(real = GMPy_MPFR_New(precision, context))) {
/* LCOV_EXCL_START */
return NULL;
/* LCOV_EXCL_STOP */
}
if (cp[2] == 0) real->rc = 0;
else if (cp[2] == 1) real->rc = 1;
else real->rc = -1;
if (!(cp[1] & 0x01)) {
if ((cp[1] & 0x18) == 0x00)
mpfr_set_zero(real->f, sgn);
else if ((cp[1] & 0x18) == 0x08)
mpfr_set_nan(real->f);
else
mpfr_set_inf(real->f, sgn);
cp += 4 + sizesize;
goto readimag;
}
if (limbsize == 8) sizemant = ((precision + 63) / 64);
else sizemant = ((precision + 31) / 32);
newmant = (precision + mp_bits_per_limb - 1) / mp_bits_per_limb;
cp = buffer + 4 + sizesize - 1;
for (i=sizesize; i>0; --i) {
exponent = (exponent << 8) + cp[i];
}
if (limbsize * sizemant == newmant * newlimbsize) {
mpfr_set_ui(real->f, 1, MPFR_RNDN);
cp = buffer + 4 + (2 * sizesize);
for (i=0; if->_mpfr_d[i] = templimb;
cp += newlimbsize;
}
real->f->_mpfr_exp = expsgn * exponent;
if (sgn == -1)
mpfr_neg(real->f, real->f, MPFR_RNDN);
}
else if (limbsize * sizemant > newmant * newlimbsize) {
if ((limbsize == 8) && (newlimbsize == 4)) {
VALUE_ERROR("byte sequence invalid for from_binary()");
Py_DECREF((PyObject*)real);
return NULL;
}
mpfr_set_ui(real->f, 1, MPFR_RNDN);
cp = buffer + 4 + (2 * sizesize) + 4;
for (i=0; if->_mpfr_d[i] = templimb;
cp += newlimbsize;
}
real->f->_mpfr_exp = expsgn * exponent;
if (sgn == -1)
mpfr_neg(real->f, real->f, MPFR_RNDN);
}
else {
if ((limbsize == 4) && (newlimbsize == 8)) {
VALUE_ERROR("byte sequence invalid for from_binary()");
Py_DECREF((PyObject*)real);
return NULL;
}
mpfr_set_ui(real->f, 1, MPFR_RNDN);
cp = buffer + 4 + (2 * sizesize);
templimb = cp[3];
templimb = (templimb << 8) + cp[2];
templimb = (templimb << 8) + cp[1];
templimb = (templimb << 8) + cp[0];
real->f->_mpfr_d[i] = ((templimb << 16) << 16);
cp += 4;
for (i=0; if->_mpfr_d[i] = templimb;
cp += newlimbsize;
}
real->f->_mpfr_exp = expsgn * exponent;
if (sgn == -1)
mpfr_neg(real->f, real->f, MPFR_RNDN);
}
readimag:
/* Set all the variables back to default. */
tempbuf = cp;
sizemant = 0;
sizesize = 4;
precision = 0;
exponent = 0;
sgn = 1;
expsgn = 1;
limbsize = 4;
/* Done reading the real part. The next byte should be 0x05. */
if (!(cp[0] == 0x05)) {
VALUE_ERROR("byte sequence invalid for from_binary()");
Py_DECREF((PyObject*)real);
return NULL;
}
if (cp[1] & 0x04) sizesize = 8;
for (i=sizesize; i>0; --i) {
precision = (precision << 8) + cp[i+3];
}
if (cp[1] & 0x02) sgn = -1;
if (cp[1] & 0x20) expsgn = -1;
if (cp[1] & 0x40) limbsize = 8;
if (!(imag = GMPy_MPFR_New(precision, context))) {
/* LCOV_EXCL_START */
Py_DECREF((PyObject*)real);
return NULL;
/* LCOV_EXCL_STOP */
}
if (cp[2] == 0) imag->rc = 0;
else if (cp[2] == 1) imag->rc = 1;
else imag->rc = -1;
if (!(cp[1] & 0x01)) {
if ((cp[1] & 0x18) == 0x00)
mpfr_set_zero(imag->f, sgn);
else if ((cp[1] & 0x18) == 0x08)
mpfr_set_nan(imag->f);
else
mpfr_set_inf(imag->f, sgn);
goto alldone;
}
if (limbsize == 8) sizemant = ((precision + 63) / 64);
else sizemant = ((precision + 31) / 32);
newmant = (precision + mp_bits_per_limb - 1) / mp_bits_per_limb;
cp = tempbuf + 4 + sizesize - 1;
for (i=sizesize; i>0; --i) {
exponent = (exponent << 8) + cp[i];
}
if (limbsize * sizemant == newmant * newlimbsize) {
mpfr_set_ui(imag->f, 1, MPFR_RNDN);
cp = tempbuf + 4 + (2 * sizesize);
for (i=0; if->_mpfr_d[i] = templimb;
cp += newlimbsize;
}
imag->f->_mpfr_exp = expsgn * exponent;
if (sgn == -1)
mpfr_neg(imag->f, imag->f, MPFR_RNDN);
}
else if (limbsize * sizemant > newmant * newlimbsize) {
if ((limbsize == 8) && (newlimbsize == 4)) {
VALUE_ERROR("byte sequence invalid for from_binary()");
Py_DECREF((PyObject*)real);
Py_DECREF((PyObject*)imag);
return NULL;
}
mpfr_set_ui(imag->f, 1, MPFR_RNDN);
cp = tempbuf + 4 + (2 * sizesize) + 4;
for (i=0; if->_mpfr_d[i] = templimb;
cp += newlimbsize;
}
imag->f->_mpfr_exp = expsgn * exponent;
if (sgn == -1)
mpfr_neg(imag->f, imag->f, MPFR_RNDN);
}
else {
if ((limbsize == 4) && (newlimbsize == 8)) {
VALUE_ERROR("byte sequence invalid for from_binary()");
Py_DECREF((PyObject*)real);
Py_DECREF((PyObject*)imag);
return NULL;
}
mpfr_set_ui(imag->f, 1, MPFR_RNDN);
cp = tempbuf + 4 + (2 * sizesize);
templimb = cp[3];
templimb = (templimb << 8) + cp[2];
templimb = (templimb << 8) + cp[1];
templimb = (templimb << 8) + cp[0];
imag->f->_mpfr_d[i] = ((templimb << 16) << 16);
cp += 4;
for (i=0; if->_mpfr_d[i] = templimb;
cp += newlimbsize;
}
imag->f->_mpfr_exp = expsgn * exponent;
if (sgn == -1)
mpfr_neg(imag->f, imag->f, MPFR_RNDN);
}
alldone:
if (!(result = (MPC_Object*)GMPy_MPC_New(0, 0, context))) {
/* LCOV_EXCL_START */
Py_DECREF((PyObject*)real);
Py_DECREF((PyObject*)imag);
return NULL;
/* LCOV_EXCL_STOP */
}
mpfr_swap(mpc_realref(result->c), real->f);
mpfr_swap(mpc_imagref(result->c), imag->f);
Py_DECREF((PyObject*)real);
Py_DECREF((PyObject*)imag);
return (PyObject*)result;
}
default: {
TYPE_ERROR("from_binary() argument type not supported");
return NULL;
}
}
}
PyDoc_STRVAR(doc_to_binary,
"to_binary(x, /) -> bytes\n\n"
"Return a Python byte sequence that is a portable binary\n"
"representation of a gmpy2 object x. The byte sequence can\n"
"be passed to `from_binary()` to obtain an exact copy of\n"
"x's value. Raises a `TypeError` if x is not a gmpy2 object.");
static PyObject *
GMPy_MPANY_To_Binary(PyObject *self, PyObject *other)
{
if(MPZ_Check(other))
return GMPy_MPZ_To_Binary((MPZ_Object*)other);
else if(XMPZ_Check(other))
return GMPy_XMPZ_To_Binary((XMPZ_Object*)other);
else if(MPQ_Check(other))
return GMPy_MPQ_To_Binary((MPQ_Object*)other);
else if(MPFR_Check(other))
return GMPy_MPFR_To_Binary((MPFR_Object*)other);
else if(MPC_Check(other))
return GMPy_MPC_To_Binary((MPC_Object*)other);
TYPE_ERROR("to_binary() argument type not supported");
return NULL;
}
././@PaxHeader 0000000 0000000 0000000 00000000026 00000000000 010213 x ustar 00 22 mtime=1710307256.0
gmpy2-2.2.1/src/gmpy2_binary.h 0000644 0001750 0001750 00000005552 14574233670 014606 0 ustar 00case case /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* gmpy2_binary.c *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Python interface to the GMP, MPFR, and MPC multiple precision *
* libraries. *
* *
* Copyright 2000 - 2009 Alex Martelli *
* *
* Copyright 2008 - 2024 Case Van Horsen *
* *
* This file is part of GMPY2. *
* *
* GMPY2 is free software: you can redistribute it and/or modify it under *
* the terms of the GNU Lesser General Public License as published by the *
* Free Software Foundation, either version 3 of the License, or (at your *
* option) any later version. *
* *
* GMPY2 is distributed in the hope that it will be useful, but WITHOUT *
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or *
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public *
* License for more details. *
* *
* You should have received a copy of the GNU Lesser General Public *
* License along with GMPY2; if not, see *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
#ifndef GMPY_BINARY_H
#define GMPY_BINARY_H
#ifdef __cplusplus
extern "C" {
#endif
/* Conversion routines between GMPY2 objects and a compact, portable
* binary representation. The binary format of GMPY2 is not compatible
* with GMPY 1.x. Methods to read the old format are provided.
*/
static PyObject * GMPy_MPZ_From_Old_Binary(PyObject *self, PyObject *other);
static PyObject * GMPy_MPQ_From_Old_Binary(PyObject *self, PyObject *other);
static PyObject * GMPy_MPFR_From_Old_Binary(PyObject *self, PyObject *other);
static PyObject * GMPy_MPANY_From_Binary(PyObject *self, PyObject *other);
static PyObject * GMPy_MPANY_To_Binary(PyObject *self, PyObject *other);
static PyObject * GMPy_MPZ_To_Binary(MPZ_Object *self);
static PyObject * GMPy_XMPZ_To_Binary(XMPZ_Object *self);
static PyObject * GMPy_MPQ_To_Binary(MPQ_Object *self);
static PyObject * GMPy_MPFR_To_Binary(MPFR_Object *self);
static PyObject * GMPy_MPC_To_Binary(MPC_Object *self);
#ifdef __cplusplus
}
#endif
#endif
././@PaxHeader 0000000 0000000 0000000 00000000026 00000000000 010213 x ustar 00 22 mtime=1711300127.0
gmpy2-2.2.1/src/gmpy2_cache.c 0000644 0001750 0001750 00000062726 14600057037 014355 0 ustar 00case case /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* gmpy2_cache.c *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Python interface to the GMP, MPFR, and MPC multiple precision *
* libraries. *
* *
* Copyright 2000 - 2009 Alex Martelli *
* *
* Copyright 2008 - 2024 Case Van Horsen *
* *
* This file is part of GMPY2. *
* *
* GMPY2 is free software: you can redistribute it and/or modify it under *
* the terms of the GNU Lesser General Public License as published by the *
* Free Software Foundation, either version 3 of the License, or (at your *
* option) any later version. *
* *
* GMPY2 is distributed in the hope that it will be useful, but WITHOUT *
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or *
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public *
* License for more details. *
* *
* You should have received a copy of the GNU Lesser General Public *
* License along with GMPY2; if not, see *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
/* gmpy2 caches objects so they can be reused quickly without involving a new
* memory allocation or object construction.
*/
/* Caching logic for Pympz. */
/* GMPy_MPZ_New returns a reference to a new MPZ_Object. Its value
* is initialized to 0.
*/
static MPZ_Object *
GMPy_MPZ_New(CTXT_Object *context)
{
MPZ_Object *result = NULL;
if (global.in_gmpympzcache) {
result = global.gmpympzcache[--(global.in_gmpympzcache)];
Py_INCREF((PyObject*)result);
mpz_set_ui(result->z, 0);
}
else {
result = PyObject_New(MPZ_Object, &MPZ_Type);
if (result == NULL) {
return NULL;
}
mpz_init(result->z);
}
result->hash_cache = -1;
return result;
}
/* GMPy_MPZ_NewInit returns a reference to an initialized MPZ_Object. It is
* used by mpz.__new__ to replace the old mpz() factory function.
*/
static PyObject *
GMPy_MPZ_NewInit(PyTypeObject *type, PyObject *args, PyObject *keywds)
{
MPZ_Object *result = NULL;
PyObject *n = NULL;
PyObject *temp = NULL;
PyObject *out = NULL;
int base = 0;
Py_ssize_t argc;
static char *kwlist[] = {"s", "base", NULL };
CTXT_Object *context = NULL;
if (type != &MPZ_Type) {
TYPE_ERROR("mpz.__new__() requires mpz type");
return NULL;
}
/* Optimize the most common use cases first; either 0 or 1 argument */
argc = PyTuple_GET_SIZE(args);
if (argc == 0) {
return (PyObject*)GMPy_MPZ_New(context);
}
if (argc == 1 && !keywds) {
n = PyTuple_GET_ITEM(args, 0);
if (MPZ_Check(n)) {
Py_INCREF(n);
return n;
}
if (PyLong_Check(n)) {
return (PyObject*)GMPy_MPZ_From_PyLong(n, context);
}
if (MPQ_Check(n)) {
return (PyObject*)GMPy_MPZ_From_MPQ((MPQ_Object*)n, context);
}
if (MPFR_Check(n)) {
return (PyObject*)GMPy_MPZ_From_MPFR((MPFR_Object*)n, context);
}
if (PyFloat_Check(n)) {
return (PyObject*)GMPy_MPZ_From_PyFloat(n, context);
}
if (XMPZ_Check(n)) {
return (PyObject*)GMPy_MPZ_From_XMPZ((XMPZ_Object*)n, context);
}
if (IS_FRACTION(n)) {
MPQ_Object *temp = GMPy_MPQ_From_Fraction(n, context);
if (temp) {
result = GMPy_MPZ_From_MPQ(temp, context);
Py_DECREF((PyObject*)temp);
}
return (PyObject*)result;
}
if (PyStrOrUnicode_Check(n)) {
return (PyObject*)GMPy_MPZ_From_PyStr(n, base, context);
}
if (HAS_MPZ_CONVERSION(n)) {
out = (PyObject *) PyObject_CallMethod(n, "__mpz__", NULL);
if (out == NULL)
return out;
if (!MPZ_Check(out)) {
PyErr_Format(PyExc_TypeError,
"object of type '%.200s' can not be interpreted as mpz",
Py_TYPE(out)->tp_name);
Py_DECREF(out);
return NULL;
}
return out;
}
/* Try converting to integer. */
temp = PyNumber_Long(n);
if (temp) {
result = GMPy_MPZ_From_PyLong(temp, context);
Py_DECREF(temp);
return (PyObject*)result;
}
TYPE_ERROR("mpz() requires numeric or string argument");
return NULL;
}
if (!PyArg_ParseTupleAndKeywords(args, keywds, "O|i", kwlist, &n, &base)) {
return NULL;
}
if ((base != 0) && ((base < 2)|| (base > 62))) {
VALUE_ERROR("base for mpz() must be 0 or in the interval [2, 62]");
return NULL;
}
if (PyStrOrUnicode_Check(n)) {
return (PyObject*)GMPy_MPZ_From_PyStr(n, base, context);
}
if (IS_REAL(n)) {
TYPE_ERROR("mpz() with number argument only takes 1 argument");
}
else {
TYPE_ERROR("mpz() requires numeric or string (and optional base) arguments");
}
return NULL;
}
static void
GMPy_MPZ_Dealloc(MPZ_Object *self)
{
if (global.in_gmpympzcache < CACHE_SIZE &&
self->z->_mp_alloc <= MAX_CACHE_MPZ_LIMBS) {
global.gmpympzcache[(global.in_gmpympzcache)++] = self;
}
else {
mpz_clear(self->z);
PyObject_Free(self);
}
}
/* Caching logic for Pyxmpz. */
static XMPZ_Object *
GMPy_XMPZ_New(CTXT_Object *context)
{
XMPZ_Object *result = NULL;
if (global.in_gmpyxmpzcache) {
result = global.gmpyxmpzcache[--(global.in_gmpyxmpzcache)];
Py_INCREF((PyObject*)result);
mpz_set_ui(result->z, 0);
}
else {
result = PyObject_New(XMPZ_Object, &XMPZ_Type);
if (result == NULL) {
return NULL;
}
mpz_init(result->z);
}
return result;
}
static PyObject *
GMPy_XMPZ_NewInit(PyTypeObject *type, PyObject *args, PyObject *keywds)
{
XMPZ_Object *result = NULL;
PyObject *n = NULL;
PyObject *temp = NULL;
int base = 0;
Py_ssize_t argc;
static char *kwlist[] = {"s", "base", NULL };
CTXT_Object *context = NULL;
if (type != &XMPZ_Type) {
TYPE_ERROR("xmpz.__new__() requires xmpz type");
return NULL;
}
/* Optimize the most common use cases first; either 0 or 1 argument */
argc = PyTuple_GET_SIZE(args);
if (argc == 0) {
return (PyObject*)GMPy_XMPZ_New(context);
}
if (argc == 1 && !keywds) {
n = PyTuple_GET_ITEM(args, 0);
if (XMPZ_Check(n)) {
Py_INCREF(n);
return n;
}
if (PyLong_Check(n)) {
return (PyObject*)GMPy_XMPZ_From_PyLong(n, context);
}
if (MPQ_Check(n)) {
return (PyObject*)GMPy_XMPZ_From_MPQ((MPQ_Object*)n, context);
}
if (MPFR_Check(n)) {
return (PyObject*)GMPy_XMPZ_From_MPFR((MPFR_Object*)n, context);
}
if (PyFloat_Check(n)) {
return (PyObject*)GMPy_XMPZ_From_PyFloat(n, context);
}
if (MPZ_Check(n)) {
return (PyObject*)GMPy_XMPZ_From_MPZ((MPZ_Object*)n, context);
}
if (IS_FRACTION(n)) {
MPQ_Object *temp = GMPy_MPQ_From_Fraction(n, context);
if (temp) {
result = GMPy_XMPZ_From_MPQ(temp, context);
Py_DECREF((PyObject*)temp);
}
return (PyObject*)result;
}
if (PyStrOrUnicode_Check(n)) {
return (PyObject*)GMPy_XMPZ_From_PyStr(n, base, context);
}
/* Try converting to integer. */
temp = PyNumber_Long(n);
if (temp) {
result = GMPy_XMPZ_From_PyLong(temp, context);
Py_DECREF(temp);
return (PyObject*)result;
}
TYPE_ERROR("xmpz() requires numeric or string argument");
return NULL;
}
if (!PyArg_ParseTupleAndKeywords(args, keywds, "O|i", kwlist, &n, &base)) {
return NULL;
}
if ((base != 0) && ((base < 2)|| (base > 62))) {
VALUE_ERROR("base for xmpz() must be 0 or in the interval [2, 62]");
return NULL;
}
if (PyStrOrUnicode_Check(n)) {
return (PyObject*)GMPy_XMPZ_From_PyStr(n, base, context);
}
if (IS_REAL(n)) {
TYPE_ERROR("xmpz() with number argument only takes 1 argument");
}
else {
TYPE_ERROR("xmpz() requires numeric or string (and optional base) arguments");
}
return NULL;
}
static void
GMPy_XMPZ_Dealloc(XMPZ_Object *self)
{
if (global.in_gmpyxmpzcache < CACHE_SIZE &&
self->z->_mp_alloc <= MAX_CACHE_MPZ_LIMBS) {
global.gmpyxmpzcache[(global.in_gmpyxmpzcache)++] = self;
}
else {
mpz_clear(self->z);
PyObject_Free((PyObject*)self);
}
}
/* Caching logic for Pympq. */
static MPQ_Object *
GMPy_MPQ_New(CTXT_Object *context)
{
MPQ_Object *result = NULL;
if (global.in_gmpympqcache) {
result = global.gmpympqcache[--(global.in_gmpympqcache)];
Py_INCREF((PyObject*)result);
mpq_set_ui(result->q, 0, 1);
}
else {
result = PyObject_New(MPQ_Object, &MPQ_Type);
if (result == NULL) {
return NULL;
}
mpq_init(result->q);
}
result->hash_cache = -1;
return result;
}
static PyObject *
GMPy_MPQ_NewInit(PyTypeObject *type, PyObject *args, PyObject *keywds)
{
MPQ_Object *result = NULL, *temp = NULL;
PyObject *n = NULL, *m = NULL;
int base = 10;
Py_ssize_t argc, keywdc = 0;
static char *kwlist[] = {"s", "base", NULL };
CTXT_Object *context = NULL;
if (type != &MPQ_Type) {
TYPE_ERROR("mpq.__new__() requires mpq type");
return NULL;
}
argc = PyTuple_Size(args);
if (keywds) {
keywdc = PyDict_Size(keywds);
}
if (argc + keywdc > 2) {
TYPE_ERROR("mpq() takes at most 2 arguments");
return NULL;
}
if (argc + keywdc == 0) {
if ((result = GMPy_MPQ_New(context))) {
mpq_set_ui(result->q, 0, 1);
}
return (PyObject*)result;
}
if (argc == 0) {
TYPE_ERROR("mpq() requires at least one non-keyword argument");
return NULL;
}
n = PyTuple_GetItem(args, 0);
/* Handle the case where the first argument is a string. */
if (PyStrOrUnicode_Check(n)) {
/* keyword base is legal */
if (keywdc || argc > 1) {
if (!(PyArg_ParseTupleAndKeywords(args, keywds, "O|i", kwlist, &n, &base))) {
return NULL;
}
}
if ((base != 0) && ((base < 2) || (base > 62))) {
VALUE_ERROR("base for mpq() must be 0 or in the interval [2, 62]");
return NULL;
}
return (PyObject*)GMPy_MPQ_From_PyStr(n, base, context);
}
/* Handle 1 argument. It must be non-complex number or an object with a __mpq__ method. */
if (argc == 1) {
if (IS_REAL(n)) {
return (PyObject *) GMPy_MPQ_From_Number(n, context);
}
}
/* Handle 2 arguments. Both arguments must be integer or rational. */
if (argc == 2) {
m = PyTuple_GetItem(args, 1);
if (IS_RATIONAL(n) && IS_RATIONAL(m)) {
result = GMPy_MPQ_From_RationalAndCopy(n, context);
temp = GMPy_MPQ_From_Rational(m, context);
if (!result || !temp) {
Py_XDECREF((PyObject*)result);
Py_XDECREF((PyObject*)temp);
return NULL;
}
if (mpq_sgn(temp->q) == 0) {
ZERO_ERROR("zero denominator in mpq()");
Py_DECREF((PyObject*)result);
Py_DECREF((PyObject*)temp);
return NULL;
}
mpq_div(result->q, result->q, temp->q);
Py_DECREF((PyObject*)temp);
return (PyObject*)result;
}
}
TYPE_ERROR("mpq() requires numeric or string argument");
return NULL;
}
static void
GMPy_MPQ_Dealloc(MPQ_Object *self)
{
if (global.in_gmpympqcache < CACHE_SIZE &&
mpq_numref(self->q)->_mp_alloc <= MAX_CACHE_MPZ_LIMBS &&
mpq_denref(self->q)->_mp_alloc <= MAX_CACHE_MPZ_LIMBS) {
global.gmpympqcache[(global.in_gmpympqcache)++] = self;
}
else {
mpq_clear(self->q);
PyObject_Free(self);
}
}
/* Caching logic for Pympfr. */
static MPFR_Object *
GMPy_MPFR_New(mpfr_prec_t bits, CTXT_Object *context)
{
MPFR_Object *result;
if (bits < 2) {
CHECK_CONTEXT(context);
bits = GET_MPFR_PREC(context);
}
if (bits < MPFR_PREC_MIN || bits > MPFR_PREC_MAX) {
VALUE_ERROR("invalid value for precision");
return NULL;
}
if (global.in_gmpympfrcache) {
result = global.gmpympfrcache[--(global.in_gmpympfrcache)];
Py_INCREF((PyObject*)result);
}
else {
result = PyObject_New(MPFR_Object, &MPFR_Type);
if (result == NULL) {
return NULL;
}
}
mpfr_init2(result->f, bits);
result->hash_cache = -1;
result->rc = 0;
return result;
}
static PyObject *
GMPy_MPFR_NewInit(PyTypeObject *type, PyObject *args, PyObject *keywds)
{
MPFR_Object *result = NULL;
CTXT_Object *context = NULL;
Py_ssize_t argc, keywdc = 0;
PyObject *arg0 = NULL;
PyObject *out = NULL;
int base = 0;
/* Assumes mpfr_prec_t is the same as a long. */
mpfr_prec_t prec = 0;
static char *kwlist_s[] = {"s", "precision", "base", "context", NULL};
static char *kwlist_n[] = {"n", "precision", "context", NULL};
if (type != &MPFR_Type) {
TYPE_ERROR("mpfr.__new__() requires mpfr type");
return NULL;
}
CHECK_CONTEXT(context);
argc = PyTuple_Size(args);
if (keywds) {
keywdc = PyDict_Size(keywds);
}
if (argc + keywdc > 4) {
TYPE_ERROR("mpfr() takes at most 4 arguments");
return NULL;
}
if (argc + keywdc == 0) {
if ((result = GMPy_MPFR_New(0, context))) {
mpfr_set_ui(result->f, 0, MPFR_RNDN);
}
return (PyObject*)result;
}
if (argc == 0) {
TYPE_ERROR("mpfr() requires at least one non-keyword argument");
return NULL;
}
arg0 = PyTuple_GET_ITEM(args, 0);
/* A string can have precision, base, and context as additional arguments. */
if (PyStrOrUnicode_Check(arg0)) {
if (keywdc || argc > 1) {
if (!(PyArg_ParseTupleAndKeywords(args, keywds, "O|liO", kwlist_s,
&arg0, &prec, &base, &context)))
return NULL;
}
if (!CTXT_Check(context)) {
TYPE_ERROR("context argument is not a valid context");
return NULL;
}
if (prec < 0) {
VALUE_ERROR("precision for mpfr() must be >= 0");
return NULL;
}
if (base != 0 && (base < 2 || base > 62)) {
VALUE_ERROR("base for mpfr() must be 0 or in the interval [2, 62]");
return NULL;
}
return (PyObject*)GMPy_MPFR_From_PyStr(arg0, base, prec, context);
}
if (HAS_MPFR_CONVERSION(arg0)) {
out = (PyObject *) PyObject_CallMethod(arg0, "__mpfr__", NULL);
if(out == NULL)
return out;
if (!MPFR_Check(out)) {
PyErr_Format(PyExc_TypeError,
"object of type '%.200s' can not be interpreted as mpfr",
Py_TYPE(out)->tp_name);
Py_DECREF(out);
return NULL;
}
return out;
}
/* A number can only have precision and context as additional arguments. */
if (IS_REAL(arg0)) {
if (keywdc || argc > 1) {
if (!(PyArg_ParseTupleAndKeywords(args, keywds, "O|lO", kwlist_n,
&arg0, &prec, &context)))
return NULL;
}
if (!CTXT_Check(context)) {
TYPE_ERROR("context argument is not a valid context");
return NULL;
}
if (prec < 0) {
VALUE_ERROR("precision for mpfr() must be >= 0");
return NULL;
}
return (PyObject*)GMPy_MPFR_From_Real(arg0, prec, context);
}
TYPE_ERROR("mpfr() requires numeric or string argument");
return NULL;
}
static void
GMPy_MPFR_Dealloc(MPFR_Object *self)
{
if (global.in_gmpympfrcache < CACHE_SIZE &&
self->f->_mpfr_prec <= MAX_CACHE_MPFR_BITS) {
global.gmpympfrcache[(global.in_gmpympfrcache)++] = self;
}
else {
mpfr_clear(self->f);
PyObject_Free(self);
}
}
static MPC_Object *
GMPy_MPC_New(mpfr_prec_t rprec, mpfr_prec_t iprec, CTXT_Object *context)
{
MPC_Object *result;
if (rprec < 2) {
CHECK_CONTEXT(context);
rprec = GET_REAL_PREC(context);
}
if (iprec < 2) {
CHECK_CONTEXT(context);
iprec = GET_IMAG_PREC(context);
}
if (rprec < MPFR_PREC_MIN || rprec > MPFR_PREC_MAX ||
iprec < MPFR_PREC_MIN || iprec > MPFR_PREC_MAX) {
VALUE_ERROR("invalid value for precision");
return NULL;
}
if (global.in_gmpympccache) {
result = global.gmpympccache[--(global.in_gmpympccache)];
Py_INCREF((PyObject*)result);
}
else {
result = PyObject_New(MPC_Object, &MPC_Type);
if (result == NULL) {
return NULL;
}
}
mpc_init3(result->c, rprec, iprec);
result->hash_cache = -1;
result->rc = 0;
return result;
}
static PyObject *
GMPy_MPC_NewInit(PyTypeObject *type, PyObject *args, PyObject *keywds)
{
MPC_Object *result = NULL;
MPFR_Object *tempreal = NULL, *tempimag = NULL;
PyObject *arg0 = NULL, *arg1 = NULL, *prec = NULL, *out = NULL;
int base = 10;
Py_ssize_t argc = 0, keywdc = 0;
CTXT_Object *context = NULL;
/* Assumes mpfr_prec_t is the same as a long. */
mpfr_prec_t rprec = 0, iprec = 0;
static char *kwlist_c[] = {"c", "precision", "context", NULL};
static char *kwlist_r[] = {"real", "imag", "precision", "context", NULL};
static char *kwlist_s[] = {"s", "precision", "base", "context", NULL};
if (type != &MPC_Type) {
TYPE_ERROR("mpc.__new__() requires mpc type");
return NULL;
}
CHECK_CONTEXT(context);
argc = PyTuple_Size(args);
if (keywds) {
keywdc = PyDict_Size(keywds);
}
if (argc + keywdc > 4) {
TYPE_ERROR("mpc() takes at most 4 arguments");
return NULL;
}
if (argc + keywdc == 0) {
if ((result = GMPy_MPC_New(0, 0, context))) {
mpc_set_ui(result->c, 0, GET_MPC_ROUND(context));
}
return (PyObject*)result;
}
if (argc == 0) {
TYPE_ERROR("mpc() requires at least one non-keyword argument");
return NULL;
}
arg0 = PyTuple_GET_ITEM(args, 0);
/* A string can have precision, base, and context as additional arguments.
*/
if (PyStrOrUnicode_Check(arg0)) {
if (keywdc || argc > 1) {
if (!(PyArg_ParseTupleAndKeywords(args, keywds, "O|OiO", kwlist_s,
&arg0, &prec, &base, &context)))
return NULL;
}
if (!CTXT_Check(context)) {
TYPE_ERROR("context argument is not a valid context");
return NULL;
}
if (prec) {
if (PyLong_Check(prec)) {
rprec = (mpfr_prec_t)PyLong_AsLong(prec);
iprec = rprec;
}
else if (PyTuple_Check(prec) && PyTuple_Size(prec) == 2) {
rprec = (mpfr_prec_t)PyLong_AsLong(PyTuple_GET_ITEM(prec, 0));
iprec = (mpfr_prec_t)PyLong_AsLong(PyTuple_GET_ITEM(prec, 1));
}
else {
TYPE_ERROR("precision for mpc() must be integer or tuple");
return NULL;
}
if (rprec < 0 || iprec < 0) {
if (PyErr_Occurred()) {
VALUE_ERROR("invalid value for precision in mpc()");
}
else {
VALUE_ERROR("precision for mpc() must be >= 0");
}
return NULL;
}
}
if (base < 2 || base > 36) {
VALUE_ERROR("base for mpc() must be in the interval [2,36]");
return NULL;
}
return (PyObject*)GMPy_MPC_From_PyStr(arg0, base, rprec, iprec, context);
}
if (HAS_MPC_CONVERSION(arg0)) {
out = (PyObject*) PyObject_CallMethod(arg0, "__mpc__", NULL);
if(out == NULL)
return out;
if (!MPC_Check(out)) {
PyErr_Format(PyExc_TypeError,
"object of type '%.200s' can not be interpreted as mpc",
Py_TYPE(out)->tp_name);
Py_DECREF(out);
return NULL;
}
return out;
}
/* Should special case PyFLoat to avoid double rounding. */
if (IS_REAL(arg0)) {
if (keywdc || argc > 1) {
if (!(PyArg_ParseTupleAndKeywords(args, keywds, "O|OOO", kwlist_r,
&arg0, &arg1, &prec, &context)))
return NULL;
}
if (!CTXT_Check(context)) {
TYPE_ERROR("context argument is not a valid context");
return NULL;
}
if (prec) {
if (PyLong_Check(prec)) {
rprec = (mpfr_prec_t)PyLong_AsLong(prec);
iprec = rprec;
}
else if (PyTuple_Check(prec) && PyTuple_Size(prec) == 2) {
rprec = (mpfr_prec_t)PyLong_AsLong(PyTuple_GET_ITEM(prec, 0));
iprec = (mpfr_prec_t)PyLong_AsLong(PyTuple_GET_ITEM(prec, 1));
}
else {
TYPE_ERROR("precision for mpc() must be integer or tuple");
return NULL;
}
if (rprec < 0 || iprec < 0) {
if (PyErr_Occurred()) {
VALUE_ERROR("invalid value for precision in mpc()");
}
else {
VALUE_ERROR("precision for mpc() must be >= 0");
}
return NULL;
}
}
if (arg1 && !IS_REAL(arg1)) {
TYPE_ERROR("invalid type for imaginary component in mpc()");
return NULL;
}
tempreal = GMPy_MPFR_From_Real(arg0, rprec, context);
if (arg1) {
tempimag = GMPy_MPFR_From_Real(arg1, iprec, context);
}
else {
if ((tempimag = GMPy_MPFR_New(iprec, context))) {
mpfr_set_ui(tempimag->f, 0, MPFR_RNDN);
}
}
result = GMPy_MPC_New(rprec, iprec, context);
if (!tempreal || !tempimag || !result) {
Py_XDECREF(tempreal);
Py_XDECREF(tempimag);
Py_XDECREF(result);
TYPE_ERROR("mpc() requires string or numeric argument.");
return NULL;
}
mpc_set_fr_fr(result->c, tempreal->f, tempimag->f, GET_MPC_ROUND(context));
Py_DECREF(tempreal);
Py_DECREF(tempimag);
return (PyObject*)result;
}
if (IS_COMPLEX_ONLY(arg0)) {
if (keywdc || argc > 1) {
if (!(PyArg_ParseTupleAndKeywords(args, keywds, "O|O", kwlist_c,
&arg0, &prec)))
return NULL;
}
if (prec) {
if (PyLong_Check(prec)) {
rprec = (mpfr_prec_t)PyLong_AsLong(prec);
iprec = rprec;
}
else if (PyTuple_Check(prec) && PyTuple_Size(prec) == 2) {
rprec = (mpfr_prec_t)PyLong_AsLong(PyTuple_GET_ITEM(prec, 0));
iprec = (mpfr_prec_t)PyLong_AsLong(PyTuple_GET_ITEM(prec, 1));
}
else {
TYPE_ERROR("precision for mpc() must be integer or tuple");
return NULL;
}
if (rprec < 0 || iprec < 0) {
if (PyErr_Occurred()) {
VALUE_ERROR("invalid value for precision in mpc()");
}
else {
VALUE_ERROR("precision for mpc() must be >= 0");
}
return NULL;
}
}
if (PyComplex_Check(arg0)) {
result = GMPy_MPC_From_PyComplex(arg0, rprec, iprec, context);
}
else {
result = GMPy_MPC_From_MPC((MPC_Object*)arg0, rprec, iprec, context);
}
return (PyObject*)result;
}
TYPE_ERROR("mpc() requires numeric or string argument");
return NULL;
}
static void
GMPy_MPC_Dealloc(MPC_Object *self)
{
if (global.in_gmpympccache < CACHE_SIZE &&
mpc_realref(self->c)->_mpfr_prec <= MAX_CACHE_MPFR_BITS &&
mpc_imagref(self->c)->_mpfr_prec <= MAX_CACHE_MPFR_BITS) {
global.gmpympccache[(global.in_gmpympccache)++] = self;
}
else {
mpc_clear(self->c);
PyObject_Free(self);
}
}
././@PaxHeader 0000000 0000000 0000000 00000000026 00000000000 010213 x ustar 00 22 mtime=1710307256.0
gmpy2-2.2.1/src/gmpy2_cache.h 0000644 0001750 0001750 00000010074 14574233670 014360 0 ustar 00case case /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* gmpy2_cache.h *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Python interface to the GMP, MPFR, and MPC multiple precision *
* libraries. *
* *
* Copyright 2000 - 2009 Alex Martelli *
* *
* Copyright 2008 - 2024 Case Van Horsen *
* *
* This file is part of GMPY2. *
* *
* GMPY2 is free software: you can redistribute it and/or modify it under *
* the terms of the GNU Lesser General Public License as published by the *
* Free Software Foundation, either version 3 of the License, or (at your *
* option) any later version. *
* *
* GMPY2 is distributed in the hope that it will be useful, but WITHOUT *
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or *
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public *
* License for more details. *
* *
* You should have received a copy of the GNU Lesser General Public *
* License along with GMPY2; if not, see *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
/* gmpy2 caches objects so they can be reused quickly without involving a new
* memory allocation or object construction.
*/
#ifndef GMPY_CACHE_H
#define GMPY_CACHE_H
#ifdef __cplusplus
extern "C" {
#endif
/* Private functions */
/* C-API functions */
/* static MPZ_Object * GMPy_MPZ_New(CTXT_Object *context); */
/* static PyObject * GMPy_MPZ_NewInit(PyTypeObject *type, PyObject *args, PyObject *keywds); */
/* static void GMPy_MPZ_Dealloc(MPZ_Object *self); */
static GMPy_MPZ_New_RETURN GMPy_MPZ_New GMPy_MPZ_New_PROTO;
static GMPy_MPZ_NewInit_RETURN GMPy_MPZ_NewInit GMPy_MPZ_NewInit_PROTO;
static GMPy_MPZ_Dealloc_RETURN GMPy_MPZ_Dealloc GMPy_MPZ_Dealloc_PROTO;
/* static XMPZ_Object * GMPy_XMPZ_New(CTXT_Object *context); */
/* static PyObject * GMPy_XMPZ_NewInit(PyTypeObject *type, PyObject *args, PyObject *keywds); */
/* static void GMPy_XMPZ_Dealloc(XMPZ_Object *self); */
static GMPy_XMPZ_New_RETURN GMPy_XMPZ_New GMPy_XMPZ_New_PROTO;
static GMPy_XMPZ_NewInit_RETURN GMPy_XMPZ_NewInit GMPy_XMPZ_NewInit_PROTO;
static GMPy_XMPZ_Dealloc_RETURN GMPy_XMPZ_Dealloc GMPy_XMPZ_Dealloc_PROTO;
/* static MPQ_Object * GMPy_MPQ_New(CTXT_Object *context); */
/* static PyObject * GMPy_MPQ_NewInit(PyTypeObject *type, PyObject *args, PyObject *keywds); */
/* static void GMPy_MPQ_Dealloc(MPQ_Object *self); */
static GMPy_MPQ_New_RETURN GMPy_MPQ_New GMPy_MPQ_New_PROTO;
static GMPy_MPQ_NewInit_RETURN GMPy_MPQ_NewInit GMPy_MPQ_NewInit_PROTO;
static GMPy_MPQ_Dealloc_RETURN GMPy_MPQ_Dealloc GMPy_MPQ_Dealloc_PROTO;
/* static MPFR_Object * GMPy_MPFR_New(CTXT_Object *context); */
/* static PyObject * GMPy_MPFR_NewInit(PyTypeObject *type, PyObject *args, PyObject *keywds); */
/* static void GMPy_MPFR_Dealloc(MPFR_Object *self); */
static GMPy_MPFR_New_RETURN GMPy_MPFR_New GMPy_MPFR_New_PROTO;
static GMPy_MPFR_NewInit_RETURN GMPy_MPFR_NewInit GMPy_MPFR_NewInit_PROTO;
static GMPy_MPFR_Dealloc_RETURN GMPy_MPFR_Dealloc GMPy_MPFR_Dealloc_PROTO;
static MPC_Object * GMPy_MPC_New(mpfr_prec_t rprec, mpfr_prec_t iprec, CTXT_Object *context);
static void GMPy_MPC_Dealloc(MPC_Object *self);
#ifdef __cplusplus
}
#endif
#endif
././@PaxHeader 0000000 0000000 0000000 00000000026 00000000000 010213 x ustar 00 22 mtime=1710307256.0
gmpy2-2.2.1/src/gmpy2_cmp.c 0000644 0001750 0001750 00000042522 14574233670 014072 0 ustar 00case case /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* gmpy2_cmp.c *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Python interface to the GMP, MPFR, and MPC multiple precision *
* libraries. *
* *
* Copyright 2000 - 2009 Alex Martelli *
* *
* Copyright 2008 - 2024 Case Van Horsen *
* *
* This file is part of GMPY2. *
* *
* GMPY2 is free software: you can redistribute it and/or modify it under *
* the terms of the GNU Lesser General Public License as published by the *
* Free Software Foundation, either version 3 of the License, or (at your *
* option) any later version. *
* *
* GMPY2 is distributed in the hope that it will be useful, but WITHOUT *
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or *
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public *
* License for more details. *
* *
* You should have received a copy of the GNU Lesser General Public *
* License along with GMPY2; if not, see *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
PyDoc_STRVAR(GMPy_doc_mpany_cmp,
"cmp(x, y, /) -> int\n\n"
"Return -1 if x < y; 0 if x = y; or 1 if x > y. Both x and y must be\n"
"integer, rational or real. Note: 0 is returned (and exception flag set)\n"
"if either argument is NaN.");
static PyObject * _return_cmp(int c)
{
if (c < 0) return PyLong_FromLong(-1);
if (c > 0) return PyLong_FromLong(1);
return PyLong_FromLong(0);
}
static PyObject * _return_negated_cmp(int c)
{
if (c < 0) return PyLong_FromLong(1);
if (c > 0) return PyLong_FromLong(-1);
return PyLong_FromLong(0);
}
static PyObject *
GMPy_MPANY_cmp(PyObject *self, PyObject *args)
{
PyObject *x, *y, *result = NULL;
int xtype, ytype;
CTXT_Object *context = NULL;
CHECK_CONTEXT(context);
if (PyTuple_GET_SIZE(args) != 2) {
TYPE_ERROR("cmp() requires 2 arguments");
return NULL;
}
x = PyTuple_GET_ITEM(args, 0);
y = PyTuple_GET_ITEM(args, 1);
xtype = GMPy_ObjectType(x);
ytype = GMPy_ObjectType(y);
if (IS_TYPE_INTEGER(xtype) && IS_TYPE_INTEGER(ytype)) {
MPZ_Object *tempx = NULL, *tempy = NULL;
if (!(tempx = GMPy_MPZ_From_IntegerWithType(x, xtype, context)) ||
!(tempy = GMPy_MPZ_From_IntegerWithType(y, ytype, context))) {
/* LCOV_EXCL_START */
Py_XDECREF((PyObject*)tempx);
Py_XDECREF((PyObject*)tempy);
return NULL;
/* LCOV_EXCL_STOP */
}
result = _return_cmp(mpz_cmp(tempx->z, tempy->z));
Py_DECREF((PyObject*)tempx);
Py_DECREF((PyObject*)tempy);
return result;
}
if (IS_TYPE_RATIONAL(xtype) && IS_TYPE_INTEGER(ytype)) {
MPQ_Object *tempx = NULL;
MPZ_Object *tempy = NULL;
if (!(tempx = GMPy_MPQ_From_RationalWithType(x, xtype, context)) ||
!(tempy = GMPy_MPZ_From_IntegerWithType(y, ytype, context))) {
/* LCOV_EXCL_START */
Py_XDECREF((PyObject*)tempx);
Py_XDECREF((PyObject*)tempy);
return NULL;
/* LCOV_EXCL_STOP */
}
result = _return_cmp(mpq_cmp_z(tempx->q, tempy->z));
Py_DECREF((PyObject*)tempx);
Py_DECREF((PyObject*)tempy);
return result;
}
if (IS_TYPE_INTEGER(xtype) && IS_TYPE_RATIONAL(ytype)) {
MPZ_Object *tempx = NULL;
MPQ_Object *tempy = NULL;
if (!(tempx = GMPy_MPZ_From_IntegerWithType(x, xtype, context)) ||
!(tempy = GMPy_MPQ_From_RationalWithType(y, ytype, context))) {
/* LCOV_EXCL_START */
Py_XDECREF((PyObject*)tempx);
Py_XDECREF((PyObject*)tempy);
return NULL;
/* LCOV_EXCL_STOP */
}
result = _return_negated_cmp(mpq_cmp_z(tempy->q, tempx->z));
Py_DECREF((PyObject*)tempx);
Py_DECREF((PyObject*)tempy);
return result;
}
if (IS_TYPE_RATIONAL(xtype) && IS_TYPE_RATIONAL(ytype)) {
MPQ_Object *tempx = NULL, *tempy = NULL;
if (!(tempx = GMPy_MPQ_From_RationalWithType(x, xtype, context)) ||
!(tempy = GMPy_MPQ_From_RationalWithType(y, ytype, context))) {
/* LCOV_EXCL_START */
Py_XDECREF((PyObject*)tempx);
Py_XDECREF((PyObject*)tempy);
return NULL;
/* LCOV_EXCL_STOP */
}
result = _return_cmp(mpq_cmp(tempx->q, tempy->q));
Py_DECREF((PyObject*)tempx);
Py_DECREF((PyObject*)tempy);
return result;
}
/* We perform exact comparisons between the mpz, mpq, and mpfr types.
*/
if (IS_TYPE_REAL(xtype) && IS_TYPE_INTEGER(ytype)) {
MPFR_Object *tempx = NULL;
MPZ_Object *tempy = NULL;
if (!(tempx = GMPy_MPFR_From_RealWithType(x, xtype, 1, context)) ||
!(tempy = GMPy_MPZ_From_IntegerWithType(y, ytype, context))) {
/* LCOV_EXCL_START */
Py_XDECREF((PyObject*)tempx);
Py_XDECREF((PyObject*)tempy);
return NULL;
/* LCOV_EXCL_STOP */
}
mpfr_clear_flags();
result =_return_cmp(mpfr_cmp_z(tempx->f, tempy->z));
Py_DECREF((PyObject*)tempx);
Py_DECREF((PyObject*)tempy);
GMPY_CHECK_ERANGE(result, context, "invalid comparison with NaN");
return result;
}
if (IS_TYPE_REAL(xtype) && IS_TYPE_RATIONAL(ytype)) {
MPFR_Object *tempx = NULL;
MPQ_Object *tempy = NULL;
if (!(tempx = GMPy_MPFR_From_RealWithType(x, xtype, 1, context)) ||
!(tempy = GMPy_MPQ_From_RationalWithType(y, ytype, context))) {
/* LCOV_EXCL_START */
Py_XDECREF((PyObject*)tempx);
Py_XDECREF((PyObject*)tempy);
return NULL;
/* LCOV_EXCL_STOP */
}
mpfr_clear_flags();
result =_return_cmp(mpfr_cmp_q(tempx->f, tempy->q));
Py_DECREF((PyObject*)tempx);
Py_DECREF((PyObject*)tempy);
GMPY_CHECK_ERANGE(result, context, "invalid comparison with NaN");
return result;
}
if (IS_TYPE_REAL(xtype) && IS_TYPE_REAL(ytype)) {
MPFR_Object *tempx = NULL;
MPFR_Object *tempy = NULL;
if (!(tempx = GMPy_MPFR_From_RealWithType(x, xtype, 1, context)) ||
!(tempy = GMPy_MPFR_From_RealWithType(y, ytype, 1, context))) {
/* LCOV_EXCL_START */
Py_XDECREF((PyObject*)tempx);
Py_XDECREF((PyObject*)tempy);
return NULL;
/* LCOV_EXCL_STOP */
}
mpfr_clear_flags();
result =_return_cmp(mpfr_cmp(tempx->f, tempy->f));
Py_DECREF((PyObject*)tempx);
Py_DECREF((PyObject*)tempy);
GMPY_CHECK_ERANGE(result, context, "invalid comparison with NaN");
return result;
}
if (IS_TYPE_INTEGER(xtype) && IS_TYPE_REAL(ytype)) {
MPZ_Object *tempx = NULL;
MPFR_Object *tempy = NULL;
if (!(tempx = GMPy_MPZ_From_IntegerWithType(x, xtype, context)) ||
!(tempy = GMPy_MPFR_From_RealWithType(y, ytype, 1, context))) {
/* LCOV_EXCL_START */
Py_XDECREF((PyObject*)tempx);
Py_XDECREF((PyObject*)tempy);
return NULL;
/* LCOV_EXCL_STOP */
}
mpfr_clear_flags();
result =_return_negated_cmp(mpfr_cmp_z(tempy->f, tempx->z));
Py_DECREF((PyObject*)tempx);
Py_DECREF((PyObject*)tempy);
GMPY_CHECK_ERANGE(result, context, "invalid comparison with NaN");
return result;
}
if (IS_TYPE_RATIONAL(xtype) && IS_TYPE_REAL(ytype)) {
MPQ_Object *tempx = NULL;
MPFR_Object *tempy = NULL;
if (!(tempx = GMPy_MPQ_From_RationalWithType(x, xtype, context)) ||
!(tempy = GMPy_MPFR_From_RealWithType(y, ytype, 1, context))) {
/* LCOV_EXCL_START */
Py_XDECREF((PyObject*)tempx);
Py_XDECREF((PyObject*)tempy);
return NULL;
/* LCOV_EXCL_STOP */
}
mpfr_clear_flags();
result =_return_negated_cmp(mpfr_cmp_q(tempy->f, tempx->q));
Py_DECREF((PyObject*)tempx);
Py_DECREF((PyObject*)tempy);
GMPY_CHECK_ERANGE(result, context, "invalid comparison with NaN");
return result;
}
TYPE_ERROR("cmp() requires integer, rational, or real arguments");
return NULL;
}
PyDoc_STRVAR(GMPy_doc_mpany_cmp_abs,
"cmp_abs(x, y, /) -> int\n\n"
"Return -1 if abs(x) < abs(y); 0 if abs(x) = abs(y); or 1 else.");
static PyObject *
GMPy_MPANY_cmp_abs(PyObject *self, PyObject *args)
{
PyObject *x, *y, *result = NULL;
int xtype, ytype;
CTXT_Object *context = NULL;
CHECK_CONTEXT(context);
if (PyTuple_GET_SIZE(args) != 2) {
TYPE_ERROR("cmp() requires 2 arguments");
return NULL;
}
x = PyTuple_GET_ITEM(args, 0);
y = PyTuple_GET_ITEM(args, 1);
xtype = GMPy_ObjectType(x);
ytype = GMPy_ObjectType(y);
if (IS_TYPE_INTEGER(xtype) && IS_TYPE_INTEGER(ytype)) {
MPZ_Object *tempx = NULL, *tempy = NULL;
if (!(tempx = GMPy_MPZ_From_IntegerWithType(x, xtype, context)) ||
!(tempy = GMPy_MPZ_From_IntegerWithType(y, ytype, context))) {
/* LCOV_EXCL_START */
Py_XDECREF((PyObject*)tempx);
Py_XDECREF((PyObject*)tempy);
return NULL;
/* LCOV_EXCL_STOP */
}
result = _return_cmp(mpz_cmpabs(tempx->z, tempy->z));
Py_DECREF((PyObject*)tempx);
Py_DECREF((PyObject*)tempy);
return result;
}
if (IS_TYPE_RATIONAL(xtype) && IS_TYPE_INTEGER(ytype)) {
MPQ_Object *tempx = NULL;
MPZ_Object *tempy = NULL;
if (!(tempx = GMPy_MPQ_From_RationalWithTypeAndCopy(x, xtype, context)) ||
!(tempy = GMPy_MPZ_From_IntegerWithTypeAndCopy(y, ytype, context))) {
/* LCOV_EXCL_START */
Py_XDECREF((PyObject*)tempx);
Py_XDECREF((PyObject*)tempy);
return NULL;
/* LCOV_EXCL_STOP */
}
mpq_abs(tempx->q, tempx->q);
mpz_abs(tempy->z, tempy->z);
result = _return_cmp(mpq_cmp_z(tempx->q, tempy->z));
Py_DECREF((PyObject*)tempx);
Py_DECREF((PyObject*)tempy);
return result;
}
if (IS_TYPE_INTEGER(xtype) && IS_TYPE_RATIONAL(ytype)) {
MPZ_Object *tempx = NULL;
MPQ_Object *tempy = NULL;
if (!(tempx = GMPy_MPZ_From_IntegerWithTypeAndCopy(x,xtype, context)) ||
!(tempy = GMPy_MPQ_From_RationalWithTypeAndCopy(y, ytype, context))) {
/* LCOV_EXCL_START */
Py_XDECREF((PyObject*)tempx);
Py_XDECREF((PyObject*)tempy);
return NULL;
/* LCOV_EXCL_STOP */
}
mpz_abs(tempx->z, tempx->z);
mpq_abs(tempy->q, tempy->q);
result = _return_negated_cmp(mpq_cmp_z(tempy->q, tempx->z));
Py_DECREF((PyObject*)tempx);
Py_DECREF((PyObject*)tempy);
return result;
}
if (IS_TYPE_RATIONAL(xtype) && IS_TYPE_RATIONAL(ytype)) {
MPQ_Object *tempx = NULL, *tempy = NULL;
if (!(tempx = GMPy_MPQ_From_RationalWithTypeAndCopy(x, xtype, context)) ||
!(tempy = GMPy_MPQ_From_RationalWithTypeAndCopy(y, ytype, context))) {
/* LCOV_EXCL_START */
Py_XDECREF((PyObject*)tempx);
Py_XDECREF((PyObject*)tempy);
return NULL;
/* LCOV_EXCL_STOP */
}
mpq_abs(tempx->q, tempx->q);
mpq_abs(tempy->q, tempy->q);
result = _return_cmp(mpq_cmp(tempx->q, tempy->q));
Py_DECREF((PyObject*)tempx);
Py_DECREF((PyObject*)tempy);
return result;
}
/* We perform exact comparisons between the mpz, mpq, and mpfr types.
*/
if (IS_TYPE_REAL(xtype) && IS_TYPE_INTEGER(ytype)) {
MPFR_Object *tempx = NULL;
MPZ_Object *tempy = NULL;
if (!(tempx = GMPy_MPFR_From_RealWithTypeAndCopy(x, xtype, 1, context)) ||
!(tempy = GMPy_MPZ_From_IntegerWithTypeAndCopy(y, ytype, context))) {
/* LCOV_EXCL_START */
Py_XDECREF((PyObject*)tempx);
Py_XDECREF((PyObject*)tempy);
return NULL;
/* LCOV_EXCL_STOP */
}
mpfr_clear_flags();
mpfr_abs(tempx->f, tempx->f, MPFR_RNDN);
mpz_abs(tempy->z, tempy->z);
result =_return_cmp(mpfr_cmp_z(tempx->f, tempy->z));
Py_DECREF((PyObject*)tempx);
Py_DECREF((PyObject*)tempy);
GMPY_CHECK_ERANGE(result, context, "invalid comparison with NaN");
return result;
}
if (IS_TYPE_REAL(xtype) && IS_TYPE_RATIONAL(ytype)) {
MPFR_Object *tempx = NULL;
MPQ_Object *tempy = NULL;
if (!(tempx = GMPy_MPFR_From_RealWithTypeAndCopy(x, xtype, 1, context)) ||
!(tempy = GMPy_MPQ_From_RationalWithTypeAndCopy(y, ytype, context))) {
/* LCOV_EXCL_START */
Py_XDECREF((PyObject*)tempx);
Py_XDECREF((PyObject*)tempy);
return NULL;
/* LCOV_EXCL_STOP */
}
mpfr_clear_flags();
mpfr_abs(tempx->f, tempx->f, MPFR_RNDN);
mpq_abs(tempy->q, tempy->q);
result =_return_cmp(mpfr_cmp_q(tempx->f, tempy->q));
Py_DECREF((PyObject*)tempx);
Py_DECREF((PyObject*)tempy);
GMPY_CHECK_ERANGE(result, context, "invalid comparison with NaN");
return result;
}
if (IS_TYPE_REAL(xtype) && IS_TYPE_REAL(ytype)) {
MPFR_Object *tempx = NULL;
MPFR_Object *tempy = NULL;
if (!(tempx = GMPy_MPFR_From_RealWithType(x, xtype, 1, context)) ||
!(tempy = GMPy_MPFR_From_RealWithType(y, ytype, 1, context))) {
/* LCOV_EXCL_START */
Py_XDECREF((PyObject*)tempx);
Py_XDECREF((PyObject*)tempy);
return NULL;
/* LCOV_EXCL_STOP */
}
mpfr_clear_flags();
result =_return_cmp(mpfr_cmpabs(tempx->f, tempy->f));
Py_DECREF((PyObject*)tempx);
Py_DECREF((PyObject*)tempy);
GMPY_CHECK_ERANGE(result, context, "invalid comparison with NaN");
return result;
}
if (IS_TYPE_INTEGER(xtype) && IS_TYPE_REAL(ytype)) {
MPZ_Object *tempx = NULL;
MPFR_Object *tempy = NULL;
if (!(tempx = GMPy_MPZ_From_IntegerWithTypeAndCopy(x, xtype, context)) ||
!(tempy = GMPy_MPFR_From_RealWithTypeAndCopy(y, ytype, 1, context))) {
/* LCOV_EXCL_START */
Py_XDECREF((PyObject*)tempx);
Py_XDECREF((PyObject*)tempy);
return NULL;
/* LCOV_EXCL_STOP */
}
mpfr_clear_flags();
mpz_abs(tempx->z, tempx->z);
mpfr_abs(tempy->f, tempy->f, MPFR_RNDN);
result =_return_negated_cmp(mpfr_cmp_z(tempy->f, tempx->z));
Py_DECREF((PyObject*)tempx);
Py_DECREF((PyObject*)tempy);
GMPY_CHECK_ERANGE(result, context, "invalid comparison with NaN");
return result;
}
if (IS_TYPE_RATIONAL(xtype) && IS_TYPE_REAL(ytype)) {
MPQ_Object *tempx = NULL;
MPFR_Object *tempy = NULL;
if (!(tempx = GMPy_MPQ_From_RationalWithTypeAndCopy(x, xtype, context)) ||
!(tempy = GMPy_MPFR_From_RealWithTypeAndCopy(y, xtype, 1, context))) {
/* LCOV_EXCL_START */
Py_XDECREF((PyObject*)tempx);
Py_XDECREF((PyObject*)tempy);
return NULL;
/* LCOV_EXCL_STOP */
}
mpfr_clear_flags();
mpq_abs(tempx->q, tempx->q);
mpfr_abs(tempy->f, tempy->f, MPFR_RNDN);
result =_return_negated_cmp(mpfr_cmp_q(tempy->f, tempx->q));
Py_DECREF((PyObject*)tempx);
Py_DECREF((PyObject*)tempy);
GMPY_CHECK_ERANGE(result, context, "invalid comparison with NaN");
return result;
}
if (IS_TYPE_COMPLEX(xtype) && IS_TYPE_COMPLEX(ytype)) {
MPC_Object *tempx = NULL;
MPC_Object *tempy = NULL;
if (!(tempx = GMPy_MPC_From_ComplexWithType(x, xtype, 1, 1, context)) ||
!(tempy = GMPy_MPC_From_ComplexWithType(y, ytype, 1, 1, context))) {
/* LCOV_EXCL_START */
Py_XDECREF((PyObject*)tempx);
Py_XDECREF((PyObject*)tempy);
return NULL;
/* LCOV_EXCL_STOP */
}
mpfr_clear_flags();
result =_return_cmp(mpc_cmp_abs(tempx->c, tempy->c));
Py_DECREF((PyObject*)tempx);
Py_DECREF((PyObject*)tempy);
GMPY_CHECK_ERANGE(result, context, "invalid comparison with NaN");
return result;
}
TYPE_ERROR("cmp_abs() requires integer, rational, real, or complex arguments");
return NULL;
}
././@PaxHeader 0000000 0000000 0000000 00000000026 00000000000 010213 x ustar 00 22 mtime=1710307256.0
gmpy2-2.2.1/src/gmpy2_cmp.h 0000644 0001750 0001750 00000004202 14574233670 014070 0 ustar 00case case /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* gmpy2_cmp.h *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Python interface to the GMP, MPFR, and MPC multiple precision *
* libraries. *
* *
* Copyright 2000 - 2009 Alex Martelli *
* *
* Copyright 2008 - 2024 Case Van Horsen *
* *
* This file is part of GMPY2. *
* *
* GMPY2 is free software: you can redistribute it and/or modify it under *
* the terms of the GNU Lesser General Public License as published by the *
* Free Software Foundation, either version 3 of the License, or (at your *
* option) any later version. *
* *
* GMPY2 is distributed in the hope that it will be useful, but WITHOUT *
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or *
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public *
* License for more details. *
* *
* You should have received a copy of the GNU Lesser General Public *
* License along with GMPY2; if not, see *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
#ifndef GMPY_CMP_H
#define GMPY_CMP_H
#ifdef __cplusplus
extern "C" {
#endif
static PyObject * GMPy_MPANY_cmp(PyObject *self, PyObject *args);
static PyObject * GMPy_MPANY_cmp_abs(PyObject *self, PyObject *args);
#ifdef __cplusplus
}
#endif
#endif
././@PaxHeader 0000000 0000000 0000000 00000000026 00000000000 010213 x ustar 00 22 mtime=1710307256.0
gmpy2-2.2.1/src/gmpy2_const.c 0000644 0001750 0001750 00000016232 14574233670 014440 0 ustar 00case case /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* gmpy2_const.c *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Python interface to the GMP, MPFR, and MPC multiple precision *
* libraries. *
* *
* Copyright 2000 - 2009 Alex Martelli *
* *
* Copyright 2008 - 2024 Case Van Horsen *
* *
* This file is part of GMPY2. *
* *
* GMPY2 is free software: you can redistribute it and/or modify it under *
* the terms of the GNU Lesser General Public License as published by the *
* Free Software Foundation, either version 3 of the License, or (at your *
* option) any later version. *
* *
* GMPY2 is distributed in the hope that it will be useful, but WITHOUT *
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or *
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public *
* License for more details. *
* *
* You should have received a copy of the GNU Lesser General Public *
* License along with GMPY2; if not, see *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
PyDoc_STRVAR(GMPy_doc_function_const_pi,
"const_pi(precision=0) -> mpfr\n\n"
"Return the constant pi using the specified precision. If no\n"
"precision is specified, the default precision is used.");
static PyObject *
GMPy_Function_Const_Pi(PyObject *self, PyObject *args, PyObject *keywds)
{
MPFR_Object *result = NULL;
mpfr_prec_t bits = 0;
static char *kwlist[] = {"precision", NULL};
CTXT_Object *context = NULL;
CHECK_CONTEXT(context);
if (!PyArg_ParseTupleAndKeywords(args, keywds, "|l", kwlist, &bits)) {
return NULL;
}
if ((result = GMPy_MPFR_New(bits, context))) {
mpfr_clear_flags();
result->rc = mpfr_const_pi(result->f, GET_MPFR_ROUND(context));
_GMPy_MPFR_Cleanup(&result, context);
}
return (PyObject*)result;
}
PyDoc_STRVAR(GMPy_doc_context_const_pi,
"context.const_pi() -> mpfr\n\n"
"Return the constant pi using the context's precision.");
static PyObject *
GMPy_Context_Const_Pi(PyObject *self, PyObject *args)
{
MPFR_Object *result = NULL;
CTXT_Object *context = (CTXT_Object*)self;
if ((result = GMPy_MPFR_New(0, context))) {
mpfr_clear_flags();
result->rc = mpfr_const_pi(result->f, GET_MPFR_ROUND(context));
_GMPy_MPFR_Cleanup(&result, context);
}
return (PyObject*)result;
}
PyDoc_STRVAR(GMPy_doc_function_const_euler,
"const_euler(precision=0) -> mpfr\n\n"
"Return the euler constant using the specified precision. If no\n"
"precision is specified, the default precision is used.");
static PyObject *
GMPy_Function_Const_Euler(PyObject *self, PyObject *args, PyObject *keywds)
{
MPFR_Object *result = NULL;
mpfr_prec_t bits = 0;
static char *kwlist[] = {"precision", NULL};
CTXT_Object *context = NULL;
CHECK_CONTEXT(context);
if (!PyArg_ParseTupleAndKeywords(args, keywds, "|l", kwlist, &bits)) {
return NULL;
}
if ((result = GMPy_MPFR_New(bits, context))) {
mpfr_clear_flags();
result->rc = mpfr_const_euler(result->f, GET_MPFR_ROUND(context));
_GMPy_MPFR_Cleanup(&result, context);
}
return (PyObject*)result;
}
PyDoc_STRVAR(GMPy_doc_context_const_euler,
"context.const_euler() -> mpfr\n\n"
"Return the euler constant using the context's precision.");
static PyObject *
GMPy_Context_Const_Euler(PyObject *self, PyObject *args)
{
MPFR_Object *result = NULL;
CTXT_Object *context = (CTXT_Object*)self;
if ((result = GMPy_MPFR_New(0, context))) {
mpfr_clear_flags();
result->rc = mpfr_const_euler(result->f, GET_MPFR_ROUND(context));
_GMPy_MPFR_Cleanup(&result, context);
}
return (PyObject*)result;
}
PyDoc_STRVAR(GMPy_doc_function_const_log2,
"const_log2(precision=0) -> mpfr\n\n"
"Return the log2 constant using the specified precision. If no\n"
"precision is specified, the default precision is used.");
static PyObject *
GMPy_Function_Const_Log2(PyObject *self, PyObject *args, PyObject *keywds)
{
MPFR_Object *result = NULL;
mpfr_prec_t bits = 0;
static char *kwlist[] = {"precision", NULL};
CTXT_Object *context = NULL;
CHECK_CONTEXT(context);
if (!PyArg_ParseTupleAndKeywords(args, keywds, "|l", kwlist, &bits)) {
return NULL;
}
if ((result = GMPy_MPFR_New(bits, context))) {
mpfr_clear_flags();
result->rc = mpfr_const_log2(result->f, GET_MPFR_ROUND(context));
_GMPy_MPFR_Cleanup(&result, context);
}
return (PyObject*)result;
}
PyDoc_STRVAR(GMPy_doc_context_const_log2,
"context.const_log2() -> mpfr\n\n"
"Return the log2 constant using the context's precision.");
static PyObject *
GMPy_Context_Const_Log2(PyObject *self, PyObject *args)
{
MPFR_Object *result = NULL;
CTXT_Object *context = (CTXT_Object*)self;
if ((result = GMPy_MPFR_New(0, context))) {
mpfr_clear_flags();
result->rc = mpfr_const_log2(result->f, GET_MPFR_ROUND(context));
_GMPy_MPFR_Cleanup(&result, context);
}
return (PyObject*)result;
}
PyDoc_STRVAR(GMPy_doc_function_const_catalan,
"const_catalan(precision=0) -> mpfr\n\n"
"Return the catalan constant using the specified precision. If no\n"
"precision is specified, the default precision is used.");
static PyObject *
GMPy_Function_Const_Catalan(PyObject *self, PyObject *args, PyObject *keywds)
{
MPFR_Object *result = NULL;
mpfr_prec_t bits = 0;
static char *kwlist[] = {"precision", NULL};
CTXT_Object *context = NULL;
CHECK_CONTEXT(context);
if (!PyArg_ParseTupleAndKeywords(args, keywds, "|l", kwlist, &bits)) {
return NULL;
}
if ((result = GMPy_MPFR_New(bits, context))) {
mpfr_clear_flags();
result->rc = mpfr_const_catalan(result->f, GET_MPFR_ROUND(context));
_GMPy_MPFR_Cleanup(&result, context);
}
return (PyObject*)result;
}
PyDoc_STRVAR(GMPy_doc_context_const_catalan,
"context.const_catalan() -> mpfr\n\n"
"Return the catalan constant using the context's precision.");
static PyObject *
GMPy_Context_Const_Catalan(PyObject *self, PyObject *args)
{
MPFR_Object *result = NULL;
CTXT_Object *context = (CTXT_Object*)self;
if ((result = GMPy_MPFR_New(0, context))) {
mpfr_clear_flags();
result->rc = mpfr_const_catalan(result->f, GET_MPFR_ROUND(context));
_GMPy_MPFR_Cleanup(&result, context);
}
return (PyObject*)result;
}
././@PaxHeader 0000000 0000000 0000000 00000000026 00000000000 010213 x ustar 00 22 mtime=1710307256.0
gmpy2-2.2.1/src/gmpy2_const.h 0000644 0001750 0001750 00000005252 14574233670 014445 0 ustar 00case case /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* gmpy2_const.h *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Python interface to the GMP, MPFR, and MPC multiple precision *
* libraries. *
* *
* Copyright 2000 - 2009 Alex Martelli *
* *
* Copyright 2008 - 2024 Case Van Horsen *
* *
* This file is part of GMPY2. *
* *
* GMPY2 is free software: you can redistribute it and/or modify it under *
* the terms of the GNU Lesser General Public License as published by the *
* Free Software Foundation, either version 3 of the License, or (at your *
* option) any later version. *
* *
* GMPY2 is distributed in the hope that it will be useful, but WITHOUT *
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or *
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public *
* License for more details. *
* *
* You should have received a copy of the GNU Lesser General Public *
* License along with GMPY2; if not, see *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
#ifndef GMPY_CONST_H
#define GMPY_CONST_H
#ifdef __cplusplus
extern "C" {
#endif
static PyObject * GMPy_Function_Const_Pi(PyObject *self, PyObject *args, PyObject *keywds);
static PyObject * GMPy_Context_Const_Pi(PyObject *self, PyObject *args);
static PyObject * GMPy_Function_Const_Euler(PyObject *self, PyObject *args, PyObject *keywds);
static PyObject * GMPy_Context_Const_Euler(PyObject *self, PyObject *args);
static PyObject * GMPy_Function_Const_Log2(PyObject *self, PyObject *args, PyObject *keywds);
static PyObject * GMPy_Context_Const_Log2(PyObject *self, PyObject *args);
static PyObject * GMPy_Function_Const_Catalan(PyObject *self, PyObject *args, PyObject *keywds);
static PyObject * GMPy_Context_Const_Catalan(PyObject *self, PyObject *args);
#ifdef __cplusplus
}
#endif
#endif
././@PaxHeader 0000000 0000000 0000000 00000000026 00000000000 010213 x ustar 00 22 mtime=1711300127.0
gmpy2-2.2.1/src/gmpy2_context.c 0000644 0001750 0001750 00000126743 14600057037 014776 0 ustar 00case case /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* gmpy2_context.c *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Python interface to the GMP, MPFR, and MPC multiple precision *
* libraries. *
* *
* Copyright 2000 - 2009 Alex Martelli *
* *
* Copyright 2008 - 2024 Case Van Horsen *
* *
* This file is part of GMPY2. *
* *
* GMPY2 is free software: you can redistribute it and/or modify it under *
* the terms of the GNU Lesser General Public License as published by the *
* Free Software Foundation, either version 3 of the License, or (at your *
* option) any later version. *
* *
* GMPY2 is distributed in the hope that it will be useful, but WITHOUT *
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or *
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public *
* License for more details. *
* *
* You should have received a copy of the GNU Lesser General Public *
* License along with GMPY2; if not, see *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
/* This file implements contexts and context managers.
*
* Public API
* ==========
* TBD
*
* Private API
* ===========
* GMPy_CTXT_New
* GMPy_CTXT_Dealloc
* GMPy_CTXT_Set
* GMPy_CTXT_Get
* GMPy_CTXT_Copy
* GMPy_CTXT_ieee
* GMPy_CTXT_Context
* GMPy_CTXT_Repr_Slot
* GMPy_CTXT_Enter
* GMPy_CTXT_Exit
* GMPy_CTXT_Clear_Flags
* plus getters & setters....
*
* Internal functions
* ==================
* GMPy_current_context
*/
#include "pythoncapi_compat.h"
/* Create and delete Context objects. */
static PyObject *
GMPy_CTXT_New(void)
{
CTXT_Object *result;
if ((result = PyObject_New(CTXT_Object, &CTXT_Type))) {
result->ctx.mpfr_prec = DBL_MANT_DIG;
result->ctx.mpfr_round = MPFR_RNDN;
result->ctx.emax = MPFR_EMAX_DEFAULT;
result->ctx.emin = MPFR_EMIN_DEFAULT;
result->ctx.subnormalize = 0;
result->ctx.underflow = 0;
result->ctx.overflow = 0;
result->ctx.inexact = 0;
result->ctx.invalid = 0;
result->ctx.erange = 0;
result->ctx.divzero = 0;
result->ctx.traps = TRAP_NONE;
result->ctx.real_prec = -1;
result->ctx.imag_prec = -1;
result->ctx.real_round = -1;
result->ctx.imag_round = -1;
result->ctx.allow_complex = 0;
result->ctx.rational_division = 0;
result->ctx.allow_release_gil = 0;
result->token = NULL;
}
return (PyObject*)result;
};
static void
GMPy_CTXT_Dealloc(CTXT_Object *self)
{
PyObject_Free(self);
};
/* Begin support for context vars. */
PyDoc_STRVAR(GMPy_doc_get_context,
"get_context() -> context\n\n"
"Return a reference to the current context.");
static inline PyObject *
GMPy_CTXT_Get(PyObject *self, PyObject *args)
{
PyObject *tl_context;
if (PyContextVar_Get(current_context_var, NULL, &tl_context) < 0) {
return NULL;
}
if (tl_context != NULL) {
return tl_context;
}
/* Since there is no existing context, and no default value, let's
* just create a new one.
*/
tl_context = GMPy_CTXT_New();
if (tl_context == NULL) {
return NULL;
}
PyObject *tok = PyContextVar_Set(current_context_var, tl_context);
if (tok == NULL) {
Py_DECREF(tl_context);
return NULL;
}
Py_DECREF(tok);
return tl_context;
}
PyDoc_STRVAR(GMPy_doc_set_context,
"set_context(context, /) -> None\n\n"
"Activate a context object controlling gmpy2 arithmetic.\n");
/* Set the thread local context to a new context, decrement old reference */
static PyObject *
GMPy_CTXT_Set(PyObject *self, PyObject *v)
{
if (!CTXT_Check(v)) {
VALUE_ERROR("set_context() requires a context argument");
return NULL;
}
Py_INCREF(v);
PyObject *tok = PyContextVar_Set(current_context_var, v);
Py_DECREF(v);
if (tok == NULL) {
return NULL;
}
Py_DECREF(tok);
Py_RETURN_NONE;
}
#if 1
static PyObject *
GMPy_CTXT_Enter(PyObject *self, PyObject *args)
{
PyObject *tok = NULL;
PyObject *result = NULL;
result = GMPy_CTXT_Copy(self, NULL);
if (!result) {
return NULL;
}
Py_INCREF(result);
tok = PyContextVar_Set(current_context_var, result);
Py_DECREF(result);
if (tok == NULL) {
return NULL;
}
((CTXT_Object*)self)->token = tok;
return result;
}
static PyObject *
GMPy_CTXT_Exit(PyObject *self, PyObject *args)
{
int res = PyContextVar_Reset(current_context_var, ((CTXT_Object*)self)->token);
if (res == -1) {
SYSTEM_ERROR("Unexpected failure in restoring context.");
return NULL;
}
Py_RETURN_NONE;
}
#endif
PyDoc_STRVAR(GMPy_doc_context_ieee,
"ieee(size, /, subnormalize=True) -> context\n\n"
"Return a new context corresponding to a standard IEEE floating point\n"
"format. The supported sizes are 16, 32, 64, 128, and multiples of\n"
"32 greater than 128.");
static PyObject *
GMPy_CTXT_ieee(PyObject *self, PyObject *args, PyObject *kwargs)
{
long bitwidth;
double bitlog2;
int sub_mode=1;
PyObject *temp;
CTXT_Object *result;
static char *kwlist[] = {"subnormalize", NULL};
if (PyTuple_GET_SIZE(args) != 1) {
TYPE_ERROR("ieee() requires 'int' argument");
return NULL;
}
bitwidth = PyLong_AsLong(PyTuple_GET_ITEM(args, 0));
if (bitwidth == -1 && PyErr_Occurred()) {
TYPE_ERROR("ieee() requires 'int' argument");
return NULL;
}
if (bitwidth <= 0) {
VALUE_ERROR("ieee() requires positive value for size");
return NULL;
}
/* Process just the two keyword arguments. */
if (!(temp = PyTuple_New(0))) {
return NULL;
}
if (!(PyArg_ParseTupleAndKeywords(temp, kwargs,
"|ii", kwlist, &sub_mode))) {
VALUE_ERROR("invalid keyword arguments for ieee()");
Py_DECREF(temp);
return NULL;
}
Py_DECREF(temp);
if (sub_mode)
sub_mode = 1;
if (!(result = (CTXT_Object*)GMPy_CTXT_New())) {
return NULL;
}
if (bitwidth == 16) {
result->ctx.mpfr_prec = 11;
result->ctx.emax = 16;
}
else if (bitwidth == 32) {
result->ctx.mpfr_prec = 24;
result->ctx.emax = 128;
}
else if (bitwidth == 64) {
result->ctx.mpfr_prec = 53;
result->ctx.emax = 1024;
}
else if (bitwidth == 128) {
result->ctx.mpfr_prec = 113;
result->ctx.emax = 16384;
}
else {
if ((bitwidth < 128) && (bitwidth & 31)) {
VALUE_ERROR("bitwidth must be 16, 32, 64, 128; or must be greater than 128 and divisible by 32.");
Py_DECREF((PyObject*)result);
return NULL;
}
bitlog2 = floor((4 * log(bitwidth) / log(2.0)) + 0.5);
result->ctx.mpfr_prec = bitwidth - (long)(bitlog2) + 13;
result->ctx.emax = 1 << (bitwidth - result->ctx.mpfr_prec - 1);
}
result->ctx.subnormalize = sub_mode;
result->ctx.emin = 4 - result->ctx.emax - result->ctx.mpfr_prec;
return (PyObject*)result;
}
/* Helper function to convert to convert a rounding mode to a string. */
static PyObject *
_round_to_name(int val)
{
if (val == MPFR_RNDN) return PyUnicode_FromString("RoundToNearest");
if (val == MPFR_RNDZ) return PyUnicode_FromString("RoundToZero");
if (val == MPFR_RNDU) return PyUnicode_FromString("RoundUp");
if (val == MPFR_RNDD) return PyUnicode_FromString("RoundDown");
if (val == MPFR_RNDA) return PyUnicode_FromString("RoundAwayZero");
if (val == GMPY_DEFAULT) return PyUnicode_FromString("Default");
return NULL;
}
static PyObject *
GMPy_CTXT_Repr_Slot(CTXT_Object *self)
{
PyObject *format;
PyObject *tuple;
PyObject *result = NULL;
int i = 0;
tuple = PyTuple_New(24);
if (!tuple)
return NULL;
format = PyUnicode_FromString(
"context(precision=%s, real_prec=%s, imag_prec=%s,\n"
" round=%s, real_round=%s, imag_round=%s,\n"
" emax=%s, emin=%s,\n"
" subnormalize=%s,\n"
" trap_underflow=%s, underflow=%s,\n"
" trap_overflow=%s, overflow=%s,\n"
" trap_inexact=%s, inexact=%s,\n"
" trap_invalid=%s, invalid=%s,\n"
" trap_erange=%s, erange=%s,\n"
" trap_divzero=%s, divzero=%s,\n"
" allow_complex=%s,\n"
" rational_division=%s,\n"
" allow_release_gil=%s)"
);
if (!format) {
Py_DECREF(tuple);
return NULL;
}
PyTuple_SET_ITEM(tuple, i++, PyLong_FromLong(self->ctx.mpfr_prec));
if (self->ctx.real_prec == GMPY_DEFAULT)
PyTuple_SET_ITEM(tuple, i++, PyUnicode_FromString("Default"));
else
PyTuple_SET_ITEM(tuple, i++, PyLong_FromLong(self->ctx.real_prec));
if (self->ctx.imag_prec == GMPY_DEFAULT)
PyTuple_SET_ITEM(tuple, i++, PyUnicode_FromString("Default"));
else
PyTuple_SET_ITEM(tuple, i++, PyLong_FromLong(self->ctx.imag_prec));
PyTuple_SET_ITEM(tuple, i++, _round_to_name(self->ctx.mpfr_round));
PyTuple_SET_ITEM(tuple, i++, _round_to_name(self->ctx.real_round));
PyTuple_SET_ITEM(tuple, i++, _round_to_name(self->ctx.imag_round));
PyTuple_SET_ITEM(tuple, i++, PyLong_FromLong(self->ctx.emax));
PyTuple_SET_ITEM(tuple, i++, PyLong_FromLong(self->ctx.emin));
PyTuple_SET_ITEM(tuple, i++, PyBool_FromLong(self->ctx.subnormalize));
PyTuple_SET_ITEM(tuple, i++, PyBool_FromLong(self->ctx.traps & TRAP_UNDERFLOW));
PyTuple_SET_ITEM(tuple, i++, PyBool_FromLong(self->ctx.underflow));
PyTuple_SET_ITEM(tuple, i++, PyBool_FromLong(self->ctx.traps & TRAP_OVERFLOW));
PyTuple_SET_ITEM(tuple, i++, PyBool_FromLong(self->ctx.overflow));
PyTuple_SET_ITEM(tuple, i++, PyBool_FromLong(self->ctx.traps & TRAP_INEXACT));
PyTuple_SET_ITEM(tuple, i++, PyBool_FromLong(self->ctx.inexact));
PyTuple_SET_ITEM(tuple, i++, PyBool_FromLong(self->ctx.traps & TRAP_INVALID));
PyTuple_SET_ITEM(tuple, i++, PyBool_FromLong(self->ctx.invalid));
PyTuple_SET_ITEM(tuple, i++, PyBool_FromLong(self->ctx.traps & TRAP_ERANGE));
PyTuple_SET_ITEM(tuple, i++, PyBool_FromLong(self->ctx.erange));
PyTuple_SET_ITEM(tuple, i++, PyBool_FromLong(self->ctx.traps & TRAP_DIVZERO));
PyTuple_SET_ITEM(tuple, i++, PyBool_FromLong(self->ctx.divzero));
PyTuple_SET_ITEM(tuple, i++, PyBool_FromLong(self->ctx.allow_complex));
PyTuple_SET_ITEM(tuple, i++, PyBool_FromLong(self->ctx.rational_division));
PyTuple_SET_ITEM(tuple, i++, PyBool_FromLong(self->ctx.allow_release_gil));
if (!PyErr_Occurred())
result = PyUnicode_Format(format, tuple);
else
SYSTEM_ERROR("internal error in GMPy_CTXT_Repr");
Py_DECREF(format);
Py_DECREF(tuple);
return result;
}
PyDoc_STRVAR(GMPy_doc_context_copy,
"context.copy() -> context\n\n"
"Return a copy of a context.");
static PyObject *
GMPy_CTXT_Copy(PyObject *self, PyObject *other)
{
CTXT_Object *result;
if(!(result = (CTXT_Object*)GMPy_CTXT_New())) {
return NULL;
}
result->ctx = ((CTXT_Object*)self)->ctx;
return (PyObject*)result;
}
/* Parse the keyword arguments available to a context. Returns 1 if no
* error occurred; returns 0 is an error occurred.
*/
static int
_parse_context_args(CTXT_Object *ctxt, PyObject *kwargs)
{
PyObject *args;
int x_trap_underflow = 0, x_trap_overflow = 0, x_trap_inexact = 0;
int x_trap_invalid = 0, x_trap_erange = 0, x_trap_divzero = 0;
static char *kwlist[] = {
"precision", "real_prec", "imag_prec", "round",
"real_round", "imag_round", "emax", "emin", "subnormalize",
"trap_underflow", "trap_overflow", "trap_inexact",
"trap_invalid", "trap_erange", "trap_divzero", "allow_complex",
"rational_division", "allow_release_gil", NULL };
/* Create an empty dummy tuple to use for args. */
if (!(args = PyTuple_New(0))) {
return 0;
}
/* Convert the trap bit positions into ints for the benefit of
* PyArg_ParseTupleAndKeywords().
*/
x_trap_underflow = ctxt->ctx.traps & TRAP_UNDERFLOW;
x_trap_overflow = ctxt->ctx.traps & TRAP_OVERFLOW;
x_trap_inexact = ctxt->ctx.traps & TRAP_INEXACT;
x_trap_invalid = ctxt->ctx.traps & TRAP_INVALID;
x_trap_erange = ctxt->ctx.traps & TRAP_ERANGE;
x_trap_divzero = ctxt->ctx.traps & TRAP_DIVZERO;
if (!(PyArg_ParseTupleAndKeywords(args, kwargs,
"|llliiilliiiiiiiiii", kwlist,
&ctxt->ctx.mpfr_prec,
&ctxt->ctx.real_prec,
&ctxt->ctx.imag_prec,
&ctxt->ctx.mpfr_round,
&ctxt->ctx.real_round,
&ctxt->ctx.imag_round,
&ctxt->ctx.emax,
&ctxt->ctx.emin,
&ctxt->ctx.subnormalize,
&x_trap_underflow,
&x_trap_overflow,
&x_trap_inexact,
&x_trap_invalid,
&x_trap_erange,
&x_trap_divzero,
&ctxt->ctx.allow_complex,
&ctxt->ctx.rational_division,
&ctxt->ctx.allow_release_gil))) {
VALUE_ERROR("invalid keyword arguments for context");
Py_DECREF(args);
return 0;
}
Py_DECREF(args);
ctxt->ctx.traps = TRAP_NONE;
if (x_trap_underflow)
ctxt->ctx.traps |= TRAP_UNDERFLOW;
if (x_trap_overflow)
ctxt->ctx.traps |= TRAP_OVERFLOW;
if (x_trap_inexact)
ctxt->ctx.traps |= TRAP_INEXACT;
if (x_trap_invalid)
ctxt->ctx.traps |= TRAP_INVALID;
if (x_trap_erange)
ctxt->ctx.traps |= TRAP_ERANGE;
if (x_trap_divzero)
ctxt->ctx.traps |= TRAP_DIVZERO;
if (ctxt->ctx.subnormalize)
ctxt->ctx.subnormalize = 1;
/* Sanity check for values. */
if (ctxt->ctx.mpfr_prec < MPFR_PREC_MIN ||
ctxt->ctx.mpfr_prec > MPFR_PREC_MAX) {
VALUE_ERROR("invalid value for precision");
return 0;
}
if (!(ctxt->ctx.real_prec == GMPY_DEFAULT ||
(ctxt->ctx.real_prec >= MPFR_PREC_MIN &&
ctxt->ctx.real_prec <= MPFR_PREC_MAX))) {
VALUE_ERROR("invalid value for real_prec");
return 0;
}
if (!(ctxt->ctx.imag_prec == GMPY_DEFAULT ||
(ctxt->ctx.imag_prec >= MPFR_PREC_MIN &&
ctxt->ctx.imag_prec <= MPFR_PREC_MAX))) {
VALUE_ERROR("invalid value for imag_prec");
return 0;
}
if (!(ctxt->ctx.mpfr_round == MPFR_RNDN ||
ctxt->ctx.mpfr_round == MPFR_RNDZ ||
ctxt->ctx.mpfr_round == MPFR_RNDU ||
ctxt->ctx.mpfr_round == MPFR_RNDD ||
ctxt->ctx.mpfr_round == MPFR_RNDA)) {
VALUE_ERROR("invalid value for round");
return 0;
}
if (ctxt->ctx.mpfr_round == MPFR_RNDA) {
/* Since RNDA is not supported for MPC, set the MPC rounding modes
* to MPFR_RNDN.
*/
ctxt->ctx.real_round = MPFR_RNDN;
ctxt->ctx.imag_round = MPFR_RNDN;
}
if (!(ctxt->ctx.real_round == MPFR_RNDN ||
ctxt->ctx.real_round == MPFR_RNDZ ||
ctxt->ctx.real_round == MPFR_RNDU ||
ctxt->ctx.real_round == MPFR_RNDD ||
ctxt->ctx.real_round == GMPY_DEFAULT)) {
VALUE_ERROR("invalid value for real_round");
return 0;
}
if (!(ctxt->ctx.imag_round == MPFR_RNDN ||
ctxt->ctx.imag_round == MPFR_RNDZ ||
ctxt->ctx.imag_round == MPFR_RNDU ||
ctxt->ctx.imag_round == MPFR_RNDD ||
ctxt->ctx.imag_round == GMPY_DEFAULT)) {
VALUE_ERROR("invalid value for imag_round");
return 0;
}
if (ctxt->ctx.emin < mpfr_get_emin_min() ||
ctxt->ctx.emin > mpfr_get_emin_max()) {
VALUE_ERROR("invalid value for emin");
return 0;
}
if (ctxt->ctx.emax < mpfr_get_emax_min() ||
ctxt->ctx.emax > mpfr_get_emax_max()) {
VALUE_ERROR("invalid value for emax");
return 0;
}
return 1;
}
PyDoc_STRVAR(GMPy_doc_local_context,
"local_context(**kwargs) -> context\n"
"local_context(context, /, **kwargs) -> context\n\n"
"Return a new context for controlling gmpy2 arithmetic, based either\n"
"on the current context or on a ctx value. Context options additionally\n"
"can be overriden by keyword arguments.");
static PyObject *
GMPy_CTXT_Local(PyObject *self, PyObject *args, PyObject *kwargs)
{
CTXT_Object *result = NULL;
PyObject *temp = NULL;
if (PyErr_WarnFormat(PyExc_DeprecationWarning, 1,
"local_context() is deprecated, "
"use context(get_context()) instead.")) {
return NULL;
}
if (PyTuple_GET_SIZE(args) == 0) {
if (!(temp = GMPy_CTXT_Get(NULL, NULL))) {
/* LCOV_EXCL_START */
return NULL;
/* LCOV_EXCL_STOP */
}
if (!(result = (CTXT_Object*)GMPy_CTXT_Copy(temp, NULL))) {
/* LCOV_EXCL_START */
return NULL;
/* LCOV_EXCL_STOP */
}
Py_DECREF(temp);
}
else if (PyTuple_GET_SIZE(args) == 1 && CTXT_Check(PyTuple_GET_ITEM(args, 0))) {
if (!(result = (CTXT_Object*)GMPy_CTXT_Copy(PyTuple_GET_ITEM(args, 0), NULL))) {
/* LCOV_EXCL_START */
return NULL;
/* LCOV_EXCL_STOP */
}
}
else {
VALUE_ERROR("local_context() only supports [[context][,keyword]] arguments");
return NULL;
}
if (!_parse_context_args(result, kwargs)) {
/* There was an error parsing the keyword arguments. */
Py_DECREF((PyObject*)result);
return NULL;
}
else {
/* Parsing was successful. */
return (PyObject*)result;
}
}
PyDoc_STRVAR(GMPy_doc_context,
"context(**kwargs)\n"
"context(ctx, /, **kwargs)\n\n"
"Return a new context for controlling gmpy2 arithmetic, based either\n"
"on the default context or on a given by ctx value. Context options\n"
"additionally can be overriden by keyword arguments.");
static PyObject *
GMPy_CTXT_Context(PyTypeObject *type, PyObject *args, PyObject *kwargs)
{
CTXT_Object *result = NULL;
if (PyTuple_GET_SIZE(args) == 0) {
if (!(result = (CTXT_Object*)GMPy_CTXT_New())) {
/* LCOV_EXCL_START */
return NULL;
/* LCOV_EXCL_STOP */
}
}
else if (PyTuple_GET_SIZE(args) == 1 && CTXT_Check(PyTuple_GET_ITEM(args, 0))) {
if (!(result = (CTXT_Object*)GMPy_CTXT_Copy(PyTuple_GET_ITEM(args, 0), NULL))) {
/* LCOV_EXCL_START */
return NULL;
/* LCOV_EXCL_STOP */
}
}
else {
VALUE_ERROR("context() only supports [[context][,keyword]] arguments");
return NULL;
}
if (!_parse_context_args(result, kwargs)) {
/* There was an error parsing the keyword arguments. */
Py_DECREF((PyObject*)result);
return NULL;
}
else {
/* Parsing was successful. */
return (PyObject*)result;
}
}
PyDoc_STRVAR(GMPy_doc_context_clear_flags,
"clear_flags() -> None\n\n"
"Clear all MPFR exception flags.");
static PyObject *
GMPy_CTXT_Clear_Flags(PyObject *self, PyObject *args)
{
((CTXT_Object*)self)->ctx.underflow = 0;
((CTXT_Object*)self)->ctx.overflow = 0;
((CTXT_Object*)self)->ctx.inexact = 0;
((CTXT_Object*)self)->ctx.invalid = 0;
((CTXT_Object*)self)->ctx.erange = 0;
((CTXT_Object*)self)->ctx.divzero = 0;
Py_RETURN_NONE;
}
/* Define the get/set functions. */
#define GETSET_BOOLEAN(NAME) \
static PyObject * \
GMPy_CTXT_Get_##NAME(CTXT_Object *self, void *closure) \
{ \
return PyBool_FromLong(self->ctx.NAME); \
}; \
static int \
GMPy_CTXT_Set_##NAME(CTXT_Object *self, PyObject *value, void *closure) \
{ \
if (!(PyBool_Check(value))) { \
TYPE_ERROR(#NAME " must be True or False"); \
return -1; \
} \
self->ctx.NAME = Py_IsTrue(value) ? 1 : 0; \
return 0; \
}
/* Define the get/set functions. This version works with the individual
* bits in the traps field.
*/
#define GETSET_BOOLEAN_BIT(NAME, TRAP) \
static PyObject * \
GMPy_CTXT_Get_##NAME(CTXT_Object *self, void *closure) \
{ \
return PyBool_FromLong(self->ctx.traps & TRAP); \
}; \
static int \
GMPy_CTXT_Set_##NAME(CTXT_Object *self, PyObject *value, void *closure) \
{ \
if (!(PyBool_Check(value))) { \
TYPE_ERROR(#NAME " must be True or False"); \
return -1; \
} \
if (Py_IsTrue(value)) \
self->ctx.traps |= TRAP; \
else \
self->ctx.traps &= ~(TRAP); \
return 0; \
}
GETSET_BOOLEAN(subnormalize);
GETSET_BOOLEAN(underflow);
GETSET_BOOLEAN(overflow);
GETSET_BOOLEAN(inexact);
GETSET_BOOLEAN(invalid);
GETSET_BOOLEAN(erange);
GETSET_BOOLEAN(divzero);
GETSET_BOOLEAN_BIT(trap_underflow, TRAP_UNDERFLOW);
GETSET_BOOLEAN_BIT(trap_overflow, TRAP_OVERFLOW);
GETSET_BOOLEAN_BIT(trap_inexact, TRAP_INEXACT);
GETSET_BOOLEAN_BIT(trap_invalid, TRAP_INVALID);
GETSET_BOOLEAN_BIT(trap_erange, TRAP_ERANGE);
GETSET_BOOLEAN_BIT(trap_divzero, TRAP_DIVZERO);
GETSET_BOOLEAN(allow_complex)
GETSET_BOOLEAN(rational_division)
GETSET_BOOLEAN(allow_release_gil)
PyDoc_STRVAR(GMPy_doc_CTXT_subnormalize,
"The usual IEEE-754 floating point representation supports gradual\n"
"underflow when the minimum exponent is reached. The MFPR library\n"
"does not enable gradual underflow by default but it can be enabled\n"
"to precisely mimic the results of IEEE-754 floating point operations.");
PyDoc_STRVAR(GMPy_doc_CTXT_trap_underflow,
"If set to `False`, a result that is smaller than the smallest possible\n"
"`mpfr` given the current exponent range will be replaced by +/-0.0.\n"
"If set to `True`, an `UnderflowResultError` exception is raised.");
PyDoc_STRVAR(GMPy_doc_CTXT_underflow,
"This flag is not user controllable. It is automatically set if a\n"
"result underflowed to +/-0.0 and `trap_underflow` is `False`.");
PyDoc_STRVAR(GMPy_doc_CTXT_trap_overflow,
"If set to `False`, a result that is larger than the largest possible\n"
"`mpfr` given the current exponent range will be replaced by +/-Infinity.\n"
"If set to `True`, an `OverflowResultError` exception is raised.");
PyDoc_STRVAR(GMPy_doc_CTXT_overflow,
"This flag is not user controllable. It is automatically set if a\n"
"result overflowed to +/-Infinity and `trap_overflow` is `False`.");
PyDoc_STRVAR(GMPy_doc_CTXT_trap_inexact,
"This attribute controls whether or not an `InexactResultError` exception\n"
"is raised if an inexact result is returned. To check if the result is\n"
"greater or less than the exact result, check the rc attribute of\n"
"the `mpfr` result.");
PyDoc_STRVAR(GMPy_doc_CTXT_inexact,
"This flag is not user controllable. It is automatically set\n"
"if an inexact result is returned.");
PyDoc_STRVAR(GMPy_doc_CTXT_trap_invalid,
"This attribute controls whether or not an `InvalidOperationError`\n"
"exception is raised if a numerical result is not defined. A\n"
"special NaN (Not-A-Number) value will be returned if an exception\n"
"is not raised. The `InvalidOperationError` is a sub-class of\n"
"Python’s `ValueError`.\n\nFor example, gmpy2.sqrt(-2) will normally\n"
"return mpfr(‘nan’). However, if `allow_complex` is set to `True`,\n"
"then an `mpc` result will be returned.");
PyDoc_STRVAR(GMPy_doc_CTXT_invalid,
"This flag is not user controllable. It is automatically set if an\n"
"invalid (Not-A-Number) result is returned.");
PyDoc_STRVAR(GMPy_doc_CTXT_trap_erange,
"This attribute controls whether or not a `RangeError` exception is\n"
"raised when certain operations are performed on NaN and/or Infinity\n"
"values. Setting `trap_erange` to `True` can be used to raise an exception\n"
"if comparisons are attempted with a NaN.");
PyDoc_STRVAR(GMPy_doc_CTXT_erange,
"This flag is not user controllable. It is automatically\n"
"set if an erange error occurred.");
PyDoc_STRVAR(GMPy_doc_CTXT_trap_divzero,
"This attribute controls whether or not a `DivisionByZeroError` exception\n"
"is raised if division by 0 occurs. The `DivisionByZeroError` is a\n"
"sub-class of Python’s `ZeroDivisionError`.");
PyDoc_STRVAR(GMPy_doc_CTXT_divzero,
"This flag is not user controllable. It is automatically set if a\n"
"division by zero occurred and NaN result was returned.");
PyDoc_STRVAR(GMPy_doc_CTXT_allow_complex,
"This attribute controls whether or not an `mpc` result can be returned\n"
"if an `mpfr` result would normally not be possible.");
PyDoc_STRVAR(GMPy_doc_CTXT_rational_division,
"If set to `True`, `mpz` / `mpz` will return an `mpq` instead of an `mpfr`.");
PyDoc_STRVAR(GMPy_doc_CTXT_allow_release_gil,
"If set to `True`, many `mpz` and `mpq` computations will release the GIL.\n\n"
"This is considered an experimental feature.");
PyDoc_STRVAR(GMPy_doc_CTXT_precision,
"This attribute controls the precision of an `mpfr` result. The\n"
"precision is specified in bits, not decimal digits. The maximum\n"
"precision that can be specified is platform dependent and can be\n"
"retrieved with `get_max_precision()`.\n\n"
"Note: Specifying a value for precision that is too close to the\n"
"maximum precision will cause the MPFR library to fail.");
static PyObject *
GMPy_CTXT_Get_precision(CTXT_Object *self, void *closure)
{
return PyLong_FromSsize_t((Py_ssize_t)(self->ctx.mpfr_prec));
}
static int
GMPy_CTXT_Set_precision(CTXT_Object *self, PyObject *value, void *closure)
{
Py_ssize_t temp;
if (!(PyLong_Check(value))) {
TYPE_ERROR("precision must be Python integer");
return -1;
}
temp = PyLong_AsSsize_t(value);
/* A return value of -1 indicates an error has occurred. Since -1 is not
* a legal value, we don't specifically check for an error condition.
*/
if (temp < MPFR_PREC_MIN || temp > MPFR_PREC_MAX) {
VALUE_ERROR("invalid value for precision");
return -1;
}
self->ctx.mpfr_prec = (mpfr_prec_t)temp;
return 0;
}
PyDoc_STRVAR(GMPy_doc_CTXT_real_prec,
"This attribute controls the precision of the real part of an `mpc`\n"
"result. If the value is Default, then the value of the `precision`\n"
"attribute is used.");
static PyObject *
GMPy_CTXT_Get_real_prec(CTXT_Object *self, void *closure)
{
return PyLong_FromSsize_t((Py_ssize_t)(GET_REAL_PREC(self)));
}
static int
GMPy_CTXT_Set_real_prec(CTXT_Object *self, PyObject *value, void *closure)
{
Py_ssize_t temp;
if (!(PyLong_Check(value))) {
TYPE_ERROR("real_prec must be Python integer");
return -1;
}
temp = PyLong_AsSsize_t(value);
/* A return value of -1 indicates an error has occurred. Since -1 is not
* a legal value, we don't specifically check for an error condition.
*/
if (temp < MPFR_PREC_MIN || temp > MPFR_PREC_MAX) {
VALUE_ERROR("invalid value for real_prec");
return -1;
}
self->ctx.real_prec = (mpfr_prec_t)temp;
return 0;
}
PyDoc_STRVAR(GMPy_doc_CTXT_imag_prec,
"This attribute controls the precision of the imaginary part of an `mpc`\n"
"result. If the value is Default, then the value of `real_prec` is used.");
static PyObject *
GMPy_CTXT_Get_imag_prec(CTXT_Object *self, void *closure)
{
return PyLong_FromSsize_t((Py_ssize_t)(GET_IMAG_PREC(self)));
}
static int
GMPy_CTXT_Set_imag_prec(CTXT_Object *self, PyObject *value, void *closure)
{
Py_ssize_t temp;
if (!(PyLong_Check(value))) {
TYPE_ERROR("imag_prec must be Python integer");
return -1;
}
temp = PyLong_AsSsize_t(value);
/* A return value of -1 indicates an error has occurred. Since -1 is not
* a legal value, we don't specifically check for an error condition.
*/
if (temp < MPFR_PREC_MIN || temp > MPFR_PREC_MAX) {
VALUE_ERROR("invalid value for imag_prec");
return -1;
}
self->ctx.imag_prec = (mpfr_prec_t)temp;
return 0;
}
PyDoc_STRVAR(GMPy_doc_CTXT_round,
"There are five rounding modes available to `mpfr` type:\n\n"
" * RoundAwayZero - The result is rounded away from 0.0.\n"
" * RoundDown - The result is rounded towards -Infinity.\n"
" * RoundToNearest - Round to the nearest value; ties are rounded to an even value.\n"
" * RoundToZero - The result is rounded towards 0.0.\n"
" * RoundUp - The result is rounded towards +Infinity.");
static PyObject *
GMPy_CTXT_Get_round(CTXT_Object *self, void *closure)
{
return PyLong_FromLong((long)(self->ctx.mpfr_round));
}
static int
GMPy_CTXT_Set_round(CTXT_Object *self, PyObject *value, void *closure)
{
long temp;
if (!(PyLong_Check(value))) {
TYPE_ERROR("round mode must be Python integer");
return -1;
}
temp = PyLong_AsLong(value);
if (temp == -1 && PyErr_Occurred()) {
VALUE_ERROR("invalid value for round mode");
return -1;
}
if (temp == MPFR_RNDN)
self->ctx.mpfr_round = MPFR_RNDN;
else if (temp == MPFR_RNDZ)
self->ctx.mpfr_round = MPFR_RNDZ;
else if (temp == MPFR_RNDU)
self->ctx.mpfr_round = MPFR_RNDU;
else if (temp == MPFR_RNDD)
self->ctx.mpfr_round = MPFR_RNDD;
else if (temp == MPFR_RNDA) {
self->ctx.mpfr_round = MPFR_RNDA;
/* Since RNDA is not supported for MPC, set the MPC rounding modes
to MPFR_RNDN. */
self->ctx.real_round = MPFR_RNDN;
self->ctx.imag_round = MPFR_RNDN;
}
else {
VALUE_ERROR("invalid value for round mode");
return -1;
}
return 0;
}
PyDoc_STRVAR(GMPy_doc_CTXT_real_round,
"This attribute controls the rounding mode for the real part of an\n"
"`mpc` result. If the value is Default, then the value of the round\n"
"attribute is used. Note: RoundAwayZero is not a valid rounding mode for `mpc`.");
static PyObject *
GMPy_CTXT_Get_real_round(CTXT_Object *self, void *closure)
{
return PyLong_FromLong((long)GET_REAL_ROUND(self));
}
static int
GMPy_CTXT_Set_real_round(CTXT_Object *self, PyObject *value, void *closure)
{
long temp;
if (!(PyLong_Check(value))) {
TYPE_ERROR("round mode must be Python integer");
return -1;
}
temp = PyLong_AsLong(value);
if (temp == -1 && PyErr_Occurred()) {
VALUE_ERROR("invalid value for round mode");
return -1;
}
if (temp == GMPY_DEFAULT || temp == MPFR_RNDN || temp == MPFR_RNDZ ||
temp == MPFR_RNDU || temp == MPFR_RNDD) {
self->ctx.real_round = (int)temp;
}
else {
VALUE_ERROR("invalid value for round mode");
return -1;
}
return 0;
}
PyDoc_STRVAR(GMPy_doc_CTXT_imag_round,
"This attribute controls the rounding mode for the imaginary part of an\n"
"`mpc` result. If the value is Default, then the value of the `real_round`\n"
"attribute is used. Note: RoundAwayZero is not a valid rounding mode for `mpc`.");
static PyObject *
GMPy_CTXT_Get_imag_round(CTXT_Object *self, void *closure)
{
return PyLong_FromLong((long)GET_IMAG_ROUND(self));
}
static int
GMPy_CTXT_Set_imag_round(CTXT_Object *self, PyObject *value, void *closure)
{
long temp;
if (!(PyLong_Check(value))) {
TYPE_ERROR("round mode must be Python integer");
return -1;
}
temp = PyLong_AsLong(value);
if (temp == -1 && PyErr_Occurred()) {
VALUE_ERROR("invalid value for round mode");
return -1;
}
if (temp == GMPY_DEFAULT || temp == MPFR_RNDN || temp == MPFR_RNDZ ||
temp == MPFR_RNDU || temp == MPFR_RNDD) {
self->ctx.imag_round = (int)temp;
}
else {
VALUE_ERROR("invalid value for round mode");
return -1;
}
return 0;
}
PyDoc_STRVAR(GMPy_doc_CTXT_emin,
"This attribute controls the minimum allowed exponent of an `mpfr`\n"
"result. The minimum exponent is platform dependent and can be\n"
"retrieved with `get_emin_min()`.");
static PyObject *
GMPy_CTXT_Get_emin(CTXT_Object *self, void *closure)
{
return PyLong_FromLong(self->ctx.emin);
}
static int
GMPy_CTXT_Set_emin(CTXT_Object *self, PyObject *value, void *closure)
{
long exp;
if (!(PyLong_Check(value))) {
TYPE_ERROR("emin must be Python integer");
return -1;
}
exp = PyLong_AsLong(value);
if (exp == -1 && PyErr_Occurred()) {
VALUE_ERROR("requested minimum exponent is invalid");
return -1;
}
if (!(exp >= MPFR_EMIN_MIN && exp <= MPFR_EMIN_MAX)) {
VALUE_ERROR("requested minimum exponent is invalid");
return -1;
}
self->ctx.emin = exp;
return 0;
}
PyDoc_STRVAR(GMPy_doc_CTXT_emax,
"This attribute controls the maximum allowed exponent of an `mpfr`\n"
"result. The maximum exponent is platform dependent and can be\n"
"retrieved with `get_emax_max()`.");
static PyObject *
GMPy_CTXT_Get_emax(CTXT_Object *self, void *closure)
{
return PyLong_FromLong(self->ctx.emax);
}
static int
GMPy_CTXT_Set_emax(CTXT_Object *self, PyObject *value, void *closure)
{
long exp;
if (!(PyLong_Check(value))) {
TYPE_ERROR("emax must be Python integer");
return -1;
}
exp = PyLong_AsLong(value);
if (exp == -1 && PyErr_Occurred()) {
VALUE_ERROR("requested maximum exponent is invalid");
return -1;
}
if (!(exp >= MPFR_EMAX_MIN && exp <= MPFR_EMAX_MAX)) {
VALUE_ERROR("requested maximum exponent is invalid");
return -1;
}
self->ctx.emax = exp;
return 0;
}
#define ADD_GETSET(NAME) \
{#NAME, \
(getter)GMPy_CTXT_Get_##NAME, \
(setter)GMPy_CTXT_Set_##NAME, GMPy_doc_CTXT_##NAME, NULL}
static PyGetSetDef GMPyContext_getseters[] = {
ADD_GETSET(precision),
ADD_GETSET(real_prec),
ADD_GETSET(imag_prec),
ADD_GETSET(round),
ADD_GETSET(real_round),
ADD_GETSET(imag_round),
ADD_GETSET(emax),
ADD_GETSET(emin),
ADD_GETSET(subnormalize),
ADD_GETSET(underflow),
ADD_GETSET(overflow),
ADD_GETSET(inexact),
ADD_GETSET(invalid),
ADD_GETSET(erange),
ADD_GETSET(divzero),
ADD_GETSET(trap_underflow),
ADD_GETSET(trap_overflow),
ADD_GETSET(trap_inexact),
ADD_GETSET(trap_invalid),
ADD_GETSET(trap_erange),
ADD_GETSET(trap_divzero),
ADD_GETSET(allow_complex),
ADD_GETSET(rational_division),
ADD_GETSET(allow_release_gil),
{NULL}
};
static PyMethodDef GMPyContext_methods[] =
{
{ "abs", GMPy_Context_Abs, METH_O, GMPy_doc_context_abs },
{ "acos", GMPy_Context_Acos, METH_O, GMPy_doc_context_acos },
{ "acosh", GMPy_Context_Acosh, METH_O, GMPy_doc_context_acosh },
{ "add", GMPy_Context_Add, METH_VARARGS, GMPy_doc_context_add },
{ "agm", GMPy_Context_AGM, METH_VARARGS, GMPy_doc_context_agm },
{ "ai", GMPy_Context_Ai, METH_O, GMPy_doc_context_ai },
{ "asin", GMPy_Context_Asin, METH_O, GMPy_doc_context_asin },
{ "asinh", GMPy_Context_Asinh, METH_O, GMPy_doc_context_asinh },
{ "atan", GMPy_Context_Atan, METH_O, GMPy_doc_context_atan },
{ "atanh", GMPy_Context_Atanh, METH_O, GMPy_doc_context_atanh },
{ "atan2", GMPy_Context_Atan2, METH_VARARGS, GMPy_doc_context_atan2 },
{ "clear_flags", GMPy_CTXT_Clear_Flags, METH_NOARGS, GMPy_doc_context_clear_flags },
{ "cbrt", GMPy_Context_Cbrt, METH_O, GMPy_doc_context_cbrt },
{ "ceil", GMPy_Context_Ceil, METH_O, GMPy_doc_context_ceil },
{ "check_range", GMPy_Context_CheckRange, METH_O, GMPy_doc_context_check_range },
{ "const_catalan", GMPy_Context_Const_Catalan, METH_NOARGS, GMPy_doc_context_const_catalan },
{ "const_euler", GMPy_Context_Const_Euler, METH_NOARGS, GMPy_doc_context_const_euler },
{ "const_log2", GMPy_Context_Const_Log2, METH_NOARGS, GMPy_doc_context_const_log2 },
{ "const_pi", GMPy_Context_Const_Pi, METH_NOARGS, GMPy_doc_context_const_pi },
{ "cos", GMPy_Context_Cos, METH_O, GMPy_doc_context_cos },
{ "cosh", GMPy_Context_Cosh, METH_O, GMPy_doc_context_cosh },
{ "cot", GMPy_Context_Cot, METH_O, GMPy_doc_context_cot },
{ "coth", GMPy_Context_Coth, METH_O, GMPy_doc_context_coth },
{ "copy", GMPy_CTXT_Copy, METH_NOARGS, GMPy_doc_context_copy },
{ "csc", GMPy_Context_Csc, METH_O, GMPy_doc_context_csc },
{ "csch", GMPy_Context_Csch, METH_O, GMPy_doc_context_csch },
{ "degrees", GMPy_Context_Degrees, METH_O, GMPy_doc_context_degrees },
{ "digamma", GMPy_Context_Digamma, METH_O, GMPy_doc_context_digamma },
{ "div", GMPy_Context_TrueDiv, METH_VARARGS, GMPy_doc_context_truediv },
{ "divmod", GMPy_Context_DivMod, METH_VARARGS, GMPy_doc_context_divmod },
{ "div_2exp", GMPy_Context_Div_2exp, METH_VARARGS, GMPy_doc_context_div_2exp },
{ "eint", GMPy_Context_Eint, METH_O, GMPy_doc_context_eint },
{ "erf", GMPy_Context_Erf, METH_O, GMPy_doc_context_erf },
{ "erfc", GMPy_Context_Erfc, METH_O, GMPy_doc_context_erfc },
{ "exp", GMPy_Context_Exp, METH_O, GMPy_doc_context_exp },
{ "expm1", GMPy_Context_Expm1, METH_O, GMPy_doc_context_expm1 },
{ "exp10", GMPy_Context_Exp10, METH_O, GMPy_doc_context_exp10 },
{ "exp2", GMPy_Context_Exp2, METH_O, GMPy_doc_context_exp2 },
{ "factorial", GMPy_Context_Factorial, METH_O, GMPy_doc_context_factorial },
{ "floor", GMPy_Context_Floor, METH_O, GMPy_doc_context_floor },
{ "floor_div", GMPy_Context_FloorDiv, METH_VARARGS, GMPy_doc_context_floordiv },
{ "fma", GMPy_Context_FMA, METH_VARARGS, GMPy_doc_context_fma },
{ "fms", GMPy_Context_FMS, METH_VARARGS, GMPy_doc_context_fms },
#if MPFR_VERSION_MAJOR > 3
{ "fmma", GMPy_Context_FMMA, METH_VARARGS, GMPy_doc_context_fmma },
{ "fmms", GMPy_Context_FMMS, METH_VARARGS, GMPy_doc_context_fmms },
#endif
{ "fmod", GMPy_Context_Fmod, METH_VARARGS, GMPy_doc_context_fmod },
{ "frac", GMPy_Context_Frac, METH_O, GMPy_doc_context_frac },
{ "frexp", GMPy_Context_Frexp, METH_O, GMPy_doc_context_frexp },
{ "fsum", GMPy_Context_Fsum, METH_O, GMPy_doc_context_fsum },
{ "gamma", GMPy_Context_Gamma, METH_O, GMPy_doc_context_gamma },
{ "gamma_inc", GMPy_Context_Gamma_Inc, METH_VARARGS, GMPy_doc_context_gamma_inc },
{ "hypot", GMPy_Context_Hypot, METH_VARARGS, GMPy_doc_context_hypot },
{ "is_finite", GMPy_Context_Is_Finite, METH_O, GMPy_doc_context_is_finite },
{ "is_infinite", GMPy_Context_Is_Infinite, METH_O, GMPy_doc_context_is_infinite },
{ "is_integer", GMPy_Context_Is_Integer, METH_O, GMPy_doc_context_is_integer },
{ "is_nan", GMPy_Context_Is_NAN, METH_O, GMPy_doc_context_is_nan },
{ "is_regular", GMPy_Context_Is_Regular, METH_O, GMPy_doc_context_is_regular },
{ "is_signed", GMPy_Context_Is_Signed, METH_O, GMPy_doc_context_is_signed },
{ "is_zero", GMPy_Context_Is_Zero, METH_O, GMPy_doc_context_is_zero },
{ "jn", GMPy_Context_Jn, METH_VARARGS, GMPy_doc_context_jn },
{ "j0", GMPy_Context_J0, METH_O, GMPy_doc_context_j0 },
{ "j1", GMPy_Context_J1, METH_O, GMPy_doc_context_j1 },
{ "li2", GMPy_Context_Li2, METH_O, GMPy_doc_context_li2 },
{ "lgamma", GMPy_Context_Lgamma, METH_O, GMPy_doc_context_lgamma },
{ "lngamma", GMPy_Context_Lngamma, METH_O, GMPy_doc_context_lngamma },
{ "log", GMPy_Context_Log, METH_O, GMPy_doc_context_log },
{ "log10", GMPy_Context_Log10, METH_O, GMPy_doc_context_log10 },
{ "log1p", GMPy_Context_Log1p, METH_O, GMPy_doc_context_log1p },
{ "log2", GMPy_Context_Log2, METH_O, GMPy_doc_context_log2 },
{ "maxnum", GMPy_Context_Maxnum, METH_VARARGS, GMPy_doc_context_maxnum },
{ "minnum", GMPy_Context_Minnum, METH_VARARGS, GMPy_doc_context_minnum },
{ "minus", GMPy_Context_Minus, METH_VARARGS, GMPy_doc_context_minus },
{ "mod", GMPy_Context_Mod, METH_VARARGS, GMPy_doc_context_mod },
{ "modf", GMPy_Context_Modf, METH_O, GMPy_doc_context_modf },
{ "mul", GMPy_Context_Mul, METH_VARARGS, GMPy_doc_context_mul },
{ "mul_2exp", GMPy_Context_Mul_2exp, METH_VARARGS, GMPy_doc_context_mul_2exp },
{ "next_above", GMPy_Context_NextAbove, METH_O, GMPy_doc_context_next_above },
{ "next_below", GMPy_Context_NextBelow, METH_O, GMPy_doc_context_next_below },
{ "next_toward", GMPy_Context_NextToward, METH_VARARGS, GMPy_doc_context_next_toward },
{ "norm", GMPy_Context_Norm, METH_O, GMPy_doc_context_norm },
{ "phase", GMPy_Context_Phase, METH_O, GMPy_doc_context_phase },
{ "plus", GMPy_Context_Plus, METH_VARARGS, GMPy_doc_context_plus },
{ "polar", GMPy_Context_Polar, METH_O, GMPy_doc_context_polar },
{ "proj", GMPy_Context_Proj, METH_O, GMPy_doc_context_proj },
{ "pow", GMPy_Context_Pow, METH_VARARGS, GMPy_doc_context_pow },
{ "radians", GMPy_Context_Radians, METH_O, GMPy_doc_context_radians },
{ "rect", GMPy_Context_Rect, METH_VARARGS, GMPy_doc_context_rect },
{ "rec_sqrt", GMPy_Context_RecSqrt, METH_O, GMPy_doc_context_rec_sqrt },
{ "reldiff", GMPy_Context_RelDiff, METH_VARARGS, GMPy_doc_context_reldiff },
{ "remainder", GMPy_Context_Remainder, METH_VARARGS, GMPy_doc_context_remainder },
{ "remquo", GMPy_Context_RemQuo, METH_VARARGS, GMPy_doc_context_remquo },
{ "rint", GMPy_Context_Rint, METH_O, GMPy_doc_context_rint },
{ "rint_ceil", GMPy_Context_RintCeil, METH_O, GMPy_doc_context_rint_ceil },
{ "rint_floor", GMPy_Context_RintFloor, METH_O, GMPy_doc_context_rint_floor },
{ "rint_round", GMPy_Context_RintRound, METH_O, GMPy_doc_context_rint_round },
{ "rint_trunc", GMPy_Context_RintTrunc, METH_O, GMPy_doc_context_rint_trunc },
{ "root", GMPy_Context_Root, METH_VARARGS, GMPy_doc_context_root },
{ "rootn", GMPy_Context_Rootn, METH_VARARGS, GMPy_doc_context_rootn },
{ "root_of_unity", GMPy_Context_Root_Of_Unity, METH_VARARGS, GMPy_doc_context_root_of_unity },
{ "round2", GMPy_Context_Round2, METH_VARARGS, GMPy_doc_context_round2 },
{ "round_away", GMPy_Context_RoundAway, METH_O, GMPy_doc_context_round_away },
{ "sec", GMPy_Context_Sec, METH_O, GMPy_doc_context_sec },
{ "sech", GMPy_Context_Sech, METH_O, GMPy_doc_context_sech },
{ "sin", GMPy_Context_Sin, METH_O, GMPy_doc_context_sin },
{ "sin_cos", GMPy_Context_Sin_Cos, METH_O, GMPy_doc_context_sin_cos },
{ "sinh", GMPy_Context_Sinh, METH_O, GMPy_doc_context_sinh },
{ "sinh_cosh", GMPy_Context_Sinh_Cosh, METH_O, GMPy_doc_context_sinh_cosh },
{ "sqrt", GMPy_Context_Sqrt, METH_O, GMPy_doc_context_sqrt },
{ "square", GMPy_Context_Square, METH_O, GMPy_doc_context_square },
{ "sub", GMPy_Context_Sub, METH_VARARGS, GMPy_doc_context_sub },
{ "tan", GMPy_Context_Tan, METH_O, GMPy_doc_context_tan },
{ "tanh", GMPy_Context_Tanh, METH_O, GMPy_doc_context_tanh },
{ "trunc", GMPy_Context_Trunc, METH_O, GMPy_doc_context_trunc },
#ifdef VECTOR
{ "vector", GMPy_Context_Vector, METH_O, GMPy_doc_context_vector },
{ "vector2", GMPy_Context_Vector2, METH_VARARGS, GMPy_doc_context_vector2 },
#endif
{ "yn", GMPy_Context_Yn, METH_VARARGS, GMPy_doc_context_yn },
{ "y0", GMPy_Context_Y0, METH_O, GMPy_doc_context_y0 },
{ "y1", GMPy_Context_Y1, METH_O, GMPy_doc_context_y1 },
{ "zeta", GMPy_Context_Zeta, METH_O, GMPy_doc_context_zeta },
{ "__enter__", GMPy_CTXT_Enter, METH_VARARGS, NULL },
{ "__exit__", GMPy_CTXT_Exit, METH_VARARGS, NULL },
{ NULL, NULL, 1 }
};
static PyTypeObject CTXT_Type =
{
PyVarObject_HEAD_INIT(NULL, 0)
.tp_name = "gmpy2.context",
.tp_basicsize = sizeof(CTXT_Object),
.tp_dealloc = (destructor) GMPy_CTXT_Dealloc,
.tp_repr = (reprfunc) GMPy_CTXT_Repr_Slot,
.tp_flags = Py_TPFLAGS_DEFAULT,
.tp_doc = GMPy_doc_context,
.tp_methods = GMPyContext_methods,
.tp_getset = GMPyContext_getseters,
.tp_new = GMPy_CTXT_Context,
};
././@PaxHeader 0000000 0000000 0000000 00000000026 00000000000 010213 x ustar 00 22 mtime=1710307256.0
gmpy2-2.2.1/src/gmpy2_context.h 0000644 0001750 0001750 00000011703 14574233670 015001 0 ustar 00case case /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* gmpy2_context.h *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Python interface to the GMP, MPFR, and MPC multiple precision *
* libraries. *
* *
* Copyright 2000 - 2009 Alex Martelli *
* *
* Copyright 2008 - 2024 Case Van Horsen *
* *
* This file is part of GMPY2. *
* *
* GMPY2 is free software: you can redistribute it and/or modify it under *
* the terms of the GNU Lesser General Public License as published by the *
* Free Software Foundation, either version 3 of the License, or (at your *
* option) any later version. *
* *
* GMPY2 is distributed in the hope that it will be useful, but WITHOUT *
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or *
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public *
* License for more details. *
* *
* You should have received a copy of the GNU Lesser General Public *
* License along with GMPY2; if not, see *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
#ifndef GMPY_CONTEXT_H
#define GMPY_CONTEXT_H
#ifdef __cplusplus
extern "C" {
#endif
#define TRAP_NONE 0
#define TRAP_UNDERFLOW 1
#define TRAP_OVERFLOW 2
#define TRAP_INEXACT 4
#define TRAP_INVALID 8
#define TRAP_ERANGE 16
#define TRAP_DIVZERO 32
/* The actual typedefs have been moved to gmpy2_types.h. */
static PyTypeObject CTXT_Type;
/* CHECK_CONTEXT returns a borrowed reference. */
#define CHECK_CONTEXT(context) \
if (!context) { \
context = (CTXT_Object*)GMPy_CTXT_Get(NULL, NULL); \
if (context == NULL) { \
return NULL; \
} \
Py_DECREF(context); \
}
#define CHECK_CONTEXT_M1(context) \
if (!context) { \
context = (CTXT_Object*)GMPy_CTXT_Get(NULL, NULL); \
if (context == NULL) { \
return -1; \
} \
Py_DECREF(context); \
}
#define GMPY_MAYBE_BEGIN_ALLOW_THREADS(context) { \
PyThreadState *_save; \
_save = GET_THREAD_MODE(context) ? PyEval_SaveThread() : NULL;
#define GMPY_MAYBE_END_ALLOW_THREADS(context) \
if (_save) PyEval_RestoreThread(_save); \
} \
#define CTXT_Check(v) (((PyObject*)v)->ob_type == &CTXT_Type)
#define GET_MPFR_PREC(c) (c->ctx.mpfr_prec)
#define GET_REAL_PREC(c) ((c->ctx.real_prec==GMPY_DEFAULT)?GET_MPFR_PREC(c):c->ctx.real_prec)
#define GET_IMAG_PREC(c) ((c->ctx.imag_prec==GMPY_DEFAULT)?GET_REAL_PREC(c):c->ctx.imag_prec)
#define GET_MPFR_ROUND(c) (c->ctx.mpfr_round)
#define GET_REAL_ROUND(c) ((c->ctx.real_round==GMPY_DEFAULT)?GET_MPFR_ROUND(c):c->ctx.real_round)
#define GET_IMAG_ROUND(c) ((c->ctx.imag_round==GMPY_DEFAULT)?GET_REAL_ROUND(c):c->ctx.imag_round)
#define GET_MPC_ROUND(c) (MPC_RND(GET_REAL_ROUND(c), GET_IMAG_ROUND(c)))
#define GET_DIV_MODE(c) (c->ctx.rational_division)
#define GET_THREAD_MODE(c) (c->ctx.allow_release_gil)
static PyObject * GMPy_CTXT_New(void);
static void GMPy_CTXT_Dealloc(CTXT_Object *self);
static PyObject * GMPy_CTXT_Repr_Slot(CTXT_Object *self);
static PyObject * GMPy_CTXT_Get(PyObject *self, PyObject *args);
static PyObject * GMPy_CTXT_Local(PyObject *self, PyObject *args, PyObject *kwargs);
static PyObject * GMPy_CTXT_Context(PyTypeObject *type, PyObject *args, PyObject *kwargs);
static PyObject * GMPy_CTXT_Set(PyObject *self, PyObject *other);
static PyObject * GMPy_CTXT_Clear_Flags(PyObject *self, PyObject *args);
static PyObject * GMPy_CTXT_Copy(PyObject *self, PyObject *other);
static PyObject * GMPy_CTXT_ieee(PyObject *self, PyObject *args, PyObject *kwargs);
static PyObject * GMPy_CTXT_Enter(PyObject *self, PyObject *args);
static PyObject * GMPy_CTXT_Exit(PyObject *self, PyObject *args);
#ifdef __cplusplus
}
#endif
#endif
././@PaxHeader 0000000 0000000 0000000 00000000026 00000000000 010213 x ustar 00 22 mtime=1721370662.0
gmpy2-2.2.1/src/gmpy2_convert.c 0000644 0001750 0001750 00000024107 14646404046 014767 0 ustar 00case case /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* gmpy_convert.c *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Python interface to the GMP, MPFR, and MPC multiple precision *
* libraries. *
* *
* Copyright 2000 - 2009 Alex Martelli *
* *
* Copyright 2008 - 2024 Case Van Horsen *
* *
* This file is part of GMPY2. *
* *
* GMPY2 is free software: you can redistribute it and/or modify it under *
* the terms of the GNU Lesser General Public License as published by the *
* Free Software Foundation, either version 3 of the License, or (at your *
* option) any later version. *
* *
* GMPY2 is distributed in the hope that it will be useful, but WITHOUT *
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or *
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public *
* License for more details. *
* *
* You should have received a copy of the GNU Lesser General Public *
* License along with GMPY2; if not, see *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
/* This file contains all the conversion functions for gmpy2.
*
* Overview
* --------
* gmpy2 tries to optimize the performance and accuracy of conversions from
* other numeric types. gmpy2 uses a LBYL (Look Before You Leap) approach and
* identifies the numeric type before conversion before conversion to a gmpy2
* type. The basic operations (+, -, *, /) are optimized to directly work with
* some basic types such as C longs or doubles.
*/
/* ======================================================================== *
* Miscellaneous helper functions. *
* ======================================================================== */
/* Since macros are used in gmpy2's codebase, these functions are skipped
* until they are needed for the C API in the future.
*/
#if 0
static int GMPy_isInteger(PyObject *obj)
{
return IS_INTEGER(obj) ? 1 : 0;
}
static int GMPy_isFraction(PyObject *obj)
{
return (!strcmp(Py_TYPE(obj)->tp_name, "Fraction")) ? 1 : 0;
}
static int GMPy_isRational(PyObject *obj)
{
return IS_RATIONAL(obj) ? 1 : 0;
}
static int GMPy_isReal(PyObject *obj)
{
return IS_REAL(obj) ? 1 : 0;
}
static int GMPy_isComplex(PyObject *obj)
{
return IS_COMPLEX(obj) ? 1 : 0;
}
#endif
/* GMPy_ObjectType(PyObject *obj) returns an integer that identifies the
* object's type. See gmpy2_convert.h for details.
*
* Exceptions are never raised.
*/
static inline int GMPy_ObjectType(PyObject *obj)
{
/* Tests are sorted by order by (best guess of) most common argument type.
* Tests that require attribute lookups are done last.
*/
if (MPZ_Check(obj)) return OBJ_TYPE_MPZ;
if (MPFR_Check(obj)) return OBJ_TYPE_MPFR;
if (MPC_Check(obj)) return OBJ_TYPE_MPC;
if (MPQ_Check(obj)) return OBJ_TYPE_MPQ;
if (XMPZ_Check(obj)) return OBJ_TYPE_XMPZ;
if (PyLong_Check(obj)) return OBJ_TYPE_PyInteger;
if (PyFloat_Check(obj)) return OBJ_TYPE_PyFloat;
if (PyComplex_Check(obj)) return OBJ_TYPE_PyComplex;
if (IS_FRACTION(obj)) return OBJ_TYPE_PyFraction;
/* Now we look for the presence of __mpz__, __mpq__, __mpfr__, and __mpc__.
* Since a type may define more than one of the special methods, we perform
* the checks in reverse order.
*/
if (HAS_MPC_CONVERSION(obj)) return OBJ_TYPE_HAS_MPC;
if (HAS_MPFR_CONVERSION(obj)) return OBJ_TYPE_HAS_MPFR;
if (HAS_MPQ_CONVERSION(obj)) return OBJ_TYPE_HAS_MPQ;
if (HAS_MPZ_CONVERSION(obj)) return OBJ_TYPE_HAS_MPZ;
return OBJ_TYPE_UNKNOWN;
}
static PyObject *
GMPy_RemoveIgnoredASCII(PyObject *s)
{
PyObject *ascii_str = NULL, *temp = NULL, *filtered = NULL, *symbol = NULL, *blank = NULL;
if (PyBytes_CheckExact(s)) {
temp = PyUnicode_DecodeASCII(PyBytes_AS_STRING(s), PyBytes_GET_SIZE(s), "strict");
if (!temp) {
VALUE_ERROR("string contains non-ASCII characters");
return NULL;
}
}
else if (PyUnicode_Check(s)) {
Py_INCREF(s);
temp = s;
}
else {
/* LCOV_EXCL_START */
TYPE_ERROR("object is not string or Unicode");
return NULL;
/* LCOV_EXCL_STOP */
}
blank = PyUnicode_FromString("");
symbol = PyUnicode_FromString(" ");
filtered = PyUnicode_Replace(temp, symbol, blank, -1);
Py_XDECREF(symbol);
Py_XDECREF(temp);
temp = filtered;
symbol = PyUnicode_FromString("_");
filtered = PyUnicode_Replace(temp, symbol, blank, -1);
Py_XDECREF(symbol);
Py_XDECREF(temp);
Py_XDECREF(blank);
if (!filtered) {
return NULL;
}
ascii_str = PyUnicode_AsASCIIString(filtered);
Py_DECREF(filtered);
if (!ascii_str) {
VALUE_ERROR("string contains non-ASCII characters");
return NULL;
}
return ascii_str;
}
/* mpz_set_PyStr converts a Python "string" into a mpz_t structure. It accepts
* a sequence of bytes (i.e. str in Python 2, bytes in Python 3) or a Unicode
* string (i.e. unicode in Python 3, str in Python 3). Returns -1 on error,
* 1 if successful.
*/
static int
mpz_set_PyStr(mpz_t z, PyObject *s, int base)
{
char *cp;
int negative = 0;
PyObject *ascii_str;
ascii_str = GMPy_RemoveIgnoredASCII(s);
if (!ascii_str) return -1;
cp = PyBytes_AsString(ascii_str);
if (cp[0] == '+') cp++;
if (cp[0] == '-') {
cp++;
negative = 1;
}
/* Check for leading base indicators. */
if (cp[0] == '0' && cp[1] != '\0') {
if (base == 0) {
/* GMP uses prefix '0' for octal, so set base here. */
if (tolower(cp[1]) == 'o') {
base = 8;
cp += 2;
}
else if (tolower(cp[1]) != 'b' && tolower(cp[1]) != 'x') {
base = 10;
}
}
else {
/* If the specified base matches the leading base indicators,
* then we need to skip the base indicators.
*/
if ((tolower(cp[1]) == 'b' && base == 2) ||
(tolower(cp[1]) == 'o' && base == 8) ||
(tolower(cp[1]) == 'x' && base == 16))
{
cp += 2;
}
}
}
while (cp[0] == '0' && cp[1] != '\0' && base != 0) cp++;
/* delegate rest to GMP's function */
if (-1 == mpz_set_str(z, cp, base)) {
VALUE_ERROR("invalid digits");
Py_DECREF(ascii_str);
return -1;
}
if (negative) {
mpz_neg(z, z);
}
Py_DECREF(ascii_str);
return 1;
}
/* Format an mpz into any base (2 to 62). Bits in the option parameter
* control various behaviors:
* bit 0: if set, output is wrapped with mpz(...) or xmpz(...)
* bit 1: if set, a '+' is included for positive numbers
* bit 2: if set, a ' ' is included for positive nubmers
* bit 3: if set, a '0b', '0o', or '0x' is included for binary, octal, hex
* bit 4: if set, no prefix is included for binary, octal, hex
*
* Note: if neither bit 3 or 4 is set, prefixes that match the platform
* default are included.
*
* If base < 0, capital letters are used.
*
* If which = 0, then mpz formatting is used (if bit 0 set). Otherwise xmpz
* formatting is used (if bit 0 is set).
*/
static char* _ztag = "mpz(";
static char* _xztag = "xmpz(";
static PyObject *
mpz_ascii(mpz_t z, int base, int option, int which)
{
PyObject *result;
char *buffer, *p;
int negative = 0;
size_t size;
if (
!(
((base >= -36) && (base <= -2)) ||
((base >= 2) && (base <= 62))
)
) {
VALUE_ERROR("base must be in the interval 2 ... 62");
return NULL;
}
/* Allocate extra space for:
*
* minus sign and trailing NULL byte (2)
* 'xmpz()' tag (6)
* '0x' prefix (2)
* -----
* 10
*
* And add one more to be sure...
*/
size = mpz_sizeinbase(z, (base < 0 ? -base : base)) + 11;
TEMP_ALLOC(buffer, size);
if (mpz_sgn(z) < 0) {
negative = 1;
mpz_neg(z, z);
}
p = buffer;
if (option & 1) {
if (which)
strcpy(p, _xztag);
else
strcpy(p, _ztag);
p += strlen(p);
}
if (negative) {
*(p++) = '-';
}
else {
if (option & 2)
*(p++) = '+';
else if (option & 4)
*(p++) = ' ';
}
if (option & 8) {
if (base == 2) { *(p++) = '0'; *(p++) = 'b'; }
else if (base == 8) { *(p++) = '0'; *(p++) = 'o'; }
else if (base == 16) { *(p++) = '0'; *(p++) = 'x'; }
else if (base == -16) { *(p++) = '0'; *(p++) = 'X'; }
}
else if (!(option & 24)) {
if (base == 2) { *(p++) = '0'; *(p++) = 'b'; }
else if (base == 8) { *(p++) = '0'; *(p++) = 'o'; }
else if (base == 16) { *(p++) = '0'; *(p++) = 'x'; }
else if (base == -16) { *(p++) = '0'; *(p++) = 'X'; }
}
/* Call GMP. */
mpz_get_str(p, base, z);
p = buffer + strlen(buffer);
if (option & 1)
*(p++) = ')';
*(p++) = '\00';
result = PyUnicode_FromString(buffer);
if (negative == 1) {
mpz_neg(z, z);
}
TEMP_FREE(buffer, size);
return result;
}
././@PaxHeader 0000000 0000000 0000000 00000000026 00000000000 010213 x ustar 00 22 mtime=1718253275.0
gmpy2-2.2.1/src/gmpy2_convert.h 0000644 0001750 0001750 00000020220 14632473333 014764 0 ustar 00case case /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* gmpy_convert.h *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Python interface to the GMP, MPFR, and MPC multiple precision *
* libraries. *
* *
* Copyright 2000 - 2009 Alex Martelli *
* *
* Copyright 2008 - 2024 Case Van Horsen *
* *
* This file is part of GMPY2. *
* *
* GMPY2 is free software: you can redistribute it and/or modify it under *
* the terms of the GNU Lesser General Public License as published by the *
* Free Software Foundation, either version 3 of the License, or (at your *
* option) any later version. *
* *
* GMPY2 is distributed in the hope that it will be useful, but WITHOUT *
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or *
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public *
* License for more details. *
* *
* You should have received a copy of the GNU Lesser General Public *
* License along with GMPY2; if not, see *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
#ifndef GMPY2_CONVERT_H
#define GMPY2_CONVERT_H
#ifdef __cplusplus
extern "C" {
#endif
/* The following macros classify the numeric types that are supported by
* gmpy2.
*/
#define HAS_MPZ_CONVERSION(x) (PyObject_HasAttrString(x, "__mpz__"))
#define HAS_MPQ_CONVERSION(x) (PyObject_HasAttrString(x, "__mpq__"))
#define HAS_MPFR_CONVERSION(x) (PyObject_HasAttrString(x, "__mpfr__"))
#define HAS_MPC_CONVERSION(x) (PyObject_HasAttrString(x, "__mpc__"))
#define HAS_STRICT_MPZ_CONVERSION(x) (HAS_MPZ_CONVERSION(x) && \
!HAS_MPQ_CONVERSION(x))
#define HAS_STRICT_MPFR_CONVERSION(x) (HAS_MPFR_CONVERSION(x) && \
!HAS_MPC_CONVERSION(x))
#define IS_FRACTION(x) (!strcmp(Py_TYPE(x)->tp_name, "Fraction"))
#define IS_RATIONAL_ONLY(x) (MPQ_Check(x) || IS_FRACTION(x) || \
HAS_MPQ_CONVERSION(x))
#define IS_INTEGER(x) (MPZ_Check(x) || PyLong_Check(x) || \
XMPZ_Check(x) || HAS_STRICT_MPZ_CONVERSION(x))
#define IS_RATIONAL(x) (MPQ_Check(x) || IS_FRACTION(x) || \
MPZ_Check(x) || PyLong_Check(x) || \
XMPZ_Check(x) || HAS_MPQ_CONVERSION(x) || \
HAS_MPZ_CONVERSION(x))
#define IS_DECIMAL(x) (!strcmp(Py_TYPE(x)->tp_name, "decimal.Decimal") || \
!strcmp(Py_TYPE(x)->tp_name, "Decimal"))
#define IS_REAL_ONLY(x) (MPFR_Check(x) || PyFloat_Check(x) || \
HAS_STRICT_MPFR_CONVERSION(x) || IS_DECIMAL(x))
#define IS_REAL(x) (IS_RATIONAL(x) || IS_REAL_ONLY(x))
#define IS_COMPLEX_ONLY(x) (MPC_Check(x) || PyComplex_Check(x) || \
HAS_MPC_CONVERSION(x))
#define IS_COMPLEX(x) (IS_REAL(x) || IS_COMPLEX_ONLY(x))
/* Define constants used in gmpy2_convert.c->GMPy_ObjectType. */
#define OBJ_TYPE_UNKNOWN 0
#define OBJ_TYPE_MPZ 1
#define OBJ_TYPE_XMPZ 2
#define OBJ_TYPE_PyInteger 3
#define OBJ_TYPE_HAS_MPZ 4
/* 5 TO 14 reserved for additional integer types. */
#define OBJ_TYPE_INTEGER 15
#define OBJ_TYPE_MPQ 16
#define OBJ_TYPE_PyFraction 17
#define OBJ_TYPE_HAS_MPQ 18
/* 19 to 30 reserved for additional rational types. */
#define OBJ_TYPE_RATIONAL 31
#define OBJ_TYPE_MPFR 32
#define OBJ_TYPE_PyFloat 33
#define OBJ_TYPE_HAS_MPFR 34
/* 35 to 46 reserved for additional real types. */
#define OBJ_TYPE_REAL 47
#define OBJ_TYPE_MPC 48
#define OBJ_TYPE_PyComplex 49
#define OBJ_TYPE_HAS_MPC 50
/* 50 to 62 reserved for additional complex types. */
#define OBJ_TYPE_COMPLEX 63
#define OBJ_TYPE_MAX 64
/* The following macros are the recommended method to check the result of the
* object type check.
*/
#define IS_TYPE_UNKNOWN(x) (!OBJ_TYPE_UNKNOWN)
#define IS_TYPE_MPZ(x) (x == OBJ_TYPE_MPZ)
#define IS_TYPE_XMPZ(x) (x == OBJ_TYPE_XMPZ)
#define IS_TYPE_MPZANY(x) ((x == OBJ_TYPE_MPZ) || \
(x == OBJ_TYPE_XMPZ))
#define IS_TYPE_PyInteger(x) (x == OBJ_TYPE_PyInteger)
#define IS_TYPE_HAS_MPZ(x) (x == OBJ_TYPE_HAS_MPZ)
#define IS_TYPE_INTEGER(x) ((x > OBJ_TYPE_UNKNOWN) && \
(x < OBJ_TYPE_INTEGER))
#define IS_TYPE_MPQ(x) (x == OBJ_TYPE_MPQ)
#define IS_TYPE_PyFraction(x) (x == OBJ_TYPE_PyFraction)
#define IS_TYPE_HAS_MPQ(x) (x == OBJ_TYPE_HAS_MPQ)
#define IS_TYPE_RATIONAL(x) ((x > OBJ_TYPE_UNKNOWN) && \
(x < OBJ_TYPE_RATIONAL))
#define IS_TYPE_RATIONAL_ONLY(x) ((x > OBJ_TYPE_INTEGER) && \
(x < OBJ_TYPE_RATIONAL))
#define IS_TYPE_MPFR(x) (x == OBJ_TYPE_MPFR)
#define IS_TYPE_PyFloat(x) (x == OBJ_TYPE_PyFloat)
#define IS_TYPE_HAS_MPFR(x) (x == OBJ_TYPE_HAS_MPFR)
#define IS_TYPE_REAL(x) ((x > OBJ_TYPE_UNKNOWN) && \
(x < OBJ_TYPE_REAL))
#define IS_TYPE_REAL_ONLY(x) ((x > OBJ_TYPE_RATIONAL) && \
(x < OBJ_TYPE_REAL))
#define IS_TYPE_MPC(x) (x == OBJ_TYPE_MPC)
#define IS_TYPE_PyComplex(x) (x == OBJ_TYPE_PyComplex)
#define IS_TYPE_HAS_MPC(x) (x == OBJ_TYPE_HAS_MPC)
#define IS_TYPE_COMPLEX(x) ((x > OBJ_TYPE_UNKNOWN) && \
(x < OBJ_TYPE_COMPLEX))
#define IS_TYPE_COMPLEX_ONLY(x) ((x > OBJ_TYPE_REAL) && \
(x < OBJ_TYPE_COMPLEX))
/* Compatibility macros (to work with PyLongObject internals).
*/
#if PY_VERSION_HEX >= 0x030C0000
# define TAG_FROM_SIGN_AND_SIZE(is_neg, size) ((is_neg?2:(size==0)) | (((size_t)size) << 3))
# define _PyLong_SetSignAndDigitCount(obj, is_neg, size) (obj->long_value.lv_tag = TAG_FROM_SIGN_AND_SIZE(is_neg, size))
#elif PY_VERSION_HEX >= 0x030900A4
# define _PyLong_SetSignAndDigitCount(obj, is_neg, size) (Py_SET_SIZE(obj, (is_neg?-1:1)*size))
#else
# define _PyLong_SetSignAndDigitCount(obj, is_neg, size) (Py_SIZE(obj) = (is_neg?-1:1)*size)
#endif
#if PY_VERSION_HEX >= 0x030C0000
# define GET_OB_DIGIT(obj) ((PyLongObject*)obj)->long_value.ob_digit
# define _PyLong_DigitCount(obj) (((PyLongObject*)obj)->long_value.lv_tag >> 3)
#else
# define GET_OB_DIGIT(obj) obj->ob_digit
# define _PyLong_DigitCount(obj) (_PyLong_Sign(obj)<0 ? -Py_SIZE(obj):Py_SIZE(obj))
#endif
/* Since the macros are used in gmpy2's codebase, these functions are skipped
* until they are needed for the C API in the future.
*/
#if 0
/* Checks for mpz, xmpz, and the integer types included with Python. */
static int GMPy_isInteger(PyObject *obj);
/* Checks for the Fraction type included with Python. */
static int GMPy_isFraction(PyObject *obj);
/* Combined mpq, isInteger() and isFraction() check. */
static int GMPy_isRational(PyObject *obj);
/* Combined mpfr, PyFloat, and isRational() check. */
static int GMPy_isReal(PyObject *obj);
/* Combined mpc, PyComplex, and isReal() check. */
static int GMPy_isComplex(PyObject *obj);
#endif
/* ======== C helper routines ======== */
static int mpz_set_PyStr(mpz_t z, PyObject *s, int base);
static PyObject * mpz_ascii(mpz_t z, int base, int option, int which);
#ifdef __cplusplus
}
#endif
#endif
././@PaxHeader 0000000 0000000 0000000 00000000026 00000000000 010213 x ustar 00 22 mtime=1718253275.0
gmpy2-2.2.1/src/gmpy2_convert_gmp.c 0000644 0001750 0001750 00000072125 14632473333 015635 0 ustar 00case case /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* gmpy2_convert_gmp.c *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Python interface to the GMP, MPFR, and MPC multiple precision *
* libraries. *
* *
* Copyright 2000 - 2009 Alex Martelli *
* *
* Copyright 2008 - 2024 Case Van Horsen *
* *
* *
* GMPY2 is free software: you can redistribute it and/or modify it under *
* the terms of the GNU Lesser General Public License as published by the *
* Free Software Foundation, either version 3 of the License, or (at your *
* option) any later version. *
* *
* GMPY2 is distributed in the hope that it will be useful, but WITHOUT *
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or *
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public *
* License for more details. *
* *
* You should have received a copy of the GNU Lesser General Public *
* License along with GMPY2; if not, see *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
/* This file contains all the conversion functions for GMP data types.
*
* Overview
* --------
* gmpy2 tries to optimize the performance and accuracy of conversions from
* other numeric types. gmpy2 uses a LBYL (Look Before You Leap) approach and
* identifies the numeric type before conversion before conversion to a gmpy2
* type. The basic operations (+, -, *, /) are optimized to directly work with
* some basic types such as C longs or doubles.
*/
/* ======================================================================== *
* Conversion between native Python objects and MPZ. *
* ======================================================================== */
/* To support creation of temporary mpz objects. */
static void
mpz_set_PyLong(mpz_t z, PyObject *obj)
{
int negative;
Py_ssize_t len;
PyLongObject *templong = (PyLongObject*)obj;
len = _PyLong_DigitCount(obj);
negative = _PyLong_Sign(obj) < 0;
switch (len) {
case 1:
mpz_set_si(z, (sdigit)GET_OB_DIGIT(templong)[0]);
break;
case 0:
mpz_set_si(z, 0);
break;
default:
mpz_import(z, len, -1, sizeof(digit), 0,
sizeof(digit)*8 - PyLong_SHIFT,
GET_OB_DIGIT(templong));
}
if (negative) {
mpz_neg(z, z);
}
return;
}
static MPZ_Object *
GMPy_MPZ_From_PyLong(PyObject *obj, CTXT_Object *context)
{
MPZ_Object *result;
if(!(result = GMPy_MPZ_New(context))) {
/* LCOV_EXCL_START */
return NULL;
/* LCOV_EXCL_STOP */
}
mpz_set_PyLong(MPZ(result), obj);
return result;
}
static MPZ_Object *
GMPy_MPZ_From_PyStr(PyObject *s, int base, CTXT_Object *context)
{
MPZ_Object *result;
if (!(result = GMPy_MPZ_New(context))) {
/* LCOV_EXCL_START */
return NULL;
/* LCOV_EXCL_STOP */
}
if (mpz_set_PyStr(result->z, s, base) == -1) {
Py_DECREF((PyObject*)result);
return NULL;
}
return result;
}
static MPZ_Object *
GMPy_MPZ_From_PyFloat(PyObject *obj, CTXT_Object *context)
{
MPZ_Object *result;
if ((result = GMPy_MPZ_New(context))) {
double d = PyFloat_AsDouble(obj);
if (isnan(d)) {
Py_DECREF((PyObject*)result);
VALUE_ERROR("'mpz' does not support NaN");
return NULL;
}
if (isinf(d)) {
Py_DECREF((PyObject*)result);
OVERFLOW_ERROR("'mpz' does not support Infinity");
return NULL;
}
mpz_set_d(result->z, d);
}
return result;
}
static PyObject *
GMPy_PyLong_From_MPZ(MPZ_Object *obj, CTXT_Object *context)
{
if (mpz_fits_slong_p(obj->z)) {
return PyLong_FromLong(mpz_get_si(obj->z));
}
/* Assume gmp uses limbs as least as large as the builtin longs do */
size_t count, size = (mpz_sizeinbase(obj->z, 2) +
PyLong_SHIFT - 1) / PyLong_SHIFT;
PyLongObject *result;
if (!(result = _PyLong_New(size))) {
/* LCOV_EXCL_START */
return NULL;
/* LCOV_EXCL_STOP */
}
mpz_export(GET_OB_DIGIT(result), &count, -1, sizeof(digit), 0,
sizeof(digit)*8 - PyLong_SHIFT, obj->z);
for (size_t i = count; i < size; i++) {
GET_OB_DIGIT(result)[i] = 0;
}
_PyLong_SetSignAndDigitCount(result, mpz_sgn(obj->z) < 0, count);
return (PyObject*)result;
}
static PyObject *
GMPy_MPZ_Int_Slot(MPZ_Object *self)
{
return GMPy_PyLong_From_MPZ(self, NULL);
}
static PyObject *
GMPy_PyFloat_From_MPZ(MPZ_Object *obj, CTXT_Object *context)
{
double res;
res = mpz_get_d(obj->z);
if (isinf(res)) {
OVERFLOW_ERROR("'mpz' too large to convert to float");
return NULL;
}
return PyFloat_FromDouble(res);
}
static PyObject *
GMPy_MPZ_Float_Slot(MPZ_Object *self)
{
return GMPy_PyFloat_From_MPZ(self, NULL);
}
static PyObject *
GMPy_PyStr_From_MPZ(MPZ_Object *obj, int base, int option, CTXT_Object *context)
{
return mpz_ascii(obj->z, base, option, 0);
}
static MPZ_Object *
GMPy_MPZ_From_Integer(PyObject *obj, CTXT_Object *context)
{
MPZ_Object *result = NULL;
if (MPZ_Check(obj)) {
Py_INCREF(obj);
return (MPZ_Object*)obj;
}
if (PyLong_Check(obj))
return GMPy_MPZ_From_PyLong(obj, context);
if (XMPZ_Check(obj))
return GMPy_MPZ_From_XMPZ((XMPZ_Object*)obj, context);
if (HAS_STRICT_MPZ_CONVERSION(obj)) {
result = (MPZ_Object *) PyObject_CallMethod(obj, "__mpz__", NULL);
if (result != NULL && MPZ_Check(result)) {
return result;
}
else {
Py_XDECREF((PyObject*)result);
goto error;
}
}
error:
TYPE_ERROR("cannot convert object to mpz");
return NULL;
}
static MPZ_Object *
GMPy_MPZ_From_IntegerAndCopy(PyObject *obj, CTXT_Object *context)
{
MPZ_Object *result = NULL;
if (MPZ_Check(obj)) {
if (!(result = GMPy_MPZ_New(context))) {
/* LCOV_EXCL_START */
return NULL;
/* LCOV_EXCL_STOP */
}
mpz_set(result->z, MPZ(obj));
return result;
}
if (PyLong_Check(obj))
return GMPy_MPZ_From_PyLong(obj, context);
if (XMPZ_Check(obj))
return GMPy_MPZ_From_XMPZ((XMPZ_Object*)obj, context);
if (HAS_STRICT_MPZ_CONVERSION(obj)) {
result = (MPZ_Object *) PyObject_CallMethod(obj, "__mpz__", NULL);
if (result != NULL && MPZ_Check(result)) {
return result;
}
else {
Py_XDECREF((PyObject*)result);
goto error;
}
}
error:
TYPE_ERROR("cannot convert object to mpz");
return NULL;
}
static MPZ_Object *
GMPy_MPZ_From_IntegerWithType(PyObject *obj, int xtype, CTXT_Object *context)
{
MPZ_Object *result = NULL;
if (IS_TYPE_MPZ(xtype)) {
Py_INCREF(obj);
return (MPZ_Object*)obj;
}
if (IS_TYPE_PyInteger(xtype))
return GMPy_MPZ_From_PyLong(obj, context);
if (IS_TYPE_XMPZ(xtype))
return GMPy_MPZ_From_XMPZ((XMPZ_Object*)obj, context);
if (IS_TYPE_HAS_MPZ(xtype)) {
result = (MPZ_Object *) PyObject_CallMethod(obj, "__mpz__", NULL);
if (result != NULL && MPZ_Check(result)) {
return result;
}
else {
Py_XDECREF((PyObject*)result);
goto error;
}
}
error:
TYPE_ERROR("cannot convert object to mpz");
return NULL;
}
static MPZ_Object *
GMPy_MPZ_From_IntegerWithTypeAndCopy(PyObject *obj, int xtype, CTXT_Object *context)
{
MPZ_Object *result = NULL, *temp = NULL;
result = GMPy_MPZ_From_IntegerWithType(obj, xtype, context);
if (result == NULL)
return result;
if (Py_REFCNT(result) == 1)
return result;
if (!(temp = GMPy_MPZ_New(context))) {
/* LCOV_EXCL_START */
return NULL;
/* LCOV_EXCL_STOP */
}
mpz_set(temp->z, result->z);
Py_DECREF((PyObject*)result);
return temp;
}
/* str and repr implementations for mpz */
static PyObject *
GMPy_MPZ_Str_Slot(MPZ_Object *self)
{
/* base-10, no tag */
return GMPy_PyStr_From_MPZ(self, 10, 0, NULL);
}
static PyObject *
GMPy_MPZ_Repr_Slot(MPZ_Object *self)
{
/* base-10, with tag */
return GMPy_PyStr_From_MPZ(self, 10, 1, NULL);
}
#ifdef SHARED
/* Helper function for argument parsing. Not used in static build. */
static int
GMPy_MPZ_ConvertArg(PyObject *arg, PyObject **ptr)
{
MPZ_Object *result = GMPy_MPZ_From_IntegerWithType(arg, GMPy_ObjectType(arg), NULL);
if (result) {
*ptr = (PyObject*)result;
return 1;
}
else {
TYPE_ERROR("argument can not be converted to 'mpz'");
return 0;
}
}
#endif
/* ======================================================================== *
* Conversion between native Python objects/MPZ and XMPZ. *
* ======================================================================== */
static XMPZ_Object *
GMPy_XMPZ_From_PyLong(PyObject *obj, CTXT_Object *context)
{
XMPZ_Object *result;
if(!(result = GMPy_XMPZ_New(context))) {
/* LCOV_EXCL_START */
return NULL;
/* LCOV_EXCL_STOP */
}
mpz_set_PyLong(result->z, obj);
return result;
}
static XMPZ_Object *
GMPy_XMPZ_From_PyStr(PyObject *s, int base, CTXT_Object *context)
{
XMPZ_Object *result;
if (!(result = GMPy_XMPZ_New(context)))
return NULL;
if (mpz_set_PyStr(result->z, s, base) == -1) {
Py_DECREF((PyObject*)result);
return NULL;
}
return result;
}
static XMPZ_Object *
GMPy_XMPZ_From_PyFloat(PyObject *obj, CTXT_Object *context)
{
XMPZ_Object *result;
if ((result = GMPy_XMPZ_New(context))) {
double d = PyFloat_AsDouble(obj);
if (isnan(d)) {
Py_DECREF((PyObject*)result);
VALUE_ERROR("'xmpz' does not support NaN");
return NULL;
}
if (isinf(d)) {
Py_DECREF((PyObject*)result);
OVERFLOW_ERROR("'xmpz' does not support Infinity");
return NULL;
}
mpz_set_d(result->z, d);
}
return result;
}
static XMPZ_Object *
GMPy_XMPZ_From_MPZ(MPZ_Object *obj, CTXT_Object *context)
{
XMPZ_Object *result;
if ((result = GMPy_XMPZ_New(context)))
mpz_set(result->z, obj->z);
return result;
}
static XMPZ_Object *
GMPy_XMPZ_From_XMPZ(XMPZ_Object *obj, CTXT_Object *context)
{
XMPZ_Object *result;
if ((result = GMPy_XMPZ_New(context)))
mpz_set(result->z, obj->z);
return result;
}
static PyObject *
GMPy_PyStr_From_XMPZ(XMPZ_Object *obj, int base, int option, CTXT_Object *context)
{
return mpz_ascii(obj->z, base, option, 1);
}
static MPZ_Object *
GMPy_MPZ_From_XMPZ(XMPZ_Object *obj, CTXT_Object *context)
{
MPZ_Object *result;
if ((result = GMPy_MPZ_New(context)))
mpz_set(result->z, obj->z);
return result;
}
/* str and repr implementations for xmpz */
static PyObject *
GMPy_XMPZ_Str_Slot(XMPZ_Object *self)
{
/* base-10, no tag */
return GMPy_PyStr_From_XMPZ(self, 10, 0, NULL);
}
static PyObject *
GMPy_XMPZ_Repr_Slot(XMPZ_Object *self)
{
/* base-10, with tag */
return GMPy_PyStr_From_XMPZ(self, 10, 1, NULL);
}
/* ======================================================================== *
* Conversion between native Python objects/MPZ/XMPZ and MPQ. *
* ======================================================================== */
static MPQ_Object *
GMPy_MPQ_From_PyLong(PyObject *obj, CTXT_Object *context)
{
MPQ_Object *result;
MPZ_Object *temp;
temp = GMPy_MPZ_From_PyLong(obj, context);
if (!temp)
return NULL;
if ((result = GMPy_MPQ_New(context))) {
mpq_set_z(result->q, temp->z);
Py_DECREF((PyObject*)temp);
}
return result;
}
static MPQ_Object *
GMPy_MPQ_From_PyStr(PyObject *s, int base, CTXT_Object *context)
{
MPQ_Object *result;
char *cp;
char exp_char = 'E';
long expt = 0;
PyObject *ascii_str = ascii_str = GMPy_RemoveIgnoredASCII(s);
if (!ascii_str) return NULL;
if (!(result = GMPy_MPQ_New(context))) {
/* LCOV_EXCL_START */
return NULL;
/* LCOV_EXCL_STOP */
}
cp = PyBytes_AsString(ascii_str);
{
char *whereslash = strchr((char*)cp, '/');
char *wheredot = strchr((char*)cp, '.');
char *whereexp = strchr((char*)cp, 'E');
if (!whereexp) {
whereexp = strchr((char*)cp, 'e');
exp_char = 'e';
}
if (whereslash && wheredot) {
VALUE_ERROR("illegal string: both . and / found");
goto error;
}
if (wheredot && (base != 10)) {
VALUE_ERROR("illegal string: embedded . requires base=10");
goto error;
}
/* If base=10, no slash is found, and an exponent symbol is found, then
* assume we have decimal number in scientific format.
*/
if (whereexp && !whereslash && (base == 10)) {
/* Temporarily shorten the string and continue processing as
* normal. We'll deal with the exponent later.
*/
*whereexp = '\0';
expt = atol(whereexp+1);
}
/* Handle the case where an embedded decimal point exists. An optional
* exponent is also allowed. We take advantage of the fact that
* mpz_set_str() ignores embedded space characters. We count the
* number of digits after the decimal point and then replace the '.'
* with a ' '. We've already inserted a NUL byte to terminate the
* string in the case when an exponent was entered. The value for
* the exponent has already been read.
*/
if (wheredot) {
unsigned char *counter;
long digits = 0;
counter = (unsigned char*)wheredot;
digits = 0;
*wheredot = ' ';
while (*++counter != '\0') {
if (isdigit(*counter))
digits++;
}
if (-1 == mpz_set_str(mpq_numref(result->q), (char*)cp, base)) {
if (wheredot)
*wheredot = '.';
/* Restore the exponent! */
if (whereexp && !whereslash && (base == 10))
*whereexp = exp_char;
VALUE_ERROR("invalid digits");
goto error;
}
/* Process the exponent. */
digits = expt - digits;
if (digits < 0) {
mpz_ui_pow_ui(mpq_denref(result->q), 10, (unsigned long)(-digits));
}
else {
/* Use the denominator instead of a temporary variable. */
mpz_ui_pow_ui(mpq_denref(result->q), 10, (unsigned long)(digits));
mpz_mul(mpq_numref(result->q), mpq_numref(result->q), mpq_denref(result->q));
mpz_set_ui(mpq_denref(result->q), 1);
}
mpq_canonicalize(result->q);
/* Restore the decimal point. */
*wheredot = '.';
/* Restore the exponent! */
if (whereexp && (base == 10))
*whereexp = exp_char;
goto finish;
}
if (whereslash)
*whereslash = '\0';
/* Read the numerator. */
if (-1 == mpz_set_str(mpq_numref(result->q), (char*)cp, base)) {
if (whereslash)
*whereslash = '/';
VALUE_ERROR("invalid digits");
goto error;
}
/* If a slash was present, read the denominator. */
if (whereslash) {
*whereslash = '/';
if (-1 == mpz_set_str(mpq_denref(result->q), whereslash+1, base)) {
VALUE_ERROR("invalid digits");
goto error;
}
if (0 == mpz_sgn(mpq_denref(result->q))) {
ZERO_ERROR("zero denominator in mpq()");
goto error;
}
mpq_canonicalize(result->q);
}
else {
/* Since no slash was present, either the denominator is 1 or a
* power of 10.
*/
if (expt <= 0) {
mpz_ui_pow_ui(mpq_denref(result->q), 10, (unsigned long)(-expt));
}
else {
mpz_ui_pow_ui(mpq_denref(result->q), 10, (unsigned long)(expt));
mpz_mul(mpq_numref(result->q), mpq_numref(result->q), mpq_denref(result->q));
mpz_set_ui(mpq_denref(result->q), 1);
}
mpq_canonicalize(result->q);
if (whereexp && (base == 10))
*whereexp = exp_char;
}
}
finish:
Py_XDECREF(ascii_str);
return result;
error:
Py_DECREF((PyObject*)result);
Py_XDECREF(ascii_str);
return NULL;
}
static MPQ_Object *
GMPy_MPQ_From_PyFloat(PyObject *obj, CTXT_Object *context)
{
MPQ_Object *result;
if ((result = GMPy_MPQ_New(context))) {
double d = PyFloat_AsDouble(obj);
if (isnan(d)) {
Py_DECREF((PyObject*)result);
VALUE_ERROR("'mpq' does not support NaN");
return NULL;
}
if (isinf(d)) {
Py_DECREF((PyObject*)result);
OVERFLOW_ERROR("'mpq' does not support Infinity");
return NULL;
}
mpq_set_d(result->q, d);
}
return result;
}
static MPQ_Object *
GMPy_MPQ_From_MPZ(MPZ_Object *obj, CTXT_Object *context)
{
MPQ_Object *result;
if ((result = GMPy_MPQ_New(context)))
mpq_set_z(result->q, obj->z);
return result;
}
static MPQ_Object *
GMPy_MPQ_From_XMPZ(XMPZ_Object *obj, CTXT_Object *context)
{
MPQ_Object *result;
if ((result = GMPy_MPQ_New(context)))
mpq_set_z(result->q, obj->z);
return result;
}
static MPZ_Object *
GMPy_MPZ_From_MPQ(MPQ_Object *obj, CTXT_Object *context)
{
MPZ_Object *result;
if ((result = GMPy_MPZ_New(context)))
mpz_set_q(result->z, obj->q);
return result;
}
static XMPZ_Object *
GMPy_XMPZ_From_MPQ(MPQ_Object *obj, CTXT_Object *context)
{
XMPZ_Object *result;
if ((result = GMPy_XMPZ_New(context)))
mpz_set_q(result->z, obj->q);
return result;
}
static PyObject *
GMPy_PyLong_From_MPQ(MPQ_Object *obj, CTXT_Object *context)
{
PyObject *result;
MPZ_Object *temp;
temp = GMPy_MPZ_From_MPQ(obj, context);
if (!temp) {
/* LCOV_EXCL_START */
return NULL;
/* LCOV_EXCL_STOP */
}
result = GMPy_PyLong_From_MPZ(temp, context);
Py_DECREF((PyObject*)temp);
return result;
}
static PyObject *
GMPy_MPQ_Int_Slot(MPQ_Object *self)
{
return GMPy_PyLong_From_MPQ(self, NULL);
}
static char* _qtag = "mpq(";
static PyObject *
GMPy_PyStr_From_MPQ(MPQ_Object *obj, int base, int option, CTXT_Object *context)
{
PyObject *result = NULL, *numstr = NULL, *denstr = NULL;
char buffer[50], *p;
numstr = mpz_ascii(mpq_numref(obj->q), base, 0, 0);
if (!numstr) {
/* LCOV_EXCL_START */
return NULL;
/* LCOV_EXCL_STOP */
}
/* Check if denominator is 1 and no tag is requested. If so, just
* return the numerator.
*/
if (!(option & 1) && (0 == mpz_cmp_ui(mpq_denref(obj->q),1)))
return numstr;
denstr = mpz_ascii(mpq_denref(obj->q), base, 0, 0);
if (!denstr) {
/* LCOV_EXCL_START */
Py_DECREF(numstr);
return NULL;
/* LCOV_EXCL_STOP */
}
/* Build the format string. */
p = buffer;
if (option & 1) {
strcpy(p, _qtag);
p += strlen(p);
}
*(p++) = '%';
*(p++) = 'U';
if (option & 1)
*(p++) = ',';
else
*(p++) = '/';
*(p++) = '%';
*(p++) = 'U';
if (option & 1)
*(p++) = ')';
*(p++) = '\00';
result = PyUnicode_FromFormat(buffer, numstr, denstr);
Py_DECREF(numstr);
Py_DECREF(denstr);
return result;
}
static PyObject *
GMPy_PyFloat_From_MPQ(MPQ_Object *obj, CTXT_Object *context)
{
double res;
res = mpq_get_d(obj->q);
if (isinf(res)) {
OVERFLOW_ERROR("'mpq' too large to convert to float");
return NULL;
}
return PyFloat_FromDouble(res);
}
static PyObject *
GMPy_MPQ_Float_Slot(MPQ_Object *self)
{
return GMPy_PyFloat_From_MPQ(self, NULL);
}
static MPQ_Object*
GMPy_MPQ_From_Fraction(PyObject* obj, CTXT_Object *context)
{
MPQ_Object *result;
PyObject *num, *den;
if (!(result = GMPy_MPQ_New(context))) {
/* LCOV_EXCL_START */
return NULL;
/* LCOV_EXCL_STOP */
}
mpq_set_si(result->q, 0, 1);
num = PyObject_GetAttrString(obj, "numerator");
den = PyObject_GetAttrString(obj, "denominator");
if (!num || !PyLong_Check(num) || !den || !PyLong_Check(den)) {
SYSTEM_ERROR("Object does not appear to be Fraction");
Py_XDECREF(num);
Py_XDECREF(den);
Py_DECREF((PyObject*)result);
return NULL;
}
mpz_set_PyLong(mpq_numref(result->q), num);
mpz_set_PyLong(mpq_denref(result->q), den);
Py_DECREF(num);
Py_DECREF(den);
return result;
}
static MPQ_Object*
GMPy_MPQ_From_Number(PyObject *obj, CTXT_Object *context)
{
if (MPQ_Check(obj)) {
Py_INCREF(obj);
return (MPQ_Object*)obj;
}
if (MPZ_Check(obj))
return GMPy_MPQ_From_MPZ((MPZ_Object*)obj, context);
if (MPFR_Check(obj))
return GMPy_MPQ_From_MPFR((MPFR_Object*)obj, context);
if (PyFloat_Check(obj))
return GMPy_MPQ_From_PyFloat(obj, context);
if (PyLong_Check(obj))
return GMPy_MPQ_From_PyLong(obj, context);
if (XMPZ_Check(obj))
return GMPy_MPQ_From_XMPZ((XMPZ_Object*)obj, context);
if (IS_FRACTION(obj))
return GMPy_MPQ_From_Fraction(obj, context);
PyObject *pair = PyObject_CallMethod(obj, "as_integer_ratio", NULL);
if (pair != NULL) {
MPQ_Object *res = (MPQ_Object*)GMPy_MPQ_NewInit(&MPQ_Type, pair, NULL);
Py_DECREF(pair);
return res;
}
PyErr_Clear();
if (HAS_MPQ_CONVERSION(obj)) {
MPQ_Object * res = (MPQ_Object *) PyObject_CallMethod(obj, "__mpq__", NULL);
if (res != NULL && MPQ_Check(res)) {
return res;
}
else {
Py_XDECREF((PyObject*)res);
goto error;
}
}
if (HAS_MPZ_CONVERSION(obj)) {
MPZ_Object * res = (MPZ_Object *) PyObject_CallMethod(obj, "__mpz__", NULL);
if (res != NULL && MPZ_Check(res)) {
MPQ_Object * temp = GMPy_MPQ_From_MPZ(res, context);
Py_DECREF(res);
return temp;
}
else {
Py_XDECREF((PyObject*)res);
goto error;
}
}
error:
TYPE_ERROR("cannot convert object to mpq");
return NULL;
}
static MPQ_Object*
GMPy_MPQ_From_NumberWithType(PyObject *obj, int xtype, CTXT_Object *context)
{
if (IS_TYPE_MPQ(xtype)) {
Py_INCREF(obj);
return (MPQ_Object*)obj;
}
if (IS_TYPE_MPZ(xtype))
return GMPy_MPQ_From_MPZ((MPZ_Object*)obj, context);
if (IS_TYPE_MPFR(xtype))
return GMPy_MPQ_From_MPFR((MPFR_Object*)obj, context);
if (IS_TYPE_PyFloat(xtype))
return GMPy_MPQ_From_PyFloat(obj, context);
if (IS_TYPE_PyInteger(xtype))
return GMPy_MPQ_From_PyLong(obj, context);
if (IS_TYPE_XMPZ(xtype))
return GMPy_MPQ_From_XMPZ((XMPZ_Object*)obj, context);
if (IS_TYPE_PyFraction(xtype))
return GMPy_MPQ_From_Fraction(obj, context);
if (IS_TYPE_HAS_MPQ(xtype)) {
MPQ_Object * res = (MPQ_Object *) PyObject_CallMethod(obj, "__mpq__", NULL);
if (res != NULL && MPQ_Check(res)) {
return res;
}
else {
Py_XDECREF((PyObject*)res);
goto error;
}
}
if (IS_TYPE_HAS_MPZ(xtype)) {
MPZ_Object * res = (MPZ_Object *) PyObject_CallMethod(obj, "__mpz__", NULL);
if (res != NULL && MPZ_Check(res)) {
MPQ_Object * temp = GMPy_MPQ_From_MPZ(res, context);
Py_DECREF(res);
return temp;
}
else {
Py_XDECREF((PyObject*)res);
goto error;
}
}
error:
TYPE_ERROR("cannot convert object to mpq");
return NULL;
}
static MPQ_Object*
GMPy_MPQ_From_RationalWithTypeAndCopy(PyObject *obj, int xtype, CTXT_Object *context)
{
MPQ_Object *result = NULL, *temp = NULL;
result = GMPy_MPQ_From_RationalWithType(obj, xtype, context);
if (result == NULL)
return result;
if (Py_REFCNT(result) == 1)
return result;
if (!(temp = GMPy_MPQ_New(context))) {
/* LCOV_EXCL_START */
return NULL;
/* LCOV_EXCL_STOP */
}
mpq_set(temp->q, result->q);
Py_DECREF((PyObject*)result);
return temp;
}
static MPQ_Object*
GMPy_MPQ_From_Rational(PyObject *obj, CTXT_Object *context)
{
if (MPQ_Check(obj)) {
Py_INCREF(obj);
return (MPQ_Object*)obj;
}
if (MPZ_Check(obj))
return GMPy_MPQ_From_MPZ((MPZ_Object*)obj, context);
if (PyLong_Check(obj))
return GMPy_MPQ_From_PyLong(obj, context);
if (XMPZ_Check(obj))
return GMPy_MPQ_From_XMPZ((XMPZ_Object*)obj, context);
if (IS_FRACTION(obj))
return GMPy_MPQ_From_Fraction(obj, context);
if (HAS_MPQ_CONVERSION(obj)) {
MPQ_Object * res = (MPQ_Object *) PyObject_CallMethod(obj, "__mpq__", NULL);
if (res != NULL && MPQ_Check(res)) {
return res;
}
else {
Py_XDECREF((PyObject*)res);
goto error;
}
}
if (HAS_MPZ_CONVERSION(obj)) {
MPZ_Object * res = (MPZ_Object *) PyObject_CallMethod(obj, "__mpz__", NULL);
if (res != NULL && MPZ_Check(res)) {
MPQ_Object * temp = GMPy_MPQ_From_MPZ(res, context);
Py_DECREF(res);
return temp;
}
else {
Py_XDECREF((PyObject*)res);
goto error;
}
}
error:
TYPE_ERROR("cannot convert object to mpq");
return NULL;
}
static MPQ_Object*
GMPy_MPQ_From_RationalAndCopy(PyObject *obj, CTXT_Object *context)
{
MPQ_Object *result = NULL, *temp = NULL;
result = GMPy_MPQ_From_Rational(obj, context);
if (result == NULL)
return result;
if (Py_REFCNT(result) == 1)
return result;
if (!(temp = GMPy_MPQ_New(context))) {
/* LCOV_EXCL_START */
return NULL;
/* LCOV_EXCL_STOP */
}
mpq_set(temp->q, result->q);
Py_DECREF((PyObject*)result);
return temp;
}
static MPQ_Object*
GMPy_MPQ_From_RationalWithType(PyObject *obj, int xtype, CTXT_Object *context)
{
if (IS_TYPE_MPQ(xtype)) {
Py_INCREF(obj);
return (MPQ_Object*)obj;
}
if (IS_TYPE_MPZ(xtype))
return GMPy_MPQ_From_MPZ((MPZ_Object*)obj, context);
if (IS_TYPE_PyInteger(xtype))
return GMPy_MPQ_From_PyLong(obj, context);
if (IS_TYPE_XMPZ(xtype))
return GMPy_MPQ_From_XMPZ((XMPZ_Object*)obj, context);
if (IS_TYPE_PyFraction(xtype))
return GMPy_MPQ_From_Fraction(obj, context);
if (IS_TYPE_HAS_MPQ(xtype)) {
MPQ_Object * res = (MPQ_Object *) PyObject_CallMethod(obj, "__mpq__", NULL);
if (res != NULL && MPQ_Check(res)) {
return res;
}
else {
Py_XDECREF((PyObject*)res);
goto error;
}
}
if (IS_TYPE_HAS_MPZ(xtype)) {
MPZ_Object * res = (MPZ_Object *) PyObject_CallMethod(obj, "__mpz__", NULL);
if (res != NULL && MPZ_Check(res)) {
MPQ_Object * temp = GMPy_MPQ_From_MPZ(res, context);
Py_DECREF(res);
return temp;
}
else {
Py_XDECREF((PyObject*)res);
goto error;
}
}
error:
TYPE_ERROR("cannot convert object to mpq");
return NULL;
}
/*
* coerce any number to a mpq
*/
#ifdef SHARED
/* Helper function for argument parsing. Not used in static build. */
int
GMPy_MPQ_ConvertArg(PyObject *arg, PyObject **ptr)
{
MPQ_Object* result = GMPy_MPQ_From_NumberWithType(arg, GMPy_ObjectType(arg), NULL);
if (result) {
*ptr = (PyObject*)result;
return 1;
}
else {
if (!PyErr_Occurred()) {
TYPE_ERROR("argument can not be converted to 'mpq'");
}
return 0;
}
}
#endif
/* str and repr implementations for mpq */
static PyObject *
GMPy_MPQ_Str_Slot(MPQ_Object *self)
{
/* base-10, no tag */
return GMPy_PyStr_From_MPQ(self, 10, 0, NULL);
}
static PyObject *
GMPy_MPQ_Repr_Slot(MPQ_Object *self)
{
/* base-10, with tag */
return GMPy_PyStr_From_MPQ(self, 10, 1, NULL);
}
././@PaxHeader 0000000 0000000 0000000 00000000026 00000000000 010213 x ustar 00 22 mtime=1710307256.0
gmpy2-2.2.1/src/gmpy2_convert_gmp.h 0000644 0001750 0001750 00000015031 14574233670 015636 0 ustar 00case case /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* gmpy_convert_gmp.h *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Python interface to the GMP, MPFR, and MPC multiple precision *
* libraries. *
* *
* Copyright 2000 - 2009 Alex Martelli *
* *
* Copyright 2008 - 2024 Case Van Horsen *
* *
* This file is part of GMPY2. *
* *
* GMPY2 is free software: you can redistribute it and/or modify it under *
* the terms of the GNU Lesser General Public License as published by the *
* Free Software Foundation, either version 3 of the License, or (at your *
* option) any later version. *
* *
* GMPY2 is distributed in the hope that it will be useful, but WITHOUT *
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or *
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public *
* License for more details. *
* *
* You should have received a copy of the GNU Lesser General Public *
* License along with GMPY2; if not, see *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
#ifndef GMPY2_CONVERT_GMP_H
#define GMPY2_CONVERT_GMP_H
#ifdef __cplusplus
extern "C" {
#endif
/* ======================================================================== *
* Conversion between native Python objects and MPZ. *
* ======================================================================== */
static MPZ_Object * GMPy_MPZ_From_PyLong(PyObject *obj, CTXT_Object *context);
static MPZ_Object * GMPy_MPZ_From_PyStr(PyObject *s, int base, CTXT_Object *context);
static MPZ_Object * GMPy_MPZ_From_PyFloat(PyObject *obj, CTXT_Object *context);
static MPZ_Object * GMPy_MPZ_From_Integer(PyObject *obj, CTXT_Object *context);
static MPZ_Object * GMPy_MPZ_From_IntegerAndCopy(PyObject *obj, CTXT_Object *context);
static MPZ_Object * GMPy_MPZ_From_IntegerWithType(PyObject *obj, int xtype, CTXT_Object *context);
static MPZ_Object * GMPy_MPZ_From_IntegerWithTypeAndCopy(PyObject *obj, int xtype, CTXT_Object *context);
static PyObject * GMPy_MPZ_Str_Slot(MPZ_Object *self);
static PyObject * GMPy_MPZ_Repr_Slot(MPZ_Object *self);
static PyObject * GMPy_PyLong_From_MPZ(MPZ_Object *obj, CTXT_Object *context);
static PyObject * GMPy_PyFloat_From_MPZ(MPZ_Object *obj, CTXT_Object *context);
static PyObject * GMPy_PyStr_From_MPZ(MPZ_Object *obj, int base, int option, CTXT_Object *context);
#ifdef SHARED
/* static int GMPy_MPZ_ConvertArg(PyObject *arg, PyObject **ptr); */
static GMPy_MPZ_ConvertArg_RETURN GMPy_MPZ_ConvertArg GMPy_MPZ_ConvertArg_PROTO;
#endif
/* ======================================================================== *
* Conversion between native Python objects/MPZ and XMPZ. *
* ======================================================================== */
static XMPZ_Object * GMPy_XMPZ_From_PyLong(PyObject *obj, CTXT_Object *context);
static XMPZ_Object * GMPy_XMPZ_From_PyStr(PyObject *s, int base, CTXT_Object *context);
static XMPZ_Object * GMPy_XMPZ_From_PyFloat(PyObject *self, CTXT_Object *context);
static XMPZ_Object * GMPy_XMPZ_From_MPZ(MPZ_Object *obj, CTXT_Object *context);
static XMPZ_Object * GMPy_XMPZ_From_XMPZ(XMPZ_Object *obj, CTXT_Object *context);
static PyObject * GMPy_XMPZ_Str_Slot(XMPZ_Object *self);
static PyObject * GMPy_XMPZ_Repr_Slot(XMPZ_Object *self);
static PyObject * GMPy_PyStr_From_XMPZ(XMPZ_Object *self, int base, int option, CTXT_Object *context);
static MPZ_Object * GMPy_MPZ_From_XMPZ(XMPZ_Object *obj, CTXT_Object *context);
/* ======================================================================== *
* Conversion between native Python objects/MPZ/XMPZ and MPQ. *
* ======================================================================== */
static MPQ_Object * GMPy_MPQ_From_PyLong(PyObject *obj, CTXT_Object *context);
static MPQ_Object * GMPy_MPQ_From_PyStr(PyObject *s, int base, CTXT_Object *context);
static MPQ_Object * GMPy_MPQ_From_PyFloat(PyObject *obj, CTXT_Object *context);
static MPQ_Object * GMPy_MPQ_From_Fraction(PyObject *obj, CTXT_Object *context);
static MPQ_Object * GMPy_MPQ_From_MPZ(MPZ_Object *obj, CTXT_Object *context);
static MPQ_Object * GMPy_MPQ_From_XMPZ(XMPZ_Object *obj, CTXT_Object *context);
static MPQ_Object * GMPy_MPQ_From_Rational(PyObject* obj, CTXT_Object *context);
static MPQ_Object * GMPy_MPQ_From_RationalAndCopy(PyObject* obj, CTXT_Object *context);
static MPQ_Object * GMPy_MPQ_From_NumberWithType(PyObject* obj, int xtype, CTXT_Object *context);
static MPQ_Object * GMPy_MPQ_From_Number(PyObject* obj, CTXT_Object *context);
static MPQ_Object * GMPy_MPQ_From_RationalWithTypeAndCopy(PyObject* obj, int xtype, CTXT_Object *context);
static MPQ_Object * GMPy_MPQ_From_RationalWithType(PyObject *obj, int xtype, CTXT_Object *context);
static PyObject * GMPy_PyLong_From_MPQ(MPQ_Object *obj, CTXT_Object *context);
static PyObject * GMPy_PyStr_From_MPQ(MPQ_Object *obj, int base, int option, CTXT_Object *context);
static PyObject * GMPy_PyFloat_From_MPQ(MPQ_Object *obj, CTXT_Object *context);
static MPZ_Object * GMPy_MPZ_From_MPQ(MPQ_Object *obj, CTXT_Object *context);
static XMPZ_Object * GMPy_XMPZ_From_MPQ(MPQ_Object *obj, CTXT_Object *context);
/* support str() and repr() */
static PyObject * GMPy_MPQ_Str_Slot(MPQ_Object *obj);
static PyObject * GMPy_MPQ_Repr_Slot(MPQ_Object *obj);
static PyObject * GMPy_MPQ_Float_Slot(MPQ_Object *obj);
static PyObject * GMPy_MPQ_Int_Slot(MPQ_Object *obj);
#ifdef SHARED
/* int GMPy_MPQ_convert_arg(PyObject *arg, PyObject **ptr); */
static GMPy_MPQ_ConvertArg_RETURN GMPy_MPQ_ConvertArg GMPy_MPQ_ConvertArg_PROTO;
#endif
#ifdef __cplusplus
}
#endif
#endif
././@PaxHeader 0000000 0000000 0000000 00000000026 00000000000 010213 x ustar 00 22 mtime=1710307256.0
gmpy2-2.2.1/src/gmpy2_convert_mpc.c 0000644 0001750 0001750 00000044637 14574233670 015643 0 ustar 00case case /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* gmpy2_convert_mpc.c *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Python interface to the GMP, MPFR, and MPC multiple precision *
* libraries. *
* *
* Copyright 2000 - 2009 Alex Martelli *
* *
* Copyright 2008 - 2024 Case Van Horsen *
* *
* This file is part of GMPY2. *
* *
* GMPY2 is free software: you can redistribute it and/or modify it under *
* the terms of the GNU Lesser General Public License as published by the *
* Free Software Foundation, either version 3 of the License, or (at your *
* option) any later version. *
* *
* GMPY2 is distributed in the hope that it will be useful, but WITHOUT *
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or *
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public *
* License for more details. *
* *
* You should have received a copy of the GNU Lesser General Public *
* License along with GMPY2; if not, see *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
/* Please see the documentation for GMPy_MPFR_From_MPFR for detailed
* description of this function.
*/
static MPC_Object *
GMPy_MPC_From_MPC(MPC_Object *obj, mpfr_prec_t rprec, mpfr_prec_t iprec,
CTXT_Object *context)
{
MPC_Object *result = NULL;
/* Optimize the critical case when prec==1 or obj is NaN or Inf. */
if ((rprec == 1 && iprec == 1) ||
(!mpfr_number_p(mpc_realref(obj->c)) &&
!mpfr_number_p(mpc_imagref(obj->c)))) {
Py_INCREF((PyObject*)obj);
return obj;
}
CHECK_CONTEXT(context);
if (rprec == 0)
rprec = GET_REAL_PREC(context);
else if (rprec == 1)
rprec = mpfr_get_prec(mpc_realref(obj->c));
if (iprec == 0)
iprec = GET_IMAG_PREC(context);
else if (iprec == 1)
iprec = mpfr_get_prec(mpc_imagref(obj->c));
/* Try to identify when an additional reference to existing instance can
* be returned. It is possible when (1) the precision matches, (2) the
* exponent is valid and not in the range that might require subnormal-
* ization, and (3) subnormalize is not enabled.
*/
if ((rprec == mpfr_get_prec(mpc_realref(obj->c))) &&
(iprec == mpfr_get_prec(mpc_imagref(obj->c))) &&
(!context->ctx.subnormalize) &&
(mpc_realref(obj->c)->_mpfr_exp >= (context->ctx.emin + mpfr_get_prec(mpc_realref(obj->c)) - 1)) &&
(mpc_realref(obj->c)->_mpfr_exp <= context->ctx.emax) &&
(mpc_imagref(obj->c)->_mpfr_exp >= (context->ctx.emin + mpfr_get_prec(mpc_imagref(obj->c)) - 1)) &&
(mpc_imagref(obj->c)->_mpfr_exp <= context->ctx.emax)
) {
Py_INCREF((PyObject*)obj);
return obj;
}
if ((result = GMPy_MPC_New(rprec, iprec, context))) {
result->rc = mpc_set(result->c, obj->c, GET_MPC_ROUND(context));
_GMPy_MPC_Cleanup(&result, context);
}
return result;
}
static MPC_Object *
GMPy_MPC_From_PyComplex(PyObject *obj, mpfr_prec_t rprec, mpfr_prec_t iprec,
CTXT_Object *context)
{
MPC_Object *result;
CHECK_CONTEXT(context);
if (rprec == 0)
rprec = GET_REAL_PREC(context);
else if (rprec == 1)
rprec = DBL_MANT_DIG;
if (iprec == 0)
iprec = GET_IMAG_PREC(context);
else if (iprec == 1)
rprec = DBL_MANT_DIG;
if ((result = GMPy_MPC_New(rprec, iprec, context))) {
result->rc = mpc_set_d_d(result->c, PyComplex_RealAsDouble(obj),
PyComplex_ImagAsDouble(obj), GET_MPC_ROUND(context));
if (rprec != 1 || iprec != 1) {
GMPY_MPC_CHECK_RANGE(result, context);
}
GMPY_MPC_SUBNORMALIZE(result, context);
GMPY_MPC_EXCEPTIONS(result, context);
}
return result;
}
static MPC_Object *
GMPy_MPC_From_MPFR(MPFR_Object *obj, mpfr_prec_t rprec, mpfr_prec_t iprec,
CTXT_Object *context)
{
MPC_Object *result;
CHECK_CONTEXT(context);
if (rprec == 0)
rprec = GET_REAL_PREC(context);
else if (rprec == 1)
rprec = mpfr_get_prec(obj->f);
if (iprec == 0)
iprec = GET_IMAG_PREC(context);
else if (iprec == 1)
rprec = mpfr_get_prec(obj->f);
if ((result = GMPy_MPC_New(rprec, iprec, context))) {
result->rc = mpc_set_fr(result->c, obj->f, GET_MPC_ROUND(context));
if (rprec != 1) {
GMPY_MPC_CHECK_RANGE(result, context);
}
GMPY_MPC_SUBNORMALIZE(result, context);
GMPY_MPC_EXCEPTIONS(result, context);
}
return result;
}
static MPC_Object *
GMPy_MPC_From_PyFloat(PyObject *obj, mpfr_prec_t rprec, mpfr_prec_t iprec,
CTXT_Object *context)
{
MPC_Object *result;
CHECK_CONTEXT(context);
if (rprec == 0)
rprec = GET_REAL_PREC(context);
else if (rprec == 1)
rprec = DBL_MANT_DIG;
if (iprec == 0)
iprec = GET_IMAG_PREC(context);
else if (iprec == 1)
rprec = DBL_MANT_DIG;
if ((result = GMPy_MPC_New(rprec, iprec, context))) {
result->rc = mpc_set_d(result->c, PyFloat_AS_DOUBLE(obj),
GET_MPC_ROUND(context));
if (rprec != 1) {
GMPY_MPC_CHECK_RANGE(result, context);
}
GMPY_MPC_SUBNORMALIZE(result, context);
GMPY_MPC_EXCEPTIONS(result, context);
}
return result;
}
static MPC_Object *
GMPy_MPC_From_MPZ(MPZ_Object *obj, mpfr_prec_t rprec, mpfr_prec_t iprec,
CTXT_Object *context)
{
MPC_Object *result = NULL;
CHECK_CONTEXT(context);
if (rprec < 2) {
rprec = GET_REAL_PREC(context);
}
if (iprec < 2) {
iprec = GET_IMAG_PREC(context);
}
if ((result = GMPy_MPC_New(rprec, iprec, context))) {
result->rc = mpc_set_z(result->c, obj->z, GET_MPC_ROUND(context));
if (rprec != 1) {
GMPY_MPC_CHECK_RANGE(result, context);
}
GMPY_MPC_SUBNORMALIZE(result, context);
GMPY_MPC_EXCEPTIONS(result, context);
}
return result;
}
static MPC_Object *
GMPy_MPC_From_MPQ(MPQ_Object *obj, mpfr_prec_t rprec, mpfr_prec_t iprec,
CTXT_Object *context)
{
MPC_Object *result = NULL;
CHECK_CONTEXT(context);
if (rprec < 2) {
rprec = GET_REAL_PREC(context);
}
if (iprec < 2) {
iprec = GET_IMAG_PREC(context);
}
if ((result = GMPy_MPC_New(rprec, iprec, context))) {
result->rc = mpc_set_q(result->c, obj->q, GET_MPC_ROUND(context));
if (rprec != 1) {
GMPY_MPC_CHECK_RANGE(result, context);
}
GMPY_MPC_SUBNORMALIZE(result, context);
GMPY_MPC_EXCEPTIONS(result, context);
}
return result;
}
static MPC_Object *
GMPy_MPC_From_Fraction(PyObject *obj, mpfr_prec_t rprec, mpfr_prec_t iprec,
CTXT_Object *context)
{
MPC_Object *result = NULL;
MPQ_Object *tempq;
CHECK_CONTEXT(context);
if ((tempq = GMPy_MPQ_From_Fraction(obj, context))) {
result = GMPy_MPC_From_MPQ(tempq, rprec, iprec, context);
Py_DECREF((PyObject*)tempq);
}
return result;
}
static MPC_Object *
GMPy_MPC_From_PyLong(PyObject *obj, mpfr_prec_t rprec, mpfr_prec_t iprec,
CTXT_Object *context)
{
MPC_Object *result = NULL;
MPZ_Object *tempz;
CHECK_CONTEXT(context);
if ((tempz = GMPy_MPZ_From_PyLong(obj, context))) {
result = GMPy_MPC_From_MPZ(tempz, rprec, iprec, context);
Py_DECREF((PyObject*)tempz);
}
return result;
}
/* Python's string representation of a complex number differs from the format
* used by MPC. Both MPC and Python surround the complex number with '(' and
* ')' but Python adds a 'j' after the imaginary component and MPC requires a
* space between the real and imaginery components. GMPy_MPC_From_PyStr tries
* to work around the differences as by reading two MPFR-compatible numbers
* from the string and storing into the real and imaginary components
* respectively.
*/
static MPC_Object *
GMPy_MPC_From_PyStr(PyObject *s, int base, mpfr_prec_t rprec, mpfr_prec_t iprec,
CTXT_Object *context)
{
MPC_Object *result;
Py_ssize_t len;
char *cp = NULL, *unwind, *tempchar, *lastchar;
int firstp = 0, lastp = 0, real_rc = 0, imag_rc = 0, rc = 0;
PyObject *ascii_str = NULL;
if (PyUnicode_Check(s))
cp = (char*)PyUnicode_AsUTF8AndSize(s, &len);
CHECK_CONTEXT(context);
if (!(result = GMPy_MPC_New(rprec, iprec, context)))
return NULL;
if (cp && *cp == '(') {
rc = mpc_strtoc(result->c, cp, &tempchar, base, GET_MPC_ROUND(context));
if (tempchar > cp + len - 1) {
result->rc = MPC_INEX1(rc);
return result;
}
}
ascii_str = GMPy_RemoveIgnoredASCII(s);
if (!ascii_str)
return NULL;
cp = (char*)PyBytes_AsString(ascii_str);
len = PyBytes_Size(ascii_str);
/* Get a pointer to the last valid character */
lastchar = cp + len - 1;
/* Skip trailing ). */
if (*lastchar == ')') {
lastp = 1;
lastchar--;
}
/* Skip trailing j. */
if (*lastchar == 'j')
lastchar--;
/* Skip a leading (. */
if (*cp == '(') {
firstp = 1;
cp++;
}
if (firstp != lastp) goto invalid_string;
/* Read the real component first. */
unwind = cp;
real_rc = mpfr_strtofr(mpc_realref(result->c), cp, &tempchar, base,
GET_REAL_ROUND(context));
/* Verify that at least one valid character was read. */
if (cp == tempchar) goto invalid_string;
/* If the next character is a j, then the real component is 0 and
* we just read the imaginary componenet.
*/
if (*tempchar == 'j') {
mpfr_set_zero(mpc_realref(result->c), MPFR_RNDN);
cp = unwind;
}
else {
/* Read the imaginary component next. */
cp = tempchar;
}
imag_rc = mpfr_strtofr(mpc_imagref(result->c), cp, &tempchar, base,
GET_IMAG_ROUND(context));
if (cp == tempchar && tempchar > lastchar)
goto valid_string;
if (*tempchar != 'j' && *cp != ' ')
goto invalid_string;
if (tempchar <= lastchar)
goto invalid_string;
valid_string:
Py_XDECREF(ascii_str);
result->rc = MPC_INEX(real_rc, imag_rc);
if (rprec != 1 || iprec != 1) {
GMPY_MPC_CHECK_RANGE(result, context);
}
GMPY_MPC_SUBNORMALIZE(result, context);
GMPY_MPC_EXCEPTIONS(result, context);
return result;
invalid_string:
VALUE_ERROR("invalid string in mpc()");
Py_DECREF((PyObject*)result);
Py_XDECREF(ascii_str);
return NULL;
}
/* See the comments for GMPy_MPFR_From_Real_Temp. */
static MPC_Object *
GMPy_MPC_From_ComplexWithType(PyObject* obj, int xtype, mp_prec_t rprec,
mp_prec_t iprec, CTXT_Object *context)
{
CHECK_CONTEXT(context);
if (IS_TYPE_MPC(xtype))
return GMPy_MPC_From_MPC((MPC_Object*)obj, rprec, iprec, context);
if (IS_TYPE_MPFR(xtype))
return GMPy_MPC_From_MPFR((MPFR_Object*)obj, rprec, iprec, context);
if (IS_TYPE_PyFloat(xtype))
return GMPy_MPC_From_PyFloat(obj, rprec, iprec, context);
if (IS_TYPE_PyComplex(xtype))
return GMPy_MPC_From_PyComplex(obj, rprec, iprec, context);
if (IS_TYPE_MPQ(xtype))
return GMPy_MPC_From_MPQ((MPQ_Object*)obj, rprec, iprec, context);
if (IS_TYPE_MPZANY(xtype))
return GMPy_MPC_From_MPZ((MPZ_Object*)obj, rprec, iprec, context);
if (IS_TYPE_PyInteger(xtype))
return GMPy_MPC_From_PyLong(obj, rprec, iprec, context);
if (IS_TYPE_PyFraction(xtype))
return GMPy_MPC_From_Fraction(obj, rprec, iprec, context);
if (IS_TYPE_HAS_MPC(xtype)) {
MPC_Object * res = (MPC_Object *) PyObject_CallMethod(obj, "__mpc__", NULL);
if (res != NULL && MPC_Check(res)) {
return res;
}
else {
Py_XDECREF((PyObject*)res);
goto error;
}
}
if (IS_TYPE_HAS_MPFR(xtype)) {
MPFR_Object * res = (MPFR_Object *) PyObject_CallMethod(obj, "__mpfr__", NULL);
if (res != NULL && MPFR_Check(res)) {
MPC_Object * temp = GMPy_MPC_From_MPFR(res, rprec, iprec, context);
Py_DECREF(res);
return temp;
}
else {
Py_XDECREF((PyObject*)res);
goto error;
}
}
if (IS_TYPE_HAS_MPQ(xtype)) {
MPQ_Object * res = (MPQ_Object *) PyObject_CallMethod(obj, "__mpq__", NULL);
if (res != NULL && MPQ_Check(res)) {
MPC_Object * temp = GMPy_MPC_From_MPQ(res, rprec, iprec, context);
Py_DECREF(res);
return temp;
}
else {
Py_XDECREF((PyObject*)res);
goto error;
}
}
if (IS_TYPE_HAS_MPZ(xtype)) {
MPZ_Object * res = (MPZ_Object *) PyObject_CallMethod(obj, "__mpz__", NULL);
if (res != NULL && MPZ_Check(res)) {
MPC_Object * temp = GMPy_MPC_From_MPZ(res, rprec, iprec, context);
Py_DECREF(res);
return temp;
}
else {
Py_XDECREF((PyObject*)res);
goto error;
}
}
error:
TYPE_ERROR("object could not be converted to 'mpc'");
return NULL;
}
static MPC_Object *
GMPy_MPC_From_Complex(PyObject* obj, mp_prec_t rprec, mp_prec_t iprec,
CTXT_Object *context)
{
return GMPy_MPC_From_ComplexWithType(obj, GMPy_ObjectType(obj),
rprec, iprec, context);
}
static MPC_Object *
GMPy_MPC_From_ComplexWithTypeAndCopy(PyObject* obj, int xtype, mp_prec_t rprec,
mp_prec_t iprec, CTXT_Object *context)
{
MPC_Object *result = NULL, *temp = NULL;
result = GMPy_MPC_From_ComplexWithType(obj, xtype, rprec, iprec, context);
if (result == NULL)
return result;
if (Py_REFCNT(result) == 1)
return result;
if (!(temp = GMPy_MPC_New(rprec = mpfr_get_prec(mpc_realref(result->c)),
iprec = mpfr_get_prec(mpc_imagref(result->c)),
context))) {
/* LCOV_EXCL_START */
Py_DECREF(result);
return NULL;
/* LCOV_EXCL_STOP */
}
/* Since the precision of temp is the same as the precision of result,
* there shouldn't be any rounding.
*/
mpc_set(temp->c, result->c, MPFR_RNDN);
Py_DECREF((PyObject*)result);
return temp;
}
static PyObject *
GMPy_PyStr_From_MPC(MPC_Object *self, int base, int digits, CTXT_Object *context)
{
PyObject *tempreal = 0, *tempimag = 0, *result;
CHECK_CONTEXT(context);
if (!((base >= 2) && (base <= 62))) {
VALUE_ERROR("base must be in the interval [2,62]");
return NULL;
}
if ((digits < 0) || (digits == 1)) {
VALUE_ERROR("digits must be 0 or >= 2");
return NULL;
}
tempreal = mpfr_ascii(mpc_realref(self->c), base, digits,
MPC_RND_RE(GET_MPC_ROUND(context)));
tempimag = mpfr_ascii(mpc_imagref(self->c), base, digits,
MPC_RND_IM(GET_MPC_ROUND(context)));
if (!tempreal || !tempimag) {
Py_XDECREF(tempreal);
Py_XDECREF(tempimag);
return NULL;
}
result = Py_BuildValue("(NN)", tempreal, tempimag);
if (!result) {
Py_DECREF(tempreal);
Py_DECREF(tempimag);
}
return result;
}
static PyObject *
GMPy_MPC_Float_Slot(PyObject *self)
{
TYPE_ERROR("can't covert 'mpc' to 'float'");
return NULL;
}
PyDoc_STRVAR(GMPy_doc_mpc_complex, "Convert 'mpc' to 'complex'.");
static PyObject *
GMPy_PyComplex_From_MPC(PyObject *self, PyObject *other)
{
CTXT_Object *context = NULL;
double real, imag;
CHECK_CONTEXT(context);
real = mpfr_get_d(mpc_realref(MPC(self)), GET_REAL_ROUND(context));
imag = mpfr_get_d(mpc_imagref(MPC(self)), GET_IMAG_ROUND(context));
return PyComplex_FromDoubles(real, imag);
}
static PyObject *
GMPy_MPC_Int_Slot(PyObject *self)
{
TYPE_ERROR("can't covert mpc to int");
return NULL;
}
#ifdef SHARED
/*
* coerce any number to a mpc
*/
int
GMPy_MPC_ConvertArg(PyObject *arg, PyObject **ptr)
{
MPC_Object *newob = GMPy_MPC_From_Complex(arg, 0, 0, NULL);
if (newob) {
*ptr = (PyObject*)newob;
return 1;
}
else {
TYPE_ERROR("can't convert argument to 'mpc'");
return 0;
}
}
#endif
/* str and repr implementations for mpc */
static PyObject *
GMPy_MPC_Str_Slot(MPC_Object *self)
{
PyObject *result, *temp;
mpfr_prec_t rbits, ibits;
long rprec, iprec;
char fmtstr[60];
mpc_get_prec2(&rbits, &ibits, MPC(self));
rprec = (long)(log10(2) * (double)rbits) + 2;
iprec = (long)(log10(2) * (double)ibits) + 2;
sprintf(fmtstr, "{0:.%ld.%ldg}", rprec, iprec);
temp = PyUnicode_FromString(fmtstr);
if (!temp)
return NULL;
result = PyObject_CallMethod(temp, "format", "O", self);
Py_DECREF(temp);
return result;
}
static PyObject *
GMPy_MPC_Repr_Slot(MPC_Object *self)
{
PyObject *result, *temp;
mpfr_prec_t rbits, ibits;
long rprec, iprec;
char fmtstr[60];
mpc_get_prec2(&rbits, &ibits, MPC(self));
rprec = (long)(log10(2) * (double)rbits) + 2;
iprec = (long)(log10(2) * (double)ibits) + 2;
if (rbits != DBL_MANT_DIG || ibits !=DBL_MANT_DIG)
sprintf(fmtstr, "mpc('{0:.%ld.%ldg}',(%ld,%ld))",
rprec, iprec, rbits, ibits);
else
sprintf(fmtstr, "mpc('{0:.%ld.%ldg}')", rprec, iprec);
temp = PyUnicode_FromString(fmtstr);
if (!temp)
return NULL;
result = PyObject_CallMethod(temp, "format", "O", self);
Py_DECREF(temp);
return result;
}
././@PaxHeader 0000000 0000000 0000000 00000000026 00000000000 010213 x ustar 00 22 mtime=1710307256.0
gmpy2-2.2.1/src/gmpy2_convert_mpc.h 0000644 0001750 0001750 00000007771 14574233670 015646 0 ustar 00case case /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* gmpy2_convert_mpc.h *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Python interface to the GMP, MPFR, and MPC multiple precision *
* libraries. *
* *
* Copyright 2000 - 2009 Alex Martelli *
* *
* Copyright 2008 - 2024 Case Van Horsen *
* *
* This file is part of GMPY2. *
* *
* GMPY2 is free software: you can redistribute it and/or modify it under *
* the terms of the GNU Lesser General Public License as published by the *
* Free Software Foundation, either version 3 of the License, or (at your *
* option) any later version. *
* *
* GMPY2 is distributed in the hope that it will be useful, but WITHOUT *
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or *
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public *
* License for more details. *
* *
* You should have received a copy of the GNU Lesser General Public *
* License along with GMPY2; if not, see *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
#ifndef GMPY2_CONVERT_MPC_H
#define GMPY2_CONVERT_MPC_H
#ifdef __cplusplus
extern "C" {
#endif
/* Conversions with Pympc */
static MPC_Object * GMPy_MPC_From_MPC(MPC_Object *obj, mpfr_prec_t rprec, mpfr_prec_t iprec, CTXT_Object *context);
static MPC_Object * GMPy_MPC_From_PyComplex(PyObject *obj, mpfr_prec_t rprec, mpfr_prec_t iprec, CTXT_Object *context);
static MPC_Object * GMPy_MPC_From_MPFR(MPFR_Object *obj, mpfr_prec_t rprec, mpfr_prec_t iprec, CTXT_Object *context);
static MPC_Object * GMPy_MPC_From_PyFloat(PyObject *obj, mpfr_prec_t rprec, mpfr_prec_t iprec, CTXT_Object *context);
static MPC_Object * GMPy_MPC_From_MPZ(MPZ_Object *obj, mpfr_prec_t rprec, mpfr_prec_t iprec, CTXT_Object *context);
static MPC_Object * GMPy_MPC_From_MPQ(MPQ_Object *obj, mpfr_prec_t rprec, mpfr_prec_t iprec, CTXT_Object *context);
static MPC_Object * GMPy_MPC_From_Fraction(PyObject *obj, mpfr_prec_t rprec, mpfr_prec_t iprec, CTXT_Object *context);
static MPC_Object * GMPy_MPC_From_PyLong(PyObject *obj, mpfr_prec_t rprec, mpfr_prec_t iprec, CTXT_Object *context);
static MPC_Object * GMPy_MPC_From_PyStr(PyObject *s, int base, mpfr_prec_t rbits, mpfr_prec_t ibits, CTXT_Object *context);
static MPC_Object * GMPy_MPC_From_Complex(PyObject* obj, mpfr_prec_t rprec, mpfr_prec_t iprec, CTXT_Object *context);
#if 0
static MPC_Object * GMPy_MPC_From_ComplexAndCopy(PyObject* obj, mpfr_prec_t rprec, mpfr_prec_t iprec, CTXT_Object *context);
#endif
static PyObject * GMPy_MPC_Float_Slot(PyObject *self);
static PyObject * GMPy_MPC_Int_Slot(PyObject *self);
static PyObject * GMPy_PyStr_From_MPC(MPC_Object *self, int base, int digits, CTXT_Object *context);
static PyObject * GMPy_PyComplex_From_MPC(PyObject *self, PyObject *other);
/* support str() and repr() */
static PyObject * GMPy_MPC_Str_Slot(MPC_Object *self);
static PyObject * GMPy_MPC_Repr_Slot(MPC_Object *self);
/* Miscellaneous */
#ifdef SHARED
/* static int GMPy_MPC_convert_arg(PyObject *arg, PyObject **ptr); */
static GMPy_MPC_ConvertArg_RETURN GMPy_MPC_ConvertArg GMPy_MPC_ConvertArg_PROTO;
#endif
#ifdef __cplusplus
}
#endif
#endif
././@PaxHeader 0000000 0000000 0000000 00000000026 00000000000 010213 x ustar 00 22 mtime=1710307256.0
gmpy2-2.2.1/src/gmpy2_convert_mpfr.c 0000644 0001750 0001750 00000070063 14574233670 016020 0 ustar 00case case /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* gmpy_convert_mpfr.c *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Python interface to the GMP, MPFR, and MPC multiple precision *
* libraries. *
* *
* Copyright 2000 - 2009 Alex Martelli *
* *
* Copyright 2008 - 2024 Case Van Horsen *
* *
* This file is part of GMPY2. *
* *
* GMPY2 is free software: you can redistribute it and/or modify it under *
* the terms of the GNU Lesser General Public License as published by the *
* Free Software Foundation, either version 3 of the License, or (at your *
* option) any later version. *
* *
* GMPY2 is distributed in the hope that it will be useful, but WITHOUT *
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or *
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public *
* License for more details. *
* *
* You should have received a copy of the GNU Lesser General Public *
* License along with GMPY2; if not, see *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
/* This file contains all the conversion functions for MPFR data types.
*
* Overview
* --------
* gmpy2 tries to optimize the performance and accuracy of conversions from
* other numeric types. The basic operations (+, -, *, /) are optimized to
* directly work with the basic types such as C longs or doubles.
*
* gmpy2 supports two different strategies for creating new references to
* an mpfr instance. If bits (or prec) is set to 0, the precison of the
* result exactly matches the precision of the context. The exponent range
* is also limited to the exponents defined in the contest. This is the
* default behavior of the mpfr() function.
*
* If bits (or prec) is set to 1, the precision of the result depends on the
* type of the source.
*
* If the source number is already a radix-2 floating point number,
* the precision is not changed. In practical terms, this only applies
* to sources operands that are either an mpfr or Python double.
*
* In addition, the exponent range is taken from the global emin/emax values
* set in the MPFR library.
*
*/
/* If prec == 0:
* Return an reference to a new mpfr instance. The context argument
* specifies the precision, exponent range, and whether or not subnormals
* are allowed.
*
* This is the default behavior of the mpfr() constructor.
*
* If prec == 1:
* Return an additional reference to an existing mpfr. The precision is not
* changed. The exponent is not checked and may be outside the bounds
* specified in the context argument.
*
* This is used internally for parsing arguments to functions.
*
* If prec >= 2:
* Return a reference to a new mpfr instance. The precision is taken from
* the argument. n instance with the specified precision and the
* exponent is valid in the current context.
*
* This is used by mpfr() with an optional precision keyword.
*
* Since references to existing objects may be returned, the result should not
* modified in-place.
*/
static MPFR_Object *
GMPy_MPFR_From_MPFR(MPFR_Object *obj, mpfr_prec_t prec, CTXT_Object *context)
{
MPFR_Object *result = NULL;
/* Optimize the critical case when prec==1 or obj is NaN or Inf. */
if (prec == 1 || !mpfr_number_p(obj->f)) {
Py_INCREF((PyObject*)obj);
return obj;
}
CHECK_CONTEXT(context);
if (prec == 0)
prec = GET_MPFR_PREC(context);
/* Try to identify when an additional reference to existing instance can
* be returned. It is possible when (1) the precision matches, (2) the
* exponent is valid and not in the range that might require subnormal-
* ization, and (3) subnormalize is not enabled.
*/
if (prec == mpfr_get_prec(obj->f) &&
!context->ctx.subnormalize &&
obj->f->_mpfr_exp >= (context->ctx.emin + mpfr_get_prec(obj->f) - 1) &&
obj->f->_mpfr_exp <= context->ctx.emax
) {
Py_INCREF((PyObject*)obj);
return obj;
}
if ((result = GMPy_MPFR_New(prec, context))) {
mpfr_clear_flags();
result->rc = mpfr_set(result->f, obj->f, GET_MPFR_ROUND(context));
_GMPy_MPFR_Cleanup(&result, context);
}
return result;
}
static MPFR_Object *
GMPy_MPFR_From_PyLong(PyObject *obj, mpfr_prec_t prec, CTXT_Object *context)
{
MPFR_Object *result = NULL;
MPZ_Object *tempx = NULL;
int was_one = 0;
long temp;
CHECK_CONTEXT(context);
if (prec == 0)
prec = GET_MPFR_PREC(context);
if (prec == 1) {
/* This should be made accurate, but is it worth the overhead? */
/* It is only used if the value fits in a C long. */
prec = 64;
was_one = 1;
}
temp = GMPy_Integer_AsLongWithType(obj, GMPy_ObjectType(obj));
if ((temp == -1) && PyErr_Occurred()) {
PyErr_Clear();
if (!(tempx = GMPy_MPZ_From_PyLong(obj, context))) {
return NULL;
}
if (was_one)
prec = 1;
result = GMPy_MPFR_From_MPZ(tempx, prec, context);
Py_DECREF((PyObject*)tempx);
return result;
}
else {
if (!(result = GMPy_MPFR_New(prec, context)))
return NULL;
mpfr_clear_flags();
result->rc = mpfr_set_si(result->f, temp, GET_MPFR_ROUND(context));
if (!was_one) {
GMPY_MPFR_CHECK_RANGE(result, context);
}
GMPY_MPFR_EXCEPTIONS(result, context);
}
return result;
}
/* If prec==0, then the precision of the current context is used.
*
* If prec==1, then the precision of Python float type is used (typically 53).
*
* If prec>=2, then the specified precision is used.
*/
static MPFR_Object *
GMPy_MPFR_From_PyFloat(PyObject *obj, mpfr_prec_t prec, CTXT_Object *context)
{
MPFR_Object *result;
CHECK_CONTEXT(context);
if (prec == 0)
prec = GET_MPFR_PREC(context);
else if (prec == 1)
prec = DBL_MANT_DIG;
if ((result = GMPy_MPFR_New(prec, context))) {
mpfr_clear_flags();
result->rc = mpfr_set_d(result->f, PyFloat_AS_DOUBLE(obj), GET_MPFR_ROUND(context));
if (prec != 1) {
GMPY_MPFR_CHECK_RANGE(result, context);
}
GMPY_MPFR_SUBNORMALIZE(result, context);
GMPY_MPFR_EXCEPTIONS(result, context);
}
return result;
}
/* If prec==0, then the precision of the current context is used.
*
* If prec==1, then an exact conversion is done by using the bit length of the
* argument as the precision.
*
* If prec>=2, then the specified precision is used.
*/
static MPFR_Object *
GMPy_MPFR_From_MPZ(MPZ_Object *obj, mpfr_prec_t prec, CTXT_Object *context)
{
MPFR_Object *result;
int was_one = 0;
size_t bitlen;
CHECK_CONTEXT(context);
if (prec == 0)
prec = GET_MPFR_PREC(context);
if (prec == 1) {
bitlen = mpz_sizeinbase(obj->z, 2);
if (bitlen < MPFR_PREC_MIN) {
bitlen = MPFR_PREC_MIN;
}
if (bitlen > MPFR_PREC_MAX) {
OVERFLOW_ERROR("'mpz' to large to convert to 'mpfr'\n");
return NULL;
}
prec = (mpfr_prec_t)bitlen;
was_one = 1;
}
if ((result = GMPy_MPFR_New(prec, context))) {
mpfr_clear_flags();
result->rc = mpfr_set_z(result->f, obj->z, GET_MPFR_ROUND(context));
if (!was_one) {
GMPY_MPFR_CHECK_RANGE(result, context);
}
GMPY_MPFR_EXCEPTIONS(result, context);
}
return result;
}
/* If prec<2, then the precision of the current context is used.
*
* If prec>=2, then the specified precision is used.
*/
static MPFR_Object *
GMPy_MPFR_From_MPQ(MPQ_Object *obj, mpfr_prec_t prec, CTXT_Object *context)
{
MPFR_Object *result;
CHECK_CONTEXT(context);
if (prec < 2)
prec = GET_MPFR_PREC(context);
if ((result = GMPy_MPFR_New(prec, context))) {
mpfr_clear_flags();
result->rc = mpfr_set_q(result->f, obj->q, GET_MPFR_ROUND(context));
GMPY_MPFR_CHECK_RANGE(result, context);
GMPY_MPFR_SUBNORMALIZE(result, context);
GMPY_MPFR_EXCEPTIONS(result, context);
}
return result;
}
/* If prec<2, then the precision of the current context is used.
*
* If prec>=2, then the specified precision is used.
*/
static MPFR_Object *
GMPy_MPFR_From_Fraction(PyObject *obj, mpfr_prec_t prec, CTXT_Object *context)
{
MPFR_Object *result = NULL;
MPQ_Object *tempq;
CHECK_CONTEXT(context);
if ((tempq = GMPy_MPQ_From_Fraction(obj, context))) {
result = GMPy_MPFR_From_MPQ(tempq, prec, context);
Py_DECREF((PyObject*)tempq);
}
return result;
}
static MPFR_Object *
GMPy_MPFR_From_PyStr(PyObject *s, int base, mpfr_prec_t prec, CTXT_Object *context)
{
MPFR_Object *result;
MPQ_Object *tempq;
char *cp, *endptr;
Py_ssize_t len;
PyObject *ascii_str = ascii_str = GMPy_RemoveIgnoredASCII(s);
if (!ascii_str) return NULL;
CHECK_CONTEXT(context);
if (prec < 2)
prec = GET_MPFR_PREC(context);
len = PyBytes_Size(ascii_str);
cp = PyBytes_AsString(ascii_str);
/* Check for leading base indicators. */
if (base == 0) {
if (len > 2 && cp[0] == '0') {
if (cp[1] == 'b') { base = 2; cp += 2; len -= 2; }
else if (cp[1] == 'x') { base = 16; cp += 2; len -= 2; }
else { base = 10; }
}
else {
base = 10;
}
}
else if (cp[0] == '0') {
/* If the specified base matches the leading base indicators, then
* we need to skip the base indicators.
*/
if (cp[1] =='b' && base == 2) { cp += 2; len -= 2; }
else if (cp[1] =='x' && base == 16) { cp += 2; len -= 2; }
}
if (!(result = GMPy_MPFR_New(prec, context))) {
Py_XDECREF(ascii_str);
return NULL;
}
/* delegate the rest to MPFR */
mpfr_clear_flags();
result->rc = mpfr_strtofr(result->f, cp, &endptr, base, GET_MPFR_ROUND(context));
Py_XDECREF(ascii_str);
if (len != (Py_ssize_t)(endptr - cp)) {
VALUE_ERROR("invalid digits");
Py_DECREF((PyObject*)result);
return NULL;
}
/* If the context requests subnormals and the result is in the range for subnormals,
* we use exact conversion via intermediate conversion to an mpq.
*
* The sticky bit returned by MPFR's string conversion appears to only reflect the
* portion of the string needed to compute the correctly rounded result. It does not
* accurately reflect whether or not the result is larger or smaller than the entire
* input string. A correct sticky bit is needed by mfpr_subnormalize. Converting the
* string to an mpq and then converting the mpq to an mpfr does properly set the
* sticky bit.
*/
if (mpfr_regular_p(result->f) &&
base == 10 &&
context->ctx.subnormalize &&
result->f->_mpfr_exp <= context->ctx.emin + mpfr_get_prec(result->f) - 1)
{
if (!(tempq = GMPy_MPQ_From_PyStr(s, base, context))) {
Py_DECREF((PyObject*)result);
return NULL;
}
mpfr_clear_flags();
result->rc = mpfr_set_q(result->f, tempq->q, GET_MPFR_ROUND(context));
Py_DECREF((PyObject*)tempq);
}
GMPY_MPFR_CHECK_RANGE(result, context);
GMPY_MPFR_SUBNORMALIZE(result, context);
GMPY_MPFR_EXCEPTIONS(result, context);
return result;
}
/* GMPy_MPFR_From_Real() converts a real number (see IS_REAL()) to an mpfr.
*
* If prec==0, then the result has the precision of the current context.
*
* If prec==1 and the value can be converted exactly (i.e. the input value is
* a floating-point number using radix-2 representation or an integer), then
* the conversion is done with the maximum possible precision. If the input
* value can't be converted exactly, then the context precision is used.
*
* If prec >=2, then the specified precision is used.
*
* The return value is guaranteed to have a valid exponent.
*/
static MPFR_Object *
GMPy_MPFR_From_RealWithType(PyObject *obj, int xtype, mp_prec_t prec, CTXT_Object *context)
{
CHECK_CONTEXT(context);
if (IS_TYPE_MPFR(xtype))
return GMPy_MPFR_From_MPFR((MPFR_Object*)obj, prec, context);
if (IS_TYPE_PyFloat(xtype))
return GMPy_MPFR_From_PyFloat(obj, prec, context);
if (IS_TYPE_MPQ(xtype))
return GMPy_MPFR_From_MPQ((MPQ_Object*)obj, prec, context);
if (IS_TYPE_MPZANY(xtype))
return GMPy_MPFR_From_MPZ((MPZ_Object*)obj, prec, context);
if (IS_TYPE_PyInteger(xtype))
return GMPy_MPFR_From_PyLong(obj, prec, context);
if (IS_TYPE_PyFraction(xtype))
return GMPy_MPFR_From_Fraction(obj, prec, context);
if (IS_TYPE_HAS_MPFR(xtype)) {
MPFR_Object *res = (MPFR_Object *) PyObject_CallMethod(obj, "__mpfr__", NULL);
if (res != NULL && MPFR_Check(res)) {
return res;
}
else {
Py_XDECREF((PyObject*)res);
goto error;
}
}
if (IS_TYPE_HAS_MPQ(xtype)) {
MPQ_Object *res = (MPQ_Object *) PyObject_CallMethod(obj, "__mpq__", NULL);
if (res != NULL && MPQ_Check(res)) {
MPFR_Object * temp = GMPy_MPFR_From_MPQ(res, prec, context);
Py_DECREF(res);
return temp;
}
else {
Py_XDECREF((PyObject*)res);
goto error;
}
}
if (IS_TYPE_HAS_MPZ(xtype)) {
MPZ_Object *res = (MPZ_Object *) PyObject_CallMethod(obj, "__mpz__", NULL);
if (res != NULL && MPZ_Check(res)) {
MPFR_Object * temp = GMPy_MPFR_From_MPZ(res, prec, context);
Py_DECREF(res);
return temp;
}
else {
Py_XDECREF((PyObject*)res);
goto error;
}
}
error:
TYPE_ERROR("object could not be converted to 'mpfr'");
return NULL;
}
static MPFR_Object *
GMPy_MPFR_From_Real(PyObject *obj, mp_prec_t prec, CTXT_Object *context)
{
return GMPy_MPFR_From_RealWithType(obj, GMPy_ObjectType(obj),
prec, context);
}
static MPFR_Object *
GMPy_MPFR_From_RealWithTypeAndCopy(PyObject *obj, int xtype, mp_prec_t prec, CTXT_Object *context)
{
MPFR_Object *result = NULL, *temp = NULL;
result = GMPy_MPFR_From_RealWithType(obj, xtype, prec, context);
if (result == NULL)
return result;
if (Py_REFCNT(result) == 1)
return result;
if (!(temp = GMPy_MPFR_New(mpfr_get_prec(result->f), context))) {
/* LCOV_EXCL_START */
return NULL;
/* LCOV_EXCL_STOP */
}
/* Since the precision of temp is the same as the precision of result,
* there shouldn't be any rounding.
*/
mpfr_set(temp->f, result->f, MPFR_RNDN);
Py_DECREF((PyObject*)result);
return temp;
}
static MPZ_Object *
GMPy_MPZ_From_MPFR(MPFR_Object *obj, CTXT_Object *context)
{
MPZ_Object *result;
CHECK_CONTEXT(context);
if ((result = GMPy_MPZ_New(context))) {
if (mpfr_nan_p(MPFR(obj))) {
Py_DECREF((PyObject*)result);
VALUE_ERROR("'mpz' does not support NaN");
return NULL;
}
if (mpfr_inf_p(MPFR(obj))) {
Py_DECREF((PyObject*)result);
OVERFLOW_ERROR("'mpz' does not support Infinity");
return NULL;
}
/* return code is ignored */
mpfr_get_z(result->z, MPFR(obj), GET_MPFR_ROUND(context));
}
return result;
}
static XMPZ_Object *
GMPy_XMPZ_From_MPFR(MPFR_Object *self, CTXT_Object *context)
{
XMPZ_Object *result;
CHECK_CONTEXT(context);
if ((result = GMPy_XMPZ_New(context))) {
if (mpfr_nan_p(MPFR(self))) {
Py_DECREF((PyObject*)result);
VALUE_ERROR("'xmpz' does not support NaN");
return NULL;
}
if (mpfr_inf_p(MPFR(self))) {
Py_DECREF((PyObject*)result);
OVERFLOW_ERROR("'xmpz' does not support Infinity");
return NULL;
}
/* return code is ignored */
mpfr_get_z(result->z, MPFR(self), GET_MPFR_ROUND(context));
}
return result;
}
/* Return the simpliest rational number that approximates 'self' to the
* requested error bound.
*
* 'bits' is used as the working precision for the calculations.
* - If (bits == 0) then the precision of 'self' is used.
* - If (bits > precision of 'self') then use precision of 'self'.
*
* 'err' is the maximum error in the rational approximation.
* - If (err > 0) then prec
* - If (err == NULL), then the requested precision is 1/(2**prec).
* This should return the smallest fraction that returns the
* same interval that includes 'self'.
* 'err'. If 'err' is negative, then the requested
* precision is -2**abs(int(err)). If 'err' is NULL, then the requested
* precision is -2**prec. If 'prec' is 0, then the requested precision is
* the precision of 'self'.
*/
static PyObject *
stern_brocot(MPFR_Object* self, MPFR_Object *err, mpfr_prec_t bits, int mayz, CTXT_Object *context)
{
PyObject* result = NULL;
MPQ_Object *mpqres = NULL;
MPZ_Object *mpzres = NULL;
int i, negative, errsign;
mpfr_t f, al, a, r1[3], r2[3], temperr, minerr, curerr, newerr, temp;
if (mpfr_nan_p(self->f)) {
VALUE_ERROR("Cannot convert NaN to a number.");
return NULL;
}
if (mpfr_inf_p(self->f)) {
OVERFLOW_ERROR("Cannot convert Infinity to a number.");
return NULL;
}
if (!bits) {
bits = mpfr_get_prec(self->f);
}
if (err) {
/* Make a copy. */
mpfr_init2(temperr, mpfr_get_prec(err->f));
mpfr_set(temperr, err->f, MPFR_RNDN);
}
else {
mpfr_init2(temperr, mpfr_get_prec(self->f));
mpfr_set_ui(temperr, 0, MPFR_RNDN);
}
errsign = mpfr_sgn(temperr);
if (errsign <= 0 && (bits < 2 || bits > mpfr_get_prec(self->f))) {
VALUE_ERROR("Requested precision out-of-bounds.");
mpfr_clear(temperr);
return NULL;
}
if (errsign == 0) {
mpfr_set_si(temperr, 1, MPFR_RNDN);
mpfr_div_2exp(temperr, temperr, bits, MPFR_RNDN);
}
else if (errsign < 0) {
long ubits;
mpfr_abs(temperr, temperr, MPFR_RNDN);
mpfr_floor(temperr, temperr);
ubits = mpfr_get_si(temperr, MPFR_RNDN);
if (ubits < 2 || ubits > mpfr_get_prec(self->f)) {
VALUE_ERROR("Requested precision out-of-bounds.");
mpfr_clear(temperr);
return NULL;
}
mpfr_set_si(temperr, 1, MPFR_RNDN);
mpfr_div_2exp(temperr, temperr, ubits, MPFR_RNDN);
}
if (!(mpqres = GMPy_MPQ_New(context)) ||
!(mpzres = GMPy_MPZ_New(context))) {
Py_XDECREF((PyObject*)mpqres);
Py_XDECREF((PyObject*)mpzres);
mpfr_clear(temperr);
return NULL;
}
mpfr_init2(minerr, bits);
mpfr_set(minerr, temperr, MPFR_RNDN);
mpfr_clear(temperr);
mpfr_init2(f, bits);
if (mpfr_sgn(self->f) < 0) {
negative = 1;
mpfr_abs(f, self->f, MPFR_RNDN);
}
else {
negative = 0;
mpfr_set(f, self->f, MPFR_RNDN);
}
mpfr_init2(al, bits);
mpfr_set(al, f, MPFR_RNDN);
mpfr_init2(a, bits);
mpfr_floor(a, al);
mpfr_init2(temp, bits);
for (i=0; i<3; ++i) {
mpfr_init2(r1[i], bits);
mpfr_init2(r2[i], bits);
}
mpfr_set_si(r1[0], 0, MPFR_RNDN);
mpfr_set_si(r1[1], 0, MPFR_RNDN);
mpfr_set_si(r1[2], 1, MPFR_RNDN);
mpfr_set_si(r2[0], 0, MPFR_RNDN);
mpfr_set_si(r2[1], 1, MPFR_RNDN);
mpfr_set(r2[2], a, MPFR_RNDN);
mpfr_init2(curerr, bits);
mpfr_init2(newerr, bits);
mpfr_reldiff(curerr, f, a, MPFR_RNDN);
while (mpfr_cmp(curerr, minerr) > 0) {
mpfr_sub(temp, al, a, MPFR_RNDN);
mpfr_ui_div(al, 1, temp, MPFR_RNDN);
mpfr_floor(a, al);
mpfr_swap(r1[0], r1[1]);
mpfr_swap(r1[1], r1[2]);
//mpfr_fma(r1[2], r1[1], a, r1[0], MPFR_RNDN);
mpfr_mul(r1[2], r1[1], a, MPFR_RNDN);
mpfr_add(r1[2], r1[2], r1[0], MPFR_RNDN);
mpfr_swap(r2[0], r2[1]);
mpfr_swap(r2[1], r2[2]);
//mpfr_fma(r2[2], r2[1], a, r2[0], MPFR_RNDN);
mpfr_mul(r2[2], r2[1], a, MPFR_RNDN);
mpfr_add(r2[2], r2[2], r2[0], MPFR_RNDN);
mpfr_div(temp, r2[2], r1[2], MPFR_RNDN);
mpfr_reldiff(newerr, f, temp, MPFR_RNDN);
if(mpfr_cmp(curerr, newerr) <= 0) {
mpfr_swap(r1[1],r1[2]);
mpfr_swap(r2[1],r2[2]);
break;
}
mpfr_swap(curerr, newerr);
}
/* Note: both mpqres and mpzrec have been created. Remember to delete the
* one you don't need.
*/
if (mayz && (mpfr_cmp_ui(r1[2],1) == 0)) {
mpfr_get_z(mpzres->z, r2[2], MPFR_RNDN);
if (negative) {
mpz_neg(mpzres->z, mpzres->z);
}
result = (PyObject*)mpzres;
Py_DECREF(mpqres);
}
else {
mpfr_get_z(mpq_numref(mpqres->q), r2[2], MPFR_RNDN);
mpfr_get_z(mpq_denref(mpqres->q), r1[2], MPFR_RNDN);
if (negative) {
mpz_neg(mpq_numref(mpqres->q), mpq_numref(mpqres->q));
}
result = (PyObject*)mpqres;
Py_DECREF(mpzres);
}
mpfr_clear(minerr);
mpfr_clear(al);
mpfr_clear(a);
mpfr_clear(f);
for (i=0; i<3; ++i) {
mpfr_clear(r1[i]);
mpfr_clear(r2[i]);
}
mpfr_clear(curerr);
mpfr_clear(newerr);
mpfr_clear(temp);
return result;
}
static MPQ_Object *
GMPy_MPQ_From_MPFR(MPFR_Object *self, CTXT_Object *context)
{
mpfr_exp_t temp, twocount;
MPQ_Object *result;
CHECK_CONTEXT(context);
if (mpfr_nan_p(self->f)) {
VALUE_ERROR("can not convert NaN to MPQ");
return NULL;
}
if (mpfr_inf_p(self->f)) {
OVERFLOW_ERROR("can not convert Infinity to MPQ");
return NULL;
}
if (!(result = GMPy_MPQ_New(context))) {
return NULL;
}
if (mpfr_zero_p(self->f)) {
mpz_set_ui(mpq_numref(result->q), 0);
mpz_set_ui(mpq_denref(result->q), 1);
}
else {
temp = mpfr_get_z_2exp(mpq_numref(result->q), self->f);
twocount = (mpfr_exp_t)mpz_scan1(mpq_numref(result->q), 0);
if (twocount) {
temp += twocount;
mpz_div_2exp(mpq_numref(result->q), mpq_numref(result->q), twocount);
}
mpz_set_ui(mpq_denref(result->q), 1);
if (temp > 0)
mpz_mul_2exp(mpq_numref(result->q), mpq_numref(result->q), temp);
else if (temp < 0)
mpz_mul_2exp(mpq_denref(result->q), mpq_denref(result->q), -temp);
}
return result;
}
static PyObject *
GMPy_PyLong_From_MPFR(MPFR_Object *obj, CTXT_Object *context)
{
PyObject *result;
MPZ_Object *tempz;
CHECK_CONTEXT(context);
if (!(tempz = GMPy_MPZ_From_MPFR(obj, context)))
return NULL;
result = GMPy_PyLong_From_MPZ(tempz, context);
Py_DECREF((PyObject*)tempz);
return result;
}
static PyObject *
GMPy_MPFR_Int_Slot(MPFR_Object *self) {
return GMPy_PyLong_From_MPFR(self, NULL);
}
static PyObject *
GMPy_PyFloat_From_MPFR(MPFR_Object *self, CTXT_Object *context)
{
double res;
CHECK_CONTEXT(context);
res = mpfr_get_d(self->f, GET_MPFR_ROUND(context));
return PyFloat_FromDouble(res);
}
static PyObject *
GMPy_MPFR_Float_Slot(MPFR_Object *self) {
return GMPy_PyFloat_From_MPFR(self, NULL);
}
static PyObject*
GMPy_PyStr_From_MPFR(MPFR_Object *self, int base, int digits, CTXT_Object *context)
{
PyObject *result;
char *buffer;
mpfr_exp_t the_exp;
CHECK_CONTEXT(context);
/* check arguments are valid */
if (!((base >= 2) && (base <= 62))) {
VALUE_ERROR("base must be in the interval [2,62]");
return NULL;
}
if ((digits < 0) || (digits == 1)) {
VALUE_ERROR("digits must be 0 or >= 2");
return NULL;
}
/* Process special cases first */
if (!(mpfr_regular_p(self->f))) {
if (mpfr_nan_p(self->f)) {
return Py_BuildValue("(sii)", "nan", 0, 0);
}
else if (mpfr_inf_p(self->f) && !mpfr_signbit(self->f)) {
return Py_BuildValue("(sii)", "inf", 0, 0);
}
else if (mpfr_inf_p(self->f) && mpfr_signbit(self->f)) {
return Py_BuildValue("(sii)", "-inf", 0, 0);
}
/* 0 is not considered a 'regular" number */
else if (mpfr_signbit(self->f)) {
return Py_BuildValue("(sii)", "-0", 0, mpfr_get_prec(self->f));
}
else {
return Py_BuildValue("(sii)", "0", 0, mpfr_get_prec(self->f));
}
}
/* obtain digits-string and exponent */
buffer = mpfr_get_str(0, &the_exp, base, digits, self->f, GET_MPFR_ROUND(context));
if (!*buffer) {
SYSTEM_ERROR("Internal error in Pympfr_To_PyStr");
return NULL;
}
result = Py_BuildValue("(sii)", buffer, the_exp, mpfr_get_prec(self->f));
mpfr_free_str(buffer);
return result;
}
#ifdef SHARED
/*
* coerce any number to a mpf
*/
int
GMPy_MPFR_ConvertArg(PyObject *arg, PyObject **ptr)
{
MPFR_Object* newob = GMPy_MPFR_From_RealWithType(arg, GMPy_ObjectType(arg),
1, NULL);
if (newob) {
*ptr = (PyObject*)newob;
return 1;
}
else {
TYPE_ERROR("argument can not be converted to 'mpfr'");
return 0;
}
}
#endif
/* str and repr implementations for mpfr */
static PyObject *
GMPy_MPFR_Str_Slot(MPFR_Object *self)
{
PyObject *result, *temp;
long precision;
char fmtstr[60];
precision = (long)(log10(2) * (double)mpfr_get_prec(MPFR(self))) + 2;
sprintf(fmtstr, "{0:.%ldg}", precision);
temp = PyUnicode_FromString(fmtstr);
if (!temp)
return NULL;
result = PyObject_CallMethod(temp, "format", "O", self);
Py_DECREF(temp);
return result;
}
static PyObject *
GMPy_MPFR_Repr_Slot(MPFR_Object *self)
{
PyObject *result, *temp;
long precision, bits;
char fmtstr[60];
bits = mpfr_get_prec(MPFR(self));
precision = (long)(log10(2) * (double)bits) + 2;
if (mpfr_number_p(MPFR(self)) && bits != DBL_MANT_DIG)
sprintf(fmtstr, "mpfr('{0:.%ldg}',%ld)", precision, bits);
else
sprintf(fmtstr, "mpfr('{0:.%ldg}')", precision);
temp = PyUnicode_FromString(fmtstr);
if (!temp)
return NULL;
result = PyObject_CallMethod(temp, "format", "O", self);
Py_DECREF(temp);
return result;
}
static PyObject *
mpfr_ascii(mpfr_t self, int base, int digits, int round)
{
PyObject *result;
char *buffer;
mpfr_exp_t the_exp;
/* Process special cases first */
if (!(mpfr_regular_p(self))) {
if (mpfr_nan_p(self)) {
return Py_BuildValue("(sii)", "nan", 0, 0);
}
else if (mpfr_inf_p(self) && !mpfr_signbit(self)) {
return Py_BuildValue("(sii)", "inf", 0, 0);
}
else if (mpfr_inf_p(self) && mpfr_signbit(self)) {
return Py_BuildValue("(sii)", "-inf", 0, 0);
}
/* 0 is not considered a 'regular" number */
else if (mpfr_signbit(self)) {
return Py_BuildValue("(sii)", "-0", 0, mpfr_get_prec(self));
}
else {
return Py_BuildValue("(sii)", "0", 0, mpfr_get_prec(self));
}
}
/* obtain digits-string and exponent */
buffer = mpfr_get_str(0, &the_exp, base, digits, self, round);
if (!*buffer) {
SYSTEM_ERROR("Internal error in mpfr_ascii");
return NULL;
}
result = Py_BuildValue("(sii)", buffer, the_exp, mpfr_get_prec(self));
mpfr_free_str(buffer);
return result;
}
././@PaxHeader 0000000 0000000 0000000 00000000026 00000000000 010213 x ustar 00 22 mtime=1710307256.0
gmpy2-2.2.1/src/gmpy2_convert_mpfr.h 0000644 0001750 0001750 00000010307 14574233670 016020 0 ustar 00case case /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* gmpy2_convert_mpfr.h *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Python interface to the GMP, MPFR, and MPC multiple precision *
* libraries. *
* *
* Copyright 2000 - 2009 Alex Martelli *
* *
* Copyright 2008 - 2024 Case Van Horsen *
* *
* This file is part of GMPY2. *
* *
* GMPY2 is free software: you can redistribute it and/or modify it under *
* the terms of the GNU Lesser General Public License as published by the *
* Free Software Foundation, either version 3 of the License, or (at your *
* option) any later version. *
* *
* GMPY2 is distributed in the hope that it will be useful, but WITHOUT *
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or *
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public *
* License for more details. *
* *
* You should have received a copy of the GNU Lesser General Public *
* License along with GMPY2; if not, see *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
#ifndef GMPY2_CONVERT_MPFR_H
#define GMPY2_CONVERT_MPFR_H
#ifdef __cplusplus
extern "C" {
#endif
/********* Pympfr Conversions *********/
/* Conversions with Pympfr */
static MPFR_Object * GMPy_MPFR_From_MPFR(MPFR_Object *obj, mpfr_prec_t prec, CTXT_Object *context);
static MPFR_Object * GMPy_MPFR_From_PyLong(PyObject *obj, mpfr_prec_t prec, CTXT_Object *context);
static MPFR_Object * GMPy_MPFR_From_PyFloat(PyObject *obj, mpfr_prec_t prec, CTXT_Object *context);
static MPFR_Object * GMPy_MPFR_From_MPZ(MPZ_Object *obj, mpfr_prec_t prec, CTXT_Object *context);
static MPFR_Object * GMPy_MPFR_From_MPQ(MPQ_Object *obj, mpfr_prec_t prec, CTXT_Object *context);
static MPFR_Object * GMPy_MPFR_From_Fraction(PyObject *obj, mpfr_prec_t prec, CTXT_Object *context);
static MPFR_Object * GMPy_MPFR_From_PyStr(PyObject *s, int base, mpfr_prec_t prec, CTXT_Object *context);
static MPFR_Object * GMPy_MPFR_From_Real(PyObject* obj, mpfr_prec_t prec, CTXT_Object *context);
static MPFR_Object * GMPy_MPFR_From_RealWithTypeAndCopy(PyObject* obj, int xtype, mpfr_prec_t prec, CTXT_Object *context);
static PyObject * GMPy_PyLong_From_MPFR(MPFR_Object *obj, CTXT_Object *context);
static MPZ_Object * GMPy_MPZ_From_MPFR(MPFR_Object *obj, CTXT_Object *context);
static XMPZ_Object * GMPy_XMPZ_From_MPFR(MPFR_Object *self, CTXT_Object *context);
static MPQ_Object * GMPy_MPQ_From_MPFR(MPFR_Object *self, CTXT_Object *context);
static PyObject * GMPy_PyFloat_From_MPFR(MPFR_Object *self, CTXT_Object *context);
static PyObject * GMPy_PyStr_From_MPFR(MPFR_Object *self, int base, int digits, CTXT_Object *context);
static PyObject * GMPy_MPFR_Str_Slot(MPFR_Object *self);
static PyObject * GMPy_MPFR_Repr_Slot(MPFR_Object *self);
static PyObject * GMPy_MPFR_Int_Slot(MPFR_Object *self);
static PyObject * GMPy_MPFR_Float_Slot(MPFR_Object *self);
/* Miscellaneous */
#ifdef SHARED
/* static int GMPy_MPFR_ConvertArg(PyObject *arg, PyObject **ptr); */
static GMPy_MPFR_ConvertArg_RETURN GMPy_MPFR_ConvertArg GMPy_MPFR_ConvertArg_PROTO;
#endif
static PyObject * stern_brocot(MPFR_Object* self, MPFR_Object *err, mpfr_prec_t prec, int mayz, CTXT_Object *context);
static PyObject * mpfr_ascii(mpfr_t self, int base, int digits, int round);
#ifdef __cplusplus
}
#endif
#endif
././@PaxHeader 0000000 0000000 0000000 00000000026 00000000000 010213 x ustar 00 22 mtime=1710307256.0
gmpy2-2.2.1/src/gmpy2_convert_utils.c 0000644 0001750 0001750 00000023077 14574233670 016217 0 ustar 00case case /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* gmpy2_convert_utils.c *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Python interface to the GMP, MPFR, and MPC multiple precision *
* libraries. *
* *
* Copyright 2000 - 2009 Alex Martelli *
* *
* Copyright 2008 - 2024 Case Van Horsen *
* *
* This file is part of GMPY2. *
* *
* GMPY2 is free software: you can redistribute it and/or modify it under *
* the terms of the GNU Lesser General Public License as published by the *
* Free Software Foundation, either version 3 of the License, or (at your *
* option) any later version. *
* *
* GMPY2 is distributed in the hope that it will be useful, but WITHOUT *
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or *
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public *
* License for more details. *
* *
* You should have received a copy of the GNU Lesser General Public *
* License along with GMPY2; if not, see *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
/* ======================================================================== *
* Conversion between Integer objects and C types. *
* ======================================================================== *
*
* Optimized routines for converting an Integer object (Python's integer
* type(s), mpz, plus types defining __mpz__) to various C types.
*/
static long
GMPy_Integer_AsLongWithType(PyObject *x, int xtype)
{
if IS_TYPE_PyInteger(xtype) {
return PyLong_AsLong(x);
}
if (IS_TYPE_MPZANY(xtype)) {
if (mpz_fits_slong_p(MPZ(x))) {
return (long) mpz_get_si(MPZ(x));
}
else {
OVERFLOW_ERROR("value could not be converted to C long");
return -1;
}
}
if (IS_TYPE_HAS_MPZ(xtype)) {
long result = 0;
PyObject *temp_mpz = PyObject_CallMethod(x, "__mpz__", NULL);
if ((temp_mpz != NULL) && MPZ_Check(temp_mpz)) {
if (mpz_fits_slong_p(MPZ(temp_mpz))) {
result = (long) mpz_get_si(MPZ(temp_mpz));
}
else {
OVERFLOW_ERROR("value could not be converted to C long");
result = -1;
}
}
Py_XDECREF(temp_mpz);
return result;
}
TYPE_ERROR("could not convert object to integer");
return (long)-1;
}
static long
GMPy_Integer_AsLong(PyObject *x)
{
return GMPy_Integer_AsLongWithType(x, GMPy_ObjectType(x));
}
static unsigned long
GMPy_Integer_AsUnsignedLongWithType(PyObject *x, int xtype)
{
if IS_TYPE_PyInteger(xtype) {
return PyLong_AsUnsignedLong(x);
}
if (IS_TYPE_MPZANY(xtype)) {
if (mpz_fits_ulong_p(MPZ(x))) {
return (unsigned long) mpz_get_ui(MPZ(x));
}
else {
OVERFLOW_ERROR("value could not be converted to C long");
return (unsigned long)-1;
}
}
if (IS_TYPE_HAS_MPZ(xtype)) {
unsigned long result = 0;
PyObject *temp_mpz = PyObject_CallMethod(x, "__mpz__", NULL);
if ((temp_mpz != NULL) && MPZ_Check(temp_mpz)) {
if (mpz_fits_ulong_p(MPZ(temp_mpz))) {
result = (unsigned long) mpz_get_ui(MPZ(temp_mpz));
}
else {
OVERFLOW_ERROR("value could not be converted to C long");
result = (unsigned long)-1;
}
}
Py_XDECREF(temp_mpz);
return result;
}
TYPE_ERROR("could not convert object to integer");
return (unsigned long)-1;
}
static unsigned long
GMPy_Integer_AsUnsignedLong(PyObject *x)
{
return GMPy_Integer_AsUnsignedLongWithType(x, GMPy_ObjectType(x));
}
static long
GMPy_Integer_AsUnsignedLongOrLong(PyObject *x, int *is_signed)
{
long result = (long)GMPy_Integer_AsUnsignedLong(x);
if (result == -1 && PyErr_Occurred()) {
*is_signed = 1;
PyErr_Clear();
result = GMPy_Integer_AsLong(x);
if (result == -1 && PyErr_Occurred()) {
return -1;
}
}
return result;
}
#define PY_ABS_LLONG_MIN (0-(unsigned PY_LONG_LONG)PY_LLONG_MIN)
static PY_LONG_LONG
GMPy_Integer_AsLongLongWithType(PyObject *x, int xtype)
{
int sign = 0;
if IS_TYPE_PyInteger(xtype) {
return PyLong_AsLongLong(x);
}
if (IS_TYPE_MPZANY(xtype)) {
unsigned PY_LONG_LONG xtemp = 0;
PY_LONG_LONG result = 0;
sign = mpz_sgn(MPZ(x));
if (sign) {
if (mpz_sizeinbase(MPZ(x), 256) <= sizeof(xtemp)) {
mpz_export(&xtemp, NULL, 1, sizeof(xtemp), 0, 0, MPZ(x));
}
if (xtemp <= (unsigned PY_LONG_LONG)PY_LLONG_MAX) {
result = (PY_LONG_LONG)xtemp * sign;
}
else if (sign < 0 && xtemp == PY_ABS_LLONG_MIN) {
result = PY_LLONG_MIN;
}
else {
OVERFLOW_ERROR("value could not be converted to C long long");
result = -1;
}
}
return result;
}
if (IS_TYPE_HAS_MPZ(xtype)) {
unsigned PY_LONG_LONG xtemp = 0;
PY_LONG_LONG result = 0;
PyObject *temp_mpz = PyObject_CallMethod(x, "__mpz__", NULL);
if (temp_mpz != NULL && MPZ_Check(temp_mpz)) {
sign = mpz_sgn(MPZ(temp_mpz));
if (sign) {
if (mpz_sizeinbase(MPZ(x), 256) <= sizeof(xtemp)) {
mpz_export(&xtemp, NULL, 1, sizeof(xtemp), 0, 0, MPZ(x));
}
if (xtemp <= (unsigned PY_LONG_LONG)PY_LLONG_MAX) {
result = (PY_LONG_LONG)xtemp * sign;
}
else if (sign < 0 && xtemp == PY_ABS_LLONG_MIN) {
result = PY_LLONG_MIN;
}
else {
OVERFLOW_ERROR("value could not be converted to C long long");
result = -1;
}
}
}
Py_XDECREF(temp_mpz);
return result;
}
TYPE_ERROR("could not convert object to integer");
return -1;
}
static PY_LONG_LONG
GMPy_Integer_AsLongLong(PyObject *x)
{
return GMPy_Integer_AsLongLongWithType(x, GMPy_ObjectType(x));
}
static mp_bitcnt_t
GMPy_Integer_AsMpBitCnt(PyObject *x)
{
if(sizeof(mp_bitcnt_t) == sizeof(unsigned long long))
return GMPy_Integer_AsUnsignedLongLong(x);
if(sizeof(mp_bitcnt_t) == sizeof(unsigned long))
return GMPy_Integer_AsUnsignedLong(x);
SYSTEM_ERROR("Unexpected sizes in GMPy_Integer_AsMpBitCnt.");
}
static mp_bitcnt_t
GMPy_PyLong_AsMpBitCnt(PyObject *x)
{
if(sizeof(mp_bitcnt_t) == sizeof(unsigned long long))
return PyLong_AsUnsignedLongLong(x);
if(sizeof(mp_bitcnt_t) == sizeof(unsigned long))
return PyLong_AsUnsignedLong(x);
SYSTEM_ERROR("Unexpected sizes in GMPy_PyLong_AsMpBitCnt.");
}
static PyObject *
GMPy_PyLong_FromMpBitCnt(mp_bitcnt_t n)
{
if(sizeof(mp_bitcnt_t) == sizeof(unsigned long long))
return PyLong_FromUnsignedLongLong((unsigned long long)n);
if(sizeof(mp_bitcnt_t) == sizeof(unsigned long))
return PyLong_FromUnsignedLong((unsigned long)n);
SYSTEM_ERROR("Unexpected sizes in GMPy_PyLong_FromMpBitCnt.");
}
static unsigned PY_LONG_LONG
GMPy_Integer_AsUnsignedLongLongWithType(PyObject *x, int xtype)
{
if IS_TYPE_PyInteger(xtype) {
return PyLong_AsUnsignedLongLong(x);
}
if (IS_TYPE_MPZANY(xtype)) {
unsigned PY_LONG_LONG xtemp = 0;
int sign = mpz_sgn(MPZ(x));
if (sign >= 0) {
if (mpz_sizeinbase(MPZ(x), 256) <= sizeof(xtemp)) {
mpz_export(&xtemp, NULL, 1, sizeof(xtemp), 0, 0, MPZ(x));
}
else {
OVERFLOW_ERROR("value could not be converted to C long long");
xtemp = (unsigned PY_LONG_LONG)-1;
}
}
return xtemp;
}
if (IS_TYPE_HAS_MPZ(xtype)) {
unsigned PY_LONG_LONG xtemp = 0;
PyObject *temp_mpz = PyObject_CallMethod(x, "__mpz__", NULL);
if (temp_mpz != NULL && MPZ_Check(temp_mpz)) {
int sign = mpz_sgn(MPZ(temp_mpz));
if (sign >= 0) {
if (mpz_sizeinbase(MPZ(x), 256) <= sizeof(xtemp)) {
mpz_export(&xtemp, NULL, 1, sizeof(xtemp), 0, 0, MPZ(x));
}
else {
OVERFLOW_ERROR("value could not be converted to C long long");
xtemp = (unsigned PY_LONG_LONG)-1;
}
}
}
Py_XDECREF((PyObject*)temp_mpz);
return xtemp;
}
TYPE_ERROR("could not convert object to integer");
return -1;
}
static unsigned PY_LONG_LONG
GMPy_Integer_AsUnsignedLongLong(PyObject *x)
{
return GMPy_Integer_AsUnsignedLongLongWithType(x, GMPy_ObjectType(x));
}
././@PaxHeader 0000000 0000000 0000000 00000000026 00000000000 010213 x ustar 00 22 mtime=1710307256.0
gmpy2-2.2.1/src/gmpy2_convert_utils.h 0000644 0001750 0001750 00000006335 14574233670 016222 0 ustar 00case case /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* gmpy_convert_utils.h *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Python interface to the GMP, MPFR, and MPC multiple precision *
* libraries. *
* *
* Copyright 2000 - 2009 Alex Martelli *
* *
* Copyright 2008 - 2024 Case Van Horsen *
* *
* This file is part of GMPY2. *
* *
* GMPY2 is free software: you can redistribute it and/or modify it under *
* the terms of the GNU Lesser General Public License as published by the *
* Free Software Foundation, either version 3 of the License, or (at your *
* option) any later version. *
* *
* GMPY2 is distributed in the hope that it will be useful, but WITHOUT *
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or *
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public *
* License for more details. *
* *
* You should have received a copy of the GNU Lesser General Public *
* License along with GMPY2; if not, see *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
#ifndef GMPY2_CONVERT_UTILS_H
#define GMPY2_CONVERT_UTILS_H
#ifdef __cplusplus
extern "C" {
#endif
/* ======================================================================== *
* Conversion between Integer objects and C types. *
* ======================================================================== */
static long GMPy_Integer_AsLongWithType(PyObject *x, int xtype);
static long GMPy_Integer_AsLong(PyObject *x);
static unsigned long GMPy_Integer_AsUnsignedLongWithType(PyObject *x, int xtype);
static unsigned long GMPy_Integer_AsUnsignedLong(PyObject *x);
static long GMPy_Integer_AsUnsignedLongOrLong(PyObject *x, int *is_signed);
static PY_LONG_LONG GMPy_Integer_AsLongLongWithType(PyObject *x, int xtype);
static PY_LONG_LONG GMPy_Integer_AsLongLong(PyObject *x);
static mp_bitcnt_t GMPy_Integer_AsMpBitCnt(PyObject *x);
static mp_bitcnt_t GMPy_PyLong_AsMpBitCnt(PyObject *x);
static PyObject * GMPy_PyLong_FromMpBitCnt(mp_bitcnt_t n);
static unsigned PY_LONG_LONG GMPy_Integer_AsUnsignedLongLongWithType(PyObject *x, int xtype);
static unsigned PY_LONG_LONG GMPy_Integer_AsUnsignedLongLong(PyObject *x);
#define GMPy_Integer_AsSsize_t (Py_ssize_t)GMPy_Integer_AsLongLong
static mp_bitcnt_t GMPy_Integer_AsMpBitCnt(PyObject *x);
#ifdef __cplusplus
}
#endif
#endif
././@PaxHeader 0000000 0000000 0000000 00000000026 00000000000 010213 x ustar 00 22 mtime=1710307256.0
gmpy2-2.2.1/src/gmpy2_divmod.c 0000644 0001750 0001750 00000032567 14574233670 014605 0 ustar 00case case /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* gmpy2_divmod.c *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Python interface to the GMP, MPFR, and MPC multiple precision *
* libraries. *
* *
* Copyright 2000 - 2009 Alex Martelli *
* *
* Copyright 2008 - 2024 Case Van Horsen *
* *
* This file is part of GMPY2. *
* *
* GMPY2 is free software: you can redistribute it and/or modify it under *
* the terms of the GNU Lesser General Public License as published by the *
* Free Software Foundation, either version 3 of the License, or (at your *
* option) any later version. *
* *
* GMPY2 is distributed in the hope that it will be useful, but WITHOUT *
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or *
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public *
* License for more details. *
* *
* You should have received a copy of the GNU Lesser General Public *
* License along with GMPY2; if not, see *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
/* This file implements __divmod__ and context.divmod().
*/
static PyObject *
GMPy_Integer_DivModWithType(PyObject *x, int xtype, PyObject *y, int ytype,
CTXT_Object *context)
{
PyObject *result = NULL;
MPZ_Object *tempx = NULL, *tempy = NULL, *rem = NULL, *quo = NULL;
CHECK_CONTEXT(context);
if (!(result = PyTuple_New(2)) ||
!(rem = GMPy_MPZ_New(context)) ||
!(quo = GMPy_MPZ_New(context))) {
/* LCOV_EXCL_START */
goto error;
/* LCOV_EXCL_STOP */
}
if (IS_TYPE_MPZANY(xtype)) {
if (IS_TYPE_MPZANY(ytype)) {
if (mpz_sgn(MPZ(y)) == 0) {
ZERO_ERROR("division or modulo by zero");
goto error;
}
GMPY_MAYBE_BEGIN_ALLOW_THREADS(context);
mpz_fdiv_qr(quo->z, rem->z, MPZ(x), MPZ(y));
GMPY_MAYBE_END_ALLOW_THREADS(context);
PyTuple_SET_ITEM(result, 0, (PyObject*)quo);
PyTuple_SET_ITEM(result, 1, (PyObject*)rem);
return result;
}
if (IS_TYPE_PyInteger(ytype)) {
int error;
long temp = PyLong_AsLongAndOverflow(y, &error);
if (error) {
/* Use quo->z as a temporary variable. */
mpz_set_PyLong(quo->z, y);
GMPY_MAYBE_BEGIN_ALLOW_THREADS(context);
mpz_fdiv_qr(quo->z, rem->z, MPZ(x), quo->z);
GMPY_MAYBE_END_ALLOW_THREADS(context);
}
else if (temp > 0) {
mpz_fdiv_qr_ui(quo->z, rem->z, MPZ(x), temp);
}
else if (temp == 0) {
ZERO_ERROR("division or modulo by zero");
goto error;
}
else {
mpz_cdiv_qr_ui(quo->z, rem->z, MPZ(x), -temp);
mpz_neg(quo->z, quo->z);
}
PyTuple_SET_ITEM(result, 0, (PyObject*)quo);
PyTuple_SET_ITEM(result, 1, (PyObject*)rem);
return result;
}
}
if (IS_TYPE_MPZANY(ytype)) {
if (IS_TYPE_PyInteger(xtype)) {
if (mpz_sgn(MPZ(y)) == 0) {
ZERO_ERROR("division or modulo by zero");
goto error;
}
else {
mpz_set_PyLong(quo->z, x);
GMPY_MAYBE_BEGIN_ALLOW_THREADS(context);
mpz_fdiv_qr(quo->z, rem->z, quo->z, MPZ(y));
GMPY_MAYBE_END_ALLOW_THREADS(context);
PyTuple_SET_ITEM(result, 0, (PyObject*)quo);
PyTuple_SET_ITEM(result, 1, (PyObject*)rem);
return (PyObject*)result;
}
}
}
if (IS_TYPE_INTEGER(xtype) && IS_TYPE_INTEGER(ytype)) {
if (!(tempx = GMPy_MPZ_From_IntegerWithType(x, xtype, context)) ||
!(tempy = GMPy_MPZ_From_IntegerWithType(y, ytype, context))) {
/* LCOV_EXCL_START */
goto error;
/* LCOV_EXCL_STOP */
}
if (mpz_sgn(tempy->z) == 0) {
ZERO_ERROR("division or modulo by zero");
goto error;
}
GMPY_MAYBE_BEGIN_ALLOW_THREADS(context);
mpz_fdiv_qr(quo->z, rem->z, tempx->z, tempy->z);
GMPY_MAYBE_END_ALLOW_THREADS(context);
Py_DECREF((PyObject*)tempx);
Py_DECREF((PyObject*)tempy);
PyTuple_SET_ITEM(result, 0, (PyObject*)quo);
PyTuple_SET_ITEM(result, 1, (PyObject*)rem);
return result;
}
/* LCOV_EXCL_START */
TYPE_ERROR("divmod() arguments not supported");
/* LCOV_EXCL_STOP */
error:
Py_XDECREF((PyObject*)tempx);
Py_XDECREF((PyObject*)tempy);
Py_XDECREF((PyObject*)rem);
Py_XDECREF((PyObject*)quo);
Py_XDECREF(result);
return NULL;
}
static PyObject *
GMPy_Rational_DivModWithType(PyObject *x, int xtype, PyObject *y, int ytype,
CTXT_Object *context)
{
MPQ_Object *tempx = NULL, *tempy = NULL, *rem = NULL;
MPZ_Object *quo = NULL;
PyObject *result = NULL;
CHECK_CONTEXT(context);
if (!(result = PyTuple_New(2)) ||
!(rem = GMPy_MPQ_New(context)) ||
!(quo = GMPy_MPZ_New(context))) {
/* LCOV_EXCL_START */
goto error;
/* LCOV_EXCL_STOP */
}
if (IS_TYPE_RATIONAL(xtype) && IS_TYPE_RATIONAL(ytype)) {
if (!(tempx = GMPy_MPQ_From_RationalWithType(x, xtype, context)) ||
!(tempy = GMPy_MPQ_From_RationalWithType(y, ytype, context))) {
/* LCOV_EXCL_START */
goto error;
/* LCOV_EXCL_STOP */
}
if (mpq_sgn(tempy->q) == 0) {
ZERO_ERROR("division or modulo by zero");
goto error;
}
GMPY_MAYBE_BEGIN_ALLOW_THREADS(context);
mpq_div(rem->q, tempx->q, tempy->q);
mpz_fdiv_q(quo->z, mpq_numref(rem->q), mpq_denref(rem->q));
/* Need to calculate x - quo * y. */
mpq_set_z(rem->q, quo->z);
mpq_mul(rem->q, rem->q, tempy->q);
mpq_sub(rem->q, tempx->q, rem->q);
GMPY_MAYBE_END_ALLOW_THREADS(context);
Py_DECREF((PyObject*)tempx);
Py_DECREF((PyObject*)tempy);
PyTuple_SET_ITEM(result, 0, (PyObject*)quo);
PyTuple_SET_ITEM(result, 1, (PyObject*)rem);
return result;
}
/* LCOV_EXCL_START */
TYPE_ERROR("divmod() arguments not supported");
error:
Py_XDECREF((PyObject*)tempx);
Py_XDECREF((PyObject*)tempy);
Py_XDECREF((PyObject*)rem);
Py_XDECREF((PyObject*)quo);
Py_XDECREF(result);
return NULL;
/* LCOV_EXCL_STOP */
}
static PyObject *
GMPy_Real_DivModWithType(PyObject *x, int xtype, PyObject *y, int ytype,
CTXT_Object *context)
{
MPFR_Object *tempx = NULL, *tempy = NULL, *quo = NULL, *rem = NULL, *temp;
PyObject *result = NULL;
CHECK_CONTEXT(context);
if (!(result = PyTuple_New(2)) ||
!(rem = GMPy_MPFR_New(0, context)) ||
!(quo = GMPy_MPFR_New(0, context))) {
/* LCOV_EXCL_START */
goto error;
/* LCOV_EXCL_STOP */
}
if (IS_TYPE_REAL(xtype) && IS_TYPE_REAL(ytype)) {
if (!(tempx = GMPy_MPFR_From_RealWithType(x, xtype, 1, context)) ||
!(tempy = GMPy_MPFR_From_RealWithType(y, ytype, 1, context))) {
/* LCOV_EXCL_START */
goto error;
/* LCOV_EXCL_STOP */
}
if (mpfr_zero_p(tempy->f)) {
context->ctx.divzero = 1;
if (context->ctx.traps & TRAP_DIVZERO) {
GMPY_DIVZERO("divmod() division by zero");
goto error;
}
mpfr_set_nan(quo->f);
mpfr_set_nan(rem->f);
goto okay;
}
if (mpfr_nan_p(tempx->f) || mpfr_nan_p(tempy->f) || mpfr_inf_p(tempx->f)) {
context->ctx.invalid = 1;
if (context->ctx.traps & TRAP_INVALID) {
GMPY_INVALID("divmod() invalid operation");
goto error;
}
mpfr_set_nan(quo->f);
mpfr_set_nan(rem->f);
goto okay;
}
if (mpfr_inf_p(tempy->f)) {
context->ctx.invalid = 1;
if (context->ctx.traps & TRAP_INVALID) {
GMPY_INVALID("divmod() invalid operation");
goto error;
}
if (mpfr_zero_p(tempx->f)) {
mpfr_set_zero(quo->f, mpfr_sgn(tempy->f));
mpfr_set_zero(rem->f, mpfr_sgn(tempy->f));
}
else if ((mpfr_signbit(tempx->f)) != (mpfr_signbit(tempy->f))) {
mpfr_set_si(quo->f, -1, MPFR_RNDN);
mpfr_set_inf(rem->f, mpfr_sgn(tempy->f));
}
else {
mpfr_set_si(quo->f, 0, MPFR_RNDN);
rem->rc = mpfr_set(rem->f, tempx->f, MPFR_RNDN);
}
goto okay;
}
if (!(temp = GMPy_MPFR_New(0, context))) {
/* LCOV_EXCL_START */
goto error;
/* LCOV_EXCL_STOP */
}
mpfr_fmod(rem->f, tempx->f, tempy->f, MPFR_RNDN);
mpfr_sub(temp->f, tempx->f, rem->f, MPFR_RNDN);
mpfr_div(quo->f, temp->f, tempy->f, MPFR_RNDN);
Py_DECREF((PyObject*)temp);
if (!mpfr_zero_p(rem->f)) {
if ((mpfr_sgn(tempy->f) < 0) != (mpfr_sgn(rem->f) < 0)) {
mpfr_add(rem->f, rem->f, tempy->f, MPFR_RNDN);
mpfr_sub_ui(quo->f, quo->f, 1, MPFR_RNDN);
}
}
else {
mpfr_copysign(rem->f, rem->f, tempy->f, MPFR_RNDN);
}
if (!mpfr_zero_p(quo->f)) {
mpfr_round(quo->f, quo->f);
}
else {
mpfr_setsign(quo->f, quo->f, mpfr_sgn(tempx->f) * mpfr_sgn(tempy->f) - 1, MPFR_RNDN);
}
GMPY_MPFR_CHECK_RANGE(quo, context);
GMPY_MPFR_CHECK_RANGE(rem, context);
GMPY_MPFR_SUBNORMALIZE(quo, context);
GMPY_MPFR_SUBNORMALIZE(rem, context);
okay:
Py_DECREF((PyObject*)tempx);
Py_DECREF((PyObject*)tempy);
PyTuple_SET_ITEM(result, 0, (PyObject*)quo);
PyTuple_SET_ITEM(result, 1, (PyObject*)rem);
return (PyObject*)result;
}
/* LCOV_EXCL_START */
TYPE_ERROR("divmod() arguments not supported");
error:
Py_XDECREF((PyObject*)tempx);
Py_XDECREF((PyObject*)tempy);
Py_XDECREF((PyObject*)rem);
Py_XDECREF((PyObject*)quo);
Py_XDECREF(result);
return NULL;
/* LCOV_EXCL_STOP */
}
static PyObject *
GMPy_Complex_DivModWithType(PyObject *x, int xtype, PyObject *y, int ytype,
CTXT_Object *context)
{
TYPE_ERROR("can't take floor or mod of complex number.");
return NULL;
}
static PyObject *
GMPy_Number_DivMod_Slot(PyObject *x, PyObject *y)
{
int xtype = GMPy_ObjectType(x);
int ytype = GMPy_ObjectType(y);
if (IS_TYPE_INTEGER(xtype) && IS_TYPE_INTEGER(ytype))
return GMPy_Integer_DivModWithType(x, xtype, y, ytype, NULL);
if (IS_TYPE_RATIONAL(xtype) && IS_TYPE_RATIONAL(ytype))
return GMPy_Rational_DivModWithType(x, xtype, y, ytype, NULL);
if (IS_TYPE_REAL(xtype) && IS_TYPE_REAL(ytype))
return GMPy_Real_DivModWithType(x, xtype, y, ytype, NULL);
if (IS_TYPE_COMPLEX(xtype) && IS_TYPE_COMPLEX(ytype))
return GMPy_Complex_DivModWithType(x, xtype, y, ytype, NULL);
Py_RETURN_NOTIMPLEMENTED;
}
static PyObject *
GMPy_Number_DivMod(PyObject *x, PyObject *y, CTXT_Object *context)
{
int xtype = GMPy_ObjectType(x);
int ytype = GMPy_ObjectType(y);
if (IS_TYPE_INTEGER(xtype) && IS_TYPE_INTEGER(ytype))
return GMPy_Integer_DivModWithType(x, xtype, y, ytype, NULL);
if (IS_TYPE_RATIONAL(xtype) && IS_TYPE_RATIONAL(ytype))
return GMPy_Rational_DivModWithType(x, xtype, y, ytype, NULL);
if (IS_TYPE_REAL(xtype) && IS_TYPE_REAL(ytype))
return GMPy_Real_DivModWithType(x, xtype, y, ytype, NULL);
if (IS_TYPE_COMPLEX(xtype) && IS_TYPE_COMPLEX(ytype))
return GMPy_Complex_DivModWithType(x, xtype, y, ytype, NULL);
TYPE_ERROR("divmod() argument type not supported");
return NULL;
}
PyDoc_STRVAR(GMPy_doc_context_divmod,
"context.divmod(x, y, /) -> tuple[mpz|mpfr, mpz|mpq|mpfr]\n\n"
"Return divmod(x, y).\n\n"
"Note: overflow, underflow, and inexact exceptions are not supported for\n"
"`mpfr` arguments.");
static PyObject *
GMPy_Context_DivMod(PyObject *self, PyObject *args)
{
if (PyTuple_GET_SIZE(args) != 2) {
TYPE_ERROR("div_mod() requires 2 arguments");
return NULL;
}
return GMPy_Number_DivMod(PyTuple_GET_ITEM(args, 0),
PyTuple_GET_ITEM(args, 1),
(CTXT_Object*)self);
}
././@PaxHeader 0000000 0000000 0000000 00000000026 00000000000 010213 x ustar 00 22 mtime=1710307256.0
gmpy2-2.2.1/src/gmpy2_divmod.h 0000644 0001750 0001750 00000005336 14574233670 014604 0 ustar 00case case /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* gmpy2_divmod.h *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Python interface to the GMP, MPFR, and MPC multiple precision *
* libraries. *
* *
* Copyright 2000 - 2009 Alex Martelli *
* *
* Copyright 2008 - 2024 Case Van Horsen *
* *
* This file is part of GMPY2. *
* *
* GMPY2 is free software: you can redistribute it and/or modify it under *
* the terms of the GNU Lesser General Public License as published by the *
* Free Software Foundation, either version 3 of the License, or (at your *
* option) any later version. *
* *
* GMPY2 is distributed in the hope that it will be useful, but WITHOUT *
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or *
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public *
* License for more details. *
* *
* You should have received a copy of the GNU Lesser General Public *
* License along with GMPY2; if not, see *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
#ifndef GMPY2_DIVMOD_H
#define GMPY2_DIVMOD_H
#ifdef __cplusplus
extern "C" {
#endif
/* Public API */
static PyObject * GMPy_Number_DivMod(PyObject *x, PyObject *y, CTXT_Object *context);
/* Private API */
static PyObject * GMPy_Integer_DivModWithType(PyObject *x, int xtype, PyObject *y, int ytype, CTXT_Object *context);
static PyObject * GMPy_Rational_DivModWithType(PyObject *x, int xtype, PyObject *y, int ytype, CTXT_Object *context);
static PyObject * GMPy_Real_DivModWithType(PyObject *x, int xtype, PyObject *y, int ytype, CTXT_Object *context);
static PyObject * GMPy_Complex_DivModWithType(PyObject *x, int xtype, PyObject *y, int ytype, CTXT_Object *context);
static PyObject * GMPy_Number_DivMod_Slot(PyObject *x, PyObject *y);
static PyObject * GMPy_Context_DivMod(PyObject *self, PyObject *args);
#ifdef __cplusplus
}
#endif
#endif
././@PaxHeader 0000000 0000000 0000000 00000000026 00000000000 010213 x ustar 00 22 mtime=1710307256.0
gmpy2-2.2.1/src/gmpy2_floordiv.c 0000644 0001750 0001750 00000027575 14574233670 015152 0 ustar 00case case /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* gmpy2_floordiv.c *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Python interface to the GMP, MPFR, and MPC multiple precision *
* libraries. *
* *
* Copyright 2000 - 2009 Alex Martelli *
* *
* Copyright 2008 - 2024 Case Van Horsen *
* *
* This file is part of GMPY2. *
* *
* GMPY2 is free software: you can redistribute it and/or modify it under *
* the terms of the GNU Lesser General Public License as published by the *
* Free Software Foundation, either version 3 of the License, or (at your *
* option) any later version. *
* *
* GMPY2 is distributed in the hope that it will be useful, but WITHOUT *
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or *
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public *
* License for more details. *
* *
* You should have received a copy of the GNU Lesser General Public *
* License along with GMPY2; if not, see *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
/* This file implements the // operator, gmpy2.floor_div() and
* context.floor_div().
*/
static PyObject *
GMPy_Integer_FloorDivWithType(PyObject *x, int xtype, PyObject *y, int ytype,
CTXT_Object *context)
{
MPZ_Object *result = NULL;
CHECK_CONTEXT(context);
if (!(result = GMPy_MPZ_New(context))) {
/* LCOV_EXCL_START */
return NULL;
/* LCOV_EXCL_STOP */
}
if (IS_TYPE_MPZANY(xtype)) {
if (IS_TYPE_MPZANY(ytype)) {
if (mpz_sgn(MPZ(y)) == 0) {
ZERO_ERROR("division or modulo by zero");
Py_DECREF((PyObject*)result);
return NULL;
}
GMPY_MAYBE_BEGIN_ALLOW_THREADS(context);
mpz_fdiv_q(result->z, MPZ(x), MPZ(y));
GMPY_MAYBE_END_ALLOW_THREADS(context);
return (PyObject*)result;
}
if (IS_TYPE_PyInteger(ytype)) {
int error;
long temp = PyLong_AsLongAndOverflow(y, &error);
if (!error) {
if (temp > 0) {
mpz_fdiv_q_ui(result->z, MPZ(x), temp);
}
else if (temp == 0) {
ZERO_ERROR("division or modulo by zero");
Py_DECREF((PyObject*)result);
return NULL;
}
else {
mpz_cdiv_q_ui(result->z, MPZ(x), -temp);
mpz_neg(result->z, result->z);
}
}
else {
mpz_set_PyLong(result->z, y);
GMPY_MAYBE_BEGIN_ALLOW_THREADS(context);
mpz_fdiv_q(result->z, MPZ(x), result->z);
GMPY_MAYBE_END_ALLOW_THREADS(context);
}
return (PyObject*)result;
}
}
if (IS_TYPE_MPZANY(ytype)) {
if (mpz_sgn(MPZ(y)) == 0) {
ZERO_ERROR("division or modulo by zero");
Py_DECREF((PyObject*)result);
return NULL;
}
if (IS_TYPE_PyInteger(xtype)) {
mpz_set_PyLong(result->z, x);
GMPY_MAYBE_BEGIN_ALLOW_THREADS(context);
mpz_fdiv_q(result->z, result->z, MPZ(y));
GMPY_MAYBE_END_ALLOW_THREADS(context);
return (PyObject*)result;
}
}
if (IS_TYPE_INTEGER(xtype) && (IS_TYPE_INTEGER(ytype))) {
MPZ_Object *tempx = NULL, *tempy = NULL;
if (!(tempx = GMPy_MPZ_From_IntegerWithType(x, xtype, context)) ||
!(tempy = GMPy_MPZ_From_IntegerWithType(y, ytype, context))) {
/* LCOV_EXCL_START */
Py_XDECREF((PyObject*)tempx);
Py_XDECREF((PyObject*)tempy);
Py_DECREF((PyObject*)result);
return NULL;
/* LCOV_EXCL_STOP */
}
if (mpz_sgn(tempy->z) == 0) {
ZERO_ERROR("division or modulo by zero");
Py_XDECREF((PyObject*)tempx);
Py_XDECREF((PyObject*)tempy);
Py_DECREF((PyObject*)result);
return NULL;
}
GMPY_MAYBE_BEGIN_ALLOW_THREADS(context);
mpz_fdiv_q(result->z, tempx->z, tempy->z);
GMPY_MAYBE_END_ALLOW_THREADS(context);
Py_DECREF((PyObject*)tempx);
Py_DECREF((PyObject*)tempy);
return (PyObject*)result;
}
/* LCOV_EXCL_START */
Py_DECREF((PyObject*)result);
TYPE_ERROR("floor_div() argument type not supported");
return NULL;
/* LCOV_EXCL_STOP */
}
static PyObject *
GMPy_Rational_FloorDivWithType(PyObject *x, int xtype, PyObject *y, int ytype,
CTXT_Object *context)
{
MPZ_Object *result = NULL;
MPQ_Object *tempq = NULL;
CHECK_CONTEXT(context);
if (!(result = GMPy_MPZ_New(context)) ||
!(tempq = GMPy_MPQ_New(context))) {
/* LCOV_EXCL_START */
Py_XDECREF((PyObject*)result);
Py_XDECREF((PyObject*)tempq);
return NULL;
/* LCOV_EXCL_STOP */
}
if (IS_TYPE_MPQ(xtype) && IS_TYPE_MPQ(ytype)) {
if (mpq_sgn(MPQ(y)) == 0) {
ZERO_ERROR("division or modulo by zero");
Py_DECREF((PyObject*)result);
Py_DECREF((PyObject*)tempq);
return NULL;
}
GMPY_MAYBE_BEGIN_ALLOW_THREADS(context);
mpq_div(tempq->q, MPQ(x), MPQ(y));
mpz_fdiv_q(result->z, mpq_numref(tempq->q), mpq_denref(tempq->q));
GMPY_MAYBE_END_ALLOW_THREADS(context);
Py_DECREF((PyObject*)tempq);
return (PyObject*)result;
}
if (IS_TYPE_RATIONAL(xtype) && IS_TYPE_RATIONAL(ytype)) {
MPQ_Object *tempx = NULL, *tempy = NULL;
if (!(tempx = GMPy_MPQ_From_RationalWithType(x, xtype, context)) ||
!(tempy = GMPy_MPQ_From_RationalWithType(y, ytype, context))) {
/* LCOV_EXCL_START */
Py_XDECREF((PyObject*)tempx);
Py_XDECREF((PyObject*)tempy);
Py_DECREF((PyObject*)result);
Py_DECREF((PyObject*)tempq);
return NULL;
/* LCOV_EXCL_STOP */
}
if (mpq_sgn(tempy->q) == 0) {
ZERO_ERROR("division or modulo by zero");
Py_DECREF((PyObject*)tempx);
Py_DECREF((PyObject*)tempy);
Py_DECREF((PyObject*)result);
Py_DECREF((PyObject*)tempq);
return NULL;
}
GMPY_MAYBE_BEGIN_ALLOW_THREADS(context);
mpq_div(tempq->q, tempx->q, tempy->q);
mpz_fdiv_q(result->z, mpq_numref(tempq->q), mpq_denref(tempq->q));
GMPY_MAYBE_END_ALLOW_THREADS(context);
Py_DECREF((PyObject*)tempx);
Py_DECREF((PyObject*)tempy);
Py_DECREF((PyObject*)tempq);
return (PyObject*)result;
}
/* LCOV_EXCL_START */
Py_DECREF((PyObject*)tempq);
Py_DECREF((PyObject*)result);
TYPE_ERROR("floor_div() argument type not supported");
return NULL;
/* LCOV_EXCL_STOP */
}
/* Attempt floor division of two numbers and return an mpfr. The code path is
* optimized by checking for mpfr objects first. Returns Py_NotImplemented if
* both objects are not valid reals. */
static PyObject *
GMPy_Real_FloorDivWithType(PyObject *x, int xtype, PyObject *y, int ytype,
CTXT_Object *context)
{
MPFR_Object *result = NULL;
CHECK_CONTEXT(context);
if (!(result = GMPy_MPFR_New(0, context))) {
/* LCOV_EXCL_START */
return NULL;
/* LCOV_EXCL_STOP */
}
if (IS_TYPE_MPFR(xtype) && IS_TYPE_MPFR(ytype)) {
mpfr_clear_flags();
result->rc = mpfr_div(result->f, MPFR(x), MPFR(y), GET_MPFR_ROUND(context));
result->rc = mpfr_floor(result->f, result->f);
_GMPy_MPFR_Cleanup(&result, context);
return (PyObject*)result;
}
/* Handle the remaining cases.
* Note: verify that MPZ if converted at full precision! */
if (IS_TYPE_REAL(xtype) && IS_TYPE_REAL(ytype)) {
MPFR_Object *tempx = NULL, *tempy = NULL;
if (!(tempx = GMPy_MPFR_From_RealWithType(x, xtype, 1, context)) ||
!(tempy = GMPy_MPFR_From_RealWithType(y, ytype, 1, context))) {
/* LCOV_EXCL_START */
Py_XDECREF((PyObject*)tempx);
Py_XDECREF((PyObject*)tempy);
Py_DECREF((PyObject*)result);
return NULL;
/* LCOV_EXCL_STOP */
}
mpfr_clear_flags();
result->rc = mpfr_div(result->f, MPFR(tempx), MPFR(tempy), GET_MPFR_ROUND(context));
result->rc = mpfr_floor(result->f, result->f);
Py_DECREF((PyObject*)tempx);
Py_DECREF((PyObject*)tempy);
_GMPy_MPFR_Cleanup(&result, context);
return (PyObject*)result;
}
/* LCOV_EXCL_START */
Py_DECREF((PyObject*)result);
TYPE_ERROR("floor_div() argument type not supported");
return NULL;
/* LCOV_EXCL_STOP */
}
static PyObject *
GMPy_Complex_FloorDivWithType(PyObject *x, int xtype, PyObject *y, int ytype,
CTXT_Object *context)
{
TYPE_ERROR("can't take floor of complex number");
return NULL;
}
/* Implement all the slot methods here. */
static PyObject *
GMPy_Number_FloorDiv_Slot(PyObject *x, PyObject *y)
{
int xtype = GMPy_ObjectType(x);
int ytype = GMPy_ObjectType(y);
if (IS_TYPE_INTEGER(xtype) && IS_TYPE_INTEGER(ytype))
return GMPy_Integer_FloorDivWithType(x, xtype, y, ytype, NULL);
if (IS_TYPE_RATIONAL(xtype) && IS_TYPE_RATIONAL(ytype))
return GMPy_Rational_FloorDivWithType(x, xtype, y, ytype, NULL);
if (IS_TYPE_REAL(xtype) && IS_TYPE_REAL(ytype))
return GMPy_Real_FloorDivWithType(x, xtype, y, ytype, NULL);
if (IS_TYPE_COMPLEX(xtype) && IS_TYPE_COMPLEX(ytype))
return GMPy_Complex_FloorDivWithType(x, xtype, y, ytype, NULL);
Py_RETURN_NOTIMPLEMENTED;
}
PyDoc_STRVAR(GMPy_doc_floordiv,
"floor_div(x, y, /) -> mpz | mpfr\n\n"
"Return x // y; uses floor division.");
static PyObject *
GMPy_Number_FloorDiv(PyObject *x, PyObject *y, CTXT_Object *context)
{
int xtype = GMPy_ObjectType(x);
int ytype = GMPy_ObjectType(y);
if (IS_TYPE_INTEGER(xtype) && IS_TYPE_INTEGER(ytype))
return GMPy_Integer_FloorDivWithType(x, xtype, y, ytype, NULL);
if (IS_TYPE_RATIONAL(xtype) && IS_TYPE_RATIONAL(ytype))
return GMPy_Rational_FloorDivWithType(x, xtype, y, ytype, NULL);
if (IS_TYPE_REAL(xtype) && IS_TYPE_REAL(ytype))
return GMPy_Real_FloorDivWithType(x, xtype, y, ytype, NULL);
if (IS_TYPE_COMPLEX(xtype) && IS_TYPE_COMPLEX(ytype))
return GMPy_Complex_FloorDivWithType(x, xtype, y, ytype, NULL);
TYPE_ERROR("floor_div() argument type not supported");
return NULL;
}
PyDoc_STRVAR(GMPy_doc_context_floordiv,
"context.floor_div(x, y, /) -> mpz | mpfr\n\n"
"Return x // y; uses floor division.");
static PyObject *
GMPy_Context_FloorDiv(PyObject *self, PyObject *args)
{
if (PyTuple_GET_SIZE(args) != 2) {
TYPE_ERROR("floor_div() requires 2 arguments");
return NULL;
}
return GMPy_Number_FloorDiv(PyTuple_GET_ITEM(args, 0),
PyTuple_GET_ITEM(args, 1),
(CTXT_Object*)self);
}
././@PaxHeader 0000000 0000000 0000000 00000000026 00000000000 010213 x ustar 00 22 mtime=1710307256.0
gmpy2-2.2.1/src/gmpy2_floordiv.h 0000644 0001750 0001750 00000005356 14574233670 015150 0 ustar 00case case /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* gmpy2_floordiv.h *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Python interface to the GMP, MPFR, and MPC multiple precision *
* libraries. *
* *
* Copyright 2000 - 2009 Alex Martelli *
* *
* Copyright 2008 - 2024 Case Van Horsen *
* *
* This file is part of GMPY2. *
* *
* GMPY2 is free software: you can redistribute it and/or modify it under *
* the terms of the GNU Lesser General Public License as published by the *
* Free Software Foundation, either version 3 of the License, or (at your *
* option) any later version. *
* *
* GMPY2 is distributed in the hope that it will be useful, but WITHOUT *
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or *
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public *
* License for more details. *
* *
* You should have received a copy of the GNU Lesser General Public *
* License along with GMPY2; if not, see *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
#ifndef GMPY2_FLOORDIV_H
#define GMPY2_FLOORDIV_H
#ifdef __cplusplus
extern "C" {
#endif
/* Public API */
static PyObject * GMPy_Number_FloorDiv(PyObject *x, PyObject *y, CTXT_Object *context);
/* Private API */
static PyObject * GMPy_Integer_FloorDivWithType(PyObject *x, int xtype, PyObject *y, int ytype, CTXT_Object *context);
static PyObject * GMPy_Rational_FloorDivWithType(PyObject *x, int xtype, PyObject *y, int ytype, CTXT_Object *context);
static PyObject * GMPy_Real_FloorDivWithType(PyObject *x, int xtype, PyObject *y, int ytype, CTXT_Object *context);
static PyObject * GMPy_Complex_FloorDivWithType(PyObject *x, int xtype, PyObject *y, int ytype, CTXT_Object *context);
static PyObject * GMPy_Number_FloorDiv_Slot(PyObject *x, PyObject *y);
static PyObject * GMPy_Context_FloorDiv(PyObject *self, PyObject *args);
#ifdef __cplusplus
}
#endif
#endif
././@PaxHeader 0000000 0000000 0000000 00000000026 00000000000 010213 x ustar 00 22 mtime=1710307256.0
gmpy2-2.2.1/src/gmpy2_format.c 0000644 0001750 0001750 00000060665 14574233670 014613 0 ustar 00case case /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* gmpy2_format.c *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Python interface to the GMP, MPFR, and MPC multiple precision *
* libraries. *
* *
* Copyright 2000 - 2009 Alex Martelli *
* *
* Copyright 2008 - 2024 Case Van Horsen *
* *
* This file is part of GMPY2. *
* *
* GMPY2 is free software: you can redistribute it and/or modify it under *
* the terms of the GNU Lesser General Public License as published by the *
* Free Software Foundation, either version 3 of the License, or (at your *
* option) any later version. *
* *
* GMPY2 is distributed in the hope that it will be useful, but WITHOUT *
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or *
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public *
* License for more details. *
* *
* You should have received a copy of the GNU Lesser General Public *
* License along with GMPY2; if not, see *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
PyDoc_STRVAR(GMPy_doc_mpz_format,
"x.__format__(fmt) -> str\n\n"
"Return a Python string by formatting `mpz` 'x' using the format string\n"
"'fmt'. A valid format string consists of:\n\n"
" optional alignment code:\n\n"
" '<' -> left shifted in field\n"
" '>' -> right shifted in field\n"
" '^' -> centered in field\n\n"
" optional leading sign code:\n\n"
" '+' -> always display leading sign\n"
" '-' -> only display minus sign\n"
" ' ' -> minus for negative values, space for positive values\n\n"
" optional base indicator\n\n"
" '#' -> precede binary, octal, or hex with 0b, 0o or 0x\n\n"
" optional width\n\n"
" optional conversion code:\n\n"
" 'd' -> decimal format\n"
" 'b' -> binary format\n"
" 'o' -> octal format\n"
" 'x' -> hex format\n"
" 'X' -> upper-case hex format\n\n"
"The default format is 'd'.");
/* Formatting occurs in two phases. Pympz_ascii() is used to create a string
* with the appropriate binary/octal/decimal/hex formatting, including the
* leading sign character (+ , -, or space) and base encoding (0b, 0o, or 0x).
* Left/right/centering using the specified width is done by creating a
* format string and calling the __format__() method of the string object
* returned by Pympz_ascii().
*/
static PyObject *
GMPy_MPZ_Format(PyObject *self, PyObject *args)
{
PyObject *result = NULL, *mpzstr = NULL;
char *fmtcode = 0;
unsigned char *p1, *p2;
char fmt[30];
int base = 10, option = 16;
int seensign = 0, seenindicator = 0, seenalign = 0, seendigits = 0;
if (!CHECK_MPZANY(self)) {
TYPE_ERROR("requires mpz type");
return NULL;
}
if (!PyArg_ParseTuple(args, "s", &fmtcode))
return NULL;
p2 = (unsigned char*)fmt;
for (p1 = (unsigned char*)fmtcode; *p1 != '\00'; p1++) {
if (*p1 == '<' || *p1 == '>' || *p1 == '^') {
if (seenalign || seensign || seenindicator || seendigits) {
VALUE_ERROR("Invalid conversion specification");
return NULL;
}
else {
*(p2++) = *p1;
seenalign = 1;
continue;
}
}
if (*p1 == '+') {
if (seensign || seenindicator || seendigits) {
VALUE_ERROR("Invalid conversion specification");
return NULL;
}
else {
option |= 2;
seensign = 1;
continue;
}
}
if (*p1 == '-') {
if (seensign || seenindicator || seendigits) {
VALUE_ERROR("Invalid conversion specification");
return NULL;
}
else {
seensign = 1;
continue;
}
}
if (*p1 == ' ') {
if (seensign || seenindicator || seendigits) {
VALUE_ERROR("Invalid conversion specification");
return NULL;
}
else {
option |= 4;
seensign = 1;
continue;
}
}
if (*p1 == '#') {
if (seenindicator || seendigits) {
VALUE_ERROR("Invalid conversion specification");
return NULL;
}
else {
option |= 8;
seenindicator = 1;
continue;
}
}
if (isdigit(*p1)) {
if (!seenalign) {
*(p2++) = '>';
seenalign = 1;
}
*(p2++) = *p1;
seendigits = 1;
continue;
}
if (*p1 == 'b') {
base = 2;
break;
}
if (*p1 == 'o') {
base = 8;
break;
}
if (*p1 == 'x') {
base = 16;
break;
}
if (*p1 == 'd') {
base = 10;
break;
}
if (*p1 == 'X') {
base = -16;
break;
}
VALUE_ERROR("Invalid conversion specification");
return NULL;
}
*(p2++) = '\00';
if (!(mpzstr = mpz_ascii(MPZ(self), base, option, 0)))
return NULL;
result = PyObject_CallMethod(mpzstr, "__format__", "(s)", fmt);
Py_DECREF(mpzstr);
return result;
}
PyDoc_STRVAR(GMPy_doc_mpfr_format,
"x.__format__(fmt) -> str\n\n"
"Return a Python string by formatting 'x' using the format string\n"
"'fmt'. A valid format string consists of:\n\n"
" optional alignment code:\n\n"
" '<' -> left shifted in field\n"
" '>' -> right shifted in field\n"
" '^' -> centered in field\n\n"
" optional leading sign code\n\n"
" '+' -> always display leading sign\n"
" '-' -> only display minus for negative values\n"
" ' ' -> minus for negative values, space for positive values\n\n"
" optional width.precision\n\n"
" optional rounding mode:\n\n"
" 'U' -> round toward plus Infinity\n"
" 'D' -> round toward minus Infinity\n"
" 'Y' -> round away from zero\n"
" 'Z' -> round toward zero\n"
" 'N' -> round to nearest\n\n"
" optional conversion code:\n\n"
" 'a','A' -> hex format\n"
" 'b' -> binary format\n"
" 'e','E' -> scientific format\n"
" 'f','F' -> fixed point format\n"
" 'g','G' -> fixed or float format\n\n"
"The default format is '.6f'.");
static PyObject *
GMPy_MPFR_Format(PyObject *self, PyObject *args)
{
PyObject *result = NULL, *mpfrstr = NULL;
char *buffer = 0, *newbuf = 0, *fmtcode = 0, *p2, *p3;
unsigned char *p1;
char mpfrfmt[100], fmt[30];
int buflen;
int seensign = 0, seenalign = 0, seendecimal = 0, seendigits = 0;
int seenround = 0, seenconv = 0;
if (!MPFR_Check(self)) {
TYPE_ERROR("requires mpfr type");
return NULL;
}
if (!PyArg_ParseTuple(args, "s", &fmtcode))
return NULL;
p2 = mpfrfmt;
p3 = fmt;
*(p2++) = '%';
for (p1 = (unsigned char*)fmtcode; *p1 != '\00'; p1++) {
if (*p1 == '<' || *p1 == '>' || *p1 == '^') {
if (seenalign || seensign || seendecimal || seendigits || seenround) {
VALUE_ERROR("Invalid conversion specification");
return NULL;
}
else {
*(p3++) = *p1;
seenalign = 1;
continue;
}
}
if (*p1 == '+' || *p1 == ' ') {
if (seensign || seendecimal || seendigits || seenround) {
VALUE_ERROR("Invalid conversion specification");
return NULL;
}
else {
*(p2++) = *p1;
seensign = 1;
continue;
}
}
if (*p1 == '-') {
if (seensign || seendecimal || seendigits || seenround) {
VALUE_ERROR("Invalid conversion specification");
return NULL;
}
else {
seensign = 1;
continue;
}
}
if (*p1 == '.') {
if (seendecimal || seendigits || seenround) {
VALUE_ERROR("Invalid conversion specification");
return NULL;
}
else {
*(p2++) = *p1;
seendecimal = 1;
continue;
}
}
if (isdigit(*p1)) {
if (seendigits || seenround) {
VALUE_ERROR("Invalid conversion specification");
return NULL;
}
else if (seendecimal) {
*(p2++) = *p1;
continue;
}
else {
if (p3 == fmt) {
*(p3++) = '>';
seenalign = 1;
}
*(p3++) = *p1;
continue;
}
}
if (!seendigits) {
seendigits = 1;
*(p2++) = 'R';
}
if (*p1 == 'U' || *p1 == 'D' || *p1 == 'Y' || *p1 == 'Z' ||
*p1 == 'N' ) {
if (seenround) {
VALUE_ERROR("Invalid conversion specification");
return NULL;
}
else {
*(p2++) = *p1;
seenround = 1;
continue;
}
}
if (*p1 == 'a' || *p1 == 'A' || *p1 == 'b' || *p1 == 'e' ||
*p1 == 'E' || *p1 == 'f' || *p1 == 'F' || *p1 == 'g' ||
*p1 == 'G' ) {
*(p2++) = *p1;
seenconv = 1;
break;
}
VALUE_ERROR("Invalid conversion specification");
return NULL;
}
if (!seendigits)
*(p2++) = 'R';
if (!seenconv)
*(p2++) = 'f';
*(p2) = '\00';
*(p3) = '\00';
buflen = mpfr_asprintf(&buffer, mpfrfmt, MPFR(self));
/* If there isn't a decimal point in the output and the output
* only consists of digits, then append .0 */
if (strlen(buffer) == strspn(buffer, "+- 0123456789")) {
newbuf = malloc(buflen + 3);
if (!newbuf) {
mpfr_free_str(buffer);
return PyErr_NoMemory();
}
*newbuf = '\0';
strcat(newbuf, buffer);
strcat(newbuf, ".0");
mpfr_free_str(buffer);
mpfrstr = PyUnicode_FromString(newbuf);
free(newbuf);
}
else {
mpfrstr = PyUnicode_FromString(buffer);
mpfr_free_str(buffer);
}
if (!mpfrstr) {
return NULL;
}
result = PyObject_CallMethod(mpfrstr, "__format__", "(s)", fmt);
Py_DECREF(mpfrstr);
return result;
}
PyDoc_STRVAR(GMPy_doc_mpc_format,
"x.__format__(fmt) -> str\n\n"
"Return a Python string by formatting 'x' using the format string\n"
"'fmt'. A valid format string consists of:\n\n"
" optional alignment code:\n\n"
" '<' -> left shifted in field\n"
" '>' -> right shifted in field\n"
" '^' -> centered in field\n\n"
" optional leading sign code\n\n"
" '+' -> always display leading sign\n"
" '-' -> only display minus for negative values\n"
" ' ' -> minus for negative values, space for positive values\n\n"
" optional width.real_precision.imag_precision\n\n"
" optional rounding mode:\n\n"
" 'U' -> round toward plus infinity\n"
" 'D' -> round toward minus infinity\n"
" 'Z' -> round toward zero\n"
" 'N' -> round to nearest\n\n"
" optional output style:\n\n"
" 'P' -> Python style, 1+2j, (default)\n"
" 'M' -> MPC style, (1 2)\n\n"
" optional conversion code:\n\n"
" 'a','A' -> hex format\n"
" 'b' -> binary format\n"
" 'e','E' -> scientific format\n"
" 'f','F' -> fixed point format\n"
" 'g','G' -> fixed or scientific format\n\n"
"The default format is 'f'.");
static PyObject *
GMPy_MPC_Format(PyObject *self, PyObject *args)
{
PyObject *result = NULL, *tempstr = NULL;
char *realbuf = 0, *imagbuf = 0, *tempbuf = 0, *fmtcode = 0;
char *rfmtptr, *fmtptr;
unsigned char *p, *ifmtptr;
char rfmt[100], ifmt[100], fmt[30];
int rbuflen, ibuflen;
int seensign = 0, seenalign = 0, seendecimal = 0, seendigits = 0;
int seenround = 0, seenconv = 0, seenstyle = 0, mpcstyle = 0;
if (!MPC_Check(self)) {
TYPE_ERROR("requires 'mpc' object");
return NULL;
}
if (!PyArg_ParseTuple(args, "s", &fmtcode)) {
return NULL;
}
rfmtptr = rfmt;
ifmtptr = (unsigned char*)ifmt;
fmtptr = fmt;
*(rfmtptr++) = '%';
*(ifmtptr++) = '%';
for (p = (unsigned char*)fmtcode; *p != '\00'; p++) {
if (*p == '<' || *p == '>' || *p == '^') {
if (seenalign || seensign || seendecimal || seendigits ||
seenround || seenstyle) {
VALUE_ERROR("Invalid conversion specification");
return NULL;
}
else {
*(fmtptr++) = *p;
seenalign = 1;
continue;
}
}
if (*p == '+' || *p == ' ' || *p == '-') {
if (seensign || seendecimal || seendigits || seenround ||
seenstyle) {
VALUE_ERROR("Invalid conversion specification");
return NULL;
}
else {
*(rfmtptr++) = *p;
*(ifmtptr++) = *p;
seensign = 1;
continue;
}
}
if (!seensign) {
*(rfmtptr++) = '-';
*(ifmtptr++) = '-';
seensign = 1;
}
if (*p == '.') {
if (seendecimal == 2 || seendigits || seenround || seenstyle) {
VALUE_ERROR("Invalid conversion specification");
return NULL;
}
else {
if (!seendecimal) {
*(rfmtptr++) = *p;
*(ifmtptr++) = *p;
}
seendecimal++;
if (seendecimal == 2) {
while (isdigit(*(ifmtptr-1)))
ifmtptr--;
}
continue;
}
}
if (isdigit(*p)) {
if (seendigits || seenround || seenstyle) {
VALUE_ERROR("Invalid conversion specification");
return NULL;
}
else if (seendecimal == 1) {
*(rfmtptr++) = *p;
*(ifmtptr++) = *p;
continue;
}
else if (seendecimal == 2) {
*(ifmtptr++) = *p;
continue;
}
else {
if (fmtptr == fmt) {
*(fmtptr++) = '>';
seenalign = 1;
}
*(fmtptr++) = *p;
continue;
}
}
if (!seendigits) {
seendigits = 1;
*(rfmtptr++) = 'R';
*(ifmtptr++) = 'R';
}
if (*p == 'U' || *p == 'D' || *p == 'Y' || *p == 'Z' ||
*p == 'N' ) {
if (seenround || seenstyle) {
VALUE_ERROR("Invalid conversion specification");
return NULL;
}
else {
*(rfmtptr++) = *p;
*(ifmtptr++) = *p;
seenround = 1;
continue;
}
}
if (*p == 'P' || *p == 'M') {
if (seenstyle) {
VALUE_ERROR("Invalid conversion specification");
return NULL;
}
else {
if (*p == 'M')
mpcstyle = 1;
seenstyle = 1;
continue;
}
}
if (*p == 'a' || *p == 'A' || *p == 'b' || *p == 'e' ||
*p == 'E' || *p == 'f' || *p == 'F' || *p == 'g' ||
*p == 'G' ) {
*(rfmtptr++) = *p;
*(ifmtptr++) = *p;
seenconv = 1;
break;
}
VALUE_ERROR("Invalid conversion specification");
return NULL;
}
if (!seensign) {
*(rfmtptr++) = '-';
*(ifmtptr++) = '-';
}
if (!seendigits) {
*(rfmtptr++) = 'R';
*(ifmtptr++) = 'R';
}
if (!seenconv) {
*(rfmtptr++) = 'f';
*(ifmtptr++) = 'f';
}
*(rfmtptr) = '\00';
*(ifmtptr) = '\00';
*(fmtptr) = '\00';
/* Format the real part.... */
rbuflen = mpfr_asprintf(&realbuf, rfmt,
mpc_realref(MPC(self)));
if (rbuflen < 0) {
mpfr_free_str(realbuf);
SYSTEM_ERROR("Internal error in mpfr_asprintf");
return NULL;
}
/* Format the imaginary part. If Python style is wanted, convert the '-'
* or ' ' sign indicator to '+'. */
if (!mpcstyle) {
if (ifmt[1] == ' ' || ifmt[1] == '-' || ifmt[1] == '+') {
ifmt[1] = '+';
}
else {
mpfr_free_str(realbuf);
VALUE_ERROR("Invalid conversion specification for imag");
return NULL;
}
}
ibuflen = mpfr_asprintf(&imagbuf, ifmt,
mpc_imagref(MPC(self)));
if (ibuflen < 0) {
mpfr_free_str(realbuf);
mpfr_free_str(imagbuf);
SYSTEM_ERROR("Internal error in mpfr_asprintf");
return NULL;
}
/* Combine the real and imaginary components into a single buffer.
* Include space for '(', ' ', and 'j)' and possibly appending '.0' twice.
*/
tempbuf = malloc(rbuflen + ibuflen + 10);
if (!tempbuf) {
mpfr_free_str(realbuf);
mpfr_free_str(imagbuf);
return PyErr_NoMemory();
}
tempbuf[0] = '\00';
if (mpcstyle)
strcat(tempbuf, "(");
strcat(tempbuf, realbuf);
/* If there isn't a decimal point in the output and the output
* is short and only consists of digits, then append .0 */
if (strlen(realbuf) < 50 &&
strlen(realbuf) == strspn(realbuf, "+- 0123456789")) {
strcat(tempbuf, ".0");
}
if (mpcstyle)
strcat(tempbuf, " ");
else {
#if MPFR_VERSION < MPFR_VERSION_NUM(4,2,1)
/* Need to insert + if imag is nan or +inf. */
if (mpfr_nan_p(mpc_imagref(MPC(self))) ||
(mpfr_inf_p(mpc_imagref(MPC(self))) &&
mpfr_sgn(mpc_imagref(MPC(self))) > 0)) {
strcat(tempbuf, "+");
}
#endif
}
strcat(tempbuf, imagbuf);
if (strlen(imagbuf) < 50 &&
strlen(imagbuf) == strspn(imagbuf, "+- 0123456789")) {
strcat(tempbuf, ".0");
}
if (mpcstyle)
strcat(tempbuf, ")");
else
strcat(tempbuf, "j");
mpfr_free_str(realbuf);
mpfr_free_str(imagbuf);
tempstr = PyUnicode_FromString(tempbuf);
if (!tempstr) {
free(tempbuf);
return NULL;
}
result = PyObject_CallMethod(tempstr, "__format__", "(s)", fmt);
Py_DECREF(tempstr);
return result;
}
/* produce digits for an mpz in requested base, default 10 */
PyDoc_STRVAR(GMPy_doc_mpz_digits_method,
"x.digits(base=10, /) -> str\n\n"
"Return Python string representing x in the given base. Values for\n"
"base can range between 2 to 62. A leading '-' is present if x<0\n"
"but no leading '+' is present if x>=0.");
static PyObject *
GMPy_MPZ_Digits_Method(PyObject *self, PyObject *args)
{
int base = 10;
if (PyTuple_GET_SIZE(args) && !PyArg_ParseTuple(args, "|i", &base)) {
return NULL;
}
return GMPy_PyStr_From_MPZ((MPZ_Object*)self, base, 16, NULL);
}
static PyObject *
GMPy_XMPZ_Digits_Method(PyObject *self, PyObject *args)
{
int base = 10;
if (PyTuple_GET_SIZE(args) && !PyArg_ParseTuple(args, "|i", &base)) {
return NULL;
}
return GMPy_PyStr_From_XMPZ((XMPZ_Object*)self, base, 0, NULL);
}
PyDoc_STRVAR(GMPy_doc_mpq_digits_method,
"x.digits(base=10, /) -> str\n\n"
"Return a Python string representing x in the given base (2 to 62,\n"
"default is 10). A leading '-' is present if x<0, but no leading '+'\n"
"is present if x>=0.\n");
static PyObject *
GMPy_MPQ_Digits_Method(PyObject *self, PyObject *args)
{
int base = 10;
if (PyTuple_GET_SIZE(args) && !PyArg_ParseTuple(args, "|i", &base)) {
return NULL;
}
return GMPy_PyStr_From_MPQ((MPQ_Object*)self, base, 0, NULL);
}
PyDoc_STRVAR(GMPy_doc_mpfr_digits_method,
"x.digits(base=10, prec=0, /) -> tuple[str, int, int]\n\n"
"Returns up to 'prec' digits in the given base. If 'prec' is 0, as many\n"
"digits that are available are returned. No more digits than available\n"
"given x's precision are returned. 'base' must be between 2 and 62,\n"
"inclusive. The result is a three element `tuple` containing the mantissa,\n"
"the exponent, and the number of bits of precision.");
static PyObject *
GMPy_MPFR_Digits_Method(PyObject *self, PyObject *args)
{
int base = 10, prec = 0;
if (PyTuple_GET_SIZE(args) && !PyArg_ParseTuple(args, "|ii", &base, &prec)) {
return NULL;
}
return GMPy_PyStr_From_MPFR((MPFR_Object*)self, base, prec, NULL);
}
PyDoc_STRVAR(GMPy_doc_mpc_digits_method,
"c.digits(base=10, prec=0, /) -> tuple[tuple[str, int, int], tuple[str, int, int]]\n\n"
"Returns up to 'prec' digits in the given base. If 'prec' is 0, as many\n"
"digits that are available given c's precision are returned. 'base' must\n"
"be between 2 and 62. The result consists of 2 three-element tuples that\n"
"contain the mantissa, exponent, and number of bits of precision of the\n"
"real and imaginary components.");
static PyObject *
GMPy_MPC_Digits_Method(PyObject *self, PyObject *args)
{
int base = 10, prec = 0;
if (PyTuple_GET_SIZE(args) && !PyArg_ParseTuple(args, "|ii", &base, &prec)) {
return NULL;
}
return GMPy_PyStr_From_MPC((MPC_Object*)self, base, prec, NULL);
}
PyDoc_STRVAR(GMPy_doc_context_digits,
"digits(x, base=10, prec=0, /) -> str\n\n"
"Return string representing a number x.");
static PyObject *
GMPy_Context_Digits(PyObject *self, PyObject *args)
{
PyObject *arg0, *tuple, *temp, *result;
Py_ssize_t argc;
int xtype;
argc = PyTuple_GET_SIZE(args);
if (argc == 0) {
TYPE_ERROR("digits() requires at least one argument");
return NULL;
}
if (argc > 3) {
TYPE_ERROR("digits() accepts at most three arguments");
return NULL;
}
arg0 = PyTuple_GET_ITEM(args, 0);
xtype = GMPy_ObjectType(arg0);
if (!(tuple = PyTuple_GetSlice(args, 1, argc))) {
return NULL;
}
if (IS_TYPE_INTEGER(xtype)) {
temp = (PyObject*)GMPy_MPZ_From_IntegerWithType(arg0, xtype, NULL);
if (!temp) {
Py_DECREF(tuple);
return NULL;
}
result = GMPy_MPZ_Digits_Method(temp, tuple);
Py_DECREF(temp);
Py_DECREF(tuple);
return result;
}
if (IS_TYPE_RATIONAL(xtype)) {
temp = (PyObject*)GMPy_MPQ_From_RationalWithType(arg0, xtype, NULL);
if (!temp) {
Py_DECREF(tuple);
return NULL;
}
result = GMPy_MPQ_Digits_Method(temp, tuple);
Py_DECREF(temp);
Py_DECREF(tuple);
return result;
}
if (IS_TYPE_REAL(xtype)) {
temp = (PyObject*)GMPy_MPFR_From_RealWithType(arg0, xtype, 1, NULL);
if (!temp) {
Py_DECREF(tuple);
return NULL;
}
result = GMPy_MPFR_Digits_Method(temp, tuple);
Py_DECREF(temp);
Py_DECREF(tuple);
return result;
}
if (IS_TYPE_COMPLEX(xtype)) {
temp = (PyObject*)GMPy_MPC_From_ComplexWithType(arg0, xtype, 1, 1, NULL);
if (!temp) {
Py_DECREF(tuple);
return NULL;
}
result = GMPy_MPC_Digits_Method(temp, tuple);
Py_DECREF(temp);
Py_DECREF(tuple);
return result;
}
Py_DECREF(tuple);
TYPE_ERROR("digits() argument type not supported");
return NULL;
}
././@PaxHeader 0000000 0000000 0000000 00000000026 00000000000 010213 x ustar 00 22 mtime=1710307256.0
gmpy2-2.2.1/src/gmpy2_format.h 0000644 0001750 0001750 00000005204 14574233670 014604 0 ustar 00case case /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* gmpy2_format.h *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Python interface to the GMP, MPFR, and MPC multiple precision *
* libraries. *
* *
* Copyright 2000 - 2009 Alex Martelli *
* *
* Copyright 2008 - 2024 Case Van Horsen *
* *
* This file is part of GMPY2. *
* *
* GMPY2 is free software: you can redistribute it and/or modify it under *
* the terms of the GNU Lesser General Public License as published by the *
* Free Software Foundation, either version 3 of the License, or (at your *
* option) any later version. *
* *
* GMPY2 is distributed in the hope that it will be useful, but WITHOUT *
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or *
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public *
* License for more details. *
* *
* You should have received a copy of the GNU Lesser General Public *
* License along with GMPY2; if not, see *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
#ifndef GMPY_FORMAT_H
#define GMPY_FORMAT_H
#ifdef __cplusplus
extern "C" {
#endif
static PyObject * GMPy_MPZ_Digits_Method(PyObject *self, PyObject *args);
static PyObject * GMPy_MPZ_Format(PyObject *self, PyObject *args);
static PyObject * GMPy_MPQ_Digits_Method(PyObject *self, PyObject *args);
/* static PyObject * GMPy_MPQ_Format(PyObject *self, PyObject *args); */
static PyObject * GMPy_MPFR_Digits_Method(PyObject *self, PyObject *args);
static PyObject * GMPy_MPFR_Format(PyObject *self, PyObject *args);
static PyObject * GMPy_MPC_Digits_Method(PyObject *self, PyObject *args);
static PyObject * GMPy_MPC_Format(PyObject *self, PyObject *args);
static PyObject * GMPy_Context_Digits(PyObject *self, PyObject *args);
#ifdef __cplusplus
}
#endif
#endif
././@PaxHeader 0000000 0000000 0000000 00000000026 00000000000 010213 x ustar 00 22 mtime=1710307256.0
gmpy2-2.2.1/src/gmpy2_fused.c 0000644 0001750 0001750 00000054354 14574233670 014427 0 ustar 00case case /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* gmpy2_fused.c *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Python interface to the GMP, MPFR, and MPC multiple precision *
* libraries. *
* *
* Copyright 2000 - 2009 Alex Martelli *
* *
* Copyright 2008 - 2024 Case Van Horsen *
* *
* This file is part of GMPY2. *
* *
* GMPY2 is free software: you can redistribute it and/or modify it under *
* the terms of the GNU Lesser General Public License as published by the *
* Free Software Foundation, either version 3 of the License, or (at your *
* option) any later version. *
* *
* GMPY2 is distributed in the hope that it will be useful, but WITHOUT *
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or *
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public *
* License for more details. *
* *
* You should have received a copy of the GNU Lesser General Public *
* License along with GMPY2; if not, see *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
static PyObject *
_GMPy_MPZ_FMA(PyObject *x, PyObject *y, PyObject *z, CTXT_Object *context)
{
MPZ_Object *result = NULL;
if (!(result = GMPy_MPZ_New(context))) {
/* LCOV_EXCL_START */
return NULL;
/* LCOV_EXCL_STOP */
}
GMPY_MAYBE_BEGIN_ALLOW_THREADS(context);
mpz_mul(result->z, MPZ(x), MPZ(y));
mpz_add(result->z, result->z, MPZ(z));
GMPY_MAYBE_END_ALLOW_THREADS(context);
return (PyObject*)result;
}
static PyObject *
GMPy_IntegerWithType_FMA(PyObject *x, int xtype, PyObject *y, int ytype, PyObject *z, int ztype, CTXT_Object *context)
{
PyObject *result, *tempx = NULL, *tempy = NULL, *tempz = NULL;
if (!(tempx = (PyObject*)GMPy_MPZ_From_IntegerWithType(x, xtype, context)) ||
!(tempy = (PyObject*)GMPy_MPZ_From_IntegerWithType(y, ytype, context)) ||
!(tempz = (PyObject*)GMPy_MPZ_From_IntegerWithType(z, ztype, context))) {
/* LCOV_EXCL_START */
Py_XDECREF(tempx);
Py_XDECREF(tempy);
Py_XDECREF(tempz);
return NULL;
/* LCOV_EXCL_STOP */
}
result = _GMPy_MPZ_FMA(tempx, tempy, tempz, context);
Py_DECREF(tempx);
Py_DECREF(tempy);
Py_DECREF(tempz);
return result;
}
static PyObject *
_GMPy_MPQ_FMA(PyObject *x, PyObject *y, PyObject *z, CTXT_Object *context)
{
MPQ_Object *result;
if (!(result = GMPy_MPQ_New(context))) {
/* LCOV_EXCL_START */
return NULL;
/* LCOV_EXCL_STOP */
}
GMPY_MAYBE_BEGIN_ALLOW_THREADS(context);
mpq_mul(result->q, MPQ(x), MPQ(y));
mpq_add(result->q, result->q, MPQ(z));
GMPY_MAYBE_END_ALLOW_THREADS(context);
return (PyObject*)result;
}
static PyObject *
GMPy_RationalWithType_FMA(PyObject *x, int xtype, PyObject *y, int ytype, PyObject *z, int ztype, CTXT_Object *context)
{
PyObject *result, *tempx = NULL, *tempy = NULL, *tempz = NULL;
if (!(tempx = (PyObject*)GMPy_MPQ_From_RationalWithType(x, xtype, context)) ||
!(tempy = (PyObject*)GMPy_MPQ_From_RationalWithType(y, ytype, context)) ||
!(tempz = (PyObject*)GMPy_MPQ_From_RationalWithType(z, ztype, context))) {
/* LCOV_EXCL_START */
Py_XDECREF(tempx);
Py_XDECREF(tempy);
Py_XDECREF(tempz);
return NULL;
/* LCOV_EXCL_STOP */
}
result = _GMPy_MPQ_FMA(tempx, tempy, tempz, context);
Py_DECREF((PyObject*)tempx);
Py_DECREF((PyObject*)tempy);
Py_DECREF((PyObject*)tempz);
return (result);
}
static PyObject *
_GMPy_MPFR_FMA(PyObject *x, PyObject *y, PyObject *z, CTXT_Object *context)
{
MPFR_Object *result;
if (!(result = GMPy_MPFR_New(0, context))) {
/* LCOV_EXCL_START */
return NULL;
/* LCOV_EXCL_STOP */
}
mpfr_clear_flags();
result->rc = mpfr_fma(result->f, MPFR(x), MPFR(y), MPFR(z), GET_MPFR_ROUND(context));
_GMPy_MPFR_Cleanup(&result, context);
return (PyObject*)result;
}
static PyObject *
GMPy_RealWithType_FMA(PyObject *x, int xtype, PyObject *y, int ytype, PyObject *z, int ztype, CTXT_Object *context)
{
PyObject *result, *tempx = NULL, *tempy = NULL, *tempz = NULL;
if (!(tempx = (PyObject*)GMPy_MPFR_From_RealWithType(x, xtype, 1, context)) ||
!(tempy = (PyObject*)GMPy_MPFR_From_RealWithType(y, ytype, 1, context)) ||
!(tempz = (PyObject*)GMPy_MPFR_From_RealWithType(z, ztype, 1, context))) {
/* LCOV_EXCL_START */
Py_XDECREF(tempx);
Py_XDECREF(tempy);
Py_XDECREF(tempz);
return NULL;
/* LCOV_EXCL_STOP */
}
result = _GMPy_MPFR_FMA(tempx, tempy, tempz, context);
Py_DECREF(tempx);
Py_DECREF(tempy);
Py_DECREF(tempz);
return result;
}
static PyObject *
_GMPy_MPC_FMA(PyObject *x, PyObject *y, PyObject *z, CTXT_Object *context)
{
MPC_Object *result;
if (!(result = GMPy_MPC_New(0, 0, context))) {
/* LCOV_EXCL_START */
return NULL;
/* LCOV_EXCL_STOP */
}
result->rc = mpc_fma(result->c, MPC(x), MPC(y), MPC(z), GET_MPC_ROUND(context));
_GMPy_MPC_Cleanup(&result, context);
return (PyObject*)result;
}
static PyObject *
GMPy_ComplexWithType_FMA(PyObject *x, int xtype, PyObject *y, int ytype, PyObject *z, int ztype, CTXT_Object *context)
{
PyObject *result, *tempx = NULL, *tempy = NULL, *tempz = NULL;
if (!(tempx = (PyObject*)GMPy_MPC_From_ComplexWithType(x, xtype, 1, 1, context)) ||
!(tempy = (PyObject*)GMPy_MPC_From_ComplexWithType(y, ytype, 1, 1, context)) ||
!(tempz = (PyObject*)GMPy_MPC_From_ComplexWithType(z, ztype, 1, 1, context))) {
/* LCOV_EXCL_START */
Py_XDECREF(tempx);
Py_XDECREF(tempy);
Py_XDECREF(tempz);
return NULL;
/* LCOV_EXCL_STOP */
}
result = _GMPy_MPC_FMA(tempx, tempy, tempz, context);
Py_DECREF(tempx);
Py_DECREF(tempy);
Py_DECREF(tempz);
return result;
}
PyDoc_STRVAR(GMPy_doc_context_fma,
"context.fma(x, y, z, /) -> mpz | mpq | mpfr | mpc\n\n"
"Return correctly rounded result of (x * y) + z.");
PyDoc_STRVAR(GMPy_doc_function_fma,
"fma(x, y, z, /) -> mpz | mpq | mpfr | mpc\n\n"
"Return correctly rounded result of (x * y) + z.");
GMPY_MPFR_MPC_TRIOP_TEMPLATEWT(FMA, fma);
static PyObject *
_GMPy_MPZ_FMS(PyObject *x, PyObject *y, PyObject *z, CTXT_Object *context)
{
MPZ_Object *result;
if (!(result = GMPy_MPZ_New(context))) {
/* LCOV_EXCL_START */
return NULL;
/* LCOV_EXCL_STOP */
}
GMPY_MAYBE_BEGIN_ALLOW_THREADS(context);
mpz_mul(result->z, MPZ(x), MPZ(y));
mpz_sub(result->z, result->z, MPZ(z));
GMPY_MAYBE_END_ALLOW_THREADS(context);
return (PyObject*)result;
}
static PyObject *
GMPy_IntegerWithType_FMS(PyObject *x, int xtype, PyObject *y, int ytype, PyObject *z, int ztype, CTXT_Object *context)
{
PyObject *result, *tempx = NULL, *tempy = NULL, *tempz = NULL;
if (!(tempx = (PyObject*)GMPy_MPZ_From_IntegerWithType(x, xtype, context)) ||
!(tempy = (PyObject*)GMPy_MPZ_From_IntegerWithType(y, ytype, context)) ||
!(tempz = (PyObject*)GMPy_MPZ_From_IntegerWithType(z, ztype, context))) {
/* LCOV_EXCL_START */
Py_XDECREF(tempx);
Py_XDECREF(tempy);
Py_XDECREF(tempz);
return NULL;
/* LCOV_EXCL_STOP */
}
result = _GMPy_MPZ_FMS(tempx, tempy, tempz, context);
Py_DECREF(tempx);
Py_DECREF(tempy);
Py_DECREF(tempz);
return result;
}
static PyObject *
_GMPy_MPQ_FMS(PyObject *x, PyObject *y, PyObject *z, CTXT_Object *context)
{
MPQ_Object *result;
if (!(result = GMPy_MPQ_New(context))) {
/* LCOV_EXCL_START */
return NULL;
/* LCOV_EXCL_STOP */
}
GMPY_MAYBE_BEGIN_ALLOW_THREADS(context);
mpq_mul(result->q, MPQ(x), MPQ(y));
mpq_sub(result->q, result->q, MPQ(z));
GMPY_MAYBE_END_ALLOW_THREADS(context);
return (PyObject*)result;
}
static PyObject *
GMPy_RationalWithType_FMS(PyObject *x, int xtype, PyObject *y, int ytype, PyObject *z, int ztype, CTXT_Object *context)
{
PyObject *result, *tempx = NULL, *tempy = NULL, *tempz = NULL;
if (!(tempx = (PyObject*)GMPy_MPQ_From_RationalWithType(x, xtype, context)) ||
!(tempy = (PyObject*)GMPy_MPQ_From_RationalWithType(y, ytype, context)) ||
!(tempz = (PyObject*)GMPy_MPQ_From_RationalWithType(z, ztype, context))) {
/* LCOV_EXCL_START */
Py_XDECREF(tempx);
Py_XDECREF(tempy);
Py_XDECREF(tempz);
return NULL;
/* LCOV_EXCL_STOP */
}
result = _GMPy_MPQ_FMS(tempx, tempy, tempz, context);
Py_DECREF(tempx);
Py_DECREF(tempy);
Py_DECREF(tempz);
return result;
}
static PyObject *
_GMPy_MPFR_FMS(PyObject *x, PyObject *y, PyObject *z, CTXT_Object *context)
{
MPFR_Object *result;
if (!(result = GMPy_MPFR_New(0, context))) {
/* LCOV_EXCL_START */
return NULL;
/* LCOV_EXCL_STOP */
}
mpfr_clear_flags();
result->rc = mpfr_fms(result->f, MPFR(x), MPFR(y), MPFR(z), GET_MPFR_ROUND(context));
_GMPy_MPFR_Cleanup(&result, context);
return (PyObject*)result;
}
static PyObject *
GMPy_RealWithType_FMS(PyObject *x, int xtype, PyObject *y, int ytype, PyObject *z, int ztype, CTXT_Object *context)
{
PyObject *result, *tempx = NULL, *tempy = NULL, *tempz = NULL;
if (!(tempx = (PyObject*)GMPy_MPFR_From_RealWithType(x, xtype, 1, context)) ||
!(tempy = (PyObject*)GMPy_MPFR_From_RealWithType(y, ytype, 1, context)) ||
!(tempz = (PyObject*)GMPy_MPFR_From_RealWithType(z, ztype, 1, context))) {
/* LCOV_EXCL_START */
Py_XDECREF(tempx);
Py_XDECREF(tempy);
Py_XDECREF(tempz);
return NULL;
/* LCOV_EXCL_STOP */
}
result = _GMPy_MPFR_FMS(tempx, tempy, tempz, context);
Py_DECREF(tempx);
Py_DECREF(tempy);
Py_DECREF(tempz);
return result;
}
static PyObject *
_GMPy_MPC_FMS(PyObject *x, PyObject *y, PyObject *z, CTXT_Object *context)
{
MPC_Object *result = NULL, *temp = NULL;
if (!(result = GMPy_MPC_New(0, 0, context))) {
/* LCOV_EXCL_START */
return NULL;
/* LCOV_EXCL_STOP */
}
temp = GMPy_MPC_From_ComplexWithTypeAndCopy(z, OBJ_TYPE_MPC, 1, 1, context);
mpc_neg(MPC(temp), MPC(temp), GET_MPC_ROUND(context));
result->rc = mpc_fma(result->c, MPC(x), MPC(y), MPC(temp), GET_MPC_ROUND(context));
Py_DECREF(temp);
_GMPy_MPC_Cleanup(&result, context);
return (PyObject*)result;
}
static PyObject *
GMPy_ComplexWithType_FMS(PyObject *x, int xtype, PyObject *y, int ytype, PyObject *z, int ztype, CTXT_Object *context)
{
PyObject *result, *tempx = NULL, *tempy = NULL, *tempz = NULL;
if (!(tempx = (PyObject*)GMPy_MPC_From_ComplexWithType(x, xtype, 1, 1, context)) ||
!(tempy = (PyObject*)GMPy_MPC_From_ComplexWithType(y, ytype, 1, 1, context)) ||
!(tempz = (PyObject*)GMPy_MPC_From_ComplexWithType(z, ztype, 1, 1, context))) {
/* LCOV_EXCL_START */
Py_XDECREF(tempx);
Py_XDECREF(tempy);
Py_XDECREF(tempz);
return NULL;
/* LCOV_EXCL_STOP */
}
result = _GMPy_MPC_FMS(tempx, tempy, tempz, context);
Py_DECREF(tempx);
Py_DECREF(tempy);
Py_DECREF(tempz);
return result;
}
PyDoc_STRVAR(GMPy_doc_context_fms,
"context.fms(x, y, z, /) -> mpz | mpq | mpfr | mpc\n\n"
"Return correctly rounded result of (x * y) - z.");
PyDoc_STRVAR(GMPy_doc_function_fms,
"fms(x, y, z, /) -> mpz | mpq | mpfr | mpc\n\n"
"Return correctly rounded result of (x * y) - z.");
GMPY_MPFR_MPC_TRIOP_TEMPLATEWT(FMS, fms);
/* Add support for new fmma and fmms functions from MPFR 4. */\
#if MPFR_VERSION_MAJOR > 3
static PyObject *
_GMPy_MPZ_FMMA(PyObject *x, PyObject *y, PyObject *z, PyObject *t, CTXT_Object *context)
{
MPZ_Object *result = NULL, *temp = NULL;
if (!(result = GMPy_MPZ_New(context)) ||
!(temp = GMPy_MPZ_New(context))) {
/* LCOV_EXCL_START */
Py_XDECREF(result);
Py_XDECREF(temp);
return NULL;
/* LCOV_EXCL_STOP */
}
GMPY_MAYBE_BEGIN_ALLOW_THREADS(context);
mpz_mul(result->z, MPZ(x), MPZ(y));
mpz_mul(temp->z, MPZ(z), MPZ(t));
mpz_add(result->z, result->z, temp->z);
GMPY_MAYBE_END_ALLOW_THREADS(context);
Py_DECREF(temp);
return (PyObject*)result;
}
static PyObject *
GMPy_IntegerWithType_FMMA(PyObject *x, int xtype, PyObject *y, int ytype, PyObject *z,
int ztype, PyObject *t, int ttype, CTXT_Object *context)
{
PyObject *result = NULL, *tempx = NULL, *tempy = NULL, *tempz = NULL, *tempt = NULL;
if (!(tempx = (PyObject*)GMPy_MPZ_From_IntegerWithType(x, xtype, context)) ||
!(tempy = (PyObject*)GMPy_MPZ_From_IntegerWithType(y, ytype, context)) ||
!(tempz = (PyObject*)GMPy_MPZ_From_IntegerWithType(z, ztype, context)) ||
!(tempt = (PyObject*)GMPy_MPZ_From_IntegerWithType(t, ttype, context))) {
/* LCOV_EXCL_START */
Py_XDECREF(tempx);
Py_XDECREF(tempy);
Py_XDECREF(tempz);
Py_XDECREF(tempt);
return NULL;
/* LCOV_EXCL_STOP */
}
result = _GMPy_MPZ_FMMA(tempx, tempy, tempz, tempt, context);
Py_DECREF(tempx);
Py_DECREF(tempy);
Py_DECREF(tempz);
Py_DECREF(tempt);
return result;
}
static PyObject *
_GMPy_MPQ_FMMA(PyObject *x, PyObject *y, PyObject *z, PyObject *t, CTXT_Object *context)
{
MPQ_Object *result = NULL, *temp = NULL;
if (!(result = GMPy_MPQ_New(context)) ||
!(temp = GMPy_MPQ_New(context))) {
/* LCOV_EXCL_START */
Py_XDECREF(result);
Py_XDECREF(temp);
return NULL;
/* LCOV_EXCL_STOP */
}
GMPY_MAYBE_BEGIN_ALLOW_THREADS(context);
mpq_mul(result->q, MPQ(x), MPQ(y));
mpq_mul(temp->q, MPQ(z), MPQ(t));
mpq_add(result->q, result->q, temp->q);
GMPY_MAYBE_END_ALLOW_THREADS(context);
Py_DECREF(temp);
return (PyObject*)result;
}
static PyObject *
GMPy_RationalWithType_FMMA(PyObject *x, int xtype, PyObject *y, int ytype, PyObject *z,
int ztype, PyObject *t, int ttype, CTXT_Object *context)
{
PyObject *result = NULL, *tempx = NULL, *tempy = NULL, *tempz = NULL, *tempt = NULL;
if (!(tempx = (PyObject*)GMPy_MPQ_From_RationalWithType(x, xtype, context)) ||
!(tempy = (PyObject*)GMPy_MPQ_From_RationalWithType(y, ytype, context)) ||
!(tempz = (PyObject*)GMPy_MPQ_From_RationalWithType(z, ztype, context)) ||
!(tempt = (PyObject*)GMPy_MPQ_From_RationalWithType(t, ttype, context))) {
/* LCOV_EXCL_START */
Py_XDECREF(tempx);
Py_XDECREF(tempy);
Py_XDECREF(tempz);
Py_XDECREF(tempt);
return NULL;
/* LCOV_EXCL_STOP */
}
result = _GMPy_MPQ_FMMA(tempx, tempy, tempz, tempt, context);
Py_DECREF((PyObject*)tempx);
Py_DECREF((PyObject*)tempy);
Py_DECREF((PyObject*)tempz);
Py_DECREF((PyObject*)tempt);
return (result);
}
static PyObject *
_GMPy_MPFR_FMMA(PyObject *x, PyObject *y, PyObject *z, PyObject *t, CTXT_Object *context)
{
MPFR_Object *result;
if (!(result = GMPy_MPFR_New(0, context))) {
/* LCOV_EXCL_START */
return NULL;
/* LCOV_EXCL_STOP */
}
mpfr_clear_flags();
result->rc = mpfr_fmma(result->f, MPFR(x), MPFR(y), MPFR(z), MPFR(t), GET_MPFR_ROUND(context));
_GMPy_MPFR_Cleanup(&result, context);
return (PyObject*)result;
}
static PyObject *
GMPy_RealWithType_FMMA(PyObject *x, int xtype, PyObject *y, int ytype, PyObject *z,
int ztype, PyObject *t, int ttype, CTXT_Object *context)
{
PyObject *result, *tempx = NULL, *tempy = NULL, *tempz = NULL, *tempt = NULL;
if (!(tempx = (PyObject*)GMPy_MPFR_From_RealWithType(x, xtype, 1, context)) ||
!(tempy = (PyObject*)GMPy_MPFR_From_RealWithType(y, ytype, 1, context)) ||
!(tempz = (PyObject*)GMPy_MPFR_From_RealWithType(z, ztype, 1, context)) ||
!(tempt = (PyObject*)GMPy_MPFR_From_RealWithType(t, ttype, 1, context))) {
/* LCOV_EXCL_START */
Py_XDECREF(tempx);
Py_XDECREF(tempy);
Py_XDECREF(tempz);
Py_XDECREF(tempt);
return NULL;
/* LCOV_EXCL_STOP */
}
result = _GMPy_MPFR_FMMA(tempx, tempy, tempz, tempt, context);
Py_DECREF(tempx);
Py_DECREF(tempy);
Py_DECREF(tempz);
Py_DECREF(tempt);
return result;
}
PyDoc_STRVAR(GMPy_doc_context_fmma,
"context.fmma(x, y, z, t, /) -> mpfr\n\n"
"Return correctly rounded result of (x * y) + (z * t).");
PyDoc_STRVAR(GMPy_doc_function_fmma,
"fmma(x, y, z, t, /) -> mpfr\n\n"
"Return correctly rounded result of (x * y) + (z + t).");
GMPY_MPFR_QUADOP_TEMPLATEWT(FMMA, fmma);
static PyObject *
_GMPy_MPZ_FMMS(PyObject *x, PyObject *y, PyObject *z, PyObject *t, CTXT_Object *context)
{
MPZ_Object *result = NULL, *temp = NULL;
if (!(result = GMPy_MPZ_New(context)) ||
!(temp = GMPy_MPZ_New(context))) {
/* LCOV_EXCL_START */
Py_XDECREF(result);
Py_XDECREF(temp);
return NULL;
/* LCOV_EXCL_STOP */
}
GMPY_MAYBE_BEGIN_ALLOW_THREADS(context);
mpz_mul(result->z, MPZ(x), MPZ(y));
mpz_mul(temp->z, MPZ(z), MPZ(t));
mpz_sub(result->z, result->z, temp->z);
GMPY_MAYBE_END_ALLOW_THREADS(context);
Py_DECREF(temp);
return (PyObject*)result;
}
static PyObject *
GMPy_IntegerWithType_FMMS(PyObject *x, int xtype, PyObject *y, int ytype, PyObject *z,
int ztype, PyObject *t, int ttype, CTXT_Object *context)
{
PyObject *result = NULL, *tempx = NULL, *tempy = NULL, *tempz = NULL, *tempt = NULL;
if (!(tempx = (PyObject*)GMPy_MPZ_From_IntegerWithType(x, xtype, context)) ||
!(tempy = (PyObject*)GMPy_MPZ_From_IntegerWithType(y, ytype, context)) ||
!(tempz = (PyObject*)GMPy_MPZ_From_IntegerWithType(z, ztype, context)) ||
!(tempt = (PyObject*)GMPy_MPZ_From_IntegerWithType(t, ttype, context))) {
/* LCOV_EXCL_START */
Py_XDECREF(tempx);
Py_XDECREF(tempy);
Py_XDECREF(tempz);
Py_XDECREF(tempt);
return NULL;
/* LCOV_EXCL_STOP */
}
result = _GMPy_MPZ_FMMS(tempx, tempy, tempz, tempt, context);
Py_DECREF(tempx);
Py_DECREF(tempy);
Py_DECREF(tempz);
Py_DECREF(tempt);
return result;
}
static PyObject *
_GMPy_MPQ_FMMS(PyObject *x, PyObject *y, PyObject *z, PyObject *t, CTXT_Object *context)
{
MPQ_Object *result = NULL, *temp = NULL;
if (!(result = GMPy_MPQ_New(context)) ||
!(temp = GMPy_MPQ_New(context))) {
/* LCOV_EXCL_START */
Py_XDECREF(result);
Py_XDECREF(temp);
return NULL;
/* LCOV_EXCL_STOP */
}
GMPY_MAYBE_BEGIN_ALLOW_THREADS(context);
mpq_mul(result->q, MPQ(x), MPQ(y));
mpq_mul(temp->q, MPQ(z), MPQ(t));
mpq_sub(result->q, result->q, temp->q);
GMPY_MAYBE_END_ALLOW_THREADS(context);
Py_DECREF(temp);
return (PyObject*)result;
}
static PyObject *
GMPy_RationalWithType_FMMS(PyObject *x, int xtype, PyObject *y, int ytype, PyObject *z,
int ztype, PyObject *t, int ttype, CTXT_Object *context)
{
PyObject *result = NULL, *tempx = NULL, *tempy = NULL, *tempz = NULL, *tempt = NULL;
if (!(tempx = (PyObject*)GMPy_MPQ_From_RationalWithType(x, xtype, context)) ||
!(tempy = (PyObject*)GMPy_MPQ_From_RationalWithType(y, ytype, context)) ||
!(tempz = (PyObject*)GMPy_MPQ_From_RationalWithType(z, ztype, context)) ||
!(tempt = (PyObject*)GMPy_MPQ_From_RationalWithType(t, ttype, context))) {
/* LCOV_EXCL_START */
Py_XDECREF(tempx);
Py_XDECREF(tempy);
Py_XDECREF(tempz);
Py_XDECREF(tempt);
return NULL;
/* LCOV_EXCL_STOP */
}
result = _GMPy_MPQ_FMMS(tempx, tempy, tempz, tempt, context);
Py_DECREF((PyObject*)tempx);
Py_DECREF((PyObject*)tempy);
Py_DECREF((PyObject*)tempz);
Py_DECREF((PyObject*)tempt);
return (result);
}
static PyObject *
_GMPy_MPFR_FMMS(PyObject *x, PyObject *y, PyObject *z, PyObject *t, CTXT_Object *context)
{
MPFR_Object *result;
if (!(result = GMPy_MPFR_New(0, context))) {
/* LCOV_EXCL_START */
return NULL;
/* LCOV_EXCL_STOP */
}
mpfr_clear_flags();
result->rc = mpfr_fmms(result->f, MPFR(x), MPFR(y), MPFR(z), MPFR(t), GET_MPFR_ROUND(context));
_GMPy_MPFR_Cleanup(&result, context);
return (PyObject*)result;
}
static PyObject *
GMPy_RealWithType_FMMS(PyObject *x, int xtype, PyObject *y, int ytype, PyObject *z,
int ztype, PyObject *t, int ttype, CTXT_Object *context)
{
PyObject *result, *tempx = NULL, *tempy = NULL, *tempz = NULL, *tempt = NULL;
if (!(tempx = (PyObject*)GMPy_MPFR_From_RealWithType(x, xtype, 1, context)) ||
!(tempy = (PyObject*)GMPy_MPFR_From_RealWithType(y, ytype, 1, context)) ||
!(tempz = (PyObject*)GMPy_MPFR_From_RealWithType(z, ztype, 1, context)) ||
!(tempt = (PyObject*)GMPy_MPFR_From_RealWithType(t, ttype, 1, context))) {
/* LCOV_EXCL_START */
Py_XDECREF(tempx);
Py_XDECREF(tempy);
Py_XDECREF(tempz);
Py_XDECREF(tempt);
return NULL;
/* LCOV_EXCL_STOP */
}
result = _GMPy_MPFR_FMMS(tempx, tempy, tempz, tempt, context);
Py_DECREF(tempx);
Py_DECREF(tempy);
Py_DECREF(tempz);
Py_DECREF(tempt);
return result;
}
PyDoc_STRVAR(GMPy_doc_context_fmms,
"context.fmms(x, y, z, t, /) -> mpfr\n\n"
"Return correctly rounded result of (x * y) - (z * t).");
PyDoc_STRVAR(GMPy_doc_function_fmms,
"fmms(x, y, z, t, /) -> mpfr\n\n"
"Return correctly rounded result of (x * y) - (z + t).");
GMPY_MPFR_QUADOP_TEMPLATEWT(FMMS, fmms);
#endif
././@PaxHeader 0000000 0000000 0000000 00000000026 00000000000 010213 x ustar 00 22 mtime=1710307256.0
gmpy2-2.2.1/src/gmpy2_fused.h 0000644 0001750 0001750 00000011347 14574233670 014427 0 ustar 00case case /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* gmpy2_fused.h *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Python interface to the GMP, MPFR, and MPC multiple precision *
* libraries. *
* *
* Copyright 2000 - 2009 Alex Martelli *
* *
* Copyright 2008 - 2024 Case Van Horsen *
* *
* This file is part of GMPY2. *
* *
* GMPY2 is free software: you can redistribute it and/or modify it under *
* the terms of the GNU Lesser General Public License as published by the *
* Free Software Foundation, either version 3 of the License, or (at your *
* option) any later version. *
* *
* GMPY2 is distributed in the hope that it will be useful, but WITHOUT *
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or *
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public *
* License for more details. *
* *
* You should have received a copy of the GNU Lesser General Public *
* License along with GMPY2; if not, see *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
#ifndef GMPY_FUSED_H
#define GMPY_FUSED_H
#ifdef __cplusplus
extern "C" {
#endif
static PyObject * GMPy_IntegerWithType_FMA(PyObject *x, int xtype, PyObject *y, int ytype, PyObject *z, int ztype, CTXT_Object *context);
static PyObject * GMPy_RationalWithType_FMA(PyObject *x, int xtype, PyObject *y, int ytype, PyObject *z, int ztype, CTXT_Object *context);
static PyObject * GMPy_RealWithType_FMA(PyObject *x, int xtype, PyObject *y, int ytype, PyObject *z, int ztype, CTXT_Object *context);
static PyObject * GMPy_ComplexWithType_FMA(PyObject *x, int xtype, PyObject *y, int ytype, PyObject *z, int ztype, CTXT_Object *context);
static PyObject * GMPy_Number_FMA(PyObject *x, PyObject *y, PyObject *z, CTXT_Object *context);
static PyObject * GMPy_Context_FMA(PyObject *self, PyObject *args);
static PyObject * GMPy_IntegerWithType_FMS(PyObject *x, int xtype, PyObject *y, int ytype, PyObject *z, int ztype, CTXT_Object *context);
static PyObject * GMPy_RationalWithType_FMS(PyObject *x, int xtype, PyObject *y, int ytype, PyObject *z, int ztype, CTXT_Object *context);
static PyObject * GMPy_RealWithType_FMS(PyObject *x, int xtype, PyObject *y, int ytype, PyObject *z, int ztype, CTXT_Object *context);
static PyObject * GMPy_ComplexWithType_FMS(PyObject *x, int xtype, PyObject *y, int ytype, PyObject *z, int ztype, CTXT_Object *context);
static PyObject * GMPy_Number_FMS(PyObject *x, PyObject *y, PyObject *z, CTXT_Object *context);
static PyObject * GMPy_Context_FMS(PyObject *self, PyObject *args);
#if MPFR_VERSION_MAJOR > 3
static PyObject * GMPy_IntegerWithType_FMMA(PyObject *x, int xtype, PyObject *y, int ytype, PyObject *z, int ztype, PyObject *t, int ttype, CTXT_Object *context);
static PyObject * GMPy_RationalWithType_FMMA(PyObject *x, int xtype, PyObject *y, int ytype, PyObject *z, int ztype, PyObject *t, int ttype,CTXT_Object *context);
static PyObject * GMPy_RealWithType_FMMA(PyObject *x, int xtype, PyObject *y, int ytype, PyObject *z, int ztype, PyObject *t, int ttype,CTXT_Object *context);
static PyObject * GMPy_Number_FMMA(PyObject *x, PyObject *y, PyObject *z, PyObject *t, CTXT_Object *context);
static PyObject * GMPy_Context_FMMA(PyObject *self, PyObject *args);
static PyObject * GMPy_IntegerWithType_FMMS(PyObject *x, int xtype, PyObject *y, int ytype, PyObject *z, int ztype, PyObject *t, int ttype, CTXT_Object *context);
static PyObject * GMPy_RationalWithType_FMMS(PyObject *x, int xtype, PyObject *y, int ytype, PyObject *z, int ztype, PyObject *t, int ttype,CTXT_Object *context);
static PyObject * GMPy_RealWithType_FMMS(PyObject *x, int xtype, PyObject *y, int ytype, PyObject *z, int ztype, PyObject *t, int ttype,CTXT_Object *context);
static PyObject * GMPy_Number_FMMS(PyObject *x, PyObject *y, PyObject *z, PyObject *t, CTXT_Object *context);
static PyObject * GMPy_Context_FMMS(PyObject *self, PyObject *args);
#endif
#ifdef __cplusplus
}
#endif
#endif
././@PaxHeader 0000000 0000000 0000000 00000000026 00000000000 010213 x ustar 00 22 mtime=1711300127.0
gmpy2-2.2.1/src/gmpy2_hash.c 0000644 0001750 0001750 00000012661 14600057037 014226 0 ustar 00case case /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* gmpy2_hash.c *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Python interface to the GMP, MPFR, and MPC multiple precision *
* libraries. *
* *
* Copyright 2000 - 2009 Alex Martelli *
* *
* Copyright 2008 - 2024 Case Van Horsen *
* *
* This file is part of GMPY2. *
* *
* GMPY2 is free software: you can redistribute it and/or modify it under *
* the terms of the GNU Lesser General Public License as published by the *
* Free Software Foundation, either version 3 of the License, or (at your *
* option) any later version. *
* *
* GMPY2 is distributed in the hope that it will be useful, but WITHOUT *
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or *
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public *
* License for more details. *
* *
* You should have received a copy of the GNU Lesser General Public *
* License along with GMPY2; if not, see *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
#include "pythoncapi_compat.h"
static Py_hash_t
GMPy_MPZ_Hash_Slot(MPZ_Object *self)
{
Py_hash_t hash;
if (self->hash_cache != -1) {
return self->hash_cache;
}
hash = (Py_hash_t)mpn_mod_1(self->z->_mp_d, (mp_size_t)mpz_size(self->z), PyHASH_MODULUS);
if (mpz_sgn(self->z) < 0) {
hash = -hash;
}
if (hash == -1) {
hash = -2;
}
return (self->hash_cache = hash);
}
static Py_hash_t
GMPy_MPQ_Hash_Slot(MPQ_Object *self)
{
Py_hash_t hash = 0;
mpz_t temp, temp1, mask;
if (self->hash_cache != -1) {
return self->hash_cache;
}
mpz_init(temp);
mpz_init(temp1);
mpz_init(mask);
mpz_set_si(mask, 1);
mpz_mul_2exp(mask, mask, PyHASH_BITS);
mpz_sub_ui(mask, mask, 1);
if (!mpz_invert(temp, mpq_denref(self->q), mask)) {
mpz_clear(temp);
mpz_clear(temp1);
mpz_clear(mask);
hash = PyHASH_INF;
if (mpz_sgn(mpq_numref(self->q)) < 0) {
hash = -hash;
}
self->hash_cache = hash;
return hash;
}
mpz_set(temp1, mask);
mpz_sub_ui(temp1, temp1, 2);
mpz_powm(temp, mpq_denref(self->q), temp1, mask);
mpz_tdiv_r(temp1, mpq_numref(self->q), mask);
mpz_mul(temp, temp, temp1);
hash = (Py_hash_t)mpn_mod_1(temp->_mp_d, (mp_size_t)mpz_size(temp), PyHASH_MODULUS);
if (mpz_sgn(mpq_numref(self->q)) < 0) {
hash = -hash;
}
if (hash == -1) {
hash = -2;
}
mpz_clear(temp);
mpz_clear(temp1);
mpz_clear(mask);
self->hash_cache = hash;
return hash;
}
static Py_hash_t
_mpfr_hash(mpfr_t f)
{
Py_uhash_t hash = 0;
Py_ssize_t exp;
size_t msize;
int sign;
/* Handle special cases first */
if (!mpfr_number_p(f)) {
if (mpfr_inf_p(f)) {
if (mpfr_sgn(f) > 0) {
return PyHASH_INF;
}
else {
return -PyHASH_INF;
}
}
else {
#if PY_VERSION_HEX >= 0x030A00A0
return Py_HashPointer(f);
#else
return _PyHASH_NAN;
#endif
}
}
/* Calculate the number of limbs in the mantissa. */
msize = (f->_mpfr_prec + mp_bits_per_limb - 1) / mp_bits_per_limb;
/* Calculate the hash of the mantissa. */
if (mpfr_sgn(f) > 0) {
hash = mpn_mod_1(f->_mpfr_d, (mp_size_t)msize, PyHASH_MODULUS);
sign = 1;
}
else if (mpfr_sgn(f) < 0) {
hash = mpn_mod_1(f->_mpfr_d, (mp_size_t)msize, PyHASH_MODULUS);
sign = -1;
}
else {
return 0;
}
/* Calculate the final hash. */
exp = f->_mpfr_exp - (msize * mp_bits_per_limb);
exp = exp >= 0 ? exp % PyHASH_BITS : PyHASH_BITS-1-((-1-exp) % PyHASH_BITS);
hash = ((hash << exp) & PyHASH_MODULUS) | hash >> (PyHASH_BITS - exp);
hash *= sign;
if (hash == (Py_uhash_t)(-1)) {
hash = (Py_uhash_t)(-2);
}
return (Py_hash_t)hash;
}
static Py_hash_t
GMPy_MPFR_Hash_Slot(MPFR_Object *self)
{
if (self->hash_cache == -1) {
self->hash_cache = _mpfr_hash(self->f);
}
return self->hash_cache;
}
static Py_hash_t
GMPy_MPC_Hash_Slot(MPC_Object *self)
{
Py_uhash_t hashreal, hashimag, combined;
if (self->hash_cache != -1) {
return self->hash_cache;
}
hashreal = (Py_uhash_t)_mpfr_hash(mpc_realref(self->c));
hashimag = (Py_uhash_t)_mpfr_hash(mpc_imagref(self->c));
combined = hashreal + PyHASH_IMAG * hashimag;
if (combined == (Py_uhash_t)(-1)) {
combined = (Py_uhash_t)(-2);
}
self->hash_cache = combined;
return (Py_hash_t)combined;
}
././@PaxHeader 0000000 0000000 0000000 00000000026 00000000000 010213 x ustar 00 22 mtime=1710307256.0
gmpy2-2.2.1/src/gmpy2_hash.h 0000644 0001750 0001750 00000004333 14574233670 014241 0 ustar 00case case /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* gmpy2_hash.h *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Python interface to the GMP, MPFR, and MPC multiple precision *
* libraries. *
* *
* Copyright 2000 - 2009 Alex Martelli *
* *
* Copyright 2008 - 2024 Case Van Horsen *
* *
* This file is part of GMPY2. *
* *
* GMPY2 is free software: you can redistribute it and/or modify it under *
* the terms of the GNU Lesser General Public License as published by the *
* Free Software Foundation, either version 3 of the License, or (at your *
* option) any later version. *
* *
* GMPY2 is distributed in the hope that it will be useful, but WITHOUT *
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or *
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public *
* License for more details. *
* *
* You should have received a copy of the GNU Lesser General Public *
* License along with GMPY2; if not, see *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
#ifndef GMPY_HASH_H
#define GMPY_HASH_H
#ifdef __cplusplus
extern "C" {
#endif
static Py_hash_t GMPy_MPZ_Hash_Slot(MPZ_Object *self);
static Py_hash_t GMPy_MPQ_Hash_Slot(MPQ_Object *self);
static Py_hash_t GMPy_MPFR_Hash_Slot(MPFR_Object *self);
static Py_hash_t GMPy_MPC_Hash_Slot(MPC_Object *self);
#ifdef __cplusplus
}
#endif
#endif
././@PaxHeader 0000000 0000000 0000000 00000000026 00000000000 010213 x ustar 00 22 mtime=1710307256.0
gmpy2-2.2.1/src/gmpy2_macros.h 0000644 0001750 0001750 00000064644 14574233670 014615 0 ustar 00case case /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* gmpy2_macros.h *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Python interface to the GMP, MPFR, and MPC multiple precision *
* libraries. *
* *
* Copyright 2000 - 2009 Alex Martelli *
* *
* Copyright 2008 - 2024 Case Van Horsen *
* *
* This file is part of GMPY2. *
* *
* GMPY2 is free software: you can redistribute it and/or modify it under *
* the terms of the GNU Lesser General Public License as published by the *
* Free Software Foundation, either version 3 of the License, or (at your *
* option) any later version. *
* *
* GMPY2 is distributed in the hope that it will be useful, but WITHOUT *
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or *
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public *
* License for more details. *
* *
* You should have received a copy of the GNU Lesser General Public *
* License along with GMPY2; if not, see *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
/* This file contains a collection of macros that can be used to reduce
* repetitive code. As new macros are written to support of refactoring,
* they should be placed here.
*/
/* NAME is used as part of the GMPy function name. It usually uses an upper-
* case first character.
* FUNC is the component of the actual name used by MPFR and MPC.
*
* Note: the following macro can release the GIL.
* GMPY_MPFR_MPC_UNIOP_EXWT(NAME, FUNC) creates the following functions:
* GMPy_RealWithType_NAME(x, xtype, context)
* GMPy_ComplexWithType_NAME(x, xtype, context)
* GMPy_Number_NAME(x, context)
* GMPy_Context_NAME(self, other)
* - called with METH_O
*
* Note: the following macro is only used for is_xxx tests so it does
* not release the GIL.
* GMPY_MPFR_MPC_UNIOP_TEMPLATEWT(NAME, FUNC) creates the following functions:
* GMPy_Number_NAME(x, context)
* - assumes GMPy_RealWithType_NAME & GMPy_ComplexWithType_NAME exist
* GMPy_Context_NAME(self, other)
* - called with METH_O
*
* GMPY_MPFR_MPC_TRIOP_EX(NAME, FUNC) creates the following functions:
* GMPy_Real_NAME(x, y, Z, context)
* GMPy_Complex_NAME(x, y, Z, context)
* GMPy_Number_NAME(x, y, Z, context)
* - assumes GMPy_Integer_NAME & GMPy_Rational_NAME also exist
* GMPy_Context_NAME(self, args)
* - called with METH_VARARGS
*
* GMPY_MPFR_MPC_UNIOP_TEMPLATE(NAME, FUNC) creates the following functions:
* GMPy_Number_NAME(x, context)
* - assumes GMPy_Real_NAME & GMPy_Complex_NAME exist
* GMPy_Context_NAME(self, other)
* - called with METH_O
*
* GMPY_MPFR_UNIOP(NAME, FUNC) creates the following functions:
* GMPy_Real_NAME(x, context)
* GMPy_Number_NAME(x, context)
* GMPy_Context_NAME(self, other)
* - called with METH_O
*
* GMPY_MPFR_UNIOP_TEMPLATE(NAME, FUNC) creates the following functions:
* GMPy_Number_NAME(x, context)
* - assumes GMPy_Real_NAME exists
* GMPy_Context_NAME(self, other)
* - called with METH_O
*
* GMPY_MPFR_BINOP(NAME, FUNC) creates the following functions:
* GMPy_Real_NAME(x, y, context)
* GMPy_Number_NAME(x, y, context)
* GMPy_Context_NAME(self, args)
* - called with METH_VARARGS
*
*/
#define GMPY_MPFR_MPC_UNIOP_EXWT(NAME, FUNC) \
static PyObject * \
GMPy_RealWithType_##NAME(PyObject *x, int xtype, CTXT_Object *context) \
{ \
MPFR_Object *result = NULL, *tempx = NULL; \
if (IS_TYPE_MPFR(xtype)) { \
if (!(result = GMPy_MPFR_New(0, context))) return NULL; \
mpfr_clear_flags(); \
result->rc = mpfr_##FUNC(result->f, MPFR(x), GET_MPFR_ROUND(context)); \
_GMPy_MPFR_Cleanup(&result, context); \
return (PyObject*)result; \
} \
if (IS_TYPE_REAL(xtype)) { \
if (!(tempx = GMPy_MPFR_From_RealWithType(x, xtype, 1, context))) return NULL; \
if (!(result = GMPy_MPFR_New(0, context))) { \
Py_DECREF(tempx); \
return NULL; \
} \
mpfr_clear_flags(); \
result->rc = mpfr_##FUNC(result->f, MPFR(tempx), GET_MPFR_ROUND(context)); \
_GMPy_MPFR_Cleanup(&result, context); \
Py_DECREF(tempx); \
return (PyObject*)result; \
} \
TYPE_ERROR(#FUNC"() argument type not supported"); \
return NULL; \
} \
static PyObject * \
GMPy_ComplexWithType_##NAME(PyObject *x, int xtype, CTXT_Object *context) \
{ \
MPC_Object *result = NULL, *tempx = NULL; \
if (IS_TYPE_MPC(xtype)) { \
if (!(result = GMPy_MPC_New(0, 0, context))) return NULL; \
result->rc = mpc_##FUNC(result->c, MPC(x), GET_MPC_ROUND(context)); \
_GMPy_MPC_Cleanup(&result, context); \
return (PyObject*)result; \
} \
if (IS_TYPE_COMPLEX(xtype)) { \
if (!(tempx = GMPy_MPC_From_ComplexWithType(x, xtype, 1, 1, context))) return NULL; \
if (!(result = GMPy_MPC_New(0, 0, context))) { \
Py_DECREF(tempx); \
return NULL; \
} \
result->rc = mpc_##FUNC(result->c, MPC(tempx), GET_MPC_ROUND(context)); \
_GMPy_MPC_Cleanup(&result, context); \
Py_DECREF(tempx); \
return (PyObject*)result; \
} \
TYPE_ERROR(#FUNC"() argument type not supported"); \
return NULL; \
} \
static PyObject * \
GMPy_Number_##NAME(PyObject *x, CTXT_Object *context) \
{ \
CHECK_CONTEXT(context); \
int xtype = GMPy_ObjectType(x);\
if (IS_TYPE_REAL(xtype)) \
return GMPy_RealWithType_##NAME(x, xtype, context); \
if (IS_TYPE_COMPLEX(xtype)) \
return GMPy_ComplexWithType_##NAME(x, xtype, context); \
TYPE_ERROR(#FUNC"() argument type not supported"); \
return NULL; \
} \
static PyObject * \
GMPy_Context_##NAME(PyObject *self, PyObject *other) \
{ \
CTXT_Object *context = NULL; \
if (self && CTXT_Check(self)) { \
context = (CTXT_Object*)self; \
} \
else { \
CHECK_CONTEXT(context); \
} \
return GMPy_Number_##NAME(other, context); \
}
/*********************************************************************/
#define GMPY_MPFR_MPC_UNIOP_TEMPLATEWT(NAME, FUNC) \
static PyObject * \
GMPy_Number_##NAME(PyObject *x, CTXT_Object *context) \
{ \
CHECK_CONTEXT(context); \
int xtype = GMPy_ObjectType(x); \
if (IS_TYPE_REAL(xtype)) \
return GMPy_RealWithType_##NAME(x, xtype, context); \
if (IS_TYPE_COMPLEX(xtype)) \
return GMPy_ComplexWithType_##NAME(x, xtype, context); \
TYPE_ERROR(#FUNC"() argument type not supported"); \
return NULL; \
} \
static PyObject * \
GMPy_Context_##NAME(PyObject *self, PyObject *other) \
{ \
CTXT_Object *context = NULL; \
if (self && CTXT_Check(self)) { \
context = (CTXT_Object*)self; \
} \
else { \
CHECK_CONTEXT(context); \
} \
return GMPy_Number_##NAME(other, context); \
} \
static PyObject * \
GMPy_Number_Method_##NAME(PyObject *self, PyObject *args) \
{ \
return GMPy_Number_##NAME(self, NULL); \
} \
/*********************************************************************/
#define GMPY_MPFR_MPC_UNIOP_TEMPLATE_EXWT(NAME, FUNC) \
static PyObject * \
GMPy_Number_##NAME(PyObject *x, CTXT_Object *context) \
{ \
CHECK_CONTEXT(context); \
int xtype = GMPy_ObjectType(x); \
if (IS_TYPE_REAL(xtype)) \
return GMPy_RealWithType_##NAME(x, xtype, context); \
if (IS_TYPE_COMPLEX(xtype)) \
return GMPy_ComplexWithType_##NAME(x, xtype, context); \
TYPE_ERROR(#FUNC"() argument type not supported"); \
return NULL; \
} \
static PyObject * \
GMPy_Context_##NAME(PyObject *self, PyObject *other) \
{ \
CTXT_Object *context = NULL; \
if (self && CTXT_Check(self)) { \
context = (CTXT_Object*)self; \
} \
else { \
CHECK_CONTEXT(context); \
} \
return GMPy_Number_##NAME(other, context); \
} \
/*********************************************************************/
#define GMPY_MPFR_MPC_TRIOP_TEMPLATEWT(NAME, FUNC) \
static PyObject * \
GMPy_Number_##NAME(PyObject *x, PyObject *y, PyObject *z, CTXT_Object *context) \
{ \
CHECK_CONTEXT(context); \
int xtype = GMPy_ObjectType(x); \
int ytype = GMPy_ObjectType(y); \
int ztype = GMPy_ObjectType(z); \
if (IS_TYPE_MPZ(xtype) && IS_TYPE_MPZ(ytype) && IS_TYPE_MPZ(ztype)) \
return _GMPy_MPZ_##NAME(x, y, z, context); \
if (IS_TYPE_MPQ(xtype) && IS_TYPE_MPQ(ytype) && IS_TYPE_MPQ(ztype)) \
return _GMPy_MPQ_##NAME(x, y, z, context); \
if (IS_TYPE_MPFR(xtype) && IS_TYPE_MPFR(ytype) && IS_TYPE_MPFR(ztype)) \
return _GMPy_MPFR_##NAME(x, y, z, context); \
if (IS_TYPE_MPC(xtype) && IS_TYPE_MPC(ytype) && IS_TYPE_MPC(ztype)) \
return _GMPy_MPC_##NAME(x, y, z, context); \
if (IS_TYPE_INTEGER(xtype) && IS_TYPE_INTEGER(ytype) && IS_TYPE_INTEGER(ztype)) \
return GMPy_IntegerWithType_##NAME(x, xtype, y, ytype, z, ztype, context); \
if (IS_TYPE_RATIONAL(xtype) && IS_TYPE_RATIONAL(ytype) && IS_TYPE_RATIONAL(ztype)) \
return GMPy_RationalWithType_##NAME(x, xtype, y, ytype, z, ztype, context); \
if (IS_TYPE_REAL(xtype) && IS_TYPE_REAL(ytype) && IS_TYPE_REAL(ztype)) \
return GMPy_RealWithType_##NAME(x, xtype, y, ytype, z, ztype, context); \
if (IS_TYPE_COMPLEX(xtype) && IS_TYPE_COMPLEX(ytype) && IS_TYPE_COMPLEX(ztype)) \
return GMPy_ComplexWithType_##NAME(x, xtype, y, ytype, z, ztype, context); \
TYPE_ERROR(#FUNC"() argument type not supported"); \
return NULL; \
} \
static PyObject * \
GMPy_Context_##NAME(PyObject *self, PyObject *args) \
{ \
CTXT_Object *context = NULL; \
if (PyTuple_GET_SIZE(args) != 3) { \
TYPE_ERROR(#FUNC"() requires 3 arguments"); \
return NULL; \
} \
if (self && CTXT_Check(self)) { \
context = (CTXT_Object*)self; \
} \
else { \
CHECK_CONTEXT(context); \
} \
return GMPy_Number_##NAME(PyTuple_GET_ITEM(args, 0), \
PyTuple_GET_ITEM(args, 1), \
PyTuple_GET_ITEM(args, 2), context); \
}
/*********************************************************************/
#define GMPY_MPFR_QUADOP_TEMPLATEWT(NAME, FUNC) \
static PyObject * \
GMPy_Number_##NAME(PyObject *x, PyObject *y, PyObject *z, PyObject *t, CTXT_Object *context) \
{ \
CHECK_CONTEXT(context); \
int xtype = GMPy_ObjectType(x); \
int ytype = GMPy_ObjectType(y); \
int ztype = GMPy_ObjectType(z); \
int ttype = GMPy_ObjectType(t); \
if (IS_TYPE_MPZ(xtype) && IS_TYPE_MPZ(ytype) && IS_TYPE_MPZ(ztype) && IS_TYPE_MPZ(ttype)) \
return _GMPy_MPZ_##NAME(x, y, z, t, context); \
if (IS_TYPE_MPQ(xtype) && IS_TYPE_MPQ(ytype) && IS_TYPE_MPQ(ztype) && IS_TYPE_MPQ(ttype)) \
return _GMPy_MPQ_##NAME(x, y, z, t, context); \
if (IS_TYPE_MPFR(xtype) && IS_TYPE_MPFR(ytype) && IS_TYPE_MPFR(ztype) && IS_TYPE_MPFR(ttype)) \
return _GMPy_MPFR_##NAME(x, y, z, t, context); \
if (IS_TYPE_INTEGER(xtype) && IS_TYPE_INTEGER(ytype) && IS_TYPE_INTEGER(ztype) && IS_TYPE_INTEGER(ttype)) \
return GMPy_IntegerWithType_##NAME(x, xtype, y, ytype, z, ztype, t, ttype, context); \
if (IS_TYPE_RATIONAL(xtype) && IS_TYPE_RATIONAL(ytype) && IS_TYPE_RATIONAL(ztype) && IS_TYPE_RATIONAL(ttype)) \
return GMPy_RationalWithType_##NAME(x, xtype, y, ytype, z, ztype, t, ttype, context); \
if (IS_TYPE_REAL(xtype) && IS_TYPE_REAL(ytype) && IS_TYPE_REAL(ztype) && IS_TYPE_REAL(ttype)) \
return GMPy_RealWithType_##NAME(x, xtype, y, ytype, z, ztype, t, ttype, context); \
TYPE_ERROR(#FUNC"() argument type not supported"); \
return NULL; \
} \
static PyObject * \
GMPy_Context_##NAME(PyObject *self, PyObject *args) \
{ \
CTXT_Object *context = NULL; \
if (PyTuple_GET_SIZE(args) != 4) { \
TYPE_ERROR(#FUNC"() requires 4 arguments"); \
return NULL; \
} \
if (self && CTXT_Check(self)) { \
context = (CTXT_Object*)self; \
} \
else { \
CHECK_CONTEXT(context); \
} \
return GMPy_Number_##NAME(PyTuple_GET_ITEM(args, 0), \
PyTuple_GET_ITEM(args, 1), \
PyTuple_GET_ITEM(args, 2), \
PyTuple_GET_ITEM(args, 3), context); \
}
/*********************************************************************/
#define GMPY_MPFR_UNIOP_NOROUNDWT(NAME, FUNC) \
static PyObject * \
GMPy_RealWithType_##NAME(PyObject *x, int xtype, CTXT_Object *context) \
{ \
MPFR_Object *result = NULL, *tempx = NULL; \
result = GMPy_MPFR_New(0, context); \
tempx = GMPy_MPFR_From_RealWithType(x, xtype, 1, context); \
if (!result || !tempx) { \
Py_XDECREF((PyObject*)result); \
Py_XDECREF((PyObject*)tempx); \
return NULL; \
} \
mpfr_clear_flags(); \
result->rc = mpfr_##FUNC(result->f, tempx->f); \
Py_DECREF((PyObject*)tempx); \
_GMPy_MPFR_Cleanup(&result, context); \
return (PyObject*)result; \
} \
static PyObject * \
GMPy_Number_##NAME(PyObject *x, CTXT_Object *context) \
{ \
int xtype = GMPy_ObjectType(x); \
if (IS_TYPE_REAL(xtype)) \
return GMPy_RealWithType_##NAME(x, xtype, context); \
TYPE_ERROR(#FUNC"() argument type not supported"); \
return NULL; \
} \
static PyObject * \
GMPy_MPFR_Method_##NAME(PyObject *self, PyObject *other) \
{ \
CTXT_Object *context = NULL; \
CHECK_CONTEXT(context); \
return GMPy_Number_##NAME(self, context); \
}\
static PyObject * \
GMPy_Context_##NAME(PyObject *self, PyObject *other) \
{ \
CTXT_Object *context = NULL; \
if (self && CTXT_Check(self)) { \
context = (CTXT_Object*)self; \
} \
else { \
CHECK_CONTEXT(context); \
} \
return GMPy_Number_##NAME(other, context); \
}
/*********************************************************************/
#define GMPY_MPFR_UNIOP_NOROUND_NOMETHODWT(NAME, FUNC) \
static PyObject * \
GMPy_RealWithType_##NAME(PyObject *x, int xtype, CTXT_Object *context) \
{ \
MPFR_Object *result = NULL, *tempx = NULL; \
result = GMPy_MPFR_New(0, context); \
tempx = GMPy_MPFR_From_RealWithType(x, xtype, 1, context); \
if (!result || !tempx) { \
Py_XDECREF((PyObject*)result); \
Py_XDECREF((PyObject*)tempx); \
return NULL; \
} \
mpfr_clear_flags(); \
result->rc = mpfr_##FUNC(result->f, tempx->f); \
Py_DECREF((PyObject*)tempx); \
_GMPy_MPFR_Cleanup(&result, context); \
return (PyObject*)result; \
} \
static PyObject * \
GMPy_Number_##NAME(PyObject *x, CTXT_Object *context) \
{ \
int xtype = GMPy_ObjectType(x); \
if (IS_TYPE_REAL(xtype)) \
return GMPy_RealWithType_##NAME(x, xtype, context); \
TYPE_ERROR(#FUNC"() argument type not supported"); \
return NULL; \
} \
static PyObject * \
GMPy_Context_##NAME(PyObject *self, PyObject *other) \
{ \
CTXT_Object *context = NULL; \
if (self && CTXT_Check(self)) { \
context = (CTXT_Object*)self; \
} \
else { \
CHECK_CONTEXT(context); \
} \
return GMPy_Number_##NAME(other, context); \
}
/*********************************************************************/
#define GMPY_MPFR_UNIOP_EXWT(NAME, FUNC) \
static PyObject * \
GMPy_RealWithType_##NAME(PyObject *x, int xtype, CTXT_Object *context) \
{ \
MPFR_Object *result = NULL, *tempx = NULL; \
if (IS_TYPE_MPFR(xtype)) { \
if (!(result = GMPy_MPFR_New(0, context))) return NULL; \
mpfr_clear_flags(); \
result->rc = mpfr_##FUNC(result->f, MPFR(x), GET_MPFR_ROUND(context)); \
_GMPy_MPFR_Cleanup(&result, context); \
return (PyObject*)result; \
} \
if (IS_TYPE_REAL(xtype)) { \
if (!(tempx = GMPy_MPFR_From_RealWithType(x, xtype, 1, context))) return NULL; \
if (!(result = GMPy_MPFR_New(0, context))) { \
Py_DECREF(tempx); \
return NULL; \
} \
mpfr_clear_flags(); \
result->rc = mpfr_##FUNC(result->f, MPFR(tempx), GET_MPFR_ROUND(context)); \
Py_DECREF(tempx); \
_GMPy_MPFR_Cleanup(&result, context); \
return (PyObject*)result; \
} \
TYPE_ERROR(#FUNC"() argument type not supported"); \
return NULL; \
} \
static PyObject * \
GMPy_Number_##NAME(PyObject *x, CTXT_Object *context) \
{ \
CHECK_CONTEXT(context); \
int xtype = GMPy_ObjectType(x);\
if (IS_TYPE_REAL(xtype)) \
return GMPy_RealWithType_##NAME(x, xtype, context); \
TYPE_ERROR(#FUNC"() argument type not supported"); \
return NULL; \
} \
static PyObject * \
GMPy_Context_##NAME(PyObject *self, PyObject *other) \
{ \
CTXT_Object *context = NULL; \
if (self && CTXT_Check(self)) { \
context = (CTXT_Object*)self; \
} \
else { \
CHECK_CONTEXT(context); \
} \
return GMPy_Number_##NAME(other, context); \
}
/*********************************************************************/
#define GMPY_MPFR_UNIOP_TEMPLATEWT(NAME, FUNC) \
static PyObject * \
GMPy_Number_##NAME(PyObject *x, CTXT_Object *context) \
{ \
CHECK_CONTEXT(context); \
int xtype = GMPy_ObjectType(x);\
if (IS_TYPE_REAL(xtype)) \
return GMPy_RealWithType_##NAME(x, xtype, context); \
TYPE_ERROR(#FUNC"() argument type not supported"); \
return NULL; \
} \
static PyObject * \
GMPy_Context_##NAME(PyObject *self, PyObject *other) \
{ \
CTXT_Object *context = NULL; \
if (self && CTXT_Check(self)) { \
context = (CTXT_Object*)self; \
} \
else { \
CHECK_CONTEXT(context); \
} \
return GMPy_Number_##NAME(other, context); \
}
/*********************************************************************/
#define GMPY_MPFR_BINOPWT(NAME, FUNC) \
static PyObject * \
GMPy_RealWithType_##NAME(PyObject *x, int xtype, PyObject *y, int ytype, CTXT_Object *context) \
{ \
MPFR_Object *result = NULL, *tempx = NULL, *tempy = NULL; \
tempx = GMPy_MPFR_From_RealWithType(x, xtype, 1, context); \
tempy = GMPy_MPFR_From_RealWithType(y, ytype, 1, context); \
result = GMPy_MPFR_New(0, context); \
if (!result || !tempx || !tempy) { \
Py_XDECREF((PyObject*)tempx); \
Py_XDECREF((PyObject*)tempy); \
Py_XDECREF((PyObject*)result); \
return NULL; \
} \
mpfr_clear_flags(); \
result->rc = mpfr_##FUNC(result->f, tempx->f, tempy->f, GET_MPFR_ROUND(context)); \
Py_DECREF((PyObject*)tempx); \
Py_DECREF((PyObject*)tempy); \
_GMPy_MPFR_Cleanup(&result, context); \
return (PyObject*)result; \
} \
static PyObject * \
GMPy_Number_##NAME(PyObject *x, PyObject *y, CTXT_Object *context) \
{ \
int xtype = GMPy_ObjectType(x); \
int ytype = GMPy_ObjectType(y); \
CHECK_CONTEXT(context); \
if (IS_TYPE_REAL(xtype) && IS_TYPE_REAL(ytype)) \
return GMPy_RealWithType_##NAME(x, xtype, y, ytype, context); \
TYPE_ERROR(#FUNC"() argument type not supported"); \
return NULL; \
} \
static PyObject * \
GMPy_Context_##NAME(PyObject *self, PyObject *args) \
{ \
CTXT_Object *context = NULL; \
if (PyTuple_GET_SIZE(args) != 2) { \
TYPE_ERROR(#FUNC"() requires 2 arguments"); \
return NULL; \
} \
if (self && CTXT_Check(self)) { \
context = (CTXT_Object*)self; \
} \
else { \
CHECK_CONTEXT(context); \
} \
return GMPy_Number_##NAME(PyTuple_GET_ITEM(args, 0), PyTuple_GET_ITEM(args, 1), context); \
} \
/* Macro to support functions that require ('mpfr', 'int').
* More precisely, the first argument must pass IS_REAL() and the second
* argument must pass IS_INTEGER(). The calling sequence passes n first
* to the MPFR library.*/
/*********************************************************************/
#define GMPY_MPFR_BINOP_REAL_LONGWT(NAME, FUNC) \
static PyObject * \
GMPy_RealWithType_##NAME(PyObject *x, int xtype, PyObject *y, int ytype, CTXT_Object *context) \
{ \
MPFR_Object *result = NULL, *tempx = NULL; \
long n; \
result = GMPy_MPFR_New(0, context); \
tempx = GMPy_MPFR_From_RealWithType(x, xtype, 1, context); \
n = GMPy_Integer_AsLongWithType(y, ytype); \
if (!result || !tempx || (n == -1 && PyErr_Occurred())) { \
Py_XDECREF((PyObject*)tempx); \
Py_XDECREF((PyObject*)result); \
return NULL; \
} \
mpfr_clear_flags(); \
result->rc = mpfr_##FUNC(result->f, n, tempx->f, GET_MPFR_ROUND(context)); \
Py_DECREF((PyObject*)tempx); \
_GMPy_MPFR_Cleanup(&result, context); \
return (PyObject*)result; \
} \
static PyObject * \
GMPy_Number_##NAME(PyObject *x, PyObject *y, CTXT_Object *context) \
{ \
int xtype = GMPy_ObjectType(x); \
int ytype = GMPy_ObjectType(y); \
CHECK_CONTEXT(context); \
if (IS_TYPE_REAL(xtype) && IS_TYPE_INTEGER(ytype)) \
return GMPy_RealWithType_##NAME(x, xtype, y, ytype, context); \
TYPE_ERROR(#FUNC"() argument type not supported"); \
return NULL; \
} \
static PyObject * \
GMPy_Context_##NAME(PyObject *self, PyObject *args) \
{ \
CTXT_Object *context = NULL; \
if (PyTuple_GET_SIZE(args) != 2) { \
TYPE_ERROR(#FUNC"() requires 2 arguments"); \
return NULL; \
} \
if (self && CTXT_Check(self)) { \
context = (CTXT_Object*)self; \
} \
else { \
CHECK_CONTEXT(context); \
} \
return GMPy_Number_##NAME(PyTuple_GET_ITEM(args, 0), PyTuple_GET_ITEM(args, 1), context); \
} \
/*********************************************************************/
/* Support standard calling convention for jn() and yn().*/
#define GMPY_MPFR_BINOP_LONG_REALWT(NAME, FUNC) \
static PyObject * \
GMPy_RealWithType_##NAME(PyObject *x, int xtype, PyObject *y, int ytype, CTXT_Object *context) \
{ \
MPFR_Object *result = NULL, *temp = NULL; \
long n; \
result = GMPy_MPFR_New(0, context); \
temp = GMPy_MPFR_From_RealWithType(y, ytype, 1, context); \
n = GMPy_Integer_AsLongWithType(x, xtype); \
if (!result || !temp || (n == -1 && PyErr_Occurred())) { \
Py_XDECREF((PyObject*)temp); \
Py_XDECREF((PyObject*)result); \
return NULL; \
} \
mpfr_clear_flags(); \
result->rc = mpfr_##FUNC(result->f, n, temp->f, GET_MPFR_ROUND(context)); \
Py_DECREF((PyObject*)temp); \
_GMPy_MPFR_Cleanup(&result, context); \
return (PyObject*)result; \
} \
static PyObject * \
GMPy_Number_##NAME(PyObject *x, PyObject *y, CTXT_Object *context) \
{ \
int xtype = GMPy_ObjectType(x); \
int ytype = GMPy_ObjectType(y); \
CHECK_CONTEXT(context); \
if (IS_TYPE_INTEGER(xtype) && IS_TYPE_REAL(ytype)) \
return GMPy_RealWithType_##NAME(x, xtype, y, ytype, context); \
TYPE_ERROR(#FUNC"() argument types not supported. Note that the argument order " \
"for jn() and yn() has changed to (int, mpfr) instead of (mpfr,int)."); \
return NULL; \
} \
static PyObject * \
GMPy_Context_##NAME(PyObject *self, PyObject *args) \
{ \
CTXT_Object *context = NULL; \
if (PyTuple_GET_SIZE(args) != 2) { \
TYPE_ERROR(#FUNC"() requires 2 arguments"); \
return NULL; \
} \
if (self && CTXT_Check(self)) { \
context = (CTXT_Object*)self; \
} \
else { \
CHECK_CONTEXT(context); \
} \
return GMPy_Number_##NAME(PyTuple_GET_ITEM(args, 0), PyTuple_GET_ITEM(args, 1), context); \
} \
/*********************************************************************/
#define GMPY_MPFR_BINOP_TEMPLATEWT(NAME, FUNC) \
static PyObject * \
GMPy_Number_##NAME(PyObject *x, PyObject *y, CTXT_Object *context) \
{ \
int xtype = GMPy_ObjectType(x); \
int ytype = GMPy_ObjectType(y); \
CHECK_CONTEXT(context); \
if (IS_TYPE_REAL(xtype) && IS_TYPE_REAL(ytype)) \
return GMPy_RealWithType_##NAME(x, xtype, y, ytype, context); \
TYPE_ERROR(#FUNC"() argument type not supported"); \
return NULL; \
} \
static PyObject * \
GMPy_Context_##NAME(PyObject *self, PyObject *args) \
{ \
CTXT_Object *context = NULL; \
if (PyTuple_GET_SIZE(args) != 2) { \
TYPE_ERROR(#FUNC"() requires 2 arguments"); \
return NULL; \
} \
if (self && CTXT_Check(self)) { \
context = (CTXT_Object*)self; \
} \
else { \
CHECK_CONTEXT(context); \
} \
return GMPy_Number_##NAME(PyTuple_GET_ITEM(args, 0), PyTuple_GET_ITEM(args, 1), context); \
} \
/*********************************************************************/
#define GMPY_MPFR_BINOP_EXWT(NAME, FUNC) \
static PyObject * \
GMPy_RealWithType_##NAME(PyObject *x, int xtype, PyObject *y, int ytype, CTXT_Object *context) \
{ \
MPFR_Object *result = NULL, *tempx = NULL, *tempy = NULL; \
CHECK_CONTEXT(context); \
tempx = GMPy_MPFR_From_RealWithType(x, xtype, 1, context); \
tempy = GMPy_MPFR_From_RealWithType(y, ytype, 1, context); \
result = GMPy_MPFR_New(0, context); \
if (!tempx || !tempy || !result) { \
Py_XDECREF(tempx); \
Py_XDECREF(tempy); \
Py_XDECREF(result); \
return NULL; \
} \
mpfr_clear_flags(); \
result->rc = mpfr_##FUNC(result->f, tempx->f, tempy->f, GET_MPFR_ROUND(context)); \
Py_DECREF(tempx); \
Py_DECREF(tempy); \
_GMPy_MPFR_Cleanup(&result, context); \
return (PyObject*)result; \
} \
static PyObject * \
GMPy_Number_##NAME(PyObject *x, PyObject *y, CTXT_Object *context) \
{ \
int xtype = GMPy_ObjectType(x); \
int ytype = GMPy_ObjectType(y); \
CHECK_CONTEXT(context); \
if (IS_TYPE_REAL(xtype) && IS_TYPE_REAL(ytype)) \
return GMPy_RealWithType_##NAME(x, xtype, y, ytype, context); \
TYPE_ERROR(#FUNC"() argument type not supported"); \
return NULL; \
} \
static PyObject * \
GMPy_Context_##NAME(PyObject *self, PyObject *args) \
{ \
CTXT_Object *context = NULL; \
if (PyTuple_GET_SIZE(args) != 2) { \
TYPE_ERROR(#FUNC"() requires 2 arguments"); \
return NULL; \
} \
if (self && CTXT_Check(self)) { \
context = (CTXT_Object*)self; \
} \
else { \
CHECK_CONTEXT(context); \
} \
return GMPy_Number_##NAME(PyTuple_GET_ITEM(args, 0), PyTuple_GET_ITEM(args, 1), context); \
}
././@PaxHeader 0000000 0000000 0000000 00000000026 00000000000 010213 x ustar 00 22 mtime=1710307256.0
gmpy2-2.2.1/src/gmpy2_math.c 0000644 0001750 0001750 00000163475 14574233670 014257 0 ustar 00case case /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* gmpy2_math.c *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Python interface to the GMP, MPFR, and MPC multiple precision *
* libraries. *
* *
* Copyright 2000 - 2009 Alex Martelli *
* *
* Copyright 2008 - 2024 Case Van Horsen *
* *
* This file is part of GMPY2. *
* *
* GMPY2 is free software: you can redistribute it and/or modify it under *
* the terms of the GNU Lesser General Public License as published by the *
* Free Software Foundation, either version 3 of the License, or (at your *
* option) any later version. *
* *
* GMPY2 is distributed in the hope that it will be useful, but WITHOUT *
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or *
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public *
* License for more details. *
* *
* You should have received a copy of the GNU Lesser General Public *
* License along with GMPY2; if not, see *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
PyDoc_STRVAR(GMPy_doc_context_sin,
"context.sin(x, /) -> mpfr | mpc\n\n"
"Return sine of x; x in radians.");
PyDoc_STRVAR(GMPy_doc_function_sin,
"sin(x, /) -> mpfr | mpc\n\n"
"Return sine of x; x in radians.");
GMPY_MPFR_MPC_UNIOP_EXWT(Sin, sin)
PyDoc_STRVAR(GMPy_doc_context_cos,
"context.cos(x, /) -> mpfr | mpc\n\n"
"Return cosine of x; x in radians.");
PyDoc_STRVAR(GMPy_doc_function_cos,
"cos(x, /) -> mpfr | mpc\n\n"
"Return cosine of x; x in radians.");
GMPY_MPFR_MPC_UNIOP_EXWT(Cos, cos)
PyDoc_STRVAR(GMPy_doc_context_tan,
"context.tan(x, /) -> mpfr | mpc\n\n"
"Return tangent of x; x in radians.");
PyDoc_STRVAR(GMPy_doc_function_tan,
"tan(x, /) -> mpfr | mpc\n\n"
"Return tangent of x; x in radians.");
GMPY_MPFR_MPC_UNIOP_EXWT(Tan, tan)
PyDoc_STRVAR(GMPy_doc_context_atan,
"context.atan(x, /) -> mpfr | mpc\n\n"
"Return inverse tangent of x; result in radians.");
PyDoc_STRVAR(GMPy_doc_function_atan,
"atan(x, /) -> mpfr | mpc\n\n"
"Return inverse tangent of x; result in radians.");
GMPY_MPFR_MPC_UNIOP_EXWT(Atan, atan)
PyDoc_STRVAR(GMPy_doc_context_sinh,
"context.sinh(x, /) -> mpfr | mpc\n\n"
"Return hyperbolic sine of x.");
PyDoc_STRVAR(GMPy_doc_function_sinh,
"sinh(x, /) -> mpfr | mpc\n\n"
"Return hyperbolic sine of x.");
GMPY_MPFR_MPC_UNIOP_EXWT(Sinh, sinh)
PyDoc_STRVAR(GMPy_doc_context_cosh,
"context.cosh(x, /) -> mpfr | mpc\n\n"
"Return hyperbolic cosine of x.");
PyDoc_STRVAR(GMPy_doc_function_cosh,
"cosh(x, /) -> mpfr | mpc\n\n"
"Return hyperbolic cosine of x.");
GMPY_MPFR_MPC_UNIOP_EXWT(Cosh, cosh)
PyDoc_STRVAR(GMPy_doc_context_tanh,
"context.tanh(x, /) -> mpfr | mpc\n\n"
"Return hyperbolic tangent of x.");
PyDoc_STRVAR(GMPy_doc_function_tanh,
"tanh(x, /) -> mpfr | mpc\n\n"
"Return hyperbolic tangent of x.");
GMPY_MPFR_MPC_UNIOP_EXWT(Tanh, tanh)
PyDoc_STRVAR(GMPy_doc_context_asinh,
"context.asinh(x, /) -> mpfr | mpc\n\n"
"Return inverse hyperbolic sine of x.");
PyDoc_STRVAR(GMPy_doc_function_asinh,
"asinh(x, /) -> mpfr | mpc\n\n"
"Return inverse hyperbolic sine of x.");
GMPY_MPFR_MPC_UNIOP_EXWT(Asinh, asinh)
PyDoc_STRVAR(GMPy_doc_context_acosh,
"context.acosh(x, /) -> mpfr | mpc\n\n"
"Return inverse hyperbolic cosine of x.");
PyDoc_STRVAR(GMPy_doc_function_acosh,
"acosh(x, /) -> mpfr | mpc\n\n"
"Return inverse hyperbolic cosine of x.");
GMPY_MPFR_MPC_UNIOP_EXWT(Acosh, acosh)
/* Section 2:
* These functions accept a single argument and return an mpfr result.
*
* GMPY_MPFR_UNIOP(NAME, FUNC) creates the following functions:
* GMPy_Real_NAME(x, context)
* GMPy_Number_NAME(x, context)
* GMPy_Context_NAME(self, other)
* - called with METH_O
*/
PyDoc_STRVAR(GMPy_doc_context_sec,
"context.sec(x, /) -> mpfr\n\n"
"Return secant of x; x in radians.");
PyDoc_STRVAR(GMPy_doc_function_sec,
"sec(x, /) -> mpfr\n\n"
"Return secant of x; x in radians.");
GMPY_MPFR_UNIOP_EXWT(Sec, sec)
PyDoc_STRVAR(GMPy_doc_context_csc,
"context.csc(x, /) -> mpfr\n\n"
"Return cosecant of x; x in radians.");
PyDoc_STRVAR(GMPy_doc_function_csc,
"csc(x, /) -> mpfr\n\n"
"Return cosecant of x; x in radians.");
GMPY_MPFR_UNIOP_EXWT(Csc, csc)
PyDoc_STRVAR(GMPy_doc_context_cot,
"context.cot(x, /) -> mpfr\n\n"
"Return cotangent of x; x in radians.");
PyDoc_STRVAR(GMPy_doc_function_cot,
"cot(x, /) -> mpfr\n\n"
"Return cotangent of x; x in radians.");
GMPY_MPFR_UNIOP_EXWT(Cot, cot)
PyDoc_STRVAR(GMPy_doc_context_sech,
"context.sech(x, /) -> mpfr\n\n"
"Return hyperbolic secant of x.");
PyDoc_STRVAR(GMPy_doc_function_sech,
"sech(x, /) -> mpfr\n\n"
"Return hyperbolic secant of x.");
GMPY_MPFR_UNIOP_EXWT(Sech, sech)
PyDoc_STRVAR(GMPy_doc_context_csch,
"context.csch(x, /) -> mpfr\n\n"
"Return hyperbolic cosecant of x.");
PyDoc_STRVAR(GMPy_doc_function_csch,
"csch(x, /) -> mpfr\n\n"
"Return hyperbolic cosecant of x.");
GMPY_MPFR_UNIOP_EXWT(Csch, csch)
PyDoc_STRVAR(GMPy_doc_context_coth,
"context.coth(x, /) -> mpfr\n\n"
"Return hyperbolic cotangent of x.");
PyDoc_STRVAR(GMPy_doc_function_coth,
"coth(x, /) -> mpfr\n\n"
"Return hyperbolic cotangent of x.");
GMPY_MPFR_UNIOP_EXWT(Coth, coth)
PyDoc_STRVAR(GMPy_doc_context_rec_sqrt,
"context.rec_sqrt(x, /) -> mpfr\n\n"
"Return the reciprocal of the square root of x.");
PyDoc_STRVAR(GMPy_doc_function_rec_sqrt,
"rec_sqrt(x, /) -> mpfr\n\n"
"Return the reciprocal of the square root of x.");
GMPY_MPFR_UNIOP_EXWT(RecSqrt, rec_sqrt)
PyDoc_STRVAR(GMPy_doc_context_rint,
"context.rint(x, /) -> mpfr\n\n"
"Return x rounded to the nearest integer using the context rounding\n"
"mode.");
PyDoc_STRVAR(GMPy_doc_function_rint,
"rint(x, /) -> mpfr\n\n"
"Return x rounded to the nearest integer using the current rounding\n"
"mode.");
GMPY_MPFR_UNIOP_EXWT(Rint, rint)
PyDoc_STRVAR(GMPy_doc_context_rint_ceil,
"context.rint_ceil(x, /) -> mpfr\n\n"
"Return x rounded to the nearest integer by first rounding to the\n"
"next higher or equal integer and then, if needed, using the context\n"
"rounding mode.");
PyDoc_STRVAR(GMPy_doc_function_rint_ceil,
"rint_ceil(x, /) -> mpfr\n\n"
"Return x rounded to the nearest integer by first rounding to the\n"
"next higher or equal integer and then, if needed, using the current\n"
"rounding mode.");
GMPY_MPFR_UNIOP_EXWT(RintCeil, rint_ceil)
PyDoc_STRVAR(GMPy_doc_context_rint_floor,
"context.rint_floor(x, /) -> mpfr\n\n"
"Return x rounded to the nearest integer by first rounding to the\n"
"next lower or equal integer and then, if needed, using the context\n"
"rounding mode.");
PyDoc_STRVAR(GMPy_doc_function_rint_floor,
"rint_floor(x, /) -> mpfr\n\n"
"Return x rounded to the nearest integer by first rounding to the\n"
"next lower or equal integer and then, if needed, using the current\n"
"rounding mode.");
GMPY_MPFR_UNIOP_EXWT(RintFloor, rint_floor)
PyDoc_STRVAR(GMPy_doc_context_rint_round,
"context.rint_round(x, /) -> mpfr\n\n"
"Return x rounded to the nearest integer by first rounding to the\n"
"nearest integer (ties away from 0) and then, if needed, using\n"
"the context rounding mode.");
PyDoc_STRVAR(GMPy_doc_function_rint_round,
"rint_round(x, /) -> mpfr\n\n"
"Return x rounded to the nearest integer by first rounding to the\n"
"nearest integer (ties away from 0) and then, if needed, using\n"
"the current rounding mode.");
GMPY_MPFR_UNIOP_EXWT(RintRound, rint_round)
PyDoc_STRVAR(GMPy_doc_context_rint_trunc,
"context.rint_trunc(x, /) -> mpfr\n\n"
"Return x rounded to the nearest integer by first rounding towards\n"
"zero and then, if needed, using the context rounding mode.");
PyDoc_STRVAR(GMPy_doc_function_rint_trunc,
"rint_trunc(x, /) -> mpfr\n\n"
"Return x rounded to the nearest integer by first rounding towards\n"
"zero and then, if needed, using the current rounding mode.");
GMPY_MPFR_UNIOP_EXWT(RintTrunc, rint_trunc)
PyDoc_STRVAR(GMPy_doc_context_frac,
"context.frac(x, /) -> mpfr\n\n"
"Return fractional part of x.");
PyDoc_STRVAR(GMPy_doc_function_frac,
"frac(x, /) -> mpfr\n\n"
"Return fractional part of x.");
GMPY_MPFR_UNIOP_EXWT(Frac, frac)
PyDoc_STRVAR(GMPy_doc_context_cbrt,
"context.cbrt(x, /) -> mpfr\n\n"
"Return the cube root of x.");
PyDoc_STRVAR(GMPy_doc_function_cbrt,
"cbrt(x, /) -> mpfr\n\n"
"Return the cube root of x.");
GMPY_MPFR_UNIOP_EXWT(Cbrt, cbrt)
PyDoc_STRVAR(GMPy_doc_context_log2,
"context.log2(x, /) -> mpfr\n\n"
"Return base-2 logarithm of x.");
PyDoc_STRVAR(GMPy_doc_function_log2,
"log2(x, /) -> mpfr\n\n"
"Return base-2 logarithm of x.");
GMPY_MPFR_UNIOP_EXWT(Log2, log2)
PyDoc_STRVAR(GMPy_doc_context_exp2,
"context.exp2(x, /) -> mpfr\n\n"
"Return 2**x.");
PyDoc_STRVAR(GMPy_doc_function_exp2,
"exp2(x, /) -> mpfr\n\n"
"Return 2**x.");
GMPY_MPFR_UNIOP_EXWT(Exp2, exp2)
PyDoc_STRVAR(GMPy_doc_context_exp10,
"context.exp10(x, /) -> mpfr\n\n"
"Return 10**x.");
PyDoc_STRVAR(GMPy_doc_function_exp10,
"exp10(x, /) -> mpfr\n\n"
"Return 10**x.");
GMPY_MPFR_UNIOP_EXWT(Exp10, exp10)
PyDoc_STRVAR(GMPy_doc_context_log1p,
"context.log1p(x, /) -> mpfr\n\n"
"Return natural logarithm of (1+x).");
PyDoc_STRVAR(GMPy_doc_function_log1p,
"log1p(x, /) -> mpfr\n\n"
"Return natural logarithm of (1+x).");
GMPY_MPFR_UNIOP_EXWT(Log1p, log1p)
PyDoc_STRVAR(GMPy_doc_context_expm1,
"context.expm1(x, /) -> mpfr\n\n"
"Return exp(x) - 1.");
PyDoc_STRVAR(GMPy_doc_function_expm1,
"expm1(x, /) -> mpfr\n\n"
"Return exp(x) - 1.");
GMPY_MPFR_UNIOP_EXWT(Expm1, expm1)
PyDoc_STRVAR(GMPy_doc_context_eint,
"context.eint(x, /) -> mpfr\n\n"
"Return exponential integral of x.");
PyDoc_STRVAR(GMPy_doc_function_eint,
"eint(x, /) -> mpfr\n\n"
"Return exponential integral of x.");
GMPY_MPFR_UNIOP_EXWT(Eint, eint)
PyDoc_STRVAR(GMPy_doc_context_li2,
"context.li2(x, /) -> mpfr\n\n"
"Return real part of dilogarithm of x.");
PyDoc_STRVAR(GMPy_doc_function_li2,
"li2(x, /) -> mpfr\n\n"
"Return real part of dilogarithm of x.");
GMPY_MPFR_UNIOP_EXWT(Li2, li2)
PyDoc_STRVAR(GMPy_doc_context_gamma,
"context.gamma(x, /) -> mpfr\n\n"
"Return gamma of x.");
PyDoc_STRVAR(GMPy_doc_function_gamma,
"gamma(x, /) -> mpfr\n\n"
"Return gamma of x.");
GMPY_MPFR_UNIOP_EXWT(Gamma, gamma)
PyDoc_STRVAR(GMPy_doc_function_gamma_inc,
"gamma_inc(a, x, /) -> mpfr\n\n\
Return (upper) incomplete gamma of a and x.");
PyDoc_STRVAR(GMPy_doc_context_gamma_inc,
"context.gamma_inc(a, x, /) -> mpfr\n\n\
Return (upper) incomplete gamma of a and x.");
GMPY_MPFR_BINOP_EXWT(Gamma_Inc, gamma_inc)
PyDoc_STRVAR(GMPy_doc_context_lngamma,
"context.lngamma(x, /) -> mpfr\n\n"
"Return natural logarithm of gamma(x).");
PyDoc_STRVAR(GMPy_doc_function_lngamma,
"lngamma(x, /) -> mpfr\n\n"
"Return natural logarithm of gamma(x).");
GMPY_MPFR_UNIOP_EXWT(Lngamma, lngamma)
PyDoc_STRVAR(GMPy_doc_context_digamma,
"context.digamma(x, /) -> mpfr\n\n"
"Return digamma of x.");
PyDoc_STRVAR(GMPy_doc_function_digamma,
"digamma(x, /) -> mpfr\n\n"
"Return digamma of x.");
GMPY_MPFR_UNIOP_EXWT(Digamma, digamma)
PyDoc_STRVAR(GMPy_doc_context_zeta,
"context.zeta(x, /) -> mpfr\n\n"
"Return Riemann zeta of x.");
PyDoc_STRVAR(GMPy_doc_function_zeta,
"zeta(x, /) -> mpfr\n\n"
"Return Riemann zeta of x.");
GMPY_MPFR_UNIOP_EXWT(Zeta, zeta)
PyDoc_STRVAR(GMPy_doc_context_erf,
"context.erf(x, /) -> mpfr\n\n"
"Return error function of x.");
PyDoc_STRVAR(GMPy_doc_function_erf,
"erf(x, /) -> mpfr\n\n"
"Return error function of x.");
GMPY_MPFR_UNIOP_EXWT(Erf, erf)
PyDoc_STRVAR(GMPy_doc_context_erfc,
"context.erfc(x, /) -> mpfr\n\n"
"Return complementary error function of x.");
PyDoc_STRVAR(GMPy_doc_function_erfc,
"erfc(x, /) -> mpfr\n\n"
"Return complementary error function of x.");
GMPY_MPFR_UNIOP_EXWT(Erfc, erfc)
PyDoc_STRVAR(GMPy_doc_context_j0,
"context.j0(x, /) -> mpfr\n\n"
"Return first kind Bessel function of order 0 of x.");
PyDoc_STRVAR(GMPy_doc_function_j0,
"j0(x, /) -> mpfr\n\n"
"Return first kind Bessel function of order 0 of x.");
GMPY_MPFR_UNIOP_EXWT(J0, j0)
PyDoc_STRVAR(GMPy_doc_context_j1,
"context.j1(x, /) -> mpfr\n\n"
"Return first kind Bessel function of order 1 of x.");
PyDoc_STRVAR(GMPy_doc_function_j1,
"j1(x, /) -> mpfr\n\n"
"Return first kind Bessel function of order 1 of x.");
GMPY_MPFR_UNIOP_EXWT(J1, j1)
PyDoc_STRVAR(GMPy_doc_context_y0,
"context.y0(x, /) -> mpfr\n\n"
"Return second kind Bessel function of order 0 of x.");
PyDoc_STRVAR(GMPy_doc_function_y0,
"y0(x, /) -> mpfr\n\n"
"Return second kind Bessel function of order 0 of x.");
GMPY_MPFR_UNIOP_EXWT(Y0, y0)
PyDoc_STRVAR(GMPy_doc_context_y1,
"context.y1(x, /) -> mpfr\n\n"
"Return second kind Bessel function of order 1 of x.");
PyDoc_STRVAR(GMPy_doc_function_y1,
"y1(x, /) -> mpfr\n\n"
"Return second kind Bessel function of order 1 of x.");
GMPY_MPFR_UNIOP_EXWT(Y1, y1)
PyDoc_STRVAR(GMPy_doc_context_ai,
"context.ai(x, /) -> mpfr\n\n"
"Return Airy function of x.");
PyDoc_STRVAR(GMPy_doc_function_ai,
"ai(x, /) -> mpfr\n\n"
"Return Airy function of x.");
GMPY_MPFR_UNIOP_EXWT(Ai, ai)
/* Section 3:
* The following functions may return an mpc result for certain mpfr arguments.
* Since the expectional values vary between functions, the 'Real' and 'Complex'
* functions do not use macros. However, they do use a macro to create the
* higher-level functions.
*
* GMPY_MPFR_MPC_UNIOP_TEMPLATE_EXWT(NAME, FUNC) creates the following functions:
* GMPy_Number_NAME(x, context)
* - assumes GMPy_RealWithType_NAME & GMPy_ComplexWithType_NAME exist
* GMPy_Context_NAME(self, other)
* - called with METH_O
*/
PyDoc_STRVAR(GMPy_doc_context_acos,
"context.acos(x, /) -> mpfr | mpc\n\n"
"Return inverse cosine of x; result in radians.");
PyDoc_STRVAR(GMPy_doc_function_acos,
"acos(x, /) -> mpfr | mpc\n\n"
"Return inverse cosine of x; result in radians.");
/* Helper function assumes x is of type mpfr. */
static PyObject *
_GMPy_MPFR_Acos(PyObject *x, CTXT_Object *context)
{
MPFR_Object *result = NULL;
if (!mpfr_nan_p(MPFR(x)) &&
(mpfr_cmp_si(MPFR(x), 1) > 0 || mpfr_cmp_si(MPFR(x), -1) < 0) &&
context->ctx.allow_complex
) {
return GMPy_ComplexWithType_Acos(x, OBJ_TYPE_MPFR, context);
}
if (!(result = GMPy_MPFR_New(0, context))) {
return NULL;
}
mpfr_clear_flags();
result->rc = mpfr_acos(result->f, MPFR(x), GET_MPFR_ROUND(context));
_GMPy_MPFR_Cleanup(&result, context);
return (PyObject*)result;
}
/* Helper function assumes x is of type mpc. */
static PyObject *
_GMPy_MPC_Acos(PyObject *x, CTXT_Object *context)
{
MPC_Object *result = NULL;
if (!(result = GMPy_MPC_New(0, 0, context))) {
return NULL;
}
result->rc = mpc_acos(result->c, MPC(x), GET_MPC_ROUND(context));
_GMPy_MPC_Cleanup(&result, context);
return (PyObject*)result;
}
static PyObject *
GMPy_RealWithType_Acos(PyObject *x, int xtype, CTXT_Object *context)
{
MPFR_Object *tempx = NULL;
PyObject *result = NULL;
if (IS_TYPE_MPFR(xtype)) {
return _GMPy_MPFR_Acos(x, context);
}
else {
if (!(tempx = GMPy_MPFR_From_RealWithType(x, xtype, 1, context))) {
return NULL;
}
result = _GMPy_MPFR_Acos((PyObject*)tempx, context);
Py_DECREF(tempx);
return result;
}
}
static PyObject *
GMPy_ComplexWithType_Acos(PyObject *x, int xtype, CTXT_Object *context)
{
MPC_Object *tempx = NULL;
PyObject *result = NULL;
if (IS_TYPE_MPC(xtype)) {
return _GMPy_MPC_Acos(x, context);
}
else {
if (!(tempx = GMPy_MPC_From_ComplexWithType(x, xtype, 1, 1, context))) {
return NULL;
}
result = _GMPy_MPC_Acos((PyObject*)tempx, context);
Py_DECREF(tempx);
return result;
}
}
GMPY_MPFR_MPC_UNIOP_TEMPLATE_EXWT(Acos, acos)
PyDoc_STRVAR(GMPy_doc_context_asin,
"context.asin(x, /) -> mpfr | mpc\n\n"
"Return inverse sine of x; result in radians.");
PyDoc_STRVAR(GMPy_doc_function_asin,
"asin(x, /) -> mpfr | mpc\n\n"
"Return inverse sine of x; result in radians.");
static PyObject *
_GMPy_MPFR_Asin(PyObject *x, CTXT_Object *context)
{
MPFR_Object *result = NULL;
if (!mpfr_nan_p(MPFR(x)) &&
(mpfr_cmp_si(MPFR(x), 1) > 0 || mpfr_cmp_si(MPFR(x), -1) < 0) &&
context->ctx.allow_complex
) {
return GMPy_ComplexWithType_Asin(x, OBJ_TYPE_MPFR, context);
}
if (!(result = GMPy_MPFR_New(0, context))) {
return NULL;
}
mpfr_clear_flags();
result->rc = mpfr_asin(result->f, MPFR(x), GET_MPFR_ROUND(context));
_GMPy_MPFR_Cleanup(&result, context);
return (PyObject*)result;
}
static PyObject *
_GMPy_MPC_Asin(PyObject *x, CTXT_Object *context)
{
MPC_Object *result = NULL;
if (!(result = GMPy_MPC_New(0, 0, context))) {
return NULL;
}
result->rc = mpc_asin(result->c, MPC(x), GET_MPC_ROUND(context));
_GMPy_MPC_Cleanup(&result, context);
return (PyObject*)result;
}
static PyObject *
GMPy_RealWithType_Asin(PyObject *x, int xtype, CTXT_Object *context)
{
MPFR_Object *tempx = NULL;
PyObject *result = NULL;
if (IS_TYPE_MPFR(xtype)) {
return _GMPy_MPFR_Asin(x, context);
}
else {
if (!(tempx = GMPy_MPFR_From_RealWithType(x, xtype, 1, context))) {
return NULL;
}
result = _GMPy_MPFR_Asin((PyObject*)tempx, context);
Py_DECREF(tempx);
return result;
}
}
static PyObject *
GMPy_ComplexWithType_Asin(PyObject *x, int xtype, CTXT_Object *context)
{
MPC_Object *tempx = NULL;
PyObject *result = NULL;
if (IS_TYPE_MPC(xtype)) {
return _GMPy_MPC_Asin(x, context);
}
else {
if (!(tempx = GMPy_MPC_From_ComplexWithType(x, xtype, 1, 1, context))) {
return NULL;
}
result = _GMPy_MPC_Asin((PyObject*)tempx, context);
Py_DECREF(tempx);
return result;
}
}
GMPY_MPFR_MPC_UNIOP_TEMPLATE_EXWT(Asin, asin)
PyDoc_STRVAR(GMPy_doc_context_atanh,
"context.atanh(x, /) -> mpfr | mpc\n\n"
"Return inverse hyperbolic tanget of x.");
PyDoc_STRVAR(GMPy_doc_function_atanh,
"atanh(x, /) -> mpfr | mpc\n\n"
"Return inverse hyperbolic tangent of x.");
static PyObject *
_GMPy_MPFR_Atanh(PyObject *x, CTXT_Object *context)
{
MPFR_Object *result = NULL;
if (!mpfr_nan_p(MPFR(x)) &&
(mpfr_cmp_si(MPFR(x), 1) > 0 || mpfr_cmp_si(MPFR(x), -1) < 0) &&
context->ctx.allow_complex
) {
return GMPy_ComplexWithType_Atanh(x, OBJ_TYPE_MPFR, context);
}
if (!(result = GMPy_MPFR_New(0, context))) {
return NULL;
}
mpfr_clear_flags();
result->rc = mpfr_atanh(result->f, MPFR(x), GET_MPFR_ROUND(context));
_GMPy_MPFR_Cleanup(&result, context);
return (PyObject*)result;
}
static PyObject *
_GMPy_MPC_Atanh(PyObject *x, CTXT_Object *context)
{
MPC_Object *result = NULL;
if (!(result = GMPy_MPC_New(0, 0, context))) {
return NULL;
}
result->rc = mpc_atanh(result->c, MPC(x), GET_MPC_ROUND(context));
_GMPy_MPC_Cleanup(&result, context);
return (PyObject*)result;
}
static PyObject *
GMPy_RealWithType_Atanh(PyObject *x, int xtype, CTXT_Object *context)
{
MPFR_Object *tempx = NULL;
PyObject *result = NULL;
if (IS_TYPE_MPFR(xtype)) {
return _GMPy_MPFR_Atanh(x, context);
}
else {
if (!(tempx = GMPy_MPFR_From_RealWithType(x, xtype, 1, context))) {
return NULL;
}
result = _GMPy_MPFR_Atanh((PyObject*)tempx, context);
Py_DECREF(tempx);
return result;
}
}
static PyObject *
GMPy_ComplexWithType_Atanh(PyObject *x, int xtype, CTXT_Object *context)
{
MPC_Object *tempx = NULL;
PyObject *result = NULL;
if (IS_TYPE_MPC(xtype)) {
return _GMPy_MPC_Atanh(x, context);
}
else {
if (!(tempx = GMPy_MPC_From_ComplexWithType(x, xtype, 1, 1, context))) {
return NULL;
}
result = _GMPy_MPC_Atanh((PyObject*)tempx, context);
Py_DECREF(tempx);
return result;
}
}
GMPY_MPFR_MPC_UNIOP_TEMPLATE_EXWT(Atanh, atanh)
PyDoc_STRVAR(GMPy_doc_function_atan2,
"atan2(y, x, /) -> mpfr\n\n"
"Return arc-tangent of (y/x); result in radians.");
PyDoc_STRVAR(GMPy_doc_context_atan2,
"context.atan2(y, x, /) -> mpfr\n\n"
"Return arc-tangent of (y/x); result in radians.");
GMPY_MPFR_BINOP_EXWT(Atan2, atan2)
PyDoc_STRVAR(GMPy_doc_function_hypot,
"hypot(x, y, /) -> mpfr\n\n"
"Return square root of (x**2 + y**2).");
PyDoc_STRVAR(GMPy_doc_context_hypot,
"context.hypot(x, y, /) -> mpfr\n\n"
"Return square root of (x**2 + y**2).");
GMPY_MPFR_BINOP_EXWT(Hypot, hypot)
static PyObject *
GMPy_RealWithType_Sin_Cos(PyObject *x, int xtype, CTXT_Object *context)
{
MPFR_Object *s = NULL, *c = NULL, *tempx = NULL;
PyObject *result = NULL;
int code;
s = GMPy_MPFR_New(0, context);
c = GMPy_MPFR_New(0, context);
tempx = GMPy_MPFR_From_RealWithType(x, xtype, 1, context);
result = PyTuple_New(2);
if (!s || !c || !tempx || !result) {
Py_XDECREF(s);
Py_XDECREF(c);
Py_XDECREF(tempx);
Py_XDECREF(result);
return NULL;
}
mpfr_clear_flags();
code = mpfr_sin_cos(s->f, c->f, tempx->f, GET_MPFR_ROUND(context));
Py_DECREF(tempx);
s->rc = code & 0x03;
c->rc = code >> 2;
if (s->rc == 2) s->rc = -1;
if (c->rc == 2) c->rc = -1;
_GMPy_MPFR_Cleanup(&s, context);
_GMPy_MPFR_Cleanup(&c, context);
if (!s || !c) {
Py_XDECREF((PyObject*)s);
Py_XDECREF((PyObject*)c);
Py_DECREF(result);
return NULL;
}
PyTuple_SET_ITEM(result, 0, (PyObject*)s);
PyTuple_SET_ITEM(result, 1, (PyObject*)c);
return result;
}
static PyObject *
_GMPy_MPC_Sin_Cos(PyObject *x, CTXT_Object *context)
{
MPC_Object *s = NULL, *c = NULL;
PyObject *result = NULL;
int code;
s = GMPy_MPC_New(0, 0, context);
c = GMPy_MPC_New(0, 0, context);
result = PyTuple_New(2);
if (!s || !c || !result) {
Py_XDECREF((PyObject*)s);
Py_XDECREF((PyObject*)c);
Py_XDECREF(result);
return NULL;
}
code = mpc_sin_cos(s->c, c->c, MPC(x), GET_MPC_ROUND(context), GET_MPC_ROUND(context));
s->rc = MPC_INEX1(code);
c->rc = MPC_INEX2(code);
_GMPy_MPC_Cleanup(&s, context);
_GMPy_MPC_Cleanup(&c, context);
if (!s || !c) {
Py_XDECREF((PyObject*)s);
Py_XDECREF((PyObject*)c);
Py_XDECREF(result);
return NULL;
}
PyTuple_SET_ITEM(result, 0, (PyObject*)s);
PyTuple_SET_ITEM(result, 1, (PyObject*)c);
return result;
}
static PyObject *
GMPy_ComplexWithType_Sin_Cos(PyObject *x, int xtype, CTXT_Object *context)
{
PyObject *result, *tempx;
if (!(tempx = (PyObject*)GMPy_MPC_From_ComplexWithType(x, xtype, 1, 1, context))) {
return NULL;
}
result = _GMPy_MPC_Sin_Cos(tempx, context);
Py_DECREF(tempx);
return result;
}
PyDoc_STRVAR(GMPy_doc_context_sin_cos,
"context.sin_cos(x, /) -> tuple[mpfr|mpc, mpfr|mpc]\n\n"
"Return a tuple containing the sine and cosine of x; x in radians.");
PyDoc_STRVAR(GMPy_doc_function_sin_cos,
"sin_cos(x, /) -> tuple[mpfr|mpc, mpfr|mpc]\n\n"
"Return a tuple containing the sine and cosine of x; x in radians.");
GMPY_MPFR_MPC_UNIOP_TEMPLATE_EXWT(Sin_Cos, sin_cos)
static PyObject *
GMPy_RealWithType_Sinh_Cosh(PyObject *x, int xtype, CTXT_Object *context)
{
MPFR_Object *s = NULL, *c = NULL, *tempx = NULL;
PyObject *result = NULL;
int code;
s = GMPy_MPFR_New(0, context);
c = GMPy_MPFR_New(0, context);
tempx = GMPy_MPFR_From_RealWithType(x, xtype, 1, context);
result = PyTuple_New(2);
if (!s || !c || !tempx || !result) {
Py_XDECREF((PyObject*)s);
Py_XDECREF((PyObject*)c);
Py_XDECREF(result);
return NULL;
}
mpfr_clear_flags();
code = mpfr_sinh_cosh(s->f, c->f, tempx->f, GET_MPFR_ROUND(context));
Py_DECREF(tempx);
s->rc = code & 0x03;
c->rc = code >> 2;
if (s->rc == 2) s->rc = -1;
if (c->rc == 2) c->rc = -1;
_GMPy_MPFR_Cleanup(&s, context);
_GMPy_MPFR_Cleanup(&c, context);
if (!s || !c) {
Py_XDECREF((PyObject*)s);
Py_XDECREF((PyObject*)c);
Py_DECREF(result);
return NULL;
}
PyTuple_SET_ITEM(result, 0, (PyObject*)s);
PyTuple_SET_ITEM(result, 1, (PyObject*)c);
return result;
}
PyDoc_STRVAR(GMPy_doc_context_sinh_cosh,
"context.sinh_cosh(x, /) -> tuple[mpfr, mpfr]\n\n"
"Return a `tuple` containing the hyperbolic sine and cosine of x.");
PyDoc_STRVAR(GMPy_doc_function_sinh_cosh,
"sinh_cosh(x, /) -> tuple[mpfr, mpfr]\n\n"
"Return a `tuple` containing the hyperbolic sine and cosine of x.");
GMPY_MPFR_UNIOP_TEMPLATEWT(Sinh_Cosh, sinh_cosh)
PyDoc_STRVAR(GMPy_doc_function_degrees,
"degrees(x, /) -> mpfr\n\n"
"Convert angle x from radians to degrees.\n"
"Note: In rare cases the result may not be correctly rounded.");
PyDoc_STRVAR(GMPy_doc_context_degrees,
"context.degrees(x, /) -> mpfr\n\n"
"Convert angle x from radians to degrees.\n"
"Note: In rare cases the result may not be correctly rounded.");
static PyObject *
GMPy_Context_Degrees(PyObject *self, PyObject *other)
{
MPFR_Object *result, *tempx, *temp;
CTXT_Object *context = NULL;
if (self && CTXT_Check(self)) {
context = (CTXT_Object*)self;
}
else {
CHECK_CONTEXT(context);
}
result = GMPy_MPFR_New(0, context);
temp = GMPy_MPFR_New(context->ctx.mpfr_prec + 100, context);
tempx = GMPy_MPFR_From_Real(other, 1, context);
if (!result || !temp || !tempx) {
Py_XDECREF((PyObject*)temp);
Py_XDECREF((PyObject*)tempx);
Py_XDECREF((PyObject*)result);
return NULL;
}
mpfr_const_pi(temp->f, MPFR_RNDN);
mpfr_ui_div(temp->f, 180, temp->f, MPFR_RNDN);
mpfr_clear_flags();
mpfr_mul(result->f, temp->f, tempx->f, MPFR_RNDN);
Py_DECREF((PyObject*)temp);
Py_DECREF((PyObject*)tempx);
_GMPy_MPFR_Cleanup(&result, context);
return (PyObject*)result;
}
PyDoc_STRVAR(GMPy_doc_function_radians,
"radians(x, /) -> mpfr\n\n"
"Convert angle x from degrees to radians.\n"
"Note: In rare cases the result may not be correctly rounded.");
PyDoc_STRVAR(GMPy_doc_context_radians,
"context.radians(x, /) -> mpfr\n\n"
"Convert angle x from degrees to radians.\n"
"Note: In rare cases the result may not be correctly rounded.");
static PyObject *
GMPy_Context_Radians(PyObject *self, PyObject *other)
{
MPFR_Object *result, *tempx, *temp;
CTXT_Object *context = NULL;
if (self && CTXT_Check(self)) {
context = (CTXT_Object*)self;
}
else {
CHECK_CONTEXT(context);
}
result = GMPy_MPFR_New(0, context);
temp = GMPy_MPFR_New(context->ctx.mpfr_prec + 100, context);
tempx = GMPy_MPFR_From_Real(other, 1, context);
if (!result || !temp || !tempx) {
Py_XDECREF((PyObject*)temp);
Py_XDECREF((PyObject*)tempx);
Py_XDECREF((PyObject*)result);
return NULL;
}
mpfr_const_pi(temp->f, MPFR_RNDN);
mpfr_div_ui(temp->f, temp->f, 180, MPFR_RNDN);
mpfr_clear_flags();
mpfr_mul(result->f, tempx->f, temp->f, MPFR_RNDN);
Py_DECREF((PyObject*)temp);
Py_DECREF((PyObject*)tempx);
_GMPy_MPFR_Cleanup(&result, context);
return (PyObject*)result;
}
PyDoc_STRVAR(GMPy_doc_context_log10,
"context.log10(x, /) -> mpfr | mpc\n\n"
"Return the base-10 logarithm of x.");
PyDoc_STRVAR(GMPy_doc_function_log10,
"log10(x, /) -> mpfr | mpc\n\n"
"Return the base-10 logarithm of x.");
GMPY_MPFR_MPC_UNIOP_EXWT(Log10, log10)
PyDoc_STRVAR(GMPy_doc_context_log,
"context.log(x, /) -> mpfr | mpc\n\n"
"Return the natural logarithm of x.");
PyDoc_STRVAR(GMPy_doc_function_log,
"log(x, /) -> mpfr | mpc\n\n"
"Return the natural logarithm of x.");
GMPY_MPFR_MPC_UNIOP_EXWT(Log, log)
PyDoc_STRVAR(GMPy_doc_context_exp,
"context.exp(x, /) -> mpfr | mpc\n\n"
"Return the exponential of x.");
PyDoc_STRVAR(GMPy_doc_function_exp,
"exp(x, /) -> mpfr | mpc\n\n"
"Return the exponential of x.");
GMPY_MPFR_MPC_UNIOP_EXWT(Exp, exp)
PyDoc_STRVAR(GMPy_doc_context_sqrt,
"context.sqrt(x, /) -> mpfr | mpc\n\n"
"Return the square root of x.");
PyDoc_STRVAR(GMPy_doc_function_sqrt,
"sqrt(x, /) -> mpfr | mpc\n\n"
"Return the square root of x.");
static PyObject *
GMPy_RealWithType_Sqrt(PyObject *x, int xtype, CTXT_Object *context)
{
MPFR_Object *result = NULL;
CHECK_CONTEXT(context);
if (IS_TYPE_MPFR(xtype)) {
if (mpfr_sgn(MPFR(x)) < 0 && context->ctx.allow_complex) {
return GMPy_ComplexWithType_Sqrt(x, xtype, context);
}
if (!(result = GMPy_MPFR_New(0, context))) {
return NULL;
}
mpfr_clear_flags();
result->rc = mpfr_sqrt(result->f, MPFR(x), GET_MPFR_ROUND(context));
_GMPy_MPFR_Cleanup(&result, context);
return (PyObject*)result;
}
if (IS_TYPE_REAL(xtype)) {
MPFR_Object *tempx = NULL;
if (!(tempx = GMPy_MPFR_From_RealWithType(x, xtype, 1, context))) {
return NULL;
}
if (mpfr_sgn(MPFR(tempx)) < 0 && context->ctx.allow_complex) {
PyObject *res = NULL;
res = GMPy_ComplexWithType_Sqrt((PyObject*)tempx, OBJ_TYPE_MPFR, context);
Py_DECREF(tempx);
return res;
}
if (!(result = GMPy_MPFR_New(0, context))) {
Py_DECREF((PyObject*)tempx);
return NULL;
}
mpfr_clear_flags();
result->rc = mpfr_sqrt(result->f, MPFR(tempx), GET_MPFR_ROUND(context));
Py_DECREF((PyObject*)tempx);
_GMPy_MPFR_Cleanup(&result, context);
return (PyObject*)result;
}
TYPE_ERROR("sqrt() argument type not supported");
return NULL;
}
static PyObject *
GMPy_ComplexWithType_Sqrt(PyObject *x, int xtype, CTXT_Object *context)
{
MPC_Object *result = NULL;
CHECK_CONTEXT(context);
if (!(result = GMPy_MPC_New(0, 0, context))) {
return NULL;
}
if (IS_TYPE_MPC(xtype)) {
result->rc = mpc_sqrt(result->c, MPC(x), GET_MPFR_ROUND(context));
_GMPy_MPC_Cleanup(&result, context);
return (PyObject*)result;
}
if (IS_TYPE_COMPLEX(xtype)) {
MPC_Object *tempx = NULL;
if (!(tempx = GMPy_MPC_From_ComplexWithType(x, xtype, 1, 1, context))) {
Py_DECREF(result);
return NULL;
}
result->rc = mpc_sqrt(result->c, MPC(tempx), GET_MPFR_ROUND(context));
Py_DECREF(tempx);
_GMPy_MPC_Cleanup(&result, context);
return (PyObject*)result;
}
TYPE_ERROR("sqrt() argument type not supported");
return NULL;
}
GMPY_MPFR_MPC_UNIOP_TEMPLATE_EXWT(Sqrt, sqrt)
PyDoc_STRVAR(GMPy_doc_function_root,
"root(x, n, /) -> mpfr\n\n"
"Return n-th root of x. The result always an `mpfr`.\n"
"Note: not IEEE 754-2008 compliant; result differs when\n"
"x = -0 and n is even. See `rootn()`.");
PyDoc_STRVAR(GMPy_doc_context_root,
"context.root(x, n, /) -> mpfr\n\n"
"Return n-th root of x. The result always an `mpfr`.\n"
"Note: not IEEE 754-2008 compliant; result differs when\n"
"x = -0 and n is even. See `context.rootn()`.");
PyDoc_STRVAR(GMPy_doc_function_rootn,
"rootn(x, n, /) -> mpfr\n\n"
"Return n-th root of x. The result always an `mpfr`.\n"
"Note: this is IEEE 754-2008 compliant version of `root()`.");
PyDoc_STRVAR(GMPy_doc_context_rootn,
"context.rootn(x, n, /) -> mpfr\n\n"
"Return n-th root of x. The result always an `mpfr`.\n"
"Note: this is IEEE 754-2008 compliant version of `context.root()`.");
#if MPFR_VERSION_MAJOR > 3
/* Since mpfr_root is deprecated in MPFR 4, we use mpfr_rootn_ui to
* mimic the behavior of mpfr_root. And the converse will be true when
* using MPFR 3.
*/
static PyObject *
GMPy_Real_Rootn(PyObject *x, PyObject *y, CTXT_Object *context)
{
MPFR_Object *result = NULL, *tempx = NULL;
unsigned long n;
CHECK_CONTEXT(context);
result = GMPy_MPFR_New(0, context);
tempx = GMPy_MPFR_From_Real(x, 1, context);
n = GMPy_Integer_AsUnsignedLong(y);
if (!result || !tempx || (n == (unsigned long)(-1) && PyErr_Occurred())) {
Py_XDECREF((PyObject*)tempx);
Py_XDECREF((PyObject*)result);
return NULL;
}
mpfr_clear_flags();
result->rc = mpfr_rootn_ui(result->f, tempx->f, n, GET_MPFR_ROUND(context));
Py_DECREF((PyObject*)tempx);
_GMPy_MPFR_Cleanup(&result, context);
return (PyObject*)result;
}
static PyObject *
GMPy_Real_Root(PyObject *x, PyObject *y, CTXT_Object *context)
{
MPFR_Object *result = NULL, *tempx = NULL;
unsigned long n;
CHECK_CONTEXT(context);
result = GMPy_MPFR_New(0, context);
tempx = GMPy_MPFR_From_Real(x, 1, context);
n = GMPy_Integer_AsUnsignedLong(y);
if (!result || !tempx || (n == (unsigned long)(-1) && PyErr_Occurred())) {
Py_XDECREF((PyObject*)tempx);
Py_XDECREF((PyObject*)result);
return NULL;
}
mpfr_clear_flags();
/* Mimic the non-compliant IEEE 752-2008 behavior. */
if (mpfr_zero_p(tempx->f)) {
mpfr_set(result->f, tempx->f, GET_MPFR_ROUND(context));
}
else {
result->rc = mpfr_rootn_ui(result->f, tempx->f, n, GET_MPFR_ROUND(context));
}
Py_DECREF((PyObject*)tempx);
_GMPy_MPFR_Cleanup(&result, context);
return (PyObject*)result;
}
#else
static PyObject *
GMPy_Real_Rootn(PyObject *x, PyObject *y, CTXT_Object *context)
{
MPFR_Object *result = NULL, *tempx = NULL;
unsigned long n;
CHECK_CONTEXT(context);
result = GMPy_MPFR_New(0, context);
tempx = GMPy_MPFR_From_Real(x, 1, context);
n = GMPy_Integer_AsUnsignedLong(y);
if (!result || !tempx || (n == (unsigned long)(-1) && PyErr_Occurred())) {
Py_XDECREF((PyObject*)tempx);
Py_XDECREF((PyObject*)result);
return NULL;
}
mpfr_clear_flags();
/* Mimic the compliant IEEE 752-2008 behavior. */
if (mpfr_zero_p(tempx->f) && mpfr_signbit(tempx->f)) {
if ((n & 1)) {
/* Odd, so result is -0. */
mpfr_set_zero(result->f, -1);
}
else {
/* Even, so result is 0. */
mpfr_set_zero(result->f, 1);
}
}
else {
result->rc = mpfr_root(result->f, tempx->f, n, GET_MPFR_ROUND(context));
}
Py_DECREF((PyObject*)tempx);
_GMPy_MPFR_Cleanup(&result, context);
return (PyObject*)result;
}
static PyObject *
GMPy_Real_Root(PyObject *x, PyObject *y, CTXT_Object *context)
{
MPFR_Object *result = NULL, *tempx = NULL;
unsigned long n;
CHECK_CONTEXT(context);
result = GMPy_MPFR_New(0, context);
tempx = GMPy_MPFR_From_Real(x, 1, context);
n = GMPy_Integer_AsUnsignedLong(y);
if (!result || !tempx || (n == (unsigned long)(-1) && PyErr_Occurred())) {
Py_XDECREF((PyObject*)tempx);
Py_XDECREF((PyObject*)result);
return NULL;
}
mpfr_clear_flags();
result->rc = mpfr_root(result->f, tempx->f, n, GET_MPFR_ROUND(context));
Py_DECREF((PyObject*)tempx);
_GMPy_MPFR_Cleanup(&result, context);
return (PyObject*)result;
}
#endif
static PyObject *
GMPy_Number_Rootn(PyObject *x, PyObject *y, CTXT_Object *context)
{
if (IS_REAL(x) && PyLong_Check(y))
return GMPy_Real_Rootn(x, y, context);
TYPE_ERROR("rootn() argument type not supported");
return NULL;
}
static PyObject *
GMPy_Context_Rootn(PyObject *self, PyObject *args)
{
CTXT_Object *context = NULL;
if (PyTuple_GET_SIZE(args) != 2) {
TYPE_ERROR("rootn() requires 2 arguments");
return NULL;
}
if (self && CTXT_Check(self)) {
context = (CTXT_Object*)self;
}
else {
CHECK_CONTEXT(context);
}
return GMPy_Number_Rootn(PyTuple_GET_ITEM(args, 0), PyTuple_GET_ITEM(args, 1), context);
}
static PyObject *
GMPy_Number_Root(PyObject *x, PyObject *y, CTXT_Object *context)
{
if (IS_REAL(x) && PyLong_Check(y))
return GMPy_Real_Root(x, y, context);
TYPE_ERROR("root() argument type not supported");
return NULL;
}
static PyObject *
GMPy_Context_Root(PyObject *self, PyObject *args)
{
CTXT_Object *context = NULL;
if (PyTuple_GET_SIZE(args) != 2) {
TYPE_ERROR("root() requires 2 arguments");
return NULL;
}
if (self && CTXT_Check(self)) {
context = (CTXT_Object*)self;
}
else {
CHECK_CONTEXT(context);
}
return GMPy_Number_Root(PyTuple_GET_ITEM(args, 0), PyTuple_GET_ITEM(args, 1), context);
}
PyDoc_STRVAR(GMPy_doc_function_jn,
"jn(n,x, /) -> mpfr\n\n"
"Return the first kind Bessel function of order n of x.\n"
"Note: the order of the arguments changed in gmpy2 2.2.0a2");
PyDoc_STRVAR(GMPy_doc_context_jn,
"context.jn(n,x, /) -> mpfr\n\n"
"Return the first kind Bessel function of order n of x.\n"
"Note: the order of the arguments changed in gmpy2 2.2.0a2");
GMPY_MPFR_BINOP_LONG_REALWT(Jn, jn)
PyDoc_STRVAR(GMPy_doc_function_yn,
"yn(n,x, /) -> mpfr\n\n"
"Return the second kind Bessel function of order n of x.\n"
"Note: the order of the arguments changed in gmpy2 2.2.0a2");
PyDoc_STRVAR(GMPy_doc_context_yn,
"context.yn(n,x, /) -> mpfr\n\n"
"Return the second kind Bessel function of order n of x.\n"
"Note: the order of the arguments changed in gmpy2 2.2.0a2");
GMPY_MPFR_BINOP_LONG_REALWT(Yn, yn)
PyDoc_STRVAR(GMPy_doc_function_agm,
"agm(x, y, /) -> mpfr\n\n"
"Return arithmetic-geometric mean of x and y.");
PyDoc_STRVAR(GMPy_doc_context_agm,
"context.agm(x, y, /) -> mpfr\n\n"
"Return arithmetic-geometric mean of x and y.");
GMPY_MPFR_BINOPWT(AGM, agm)
PyDoc_STRVAR(GMPy_doc_function_maxnum,
"maxnum(x, y, /) -> mpfr\n\n"
"Return the maximum number of x and y. If x and y are not `mpfr`, they are\n"
"converted to `mpfr`. The result is rounded to match the current context.\n"
"If only one of x or y is a number, then that number is returned.");
PyDoc_STRVAR(GMPy_doc_context_maxnum,
"context.maxnum(x, y, /) -> mpfr\n\n"
"Return the maximum number of x and y. If x and y are not `mpfr`, they are\n"
"converted to `mpfr`. The result is rounded to match the specified context.\n"
"If only one of x or y is a number, then that number is returned.");
GMPY_MPFR_BINOPWT(Maxnum, max)
PyDoc_STRVAR(GMPy_doc_function_minnum,
"minnum(x, y, /) -> mpfr\n\n"
"Return the minimum number of x and y. If x and y are not `mpfr`, they are\n"
"converted to `mpfr`. The result is rounded to match the current context.\n"
"If only one of x or y is a number, then that number is returned.");
PyDoc_STRVAR(GMPy_doc_context_minnum,
"context.minnum(x, y, /) -> mpfr\n\n"
"Return the minimum number of x and y. If x and y are not `mpfr`, they are\n"
"converted to `mpfr`. The result is rounded to match the specified context.\n"
"If only one of x or y is a number, then that number is returned.");
GMPY_MPFR_BINOPWT(Minnum, min)
PyDoc_STRVAR(GMPy_doc_function_remainder,
"remainder(x, y, /) -> mpfr\n\n"
"Return x - n*y where n is the integer quotient of x/y, rounded to\n"
"the nearest integer and ties rounded to even.");
PyDoc_STRVAR(GMPy_doc_context_remainder,
"context.remainder(x, y, /) -> mpfr\n\n"
"Return x - n*y where n is the integer quotient of x/y, rounded to\n"
"the nearest integer and ties rounded to even.");
GMPY_MPFR_BINOPWT(Remainder, remainder)
PyDoc_STRVAR(GMPy_doc_function_fmod,
"fmod(x, y, /) -> mpfr\n\n"
"Return x - n*y where n is the integer quotient of x/y, rounded to 0.");
PyDoc_STRVAR(GMPy_doc_context_fmod,
"context.fmod(x, y, /) -> mpfr\n\n"
"Return x - n*y where n is the integer quotient of x/y, rounded to 0.");
GMPY_MPFR_BINOPWT(Fmod, fmod)
PyDoc_STRVAR(GMPy_doc_function_round2,
"round2(x, n=0, /) -> mpfr\n\n"
"Return x rounded to n bits. Uses default precision if n is not specified.\n"
"See `round_away()` to access the mpfr_round() function of the MPFR.");
PyDoc_STRVAR(GMPy_doc_context_round2,
"context.round2(x, n=0, /) -> mpfr\n\n"
"Return x rounded to n bits. Uses default precision if n is not specified.\n"
"See `context.round_away()` to access the mpfr_round() function of the MPFR.");
static PyObject *
GMPy_Real_Round2(PyObject *x, PyObject *y, CTXT_Object *context)
{
MPFR_Object *result, *tempx;
long n = 0;
CHECK_CONTEXT(context);
if (y) {
n = PyLong_AsLong(y);
if (n && ((n == -1 && PyErr_Occurred()) || n < MPFR_PREC_MIN || n > MPFR_PREC_MAX)) {
VALUE_ERROR("invalid precision");
return NULL;
}
}
if (!n) {
n = GET_MPFR_PREC(context);
}
if (!(tempx = GMPy_MPFR_From_Real(x, 1, context))) {
return NULL;
}
if (!(result = GMPy_MPFR_New(mpfr_get_prec(tempx->f), context))) {
Py_DECREF((PyObject*)tempx);
return NULL;
}
mpfr_set(result->f, tempx->f, GET_MPFR_ROUND(context));
Py_DECREF((PyObject*)tempx);
mpfr_clear_flags();
result->rc = mpfr_prec_round(result->f, n, GET_MPFR_ROUND(context));
_GMPy_MPFR_Cleanup(&result, context);
return (PyObject*)result;
}
static PyObject *
GMPy_Number_Round2(PyObject *x, PyObject *y, CTXT_Object *context)
{
if (IS_REAL(x) && (!y || PyLong_Check(y)))
return GMPy_Real_Round2(x, y, context);
TYPE_ERROR("round2() argument type not supported");
return NULL;
}
static PyObject *
GMPy_Context_Round2(PyObject *self, PyObject *args)
{
CTXT_Object *context = NULL;
if (PyTuple_GET_SIZE(args) < 1 || PyTuple_GET_SIZE(args) > 2) {
TYPE_ERROR("round2() requires 1 or 2 arguments");
return NULL;
}
if (self && CTXT_Check(self)) {
context = (CTXT_Object*)self;
}
else {
CHECK_CONTEXT(context);
}
if (PyTuple_GET_SIZE(args) == 1) {
return GMPy_Number_Round2(PyTuple_GET_ITEM(args, 0), NULL, context);
}
else {
return GMPy_Number_Round2(PyTuple_GET_ITEM(args, 0), PyTuple_GET_ITEM(args, 1), context);
}
}
PyDoc_STRVAR(GMPy_doc_function_reldiff,
"reldiff(x, y, /) -> mpfr\n\n"
"Return the relative difference between x and y. Result is equal to\n"
"abs(x-y)/x.");
PyDoc_STRVAR(GMPy_doc_context_reldiff,
"context.reldiff(x, y, /) -> mpfr\n\n"
"Return the relative difference between x and y. Result is equal to\n"
"abs(x-y)/x.");
static PyObject *
GMPy_RealWithType_RelDiff(PyObject *x, int xtype, PyObject *y, int ytype, CTXT_Object *context)
{
MPFR_Object *tempx = NULL, *tempy = NULL, *result = NULL;
CHECK_CONTEXT(context);
result = GMPy_MPFR_New(0, context);
tempx = GMPy_MPFR_From_RealWithType(x, xtype, 1, context);
tempy = GMPy_MPFR_From_RealWithType(y, ytype, 1, context);
if (!result || !tempx || !tempy) {
Py_XDECREF((PyObject*)result);
Py_XDECREF((PyObject*)tempx);
Py_XDECREF((PyObject*)tempy);
return NULL;
}
mpfr_clear_flags();
mpfr_reldiff(result->f, tempx->f, tempy->f, GET_MPFR_ROUND(context));
result->rc = 0;
_GMPy_MPFR_Cleanup(&result, context);
Py_DECREF((PyObject*)tempx);
Py_DECREF((PyObject*)tempy);
return (PyObject*)result;
}
GMPY_MPFR_BINOP_TEMPLATEWT(RelDiff, reldiff)
PyDoc_STRVAR(GMPy_doc_mpfr_ceil_method,
"x.__ceil__() -> mpfr\n\n"
"Return an 'mpfr' that is the smallest integer >= x.");
PyDoc_STRVAR(GMPy_doc_function_ceil,
"ceil(x, /) -> mpfr\n\n"
"Return an 'mpfr' that is the smallest integer >= x.");
PyDoc_STRVAR(GMPy_doc_context_ceil,
"context.ceil(x, /) ->mpfr\n\n"
"Return an `mpfr` that is the smallest integer >= x.");
GMPY_MPFR_UNIOP_NOROUNDWT(Ceil, ceil)
PyDoc_STRVAR(GMPy_doc_mpfr_floor_method,
"x.__floor__() -> mpfr\n\n"
"Return an 'mpfr' that is the largest integer <= x.");
PyDoc_STRVAR(GMPy_doc_function_floor,
"floor(x, /) -> mpfr\n\n"
"Return an `mpfr` that is the largest integer <= x.");
PyDoc_STRVAR(GMPy_doc_context_floor,
"context.floor(x, /) -> mpfr\n\n"
"Return an `mpfr` that is the largest integer <= x.");
GMPY_MPFR_UNIOP_NOROUNDWT(Floor, floor);
PyDoc_STRVAR(GMPy_doc_mpfr_trunc_method,
"x.__trunc__() -> mpfr\n\n"
"Return an 'mpfr' that is truncated towards 0. Same as\n"
"x.floor() if x>=0 or x.ceil() if x<0.");
PyDoc_STRVAR(GMPy_doc_function_trunc,
"trunc(x, /) -> mpfr\n\n"
"Return an `mpfr` that is x truncated towards 0. Same as\n"
"x.floor() if x>=0 or x.ceil() if x<0.");
PyDoc_STRVAR(GMPy_doc_context_trunc,
"context.trunc(x, /) -> mpfr\n\n"
"Return an `mpfr` that is x truncated towards 0. Same as\n"
"x.floor() if x>=0 or x.ceil() if x<0.");
GMPY_MPFR_UNIOP_NOROUNDWT(Trunc, trunc)
PyDoc_STRVAR(GMPy_doc_function_round_away,
"round_away(x, /) -> mpfr\n\n"
"Return an `mpfr` that is x rounded to the nearest integer,\n"
"with ties rounded away from 0.");
PyDoc_STRVAR(GMPy_doc_context_round_away,
"context.round_away(x, /) -> mpfr\n\n"
"Return an `mpfr` that is x rounded to the nearest integer,\n"
"with ties rounded away from 0.");
GMPY_MPFR_UNIOP_NOROUND_NOMETHODWT(RoundAway, round)
PyDoc_STRVAR(GMPy_doc_function_modf,
"modf(x, /) -> tuple[mpfr, mpfr]\n\n"
"Return a `tuple` containing the integer and fractional portions\n"
"of x.");
PyDoc_STRVAR(GMPy_doc_context_modf,
"context.modf(x, /) -> tuple[mpfr, mpfr]\n\n"
"Return a `tuple` containing the integer and fractional portions\n"
"of x.");
static PyObject *
GMPy_RealWithType_Modf(PyObject *x, int xtype, CTXT_Object *context)
{
MPFR_Object *s = NULL, *c = NULL, *tempx = NULL;
PyObject *result = NULL;
int code;
tempx = GMPy_MPFR_From_RealWithType(x, xtype, 1, context);
s = GMPy_MPFR_New(0, context);
c = GMPy_MPFR_New(0, context);
result = PyTuple_New(2);
if (! tempx || !s || !c || !result) {
Py_XDECREF((PyObject*)tempx);
Py_XDECREF((PyObject*)s);
Py_XDECREF((PyObject*)c);
Py_XDECREF(result);
return NULL;
}
mpfr_clear_flags();
code = mpfr_modf(s->f, c->f, tempx->f, GET_MPFR_ROUND(context));
Py_DECREF((PyObject*)tempx);
s->rc = code & 0x03;
c->rc = code >> 2;
if (s->rc == 2) s->rc = -1;
if (c->rc == 2) c->rc = -1;
_GMPy_MPFR_Cleanup(&s, context);
_GMPy_MPFR_Cleanup(&c, context);
if (!s || !c) {
Py_XDECREF((PyObject*)s);
Py_XDECREF((PyObject*)c);
Py_DECREF(result);
return NULL;
}
PyTuple_SET_ITEM(result, 0, (PyObject*)s);
PyTuple_SET_ITEM(result, 1, (PyObject*)c);
return result;
}
GMPY_MPFR_UNIOP_TEMPLATEWT(Modf, modf)
PyDoc_STRVAR(GMPy_doc_function_lgamma,
"lgamma(x, /) -> tuple[mpfr, int]\n\n"
"Return a `tuple` containing the logarithm of the absolute value of\n"
"gamma(x) and the sign of gamma(x)");
PyDoc_STRVAR(GMPy_doc_context_lgamma,
"context.lgamma(x, /) -> tuple[mpfr, int]\n\n"
"Return a `tuple` containing the logarithm of the absolute value of\n"
"gamma(x) and the sign of gamma(x)");
static PyObject *
GMPy_RealWithType_Lgamma(PyObject *x, int xtype, CTXT_Object *context)
{
PyObject *result = NULL;
MPFR_Object *value = NULL, *tempx = NULL;
int signp = 0;
tempx = GMPy_MPFR_From_RealWithType(x, xtype, 1, context);
value = GMPy_MPFR_New(0, context);
result = PyTuple_New(2);
if (!tempx || !value || !result) {
Py_XDECREF((PyObject*)tempx);
Py_XDECREF((PyObject*)value);
Py_XDECREF(result);
return NULL;
}
mpfr_clear_flags();
value->rc = mpfr_lgamma(value->f, &signp, tempx->f, GET_MPFR_ROUND(context));
Py_DECREF((PyObject*)tempx);
_GMPy_MPFR_Cleanup(&value, context);
if (!value) {
Py_DECREF(result);
return NULL;
}
PyTuple_SET_ITEM(result, 0, (PyObject*)value);
PyTuple_SET_ITEM(result, 1, PyLong_FromLong((long)signp));
return result;
}
GMPY_MPFR_UNIOP_TEMPLATEWT(Lgamma, lgamma)
PyDoc_STRVAR(GMPy_doc_function_remquo,
"remquo(x, y, /) -> tuple[mpfr, int]\n\n"
"Return a `tuple` containing the remainder(x,y) and the low bits of the\n"
"quotient.");
PyDoc_STRVAR(GMPy_doc_context_remquo,
"context.remquo(x, y, /) -> tuple[mpfr, int]\n\n"
"Return a `tuple` containing the remainder(x,y) and the low bits of the\n"
"quotient.");
static PyObject *
GMPy_RealWithType_RemQuo(PyObject *x, int xtype, PyObject *y, int ytype, CTXT_Object *context)
{
PyObject *result;
MPFR_Object *value, *tempx, *tempy;
long quobits = 0;
CHECK_CONTEXT(context);
value = GMPy_MPFR_New(0, context);
tempx = GMPy_MPFR_From_RealWithType(x, xtype, 1, context);
tempy = GMPy_MPFR_From_RealWithType(y, ytype, 1, context);
result = PyTuple_New(2);
if (!value || !tempx || !tempx || !result) {
Py_XDECREF((PyObject*)tempx);
Py_XDECREF((PyObject*)tempy);
Py_XDECREF((PyObject*)value);
Py_XDECREF(result);
return NULL;
}
mpfr_clear_flags();
value->rc = mpfr_remquo(value->f, &quobits, tempx->f, tempy->f, GET_MPFR_ROUND(context));
Py_DECREF((PyObject*)tempx);
Py_DECREF((PyObject*)tempy);
_GMPy_MPFR_Cleanup(&value, context);
PyTuple_SET_ITEM(result, 0, (PyObject*)value);
PyTuple_SET_ITEM(result, 1, PyLong_FromLong(quobits));
return result;
}
GMPY_MPFR_BINOP_TEMPLATEWT(RemQuo, remquo);
PyDoc_STRVAR(GMPy_doc_function_frexp,
"frexp(x, /) -> tuple[int, mpfr]\n\n"
"Return a `tuple` containing the exponent and mantissa of x.");
PyDoc_STRVAR(GMPy_doc_context_frexp,
"context.frexp(x, /) -> tuple[int, mpfr]\n\n"
"Return a `tuple` containing the exponent and mantissa of x.");
static PyObject *
GMPy_RealWithType_Frexp(PyObject *x, int xtype, CTXT_Object *context)
{
PyObject *result = NULL;
MPFR_Object *value = NULL, *tempx = NULL;
mpfr_exp_t exp = 0;
value = GMPy_MPFR_New(0, context);
tempx = GMPy_MPFR_From_RealWithType(x, xtype, 1, context);
result = PyTuple_New(2);
if (!value || !result || !tempx) {
Py_XDECREF((PyObject*)tempx);
Py_XDECREF((PyObject*)value);
Py_XDECREF(result);
return NULL;
}
mpfr_clear_flags();
value->rc = mpfr_frexp(&exp, value->f, tempx->f, GET_MPFR_ROUND(context));
Py_DECREF((PyObject*)tempx);
_GMPy_MPFR_Cleanup(&value, context);
PyTuple_SET_ITEM(result, 0, PyLong_FromSsize_t((Py_ssize_t)exp));
PyTuple_SET_ITEM(result, 1, (PyObject*)value);
return result;
}
GMPY_MPFR_UNIOP_TEMPLATEWT(Frexp, frexp)
PyDoc_STRVAR(GMPy_doc_function_next_toward,
"next_toward(x, y, /) -> mpfr\n\n"
"Return the next `mpfr` from x in the direction of y. The result has\n"
"the same precision as x.");
PyDoc_STRVAR(GMPy_doc_context_next_toward,
"context.next_toward(x, y, /) -> mpfr\n\n"
"Return the next `mpfr` from x in the direction of y. The result has\n"
"the same precision as x.");
static PyObject *
GMPy_Context_NextToward(PyObject *self, PyObject *args)
{
MPFR_Object *result, *tempx, *tempy;
CTXT_Object *context = NULL;
int direction;
mpfr_rnd_t temp_round;
if (self && CTXT_Check(self)) {
context = (CTXT_Object*)self;
}
else {
CHECK_CONTEXT(context);
}
if (PyTuple_GET_SIZE(args) != 2) {
TYPE_ERROR("next_toward() requires 2 arguments");
return NULL;
}
tempx = GMPy_MPFR_From_Real(PyTuple_GET_ITEM(args, 0), 1, context);
tempy = GMPy_MPFR_From_Real(PyTuple_GET_ITEM(args, 1), 1, context);
if (!tempx || !tempy) {
TYPE_ERROR("next_toward() argument type not supported");
Py_XDECREF((PyObject*)tempx);
Py_XDECREF((PyObject*)tempy);
return NULL;
}
if (!(result = GMPy_MPFR_New(mpfr_get_prec(tempx->f), context))) {
Py_DECREF((PyObject*)tempx);
Py_DECREF((PyObject*)tempy);
return NULL;
}
mpfr_clear_flags();
mpfr_set(result->f, tempx->f, GET_MPFR_ROUND(context));
mpfr_nexttoward(result->f, tempy->f);
result->rc = 0;
direction = mpfr_signbit(tempy->f);
Py_DECREF((PyObject*)tempx);
Py_DECREF((PyObject*)tempy);
temp_round = GET_MPFR_ROUND(context);
if (direction)
context->ctx.mpfr_round = MPFR_RNDD;
else
context->ctx.mpfr_round = MPFR_RNDU;
_GMPy_MPFR_Cleanup(&result, context);
context->ctx.mpfr_round = temp_round;
return (PyObject*)result;
}
PyDoc_STRVAR(GMPy_doc_function_next_above,
"next_above(x, /) -> mpfr\n\n"
"Return the next `mpfr` from x toward +Infinity.");
PyDoc_STRVAR(GMPy_doc_context_next_above,
"context.next_above(x, /) -> mpfr\n\n"
"Return the next `mpfr` from x toward +Infinity.");
static PyObject *
GMPy_Context_NextAbove(PyObject *self, PyObject *other)
{
MPFR_Object *result, *tempx;
CTXT_Object *context = NULL;
mpfr_rnd_t temp_round;
if (self && CTXT_Check(self)) {
context = (CTXT_Object*)self;
}
else {
CHECK_CONTEXT(context);
}
if (!(tempx = GMPy_MPFR_From_Real(other, 1, context))) {
TYPE_ERROR("next_above() argument type not supported");
return NULL;
}
if (!(result = GMPy_MPFR_New(mpfr_get_prec(tempx->f), context))) {
Py_DECREF((PyObject*)tempx);
return NULL;
}
mpfr_clear_flags();
mpfr_set(result->f, tempx->f, GET_MPFR_ROUND(context));
Py_DECREF((PyObject*)tempx);
mpfr_nextabove(result->f);
result->rc = 0;
temp_round = GET_MPFR_ROUND(context);
context->ctx.mpfr_round = MPFR_RNDU;
_GMPy_MPFR_Cleanup(&result, context);
context->ctx.mpfr_round = temp_round;
return (PyObject*)result;
}
PyDoc_STRVAR(GMPy_doc_function_next_below,
"next_below(x, /) -> mpfr\n\n"
"Return the next `mpfr` from x toward -Infinity.");
PyDoc_STRVAR(GMPy_doc_context_next_below,
"context.next_below(x, /) -> mpfr\n\n"
"Return the next `mpfr` from x toward -Infinity.");
static PyObject *
GMPy_Context_NextBelow(PyObject *self, PyObject *other)
{
MPFR_Object *result, *tempx;
CTXT_Object *context = NULL;
mpfr_rnd_t temp_round;
if (self && CTXT_Check(self)) {
context = (CTXT_Object*)self;
}
else {
CHECK_CONTEXT(context);
}
if (!(tempx = GMPy_MPFR_From_Real(other, 1, context))) {
TYPE_ERROR("next_below() argument type not supported");
return NULL;
}
if (!(result = GMPy_MPFR_New(mpfr_get_prec(tempx->f), context))) {
Py_DECREF((PyObject*)tempx);
return NULL;
}
mpfr_clear_flags();
mpfr_set(result->f, tempx->f, GET_MPFR_ROUND(context));
Py_DECREF((PyObject*)tempx);
mpfr_nextbelow(result->f);
result->rc = 0;
temp_round = GET_MPFR_ROUND(context);
context->ctx.mpfr_round = MPFR_RNDD;
_GMPy_MPFR_Cleanup(&result, context);
context->ctx.mpfr_round = temp_round;
return (PyObject*)result;
}
PyDoc_STRVAR(GMPy_doc_function_factorial,
"factorial(n, /) -> mpfr\n\n"
"Return the floating-point approximation to the factorial of n.\n\n"
"See `fac()` to get the exact integer result.");
PyDoc_STRVAR(GMPy_doc_context_factorial,
"context.factorial(n, /) -> mpfr\n\n"
"Return the floating-point approximation to the factorial of n.\n\n"
"See `fac()` to get the exact integer result.");
static PyObject *
GMPy_Context_Factorial(PyObject *self, PyObject *other)
{
MPFR_Object *result;
unsigned long n;
CTXT_Object *context = NULL;
if (self && CTXT_Check(self)) {
context = (CTXT_Object*)self;
}
else {
CHECK_CONTEXT(context);
}
n = GMPy_Integer_AsUnsignedLong(other);
if ((n == (unsigned long)-1) && PyErr_Occurred()) {
return NULL;
}
if (!(result = GMPy_MPFR_New(0, context))) {
return NULL;
}
/* Force result to be 'inf' if n >= 44787928. The matches the behavior of
* MPFR compiled on 64-bit Linux. MPFR compiled on 32-bit Linux and both 32
* and 64-bit versions of Windows will enter an infinite loop. The constant
* 44787929 occurs in the MPFR file gamma.c.
*/
mpfr_clear_flags();
if (n >= 44787928) {
mpfr_set_inf(result->f, 1);
mpfr_set_overflow();
}
else {
mpfr_fac_ui(result->f, n, GET_MPFR_ROUND(context));
}
_GMPy_MPFR_Cleanup(&result, context);
return (PyObject*)result;
}
PyDoc_STRVAR(GMPy_doc_function_fsum,
"fsum(iterable, /) -> mpfr\n\n"
"Return an accurate sum of the values in the iterable.");
PyDoc_STRVAR(GMPy_doc_context_fsum,
"fsum(iterable, /) -> mpfr\n\n"
"Return an accurate sum of the values in the iterable.");
static PyObject *
GMPy_Context_Fsum(PyObject *self, PyObject *other)
{
MPFR_Object *temp, *result;
mpfr_ptr *tab;
int errcode;
Py_ssize_t i, seq_length = 0;
CTXT_Object *context = NULL;
if (self && CTXT_Check(self)) {
context = (CTXT_Object*)self;
}
else {
CHECK_CONTEXT(context);
}
if (!(result = GMPy_MPFR_New(0, context))) {
return NULL;
}
if (!(other = PySequence_List(other))) {
Py_DECREF((PyObject*)result);
TYPE_ERROR("argument must be an iterable");
return NULL;
}
/* other contains a new list containing all the values from the
* iterable. Now make sure each item in the list is an mpfr.
*/
seq_length = PyList_GET_SIZE(other);
if (seq_length > LONG_MAX) {
OVERFLOW_ERROR("temporary array is too large");
Py_DECREF(other);
Py_DECREF((PyObject*)result);
return NULL;
}
for (i=0; i < seq_length; i++) {
if (!(temp = GMPy_MPFR_From_Real(PyList_GET_ITEM(other, i), 1, context))) {
Py_DECREF(other);
Py_DECREF((PyObject*)result);
TYPE_ERROR("all items in iterable must be real numbers");
return NULL;
}
errcode = PyList_SetItem(other, i,(PyObject*)temp);
if (errcode < 0) {
Py_DECREF(other);
Py_DECREF((PyObject*)result);
TYPE_ERROR("all items in iterable must be real numbers");
return NULL;
}
}
/* create an array of pointers to the mpfr_t field of a Pympfr object */
if (!(tab = (mpfr_ptr *)malloc((sizeof(mpfr_srcptr) * seq_length)))) {
Py_DECREF(other);
Py_DECREF((PyObject*)result);
return PyErr_NoMemory();
}
for (i=0; i < seq_length; i++) {
temp = (MPFR_Object*)PyList_GET_ITEM(other, i);
tab[i] = temp->f;
}
mpfr_clear_flags();
/* The cast is safe since we have compared seq_length to LONG_MAX. */
result->rc = mpfr_sum(result->f, tab, (unsigned long)seq_length, GET_MPFR_ROUND(context));
Py_DECREF(other);
free(tab);
_GMPy_MPFR_Cleanup(&result, context);
return (PyObject*)result;
}
././@PaxHeader 0000000 0000000 0000000 00000000026 00000000000 010213 x ustar 00 22 mtime=1710307256.0
gmpy2-2.2.1/src/gmpy2_math.h 0000644 0001750 0001750 00000050415 14574233670 014251 0 ustar 00case case /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* gmpy2_math.h *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Python interface to the GMP, MPFR, and MPC multiple precision *
* libraries. *
* *
* Copyright 2000 - 2009 Alex Martelli *
* *
* Copyright 2008 - 2024 Case Van Horsen *
* *
* This file is part of GMPY2. *
* *
* GMPY2 is free software: you can redistribute it and/or modify it under *
* the terms of the GNU Lesser General Public License as published by the *
* Free Software Foundation, either version 3 of the License, or (at your *
* option) any later version. *
* *
* GMPY2 is distributed in the hope that it will be useful, but WITHOUT *
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or *
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public *
* License for more details. *
* *
* You should have received a copy of the GNU Lesser General Public *
* License along with GMPY2; if not, see *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
#ifndef GMPY_MATH_H
#define GMPY_MATH_H
#ifdef __cplusplus
extern "C" {
#endif
static PyObject * GMPy_RealWithType_Sin(PyObject *x, int xtype, CTXT_Object *context);
static PyObject * GMPy_ComplexWithType_Sin(PyObject *x, int xtype, CTXT_Object *context);
static PyObject * GMPy_Number_Sin(PyObject *x, CTXT_Object *context);
static PyObject * GMPy_Context_Sin(PyObject *self, PyObject *other);
static PyObject * GMPy_RealWithType_Cos(PyObject *x, int xtype, CTXT_Object *context);
static PyObject * GMPy_ComplexWithType_Cos(PyObject *x, int xtype, CTXT_Object *context);
static PyObject * GMPy_Number_Cos(PyObject *x, CTXT_Object *context);
static PyObject * GMPy_Context_Cos(PyObject *self, PyObject *other);
static PyObject * GMPy_RealWithType_Tan(PyObject *x, int xtype, CTXT_Object *context);
static PyObject * GMPy_ComplexWithType_Tan(PyObject *x, int xtype, CTXT_Object *context);
static PyObject * GMPy_Number_Tan(PyObject *x, CTXT_Object *context);
static PyObject * GMPy_Context_Tan(PyObject *self, PyObject *other);
static PyObject * GMPy_RealWithType_Atan(PyObject *x, int xtype, CTXT_Object *context);
static PyObject * GMPy_ComplexWithType_Atan(PyObject *x, int xtype, CTXT_Object *context);
static PyObject * GMPy_Number_Atan(PyObject *x, CTXT_Object *context);
static PyObject * GMPy_Context_Atan(PyObject *self, PyObject *other);
static PyObject * GMPy_RealWithType_Sinh(PyObject *x, int xtype, CTXT_Object *context);
static PyObject * GMPy_ComplexWithType_Sinh(PyObject *x, int xtype, CTXT_Object *context);
static PyObject * GMPy_Number_Sinh(PyObject *x, CTXT_Object *context);
static PyObject * GMPy_Context_Sinh(PyObject *self, PyObject *other);
static PyObject * GMPy_RealWithType_Cosh(PyObject *x, int xtype, CTXT_Object *context);
static PyObject * GMPy_ComplexWithType_Cosh(PyObject *x, int xtype, CTXT_Object *context);
static PyObject * GMPy_Number_Cosh(PyObject *x, CTXT_Object *context);
static PyObject * GMPy_Context_Cosh(PyObject *self, PyObject *other);
static PyObject * GMPy_RealWithType_Tanh(PyObject *x, int xtype, CTXT_Object *context);
static PyObject * GMPy_ComplexWithType_Tanh(PyObject *x, int xtype, CTXT_Object *context);
static PyObject * GMPy_Number_Tanh(PyObject *x, CTXT_Object *context);
static PyObject * GMPy_Context_Tanh(PyObject *self, PyObject *other);
static PyObject * GMPy_RealWithType_Asinh(PyObject *x, int xtype, CTXT_Object *context);
static PyObject * GMPy_ComplexWithType_Asinh(PyObject *x, int xtype, CTXT_Object *context);
static PyObject * GMPy_Number_Asinh(PyObject *x, CTXT_Object *context);
static PyObject * GMPy_Context_Asinh(PyObject *self, PyObject *other);
static PyObject * GMPy_RealWithType_Acosh(PyObject *x, int xtype, CTXT_Object *context);
static PyObject * GMPy_ComplexWithType_Acosh(PyObject *x, int xtype, CTXT_Object *context);
static PyObject * GMPy_Number_Acosh(PyObject *x, CTXT_Object *context);
static PyObject * GMPy_Context_Acosh(PyObject *self, PyObject *other);
static PyObject * GMPy_RealWithType_Sec(PyObject *x, int xtype, CTXT_Object *context);
static PyObject * GMPy_Number_Sec(PyObject *x, CTXT_Object *context);
static PyObject * GMPy_Context_Sec(PyObject *self, PyObject *other);
static PyObject * GMPy_RealWithType_Csc(PyObject *x, int xtype, CTXT_Object *context);
static PyObject * GMPy_Number_Csc(PyObject *x, CTXT_Object *context);
static PyObject * GMPy_Context_Csc(PyObject *self, PyObject *other);
static PyObject * GMPy_RealWithType_Cot(PyObject *x, int xtype, CTXT_Object *context);
static PyObject * GMPy_Number_Cot(PyObject *x, CTXT_Object *context);
static PyObject * GMPy_Context_Cot(PyObject *self, PyObject *other);
static PyObject * GMPy_RealWithType_Sech(PyObject *x, int xtype, CTXT_Object *context);
static PyObject * GMPy_Number_Sech(PyObject *x, CTXT_Object *context);
static PyObject * GMPy_Context_Sech(PyObject *self, PyObject *other);
static PyObject * GMPy_RealWithType_Csch(PyObject *x, int xtype, CTXT_Object *context);
static PyObject * GMPy_Number_Csch(PyObject *x, CTXT_Object *context);
static PyObject * GMPy_Context_Csch(PyObject *self, PyObject *other);
static PyObject * GMPy_RealWithType_Coth(PyObject *x, int xtype, CTXT_Object *context);
static PyObject * GMPy_Number_Coth(PyObject *x, CTXT_Object *context);
static PyObject * GMPy_Context_Coth(PyObject *self, PyObject *other);
static PyObject * GMPy_RealWithType_Acos(PyObject *x, int xtype, CTXT_Object *context);
static PyObject * GMPy_ComplexWithType_Acos(PyObject *x, int xtype, CTXT_Object *context);
static PyObject * GMPy_Number_Acos(PyObject *x, CTXT_Object *context);
static PyObject * GMPy_Context_Acos(PyObject *self, PyObject *other);
static PyObject * GMPy_RealWithType_Asin(PyObject *x, int xtype, CTXT_Object *context);
static PyObject * GMPy_ComplexWithType_Asin(PyObject *x, int xtype, CTXT_Object *context);
static PyObject * GMPy_Number_Asin(PyObject *x, CTXT_Object *context);
static PyObject * GMPy_Context_Asin(PyObject *self, PyObject *other);
static PyObject * GMPy_RealWithType_Atanh(PyObject *x, int xtype, CTXT_Object *context);
static PyObject * GMPy_ComplexWithType_Atanh(PyObject *x, int xtype, CTXT_Object *context);
static PyObject * GMPy_Number_Atanh(PyObject *x, CTXT_Object *context);
static PyObject * GMPy_Context_Atanh(PyObject *self, PyObject *other);
static PyObject * GMPy_RealWithType_Sin_Cos(PyObject *x, int xtype, CTXT_Object *context);
static PyObject * GMPy_ComplexWithType_Sin_Cos(PyObject *x, int xtype, CTXT_Object *context);
static PyObject * GMPy_Number_Sin_Cos(PyObject *x, CTXT_Object *context);
static PyObject * GMPy_Context_Sin_Cos(PyObject *self, PyObject *other);
static PyObject * GMPy_RealWithType_Sinh_Cosh(PyObject *x, int xtype, CTXT_Object *context);
static PyObject * GMPy_Number_Sinh_Cosh(PyObject *x, CTXT_Object *context);
static PyObject * GMPy_Context_Sinh_Cosh(PyObject *self, PyObject *other);
static PyObject * GMPy_RealWithType_Atan2(PyObject *x, int xtype, PyObject *y, int ytype, CTXT_Object *context);
static PyObject * GMPy_Number_Atan2(PyObject *x, PyObject *y, CTXT_Object *context);
static PyObject * GMPy_Context_Atan2(PyObject *self, PyObject *args);
static PyObject * GMPy_RealWithType_Hypot(PyObject *x, int xtype, PyObject *y, int ytype, CTXT_Object *context);
static PyObject * GMPy_Number_Hypot(PyObject *x, PyObject *y, CTXT_Object *context);
static PyObject * GMPy_Context_Hypot(PyObject *self, PyObject *args);
static PyObject * GMPy_Context_Degrees(PyObject *self, PyObject *other);
static PyObject * GMPy_Context_Radians(PyObject *self, PyObject *other);
static PyObject * GMPy_RealWithType_Log(PyObject *x, int xtype, CTXT_Object *context);
static PyObject * GMPy_ComplexWithType_Log(PyObject *x, int xtype, CTXT_Object *context);
static PyObject * GMPy_Number_Log(PyObject *x, CTXT_Object *context);
static PyObject * GMPy_Context_Log(PyObject *self, PyObject *other);
static PyObject * GMPy_RealWithType_Log10(PyObject *x, int xtype, CTXT_Object *context);
static PyObject * GMPy_ComplexWithType_Log10(PyObject *x, int xtype, CTXT_Object *context);
static PyObject * GMPy_Number_Log10(PyObject *x, CTXT_Object *context);
static PyObject * GMPy_Context_Log10(PyObject *self, PyObject *other);
static PyObject * GMPy_RealWithType_Exp(PyObject *x, int xtype, CTXT_Object *context);
static PyObject * GMPy_ComplexWithType_Exp(PyObject *x, int xtype, CTXT_Object *context);
static PyObject * GMPy_Number_Exp(PyObject *x, CTXT_Object *context);
static PyObject * GMPy_Context_Exp(PyObject *self, PyObject *other);
static PyObject * GMPy_RealWithType_Sqrt(PyObject *x, int xtype, CTXT_Object *context);
static PyObject * GMPy_ComplexWithType_Sqrt(PyObject *x, int xtype, CTXT_Object *context);
static PyObject * GMPy_Number_Sqrt(PyObject *x, CTXT_Object *context);
static PyObject * GMPy_Context_Sqrt(PyObject *self, PyObject *other);
static PyObject * GMPy_RealWithType_RecSqrt(PyObject *x, int xtype, CTXT_Object *context);
static PyObject * GMPy_Number_RecSqrt(PyObject *x, CTXT_Object *context);
static PyObject * GMPy_Context_RecSqrt(PyObject *self, PyObject *other);
static PyObject * GMPy_RealWithType_Rint(PyObject *x, int xtype, CTXT_Object *context);
static PyObject * GMPy_Number_Rint(PyObject *x, CTXT_Object *context);
static PyObject * GMPy_Context_Rint(PyObject *self, PyObject *other);
static PyObject * GMPy_RealWithType_RintCeil(PyObject *x, int xtype, CTXT_Object *context);
static PyObject * GMPy_Number_RintCeil(PyObject *x, CTXT_Object *context);
static PyObject * GMPy_Context_RintCeil(PyObject *self, PyObject *other);
static PyObject * GMPy_RealWithType_RintFloor(PyObject *x, int xtype, CTXT_Object *context);
static PyObject * GMPy_Number_RintFloor(PyObject *x, CTXT_Object *context);
static PyObject * GMPy_Context_RintFloor(PyObject *self, PyObject *other);
static PyObject * GMPy_RealWithType_RintRound(PyObject *x, int xtype, CTXT_Object *context);
static PyObject * GMPy_Number_RintRound(PyObject *x, CTXT_Object *context);
static PyObject * GMPy_Context_RintRound(PyObject *self, PyObject *other);
static PyObject * GMPy_RealWithType_RintTrunc(PyObject *x, int xtype, CTXT_Object *context);
static PyObject * GMPy_Number_RintTrunc(PyObject *x, CTXT_Object *context);
static PyObject * GMPy_Context_RintTrunc(PyObject *self, PyObject *other);
static PyObject * GMPy_RealWithType_Frac(PyObject *x, int xtype, CTXT_Object *context);
static PyObject * GMPy_Number_Frac(PyObject *x, CTXT_Object *context);
static PyObject * GMPy_Context_Frac(PyObject *self, PyObject *other);
static PyObject * GMPy_RealWithType_Cbrt(PyObject *x, int xtype, CTXT_Object *context);
static PyObject * GMPy_Number_Cbrt(PyObject *x, CTXT_Object *context);
static PyObject * GMPy_Context_Cbrt(PyObject *self, PyObject *other);
static PyObject * GMPy_RealWithType_Log2(PyObject *x, int xtype, CTXT_Object *context);
static PyObject * GMPy_Number_Log2(PyObject *x, CTXT_Object *context);
static PyObject * GMPy_Context_Log2(PyObject *self, PyObject *other);
static PyObject * GMPy_RealWithType_Exp2(PyObject *x, int xtype, CTXT_Object *context);
static PyObject * GMPy_Number_Exp2(PyObject *x, CTXT_Object *context);
static PyObject * GMPy_Context_Exp2(PyObject *self, PyObject *other);
static PyObject * GMPy_RealWithType_Exp10(PyObject *x, int xtype, CTXT_Object *context);
static PyObject * GMPy_Number_Exp10(PyObject *x, CTXT_Object *context);
static PyObject * GMPy_Context_Exp10(PyObject *self, PyObject *other);
static PyObject * GMPy_RealWithType_Log1p(PyObject *x, int xtype, CTXT_Object *context);
static PyObject * GMPy_Number_Log1p(PyObject *x, CTXT_Object *context);
static PyObject * GMPy_Context_Log1p(PyObject *self, PyObject *other);
static PyObject * GMPy_RealWithType_Expm1(PyObject *x, int xtype, CTXT_Object *context);
static PyObject * GMPy_Number_Expm1(PyObject *x, CTXT_Object *context);
static PyObject * GMPy_Context_Expm1(PyObject *self, PyObject *other);
static PyObject * GMPy_RealWithType_Eint(PyObject *x, int xtype, CTXT_Object *context);
static PyObject * GMPy_Number_Eint(PyObject *x, CTXT_Object *context);
static PyObject * GMPy_Context_Eint(PyObject *self, PyObject *other);
static PyObject * GMPy_RealWithType_Li2(PyObject *x, int xtype, CTXT_Object *context);
static PyObject * GMPy_Number_Li2(PyObject *x, CTXT_Object *context);
static PyObject * GMPy_Context_Li2(PyObject *self, PyObject *other);
static PyObject * GMPy_RealWithType_Lngamma(PyObject *x, int xtype, CTXT_Object *context);
static PyObject * GMPy_Number_Lngamma(PyObject *x, CTXT_Object *context);
static PyObject * GMPy_Context_Lngamma(PyObject *self, PyObject *other);
static PyObject * GMPy_RealWithType_Digamma(PyObject *x, int xtype, CTXT_Object *context);
static PyObject * GMPy_Number_Digamma(PyObject *x, CTXT_Object *context);
static PyObject * GMPy_Context_Digamma(PyObject *self, PyObject *other);
static PyObject * GMPy_RealWithType_Zeta(PyObject *x, int xtype, CTXT_Object *context);
static PyObject * GMPy_Number_Zeta(PyObject *x, CTXT_Object *context);
static PyObject * GMPy_Context_Zeta(PyObject *self, PyObject *other);
static PyObject * GMPy_RealWithType_Erf(PyObject *x,int xtype, CTXT_Object *context);
static PyObject * GMPy_Number_Erf(PyObject *x, CTXT_Object *context);
static PyObject * GMPy_Context_Erf(PyObject *self, PyObject *other);
static PyObject * GMPy_RealWithType_Erfc(PyObject *x, int xtype, CTXT_Object *context);
static PyObject * GMPy_Number_Erfc(PyObject *x, CTXT_Object *context);
static PyObject * GMPy_Context_Erfc(PyObject *self, PyObject *other);
static PyObject * GMPy_RealWithType_J0(PyObject *x, int xtype, CTXT_Object *context);
static PyObject * GMPy_Number_J0(PyObject *x, CTXT_Object *context);
static PyObject * GMPy_Context_J0(PyObject *self, PyObject *other);
static PyObject * GMPy_RealWithType_J1(PyObject *x, int xtype, CTXT_Object *context);
static PyObject * GMPy_Number_J1(PyObject *x, CTXT_Object *context);
static PyObject * GMPy_Context_J1(PyObject *self, PyObject *other);
static PyObject * GMPy_RealWithType_Y0(PyObject *x, int xtype, CTXT_Object *context);
static PyObject * GMPy_Number_Y0(PyObject *x, CTXT_Object *context);
static PyObject * GMPy_Context_Y0(PyObject *self, PyObject *other);
static PyObject * GMPy_RealWithType_Y1(PyObject *x, int xtype, CTXT_Object *context);
static PyObject * GMPy_Number_Y1(PyObject *x, CTXT_Object *context);
static PyObject * GMPy_Context_Y1(PyObject *self, PyObject *other);
static PyObject * GMPy_RealWithType_Ai(PyObject *x, int xtype, CTXT_Object *context);
static PyObject * GMPy_Number_Ai(PyObject *x, CTXT_Object *context);
static PyObject * GMPy_Context_Ai(PyObject *self, PyObject *other);
static PyObject * GMPy_Real_Root(PyObject *x, PyObject *y, CTXT_Object *context);
static PyObject * GMPy_Number_Root(PyObject *x, PyObject *y, CTXT_Object *context);
static PyObject * GMPy_Context_Root(PyObject *self, PyObject *args);
static PyObject * GMPy_RealWithType_Jn(PyObject *x, int xtype, PyObject *y, int ytype, CTXT_Object *context);
static PyObject * GMPy_Number_Jn(PyObject *x, PyObject *y, CTXT_Object *context);
static PyObject * GMPy_Context_Jn(PyObject *self, PyObject *args);
static PyObject * GMPy_RealWithType_Yn(PyObject *x, int xtype, PyObject *y, int ytype, CTXT_Object *context);
static PyObject * GMPy_Number_Yn(PyObject *x, PyObject *y, CTXT_Object *context);
static PyObject * GMPy_Context_Yn(PyObject *self, PyObject *args);
static PyObject * GMPy_RealWithType_AGM(PyObject *x, int xtype, PyObject *y, int ytype, CTXT_Object *context);
static PyObject * GMPy_Number_AGM(PyObject *x, PyObject *y, CTXT_Object *context);
static PyObject * GMPy_Context_AGM(PyObject *self, PyObject *args);
static PyObject * GMPy_RealWithType_Maxnum(PyObject *x, int xtype, PyObject *y, int ytype, CTXT_Object *context);
static PyObject * GMPy_Number_Maxnum(PyObject *x, PyObject *y, CTXT_Object *context);
static PyObject * GMPy_Context_Maxnum(PyObject *self, PyObject *args);
static PyObject * GMPy_RealWithType_Minnum(PyObject *x, int xtype, PyObject *y, int ytype, CTXT_Object *context);
static PyObject * GMPy_Number_Minnum(PyObject *x, PyObject *y, CTXT_Object *context);
static PyObject * GMPy_Context_Minnum(PyObject *self, PyObject *args);
static PyObject * GMPy_RealWithType_Remainder(PyObject *x, int xtype, PyObject *y, int ytype, CTXT_Object *context);
static PyObject * GMPy_Number_Remainder(PyObject *x, PyObject *y, CTXT_Object *context);
static PyObject * GMPy_Context_Remainder(PyObject *self, PyObject *args);
static PyObject * GMPy_RealWithType_Fmod(PyObject *x, int xtype, PyObject *y, int ytype, CTXT_Object *context);
static PyObject * GMPy_Number_Fmod(PyObject *x, PyObject *y, CTXT_Object *context);
static PyObject * GMPy_Context_Fmod(PyObject *self, PyObject *args);
static PyObject * GMPy_RealWithType_RelDiff(PyObject *x, int xtype, PyObject *y, int ytype, CTXT_Object *context);
static PyObject * GMPy_Number_RelDiff(PyObject *x, PyObject *y, CTXT_Object *context);
static PyObject * GMPy_Context_RelDiff(PyObject *self, PyObject *args);
static PyObject * GMPy_RealWithType_Ceil(PyObject *x, int xtype, CTXT_Object *context);
static PyObject * GMPy_Number_Ceil(PyObject *x, CTXT_Object *context);
static PyObject * GMPy_MPFR_Method_Ceil(PyObject *self, PyObject *args);
static PyObject * GMPy_Context_Ceil(PyObject *self, PyObject *args);
static PyObject * GMPy_RealWithType_Floor(PyObject *x, int xtype, CTXT_Object *context);
static PyObject * GMPy_Number_Floor(PyObject *x, CTXT_Object *context);
static PyObject * GMPy_MPFR_Method_Floor(PyObject *self, PyObject *args);
static PyObject * GMPy_Context_Floor(PyObject *self, PyObject *args);
static PyObject * GMPy_RealWithType_Trunc(PyObject *x, int xtype, CTXT_Object *context);
static PyObject * GMPy_Number_Trunc(PyObject *x, CTXT_Object *context);
static PyObject * GMPy_MPFR_Method_Trunc(PyObject *self, PyObject *args);
static PyObject * GMPy_Context_Trunc(PyObject *self, PyObject *args);
static PyObject * GMPy_Real_Round2(PyObject *x, PyObject *y, CTXT_Object *context);
static PyObject * GMPy_Number_Round2(PyObject *x, PyObject *y, CTXT_Object *context);
static PyObject * GMPy_Context_Round2(PyObject *self, PyObject *args);
static PyObject * GMPy_RealWithType_RoundAway(PyObject *x, int xtype, CTXT_Object *context);
static PyObject * GMPy_Number_RoundAway(PyObject *x, CTXT_Object *context);
static PyObject * GMPy_Context_RoundAway(PyObject *self, PyObject *other);
static PyObject * GMPy_RealWithType_Modf(PyObject *x, int xtype, CTXT_Object *context);
static PyObject * GMPy_Number_Modf(PyObject *x, CTXT_Object *context);
static PyObject * GMPy_Context_Modf(PyObject *self, PyObject *other);
static PyObject * GMPy_RealWithType_Lgamma(PyObject *x, int xtype, CTXT_Object *context);
static PyObject * GMPy_Number_Lgamma(PyObject *x, CTXT_Object *context);
static PyObject * GMPy_Context_Lgamma(PyObject *self, PyObject *other);
static PyObject * GMPy_RealWithType_RemQuo(PyObject *x, int xtype, PyObject *y, int ytype, CTXT_Object *context);
static PyObject * GMPy_Number_RemQuo(PyObject *x, PyObject *y, CTXT_Object *context);
static PyObject * GMPy_Context_RemQuo(PyObject *self, PyObject *other);
static PyObject * GMPy_RealWithType_Frexp(PyObject *x, int xtype, CTXT_Object *context);
static PyObject * GMPy_Number_Frexp(PyObject *x, CTXT_Object *context);
static PyObject * GMPy_Context_Frexp(PyObject *self, PyObject *other);
static PyObject * GMPy_Context_NextToward(PyObject *self, PyObject *args);
static PyObject * GMPy_Context_NextAbove(PyObject *self, PyObject *other);
static PyObject * GMPy_Context_NextBelow(PyObject *self, PyObject *other);
static PyObject * GMPy_Context_Factorial(PyObject *self, PyObject *other);
static PyObject * GMPy_Context_Fsum(PyObject *self, PyObject *other);
#ifdef __cplusplus
}
#endif
#endif
././@PaxHeader 0000000 0000000 0000000 00000000026 00000000000 010213 x ustar 00 22 mtime=1710307256.0
gmpy2-2.2.1/src/gmpy2_minus.c 0000644 0001750 0001750 00000015350 14574233670 014445 0 ustar 00case case /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* gmpy2_minus.c *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Python interface to the GMP, MPFR, and MPC multiple precision *
* libraries. *
* *
* Copyright 2000 - 2009 Alex Martelli *
* *
* Copyright 2008 - 2024 Case Van Horsen *
* *
* This file is part of GMPY2. *
* *
* GMPY2 is free software: you can redistribute it and/or modify it under *
* the terms of the GNU Lesser General Public License as published by the *
* Free Software Foundation, either version 3 of the License, or (at your *
* option) any later version. *
* *
* GMPY2 is distributed in the hope that it will be useful, but WITHOUT *
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or *
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public *
* License for more details. *
* *
* You should have received a copy of the GNU Lesser General Public *
* License along with GMPY2; if not, see *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
/* This file implements __neg__ and context.minus().
*
* Public API
* ==========
* The following function is available as part of GMPY2's C API. If the value
* of context is NULL, then the function should use the currently active
* context.
*
* GMPy_Number_Minus(Number, context)
*
* Private API
* ===========
* GMPy_MPZ_Minus_Slot
* GMPy_MPQ_Minus_Slot
* GMPy_MPFR_Minus_Slot
* GMPy_MPC_Minus_Slot
*
* GMPy_Integer_Minus(Integer, context|NULL)
* GMPy_Rational_Minus(Rational, context|NULL)
* GMPy_Real_Minus(Real, context|NULL)
* GMPy_Complex_Minus(Complex, context|NULL)
*
* GMPy_Context_Minus(context, args)
*/
static PyObject *
_GMPy_MPZ_Minus(PyObject *x, CTXT_Object *context)
{
MPZ_Object *result;
if (!(result = GMPy_MPZ_New(context))) {
return NULL;
}
mpz_neg(result->z, MPZ(x));
return (PyObject*)result;
}
static PyObject *
GMPy_Integer_MinusWithType(PyObject *x, int xtype, CTXT_Object *context)
{
PyObject *result, *tempx;
if (!(tempx = (PyObject*)GMPy_MPZ_From_IntegerWithType(x, xtype, context))) {
return NULL;
}
result = _GMPy_MPZ_Minus(tempx, context);
Py_DECREF(tempx);
return result;
}
static PyObject *
GMPy_MPZ_Minus_Slot(MPZ_Object *x)
{
return _GMPy_MPZ_Minus((PyObject*)x, NULL);
}
static PyObject *
_GMPy_MPQ_Minus(PyObject *x, CTXT_Object *context)
{
MPQ_Object *result;
CHECK_CONTEXT(context);
if (!(result = GMPy_MPQ_New(context))) {
return NULL;
}
mpq_neg(result->q, MPQ(x));
return (PyObject*)result;
}
static PyObject *
GMPy_Rational_MinusWithType(PyObject *x, int xtype, CTXT_Object *context)
{
PyObject *result, *tempx;
CHECK_CONTEXT(context);
if (!(tempx = (PyObject*)GMPy_MPQ_From_RationalWithType(x, xtype, context))) {
return NULL;
}
result = _GMPy_MPQ_Minus(tempx, context);
Py_DECREF(tempx);
return result;
}
static PyObject *
GMPy_MPQ_Minus_Slot(MPQ_Object *x)
{
return _GMPy_MPQ_Minus((PyObject*)x, NULL);
}
static PyObject *
_GMPy_MPFR_Minus(PyObject *x, CTXT_Object *context)
{
MPFR_Object *result;
CHECK_CONTEXT(context);
if (!(result = GMPy_MPFR_New(0, context))) {
return NULL;
}
mpfr_clear_flags();
result->rc = mpfr_neg(result->f, MPFR(x), GET_MPFR_ROUND(context));
_GMPy_MPFR_Cleanup(&result, context);
return (PyObject*)result;
}
static PyObject *
GMPy_Real_MinusWithType(PyObject *x, int xtype, CTXT_Object *context)
{
PyObject *result, *tempx;
CHECK_CONTEXT(context);
if (!(tempx = (PyObject*)GMPy_MPFR_From_RealWithType(x, xtype, 1, context))) {
return NULL;
}
result = _GMPy_MPFR_Minus(tempx, context);
Py_DECREF(tempx);
return result;
}
static PyObject *
GMPy_MPFR_Minus_Slot(MPFR_Object *x)
{
return _GMPy_MPFR_Minus((PyObject*)x, NULL);
}
static PyObject *
_GMPy_MPC_Minus(PyObject *x, CTXT_Object *context)
{
MPC_Object *result;
CHECK_CONTEXT(context);
if (!(result = GMPy_MPC_New(0, 0, context))) {
return NULL;
}
result->rc = mpc_neg(result->c, MPC(x), GET_MPC_ROUND(context));
_GMPy_MPC_Cleanup(&result, context);
return (PyObject*)result;
}
static PyObject *
GMPy_Complex_MinusWithType(PyObject *x, int xtype, CTXT_Object *context)
{
PyObject *result, *tempx;
CHECK_CONTEXT(context);
if (!(tempx = (PyObject*)GMPy_MPC_From_ComplexWithType(x, xtype, 1, 1, context))) {
return NULL;
}
result = _GMPy_MPC_Minus(tempx, context);
Py_DECREF(tempx);
return result;
}
static PyObject *
GMPy_MPC_Minus_Slot(MPC_Object *x)
{
return _GMPy_MPC_Minus((PyObject*)x, NULL);
}
static PyObject *
GMPy_Number_Minus(PyObject *x, CTXT_Object *context)
{
int xtype = GMPy_ObjectType(x);
if (IS_TYPE_MPZ(xtype))
return _GMPy_MPZ_Minus(x, context);
if (IS_TYPE_MPQ(xtype))
return _GMPy_MPQ_Minus(x, context);
if (IS_TYPE_MPFR(xtype))
return _GMPy_MPFR_Minus(x, context);
if (IS_TYPE_MPC(xtype))
return _GMPy_MPC_Minus(x, context);
if (IS_TYPE_INTEGER(xtype))
return GMPy_Integer_MinusWithType(x, xtype, context);
if (IS_TYPE_RATIONAL(xtype))
return GMPy_Rational_MinusWithType(x, xtype, context);
if (IS_TYPE_REAL(xtype))
return GMPy_Real_MinusWithType(x, xtype, context);
if (IS_TYPE_COMPLEX(xtype))
return GMPy_Complex_MinusWithType(x, xtype, context);
TYPE_ERROR("minus() argument type not supported");
return NULL;
}
PyDoc_STRVAR(GMPy_doc_context_minus,
"context.minus(x, /) -> mpz | mpq | mpfr | mpc\n\n"
"Return -x. The context is applied to the result.");
static PyObject *
GMPy_Context_Minus(PyObject *self, PyObject *args)
{
if (PyTuple_GET_SIZE(args) != 1) {
TYPE_ERROR("minus() requires 1 argument.");
return NULL;
}
return GMPy_Number_Minus(PyTuple_GET_ITEM(args, 0), (CTXT_Object*)self);
}
././@PaxHeader 0000000 0000000 0000000 00000000026 00000000000 010213 x ustar 00 22 mtime=1710307256.0
gmpy2-2.2.1/src/gmpy2_minus.h 0000644 0001750 0001750 00000005376 14574233670 014461 0 ustar 00case case /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* gmpy2_minus.h *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Python interface to the GMP, MPFR, and MPC multiple precision *
* libraries. *
* *
* Copyright 2000 - 2009 Alex Martelli *
* *
* Copyright 2008 - 2024 Case Van Horsen *
* *
* This file is part of GMPY2. *
* *
* GMPY2 is free software: you can redistribute it and/or modify it under *
* the terms of the GNU Lesser General Public License as published by the *
* Free Software Foundation, either version 3 of the License, or (at your *
* option) any later version. *
* *
* GMPY2 is distributed in the hope that it will be useful, but WITHOUT *
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or *
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public *
* License for more details. *
* *
* You should have received a copy of the GNU Lesser General Public *
* License along with GMPY2; if not, see *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
#ifndef GMPY2_MINUS_H
#define GMPY2_MINUS_H
#ifdef __cplusplus
extern "C" {
#endif
/* Public API */
static PyObject * GMPy_Number_Minus(PyObject *x, CTXT_Object *context);
/* Private API */
static PyObject * GMPy_Integer_MinusWithType(PyObject *x, int xtype, CTXT_Object *context);
static PyObject * GMPy_Rational_MinusWithType(PyObject *x, int xtype, CTXT_Object *context);
static PyObject * GMPy_Real_MinusWithType(PyObject *x, int xtype, CTXT_Object *context);
static PyObject * GMPy_Complex_MinusWithType(PyObject *x, int xtype, CTXT_Object *context);
static PyObject * GMPy_MPZ_Minus_Slot(MPZ_Object *x);
static PyObject * GMPy_MPQ_Minus_Slot(MPQ_Object *x);
static PyObject * GMPy_MPFR_Minus_Slot(MPFR_Object *x);
static PyObject * GMPy_MPC_Minus_Slot(MPC_Object *x);
static PyObject * GMPy_Context_Minus(PyObject *self, PyObject *args);
#ifdef __cplusplus
}
#endif
#endif
././@PaxHeader 0000000 0000000 0000000 00000000026 00000000000 010213 x ustar 00 22 mtime=1710307256.0
gmpy2-2.2.1/src/gmpy2_misc.c 0000644 0001750 0001750 00000006506 14574233670 014250 0 ustar 00case case /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* gmpy2_misc.c *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Python interface to the GMP, MPFR, and MPC multiple precision *
* libraries. *
* *
* Copyright 2000 - 2009 Alex Martelli *
* *
* Copyright 2008 - 2024 Case Van Horsen *
* *
* This file is part of GMPY2. *
* *
* GMPY2 is free software: you can redistribute it and/or modify it under *
* the terms of the GNU Lesser General Public License as published by the *
* Free Software Foundation, either version 3 of the License, or (at your *
* option) any later version. *
* *
* GMPY2 is distributed in the hope that it will be useful, but WITHOUT *
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or *
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public *
* License for more details. *
* *
* You should have received a copy of the GNU Lesser General Public *
* License along with GMPY2; if not, see *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
/* Miscellaneous module-level functions and helper functions. */
PyDoc_STRVAR(GMPy_doc_license,
"license() -> str\n\n"
"Return string giving license information.");
static PyObject *
GMPy_get_license(PyObject *self, PyObject *args)
{
return PyUnicode_FromString(gmpy_license);
}
PyDoc_STRVAR(GMPy_doc_version,
"version() -> str\n\n"
"Return string giving current GMPY2 version.");
static PyObject *
GMPy_get_version(PyObject *self, PyObject *args)
{
return PyUnicode_FromString(gmpy_version);
}
PyDoc_STRVAR(GMPy_doc_mp_version,
"mp_version() -> str\n\n"
"Return string giving current GMP version.");
static PyObject *
GMPy_get_mp_version(PyObject *self, PyObject *args)
{
return PyUnicode_FromFormat("GMP %s", gmp_version);
}
PyDoc_STRVAR(GMPy_doc_mpfr_version,
"mpfr_version() -> str\n\n"
"Return string giving current MPFR version.");
static PyObject *
GMPy_get_mpfr_version(PyObject *self, PyObject *args)
{
return PyUnicode_FromFormat("MPFR %s", MPFR_VERSION_STRING);
}
PyDoc_STRVAR(GMPy_doc_mpc_version,
"mpc_version() -> str\n\n"
"Return string giving current MPC version.");
static PyObject *
GMPy_get_mpc_version(PyObject *self, PyObject *args)
{
return PyUnicode_FromFormat("MPC %s", MPC_VERSION_STRING);
}
PyDoc_STRVAR(GMPy_doc_mp_limbsize,
"mp_limbsize() -> int\n\n\
Return the number of bits per limb.");
static PyObject *
GMPy_get_mp_limbsize(PyObject *self, PyObject *args)
{
return PyLong_FromLong(mp_bits_per_limb);
}
././@PaxHeader 0000000 0000000 0000000 00000000026 00000000000 010213 x ustar 00 22 mtime=1710307256.0
gmpy2-2.2.1/src/gmpy2_misc.h 0000644 0001750 0001750 00000004644 14574233670 014256 0 ustar 00case case /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* gmpy2_misc.c *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Python interface to the GMP, MPFR, and MPC multiple precision *
* libraries. *
* *
* Copyright 2000 - 2009 Alex Martelli *
* *
* Copyright 2008 - 2024 Case Van Horsen *
* *
* This file is part of GMPY2. *
* *
* GMPY2 is free software: you can redistribute it and/or modify it under *
* the terms of the GNU Lesser General Public License as published by the *
* Free Software Foundation, either version 3 of the License, or (at your *
* option) any later version. *
* *
* GMPY2 is distributed in the hope that it will be useful, but WITHOUT *
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or *
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public *
* License for more details. *
* *
* You should have received a copy of the GNU Lesser General Public *
* License along with GMPY2; if not, see *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
#ifndef GMPY_MISC_H
#define GMPY_MISC_H
#ifdef __cplusplus
extern "C" {
#endif
static PyObject * GMPy_get_license(PyObject *self, PyObject *args);
static PyObject * GMPy_get_version(PyObject *self, PyObject *args);
static PyObject * GMPy_get_mp_version(PyObject *self, PyObject *args);
static PyObject * GMPy_get_mpfr_version(PyObject *self, PyObject *args);
static PyObject * GMPy_get_mpc_version(PyObject *self, PyObject *args);
static PyObject * GMPy_get_mp_limbsize(PyObject *self, PyObject *args);
#ifdef __cplusplus
}
#endif
#endif
././@PaxHeader 0000000 0000000 0000000 00000000026 00000000000 010213 x ustar 00 22 mtime=1710307256.0
gmpy2-2.2.1/src/gmpy2_mod.c 0000644 0001750 0001750 00000030160 14574233670 014065 0 ustar 00case case /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* gmpy2_mod.c *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Python interface to the GMP, MPFR, and MPC multiple precision *
* libraries. *
* *
* Copyright 2000 - 2009 Alex Martelli *
* *
* Copyright 2008 - 2024 Case Van Horsen *
* *
* This file is part of GMPY2. *
* *
* GMPY2 is free software: you can redistribute it and/or modify it under *
* the terms of the GNU Lesser General Public License as published by the *
* Free Software Foundation, either version 3 of the License, or (at your *
* option) any later version. *
* *
* GMPY2 is distributed in the hope that it will be useful, but WITHOUT *
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or *
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public *
* License for more details. *
* *
* You should have received a copy of the GNU Lesser General Public *
* License along with GMPY2; if not, see *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
/* This file implements __mod__, gmpy2.mod(), and context.mod().
*/
static PyObject *
GMPy_Integer_ModWithType(PyObject *x, int xtype, PyObject *y, int ytype,
CTXT_Object *context)
{
MPZ_Object *result;
CHECK_CONTEXT(context);
if (!(result = GMPy_MPZ_New(context))) {
/* LCOV_EXCL_START */
return NULL;
/* LCOV_EXCL_STOP */
}
if (IS_TYPE_MPZANY(xtype)) {
if (IS_TYPE_MPZANY(ytype)) {
if (mpz_sgn(MPZ(y)) == 0) {
ZERO_ERROR("division or modulo by zero");
Py_DECREF((PyObject*)result);
return NULL;
}
GMPY_MAYBE_BEGIN_ALLOW_THREADS(context);
mpz_fdiv_r(result->z, MPZ(x), MPZ(y));
GMPY_MAYBE_END_ALLOW_THREADS(context);
return (PyObject*)result;
}
if (IS_TYPE_PyInteger(ytype)) {
int error;
long temp = PyLong_AsLongAndOverflow(y, &error);
if (!error) {
if (temp > 0) {
mpz_fdiv_r_ui(result->z, MPZ(x), temp);
}
else if (temp == 0) {
ZERO_ERROR("division or modulo by zero");
Py_DECREF((PyObject*)result);
return NULL;
}
else {
mpz_cdiv_r_ui(result->z, MPZ(x), -temp);
}
}
else {
mpz_set_PyLong(result->z, y);
GMPY_MAYBE_BEGIN_ALLOW_THREADS(context);
mpz_fdiv_r(result->z, MPZ(x), result->z);
GMPY_MAYBE_END_ALLOW_THREADS(context);
}
return (PyObject*)result;
}
}
if (IS_TYPE_MPZANY(ytype)) {
if (mpz_sgn(MPZ(y)) == 0) {
ZERO_ERROR("division or modulo by zero");
Py_DECREF((PyObject*)result);
return NULL;
}
if (PyLong_Check(x)) {
mpz_set_PyLong(result->z, x);
mpz_fdiv_r(result->z, result->z, MPZ(y));
return (PyObject*)result;
}
}
if (IS_TYPE_INTEGER(xtype) && (IS_TYPE_INTEGER(ytype))) {
MPZ_Object *tempx = NULL, *tempy = NULL;
if (!(tempx = GMPy_MPZ_From_IntegerWithType(x, xtype, context)) ||
!(tempy = GMPy_MPZ_From_IntegerWithType(y, ytype, context))) {
/* LCOV_EXCL_START */
Py_XDECREF((PyObject*)tempx);
Py_XDECREF((PyObject*)tempy);
Py_DECREF((PyObject*)result);
return NULL;
/* LCOV_EXCL_STOP */
}
if (mpz_sgn(tempy->z) == 0) {
ZERO_ERROR("division or modulo by zero");
Py_XDECREF((PyObject*)tempx);
Py_XDECREF((PyObject*)tempy);
Py_DECREF((PyObject*)result);
return NULL;
}
GMPY_MAYBE_BEGIN_ALLOW_THREADS(context);
mpz_fdiv_r(result->z, tempx->z, tempy->z);
GMPY_MAYBE_END_ALLOW_THREADS(context);
Py_DECREF((PyObject*)tempx);
Py_DECREF((PyObject*)tempy);
return (PyObject*)result;
}
/* LCOV_EXCL_START */
Py_DECREF((PyObject*)result);
TYPE_ERROR("mod() argument type not supported");
return NULL;
/* LCOV_EXCL_STOP */
}
static PyObject *
GMPy_Rational_ModWithType(PyObject *x, int xtype, PyObject *y, int ytype,
CTXT_Object *context)
{
MPQ_Object *tempx = NULL, *tempy = NULL, *result = NULL;
MPZ_Object *tempz = NULL;
CHECK_CONTEXT(context);
if (!(result = GMPy_MPQ_New(context)) ||
!(tempz = GMPy_MPZ_New(context))) {
/* LCOV_EXCL_START */
Py_XDECREF((PyObject*)tempz);
Py_XDECREF((PyObject*)result);
return NULL;
/* LCOV_EXCL_STOP */
}
if (IS_TYPE_RATIONAL(xtype) && IS_TYPE_RATIONAL(ytype)) {
if (!(tempx = GMPy_MPQ_From_RationalWithType(x, xtype, context)) ||
!(tempy = GMPy_MPQ_From_RationalWithType(y, ytype, context))) {
/* LCOV_EXCL_START */
Py_XDECREF((PyObject*)tempx);
Py_XDECREF((PyObject*)tempy);
Py_DECREF((PyObject*)tempz);
Py_DECREF((PyObject*)result);
return NULL;
/* LCOV_EXCL_STOP */
}
if (mpq_sgn(tempy->q) == 0) {
ZERO_ERROR("division or modulo by zero");
Py_XDECREF((PyObject*)tempx);
Py_XDECREF((PyObject*)tempy);
Py_DECREF((PyObject*)tempz);
Py_DECREF((PyObject*)result);
return NULL;
}
GMPY_MAYBE_BEGIN_ALLOW_THREADS(context);
mpq_div(result->q, tempx->q, tempy->q);
mpz_fdiv_q(tempz->z, mpq_numref(result->q), mpq_denref(result->q));
/* Need to calculate x - tempz * y. */
mpq_set_z(result->q, tempz->z);
mpq_mul(result->q, result->q, tempy->q);
mpq_sub(result->q, tempx->q, result->q);
GMPY_MAYBE_END_ALLOW_THREADS(context);
Py_DECREF((PyObject*)tempx);
Py_DECREF((PyObject*)tempy);
Py_DECREF((PyObject*)tempz);
return (PyObject*)result;
}
/* LCOV_EXCL_START */
Py_DECREF((PyObject*)result);
TYPE_ERROR("mod() argument type not supported");
return NULL;
/* LCOV_EXCL_STOP */
}
static PyObject *
GMPy_Real_ModWithType(PyObject *x, int xtype, PyObject *y, int ytype,
CTXT_Object *context)
{
MPFR_Object *tempx = NULL, *tempy = NULL, *result = NULL;
CHECK_CONTEXT(context);
if (!(result = GMPy_MPFR_New(0, context))) {
/* LCOV_EXCL_START */
return NULL;
/* LCOV_EXCL_STOP */
}
if (IS_TYPE_REAL(xtype) && IS_TYPE_REAL(ytype)) {
if (!(tempx = GMPy_MPFR_From_RealWithType(x, xtype, 1, context)) ||
!(tempy = GMPy_MPFR_From_RealWithType(y, ytype, 1, context))) {
/* LCOV_EXCL_START */
goto error;
/* LCOV_EXCL_STOP */
}
if (mpfr_zero_p(tempy->f)) {
context->ctx.divzero = 1;
if (context->ctx.traps & TRAP_DIVZERO) {
GMPY_DIVZERO("mod() modulo by zero");
goto error;
}
}
mpfr_clear_flags();
if (mpfr_nan_p(tempx->f) || mpfr_nan_p(tempy->f) || mpfr_inf_p(tempx->f)) {
context->ctx.invalid = 1;
if (context->ctx.traps & TRAP_INVALID) {
GMPY_INVALID("mod() invalid operation");
goto error;
}
mpfr_set_nan(result->f);
}
else if (mpfr_inf_p(tempy->f)) {
context->ctx.invalid = 1;
if (context->ctx.traps & TRAP_INVALID) {
GMPY_INVALID("mod() invalid operation");
goto error;
}
if (mpfr_signbit(tempy->f)) {
mpfr_set_inf(result->f, -1);
}
else {
result->rc = mpfr_set(result->f, tempx->f,
GET_MPFR_ROUND(context));
}
}
else {
mpfr_fmod(result->f, tempx->f, tempy->f, GET_MPFR_ROUND(context));
if (!mpfr_zero_p(result->f)) {
if ((mpfr_sgn(tempy->f) < 0) != (mpfr_sgn(result->f) < 0)) {
mpfr_add(result->f, result->f, tempy->f, GET_MPFR_ROUND(context));
}
}
else {
mpfr_copysign(result->f, result->f, tempy->f, GET_MPFR_ROUND(context));
}
}
_GMPy_MPFR_Cleanup(&result, context);
Py_DECREF((PyObject*)tempx);
Py_DECREF((PyObject*)tempy);
return (PyObject*)result;
}
/* LCOV_EXCL_START */
Py_DECREF((PyObject*)result);
TYPE_ERROR("mod() argument type not supported");
return NULL;
/* LCOV_EXCL_STOP */
error:
Py_XDECREF((PyObject*)tempx);
Py_XDECREF((PyObject*)tempy);
Py_DECREF((PyObject*)result);
return NULL;
}
static PyObject *
GMPy_Complex_ModWithType(PyObject *x, int xtype, PyObject *y, int ytype,
CTXT_Object *context)
{
TYPE_ERROR("can't take mod of complex number");
return NULL;
}
static PyObject *
GMPy_Number_Mod_Slot(PyObject *x, PyObject *y)
{
int xtype = GMPy_ObjectType(x);
int ytype = GMPy_ObjectType(y);
if (IS_TYPE_INTEGER(xtype) && IS_TYPE_INTEGER(ytype))
return GMPy_Integer_ModWithType(x, xtype, y, ytype, NULL);
if (IS_TYPE_RATIONAL(xtype) && IS_TYPE_RATIONAL(ytype))
return GMPy_Rational_ModWithType(x, xtype, y, ytype, NULL);
if (IS_TYPE_REAL(xtype) && IS_TYPE_REAL(ytype))
return GMPy_Real_ModWithType(x, xtype, y, ytype, NULL);
if (IS_TYPE_COMPLEX(xtype) && IS_TYPE_COMPLEX(ytype))
return GMPy_Complex_ModWithType(x, xtype, y, ytype, NULL);
Py_RETURN_NOTIMPLEMENTED;
}
PyDoc_STRVAR(GMPy_doc_mod,
"mod(x, y, /) -> mpz|mpq|mpfr\n\n"
"Return mod(x, y).\n"
"Note: overflow, underflow, and inexact exceptions are not supported for\n"
"mpfr arguments to mod().");
static PyObject *
GMPy_Number_Mod(PyObject *x, PyObject *y, CTXT_Object *context)
{
int xtype = GMPy_ObjectType(x);
int ytype = GMPy_ObjectType(y);
if (IS_TYPE_INTEGER(xtype) && IS_TYPE_INTEGER(ytype))
return GMPy_Integer_ModWithType(x, xtype, y, ytype, context);
if (IS_TYPE_RATIONAL(xtype) && IS_TYPE_RATIONAL(ytype))
return GMPy_Rational_ModWithType(x, xtype, y, ytype, context);
if (IS_TYPE_REAL(xtype) && IS_TYPE_REAL(ytype))
return GMPy_Real_ModWithType(x, xtype, y, ytype, context);
if (IS_TYPE_COMPLEX(xtype) && IS_TYPE_COMPLEX(ytype))
return GMPy_Complex_ModWithType(x, xtype, y, ytype, context);
TYPE_ERROR("mod() argument type not supported");
return NULL;
}
PyDoc_STRVAR(GMPy_doc_context_mod,
"context.mod(x, y, /) -> mpz|mpq|mpfr\n\n"
"Return mod(x, y).\n"
"Note: overflow, underflow, and inexact exceptions are not supported for\n"
"`mpfr` arguments.");
static PyObject *
GMPy_Context_Mod(PyObject *self, PyObject *args)
{
CTXT_Object *context = NULL;
if (PyTuple_GET_SIZE(args) != 2) {
TYPE_ERROR("mod() requires 2 arguments");
return NULL;
}
if (self && CTXT_Check(self)) {
context = (CTXT_Object*)self;
}
else {
CHECK_CONTEXT(context);
}
return GMPy_Number_Mod(PyTuple_GET_ITEM(args, 0),
PyTuple_GET_ITEM(args, 1),
context);
}
././@PaxHeader 0000000 0000000 0000000 00000000026 00000000000 010213 x ustar 00 22 mtime=1710307256.0
gmpy2-2.2.1/src/gmpy2_mod.h 0000644 0001750 0001750 00000005301 14574233670 014071 0 ustar 00case case /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* gmpy2_mod.h *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Python interface to the GMP, MPFR, and MPC multiple precision *
* libraries. *
* *
* Copyright 2000 - 2009 Alex Martelli *
* *
* Copyright 2008 - 2024 Case Van Horsen *
* *
* This file is part of GMPY2. *
* *
* GMPY2 is free software: you can redistribute it and/or modify it under *
* the terms of the GNU Lesser General Public License as published by the *
* Free Software Foundation, either version 3 of the License, or (at your *
* option) any later version. *
* *
* GMPY2 is distributed in the hope that it will be useful, but WITHOUT *
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or *
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public *
* License for more details. *
* *
* You should have received a copy of the GNU Lesser General Public *
* License along with GMPY2; if not, see *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
#ifndef GMPY2_MOD_H
#define GMPY2_MOD_H
#ifdef __cplusplus
extern "C" {
#endif
/* Public API */
static PyObject * GMPy_Number_Mod(PyObject *x, PyObject *y, CTXT_Object *context);
/* Private API */
static PyObject * GMPy_Integer_ModWithType(PyObject *x, int xtype, PyObject *y, int ytype, CTXT_Object *context);
static PyObject * GMPy_Rational_ModWithType(PyObject *x, int xtype, PyObject *y, int ytype, CTXT_Object *context);
static PyObject * GMPy_Real_ModWithType(PyObject *x, int xtype, PyObject *y, int ytype, CTXT_Object *context);
static PyObject * GMPy_Complex_ModWithType(PyObject *x, int xtype, PyObject *y, int ytype, CTXT_Object *context);
static PyObject * GMPy_Number_Mod_Slot(PyObject *x, PyObject *y);
static PyObject * GMPy_Context_Mod(PyObject *self, PyObject *args);
#ifdef __cplusplus
}
#endif
#endif
././@PaxHeader 0000000 0000000 0000000 00000000026 00000000000 010213 x ustar 00 22 mtime=1718253275.0
gmpy2-2.2.1/src/gmpy2_mpc.c 0000644 0001750 0001750 00000023257 14632473333 014073 0 ustar 00case case /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* gmpy2_mpc.c *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Python interface to the GMP, MPFR, and MPC multiple precision *
* libraries. *
* *
* Copyright 2000 - 2009 Alex Martelli *
* *
* Copyright 2008 - 2024 Case Van Horsen *
* *
* This file is part of GMPY2. *
* *
* GMPY2 is free software: you can redistribute it and/or modify it under *
* the terms of the GNU Lesser General Public License as published by the *
* Free Software Foundation, either version 3 of the License, or (at your *
* option) any later version. *
* *
* GMPY2 is distributed in the hope that it will be useful, but WITHOUT *
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or *
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public *
* License for more details. *
* *
* You should have received a copy of the GNU Lesser General Public *
* License along with GMPY2; if not, see *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
static void
_GMPy_MPC_Cleanup(MPC_Object **v, CTXT_Object *ctext)
{
/* GMPY_MPC_CHECK_RANGE(V, CTX) */
{
int rcr, rci;
rcr = MPC_INEX_RE((*v)->rc);
rci = MPC_INEX_IM((*v)->rc);
if (mpfr_regular_p(mpc_realref((*v)->c)) &&
(!((mpc_realref((*v)->c)->_mpfr_exp >= ctext->ctx.emin) &&
(mpc_realref((*v)->c)->_mpfr_exp <= ctext->ctx.emax)))) {
mpfr_exp_t _oldemin, _oldemax;
_oldemin = mpfr_get_emin();
_oldemax = mpfr_get_emax();
mpfr_set_emin(ctext->ctx.emin);
mpfr_set_emax(ctext->ctx.emax);
rcr = mpfr_check_range(mpc_realref((*v)->c), rcr, GET_REAL_ROUND(ctext));
mpfr_set_emin(_oldemin);
mpfr_set_emax(_oldemax);
}
if (mpfr_regular_p(mpc_imagref((*v)->c)) &&
(!((mpc_imagref((*v)->c)->_mpfr_exp >= ctext->ctx.emin) &&
(mpc_imagref((*v)->c)->_mpfr_exp <= ctext->ctx.emax)))) {
mpfr_exp_t _oldemin, _oldemax;
_oldemin = mpfr_get_emin();
_oldemax = mpfr_get_emax();
mpfr_set_emin(ctext->ctx.emin);
mpfr_set_emax(ctext->ctx.emax);
rci = mpfr_check_range(mpc_imagref((*v)->c), rci, GET_IMAG_ROUND(ctext));
mpfr_set_emin(_oldemin);
mpfr_set_emax(_oldemax);
}
(*v)->rc = MPC_INEX(rcr, rci);
}
/* GMPY_MPC_SUBNORMALIZE(V, CTX) */
{
int rcr, rci;
rcr = MPC_INEX_RE((*v)->rc);
rci = MPC_INEX_IM((*v)->rc);
if (ctext->ctx.subnormalize &&
(!((mpc_realref((*v)->c)->_mpfr_exp >= ctext->ctx.emin) &&
(mpc_realref((*v)->c)->_mpfr_exp <= ctext->ctx.emin + mpfr_get_prec(mpc_realref((*v)->c)) - 2)))) {
mpfr_exp_t _oldemin, _oldemax;
_oldemin = mpfr_get_emin();
_oldemax = mpfr_get_emax();
mpfr_set_emin(ctext->ctx.emin);
mpfr_set_emax(ctext->ctx.emax);
rcr = mpfr_subnormalize(mpc_realref((*v)->c), rcr, GET_REAL_ROUND(ctext));
mpfr_set_emin(_oldemin);
mpfr_set_emax(_oldemax);
}
if (ctext->ctx.subnormalize &&
(!((mpc_imagref((*v)->c)->_mpfr_exp >= ctext->ctx.emin) &&
(mpc_imagref((*v)->c)->_mpfr_exp <= ctext->ctx.emin + mpfr_get_prec(mpc_imagref((*v)->c)) - 2)))) {
mpfr_exp_t _oldemin, _oldemax;
_oldemin = mpfr_get_emin();
_oldemax = mpfr_get_emax();
mpfr_set_emin(ctext->ctx.emin);
mpfr_set_emax(ctext->ctx.emax);
rci = mpfr_check_range(mpc_imagref((*v)->c), rci, GET_IMAG_ROUND(ctext));
mpfr_set_emin(_oldemin);
mpfr_set_emax(_oldemax);
}
(*v)->rc = MPC_INEX(rcr, rci);
}
/* GMPY_MPC_EXCEPTIONS(V, CTX) */
{
int _invalid = 0, _underflow = 0, _overflow = 0, _inexact = 0;
int rcr, rci;
rcr = MPC_INEX_RE((*v)->rc);
rci = MPC_INEX_IM((*v)->rc);
if (MPC_IS_NAN_P(*v)) {
ctext->ctx.invalid = 1;
_invalid = 1;
}
if ((*v)->rc) {
ctext->ctx.inexact = 1;
_inexact = 1;
}
if ((rcr && mpfr_zero_p(mpc_realref((*v)->c))) || (rci && mpfr_zero_p(mpc_imagref((*v)->c)))) {
ctext->ctx.underflow = 1;
_underflow = 1;
}
if ((rcr && mpfr_inf_p(mpc_realref((*v)->c))) || (rci && mpfr_inf_p(mpc_imagref((*v)->c)))) {
ctext->ctx.overflow = 1;
_overflow = 1;
}
if (ctext->ctx.traps) {
if ((ctext->ctx.traps & TRAP_UNDERFLOW) && _underflow) { \
GMPY_UNDERFLOW("underflow");
Py_XDECREF((PyObject*)(*v));
(*v) = NULL;
}
if ((ctext->ctx.traps & TRAP_OVERFLOW) && _overflow) {
GMPY_OVERFLOW("overflow");
Py_XDECREF((PyObject*)(*v));
(*v) = NULL;
}
if ((ctext->ctx.traps & TRAP_INEXACT) && _inexact) {
GMPY_INEXACT("inexact result");
Py_XDECREF((PyObject*)(*v));
(*v) = NULL;
}
if ((ctext->ctx.traps & TRAP_INVALID) && _invalid) {
GMPY_INVALID("invalid operation");
Py_XDECREF((PyObject*)(*v));
(*v) = NULL;
}
}
}
}
PyDoc_STRVAR(GMPy_doc_mpc,
"mpc(c=0, /, precision=0)\n"
"mpc(c=0, /, precision, context)\n"
"mpc(real, /, imag=0, precision=0)\n"
"mpc(real, /, imag, precision, context)\n"
"mpc(s, /, precision=0, base=10)\n"
"mpc(s, /, precision, base, context)\n\n"
"Return a complex floating-point number constructed from a numeric value\n"
"c or from a pair of two non-complex numbers real and imag or from a\n"
"string s made of digits in the given base.\n\n"
"A string can be possibly with real-part and/or imaginary-part (that\n"
"have 'j' as a suffix), separated by '+' and parsed the same as the\n"
"`mpfr` constructor does (but the base must be up to 36).\n\n"
"The precision can be specified by either a single number that is used\n"
"for both the real and imaginary components, or as a pair of different\n"
"precisions for the real and imaginary components. For every component,\n"
"the meaning of its precision value is the same as in the `mpfr`\n"
"type constructor.");
static PyMethodDef Pympc_methods[] =
{
{ "__complex__", GMPy_PyComplex_From_MPC, METH_NOARGS, GMPy_doc_mpc_complex },
{ "__format__", GMPy_MPC_Format, METH_VARARGS, GMPy_doc_mpc_format },
{ "__sizeof__", GMPy_MPC_SizeOf_Method, METH_NOARGS, GMPy_doc_mpc_sizeof_method },
{ "conjugate", GMPy_MPC_Conjugate_Method, METH_NOARGS, GMPy_doc_mpc_conjugate_method },
{ "digits", GMPy_MPC_Digits_Method, METH_VARARGS, GMPy_doc_mpc_digits_method },
{ "is_finite", GMPy_Number_Method_Is_Finite, METH_NOARGS, GMPy_doc_method_is_finite },
{ "is_infinite", GMPy_Number_Method_Is_Infinite, METH_NOARGS, GMPy_doc_method_is_infinite },
{ "is_nan", GMPy_Number_Method_Is_NAN, METH_NOARGS, GMPy_doc_method_is_nan },
{ "is_zero", GMPy_Number_Method_Is_Zero, METH_NOARGS, GMPy_doc_method_is_zero },
{ NULL }
};
static PyNumberMethods mpc_number_methods =
{
.nb_add = (binaryfunc) GMPy_Number_Add_Slot,
.nb_subtract = (binaryfunc) GMPy_Number_Sub_Slot,
.nb_multiply = (binaryfunc) GMPy_Number_Mul_Slot,
.nb_remainder = (binaryfunc) GMPy_Number_Mod_Slot,
.nb_divmod = (binaryfunc) GMPy_Number_DivMod_Slot,
.nb_power = (ternaryfunc) GMPy_Number_Pow_Slot,
.nb_negative = (unaryfunc) GMPy_MPC_Minus_Slot,
.nb_positive = (unaryfunc) GMPy_MPC_Plus_Slot,
.nb_absolute = (unaryfunc) GMPy_MPC_Abs_Slot,
.nb_bool = (inquiry) GMPy_MPC_NonZero_Slot,
.nb_int = (unaryfunc) GMPy_MPC_Int_Slot,
.nb_float = (unaryfunc) GMPy_MPC_Float_Slot,
.nb_floor_divide = (binaryfunc) GMPy_Number_FloorDiv_Slot,
.nb_true_divide = (binaryfunc) GMPy_Number_TrueDiv_Slot,
};
static PyGetSetDef Pympc_getseters[] =
{
{"precision", (getter)GMPy_MPC_GetPrec_Attrib, NULL, "precision in bits", NULL},
{"rc", (getter)GMPy_MPC_GetRc_Attrib, NULL, "return code", NULL},
{"imag", (getter)GMPy_MPC_GetImag_Attrib, NULL, "imaginary component", NULL},
{"real", (getter)GMPy_MPC_GetReal_Attrib, NULL, "real component", NULL},
{NULL}
};
static PyTypeObject MPC_Type =
{
PyVarObject_HEAD_INIT(NULL, 0)
.tp_name = "mpc",
.tp_basicsize = sizeof(MPC_Object),
.tp_dealloc = (destructor) GMPy_MPC_Dealloc,
.tp_repr = (reprfunc) GMPy_MPC_Repr_Slot,
.tp_as_number = &mpc_number_methods,
.tp_hash = (hashfunc) GMPy_MPC_Hash_Slot,
.tp_str = (reprfunc) GMPy_MPC_Str_Slot,
.tp_flags = Py_TPFLAGS_DEFAULT,
.tp_doc = GMPy_doc_mpc,
.tp_richcompare = (richcmpfunc)&GMPy_RichCompare_Slot,
.tp_methods = Pympc_methods,
.tp_getset = Pympc_getseters,
.tp_new = GMPy_MPC_NewInit,
};
././@PaxHeader 0000000 0000000 0000000 00000000026 00000000000 010213 x ustar 00 22 mtime=1710307256.0
gmpy2-2.2.1/src/gmpy2_mpc.h 0000644 0001750 0001750 00000017242 14574233670 014100 0 ustar 00case case /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* gmpy2_mpc.h *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Python interface to the GMP, MPFR, and MPC multiple precision *
* libraries. *
* *
* Copyright 2000 - 2009 Alex Martelli *
* *
* Copyright 2008 - 2024 Case Van Horsen *
* *
* This file is part of GMPY2. *
* *
* GMPY2 is free software: you can redistribute it and/or modify it under *
* the terms of the GNU Lesser General Public License as published by the *
* Free Software Foundation, either version 3 of the License, or (at your *
* option) any later version. *
* *
* GMPY2 is distributed in the hope that it will be useful, but WITHOUT *
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or *
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public *
* License for more details. *
* *
* You should have received a copy of the GNU Lesser General Public *
* License along with GMPY2; if not, see *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
#ifndef GMPY_MPC_H
#define GMPY_MPC_H
#ifdef __cplusplus
extern "C" {
#endif
/* gmpy_mpc C API extension header file.
*
* Provide interface to the MPC (Multiple Precision Complex) library.
*
* Version 2.00, April 2011 (created) casevh
*
* This file is expected to be included from gmpy.h
*/
#if defined(MS_WIN32) && defined(_MSC_VER)
# pragma comment(lib,"mpc.lib")
#endif
static PyTypeObject MPC_Type;
#define MPC_Check(v) (((PyObject*)v)->ob_type == &MPC_Type)
/*
* Define macros for comparing with zero, checking if either component is
* 'nan' or 'inf', etc. Based on the macros found in mpc-impl.h.
*/
#define MPC_IS_ZERO_P(x) \
(mpfr_zero_p(mpc_realref(MPC(x))) && \
mpfr_zero_p(mpc_imagref(MPC(x))))
#define MPC_IS_NAN_P(x) \
((mpfr_nan_p(mpc_realref(MPC(x))) && !mpfr_inf_p(mpc_imagref(MPC(x)))) || \
(mpfr_nan_p(mpc_imagref(MPC(x))) && !mpfr_inf_p(mpc_realref(MPC(x)))))
#define MPC_IS_INF_P(x) \
(mpfr_inf_p(mpc_realref(MPC(x))) || \
mpfr_inf_p(mpc_imagref(MPC(x))))
#define MPC_IS_FINITE_P(x) \
(mpfr_number_p(mpc_realref(MPC(x))) && \
mpfr_number_p(mpc_imagref(MPC(x))))
/* V is the value that is expected to be returned.
* CTX is the context.
* NAME is prepended to the error message.
*/
#define GMPY_MPC_CHECK_RANGE(V, CTX) \
{ \
int rcr, rci; \
rcr = MPC_INEX_RE(V->rc); \
rci = MPC_INEX_IM(V->rc); \
if (mpfr_regular_p(mpc_realref(V->c)) && \
(!((mpc_realref(V->c)->_mpfr_exp >= CTX->ctx.emin) && \
(mpc_realref(V->c)->_mpfr_exp <= CTX->ctx.emax)))) { \
mpfr_exp_t _oldemin, _oldemax; \
_oldemin = mpfr_get_emin(); \
_oldemax = mpfr_get_emax(); \
mpfr_set_emin(CTX->ctx.emin); \
mpfr_set_emax(CTX->ctx.emax); \
rcr = mpfr_check_range(mpc_realref(V->c), rcr, GET_REAL_ROUND(CTX)); \
mpfr_set_emin(_oldemin); \
mpfr_set_emax(_oldemax); \
} \
if (mpfr_regular_p(mpc_imagref(V->c)) && \
(!((mpc_imagref(V->c)->_mpfr_exp >= CTX->ctx.emin) && \
(mpc_imagref(V->c)->_mpfr_exp <= CTX->ctx.emax)))) { \
mpfr_exp_t _oldemin, _oldemax; \
_oldemin = mpfr_get_emin(); \
_oldemax = mpfr_get_emax(); \
mpfr_set_emin(CTX->ctx.emin); \
mpfr_set_emax(CTX->ctx.emax); \
rci = mpfr_check_range(mpc_imagref(V->c), rci, GET_IMAG_ROUND(CTX)); \
mpfr_set_emin(_oldemin); \
mpfr_set_emax(_oldemax); \
} \
V->rc = MPC_INEX(rcr, rci); \
}
#define GMPY_MPC_SUBNORMALIZE(V, CTX) \
{ \
int rcr, rci; \
rcr = MPC_INEX_RE(V->rc); \
rci = MPC_INEX_IM(V->rc); \
if (CTX->ctx.subnormalize && \
(!((mpc_realref(V->c)->_mpfr_exp >= CTX->ctx.emin) && \
(mpc_realref(V->c)->_mpfr_exp <= CTX->ctx.emin + mpfr_get_prec(mpc_realref(V->c)) - 2)))) { \
mpfr_exp_t _oldemin, _oldemax; \
_oldemin = mpfr_get_emin(); \
_oldemax = mpfr_get_emax(); \
mpfr_set_emin(CTX->ctx.emin); \
mpfr_set_emax(CTX->ctx.emax); \
rcr = mpfr_subnormalize(mpc_realref(V->c), rcr, GET_REAL_ROUND(CTX)); \
mpfr_set_emin(_oldemin); \
mpfr_set_emax(_oldemax); \
} \
if (CTX->ctx.subnormalize && \
(!((mpc_imagref(V->c)->_mpfr_exp >= CTX->ctx.emin) && \
(mpc_imagref(V->c)->_mpfr_exp <= CTX->ctx.emin + mpfr_get_prec(mpc_imagref(V->c)) - 2)))) { \
mpfr_exp_t _oldemin, _oldemax; \
_oldemin = mpfr_get_emin(); \
_oldemax = mpfr_get_emax(); \
mpfr_set_emin(CTX->ctx.emin); \
mpfr_set_emax(CTX->ctx.emax); \
rci = mpfr_check_range(mpc_imagref(V->c), rci, GET_IMAG_ROUND(CTX)); \
mpfr_set_emin(_oldemin); \
mpfr_set_emax(_oldemax); \
} \
V->rc = MPC_INEX(rcr, rci); \
}
#define GMPY_MPC_EXCEPTIONS(V, CTX) \
do { \
int _invalid = 0, _underflow = 0, _overflow = 0, _inexact = 0; \
int rcr, rci; \
rcr = MPC_INEX_RE(V->rc); \
rci = MPC_INEX_IM(V->rc); \
if (MPC_IS_NAN_P(V)) { \
CTX->ctx.invalid = 1; \
_invalid = 1; \
} \
if (V->rc) { \
CTX->ctx.inexact = 1; \
_inexact = 1; \
} \
if ((rcr && mpfr_zero_p(mpc_realref(V->c))) || (rci && mpfr_zero_p(mpc_imagref(V->c)))) { \
CTX->ctx.underflow = 1; \
_underflow = 1; \
} \
if ((rcr && mpfr_inf_p(mpc_realref(V->c))) || (rci && mpfr_inf_p(mpc_imagref(V->c)))) { \
CTX->ctx.overflow = 1; \
_overflow = 1; \
} \
if (CTX->ctx.traps) { \
if ((CTX->ctx.traps & TRAP_UNDERFLOW) && _underflow) { \
GMPY_UNDERFLOW("underflow"); \
Py_XDECREF((PyObject*)V); \
V = NULL; \
} \
if ((CTX->ctx.traps & TRAP_OVERFLOW) && _overflow) { \
GMPY_OVERFLOW("overflow"); \
Py_XDECREF((PyObject*)V); \
V = NULL; \
} \
if ((CTX->ctx.traps & TRAP_INEXACT) && _inexact) { \
GMPY_INEXACT("inexact result"); \
Py_XDECREF((PyObject*)V); \
V = NULL; \
} \
if ((CTX->ctx.traps & TRAP_INVALID) && _invalid) { \
GMPY_INVALID("invalid operation"); \
Py_XDECREF((PyObject*)V); \
V = NULL; \
} \
} \
} while(0); \
#define GMPY_MPC_CLEANUP(V, CTX) \
GMPY_MPC_CHECK_RANGE(V, CTX); \
GMPY_MPC_SUBNORMALIZE(V, CTX); \
GMPY_MPC_EXCEPTIONS(V, CTX); \
static void _GMPy_MPC_Cleanup(MPC_Object **v, CTXT_Object *ctext);
#ifdef __cplusplus
}
#endif
#endif
././@PaxHeader 0000000 0000000 0000000 00000000026 00000000000 010213 x ustar 00 22 mtime=1710307256.0
gmpy2-2.2.1/src/gmpy2_mpc_misc.c 0000644 0001750 0001750 00000032342 14574233670 015104 0 ustar 00case case /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* gmpy2_mpc_misc.c *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Python interface to the GMP, MPFR, and MPC multiple precision *
* libraries. *
* *
* Copyright 2000 - 2009 Alex Martelli *
* *
* Copyright 2008 - 2024 Case Van Horsen *
* *
* This file is part of GMPY2. *
* *
* GMPY2 is free software: you can redistribute it and/or modify it under *
* the terms of the GNU Lesser General Public License as published by the *
* Free Software Foundation, either version 3 of the License, or (at your *
* option) any later version. *
* *
* GMPY2 is distributed in the hope that it will be useful, but WITHOUT *
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or *
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public *
* License for more details. *
* *
* You should have received a copy of the GNU Lesser General Public *
* License along with GMPY2; if not, see *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
PyDoc_STRVAR(GMPy_doc_context_phase,
"context.phase(x, /) -> mpfr\n\n"
"Return the phase angle, also known as argument, of a complex x.");
PyDoc_STRVAR(GMPy_doc_function_phase,
"phase(x, /) -> mpfr\n\n"
"Return the phase angle, also known as argument, of a complex x.");
static PyObject *
GMPy_Complex_Phase(PyObject *x, CTXT_Object *context)
{
MPFR_Object *result = NULL;
MPC_Object *tempx = NULL;
CHECK_CONTEXT(context)
if (!(IS_COMPLEX_ONLY(x))) {
TYPE_ERROR("phase() argument type not supported");
return NULL;
}
result = GMPy_MPFR_New(0, context);
tempx = GMPy_MPC_From_Complex(x, 1, 1, context);
if (!result || !tempx) {
Py_XDECREF(result);
Py_XDECREF(tempx);
return NULL;
}
mpfr_clear_flags();
result->rc = mpc_arg(result->f, tempx->c, GET_MPFR_ROUND(context));
Py_DECREF((PyObject*)tempx);
_GMPy_MPFR_Cleanup(&result, context);
return (PyObject*)result;
}
static PyObject *
GMPy_Context_Phase(PyObject *self, PyObject *other)
{
CTXT_Object *context = NULL;
if (self && CTXT_Check(self)) {
context = (CTXT_Object*)self;
}
else {
CHECK_CONTEXT(context);
}
return GMPy_Complex_Phase(other, context);
}
PyDoc_STRVAR(GMPy_doc_context_root_of_unity,
"context.root_of_unity(n, k, /) -> mpc\n\n"
"Return the n-th root of mpc(1) raised to the k-th power..");
PyDoc_STRVAR(GMPy_doc_function_root_of_unity,
"root_of_unity(n, k, /) -> mpc\n\n"
"Return the n-th root of mpc(1) raised to the k-th power..");
static PyObject *
GMPy_Complex_Root_Of_Unity(PyObject *n, PyObject *k, CTXT_Object *context)
{
MPC_Object *result;
unsigned long n_val, k_val;
CHECK_CONTEXT(context)
result = GMPy_MPC_New(0, 0, context);
if (!result) {
return NULL;
}
n_val = GMPy_Integer_AsUnsignedLong(n);
k_val = GMPy_Integer_AsUnsignedLong(k);
if ((n_val == (unsigned long)(-1) && PyErr_Occurred()) ||
(k_val == (unsigned long)(-1) && PyErr_Occurred())) {
Py_DECREF((PyObject*)result);
VALUE_ERROR("root_of_unity() requires positive integer arguments.");
return NULL;
}
result->rc = mpc_rootofunity(result->c, n_val, k_val, GET_MPC_ROUND(context));
_GMPy_MPC_Cleanup(&result, context);
return (PyObject*)result;
}
static PyObject *
GMPy_Context_Root_Of_Unity(PyObject *self, PyObject *args)
{
PyObject *n, *k;
CTXT_Object *context = NULL;
if (PyTuple_GET_SIZE(args) != 2) {
TYPE_ERROR("root_of_unity() requires 2 arguments");
return NULL;
}
if (self && CTXT_Check(self)) {
context = (CTXT_Object*)self;
}
else {
CHECK_CONTEXT(context);
}
n = PyTuple_GET_ITEM(args, 0);
k = PyTuple_GET_ITEM(args, 1);
if (IS_INTEGER(n) && IS_INTEGER(k)) {
return GMPy_Complex_Root_Of_Unity(n, k, context);
}
else {
TYPE_ERROR("root_of_unity() requires integer arguments");
return NULL;
}
}
PyDoc_STRVAR(GMPy_doc_context_norm,
"context.norm(x, /) -> mpfr\n\n"
"Return the norm of a complex x. The norm(x) is defined as\n"
"x.real**2 + x.imag**2. abs(x) is the square root of norm(x).\n");
PyDoc_STRVAR(GMPy_doc_function_norm,
"norm(x, /) -> mpfr\n\n"
"Return the norm of a complex x. The norm(x) is defined as\n"
"x.real**2 + x.imag**2. abs(x) is the square root of norm(x).\n");
static PyObject *
GMPy_Complex_Norm(PyObject *x, CTXT_Object *context)
{
MPFR_Object *result = NULL;
MPC_Object *tempx = NULL;
CHECK_CONTEXT(context);
if (!(IS_COMPLEX_ONLY(x))) {
TYPE_ERROR("norm() argument type not supported");
return NULL;
}
result = GMPy_MPFR_New(0, context);
tempx = GMPy_MPC_From_Complex(x, 1, 1, context);
if (!result || !tempx) {
Py_XDECREF(result);
Py_XDECREF(tempx);
return NULL;
}
mpfr_clear_flags();
result->rc = mpc_norm(result->f, tempx->c, GET_MPFR_ROUND(context));
Py_DECREF((PyObject*)tempx);
_GMPy_MPFR_Cleanup(&result, context);
return (PyObject*)result;
}
static PyObject *
GMPy_Context_Norm(PyObject *self, PyObject *other)
{
CTXT_Object *context = NULL;
if (self && CTXT_Check(self)) {
context = (CTXT_Object*)self;
}
else {
CHECK_CONTEXT(context);
}
return GMPy_Complex_Norm(other, context);
}
PyDoc_STRVAR(GMPy_doc_context_polar,
"context.polar(x, /) -> tuple[mpfr, mpfr]\n\n"
"Return the polar coordinate form of a complex x that is in\n"
"rectangular form.");
PyDoc_STRVAR(GMPy_doc_function_polar,
"polar(x, /) -> tuple[mpfr, mpfr]\n\n"
"Return the polar coordinate form of a complex x that is in\n"
"rectangular form.");
static PyObject *
GMPy_Complex_Polar(PyObject *x, CTXT_Object *context)
{
PyObject *tempx, *abs, *phase, *result;
CHECK_CONTEXT(context);
if (!(IS_COMPLEX_ONLY(x))) {
TYPE_ERROR("polar() argument type not supported");
return NULL;
}
if (!(tempx = (PyObject*)GMPy_MPC_From_Complex(x, 1, 1, context))) {
return NULL;
}
abs = GMPy_Complex_AbsWithType(tempx, OBJ_TYPE_MPC, context);
phase = GMPy_Complex_Phase(tempx, context);
Py_DECREF(tempx);
result = PyTuple_New(2);
if (!abs || !phase || !result) {
Py_XDECREF(abs);
Py_XDECREF(phase);
Py_XDECREF(result);
return NULL;
}
PyTuple_SET_ITEM(result, 0, abs);
PyTuple_SET_ITEM(result, 1, phase);
return result;
}
static PyObject *
GMPy_Context_Polar(PyObject *self, PyObject *other)
{
CTXT_Object *context = NULL;
if (self && CTXT_Check(self)) {
context = (CTXT_Object*)self;
}
else {
CHECK_CONTEXT(context);
}
return GMPy_Complex_Polar(other, context);
}
PyDoc_STRVAR(GMPy_doc_context_rect,
"context.rect(r, phi, /) -> mpc\n\n"
"Return the rectangular coordinate form of a complex number that is\n"
"given in polar form.");
PyDoc_STRVAR(GMPy_doc_function_rect,
"rect(r, phi, /) -> mpc\n\n"
"Return the rectangular coordinate form of a complex number that is\n"
"given in polar form.");
static PyObject *
GMPy_Complex_Rect(PyObject *r, PyObject *phi, CTXT_Object *context)
{
MPFR_Object *tempx, *tempy;
MPC_Object *result;
CHECK_CONTEXT(context);
tempx = GMPy_MPFR_From_Real(r, 1, context);
tempy = GMPy_MPFR_From_Real(phi, 1, context);
result = GMPy_MPC_New(0, 0, context);
if (!tempx || !tempy || !result) {
Py_XDECREF((PyObject*)tempx);
Py_XDECREF((PyObject*)tempy);
Py_XDECREF((PyObject*)result);
return NULL;
}
mpfr_cos(mpc_realref(result->c), tempy->f, GET_REAL_ROUND(context));
mpfr_mul(mpc_realref(result->c), mpc_realref(result->c), tempx->f, GET_REAL_ROUND(context));
mpfr_sin(mpc_imagref(result->c), tempy->f, GET_IMAG_ROUND(context));
mpfr_mul(mpc_imagref(result->c), mpc_imagref(result->c), tempx->f, GET_IMAG_ROUND(context));
Py_DECREF((PyObject*)tempx);
Py_DECREF((PyObject*)tempy);
_GMPy_MPC_Cleanup(&result, context);
return (PyObject*)result;
}
static PyObject *
GMPy_Context_Rect(PyObject *self, PyObject *args)
{
PyObject *r, *phi;
CTXT_Object *context = NULL;
if (PyTuple_GET_SIZE(args) != 2) {
TYPE_ERROR("rect() requires 2 arguments");
return NULL;
}
if (self && CTXT_Check(self)) {
context = (CTXT_Object*)self;
}
else {
CHECK_CONTEXT(context);
}
r = PyTuple_GET_ITEM(args, 0);
phi = PyTuple_GET_ITEM(args, 1);
if (IS_REAL(r) && IS_REAL(phi)) {
return GMPy_Complex_Rect(r, phi, context);
}
else {
TYPE_ERROR("rect() argument type not supported");
return NULL;
}
}
PyDoc_STRVAR(GMPy_doc_context_proj,
"context.proj(x, /) -> mpc\n\n"
"Returns the projection of a complex x on to the Riemann sphere.");
PyDoc_STRVAR(GMPy_doc_function_proj,
"proj(x, /) -> mpc\n\n"
"Returns the projection of a complex x on to the Riemann sphere.");
static PyObject *
GMPy_Complex_Proj(PyObject *x, CTXT_Object *context)
{
MPC_Object *result = NULL, *tempx = NULL;
CHECK_CONTEXT(context);
if (!(IS_COMPLEX_ONLY(x))) {
TYPE_ERROR("proj() argument type not supported");
return NULL;
}
result = GMPy_MPC_New(0, 0, context);
tempx = GMPy_MPC_From_Complex(x, 1, 1, context);
if (!result || !tempx) {
Py_XDECREF(result);
Py_XDECREF(tempx);
return NULL;
}
mpfr_clear_flags();
result->rc = mpc_proj(result->c, tempx->c, GET_MPC_ROUND(context));
Py_DECREF((PyObject*)tempx);
_GMPy_MPC_Cleanup(&result, context);
return (PyObject*)result;
}
static PyObject *
GMPy_Context_Proj(PyObject *self, PyObject *other)
{
CTXT_Object *context = NULL;
if (self && CTXT_Check(self)) {
context = (CTXT_Object*)self;
}
else {
CHECK_CONTEXT(context);
}
return GMPy_Complex_Proj(other, context);
}
/* Implement the conjugate() method. */
PyDoc_STRVAR(GMPy_doc_mpc_conjugate_method,
"x.conjugate() -> mpc\n\n"
"Returns the conjugate of x.");
static PyObject *
GMPy_MPC_Conjugate_Method(PyObject *self, PyObject *args)
{
MPC_Object *result;
CTXT_Object *context = NULL;
CHECK_CONTEXT(context);
if (!(result = GMPy_MPC_New(0, 0, context))) {
return NULL;
}
result->rc = mpc_conj(result->c, MPC(self), GET_MPC_ROUND(context));
_GMPy_MPC_Cleanup(&result, context);
return (PyObject*)result;
}
/* Implement the .precision attribute of an mpc. */
static PyObject *
GMPy_MPC_GetPrec_Attrib(MPC_Object *self, void *closure)
{
mpfr_prec_t rprec = 0, iprec = 0;
mpc_get_prec2(&rprec, &iprec, self->c);
return Py_BuildValue("(nn)", rprec, iprec);
}
/* Implement the .rc attribute of an mpc. */
static PyObject *
GMPy_MPC_GetRc_Attrib(MPC_Object *self, void *closure)
{
return Py_BuildValue("(ii)", MPC_INEX_RE(self->rc), MPC_INEX_IM(self->rc));
}
/* Implement the .imag attribute of an mpc. */
static PyObject *
GMPy_MPC_GetImag_Attrib(MPC_Object *self, void *closure)
{
MPFR_Object *result = NULL;
CTXT_Object *context = NULL;
mpfr_prec_t rprec = 0, iprec = 0;
mpc_get_prec2(&rprec, &iprec, self->c);
CHECK_CONTEXT(context);
if ((result = GMPy_MPFR_New(iprec, context))) {
result->rc = mpc_imag(result->f, self->c, GET_MPFR_ROUND(context));
_GMPy_MPFR_Cleanup(&result, context);
}
return (PyObject*)result;
}
/* Implement the .real attribute of an mpc. */
static PyObject *
GMPy_MPC_GetReal_Attrib(MPC_Object *self, void *closure)
{
MPFR_Object *result = NULL;
CTXT_Object *context = NULL;
mpfr_prec_t rprec = 0, iprec = 0;
mpc_get_prec2(&rprec, &iprec, self->c);
CHECK_CONTEXT(context);
if ((result = GMPy_MPFR_New(rprec, context))) {
result->rc = mpc_real(result->f, self->c, context->ctx.mpfr_round);
_GMPy_MPFR_Cleanup(&result, context);
}
return (PyObject*)result;
}
/* Implement the nb_bool slot. */
static int
GMPy_MPC_NonZero_Slot(MPC_Object *self)
{
return !MPC_IS_ZERO_P(self->c);
}
PyDoc_STRVAR(GMPy_doc_mpc_sizeof_method,
"x.__sizeof__()\n\n"
"Returns the amount of memory consumed by x.");
static PyObject *
GMPy_MPC_SizeOf_Method(PyObject *self, PyObject *other)
{
return PyLong_FromSize_t(sizeof(MPC_Object) + \
(((mpc_realref(MPC(self))->_mpfr_prec + mp_bits_per_limb - 1) / \
mp_bits_per_limb) * sizeof(mp_limb_t)) + \
(((mpc_imagref(MPC(self))->_mpfr_prec + mp_bits_per_limb - 1) / \
mp_bits_per_limb) * sizeof(mp_limb_t)));
}
././@PaxHeader 0000000 0000000 0000000 00000000026 00000000000 010213 x ustar 00 22 mtime=1710307256.0
gmpy2-2.2.1/src/gmpy2_mpc_misc.h 0000644 0001750 0001750 00000007534 14574233670 015116 0 ustar 00case case /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* gmpy2_mpc_misc.h *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Python interface to the GMP, MPFR, and MPC multiple precision *
* libraries. *
* *
* Copyright 2000 - 2009 Alex Martelli *
* *
* Copyright 2008 - 2024 Case Van Horsen *
* *
* This file is part of GMPY2. *
* *
* GMPY2 is free software: you can redistribute it and/or modify it under *
* the terms of the GNU Lesser General Public License as published by the *
* Free Software Foundation, either version 3 of the License, or (at your *
* option) any later version. *
* *
* GMPY2 is distributed in the hope that it will be useful, but WITHOUT *
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or *
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public *
* License for more details. *
* *
* You should have received a copy of the GNU Lesser General Public *
* License along with GMPY2; if not, see *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
#ifndef GMPY_MPC_MISC_H
#define GMPY_MPC_MISC_H
#ifdef __cplusplus
extern "C" {
#endif
static PyObject * GMPy_Complex_Phase(PyObject *x, CTXT_Object *context);
static PyObject * GMPy_Context_Phase(PyObject *self, PyObject *other);
#ifdef MPC_110
static PyObject * GMPy_Complex_Root_Of_Unity(PyObject *n, PyObject *k, CTXT_Object *context);
static PyObject * GMPy_Context_Root_Of_Unity(PyObject *self, PyObject *args);
#endif
static PyObject * GMPy_Complex_Norm(PyObject *x, CTXT_Object *context);
static PyObject * GMPy_Context_Norm(PyObject *self, PyObject *other);
static PyObject * GMPy_Complex_Polar(PyObject *x, CTXT_Object *context);
static PyObject * GMPy_Context_Polar(PyObject *self, PyObject *other);
static PyObject * GMPy_Complex_Rect(PyObject *r, PyObject *phi, CTXT_Object *context);
static PyObject * GMPy_Context_Rect(PyObject *self, PyObject *args);
static PyObject * GMPy_Complex_Proj(PyObject *x, CTXT_Object *context);
static PyObject * GMPy_Context_Proj(PyObject *self, PyObject *other);
static PyObject * GMPy_MPC_Conjugate_Method(PyObject *self, PyObject *args);
static PyObject * GMPy_MPC_GetPrec_Attrib(MPC_Object *self, void *closure);
static PyObject * GMPy_MPC_GetRc_Attrib(MPC_Object *self, void *closure);
static PyObject * GMPy_MPC_GetImag_Attrib(MPC_Object *self, void *closure);
static PyObject * GMPy_MPC_GetReal_Attrib(MPC_Object *self, void *closure);
static int GMPy_MPC_NonZero_Slot(MPC_Object *self);
static PyObject * GMPy_MPC_SizeOf_Method(PyObject *self, PyObject *other);
static PyObject * GMPy_MPC_Conjugate_Method(PyObject *self, PyObject *args);
static PyObject * GMPy_MPC_GetPrec_Attrib(MPC_Object *self, void *closure);
static PyObject * GMPy_MPC_GetRc_Attrib(MPC_Object *self, void *closure);
static PyObject * GMPy_MPC_GetImag_Attrib(MPC_Object *self, void *closure);
static PyObject * GMPy_MPC_GetReal_Attrib(MPC_Object *self, void *closure);
static int GMPy_MPC_NonZero_Slot(MPC_Object *self);
#ifdef __cplusplus
}
#endif
#endif
././@PaxHeader 0000000 0000000 0000000 00000000026 00000000000 010213 x ustar 00 22 mtime=1718253275.0
gmpy2-2.2.1/src/gmpy2_mpfr.c 0000644 0001750 0001750 00000022607 14632473333 014256 0 ustar 00case case /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* gmpy2_mpfr.c *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Python interface to the GMP, MPFR, and MPC multiple precision *
* libraries. *
* *
* Copyright 2000 - 2009 Alex Martelli *
* *
* Copyright 2008 - 2024 Case Van Horsen *
* *
* This file is part of GMPY2. *
* *
* GMPY2 is free software: you can redistribute it and/or modify it under *
* the terms of the GNU Lesser General Public License as published by the *
* Free Software Foundation, either version 3 of the License, or (at your *
* option) any later version. *
* *
* GMPY2 is distributed in the hope that it will be useful, but WITHOUT *
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or *
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public *
* License for more details. *
* *
* You should have received a copy of the GNU Lesser General Public *
* License along with GMPY2; if not, see *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
/* General purpose functions are defined here. They are used as an alternative
* to code bloat via macro overuse.
*/
static inline void
_GMPy_MPFR_Cleanup(MPFR_Object **v, CTXT_Object *ctext)
{
/* GMPY_MPFR_CHECK_RANGE(V, CTX) */
if (mpfr_regular_p((*v)->f) &&
(!(((*v)->f->_mpfr_exp >= ctext->ctx.emin) &&
((*v)->f->_mpfr_exp <= ctext->ctx.emax)))) {
mpfr_exp_t _oldemin, _oldemax;
_oldemin = mpfr_get_emin();
_oldemax = mpfr_get_emax();
mpfr_set_emin(ctext->ctx.emin);
mpfr_set_emax(ctext->ctx.emax);
(*v)->rc = mpfr_check_range((*v)->f, (*v)->rc, GET_MPFR_ROUND(ctext));
mpfr_set_emin(_oldemin);
mpfr_set_emax(_oldemax);
}
/* GMPY_MPFR_SUBNORMALIZE(V, CTX) */
if (ctext->ctx.subnormalize &&
(*v)->f->_mpfr_exp >= ctext->ctx.emin &&
(*v)->f->_mpfr_exp <= ctext->ctx.emin + mpfr_get_prec((*v)->f) - 2) {
mpfr_exp_t _oldemin, _oldemax;
_oldemin = mpfr_get_emin();
_oldemax = mpfr_get_emax();
mpfr_set_emin(ctext->ctx.emin);
mpfr_set_emax(ctext->ctx.emax);
(*v)->rc = mpfr_subnormalize((*v)->f, (*v)->rc, GET_MPFR_ROUND(ctext));
mpfr_set_emin(_oldemin);
mpfr_set_emax(_oldemax);
}
/* GMPY_MPFR_EXCEPTIONS(V, CTX) */
ctext->ctx.underflow |= mpfr_underflow_p();
ctext->ctx.overflow |= mpfr_overflow_p();
ctext->ctx.invalid |= mpfr_nanflag_p();
ctext->ctx.inexact |= mpfr_inexflag_p();
ctext->ctx.divzero |= mpfr_divby0_p();
if (ctext->ctx.traps) {
if ((ctext->ctx.traps & TRAP_UNDERFLOW) && mpfr_underflow_p()) {
PyErr_SetString(GMPyExc_Underflow, "underflow");
Py_XDECREF((PyObject*)(*v));
(*v) = NULL;
}
if ((ctext->ctx.traps & TRAP_OVERFLOW) && mpfr_overflow_p()) {
PyErr_SetString(GMPyExc_Overflow, "overflow");
Py_XDECREF((PyObject*)(*v));
(*v) = NULL;
}
if ((ctext->ctx.traps & TRAP_INEXACT) && mpfr_inexflag_p()) {
PyErr_SetString(GMPyExc_Inexact, "inexact result");
Py_XDECREF((PyObject*)(*v));
(*v) = NULL;
}
if ((ctext->ctx.traps & TRAP_INVALID) && mpfr_nanflag_p()) {
PyErr_SetString(GMPyExc_Invalid, "invalid operation");
Py_XDECREF((PyObject*)(*v));
(*v) = NULL;
}
if ((ctext->ctx.traps & TRAP_DIVZERO) && mpfr_divby0_p()) {
PyErr_SetString(GMPyExc_DivZero, "division by zero");
Py_XDECREF((PyObject*)(*v));
(*v) = NULL;
}
}
}
PyDoc_STRVAR(GMPy_doc_mpfr,
"mpfr(n=0, /, precision=0)\n"
"mpfr(n, /, precision, context)\n"
"mpfr(s, /, precision=0, base=0)\n"
"mpfr(s, /, precision, base, context)\n\n"
"Return a floating-point number after converting a numeric value n or\n"
"a string s made of digits in the given base.\n\n"
"A string can be with fraction-part (with a period as a separator)\n"
"and/or exponent-part with an exponent marker 'e' or 'E' for bases up to\n"
"10, else '@' in any base. In bases 2 and 16, the exponent prefix can also\n"
"be 'p' or 'P', in which case the exponent indicates\n"
"a multiplication by a power of 2 instead of the base. The value of\n"
"an exponent is always written in base 10. The fractional-part digits\n"
"are parsed the same as the `mpz` type constructor\n"
"does and both the whole number and exponent-part optionally can be\n"
"preceded by ‘+’ or ‘-’. Every input, accepted by the `float` type\n"
"constructor or the `float.fromhex` method is also accepted.\n\n"
"If a precision greater than or equal to 2 is specified, then it\n"
"is used. A precision of 0 (the default) implies the precision of either\n"
"the specified context or the current context is used.\n"
"A precision of 1 minimizes the loss of precision by following\n"
"these rules:\n\n"
" 1) If n is a radix-2 floating point number, then the full\n"
" precision of n is retained.\n"
" 2) If n is an integer, then the precision is the bit length\n"
" of the integer.\n");
static PyNumberMethods mpfr_number_methods =
{
.nb_add = (binaryfunc) GMPy_Number_Add_Slot,
.nb_subtract = (binaryfunc) GMPy_Number_Sub_Slot,
.nb_multiply = (binaryfunc) GMPy_Number_Mul_Slot,
.nb_remainder = (binaryfunc) GMPy_Number_Mod_Slot,
.nb_divmod = (binaryfunc) GMPy_Number_DivMod_Slot,
.nb_power = (ternaryfunc) GMPy_Number_Pow_Slot,
.nb_negative = (unaryfunc) GMPy_MPFR_Minus_Slot,
.nb_positive = (unaryfunc) GMPy_MPFR_Plus_Slot,
.nb_absolute = (unaryfunc) GMPy_MPFR_Abs_Slot,
.nb_bool = (inquiry) GMPy_MPFR_NonZero_Slot,
.nb_int = (unaryfunc) GMPy_MPFR_Int_Slot,
.nb_float = (unaryfunc) GMPy_MPFR_Float_Slot,
.nb_floor_divide = (binaryfunc) GMPy_Number_FloorDiv_Slot,
.nb_true_divide = (binaryfunc) GMPy_Number_TrueDiv_Slot,
};
static PyGetSetDef Pympfr_getseters[] =
{
{"precision", (getter)GMPy_MPFR_GetPrec_Attrib, NULL, "precision in bits", NULL},
{"rc", (getter)GMPy_MPFR_GetRc_Attrib, NULL, "return code", NULL},
{"imag", (getter)GMPy_MPFR_GetImag_Attrib, NULL, "imaginary component", NULL},
{"real", (getter)GMPy_MPFR_GetReal_Attrib, NULL, "real component", NULL},
{"_mpf_", (getter)GMPy_MPFR_Get_Mpmath_MPF_Tuple, NULL, "return raw mpf tuple", NULL},
{NULL}
};
static PyMethodDef Pympfr_methods [] =
{
{ "__ceil__", GMPy_MPFR_Method_Ceil, METH_NOARGS, GMPy_doc_mpfr_ceil_method },
{ "__floor__", GMPy_MPFR_Method_Floor, METH_NOARGS, GMPy_doc_mpfr_floor_method },
{ "__format__", GMPy_MPFR_Format, METH_VARARGS, GMPy_doc_mpfr_format },
{ "__round__", GMPy_MPFR_Method_Round10, METH_VARARGS, GMPy_doc_method_round10 },
{ "__sizeof__", GMPy_MPFR_SizeOf_Method, METH_NOARGS, GMPy_doc_mpfr_sizeof_method },
{ "__trunc__", GMPy_MPFR_Method_Trunc, METH_NOARGS, GMPy_doc_mpfr_trunc_method },
{ "as_integer_ratio", GMPy_MPFR_Integer_Ratio_Method, METH_NOARGS, GMPy_doc_method_integer_ratio },
{ "as_mantissa_exp", GMPy_MPFR_Mantissa_Exp_Method, METH_NOARGS, GMPy_doc_method_mantissa_exp },
{ "as_simple_fraction", (PyCFunction)GMPy_MPFR_Simple_Fraction_Method, METH_VARARGS | METH_KEYWORDS, GMPy_doc_method_simple_fraction },
{ "conjugate", GMPy_MP_Method_Conjugate, METH_NOARGS, GMPy_doc_mp_method_conjugate },
{ "digits", GMPy_MPFR_Digits_Method, METH_VARARGS, GMPy_doc_mpfr_digits_method },
{ "is_finite", GMPy_Number_Method_Is_Finite, METH_NOARGS, GMPy_doc_method_is_finite },
{ "is_infinite", GMPy_Number_Method_Is_Infinite, METH_NOARGS, GMPy_doc_method_is_infinite },
{ "is_integer", GMPy_MPFR_Is_Integer_Method, METH_NOARGS, GMPy_doc_method_is_integer },
{ "is_nan", GMPy_Number_Method_Is_NAN, METH_NOARGS, GMPy_doc_method_is_nan },
{ "is_regular", GMPy_MPFR_Is_Regular_Method, METH_NOARGS, GMPy_doc_method_is_regular },
{ "is_signed", GMPy_MPFR_Is_Signed_Method, METH_NOARGS, GMPy_doc_method_is_signed },
{ "is_zero", GMPy_Number_Method_Is_Zero, METH_NOARGS, GMPy_doc_method_is_zero },
{ NULL }
};
static PyTypeObject MPFR_Type =
{
PyVarObject_HEAD_INIT(NULL, 0)
.tp_name = "gmpy2.mpfr",
.tp_basicsize = sizeof(MPFR_Object),
.tp_dealloc = (destructor) GMPy_MPFR_Dealloc,
.tp_repr = (reprfunc) GMPy_MPFR_Repr_Slot,
.tp_as_number = &mpfr_number_methods,
.tp_hash = (hashfunc) GMPy_MPFR_Hash_Slot,
.tp_str = (reprfunc) GMPy_MPFR_Str_Slot,
.tp_flags = Py_TPFLAGS_DEFAULT,
.tp_doc = GMPy_doc_mpfr,
.tp_richcompare = (richcmpfunc)&GMPy_RichCompare_Slot,
.tp_methods = Pympfr_methods,
.tp_getset = Pympfr_getseters,
.tp_new = GMPy_MPFR_NewInit,
};
././@PaxHeader 0000000 0000000 0000000 00000000026 00000000000 010213 x ustar 00 22 mtime=1710307256.0
gmpy2-2.2.1/src/gmpy2_mpfr.h 0000644 0001750 0001750 00000020120 14574233670 014252 0 ustar 00case case /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* gmpy2_mpfr.h *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Python interface to the GMP, MPFR, and MPC multiple precision *
* libraries. *
* *
* Copyright 2000 - 2009 Alex Martelli *
* *
* Copyright 2008 - 2024 Case Van Horsen *
* *
* This file is part of GMPY2. *
* *
* GMPY2 is free software: you can redistribute it and/or modify it under *
* the terms of the GNU Lesser General Public License as published by the *
* Free Software Foundation, either version 3 of the License, or (at your *
* option) any later version. *
* *
* GMPY2 is distributed in the hope that it will be useful, but WITHOUT *
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or *
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public *
* License for more details. *
* *
* You should have received a copy of the GNU Lesser General Public *
* License along with GMPY2; if not, see *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
/* gmpy_mpfr C API extension header file.
*
* Provide interface to the MPFR (Multiple Precision Floating-point with
* Rounding) library.
*
* Version 2.00, April 2011 (created) casevh
*/
#ifndef GMPY_MPFR_H
#define GMPY_MPFR_H
#ifdef __cplusplus
extern "C" {
#endif
#if !defined(FLT_RADIX) || (FLT_RADIX!=2)
# error "FLT_RADIX undefined or != 2, GMPY2 is confused. :("
#endif
#if defined(MS_WIN32) && defined(_MSC_VER)
# pragma comment(lib,"mpfr.lib")
#endif
#ifdef FAST
/* Very bad code ahead. I've copied portions of mpfr-impl.h and
* hacked them so they work. This code will only be enabled if you
* specify the --fast option.
*/
#define MPFR_THREAD_ATTR __thread
__MPFR_DECLSPEC extern MPFR_THREAD_ATTR unsigned int __gmpfr_flags;
__MPFR_DECLSPEC extern MPFR_THREAD_ATTR mpfr_exp_t __gmpfr_emin;
__MPFR_DECLSPEC extern MPFR_THREAD_ATTR mpfr_exp_t __gmpfr_emax;
/* Flags of __gmpfr_flags */
#define MPFR_FLAGS_UNDERFLOW 1
#define MPFR_FLAGS_OVERFLOW 2
#define MPFR_FLAGS_NAN 4
#define MPFR_FLAGS_INEXACT 8
#define MPFR_FLAGS_ERANGE 16
#define MPFR_FLAGS_DIVBY0 32
#define MPFR_FLAGS_ALL (MPFR_FLAGS_UNDERFLOW | \
MPFR_FLAGS_OVERFLOW | \
MPFR_FLAGS_NAN | \
MPFR_FLAGS_INEXACT | \
MPFR_FLAGS_ERANGE | \
MPFR_FLAGS_DIVBY0)
/* Replace some common functions for direct access to the global vars */
#define mpfr_get_emin() (__gmpfr_emin + 0)
#define mpfr_get_emax() (__gmpfr_emax + 0)
#define mpfr_clear_flags() ((void) (__gmpfr_flags = 0))
#define mpfr_clear_underflow() ((void) (__gmpfr_flags &= MPFR_FLAGS_ALL ^ MPFR_FLAGS_UNDERFLOW))
#define mpfr_clear_overflow() ((void) (__gmpfr_flags &= MPFR_FLAGS_ALL ^ MPFR_FLAGS_OVERFLOW))
#define mpfr_clear_nanflag() ((void) (__gmpfr_flags &= MPFR_FLAGS_ALL ^ MPFR_FLAGS_NAN))
#define mpfr_clear_inexflag() ((void) (__gmpfr_flags &= MPFR_FLAGS_ALL ^ MPFR_FLAGS_INEXACT))
#define mpfr_clear_erangeflag() ((void) (__gmpfr_flags &= MPFR_FLAGS_ALL ^ MPFR_FLAGS_ERANGE))
#define mpfr_clear_divby0() ((void) (__gmpfr_flags &= MPFR_FLAGS_ALL ^ MPFR_FLAGS_DIVBY0))
#define mpfr_underflow_p() ((int) (__gmpfr_flags & MPFR_FLAGS_UNDERFLOW))
#define mpfr_overflow_p() ((int) (__gmpfr_flags & MPFR_FLAGS_OVERFLOW))
#define mpfr_nanflag_p() ((int) (__gmpfr_flags & MPFR_FLAGS_NAN))
#define mpfr_inexflag_p() ((int) (__gmpfr_flags & MPFR_FLAGS_INEXACT))
#define mpfr_erangeflag_p() ((int) (__gmpfr_flags & MPFR_FLAGS_ERANGE))
#define mpfr_divby0_p() ((int) (__gmpfr_flags & MPFR_FLAGS_DIVBY0))
#define mpfr_check_range(x,t,r) \
((((x)->_mpfr_exp) >= __gmpfr_emin && ((x)->_mpfr_exp) <= __gmpfr_emax) \
? ((t) ? (__gmpfr_flags |= MPFR_FLAGS_INEXACT, (t)) : 0) \
: mpfr_check_range(x,t,r))
/* End of the really bad code. Hopefully.
*/
#endif
static PyTypeObject MPFR_Type;
#define MPFR_Check(v) (((PyObject*)v)->ob_type == &MPFR_Type)
#define GMPY_DIVZERO(msg) PyErr_SetString(GMPyExc_DivZero, msg)
#define GMPY_INEXACT(msg) PyErr_SetString(GMPyExc_Inexact, msg)
#define GMPY_INVALID(msg) PyErr_SetString(GMPyExc_Invalid, msg)
#define GMPY_OVERFLOW(msg) PyErr_SetString(GMPyExc_Overflow, msg)
#define GMPY_UNDERFLOW(msg) PyErr_SetString(GMPyExc_Underflow, msg)
#define GMPY_ERANGE(msg) PyErr_SetString(GMPyExc_Erange, msg)
#define GMPY_MPFR_CHECK_RANGE(V, CTX) \
if (mpfr_regular_p(V->f) && \
(!((V->f->_mpfr_exp >= CTX->ctx.emin) && \
(V->f->_mpfr_exp <= CTX->ctx.emax)))) { \
mpfr_exp_t _oldemin, _oldemax; \
_oldemin = mpfr_get_emin(); \
_oldemax = mpfr_get_emax(); \
mpfr_set_emin(CTX->ctx.emin); \
mpfr_set_emax(CTX->ctx.emax); \
V->rc = mpfr_check_range(V->f, V->rc, GET_MPFR_ROUND(CTX)); \
mpfr_set_emin(_oldemin); \
mpfr_set_emax(_oldemax); \
}
#define GMPY_MPFR_SUBNORMALIZE(V, CTX) \
if (CTX->ctx.subnormalize && \
V->f->_mpfr_exp >= CTX->ctx.emin && \
V->f->_mpfr_exp <= CTX->ctx.emin + mpfr_get_prec(V->f) - 2) { \
mpfr_exp_t _oldemin, _oldemax; \
_oldemin = mpfr_get_emin(); \
_oldemax = mpfr_get_emax(); \
mpfr_set_emin(CTX->ctx.emin); \
mpfr_set_emax(CTX->ctx.emax); \
V->rc = mpfr_subnormalize(V->f, V->rc, GET_MPFR_ROUND(CTX)); \
mpfr_set_emin(_oldemin); \
mpfr_set_emax(_oldemax); \
}
/* Exceptions should be checked in order of least important to most important.
*/
#define GMPY_MPFR_EXCEPTIONS(V, CTX) \
CTX->ctx.underflow |= mpfr_underflow_p(); \
CTX->ctx.overflow |= mpfr_overflow_p(); \
CTX->ctx.invalid |= mpfr_nanflag_p(); \
CTX->ctx.inexact |= mpfr_inexflag_p(); \
CTX->ctx.divzero |= mpfr_divby0_p(); \
if (CTX->ctx.traps) { \
if ((CTX->ctx.traps & TRAP_UNDERFLOW) && mpfr_underflow_p()) { \
GMPY_UNDERFLOW("underflow"); \
Py_XDECREF((PyObject*)V); \
V = NULL; \
} \
if ((CTX->ctx.traps & TRAP_OVERFLOW) && mpfr_overflow_p()) { \
GMPY_OVERFLOW("overflow"); \
Py_XDECREF((PyObject*)V); \
V = NULL; \
} \
if ((CTX->ctx.traps & TRAP_INEXACT) && mpfr_inexflag_p()) { \
GMPY_INEXACT("inexact result"); \
Py_XDECREF((PyObject*)V); \
V = NULL; \
} \
if ((CTX->ctx.traps & TRAP_INVALID) && mpfr_nanflag_p()) { \
GMPY_INVALID("invalid operation"); \
Py_XDECREF((PyObject*)V); \
V = NULL; \
} \
if ((CTX->ctx.traps & TRAP_DIVZERO) && mpfr_divby0_p()) { \
GMPY_DIVZERO("division by zero"); \
Py_XDECREF((PyObject*)V); \
V = NULL; \
} \
}
#define GMPY_MPFR_CLEANUP(V, CTX) \
GMPY_MPFR_CHECK_RANGE(V, CTX); \
GMPY_MPFR_SUBNORMALIZE(V, CTX); \
GMPY_MPFR_EXCEPTIONS(V, CTX);
#define GMPY_CHECK_ERANGE(V, CTX, MSG) \
CTX->ctx.erange |= mpfr_erangeflag_p(); \
if (CTX->ctx.traps) { \
if ((CTX->ctx.traps & TRAP_ERANGE) && mpfr_erangeflag_p()) { \
GMPY_ERANGE(MSG); \
Py_XDECREF((PyObject*)V); \
V = NULL; \
} \
} \
static void _GMPy_MPFR_Cleanup(MPFR_Object **v, CTXT_Object *ctext);
#ifdef __cplusplus
}
#endif
#endif
././@PaxHeader 0000000 0000000 0000000 00000000026 00000000000 010213 x ustar 00 22 mtime=1710307256.0
gmpy2-2.2.1/src/gmpy2_mpfr_misc.c 0000644 0001750 0001750 00000054615 14574233670 015300 0 ustar 00case case /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* gmpy2_mpfr_misc.c *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Python interface to the GMP, MPFR, and MPC multiple precision *
* libraries. *
* *
* Copyright 2000 - 2009 Alex Martelli *
* *
* Copyright 2008 - 2024 Case Van Horsen *
* *
* This file is part of GMPY2. *
* *
* GMPY2 is free software: you can redistribute it and/or modify it under *
* the terms of the GNU Lesser General Public License as published by the *
* Free Software Foundation, either version 3 of the License, or (at your *
* option) any later version. *
* *
* GMPY2 is distributed in the hope that it will be useful, but WITHOUT *
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or *
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public *
* License for more details. *
* *
* You should have received a copy of the GNU Lesser General Public *
* License along with GMPY2; if not, see *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
PyDoc_STRVAR(GMPy_doc_function_f2q,
"f2q(x, err=0, /) -> mpz | mpq\n\n"
"Return the 'best' `mpq` approximating x to within relative error err.\n"
"Default is the precision of x. Uses Stern-Brocot tree to find the\n"
"'best' approximation. An `mpz` object is returned if the denominator\n"
"is 1. If err<0, relative error is 2.0 ** err.");
static PyObject *
GMPy_Real_F2Q(PyObject *x, PyObject *y, CTXT_Object *context)
{
MPFR_Object *tempx, *tempy = NULL;
PyObject *result;
CHECK_CONTEXT(context);
if (y) {
if (!(tempy = GMPy_MPFR_From_Real(y, 1, context))) {
/* LCOV_EXCL_START */
return NULL;
/* LCOV_EXCL_STOP */
}
}
if (!(tempx = GMPy_MPFR_From_Real(x, 1, context))) {
/* LCOV_EXCL_START */
Py_XDECREF((PyObject*)tempy);
return NULL;
/* LCOV_EXCL_STOP */
}
/* See gmpy2_convert_mpfr for stern_brocot(). */
result = stern_brocot(tempx, tempy, 0, 1, context);
Py_DECREF((PyObject*)tempx);
Py_XDECREF((PyObject*)tempy);
return result;
}
static PyObject *
GMPy_Number_F2Q(PyObject *x, PyObject *y, CTXT_Object *context)
{
if (IS_REAL(x) && (!y || IS_REAL(y)))
return GMPy_Real_F2Q(x, y, context);
TYPE_ERROR("f2q() argument types not supported");
return NULL;
}
static PyObject *
GMPy_Context_F2Q(PyObject *self, PyObject *args)
{
CTXT_Object *context = NULL;
if (PyTuple_GET_SIZE(args) < 1 || PyTuple_GET_SIZE(args) > 2) {
TYPE_ERROR("f2q() requires 1 or 2 arguments");
return NULL;
}
if (self && CTXT_Check(self)) {
/* LCOV_EXCL_START */
context = (CTXT_Object*)self;
/* LCOV_EXCL_STOP */
}
else {
CHECK_CONTEXT(context);
}
if (PyTuple_GET_SIZE(args) == 1) {
return GMPy_Number_F2Q(PyTuple_GET_ITEM(args, 0), NULL, context);
}
else {
return GMPy_Number_F2Q(PyTuple_GET_ITEM(args, 0), PyTuple_GET_ITEM(args, 1), context);
}
}
PyDoc_STRVAR(GMPy_doc_mpfr_free_cache,
"free_cache() -> None\n\n"
"Free the internal cache of constants maintained by MPFR.");
static PyObject *
GMPy_MPFR_Free_Cache(PyObject *self, PyObject *args)
{
mpfr_free_cache();
Py_RETURN_NONE;
}
PyDoc_STRVAR(GMPy_doc_mpfr_can_round,
"can_round(b, err, rnd1, rnd2, prec, /) -> bool\n\n"
"Let b be an approximation to an unknown number x that is rounded\n"
"according to rnd1. Assume the b has an error at most two to the power\n"
"of E(b)-err where E(b) is the exponent of b. Then return `True` if x\n"
"can be rounded correctly to prec bits with rounding mode rnd2.");
static PyObject *
GMPy_MPFR_Can_Round(PyObject *self, PyObject *args)
{
int rnd1, rnd2;
long err, prec;
PyObject *b;
if (!PyArg_ParseTuple(args, "O!liil", &MPFR_Type, &b, &err, &rnd1, &rnd2, &prec)) {
return NULL;
}
if (!(rnd1 == MPFR_RNDN || rnd1 == MPFR_RNDZ ||
rnd1 == MPFR_RNDU || rnd1 == MPFR_RNDD ||
rnd1 == MPFR_RNDA)) {
VALUE_ERROR("invalid value for rounding mode");
return NULL;
}
if (!(rnd2 == MPFR_RNDN || rnd2 == MPFR_RNDZ ||
rnd2 == MPFR_RNDU || rnd2 == MPFR_RNDD ||
rnd2 == MPFR_RNDA)) {
VALUE_ERROR("invalid value for rounding mode");
return NULL;
}
if (prec < MPFR_PREC_MIN || prec > MPFR_PREC_MAX) {
VALUE_ERROR("invalid value for precision");
return NULL;
}
if (mpfr_can_round(MPFR(b), err, rnd1, rnd2, prec))
Py_RETURN_TRUE;
else
Py_RETURN_FALSE;
}
PyDoc_STRVAR(GMPy_doc_mpfr_get_emin_min,
"get_emin_min() -> int\n\n"
"Return the minimum possible exponent that can be set for `mpfr`.");
static PyObject *
GMPy_MPFR_get_emin_min(PyObject *self, PyObject *args)
{
return PyLong_FromSsize_t((Py_ssize_t)mpfr_get_emin_min());
}
PyDoc_STRVAR(GMPy_doc_mpfr_get_emax_max,
"get_emax_max() -> int\n\n"
"Return the maximum possible exponent that can be set for `mpfr`.");
static PyObject *
GMPy_MPFR_get_emax_max(PyObject *self, PyObject *args)
{
return PyLong_FromSsize_t((Py_ssize_t)mpfr_get_emax_max());
}
PyDoc_STRVAR(GMPy_doc_mpfr_get_max_precision,
"get_max_precision() -> int\n\n"
"Return the maximum bits of precision that can be used for calculations.\n"
"Note: to allow extra precision for intermediate calculations, avoid\n"
"setting precision close the maximum precision.");
static PyObject *
GMPy_MPFR_get_max_precision(PyObject *self, PyObject *args)
{
return PyLong_FromSsize_t((Py_ssize_t)MPFR_PREC_MAX);
}
PyDoc_STRVAR(GMPy_doc_mpfr_get_exp,
"get_exp(x, /) -> int\n\n"
"Return the exponent of x. Returns 0 for NaN or Infinity and\n"
"sets the `context.erange` flag of the current context and will\n"
"raise an exception if `context.trap_erange` is set.");
static PyObject *
GMPy_MPFR_get_exp(PyObject *self, PyObject *other)
{
PyObject *result = NULL;
Py_ssize_t exp;
CTXT_Object *context = NULL;
CHECK_CONTEXT(context);
if (!(MPFR_Check(other))) {
TYPE_ERROR("get_exp() requires 'mpfr' argument");
return NULL;
}
if (mpfr_regular_p(MPFR(other))) {
exp = (Py_ssize_t)mpfr_get_exp(MPFR(other));
result = PyLong_FromSsize_t(exp);
}
else if (mpfr_zero_p(MPFR(other))) {
result = PyLong_FromSsize_t(0);
}
else {
context->ctx.erange = 1;
if (context->ctx.traps & TRAP_ERANGE) {
GMPY_ERANGE("Can not get exponent from NaN or Infinity.");
}
else {
result = PyLong_FromSsize_t(0);
}
}
return result;
}
PyDoc_STRVAR(GMPy_doc_mpfr_set_exp,
"set_exp(x, n, /) -> mpfr\n\n"
"Set the exponent of x to n. If n is outside the range of\n"
"valid exponents, `set_exp()` will set the `context.erange` flag\n"
"of the current context and either return the original value or raise\n"
"an exception if `context.trap_erange` is set.");
static PyObject *
GMPy_MPFR_set_exp(PyObject *self, PyObject *args)
{
MPFR_Object *result;
PyObject *temp;
mpfr_exp_t _oldemin, _oldemax, exp;
CTXT_Object *context = NULL;
CHECK_CONTEXT(context);
if (PyTuple_GET_SIZE(args) != 2 ||
!MPFR_Check(PyTuple_GET_ITEM(args, 0)) ||
!PyLong_Check(PyTuple_GET_ITEM(args, 1))) {
TYPE_ERROR("set_exp() requires 'mpfr', 'integer' arguments");
return NULL;
}
temp = PyTuple_GET_ITEM(args, 0);
exp = (mpfr_exp_t)PyLong_AsLong(PyTuple_GET_ITEM(args, 1));
if (exp == -1 && PyErr_Occurred()) {
VALUE_ERROR("exponent too large");
return NULL;
}
if (!(result = GMPy_MPFR_New(mpfr_get_prec(MPFR(temp)), context))) {
return NULL;
}
_oldemin = mpfr_get_emin();
_oldemax = mpfr_get_emax();
mpfr_set_emin(context->ctx.emin);
mpfr_set_emax(context->ctx.emax);
mpfr_set(MPFR(result), MPFR(temp), GET_MPFR_ROUND(context));
result->rc = mpfr_set_exp(MPFR(result), exp);
mpfr_set_emin(_oldemin);
mpfr_set_emax(_oldemax);
if (result->rc) {
context->ctx.erange = 1;
if (context->ctx.traps & TRAP_ERANGE) {
GMPY_ERANGE("new exponent is out-of-bounds");
Py_DECREF((PyObject*)result);
return NULL;
}
}
return (PyObject*)result;
}
PyDoc_STRVAR(GMPy_doc_mpfr_set_sign,
"set_sign(x, s, /) -> mpfr\n\n"
"If s is `True`, then return x with the sign bit set.");
static PyObject *
GMPy_MPFR_set_sign(PyObject *self, PyObject *args)
{
MPFR_Object *result;
CTXT_Object *context = NULL;
CHECK_CONTEXT(context);
if (PyTuple_GET_SIZE(args) != 2 ||
!MPFR_Check(PyTuple_GET_ITEM(args, 0)) ||
!PyLong_Check(PyTuple_GET_ITEM(args, 1))) {
TYPE_ERROR("set_sign() requires 'mpfr', 'boolean' arguments");
return NULL;
}
if (!(result = GMPy_MPFR_New(0, context))) {
return NULL;
}
result->rc = mpfr_setsign(MPFR(result), MPFR(PyTuple_GET_ITEM(args, 0)),
PyObject_IsTrue(PyTuple_GET_ITEM(args, 1)),
GET_MPFR_ROUND(context));
return (PyObject*)result;
}
PyDoc_STRVAR(GMPy_doc_mpfr_copy_sign,
"copy_sign(x, y, /) -> mpfr\n\n"
"Return an `mpfr` composed of x with the sign of y.");
static PyObject *
GMPy_MPFR_copy_sign(PyObject *self, PyObject *args)
{
MPFR_Object *result;
CTXT_Object *context = NULL;
CHECK_CONTEXT(context);
if (PyTuple_GET_SIZE(args) != 2 ||
!MPFR_Check(PyTuple_GET_ITEM(args, 0)) ||
!MPFR_Check(PyTuple_GET_ITEM(args, 1))) {
TYPE_ERROR("copy_sign() requires 'mpfr', 'mpfr' arguments");
return NULL;
}
if (!(result = GMPy_MPFR_New(0, context))) {
return NULL;
}
result->rc = mpfr_copysign(MPFR(result), MPFR(PyTuple_GET_ITEM(args, 0)),
MPFR(PyTuple_GET_ITEM(args, 1)),
GET_MPFR_ROUND(context));
return (PyObject*)result;
}
PyDoc_STRVAR(GMPy_doc_mpfr_set_nan,
"nan() -> mpfr\n\n"
"Return an `mpfr` initialized to NaN (Not-A-Number).");
static PyObject *
GMPy_MPFR_set_nan(PyObject *self, PyObject *other)
{
MPFR_Object *result;
CTXT_Object *context = NULL;
CHECK_CONTEXT(context);
if ((result = GMPy_MPFR_New(0, context))) {
mpfr_set_nan(result->f);
}
return (PyObject*)result;
}
PyDoc_STRVAR(GMPy_doc_mpfr_set_inf,
"inf(n, /) -> mpfr\n\n"
"Return an `mpfr` initialized to Infinity with the same sign as n.\n"
"If n is not given, +Infinity is returned.");
static PyObject *
GMPy_MPFR_set_inf(PyObject *self, PyObject *args)
{
MPFR_Object *result;
long s = 1;
CTXT_Object *context = NULL;
CHECK_CONTEXT(context);
if (PyTuple_Size(args) == 1) {
s = GMPy_Integer_AsLongWithType(PyTuple_GET_ITEM(args, 0),
GMPy_ObjectType(PyTuple_GET_ITEM(args, 0)));
if (s == -1 && PyErr_Occurred()) {
return NULL;
}
}
if ((result = GMPy_MPFR_New(0, context))) {
mpfr_set_inf(result->f, s < 0 ? -1 : 1);
}
return (PyObject*)result;
}
PyDoc_STRVAR(GMPy_doc_mpfr_set_zero,
"zero(n, /) -> mpfr\n\n"
"Return an `mpfr` initialized to 0.0 with the same sign as n.\n"
"If n is not given, +0.0 is returned.");
static PyObject *
GMPy_MPFR_set_zero(PyObject *self, PyObject *args)
{
MPFR_Object *result;
long s = 1;
CTXT_Object *context = NULL;
CHECK_CONTEXT(context);
if (PyTuple_Size(args) == 1) {
s = GMPy_Integer_AsLongWithType(PyTuple_GET_ITEM(args, 0),
GMPy_ObjectType(PyTuple_GET_ITEM(args, 0)));
if (s == -1 && PyErr_Occurred()) {
return NULL;
}
}
if ((result = GMPy_MPFR_New(0, context))) {
mpfr_set_zero(result->f, s < 0 ? -1 : 1);
}
return (PyObject*)result;
}
PyDoc_STRVAR(GMPy_doc_method_integer_ratio,
"x.as_integer_ratio() -> tuple[mpz, mpz]\n\n"
"Return the exact rational equivalent of an `mpfr`. Value is a `tuple`\n"
"for compatibility with Python's `float.as_integer_ratio`.");
/* Note: almost identical code exists in gmpy2_convert_mpfr.c as the
* function GMPy_MPQ_From_MPFR. They should be refactored.
*/
static PyObject *
GMPy_MPFR_Integer_Ratio_Method(PyObject *self, PyObject *args)
{
MPZ_Object *num, *den;
mpfr_exp_t temp, twocount;
PyObject *result;
CTXT_Object *context = NULL;
CHECK_CONTEXT(context);
if (mpfr_nan_p(MPFR(self))) {
VALUE_ERROR("Cannot pass NaN to mpfr.as_integer_ratio.");
return NULL;
}
if (mpfr_inf_p(MPFR(self))) {
OVERFLOW_ERROR("Cannot pass Infinity to mpfr.as_integer_ratio.");
return NULL;
}
num = GMPy_MPZ_New(context);
den = GMPy_MPZ_New(context);
if (!num || !den) {
/* LCOV_EXCL_START */
Py_XDECREF((PyObject*)num);
Py_XDECREF((PyObject*)den);
return NULL;
/* LCOV_EXCL_STOP */
}
if (mpfr_zero_p(MPFR(self))) {
mpz_set_ui(num->z, 0);
mpz_set_ui(den->z, 1);
}
else {
temp = mpfr_get_z_2exp(num->z, MPFR(self));
twocount = (mpfr_exp_t)mpz_scan1(num->z, 0);
if (twocount) {
temp += twocount;
mpz_div_2exp(num->z, num->z, twocount);
}
mpz_set_ui(den->z, 1);
if (temp > 0)
mpz_mul_2exp(num->z, num->z, temp);
else if (temp < 0)
mpz_mul_2exp(den->z, den->z, -temp);
}
result = Py_BuildValue("(NN)", (PyObject*)num, (PyObject*)den);
if (!result) {
/* LCOV_EXCL_START */
Py_DECREF((PyObject*)num);
Py_DECREF((PyObject*)den);
/* LCOV_EXCL_STOP */
}
return result;
}
PyDoc_STRVAR(GMPy_doc_method_mantissa_exp,
"x.as_mantissa_exp() -> tuple[mpz, mpz]\n\n"
"Return the mantissa and exponent of an `mpfr`.");
static PyObject *
GMPy_MPFR_Mantissa_Exp_Method(PyObject *self, PyObject *args)
{
MPZ_Object *mantissa , *exponent;
mpfr_exp_t temp;
PyObject *result;
CTXT_Object *context = NULL;
CHECK_CONTEXT(context);
if (mpfr_nan_p(MPFR(self))) {
VALUE_ERROR("Cannot pass NaN to mpfr.as_mantissa_exp.");
return NULL;
}
if (mpfr_inf_p(MPFR(self))) {
OVERFLOW_ERROR("Cannot pass Infinity to mpfr.as_mantissa_exp.");
return NULL;
}
mantissa = GMPy_MPZ_New(context);
exponent = GMPy_MPZ_New(context);
if (!mantissa || !exponent) {
/* LCOV_EXCL_START */
Py_XDECREF((PyObject*)mantissa);
Py_XDECREF((PyObject*)exponent);
return NULL;
/* LCOV_EXCL_STOP */
}
if (mpfr_zero_p(MPFR(self))) {
mpz_set_ui(mantissa->z, 0);
mpz_set_ui(exponent->z, 1);
}
else {
temp = mpfr_get_z_2exp(mantissa->z, MPFR(self));
mpz_set_si(exponent->z, temp);
}
result = Py_BuildValue("(NN)", (PyObject*)mantissa, (PyObject*)exponent);
if (!result) {
/* LCOV_EXCL_START */
Py_DECREF((PyObject*)mantissa);
Py_DECREF((PyObject*)exponent);
/* LCOV_EXCL_STOP */
}
return result;
}
PyDoc_STRVAR(GMPy_doc_method_simple_fraction,
"x.as_simple_fraction(precision=0) -> mpq\n\n"
"Return a simple rational approximation to x. The result will be\n"
"accurate to 'precision' bits. If 'precision' is 0, the precision\n"
"of 'x' will be used.");
static PyObject *
GMPy_MPFR_Simple_Fraction_Method(PyObject *self, PyObject *args, PyObject *keywds)
{
mpfr_prec_t prec = 0;
static char *kwlist[] = {"precision", NULL};
CTXT_Object *context = NULL;
if (!PyArg_ParseTupleAndKeywords(args, keywds, "|l", kwlist, &prec)) {
return NULL;
}
return (PyObject*)stern_brocot((MPFR_Object*)self, 0, prec, 0, context);
}
/* Implement the .precision attribute of an mpfr. */
static PyObject *
GMPy_MPFR_GetPrec_Attrib(MPFR_Object *self, void *closure)
{
return PyLong_FromSsize_t((Py_ssize_t)mpfr_get_prec(self->f));
}
/* Implement the .rc attribute of an mpfr. */
static PyObject *
GMPy_MPFR_GetRc_Attrib(MPFR_Object *self, void *closure)
{
return PyLong_FromLong((long)self->rc);
}
/* Implement the .imag attribute of an mpfr. */
static PyObject *
GMPy_MPFR_GetImag_Attrib(MPFR_Object *self, void *closure)
{
MPFR_Object *result;
CTXT_Object *context = NULL;
CHECK_CONTEXT(context);
if ((result = GMPy_MPFR_New(0, context)))
mpfr_set_zero(result->f, 1);
return (PyObject*)result;
}
/* Implement the .real attribute of an mpfr. */
static PyObject *
GMPy_MPFR_GetReal_Attrib(MPFR_Object *self, void *closure)
{
Py_INCREF((PyObject*)self);
return (PyObject*)self;
}
static PyObject *
GMPy_MPFR_Get_Mpmath_MPF_Tuple(MPFR_Object *self, void *closure)
{
long sign;
mp_bitcnt_t bc;
MPZ_Object *mantissa;
MPZ_Object *exponent;
mpfr_exp_t temp;
PyObject *tuple;
if (!(tuple = PyTuple_New(4))) {
return NULL;
}
mantissa = GMPy_MPZ_New(NULL);
exponent = GMPy_MPZ_New(NULL);
if (!mantissa || !exponent) {
/* LCOV_EXCL_START */
Py_XDECREF((PyObject*)mantissa);
Py_XDECREF((PyObject*)exponent);
return NULL;
/* LCOV_EXCL_STOP */
}
if (mpfr_zero_p(MPFR(self))) {
mpz_set_ui(MPZ(mantissa), 0);
mpz_set_ui(MPZ(exponent), 1);
}
else {
temp = mpfr_get_z_2exp(MPZ(mantissa), MPFR(self));
mpz_set_si(MPZ(exponent), temp);
}
sign = mpz_sgn(MPZ(mantissa)) < 0;
mpz_abs(MPZ(mantissa), MPZ(mantissa));
bc = mpz_sizeinbase(MPZ(mantissa), 2);
PyTuple_SET_ITEM(tuple, 0, PyLong_FromLong(sign));
PyTuple_SET_ITEM(tuple, 1, (PyObject*)mantissa);
PyTuple_SET_ITEM(tuple, 2, GMPy_PyLong_From_MPZ(exponent, NULL));
PyTuple_SET_ITEM(tuple, 3, GMPy_PyLong_FromMpBitCnt(bc));
return tuple;
}
/* Implement the nb_bool slot. */
static int
GMPy_MPFR_NonZero_Slot(MPFR_Object *self)
{
return !mpfr_zero_p(self->f);
}
PyDoc_STRVAR(GMPy_doc_function_check_range,
"check_range(x, /) -> mpfr\n\n"
"Return a new `mpfr` with exponent that lies within the current range\n"
"of emin and emax.");
PyDoc_STRVAR(GMPy_doc_context_check_range,
"context.check_range(x, /) -> mpfr\n\n"
"Return a new `mpfr` with exponent that lies within the range of emin\n"
"and emax specified by context.");
static PyObject *
GMPy_MPFR_CheckRange(PyObject *x, CTXT_Object *context)
{
MPFR_Object *result;
CHECK_CONTEXT(context);
if ((result = GMPy_MPFR_New(mpfr_get_prec(MPFR(x)), context))) {
mpfr_set(result->f, MPFR(x), GET_MPFR_ROUND(context));
mpfr_clear_flags();
_GMPy_MPFR_Cleanup(&result, context);
}
return (PyObject*)result;
}
static PyObject *
GMPy_Number_CheckRange(PyObject *x, CTXT_Object *context)
{
if (MPFR_Check(x))
return GMPy_MPFR_CheckRange(x, context);
TYPE_ERROR("check_range() argument types not supported");
return NULL;
}
static PyObject *
GMPy_Context_CheckRange(PyObject *self, PyObject *other)
{
CTXT_Object *context = NULL;
if (self && CTXT_Check(self)) {
context = (CTXT_Object*)self;
}
else {
CHECK_CONTEXT(context);
}
return GMPy_Number_CheckRange(other, context);
}
PyDoc_STRVAR(GMPy_doc_mpfr_sizeof_method,
"x.__sizeof__()\n\n"
"Returns the amount of memory consumed by x.");
static PyObject *
GMPy_MPFR_SizeOf_Method(PyObject *self, PyObject *other)
{
return PyLong_FromSize_t(sizeof(MPFR_Object) + \
(((MPFR(self))->_mpfr_prec + mp_bits_per_limb - 1) / \
mp_bits_per_limb) * sizeof(mp_limb_t));
}
PyDoc_STRVAR(GMPy_doc_method_round10,
"x.__round__(n = 0, /) -> mpfr\n\n"
"Return x rounded to n decimal digits before (n < 0) or after (n > 0)\n"
"the decimal point. Rounds to an integer if n is not specified.");
static PyObject *
GMPy_MPFR_Method_Round10(PyObject *self, PyObject *args)
{
long digits = 0;
mpz_t temp;
MPFR_Object *resultf = 0;
MPZ_Object *resultz;
CTXT_Object *context = NULL;
CHECK_CONTEXT(context);
/* If the size of args is 0, we just return an mpz. */
if (PyTuple_GET_SIZE(args) == 0) {
if ((resultz = GMPy_MPZ_New(context))) {
if (mpfr_nan_p(MPFR(self))) {
Py_DECREF((PyObject*)resultz);
VALUE_ERROR("'mpz' does not support NaN");
return NULL;
}
if (mpfr_inf_p(MPFR(self))) {
Py_DECREF((PyObject*)resultz);
OVERFLOW_ERROR("'mpz' does not support Infinity");
return NULL;
}
/* return code is ignored */
mpfr_get_z(resultz->z, MPFR(self), MPFR_RNDN);
}
return (PyObject*)resultz;
}
/* Now we need to return an mpfr, so handle the simple cases. */
if (!mpfr_regular_p(MPFR(self))) {
Py_INCREF(self);
return self;
}
if (PyTuple_GET_SIZE(args) >= 1) {
digits = PyLong_AsLong(PyTuple_GET_ITEM(args, 0));
if (digits == -1 && PyErr_Occurred()) {
TYPE_ERROR("__round__() requires 'int' argument");
return NULL;
}
}
/* TODO: better error analysis, or else convert the mpfr to an exact
* fraction, round the fraction, and then convert back to an mpfr.
*/
if (!(resultf = GMPy_MPFR_New(mpfr_get_prec(MPFR(self))+100, context))) {
return NULL;
}
mpz_init(temp);
mpz_ui_pow_ui(temp, 10, digits > 0 ? digits : -digits);
if (digits >= 0) {
mpfr_mul_z(resultf->f, MPFR(self), temp, MPFR_RNDN);
}
else {
mpfr_div_z(resultf->f, MPFR(self), temp, MPFR_RNDN);
}
mpfr_rint(resultf->f, resultf->f, MPFR_RNDN);
if (digits >= 0) {
mpfr_div_z(resultf->f, resultf->f, temp, MPFR_RNDN);
}
else {
mpfr_mul_z(resultf->f, resultf->f, temp, MPFR_RNDN);
}
mpfr_prec_round(resultf->f, mpfr_get_prec(MPFR(self)), MPFR_RNDN);
mpz_clear(temp);
return((PyObject*)resultf);
}
././@PaxHeader 0000000 0000000 0000000 00000000026 00000000000 010213 x ustar 00 22 mtime=1710307256.0
gmpy2-2.2.1/src/gmpy2_mpfr_misc.h 0000644 0001750 0001750 00000007670 14574233670 015304 0 ustar 00case case /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* gmpy2_mpfr_misc.h *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Python interface to the GMP, MPFR, and MPC multiple precision *
* libraries. *
* *
* Copyright 2000 - 2009 Alex Martelli *
* *
* Copyright 2008 - 2024 Case Van Horsen *
* *
* This file is part of GMPY2. *
* *
* GMPY2 is free software: you can redistribute it and/or modify it under *
* the terms of the GNU Lesser General Public License as published by the *
* Free Software Foundation, either version 3 of the License, or (at your *
* option) any later version. *
* *
* GMPY2 is distributed in the hope that it will be useful, but WITHOUT *
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or *
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public *
* License for more details. *
* *
* You should have received a copy of the GNU Lesser General Public *
* License along with GMPY2; if not, see *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
#ifndef GMPY_MPFR_MISC_H
#define GMPY_MPFR_MISC_H
#ifdef __cplusplus
extern "C" {
#endif
static PyObject * GMPy_Real_F2Q(PyObject *x, PyObject *y, CTXT_Object *context);
static PyObject * GMPy_MPFR_Free_Cache(PyObject *self, PyObject *args);
static PyObject * GMPy_MPFR_Can_Round(PyObject *self, PyObject *args);
static PyObject * GMPy_MPFR_get_emax_max(PyObject *self, PyObject *args);
static PyObject * GMPy_MPFR_get_max_precision(PyObject *self, PyObject *args);
static PyObject * GMPy_MPFR_get_exp(PyObject *self, PyObject *other);
static PyObject * GMPy_MPFR_set_exp(PyObject *self, PyObject *args);
static PyObject * GMPy_MPFR_set_sign(PyObject *self, PyObject *args);
static PyObject * GMPy_MPFR_copy_sign(PyObject *self, PyObject *args);
static PyObject * GMPy_MPFR_Integer_Ratio_Method(PyObject *self, PyObject *args);
static PyObject * GMPy_MPFR_Mantissa_Exp_Method(PyObject *self, PyObject *args);
static PyObject * GMPy_MPFR_Simple_Fraction_Method(PyObject *self, PyObject *args, PyObject *keywds);
static PyObject * GMPy_MPFR_set_nan(PyObject *self, PyObject *other);
static PyObject * GMPy_MPFR_set_inf(PyObject *self, PyObject *args);
static PyObject * GMPy_MPFR_set_zero(PyObject *self, PyObject *args);
static PyObject * GMPy_MPFR_GetPrec_Attrib(MPFR_Object *self, void *closure);
static PyObject * GMPy_MPFR_GetRc_Attrib(MPFR_Object *self, void *closure);
static PyObject * GMPy_MPFR_GetImag_Attrib(MPFR_Object *self, void *closure);
static PyObject * GMPy_MPFR_GetReal_Attrib(MPFR_Object *self, void *closure);
static PyObject * GMPy_MPFR_Get_Mpmath_MPF_Tuple(MPFR_Object *self, void *closure);
static int GMPy_MPFR_NonZero_Slot(MPFR_Object *self);
static PyObject * GMPy_MPFR_SizeOf_Method(PyObject *self, PyObject *other);
static PyObject * GMPy_MPFR_CheckRange(PyObject *x, CTXT_Object *context);
static PyObject * GMPy_Number_CheckRange(PyObject *x, CTXT_Object *context);
static PyObject * GMPy_Context_CheckRange(PyObject *self, PyObject *other);
static PyObject * GMPy_MPFR_Method_Round10(PyObject *self, PyObject *args);
#ifdef __cplusplus
}
#endif
#endif
././@PaxHeader 0000000 0000000 0000000 00000000026 00000000000 010213 x ustar 00 22 mtime=1710307256.0
gmpy2-2.2.1/src/gmpy2_mpmath.c 0000644 0001750 0001750 00000033371 14574233670 014603 0 ustar 00case case /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* gmpy2_mpmath.c *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Python interface to the GMP, MPFR, and MPC multiple precision *
* libraries. *
* *
* Copyright 2000 - 2009 Alex Martelli *
* *
* Copyright 2008 - 2024 Case Van Horsen *
* *
* This file is part of GMPY2. *
* *
* GMPY2 is free software: you can redistribute it and/or modify it under *
* the terms of the GNU Lesser General Public License as published by the *
* Free Software Foundation, either version 3 of the License, or (at your *
* option) any later version. *
* *
* GMPY2 is distributed in the hope that it will be useful, but WITHOUT *
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or *
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public *
* License for more details. *
* *
* You should have received a copy of the GNU Lesser General Public *
* License along with GMPY2; if not, see *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
/* Internal helper function for mpmath. */
static PyObject *
mpmath_build_mpf(long sign, MPZ_Object *man, PyObject *exp, mp_bitcnt_t bc)
{
PyObject *tup, *tsign, *tbc;
if (!(tup = PyTuple_New(4))) {
/* LCOV_EXCL_START */
Py_DECREF((PyObject*)man);
Py_DECREF(exp);
return NULL;
/* LCOV_EXCL_STOP */
}
if (!(tsign = PyLong_FromLong(sign))) {
/* LCOV_EXCL_START */
Py_DECREF((PyObject*)man);
Py_DECREF(exp);
Py_DECREF(tup);
return NULL;
/* LCOV_EXCL_STOP */
}
if (!(tbc = GMPy_PyLong_FromMpBitCnt(bc))) {
/* LCOV_EXCL_START */
Py_DECREF((PyObject*)man);
Py_DECREF(exp);
Py_DECREF(tup);
Py_DECREF(tsign);
return NULL;
/* LCOV_EXCL_STOP */
}
PyTuple_SET_ITEM(tup, 0, tsign);
PyTuple_SET_ITEM(tup, 1, (PyObject*)man);
PyTuple_SET_ITEM(tup, 2, (exp)?exp:PyLong_FromLong(0));
PyTuple_SET_ITEM(tup, 3, tbc);
return tup;
}
static long
mpmath_get_sign(PyObject *x)
{
/* Assume properly normalized arguments. A value of 0 implies positive, and
* value of 1 implies negative.
*/
if (PyLong_Check(x)) {
return PyLong_AsLong(x);
}
if (MPZ_Check(x)) {
if (mpz_sgn(MPZ(x)) < 0) {
return 1;
}
else {
return 0;
}
}
TYPE_ERROR("could not convert object to integer");
return (long)-1;
}
PyDoc_STRVAR(doc_mpmath_normalizeg,
"_mpmath_normalize(...): helper function for mpmath.");
static PyObject *
Pympz_mpmath_normalize_fast(PyObject *self, PyObject *const *args, Py_ssize_t nargs)
{
long sign = 0;
long carry = 0;
mp_bitcnt_t zbits, shift = 0, bc = 0, prec = 0;
PyObject *exp = NULL, *newexp = NULL, *newexp2 = NULL, *tmp = NULL, *rndstr = NULL;
MPZ_Object *man = NULL, *upper = NULL, *lower = NULL;
Py_UCS4 rnd = 0;
if (nargs == 6) {
/* Need better error-checking here. Under Python 3.0, overflow into
C-long is possible. */
sign = mpmath_get_sign(args[0]);
man = (MPZ_Object*)args[1];
exp = args[2];
bc = GMPy_PyLong_AsMpBitCnt(args[3]);
prec = GMPy_PyLong_AsMpBitCnt(args[4]);
rndstr = args[5];
if ((sign == -1) || (bc == (mp_bitcnt_t)(-1)) || (prec == (mp_bitcnt_t)(-1))) {
TYPE_ERROR("arguments long, MPZ_Object*, PyObject*, long, long, char needed");
return NULL;
}
}
else {
TYPE_ERROR("6 arguments required");
return NULL;
}
if (!MPZ_Check(man)) {
/* Try to convert to an mpz... */
if (!(man = GMPy_MPZ_From_Integer((PyObject*)man, NULL))) {
TYPE_ERROR("argument is not an mpz");
return NULL;
}
}
/* If rndstr really is a string, extract the first character. */
if (PyUnicode_Check(rndstr)) {
rnd = PyString_1Char(rndstr);
}
else {
VALUE_ERROR("invalid rounding mode specified");
return NULL;
}
/* If the mantissa is 0, return the normalized representation. */
if (!mpz_sgn(man->z)) {
Py_INCREF((PyObject*)man);
return mpmath_build_mpf(0, man, 0, 0);
}
/* if bc <= prec and the number is odd return it */
if ((bc <= prec) && mpz_odd_p(man->z)) {
Py_INCREF((PyObject*)man);
Py_INCREF((PyObject*)exp);
return mpmath_build_mpf(sign, man, exp, bc);
}
if (!(upper = GMPy_MPZ_New(NULL)) || !(lower = GMPy_MPZ_New(NULL))) {
/* LCOV_EXCL_START */
Py_XDECREF((PyObject*)upper);
Py_XDECREF((PyObject*)lower);
return NULL;
/* LCOV_EXCL_STOP */
}
if (bc > prec) {
shift = bc - prec;
switch (rnd) {
case (Py_UCS4)'f':
if(sign) {
mpz_cdiv_q_2exp(upper->z, man->z, shift);
}
else {
mpz_fdiv_q_2exp(upper->z, man->z, shift);
}
break;
case (Py_UCS4)'c':
if(sign) {
mpz_fdiv_q_2exp(upper->z, man->z, shift);
}
else {
mpz_cdiv_q_2exp(upper->z, man->z, shift);
}
break;
case (Py_UCS4)'d':
mpz_fdiv_q_2exp(upper->z, man->z, shift);
break;
case (Py_UCS4)'u':
mpz_cdiv_q_2exp(upper->z, man->z, shift);
break;
case (Py_UCS4)'n':
default:
mpz_tdiv_r_2exp(lower->z, man->z, shift);
mpz_tdiv_q_2exp(upper->z, man->z, shift);
if (mpz_sgn(lower->z)) {
/* lower is not 0 so it must have at least 1 bit set */
if (mpz_sizeinbase(lower->z, 2) == shift) {
/* lower is >= 1/2 */
if (mpz_scan1(lower->z, 0) == shift-1) {
/* lower is exactly 1/2 */
if (mpz_odd_p(upper->z))
carry = 1;
}
else {
carry = 1;
}
}
}
if (carry)
mpz_add_ui(upper->z, upper->z, 1);
}
if (!(tmp = PyLong_FromUnsignedLong((unsigned long)shift))) {
/* LCOV_EXCL_START */
Py_DECREF((PyObject*)upper);
Py_DECREF((PyObject*)lower);
return NULL;
/* LCOV_EXCL_STOP */
}
if (!(newexp = PyNumber_Add(exp, tmp))) {
/* LCOV_EXCL_START */
Py_DECREF((PyObject*)upper);
Py_DECREF((PyObject*)lower);
Py_DECREF(tmp);
return NULL;
/* LCOV_EXCL_STOP */
}
Py_DECREF(tmp);
bc = prec;
}
else {
mpz_set(upper->z, man->z);
newexp = exp;
Py_INCREF(newexp);
}
/* Strip trailing 0 bits. */
if ((zbits = mpz_scan1(upper->z, 0)))
mpz_tdiv_q_2exp(upper->z, upper->z, zbits);
if (!(tmp = GMPy_PyLong_FromMpBitCnt(zbits))) {
/* LCOV_EXCL_START */
Py_DECREF((PyObject*)upper);
Py_DECREF((PyObject*)lower);
Py_DECREF(newexp);
return NULL;
/* LCOV_EXCL_STOP */
}
if (!(newexp2 = PyNumber_Add(newexp, tmp))) {
/* LCOV_EXCL_START */
Py_DECREF((PyObject*)upper);
Py_DECREF((PyObject*)lower);
Py_DECREF(tmp);
Py_DECREF(newexp);
return NULL;
/* LCOV_EXCL_STOP */
}
Py_DECREF(newexp);
Py_DECREF(tmp);
bc -= zbits;
/* Check if one less than a power of 2 was rounded up. */
if (!mpz_cmp_ui(upper->z, 1))
bc = 1;
Py_DECREF((PyObject*)lower);
return mpmath_build_mpf(sign, upper, newexp2, bc);
}
PyDoc_STRVAR(doc_mpmath_create,
"_mpmath_create(...): helper function for mpmath.");
static PyObject *
Pympz_mpmath_create_fast(PyObject *self, PyObject *const *args, Py_ssize_t nargs)
{
long sign, carry = 0;
mp_bitcnt_t zbits, bc = 0, prec = 0, shift = 0;
PyObject *exp = NULL, *newexp = NULL, *newexp2 = NULL, *tmp = NULL;
MPZ_Object *man = NULL, *upper = NULL, *lower = NULL;
Py_UCS4 rnd = (Py_UCS4)'f';
if (nargs < 2) {
TYPE_ERROR("mpmath_create() expects 'mpz','int'[,'int','str'] arguments");
return NULL;
}
switch (nargs) {
case 4:
rnd = PyString_1Char(args[3]);
case 3:
prec = GMPy_Integer_AsLong(args[2]);
if (prec == (mp_bitcnt_t)(-1)) {
VALUE_ERROR("could not convert prec to positive int");
return NULL;
}
case 2:
exp = args[1];
case 1:
man = GMPy_MPZ_From_Integer(args[0], NULL);
if (!man) {
TYPE_ERROR("mpmath_create() expects 'mpz','int'[,'int','str'] arguments");
return NULL;
}
}
/* If the mantissa is 0, return the normalized representation. */
if (!mpz_sgn(man->z)) {
return mpmath_build_mpf(0, man, 0, 0);
}
upper = GMPy_MPZ_New(NULL);
lower = GMPy_MPZ_New(NULL);
if (!upper || !lower) {
/* LCOV_EXCL_START */
Py_DECREF((PyObject*)man);
Py_XDECREF((PyObject*)upper);
Py_XDECREF((PyObject*)lower);
return NULL;
/* LCOV_EXCL_STOP */
}
/* Extract sign, make man positive, and set bit count */
sign = (mpz_sgn(man->z) == -1);
mpz_abs(upper->z, man->z);
bc = mpz_sizeinbase(upper->z, 2);
if (!prec) {
prec = bc;
}
if (bc > prec) {
shift = bc - prec;
switch (rnd) {
case (Py_UCS4)'f':
if (sign) {
mpz_cdiv_q_2exp(upper->z, upper->z, shift);
}
else {
mpz_fdiv_q_2exp(upper->z, upper->z, shift);
}
break;
case (Py_UCS4)'c':
if (sign) {
mpz_fdiv_q_2exp(upper->z, upper->z, shift);
}
else {
mpz_cdiv_q_2exp(upper->z, upper->z, shift);
}
break;
case (Py_UCS4)'d':
mpz_fdiv_q_2exp(upper->z, upper->z, shift);
break;
case (Py_UCS4)'u':
mpz_cdiv_q_2exp(upper->z, upper->z, shift);
break;
case (Py_UCS4)'n':
default:
mpz_tdiv_r_2exp(lower->z, upper->z, shift);
mpz_tdiv_q_2exp(upper->z, upper->z, shift);
if (mpz_sgn(lower->z)) {
/* lower is not 0 so it must have at least 1 bit set */
if (mpz_sizeinbase(lower->z, 2)==shift) {
/* lower is >= 1/2 */
if (mpz_scan1(lower->z, 0)==shift-1) {
/* lower is exactly 1/2 */
if (mpz_odd_p(upper->z))
carry = 1;
}
else {
carry = 1;
}
}
}
if (carry) {
mpz_add_ui(upper->z, upper->z, 1);
}
}
if (!(tmp = PyLong_FromUnsignedLong((unsigned long)shift))) {
/* LCOV_EXCL_START */
Py_DECREF((PyObject*)upper);
Py_DECREF((PyObject*)lower);
return NULL;
/* LCOV_EXCL_STOP */
}
if (!(newexp = PyNumber_Add(exp, tmp))) {
/* LCOV_EXCL_START */
Py_DECREF((PyObject*)man);
Py_DECREF((PyObject*)upper);
Py_DECREF((PyObject*)lower);
Py_DECREF(tmp);
return NULL;
/* LCOV_EXCL_STOP */
}
Py_DECREF(tmp);
bc = prec;
}
else {
newexp = exp;
Py_INCREF(newexp);
}
/* Strip trailing 0 bits. */
if ((zbits = mpz_scan1(upper->z, 0)))
mpz_tdiv_q_2exp(upper->z, upper->z, zbits);
if (!(tmp = GMPy_PyLong_FromMpBitCnt(zbits))) {
/* LCOV_EXCL_START */
Py_DECREF((PyObject*)man);
Py_DECREF((PyObject*)upper);
Py_DECREF((PyObject*)lower);
Py_DECREF(newexp);
return NULL;
/* LCOV_EXCL_STOP */
}
if (!(newexp2 = PyNumber_Add(newexp, tmp))) {
/* LCOV_EXCL_START */
Py_DECREF((PyObject*)man);
Py_DECREF((PyObject*)upper);
Py_DECREF((PyObject*)lower);
Py_DECREF(tmp);
Py_DECREF(newexp);
return NULL;
/* LCOV_EXCL_STOP */
}
Py_DECREF(newexp);
Py_DECREF(tmp);
bc -= zbits;
/* Check if one less than a power of 2 was rounded up. */
if (!mpz_cmp_ui(upper->z, 1))
bc = 1;
Py_DECREF((PyObject*)lower);
Py_DECREF((PyObject*)man);
return mpmath_build_mpf(sign, upper, newexp2, bc);
}
././@PaxHeader 0000000 0000000 0000000 00000000026 00000000000 010213 x ustar 00 22 mtime=1718253275.0
gmpy2-2.2.1/src/gmpy2_mpq.c 0000644 0001750 0001750 00000013302 14632473333 014077 0 ustar 00case case /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* gmpy2_mpq.c *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Python interface to the GMP, MPFR, and MPC multiple precision *
* libraries. *
* *
* Copyright 2000 - 2009 Alex Martelli *
* *
* Copyright 2008 - 2024 Case Van Horsen *
* *
* This file is part of GMPY2. *
* *
* GMPY2 is free software: you can redistribute it and/or modify it under *
* the terms of the GNU Lesser General Public License as published by the *
* Free Software Foundation, either version 3 of the License, or (at your *
* option) any later version. *
* *
* GMPY2 is distributed in the hope that it will be useful, but WITHOUT *
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or *
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public *
* License for more details. *
* *
* You should have received a copy of the GNU Lesser General Public *
* License along with GMPY2; if not, see *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
PyDoc_STRVAR(GMPy_doc_mpq,
"mpq(n=0, /)\n"
"mpq(n, m, /)\n"
"mpq(s, /, base=10)\n\n"
"Return a rational number constructed from a non-complex number n\n"
"exactly or from a pair of `~numbers.Rational` values n and m or\n"
"from a string s made up of digits in the given base.\n"
"Every input, that is accepted by the `~fractions.Fraction` type\n"
"constructor is also accepted.\n\n"
"A string may be made up to two integers in the same base separated\n"
"by a '/' character, both parsed the same as the `mpz` type constructor\n"
"does. If base is 0 then the leading characters are used to recognize the\n"
"base, this is done separately for the numerator and denominator. If\n"
"base=10, any string that represents a finite value and is accepted by\n"
"the `float` constructor is also accepted.");
/* Since `gmpy2.mpq` is now a type and no longer a factory function, see
* gmpy2_cache.c/GMPy_MPQ_NewInit for details on creation.
*/
static PyNumberMethods mpq_number_methods =
{
.nb_add = (binaryfunc) GMPy_Number_Add_Slot,
.nb_subtract = (binaryfunc) GMPy_Number_Sub_Slot,
.nb_multiply = (binaryfunc) GMPy_Number_Mul_Slot,
.nb_remainder = (binaryfunc) GMPy_Number_Mod_Slot,
.nb_divmod = (binaryfunc) GMPy_Number_DivMod_Slot,
.nb_power = (ternaryfunc) GMPy_Number_Pow_Slot,
.nb_negative = (unaryfunc) GMPy_MPQ_Minus_Slot,
.nb_positive = (unaryfunc) GMPy_MPQ_Plus_Slot,
.nb_absolute = (unaryfunc) GMPy_MPQ_Abs_Slot,
.nb_bool = (inquiry) GMPy_MPQ_NonZero_Slot,
.nb_int = (unaryfunc) GMPy_MPQ_Int_Slot,
.nb_float = (unaryfunc) GMPy_MPQ_Float_Slot,
.nb_floor_divide = (binaryfunc) GMPy_Number_FloorDiv_Slot,
.nb_true_divide = (binaryfunc) GMPy_Number_TrueDiv_Slot,
};
static PyGetSetDef GMPy_MPQ_getseters[] =
{
{ "numerator", (getter)GMPy_MPQ_Attrib_GetNumer, NULL,
"the numerator of a rational number in lowest terms", NULL },
{ "denominator", (getter)GMPy_MPQ_Attrib_GetDenom, NULL,
"the denominator of a rational number in lowest terms", NULL },
{ "real", (getter)GMPy_MPQ_Attrib_GetReal, NULL,
"the real part of a complex number", NULL },
{ "imag", (getter)GMPy_MPQ_Attrib_GetImag, NULL,
"the imaginary part of a complex number", NULL },
{NULL}
};
static PyMethodDef GMPy_MPQ_methods [] =
{
{ "__ceil__", GMPy_MPQ_Method_Ceil, METH_NOARGS, GMPy_doc_mpq_method_ceil },
{ "__floor__", GMPy_MPQ_Method_Floor, METH_NOARGS, GMPy_doc_mpq_method_floor },
{ "__round__", GMPy_MPQ_Method_Round, METH_VARARGS, GMPy_doc_mpq_method_round },
{ "__sizeof__", GMPy_MPQ_Method_Sizeof, METH_NOARGS, GMPy_doc_mpq_method_sizeof },
{ "__trunc__", GMPy_MPQ_Method_Trunc, METH_NOARGS, GMPy_doc_mpq_method_trunc },
{ "conjugate", GMPy_MP_Method_Conjugate, METH_NOARGS, GMPy_doc_mp_method_conjugate },
{ "digits", GMPy_MPQ_Digits_Method, METH_VARARGS, GMPy_doc_mpq_digits_method },
{ "as_integer_ratio", GMPy_MPQ_Method_As_Integer_Ratio, METH_NOARGS, GMPy_doc_mpq_method_as_integer_ratio },
{ "from_float", (PyCFunction)GMPy_MPQ_Method_From_As_Integer_Ratio, METH_FASTCALL | METH_CLASS, GMPy_doc_mpq_method_from_float },
{ "from_decimal", (PyCFunction)GMPy_MPQ_Method_From_As_Integer_Ratio, METH_FASTCALL | METH_CLASS, GMPy_doc_mpq_method_from_decimal },
{ NULL }
};
static PyTypeObject MPQ_Type =
{
PyVarObject_HEAD_INIT(NULL, 0)
.tp_name = "gmpy2.mpq",
.tp_basicsize = sizeof(MPQ_Object),
.tp_dealloc = (destructor) GMPy_MPQ_Dealloc,
.tp_repr = (reprfunc) GMPy_MPQ_Repr_Slot,
.tp_as_number = &mpq_number_methods,
.tp_hash = (hashfunc) GMPy_MPQ_Hash_Slot,
.tp_str = (reprfunc) GMPy_MPQ_Str_Slot,
.tp_flags = Py_TPFLAGS_DEFAULT,
.tp_doc = GMPy_doc_mpq,
.tp_richcompare = (richcmpfunc)&GMPy_RichCompare_Slot,
.tp_methods = GMPy_MPQ_methods,
.tp_getset = GMPy_MPQ_getseters,
.tp_new =GMPy_MPQ_NewInit,
};
././@PaxHeader 0000000 0000000 0000000 00000000026 00000000000 010213 x ustar 00 22 mtime=1710307256.0
gmpy2-2.2.1/src/gmpy2_mpq.h 0000644 0001750 0001750 00000004124 14574233670 014111 0 ustar 00case case /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* gmpy2_mpq.h *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Python interface to the GMP, MPFR, and MPC multiple precision *
* libraries. *
* *
* Copyright 2000 - 2009 Alex Martelli *
* *
* Copyright 2008 - 2024 Case Van Horsen *
* *
* This file is part of GMPY2. *
* *
* GMPY2 is free software: you can redistribute it and/or modify it under *
* the terms of the GNU Lesser General Public License as published by the *
* Free Software Foundation, either version 3 of the License, or (at your *
* option) any later version. *
* *
* GMPY2 is distributed in the hope that it will be useful, but WITHOUT *
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or *
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public *
* License for more details. *
* *
* You should have received a copy of the GNU Lesser General Public *
* License along with GMPY2; if not, see *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
#ifndef GMPY_MPQ_H
#define GMPY_MPQ_H
#ifdef __cplusplus
extern "C" {
#endif
static PyTypeObject MPQ_Type;
#define MPQ_Check(v) (((PyObject*)v)->ob_type == &MPQ_Type)
#ifdef __cplusplus
}
#endif
#endif
././@PaxHeader 0000000 0000000 0000000 00000000026 00000000000 010213 x ustar 00 22 mtime=1710307256.0
gmpy2-2.2.1/src/gmpy2_mpq_misc.c 0000644 0001750 0001750 00000030636 14574233670 015126 0 ustar 00case case /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* gmpy2_mpq_misc.c *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Python interface to the GMP, MPFR, and MPC multiple precision *
* libraries. *
* *
* Copyright 2000 - 2009 Alex Martelli *
* *
* Copyright 2008 - 2024 Case Van Horsen *
* *
* This file is part of GMPY2. *
* *
* GMPY2 is free software: you can redistribute it and/or modify it under *
* the terms of the GNU Lesser General Public License as published by the *
* Free Software Foundation, either version 3 of the License, or (at your *
* option) any later version. *
* *
* GMPY2 is distributed in the hope that it will be useful, but WITHOUT *
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or *
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public *
* License for more details. *
* *
* You should have received a copy of the GNU Lesser General Public *
* License along with GMPY2; if not, see *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
static PyObject *
GMPy_MPQ_Attrib_GetNumer(MPQ_Object *self, void *closure)
{
MPZ_Object *result;
CTXT_Object *context = NULL;
if ((result = GMPy_MPZ_New(context)))
mpz_set(result->z, mpq_numref(self->q));
return (PyObject*)result;
}
static PyObject *
GMPy_MPQ_Attrib_GetReal(MPQ_Object *self, void *closure)
{
Py_INCREF((PyObject*)self);
return (PyObject*)self;
}
static PyObject *
GMPy_MPQ_Attrib_GetDenom(MPQ_Object *self, void *closure)
{
MPZ_Object *result;
CTXT_Object *context = NULL;
if ((result = GMPy_MPZ_New(context)))
mpz_set(result->z, mpq_denref(self->q));
return (PyObject*)result;
}
static PyObject *
GMPy_MPQ_Attrib_GetImag(MPQ_Object *self, void *closure)
{
MPZ_Object *result;
CTXT_Object *context = NULL;
if ((result = GMPy_MPZ_New(context)))
mpz_set_ui(result->z, 0);
return (PyObject*)result;
}
PyDoc_STRVAR(GMPy_doc_mpq_function_numer,
"numer(x, /) -> mpz\n\n"
"Return the numerator of x.");
static PyObject *
GMPy_MPQ_Function_Numer(PyObject *self, PyObject *other)
{
MPZ_Object *result;
MPQ_Object *tempq;
CTXT_Object *context = NULL;
if (!(result = (MPZ_Object*)GMPy_MPZ_New(context)))
return NULL;
if (!(tempq = GMPy_MPQ_From_Rational(other, context))) {
Py_DECREF((PyObject*)result);
return NULL;
}
mpz_set(result->z, mpq_numref(tempq->q));
Py_DECREF((PyObject*)tempq);
return (PyObject*)result;
}
PyDoc_STRVAR(GMPy_doc_mpq_function_denom,
"denom(x, /) -> mpz\n\n"
"Return the denominator of x.");
static PyObject *
GMPy_MPQ_Function_Denom(PyObject *self, PyObject *other)
{
MPZ_Object *result;
MPQ_Object *tempq;
CTXT_Object *context = NULL;
if (!(result = (MPZ_Object*)GMPy_MPZ_New(context)))
return NULL;
if (!(tempq = GMPy_MPQ_From_Rational(other, context))) {
Py_DECREF((PyObject*)result);
return NULL;
}
mpz_set(result->z, mpq_denref(tempq->q));
Py_DECREF((PyObject*)tempq);
return (PyObject*)result;
}
PyDoc_STRVAR(GMPy_doc_mpq_method_as_integer_ratio,
"x.as_integer_ratio() -> tuple[mpz, mpz]\n\n\
Return a pair of integers, whose ratio is exactly equal to the\n\
original number. The ratio is in lowest terms and has a\n\
positive denominator.");
static PyObject *
GMPy_MPQ_Method_As_Integer_Ratio(PyObject *self, PyObject *Py_UNUSED(ignored))
{
return PyTuple_Pack(2, GMPy_MPQ_Attrib_GetNumer((MPQ_Object*)self, NULL),
GMPy_MPQ_Attrib_GetDenom((MPQ_Object*)self, NULL));
}
PyDoc_STRVAR(GMPy_doc_mpq_method_from_float,
"mpq.from_float(f, /) -> mpq\n\n\
Converts a finite float to a rational number, exactly.");
PyDoc_STRVAR(GMPy_doc_mpq_method_from_decimal,
"mpq.from_decimal(dec, /) -> mpq\n\n\
Converts a finite `decimal.Decimal` instance to a rational number, exactly.");
static PyObject *
GMPy_MPQ_Method_From_As_Integer_Ratio(PyTypeObject *type, PyObject *const *args, Py_ssize_t nargs)
{
PyObject *pair, *result;
if (nargs != 1) {
TYPE_ERROR("missing 1 required positional argument");
return NULL;
}
pair = PyObject_CallMethod(args[0], "as_integer_ratio", NULL);
if (pair == NULL) {
return NULL;
}
result = GMPy_MPQ_NewInit(type, pair, NULL);
Py_DECREF(pair);
return result;
}
PyDoc_STRVAR(GMPy_doc_function_qdiv,
"qdiv(x, y=1, /) -> mpz | mpq\n\n"
"Return x/y as `mpz` if possible, or as `mpq` if x is not exactly\n"
"divisible by y.");
static PyObject *
GMPy_MPQ_Function_Qdiv(PyObject *self, PyObject *args)
{
Py_ssize_t argc;
PyObject *result = NULL, *x, *y;
MPQ_Object *tempx = NULL, *tempy = NULL, *tempr = NULL;
CTXT_Object *context = NULL;
CHECK_CONTEXT(context);
/* Validate the argument(s). */
/* If there is only one argument, it should be either an integer or
* rational type. If it is an integer, then immediately return an mpz().
* If it is a rational type, convert it to an mpq and check the denominator.
*/
argc = PyTuple_GET_SIZE(args);
if (argc == 1) {
x = PyTuple_GET_ITEM(args, 0);
if (!IS_RATIONAL(x)) {
goto arg_error;
}
if (IS_INTEGER(x)) {
return (PyObject*)GMPy_MPZ_From_Integer(x, context);
}
if (!(tempx = GMPy_MPQ_From_Rational(x, context))) {
return NULL;
}
if (mpz_cmp_ui(mpq_denref(tempx->q), 1) == 0) {
if ((result = (PyObject*)GMPy_MPZ_New(context))) {
mpz_set(MPZ(result), mpq_numref(tempx->q));
}
Py_DECREF((PyObject*)tempx);
return result;
}
else {
return (PyObject*)tempx;
}
}
/* If there are two rational arguments, just convert them both to mpq,
* divide, and then check the denominator.
*/
if (argc == 2) {
x = PyTuple_GET_ITEM(args, 0);
y = PyTuple_GET_ITEM(args, 1);
if (!IS_RATIONAL(x) || !IS_RATIONAL(y)) {
goto arg_error;
}
if (!(tempx = GMPy_MPQ_From_Rational(x, context)) ||
!(tempy = GMPy_MPQ_From_Rational(y, context))) {
Py_XDECREF((PyObject*)tempx);
Py_XDECREF((PyObject*)tempy);
return NULL;
}
if (mpq_sgn(tempy->q) == 0) {
Py_DECREF((PyObject*)tempx);
Py_DECREF((PyObject*)tempy);
ZERO_ERROR("qdiv() division by zero");
return NULL;
}
/* tempr contains the result of the division. */
if (!(tempr = GMPy_MPQ_New(context))) {
Py_DECREF((PyObject*)tempx);
Py_DECREF((PyObject*)tempy);
return NULL;
}
mpq_div(tempr->q, tempx->q, tempy->q);
Py_DECREF((PyObject*)tempx);
Py_DECREF((PyObject*)tempy);
if (mpz_cmp_ui(mpq_denref(tempr->q), 1) == 0) {
if ((result = (PyObject*)GMPy_MPZ_New(context))) {
mpz_set(MPZ(result), mpq_numref(tempr->q));
}
Py_DECREF((PyObject*)tempr);
return result;
}
else {
return (PyObject*)tempr;
};
}
arg_error:
TYPE_ERROR("qdiv() requires 1 or 2 integer or rational arguments");
return NULL;
}
PyDoc_STRVAR(GMPy_doc_mpq_method_floor,
"Return greatest integer less than or equal to an mpq.");
static PyObject *
GMPy_MPQ_Method_Floor(PyObject *self, PyObject *other)
{
MPZ_Object *result;
CTXT_Object *context = NULL;
CHECK_CONTEXT(context);
if ((result = GMPy_MPZ_New(context))) {
mpz_fdiv_q(result->z, mpq_numref(MPQ(self)), mpq_denref(MPQ(self)));
}
return (PyObject*)result;
}
PyDoc_STRVAR(GMPy_doc_mpq_method_ceil,
"Return least integer greater than or equal to an mpq.");
static PyObject *
GMPy_MPQ_Method_Ceil(PyObject *self, PyObject *other)
{
MPZ_Object *result;
CTXT_Object *context = NULL;
CHECK_CONTEXT(context);
if ((result = GMPy_MPZ_New(context))) {
mpz_cdiv_q(result->z, mpq_numref(MPQ(self)), mpq_denref(MPQ(self)));
}
return (PyObject*)result;
}
PyDoc_STRVAR(GMPy_doc_mpq_method_trunc,
"Return integer portion of an mpq.");
static PyObject *
GMPy_MPQ_Method_Trunc(PyObject *self, PyObject *other)
{
MPZ_Object *result;
CTXT_Object *context = NULL;
CHECK_CONTEXT(context);
if ((result = GMPy_MPZ_New(context))) {
mpz_tdiv_q(result->z, mpq_numref(MPQ(self)), mpq_denref(MPQ(self)));
}
return (PyObject*)result;
}
PyDoc_STRVAR(GMPy_doc_mpq_method_round, "Round an mpq to power of 10.");
static PyObject *
GMPy_MPQ_Method_Round(PyObject *self, PyObject *args)
{
Py_ssize_t round_digits = 0;
MPQ_Object *resultq;
MPZ_Object *resultz;
mpz_t temp, rem;
CTXT_Object *context = NULL;
CHECK_CONTEXT(context);
/* If args is NULL or the size of args is 0, we just return an mpz. */
if (!args || PyTuple_GET_SIZE(args) == 0) {
if (!(resultz = GMPy_MPZ_New(context))) {
return NULL;
}
mpz_init(rem);
mpz_fdiv_qr(resultz->z, rem, mpq_numref(MPQ(self)), mpq_denref(MPQ(self)));
mpz_mul_2exp(rem, rem, 1);
if (mpz_cmp(rem, mpq_denref(MPQ(self))) > 0) {
mpz_add_ui(resultz->z, resultz->z, 1);
}
else if (mpz_cmp(rem, mpq_denref(MPQ(self))) == 0) {
if (mpz_odd_p(resultz->z)) {
mpz_add_ui(resultz->z, resultz->z, 1);
}
}
mpz_clear(rem);
return (PyObject*)resultz;
}
if (PyTuple_GET_SIZE(args) > 1) {
TYPE_ERROR("Too many arguments for __round__()");
return NULL;
}
if (PyTuple_GET_SIZE(args) == 1) {
round_digits = PyLong_AsSsize_t(PyTuple_GET_ITEM(args, 0));
if (round_digits == -1 && PyErr_Occurred()) {
TYPE_ERROR("__round__() requires 'int' argument");
return NULL;
}
}
if (!(resultq = GMPy_MPQ_New(context))) {
return NULL;
}
mpz_init(temp);
mpz_ui_pow_ui(temp, 10, round_digits > 0 ? (unsigned long)round_digits : (unsigned long)-round_digits);
mpq_set(resultq->q, MPQ(self));
if (round_digits > 0) {
mpz_mul(mpq_numref(resultq->q), mpq_numref(resultq->q), temp);
mpq_canonicalize(resultq->q);
if (!(resultz = (MPZ_Object*)GMPy_MPQ_Method_Round((PyObject*)resultq, NULL))) {
mpz_clear(temp);
return NULL;
}
mpz_set(mpq_numref(resultq->q), resultz->z);
Py_DECREF((PyObject*)resultz);
mpz_set(mpq_denref(resultq->q), temp);
mpz_clear(temp);
mpq_canonicalize(resultq->q);
}
else {
mpz_mul(mpq_denref(resultq->q), mpq_denref(resultq->q), temp);
mpq_canonicalize(resultq->q);
if (!(resultz = (MPZ_Object*)GMPy_MPQ_Method_Round((PyObject*)resultq, NULL))) {
mpz_clear(temp);
return NULL;
}
mpq_set_ui(resultq->q, 0, 1);
mpz_mul(mpq_numref(resultq->q), resultz->z, temp);
Py_DECREF((PyObject*)resultz);
mpz_clear(temp);
mpq_canonicalize(resultq->q);
}
return (PyObject*)resultq;
}
static int
GMPy_MPQ_NonZero_Slot(MPQ_Object *self)
{
return mpq_sgn(self->q) != 0;
}
PyDoc_STRVAR(GMPy_doc_mpq_method_sizeof,
"x.__sizeof__()\n\n"
"Returns the amount of memory consumed by x. Note: deleted mpq objects\n"
"are reused and may or may not be resized when a new value is assigned.");
static PyObject *
GMPy_MPQ_Method_Sizeof(PyObject *self, PyObject *other)
{
return PyLong_FromSize_t(sizeof(MPQ_Object) + \
(mpq_numref(MPQ(self))->_mp_alloc * sizeof(mp_limb_t)) + \
(mpq_denref(MPQ(self))->_mp_alloc * sizeof(mp_limb_t)));
}
././@PaxHeader 0000000 0000000 0000000 00000000026 00000000000 010213 x ustar 00 22 mtime=1710307256.0
gmpy2-2.2.1/src/gmpy2_mpq_misc.h 0000644 0001750 0001750 00000006120 14574233670 015122 0 ustar 00case case /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* gmpy2_mpq_misc.h *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Python interface to the GMP, MPFR, and MPC multiple precision *
* libraries. *
* *
* Copyright 2000 - 2009 Alex Martelli *
* *
* Copyright 2008 - 2024 Case Van Horsen *
* *
* This file is part of GMPY2. *
* *
* GMPY2 is free software: you can redistribute it and/or modify it under *
* the terms of the GNU Lesser General Public License as published by the *
* Free Software Foundation, either version 3 of the License, or (at your *
* option) any later version. *
* *
* GMPY2 is distributed in the hope that it will be useful, but WITHOUT *
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or *
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public *
* License for more details. *
* *
* You should have received a copy of the GNU Lesser General Public *
* License along with GMPY2; if not, see *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
#ifndef GMPY_MPQ_MISC_H
#define GMPY_MPQ_MISC_H
#ifdef __cplusplus
extern "C" {
#endif
static PyObject * GMPy_MPQ_Attrib_GetNumer(MPQ_Object *self, void *closure);
static PyObject * GMPy_MPQ_Attrib_GetDenom(MPQ_Object *self, void *closure);
static PyObject * GMPy_MPQ_Attrib_GetReal(MPQ_Object *self, void *closure);
static PyObject * GMPy_MPQ_Attrib_GetImag(MPQ_Object *self, void *closure);
static PyObject * GMPy_MPQ_Method_As_Integer_Ratio(PyObject *self, PyObject *Py_UNUSED(ignored));
static PyObject * GMPy_MPQ_Method_From_As_Integer_Ratio(PyTypeObject *type, PyObject *const *args, Py_ssize_t nargs);
static PyObject * GMPy_MPQ_Function_Numer(PyObject *self, PyObject *other);
static PyObject * GMPy_MPQ_Function_Denom(PyObject *self, PyObject *other);
static PyObject * GMPy_MPQ_Function_Qdiv(PyObject *self, PyObject *args);
static PyObject * GMPy_MPQ_Method_Ceil(PyObject *self, PyObject *other);
static PyObject * GMPy_MPQ_Method_Floor(PyObject *self, PyObject *other);
static PyObject * GMPy_MPQ_Method_Trunc(PyObject *self, PyObject *other);
static PyObject * GMPy_MPQ_Method_Round(PyObject *self, PyObject *other);
static int GMPy_MPQ_NonZero_Slot(MPQ_Object *x);
#ifdef __cplusplus
}
#endif
#endif
././@PaxHeader 0000000 0000000 0000000 00000000026 00000000000 010213 x ustar 00 22 mtime=1718253275.0
gmpy2-2.2.1/src/gmpy2_mpz.c 0000644 0001750 0001750 00000017506 14632473333 014122 0 ustar 00case case /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* gmpy2_mpz.c *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Python interface to the GMP, MPFR, and MPC multiple precision *
* libraries. *
* *
* Copyright 2000 - 2009 Alex Martelli *
* *
* Copyright 2008 - 2024 Case Van Horsen *
* *
* This file is part of GMPY2. *
* *
* GMPY2 is free software: you can redistribute it and/or modify it under *
* the terms of the GNU Lesser General Public License as published by the *
* Free Software Foundation, either version 3 of the License, or (at your *
* option) any later version. *
* *
* GMPY2 is distributed in the hope that it will be useful, but WITHOUT *
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or *
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public *
* License for more details. *
* *
* You should have received a copy of the GNU Lesser General Public *
* License along with GMPY2; if not, see *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
PyDoc_STRVAR(GMPy_doc_mpz,
"mpz(n=0, /)\n"
"mpz(s, /, base=0)\n\n"
"Return an immutable integer constructed from a numeric value n (truncating\n"
"n to its integer part) or a string s made of digits in the given base.\n"
"Every input, that is accepted by the `int` type constructor is also accepted.\n\n"
"The base may vary from 2 to 62, or if base is 0, then binary, octal, or\n"
"hexadecimal strings are recognized by leading '0b', '0o', or '0x'\n"
"characters (case is ignored), otherwise the string is assumed to be\n"
"decimal. For bases up to 36, digits case is ignored. For bases 37\n"
"to 62, upper-case letter represent the usual 10..35 range, while\n"
"lower-case letter represent 36..61. Optionally the string can be\n"
"preceded by '+' or '-'. White space and underscore is simply ignored.");
/* Since `gmpy2.mpz` is now a type and no longer a factory function, see
* gmpy2_cache.c/GMPy_MPZ_NewInit for details on creation.
*/
static PyNumberMethods GMPy_MPZ_number_methods = {
.nb_add = (binaryfunc) GMPy_Number_Add_Slot,
.nb_subtract = (binaryfunc) GMPy_Number_Sub_Slot,
.nb_multiply = (binaryfunc) GMPy_Number_Mul_Slot,
.nb_remainder = (binaryfunc) GMPy_Number_Mod_Slot,
.nb_divmod = (binaryfunc) GMPy_Number_DivMod_Slot,
.nb_power = (ternaryfunc) GMPy_Number_Pow_Slot,
.nb_negative = (unaryfunc) GMPy_MPZ_Minus_Slot,
.nb_positive = (unaryfunc) GMPy_MPZ_Plus_Slot,
.nb_absolute = (unaryfunc) GMPy_MPZ_Abs_Slot,
.nb_bool = (inquiry) GMPy_MPZ_NonZero_Slot,
.nb_invert = (unaryfunc) GMPy_MPZ_Invert_Slot,
.nb_lshift = (binaryfunc) GMPy_MPZ_Lshift_Slot,
.nb_rshift = (binaryfunc) GMPy_MPZ_Rshift_Slot,
.nb_and = (binaryfunc) GMPy_MPZ_And_Slot,
.nb_xor = (binaryfunc) GMPy_MPZ_Xor_Slot,
.nb_or = (binaryfunc) GMPy_MPZ_Ior_Slot,
.nb_int = (unaryfunc) GMPy_MPZ_Int_Slot,
.nb_float = (unaryfunc) GMPy_MPZ_Float_Slot,
.nb_floor_divide = (binaryfunc) GMPy_Number_FloorDiv_Slot,
.nb_true_divide = (binaryfunc) GMPy_Number_TrueDiv_Slot,
.nb_index = (unaryfunc) GMPy_MPZ_Int_Slot,
};
static PyMappingMethods GMPy_MPZ_mapping_methods = {
(lenfunc)GMPy_MPZ_Method_Length,
(binaryfunc)GMPy_MPZ_Method_SubScript,
NULL
};
static PyGetSetDef GMPy_MPZ_getseters[] = {
{ "numerator", (getter)GMPy_MPZ_Attrib_GetNumer, NULL,
"the numerator of a rational number in lowest terms", NULL },
{ "denominator", (getter)GMPy_MPZ_Attrib_GetDenom, NULL,
"the denominator of a rational number in lowest terms", NULL },
{ "real", (getter)GMPy_MPZ_Attrib_GetReal, NULL,
"the real part of a complex number", NULL },
{ "imag", (getter)GMPy_MPZ_Attrib_GetImag, NULL,
"the imaginary part of a complex number", NULL },
{NULL}
};
static PyMethodDef GMPy_MPZ_methods[] = {
{ "__format__", GMPy_MPZ_Format, METH_VARARGS, GMPy_doc_mpz_format },
{ "__ceil__", GMPy_MPZ_Method_Ceil, METH_NOARGS, GMPy_doc_mpz_method_ceil },
{ "__floor__", GMPy_MPZ_Method_Floor, METH_NOARGS, GMPy_doc_mpz_method_floor },
{ "__round__", (PyCFunction)GMPy_MPZ_Method_Round, METH_FASTCALL, GMPy_doc_mpz_method_round },
{ "__sizeof__", GMPy_MPZ_Method_SizeOf, METH_NOARGS, GMPy_doc_mpz_method_sizeof },
{ "__trunc__", GMPy_MPZ_Method_Trunc, METH_NOARGS, GMPy_doc_mpz_method_trunc },
{ "bit_clear", GMPy_MPZ_bit_clear_method, METH_O, doc_bit_clear_method },
{ "bit_count", GMPy_MPZ_bit_count_method, METH_NOARGS, doc_bit_count_method },
{ "bit_flip", GMPy_MPZ_bit_flip_method, METH_O, doc_bit_flip_method },
{ "bit_length", GMPy_MPZ_bit_length_method, METH_NOARGS, doc_bit_length_method },
{ "bit_scan0", (PyCFunction)GMPy_MPZ_bit_scan0_method, METH_FASTCALL, doc_bit_scan0_method },
{ "bit_scan1", (PyCFunction)GMPy_MPZ_bit_scan1_method, METH_FASTCALL, doc_bit_scan1_method },
{ "bit_set", GMPy_MPZ_bit_set_method, METH_O, doc_bit_set_method },
{ "bit_test", GMPy_MPZ_bit_test_method, METH_O, doc_bit_test_method },
{ "conjugate", GMPy_MP_Method_Conjugate, METH_NOARGS, GMPy_doc_mp_method_conjugate },
{ "digits", GMPy_MPZ_Digits_Method, METH_VARARGS, GMPy_doc_mpz_digits_method },
{ "is_congruent", (PyCFunction)GMPy_MPZ_Method_IsCongruent, METH_FASTCALL, GMPy_doc_mpz_method_is_congruent },
{ "is_divisible", GMPy_MPZ_Method_IsDivisible, METH_O, GMPy_doc_mpz_method_is_divisible },
{ "is_even", GMPy_MPZ_Method_IsEven, METH_NOARGS, GMPy_doc_mpz_method_is_even },
{ "is_odd", GMPy_MPZ_Method_IsOdd, METH_NOARGS, GMPy_doc_mpz_method_is_odd },
{ "is_power", GMPy_MPZ_Method_IsPower, METH_NOARGS, GMPy_doc_mpz_method_is_power },
{ "is_prime", (PyCFunction)GMPy_MPZ_Method_IsPrime, METH_FASTCALL, GMPy_doc_mpz_method_is_prime },
{ "is_probab_prime", (PyCFunction)GMPy_MPZ_Method_IsProbabPrime, METH_FASTCALL, GMPy_doc_mpz_method_is_probab_prime },
{ "is_square", GMPy_MPZ_Method_IsSquare, METH_NOARGS, GMPy_doc_mpz_method_is_square },
{ "num_digits", (PyCFunction)GMPy_MPZ_Method_NumDigits, METH_FASTCALL, GMPy_doc_mpz_method_num_digits },
{ "as_integer_ratio", GMPy_MPZ_Method_As_Integer_Ratio, METH_NOARGS, GMPy_doc_mpz_method_as_integer_ratio },
{ "to_bytes", (PyCFunction)GMPy_MPZ_Method_To_Bytes, METH_FASTCALL | METH_KEYWORDS, GMPy_doc_mpz_method_to_bytes },
{ "from_bytes", (PyCFunction)GMPy_MPZ_Method_From_Bytes, METH_FASTCALL | METH_KEYWORDS | METH_CLASS, GMPy_doc_mpz_method_from_bytes },
{ NULL }
};
static PyTypeObject MPZ_Type = {
PyVarObject_HEAD_INIT(NULL, 0)
.tp_name = "gmpy2.mpz",
.tp_basicsize = sizeof(MPZ_Object),
.tp_dealloc = (destructor) GMPy_MPZ_Dealloc,
.tp_repr = (reprfunc) GMPy_MPZ_Repr_Slot,
.tp_as_number = &GMPy_MPZ_number_methods,
.tp_as_mapping = &GMPy_MPZ_mapping_methods,
.tp_hash = (hashfunc) GMPy_MPZ_Hash_Slot,
.tp_str = (reprfunc) GMPy_MPZ_Str_Slot,
.tp_flags = Py_TPFLAGS_DEFAULT,
.tp_doc = GMPy_doc_mpz,
.tp_richcompare = (richcmpfunc)&GMPy_RichCompare_Slot,
.tp_methods = GMPy_MPZ_methods,
.tp_getset = GMPy_MPZ_getseters,
.tp_new = GMPy_MPZ_NewInit,
};
././@PaxHeader 0000000 0000000 0000000 00000000026 00000000000 010213 x ustar 00 22 mtime=1710307256.0
gmpy2-2.2.1/src/gmpy2_mpz.h 0000644 0001750 0001750 00000004177 14574233670 014132 0 ustar 00case case /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* gmpy2_mpz.h *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Python interface to the GMP, MPFR, and MPC multiple precision *
* libraries. *
* *
* Copyright 2000 - 2009 Alex Martelli *
* *
* Copyright 2008 - 2024 Case Van Horsen *
* *
* This file is part of GMPY2. *
* *
* GMPY2 is free software: you can redistribute it and/or modify it under *
* the terms of the GNU Lesser General Public License as published by the *
* Free Software Foundation, either version 3 of the License, or (at your *
* option) any later version. *
* *
* GMPY2 is distributed in the hope that it will be useful, but WITHOUT *
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or *
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public *
* License for more details. *
* *
* You should have received a copy of the GNU Lesser General Public *
* License along with GMPY2; if not, see *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
#ifndef GMPY_MPZ_H
#define GMPY_MPZ_H
#ifdef __cplusplus
extern "C" {
#endif
static PyTypeObject MPZ_Type;
#define MPZ(obj) (((MPZ_Object*)(obj))->z)
#define MPZ_Check(v) (((PyObject*)v)->ob_type == &MPZ_Type)
#ifdef __cplusplus
}
#endif
#endif
././@PaxHeader 0000000 0000000 0000000 00000000026 00000000000 010213 x ustar 00 22 mtime=1710307256.0
gmpy2-2.2.1/src/gmpy2_mpz_bitops.c 0000644 0001750 0001750 00000051334 14574233670 015502 0 ustar 00case case /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* gmpy2_mpz_bitops.c *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Python interface to the GMP, MPFR, and MPC multiple precision *
* libraries. *
* *
* Copyright 2000 - 2009 Alex Martelli *
* *
* Copyright 2008 - 2024 Case Van Horsen *
* *
* This file is part of GMPY2. *
* *
* GMPY2 is free software: you can redistribute it and/or modify it under *
* the terms of the GNU Lesser General Public License as published by the *
* Free Software Foundation, either version 3 of the License, or (at your *
* option) any later version. *
* *
* GMPY2 is distributed in the hope that it will be useful, but WITHOUT *
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or *
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public *
* License for more details. *
* *
* You should have received a copy of the GNU Lesser General Public *
* License along with GMPY2; if not, see *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
PyDoc_STRVAR(doc_bit_length_method,
"x.bit_length() -> int\n\n"
"Return the number of significant bits in the radix-2\n"
"representation of x. Note: mpz(0).bit_length() returns 0.");
static PyObject *
GMPy_MPZ_bit_length_method(PyObject *self, PyObject *other)
{
mp_bitcnt_t n = 0;
if (mpz_size(MPZ(self)))
n = mpz_sizeinbase(MPZ(self), 2);
return GMPy_PyLong_FromMpBitCnt(n);
}
PyDoc_STRVAR(doc_bit_length_function,
"bit_length(x, /) -> int\n\n"
"Return the number of significant bits in the radix-2\n"
"representation of x. Note: bit_length(0) returns 0.");
static PyObject *
GMPy_MPZ_bit_length_function(PyObject *self, PyObject *other)
{
mp_bitcnt_t n = 0;
MPZ_Object* tempx;
if (!(tempx = GMPy_MPZ_From_Integer(other, NULL))) {
TYPE_ERROR("bit_length() requires 'mpz' argument");
return NULL;
}
if (mpz_size(MPZ(tempx)))
n = mpz_sizeinbase(tempx->z, 2);
Py_DECREF((PyObject*)tempx);
return GMPy_PyLong_FromMpBitCnt(n);
}
PyDoc_STRVAR(doc_bit_mask,
"bit_mask(n, /) -> mpz\n\n"
"Return an `mpz` exactly n bits in length with all bits set.\n");
static PyObject *
GMPy_MPZ_bit_mask(PyObject *self, PyObject *other)
{
mp_bitcnt_t n = 0;
MPZ_Object* result;
n = GMPy_Integer_AsMpBitCnt(other);
if (n == (mp_bitcnt_t)(-1) && PyErr_Occurred()) {
return NULL;
}
if (!(result = GMPy_MPZ_New(NULL)))
return NULL;
mpz_set_ui(result->z, 1);
mpz_mul_2exp(result->z, result->z, n);
mpz_sub_ui(result->z, result->z, 1);
return (PyObject*)result;
}
/* return scan0/scan1 for an mpz */
PyDoc_STRVAR(doc_bit_scan0_method,
"x.bit_scan0(n=0, /) -> int | None\n\n"
"Return the index of the first 0-bit of x with index >= n. n >= 0.\n"
"If there are no more 0-bits in x at or above index n (which can\n"
"only happen for x<0, assuming an infinitely long 2's complement\n"
"format), then `None` is returned.");
static PyObject *
GMPy_MPZ_bit_scan0_method(PyObject *self, PyObject *const *args,
Py_ssize_t nargs)
{
mp_bitcnt_t index, starting_bit = 0;
if (nargs == 1) {
starting_bit = GMPy_Integer_AsMpBitCnt(args[0]);
if (starting_bit == (mp_bitcnt_t)(-1) && PyErr_Occurred()) {
return NULL;
}
}
index = mpz_scan0(MPZ(self), starting_bit);
if (index == (mp_bitcnt_t)(-1)) {
Py_RETURN_NONE;
}
else {
return GMPy_PyLong_FromMpBitCnt(index);
}
}
PyDoc_STRVAR(doc_bit_scan0_function,
"bit_scan0(x, n=0, /) -> int | None\n\n"
"Return the index of the first 0-bit of x with index >= n. n >= 0.\n"
"If there are no more 0-bits in x at or above index n (which can\n"
"only happen for x<0, assuming an infinitely long 2's complement\n"
"format), then `None` is returned.");
static PyObject *
GMPy_MPZ_bit_scan0_function(PyObject *self, PyObject *const *args,
Py_ssize_t nargs)
{
mp_bitcnt_t index, starting_bit = 0;
MPZ_Object *tempx = NULL;
if (nargs == 0 || nargs > 2) {
goto err;
}
if (!(tempx = GMPy_MPZ_From_Integer(args[0], NULL))) {
goto err;
}
if (nargs == 2) {
starting_bit = GMPy_Integer_AsMpBitCnt(args[1]);
if (starting_bit == (mp_bitcnt_t)(-1) && PyErr_Occurred()) {
goto err_index;
}
}
index = mpz_scan0(tempx->z, starting_bit);
Py_DECREF((PyObject*)tempx);
if (index == (mp_bitcnt_t)(-1)) {
Py_RETURN_NONE;
}
else {
return GMPy_PyLong_FromMpBitCnt(index);
}
err:
TYPE_ERROR("bit_scan0() requires 'mpz',['int'] arguments");
err_index:
Py_XDECREF((PyObject*)tempx);
return NULL;
}
PyDoc_STRVAR(doc_bit_scan1_method,
"x.bit_scan1(n=0, /) -> int | None\n\n"
"Return the index of the first 1-bit of x with index >= n. n >= 0.\n"
"If there are no more 1-bits in x at or above index n (which can\n"
"only happen for x>=0, assuming an infinitely long 2's complement\n"
"format), then `None` is returned.");
static PyObject *
GMPy_MPZ_bit_scan1_method(PyObject *self, PyObject *const *args,
Py_ssize_t nargs)
{
mp_bitcnt_t index, starting_bit = 0;
if (nargs == 1) {
starting_bit = GMPy_Integer_AsMpBitCnt(args[0]);
if (starting_bit == (mp_bitcnt_t)(-1) && PyErr_Occurred()) {
return NULL;
}
}
index = mpz_scan1(MPZ(self), starting_bit);
if (index == (mp_bitcnt_t)(-1)) {
Py_RETURN_NONE;
}
else {
return GMPy_PyLong_FromMpBitCnt(index);
}
}
PyDoc_STRVAR(doc_bit_scan1_function,
"bit_scan1(x, n=0, /) -> int | None\n\n"
"Return the index of the first 1-bit of x with index >= n. n >= 0.\n"
"If there are no more 1-bits in x at or above index n (which can\n"
"only happen for x>=0, assuming an infinitely long 2's complement\n"
"format), then `None` is returned.");
static PyObject *
GMPy_MPZ_bit_scan1_function(PyObject *self, PyObject *const *args,
Py_ssize_t nargs)
{
mp_bitcnt_t index, starting_bit = 0;
MPZ_Object *tempx = NULL;
if (nargs == 0 || nargs > 2) {
goto err;
}
if (!(tempx = GMPy_MPZ_From_Integer(args[0], NULL))) {
goto err;
}
if (nargs == 2) {
starting_bit = GMPy_Integer_AsMpBitCnt(args[1]);
if (starting_bit == (mp_bitcnt_t)(-1) && PyErr_Occurred()) {
goto err_index;
}
}
index = mpz_scan1(tempx->z, starting_bit);
Py_DECREF((PyObject*)tempx);
if (index == (mp_bitcnt_t)(-1)) {
Py_RETURN_NONE;
}
else {
return GMPy_PyLong_FromMpBitCnt(index);
}
err:
TYPE_ERROR("bit_scan1() requires 'mpz',['int'] arguments");
err_index:
Py_XDECREF((PyObject*)tempx);
return NULL;
}
/* get & return one bit from an mpz */
PyDoc_STRVAR(doc_bit_test_function,
"bit_test(x, n, /) -> bool\n\n"
"Return the value of the n-th bit of x.");
static PyObject *
GMPy_MPZ_bit_test_function(PyObject *self, PyObject *const *args,
Py_ssize_t nargs)
{
mp_bitcnt_t bit_index;
int temp;
MPZ_Object *tempx = NULL;
if (nargs != 2) {
goto err;
}
if (!(tempx = GMPy_MPZ_From_Integer(args[0], NULL))) {
goto err;
}
bit_index = GMPy_Integer_AsMpBitCnt(args[1]);
if (bit_index == (mp_bitcnt_t)(-1) && PyErr_Occurred()) {
goto err_index;
}
temp = mpz_tstbit(tempx->z, bit_index);
Py_DECREF((PyObject*)tempx);
if (temp)
Py_RETURN_TRUE;
else
Py_RETURN_FALSE;
err:
TYPE_ERROR("bit_test() requires 'mpz','int' arguments");
err_index:
Py_XDECREF((PyObject*)tempx);
return NULL;
}
PyDoc_STRVAR(doc_bit_test_method,
"x.bit_test(n, /) -> bool\n\n"
"Return the value of the n-th bit of x.");
static PyObject *
GMPy_MPZ_bit_test_method(PyObject *self, PyObject *other)
{
mp_bitcnt_t bit_index;
bit_index = GMPy_Integer_AsMpBitCnt(other);
if (bit_index == (mp_bitcnt_t)(-1) && PyErr_Occurred()) {
return NULL;
}
if (mpz_tstbit(MPZ(self), bit_index))
Py_RETURN_TRUE;
else
Py_RETURN_FALSE;
}
PyDoc_STRVAR(doc_bit_clear_function,
"bit_clear(x, n, /) -> mpz\n\n"
"Return a copy of x with the n-th bit cleared.");
static PyObject *
GMPy_MPZ_bit_clear_function(PyObject *self, PyObject *args)
{
mp_bitcnt_t bit_index;
MPZ_Object *result = NULL, *tempx = NULL;
if (PyTuple_GET_SIZE(args) != 2)
goto err;
if (!(result = GMPy_MPZ_New(NULL)))
return NULL;
if (!(tempx = GMPy_MPZ_From_Integer(PyTuple_GET_ITEM(args, 0), NULL)))
goto err;
bit_index = GMPy_Integer_AsMpBitCnt(PyTuple_GET_ITEM(args, 1));
if (bit_index == (mp_bitcnt_t)(-1) && PyErr_Occurred())
goto err_index;
mpz_set(result->z, tempx->z);
mpz_clrbit(result->z, bit_index);
Py_DECREF((PyObject*)tempx);
return (PyObject*)result;
err:
TYPE_ERROR("bit_clear() requires 'mpz','int' arguments");
err_index:
Py_XDECREF((PyObject*)result);
Py_XDECREF((PyObject*)tempx);
return NULL;
}
PyDoc_STRVAR(doc_bit_clear_method,
"x.bit_clear(n, /) -> mpz\n\n"
"Return a copy of x with the n-th bit cleared.");
static PyObject *
GMPy_MPZ_bit_clear_method(PyObject *self, PyObject *other)
{
mp_bitcnt_t bit_index;
MPZ_Object *result = NULL;
if (!(result = GMPy_MPZ_New(NULL)))
return NULL;
bit_index = GMPy_Integer_AsMpBitCnt(other);
if (bit_index == (mp_bitcnt_t)(-1) && PyErr_Occurred()) {
Py_DECREF(result);
return NULL;
}
mpz_set(result->z, MPZ(self));
mpz_clrbit(result->z, bit_index);
return (PyObject*)result;
}
PyDoc_STRVAR(doc_bit_set_function,
"bit_set(x, n, /) -> mpz\n\n"
"Return a copy of x with the n-th bit set.");
static PyObject *
GMPy_MPZ_bit_set_function(PyObject *self, PyObject *args)
{
mp_bitcnt_t bit_index;
MPZ_Object *result = NULL, *tempx = NULL;
if (PyTuple_GET_SIZE(args) != 2)
goto err;
if (!(result = GMPy_MPZ_New(NULL)))
return NULL;
if (!(tempx = GMPy_MPZ_From_Integer(PyTuple_GET_ITEM(args, 0), NULL)))
goto err;
bit_index = GMPy_Integer_AsMpBitCnt(PyTuple_GET_ITEM(args, 1));
if (bit_index == (mp_bitcnt_t)(-1) && PyErr_Occurred())
goto err_index;
mpz_set(result->z, tempx->z);
mpz_setbit(result->z, bit_index);
Py_DECREF((PyObject*)tempx);
return (PyObject*)result;
err:
TYPE_ERROR("bit_set() requires 'mpz','int' arguments");
err_index:
Py_XDECREF((PyObject*)result);
Py_XDECREF((PyObject*)tempx);
return NULL;
}
PyDoc_STRVAR(doc_bit_set_method,
"x.bit_set(n, /) -> mpz\n\n"
"Return a copy of x with the n-th bit set.");
static PyObject *
GMPy_MPZ_bit_set_method(PyObject *self, PyObject *other)
{
mp_bitcnt_t bit_index;
MPZ_Object *result = NULL;
if (!(result = GMPy_MPZ_New(NULL)))
return NULL;
bit_index = GMPy_Integer_AsMpBitCnt(other);
if (bit_index == (mp_bitcnt_t)(-1) && PyErr_Occurred()) {
Py_DECREF(result);
return NULL;
}
mpz_set(result->z, MPZ(self));
mpz_setbit(result->z, bit_index);
return (PyObject*)result;
}
PyDoc_STRVAR(doc_bit_flip_function,
"bit_flip(x, n, /) -> mpz\n\n"
"Return a copy of x with the n-th bit inverted.");
static PyObject *
GMPy_MPZ_bit_flip_function(PyObject *self, PyObject *args)
{
mp_bitcnt_t bit_index;
MPZ_Object *result = NULL, *tempx = NULL;
if (PyTuple_GET_SIZE(args) != 2)
goto err;
if (!(result = GMPy_MPZ_New(NULL)))
return NULL;
if (!(tempx = GMPy_MPZ_From_Integer(PyTuple_GET_ITEM(args, 0), NULL)))
goto err;
bit_index = GMPy_Integer_AsMpBitCnt(PyTuple_GET_ITEM(args, 1));
if (bit_index == (mp_bitcnt_t)(-1) && PyErr_Occurred())
goto err_index;
mpz_set(result->z, tempx->z);
mpz_combit(result->z, bit_index);
Py_DECREF((PyObject*)tempx);
return (PyObject*)result;
err:
TYPE_ERROR("bit_flip() requires 'mpz','int' arguments");
err_index:
Py_XDECREF((PyObject*)result);
Py_XDECREF((PyObject*)tempx);
return NULL;
}
PyDoc_STRVAR(doc_bit_flip_method,
"x.bit_flip(n, /) -> mpz\n\n"
"Return a copy of x with the n-th bit inverted.");
static PyObject *
GMPy_MPZ_bit_flip_method(PyObject *self, PyObject *other)
{
mp_bitcnt_t bit_index;
MPZ_Object *result = NULL;
if (!(result = GMPy_MPZ_New(NULL)))
return NULL;
bit_index = GMPy_Integer_AsMpBitCnt(other);
if (bit_index == (mp_bitcnt_t)(-1) && PyErr_Occurred()) {
Py_DECREF(result);
return NULL;
}
mpz_set(result->z, MPZ(self));
mpz_combit(result->z, bit_index);
return (PyObject*)result;
}
static PyObject *
GMPy_MPZ_Invert_Slot(MPZ_Object *self)
{
MPZ_Object *result;
if ((result = GMPy_MPZ_New(NULL)))
mpz_com(result->z, MPZ(self));
return (PyObject*)result;
}
static PyObject *
GMPy_MPZ_And_Slot(PyObject *self, PyObject *other)
{
MPZ_Object *result;
if (CHECK_MPZANY(self)) {
if (CHECK_MPZANY(other)) {
if (!(result = GMPy_MPZ_New(NULL)))
return NULL;
mpz_and(result->z, MPZ(self), MPZ(other));
}
else {
if (!(result = GMPy_MPZ_From_Integer(other, NULL)))
return NULL;
mpz_and(result->z, MPZ(self), result->z);
}
}
else if (CHECK_MPZANY(other)) {
if (!(result = GMPy_MPZ_From_Integer(self, NULL)))
return NULL;
mpz_and(result->z, result->z, MPZ(other));
}
else {
/* LCOV_EXCL_START */
Py_RETURN_NOTIMPLEMENTED;
/* LCOV_EXCL_STOP */
}
return (PyObject*)result;
}
static PyObject *
GMPy_MPZ_Ior_Slot(PyObject *self, PyObject *other)
{
MPZ_Object *result;
if (CHECK_MPZANY(self)) {
if (CHECK_MPZANY(other)) {
if (!(result = GMPy_MPZ_New(NULL)))
return NULL;
mpz_ior(result->z, MPZ(self), MPZ(other));
}
else {
if (!(result = GMPy_MPZ_From_Integer(other, NULL)))
return NULL;
mpz_ior(result->z, MPZ(self), result->z);
}
}
else if (CHECK_MPZANY(other)) {
if (!(result = GMPy_MPZ_From_Integer(self, NULL)))
return NULL;
mpz_ior(result->z, result->z, MPZ(other));
}
else {
/* LCOV_EXCL_START */
Py_RETURN_NOTIMPLEMENTED;
/* LCOV_EXCL_STOP */
}
return (PyObject*)result;
}
static PyObject *
GMPy_MPZ_Xor_Slot(PyObject *self, PyObject *other)
{
MPZ_Object *result;
if (CHECK_MPZANY(self)) {
if (CHECK_MPZANY(other)) {
if (!(result = GMPy_MPZ_New(NULL)))
return NULL;
mpz_xor(result->z, MPZ(self), MPZ(other));
}
else {
if (!(result = GMPy_MPZ_From_Integer(other, NULL)))
return NULL;
mpz_xor(result->z, MPZ(self), result->z);
}
}
else if (CHECK_MPZANY(other)) {
if (!(result = GMPy_MPZ_From_Integer(self, NULL)))
return NULL;
mpz_xor(result->z, result->z, MPZ(other));
}
else {
/* LCOV_EXCL_START */
Py_RETURN_NOTIMPLEMENTED;
/* LCOV_EXCL_STOP */
}
return (PyObject*)result;
}
static PyObject *
GMPy_MPZ_Rshift_Slot(PyObject *self, PyObject *other)
{
mp_bitcnt_t count;
MPZ_Object *result, *tempx;
count = GMPy_Integer_AsMpBitCnt(other);
if ((count == (mp_bitcnt_t)(-1)) && PyErr_Occurred())
return NULL;
if (!(result = GMPy_MPZ_New(NULL)))
return NULL;
if (CHECK_MPZANY(self)) {
mpz_fdiv_q_2exp(result->z, MPZ(self), count);
return (PyObject*)result;
}
else {
if (!(tempx = GMPy_MPZ_From_Integer(self, NULL))) {
Py_XDECREF((PyObject*)result);
Py_XDECREF((PyObject*)tempx);
return NULL;
}
mpz_fdiv_q_2exp(result->z, tempx->z, count);
Py_DECREF((PyObject*)tempx);
return (PyObject*)result;
}
}
static PyObject *
GMPy_MPZ_Lshift_Slot(PyObject *self, PyObject *other)
{
mp_bitcnt_t count;
MPZ_Object *result, *tempx;
count = GMPy_Integer_AsMpBitCnt(other);
if ((count == (mp_bitcnt_t)(-1)) && PyErr_Occurred())
return NULL;
if (!(result = GMPy_MPZ_New(NULL)))
return NULL;
if (CHECK_MPZANY(self)) {
mpz_mul_2exp(result->z, MPZ(self), count);
return (PyObject*)result;
}
else {
if (!(tempx = GMPy_MPZ_From_Integer(self, NULL))) {
Py_XDECREF((PyObject*)result);
Py_XDECREF((PyObject*)tempx);
return NULL;
}
mpz_mul_2exp(result->z, tempx->z, count);
Py_DECREF((PyObject*)tempx);
return (PyObject*)result;
}
}
PyDoc_STRVAR(doc_popcount,
"popcount(x, /) -> int\n\n"
"Return the number of 1-bits set in x. If x<0, the number of\n"
"1-bits is infinite so -1 is returned in that case.");
static PyObject *
GMPy_MPZ_popcount(PyObject *self, PyObject *other)
{
mp_bitcnt_t n;
MPZ_Object *tempx;
if ((tempx = GMPy_MPZ_From_Integer(other, NULL))) {
n = mpz_popcount(tempx->z);
Py_DECREF((PyObject*)tempx);
if (n == (mp_bitcnt_t)(-1))
return PyLong_FromLong(-1);
else
return GMPy_PyLong_FromMpBitCnt(n);
}
else {
TYPE_ERROR("popcount() requires 'mpz' argument");
return NULL;
}
}
PyDoc_STRVAR(doc_bit_count_method,
"x.bit_count() -> int\n\n"
"Return the number of 1-bits set in abs(x).");
static PyObject *
GMPy_MPZ_bit_count_method(PyObject *self, PyObject *other)
{
mp_bitcnt_t n = 0;
MPZ_Object *temppos = NULL;
/* Since tempx could just be an additional reference to
* an existing mpz, we need to make a copy to change the
* sign.
*/
if (mpz_sgn(MPZ(self)) == -1) {
if (!(temppos = GMPy_MPZ_New(NULL))) {
/* LCOV_EXCL_START */
return NULL;
/* LCOV_EXCL_STOP */
}
mpz_abs(MPZ(temppos), MPZ(self));
n = mpz_popcount(MPZ(temppos));
Py_DECREF((PyObject*)temppos);
}
else {
n = mpz_popcount(MPZ(self));
}
return GMPy_PyLong_FromMpBitCnt(n);
}
PyDoc_STRVAR(doc_bit_count,
"bit_count(x, /) -> int\n\n"
"Return the number of 1-bits set in abs(x).");
static PyObject *
GMPy_MPZ_bit_count(PyObject *self, PyObject *other)
{
mp_bitcnt_t n;
MPZ_Object *tempx = NULL, *temppos = NULL;
if ((tempx = GMPy_MPZ_From_Integer(other, NULL))) {
/* Since tempx could just be an additional reference to
* an existing mpz, we need to make a copy to change the
* sign.
*/
if (mpz_sgn(MPZ(tempx)) == -1) {
if (!(temppos = GMPy_MPZ_New(NULL))) {
/* LCOV_EXCL_START */
return NULL;
/* LCOV_EXCL_STOP */
}
mpz_abs(MPZ(temppos), MPZ(tempx));
n = mpz_popcount(MPZ(temppos));
Py_DECREF((PyObject*)tempx);
Py_DECREF((PyObject*)temppos);
}
else {
n = mpz_popcount(MPZ(tempx));
Py_DECREF((PyObject*)tempx);
}
return GMPy_PyLong_FromMpBitCnt(n);
}
else {
TYPE_ERROR("bit_count() requires 'mpz' argument");
return NULL;
}
}
PyDoc_STRVAR(doc_hamdist,
"hamdist(x, y, /) -> int\n\n"
"Return the Hamming distance (number of bit-positions where the\n"
"bits differ) between integers x and y.");
static PyObject *
GMPy_MPZ_hamdist(PyObject *self, PyObject *args)
{
PyObject *result = NULL;
MPZ_Object *tempx = NULL, *tempy = NULL;
if (PyTuple_GET_SIZE(args) != 2)
goto err;
tempx = GMPy_MPZ_From_Integer(PyTuple_GET_ITEM(args, 0), NULL);
tempy = GMPy_MPZ_From_Integer(PyTuple_GET_ITEM(args, 1), NULL);
if (!tempx || !tempy)
goto err;
result = GMPy_PyLong_FromMpBitCnt(mpz_hamdist(tempx->z, tempy->z));
Py_DECREF((PyObject*)tempx);
Py_DECREF((PyObject*)tempy);
return result;
err:
TYPE_ERROR("hamdist() requires 'mpz','mpz' arguments");
Py_XDECREF((PyObject*)tempx);
Py_XDECREF((PyObject*)tempy);
return NULL;
}
././@PaxHeader 0000000 0000000 0000000 00000000026 00000000000 010213 x ustar 00 22 mtime=1710307256.0
gmpy2-2.2.1/src/gmpy2_mpz_bitops.h 0000644 0001750 0001750 00000007472 14574233670 015513 0 ustar 00case case /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* gmpy2_mpz_bitops.h *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Python interface to the GMP, MPFR, and MPC multiple precision *
* libraries. *
* *
* Copyright 2000 - 2009 Alex Martelli *
* *
* Copyright 2008 - 2024 Case Van Horsen *
* *
* This file is part of GMPY2. *
* *
* GMPY2 is free software: you can redistribute it and/or modify it under *
* the terms of the GNU Lesser General Public License as published by the *
* Free Software Foundation, either version 3 of the License, or (at your *
* option) any later version. *
* *
* GMPY2 is distributed in the hope that it will be useful, but WITHOUT *
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or *
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public *
* License for more details. *
* *
* You should have received a copy of the GNU Lesser General Public *
* License along with GMPY2; if not, see *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
#ifndef GMPY_MPZ_BITOPS_H
#define GMPY_MPZ_BITOPS_H
#ifdef __cplusplus
extern "C" {
#endif
static PyObject * GMPy_MPZ_bit_length_function(PyObject *self, PyObject *other);
static PyObject * GMPy_MPZ_bit_length_method(PyObject *self, PyObject *other);
static PyObject * GMPy_MPZ_bit_mask(PyObject *self, PyObject *other);
static PyObject * GMPy_MPZ_bit_scan0_function(PyObject *self, PyObject *const *args, Py_ssize_t nargs);
static PyObject * GMPy_MPZ_bit_scan0_method(PyObject *self, PyObject *const *args, Py_ssize_t nargs);
static PyObject * GMPy_MPZ_bit_scan1_function(PyObject *self, PyObject *const *args, Py_ssize_t nargs);
static PyObject * GMPy_MPZ_bit_scan1_method(PyObject *self, PyObject *const *args, Py_ssize_t nargs);
static PyObject * GMPy_MPZ_bit_test_function(PyObject *self, PyObject *const *args, Py_ssize_t nargs);
static PyObject * GMPy_MPZ_bit_test_method(PyObject *self, PyObject *other);
static PyObject * GMPy_MPZ_bit_clear_function(PyObject *self, PyObject *args);
static PyObject * GMPy_MPZ_bit_clear_method(PyObject *self, PyObject *other);
static PyObject * GMPy_MPZ_bit_set_function(PyObject *self, PyObject *args);
static PyObject * GMPy_MPZ_bit_set_method(PyObject *self, PyObject *other);
static PyObject * GMPy_MPZ_bit_flip_function(PyObject *self, PyObject *args);
static PyObject * GMPy_MPZ_bit_flip_method(PyObject *self, PyObject *other);
static PyObject * GMPy_MPZ_popcount(PyObject *self, PyObject *other);
static PyObject * GMPy_MPZ_hamdist(PyObject *self, PyObject *args);
static PyObject * GMPy_MPZ_Invert_Slot(MPZ_Object *self);
static PyObject * GMPy_MPZ_And_Slot(PyObject *self, PyObject *other);
static PyObject * GMPy_MPZ_Ior_Slot(PyObject *self, PyObject *other);
static PyObject * GMPy_MPZ_Xor_Slot(PyObject *self, PyObject *other);
static PyObject * GMPy_MPZ_Rshift_Slot(PyObject *self, PyObject *other);
static PyObject * GMPy_MPZ_Lshift_Slot(PyObject *self, PyObject *other);
#ifdef __cplusplus
}
#endif
#endif
././@PaxHeader 0000000 0000000 0000000 00000000026 00000000000 010213 x ustar 00 22 mtime=1710307256.0
gmpy2-2.2.1/src/gmpy2_mpz_divmod.c 0000644 0001750 0001750 00000030713 14574233670 015462 0 ustar 00case case /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* gmpy2_mpz_divmod.c *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Python interface to the GMP, MPFR, and MPC multiple precision *
* libraries. *
* *
* Copyright 2000 - 2009 Alex Martelli *
* *
* Copyright 2008 - 2024 Case Van Horsen *
* *
* This file is part of GMPY2. *
* *
* GMPY2 is free software: you can redistribute it and/or modify it under *
* the terms of the GNU Lesser General Public License as published by the *
* Free Software Foundation, either version 3 of the License, or (at your *
* option) any later version. *
* *
* GMPY2 is distributed in the hope that it will be useful, but WITHOUT *
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or *
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public *
* License for more details. *
* *
* You should have received a copy of the GNU Lesser General Public *
* License along with GMPY2; if not, see *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
/* This file contains functions related to division and remainder. */
/*
**************************************************************************
* Ceiling division and remainder.
**************************************************************************
*/
PyDoc_STRVAR(doc_c_divmod,
"c_divmod(x, y, /) -> tuple[mpz, mpz]\n\n"
"Return the quotient and remainder of x divided by y. The quotient\n"
"is rounded towards +Inf (ceiling rounding) and the remainder will\n"
"have the opposite sign of y. x and y must be integers.");
static PyObject *
GMPy_MPZ_c_divmod(PyObject *self, PyObject *args)
{
PyObject *result = NULL;
MPZ_Object *q = NULL, *r = NULL, *tempx = NULL, *tempy = NULL;
if (PyTuple_GET_SIZE(args) != 2) {
TYPE_ERROR("c_divmod() requires 'mpz','mpz' arguments");
return NULL;
}
if (!(tempx = GMPy_MPZ_From_Integer(PyTuple_GET_ITEM(args, 0), NULL)) ||
!(tempy = GMPy_MPZ_From_Integer(PyTuple_GET_ITEM(args, 1), NULL)) ||
!(q = GMPy_MPZ_New(NULL)) ||
!(r = GMPy_MPZ_New(NULL)) ||
!(result = PyTuple_New(2))) {
goto err;
}
if (mpz_sgn(tempy->z) == 0) {
ZERO_ERROR("c_divmod() division by 0");
goto err;
}
mpz_cdiv_qr(q->z, r->z, tempx->z, tempy->z);
Py_DECREF((PyObject*)tempx);
Py_DECREF((PyObject*)tempy);
PyTuple_SET_ITEM(result, 0, (PyObject*)q);
PyTuple_SET_ITEM(result, 1, (PyObject*)r);
return result;
err:
Py_XDECREF(result);
Py_XDECREF((PyObject*)tempx);
Py_XDECREF((PyObject*)tempy);
Py_XDECREF((PyObject*)q);
Py_XDECREF((PyObject*)r);
return NULL;
}
PyDoc_STRVAR(doc_c_div,
"c_div(x, y, /) -> mpz\n\n"
"Return the quotient of x divided by y. The quotient is rounded\n"
"towards +Inf (ceiling rounding). x and y must be integers.");
static PyObject *
GMPy_MPZ_c_div(PyObject *self, PyObject *args)
{
MPZ_Object *q = NULL, *tempx = NULL, *tempy = NULL;
if (PyTuple_GET_SIZE(args) != 2) {
TYPE_ERROR("c_div() requires 'mpz','mpz' arguments");
return NULL;
}
if (!(tempx = GMPy_MPZ_From_Integer(PyTuple_GET_ITEM(args, 0), NULL)) ||
!(tempy = GMPy_MPZ_From_Integer(PyTuple_GET_ITEM(args, 1), NULL)) ||
!(q = GMPy_MPZ_New(NULL))) {
goto err;
}
if (mpz_sgn(tempy->z) == 0) {
ZERO_ERROR("c_div() division by 0");
goto err;
}
mpz_cdiv_q(q->z, tempx->z, tempy->z);
Py_DECREF((PyObject*)tempx);
Py_DECREF((PyObject*)tempy);
return (PyObject*)q;
err:
Py_XDECREF((PyObject*)tempx);
Py_XDECREF((PyObject*)tempy);
Py_XDECREF((PyObject*)q);
return NULL;
}
PyDoc_STRVAR(doc_c_mod,
"c_mod(x, y, /) -> mpz\n\n"
"Return the remainder of x divided by y. The remainder will have\n"
"the opposite sign of y. x and y must be integers.");
static PyObject *
GMPy_MPZ_c_mod(PyObject *self, PyObject *args)
{
MPZ_Object *r = NULL, *tempx = NULL, *tempy = NULL;
if (PyTuple_GET_SIZE(args) != 2) {
TYPE_ERROR("c_mod() requires 'mpz','mpz' arguments");
return NULL;
}
if (!(tempx = GMPy_MPZ_From_Integer(PyTuple_GET_ITEM(args, 0), NULL)) ||
!(tempy = GMPy_MPZ_From_Integer(PyTuple_GET_ITEM(args, 1), NULL)) ||
!(r = GMPy_MPZ_New(NULL))) {
goto err;
}
if (mpz_sgn(tempy->z) == 0) {
ZERO_ERROR("c_mod() division by 0");
goto err;
}
mpz_cdiv_r(r->z, tempx->z, tempy->z);
Py_DECREF((PyObject*)tempx);
Py_DECREF((PyObject*)tempy);
return (PyObject*)r;
err:
Py_XDECREF((PyObject*)tempx);
Py_XDECREF((PyObject*)tempy);
Py_XDECREF((PyObject*)r);
return NULL;
}
/*
**************************************************************************
* Floor division and remainder.
**************************************************************************
*/
PyDoc_STRVAR(doc_f_divmod,
"f_divmod(x, y, /) -> tuple[mpz, mpz]\n\n"
"Return the quotient and remainder of x divided by y. The quotient\n"
"is rounded towards -Inf (floor rounding) and the remainder will\n"
"have the same sign as y. x and y must be integers.");
static PyObject *
GMPy_MPZ_f_divmod(PyObject *self, PyObject *args)
{
PyObject *result = NULL;
MPZ_Object *q = NULL, *r = NULL, *tempx = NULL, *tempy = NULL;
if (PyTuple_GET_SIZE(args) != 2) {
TYPE_ERROR("f_divmod() requires 'mpz','mpz' arguments");
return NULL;
}
if (!(tempx = GMPy_MPZ_From_Integer(PyTuple_GET_ITEM(args, 0), NULL)) ||
!(tempy = GMPy_MPZ_From_Integer(PyTuple_GET_ITEM(args, 1), NULL)) ||
!(q = GMPy_MPZ_New(NULL)) ||
!(r = GMPy_MPZ_New(NULL)) ||
!(result = PyTuple_New(2))) {
goto err;
}
if (mpz_sgn(tempy->z) == 0) {
ZERO_ERROR("f_divmod() division by 0");
goto err;
}
mpz_fdiv_qr(q->z, r->z, tempx->z, tempy->z);
Py_DECREF((PyObject*)tempx);
Py_DECREF((PyObject*)tempy);
PyTuple_SET_ITEM(result, 0, (PyObject*)q);
PyTuple_SET_ITEM(result, 1, (PyObject*)r);
return result;
err:
Py_XDECREF(result);
Py_XDECREF((PyObject*)tempx);
Py_XDECREF((PyObject*)tempy);
Py_XDECREF((PyObject*)q);
Py_XDECREF((PyObject*)r);
return NULL;
}
PyDoc_STRVAR(doc_f_div,
"f_div(x, y, /) -> mpz\n\n"
"Return the quotient of x divided by y. The quotient is rounded\n"
"towards -Inf (floor rounding). x and y must be integers.");
static PyObject *
GMPy_MPZ_f_div(PyObject *self, PyObject *args)
{
MPZ_Object *q = NULL, *tempx = NULL, *tempy = NULL;
if(PyTuple_GET_SIZE(args) != 2) {
TYPE_ERROR("f_div() requires 'mpz','mpz' arguments");
return NULL;
}
if (!(tempx = GMPy_MPZ_From_Integer(PyTuple_GET_ITEM(args, 0), NULL)) ||
!(tempy = GMPy_MPZ_From_Integer(PyTuple_GET_ITEM(args, 1), NULL)) ||
!(q = GMPy_MPZ_New(NULL))) {
goto err;
}
if (mpz_sgn(tempy->z) == 0) {
ZERO_ERROR("f_div() division by 0");
goto err;
}
mpz_fdiv_q(q->z, tempx->z, tempy->z);
Py_DECREF((PyObject*)tempx);
Py_DECREF((PyObject*)tempy);
return (PyObject*)q;
err:
Py_XDECREF((PyObject*)tempx);
Py_XDECREF((PyObject*)tempy);
Py_XDECREF((PyObject*)q);
return NULL;
}
PyDoc_STRVAR(doc_f_mod,
"f_mod(x, y, /) -> mpz\n\n"
"Return the remainder of x divided by y. The remainder will have\n"
"the same sign as y. x and y must be integers.");
static PyObject *
GMPy_MPZ_f_mod(PyObject *self, PyObject *args)
{
MPZ_Object *r = NULL, *tempx = NULL, *tempy = NULL;
if (PyTuple_GET_SIZE(args) != 2) {
TYPE_ERROR("f_mod() requires 'mpz','mpz' arguments");
return NULL;
}
if (!(tempx = GMPy_MPZ_From_Integer(PyTuple_GET_ITEM(args, 0), NULL)) ||
!(tempy = GMPy_MPZ_From_Integer(PyTuple_GET_ITEM(args, 1), NULL)) ||
!(r = GMPy_MPZ_New(NULL))) {
goto err;
}
if (mpz_sgn(tempy->z) == 0) {
ZERO_ERROR("f_mod() division by 0");
goto err;
}
mpz_fdiv_r(r->z, tempx->z, tempy->z);
Py_DECREF((PyObject*)tempx);
Py_DECREF((PyObject*)tempy);
return (PyObject*)r;
err:
Py_XDECREF((PyObject*)tempx);
Py_XDECREF((PyObject*)tempy);
Py_XDECREF((PyObject*)r);
return NULL;
}
/*
**************************************************************************
* Truncating division and remainder.
**************************************************************************
*/
PyDoc_STRVAR(doc_t_divmod,
"t_divmod(x, y, /) -> tuple[mpz, mpz]\n\n"
"Return the quotient and remainder of x divided by y. The quotient\n"
"is rounded towards zero (truncation) and the remainder will have\n"
"the same sign as x. x and y must be integers.");
static PyObject *
GMPy_MPZ_t_divmod(PyObject *self, PyObject *args)
{
PyObject *result = NULL;
MPZ_Object *q = NULL, *r = NULL, *tempx = NULL, *tempy = NULL;
if (PyTuple_GET_SIZE(args) != 2) {
TYPE_ERROR("t_divmod() requires 'mpz','mpz' arguments");
return NULL;
}
if (!(tempx = GMPy_MPZ_From_Integer(PyTuple_GET_ITEM(args, 0), NULL)) ||
!(tempy = GMPy_MPZ_From_Integer(PyTuple_GET_ITEM(args, 1), NULL)) ||
!(q = GMPy_MPZ_New(NULL)) ||
!(r = GMPy_MPZ_New(NULL)) ||
!(result = PyTuple_New(2))) {
goto err;
}
if (mpz_sgn(tempy->z) == 0) {
ZERO_ERROR("t_divmod() division by 0");
goto err;
}
mpz_tdiv_qr(q->z, r->z, tempx->z, tempy->z);
Py_DECREF((PyObject*)tempx);
Py_DECREF((PyObject*)tempy);
PyTuple_SET_ITEM(result, 0, (PyObject*)q);
PyTuple_SET_ITEM(result, 1, (PyObject*)r);
return result;
err:
Py_XDECREF(result);
Py_XDECREF((PyObject*)tempx);
Py_XDECREF((PyObject*)tempy);
Py_XDECREF((PyObject*)q);
Py_XDECREF((PyObject*)r);
return NULL;
}
PyDoc_STRVAR(doc_t_div,
"t_div(x, y, /) -> mpz\n\n"
"Return the quotient of x divided by y. The quotient is rounded\n"
"towards 0. x and y must be integers.");
static PyObject *
GMPy_MPZ_t_div(PyObject *self, PyObject *args)
{
MPZ_Object *q = NULL, *tempx = NULL, *tempy = NULL;
if (PyTuple_GET_SIZE(args) != 2) {
TYPE_ERROR("t_div() requires 'mpz','mpz' arguments");
return NULL;
}
if (!(tempx = GMPy_MPZ_From_Integer(PyTuple_GET_ITEM(args, 0), NULL)) ||
!(tempy = GMPy_MPZ_From_Integer(PyTuple_GET_ITEM(args, 1), NULL)) ||
!(q = GMPy_MPZ_New(NULL))) {
goto err;
}
if (mpz_sgn(tempy->z) == 0) {
ZERO_ERROR("t_div() division by 0");
goto err;
}
mpz_tdiv_q(q->z, tempx->z, tempy->z);
Py_DECREF((PyObject*)tempx);
Py_DECREF((PyObject*)tempy);
return (PyObject*)q;
err:
Py_XDECREF((PyObject*)tempx);
Py_XDECREF((PyObject*)tempy);
Py_XDECREF((PyObject*)q);
return NULL;
}
PyDoc_STRVAR(doc_t_mod,
"t_mod(x, y, /) -> mpz\n\n"
"Return the remainder of x divided by y. The remainder will have\n"
"the same sign as x. x and y must be integers.");
static PyObject *
GMPy_MPZ_t_mod(PyObject *self, PyObject *args)
{
MPZ_Object *r = NULL, *tempx = NULL, *tempy = NULL;
if (PyTuple_GET_SIZE(args) != 2) {
TYPE_ERROR("t_mod() requires 'mpz','mpz' arguments");
return NULL;
}
if (!(tempx = GMPy_MPZ_From_Integer(PyTuple_GET_ITEM(args, 0), NULL)) ||
!(tempy = GMPy_MPZ_From_Integer(PyTuple_GET_ITEM(args, 1), NULL)) ||
!(r = GMPy_MPZ_New(NULL))) {
goto err;
}
if (mpz_sgn(tempy->z) == 0) {
ZERO_ERROR("t_mod() division by 0");
goto err;
}
mpz_tdiv_r(r->z, tempx->z, tempy->z);
Py_DECREF((PyObject*)tempx);
Py_DECREF((PyObject*)tempy);
return (PyObject*)r;
err:
Py_XDECREF((PyObject*)tempx);
Py_XDECREF((PyObject*)tempy);
Py_XDECREF((PyObject*)r);
return NULL;
}
././@PaxHeader 0000000 0000000 0000000 00000000026 00000000000 010213 x ustar 00 22 mtime=1710307256.0
gmpy2-2.2.1/src/gmpy2_mpz_divmod.h 0000644 0001750 0001750 00000005143 14574233670 015466 0 ustar 00case case /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* gmpy2_mpz_divmod.h *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Python interface to the GMP, MPFR, and MPC multiple precision *
* libraries. *
* *
* Copyright 2000 - 2009 Alex Martelli *
* *
* Copyright 2008 - 2024 Case Van Horsen *
* *
* This file is part of GMPY2. *
* *
* GMPY2 is free software: you can redistribute it and/or modify it under *
* the terms of the GNU Lesser General Public License as published by the *
* Free Software Foundation, either version 3 of the License, or (at your *
* option) any later version. *
* *
* GMPY2 is distributed in the hope that it will be useful, but WITHOUT *
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or *
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public *
* License for more details. *
* *
* You should have received a copy of the GNU Lesser General Public *
* License along with GMPY2; if not, see *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
#ifndef GMPY_MPZ_DIVMOD_H
#define GMPY_MPZ_DIVMOD_H
#ifdef __cplusplus
extern "C" {
#endif
static PyObject * GMPy_MPZ_c_divmod(PyObject *self, PyObject *args);
static PyObject * GMPy_MPZ_c_div(PyObject *self, PyObject *args);
static PyObject * GMPy_MPZ_c_mod(PyObject *self, PyObject *args);
static PyObject * GMPy_MPZ_f_divmod(PyObject *self, PyObject *args);
static PyObject * GMPy_MPZ_f_div(PyObject *self, PyObject *args);
static PyObject * GMPy_MPZ_f_mod(PyObject *self, PyObject *args);
static PyObject * GMPy_MPZ_t_divmod(PyObject *self, PyObject *args);
static PyObject * GMPy_MPZ_t_div(PyObject *self, PyObject *args);
static PyObject * GMPy_MPZ_t_mod(PyObject *self, PyObject *args);
#ifdef __cplusplus
}
#endif
#endif
././@PaxHeader 0000000 0000000 0000000 00000000026 00000000000 010213 x ustar 00 22 mtime=1710307256.0
gmpy2-2.2.1/src/gmpy2_mpz_divmod2exp.c 0000644 0001750 0001750 00000030047 14574233670 016261 0 ustar 00case case /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* gmpy2_mpz_divmod2exp.c *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Python interface to the GMP, MPFR, and MPC multiple precision *
* libraries. *
* *
* Copyright 2000 - 2009 Alex Martelli *
* *
* Copyright 2008 - 2024 Case Van Horsen *
* *
* This file is part of GMPY2. *
* *
* GMPY2 is free software: you can redistribute it and/or modify it under *
* the terms of the GNU Lesser General Public License as published by the *
* Free Software Foundation, either version 3 of the License, or (at your *
* option) any later version. *
* *
* GMPY2 is distributed in the hope that it will be useful, but WITHOUT *
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or *
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public *
* License for more details. *
* *
* You should have received a copy of the GNU Lesser General Public *
* License along with GMPY2; if not, see *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
/* This file contains functions related to division and remainder by a power
* of two.
*/
/*
**************************************************************************
* Ceiling division and remainder by power of two.
**************************************************************************
*/
PyDoc_STRVAR(doc_c_divmod_2exp,
"c_divmod_2exp(x, n, /) -> tuple[mpz, mpz]\n\n"
"Return the quotient and remainder of x divided by 2**n. The quotient\n"
"is rounded towards +Inf (ceiling rounding) and the remainder will\n"
"be negative. x must be an integer. n must be >0.");
static PyObject *
GMPy_MPZ_c_divmod_2exp(PyObject *self, PyObject *args)
{
mp_bitcnt_t nbits;
PyObject *result = NULL;
MPZ_Object *q = NULL, *r = NULL, *tempx = NULL;
if (PyTuple_GET_SIZE(args) != 2) {
TYPE_ERROR("c_divmod_2exp() requires 'mpz','int' arguments");
return NULL;
}
nbits = GMPy_Integer_AsMpBitCnt(PyTuple_GET_ITEM(args, 1));
if (nbits == (mp_bitcnt_t)(-1) && PyErr_Occurred()) {
return NULL;
}
if (!(tempx = GMPy_MPZ_From_Integer(PyTuple_GET_ITEM(args, 0), NULL)) ||
!(q = GMPy_MPZ_New(NULL)) ||
!(r = GMPy_MPZ_New(NULL)) ||
!(result = PyTuple_New(2))) {
Py_XDECREF(result);
Py_XDECREF((PyObject*)tempx);
Py_XDECREF((PyObject*)q);
Py_XDECREF((PyObject*)r);
return NULL;
}
mpz_cdiv_q_2exp(q->z, tempx->z, nbits);
mpz_cdiv_r_2exp(r->z, tempx->z, nbits);
Py_DECREF((PyObject*)tempx);
PyTuple_SET_ITEM(result, 0, (PyObject*)q);
PyTuple_SET_ITEM(result, 1, (PyObject*)r);
return result;
}
PyDoc_STRVAR(doc_c_div_2exp,
"c_div_2exp(x, n, /) -> mpz\n\n"
"Returns the quotient of x divided by 2**n. The quotient is rounded\n"
"towards +Inf (ceiling rounding). x must be an integer. n must be >0.");
static PyObject *
GMPy_MPZ_c_div_2exp(PyObject *self, PyObject *args)
{
mp_bitcnt_t nbits;
MPZ_Object *result, *tempx;
if (PyTuple_GET_SIZE(args) != 2) {
TYPE_ERROR("c_div_2exp() requires 'mpz','int' arguments");
return NULL;
}
nbits = GMPy_Integer_AsMpBitCnt(PyTuple_GET_ITEM(args, 1));
if (nbits == (mp_bitcnt_t)(-1) && PyErr_Occurred()) {
return NULL;
}
tempx = GMPy_MPZ_From_Integer(PyTuple_GET_ITEM(args, 0), NULL);
result = GMPy_MPZ_New(NULL);
if (!tempx || !result) {
Py_XDECREF((PyObject*)result);
Py_XDECREF((PyObject*)tempx);
return NULL;
}
mpz_cdiv_q_2exp(result->z, tempx->z, nbits);
Py_DECREF((PyObject*)tempx);
return (PyObject*)result;
}
PyDoc_STRVAR(doc_c_mod_2exp,
"c_mod_2exp(x, n, /) -> mpz\n\n"
"Return the remainder of x divided by 2**n. The remainder will be\n"
"negative. x must be an integer. n must be >0.");
static PyObject *
GMPy_MPZ_c_mod_2exp(PyObject *self, PyObject *args)
{
mp_bitcnt_t nbits;
MPZ_Object *result, *tempx;
if (PyTuple_GET_SIZE(args) != 2) {
TYPE_ERROR("c_mod_2exp() requires 'mpz','int' arguments");
return NULL;
}
nbits = GMPy_Integer_AsMpBitCnt(PyTuple_GET_ITEM(args, 1));
if (nbits == (mp_bitcnt_t)(-1) && PyErr_Occurred()) {
return NULL;
}
tempx = GMPy_MPZ_From_Integer(PyTuple_GET_ITEM(args, 0), NULL);
result = GMPy_MPZ_New(NULL);
if (!tempx || !result) {
Py_XDECREF((PyObject*)result);
Py_XDECREF((PyObject*)tempx);
return NULL;
}
mpz_cdiv_r_2exp(result->z, tempx->z, nbits);
Py_DECREF((PyObject*)tempx);
return (PyObject*)result;
}
/*
**************************************************************************
* Floor division and remainder by power of two.
**************************************************************************
*/
PyDoc_STRVAR(doc_f_divmod_2exp,
"f_divmod_2exp(x, n, /) -> tuple[mpz, mpz]\n\n"
"Return quotient and remainder after dividing x by 2**n. The quotient\n"
"is rounded towards -Inf (floor rounding) and the remainder will be\n"
"positive. x must be an integer. n must be >0.");
static PyObject *
GMPy_MPZ_f_divmod_2exp(PyObject *self, PyObject *args)
{
mp_bitcnt_t nbits;
PyObject *result;
MPZ_Object *q, *r, *tempx;
if (PyTuple_GET_SIZE(args) != 2) {
TYPE_ERROR("f_divmod_2exp() requires 'mpz','int' arguments");
return NULL;
}
nbits = GMPy_Integer_AsMpBitCnt(PyTuple_GET_ITEM(args, 1));
if (nbits == (mp_bitcnt_t)(-1) && PyErr_Occurred()) {
return NULL;
}
tempx = GMPy_MPZ_From_Integer(PyTuple_GET_ITEM(args, 0), NULL);
q = GMPy_MPZ_New(NULL);
r = GMPy_MPZ_New(NULL);
result = PyTuple_New(2);
if (!tempx || !q || !r || !result) {
Py_XDECREF(result);
Py_XDECREF((PyObject*)tempx);
Py_XDECREF((PyObject*)q);
Py_XDECREF((PyObject*)r);
return NULL;
}
mpz_fdiv_q_2exp(q->z, tempx->z, nbits);
mpz_fdiv_r_2exp(r->z, tempx->z, nbits);
Py_DECREF((PyObject*)tempx);
PyTuple_SET_ITEM(result, 0, (PyObject*)q);
PyTuple_SET_ITEM(result, 1, (PyObject*)r);
return result;
}
PyDoc_STRVAR(doc_f_div_2exp,
"f_div_2exp(x, n, /) -> mpz\n\n"
"Return the quotient of x divided by 2**n. The quotient is rounded\n"
"towards -Inf (floor rounding). x must be an integer. n must be >0.");
static PyObject *
GMPy_MPZ_f_div_2exp(PyObject *self, PyObject *args)
{
mp_bitcnt_t nbits;
MPZ_Object *result, *tempx;
if (PyTuple_GET_SIZE(args) != 2) {
TYPE_ERROR("f_div_2exp() requires 'mpz','int' arguments");
return NULL;
}
nbits = GMPy_Integer_AsMpBitCnt(PyTuple_GET_ITEM(args, 1));
if (nbits == (mp_bitcnt_t)(-1) && PyErr_Occurred()) {
return NULL;
}
tempx = GMPy_MPZ_From_Integer(PyTuple_GET_ITEM(args, 0), NULL);
result = GMPy_MPZ_New(NULL);
if (!tempx || !result) {
Py_XDECREF((PyObject*)result);
Py_XDECREF((PyObject*)tempx);
return NULL;
}
mpz_fdiv_q_2exp(result->z, tempx->z, nbits);
Py_DECREF((PyObject*)tempx);
return (PyObject*)result;
}
PyDoc_STRVAR(doc_f_mod_2exp,
"f_mod_2exp(x, n, /) -> mpz\n\n"
"Return remainder of x divided by 2**n. The remainder will be\n"
"positive. x must be an integer. n must be >0.");
static PyObject *
GMPy_MPZ_f_mod_2exp(PyObject *self, PyObject *args)
{
mp_bitcnt_t nbits;
MPZ_Object *result, *tempx;
if (PyTuple_GET_SIZE(args) != 2) {
TYPE_ERROR("f_mod_2exp() requires 'mpz','int' arguments");
return NULL;
}
nbits = GMPy_Integer_AsMpBitCnt(PyTuple_GET_ITEM(args, 1));
if (nbits == (mp_bitcnt_t)(-1) && PyErr_Occurred()) {
return NULL;
}
tempx = GMPy_MPZ_From_Integer(PyTuple_GET_ITEM(args, 0), NULL);
result = GMPy_MPZ_New(NULL);
if (!tempx || !result) {
Py_XDECREF((PyObject*)result);
Py_XDECREF((PyObject*)tempx);
return NULL;
}
mpz_fdiv_r_2exp(result->z, tempx->z, nbits);
Py_DECREF((PyObject*)tempx);
return (PyObject*)result;
}
/*
**************************************************************************
* Truncating division and remainder by power of two.
**************************************************************************
*/
PyDoc_STRVAR(doc_t_divmod_2exp,
"t_divmod_2exp(x, n, /) -> tuple[mpz, mpz]\n\n"
"Return the quotient and remainder of x divided by 2**n. The quotient\n"
"is rounded towards zero (truncation) and the remainder will have the\n"
"same sign as x. x must be an integer. n must be >0.");
static PyObject *
GMPy_MPZ_t_divmod_2exp(PyObject *self, PyObject *args)
{
mp_bitcnt_t nbits;
MPZ_Object *q, *r, *tempx;
PyObject *result;
if (PyTuple_GET_SIZE(args) != 2) {
TYPE_ERROR("t_divmod_2exp() requires 'mpz','int' arguments");
return NULL;
}
nbits = GMPy_Integer_AsMpBitCnt(PyTuple_GET_ITEM(args, 1));
if (nbits == (mp_bitcnt_t)(-1) && PyErr_Occurred()) {
return NULL;
}
tempx = GMPy_MPZ_From_Integer(PyTuple_GET_ITEM(args, 0), NULL);
q = GMPy_MPZ_New(NULL);
r = GMPy_MPZ_New(NULL);
result = PyTuple_New(2);
if (!tempx || !q || !r || !result) {
Py_XDECREF(result);
Py_XDECREF((PyObject*)tempx);
Py_XDECREF((PyObject*)q);
Py_XDECREF((PyObject*)r);
return NULL;
}
mpz_tdiv_q_2exp(q->z, tempx->z, nbits);
mpz_tdiv_r_2exp(r->z, tempx->z, nbits);
Py_DECREF((PyObject*)tempx);
PyTuple_SET_ITEM(result, 0, (PyObject*)q);
PyTuple_SET_ITEM(result, 1, (PyObject*)r);
return result;
}
PyDoc_STRVAR(doc_t_div_2exp,
"t_div_2exp(x, n, /) -> mpz\n\n"
"Return the quotient of x divided by 2**n. The quotient is rounded\n"
"towards zero (truncation). n must be >0.");
static PyObject *
GMPy_MPZ_t_div_2exp(PyObject *self, PyObject *args)
{
mp_bitcnt_t nbits;
MPZ_Object *result, *tempx;
if (PyTuple_GET_SIZE(args) != 2) {
TYPE_ERROR("t_div_2exp() requires 'mpz','int' arguments");
return NULL;
}
nbits = GMPy_Integer_AsMpBitCnt(PyTuple_GET_ITEM(args, 1));
if (nbits == (mp_bitcnt_t)(-1) && PyErr_Occurred()) {
return NULL;
}
tempx = GMPy_MPZ_From_Integer(PyTuple_GET_ITEM(args, 0), NULL);
result = GMPy_MPZ_New(NULL);
if (!tempx || !result) {
Py_XDECREF((PyObject*)result);
Py_XDECREF((PyObject*)tempx);
return NULL;
}
mpz_tdiv_q_2exp(result->z, tempx->z, nbits);
Py_DECREF((PyObject*)tempx);
return (PyObject*)result;
}
PyDoc_STRVAR(doc_t_mod_2exp,
"t_mod_2exp(x, n, /) -> mpz\n\n"
"Return the remainder of x divided by 2**n. The remainder will have\n"
"the same sign as x. x must be an integer. n must be >0.");
static PyObject *
GMPy_MPZ_t_mod_2exp(PyObject *self, PyObject *args)
{
mp_bitcnt_t nbits;
MPZ_Object *result, *tempx;
if (PyTuple_GET_SIZE(args) != 2) {
TYPE_ERROR("t_mod_2exp() requires 'mpz','int' arguments");
return NULL;
}
nbits = GMPy_Integer_AsMpBitCnt(PyTuple_GET_ITEM(args, 1));
if (nbits == (mp_bitcnt_t)(-1) && PyErr_Occurred()) {
return NULL;
}
tempx = GMPy_MPZ_From_Integer(PyTuple_GET_ITEM(args, 0), NULL);
result = GMPy_MPZ_New(NULL);
if (!tempx || !result) {
Py_XDECREF((PyObject*)result);
Py_XDECREF((PyObject*)tempx);
return NULL;
}
mpz_tdiv_r_2exp(result->z, tempx->z, nbits);
Py_DECREF((PyObject*)tempx);
return (PyObject*)result;
}
././@PaxHeader 0000000 0000000 0000000 00000000026 00000000000 010213 x ustar 00 22 mtime=1710307256.0
gmpy2-2.2.1/src/gmpy2_mpz_divmod2exp.h 0000644 0001750 0001750 00000005230 14574233670 016262 0 ustar 00case case /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* gmpy2_mpz_divmod2exp.h *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Python interface to the GMP, MPFR, and MPC multiple precision *
* libraries. *
* *
* Copyright 2000 - 2009 Alex Martelli *
* *
* Copyright 2008 - 2024 Case Van Horsen *
* *
* This file is part of GMPY2. *
* *
* GMPY2 is free software: you can redistribute it and/or modify it under *
* the terms of the GNU Lesser General Public License as published by the *
* Free Software Foundation, either version 3 of the License, or (at your *
* option) any later version. *
* *
* GMPY2 is distributed in the hope that it will be useful, but WITHOUT *
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or *
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public *
* License for more details. *
* *
* You should have received a copy of the GNU Lesser General Public *
* License along with GMPY2; if not, see *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
#ifndef GMPY_MPZ_DIVMOD2EXP_H
#define GMPY_MPZ_DIVMOD2EXP_H
#ifdef __cplusplus
extern "C" {
#endif
static PyObject * GMPy_MPZ_c_divmod_2exp(PyObject *self, PyObject *args);
static PyObject * GMPy_MPZ_c_div_2exp(PyObject *self, PyObject *args);
static PyObject * GMPy_MPZ_c_mod_2exp(PyObject *self, PyObject *args);
static PyObject * GMPy_MPZ_f_divmod_2exp(PyObject *self, PyObject *args);
static PyObject * GMPy_MPZ_f_div_2exp(PyObject *self, PyObject *args);
static PyObject * GMPy_MPZ_f_mod_2exp(PyObject *self, PyObject *args);
static PyObject * GMPy_MPZ_t_divmod_2exp(PyObject *self, PyObject *args);
static PyObject * GMPy_MPZ_t_div_2exp(PyObject *self, PyObject *args);
static PyObject * GMPy_MPZ_t_mod_2exp(PyObject *self, PyObject *args);
#ifdef __cplusplus
}
#endif
#endif
././@PaxHeader 0000000 0000000 0000000 00000000026 00000000000 010213 x ustar 00 22 mtime=1721370662.0
gmpy2-2.2.1/src/gmpy2_mpz_misc.c 0000644 0001750 0001750 00000166271 14646404046 015141 0 ustar 00case case /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* gmpy2_mpz_misc.c *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Python interface to the GMP, MPFR, and MPC multiple precision *
* libraries. *
* *
* Copyright 2000 - 2009 Alex Martelli *
* *
* Copyright 2008 - 2024 Case Van Horsen *
* *
* This file is part of GMPY2. *
* *
* GMPY2 is free software: you can redistribute it and/or modify it under *
* the terms of the GNU Lesser General Public License as published by the *
* Free Software Foundation, either version 3 of the License, or (at your *
* option) any later version. *
* *
* GMPY2 is distributed in the hope that it will be useful, but WITHOUT *
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or *
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public *
* License for more details. *
* *
* You should have received a copy of the GNU Lesser General Public *
* License along with GMPY2; if not, see *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
/* return number-of-digits for an mpz in requested base, default 10 */
PyDoc_STRVAR(GMPy_doc_mpz_method_num_digits,
"x.num_digits(base=10, /) -> int\n\n"
"Return length of string representing the absolute value of x in\n"
"the given base. Values for base can range between 2 and 62. The\n"
"value returned may be 1 too large.");
PyDoc_STRVAR(GMPy_doc_mpz_function_num_digits,
"num_digits(x, base=10, /) -> int\n\n"
"Return length of string representing the absolute value of x in\n"
"the given base. Values for base can range between 2 and 62. The\n"
"value returned may be 1 too large.");
static PyObject *
GMPy_MPZ_Method_NumDigits(PyObject *self, PyObject *const *args,
Py_ssize_t nargs)
{
long base = 10;
PyObject *result;
if (nargs == 1) {
base = PyLong_AsLong(args[0]);
if (base == -1 && PyErr_Occurred()) {
return NULL;
}
}
if ((base < 2) || (base > 62)) {
VALUE_ERROR("base must be in the interval [2, 62]");
return NULL;
}
result = PyLong_FromSize_t(mpz_sizeinbase(MPZ(self), (int)base));
return result;
}
static PyObject *
GMPy_MPZ_Function_NumDigits(PyObject *self, PyObject *const *args,
Py_ssize_t nargs)
{
long base = 10;
MPZ_Object *temp;
PyObject *result;
if (nargs == 0 || nargs > 2) {
TYPE_ERROR("num_digits() requires 'mpz',['int'] arguments");
return NULL;
}
if (nargs == 2) {
base = PyLong_AsLong(args[1]);
if (base == -1 && PyErr_Occurred()) {
return NULL;
}
}
if ((base < 2) || (base > 62)) {
VALUE_ERROR("base must be in the interval [2, 62]");
return NULL;
}
if (!(temp = GMPy_MPZ_From_Integer(args[0], NULL))) {
return NULL;
}
result = PyLong_FromSize_t(mpz_sizeinbase(temp->z, (int)base));
Py_DECREF((PyObject*)temp);
return result;
}
PyDoc_STRVAR(GMPy_doc_mpz_function_iroot,
"iroot(x,n,/) -> tuple[mpz, bool]\n\n"
"Return the integer n-th root of x and boolean value that is `True`\n"
"iff the root is exact. x >= 0. n > 0.");
static PyObject *
GMPy_MPZ_Function_Iroot(PyObject *self, PyObject *const *args,
Py_ssize_t nargs)
{
unsigned long n;
int exact, is_signed = 0;
MPZ_Object *root = NULL, *tempx = NULL;
PyObject *result = NULL;
if (nargs != 2 || !IS_INTEGER(args[0]) || !IS_INTEGER(args[1])) {
TYPE_ERROR("iroot() requires 'int','int' arguments");
return NULL;
}
n = (unsigned long)GMPy_Integer_AsUnsignedLongOrLong(args[1], &is_signed);
if ((n == (unsigned long)(-1)) && PyErr_Occurred()) {
return NULL;
}
if (is_signed || !n) {
VALUE_ERROR("n must be > 0");
return NULL;
}
if (!(tempx = GMPy_MPZ_From_Integer(args[0], NULL))) {
/* LCOV_EXCL_START */
return NULL;
/* LCOV_EXCL_STOP */
}
if (mpz_sgn(tempx->z) < 0) {
VALUE_ERROR("iroot() of negative number");
Py_DECREF((PyObject*)tempx);
return NULL;
}
if (!(result = PyTuple_New(2)) ||
!(root = GMPy_MPZ_New(NULL))) {
/* LCOV_EXCL_START */
Py_DECREF((PyObject*)tempx);
Py_XDECREF((PyObject*)root);
Py_XDECREF(result);
return NULL;
/* LCOV_EXCL_STOP */
}
exact = mpz_root(root->z, tempx->z, n);
Py_DECREF((PyObject*)tempx);
PyTuple_SET_ITEM(result, 0, (PyObject*)root);
PyTuple_SET_ITEM(result, 1, (PyObject*)PyBool_FromLong(exact));
return result;
}
PyDoc_STRVAR(GMPy_doc_mpz_function_iroot_rem,
"iroot_rem(x,n,/) -> tuple[mpz, mpz]\n\n"
"Return a 2-element tuple (y,r), such that y is the integer n-th\n"
"root of x and x=y**n + r. x >= 0. n > 0.");
static PyObject *
GMPy_MPZ_Function_IrootRem(PyObject *self, PyObject *const *args,
Py_ssize_t nargs)
{
unsigned long n;
MPZ_Object *root = NULL, *rem = NULL, *tempx = NULL;
PyObject *result = NULL;
if (nargs != 2 || !IS_INTEGER(args[0]) || !IS_INTEGER(args[1])) {
TYPE_ERROR("iroot_rem() requires 'int','int' arguments");
return NULL;
}
n = GMPy_Integer_AsUnsignedLong(args[1]);
if ((n == 0) || ((n == (unsigned long)(-1)) && PyErr_Occurred())) {
VALUE_ERROR("n must be > 0");
return NULL;
}
if (!(tempx = GMPy_MPZ_From_Integer(args[0], NULL))) {
/* LCOV_EXCL_START */
return NULL;
/* LCOV_EXCL_STOP */
}
if (mpz_sgn(tempx->z) < 0) {
VALUE_ERROR("iroot_rem() of negative number");
Py_DECREF((PyObject*)tempx);
return NULL;
}
if (!(result = PyTuple_New(2)) ||
!(root = GMPy_MPZ_New(NULL)) ||
!(rem = GMPy_MPZ_New(NULL))) {
/* LCOV_EXCL_START */
Py_DECREF((PyObject*)tempx);
Py_XDECREF(result);
Py_XDECREF((PyObject*)root);
Py_XDECREF((PyObject*)rem);
return NULL;
/* LCOV_EXCL_STOP */
}
mpz_rootrem(root->z, rem->z, tempx->z, n);
Py_DECREF((PyObject*)tempx);
PyTuple_SET_ITEM(result, 0, (PyObject*)root);
PyTuple_SET_ITEM(result, 1, (PyObject*)rem);
return result;
}
PyDoc_STRVAR(GMPy_doc_mpz_method_ceil, "Ceiling of an mpz returns itself.");
static PyObject *
GMPy_MPZ_Method_Ceil(PyObject *self, PyObject *other)
{
Py_INCREF(self);
return self;
}
PyDoc_STRVAR(GMPy_doc_mpz_method_floor, "Floor of an mpz returns itself.");
static PyObject *
GMPy_MPZ_Method_Floor(PyObject *self, PyObject *other)
{
Py_INCREF(self);
return self;
}
PyDoc_STRVAR(GMPy_doc_mpz_method_trunc, "Truncating an mpz returns itself.");
static PyObject *
GMPy_MPZ_Method_Trunc(PyObject *self, PyObject *other)
{
Py_INCREF(self);
return self;
}
PyDoc_STRVAR(GMPy_doc_mpz_method_round, "Round an mpz to power of 10.");
static PyObject *
GMPy_MPZ_Method_Round(PyObject *self, PyObject *const *args,
Py_ssize_t nargs)
{
Py_ssize_t round_digits;
MPZ_Object *result;
mpz_t temp, rem;
if (nargs == 0) {
Py_INCREF(self);
return self;
}
round_digits = GMPy_Integer_AsSsize_t(args[0]);
if (round_digits == -1 && PyErr_Occurred()) {
TYPE_ERROR("__round__() requires 'int' argument");
return NULL;
}
if (round_digits >= 0) {
Py_INCREF(self);
return self;
}
/* We can now assume round_digits > 0. */
round_digits = -round_digits;
if ((result = GMPy_MPZ_New(NULL))) {
if ((unsigned)round_digits >= mpz_sizeinbase(MPZ(self), 10)) {
mpz_set_ui(result->z, 0);
}
else {
mpz_init(temp);
mpz_init(rem);
mpz_ui_pow_ui(temp, 10, (unsigned long)round_digits);
mpz_fdiv_qr(result->z, rem, MPZ(self), temp);
mpz_mul_2exp(rem, rem, 1);
if (mpz_cmp(rem, temp) > 0) {
mpz_add_ui(result->z, result->z, 1);
}
else if (mpz_cmp(rem, temp) == 0) {
if (mpz_odd_p(result->z)) {
mpz_add_ui(result->z, result->z, 1);
}
}
mpz_mul(result->z, result->z, temp);
mpz_clear(rem);
mpz_clear(temp);
}
}
return (PyObject*)result;
}
static int
GMPy_MPZ_NonZero_Slot(MPZ_Object *self)
{
return mpz_sgn(self->z) != 0;
}
/* Miscellaneous gmpy functions */
PyDoc_STRVAR(GMPy_doc_mpz_function_gcd,
"gcd(*integers, /) -> mpz\n\n"
"Return the greatest common divisor of integers.");
static PyObject *
GMPy_MPZ_Function_GCD(PyObject *self, PyObject * const *args, Py_ssize_t nargs)
{
MPZ_Object *arg, *result = NULL;
CTXT_Object *context = NULL;
Py_ssize_t i;
CHECK_CONTEXT(context);
if (!(result = GMPy_MPZ_New(context))) {
/* LCOV_EXCL_START */
return NULL;
/* LCOV_EXCL_STOP */
}
for (i = 0; i < nargs; i++) {
if (!(arg = GMPy_MPZ_From_Integer(args[i], context))) {
TYPE_ERROR("gcd() requires 'mpz' arguments");
Py_XDECREF((PyObject*)arg);
Py_DECREF((PyObject*)result);
return NULL;
}
if (mpz_cmp_si(MPZ(result), 1) != 0) {
GMPY_MAYBE_BEGIN_ALLOW_THREADS(context);
mpz_gcd(MPZ(result), MPZ(arg), MPZ(result));
GMPY_MAYBE_END_ALLOW_THREADS(context);
}
Py_DECREF((PyObject*)arg);
}
return (PyObject*)result;
}
PyDoc_STRVAR(GMPy_doc_mpz_function_lcm,
"lcm(*integers, /) -> mpz\n\n"
"Return the lowest common multiple of integers.");
static PyObject *
GMPy_MPZ_Function_LCM(PyObject *self, PyObject * const *args, Py_ssize_t nargs)
{
MPZ_Object *arg, *result = NULL;
CTXT_Object *context = NULL;
Py_ssize_t i;
CHECK_CONTEXT(context);
if (!(result = GMPy_MPZ_New(context))) {
/* LCOV_EXCL_START */
return NULL;
/* LCOV_EXCL_STOP */
}
mpz_set_ui(result->z, 1);
for (i = 0; i < nargs; i++) {
if (!(arg = GMPy_MPZ_From_Integer(args[i], context))) {
TYPE_ERROR("lcm() requires 'mpz' arguments");
Py_XDECREF((PyObject*)arg);
Py_DECREF((PyObject*)result);
return NULL;
}
GMPY_MAYBE_BEGIN_ALLOW_THREADS(context);
mpz_lcm(MPZ(result), MPZ(arg), MPZ(result));
GMPY_MAYBE_END_ALLOW_THREADS(context);
Py_DECREF((PyObject*)arg);
}
return (PyObject*)result;
}
PyDoc_STRVAR(GMPy_doc_mpz_function_gcdext,
"gcdext(a, b, /) -> tuple[mpz, mpz, mpz]\n\n"
"Return a 3-element tuple (g,s,t) such that g == gcd(a,b)\n"
"and g == a*s + b*t.");
static PyObject *
GMPy_MPZ_Function_GCDext(PyObject *self, PyObject * const *args,
Py_ssize_t nargs)
{
PyObject *arg0, *arg1, *result = NULL;
MPZ_Object *g = NULL, *s = NULL, *t = NULL, *tempa = NULL, *tempb = NULL;
CTXT_Object *context = NULL;
CHECK_CONTEXT(context);
if(nargs != 2) {
TYPE_ERROR("gcdext() requires 'mpz','mpz' arguments");
return NULL;
}
if (!(result = PyTuple_New(3)) ||
!(g = GMPy_MPZ_New(NULL)) ||
!(s = GMPy_MPZ_New(NULL)) ||
!(t = GMPy_MPZ_New(NULL))) {
/* LCOV_EXCL_START */
Py_XDECREF((PyObject*)g);
Py_XDECREF((PyObject*)s);
Py_XDECREF((PyObject*)t);
Py_XDECREF(result);
return NULL;
/* LCOV_EXCL_STOP */
}
arg0 = args[0];
arg1 = args[1];
if (MPZ_Check(arg0) && MPZ_Check(arg1)) {
GMPY_MAYBE_BEGIN_ALLOW_THREADS(context);
mpz_gcdext(g->z, s->z, t->z, MPZ(arg0), MPZ(arg1));
GMPY_MAYBE_END_ALLOW_THREADS(context);
}
else {
if(!(tempa = GMPy_MPZ_From_Integer(arg0, NULL)) ||
!(tempb = GMPy_MPZ_From_Integer(arg1, NULL))) {
TYPE_ERROR("gcdext() requires 'mpz','mpz' arguments");
Py_XDECREF((PyObject*)tempa);
Py_XDECREF((PyObject*)tempb);
Py_DECREF((PyObject*)g);
Py_DECREF((PyObject*)s);
Py_DECREF((PyObject*)t);
Py_DECREF(result);
return NULL;
}
GMPY_MAYBE_BEGIN_ALLOW_THREADS(context);
mpz_gcdext(g->z, s->z, t->z, tempa->z, tempb->z);
GMPY_MAYBE_END_ALLOW_THREADS(context);
Py_DECREF((PyObject*)tempa);
Py_DECREF((PyObject*)tempb);
}
PyTuple_SET_ITEM(result, 0, (PyObject*)g);
PyTuple_SET_ITEM(result, 1, (PyObject*)s);
PyTuple_SET_ITEM(result, 2, (PyObject*)t);
return result;
}
PyDoc_STRVAR(GMPy_doc_mpz_function_divm,
"divm(a, b, m, /) -> mpz\n\n"
"Return x such that b*x == a mod m. Raises a `ZeroDivisionError`\n"
"exception if no such value x exists.");
static PyObject *
GMPy_MPZ_Function_Divm(PyObject *self, PyObject * const *args,
Py_ssize_t nargs)
{
MPZ_Object *result = NULL, *num = NULL, *den = NULL, *mod = NULL;
mpz_t numz, denz, modz, gcdz;
int ok = 0;
CTXT_Object *context = NULL;
CHECK_CONTEXT(context);
if (nargs != 3) {
TYPE_ERROR("divm() requires 'mpz','mpz','mpz' arguments");
return NULL;
}
if (!(result = GMPy_MPZ_New(NULL))) {
/* LCOV_EXCL_START */
return NULL;
/* LCOV_EXCL_STOP */
}
if (!(num = GMPy_MPZ_From_Integer(args[0], NULL)) ||
!(den = GMPy_MPZ_From_Integer(args[1], NULL)) ||
!(mod = GMPy_MPZ_From_Integer(args[2], NULL))) {
TYPE_ERROR("divm() requires 'mpz','mpz','mpz' arguments");
Py_XDECREF((PyObject*)num);
Py_XDECREF((PyObject*)den);
Py_XDECREF((PyObject*)mod);
Py_DECREF((PyObject*)result);
return NULL;
}
/* Make copies so we don't destroy the input. */
mpz_init(numz);
mpz_init(denz);
mpz_init(modz);
mpz_set(numz, num->z);
mpz_set(denz, den->z);
mpz_set(modz, mod->z);
Py_DECREF((PyObject*)num);
Py_DECREF((PyObject*)den);
Py_DECREF((PyObject*)mod);
GMPY_MAYBE_BEGIN_ALLOW_THREADS(context);
ok = mpz_invert(result->z, denz, modz);
GMPY_MAYBE_END_ALLOW_THREADS(context);
if (!ok) {
/* last-ditch attempt: do num, den AND mod have a gcd>1 ? */
GMPY_MAYBE_BEGIN_ALLOW_THREADS(context);
mpz_init(gcdz);
mpz_gcd(gcdz, numz, denz);
mpz_gcd(gcdz, gcdz, modz);
mpz_divexact(numz, numz, gcdz);
mpz_divexact(denz, denz, gcdz);
mpz_divexact(modz, modz, gcdz);
mpz_clear(gcdz);
ok = mpz_invert(result->z, denz, modz);
GMPY_MAYBE_END_ALLOW_THREADS(context);
}
if (ok) {
GMPY_MAYBE_BEGIN_ALLOW_THREADS(context);
mpz_mul(result->z, result->z, numz);
mpz_mod(result->z, result->z, modz);
mpz_clear(numz);
mpz_clear(denz);
mpz_clear(modz);
GMPY_MAYBE_END_ALLOW_THREADS(context);
return (PyObject*)result;
}
else {
ZERO_ERROR("not invertible");
mpz_clear(numz);
mpz_clear(denz);
mpz_clear(modz);
Py_DECREF((PyObject*)result);
return NULL;
}
}
PyDoc_STRVAR(GMPy_doc_mpz_function_fac,
"fac(n, /) -> mpz\n\n"
"Return the exact factorial of n.\n\n"
"See factorial(n) to get the floating-point approximation.");
static PyObject *
GMPy_MPZ_Function_Fac(PyObject *self, PyObject *other)
{
MPZ_Object *result = NULL;
unsigned long n;
n = GMPy_Integer_AsUnsignedLong(other);
if (n == (unsigned long)(-1) && PyErr_Occurred()) {
return NULL;
}
if ((result = GMPy_MPZ_New(NULL))) {
mpz_fac_ui(result->z, n);
}
return (PyObject*)result;
}
PyDoc_STRVAR(GMPy_doc_mpz_function_double_fac,
"double_fac(n, /) -> mpz\n\n"
"Return the exact double factorial (n!!) of n. The double\n"
"factorial is defined as n*(n-2)*(n-4)...");
static PyObject *
GMPy_MPZ_Function_DoubleFac(PyObject *self, PyObject *other)
{
MPZ_Object *result = NULL;
unsigned long n;
n = GMPy_Integer_AsUnsignedLong(other);
if (n == (unsigned long)(-1) && PyErr_Occurred()) {
return NULL;
}
if ((result = GMPy_MPZ_New(NULL))) {
mpz_2fac_ui(result->z, n);
}
return (PyObject*)result;
}
PyDoc_STRVAR(GMPy_doc_mpz_function_primorial,
"primorial(n, /) -> mpz\n\n"
"Return the product of all positive prime numbers less than or\n"
"equal to n.");
static PyObject *
GMPy_MPZ_Function_Primorial(PyObject *self, PyObject *other)
{
MPZ_Object *result = NULL;
unsigned long n;
n = GMPy_Integer_AsUnsignedLong(other);
if (n == (unsigned long)(-1) && PyErr_Occurred()) {
return NULL;
}
if ((result = GMPy_MPZ_New(NULL))) {
mpz_primorial_ui(result->z, n);
}
return (PyObject*)result;
}
PyDoc_STRVAR(GMPy_doc_mpz_function_multi_fac,
"multi_fac(n,m,/) -> mpz\n\n"
"Return the exact m-multi factorial of n. The m-multi"
"factorial is defined as n*(n-m)*(n-2m)...");
static PyObject *
GMPy_MPZ_Function_MultiFac(PyObject *self, PyObject *const *args,
Py_ssize_t nargs)
{
MPZ_Object *result = NULL;
unsigned long n, m;
if (nargs != 2) {
TYPE_ERROR("multi_fac() requires 2 integer arguments");
return NULL;
}
n = GMPy_Integer_AsUnsignedLong(args[0]);
if (n == (unsigned long)(-1) && PyErr_Occurred()) {
return NULL;
}
m = GMPy_Integer_AsUnsignedLong(args[1]);
if (m == (unsigned long)(-1) && PyErr_Occurred()) {
return NULL;
}
if ((result = GMPy_MPZ_New(NULL))) {
mpz_mfac_uiui(result->z, n, m);
}
return (PyObject*)result;
}
PyDoc_STRVAR(GMPy_doc_mpz_function_fib,
"fib(n, /) -> mpz\n\n"
"Return the n-th Fibonacci number.");
static PyObject *
GMPy_MPZ_Function_Fib(PyObject *self, PyObject *other)
{
MPZ_Object *result = NULL;
unsigned long n;
n = GMPy_Integer_AsUnsignedLong(other);
if (n == (unsigned long)(-1) && PyErr_Occurred()) {
return NULL;
}
if ((result = GMPy_MPZ_New(NULL))) {
mpz_fib_ui(result->z, n);
}
return (PyObject*)result;
}
PyDoc_STRVAR(GMPy_doc_mpz_function_fib2,
"fib2(n, /) -> tuple[mpz, mpz]\n\n"
"Return a 2-tuple with the (n-1)-th and n-th Fibonacci numbers.");
static PyObject *
GMPy_MPZ_Function_Fib2(PyObject *self, PyObject *other)
{
PyObject *result = NULL;
MPZ_Object *fib1 = NULL, *fib2 = NULL;
unsigned long n;
n = GMPy_Integer_AsUnsignedLong(other);
if (n == (unsigned long)(-1) && PyErr_Occurred()) {
return NULL;
}
if (!(result = PyTuple_New(2)) ||
!(fib1 = GMPy_MPZ_New(NULL)) ||
!(fib2 = GMPy_MPZ_New(NULL))) {
/* LCOV_EXCL_START */
Py_XDECREF(result);
Py_XDECREF((PyObject*)fib1);
Py_XDECREF((PyObject*)fib2);
result = NULL;
/* LCOV_EXCL_STOP */
}
mpz_fib2_ui(fib1->z, fib2->z, n);
PyTuple_SET_ITEM(result, 0, (PyObject*)fib1);
PyTuple_SET_ITEM(result, 1, (PyObject*)fib2);
return (PyObject*)result;
}
PyDoc_STRVAR(GMPy_doc_mpz_function_lucas,
"lucas(n, /) -> mpz\n\n"
"Return the n-th Lucas number.");
static PyObject *
GMPy_MPZ_Function_Lucas(PyObject *self, PyObject *other)
{
MPZ_Object *result = NULL;
unsigned long n;
n = GMPy_Integer_AsUnsignedLong(other);
if (n == (unsigned long)(-1) && PyErr_Occurred()) {
return NULL;
}
if ((result = GMPy_MPZ_New(NULL))) {
mpz_lucnum_ui(result->z, n);
}
return (PyObject*)result;
}
PyDoc_STRVAR(GMPy_doc_mpz_function_lucas2,
"lucas2(n, /) -> tuple[mpz, mpz]\n\n"
"Return a 2-tuple with the (n-1)-th and n-th Lucas numbers.");
static PyObject *
GMPy_MPZ_Function_Lucas2(PyObject *self, PyObject *other)
{
PyObject *result = NULL;
MPZ_Object *luc1 = NULL, *luc2 = NULL;
unsigned long n;
n = GMPy_Integer_AsUnsignedLong(other);
if (n == (unsigned long)(-1) && PyErr_Occurred()) {
return NULL;
}
if (!(result = PyTuple_New(2)) ||
!(luc1 = GMPy_MPZ_New(NULL)) ||
!(luc2 = GMPy_MPZ_New(NULL))) {
/* LCOV_EXCL_START */
Py_XDECREF(result);
Py_XDECREF((PyObject*)luc1);
Py_XDECREF((PyObject*)luc2);
result = NULL;
/* LCOV_EXCL_STOP */
}
mpz_lucnum2_ui(luc1->z, luc2->z, n);
PyTuple_SET_ITEM(result, 0, (PyObject*)luc1);
PyTuple_SET_ITEM(result, 1, (PyObject*)luc2);
return result;
}
PyDoc_STRVAR(GMPy_doc_mpz_function_bincoef,
"bincoef(n, k, /) -> mpz\n\n"
"Return the binomial coefficient ('n choose k'). k >= 0.");
PyDoc_STRVAR(GMPy_doc_mpz_function_comb,
"comb(n, k, /) -> mpz\n\n"
"Return the number of combinations of 'n things, taking k at a\n"
"time'. k >= 0. Same as bincoef(n, k)");
static PyObject *
GMPy_MPZ_Function_Bincoef(PyObject *self, PyObject * const *args,
Py_ssize_t nargs)
{
MPZ_Object *result = NULL, *tempx;
unsigned long n, k;
if (nargs != 2) {
TYPE_ERROR("bincoef() requires two integer arguments");
return NULL;
}
if (!(result = GMPy_MPZ_New(NULL))) {
/* LCOV_EXCL_START */
return NULL;
/* LCOV_EXCL_STOP */
}
k = GMPy_Integer_AsUnsignedLong(args[1]);
if (k == (unsigned long)(-1) && PyErr_Occurred()) {
Py_DECREF((PyObject*)result);
return NULL;
}
n = GMPy_Integer_AsUnsignedLong(args[0]);
if (n == (unsigned long)(-1) && PyErr_Occurred()) {
/* Since we plan to skip the else clause and continue,
* we need to clear the error since we aren't acting on it.
*/
PyErr_Clear();
}
else {
/* Use mpz_bin_uiui which should be faster. */
mpz_bin_uiui(result->z, n, k);
return (PyObject*)result;
}
if (!(tempx = GMPy_MPZ_From_Integer(args[0], NULL))) {
Py_DECREF((PyObject*)result);
return NULL;
}
mpz_bin_ui(result->z, tempx->z, k);
Py_DECREF((PyObject*)tempx);
return (PyObject*)result;
}
PyDoc_STRVAR(GMPy_doc_mpz_function_isqrt,
"isqrt(x, /) -> mpz\n\n"
"Return the integer square root of a non-negative integer x.");
static PyObject *
GMPy_MPZ_Function_Isqrt(PyObject *self, PyObject *other)
{
MPZ_Object *result;
if (CHECK_MPZANY(other)) {
if (mpz_sgn(MPZ(other)) < 0) {
VALUE_ERROR("isqrt() of negative number");
return NULL;
}
if ((result = GMPy_MPZ_New(NULL))) {
mpz_sqrt(result->z, MPZ(other));
}
}
else {
if (!(result = GMPy_MPZ_From_Integer(other, NULL))) {
TYPE_ERROR("isqrt() requires 'mpz' argument");
return NULL;
}
if (mpz_sgn(result->z) < 0) {
VALUE_ERROR("isqrt() of negative number");
Py_DECREF((PyObject*)result);
return NULL;
}
mpz_sqrt(result->z, result->z);
}
return (PyObject*)result;
}
PyDoc_STRVAR(GMPy_doc_mpz_function_isqrt_rem,
"isqrt_rem(x, /) -> (mpz, mpz)\n\n"
"Return a 2-element tuple (s,t) such that s=isqrt(x) and t=x-s*s.\n"
"x >=0.");
static PyObject *
GMPy_MPZ_Function_IsqrtRem(PyObject *self, PyObject *other)
{
MPZ_Object *root = NULL, *rem = NULL, *temp = NULL;
PyObject *result;
if (!(temp = GMPy_MPZ_From_Integer(other, NULL))) {
TYPE_ERROR("isqrt_rem() requires 'mpz' argument");
return NULL;
}
if (mpz_sgn(temp->z) < 0) {
VALUE_ERROR("isqrt_rem() of negative number");
Py_DECREF((PyObject*)temp);
return NULL;
}
if (!(result = PyTuple_New(2)) ||
!(root = GMPy_MPZ_New(NULL)) ||
!(rem = GMPy_MPZ_New(NULL))) {
/* LCOV_EXCL_START */
Py_DECREF((PyObject*)temp);
Py_XDECREF(result);
Py_XDECREF((PyObject*)root);
Py_XDECREF((PyObject*)rem);
return NULL;
/* LCOV_EXCL_STOP */
}
mpz_sqrtrem(root->z, rem->z, temp->z);
Py_DECREF((PyObject*)temp);
PyTuple_SET_ITEM(result, 0, (PyObject*)root);
PyTuple_SET_ITEM(result, 1, (PyObject*)rem);
return result;
}
PyDoc_STRVAR(GMPy_doc_mpz_function_remove,
"remove(x, f, /) -> tuple[mpz, mpz]\n\n"
"Return a 2-element tuple (y,m) such that x=y*(f**m) and f does\n"
"not divide y. Remove the factor f from x as many times as\n"
"possible. m is the multiplicity f in x. f > 1.");
static PyObject *
GMPy_MPZ_Function_Remove(PyObject *self, PyObject * const *args,
Py_ssize_t nargs)
{
MPZ_Object *result = NULL, *tempx = NULL, *tempf = NULL;
PyObject *x, *f;
size_t multiplicity;
if (nargs != 2) {
TYPE_ERROR("remove() requires 'mpz','mpz' arguments");
return NULL;
}
if (!(result = GMPy_MPZ_New(NULL))) {
/* LCOV_EXCL_START */
return NULL;
/* LCOV_EXCL_STOP */
}
x = args[0];
f = args[1];
if (MPZ_Check(x) && MPZ_Check(f)) {
if (mpz_cmp_si(MPZ(f), 2) < 0) {
VALUE_ERROR("factor must be > 1");
Py_DECREF((PyObject*)result);
return NULL;
}
multiplicity = mpz_remove(result->z, MPZ(x), MPZ(f));
return Py_BuildValue("(Nk)", result, multiplicity);
}
else {
if (!(tempx = GMPy_MPZ_From_Integer(x, NULL)) ||
!(tempf = GMPy_MPZ_From_Integer(f, NULL))) {
TYPE_ERROR("remove() requires 'mpz','mpz' arguments");
Py_XDECREF((PyObject*)tempx);
Py_XDECREF((PyObject*)tempf);
Py_DECREF((PyObject*)result);
return NULL;
}
if (mpz_cmp_si(MPZ(tempf), 2) < 0) {
VALUE_ERROR("factor must be > 1");
Py_DECREF((PyObject*)tempx);
Py_DECREF((PyObject*)tempf);
Py_DECREF((PyObject*)result);
return NULL;
}
multiplicity = mpz_remove(result->z, tempx->z, tempf->z);
Py_DECREF((PyObject*)tempx);
Py_DECREF((PyObject*)tempf);
return Py_BuildValue("(Nk)", result, multiplicity);
}
}
PyDoc_STRVAR(GMPy_doc_mpz_function_invert,
"invert(x, m, /) -> mpz\n\n"
"Return y such that x*y == 1 modulo m. Raises `ZeroDivisionError` if no\n"
"inverse exists.");
static PyObject *
GMPy_MPZ_Function_Invert(PyObject *self, PyObject * const *args,
Py_ssize_t nargs)
{
PyObject *x, *y;
MPZ_Object *result = NULL, *tempx = NULL, *tempy = NULL;
int success;
if (nargs != 2) {
TYPE_ERROR("invert() requires 'mpz','mpz' arguments");
return NULL;
}
if (!(result = GMPy_MPZ_New(NULL))) {
/* LCOV_EXCL_START */
return NULL;
/* LCOV_EXCL_STOP */
}
x = args[0];
y = args[1];
if (MPZ_Check(x) && MPZ_Check(y)) {
if (mpz_sgn(MPZ(y)) == 0) {
ZERO_ERROR("invert() division by 0");
Py_DECREF((PyObject*)result);
return NULL;
}
success = mpz_invert(result->z, MPZ(x), MPZ(y));
if (!success) {
ZERO_ERROR("invert() no inverse exists");
Py_DECREF((PyObject*)result);
return NULL;
}
}
else {
if (!(tempx = GMPy_MPZ_From_Integer(x, NULL)) ||
!(tempy = GMPy_MPZ_From_Integer(y, NULL))) {
TYPE_ERROR("invert() requires 'mpz','mpz' arguments");
Py_XDECREF((PyObject*)tempx);
Py_XDECREF((PyObject*)tempy);
Py_DECREF((PyObject*)result);
return NULL;
}
if (mpz_sgn(tempy->z) == 0) {
ZERO_ERROR("invert() division by 0");
Py_DECREF((PyObject*)tempx);
Py_DECREF((PyObject*)tempy);
Py_DECREF(result);
return NULL;
}
success = mpz_invert(result->z, tempx->z, tempy->z);
Py_DECREF((PyObject*)tempx);
Py_DECREF((PyObject*)tempy);
if (!success) {
ZERO_ERROR("invert() no inverse exists");
Py_DECREF((PyObject*)result);
return NULL;
}
}
return (PyObject*)result;
}
PyDoc_STRVAR(GMPy_doc_mpz_function_divexact,
"divexact(x, y, /) -> mpz\n\n"
"Return the quotient of x divided by y. Faster than standard\n"
"division but requires the remainder is zero!");
static PyObject *
GMPy_MPZ_Function_Divexact(PyObject *self, PyObject * const *args,
Py_ssize_t nargs)
{
PyObject *x, *y;
MPZ_Object *result, *tempx= NULL, *tempy = NULL;
if (nargs != 2) {
TYPE_ERROR("divexact() requires 'mpz','mpz' arguments");
return NULL;
}
if (!(result = GMPy_MPZ_New(NULL))) {
/* LCOV_EXCL_START */
return NULL;
/* LCOV_EXCL_STOP */
}
x = args[0];
y = args[1];
if (MPZ_Check(x) && MPZ_Check(y)) {
if (mpz_sgn(MPZ(y)) == 0) {
ZERO_ERROR("divexact() division by 0");
Py_DECREF((PyObject*)result);
return NULL;
}
mpz_divexact(result->z, MPZ(x), MPZ(y));
}
else {
if (!(tempx = GMPy_MPZ_From_Integer(x, NULL)) ||
!(tempy = GMPy_MPZ_From_Integer(y, NULL))) {
TYPE_ERROR("divexact() requires 'mpz','mpz' arguments");
Py_XDECREF((PyObject*)tempx);
Py_XDECREF((PyObject*)tempy);
Py_DECREF((PyObject*)result);
return NULL;
}
if (mpz_sgn(MPZ(tempy)) == 0) {
ZERO_ERROR("divexact() division by 0");
Py_DECREF((PyObject*)tempx);
Py_DECREF((PyObject*)tempy);
Py_DECREF((PyObject*)result);
return NULL;
}
mpz_divexact(result->z, tempx->z, tempy->z);
Py_DECREF((PyObject*)tempx);
Py_DECREF((PyObject*)tempy);
}
return (PyObject*)result;
}
PyDoc_STRVAR(GMPy_doc_mpz_function_is_square,
"is_square(x, /) -> bool\n\n"
"Returns `True` if x is a perfect square, else return `False`.");
static PyObject *
GMPy_MPZ_Function_IsSquare(PyObject *self, PyObject *other)
{
int res;
MPZ_Object *tempx;
if (MPZ_Check(other)) {
res = mpz_perfect_square_p(MPZ(other));
}
else {
if (!(tempx = GMPy_MPZ_From_Integer(other, NULL))) {
TYPE_ERROR("is_square() requires 'mpz' argument");
return NULL;
}
else {
res = mpz_perfect_square_p(tempx->z);
Py_DECREF((PyObject*)tempx);
}
}
if (res)
Py_RETURN_TRUE;
else
Py_RETURN_FALSE;
}
PyDoc_STRVAR(GMPy_doc_mpz_method_is_square,
"x.is_square() -> bool\n\n"
"Returns `True` if x is a perfect square, else return `False`.");
static PyObject *
GMPy_MPZ_Method_IsSquare(PyObject *self, PyObject *other)
{
int res;
res = mpz_perfect_square_p(MPZ(self));
if (res)
Py_RETURN_TRUE;
else
Py_RETURN_FALSE;
}
PyDoc_STRVAR(GMPy_doc_mpz_function_is_divisible,
"is_divisible(x, d, /) -> bool\n\n"
"Returns `True` if x is divisible by d, else return `False`.");
static PyObject *
GMPy_MPZ_Function_IsDivisible(PyObject *self, PyObject * const * args,
Py_ssize_t nargs)
{
unsigned long temp;
int res = 0;
MPZ_Object *tempx, *tempd;
if (nargs != 2) {
TYPE_ERROR("is_divisible() requires 2 integer arguments");
return NULL;
}
if (!(tempx = GMPy_MPZ_From_Integer(args[0], NULL))) {
return NULL;
}
temp = GMPy_Integer_AsUnsignedLong(args[1]);
if (temp == (unsigned long)-1 && PyErr_Occurred()) {
PyErr_Clear();
/* Implement mpz_divisible_p here. */
if (!(tempd = GMPy_MPZ_From_Integer(args[1], NULL))) {
TYPE_ERROR("is_divisible() requires 2 integer arguments");
Py_DECREF((PyObject*)tempx);
return NULL;
}
res = mpz_divisible_p(tempx->z, tempd->z);
Py_DECREF((PyObject*)tempx);
Py_DECREF((PyObject*)tempd);
}
else {
/* Implement mpz_divisible_ui_p here. */
res = mpz_divisible_ui_p(tempx->z, temp);
Py_DECREF((PyObject*)tempx);
}
if (res)
Py_RETURN_TRUE;
else
Py_RETURN_FALSE;
}
PyDoc_STRVAR(GMPy_doc_mpz_method_is_divisible,
"x.is_divisible(d, /) -> bool\n\n"
"Returns `True` if x is divisible by d, else return `False`.");
static PyObject *
GMPy_MPZ_Method_IsDivisible(PyObject *self, PyObject *other)
{
unsigned long temp;
int res;
MPZ_Object *tempd;
temp = GMPy_Integer_AsUnsignedLong(other);
if (temp == (unsigned long)-1 && PyErr_Occurred()) {
PyErr_Clear();
/* Implement mpz_divisible_p here. */
if (!(tempd = GMPy_MPZ_From_Integer(other, NULL))) {
TYPE_ERROR("is_divisible() requires 2 integer arguments");
return NULL;
}
res = mpz_divisible_p(MPZ(self), tempd->z);
Py_DECREF((PyObject*)tempd);
}
else {
/* Implement mpz_divisible_ui_p here. */
res = mpz_divisible_ui_p(MPZ(self), temp);
}
if (res)
Py_RETURN_TRUE;
else
Py_RETURN_FALSE;
}
PyDoc_STRVAR(GMPy_doc_mpz_function_is_congruent,
"is_congruent(x, y, m, /) -> bool\n\n"
"Returns `True` if x is congruent to y modulo m, else return `False`.");
static PyObject *
GMPy_MPZ_Function_IsCongruent(PyObject *self, PyObject * const *args,
Py_ssize_t nargs)
{
int res;
MPZ_Object *tempx = NULL, *tempy = NULL, *tempm = NULL;
if (nargs != 3) {
TYPE_ERROR("is_congruent() requires 3 integer arguments");
return NULL;
}
if (!(tempx = GMPy_MPZ_From_Integer(args[0], NULL)) ||
!(tempy = GMPy_MPZ_From_Integer(args[1], NULL)) ||
!(tempm = GMPy_MPZ_From_Integer(args[2], NULL))) {
Py_XDECREF((PyObject*)tempx);
Py_XDECREF((PyObject*)tempy);
Py_XDECREF((PyObject*)tempm);
TYPE_ERROR("is_congruent() requires 3 integer arguments");
return NULL;
}
res = mpz_congruent_p(tempx->z, tempy->z, tempm->z);
Py_DECREF((PyObject*)tempx);
Py_DECREF((PyObject*)tempy);
Py_DECREF((PyObject*)tempm);
if (res)
Py_RETURN_TRUE;
else
Py_RETURN_FALSE;
}
PyDoc_STRVAR(GMPy_doc_mpz_method_is_congruent,
"x.is_congruent(y, m, /) -> bool\n\n"
"Returns `True` if x is congruent to y modulo m, else return `False`.");
static PyObject *
GMPy_MPZ_Method_IsCongruent(PyObject *self, PyObject *const *args,
Py_ssize_t nargs)
{
int res;
MPZ_Object *tempy = NULL, *tempm = NULL;
if (nargs != 2) {
TYPE_ERROR("is_congruent() requires 2 integer arguments");
return NULL;
}
if (!(tempy = GMPy_MPZ_From_Integer(args[0], NULL)) ||
!(tempm = GMPy_MPZ_From_Integer(args[1], NULL))) {
Py_XDECREF((PyObject*)tempy);
Py_XDECREF((PyObject*)tempm);
TYPE_ERROR("is_congruent() requires 2 integer arguments");
return NULL;
}
res = mpz_congruent_p(MPZ(self), tempy->z, tempm->z);
Py_DECREF((PyObject*)tempy);
Py_DECREF((PyObject*)tempm);
if (res)
Py_RETURN_TRUE;
else
Py_RETURN_FALSE;
}
PyDoc_STRVAR(GMPy_doc_mpz_function_is_power,
"is_power(x, /) -> bool\n\n"
"Return `True` if x is a perfect power (there exists a y and an\n"
"n > 1, such that x=y**n), else return `False`.");
static PyObject *
GMPy_MPZ_Function_IsPower(PyObject *self, PyObject *other)
{
int res;
MPZ_Object* tempx;
if (MPZ_Check(other)) {
res = mpz_perfect_power_p(MPZ(other));
}
else {
if (!(tempx = GMPy_MPZ_From_Integer(other, NULL))) {
TYPE_ERROR("is_power() requires 'mpz' argument");
return NULL;
}
else {
res = mpz_perfect_power_p(tempx->z);
Py_DECREF((PyObject*)tempx);
}
}
if (res)
Py_RETURN_TRUE;
else
Py_RETURN_FALSE;
}
PyDoc_STRVAR(GMPy_doc_mpz_method_is_power,
"x.is_power() -> bool\n\n"
"Return `True` if x is a perfect power (there exists a y and an\n"
"n > 1, such that x=y**n), else return `False`.");
static PyObject *
GMPy_MPZ_Method_IsPower(PyObject *self, PyObject *other)
{
int res;
res = mpz_perfect_power_p(MPZ(self));
if (res)
Py_RETURN_TRUE;
else
Py_RETURN_FALSE;
}
PyDoc_STRVAR(GMPy_doc_mpz_function_is_prime,
"is_prime(x, n=25, /) -> bool\n\n"
"Return `True` if x is *probably* prime, else `False` if x is\n"
"definitely composite. x is checked for small divisors and up\n"
"to n Miller-Rabin tests are performed.");
static PyObject *
GMPy_MPZ_Function_IsPrime(PyObject *self, PyObject * const *args,
Py_ssize_t nargs)
{
int i;
unsigned long reps = 25;
MPZ_Object* tempx;
if (nargs == 0 || nargs > 2) {
TYPE_ERROR("is_prime() requires 'mpz'[,'int'] arguments");
return NULL;
}
if (nargs == 2) {
reps = GMPy_Integer_AsUnsignedLong(args[1]);
if (reps == (unsigned long)(-1) && PyErr_Occurred()) {
return NULL;
}
/* Silently limit n to a reasonable value. */
if (reps > 1000) {
reps = 1000;
}
}
if (!(tempx = GMPy_MPZ_From_Integer(args[0], NULL))) {
return NULL;
}
if (mpz_sgn(tempx->z) == -1) {
Py_DECREF((PyObject*)tempx);
Py_RETURN_FALSE;
}
i = mpz_probab_prime_p(tempx->z, (int)reps);
Py_DECREF((PyObject*)tempx);
if (i)
Py_RETURN_TRUE;
else
Py_RETURN_FALSE;
}
PyDoc_STRVAR(GMPy_doc_mpz_method_is_prime,
"x.is_prime(n=25, /) -> bool\n\n"
"Return `True` if x is *probably* prime, else `False` if x is\n"
"definitely composite. x is checked for small divisors and up\n"
"to n Miller-Rabin tests are performed.");
static PyObject *
GMPy_MPZ_Method_IsPrime(PyObject *self, PyObject * const *args,
Py_ssize_t nargs)
{
int i;
unsigned long reps = 25;
if (nargs > 1) {
TYPE_ERROR("is_prime() takes at most 1 argument");
return NULL;
}
if (nargs == 1) {
reps = GMPy_Integer_AsUnsignedLong(args[0]);
if (reps == (unsigned long)(-1) && PyErr_Occurred()) {
return NULL;
}
/* Silently limit n to a reasonable value. */
if (reps > 1000) {
reps = 1000;
}
}
if (mpz_sgn(MPZ(self)) == -1) {
Py_RETURN_FALSE;
}
i = mpz_probab_prime_p(MPZ(self), (int)reps);
if (i)
Py_RETURN_TRUE;
else
Py_RETURN_FALSE;
}
PyDoc_STRVAR(GMPy_doc_mpz_function_is_probab_prime,
"is_probab_prime(x, n=25, /) -> int\n\n"
"Return 2 if x is definitely prime, 1 if x is probably prime,\n"
"or return 0 if x is definitely non-prime. x is checked for small\n"
"divisors and up to n Miller-Rabin tests are performed. Reasonable\n"
"values of n are between 15 and 50.");
static PyObject *
GMPy_MPZ_Function_IsProbabPrime(PyObject *module, PyObject *const *args,
Py_ssize_t nargs)
{
int ret;
unsigned long reps = 25;
MPZ_Object* tempx;
if (nargs == 0 || nargs > 2) {
TYPE_ERROR("is_probab_prime() requires 'mpz'[,'int'] arguments");
return NULL;
}
if (nargs == 2) {
reps = PyLong_AsUnsignedLong(args[1]);
if (reps == (unsigned long)(-1) && PyErr_Occurred()) {
return NULL;
}
}
if (!(tempx = GMPy_MPZ_From_Integer(args[0], NULL))) {
return NULL;
}
if (mpz_sgn(MPZ(tempx)) == -1) {
Py_DECREF((PyObject*)tempx);
return PyLong_FromLong(0);
}
ret = mpz_probab_prime_p(MPZ(tempx), reps);
Py_DECREF((PyObject*)tempx);
return PyLong_FromLong(ret);
}
PyDoc_STRVAR(GMPy_doc_mpz_method_is_probab_prime,
"x.is_probab_prime(n=25, /) -> int\n\n"
"Return 2 if x is definitely prime, 1 if x is probably prime,\n"
"or return 0 if x is definitely non-prime. x is checked for small\n"
"divisors and up to n Miller-Rabin tests are performed. Reasonable\n"
"values of n are between 15 and 50.");
static PyObject *
GMPy_MPZ_Method_IsProbabPrime(PyObject *self, PyObject *const *args,
Py_ssize_t nargs)
{
int ret;
unsigned long reps = 25;
if (nargs > 1) {
TYPE_ERROR("is_probab_prime() takes at most 1 argument");
return NULL;
}
if (nargs == 1) {
reps = PyLong_AsUnsignedLong(args[0]);
if (reps == (unsigned long)(-1) && PyErr_Occurred()) {
return NULL;
}
}
if (mpz_sgn(MPZ(self)) == -1) {
return PyLong_FromLong(0);
}
ret = mpz_probab_prime_p(MPZ(self), (int)reps);
return PyLong_FromLong(ret);
}
PyDoc_STRVAR(GMPy_doc_mpz_function_next_prime,
"next_prime(x, /) -> mpz\n\n"
"Return the next *probable* prime number > x.");
static PyObject *
GMPy_MPZ_Function_NextPrime(PyObject *self, PyObject *other)
{
MPZ_Object *result;
if(MPZ_Check(other)) {
if(!(result = GMPy_MPZ_New(NULL))) {
/* LCOV_EXCL_START */
return NULL;
/* LCOV_EXCL_STOP */
}
mpz_nextprime(result->z, MPZ(other));
}
else {
if (!(result = GMPy_MPZ_From_Integer(other, NULL))) {
TYPE_ERROR("next_prime() requires 'mpz' argument");
return NULL;
}
else {
mpz_nextprime(result->z, result->z);
}
}
return (PyObject*)result;
}
PyDoc_STRVAR(GMPy_doc_mpz_function_prev_prime,
"prev_prime(x, /) -> mpz\n\n"
"Return the previous *probable* prime number < x.\n"
"Only present when compiled with GMP 6.3.0 or later.");
#if (__GNU_MP_VERSION > 6) || (__GNU_MP_VERSION == 6 && __GNU_MP_VERSION_MINOR >= 3)
static PyObject *
GMPy_MPZ_Function_PrevPrime(PyObject *self, PyObject *other)
{
MPZ_Object *result;
if(MPZ_Check(other)) {
if(!(result = GMPy_MPZ_New(NULL))) {
/* LCOV_EXCL_START */
return NULL;
/* LCOV_EXCL_STOP */
}
if (!mpz_prevprime(result->z, MPZ(other))) {
/* no previous prime, raise value error. */
VALUE_ERROR("x must be >= 3");
return NULL;
}
}
else {
if (!(result = GMPy_MPZ_From_Integer(other, NULL))) {
TYPE_ERROR("prev_prime() requires 'mpz' argument");
return NULL;
}
else {
if (!mpz_prevprime(result->z, result->z)) {
/* no previous prime, raise value error. */
VALUE_ERROR("x must be >= 3");
return NULL;
}
}
}
return (PyObject*)result;
}
#endif
PyDoc_STRVAR(GMPy_doc_mpz_function_jacobi,
"jacobi(x, y, /) -> mpz\n\n"
"Return the Jacobi symbol (x|y). y must be odd and >0.");
static PyObject *
GMPy_MPZ_Function_Jacobi(PyObject *self, PyObject *const *args,
Py_ssize_t nargs)
{
MPZ_Object *tempx = NULL, *tempy = NULL;
long res;
if (nargs != 2) {
TYPE_ERROR("jacobi() requires 'mpz','mpz' arguments");
return NULL;
}
if (!(tempx = GMPy_MPZ_From_Integer(args[0], NULL)) ||
!(tempy = GMPy_MPZ_From_Integer(args[1], NULL))) {
Py_XDECREF((PyObject*)tempx);
Py_XDECREF((PyObject*)tempy);
return NULL;
}
if (mpz_sgn(tempy->z) <= 0 || mpz_even_p(tempy->z)) {
VALUE_ERROR("y must be odd and >0");
Py_DECREF((PyObject*)tempx);
Py_DECREF((PyObject*)tempy);
return NULL;
}
res = (long)(mpz_jacobi(tempx->z, tempy->z));
Py_DECREF((PyObject*)tempx);
Py_DECREF((PyObject*)tempy);
return PyLong_FromLong(res);
}
PyDoc_STRVAR(GMPy_doc_mpz_function_legendre,
"legendre(x, y, /) -> mpz\n\n"
"Return the Legendre symbol (x|y). y is assumed to be an odd prime.");
static PyObject *
GMPy_MPZ_Function_Legendre(PyObject *self, PyObject * const *args,
Py_ssize_t nargs)
{
MPZ_Object *tempx = NULL, *tempy = NULL;
long res;
if (nargs != 2) {
TYPE_ERROR("legendre() requires 'mpz','mpz' arguments");
return NULL;
}
if (!(tempx = GMPy_MPZ_From_Integer(args[0], NULL)) ||
!(tempy = GMPy_MPZ_From_Integer(args[1], NULL))) {
Py_XDECREF((PyObject*)tempx);
Py_XDECREF((PyObject*)tempy);
return NULL;
}
if (mpz_sgn(tempy->z) <= 0 || mpz_even_p(tempy->z)) {
VALUE_ERROR("y must be odd, prime, and >0");
Py_DECREF((PyObject*)tempx);
Py_DECREF((PyObject*)tempy);
return NULL;
}
res = (long)(mpz_legendre(tempx->z, tempy->z));
Py_DECREF((PyObject*)tempx);
Py_DECREF((PyObject*)tempy);
return PyLong_FromLong(res);
}
PyDoc_STRVAR(GMPy_doc_mpz_function_kronecker,
"kronecker(x, y, /) -> mpz\n\n"
"Return the Kronecker-Jacobi symbol (x|y).");
static PyObject *
GMPy_MPZ_Function_Kronecker(PyObject *self, PyObject * const *args,
Py_ssize_t nargs)
{
MPZ_Object *tempx = NULL, *tempy = NULL;
long res;
if (nargs != 2) {
TYPE_ERROR("kronecker() requires 'mpz','mpz' arguments");
return NULL;
}
if (!(tempx = GMPy_MPZ_From_Integer(args[0], NULL)) ||
!(tempy = GMPy_MPZ_From_Integer(args[1], NULL))) {
Py_XDECREF((PyObject*)tempx);
Py_XDECREF((PyObject*)tempy);
return NULL;
}
res = (long)(mpz_kronecker(tempx->z, tempy->z));
Py_DECREF((PyObject*)tempx);
Py_DECREF((PyObject*)tempy);
return PyLong_FromLong(res);
}
PyDoc_STRVAR(GMPy_doc_mpz_function_is_even,
"is_even(x, /) -> bool\n\n"
"Return `True` if x is even, `False` otherwise.");
static PyObject *
GMPy_MPZ_Function_IsEven(PyObject *self, PyObject *other)
{
int res;
MPZ_Object *tempx;
if (MPZ_Check(other)) {
res = mpz_even_p(MPZ(other));
}
else {
if (!(tempx = GMPy_MPZ_From_Integer(other, NULL))) {
TYPE_ERROR("is_even() requires 'mpz' argument");
return NULL;
}
else {
res = mpz_even_p(tempx->z);
Py_DECREF((PyObject*)tempx);
}
}
if (res)
Py_RETURN_TRUE;
else
Py_RETURN_FALSE;
}
PyDoc_STRVAR(GMPy_doc_mpz_method_is_even,
"x.is_even() -> bool\n\n"
"Return `True` if x is even, `False` otherwise.");
static PyObject *
GMPy_MPZ_Method_IsEven(PyObject *self, PyObject *other)
{
int res;
res = mpz_even_p(MPZ(self));
if (res)
Py_RETURN_TRUE;
else
Py_RETURN_FALSE;
}
PyDoc_STRVAR(GMPy_doc_mpz_function_is_odd,
"is_odd(x, /) -> bool\n\n"
"Return `True` if x is odd, `False` otherwise.");
static PyObject *
GMPy_MPZ_Function_IsOdd(PyObject *self, PyObject *other)
{
int res;
MPZ_Object *tempx;
if (CHECK_MPZANY(other)) {
res = mpz_odd_p(MPZ(other));
}
else {
if (!(tempx = GMPy_MPZ_From_Integer(other, NULL))) {
TYPE_ERROR("is_odd() requires 'mpz' argument");
return NULL;
}
else {
res = mpz_odd_p(tempx->z);
Py_DECREF((PyObject*)tempx);
}
}
if (res)
Py_RETURN_TRUE;
else
Py_RETURN_FALSE;
}
PyDoc_STRVAR(GMPy_doc_mpz_method_is_odd,
"x.is_odd() -> bool\n\n"
"Return `True` if x is odd, `False` otherwise.");
static PyObject *
GMPy_MPZ_Method_IsOdd(PyObject *self, PyObject *other)
{
int res;
res = mpz_odd_p(MPZ(self));
if (res)
Py_RETURN_TRUE;
else
Py_RETURN_FALSE;
}
/*
* Add mapping support to mpz objects.
*/
static Py_ssize_t
GMPy_MPZ_Method_Length(MPZ_Object *self)
{
return mpz_sizeinbase(self->z, 2);
}
static PyObject *
GMPy_MPZ_Method_SubScript(MPZ_Object *self, PyObject *item)
{
if (PyIndex_Check(item)) {
Py_ssize_t i;
i = PyLong_AsSsize_t(item);
if (i == -1 && PyErr_Occurred()) {
INDEX_ERROR("argument too large to convert to an index");
return NULL;
}
if (i < 0) {
i += mpz_sizeinbase(self->z, 2);
}
return PyLong_FromLong(mpz_tstbit(self->z, i));
}
else if (PySlice_Check(item)) {
Py_ssize_t start, stop, step, slicelength, cur, i;
MPZ_Object *result;
if (PySlice_GetIndicesEx(item,
mpz_sizeinbase(self->z, 2),
&start, &stop, &step, &slicelength) < 0) {
return NULL;
}
if ((step < 0 && start < stop) || (step > 0 && start > stop)) {
stop = start;
}
if (!(result = GMPy_MPZ_New(NULL))) {
return NULL;
}
mpz_set_ui(result->z, 0);
if (slicelength > 0) {
for (cur = start, i = 0; i < slicelength; cur += step, i++) {
if(mpz_tstbit(self->z, cur)) {
mpz_setbit(result->z, i);
}
}
}
return (PyObject*)result;
}
else {
TYPE_ERROR("bit positions must be integers");
return NULL;
}
}
static PyObject *
GMPy_MPZ_Attrib_GetNumer(MPZ_Object *self, void *closure)
{
Py_INCREF((PyObject*)self);
return (PyObject*)self;
}
static PyObject *
GMPy_MPZ_Attrib_GetReal(MPZ_Object *self, void *closure)
{
Py_INCREF((PyObject*)self);
return (PyObject*)self;
}
static PyObject *
GMPy_MPZ_Attrib_GetDenom(MPZ_Object *self, void *closure)
{
MPZ_Object *result;
if ((result = GMPy_MPZ_New(NULL))) {
mpz_set_ui(result->z, 1);
}
return (PyObject*)result;
}
PyDoc_STRVAR(GMPy_doc_mpz_method_as_integer_ratio,
"x.as_integer_ratio() -> tuple[mpz, mpz]\n\n"
"Return a pair of integers, whose ratio is exactly equal to the\n"
"original number. The ratio is in lowest terms and has a\n"
"positive denominator.");
static PyObject *
GMPy_MPZ_Method_As_Integer_Ratio(PyObject *self, PyObject *args)
{
return PyTuple_Pack(2,
GMPy_MPZ_Attrib_GetNumer((MPZ_Object*)self, NULL),
GMPy_MPZ_Attrib_GetDenom((MPZ_Object*)self, NULL));
}
PyDoc_STRVAR(GMPy_doc_mpz_method_to_bytes,
"x.to_bytes(length=1, byteorder=\'big\', *, signed=False) -> bytes\n\n\
Return an array of bytes representing an integer.\n\n\
length\n\
Length of bytes object to use. An `OverflowError` is raised if the\n\
integer is not representable with the given number of bytes.\n\
byteorder\n\
The byte order used to represent the integer. If byteorder is\n\
\'big\', the most significant byte is at the beginning of the byte\n\
array. If byteorder is \'little\', the most significant byte is at\n\
the end of the byte array. To request the native byte order of the\n\
host system, use `sys.byteorder` as the byte order value.\n\
signed\n\
Determines whether two\'s complement is used to represent the\n\
integer. If signed is `False` and a negative integer is given,\n\
an `OverflowError` is raised.");
static PyObject *
GMPy_MPZ_Method_To_Bytes(PyObject *self, PyObject *const *args,
Py_ssize_t nargs, PyObject *kwnames)
{
Py_ssize_t i, nkws = 0, size, gap, length = 1;
PyObject *bytes, *arg;
mpz_t tmp, *px = &MPZ(self);
char *buffer;
int sign, is_signed = 0, is_negative, is_big, argidx[2] = {-1, -1};
const char *byteorder = NULL, *kwname;
if (nargs > 2) {
TYPE_ERROR("to_bytes() takes at most 2 positional arguments");
return NULL;
}
if (nargs >= 1) {
argidx[0] = 0;
}
if (nargs == 2) {
argidx[1] = 1;
}
if (kwnames) {
nkws = PyTuple_GET_SIZE(kwnames);
}
if (nkws > 3) {
TYPE_ERROR("to_bytes() takes at most 3 keyword arguments");
return NULL;
}
for (i = 0; i < nkws; i++) {
kwname = PyUnicode_AsUTF8(PyTuple_GET_ITEM(kwnames, i));
if (strcmp(kwname, "signed") == 0) {
is_signed = PyObject_IsTrue(args[nargs + i]);
}
else if (strcmp(kwname, "length") == 0) {
if (nargs == 0) {
argidx[0] = (int)(nargs + i);
}
else {
TYPE_ERROR("argument for to_bytes() given by name ('length') and position (1)");
return NULL;
}
}
else if (strcmp(kwname, "byteorder") == 0) {
if (nargs <= 1) {
argidx[1] = (int)(nargs + i);
}
else {
TYPE_ERROR("argument for to_bytes() given by name ('byteorder') and position (2)");
return NULL;
}
}
else {
TYPE_ERROR("got an invalid keyword argument for to_bytes()");
return NULL;
}
}
if (argidx[0] >= 0) {
arg = args[argidx[0]];
if (PyLong_Check(arg)) {
length = PyLong_AsSsize_t(arg);
}
else {
TYPE_ERROR("to_bytes() takes an integer argument 'length'");
return NULL;
}
}
if (argidx[1] >= 0) {
arg = args[argidx[1]];
if (PyUnicode_Check(arg)) {
byteorder = PyUnicode_AsUTF8(arg);
}
else {
TYPE_ERROR("to_bytes() argument 'byteorder' must be str");
return NULL;
}
}
if (length < 0) {
VALUE_ERROR("length argument must be non-negative");
return NULL;
}
if (byteorder == NULL || strcmp(byteorder, "big") == 0) {
is_big = 1;
}
else if (strcmp(byteorder, "little") == 0) {
is_big = 0;
}
else {
VALUE_ERROR("byteorder must be either 'little' or 'big'");
return NULL;
}
is_negative = mpz_sgn(*px) < 0;
if (is_negative) {
if (!is_signed) {
OVERFLOW_ERROR("can't convert negative mpz to unsigned");
return NULL;
}
mpz_init(tmp);
mpz_ui_pow_ui(tmp, 256, length);
mpz_add(tmp, tmp, *px);
px = &tmp;
}
sign = mpz_sgn(*px);
size = mpz_sizeinbase(*px, 256) - !sign;
gap = length - size;
if (gap < 0 || sign < 0 ||
(is_signed && length && mpz_tstbit(*px, 8*length - 1) == !is_negative))
{
OVERFLOW_ERROR("mpz too big to convert");
return NULL;
}
bytes = PyBytes_FromStringAndSize(NULL, length);
if (bytes == NULL) {
return NULL;
}
buffer = PyBytes_AS_STRING(bytes);
memset(buffer, 0, length);
if (is_big) {
mpz_export(buffer + gap, NULL, 1, sizeof(char), 0, 0, *px);
}
else {
mpz_export(buffer, NULL, -1, sizeof(char), 0, 0, *px);
}
if (is_negative) {
mpz_clear(tmp);
}
return bytes;
}
PyDoc_STRVAR(GMPy_doc_mpz_method_from_bytes,
"mpz.from_bytes(bytes, byteorder=\'big\', *, signed=False) -> mpz\n\n\
Return the integer represented by the given array of bytes.\n\n\
bytes\n\
Holds the array of bytes to convert. The argument must either\n\
support the buffer protocol or be an iterable object producing bytes.\n\
`bytes` and `bytearray` are examples of built-in objects that support\n\
the buffer protocol.\n\
byteorder\n\
The byte order used to represent the integer. If byteorder is \'big\',\n\
the most significant byte is at the beginning of the byte array. If\n\
byteorder is \'little\', the most significant byte is at the end of the\n\
byte array. To request the native byte order of the host system, use\n\
`sys.byteorder` as the byte order value.\n\
signed\n\
Indicates whether two\'s complement is used to represent the integer.");
static PyObject *
GMPy_MPZ_Method_From_Bytes(PyTypeObject *type, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames)
{
Py_ssize_t i, nkws = 0, length;
PyObject *arg, *bytes;
char *buffer;
int is_signed = 0, endian, argidx[2] = {-1, -1};
const char *byteorder = NULL, *kwname;
mpz_t tmp;
MPZ_Object *result;
if (nargs > 2) {
TYPE_ERROR("from_bytes() takes at most 2 positional arguments");
return NULL;
}
if (nargs >= 1) {
argidx[0] = 0;
}
if (nargs == 2) {
argidx[1] = 1;
}
if (kwnames) {
nkws = PyTuple_GET_SIZE(kwnames);
}
if (nkws > 3) {
TYPE_ERROR("from_bytes() takes at most 3 keyword arguments");
return NULL;
}
if (nkws + nargs < 1) {
TYPE_ERROR("from_bytes() missing required argument 'bytes' (pos 1)");
return NULL;
}
for (i = 0; i < nkws; i++) {
kwname = PyUnicode_AsUTF8(PyTuple_GET_ITEM(kwnames, i));
if (strcmp(kwname, "signed") == 0) {
is_signed = PyObject_IsTrue(args[nargs + i]);
}
else if (strcmp(kwname, "bytes") == 0) {
if (nargs == 0) {
argidx[0] = (int)(nargs + i);
}
else {
TYPE_ERROR("argument for from_bytes() given by name ('bytes') and position (1)");
return NULL;
}
}
else if (strcmp(kwname, "byteorder") == 0) {
if (nargs <= 1) {
argidx[1] = (int)(nargs + i);
}
else {
TYPE_ERROR("argument for from_bytes() given by name ('byteorder') and position (2)");
return NULL;
}
}
else {
TYPE_ERROR("got an invalid keyword argument for from_bytes()");
return NULL;
}
}
if (argidx[1] >= 0) {
arg = args[argidx[1]];
if (PyUnicode_Check(arg)) {
byteorder = PyUnicode_AsUTF8(arg);
}
else {
TYPE_ERROR("from_bytes() argument 'byteorder' must be str");
return NULL;
}
}
if (byteorder == NULL || strcmp(byteorder, "big") == 0) {
endian = 1;
}
else if (strcmp(byteorder, "little") == 0) {
endian = -1;
}
else {
VALUE_ERROR("byteorder must be either 'little' or 'big'");
return NULL;
}
if (!(result = GMPy_MPZ_New(NULL))) {
return NULL;
}
bytes = PyObject_Bytes(args[argidx[0]]);
if (bytes == NULL) {
return NULL;
}
if (PyBytes_AsStringAndSize(bytes, &buffer, &length) == -1) {
return NULL;
}
mpz_import(MPZ(result), length, endian, sizeof(char), 0, 0, buffer);
Py_DECREF(bytes);
if (is_signed && mpz_tstbit(MPZ(result), 8*length - 1)) {
mpz_init(tmp);
mpz_ui_pow_ui(tmp, 256, (mp_size_t)length);
mpz_sub(MPZ(result), tmp, MPZ(result));
mpz_clear(tmp);
mpz_neg(MPZ(result), MPZ(result));
}
return (PyObject*)result;
}
static PyObject *
GMPy_MPZ_Attrib_GetImag(MPZ_Object *self, void *closure)
{
MPZ_Object *result;
if ((result = GMPy_MPZ_New(NULL))) {
mpz_set_ui(result->z, 0);
}
return (PyObject*)result;
}
PyDoc_STRVAR(GMPy_doc_mpz_method_sizeof,
"x.__sizeof__()\n\n"
"Returns the amount of memory consumed by x. Note: deleted mpz objects\n"
"are reused and may or may not be resized when a new value is assigned.");
static PyObject *
GMPy_MPZ_Method_SizeOf(PyObject *self, PyObject *other)
{
return PyLong_FromSize_t(sizeof(MPZ_Object) + \
(MPZ(self)->_mp_alloc * sizeof(mp_limb_t)));
}
/* Note: this particular function is also used for xmpz, mpq, and mpfr. Only
* mpc.conjugate() does more that just return another reference to the original
* object.
*/
PyDoc_STRVAR(GMPy_doc_mp_method_conjugate,
"x.conjugate() -> mpz\n\n"
"Return the conjugate of x (which is just a new reference to x since x is\n"
"not a complex number).");
static PyObject *
GMPy_MP_Method_Conjugate(PyObject *self, PyObject *args)
{
Py_INCREF((PyObject*)self);
return (PyObject*)self;
}
././@PaxHeader 0000000 0000000 0000000 00000000026 00000000000 010213 x ustar 00 22 mtime=1710307256.0
gmpy2-2.2.1/src/gmpy2_mpz_misc.h 0000644 0001750 0001750 00000016174 14574233670 015145 0 ustar 00case case /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* gmpy2_mpz_misc.h *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Python interface to the GMP, MPFR, and MPC multiple precision *
* libraries. *
* *
* Copyright 2000 - 2009 Alex Martelli *
* *
* Copyright 2008 - 2024 Case Van Horsen *
* *
* This file is part of GMPY2. *
* *
* GMPY2 is free software: you can redistribute it and/or modify it under *
* the terms of the GNU Lesser General Public License as published by the *
* Free Software Foundation, either version 3 of the License, or (at your *
* option) any later version. *
* *
* GMPY2 is distributed in the hope that it will be useful, but WITHOUT *
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or *
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public *
* License for more details. *
* *
* You should have received a copy of the GNU Lesser General Public *
* License along with GMPY2; if not, see *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
#ifndef GMPY_MPZ_MISC_H
#define GMPY_MPZ_MISC_H
#ifdef __cplusplus
extern "C" {
#endif
static int GMPy_MPZ_NonZero_Slot(MPZ_Object *self);
static PyObject * GMPy_MPZ_Attrib_GetNumer(MPZ_Object *self, void *closure);
static PyObject * GMPy_MPZ_Attrib_GetDenom(MPZ_Object *self, void *closure);
static PyObject * GMPy_MPZ_Attrib_GetReal(MPZ_Object *self, void *closure);
static PyObject * GMPy_MPZ_Attrib_GetImag(MPZ_Object *self, void *closure);
static PyObject * GMPy_MPZ_Method_As_Integer_Ratio(PyObject *self, PyObject *args);
static PyObject * GMPy_MPZ_Method_To_Bytes(PyObject *self, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames);
static PyObject * GMPy_MPZ_Method_From_Bytes(PyTypeObject *type, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames);
static PyObject * GMPy_MPZ_Method_Ceil(PyObject *self, PyObject *other);
static PyObject * GMPy_MPZ_Method_Floor(PyObject *self, PyObject *other);
static PyObject * GMPy_MPZ_Method_Trunc(PyObject *self, PyObject *other);
static PyObject * GMPy_MPZ_Method_Round(PyObject *self, PyObject *const *args, Py_ssize_t nargs);
static PyObject * GMPy_MPZ_Method_NumDigits(PyObject *self, PyObject *const *args, Py_ssize_t nargs);
static Py_ssize_t GMPy_MPZ_Method_Length(MPZ_Object *self);
static PyObject * GMPy_MPZ_Method_SubScript(MPZ_Object *self, PyObject *item);
static PyObject * GMPy_MPZ_Method_IsSquare(PyObject *self, PyObject *other);
static PyObject * GMPy_MPZ_Method_IsDivisible(PyObject *self, PyObject *other);
static PyObject * GMPy_MPZ_Method_IsCongruent(PyObject *self, PyObject *const *args, Py_ssize_t nargs);
static PyObject * GMPy_MPZ_Method_IsPower(PyObject *self, PyObject *other);
static PyObject * GMPy_MPZ_Method_IsPrime(PyObject *self, PyObject *const *args, Py_ssize_t nargs);
static PyObject * GMPy_MPZ_Method_IsProbabPrime(PyObject *self, PyObject *const *args, Py_ssize_t nargs);
static PyObject * GMPy_MPZ_Method_IsEven(PyObject *self, PyObject *other);
static PyObject * GMPy_MPZ_Method_IsOdd(PyObject *self, PyObject *other);
static PyObject * GMPy_MP_Method_Conjugate(PyObject *self, PyObject *args);
static PyObject * GMPy_MPZ_Function_NumDigits(PyObject *self, PyObject *const *args, Py_ssize_t nargs);
static PyObject * GMPy_MPZ_Function_Iroot(PyObject *self, PyObject *const *args, Py_ssize_t nargs);
static PyObject * GMPy_MPZ_Function_IrootRem(PyObject *self, PyObject *const *args, Py_ssize_t nargs);
static PyObject * GMPy_MPZ_Function_Bincoef(PyObject *self, PyObject *const *args, Py_ssize_t nargs);
static PyObject * GMPy_MPZ_Function_GCD(PyObject *self, PyObject * const *args, Py_ssize_t nargs);
static PyObject * GMPy_MPZ_Function_LCM(PyObject *self, PyObject * const *args, Py_ssize_t nargs);
static PyObject * GMPy_MPZ_Function_GCDext(PyObject *self, PyObject * const *args, Py_ssize_t nargs);
static PyObject * GMPy_MPZ_Function_Divm(PyObject *self, PyObject * const *args, Py_ssize_t nargs);
static PyObject * GMPy_MPZ_Function_Fac(PyObject *self, PyObject *other);
static PyObject * GMPy_MPZ_Function_Primorial(PyObject *self, PyObject *other);
static PyObject * GMPy_MPZ_Function_DoubleFac(PyObject *self, PyObject *other);
static PyObject * GMPy_MPZ_Function_MultiFac(PyObject *self, PyObject * const *args, Py_ssize_t nargs);
static PyObject * GMPy_MPZ_Function_Fib(PyObject *self, PyObject *other);
static PyObject * GMPy_MPZ_Function_Fib2(PyObject *self, PyObject *other);
static PyObject * GMPy_MPZ_Function_Lucas(PyObject *self, PyObject *other);
static PyObject * GMPy_MPZ_Function_Lucas2(PyObject *self, PyObject *other);
static PyObject * GMPy_MPZ_Function_Isqrt(PyObject *self, PyObject *other);
static PyObject * GMPy_MPZ_Function_IsqrtRem(PyObject *self, PyObject *other);
static PyObject * GMPy_MPZ_Function_Remove(PyObject *self, PyObject * const *args, Py_ssize_t nargs);
static PyObject * GMPy_MPZ_Function_Invert(PyObject *self, PyObject * const *args, Py_ssize_t nargs);
static PyObject * GMPy_MPZ_Function_Divexact(PyObject *self, PyObject * const *args, Py_ssize_t nargs);
static PyObject * GMPy_MPZ_Function_IsSquare(PyObject *self, PyObject *other);
static PyObject * GMPy_MPZ_Function_IsDivisible(PyObject *self, PyObject * const *args, Py_ssize_t nargs);
static PyObject * GMPy_MPZ_Function_IsCongruent(PyObject *self, PyObject * const *args, Py_ssize_t nargs);
static PyObject * GMPy_MPZ_Function_IsPower(PyObject *self, PyObject *other);
static PyObject * GMPy_MPZ_Function_IsPrime(PyObject *self, PyObject * const *args, Py_ssize_t nargs);
static PyObject * GMPy_MPZ_Function_IsProbabPrime(PyObject *self, PyObject *const *args, Py_ssize_t nargs);
static PyObject * GMPy_MPZ_Function_NextPrime(PyObject *self, PyObject *other);
#if (__GNU_MP_VERSION > 6) || (__GNU_MP_VERSION == 6 && __GNU_MP_VERSION_MINOR >= 3)
static PyObject * GMPy_MPZ_Function_PrevPrime(PyObject *self, PyObject *other);
#endif
static PyObject * GMPy_MPZ_Function_Jacobi(PyObject *self, PyObject * const *args, Py_ssize_t nargs);
static PyObject * GMPy_MPZ_Function_Legendre(PyObject *self, PyObject * const *args, Py_ssize_t nargs);
static PyObject * GMPy_MPZ_Function_Kronecker(PyObject *self, PyObject * const *args, Py_ssize_t nargs);
static PyObject * GMPy_MPZ_Function_IsEven(PyObject *self, PyObject *other);
static PyObject * GMPy_MPZ_Function_IsOdd(PyObject *self, PyObject *other);
#ifdef __cplusplus
}
#endif
#endif
././@PaxHeader 0000000 0000000 0000000 00000000026 00000000000 010213 x ustar 00 22 mtime=1710307256.0
gmpy2-2.2.1/src/gmpy2_mpz_pack.c 0000644 0001750 0001750 00000021023 14574233670 015110 0 ustar 00case case /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* gmpy2_mpz_pack.c *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Python interface to the GMP, MPFR, and MPC multiple precision *
* libraries. *
* *
* Copyright 2000 - 2009 Alex Martelli *
* *
* Copyright 2008 - 2024 Case Van Horsen *
* *
* This file is part of GMPY2. *
* *
* GMPY2 is free software: you can redistribute it and/or modify it under *
* the terms of the GNU Lesser General Public License as published by the *
* Free Software Foundation, either version 3 of the License, or (at your *
* option) any later version. *
* *
* GMPY2 is distributed in the hope that it will be useful, but WITHOUT *
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or *
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public *
* License for more details. *
* *
* You should have received a copy of the GNU Lesser General Public *
* License along with GMPY2; if not, see *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
/*
**************************************************************************
* pack and unpack methods
*
* Both pack and unpack use a devious trick when stuffing values into the
* internal structure of an mpz_t. By setting a bit beyond the range of
* interest, we are guaranteed that memory will remain available. When
* the bit is cleared, it also triggers normalization of the value by
* accounting for leading bits that are zero.
**************************************************************************
*/
PyDoc_STRVAR(doc_pack,
"pack(lst, n, /) -> mpz\n\n"
"Pack a list of integers lst into a single `mpz` by concatenating\n"
"each integer element of lst after padding to length n bits. Raises\n"
"an error if any integer is negative or greater than n bits in\n"
"length.");
static PyObject *
GMPy_MPZ_pack(PyObject *self, PyObject *args)
{
mp_bitcnt_t nbits, total_bits, tempx_bits;
mp_size_t i;
Py_ssize_t index, lst_count, temp_bits, limb_count;
PyObject *lst;
mpz_t temp, temp1;
MPZ_Object *result, *tempx = 0;
CTXT_Object *context = NULL;
if (PyTuple_GET_SIZE(args) != 2) {
TYPE_ERROR("pack() requires 'list','int' arguments");
return NULL;
}
nbits = GMPy_Integer_AsMpBitCnt(PyTuple_GET_ITEM(args, 1));
if (nbits == (mp_bitcnt_t)(-1) && PyErr_Occurred()) {
return NULL;
}
if (!PyList_Check(PyTuple_GET_ITEM(args, 0))) {
TYPE_ERROR("pack() requires 'list','int' arguments");
return NULL;
}
if (!(result = GMPy_MPZ_New(context)))
return NULL;
lst = PyTuple_GET_ITEM(args, 0);
lst_count = PyList_GET_SIZE(lst);
total_bits = nbits * lst_count;
if ((total_bits / lst_count) != nbits) {
VALUE_ERROR("result too large to store in an 'mpz'");
return NULL;
}
mpz_set_ui(result->z, 0);
mpz_setbit(result->z, total_bits + (mp_bits_per_limb * 2));
mpz_init(temp);
mpz_init(temp1);
mpz_set_ui(temp, 0);
limb_count = 0;
tempx_bits = 0;
for (index = 0; index < lst_count; index++) {
if (!(tempx = GMPy_MPZ_From_Integer(PyList_GetItem(lst, index), context))
|| (mpz_sgn(tempx->z) < 0)
|| (mpz_sizeinbase(tempx->z,2) > (size_t)nbits)) {
TYPE_ERROR("pack() requires list elements be positive integers < 2^n bits");
mpz_clear(temp);
Py_XDECREF((PyObject*)tempx);
Py_DECREF((PyObject*)result);
return NULL;
}
mpz_mul_2exp(temp1, tempx->z, tempx_bits);
mpz_add(temp, temp, temp1);
tempx_bits += nbits;
i = 0;
temp_bits = mpz_sizeinbase(temp, 2) * mpz_sgn(temp);
while (tempx_bits >= (mp_bitcnt_t)mp_bits_per_limb) {
if (temp_bits > 0) {
result->z->_mp_d[limb_count] = mpz_getlimbn(temp, i);
}
i += 1;
tempx_bits -= mp_bits_per_limb;
limb_count += 1;
temp_bits -= mp_bits_per_limb;
}
if (temp_bits > 0) {
mpz_tdiv_q_2exp(temp, temp, mp_bits_per_limb * (mp_bitcnt_t)i);
}
else {
mpz_set_ui(temp, 0);
}
Py_DECREF((PyObject*)tempx);
}
result->z->_mp_d[limb_count] = mpz_getlimbn(temp, 0);
mpz_clrbit(result->z, total_bits + (mp_bits_per_limb * 2));
mpz_clear(temp);
mpz_clear(temp1);
return (PyObject*)result;
}
PyDoc_STRVAR(doc_unpack,
"unpack(x, n, /) -> list\n\n"
"Unpack an integer x into a list of n-bit values. Equivalent to\n"
"repeated division by 2**n. Raises error if x is negative.");
static PyObject *
GMPy_MPZ_unpack(PyObject *self, PyObject *args)
{
mp_bitcnt_t nbits, total_bits, guard_bit, extra_bits, temp_bits;
mp_size_t index = 0;
Py_ssize_t lst_count, i, lst_ptr = 0;
PyObject *result;
mpz_t temp;
mp_limb_t extra = 0;
MPZ_Object *item, *tempx = NULL;
CTXT_Object *context = NULL;
if (PyTuple_GET_SIZE(args) != 2) {
TYPE_ERROR("unpack() requires 'int','int' arguments");
return NULL;
}
nbits = GMPy_Integer_AsMpBitCnt(PyTuple_GET_ITEM(args, 1));
if (nbits == (mp_bitcnt_t)(-1) && PyErr_Occurred()) {
return NULL;
}
if (!(tempx = GMPy_MPZ_From_Integer(PyTuple_GET_ITEM(args, 0), context))) {
TYPE_ERROR("unpack() requires 'int','int' arguments");
return NULL;
}
if (mpz_sgn(tempx->z) < 0) {
VALUE_ERROR("unpack() requires x >= 0");
return NULL;
}
if (mpz_sgn(tempx->z) == 0) {
total_bits = 0;
}
else {
total_bits = mpz_sizeinbase(tempx->z, 2);
}
lst_count = total_bits / nbits;
if ((total_bits % nbits) || !lst_count) {
lst_count += 1;
}
if (!(result = PyList_New(lst_count))) {
/* LCOV_EXCL_START */
Py_DECREF((PyObject*)tempx);
return NULL;
/* LCOV_EXCL_STOP */
}
if (mpz_sgn(tempx->z) == 0) {
if (!(item = GMPy_MPZ_New(context))) {
/* LCOV_EXCL_START */
Py_DECREF((PyObject*)tempx);
Py_DECREF(result);
return NULL;
/* LCOV_EXCL_STOP */
}
mpz_set_ui(item->z, 0);
PyList_SET_ITEM(result, 0, (PyObject*)item);
Py_DECREF((PyObject*)tempx);
return result;
}
mpz_init(temp);
guard_bit = nbits + (2 * mp_bits_per_limb);
extra_bits = 0;
index = 0;
while (lst_ptr < lst_count) {
i = 0;
temp_bits = 0;
mpz_set_ui(temp, 0);
mpz_setbit(temp, guard_bit);
while (temp_bits + extra_bits < nbits) {
temp->_mp_d[i++] = mpz_getlimbn(tempx->z, index++);
temp_bits += mp_bits_per_limb;
}
mpz_clrbit(temp, guard_bit);
mpz_mul_2exp(temp, temp, extra_bits);
if (mpz_sgn(temp) == 0 && extra != 0) {
mpz_set_ui(temp, 1);
temp->_mp_d[0] = extra;
}
else {
mpn_add_1(temp->_mp_d, temp->_mp_d, (mp_size_t)mpz_size(temp), extra);
}
temp_bits += extra_bits;
while ((lst_ptr < lst_count) && (temp_bits >= nbits)) {
if(!(item = GMPy_MPZ_New(context))) {
/* LCOV_EXCL_START */
mpz_clear(temp);
Py_DECREF((PyObject*)tempx);
Py_DECREF(result);
return NULL;
/* LCOV_EXCL_STOP */
}
mpz_tdiv_r_2exp(item->z, temp, nbits);
PyList_SET_ITEM(result, lst_ptr++, (PyObject*)item);
mpz_tdiv_q_2exp(temp, temp, nbits);
temp_bits -= nbits;
}
extra = mpz_getlimbn(temp, 0);
extra_bits = temp_bits;
}
Py_DECREF((PyObject*)tempx);
mpz_clear(temp);
return result;
}
././@PaxHeader 0000000 0000000 0000000 00000000026 00000000000 010213 x ustar 00 22 mtime=1710307256.0
gmpy2-2.2.1/src/gmpy2_mpz_pack.h 0000644 0001750 0001750 00000004203 14574233670 015116 0 ustar 00case case /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* gmpy2_mpz_pack.h *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Python interface to the GMP, MPFR, and MPC multiple precision *
* libraries. *
* *
* Copyright 2000 - 2009 Alex Martelli *
* *
* Copyright 2008 - 2024 Case Van Horsen *
* *
* This file is part of GMPY2. *
* *
* GMPY2 is free software: you can redistribute it and/or modify it under *
* the terms of the GNU Lesser General Public License as published by the *
* Free Software Foundation, either version 3 of the License, or (at your *
* option) any later version. *
* *
* GMPY2 is distributed in the hope that it will be useful, but WITHOUT *
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or *
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public *
* License for more details. *
* *
* You should have received a copy of the GNU Lesser General Public *
* License along with GMPY2; if not, see *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
#ifndef GMPY_MPZ_PACK_H
#define GMPY_MPZ_PACK_H
#ifdef __cplusplus
extern "C" {
#endif
static PyObject * GMPy_MPZ_pack(PyObject *self, PyObject *args);
static PyObject * GMPy_MPZ_unpack(PyObject *self, PyObject *args);
#ifdef __cplusplus
}
#endif
#endif
././@PaxHeader 0000000 0000000 0000000 00000000026 00000000000 010213 x ustar 00 22 mtime=1710307256.0
gmpy2-2.2.1/src/gmpy2_mul.c 0000644 0001750 0001750 00000026626 14574233670 014117 0 ustar 00case case /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* gmpy2_mul.c *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Python interface to the GMP, MPFR, and MPC multiple precision *
* libraries. *
* *
* Copyright 2000 - 2009 Alex Martelli *
* *
* Copyright 2008 - 2024 Case Van Horsen *
* *
* This file is part of GMPY2. *
* *
* GMPY2 is free software: you can redistribute it and/or modify it under *
* the terms of the GNU Lesser General Public License as published by the *
* Free Software Foundation, either version 3 of the License, or (at your *
* option) any later version. *
* *
* GMPY2 is distributed in the hope that it will be useful, but WITHOUT *
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or *
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public *
* License for more details. *
* *
* You should have received a copy of the GNU Lesser General Public *
* License along with GMPY2; if not, see *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
/* This file implements the * operator, gmpy2.mul() and context.mul().
*/
/* Multiply two Integer objects (see gmpy2_convert.c). If an error occurs,
* NULL is returned and an exception is set. If either x or y can't be
* converted into an mpz, Py_NotImplemented is returned. */
static PyObject *
GMPy_Integer_MulWithType(PyObject *x, int xtype, PyObject *y, int ytype,
CTXT_Object *context)
{
MPZ_Object *result = NULL;
if (!(result = GMPy_MPZ_New(context))) {
/* LCOV_EXCL_START */
return NULL;
/* LCOV_EXCL_STOP */
}
if (IS_TYPE_MPZANY(xtype)) {
if (IS_TYPE_MPZANY(ytype)) {
GMPY_MAYBE_BEGIN_ALLOW_THREADS(context);
mpz_mul(result->z, MPZ(x), MPZ(y));
GMPY_MAYBE_END_ALLOW_THREADS(context);
return (PyObject*)result;
}
if (IS_TYPE_PyInteger(ytype)) {
int error;
long temp = PyLong_AsLongAndOverflow(y, &error);
if (!error) {
mpz_mul_si(result->z, MPZ(x), temp);
}
else {
mpz_set_PyLong(result->z, y);
GMPY_MAYBE_BEGIN_ALLOW_THREADS(context);
mpz_mul(result->z, MPZ(x), result->z);
GMPY_MAYBE_END_ALLOW_THREADS(context);
}
return (PyObject*)result;
}
}
if (IS_TYPE_MPZANY(ytype)) {
if (IS_TYPE_PyInteger(xtype)) {
int error;
long temp = PyLong_AsLongAndOverflow(x, &error);
if (!error) {
mpz_mul_si(result->z, MPZ(y), temp);
}
else {
mpz_set_PyLong(result->z, x);
GMPY_MAYBE_BEGIN_ALLOW_THREADS(context);
mpz_mul(result->z, result->z, MPZ(y));
GMPY_MAYBE_END_ALLOW_THREADS(context);
}
return (PyObject*)result;
}
}
if (IS_TYPE_INTEGER(xtype) && (IS_TYPE_INTEGER(ytype))) {
MPZ_Object *tempx = NULL, *tempy = NULL;
if (!(tempx = GMPy_MPZ_From_IntegerWithType(x, xtype, context)) ||
!(tempy = GMPy_MPZ_From_IntegerWithType(y, ytype, context))) {
/* LCOV_EXCL_START */
Py_XDECREF((PyObject*)tempx);
Py_XDECREF((PyObject*)tempy);
Py_DECREF((PyObject*)result);
return NULL;
/* LCOV_EXCL_STOP */
}
GMPY_MAYBE_BEGIN_ALLOW_THREADS(context);
mpz_mul(result->z, tempx->z, tempy->z);
GMPY_MAYBE_END_ALLOW_THREADS(context);
Py_DECREF((PyObject*)tempx);
Py_DECREF((PyObject*)tempy);
return (PyObject*)result;
}
/* LCOV_EXCL_START */
Py_DECREF((PyObject*)result);
TYPE_ERROR("mul() argument type not supported");
return NULL;
/* LCOV_EXCL_STOP */
}
static PyObject *
GMPy_Rational_MulWithType(PyObject *x, int xtype, PyObject *y, int ytype,
CTXT_Object *context)
{
MPQ_Object *result = NULL;
if (!(result = GMPy_MPQ_New(context))) {
/* LCOV_EXCL_START */
return NULL;
/* LCOV_EXCL_STOP */
}
if (IS_TYPE_MPQ(xtype) && IS_TYPE_MPQ(ytype)) {
GMPY_MAYBE_BEGIN_ALLOW_THREADS(context);
mpq_mul(result->q, MPQ(x), MPQ(y));
GMPY_MAYBE_END_ALLOW_THREADS(context);
return (PyObject*)result;
}
if (IS_TYPE_RATIONAL(xtype) && IS_TYPE_RATIONAL(ytype)) {
MPQ_Object *tempx = NULL, *tempy = NULL;
if (!(tempx = GMPy_MPQ_From_RationalWithType(x, xtype, context)) ||
!(tempy = GMPy_MPQ_From_RationalWithType(y, ytype, context))) {
/* LCOV_EXCL_START */
Py_XDECREF((PyObject*)tempx);
Py_XDECREF((PyObject*)tempy);
Py_DECREF((PyObject*)result);
return NULL;
/* LCOV_EXCL_STOP */
}
GMPY_MAYBE_BEGIN_ALLOW_THREADS(context);
mpq_mul(result->q, tempx->q, tempy->q);
GMPY_MAYBE_END_ALLOW_THREADS(context);
Py_DECREF((PyObject*)tempx);
Py_DECREF((PyObject*)tempy);
return (PyObject*)result;
}
/* LCOV_EXCL_START */
Py_DECREF((PyObject*)result);
TYPE_ERROR("mul() argument type not supported");
return NULL;
/* LCOV_EXCL_STOP */
}
static PyObject *
GMPy_Real_MulWithType(PyObject *x, int xtype, PyObject *y, int ytype,
CTXT_Object *context)
{
MPFR_Object *result = NULL;
if (!(result = GMPy_MPFR_New(0, context))) {
/* LCOV_EXCL_START */
return NULL;
/* LCOV_EXCL_STOP */
}
if (IS_TYPE_MPFR(xtype) && IS_TYPE_MPFR(ytype)) {
mpfr_clear_flags();
result->rc = mpfr_mul(result->f, MPFR(x), MPFR(y), GET_MPFR_ROUND(context));
_GMPy_MPFR_Cleanup(&result, context);
return (PyObject*)result;
}
if (IS_TYPE_REAL(xtype) && IS_TYPE_REAL(ytype)) {
MPFR_Object *tempx = NULL, *tempy = NULL;
if (!(tempx = GMPy_MPFR_From_RealWithType(x, xtype, 1, context)) ||
!(tempy = GMPy_MPFR_From_RealWithType(y, ytype, 1, context))) {
/* LCOV_EXCL_START */
Py_XDECREF((PyObject*)tempx);
Py_XDECREF((PyObject*)tempy);
Py_DECREF((PyObject*)result);
return NULL;
/* LCOV_EXCL_STOP */
}
mpfr_clear_flags();
result->rc = mpfr_mul(result->f, MPFR(tempx), MPFR(tempy), GET_MPFR_ROUND(context));
Py_DECREF((PyObject*)tempx);
Py_DECREF((PyObject*)tempy);
_GMPy_MPFR_Cleanup(&result, context);
return (PyObject*)result;
}
/* LCOV_EXCL_START */
Py_DECREF((PyObject*)result);
TYPE_ERROR("mul() argument type not supported");
return NULL;
/* LCOV_EXCL_STOP */
}
/* GMPy_Complex_Mul(x, y, context) returns x*y using the provided context. If
* an error occurs, NULL is returned and an exception is set. If either x or
* y can't be converted to an mpc, then Py_NotImplemented is returned. */
static PyObject *
GMPy_Complex_MulWithType(PyObject *x, int xtype, PyObject *y, int ytype,
CTXT_Object *context)
{
MPC_Object *result = NULL;
if (!(result = GMPy_MPC_New(0, 0, context))) {
/* LCOV_EXCL_START */
return NULL;
/* LCOV_EXCL_STOP */
}
if (IS_TYPE_MPC(xtype) && IS_TYPE_MPC(ytype)) {
result->rc = mpc_mul(result->c, MPC(x), MPC(y), GET_MPC_ROUND(context));
_GMPy_MPC_Cleanup(&result, context);
return (PyObject*)result;
}
if (IS_TYPE_COMPLEX(xtype) && IS_TYPE_COMPLEX(ytype)) {
MPC_Object *tempx = NULL, *tempy = NULL;
if (!(tempx = GMPy_MPC_From_ComplexWithType(x, xtype, 1, 1, context)) ||
!(tempy = GMPy_MPC_From_ComplexWithType(y, ytype, 1, 1, context))) {
/* LCOV_EXCL_START */
Py_XDECREF((PyObject*)tempx);
Py_XDECREF((PyObject*)tempy);
Py_DECREF((PyObject*)result);
return NULL;
/* LCOV_EXCL_STOP */
}
result->rc = mpc_mul(result->c, tempx->c, tempy->c, GET_MPC_ROUND(context));
Py_DECREF((PyObject*)tempx);
Py_DECREF((PyObject*)tempy);
_GMPy_MPC_Cleanup(&result, context);
return (PyObject*)result;
}
/* LCOV_EXCL_START */
Py_DECREF((PyObject*)result);
TYPE_ERROR("mul() argument type not supported");
return NULL;
/* LCOV_EXCL_STOP */
}
static PyObject *
GMPy_Number_Mul(PyObject *x, PyObject *y, CTXT_Object *context)
{
CHECK_CONTEXT(context);
int xtype = GMPy_ObjectType(x);
int ytype = GMPy_ObjectType(y);
if (IS_TYPE_INTEGER(xtype) && IS_TYPE_INTEGER(ytype))
return GMPy_Integer_MulWithType(x, xtype, y, ytype, context);
if (IS_TYPE_RATIONAL(xtype) && IS_TYPE_RATIONAL(ytype))
return GMPy_Rational_MulWithType(x, xtype, y, ytype, context);
if (IS_TYPE_REAL(xtype) && IS_TYPE_REAL(ytype))
return GMPy_Real_MulWithType(x, xtype, y, ytype, context);
if (IS_TYPE_COMPLEX(xtype) && IS_TYPE_COMPLEX(ytype))
return GMPy_Complex_MulWithType(x, xtype, y, ytype, context);
TYPE_ERROR("mul() argument type not supported");
return NULL;
}
/* Implement all the slot methods here. */
static PyObject *
GMPy_Number_Mul_Slot(PyObject *x, PyObject *y)
{
CTXT_Object *context = NULL;
CHECK_CONTEXT(context);
int xtype = GMPy_ObjectType(x);
int ytype = GMPy_ObjectType(y);
if (IS_TYPE_INTEGER(xtype) && IS_TYPE_INTEGER(ytype))
return GMPy_Integer_MulWithType(x, xtype, y, ytype, context);
if (IS_TYPE_RATIONAL(xtype) && IS_TYPE_RATIONAL(ytype))
return GMPy_Rational_MulWithType(x, xtype, y, ytype, context);
if (IS_TYPE_REAL(xtype) && IS_TYPE_REAL(ytype))
return GMPy_Real_MulWithType(x, xtype, y, ytype, context);
if (IS_TYPE_COMPLEX(xtype) && IS_TYPE_COMPLEX(ytype))
return GMPy_Complex_MulWithType(x, xtype, y, ytype, context);
Py_RETURN_NOTIMPLEMENTED;
}
/* Implement context.mul() and gmpy2.mul(). */
PyDoc_STRVAR(GMPy_doc_function_mul,
"mul(x, y, /) -> mpz | mpq | mpfr | mpc\n\n"
"Return x * y.");
PyDoc_STRVAR(GMPy_doc_context_mul,
"context.mul(x, y, /) -> mpz | mpq | mpfr | mpc\n\n"
"Return x * y.");
static PyObject *
GMPy_Context_Mul(PyObject *self, PyObject *args)
{
CTXT_Object *context = NULL;
if (PyTuple_GET_SIZE(args) != 2) {
TYPE_ERROR("mul() requires 2 arguments");
return NULL;
}
if (self && CTXT_Check(self)) {
context = (CTXT_Object*)self;
}
else {
CHECK_CONTEXT(context);
}
return GMPy_Number_Mul(PyTuple_GET_ITEM(args, 0),
PyTuple_GET_ITEM(args, 1),
context);
}
././@PaxHeader 0000000 0000000 0000000 00000000026 00000000000 010213 x ustar 00 22 mtime=1710307256.0
gmpy2-2.2.1/src/gmpy2_mul.h 0000644 0001750 0001750 00000005301 14574233670 014107 0 ustar 00case case /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* gmpy2_mul.h *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Python interface to the GMP, MPFR, and MPC multiple precision *
* libraries. *
* *
* Copyright 2000 - 2009 Alex Martelli *
* *
* Copyright 2008 - 2024 Case Van Horsen *
* *
* This file is part of GMPY2. *
* *
* GMPY2 is free software: you can redistribute it and/or modify it under *
* the terms of the GNU Lesser General Public License as published by the *
* Free Software Foundation, either version 3 of the License, or (at your *
* option) any later version. *
* *
* GMPY2 is distributed in the hope that it will be useful, but WITHOUT *
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or *
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public *
* License for more details. *
* *
* You should have received a copy of the GNU Lesser General Public *
* License along with GMPY2; if not, see *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
#ifndef GMPY2_MUL_H
#define GMPY2_MUL_H
#ifdef __cplusplus
extern "C" {
#endif
/* Public API */
static PyObject * GMPy_Number_Mul(PyObject *x, PyObject *y, CTXT_Object *context);
/* Private API */
static PyObject * GMPy_Integer_MulWithType(PyObject *x, int xtype, PyObject *y, int ytype, CTXT_Object *context);
static PyObject * GMPy_Rational_MulWithType(PyObject *x, int xtype, PyObject *y, int ytype, CTXT_Object *context);
static PyObject * GMPy_Real_MulWithType(PyObject *x, int xtype, PyObject *y, int ytype, CTXT_Object *context);
static PyObject * GMPy_Complex_MulWithType(PyObject *x, int xtype, PyObject *y, int ytype, CTXT_Object *context);
static PyObject * GMPy_Number_Mul_Slot(PyObject *x, PyObject *y);
static PyObject * GMPy_Context_Mul(PyObject *self, PyObject *args);
#ifdef __cplusplus
}
#endif
#endif
././@PaxHeader 0000000 0000000 0000000 00000000026 00000000000 010213 x ustar 00 22 mtime=1710307256.0
gmpy2-2.2.1/src/gmpy2_muldiv_2exp.c 0000644 0001750 0001750 00000020003 14574233670 015537 0 ustar 00case case /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* gmpy2_muldiv_2exp.c *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Python interface to the GMP, MPFR, and MPC multiple precision *
* libraries. *
* *
* Copyright 2000 - 2009 Alex Martelli *
* *
* Copyright 2008 - 2024 Case Van Horsen *
* *
* This file is part of GMPY2. *
* *
* GMPY2 is free software: you can redistribute it and/or modify it under *
* the terms of the GNU Lesser General Public License as published by the *
* Free Software Foundation, either version 3 of the License, or (at your *
* option) any later version. *
* *
* GMPY2 is distributed in the hope that it will be useful, but WITHOUT *
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or *
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public *
* License for more details. *
* *
* You should have received a copy of the GNU Lesser General Public *
* License along with GMPY2; if not, see *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
static PyObject *
GMPy_Real_Mul_2exp(PyObject *x, PyObject *y, CTXT_Object *context)
{
MPFR_Object *result, *tempx;
long exp;
int is_signed = 0;
CHECK_CONTEXT(context);
exp = GMPy_Integer_AsUnsignedLongOrLong(y, &is_signed);
if (exp == -1 && PyErr_Occurred()) {
return NULL;
}
result = GMPy_MPFR_New(0, context);
tempx = GMPy_MPFR_From_Real(x, 1, context);
if (!result || !tempx) {
/* LCOV_EXCL_START */
Py_XDECREF((PyObject*)result);
Py_XDECREF((PyObject*)tempx);
return NULL;
/* LCOV_EXCL_STOP */
}
mpfr_clear_flags();
if (is_signed) {
result->rc = mpfr_mul_2si(result->f, tempx->f, exp,
GET_MPFR_ROUND(context));
}
else {
result->rc = mpfr_mul_2ui(result->f, tempx->f, (unsigned long)exp,
GET_MPFR_ROUND(context));
}
Py_DECREF((PyObject*)tempx);
_GMPy_MPFR_Cleanup(&result, context);
return (PyObject*)result;
}
static PyObject *
GMPy_Complex_Mul_2exp(PyObject *x, PyObject *y, CTXT_Object *context)
{
MPC_Object *result, *tempx;
long exp;
int is_signed = 0;
CHECK_CONTEXT(context);
exp = GMPy_Integer_AsUnsignedLongOrLong(y, &is_signed);
if (exp == -1 && PyErr_Occurred()) {
return NULL;
}
result = GMPy_MPC_New(0, 0, context);
tempx = GMPy_MPC_From_Complex(x, 1, 1, context);
if (!result || !tempx) {
/* LCOV_EXCL_START */
Py_XDECREF((PyObject*)result);
Py_XDECREF((PyObject*)tempx);
return NULL;
/* LCOV_EXCL_STOP */
}
if (is_signed) {
result->rc = mpc_mul_2si(result->c, tempx->c, exp,
GET_MPC_ROUND(context));
}
else {
result->rc = mpc_mul_2ui(result->c, tempx->c, exp,
GET_MPC_ROUND(context));
}
Py_DECREF((PyObject*)tempx);
_GMPy_MPC_Cleanup(&result, context);
return (PyObject*)result;
}
PyDoc_STRVAR(GMPy_doc_context_mul_2exp,
"context.mul_2exp(x, n, /) -> mpfr | mpc\n\n"
"Return `mpfr` or `mpc` multiplied by 2**n.");
PyDoc_STRVAR(GMPy_doc_function_mul_2exp,
"mul_2exp(x, n, /) -> mpfr | mpc\n\n"
"Return x multiplied by 2**n.");
static PyObject *
GMPy_Number_Mul_2exp(PyObject *x, PyObject *y, CTXT_Object *context)
{
if (IS_REAL(x))
return GMPy_Real_Mul_2exp(x, y, context);
if (IS_COMPLEX(x))
return GMPy_Complex_Mul_2exp(x, y, context);
TYPE_ERROR("mul_2exp() argument type not supported");
return NULL;
}
static PyObject *
GMPy_Context_Mul_2exp(PyObject *self, PyObject *args)
{
CTXT_Object *context = NULL;
if (PyTuple_GET_SIZE(args) != 2) {
TYPE_ERROR("mul_2exp() requires 2 arguments");
return NULL;
}
if (self && CTXT_Check(self)) {
context = (CTXT_Object*)self;
}
else {
CHECK_CONTEXT(context);
}
return GMPy_Number_Mul_2exp(PyTuple_GET_ITEM(args, 0),
PyTuple_GET_ITEM(args, 1),
context);
}
/* ======================================================================= */
static PyObject *
GMPy_Real_Div_2exp(PyObject *x, PyObject *y, CTXT_Object *context)
{
MPFR_Object *result, *tempx;
long exp;
int is_signed = 0;
CHECK_CONTEXT(context);
exp = GMPy_Integer_AsUnsignedLongOrLong(y, &is_signed);
if (exp == -1 && PyErr_Occurred()) {
return NULL;
}
result = GMPy_MPFR_New(0, context);
tempx = GMPy_MPFR_From_Real(x, 1, context);
if (!result || !tempx) {
/* LCOV_EXCL_START */
Py_XDECREF((PyObject*)result);
Py_XDECREF((PyObject*)tempx);
return NULL;
/* LCOV_EXCL_STOP */
}
mpfr_clear_flags();
if (is_signed) {
result->rc = mpfr_div_2si(result->f, tempx->f, exp,
GET_MPFR_ROUND(context));
}
else {
result->rc = mpfr_div_2ui(result->f, tempx->f, exp,
GET_MPFR_ROUND(context));
}
Py_DECREF((PyObject*)tempx);
_GMPy_MPFR_Cleanup(&result, context);
return (PyObject*)result;
}
static PyObject *
GMPy_Complex_Div_2exp(PyObject *x, PyObject *y, CTXT_Object *context)
{
MPC_Object *result, *tempx;
long exp;
int is_signed = 0;
CHECK_CONTEXT(context);
exp = GMPy_Integer_AsUnsignedLongOrLong(y, &is_signed);
if (exp == -1 && PyErr_Occurred()) {
return NULL;
}
result = GMPy_MPC_New(0, 0, context);
tempx = GMPy_MPC_From_Complex(x, 1, 1, context);
if (!result || !tempx) {
/* LCOV_EXCL_START */
Py_XDECREF((PyObject*)result);
Py_XDECREF((PyObject*)tempx);
return NULL;
/* LCOV_EXCL_STOP */
}
if (is_signed) {
result->rc = mpc_div_2si(result->c, tempx->c, exp,
GET_MPC_ROUND(context));
}
else {
result->rc = mpc_div_2ui(result->c, tempx->c, exp,
GET_MPC_ROUND(context));
}
Py_DECREF((PyObject*)tempx);
_GMPy_MPC_Cleanup(&result, context);
return (PyObject*)result;
}
PyDoc_STRVAR(GMPy_doc_context_div_2exp,
"context.div_2exp(x, n, /) -> mpfr | mpc\n\n"
"Return `mpfr` or `mpc` divided by 2**n.");
PyDoc_STRVAR(GMPy_doc_function_div_2exp,
"div_2exp(x, n, /) -> mpfr | mpc\n\n"
"Return x divided by 2**n.");
static PyObject *
GMPy_Number_Div_2exp(PyObject *x, PyObject *y, CTXT_Object *context)
{
if (IS_REAL(x))
return GMPy_Real_Div_2exp(x, y, context);
if (IS_COMPLEX(x))
return GMPy_Complex_Div_2exp(x, y, context);
TYPE_ERROR("div_2exp() argument type not supported");
return NULL;
}
static PyObject *
GMPy_Context_Div_2exp(PyObject *self, PyObject *args)
{
CTXT_Object *context = NULL;
if (PyTuple_GET_SIZE(args) != 2) {
TYPE_ERROR("div_2exp() requires 2 arguments");
return NULL;
}
if (self && CTXT_Check(self)) {
context = (CTXT_Object*)self;
}
else {
CHECK_CONTEXT(context);
}
return GMPy_Number_Div_2exp(PyTuple_GET_ITEM(args, 0),
PyTuple_GET_ITEM(args, 1),
context);
}
././@PaxHeader 0000000 0000000 0000000 00000000026 00000000000 010213 x ustar 00 22 mtime=1710307256.0
gmpy2-2.2.1/src/gmpy2_muldiv_2exp.h 0000644 0001750 0001750 00000005253 14574233670 015556 0 ustar 00case case /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* gmpy2_muldiv_2exp.h *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Python interface to the GMP, MPFR, and MPC multiple precision *
* libraries. *
* *
* Copyright 2000 - 2009 Alex Martelli *
* *
* Copyright 2008 - 2024 Case Van Horsen *
* *
* This file is part of GMPY2. *
* *
* GMPY2 is free software: you can redistribute it and/or modify it under *
* the terms of the GNU Lesser General Public License as published by the *
* Free Software Foundation, either version 3 of the License, or (at your *
* option) any later version. *
* *
* GMPY2 is distributed in the hope that it will be useful, but WITHOUT *
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or *
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public *
* License for more details. *
* *
* You should have received a copy of the GNU Lesser General Public *
* License along with GMPY2; if not, see *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
#ifndef GMPY_MULDIV_2EXP_H
#define GMPY_MULDIV_2EXP_H
#ifdef __cplusplus
extern "C" {
#endif
static PyObject * GMPy_Real_Mul_2exp(PyObject *x, PyObject *y, CTXT_Object *context);
static PyObject * GMPy_Complex_Mul_2exp(PyObject *x, PyObject *y, CTXT_Object *context);
static PyObject * GMPy_Number_Mul_2exp(PyObject *x, PyObject *y, CTXT_Object *context);
static PyObject * GMPy_Context_Mul_2exp(PyObject *self, PyObject *args);
static PyObject * GMPy_Real_Div_2exp(PyObject *x, PyObject *y, CTXT_Object *context);
static PyObject * GMPy_Complex_Div_2exp(PyObject *x, PyObject *y, CTXT_Object *context);
static PyObject * GMPy_Number_Div_2exp(PyObject *x, PyObject *y, CTXT_Object *context);
static PyObject * GMPy_Context_Div_2exp(PyObject *self, PyObject *args);
#ifdef __cplusplus
}
#endif
#endif
././@PaxHeader 0000000 0000000 0000000 00000000026 00000000000 010213 x ustar 00 22 mtime=1710307256.0
gmpy2-2.2.1/src/gmpy2_plus.c 0000644 0001750 0001750 00000011224 14574233670 014271 0 ustar 00case case /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* gmpy2_plus.c *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Python interface to the GMP, MPFR, and MPC multiple precision *
* libraries. *
* *
* Copyright 2000 - 2009 Alex Martelli *
* *
* Copyright 2008 - 2024 Case Van Horsen *
* *
* This file is part of GMPY2. *
* *
* GMPY2 is free software: you can redistribute it and/or modify it under *
* the terms of the GNU Lesser General Public License as published by the *
* Free Software Foundation, either version 3 of the License, or (at your *
* option) any later version. *
* *
* GMPY2 is distributed in the hope that it will be useful, but WITHOUT *
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or *
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public *
* License for more details. *
* *
* You should have received a copy of the GNU Lesser General Public *
* License along with GMPY2; if not, see *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
/* This file implements __pos__ and context.plus().
*
* Public API
* ==========
* The following function is available as part of GMPY2's C API. If the value
* of context is NULL, then the function should use the currently active
* context.
*
* GMPy_Number_Plus(Number, context)
*
* Private API
* ===========
* GMPy_MPZ_Plus_Slot
* GMPy_MPQ_Plus_Slot
* GMPy_MPFR_Plus_Slot
* GMPy_MPC_Plus_Slot
*
* GMPy_Integer_Plus(Integer, context|NULL)
* GMPy_Rational_Plus(Rational, context|NULL)
* GMPy_Real_Plus(Real, context|NULL)
* GMPy_Complex_Plus(Complex, context|NULL)
*
* GMPy_Context_Plus(context, args)
*/
static PyObject *
GMPy_Integer_PlusWithType(PyObject *x, int xtype, CTXT_Object *context)
{
return (PyObject*)GMPy_MPZ_From_IntegerWithType(x, xtype, context);
}
static PyObject *
GMPy_MPZ_Plus_Slot(MPZ_Object *x)
{
Py_INCREF((PyObject*)x);
return (PyObject*)x;
}
static PyObject *
GMPy_Rational_PlusWithType(PyObject *x, int xtype, CTXT_Object *context)
{
return (PyObject*)GMPy_MPQ_From_RationalWithType(x, xtype, context);
}
static PyObject *
GMPy_MPQ_Plus_Slot(MPQ_Object *x)
{
Py_INCREF((PyObject*)x);
return (PyObject*)x;
}
static PyObject *
GMPy_Real_PlusWithType(PyObject *x, int xtype, CTXT_Object *context)
{
return (PyObject*)GMPy_MPFR_From_RealWithType(x, xtype, 0, context);
}
static PyObject *
GMPy_MPFR_Plus_Slot(MPFR_Object *x)
{
return (PyObject*)GMPy_MPFR_From_MPFR(x, 0, NULL);
}
static PyObject *
GMPy_Complex_PlusWithType(PyObject *x, int xtype, CTXT_Object *context)
{
return (PyObject*)GMPy_MPC_From_ComplexWithType(x, xtype, 0, 0, context);
}
static PyObject *
GMPy_MPC_Plus_Slot(MPC_Object *x)
{
return (PyObject*)GMPy_MPC_From_MPC(x, 0, 0, NULL);
}
static PyObject *
GMPy_Number_Plus(PyObject *x, CTXT_Object *context)
{
int xtype = GMPy_ObjectType(x);
if (IS_TYPE_INTEGER(xtype))
return GMPy_Integer_PlusWithType(x, xtype, context);
if (IS_TYPE_RATIONAL(xtype))
return GMPy_Rational_PlusWithType(x, xtype, context);
if (IS_TYPE_REAL(xtype))
return GMPy_Real_PlusWithType(x, xtype, context);
if (IS_TYPE_COMPLEX(xtype))
return GMPy_Complex_PlusWithType(x, xtype, context);
TYPE_ERROR("plus() argument type not supported");
return NULL;
}
/* Implement context.plus(). The following code assumes it used a as method of
* a context. */
PyDoc_STRVAR(GMPy_doc_context_plus,
"context.plus(x, /) -> mpz | mpq | mpfr | mpc\n\n"
"Return +x, the context is applied to the result.");
static PyObject *
GMPy_Context_Plus(PyObject *self, PyObject *args)
{
if (PyTuple_GET_SIZE(args) != 1) {
TYPE_ERROR("plus() requires 1 argument.");
return NULL;
}
return GMPy_Number_Plus(PyTuple_GET_ITEM(args, 0), (CTXT_Object*)self);
}
././@PaxHeader 0000000 0000000 0000000 00000000026 00000000000 010213 x ustar 00 22 mtime=1710307256.0
gmpy2-2.2.1/src/gmpy2_plus.h 0000644 0001750 0001750 00000005363 14574233670 014305 0 ustar 00case case /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* gmpy2_plus.h *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Python interface to the GMP, MPFR, and MPC multiple precision *
* libraries. *
* *
* Copyright 2000 - 2009 Alex Martelli *
* *
* Copyright 2008 - 2024 Case Van Horsen *
* *
* This file is part of GMPY2. *
* *
* GMPY2 is free software: you can redistribute it and/or modify it under *
* the terms of the GNU Lesser General Public License as published by the *
* Free Software Foundation, either version 3 of the License, or (at your *
* option) any later version. *
* *
* GMPY2 is distributed in the hope that it will be useful, but WITHOUT *
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or *
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public *
* License for more details. *
* *
* You should have received a copy of the GNU Lesser General Public *
* License along with GMPY2; if not, see *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
#ifndef GMPY2_PLUS_H
#define GMPY2_PLUS_H
#ifdef __cplusplus
extern "C" {
#endif
/* Public API */
static PyObject * GMPy_Number_Plus(PyObject *x, CTXT_Object *context);
/* Private API */
static PyObject * GMPy_Integer_PlusWithType(PyObject *x, int xtype, CTXT_Object *context);
static PyObject * GMPy_Rational_PlusWithType(PyObject *x, int xtype, CTXT_Object *context);
static PyObject * GMPy_Real_PlusWithType(PyObject *x, int xtype, CTXT_Object *context);
static PyObject * GMPy_Complex_PlusWithType(PyObject *x, int xtype, CTXT_Object *context);
static PyObject * GMPy_MPZ_Plus_Slot(MPZ_Object *x);
static PyObject * GMPy_MPQ_Plus_Slot(MPQ_Object *x);
static PyObject * GMPy_MPFR_Plus_Slot(MPFR_Object *x);
static PyObject * GMPy_MPC_Plus_Slot(MPC_Object *x);
static PyObject * GMPy_Context_Plus(PyObject *self, PyObject *args);
#ifdef __cplusplus
}
#endif
#endif
././@PaxHeader 0000000 0000000 0000000 00000000026 00000000000 010213 x ustar 00 22 mtime=1711300127.0
gmpy2-2.2.1/src/gmpy2_pow.c 0000644 0001750 0001750 00000063607 14600057037 014116 0 ustar 00case case /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* gmpy2_pow.c *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Python interface to the GMP, MPFR, and MPC multiple precision *
* libraries. *
* *
* Copyright 2000 - 2009 Alex Martelli *
* *
* Copyright 2008 - 2024 Case Van Horsen *
* *
* This file is part of GMPY2. *
* *
* GMPY2 is free software: you can redistribute it and/or modify it under *
* the terms of the GNU Lesser General Public License as published by the *
* Free Software Foundation, either version 3 of the License, or (at your *
* option) any later version. *
* *
* GMPY2 is distributed in the hope that it will be useful, but WITHOUT *
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or *
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public *
* License for more details. *
* *
* You should have received a copy of the GNU Lesser General Public *
* License along with GMPY2; if not, see *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
#include "pythoncapi_compat.h"
/* This file implements the ** operator, Python's pow() function,
* gmpy2.powmod(), and context.pow().
*/
/* Pympz_Pow_Integer is called by GMPy_Number_Pow() after verifying that the
* first two arguments are integers, but not necessarily mpz. The third
* argument must either be an integer or Py_None. The context argument is not
* currently used but may be used in the future.
*/
/* TODO: refactor to improve performance.
* - dont't convert the exponent to an MPZ if there is no modulus
*/
static PyObject *
GMPy_Integer_PowWithType(PyObject *b, int btype, PyObject *e, int etype,
PyObject *m, CTXT_Object *context)
{
MPZ_Object *result = NULL, *tempb = NULL, *tempe = NULL, *tempm = NULL;
int has_mod, mtype;
CHECK_CONTEXT(context);
/* Try to parse the modulus value first. */
if (Py_IsNone(m)) {
has_mod = 0;
}
else {
has_mod = 1;
mtype = GMPy_ObjectType(m);
if (!IS_TYPE_INTEGER(mtype)) {
TYPE_ERROR("pow() modulus must be an integer");
return NULL;
}
else {
if (!(tempm = GMPy_MPZ_From_IntegerWithType(m, mtype, context))) {
goto err;
}
}
}
if (!(result = GMPy_MPZ_New(context)) ||
!(tempb = GMPy_MPZ_From_IntegerWithType(b, btype, context)) ||
!(tempe = GMPy_MPZ_From_IntegerWithType(e, etype, context))) {
goto err;
}
if (!has_mod) {
/* When no modulo is present, the exponent must fit in unsigned long.
*/
unsigned long el;
if (mpz_sgn(tempe->z) < 0) {
Py_DECREF((PyObject*)result);
Py_DECREF((PyObject*)tempb);
Py_DECREF((PyObject*)tempe);
/* This should return an mpfr result. */
return GMPy_Real_PowWithType(b, btype, e, etype, m, context);
}
/* Catch -1, 0, 1 getting raised to large exponents. */
if (mpz_cmp_si(tempb->z, 0) == 0) {
if (mpz_cmp_si(tempe->z, 0) == 0) {
mpz_set_ui(result->z, 1);
}
else {
mpz_set_ui(result->z, 0);
}
goto done;
}
if (mpz_cmp_si(tempb->z, 1) == 0) {
mpz_set_ui(result->z, 1);
goto done;
}
if (mpz_cmp_si(tempb->z, -1) == 0) {
if (mpz_even_p(tempe->z)) {
mpz_set_ui(result->z, 1);
}
else {
mpz_set_si(result->z, -1);
}
goto done;
}
if (!mpz_fits_ulong_p(tempe->z)) {
VALUE_ERROR("pow() outrageous exponent");
goto err;
}
el = (unsigned long) mpz_get_ui(tempe->z);
mpz_pow_ui(result->z, tempb->z, el);
goto done;
}
else {
/* Modulo is present. */
int sign, has_inverse;
mpz_t mm, base, exp;
sign = mpz_sgn(tempm->z);
if (sign == 0) {
VALUE_ERROR("pow() 3rd argument cannot be 0");
goto err;
}
mpz_init(mm);
mpz_abs(mm, tempm->z);
/* A negative exponent is allowed if inverse exists. */
if (mpz_sgn(tempe->z) < 0) {
mpz_init(base);
mpz_init(exp);
has_inverse = mpz_invert(base, tempb->z, mm);
if (has_inverse) {
mpz_abs(exp, tempe->z);
mpz_powm(result->z, base, exp, mm);
}
mpz_clear(base);
mpz_clear(exp);
mpz_clear(mm);
/* Python uses a rather peculiar convention for negative modulos
* If the modulo is negative, result should be in the interval
* m < r <= 0 .
*/
if ((sign < 0) && (mpz_sgn(result->z) > 0)) {
mpz_add(result->z, result->z, tempm->z);
}
if (!has_inverse) {
VALUE_ERROR("pow() base not invertible");
goto err;
}
}
else {
GMPY_MAYBE_BEGIN_ALLOW_THREADS(context);
mpz_powm(result->z, tempb->z, tempe->z, mm);
mpz_clear(mm);
/* Python uses a rather peculiar convention for negative modulos
* If the modulo is negative, result should be in the interval
* m < r <= 0 .
*/
if ((sign < 0) && (mpz_sgn(result->z) > 0))
mpz_add(result->z, result->z, tempm->z);
GMPY_MAYBE_END_ALLOW_THREADS(context);
}
}
done:
Py_XDECREF((PyObject*)tempb);
Py_XDECREF((PyObject*)tempe);
Py_XDECREF((PyObject*)tempm);
return (PyObject*)result;
err:
Py_XDECREF((PyObject*)tempb);
Py_XDECREF((PyObject*)tempe);
Py_XDECREF((PyObject*)tempm);
Py_DECREF((PyObject*)result);
return NULL;
}
static PyObject *
GMPy_Integer_PowModBaseListWithType(PyObject *base_lst,
PyObject *e, int etype,
PyObject *m, int mtype)
{
MPZ_Object *tempe = NULL, *tempm = NULL, *tempres = NULL;
PyObject *result = NULL, *temp = NULL;
Py_ssize_t i, seq_length;
if (!(tempm = GMPy_MPZ_From_IntegerWithType(m, mtype, NULL)) ||
!(tempe = GMPy_MPZ_From_IntegerWithType(e, etype, NULL))) {
return NULL;
}
if (mpz_sgn(tempm->z) < 1) {
VALUE_ERROR("powmod_base_list() 'mod' must be > 0");
Py_DECREF((PyObject*)tempm);
Py_DECREF((PyObject*)tempe);
return NULL;
}
/* Convert base_lst to a true list. */
if (!(base_lst = PySequence_Fast(base_lst, "argument must be an iterable"))) {
return NULL;
}
/* Try to convert all items of base_lst to an mpz.
*
* Note: MUST USE GMPy_MPZ_From_IntegerAndCopy()
* since the value is changed in-place.
*/
seq_length = PySequence_Fast_GET_SIZE(base_lst);
if (!(result = PyList_New(seq_length))) {
Py_DECREF((PyObject*)tempe);
Py_DECREF((PyObject*)tempm);
Py_DECREF((PyObject*)base_lst);
return NULL;
}
for (i=0; i < seq_length; i++) {
if (!(tempres = GMPy_MPZ_From_IntegerAndCopy(PySequence_Fast_GET_ITEM(base_lst, i), NULL))) {
Py_DECREF((PyObject*)tempe);
Py_DECREF((PyObject*)tempm);
Py_DECREF(base_lst);
Py_DECREF(result);
TYPE_ERROR("all items in iterable must be integers");
return NULL;
}
if (PyList_SetItem(result, i, (PyObject*)tempres) < 0) {
Py_DECREF((PyObject*)tempe);
Py_DECREF((PyObject*)tempm);
Py_DECREF(base_lst);
Py_DECREF(result);
return NULL;
}
}
Py_BEGIN_ALLOW_THREADS;
for (i=0; i < seq_length; i++) {
temp = PySequence_Fast_GET_ITEM(result, i);
mpz_powm(MPZ(temp), MPZ(temp), tempe->z, tempm->z);
}
Py_END_ALLOW_THREADS;
Py_DECREF((PyObject*)tempe);
Py_DECREF((PyObject*)tempm);
Py_DECREF((PyObject*)base_lst);
return (PyObject*)result;
}
PyDoc_STRVAR(GMPy_doc_integer_powmod_base_list,
"powmod_base_list(base_lst, exp, mod, /) -> list[mpz, ...]\n\n"
"Returns list(powmod(i, exp, mod) for i in base_lst). Will always release\n"
"the GIL. (Experimental in gmpy2 2.1.x).");
static PyObject *
GMPy_Integer_PowMod_Base_List(PyObject *self, PyObject *args)
{
if (PyTuple_GET_SIZE(args) != 3) {
TYPE_ERROR("powmod_base_list requires 3 arguments");
return NULL;
}
if (!PySequence_Check(PyTuple_GET_ITEM(args, 0))) {
TYPE_ERROR("the first argument to powmod_base_list must be a sequence");
return NULL;
}
int etype = GMPy_ObjectType(PyTuple_GET_ITEM(args, 1));
int mtype = GMPy_ObjectType(PyTuple_GET_ITEM(args, 2));
if (IS_TYPE_INTEGER(etype) && IS_TYPE_INTEGER(mtype))
return GMPy_Integer_PowModBaseListWithType(PyTuple_GET_ITEM(args, 0),
PyTuple_GET_ITEM(args, 1), etype,
PyTuple_GET_ITEM(args, 2), mtype);
TYPE_ERROR("powmod_base_list() requires integer arguments");
return NULL;
}
static PyObject *
GMPy_Integer_PowModExpListWithType(PyObject *b, int btype,
PyObject *exp_lst,
PyObject *m, int mtype)
{
MPZ_Object *tempb = NULL, *tempm = NULL, *tempres = NULL;
PyObject *result = NULL, *temp = NULL;
Py_ssize_t i, seq_length;
if (!(tempm = GMPy_MPZ_From_IntegerWithType(m, mtype, NULL)) ||
!(tempb = GMPy_MPZ_From_IntegerWithType(b, btype, NULL))) {
return NULL;
}
if (mpz_sgn(tempm->z) < 1) {
VALUE_ERROR("powmod_exp_list() 'mod' must be > 0");
Py_DECREF((PyObject*)tempm);
Py_DECREF((PyObject*)tempb);
return NULL;
}
/* Convert exp_lst to a true list. */
if (!(exp_lst = PySequence_Fast(exp_lst, "argument must be an iterable"))) {
return NULL;
}
/* Try to convert all items of exp_lst to an mpz.
*
* Note: MUST USE GMPy_MPZ_From_IntegerAndCopy()
* since the value it changes in-place.
*/
seq_length = PySequence_Fast_GET_SIZE(exp_lst);
if (!(result = PyList_New(seq_length))) {
Py_DECREF((PyObject*)tempb);
Py_DECREF((PyObject*)tempm);
Py_DECREF((PyObject*)exp_lst);
return NULL;
}
for (i=0; i < seq_length; i++) {
if (!(tempres = GMPy_MPZ_From_IntegerAndCopy(PySequence_Fast_GET_ITEM(exp_lst, i), NULL))) {
Py_DECREF((PyObject*)tempb);
Py_DECREF((PyObject*)tempm);
Py_DECREF(exp_lst);
Py_DECREF(result);
TYPE_ERROR("all items in iterable must be integers");
return NULL;
}
if (PyList_SetItem(result, i, (PyObject*)tempres) < 0) {
Py_DECREF((PyObject*)tempb);
Py_DECREF((PyObject*)tempm);
Py_DECREF(exp_lst);
Py_DECREF(result);
return NULL;
}
}
Py_BEGIN_ALLOW_THREADS;
for (i=0; i < seq_length; i++) {
temp = PySequence_Fast_GET_ITEM(result, i);
mpz_powm(MPZ(temp), tempb->z, MPZ(temp), tempm->z);
}
Py_END_ALLOW_THREADS;
Py_DECREF((PyObject*)tempb);
Py_DECREF((PyObject*)tempm);
Py_DECREF((PyObject*)exp_lst);
return (PyObject*)result;
}
PyDoc_STRVAR(GMPy_doc_integer_powmod_exp_list,
"powmod_exp_list(base, exp_lst, mod, /) -> list[mpz, ...]\n\n"
"Returns list(powmod(base, i, mod) for i in exp_lst). Will always release\n"
"the GIL. (Experimental in gmpy2 2.1.x).");
static PyObject *
GMPy_Integer_PowMod_Exp_List(PyObject *self, PyObject *args)
{
if (PyTuple_GET_SIZE(args) != 3) {
TYPE_ERROR("powmod_exp_list requires 3 arguments");
return NULL;
}
if (!PySequence_Check(PyTuple_GET_ITEM(args, 1))) {
TYPE_ERROR("the second argument to powmod_exp_list must be a sequence");
return NULL;
}
int btype = GMPy_ObjectType(PyTuple_GET_ITEM(args, 0));
int mtype = GMPy_ObjectType(PyTuple_GET_ITEM(args, 2));
if (IS_TYPE_INTEGER(btype) && IS_TYPE_INTEGER(mtype))
return GMPy_Integer_PowModExpListWithType(PyTuple_GET_ITEM(args, 0), btype,
PyTuple_GET_ITEM(args, 1),
PyTuple_GET_ITEM(args, 2), mtype);
TYPE_ERROR("powmod_exp_list() requires integer arguments");
return NULL;
}
static PyObject *
GMPy_Rational_PowWithType(PyObject *base, int btype, PyObject *exp, int etype,
PyObject *mod, CTXT_Object *context)
{
MPQ_Object *tempbq = NULL, *resultq = NULL;
MPZ_Object *tempez = NULL;
int bsign;
long tempexp;
if (!Py_IsNone(mod)) {
TYPE_ERROR("pow() 3rd argument not allowed unless all arguments are integers");
return NULL;
}
/* Only support mpq**int. Everything else gets converted to mpf. */
if (IS_TYPE_RATIONAL(btype) && IS_TYPE_INTEGER(etype)) {
if (!(resultq = GMPy_MPQ_New(context)) ||
!(tempbq = GMPy_MPQ_From_RationalWithType(base, btype, context)) ||
!(tempez = GMPy_MPZ_From_IntegerWithType(exp, etype, context))) {
Py_XDECREF((PyObject*)resultq);
Py_XDECREF((PyObject*)tempbq);
Py_XDECREF((PyObject*)tempez);
return NULL;
}
if (!mpz_fits_slong_p(tempez->z)) {
VALUE_ERROR("mpq.pow() outrageous exponent");
Py_DECREF((PyObject*)resultq);
Py_DECREF((PyObject*)tempbq);
Py_DECREF((PyObject*)tempez);
return NULL;
}
tempexp = (long) mpz_get_si(tempez->z);
if (tempexp == 0) {
mpq_set_si(resultq->q, 1, 1);
Py_DECREF((PyObject*)tempbq);
Py_DECREF((PyObject*)tempez);
return (PyObject*)resultq;
}
bsign = mpq_sgn(tempbq->q);
if (tempexp < 0) {
if (bsign == 0) {
ZERO_ERROR("pow() 0 base to negative exponent");
Py_DECREF((PyObject*)resultq);
Py_DECREF((PyObject*)tempbq);
Py_DECREF((PyObject*)tempez);
return NULL;
}
if (bsign < 0) {
mpz_neg(mpq_numref(resultq->q), mpq_denref(tempbq->q));
}
else {
mpz_set(mpq_numref(resultq->q), mpq_denref(tempbq->q));
}
mpz_abs(mpq_denref(resultq->q), mpq_numref(tempbq->q));
tempexp = -tempexp;
}
else {
mpq_set(resultq->q, tempbq->q);
}
if (tempexp > 1) {
mpz_pow_ui(mpq_numref(resultq->q), mpq_numref(resultq->q), tempexp);
mpz_pow_ui(mpq_denref(resultq->q), mpq_denref(resultq->q), tempexp);
}
Py_DECREF((PyObject*)tempbq);
Py_DECREF((PyObject*)tempez);
return (PyObject*)resultq;
}
else {
return GMPy_Real_PowWithType(base, btype, exp, etype, Py_None, context);
}
}
static PyObject *
GMPy_Real_PowWithType(PyObject *base, int btype, PyObject *exp, int etype,
PyObject *mod, CTXT_Object *context)
{
MPFR_Object *tempb = NULL, *tempe = NULL, *result = NULL;
MPZ_Object *tempz = NULL;
MPC_Object *mpc_result = NULL;
if (!Py_IsNone(mod)) {
TYPE_ERROR("pow() 3rd argument not allowed unless all arguments are integers");
return NULL;
}
CHECK_CONTEXT(context);
if (!(result = GMPy_MPFR_New(0, context)) ||
!(tempb = GMPy_MPFR_From_RealWithType(base, btype, 1, context))) {
goto err;
}
mpfr_clear_flags();
if (IS_TYPE_PyInteger(etype)) {
int error;
unsigned long intb;
long temp;
if (mpfr_fits_ulong_p(tempb->f, MPFR_RNDF)) {
/* Need to check the inexact flag to verify that tempb is an integer. */
intb = mpfr_get_ui(tempb->f, MPFR_RNDF);
if (mpfr_inexflag_p()) {
mpfr_clear_inexflag();
}
else {
temp = PyLong_AsLongAndOverflow(exp, &error);
if (!error) {
if (temp >= 0) {
result->rc = mpfr_ui_pow_ui(result->f, intb, temp, GET_MPFR_ROUND(context));
goto done;
}
}
}
}
}
if (IS_TYPE_INTEGER(etype)) {
if (!(tempz = GMPy_MPZ_From_IntegerWithType(exp, etype, context))) {
goto err;
}
result->rc = mpfr_pow_z(result->f, tempb->f, tempz->z, GET_MPFR_ROUND(context));
goto done;
}
else if (IS_TYPE_REAL(etype)) {
if (!(tempe = GMPy_MPFR_From_RealWithType(exp, etype, 1, context))) {
goto err;
}
result->rc = mpfr_pow(result->f, tempb->f, tempe->f, GET_MPFR_ROUND(context));
goto done;
}
/* If the result is NaN, check if a complex result works. */
if (mpfr_nanflag_p() && context->ctx.allow_complex) {
mpc_result = (MPC_Object*)GMPy_Complex_PowWithType(base, btype, exp, etype, Py_None, context);
if (!mpc_result || MPC_IS_NAN_P(mpc_result)) {
Py_XDECREF((PyObject*)mpc_result);
context->ctx.invalid = 1;
GMPY_INVALID("pow() invalid operation");
goto err;
}
/* return a valid complex result */
Py_XDECREF((PyObject*)tempe);
Py_XDECREF((PyObject*)tempz);
Py_XDECREF((PyObject*)tempb);
Py_XDECREF((PyObject*)result);
return (PyObject*)mpc_result;
}
done:
_GMPy_MPFR_Cleanup(&result, context);
Py_XDECREF((PyObject*)tempz);
Py_XDECREF((PyObject*)tempe);
Py_XDECREF((PyObject*)tempb);
return (PyObject*)result;
err:
Py_XDECREF((PyObject*)result);
Py_XDECREF((PyObject*)tempz);
Py_XDECREF((PyObject*)tempe);
Py_XDECREF((PyObject*)tempb);
return NULL;
}
static PyObject *
GMPy_Complex_PowWithType(PyObject *base, int btype, PyObject *exp, int etype,
PyObject *mod, CTXT_Object *context)
{
MPC_Object *tempb = NULL, *tempe = NULL, *result= NULL;
MPFR_Object *tempf = NULL;
MPZ_Object *tempz = NULL;
if (!Py_IsNone(mod)) {
TYPE_ERROR("pow() 3rd argument not allowed unless all arguments are integers");
return NULL;
}
CHECK_CONTEXT(context);
if (!(result = GMPy_MPC_New(0, 0, context)) ||
!(tempb = GMPy_MPC_From_ComplexWithType(base, btype, 1, 1, context))) {
goto err;
}
mpfr_clear_flags();
if (IS_TYPE_INTEGER(etype)) {
if (!(tempz = GMPy_MPZ_From_IntegerWithType(exp, etype, context))) {
goto err;
}
result->rc = mpc_pow_z(result->c, tempb->c, tempz->z, GET_MPC_ROUND(context));
goto done;
}
if (IS_TYPE_REAL(etype)) {
if (!(tempf = GMPy_MPFR_From_RealWithType(exp, etype, 1, context))) {
goto err;
}
result->rc = mpc_pow_fr(result->c, tempb->c, tempf->f, GET_MPC_ROUND(context));
goto done;
}
if (IS_TYPE_COMPLEX(etype)) {
if (!(tempe = GMPy_MPC_From_ComplexWithType(exp, etype, 1, 1, context))) {
goto err;
}
result->rc = mpc_pow(result->c, tempb->c, tempe->c, GET_MPC_ROUND(context));
goto done;
}
TYPE_ERROR("pow() argument types not supported");
goto err;
done:
_GMPy_MPC_Cleanup(&result, context);
Py_XDECREF((PyObject*)tempz);
Py_XDECREF((PyObject*)tempf);
Py_XDECREF((PyObject*)tempe);
Py_XDECREF((PyObject*)tempb);
return (PyObject*)result;
err:
Py_XDECREF((PyObject*)result);
Py_XDECREF((PyObject*)tempz);
Py_XDECREF((PyObject*)tempf);
Py_XDECREF((PyObject*)tempe);
Py_XDECREF((PyObject*)tempb);
return NULL;
}
PyDoc_STRVAR(GMPy_doc_integer_powmod,
"powmod(x, y, m, /) -> mpz\n\n"
"Return (x**y) mod m. Same as the three argument version of Python's\n"
"built-in `pow`, but converts all three arguments to `mpz`.");
static PyObject *
GMPy_Integer_PowMod(PyObject *self, PyObject *args)
{
PyObject *x, *y, *m;
int xtype, ytype, mtype;
if (PyTuple_GET_SIZE(args) != 3) {
TYPE_ERROR("powmod() requires 3 arguments.");
return NULL;
}
x = PyTuple_GET_ITEM(args, 0);
y = PyTuple_GET_ITEM(args, 1);
m = PyTuple_GET_ITEM(args, 2);
xtype = GMPy_ObjectType(x);
ytype = GMPy_ObjectType(y);
mtype = GMPy_ObjectType(m);
if (IS_TYPE_INTEGER(xtype) &&
IS_TYPE_INTEGER(ytype) &&
IS_TYPE_INTEGER(mtype)) {
return GMPy_Integer_PowWithType(x, xtype, y, ytype, m, NULL);
}
TYPE_ERROR("powmod() argument types not supported");
return NULL;
}
PyDoc_STRVAR(GMPy_doc_integer_powmod_sec,
"powmod_sec(x, y, m, /) -> mpz\n\n"
"Return (x**y) mod m. Calculates x ** y (mod m) but using a constant\n"
"time algorithm to reduce the risk of side channel attacks. y must be\n"
"an integer >0. m must be an odd integer.");
static PyObject *
GMPy_Integer_PowMod_Sec(PyObject *self, PyObject *args)
{
PyObject *x, *y, *m;
int xtype, ytype, mtype;
MPZ_Object *tempx = NULL, *tempy = NULL, *tempm = NULL, *result = NULL;
CTXT_Object *context = NULL;
CHECK_CONTEXT(context);
if (PyTuple_GET_SIZE(args) != 3) {
TYPE_ERROR("powmod_sec() requires 3 arguments.");
goto err;
}
if (!(result = GMPy_MPZ_New(NULL))) {
/* LCOV_EXCL_START */
goto err;
/* LCOV_EXCL_STOP */
}
x = PyTuple_GET_ITEM(args, 0);
y = PyTuple_GET_ITEM(args, 1);
m = PyTuple_GET_ITEM(args, 2);
xtype = GMPy_ObjectType(x);
ytype = GMPy_ObjectType(y);
mtype = GMPy_ObjectType(m);
/* Validate base. */
if (!IS_TYPE_INTEGER(xtype)) {
TYPE_ERROR("powmod_sec() base must be an integer.");
goto err;
}
if (!(tempx = GMPy_MPZ_From_IntegerWithType(x, xtype, NULL))) {
/* LCOV_EXCL_START */
goto err;
/* LCOV_EXCL_STOP */
}
/* Validate exponent. It must be > 0. */
if (!IS_TYPE_INTEGER(ytype)) {
TYPE_ERROR("powmod_sec() exponent must be an integer.");
goto err;
}
if (!(tempy = GMPy_MPZ_From_IntegerWithType(y, ytype, NULL))) {
/* LCOV_EXCL_START */
goto err;
/* LCOV_EXCL_STOP */
}
if (!(mpz_sgn(tempy->z) == 1)) {
VALUE_ERROR("powmod_sec() exponent must be > 0.");
goto err;
}
/* Validate modulus. It must be odd.*/
if (!IS_TYPE_INTEGER(mtype)) {
TYPE_ERROR("powmod_sec() modulus must be an integer.");
goto err;
}
if (!(tempm = GMPy_MPZ_From_IntegerWithType(m, mtype, NULL))) {
/* LCOV_EXCL_START */
goto err;
/* LCOV_EXCL_STOP */
}
if (mpz_even_p(tempm->z)) {
VALUE_ERROR("powmod_sec() modulus must be odd.");
goto err;
}
GMPY_MAYBE_BEGIN_ALLOW_THREADS(context);
mpz_powm_sec(result->z, tempx->z, tempy->z, tempm->z);
GMPY_MAYBE_END_ALLOW_THREADS(context);
Py_DECREF(tempx);
Py_DECREF(tempy);
Py_DECREF(tempm);
return (PyObject*)result;
err:
Py_XDECREF(tempx);
Py_XDECREF(tempy);
Py_XDECREF(tempm);
return NULL;
}
static PyObject *
GMPy_Number_Pow(PyObject *x, PyObject *y, PyObject *z, CTXT_Object *context)
{
int xtype = GMPy_ObjectType(x);
int ytype = GMPy_ObjectType(y);
if (IS_TYPE_INTEGER(xtype) && IS_TYPE_INTEGER(ytype))
return GMPy_Integer_PowWithType(x, xtype, y, ytype, z, context);
if (IS_TYPE_RATIONAL(xtype) && IS_TYPE_RATIONAL(ytype))
return GMPy_Rational_PowWithType(x, xtype, y, ytype, z, context);
if (IS_TYPE_REAL(xtype) && IS_TYPE_REAL(ytype))
return GMPy_Real_PowWithType(x, xtype, y, ytype, z, context);
if (IS_TYPE_COMPLEX(xtype) && IS_TYPE_COMPLEX(ytype))
return GMPy_Complex_PowWithType(x, xtype, y, ytype, z, context);
TYPE_ERROR("pow() argument type not supported");
return NULL;
}
PyDoc_STRVAR(GMPy_doc_context_pow,
"context.pow(x, y, /) -> mpz | mpq | mpfr | mpc\n\n"
"Return x ** y.");
static PyObject *
GMPy_Context_Pow(PyObject *self, PyObject *args)
{
CTXT_Object *context = NULL;
if (PyTuple_GET_SIZE(args) != 2) {
TYPE_ERROR("pow() requires 2 arguments.");
return NULL;
}
if (self && CTXT_Check(self)) {
context = (CTXT_Object*)self;
}
else {
CHECK_CONTEXT(context);
}
return GMPy_Number_Pow(PyTuple_GET_ITEM(args, 0),
PyTuple_GET_ITEM(args, 1),
Py_None, context);
}
static PyObject *
GMPy_Number_Pow_Slot(PyObject *base, PyObject *exp, PyObject *mod)
{
int btype = GMPy_ObjectType(base);
int etype = GMPy_ObjectType(exp);
if (IS_TYPE_INTEGER(btype) && IS_TYPE_INTEGER(etype))
return GMPy_Integer_PowWithType(base, btype, exp, etype, mod, NULL);
if (IS_TYPE_RATIONAL(btype) && IS_TYPE_RATIONAL(etype))
return GMPy_Rational_PowWithType(base, btype, exp, etype, mod, NULL);
if (IS_TYPE_REAL(btype) && IS_TYPE_REAL(etype))
return GMPy_Real_PowWithType(base, btype, exp, etype, mod, NULL);
if (IS_TYPE_COMPLEX(btype) && IS_TYPE_COMPLEX(etype))
return GMPy_Complex_PowWithType(base, btype, exp, etype, mod, NULL);
Py_RETURN_NOTIMPLEMENTED;
}
././@PaxHeader 0000000 0000000 0000000 00000000026 00000000000 010213 x ustar 00 22 mtime=1710307256.0
gmpy2-2.2.1/src/gmpy2_pow.h 0000644 0001750 0001750 00000005663 14574233670 014132 0 ustar 00case case /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* gmpy2_pow.h *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Python interface to the GMP, MPFR, and MPC multiple precision *
* libraries. *
* *
* Copyright 2000 - 2009 Alex Martelli *
* *
* Copyright 2008 - 2024 Case Van Horsen *
* *
* This file is part of GMPY2. *
* *
* GMPY2 is free software: you can redistribute it and/or modify it under *
* the terms of the GNU Lesser General Public License as published by the *
* Free Software Foundation, either version 3 of the License, or (at your *
* option) any later version. *
* *
* GMPY2 is distributed in the hope that it will be useful, but WITHOUT *
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or *
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public *
* License for more details. *
* *
* You should have received a copy of the GNU Lesser General Public *
* License along with GMPY2; if not, see *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
#ifndef GMPY2_POW_H
#define GMPY2_POW_H
#ifdef __cplusplus
extern "C" {
#endif
/* Private API */
static PyObject * GMPy_Number_Pow_Slot(PyObject *base, PyObject *exp, PyObject *mod);
static PyObject * GMPy_Integer_PowWithType(PyObject *base, int btype, PyObject *exp, int etype, PyObject *mod, CTXT_Object *context);
static PyObject * GMPy_Rational_PowWithType(PyObject *base, int btype, PyObject *exp, int etype, PyObject *mod, CTXT_Object *context);
static PyObject * GMPy_Real_PowWithType(PyObject *base, int btype, PyObject *exp, int etype, PyObject *mod, CTXT_Object *context);
static PyObject * GMPy_Complex_PowWithType(PyObject *base, int btype, PyObject *exp, int etype, PyObject *mod, CTXT_Object *context);
static PyObject * GMPy_Integer_PowMod(PyObject *self, PyObject *args);
static PyObject * GMPy_Integer_PowMod_Sec(PyObject *self, PyObject *args);
static PyObject * GMPy_Context_Pow(PyObject *self, PyObject *args);
static PyObject * GMPy_Number_Pow(PyObject *x, PyObject *y, PyObject *z, CTXT_Object *context);
#ifdef __cplusplus
}
#endif
#endif
././@PaxHeader 0000000 0000000 0000000 00000000026 00000000000 010213 x ustar 00 22 mtime=1710307256.0
gmpy2-2.2.1/src/gmpy2_predicate.c 0000644 0001750 0001750 00000032351 14574233670 015252 0 ustar 00case case /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* gmpy2_predicate.c *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Python interface to the GMP, MPFR, and MPC multiple precision *
* libraries. *
* *
* Copyright 2000 - 2009 Alex Martelli *
* *
* Copyright 2008 - 2024 Case Van Horsen *
* *
* This file is part of GMPY2. *
* *
* GMPY2 is free software: you can redistribute it and/or modify it under *
* the terms of the GNU Lesser General Public License as published by the *
* Free Software Foundation, either version 3 of the License, or (at your *
* option) any later version. *
* *
* GMPY2 is distributed in the hope that it will be useful, but WITHOUT *
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or *
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public *
* License for more details. *
* *
* You should have received a copy of the GNU Lesser General Public *
* License along with GMPY2; if not, see *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
/* To work with the MPC_IS_ macros, NAN, INF, FINITE, and ZERO are
* all upper-case.
*/
PyDoc_STRVAR(GMPy_doc_function_is_nan,
"is_nan(x, /) -> bool\n\n"
"Return `True` if x is NaN (Not-A-Number) else `False`.");
PyDoc_STRVAR(GMPy_doc_context_is_nan,
"context.is_nan(x, /) -> bool\n\n"
"Return `True` if x is NaN (Not-A-Number) else `False`.");
PyDoc_STRVAR(GMPy_doc_method_is_nan,
"x.is_nan() -> bool\n\n"
"Return `True` if x is NaN (Not-A-Number) else `False`.");
static PyObject *
GMPy_RealWithType_Is_NAN(PyObject *x, int xtype, CTXT_Object *context)
{
MPFR_Object *tempx = NULL;
int res = 0;
if (IS_TYPE_MPFR(xtype)) {
res = mpfr_nan_p(MPFR(x));
}
else {
if (!(tempx = GMPy_MPFR_From_RealWithType(x, xtype, 1, context)))
return NULL;
res = mpfr_nan_p(tempx->f);
Py_DECREF((PyObject*)tempx);
}
if (res)
Py_RETURN_TRUE;
else
Py_RETURN_FALSE;
}
static PyObject *
GMPy_ComplexWithType_Is_NAN(PyObject *x, int xtype, CTXT_Object *context)
{
MPC_Object *tempx = NULL;
int res = 0;
if (IS_TYPE_MPC(xtype)) {
res = MPC_IS_NAN_P(x);
}
else {
if (!(tempx = GMPy_MPC_From_ComplexWithType(x, xtype, 1, 1, context)))
return NULL;
res = MPC_IS_NAN_P(tempx);
Py_DECREF(tempx);
}
if (res)
Py_RETURN_TRUE;
else
Py_RETURN_FALSE;
}
/* This creates the following functions:
* GMPy_Number_Is_NAN(x, context)
* GMPy_Context_Is_NAN(self, other)
* GMPy_Number_Method_Is_NAN(self, args)
*
* They assume the following functions have been defined above:
* GMPy_RealWithType_Is_NAN(x, xtype, context)
* GMPy_ComplexWithType_Is_NAN(x, xtype, context)
*/
GMPY_MPFR_MPC_UNIOP_TEMPLATEWT(Is_NAN, is_nan);
PyDoc_STRVAR(GMPy_doc_function_is_infinite,
"is_infinite(x, /) -> bool\n\n"
"Return `True` if x is +Infinity or -Infinity. If x is an `mpc`, return `True`\n"
"if either x.real or x.imag is infinite. Otherwise return `False`.");
PyDoc_STRVAR(GMPy_doc_context_is_infinite,
"context.is_infinite(x, /) -> bool\n\n"
"Return `True` if x is +Infinity or -Infinity. If x is an `mpc`, return `True`\n"
"if either x.real or x.imag is infinite. Otherwise return `False`.");
PyDoc_STRVAR(GMPy_doc_method_is_infinite,
"x.is_infinite() -> bool\n\n"
"Return `True` if x is +Infinity or -Infinity. If x is an `mpc`, return `True`\n"
"if either x.real or x.imag is infinite. Otherwise return `False`.");
static PyObject *
GMPy_RealWithType_Is_Infinite(PyObject *x, int xtype, CTXT_Object *context)
{
MPFR_Object *tempx = NULL;
int res = 0;
if (IS_TYPE_MPFR(xtype)) {
res = mpfr_inf_p(MPFR(x));
}
else {
if (!(tempx = GMPy_MPFR_From_RealWithType(x, xtype, 1, context)))
return NULL;
res = mpfr_inf_p(tempx->f);
Py_DECREF(tempx);
}
if (res)
Py_RETURN_TRUE;
else
Py_RETURN_FALSE;
}
static PyObject *
GMPy_ComplexWithType_Is_Infinite(PyObject *x, int xtype, CTXT_Object *context)
{
MPC_Object *tempx = NULL;
int res = 0;
if (IS_TYPE_MPC(xtype)) {
res = MPC_IS_INF_P(x);
}
else {
if (!(tempx = GMPy_MPC_From_ComplexWithType(x, xtype, 1, 1, context)))
return NULL;
res = MPC_IS_INF_P(tempx);
Py_DECREF(tempx);
}
if (res)
Py_RETURN_TRUE;
else
Py_RETURN_FALSE;
}
GMPY_MPFR_MPC_UNIOP_TEMPLATEWT(Is_Infinite, is_infinite);
PyDoc_STRVAR(GMPy_doc_function_is_finite,
"is_finite(x, /) -> bool\n\n"
"Return `True` if x is an actual number (i.e. non NaN or Infinity). If x is\n"
"an `mpc`, return `True` if both x.real and x.imag are finite.");
PyDoc_STRVAR(GMPy_doc_context_is_finite,
"context.is_finite(x, /) -> bool\n\n"
"Return `True` if x is an actual number (i.e. non NaN or Infinity). If x is\n"
"an `mpc`, return `True` if both x.real and x.imag are finite.");
PyDoc_STRVAR(GMPy_doc_method_is_finite,
"x.is_finite() -> bool\n\n"
"Return `True` if x is an actual number (i.e. non NaN or Infinity). If x is\n"
"an `mpc`, return `True` if both x.real and x.imag are finite.");
static PyObject *
GMPy_RealWithType_Is_Finite(PyObject *x, int xtype, CTXT_Object *context)
{
MPFR_Object *tempx = NULL;
int res = 0;
if (IS_TYPE_MPFR(xtype)) {
res = mpfr_number_p(MPFR(x));
}
else {
if (!(tempx = GMPy_MPFR_From_RealWithType(x, xtype, 1, context)))
return NULL;
res = mpfr_number_p(tempx->f);
Py_DECREF(tempx);
}
if (res)
Py_RETURN_TRUE;
else
Py_RETURN_FALSE;
}
static PyObject *
GMPy_ComplexWithType_Is_Finite(PyObject *x, int xtype, CTXT_Object *context)
{
MPC_Object *tempx = NULL;
int res = 0;
if (IS_TYPE_MPC(xtype)) {
res = MPC_IS_FINITE_P(x);
}
else {
if (!(tempx = GMPy_MPC_From_ComplexWithType(x, xtype, 1, 1, context)))
return NULL;
res = MPC_IS_FINITE_P(tempx);
Py_DECREF(tempx);
}
if (res)
Py_RETURN_TRUE;
else
Py_RETURN_FALSE;
}
GMPY_MPFR_MPC_UNIOP_TEMPLATEWT(Is_Finite, is_finite);
PyDoc_STRVAR(GMPy_doc_function_is_zero,
"is_zero(x, /) -> bool\n\n"
"Return `True` if x is equal to 0. If x is an `mpc`, return `True` if both x.real\n"
"and x.imag are equal to 0.");
PyDoc_STRVAR(GMPy_doc_context_is_zero,
"context.is_zero(x, /) -> bool\n\n"
"Return `True` if x is equal to 0. If x is an `mpc`, return `True` if both x.real\n"
"and x.imag are equal to 0.");
PyDoc_STRVAR(GMPy_doc_method_is_zero,
"x.is_zero() -> bool\n\n"
"Return `True` if x is equal to 0. If x is an `mpc`, return `True` if both x.real\n"
"and x.imag are equal to 0.");
static PyObject *
GMPy_RealWithType_Is_Zero(PyObject *x, int xtype, CTXT_Object *context)
{
MPFR_Object *tempx = NULL;
int res = 0;
if (IS_TYPE_MPFR(xtype)) {
res = mpfr_zero_p(MPFR(x));
}
else {
if (!(tempx = GMPy_MPFR_From_RealWithType(x, xtype, 1, context)))
return NULL;
res = mpfr_zero_p(tempx->f);
Py_DECREF(tempx);
}
if (res)
Py_RETURN_TRUE;
else
Py_RETURN_FALSE;
}
static PyObject *
GMPy_ComplexWithType_Is_Zero(PyObject *x, int xtype, CTXT_Object *context)
{
MPC_Object *tempx = NULL;
int res = 0;
if (IS_TYPE_MPC(xtype)) {
res = MPC_IS_ZERO_P(x);
}
else {
if (!(tempx = GMPy_MPC_From_ComplexWithType(x, xtype, 1, 1, context)))
return NULL;
res = MPC_IS_ZERO_P(tempx);
Py_DECREF(tempx);
}
if (res)
Py_RETURN_TRUE;
else
Py_RETURN_FALSE;
}
GMPY_MPFR_MPC_UNIOP_TEMPLATEWT(Is_Zero, is_zero);
PyDoc_STRVAR(GMPy_doc_function_is_signed,
"is_signed(x, /) -> bool\n\n"
"Return `True` if the sign bit of x is set.");
PyDoc_STRVAR(GMPy_doc_context_is_signed,
"context.is_signed(x, /) -> bool\n\n"
"Return `True` if the sign bit of x is set.");
PyDoc_STRVAR(GMPy_doc_method_is_signed,
"x.is_signed() -> bool\n\n"
"Return `True` if the sign bit of x is set.");
static PyObject *
GMPy_RealWithType_Is_Signed(PyObject *x, int xtype, CTXT_Object *context)
{
MPFR_Object *tempx = NULL;
int res;
if (IS_TYPE_MPFR(xtype)) {
res = mpfr_signbit(MPFR(x));
}
else {
if (!(tempx = GMPy_MPFR_From_RealWithType(x, xtype, 1, context))) {
return NULL;
}
res = mpfr_signbit(tempx->f);
Py_DECREF((PyObject*)tempx);
}
if (res) {
Py_RETURN_TRUE;
}
else {
Py_RETURN_FALSE;
}
}
static PyObject *
GMPy_MPFR_Is_Signed_Method(PyObject *self, PyObject *args)
{
return GMPy_Number_Is_Signed(self, NULL);
}
GMPY_MPFR_UNIOP_TEMPLATEWT(Is_Signed, is_signed);
PyDoc_STRVAR(GMPy_doc_function_is_regular,
"is_regular(x, /) -> bool\n\n"
"Return `True` if x is not zero, NaN, or Infinity; `False` otherwise.");
PyDoc_STRVAR(GMPy_doc_context_is_regular,
"context.is_regular(x, /) -> bool\n\n"
"Return `True` if x is not zero, NaN, or Infinity; `False` otherwise.");
PyDoc_STRVAR(GMPy_doc_method_is_regular,
"x.is_regular() -> bool\n\n"
"Return `True` if x is not zero, NaN, or Infinity; `False` otherwise.");
static PyObject *
GMPy_RealWithType_Is_Regular(PyObject *x, int xtype, CTXT_Object *context)
{
MPFR_Object *tempx = NULL;
int res;
if (IS_TYPE_MPFR(xtype)) {
res = mpfr_regular_p(MPFR(x));
}
else {
if (!(tempx = GMPy_MPFR_From_RealWithType(x, xtype, 1, context))) {
return NULL;
}
res = mpfr_regular_p(tempx->f);
Py_DECREF((PyObject*)tempx);
}
if (res) {
Py_RETURN_TRUE;
}
else {
Py_RETURN_FALSE;
}
}
static PyObject *
GMPy_MPFR_Is_Regular_Method(PyObject *self, PyObject *args)
{
return GMPy_Number_Is_Regular(self, NULL);
}
GMPY_MPFR_UNIOP_TEMPLATEWT(Is_Regular, is_regular);
PyDoc_STRVAR(GMPy_doc_function_is_integer,
"is_integer(x, /) -> bool\n\n"
"Return `True` if x is an integer; `False` otherwise.");
PyDoc_STRVAR(GMPy_doc_context_is_integer,
"context.is_integer(x, /) -> bool\n\n"
"Return `True` if x is an integer; `False` otherwise.");
PyDoc_STRVAR(GMPy_doc_method_is_integer,
"x.is_integer() -> bool\n\n"
"Return `True` if x is an integer; `False` otherwise.");
static PyObject *
GMPy_RealWithType_Is_Integer(PyObject *x, int xtype, CTXT_Object *context)
{
MPFR_Object *tempx = NULL;
int res;
if (IS_TYPE_MPFR(xtype)) {
res = mpfr_integer_p(MPFR(x));
}
else {
if (!(tempx = GMPy_MPFR_From_RealWithType(x, xtype, 1, context))) {
return NULL;
}
res = mpfr_integer_p(tempx->f);
Py_DECREF((PyObject*)tempx);
}
if (res) {
Py_RETURN_TRUE;
}
else {
Py_RETURN_FALSE;
}
}
static PyObject *
GMPy_MPFR_Is_Integer_Method(PyObject *self, PyObject *args)
{
return GMPy_Number_Is_Integer(self, NULL);
}
GMPY_MPFR_UNIOP_TEMPLATEWT(Is_Integer, is_integer);
PyDoc_STRVAR(GMPy_doc_function_is_lessgreater,
"is_lessgreater(x,y, /) -> bool\n\n"
"Return `True` if x > y or x < y. Return `False` if x == y or either x\n"
"and/or y is NaN.");
static PyObject *
GMPy_RealWithType_Is_LessGreater(PyObject *x, int xtype, PyObject *y, int ytype, CTXT_Object *context)
{
MPFR_Object *tempx = NULL, *tempy = NULL;
int res;
tempx = GMPy_MPFR_From_RealWithType(x, xtype, 1, context);
tempy = GMPy_MPFR_From_RealWithType(y, ytype, 1, context);
if (!tempx || !tempy) {
Py_XDECREF(tempx);
Py_XDECREF(tempy);
return NULL;
}
res = mpfr_lessgreater_p(tempx->f, tempy->f);
Py_DECREF((PyObject*)tempx);
Py_DECREF((PyObject*)tempy);
if (res)
Py_RETURN_TRUE;
else
Py_RETURN_FALSE;
}
GMPY_MPFR_BINOP_TEMPLATEWT(Is_LessGreater, is_lessgreater)
PyDoc_STRVAR(GMPy_doc_function_is_unordered,
"is_unordered(x,y, /) -> bool\n\n"
"Return `True` if either x and/or y is NaN.");
static PyObject *
GMPy_RealWithType_Is_Unordered(PyObject *x, int xtype, PyObject *y, int ytype, CTXT_Object *context)
{
MPFR_Object *tempx = NULL, *tempy = NULL;
int res;
tempx = GMPy_MPFR_From_RealWithType(x, xtype, 1, context);
tempy = GMPy_MPFR_From_RealWithType(y, ytype, 1, context);
if (!tempx || !tempy) {
Py_XDECREF(tempx);
Py_XDECREF(tempy);
return NULL;
}
res = mpfr_unordered_p(tempx->f, tempy->f);
Py_DECREF((PyObject*)tempx);
Py_DECREF((PyObject*)tempy);
if (res)
Py_RETURN_TRUE;
else
Py_RETURN_FALSE;
}
GMPY_MPFR_BINOP_TEMPLATEWT(Is_Unordered, is_unordered)
././@PaxHeader 0000000 0000000 0000000 00000000026 00000000000 010213 x ustar 00 22 mtime=1710307256.0
gmpy2-2.2.1/src/gmpy2_predicate.h 0000644 0001750 0001750 00000012244 14574233670 015256 0 ustar 00case case /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* gmpy2_predicate.h *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Python interface to the GMP, MPFR, and MPC multiple precision *
* libraries. *
* *
* Copyright 2000 - 2009 Alex Martelli *
* *
* Copyright 2008 - 2024 Case Van Horsen *
* *
* This file is part of GMPY2. *
* *
* GMPY2 is free software: you can redistribute it and/or modify it under *
* the terms of the GNU Lesser General Public License as published by the *
* Free Software Foundation, either version 3 of the License, or (at your *
* option) any later version. *
* *
* GMPY2 is distributed in the hope that it will be useful, but WITHOUT *
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or *
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public *
* License for more details. *
* *
* You should have received a copy of the GNU Lesser General Public *
* License along with GMPY2; if not, see *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
#ifndef GMPY_PREDICATE_H
#define GMPY_PREDICATE_H
#ifdef __cplusplus
extern "C" {
#endif
static PyObject * GMPy_RealWithType_Is_NAN(PyObject *x, int xtype, CTXT_Object *context);
static PyObject * GMPy_ComplexWithType_Is_NAN(PyObject *x, int xtype, CTXT_Object *context);
static PyObject * GMPy_Number_Method_Is_NAN(PyObject *self, PyObject *args);
static PyObject * GMPy_Number_Is_NAN(PyObject *x, CTXT_Object *context);
static PyObject * GMPy_Context_Is_NAN(PyObject *self, PyObject *other);
static PyObject * GMPy_RealWithType_Is_Infinite(PyObject *x, int xtype, CTXT_Object *context);
static PyObject * GMPy_ComplexWithType_Is_Infinite(PyObject *x, int xtype, CTXT_Object *context);
static PyObject * GMPy_Number_Method_Is_Infinite(PyObject *self, PyObject *args);
static PyObject * GMPy_Number_Is_Infinite(PyObject *x, CTXT_Object *context);
static PyObject * GMPy_Context_Is_Infinite(PyObject *self, PyObject *other);
static PyObject * GMPy_RealWithType_Is_Finite(PyObject *x, int xtype, CTXT_Object *context);
static PyObject * GMPy_ComplexWithType_Is_Finite(PyObject *x, int xtype, CTXT_Object *context);
static PyObject * GMPy_Number_Method_Is_Finite(PyObject *self, PyObject *args);
static PyObject * GMPy_Number_Is_Finite(PyObject *x, CTXT_Object *context);
static PyObject * GMPy_Context_Is_Finite(PyObject *self, PyObject *other);
static PyObject * GMPy_RealWithType_Is_Zero(PyObject *x, int xtype, CTXT_Object *context);
static PyObject * GMPy_ComplexWithType_Is_Zero(PyObject *x, int xtype, CTXT_Object *context);
static PyObject * GMPy_Number_Method_Is_Zero(PyObject *self, PyObject *args);
static PyObject * GMPy_Number_Is_Zero(PyObject *x, CTXT_Object *context);
static PyObject * GMPy_Context_Is_Zero(PyObject *self, PyObject *other);
static PyObject * GMPy_RealWithType_Is_Signed(PyObject *x, int xtype, CTXT_Object *context);
static PyObject * GMPy_MPFR_Is_Signed_Method(PyObject *self, PyObject *args);
static PyObject * GMPy_Number_Is_Signed(PyObject *x, CTXT_Object *context);
static PyObject * GMPy_Context_Is_Signed(PyObject *self, PyObject *other);
static PyObject * GMPy_RealWithType_Is_Regular(PyObject *x, int xtype, CTXT_Object *context);
static PyObject * GMPy_MPFR_Is_Regular_Method(PyObject *self, PyObject *args);
static PyObject * GMPy_Number_Is_Regular(PyObject *x, CTXT_Object *context);
static PyObject * GMPy_Context_Is_Regular(PyObject *self, PyObject *other);
static PyObject * GMPy_RealWithType_Is_Integer(PyObject *x, int xtype, CTXT_Object *context);
static PyObject * GMPy_MPFR_Is_Integer_Method(PyObject *self, PyObject *args);
static PyObject * GMPy_Number_Is_Integer(PyObject *x, CTXT_Object *context);
static PyObject * GMPy_Context_Is_Integer(PyObject *self, PyObject *other);
static PyObject * GMPy_RealWithType_Is_LessGreater(PyObject *x, int xtype, PyObject *y, int ytype, CTXT_Object *context);
static PyObject * GMPy_Number_Is_LessGreater(PyObject *x, PyObject *y, CTXT_Object *context);
static PyObject * GMPy_Context_Is_LessGreater(PyObject *self, PyObject *args);
static PyObject * GMPy_RealWithType_Is_Unordered(PyObject *x, int xtype, PyObject *y, int ytype, CTXT_Object *context);
static PyObject * GMPy_Number_Is_Unordered(PyObject *x, PyObject *y, CTXT_Object *context);
static PyObject * GMPy_Context_Is_Unordered(PyObject *self, PyObject *args);
#ifdef __cplusplus
}
#endif
#endif
././@PaxHeader 0000000 0000000 0000000 00000000026 00000000000 010213 x ustar 00 22 mtime=1711300127.0
gmpy2-2.2.1/src/gmpy2_random.c 0000644 0001750 0001750 00000027361 14600057037 014566 0 ustar 00case case /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* gmpy_random.c *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Python interface to the GMP, MPFR, and MPC multiple precision *
* libraries. *
* *
* Copyright 2000 - 2009 Alex Martelli *
* *
* Copyright 2008 - 2024 Case Van Horsen *
* *
* This file is part of GMPY2. *
* *
* GMPY2 is free software: you can redistribute it and/or modify it under *
* the terms of the GNU Lesser General Public License as published by the *
* Free Software Foundation, either version 3 of the License, or (at your *
* option) any later version. *
* *
* GMPY2 is distributed in the hope that it will be useful, but WITHOUT *
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or *
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public *
* License for more details. *
* *
* You should have received a copy of the GNU Lesser General Public *
* License along with GMPY2; if not, see *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
static RandomState_Object *
GMPy_RandomState_New(void)
{
RandomState_Object *result;
if ((result = PyObject_New(RandomState_Object, &RandomState_Type))) {
gmp_randinit_default(result->state);
}
return result;
};
static void
GMPy_RandomState_Dealloc(RandomState_Object *self)
{
gmp_randclear(self->state);
PyObject_Free(self);
};
static PyObject *
GMPy_RandomState_Repr(RandomState_Object *self)
{
return PyUnicode_FromString("");
};
PyDoc_STRVAR(GMPy_doc_random_state_factory,
"random_state(seed=0, /) -> object\n\n"
"Return new object containing state information for the random number\n"
"generator. An optional integer can be specified as the seed value.");
static PyObject *
GMPy_RandomState_Factory(PyObject *self, PyObject *args)
{
RandomState_Object *result;
MPZ_Object *temp;
if (!(result = GMPy_RandomState_New())) {
return NULL;
}
if (PyTuple_GET_SIZE(args) == 0) {
gmp_randseed_ui(result->state, 0);
}
else if (PyTuple_GET_SIZE(args) == 1) {
if (!(temp = GMPy_MPZ_From_Integer(PyTuple_GET_ITEM(args,0), NULL))) {
Py_DECREF((PyObject*)result);
TYPE_ERROR("seed must be an integer");
return NULL;
}
gmp_randseed(result->state, temp->z);
Py_DECREF((PyObject*)temp);
}
else {
Py_DECREF((PyObject*)result);
TYPE_ERROR("random_state() requires 0 or 1 integer arguments");
return NULL;
}
return (PyObject*)result;
}
PyDoc_STRVAR(GMPy_doc_mpz_urandomb_function,
"mpz_urandomb(random_state, bit_count, /) -> mpz\n\n"
"Return uniformly distributed random integer between 0 and\n"
"2**bit_count-1.");
static PyObject *
GMPy_MPZ_urandomb_Function(PyObject *self, PyObject *args)
{
MPZ_Object *result;
PyObject *temp0, *temp1;
unsigned long len;
if (PyTuple_GET_SIZE(args) != 2) {
TYPE_ERROR("mpz_urandomb() requires 2 arguments");
return NULL;
}
temp0 = PyTuple_GET_ITEM(args, 0);
temp1 = PyTuple_GET_ITEM(args, 1);
if (!RandomState_Check(temp0)) {
TYPE_ERROR("mpz_urandomb() requires 'random_state' and 'bit_count' arguments");
return NULL;
}
len = GMPy_Integer_AsUnsignedLongWithType(temp1, GMPy_ObjectType(temp1));
if (len == (unsigned long)(-1) && PyErr_Occurred()) {
TYPE_ERROR("mpz_urandomb() requires 'random_state' and 'bit_count' arguments");
return NULL;
}
if ((result = GMPy_MPZ_New(NULL))) {
mpz_urandomb(result->z, RANDOM_STATE(temp0), len);
}
return (PyObject*)result;
}
PyDoc_STRVAR(GMPy_doc_mpz_rrandomb_function,
"mpz_rrandomb(random_state, bit_count, /) -> mpz\n\n"
"Return a random integer between 0 and 2**bit_count-1 with long\n"
"sequences of zeros and one in its binary representation.");
static PyObject *
GMPy_MPZ_rrandomb_Function(PyObject *self, PyObject *args)
{
MPZ_Object *result;
PyObject *temp0, *temp1;
unsigned long len;
if (PyTuple_GET_SIZE(args) != 2) {
TYPE_ERROR("mpz_rrandomb() requires 2 arguments");
return NULL;
}
temp0 = PyTuple_GET_ITEM(args, 0);
temp1 = PyTuple_GET_ITEM(args, 1);
if (!RandomState_Check(temp0)) {
TYPE_ERROR("mpz_rrandomb() requires 'random_state' and 'bit_count' arguments");
return NULL;
}
len = GMPy_Integer_AsUnsignedLongWithType(temp1, GMPy_ObjectType(temp1));
if (len == (mp_bitcnt_t)(-1) && PyErr_Occurred()) {
TYPE_ERROR("mpz_rrandomb() requires 'random_state' and 'bit_count' arguments");
return NULL;
}
if ((result = GMPy_MPZ_New(NULL))) {
mpz_rrandomb(result->z, RANDOM_STATE(temp0), len);
}
return (PyObject*)result;
}
PyDoc_STRVAR(GMPy_doc_mpz_random_function,
"mpz_random(random_state, int, /) -> mpz\n\n"
"Return uniformly distributed random integer between 0 and n-1.");
static PyObject *
GMPy_MPZ_random_Function(PyObject *self, PyObject *args)
{
MPZ_Object *result, *temp;
PyObject *temp0, *temp1;
if (PyTuple_GET_SIZE(args) != 2) {
TYPE_ERROR("mpz_random() requires 2 arguments");
return NULL;
}
temp0 = PyTuple_GET_ITEM(args, 0);
temp1 = PyTuple_GET_ITEM(args, 1);
if (!RandomState_Check(temp0)) {
TYPE_ERROR("mpz_random() requires 'random_state' and 'int' arguments");
return NULL;
}
if (!(temp = GMPy_MPZ_From_IntegerWithType(temp1, GMPy_ObjectType(temp1), NULL))) {
TYPE_ERROR("mpz_random() requires 'random_state' and 'int' arguments");
return NULL;
}
if ((result = GMPy_MPZ_New(NULL))) {
mpz_urandomm(result->z, RANDOM_STATE(PyTuple_GET_ITEM(args, 0)), temp->z);
}
Py_DECREF((PyObject*)temp);
return (PyObject*)result;
}
PyDoc_STRVAR(GMPy_doc_mpfr_random_function,
"mpfr_random(random_state, /) -> mpfr\n\n"
"Return uniformly distributed number between [0,1].");
static PyObject *
GMPy_MPFR_random_Function(PyObject *self, PyObject *args)
{
MPFR_Object *result;
CTXT_Object *context = NULL;
CHECK_CONTEXT(context);
if (PyTuple_GET_SIZE(args) != 1) {
TYPE_ERROR("mpfr_random() requires 1 argument");
return NULL;
}
if (!RandomState_Check(PyTuple_GET_ITEM(args, 0))) {
TYPE_ERROR("mpfr_random() requires 'random_state' argument");
return NULL;
}
if ((result = GMPy_MPFR_New(0, context))) {
mpfr_urandom(result->f, RANDOM_STATE(PyTuple_GET_ITEM(args, 0)), GET_MPFR_ROUND(context));
}
return (PyObject*)result;
}
#if MPFR_VERSION_MAJOR > 3
PyDoc_STRVAR(GMPy_doc_mpfr_nrandom_function,
"mpfr_nrandom(random_state, /) -> (mpfr)\n\n"
"Return a random number with gaussian distribution.");
static PyObject *
GMPy_MPFR_nrandom_Function(PyObject *self, PyObject *args)
{
MPFR_Object *result;
CTXT_Object *context = NULL;
CHECK_CONTEXT(context);
if (PyTuple_GET_SIZE(args) != 1) {
TYPE_ERROR("mpfr_nrandom() requires 1 argument");
return NULL;
}
if (!RandomState_Check(PyTuple_GET_ITEM(args, 0))) {
TYPE_ERROR("mpfr_nrandom() requires 'random_state' argument");
return NULL;
}
if ((result = GMPy_MPFR_New(0, context))) {
mpfr_nrandom(result->f,
RANDOM_STATE(PyTuple_GET_ITEM(args, 0)),
GET_MPFR_ROUND(context));
}
return (PyObject*)result;
}
PyDoc_STRVAR(GMPy_doc_mpfr_grandom_function,
"mpfr_grandom(random_state, /) -> tuple[mpfr, mpfr]\n\n"
"Return two random numbers with gaussian distribution.");
static PyObject *
GMPy_MPFR_grandom_Function(PyObject *self, PyObject *args)
{
MPFR_Object *result1, *result2;
PyObject *result;
CTXT_Object *context = NULL;
CHECK_CONTEXT(context);
if (PyTuple_GET_SIZE(args) != 1) {
TYPE_ERROR("mpfr_grandom() requires 1 argument");
return NULL;
}
if (!RandomState_Check(PyTuple_GET_ITEM(args, 0))) {
TYPE_ERROR("mpfr_grandom() requires 'random_state' argument");
return NULL;
}
result1 = GMPy_MPFR_New(0, context);
result2 = GMPy_MPFR_New(0, context);
if (!result1 || !result2) {
Py_XDECREF((PyObject*)result1);
Py_XDECREF((PyObject*)result2);
return NULL;
}
mpfr_nrandom(result1->f,
RANDOM_STATE(PyTuple_GET_ITEM(args, 0)),
GET_MPFR_ROUND(context));
mpfr_nrandom(result2->f,
RANDOM_STATE(PyTuple_GET_ITEM(args, 0)),
GET_MPFR_ROUND(context));
result = Py_BuildValue("(NN)", (PyObject*)result1, (PyObject*)result2);
if (!result) {
Py_DECREF((PyObject*)result1);
Py_DECREF((PyObject*)result2);
}
return result;
}
#else
PyDoc_STRVAR(GMPy_doc_mpfr_grandom_function,
"mpfr_grandom(random_state, /) -> (mpfr, mpfr)\n\n"
"Return two random numbers with gaussian distribution.");
static PyObject *
GMPy_MPFR_grandom_Function(PyObject *self, PyObject *args)
{
MPFR_Object *result1, *result2;
PyObject *result;
CTXT_Object *context = NULL;
CHECK_CONTEXT(context);
if (PyTuple_GET_SIZE(args) != 1) {
TYPE_ERROR("mpfr_grandom() requires 1 argument");
return NULL;
}
if (!RandomState_Check(PyTuple_GET_ITEM(args, 0))) {
TYPE_ERROR("mpfr_grandom() requires 'random_state' argument");
return NULL;
}
result1 = GMPy_MPFR_New(0, context);
result2 = GMPy_MPFR_New(0, context);
if (!result1 || !result2) {
Py_XDECREF((PyObject*)result1);
Py_XDECREF((PyObject*)result2);
return NULL;
}
mpfr_grandom(result1->f, result2->f,
RANDOM_STATE(PyTuple_GET_ITEM(args, 0)),
GET_MPFR_ROUND(context));
result = Py_BuildValue("(NN)", (PyObject*)result1, (PyObject*)result2);
if (!result) {
Py_DECREF((PyObject*)result1);
Py_DECREF((PyObject*)result2);
}
return result;
}
#endif
PyDoc_STRVAR(GMPy_doc_mpc_random_function,
"mpc_random(random_state, /) -> mpc\n\n"
"Return uniformly distributed number in the unit square [0,1]x[0,1].");
static PyObject *
GMPy_MPC_random_Function(PyObject *self, PyObject *args)
{
MPC_Object *result;
CTXT_Object *context = NULL;
CHECK_CONTEXT(context);
if (PyTuple_GET_SIZE(args) != 1) {
TYPE_ERROR("mpfc_random() requires 1 argument");
return NULL;
}
if (!RandomState_Check(PyTuple_GET_ITEM(args, 0))) {
TYPE_ERROR("mpc_random() requires 'random_state' argument");
return NULL;
}
if ((result = GMPy_MPC_New(0, 0, context))) {
mpc_urandom(result->c, RANDOM_STATE(PyTuple_GET_ITEM(args, 0)));
}
return (PyObject*)result;
}
static PyTypeObject RandomState_Type =
{
PyVarObject_HEAD_INIT(0, 0)
.tp_name = "gmpy2.random_state",
.tp_basicsize = sizeof(RandomState_Object),
.tp_dealloc = (destructor) GMPy_RandomState_Dealloc,
.tp_repr = (reprfunc) GMPy_RandomState_Repr,
.tp_flags = Py_TPFLAGS_DEFAULT,
.tp_doc = "GMPY2 Random number generator state",
};
././@PaxHeader 0000000 0000000 0000000 00000000026 00000000000 010213 x ustar 00 22 mtime=1710307256.0
gmpy2-2.2.1/src/gmpy2_random.h 0000644 0001750 0001750 00000006321 14574233670 014575 0 ustar 00case case /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* gmpy_random.h *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Python interface to the GMP, MPFR, and MPC multiple precision *
* libraries. *
* *
* Copyright 2000 - 2009 Alex Martelli *
* *
* Copyright 2008 - 2024 Case Van Horsen *
* *
* This file is part of GMPY2. *
* *
* GMPY2 is free software: you can redistribute it and/or modify it under *
* the terms of the GNU Lesser General Public License as published by the *
* Free Software Foundation, either version 3 of the License, or (at your *
* option) any later version. *
* *
* GMPY2 is distributed in the hope that it will be useful, but WITHOUT *
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or *
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public *
* License for more details. *
* *
* You should have received a copy of the GNU Lesser General Public *
* License along with GMPY2; if not, see *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
#ifndef GMPY_RANDOM_H
#define GMPY_RANDOM_H
#ifdef __cplusplus
extern "C" {
#endif
/* gmpy_random C API extension header file.
*
* Provide support random number state.
*
* Version 2.00, December 2011 (created) casevh
*
* This file is expected to be included from gmpy.h
*/
static PyTypeObject RandomState_Type;
#define RANDOM_STATE(obj) (((RandomState_Object *)(obj))->state)
#define RandomState_Check(v) (((PyObject*)v)->ob_type == &RandomState_Type)
static RandomState_Object * GMPy_RandomState_New(void);
static void GMPy_RandomState_Dealloc(RandomState_Object *self);
static PyObject * GMPy_RandomState_Repr(RandomState_Object *self);
static PyObject * GMPy_RandomState_Factory(PyObject *self, PyObject *args);
static PyObject * GMPy_MPZ_urandomb_Function(PyObject *self, PyObject *args);
static PyObject * GMPy_MPZ_rrandomb_Function(PyObject *self, PyObject *args);
static PyObject * GMPy_MPZ_random_Function(PyObject *self, PyObject *args);
static PyObject * GMPy_MPFR_random_Function(PyObject *self, PyObject *args);
#if MPFR_VERSION_MAJOR > 3
static PyObject * GMPy_MPFR_nrandom_Function(PyObject *self, PyObject *args);
#endif
static PyObject * GMPy_MPFR_grandom_Function(PyObject *self, PyObject *args);
static PyObject * GMPy_MPC_random_Function(PyObject *self, PyObject *args);
#ifdef __cplusplus
}
#endif
#endif
././@PaxHeader 0000000 0000000 0000000 00000000026 00000000000 010213 x ustar 00 22 mtime=1718253275.0
gmpy2-2.2.1/src/gmpy2_richcompare.c 0000644 0001750 0001750 00000030113 14632473333 015575 0 ustar 00case case /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* gmpy2_richcompare.c *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Python interface to the GMP, MPFR, and MPC multiple precision *
* libraries. *
* *
* Copyright 2000 - 2009 Alex Martelli *
* *
* Copyright 2008 - 2024 Case Van Horsen *
* *
* This file is part of GMPY2. *
* *
* GMPY2 is free software: you can redistribute it and/or modify it under *
* the terms of the GNU Lesser General Public License as published by the *
* Free Software Foundation, either version 3 of the License, or (at your *
* option) any later version. *
* *
* GMPY2 is distributed in the hope that it will be useful, but WITHOUT *
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or *
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public *
* License for more details. *
* *
* You should have received a copy of the GNU Lesser General Public *
* License along with GMPY2; if not, see *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
static PyObject *_cmp_to_object(int c, int op)
{
PyObject *result;
switch (op) {
case Py_LT: c = c < 0; break;
case Py_LE: c = c <= 0; break;
case Py_EQ: c = c == 0; break;
case Py_NE: c = c != 0; break;
case Py_GT: c = c > 0; break;
case Py_GE: c = c >= 0; break;
}
result = c ? Py_True : Py_False;
Py_INCREF(result);
return result;
}
static PyObject *
GMPy_RichCompare_Slot(PyObject *a, PyObject *b, int op)
{
int atype, btype, c;
PyObject *tempa = NULL, *tempb = NULL, *result = NULL;
CTXT_Object *context = NULL;
CHECK_CONTEXT(context);
atype = GMPy_ObjectType(a);
btype = GMPy_ObjectType(b);
if (IS_TYPE_MPZANY(atype)) {
if (IS_TYPE_PyInteger(btype)) {
int error;
long temp = PyLong_AsLongAndOverflow(b, &error);
if (!error) {
c = mpz_cmp_si(MPZ(a), temp);
}
else {
mpz_t tempz;
mpz_init(tempz);
mpz_set_PyLong(tempz, b);
c = mpz_cmp(MPZ(a), tempz);
mpz_clear(tempz);
}
return _cmp_to_object(c, op);
}
if (IS_TYPE_MPZANY(btype)) {
return _cmp_to_object(mpz_cmp(MPZ(a), MPZ(b)), op);
}
if (IS_TYPE_INTEGER(btype)) {
if (!(tempb = (PyObject*)GMPy_MPZ_From_IntegerWithType(b, btype, context))) {
return NULL;
}
c = mpz_cmp(MPZ(a), MPZ(tempb));
Py_DECREF(tempb);
return _cmp_to_object(c, op);
}
if (IS_TYPE_RATIONAL(btype)) {
tempa = (PyObject*)GMPy_MPQ_From_RationalWithType(a, atype, context);
tempb = (PyObject*)GMPy_MPQ_From_RationalWithType(b, btype, context);
if (!tempa || !tempb) {
Py_XDECREF(a);
Py_XDECREF(b);
return NULL;
}
c = mpq_cmp(MPQ(tempa), MPQ(tempb));
Py_DECREF(tempa);
Py_DECREF(tempb);
return _cmp_to_object(c, op);
}
if (IS_TYPE_PyFloat(btype)) {
double d = PyFloat_AS_DOUBLE(b);
if (isnan(d)) {
result = (op == Py_NE) ? Py_True : Py_False;
Py_INCREF(result);
return result;
}
else if (isinf(d)) {
if (d < 0.0)
return _cmp_to_object(1, op);
else
return _cmp_to_object(-1, op);
}
else {
return _cmp_to_object(mpz_cmp_d(MPZ(a), d), op);
}
}
}
if (IS_TYPE_MPQ(atype)) {
if (IS_TYPE_MPQ(btype)) {
return _cmp_to_object(mpq_cmp(MPQ(a), MPQ(b)), op);
}
if (IS_TYPE_RATIONAL(btype)) {
if (!(tempb = (PyObject*)GMPy_MPQ_From_RationalWithType(b, btype, context))) {
return NULL;
}
c = mpq_cmp(MPQ(a), MPQ(tempb));
Py_DECREF(tempb);
return _cmp_to_object(c, op);
}
if (IS_TYPE_PyFloat(btype)) {
double d = PyFloat_AS_DOUBLE(b);
if (isnan(d)) {
result = (op == Py_NE) ? Py_True : Py_False;
Py_INCREF(result);
return result;
}
else if (isinf(d)) {
if (d < 0.0)
return _cmp_to_object(1, op);
else
return _cmp_to_object(-1, op);
}
else {
if (!(tempb = (PyObject*)GMPy_MPQ_New(context))) {
return NULL;
}
mpq_set_d(MPQ(tempb), d);
c = mpq_cmp(MPQ(a), MPQ(tempb));
Py_DECREF(tempb);
return _cmp_to_object(c, op);
}
}
}
if (IS_TYPE_MPFR(atype)) {
if (IS_TYPE_MPFR(btype)) {
mpfr_clear_flags();
c = mpfr_cmp(MPFR(a), MPFR(b));
if (mpfr_erangeflag_p()) {
/* Set erange and check if an exception should be raised. */
context->ctx.erange = 1;
if (context->ctx.traps & TRAP_ERANGE) {
GMPY_ERANGE("comparison with NaN");
return NULL;
}
result = (op == Py_NE) ? Py_True : Py_False;
Py_INCREF(result);
return result;
}
else {
return _cmp_to_object(c, op);
}
}
if (IS_TYPE_PyFloat(btype)) {
double d = PyFloat_AS_DOUBLE(b);
mpfr_clear_flags();
c = mpfr_cmp_d(MPFR(a), d);
if (mpfr_erangeflag_p()) {
/* Set erange and check if an exception should be raised. */
context->ctx.erange = 1;
if (context->ctx.traps & TRAP_ERANGE) {
GMPY_ERANGE("comparison with NaN");
return NULL;
}
result = (op == Py_NE) ? Py_True : Py_False;
Py_INCREF(result);
return result;
}
else {
return _cmp_to_object(c, op);
}
}
if (IS_TYPE_INTEGER(btype)) {
if (!(tempb = (PyObject*)GMPy_MPZ_From_IntegerWithType(b, btype, context))) {
return NULL;
}
mpfr_clear_flags();
c = mpfr_cmp_z(MPFR(a), MPZ(tempb));
Py_DECREF(tempb);
if (mpfr_erangeflag_p()) {
/* Set erange and check if an exception should be raised. */
context->ctx.erange = 1;
if (context->ctx.traps & TRAP_ERANGE) {
GMPY_ERANGE("comparison with NaN");
return NULL;
}
result = (op == Py_NE) ? Py_True : Py_False;
Py_INCREF(result);
return result;
}
else {
return _cmp_to_object(c, op);
}
}
if (IS_TYPE_RATIONAL(btype)) {
if (!(tempb = (PyObject*)GMPy_MPQ_From_RationalWithType(b, btype, context))) {
return NULL;
}
mpfr_clear_flags();
c = mpfr_cmp_q(MPFR(a), MPQ(tempb));
Py_DECREF(tempb);
if (mpfr_erangeflag_p()) {
/* Set erange and check if an exception should be raised. */
context->ctx.erange = 1;
if (context->ctx.traps & TRAP_ERANGE) {
GMPY_ERANGE("comparison with NaN");
return NULL;
}
result = (op == Py_NE) ? Py_True : Py_False;
Py_INCREF(result);
return result;
}
else {
return _cmp_to_object(c, op);
}
}
if (IS_TYPE_REAL(btype)) {
if (!(tempb = (PyObject*)GMPy_MPFR_From_RealWithType(b, btype, 1, context))) {
return NULL;
}
mpfr_clear_flags();
c = mpfr_cmp(MPFR(a), MPFR(tempb));
Py_DECREF(tempb);
if (mpfr_erangeflag_p()) {
/* Set erange and check if an exception should be raised. */
context->ctx.erange = 1;
if (context->ctx.traps & TRAP_ERANGE) {
GMPY_ERANGE("comparison with NaN");
return NULL;
}
result = (op == Py_NE) ? Py_True : Py_False;
Py_INCREF(result);
return result;
}
else {
return _cmp_to_object(c, op);
}
}
}
if (IS_TYPE_MPC(atype)) {
if (!(op == Py_EQ || op == Py_NE)) {
TYPE_ERROR("no ordering relation is defined for complex numbers");
return NULL;
}
if (IS_TYPE_MPC(btype)) {
mpfr_clear_flags();
c = mpc_cmp(MPC(a), MPC(b));
if (mpfr_erangeflag_p()) {
/* Set erange and check if an exception should be raised. */
context->ctx.erange = 1;
if (context->ctx.traps & TRAP_ERANGE) {
GMPY_ERANGE("comparison with NaN");
return NULL;
}
result = (op == Py_NE) ? Py_True : Py_False;
Py_INCREF(result);
return result;
}
else {
return _cmp_to_object(c, op);
}
}
if (PyComplex_Check(b)) {
if (!(tempb = (PyObject*)GMPy_MPC_From_PyComplex(b, 1, 1, context))) {
return NULL;
}
mpfr_clear_flags();
c = mpc_cmp(MPC(a), MPC(tempb));
Py_DECREF(tempb);
if (mpfr_erangeflag_p()) {
/* Set erange and check if an exception should be raised. */
context->ctx.erange = 1;
if (context->ctx.traps & TRAP_ERANGE) {
GMPY_ERANGE("comparison with NaN");
return NULL;
}
result = (op == Py_NE) ? Py_True : Py_False;
Py_INCREF(result);
return result;
}
else {
return _cmp_to_object(c, op);
}
}
/* a.imag must be 0 or else all further comparisons will be NE */
if (!mpfr_zero_p(mpc_imagref(MPC(a)))) {
/* if a.real is NaN, possibly raise exception */
if (mpfr_nan_p(mpc_realref(MPC(a)))) {
context->ctx.erange = 1;
if (context->ctx.traps & TRAP_ERANGE) {
GMPY_ERANGE("comparison with NaN");
return NULL;
}
}
result = (op == Py_NE) ? Py_True : Py_False;
Py_INCREF(result);
return result;
}
else {
if (!(tempb = (PyObject*)GMPy_MPFR_New(mpfr_get_prec(mpc_realref(MPC(a))), context))) {
return NULL;
}
mpc_real(MPFR(tempb), MPC(a), GET_MPFR_ROUND(context));
result = GMPy_RichCompare_Slot(tempb, b, op);
Py_DECREF(tempb);
return result;
}
}
Py_RETURN_NOTIMPLEMENTED;
}
././@PaxHeader 0000000 0000000 0000000 00000000026 00000000000 010213 x ustar 00 22 mtime=1710307256.0
gmpy2-2.2.1/src/gmpy2_richcompare.h 0000644 0001750 0001750 00000004175 14574233670 015616 0 ustar 00case case /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* gmpy2_richcompare.h *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Python interface to the GMP, MPFR, and MPC multiple precision *
* libraries. *
* *
* Copyright 2000 - 2009 Alex Martelli *
* *
* Copyright 2008 - 2024 Case Van Horsen *
* *
* This file is part of GMPY2. *
* *
* GMPY2 is free software: you can redistribute it and/or modify it under *
* the terms of the GNU Lesser General Public License as published by the *
* Free Software Foundation, either version 3 of the License, or (at your *
* option) any later version. *
* *
* GMPY2 is distributed in the hope that it will be useful, but WITHOUT *
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or *
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public *
* License for more details. *
* *
* You should have received a copy of the GNU Lesser General Public *
* License along with GMPY2; if not, see *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
#ifndef GMPY_RICHCOMPARE_H
#define GMPY_RICHCOMPARE_H
#ifdef __cplusplus
extern "C" {
#endif
/* Forward declarations begin here. */
static PyObject * GMPy_RichCompare_Slot(PyObject *a, PyObject *b, int op);
#ifdef __cplusplus
}
#endif
#endif
././@PaxHeader 0000000 0000000 0000000 00000000026 00000000000 010213 x ustar 00 22 mtime=1710307256.0
gmpy2-2.2.1/src/gmpy2_sign.c 0000644 0001750 0001750 00000007402 14574233670 014251 0 ustar 00case case /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* gmpy2_sign.c *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Python interface to the GMP, MPFR, and MPC multiple precision *
* libraries. *
* *
* Copyright 2000 - 2009 Alex Martelli *
* *
* Copyright 2008 - 2024 Case Van Horsen *
* *
* This file is part of GMPY2. *
* *
* GMPY2 is free software: you can redistribute it and/or modify it under *
* the terms of the GNU Lesser General Public License as published by the *
* Free Software Foundation, either version 3 of the License, or (at your *
* option) any later version. *
* *
* GMPY2 is distributed in the hope that it will be useful, but WITHOUT *
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or *
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public *
* License for more details. *
* *
* You should have received a copy of the GNU Lesser General Public *
* License along with GMPY2; if not, see *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
static PyObject *
GMPy_Integer_Sign(PyObject *x, CTXT_Object *context)
{
long res;
MPZ_Object *tempx;
if (!(tempx = GMPy_MPZ_From_Integer(x, context))) {
return NULL;
}
else {
res = mpz_sgn(tempx->z);
Py_DECREF((PyObject*)tempx);
return PyLong_FromLong(res);
}
}
static PyObject *
GMPy_Rational_Sign(PyObject *x, CTXT_Object *context)
{
long res;
MPQ_Object *tempx;
if (!(tempx = GMPy_MPQ_From_Rational(x, context))) {
return NULL;
}
else {
res = mpq_sgn(tempx->q);
Py_DECREF((PyObject*)tempx);
return PyLong_FromLong(res);
}
}
static PyObject *
GMPy_Real_Sign(PyObject *x, CTXT_Object *context)
{
long sign;
MPFR_Object *tempx;
PyObject *result;
CHECK_CONTEXT(context);
if (!(tempx = GMPy_MPFR_From_Real(x, 1, context))) {
return NULL;
}
else {
mpfr_clear_flags();
sign = mpfr_sgn(tempx->f);
Py_DECREF((PyObject*)tempx);
result = PyLong_FromLong(sign);
GMPY_CHECK_ERANGE(result, context, "sign() of invalid value (NaN)");
return result;
}
}
static PyObject *
GMPy_Number_Sign(PyObject *x, CTXT_Object *context)
{
if (IS_INTEGER(x))
return GMPy_Integer_Sign(x, context);
else if (IS_RATIONAL_ONLY(x))
return GMPy_Rational_Sign(x, context);
else if (IS_REAL_ONLY(x))
return GMPy_Real_Sign(x, context);
TYPE_ERROR("sign() argument type not supported");
return NULL;
}
PyDoc_STRVAR(GMPy_doc_function_sign,
"sign(x, /) -> int\n\n"
"Return -1 if x < 0, 0 if x == 0, or +1 if x >0.");
static PyObject *
GMPy_Context_Sign(PyObject *self, PyObject *other)
{
CTXT_Object *context = NULL;
if (self && CTXT_Check(self)) {
context = (CTXT_Object*)self;
}
else {
CHECK_CONTEXT(context);
}
return GMPy_Number_Sign(other, context);
}
././@PaxHeader 0000000 0000000 0000000 00000000026 00000000000 010213 x ustar 00 22 mtime=1710307256.0
gmpy2-2.2.1/src/gmpy2_sign.h 0000644 0001750 0001750 00000004537 14574233670 014264 0 ustar 00case case /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* gmpy_mpany.h *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Python interface to the GMP, MPFR, and MPC multiple precision *
* libraries. *
* *
* Copyright 2000 - 2009 Alex Martelli *
* *
* Copyright 2008 - 2024 Case Van Horsen *
* *
* This file is part of GMPY2. *
* *
* GMPY2 is free software: you can redistribute it and/or modify it under *
* the terms of the GNU Lesser General Public License as published by the *
* Free Software Foundation, either version 3 of the License, or (at your *
* option) any later version. *
* *
* GMPY2 is distributed in the hope that it will be useful, but WITHOUT *
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or *
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public *
* License for more details. *
* *
* You should have received a copy of the GNU Lesser General Public *
* License along with GMPY2; if not, see *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
#ifndef GMPY_SIGN_H
#define GMPY_SIGN_H
#ifdef __cplusplus
extern "C" {
#endif
static PyObject * GMPy_Integer_Sign(PyObject *x, CTXT_Object *context);
static PyObject * GMPy_Rational_Sign(PyObject *x, CTXT_Object *context);
static PyObject * GMPy_Real_Sign(PyObject *x, CTXT_Object *context);
static PyObject * GMPy_Number_Sign(PyObject *x, CTXT_Object *context);
static PyObject * GMPy_Context_Sign(PyObject *self, PyObject *other);
#ifdef __cplusplus
}
#endif
#endif
././@PaxHeader 0000000 0000000 0000000 00000000026 00000000000 010213 x ustar 00 22 mtime=1710307256.0
gmpy2-2.2.1/src/gmpy2_square.c 0000644 0001750 0001750 00000013733 14574233670 014615 0 ustar 00case case /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* gmpy2_square.c *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Python interface to the GMP, MPFR, and MPC multiple precision *
* libraries. *
* *
* Copyright 2000 - 2009 Alex Martelli *
* *
* Copyright 2008 - 2024 Case Van Horsen *
* *
* This file is part of GMPY2. *
* *
* GMPY2 is free software: you can redistribute it and/or modify it under *
* the terms of the GNU Lesser General Public License as published by the *
* Free Software Foundation, either version 3 of the License, or (at your *
* option) any later version. *
* *
* GMPY2 is distributed in the hope that it will be useful, but WITHOUT *
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or *
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public *
* License for more details. *
* *
* You should have received a copy of the GNU Lesser General Public *
* License along with GMPY2; if not, see *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
/* Public API
* ==========
* The following function is available as part of GMPY2's C API. A NULL value
* for context implies the function should use the currently active context.
*
* GMPy_Number_Square(Number, Number, context|NULL)
*
* Private API
* ===========
* GMPy_Integer_Square(Integer, Integer, context|NULL)
* GMPy_Rational_Square(Rational, Rational, context|NULL)
* GMPy_Real_Square(Real, Real, context|NULL)
* GMPy_Complex_Square(Complex, Complex, context|NULL)
*
* GMPy_Context_Square(context, args)
*
*/
static PyObject *
_GMPy_MPZ_Square(PyObject *x, CTXT_Object *context)
{
MPZ_Object *result = NULL;
if (!(result = GMPy_MPZ_New(context))) {
return NULL;
}
mpz_mul(result->z, MPZ(x), MPZ(x));
return (PyObject*)result;
}
static PyObject *
GMPy_Integer_Square(PyObject *x, CTXT_Object *context)
{
PyObject *result, *tempx;
if (!(tempx = (PyObject*)GMPy_MPZ_From_Integer(x, context))) {
return NULL;
}
result = _GMPy_MPZ_Square(tempx, context);
Py_DECREF(tempx);
return result;
}
static PyObject *
_GMPy_MPQ_Square(PyObject *x, CTXT_Object *context)
{
MPQ_Object *result;
if (!(result = GMPy_MPQ_New(context))) {
return NULL;
}
mpq_mul(result->q, MPQ(x), MPQ(x));
return (PyObject*)result;
}
static PyObject *
GMPy_Rational_Square(PyObject *x, CTXT_Object *context)
{
PyObject *result, *tempx;
if (!(tempx = (PyObject*)GMPy_MPQ_From_Rational(x, context))) {
return NULL;
}
result = _GMPy_MPQ_Square(tempx, context);
Py_DECREF(tempx);
return result;
}
static PyObject *
_GMPy_MPFR_Square(PyObject *x, CTXT_Object *context)
{
MPFR_Object *result;
CHECK_CONTEXT(context);
if (!(result = GMPy_MPFR_New(0, context))) {
return NULL;
}
mpfr_clear_flags();
mpfr_sqr(result->f, MPFR(x), GET_MPFR_ROUND(context));
_GMPy_MPFR_Cleanup(&result, context);
return (PyObject*)result;
}
static PyObject *
GMPy_Real_Square(PyObject *x, CTXT_Object *context)
{
PyObject *result, *tempx;
CHECK_CONTEXT(context);
if (!(tempx = (PyObject*)GMPy_MPFR_From_Real(x, 1, context))) {
return NULL;
}
result = _GMPy_MPFR_Square(tempx, context);
Py_DECREF(tempx);
return result;
}
static PyObject *
_GMPy_MPC_Square(PyObject *x, CTXT_Object *context)
{
MPC_Object *result;
CHECK_CONTEXT(context);
if (!(result = GMPy_MPC_New(0, 0, context))) {
return NULL;
}
mpc_sqr(result->c, MPC(x), GET_MPC_ROUND(context));
_GMPy_MPC_Cleanup(&result, context);
return (PyObject*)result;
}
static PyObject *
GMPy_Complex_Square(PyObject *x, CTXT_Object *context)
{
PyObject *result, *tempx;
CHECK_CONTEXT(context);
if (!(tempx = (PyObject*)GMPy_MPC_From_Complex(x, 1, 1, context))) {
return NULL;
}
result = _GMPy_MPC_Square(tempx, context);
Py_DECREF(tempx);
return result;
}
PyDoc_STRVAR(GMPy_doc_function_square,
"square(x, /) -> mpz | mpq | mpfr | mpc\n\n"
"Return x * x.");
PyDoc_STRVAR(GMPy_doc_context_square,
"context.square(x, /) -> mpz | mpq | mpfr | mpc\n\n"
"Return x * x.");
static PyObject *
GMPy_Number_Square(PyObject *x, CTXT_Object *context)
{
if (MPZ_Check(x))
return _GMPy_MPZ_Square(x, context);
if (MPQ_Check(x))
return _GMPy_MPQ_Square(x, context);
if (MPFR_Check(x))
return _GMPy_MPFR_Square(x, context);
if (MPC_Check(x))
return _GMPy_MPC_Square(x, context);
if (IS_INTEGER(x))
return GMPy_Integer_Square(x, context);
if (IS_RATIONAL(x))
return GMPy_Rational_Square(x, context);
if (IS_REAL(x))
return GMPy_Real_Square(x, context);
if (IS_COMPLEX(x))
return GMPy_Complex_Square(x, context);
TYPE_ERROR("square() argument type not supported");
return NULL;
}
static PyObject *
GMPy_Context_Square(PyObject *self, PyObject *other)
{
CTXT_Object *context = NULL;
if (self && CTXT_Check(self)) {
context = (CTXT_Object*)self;
}
else {
CHECK_CONTEXT(context);
}
return GMPy_Number_Square(other, context);
}
././@PaxHeader 0000000 0000000 0000000 00000000026 00000000000 010213 x ustar 00 22 mtime=1710307256.0
gmpy2-2.2.1/src/gmpy2_square.h 0000644 0001750 0001750 00000004671 14574233670 014623 0 ustar 00case case /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* gmpy2_square.h *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Python interface to the GMP, MPFR, and MPC multiple precision *
* libraries. *
* *
* Copyright 2000 - 2009 Alex Martelli *
* *
* Copyright 2008 - 2024 Case Van Horsen *
* *
* This file is part of GMPY2. *
* *
* GMPY2 is free software: you can redistribute it and/or modify it under *
* the terms of the GNU Lesser General Public License as published by the *
* Free Software Foundation, either version 3 of the License, or (at your *
* option) any later version. *
* *
* GMPY2 is distributed in the hope that it will be useful, but WITHOUT *
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or *
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public *
* License for more details. *
* *
* You should have received a copy of the GNU Lesser General Public *
* License along with GMPY2; if not, see *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
#ifndef GMPY2_SQUARE_H
#define GMPY2_SQUARE_H
#ifdef __cplusplus
extern "C" {
#endif
static PyObject * GMPy_Integer_Square(PyObject *x, CTXT_Object *context);
static PyObject * GMPy_Rational_Square(PyObject *x, CTXT_Object *context);
static PyObject * GMPy_Real_Square(PyObject *x, CTXT_Object *context);
static PyObject * GMPy_Complex_Square(PyObject *x, CTXT_Object *context);
static PyObject * GMPy_Number_Square(PyObject *x, CTXT_Object *context);
static PyObject * GMPy_Context_Square(PyObject *self, PyObject *args);
#ifdef __cplusplus
}
#endif
#endif
././@PaxHeader 0000000 0000000 0000000 00000000026 00000000000 010213 x ustar 00 22 mtime=1710307256.0
gmpy2-2.2.1/src/gmpy2_sub.c 0000644 0001750 0001750 00000030632 14574233670 014103 0 ustar 00case case /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* gmpy2_sub.c *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Python interface to the GMP, MPFR, and MPC multiple precision *
* libraries. *
* *
* Copyright 2000 - 2009 Alex Martelli *
* *
* Copyright 2008 - 2024 Case Van Horsen *
* *
* This file is part of GMPY2. *
* *
* GMPY2 is free software: you can redistribute it and/or modify it under *
* the terms of the GNU Lesser General Public License as published by the *
* Free Software Foundation, either version 3 of the License, or (at your *
* option) any later version. *
* *
* GMPY2 is distributed in the hope that it will be useful, but WITHOUT *
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or *
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public *
* License for more details. *
* *
* You should have received a copy of the GNU Lesser General Public *
* License along with GMPY2; if not, see *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
/* This file implements the - operator, gmpy2.sub(), and context.sub().
*/
/* Subtract two Integer objects (see gmpy2_convert.c). If an error occurs,
* NULL is returned and an exception is set. If either x or y can't be
* converted into an mpz, Py_NotImplemented is returned. */
static PyObject *
GMPy_Integer_SubWithType(PyObject *x, int xtype, PyObject *y, int ytype,
CTXT_Object *context)
{
MPZ_Object *result = NULL;
if (!(result = GMPy_MPZ_New(context))) {
/* LCOV_EXCL_START */
return NULL;
/* LCOV_EXCL_STOP */
}
if (IS_TYPE_MPZANY(xtype)) {
if (IS_TYPE_MPZANY(ytype)) {
GMPY_MAYBE_BEGIN_ALLOW_THREADS(context);
mpz_sub(result->z, MPZ(x), MPZ(y));
GMPY_MAYBE_END_ALLOW_THREADS(context);
return (PyObject*)result;
}
if (IS_TYPE_PyInteger(ytype)) {
int error;
long temp = PyLong_AsLongAndOverflow(y, &error);
if (!error) {
if (temp >= 0) {
mpz_sub_ui(result->z, MPZ(x), temp);
}
else {
mpz_add_ui(result->z, MPZ(x), -temp);
}
}
else {
mpz_set_PyLong(result->z, y);
GMPY_MAYBE_BEGIN_ALLOW_THREADS(context);
mpz_sub(result->z, MPZ(x), result->z);
GMPY_MAYBE_END_ALLOW_THREADS(context);
}
return (PyObject*)result;
}
}
if (IS_TYPE_MPZANY(ytype)) {
if (IS_TYPE_PyInteger(xtype)) {
int error;
long temp = PyLong_AsLongAndOverflow(x, &error);
if (!error) {
if (temp >= 0) {
mpz_ui_sub(result->z, temp, MPZ(y));
}
else {
mpz_add_ui(result->z, MPZ(y), -temp);
mpz_neg(result->z, result->z);
}
}
else {
GMPY_MAYBE_BEGIN_ALLOW_THREADS(context);
mpz_set_PyLong(result->z, x);
mpz_sub(result->z, result->z, MPZ(y));
GMPY_MAYBE_END_ALLOW_THREADS(context);
}
return (PyObject*)result;
}
}
if (IS_TYPE_INTEGER(xtype) && IS_TYPE_INTEGER(ytype)) {
MPZ_Object *tempx = NULL, *tempy = NULL;
if (!(tempx = GMPy_MPZ_From_IntegerWithType(x, xtype, context)) ||
!(tempy = GMPy_MPZ_From_IntegerWithType(y, ytype, context))) {
/* LCOV_EXCL_START */
Py_XDECREF((PyObject*)tempx);
Py_XDECREF((PyObject*)tempy);
Py_DECREF((PyObject*)result);
return NULL;
/* LCOV_EXCL_STOP */
}
GMPY_MAYBE_BEGIN_ALLOW_THREADS(context);
mpz_sub(result->z, tempx->z, tempy->z);
GMPY_MAYBE_END_ALLOW_THREADS(context);
Py_DECREF((PyObject*)tempx);
Py_DECREF((PyObject*)tempy);
return (PyObject*)result;
}
/* LCOV_EXCL_START */
Py_DECREF((PyObject*)result);
TYPE_ERROR("sub() argument type not supported");
return NULL;
/* LCOV_EXCL_STOP */
}
/* Subtract two Rational objects (see gmpy2_convert.h). Returns None and
* raises TypeError if both objects are not valid rationals. Pympq_Sub_Rational
* is intended to be called from GMPy_Number_Sub(). */
static PyObject *
GMPy_Rational_SubWithType(PyObject *x, int xtype, PyObject *y, int ytype,
CTXT_Object *context)
{
MPQ_Object *result = NULL;
if (!(result = GMPy_MPQ_New(context))) {
/* LCOV_EXCL_START */
return NULL;
/* LCOV_EXCL_STOP */
}
if (IS_TYPE_MPQ(xtype) && IS_TYPE_MPQ(ytype)) {
GMPY_MAYBE_BEGIN_ALLOW_THREADS(context);
mpq_sub(result->q, MPQ(x), MPQ(y));
GMPY_MAYBE_END_ALLOW_THREADS(context);
return (PyObject*)result;
}
if (IS_TYPE_RATIONAL(xtype) && IS_TYPE_RATIONAL(ytype)) {
MPQ_Object *tempx = NULL, *tempy = NULL;
if (!(tempx = GMPy_MPQ_From_RationalWithType(x, xtype, context)) ||
!(tempy = GMPy_MPQ_From_RationalWithType(y, ytype, context))) {
/* LCOV_EXCL_START */
Py_XDECREF((PyObject*)tempx);
Py_XDECREF((PyObject*)tempy);
Py_DECREF((PyObject*)result);
return NULL;
/* LCOV_EXCL_STOP */
}
GMPY_MAYBE_BEGIN_ALLOW_THREADS(context);
mpq_sub(result->q, tempx->q, tempy->q);
GMPY_MAYBE_END_ALLOW_THREADS(context);
Py_DECREF((PyObject*)tempx);
Py_DECREF((PyObject*)tempy);
return (PyObject*)result;
}
/* LCOV_EXCL_START */
Py_DECREF((PyObject*)result);
TYPE_ERROR("sub() argument type not supported");
return NULL;
/* LCOV_EXCL_STOP */
}
/* GMPy_Real_Sub(x, y, context) returns x-y using the provided context. If
* provided context is NULL, then the current context is used. If an error
* occurs, NULL is returned and an exception is set. If either x or y can't
* be converted to an mpfr, then Py_NotImplemented is returned.
* GMPy_Real_Sub() will not try to promote the result to a different type
* (i.e. mpc).
*/
static PyObject *
GMPy_Real_SubWithType(PyObject *x, int xtype, PyObject *y, int ytype,
CTXT_Object *context)
{
MPFR_Object *result = NULL;
if (!(result = GMPy_MPFR_New(0, context))) {
/* LCOV_EXCL_START */
return NULL;
/* LCOV_EXCL_STOP */
}
if (IS_TYPE_MPFR(xtype) && IS_TYPE_MPFR(ytype)) {
mpfr_clear_flags();
result->rc = mpfr_sub(result->f, MPFR(x), MPFR(y), GET_MPFR_ROUND(context));
_GMPy_MPFR_Cleanup(&result, context);
return (PyObject*)result;
}
if (IS_TYPE_REAL(xtype) && IS_TYPE_REAL(ytype)) {
MPFR_Object *tempx = NULL, *tempy = NULL;
if (!(tempx = GMPy_MPFR_From_RealWithType(x, xtype, 1, context)) ||
!(tempy = GMPy_MPFR_From_RealWithType(y, ytype, 1, context))) {
/* LCOV_EXCL_START */
Py_XDECREF((PyObject*)tempx);
Py_XDECREF((PyObject*)tempy);
Py_DECREF((PyObject*)result);
return NULL;
/* LCOV_EXCL_STOP */
}
mpfr_clear_flags();
result->rc = mpfr_sub(result->f, MPFR(tempx), MPFR(tempy), GET_MPFR_ROUND(context));
Py_DECREF((PyObject*)tempx);
Py_DECREF((PyObject*)tempy);
goto done;
}
/* LCOV_EXCL_START */
Py_DECREF((PyObject*)result);
TYPE_ERROR("sub() argument type not supported");
return NULL;
/* LCOV_EXCL_STOP */
done:
_GMPy_MPFR_Cleanup(&result, context);
return (PyObject*)result;
}
/* GMPy_Complex_Sub(x, y, context) returns x-y using the provided context. If
* context is NULL, then the current context is used. If an error occurs, NULL
* is returned and an exception is set. If either x or y can't be converted to
* an mpc, then Py_NotImplemented is returned. */
static PyObject *
GMPy_Complex_SubWithType(PyObject *x, int xtype, PyObject *y, int ytype,
CTXT_Object *context)
{
MPC_Object *result = NULL;
if (!(result = GMPy_MPC_New(0, 0, context))) {
/* LCOV_EXCL_START */
return NULL;
/* LCOV_EXCL_STOP */
}
if (IS_TYPE_MPC(xtype) && IS_TYPE_MPC(ytype)) {
result->rc = mpc_sub(result->c, MPC(x), MPC(y), GET_MPC_ROUND(context));
_GMPy_MPC_Cleanup(&result, context);
return (PyObject*)result;
}
if (IS_TYPE_COMPLEX(xtype) && IS_TYPE_COMPLEX(ytype)) {
MPC_Object *tempx = NULL, *tempy = NULL;
if (!(tempx = GMPy_MPC_From_ComplexWithType(x, xtype, 1, 1, context)) ||
!(tempy = GMPy_MPC_From_ComplexWithType(y, ytype, 1, 1, context))) {
/* LCOV_EXCL_START */
Py_XDECREF((PyObject*)tempx);
Py_XDECREF((PyObject*)tempy);
Py_DECREF((PyObject*)result);
return NULL;
/* LCOV_EXCL_STOP */
}
result->rc = mpc_sub(result->c, tempx->c, tempy->c, GET_MPC_ROUND(context));
Py_DECREF((PyObject*)tempx);
Py_DECREF((PyObject*)tempy);
_GMPy_MPC_Cleanup(&result, context);
return (PyObject*)result;
}
/* LCOV_EXCL_START */
Py_DECREF((PyObject*)result);
TYPE_ERROR("sub() argument type not supported");
return NULL;
/* LCOV_EXCL_STOP */
}
static PyObject *
GMPy_Number_Sub(PyObject *x, PyObject *y, CTXT_Object *context)
{
CHECK_CONTEXT(context);
int xtype = GMPy_ObjectType(x);
int ytype = GMPy_ObjectType(y);
if (IS_TYPE_INTEGER(xtype) && IS_TYPE_INTEGER(ytype))
return GMPy_Integer_SubWithType(x, xtype, y, ytype, context);
if (IS_TYPE_RATIONAL(xtype) && IS_TYPE_RATIONAL(ytype))
return GMPy_Rational_SubWithType(x, xtype, y, ytype, context);
if (IS_TYPE_REAL(xtype) && IS_TYPE_REAL(ytype))
return GMPy_Real_SubWithType(x, xtype, y, ytype, context);
if (IS_TYPE_COMPLEX(xtype) && IS_TYPE_COMPLEX(ytype))
return GMPy_Complex_SubWithType(x, xtype, y, ytype, context);
TYPE_ERROR("sub() argument type not supported");
return NULL;
}
/* Implement all the slot methods here. */
static PyObject *
GMPy_Number_Sub_Slot(PyObject *x, PyObject *y)
{
CTXT_Object *context = NULL;
CHECK_CONTEXT(context);
int xtype = GMPy_ObjectType(x);
int ytype = GMPy_ObjectType(y);
if (IS_TYPE_INTEGER(xtype) && IS_TYPE_INTEGER(ytype))
return GMPy_Integer_SubWithType(x, xtype, y, ytype, context);
if (IS_TYPE_RATIONAL(xtype) && IS_TYPE_RATIONAL(ytype))
return GMPy_Rational_SubWithType(x, xtype, y, ytype, context);
if (IS_TYPE_REAL(xtype) && IS_TYPE_REAL(ytype))
return GMPy_Real_SubWithType(x, xtype, y, ytype, context);
if (IS_TYPE_COMPLEX(xtype) && IS_TYPE_COMPLEX(ytype))
return GMPy_Complex_SubWithType(x, xtype, y, ytype, context);
Py_RETURN_NOTIMPLEMENTED;
}
/* Implement context.sub() and gmpy2.sub(). */
PyDoc_STRVAR(GMPy_doc_sub,
"sub(x, y, /) -> mpz | mpq | mpfr | mpc\n\n"
"Return x - y.");
PyDoc_STRVAR(GMPy_doc_context_sub,
"context.sub(x, y, /) -> mpz | mpq | mpfr | mpc\n\n"
"Return x - y.");
static PyObject *
GMPy_Context_Sub(PyObject *self, PyObject *args)
{
CTXT_Object *context = NULL;
if (PyTuple_GET_SIZE(args) != 2) {
TYPE_ERROR("sub() requires 2 arguments");
return NULL;
}
if (self && CTXT_Check(self)) {
context = (CTXT_Object*)self;
}
else {
CHECK_CONTEXT(context);
}
return GMPy_Number_Sub(PyTuple_GET_ITEM(args, 0),
PyTuple_GET_ITEM(args, 1),
context);
}
././@PaxHeader 0000000 0000000 0000000 00000000026 00000000000 010213 x ustar 00 22 mtime=1710307256.0
gmpy2-2.2.1/src/gmpy2_sub.h 0000644 0001750 0001750 00000005301 14574233670 014103 0 ustar 00case case /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* gmpy2_sub.h *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Python interface to the GMP, MPFR, and MPC multiple precision *
* libraries. *
* *
* Copyright 2000 - 2009 Alex Martelli *
* *
* Copyright 2008 - 2024 Case Van Horsen *
* *
* This file is part of GMPY2. *
* *
* GMPY2 is free software: you can redistribute it and/or modify it under *
* the terms of the GNU Lesser General Public License as published by the *
* Free Software Foundation, either version 3 of the License, or (at your *
* option) any later version. *
* *
* GMPY2 is distributed in the hope that it will be useful, but WITHOUT *
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or *
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public *
* License for more details. *
* *
* You should have received a copy of the GNU Lesser General Public *
* License along with GMPY2; if not, see *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
#ifndef GMPY2_SUB_H
#define GMPY2_SUB_H
#ifdef __cplusplus
extern "C" {
#endif
/* Public API */
static PyObject * GMPy_Number_Sub(PyObject *x, PyObject *y, CTXT_Object *context);
/* Private API */
static PyObject * GMPy_Integer_SubWithType(PyObject *x, int xtype, PyObject *y, int ytype, CTXT_Object *context);
static PyObject * GMPy_Rational_SubWithType(PyObject *x, int xtype, PyObject *y, int ytype, CTXT_Object *context);
static PyObject * GMPy_Real_SubWithType(PyObject *x, int xtype, PyObject *y, int ytype, CTXT_Object *context);
static PyObject * GMPy_Complex_SubWithType(PyObject *x, int xtype, PyObject *y, int ytype, CTXT_Object *context);
static PyObject * GMPy_Number_Sub_Slot(PyObject *x, PyObject *y);
static PyObject * GMPy_Context_Sub(PyObject *self, PyObject *args);
#ifdef __cplusplus
}
#endif
#endif
././@PaxHeader 0000000 0000000 0000000 00000000026 00000000000 010213 x ustar 00 22 mtime=1710307256.0
gmpy2-2.2.1/src/gmpy2_truediv.c 0000644 0001750 0001750 00000027112 14574233670 014773 0 ustar 00case case /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* gmpy2_truediv.c *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Python interface to the GMP, MPFR, and MPC multiple precision *
* libraries. *
* *
* Copyright 2000 - 2009 Alex Martelli *
* *
* Copyright 2008 - 2024 Case Van Horsen *
* *
* This file is part of GMPY2. *
* *
* GMPY2 is free software: you can redistribute it and/or modify it under *
* the terms of the GNU Lesser General Public License as published by the *
* Free Software Foundation, either version 3 of the License, or (at your *
* option) any later version. *
* *
* GMPY2 is distributed in the hope that it will be useful, but WITHOUT *
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or *
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public *
* License for more details. *
* *
* You should have received a copy of the GNU Lesser General Public *
* License along with GMPY2; if not, see *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
/* This file implements the / operator, gmpy2.div() and context.div().
*
* Public API
* ==========
* The following function is available as part of GMPY2's C API. A NULL value
* for context implies the function should use the currently active context.
*/
/* Divide two Integer objects (see convert.c/isInteger) using true division.
* If an error occurs, NULL is returned and an exception is set. If either x
* or y can't be converted into an mpz, Py_NotImplemented is returned. */
static PyObject *
GMPy_Integer_TrueDivWithType(PyObject *x, int xtype, PyObject *y, int ytype,
CTXT_Object *context)
{
MPZ_Object *tempx = NULL, *tempy = NULL;
mpq_t tempq;
MPFR_Object *result = NULL;
CHECK_CONTEXT(context);
if (GET_DIV_MODE(context))
return GMPy_Rational_TrueDivWithType(x, xtype, y, ytype, context);
if (!(result = GMPy_MPFR_New(0, context)))
return NULL;
if (IS_TYPE_INTEGER(xtype) && IS_TYPE_INTEGER(ytype)) {
if (!(tempx = GMPy_MPZ_From_IntegerWithType(x, xtype, context)) ||
!(tempy = GMPy_MPZ_From_IntegerWithType(y, ytype, context))) {
/* LCOV_EXCL_START */
Py_XDECREF((PyObject*)tempx);
Py_XDECREF((PyObject*)tempy);
Py_DECREF((PyObject*)result);
return NULL;
/* LCOV_EXCL_STOP */
}
if (mpz_sgn(tempy->z) == 0) {
ZERO_ERROR("division or modulo by zero");
Py_XDECREF((PyObject*)tempx);
Py_XDECREF((PyObject*)tempy);
Py_DECREF((PyObject*)result);
return NULL;
}
mpq_init(tempq);
mpq_set_num(tempq, tempx->z);
mpq_set_den(tempq, tempy->z);
mpq_canonicalize(tempq);
mpfr_clear_flags();
result->rc = mpfr_set_q(result->f, tempq, GET_MPFR_ROUND(context));
mpq_clear(tempq);
Py_DECREF((PyObject*)tempx);
Py_DECREF((PyObject*)tempy);
_GMPy_MPFR_Cleanup(&result, context);
return (PyObject*)result;
}
/* LCOV_EXCL_START */
Py_DECREF((PyObject*)result);
TYPE_ERROR("div() argument type not supported");
return NULL;
/* LCOV_EXCL_STOP */
}
static PyObject *
GMPy_Rational_TrueDivWithType(PyObject *x, int xtype, PyObject *y, int ytype,
CTXT_Object *context)
{
MPQ_Object *result = NULL, *tempx = NULL, *tempy = NULL;
CHECK_CONTEXT(context);
if (!(result = GMPy_MPQ_New(context)))
return NULL;
if (IS_TYPE_MPQ(xtype) && IS_TYPE_MPQ(ytype)) {
if (mpq_sgn(MPQ(y)) == 0) {
ZERO_ERROR("division or modulo by zero");
Py_XDECREF((PyObject*)tempx);
Py_XDECREF((PyObject*)tempy);
Py_DECREF((PyObject*)result);
return NULL;
}
GMPY_MAYBE_BEGIN_ALLOW_THREADS(context);
mpq_div(result->q, MPQ(x), MPQ(y));
GMPY_MAYBE_END_ALLOW_THREADS(context);
return (PyObject*)result;
}
if (IS_TYPE_RATIONAL(xtype) && IS_TYPE_RATIONAL(ytype)) {
if (!(tempx = GMPy_MPQ_From_RationalWithType(x, xtype, context)) ||
!(tempy = GMPy_MPQ_From_RationalWithType(y, ytype, context))) {
/* LCOV_EXCL_START */
Py_XDECREF((PyObject*)tempx);
Py_XDECREF((PyObject*)tempy);
Py_DECREF((PyObject*)result);
return NULL;
/* LCOV_EXCL_STOP */
}
if (mpq_sgn(tempy->q) == 0) {
ZERO_ERROR("division or modulo by zero");
Py_XDECREF((PyObject*)tempx);
Py_XDECREF((PyObject*)tempy);
Py_DECREF((PyObject*)result);
return NULL;
}
GMPY_MAYBE_BEGIN_ALLOW_THREADS(context);
mpq_div(result->q, tempx->q, tempy->q);
GMPY_MAYBE_END_ALLOW_THREADS(context);
Py_DECREF((PyObject*)tempx);
Py_DECREF((PyObject*)tempy);
return (PyObject*)result;
}
/* LCOV_EXCL_START */
Py_DECREF((PyObject*)result);
TYPE_ERROR("div() argument type not supported");
return NULL;
/* LCOV_EXCL_STOP */
}
/* Attempt true division of two numbers and return an mpfr. The code path is
* optimized by checking for mpfr objects first. Returns Py_NotImplemented if
* both objects are not valid reals. */
static PyObject *
GMPy_Real_TrueDivWithType(PyObject *x, int xtype, PyObject *y, int ytype,
CTXT_Object *context)
{
MPFR_Object *result = NULL;
CHECK_CONTEXT(context);
if (!(result = GMPy_MPFR_New(0, context))) {
/* LCOV_EXCL_START */
return NULL;
/* LCOV_EXCL_STOP */
}
if (IS_TYPE_MPFR(xtype) && IS_TYPE_MPFR(ytype)) {
mpfr_clear_flags();
result->rc = mpfr_div(result->f, MPFR(x), MPFR(y), GET_MPFR_ROUND(context));
_GMPy_MPFR_Cleanup(&result, context);
return (PyObject*)result;
}
if (IS_TYPE_REAL(xtype) && IS_TYPE_REAL(ytype)) {
MPFR_Object *tempx = NULL, *tempy = NULL;
if (!(tempx = GMPy_MPFR_From_RealWithType(x, xtype, 1, context)) ||
!(tempy = GMPy_MPFR_From_RealWithType(y, ytype, 1, context))) {
/* LCOV_EXCL_START */
Py_XDECREF((PyObject*)tempx);
Py_XDECREF((PyObject*)tempy);
Py_DECREF((PyObject*)result);
return NULL;
/* LCOV_EXCL_STOP */
}
mpfr_clear_flags();
result->rc = mpfr_div(result->f, tempx->f, tempy->f, GET_MPFR_ROUND(context));
Py_DECREF((PyObject*)tempx);
Py_DECREF((PyObject*)tempy);
_GMPy_MPFR_Cleanup(&result, context);
return (PyObject*)result;
}
/* LCOV_EXCL_START */
Py_DECREF((PyObject*)result);
TYPE_ERROR("div() argument type not supported");
return NULL;
/* LCOV_EXCL_STOP */
}
static PyObject *
GMPy_Complex_TrueDivWithType(PyObject *x, int xtype, PyObject *y, int ytype,
CTXT_Object *context)
{
MPC_Object *result = NULL;
CHECK_CONTEXT(context);
if (!(result = GMPy_MPC_New(0, 0, context))) {
/* LCOV_EXCL_START */
return NULL;
/* LCOV_EXCL_STOP */
}
if (IS_TYPE_MPC(xtype) && IS_TYPE_MPC(ytype)) {
if (MPC_IS_ZERO_P(y)) {
context->ctx.divzero = 1;
if (context->ctx.traps & TRAP_DIVZERO) {
GMPY_DIVZERO("'mpc' division by zero");
Py_DECREF((PyObject*)result);
return NULL;
}
}
GMPY_MAYBE_BEGIN_ALLOW_THREADS(context);
result->rc = mpc_div(result->c, MPC(x), MPC(y), GET_MPC_ROUND(context));
GMPY_MAYBE_END_ALLOW_THREADS(context);
_GMPy_MPC_Cleanup(&result, context);
return (PyObject*)result;
}
if (IS_TYPE_COMPLEX(xtype) && IS_TYPE_COMPLEX(ytype)) {
MPC_Object *tempx = NULL, *tempy = NULL;
if (!(tempx = GMPy_MPC_From_ComplexWithType(x, xtype, 1, 1, context)) ||
!(tempy = GMPy_MPC_From_ComplexWithType(y, ytype, 1, 1, context))) {
/* LCOV_EXCL_START */
Py_XDECREF((PyObject*)tempx);
Py_XDECREF((PyObject*)tempy);
Py_DECREF((PyObject*)result);
return NULL;
/* LCOV_EXCL_STOP */
}
result->rc = mpc_div(result->c, tempx->c, tempy->c, GET_MPC_ROUND(context));
Py_DECREF((PyObject*)tempx);
Py_DECREF((PyObject*)tempy);
_GMPy_MPC_Cleanup(&result, context);
return (PyObject*)result;
}
/* LCOV_EXCL_START */
Py_DECREF((PyObject*)result);
TYPE_ERROR("div() argument type not supported");
return NULL;
/* LCOV_EXCL_STOP */
}
/* Implement all the slot methods here. */
static PyObject *
GMPy_Number_TrueDiv_Slot(PyObject *x, PyObject *y)
{
int xtype = GMPy_ObjectType(x);
int ytype = GMPy_ObjectType(y);
if (IS_TYPE_INTEGER(xtype) && IS_TYPE_INTEGER(ytype))
return GMPy_Integer_TrueDivWithType(x, xtype, y, ytype, NULL);
if (IS_TYPE_RATIONAL(xtype) && IS_TYPE_RATIONAL(ytype))
return GMPy_Rational_TrueDivWithType(x, xtype, y, ytype, NULL);
if (IS_TYPE_REAL(xtype) && IS_TYPE_REAL(ytype))
return GMPy_Real_TrueDivWithType(x, xtype, y, ytype, NULL);
if (IS_TYPE_COMPLEX(xtype) && IS_TYPE_COMPLEX(ytype))
return GMPy_Complex_TrueDivWithType(x, xtype, y, ytype, NULL);
Py_RETURN_NOTIMPLEMENTED;
}
PyDoc_STRVAR(GMPy_doc_truediv,
"div(x, y, /) -> mpz | mpq | mpfr | mpc\n\n"
"Return x / y; uses true division.");
static PyObject *
GMPy_Number_TrueDiv(PyObject *x, PyObject *y, CTXT_Object *context)
{
int xtype = GMPy_ObjectType(x);
int ytype = GMPy_ObjectType(y);
if (IS_TYPE_INTEGER(xtype) && IS_TYPE_INTEGER(ytype))
return GMPy_Integer_TrueDivWithType(x, xtype, y, ytype, NULL);
if (IS_TYPE_RATIONAL(xtype) && IS_TYPE_RATIONAL(ytype))
return GMPy_Rational_TrueDivWithType(x, xtype, y, ytype, NULL);
if (IS_TYPE_REAL(xtype) && IS_TYPE_REAL(ytype))
return GMPy_Real_TrueDivWithType(x, xtype, y, ytype, NULL);
if (IS_TYPE_COMPLEX(xtype) && IS_TYPE_COMPLEX(ytype))
return GMPy_Complex_TrueDivWithType(x, xtype, y, ytype, NULL);
TYPE_ERROR("div() argument type not supported");
return NULL;
}
PyDoc_STRVAR(GMPy_doc_context_truediv,
"context.div(x, y, /) -> mpz | mpq | mpfr | mpc\n\n"
"Return x / y; uses true division.");
static PyObject *
GMPy_Context_TrueDiv(PyObject *self, PyObject *args)
{
CTXT_Object *context = NULL;
if (PyTuple_GET_SIZE(args) != 2) {
TYPE_ERROR("div() requires 2 arguments.");
return NULL;
}
if (self && CTXT_Check(self)) {
context = (CTXT_Object*)self;
}
else {
CHECK_CONTEXT(context);
}
return GMPy_Number_TrueDiv(PyTuple_GET_ITEM(args, 0),
PyTuple_GET_ITEM(args, 1),
context);
}
././@PaxHeader 0000000 0000000 0000000 00000000026 00000000000 010213 x ustar 00 22 mtime=1710307256.0
gmpy2-2.2.1/src/gmpy2_truediv.h 0000644 0001750 0001750 00000005345 14574233670 015004 0 ustar 00case case /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* gmpy2_truediv.h *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Python interface to the GMP, MPFR, and MPC multiple precision *
* libraries. *
* *
* Copyright 2000 - 2009 Alex Martelli *
* *
* Copyright 2008 - 2024 Case Van Horsen *
* *
* This file is part of GMPY2. *
* *
* GMPY2 is free software: you can redistribute it and/or modify it under *
* the terms of the GNU Lesser General Public License as published by the *
* Free Software Foundation, either version 3 of the License, or (at your *
* option) any later version. *
* *
* GMPY2 is distributed in the hope that it will be useful, but WITHOUT *
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or *
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public *
* License for more details. *
* *
* You should have received a copy of the GNU Lesser General Public *
* License along with GMPY2; if not, see *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
#ifndef GMPY2_TRUEDIV_H
#define GMPY2_TRUEDIV_H
#ifdef __cplusplus
extern "C" {
#endif
/* Public API */
static PyObject * GMPy_Number_TrueDiv(PyObject *x, PyObject *y, CTXT_Object *context);
/* Private API */
static PyObject * GMPy_Integer_TrueDivWithType(PyObject *x, int xtype, PyObject *y, int ytype, CTXT_Object *context);
static PyObject * GMPy_Rational_TrueDivWithType(PyObject *x, int xtype, PyObject *y, int ytype, CTXT_Object *context);
static PyObject * GMPy_Real_TrueDivWithType(PyObject *x, int xtype, PyObject *y, int ytype, CTXT_Object *context);
static PyObject * GMPy_Complex_TrueDivWithType(PyObject *x, int xtype, PyObject *y, int ytype, CTXT_Object *context);
static PyObject * GMPy_Number_TrueDiv_Slot(PyObject *x, PyObject *y);
static PyObject * GMPy_Context_TrueDiv(PyObject *self, PyObject *args);
#ifdef __cplusplus
}
#endif
#endif
././@PaxHeader 0000000 0000000 0000000 00000000026 00000000000 010213 x ustar 00 22 mtime=1710307256.0
gmpy2-2.2.1/src/gmpy2_types.h 0000644 0001750 0001750 00000007655 14574233670 014474 0 ustar 00case case /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* gmpy2_types.h *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Python interface to the GMP, MPFR, and MPC multiple precision *
* libraries. *
* *
* Copyright 2000 - 2009 Alex Martelli *
* *
* Copyright 2008 - 2024 Case Van Horsen *
* *
* This file is part of GMPY2. *
* *
* GMPY2 is free software: you can redistribute it and/or modify it under *
* the terms of the GNU Lesser General Public License as published by the *
* Free Software Foundation, either version 3 of the License, or (at your *
* option) any later version. *
* *
* GMPY2 is distributed in the hope that it will be useful, but WITHOUT *
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or *
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public *
* License for more details. *
* *
* You should have received a copy of the GNU Lesser General Public *
* License along with GMPY2; if not, see *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
#ifndef GMPY_TYPES_H
#define GMPY_TYPES_H
#ifdef __cplusplus
extern "C" {
#endif
typedef struct {
PyObject_HEAD
mpz_t z;
Py_hash_t hash_cache;
} MPZ_Object;
typedef struct {
PyObject_HEAD
mpz_t z;
} XMPZ_Object;
typedef struct {
PyObject_HEAD
mpq_t q;
Py_hash_t hash_cache;
} MPQ_Object;
typedef struct {
PyObject_HEAD
mpfr_t f;
Py_hash_t hash_cache;
int rc;
} MPFR_Object;
typedef struct {
PyObject_HEAD
mpc_t c;
Py_hash_t hash_cache;
int rc;
} MPC_Object;
typedef struct {
PyObject_HEAD
gmp_randstate_t state;
} RandomState_Object;
typedef struct {
mpfr_prec_t mpfr_prec; /* current precision in bits, for MPFR */
mpfr_rnd_t mpfr_round; /* current rounding mode for float (MPFR) */
mpfr_exp_t emax; /* maximum exponent */
mpfr_exp_t emin; /* minimum exponent */
int subnormalize; /* if 1, subnormalization is performed */
int underflow; /* did an underflow occur? */
int overflow; /* did an overflow occur? */
int inexact; /* was the result inexact? */
int invalid; /* invalid operation (i.e. NaN)? */
int erange; /* did a range error occur? */
int divzero; /* divided by zero? */
int traps; /* if 0, do not trap any exceptions */
/* if not 0, then raise traps per bits above */
mpfr_prec_t real_prec; /* current precision in bits, for Re(MPC) */
mpfr_prec_t imag_prec; /* current precision in bits, for Im(MPC) */
mpfr_rnd_t real_round; /* current rounding mode for Re(MPC) */
mpfr_rnd_t imag_round; /* current rounding mode for Im(MPC) */
int allow_complex; /* if 1, allow mpfr functions to return an mpc */
int rational_division; /* if 1, mpz/mpz returns an mpq result */
int allow_release_gil; /* if 1, release GIL for mpz operations */
} gmpy_context;
typedef struct {
PyObject_HEAD
gmpy_context ctx;
} CTXT_Object;
#ifdef __cplusplus
}
#endif
#endif
././@PaxHeader 0000000 0000000 0000000 00000000026 00000000000 010213 x ustar 00 22 mtime=1710307256.0
gmpy2-2.2.1/src/gmpy2_vector.c 0000644 0001750 0001750 00000014152 14574233670 014613 0 ustar 00case case /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* gmpy2_vector.c *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Python interface to the GMP, MPFR, and MPC multiple precision *
* libraries. *
* *
* Copyright 2000 - 2009 Alex Martelli *
* *
* Copyright 2008 - 2024 Case Van Horsen *
* *
* This file is part of GMPY2. *
* *
* GMPY2 is free software: you can redistribute it and/or modify it under *
* the terms of the GNU Lesser General Public License as published by the *
* Free Software Foundation, either version 3 of the License, or (at your *
* option) any later version. *
* *
* GMPY2 is distributed in the hope that it will be useful, but WITHOUT *
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or *
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public *
* License for more details. *
* *
* You should have received a copy of the GNU Lesser General Public *
* License along with GMPY2; if not, see *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
/* The following code was a test case for creating a gmpy2 function that would
* apply an MPFR function to all the elements of a list. It was slightly faster
* than map(gmpy2.list, <>) but not enough to justify the effort. The
* code is left for possible future use.
*/
PyDoc_STRVAR(GMPy_doc_function_vector,
"vector(iterable, /) -> list\n\n"
"Template for applying a function to an iterable.");
PyDoc_STRVAR(GMPy_doc_context_vector,
"vector(iterable, /) -> list\n\n"
"Template for applying a function to an iterable.");
static PyObject *
GMPy_Context_Vector(PyObject *self, PyObject *other)
{
PyObject *result, *tempres;
Py_ssize_t i, seq_length;
CTXT_Object *context = NULL;
if (self && CTXT_Check(self)) {
context = (CTXT_Object*)self;
}
else {
CHECK_CONTEXT(context);
}
if (!(other = PySequence_List(other))) {
TYPE_ERROR("argument must be an iterable");
return NULL;
}
/* other contains a new list containing all the values from the
* iterable. Create a list to store the results.
*/
seq_length = PyList_GET_SIZE(other);
if (!(result = PyList_New(seq_length))) {
Py_DECREF(other);
return NULL;
}
/* Iterate through the list. */
for (i=0; i < seq_length; i++) {
if (!(tempres = GMPy_Number_Sin(PyList_GET_ITEM(other, i), context))) {
Py_DECREF(other);
Py_DECREF(result);
TYPE_ERROR("all items in iterable must be numbers");
return NULL;
}
if (PyList_SetItem(result, i, tempres) < 0) {
Py_DECREF(other);
Py_DECREF(result);
return NULL;
}
}
Py_DECREF(other);
return (PyObject*)result;
}
PyDoc_STRVAR(GMPy_doc_function_vector2,
"vector2(iterable, iterable, /) -> list\n\n"
"Template for applying a function to a pair of iterables.");
PyDoc_STRVAR(GMPy_doc_context_vector2,
"vector2(iterable, /) -> list\n\n"
"Template for applying a function to a pair of iterables.");
static PyObject *
GMPy_Context_Vector2(PyObject *self, PyObject *args)
{
PyObject *arg1, *arg2, *result;
MPFR_Object *tempres;
Py_ssize_t i, seq_length;
CTXT_Object *context = NULL;
if (self && CTXT_Check(self)) {
context = (CTXT_Object*)self;
}
else {
CHECK_CONTEXT(context);
}
if (PyTuple_GET_SIZE(args) != 2) {
TYPE_ERROR("vector2() requires 2 arguments");
return NULL;
}
if (!(arg1 = PySequence_List(PyTuple_GET_ITEM(args, 0)))) {
TYPE_ERROR("argument must be an iterable");
return NULL;
}
if (!(arg2 = PySequence_List(PyTuple_GET_ITEM(args, 1)))) {
Py_DECREF(arg1);
TYPE_ERROR("argument must be an iterable");
return NULL;
}
/* other contains a new list containing all the values from the
* iterable. Create a list to store the results.
*/
if (PyList_GET_SIZE(arg1) != PyList_GET_SIZE(arg2)) {
Py_DECREF(arg1);
Py_DECREF(arg2);
TYPE_ERROR("arguments must be the same length");
return NULL;
}
seq_length = PyList_GET_SIZE(arg1);
if (!(result = PyList_New(seq_length))) {
Py_DECREF(arg1);
Py_DECREF(arg2);
return NULL;
}
/* Iterate through the list. */
for (i=0; i < seq_length; i++) {
//~ if (!(tempres = GMPy_Number_Mul(PyList_GET_ITEM(arg1, i),
//~ PyList_GET_ITEM(arg2, i),
//~ context))) {
//~ Py_DECREF(arg1);
//~ Py_DECREF(arg2);
//~ Py_DECREF(result);
//~ TYPE_ERROR("all items in iterable must be numbers");
//~ return NULL;
//~ }
tempres = GMPy_MPFR_New(0, context);
tempres->rc = mpfr_mul(tempres->f,
MPFR(PyList_GET_ITEM(arg1, i)),
MPFR(PyList_GET_ITEM(arg2, i)),
GET_MPFR_ROUND(context));
if (PyList_SetItem(result, i, (PyObject*)tempres) < 0) {
Py_DECREF(arg1);
Py_DECREF(arg2);
Py_DECREF(result);
return NULL;
}
}
Py_DECREF(arg1);
Py_DECREF(arg2);
return (PyObject*)result;
}
././@PaxHeader 0000000 0000000 0000000 00000000026 00000000000 010213 x ustar 00 22 mtime=1710307256.0
gmpy2-2.2.1/src/gmpy2_vector.h 0000644 0001750 0001750 00000004220 14574233670 014613 0 ustar 00case case /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* gmpy2_vector.h *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Python interface to the GMP, MPFR, and MPC multiple precision *
* libraries. *
* *
* Copyright 2000 - 2009 Alex Martelli *
* *
* Copyright 2008 - 2024 Case Van Horsen *
* *
* This file is part of GMPY2. *
* *
* GMPY2 is free software: you can redistribute it and/or modify it under *
* the terms of the GNU Lesser General Public License as published by the *
* Free Software Foundation, either version 3 of the License, or (at your *
* option) any later version. *
* *
* GMPY2 is distributed in the hope that it will be useful, but WITHOUT *
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or *
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public *
* License for more details. *
* *
* You should have received a copy of the GNU Lesser General Public *
* License along with GMPY2; if not, see *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
#ifndef GMPY_VECTOR_H
#define GMPY_VECTOR_H
#ifdef __cplusplus
extern "C" {
#endif
static PyObject * GMPy_Context_Vector(PyObject *self, PyObject *other);
static PyObject * GMPy_Context_Vector2(PyObject *self, PyObject *args);
#ifdef __cplusplus
}
#endif
#endif
././@PaxHeader 0000000 0000000 0000000 00000000026 00000000000 010213 x ustar 00 22 mtime=1721370662.0
gmpy2-2.2.1/src/gmpy2_xmpz.c 0000644 0001750 0001750 00000016774 14646404046 014320 0 ustar 00case case /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* gmpy2_xmpz.c *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Python interface to the GMP, MPFR, and MPC multiple precision *
* libraries. *
* *
* Copyright 2000 - 2009 Alex Martelli *
* *
* Copyright 2008 - 2024 Case Van Horsen *
* *
* This file is part of GMPY2. *
* *
* GMPY2 is free software: you can redistribute it and/or modify it under *
* the terms of the GNU Lesser General Public License as published by the *
* Free Software Foundation, either version 3 of the License, or (at your *
* option) any later version. *
* *
* GMPY2 is distributed in the hope that it will be useful, but WITHOUT *
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or *
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public *
* License for more details. *
* *
* You should have received a copy of the GNU Lesser General Public *
* License along with GMPY2; if not, see *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
PyDoc_STRVAR(GMPy_doc_xmpz,
"xmpz(n=0, /)\n"
"xmpz(s, /, base=0)\n\n"
"Return a mutable integer constructed from a numeric value n\n"
"or a string s made of digits in the given base. Every input,\n"
"that is accepted by the `mpz` type constructor is also accepted.\n\n"
"Note: This type can be faster when used for augmented assignment\n"
"(+=, -=, etc), but `xmpz` objects cannot be used as dictionary keys.");
static PyNumberMethods GMPy_XMPZ_number_methods =
{
.nb_add = (binaryfunc) GMPy_Number_Add_Slot,
.nb_subtract = (binaryfunc) GMPy_Number_Sub_Slot,
.nb_multiply = (binaryfunc) GMPy_Number_Mul_Slot,
.nb_remainder = (binaryfunc) GMPy_Number_Mod_Slot,
.nb_divmod = (binaryfunc) GMPy_Number_DivMod_Slot,
.nb_power = (ternaryfunc) GMPy_Number_Pow_Slot,
.nb_negative = (unaryfunc) GMPy_XMPZ_Neg_Slot,
.nb_positive = (unaryfunc) GMPy_XMPZ_Pos_Slot,
.nb_absolute = (unaryfunc) GMPy_XMPZ_Abs_Slot,
.nb_bool = (inquiry) GMPy_XMPZ_NonZero_Slot,
.nb_invert = (unaryfunc) GMPy_XMPZ_Com_Slot,
.nb_lshift = (binaryfunc) GMPy_MPZ_Lshift_Slot,
.nb_rshift = (binaryfunc) GMPy_MPZ_Rshift_Slot,
.nb_and = (binaryfunc) GMPy_MPZ_And_Slot,
.nb_xor = (binaryfunc) GMPy_MPZ_Xor_Slot,
.nb_or = (binaryfunc) GMPy_MPZ_Ior_Slot,
.nb_int = (unaryfunc) GMPy_MPZ_Int_Slot,
.nb_float = (unaryfunc) GMPy_MPZ_Float_Slot,
.nb_inplace_add = (binaryfunc) GMPy_XMPZ_IAdd_Slot,
.nb_inplace_subtract = (binaryfunc) GMPy_XMPZ_ISub_Slot,
.nb_inplace_multiply = (binaryfunc) GMPy_XMPZ_IMul_Slot,
.nb_inplace_remainder = (binaryfunc) GMPy_XMPZ_IRem_Slot,
.nb_inplace_power = (ternaryfunc) GMPy_XMPZ_IPow_Slot,
.nb_inplace_lshift = (binaryfunc) GMPy_XMPZ_ILshift_Slot,
.nb_inplace_rshift = (binaryfunc) GMPy_XMPZ_IRshift_Slot,
.nb_inplace_and = (binaryfunc) GMPy_XMPZ_IAnd_Slot,
.nb_inplace_xor = (binaryfunc) GMPy_XMPZ_IXor_Slot,
.nb_inplace_or = (binaryfunc) GMPy_XMPZ_IIor_Slot,
.nb_floor_divide = (binaryfunc) GMPy_Number_FloorDiv_Slot,
.nb_true_divide = (binaryfunc) GMPy_Number_TrueDiv_Slot,
.nb_inplace_floor_divide = (binaryfunc) GMPy_XMPZ_IFloorDiv_Slot,
.nb_index = (unaryfunc) GMPy_MPZ_Int_Slot,
};
static PyMappingMethods GMPy_XMPZ_mapping_methods = {
(lenfunc)GMPy_XMPZ_Method_Length,
(binaryfunc)GMPy_XMPZ_Method_SubScript,
(objobjargproc)GMPy_XMPZ_Method_AssignSubScript
};
static PyGetSetDef GMPy_XMPZ_getseters[] =
{
{ "numerator", (getter)GMPy_XMPZ_Attrib_GetNumer, NULL,
"the numerator of a rational number in lowest terms", NULL },
{ "denominator", (getter)GMPy_XMPZ_Attrib_GetDenom, NULL,
"the denominator of a rational number in lowest terms", NULL },
{ "real", (getter)GMPy_XMPZ_Attrib_GetReal, NULL,
"the real part of a complex number", NULL },
{ "denominator", (getter)GMPy_XMPZ_Attrib_GetImag, NULL,
"the imaginary part of a complex number", NULL },
{NULL}
};
static PyMethodDef GMPy_XMPZ_methods [] =
{
{ "__format__", GMPy_MPZ_Format, METH_VARARGS, GMPy_doc_mpz_format },
{ "__sizeof__", GMPy_XMPZ_Method_SizeOf, METH_NOARGS, GMPy_doc_xmpz_method_sizeof },
{ "bit_clear", GMPy_MPZ_bit_clear_method, METH_O, doc_bit_clear_method },
{ "bit_flip", GMPy_MPZ_bit_flip_method, METH_O, doc_bit_flip_method },
{ "bit_length", GMPy_MPZ_bit_length_method, METH_NOARGS, doc_bit_length_method },
{ "bit_count", GMPy_MPZ_bit_count_method, METH_NOARGS, doc_bit_count_method },
{ "bit_scan0", (PyCFunction)GMPy_MPZ_bit_scan0_method, METH_FASTCALL, doc_bit_scan0_method },
{ "bit_scan1", (PyCFunction)GMPy_MPZ_bit_scan1_method, METH_FASTCALL, doc_bit_scan1_method },
{ "bit_set", GMPy_MPZ_bit_set_method, METH_O, doc_bit_set_method },
{ "bit_test", GMPy_MPZ_bit_test_method, METH_O, doc_bit_test_method },
{ "conjugate", GMPy_MP_Method_Conjugate, METH_NOARGS, GMPy_doc_mp_method_conjugate },
{ "copy", GMPy_XMPZ_Method_Copy, METH_NOARGS, GMPy_doc_xmpz_method_copy },
{ "digits", GMPy_XMPZ_Digits_Method, METH_VARARGS, GMPy_doc_mpz_digits_method },
{ "iter_bits", (PyCFunction)GMPy_XMPZ_Method_IterBits, METH_VARARGS | METH_KEYWORDS, GMPy_doc_xmpz_method_iter_bits },
{ "iter_clear", (PyCFunction)GMPy_XMPZ_Method_IterClear, METH_VARARGS | METH_KEYWORDS, GMPy_doc_xmpz_method_iter_clear },
{ "iter_set", (PyCFunction)GMPy_XMPZ_Method_IterSet, METH_VARARGS | METH_KEYWORDS, GMPy_doc_xmpz_method_iter_set },
{ "make_mpz", GMPy_XMPZ_Method_MakeMPZ, METH_NOARGS, GMPy_doc_xmpz_method_make_mpz },
{ "num_digits", (PyCFunction)GMPy_MPZ_Method_NumDigits, METH_FASTCALL, GMPy_doc_mpz_method_num_digits },
{ "num_limbs", GMPy_XMPZ_Method_NumLimbs, METH_NOARGS, GMPy_doc_xmpz_method_num_limbs },
{ "limbs_read", GMPy_XMPZ_Method_LimbsRead, METH_NOARGS, GMPy_doc_xmpz_method_limbs_read },
{ "limbs_write", GMPy_XMPZ_Method_LimbsWrite, METH_O, GMPy_doc_xmpz_method_limbs_write },
{ "limbs_modify", GMPy_XMPZ_Method_LimbsModify, METH_O, GMPy_doc_xmpz_method_limbs_modify },
{ "limbs_finish", GMPy_XMPZ_Method_LimbsFinish, METH_O, GMPy_doc_xmpz_method_limbs_finish },
{ NULL }
};
static PyTypeObject XMPZ_Type =
{
PyVarObject_HEAD_INIT(NULL, 0)
.tp_name = "gmpy2.xmpz",
.tp_basicsize = sizeof(XMPZ_Object),
.tp_dealloc = (destructor) GMPy_XMPZ_Dealloc,
.tp_repr = (reprfunc) GMPy_XMPZ_Repr_Slot,
.tp_as_number = &GMPy_XMPZ_number_methods,
.tp_as_mapping = &GMPy_XMPZ_mapping_methods,
.tp_str = (reprfunc) GMPy_XMPZ_Str_Slot,
.tp_flags = Py_TPFLAGS_DEFAULT,
.tp_doc = GMPy_doc_xmpz,
.tp_richcompare = (richcmpfunc)&GMPy_RichCompare_Slot,
.tp_methods = GMPy_XMPZ_methods,
.tp_getset = GMPy_XMPZ_getseters,
.tp_new = GMPy_XMPZ_NewInit,
};
././@PaxHeader 0000000 0000000 0000000 00000000026 00000000000 010213 x ustar 00 22 mtime=1710307256.0
gmpy2-2.2.1/src/gmpy2_xmpz.h 0000644 0001750 0001750 00000004654 14574233670 014322 0 ustar 00case case /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* gmpy2_xmpz.h *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Python interface to the GMP, MPFR, and MPC multiple precision *
* libraries. *
* *
* Copyright 2000 - 2009 Alex Martelli *
* *
* Copyright 2008 - 2024 Case Van Horsen *
* *
* This file is part of GMPY2. *
* *
* GMPY2 is free software: you can redistribute it and/or modify it under *
* the terms of the GNU Lesser General Public License as published by the *
* Free Software Foundation, either version 3 of the License, or (at your *
* option) any later version. *
* *
* GMPY2 is distributed in the hope that it will be useful, but WITHOUT *
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or *
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public *
* License for more details. *
* *
* You should have received a copy of the GNU Lesser General Public *
* License along with GMPY2; if not, see *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
#ifndef GMPY_XMPZ_H
#define GMPY_XMPZ_H
#ifdef __cplusplus
extern "C" {
#endif
static PyTypeObject XMPZ_Type;
#define XMPZ(obj) (((XMPZ_Object*)(obj))->z)
#define XMPZ_Check(v) (((PyObject*)v)->ob_type == &XMPZ_Type)
#define CHECK_MPZANY(v) (MPZ_Check(v) || XMPZ_Check(v))
typedef struct {
PyObject_HEAD
XMPZ_Object *bitmap;
mp_bitcnt_t start, stop;
int iter_type;
} GMPy_Iter_Object;
static PyTypeObject GMPy_Iter_Type;
#define GMPy_Iter_Check(v) (((PyObject*)v)->ob_type == &GMPy_Iter_Type)
#ifdef __cplusplus
}
#endif
#endif
././@PaxHeader 0000000 0000000 0000000 00000000026 00000000000 010213 x ustar 00 22 mtime=1710307256.0
gmpy2-2.2.1/src/gmpy2_xmpz_inplace.c 0000644 0001750 0001750 00000027132 14574233670 016004 0 ustar 00case case /* * * * * * * * * * * * * * * * * * * * ** * * * * * * * * * * * * * * * *
* gmpy2_xmpz_inplace.c *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Python interface to the GMP, MPFR, and MPC multiple precision *
* libraries. *
* *
* Copyright 2000 - 2009 Alex Martelli *
* *
* Copyright 2008 - 2024 Case Van Horsen *
* *
* This file is part of GMPY2. *
* *
* GMPY2 is free software: you can redistribute it and/or modify it under *
* the terms of the GNU Lesser General Public License as published by the *
* Free Software Foundation, either version 3 of the License, or (at your *
* option) any later version. *
* *
* GMPY2 is distributed in the hope that it will be useful, but WITHOUT *
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or *
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public *
* License for more details. *
* *
* You should have received a copy of the GNU Lesser General Public *
* License along with GMPY2; if not, see *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
/* Provides inplace mutating operations for xmpz. */
#include
/* Inplace xmpz addition. */
static PyObject *
GMPy_XMPZ_IAdd_Slot(PyObject *self, PyObject *other)
{
/* Try to make mpz + small_int faster */
CTXT_Object *context = NULL;
CHECK_CONTEXT(context);
int ytype = GMPy_ObjectType(other);
if (IS_TYPE_PyInteger(ytype)) {
int error;
long temp = PyLong_AsLongAndOverflow(other, &error);
if (!error) {
if (temp >= 0) {
mpz_add_ui(MPZ(self), MPZ(self), temp);
}
else {
mpz_sub_ui(MPZ(self), MPZ(self), -temp);
}
}
else {
mpz_t tempz;
mpz_init(tempz);
mpz_set_PyLong(tempz, other);
GMPY_MAYBE_BEGIN_ALLOW_THREADS(context);
mpz_add(MPZ(self), MPZ(self), tempz);
GMPY_MAYBE_END_ALLOW_THREADS(context);
mpz_clear(tempz);
}
Py_INCREF(self);
return self;
}
if (IS_TYPE_MPZANY(ytype)) {
GMPY_MAYBE_BEGIN_ALLOW_THREADS(context);
mpz_add(MPZ(self), MPZ(self), MPZ(other));
GMPY_MAYBE_END_ALLOW_THREADS(context);
Py_INCREF(self);
return self;
}
Py_RETURN_NOTIMPLEMENTED;
}
/* Inplace mpz subtraction.
*/
static PyObject *
GMPy_XMPZ_ISub_Slot(PyObject *self, PyObject *other)
{
CTXT_Object *context = NULL;
CHECK_CONTEXT(context);
int ytype = GMPy_ObjectType(other);
if (IS_TYPE_PyInteger(ytype)) {
int error;
long temp = PyLong_AsLongAndOverflow(other, &error);
if (!error) {
if (temp >= 0) {
mpz_sub_ui(MPZ(self), MPZ(self), temp);
}
else {
mpz_add_ui(MPZ(self), MPZ(self), -temp);
}
}
else {
mpz_t tempz;
mpz_init(tempz);
mpz_set_PyLong(tempz, other);
GMPY_MAYBE_BEGIN_ALLOW_THREADS(context);
mpz_sub(MPZ(self), MPZ(self), tempz);
GMPY_MAYBE_END_ALLOW_THREADS(context);
mpz_clear(tempz);
}
Py_INCREF(self);
return self;
}
if (IS_TYPE_MPZANY(ytype)) {
GMPY_MAYBE_BEGIN_ALLOW_THREADS(context);
mpz_sub(MPZ(self), MPZ(self), MPZ(other));
GMPY_MAYBE_END_ALLOW_THREADS(context);
Py_INCREF(self);
return self;
}
Py_RETURN_NOTIMPLEMENTED;
}
/* Inplace xmpz multiplication.
*/
static PyObject *
GMPy_XMPZ_IMul_Slot(PyObject *self, PyObject *other)
{
CTXT_Object *context = NULL;
CHECK_CONTEXT(context);
int ytype = GMPy_ObjectType(other);
if (IS_TYPE_PyInteger(ytype)) {
int error;
long temp = PyLong_AsLongAndOverflow(other, &error);
if (!error) {
mpz_mul_si(MPZ(self), MPZ(self), temp);
}
else {
mpz_t tempz;
mpz_init(tempz);
mpz_set_PyLong(tempz, other);
GMPY_MAYBE_BEGIN_ALLOW_THREADS(context);
mpz_mul(MPZ(self), MPZ(self), tempz);
GMPY_MAYBE_END_ALLOW_THREADS(context);
mpz_clear(tempz);
}
Py_INCREF(self);
return self;
}
if (IS_TYPE_MPZANY(ytype)) {
GMPY_MAYBE_BEGIN_ALLOW_THREADS(context);
mpz_mul(MPZ(self), MPZ(self), MPZ(other));
GMPY_MAYBE_END_ALLOW_THREADS(context);
Py_INCREF(self);
return self;
}
Py_RETURN_NOTIMPLEMENTED;
}
/* Pympany_floordiv follows the // semantics from Python 3.x. The result is
* an mpz when the arguments are mpz or mpq, but the result is an mpf when
* the arguments are mpf.
*/
static PyObject *
GMPy_XMPZ_IFloorDiv_Slot(PyObject *self, PyObject *other)
{
CTXT_Object *context = NULL;
CHECK_CONTEXT(context);
int ytype = GMPy_ObjectType(other);
if (IS_TYPE_PyInteger(ytype)) {
int error;
long temp = PyLong_AsLongAndOverflow(other, &error);
if (!error) {
if (temp == 0) {
ZERO_ERROR("xmpz division by zero");
return NULL;
}
else if (temp > 0) {
mpz_fdiv_q_ui(MPZ(self), MPZ(self), temp);
}
else {
mpz_cdiv_q_ui(MPZ(self), MPZ(self), -temp);
mpz_neg(MPZ(self), MPZ(self));
}
}
else {
mpz_t tempz;
mpz_init(tempz);
mpz_set_PyLong(tempz, other);
GMPY_MAYBE_BEGIN_ALLOW_THREADS(context);
mpz_fdiv_q(MPZ(self), MPZ(self), tempz);
GMPY_MAYBE_END_ALLOW_THREADS(context);
mpz_clear(tempz);
}
Py_INCREF(self);
return self;
}
if (IS_TYPE_MPZANY(ytype)) {
if (mpz_sgn(MPZ(other)) == 0) {
ZERO_ERROR("xmpz division by zero");
return NULL;
}
GMPY_MAYBE_BEGIN_ALLOW_THREADS(context);
mpz_fdiv_q(MPZ(self), MPZ(self), MPZ(other));
GMPY_MAYBE_END_ALLOW_THREADS(context);
Py_INCREF(self);
return self;
}
Py_RETURN_NOTIMPLEMENTED;
}
/* Inplace xmpz remainder.
*/
static PyObject *
GMPy_XMPZ_IRem_Slot(PyObject *self, PyObject *other)
{
CTXT_Object *context = NULL;
CHECK_CONTEXT(context);
int ytype = GMPy_ObjectType(other);
if (IS_TYPE_PyInteger(ytype)) {
int error;
long temp = PyLong_AsLongAndOverflow(other, &error);
if (!error) {
if (temp > 0) {
mpz_fdiv_r_ui(MPZ(self), MPZ(self), temp);
}
else if (temp == 0) {
ZERO_ERROR("xmpz modulo by zero");
return NULL;
}
else {
mpz_cdiv_r_ui(MPZ(self), MPZ(self), -temp);
}
}
else {
mpz_t tempz;
mpz_init(tempz);
mpz_set_PyLong(tempz, other);
GMPY_MAYBE_BEGIN_ALLOW_THREADS(context);
mpz_fdiv_r(MPZ(self), MPZ(self), tempz);
GMPY_MAYBE_END_ALLOW_THREADS(context);
mpz_clear(tempz);
}
Py_INCREF(self);
return self;
}
if (IS_TYPE_MPZANY(ytype)) {
if(mpz_sgn(MPZ(other)) == 0) {
ZERO_ERROR("xmpz modulo by zero");
return NULL;
}
GMPY_MAYBE_BEGIN_ALLOW_THREADS(context);
mpz_fdiv_r(MPZ(self), MPZ(self), MPZ(other));
GMPY_MAYBE_END_ALLOW_THREADS(context);
Py_INCREF(self);
return self;
}
Py_RETURN_NOTIMPLEMENTED;
}
/* Inplace xmpz rshift.
*/
static PyObject *
GMPy_XMPZ_IRshift_Slot(PyObject *self, PyObject *other)
{
mp_bitcnt_t shift = GMPy_Integer_AsMpBitCnt(other);
if (shift == (mp_bitcnt_t)(-1) && PyErr_Occurred())
return NULL;
mpz_fdiv_q_2exp(MPZ(self), MPZ(self), shift);
Py_INCREF(self);
return self;
Py_RETURN_NOTIMPLEMENTED;
}
/* Inplace xmpz lshift.
*/
static PyObject *
GMPy_XMPZ_ILshift_Slot(PyObject *self, PyObject *other)
{
mp_bitcnt_t shift = GMPy_Integer_AsMpBitCnt(other);
if (shift == (mp_bitcnt_t)(-1) && PyErr_Occurred())
return NULL;
mpz_mul_2exp(MPZ(self), MPZ(self), shift);
Py_INCREF(self);
return self;
Py_RETURN_NOTIMPLEMENTED;
}
/* Inplace xmpz_pow.
*/
static PyObject *
GMPy_XMPZ_IPow_Slot(PyObject *self, PyObject *other, PyObject *mod)
{
unsigned long exp = GMPy_Integer_AsUnsignedLong(other);
if (exp == (unsigned long)(-1) && PyErr_Occurred())
return NULL;
mpz_pow_ui(MPZ(self), MPZ(self), exp);
Py_INCREF((PyObject*)self);
return self;
Py_RETURN_NOTIMPLEMENTED;
}
/* Inplace xmpz and.
*/
static PyObject *
GMPy_XMPZ_IAnd_Slot(PyObject *self, PyObject *other)
{
CTXT_Object *context = NULL;
CHECK_CONTEXT(context);
if (CHECK_MPZANY(other)) {
GMPY_MAYBE_BEGIN_ALLOW_THREADS(context);
mpz_and(MPZ(self), MPZ(self), MPZ(other));
GMPY_MAYBE_END_ALLOW_THREADS(context);
Py_INCREF(self);
return self;
}
if (PyLong_Check(other)) {
mpz_t tempz;
mpz_init(tempz);
mpz_set_PyLong(tempz, other);
GMPY_MAYBE_BEGIN_ALLOW_THREADS(context);
mpz_and(MPZ(self), MPZ(self), tempz);
GMPY_MAYBE_END_ALLOW_THREADS(context);
mpz_clear(tempz);
Py_INCREF(self);
return self;
}
Py_RETURN_NOTIMPLEMENTED;
}
/* Inplace xmpz xor.
*/
static PyObject *
GMPy_XMPZ_IXor_Slot(PyObject *self, PyObject *other)
{
CTXT_Object *context = NULL;
CHECK_CONTEXT(context);
if(CHECK_MPZANY(other)) {
GMPY_MAYBE_BEGIN_ALLOW_THREADS(context);
mpz_xor(MPZ(self), MPZ(self), MPZ(other));
GMPY_MAYBE_END_ALLOW_THREADS(context);
Py_INCREF(self);
return self;
}
if(PyLong_Check(other)) {
mpz_t tempz;
mpz_init(tempz);
mpz_set_PyLong(tempz, other);
GMPY_MAYBE_BEGIN_ALLOW_THREADS(context);
mpz_xor(MPZ(self), MPZ(self), tempz);
GMPY_MAYBE_END_ALLOW_THREADS(context);
mpz_clear(tempz);
Py_INCREF(self);
return self;
}
Py_RETURN_NOTIMPLEMENTED;
}
/* Inplace xmpz or.
*/
static PyObject *
GMPy_XMPZ_IIor_Slot(PyObject *self, PyObject *other)
{
CTXT_Object *context = NULL;
CHECK_CONTEXT(context);
if(CHECK_MPZANY(other)) {
GMPY_MAYBE_BEGIN_ALLOW_THREADS(context);
mpz_ior(MPZ(self), MPZ(self), MPZ(other));
GMPY_MAYBE_END_ALLOW_THREADS(context);
Py_INCREF(self);
return self;
}
if(PyLong_Check(other)) {
mpz_t tempz;
mpz_init(tempz);
mpz_set_PyLong(tempz, other);
GMPY_MAYBE_BEGIN_ALLOW_THREADS(context);
mpz_ior(MPZ(self), MPZ(self), tempz);
GMPY_MAYBE_END_ALLOW_THREADS(context);
mpz_clear(tempz);
Py_INCREF(self);
return self;
}
Py_RETURN_NOTIMPLEMENTED;
}
././@PaxHeader 0000000 0000000 0000000 00000000026 00000000000 010213 x ustar 00 22 mtime=1710307256.0
gmpy2-2.2.1/src/gmpy2_xmpz_inplace.h 0000644 0001750 0001750 00000005476 14574233670 016020 0 ustar 00case case /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* gmpy2_xmpz_inplace.c *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Python interface to the GMP, MPFR, and MPC multiple precision *
* libraries. *
* *
* Copyright 2000 - 2009 Alex Martelli *
* *
* Copyright 2008 - 2024 Case Van Horsen *
* *
* This file is part of GMPY2. *
* *
* GMPY2 is free software: you can redistribute it and/or modify it under *
* the terms of the GNU Lesser General Public License as published by the *
* Free Software Foundation, either version 3 of the License, or (at your *
* option) any later version. *
* *
* GMPY2 is distributed in the hope that it will be useful, but WITHOUT *
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or *
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public *
* License for more details. *
* *
* You should have received a copy of the GNU Lesser General Public *
* License along with GMPY2; if not, see *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
#ifndef GMPY_XMPZ_INPLACE_H
#define GMPY_XMPZ_INPLACE_H
#ifdef __cplusplus
extern "C" {
#endif
static PyObject * GMPy_XMPZ_IAdd_Slot(PyObject *self, PyObject *other);
static PyObject * GMPy_XMPZ_ISub_Slot(PyObject *self, PyObject *other);
static PyObject * GMPy_XMPZ_IMul_Slot(PyObject *self, PyObject *other);
static PyObject * GMPy_XMPZ_IFloorDiv_Slot(PyObject *self, PyObject *other);
static PyObject * GMPy_XMPZ_IRem_Slot(PyObject *self, PyObject *other);
static PyObject * GMPy_XMPZ_IRshift_Slot(PyObject *self, PyObject *other);
static PyObject * GMPy_XMPZ_ILshift_Slot(PyObject *self, PyObject *other);
static PyObject * GMPy_XMPZ_IPow_Slot(PyObject *self, PyObject *other, PyObject *mod);
static PyObject * GMPy_XMPZ_IAnd_Slot(PyObject *self, PyObject *other);
static PyObject * GMPy_XMPZ_IXor_Slot(PyObject *self, PyObject *other);
static PyObject * GMPy_XMPZ_IIor_Slot(PyObject *self, PyObject *other);
#ifdef __cplusplus
}
#endif
#endif
././@PaxHeader 0000000 0000000 0000000 00000000026 00000000000 010213 x ustar 00 22 mtime=1710307256.0
gmpy2-2.2.1/src/gmpy2_xmpz_limbs.c 0000644 0001750 0001750 00000010635 14574233670 015477 0 ustar 00case case /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* gmpy2_xmpz_limbs.c *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Python interface to the GMP, MPFR, and MPC multiple precision *
* libraries. *
* *
* Copyright 2020 Tyler Lanphear *
* *
* This file is part of GMPY2. *
* *
* GMPY2 is free software: you can redistribute it and/or modify it under *
* the terms of the GNU Lesser General Public License as published by the *
* Free Software Foundation, either version 3 of the License, or (at your *
* option) any later version. *
* *
* GMPY2 is distributed in the hope that it will be useful, but WITHOUT *
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or *
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public *
* License for more details. *
* *
* You should have received a copy of the GNU Lesser General Public *
* License along with GMPY2; if not, see *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
PyDoc_STRVAR(GMPy_doc_xmpz_method_num_limbs,
"x.num_limbs() -> int\n\n"
"Return the number of limbs of x.");
static PyObject* GMPy_XMPZ_Method_NumLimbs(PyObject* obj, PyObject* other)
{
return PyLong_FromSize_t(mpz_size(XMPZ(obj)));
}
PyDoc_STRVAR(GMPy_doc_xmpz_method_limbs_read,
"x.limbs_read() -> int\n\n"
"Returns the address of the immutable buffer representing the\n"
"limbs of x.");
static PyObject* GMPy_XMPZ_Method_LimbsRead(PyObject* obj, PyObject* args)
{
const mp_limb_t* limbs = mpz_limbs_read(XMPZ(obj));
return PyLong_FromVoidPtr((void *) limbs);
}
PyDoc_STRVAR(GMPy_doc_xmpz_method_limbs_write,
"x.limbs_write(n, /) -> int\n\n"
"Returns the address of a mutable buffer representing the limbs\n"
"of x, resized so that it may hold at least n limbs.\n"
"Must be followed by a call to x.limbs_finish(n) after writing to\n"
"the returned address in order for the changes to take effect.\n"
"WARNING: this operation is destructive and may destroy the old\n"
"value of x.");
static PyObject* GMPy_XMPZ_Method_LimbsWrite(PyObject* obj, PyObject* other)
{
if (!PyLong_Check(other)) {
TYPE_ERROR("number of limbs must be an int or a long");
return NULL;
}
else {
size_t num_limbs = (size_t) PyLong_AsSsize_t(other);
mp_limb_t * limbs = mpz_limbs_write(XMPZ(obj), (mp_size_t) num_limbs);
return PyLong_FromVoidPtr((void *) limbs);
}
}
PyDoc_STRVAR(GMPy_doc_xmpz_method_limbs_modify,
"x.limbs_modify(n, /) -> int\n\n"
"Returns the address of a mutable buffer representing the limbs\n"
"of x, resized so that it may hold at least n limbs.\n"
"Must be followed by a call to x.limbs_finish(n) after writing to\n"
"the returned address in order for the changes to take effect.");
static PyObject* GMPy_XMPZ_Method_LimbsModify(PyObject* obj, PyObject* other)
{
if (!PyLong_Check(other)) {
TYPE_ERROR("number of limbs must be an int or a long");
return NULL;
}
else {
size_t num_limbs = (size_t) PyLong_AsSsize_t(other);
mp_limb_t * limbs = mpz_limbs_modify(XMPZ(obj), (mp_size_t) num_limbs);
return PyLong_FromVoidPtr((void *) limbs);
}
}
PyDoc_STRVAR(GMPy_doc_xmpz_method_limbs_finish,
"x.limbs_finish(n, /) -> None\n\n"
"Must be called after writing to the address returned by\n"
"x.limbs_write(n) or x.limbs_modify(n) to update\n"
"the limbs of x.");
static PyObject* GMPy_XMPZ_Method_LimbsFinish(PyObject* obj, PyObject* other)
{
if (!PyLong_Check(other)) {
TYPE_ERROR("number of limbs must be an int or long");
return NULL;
}
else {
size_t num_limbs = (size_t) PyLong_AsSsize_t(other);
mpz_limbs_finish(XMPZ(obj), num_limbs);
Py_RETURN_NONE;
}
}
././@PaxHeader 0000000 0000000 0000000 00000000026 00000000000 010213 x ustar 00 22 mtime=1710307256.0
gmpy2-2.2.1/src/gmpy2_xmpz_limbs.h 0000644 0001750 0001750 00000004363 14574233670 015505 0 ustar 00case case /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* gmpy2_xmpz_limbs.h *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Python interface to the GMP, MPFR, and MPC multiple precision *
* libraries. *
* *
* Copyright 2020 Tyler Lanphear *
* *
* This file is part of GMPY2. *
* *
* GMPY2 is free software: you can redistribute it and/or modify it under *
* the terms of the GNU Lesser General Public License as published by the *
* Free Software Foundation, either version 3 of the License, or (at your *
* option) any later version. *
* *
* GMPY2 is distributed in the hope that it will be useful, but WITHOUT *
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or *
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public *
* License for more details. *
* *
* You should have received a copy of the GNU Lesser General Public *
* License along with GMPY2; if not, see *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
#ifndef GMPY_XMPZ_LIMBS_H
#define GMPY_XMPZ_LIMBS_H
#ifdef __cplusplus
extern "C" {
#endif
static PyObject* GMPy_XMPZ_Method_NumLimbs(PyObject* obj, PyObject* other);
static PyObject* GMPy_XMPZ_Method_LimbsRead(PyObject* obj, PyObject* other);
static PyObject* GMPy_XMPZ_Method_LimbsWrite(PyObject* obj, PyObject* other);
static PyObject* GMPy_XMPZ_Method_LimbsModify(PyObject* obj, PyObject* other);
static PyObject* GMPy_XMPZ_Method_LimbsFinish(PyObject* obj, PyObject* other);
#ifdef __cplusplus
}
#endif
#endif
././@PaxHeader 0000000 0000000 0000000 00000000026 00000000000 010213 x ustar 00 22 mtime=1711300127.0
gmpy2-2.2.1/src/gmpy2_xmpz_misc.c 0000644 0001750 0001750 00000043520 14600057037 015312 0 ustar 00case case /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* gmpy2_xmpz_misc.c *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Python interface to the GMP, MPFR, and MPC multiple precision *
* libraries. *
* *
* Copyright 2000 - 2009 Alex Martelli *
* *
* Copyright 2008 - 2024 Case Van Horsen *
* *
* This file is part of GMPY2. *
* *
* GMPY2 is free software: you can redistribute it and/or modify it under *
* the terms of the GNU Lesser General Public License as published by the *
* Free Software Foundation, either version 3 of the License, or (at your *
* option) any later version. *
* *
* GMPY2 is distributed in the hope that it will be useful, but WITHOUT *
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or *
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public *
* License for more details. *
* *
* You should have received a copy of the GNU Lesser General Public *
* License along with GMPY2; if not, see *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
#include "pythoncapi_compat.h"
PyDoc_STRVAR(GMPy_doc_xmpz_function_xbit_mask,
"xbit_mask(n, /) -> xmpz\n\n"
"Return an 'xmpz' exactly n bits in length with all bits set.\n");
static PyObject *
GMPy_XMPZ_Function_XbitMask(PyObject *self, PyObject *other)
{
Py_ssize_t i = 0;
XMPZ_Object* result;
CTXT_Object *context = NULL;
CHECK_CONTEXT(context);
i = GMPy_Integer_AsSsize_t(other);
if (i == -1 && PyErr_Occurred()) {
TYPE_ERROR("xbit_mask() requires 'int' argument");
return NULL;
}
if (i < 0) {
VALUE_ERROR("mask length must be >= 0");
return NULL;
}
if (!(result = GMPy_XMPZ_New(context))) {
return NULL;
}
mpz_set_ui(result->z, 1);
mpz_mul_2exp(result->z, result->z, i);
mpz_sub_ui(result->z, result->z, 1);
return (PyObject*)result;
}
static PyObject *
GMPy_XMPZ_Abs_Slot(XMPZ_Object *x)
{
mpz_abs(x->z, x->z);
Py_RETURN_NONE;
}
static PyObject *
GMPy_XMPZ_Neg_Slot(XMPZ_Object *x)
{
mpz_neg(x->z, x->z);
Py_RETURN_NONE;
}
static PyObject *
GMPy_XMPZ_Pos_Slot(XMPZ_Object *x)
{
Py_RETURN_NONE;
}
static int
GMPy_XMPZ_NonZero_Slot(XMPZ_Object *x)
{
return mpz_sgn(x->z) != 0;
}
/* BIT OPERATIONS */
static PyObject *
GMPy_XMPZ_Com_Slot(XMPZ_Object *x)
{
mpz_com(x->z, x->z);
Py_RETURN_NONE;
}
PyDoc_STRVAR(GMPy_doc_xmpz_method_make_mpz,
"x.make_mpz() -> mpz\n\n"
"Return an `mpz` by converting x as quickly as possible.\n\n"
"NOTE: Optimized for speed so the original `xmpz` value is set to 0!");
static PyObject *
GMPy_XMPZ_Method_MakeMPZ(PyObject *self, PyObject *other)
{
MPZ_Object* result;
CTXT_Object *context = NULL;
CHECK_CONTEXT(context);
if (!(result = GMPy_MPZ_New(context))) {
return NULL;
}
mpz_swap(result->z, MPZ(self));
mpz_set_ui(MPZ(self), 0);
return (PyObject*)result;
}
PyDoc_STRVAR(GMPy_doc_xmpz_method_copy,
"x.copy() -> xmpz\n\n"
"Return a copy of a x.");
static PyObject *
GMPy_XMPZ_Method_Copy(PyObject *self, PyObject *other)
{
CTXT_Object *context = NULL;
CHECK_CONTEXT(context);
return (PyObject*)GMPy_XMPZ_From_XMPZ((XMPZ_Object*)self, context);
}
/*
* Add mapping support to xmpz objects.
*/
static Py_ssize_t
GMPy_XMPZ_Method_Length(XMPZ_Object *obj)
{
return mpz_sizeinbase(obj->z, 2);
}
static PyObject *
GMPy_XMPZ_Method_SubScript(XMPZ_Object* self, PyObject* item)
{
CTXT_Object *context = NULL;
CHECK_CONTEXT(context);
if (PyIndex_Check(item)) {
Py_ssize_t i;
i = PyLong_AsSsize_t(item);
if (i == -1 && PyErr_Occurred()) {
INDEX_ERROR("argument too large to be converted to an index");
return NULL;
}
if (i < 0) {
i += mpz_sizeinbase(self->z, 2);
}
return PyLong_FromLong(mpz_tstbit(self->z, i));
}
else if (PySlice_Check(item)) {
Py_ssize_t start, stop, step, slicelength, cur, i;
MPZ_Object *result;
if (PySlice_GetIndicesEx(item,
mpz_sizeinbase(self->z, 2),
&start, &stop, &step, &slicelength) < 0) {
return NULL;
}
if ((step < 0 && start < stop) || (step > 0 && start > stop)) {
stop = start;
}
if (!(result = GMPy_MPZ_New(context))) {
return NULL;
}
mpz_set_ui(result->z, 0);
if (slicelength > 0) {
for (cur = start, i = 0; i < slicelength; cur += step, i++) {
if (mpz_tstbit(self->z, cur)) {
mpz_setbit(result->z, i);
}
}
}
return (PyObject*)result;
}
else {
TYPE_ERROR("bit positions must be integers");
return NULL;
}
}
static int
GMPy_XMPZ_Method_AssignSubScript(XMPZ_Object* self, PyObject* item, PyObject* value)
{
CTXT_Object *context = NULL;
CHECK_CONTEXT_M1(context);
if (PyIndex_Check(item)) {
Py_ssize_t bit_value, i;
i = PyLong_AsSsize_t(item);
if (i == -1 && PyErr_Occurred()) {
INDEX_ERROR("argument too large to be converted to an index");
return -1;
}
if (i < 0) {
i += mpz_sizeinbase(self->z, 2);
}
bit_value = PyLong_AsSsize_t(value);
if (bit_value == -1 && PyErr_Occurred()) {
VALUE_ERROR("bit value must be 0 or 1");
return -1;
}
if (bit_value == 1) {
mpz_setbit(self->z, i);
return 0;
}
else if (bit_value == 0) {
mpz_clrbit(self->z, i);
return 0;
}
else {
VALUE_ERROR("bit value must be 0 or 1");
return -1;
}
}
else if (PySlice_Check(item)) {
Py_ssize_t cur, i, seq_len, start, stop, step, slicelength, temp;
seq_len = mpz_sizeinbase(self->z, 2);
if (!Py_IsNone(((PySliceObject*)item)->stop)) {
/* If a fixed endpoint is specified, and the endpoint is greater
* than the length of the xmpz object, allow the underlying xmpz
* object to be made larger.
*/
temp = PyLong_AsSsize_t(((PySliceObject*)item)->stop);
if (temp == -1 && PyErr_Occurred()) {
return 0;
}
if (temp > seq_len) {
seq_len = temp;
}
}
if (PySlice_GetIndicesEx(item,
seq_len,
&start, &stop, &step, &slicelength) < 0) {
return -1;
}
if ((step < 0 && start < stop) || (step > 0 && start > stop)) {
stop = start;
}
if (value == NULL) {
TYPE_ERROR("deleting bits not supported");
return -1;
}
else {
int bit;
MPZ_Object *tempx;
if (!(tempx = GMPy_MPZ_From_Integer(value, context))) {
VALUE_ERROR("must specify bit sequence as an integer");
return -1;
}
if (mpz_sgn(tempx->z) == 0) {
for (cur = start, i = 0; i < slicelength; cur += step, i++) {
mpz_clrbit(self->z, cur);
}
}
else if (!(mpz_cmp_si(tempx->z, -1))) {
for (cur = start + (slicelength-1) * step, i = 0;
i < slicelength;
cur -= step, i++) {
mpz_setbit(self->z, cur);
}
}
else {
for (cur = start, i = 0; i < slicelength; cur += step, i++) {
bit = mpz_tstbit(tempx->z, i);
if (bit)
mpz_setbit(self->z, cur);
else
mpz_clrbit(self->z, cur);
}
}
Py_DECREF((PyObject*)tempx);
}
return 0;
}
else {
TYPE_ERROR("bit positions must be integers");
return -1;
}
return -1;
}
/* Implement a multi-purpose iterator object that iterates over the bits in
* an xmpz. Three different iterators can be created:
* 1) xmpz.iter_bits(start=0, stop=-1) will return True/False for each bit
* position in the xmpz, beginning with bit 'start'. If stop is specified,
* the xmpz will be padded with 0-bits (False) until stop is reached.
* 2) xmpz.iter_set(start=0, stop=-1, scale=1, offset=0) will return
* (scale*bit_position + offset) when bit_position is set, beginning at
* 'start', ending at 'stop'.
* 3) xmpz.iter_clear(start=0, stop=-1, scale=1, offset=0) will return
* (scale*bit_position + offset) when bit_position is clear, beginning at
* 'start', ending at 'stop'.
*
*/
static GMPy_Iter_Object *
GMPy_Iter_New(void)
{
GMPy_Iter_Object *result;
if ((result = PyObject_New(GMPy_Iter_Object,
&GMPy_Iter_Type))) {
result->bitmap = NULL;
result->start = 0;
result->stop = (mp_bitcnt_t)-1;
result->iter_type = 1;
}
return result;
};
static void
GMPy_Iter_Dealloc(GMPy_Iter_Object *self)
{
Py_XDECREF((PyObject*)self->bitmap);
PyObject_Free(self);
};
static PyObject *
GMPy_Iter_Next(GMPy_Iter_Object *self) {
PyObject *result = 0;
mp_bitcnt_t temp, current_stop;
if (self->stop == (mp_bitcnt_t)(-1))
current_stop = mpz_sizeinbase(self->bitmap->z, 2);
else
current_stop = self->stop;
switch (self->iter_type) {
case 1:
if (self->start >= current_stop)
PyErr_SetNone(PyExc_StopIteration);
else {
temp = mpz_tstbit(self->bitmap->z, self->start);
self->start += 1;
result = temp ? Py_True : Py_False;
Py_INCREF(result);
}
break;
case 2:
if (self->start >= current_stop)
PyErr_SetNone(PyExc_StopIteration);
else {
temp = mpz_scan1(self->bitmap->z, self->start);
if (temp == (mp_bitcnt_t)(-1))
PyErr_SetNone(PyExc_StopIteration);
else {
self->start = temp + 1;
result = PyLong_FromSsize_t(temp);
}
}
break;
case 3:
if (self->start >= current_stop)
PyErr_SetNone(PyExc_StopIteration);
else {
temp = mpz_scan0(self->bitmap->z, self->start);
if (temp >= current_stop)
PyErr_SetNone(PyExc_StopIteration);
else {
self->start = temp + 1;
result = PyLong_FromSsize_t(temp);
}
}
break;
default:
SYSTEM_ERROR("Illegal iter_type in gmpy2.Iterator.");
}
return result;
}
static PyObject *
GMPy_Iter_Repr(GMPy_Iter_Object *self)
{
return PyUnicode_FromString("");
};
PyDoc_STRVAR(GMPy_doc_xmpz_method_iter_bits,
"x.iter_bits(start=0, stop=-1) -> collections.abc.Iterator\n\n"
"Return `True` or `False` for each bit position in x beginning at\n"
"'start'. If a positive value is specified for 'stop', iteration is\n"
"continued until 'stop' is reached. If a negative value is specified,\n"
"iteration is continued until the last 1-bit. Note: the value of the\n"
"underlying `xmpz` object can change during iteration.");
static PyObject *
GMPy_XMPZ_Method_IterBits(PyObject *self, PyObject *args, PyObject *kwargs)
{
GMPy_Iter_Object *result;
Py_ssize_t start = 0, stop = -1;
static char *kwlist[] = {"start", "stop", NULL };
if (!(result = GMPy_Iter_New())) {
return NULL;
}
if (!(PyArg_ParseTupleAndKeywords(args, kwargs, "|nn", kwlist, &start, &stop))) {
Py_XDECREF((PyObject*)result);
return NULL;
}
result->iter_type = 1;
result->bitmap = (XMPZ_Object*)self;
Py_INCREF(self);
result->start = start;
result->stop = stop;
return (PyObject*)result;
}
PyDoc_STRVAR(GMPy_doc_xmpz_method_iter_set,
"x.iter_set(start=0, stop=-1) -> collections.abc.Iterator\n\n"
"Return an iterator yielding the bit position for every bit that\n"
"is set in x, beginning at 'start'. If a positive value is\n"
"specified for 'stop', iteration is continued until 'stop' is\n"
"reached. To match the behavior of slicing, 'stop' is not included.\n"
"If a negative value is specified, iteration is continued until\n"
"the last 1-bit. Note: the value of the underlying `xmpz` object can\n"
"change during iteration.");
static PyObject *
GMPy_XMPZ_Method_IterSet(PyObject *self, PyObject *args, PyObject *kwargs)
{
GMPy_Iter_Object *result;
Py_ssize_t start = 0, stop = -1;
static char *kwlist[] = {"start", "stop", NULL };
if (!(result = GMPy_Iter_New())) {
return NULL;
}
if (!(PyArg_ParseTupleAndKeywords(args, kwargs, "|nn", kwlist, &start, &stop))) {
Py_XDECREF((PyObject*)result);
return NULL;
}
result->iter_type = 2;
result->bitmap = (XMPZ_Object*)self;
Py_INCREF(self);
result->start = start;
result->stop = stop;
return (PyObject*)result;
}
PyDoc_STRVAR(GMPy_doc_xmpz_method_iter_clear,
"x.iter_clear(start=0, stop=-1) -> collections.abc.Iterator\n\n"
"Return every bit position that is clear in x, beginning at\n"
"'start'. If a positive value is specified for 'stop', iteration\n"
"is continued until 'stop' is reached. If a negative value is specified,\n"
"iteration is continued until the last 1-bit. Note: the value of the\n"
"underlying `xmpz` object can change during iteration.");
static PyObject *
GMPy_XMPZ_Method_IterClear(PyObject *self, PyObject *args, PyObject *kwargs)
{
GMPy_Iter_Object *result;
Py_ssize_t start = 0, stop = -1;
static char *kwlist[] = {"start", "stop", NULL };
if (!(result = GMPy_Iter_New())) {
return NULL;
}
if (!(PyArg_ParseTupleAndKeywords(args, kwargs, "|nn", kwlist, &start, &stop))) {
Py_XDECREF((PyObject*)result);
return NULL;
}
result->iter_type = 3;
result->bitmap = (XMPZ_Object*)self;
Py_INCREF(self);
result->start = start;
result->stop = stop;
return (PyObject*)result;
}
static PyObject *
GMPy_XMPZ_Attrib_GetNumer(XMPZ_Object *self, void *closure)
{
Py_INCREF((PyObject*)self);
return (PyObject*)self;
}
static PyObject *
GMPy_XMPZ_Attrib_GetReal(XMPZ_Object *self, void *closure)
{
Py_INCREF((PyObject*)self);
return (PyObject*)self;
}
static PyObject *
GMPy_XMPZ_Attrib_GetDenom(XMPZ_Object *self, void *closure)
{
XMPZ_Object *result;
if ((result = GMPy_XMPZ_New(NULL))) {
mpz_set_ui(result->z, 1);
}
return (PyObject*)result;
}
static PyObject *
GMPy_XMPZ_Attrib_GetImag(XMPZ_Object *self, void *closure)
{
XMPZ_Object *result;
if ((result = GMPy_XMPZ_New(NULL))) {
mpz_set_ui(result->z, 0);
}
return (PyObject*)result;
}
PyDoc_STRVAR(GMPy_doc_xmpz_method_sizeof,
"x.__sizeof__()\n\n"
"Returns the amount of memory consumed by x. Note: deleted xmpz objects\n"
"are reused and may or may not be resized when a new value is assigned.");
static PyObject *
GMPy_XMPZ_Method_SizeOf(PyObject *self, PyObject *other)
{
return PyLong_FromSize_t(sizeof(XMPZ_Object) + \
(MPZ(self)->_mp_alloc * sizeof(mp_limb_t)));
}
static PyTypeObject GMPy_Iter_Type =
{
PyVarObject_HEAD_INIT(0, 0)
"gmpy2 iterator", /* tp_name */
sizeof(GMPy_Iter_Object), /* tp_basicsize */
0, /* tp_itemsize */
(destructor) GMPy_Iter_Dealloc, /* tp_dealloc */
0, /* tp_print */
0, /* tp_getattr */
0, /* tp_setattr */
0, /* tp_reserved */
(reprfunc) GMPy_Iter_Repr, /* tp_repr */
0, /* tp_as_number */
0, /* tp_as_sequence */
0, /* tp_as_mapping */
0, /* tp_hash */
0, /* tp_call */
0, /* tp_str */
0, /* tp_getattro */
0, /* tp_setattro */
0, /* tp_as_buffer */
Py_TPFLAGS_DEFAULT, /* tp_flags */
"GMPY2 Iterator Object", /* tp_doc */
0, /* tp_traverse */
0, /* tp_clear */
0, /* tp_richcompare */
0, /* tp_weaklistoffset*/
PyObject_SelfIter, /* tp_iter */
(iternextfunc)GMPy_Iter_Next, /* tp_iternext */
};
././@PaxHeader 0000000 0000000 0000000 00000000026 00000000000 010213 x ustar 00 22 mtime=1710307256.0
gmpy2-2.2.1/src/gmpy2_xmpz_misc.h 0000644 0001750 0001750 00000007263 14574233670 015334 0 ustar 00case case /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* gmpy2_xmpz_misc.h *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Python interface to the GMP, MPFR, and MPC multiple precision *
* libraries. *
* *
* Copyright 2000 - 2009 Alex Martelli *
* *
* Copyright 2008 - 2024 Case Van Horsen *
* *
* This file is part of GMPY2. *
* *
* GMPY2 is free software: you can redistribute it and/or modify it under *
* the terms of the GNU Lesser General Public License as published by the *
* Free Software Foundation, either version 3 of the License, or (at your *
* option) any later version. *
* *
* GMPY2 is distributed in the hope that it will be useful, but WITHOUT *
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or *
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public *
* License for more details. *
* *
* You should have received a copy of the GNU Lesser General Public *
* License along with GMPY2; if not, see *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
#ifndef GMPY_XMPZ_MISC_H
#define GMPY_XMPZ_MISC_H
#ifdef __cplusplus
extern "C" {
#endif
static int GMPy_XMPZ_NonZero_Slot(XMPZ_Object *x);
static PyObject * GMPy_XMPZ_Function_XbitMask(PyObject *self, PyObject *other);
static PyObject * GMPy_XMPZ_Abs_Slot(XMPZ_Object *x);
static PyObject * GMPy_XMPZ_Neg_Slot(XMPZ_Object *x);
static PyObject * GMPy_XMPZ_Pos_Slot(XMPZ_Object *x);
static PyObject * GMPy_XMPZ_Com_Slot(XMPZ_Object *x);
static PyObject * GMPy_XMPZ_Method_MakeMPZ(PyObject *self, PyObject *other);
static PyObject * GMPy_XMPZ_Method_Copy(PyObject *self, PyObject *other);
static Py_ssize_t GMPy_XMPZ_Method_Length(XMPZ_Object *obj);
static PyObject * GMPy_XMPZ_Method_SubScript(XMPZ_Object* self, PyObject* item);
static int GMPy_XMPZ_Method_AssignSubScript(XMPZ_Object* self, PyObject* item, PyObject* value);
static PyObject * GMPy_XMPZ_Attrib_GetNumer(XMPZ_Object *self, void *closure);
static PyObject * GMPy_XMPZ_Attrib_GetDenom(XMPZ_Object *self, void *closure);
static PyObject * GMPy_XMPZ_Attrib_GetReal(XMPZ_Object *self, void *closure);
static PyObject * GMPy_XMPZ_Attrib_GetImag(XMPZ_Object *self, void *closure);
static GMPy_Iter_Object * GMPy_Iter_New(void);
static void GMPy_Iter_Dealloc(GMPy_Iter_Object *self);
static PyObject * GMPy_Iter_Next(GMPy_Iter_Object *self);
static PyObject * GMPy_Iter_Repr(GMPy_Iter_Object *self);
static PyObject * GMPy_XMPZ_Method_IterBits(PyObject *self, PyObject *args, PyObject *kwargs);
static PyObject * GMPy_XMPZ_Method_IterSet(PyObject *self, PyObject *args, PyObject *kwargs);
static PyObject * GMPy_XMPZ_Method_IterClear(PyObject *self, PyObject *args, PyObject *kwargs);
static PyObject * GMPy_XMPZ_Method_SizeOf(PyObject *self, PyObject *other);
#ifdef __cplusplus
}
#endif
#endif
././@PaxHeader 0000000 0000000 0000000 00000000026 00000000000 010213 x ustar 00 22 mtime=1718253275.0
gmpy2-2.2.1/src/gmpy_mpz_lucas.c 0000644 0001750 0001750 00000043332 14632473333 015223 0 ustar 00case case /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* gmpy_mpz_lucas.c *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Python interface to the GMP, MPFR, and MPC multiple precision *
* libraries. *
* *
* Copyright 2011 David Cleaver *
* *
* Copyright 2012 - 2024 Case Van Horsen *
* *
* The original file is available at: *
* *
* *
* Modified by Case Van Horsen for inclusion into GMPY2. *
* *
* This file is part of GMPY2. *
* *
* GMPY2 is free software: you can redistribute it and/or modify it under *
* the terms of the GNU Lesser General Public License as published by the *
* Free Software Foundation, either version 3 of the License, or (at your *
* option) any later version. *
* *
* GMPY2 is distributed in the hope that it will be useful, but WITHOUT *
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or *
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public *
* License for more details. *
* *
* You should have received a copy of the GNU Lesser General Public *
* License along with GMPY2; if not, see *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
PyDoc_STRVAR(doc_mpz_lucasu,
"lucasu(p,q,k,/) -> mpz\n\n"
"Return the k-th element of the Lucas U sequence defined by p,q.\n"
"p*p - 4*q must not equal 0; k must be greater than or equal to 0.");
static PyObject *
GMPY_mpz_lucasu(PyObject *self, PyObject *args)
{
/* Adaptation of algorithm found in
* https://web.archive.org/web/20150202074230/http://joye.site88.net/papers/JQ96lucas.pdf
* calculate u[k] of Lucas U sequence for p,q.
* Note: p^2-4q=0 is not tested, not a proper Lucas sequence!!
*/
MPZ_Object *result = NULL, *p = NULL, *q = NULL, *k = NULL;
size_t s = 0, j = 0;
mpz_t uh, vl, vh, ql, qh, tmp;
if (PyTuple_Size(args) != 3) {
TYPE_ERROR("lucasu() requires 3 integer arguments");
return NULL;
}
mpz_init(uh);
mpz_init(vl);
mpz_init(vh);
mpz_init(ql);
mpz_init(qh);
mpz_init(tmp);
p = GMPy_MPZ_From_Integer(PyTuple_GET_ITEM(args, 0), NULL);
q = GMPy_MPZ_From_Integer(PyTuple_GET_ITEM(args, 1), NULL);
k = GMPy_MPZ_From_Integer(PyTuple_GET_ITEM(args, 2), NULL);
if (!p || !q || !k) {
TYPE_ERROR("lucasu() requires 3 integer arguments");
goto cleanup;
}
/* Check if p*p - 4*q == 0. */
mpz_mul(tmp, p->z, p->z);
mpz_mul_ui(qh, q->z, 4);
mpz_sub(tmp, tmp, qh);
if (mpz_sgn(tmp) == 0) {
VALUE_ERROR("invalid values for p,q in lucasu()");
goto cleanup;
}
/* Check if k < 0. */
if (mpz_sgn(k->z) < 0) {
VALUE_ERROR("invalid value for k in lucasu()");
goto cleanup;
}
mpz_set_si(uh, 1);
mpz_set_si(vl, 2);
mpz_set(vh, p->z);
mpz_set_si(ql, 1);
mpz_set_si(qh, 1);
mpz_set_si(tmp, 0);
if (mpz_sgn(k->z) == 0) {
mpz_set_si(uh, 0);
goto end;
}
s = mpz_scan1(k->z, 0);
for (j = mpz_sizeinbase(k->z,2)-1; j >= s+1; j--) {
/* ql = ql*qh */
mpz_mul(ql, ql, qh);
if (mpz_tstbit(k->z,j) == 1) {
/* qh = ql*q */
mpz_mul(qh, ql, q->z);
/* uh = uh*vh */
mpz_mul(uh, uh, vh);
/* vl = vh*vl - p*ql */
mpz_mul(vl, vh, vl);
mpz_mul(tmp, ql, p->z);
mpz_sub(vl, vl, tmp);
/* vh = vh*vh - 2*qh */
mpz_mul(vh, vh, vh);
mpz_mul_si(tmp, qh, 2);
mpz_sub(vh, vh, tmp);
}
else {
/* qh = ql */
mpz_set(qh, ql);
/* uh = uh*vl - ql */
mpz_mul(uh, uh, vl);
mpz_sub(uh, uh, ql);
/* vh = vh*vl - p*ql */
mpz_mul(vh, vh, vl);
mpz_mul(tmp, ql, p->z);
mpz_sub(vh, vh, tmp);
/* vl = vl*vl - 2*ql */
mpz_mul(vl, vl, vl);
mpz_mul_si(tmp, ql, 2);
mpz_sub(vl, vl, tmp);
}
}
/* ql = ql*qh */
mpz_mul(ql, ql, qh);
/* qh = ql*q */
mpz_mul(qh, ql, q->z);
/* uh = uh*vl - ql */
mpz_mul(uh, uh, vl);
mpz_sub(uh, uh, ql);
/* vl = vh*vl - p*ql */
mpz_mul(vl, vh, vl);
mpz_mul(tmp, ql, p->z);
mpz_sub(vl, vl, tmp);
/* ql = ql*qh */
mpz_mul(ql, ql, qh);
for (j = 1; j <= s; j++) {
/* uh = uh*vl */
mpz_mul(uh, uh, vl);
/* vl = vl*vl - 2*ql */
mpz_mul(vl, vl, vl);
mpz_mul_si(tmp, ql, 2);
mpz_sub(vl, vl, tmp);
/* ql = ql*ql */
mpz_mul(ql, ql, ql);
}
end:
if (!(result = GMPy_MPZ_New(NULL)))
goto cleanup;
/* uh contains our return value */
mpz_set(result->z, uh);
cleanup:
mpz_clear(uh);
mpz_clear(vl);
mpz_clear(vh);
mpz_clear(ql);
mpz_clear(qh);
mpz_clear(tmp);
Py_XDECREF((PyObject*)p);
Py_XDECREF((PyObject*)q);
Py_XDECREF((PyObject*)k);
return (PyObject*)result;
}
PyDoc_STRVAR(doc_mpz_lucasu_mod,
"lucasu_mod(p,q,k,n,/) -> mpz\n\n"
"Return the k-th element of the Lucas U sequence defined by p,q (mod n).\n"
"p*p - 4*q must not equal 0; k must be greater than or equal to 0;\n"
"n must be greater than 0.");
static PyObject *
GMPY_mpz_lucasu_mod(PyObject *self, PyObject *args)
{
/* Adaptation of algorithm found in http://joye.site88.net/papers/JQ96lucas.pdf
* calculate u[k] (modulo n) of Lucas U sequence for p,q.
* Note: p^2-4q=0 is not tested, not a proper Lucas sequence!!
*/
MPZ_Object *result = NULL, *p = NULL, *q = NULL, *k = NULL, *n = NULL;
size_t s = 0, j = 0;
mpz_t uh, vl, vh, ql, qh, tmp;
if (PyTuple_Size(args) != 4) {
TYPE_ERROR("lucasu_mod() requires 4 integer arguments");
return NULL;
}
mpz_init(uh);
mpz_init(vl);
mpz_init(vh);
mpz_init(ql);
mpz_init(qh);
mpz_init(tmp);
p = GMPy_MPZ_From_Integer(PyTuple_GET_ITEM(args, 0), NULL);
q = GMPy_MPZ_From_Integer(PyTuple_GET_ITEM(args, 1), NULL);
k = GMPy_MPZ_From_Integer(PyTuple_GET_ITEM(args, 2), NULL);
n = GMPy_MPZ_From_Integer(PyTuple_GET_ITEM(args, 3), NULL);
if (!p || !q || !k || !n) {
TYPE_ERROR("lucasu_mod() requires 4 integer arguments");
goto cleanup;
}
/* Check if p*p - 4*q == 0. */
mpz_mul(tmp, p->z, p->z);
mpz_mul_ui(qh, q->z, 4);
mpz_sub(tmp, tmp, qh);
if (mpz_sgn(tmp) == 0) {
VALUE_ERROR("invalid values for p,q in lucasu_mod()");
goto cleanup;
}
/* Check if k < 0. */
if (mpz_sgn(k->z) < 0) {
VALUE_ERROR("invalid value for k in lucasu_mod()");
goto cleanup;
}
/* Check if n > 0. */
if (mpz_sgn(n->z) <= 0) {
VALUE_ERROR("invalid value for n in lucasu_mod()");
goto cleanup;
}
mpz_set_si(uh, 1);
mpz_set_si(vl, 2);
mpz_set(vh, p->z);
mpz_set_si(ql, 1);
mpz_set_si(qh, 1);
mpz_set_si(tmp, 0);
if (mpz_sgn(k->z) == 0) {
mpz_set_si(uh, 0);
goto end;
}
s = mpz_scan1(k->z, 0);
for (j = mpz_sizeinbase(k->z,2)-1; j >= s+1; j--) {
/* ql = ql*qh (mod n) */
mpz_mul(ql, ql, qh);
mpz_mod(ql, ql, n->z);
if (mpz_tstbit(k->z,j) == 1) {
/* qh = ql*q */
mpz_mul(qh, ql, q->z);
/* uh = uh*vh (mod n) */
mpz_mul(uh, uh, vh);
mpz_mod(uh, uh, n->z);
/* vl = vh*vl - p*ql (mod n) */
mpz_mul(vl, vh, vl);
mpz_mul(tmp, ql, p->z);
mpz_sub(vl, vl, tmp);
mpz_mod(vl, vl, n->z);
/* vh = vh*vh - 2*qh (mod n) */
mpz_mul(vh, vh, vh);
mpz_mul_si(tmp, qh, 2);
mpz_sub(vh, vh, tmp);
mpz_mod(vh, vh, n->z);
}
else {
/* qh = ql */
mpz_set(qh, ql);
/* uh = uh*vl - ql (mod n) */
mpz_mul(uh, uh, vl);
mpz_sub(uh, uh, ql);
mpz_mod(uh, uh, n->z);
/* vh = vh*vl - p*ql (mod n) */
mpz_mul(vh, vh, vl);
mpz_mul(tmp, ql, p->z);
mpz_sub(vh, vh, tmp);
mpz_mod(vh, vh, n->z);
/* vl = vl*vl - 2*ql (mod n) */
mpz_mul(vl, vl, vl);
mpz_mul_si(tmp, ql, 2);
mpz_sub(vl, vl, tmp);
mpz_mod(vl, vl, n->z);
}
}
/* ql = ql*qh */
mpz_mul(ql, ql, qh);
/* qh = ql*q */
mpz_mul(qh, ql, q->z);
/* uh = uh*vl - ql */
mpz_mul(uh, uh, vl);
mpz_sub(uh, uh, ql);
/* vl = vh*vl - p*ql */
mpz_mul(vl, vh, vl);
mpz_mul(tmp, ql, p->z);
mpz_sub(vl, vl, tmp);
/* ql = ql*qh */
mpz_mul(ql, ql, qh);
for (j = 1; j <= s; j++) {
/* uh = uh*vl (mod n) */
mpz_mul(uh, uh, vl);
mpz_mod(uh, uh, n->z);
/* vl = vl*vl - 2*ql (mod n) */
mpz_mul(vl, vl, vl);
mpz_mul_si(tmp, ql, 2);
mpz_sub(vl, vl, tmp);
mpz_mod(vl, vl, n->z);
/* ql = ql*ql (mod n) */
mpz_mul(ql, ql, ql);
mpz_mod(ql, ql, n->z);
}
end:
if (!(result = GMPy_MPZ_New(NULL)))
goto cleanup;
/* uh contains our return value */
mpz_mod(result->z, uh, n->z);
cleanup:
mpz_clear(uh);
mpz_clear(vl);
mpz_clear(vh);
mpz_clear(ql);
mpz_clear(qh);
mpz_clear(tmp);
Py_XDECREF((PyObject*)p);
Py_XDECREF((PyObject*)q);
Py_XDECREF((PyObject*)k);
Py_XDECREF((PyObject*)n);
return (PyObject*)result;
}
PyDoc_STRVAR(doc_mpz_lucasv,
"lucasv(p,q,k,/) -> mpz\n\n"
"Return the k-th element of the Lucas V sequence defined by p,q.\n"
"p*p - 4*q must not equal 0; k must be greater than or equal to 0.");
static PyObject *
GMPY_mpz_lucasv(PyObject *self, PyObject *args)
{
/* Adaptation of algorithm found in http://joye.site88.net/papers/JQ96lucas.pdf
* calculate v[k] of Lucas V sequence for p,q.
* Note: p^2-4q=0 is not tested, not a proper Lucas sequence!!
*/
MPZ_Object *result = NULL, *p = NULL, *q = NULL, *k = NULL;
size_t s = 0, j = 0;
mpz_t vl, vh, ql, qh, tmp;
if (PyTuple_Size(args) != 3) {
TYPE_ERROR("lucasv() requires 3 integer arguments");
return NULL;
}
mpz_init(vl);
mpz_init(vh);
mpz_init(ql);
mpz_init(qh);
mpz_init(tmp);
p = GMPy_MPZ_From_Integer(PyTuple_GET_ITEM(args, 0), NULL);
q = GMPy_MPZ_From_Integer(PyTuple_GET_ITEM(args, 1), NULL);
k = GMPy_MPZ_From_Integer(PyTuple_GET_ITEM(args, 2), NULL);
if (!p || !q || !k) {
TYPE_ERROR("lucasv() requires 3 integer arguments");
goto cleanup;
}
/* Check if p*p - 4*q == 0. */
mpz_mul(tmp, p->z, p->z);
mpz_mul_ui(qh, q->z, 4);
mpz_sub(tmp, tmp, qh);
if (mpz_sgn(tmp) == 0) {
VALUE_ERROR("invalid values for p,q in lucasv()");
goto cleanup;
}
/* Check if k < 0. */
if (mpz_sgn(k->z) < 0) {
VALUE_ERROR("invalid value for k in lucasv()");
goto cleanup;
}
mpz_set_si(vl, 2);
mpz_set(vh, p->z);
mpz_set_si(ql, 1);
mpz_set_si(qh, 1);
mpz_set_si(tmp,0);
if (mpz_sgn(k->z) == 0) {
goto end;
}
s = mpz_scan1(k->z, 0);
for (j = mpz_sizeinbase(k->z,2)-1; j >= s+1; j--) {
/* ql = ql*qh */
mpz_mul(ql, ql, qh);
if (mpz_tstbit(k->z,j) == 1) {
/* qh = ql*q */
mpz_mul(qh, ql, q->z);
/* vl = vh*vl - p*ql */
mpz_mul(vl, vh, vl);
mpz_mul(tmp, ql, p->z);
mpz_sub(vl, vl, tmp);
/* vh = vh*vh - 2*qh */
mpz_mul(vh, vh, vh);
mpz_mul_si(tmp, qh, 2);
mpz_sub(vh, vh, tmp);
}
else {
/* qh = ql */
mpz_set(qh, ql);
/* vh = vh*vl - p*ql */
mpz_mul(vh, vh, vl);
mpz_mul(tmp, ql, p->z);
mpz_sub(vh, vh, tmp);
/* vl = vl*vl - 2*ql */
mpz_mul(vl, vl, vl);
mpz_mul_si(tmp, ql, 2);
mpz_sub(vl, vl, tmp);
}
}
/* ql = ql*qh */
mpz_mul(ql, ql, qh);
/* qh = ql*q */
mpz_mul(qh, ql, q->z);
/* vl = vh*vl - p*ql */
mpz_mul(vl, vh, vl);
mpz_mul(tmp, ql, p->z);
mpz_sub(vl, vl, tmp);
/* ql = ql*qh */
mpz_mul(ql, ql, qh);
for (j = 1; j <= s; j++) {
/* vl = vl*vl - 2*ql */
mpz_mul(vl, vl, vl);
mpz_mul_si(tmp, ql, 2);
mpz_sub(vl, vl, tmp);
/* ql = ql*ql */
mpz_mul(ql, ql, ql);
}
end:
if (!(result = GMPy_MPZ_New(NULL)))
goto cleanup;
/* vl contains our return value */
mpz_set(result->z, vl);
cleanup:
mpz_clear(vl);
mpz_clear(vh);
mpz_clear(ql);
mpz_clear(qh);
mpz_clear(tmp);
Py_XDECREF((PyObject*)p);
Py_XDECREF((PyObject*)q);
Py_XDECREF((PyObject*)k);
return (PyObject*)result;
}
PyDoc_STRVAR(doc_mpz_lucasv_mod,
"lucasv_mod(p,q,k,n,/) -> mpz\n\n"
"Return the k-th element of the Lucas V sequence defined by p,q (mod n).\n"
"p*p - 4*q must not equal 0; k must be greater than or equal to 0;\n"
"n must be greater than 0.");
static PyObject *
GMPY_mpz_lucasv_mod(PyObject *self, PyObject *args)
{
/* Adaptation of algorithm found in http://joye.site88.net/papers/JQ96lucas.pdf
* calculate v[k] (modulo n) of Lucas V sequence for p,q.
* Note: p^2-4q=0 is not tested, not a proper Lucas sequence!!
*/
MPZ_Object *result = NULL, *p = NULL, *q = NULL, *k = NULL, *n = NULL;
size_t s = 0, j = 0;
mpz_t vl, vh, ql, qh, tmp;
if (PyTuple_Size(args) != 4) {
TYPE_ERROR("lucasv_mod() requires 4 integer arguments");
return NULL;
}
mpz_init(vl);
mpz_init(vh);
mpz_init(ql);
mpz_init(qh);
mpz_init(tmp);
p = GMPy_MPZ_From_Integer(PyTuple_GET_ITEM(args, 0), NULL);
q = GMPy_MPZ_From_Integer(PyTuple_GET_ITEM(args, 1), NULL);
k = GMPy_MPZ_From_Integer(PyTuple_GET_ITEM(args, 2), NULL);
n = GMPy_MPZ_From_Integer(PyTuple_GET_ITEM(args, 3), NULL);
if (!p || !q || !k || !n) {
TYPE_ERROR("lucasv_mod() requires 4 integer arguments");
goto cleanup;
}
/* Check if p*p - 4*q == 0. */
mpz_mul(tmp, p->z, p->z);
mpz_mul_ui(qh, q->z, 4);
mpz_sub(tmp, tmp, qh);
if (mpz_sgn(tmp) == 0) {
VALUE_ERROR("invalid values for p,q in lucasv_mod()");
goto cleanup;
}
/* Check if k < 0. */
if (mpz_sgn(k->z) < 0) {
VALUE_ERROR("invalid value for k in lucasv_mod()");
goto cleanup;
}
/* Check if n > 0. */
if (mpz_sgn(n->z) <= 0) {
VALUE_ERROR("invalid value for n in lucasv_mod()");
goto cleanup;
}
mpz_set_si(vl, 2);
mpz_set(vh, p->z);
mpz_set_si(ql, 1);
mpz_set_si(qh, 1);
mpz_set_si(tmp,0);
if (mpz_sgn(k->z) == 0) {
goto end;
}
s = mpz_scan1(k->z, 0);
for (j = mpz_sizeinbase(k->z,2)-1; j >= s+1; j--) {
/* ql = ql*qh (mod n) */
mpz_mul(ql, ql, qh);
mpz_mod(ql, ql, n->z);
if (mpz_tstbit(k->z,j) == 1) {
/* qh = ql*q */
mpz_mul(qh, ql, q->z);
/* vl = vh*vl - p*ql (mod n) */
mpz_mul(vl, vh, vl);
mpz_mul(tmp, ql, p->z);
mpz_sub(vl, vl, tmp);
mpz_mod(vl, vl, n->z);
/* vh = vh*vh - 2*qh (mod n) */
mpz_mul(vh, vh, vh);
mpz_mul_si(tmp, qh, 2);
mpz_sub(vh, vh, tmp);
mpz_mod(vh, vh, n->z);
}
else {
/* qh = ql */
mpz_set(qh, ql);
/* vh = vh*vl - p*ql (mod n) */
mpz_mul(vh, vh, vl);
mpz_mul(tmp, ql, p->z);
mpz_sub(vh, vh, tmp);
mpz_mod(vh, vh, n->z);
/* vl = vl*vl - 2*ql (mod n) */
mpz_mul(vl, vl, vl);
mpz_mul_si(tmp, ql, 2);
mpz_sub(vl, vl, tmp);
mpz_mod(vl, vl, n->z);
}
}
/* ql = ql*qh */
mpz_mul(ql, ql, qh);
/* qh = ql*q */
mpz_mul(qh, ql, q->z);
/* vl = vh*vl - p*ql */
mpz_mul(vl, vh, vl);
mpz_mul(tmp, ql, p->z);
mpz_sub(vl, vl, tmp);
/* ql = ql*qh */
mpz_mul(ql, ql, qh);
for (j = 1; j <= s; j++) {
/* vl = vl*vl - 2*ql (mod n) */
mpz_mul(vl, vl, vl);
mpz_mul_si(tmp, ql, 2);
mpz_sub(vl, vl, tmp);
mpz_mod(vl, vl, n->z);
/* ql = ql*ql (mod n) */
mpz_mul(ql, ql, ql);
mpz_mod(ql, ql, n->z);
}
end:
if (!(result = GMPy_MPZ_New(NULL)))
goto cleanup;
/* vl contains our return value */
mpz_mod(result->z, vl, n->z);
cleanup:
mpz_clear(vl);
mpz_clear(vh);
mpz_clear(ql);
mpz_clear(qh);
mpz_clear(tmp);
Py_XDECREF((PyObject*)p);
Py_XDECREF((PyObject*)q);
Py_XDECREF((PyObject*)k);
Py_XDECREF((PyObject*)n);
return (PyObject*)result;
}
././@PaxHeader 0000000 0000000 0000000 00000000026 00000000000 010213 x ustar 00 22 mtime=1710307256.0
gmpy2-2.2.1/src/gmpy_mpz_lucas.h 0000644 0001750 0001750 00000004170 14574233670 015230 0 ustar 00case case /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* gmpy_mpz_lucas.h *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Python interface to the GMP, MPFR, and MPC multiple precision *
* libraries. *
* *
* Copyright 2012 - 2024 Case Van Horsen *
* *
* This file is part of GMPY2. *
* *
* GMPY2 is free software: you can redistribute it and/or modify it under *
* the terms of the GNU Lesser General Public License as published by the *
* Free Software Foundation, either version 3 of the License, or (at your *
* option) any later version. *
* *
* GMPY2 is distributed in the hope that it will be useful, but WITHOUT *
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or *
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public *
* License for more details. *
* *
* You should have received a copy of the GNU Lesser General Public *
* License along with GMPY2; if not, see *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
#ifndef GMPY_LUCAS_H
#define GMPY_LUCAS_H
#ifdef __cplusplus
extern "C" {
#endif
static PyObject * GMPY_mpz_lucasu(PyObject *self, PyObject *args);
static PyObject * GMPY_mpz_lucasu_mod(PyObject *self, PyObject *args);
static PyObject * GMPY_mpz_lucasv(PyObject *self, PyObject *args);
static PyObject * GMPY_mpz_lucasv_mod(PyObject *self, PyObject *args);
#ifdef __cplusplus
}
#endif
#endif
././@PaxHeader 0000000 0000000 0000000 00000000026 00000000000 010213 x ustar 00 22 mtime=1711300127.0
gmpy2-2.2.1/src/gmpy_mpz_prp.c 0000644 0001750 0001750 00000130360 14600057037 014705 0 ustar 00case case /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* gmpy_mpz_prp.c *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Python interface to the GMP, MPFR, and MPC multiple precision *
* libraries. *
* *
* Copyright 2011 David Cleaver *
* *
* Copyright 2012 - 2024 Case Van Horsen *
* *
* The original file is available at: *
* *
* *
* Modified by Case Van Horsen for inclusion into GMPY2. *
* *
* This file is part of GMPY2. *
* *
* GMPY2 is free software: you can redistribute it and/or modify it under *
* the terms of the GNU Lesser General Public License as published by the *
* Free Software Foundation, either version 3 of the License, or (at your *
* option) any later version. *
* *
* GMPY2 is distributed in the hope that it will be useful, but WITHOUT *
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or *
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public *
* License for more details. *
* *
* You should have received a copy of the GNU Lesser General Public *
* License along with GMPY2; if not, see *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
#include "pythoncapi_compat.h"
/* ******************************************************************
* mpz_prp: (also called a Fermat probable prime)
* A "probable prime" to the base a is a number n such that,
* (a,n)=1 and a^(n-1) = 1 mod n
* ******************************************************************/
PyDoc_STRVAR(doc_mpz_is_fermat_prp,
"is_fermat_prp(n,a,/) -> bool\n\n"
"Return `True` if n is a Fermat probable prime to the base a.\n"
"Assuming:\n\n"
" gcd(n,a) == 1\n\n"
"Then a Fermat probable prime requires:\n\n"
" a**(n-1) == 1 (mod n)");
static PyObject *
GMPY_mpz_is_fermat_prp(PyObject *self, PyObject *args)
{
MPZ_Object *a = NULL, *n = NULL;
PyObject *result = NULL;
mpz_t res, nm1;
if (PyTuple_Size(args) != 2) {
TYPE_ERROR("is_fermat_prp() requires 2 integer arguments");
return NULL;
}
mpz_init(res);
mpz_init(nm1);
n = GMPy_MPZ_From_Integer(PyTuple_GET_ITEM(args, 0), NULL);
a = GMPy_MPZ_From_Integer(PyTuple_GET_ITEM(args, 1), NULL);
if (!a || !n) {
TYPE_ERROR("is_fermat_prp() requires 2 integer arguments");
goto cleanup;
}
/* Require a >= 2. */
if (mpz_cmp_ui(a->z, 2) < 0) {
VALUE_ERROR("is_fermat_prp() requires 'a' greater than or equal to 2");
goto cleanup;
}
/* Require n > 0. */
if (mpz_sgn(n->z) <= 0) {
VALUE_ERROR("is_fermat_prp() requires 'n' be greater than 0");
goto cleanup;
}
/* Check for n == 1 */
if (mpz_cmp_ui(n->z, 1) == 0) {
result = Py_False;
goto cleanup;
}
/* Handle n even. */
/* Should n even raise an exception? */
if (mpz_divisible_ui_p(n->z, 2)) {
if (mpz_cmp_ui(n->z, 2) == 0)
result = Py_True;
else
result = Py_False;
goto cleanup;
}
/* Check gcd(a,n) */
mpz_gcd(res, n->z, a->z);
if (mpz_cmp_ui(res, 1) > 0) {
VALUE_ERROR("is_fermat_prp() requires gcd(n,a) == 1");
goto cleanup;
}
mpz_set(nm1, n->z);
mpz_sub_ui(nm1, nm1, 1);
mpz_powm(res, a->z, nm1, n->z);
if (mpz_cmp_ui(res, 1) == 0)
result = Py_True;
else
result = Py_False;
cleanup:
Py_XINCREF(result);
mpz_clear(res);
mpz_clear(nm1);
Py_XDECREF((PyObject*)a);
Py_XDECREF((PyObject*)n);
return result;
}
/* *************************************************************************
* mpz_euler_prp: (also called a Solovay-Strassen probable prime)
* An "Euler probable prime" to the base a is an odd composite number n with,
* (a,n)=1 such that a^((n-1)/2)=(a/n) mod n [(a/n) is the Jacobi symbol]
* *************************************************************************/
PyDoc_STRVAR(doc_mpz_is_euler_prp,
"is_euler_prp(n,a,/) -> bool\n\n"
"Return `True` if n is an Euler (also known as Solovay-Strassen)\n"
"probable prime to the base a.\n"
"Assuming:\n\n"
" gcd(n,a) == 1\n"
" n is odd\n\n"
"Then an Euler probable prime requires:\n\n"
" a**((n-1)/2) == (a/n) (mod n)\n\n"
"where (a/n) is the Jacobi symbol.");
static PyObject *
GMPY_mpz_is_euler_prp(PyObject *self, PyObject *args)
{
MPZ_Object *a = NULL, *n = NULL;
PyObject *result = NULL;
mpz_t res, exp;
int ret;
if (PyTuple_Size(args) != 2) {
TYPE_ERROR("is_euler_prp() requires 2 integer arguments");
return NULL;
}
mpz_init(res);
mpz_init(exp);
n = GMPy_MPZ_From_Integer(PyTuple_GET_ITEM(args, 0), NULL);
a = GMPy_MPZ_From_Integer(PyTuple_GET_ITEM(args, 1), NULL);
if (!a || !n) {
TYPE_ERROR("is_euler_prp() requires 2 integer arguments");
goto cleanup;
}
/* Require a >= 2. */
if (mpz_cmp_ui(a->z, 2) < 0) {
VALUE_ERROR("is_euler_prp() requires 'a' greater than or equal to 2");
goto cleanup;
}
/* Require n > 0. */
if (mpz_sgn(n->z) <= 0) {
VALUE_ERROR("is_euler_prp() requires 'n' be greater than 0");
goto cleanup;
}
/* Check for n == 1 */
if (mpz_cmp_ui(n->z, 1) == 0) {
result = Py_False;
goto cleanup;
}
/* Handle n even. */
if (mpz_divisible_ui_p(n->z, 2)) {
if (mpz_cmp_ui(n->z, 2) == 0)
result = Py_True;
else
result = Py_False;
goto cleanup;
}
/* Check gcd(a,b) */
mpz_gcd(res, n->z, a->z);
if (mpz_cmp_ui(res, 1) > 0) {
VALUE_ERROR("is_euler_prp() requires gcd(n,a) == 1");
goto cleanup;
}
mpz_set(exp, n->z);
mpz_sub_ui(exp, exp, 1);
mpz_divexact_ui(exp, exp, 2);
mpz_powm(res, a->z, exp, n->z);
/* reuse exp to calculate jacobi(a,n) mod n */
ret = mpz_jacobi(a->z,n->z);
mpz_set(exp, n->z);
if (ret == -1)
mpz_sub_ui(exp, exp, 1);
else if (ret == 1)
mpz_add_ui(exp, exp, 1);
mpz_mod(exp, exp, n->z);
if (mpz_cmp(res, exp) == 0)
result = Py_True;
else
result = Py_False;
cleanup:
Py_XINCREF(result);
mpz_clear(res);
mpz_clear(exp);
Py_XDECREF((PyObject*)a);
Py_XDECREF((PyObject*)n);
return result;
}
/* *********************************************************************************************
* mpz_sprp: (also called a Miller-Rabin probable prime)
* A "strong probable prime" to the base a is an odd composite n = (2^r)*s+1 with s odd such that
* either a^s == 1 mod n, or a^((2^t)*s) == -1 mod n, for some integer t, with 0 <= t < r.
* *********************************************************************************************/
PyDoc_STRVAR(doc_mpz_is_strong_prp,
"is_strong_prp(n,a,/) -> bool\n\n"
"Return `True` if n is a strong (also known as Miller-Rabin)\n"
"probable prime to the base a.\n"
"Assuming:\n\n"
" gcd(n,a) == 1\n"
" n is odd\n"
" n = s*(2**r) + 1, with s odd\n\n"
"Then a strong probable prime requires one of the following is true:\n\n"
" a**s == 1 (mod n)\n"
" or\n"
" a**(s*(2**t)) == -1 (mod n) for some t, 0 <= t < r.");
static PyObject *
GMPY_mpz_is_strong_prp(PyObject *self, PyObject *args)
{
MPZ_Object *a = NULL, *n = NULL;
PyObject *result = NULL;
mpz_t s, nm1, mpz_test;
mp_bitcnt_t r = 0;
if (PyTuple_Size(args) != 2) {
TYPE_ERROR("is_strong_prp() requires 2 integer arguments");
return NULL;
}
mpz_init(s);
mpz_init(nm1);
mpz_init(mpz_test);
n = GMPy_MPZ_From_Integer(PyTuple_GET_ITEM(args, 0), NULL);
a = GMPy_MPZ_From_Integer(PyTuple_GET_ITEM(args, 1), NULL);
if (!a || !n) {
TYPE_ERROR("is_strong_prp() requires 2 integer arguments");
goto cleanup;
}
/* Require a >= 2. */
if (mpz_cmp_ui(a->z, 2) < 0) {
VALUE_ERROR("is_strong_prp() requires 'a' greater than or equal to 2");
goto cleanup;
}
/* Require n > 0. */
if (mpz_sgn(n->z) <= 0) {
VALUE_ERROR("is_strong_prp() requires 'n' be greater than 0");
goto cleanup;
}
/* Check for n == 1 */
if (mpz_cmp_ui(n->z, 1) == 0) {
result = Py_False;
goto cleanup;
}
/* Handle n even. */
if (mpz_divisible_ui_p(n->z, 2)) {
if (mpz_cmp_ui(n->z, 2) == 0)
result = Py_True;
else
result = Py_False;
goto cleanup;
}
/* Check gcd(a,b) */
mpz_gcd(s, n->z, a->z);
if (mpz_cmp_ui(s, 1) > 0) {
VALUE_ERROR("is_strong_prp() requires gcd(n,a) == 1");
goto cleanup;
}
mpz_set(nm1, n->z);
mpz_sub_ui(nm1, nm1, 1);
/* Find s and r satisfying: n-1=(2^r)*s, s odd */
r = mpz_scan1(nm1, 0);
mpz_fdiv_q_2exp(s, nm1, r);
/* Check a^((2^t)*s) mod n for 0 <= t < r */
mpz_powm(mpz_test, a->z, s, n->z);
if ((mpz_cmp_ui(mpz_test, 1) == 0) || (mpz_cmp(mpz_test, nm1) == 0)) {
result = Py_True;
goto cleanup;
}
while (--r) {
/* mpz_test = mpz_test^2%n */
mpz_mul(mpz_test, mpz_test, mpz_test);
mpz_mod(mpz_test, mpz_test, n->z);
if (mpz_cmp(mpz_test, nm1) == 0) {
result = Py_True;
goto cleanup;
}
}
result = Py_False;
cleanup:
Py_XINCREF(result);
mpz_clear(s);
mpz_clear(nm1);
mpz_clear(mpz_test);
Py_XDECREF((PyObject*)a);
Py_XDECREF((PyObject*)n);
return result;
}
/* *************************************************************************
* mpz_fibonacci_prp:
* A "Fibonacci probable prime" with parameters (P,Q), P > 0, Q=+/-1, is a
* composite n for which V_n == P mod n
* [V is the Lucas V sequence with parameters P,Q]
* *************************************************************************/
PyDoc_STRVAR(doc_mpz_is_fibonacci_prp,
"is_fibonacci_prp(n,p,q,/) -> bool\n\n"
"Return `True` if n is a Fibonacci probable prime with parameters (p,q).\n"
"Assuming:\n\n"
" n is odd\n"
" p > 0, q = +/-1\n"
" p*p - 4*q != 0\n\n"
"Then a Fibonacci probable prime requires:\n\n"
" lucasv(p,q,n) == p (mod n).");
static PyObject *
GMPY_mpz_is_fibonacci_prp(PyObject *self, PyObject *args)
{
MPZ_Object *n = NULL, *p = NULL, *q = NULL;
PyObject *result = NULL;
mpz_t pmodn, zP;
/* used for calculating the Lucas V sequence */
mpz_t vl, vh, ql, qh, tmp;
mp_bitcnt_t s = 0, j = 0;
if (PyTuple_Size(args) != 3) {
TYPE_ERROR("is_fibonacci_prp() requires 3 integer arguments");
return NULL;
}
mpz_init(pmodn);
mpz_init(zP);
mpz_init(vl);
mpz_init(vh);
mpz_init(ql);
mpz_init(qh);
mpz_init(tmp);
n = GMPy_MPZ_From_Integer(PyTuple_GET_ITEM(args, 0), NULL);
p = GMPy_MPZ_From_Integer(PyTuple_GET_ITEM(args, 1), NULL);
q = GMPy_MPZ_From_Integer(PyTuple_GET_ITEM(args, 2), NULL);
if (!n || !p || !q) {
TYPE_ERROR("is_fibonacci_prp() requires 3 integer arguments");
goto cleanup;
}
/* Check if p*p - 4*q == 0. */
mpz_mul(tmp, p->z, p->z);
mpz_mul_ui(qh, q->z, 4);
mpz_sub(tmp, tmp, qh);
if (mpz_sgn(tmp) == 0) {
VALUE_ERROR("invalid values for p,q in is_fibonacci_prp()");
goto cleanup;
}
/* Verify q = +/-1 */
if ((mpz_cmp_si(q->z, 1) && mpz_cmp_si(q->z, -1)) || (mpz_sgn(p->z) <= 0)) {
VALUE_ERROR("invalid values for p,q in is_fibonacci_prp()");
goto cleanup;
}
/* Require n > 0. */
if (mpz_sgn(n->z) <= 0) {
VALUE_ERROR("is_fibonacci_prp() requires 'n' be greater than 0");
goto cleanup;
}
/* Check for n == 1 */
if (mpz_cmp_ui(n->z, 1) == 0) {
result = Py_False;
goto cleanup;
}
/* Handle n even. */
if (mpz_divisible_ui_p(n->z, 2)) {
if (mpz_cmp_ui(n->z, 2) == 0)
result = Py_True;
else
result = Py_False;
goto cleanup;
}
mpz_set(zP, p->z);
mpz_mod(pmodn, zP, n->z);
/* mpz_lucasvmod(res, p, q, n, n); */
mpz_set_si(vl, 2);
mpz_set(vh, p->z);
mpz_set_si(ql, 1);
mpz_set_si(qh, 1);
mpz_set_si(tmp,0);
s = mpz_scan1(n->z, 0);
for (j = mpz_sizeinbase(n->z,2)-1; j >= s+1; j--) {
/* ql = ql*qh (mod n) */
mpz_mul(ql, ql, qh);
mpz_mod(ql, ql, n->z);
if (mpz_tstbit(n->z,j) == 1) {
/* qh = ql*q */
mpz_mul(qh, ql, q->z);
/* vl = vh*vl - p*ql (mod n) */
mpz_mul(vl, vh, vl);
mpz_mul(tmp, ql, p->z);
mpz_sub(vl, vl, tmp);
mpz_mod(vl, vl, n->z);
/* vh = vh*vh - 2*qh (mod n) */
mpz_mul(vh, vh, vh);
mpz_mul_si(tmp, qh, 2);
mpz_sub(vh, vh, tmp);
mpz_mod(vh, vh, n->z);
}
else {
/* qh = ql */
mpz_set(qh, ql);
/* vh = vh*vl - p*ql (mod n) */
mpz_mul(vh, vh, vl);
mpz_mul(tmp, ql, p->z);
mpz_sub(vh, vh, tmp);
mpz_mod(vh, vh, n->z);
/* vl = vl*vl - 2*ql (mod n) */
mpz_mul(vl, vl, vl);
mpz_mul_si(tmp, ql, 2);
mpz_sub(vl, vl, tmp);
mpz_mod(vl, vl, n->z);
}
}
/* ql = ql*qh */
mpz_mul(ql, ql, qh);
/* qh = ql*q */
mpz_mul(qh, ql, q->z);
/* vl = vh*vl - p*ql */
mpz_mul(vl, vh, vl);
mpz_mul(tmp, ql, p->z);
mpz_sub(vl, vl, tmp);
/* ql = ql*qh */
mpz_mul(ql, ql, qh);
for (j = 1; j <= s; j++) {
/* vl = vl*vl - 2*ql (mod n) */
mpz_mul(vl, vl, vl);
mpz_mul_si(tmp, ql, 2);
mpz_sub(vl, vl, tmp);
mpz_mod(vl, vl, n->z);
/* ql = ql*ql (mod n) */
mpz_mul(ql, ql, ql);
mpz_mod(ql, ql, n->z);
}
/* vl contains our return value */
mpz_mod(vl, vl, n->z);
if (mpz_cmp(vl, pmodn) == 0)
result = Py_True;
else
result = Py_False;
cleanup:
Py_XINCREF(result);
mpz_clear(pmodn);
mpz_clear(zP);
mpz_clear(vl);
mpz_clear(vh);
mpz_clear(ql);
mpz_clear(qh);
mpz_clear(tmp);
Py_XDECREF((PyObject*)p);
Py_XDECREF((PyObject*)q);
Py_XDECREF((PyObject*)n);
return result;
}
/* *******************************************************************************
* mpz_lucas_prp:
* A "Lucas probable prime" with parameters (P,Q) is a composite n with D=P^2-4Q,
* (n,2QD)=1 such that U_(n-(D/n)) == 0 mod n [(D/n) is the Jacobi symbol]
* *******************************************************************************/
PyDoc_STRVAR(doc_mpz_is_lucas_prp,
"is_lucas_prp(n,p,q,/) -> bool\n\n"
"Return `True` if n is a Lucas probable prime with parameters (p,q).\n"
"Assuming:\n\n"
" n is odd\n"
" D = p*p - 4*q, D != 0\n"
" gcd(n, 2*q*D) == 1\n\n"
"Then a Lucas probable prime requires:\n\n"
" lucasu(p,q,n - Jacobi(D,n)) == 0 (mod n)");
static PyObject *
GMPY_mpz_is_lucas_prp(PyObject *self, PyObject *args)
{
MPZ_Object *n = NULL, *p = NULL, *q = NULL;
PyObject *result = NULL;
mpz_t zD, res, index;
/* used for calculating the Lucas U sequence */
mpz_t uh, vl, vh, ql, qh, tmp;
mp_bitcnt_t s = 0, j = 0;
int ret;
if (PyTuple_Size(args) != 3) {
TYPE_ERROR("is_lucas_prp() requires 3 integer arguments");
return NULL;
}
mpz_init(zD);
mpz_init(res);
mpz_init(index);
mpz_init(uh);
mpz_init(vl);
mpz_init(vh);
mpz_init(ql);
mpz_init(qh);
mpz_init(tmp);
n = GMPy_MPZ_From_Integer(PyTuple_GET_ITEM(args, 0), NULL);
p = GMPy_MPZ_From_Integer(PyTuple_GET_ITEM(args, 1), NULL);
q = GMPy_MPZ_From_Integer(PyTuple_GET_ITEM(args, 2), NULL);
if (!n || !p || !q) {
TYPE_ERROR("is_lucas_prp() requires 3 integer arguments");
goto cleanup;
}
/* Check if p*p - 4*q == 0. */
mpz_mul(zD, p->z, p->z);
mpz_mul_ui(tmp, q->z, 4);
mpz_sub(zD, zD, tmp);
if (mpz_sgn(zD) == 0) {
VALUE_ERROR("invalid values for p,q in is_lucas_prp()");
goto cleanup;
}
/* Require n > 0. */
if (mpz_sgn(n->z) <= 0) {
VALUE_ERROR("is_lucas_prp() requires 'n' be greater than 0");
goto cleanup;
}
/* Check for n == 1 */
if (mpz_cmp_ui(n->z, 1) == 0) {
result = Py_False;
goto cleanup;
}
/* Handle n even. */
if (mpz_divisible_ui_p(n->z, 2)) {
if (mpz_cmp_ui(n->z, 2) == 0)
result = Py_True;
else
result = Py_False;
goto cleanup;
}
/* Check GCD */
mpz_mul(res, zD, q->z);
mpz_mul_ui(res, res, 2);
mpz_gcd(res, res, n->z);
if ((mpz_cmp(res, n->z) != 0) && (mpz_cmp_ui(res, 1) > 0)) {
VALUE_ERROR("is_lucas_prp() requires gcd(n,2*q*D) == 1");
goto cleanup;
}
/* index = n-(D/n), where (D/n) is the Jacobi symbol */
mpz_set(index, n->z);
ret = mpz_jacobi(zD, n->z);
if (ret == -1)
mpz_add_ui(index, index, 1);
else if (ret == 1)
mpz_sub_ui(index, index, 1);
/* mpz_lucasumod(res, p, q, index, n); */
mpz_set_si(uh, 1);
mpz_set_si(vl, 2);
mpz_set(vh, p->z);
mpz_set_si(ql, 1);
mpz_set_si(qh, 1);
mpz_set_si(tmp,0);
s = mpz_scan1(index, 0);
for (j = mpz_sizeinbase(index,2)-1; j >= s+1; j--) {
/* ql = ql*qh (mod n) */
mpz_mul(ql, ql, qh);
mpz_mod(ql, ql, n->z);
if (mpz_tstbit(index,j) == 1) {
/* qh = ql*q */
mpz_mul(qh, ql, q->z);
/* uh = uh*vh (mod n) */
mpz_mul(uh, uh, vh);
mpz_mod(uh, uh, n->z);
/* vl = vh*vl - p*ql (mod n) */
mpz_mul(vl, vh, vl);
mpz_mul(tmp, ql, p->z);
mpz_sub(vl, vl, tmp);
mpz_mod(vl, vl, n->z);
/* vh = vh*vh - 2*qh (mod n) */
mpz_mul(vh, vh, vh);
mpz_mul_si(tmp, qh, 2);
mpz_sub(vh, vh, tmp);
mpz_mod(vh, vh, n->z);
}
else {
/* qh = ql */
mpz_set(qh, ql);
/* uh = uh*vl - ql (mod n) */
mpz_mul(uh, uh, vl);
mpz_sub(uh, uh, ql);
mpz_mod(uh, uh, n->z);
/* vh = vh*vl - p*ql (mod n) */
mpz_mul(vh, vh, vl);
mpz_mul(tmp, ql, p->z);
mpz_sub(vh, vh, tmp);
mpz_mod(vh, vh, n->z);
/* vl = vl*vl - 2*ql (mod n) */
mpz_mul(vl, vl, vl);
mpz_mul_si(tmp, ql, 2);
mpz_sub(vl, vl, tmp);
mpz_mod(vl, vl, n->z);
}
}
/* ql = ql*qh */
mpz_mul(ql, ql, qh);
/* qh = ql*q */
mpz_mul(qh, ql, q->z);
/* uh = uh*vl - ql */
mpz_mul(uh, uh, vl);
mpz_sub(uh, uh, ql);
/* vl = vh*vl - p*ql */
mpz_mul(vl, vh, vl);
mpz_mul(tmp, ql, p->z);
mpz_sub(vl, vl, tmp);
/* ql = ql*qh */
mpz_mul(ql, ql, qh);
for (j = 1; j <= s; j++) {
/* uh = uh*vl (mod n) */
mpz_mul(uh, uh, vl);
mpz_mod(uh, uh, n->z);
/* vl = vl*vl - 2*ql (mod n) */
mpz_mul(vl, vl, vl);
mpz_mul_si(tmp, ql, 2);
mpz_sub(vl, vl, tmp);
mpz_mod(vl, vl, n->z);
/* ql = ql*ql (mod n) */
mpz_mul(ql, ql, ql);
mpz_mod(ql, ql, n->z);
}
/* uh contains our return value */
mpz_mod(res, uh, n->z);
if (mpz_cmp_ui(res, 0) == 0)
result = Py_True;
else
result = Py_False;
cleanup:
Py_XINCREF(result);
mpz_clear(zD);
mpz_clear(res);
mpz_clear(index);
mpz_clear(uh);
mpz_clear(vl);
mpz_clear(vh);
mpz_clear(ql);
mpz_clear(qh);
mpz_clear(tmp);
Py_XDECREF((PyObject*)p);
Py_XDECREF((PyObject*)q);
Py_XDECREF((PyObject*)n);
return result;
}
/* *********************************************************************************************
* mpz_stronglucas_prp:
* A "strong Lucas probable prime" with parameters (P,Q) is a composite n = (2^r)*s+(D/n), where
* s is odd, D=P^2-4Q, and (n,2QD)=1 such that either U_s == 0 mod n or V_((2^t)*s) == 0 mod n
* for some t, 0 <= t < r. [(D/n) is the Jacobi symbol]
* *********************************************************************************************/
PyDoc_STRVAR(doc_mpz_is_stronglucas_prp,
"is_strong_lucas_prp(n,p,q,/) -> bool\n\n"
"Return `True` if n is a strong Lucas probable prime with parameters (p,q).\n"
"Assuming:\n\n"
" n is odd\n"
" D = p*p - 4*q, D != 0\n"
" gcd(n, 2*q*D) == 1\n"
" n = s*(2**r) + Jacobi(D,n), s odd\n\n"
"Then a strong Lucas probable prime requires:\n\n"
" lucasu(p,q,s) == 0 (mod n)\n"
" or\n"
" lucasv(p,q,s*(2**t)) == 0 (mod n) for some t, 0 <= t < r");
static PyObject *
GMPY_mpz_is_stronglucas_prp(PyObject *self, PyObject *args)
{
MPZ_Object *n = NULL, *p= NULL, *q = NULL;
PyObject *result = NULL;
mpz_t zD, s, nmj, res;
/* these are needed for the LucasU and LucasV part of this function */
mpz_t uh, vl, vh, ql, qh, tmp;
mp_bitcnt_t r = 0, j = 0;
int ret = 0;
if (PyTuple_Size(args) != 3) {
TYPE_ERROR("is_strong_lucas_prp() requires 3 integer arguments");
return NULL;
}
mpz_init(zD);
mpz_init(s);
mpz_init(nmj);
mpz_init(res);
mpz_init(uh);
mpz_init(vl);
mpz_init(vh);
mpz_init(ql);
mpz_init(qh);
mpz_init(tmp);
n = GMPy_MPZ_From_Integer(PyTuple_GET_ITEM(args, 0), NULL);
p = GMPy_MPZ_From_Integer(PyTuple_GET_ITEM(args, 1), NULL);
q = GMPy_MPZ_From_Integer(PyTuple_GET_ITEM(args, 2), NULL);
if (!n || !p || !q) {
TYPE_ERROR("is_strong_lucas_prp() requires 3 integer arguments");
goto cleanup;
}
/* Check if p*p - 4*q == 0. */
mpz_mul(zD, p->z, p->z);
mpz_mul_ui(tmp, q->z, 4);
mpz_sub(zD, zD, tmp);
if (mpz_sgn(zD) == 0) {
VALUE_ERROR("invalid values for p,q in is_strong_lucas_prp()");
goto cleanup;
}
/* Require n > 0. */
if (mpz_sgn(n->z) <= 0) {
VALUE_ERROR("is_strong_lucas_prp() requires 'n' be greater than 0");
goto cleanup;
}
/* Check for n == 1 */
if (mpz_cmp_ui(n->z, 1) == 0) {
result = Py_False;
goto cleanup;
}
/* Handle n even. */
if (mpz_divisible_ui_p(n->z, 2)) {
if (mpz_cmp_ui(n->z, 2) == 0)
result = Py_True;
else
result = Py_False;
goto cleanup;
}
/* Check GCD */
mpz_mul(res, zD, q->z);
mpz_mul_ui(res, res, 2);
mpz_gcd(res, res, n->z);
if ((mpz_cmp(res, n->z) != 0) && (mpz_cmp_ui(res, 1) > 0)) {
VALUE_ERROR("is_strong_lucas_prp() requires gcd(n,2*q*D) == 1");
goto cleanup;
}
/* nmj = n - (D/n), where (D/n) is the Jacobi symbol */
mpz_set(nmj, n->z);
ret = mpz_jacobi(zD, n->z);
if (ret == -1)
mpz_add_ui(nmj, nmj, 1);
else if (ret == 1)
mpz_sub_ui(nmj, nmj, 1);
r = mpz_scan1(nmj, 0);
mpz_fdiv_q_2exp(s, nmj, r);
/* make sure U_s == 0 mod n or V_((2^t)*s) == 0 mod n, for some t, 0 <= t < r */
mpz_set_si(uh, 1);
mpz_set_si(vl, 2);
mpz_set(vh, p->z);
mpz_set_si(ql, 1);
mpz_set_si(qh, 1);
mpz_set_si(tmp,0);
for (j = mpz_sizeinbase(s,2)-1; j >= 1; j--) {
/* ql = ql*qh (mod n) */
mpz_mul(ql, ql, qh);
mpz_mod(ql, ql, n->z);
if (mpz_tstbit(s,j) == 1) {
/* qh = ql*q */
mpz_mul(qh, ql, q->z);
/* uh = uh*vh (mod n) */
mpz_mul(uh, uh, vh);
mpz_mod(uh, uh, n->z);
/* vl = vh*vl - p*ql (mod n) */
mpz_mul(vl, vh, vl);
mpz_mul(tmp, ql, p->z);
mpz_sub(vl, vl, tmp);
mpz_mod(vl, vl, n->z);
/* vh = vh*vh - 2*qh (mod n) */
mpz_mul(vh, vh, vh);
mpz_mul_si(tmp, qh, 2);
mpz_sub(vh, vh, tmp);
mpz_mod(vh, vh, n->z);
}
else {
/* qh = ql */
mpz_set(qh, ql);
/* uh = uh*vl - ql (mod n) */
mpz_mul(uh, uh, vl);
mpz_sub(uh, uh, ql);
mpz_mod(uh, uh, n->z);
/* vh = vh*vl - p*ql (mod n) */
mpz_mul(vh, vh, vl);
mpz_mul(tmp, ql, p->z);
mpz_sub(vh, vh, tmp);
mpz_mod(vh, vh, n->z);
/* vl = vl*vl - 2*ql (mod n) */
mpz_mul(vl, vl, vl);
mpz_mul_si(tmp, ql, 2);
mpz_sub(vl, vl, tmp);
mpz_mod(vl, vl, n->z);
}
}
/* ql = ql*qh */
mpz_mul(ql, ql, qh);
/* qh = ql*q */
mpz_mul(qh, ql, q->z);
/* uh = uh*vl - ql */
mpz_mul(uh, uh, vl);
mpz_sub(uh, uh, ql);
/* vl = vh*vl - p*ql */
mpz_mul(vl, vh, vl);
mpz_mul(tmp, ql, p->z);
mpz_sub(vl, vl, tmp);
/* ql = ql*qh */
mpz_mul(ql, ql, qh);
mpz_mod(uh, uh, n->z);
mpz_mod(vl, vl, n->z);
/* uh contains LucasU_s and vl contains LucasV_s */
if ((mpz_cmp_ui(uh, 0) == 0) || (mpz_cmp_ui(vl, 0) == 0)) {
result = Py_True;
goto cleanup;
}
for (j = 1; j < r; j++) {
/* vl = vl*vl - 2*ql (mod n) */
mpz_mul(vl, vl, vl);
mpz_mul_si(tmp, ql, 2);
mpz_sub(vl, vl, tmp);
mpz_mod(vl, vl, n->z);
/* ql = ql*ql (mod n) */
mpz_mul(ql, ql, ql);
mpz_mod(ql, ql, n->z);
if (mpz_cmp_ui(vl, 0) == 0) {
result = Py_True;
goto cleanup;
}
}
result = Py_False;
cleanup:
Py_XINCREF(result);
mpz_clear(zD);
mpz_clear(s);
mpz_clear(nmj);
mpz_clear(res);
mpz_clear(uh);
mpz_clear(vl);
mpz_clear(vh);
mpz_clear(ql);
mpz_clear(qh);
mpz_clear(tmp);
Py_XDECREF((PyObject*)p);
Py_XDECREF((PyObject*)q);
Py_XDECREF((PyObject*)n);
return result;
}
/* *******************************************************************************************
* mpz_extrastronglucas_prp:
* Let U_n = LucasU(p,1), V_n = LucasV(p,1), and D=p^2-4.
* An "extra strong Lucas probable prime" to the base p is a composite n = (2^r)*s+(D/n), where
* s is odd and (n,2D)=1, such that either U_s == 0 mod n and V_s == +/-2 mod n, or
* V_((2^t)*s) == 0 mod n for some t with 0 <= t < r-1 [(D/n) is the Jacobi symbol]
* *******************************************************************************************/
PyDoc_STRVAR(doc_mpz_is_extrastronglucas_prp,
"is_extra_strong_lucas_prp(n,p,/) -> bool\n\n"
"Return `True` if n is an extra strong Lucas probable prime with parameters\n"
"(p,1). Assuming:\n\n"
" n is odd\n"
" D = p*p - 4, D != 0\n"
" gcd(n, 2*D) == 1\n"
" n = s*(2**r) + Jacobi(D,n), s odd\n\n"
"Then an extra strong Lucas probable prime requires:\n\n"
" lucasu(p,1,s) == 0 (mod n) and lucasv(p,1,s) == +/-2 (mod n)\n"
" or\n"
" lucasv(p,1,s*(2**t)) == 0 (mod n) for some t, 0 <= t < r");
static PyObject *
GMPY_mpz_is_extrastronglucas_prp(PyObject *self, PyObject *args)
{
MPZ_Object *n = NULL, *p = NULL;
PyObject *result = NULL;
mpz_t zD, s, nmj, nm2, res;
/* these are needed for the LucasU and LucasV part of this function */
mpz_t uh, vl, vh, ql, qh, tmp;
mp_bitcnt_t r = 0, j = 0;
long int q = 1;
int ret = 0;
if (PyTuple_Size(args) != 2) {
TYPE_ERROR("is_extra_strong_lucas_prp() requires 2 integer arguments");
return NULL;
}
mpz_init(zD);
mpz_init(s);
mpz_init(nmj);
mpz_init(nm2);
mpz_init(res);
mpz_init(uh);
mpz_init(vl);
mpz_init(vh);
mpz_init(ql);
mpz_init(qh);
mpz_init(tmp);
n = GMPy_MPZ_From_Integer(PyTuple_GET_ITEM(args, 0), NULL);
p = GMPy_MPZ_From_Integer(PyTuple_GET_ITEM(args, 1), NULL);
if (!n || !p) {
TYPE_ERROR("is_extra_strong_lucas_prp() requires 2 integer arguments");
goto cleanup;
}
/* Check if p*p - 4 == 0. */
mpz_mul(zD, p->z, p->z);
mpz_sub_ui(zD, zD, 4);
if (mpz_sgn(zD) == 0) {
VALUE_ERROR("invalid value for p in is_extra_strong_lucas_prp()");
goto cleanup;
}
/* Require n > 0. */
if (mpz_sgn(n->z) <= 0) {
VALUE_ERROR("is_extra_strong_lucas_prp() requires 'n' be greater than 0");
goto cleanup;
}
/* Check for n == 1 */
if (mpz_cmp_ui(n->z, 1) == 0) {
result = Py_False;
goto cleanup;
}
/* Handle n even. */
if (mpz_divisible_ui_p(n->z, 2)) {
if (mpz_cmp_ui(n->z, 2) == 0)
result = Py_True;
else
result = Py_False;
goto cleanup;
}
/* Check GCD */
mpz_mul_ui(res, zD, 2);
mpz_gcd(res, res, n->z);
if ((mpz_cmp(res, n->z) != 0) && (mpz_cmp_ui(res, 1) > 0)) {
VALUE_ERROR("is_extra_strong_lucas_prp() requires gcd(n,2*D) == 1");
goto cleanup;
}
/* nmj = n - (D/n), where (D/n) is the Jacobi symbol */
mpz_set(nmj, n->z);
ret = mpz_jacobi(zD, n->z);
if (ret == -1)
mpz_add_ui(nmj, nmj, 1);
else if (ret == 1)
mpz_sub_ui(nmj, nmj, 1);
r = mpz_scan1(nmj, 0);
mpz_fdiv_q_2exp(s, nmj, r);
mpz_set(nm2, n->z);
mpz_sub_ui(nm2, nm2, 2);
/* make sure that either U_s == 0 mod n and V_s == +/-2 mod n, or */
/* V_((2^t)*s) == 0 mod n for some t with 0 <= t < r-1 */
mpz_set_si(uh, 1);
mpz_set_si(vl, 2);
mpz_set(vh, p->z);
mpz_set_si(ql, 1);
mpz_set_si(qh, 1);
mpz_set_si(tmp,0);
for (j = mpz_sizeinbase(s,2)-1; j >= 1; j--) {
/* ql = ql*qh (mod n) */
mpz_mul(ql, ql, qh);
mpz_mod(ql, ql, n->z);
if (mpz_tstbit(s,j) == 1) {
/* qh = ql*q */
mpz_mul_si(qh, ql, q);
/* uh = uh*vh (mod n) */
mpz_mul(uh, uh, vh);
mpz_mod(uh, uh, n->z);
/* vl = vh*vl - p*ql (mod n) */
mpz_mul(vl, vh, vl);
mpz_mul(tmp, ql, p->z);
mpz_sub(vl, vl, tmp);
mpz_mod(vl, vl, n->z);
/* vh = vh*vh - 2*qh (mod n) */
mpz_mul(vh, vh, vh);
mpz_mul_si(tmp, qh, 2);
mpz_sub(vh, vh, tmp);
mpz_mod(vh, vh, n->z);
}
else {
/* qh = ql */
mpz_set(qh, ql);
/* uh = uh*vl - ql (mod n) */
mpz_mul(uh, uh, vl);
mpz_sub(uh, uh, ql);
mpz_mod(uh, uh, n->z);
/* vh = vh*vl - p*ql (mod n) */
mpz_mul(vh, vh, vl);
mpz_mul(tmp, ql, p->z);
mpz_sub(vh, vh, tmp);
mpz_mod(vh, vh, n->z);
/* vl = vl*vl - 2*ql (mod n) */
mpz_mul(vl, vl, vl);
mpz_mul_si(tmp, ql, 2);
mpz_sub(vl, vl, tmp);
mpz_mod(vl, vl, n->z);
}
}
/* ql = ql*qh */
mpz_mul(ql, ql, qh);
/* qh = ql*q */
mpz_mul_si(qh, ql, q);
/* uh = uh*vl - ql */
mpz_mul(uh, uh, vl);
mpz_sub(uh, uh, ql);
/* vl = vh*vl - p*ql */
mpz_mul(vl, vh, vl);
mpz_mul(tmp, ql, p->z);
mpz_sub(vl, vl, tmp);
/* ql = ql*qh */
mpz_mul(ql, ql, qh);
mpz_mod(uh, uh, n->z);
mpz_mod(vl, vl, n->z);
/* tmp = n-2, for the following comparison */
mpz_sub_ui(tmp, n->z, 2);
/* uh contains LucasU_s and vl contains LucasV_s */
if ( ((mpz_cmp_ui(uh, 0) == 0)
&&
((mpz_cmp(vl, tmp) == 0) || (mpz_cmp_si(vl, 2) == 0))
)
||
(mpz_cmp_ui(vl, 0) == 0)
) {
result = Py_True;
goto cleanup;
}
for (j = 1; j < r-1; j++) {
/* vl = vl*vl - 2*ql (mod n) */
mpz_mul(vl, vl, vl);
mpz_mul_si(tmp, ql, 2);
mpz_sub(vl, vl, tmp);
mpz_mod(vl, vl, n->z);
/* ql = ql*ql (mod n) */
mpz_mul(ql, ql, ql);
mpz_mod(ql, ql, n->z);
if (mpz_cmp_ui(vl, 0) == 0) {
result = Py_True;
goto cleanup;
}
}
result = Py_False;
cleanup:
Py_XINCREF(result);
mpz_clear(zD);
mpz_clear(s);
mpz_clear(nmj);
mpz_clear(nm2);
mpz_clear(res);
mpz_clear(uh);
mpz_clear(vl);
mpz_clear(vh);
mpz_clear(ql);
mpz_clear(qh);
mpz_clear(tmp);
Py_XDECREF((PyObject*)p);
Py_XDECREF((PyObject*)n);
return result;
}
/* ***********************************************************************************************
* mpz_selfridge_prp:
* A "Lucas-Selfridge probable prime" n is a "Lucas probable prime" using Selfridge parameters of:
* Find the first element D in the sequence {5, -7, 9, -11, 13, ...} such that Jacobi(D,n) = -1
* Then use P=1 and Q=(1-D)/4 in the Lucas probable prime test.
* Make sure n is not a perfect square, otherwise the search for D will only stop when D=n.
* ***********************************************************************************************/
PyDoc_STRVAR(doc_mpz_is_selfridge_prp,
"is_selfridge_prp(n, /) -> bool\n\n"
"Return `True` if n is a Lucas probable prime with Selfidge parameters\n"
"(p,q). The Selfridge parameters are chosen by finding the first\n"
"element D in the sequence {5, -7, 9, -11, 13, ...} such that\n"
"Jacobi(D,n) == -1. Then let p=1 and q = (1-D)/4. Then perform\n"
"a Lucas probable prime test.");
static PyObject *
GMPY_mpz_is_selfridge_prp(PyObject *self, PyObject *args)
{
MPZ_Object *n = NULL;
PyObject *result = NULL, *temp = NULL;
long d = 5, p = 1, q = 0, max_d = 1000000;
int jacobi = 0;
mpz_t zD;
if (PyTuple_Size(args) != 1) {
TYPE_ERROR("is_selfridge_prp() requires 1 integer argument");
return NULL;
}
mpz_init(zD);
n = GMPy_MPZ_From_Integer(PyTuple_GET_ITEM(args, 0), NULL);
if (!n) {
TYPE_ERROR("is_selfridge_prp() requires 1 integer argument");
goto cleanup;
}
/* Require n > 0. */
if (mpz_sgn(n->z) <= 0) {
VALUE_ERROR("is_selfridge_prp() requires 'n' be greater than 0");
goto cleanup;
}
/* Check for n == 1 */
if (mpz_cmp_ui(n->z, 1) == 0) {
result = Py_False;
goto cleanup;
}
/* Handle n even. */
if (mpz_divisible_ui_p(n->z, 2)) {
if (mpz_cmp_ui(n->z, 2) == 0)
result = Py_True;
else
result = Py_False;
goto cleanup;
}
mpz_set_ui(zD, d);
while (1) {
jacobi = mpz_jacobi(zD, n->z);
/* if jacobi == 0, d is a factor of n, therefore n is composite... */
/* if d == n, then either n is either prime or 9... */
if (jacobi == 0) {
if ((mpz_cmpabs(zD, n->z) == 0) && (mpz_cmp_ui(zD, 9) != 0)) {
result = Py_True;
goto cleanup;
}
else {
result = Py_False;
goto cleanup;
}
}
if (jacobi == -1)
break;
/* if we get to the 5th d, make sure we aren't dealing with a square... */
if (d == 13) {
if (mpz_perfect_square_p(n->z)) {
result = Py_False;
goto cleanup;
}
}
if (d < 0) {
d *= -1;
d += 2;
}
else {
d += 2;
d *= -1;
}
/* make sure we don't search forever */
if (d >= max_d) {
VALUE_ERROR("appropriate value for D cannot be found in is_selfridge_prp()");
goto cleanup;
}
mpz_set_si(zD, d);
}
q = (1-d)/4;
/* Since "O" is used, the refcount for n is incremented so deleting
* temp will not delete n.
*/
temp = Py_BuildValue("Oll", n, p, q);
if (!temp)
goto cleanup;
result = GMPY_mpz_is_lucas_prp(NULL, temp);
Py_DECREF(temp);
goto return_result;
cleanup:
Py_XINCREF(result);
return_result:
mpz_clear(zD);
Py_DECREF((PyObject*)n);
return result;
}
/* *********************************************************************************************************
* mpz_strongselfridge_prp:
* A "strong Lucas-Selfridge probable prime" n is a "strong Lucas probable prime" using Selfridge parameters of:
* Find the first element D in the sequence {5, -7, 9, -11, 13, ...} such that Jacobi(D,n) = -1
* Then use P=1 and Q=(1-D)/4 in the strong Lucas probable prime test.
* Make sure n is not a perfect square, otherwise the search for D will only stop when D=n.
* **********************************************************************************************************/
PyDoc_STRVAR(doc_mpz_is_strongselfridge_prp,
"is_strong_selfridge_prp(n, /) -> bool\n\n"
"Return `True` if n is a strong Lucas probable prime with Selfidge\n"
"parameters (p,q). The Selfridge parameters are chosen by finding\n"
"the first element D in the sequence {5, -7, 9, -11, 13, ...} such\n"
"that Jacobi(D,n) == -1. Then let p=1 and q = (1-D)/4. Then perform\n"
"a strong Lucas probable prime test.");
static PyObject *
GMPY_mpz_is_strongselfridge_prp(PyObject *self, PyObject *args)
{
MPZ_Object *n = NULL;
PyObject *result = NULL, *temp = NULL;
long d = 5, p = 1, q = 0, max_d = 1000000;
int jacobi = 0;
mpz_t zD;
if (PyTuple_Size(args) != 1) {
TYPE_ERROR("is_strong_selfridge_prp() requires 1 integer argument");
return NULL;
}
mpz_init(zD);
n = GMPy_MPZ_From_Integer(PyTuple_GET_ITEM(args, 0), NULL);
if (!n) {
TYPE_ERROR("is_strong_selfridge_prp() requires 1 integer argument");
goto cleanup;
}
/* Require n > 0. */
if (mpz_sgn(n->z) <= 0) {
VALUE_ERROR("is_strong_selfridge_prp() requires 'n' be greater than 0");
goto cleanup;
}
/* Check for n == 1 */
if (mpz_cmp_ui(n->z, 1) == 0) {
result = Py_False;
goto cleanup;
}
/* Handle n even. */
if (mpz_divisible_ui_p(n->z, 2)) {
if (mpz_cmp_ui(n->z, 2) == 0)
result = Py_True;
else
result = Py_False;
goto cleanup;
}
mpz_set_ui(zD, d);
while (1) {
jacobi = mpz_jacobi(zD, n->z);
/* if jacobi == 0, d is a factor of n, therefore n is composite... */
/* if d == n, then either n is either prime or 9... */
if (jacobi == 0) {
if ((mpz_cmpabs(zD, n->z) == 0) && (mpz_cmp_ui(zD, 9) != 0)) {
result = Py_True;
goto cleanup;
}
else {
result = Py_False;
goto cleanup;
}
}
if (jacobi == -1)
break;
/* if we get to the 5th d, make sure we aren't dealing with a square... */
if (d == 13) {
if (mpz_perfect_square_p(n->z)) {
result = Py_False;
goto cleanup;
}
}
if (d < 0) {
d *= -1;
d += 2;
}
else {
d += 2;
d *= -1;
}
/* make sure we don't search forever */
if (d >= max_d) {
VALUE_ERROR("appropriate value for D cannot be found in is_strong_selfridge_prp()");
goto cleanup;
}
mpz_set_si(zD, d);
}
q = (1-d)/4;
/* Since "O" is used, the refcount for n is incremented so deleting
* temp will not delete n.
*/
temp = Py_BuildValue("Oll", n, p, q);
if (!temp)
goto cleanup;
result = GMPY_mpz_is_stronglucas_prp(NULL, temp);
Py_DECREF(temp);
goto return_result;
cleanup:
Py_XINCREF(result);
return_result:
mpz_clear(zD);
Py_DECREF((PyObject*)n);
return result;
}
/* **********************************************************************************
* mpz_bpsw_prp:
* A "Baillie-Pomerance-Selfridge-Wagstaff probable prime" is a composite n such that
* n is a strong probable prime to the base 2 and
* n is a Lucas probable prime using the Selfridge parameters.
* **********************************************************************************/
PyDoc_STRVAR(doc_mpz_is_bpsw_prp,
"is_bpsw_prp(n, /) -> bool\n\n"
"Return `True` if n is a Baillie-Pomerance-Selfridge-Wagstaff probable\n"
"prime. A BPSW probable prime passes the `is_strong_prp()` test with base\n"
"2 and the `is_selfridge_prp()` test.\n");
static PyObject *
GMPY_mpz_is_bpsw_prp(PyObject *self, PyObject *args)
{
MPZ_Object *n = NULL;
PyObject *result = NULL, *temp = NULL;
if (PyTuple_Size(args) != 1) {
TYPE_ERROR("is_bpsw_prp() requires 1 integer argument");
return NULL;
}
n = GMPy_MPZ_From_Integer(PyTuple_GET_ITEM(args, 0), NULL);
if (!n) {
TYPE_ERROR("is_bpsw_prp() requires 1 integer argument");
goto cleanup;
}
/* Require n > 0. */
if (mpz_sgn(n->z) <= 0) {
VALUE_ERROR("is_bpsw_prp() requires 'n' be greater than 0");
goto cleanup;
}
/* Check for n == 1 */
if (mpz_cmp_ui(n->z, 1) == 0) {
result = Py_False;
goto cleanup;
}
/* Handle n even. */
if (mpz_divisible_ui_p(n->z, 2)) {
if (mpz_cmp_ui(n->z, 2) == 0)
result = Py_True;
else
result = Py_False;
goto cleanup;
}
/* "O" is used to increment the reference to n so deleting temp won't
* delete n.
*/
temp = Py_BuildValue("Oi", n, 2);
if (!temp)
goto cleanup;
result = GMPY_mpz_is_strong_prp(NULL, temp);
Py_DECREF(temp);
if (Py_IsFalse(result))
goto return_result;
/* Remember to ignore the preceding result */
Py_DECREF(result);
temp = PyTuple_Pack(1, n);
if (!temp)
goto cleanup;
result = GMPY_mpz_is_selfridge_prp(NULL, temp);
Py_DECREF(temp);
goto return_result;
cleanup:
Py_XINCREF(result);
return_result:
Py_DECREF((PyObject*)n);
return result;
}
/* ****************************************************************************************
* mpz_strongbpsw_prp:
* A "strong Baillie-Pomerance-Selfridge-Wagstaff probable prime" is a composite n such that
* n is a strong probable prime to the base 2 and
* n is a strong Lucas probable prime using the Selfridge parameters.
* ****************************************************************************************/
PyDoc_STRVAR(doc_mpz_is_strongbpsw_prp,
"is_strong_bpsw_prp(n, /) -> bool\n\n"
"Return `True` if n is a strong Baillie-Pomerance-Selfridge-Wagstaff\n"
"probable prime. A strong BPSW probable prime passes the `is_strong_prp()`\n"
"test with base and the `is_strong_selfridge_prp()` test.\n");
static PyObject *
GMPY_mpz_is_strongbpsw_prp(PyObject *self, PyObject *args)
{
MPZ_Object *n = NULL;
PyObject *result = NULL, *temp = NULL;
if (PyTuple_Size(args) != 1) {
TYPE_ERROR("is_strong_bpsw_prp() requires 1 integer argument");
return NULL;
}
n = GMPy_MPZ_From_Integer(PyTuple_GET_ITEM(args, 0), NULL);
if (!n) {
TYPE_ERROR("is_strong_bpsw_prp() requires 1 integer argument");
goto cleanup;
}
/* Require n > 0. */
if (mpz_sgn(n->z) <= 0) {
VALUE_ERROR("is_strong_bpsw_prp() requires 'n' be greater than 0");
goto cleanup;
}
/* Check for n == 1 */
if (mpz_cmp_ui(n->z, 1) == 0) {
result = Py_False;
goto cleanup;
}
/* Handle n even. */
if (mpz_divisible_ui_p(n->z, 2)) {
if (mpz_cmp_ui(n->z, 2) == 0)
result = Py_True;
else
result = Py_False;
goto cleanup;
}
/* "O" is used to increment the reference to n so deleting temp won't
* delete n.
*/
temp = Py_BuildValue("Oi", n, 2);
if (!temp)
goto cleanup;
result = GMPY_mpz_is_strong_prp(NULL, temp);
Py_DECREF(temp);
if (Py_IsFalse(result))
goto return_result;
/* Remember to ignore the preceding result */
Py_DECREF(result);
temp = PyTuple_Pack(1, n);
if (!temp)
goto cleanup;
result = GMPY_mpz_is_strongselfridge_prp(NULL, temp);
Py_DECREF(temp);
goto return_result;
cleanup:
Py_XINCREF(result);
return_result:
Py_DECREF((PyObject*)n);
return result;
}
././@PaxHeader 0000000 0000000 0000000 00000000026 00000000000 010213 x ustar 00 22 mtime=1710307256.0
gmpy2-2.2.1/src/gmpy_mpz_prp.h 0000644 0001750 0001750 00000005254 14574233670 014726 0 ustar 00case case /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* gmpy_mpz_prp.h *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Python interface to the GMP, MPFR, and MPC multiple precision *
* libraries. *
* *
* Copyright 2012 - 2024 Case Van Horsen *
* *
* This file is part of GMPY2. *
* *
* GMPY2 is free software: you can redistribute it and/or modify it under *
* the terms of the GNU Lesser General Public License as published by the *
* Free Software Foundation, either version 3 of the License, or (at your *
* option) any later version. *
* *
* GMPY2 is distributed in the hope that it will be useful, but WITHOUT *
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or *
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public *
* License for more details. *
* *
* You should have received a copy of the GNU Lesser General Public *
* License along with GMPY2; if not, see *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
#ifndef GMPY_PRP_H
#define GMPY_PRP_H
#ifdef __cplusplus
extern "C" {
#endif
static PyObject * GMPY_mpz_is_fermat_prp(PyObject *self, PyObject *args);
static PyObject * GMPY_mpz_is_euler_prp(PyObject *self, PyObject *args);
static PyObject * GMPY_mpz_is_strong_prp(PyObject *self, PyObject *args);
static PyObject * GMPY_mpz_is_fibonacci_prp(PyObject *self, PyObject *args);
static PyObject * GMPY_mpz_is_lucas_prp(PyObject *self, PyObject *args);
static PyObject * GMPY_mpz_is_stronglucas_prp(PyObject *self, PyObject *args);
static PyObject * GMPY_mpz_is_extrastronglucas_prp(PyObject *self, PyObject *args);
static PyObject * GMPY_mpz_is_selfridge_prp(PyObject *self, PyObject *args);
static PyObject * GMPY_mpz_is_strongselfridge_prp(PyObject *self, PyObject *args);
static PyObject * GMPY_mpz_is_bpsw_prp(PyObject *self, PyObject *args);
static PyObject * GMPY_mpz_is_strongbpsw_prp(PyObject *self, PyObject *args);
#ifdef __cplusplus
}
#endif
#endif
././@PaxHeader 0000000 0000000 0000000 00000000026 00000000000 010213 x ustar 00 22 mtime=1711300127.0
gmpy2-2.2.1/src/mpz_pylong.c 0000644 0001750 0001750 00000016346 14600057037 014367 0 ustar 00case case /* mpz <-> pylong conversion and "pythonhash" for mpz
*
* Originally written for sage (http://sagemath.org) by Gonzalo Tornaría
* . If you improve on these functions, please
* contribute them back to sage by posting to sage-devel@googlegroups.com
* or by sending an email to the original author.
*
* Integration with gmpy2 by Case Van Horsen .
*
* License: LGPL v2 or later
*
*/
#include "pythoncapi_compat.h"
/* This file created by merging mpn_pylong and mpz_pylong. Permission
* was granted by the original author to make this code available under
* the LGPLv2+ license.
*/
/* This code assumes that SHIFT < GMP_NUMB_BITS */
#if PyLong_SHIFT >= GMP_NUMB_BITS
#error "Python limb larger than GMP limb !!!"
#endif
#ifndef ABS
#define ABS(a) (((a) < 0) ? -(a) : (a))
#endif
/* Use these "portable" (I hope) sizebits functions.
* We could implement this in terms of count_leading_zeros from GMP,
* but it is not exported!
*/
static const
unsigned char
__sizebits_tab[128] =
{
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
};
#if GMP_LIMB_BITS > 64
#error "word size > 64 unsupported"
#endif
static inline
size_t
mpn_sizebits(mp_ptr up, size_t un) {
size_t cnt;
mp_limb_t x;
if (un==0)
return 0;
cnt = (un - 1) * GMP_NUMB_BITS;
x = up[un - 1];
#if GMP_LIMB_BITS > 32
if ((x >> 32) != 0) { x >>= 32; cnt += 32; }
#endif
#if GMP_LIMB_BITS > 16
if ((x >> 16) != 0) { x >>= 16; cnt += 16; }
#endif
#if GMP_LIMB_BITS > 8
if ((x >> 8) != 0) { x >>= 8; cnt += 8; }
#endif
return cnt + ((x & 0x80) ? 8 : __sizebits_tab[x]);
}
static inline
size_t
pylong_sizebits(digit *digits, size_t size) {
size_t cnt;
digit x;
if (size==0)
return 0;
cnt = (size - 1) * PyLong_SHIFT;
x = digits[size - 1];
#if PyLong_SHIFT > 32
if ((x >> 32) != 0) { x >>= 32; cnt += 32; }
#endif
#if PyLong_SHIFT > 16
if ((x >> 16) != 0) { x >>= 16; cnt += 16; }
#endif
#if PyLong_SHIFT > 8
if ((x >> 8) != 0) { x >>= 8; cnt += 8; }
#endif
return cnt + ((x & 0x80) ? 8 : __sizebits_tab[x]);
}
/* mpn -> pylong conversion */
size_t
mpn_pylong_size (mp_ptr up, size_t un)
{
return (mpn_sizebits(up, un) + PyLong_SHIFT - 1) / PyLong_SHIFT;
}
/* this is based from GMP code in mpn/get_str.c */
/* Assume digits points to a chunk of size size
* where size >= mpn_pylong_size(up, un)
*/
void
mpn_get_pylong (digit *digits, size_t size, mp_ptr up, size_t un)
{
mp_limb_t n1, n0;
size_t i;
ssize_t bit_pos;
/* point past the allocated chunk */
digit *s = digits + size;
/* input length 0 is special ! */
if (un == 0) {
while (size) digits[--size] = 0;
return;
}
i = un - 1;
n1 = up[i];
bit_pos = size * PyLong_SHIFT - i * GMP_NUMB_BITS;
for (;;) {
bit_pos -= PyLong_SHIFT;
while (bit_pos >= 0) {
*--s = (n1 >> bit_pos) & PyLong_MASK;
bit_pos -= PyLong_SHIFT;
}
if (i == 0)
break;
n0 = (n1 << -bit_pos) & PyLong_MASK;
n1 = up[--i];
bit_pos += GMP_NUMB_BITS;
*--s = (digit)(n0 | (n1 >> bit_pos));
}
}
/* pylong -> mpn conversion */
size_t
mpn_size_from_pylong (digit *digits, size_t size)
{
return (pylong_sizebits(digits, size) + GMP_NUMB_BITS - 1) / GMP_NUMB_BITS;
}
void
mpn_set_pylong(mp_ptr up, size_t un, digit *digits, size_t size)
{
mp_limb_t n1, d;
size_t i;
ssize_t bit_pos;
/* point past the allocated chunk */
digit * s = digits + size;
/* input length 0 is special ! */
if (size == 0) {
while (un) up[--un] = 0;
return;
}
i = un - 1;
n1 = 0;
bit_pos = size * PyLong_SHIFT - i * GMP_NUMB_BITS;
for (;;) {
bit_pos -= PyLong_SHIFT;
while (bit_pos >= 0) {
d = (mp_limb_t) *--s;
n1 |= (d << bit_pos) & GMP_NUMB_MASK;
bit_pos -= PyLong_SHIFT;
}
if (i == 0)
break;
d = (mp_limb_t) *--s;
/* add some high bits of d; maybe none if bit_pos=-SHIFT */
up[i--] = n1 | (d & PyLong_MASK) >> -bit_pos;
bit_pos += GMP_NUMB_BITS;
n1 = (d << bit_pos) & GMP_NUMB_MASK;
}
up[0] = n1;
}
/************************************************************/
/* Hashing functions */
#define LONG_BIT_SHIFT (8*sizeof(long) - PyLong_SHIFT)
/*
* for an mpz, this number has to be multiplied by the sign
* also remember to catch -1 and map it to -2 !
*/
long
mpn_pythonhash (mp_ptr up, mp_size_t un)
{
mp_limb_t n1, n0;
mp_size_t i;
ssize_t bit_pos;
long x = 0;
/* input length 0 is special ! */
if (un == 0)
return 0;
i = un - 1;
n1 = up[i];
{
size_t bits;
bits = mpn_sizebits(up, un) + PyLong_SHIFT - 1;
bits -= bits % PyLong_SHIFT;
/* position of the MSW in base 2^SHIFT, counted from the MSW in
* the GMP representation (in base 2^GMP_NUMB_BITS)
*/
bit_pos = bits - i * GMP_NUMB_BITS;
}
for (;;) {
while (bit_pos >= 0) {
/* Force a native long #-bits (32 or 64) circular shift */
x = ((x << PyLong_SHIFT) & ~(long)PyLong_MASK) | ((x >> LONG_BIT_SHIFT) & (long)PyLong_MASK);
/* Shifting to the right by more than wordsize bits
* actually shifts by (wordsize % 32) bits -- which is
* *not* the intended behavior here. */
if (bit_pos <= 8*sizeof(mp_limb_t))
x += (n1 >> bit_pos) & (long)PyLong_MASK;
bit_pos -= PyLong_SHIFT;
}
i--;
if (i < 0)
break;
n0 = (n1 << -bit_pos) & (long)PyLong_MASK;
n1 = up[i];
bit_pos += GMP_NUMB_BITS;
/* Force a native long #-bits (32 or 64) circular shift */
x = ((x << PyLong_SHIFT) & ~(long)PyLong_MASK) | ((x >> LONG_BIT_SHIFT) & (long)PyLong_MASK);
x += (long)(n0 | (n1 >> bit_pos));
bit_pos -= PyLong_SHIFT;
}
return x;
}
/* mpz python hash */
long
mpz_pythonhash(mpz_srcptr z)
{
long x = mpn_pythonhash(z->_mp_d, ABS(z->_mp_size));
if (z->_mp_size < 0)
x = -x;
if (x == -1)
x = -2;
return x;
}
/* mpz -> pylong conversion */
PyObject *
mpz_get_PyLong(mpz_srcptr z)
{
size_t size = mpn_pylong_size(z->_mp_d, ABS(z->_mp_size));
PyLongObject *lptr = PyObject_NewVar(PyLongObject, &PyLong_Type, size);
if (lptr != NULL) {
mpn_get_pylong(lptr->ob_digit, size, z->_mp_d, ABS(z->_mp_size));
if (z->_mp_size < 0)
Py_SET_SIZE(lptr, -(Py_SIZE(lptr)));
}
return (PyObject*)lptr;
}
/* pylong -> mpz conversion */
void
mpz_set_PyLong(mpz_ptr z, PyObject *lsrc)
{
register PyLongObject *lptr = (PyLongObject*)lsrc;
ssize_t size;
size = (ssize_t)mpn_size_from_pylong(lptr->ob_digit, ABS(Py_SIZE(lptr)));
if (z->_mp_alloc < size)
_mpz_realloc(z, (mp_size_t)size);
mpn_set_pylong(z->_mp_d, size, lptr->ob_digit, ABS(Py_SIZE(lptr)));
z->_mp_size = (int)(Py_SIZE(lptr) < 0 ? -size : size);
return;
}
././@PaxHeader 0000000 0000000 0000000 00000000026 00000000000 010213 x ustar 00 22 mtime=1711300127.0
gmpy2-2.2.1/src/pythoncapi_compat.h 0000644 0001750 0001750 00000077576 14600057037 015733 0 ustar 00case case // Header file providing new C API functions to old Python versions.
//
// File distributed under the Zero Clause BSD (0BSD) license.
// Copyright Contributors to the pythoncapi_compat project.
//
// Homepage:
// https://github.com/python/pythoncapi_compat
//
// Latest version:
// https://raw.githubusercontent.com/python/pythoncapi_compat/master/pythoncapi_compat.h
//
// SPDX-License-Identifier: 0BSD
#ifndef PYTHONCAPI_COMPAT
#define PYTHONCAPI_COMPAT
#ifdef __cplusplus
extern "C" {
#endif
#include
// Python 3.11.0b4 added PyFrame_Back() to Python.h
#if PY_VERSION_HEX < 0x030b00B4 && !defined(PYPY_VERSION)
# include "frameobject.h" // PyFrameObject, PyFrame_GetBack()
#endif
#ifndef _Py_CAST
# define _Py_CAST(type, expr) ((type)(expr))
#endif
// On C++11 and newer, _Py_NULL is defined as nullptr on C++11,
// otherwise it is defined as NULL.
#ifndef _Py_NULL
# if defined(__cplusplus) && __cplusplus >= 201103
# define _Py_NULL nullptr
# else
# define _Py_NULL NULL
# endif
#endif
// Cast argument to PyObject* type.
#ifndef _PyObject_CAST
# define _PyObject_CAST(op) _Py_CAST(PyObject*, op)
#endif
// bpo-42262 added Py_NewRef() to Python 3.10.0a3
#if PY_VERSION_HEX < 0x030A00A3 && !defined(Py_NewRef)
static inline PyObject* _Py_NewRef(PyObject *obj)
{
Py_INCREF(obj);
return obj;
}
#define Py_NewRef(obj) _Py_NewRef(_PyObject_CAST(obj))
#endif
// bpo-42262 added Py_XNewRef() to Python 3.10.0a3
#if PY_VERSION_HEX < 0x030A00A3 && !defined(Py_XNewRef)
static inline PyObject* _Py_XNewRef(PyObject *obj)
{
Py_XINCREF(obj);
return obj;
}
#define Py_XNewRef(obj) _Py_XNewRef(_PyObject_CAST(obj))
#endif
// bpo-39573 added Py_SET_REFCNT() to Python 3.9.0a4
#if PY_VERSION_HEX < 0x030900A4 && !defined(Py_SET_REFCNT)
static inline void _Py_SET_REFCNT(PyObject *ob, Py_ssize_t refcnt)
{
ob->ob_refcnt = refcnt;
}
#define Py_SET_REFCNT(ob, refcnt) _Py_SET_REFCNT(_PyObject_CAST(ob), refcnt)
#endif
// Py_SETREF() and Py_XSETREF() were added to Python 3.5.2.
// It is excluded from the limited C API.
#if (PY_VERSION_HEX < 0x03050200 && !defined(Py_SETREF)) && !defined(Py_LIMITED_API)
#define Py_SETREF(dst, src) \
do { \
PyObject **_tmp_dst_ptr = _Py_CAST(PyObject**, &(dst)); \
PyObject *_tmp_dst = (*_tmp_dst_ptr); \
*_tmp_dst_ptr = _PyObject_CAST(src); \
Py_DECREF(_tmp_dst); \
} while (0)
#define Py_XSETREF(dst, src) \
do { \
PyObject **_tmp_dst_ptr = _Py_CAST(PyObject**, &(dst)); \
PyObject *_tmp_dst = (*_tmp_dst_ptr); \
*_tmp_dst_ptr = _PyObject_CAST(src); \
Py_XDECREF(_tmp_dst); \
} while (0)
#endif
// bpo-43753 added Py_Is(), Py_IsNone(), Py_IsTrue() and Py_IsFalse()
// to Python 3.10.0b1.
#if PY_VERSION_HEX < 0x030A00B1 && !defined(Py_Is)
# define Py_Is(x, y) ((x) == (y))
#endif
#if PY_VERSION_HEX < 0x030A00B1 && !defined(Py_IsNone)
# define Py_IsNone(x) Py_Is(x, Py_None)
#endif
#if (PY_VERSION_HEX < 0x030A00B1 || defined(PYPY_VERSION)) && !defined(Py_IsTrue)
# define Py_IsTrue(x) Py_Is(x, Py_True)
#endif
#if (PY_VERSION_HEX < 0x030A00B1 || defined(PYPY_VERSION)) && !defined(Py_IsFalse)
# define Py_IsFalse(x) Py_Is(x, Py_False)
#endif
// bpo-39573 added Py_SET_TYPE() to Python 3.9.0a4
#if PY_VERSION_HEX < 0x030900A4 && !defined(Py_SET_TYPE)
static inline void _Py_SET_TYPE(PyObject *ob, PyTypeObject *type)
{
ob->ob_type = type;
}
#define Py_SET_TYPE(ob, type) _Py_SET_TYPE(_PyObject_CAST(ob), type)
#endif
// bpo-39573 added Py_SET_SIZE() to Python 3.9.0a4
#if PY_VERSION_HEX < 0x030900A4 && !defined(Py_SET_SIZE)
static inline void _Py_SET_SIZE(PyVarObject *ob, Py_ssize_t size)
{
ob->ob_size = size;
}
#define Py_SET_SIZE(ob, size) _Py_SET_SIZE((PyVarObject*)(ob), size)
#endif
// bpo-40421 added PyFrame_GetCode() to Python 3.9.0b1
#if PY_VERSION_HEX < 0x030900B1 || defined(PYPY_VERSION)
static inline PyCodeObject* PyFrame_GetCode(PyFrameObject *frame)
{
assert(frame != _Py_NULL);
assert(frame->f_code != _Py_NULL);
return _Py_CAST(PyCodeObject*, Py_NewRef(frame->f_code));
}
#endif
static inline PyCodeObject* _PyFrame_GetCodeBorrow(PyFrameObject *frame)
{
PyCodeObject *code = PyFrame_GetCode(frame);
Py_DECREF(code);
return code;
}
// bpo-40421 added PyFrame_GetBack() to Python 3.9.0b1
#if PY_VERSION_HEX < 0x030900B1 && !defined(PYPY_VERSION)
static inline PyFrameObject* PyFrame_GetBack(PyFrameObject *frame)
{
assert(frame != _Py_NULL);
return _Py_CAST(PyFrameObject*, Py_XNewRef(frame->f_back));
}
#endif
#if !defined(PYPY_VERSION)
static inline PyFrameObject* _PyFrame_GetBackBorrow(PyFrameObject *frame)
{
PyFrameObject *back = PyFrame_GetBack(frame);
Py_XDECREF(back);
return back;
}
#endif
// bpo-40421 added PyFrame_GetLocals() to Python 3.11.0a7
#if PY_VERSION_HEX < 0x030B00A7 && !defined(PYPY_VERSION)
static inline PyObject* PyFrame_GetLocals(PyFrameObject *frame)
{
#if PY_VERSION_HEX >= 0x030400B1
if (PyFrame_FastToLocalsWithError(frame) < 0) {
return NULL;
}
#else
PyFrame_FastToLocals(frame);
#endif
return Py_NewRef(frame->f_locals);
}
#endif
// bpo-40421 added PyFrame_GetGlobals() to Python 3.11.0a7
#if PY_VERSION_HEX < 0x030B00A7 && !defined(PYPY_VERSION)
static inline PyObject* PyFrame_GetGlobals(PyFrameObject *frame)
{
return Py_NewRef(frame->f_globals);
}
#endif
// bpo-40421 added PyFrame_GetBuiltins() to Python 3.11.0a7
#if PY_VERSION_HEX < 0x030B00A7 && !defined(PYPY_VERSION)
static inline PyObject* PyFrame_GetBuiltins(PyFrameObject *frame)
{
return Py_NewRef(frame->f_builtins);
}
#endif
// bpo-40421 added PyFrame_GetLasti() to Python 3.11.0b1
#if PY_VERSION_HEX < 0x030B00B1 && !defined(PYPY_VERSION)
static inline int PyFrame_GetLasti(PyFrameObject *frame)
{
#if PY_VERSION_HEX >= 0x030A00A7
// bpo-27129: Since Python 3.10.0a7, f_lasti is an instruction offset,
// not a bytes offset anymore. Python uses 16-bit "wordcode" (2 bytes)
// instructions.
if (frame->f_lasti < 0) {
return -1;
}
return frame->f_lasti * 2;
#else
return frame->f_lasti;
#endif
}
#endif
// gh-91248 added PyFrame_GetVar() to Python 3.12.0a2
#if PY_VERSION_HEX < 0x030C00A2 && !defined(PYPY_VERSION)
static inline PyObject* PyFrame_GetVar(PyFrameObject *frame, PyObject *name)
{
PyObject *locals, *value;
locals = PyFrame_GetLocals(frame);
if (locals == NULL) {
return NULL;
}
#if PY_VERSION_HEX >= 0x03000000
value = PyDict_GetItemWithError(locals, name);
#else
value = _PyDict_GetItemWithError(locals, name);
#endif
Py_DECREF(locals);
if (value == NULL) {
if (PyErr_Occurred()) {
return NULL;
}
#if PY_VERSION_HEX >= 0x03000000
PyErr_Format(PyExc_NameError, "variable %R does not exist", name);
#else
PyErr_SetString(PyExc_NameError, "variable does not exist");
#endif
return NULL;
}
return Py_NewRef(value);
}
#endif
// gh-91248 added PyFrame_GetVarString() to Python 3.12.0a2
#if PY_VERSION_HEX < 0x030C00A2 && !defined(PYPY_VERSION)
static inline PyObject*
PyFrame_GetVarString(PyFrameObject *frame, const char *name)
{
PyObject *name_obj, *value;
#if PY_VERSION_HEX >= 0x03000000
name_obj = PyUnicode_FromString(name);
#else
name_obj = PyString_FromString(name);
#endif
if (name_obj == NULL) {
return NULL;
}
value = PyFrame_GetVar(frame, name_obj);
Py_DECREF(name_obj);
return value;
}
#endif
// bpo-39947 added PyThreadState_GetInterpreter() to Python 3.9.0a5
#if PY_VERSION_HEX < 0x030900A5 || defined(PYPY_VERSION)
static inline PyInterpreterState *
PyThreadState_GetInterpreter(PyThreadState *tstate)
{
assert(tstate != _Py_NULL);
return tstate->interp;
}
#endif
// bpo-40429 added PyThreadState_GetFrame() to Python 3.9.0b1
#if PY_VERSION_HEX < 0x030900B1 && !defined(PYPY_VERSION)
static inline PyFrameObject* PyThreadState_GetFrame(PyThreadState *tstate)
{
assert(tstate != _Py_NULL);
return _Py_CAST(PyFrameObject *, Py_XNewRef(tstate->frame));
}
#endif
#if !defined(PYPY_VERSION)
static inline PyFrameObject*
_PyThreadState_GetFrameBorrow(PyThreadState *tstate)
{
PyFrameObject *frame = PyThreadState_GetFrame(tstate);
Py_XDECREF(frame);
return frame;
}
#endif
// bpo-39947 added PyInterpreterState_Get() to Python 3.9.0a5
#if PY_VERSION_HEX < 0x030900A5 || defined(PYPY_VERSION)
static inline PyInterpreterState* PyInterpreterState_Get(void)
{
PyThreadState *tstate;
PyInterpreterState *interp;
tstate = PyThreadState_GET();
if (tstate == _Py_NULL) {
Py_FatalError("GIL released (tstate is NULL)");
}
interp = tstate->interp;
if (interp == _Py_NULL) {
Py_FatalError("no current interpreter");
}
return interp;
}
#endif
// bpo-39947 added PyInterpreterState_Get() to Python 3.9.0a6
#if 0x030700A1 <= PY_VERSION_HEX && PY_VERSION_HEX < 0x030900A6 && !defined(PYPY_VERSION)
static inline uint64_t PyThreadState_GetID(PyThreadState *tstate)
{
assert(tstate != _Py_NULL);
return tstate->id;
}
#endif
// bpo-43760 added PyThreadState_EnterTracing() to Python 3.11.0a2
#if PY_VERSION_HEX < 0x030B00A2 && !defined(PYPY_VERSION)
static inline void PyThreadState_EnterTracing(PyThreadState *tstate)
{
tstate->tracing++;
#if PY_VERSION_HEX >= 0x030A00A1
tstate->cframe->use_tracing = 0;
#else
tstate->use_tracing = 0;
#endif
}
#endif
// bpo-43760 added PyThreadState_LeaveTracing() to Python 3.11.0a2
#if PY_VERSION_HEX < 0x030B00A2 && !defined(PYPY_VERSION)
static inline void PyThreadState_LeaveTracing(PyThreadState *tstate)
{
int use_tracing = (tstate->c_tracefunc != _Py_NULL
|| tstate->c_profilefunc != _Py_NULL);
tstate->tracing--;
#if PY_VERSION_HEX >= 0x030A00A1
tstate->cframe->use_tracing = use_tracing;
#else
tstate->use_tracing = use_tracing;
#endif
}
#endif
// bpo-37194 added PyObject_CallNoArgs() to Python 3.9.0a1
// PyObject_CallNoArgs() added to PyPy 3.9.16-v7.3.11
#if !defined(PyObject_CallNoArgs) && PY_VERSION_HEX < 0x030900A1
static inline PyObject* PyObject_CallNoArgs(PyObject *func)
{
return PyObject_CallFunctionObjArgs(func, NULL);
}
#endif
// bpo-39245 made PyObject_CallOneArg() public (previously called
// _PyObject_CallOneArg) in Python 3.9.0a4
// PyObject_CallOneArg() added to PyPy 3.9.16-v7.3.11
#if !defined(PyObject_CallOneArg) && PY_VERSION_HEX < 0x030900A4
static inline PyObject* PyObject_CallOneArg(PyObject *func, PyObject *arg)
{
return PyObject_CallFunctionObjArgs(func, arg, NULL);
}
#endif
// bpo-1635741 added PyModule_AddObjectRef() to Python 3.10.0a3
#if PY_VERSION_HEX < 0x030A00A3
static inline int
PyModule_AddObjectRef(PyObject *module, const char *name, PyObject *value)
{
int res;
if (!value && !PyErr_Occurred()) {
// PyModule_AddObject() raises TypeError in this case
PyErr_SetString(PyExc_SystemError,
"PyModule_AddObjectRef() must be called "
"with an exception raised if value is NULL");
return -1;
}
Py_XINCREF(value);
res = PyModule_AddObject(module, name, value);
if (res < 0) {
Py_XDECREF(value);
}
return res;
}
#endif
// bpo-40024 added PyModule_AddType() to Python 3.9.0a5
#if PY_VERSION_HEX < 0x030900A5
static inline int PyModule_AddType(PyObject *module, PyTypeObject *type)
{
const char *name, *dot;
if (PyType_Ready(type) < 0) {
return -1;
}
// inline _PyType_Name()
name = type->tp_name;
assert(name != _Py_NULL);
dot = strrchr(name, '.');
if (dot != _Py_NULL) {
name = dot + 1;
}
return PyModule_AddObjectRef(module, name, _PyObject_CAST(type));
}
#endif
// bpo-40241 added PyObject_GC_IsTracked() to Python 3.9.0a6.
// bpo-4688 added _PyObject_GC_IS_TRACKED() to Python 2.7.0a2.
#if PY_VERSION_HEX < 0x030900A6 && !defined(PYPY_VERSION)
static inline int PyObject_GC_IsTracked(PyObject* obj)
{
return (PyObject_IS_GC(obj) && _PyObject_GC_IS_TRACKED(obj));
}
#endif
// bpo-40241 added PyObject_GC_IsFinalized() to Python 3.9.0a6.
// bpo-18112 added _PyGCHead_FINALIZED() to Python 3.4.0 final.
#if PY_VERSION_HEX < 0x030900A6 && PY_VERSION_HEX >= 0x030400F0 && !defined(PYPY_VERSION)
static inline int PyObject_GC_IsFinalized(PyObject *obj)
{
PyGC_Head *gc = _Py_CAST(PyGC_Head*, obj) - 1;
return (PyObject_IS_GC(obj) && _PyGCHead_FINALIZED(gc));
}
#endif
// bpo-39573 added Py_IS_TYPE() to Python 3.9.0a4
#if PY_VERSION_HEX < 0x030900A4 && !defined(Py_IS_TYPE)
static inline int _Py_IS_TYPE(PyObject *ob, PyTypeObject *type) {
return Py_TYPE(ob) == type;
}
#define Py_IS_TYPE(ob, type) _Py_IS_TYPE(_PyObject_CAST(ob), type)
#endif
// bpo-46906 added PyFloat_Pack2() and PyFloat_Unpack2() to Python 3.11a7.
// bpo-11734 added _PyFloat_Pack2() and _PyFloat_Unpack2() to Python 3.6.0b1.
// Python 3.11a2 moved _PyFloat_Pack2() and _PyFloat_Unpack2() to the internal
// C API: Python 3.11a2-3.11a6 versions are not supported.
#if 0x030600B1 <= PY_VERSION_HEX && PY_VERSION_HEX <= 0x030B00A1 && !defined(PYPY_VERSION)
static inline int PyFloat_Pack2(double x, char *p, int le)
{ return _PyFloat_Pack2(x, (unsigned char*)p, le); }
static inline double PyFloat_Unpack2(const char *p, int le)
{ return _PyFloat_Unpack2((const unsigned char *)p, le); }
#endif
// bpo-46906 added PyFloat_Pack4(), PyFloat_Pack8(), PyFloat_Unpack4() and
// PyFloat_Unpack8() to Python 3.11a7.
// Python 3.11a2 moved _PyFloat_Pack4(), _PyFloat_Pack8(), _PyFloat_Unpack4()
// and _PyFloat_Unpack8() to the internal C API: Python 3.11a2-3.11a6 versions
// are not supported.
#if PY_VERSION_HEX <= 0x030B00A1 && !defined(PYPY_VERSION)
static inline int PyFloat_Pack4(double x, char *p, int le)
{ return _PyFloat_Pack4(x, (unsigned char*)p, le); }
static inline int PyFloat_Pack8(double x, char *p, int le)
{ return _PyFloat_Pack8(x, (unsigned char*)p, le); }
static inline double PyFloat_Unpack4(const char *p, int le)
{ return _PyFloat_Unpack4((const unsigned char *)p, le); }
static inline double PyFloat_Unpack8(const char *p, int le)
{ return _PyFloat_Unpack8((const unsigned char *)p, le); }
#endif
// gh-92154 added PyCode_GetCode() to Python 3.11.0b1
#if PY_VERSION_HEX < 0x030B00B1 && !defined(PYPY_VERSION)
static inline PyObject* PyCode_GetCode(PyCodeObject *code)
{
return Py_NewRef(code->co_code);
}
#endif
// gh-95008 added PyCode_GetVarnames() to Python 3.11.0rc1
#if PY_VERSION_HEX < 0x030B00C1 && !defined(PYPY_VERSION)
static inline PyObject* PyCode_GetVarnames(PyCodeObject *code)
{
return Py_NewRef(code->co_varnames);
}
#endif
// gh-95008 added PyCode_GetFreevars() to Python 3.11.0rc1
#if PY_VERSION_HEX < 0x030B00C1 && !defined(PYPY_VERSION)
static inline PyObject* PyCode_GetFreevars(PyCodeObject *code)
{
return Py_NewRef(code->co_freevars);
}
#endif
// gh-95008 added PyCode_GetCellvars() to Python 3.11.0rc1
#if PY_VERSION_HEX < 0x030B00C1 && !defined(PYPY_VERSION)
static inline PyObject* PyCode_GetCellvars(PyCodeObject *code)
{
return Py_NewRef(code->co_cellvars);
}
#endif
// Py_UNUSED() was added to Python 3.4.0b2.
#if PY_VERSION_HEX < 0x030400B2 && !defined(Py_UNUSED)
# if defined(__GNUC__) || defined(__clang__)
# define Py_UNUSED(name) _unused_ ## name __attribute__((unused))
# else
# define Py_UNUSED(name) _unused_ ## name
# endif
#endif
// gh-105922 added PyImport_AddModuleRef() to Python 3.13.0a1
#if PY_VERSION_HEX < 0x030D00A0
static inline PyObject* PyImport_AddModuleRef(const char *name)
{
return Py_XNewRef(PyImport_AddModule(name));
}
#endif
// gh-105927 added PyWeakref_GetRef() to Python 3.13.0a1
#if PY_VERSION_HEX < 0x030D0000
static inline int PyWeakref_GetRef(PyObject *ref, PyObject **pobj)
{
PyObject *obj;
if (ref != NULL && !PyWeakref_Check(ref)) {
*pobj = NULL;
PyErr_SetString(PyExc_TypeError, "expected a weakref");
return -1;
}
obj = PyWeakref_GetObject(ref);
if (obj == NULL) {
// SystemError if ref is NULL
*pobj = NULL;
return -1;
}
if (obj == Py_None) {
*pobj = NULL;
return 0;
}
*pobj = Py_NewRef(obj);
return (*pobj != NULL);
}
#endif
// bpo-36974 added PY_VECTORCALL_ARGUMENTS_OFFSET to Python 3.8b1
#ifndef PY_VECTORCALL_ARGUMENTS_OFFSET
# define PY_VECTORCALL_ARGUMENTS_OFFSET (_Py_CAST(size_t, 1) << (8 * sizeof(size_t) - 1))
#endif
// bpo-36974 added PyVectorcall_NARGS() to Python 3.8b1
#if PY_VERSION_HEX < 0x030800B1
static inline Py_ssize_t PyVectorcall_NARGS(size_t n)
{
return n & ~PY_VECTORCALL_ARGUMENTS_OFFSET;
}
#endif
// gh-105922 added PyObject_Vectorcall() to Python 3.9.0a4
#if PY_VERSION_HEX < 0x030900A4
static inline PyObject*
PyObject_Vectorcall(PyObject *callable, PyObject *const *args,
size_t nargsf, PyObject *kwnames)
{
#if PY_VERSION_HEX >= 0x030800B1 && !defined(PYPY_VERSION)
// bpo-36974 added _PyObject_Vectorcall() to Python 3.8.0b1
return _PyObject_Vectorcall(callable, args, nargsf, kwnames);
#else
PyObject *posargs = NULL, *kwargs = NULL;
PyObject *res;
Py_ssize_t nposargs, nkwargs, i;
if (nargsf != 0 && args == NULL) {
PyErr_BadInternalCall();
goto error;
}
if (kwnames != NULL && !PyTuple_Check(kwnames)) {
PyErr_BadInternalCall();
goto error;
}
nposargs = (Py_ssize_t)PyVectorcall_NARGS(nargsf);
if (kwnames) {
nkwargs = PyTuple_GET_SIZE(kwnames);
}
else {
nkwargs = 0;
}
posargs = PyTuple_New(nposargs);
if (posargs == NULL) {
goto error;
}
if (nposargs) {
for (i=0; i < nposargs; i++) {
PyTuple_SET_ITEM(posargs, i, Py_NewRef(*args));
args++;
}
}
if (nkwargs) {
kwargs = PyDict_New();
if (kwargs == NULL) {
goto error;
}
for (i = 0; i < nkwargs; i++) {
PyObject *key = PyTuple_GET_ITEM(kwnames, i);
PyObject *value = *args;
args++;
if (PyDict_SetItem(kwargs, key, value) < 0) {
goto error;
}
}
}
else {
kwargs = NULL;
}
res = PyObject_Call(callable, posargs, kwargs);
Py_DECREF(posargs);
Py_XDECREF(kwargs);
return res;
error:
Py_DECREF(posargs);
Py_XDECREF(kwargs);
return NULL;
#endif
}
#endif
// gh-106521 added PyObject_GetOptionalAttr() and
// PyObject_GetOptionalAttrString() to Python 3.13.0a1
#if PY_VERSION_HEX < 0x030D00A1
static inline int
PyObject_GetOptionalAttr(PyObject *obj, PyObject *attr_name, PyObject **result)
{
// bpo-32571 added _PyObject_LookupAttr() to Python 3.7.0b1
#if PY_VERSION_HEX >= 0x030700B1 && !defined(PYPY_VERSION)
return _PyObject_LookupAttr(obj, attr_name, result);
#else
*result = PyObject_GetAttr(obj, attr_name);
if (*result != NULL) {
return 1;
}
if (!PyErr_Occurred()) {
return 0;
}
if (PyErr_ExceptionMatches(PyExc_AttributeError)) {
PyErr_Clear();
return 0;
}
return -1;
#endif
}
static inline int
PyObject_GetOptionalAttrString(PyObject *obj, const char *attr_name, PyObject **result)
{
PyObject *name_obj;
int rc;
#if PY_VERSION_HEX >= 0x03000000
name_obj = PyUnicode_FromString(attr_name);
#else
name_obj = PyString_FromString(attr_name);
#endif
if (name_obj == NULL) {
*result = NULL;
return -1;
}
rc = PyObject_GetOptionalAttr(obj, name_obj, result);
Py_DECREF(name_obj);
return rc;
}
#endif
// gh-106307 added PyObject_GetOptionalAttr() and
// PyMapping_GetOptionalItemString() to Python 3.13.0a1
#if PY_VERSION_HEX < 0x030D00A1
static inline int
PyMapping_GetOptionalItem(PyObject *obj, PyObject *key, PyObject **result)
{
*result = PyObject_GetItem(obj, key);
if (*result) {
return 1;
}
if (!PyErr_ExceptionMatches(PyExc_KeyError)) {
return -1;
}
PyErr_Clear();
return 0;
}
static inline int
PyMapping_GetOptionalItemString(PyObject *obj, const char *key, PyObject **result)
{
PyObject *key_obj;
int rc;
#if PY_VERSION_HEX >= 0x03000000
key_obj = PyUnicode_FromString(key);
#else
key_obj = PyString_FromString(key);
#endif
if (key_obj == NULL) {
*result = NULL;
return -1;
}
rc = PyMapping_GetOptionalItem(obj, key_obj, result);
Py_DECREF(key_obj);
return rc;
}
#endif
// gh-108511 added PyMapping_HasKeyWithError() and
// PyMapping_HasKeyStringWithError() to Python 3.13.0a1
#if PY_VERSION_HEX < 0x030D00A1
static inline int
PyMapping_HasKeyWithError(PyObject *obj, PyObject *key)
{
PyObject *res;
int rc = PyMapping_GetOptionalItem(obj, key, &res);
Py_XDECREF(res);
return rc;
}
static inline int
PyMapping_HasKeyStringWithError(PyObject *obj, const char *key)
{
PyObject *res;
int rc = PyMapping_GetOptionalItemString(obj, key, &res);
Py_XDECREF(res);
return rc;
}
#endif
// gh-108511 added PyObject_HasAttrWithError() and
// PyObject_HasAttrStringWithError() to Python 3.13.0a1
#if PY_VERSION_HEX < 0x030D00A1
static inline int
PyObject_HasAttrWithError(PyObject *obj, PyObject *attr)
{
PyObject *res;
int rc = PyObject_GetOptionalAttr(obj, attr, &res);
Py_XDECREF(res);
return rc;
}
static inline int
PyObject_HasAttrStringWithError(PyObject *obj, const char *attr)
{
PyObject *res;
int rc = PyObject_GetOptionalAttrString(obj, attr, &res);
Py_XDECREF(res);
return rc;
}
#endif
// gh-106004 added PyDict_GetItemRef() and PyDict_GetItemStringRef()
// to Python 3.13.0a1
#if PY_VERSION_HEX < 0x030D00A1
static inline int
PyDict_GetItemRef(PyObject *mp, PyObject *key, PyObject **result)
{
#if PY_VERSION_HEX >= 0x03000000
PyObject *item = PyDict_GetItemWithError(mp, key);
#else
PyObject *item = _PyDict_GetItemWithError(mp, key);
#endif
if (item != NULL) {
*result = Py_NewRef(item);
return 1; // found
}
if (!PyErr_Occurred()) {
*result = NULL;
return 0; // not found
}
*result = NULL;
return -1;
}
static inline int
PyDict_GetItemStringRef(PyObject *mp, const char *key, PyObject **result)
{
int res;
#if PY_VERSION_HEX >= 0x03000000
PyObject *key_obj = PyUnicode_FromString(key);
#else
PyObject *key_obj = PyString_FromString(key);
#endif
if (key_obj == NULL) {
*result = NULL;
return -1;
}
res = PyDict_GetItemRef(mp, key_obj, result);
Py_DECREF(key_obj);
return res;
}
#endif
// gh-106307 added PyModule_Add() to Python 3.13.0a1
#if PY_VERSION_HEX < 0x030D00A1
static inline int
PyModule_Add(PyObject *mod, const char *name, PyObject *value)
{
int res = PyModule_AddObjectRef(mod, name, value);
Py_XDECREF(value);
return res;
}
#endif
// gh-108014 added Py_IsFinalizing() to Python 3.13.0a1
// bpo-1856 added _Py_Finalizing to Python 3.2.1b1.
// _Py_IsFinalizing() was added to PyPy 7.3.0.
#if (0x030201B1 <= PY_VERSION_HEX && PY_VERSION_HEX < 0x030D00A1) \
&& (!defined(PYPY_VERSION_NUM) || PYPY_VERSION_NUM >= 0x7030000)
static inline int Py_IsFinalizing(void)
{
#if PY_VERSION_HEX >= 0x030700A1
// _Py_IsFinalizing() was added to Python 3.7.0a1.
return _Py_IsFinalizing();
#else
return (_Py_Finalizing != NULL);
#endif
}
#endif
// gh-108323 added PyDict_ContainsString() to Python 3.13.0a1
#if PY_VERSION_HEX < 0x030D00A1
static inline int PyDict_ContainsString(PyObject *op, const char *key)
{
PyObject *key_obj = PyUnicode_FromString(key);
if (key_obj == NULL) {
return -1;
}
int res = PyDict_Contains(op, key_obj);
Py_DECREF(key_obj);
return res;
}
#endif
// gh-108445 added PyLong_AsInt() to Python 3.13.0a1
#if PY_VERSION_HEX < 0x030D00A1
static inline int PyLong_AsInt(PyObject *obj)
{
#ifdef PYPY_VERSION
long value = PyLong_AsLong(obj);
if (value == -1 && PyErr_Occurred()) {
return -1;
}
if (value < (long)INT_MIN || (long)INT_MAX < value) {
PyErr_SetString(PyExc_OverflowError,
"Python int too large to convert to C int");
return -1;
}
return (int)value;
#else
return _PyLong_AsInt(obj);
#endif
}
#endif
// gh-107073 added PyObject_VisitManagedDict() to Python 3.13.0a1
#if PY_VERSION_HEX < 0x030D00A1
static inline int
PyObject_VisitManagedDict(PyObject *obj, visitproc visit, void *arg)
{
PyObject **dict = _PyObject_GetDictPtr(obj);
if (*dict == NULL) {
return -1;
}
Py_VISIT(*dict);
return 0;
}
static inline void
PyObject_ClearManagedDict(PyObject *obj)
{
PyObject **dict = _PyObject_GetDictPtr(obj);
if (*dict == NULL) {
return;
}
Py_CLEAR(*dict);
}
#endif
// gh-108867 added PyThreadState_GetUnchecked() to Python 3.13.0a1
// Python 3.5.2 added _PyThreadState_UncheckedGet().
#if PY_VERSION_HEX >= 0x03050200 && PY_VERSION_HEX < 0x030D00A1
static inline PyThreadState*
PyThreadState_GetUnchecked(void)
{
return _PyThreadState_UncheckedGet();
}
#endif
// gh-110289 added PyUnicode_EqualToUTF8() and PyUnicode_EqualToUTF8AndSize()
// to Python 3.13.0a1
#if PY_VERSION_HEX < 0x030D00A1
static inline int
PyUnicode_EqualToUTF8AndSize(PyObject *unicode, const char *str, Py_ssize_t str_len)
{
Py_ssize_t len;
const void *utf8;
PyObject *exc_type, *exc_value, *exc_tb;
int res;
// API cannot report errors so save/restore the exception
PyErr_Fetch(&exc_type, &exc_value, &exc_tb);
// Python 3.3.0a1 added PyUnicode_AsUTF8AndSize()
#if PY_VERSION_HEX >= 0x030300A1
if (PyUnicode_IS_ASCII(unicode)) {
utf8 = PyUnicode_DATA(unicode);
len = PyUnicode_GET_LENGTH(unicode);
}
else {
utf8 = PyUnicode_AsUTF8AndSize(unicode, &len);
if (utf8 == NULL) {
// Memory allocation failure. The API cannot report error,
// so ignore the exception and return 0.
res = 0;
goto done;
}
}
if (len != str_len) {
res = 0;
goto done;
}
res = (memcmp(utf8, str, (size_t)len) == 0);
#else
PyObject *bytes = PyUnicode_AsUTF8String(unicode);
if (bytes == NULL) {
// Memory allocation failure. The API cannot report error,
// so ignore the exception and return 0.
res = 0;
goto done;
}
#if PY_VERSION_HEX >= 0x03000000
len = PyBytes_GET_SIZE(bytes);
utf8 = PyBytes_AS_STRING(bytes);
#else
len = PyString_GET_SIZE(bytes);
utf8 = PyString_AS_STRING(bytes);
#endif
if (len != str_len) {
Py_DECREF(bytes);
res = 0;
goto done;
}
res = (memcmp(utf8, str, (size_t)len) == 0);
Py_DECREF(bytes);
#endif
done:
PyErr_Restore(exc_type, exc_value, exc_tb);
return res;
}
static inline int
PyUnicode_EqualToUTF8(PyObject *unicode, const char *str)
{
return PyUnicode_EqualToUTF8AndSize(unicode, str, (Py_ssize_t)strlen(str));
}
#endif
// gh-111138 added PyList_Extend() and PyList_Clear() to Python 3.13.0a2
#if PY_VERSION_HEX < 0x030D00A2
static inline int
PyList_Extend(PyObject *list, PyObject *iterable)
{
return PyList_SetSlice(list, PY_SSIZE_T_MAX, PY_SSIZE_T_MAX, iterable);
}
static inline int
PyList_Clear(PyObject *list)
{
return PyList_SetSlice(list, 0, PY_SSIZE_T_MAX, NULL);
}
#endif
// gh-111262 added PyDict_Pop() and PyDict_PopString() to Python 3.13.0a2
#if PY_VERSION_HEX < 0x030D00A2
static inline int
PyDict_Pop(PyObject *dict, PyObject *key, PyObject **result)
{
PyObject *value;
if (!PyDict_Check(dict)) {
PyErr_BadInternalCall();
if (result) {
*result = NULL;
}
return -1;
}
// bpo-16991 added _PyDict_Pop() to Python 3.5.0b2.
// Python 3.6.0b3 changed _PyDict_Pop() first argument type to PyObject*.
// Python 3.13.0a1 removed _PyDict_Pop().
#if defined(PYPY_VERSION) || PY_VERSION_HEX < 0x030500b2 || PY_VERSION_HEX >= 0x030D0000
value = PyObject_CallMethod(dict, "pop", "O", key);
#elif PY_VERSION_HEX < 0x030600b3
value = _PyDict_Pop(_Py_CAST(PyDictObject*, dict), key, NULL);
#else
value = _PyDict_Pop(dict, key, NULL);
#endif
if (value == NULL) {
if (result) {
*result = NULL;
}
if (PyErr_Occurred() && !PyErr_ExceptionMatches(PyExc_KeyError)) {
return -1;
}
PyErr_Clear();
return 0;
}
if (result) {
*result = value;
}
else {
Py_DECREF(value);
}
return 1;
}
static inline int
PyDict_PopString(PyObject *dict, const char *key, PyObject **result)
{
PyObject *key_obj = PyUnicode_FromString(key);
if (key_obj == NULL) {
if (result != NULL) {
*result = NULL;
}
return -1;
}
int res = PyDict_Pop(dict, key_obj, result);
Py_DECREF(key_obj);
return res;
}
#endif
#if PY_VERSION_HEX < 0x030200A4
// Python 3.2.0a4 added Py_hash_t type
typedef Py_ssize_t Py_hash_t;
#endif
// gh-111545 added Py_HashPointer() to Python 3.13.0a3
#if PY_VERSION_HEX < 0x030D00A3
static inline Py_hash_t Py_HashPointer(const void *ptr)
{
#if PY_VERSION_HEX >= 0x030900A4 && !defined(PYPY_VERSION)
return _Py_HashPointer(ptr);
#else
return _Py_HashPointer(_Py_CAST(void*, ptr));
#endif
}
#endif
// Python 3.13a4 added a PyTime API.
// Use the private API added to Python 3.5.
#if PY_VERSION_HEX < 0x030D00A4 && PY_VERSION_HEX >= 0x03050000
typedef _PyTime_t PyTime_t;
#define PyTime_MIN _PyTime_MIN
#define PyTime_MAX _PyTime_MAX
static inline double PyTime_AsSecondsDouble(PyTime_t t)
{ return _PyTime_AsSecondsDouble(t); }
static inline int PyTime_Monotonic(PyTime_t *result)
{ return _PyTime_GetMonotonicClockWithInfo(result, NULL); }
static inline int PyTime_Time(PyTime_t *result)
{ return _PyTime_GetSystemClockWithInfo(result, NULL); }
static inline int PyTime_PerfCounter(PyTime_t *result)
{
#if PY_VERSION_HEX >= 0x03070000 && !defined(PYPY_VERSION)
return _PyTime_GetPerfCounterWithInfo(result, NULL);
#elif PY_VERSION_HEX >= 0x03070000
// Call time.perf_counter_ns() and convert Python int object to PyTime_t.
// Cache time.perf_counter_ns() function for best performance.
static PyObject *func = NULL;
if (func == NULL) {
PyObject *mod = PyImport_ImportModule("time");
if (mod == NULL) {
return -1;
}
func = PyObject_GetAttrString(mod, "perf_counter_ns");
Py_DECREF(mod);
if (func == NULL) {
return -1;
}
}
PyObject *res = PyObject_CallNoArgs(func);
if (res == NULL) {
return -1;
}
long long value = PyLong_AsLongLong(res);
Py_DECREF(res);
if (value == -1 && PyErr_Occurred()) {
return -1;
}
Py_BUILD_ASSERT(sizeof(value) >= sizeof(PyTime_t));
*result = (PyTime_t)value;
return 0;
#else
// Call time.perf_counter() and convert C double to PyTime_t.
// Cache time.perf_counter() function for best performance.
static PyObject *func = NULL;
if (func == NULL) {
PyObject *mod = PyImport_ImportModule("time");
if (mod == NULL) {
return -1;
}
func = PyObject_GetAttrString(mod, "perf_counter");
Py_DECREF(mod);
if (func == NULL) {
return -1;
}
}
PyObject *res = PyObject_CallNoArgs(func);
if (res == NULL) {
return -1;
}
double d = PyFloat_AsDouble(res);
Py_DECREF(res);
if (d == -1.0 && PyErr_Occurred()) {
return -1;
}
// Avoid floor() to avoid having to link to libm
*result = (PyTime_t)(d * 1e9);
return 0;
#endif
}
#endif
// gh-111389 added hash constants to Python 3.13.0a5. These constants were
// added first as private macros to Python 3.4.0b1 and PyPy 7.3.9.
#if (!defined(PyHASH_BITS) \
&& ((!defined(PYPY_VERSION) && PY_VERSION_HEX >= 0x030400B1) \
|| (defined(PYPY_VERSION) && PY_VERSION_HEX >= 0x03070000 \
&& PYPY_VERSION_NUM >= 0x07090000)))
# define PyHASH_BITS _PyHASH_BITS
# define PyHASH_MODULUS _PyHASH_MODULUS
# define PyHASH_INF _PyHASH_INF
# define PyHASH_IMAG _PyHASH_IMAG
#endif
#ifdef __cplusplus
}
#endif
#endif // PYTHONCAPI_COMPAT
././@PaxHeader 0000000 0000000 0000000 00000000034 00000000000 010212 x ustar 00 28 mtime=1721563243.6844618
gmpy2-2.2.1/test/ 0000755 0001750 0001750 00000000000 14647174154 012216 5 ustar 00case case ././@PaxHeader 0000000 0000000 0000000 00000000026 00000000000 010213 x ustar 00 22 mtime=1710307256.0
gmpy2-2.2.1/test/conftest.py 0000644 0001750 0001750 00000000670 14574233670 014416 0 ustar 00case case import pytest
import gmpy2
collect_ignore_glob = ['*.txt']
@pytest.fixture(autouse=True, scope='function')
def _set_default_context():
gmpy2.set_context(gmpy2.context())
def pytest_report_header(config):
print("""
Mutliple-precision library: {0}
Floating-point library: {1}
Complex library: {2}
""".format(gmpy2.mp_version(),
gmpy2.mpfr_version(),
gmpy2.mpc_version()))
././@PaxHeader 0000000 0000000 0000000 00000000026 00000000000 010213 x ustar 00 22 mtime=1710307256.0
gmpy2-2.2.1/test/supportclasses.py 0000644 0001750 0001750 00000001641 14574233670 015662 0 ustar 00case case import gmpy2
class Z:
def __mpz__(self): return gmpy2.mpz(2)
class Q:
def __mpz__(self): return gmpy2.mpz(1)
def __mpq__(self): return gmpy2.mpq(3,2)
class R:
def __mpfr__(self): return gmpy2.mpfr(1.5)
class Cx:
def __mpfr__(self): return gmpy2.mpfr(1.5)
def __mpc__(self): return gmpy2.mpc(42,67)
z = Z()
q = Q()
r = R()
cx = Cx()
class A:
def __mpz__(self): return gmpy2.mpz(1)
def __mpq__(self): return gmpy2.mpq(3,2)
def __mpfr__(self): return gmpy2.mpfr(1.5)
def __mpc__(self): return gmpy2.mpc(42,67)
class B:
def __mpz__(self): return 'hello'
def __mpq__(self): return 'hello'
def __mpfr__(self): return 'hello'
def __mpc__(self): return 'hello'
class C:
pass
class D:
def __mpz__(self): raise TypeError
def __mpq__(self): raise TypeError
def __mpfr__(self): raise TypeError
def __mpc__(self): raise TypeError
a = A()
b = B()
c = C()
d = D()
././@PaxHeader 0000000 0000000 0000000 00000000026 00000000000 010213 x ustar 00 22 mtime=1710307256.0
gmpy2-2.2.1/test/test_consts.py 0000644 0001750 0001750 00000004643 14574233670 015145 0 ustar 00case case import pytest
import gmpy2
from gmpy2 import const_catalan, const_euler, const_log2, const_pi, mpfr
def test_pi():
assert const_pi() == mpfr('3.1415926535897931')
assert const_pi(100) == mpfr('3.1415926535897932384626433832793',100)
pytest.raises(TypeError, lambda: const_pi(100,200))
pytest.raises(TypeError, lambda: const_pi(prec=100))
assert const_pi(precision=100) == mpfr('3.1415926535897932384626433832793',100)
assert gmpy2.ieee(32).const_pi() == mpfr('3.14159274',24)
pytest.raises(TypeError, lambda: gmpy2.ieee(32).const_pi(100))
assert gmpy2.ieee(128).const_pi() == mpfr('3.1415926535897932384626433832795028',113)
def test_log2():
assert const_log2() == mpfr('0.69314718055994529')
assert const_log2(100) == mpfr('0.69314718055994530941723212145798',100)
pytest.raises(TypeError, lambda: const_log2(100,200))
pytest.raises(TypeError, lambda: const_log2(prec=100))
assert const_log2(precision=100) == mpfr('0.69314718055994530941723212145798',100)
assert gmpy2.ieee(32).const_log2() == mpfr('0.693147182',24)
pytest.raises(TypeError, lambda: gmpy2.ieee(32).const_log2(100))
assert gmpy2.ieee(128).const_log2() == mpfr('0.693147180559945309417232121458176575',113)
def test_catalan():
assert const_catalan() == mpfr('0.91596559417721901')
assert const_catalan(100) == mpfr('0.91596559417721901505460351493252',100)
pytest.raises(TypeError, lambda: const_catalan(100,200))
pytest.raises(TypeError, lambda: const_catalan(prec=100))
assert gmpy2.const_catalan(precision=100) == mpfr('0.91596559417721901505460351493252',100)
assert gmpy2.ieee(32).const_catalan() == mpfr('0.915965617',24)
pytest.raises(TypeError, lambda: gmpy2.ieee(32).const_catalan(100))
assert gmpy2.ieee(128).const_catalan() == mpfr('0.915965594177219015054603514932384146',113)
def test_euler():
assert const_euler() == mpfr('0.57721566490153287')
assert const_euler(100) == mpfr('0.57721566490153286060651209008234',100)
pytest.raises(TypeError, lambda: const_euler(100,200))
pytest.raises(TypeError, lambda: const_euler(prec=100))
assert const_euler(precision=100) == mpfr('0.57721566490153286060651209008234',100)
assert gmpy2.ieee(32).const_euler() == mpfr('0.577215672',24)
pytest.raises(TypeError, lambda: gmpy2.ieee(32).const_euler(100))
assert gmpy2.ieee(128).const_euler() == mpfr('0.577215664901532860606512090082402471',113)
././@PaxHeader 0000000 0000000 0000000 00000000026 00000000000 010213 x ustar 00 22 mtime=1710307256.0
gmpy2-2.2.1/test/test_context.py 0000644 0001750 0001750 00000023411 14574233670 015312 0 ustar 00case case import warnings
import pytest
import gmpy2
from gmpy2 import (context, get_context, ieee, local_context, mpc, mpfr, mpz,
set_context)
def test_context_abs():
ctx = gmpy2.context()
assert ctx.abs(-1) == mpz(1)
assert ctx.abs(0) == mpz(0)
assert ctx.abs(1) == mpz(1)
assert ctx.abs(mpz(8)) == mpz(8)
assert ctx.abs(mpz(-8)) == mpz(8)
assert ctx.abs(-1.0) == mpfr('1.0')
assert ctx.abs(mpfr(-2)) == mpfr('2.0')
assert ctx.abs(2+3j) == mpfr('3.6055512754639891')
assert ctx.abs(mpc(2+3j)) == mpfr('3.6055512754639891')
def test_context_ieee():
ctx = ieee(32)
assert (ctx.precision == 24 and ctx.emax == 128 and
ctx.emin == -148 and ctx.subnormalize)
ctx = ieee(64)
assert (ctx.precision == 53 and ctx.emax == 1024 and
ctx.emin == -1073 and ctx.subnormalize)
ctx = ieee(128)
assert (ctx.precision == 113 and ctx.emax == 16384 and
ctx.emin == -16493 and ctx.subnormalize)
ctx = ieee(256)
assert (ctx.precision == 237 and ctx.emax == 262144 and
ctx.emin == -262377 and ctx.subnormalize)
pytest.raises(ValueError, lambda: ieee(-1))
pytest.raises(TypeError, lambda: ieee("a"))
set_context(ieee(32))
assert gmpy2.const_pi().digits(2) == ('110010010000111111011011', 2, 24)
set_context(ieee(64))
assert gmpy2.const_pi().digits(2) == ('11001001000011111101101010100010001000010110100011000', 2, 53)
set_context(ieee(128))
assert gmpy2.const_pi().digits(2) == ('11001001000011111101101010100010001000010110100011000010001101001100010011000110011000101000101110000000110111000', 2, 113)
def test_context():
ctx = context()
assert (ctx.precision == 53 and ctx.emax == 1073741823 and
ctx.emin == -1073741823 and not ctx.subnormalize)
ctx = context(precision=100)
assert (ctx.precision == 100 and ctx.emax == 1073741823 and
ctx.emin == -1073741823 and not ctx.subnormalize)
ctx = context(real_prec=100)
assert (ctx.precision == 53 and ctx.emax == 1073741823 and
ctx.emin == -1073741823 and not ctx.subnormalize and
ctx.real_prec == 100)
ctx = context(real_prec=100,imag_prec=200)
assert (ctx.precision == 53 and ctx.emax == 1073741823 and
ctx.emin == -1073741823 and not ctx.subnormalize and
ctx.real_prec == 100 and ctx.imag_prec == 200)
pytest.raises(ValueError, lambda: context(1, 2))
pytest.raises(ValueError, lambda: context(spam=123))
def test_get_context():
set_context(context())
ctx = get_context()
assert (ctx.precision == 53 and ctx.emax == 1073741823 and
ctx.emin == -1073741823 and not ctx.subnormalize)
ctx = get_context()
ctx.precision = 100
assert (ctx.precision == 100 and ctx.emax == 1073741823 and
ctx.emin == -1073741823 and not ctx.subnormalize)
ctx = get_context()
assert (ctx.precision == 100 and ctx.emax == 1073741823 and
ctx.emin == -1073741823 and not ctx.subnormalize)
b = ctx.copy()
b.precision = 200
assert (b.precision == 200 and b.emax == 1073741823 and
b.emin == -1073741823 and not b.subnormalize)
assert (ctx.precision == 100 and ctx.emax == 1073741823 and
ctx.emin == -1073741823 and not ctx.subnormalize)
ctx = get_context()
assert (ctx.precision == 100 and ctx.emax == 1073741823 and
ctx.emin == -1073741823 and not ctx.subnormalize)
def test_context_2():
set_context(context())
with context() as ctx:
assert ctx.precision == 53
ctx.precision += 20
assert ctx.precision == 73
ctx = get_context()
assert (ctx.precision == 53 and ctx.emax == 1073741823 and
ctx.emin == -1073741823 and not ctx.subnormalize)
with context(ieee(64)) as ctx:
assert (ctx.precision == 53 and ctx.emax == 1024 and
ctx.emin == -1073 and ctx.subnormalize)
ctx = get_context()
assert (ctx.precision == 53 and ctx.emax == 1073741823 and
ctx.emin == -1073741823 and not ctx.subnormalize)
with get_context() as ctx:
assert ctx.precision == 53
ctx.precision += 100
assert ctx.precision == 153
ctx = get_context()
assert (ctx.precision == 53 and ctx.emax == 1073741823 and
ctx.emin == -1073741823 and not ctx.subnormalize)
with context(precision=200) as ctx:
assert ctx.precision == 200
ctx.precision += 100
assert ctx.precision == 300
ctx = get_context()
assert (ctx.precision == 53 and ctx.emax == 1073741823 and
ctx.emin == -1073741823 and not ctx.subnormalize)
def test_nested_context():
set_context(context())
r = [get_context().precision]
with ieee(128):
r.append(get_context().precision)
with ieee(256):
r.append(get_context().precision)
with ieee(512):
r.append(get_context().precision)
r.append(get_context().precision)
r.append(get_context().precision)
r.append(get_context().precision)
assert r == [53, 113, 237, 489, 237, 113, 53]
@pytest.mark.filterwarnings("ignore:local_context().*:DeprecationWarning")
def test_nested_local_context():
set_context(context())
r = [get_context().precision]
with local_context(ieee(128)):
r.append(get_context().precision)
with local_context(ieee(256)):
r.append(get_context().precision)
with local_context(ieee(512)):
r.append(get_context().precision)
r.append(get_context().precision)
r.append(get_context().precision)
r.append(get_context().precision)
assert r == [53, 113, 237, 489, 237, 113, 53]
def test_context_repr():
ctx = get_context()
assert repr(ctx) == \
"""context(precision=53, real_prec=Default, imag_prec=Default,\n\
round=RoundToNearest, real_round=Default, imag_round=Default,\n\
emax=1073741823, emin=-1073741823,\n subnormalize=False,\n\
trap_underflow=False, underflow=False,\n trap_overflow=False,\
overflow=False,\n trap_inexact=False, inexact=False,\n\
trap_invalid=False, invalid=False,\n trap_erange=False,\
erange=False,\n trap_divzero=False, divzero=False,\n\
allow_complex=False,\n rational_division=False,\n\
allow_release_gil=False)"""
ctx.real_prec = 100
ctx.imag_prec = 200
assert repr(ctx) == \
"""context(precision=53, real_prec=100, imag_prec=200,\n\
round=RoundToNearest, real_round=Default, imag_round=Default,\n\
emax=1073741823, emin=-1073741823,\n subnormalize=False,\n\
trap_underflow=False, underflow=False,\n trap_overflow=False,\
overflow=False,\n trap_inexact=False, inexact=False,\n\
trap_invalid=False, invalid=False,\n trap_erange=False,\
erange=False,\n trap_divzero=False, divzero=False,\n\
allow_complex=False,\n rational_division=False,\n\
allow_release_gil=False)"""
ctx.trap_invalid = True
assert repr(ctx) == \
"""context(precision=53, real_prec=100, imag_prec=200,\n\
round=RoundToNearest, real_round=Default, imag_round=Default,\n\
emax=1073741823, emin=-1073741823,\n subnormalize=False,\n\
trap_underflow=False, underflow=False,\n trap_overflow=False,\
overflow=False,\n trap_inexact=False, inexact=False,\n\
trap_invalid=True, invalid=False,\n trap_erange=False,\
erange=False,\n trap_divzero=False, divzero=False,\n\
allow_complex=False,\n rational_division=False,\n\
allow_release_gil=False)"""
pytest.raises(gmpy2.InvalidOperationError, lambda: mpfr('nan') % 123)
assert repr(ctx) == \
"""context(precision=53, real_prec=100, imag_prec=200,\n\
round=RoundToNearest, real_round=Default, imag_round=Default,\n\
emax=1073741823, emin=-1073741823,\n subnormalize=False,\n\
trap_underflow=False, underflow=False,\n trap_overflow=False,\
overflow=False,\n trap_inexact=False, inexact=False,\n\
trap_invalid=True, invalid=True,\n trap_erange=False,\
erange=False,\n trap_divzero=False, divzero=False,\n\
allow_complex=False,\n rational_division=False,\n\
allow_release_gil=False)"""
set_context(ieee(32))
ctx = get_context()
ctx.trap_underflow = True
c = mpc(0.1 + 0.1j)
pytest.raises(gmpy2.UnderflowResultError, lambda: c**201)
assert repr(ctx) == \
"""context(precision=24, real_prec=Default, imag_prec=Default,\n\
round=RoundToNearest, real_round=Default, imag_round=Default,\n\
emax=128, emin=-148,\n subnormalize=True,\n\
trap_underflow=True, underflow=True,\n trap_overflow=False,\
overflow=False,\n trap_inexact=False, inexact=True,\n\
trap_invalid=False, invalid=False,\n trap_erange=False,\
erange=False,\n trap_divzero=False, divzero=False,\n\
allow_complex=False,\n rational_division=False,\n\
allow_release_gil=False)"""
def test_local_context_deprecated():
with pytest.deprecated_call():
local_context()
with warnings.catch_warnings():
warnings.simplefilter("error", DeprecationWarning)
pytest.raises(DeprecationWarning, lambda: local_context())
@pytest.mark.filterwarnings("ignore:local_context().*:DeprecationWarning")
def test_local_context():
ctx_orig = get_context()
ctx_orig.precision = 123
with context() as ctx:
assert ctx.precision == 53
with local_context() as ctx:
assert ctx.precision == 123
ctx.precision = 321
with local_context(ctx_orig) as ctx:
assert ctx.precision == 123
pytest.raises(ValueError, lambda: local_context(1, 2))
pytest.raises(ValueError, lambda: local_context(spam=123))
././@PaxHeader 0000000 0000000 0000000 00000000026 00000000000 010213 x ustar 00 22 mtime=1710307256.0
gmpy2-2.2.1/test/test_functions.py 0000644 0001750 0001750 00000156253 14574233670 015651 0 ustar 00case case import ctypes
from fractions import Fraction
import pytest
import gmpy2
from gmpy2 import (acos, acosh, asin, asinh, atan, atan2, atanh, bincoef,
c_div, c_div_2exp, c_divmod, c_divmod_2exp, c_mod,
c_mod_2exp, can_round, check_range, comb, context,
copy_sign, cos, cosh, cot, coth, csc, csch, degrees,
divexact, divm, double_fac, f2q, f_div, f_div_2exp,
f_divmod, f_divmod_2exp, f_mod, f_mod_2exp, fac, fib, fib2,
fma, fmma, fmms, fms, free_cache, from_binary, gcd, gcdext,
get_context, get_emax_max, get_emin_min, get_exp, ieee, inf,
invert, iroot, iroot_rem, is_bpsw_prp, is_euler_prp,
is_extra_strong_lucas_prp, is_fermat_prp, is_fibonacci_prp,
is_finite, is_infinite, is_integer, is_lessgreater,
is_lucas_prp, is_nan, is_regular, is_selfridge_prp,
is_signed, is_strong_bpsw_prp, is_strong_lucas_prp,
is_strong_prp, is_strong_selfridge_prp, is_unordered,
is_zero, isqrt, isqrt_rem, jacobi, kronecker, lcm, legendre,
lucas, lucas2, maxnum, minnum, mpc, mpfr,
mpfr_from_old_binary, mpq, mpq_from_old_binary, mpz,
mpz_from_old_binary, multi_fac, nan, next_prime, norm,
phase, polar, powmod, powmod_sec, primorial, proj, radians,
rect, remove, root, root_of_unity, rootn, sec, sech,
set_context, set_exp, set_sign, sign, sin, sin_cos, sinh,
sinh_cosh, t_div, t_div_2exp, t_divmod, t_divmod_2exp,
t_mod, t_mod_2exp, tan, tanh, zero)
def test_exp():
r, r2 = mpfr('5.6'), mpfr(5.4)
f = 0.6
ctx = gmpy2.get_context()
assert ctx.exp(10.5) == mpfr('36315.502674246636')
assert gmpy2.exp(mpfr(1)) == mpfr('2.7182818284590451')
assert gmpy2.exp2(r) == mpfr('48.502930128332729')
assert gmpy2.exp10(r) == mpfr('398107.17055349692')
assert gmpy2.exp2(r2) == mpfr('42.224253144732629')
assert gmpy2.exp10(r2) == mpfr('251188.6431509582')
assert gmpy2.exp2(f) == mpfr('1.515716566510398')
assert gmpy2.exp10(f) == mpfr('3.9810717055349722')
assert gmpy2.expm1(r) == mpfr('269.42640742615254')
assert gmpy2.expm1(r2) == mpfr('220.40641620418717')
assert gmpy2.expm1(f) == mpfr('0.82211880039050889')
assert gmpy2.eint(r) == mpfr('63.101785974299247')
def test_log():
r, r2 = mpfr('5.6'), mpfr(5.4)
f = 0.6
ctx = gmpy2.get_context()
assert ctx.log(mpfr(2)) == mpfr('0.69314718055994529')
assert ctx.log(mpfr(1)) == mpfr('0.0')
assert gmpy2.log10(mpfr(10)) == mpfr('1.0')
assert gmpy2.log2(r) == mpfr('2.4854268271702415')
assert gmpy2.log2(r2) == mpfr('2.4329594072761065')
assert gmpy2.log2(f) == mpfr('-0.73696559416620622')
assert gmpy2.log1p(r) == mpfr('1.8870696490323797')
assert gmpy2.log1p(r2) == mpfr('1.8562979903656263')
assert gmpy2.log1p(f) == mpfr('0.47000362924573552')
def test_root():
assert root(zero(1), 2) == mpfr('0.0')
assert root(zero(-1), 2) == mpfr('-0.0')
assert root(zero(-1), 3) == mpfr('-0.0')
assert root(zero(-1), 4) == mpfr('-0.0')
assert root(zero(-1), 5) == mpfr('-0.0')
assert root(zero(-1), 6) == mpfr('-0.0')
assert root(2, 2) == mpfr('1.4142135623730951')
assert root(mpz(2), 2) == mpfr('1.4142135623730951')
assert root(mpq(2), 2) == mpfr('1.4142135623730951')
assert root(mpfr(2), 2) == mpfr('1.4142135623730951')
pytest.raises(TypeError, lambda: root(mpc(2), 2))
assert is_nan(root(-2, 2))
pytest.raises(OverflowError, lambda: root(2, -2))
pytest.raises(TypeError, lambda: root(2, 0.5))
ctx = gmpy2.get_context()
pytest.raises(TypeError, lambda: ctx.root(mpfr(25)))
def test_rootn():
assert rootn(zero(1), 2) == mpfr('0.0')
assert rootn(zero(-1), 2) == mpfr('0.0')
assert rootn(zero(-1), 3) == mpfr('-0.0')
assert rootn(zero(-1), 4) == mpfr('0.0')
assert rootn(zero(-1), 5) == mpfr('-0.0')
assert rootn(zero(-1), 6) == mpfr('0.0')
ctx = gmpy2.get_context()
pytest.raises(TypeError, lambda: ctx.rootn(5.5))
pytest.raises(TypeError, lambda: ctx.rootn(mpc(4,1), 4))
assert ctx.rootn(mpfr(25), 4) == mpfr('2.2360679774997898')
pytest.raises(TypeError, lambda: ctx.rootn(mpfr(25), 4.0))
def test_sqrt():
ctx = gmpy2.get_context()
assert gmpy2.sqrt(float(25)) == mpfr('5.0')
assert 19.5 ** 2 == 380.25
assert ctx.sqrt(mpfr(380.25)) == mpfr('19.5')
ctx.allow_complex = True
assert ctx.sqrt(mpfr(-380.25)) == mpc('0.0+19.5j')
ctx.allow_complex = False
assert is_nan(ctx.sqrt(mpfr(-380.25)))
assert ctx.sqrt(complex(16,4)) == mpc('4.0306589103067649+0.4961967868047123j')
assert ctx.sqrt(mpc(16,4)) == mpc('4.0306589103067649+0.4961967868047123j')
assert gmpy2.rec_sqrt(mpfr('380.25')) == mpfr('0.05128205128205128')
def test_maxnum():
a = mpfr("12.34")
b = mpfr("45.67")
nan = mpfr("nan")
inf = mpfr("inf")
assert maxnum(a, b) == mpfr('45.670000000000002')
assert maxnum(b, a) == mpfr('45.670000000000002')
assert maxnum(a, -b) == mpfr('12.34')
assert maxnum(a, 123456) == mpfr('123456.0')
assert maxnum(12345678901234567890, a) == mpfr('1.2345678901234567e+19')
assert maxnum(0, -1) == mpfr('0.0')
assert maxnum(1, inf) == mpfr('inf')
assert maxnum(1, -inf) == mpfr('1.0')
assert maxnum(nan, a) == mpfr('12.34')
assert maxnum(a, nan) == mpfr('12.34')
assert maxnum(nan, inf) == mpfr('inf')
assert maxnum(nan, -inf) == mpfr('-inf')
assert is_nan(maxnum(nan, nan))
def test_minnum():
a = mpfr("12.34")
b = mpfr("45.67")
nan = mpfr("nan")
inf = mpfr("inf")
minf = mpfr("-inf")
assert minnum(a, b) == mpfr('12.34')
assert minnum(b, a) == mpfr('12.34')
assert minnum(1, inf) == mpfr('1.0')
assert minnum(minf, a) == mpfr('-inf')
assert minnum(nan, inf) == mpfr('inf')
assert is_nan(minnum(nan, nan))
def test_fused():
assert fma(2,3,4) == mpz(10)
assert fma(2,3,-4) == mpz(2)
assert fma(2.0,3,-4) == mpfr('2.0')
assert fma(2,3.0,-4) == mpfr('2.0')
assert fma(2,3,-4.0) == mpfr('2.0')
assert fma(2,mpfr(3),-4.0) == mpfr('2.0')
assert fma(mpc(2),mpfr(3),-4.0) == mpc('2.0+0.0j')
assert fms(2,3,4) == mpz(2)
assert fms(2,3,-4) == mpz(10)
assert ieee(128).fma(7,1/7,-1) == mpfr('-5.55111512312578270211815834045410156e-17',113)
assert ieee(128).fma(7,mpq(1,7),-1) == mpq(0,1)
pytest.raises(TypeError, lambda: fma(1,2,"r"))
assert fma(1,2,mpq(3,4)) == mpq(11,4)
assert fms(1,2,mpq(3,4)) == mpq(5,4)
assert fms(1,mpfr(2),3) == mpfr('-1.0')
assert fms(1,mpc(2),3) == mpc('-1.0+0.0j')
assert fmma(2,3,4,5) == mpz(26)
assert fmma(2,3,-4,5) == mpz(-14)
assert fmma(2.0,3,-4, mpq(5)) == mpfr('-14.0')
assert fmma(2,3.0,-4,5) == mpfr('-14.0')
assert fmma(2,3,-4.0,5) == mpfr('-14.0')
assert fmma(2,mpfr(3),-4.0,5) == mpfr('-14.0')
pytest.raises(TypeError, lambda: fmma(mpc(2),mpfr(3),-4.0,5))
assert fmms(2,3,4,5) == mpz(-14)
assert fmms(2,3,-4,5) == mpz(26)
assert fmms(2, 3, mpq(1, 2), 5) == mpq(7,2)
assert fmms(2, 3, mpfr(1.2), 1) == mpfr('4.7999999999999998')
assert ieee(128).fmma(7,1/7,-1,3/11) == mpfr('0.727272727272727237401994671017746441',113)
assert ieee(128).fmma(7,mpq(1,7),-1,mpq(3,11)) == mpq(8,11)
def test_trigonometric():
assert gmpy2.acos(mpc(0.2, 0.2)) == mpc('1.3735541886535356-0.20256635782456389j')
assert gmpy2.acos(mpc(0.2, 0.2)) == gmpy2.acos(complex(0.2, 0.2))
assert gmpy2.asin(mpc(0.2,0.2)) == mpc('0.1972421381413611+0.20256635782456389j')
assert gmpy2.asin(mpc(2.0,0.2)) == mpc('1.4560834209500821+1.3245636864399635j')
assert gmpy2.asin(mpc(0.2,0.2)) == gmpy2.asin(complex(0.2,0.2))
assert gmpy2.atan(mpc(2.0, 2.0)) == mpc('1.311223269671635+0.23887786125685909j')
assert gmpy2.atan(mpc(2.0, 2.0)) == gmpy2.atan(complex(2.0, 2.0))
c = mpc(2,3)
assert gmpy2.cos(c) == mpc('-4.189625690968807-9.109227893755337j')
assert gmpy2.sin(c) == mpc('9.1544991469114301-4.1689069599665647j')
assert gmpy2.sin_cos(c) == (mpc('9.1544991469114301-4.1689069599665647j'), mpc('-4.189625690968807-9.109227893755337j'))
assert gmpy2.sin_cos(c) == gmpy2.sin_cos(complex(2,3))
assert gmpy2.sin_cos(c) == (gmpy2.sin(c), gmpy2.cos(c))
assert gmpy2.tan(mpc(4,5)) == mpc('8.9834776469715613e-05+1.0000132074347847j')
assert gmpy2.atanh(mpc(2.0, 3.0)) == mpc('0.14694666622552977+1.3389725222944935j')
assert gmpy2.atanh(mpc(2.0, 3.0)) == gmpy2.atanh(complex(2, 3))
assert gmpy2.tanh(mpc(4,5)) == mpc('1.0005630461157933-0.00036520305451130409j')
def test_get_exp():
ctx = gmpy2.get_context()
ctx.trap_erange = True
pytest.raises(gmpy2.RangeError, lambda: get_exp(mpfr('inf')))
gmpy2.set_context(context())
assert get_exp(mpfr(5.232)) == 3
pytest.raises(TypeError, lambda: get_exp(0))
assert get_exp(mpfr('inf')) == 0
assert get_exp(mpfr(0)) == 0
def test_set_exp():
pytest.raises(ValueError, lambda: set_exp(mpfr('1.0'), int(fac(100))))
gmpy2.set_context(gmpy2.ieee(32))
ctx = gmpy2.get_context()
ctx.trap_erange = True
pytest.raises(gmpy2.RangeError, lambda: set_exp(mpfr('1.0'), 1000))
ctx.trap_erange = False
assert set_exp(mpfr('1.0'), 1000) == mpfr('1.0')
r = mpfr(4.55)
assert set_exp(r, 4) == mpfr('9.0999999999999996')
pytest.raises(TypeError, lambda: set_exp(r, mpz(4)))
def test_can_round():
pytest.raises(TypeError, lambda: can_round(mpfr('1.1'), 10, "spam"))
pytest.raises(ValueError, lambda: can_round(mpfr('1.1'), 10, 111, 111, 111))
pytest.raises(ValueError, lambda: can_round(mpfr('1.1'), 10, 1, 111, 111))
pytest.raises(ValueError, lambda: can_round(mpfr('1.1'), 10, 1, 1, -111))
x = mpfr('-1.112')
assert can_round(x, 10, 1, 1, 1)
assert not can_round(x, 10, 1, 1, 10)
def test_powmod():
z1, z2 = mpz(5), mpz(2)
q = mpq(2,3)
assert powmod(z1, z2, 4) == pow(z1, z2, 4)
pytest.raises(TypeError, lambda: powmod(z1))
pytest.raises(TypeError, lambda: powmod(z1, q, 4))
def test_powmod_sec():
assert powmod_sec(3,3,7) == mpz(6)
assert powmod_sec(-3,3,7) == mpz(1)
assert powmod(-3,3,7) == mpz(1)
assert powmod(3,-3,7) == mpz(6)
pytest.raises(TypeError, lambda: powmod_sec(1,2))
pytest.raises(TypeError, lambda: powmod_sec(1.2,3,4))
pytest.raises(TypeError, lambda: powmod_sec(1,2.3,4))
pytest.raises(TypeError, lambda: powmod_sec(1,2,3.4))
pytest.raises(ValueError, lambda: powmod_sec(3,-3,7))
pytest.raises(ValueError, lambda: powmod_sec(3,4,8))
def test_is_fermat_prp():
assert is_fermat_prp(12345,2) is False
assert is_fermat_prp(113,2)
assert is_fermat_prp(1234,2) is False
pytest.raises(TypeError, lambda: is_fermat_prp(1234,'a'))
pytest.raises(TypeError, lambda: is_fermat_prp(1234, 2, 3))
pytest.raises(ValueError, lambda: is_fermat_prp(113, 1))
pytest.raises(ValueError, lambda: is_fermat_prp(-113, 3))
pytest.raises(ValueError, lambda: is_fermat_prp(339, 3))
assert is_fermat_prp(mpz(12345),2) is False
assert is_fermat_prp(113,mpz(2))
def test_is_euler_prp():
assert is_euler_prp(12345,2) is False
assert is_euler_prp(113,2)
assert is_euler_prp(1234,2) is False
pytest.raises(TypeError, lambda: is_euler_prp(1234,'a'))
pytest.raises(TypeError, lambda: is_euler_prp(1234, 2, 3))
pytest.raises(ValueError, lambda: is_euler_prp(113, 1))
pytest.raises(ValueError, lambda: is_euler_prp(-113, 3))
pytest.raises(ValueError, lambda: is_euler_prp(339, 3))
assert is_euler_prp(mpz(12345),2) is False
assert is_euler_prp(113,mpz(2))
def test_is_strong_prp():
assert is_strong_prp(12345,2) is False
assert is_strong_prp(113,2)
assert is_strong_prp(1234,2) is False
pytest.raises(TypeError, lambda: is_strong_prp(1234,'a'))
pytest.raises(TypeError, lambda: is_strong_prp(1234, 2, 3))
pytest.raises(ValueError, lambda: is_strong_prp(113, 1))
pytest.raises(ValueError, lambda: is_strong_prp(-113, 3))
pytest.raises(ValueError, lambda: is_strong_prp(339, 3))
assert is_strong_prp(mpz(12345),2) is False
assert is_strong_prp(113,mpz(2))
def test_is_fibonacci_prp():
assert is_fibonacci_prp(12345, 3, 1) is False
assert is_fibonacci_prp(113, 3, 1)
assert is_fibonacci_prp(12345, 3, -1) is False
assert is_fibonacci_prp(113, 3, -1)
pytest.raises(ValueError, lambda: is_fibonacci_prp(113, 3, 2))
pytest.raises(TypeError, lambda: is_fibonacci_prp('a', 3, 2))
pytest.raises(ValueError, lambda: is_fibonacci_prp(113, 2, 1))
assert is_fibonacci_prp(113, 2, -1)
def test_is_lucas_prp():
assert is_lucas_prp(12345, 5, 2) is False
assert is_lucas_prp(113, 5, 2)
pytest.raises(ValueError, lambda: is_lucas_prp(12345, 3, 5))
def test_is_is_stronglucas_prp():
assert is_strong_lucas_prp(12345, 5, 2) is False
assert is_strong_lucas_prp(113, 5, 2)
pytest.raises(ValueError, lambda: is_strong_lucas_prp(12345, 3, 5))
def test_is_extra_strong_lucas_prp():
assert is_extra_strong_lucas_prp(12345, 9) is False
assert is_extra_strong_lucas_prp(113, 5)
pytest.raises(ValueError, lambda: is_extra_strong_lucas_prp(12345, 3))
def test_is_selfridge_prp():
assert is_selfridge_prp(12345) is False
assert is_selfridge_prp(113)
def test_is_strong_selfridge_prp():
assert is_strong_selfridge_prp(12345) is False
assert is_strong_selfridge_prp(113)
def test_is_bpsw_prp():
assert is_bpsw_prp(12345) is False
assert is_bpsw_prp(113)
def test_is_strong_bpsw_prp():
assert is_strong_bpsw_prp(12345) is False
assert is_strong_bpsw_prp(113)
def test_mpz_from_old_binary():
assert gmpy2.mpz_from_old_binary(b'\x15\xcd[\x07') == mpz(123456789)
assert gmpy2.mpz_from_old_binary(b'\x15\xcd[\x07\xff') == mpz(-123456789)
pytest.raises(TypeError, lambda: mpz_from_old_binary(1))
def test_mpq_from_old_binary():
assert mpq_from_old_binary(b'\x01\x00\x00\x00)\x98') == mpq(41,152)
assert mpq_from_old_binary(b'\x01\x00\x00\x80)\x98') == mpq(-41,152)
pytest.raises(TypeError, lambda: mpq_from_old_binary(1))
pytest.raises(ValueError, lambda: mpq_from_old_binary(b'aa'))
pytest.raises(ValueError, lambda: mpq_from_old_binary(b'aaaaaaaaa'))
def test_mpfr_from_old_binary():
assert mpfr_from_old_binary(b'\x085\x00\x00\x00\x02\x00\x00\x0009\xac\xcc\xcc\xcc\xcc\xcc\xd0') == mpfr('12345.674999999999')
assert mpfr_from_old_binary(b'\t5\x00\x00\x00\x02\x00\x00\x0009\xac\xcc\xcc\xcc\xcc\xcc\xd0') == mpfr('-12345.674999999999')
assert mpfr_from_old_binary(b'\n5\x00\x00\x00\x06\x00\x00\x00\x01\x14\xb3\x7fKQ\xf7\x0en') == mpfr('1.5e-17')
pytest.raises(TypeError, lambda: mpfr_from_old_binary(1))
pytest.raises(ValueError, lambda: mpfr_from_old_binary(b'aaaaa'))
assert mpfr_from_old_binary(b'\x04') == mpfr('0.0')
def test_from_binary():
pytest.raises(TypeError, lambda: from_binary(1))
pytest.raises(ValueError, lambda: from_binary(b'a'))
def test_phase():
pytest.raises(TypeError, lambda: phase())
pytest.raises(TypeError, lambda: phase(3))
assert phase(mpc(4,5)) == mpfr('0.89605538457134393')
assert ieee(64).phase(mpc(4,5)) == mpfr('0.89605538457134393')
def test_root_of_unity():
assert root_of_unity(1,1) == mpc('1.0+0.0j')
assert root_of_unity(1,2) == mpc('1.0+0.0j')
assert root_of_unity(2,1) == mpc('-1.0+0.0j')
assert root_of_unity(3,1) == mpc('-0.5+0.8660254037844386j')
assert root_of_unity(3,2) == mpc('-0.5-0.8660254037844386j')
assert root_of_unity(3,3) == mpc('1.0+0.0j')
assert ieee(128).root_of_unity(3,1) == mpc('-0.5+0.866025403784438646763723170752936161j',(113,113))
pytest.raises(TypeError, lambda: ieee(128).root_of_unity())
pytest.raises(TypeError, lambda: ieee(128).root_of_unity('a','b'))
def test_norm():
pytest.raises(TypeError, lambda: norm())
pytest.raises(TypeError, lambda: norm(2))
assert norm(mpc(1,2)) == mpfr('5.0')
assert ieee(32).norm(mpc(1,2)) == mpfr('5.0',24)
def test_polar():
pytest.raises(TypeError, lambda: polar())
pytest.raises(TypeError, lambda: polar(5))
assert polar(mpc(1,1)) == (mpfr('1.4142135623730951'), mpfr('0.78539816339744828'))
def test_rect():
pytest.raises(TypeError, lambda: rect())
pytest.raises(TypeError, lambda: rect(1))
assert rect(1,1) == mpc('0.54030230586813977+0.8414709848078965j')
def test_proj():
pytest.raises(TypeError, lambda: proj())
pytest.raises(TypeError, lambda: proj(1))
assert proj(mpc(1,1)) == mpc('1.0+1.0j')
assert proj(mpc(1,2)) == mpc('1.0+2.0j')
def test_is_zero():
assert is_zero(mpc("0+0j"))
assert is_zero(mpc("1+0j")) is False
assert is_zero(mpc("1+1j")) is False
assert is_zero(mpc("0+1j")) is False
ctx = gmpy2.get_context()
pynan = float('nan')
pyinf = float('inf')
rnan = mpfr('nan')
rinf = mpfr('inf')
assert is_zero(float(0))
assert is_zero(mpfr(0))
assert not is_zero(pynan)
assert not is_zero(rinf)
assert not is_zero(mpfr(5))
assert not gmpy2.is_zero(float(5))
pytest.raises(TypeError, lambda: is_zero(None))
assert ctx.is_zero(float(0))
assert ctx.is_zero(mpfr(0))
assert not ctx.is_zero(pynan)
assert not ctx.is_zero(rinf)
assert not ctx.is_zero(mpfr(5))
assert not ctx.is_zero(float(5))
assert not ctx.is_zero(mpc(4,4))
assert not ctx.is_zero(mpc(0,4))
assert ctx.is_zero(mpc(0,0))
assert ctx.is_zero(complex(0,0))
assert not ctx.is_zero(complex(0,5))
assert mpfr(0).is_zero()
assert not rinf.is_zero()
assert not mpfr(-5).is_zero()
assert mpc(0, 0).is_zero()
assert not mpc(0, 4).is_zero()
def test_is_nan():
assert is_nan(mpc("nan+1j"))
assert is_nan(mpc("1+nanj"))
assert is_nan(mpc("nan+nanj"))
assert is_nan(mpc("1+1j")) is False
ctx = gmpy2.get_context()
pynan = float('nan')
pyinf = float('inf')
rnan = mpfr('nan')
rinf = mpfr('inf')
r = mpfr(4)
assert not r.is_nan()
assert rnan.is_nan()
assert not is_nan(r)
assert is_nan(rnan)
assert not ctx.is_nan(r)
assert ctx.is_nan(rnan)
assert ctx.is_nan(pynan)
assert not ctx.is_nan(pyinf)
assert mpc(rnan).is_nan()
assert not mpc('4.0').is_nan()
assert ctx.is_nan(complex(pynan))
def test_is_infinite():
assert is_infinite(mpc("inf+1j"))
assert is_infinite(mpc("-inf+1j"))
assert is_infinite(mpc("1+infj"))
assert is_infinite(mpc("1-infj"))
assert is_infinite(mpc("inf-infj"))
assert is_infinite(mpc("1+1j")) is False
ctx = gmpy2.get_context()
pynan = float('nan')
pyinf = float('inf')
rnan = mpfr('nan')
rinf = mpfr('inf')
z5 = mpz(5)
assert not is_infinite(5)
assert not is_infinite(z5)
assert is_infinite(rinf)
assert is_infinite(pyinf)
assert is_infinite(complex(pyinf))
assert ctx.is_infinite(rinf)
assert ctx.is_infinite(pyinf)
assert not ctx.is_infinite(pynan)
assert not ctx.is_infinite(rnan)
assert not rnan.is_infinite()
assert rinf.is_infinite()
assert mpc(pyinf).is_infinite()
assert not mpc(3, 4).is_infinite()
def test_is_finite():
assert is_finite(mpc("0+0j"))
assert is_finite(mpc("nan+0j")) is False
assert is_finite(mpc("0+nanj")) is False
assert is_finite(mpc("0+infj")) is False
assert is_finite(mpc("inf+3j")) is False
ctx = gmpy2.get_context()
pynan = float('nan')
pyinf = float('inf')
rnan = mpfr('nan')
rinf = mpfr('inf')
z5 = mpz(5)
assert is_finite(5)
assert is_finite(z5)
assert not is_finite(rinf)
assert not is_finite(pyinf)
assert not is_finite(complex(pyinf))
assert not ctx.is_finite(rinf)
assert not ctx.is_finite(pyinf)
assert not ctx.is_finite(pynan)
assert not ctx.is_finite(rnan)
assert not rnan.is_finite()
assert not rinf.is_finite()
q = mpq(2,3)
assert ctx.is_finite(q)
assert not mpc(pyinf).is_finite()
assert mpc(3, 4).is_finite()
def test_is_signed():
rnan = mpfr('nan')
rinf = mpfr('inf')
assert not rinf.is_signed()
assert not rnan.is_signed()
assert mpfr(-5).is_signed()
assert not mpfr(0).is_signed()
assert not is_signed(5)
assert is_signed(-5)
assert not is_signed(float(5))
assert not is_signed(mpfr(5))
def test_is_regular():
ctx = gmpy2.get_context()
pynan = float('nan')
pyinf = float('inf')
rnan = mpfr('nan')
rinf = mpfr('inf')
z5 = mpz(5)
assert not is_regular(rnan)
assert not is_regular(rinf)
assert not is_regular(mpfr(0))
assert not is_regular(pyinf)
assert is_regular(mpfr(5))
assert is_regular(z5)
assert is_regular(-0.6)
assert not is_regular(pynan)
assert not ctx.is_regular(rnan)
assert not ctx.is_regular(rinf)
assert not ctx.is_regular(mpfr(0))
assert not ctx.is_regular(pyinf)
assert ctx.is_regular(mpfr(5))
assert ctx.is_regular(z5)
assert ctx.is_regular(-0.6)
assert not ctx.is_regular(pynan)
assert mpfr(-0.6).is_regular()
def test_is_integer():
ctx = gmpy2.get_context()
pyinf = float('inf')
rnan = mpfr('nan')
rinf = mpfr('inf')
assert not rinf.is_integer()
assert not rnan.is_integer()
assert mpfr(0).is_integer()
assert mpfr(-42).is_integer()
assert not mpfr(-42.65).is_integer()
assert not is_integer(pyinf)
assert is_integer(5)
assert not is_integer(5.6)
assert not is_integer(float(5.6))
assert ctx.is_integer(mpfr(5))
assert not ctx.is_integer(mpfr('5.6'))
def test_is_lessgreater():
pynan = float('nan')
rnan = mpfr('nan')
assert not is_lessgreater(rnan, pynan)
assert not is_lessgreater(rnan, 5)
assert not is_lessgreater(5, pynan)
assert not is_lessgreater(5, 5)
assert not is_lessgreater(5, mpq(5/1))
assert not is_lessgreater(-5, float(-5))
assert is_lessgreater(-5, mpfr(4))
pytest.raises(TypeError, lambda: is_lessgreater(mpfr(0), mpc(4,1)))
class Spam:
def __mpfr__(self):
return
pytest.raises(TypeError, lambda: is_lessgreater(2, Spam()))
def test_is_unordered():
pynan = float('nan')
rnan = mpfr('nan')
rinf = mpfr('inf')
assert not is_unordered(-5, float(-5))
pytest.raises(TypeError, lambda: is_unordered(mpfr(0), mpc(4,1)))
assert not is_unordered(-rinf, 0.0)
assert is_unordered(rnan, pynan)
assert is_unordered(rnan, 5)
assert is_unordered(5, pynan)
class Spam:
def __mpfr__(self):
return
pytest.raises(TypeError, lambda: is_unordered(2, Spam()))
def test_f2q():
a = mpfr('123.456')
pytest.raises(TypeError, lambda: f2q('a'))
pytest.raises(TypeError, lambda: f2q(1,2,3,4))
assert f2q(a,0.1) == mpz(123)
assert f2q(a,0.01) == mpz(123)
assert f2q(a,0.001) == mpq(247,2)
assert f2q(a,0.0001) == mpq(1358,11)
assert f2q(a,0.00001) == mpq(7037,57)
assert f2q(a,0.000001) == mpq(15432,125)
assert f2q(a,0.0000001) == mpq(15432,125)
assert f2q(a) == mpq(15432,125)
assert f2q(2.50000000000008) == mpq(15637498706148,6254999482459)
assert f2q(2.5000000000000) == mpq(5,2)
assert f2q(2.50000000000008, 0.001) == mpq(5,2)
assert f2q(2.50000000000008, -50) == mpq(15637498706148,6254999482459)
assert f2q(mpfr('0.500000011'), 1e-4) == mpq(1,2)
assert f2q(mpfr('0.500000011'), 1e-5) == mpq(1,2)
assert f2q(mpfr('0.500000011'), 1e-6) == mpq(1,2)
assert f2q(mpfr('0.500000011'), 1e-7) == mpq(1,2)
assert f2q(mpfr('0.500000011'), 1e-8) == mpq(22727273,45454545)
assert f2q(mpfr('0.500000011'), 1e-9) == mpq(22727273,45454545)
assert f2q(mpfr('0.500000011'), 1e-10) == mpq(22727273,45454545)
assert f2q(mpfr('0.500000011'), 1e-11) == mpq(22727273,45454545)
assert f2q(mpfr('0.500000011'), 1e-12) == mpq(22727273,45454545)
assert f2q(mpfr('0.500000011'), 1e-13) == mpq(22727273,45454545)
assert f2q(mpfr('0.500000011'), 1e-14) == mpq(22727273,45454545)
assert f2q(mpfr('0.500000011'), 1e-15) == mpq(22727273,45454545)
assert f2q(mpfr('0.500000011'), 1e-16) == mpq(204545458,409090907)
assert f2q(mpfr('0.500000011'), 1e-17) == mpq(204545458,409090907)
def test_get_emin_min():
assert get_emin_min() in (-4611686018427387903, -1073741823)
def test_get_emax_max():
assert get_emax_max() in (4611686018427387903, 1073741823)
def test_set_sign():
r = mpfr(4.55)
assert set_sign(r, False) == mpfr('4.5499999999999998')
assert set_sign(r, True) == mpfr('-4.5499999999999998')
pytest.raises(TypeError, lambda: set_sign(mpz(5), True))
pytest.raises(TypeError, lambda: set_sign(r, 'oiio'))
def test_copy_sign():
assert copy_sign(mpfr(4), mpfr(-2)) == mpfr('-4.0')
pytest.raises(TypeError, lambda: copy_sign(mpfr(4), True))
def test_nan():
x = nan()
assert is_nan(x)
def test_inf():
assert inf() == mpfr('inf')
assert inf(-5) == mpfr('-inf')
assert inf(mpz(-30)) == mpfr('-inf')
pytest.raises(TypeError, lambda: inf(mpfr(30)))
def test_check_range():
r = mpfr(4.55)
assert check_range(r) == mpfr('4.5499999999999998')
ctx = gmpy2.get_context()
assert ctx.check_range(r) == mpfr('4.5499999999999998')
pytest.raises(TypeError, lambda: ctx.check_range(mpz(5)))
def test_sign():
a = mpq(3,11)
assert sign(a) == 1
assert sign(-a) == -1
assert sign(mpq(0,5)) == 0
pytest.raises(TypeError, lambda: sign('str'))
a = mpfr("12.34")
assert sign(-1.5) == -1
assert sign(a) == 1
assert sign(mpfr(0)) == 0
assert sign(mpfr('inf')) == 1
assert sign(mpfr('-inf')) == -1
assert sign(mpfr('nan')) == 0
a = mpz(123)
b = mpz(456)
assert sign(b-a) == 1
assert sign(b-b) == 0
assert sign(a-b) == -1
assert sign(a) == 1
assert sign(-a) == -1
def test_acos():
assert acos(mpfr("0.2")).as_integer_ratio() == (mpz(6167402294989009), mpz(4503599627370496))
pytest.raises(TypeError, lambda: acos())
pytest.raises(TypeError, lambda: acos("a"))
pytest.raises(TypeError, lambda: acos(0,0))
assert acos(0) == mpfr('1.5707963267948966')
assert acos(mpz(0)) == mpfr('1.5707963267948966')
assert acos(mpq(1,2)) == mpfr('1.0471975511965979')
assert acos(Fraction(1,2)) == mpfr('1.0471975511965979')
assert is_nan(acos(mpfr("nan")))
assert is_nan(acos(mpfr("inf")))
assert is_nan(acos(mpfr("-inf")))
set_context(context(trap_invalid=True))
pytest.raises(gmpy2.InvalidOperationError, lambda: acos(mpfr("nan")))
pytest.raises(gmpy2.InvalidOperationError, lambda: acos(mpfr("inf")))
pytest.raises(gmpy2.InvalidOperationError, lambda: acos(mpfr("-inf")))
set_context(context(precision=100))
assert acos(mpfr("0.2")) == mpfr('1.3694384060045658277761961394221',100)
assert get_context().precision == 100
assert get_context().inexact
def test_asin():
assert gmpy2.asin(mpfr("0.2")).as_integer_ratio() == (mpz(7254683656315453), mpz(36028797018963968))
pytest.raises(TypeError, lambda: asin())
pytest.raises(TypeError, lambda: asin("a"))
pytest.raises(TypeError, lambda: asin(0,0))
assert asin(0) == mpfr('0.0')
assert asin(mpz(0)) == mpfr('0.0')
assert asin(mpq(1,2)) == mpfr('0.52359877559829893')
assert asin(Fraction(1,2)) == mpfr('0.52359877559829893')
assert is_nan(asin(mpfr("nan")))
assert is_nan(asin(mpfr("inf")))
assert is_nan(asin(mpfr("-inf")))
set_context(context(trap_invalid=True))
pytest.raises(gmpy2.InvalidOperationError, lambda: asin(mpfr("nan")))
pytest.raises(gmpy2.InvalidOperationError, lambda: asin(mpfr("inf")))
pytest.raises(gmpy2.InvalidOperationError, lambda: asin(mpfr("-inf")))
set_context(context(precision=100))
assert asin(mpfr("0.2")) == mpfr('0.20135792079033079145512555221757',100)
assert get_context().precision == 100
assert get_context().inexact
def test_atan():
assert atan(mpfr("0.2")).as_integer_ratio() == (mpz(1777981139569027), mpz(9007199254740992))
assert atan(mpfr("100")).as_integer_ratio() == (mpz(3514601628432273), mpz(2251799813685248))
pytest.raises(TypeError, lambda: atan())
pytest.raises(TypeError, lambda: atan("a"))
pytest.raises(TypeError, lambda: atan(0,0))
assert atan(0) == mpfr('0.0')
assert atan(mpz(0)) == mpfr('0.0')
assert atan(mpq(1,2)) == mpfr('0.46364760900080609')
assert atan(Fraction(1,2)) == mpfr('0.46364760900080609')
assert is_nan(gmpy2.atan(mpfr("nan")))
assert atan(mpfr("inf")) == mpfr('1.5707963267948966')
assert atan(mpfr("-inf")) == mpfr('-1.5707963267948966')
set_context(context(trap_invalid=True))
pytest.raises(gmpy2.InvalidOperationError, lambda: atan(mpfr("nan")))
set_context(context(precision=100))
assert gmpy2.atan(mpfr("0.2")) == mpfr('0.19739555984988075837004976519484',100)
assert get_context().precision == 100
assert get_context().inexact
def test_atan2():
assert atan2(1,2).as_integer_ratio() == (mpz(8352332796509007), mpz(18014398509481984))
assert atan2(-1,2).as_integer_ratio() == (mpz(-8352332796509007), mpz(18014398509481984))
assert atan2(1,-2).as_integer_ratio() == (mpz(3015098076232407), mpz(1125899906842624))
assert atan2(-1,-2).as_integer_ratio() == (mpz(-3015098076232407), mpz(1125899906842624))
assert atan2(float("0"),float("0")).as_integer_ratio() == (mpz(0), mpz(1))
assert atan2(float("-0"),float("0")).as_integer_ratio() == (mpz(0), mpz(1))
assert atan2(float("0"),float("-0")).as_integer_ratio() == (mpz(884279719003555), mpz(281474976710656))
assert atan2(float("-0"),float("-0")).as_integer_ratio() == (mpz(-884279719003555), mpz(281474976710656))
assert atan2(float("inf"),float("inf")).as_integer_ratio() == (mpz(884279719003555), mpz(1125899906842624))
assert atan2(float("-inf"),float("inf")).as_integer_ratio() == (mpz(-884279719003555), mpz(1125899906842624))
assert atan2(float("inf"),float("-inf")).as_integer_ratio() == (mpz(2652839157010665), mpz(1125899906842624))
assert atan2(float("-inf"),float("-inf")).as_integer_ratio() == (mpz(-2652839157010665), mpz(1125899906842624))
def test_cos():
assert cos(mpfr("0.2")).as_integer_ratio() == (mpz(4413827474764093), mpz(4503599627370496))
assert cos(mpfr("20")).as_integer_ratio() == (mpz(7351352886077503), mpz(18014398509481984)) or (sys.platform == 'win32')
assert cos(mpfr("2000")).as_integer_ratio() == (mpz(-3309781376808469), mpz(9007199254740992))
pytest.raises(TypeError, lambda: cos())
pytest.raises(TypeError, lambda: cos("a"))
pytest.raises(TypeError, lambda: cos(0,0))
assert cos(0) == mpfr('1.0')
assert cos(mpz(0)) == mpfr('1.0')
assert cos(mpq(1,2)) == mpfr('0.87758256189037276')
assert cos(Fraction(1,2)) == mpfr('0.87758256189037276')
assert is_nan(cos(mpfr("nan")))
assert is_nan(cos(mpfr("inf")))
assert is_nan(cos(mpfr("-inf")))
set_context(context(trap_invalid=True))
pytest.raises(gmpy2.InvalidOperationError, lambda: cos(mpfr("nan")))
pytest.raises(gmpy2.InvalidOperationError, lambda: cos(mpfr("inf")))
pytest.raises(gmpy2.InvalidOperationError, lambda: cos(mpfr("-inf")))
set_context(context(precision=100))
assert cos(mpfr("0.2")) == mpfr('0.98006657784124163112419651674809',100)
assert get_context().precision == 100
assert get_context().inexact
def test_cot():
assert cot(mpfr("0.2")).as_integer_ratio() == (mpz(173569956714485), mpz(35184372088832))
assert cot(gmpy2.const_pi()).as_integer_ratio() == (mpz(-8165619676597685), mpz(1))
assert cot(1) == mpfr('0.64209261593433076')
assert cot(float('0')) == mpfr('inf')
assert cot(float('-0')) == mpfr('-inf')
assert cot(mpfr('0')) == mpfr('inf')
assert cot(mpfr('-0')) == mpfr('-inf')
def test_csc():
r2 = mpfr('5.6')
assert csc(r2) == mpfr('-1.5841166632383596')
def test_sec():
r2 = mpfr('5.6')
assert sec(r2) == mpfr('1.2893811186238056')
def test_sin():
r = mpfr(5.6)
assert sin(r) == mpfr('-0.63126663787232162')
assert sin(r) == sin(5.6)
def test_sin_cos():
r = mpfr(5.6)
assert sin_cos(r) == (mpfr('-0.63126663787232162'), mpfr('0.77556587851024961'))
assert sin_cos(r) == sin_cos(5.6)
assert sin_cos(r) == (sin(r), cos(r))
def test_tan():
r = mpfr(5.6)
assert tan(r) == mpfr('-0.8139432836897027')
def test_acosh():
r = mpfr(5.6)
assert acosh(r) == mpfr('2.4078447868719399')
def test_asinh():
r = mpfr(5.6)
assert asinh(r) == mpfr('2.4237920435875173')
def test_atanh():
assert atanh(mpfr(0.365)) == mpfr('0.38264235436318422')
assert atanh(mpfr(0.365)) == atanh(0.365)
def test_cosh():
r = mpfr(5.6)
assert cosh(r) == mpfr('135.2150526449345')
assert cosh(r) == cosh(5.6)
def test_coth():
r = mpfr(5.6)
assert coth(r) == mpfr('1.0000273487661038')
def test_csch():
r = mpfr(5.6)
assert csch(r) == mpfr('0.0073958285649757295')
def test_degrees():
rad = mpfr(1.57)
ctx = get_context()
assert ctx.degrees(rad) == mpfr('89.954373835539243')
assert degrees(rad) == mpfr('89.954373835539243')
assert degrees(1) == mpfr('57.295779513082323')
def test_radians():
deg = mpfr(90)
ctx = get_context()
assert ctx.radians(deg) == mpfr('1.5707963267948966')
assert radians(deg) == mpfr('1.5707963267948966')
assert radians(45) == mpfr('0.78539816339744828')
assert radians(mpz(20)) == mpfr('0.3490658503988659')
assert radians(mpfr('inf')) == mpfr('inf')
assert is_nan(radians(mpfr('nan')))
def test_sech():
r = mpfr(5.6)
assert sech(r) == mpfr('0.0073956263037217584')
def test_sinh():
r = mpfr(5.6)
assert sinh(r) == mpfr('135.21135478121803')
assert sinh(r) == gmpy2.sinh(5.6)
def test_sinh_cosh():
r = mpfr(5.6)
assert sinh_cosh(r) == (mpfr('135.21135478121803'), mpfr('135.2150526449345'))
assert sinh_cosh(r) == sinh_cosh(5.6)
assert sinh_cosh(r) == (sinh(r), cosh(r))
def test_tanh():
r = mpfr(5.6)
assert tanh(r) == mpfr('0.99997265198183083')
def test_c_divmod():
a = mpz(123)
b = mpz(456)
pytest.raises(TypeError, lambda: c_divmod(1))
pytest.raises(TypeError, lambda: c_divmod(1, 'a'))
pytest.raises(ZeroDivisionError, lambda: c_divmod(a,0))
assert c_divmod(b,a) == (mpz(4), mpz(-36))
assert c_divmod(b,-a) == (mpz(-3), mpz(87))
assert c_divmod(-b,a) == (mpz(-3), mpz(-87))
assert c_divmod(-b,-a) == (mpz(4), mpz(36))
def test_c_divmod_2exp():
a = mpz(123456)
pytest.raises(TypeError, lambda: c_divmod_2exp(1))
pytest.raises(TypeError, lambda: c_divmod_2exp(1, 'a'))
pytest.raises(TypeError, lambda: c_divmod_2exp('a', 16))
pytest.raises(OverflowError, lambda: c_divmod_2exp(a,-16))
assert c_divmod_2exp(a,0) == (mpz(123456), mpz(0))
assert c_divmod_2exp(a,16) == (mpz(2), mpz(-7616))
assert c_divmod_2exp(-a,16) == (mpz(-1), mpz(-57920))
def test_c_div():
a = mpz(123)
b = mpz(456)
pytest.raises(TypeError, lambda: c_div(1))
pytest.raises(TypeError, lambda: c_div(1, 'a'))
pytest.raises(ZeroDivisionError, lambda: c_div(a,0))
assert c_div(b,a) == mpz(4)
assert c_div(b,-a) == mpz(-3)
assert c_div(-b,a) == mpz(-3)
assert c_div(-b,-a) == mpz(4)
def test_c_div_2exp():
a = mpz(123456)
pytest.raises(TypeError, lambda: c_div_2exp(1))
pytest.raises(TypeError, lambda: c_div_2exp(1, 'a'))
pytest.raises(TypeError, lambda: c_div_2exp('a', 16))
pytest.raises(OverflowError, lambda: c_div_2exp(a, -16))
assert c_div_2exp(a,0) == mpz(123456)
assert c_div_2exp(a,16) == mpz(2)
assert c_div_2exp(-a,16) == mpz(-1)
def test_c_mod():
a = mpz(123)
b = mpz(456)
pytest.raises(TypeError, lambda: c_mod(1))
pytest.raises(TypeError, lambda: c_mod(1, 'a'))
pytest.raises(ZeroDivisionError, lambda: c_mod(a,0))
assert c_mod(b,a) == mpz(-36)
assert c_mod(b,-a) == mpz(87)
assert c_mod(-b,a) == mpz(-87)
assert c_mod(-b,-a) == mpz(36)
def test_c_mod_2exp():
a = mpz(123456)
pytest.raises(TypeError, lambda: c_mod_2exp(1))
pytest.raises(TypeError, lambda: c_mod_2exp(1, 'a'))
pytest.raises(TypeError, lambda: c_mod_2exp('a', 16))
pytest.raises(OverflowError, lambda: c_mod_2exp(a, -16))
assert c_mod_2exp(a,0) == mpz(0)
assert c_mod_2exp(a,16) == mpz(-7616)
assert c_mod_2exp(-a,16) == mpz(-57920)
def test_f_divmod():
a = mpz(123)
b = mpz(456)
pytest.raises(TypeError, lambda: f_divmod(1))
pytest.raises(TypeError, lambda: f_divmod(1, 'a'))
pytest.raises(ZeroDivisionError, lambda: f_divmod(a,0))
assert f_divmod(b,a) == (mpz(3), mpz(87))
assert f_divmod(b,-a) == (mpz(-4), mpz(-36))
assert f_divmod(-b,a) == (mpz(-4), mpz(36))
assert f_divmod(-b,-a) == (mpz(3), mpz(-87))
def test_f_divmod_2exp():
a = mpz(123456)
pytest.raises(TypeError, lambda: f_divmod_2exp(1))
pytest.raises(TypeError, lambda: f_divmod_2exp(1, 'a'))
pytest.raises(TypeError, lambda: f_divmod_2exp('a', 16))
pytest.raises(OverflowError, lambda: f_divmod_2exp(a,-16))
assert f_divmod_2exp(a,0) == (mpz(123456), mpz(0))
assert f_divmod_2exp(a,16) == (mpz(1), mpz(57920))
assert f_divmod_2exp(-a,16) == (mpz(-2), mpz(7616))
def test_f_div():
a = mpz(123)
b = mpz(456)
pytest.raises(TypeError, lambda: f_div(1))
pytest.raises(TypeError, lambda: f_div(1, 'a'))
pytest.raises(ZeroDivisionError, lambda: f_div(a,0))
assert f_div(b,a) == mpz(3)
assert f_div(b,-a) == mpz(-4)
assert f_div(-b,a) == mpz(-4)
assert f_div(-b,-a) == mpz(3)
def test_f_div_2exp():
a = mpz(123456)
pytest.raises(TypeError, lambda: f_div_2exp(1))
pytest.raises(TypeError, lambda: f_div_2exp(1, 'a'))
pytest.raises(TypeError, lambda: f_div_2exp('a', 16))
pytest.raises(OverflowError, lambda: f_div_2exp(a, -16))
assert f_div_2exp(a,0) == mpz(123456)
assert f_div_2exp(a,16) == mpz(1)
assert f_div_2exp(-a,16) == mpz(-2)
def test_f_mod():
a = mpz(123)
b = mpz(456)
pytest.raises(TypeError, lambda: f_mod(1))
pytest.raises(TypeError, lambda: f_mod(1, 'a'))
pytest.raises(ZeroDivisionError, lambda: f_mod(a,0))
assert f_mod(b,a) == mpz(87)
assert f_mod(b,-a) == mpz(-36)
assert f_mod(-b,a) == mpz(36)
assert f_mod(-b,-a) == mpz(-87)
def test_f_mod_2exp():
a = mpz(123456)
pytest.raises(TypeError, lambda: f_mod_2exp(1))
pytest.raises(TypeError, lambda: f_mod_2exp(1, 'a'))
pytest.raises(TypeError, lambda: f_mod_2exp('a', 16))
pytest.raises(OverflowError, lambda: f_mod_2exp(a, -16))
assert f_mod_2exp(a,0) == mpz(0)
assert f_mod_2exp(a,16) == mpz(57920)
assert f_mod_2exp(-a,16) == mpz(7616)
def test_t_divmod():
a = mpz(123)
b = mpz(456)
pytest.raises(TypeError, lambda: t_divmod(1))
pytest.raises(TypeError, lambda: t_divmod(1, 'a'))
pytest.raises(ZeroDivisionError, lambda: t_divmod(a,0))
assert t_divmod(b,a) == (mpz(3), mpz(87))
assert t_divmod(b,-a) == (mpz(-3), mpz(87))
assert t_divmod(-b,a) == (mpz(-3), mpz(-87))
assert t_divmod(-b,-a) == (mpz(3), mpz(-87))
def test_t_divmod_2exp():
a = mpz(123456)
pytest.raises(TypeError, lambda: t_divmod_2exp(1))
pytest.raises(TypeError, lambda: t_divmod_2exp(1, 'a'))
pytest.raises(TypeError, lambda: t_divmod_2exp('a', 16))
pytest.raises(OverflowError, lambda: t_divmod_2exp(a,-16))
assert t_divmod_2exp(a,0) == (mpz(123456), mpz(0))
assert t_divmod_2exp(a,16) == (mpz(1), mpz(57920))
assert t_divmod_2exp(-a,16) == (mpz(-1), mpz(-57920))
def test_t_div():
a = mpz(123)
b = mpz(456)
pytest.raises(TypeError, lambda: t_div(1))
pytest.raises(TypeError, lambda: t_div(1, 'a'))
pytest.raises(ZeroDivisionError, lambda: t_div(a,0))
assert t_div(b,a) == mpz(3)
assert t_div(b,-a) == mpz(-3)
assert t_div(-b,a) == mpz(-3)
assert t_div(-b,-a) == mpz(3)
def test_t_div_2exp():
a = mpz(123456)
pytest.raises(TypeError, lambda: t_div_2exp(1))
pytest.raises(TypeError, lambda: t_div_2exp(1, 'a'))
pytest.raises(TypeError, lambda: t_div_2exp('a', 16))
pytest.raises(OverflowError, lambda: t_div_2exp(a, -16))
assert t_div_2exp(a,0) == mpz(123456)
assert t_div_2exp(a,16) == mpz(1)
assert t_div_2exp(-a,16) == mpz(-1)
def test_t_mod():
a = mpz(123)
b = mpz(456)
pytest.raises(TypeError, lambda: t_mod(1))
pytest.raises(TypeError, lambda: t_mod(1, 'a'))
pytest.raises(ZeroDivisionError, lambda: t_mod(a,0))
assert t_mod(b,a) == mpz(87)
assert t_mod(b,-a) == mpz(87)
assert t_mod(-b,a) == mpz(-87)
assert t_mod(-b,-a) == mpz(-87)
def test_t_mod_2exp():
a = mpz(123456)
pytest.raises(TypeError, lambda: t_mod_2exp(1))
pytest.raises(TypeError, lambda: t_mod_2exp(1, 'a'))
pytest.raises(TypeError, lambda: t_mod_2exp('a', 16))
pytest.raises(OverflowError, lambda: t_mod_2exp(a, -16))
assert t_mod_2exp(a,0) == mpz(0)
assert t_mod_2exp(a,16) == mpz(57920)
assert t_mod_2exp(-a,16) == mpz(-57920)
def test_get_max_precision():
assert gmpy2.get_max_precision() > 53
def test_free_cache():
assert free_cache() is None
def test_gcd():
a = mpz(123)
b = mpz(456)
assert gcd(1,2,3) == mpz(1)
assert gcd(2, 4, 6) == mpz(2)
pytest.raises(TypeError, lambda: gcd(1,'a'))
assert gcd(123,456) == mpz(3)
assert gcd(a,b) == mpz(3)
def test_lcm():
a = mpz(123)
b = mpz(456)
assert lcm(1,2,3) == mpz(6)
assert lcm(2, 3, 4) == mpz(12)
pytest.raises(TypeError, lambda: lcm(1,'a'))
assert lcm(a,b) == mpz(18696)
assert lcm(123,456) == mpz(18696)
def test_gcdext():
a = mpz(123)
b = mpz(456)
pytest.raises(TypeError, lambda: gcdext(1,2,3))
pytest.raises(TypeError, lambda: gcdext(1,'a'))
temp = gcdext(a,b)
assert temp[0] == a*temp[1] + b*temp[2]
temp = gcdext(123,456)
assert temp[0] == a*temp[1] + b*temp[2]
def test_divm():
a = mpz(123)
b = mpz(456)
assert divm(b,a,20) == mpz(12)
pytest.raises(TypeError, lambda: divm(a,b,100,5))
pytest.raises(TypeError, lambda: divm(a,b,'a'))
pytest.raises(ZeroDivisionError, lambda: divm(a,b,100))
assert divm(6,12,14) == mpz(4)
assert divm(0,1,2) == mpz(0)
assert divm(4,8,20) == mpz(3)
def test_fac():
pytest.raises(OverflowError, lambda: fac(-7))
pytest.raises(TypeError, lambda: fac('a'))
assert fac(7) == mpz(5040)
def test_double_fac():
pytest.raises(OverflowError, lambda: double_fac(-7))
pytest.raises(TypeError, lambda: double_fac('a'))
assert double_fac(7) == mpz(105)
assert double_fac(7) * gmpy2.double_fac(8) == mpz(40320)
assert fac(8) == mpz(40320)
def test_primorial():
pytest.raises(OverflowError, lambda: primorial(-7))
pytest.raises(TypeError, lambda: primorial('a'))
assert primorial(7) == mpz(210)
def test_multi_fac():
pytest.raises(TypeError, lambda: multi_fac(-7))
pytest.raises(TypeError, lambda: multi_fac(7,'a'))
pytest.raises(OverflowError, lambda: multi_fac(7,-1))
pytest.raises(OverflowError, lambda: multi_fac(-7,1))
pytest.raises(TypeError, lambda: multi_fac('a'))
pytest.raises(TypeError, lambda: multi_fac(10))
pytest.raises(TypeError, lambda: multi_fac(10,11,12))
assert multi_fac(17,4) == mpz(9945)
def test_fib():
pytest.raises(OverflowError, lambda: fib(-2))
assert fib(17) == mpz(1597)
def test_fib2():
pytest.raises(OverflowError, lambda: fib2(-2))
assert fib2(17) == (mpz(1597), mpz(987))
def test_lucas():
pytest.raises(OverflowError, lambda: lucas(-2))
assert lucas(17) == mpz(3571)
def test_lucas2():
pytest.raises(OverflowError, lambda: lucas2(-2))
assert lucas2(17) == (mpz(3571), mpz(2207))
def test_bincoef():
pytest.raises(TypeError, lambda: bincoef(1))
pytest.raises(TypeError, lambda: bincoef(1,2,3))
assert [bincoef(10,i) for i in range(10)] == [1, 10, 45, 120, 210,
252, 210, 120, 45, 10]
assert bincoef(1111111111111111111111,
2) == mpz(617283950617283950616604938271604938271605)
def test_comb():
pytest.raises(OverflowError, lambda: comb(3,-1))
pytest.raises(TypeError, lambda: comb('a',4))
assert comb(8,4) == mpz(70)
def test_isqrt():
a = mpz(123)
assert isqrt(a) == 11
assert isqrt(123) == 11
pytest.raises(ValueError, lambda: isqrt(-1))
pytest.raises(ValueError, lambda: isqrt(mpz(-1)))
pytest.raises(TypeError, lambda: isqrt('a'))
def test_isqrt_rem():
a = mpz(123)
b = mpz(456)
assert isqrt_rem(a) == (mpz(11), mpz(2))
assert isqrt_rem(b) == (mpz(21), mpz(15))
pytest.raises(ValueError, lambda: isqrt_rem(-1))
pytest.raises(ValueError, lambda: isqrt_rem(mpz(-1)))
pytest.raises(TypeError, lambda: isqrt_rem('a'))
pytest.raises(ValueError, lambda: isqrt_rem(mpz(-1)))
def test_remove():
a = mpz(123)
b = mpz(456)
assert remove(a,2) == (mpz(123), 0)
assert remove(a,mpz(2)) == (mpz(123), 0)
assert remove(a,3) == (mpz(41), 1)
assert remove(b,2) == (mpz(57), 3)
assert remove(b,3) == (mpz(152), 1)
pytest.raises(ValueError, lambda: remove(b,1))
pytest.raises(ValueError, lambda: remove(b,mpz(1)))
pytest.raises(ValueError, lambda: remove(b,0))
assert remove(b,789) == (mpz(456), 0)
pytest.raises(ValueError, lambda: remove(b,-3))
pytest.raises(TypeError, lambda: remove(b,float('NaN')))
pytest.raises(ValueError, lambda: remove(3,-1))
pytest.raises(TypeError, lambda: remove(3))
pytest.raises(TypeError, lambda: remove())
def test_invert():
a = mpz(123)
b = mpz(456)
assert invert(a,100) == mpz(87)
assert invert(a,mpz(100)) == mpz(87)
pytest.raises(ZeroDivisionError, lambda: invert(b,mpz(100)))
pytest.raises(ZeroDivisionError, lambda: invert(b,mpz(0)))
pytest.raises(TypeError, lambda: invert(3))
pytest.raises(TypeError, lambda: invert())
pytest.raises(ZeroDivisionError, lambda: invert(456,0))
pytest.raises(TypeError, lambda: invert(456,'a'))
pytest.raises(ZeroDivisionError, lambda: invert(456,100))
assert invert(123,100) == mpz(87)
def test_divexact():
a = mpz(123)
pytest.raises(TypeError, lambda: divexact(2))
pytest.raises(TypeError, lambda: divexact(2, 'a'))
pytest.raises(ZeroDivisionError, lambda: divexact(a,0))
pytest.raises(ZeroDivisionError, lambda: divexact(a,mpz(0)))
pytest.raises(ZeroDivisionError, lambda: divexact(123,0))
aa = mpz('1234567912345678912345679')
bb = mpz('789789789789789789789789')
cc = aa*bb
assert divexact(cc,aa) == 789789789789789789789789
aa = 1234567912345678912345679
bb = 789789789789789789789789
cc = aa*bb
assert divexact(cc,aa) == 789789789789789789789789
def test_next_prime():
pytest.raises(TypeError, lambda: next_prime('a'))
assert next_prime(mpz(2)) == mpz(3)
assert next_prime(2) == mpz(3)
assert next_prime(1000000) == mpz(1000003)
assert next_prime(2357*7069-1) != 2357*7069
def test_iroot():
a = mpz(123)
b = mpz(456)
pytest.raises(TypeError, lambda: iroot(1,2,3))
pytest.raises(ValueError, lambda: iroot(-9,2))
pytest.raises(ValueError, lambda: iroot(9,0))
assert [(iroot(a,i+1),gmpy2.iroot(b,i+1))
for i in range(5)] == [((mpz(123), True), (mpz(456), True)),
((mpz(11), False), (mpz(21), False)),
((mpz(4), False), (mpz(7), False)),
((mpz(3), False), (mpz(4), False)),
((mpz(2), False), (mpz(3), False))]
assert iroot(9,2) == (mpz(3), True)
ULONG_MAX = ctypes.c_ulong(-1).value
assert iroot(4,ULONG_MAX) == (mpz(1), False)
pytest.raises(OverflowError, lambda: iroot(4,ULONG_MAX+1))
def test_iroot_rem():
a = mpz(123)
pytest.raises(TypeError, lambda: iroot_rem(1,2,3))
pytest.raises(ValueError, lambda: iroot_rem(-9,2))
pytest.raises(ValueError, lambda: iroot_rem(9,0))
assert iroot_rem(a,2) == (mpz(11), mpz(2))
assert iroot_rem(a,3) == (mpz(4), mpz(59))
assert iroot_rem(a*a,2) == (mpz(123), mpz(0))
def test_jacobi():
pytest.raises(TypeError, lambda: jacobi('a', 10))
pytest.raises(ValueError, lambda: jacobi(10,-3))
pytest.raises(TypeError, lambda: jacobi(3))
pytest.raises(TypeError, lambda: jacobi())
assert jacobi(10,3) == 1
def test_kronecker():
pytest.raises(TypeError, lambda: gmpy2.kronecker('a', 10))
assert kronecker(10,3) == 1
assert kronecker(10,-3) == 1
pytest.raises(TypeError, lambda: kronecker(3))
pytest.raises(TypeError, lambda: kronecker())
aaa = 10**20
bbb = aaa + 39
assert jacobi(aaa,bbb) == 1
assert legendre(aaa,bbb) == 1
assert kronecker(aaa,bbb) == 1
def test_legendre():
pytest.raises(TypeError, lambda: legendre('a', 10))
assert legendre(10,3) == 1
pytest.raises(ValueError, lambda: legendre(10,-3))
pytest.raises(TypeError, lambda: legendre(3))
pytest.raises(TypeError, lambda: legendre())
def test_fsum():
assert gmpy2.fsum([]) == mpfr('0.0')
assert gmpy2.fsum([4, 5, 6]) == mpfr('15.0')
assert gmpy2.fsum(range(13)) == mpfr('78.0')
pytest.raises(TypeError, lambda: gmpy2.fsum(1))
def test_next_toward():
r, r2 = mpfr('5.6'), mpfr(5.4)
f = 0.6
pytest.raises(TypeError, lambda: gmpy2.next_toward())
pytest.raises(TypeError, lambda: gmpy2.next_toward(r))
assert gmpy2.next_toward(r, r2) == mpfr('5.5999999999999988')
assert gmpy2.next_toward(r, f) == mpfr('5.5999999999999988')
def test_next_above():
r, r2 = mpfr('5.6'), mpfr(5.4)
f = 0.6
pytest.raises(TypeError, lambda: gmpy2.next_above())
pytest.raises(TypeError, lambda: gmpy2.next_above(r, r2))
assert gmpy2.next_above(r) == mpfr('5.6000000000000005')
assert gmpy2.next_above(r2) == mpfr('5.4000000000000012')
assert gmpy2.next_above(f) == mpfr('0.60000000000000009')
def test_factorial():
ctx = gmpy2.get_context()
assert gmpy2.factorial(0) == mpfr('1.0')
pytest.raises(TypeError, lambda: gmpy2.factorial(-0.0))
assert gmpy2.factorial(2) == mpfr('2.0')
pytest.raises(TypeError, lambda: gmpy2.factorial('fred'))
assert gmpy2.factorial(123) == mpfr('1.2146304367025329e+205')
assert gmpy2.factorial(123456) == mpfr('2.6040699049291379e+574964')
assert gmpy2.factorial(123456789) == mpfr('inf')
pytest.raises(OverflowError, lambda: gmpy2.factorial(1234567899999999999999))
assert gmpy2.factorial(mpz(5)) == mpfr('120.0')
assert ctx.factorial(4) == mpfr('24.0')
def test_round2():
r = mpfr(1.65656565)
assert gmpy2.round2(r, 2) == mpfr('1.5',2)
assert gmpy2.round2(r, 5) == mpfr('1.69',5)
assert gmpy2.round2(r) == mpfr('1.6565656499999999')
assert gmpy2.round2(mpq('1/3')) == mpfr('0.33333333333333331')
assert gmpy2.round2(mpq('1/3'), 30) == mpfr('0.33333333349',30)
pytest.raises(ValueError, lambda: gmpy2.round2(r, -5))
pytest.raises(TypeError, lambda: gmpy2.round2(mpc(4, 4), 5))
assert gmpy2.round2(mpz(5), 5) == mpfr('5.0',5)
pytest.raises(TypeError, lambda: gmpy2.round2(5, 6, 5))
pytest.raises(TypeError, lambda: gmpy2.round2())
def test_reldiff():
assert gmpy2.reldiff(mpfr(2.5), mpfr(17.5)) == mpfr('6.0')
def test_modf():
r, r2 = mpfr('5.6'), mpfr(5.4)
f = 0.6
pytest.raises(TypeError, lambda: gmpy2.modf(r, r2))
assert gmpy2.modf(0.8) == (mpfr('0.0'), mpfr('0.80000000000000004'))
assert gmpy2.modf(r) == (mpfr('5.0'), mpfr('0.59999999999999964'))
assert gmpy2.modf(-r2) == (mpfr('-5.0'), mpfr('-0.40000000000000036'))
assert gmpy2.fmod(mpfr(25), mpfr(2.5)) == mpfr('0.0')
assert gmpy2.fmod(mpfr(25), 5.0) == mpfr('0.0')
pytest.raises(TypeError, lambda: gmpy2.fmod(mpfr(25)))
def test_remquo():
r, r2 = mpfr('5.6'), mpfr(5.4)
f = 0.6
pytest.raises(TypeError, lambda: gmpy2.remquo())
pytest.raises(TypeError, lambda: gmpy2.remquo(r))
assert gmpy2.remquo(r, f) == (mpfr('0.19999999999999984'), 9)
assert gmpy2.remquo(r, r2) == (mpfr('0.19999999999999929'), 1)
def test_frexp():
r, r2 = mpfr('5.6'), mpfr(5.4)
f = 0.6
pytest.raises(TypeError, lambda: gmpy2.frexp())
pytest.raises(TypeError, lambda: gmpy2.frexp(r, r2))
assert gmpy2.frexp(r) == (3, mpfr('0.69999999999999996'))
assert gmpy2.frexp(r2) == (3, mpfr('0.67500000000000004'))
assert gmpy2.frexp(f) == (0, mpfr('0.59999999999999998'))
def test_rint():
r, r2 = mpfr('5.6'), mpfr(5.4)
assert gmpy2.rint(r) == mpfr('6.0')
assert gmpy2.rint(r2) == mpfr('5.0')
def test_rint_ceil():
r, r2 = mpfr('5.6'), mpfr(5.4)
f = 0.6
assert gmpy2.rint_ceil(r) == mpfr('6.0') == gmpy2.ceil(r)
assert gmpy2.rint_ceil(r2) == mpfr('6.0') == gmpy2.ceil(r2)
assert gmpy2.rint_ceil(f) == mpfr('1.0') == gmpy2.ceil(f)
def test_rint_floor():
r, r2 = mpfr('5.6'), mpfr(5.4)
f = 0.6
assert gmpy2.rint_floor(r) == mpfr('5.0') == gmpy2.floor(r)
assert gmpy2.rint_floor(r2) == mpfr('5.0') == gmpy2.floor(r2)
assert gmpy2.rint_floor(f) == mpfr('0.0') == gmpy2.floor(f)
def test_rint_round():
r, r2 = mpfr('5.6'), mpfr(5.4)
f = 0.6
assert gmpy2.rint_round(r) == mpfr('6.0')
assert gmpy2.rint_round(r2) == mpfr('5.0')
assert gmpy2.rint_round(f) == mpfr('1.0')
def test_rint_trunc():
r, r2 = mpfr('5.6'), mpfr(5.4)
f = 0.6
assert gmpy2.rint_trunc(r) == mpfr('5.0') == gmpy2.trunc(r)
assert gmpy2.rint_trunc(r2) == mpfr('5.0') == gmpy2.trunc(r2)
assert gmpy2.rint_trunc(f) == mpfr('0.0') == gmpy2.trunc(f)
def test_round_away():
r, r2 = mpfr('5.6'), mpfr(5.4)
f = 0.6
assert gmpy2.round_away(r) == mpfr('6.0')
assert gmpy2.round_away(r2) == mpfr('5.0')
assert gmpy2.round_away(f) == mpfr('1.0')
def test_gamma_funcs():
r, r2 = mpfr('5.6'), mpfr(5.4)
assert gmpy2.gamma(r) == mpfr('61.55391500628923')
assert gmpy2.lngamma(r) == mpfr('4.1199134575335288')
assert gmpy2.digamma(r) == mpfr('1.6308319195144647')
pytest.raises(TypeError, lambda: gmpy2.lgamma())
pytest.raises(TypeError, lambda: gmpy2.lgamma(r, r2))
assert gmpy2.lgamma(r) == (mpfr('4.1199134575335288'), 1)
assert is_nan(gmpy2.lgamma(mpfr('nan'))[0])
assert gmpy2.lgamma(mpfr('inf')) == (mpfr('inf'), 1)
def test_bessel_funcs():
r = mpfr('5.6')
assert gmpy2.j0(r) == mpfr('0.026970884685114358')
assert gmpy2.j1(r) == mpfr('-0.33433283629100752')
assert gmpy2.y0(r) == mpfr('-0.33544418124531583')
assert gmpy2.y1(r) == mpfr('-0.056805614399479849')
assert gmpy2.jn(5, 43.2) == mpfr('-0.11672089168206982')
pytest.raises(TypeError, lambda: gmpy2.jn(1.2,43.2))
assert gmpy2.yn(5,43.2) == mpfr('-0.034805474763124698')
pytest.raises(TypeError, lambda: gmpy2.yn(43.2, 5.5))
def test_other_funcs():
r, r2 = mpfr('5.6'), mpfr(5.4)
f = 0.6
pytest.raises(TypeError, lambda: gmpy2.agm(mpc(4,4), 5))
assert gmpy2.frac(r) == mpfr('0.59999999999999964')
assert gmpy2.frac(r2) == mpfr('0.40000000000000036')
assert gmpy2.frac(f) == mpfr('0.59999999999999998')
assert gmpy2.cbrt(r) == mpfr('1.7758080034852013')
assert gmpy2.cbrt(r2) == mpfr('1.7544106429277198')
assert gmpy2.cbrt(f) == mpfr('0.84343266530174921')
assert gmpy2.li2(r) == mpfr('1.6186578451141254')
assert gmpy2.zeta(r) == mpfr('1.02337547922703')
assert gmpy2.erf(r) == mpfr('0.99999999999999767')
assert gmpy2.erfc(r) == mpfr('2.382836284583028e-15')
assert gmpy2.ai(r) == mpfr('2.6500613296849995e-05')
assert gmpy2.remainder(mpfr(5), mpfr(3.2)) == mpfr('-1.4000000000000004')
././@PaxHeader 0000000 0000000 0000000 00000000026 00000000000 010213 x ustar 00 22 mtime=1710307256.0
gmpy2-2.2.1/test/test_generic.py 0000644 0001750 0001750 00000023042 14574233670 015242 0 ustar 00case case from fractions import Fraction
import pytest
import gmpy2
from gmpy2 import mpz, mpq, mpfr, mpc, get_context, square, add, digits, xmpz
from supportclasses import z, q, r, cx
def test_minus():
ctx = get_context()
assert ctx.minus(mpz(5)) == mpz(-5)
assert ctx.minus(mpq(4,5)) == mpq(-4,5)
assert ctx.minus(mpfr(4,5)) == mpfr('-4.0')
assert ctx.minus(mpfr('inf')) == mpfr('-inf')
assert ctx.minus(mpc(15,3)) == mpc('-15.0-3.0j')
assert ctx.minus(65) == mpz(-65)
assert ctx.minus(5.5) == mpfr('-5.5')
assert ctx.minus(Fraction(2,3)) == mpq(-2,3)
assert ctx.minus(complex(15,3)) == mpc('-15.0-3.0j')
assert -mpc(5,5) == mpc('-5.0-5.0j')
pytest.raises(TypeError, lambda: ctx.minus('invalid'))
pytest.raises(TypeError, lambda: ctx.minus())
def test_plus():
ctx = get_context()
assert ctx.plus(5) == mpz(5)
assert ctx.plus(-5) == mpz(-5)
assert ctx.plus(Fraction(4,5)) == mpq(4,5)
assert ctx.plus(4.5) == mpfr('4.5')
assert ctx.plus(complex(5.2,5)) == mpc('5.2000000000000002+5.0j')
assert ctx.plus(mpz(421)) == mpz(421)
pytest.raises(TypeError, lambda: ctx.plus('invalid'))
pytest.raises(TypeError, lambda: ctx.plus())
assert + mpz(421) == mpz(421)
assert + mpq('4/5') == mpq(4,5)
assert + mpfr('inf') == mpfr('inf')
assert + mpc(65.0, 45) == mpc('65.0+45.0j')
def test_square():
z = mpz(2)
assert square(z) == mpz(4)
assert square(z) == z * z
q = mpq(2,3)
assert square(q) == mpq(4,9)
assert square(q) == q * q
r = mpfr(5.3)
assert square(r) == mpfr('28.09')
assert square(r) == r * r
c = mpc(2,3)
assert square(c) == mpc('-5.0+12.0j')
assert square(c) == c * c
assert square(2) == square(z)
assert square(Fraction(2,3)) == square(q)
assert square(5.3) == square(r)
assert square(complex(2,3)) == square(c)
pytest.raises(TypeError, lambda: square('invalid'))
def test_add():
a = mpz(123)
b = mpz(456)
c = 12345678901234567890
assert a+1 == mpz(124)
assert a+(-1) == mpz(122)
assert 1+a == mpz(124)
assert (-1)+a == mpz(122)
assert a+c == mpz(12345678901234568013)
assert c+a == mpz(12345678901234568013)
assert a+(-c) == mpz(-12345678901234567767)
assert (-c)+a == mpz(-12345678901234567767)
assert a+b == mpz(579)
assert b+a == mpz(579)
assert a+(-b) == mpz(-333)
assert (-b)+a == mpz(-333)
assert a+z == mpz(125)
assert add(a,b) == a+b
assert add(c,c) == c+c
assert add(1, 1) == mpz(2)
assert add(mpfr(1), mpfr(1)) == mpfr('2.0')
assert add(a, 1) == mpz(124)
assert add(1, a) == mpz(124)
assert add(a, mpq(0)) == mpq(123,1)
assert add(a, mpfr(0)) == mpfr('123.0')
assert add(a, mpc(0)) == mpc('123.0+0.0j')
pytest.raises(TypeError, lambda: add(1))
pytest.raises(TypeError, lambda: add(1,2,3))
assert add(1,1) == mpz(2)
pytest.raises(TypeError, lambda: a+'b')
pytest.raises(TypeError, lambda: 'b'+a)
assert mpq(1,2) + Fraction(3,2) == mpq(2,1)
assert Fraction(1,2) + mpq(3,2) == mpq(2,1)
assert mpq(1,2) + mpq(3,2) == mpq(2,1)
assert mpq(1,2) + 0 == mpq(1,2)
assert mpq(1,2) + mpz(1) == mpq(3,2)
assert mpq(1,2) + (-1) == mpq(-1,2)
assert 1 + mpq(1,2) == mpq(3,2)
assert mpz(1) + mpq(1,2) == mpq(3,2)
assert mpq(1,2) + mpz(1) == mpq(3,2)
assert mpq(1,1) + mpc(0) == mpc('1.0+0.0j')
assert mpc(0) + mpq(1,1) == mpc('1.0+0.0j')
assert mpq(1,2) + z == mpq(5,2)
assert mpq(1,2) + q == mpq(2,1)
assert add(mpq(1,2), mpq(3,2)) == mpq(2,1)
assert add(mpq(1,2), Fraction(3,2)) == mpq(2,1)
assert add(Fraction(1,2), mpq(3,2)) == mpq(2,1)
assert add(Fraction(1,2), Fraction(3,2)) == mpq(2,1)
pytest.raises(TypeError, lambda: add(1, 'a'))
pytest.raises(TypeError, lambda: mpq(1,2) + 'a')
pytest.raises(TypeError, lambda: 'a' + mpq(1,2))
assert mpfr(1) + 1 == mpfr('2.0')
assert 1 + mpfr(1) == mpfr('2.0')
assert mpfr(1) + mpz(1) == mpfr('2.0')
assert mpz(1) + mpfr(1) == mpfr('2.0')
assert mpfr(1) + mpfr(1) == mpfr('2.0')
assert mpfr(1) + mpq(1,1) == mpfr('2.0')
assert mpq(1,1) + mpfr(1) == mpfr('2.0')
assert mpfr(1) + Fraction(1,1) == mpfr('2.0')
assert Fraction(1,1) + mpfr(1) == mpfr('2.0')
assert mpfr(1) + 1.0 == mpfr('2.0')
assert 1.0 + mpfr(1) == mpfr('2.0')
assert mpfr(0) + (1 << 100) == mpfr('1p100', base=2)
assert (1 << 100) + mpfr(0) == mpfr('1p100', base=2)
assert mpfr(1) + z == mpfr('3.0')
assert mpfr(0.5) + q == mpfr('2.0')
assert mpfr(1.5) + r == mpfr('3.0')
pytest.raises(TypeError, lambda: mpc(1,2) + 'a')
assert mpfr(1) + mpc(1,2) == mpc('2.0+2.0j')
assert mpc(1,2) + mpfr(1) == mpc('2.0+2.0j')
assert mpc(1,2) + 1+0j == mpc('2.0+2.0j')
assert 1+0j + mpc(1,2) == mpc('2.0+2.0j')
assert mpc(1,2) + cx == mpc('43.0+69.0j')
assert mpc(1,2) + r == mpc('2.5+2.0j')
assert mpc(1,2) + q == mpc('2.5+2.0j')
assert mpc(1,2) + z == mpc('3.0+2.0j')
def test_digits():
z2 = mpz(5)
pytest.raises(TypeError, lambda: digits())
pytest.raises(TypeError, lambda: digits(5, 5, 4, 5))
assert digits(z2) == '5'
assert digits(z2, 2) == '101'
pytest.raises(TypeError, lambda: digits(z2, 2, 5))
assert digits(mpq(3,5)) == '3/5'
assert digits(mpq(3,5), 4) == '3/11'
assert digits(mpfr(3,5), 4) == ('300', 1, 5)
assert digits(mpfr(3,5), 4, 5) == ('30000', 1, 5)
assert digits(complex(5,5), 4, 5) == (('11000', 2, 53), ('11000', 2, 53))
pytest.raises(TypeError, lambda: digits('string', 4, 5))
def test_abs():
a = mpz(123)
b = abs(a)
assert a is b
a = xmpz(123)
b = abs(a)
assert a is not b
a = mpz(-123)
b = abs(a)
assert b == mpz(123)
assert a is not b
assert a == mpz(-123)
a = mpq(12,7)
b = abs(a)
assert a is b
a = mpq(-12,7)
b = abs(a)
assert b == mpq(12,7)
assert a == mpq(-12,7)
a = xmpz(-123)
b = abs(a)
assert a == xmpz(123)
assert b is None
b = abs(a)
assert b is None
a = mpfr(1.0)
b = abs(a)
assert a is not b
assert abs(mpfr(1, precision=100)) == mpfr('1.0')
ctx = gmpy2.get_context()
ctx.clear_flags()
assert gmpy2.is_nan(abs(mpfr('nan')))
assert ctx.invalid
ctx.clear_flags()
assert abs(mpfr('inf')) == mpfr('inf')
assert ctx.overflow is False
ctx.clear_flags()
assert abs(mpfr('-inf')) == mpfr('inf')
assert ctx.overflow is False
assert abs(mpc(-1,0)) == mpfr('1.0')
assert abs(-1+0j) == 1.0
assert abs(mpc(1,1)) == mpfr('1.4142135623730951')
ctx = gmpy2.get_context()
ctx.clear_flags()
c = mpc('nan+0j')
assert gmpy2.is_nan(c.real) and c.imag == 0.0
assert ctx.invalid
assert gmpy2.is_nan(abs(c))
assert ctx.invalid
ctx.clear_flags()
assert gmpy2.is_nan(abs(mpc('nanj')))
assert ctx.invalid
ctx.clear_flags()
assert abs(mpc('inf+10j')) == mpfr('inf')
assert ctx.overflow is False
ctx.clear_flags()
assert abs(mpc('-infj')) == mpfr('inf')
assert ctx.overflow is False
a = mpc('nan+infj')
ctx.clear_flags()
assert abs(a) == mpfr('inf')
assert ctx.overflow is False
assert ctx.invalid is False
a=mpc('-inf+nanj')
ctx.clear_flags()
assert abs(a) == mpfr('inf')
assert ctx.overflow is False
assert ctx.invalid is False
ctx = gmpy2.context()
pytest.raises(TypeError, lambda: ctx.abs('a'))
assert ctx.abs(-1) == mpz(1)
assert ctx.abs(0) == mpz(0)
assert ctx.abs(1) == mpz(1)
assert ctx.abs(mpz(8)) == mpz(8)
assert ctx.abs(mpz(-8)) == mpz(8)
assert ctx.abs(-1.0) == mpfr('1.0')
assert ctx.abs(mpfr(-2)) == mpfr('2.0')
assert ctx.abs(2+3j) == mpfr('3.6055512754639891')
assert ctx.abs(mpc(2+3j)) == mpfr('3.6055512754639891')
assert ctx.abs(Fraction(1,2)) == mpq(1,2)
assert ctx.abs(Fraction(-1,2)) == mpq(1,2)
def test_muldiv_2exp():
ctx = gmpy2.get_context()
r = mpfr(7.6)
z = mpz(3)
c = mpc(4,4)
assert gmpy2.mul_2exp(r, z) == mpfr('60.799999999999997')
assert gmpy2.mul_2exp(r, 3) == mpfr('60.799999999999997')
assert gmpy2.mul_2exp(r, -5) == mpfr('0.23749999999999999')
assert gmpy2.mul_2exp(1, -5) == mpfr('0.03125') # issue 328
pytest.raises(OverflowError, lambda: gmpy2.mul_2exp(z, 10**100))
pytest.raises(OverflowError, lambda: gmpy2.mul_2exp(z, -10**100))
pytest.raises(TypeError, lambda: gmpy2.mul_2exp(z, r))
pytest.raises(TypeError, lambda: gmpy2.mul_2exp('not', 5))
pytest.raises(TypeError, lambda: ctx.mul_2exp(r, z, 45))
assert ctx.mul_2exp(c, z) == mpc('32.0+32.0j')
assert ctx.mul_2exp(c, -5) == mpc('0.125+0.125j')
pytest.raises(OverflowError, lambda: ctx.mul_2exp(c, 10**100))
pytest.raises(OverflowError, lambda: ctx.mul_2exp(c, -10**100))
assert ctx.mul_2exp(r, 0) == mpfr('7.5999999999999996')
assert gmpy2.div_2exp(r, z) == mpfr('0.94999999999999996')
assert gmpy2.div_2exp(r, 3) == mpfr('0.94999999999999996')
assert gmpy2.div_2exp(r, -5) == mpfr('243.19999999999999')
pytest.raises(OverflowError, lambda: gmpy2.div_2exp(r, 10**100))
pytest.raises(OverflowError, lambda: gmpy2.div_2exp(r, -10**100))
pytest.raises(TypeError, lambda: gmpy2.div_2exp(z, r))
pytest.raises(TypeError, lambda: gmpy2.div_2exp('not', 5))
pytest.raises(TypeError, lambda: ctx.div_2exp(r, z, 45))
assert ctx.div_2exp(c, z) == mpc('0.5+0.5j')
assert ctx.div_2exp(c, -5) == mpc('128.0+128.0j')
pytest.raises(OverflowError, lambda: ctx.div_2exp(c, 10**100))
pytest.raises(OverflowError, lambda: ctx.div_2exp(c, -10**100))
././@PaxHeader 0000000 0000000 0000000 00000000026 00000000000 010213 x ustar 00 22 mtime=1721370662.0
gmpy2-2.2.1/test/test_misc.py 0000644 0001750 0001750 00000001563 14646404046 014562 0 ustar 00case case import sys
import gmpy2
def test_misc():
assert gmpy2.version().startswith('2.2.1')
assert gmpy2.mp_limbsize() in (32,64)
assert '5.0.0' <= gmpy2.mp_version()
assert gmpy2.mpfr_version() and gmpy2.mpfr_version().startswith('MPFR')
assert gmpy2.mpfr_version() and '3.1.0' <= gmpy2.mpfr_version().split()[1]
assert gmpy2.mpc_version() and gmpy2.mpc_version().startswith('MPC')
assert gmpy2.mpc_version() and '1.0' <= gmpy2.mpc_version().split()[1]
assert gmpy2.license() == ('The GMPY2 source code is licensed under LGPL '
'3 or later. The supported versions of the GMP, '
'MPFR, and MPC libraries are also licensed '
'under LGPL 3 or later.')
def test_sizeof():
assert sys.getsizeof(gmpy2.mpz(10)) > 0
assert sys.getsizeof(gmpy2.mpfr('1.0')) > 0
././@PaxHeader 0000000 0000000 0000000 00000000026 00000000000 010213 x ustar 00 22 mtime=1710307256.0
gmpy2-2.2.1/test/test_mpc.py 0000644 0001750 0001750 00000032026 14574233670 014407 0 ustar 00case case from fractions import Fraction
import pytest
from hypothesis import example, given, settings
from hypothesis.strategies import complex_numbers
from supportclasses import a, b, c, cx, d, q, r, z
import gmpy2
from gmpy2 import (cmp, cmp_abs, from_binary, get_context, is_nan, mpc,
mpc_random, mpfr, mpq, mpz, nan, random_state, to_binary)
def test_mpc_cmp():
pytest.raises(TypeError, lambda: cmp(mpc(1,2), mpc(3,4)))
assert cmp_abs(mpc(1,2), mpc(3,4)) == -1
assert cmp_abs(mpc(1,2), mpc(1,2)) == 0
assert cmp_abs(mpc(3,4), mpc(1,2)) == 1
gmpy2.get_context().clear_flags()
assert gmpy2.get_context().erange is False
assert cmp_abs(mpc(nan(),1), mpc(4.5)) == 0
assert gmpy2.get_context().erange is True
def test_mpc_comparisons():
a = mpz(123)
c = mpc(4.5,6)
assert (c == a, c != a) == (False, True)
pytest.raises(TypeError, lambda: c < a)
cnan = mpc(mpfr('nan'), 6)
assert (c == cnan, c != cnan) == (False, True)
pytest.raises(TypeError, lambda: c > cnan)
cx = complex(4.5,6)
assert (c == cx, c != cx) == (True, False)
pytest.raises(TypeError, lambda: c > cx)
from supportclasses import c
assert (c == cx) is False
def test_mpc_conversion():
x = mpc(a)
assert isinstance(x, mpc)
assert x == 42+67j
pytest.raises(TypeError, lambda: mpc(b))
pytest.raises(TypeError, lambda: mpc(c))
pytest.raises(TypeError, lambda: mpc(d))
assert mpc(mpfr(5.6), precision=(0,0)) == mpc('5.5999999999999996+0.0j')
assert mpc(Fraction(4,5)) == mpc('0.80000000000000004+0.0j')
assert mpc(b'5+6j') == mpc('5.0+6.0j')
assert mpc('5+6j') == mpc('5.0+6.0j')
pytest.raises(ValueError, lambda: mpc('\xc3'))
pytest.raises(ValueError, lambda: mpc('notanumber'))
pytest.raises(ValueError, lambda: mpc('\0'))
assert mpc('(5+6j)') == mpc('5.0+6.0j')
assert mpc(' 5+6j ') == mpc('5.0+6.0j')
pytest.raises(ValueError, lambda: mpc('5+6ji'))
assert str(mpc(5,6)) == '5.0+6.0j'
assert complex(mpc(4,5)) == (4+5j)
assert complex(mpc(4,5)) == (4+5j)
def test_mpc_creation():
ctx = gmpy2.get_context()
ctx.clear_flags()
a = mpc("1.2")
assert a.rc == (-1, 0)
assert ctx.inexact
ctx.clear_flags()
a = mpc("(1 2)")
assert a == 1 + 2j
assert a.rc == (0, 0)
assert ctx.inexact is False
ctx.clear_flags()
a = mpc("1 + 2.1 j")
assert a == 1 + 2.1j
assert a.rc == (0, 1)
assert ctx.inexact
c = mpc('67+87j', precision=70)
assert c.precision == (70, 70)
assert c.real.precision == 70
assert c.imag.precision == 70
c = mpc('42e56+42.909j', precision=(45,300))
assert c.precision == (45, 300)
assert c.real.precision == 45
assert c.imag.precision == 300
x = mpc("1.3142123+4.3e-1001j", precision=(70,37))
assert mpc(x.real, x.imag, precision=(70,37)) == x
assert mpc('1_2+4_5j') == mpc('12.0+45.0j')
def test_mpc_random():
assert (mpc_random(random_state(42))
== mpc('0.86555158787663011+0.4422082613292212j'))
def test_mpc_to_from_binary():
x = mpc("0+0j")
assert x == from_binary(to_binary(x))
x = mpc("1+0j")
assert x == from_binary(to_binary(x))
x = mpc("-1+0j")
assert x == from_binary(to_binary(x))
x = mpc("0+1j")
assert x == from_binary(to_binary(x))
x = mpc("0-1j")
assert x == from_binary(to_binary(x))
x = mpc("inf+0j")
assert x == from_binary(to_binary(x))
x = mpc("0+infj")
assert x == from_binary(to_binary(x))
x = mpc("inf-infj")
assert x == from_binary(to_binary(x))
x = mpc("inf+nanj")
y = from_binary(to_binary(x))
assert x.real == y.real
assert is_nan(y.imag)
x = mpc("-inf+0j")
assert x == from_binary(to_binary(x))
x = mpc("0-infj")
assert x == from_binary(to_binary(x))
x = mpc("-inf-infj")
assert x == from_binary(to_binary(x))
x = mpc("-inf+nanj")
y = from_binary(to_binary(x))
assert x.real == y.real
assert is_nan(y.imag)
x = mpc("nan+0j")
y = from_binary(to_binary(x))
assert x.imag == y.imag
assert is_nan(y.real)
x = mpc("0+nanj")
y = from_binary(to_binary(x))
assert x.real == y.real
assert is_nan(y.imag)
x = mpc("nan-infj")
y = from_binary(to_binary(x))
assert x.imag == y.imag
assert is_nan(y.real)
x = mpc("nan+nanj")
y = from_binary(to_binary(x))
assert is_nan(y.real)
assert is_nan(y.imag)
get_context().real_prec=100
get_context().imag_prec=110
assert (from_binary(to_binary(mpc("1.3-4.7j"))) ==
mpc('1.2999999999999999999999999999994-4.7000000000000000000000000000000025j',
(100,110)))
def test_mpc_format():
gmpy2.set_context(gmpy2.context())
c, c1 = mpc(mpq(1/3), 5), mpc(-1, -2)
assert '{:>20}'.format(c) == ' 0.333333+5.000000j'
assert '{:<20}'.format(c) == '0.333333+5.000000j '
assert '{:^20}'.format(c) == ' 0.333333+5.000000j '
pytest.raises(ValueError, lambda: '{:<<20}'.format(c))
assert '{:>+20}'.format(c) == ' +0.333333+5.000000j'
pytest.raises(ValueError, lambda: '{:+^20}'.format(c))
assert '{:.10f}'.format(c) == '0.3333333333+5.0000000000j'
pytest.raises(ValueError, lambda: '{:Z.10f}'.format(c))
pytest.raises(ValueError, lambda: '{:Z 10}'.format(c))
assert '{:Z}'.format(c) == '0.333333+5.000000j'
assert '{:U}'.format(c) == '0.333334+5.000000j'
pytest.raises(ValueError, lambda: '{:PU}'.format(c))
assert '{:UP}'.format(c) == '0.333334+5.000000j'
pytest.raises(ValueError, lambda: '{:PP}'.format(c))
assert '{:G}'.format(c) == '0.333333+5.0j'
assert '{:M}'.format(c) == '(0.333333 5.000000)'
assert '{:b}'.format(c) == '1.0101010101010101010101010101010101010101010101010101p-2+1.01p+2j'
assert '{:a}'.format(c) == '0x5.5555555555554p-4+0x5p+0j'
assert '{:e}'.format(c) in ('3.3333333333333331e-01+5e+00j', '3.3333333333333331e-01+5.0000000000000000e+00j')
assert '{:M}'.format(c1) == '(-1.000000 -2.000000)'
def test_mpc_repr():
c = mpc('1.2999999999999999999999999999994-4.7000000000000000000000000000000025j',(100,110))
assert repr(c) == "mpc('1.2999999999999999999999999999994-4.7000000000000000000000000000000025j',(100,110))"
assert repr(mpc("1+nanj")) == "mpc('1.0+nanj')"
assert repr(mpc("infj")) == "mpc('0.0+infj')"
def test_mpc_digits():
c = mpc(mpq(1/3), 5)
assert c.digits(8) == (('2525252525252525250', 0, 53), ('5000000000000000000', 1, 53))
assert c.digits(8, 2) == (('25', 0, 53), ('50', 1, 53))
pytest.raises(ValueError, lambda: c.digits(8, -2))
pytest.raises(ValueError, lambda: c.digits(0))
def test_mpc_abs():
assert abs(mpc(-1,0)) == mpfr('1.0')
assert abs(-1+0j) == 1.0
assert abs(mpc(1,1)) == mpfr('1.4142135623730951')
ctx = gmpy2.get_context()
ctx.clear_flags()
c = mpc('nan+0.0j')
assert is_nan(c.real) and c.imag == 0.0
assert ctx.invalid
ctx.clear_flags()
c = mpc('nan+0j')
assert is_nan(c.real) and c.imag == 0.0
assert ctx.invalid
ctx.clear_flags()
assert is_nan(abs(mpc('nanj'))) and ctx.invalid
ctx.clear_flags()
assert abs(mpc('inf+10j')) == mpfr('inf')
assert abs(mpc('-infj')) == mpfr('inf')
a = mpc('nan+infj')
assert abs(a) and not ctx.invalid
a = mpc('-inf+nanj')
assert abs(a) and not ctx.invalid
def test_mpc_add():
a = mpz(123)
aj = mpc(1+2j)
bj = mpc(4+5j)
assert aj + bj == mpc('5.0+7.0j')
assert bj + aj == mpc('5.0+7.0j')
assert aj + a == mpc('124.0+2.0j')
assert a + aj == mpc('124.0+2.0j')
assert aj + 1 == mpc('2.0+2.0j')
assert 1 + aj == mpc('2.0+2.0j')
assert aj + 0 == mpc('1.0+2.0j')
assert 0 + aj == mpc('1.0+2.0j')
assert -1 + aj == mpc('0.0+2.0j')
assert aj - 1 == mpc('0.0+2.0j')
assert aj + 1.2 == 2.2 + 2j
assert aj + float('inf') == mpc('inf+2.0j')
assert aj + float('-inf') == mpc('-inf+2.0j')
x = aj + float('nan')
assert is_nan(x.real) and x.imag == 2.0
def test_mpc_sub():
pytest.raises(TypeError, lambda: mpc(1,2) - 'a')
assert mpfr(1) - mpc(1,2) == mpc('0.0-2.0j')
assert mpc(1,2) - mpfr(1) == mpc('0.0+2.0j')
assert mpc(1,2) - 1+0j == mpc('0.0+2.0j')
assert 1+0j - mpc(1,2) == mpc('0.0-2.0j')
assert mpc(1,2) - z == mpc('-1.0+2.0j')
assert mpc(1,2) - q == mpc('-0.5+2.0j')
assert mpc(1,2) - r == mpc('-0.5+2.0j')
assert mpc(1,2) - cx == mpc('-41.0-65.0j')
a = mpz(123)
aj = mpc(1+2j)
bj = mpc(4+5j)
assert aj - bj == mpc('-3.0-3.0j')
assert bj - aj == mpc('3.0+3.0j')
assert aj - a == mpc('-122.0+2.0j')
assert a - aj == mpc('122.0-2.0j')
assert aj - 1 == mpc('0.0+2.0j')
assert 1 - aj == mpc('0.0-2.0j')
assert 0 - aj == mpc('-1.0-2.0j')
assert aj - 0 == mpc('1.0+2.0j')
assert aj - -1 == mpc('2.0+2.0j')
assert -1 - aj == mpc('-2.0-2.0j')
assert aj - 1.2 == (1+2j) - 1.2
assert float('inf') - aj == mpc('inf-2.0j')
assert aj - float('inf') == mpc('-inf+2.0j')
assert aj - float('-inf') == mpc('inf+2.0j')
x = aj - float('nan')
assert is_nan(x.real) and x.imag == 2.0
def test_mpc_mul():
pytest.raises(TypeError, lambda: mpc(1,2) * 'a')
assert mpfr(1) * mpc(1,2) == mpc('1.0+2.0j')
assert mpc(1,2) * mpfr(1) == mpc('1.0+2.0j')
assert mpc(1,2) * mpfr(-1) == mpc('-1.0-2.0j')
assert mpc(1,2) * (1+0j) == mpc('1.0+2.0j')
assert (1+0j) * mpc(1,2) == mpc('1.0+2.0j')
assert mpc(1,2) * z == mpc('2.0+4.0j')
assert mpc(1,2) * q == mpc('1.5+3.0j')
assert mpc(1,2) * r == mpc('1.5+3.0j')
assert mpc(1,2) * cx == mpc('-92.0+151.0j')
a = mpz(123)
aj = mpc(1+2j)
bj = mpc(4+5j)
assert aj * bj == mpc('-6.0+13.0j')
assert bj * aj == mpc('-6.0+13.0j')
assert aj * a == mpc('123.0+246.0j')
assert a * aj == mpc('123.0+246.0j')
assert aj * -1 == mpc('-1.0-2.0j')
assert aj * (0.0+1j) == mpc('-2.0+1.0j')
assert aj * float('inf') == mpc('inf+infj')
assert aj * float('-inf') == mpc('-inf-infj')
for x in [aj * float('nan'), mpc(0,0) * float('inf'),
mpc(0,0) * float('-inf'), mpc(0,0) * float('nan')]:
assert all(is_nan(_) for _ in [x.real, x.imag])
def test_mpc_divmod():
pytest.raises(TypeError, lambda: divmod(mpc(1),'a'))
ctx = gmpy2.context()
pytest.raises(TypeError, lambda: ctx.divmod(mpc(1,2),mpc(3,4)))
pytest.raises(TypeError, lambda: divmod(mpc(1,2), mpc(1,2)))
pytest.raises(TypeError, lambda: ctx.divmod(mpc(1,2),mpc(3,4)))
aj = mpc(1+2j)
bj = mpc(4+5j)
with pytest.raises(TypeError):
divmod(aj, bj)
def test_mpc_div():
a = mpz(123)
aj = mpc(1+2j)
bj = mpc(4+5j)
assert aj / bj == mpc('0.34146341463414637+0.073170731707317069j')
assert gmpy2.div(aj, bj) == mpc('0.34146341463414637+0.073170731707317069j')
with pytest.raises(TypeError):
aj // bj
assert aj / a == mpc('0.008130081300813009+0.016260162601626018j')
assert a / aj == mpc('24.600000000000001-49.200000000000003j')
assert aj / 0 == mpc('inf+infj')
assert mpc('2.0+2.0j') / z == mpc('1.0+1.0j')
assert mpc('2.0+2.0j') / q == mpc('1.3333333333333333+1.3333333333333333j')
assert mpc('2.0+2.0j') / r == mpc('1.3333333333333333+1.3333333333333333j')
assert mpc(15,15) / cx == mpc('0.26147449224372299-0.059971213817367662j')
with gmpy2.context(trap_divzero=True):
with pytest.raises(gmpy2.DivisionByZeroError):
mpc(15, 15)/mpc(0)
assert aj / float('inf') == mpc('0.0+0.0j')
assert aj / float('-inf') == mpc('-0.0-0.0j')
assert float('inf') / aj == mpc('inf-infj')
assert float('-inf') / aj == mpc('-inf+infj')
def test_mpc_mod():
a = mpz(123)
aj = mpc(1+2j)
bj = mpc(4+5j)
with pytest.raises(TypeError):
aj % bj
with pytest.raises(TypeError):
aj % a
with pytest.raises(TypeError):
a % aj
def test_mpc_pow():
c1, c2 = mpc(2,5), mpc(5,2)
ctx = gmpy2.get_context()
assert ctx.pow(complex(2,5), complex(5,2)) == mpc('-416.55882051164394+44.334999625388825j')
assert pow(c1, c2) == mpc('-416.55882051164394+44.334999625388825j')
assert ctx.pow(c1, c2) == mpc('-416.55882051164394+44.334999625388825j')
assert ctx.pow(c1, c2) == c1 ** c2
pytest.raises(TypeError, lambda: pow(c1, c2, 5))
assert pow(c1, 5) == mpc('4282.0-1475.0j')
assert c1 ** mpz(5) == mpc('4282.0-1475.0j')
assert c1 ** mpfr(2.5) == mpc('-66.373652915897722+11.111336616269842j')
@settings(max_examples=1000)
@given(complex_numbers(allow_nan=False))
@example(complex())
@example(complex(-1))
@example(complex(-2))
def test_mpc_hash(c):
assert hash(mpc(c)) == hash(c)
def test_mpc_exc():
gmpy2.set_context(gmpy2.ieee(32))
ctx = gmpy2.get_context()
ctx.trap_overflow = True
ctx.trap_underflow = True
c = mpc(0.1 + 0.1j)
pytest.raises(gmpy2.UnderflowResultError, lambda: c**201)
pytest.raises(gmpy2.OverflowResultError, lambda: c**-201)
ctx.trap_inexact = True
pytest.raises(gmpy2.InexactResultError, lambda: mpc(0.25)**0.25)
ctx.trap_invalid = True
pytest.raises(gmpy2.InvalidOperationError, lambda: mpc(mpfr('nan')))
././@PaxHeader 0000000 0000000 0000000 00000000026 00000000000 010213 x ustar 00 22 mtime=1710307256.0
gmpy2-2.2.1/test/test_mpfr.py 0000644 0001750 0001750 00000071045 14574233670 014600 0 ustar 00case case import math
import pickle
import sys
from decimal import Decimal
from fractions import Fraction
import pytest
from hypothesis import example, given, settings
from hypothesis.strategies import floats
from supportclasses import a, b, c, d, q, r, z
import gmpy2
from gmpy2 import (cmp, cmp_abs, from_binary, gamma_inc, get_context, inf,
is_nan, mpc, mpfr, mpfr_grandom, mpfr_nrandom, mpq, mpz,
nan, random_state, to_binary, xmpz, zero)
def test_mpfr_gamma_inc():
assert gamma_inc(1, 1) == mpfr('0.36787944117144233')
assert gamma_inc(1, 0) == mpfr('1.0')
assert gamma_inc(0, 1) == mpfr('0.21938393439552029')
def test_mpfr_cmp():
assert cmp(mpfr(0), mpfr(0)) == 0
assert cmp(mpfr(0), mpz(0)) == 0
assert cmp(mpfr(0), mpq(0,1)) == 0
assert cmp(zero(-1), zero(-1)) == 0
assert cmp(zero(1), zero(-1)) == 0
assert cmp(zero(-1), zero(1)) == 0
assert cmp(mpfr(1), mpfr(0)) == 1
assert cmp(mpfr(1), mpz(0)) == 1
assert cmp(mpfr(1), mpq(0,1)) == 1
assert cmp(mpfr(-1), mpfr(0)) == -1
assert cmp(mpfr(-1), mpz(0)) == -1
assert cmp(mpfr(-1), mpq(0,1)) == -1
assert cmp(nan(), mpfr(0)) == 0
assert cmp(nan(), mpz(0)) == 0
assert cmp(nan(), mpq(0,1)) == 0
gmpy2.get_context().clear_flags()
assert cmp(nan(), 1) == 0
assert gmpy2.get_context().erange is True
assert cmp_abs(mpfr(-1), mpfr(0)) == 1
assert cmp_abs(mpfr(-1), mpz(0)) == 1
assert cmp_abs(mpfr(-1), mpq(0,1)) == 1
assert cmp_abs(mpfr(0), mpfr(-1)) == -1
assert cmp_abs(mpz(0), mpfr(-1)) == -1
assert cmp_abs(mpq(0,1), mpfr(-1)) == -1
assert cmp(mpfr(1.5), q) == 0
assert cmp(r, mpfr(1.5)) == 0
def test_mpfr_comparisons():
from supportclasses import a, q, r
assert mpfr(1.5) == q
assert r == mpfr(1.5)
assert (r == a) is False
a = mpz(123)
r = mpfr('inf')
q = mpq('45/7')
f = float(0.7)
r2 = mpfr(454.6)
assert (r == a, r != a, r > a, r >= a, r < a, r <= a) == (False, True, True, True, False, False)
r = mpfr('-inf')
assert (r == a, r != a, r > a, r >= a, r < a, r <= a) == (False, True, False, False, True, True)
r = mpfr('nan')
assert (r == a, r != a, r > a, r >= a, r < a, r <= a) == (False, True, False, False, False, False)
assert (r == q, r != q, r > q, r >= q, r < q, r <= q) == (False, True, False, False, False, False)
assert (r == f, r != f, r > f, r >= f, r < f, r <= f) == (False, True, False, False, False, False)
assert (r == r2, r != r2, r > r2, r >= r2, r < r2, r <= r2) == (False, True, False, False, False, False)
r = mpfr(126.5)
assert (r == a, r != a, r > a, r >= a, r < a, r <= a) == (False, True, True, True, False, False)
assert (r == q, r != q, r > q, r >= q, r < q, r <= q) == (False, True, True, True, False, False)
f = float(126.5)
assert (r == f, r != f, r > f, r >= f, r < f, r <= f) == (True, False, False, True, False, True)
assert (r == r2, r != r2, r > r2, r >= r2, r < r2, r <= r2) == (False, True, False, False, True, True)
def test_mpfr_conversion():
x = mpfr(a)
assert isinstance(x, mpfr)
assert x == 1.5
pytest.raises(TypeError, lambda: mpfr(b))
pytest.raises(TypeError, lambda: mpfr(c))
pytest.raises(TypeError, lambda: mpfr(d))
pytest.raises(OverflowError, lambda: mpz(mpfr('inf')))
assert mpz(mpfr(5.51)) == mpz(6)
pytest.raises(OverflowError, lambda: xmpz(mpfr('inf')))
assert xmpz(mpfr(5.51)) == xmpz(6)
pytest.raises(OverflowError, lambda: mpq(mpfr('inf')))
assert mpq(mpfr(4.5)) == mpq(9,2)
assert mpq(mpfr(0)) == mpq(0,1)
assert int(mpfr(5.3)) == 5
assert float(mpfr(5.3)) == 5.3
assert str(float('5.656')) == '5.656'
def test_mpfr_create():
assert mpfr() == mpfr('0.0')
assert mpfr(0) == mpfr('0.0')
assert mpfr(1) == mpfr('1.0')
assert mpfr(-1) == mpfr('-1.0')
assert mpfr("123e17") == mpfr('1.23e+19')
assert mpfr('1._3_5e4_5') == mpfr('1.3499999999999999e+45')
pytest.raises(ValueError, lambda: mpfr("foo"))
assert mpfr(1,100) == mpfr('1.0',100)
assert mpfr("1",100) == mpfr('1.0',100)
pytest.raises(TypeError, lambda: mpfr("1","hi"))
assert mpfr("-inf") == mpfr('-inf')
assert mpfr("inf") == mpfr('inf')
assert is_nan(mpfr("nan"))
assert mpfr(float("-inf")) == mpfr('-inf')
assert mpfr(float("inf")) == mpfr('inf')
assert is_nan(mpfr(float("nan")))
assert mpfr(float("0")) == mpfr('0.0')
assert mpfr(float("-0")) == mpfr('-0.0')
assert mpfr("-0") == mpfr('-0.0')
a = float("1.2345678901234567890")
b = mpfr("1.2345678901234567890")
assert a == 1.2345678901234567
assert b == mpfr('1.2345678901234567')
assert a == b
c = mpfr(b)
assert b is c
assert mpfr(Fraction(0,1)) == mpfr('0.0')
assert mpfr(Fraction(0,-1)) == mpfr('0.0')
assert mpfr(Fraction(1,2)) == mpfr('0.5')
assert mpfr(-1) == mpfr('-1.0')
assert mpfr(12345678901234567890) == mpfr('1.2345678901234567e+19')
assert mpfr(mpz(12345678901234567890)) == mpfr('1.2345678901234567e+19')
assert mpfr(mpz(-1)) == mpfr('-1.0')
assert mpfr(2**15 - 1) == mpfr('32767.0')
assert mpfr(2**15) == mpfr('32768.0')
assert mpfr(2**15 + 1) == mpfr('32769.0')
assert mpfr(2**30 - 1) == mpfr('1073741823.0')
assert mpfr(2**30 ) == mpfr('1073741824.0')
assert mpfr(2**30 + 1) == mpfr('1073741825.0')
ctx = gmpy2.get_context()
ctx.clear_flags()
a = mpfr("1.2")
assert a.rc == -1
ctx.clear_flags()
a = mpfr("1.25")
assert a.rc == 0
ctx.clear_flags()
a = mpfr('nan')
assert is_nan(a)
assert ctx.invalid
ctx.clear_flags()
assert is_nan(mpfr(a))
assert not ctx.invalid
ctx.clear_flags()
assert is_nan(mpfr(float('nan')))
assert ctx.invalid
gmpy2.set_context(gmpy2.ieee(128))
assert mpfr(1)/7 == mpfr('0.14285714285714285714285714285714285',113)
assert mpfr(1.0/7) == mpfr('0.142857142857142849212692681248881854',113)
assert mpfr(1.0/7).digits(2) == ('10010010010010010010010010010010010010010010010010010000000000000000000000000000000000000000000000000000000000000', -2, 113)
gmpy2.set_context(gmpy2.ieee(32))
assert mpfr(1)/7 == mpfr('0.142857149',24)
assert (mpfr(1)/7).digits(2) == ('100100100100100100100101', -2, 24)
assert mpfr(1.0/7) == mpfr('0.142857149',24)
assert mpfr(1.0/7).digits(2) == ('100100100100100100100101', -2, 24)
assert mpfr(1.0/7, precision=0) == mpfr('0.142857149',24)
assert repr(mpfr(1.0/7, precision=1)) == "mpfr('0.14285714285714285')"
assert repr(mpfr(1.0/7, precision=5)) == "mpfr('0.141',5)"
@settings(max_examples=1000)
@given(floats())
@example(0.0)
@example(1.0)
@example(2.0)
@example(-1.0)
@example(123.456)
@example(123.5)
@example(float('inf'))
@example(-float('inf'))
@example(float('nan'))
def test_mpfr_hash(x):
if math.isnan(x):
if sys.version_info < (3, 10):
assert hash(mpfr(x)) == hash(x) == sys.hash_info.nan
else:
assert hash(mpfr(x)) != hash(x)
else:
assert hash(mpfr(x)) == hash(x)
@given(floats())
@example(0.0)
@example(1.0)
@example(-1.0)
@example(+float('inf'))
@example(-float('inf'))
@example(float('nan'))
@example(1.345)
def test_mpfr_to_from_binary_bulk(r):
x = mpfr(r)
y = from_binary(to_binary(x))
assert x == y or (is_nan(x) and is_nan(y))
def test_mpfr_to_from_binary():
x = mpfr("1.345e1000")
assert x == from_binary(to_binary(x))
assert -x == from_binary(to_binary(-x))
x = mpfr("1e1234567890123456789")
assert x == from_binary(to_binary(x))
assert x.rc == 1
x = mpfr("-1e1234567890123456789")
assert x == from_binary(to_binary(x))
assert x.rc == -1
x = gmpy2.const_pi()
assert x.rc == -1
y = from_binary(to_binary(x))
assert x == y and y.rc == -1
-1
x = gmpy2.const_pi(precision=104)
assert x.rc == 1
y = from_binary(to_binary(x))
assert x == y and y.rc == 1
with gmpy2.context() as ctx:
ctx.precision = 20
x = gmpy2.const_pi()
assert x == from_binary(to_binary(x))
ctx.precision = 100
x = gmpy2.const_pi()
assert x == from_binary(to_binary(x))
ctx.precision = 200
x = mpfr(gmpy2.const_pi())
assert x == from_binary(to_binary(x))
x = gmpy2.const_pi()
ctx.precision = 300
x = from_binary(to_binary(x))
assert x.precision == 200
def test_mpfr_random():
assert gmpy2.mpfr_random(random_state(42)) == mpfr('0.93002690534702315')
def test_mpfr_grandom():
assert mpfr_grandom(random_state(42)) == (mpfr('-0.32898912492644183'),
mpfr('0.03656576719642516'))
def test_mpfr_nrandom():
assert mpfr_nrandom(random_state(42)) == mpfr('-0.32898912492644183')
def test_mpfr_mpmath():
mpmath = pytest.importorskip("mpmath")
a, b, c, d = '1.1', '-1.1', '-3.14', '0'
assert mpfr(a)._mpf_ == (0, mpz(4953959590107546), -52, 53)
assert mpmath.mpf(mpfr(a)) == mpmath.mpf(a)
assert mpfr(b)._mpf_ == (1, mpz(4953959590107546), -52, 53)
assert mpmath.mpf(mpfr(b)) == mpmath.mpf(b)
assert mpfr(c, precision=10)._mpf_ == (1, mpz(804), -8, 10)
assert mpmath.mpf(mpfr(c, precision=10), prec=10) == mpmath.mpf(c, prec=10)
assert mpfr(d)._mpf_ == (0, mpz(0), 1, 1)
pytest.raises(TypeError, lambda: gmpy2._mpmath_create(1))
pytest.raises(ValueError, lambda: gmpy2._mpmath_create(1, 1, -1))
pytest.raises(TypeError, lambda: mpmath.mpf(("!", 1,)))
def test_mpfr_format():
r, r1, r2 = mpfr(5.6), mpfr(-3), mpfr(5)
assert '{:<30}'.format(r1) == '-3.000000 '
assert '{:>+20}'.format(r2) == ' +5.000000'
assert '{:>-15}'.format(r2) == ' 5.000000'
assert '{:>-15}'.format(r1) == ' -3.000000'
assert '{:U}'.format(r) == '5.600000'
pytest.raises(ValueError, lambda: '{:U-}'.format(r))
assert '{:Z}'.format(r) == '5.599999'
pytest.raises(ValueError, lambda: '{:Z+}'.format(r))
assert '{:+Z}'.format(r) == '+5.599999'
pytest.raises(ValueError, lambda: '{:Z }'.format(r))
assert '{:.10f}'.format(r) == '5.6000000000'
assert '{:.10f.}'.format(r) == '5.6000000000'
assert "{:.0f}".format(mpfr('123')) == '123.0'
pytest.raises(ValueError, lambda: '{:Z.}'.format(r))
pytest.raises(ValueError, lambda: '{:->}'.format(r))
pytest.raises(ValueError, lambda: '{:YZ}'.format(r))
def test_mpfr_digits():
r, r2 = mpfr(5.6), mpfr(5)
assert r.digits() == ('55999999999999996', 1, 53)
assert r.digits(2) == ('10110011001100110011001100110011001100110011001100110', 3, 53)
assert r.digits(2,54) == ('101100110011001100110011001100110011001100110011001100', 3, 53)
assert r.digits(10,54) == ('559999999999999964472863211994990706443786621093750000', 1, 53)
assert r2.digits(2) == ('10100000000000000000000000000000000000000000000000000', 3, 53)
pytest.raises(TypeError, lambda: r2.digits(2, 5, 6))
pytest.raises(ValueError, lambda: r.digits(0))
def test_mpfr_abs():
a = mpfr(1.0)
b = abs(a)
assert a is not b
assert abs(mpfr(1, precision=100)) == mpfr('1.0')
ctx = gmpy2.get_context()
ctx.clear_flags()
assert is_nan(abs(mpfr('nan')))
assert ctx.invalid
ctx.clear_flags()
assert abs(mpfr('inf')) == mpfr('inf')
assert abs(mpfr('-inf')) == mpfr('inf')
def test_mpfr_not():
assert not mpfr(0)
assert not mpfr(1) is False
def test_mpfr_add():
a = mpfr("12.34")
b = mpfr("45.67")
assert a+1 == mpfr('13.34')
assert a+1.0 == mpfr('13.34')
assert a+mpz(1) == mpfr('13.34')
assert a+mpq(1,1) == mpfr('13.34')
assert 1+a == mpfr('13.34')
assert 1.0+a == mpfr('13.34')
assert mpz(1)+a == mpfr('13.34')
assert mpq(1,1)+a == mpfr('13.34')
assert a+b == mpfr('58.010000000000005')
assert a+0 == mpfr('12.34')
assert 0+a == mpfr('12.34')
assert b+a == mpfr('58.010000000000005')
pytest.raises(TypeError, lambda: a+'b')
pytest.raises(TypeError, lambda: 'b'+a)
assert a == 12.34
assert b == 45.67
assert a+b == 12.34+45.67
assert a + float('Inf') == mpfr('inf')
assert float('Inf') + a == mpfr('inf')
assert a + float('-Inf') == mpfr('-inf')
assert float('-Inf') + a == mpfr('-inf')
assert is_nan(a + float('nan'))
assert is_nan(float('nan') + a)
assert a + mpfr('Inf') == mpfr('inf')
assert mpfr('Inf') + a == mpfr('inf')
assert a + mpfr('-Inf') == mpfr('-inf')
assert mpfr('-Inf') + a == mpfr('-inf')
assert is_nan(a + mpfr('nan'))
assert is_nan(mpfr('nan') + a)
def test_mpfr_sub():
assert mpfr(10) - 1 == mpfr('9.0')
assert 10 - mpfr(1) == mpfr('9.0')
assert mpfr(10) - mpz(1) == mpfr('9.0')
assert mpz(10) - mpfr(1) == mpfr('9.0')
assert mpfr(10) - mpfr(1) == mpfr('9.0')
assert mpfr(10) - mpq(1,1) == mpfr('9.0')
assert mpq(10,1) - mpfr(1) == mpfr('9.0')
assert mpfr(10) - Fraction(1,1) == mpfr('9.0')
assert Fraction(10,1) - mpfr(1) == mpfr('9.0')
assert mpfr(10) - 1.0 == mpfr('9.0')
assert 10.0 - mpfr(1) == mpfr('9.0')
assert mpfr(0) - (1 << 100) == mpfr('-1p100', base=2)
assert (1 << 100) - mpfr(0) == mpfr('1p100', base=2)
assert mpfr(10) - z == mpfr('8.0')
assert mpfr(10) - q == mpfr('8.5')
assert mpfr(10) - r == mpfr('8.5')
a = mpfr("12.34")
b = mpfr("45.67")
assert a-1 == mpfr('11.34')
assert a-1.0 == mpfr('11.34')
assert a-(-1) == mpfr('13.34')
assert a-(-1.0) == mpfr('13.34')
assert a-b == mpfr('-33.329999999999998')
assert b-a == mpfr('33.329999999999998')
pytest.raises(TypeError, lambda: a-'b')
pytest.raises(TypeError, lambda: 'b'-a)
assert a-b == 12.34-45.67
assert a - float('Inf') == mpfr('-inf')
assert float('Inf') - a == mpfr('inf')
assert a - float('-Inf') == mpfr('inf')
assert float('-Inf') - a == mpfr('-inf')
assert is_nan(a - float('nan'))
assert is_nan(float('nan') - a)
assert a - mpfr('Inf') == mpfr('-inf')
assert mpfr('Inf') - a == mpfr('inf')
assert a - mpfr('-Inf') == mpfr('inf')
assert mpfr('-Inf') - a == mpfr('-inf')
assert is_nan(a - mpfr('nan'))
assert is_nan(mpfr('nan') - a)
def test_mpfr_mul():
c = 12345678901234567890
assert mpfr(10) * 1 == mpfr('10.0')
assert 10 * mpfr(1) == mpfr('10.0')
assert mpfr(10) * mpz(1) == mpfr('10.0')
assert mpz(10) * mpfr(1) == mpfr('10.0')
assert mpfr(10) * mpfr(1) == mpfr('10.0')
assert mpfr(10) * mpq(1,1) == mpfr('10.0')
assert mpq(10,1) * mpfr(1) == mpfr('10.0')
assert mpfr(10) * Fraction(1,1) == mpfr('10.0')
assert Fraction(10,1) * mpfr(1) == mpfr('10.0')
assert mpfr(10) * 1.0 == mpfr('10.0')
assert 10.0 * mpfr(1) == mpfr('10.0')
assert mpfr(1) * c == mpfr(c)
assert c * mpfr(1) == mpfr(c)
assert mpfr(10) * z == mpfr('20.0')
assert mpfr(10) * q == mpfr('15.0')
assert mpfr(10) * r == mpfr('15.0')
pytest.raises(TypeError, lambda: mpfr(10) * 'a')
pytest.raises(TypeError, lambda: 'a' * mpfr(10))
a = mpfr("12.34")
b = mpfr("45.67")
assert a*b == mpfr('563.56780000000003')
assert a*0 == mpfr('0.0')
assert a*0.0 == mpfr('0.0')
assert a*1 == mpfr('12.34')
assert a*1.0 == mpfr('12.34')
assert a*(-1.0) == mpfr('-12.34')
assert 0*a == mpfr('0.0')
assert 0.0*a == mpfr('0.0')
assert 1*a == mpfr('12.34')
assert 1.0*a == mpfr('12.34')
assert a*b == mpfr('563.56780000000003')
assert a*b == 12.34*45.67
assert a * float('Inf') == mpfr('inf')
assert float('Inf') * a == mpfr('inf')
assert a * float('-Inf') == mpfr('-inf')
assert float('-Inf') * a == mpfr('-inf')
assert -a * float('Inf') == mpfr('-inf')
assert float('Inf') * -a == mpfr('-inf')
assert -a * float('-Inf') == mpfr('inf')
assert float('-Inf') * -a == mpfr('inf')
assert is_nan(a * float('nan'))
assert is_nan(float('nan') * a)
assert is_nan(mpfr(0) * float('Inf'))
assert is_nan(mpfr(0) * float('-Inf'))
assert is_nan(float('Inf') * mpfr(0))
assert is_nan(float('-Inf') * mpfr(0))
assert a * mpfr('Inf') == mpfr('inf')
assert mpfr('Inf') * a == mpfr('inf')
assert a * mpfr('-Inf') == mpfr('-inf')
assert mpfr('-Inf') * a == mpfr('-inf')
assert -a * mpfr('Inf') == mpfr('-inf')
assert mpfr('Inf') * -a == mpfr('-inf')
assert -a * mpfr('-Inf') == mpfr('inf')
assert mpfr('-Inf') * -a == mpfr('inf')
assert is_nan(a * mpfr('nan'))
assert is_nan(mpfr('nan') * a)
assert is_nan(mpz(0) * mpfr('Inf'))
assert is_nan(mpz(0) * mpfr('-Inf'))
assert is_nan(mpfr('Inf') * mpfr(0))
assert is_nan(mpfr('-Inf') * mpfr(0))
def test_mpfr_divmod():
pytest.raises(TypeError, lambda: divmod(mpfr(1),'a'))
ctx = gmpy2.context()
assert ctx.divmod(mpfr(2),mpfr(1)) == (mpfr('2.0'), mpfr('0.0'))
pytest.raises(TypeError, lambda: divmod(mpfr(1), mpc(1,2)))
assert divmod(mpfr(1.2), mpfr(0.7)) == (mpfr('1.0'), mpfr('0.5'))
ctx = gmpy2.ieee(64)
gmpy2.set_context(ctx)
assert divmod(mpfr(1.2), mpfr(0.7)) == (mpfr('1.0'), mpfr('0.5'))
ctx.clear_flags()
assert ctx.divzero is False
assert all(map(ctx.is_nan, divmod(mpfr(1.2), mpfr(0))))
with gmpy2.context(trap_divzero=True):
pytest.raises(gmpy2.DivisionByZeroError, lambda: divmod(mpfr(1), mpfr(0)))
with gmpy2.context(trap_invalid=True):
pytest.raises(gmpy2.InvalidOperationError, lambda: divmod(gmpy2.nan(), mpfr(1)))
with gmpy2.context(trap_invalid=True):
pytest.raises(gmpy2.InvalidOperationError, lambda: divmod(mpfr(1), gmpy2.inf()))
assert divmod(mpfr(111), mpfr(-222)) == (mpfr('-1.0'), mpfr('-111.0'))
a = mpfr("12.34")
b = mpfr("45.67")
assert divmod(12.34, 45.67) == (0.0, 12.34)
assert divmod(a,b) == (mpfr('0.0'), mpfr('12.34'))
assert divmod(b,a) == (mpfr('3.0'), mpfr('8.6500000000000021'))
assert divmod(45.67,12.34) == divmod(b,a)
assert divmod(a, float('Inf')) == (mpfr('0.0'), mpfr('12.34'))
assert divmod(a, float('-Inf')) == (mpfr('-1.0'), mpfr('-inf'))
assert divmod(-a, float('Inf')) == (mpfr('-1.0'), mpfr('inf'))
assert divmod(-a, float('-Inf')) == (mpfr('0.0'), mpfr('-12.34'))
assert all(map(is_nan, divmod(a, float('nan'))))
assert all(map(is_nan, divmod(-a, float('nan'))))
assert divmod(mpfr(0), float('Inf')) == (mpfr('0.0'), mpfr('0.0'))
assert divmod(mpfr(0), float('-Inf')) == (mpfr('-0.0'), mpfr('-0.0'))
assert divmod(mpfr(0), float('nan'))
assert all(map(is_nan, divmod(float('Inf'), a)))
assert all(map(is_nan, divmod(float('-Inf'), a)))
assert all(map(is_nan, divmod(float('Inf'), -a)))
assert all(map(is_nan, divmod(float('-Inf'), -a)))
assert all(map(is_nan, divmod(float('nan'), a)))
assert all(map(is_nan, divmod(float('nan'), -a)))
assert all(map(is_nan, divmod(float('Inf'), mpfr(0))))
assert all(map(is_nan, divmod(float('-Inf'), mpfr(0))))
assert all(map(is_nan, divmod(float('nan'), mpfr(0))))
assert divmod(a, mpfr('Inf')) == (mpfr('0.0'), mpfr('12.34'))
assert divmod(a, mpfr('-Inf')) == (mpfr('-1.0'), mpfr('-inf'))
assert divmod(-a, mpfr('Inf')) == (mpfr('-1.0'), mpfr('inf'))
assert divmod(-a, mpfr('-Inf')) == (mpfr('0.0'), mpfr('-12.34'))
assert all(map(is_nan, divmod(a, mpfr('nan'))))
assert all(map(is_nan, divmod(-a, mpfr('nan'))))
assert divmod(mpfr(0), mpfr('Inf')) == (mpfr('0.0'), mpfr('0.0'))
assert divmod(mpfr(0), mpfr('-Inf')) == (mpfr('-0.0'), mpfr('-0.0'))
assert divmod(mpfr(0), mpfr('nan'))
assert all(map(is_nan, divmod(mpfr('Inf'), a)))
assert all(map(is_nan, divmod(mpfr('-Inf'), a)))
assert all(map(is_nan, divmod(mpfr('Inf'), -a)))
assert all(map(is_nan, divmod(mpfr('-Inf'), -a)))
assert all(map(is_nan, divmod(mpfr('nan'), a)))
assert all(map(is_nan, divmod(mpfr('nan'), -a)))
assert all(map(is_nan, divmod(mpfr('Inf'), mpfr(0))))
assert all(map(is_nan, divmod(mpfr('-Inf'), mpfr(0))))
assert all(map(is_nan, divmod(mpfr('nan'), mpfr(0))))
def test_mpfr_floordiv():
ctx = gmpy2.get_context()
a, b = mpz(45), mpz(6)
r, r2 = mpfr(45), mpfr(3.1)
q, q2 = mpq(118,18), mpq(3,2)
pyq, pyq2 = Fraction(118,18), Fraction(3,2)
c, c2 = mpc(51, 65), mpc(4, 6)
assert ctx.floor_div(r, r2) == mpfr('14.0')
assert ctx.floor_div(r, r2) == mpfr('14.0')
assert ctx.floor_div(r, 3.1) == mpfr('14.0')
assert ctx.floor_div(r, 4) == mpfr('11.0')
assert ctx.floor_div(r, b) == mpfr('7.0')
assert ctx.floor_div(r, q2) == mpfr('30.0')
assert ctx.floor_div(r, pyq2) == mpfr('30.0')
assert ctx.floor_div(r, 0) == mpfr('inf')
assert ctx.floor_div(r, mpz(0)) == mpfr('inf')
assert ctx.floor_div(45.0, r2) == mpfr('14.0')
assert ctx.floor_div(45.0, r2) == mpfr('14.0')
assert ctx.floor_div(45.0, 3.1) == mpfr('14.0')
assert ctx.floor_div(45.0, 4) == mpfr('11.0')
assert ctx.floor_div(45.0, b) == mpfr('7.0')
assert ctx.floor_div(45.0, q2) == mpfr('30.0')
assert ctx.floor_div(45.0, pyq2) == mpfr('30.0')
assert ctx.floor_div(45.0, 0) == mpfr('inf')
assert ctx.floor_div(45.0, mpz(0)) == mpfr('inf')
assert ctx.floor_div(45, r2) == mpfr('14.0')
pytest.raises(TypeError, lambda: ctx.floor_div(r, 'not'))
assert r // b == mpfr('7.0')
assert r // q2 == mpfr('30.0')
assert r // r2 == mpfr('14.0')
pytest.raises(TypeError, lambda: r // c2)
pytest.raises(TypeError, lambda: r // 'not')
a = mpfr("12.34")
b = mpfr("45.67")
assert a//b == mpfr('0.0')
assert b//a == mpfr('3.0')
def test_mpfr_truediv():
a = mpfr("12.34")
b = mpfr("45.67")
assert a/b == mpfr('0.27019925552879348')
assert gmpy2.div(a, b) == mpfr('0.27019925552879348')
assert get_context().div(a, b) == mpfr('0.27019925552879348')
assert b/a == mpfr('3.7009724473257699')
assert a/b == 12.34/45.67
assert a/0 == mpfr('inf')
assert a/(-0.0) == mpfr('-inf')
assert a/b == 12.34/45.67
assert mpfr(10) / z == mpfr('5.0')
assert mpfr(10) / q == mpfr('6.666666666666667')
assert mpfr(10) / r == mpfr('6.666666666666667')
assert b / mpc(4, 4) == mpc('5.7087500000000002-5.7087500000000002j')
assert get_context().div(b, mpc(4, 4)) == mpc('5.7087500000000002-5.7087500000000002j')
ans = b / mpc(0, 0)
assert ans.real == mpfr('inf') and is_nan(ans.imag)
ans = get_context().div(b, mpc(0, 0))
assert ans.real == mpfr('inf') and is_nan(ans.imag)
pytest.raises(TypeError, lambda: b / 'str')
pytest.raises(TypeError, lambda: get_context().div(b, 'str'))
assert a / float('Inf') == mpfr('0.0')
assert -a / float('Inf') == mpfr('-0.0')
assert float('Inf') / a == mpfr('inf')
assert float('Inf') / -a == mpfr('-inf')
assert a / float('-Inf') == mpfr('-0.0')
assert -a / float('-Inf') == mpfr('0.0')
assert float('-Inf') / a == mpfr('-inf')
assert float('-Inf') / -a == mpfr('inf')
assert is_nan(a / float('nan'))
assert is_nan(float('nan') / a)
assert is_nan(float('nan') / mpfr(0))
assert is_nan(float('nan') / mpfr(0))
assert a / mpfr('Inf') == mpfr('0.0')
assert -a / mpfr('Inf') == mpfr('-0.0')
assert mpfr('Inf') / a == mpfr('inf')
assert mpfr('Inf') / -a == mpfr('-inf')
assert a / mpfr('-Inf') == mpfr('-0.0')
assert -a / mpfr('-Inf') == mpfr('0.0')
assert mpfr('-Inf') / a == mpfr('-inf')
assert mpfr('-Inf') / -a == mpfr('inf')
assert is_nan(a / mpfr('nan'))
assert is_nan(mpfr('nan') / a)
assert is_nan(mpfr('nan') / mpfr(0))
assert is_nan(mpfr('nan') / mpfr(0))
def test_mpfr_mod():
r = mpfr('0.0') % mpfr('-1.0')
assert r.is_zero() and r.is_signed()
a = mpfr("12.34")
b = mpfr("45.67")
assert a % 1 == mpfr('0.33999999999999986')
assert 12.34 % 1 == 0.33999999999999986
assert a % z == mpfr('0.33999999999999986')
assert is_nan(b % 0)
assert is_nan(b % mpz(0))
assert is_nan(get_context().mod(b, 0))
assert is_nan(get_context().mod(b, mpz(0)))
assert is_nan(b % mpfr(0))
assert is_nan(get_context().mod(b, mpfr(0)))
get_context().trap_divzero = True
pytest.raises(gmpy2.DivisionByZeroError, lambda: b % 0)
pytest.raises(gmpy2.DivisionByZeroError, lambda: b % mpz(0))
pytest.raises(gmpy2.DivisionByZeroError, lambda: get_context().mod(b, 0))
pytest.raises(gmpy2.DivisionByZeroError, lambda: get_context().mod(b, mpz(0)))
pytest.raises(gmpy2.DivisionByZeroError, lambda: b % mpfr(0))
pytest.raises(gmpy2.DivisionByZeroError, lambda: get_context().mod(b, mpfr(0)))
get_context().trap_divzero = False
pytest.raises(TypeError, lambda: b % 'str')
pytest.raises(TypeError, lambda: get_context().mod(b,'str'))
pytest.raises(TypeError, lambda: b % mpc(3, 5))
assert is_nan(mpfr('nan') % a)
assert is_nan(a % mpfr('nan'))
assert is_nan(mpfr('inf') % a)
assert a % mpfr('inf') == mpfr('12.34')
get_context().trap_invalid = True
pytest.raises(gmpy2.InvalidOperationError, lambda: mpfr('nan') % a)
pytest.raises(gmpy2.InvalidOperationError, lambda: a % mpfr('nan'))
pytest.raises(gmpy2.InvalidOperationError, lambda: mpfr('inf') % a)
pytest.raises(gmpy2.InvalidOperationError, lambda: a % mpfr('inf'))
get_context().trap_invalid = False
pytest.raises(TypeError, lambda: get_context().mod(a, b, 5))
assert get_context().mod(a, -mpfr('inf')) == mpfr('-inf')
def test_mpfr_pow():
r1, r2 = mpfr(5.0), mpfr(2.5)
ctx = gmpy2.get_context()
assert r1 ** mpz(2) == mpfr('25.0')
assert r2 ** mpz(2) == mpfr('6.25')
assert r2 ** 2 == mpfr('6.25')
assert pow(r1, r2) == mpfr('55.901699437494742')
assert ctx.pow(r1, r2) == mpfr('55.901699437494742')
assert ctx.pow(r1, r2) == r1 ** r2
pytest.raises(TypeError, lambda: pow(r1, r2, 5))
pytest.raises(TypeError, lambda: ctx.pow(r1, r2, 5))
assert pow(r1, 4) == mpfr('625.0')
assert ctx.pow(r1, 4) == mpfr('625.0')
def test_mpfr_subnormalize():
gmpy2.set_context(gmpy2.ieee(64))
zeroes = '0.' + '0' * 323
assert mpfr(zeroes + '2470328229206232720') == mpfr('0.0')
assert mpfr(zeroes + '2470328229206232721') == mpfr('4.9406564584124654e-324')
assert mpfr(zeroes + '247032822920623272088') == mpfr('0.0')
assert mpfr(zeroes + '247032822920623272089') == mpfr('4.9406564584124654e-324')
gmpy2.set_context(gmpy2.ieee(32))
def fmt(v):
return '{:.23b}'.format(v)
a = mpfr('0x1p-126')
assert fmt(a) == '1.00000000000000000000000p-126'
assert fmt(gmpy2.next_below(a)) == '1.11111111111111111111110p-127'
assert fmt(gmpy2.next_above(a)) == '1.00000000000000000000001p-126'
assert fmt(gmpy2.next_below(0)) == '-1.00000000000000000000000p-149'
assert fmt(gmpy2.next_above(0)) == '1.00000000000000000000000p-149'
assert fmt(gmpy2.next_toward(a, -10)) == '1.11111111111111111111110p-127'
assert fmt(gmpy2.next_toward(a, 10)) == '1.00000000000000000000001p-126'
gmpy2.set_context(gmpy2.context())
def test_mpfr_as_integer_ratio():
assert mpfr('1.1e+2').as_integer_ratio() == (mpz(110), mpz(1))
pytest.raises(ValueError, lambda: mpfr('nan').as_integer_ratio())
pytest.raises(OverflowError, lambda: mpfr('inf').as_integer_ratio())
def test_mpfr_round():
pytest.raises(TypeError, lambda: round(mpfr('1.0'), "spam"))
r = round(mpfr('-0.0'), 123)
assert r.is_zero() and r.is_signed()
assert round(mpfr('12.34'), -1) == mpfr('10.0')
r = mpfr(4.55)
assert round(r, 1) == mpfr('4.5')
assert round(mpfr('5.1')) == mpz(5)
pytest.raises(ValueError, lambda: round(nan()))
pytest.raises(OverflowError, lambda: round(inf()))
def test_mpfr_as_mantissa_exp():
r = mpfr(4.55)
assert r.as_mantissa_exp() == (mpz(5122844576133939), mpz(-50))
assert mpfr(0).as_mantissa_exp() == (mpz(0), mpz(1))
pytest.raises(OverflowError, lambda: inf().as_mantissa_exp())
pytest.raises(ValueError, lambda: nan().as_mantissa_exp())
def test_mpfr_as_simple_fraction():
r = mpfr(4.55)
assert r.as_simple_fraction() == mpq(91,20)
pytest.raises(ValueError, lambda: r.as_simple_fraction(precision=100))
pytest.raises(TypeError, lambda: r.as_simple_fraction(nosense=10))
def test_mpfr_real_imag():
r = mpfr(4.55)
a = mpfr('12.34')
assert r.imag == mpfr('0.0')
assert r.real == mpfr('4.5499999999999998')
assert a.real == mpfr('12.34')
assert a.imag == mpfr('0.0')
def test_mpfr_conjugate():
r = mpfr(4.55)
a = mpfr('12.34')
assert r.conjugate() == r
assert a.conjugate() == a
def test_mpfr_pickle():
a = mpfr('12.34')
assert pickle.loads(pickle.dumps(a)) == a
assert pickle.loads(pickle.dumps(mpfr("inf"))) == mpfr('inf')
assert pickle.loads(pickle.dumps(mpfr("-inf"))) == mpfr('-inf')
assert is_nan(pickle.loads(pickle.dumps(mpfr("nan"))))
assert pickle.loads(pickle.dumps(mpfr(0))) == mpfr('0.0')
././@PaxHeader 0000000 0000000 0000000 00000000026 00000000000 010213 x ustar 00 22 mtime=1710307256.0
gmpy2-2.2.1/test/test_mpq.py 0000644 0001750 0001750 00000043404 14574233670 014427 0 ustar 00case case import math
import numbers
import pickle
import sys
from decimal import Decimal
from fractions import Fraction
import pytest
from hypothesis import example, given, settings
from hypothesis.strategies import fractions, integers
from supportclasses import a, b, c, d, q, z
import gmpy2
from gmpy2 import (cmp, cmp_abs, from_binary, is_nan, mpc, mpfr, mpq, mpz,
to_binary, xmpz)
def test_mpz_constructor():
assert mpq('1/1') == mpq(1,1)
assert mpq('1_/_1') == mpq(1,1)
def test_mpq_as_integer_ratio():
assert mpq(2, 3).as_integer_ratio() == (mpz(2), mpz(3))
def test_mpq_numbers_abc():
assert isinstance(mpq(1, 3), numbers.Rational)
def test_mpq_pickling():
for proto in range(pickle.HIGHEST_PROTOCOL + 1):
for x in [mpq(1234, 6789), mpq(-1234, 6789), mpq(0, 1)]:
assert pickle.loads(pickle.dumps(x, protocol=proto)) == x
def test_mpq_from_float():
assert mpq.from_float(3.2) == mpq(3602879701896397, 1125899906842624)
def test_mpq_from_Decimal():
assert mpq(Decimal("5e-3")) == mpq(5, 1000)
assert mpq(Decimal(1)) == mpq(1) # issue 327
assert mpq(Decimal('0.6')) == mpq(3, 5)
assert mpq.from_decimal(Decimal("5e-3")) == mpq(5, 1000)
def test_mpq_cmp():
assert cmp(mpq(1,2), mpq(1,2)) == 0
assert cmp(mpq(-1,2), mpq(1,2)) == -1
assert cmp(mpq(1,2), mpq(-1,2)) == 1
assert cmp(0, mpq(1,2)) == -1
assert cmp(mpq(1,2), 0) == 1
assert cmp_abs(mpq(1,2), mpq(1,3)) == 1
assert cmp_abs(mpq(-1,2), mpq(1,3)) == 1
assert cmp_abs(mpq(1,2), mpq(-1,3)) == 1
assert cmp_abs(mpq(1,4), mpq(1,3)) == -1
assert cmp_abs(mpq(-1,4), mpq(1,3)) == -1
assert cmp_abs(mpq(1,4), mpq(-1,3)) == -1
assert cmp(mpq(3,2), q) == 0
assert cmp(q, mpq(3,5)) == 1
def test_mpq_comparisons():
from supportclasses import q
assert mpq(3,2) == q
assert (q == mpq(3,5)) is False
a = mpz(123)
q = mpq(4, 5)
assert (q == a, q != a, q > a, q >= a, q < a, q <= a) == (False, True, False, False, True, True)
assert (mpq(246,2) != a) is False
f = float(0.7)
assert (q == f, q != f, q > f, q >= f, q < f, q <= f) == (False, True, True, True, False, False)
f = float('nan')
assert (q == f, q != f, q > f, q >= f, q < f, q <= f) == (False, True, False, False, False, False)
f = float('inf')
assert (q == f, q != f, q > f, q >= f, q < f, q <= f) == (False, True, False, False, True, True)
f = -f
assert (q == f, q != f, q > f, q >= f, q < f, q <= f) == (False, True, True, True, False, False)
def test_mpq_conversion():
x = mpq(a)
assert isinstance(x, mpq)
assert 2*x == 3
assert mpq(z, z) == mpq(1, 1)
class Three:
def __mpz__(self): return mpz(3)
assert mpq(z, Three()) == mpq(2,3)
pytest.raises(TypeError, lambda: mpq(b))
pytest.raises(TypeError, lambda: mpq(c))
pytest.raises(TypeError, lambda: mpq(d))
assert mpq('2/3') == mpq(2,3)
assert mpq(b'2/3') == mpq(2,3)
pytest.raises(ValueError, lambda: mpq('2,3'))
pytest.raises(ValueError, lambda: mpq('2/a'))
assert mpq('2.3') == mpq(23,10)
assert pytest.raises(ValueError, lambda: mpq('2.3/10'))
assert mpq(4.5) == mpq(9,2)
pytest.raises(OverflowError, lambda: mpq(float('inf')))
assert mpq(xmpz(15)) == mpq(15,1)
assert mpq(mpfr(4.5)) == mpq(9,2)
pytest.raises(TypeError, lambda: mpq(dict()))
assert float(mpq(1,2)) == 0.5
assert int(mpq(15,2)) == 7
def test_mpq_round():
pytest.raises(TypeError, lambda: round(mpq(7,3), 4.5))
q = mpq('4/5')
assert round(mpq('7/2')) == mpz(4)
assert round(q, 4) == mpq(4,5)
pytest.raises(TypeError, lambda: round(q, 4, 2))
@settings(max_examples=1000)
@given(integers(), integers(min_value=1))
@example(0, 1)
@example(1, 1)
@example(-1, 2)
@example(123456789123456789, 9876)
def test_mpq_to_from_binary(p, q):
x = mpq(p,q)
assert x == from_binary(to_binary(x))
@settings(max_examples=1000)
@given(fractions())
@example(Fraction(0))
@example(Fraction(-1))
@example(Fraction(-2))
@example(Fraction(15432, 125))
@example(Fraction(1, sys.hash_info.modulus))
@example(Fraction(-1, sys.hash_info.modulus))
def test_mpq_hash(q):
assert hash(mpq(q)) == hash(q)
def test_mpq_digits():
q = mpq(2/3)
assert q.digits() == '6004799503160661/9007199254740992'
assert q.digits(16) == '0x15555555555555/0x20000000000000'
pytest.raises(TypeError, lambda: q.digits(16, 5))
pytest.raises(ValueError, lambda: q.digits(0))
def test_mpq_abs():
a = mpq(12,7)
b = abs(a)
assert a is b
a = mpq(-12,7)
b = abs(a)
assert b == mpq(12,7)
assert a == mpq(-12,7)
def test_mpq_add():
a = mpq(3,11)
assert a + float('Inf') == mpfr('inf')
assert float('Inf') + a == mpfr('inf')
assert a + float('-Inf') == mpfr('-inf')
assert float('-Inf') + a == mpfr('-inf')
assert is_nan(a + float('nan'))
assert is_nan(float('nan') + a)
assert a + mpfr('Inf') == mpfr('inf')
assert mpfr('Inf') + a == mpfr('inf')
assert a + mpfr('-Inf') == mpfr('-inf')
assert mpfr('-Inf') + a == mpfr('-inf')
assert is_nan(a + mpfr('nan'))
assert is_nan(mpfr('nan') + a)
def test_mpq_sub():
assert mpq(1,2) - Fraction(3,2) == mpq(-1,1)
assert Fraction(1,2) - mpq(3,2) == mpq(-1,1)
assert mpq(1,2) - mpq(3,2) == mpq(-1,1)
assert mpq(1,2) - 0 == mpq(1,2)
assert mpq(1,2) - mpz(1) == mpq(-1,2)
assert mpq(1,2) + (-1) == mpq(-1,2)
assert 1 - mpq(1,2) == mpq(1,2)
assert mpz(1) - mpq(1,2) == mpq(1,2)
assert mpq(1,2) - mpz(1) == mpq(-1,2)
assert mpq(1,1) - mpc(0) == mpc('1.0+0.0j')
assert mpc(0) - mpq(1,1) == mpc('-1.0+0.0j')
assert mpq(1,2) - z == mpq(-3,2)
assert mpq(1,2) - q ==mpq(-1,1)
ctx = gmpy2.context()
assert ctx.sub(mpq(1,2), mpq(3,2)) == mpq(-1,1)
assert ctx.sub(mpq(1,2), Fraction(3,2)) == mpq(-1,1)
assert ctx.sub(Fraction(1,2), mpq(3,2)) == mpq(-1,1)
assert ctx.sub(Fraction(1,2), Fraction(3,2)) == mpq(-1,1)
pytest.raises(TypeError, lambda: ctx.sub(1,'a'))
pytest.raises(TypeError, lambda: mpq(1,2) - 'a')
pytest.raises(TypeError, lambda: 'a' - mpq(1,2))
a = mpq(3,11)
b = mpq(1,2)
c = Fraction(5,7)
assert a-b == mpq(-5,22)
assert b-a == mpq(5,22)
assert a-1 == mpq(-8,11)
assert 1-a == mpq(8,11)
assert a-c == mpq(-34,77)
assert c-a == mpq(34,77)
assert a-a == mpq(0,1)
assert a-mpz(123456) == mpq(-1358013,11)
assert mpz(-123456)-a == mpq(-1358019,11)
pytest.raises(TypeError, lambda: a-'b')
pytest.raises(TypeError, lambda: 'b'-a)
assert a - float('Inf') == mpfr('-inf')
assert float('Inf') - a == mpfr('inf')
assert a - float('-Inf') == mpfr('inf')
assert float('-Inf') - a == mpfr('-inf')
assert is_nan(a - float('nan'))
assert is_nan(float('nan') - a)
assert a - mpfr('Inf') == mpfr('-inf')
assert mpfr('Inf') - a == mpfr('inf')
assert a - mpfr('-Inf') == mpfr('inf')
assert mpfr('-Inf') - a == mpfr('-inf')
assert is_nan(a - mpfr('nan'))
assert is_nan(mpfr('nan') - a)
def test_mpq_mul():
assert mpq(1,2) * Fraction(3,2) == mpq(3,4)
assert Fraction(1,2) * mpq(3,2) == mpq(3,4)
assert mpq(1,2) * mpq(3,2) == mpq(3,4)
assert mpq(1,2) * 0 == mpq(0,1)
assert mpq(1,2) * mpz(1) == mpq(1,2)
assert mpq(1,2) * (-1) == mpq(-1,2)
assert mpq(1,1) * mpc(1,0) == mpc('1.0+0.0j')
assert mpc(1,0) * mpq(1,1) == mpc('1.0+0.0j')
assert mpq(1,2) * z == mpq(1,1)
assert mpq(1,2) * q == mpq(3,4)
ctx = gmpy2.context()
assert ctx.mul(mpq(1,2), mpq(3,2)) == mpq(3,4)
assert ctx.mul(mpq(1,2), Fraction(3,2)) == mpq(3,4)
assert ctx.mul(Fraction(1,2), mpq(3,2)) == mpq(3,4)
assert ctx.mul(Fraction(1,2), Fraction(3,2)) == mpq(3,4)
pytest.raises(TypeError, lambda: ctx.mul(1,'a'))
pytest.raises(TypeError, lambda: mpq(1,2) * 'a')
pytest.raises(TypeError, lambda: 'a' * mpq(1,2))
a = mpq(3,11)
b = mpq(1,2)
assert a*b == mpq(3,22)
assert b*a == mpq(3,22)
assert a*0 == mpq(0,1)
assert 0*a == mpq(0,1)
assert a*-1 == mpq(-3,11)
assert -1*a == mpq(-3,11)
assert a*mpz(17) == mpq(51,11)
assert mpz(17)*a == mpq(51,11)
assert a*a == mpq(9,121)
pytest.raises(TypeError, lambda: a*'b')
pytest.raises(TypeError, lambda: 'b'*a)
assert a * float('Inf') == mpfr('inf')
assert float('Inf') * a == mpfr('inf')
assert a * float('-Inf') == mpfr('-inf')
assert float('-Inf') * a == mpfr('-inf')
assert -a * float('Inf') == mpfr('-inf')
assert float('Inf') * -a == mpfr('-inf')
assert -a * float('-Inf') == mpfr('inf')
assert float('-Inf') * -a == mpfr('inf')
assert is_nan(a * float('nan'))
assert is_nan(float('nan') * a)
assert is_nan(mpz(0) * float('Inf'))
assert is_nan(mpz(0) * float('-Inf'))
assert is_nan(float('Inf') * mpz(0))
assert is_nan(float('-Inf') * mpz(0))
assert a * mpfr('Inf') == mpfr('inf')
assert mpfr('Inf') * a == mpfr('inf')
assert a * mpfr('-Inf') == mpfr('-inf')
assert mpfr('-Inf') * a == mpfr('-inf')
assert -a * mpfr('Inf') == mpfr('-inf')
assert mpfr('Inf') * -a == mpfr('-inf')
assert -a * mpfr('-Inf') == mpfr('inf')
assert mpfr('-Inf') * -a == mpfr('inf')
assert is_nan(a * mpfr('nan'))
assert is_nan(mpfr('nan') * a)
assert is_nan(mpz(0) * mpfr('Inf'))
assert is_nan(mpz(0) * mpfr('-Inf'))
assert is_nan(mpfr('Inf') * mpz(0))
assert is_nan(mpfr('-Inf') * mpz(0))
def test_mpq_mod():
a = mpq(3,11)
b = mpq(1,2)
ctx = gmpy2.get_context()
assert a%b == mpq(3,11)
assert b%a == mpq(5,22)
assert a%z == mpq(3,11)
assert mpq(3,1) % q == mpq(0,1)
pytest.raises(ZeroDivisionError, lambda: a % mpq(0,5))
assert ctx.mod(a, mpfr(1.5)) == mpfr('0.27272727272727271')
pytest.raises(TypeError, lambda: ctx.mod(a, mpc(0.5, 2)))
pytest.raises(ZeroDivisionError, lambda: ctx.mod(a, mpq(0, 2)))
assert a % mpfr(1.5) == mpfr('0.27272727272727271')
pytest.raises(TypeError, lambda: a % mpc(0.5, 2))
pytest.raises(TypeError, lambda: a % 'str')
pytest.raises(TypeError, lambda: ctx.mod(a, 'str'))
def test_mpq_divmod():
a = mpq(3,11)
b = mpq(1,2)
c = Fraction(5,7)
ctx = gmpy2.get_context()
assert divmod(a,b) == (mpz(0), mpq(3,11))
assert divmod(b,a) == (mpz(1), mpq(5,22))
pytest.raises(ZeroDivisionError, lambda: divmod(a,0))
assert divmod(17,a) == (mpz(62), mpq(1,11))
assert divmod(mpz(17),a) == (mpz(62), mpq(1,11))
assert divmod(a,c) == (mpz(0), mpq(3,11))
pytest.raises(TypeError, lambda: divmod(mpq(1,2),'a'))
ctx = gmpy2.ieee(64)
gmpy2.set_context(ctx)
assert ctx.divmod(mpq(3,2),mpq(3,7)) == (mpz(3), mpq(3,14))
pytest.raises(TypeError, lambda: divmod(mpq(1,2), mpc(1,2)))
assert divmod(a, float('Inf')) == (mpfr('0.0'), mpfr('0.27272727272727271'))
assert divmod(a, float('-Inf')) == (mpfr('-1.0'), mpfr('-inf'))
assert divmod(-a, float('Inf')) == (mpfr('-1.0'), mpfr('inf'))
assert divmod(-a, float('-Inf')) == (mpfr('0.0'), mpfr('-0.27272727272727271'))
assert all(map(is_nan, divmod(a, float('nan'))))
assert all(map(is_nan, divmod(-a, float('nan'))))
assert divmod(mpz(0), float('Inf')) == (mpfr('0.0'), mpfr('0.0'))
assert divmod(mpz(0), float('-Inf')) == (mpfr('-0.0'), mpfr('-0.0'))
assert all(map(is_nan, divmod(mpz(0), float('nan'))))
assert all(map(is_nan, divmod(float('Inf'), a)))
assert all(map(is_nan, divmod(float('-Inf'), a)))
assert all(map(is_nan, divmod(float('Inf'), -a)))
assert all(map(is_nan, divmod(float('-Inf'), -a)))
assert all(map(is_nan, divmod(float('nan'), a)))
assert all(map(is_nan, divmod(float('nan'), -a)))
assert all(map(is_nan, divmod(float('Inf'), mpz(0))))
assert all(map(is_nan, divmod(float('-Inf'), mpz(0))))
assert all(map(is_nan, divmod(float('nan'), mpz(0))))
assert divmod(a, mpfr('Inf')) == (mpfr('0.0'), mpfr('0.27272727272727271'))
assert divmod(a, mpfr('-Inf')) == (mpfr('-1.0'), mpfr('-inf'))
assert divmod(-a, mpfr('Inf')) == (mpfr('-1.0'), mpfr('inf'))
assert divmod(-a, mpfr('-Inf')) == (mpfr('0.0'), mpfr('-0.27272727272727271'))
assert all(map(is_nan, divmod(a, mpfr('nan'))))
assert all(map(is_nan, divmod(-a, mpfr('nan'))))
assert divmod(mpz(0), mpfr('Inf')) == (mpfr('0.0'), mpfr('0.0'))
assert divmod(mpz(0), mpfr('-Inf')) == (mpfr('-0.0'), mpfr('-0.0'))
assert divmod(mpz(0), mpfr('nan'))
assert divmod(mpfr('Inf'), a)
assert divmod(mpfr('-Inf'), a)
assert divmod(mpfr('Inf'), -a)
assert divmod(mpfr('-Inf'), -a)
assert divmod(mpfr('nan'), a)
assert divmod(mpfr('nan'), -a)
assert divmod(mpfr('Inf'), mpz(0))
assert divmod(mpfr('-Inf'), mpz(0))
assert divmod(mpfr('nan'), mpz(0))
def test_mpq_floordiv():
ctx = gmpy2.get_context()
a, b = mpz(45), mpz(6)
r, r2 = mpfr(45), mpfr(3.1)
q, q2 = mpq(118,18), mpq(3,2)
pyq, pyq2 = Fraction(118,18), Fraction(3,2)
c, c2 = mpc(51, 65), mpc(4, 6)
assert ctx.floor_div(q, q2) == mpz(4)
assert ctx.floor_div(q, pyq2) == mpz(4)
assert ctx.floor_div(q, pyq) == mpz(1)
assert ctx.floor_div(pyq, q2) == mpz(4)
assert ctx.floor_div(pyq, pyq2) == mpz(4)
assert ctx.floor_div(pyq, q) == mpz(1)
pytest.raises(ZeroDivisionError, lambda: ctx.floor_div(q, mpq(0,1)))
pytest.raises(ZeroDivisionError, lambda: ctx.floor_div(q, Fraction(0)))
pytest.raises(ZeroDivisionError, lambda: ctx.floor_div(pyq, mpq(0,1)))
pytest.raises(ZeroDivisionError, lambda: ctx.floor_div(pyq, Fraction(0)))
assert q // b == mpz(1)
assert q // q2 == mpz(4)
assert q // r2 == mpfr('2.0')
pytest.raises(TypeError, lambda: q // c2)
pytest.raises(TypeError, lambda: q // 'not')
a = mpq(3,11)
b = mpq(1,2)
assert a//b == mpz(0)
assert b//a == mpz(1)
pytest.raises(ZeroDivisionError, lambda: a//0)
assert 0//a == mpz(0)
assert mpq(355, 113) // 2 == mpz(1)
assert mpq(355, 113) // mpz(2) == mpz(1)
assert mpq(355, 113) // z == mpz(1)
def test_mpq_truediv():
a = mpq(3,11)
b = mpq(1,2)
ctx = gmpy2.get_context()
assert a/b == mpq(6,11)
assert gmpy2.div(a, b) == mpq(6,11)
assert ctx.div(a, b) == mpq(6,11)
assert b/a == mpq(11,6)
pytest.raises(ZeroDivisionError, lambda: a/0)
assert 0/a == mpq(0,1)
assert a / z == mpq(3,22)
assert mpq(3,11) / q == mpq(2,11)
assert a / mpc(5, 4) == mpc('0.03325942350332594-0.02660753880266075j')
pytest.raises(ZeroDivisionError, lambda: a / mpq(0,1))
pytest.raises(TypeError, lambda: a / 'str')
assert a / float('Inf') == mpfr('0.0')
assert -a / float('Inf') == mpfr('-0.0')
assert float('Inf') / a == mpfr('inf')
assert float('Inf') / -a == mpfr('-inf')
assert a / float('-Inf') == mpfr('-0.0')
assert -a / float('-Inf') == mpfr('0.0')
assert float('-Inf') / a == mpfr('-inf')
assert float('-Inf') / -a == mpfr('inf')
assert is_nan(a / float('nan'))
assert is_nan(float('nan') / a)
assert is_nan(float('nan') / mpz(0))
assert a / mpfr('Inf') == mpfr('0.0')
assert -a / mpfr('Inf') == mpfr('-0.0')
assert mpfr('Inf') / a == mpfr('inf')
assert mpfr('Inf') / -a == mpfr('-inf')
assert a / mpfr('-Inf') == mpfr('-0.0')
assert -a / mpfr('-Inf') == mpfr('0.0')
assert mpfr('-Inf') / a == mpfr('-inf')
assert mpfr('-Inf') / -a == mpfr('inf')
assert is_nan(a / mpfr('nan'))
assert is_nan(mpfr('nan') / a)
assert is_nan(mpfr('nan') / mpz(0))
assert is_nan(mpfr('nan') / mpz(0))
def test_mpq_pow():
q = mpq(2,3)
ctx = gmpy2.get_context()
assert q ** 2 == mpq(4,9)
assert q ** 0 == mpq(1,1)
assert q ** -5 == mpq(243,32)
assert ctx.pow(Fraction(2,3),2) == q ** 2
assert mpq(-5,8) ** 5 == mpq(-3125,32768)
assert q ** mpq(4,5) == mpfr('0.72298118079846574')
pytest.raises(TypeError, lambda: pow(q, 5, 2))
def test_mpq_attributes():
q = mpq('4/5')
a = mpq(3,11)
pyq = Fraction(4, 5)
assert q.numerator == mpz(4)
assert q.denominator == mpz(5)
assert gmpy2.numer(q) == mpz(4)
assert gmpy2.denom(q) == mpz(5)
assert a.numerator == mpz(3)
assert a.denominator == mpz(11)
assert a.real == mpq(3,11)
assert a.imag == mpz(0)
pytest.raises(TypeError, lambda: gmpy2.numer(6.2))
pytest.raises(TypeError, lambda: gmpy2.denom(5.6))
pytest.raises(TypeError, lambda: gmpy2.denom(mpfr(5)))
assert gmpy2.numer(pyq) == mpz(4)
assert gmpy2.denom(pyq) == mpz(5)
def test_mpq_conjugate():
a = mpq(3, 11)
assert a.conjugate() == a
def test_mpq_floor():
assert math.floor(mpq('7/2')) == mpz(3)
def test_mpq_ceil():
assert math.ceil(mpq('7/2')) == mpz(4)
def test_mpq_trunc():
assert math.trunc(mpq('7/2')) == mpz(3)
def test_mpq_not():
q = mpq('4/5')
assert q
assert not mpq('0/5')
def test_mpq_qdiv():
q = mpq('4/5')
pyq = Fraction(4, 5)
assert gmpy2.qdiv(q) == mpq(4,5)
assert gmpy2.qdiv(pyq) == mpq(4,5)
assert gmpy2.qdiv(5) == mpz(5)
pytest.raises(TypeError, lambda: gmpy2.qdiv(mpc(4, 5)))
pytest.raises(TypeError, lambda: gmpy2.qdiv(4, 5, 4))
pytest.raises(TypeError, lambda: gmpy2.qdiv(4, 5.6))
assert gmpy2.qdiv(q, 2) == mpq(2,5)
assert gmpy2.qdiv(10, q) == mpq(25,2)
assert gmpy2.qdiv(1) == mpz(1)
assert gmpy2.qdiv(8,1) == mpz(8)
assert gmpy2.qdiv(8,2) == mpz(4)
assert gmpy2.qdiv(8,3) == mpq(8,3)
assert gmpy2.qdiv(8,4) == mpz(2)
assert gmpy2.qdiv(mpq(3,4), mpq(1,3)) == mpq(9,4)
assert gmpy2.qdiv(mpq(3,4), mpq(1,4)) == mpz(3)
args = mpq(2), 1/gmpy2.mpq(2)
assert gmpy2.qdiv(*args) == mpz(4)
assert args == (mpq(2), 1/mpq(2))
def test_mpq_repr():
assert repr(mpq(11,13)) == 'mpq(11,13)'
def test_mpq_str():
assert str(mpq(11,13)) == '11/13'
def test_issue_334():
x = mpq(3,2)
y = mpq(x,2)
assert x == mpq(3,2)
assert y == mpq(3,4)
assert id(x) is not id(y)
././@PaxHeader 0000000 0000000 0000000 00000000026 00000000000 010213 x ustar 00 22 mtime=1718253275.0
gmpy2-2.2.1/test/test_mpz.py 0000644 0001750 0001750 00000136302 14632473333 014435 0 ustar 00case case import math
import numbers
import pickle
from fractions import Fraction
from hypothesis import assume, example, given, settings
from hypothesis.strategies import booleans, integers, sampled_from
from pytest import mark, raises
from supportclasses import a, b, c, d, q, z
import gmpy2
from gmpy2 import (cmp, cmp_abs, from_binary, is_nan, is_prime, mp_version,
mpc, mpfr, mpq, mpz, mpz_random, mpz_rrandomb, mpz_urandomb,
next_prime, pack, random_state, to_binary, unpack, xmpz)
def test_mpz_to_bytes_interface():
x = mpz(1)
with raises(TypeError):
x.to_bytes(1, 2, 3)
with raises(TypeError):
x.to_bytes(1, 2)
with raises(TypeError):
x.to_bytes('spam')
with raises(TypeError):
x.to_bytes(a=1, b=2, c=3, d=4)
with raises(TypeError):
x.to_bytes(2, length=2)
with raises(TypeError):
x.to_bytes(2, 'big', byteorder='big')
with raises(TypeError):
x.to_bytes(spam=1)
with raises(ValueError):
x.to_bytes(2, 'spam')
with raises(ValueError):
x.to_bytes(-1)
assert x.to_bytes(2) == x.to_bytes(length=2)
assert x.to_bytes(2, byteorder='little') == x.to_bytes(2, 'little')
assert x.to_bytes() == x.to_bytes(1)
assert x.to_bytes() == x.to_bytes(1, 'big')
assert x.to_bytes() == x.to_bytes(signed=False)
@settings(max_examples=1000)
@given(integers(), integers(min_value=0, max_value=10000),
sampled_from(['big', 'little']), booleans())
@example(0, 0, 'big', False)
@example(0, 0, 'little', False)
@example(0, 1, 'big', False)
@example(128, 1, 'big', True)
@example(128, 1, 'little', True)
@example(-129, 1, 'big', True)
@example(-129, 1, 'little', True)
@example(-1, 0, 'big', True)
@example(-2, 0, 'big', True)
@example(-2, 0, 'little', True)
@example(42, 1, 'big', False)
@example(42, 1, 'little', False)
@example(42, 3, 'big', False)
@example(42, 3, 'little', False)
@example(1000, 2, 'big', False)
@example(1000, 4, 'big', False)
@example(-2049, 1, 'big', True)
@example(-65281, 3, 'big', True)
@example(-65281, 3, 'little', True)
def test_mpz_to_bytes(x, length, byteorder, signed):
try:
rx = x.to_bytes(length, byteorder, signed=signed)
except OverflowError:
with raises(OverflowError):
mpz(x).to_bytes(length, byteorder, signed=signed)
else:
assert rx == mpz(x).to_bytes(length, byteorder, signed=signed)
def test_mpz_from_bytes_interface():
with raises(TypeError):
mpz.from_bytes()
with raises(TypeError):
mpz.from_bytes(1, 2, 3)
with raises(TypeError):
mpz.from_bytes(b'', 2)
with raises(TypeError):
mpz.from_bytes(1)
with raises(TypeError):
mpz.from_bytes(b'', bytes=b'')
with raises(TypeError):
mpz.from_bytes(b'', 'big', byteorder='big')
with raises(TypeError):
mpz.from_bytes(b'', spam=1)
with raises(TypeError):
mpz.from_bytes(a=1, b=2, c=3, d=4)
with raises(ValueError):
mpz.from_bytes(b'', 'spam')
assert mpz.from_bytes(b'\x01', byteorder='little') == mpz.from_bytes(b'\x01', 'little')
assert mpz.from_bytes(b'\x01') == mpz.from_bytes(bytes=b'\x01')
assert mpz.from_bytes(b'\x01') == mpz.from_bytes(b'\x01', 'big')
assert mpz.from_bytes(b'\x01') == mpz.from_bytes(b'\x01', signed=False)
@settings(max_examples=1000)
@given(integers(), integers(min_value=0, max_value=10000),
sampled_from(['big', 'little']), booleans())
@example(0, 0, 'big', False)
@example(0, 0, 'little', False)
@example(0, 1, 'big', False)
@example(128, 1, 'big', True)
@example(128, 1, 'little', True)
@example(-129, 1, 'big', True)
@example(-129, 1, 'little', True)
@example(-1, 0, 'big', True)
@example(-1, 1, 'big', True)
@example(-1, 1, 'little', True)
@example(-2, 0, 'big', True)
@example(-2, 0, 'little', True)
@example(-1, 3, 'big', True)
@example(-2, 3, 'big', True)
@example(-2, 5, 'little', True)
def test_mpz_from_bytes(x, length, byteorder, signed):
try:
bytes = x.to_bytes(length, byteorder, signed=signed)
except OverflowError:
assume(False)
else:
rx = int.from_bytes(bytes, byteorder, signed=signed)
assert rx == mpz.from_bytes(bytes, byteorder, signed=signed)
assert rx == mpz.from_bytes(bytearray(bytes), byteorder, signed=signed)
assert rx == mpz.from_bytes(list(bytes), byteorder, signed=signed)
def test_mpz_as_integer_ratio():
assert mpz(3).as_integer_ratio() == (mpz(3), mpz(1))
def test_mpz_numbers_abc():
assert isinstance(mpz(2), numbers.Integral)
def test_mpz_pickling():
for proto in range(pickle.HIGHEST_PROTOCOL + 1):
for x in [mpz(12346789), mpz(-12346789), mpz(0)]:
assert pickle.loads(pickle.dumps(x, protocol=proto)) == x
@settings(max_examples=1000)
@given(integers(), integers())
@example(0, 0)
@example(0, 1)
@example(-11, 75)
@example(14, 105)
@example(64, 123456789012345678901234567890)
@example(321, -123)
def test_mpz_arithmetics(i, z):
i, z = map(mpz, [i, z])
assert int(i) + int(z) == i + z
assert int(z) + int(i) == z + i
assert int(i) - int(z) == i - z
assert int(z) - int(i) == z - i
assert int(i) * int(z) == i * z
assert int(z) * int(i) == z * i
# Test all permutations of floor division
if z:
assert int(i) // int(z) == i // z
assert int(i) % int(z) == i % z
assert i % int(z) == i % z
assert int(i) % z == i % z
assert divmod(int(i), int(z)) == divmod(i, z)
assert divmod(i, int(z)) == divmod(i, z)
assert divmod(int(i), z) == divmod(i, z)
if i:
assert int(z) // int(i) == z // i
assert int(z) % int(i) == z % i
assert z % int(i) == z % i
assert int(z) % i == z % i
assert divmod(int(z), int(i)) == divmod(z, i)
assert divmod(z, int(i)) == divmod(z, i)
assert divmod(int(z), i) == divmod(z, i)
@settings(max_examples=1000)
@given(integers(min_value=0),
integers(min_value=1, max_value=100000))
def test_mpz_pack_unpack_bulk(x, n):
lst = unpack(x, n)
assert pack(lst, n) == x
def test_mpz_pack_unpack():
x = mpz(0)
assert all((x == pack(unpack(x,i),i) for i in range(1,100)))
x = mpz(1)
assert all((x == pack(unpack(x,i),i) for i in range(1,100)))
x = mpz(2)
assert all((x == pack(unpack(x,i),i) for i in range(1,100)))
x = mpz(3141592635)
assert all((x == pack(unpack(x,i),i) for i in range(1,100)))
x = mpz(1234567891234567890000000000000000000000000000000000000123)
assert all((x == pack(unpack(x,i),i) for i in range(1,100)))
x = mpz(1) << 500
assert all((x == pack(unpack(x,i),i) for i in range(1,200)))
x -= 1
assert all((x == pack(unpack(x,i),i) for i in range(1,200)))
raises(TypeError, lambda: pack(x))
raises(TypeError, lambda: pack(1, 1))
raises(TypeError, lambda: pack([mpz(1), mpz(-1)], 2))
raises(TypeError, lambda: unpack(x))
raises(TypeError, lambda: unpack([], 1))
raises(ValueError, lambda: unpack(-1, 1))
def test_mpz_cmp():
assert cmp(0, mpz(0)) == 0
assert cmp(1, mpz(0)) == 1
assert cmp(0, mpz(1)) == -1
assert cmp(-1, mpz(0)) == -1
assert cmp(0, mpz(-1)) == 1
assert cmp_abs(mpz(0), 0) == 0
assert cmp_abs(mpz(1), 0) == 1
assert cmp_abs(mpz(0), 1) == -1
assert cmp_abs(mpz(-1), 0) == 1
assert cmp_abs(mpz(0), -1) == -1
a = mpz(-10)
assert cmp_abs(a, 0) == 1
assert a == mpz(-10)
assert cmp_abs(100, a) == 1
assert a == mpz(-10)
assert cmp(mpz(2), z) == 0
assert cmp(z, mpz(3)) == -1
assert cmp(mpz(1), q) == -1
assert cmp(mpz(1), mpz(q)) == 0
def test_mpz_comparisons():
from supportclasses import q
assert mpz(2) == z
assert (z == mpz(3)) is False
assert (mpz(1) == q) is False
assert mpz(1) == mpz(q)
a = mpz(123)
b = mpz(456)
c = mpz(a)
q = mpq(4, 5)
assert a == mpz(123)
assert b == mpz(456)
assert c is a
assert c==a
assert (c>a) is False
assert (cb) is False
assert a q, a >= q, a < q, a <= q) == (False, True, True, True, False, False)
q = mpq(123, 1)
assert (a == q, a != q, a > q, a >= q, a < q, a <= q) == (True, False, False, True, False, True)
gmpy2.context().trap_divzero == False
f = float('inf')
assert (a == f, a != f, a > f, a >= f, a < f, a <= f) == (False, True, False, False, True, True)
assert (f == a, f != a, f > a, f >= a, f < a, f <= a) == (False, True, True, True, False, False)
f = float('-inf')
assert (a == f, a != f, a > f, a >= f, a < f, a <= f) == (False, True, True, True, False, False)
assert (f == a, f != a, f > a, f >= a, f < a, f <= a) == (False, True, False, False, True, True)
f = float('nan')
assert (a == f, a != f, a > f, a >= f, a < f, a <= f) == (False, True, False, False, False, False)
assert (f == a, f != a, f > a, f >= a, f < a, f <= a) == (False, True, False, False, False, False)
r = mpfr('inf')
assert (a == r, a != r, a > r, a >= r, a < r, a <= r) == (False, True, False, False, True, True)
r = mpfr('-inf')
assert (a == r, a != r, a > r, a >= r, a < r, a <= r) == (False, True, True, True, False, False)
r = mpfr('nan')
assert (a == r, a != r, a > r, a >= r, a < r, a <= r) == (False, True, False, False, False, False)
def test_mpz_conversion():
x = mpz(a)
assert isinstance(x, mpz)
assert x == 1
raises(TypeError, lambda: mpz(b))
raises(TypeError, lambda: mpz(c))
raises(TypeError, lambda: mpz(d))
assert float(mpz(1)) == 1.0
raises(OverflowError, lambda: float(mpz(99**199)))
assert mpz(xmpz(1)) == mpz(1)
assert int(mpz(-3)) == -3
assert int(mpz(11)) is int(mpz(11))
def test_mpz_create():
assert mpz() == mpz(0)
assert mpz(0) == mpz(0)
assert mpz(1) == mpz(1)
assert mpz(-1) == mpz(-1)
assert mpz(2**15-2) == mpz(32766)
assert mpz(2**15-1) == mpz(32767)
assert mpz(2**15) == mpz(32768)
assert mpz(2**15+1) == mpz(32769)
assert mpz(2**15+2) == mpz(32770)
assert mpz(2**30-2) == mpz(1073741822)
assert mpz(2**30-1) == mpz(1073741823)
assert mpz(2**30) == mpz(1073741824)
assert mpz(2**30+1) == mpz(1073741825)
assert mpz(2**30+2) == mpz(1073741826)
assert mpz(2**16-2) == mpz(65534)
assert mpz(2**16-1) == mpz(65535)
assert mpz(2**16) == mpz(65536)
assert mpz(2**16+1) == mpz(65537)
assert mpz(2**16+2) == mpz(65538)
assert mpz(1000000000000) == mpz(1000000000000)
assert mpz(-1000000000000) == mpz(-1000000000000)
raises(ValueError, lambda: mpz(''))
raises(ValueError, lambda: mpz('a'))
assert mpz('a',16) == mpz(10)
raises(ValueError, lambda: mpz('z',16))
assert mpz('0b1101') == mpz(13)
assert mpz('0b1101',2) == mpz(13)
assert mpz('1101',2) == mpz(13)
assert mpz('0b0010') == mpz(2)
assert mpz('0b0010',2) == mpz(2)
raises(ValueError, lambda: mpz('0b0b10',2))
raises(ValueError, lambda: mpz('0b0b10'))
raises(ValueError, lambda: mpz('0b0012'))
assert mpz('0o0012') == mpz(10)
assert mpz('0o0012',8) == mpz(10)
assert mpz('12',8) == mpz(10)
assert mpz('0x12') == mpz(18)
assert mpz('0x12',16) == mpz(18)
assert mpz('12',16) == mpz(18)
assert mpz('-1') == mpz(-1)
assert mpz('+1') == mpz(1)
assert mpz(' 0xA', base=0) == mpz(10)
raises(ValueError, lambda: mpz(float('nan')))
raises(OverflowError, lambda: mpz(float('inf')))
raises(OverflowError, lambda: mpz(float('-inf')))
raises(TypeError, lambda: mpz(12, base=16))
assert mpz('12', base=16) == mpz(18)
raises(ValueError, lambda: mpz('\xff'))
raises(ValueError, lambda: mpz('\x0cf'))
raises(ValueError, lambda: mpz('\0xff'))
assert mpz(b'12') == mpz(12)
raises(TypeError, lambda: mpz(None))
raises(TypeError, lambda: mpz(None,base=10))
raises(ValueError, lambda: mpz('99',base=100))
raises(TypeError, lambda: mpz('99',base='a'))
assert mpz('99',base=10) == mpz(99)
assert mpz(xmpz(5)) == mpz(5)
raises(ValueError, lambda: mpz('ы'))
raises(ValueError, lambda: mpz(bytes('ы', encoding='utf-8')))
assert mpz(3.14) == mpz(3)
assert mpz(mpq(17,3)) == mpz(5)
assert mpz(23) == mpz(23)
assert mpz(-23) == mpz(-23)
x = 1000*1000*1000*1000*1000*1000*1000
assert mpz(x) == 1000000000000000000000
assert mpz(0.0) == mpz(0)
assert mpz(-0.0) == mpz(0)
raises(ValueError, lambda: mpz(float("nan")))
raises(OverflowError, lambda: mpz(float("inf")))
raises(OverflowError, lambda: mpz(float("-inf")))
assert mpz("0") == mpz(0)
assert mpz("-0") == mpz(0)
raises(ValueError, lambda: mpz("hi"))
assert mpz("123456", 7) == mpz(22875)
raises(ValueError, lambda: mpz("123456", base=3))
assert mpz() == mpz(0)
assert mpz(Fraction(1,2)) == mpz(0)
assert mpz(Fraction(-3,2)) == mpz(-1)
assert mpz(Fraction(3,2)) == mpz(1)
assert mpz('043') == mpz(43)
assert mpz('43',0) == mpz(43)
assert mpz('0o43') == mpz(35)
assert mpz('0x43') == mpz(67)
raises(ValueError, lambda: mpz('0x43',10))
assert mpz('43') == mpz(43)
assert mpz('1_2') == mpz(12)
assert mpz('_1_2') == mpz(12)
assert mpz('1 2') == mpz(12)
assert mpz(' 1 2') == mpz(12)
@given(integers())
@example(0)
@example(-3)
def test_mpz_conversion_bulk(n):
assert int(mpz(n)) == n
@settings(max_examples=1000)
@given(integers())
@example(0)
@example(1)
@example(-1)
@example(123456789123456789)
def test_mpz_to_from_binary(n):
x = mpz(n)
assert x == from_binary(to_binary(x))
@settings(max_examples=1000)
@given(integers())
@example(0)
@example(1)
@example(-1)
@example(-2)
@example(123)
def test_mpz_hash(n):
assert hash(mpz(n)) == hash(n)
def test_mpz_ceil():
a = mpz(123)
assert math.ceil(a) == a
assert math.ceil(a) is a
def test_mpz_floor():
a = mpz(123)
assert math.floor(a) == a
assert math.floor(a) is a
def test_mpz_trunc():
a = mpz(123)
assert math.trunc(a) == a
assert math.trunc(a) is a
def test_mpz_round():
assert round(mpz(123456), 2) == mpz(123456)
assert round(mpz(123456), -22) == mpz(0)
assert round(mpz(123456), -2) == mpz(123500)
assert round(mpz(123456), -1) == mpz(123460)
assert round(mpz(123455), -1) == mpz(123460)
assert round(mpz(123454), -1) == mpz(123450)
assert round(mpz(123445), -1) == mpz(123440)
assert round(mpz(123445)) == mpz(123445)
raises(TypeError, lambda: round(mpz(123456),'a'))
raises(TypeError, lambda: round(mpz(123456),'a',4))
def test_mpz_bool():
assert bool(mpz(100))
assert not bool(mpz(0))
assert bool(mpz(-100))
def test_mpz_random():
r1 = random_state(42)
r2 = random_state(42)
assert mpz_random(r1, 2**88) == mpz(171378365038768291737094841)
assert mpz_random(r2, 2**88) == mpz(171378365038768291737094841)
assert mpz_random(r1, 2**88) == mpz(62749575961297098445301393)
assert mpz_random(r2, 2**88) == mpz(62749575961297098445301393)
def test_mpz_urandomb():
assert (mpz_urandomb(random_state(42), 64).digits(2) ==
'1100100011011011101100101001100100111110010111011100101010111001')
def test_mpz_rrandomb():
assert (mpz_rrandomb(random_state(42), 64).digits(2) ==
'1111111111111111111111111100000000111111111111111111000000000000')
@mark.skipif(mp_version() < "GMP 6.3.0", reason="requires GMP 6.3.0 or higher")
def test_prev_prime():
# Imported here as symbol won't exist if mp_version() < 6.3.0
from gmpy2 import prev_prime
assert prev_prime(3) == mpz(2)
assert prev_prime(4) == mpz(3)
assert prev_prime(5) == mpz(3)
assert prev_prime(6) == mpz(5)
assert prev_prime(1000004) == mpz(1000003)
assert prev_prime(1000033) == mpz(1000003)
with raises(ValueError):
prev_prime(-100)
with raises(ValueError):
prev_prime(2)
with raises(TypeError):
prev_prime('a')
with raises(TypeError):
prev_prime(4.5)
def test_mpz_format():
z1, z2 = mpz(-3), mpz(5)
assert '{:<5}'.format(z1) == '-3 '
assert '{:>+5}'.format(z2) == ' +5'
raises(ValueError, lambda: '{:5+}'.format(z1))
assert '{:>-4}'.format(z2) == ' 5'
assert '{:<-4}'.format(z1) == '-3 '
raises(ValueError, lambda: '{:>4-}'.format(z1))
raises(ValueError, lambda: '{:<4 }'.format(z1))
assert '{:#x}'.format(z1) == '-0x3'
assert '{:#o}'.format(z1) == '-0o3'
raises(ValueError, lambda: '{:>5#}'.format(z1))
raises(ValueError, lambda: '{:~}'.format(z1))
a = mpz(123)
assert str(a) == '123'
assert repr(a) == 'mpz(123)'
assert hex(a) == '0x7b'
assert oct(a) == '0o173'
assert mpz('1001001011',2) == mpz(587)
assert bin(mpz('1001001011',2)) == '0b1001001011'
assert '1001001011' == mpz('1001001011',2).digits(2)
assert [a.digits(i) for i in range(2,63)] == ['1111011', '11120', '1323',
'443', '323', '234', '173',
'146', '123', '102', 'a3',
'96', '8b', '83', '7b', '74',
'6f', '69', '63', '5i', '5d',
'58', '53', '4n', '4j', '4f',
'4b', '47', '43', '3u', '3r',
'3o', '3l', '3i', '3f', '3C',
'39', '36', '33', '30', '2d',
'2b', '2Z', '2X', '2V', '2T',
'2R', '2P', '2N', '2L', '2J',
'2H', '2F', '2D', '2B', '29',
'27', '25', '23', '21', '1z']
raises(ValueError, lambda: a.digits(63))
assert '{}'.format(a) == '123'
assert '{:d}'.format(a) == '123'
assert '{:b}'.format(a) == '1111011'
assert '{:o}'.format(a) == '173'
assert '{:x}'.format(a) == '7b'
assert '{:#x}'.format(a) == '0x7b'
assert '{:#X}'.format(a) == '0X7B'
assert '{:#o}'.format(a) == '0o173'
assert '{:#15o}'.format(a) == ' 0o173'
assert '{:<#15o}'.format(a) == '0o173 '
assert '{:^#15o}'.format(a) == ' 0o173 '
assert '{:>#15o}'.format(a) == ' 0o173'
assert '{:^ #15o}'.format(a) == ' 0o173 '
assert '{:^#15o}'.format(a) == ' 0o173 '
assert '{:^ #16o}'.format(a) == ' 0o173 '
raises(ValueError, lambda: '{:#^16o}'.format(a))
assert '{:^#16o}'.format(a) == ' 0o173 '
def test_mpz_digits():
z1, z2 = mpz(-3), mpz(15)
assert z1.digits() == '-3'
assert z1.digits(2) == '-11'
assert z1.digits(8) == '-3'
assert z2.digits(16) == 'f'
raises(ValueError, lambda: z1.digits(0))
raises(ValueError, lambda: z1.digits(1))
def test_mpz_abs():
a = mpz(123)
b = abs(a)
assert a is b
assert abs(-a) == a
a = mpz(-123)
b = abs(a)
assert b == mpz(123)
assert a is not b
assert a == mpz(-123)
def test_mpz_add():
a = mpz(123)
b = mpz(456)
c = 12345678901234567890
assert a+1 == mpz(124)
assert a+(-1) == mpz(122)
assert 1+a == mpz(124)
assert (-1)+a == mpz(122)
assert a+b == mpz(579)
assert b+a == mpz(579)
raises(TypeError, lambda: a+'b')
raises(TypeError, lambda: 'b'+a)
assert a+c == 12345678901234568013
assert c+a == 12345678901234568013
assert a+True == mpz(124)
assert a+False == mpz(123)
assert a + float('Inf') == mpfr('inf')
assert float('Inf') + a == mpfr('inf')
assert a + float('-Inf') == mpfr('-inf')
assert float('-Inf') + a == mpfr('-inf')
assert is_nan(a + float('nan'))
assert is_nan(float('nan') + a)
def test_mpz_iadd():
x = mpz(5)
x += mpz(6)
assert x == mpz(11)
x += 7
assert x == mpz(18)
x += -6
assert x == mpz(12)
x += 0
assert x == mpz(12)
x += mpfr(2.5)
assert x == mpfr('14.5')
def test_mpz_sub():
a, b = mpz(123), mpz(456)
c = 12345678901234567890
assert a-1 == mpz(122)
assert a-(-1) == mpz(124)
assert 1-a == mpz(-122)
assert (-1)-a == mpz(-124)
assert a-c == -12345678901234567767
assert c-a == 12345678901234567767
assert a-(-c) == 12345678901234568013
assert (-c)-a == -12345678901234568013
assert a-b == mpz(-333)
assert b-a == mpz(333)
assert a-(-b) == mpz(579)
assert (-b)-a == mpz(-579)
assert a-z == mpz(121)
assert gmpy2.sub(2,1) == mpz(1)
ctx = gmpy2.context()
assert ctx.sub(a,b) == a-b
assert ctx.sub(c,c) == c-c
assert ctx.sub(1, 1) == mpz(0)
assert ctx.sub(a, 1) == mpz(122)
assert ctx.sub(1, a) == mpz(-122)
assert ctx.sub(a, mpq(0)) == mpq(123,1)
assert ctx.sub(a, mpfr(0)) == mpfr('123.0')
assert ctx.sub(a, mpc(0)) == mpc('123.0+0.0j')
raises(TypeError, lambda: ctx.sub(1))
raises(TypeError, lambda: ctx.sub(1,2,3))
raises(TypeError, lambda: a-'b')
raises(TypeError, lambda: 'b'-a)
assert a-1 == mpz(122)
assert a-(-1) == mpz(124)
assert 1-a == mpz(-122)
assert (-1)-a == mpz(-124)
assert a-b == mpz(-333)
assert b-a == mpz(333)
raises(TypeError, lambda: a-'b')
raises(TypeError, lambda: 'b'-a)
assert a-c == -12345678901234567767
assert c-a == 12345678901234567767
assert a - float('Inf') == mpfr('-inf')
assert float('Inf') - a == mpfr('inf')
assert a - float('-Inf') == mpfr('inf')
assert float('-Inf') - a == mpfr('-inf')
assert is_nan(a - float('nan'))
assert is_nan(float('nan') - a)
def test_mpz_isub():
x = mpz(7)
x -= mpz(1)
assert x == mpz(6)
x -= 1
assert x == mpz(5)
x -= xmpz(7)
assert x == mpz(-2)
x -= -5
assert x == mpz(3)
x -= -mpfr(5)
assert x == mpfr('8.0')
def test_mpz_mul():
a = mpz(123)
b = mpz(456)
c = 12345678901234567890
assert mpz(2)*z == mpz(4)
assert gmpy2.mul(2,1) == mpz(2)
ctx = gmpy2.context()
assert ctx.mul(a,b) == a*b
assert ctx.mul(c,c) == c*c
assert ctx.mul(a, mpq(1)) == mpq(123,1)
assert ctx.mul(a, mpfr(1)) == mpfr('123.0')
assert ctx.mul(a, mpc(1)) == mpc('123.0+0.0j')
raises(TypeError, lambda: ctx.mul(1))
raises(TypeError, lambda: ctx.mul(1,2,3))
assert a*b == mpz(56088)
assert b*a == mpz(56088)
assert a*0 == mpz(0)
assert 0*a == mpz(0)
assert a*123 == mpz(15129)
assert 123*a == mpz(15129)
assert a*c == 1518518504851851850470
assert c*a == 1518518504851851850470
a = mpz(3)
assert a*'b' == 'bbb'
assert 'b'*a == 'bbb'
assert a*False == mpz(0)
assert a * float('Inf') == mpfr('inf')
assert float('Inf') * a == mpfr('inf')
assert a * float('-Inf') == mpfr('-inf')
assert float('-Inf') * a == mpfr('-inf')
assert -a * float('Inf') == mpfr('-inf')
assert float('Inf') * -a == mpfr('-inf')
assert -a * float('-Inf') == mpfr('inf')
assert float('-Inf') * -a == mpfr('inf')
assert is_nan(a * float('nan'))
assert is_nan(float('nan') * a)
assert is_nan(mpz(0) * float('Inf'))
assert is_nan(mpz(0) * float('-Inf'))
assert is_nan(float('Inf') * mpz(0))
assert is_nan(float('-Inf') * mpz(0))
def test_mul_imul():
x = mpz(2)
x *= mpz(2)
assert x == mpz(4)
x *= 2
assert x == mpz(8)
x *= xmpz(3)
assert x == mpz(24)
x *= -1
assert x == mpz(-24)
x *= mpfr(-0.5)
assert x == mpfr('12.0')
def test_mpz_divmod():
a = mpz(123)
b = mpz(456)
c = 12345678901234567890
ctx = gmpy2.get_context()
raises(TypeError, lambda: divmod(mpz(123),'a'))
ctx = gmpy2.context()
raises(TypeError, lambda: ctx.divmod('a',456))
raises(TypeError, lambda: ctx.divmod(1,2,3))
raises(ZeroDivisionError, lambda: ctx.divmod(456, 0))
raises(TypeError, lambda: ctx.divmod(a,mpc(456)))
raises(TypeError, lambda: divmod(mpz(1), mpc(1,2)))
assert ctx.divmod(a,b) == (mpz(0), mpz(123))
assert ctx.divmod(123,456) == (mpz(0), mpz(123))
assert divmod(mpz(3), z) == (mpz(1), mpz(1))
assert divmod(z, mpz(3)) == (mpz(0), mpz(2))
assert divmod(a,b) == (mpz(0), mpz(123))
assert divmod(b,a) == (mpz(3), mpz(87))
raises(ZeroDivisionError, lambda: divmod(a,0))
raises(ZeroDivisionError, lambda: divmod(a, mpz(0)))
raises(ZeroDivisionError, lambda: divmod(123, mpz(0)))
assert divmod(b,123) == (mpz(3), mpz(87))
assert divmod(a,c) == (mpz(0), mpz(123))
assert divmod(a,int(c)) == (mpz(0), mpz(123))
assert divmod(a*(c-1),c) == (122, 12345678901234567767)
assert divmod(a*(c-1),int(c)) == (122, 12345678901234567767)
assert divmod(a*(c-1),-c) == (mpz(-123), mpz(-123))
assert divmod(a*(c-1),-int(c)) == (mpz(-123), mpz(-123))
assert divmod(int(a*(c-1)),-int(c)) == (-123, -123)
assert divmod(a, mpfr('Inf')) == (mpfr('0.0'), mpfr('123.0'))
assert divmod(a, mpfr('-Inf')) == (mpfr('-1.0'), mpfr('-inf'))
assert divmod(-a, mpfr('Inf')) == (mpfr('-1.0'), mpfr('inf'))
assert divmod(-a, mpfr('-Inf')) == (mpfr('0.0'), mpfr('-123.0'))
assert all(is_nan(_) for _ in divmod(a, mpfr('nan')))
assert all(is_nan(_) for _ in divmod(-a, mpfr('nan')))
assert divmod(mpz(0), mpfr('Inf')) == (mpfr('0.0'), mpfr('0.0'))
assert divmod(mpz(0), mpfr('-Inf')) == (mpfr('-0.0'), mpfr('-0.0'))
assert divmod(mpz(0), mpfr('nan'))
assert all(is_nan(_) for _ in divmod(mpfr('Inf'), a))
assert all(is_nan(_) for _ in divmod(mpfr('-Inf'), a))
assert all(is_nan(_) for _ in divmod(mpfr('Inf'), -a))
assert all(is_nan(_) for _ in divmod(mpfr('-Inf'), -a))
assert all(is_nan(_) for _ in divmod(mpfr('nan'), a))
assert all(is_nan(_) for _ in divmod(mpfr('nan'), -a))
assert all(is_nan(_) for _ in divmod(mpfr('Inf'), mpz(0)))
assert all(is_nan(_) for _ in divmod(mpfr('-Inf'), mpz(0)))
assert all(is_nan(_) for _ in divmod(mpfr('nan'), mpz(0)))
assert divmod(a, mpfr('Inf')) == (mpfr('0.0'), mpfr('123.0'))
assert divmod(a, mpfr('-Inf')) == (mpfr('-1.0'), mpfr('-inf'))
assert divmod(-a, mpfr('Inf')) == (mpfr('-1.0'), mpfr('inf'))
assert divmod(-a, mpfr('-Inf')) == (mpfr('0.0'), mpfr('-123.0'))
assert all(is_nan(_) for _ in divmod(a, mpfr('nan')))
assert all(is_nan(_) for _ in divmod(-a, mpfr('nan')))
assert divmod(mpz(0), mpfr('Inf')) == (mpfr('0.0'), mpfr('0.0'))
assert divmod(mpz(0), mpfr('-Inf')) == (mpfr('-0.0'), mpfr('-0.0'))
assert divmod(mpz(0), mpfr('nan'))
assert all(is_nan(_) for _ in divmod(mpfr('Inf'), a))
assert all(is_nan(_) for _ in divmod(mpfr('-Inf'), a))
assert all(is_nan(_) for _ in divmod(mpfr('Inf'), -a))
assert all(is_nan(_) for _ in divmod(mpfr('-Inf'), -a))
assert all(is_nan(_) for _ in divmod(mpfr('nan'), a))
assert all(is_nan(_) for _ in divmod(mpfr('nan'), -a))
assert all(is_nan(_) for _ in divmod(mpfr('Inf'), mpz(0)))
assert all(is_nan(_) for _ in divmod(mpfr('-Inf'), mpz(0)))
assert all(is_nan(_) for _ in divmod(mpfr('nan'), mpz(0)))
def test_mpz_floordiv():
ctx = gmpy2.get_context()
a, b = mpz(45), mpz(6)
r, r2 = mpfr(45), mpfr(3.1)
q, q2 = mpq(118,18), mpq(3,2)
c, c2 = mpc(51, 65), mpc(4, 6)
assert ctx.floor_div(a, 6) == mpz(7)
assert ctx.floor_div(a, b) == mpz(7)
raises(ZeroDivisionError, lambda: ctx.floor_div(a, 0))
raises(ZeroDivisionError, lambda: ctx.floor_div(a, mpz(0)))
assert ctx.floor_div(45, b) == mpz(7)
raises(ZeroDivisionError, lambda: ctx.floor_div(45, 0))
raises(ZeroDivisionError, lambda: ctx.floor_div(45, mpz(0)))
raises(TypeError, lambda: ctx.floor_div())
raises(TypeError, lambda: gmpy2.floor_div(4,5,6))
assert a // b == mpz(7)
raises(ZeroDivisionError, lambda: a // 0)
raises(ZeroDivisionError, lambda: a // mpz(0))
assert ctx.floor_div(a, q2) == mpz(30)
assert ctx.floor_div(a, r2) == mpfr('14.0')
raises(TypeError, lambda: ctx.floor_div(a, c))
assert a // b == mpz(7)
assert a // q == mpz(6)
assert a // r2 == mpfr('14.0')
raises(TypeError, lambda: a // c2)
raises(TypeError, lambda: a // 'not')
a = mpz(123)
b = mpz(456)
c = 12345678901234567890
assert a//b == mpz(0)
assert b//a == mpz(3)
assert (a*b)//b == mpz(123)
assert (a*b)//a == mpz(456)
raises(ZeroDivisionError, lambda: a//0)
assert c//a == 100371373180768844
assert a**10//c == mpz(64)
assert a // z == mpz(61)
assert a//True == mpz(123)
def test_mpz_ifloordiv():
x = mpz(49)
x //= mpz(3)
assert x == mpz(16)
x //= xmpz(3)
assert x == mpz(5)
x //= 2
assert x == mpz(2)
with raises(ZeroDivisionError):
x //= mpz(0)
with raises(ZeroDivisionError):
x //= 0
assert x == mpz(2)
x //= mpfr(-0.5)
assert x == mpfr('-4.0')
x = mpz(11)
x //= -5
assert x == mpz(-3)
def test_mpz_mod():
a = mpz(123)
b = mpz(456)
c = 12345678901234567890
ctx = gmpy2.get_context()
assert a % b == mpz(123)
assert b % a == mpz(87)
assert gmpy2.mod(b, a) == mpz(87)
assert ctx.mod(b, a) == mpz(87)
assert a % z == mpz(1)
raises(ZeroDivisionError, lambda: a % mpz(0))
raises(ZeroDivisionError, lambda: a % 0)
raises(ZeroDivisionError, lambda: 14 % mpz(0))
raises(ZeroDivisionError, lambda: gmpy2.mod(14, mpz(0)))
raises(ZeroDivisionError, lambda: gmpy2.mod(124, 0))
raises(ZeroDivisionError, lambda: gmpy2.mod(b, mpz(0)))
raises(ZeroDivisionError, lambda: ctx.mod(b, mpz(0)))
raises(TypeError, lambda: gmpy2.mod(124, 'str'))
raises(TypeError, lambda: a % 'str')
assert gmpy2.mod(124, mpz(5)) == mpz(4)
assert z % mpq(1,2) == mpq(0,1)
assert a % mpq(2,3) == mpq(1,3)
def test_mpz_imod():
x = mpz(45)
x %= mpz(18)
assert x == mpz(9)
x %= xmpz(2)
assert x == mpz(1)
x = mpz(40)
x %= 21
assert x == mpz(19)
with raises(ZeroDivisionError):
x %= 0
assert x == mpz(19)
with raises(ZeroDivisionError):
x %= mpz(0)
x %= -9
assert x == mpz(-8)
x %= mpfr(10)
assert x == mpfr('2.0')
def test_mpz_truediv():
a = mpz(123)
b = mpz(456)
c = 12345678901234567890
ctx = gmpy2.get_context()
assert a/b == mpfr('0.26973684210526316')
assert gmpy2.div(a, b) == mpfr('0.26973684210526316')
assert ctx.div(a, b) == mpfr('0.26973684210526316')
assert b/a == mpfr('3.7073170731707319')
raises(ZeroDivisionError, lambda: a/0)
assert a/0.0 == mpfr('inf')
assert a / z == mpfr('61.5')
raises(TypeError, lambda: ctx.div(a, b, 5))
raises(TypeError, lambda: ctx.div(a, 'str'))
raises(TypeError, lambda: a / 'str')
with gmpy2.context(rational_division=True):
assert mpz(1)/mpz(2) == mpq(1, 2)
assert a / float('Inf') == mpfr('0.0')
assert -a / float('Inf') == mpfr('-0.0')
assert float('Inf') / a == mpfr('inf')
assert float('Inf') / -a == mpfr('-inf')
assert a / float('-Inf') == mpfr('-0.0')
assert -a / float('-Inf') == mpfr('0.0')
assert float('-Inf') / a == mpfr('-inf')
assert float('-Inf') / -a == mpfr('inf')
assert is_nan(a / float('nan'))
assert is_nan(float('nan') / a)
assert is_nan(float('nan') / mpz(0))
assert is_nan(float('nan') / mpz(0))
assert a / mpfr('Inf') == mpfr('0.0')
assert -a / mpfr('Inf') == mpfr('-0.0')
assert mpfr('Inf') / a == mpfr('inf')
assert mpfr('Inf') / -a == mpfr('-inf')
assert a / mpfr('-Inf') == mpfr('-0.0')
assert -a / mpfr('-Inf') == mpfr('0.0')
assert mpfr('-Inf') / a == mpfr('-inf')
assert mpfr('-Inf') / -a == mpfr('inf')
assert is_nan(a / mpfr('nan'))
assert is_nan(mpfr('nan') / a)
assert is_nan(mpfr('nan') / mpz(0))
assert is_nan(mpfr('nan') / mpz(0))
def test_mpz_pow():
z1, z2 = mpz(5), mpz(2)
ctx = gmpy2.get_context()
assert z1 ** z2 == mpz(25)
assert ctx.pow(z1, z2) == mpz(25)
assert z1 ** -z2 == mpfr('0.040000000000000001')
assert z1 ** 0 == mpz(1)
assert mpz(0) ** 32 == mpz(0)
assert mpz(-1) ** 32 == mpz(1)
assert mpz(1) ** mpz(324) == mpz(1)
assert mpz(0) ** 0 == mpz(1)
assert mpz(-1) ** 3 == mpz(-1)
assert z1 ** 2 == pow(z1, 2)
assert pow(z1, 2, 19) == mpz(6)
assert pow(z1, -2, 19) == mpz(16)
raises(ValueError, lambda: pow(mpz(0), -2, 19))
assert pow(z1, 2, -19) == mpz(-13)
raises(ValueError, lambda: pow(5, 2, 0))
raises(TypeError, lambda: ctx.pow(z1, 'invalid'))
a = mpz(123)
b = mpz(456)
assert pow(a,10) == 792594609605189126649
assert pow(a,7,b) == mpz(99)
def test_mpz_ipow():
x = mpz(5)
x **= mpz(2)
assert x == mpz(25)
x **= xmpz(2)
assert x == mpz(625)
x **= -2
assert x == mpfr('2.5600000000000001e-06')
x = mpz(625)
x **= 2
assert x == mpz(390625)
x **= mpfr(2)
assert x == mpfr('152587890625.0')
x = mpz(390625)
x **= mpfr(-2)
assert x == mpfr('6.5535999999999999e-12')
def test_lucasu():
assert gmpy2.lucasu(2,4,0) == mpz(0)
assert gmpy2.lucasu(2,4,1) == mpz(1)
raises(ValueError, lambda: gmpy2.lucasu(2,1,1))
assert gmpy2.lucasu(2,4,8) == mpz(128)
raises(TypeError, lambda: gmpy2.lucasu('a',4,8))
raises(TypeError, lambda: gmpy2.lucasu(2,'b',8))
raises(TypeError, lambda: gmpy2.lucasu(2,4,None))
raises(ValueError, lambda: gmpy2.lucasu(mpz(2), mpz(1), mpz(7)))
assert gmpy2.lucasu_mod(3,2,0,7) == mpz(0)
assert gmpy2.lucasu_mod(3,2,5,7) == mpz(3)
assert gmpy2.lucasu_mod(3,2,555,777777777) == mpz(387104641)
raises(ValueError, lambda: gmpy2.lucasu_mod(2,1,555,777777777))
raises(ValueError, lambda: gmpy2.lucasv(2,1,4))
raises(TypeError, lambda: gmpy2.lucasv('a',1,2))
raises(TypeError, lambda: gmpy2.lucasv(4,'b',2))
raises(TypeError, lambda: gmpy2.lucasv(4,3,'c'))
assert gmpy2.lucasv(4,3,0) == mpz(2)
assert gmpy2.lucasv(4,3,7) == mpz(2188)
assert gmpy2.lucasv(4,3,8) == mpz(6562)
assert gmpy2.lucasv_mod(4,3,0,2) == mpz(0)
assert gmpy2.lucasv_mod(4,3,0,3) == mpz(2)
assert gmpy2.lucasv_mod(4,3,55,123456) == mpz(35788)
assert gmpy2.lucasv_mod(4,3,56,123456) == mpz(107362)
assert gmpy2.lucasv_mod(4,3,57,123456) == mpz(75172)
def test_mpz_attributes():
a = mpz(123)
assert a.numerator == mpz(123)
assert a.denominator == mpz(1)
assert a.real == mpz(123)
assert a.imag == mpz(0)
def test_mpz_conjugate():
a = mpz(123)
assert a.conjugate() == a
def test_mpz_invert():
a = mpz(123)
assert ~a == mpz(-124)
def test_mpz_and():
a = mpz(123)
b = mpz(456)
assert a&b == mpz(72)
assert a&int(b) == mpz(72)
assert int(a)&b == mpz(72)
raises(TypeError, lambda: a&mpq(1))
def test_mpz_and_operator():
assert (mpz(0) and mpz(7)) == mpz(0)
assert (mpz(7) and mpz(0)) == mpz(0)
assert (mpz(7) and mpz(5)) == mpz(5)
assert (mpz(0) and 5) == mpz(0)
assert (mpz(7) and 5.2) == 5.2
assert (mpz(7) and None) is None
def test_mpz_iand():
x = mpz(7)
x &= mpz(5)
assert x == mpz(5)
x &= xmpz(4)
assert x == mpz(4)
x &= 9
assert x == mpz(0)
x = mpz(4)
x &= 12
assert x == mpz(4)
with raises(TypeError):
x &= mpfr(4)
def test_mpz_or():
a = mpz(123)
b = mpz(456)
assert a|b == mpz(507)
assert a|int(b) == mpz(507)
assert int(a)|b == mpz(507)
raises(TypeError, lambda: a|mpq(1))
def test_mpz_ior():
x = mpz(0)
x |= mpz(1)
assert x == mpz(1)
x |= mpz(0)
assert x == mpz(1)
x = mpz(0)
x |= mpz(0)
assert x == mpz(0)
x |= 5
assert x == mpz(5)
with raises(TypeError):
x |= mpfr(3)
def test_mpz_xor():
a = mpz(123)
b = mpz(456)
assert a^b == mpz(435)
assert a^int(b) == mpz(435)
assert int(a)^b == mpz(435)
raises(TypeError, lambda: a^mpq(1))
def test_mpz_ixor():
x = mpz(1)
x ^= mpz(0)
assert x == mpz(1)
x ^= xmpz(1)
assert x == mpz(0)
x ^= 1
assert x == mpz(1)
with raises(TypeError):
x ^= mpfr(0)
def test_mpz_lshift():
a = mpz(123)
assert a<<1 == mpz(246)
assert int(a)<>1 == mpz(61)
assert int(a)>>mpz(1) == mpz(61)
raises(OverflowError, lambda: a>>-2)
assert a>>0 == mpz(123)
raises(TypeError, lambda: "a" >> a)
def test_mpz_ilshift_irshift():
x = mpz(63)
x >>= mpz(63)
assert x == mpz(0)
x = mpz(63)
x >>= mpz(1)
assert x == mpz(31)
x >>= xmpz(2)
assert x == mpz(7)
x >>= 1
assert x == mpz(3)
x <<= mpz(2)
assert x == mpz(12)
x <<= mpz(1)
assert x == mpz(24)
x <<= 0
assert x == mpz(24)
with raises(TypeError):
x >>= mpfr(2)
with raises(TypeError):
x <<= mpfr(2)
with raises(OverflowError):
x >>= -1
with raises(OverflowError):
x <<= -5
def test_mpz_index():
a = mpz(123)
b = mpz(456)
assert range(333)[a] == 123
raises(IndexError, lambda: range(333)[b])
def test_mpz_seq():
a = mpz(10)
assert a[1] == 1
assert a[-1] == 1
assert a[-2] == 0
assert a[0:2] == mpz(2)
assert a[0:3] == mpz(2)
assert a[0:3:-1] == mpz(0)
raises(IndexError, lambda: a[111111111111111111111])
raises(TypeError, lambda: a["spam"])
def test_mpz_len():
assert len(mpz(0)) == 1
assert len(mpz(1)) == 1
assert len(mpz(17)) == 5
def test_mpz_num_digits():
assert mpz(123456).num_digits() == 6
assert mpz(123456).num_digits(2) == 17
raises(ValueError, lambda: mpz(123456).num_digits(-1))
raises(OverflowError, lambda: mpz(123456).num_digits(9999999999999999999999999999999999))
raises(ValueError, lambda: mpz(123456).num_digits(100))
raises(TypeError, lambda: gmpy2.num_digits(123456,-1,7))
raises(ValueError, lambda: gmpy2.num_digits(123456,-1))
raises(TypeError, lambda: gmpy2.num_digits('123456'))
raises(ValueError, lambda: gmpy2.num_digits(123456,100))
raises(TypeError, lambda: gmpy2.num_digits(123456,'a'))
assert gmpy2.num_digits(123456) == 6
assert gmpy2.num_digits(123456,2) == 17
def test_mpz_is_square():
raises(TypeError, lambda: gmpy2.is_square('a'))
assert gmpy2.is_square(mpz(9))
assert not gmpy2.is_square(10)
assert mpz(16).is_square()
assert not mpz(17).is_square()
def test_mpz_is_divisible():
raises(TypeError, lambda: gmpy2.is_divisible())
raises(TypeError, lambda: gmpy2.is_divisible('a',2))
raises(TypeError, lambda: gmpy2.is_divisible(2,'a'))
assert gmpy2.is_divisible(12,2)
assert not gmpy2.is_divisible(12,7)
assert mpz(12).is_divisible(2)
assert not mpz(12).is_divisible(7)
assert gmpy2.is_divisible(mpz(123456789123456789123456789),
123456789123456789123456789)
assert not gmpy2.is_divisible(mpz(1234567891234567891234567897),
123456789123456789123456789)
raises(TypeError, lambda: mpz(12).is_divisible('a'))
assert mpz(123456789123456789123456789).is_divisible(123456789123456789123456789)
assert not mpz(1234567891234567891234567897).is_divisible(123456789123456789123456789)
def test_mpz_is_congruent():
raises(TypeError, lambda: gmpy2.is_congruent(1))
raises(TypeError, lambda: gmpy2.is_congruent(1,'a',3))
assert gmpy2.is_congruent(7*3+2, 7*11+2, 7)
assert not gmpy2.is_congruent(7*3+2, 7*11+5, 7)
raises(TypeError, lambda: mpz(7*3+2).is_congruent(1))
raises(TypeError, lambda: mpz(7*3+2).is_congruent('a',7))
assert mpz(7*3+2).is_congruent(7*11+2,7)
assert not mpz(7*3+2).is_congruent(7*11+5,7)
def test_mpz_is_power():
a = mpz(123)
raises(TypeError, lambda: gmpy2.is_power())
raises(TypeError, lambda: gmpy2.is_power('a'))
assert not a.is_power()
assert mpz(123**11).is_power()
assert not gmpy2.is_power(a)
assert gmpy2.is_power(99*99*99)
assert not gmpy2.is_power(99*98)
def test_mpz_is_prime():
raises(OverflowError, lambda: gmpy2.is_prime(3,-3))
raises(TypeError, lambda: gmpy2.is_prime())
raises(TypeError, lambda: gmpy2.is_prime(1,2,3))
raises(TypeError, lambda: gmpy2.is_prime('a'))
assert not gmpy2.is_prime(12345)
assert gmpy2.is_prime(80**81 + 81**80)
assert gmpy2.is_prime(80**81 + 81**80, 10000)
raises(TypeError, lambda: mpz(129).is_prime(1,2))
raises(OverflowError, lambda: mpz(129).is_prime(-7))
assert not mpz(129).is_prime(10000)
assert mpz(80**81 + 81**80).is_prime()
assert not mpz(1234567890).is_prime()
assert not mpz(-3).is_prime()
assert not gmpy2.is_prime(-3)
def test_mpz_is_probab_prime():
raises(OverflowError, lambda: gmpy2.is_probab_prime(3,-3))
raises(TypeError, lambda: gmpy2.is_probab_prime())
raises(TypeError, lambda: gmpy2.is_probab_prime(1,2,3))
raises(TypeError, lambda: gmpy2.is_probab_prime('a'))
assert gmpy2.is_probab_prime(71) == 2
assert gmpy2.is_probab_prime(12345) == 0
assert gmpy2.is_probab_prime(80**81 + 81**80) == 1
assert gmpy2.is_probab_prime(80**81 + 81**80, 10000) == 1
raises(TypeError, lambda: mpz(129).is_probab_prime(1,2))
raises(OverflowError, lambda: mpz(129).is_probab_prime(-7))
assert mpz(71).is_probab_prime(71) == 2
assert mpz(129).is_probab_prime(10000) == 0
assert mpz(80**81 + 81**80).is_probab_prime() == 1
assert mpz(1234567890).is_probab_prime() == 0
assert mpz(-3).is_probab_prime() == 0
assert gmpy2.is_probab_prime(-3) == 0
def test_mpz_is_even():
a = mpz(123)
b = mpz(456)
raises(TypeError, lambda: gmpy2.is_even('a'))
assert not gmpy2.is_even(a)
assert gmpy2.is_even(b)
assert not a.is_even()
assert b.is_even()
assert not gmpy2.is_even(11)
assert gmpy2.is_even(14)
def test_mpz_is_odd():
a = mpz(123)
b = mpz(456)
raises(TypeError, lambda: gmpy2.is_odd('a'))
assert gmpy2.is_odd(a)
assert not gmpy2.is_odd(b)
assert a.is_odd()
assert not b.is_odd()
assert gmpy2.is_odd(11)
assert not gmpy2.is_odd(14)
def test_mpz_bit_length():
assert mpz(0).bit_length() == 0
assert mpz(1).bit_length() == 1
assert mpz(5).bit_length() == 3
assert mpz(8).bit_length() == 4
assert gmpy2.bit_length(mpz(10**30)) == 100
assert gmpy2.bit_length(56) == 6
raises(TypeError, lambda: gmpy2.bit_length(mpfr(4.0)))
def test_mpz_bit_mask():
assert gmpy2.bit_mask(mpz(0)) == mpz(0)
assert gmpy2.bit_mask(mpz(4)) == mpz(15)
assert gmpy2.bit_mask(mpz(3)) == mpz(7)
assert gmpy2.bit_mask(mpz(16)) == mpz(65535)
assert gmpy2.bit_mask(8) == mpz(255)
raises(OverflowError, lambda: gmpy2.bit_mask(-1))
def test_mpz_bit_scan0():
assert mpz(6).bit_scan0() == 0
assert mpz(7).bit_scan0() == 3
assert mpz(8).bit_scan0(2) == 2
assert mpz(7).bit_scan0(2) == 3
raises(OverflowError, lambda: mpz(7).bit_scan0(-2))
assert gmpy2.bit_scan0(mpz(7), 2) == 3
assert gmpy2.bit_scan0(mpz(8), 2) == 2
assert gmpy2.bit_scan0(8) == 0
raises(TypeError, lambda: gmpy2.bit_scan0())
raises(TypeError, lambda: gmpy2.bit_scan0(mpz(7), 2.5))
raises(TypeError, lambda: gmpy2.bit_scan0(mpz(7), 2, 5))
raises(TypeError, lambda: gmpy2.bit_scan0(7.5, 0))
raises(OverflowError, lambda: gmpy2.bit_scan0(8, -2))
assert gmpy2.bit_scan0(mpz(-1), 1) is None
assert mpz(-1).bit_scan0(1) is None
def test_mpz_bit_scan1():
assert mpz(7).bit_scan1() == 0
assert mpz(8).bit_scan1() == 3
assert mpz(7).bit_scan1(2) == 2
raises(OverflowError, lambda: mpz(7).bit_scan1(-2))
assert gmpy2.bit_scan1(7) == 0
assert gmpy2.bit_scan1(8) == 3
assert gmpy2.bit_scan1(7, 2) == 2
raises(TypeError, lambda: gmpy2.bit_scan1(mpz(7), 2, 5))
raises(TypeError, lambda: gmpy2.bit_scan1())
raises(TypeError, lambda: gmpy2.bit_scan1(mpz(6), 2.5))
raises(TypeError, lambda: gmpy2.bit_scan1(7.5, 0))
raises(OverflowError, lambda: gmpy2.bit_scan1(8, -1))
assert gmpy2.bit_scan1(mpz(1), 1) is None
assert mpz(1).bit_scan1(1) is None
def test_mpz_bit_test():
assert mpz(7).bit_test(2)
assert not mpz(8).bit_test(2)
assert not mpz(-8).bit_test(2)
raises(OverflowError, lambda: mpz(8).bit_test(-2))
assert gmpy2.bit_test(mpz(7), 2)
assert not gmpy2.bit_test(mpz(8), 2)
raises(TypeError, lambda: gmpy2.bit_test())
raises(TypeError, lambda: gmpy2.bit_test(mpz(7), 2.5))
raises(TypeError, lambda: gmpy2.bit_test(7.5, 2))
raises(OverflowError, lambda: gmpy2.bit_test(8, -2))
def test_mpz_bit_clear():
assert mpz(7).bit_clear(0) == mpz(6)
assert mpz(7).bit_clear(2) == mpz(3)
assert mpz(8).bit_clear(2) == mpz(8)
raises(OverflowError, lambda: mpz(8).bit_clear(-1))
assert gmpy2.bit_clear(4, 2) == mpz(0)
raises(TypeError, lambda: gmpy2.bit_clear())
raises(TypeError, lambda: gmpy2.bit_clear(7.2, 2))
raises(TypeError, lambda: gmpy2.bit_clear(mpz(4), 2.5))
raises(OverflowError, lambda: gmpy2.bit_clear(4, -2))
def test_mpz_bit_set():
assert mpz(4).bit_set(0) == mpz(5)
assert mpz(7).bit_set(3) == mpz(15)
assert mpz(0).bit_set(2) == mpz(4)
raises(OverflowError, lambda: mpz(0).bit_set(-2))
assert gmpy2.bit_set(8, 1) == mpz(10)
raises(TypeError, lambda: gmpy2.bit_set(0))
raises(TypeError, lambda: gmpy2.bit_set())
raises(TypeError, lambda: gmpy2.bit_set(8.5, 1))
raises(TypeError, lambda: gmpy2.bit_set(8, 1.5))
raises(OverflowError, lambda: gmpy2.bit_set(8, -1))
def test_mpz_bit_flip():
assert mpz(4).bit_flip(2) == mpz(0)
assert mpz(4).bit_flip(1) == mpz(6)
assert mpz(0).bit_flip(3) == mpz(8)
raises(OverflowError, lambda: mpz(5).bit_flip(-3))
assert gmpy2.bit_flip(mpz(7), mpz(1)) == mpz(5)
assert gmpy2.bit_flip(mpz(7), 2) == mpz(3)
raises(TypeError, lambda: gmpy2.bit_flip())
raises(TypeError, lambda: gmpy2.bit_flip(4.5, 2))
raises(TypeError, lambda: gmpy2.bit_flip(4, 2.5))
raises(OverflowError, lambda: gmpy2.bit_flip(mpz(7), -2))
def test_mpz_bit_count():
a = mpz(10009)
assert a.bit_count() == 7
assert gmpy2.popcount(a) == 7
assert gmpy2.bit_count(a) == 7
a = -a
assert a == mpz(-10009)
assert a.bit_count() == 7
assert gmpy2.bit_count(a) == 7
assert gmpy2.popcount(a) == -1
raises(TypeError, lambda: gmpy2.bit_count('spam'))
def test_mpz_popcount():
assert gmpy2.popcount(-65) == -1
assert gmpy2.popcount(7) == 3
assert gmpy2.popcount(8) == 1
assert gmpy2.popcount(15) == 4
assert gmpy2.popcount(mpz(0)) == 0
raises(TypeError, lambda: gmpy2.popcount(4.5))
def test_mpz_hamdist():
assert gmpy2.hamdist(mpz(5), mpz(7)) == 1
assert gmpy2.hamdist(mpz(0), mpz(7)) == 3
assert gmpy2.hamdist(mpz(0), 7) == 3
raises(TypeError, lambda: gmpy2.hamdist(mpq(14,2), 5))
raises(TypeError, lambda: gmpy2.hamdist(5,6,5))
def test_issue_339():
samples = map(mpz, [13157547707030902665, 1070317427780135395,
18019609787501108695, 3978762157568107671,
14444587867185512177])
assert all((2*q).is_divisible(q) for q in samples)
def test_issue_312():
assert not is_prime(-7)
assert not is_prime(mpz(-7))
assert not is_prime(1 - 2**4423)
assert all(not is_prime(-a) for a in range(8))
assert next_prime(-8) == 2
././@PaxHeader 0000000 0000000 0000000 00000000026 00000000000 010213 x ustar 00 22 mtime=1710307256.0
gmpy2-2.2.1/test/test_xmpz.py 0000644 0001750 0001750 00000015347 14574233670 014635 0 ustar 00case case from ctypes import memmove
import pytest
from hypothesis import example, given, settings
from hypothesis.strategies import integers
import gmpy2
from gmpy2 import from_binary, mpfr, mpq, mpz, to_binary, xmpz
def test_xmpz_digits():
x = xmpz(6)
assert x.digits() == '6'
assert x.digits(2) == '0b110'
assert x.digits(8) == '0o6'
assert x.digits(16) == '0x6'
assert xmpz(30).digits(16) == '0x1e'
pytest.raises(ValueError, lambda: x.digits(0))
pytest.raises(ValueError, lambda: x.digits(63))
def test_xmpz_limbs():
x, y = xmpz(123456789), xmpz(0);
x_limbs, num_limbs = x.limbs_read(), x.num_limbs()
assert x_limbs != 0
assert num_limbs > 0
y_limbs = y.limbs_write(num_limbs)
assert y_limbs != 0
assert memmove(y_limbs, x_limbs, num_limbs * xmpz.limb_size) > 0
y.limbs_finish(num_limbs)
assert int(y) == 123456789
x, y = xmpz(987654321), xmpz(0)
x_limbs, num_limbs = x.limbs_read(), x.num_limbs()
assert x_limbs != 0
assert num_limbs > 0
y_limbs = y.limbs_modify(num_limbs);
assert y_limbs != 0
assert memmove(y_limbs, x_limbs, num_limbs * xmpz.limb_size) > 0
y.limbs_finish(num_limbs)
assert int(y) == 987654321
def test_xmpz_attributes():
x = xmpz(10)
assert x.numerator == xmpz(10)
assert x.denominator == xmpz(1)
assert x.real == xmpz(10)
def test_xmpz_misc():
z = xmpz(5)
assert gmpy2.xbit_mask(7) == xmpz(127)
assert gmpy2.xbit_mask(z) == xmpz(31)
pytest.raises(TypeError, lambda: gmpy2.xbit_mask(4.5))
assert not xmpz(0)
assert z
-z
assert z == xmpz(-5)
-z
assert z == xmpz(5)
+z
assert z == xmpz(5)
z2 = z.copy()
assert z2 == z
assert z2 is not z
assert z.copy().make_mpz() == mpz(5)
assert xmpz(-100).make_mpz() == mpz(-100)
assert len(z) == 3
assert len(xmpz(3000)) == 12
assert str(xmpz(42)) == '42'
assert repr(xmpz(42)) == 'xmpz(42)'
def test_xmpz_subscripts():
x = xmpz(10)
assert x[0] == x[2] == 0
assert x[1] == x[3] == 1
x[0] = 1
assert x == xmpz(11)
assert x[0:2] == mpz(3)
assert x[0:] == mpz(11)
assert x[:4] == mpz(11)
x[:4] = 14
assert x == xmpz(14)
assert x[0] == 0
pytest.raises(TypeError, lambda: x[mpfr('inf')])
assert x[3:0] == mpz(0)
assert x[-1] == 1
x[-1] = 0
assert x == xmpz(6)
x[0:4] = 15
assert x == xmpz(15)
with pytest.raises(ValueError):
x[0] = 16
x[0:4] = 16
assert x == xmpz(0)
x[0:4] = 15
assert x == xmpz(15)
x[0:5] = 16
assert x == xmpz(16)
def test_xmpz_iterators():
x = xmpz(16)
assert [b for b in x.iter_bits()] == [False, False, False, False, True]
x = xmpz(30)
assert [b for b in x.iter_bits()] == [False, True, True, True, True]
assert [b for b in x.iter_bits(-1, 2)] == []
assert [b for b in x.iter_bits(1, 3)] == [True, True]
assert [b for b in x.iter_set()] == [1, 2, 3, 4]
assert [b for b in x.iter_clear()] == [0]
x = xmpz(10)
assert [b for b in x.iter_clear()] == [0, 2]
def test_xmpz_conversion():
assert xmpz('5') == xmpz(5)
assert xmpz('5') == xmpz(5)
pytest.raises(ValueError, lambda: xmpz('not'))
assert xmpz(-3.5) == xmpz(-3)
pytest.raises(OverflowError, lambda: xmpz(float('inf')))
assert xmpz(mpz(100)) == xmpz(100)
assert xmpz(xmpz(100)) == xmpz(100)
assert xmpz(mpq(30,2)) == xmpz(15)
assert str(xmpz(100)) == '100'
def test_xmpz_abs():
a = xmpz(123)
b = abs(a)
assert a is not b
a = xmpz(-123)
b = abs(a)
assert a == xmpz(123)
assert b is None
b = abs(a)
assert b is None
def test_xmpz_iadd():
x = xmpz(5)
x += mpz(6)
assert x == xmpz(11)
x += 7
assert x == xmpz(18)
x += -6
assert x == xmpz(12)
x += mpfr(2.5)
assert x == mpfr('14.5')
def test_xmpz_isub():
x = xmpz(7)
x -= xmpz(1)
assert x == xmpz(6)
x -= 1
assert x == xmpz(5)
x -= mpz(7)
assert x == xmpz(-2)
x -= -5
assert x == xmpz(3)
x -= -mpfr(5)
assert x == mpfr('8.0')
def test_xmpz_imul():
x = xmpz(2)
x *= xmpz(2)
assert x == xmpz(4)
x *= 2
assert x == xmpz(8)
x *= mpz(3)
assert x == xmpz(24)
x *= -1
assert x == xmpz(-24)
x *= mpfr(-0.5)
assert x == mpfr('12.0')
def test_xmpz_ifloordiv():
x = xmpz(49)
x //= xmpz(3)
assert x == xmpz(16)
x //= mpz(3)
assert x == xmpz(5)
x //= 2
assert x == xmpz(2)
with pytest.raises(ZeroDivisionError):
x //= 0
x == xmpz(2)
x //= mpfr(-0.5)
assert x == mpfr('-4.0')
def test_xmpz_imod():
x = xmpz(45)
x %= xmpz(18)
assert x == xmpz(9)
x %= mpz(2)
assert x == xmpz(1)
x = xmpz(40)
x %= 21
assert x == xmpz(19)
with pytest.raises(ZeroDivisionError):
x %= 0
x == xmpz(19)
x %= mpfr(10)
assert x == mpfr('9.0')
def test_xmpz_ishifts():
x = xmpz(63)
x >>= xmpz(63)
assert x == xmpz(0)
x = xmpz(63)
x >>= xmpz(1)
assert x == xmpz(31)
x >>= mpz(2)
assert x == xmpz(7)
x >>= 1
assert x == xmpz(3)
x <<= xmpz(2)
assert x == xmpz(12)
x <<= mpz(1)
assert x == xmpz(24)
x <<= 0
assert x == xmpz(24)
with pytest.raises(TypeError):
x >>= mpfr(2)
with pytest.raises(TypeError):
x <<= mpfr(2)
with pytest.raises(OverflowError):
x >>= -1
with pytest.raises(OverflowError):
x <<= -5
def test_xmpz_ipow():
x = xmpz(5)
x **= xmpz(2)
assert x == xmpz(25)
x **= mpz(2)
assert x == xmpz(625)
with pytest.raises(OverflowError):
x **= -2
x **= 2
assert x == xmpz(390625)
with pytest.raises(TypeError):
x **= mpfr(2)
def test_xmpz_iand():
x = xmpz(7)
x &= xmpz(5)
assert x == xmpz(5)
x &= mpz(4)
assert x == xmpz(4)
x &= 9
assert x == xmpz(0)
x = mpz(4)
x &= 12
assert x == mpz(4)
with pytest.raises(TypeError):
x &= mpfr(4)
def test_xmpz_ior():
x = xmpz(0)
x |= xmpz(1)
assert x == xmpz(1)
x |= xmpz(0)
assert x == xmpz(1)
x = xmpz(0)
x |= xmpz(0)
assert x == xmpz(0)
x |= 5
assert x == xmpz(5)
with pytest.raises(TypeError):
x |= mpfr(3)
def test_xmpz_ixor():
x = xmpz(1)
x ^= xmpz(0)
assert x == xmpz(1)
x ^= mpz(1)
assert x == xmpz(0)
x ^= 1
assert x == xmpz(1)
with pytest.raises(TypeError):
x ^= mpfr(0)
@settings(max_examples=1000)
@example(0)
@example(1)
@example(-1)
@example(1234567890123456789)
@given(integers())
def test_xmpz_to_from_binary(x):
x = xmpz(x)
assert from_binary(to_binary(x)) == x