mirror of
https://github.com/jart/cosmopolitan.git
synced 2025-05-23 05:42:29 +00:00
python-3.6.zip added from Github
README.cosmo contains the necessary links.
This commit is contained in:
parent
75fc601ff5
commit
0c4c56ff39
4219 changed files with 1968626 additions and 0 deletions
90
third_party/python/Modules/_decimal/libmpdec/README.txt
vendored
Normal file
90
third_party/python/Modules/_decimal/libmpdec/README.txt
vendored
Normal file
|
@ -0,0 +1,90 @@
|
|||
|
||||
|
||||
libmpdec
|
||||
========
|
||||
|
||||
libmpdec is a fast C/C++ library for correctly-rounded arbitrary precision
|
||||
decimal floating point arithmetic. It is a complete implementation of
|
||||
Mike Cowlishaw/IBM's General Decimal Arithmetic Specification.
|
||||
|
||||
|
||||
Files required for the Python _decimal module
|
||||
=============================================
|
||||
|
||||
Core files for small and medium precision arithmetic
|
||||
----------------------------------------------------
|
||||
|
||||
basearith.{c,h} -> Core arithmetic in base 10**9 or 10**19.
|
||||
bits.h -> Portable detection of least/most significant one-bit.
|
||||
constants.{c,h} -> Constants that are used in multiple files.
|
||||
context.c -> Context functions.
|
||||
io.{c,h} -> Conversions between mpd_t and ASCII strings,
|
||||
mpd_t formatting (allows UTF-8 fill character).
|
||||
memory.{c,h} -> Allocation handlers with overflow detection
|
||||
and functions for switching between static
|
||||
and dynamic mpd_t.
|
||||
mpdecimal.{c,h} -> All (quiet) functions of the specification.
|
||||
typearith.h -> Fast primitives for double word multiplication,
|
||||
division etc.
|
||||
|
||||
Visual Studio only:
|
||||
~~~~~~~~~~~~~~~~~~~
|
||||
vccompat.h -> snprintf <==> sprintf_s and similar things.
|
||||
vcstdint.h -> stdint.h (included in VS 2010 but not in VS 2008).
|
||||
vcdiv64.asm -> Double word division used in typearith.h. VS 2008 does
|
||||
not allow inline asm for x64. Also, it does not provide
|
||||
an intrinsic for double word division.
|
||||
|
||||
Files for bignum arithmetic:
|
||||
----------------------------
|
||||
|
||||
The following files implement the Fast Number Theoretic Transform
|
||||
used for multiplying coefficients with more than 1024 words (see
|
||||
mpdecimal.c: _mpd_fntmul()).
|
||||
|
||||
umodarith.h -> Fast low level routines for unsigned modular arithmetic.
|
||||
numbertheory.{c,h} -> Routines for setting up the Number Theoretic Transform.
|
||||
difradix2.{c,h} -> Decimation in frequency transform, used as the
|
||||
"base case" by the following three files:
|
||||
|
||||
fnt.{c,h} -> Transform arrays up to 4096 words.
|
||||
sixstep.{c,h} -> Transform larger arrays of length 2**n.
|
||||
fourstep.{c,h} -> Transform larger arrays of length 3 * 2**n.
|
||||
|
||||
convolute.{c,h} -> Fast convolution using one of the three transform
|
||||
functions.
|
||||
transpose.{c,h} -> Transpositions needed for the sixstep algorithm.
|
||||
crt.{c,h} -> Chinese Remainder Theorem: use information from three
|
||||
transforms modulo three different primes to get the
|
||||
final result.
|
||||
|
||||
|
||||
Pointers to literature, proofs and more
|
||||
=======================================
|
||||
|
||||
literature/
|
||||
-----------
|
||||
|
||||
REFERENCES.txt -> List of relevant papers.
|
||||
bignum.txt -> Explanation of the Fast Number Theoretic Transform (FNT).
|
||||
fnt.py -> Verify constants used in the FNT; Python demo for the
|
||||
O(N**2) discrete transform.
|
||||
|
||||
matrix-transform.txt -> Proof for the Matrix Fourier Transform used in
|
||||
fourstep.c.
|
||||
six-step.txt -> Show that the algorithm used in sixstep.c is
|
||||
a variant of the Matrix Fourier Transform.
|
||||
mulmod-64.txt -> Proof for the mulmod64 algorithm from
|
||||
umodarith.h.
|
||||
mulmod-ppro.txt -> Proof for the x87 FPU modular multiplication
|
||||
from umodarith.h.
|
||||
umodarith.lisp -> ACL2 proofs for many functions from umodarith.h.
|
||||
|
||||
|
||||
Library Author
|
||||
==============
|
||||
|
||||
Stefan Krah <skrah@bytereef.org>
|
||||
|
||||
|
||||
|
657
third_party/python/Modules/_decimal/libmpdec/basearith.c
vendored
Normal file
657
third_party/python/Modules/_decimal/libmpdec/basearith.c
vendored
Normal file
|
@ -0,0 +1,657 @@
|
|||
/*
|
||||
* Copyright (c) 2008-2016 Stefan Krah. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
|
||||
#include "mpdecimal.h"
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <assert.h>
|
||||
#include "constants.h"
|
||||
#include "typearith.h"
|
||||
#include "basearith.h"
|
||||
|
||||
|
||||
/*********************************************************************/
|
||||
/* Calculations in base MPD_RADIX */
|
||||
/*********************************************************************/
|
||||
|
||||
|
||||
/*
|
||||
* Knuth, TAOCP, Volume 2, 4.3.1:
|
||||
* w := sum of u (len m) and v (len n)
|
||||
* n > 0 and m >= n
|
||||
* The calling function has to handle a possible final carry.
|
||||
*/
|
||||
mpd_uint_t
|
||||
_mpd_baseadd(mpd_uint_t *w, const mpd_uint_t *u, const mpd_uint_t *v,
|
||||
mpd_size_t m, mpd_size_t n)
|
||||
{
|
||||
mpd_uint_t s;
|
||||
mpd_uint_t carry = 0;
|
||||
mpd_size_t i;
|
||||
|
||||
assert(n > 0 && m >= n);
|
||||
|
||||
/* add n members of u and v */
|
||||
for (i = 0; i < n; i++) {
|
||||
s = u[i] + (v[i] + carry);
|
||||
carry = (s < u[i]) | (s >= MPD_RADIX);
|
||||
w[i] = carry ? s-MPD_RADIX : s;
|
||||
}
|
||||
/* if there is a carry, propagate it */
|
||||
for (; carry && i < m; i++) {
|
||||
s = u[i] + carry;
|
||||
carry = (s == MPD_RADIX);
|
||||
w[i] = carry ? 0 : s;
|
||||
}
|
||||
/* copy the rest of u */
|
||||
for (; i < m; i++) {
|
||||
w[i] = u[i];
|
||||
}
|
||||
|
||||
return carry;
|
||||
}
|
||||
|
||||
/*
|
||||
* Add the contents of u to w. Carries are propagated further. The caller
|
||||
* has to make sure that w is big enough.
|
||||
*/
|
||||
void
|
||||
_mpd_baseaddto(mpd_uint_t *w, const mpd_uint_t *u, mpd_size_t n)
|
||||
{
|
||||
mpd_uint_t s;
|
||||
mpd_uint_t carry = 0;
|
||||
mpd_size_t i;
|
||||
|
||||
if (n == 0) return;
|
||||
|
||||
/* add n members of u to w */
|
||||
for (i = 0; i < n; i++) {
|
||||
s = w[i] + (u[i] + carry);
|
||||
carry = (s < w[i]) | (s >= MPD_RADIX);
|
||||
w[i] = carry ? s-MPD_RADIX : s;
|
||||
}
|
||||
/* if there is a carry, propagate it */
|
||||
for (; carry; i++) {
|
||||
s = w[i] + carry;
|
||||
carry = (s == MPD_RADIX);
|
||||
w[i] = carry ? 0 : s;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Add v to w (len m). The calling function has to handle a possible
|
||||
* final carry. Assumption: m > 0.
|
||||
*/
|
||||
mpd_uint_t
|
||||
_mpd_shortadd(mpd_uint_t *w, mpd_size_t m, mpd_uint_t v)
|
||||
{
|
||||
mpd_uint_t s;
|
||||
mpd_uint_t carry;
|
||||
mpd_size_t i;
|
||||
|
||||
assert(m > 0);
|
||||
|
||||
/* add v to w */
|
||||
s = w[0] + v;
|
||||
carry = (s < v) | (s >= MPD_RADIX);
|
||||
w[0] = carry ? s-MPD_RADIX : s;
|
||||
|
||||
/* if there is a carry, propagate it */
|
||||
for (i = 1; carry && i < m; i++) {
|
||||
s = w[i] + carry;
|
||||
carry = (s == MPD_RADIX);
|
||||
w[i] = carry ? 0 : s;
|
||||
}
|
||||
|
||||
return carry;
|
||||
}
|
||||
|
||||
/* Increment u. The calling function has to handle a possible carry. */
|
||||
mpd_uint_t
|
||||
_mpd_baseincr(mpd_uint_t *u, mpd_size_t n)
|
||||
{
|
||||
mpd_uint_t s;
|
||||
mpd_uint_t carry = 1;
|
||||
mpd_size_t i;
|
||||
|
||||
assert(n > 0);
|
||||
|
||||
/* if there is a carry, propagate it */
|
||||
for (i = 0; carry && i < n; i++) {
|
||||
s = u[i] + carry;
|
||||
carry = (s == MPD_RADIX);
|
||||
u[i] = carry ? 0 : s;
|
||||
}
|
||||
|
||||
return carry;
|
||||
}
|
||||
|
||||
/*
|
||||
* Knuth, TAOCP, Volume 2, 4.3.1:
|
||||
* w := difference of u (len m) and v (len n).
|
||||
* number in u >= number in v;
|
||||
*/
|
||||
void
|
||||
_mpd_basesub(mpd_uint_t *w, const mpd_uint_t *u, const mpd_uint_t *v,
|
||||
mpd_size_t m, mpd_size_t n)
|
||||
{
|
||||
mpd_uint_t d;
|
||||
mpd_uint_t borrow = 0;
|
||||
mpd_size_t i;
|
||||
|
||||
assert(m > 0 && n > 0);
|
||||
|
||||
/* subtract n members of v from u */
|
||||
for (i = 0; i < n; i++) {
|
||||
d = u[i] - (v[i] + borrow);
|
||||
borrow = (u[i] < d);
|
||||
w[i] = borrow ? d + MPD_RADIX : d;
|
||||
}
|
||||
/* if there is a borrow, propagate it */
|
||||
for (; borrow && i < m; i++) {
|
||||
d = u[i] - borrow;
|
||||
borrow = (u[i] == 0);
|
||||
w[i] = borrow ? MPD_RADIX-1 : d;
|
||||
}
|
||||
/* copy the rest of u */
|
||||
for (; i < m; i++) {
|
||||
w[i] = u[i];
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Subtract the contents of u from w. w is larger than u. Borrows are
|
||||
* propagated further, but eventually w can absorb the final borrow.
|
||||
*/
|
||||
void
|
||||
_mpd_basesubfrom(mpd_uint_t *w, const mpd_uint_t *u, mpd_size_t n)
|
||||
{
|
||||
mpd_uint_t d;
|
||||
mpd_uint_t borrow = 0;
|
||||
mpd_size_t i;
|
||||
|
||||
if (n == 0) return;
|
||||
|
||||
/* subtract n members of u from w */
|
||||
for (i = 0; i < n; i++) {
|
||||
d = w[i] - (u[i] + borrow);
|
||||
borrow = (w[i] < d);
|
||||
w[i] = borrow ? d + MPD_RADIX : d;
|
||||
}
|
||||
/* if there is a borrow, propagate it */
|
||||
for (; borrow; i++) {
|
||||
d = w[i] - borrow;
|
||||
borrow = (w[i] == 0);
|
||||
w[i] = borrow ? MPD_RADIX-1 : d;
|
||||
}
|
||||
}
|
||||
|
||||
/* w := product of u (len n) and v (single word) */
|
||||
void
|
||||
_mpd_shortmul(mpd_uint_t *w, const mpd_uint_t *u, mpd_size_t n, mpd_uint_t v)
|
||||
{
|
||||
mpd_uint_t hi, lo;
|
||||
mpd_uint_t carry = 0;
|
||||
mpd_size_t i;
|
||||
|
||||
assert(n > 0);
|
||||
|
||||
for (i=0; i < n; i++) {
|
||||
|
||||
_mpd_mul_words(&hi, &lo, u[i], v);
|
||||
lo = carry + lo;
|
||||
if (lo < carry) hi++;
|
||||
|
||||
_mpd_div_words_r(&carry, &w[i], hi, lo);
|
||||
}
|
||||
w[i] = carry;
|
||||
}
|
||||
|
||||
/*
|
||||
* Knuth, TAOCP, Volume 2, 4.3.1:
|
||||
* w := product of u (len m) and v (len n)
|
||||
* w must be initialized to zero
|
||||
*/
|
||||
void
|
||||
_mpd_basemul(mpd_uint_t *w, const mpd_uint_t *u, const mpd_uint_t *v,
|
||||
mpd_size_t m, mpd_size_t n)
|
||||
{
|
||||
mpd_uint_t hi, lo;
|
||||
mpd_uint_t carry;
|
||||
mpd_size_t i, j;
|
||||
|
||||
assert(m > 0 && n > 0);
|
||||
|
||||
for (j=0; j < n; j++) {
|
||||
carry = 0;
|
||||
for (i=0; i < m; i++) {
|
||||
|
||||
_mpd_mul_words(&hi, &lo, u[i], v[j]);
|
||||
lo = w[i+j] + lo;
|
||||
if (lo < w[i+j]) hi++;
|
||||
lo = carry + lo;
|
||||
if (lo < carry) hi++;
|
||||
|
||||
_mpd_div_words_r(&carry, &w[i+j], hi, lo);
|
||||
}
|
||||
w[j+m] = carry;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Knuth, TAOCP Volume 2, 4.3.1, exercise 16:
|
||||
* w := quotient of u (len n) divided by a single word v
|
||||
*/
|
||||
mpd_uint_t
|
||||
_mpd_shortdiv(mpd_uint_t *w, const mpd_uint_t *u, mpd_size_t n, mpd_uint_t v)
|
||||
{
|
||||
mpd_uint_t hi, lo;
|
||||
mpd_uint_t rem = 0;
|
||||
mpd_size_t i;
|
||||
|
||||
assert(n > 0);
|
||||
|
||||
for (i=n-1; i != MPD_SIZE_MAX; i--) {
|
||||
|
||||
_mpd_mul_words(&hi, &lo, rem, MPD_RADIX);
|
||||
lo = u[i] + lo;
|
||||
if (lo < u[i]) hi++;
|
||||
|
||||
_mpd_div_words(&w[i], &rem, hi, lo, v);
|
||||
}
|
||||
|
||||
return rem;
|
||||
}
|
||||
|
||||
/*
|
||||
* Knuth, TAOCP Volume 2, 4.3.1:
|
||||
* q, r := quotient and remainder of uconst (len nplusm)
|
||||
* divided by vconst (len n)
|
||||
* nplusm >= n
|
||||
*
|
||||
* If r is not NULL, r will contain the remainder. If r is NULL, the
|
||||
* return value indicates if there is a remainder: 1 for true, 0 for
|
||||
* false. A return value of -1 indicates an error.
|
||||
*/
|
||||
int
|
||||
_mpd_basedivmod(mpd_uint_t *q, mpd_uint_t *r,
|
||||
const mpd_uint_t *uconst, const mpd_uint_t *vconst,
|
||||
mpd_size_t nplusm, mpd_size_t n)
|
||||
{
|
||||
mpd_uint_t ustatic[MPD_MINALLOC_MAX];
|
||||
mpd_uint_t vstatic[MPD_MINALLOC_MAX];
|
||||
mpd_uint_t *u = ustatic;
|
||||
mpd_uint_t *v = vstatic;
|
||||
mpd_uint_t d, qhat, rhat, w2[2];
|
||||
mpd_uint_t hi, lo, x;
|
||||
mpd_uint_t carry;
|
||||
mpd_size_t i, j, m;
|
||||
int retval = 0;
|
||||
|
||||
assert(n > 1 && nplusm >= n);
|
||||
m = sub_size_t(nplusm, n);
|
||||
|
||||
/* D1: normalize */
|
||||
d = MPD_RADIX / (vconst[n-1] + 1);
|
||||
|
||||
if (nplusm >= MPD_MINALLOC_MAX) {
|
||||
if ((u = mpd_alloc(nplusm+1, sizeof *u)) == NULL) {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
if (n >= MPD_MINALLOC_MAX) {
|
||||
if ((v = mpd_alloc(n+1, sizeof *v)) == NULL) {
|
||||
mpd_free(u);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
_mpd_shortmul(u, uconst, nplusm, d);
|
||||
_mpd_shortmul(v, vconst, n, d);
|
||||
|
||||
/* D2: loop */
|
||||
for (j=m; j != MPD_SIZE_MAX; j--) {
|
||||
|
||||
/* D3: calculate qhat and rhat */
|
||||
rhat = _mpd_shortdiv(w2, u+j+n-1, 2, v[n-1]);
|
||||
qhat = w2[1] * MPD_RADIX + w2[0];
|
||||
|
||||
while (1) {
|
||||
if (qhat < MPD_RADIX) {
|
||||
_mpd_singlemul(w2, qhat, v[n-2]);
|
||||
if (w2[1] <= rhat) {
|
||||
if (w2[1] != rhat || w2[0] <= u[j+n-2]) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
qhat -= 1;
|
||||
rhat += v[n-1];
|
||||
if (rhat < v[n-1] || rhat >= MPD_RADIX) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
/* D4: multiply and subtract */
|
||||
carry = 0;
|
||||
for (i=0; i <= n; i++) {
|
||||
|
||||
_mpd_mul_words(&hi, &lo, qhat, v[i]);
|
||||
|
||||
lo = carry + lo;
|
||||
if (lo < carry) hi++;
|
||||
|
||||
_mpd_div_words_r(&hi, &lo, hi, lo);
|
||||
|
||||
x = u[i+j] - lo;
|
||||
carry = (u[i+j] < x);
|
||||
u[i+j] = carry ? x+MPD_RADIX : x;
|
||||
carry += hi;
|
||||
}
|
||||
q[j] = qhat;
|
||||
/* D5: test remainder */
|
||||
if (carry) {
|
||||
q[j] -= 1;
|
||||
/* D6: add back */
|
||||
(void)_mpd_baseadd(u+j, u+j, v, n+1, n);
|
||||
}
|
||||
}
|
||||
|
||||
/* D8: unnormalize */
|
||||
if (r != NULL) {
|
||||
_mpd_shortdiv(r, u, n, d);
|
||||
/* we are not interested in the return value here */
|
||||
retval = 0;
|
||||
}
|
||||
else {
|
||||
retval = !_mpd_isallzero(u, n);
|
||||
}
|
||||
|
||||
|
||||
if (u != ustatic) mpd_free(u);
|
||||
if (v != vstatic) mpd_free(v);
|
||||
return retval;
|
||||
}
|
||||
|
||||
/*
|
||||
* Left shift of src by 'shift' digits; src may equal dest.
|
||||
*
|
||||
* dest := area of n mpd_uint_t with space for srcdigits+shift digits.
|
||||
* src := coefficient with length m.
|
||||
*
|
||||
* The case splits in the function are non-obvious. The following
|
||||
* equations might help:
|
||||
*
|
||||
* Let msdigits denote the number of digits in the most significant
|
||||
* word of src. Then 1 <= msdigits <= rdigits.
|
||||
*
|
||||
* 1) shift = q * rdigits + r
|
||||
* 2) srcdigits = qsrc * rdigits + msdigits
|
||||
* 3) destdigits = shift + srcdigits
|
||||
* = q * rdigits + r + qsrc * rdigits + msdigits
|
||||
* = q * rdigits + (qsrc * rdigits + (r + msdigits))
|
||||
*
|
||||
* The result has q zero words, followed by the coefficient that
|
||||
* is left-shifted by r. The case r == 0 is trivial. For r > 0, it
|
||||
* is important to keep in mind that we always read m source words,
|
||||
* but write m+1 destination words if r + msdigits > rdigits, m words
|
||||
* otherwise.
|
||||
*/
|
||||
void
|
||||
_mpd_baseshiftl(mpd_uint_t *dest, mpd_uint_t *src, mpd_size_t n, mpd_size_t m,
|
||||
mpd_size_t shift)
|
||||
{
|
||||
#if defined(__GNUC__) && !defined(__INTEL_COMPILER) && !defined(__clang__)
|
||||
/* spurious uninitialized warnings */
|
||||
mpd_uint_t l=l, lprev=lprev, h=h;
|
||||
#else
|
||||
mpd_uint_t l, lprev, h;
|
||||
#endif
|
||||
mpd_uint_t q, r;
|
||||
mpd_uint_t ph;
|
||||
|
||||
assert(m > 0 && n >= m);
|
||||
|
||||
_mpd_div_word(&q, &r, (mpd_uint_t)shift, MPD_RDIGITS);
|
||||
|
||||
if (r != 0) {
|
||||
|
||||
ph = mpd_pow10[r];
|
||||
|
||||
--m; --n;
|
||||
_mpd_divmod_pow10(&h, &lprev, src[m--], MPD_RDIGITS-r);
|
||||
if (h != 0) { /* r + msdigits > rdigits <==> h != 0 */
|
||||
dest[n--] = h;
|
||||
}
|
||||
/* write m-1 shifted words */
|
||||
for (; m != MPD_SIZE_MAX; m--,n--) {
|
||||
_mpd_divmod_pow10(&h, &l, src[m], MPD_RDIGITS-r);
|
||||
dest[n] = ph * lprev + h;
|
||||
lprev = l;
|
||||
}
|
||||
/* write least significant word */
|
||||
dest[q] = ph * lprev;
|
||||
}
|
||||
else {
|
||||
while (--m != MPD_SIZE_MAX) {
|
||||
dest[m+q] = src[m];
|
||||
}
|
||||
}
|
||||
|
||||
mpd_uint_zero(dest, q);
|
||||
}
|
||||
|
||||
/*
|
||||
* Right shift of src by 'shift' digits; src may equal dest.
|
||||
* Assumption: srcdigits-shift > 0.
|
||||
*
|
||||
* dest := area with space for srcdigits-shift digits.
|
||||
* src := coefficient with length 'slen'.
|
||||
*
|
||||
* The case splits in the function rely on the following equations:
|
||||
*
|
||||
* Let msdigits denote the number of digits in the most significant
|
||||
* word of src. Then 1 <= msdigits <= rdigits.
|
||||
*
|
||||
* 1) shift = q * rdigits + r
|
||||
* 2) srcdigits = qsrc * rdigits + msdigits
|
||||
* 3) destdigits = srcdigits - shift
|
||||
* = qsrc * rdigits + msdigits - (q * rdigits + r)
|
||||
* = (qsrc - q) * rdigits + msdigits - r
|
||||
*
|
||||
* Since destdigits > 0 and 1 <= msdigits <= rdigits:
|
||||
*
|
||||
* 4) qsrc >= q
|
||||
* 5) qsrc == q ==> msdigits > r
|
||||
*
|
||||
* The result has slen-q words if msdigits > r, slen-q-1 words otherwise.
|
||||
*/
|
||||
mpd_uint_t
|
||||
_mpd_baseshiftr(mpd_uint_t *dest, mpd_uint_t *src, mpd_size_t slen,
|
||||
mpd_size_t shift)
|
||||
{
|
||||
#if defined(__GNUC__) && !defined(__INTEL_COMPILER) && !defined(__clang__)
|
||||
/* spurious uninitialized warnings */
|
||||
mpd_uint_t l=l, h=h, hprev=hprev; /* low, high, previous high */
|
||||
#else
|
||||
mpd_uint_t l, h, hprev; /* low, high, previous high */
|
||||
#endif
|
||||
mpd_uint_t rnd, rest; /* rounding digit, rest */
|
||||
mpd_uint_t q, r;
|
||||
mpd_size_t i, j;
|
||||
mpd_uint_t ph;
|
||||
|
||||
assert(slen > 0);
|
||||
|
||||
_mpd_div_word(&q, &r, (mpd_uint_t)shift, MPD_RDIGITS);
|
||||
|
||||
rnd = rest = 0;
|
||||
if (r != 0) {
|
||||
|
||||
ph = mpd_pow10[MPD_RDIGITS-r];
|
||||
|
||||
_mpd_divmod_pow10(&hprev, &rest, src[q], r);
|
||||
_mpd_divmod_pow10(&rnd, &rest, rest, r-1);
|
||||
|
||||
if (rest == 0 && q > 0) {
|
||||
rest = !_mpd_isallzero(src, q);
|
||||
}
|
||||
/* write slen-q-1 words */
|
||||
for (j=0,i=q+1; i<slen; i++,j++) {
|
||||
_mpd_divmod_pow10(&h, &l, src[i], r);
|
||||
dest[j] = ph * l + hprev;
|
||||
hprev = h;
|
||||
}
|
||||
/* write most significant word */
|
||||
if (hprev != 0) { /* always the case if slen==q-1 */
|
||||
dest[j] = hprev;
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (q > 0) {
|
||||
_mpd_divmod_pow10(&rnd, &rest, src[q-1], MPD_RDIGITS-1);
|
||||
/* is there any non-zero digit below rnd? */
|
||||
if (rest == 0) rest = !_mpd_isallzero(src, q-1);
|
||||
}
|
||||
for (j = 0; j < slen-q; j++) {
|
||||
dest[j] = src[q+j];
|
||||
}
|
||||
}
|
||||
|
||||
/* 0-4 ==> rnd+rest < 0.5 */
|
||||
/* 5 ==> rnd+rest == 0.5 */
|
||||
/* 6-9 ==> rnd+rest > 0.5 */
|
||||
return (rnd == 0 || rnd == 5) ? rnd + !!rest : rnd;
|
||||
}
|
||||
|
||||
|
||||
/*********************************************************************/
|
||||
/* Calculations in base b */
|
||||
/*********************************************************************/
|
||||
|
||||
/*
|
||||
* Add v to w (len m). The calling function has to handle a possible
|
||||
* final carry. Assumption: m > 0.
|
||||
*/
|
||||
mpd_uint_t
|
||||
_mpd_shortadd_b(mpd_uint_t *w, mpd_size_t m, mpd_uint_t v, mpd_uint_t b)
|
||||
{
|
||||
mpd_uint_t s;
|
||||
mpd_uint_t carry;
|
||||
mpd_size_t i;
|
||||
|
||||
assert(m > 0);
|
||||
|
||||
/* add v to w */
|
||||
s = w[0] + v;
|
||||
carry = (s < v) | (s >= b);
|
||||
w[0] = carry ? s-b : s;
|
||||
|
||||
/* if there is a carry, propagate it */
|
||||
for (i = 1; carry && i < m; i++) {
|
||||
s = w[i] + carry;
|
||||
carry = (s == b);
|
||||
w[i] = carry ? 0 : s;
|
||||
}
|
||||
|
||||
return carry;
|
||||
}
|
||||
|
||||
/* w := product of u (len n) and v (single word). Return carry. */
|
||||
mpd_uint_t
|
||||
_mpd_shortmul_c(mpd_uint_t *w, const mpd_uint_t *u, mpd_size_t n, mpd_uint_t v)
|
||||
{
|
||||
mpd_uint_t hi, lo;
|
||||
mpd_uint_t carry = 0;
|
||||
mpd_size_t i;
|
||||
|
||||
assert(n > 0);
|
||||
|
||||
for (i=0; i < n; i++) {
|
||||
|
||||
_mpd_mul_words(&hi, &lo, u[i], v);
|
||||
lo = carry + lo;
|
||||
if (lo < carry) hi++;
|
||||
|
||||
_mpd_div_words_r(&carry, &w[i], hi, lo);
|
||||
}
|
||||
|
||||
return carry;
|
||||
}
|
||||
|
||||
/* w := product of u (len n) and v (single word) */
|
||||
mpd_uint_t
|
||||
_mpd_shortmul_b(mpd_uint_t *w, const mpd_uint_t *u, mpd_size_t n,
|
||||
mpd_uint_t v, mpd_uint_t b)
|
||||
{
|
||||
mpd_uint_t hi, lo;
|
||||
mpd_uint_t carry = 0;
|
||||
mpd_size_t i;
|
||||
|
||||
assert(n > 0);
|
||||
|
||||
for (i=0; i < n; i++) {
|
||||
|
||||
_mpd_mul_words(&hi, &lo, u[i], v);
|
||||
lo = carry + lo;
|
||||
if (lo < carry) hi++;
|
||||
|
||||
_mpd_div_words(&carry, &w[i], hi, lo, b);
|
||||
}
|
||||
|
||||
return carry;
|
||||
}
|
||||
|
||||
/*
|
||||
* Knuth, TAOCP Volume 2, 4.3.1, exercise 16:
|
||||
* w := quotient of u (len n) divided by a single word v
|
||||
*/
|
||||
mpd_uint_t
|
||||
_mpd_shortdiv_b(mpd_uint_t *w, const mpd_uint_t *u, mpd_size_t n,
|
||||
mpd_uint_t v, mpd_uint_t b)
|
||||
{
|
||||
mpd_uint_t hi, lo;
|
||||
mpd_uint_t rem = 0;
|
||||
mpd_size_t i;
|
||||
|
||||
assert(n > 0);
|
||||
|
||||
for (i=n-1; i != MPD_SIZE_MAX; i--) {
|
||||
|
||||
_mpd_mul_words(&hi, &lo, rem, b);
|
||||
lo = u[i] + lo;
|
||||
if (lo < u[i]) hi++;
|
||||
|
||||
_mpd_div_words(&w[i], &rem, hi, lo, v);
|
||||
}
|
||||
|
||||
return rem;
|
||||
}
|
||||
|
||||
|
||||
|
222
third_party/python/Modules/_decimal/libmpdec/basearith.h
vendored
Normal file
222
third_party/python/Modules/_decimal/libmpdec/basearith.h
vendored
Normal file
|
@ -0,0 +1,222 @@
|
|||
/*
|
||||
* Copyright (c) 2008-2016 Stefan Krah. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
|
||||
#ifndef BASEARITH_H
|
||||
#define BASEARITH_H
|
||||
|
||||
|
||||
#include "mpdecimal.h"
|
||||
#include <stdio.h>
|
||||
#include "typearith.h"
|
||||
|
||||
|
||||
/* Internal header file: all symbols have local scope in the DSO */
|
||||
MPD_PRAGMA(MPD_HIDE_SYMBOLS_START)
|
||||
|
||||
|
||||
mpd_uint_t _mpd_baseadd(mpd_uint_t *w, const mpd_uint_t *u, const mpd_uint_t *v,
|
||||
mpd_size_t m, mpd_size_t n);
|
||||
void _mpd_baseaddto(mpd_uint_t *w, const mpd_uint_t *u, mpd_size_t n);
|
||||
mpd_uint_t _mpd_shortadd(mpd_uint_t *w, mpd_size_t m, mpd_uint_t v);
|
||||
mpd_uint_t _mpd_shortadd_b(mpd_uint_t *w, mpd_size_t m, mpd_uint_t v,
|
||||
mpd_uint_t b);
|
||||
mpd_uint_t _mpd_baseincr(mpd_uint_t *u, mpd_size_t n);
|
||||
void _mpd_basesub(mpd_uint_t *w, const mpd_uint_t *u, const mpd_uint_t *v,
|
||||
mpd_size_t m, mpd_size_t n);
|
||||
void _mpd_basesubfrom(mpd_uint_t *w, const mpd_uint_t *u, mpd_size_t n);
|
||||
void _mpd_basemul(mpd_uint_t *w, const mpd_uint_t *u, const mpd_uint_t *v,
|
||||
mpd_size_t m, mpd_size_t n);
|
||||
void _mpd_shortmul(mpd_uint_t *w, const mpd_uint_t *u, mpd_size_t n,
|
||||
mpd_uint_t v);
|
||||
mpd_uint_t _mpd_shortmul_c(mpd_uint_t *w, const mpd_uint_t *u, mpd_size_t n,
|
||||
mpd_uint_t v);
|
||||
mpd_uint_t _mpd_shortmul_b(mpd_uint_t *w, const mpd_uint_t *u, mpd_size_t n,
|
||||
mpd_uint_t v, mpd_uint_t b);
|
||||
mpd_uint_t _mpd_shortdiv(mpd_uint_t *w, const mpd_uint_t *u, mpd_size_t n,
|
||||
mpd_uint_t v);
|
||||
mpd_uint_t _mpd_shortdiv_b(mpd_uint_t *w, const mpd_uint_t *u, mpd_size_t n,
|
||||
mpd_uint_t v, mpd_uint_t b);
|
||||
int _mpd_basedivmod(mpd_uint_t *q, mpd_uint_t *r, const mpd_uint_t *uconst,
|
||||
const mpd_uint_t *vconst, mpd_size_t nplusm, mpd_size_t n);
|
||||
void _mpd_baseshiftl(mpd_uint_t *dest, mpd_uint_t *src, mpd_size_t n,
|
||||
mpd_size_t m, mpd_size_t shift);
|
||||
mpd_uint_t _mpd_baseshiftr(mpd_uint_t *dest, mpd_uint_t *src, mpd_size_t slen,
|
||||
mpd_size_t shift);
|
||||
|
||||
|
||||
|
||||
#ifdef CONFIG_64
|
||||
extern const mpd_uint_t mprime_rdx;
|
||||
|
||||
/*
|
||||
* Algorithm from: Division by Invariant Integers using Multiplication,
|
||||
* T. Granlund and P. L. Montgomery, Proceedings of the SIGPLAN '94
|
||||
* Conference on Programming Language Design and Implementation.
|
||||
*
|
||||
* http://gmplib.org/~tege/divcnst-pldi94.pdf
|
||||
*
|
||||
* Variables from the paper and their translations (See section 8):
|
||||
*
|
||||
* N := 64
|
||||
* d := MPD_RADIX
|
||||
* l := 64
|
||||
* m' := floor((2**(64+64) - 1)/MPD_RADIX) - 2**64
|
||||
*
|
||||
* Since N-l == 0:
|
||||
*
|
||||
* dnorm := d
|
||||
* n2 := hi
|
||||
* n10 := lo
|
||||
*
|
||||
* ACL2 proof: mpd-div-words-r-correct
|
||||
*/
|
||||
static inline void
|
||||
_mpd_div_words_r(mpd_uint_t *q, mpd_uint_t *r, mpd_uint_t hi, mpd_uint_t lo)
|
||||
{
|
||||
mpd_uint_t n_adj, h, l, t;
|
||||
mpd_uint_t n1_neg;
|
||||
|
||||
/* n1_neg = if lo >= 2**63 then MPD_UINT_MAX else 0 */
|
||||
n1_neg = (lo & (1ULL<<63)) ? MPD_UINT_MAX : 0;
|
||||
/* n_adj = if lo >= 2**63 then lo+MPD_RADIX else lo */
|
||||
n_adj = lo + (n1_neg & MPD_RADIX);
|
||||
|
||||
/* (h, l) = if lo >= 2**63 then m'*(hi+1) else m'*hi */
|
||||
_mpd_mul_words(&h, &l, mprime_rdx, hi-n1_neg);
|
||||
l = l + n_adj;
|
||||
if (l < n_adj) h++;
|
||||
t = h + hi;
|
||||
/* At this point t == qest, with q == qest or q == qest+1:
|
||||
* 1) 0 <= 2**64*hi + lo - qest*MPD_RADIX < 2*MPD_RADIX
|
||||
*/
|
||||
|
||||
/* t = 2**64-1 - qest = 2**64 - (qest+1) */
|
||||
t = MPD_UINT_MAX - t;
|
||||
|
||||
/* (h, l) = 2**64*MPD_RADIX - (qest+1)*MPD_RADIX */
|
||||
_mpd_mul_words(&h, &l, t, MPD_RADIX);
|
||||
l = l + lo;
|
||||
if (l < lo) h++;
|
||||
h += hi;
|
||||
h -= MPD_RADIX;
|
||||
/* (h, l) = 2**64*hi + lo - (qest+1)*MPD_RADIX (mod 2**128)
|
||||
* Case q == qest+1:
|
||||
* a) h == 0, l == r
|
||||
* b) q := h - t == qest+1
|
||||
* c) r := l
|
||||
* Case q == qest:
|
||||
* a) h == MPD_UINT_MAX, l == 2**64-(MPD_RADIX-r)
|
||||
* b) q := h - t == qest
|
||||
* c) r := l + MPD_RADIX = r
|
||||
*/
|
||||
|
||||
*q = (h - t);
|
||||
*r = l + (MPD_RADIX & h);
|
||||
}
|
||||
#else
|
||||
static inline void
|
||||
_mpd_div_words_r(mpd_uint_t *q, mpd_uint_t *r, mpd_uint_t hi, mpd_uint_t lo)
|
||||
{
|
||||
_mpd_div_words(q, r, hi, lo, MPD_RADIX);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
/* Multiply two single base MPD_RADIX words, store result in array w[2]. */
|
||||
static inline void
|
||||
_mpd_singlemul(mpd_uint_t w[2], mpd_uint_t u, mpd_uint_t v)
|
||||
{
|
||||
mpd_uint_t hi, lo;
|
||||
|
||||
_mpd_mul_words(&hi, &lo, u, v);
|
||||
_mpd_div_words_r(&w[1], &w[0], hi, lo);
|
||||
}
|
||||
|
||||
/* Multiply u (len 2) and v (len m, 1 <= m <= 2). */
|
||||
static inline void
|
||||
_mpd_mul_2_le2(mpd_uint_t w[4], mpd_uint_t u[2], mpd_uint_t v[2], mpd_ssize_t m)
|
||||
{
|
||||
mpd_uint_t hi, lo;
|
||||
|
||||
_mpd_mul_words(&hi, &lo, u[0], v[0]);
|
||||
_mpd_div_words_r(&w[1], &w[0], hi, lo);
|
||||
|
||||
_mpd_mul_words(&hi, &lo, u[1], v[0]);
|
||||
lo = w[1] + lo;
|
||||
if (lo < w[1]) hi++;
|
||||
_mpd_div_words_r(&w[2], &w[1], hi, lo);
|
||||
if (m == 1) return;
|
||||
|
||||
_mpd_mul_words(&hi, &lo, u[0], v[1]);
|
||||
lo = w[1] + lo;
|
||||
if (lo < w[1]) hi++;
|
||||
_mpd_div_words_r(&w[3], &w[1], hi, lo);
|
||||
|
||||
_mpd_mul_words(&hi, &lo, u[1], v[1]);
|
||||
lo = w[2] + lo;
|
||||
if (lo < w[2]) hi++;
|
||||
lo = w[3] + lo;
|
||||
if (lo < w[3]) hi++;
|
||||
_mpd_div_words_r(&w[3], &w[2], hi, lo);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Test if all words from data[len-1] to data[0] are zero. If len is 0, nothing
|
||||
* is tested and the coefficient is regarded as "all zero".
|
||||
*/
|
||||
static inline int
|
||||
_mpd_isallzero(const mpd_uint_t *data, mpd_ssize_t len)
|
||||
{
|
||||
while (--len >= 0) {
|
||||
if (data[len] != 0) return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Test if all full words from data[len-1] to data[0] are MPD_RADIX-1
|
||||
* (all nines). Return true if len == 0.
|
||||
*/
|
||||
static inline int
|
||||
_mpd_isallnine(const mpd_uint_t *data, mpd_ssize_t len)
|
||||
{
|
||||
while (--len >= 0) {
|
||||
if (data[len] != MPD_RADIX-1) return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
MPD_PRAGMA(MPD_HIDE_SYMBOLS_END) /* restore previous scope rules */
|
||||
|
||||
|
||||
#endif /* BASEARITH_H */
|
||||
|
||||
|
||||
|
192
third_party/python/Modules/_decimal/libmpdec/bits.h
vendored
Normal file
192
third_party/python/Modules/_decimal/libmpdec/bits.h
vendored
Normal file
|
@ -0,0 +1,192 @@
|
|||
/*
|
||||
* Copyright (c) 2008-2016 Stefan Krah. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
|
||||
#ifndef BITS_H
|
||||
#define BITS_H
|
||||
|
||||
|
||||
#include "mpdecimal.h"
|
||||
#include <stdio.h>
|
||||
|
||||
|
||||
/* Check if n is a power of 2. */
|
||||
static inline int
|
||||
ispower2(mpd_size_t n)
|
||||
{
|
||||
return n != 0 && (n & (n-1)) == 0;
|
||||
}
|
||||
|
||||
#if defined(ANSI)
|
||||
/*
|
||||
* Return the most significant bit position of n from 0 to 31 (63).
|
||||
* Assumptions: n != 0.
|
||||
*/
|
||||
static inline int
|
||||
mpd_bsr(mpd_size_t n)
|
||||
{
|
||||
int pos = 0;
|
||||
mpd_size_t tmp;
|
||||
|
||||
#ifdef CONFIG_64
|
||||
tmp = n >> 32;
|
||||
if (tmp != 0) { n = tmp; pos += 32; }
|
||||
#endif
|
||||
tmp = n >> 16;
|
||||
if (tmp != 0) { n = tmp; pos += 16; }
|
||||
tmp = n >> 8;
|
||||
if (tmp != 0) { n = tmp; pos += 8; }
|
||||
tmp = n >> 4;
|
||||
if (tmp != 0) { n = tmp; pos += 4; }
|
||||
tmp = n >> 2;
|
||||
if (tmp != 0) { n = tmp; pos += 2; }
|
||||
tmp = n >> 1;
|
||||
if (tmp != 0) { n = tmp; pos += 1; }
|
||||
|
||||
return pos + (int)n - 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Return the least significant bit position of n from 0 to 31 (63).
|
||||
* Assumptions: n != 0.
|
||||
*/
|
||||
static inline int
|
||||
mpd_bsf(mpd_size_t n)
|
||||
{
|
||||
int pos;
|
||||
|
||||
#ifdef CONFIG_64
|
||||
pos = 63;
|
||||
if (n & 0x00000000FFFFFFFFULL) { pos -= 32; } else { n >>= 32; }
|
||||
if (n & 0x000000000000FFFFULL) { pos -= 16; } else { n >>= 16; }
|
||||
if (n & 0x00000000000000FFULL) { pos -= 8; } else { n >>= 8; }
|
||||
if (n & 0x000000000000000FULL) { pos -= 4; } else { n >>= 4; }
|
||||
if (n & 0x0000000000000003ULL) { pos -= 2; } else { n >>= 2; }
|
||||
if (n & 0x0000000000000001ULL) { pos -= 1; }
|
||||
#else
|
||||
pos = 31;
|
||||
if (n & 0x000000000000FFFFUL) { pos -= 16; } else { n >>= 16; }
|
||||
if (n & 0x00000000000000FFUL) { pos -= 8; } else { n >>= 8; }
|
||||
if (n & 0x000000000000000FUL) { pos -= 4; } else { n >>= 4; }
|
||||
if (n & 0x0000000000000003UL) { pos -= 2; } else { n >>= 2; }
|
||||
if (n & 0x0000000000000001UL) { pos -= 1; }
|
||||
#endif
|
||||
return pos;
|
||||
}
|
||||
/* END ANSI */
|
||||
|
||||
#elif defined(ASM)
|
||||
/*
|
||||
* Bit scan reverse. Assumptions: a != 0.
|
||||
*/
|
||||
static inline int
|
||||
mpd_bsr(mpd_size_t a)
|
||||
{
|
||||
mpd_size_t retval;
|
||||
|
||||
__asm__ (
|
||||
#ifdef CONFIG_64
|
||||
"bsrq %1, %0\n\t"
|
||||
#else
|
||||
"bsr %1, %0\n\t"
|
||||
#endif
|
||||
:"=r" (retval)
|
||||
:"r" (a)
|
||||
:"cc"
|
||||
);
|
||||
|
||||
return (int)retval;
|
||||
}
|
||||
|
||||
/*
|
||||
* Bit scan forward. Assumptions: a != 0.
|
||||
*/
|
||||
static inline int
|
||||
mpd_bsf(mpd_size_t a)
|
||||
{
|
||||
mpd_size_t retval;
|
||||
|
||||
__asm__ (
|
||||
#ifdef CONFIG_64
|
||||
"bsfq %1, %0\n\t"
|
||||
#else
|
||||
"bsf %1, %0\n\t"
|
||||
#endif
|
||||
:"=r" (retval)
|
||||
:"r" (a)
|
||||
:"cc"
|
||||
);
|
||||
|
||||
return (int)retval;
|
||||
}
|
||||
/* END ASM */
|
||||
|
||||
#elif defined(MASM)
|
||||
#include <intrin.h>
|
||||
/*
|
||||
* Bit scan reverse. Assumptions: a != 0.
|
||||
*/
|
||||
static inline int __cdecl
|
||||
mpd_bsr(mpd_size_t a)
|
||||
{
|
||||
unsigned long retval;
|
||||
|
||||
#ifdef CONFIG_64
|
||||
_BitScanReverse64(&retval, a);
|
||||
#else
|
||||
_BitScanReverse(&retval, a);
|
||||
#endif
|
||||
|
||||
return (int)retval;
|
||||
}
|
||||
|
||||
/*
|
||||
* Bit scan forward. Assumptions: a != 0.
|
||||
*/
|
||||
static inline int __cdecl
|
||||
mpd_bsf(mpd_size_t a)
|
||||
{
|
||||
unsigned long retval;
|
||||
|
||||
#ifdef CONFIG_64
|
||||
_BitScanForward64(&retval, a);
|
||||
#else
|
||||
_BitScanForward(&retval, a);
|
||||
#endif
|
||||
|
||||
return (int)retval;
|
||||
}
|
||||
/* END MASM (_MSC_VER) */
|
||||
#else
|
||||
#error "missing preprocessor definitions"
|
||||
#endif /* BSR/BSF */
|
||||
|
||||
|
||||
#endif /* BITS_H */
|
||||
|
||||
|
||||
|
132
third_party/python/Modules/_decimal/libmpdec/constants.c
vendored
Normal file
132
third_party/python/Modules/_decimal/libmpdec/constants.c
vendored
Normal file
|
@ -0,0 +1,132 @@
|
|||
/*
|
||||
* Copyright (c) 2008-2016 Stefan Krah. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
|
||||
#include "mpdecimal.h"
|
||||
#include <stdio.h>
|
||||
#include "constants.h"
|
||||
|
||||
|
||||
#if defined(CONFIG_64)
|
||||
|
||||
/* number-theory.c */
|
||||
const mpd_uint_t mpd_moduli[3] = {
|
||||
18446744069414584321ULL, 18446744056529682433ULL, 18446742974197923841ULL
|
||||
};
|
||||
const mpd_uint_t mpd_roots[3] = {7ULL, 10ULL, 19ULL};
|
||||
|
||||
/* crt.c */
|
||||
const mpd_uint_t INV_P1_MOD_P2 = 18446744055098026669ULL;
|
||||
const mpd_uint_t INV_P1P2_MOD_P3 = 287064143708160ULL;
|
||||
const mpd_uint_t LH_P1P2 = 18446744052234715137ULL; /* (P1*P2) % 2^64 */
|
||||
const mpd_uint_t UH_P1P2 = 18446744052234715141ULL; /* (P1*P2) / 2^64 */
|
||||
|
||||
/* transpose.c */
|
||||
const mpd_size_t mpd_bits[64] = {
|
||||
1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024, 2048, 4096, 8192, 16384,
|
||||
32768, 65536, 131072, 262144, 524288, 1048576, 2097152, 4194304, 8388608,
|
||||
16777216, 33554432, 67108864, 134217728, 268435456, 536870912, 1073741824,
|
||||
2147483648ULL, 4294967296ULL, 8589934592ULL, 17179869184ULL, 34359738368ULL,
|
||||
68719476736ULL, 137438953472ULL, 274877906944ULL, 549755813888ULL,
|
||||
1099511627776ULL, 2199023255552ULL, 4398046511104, 8796093022208ULL,
|
||||
17592186044416ULL, 35184372088832ULL, 70368744177664ULL, 140737488355328ULL,
|
||||
281474976710656ULL, 562949953421312ULL, 1125899906842624ULL,
|
||||
2251799813685248ULL, 4503599627370496ULL, 9007199254740992ULL,
|
||||
18014398509481984ULL, 36028797018963968ULL, 72057594037927936ULL,
|
||||
144115188075855872ULL, 288230376151711744ULL, 576460752303423488ULL,
|
||||
1152921504606846976ULL, 2305843009213693952ULL, 4611686018427387904ULL,
|
||||
9223372036854775808ULL
|
||||
};
|
||||
|
||||
/* mpdecimal.c */
|
||||
const mpd_uint_t mpd_pow10[MPD_RDIGITS+1] = {
|
||||
1,10,100,1000,10000,100000,1000000,10000000,100000000,1000000000,
|
||||
10000000000ULL,100000000000ULL,1000000000000ULL,10000000000000ULL,
|
||||
100000000000000ULL,1000000000000000ULL,10000000000000000ULL,
|
||||
100000000000000000ULL,1000000000000000000ULL,10000000000000000000ULL
|
||||
};
|
||||
|
||||
/* magic number for constant division by MPD_RADIX */
|
||||
const mpd_uint_t mprime_rdx = 15581492618384294730ULL;
|
||||
|
||||
#elif defined(CONFIG_32)
|
||||
|
||||
/* number-theory.c */
|
||||
const mpd_uint_t mpd_moduli[3] = {2113929217UL, 2013265921UL, 1811939329UL};
|
||||
const mpd_uint_t mpd_roots[3] = {5UL, 31UL, 13UL};
|
||||
|
||||
/* PentiumPro modular multiplication: These constants have to be loaded as
|
||||
* 80 bit long doubles, which are not supported by certain compilers. */
|
||||
const uint32_t mpd_invmoduli[3][3] = {
|
||||
{4293885170U, 2181570688U, 16352U}, /* ((long double) 1 / 2113929217UL) */
|
||||
{1698898177U, 2290649223U, 16352U}, /* ((long double) 1 / 2013265921UL) */
|
||||
{2716021846U, 2545165803U, 16352U} /* ((long double) 1 / 1811939329UL) */
|
||||
};
|
||||
|
||||
const float MPD_TWO63 = 9223372036854775808.0; /* 2^63 */
|
||||
|
||||
/* crt.c */
|
||||
const mpd_uint_t INV_P1_MOD_P2 = 2013265901UL;
|
||||
const mpd_uint_t INV_P1P2_MOD_P3 = 54UL;
|
||||
const mpd_uint_t LH_P1P2 = 4127195137UL; /* (P1*P2) % 2^32 */
|
||||
const mpd_uint_t UH_P1P2 = 990904320UL; /* (P1*P2) / 2^32 */
|
||||
|
||||
/* transpose.c */
|
||||
const mpd_size_t mpd_bits[32] = {
|
||||
1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024, 2048, 4096, 8192, 16384,
|
||||
32768, 65536, 131072, 262144, 524288, 1048576, 2097152, 4194304, 8388608,
|
||||
16777216, 33554432, 67108864, 134217728, 268435456, 536870912, 1073741824,
|
||||
2147483648UL
|
||||
};
|
||||
|
||||
/* mpdecimal.c */
|
||||
const mpd_uint_t mpd_pow10[MPD_RDIGITS+1] = {
|
||||
1,10,100,1000,10000,100000,1000000,10000000,100000000,1000000000
|
||||
};
|
||||
|
||||
#else
|
||||
#error "CONFIG_64 or CONFIG_32 must be defined."
|
||||
#endif
|
||||
|
||||
const char *mpd_round_string[MPD_ROUND_GUARD] = {
|
||||
"ROUND_UP", /* round away from 0 */
|
||||
"ROUND_DOWN", /* round toward 0 (truncate) */
|
||||
"ROUND_CEILING", /* round toward +infinity */
|
||||
"ROUND_FLOOR", /* round toward -infinity */
|
||||
"ROUND_HALF_UP", /* 0.5 is rounded up */
|
||||
"ROUND_HALF_DOWN", /* 0.5 is rounded down */
|
||||
"ROUND_HALF_EVEN", /* 0.5 is rounded to even */
|
||||
"ROUND_05UP", /* round zero or five away from 0 */
|
||||
"ROUND_TRUNC", /* truncate, but set infinity */
|
||||
};
|
||||
|
||||
const char *mpd_clamp_string[MPD_CLAMP_GUARD] = {
|
||||
"CLAMP_DEFAULT",
|
||||
"CLAMP_IEEE_754"
|
||||
};
|
||||
|
||||
|
90
third_party/python/Modules/_decimal/libmpdec/constants.h
vendored
Normal file
90
third_party/python/Modules/_decimal/libmpdec/constants.h
vendored
Normal file
|
@ -0,0 +1,90 @@
|
|||
/*
|
||||
* Copyright (c) 2008-2016 Stefan Krah. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
|
||||
#ifndef CONSTANTS_H
|
||||
#define CONSTANTS_H
|
||||
|
||||
|
||||
#include "mpdecimal.h"
|
||||
|
||||
|
||||
/* Internal header file: all symbols have local scope in the DSO */
|
||||
MPD_PRAGMA(MPD_HIDE_SYMBOLS_START)
|
||||
|
||||
|
||||
/* choice of optimized functions */
|
||||
#if defined(CONFIG_64)
|
||||
/* x64 */
|
||||
#define MULMOD(a, b) x64_mulmod(a, b, umod)
|
||||
#define MULMOD2C(a0, a1, w) x64_mulmod2c(a0, a1, w, umod)
|
||||
#define MULMOD2(a0, b0, a1, b1) x64_mulmod2(a0, b0, a1, b1, umod)
|
||||
#define POWMOD(base, exp) x64_powmod(base, exp, umod)
|
||||
#define SETMODULUS(modnum) std_setmodulus(modnum, &umod)
|
||||
#define SIZE3_NTT(x0, x1, x2, w3table) std_size3_ntt(x0, x1, x2, w3table, umod)
|
||||
#elif defined(PPRO)
|
||||
/* PentiumPro (or later) gcc inline asm */
|
||||
#define MULMOD(a, b) ppro_mulmod(a, b, &dmod, dinvmod)
|
||||
#define MULMOD2C(a0, a1, w) ppro_mulmod2c(a0, a1, w, &dmod, dinvmod)
|
||||
#define MULMOD2(a0, b0, a1, b1) ppro_mulmod2(a0, b0, a1, b1, &dmod, dinvmod)
|
||||
#define POWMOD(base, exp) ppro_powmod(base, exp, &dmod, dinvmod)
|
||||
#define SETMODULUS(modnum) ppro_setmodulus(modnum, &umod, &dmod, dinvmod)
|
||||
#define SIZE3_NTT(x0, x1, x2, w3table) ppro_size3_ntt(x0, x1, x2, w3table, umod, &dmod, dinvmod)
|
||||
#else
|
||||
/* ANSI C99 */
|
||||
#define MULMOD(a, b) std_mulmod(a, b, umod)
|
||||
#define MULMOD2C(a0, a1, w) std_mulmod2c(a0, a1, w, umod)
|
||||
#define MULMOD2(a0, b0, a1, b1) std_mulmod2(a0, b0, a1, b1, umod)
|
||||
#define POWMOD(base, exp) std_powmod(base, exp, umod)
|
||||
#define SETMODULUS(modnum) std_setmodulus(modnum, &umod)
|
||||
#define SIZE3_NTT(x0, x1, x2, w3table) std_size3_ntt(x0, x1, x2, w3table, umod)
|
||||
#endif
|
||||
|
||||
/* PentiumPro (or later) gcc inline asm */
|
||||
extern const float MPD_TWO63;
|
||||
extern const uint32_t mpd_invmoduli[3][3];
|
||||
|
||||
enum {P1, P2, P3};
|
||||
|
||||
extern const mpd_uint_t mpd_moduli[];
|
||||
extern const mpd_uint_t mpd_roots[];
|
||||
extern const mpd_size_t mpd_bits[];
|
||||
extern const mpd_uint_t mpd_pow10[];
|
||||
|
||||
extern const mpd_uint_t INV_P1_MOD_P2;
|
||||
extern const mpd_uint_t INV_P1P2_MOD_P3;
|
||||
extern const mpd_uint_t LH_P1P2;
|
||||
extern const mpd_uint_t UH_P1P2;
|
||||
|
||||
|
||||
MPD_PRAGMA(MPD_HIDE_SYMBOLS_END) /* restore previous scope rules */
|
||||
|
||||
|
||||
#endif /* CONSTANTS_H */
|
||||
|
||||
|
||||
|
286
third_party/python/Modules/_decimal/libmpdec/context.c
vendored
Normal file
286
third_party/python/Modules/_decimal/libmpdec/context.c
vendored
Normal file
|
@ -0,0 +1,286 @@
|
|||
/*
|
||||
* Copyright (c) 2008-2016 Stefan Krah. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
|
||||
#include "mpdecimal.h"
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <signal.h>
|
||||
|
||||
|
||||
void
|
||||
mpd_dflt_traphandler(mpd_context_t *ctx UNUSED)
|
||||
{
|
||||
raise(SIGFPE);
|
||||
}
|
||||
|
||||
void (* mpd_traphandler)(mpd_context_t *) = mpd_dflt_traphandler;
|
||||
|
||||
|
||||
/* Set guaranteed minimum number of coefficient words. The function may
|
||||
be used once at program start. Setting MPD_MINALLOC to out-of-bounds
|
||||
values is a catastrophic error, so in that case the function exits rather
|
||||
than relying on the user to check a return value. */
|
||||
void
|
||||
mpd_setminalloc(mpd_ssize_t n)
|
||||
{
|
||||
static int minalloc_is_set = 0;
|
||||
|
||||
if (minalloc_is_set) {
|
||||
mpd_err_warn("mpd_setminalloc: ignoring request to set "
|
||||
"MPD_MINALLOC a second time\n");
|
||||
return;
|
||||
}
|
||||
if (n < MPD_MINALLOC_MIN || n > MPD_MINALLOC_MAX) {
|
||||
mpd_err_fatal("illegal value for MPD_MINALLOC"); /* GCOV_NOT_REACHED */
|
||||
}
|
||||
MPD_MINALLOC = n;
|
||||
minalloc_is_set = 1;
|
||||
}
|
||||
|
||||
void
|
||||
mpd_init(mpd_context_t *ctx, mpd_ssize_t prec)
|
||||
{
|
||||
mpd_ssize_t ideal_minalloc;
|
||||
|
||||
mpd_defaultcontext(ctx);
|
||||
|
||||
if (!mpd_qsetprec(ctx, prec)) {
|
||||
mpd_addstatus_raise(ctx, MPD_Invalid_context);
|
||||
return;
|
||||
}
|
||||
|
||||
ideal_minalloc = 2 * ((prec+MPD_RDIGITS-1) / MPD_RDIGITS);
|
||||
if (ideal_minalloc < MPD_MINALLOC_MIN) ideal_minalloc = MPD_MINALLOC_MIN;
|
||||
if (ideal_minalloc > MPD_MINALLOC_MAX) ideal_minalloc = MPD_MINALLOC_MAX;
|
||||
|
||||
mpd_setminalloc(ideal_minalloc);
|
||||
}
|
||||
|
||||
void
|
||||
mpd_maxcontext(mpd_context_t *ctx)
|
||||
{
|
||||
ctx->prec=MPD_MAX_PREC;
|
||||
ctx->emax=MPD_MAX_EMAX;
|
||||
ctx->emin=MPD_MIN_EMIN;
|
||||
ctx->round=MPD_ROUND_HALF_EVEN;
|
||||
ctx->traps=MPD_Traps;
|
||||
ctx->status=0;
|
||||
ctx->newtrap=0;
|
||||
ctx->clamp=0;
|
||||
ctx->allcr=1;
|
||||
}
|
||||
|
||||
void
|
||||
mpd_defaultcontext(mpd_context_t *ctx)
|
||||
{
|
||||
ctx->prec=2*MPD_RDIGITS;
|
||||
ctx->emax=MPD_MAX_EMAX;
|
||||
ctx->emin=MPD_MIN_EMIN;
|
||||
ctx->round=MPD_ROUND_HALF_UP;
|
||||
ctx->traps=MPD_Traps;
|
||||
ctx->status=0;
|
||||
ctx->newtrap=0;
|
||||
ctx->clamp=0;
|
||||
ctx->allcr=1;
|
||||
}
|
||||
|
||||
void
|
||||
mpd_basiccontext(mpd_context_t *ctx)
|
||||
{
|
||||
ctx->prec=9;
|
||||
ctx->emax=MPD_MAX_EMAX;
|
||||
ctx->emin=MPD_MIN_EMIN;
|
||||
ctx->round=MPD_ROUND_HALF_UP;
|
||||
ctx->traps=MPD_Traps|MPD_Clamped;
|
||||
ctx->status=0;
|
||||
ctx->newtrap=0;
|
||||
ctx->clamp=0;
|
||||
ctx->allcr=1;
|
||||
}
|
||||
|
||||
int
|
||||
mpd_ieee_context(mpd_context_t *ctx, int bits)
|
||||
{
|
||||
if (bits <= 0 || bits > MPD_IEEE_CONTEXT_MAX_BITS || bits % 32) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
ctx->prec = 9 * (bits/32) - 2;
|
||||
ctx->emax = 3 * ((mpd_ssize_t)1<<(bits/16+3));
|
||||
ctx->emin = 1 - ctx->emax;
|
||||
ctx->round=MPD_ROUND_HALF_EVEN;
|
||||
ctx->traps=0;
|
||||
ctx->status=0;
|
||||
ctx->newtrap=0;
|
||||
ctx->clamp=1;
|
||||
ctx->allcr=1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
mpd_ssize_t
|
||||
mpd_getprec(const mpd_context_t *ctx)
|
||||
{
|
||||
return ctx->prec;
|
||||
}
|
||||
|
||||
mpd_ssize_t
|
||||
mpd_getemax(const mpd_context_t *ctx)
|
||||
{
|
||||
return ctx->emax;
|
||||
}
|
||||
|
||||
mpd_ssize_t
|
||||
mpd_getemin(const mpd_context_t *ctx)
|
||||
{
|
||||
return ctx->emin;
|
||||
}
|
||||
|
||||
int
|
||||
mpd_getround(const mpd_context_t *ctx)
|
||||
{
|
||||
return ctx->round;
|
||||
}
|
||||
|
||||
uint32_t
|
||||
mpd_gettraps(const mpd_context_t *ctx)
|
||||
{
|
||||
return ctx->traps;
|
||||
}
|
||||
|
||||
uint32_t
|
||||
mpd_getstatus(const mpd_context_t *ctx)
|
||||
{
|
||||
return ctx->status;
|
||||
}
|
||||
|
||||
int
|
||||
mpd_getclamp(const mpd_context_t *ctx)
|
||||
{
|
||||
return ctx->clamp;
|
||||
}
|
||||
|
||||
int
|
||||
mpd_getcr(const mpd_context_t *ctx)
|
||||
{
|
||||
return ctx->allcr;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
mpd_qsetprec(mpd_context_t *ctx, mpd_ssize_t prec)
|
||||
{
|
||||
if (prec <= 0 || prec > MPD_MAX_PREC) {
|
||||
return 0;
|
||||
}
|
||||
ctx->prec = prec;
|
||||
return 1;
|
||||
}
|
||||
|
||||
int
|
||||
mpd_qsetemax(mpd_context_t *ctx, mpd_ssize_t emax)
|
||||
{
|
||||
if (emax < 0 || emax > MPD_MAX_EMAX) {
|
||||
return 0;
|
||||
}
|
||||
ctx->emax = emax;
|
||||
return 1;
|
||||
}
|
||||
|
||||
int
|
||||
mpd_qsetemin(mpd_context_t *ctx, mpd_ssize_t emin)
|
||||
{
|
||||
if (emin > 0 || emin < MPD_MIN_EMIN) {
|
||||
return 0;
|
||||
}
|
||||
ctx->emin = emin;
|
||||
return 1;
|
||||
}
|
||||
|
||||
int
|
||||
mpd_qsetround(mpd_context_t *ctx, int round)
|
||||
{
|
||||
if (!(0 <= round && round < MPD_ROUND_GUARD)) {
|
||||
return 0;
|
||||
}
|
||||
ctx->round = round;
|
||||
return 1;
|
||||
}
|
||||
|
||||
int
|
||||
mpd_qsettraps(mpd_context_t *ctx, uint32_t traps)
|
||||
{
|
||||
if (traps > MPD_Max_status) {
|
||||
return 0;
|
||||
}
|
||||
ctx->traps = traps;
|
||||
return 1;
|
||||
}
|
||||
|
||||
int
|
||||
mpd_qsetstatus(mpd_context_t *ctx, uint32_t flags)
|
||||
{
|
||||
if (flags > MPD_Max_status) {
|
||||
return 0;
|
||||
}
|
||||
ctx->status = flags;
|
||||
return 1;
|
||||
}
|
||||
|
||||
int
|
||||
mpd_qsetclamp(mpd_context_t *ctx, int c)
|
||||
{
|
||||
if (c != 0 && c != 1) {
|
||||
return 0;
|
||||
}
|
||||
ctx->clamp = c;
|
||||
return 1;
|
||||
}
|
||||
|
||||
int
|
||||
mpd_qsetcr(mpd_context_t *ctx, int c)
|
||||
{
|
||||
if (c != 0 && c != 1) {
|
||||
return 0;
|
||||
}
|
||||
ctx->allcr = c;
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
mpd_addstatus_raise(mpd_context_t *ctx, uint32_t flags)
|
||||
{
|
||||
ctx->status |= flags;
|
||||
if (flags&ctx->traps) {
|
||||
ctx->newtrap = (flags&ctx->traps);
|
||||
mpd_traphandler(ctx);
|
||||
}
|
||||
}
|
||||
|
||||
|
174
third_party/python/Modules/_decimal/libmpdec/convolute.c
vendored
Normal file
174
third_party/python/Modules/_decimal/libmpdec/convolute.c
vendored
Normal file
|
@ -0,0 +1,174 @@
|
|||
/*
|
||||
* Copyright (c) 2008-2016 Stefan Krah. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
|
||||
#include "mpdecimal.h"
|
||||
#include <stdio.h>
|
||||
#include "bits.h"
|
||||
#include "constants.h"
|
||||
#include "fnt.h"
|
||||
#include "fourstep.h"
|
||||
#include "numbertheory.h"
|
||||
#include "sixstep.h"
|
||||
#include "umodarith.h"
|
||||
#include "convolute.h"
|
||||
|
||||
|
||||
/* Bignum: Fast convolution using the Number Theoretic Transform. Used for
|
||||
the multiplication of very large coefficients. */
|
||||
|
||||
|
||||
/* Convolute the data in c1 and c2. Result is in c1. */
|
||||
int
|
||||
fnt_convolute(mpd_uint_t *c1, mpd_uint_t *c2, mpd_size_t n, int modnum)
|
||||
{
|
||||
int (*fnt)(mpd_uint_t *, mpd_size_t, int);
|
||||
int (*inv_fnt)(mpd_uint_t *, mpd_size_t, int);
|
||||
#ifdef PPRO
|
||||
double dmod;
|
||||
uint32_t dinvmod[3];
|
||||
#endif
|
||||
mpd_uint_t n_inv, umod;
|
||||
mpd_size_t i;
|
||||
|
||||
|
||||
SETMODULUS(modnum);
|
||||
n_inv = POWMOD(n, (umod-2));
|
||||
|
||||
if (ispower2(n)) {
|
||||
if (n > SIX_STEP_THRESHOLD) {
|
||||
fnt = six_step_fnt;
|
||||
inv_fnt = inv_six_step_fnt;
|
||||
}
|
||||
else {
|
||||
fnt = std_fnt;
|
||||
inv_fnt = std_inv_fnt;
|
||||
}
|
||||
}
|
||||
else {
|
||||
fnt = four_step_fnt;
|
||||
inv_fnt = inv_four_step_fnt;
|
||||
}
|
||||
|
||||
if (!fnt(c1, n, modnum)) {
|
||||
return 0;
|
||||
}
|
||||
if (!fnt(c2, n, modnum)) {
|
||||
return 0;
|
||||
}
|
||||
for (i = 0; i < n-1; i += 2) {
|
||||
mpd_uint_t x0 = c1[i];
|
||||
mpd_uint_t y0 = c2[i];
|
||||
mpd_uint_t x1 = c1[i+1];
|
||||
mpd_uint_t y1 = c2[i+1];
|
||||
MULMOD2(&x0, y0, &x1, y1);
|
||||
c1[i] = x0;
|
||||
c1[i+1] = x1;
|
||||
}
|
||||
|
||||
if (!inv_fnt(c1, n, modnum)) {
|
||||
return 0;
|
||||
}
|
||||
for (i = 0; i < n-3; i += 4) {
|
||||
mpd_uint_t x0 = c1[i];
|
||||
mpd_uint_t x1 = c1[i+1];
|
||||
mpd_uint_t x2 = c1[i+2];
|
||||
mpd_uint_t x3 = c1[i+3];
|
||||
MULMOD2C(&x0, &x1, n_inv);
|
||||
MULMOD2C(&x2, &x3, n_inv);
|
||||
c1[i] = x0;
|
||||
c1[i+1] = x1;
|
||||
c1[i+2] = x2;
|
||||
c1[i+3] = x3;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Autoconvolute the data in c1. Result is in c1. */
|
||||
int
|
||||
fnt_autoconvolute(mpd_uint_t *c1, mpd_size_t n, int modnum)
|
||||
{
|
||||
int (*fnt)(mpd_uint_t *, mpd_size_t, int);
|
||||
int (*inv_fnt)(mpd_uint_t *, mpd_size_t, int);
|
||||
#ifdef PPRO
|
||||
double dmod;
|
||||
uint32_t dinvmod[3];
|
||||
#endif
|
||||
mpd_uint_t n_inv, umod;
|
||||
mpd_size_t i;
|
||||
|
||||
|
||||
SETMODULUS(modnum);
|
||||
n_inv = POWMOD(n, (umod-2));
|
||||
|
||||
if (ispower2(n)) {
|
||||
if (n > SIX_STEP_THRESHOLD) {
|
||||
fnt = six_step_fnt;
|
||||
inv_fnt = inv_six_step_fnt;
|
||||
}
|
||||
else {
|
||||
fnt = std_fnt;
|
||||
inv_fnt = std_inv_fnt;
|
||||
}
|
||||
}
|
||||
else {
|
||||
fnt = four_step_fnt;
|
||||
inv_fnt = inv_four_step_fnt;
|
||||
}
|
||||
|
||||
if (!fnt(c1, n, modnum)) {
|
||||
return 0;
|
||||
}
|
||||
for (i = 0; i < n-1; i += 2) {
|
||||
mpd_uint_t x0 = c1[i];
|
||||
mpd_uint_t x1 = c1[i+1];
|
||||
MULMOD2(&x0, x0, &x1, x1);
|
||||
c1[i] = x0;
|
||||
c1[i+1] = x1;
|
||||
}
|
||||
|
||||
if (!inv_fnt(c1, n, modnum)) {
|
||||
return 0;
|
||||
}
|
||||
for (i = 0; i < n-3; i += 4) {
|
||||
mpd_uint_t x0 = c1[i];
|
||||
mpd_uint_t x1 = c1[i+1];
|
||||
mpd_uint_t x2 = c1[i+2];
|
||||
mpd_uint_t x3 = c1[i+3];
|
||||
MULMOD2C(&x0, &x1, n_inv);
|
||||
MULMOD2C(&x2, &x3, n_inv);
|
||||
c1[i] = x0;
|
||||
c1[i+1] = x1;
|
||||
c1[i+2] = x2;
|
||||
c1[i+3] = x3;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
50
third_party/python/Modules/_decimal/libmpdec/convolute.h
vendored
Normal file
50
third_party/python/Modules/_decimal/libmpdec/convolute.h
vendored
Normal file
|
@ -0,0 +1,50 @@
|
|||
/*
|
||||
* Copyright (c) 2008-2016 Stefan Krah. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
|
||||
#ifndef CONVOLUTE_H
|
||||
#define CONVOLUTE_H
|
||||
|
||||
|
||||
#include "mpdecimal.h"
|
||||
#include <stdio.h>
|
||||
|
||||
|
||||
/* Internal header file: all symbols have local scope in the DSO */
|
||||
MPD_PRAGMA(MPD_HIDE_SYMBOLS_START)
|
||||
|
||||
|
||||
#define SIX_STEP_THRESHOLD 4096
|
||||
|
||||
int fnt_convolute(mpd_uint_t *c1, mpd_uint_t *c2, mpd_size_t n, int modnum);
|
||||
int fnt_autoconvolute(mpd_uint_t *c1, mpd_size_t n, int modnum);
|
||||
|
||||
|
||||
MPD_PRAGMA(MPD_HIDE_SYMBOLS_END) /* restore previous scope rules */
|
||||
|
||||
|
||||
#endif
|
179
third_party/python/Modules/_decimal/libmpdec/crt.c
vendored
Normal file
179
third_party/python/Modules/_decimal/libmpdec/crt.c
vendored
Normal file
|
@ -0,0 +1,179 @@
|
|||
/*
|
||||
* Copyright (c) 2008-2016 Stefan Krah. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
|
||||
#include "mpdecimal.h"
|
||||
#include <stdio.h>
|
||||
#include <assert.h>
|
||||
#include "numbertheory.h"
|
||||
#include "umodarith.h"
|
||||
#include "crt.h"
|
||||
|
||||
|
||||
/* Bignum: Chinese Remainder Theorem, extends the maximum transform length. */
|
||||
|
||||
|
||||
/* Multiply P1P2 by v, store result in w. */
|
||||
static inline void
|
||||
_crt_mulP1P2_3(mpd_uint_t w[3], mpd_uint_t v)
|
||||
{
|
||||
mpd_uint_t hi1, hi2, lo;
|
||||
|
||||
_mpd_mul_words(&hi1, &lo, LH_P1P2, v);
|
||||
w[0] = lo;
|
||||
|
||||
_mpd_mul_words(&hi2, &lo, UH_P1P2, v);
|
||||
lo = hi1 + lo;
|
||||
if (lo < hi1) hi2++;
|
||||
|
||||
w[1] = lo;
|
||||
w[2] = hi2;
|
||||
}
|
||||
|
||||
/* Add 3 words from v to w. The result is known to fit in w. */
|
||||
static inline void
|
||||
_crt_add3(mpd_uint_t w[3], mpd_uint_t v[3])
|
||||
{
|
||||
mpd_uint_t carry;
|
||||
mpd_uint_t s;
|
||||
|
||||
s = w[0] + v[0];
|
||||
carry = (s < w[0]);
|
||||
w[0] = s;
|
||||
|
||||
s = w[1] + (v[1] + carry);
|
||||
carry = (s < w[1]);
|
||||
w[1] = s;
|
||||
|
||||
w[2] = w[2] + (v[2] + carry);
|
||||
}
|
||||
|
||||
/* Divide 3 words in u by v, store result in w, return remainder. */
|
||||
static inline mpd_uint_t
|
||||
_crt_div3(mpd_uint_t *w, const mpd_uint_t *u, mpd_uint_t v)
|
||||
{
|
||||
mpd_uint_t r1 = u[2];
|
||||
mpd_uint_t r2;
|
||||
|
||||
if (r1 < v) {
|
||||
w[2] = 0;
|
||||
}
|
||||
else {
|
||||
_mpd_div_word(&w[2], &r1, u[2], v); /* GCOV_NOT_REACHED */
|
||||
}
|
||||
|
||||
_mpd_div_words(&w[1], &r2, r1, u[1], v);
|
||||
_mpd_div_words(&w[0], &r1, r2, u[0], v);
|
||||
|
||||
return r1;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Chinese Remainder Theorem:
|
||||
* Algorithm from Joerg Arndt, "Matters Computational",
|
||||
* Chapter 37.4.1 [http://www.jjj.de/fxt/]
|
||||
*
|
||||
* See also Knuth, TAOCP, Volume 2, 4.3.2, exercise 7.
|
||||
*/
|
||||
|
||||
/*
|
||||
* CRT with carry: x1, x2, x3 contain numbers modulo p1, p2, p3. For each
|
||||
* triple of members of the arrays, find the unique z modulo p1*p2*p3, with
|
||||
* zmax = p1*p2*p3 - 1.
|
||||
*
|
||||
* In each iteration of the loop, split z into result[i] = z % MPD_RADIX
|
||||
* and carry = z / MPD_RADIX. Let N be the size of carry[] and cmax the
|
||||
* maximum carry.
|
||||
*
|
||||
* Limits for the 32-bit build:
|
||||
*
|
||||
* N = 2**96
|
||||
* cmax = 7711435591312380274
|
||||
*
|
||||
* Limits for the 64 bit build:
|
||||
*
|
||||
* N = 2**192
|
||||
* cmax = 627710135393475385904124401220046371710
|
||||
*
|
||||
* The following statements hold for both versions:
|
||||
*
|
||||
* 1) cmax + zmax < N, so the addition does not overflow.
|
||||
*
|
||||
* 2) (cmax + zmax) / MPD_RADIX == cmax.
|
||||
*
|
||||
* 3) If c <= cmax, then c_next = (c + zmax) / MPD_RADIX <= cmax.
|
||||
*/
|
||||
void
|
||||
crt3(mpd_uint_t *x1, mpd_uint_t *x2, mpd_uint_t *x3, mpd_size_t rsize)
|
||||
{
|
||||
mpd_uint_t p1 = mpd_moduli[P1];
|
||||
mpd_uint_t umod;
|
||||
#ifdef PPRO
|
||||
double dmod;
|
||||
uint32_t dinvmod[3];
|
||||
#endif
|
||||
mpd_uint_t a1, a2, a3;
|
||||
mpd_uint_t s;
|
||||
mpd_uint_t z[3], t[3];
|
||||
mpd_uint_t carry[3] = {0,0,0};
|
||||
mpd_uint_t hi, lo;
|
||||
mpd_size_t i;
|
||||
|
||||
for (i = 0; i < rsize; i++) {
|
||||
|
||||
a1 = x1[i];
|
||||
a2 = x2[i];
|
||||
a3 = x3[i];
|
||||
|
||||
SETMODULUS(P2);
|
||||
s = ext_submod(a2, a1, umod);
|
||||
s = MULMOD(s, INV_P1_MOD_P2);
|
||||
|
||||
_mpd_mul_words(&hi, &lo, s, p1);
|
||||
lo = lo + a1;
|
||||
if (lo < a1) hi++;
|
||||
|
||||
SETMODULUS(P3);
|
||||
s = dw_submod(a3, hi, lo, umod);
|
||||
s = MULMOD(s, INV_P1P2_MOD_P3);
|
||||
|
||||
z[0] = lo;
|
||||
z[1] = hi;
|
||||
z[2] = 0;
|
||||
|
||||
_crt_mulP1P2_3(t, s);
|
||||
_crt_add3(z, t);
|
||||
_crt_add3(carry, z);
|
||||
|
||||
x1[i] = _crt_div3(carry, carry, MPD_RADIX);
|
||||
}
|
||||
|
||||
assert(carry[0] == 0 && carry[1] == 0 && carry[2] == 0);
|
||||
}
|
||||
|
||||
|
47
third_party/python/Modules/_decimal/libmpdec/crt.h
vendored
Normal file
47
third_party/python/Modules/_decimal/libmpdec/crt.h
vendored
Normal file
|
@ -0,0 +1,47 @@
|
|||
/*
|
||||
* Copyright (c) 2008-2016 Stefan Krah. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
|
||||
#ifndef CRT_H
|
||||
#define CRT_H
|
||||
|
||||
|
||||
#include "mpdecimal.h"
|
||||
#include <stdio.h>
|
||||
|
||||
|
||||
/* Internal header file: all symbols have local scope in the DSO */
|
||||
MPD_PRAGMA(MPD_HIDE_SYMBOLS_START)
|
||||
|
||||
|
||||
void crt3(mpd_uint_t *x1, mpd_uint_t *x2, mpd_uint_t *x3, mpd_size_t nmemb);
|
||||
|
||||
|
||||
MPD_PRAGMA(MPD_HIDE_SYMBOLS_END) /* restore previous scope rules */
|
||||
|
||||
|
||||
#endif
|
173
third_party/python/Modules/_decimal/libmpdec/difradix2.c
vendored
Normal file
173
third_party/python/Modules/_decimal/libmpdec/difradix2.c
vendored
Normal file
|
@ -0,0 +1,173 @@
|
|||
/*
|
||||
* Copyright (c) 2008-2016 Stefan Krah. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
|
||||
#include "mpdecimal.h"
|
||||
#include <stdio.h>
|
||||
#include <assert.h>
|
||||
#include "bits.h"
|
||||
#include "numbertheory.h"
|
||||
#include "umodarith.h"
|
||||
#include "difradix2.h"
|
||||
|
||||
|
||||
/* Bignum: The actual transform routine (decimation in frequency). */
|
||||
|
||||
|
||||
/*
|
||||
* Generate index pairs (x, bitreverse(x)) and carry out the permutation.
|
||||
* n must be a power of two.
|
||||
* Algorithm due to Brent/Lehmann, see Joerg Arndt, "Matters Computational",
|
||||
* Chapter 1.14.4. [http://www.jjj.de/fxt/]
|
||||
*/
|
||||
static inline void
|
||||
bitreverse_permute(mpd_uint_t a[], mpd_size_t n)
|
||||
{
|
||||
mpd_size_t x = 0;
|
||||
mpd_size_t r = 0;
|
||||
mpd_uint_t t;
|
||||
|
||||
do { /* Invariant: r = bitreverse(x) */
|
||||
if (r > x) {
|
||||
t = a[x];
|
||||
a[x] = a[r];
|
||||
a[r] = t;
|
||||
}
|
||||
/* Flip trailing consecutive 1 bits and the first zero bit
|
||||
* that absorbs a possible carry. */
|
||||
x += 1;
|
||||
/* Mirror the operation on r: Flip n_trailing_zeros(x)+1
|
||||
high bits of r. */
|
||||
r ^= (n - (n >> (mpd_bsf(x)+1)));
|
||||
/* The loop invariant is preserved. */
|
||||
} while (x < n);
|
||||
}
|
||||
|
||||
|
||||
/* Fast Number Theoretic Transform, decimation in frequency. */
|
||||
void
|
||||
fnt_dif2(mpd_uint_t a[], mpd_size_t n, struct fnt_params *tparams)
|
||||
{
|
||||
mpd_uint_t *wtable = tparams->wtable;
|
||||
mpd_uint_t umod;
|
||||
#ifdef PPRO
|
||||
double dmod;
|
||||
uint32_t dinvmod[3];
|
||||
#endif
|
||||
mpd_uint_t u0, u1, v0, v1;
|
||||
mpd_uint_t w, w0, w1, wstep;
|
||||
mpd_size_t m, mhalf;
|
||||
mpd_size_t j, r;
|
||||
|
||||
|
||||
assert(ispower2(n));
|
||||
assert(n >= 4);
|
||||
|
||||
SETMODULUS(tparams->modnum);
|
||||
|
||||
/* m == n */
|
||||
mhalf = n / 2;
|
||||
for (j = 0; j < mhalf; j += 2) {
|
||||
|
||||
w0 = wtable[j];
|
||||
w1 = wtable[j+1];
|
||||
|
||||
u0 = a[j];
|
||||
v0 = a[j+mhalf];
|
||||
|
||||
u1 = a[j+1];
|
||||
v1 = a[j+1+mhalf];
|
||||
|
||||
a[j] = addmod(u0, v0, umod);
|
||||
v0 = submod(u0, v0, umod);
|
||||
|
||||
a[j+1] = addmod(u1, v1, umod);
|
||||
v1 = submod(u1, v1, umod);
|
||||
|
||||
MULMOD2(&v0, w0, &v1, w1);
|
||||
|
||||
a[j+mhalf] = v0;
|
||||
a[j+1+mhalf] = v1;
|
||||
|
||||
}
|
||||
|
||||
wstep = 2;
|
||||
for (m = n/2; m >= 2; m>>=1, wstep<<=1) {
|
||||
|
||||
mhalf = m / 2;
|
||||
|
||||
/* j == 0 */
|
||||
for (r = 0; r < n; r += 2*m) {
|
||||
|
||||
u0 = a[r];
|
||||
v0 = a[r+mhalf];
|
||||
|
||||
u1 = a[m+r];
|
||||
v1 = a[m+r+mhalf];
|
||||
|
||||
a[r] = addmod(u0, v0, umod);
|
||||
v0 = submod(u0, v0, umod);
|
||||
|
||||
a[m+r] = addmod(u1, v1, umod);
|
||||
v1 = submod(u1, v1, umod);
|
||||
|
||||
a[r+mhalf] = v0;
|
||||
a[m+r+mhalf] = v1;
|
||||
}
|
||||
|
||||
for (j = 1; j < mhalf; j++) {
|
||||
|
||||
w = wtable[j*wstep];
|
||||
|
||||
for (r = 0; r < n; r += 2*m) {
|
||||
|
||||
u0 = a[r+j];
|
||||
v0 = a[r+j+mhalf];
|
||||
|
||||
u1 = a[m+r+j];
|
||||
v1 = a[m+r+j+mhalf];
|
||||
|
||||
a[r+j] = addmod(u0, v0, umod);
|
||||
v0 = submod(u0, v0, umod);
|
||||
|
||||
a[m+r+j] = addmod(u1, v1, umod);
|
||||
v1 = submod(u1, v1, umod);
|
||||
|
||||
MULMOD2C(&v0, &v1, w);
|
||||
|
||||
a[r+j+mhalf] = v0;
|
||||
a[m+r+j+mhalf] = v1;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
bitreverse_permute(a, n);
|
||||
}
|
||||
|
||||
|
48
third_party/python/Modules/_decimal/libmpdec/difradix2.h
vendored
Normal file
48
third_party/python/Modules/_decimal/libmpdec/difradix2.h
vendored
Normal file
|
@ -0,0 +1,48 @@
|
|||
/*
|
||||
* Copyright (c) 2008-2016 Stefan Krah. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
|
||||
#ifndef DIF_RADIX2_H
|
||||
#define DIF_RADIX2_H
|
||||
|
||||
|
||||
#include "mpdecimal.h"
|
||||
#include <stdio.h>
|
||||
#include "numbertheory.h"
|
||||
|
||||
|
||||
/* Internal header file: all symbols have local scope in the DSO */
|
||||
MPD_PRAGMA(MPD_HIDE_SYMBOLS_START)
|
||||
|
||||
|
||||
void fnt_dif2(mpd_uint_t a[], mpd_size_t n, struct fnt_params *tparams);
|
||||
|
||||
|
||||
MPD_PRAGMA(MPD_HIDE_SYMBOLS_END) /* restore previous scope rules */
|
||||
|
||||
|
||||
#endif
|
81
third_party/python/Modules/_decimal/libmpdec/fnt.c
vendored
Normal file
81
third_party/python/Modules/_decimal/libmpdec/fnt.c
vendored
Normal file
|
@ -0,0 +1,81 @@
|
|||
/*
|
||||
* Copyright (c) 2008-2016 Stefan Krah. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
|
||||
#include "mpdecimal.h"
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <assert.h>
|
||||
#include "bits.h"
|
||||
#include "difradix2.h"
|
||||
#include "numbertheory.h"
|
||||
#include "fnt.h"
|
||||
|
||||
|
||||
/* Bignum: Fast transform for medium-sized coefficients. */
|
||||
|
||||
|
||||
/* forward transform, sign = -1 */
|
||||
int
|
||||
std_fnt(mpd_uint_t *a, mpd_size_t n, int modnum)
|
||||
{
|
||||
struct fnt_params *tparams;
|
||||
|
||||
assert(ispower2(n));
|
||||
assert(n >= 4);
|
||||
assert(n <= 3*MPD_MAXTRANSFORM_2N);
|
||||
|
||||
if ((tparams = _mpd_init_fnt_params(n, -1, modnum)) == NULL) {
|
||||
return 0;
|
||||
}
|
||||
fnt_dif2(a, n, tparams);
|
||||
|
||||
mpd_free(tparams);
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* reverse transform, sign = 1 */
|
||||
int
|
||||
std_inv_fnt(mpd_uint_t *a, mpd_size_t n, int modnum)
|
||||
{
|
||||
struct fnt_params *tparams;
|
||||
|
||||
assert(ispower2(n));
|
||||
assert(n >= 4);
|
||||
assert(n <= 3*MPD_MAXTRANSFORM_2N);
|
||||
|
||||
if ((tparams = _mpd_init_fnt_params(n, 1, modnum)) == NULL) {
|
||||
return 0;
|
||||
}
|
||||
fnt_dif2(a, n, tparams);
|
||||
|
||||
mpd_free(tparams);
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
|
49
third_party/python/Modules/_decimal/libmpdec/fnt.h
vendored
Normal file
49
third_party/python/Modules/_decimal/libmpdec/fnt.h
vendored
Normal file
|
@ -0,0 +1,49 @@
|
|||
/*
|
||||
* Copyright (c) 2008-2016 Stefan Krah. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
|
||||
#ifndef FNT_H
|
||||
#define FNT_H
|
||||
|
||||
|
||||
#include "mpdecimal.h"
|
||||
#include <stdio.h>
|
||||
|
||||
|
||||
/* Internal header file: all symbols have local scope in the DSO */
|
||||
MPD_PRAGMA(MPD_HIDE_SYMBOLS_START)
|
||||
|
||||
|
||||
int std_fnt(mpd_uint_t a[], mpd_size_t n, int modnum);
|
||||
int std_inv_fnt(mpd_uint_t a[], mpd_size_t n, int modnum);
|
||||
|
||||
|
||||
MPD_PRAGMA(MPD_HIDE_SYMBOLS_END) /* restore previous scope rules */
|
||||
|
||||
|
||||
#endif
|
||||
|
257
third_party/python/Modules/_decimal/libmpdec/fourstep.c
vendored
Normal file
257
third_party/python/Modules/_decimal/libmpdec/fourstep.c
vendored
Normal file
|
@ -0,0 +1,257 @@
|
|||
/*
|
||||
* Copyright (c) 2008-2016 Stefan Krah. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
|
||||
#include "mpdecimal.h"
|
||||
#include <assert.h>
|
||||
#include "numbertheory.h"
|
||||
#include "sixstep.h"
|
||||
#include "transpose.h"
|
||||
#include "umodarith.h"
|
||||
#include "fourstep.h"
|
||||
|
||||
|
||||
/* Bignum: Cache efficient Matrix Fourier Transform for arrays of the
|
||||
form 3 * 2**n (See literature/matrix-transform.txt). */
|
||||
|
||||
|
||||
#ifndef PPRO
|
||||
static inline void
|
||||
std_size3_ntt(mpd_uint_t *x1, mpd_uint_t *x2, mpd_uint_t *x3,
|
||||
mpd_uint_t w3table[3], mpd_uint_t umod)
|
||||
{
|
||||
mpd_uint_t r1, r2;
|
||||
mpd_uint_t w;
|
||||
mpd_uint_t s, tmp;
|
||||
|
||||
|
||||
/* k = 0 -> w = 1 */
|
||||
s = *x1;
|
||||
s = addmod(s, *x2, umod);
|
||||
s = addmod(s, *x3, umod);
|
||||
|
||||
r1 = s;
|
||||
|
||||
/* k = 1 */
|
||||
s = *x1;
|
||||
|
||||
w = w3table[1];
|
||||
tmp = MULMOD(*x2, w);
|
||||
s = addmod(s, tmp, umod);
|
||||
|
||||
w = w3table[2];
|
||||
tmp = MULMOD(*x3, w);
|
||||
s = addmod(s, tmp, umod);
|
||||
|
||||
r2 = s;
|
||||
|
||||
/* k = 2 */
|
||||
s = *x1;
|
||||
|
||||
w = w3table[2];
|
||||
tmp = MULMOD(*x2, w);
|
||||
s = addmod(s, tmp, umod);
|
||||
|
||||
w = w3table[1];
|
||||
tmp = MULMOD(*x3, w);
|
||||
s = addmod(s, tmp, umod);
|
||||
|
||||
*x3 = s;
|
||||
*x2 = r2;
|
||||
*x1 = r1;
|
||||
}
|
||||
#else /* PPRO */
|
||||
static inline void
|
||||
ppro_size3_ntt(mpd_uint_t *x1, mpd_uint_t *x2, mpd_uint_t *x3, mpd_uint_t w3table[3],
|
||||
mpd_uint_t umod, double *dmod, uint32_t dinvmod[3])
|
||||
{
|
||||
mpd_uint_t r1, r2;
|
||||
mpd_uint_t w;
|
||||
mpd_uint_t s, tmp;
|
||||
|
||||
|
||||
/* k = 0 -> w = 1 */
|
||||
s = *x1;
|
||||
s = addmod(s, *x2, umod);
|
||||
s = addmod(s, *x3, umod);
|
||||
|
||||
r1 = s;
|
||||
|
||||
/* k = 1 */
|
||||
s = *x1;
|
||||
|
||||
w = w3table[1];
|
||||
tmp = ppro_mulmod(*x2, w, dmod, dinvmod);
|
||||
s = addmod(s, tmp, umod);
|
||||
|
||||
w = w3table[2];
|
||||
tmp = ppro_mulmod(*x3, w, dmod, dinvmod);
|
||||
s = addmod(s, tmp, umod);
|
||||
|
||||
r2 = s;
|
||||
|
||||
/* k = 2 */
|
||||
s = *x1;
|
||||
|
||||
w = w3table[2];
|
||||
tmp = ppro_mulmod(*x2, w, dmod, dinvmod);
|
||||
s = addmod(s, tmp, umod);
|
||||
|
||||
w = w3table[1];
|
||||
tmp = ppro_mulmod(*x3, w, dmod, dinvmod);
|
||||
s = addmod(s, tmp, umod);
|
||||
|
||||
*x3 = s;
|
||||
*x2 = r2;
|
||||
*x1 = r1;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
/* forward transform, sign = -1; transform length = 3 * 2**n */
|
||||
int
|
||||
four_step_fnt(mpd_uint_t *a, mpd_size_t n, int modnum)
|
||||
{
|
||||
mpd_size_t R = 3; /* number of rows */
|
||||
mpd_size_t C = n / 3; /* number of columns */
|
||||
mpd_uint_t w3table[3];
|
||||
mpd_uint_t kernel, w0, w1, wstep;
|
||||
mpd_uint_t *s, *p0, *p1, *p2;
|
||||
mpd_uint_t umod;
|
||||
#ifdef PPRO
|
||||
double dmod;
|
||||
uint32_t dinvmod[3];
|
||||
#endif
|
||||
mpd_size_t i, k;
|
||||
|
||||
|
||||
assert(n >= 48);
|
||||
assert(n <= 3*MPD_MAXTRANSFORM_2N);
|
||||
|
||||
|
||||
/* Length R transform on the columns. */
|
||||
SETMODULUS(modnum);
|
||||
_mpd_init_w3table(w3table, -1, modnum);
|
||||
for (p0=a, p1=p0+C, p2=p0+2*C; p0<a+C; p0++,p1++,p2++) {
|
||||
|
||||
SIZE3_NTT(p0, p1, p2, w3table);
|
||||
}
|
||||
|
||||
/* Multiply each matrix element (addressed by i*C+k) by r**(i*k). */
|
||||
kernel = _mpd_getkernel(n, -1, modnum);
|
||||
for (i = 1; i < R; i++) {
|
||||
w0 = 1; /* r**(i*0): initial value for k=0 */
|
||||
w1 = POWMOD(kernel, i); /* r**(i*1): initial value for k=1 */
|
||||
wstep = MULMOD(w1, w1); /* r**(2*i) */
|
||||
for (k = 0; k < C-1; k += 2) {
|
||||
mpd_uint_t x0 = a[i*C+k];
|
||||
mpd_uint_t x1 = a[i*C+k+1];
|
||||
MULMOD2(&x0, w0, &x1, w1);
|
||||
MULMOD2C(&w0, &w1, wstep); /* r**(i*(k+2)) = r**(i*k) * r**(2*i) */
|
||||
a[i*C+k] = x0;
|
||||
a[i*C+k+1] = x1;
|
||||
}
|
||||
}
|
||||
|
||||
/* Length C transform on the rows. */
|
||||
for (s = a; s < a+n; s += C) {
|
||||
if (!six_step_fnt(s, C, modnum)) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
#if 0
|
||||
/* An unordered transform is sufficient for convolution. */
|
||||
/* Transpose the matrix. */
|
||||
transpose_3xpow2(a, R, C);
|
||||
#endif
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* backward transform, sign = 1; transform length = 3 * 2**n */
|
||||
int
|
||||
inv_four_step_fnt(mpd_uint_t *a, mpd_size_t n, int modnum)
|
||||
{
|
||||
mpd_size_t R = 3; /* number of rows */
|
||||
mpd_size_t C = n / 3; /* number of columns */
|
||||
mpd_uint_t w3table[3];
|
||||
mpd_uint_t kernel, w0, w1, wstep;
|
||||
mpd_uint_t *s, *p0, *p1, *p2;
|
||||
mpd_uint_t umod;
|
||||
#ifdef PPRO
|
||||
double dmod;
|
||||
uint32_t dinvmod[3];
|
||||
#endif
|
||||
mpd_size_t i, k;
|
||||
|
||||
|
||||
assert(n >= 48);
|
||||
assert(n <= 3*MPD_MAXTRANSFORM_2N);
|
||||
|
||||
|
||||
#if 0
|
||||
/* An unordered transform is sufficient for convolution. */
|
||||
/* Transpose the matrix, producing an R*C matrix. */
|
||||
transpose_3xpow2(a, C, R);
|
||||
#endif
|
||||
|
||||
/* Length C transform on the rows. */
|
||||
for (s = a; s < a+n; s += C) {
|
||||
if (!inv_six_step_fnt(s, C, modnum)) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
/* Multiply each matrix element (addressed by i*C+k) by r**(i*k). */
|
||||
SETMODULUS(modnum);
|
||||
kernel = _mpd_getkernel(n, 1, modnum);
|
||||
for (i = 1; i < R; i++) {
|
||||
w0 = 1;
|
||||
w1 = POWMOD(kernel, i);
|
||||
wstep = MULMOD(w1, w1);
|
||||
for (k = 0; k < C; k += 2) {
|
||||
mpd_uint_t x0 = a[i*C+k];
|
||||
mpd_uint_t x1 = a[i*C+k+1];
|
||||
MULMOD2(&x0, w0, &x1, w1);
|
||||
MULMOD2C(&w0, &w1, wstep);
|
||||
a[i*C+k] = x0;
|
||||
a[i*C+k+1] = x1;
|
||||
}
|
||||
}
|
||||
|
||||
/* Length R transform on the columns. */
|
||||
_mpd_init_w3table(w3table, 1, modnum);
|
||||
for (p0=a, p1=p0+C, p2=p0+2*C; p0<a+C; p0++,p1++,p2++) {
|
||||
|
||||
SIZE3_NTT(p0, p1, p2, w3table);
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
48
third_party/python/Modules/_decimal/libmpdec/fourstep.h
vendored
Normal file
48
third_party/python/Modules/_decimal/libmpdec/fourstep.h
vendored
Normal file
|
@ -0,0 +1,48 @@
|
|||
/*
|
||||
* Copyright (c) 2008-2016 Stefan Krah. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
|
||||
#ifndef FOUR_STEP_H
|
||||
#define FOUR_STEP_H
|
||||
|
||||
|
||||
#include "mpdecimal.h"
|
||||
#include <stdio.h>
|
||||
|
||||
|
||||
/* Internal header file: all symbols have local scope in the DSO */
|
||||
MPD_PRAGMA(MPD_HIDE_SYMBOLS_START)
|
||||
|
||||
|
||||
int four_step_fnt(mpd_uint_t *a, mpd_size_t n, int modnum);
|
||||
int inv_four_step_fnt(mpd_uint_t *a, mpd_size_t n, int modnum);
|
||||
|
||||
|
||||
MPD_PRAGMA(MPD_HIDE_SYMBOLS_END) /* restore previous scope rules */
|
||||
|
||||
|
||||
#endif
|
1583
third_party/python/Modules/_decimal/libmpdec/io.c
vendored
Normal file
1583
third_party/python/Modules/_decimal/libmpdec/io.c
vendored
Normal file
File diff suppressed because it is too large
Load diff
59
third_party/python/Modules/_decimal/libmpdec/io.h
vendored
Normal file
59
third_party/python/Modules/_decimal/libmpdec/io.h
vendored
Normal file
|
@ -0,0 +1,59 @@
|
|||
/*
|
||||
* Copyright (c) 2008-2016 Stefan Krah. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
|
||||
#ifndef IO_H
|
||||
#define IO_H
|
||||
|
||||
|
||||
#include <errno.h>
|
||||
#include "mpdecimal.h"
|
||||
|
||||
|
||||
#if SIZE_MAX == MPD_SIZE_MAX
|
||||
#define mpd_strtossize _mpd_strtossize
|
||||
#else
|
||||
static inline mpd_ssize_t
|
||||
mpd_strtossize(const char *s, char **end, int base)
|
||||
{
|
||||
int64_t retval;
|
||||
|
||||
errno = 0;
|
||||
retval = _mpd_strtossize(s, end, base);
|
||||
if (errno == 0 && (retval > MPD_SSIZE_MAX || retval < MPD_SSIZE_MIN)) {
|
||||
errno = ERANGE;
|
||||
}
|
||||
if (errno == ERANGE) {
|
||||
return (retval < 0) ? MPD_SSIZE_MIN : MPD_SSIZE_MAX;
|
||||
}
|
||||
|
||||
return (mpd_ssize_t)retval;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
#endif
|
51
third_party/python/Modules/_decimal/libmpdec/literature/REFERENCES.txt
vendored
Normal file
51
third_party/python/Modules/_decimal/libmpdec/literature/REFERENCES.txt
vendored
Normal file
|
@ -0,0 +1,51 @@
|
|||
|
||||
|
||||
This document contains links to the literature used in the process of
|
||||
creating the library. The list is probably not complete.
|
||||
|
||||
|
||||
Mike Cowlishaw: General Decimal Arithmetic Specification
|
||||
http://speleotrove.com/decimal/decarith.html
|
||||
|
||||
|
||||
Jean-Michel Muller: On the definition of ulp (x)
|
||||
lara.inist.fr/bitstream/2332/518/1/LIP-RR2005-09.pdf
|
||||
|
||||
|
||||
T. E. Hull, A. Abrham: Properly rounded variable precision square root
|
||||
http://portal.acm.org/citation.cfm?id=214413
|
||||
|
||||
|
||||
T. E. Hull, A. Abrham: Variable precision exponential function
|
||||
http://portal.acm.org/citation.cfm?id=6498
|
||||
|
||||
|
||||
Roman E. Maeder: Storage allocation for the Karatsuba integer multiplication
|
||||
algorithm. http://www.springerlink.com/content/w15058mj6v59t565/
|
||||
|
||||
|
||||
J. M. Pollard: The fast Fourier transform in a finite field
|
||||
http://www.ams.org/journals/mcom/1971-25-114/S0025-5718-1971-0301966-0/home.html
|
||||
|
||||
|
||||
David H. Bailey: FFTs in External or Hierarchical Memory
|
||||
http://crd.lbl.gov/~dhbailey/dhbpapers/
|
||||
|
||||
|
||||
W. Morven Gentleman: Matrix Multiplication and Fast Fourier Transforms
|
||||
http://www.alcatel-lucent.com/bstj/vol47-1968/articles/bstj47-6-1099.pdf
|
||||
|
||||
|
||||
Mikko Tommila: Apfloat documentation
|
||||
http://www.apfloat.org/apfloat/2.41/apfloat.pdf
|
||||
|
||||
|
||||
Joerg Arndt: "Matters Computational"
|
||||
http://www.jjj.de/fxt/
|
||||
|
||||
|
||||
Karl Hasselstrom: Fast Division of Large Integers
|
||||
www.treskal.com/kalle/exjobb/original-report.pdf
|
||||
|
||||
|
||||
|
83
third_party/python/Modules/_decimal/libmpdec/literature/bignum.txt
vendored
Normal file
83
third_party/python/Modules/_decimal/libmpdec/literature/bignum.txt
vendored
Normal file
|
@ -0,0 +1,83 @@
|
|||
|
||||
|
||||
Bignum support (Fast Number Theoretic Transform or FNT):
|
||||
========================================================
|
||||
|
||||
Bignum arithmetic in libmpdec uses the scheme for fast convolution
|
||||
of integer sequences from:
|
||||
|
||||
J. M. Pollard: The fast Fourier transform in a finite field
|
||||
http://www.ams.org/journals/mcom/1971-25-114/S0025-5718-1971-0301966-0/home.html
|
||||
|
||||
|
||||
The transform in a finite field can be used for convolution in the same
|
||||
way as the Fourier Transform. The main advantages of the Number Theoretic
|
||||
Transform are that it is both exact and very memory efficient.
|
||||
|
||||
|
||||
Convolution in pseudo-code:
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
fnt_convolute(a, b):
|
||||
x = fnt(a) # forward transform of a
|
||||
y = fnt(b) # forward transform of b
|
||||
z = pairwise multiply x[i] and y[i]
|
||||
result = inv_fnt(z) # backward transform of z.
|
||||
|
||||
|
||||
Extending the maximum transform length (Chinese Remainder Theorem):
|
||||
-------------------------------------------------------------------
|
||||
|
||||
The maximum transform length is quite limited when using a single
|
||||
prime field. However, it is possible to use multiple primes and
|
||||
recover the result using the Chinese Remainder Theorem.
|
||||
|
||||
|
||||
Multiplication in pseudo-code:
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
_mpd_fntmul(u, v):
|
||||
c1 = fnt_convolute(u, v, P1) # convolute modulo prime1
|
||||
c2 = fnt_convolute(u, v, P2) # convolute modulo prime2
|
||||
c3 = fnt_convolute(u, v, P3) # convolute modulo prime3
|
||||
result = crt3(c1, c2, c3) # Chinese Remainder Theorem
|
||||
|
||||
|
||||
Optimized transform functions:
|
||||
------------------------------
|
||||
|
||||
There are three different fnt() functions:
|
||||
|
||||
std_fnt: "standard" decimation in frequency transform for array lengths
|
||||
of 2**n. Performs well up to 1024 words.
|
||||
|
||||
sixstep: Cache-friendly algorithm for array lengths of 2**n. Outperforms
|
||||
std_fnt for large arrays.
|
||||
|
||||
fourstep: Algorithm for array lengths of 3 * 2**n. Also cache friendly
|
||||
in large parts.
|
||||
|
||||
|
||||
List of bignum-only files:
|
||||
--------------------------
|
||||
|
||||
Functions from these files are only used in _mpd_fntmul().
|
||||
|
||||
umodarith.h -> fast low level routines for unsigned modular arithmetic
|
||||
numbertheory.c -> routines for setting up the FNT
|
||||
difradix2.c -> decimation in frequency transform, used as the
|
||||
"base case" by the following three files:
|
||||
|
||||
fnt.c -> standard transform for smaller arrays
|
||||
sixstep.c -> transform large arrays of length 2**n
|
||||
fourstep.c -> transform arrays of length 3 * 2**n
|
||||
|
||||
convolute.c -> do the actual fast convolution, using one of
|
||||
the three transform functions.
|
||||
transpose.c -> transpositions needed for the sixstep algorithm.
|
||||
crt.c -> Chinese Remainder Theorem: use information from three
|
||||
transforms modulo three different primes to get the
|
||||
final result.
|
||||
|
||||
|
||||
|
208
third_party/python/Modules/_decimal/libmpdec/literature/fnt.py
vendored
Normal file
208
third_party/python/Modules/_decimal/libmpdec/literature/fnt.py
vendored
Normal file
|
@ -0,0 +1,208 @@
|
|||
#
|
||||
# Copyright (c) 2008-2016 Stefan Krah. All rights reserved.
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without
|
||||
# modification, are permitted provided that the following conditions
|
||||
# are met:
|
||||
#
|
||||
# 1. Redistributions of source code must retain the above copyright
|
||||
# notice, this list of conditions and the following disclaimer.
|
||||
#
|
||||
# 2. Redistributions in binary form must reproduce the above copyright
|
||||
# notice, this list of conditions and the following disclaimer in the
|
||||
# documentation and/or other materials provided with the distribution.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS "AS IS" AND
|
||||
# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
# SUCH DAMAGE.
|
||||
#
|
||||
|
||||
|
||||
######################################################################
|
||||
# This file lists and checks some of the constants and limits used #
|
||||
# in libmpdec's Number Theoretic Transform. At the end of the file #
|
||||
# there is an example function for the plain DFT transform. #
|
||||
######################################################################
|
||||
|
||||
|
||||
#
|
||||
# Number theoretic transforms are done in subfields of F(p). P[i]
|
||||
# are the primes, D[i] = P[i] - 1 are highly composite and w[i]
|
||||
# are the respective primitive roots of F(p).
|
||||
#
|
||||
# The strategy is to convolute two coefficients modulo all three
|
||||
# primes, then use the Chinese Remainder Theorem on the three
|
||||
# result arrays to recover the result in the usual base RADIX
|
||||
# form.
|
||||
#
|
||||
|
||||
# ======================================================================
|
||||
# Primitive roots
|
||||
# ======================================================================
|
||||
|
||||
#
|
||||
# Verify primitive roots:
|
||||
#
|
||||
# For a prime field, r is a primitive root if and only if for all prime
|
||||
# factors f of p-1, r**((p-1)/f) =/= 1 (mod p).
|
||||
#
|
||||
def prod(F, E):
|
||||
"""Check that the factorization of P-1 is correct. F is the list of
|
||||
factors of P-1, E lists the number of occurrences of each factor."""
|
||||
x = 1
|
||||
for y, z in zip(F, E):
|
||||
x *= y**z
|
||||
return x
|
||||
|
||||
def is_primitive_root(r, p, factors, exponents):
|
||||
"""Check if r is a primitive root of F(p)."""
|
||||
if p != prod(factors, exponents) + 1:
|
||||
return False
|
||||
for f in factors:
|
||||
q, control = divmod(p-1, f)
|
||||
if control != 0:
|
||||
return False
|
||||
if pow(r, q, p) == 1:
|
||||
return False
|
||||
return True
|
||||
|
||||
|
||||
# =================================================================
|
||||
# Constants and limits for the 64-bit version
|
||||
# =================================================================
|
||||
|
||||
RADIX = 10**19
|
||||
|
||||
# Primes P1, P2 and P3:
|
||||
P = [2**64-2**32+1, 2**64-2**34+1, 2**64-2**40+1]
|
||||
|
||||
# P-1, highly composite. The transform length d is variable and
|
||||
# must divide D = P-1. Since all D are divisible by 3 * 2**32,
|
||||
# transform lengths can be 2**n or 3 * 2**n (where n <= 32).
|
||||
D = [2**32 * 3 * (5 * 17 * 257 * 65537),
|
||||
2**34 * 3**2 * (7 * 11 * 31 * 151 * 331),
|
||||
2**40 * 3**2 * (5 * 7 * 13 * 17 * 241)]
|
||||
|
||||
# Prime factors of P-1 and their exponents:
|
||||
F = [(2,3,5,17,257,65537), (2,3,7,11,31,151,331), (2,3,5,7,13,17,241)]
|
||||
E = [(32,1,1,1,1,1), (34,2,1,1,1,1,1), (40,2,1,1,1,1,1)]
|
||||
|
||||
# Maximum transform length for 2**n. Above that only 3 * 2**31
|
||||
# or 3 * 2**32 are possible.
|
||||
MPD_MAXTRANSFORM_2N = 2**32
|
||||
|
||||
|
||||
# Limits in the terminology of Pollard's paper:
|
||||
m2 = (MPD_MAXTRANSFORM_2N * 3) // 2 # Maximum length of the smaller array.
|
||||
M1 = M2 = RADIX-1 # Maximum value per single word.
|
||||
L = m2 * M1 * M2
|
||||
P[0] * P[1] * P[2] > 2 * L
|
||||
|
||||
|
||||
# Primitive roots of F(P1), F(P2) and F(P3):
|
||||
w = [7, 10, 19]
|
||||
|
||||
# The primitive roots are correct:
|
||||
for i in range(3):
|
||||
if not is_primitive_root(w[i], P[i], F[i], E[i]):
|
||||
print("FAIL")
|
||||
|
||||
|
||||
# =================================================================
|
||||
# Constants and limits for the 32-bit version
|
||||
# =================================================================
|
||||
|
||||
RADIX = 10**9
|
||||
|
||||
# Primes P1, P2 and P3:
|
||||
P = [2113929217, 2013265921, 1811939329]
|
||||
|
||||
# P-1, highly composite. All D = P-1 are divisible by 3 * 2**25,
|
||||
# allowing for transform lengths up to 3 * 2**25 words.
|
||||
D = [2**25 * 3**2 * 7,
|
||||
2**27 * 3 * 5,
|
||||
2**26 * 3**3]
|
||||
|
||||
# Prime factors of P-1 and their exponents:
|
||||
F = [(2,3,7), (2,3,5), (2,3)]
|
||||
E = [(25,2,1), (27,1,1), (26,3)]
|
||||
|
||||
# Maximum transform length for 2**n. Above that only 3 * 2**24 or
|
||||
# 3 * 2**25 are possible.
|
||||
MPD_MAXTRANSFORM_2N = 2**25
|
||||
|
||||
|
||||
# Limits in the terminology of Pollard's paper:
|
||||
m2 = (MPD_MAXTRANSFORM_2N * 3) // 2 # Maximum length of the smaller array.
|
||||
M1 = M2 = RADIX-1 # Maximum value per single word.
|
||||
L = m2 * M1 * M2
|
||||
P[0] * P[1] * P[2] > 2 * L
|
||||
|
||||
|
||||
# Primitive roots of F(P1), F(P2) and F(P3):
|
||||
w = [5, 31, 13]
|
||||
|
||||
# The primitive roots are correct:
|
||||
for i in range(3):
|
||||
if not is_primitive_root(w[i], P[i], F[i], E[i]):
|
||||
print("FAIL")
|
||||
|
||||
|
||||
# ======================================================================
|
||||
# Example transform using a single prime
|
||||
# ======================================================================
|
||||
|
||||
def ntt(lst, dir):
|
||||
"""Perform a transform on the elements of lst. len(lst) must
|
||||
be 2**n or 3 * 2**n, where n <= 25. This is the slow DFT."""
|
||||
p = 2113929217 # prime
|
||||
d = len(lst) # transform length
|
||||
d_prime = pow(d, (p-2), p) # inverse of d
|
||||
xi = (p-1)//d
|
||||
w = 5 # primitive root of F(p)
|
||||
r = pow(w, xi, p) # primitive root of the subfield
|
||||
r_prime = pow(w, (p-1-xi), p) # inverse of r
|
||||
if dir == 1: # forward transform
|
||||
a = lst # input array
|
||||
A = [0] * d # transformed values
|
||||
for i in range(d):
|
||||
s = 0
|
||||
for j in range(d):
|
||||
s += a[j] * pow(r, i*j, p)
|
||||
A[i] = s % p
|
||||
return A
|
||||
elif dir == -1: # backward transform
|
||||
A = lst # input array
|
||||
a = [0] * d # transformed values
|
||||
for j in range(d):
|
||||
s = 0
|
||||
for i in range(d):
|
||||
s += A[i] * pow(r_prime, i*j, p)
|
||||
a[j] = (d_prime * s) % p
|
||||
return a
|
||||
|
||||
def ntt_convolute(a, b):
|
||||
"""convolute arrays a and b."""
|
||||
assert(len(a) == len(b))
|
||||
x = ntt(a, 1)
|
||||
y = ntt(b, 1)
|
||||
for i in range(len(a)):
|
||||
y[i] = y[i] * x[i]
|
||||
r = ntt(y, -1)
|
||||
return r
|
||||
|
||||
|
||||
# Example: Two arrays representing 21 and 81 in little-endian:
|
||||
a = [1, 2, 0, 0]
|
||||
b = [1, 8, 0, 0]
|
||||
|
||||
assert(ntt_convolute(a, b) == [1, 10, 16, 0])
|
||||
assert(21 * 81 == (1*10**0 + 10*10**1 + 16*10**2 + 0*10**3))
|
256
third_party/python/Modules/_decimal/libmpdec/literature/matrix-transform.txt
vendored
Normal file
256
third_party/python/Modules/_decimal/libmpdec/literature/matrix-transform.txt
vendored
Normal file
|
@ -0,0 +1,256 @@
|
|||
|
||||
|
||||
(* Copyright (c) 2011 Stefan Krah. All rights reserved. *)
|
||||
|
||||
|
||||
The Matrix Fourier Transform:
|
||||
=============================
|
||||
|
||||
In libmpdec, the Matrix Fourier Transform [1] is called four-step transform
|
||||
after a variant that appears in [2]. The algorithm requires that the input
|
||||
array can be viewed as an R*C matrix.
|
||||
|
||||
All operations are done modulo p. For readability, the proofs drop all
|
||||
instances of (mod p).
|
||||
|
||||
|
||||
Algorithm four-step (forward transform):
|
||||
----------------------------------------
|
||||
|
||||
a := input array
|
||||
d := len(a) = R * C
|
||||
p := prime
|
||||
w := primitive root of unity of the prime field
|
||||
r := w**((p-1)/d)
|
||||
A := output array
|
||||
|
||||
1) Apply a length R FNT to each column.
|
||||
|
||||
2) Multiply each matrix element (addressed by j*C+m) by r**(j*m).
|
||||
|
||||
3) Apply a length C FNT to each row.
|
||||
|
||||
4) Transpose the matrix.
|
||||
|
||||
|
||||
Proof (forward transform):
|
||||
--------------------------
|
||||
|
||||
The algorithm can be derived starting from the regular definition of
|
||||
the finite-field transform of length d:
|
||||
|
||||
d-1
|
||||
,----
|
||||
\
|
||||
A[k] = | a[l] * r**(k * l)
|
||||
/
|
||||
`----
|
||||
l = 0
|
||||
|
||||
|
||||
The sum can be rearranged into the sum of the sums of columns:
|
||||
|
||||
C-1 R-1
|
||||
,---- ,----
|
||||
\ \
|
||||
= | | a[i * C + j] * r**(k * (i * C + j))
|
||||
/ /
|
||||
`---- `----
|
||||
j = 0 i = 0
|
||||
|
||||
|
||||
Extracting a constant from the inner sum:
|
||||
|
||||
C-1 R-1
|
||||
,---- ,----
|
||||
\ \
|
||||
= | r**k*j * | a[i * C + j] * r**(k * i * C)
|
||||
/ /
|
||||
`---- `----
|
||||
j = 0 i = 0
|
||||
|
||||
|
||||
Without any loss of generality, let k = n * R + m,
|
||||
where n < C and m < R:
|
||||
|
||||
C-1 R-1
|
||||
,---- ,----
|
||||
\ \
|
||||
A[n*R+m] = | r**(R*n*j) * r**(m*j) * | a[i*C+j] * r**(R*C*n*i) * r**(C*m*i)
|
||||
/ /
|
||||
`---- `----
|
||||
j = 0 i = 0
|
||||
|
||||
|
||||
Since r = w ** ((p-1) / (R*C)):
|
||||
|
||||
a) r**(R*C*n*i) = w**((p-1)*n*i) = 1
|
||||
|
||||
b) r**(C*m*i) = w**((p-1) / R) ** (m*i) = r_R ** (m*i)
|
||||
|
||||
c) r**(R*n*j) = w**((p-1) / C) ** (n*j) = r_C ** (n*j)
|
||||
|
||||
r_R := root of the subfield of length R.
|
||||
r_C := root of the subfield of length C.
|
||||
|
||||
|
||||
C-1 R-1
|
||||
,---- ,----
|
||||
\ \
|
||||
A[n*R+m] = | r_C**(n*j) * [ r**(m*j) * | a[i*C+j] * r_R**(m*i) ]
|
||||
/ ^ /
|
||||
`---- | `---- 1) transform the columns
|
||||
j = 0 | i = 0
|
||||
^ |
|
||||
| `-- 2) multiply
|
||||
|
|
||||
`-- 3) transform the rows
|
||||
|
||||
|
||||
Note that the entire RHS is a function of n and m and that the results
|
||||
for each pair (n, m) are stored in Fortran order.
|
||||
|
||||
Let the term in square brackets be f(m, j). Step 1) and 2) precalculate
|
||||
the term for all (m, j). After that, the original matrix is now a lookup
|
||||
table with the mth element in the jth column at location m * C + j.
|
||||
|
||||
Let the complete RHS be g(m, n). Step 3) does an in-place transform of
|
||||
length n on all rows. After that, the original matrix is now a lookup
|
||||
table with the mth element in the nth column at location m * C + n.
|
||||
|
||||
But each (m, n) pair should be written to location n * R + m. Therefore,
|
||||
step 4) transposes the result of step 3).
|
||||
|
||||
|
||||
|
||||
Algorithm four-step (inverse transform):
|
||||
----------------------------------------
|
||||
|
||||
A := input array
|
||||
d := len(A) = R * C
|
||||
p := prime
|
||||
d' := d**(p-2) # inverse of d
|
||||
w := primitive root of unity of the prime field
|
||||
r := w**((p-1)/d) # root of the subfield
|
||||
r' := w**((p-1) - (p-1)/d) # inverse of r
|
||||
a := output array
|
||||
|
||||
0) View the matrix as a C*R matrix.
|
||||
|
||||
1) Transpose the matrix, producing an R*C matrix.
|
||||
|
||||
2) Apply a length C FNT to each row.
|
||||
|
||||
3) Multiply each matrix element (addressed by i*C+n) by r**(i*n).
|
||||
|
||||
4) Apply a length R FNT to each column.
|
||||
|
||||
|
||||
Proof (inverse transform):
|
||||
--------------------------
|
||||
|
||||
The algorithm can be derived starting from the regular definition of
|
||||
the finite-field inverse transform of length d:
|
||||
|
||||
d-1
|
||||
,----
|
||||
\
|
||||
a[k] = d' * | A[l] * r' ** (k * l)
|
||||
/
|
||||
`----
|
||||
l = 0
|
||||
|
||||
|
||||
The sum can be rearranged into the sum of the sums of columns. Note
|
||||
that at this stage we still have a C*R matrix, so C denotes the number
|
||||
of rows:
|
||||
|
||||
R-1 C-1
|
||||
,---- ,----
|
||||
\ \
|
||||
= d' * | | a[j * R + i] * r' ** (k * (j * R + i))
|
||||
/ /
|
||||
`---- `----
|
||||
i = 0 j = 0
|
||||
|
||||
|
||||
Extracting a constant from the inner sum:
|
||||
|
||||
R-1 C-1
|
||||
,---- ,----
|
||||
\ \
|
||||
= d' * | r' ** (k*i) * | a[j * R + i] * r' ** (k * j * R)
|
||||
/ /
|
||||
`---- `----
|
||||
i = 0 j = 0
|
||||
|
||||
|
||||
Without any loss of generality, let k = m * C + n,
|
||||
where m < R and n < C:
|
||||
|
||||
R-1 C-1
|
||||
,---- ,----
|
||||
\ \
|
||||
A[m*C+n] = d' * | r' ** (C*m*i) * r' ** (n*i) * | a[j*R+i] * r' ** (R*C*m*j) * r' ** (R*n*j)
|
||||
/ /
|
||||
`---- `----
|
||||
i = 0 j = 0
|
||||
|
||||
|
||||
Since r' = w**((p-1) - (p-1)/d) and d = R*C:
|
||||
|
||||
a) r' ** (R*C*m*j) = w**((p-1)*R*C*m*j - (p-1)*m*j) = 1
|
||||
|
||||
b) r' ** (C*m*i) = w**((p-1)*C - (p-1)/R) ** (m*i) = r_R' ** (m*i)
|
||||
|
||||
c) r' ** (R*n*j) = r_C' ** (n*j)
|
||||
|
||||
d) d' = d**(p-2) = (R*C) ** (p-2) = R**(p-2) * C**(p-2) = R' * C'
|
||||
|
||||
r_R' := inverse of the root of the subfield of length R.
|
||||
r_C' := inverse of the root of the subfield of length C.
|
||||
R' := inverse of R
|
||||
C' := inverse of C
|
||||
|
||||
|
||||
R-1 C-1
|
||||
,---- ,---- 2) transform the rows of a^T
|
||||
\ \
|
||||
A[m*C+n] = R' * | r_R' ** (m*i) * [ r' ** (n*i) * C' * | a[j*R+i] * r_C' ** (n*j) ]
|
||||
/ ^ / ^
|
||||
`---- | `---- |
|
||||
i = 0 | j = 0 |
|
||||
^ | `-- 1) Transpose input matrix
|
||||
| `-- 3) multiply to address elements by
|
||||
| i * C + j
|
||||
`-- 3) transform the columns
|
||||
|
||||
|
||||
|
||||
Note that the entire RHS is a function of m and n and that the results
|
||||
for each pair (m, n) are stored in C order.
|
||||
|
||||
Let the term in square brackets be f(n, i). Without step 1), the sum
|
||||
would perform a length C transform on the columns of the input matrix.
|
||||
This is a) inefficient and b) the results are needed in C order, so
|
||||
step 1) exchanges rows and columns.
|
||||
|
||||
Step 2) and 3) precalculate f(n, i) for all (n, i). After that, the
|
||||
original matrix is now a lookup table with the ith element in the nth
|
||||
column at location i * C + n.
|
||||
|
||||
Let the complete RHS be g(m, n). Step 4) does an in-place transform of
|
||||
length m on all columns. After that, the original matrix is now a lookup
|
||||
table with the mth element in the nth column at location m * C + n,
|
||||
which means that all A[k] = A[m * C + n] are in the correct order.
|
||||
|
||||
|
||||
--
|
||||
|
||||
[1] Joerg Arndt: "Matters Computational"
|
||||
http://www.jjj.de/fxt/
|
||||
[2] David H. Bailey: FFTs in External or Hierarchical Memory
|
||||
http://crd.lbl.gov/~dhbailey/dhbpapers/
|
||||
|
||||
|
||||
|
127
third_party/python/Modules/_decimal/libmpdec/literature/mulmod-64.txt
vendored
Normal file
127
third_party/python/Modules/_decimal/libmpdec/literature/mulmod-64.txt
vendored
Normal file
|
@ -0,0 +1,127 @@
|
|||
|
||||
|
||||
(* Copyright (c) 2011 Stefan Krah. All rights reserved. *)
|
||||
|
||||
|
||||
==========================================================================
|
||||
Calculate (a * b) % p using special primes
|
||||
==========================================================================
|
||||
|
||||
A description of the algorithm can be found in the apfloat manual by
|
||||
Tommila [1].
|
||||
|
||||
|
||||
Definitions:
|
||||
------------
|
||||
|
||||
In the whole document, "==" stands for "is congruent with".
|
||||
|
||||
Result of a * b in terms of high/low words:
|
||||
|
||||
(1) hi * 2**64 + lo = a * b
|
||||
|
||||
Special primes:
|
||||
|
||||
(2) p = 2**64 - z + 1, where z = 2**n
|
||||
|
||||
Single step modular reduction:
|
||||
|
||||
(3) R(hi, lo) = hi * z - hi + lo
|
||||
|
||||
|
||||
Strategy:
|
||||
---------
|
||||
|
||||
a) Set (hi, lo) to the result of a * b.
|
||||
|
||||
b) Set (hi', lo') to the result of R(hi, lo).
|
||||
|
||||
c) Repeat step b) until 0 <= hi' * 2**64 + lo' < 2*p.
|
||||
|
||||
d) If the result is less than p, return lo'. Otherwise return lo' - p.
|
||||
|
||||
|
||||
The reduction step b) preserves congruence:
|
||||
-------------------------------------------
|
||||
|
||||
hi * 2**64 + lo == hi * z - hi + lo (mod p)
|
||||
|
||||
Proof:
|
||||
~~~~~~
|
||||
|
||||
hi * 2**64 + lo = (2**64 - z + 1) * hi + z * hi - hi + lo
|
||||
|
||||
= p * hi + z * hi - hi + lo
|
||||
|
||||
== z * hi - hi + lo (mod p)
|
||||
|
||||
|
||||
Maximum numbers of step b):
|
||||
---------------------------
|
||||
|
||||
# To avoid unnecessary formalism, define:
|
||||
|
||||
def R(hi, lo, z):
|
||||
return divmod(hi * z - hi + lo, 2**64)
|
||||
|
||||
# For simplicity, assume hi=2**64-1, lo=2**64-1 after the
|
||||
# initial multiplication a * b. This is of course impossible
|
||||
# but certainly covers all cases.
|
||||
|
||||
# Then, for p1:
|
||||
hi=2**64-1; lo=2**64-1; z=2**32
|
||||
p1 = 2**64 - z + 1
|
||||
|
||||
hi, lo = R(hi, lo, z) # First reduction
|
||||
hi, lo = R(hi, lo, z) # Second reduction
|
||||
hi * 2**64 + lo < 2 * p1 # True
|
||||
|
||||
# For p2:
|
||||
hi=2**64-1; lo=2**64-1; z=2**34
|
||||
p2 = 2**64 - z + 1
|
||||
|
||||
hi, lo = R(hi, lo, z) # First reduction
|
||||
hi, lo = R(hi, lo, z) # Second reduction
|
||||
hi, lo = R(hi, lo, z) # Third reduction
|
||||
hi * 2**64 + lo < 2 * p2 # True
|
||||
|
||||
# For p3:
|
||||
hi=2**64-1; lo=2**64-1; z=2**40
|
||||
p3 = 2**64 - z + 1
|
||||
|
||||
hi, lo = R(hi, lo, z) # First reduction
|
||||
hi, lo = R(hi, lo, z) # Second reduction
|
||||
hi, lo = R(hi, lo, z) # Third reduction
|
||||
hi * 2**64 + lo < 2 * p3 # True
|
||||
|
||||
|
||||
Step d) preserves congruence and yields a result < p:
|
||||
-----------------------------------------------------
|
||||
|
||||
Case hi = 0:
|
||||
|
||||
Case lo < p: trivial.
|
||||
|
||||
Case lo >= p:
|
||||
|
||||
lo == lo - p (mod p) # result is congruent
|
||||
|
||||
p <= lo < 2*p -> 0 <= lo - p < p # result is in the correct range
|
||||
|
||||
Case hi = 1:
|
||||
|
||||
p < 2**64 /\ 2**64 + lo < 2*p -> lo < p # lo is always less than p
|
||||
|
||||
2**64 + lo == 2**64 + (lo - p) (mod p) # result is congruent
|
||||
|
||||
= lo - p # exactly the same value as the previous RHS
|
||||
# in uint64_t arithmetic.
|
||||
|
||||
p < 2**64 + lo < 2*p -> 0 < 2**64 + (lo - p) < p # correct range
|
||||
|
||||
|
||||
|
||||
[1] http://www.apfloat.org/apfloat/2.40/apfloat.pdf
|
||||
|
||||
|
||||
|
269
third_party/python/Modules/_decimal/libmpdec/literature/mulmod-ppro.txt
vendored
Normal file
269
third_party/python/Modules/_decimal/libmpdec/literature/mulmod-ppro.txt
vendored
Normal file
|
@ -0,0 +1,269 @@
|
|||
|
||||
|
||||
(* Copyright (c) 2011 Stefan Krah. All rights reserved. *)
|
||||
|
||||
|
||||
========================================================================
|
||||
Calculate (a * b) % p using the 80-bit x87 FPU
|
||||
========================================================================
|
||||
|
||||
A description of the algorithm can be found in the apfloat manual by
|
||||
Tommila [1].
|
||||
|
||||
The proof follows an argument made by Granlund/Montgomery in [2].
|
||||
|
||||
|
||||
Definitions and assumptions:
|
||||
----------------------------
|
||||
|
||||
The 80-bit extended precision format uses 64 bits for the significand:
|
||||
|
||||
(1) F = 64
|
||||
|
||||
The modulus is prime and less than 2**31:
|
||||
|
||||
(2) 2 <= p < 2**31
|
||||
|
||||
The factors are less than p:
|
||||
|
||||
(3) 0 <= a < p
|
||||
(4) 0 <= b < p
|
||||
|
||||
The product a * b is less than 2**62 and is thus exact in 64 bits:
|
||||
|
||||
(5) n = a * b
|
||||
|
||||
The product can be represented in terms of quotient and remainder:
|
||||
|
||||
(6) n = q * p + r
|
||||
|
||||
Using (3), (4) and the fact that p is prime, the remainder is always
|
||||
greater than zero:
|
||||
|
||||
(7) 0 <= q < p /\ 1 <= r < p
|
||||
|
||||
|
||||
Strategy:
|
||||
---------
|
||||
|
||||
Precalculate the 80-bit long double inverse of p, with a maximum
|
||||
relative error of 2**(1-F):
|
||||
|
||||
(8) pinv = (long double)1.0 / p
|
||||
|
||||
Calculate an estimate for q = floor(n/p). The multiplication has another
|
||||
maximum relative error of 2**(1-F):
|
||||
|
||||
(9) qest = n * pinv
|
||||
|
||||
If we can show that q < qest < q+1, then trunc(qest) = q. It is then
|
||||
easy to recover the remainder r. The complete algorithm is:
|
||||
|
||||
a) Set the control word to 64-bit precision and truncation mode.
|
||||
|
||||
b) n = a * b # Calculate exact product.
|
||||
|
||||
c) qest = n * pinv # Calculate estimate for the quotient.
|
||||
|
||||
d) q = (qest+2**63)-2**63 # Truncate qest to the exact quotient.
|
||||
|
||||
f) r = n - q * p # Calculate remainder.
|
||||
|
||||
|
||||
Proof for q < qest < q+1:
|
||||
-------------------------
|
||||
|
||||
Using the cumulative error, the error bounds for qest are:
|
||||
|
||||
n n * (1 + 2**(1-F))**2
|
||||
(9) --------------------- <= qest <= ---------------------
|
||||
p * (1 + 2**(1-F))**2 p
|
||||
|
||||
|
||||
Lemma 1:
|
||||
--------
|
||||
n q * p + r
|
||||
(10) q < --------------------- = ---------------------
|
||||
p * (1 + 2**(1-F))**2 p * (1 + 2**(1-F))**2
|
||||
|
||||
|
||||
Proof:
|
||||
~~~~~~
|
||||
|
||||
(I) q * p * (1 + 2**(1-F))**2 < q * p + r
|
||||
|
||||
(II) q * p * 2**(2-F) + q * p * 2**(2-2*F) < r
|
||||
|
||||
Using (1) and (7), it is sufficient to show that:
|
||||
|
||||
(III) q * p * 2**(-62) + q * p * 2**(-126) < 1 <= r
|
||||
|
||||
(III) can easily be verified by substituting the largest possible
|
||||
values p = 2**31-1 and q = 2**31-2.
|
||||
|
||||
The critical cases occur when r = 1, n = m * p + 1. These cases
|
||||
can be exhaustively verified with a test program.
|
||||
|
||||
|
||||
Lemma 2:
|
||||
--------
|
||||
|
||||
n * (1 + 2**(1-F))**2 (q * p + r) * (1 + 2**(1-F))**2
|
||||
(11) --------------------- = ------------------------------- < q + 1
|
||||
p p
|
||||
|
||||
Proof:
|
||||
~~~~~~
|
||||
|
||||
(I) (q * p + r) + (q * p + r) * 2**(2-F) + (q * p + r) * 2**(2-2*F) < q * p + p
|
||||
|
||||
(II) (q * p + r) * 2**(2-F) + (q * p + r) * 2**(2-2*F) < p - r
|
||||
|
||||
Using (1) and (7), it is sufficient to show that:
|
||||
|
||||
(III) (q * p + r) * 2**(-62) + (q * p + r) * 2**(-126) < 1 <= p - r
|
||||
|
||||
(III) can easily be verified by substituting the largest possible
|
||||
values p = 2**31-1, q = 2**31-2 and r = 2**31-2.
|
||||
|
||||
The critical cases occur when r = (p - 1), n = m * p - 1. These cases
|
||||
can be exhaustively verified with a test program.
|
||||
|
||||
|
||||
[1] http://www.apfloat.org/apfloat/2.40/apfloat.pdf
|
||||
[2] http://gmplib.org/~tege/divcnst-pldi94.pdf
|
||||
[Section 7: "Use of floating point"]
|
||||
|
||||
|
||||
|
||||
(* Coq proof for (10) and (11) *)
|
||||
|
||||
Require Import ZArith.
|
||||
Require Import QArith.
|
||||
Require Import Qpower.
|
||||
Require Import Qabs.
|
||||
Require Import Psatz.
|
||||
|
||||
Open Scope Q_scope.
|
||||
|
||||
|
||||
Ltac qreduce T :=
|
||||
rewrite <- (Qred_correct (T)); simpl (Qred (T)).
|
||||
|
||||
Theorem Qlt_move_right :
|
||||
forall x y z:Q, x + z < y <-> x < y - z.
|
||||
Proof.
|
||||
intros.
|
||||
split.
|
||||
intros.
|
||||
psatzl Q.
|
||||
intros.
|
||||
psatzl Q.
|
||||
Qed.
|
||||
|
||||
Theorem Qlt_mult_by_z :
|
||||
forall x y z:Q, 0 < z -> (x < y <-> x * z < y * z).
|
||||
Proof.
|
||||
intros.
|
||||
split.
|
||||
intros.
|
||||
apply Qmult_lt_compat_r. trivial. trivial.
|
||||
intros.
|
||||
rewrite <- (Qdiv_mult_l x z). rewrite <- (Qdiv_mult_l y z).
|
||||
apply Qmult_lt_compat_r.
|
||||
apply Qlt_shift_inv_l.
|
||||
trivial. psatzl Q. trivial. psatzl Q. psatzl Q.
|
||||
Qed.
|
||||
|
||||
Theorem Qle_mult_quad :
|
||||
forall (a b c d:Q),
|
||||
0 <= a -> a <= c ->
|
||||
0 <= b -> b <= d ->
|
||||
a * b <= c * d.
|
||||
intros.
|
||||
psatz Q.
|
||||
Qed.
|
||||
|
||||
|
||||
Theorem q_lt_qest:
|
||||
forall (p q r:Q),
|
||||
(0 < p) -> (p <= (2#1)^31 - 1) ->
|
||||
(0 <= q) -> (q <= p - 1) ->
|
||||
(1 <= r) -> (r <= p - 1) ->
|
||||
q < (q * p + r) / (p * (1 + (2#1)^(-63))^2).
|
||||
Proof.
|
||||
intros.
|
||||
rewrite Qlt_mult_by_z with (z := (p * (1 + (2#1)^(-63))^2)).
|
||||
|
||||
unfold Qdiv.
|
||||
rewrite <- Qmult_assoc.
|
||||
rewrite (Qmult_comm (/ (p * (1 + (2 # 1) ^ (-63)) ^ 2)) (p * (1 + (2 # 1) ^ (-63)) ^ 2)).
|
||||
rewrite Qmult_inv_r.
|
||||
rewrite Qmult_1_r.
|
||||
|
||||
assert (q * (p * (1 + (2 # 1) ^ (-63)) ^ 2) == q * p + (q * p) * ((2 # 1) ^ (-62) + (2 # 1) ^ (-126))).
|
||||
qreduce ((1 + (2 # 1) ^ (-63)) ^ 2).
|
||||
qreduce ((2 # 1) ^ (-62) + (2 # 1) ^ (-126)).
|
||||
ring_simplify.
|
||||
reflexivity.
|
||||
rewrite H5.
|
||||
|
||||
rewrite Qplus_comm.
|
||||
rewrite Qlt_move_right.
|
||||
ring_simplify (q * p + r - q * p).
|
||||
qreduce ((2 # 1) ^ (-62) + (2 # 1) ^ (-126)).
|
||||
|
||||
apply Qlt_le_trans with (y := 1).
|
||||
rewrite Qlt_mult_by_z with (z := 85070591730234615865843651857942052864 # 18446744073709551617).
|
||||
ring_simplify.
|
||||
|
||||
apply Qle_lt_trans with (y := ((2 # 1) ^ 31 - (2#1)) * ((2 # 1) ^ 31 - 1)).
|
||||
apply Qle_mult_quad.
|
||||
assumption. psatzl Q. psatzl Q. psatzl Q. psatzl Q. psatzl Q. assumption. psatzl Q. psatzl Q.
|
||||
Qed.
|
||||
|
||||
Theorem qest_lt_qplus1:
|
||||
forall (p q r:Q),
|
||||
(0 < p) -> (p <= (2#1)^31 - 1) ->
|
||||
(0 <= q) -> (q <= p - 1) ->
|
||||
(1 <= r) -> (r <= p - 1) ->
|
||||
((q * p + r) * (1 + (2#1)^(-63))^2) / p < q + 1.
|
||||
Proof.
|
||||
intros.
|
||||
rewrite Qlt_mult_by_z with (z := p).
|
||||
|
||||
unfold Qdiv.
|
||||
rewrite <- Qmult_assoc.
|
||||
rewrite (Qmult_comm (/ p) p).
|
||||
rewrite Qmult_inv_r.
|
||||
rewrite Qmult_1_r.
|
||||
|
||||
assert ((q * p + r) * (1 + (2 # 1) ^ (-63)) ^ 2 == q * p + r + (q * p + r) * ((2 # 1) ^ (-62) + (2 # 1) ^ (-126))).
|
||||
qreduce ((1 + (2 # 1) ^ (-63)) ^ 2).
|
||||
qreduce ((2 # 1) ^ (-62) + (2 # 1) ^ (-126)).
|
||||
ring_simplify. reflexivity.
|
||||
rewrite H5.
|
||||
|
||||
rewrite <- Qplus_assoc. rewrite <- Qplus_comm. rewrite Qlt_move_right.
|
||||
ring_simplify ((q + 1) * p - q * p).
|
||||
|
||||
rewrite <- Qplus_comm. rewrite Qlt_move_right.
|
||||
|
||||
apply Qlt_le_trans with (y := 1).
|
||||
qreduce ((2 # 1) ^ (-62) + (2 # 1) ^ (-126)).
|
||||
|
||||
rewrite Qlt_mult_by_z with (z := 85070591730234615865843651857942052864 # 18446744073709551617).
|
||||
ring_simplify.
|
||||
|
||||
ring_simplify in H0.
|
||||
apply Qle_lt_trans with (y := (2147483646 # 1) * (2147483647 # 1) + (2147483646 # 1)).
|
||||
|
||||
apply Qplus_le_compat.
|
||||
apply Qle_mult_quad.
|
||||
assumption. psatzl Q. auto with qarith. assumption. psatzl Q.
|
||||
auto with qarith. auto with qarith.
|
||||
psatzl Q. psatzl Q. assumption.
|
||||
Qed.
|
||||
|
||||
|
||||
|
63
third_party/python/Modules/_decimal/libmpdec/literature/six-step.txt
vendored
Normal file
63
third_party/python/Modules/_decimal/libmpdec/literature/six-step.txt
vendored
Normal file
|
@ -0,0 +1,63 @@
|
|||
|
||||
|
||||
(* Copyright (c) 2011 Stefan Krah. All rights reserved. *)
|
||||
|
||||
|
||||
The Six Step Transform:
|
||||
=======================
|
||||
|
||||
In libmpdec, the six-step transform is the Matrix Fourier Transform (See
|
||||
matrix-transform.txt) in disguise. It is called six-step transform after
|
||||
a variant that appears in [1]. The algorithm requires that the input
|
||||
array can be viewed as an R*C matrix.
|
||||
|
||||
|
||||
Algorithm six-step (forward transform):
|
||||
---------------------------------------
|
||||
|
||||
1a) Transpose the matrix.
|
||||
|
||||
1b) Apply a length R FNT to each row.
|
||||
|
||||
1c) Transpose the matrix.
|
||||
|
||||
2) Multiply each matrix element (addressed by j*C+m) by r**(j*m).
|
||||
|
||||
3) Apply a length C FNT to each row.
|
||||
|
||||
4) Transpose the matrix.
|
||||
|
||||
Note that steps 1a) - 1c) are exactly equivalent to step 1) of the Matrix
|
||||
Fourier Transform. For large R, it is faster to transpose twice and do
|
||||
a transform on the rows than to perform a column transpose directly.
|
||||
|
||||
|
||||
|
||||
Algorithm six-step (inverse transform):
|
||||
---------------------------------------
|
||||
|
||||
0) View the matrix as a C*R matrix.
|
||||
|
||||
1) Transpose the matrix, producing an R*C matrix.
|
||||
|
||||
2) Apply a length C FNT to each row.
|
||||
|
||||
3) Multiply each matrix element (addressed by i*C+n) by r**(i*n).
|
||||
|
||||
4a) Transpose the matrix.
|
||||
|
||||
4b) Apply a length R FNT to each row.
|
||||
|
||||
4c) Transpose the matrix.
|
||||
|
||||
Again, steps 4a) - 4c) are equivalent to step 4) of the Matrix Fourier
|
||||
Transform.
|
||||
|
||||
|
||||
|
||||
--
|
||||
|
||||
[1] David H. Bailey: FFTs in External or Hierarchical Memory
|
||||
http://crd.lbl.gov/~dhbailey/dhbpapers/
|
||||
|
||||
|
692
third_party/python/Modules/_decimal/libmpdec/literature/umodarith.lisp
vendored
Normal file
692
third_party/python/Modules/_decimal/libmpdec/literature/umodarith.lisp
vendored
Normal file
|
@ -0,0 +1,692 @@
|
|||
;
|
||||
; Copyright (c) 2008-2016 Stefan Krah. All rights reserved.
|
||||
;
|
||||
; Redistribution and use in source and binary forms, with or without
|
||||
; modification, are permitted provided that the following conditions
|
||||
; are met:
|
||||
;
|
||||
; 1. Redistributions of source code must retain the above copyright
|
||||
; notice, this list of conditions and the following disclaimer.
|
||||
;
|
||||
; 2. Redistributions in binary form must reproduce the above copyright
|
||||
; notice, this list of conditions and the following disclaimer in the
|
||||
; documentation and/or other materials provided with the distribution.
|
||||
;
|
||||
; THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS "AS IS" AND
|
||||
; ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
; IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
; ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
; FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
; DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
; OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
; HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
; LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
; OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
; SUCH DAMAGE.
|
||||
;
|
||||
|
||||
|
||||
(in-package "ACL2")
|
||||
|
||||
(include-book "arithmetic/top-with-meta" :dir :system)
|
||||
(include-book "arithmetic-2/floor-mod/floor-mod" :dir :system)
|
||||
|
||||
|
||||
;; =====================================================================
|
||||
;; Proofs for several functions in umodarith.h
|
||||
;; =====================================================================
|
||||
|
||||
|
||||
|
||||
;; =====================================================================
|
||||
;; Helper theorems
|
||||
;; =====================================================================
|
||||
|
||||
(defthm elim-mod-m<x<2*m
|
||||
(implies (and (<= m x)
|
||||
(< x (* 2 m))
|
||||
(rationalp x) (rationalp m))
|
||||
(equal (mod x m)
|
||||
(+ x (- m)))))
|
||||
|
||||
(defthm modaux-1a
|
||||
(implies (and (< x m) (< 0 x) (< 0 m)
|
||||
(rationalp x) (rationalp m))
|
||||
(equal (mod (- x) m)
|
||||
(+ (- x) m))))
|
||||
|
||||
(defthm modaux-1b
|
||||
(implies (and (< (- x) m) (< x 0) (< 0 m)
|
||||
(rationalp x) (rationalp m))
|
||||
(equal (mod x m)
|
||||
(+ x m)))
|
||||
:hints (("Goal" :use ((:instance modaux-1a
|
||||
(x (- x)))))))
|
||||
|
||||
(defthm modaux-1c
|
||||
(implies (and (< x m) (< 0 x) (< 0 m)
|
||||
(rationalp x) (rationalp m))
|
||||
(equal (mod x m)
|
||||
x)))
|
||||
|
||||
(defthm modaux-2a
|
||||
(implies (and (< 0 b) (< b m)
|
||||
(natp x) (natp b) (natp m)
|
||||
(< (mod (+ b x) m) b))
|
||||
(equal (mod (+ (- m) b x) m)
|
||||
(+ (- m) b (mod x m)))))
|
||||
|
||||
(defthm modaux-2b
|
||||
(implies (and (< 0 b) (< b m)
|
||||
(natp x) (natp b) (natp m)
|
||||
(< (mod (+ b x) m) b))
|
||||
(equal (mod (+ b x) m)
|
||||
(+ (- m) b (mod x m))))
|
||||
:hints (("Goal" :use (modaux-2a))))
|
||||
|
||||
(defthm linear-mod-1
|
||||
(implies (and (< x m) (< b m)
|
||||
(natp x) (natp b)
|
||||
(rationalp m))
|
||||
(equal (< x (mod (+ (- b) x) m))
|
||||
(< x b)))
|
||||
:hints (("Goal" :use ((:instance modaux-1a
|
||||
(x (+ b (- x))))))))
|
||||
|
||||
(defthm linear-mod-2
|
||||
(implies (and (< 0 b) (< b m)
|
||||
(natp x) (natp b)
|
||||
(natp m))
|
||||
(equal (< (mod x m)
|
||||
(mod (+ (- b) x) m))
|
||||
(< (mod x m) b))))
|
||||
|
||||
(defthm linear-mod-3
|
||||
(implies (and (< x m) (< b m)
|
||||
(natp x) (natp b)
|
||||
(rationalp m))
|
||||
(equal (<= b (mod (+ b x) m))
|
||||
(< (+ b x) m)))
|
||||
:hints (("Goal" :use ((:instance elim-mod-m<x<2*m
|
||||
(x (+ b x)))))))
|
||||
|
||||
(defthm modaux-2c
|
||||
(implies (and (< 0 b) (< b m)
|
||||
(natp x) (natp b) (natp m)
|
||||
(<= b (mod (+ b x) m)))
|
||||
(equal (mod (+ b x) m)
|
||||
(+ b (mod x m))))
|
||||
:hints (("Subgoal *1/8''" :use (linear-mod-3))))
|
||||
|
||||
(defthmd modaux-2d
|
||||
(implies (and (< x m) (< 0 x) (< 0 m)
|
||||
(< (- m) b) (< b 0) (rationalp m)
|
||||
(<= x (mod (+ b x) m))
|
||||
(rationalp x) (rationalp b))
|
||||
(equal (+ (- m) (mod (+ b x) m))
|
||||
(+ b x)))
|
||||
:hints (("Goal" :cases ((<= 0 (+ b x))))
|
||||
("Subgoal 2'" :use ((:instance modaux-1b
|
||||
(x (+ b x)))))))
|
||||
|
||||
(defthm mod-m-b
|
||||
(implies (and (< 0 x) (< 0 b) (< 0 m)
|
||||
(< x b) (< b m)
|
||||
(natp x) (natp b) (natp m))
|
||||
(equal (mod (+ (mod (- x) m) b) m)
|
||||
(mod (- x) b))))
|
||||
|
||||
|
||||
;; =====================================================================
|
||||
;; addmod, submod
|
||||
;; =====================================================================
|
||||
|
||||
(defun addmod (a b m base)
|
||||
(let* ((s (mod (+ a b) base))
|
||||
(s (if (< s a) (mod (- s m) base) s))
|
||||
(s (if (>= s m) (mod (- s m) base) s)))
|
||||
s))
|
||||
|
||||
(defthmd addmod-correct
|
||||
(implies (and (< 0 m) (< m base)
|
||||
(< a m) (<= b m)
|
||||
(natp m) (natp base)
|
||||
(natp a) (natp b))
|
||||
(equal (addmod a b m base)
|
||||
(mod (+ a b) m)))
|
||||
:hints (("Goal" :cases ((<= base (+ a b))))
|
||||
("Subgoal 2.1'" :use ((:instance elim-mod-m<x<2*m
|
||||
(x (+ a b)))))))
|
||||
|
||||
(defun submod (a b m base)
|
||||
(let* ((d (mod (- a b) base))
|
||||
(d (if (< a d) (mod (+ d m) base) d)))
|
||||
d))
|
||||
|
||||
(defthmd submod-aux1
|
||||
(implies (and (< a (mod (+ a (- b)) base))
|
||||
(< 0 base) (< a base) (<= b base)
|
||||
(natp base) (natp a) (natp b))
|
||||
(< a b))
|
||||
:rule-classes :forward-chaining)
|
||||
|
||||
(defthmd submod-aux2
|
||||
(implies (and (<= (mod (+ a (- b)) base) a)
|
||||
(< 0 base) (< a base) (< b base)
|
||||
(natp base) (natp a) (natp b))
|
||||
(<= b a))
|
||||
:rule-classes :forward-chaining)
|
||||
|
||||
(defthmd submod-correct
|
||||
(implies (and (< 0 m) (< m base)
|
||||
(< a m) (<= b m)
|
||||
(natp m) (natp base)
|
||||
(natp a) (natp b))
|
||||
(equal (submod a b m base)
|
||||
(mod (- a b) m)))
|
||||
:hints (("Goal" :cases ((<= base (+ a b))))
|
||||
("Subgoal 2.2" :use ((:instance submod-aux1)))
|
||||
("Subgoal 2.2'''" :cases ((and (< 0 (+ a (- b) m))
|
||||
(< (+ a (- b) m) m))))
|
||||
("Subgoal 2.1" :use ((:instance submod-aux2)))
|
||||
("Subgoal 1.2" :use ((:instance submod-aux1)))
|
||||
("Subgoal 1.1" :use ((:instance submod-aux2)))))
|
||||
|
||||
|
||||
(defun submod-2 (a b m base)
|
||||
(let* ((d (mod (- a b) base))
|
||||
(d (if (< a b) (mod (+ d m) base) d)))
|
||||
d))
|
||||
|
||||
(defthm submod-2-correct
|
||||
(implies (and (< 0 m) (< m base)
|
||||
(< a m) (<= b m)
|
||||
(natp m) (natp base)
|
||||
(natp a) (natp b))
|
||||
(equal (submod-2 a b m base)
|
||||
(mod (- a b) m)))
|
||||
:hints (("Subgoal 2'" :cases ((and (< 0 (+ a (- b) m))
|
||||
(< (+ a (- b) m) m))))))
|
||||
|
||||
|
||||
;; =========================================================================
|
||||
;; ext-submod is correct
|
||||
;; =========================================================================
|
||||
|
||||
; a < 2*m, b < 2*m
|
||||
(defun ext-submod (a b m base)
|
||||
(let* ((a (if (>= a m) (- a m) a))
|
||||
(b (if (>= b m) (- b m) b))
|
||||
(d (mod (- a b) base))
|
||||
(d (if (< a b) (mod (+ d m) base) d)))
|
||||
d))
|
||||
|
||||
; a < 2*m, b < 2*m
|
||||
(defun ext-submod-2 (a b m base)
|
||||
(let* ((a (mod a m))
|
||||
(b (mod b m))
|
||||
(d (mod (- a b) base))
|
||||
(d (if (< a b) (mod (+ d m) base) d)))
|
||||
d))
|
||||
|
||||
(defthmd ext-submod-ext-submod-2-equal
|
||||
(implies (and (< 0 m) (< m base)
|
||||
(< a (* 2 m)) (< b (* 2 m))
|
||||
(natp m) (natp base)
|
||||
(natp a) (natp b))
|
||||
(equal (ext-submod a b m base)
|
||||
(ext-submod-2 a b m base))))
|
||||
|
||||
(defthmd ext-submod-2-correct
|
||||
(implies (and (< 0 m) (< m base)
|
||||
(< a (* 2 m)) (< b (* 2 m))
|
||||
(natp m) (natp base)
|
||||
(natp a) (natp b))
|
||||
(equal (ext-submod-2 a b m base)
|
||||
(mod (- a b) m))))
|
||||
|
||||
|
||||
;; =========================================================================
|
||||
;; dw-reduce is correct
|
||||
;; =========================================================================
|
||||
|
||||
(defun dw-reduce (hi lo m base)
|
||||
(let* ((r1 (mod hi m))
|
||||
(r2 (mod (+ (* r1 base) lo) m)))
|
||||
r2))
|
||||
|
||||
(defthmd dw-reduce-correct
|
||||
(implies (and (< 0 m) (< m base)
|
||||
(< hi base) (< lo base)
|
||||
(natp m) (natp base)
|
||||
(natp hi) (natp lo))
|
||||
(equal (dw-reduce hi lo m base)
|
||||
(mod (+ (* hi base) lo) m))))
|
||||
|
||||
(defthmd <=-multiply-both-sides-by-z
|
||||
(implies (and (rationalp x) (rationalp y)
|
||||
(< 0 z) (rationalp z))
|
||||
(equal (<= x y)
|
||||
(<= (* z x) (* z y)))))
|
||||
|
||||
(defthmd dw-reduce-aux1
|
||||
(implies (and (< 0 m) (< m base)
|
||||
(natp m) (natp base)
|
||||
(< lo base) (natp lo)
|
||||
(< x m) (natp x))
|
||||
(< (+ lo (* base x)) (* base m)))
|
||||
:hints (("Goal" :cases ((<= (+ x 1) m)))
|
||||
("Subgoal 1''" :cases ((<= (* base (+ x 1)) (* base m))))
|
||||
("subgoal 1.2" :use ((:instance <=-multiply-both-sides-by-z
|
||||
(x (+ 1 x))
|
||||
(y m)
|
||||
(z base))))))
|
||||
|
||||
(defthm dw-reduce-aux2
|
||||
(implies (and (< x (* base m))
|
||||
(< 0 m) (< m base)
|
||||
(natp m) (natp base) (natp x))
|
||||
(< (floor x m) base)))
|
||||
|
||||
;; This is the necessary condition for using _mpd_div_words().
|
||||
(defthmd dw-reduce-second-quotient-fits-in-single-word
|
||||
(implies (and (< 0 m) (< m base)
|
||||
(< hi base) (< lo base)
|
||||
(natp m) (natp base)
|
||||
(natp hi) (natp lo)
|
||||
(equal r1 (mod hi m)))
|
||||
(< (floor (+ (* r1 base) lo) m)
|
||||
base))
|
||||
:hints (("Goal" :cases ((< r1 m)))
|
||||
("Subgoal 1''" :cases ((< (+ lo (* base (mod hi m))) (* base m))))
|
||||
("Subgoal 1.2" :use ((:instance dw-reduce-aux1
|
||||
(x (mod hi m)))))))
|
||||
|
||||
|
||||
;; =========================================================================
|
||||
;; dw-submod is correct
|
||||
;; =========================================================================
|
||||
|
||||
(defun dw-submod (a hi lo m base)
|
||||
(let* ((r (dw-reduce hi lo m base))
|
||||
(d (mod (- a r) base))
|
||||
(d (if (< a r) (mod (+ d m) base) d)))
|
||||
d))
|
||||
|
||||
(defthmd dw-submod-aux1
|
||||
(implies (and (natp a) (< 0 m) (natp m)
|
||||
(natp x) (equal r (mod x m)))
|
||||
(equal (mod (- a x) m)
|
||||
(mod (- a r) m))))
|
||||
|
||||
(defthmd dw-submod-correct
|
||||
(implies (and (< 0 m) (< m base)
|
||||
(natp a) (< a m)
|
||||
(< hi base) (< lo base)
|
||||
(natp m) (natp base)
|
||||
(natp hi) (natp lo))
|
||||
(equal (dw-submod a hi lo m base)
|
||||
(mod (- a (+ (* base hi) lo)) m)))
|
||||
:hints (("Goal" :in-theory (disable dw-reduce)
|
||||
:use ((:instance dw-submod-aux1
|
||||
(x (+ lo (* base hi)))
|
||||
(r (dw-reduce hi lo m base)))
|
||||
(:instance dw-reduce-correct)))))
|
||||
|
||||
|
||||
;; =========================================================================
|
||||
;; ANSI C arithmetic for uint64_t
|
||||
;; =========================================================================
|
||||
|
||||
(defun add (a b)
|
||||
(mod (+ a b)
|
||||
(expt 2 64)))
|
||||
|
||||
(defun sub (a b)
|
||||
(mod (- a b)
|
||||
(expt 2 64)))
|
||||
|
||||
(defun << (w n)
|
||||
(mod (* w (expt 2 n))
|
||||
(expt 2 64)))
|
||||
|
||||
(defun >> (w n)
|
||||
(floor w (expt 2 n)))
|
||||
|
||||
;; join upper and lower half of a double word, yielding a 128 bit number
|
||||
(defun join (hi lo)
|
||||
(+ (* (expt 2 64) hi) lo))
|
||||
|
||||
|
||||
;; =============================================================================
|
||||
;; Fast modular reduction
|
||||
;; =============================================================================
|
||||
|
||||
;; These are the three primes used in the Number Theoretic Transform.
|
||||
;; A fast modular reduction scheme exists for all of them.
|
||||
(defmacro p1 ()
|
||||
(+ (expt 2 64) (- (expt 2 32)) 1))
|
||||
|
||||
(defmacro p2 ()
|
||||
(+ (expt 2 64) (- (expt 2 34)) 1))
|
||||
|
||||
(defmacro p3 ()
|
||||
(+ (expt 2 64) (- (expt 2 40)) 1))
|
||||
|
||||
|
||||
;; reduce the double word number hi*2**64 + lo (mod p1)
|
||||
(defun simple-mod-reduce-p1 (hi lo)
|
||||
(+ (* (expt 2 32) hi) (- hi) lo))
|
||||
|
||||
;; reduce the double word number hi*2**64 + lo (mod p2)
|
||||
(defun simple-mod-reduce-p2 (hi lo)
|
||||
(+ (* (expt 2 34) hi) (- hi) lo))
|
||||
|
||||
;; reduce the double word number hi*2**64 + lo (mod p3)
|
||||
(defun simple-mod-reduce-p3 (hi lo)
|
||||
(+ (* (expt 2 40) hi) (- hi) lo))
|
||||
|
||||
|
||||
; ----------------------------------------------------------
|
||||
; The modular reductions given above are correct
|
||||
; ----------------------------------------------------------
|
||||
|
||||
(defthmd congruence-p1-aux
|
||||
(equal (* (expt 2 64) hi)
|
||||
(+ (* (p1) hi)
|
||||
(* (expt 2 32) hi)
|
||||
(- hi))))
|
||||
|
||||
(defthmd congruence-p2-aux
|
||||
(equal (* (expt 2 64) hi)
|
||||
(+ (* (p2) hi)
|
||||
(* (expt 2 34) hi)
|
||||
(- hi))))
|
||||
|
||||
(defthmd congruence-p3-aux
|
||||
(equal (* (expt 2 64) hi)
|
||||
(+ (* (p3) hi)
|
||||
(* (expt 2 40) hi)
|
||||
(- hi))))
|
||||
|
||||
(defthmd mod-augment
|
||||
(implies (and (rationalp x)
|
||||
(rationalp y)
|
||||
(rationalp m))
|
||||
(equal (mod (+ x y) m)
|
||||
(mod (+ x (mod y m)) m))))
|
||||
|
||||
(defthmd simple-mod-reduce-p1-congruent
|
||||
(implies (and (integerp hi)
|
||||
(integerp lo))
|
||||
(equal (mod (simple-mod-reduce-p1 hi lo) (p1))
|
||||
(mod (join hi lo) (p1))))
|
||||
:hints (("Goal''" :use ((:instance congruence-p1-aux)
|
||||
(:instance mod-augment
|
||||
(m (p1))
|
||||
(x (+ (- hi) lo (* (expt 2 32) hi)))
|
||||
(y (* (p1) hi)))))))
|
||||
|
||||
(defthmd simple-mod-reduce-p2-congruent
|
||||
(implies (and (integerp hi)
|
||||
(integerp lo))
|
||||
(equal (mod (simple-mod-reduce-p2 hi lo) (p2))
|
||||
(mod (join hi lo) (p2))))
|
||||
:hints (("Goal''" :use ((:instance congruence-p2-aux)
|
||||
(:instance mod-augment
|
||||
(m (p2))
|
||||
(x (+ (- hi) lo (* (expt 2 34) hi)))
|
||||
(y (* (p2) hi)))))))
|
||||
|
||||
(defthmd simple-mod-reduce-p3-congruent
|
||||
(implies (and (integerp hi)
|
||||
(integerp lo))
|
||||
(equal (mod (simple-mod-reduce-p3 hi lo) (p3))
|
||||
(mod (join hi lo) (p3))))
|
||||
:hints (("Goal''" :use ((:instance congruence-p3-aux)
|
||||
(:instance mod-augment
|
||||
(m (p3))
|
||||
(x (+ (- hi) lo (* (expt 2 40) hi)))
|
||||
(y (* (p3) hi)))))))
|
||||
|
||||
|
||||
; ---------------------------------------------------------------------
|
||||
; We need a number less than 2*p, so that we can use the trick from
|
||||
; elim-mod-m<x<2*m for the final reduction.
|
||||
; For p1, two modular reductions are sufficient, for p2 and p3 three.
|
||||
; ---------------------------------------------------------------------
|
||||
|
||||
;; p1: the first reduction is less than 2**96
|
||||
(defthmd simple-mod-reduce-p1-<-2**96
|
||||
(implies (and (< hi (expt 2 64))
|
||||
(< lo (expt 2 64))
|
||||
(natp hi) (natp lo))
|
||||
(< (simple-mod-reduce-p1 hi lo)
|
||||
(expt 2 96))))
|
||||
|
||||
;; p1: the second reduction is less than 2*p1
|
||||
(defthmd simple-mod-reduce-p1-<-2*p1
|
||||
(implies (and (< hi (expt 2 64))
|
||||
(< lo (expt 2 64))
|
||||
(< (join hi lo) (expt 2 96))
|
||||
(natp hi) (natp lo))
|
||||
(< (simple-mod-reduce-p1 hi lo)
|
||||
(* 2 (p1)))))
|
||||
|
||||
|
||||
;; p2: the first reduction is less than 2**98
|
||||
(defthmd simple-mod-reduce-p2-<-2**98
|
||||
(implies (and (< hi (expt 2 64))
|
||||
(< lo (expt 2 64))
|
||||
(natp hi) (natp lo))
|
||||
(< (simple-mod-reduce-p2 hi lo)
|
||||
(expt 2 98))))
|
||||
|
||||
;; p2: the second reduction is less than 2**69
|
||||
(defthmd simple-mod-reduce-p2-<-2*69
|
||||
(implies (and (< hi (expt 2 64))
|
||||
(< lo (expt 2 64))
|
||||
(< (join hi lo) (expt 2 98))
|
||||
(natp hi) (natp lo))
|
||||
(< (simple-mod-reduce-p2 hi lo)
|
||||
(expt 2 69))))
|
||||
|
||||
;; p3: the third reduction is less than 2*p2
|
||||
(defthmd simple-mod-reduce-p2-<-2*p2
|
||||
(implies (and (< hi (expt 2 64))
|
||||
(< lo (expt 2 64))
|
||||
(< (join hi lo) (expt 2 69))
|
||||
(natp hi) (natp lo))
|
||||
(< (simple-mod-reduce-p2 hi lo)
|
||||
(* 2 (p2)))))
|
||||
|
||||
|
||||
;; p3: the first reduction is less than 2**104
|
||||
(defthmd simple-mod-reduce-p3-<-2**104
|
||||
(implies (and (< hi (expt 2 64))
|
||||
(< lo (expt 2 64))
|
||||
(natp hi) (natp lo))
|
||||
(< (simple-mod-reduce-p3 hi lo)
|
||||
(expt 2 104))))
|
||||
|
||||
;; p3: the second reduction is less than 2**81
|
||||
(defthmd simple-mod-reduce-p3-<-2**81
|
||||
(implies (and (< hi (expt 2 64))
|
||||
(< lo (expt 2 64))
|
||||
(< (join hi lo) (expt 2 104))
|
||||
(natp hi) (natp lo))
|
||||
(< (simple-mod-reduce-p3 hi lo)
|
||||
(expt 2 81))))
|
||||
|
||||
;; p3: the third reduction is less than 2*p3
|
||||
(defthmd simple-mod-reduce-p3-<-2*p3
|
||||
(implies (and (< hi (expt 2 64))
|
||||
(< lo (expt 2 64))
|
||||
(< (join hi lo) (expt 2 81))
|
||||
(natp hi) (natp lo))
|
||||
(< (simple-mod-reduce-p3 hi lo)
|
||||
(* 2 (p3)))))
|
||||
|
||||
|
||||
; -------------------------------------------------------------------------
|
||||
; The simple modular reductions, adapted for compiler friendly C
|
||||
; -------------------------------------------------------------------------
|
||||
|
||||
(defun mod-reduce-p1 (hi lo)
|
||||
(let* ((y hi)
|
||||
(x y)
|
||||
(hi (>> hi 32))
|
||||
(x (sub lo x))
|
||||
(hi (if (> x lo) (+ hi -1) hi))
|
||||
(y (<< y 32))
|
||||
(lo (add y x))
|
||||
(hi (if (< lo y) (+ hi 1) hi)))
|
||||
(+ (* hi (expt 2 64)) lo)))
|
||||
|
||||
(defun mod-reduce-p2 (hi lo)
|
||||
(let* ((y hi)
|
||||
(x y)
|
||||
(hi (>> hi 30))
|
||||
(x (sub lo x))
|
||||
(hi (if (> x lo) (+ hi -1) hi))
|
||||
(y (<< y 34))
|
||||
(lo (add y x))
|
||||
(hi (if (< lo y) (+ hi 1) hi)))
|
||||
(+ (* hi (expt 2 64)) lo)))
|
||||
|
||||
(defun mod-reduce-p3 (hi lo)
|
||||
(let* ((y hi)
|
||||
(x y)
|
||||
(hi (>> hi 24))
|
||||
(x (sub lo x))
|
||||
(hi (if (> x lo) (+ hi -1) hi))
|
||||
(y (<< y 40))
|
||||
(lo (add y x))
|
||||
(hi (if (< lo y) (+ hi 1) hi)))
|
||||
(+ (* hi (expt 2 64)) lo)))
|
||||
|
||||
|
||||
; -------------------------------------------------------------------------
|
||||
; The compiler friendly versions are equal to the simple versions
|
||||
; -------------------------------------------------------------------------
|
||||
|
||||
(defthm mod-reduce-aux1
|
||||
(implies (and (<= 0 a) (natp a) (natp m)
|
||||
(< (- m) b) (<= b 0)
|
||||
(integerp b)
|
||||
(< (mod (+ b a) m)
|
||||
(mod a m)))
|
||||
(equal (mod (+ b a) m)
|
||||
(+ b (mod a m))))
|
||||
:hints (("Subgoal 2" :use ((:instance modaux-1b
|
||||
(x (+ a b)))))))
|
||||
|
||||
(defthm mod-reduce-aux2
|
||||
(implies (and (<= 0 a) (natp a) (natp m)
|
||||
(< b m) (natp b)
|
||||
(< (mod (+ b a) m)
|
||||
(mod a m)))
|
||||
(equal (+ m (mod (+ b a) m))
|
||||
(+ b (mod a m)))))
|
||||
|
||||
|
||||
(defthm mod-reduce-aux3
|
||||
(implies (and (< 0 a) (natp a) (natp m)
|
||||
(< (- m) b) (< b 0)
|
||||
(integerp b)
|
||||
(<= (mod a m)
|
||||
(mod (+ b a) m)))
|
||||
(equal (+ (- m) (mod (+ b a) m))
|
||||
(+ b (mod a m))))
|
||||
:hints (("Subgoal 1.2'" :use ((:instance modaux-1b
|
||||
(x b))))
|
||||
("Subgoal 1''" :use ((:instance modaux-2d
|
||||
(x I))))))
|
||||
|
||||
|
||||
(defthm mod-reduce-aux4
|
||||
(implies (and (< 0 a) (natp a) (natp m)
|
||||
(< b m) (natp b)
|
||||
(<= (mod a m)
|
||||
(mod (+ b a) m)))
|
||||
(equal (mod (+ b a) m)
|
||||
(+ b (mod a m)))))
|
||||
|
||||
|
||||
(defthm mod-reduce-p1==simple-mod-reduce-p1
|
||||
(implies (and (< hi (expt 2 64))
|
||||
(< lo (expt 2 64))
|
||||
(natp hi) (natp lo))
|
||||
(equal (mod-reduce-p1 hi lo)
|
||||
(simple-mod-reduce-p1 hi lo)))
|
||||
:hints (("Goal" :in-theory (disable expt)
|
||||
:cases ((< 0 hi)))
|
||||
("Subgoal 1.2.2'" :use ((:instance mod-reduce-aux1
|
||||
(m (expt 2 64))
|
||||
(b (+ (- HI) LO))
|
||||
(a (* (expt 2 32) hi)))))
|
||||
("Subgoal 1.2.1'" :use ((:instance mod-reduce-aux3
|
||||
(m (expt 2 64))
|
||||
(b (+ (- HI) LO))
|
||||
(a (* (expt 2 32) hi)))))
|
||||
("Subgoal 1.1.2'" :use ((:instance mod-reduce-aux2
|
||||
(m (expt 2 64))
|
||||
(b (+ (- HI) LO))
|
||||
(a (* (expt 2 32) hi)))))
|
||||
("Subgoal 1.1.1'" :use ((:instance mod-reduce-aux4
|
||||
(m (expt 2 64))
|
||||
(b (+ (- HI) LO))
|
||||
(a (* (expt 2 32) hi)))))))
|
||||
|
||||
|
||||
(defthm mod-reduce-p2==simple-mod-reduce-p2
|
||||
(implies (and (< hi (expt 2 64))
|
||||
(< lo (expt 2 64))
|
||||
(natp hi) (natp lo))
|
||||
(equal (mod-reduce-p2 hi lo)
|
||||
(simple-mod-reduce-p2 hi lo)))
|
||||
:hints (("Goal" :cases ((< 0 hi)))
|
||||
("Subgoal 1.2.2'" :use ((:instance mod-reduce-aux1
|
||||
(m (expt 2 64))
|
||||
(b (+ (- HI) LO))
|
||||
(a (* (expt 2 34) hi)))))
|
||||
("Subgoal 1.2.1'" :use ((:instance mod-reduce-aux3
|
||||
(m (expt 2 64))
|
||||
(b (+ (- HI) LO))
|
||||
(a (* (expt 2 34) hi)))))
|
||||
("Subgoal 1.1.2'" :use ((:instance mod-reduce-aux2
|
||||
(m (expt 2 64))
|
||||
(b (+ (- HI) LO))
|
||||
(a (* (expt 2 34) hi)))))
|
||||
("Subgoal 1.1.1'" :use ((:instance mod-reduce-aux4
|
||||
(m (expt 2 64))
|
||||
(b (+ (- HI) LO))
|
||||
(a (* (expt 2 34) hi)))))))
|
||||
|
||||
|
||||
(defthm mod-reduce-p3==simple-mod-reduce-p3
|
||||
(implies (and (< hi (expt 2 64))
|
||||
(< lo (expt 2 64))
|
||||
(natp hi) (natp lo))
|
||||
(equal (mod-reduce-p3 hi lo)
|
||||
(simple-mod-reduce-p3 hi lo)))
|
||||
:hints (("Goal" :cases ((< 0 hi)))
|
||||
("Subgoal 1.2.2'" :use ((:instance mod-reduce-aux1
|
||||
(m (expt 2 64))
|
||||
(b (+ (- HI) LO))
|
||||
(a (* (expt 2 40) hi)))))
|
||||
("Subgoal 1.2.1'" :use ((:instance mod-reduce-aux3
|
||||
(m (expt 2 64))
|
||||
(b (+ (- HI) LO))
|
||||
(a (* (expt 2 40) hi)))))
|
||||
("Subgoal 1.1.2'" :use ((:instance mod-reduce-aux2
|
||||
(m (expt 2 64))
|
||||
(b (+ (- HI) LO))
|
||||
(a (* (expt 2 40) hi)))))
|
||||
("Subgoal 1.1.1'" :use ((:instance mod-reduce-aux4
|
||||
(m (expt 2 64))
|
||||
(b (+ (- HI) LO))
|
||||
(a (* (expt 2 40) hi)))))))
|
||||
|
||||
|
||||
|
297
third_party/python/Modules/_decimal/libmpdec/memory.c
vendored
Normal file
297
third_party/python/Modules/_decimal/libmpdec/memory.c
vendored
Normal file
|
@ -0,0 +1,297 @@
|
|||
/*
|
||||
* Copyright (c) 2008-2016 Stefan Krah. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
|
||||
#include "mpdecimal.h"
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include "typearith.h"
|
||||
#include "mpalloc.h"
|
||||
|
||||
|
||||
#if defined(_MSC_VER)
|
||||
#pragma warning(disable : 4232)
|
||||
#endif
|
||||
|
||||
|
||||
/* Guaranteed minimum allocation for a coefficient. May be changed once
|
||||
at program start using mpd_setminalloc(). */
|
||||
mpd_ssize_t MPD_MINALLOC = MPD_MINALLOC_MIN;
|
||||
|
||||
/* Custom allocation and free functions */
|
||||
void *(* mpd_mallocfunc)(size_t size) = malloc;
|
||||
void *(* mpd_reallocfunc)(void *ptr, size_t size) = realloc;
|
||||
void *(* mpd_callocfunc)(size_t nmemb, size_t size) = calloc;
|
||||
void (* mpd_free)(void *ptr) = free;
|
||||
|
||||
|
||||
/* emulate calloc if it is not available */
|
||||
void *
|
||||
mpd_callocfunc_em(size_t nmemb, size_t size)
|
||||
{
|
||||
void *ptr;
|
||||
size_t req;
|
||||
mpd_size_t overflow;
|
||||
|
||||
#if MPD_SIZE_MAX < SIZE_MAX
|
||||
/* full_coverage test only */
|
||||
if (nmemb > MPD_SIZE_MAX || size > MPD_SIZE_MAX) {
|
||||
return NULL;
|
||||
}
|
||||
#endif
|
||||
|
||||
req = mul_size_t_overflow((mpd_size_t)nmemb, (mpd_size_t)size,
|
||||
&overflow);
|
||||
if (overflow) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ptr = mpd_mallocfunc(req);
|
||||
if (ptr == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
/* used on uint32_t or uint64_t */
|
||||
memset(ptr, 0, req);
|
||||
|
||||
return ptr;
|
||||
}
|
||||
|
||||
|
||||
/* malloc with overflow checking */
|
||||
void *
|
||||
mpd_alloc(mpd_size_t nmemb, mpd_size_t size)
|
||||
{
|
||||
mpd_size_t req, overflow;
|
||||
|
||||
req = mul_size_t_overflow(nmemb, size, &overflow);
|
||||
if (overflow) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return mpd_mallocfunc(req);
|
||||
}
|
||||
|
||||
/* calloc with overflow checking */
|
||||
void *
|
||||
mpd_calloc(mpd_size_t nmemb, mpd_size_t size)
|
||||
{
|
||||
mpd_size_t overflow;
|
||||
|
||||
(void)mul_size_t_overflow(nmemb, size, &overflow);
|
||||
if (overflow) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return mpd_callocfunc(nmemb, size);
|
||||
}
|
||||
|
||||
/* realloc with overflow checking */
|
||||
void *
|
||||
mpd_realloc(void *ptr, mpd_size_t nmemb, mpd_size_t size, uint8_t *err)
|
||||
{
|
||||
void *new;
|
||||
mpd_size_t req, overflow;
|
||||
|
||||
req = mul_size_t_overflow(nmemb, size, &overflow);
|
||||
if (overflow) {
|
||||
*err = 1;
|
||||
return ptr;
|
||||
}
|
||||
|
||||
new = mpd_reallocfunc(ptr, req);
|
||||
if (new == NULL) {
|
||||
*err = 1;
|
||||
return ptr;
|
||||
}
|
||||
|
||||
return new;
|
||||
}
|
||||
|
||||
/* struct hack malloc with overflow checking */
|
||||
void *
|
||||
mpd_sh_alloc(mpd_size_t struct_size, mpd_size_t nmemb, mpd_size_t size)
|
||||
{
|
||||
mpd_size_t req, overflow;
|
||||
|
||||
req = mul_size_t_overflow(nmemb, size, &overflow);
|
||||
if (overflow) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
req = add_size_t_overflow(req, struct_size, &overflow);
|
||||
if (overflow) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return mpd_mallocfunc(req);
|
||||
}
|
||||
|
||||
|
||||
/* Allocate a new decimal with a coefficient of length 'nwords'. In case
|
||||
of an error the return value is NULL. */
|
||||
mpd_t *
|
||||
mpd_qnew_size(mpd_ssize_t nwords)
|
||||
{
|
||||
mpd_t *result;
|
||||
|
||||
nwords = (nwords < MPD_MINALLOC) ? MPD_MINALLOC : nwords;
|
||||
|
||||
result = mpd_alloc(1, sizeof *result);
|
||||
if (result == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
result->data = mpd_alloc(nwords, sizeof *result->data);
|
||||
if (result->data == NULL) {
|
||||
mpd_free(result);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
result->flags = 0;
|
||||
result->exp = 0;
|
||||
result->digits = 0;
|
||||
result->len = 0;
|
||||
result->alloc = nwords;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/* Allocate a new decimal with a coefficient of length MPD_MINALLOC.
|
||||
In case of an error the return value is NULL. */
|
||||
mpd_t *
|
||||
mpd_qnew(void)
|
||||
{
|
||||
return mpd_qnew_size(MPD_MINALLOC);
|
||||
}
|
||||
|
||||
/* Allocate new decimal. Caller can check for NULL or MPD_Malloc_error.
|
||||
Raises on error. */
|
||||
mpd_t *
|
||||
mpd_new(mpd_context_t *ctx)
|
||||
{
|
||||
mpd_t *result;
|
||||
|
||||
result = mpd_qnew();
|
||||
if (result == NULL) {
|
||||
mpd_addstatus_raise(ctx, MPD_Malloc_error);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/*
|
||||
* Input: 'result' is a static mpd_t with a static coefficient.
|
||||
* Assumption: 'nwords' >= result->alloc.
|
||||
*
|
||||
* Resize the static coefficient to a larger dynamic one and copy the
|
||||
* existing data. If successful, the value of 'result' is unchanged.
|
||||
* Otherwise, set 'result' to NaN and update 'status' with MPD_Malloc_error.
|
||||
*/
|
||||
int
|
||||
mpd_switch_to_dyn(mpd_t *result, mpd_ssize_t nwords, uint32_t *status)
|
||||
{
|
||||
mpd_uint_t *p = result->data;
|
||||
|
||||
assert(nwords >= result->alloc);
|
||||
|
||||
result->data = mpd_alloc(nwords, sizeof *result->data);
|
||||
if (result->data == NULL) {
|
||||
result->data = p;
|
||||
mpd_set_qnan(result);
|
||||
mpd_set_positive(result);
|
||||
result->exp = result->digits = result->len = 0;
|
||||
*status |= MPD_Malloc_error;
|
||||
return 0;
|
||||
}
|
||||
|
||||
memcpy(result->data, p, result->alloc * (sizeof *result->data));
|
||||
result->alloc = nwords;
|
||||
mpd_set_dynamic_data(result);
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Input: 'result' is a static mpd_t with a static coefficient.
|
||||
*
|
||||
* Convert the coefficient to a dynamic one that is initialized to zero. If
|
||||
* malloc fails, set 'result' to NaN and update 'status' with MPD_Malloc_error.
|
||||
*/
|
||||
int
|
||||
mpd_switch_to_dyn_zero(mpd_t *result, mpd_ssize_t nwords, uint32_t *status)
|
||||
{
|
||||
mpd_uint_t *p = result->data;
|
||||
|
||||
result->data = mpd_calloc(nwords, sizeof *result->data);
|
||||
if (result->data == NULL) {
|
||||
result->data = p;
|
||||
mpd_set_qnan(result);
|
||||
mpd_set_positive(result);
|
||||
result->exp = result->digits = result->len = 0;
|
||||
*status |= MPD_Malloc_error;
|
||||
return 0;
|
||||
}
|
||||
|
||||
result->alloc = nwords;
|
||||
mpd_set_dynamic_data(result);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Input: 'result' is a static or a dynamic mpd_t with a dynamic coefficient.
|
||||
* Resize the coefficient to length 'nwords':
|
||||
* Case nwords > result->alloc:
|
||||
* If realloc is successful:
|
||||
* 'result' has a larger coefficient but the same value. Return 1.
|
||||
* Otherwise:
|
||||
* Set 'result' to NaN, update status with MPD_Malloc_error and return 0.
|
||||
* Case nwords < result->alloc:
|
||||
* If realloc is successful:
|
||||
* 'result' has a smaller coefficient. result->len is undefined. Return 1.
|
||||
* Otherwise (unlikely):
|
||||
* 'result' is unchanged. Reuse the now oversized coefficient. Return 1.
|
||||
*/
|
||||
int
|
||||
mpd_realloc_dyn(mpd_t *result, mpd_ssize_t nwords, uint32_t *status)
|
||||
{
|
||||
uint8_t err = 0;
|
||||
|
||||
result->data = mpd_realloc(result->data, nwords, sizeof *result->data, &err);
|
||||
if (!err) {
|
||||
result->alloc = nwords;
|
||||
}
|
||||
else if (nwords > result->alloc) {
|
||||
mpd_set_qnan(result);
|
||||
mpd_set_positive(result);
|
||||
result->exp = result->digits = result->len = 0;
|
||||
*status |= MPD_Malloc_error;
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
51
third_party/python/Modules/_decimal/libmpdec/mpalloc.h
vendored
Normal file
51
third_party/python/Modules/_decimal/libmpdec/mpalloc.h
vendored
Normal file
|
@ -0,0 +1,51 @@
|
|||
/*
|
||||
* Copyright (c) 2008-2016 Stefan Krah. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
|
||||
#ifndef MPALLOC_H
|
||||
#define MPALLOC_H
|
||||
|
||||
|
||||
#include "mpdecimal.h"
|
||||
|
||||
|
||||
/* Internal header file: all symbols have local scope in the DSO */
|
||||
MPD_PRAGMA(MPD_HIDE_SYMBOLS_START)
|
||||
|
||||
|
||||
int mpd_switch_to_dyn(mpd_t *result, mpd_ssize_t size, uint32_t *status);
|
||||
int mpd_switch_to_dyn_zero(mpd_t *result, mpd_ssize_t size, uint32_t *status);
|
||||
int mpd_realloc_dyn(mpd_t *result, mpd_ssize_t size, uint32_t *status);
|
||||
|
||||
|
||||
MPD_PRAGMA(MPD_HIDE_SYMBOLS_END) /* restore previous scope rules */
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
|
8411
third_party/python/Modules/_decimal/libmpdec/mpdecimal.c
vendored
Normal file
8411
third_party/python/Modules/_decimal/libmpdec/mpdecimal.c
vendored
Normal file
File diff suppressed because it is too large
Load diff
847
third_party/python/Modules/_decimal/libmpdec/mpdecimal.h
vendored
Normal file
847
third_party/python/Modules/_decimal/libmpdec/mpdecimal.h
vendored
Normal file
|
@ -0,0 +1,847 @@
|
|||
/*
|
||||
* Copyright (c) 2008-2016 Stefan Krah. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
|
||||
#ifndef MPDECIMAL_H
|
||||
#define MPDECIMAL_H
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#ifndef __STDC_LIMIT_MACROS
|
||||
#define __STDC_LIMIT_MACROS
|
||||
#define MPD_CLEAR_STDC_LIMIT_MACROS
|
||||
#endif
|
||||
#endif
|
||||
|
||||
|
||||
#ifndef _MSC_VER
|
||||
#include "pyconfig.h"
|
||||
#endif
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <limits.h>
|
||||
#include <assert.h>
|
||||
#include <stdint.h>
|
||||
#include <inttypes.h>
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#include "vccompat.h"
|
||||
#ifndef UNUSED
|
||||
#define UNUSED
|
||||
#endif
|
||||
#define MPD_PRAGMA(x)
|
||||
#define MPD_HIDE_SYMBOLS_START
|
||||
#define MPD_HIDE_SYMBOLS_END
|
||||
#define EXTINLINE extern inline
|
||||
#else
|
||||
#ifndef __GNUC_STDC_INLINE__
|
||||
#define __GNUC_STDC_INLINE__ 1
|
||||
#endif
|
||||
#if defined(__GNUC__) && !defined(__INTEL_COMPILER)
|
||||
#define UNUSED __attribute__((unused))
|
||||
#else
|
||||
#define UNUSED
|
||||
#endif
|
||||
#if (defined(__linux__) || defined(__FreeBSD__) || defined(__APPLE__)) && \
|
||||
defined(__GNUC__) && __GNUC__ >= 4 && !defined(__INTEL_COMPILER)
|
||||
#define MPD_PRAGMA(x) _Pragma(x)
|
||||
#define MPD_HIDE_SYMBOLS_START "GCC visibility push(hidden)"
|
||||
#define MPD_HIDE_SYMBOLS_END "GCC visibility pop"
|
||||
#else
|
||||
#define MPD_PRAGMA(x)
|
||||
#define MPD_HIDE_SYMBOLS_START
|
||||
#define MPD_HIDE_SYMBOLS_END
|
||||
#endif
|
||||
#define EXTINLINE
|
||||
#endif
|
||||
|
||||
|
||||
/* This header file is internal for the purpose of building _decimal.so.
|
||||
* All symbols should have local scope in the DSO. */
|
||||
MPD_PRAGMA(MPD_HIDE_SYMBOLS_START)
|
||||
|
||||
|
||||
#if !defined(LEGACY_COMPILER)
|
||||
#if !defined(UINT64_MAX)
|
||||
/* The following #error is just a warning. If the compiler indeed does
|
||||
* not have uint64_t, it is perfectly safe to comment out the #error. */
|
||||
#error "Warning: Compiler without uint64_t. Comment out this line."
|
||||
#define LEGACY_COMPILER
|
||||
#endif
|
||||
#endif
|
||||
|
||||
|
||||
/******************************************************************************/
|
||||
/* Version */
|
||||
/******************************************************************************/
|
||||
|
||||
#define MPD_MAJOR_VERSION 2
|
||||
#define MPD_MINOR_VERSION 4
|
||||
#define MPD_MICRO_VERSION 2
|
||||
|
||||
#define MPD_VERSION "2.4.2"
|
||||
|
||||
#define MPD_VERSION_HEX ((MPD_MAJOR_VERSION << 24) | \
|
||||
(MPD_MINOR_VERSION << 16) | \
|
||||
(MPD_MICRO_VERSION << 8))
|
||||
|
||||
const char *mpd_version(void);
|
||||
|
||||
|
||||
/******************************************************************************/
|
||||
/* Configuration */
|
||||
/******************************************************************************/
|
||||
|
||||
#if defined(UNIVERSAL)
|
||||
#if defined(CONFIG_64) || defined(CONFIG_32)
|
||||
#error "cannot use CONFIG_64 or CONFIG_32 with UNIVERSAL."
|
||||
#endif
|
||||
#if defined(__ppc__)
|
||||
#define CONFIG_32
|
||||
#define ANSI
|
||||
#elif defined(__ppc64__)
|
||||
#define CONFIG_64
|
||||
#define ANSI
|
||||
#elif defined(__i386__)
|
||||
#define CONFIG_32
|
||||
#define ANSI
|
||||
#elif defined(__x86_64__)
|
||||
#define CONFIG_64
|
||||
#define ASM
|
||||
#else
|
||||
#error "unknown architecture for universal build."
|
||||
#endif
|
||||
#endif
|
||||
|
||||
|
||||
/* BEGIN CONFIG_64 */
|
||||
#if defined(CONFIG_64)
|
||||
/* types for modular and base arithmetic */
|
||||
#define MPD_UINT_MAX UINT64_MAX
|
||||
#define MPD_BITS_PER_UINT 64
|
||||
typedef uint64_t mpd_uint_t; /* unsigned mod type */
|
||||
|
||||
#define MPD_SIZE_MAX SIZE_MAX
|
||||
typedef size_t mpd_size_t; /* unsigned size type */
|
||||
|
||||
/* type for exp, digits, len, prec */
|
||||
#define MPD_SSIZE_MAX INT64_MAX
|
||||
#define MPD_SSIZE_MIN INT64_MIN
|
||||
typedef int64_t mpd_ssize_t;
|
||||
#define _mpd_strtossize strtoll
|
||||
|
||||
/* decimal arithmetic */
|
||||
#define MPD_RADIX 10000000000000000000ULL /* 10**19 */
|
||||
#define MPD_RDIGITS 19
|
||||
#define MPD_MAX_POW10 19
|
||||
#define MPD_EXPDIGITS 19 /* MPD_EXPDIGITS <= MPD_RDIGITS+1 */
|
||||
|
||||
#define MPD_MAXTRANSFORM_2N 4294967296ULL /* 2**32 */
|
||||
#define MPD_MAX_PREC 999999999999999999LL
|
||||
#define MPD_MAX_PREC_LOG2 64
|
||||
#define MPD_ELIMIT 1000000000000000000LL
|
||||
#define MPD_MAX_EMAX 999999999999999999LL /* ELIMIT-1 */
|
||||
#define MPD_MIN_EMIN (-999999999999999999LL) /* -EMAX */
|
||||
#define MPD_MIN_ETINY (MPD_MIN_EMIN-(MPD_MAX_PREC-1))
|
||||
#define MPD_EXP_INF 2000000000000000001LL
|
||||
#define MPD_EXP_CLAMP (-4000000000000000001LL)
|
||||
#define MPD_MAXIMPORT 105263157894736842L /* ceil((2*MPD_MAX_PREC)/MPD_RDIGITS) */
|
||||
|
||||
/* conversion specifiers */
|
||||
#define PRI_mpd_uint_t PRIu64
|
||||
#define PRI_mpd_ssize_t PRIi64
|
||||
/* END CONFIG_64 */
|
||||
|
||||
|
||||
/* BEGIN CONFIG_32 */
|
||||
#elif defined(CONFIG_32)
|
||||
/* types for modular and base arithmetic */
|
||||
#define MPD_UINT_MAX UINT32_MAX
|
||||
#define MPD_BITS_PER_UINT 32
|
||||
typedef uint32_t mpd_uint_t; /* unsigned mod type */
|
||||
|
||||
#ifndef LEGACY_COMPILER
|
||||
#define MPD_UUINT_MAX UINT64_MAX
|
||||
typedef uint64_t mpd_uuint_t; /* double width unsigned mod type */
|
||||
#endif
|
||||
|
||||
#define MPD_SIZE_MAX SIZE_MAX
|
||||
typedef size_t mpd_size_t; /* unsigned size type */
|
||||
|
||||
/* type for dec->len, dec->exp, ctx->prec */
|
||||
#define MPD_SSIZE_MAX INT32_MAX
|
||||
#define MPD_SSIZE_MIN INT32_MIN
|
||||
typedef int32_t mpd_ssize_t;
|
||||
#define _mpd_strtossize strtol
|
||||
|
||||
/* decimal arithmetic */
|
||||
#define MPD_RADIX 1000000000UL /* 10**9 */
|
||||
#define MPD_RDIGITS 9
|
||||
#define MPD_MAX_POW10 9
|
||||
#define MPD_EXPDIGITS 10 /* MPD_EXPDIGITS <= MPD_RDIGITS+1 */
|
||||
|
||||
#define MPD_MAXTRANSFORM_2N 33554432UL /* 2**25 */
|
||||
#define MPD_MAX_PREC 425000000L
|
||||
#define MPD_MAX_PREC_LOG2 32
|
||||
#define MPD_ELIMIT 425000001L
|
||||
#define MPD_MAX_EMAX 425000000L /* ELIMIT-1 */
|
||||
#define MPD_MIN_EMIN (-425000000L) /* -EMAX */
|
||||
#define MPD_MIN_ETINY (MPD_MIN_EMIN-(MPD_MAX_PREC-1))
|
||||
#define MPD_EXP_INF 1000000001L /* allows for emax=999999999 in the tests */
|
||||
#define MPD_EXP_CLAMP (-2000000001L) /* allows for emin=-999999999 in the tests */
|
||||
#define MPD_MAXIMPORT 94444445L /* ceil((2*MPD_MAX_PREC)/MPD_RDIGITS) */
|
||||
|
||||
/* conversion specifiers */
|
||||
#define PRI_mpd_uint_t PRIu32
|
||||
#define PRI_mpd_ssize_t PRIi32
|
||||
/* END CONFIG_32 */
|
||||
|
||||
#else
|
||||
#error "define CONFIG_64 or CONFIG_32"
|
||||
#endif
|
||||
/* END CONFIG */
|
||||
|
||||
|
||||
#if MPD_SIZE_MAX != MPD_UINT_MAX
|
||||
#error "unsupported platform: need mpd_size_t == mpd_uint_t"
|
||||
#endif
|
||||
|
||||
|
||||
/******************************************************************************/
|
||||
/* Context */
|
||||
/******************************************************************************/
|
||||
|
||||
enum {
|
||||
MPD_ROUND_UP, /* round away from 0 */
|
||||
MPD_ROUND_DOWN, /* round toward 0 (truncate) */
|
||||
MPD_ROUND_CEILING, /* round toward +infinity */
|
||||
MPD_ROUND_FLOOR, /* round toward -infinity */
|
||||
MPD_ROUND_HALF_UP, /* 0.5 is rounded up */
|
||||
MPD_ROUND_HALF_DOWN, /* 0.5 is rounded down */
|
||||
MPD_ROUND_HALF_EVEN, /* 0.5 is rounded to even */
|
||||
MPD_ROUND_05UP, /* round zero or five away from 0 */
|
||||
MPD_ROUND_TRUNC, /* truncate, but set infinity */
|
||||
MPD_ROUND_GUARD
|
||||
};
|
||||
|
||||
enum { MPD_CLAMP_DEFAULT, MPD_CLAMP_IEEE_754, MPD_CLAMP_GUARD };
|
||||
|
||||
extern const char *mpd_round_string[MPD_ROUND_GUARD];
|
||||
extern const char *mpd_clamp_string[MPD_CLAMP_GUARD];
|
||||
|
||||
|
||||
typedef struct mpd_context_t {
|
||||
mpd_ssize_t prec; /* precision */
|
||||
mpd_ssize_t emax; /* max positive exp */
|
||||
mpd_ssize_t emin; /* min negative exp */
|
||||
uint32_t traps; /* status events that should be trapped */
|
||||
uint32_t status; /* status flags */
|
||||
uint32_t newtrap; /* set by mpd_addstatus_raise() */
|
||||
int round; /* rounding mode */
|
||||
int clamp; /* clamp mode */
|
||||
int allcr; /* all functions correctly rounded */
|
||||
} mpd_context_t;
|
||||
|
||||
|
||||
/* Status flags */
|
||||
#define MPD_Clamped 0x00000001U
|
||||
#define MPD_Conversion_syntax 0x00000002U
|
||||
#define MPD_Division_by_zero 0x00000004U
|
||||
#define MPD_Division_impossible 0x00000008U
|
||||
#define MPD_Division_undefined 0x00000010U
|
||||
#define MPD_Fpu_error 0x00000020U
|
||||
#define MPD_Inexact 0x00000040U
|
||||
#define MPD_Invalid_context 0x00000080U
|
||||
#define MPD_Invalid_operation 0x00000100U
|
||||
#define MPD_Malloc_error 0x00000200U
|
||||
#define MPD_Not_implemented 0x00000400U
|
||||
#define MPD_Overflow 0x00000800U
|
||||
#define MPD_Rounded 0x00001000U
|
||||
#define MPD_Subnormal 0x00002000U
|
||||
#define MPD_Underflow 0x00004000U
|
||||
#define MPD_Max_status (0x00008000U-1U)
|
||||
|
||||
/* Conditions that result in an IEEE 754 exception */
|
||||
#define MPD_IEEE_Invalid_operation (MPD_Conversion_syntax | \
|
||||
MPD_Division_impossible | \
|
||||
MPD_Division_undefined | \
|
||||
MPD_Fpu_error | \
|
||||
MPD_Invalid_context | \
|
||||
MPD_Invalid_operation | \
|
||||
MPD_Malloc_error) \
|
||||
|
||||
/* Errors that require the result of an operation to be set to NaN */
|
||||
#define MPD_Errors (MPD_IEEE_Invalid_operation | \
|
||||
MPD_Division_by_zero)
|
||||
|
||||
/* Default traps */
|
||||
#define MPD_Traps (MPD_IEEE_Invalid_operation | \
|
||||
MPD_Division_by_zero | \
|
||||
MPD_Overflow | \
|
||||
MPD_Underflow)
|
||||
|
||||
/* Official name */
|
||||
#define MPD_Insufficient_storage MPD_Malloc_error
|
||||
|
||||
/* IEEE 754 interchange format contexts */
|
||||
#define MPD_IEEE_CONTEXT_MAX_BITS 512 /* 16*(log2(MPD_MAX_EMAX / 3)-3) */
|
||||
#define MPD_DECIMAL32 32
|
||||
#define MPD_DECIMAL64 64
|
||||
#define MPD_DECIMAL128 128
|
||||
|
||||
|
||||
#define MPD_MINALLOC_MIN 2
|
||||
#define MPD_MINALLOC_MAX 64
|
||||
extern mpd_ssize_t MPD_MINALLOC;
|
||||
extern void (* mpd_traphandler)(mpd_context_t *);
|
||||
void mpd_dflt_traphandler(mpd_context_t *);
|
||||
|
||||
void mpd_setminalloc(mpd_ssize_t n);
|
||||
void mpd_init(mpd_context_t *ctx, mpd_ssize_t prec);
|
||||
|
||||
void mpd_maxcontext(mpd_context_t *ctx);
|
||||
void mpd_defaultcontext(mpd_context_t *ctx);
|
||||
void mpd_basiccontext(mpd_context_t *ctx);
|
||||
int mpd_ieee_context(mpd_context_t *ctx, int bits);
|
||||
|
||||
mpd_ssize_t mpd_getprec(const mpd_context_t *ctx);
|
||||
mpd_ssize_t mpd_getemax(const mpd_context_t *ctx);
|
||||
mpd_ssize_t mpd_getemin(const mpd_context_t *ctx);
|
||||
int mpd_getround(const mpd_context_t *ctx);
|
||||
uint32_t mpd_gettraps(const mpd_context_t *ctx);
|
||||
uint32_t mpd_getstatus(const mpd_context_t *ctx);
|
||||
int mpd_getclamp(const mpd_context_t *ctx);
|
||||
int mpd_getcr(const mpd_context_t *ctx);
|
||||
|
||||
int mpd_qsetprec(mpd_context_t *ctx, mpd_ssize_t prec);
|
||||
int mpd_qsetemax(mpd_context_t *ctx, mpd_ssize_t emax);
|
||||
int mpd_qsetemin(mpd_context_t *ctx, mpd_ssize_t emin);
|
||||
int mpd_qsetround(mpd_context_t *ctx, int newround);
|
||||
int mpd_qsettraps(mpd_context_t *ctx, uint32_t flags);
|
||||
int mpd_qsetstatus(mpd_context_t *ctx, uint32_t flags);
|
||||
int mpd_qsetclamp(mpd_context_t *ctx, int c);
|
||||
int mpd_qsetcr(mpd_context_t *ctx, int c);
|
||||
void mpd_addstatus_raise(mpd_context_t *ctx, uint32_t flags);
|
||||
|
||||
|
||||
/******************************************************************************/
|
||||
/* Decimal Arithmetic */
|
||||
/******************************************************************************/
|
||||
|
||||
/* mpd_t flags */
|
||||
#define MPD_POS ((uint8_t)0)
|
||||
#define MPD_NEG ((uint8_t)1)
|
||||
#define MPD_INF ((uint8_t)2)
|
||||
#define MPD_NAN ((uint8_t)4)
|
||||
#define MPD_SNAN ((uint8_t)8)
|
||||
#define MPD_SPECIAL (MPD_INF|MPD_NAN|MPD_SNAN)
|
||||
#define MPD_STATIC ((uint8_t)16)
|
||||
#define MPD_STATIC_DATA ((uint8_t)32)
|
||||
#define MPD_SHARED_DATA ((uint8_t)64)
|
||||
#define MPD_CONST_DATA ((uint8_t)128)
|
||||
#define MPD_DATAFLAGS (MPD_STATIC_DATA|MPD_SHARED_DATA|MPD_CONST_DATA)
|
||||
|
||||
/* mpd_t */
|
||||
typedef struct mpd_t {
|
||||
uint8_t flags;
|
||||
mpd_ssize_t exp;
|
||||
mpd_ssize_t digits;
|
||||
mpd_ssize_t len;
|
||||
mpd_ssize_t alloc;
|
||||
mpd_uint_t *data;
|
||||
} mpd_t;
|
||||
|
||||
|
||||
typedef unsigned char uchar;
|
||||
|
||||
|
||||
/******************************************************************************/
|
||||
/* Quiet, thread-safe functions */
|
||||
/******************************************************************************/
|
||||
|
||||
/* format specification */
|
||||
typedef struct mpd_spec_t {
|
||||
mpd_ssize_t min_width; /* minimum field width */
|
||||
mpd_ssize_t prec; /* fraction digits or significant digits */
|
||||
char type; /* conversion specifier */
|
||||
char align; /* alignment */
|
||||
char sign; /* sign printing/alignment */
|
||||
char fill[5]; /* fill character */
|
||||
const char *dot; /* decimal point */
|
||||
const char *sep; /* thousands separator */
|
||||
const char *grouping; /* grouping of digits */
|
||||
} mpd_spec_t;
|
||||
|
||||
/* output to a string */
|
||||
char *mpd_to_sci(const mpd_t *dec, int fmt);
|
||||
char *mpd_to_eng(const mpd_t *dec, int fmt);
|
||||
mpd_ssize_t mpd_to_sci_size(char **res, const mpd_t *dec, int fmt);
|
||||
mpd_ssize_t mpd_to_eng_size(char **res, const mpd_t *dec, int fmt);
|
||||
int mpd_validate_lconv(mpd_spec_t *spec);
|
||||
int mpd_parse_fmt_str(mpd_spec_t *spec, const char *fmt, int caps);
|
||||
char *mpd_qformat_spec(const mpd_t *dec, const mpd_spec_t *spec, const mpd_context_t *ctx, uint32_t *status);
|
||||
char *mpd_qformat(const mpd_t *dec, const char *fmt, const mpd_context_t *ctx, uint32_t *status);
|
||||
|
||||
#define MPD_NUM_FLAGS 15
|
||||
#define MPD_MAX_FLAG_STRING 208
|
||||
#define MPD_MAX_FLAG_LIST (MPD_MAX_FLAG_STRING+18)
|
||||
#define MPD_MAX_SIGNAL_LIST 121
|
||||
int mpd_snprint_flags(char *dest, int nmemb, uint32_t flags);
|
||||
int mpd_lsnprint_flags(char *dest, int nmemb, uint32_t flags, const char *flag_string[]);
|
||||
int mpd_lsnprint_signals(char *dest, int nmemb, uint32_t flags, const char *signal_string[]);
|
||||
|
||||
/* output to a file */
|
||||
void mpd_fprint(FILE *file, const mpd_t *dec);
|
||||
void mpd_print(const mpd_t *dec);
|
||||
|
||||
/* assignment from a string */
|
||||
void mpd_qset_string(mpd_t *dec, const char *s, const mpd_context_t *ctx, uint32_t *status);
|
||||
|
||||
/* set to NaN with error flags */
|
||||
void mpd_seterror(mpd_t *result, uint32_t flags, uint32_t *status);
|
||||
/* set a special with sign and type */
|
||||
void mpd_setspecial(mpd_t *dec, uint8_t sign, uint8_t type);
|
||||
/* set coefficient to zero or all nines */
|
||||
void mpd_zerocoeff(mpd_t *result);
|
||||
void mpd_qmaxcoeff(mpd_t *result, const mpd_context_t *ctx, uint32_t *status);
|
||||
|
||||
/* quietly assign a C integer type to an mpd_t */
|
||||
void mpd_qset_ssize(mpd_t *result, mpd_ssize_t a, const mpd_context_t *ctx, uint32_t *status);
|
||||
void mpd_qset_i32(mpd_t *result, int32_t a, const mpd_context_t *ctx, uint32_t *status);
|
||||
void mpd_qset_uint(mpd_t *result, mpd_uint_t a, const mpd_context_t *ctx, uint32_t *status);
|
||||
void mpd_qset_u32(mpd_t *result, uint32_t a, const mpd_context_t *ctx, uint32_t *status);
|
||||
#ifndef LEGACY_COMPILER
|
||||
void mpd_qset_i64(mpd_t *result, int64_t a, const mpd_context_t *ctx, uint32_t *status);
|
||||
void mpd_qset_u64(mpd_t *result, uint64_t a, const mpd_context_t *ctx, uint32_t *status);
|
||||
#endif
|
||||
|
||||
/* quietly assign a C integer type to an mpd_t with a static coefficient */
|
||||
void mpd_qsset_ssize(mpd_t *result, mpd_ssize_t a, const mpd_context_t *ctx, uint32_t *status);
|
||||
void mpd_qsset_i32(mpd_t *result, int32_t a, const mpd_context_t *ctx, uint32_t *status);
|
||||
void mpd_qsset_uint(mpd_t *result, mpd_uint_t a, const mpd_context_t *ctx, uint32_t *status);
|
||||
void mpd_qsset_u32(mpd_t *result, uint32_t a, const mpd_context_t *ctx, uint32_t *status);
|
||||
|
||||
/* quietly get a C integer type from an mpd_t */
|
||||
mpd_ssize_t mpd_qget_ssize(const mpd_t *dec, uint32_t *status);
|
||||
mpd_uint_t mpd_qget_uint(const mpd_t *dec, uint32_t *status);
|
||||
mpd_uint_t mpd_qabs_uint(const mpd_t *dec, uint32_t *status);
|
||||
|
||||
int32_t mpd_qget_i32(const mpd_t *dec, uint32_t *status);
|
||||
uint32_t mpd_qget_u32(const mpd_t *dec, uint32_t *status);
|
||||
#ifndef LEGACY_COMPILER
|
||||
int64_t mpd_qget_i64(const mpd_t *dec, uint32_t *status);
|
||||
uint64_t mpd_qget_u64(const mpd_t *dec, uint32_t *status);
|
||||
#endif
|
||||
|
||||
/* quiet functions */
|
||||
int mpd_qcheck_nan(mpd_t *nanresult, const mpd_t *a, const mpd_context_t *ctx, uint32_t *status);
|
||||
int mpd_qcheck_nans(mpd_t *nanresult, const mpd_t *a, const mpd_t *b, const mpd_context_t *ctx, uint32_t *status);
|
||||
void mpd_qfinalize(mpd_t *result, const mpd_context_t *ctx, uint32_t *status);
|
||||
|
||||
const char *mpd_class(const mpd_t *a, const mpd_context_t *ctx);
|
||||
|
||||
int mpd_qcopy(mpd_t *result, const mpd_t *a, uint32_t *status);
|
||||
mpd_t *mpd_qncopy(const mpd_t *a);
|
||||
int mpd_qcopy_abs(mpd_t *result, const mpd_t *a, uint32_t *status);
|
||||
int mpd_qcopy_negate(mpd_t *result, const mpd_t *a, uint32_t *status);
|
||||
int mpd_qcopy_sign(mpd_t *result, const mpd_t *a, const mpd_t *b, uint32_t *status);
|
||||
|
||||
void mpd_qand(mpd_t *result, const mpd_t *a, const mpd_t *b, const mpd_context_t *ctx, uint32_t *status);
|
||||
void mpd_qinvert(mpd_t *result, const mpd_t *a, const mpd_context_t *ctx, uint32_t *status);
|
||||
void mpd_qlogb(mpd_t *result, const mpd_t *a, const mpd_context_t *ctx, uint32_t *status);
|
||||
void mpd_qor(mpd_t *result, const mpd_t *a, const mpd_t *b, const mpd_context_t *ctx, uint32_t *status);
|
||||
void mpd_qscaleb(mpd_t *result, const mpd_t *a, const mpd_t *b, const mpd_context_t *ctx, uint32_t *status);
|
||||
void mpd_qxor(mpd_t *result, const mpd_t *a, const mpd_t *b, const mpd_context_t *ctx, uint32_t *status);
|
||||
int mpd_same_quantum(const mpd_t *a, const mpd_t *b);
|
||||
|
||||
void mpd_qrotate(mpd_t *result, const mpd_t *a, const mpd_t *b, const mpd_context_t *ctx, uint32_t *status);
|
||||
int mpd_qshiftl(mpd_t *result, const mpd_t *a, mpd_ssize_t n, uint32_t *status);
|
||||
mpd_uint_t mpd_qshiftr(mpd_t *result, const mpd_t *a, mpd_ssize_t n, uint32_t *status);
|
||||
mpd_uint_t mpd_qshiftr_inplace(mpd_t *result, mpd_ssize_t n);
|
||||
void mpd_qshift(mpd_t *result, const mpd_t *a, const mpd_t *b, const mpd_context_t *ctx, uint32_t *status);
|
||||
void mpd_qshiftn(mpd_t *result, const mpd_t *a, mpd_ssize_t n, const mpd_context_t *ctx, uint32_t *status);
|
||||
|
||||
int mpd_qcmp(const mpd_t *a, const mpd_t *b, uint32_t *status);
|
||||
int mpd_qcompare(mpd_t *result, const mpd_t *a, const mpd_t *b, const mpd_context_t *ctx, uint32_t *status);
|
||||
int mpd_qcompare_signal(mpd_t *result, const mpd_t *a, const mpd_t *b, const mpd_context_t *ctx, uint32_t *status);
|
||||
int mpd_cmp_total(const mpd_t *a, const mpd_t *b);
|
||||
int mpd_cmp_total_mag(const mpd_t *a, const mpd_t *b);
|
||||
int mpd_compare_total(mpd_t *result, const mpd_t *a, const mpd_t *b);
|
||||
int mpd_compare_total_mag(mpd_t *result, const mpd_t *a, const mpd_t *b);
|
||||
|
||||
void mpd_qround_to_intx(mpd_t *result, const mpd_t *a, const mpd_context_t *ctx, uint32_t *status);
|
||||
void mpd_qround_to_int(mpd_t *result, const mpd_t *a, const mpd_context_t *ctx, uint32_t *status);
|
||||
void mpd_qtrunc(mpd_t *result, const mpd_t *a, const mpd_context_t *ctx, uint32_t *status);
|
||||
void mpd_qfloor(mpd_t *result, const mpd_t *a, const mpd_context_t *ctx, uint32_t *status);
|
||||
void mpd_qceil(mpd_t *result, const mpd_t *a, const mpd_context_t *ctx, uint32_t *status);
|
||||
|
||||
void mpd_qabs(mpd_t *result, const mpd_t *a, const mpd_context_t *ctx, uint32_t *status);
|
||||
void mpd_qmax(mpd_t *result, const mpd_t *a, const mpd_t *b, const mpd_context_t *ctx, uint32_t *status);
|
||||
void mpd_qmax_mag(mpd_t *result, const mpd_t *a, const mpd_t *b, const mpd_context_t *ctx, uint32_t *status);
|
||||
void mpd_qmin(mpd_t *result, const mpd_t *a, const mpd_t *b, const mpd_context_t *ctx, uint32_t *status);
|
||||
void mpd_qmin_mag(mpd_t *result, const mpd_t *a, const mpd_t *b, const mpd_context_t *ctx, uint32_t *status);
|
||||
void mpd_qminus(mpd_t *result, const mpd_t *a, const mpd_context_t *ctx, uint32_t *status);
|
||||
void mpd_qplus(mpd_t *result, const mpd_t *a, const mpd_context_t *ctx, uint32_t *status);
|
||||
void mpd_qnext_minus(mpd_t *result, const mpd_t *a, const mpd_context_t *ctx, uint32_t *status);
|
||||
void mpd_qnext_plus(mpd_t *result, const mpd_t *a, const mpd_context_t *ctx, uint32_t *status);
|
||||
void mpd_qnext_toward(mpd_t *result, const mpd_t *a, const mpd_t *b, const mpd_context_t *ctx, uint32_t *status);
|
||||
void mpd_qquantize(mpd_t *result, const mpd_t *a, const mpd_t *b, const mpd_context_t *ctx, uint32_t *status);
|
||||
void mpd_qrescale(mpd_t *result, const mpd_t *a, mpd_ssize_t exp, const mpd_context_t *ctx, uint32_t *status);
|
||||
void mpd_qrescale_fmt(mpd_t *result, const mpd_t *a, mpd_ssize_t exp, const mpd_context_t *ctx, uint32_t *status);
|
||||
void mpd_qreduce(mpd_t *result, const mpd_t *a, const mpd_context_t *ctx, uint32_t *status);
|
||||
void mpd_qadd(mpd_t *result, const mpd_t *a, const mpd_t *b, const mpd_context_t *ctx, uint32_t *status);
|
||||
void mpd_qadd_ssize(mpd_t *result, const mpd_t *a, mpd_ssize_t b, const mpd_context_t *ctx, uint32_t *status);
|
||||
void mpd_qadd_i32(mpd_t *result, const mpd_t *a, int32_t b, const mpd_context_t *ctx, uint32_t *status);
|
||||
void mpd_qadd_uint(mpd_t *result, const mpd_t *a, mpd_uint_t b, const mpd_context_t *ctx, uint32_t *status);
|
||||
void mpd_qadd_u32(mpd_t *result, const mpd_t *a, uint32_t b, const mpd_context_t *ctx, uint32_t *status);
|
||||
void mpd_qsub(mpd_t *result, const mpd_t *a, const mpd_t *b, const mpd_context_t *ctx, uint32_t *status);
|
||||
void mpd_qsub_ssize(mpd_t *result, const mpd_t *a, mpd_ssize_t b, const mpd_context_t *ctx, uint32_t *status);
|
||||
void mpd_qsub_i32(mpd_t *result, const mpd_t *a, int32_t b, const mpd_context_t *ctx, uint32_t *status);
|
||||
void mpd_qsub_uint(mpd_t *result, const mpd_t *a, mpd_uint_t b, const mpd_context_t *ctx, uint32_t *status);
|
||||
void mpd_qsub_u32(mpd_t *result, const mpd_t *a, uint32_t b, const mpd_context_t *ctx, uint32_t *status);
|
||||
void mpd_qmul(mpd_t *result, const mpd_t *a, const mpd_t *b, const mpd_context_t *ctx, uint32_t *status);
|
||||
void mpd_qmul_ssize(mpd_t *result, const mpd_t *a, mpd_ssize_t b, const mpd_context_t *ctx, uint32_t *status);
|
||||
void mpd_qmul_i32(mpd_t *result, const mpd_t *a, int32_t b, const mpd_context_t *ctx, uint32_t *status);
|
||||
void mpd_qmul_uint(mpd_t *result, const mpd_t *a, mpd_uint_t b, const mpd_context_t *ctx, uint32_t *status);
|
||||
void mpd_qmul_u32(mpd_t *result, const mpd_t *a, uint32_t b, const mpd_context_t *ctx, uint32_t *status);
|
||||
void mpd_qfma(mpd_t *result, const mpd_t *a, const mpd_t *b, const mpd_t *c, const mpd_context_t *ctx, uint32_t *status);
|
||||
void mpd_qdiv(mpd_t *q, const mpd_t *a, const mpd_t *b, const mpd_context_t *ctx, uint32_t *status);
|
||||
void mpd_qdiv_ssize(mpd_t *result, const mpd_t *a, mpd_ssize_t b, const mpd_context_t *ctx, uint32_t *status);
|
||||
void mpd_qdiv_i32(mpd_t *result, const mpd_t *a, int32_t b, const mpd_context_t *ctx, uint32_t *status);
|
||||
void mpd_qdiv_uint(mpd_t *result, const mpd_t *a, mpd_uint_t b, const mpd_context_t *ctx, uint32_t *status);
|
||||
void mpd_qdiv_u32(mpd_t *result, const mpd_t *a, uint32_t b, const mpd_context_t *ctx, uint32_t *status);
|
||||
void mpd_qdivint(mpd_t *q, const mpd_t *a, const mpd_t *b, const mpd_context_t *ctx, uint32_t *status);
|
||||
void mpd_qrem(mpd_t *r, const mpd_t *a, const mpd_t *b, const mpd_context_t *ctx, uint32_t *status);
|
||||
void mpd_qrem_near(mpd_t *r, const mpd_t *a, const mpd_t *b, const mpd_context_t *ctx, uint32_t *status);
|
||||
void mpd_qdivmod(mpd_t *q, mpd_t *r, const mpd_t *a, const mpd_t *b, const mpd_context_t *ctx, uint32_t *status);
|
||||
void mpd_qpow(mpd_t *result, const mpd_t *base, const mpd_t *exp, const mpd_context_t *ctx, uint32_t *status);
|
||||
void mpd_qpowmod(mpd_t *result, const mpd_t *base, const mpd_t *exp, const mpd_t *mod, const mpd_context_t *ctx, uint32_t *status);
|
||||
void mpd_qexp(mpd_t *result, const mpd_t *a, const mpd_context_t *ctx, uint32_t *status);
|
||||
void mpd_qln10(mpd_t *result, mpd_ssize_t prec, uint32_t *status);
|
||||
void mpd_qln(mpd_t *result, const mpd_t *a, const mpd_context_t *ctx, uint32_t *status);
|
||||
void mpd_qlog10(mpd_t *result, const mpd_t *a, const mpd_context_t *ctx, uint32_t *status);
|
||||
void mpd_qsqrt(mpd_t *result, const mpd_t *a, const mpd_context_t *ctx, uint32_t *status);
|
||||
void mpd_qinvroot(mpd_t *result, const mpd_t *a, const mpd_context_t *ctx, uint32_t *status);
|
||||
|
||||
#ifndef LEGACY_COMPILER
|
||||
void mpd_qadd_i64(mpd_t *result, const mpd_t *a, int64_t b, const mpd_context_t *ctx, uint32_t *status);
|
||||
void mpd_qadd_u64(mpd_t *result, const mpd_t *a, uint64_t b, const mpd_context_t *ctx, uint32_t *status);
|
||||
void mpd_qsub_i64(mpd_t *result, const mpd_t *a, int64_t b, const mpd_context_t *ctx, uint32_t *status);
|
||||
void mpd_qsub_u64(mpd_t *result, const mpd_t *a, uint64_t b, const mpd_context_t *ctx, uint32_t *status);
|
||||
void mpd_qmul_i64(mpd_t *result, const mpd_t *a, int64_t b, const mpd_context_t *ctx, uint32_t *status);
|
||||
void mpd_qmul_u64(mpd_t *result, const mpd_t *a, uint64_t b, const mpd_context_t *ctx, uint32_t *status);
|
||||
void mpd_qdiv_i64(mpd_t *result, const mpd_t *a, int64_t b, const mpd_context_t *ctx, uint32_t *status);
|
||||
void mpd_qdiv_u64(mpd_t *result, const mpd_t *a, uint64_t b, const mpd_context_t *ctx, uint32_t *status);
|
||||
#endif
|
||||
|
||||
|
||||
size_t mpd_sizeinbase(const mpd_t *a, uint32_t base);
|
||||
void mpd_qimport_u16(mpd_t *result, const uint16_t *srcdata, size_t srclen,
|
||||
uint8_t srcsign, uint32_t srcbase,
|
||||
const mpd_context_t *ctx, uint32_t *status);
|
||||
void mpd_qimport_u32(mpd_t *result, const uint32_t *srcdata, size_t srclen,
|
||||
uint8_t srcsign, uint32_t srcbase,
|
||||
const mpd_context_t *ctx, uint32_t *status);
|
||||
size_t mpd_qexport_u16(uint16_t **rdata, size_t rlen, uint32_t base,
|
||||
const mpd_t *src, uint32_t *status);
|
||||
size_t mpd_qexport_u32(uint32_t **rdata, size_t rlen, uint32_t base,
|
||||
const mpd_t *src, uint32_t *status);
|
||||
|
||||
|
||||
/******************************************************************************/
|
||||
/* Signalling functions */
|
||||
/******************************************************************************/
|
||||
|
||||
char *mpd_format(const mpd_t *dec, const char *fmt, mpd_context_t *ctx);
|
||||
void mpd_import_u16(mpd_t *result, const uint16_t *srcdata, size_t srclen, uint8_t srcsign, uint32_t base, mpd_context_t *ctx);
|
||||
void mpd_import_u32(mpd_t *result, const uint32_t *srcdata, size_t srclen, uint8_t srcsign, uint32_t base, mpd_context_t *ctx);
|
||||
size_t mpd_export_u16(uint16_t **rdata, size_t rlen, uint32_t base, const mpd_t *src, mpd_context_t *ctx);
|
||||
size_t mpd_export_u32(uint32_t **rdata, size_t rlen, uint32_t base, const mpd_t *src, mpd_context_t *ctx);
|
||||
void mpd_finalize(mpd_t *result, mpd_context_t *ctx);
|
||||
int mpd_check_nan(mpd_t *result, const mpd_t *a, mpd_context_t *ctx);
|
||||
int mpd_check_nans(mpd_t *result, const mpd_t *a, const mpd_t *b, mpd_context_t *ctx);
|
||||
void mpd_set_string(mpd_t *result, const char *s, mpd_context_t *ctx);
|
||||
void mpd_maxcoeff(mpd_t *result, mpd_context_t *ctx);
|
||||
void mpd_sset_ssize(mpd_t *result, mpd_ssize_t a, mpd_context_t *ctx);
|
||||
void mpd_sset_i32(mpd_t *result, int32_t a, mpd_context_t *ctx);
|
||||
void mpd_sset_uint(mpd_t *result, mpd_uint_t a, mpd_context_t *ctx);
|
||||
void mpd_sset_u32(mpd_t *result, uint32_t a, mpd_context_t *ctx);
|
||||
void mpd_set_ssize(mpd_t *result, mpd_ssize_t a, mpd_context_t *ctx);
|
||||
void mpd_set_i32(mpd_t *result, int32_t a, mpd_context_t *ctx);
|
||||
void mpd_set_uint(mpd_t *result, mpd_uint_t a, mpd_context_t *ctx);
|
||||
void mpd_set_u32(mpd_t *result, uint32_t a, mpd_context_t *ctx);
|
||||
#ifndef LEGACY_COMPILER
|
||||
void mpd_set_i64(mpd_t *result, int64_t a, mpd_context_t *ctx);
|
||||
void mpd_set_u64(mpd_t *result, uint64_t a, mpd_context_t *ctx);
|
||||
#endif
|
||||
mpd_ssize_t mpd_get_ssize(const mpd_t *a, mpd_context_t *ctx);
|
||||
mpd_uint_t mpd_get_uint(const mpd_t *a, mpd_context_t *ctx);
|
||||
mpd_uint_t mpd_abs_uint(const mpd_t *a, mpd_context_t *ctx);
|
||||
int32_t mpd_get_i32(const mpd_t *a, mpd_context_t *ctx);
|
||||
uint32_t mpd_get_u32(const mpd_t *a, mpd_context_t *ctx);
|
||||
#ifndef LEGACY_COMPILER
|
||||
int64_t mpd_get_i64(const mpd_t *a, mpd_context_t *ctx);
|
||||
uint64_t mpd_get_u64(const mpd_t *a, mpd_context_t *ctx);
|
||||
#endif
|
||||
void mpd_and(mpd_t *result, const mpd_t *a, const mpd_t *b, mpd_context_t *ctx);
|
||||
void mpd_copy(mpd_t *result, const mpd_t *a, mpd_context_t *ctx);
|
||||
void mpd_canonical(mpd_t *result, const mpd_t *a, mpd_context_t *ctx);
|
||||
void mpd_copy_abs(mpd_t *result, const mpd_t *a, mpd_context_t *ctx);
|
||||
void mpd_copy_negate(mpd_t *result, const mpd_t *a, mpd_context_t *ctx);
|
||||
void mpd_copy_sign(mpd_t *result, const mpd_t *a, const mpd_t *b, mpd_context_t *ctx);
|
||||
void mpd_invert(mpd_t *result, const mpd_t *a, mpd_context_t *ctx);
|
||||
void mpd_logb(mpd_t *result, const mpd_t *a, mpd_context_t *ctx);
|
||||
void mpd_or(mpd_t *result, const mpd_t *a, const mpd_t *b, mpd_context_t *ctx);
|
||||
void mpd_rotate(mpd_t *result, const mpd_t *a, const mpd_t *b, mpd_context_t *ctx);
|
||||
void mpd_scaleb(mpd_t *result, const mpd_t *a, const mpd_t *b, mpd_context_t *ctx);
|
||||
void mpd_shiftl(mpd_t *result, const mpd_t *a, mpd_ssize_t n, mpd_context_t *ctx);
|
||||
mpd_uint_t mpd_shiftr(mpd_t *result, const mpd_t *a, mpd_ssize_t n, mpd_context_t *ctx);
|
||||
void mpd_shiftn(mpd_t *result, const mpd_t *a, mpd_ssize_t n, mpd_context_t *ctx);
|
||||
void mpd_shift(mpd_t *result, const mpd_t *a, const mpd_t *b, mpd_context_t *ctx);
|
||||
void mpd_xor(mpd_t *result, const mpd_t *a, const mpd_t *b, mpd_context_t *ctx);
|
||||
void mpd_abs(mpd_t *result, const mpd_t *a, mpd_context_t *ctx);
|
||||
int mpd_cmp(const mpd_t *a, const mpd_t *b, mpd_context_t *ctx);
|
||||
int mpd_compare(mpd_t *result, const mpd_t *a, const mpd_t *b, mpd_context_t *ctx);
|
||||
int mpd_compare_signal(mpd_t *result, const mpd_t *a, const mpd_t *b, mpd_context_t *ctx);
|
||||
void mpd_add(mpd_t *result, const mpd_t *a, const mpd_t *b, mpd_context_t *ctx);
|
||||
void mpd_add_ssize(mpd_t *result, const mpd_t *a, mpd_ssize_t b, mpd_context_t *ctx);
|
||||
void mpd_add_i32(mpd_t *result, const mpd_t *a, int32_t b, mpd_context_t *ctx);
|
||||
void mpd_add_uint(mpd_t *result, const mpd_t *a, mpd_uint_t b, mpd_context_t *ctx);
|
||||
void mpd_add_u32(mpd_t *result, const mpd_t *a, uint32_t b, mpd_context_t *ctx);
|
||||
void mpd_sub(mpd_t *result, const mpd_t *a, const mpd_t *b, mpd_context_t *ctx);
|
||||
void mpd_sub_ssize(mpd_t *result, const mpd_t *a, mpd_ssize_t b, mpd_context_t *ctx);
|
||||
void mpd_sub_i32(mpd_t *result, const mpd_t *a, int32_t b, mpd_context_t *ctx);
|
||||
void mpd_sub_uint(mpd_t *result, const mpd_t *a, mpd_uint_t b, mpd_context_t *ctx);
|
||||
void mpd_sub_u32(mpd_t *result, const mpd_t *a, uint32_t b, mpd_context_t *ctx);
|
||||
void mpd_div(mpd_t *q, const mpd_t *a, const mpd_t *b, mpd_context_t *ctx);
|
||||
void mpd_div_ssize(mpd_t *result, const mpd_t *a, mpd_ssize_t b, mpd_context_t *ctx);
|
||||
void mpd_div_i32(mpd_t *result, const mpd_t *a, int32_t b, mpd_context_t *ctx);
|
||||
void mpd_div_uint(mpd_t *result, const mpd_t *a, mpd_uint_t b, mpd_context_t *ctx);
|
||||
void mpd_div_u32(mpd_t *result, const mpd_t *a, uint32_t b, mpd_context_t *ctx);
|
||||
void mpd_divmod(mpd_t *q, mpd_t *r, const mpd_t *a, const mpd_t *b, mpd_context_t *ctx);
|
||||
void mpd_divint(mpd_t *q, const mpd_t *a, const mpd_t *b, mpd_context_t *ctx);
|
||||
void mpd_exp(mpd_t *result, const mpd_t *a, mpd_context_t *ctx);
|
||||
void mpd_fma(mpd_t *result, const mpd_t *a, const mpd_t *b, const mpd_t *c, mpd_context_t *ctx);
|
||||
void mpd_ln(mpd_t *result, const mpd_t *a, mpd_context_t *ctx);
|
||||
void mpd_log10(mpd_t *result, const mpd_t *a, mpd_context_t *ctx);
|
||||
void mpd_max(mpd_t *result, const mpd_t *a, const mpd_t *b, mpd_context_t *ctx);
|
||||
void mpd_max_mag(mpd_t *result, const mpd_t *a, const mpd_t *b, mpd_context_t *ctx);
|
||||
void mpd_min(mpd_t *result, const mpd_t *a, const mpd_t *b, mpd_context_t *ctx);
|
||||
void mpd_min_mag(mpd_t *result, const mpd_t *a, const mpd_t *b, mpd_context_t *ctx);
|
||||
void mpd_minus(mpd_t *result, const mpd_t *a, mpd_context_t *ctx);
|
||||
void mpd_mul(mpd_t *result, const mpd_t *a, const mpd_t *b, mpd_context_t *ctx);
|
||||
void mpd_mul_ssize(mpd_t *result, const mpd_t *a, mpd_ssize_t b, mpd_context_t *ctx);
|
||||
void mpd_mul_i32(mpd_t *result, const mpd_t *a, int32_t b, mpd_context_t *ctx);
|
||||
void mpd_mul_uint(mpd_t *result, const mpd_t *a, mpd_uint_t b, mpd_context_t *ctx);
|
||||
void mpd_mul_u32(mpd_t *result, const mpd_t *a, uint32_t b, mpd_context_t *ctx);
|
||||
void mpd_next_minus(mpd_t *result, const mpd_t *a, mpd_context_t *ctx);
|
||||
void mpd_next_plus(mpd_t *result, const mpd_t *a, mpd_context_t *ctx);
|
||||
void mpd_next_toward(mpd_t *result, const mpd_t *a, const mpd_t *b, mpd_context_t *ctx);
|
||||
void mpd_plus(mpd_t *result, const mpd_t *a, mpd_context_t *ctx);
|
||||
void mpd_pow(mpd_t *result, const mpd_t *base, const mpd_t *exp, mpd_context_t *ctx);
|
||||
void mpd_powmod(mpd_t *result, const mpd_t *base, const mpd_t *exp, const mpd_t *mod, mpd_context_t *ctx);
|
||||
void mpd_quantize(mpd_t *result, const mpd_t *a, const mpd_t *b, mpd_context_t *ctx);
|
||||
void mpd_rescale(mpd_t *result, const mpd_t *a, mpd_ssize_t exp, mpd_context_t *ctx);
|
||||
void mpd_reduce(mpd_t *result, const mpd_t *a, mpd_context_t *ctx);
|
||||
void mpd_rem(mpd_t *r, const mpd_t *a, const mpd_t *b, mpd_context_t *ctx);
|
||||
void mpd_rem_near(mpd_t *r, const mpd_t *a, const mpd_t *b, mpd_context_t *ctx);
|
||||
void mpd_round_to_intx(mpd_t *result, const mpd_t *a, mpd_context_t *ctx);
|
||||
void mpd_round_to_int(mpd_t *result, const mpd_t *a, mpd_context_t *ctx);
|
||||
void mpd_trunc(mpd_t *result, const mpd_t *a, mpd_context_t *ctx);
|
||||
void mpd_floor(mpd_t *result, const mpd_t *a, mpd_context_t *ctx);
|
||||
void mpd_ceil(mpd_t *result, const mpd_t *a, mpd_context_t *ctx);
|
||||
void mpd_sqrt(mpd_t *result, const mpd_t *a, mpd_context_t *ctx);
|
||||
void mpd_invroot(mpd_t *result, const mpd_t *a, mpd_context_t *ctx);
|
||||
|
||||
#ifndef LEGACY_COMPILER
|
||||
void mpd_add_i64(mpd_t *result, const mpd_t *a, int64_t b, mpd_context_t *ctx);
|
||||
void mpd_add_u64(mpd_t *result, const mpd_t *a, uint64_t b, mpd_context_t *ctx);
|
||||
void mpd_sub_i64(mpd_t *result, const mpd_t *a, int64_t b, mpd_context_t *ctx);
|
||||
void mpd_sub_u64(mpd_t *result, const mpd_t *a, uint64_t b, mpd_context_t *ctx);
|
||||
void mpd_div_i64(mpd_t *result, const mpd_t *a, int64_t b, mpd_context_t *ctx);
|
||||
void mpd_div_u64(mpd_t *result, const mpd_t *a, uint64_t b, mpd_context_t *ctx);
|
||||
void mpd_mul_i64(mpd_t *result, const mpd_t *a, int64_t b, mpd_context_t *ctx);
|
||||
void mpd_mul_u64(mpd_t *result, const mpd_t *a, uint64_t b, mpd_context_t *ctx);
|
||||
#endif
|
||||
|
||||
|
||||
/******************************************************************************/
|
||||
/* Configuration specific */
|
||||
/******************************************************************************/
|
||||
|
||||
#ifdef CONFIG_64
|
||||
void mpd_qsset_i64(mpd_t *result, int64_t a, const mpd_context_t *ctx, uint32_t *status);
|
||||
void mpd_qsset_u64(mpd_t *result, uint64_t a, const mpd_context_t *ctx, uint32_t *status);
|
||||
void mpd_sset_i64(mpd_t *result, int64_t a, mpd_context_t *ctx);
|
||||
void mpd_sset_u64(mpd_t *result, uint64_t a, mpd_context_t *ctx);
|
||||
#endif
|
||||
|
||||
|
||||
/******************************************************************************/
|
||||
/* Get attributes of a decimal */
|
||||
/******************************************************************************/
|
||||
|
||||
EXTINLINE mpd_ssize_t mpd_adjexp(const mpd_t *dec);
|
||||
EXTINLINE mpd_ssize_t mpd_etiny(const mpd_context_t *ctx);
|
||||
EXTINLINE mpd_ssize_t mpd_etop(const mpd_context_t *ctx);
|
||||
EXTINLINE mpd_uint_t mpd_msword(const mpd_t *dec);
|
||||
EXTINLINE int mpd_word_digits(mpd_uint_t word);
|
||||
/* most significant digit of a word */
|
||||
EXTINLINE mpd_uint_t mpd_msd(mpd_uint_t word);
|
||||
/* least significant digit of a word */
|
||||
EXTINLINE mpd_uint_t mpd_lsd(mpd_uint_t word);
|
||||
/* coefficient size needed to store 'digits' */
|
||||
EXTINLINE mpd_ssize_t mpd_digits_to_size(mpd_ssize_t digits);
|
||||
/* number of digits in the exponent, undefined for MPD_SSIZE_MIN */
|
||||
EXTINLINE int mpd_exp_digits(mpd_ssize_t exp);
|
||||
EXTINLINE int mpd_iscanonical(const mpd_t *dec UNUSED);
|
||||
EXTINLINE int mpd_isfinite(const mpd_t *dec);
|
||||
EXTINLINE int mpd_isinfinite(const mpd_t *dec);
|
||||
EXTINLINE int mpd_isinteger(const mpd_t *dec);
|
||||
EXTINLINE int mpd_isnan(const mpd_t *dec);
|
||||
EXTINLINE int mpd_isnegative(const mpd_t *dec);
|
||||
EXTINLINE int mpd_ispositive(const mpd_t *dec);
|
||||
EXTINLINE int mpd_isqnan(const mpd_t *dec);
|
||||
EXTINLINE int mpd_issigned(const mpd_t *dec);
|
||||
EXTINLINE int mpd_issnan(const mpd_t *dec);
|
||||
EXTINLINE int mpd_isspecial(const mpd_t *dec);
|
||||
EXTINLINE int mpd_iszero(const mpd_t *dec);
|
||||
/* undefined for special numbers */
|
||||
EXTINLINE int mpd_iszerocoeff(const mpd_t *dec);
|
||||
EXTINLINE int mpd_isnormal(const mpd_t *dec, const mpd_context_t *ctx);
|
||||
EXTINLINE int mpd_issubnormal(const mpd_t *dec, const mpd_context_t *ctx);
|
||||
/* odd word */
|
||||
EXTINLINE int mpd_isoddword(mpd_uint_t word);
|
||||
/* odd coefficient */
|
||||
EXTINLINE int mpd_isoddcoeff(const mpd_t *dec);
|
||||
/* odd decimal, only defined for integers */
|
||||
int mpd_isodd(const mpd_t *dec);
|
||||
/* even decimal, only defined for integers */
|
||||
int mpd_iseven(const mpd_t *dec);
|
||||
/* 0 if dec is positive, 1 if dec is negative */
|
||||
EXTINLINE uint8_t mpd_sign(const mpd_t *dec);
|
||||
/* 1 if dec is positive, -1 if dec is negative */
|
||||
EXTINLINE int mpd_arith_sign(const mpd_t *dec);
|
||||
EXTINLINE long mpd_radix(void);
|
||||
EXTINLINE int mpd_isdynamic(const mpd_t *dec);
|
||||
EXTINLINE int mpd_isstatic(const mpd_t *dec);
|
||||
EXTINLINE int mpd_isdynamic_data(const mpd_t *dec);
|
||||
EXTINLINE int mpd_isstatic_data(const mpd_t *dec);
|
||||
EXTINLINE int mpd_isshared_data(const mpd_t *dec);
|
||||
EXTINLINE int mpd_isconst_data(const mpd_t *dec);
|
||||
EXTINLINE mpd_ssize_t mpd_trail_zeros(const mpd_t *dec);
|
||||
|
||||
|
||||
/******************************************************************************/
|
||||
/* Set attributes of a decimal */
|
||||
/******************************************************************************/
|
||||
|
||||
/* set number of decimal digits in the coefficient */
|
||||
EXTINLINE void mpd_setdigits(mpd_t *result);
|
||||
EXTINLINE void mpd_set_sign(mpd_t *result, uint8_t sign);
|
||||
/* copy sign from another decimal */
|
||||
EXTINLINE void mpd_signcpy(mpd_t *result, const mpd_t *a);
|
||||
EXTINLINE void mpd_set_infinity(mpd_t *result);
|
||||
EXTINLINE void mpd_set_qnan(mpd_t *result);
|
||||
EXTINLINE void mpd_set_snan(mpd_t *result);
|
||||
EXTINLINE void mpd_set_negative(mpd_t *result);
|
||||
EXTINLINE void mpd_set_positive(mpd_t *result);
|
||||
EXTINLINE void mpd_set_dynamic(mpd_t *result);
|
||||
EXTINLINE void mpd_set_static(mpd_t *result);
|
||||
EXTINLINE void mpd_set_dynamic_data(mpd_t *result);
|
||||
EXTINLINE void mpd_set_static_data(mpd_t *result);
|
||||
EXTINLINE void mpd_set_shared_data(mpd_t *result);
|
||||
EXTINLINE void mpd_set_const_data(mpd_t *result);
|
||||
EXTINLINE void mpd_clear_flags(mpd_t *result);
|
||||
EXTINLINE void mpd_set_flags(mpd_t *result, uint8_t flags);
|
||||
EXTINLINE void mpd_copy_flags(mpd_t *result, const mpd_t *a);
|
||||
|
||||
|
||||
/******************************************************************************/
|
||||
/* Error Macros */
|
||||
/******************************************************************************/
|
||||
|
||||
#define mpd_err_fatal(...) \
|
||||
do {fprintf(stderr, "%s:%d: error: ", __FILE__, __LINE__); \
|
||||
fprintf(stderr, __VA_ARGS__); fputc('\n', stderr); \
|
||||
abort(); \
|
||||
} while (0)
|
||||
#define mpd_err_warn(...) \
|
||||
do {fprintf(stderr, "%s:%d: warning: ", __FILE__, __LINE__); \
|
||||
fprintf(stderr, __VA_ARGS__); fputc('\n', stderr); \
|
||||
} while (0)
|
||||
|
||||
|
||||
/******************************************************************************/
|
||||
/* Memory handling */
|
||||
/******************************************************************************/
|
||||
|
||||
extern void *(* mpd_mallocfunc)(size_t size);
|
||||
extern void *(* mpd_callocfunc)(size_t nmemb, size_t size);
|
||||
extern void *(* mpd_reallocfunc)(void *ptr, size_t size);
|
||||
extern void (* mpd_free)(void *ptr);
|
||||
|
||||
void *mpd_callocfunc_em(size_t nmemb, size_t size);
|
||||
|
||||
void *mpd_alloc(mpd_size_t nmemb, mpd_size_t size);
|
||||
void *mpd_calloc(mpd_size_t nmemb, mpd_size_t size);
|
||||
void *mpd_realloc(void *ptr, mpd_size_t nmemb, mpd_size_t size, uint8_t *err);
|
||||
void *mpd_sh_alloc(mpd_size_t struct_size, mpd_size_t nmemb, mpd_size_t size);
|
||||
|
||||
mpd_t *mpd_qnew(void);
|
||||
mpd_t *mpd_new(mpd_context_t *ctx);
|
||||
mpd_t *mpd_qnew_size(mpd_ssize_t size);
|
||||
EXTINLINE void mpd_del(mpd_t *dec);
|
||||
|
||||
EXTINLINE void mpd_uint_zero(mpd_uint_t *dest, mpd_size_t len);
|
||||
EXTINLINE int mpd_qresize(mpd_t *result, mpd_ssize_t size, uint32_t *status);
|
||||
EXTINLINE int mpd_qresize_zero(mpd_t *result, mpd_ssize_t size, uint32_t *status);
|
||||
EXTINLINE void mpd_minalloc(mpd_t *result);
|
||||
|
||||
int mpd_resize(mpd_t *result, mpd_ssize_t size, mpd_context_t *ctx);
|
||||
int mpd_resize_zero(mpd_t *result, mpd_ssize_t size, mpd_context_t *ctx);
|
||||
|
||||
|
||||
MPD_PRAGMA(MPD_HIDE_SYMBOLS_END) /* restore previous scope rules */
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
#ifdef MPD_CLEAR_STDC_LIMIT_MACROS
|
||||
#undef MPD_CLEAR_STDC_LIMIT_MACROS
|
||||
#undef __STDC_LIMIT_MACROS
|
||||
#endif
|
||||
} /* END extern "C" */
|
||||
#endif
|
||||
|
||||
|
||||
#endif /* MPDECIMAL_H */
|
||||
|
||||
|
||||
|
132
third_party/python/Modules/_decimal/libmpdec/numbertheory.c
vendored
Normal file
132
third_party/python/Modules/_decimal/libmpdec/numbertheory.c
vendored
Normal file
|
@ -0,0 +1,132 @@
|
|||
/*
|
||||
* Copyright (c) 2008-2016 Stefan Krah. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
|
||||
#include "mpdecimal.h"
|
||||
#include <stdlib.h>
|
||||
#include <assert.h>
|
||||
#include "bits.h"
|
||||
#include "umodarith.h"
|
||||
#include "numbertheory.h"
|
||||
|
||||
|
||||
/* Bignum: Initialize the Number Theoretic Transform. */
|
||||
|
||||
|
||||
/*
|
||||
* Return the nth root of unity in F(p). This corresponds to e**((2*pi*i)/n)
|
||||
* in the Fourier transform. We have w**n == 1 (mod p).
|
||||
* n := transform length.
|
||||
* sign := -1 for forward transform, 1 for backward transform.
|
||||
* modnum := one of {P1, P2, P3}.
|
||||
*/
|
||||
mpd_uint_t
|
||||
_mpd_getkernel(mpd_uint_t n, int sign, int modnum)
|
||||
{
|
||||
mpd_uint_t umod, p, r, xi;
|
||||
#ifdef PPRO
|
||||
double dmod;
|
||||
uint32_t dinvmod[3];
|
||||
#endif
|
||||
|
||||
SETMODULUS(modnum);
|
||||
r = mpd_roots[modnum]; /* primitive root of F(p) */
|
||||
p = umod;
|
||||
xi = (p-1) / n;
|
||||
|
||||
if (sign == -1)
|
||||
return POWMOD(r, (p-1-xi));
|
||||
else
|
||||
return POWMOD(r, xi);
|
||||
}
|
||||
|
||||
/*
|
||||
* Initialize and return transform parameters.
|
||||
* n := transform length.
|
||||
* sign := -1 for forward transform, 1 for backward transform.
|
||||
* modnum := one of {P1, P2, P3}.
|
||||
*/
|
||||
struct fnt_params *
|
||||
_mpd_init_fnt_params(mpd_size_t n, int sign, int modnum)
|
||||
{
|
||||
struct fnt_params *tparams;
|
||||
mpd_uint_t umod;
|
||||
#ifdef PPRO
|
||||
double dmod;
|
||||
uint32_t dinvmod[3];
|
||||
#endif
|
||||
mpd_uint_t kernel, w;
|
||||
mpd_uint_t i;
|
||||
mpd_size_t nhalf;
|
||||
|
||||
assert(ispower2(n));
|
||||
assert(sign == -1 || sign == 1);
|
||||
assert(P1 <= modnum && modnum <= P3);
|
||||
|
||||
nhalf = n/2;
|
||||
tparams = mpd_sh_alloc(sizeof *tparams, nhalf, sizeof (mpd_uint_t));
|
||||
if (tparams == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
SETMODULUS(modnum);
|
||||
kernel = _mpd_getkernel(n, sign, modnum);
|
||||
|
||||
tparams->modnum = modnum;
|
||||
tparams->modulus = umod;
|
||||
tparams->kernel = kernel;
|
||||
|
||||
/* wtable[] := w**0, w**1, ..., w**(nhalf-1) */
|
||||
w = 1;
|
||||
for (i = 0; i < nhalf; i++) {
|
||||
tparams->wtable[i] = w;
|
||||
w = MULMOD(w, kernel);
|
||||
}
|
||||
|
||||
return tparams;
|
||||
}
|
||||
|
||||
/* Initialize wtable of size three. */
|
||||
void
|
||||
_mpd_init_w3table(mpd_uint_t w3table[3], int sign, int modnum)
|
||||
{
|
||||
mpd_uint_t umod;
|
||||
#ifdef PPRO
|
||||
double dmod;
|
||||
uint32_t dinvmod[3];
|
||||
#endif
|
||||
mpd_uint_t kernel;
|
||||
|
||||
SETMODULUS(modnum);
|
||||
kernel = _mpd_getkernel(3, sign, modnum);
|
||||
|
||||
w3table[0] = 1;
|
||||
w3table[1] = kernel;
|
||||
w3table[2] = POWMOD(kernel, 2);
|
||||
}
|
||||
|
||||
|
78
third_party/python/Modules/_decimal/libmpdec/numbertheory.h
vendored
Normal file
78
third_party/python/Modules/_decimal/libmpdec/numbertheory.h
vendored
Normal file
|
@ -0,0 +1,78 @@
|
|||
/*
|
||||
* Copyright (c) 2008-2016 Stefan Krah. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
|
||||
#ifndef NUMBER_THEORY_H
|
||||
#define NUMBER_THEORY_H
|
||||
|
||||
|
||||
#include "constants.h"
|
||||
#include "mpdecimal.h"
|
||||
|
||||
|
||||
/* Internal header file: all symbols have local scope in the DSO */
|
||||
MPD_PRAGMA(MPD_HIDE_SYMBOLS_START)
|
||||
|
||||
|
||||
/* transform parameters */
|
||||
struct fnt_params {
|
||||
int modnum;
|
||||
mpd_uint_t modulus;
|
||||
mpd_uint_t kernel;
|
||||
mpd_uint_t wtable[];
|
||||
};
|
||||
|
||||
|
||||
mpd_uint_t _mpd_getkernel(mpd_uint_t n, int sign, int modnum);
|
||||
struct fnt_params *_mpd_init_fnt_params(mpd_size_t n, int sign, int modnum);
|
||||
void _mpd_init_w3table(mpd_uint_t w3table[3], int sign, int modnum);
|
||||
|
||||
|
||||
#ifdef PPRO
|
||||
static inline void
|
||||
ppro_setmodulus(int modnum, mpd_uint_t *umod, double *dmod, uint32_t dinvmod[3])
|
||||
{
|
||||
*dmod = *umod = mpd_moduli[modnum];
|
||||
dinvmod[0] = mpd_invmoduli[modnum][0];
|
||||
dinvmod[1] = mpd_invmoduli[modnum][1];
|
||||
dinvmod[2] = mpd_invmoduli[modnum][2];
|
||||
}
|
||||
#else
|
||||
static inline void
|
||||
std_setmodulus(int modnum, mpd_uint_t *umod)
|
||||
{
|
||||
*umod = mpd_moduli[modnum];
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
MPD_PRAGMA(MPD_HIDE_SYMBOLS_END) /* restore previous scope rules */
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
|
214
third_party/python/Modules/_decimal/libmpdec/sixstep.c
vendored
Normal file
214
third_party/python/Modules/_decimal/libmpdec/sixstep.c
vendored
Normal file
|
@ -0,0 +1,214 @@
|
|||
/*
|
||||
* Copyright (c) 2008-2016 Stefan Krah. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
|
||||
#include "mpdecimal.h"
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <assert.h>
|
||||
#include "bits.h"
|
||||
#include "difradix2.h"
|
||||
#include "numbertheory.h"
|
||||
#include "transpose.h"
|
||||
#include "umodarith.h"
|
||||
#include "sixstep.h"
|
||||
|
||||
|
||||
/* Bignum: Cache efficient Matrix Fourier Transform for arrays of the
|
||||
form 2**n (See literature/six-step.txt). */
|
||||
|
||||
|
||||
/* forward transform with sign = -1 */
|
||||
int
|
||||
six_step_fnt(mpd_uint_t *a, mpd_size_t n, int modnum)
|
||||
{
|
||||
struct fnt_params *tparams;
|
||||
mpd_size_t log2n, C, R;
|
||||
mpd_uint_t kernel;
|
||||
mpd_uint_t umod;
|
||||
#ifdef PPRO
|
||||
double dmod;
|
||||
uint32_t dinvmod[3];
|
||||
#endif
|
||||
mpd_uint_t *x, w0, w1, wstep;
|
||||
mpd_size_t i, k;
|
||||
|
||||
|
||||
assert(ispower2(n));
|
||||
assert(n >= 16);
|
||||
assert(n <= MPD_MAXTRANSFORM_2N);
|
||||
|
||||
log2n = mpd_bsr(n);
|
||||
C = ((mpd_size_t)1) << (log2n / 2); /* number of columns */
|
||||
R = ((mpd_size_t)1) << (log2n - (log2n / 2)); /* number of rows */
|
||||
|
||||
|
||||
/* Transpose the matrix. */
|
||||
if (!transpose_pow2(a, R, C)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Length R transform on the rows. */
|
||||
if ((tparams = _mpd_init_fnt_params(R, -1, modnum)) == NULL) {
|
||||
return 0;
|
||||
}
|
||||
for (x = a; x < a+n; x += R) {
|
||||
fnt_dif2(x, R, tparams);
|
||||
}
|
||||
|
||||
/* Transpose the matrix. */
|
||||
if (!transpose_pow2(a, C, R)) {
|
||||
mpd_free(tparams);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Multiply each matrix element (addressed by i*C+k) by r**(i*k). */
|
||||
SETMODULUS(modnum);
|
||||
kernel = _mpd_getkernel(n, -1, modnum);
|
||||
for (i = 1; i < R; i++) {
|
||||
w0 = 1; /* r**(i*0): initial value for k=0 */
|
||||
w1 = POWMOD(kernel, i); /* r**(i*1): initial value for k=1 */
|
||||
wstep = MULMOD(w1, w1); /* r**(2*i) */
|
||||
for (k = 0; k < C; k += 2) {
|
||||
mpd_uint_t x0 = a[i*C+k];
|
||||
mpd_uint_t x1 = a[i*C+k+1];
|
||||
MULMOD2(&x0, w0, &x1, w1);
|
||||
MULMOD2C(&w0, &w1, wstep); /* r**(i*(k+2)) = r**(i*k) * r**(2*i) */
|
||||
a[i*C+k] = x0;
|
||||
a[i*C+k+1] = x1;
|
||||
}
|
||||
}
|
||||
|
||||
/* Length C transform on the rows. */
|
||||
if (C != R) {
|
||||
mpd_free(tparams);
|
||||
if ((tparams = _mpd_init_fnt_params(C, -1, modnum)) == NULL) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
for (x = a; x < a+n; x += C) {
|
||||
fnt_dif2(x, C, tparams);
|
||||
}
|
||||
mpd_free(tparams);
|
||||
|
||||
#if 0
|
||||
/* An unordered transform is sufficient for convolution. */
|
||||
/* Transpose the matrix. */
|
||||
if (!transpose_pow2(a, R, C)) {
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
/* reverse transform, sign = 1 */
|
||||
int
|
||||
inv_six_step_fnt(mpd_uint_t *a, mpd_size_t n, int modnum)
|
||||
{
|
||||
struct fnt_params *tparams;
|
||||
mpd_size_t log2n, C, R;
|
||||
mpd_uint_t kernel;
|
||||
mpd_uint_t umod;
|
||||
#ifdef PPRO
|
||||
double dmod;
|
||||
uint32_t dinvmod[3];
|
||||
#endif
|
||||
mpd_uint_t *x, w0, w1, wstep;
|
||||
mpd_size_t i, k;
|
||||
|
||||
|
||||
assert(ispower2(n));
|
||||
assert(n >= 16);
|
||||
assert(n <= MPD_MAXTRANSFORM_2N);
|
||||
|
||||
log2n = mpd_bsr(n);
|
||||
C = ((mpd_size_t)1) << (log2n / 2); /* number of columns */
|
||||
R = ((mpd_size_t)1) << (log2n - (log2n / 2)); /* number of rows */
|
||||
|
||||
|
||||
#if 0
|
||||
/* An unordered transform is sufficient for convolution. */
|
||||
/* Transpose the matrix, producing an R*C matrix. */
|
||||
if (!transpose_pow2(a, C, R)) {
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Length C transform on the rows. */
|
||||
if ((tparams = _mpd_init_fnt_params(C, 1, modnum)) == NULL) {
|
||||
return 0;
|
||||
}
|
||||
for (x = a; x < a+n; x += C) {
|
||||
fnt_dif2(x, C, tparams);
|
||||
}
|
||||
|
||||
/* Multiply each matrix element (addressed by i*C+k) by r**(i*k). */
|
||||
SETMODULUS(modnum);
|
||||
kernel = _mpd_getkernel(n, 1, modnum);
|
||||
for (i = 1; i < R; i++) {
|
||||
w0 = 1;
|
||||
w1 = POWMOD(kernel, i);
|
||||
wstep = MULMOD(w1, w1);
|
||||
for (k = 0; k < C; k += 2) {
|
||||
mpd_uint_t x0 = a[i*C+k];
|
||||
mpd_uint_t x1 = a[i*C+k+1];
|
||||
MULMOD2(&x0, w0, &x1, w1);
|
||||
MULMOD2C(&w0, &w1, wstep);
|
||||
a[i*C+k] = x0;
|
||||
a[i*C+k+1] = x1;
|
||||
}
|
||||
}
|
||||
|
||||
/* Transpose the matrix. */
|
||||
if (!transpose_pow2(a, R, C)) {
|
||||
mpd_free(tparams);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Length R transform on the rows. */
|
||||
if (R != C) {
|
||||
mpd_free(tparams);
|
||||
if ((tparams = _mpd_init_fnt_params(R, 1, modnum)) == NULL) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
for (x = a; x < a+n; x += R) {
|
||||
fnt_dif2(x, R, tparams);
|
||||
}
|
||||
mpd_free(tparams);
|
||||
|
||||
/* Transpose the matrix. */
|
||||
if (!transpose_pow2(a, C, R)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
48
third_party/python/Modules/_decimal/libmpdec/sixstep.h
vendored
Normal file
48
third_party/python/Modules/_decimal/libmpdec/sixstep.h
vendored
Normal file
|
@ -0,0 +1,48 @@
|
|||
/*
|
||||
* Copyright (c) 2008-2016 Stefan Krah. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
|
||||
#ifndef SIX_STEP_H
|
||||
#define SIX_STEP_H
|
||||
|
||||
|
||||
#include "mpdecimal.h"
|
||||
#include <stdio.h>
|
||||
|
||||
|
||||
/* Internal header file: all symbols have local scope in the DSO */
|
||||
MPD_PRAGMA(MPD_HIDE_SYMBOLS_START)
|
||||
|
||||
|
||||
int six_step_fnt(mpd_uint_t *a, mpd_size_t n, int modnum);
|
||||
int inv_six_step_fnt(mpd_uint_t *a, mpd_size_t n, int modnum);
|
||||
|
||||
|
||||
MPD_PRAGMA(MPD_HIDE_SYMBOLS_END) /* restore previous scope rules */
|
||||
|
||||
|
||||
#endif
|
276
third_party/python/Modules/_decimal/libmpdec/transpose.c
vendored
Normal file
276
third_party/python/Modules/_decimal/libmpdec/transpose.c
vendored
Normal file
|
@ -0,0 +1,276 @@
|
|||
/*
|
||||
* Copyright (c) 2008-2016 Stefan Krah. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
|
||||
#include "mpdecimal.h"
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <limits.h>
|
||||
#include <assert.h>
|
||||
#include "bits.h"
|
||||
#include "constants.h"
|
||||
#include "typearith.h"
|
||||
#include "transpose.h"
|
||||
|
||||
|
||||
#define BUFSIZE 4096
|
||||
#define SIDE 128
|
||||
|
||||
|
||||
/* Bignum: The transpose functions are used for very large transforms
|
||||
in sixstep.c and fourstep.c. */
|
||||
|
||||
|
||||
/* Definition of the matrix transpose */
|
||||
void
|
||||
std_trans(mpd_uint_t dest[], mpd_uint_t src[], mpd_size_t rows, mpd_size_t cols)
|
||||
{
|
||||
mpd_size_t idest, isrc;
|
||||
mpd_size_t r, c;
|
||||
|
||||
for (r = 0; r < rows; r++) {
|
||||
isrc = r * cols;
|
||||
idest = r;
|
||||
for (c = 0; c < cols; c++) {
|
||||
dest[idest] = src[isrc];
|
||||
isrc += 1;
|
||||
idest += rows;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Swap half-rows of 2^n * (2*2^n) matrix.
|
||||
* FORWARD_CYCLE: even/odd permutation of the halfrows.
|
||||
* BACKWARD_CYCLE: reverse the even/odd permutation.
|
||||
*/
|
||||
static int
|
||||
swap_halfrows_pow2(mpd_uint_t *matrix, mpd_size_t rows, mpd_size_t cols, int dir)
|
||||
{
|
||||
mpd_uint_t buf1[BUFSIZE];
|
||||
mpd_uint_t buf2[BUFSIZE];
|
||||
mpd_uint_t *readbuf, *writebuf, *hp;
|
||||
mpd_size_t *done, dbits;
|
||||
mpd_size_t b = BUFSIZE, stride;
|
||||
mpd_size_t hn, hmax; /* halfrow number */
|
||||
mpd_size_t m, r=0;
|
||||
mpd_size_t offset;
|
||||
mpd_size_t next;
|
||||
|
||||
|
||||
assert(cols == mul_size_t(2, rows));
|
||||
|
||||
if (dir == FORWARD_CYCLE) {
|
||||
r = rows;
|
||||
}
|
||||
else if (dir == BACKWARD_CYCLE) {
|
||||
r = 2;
|
||||
}
|
||||
else {
|
||||
abort(); /* GCOV_NOT_REACHED */
|
||||
}
|
||||
|
||||
m = cols - 1;
|
||||
hmax = rows; /* cycles start at odd halfrows */
|
||||
dbits = 8 * sizeof *done;
|
||||
if ((done = mpd_calloc(hmax/(sizeof *done) + 1, sizeof *done)) == NULL) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
for (hn = 1; hn <= hmax; hn += 2) {
|
||||
|
||||
if (done[hn/dbits] & mpd_bits[hn%dbits]) {
|
||||
continue;
|
||||
}
|
||||
|
||||
readbuf = buf1; writebuf = buf2;
|
||||
|
||||
for (offset = 0; offset < cols/2; offset += b) {
|
||||
|
||||
stride = (offset + b < cols/2) ? b : cols/2-offset;
|
||||
|
||||
hp = matrix + hn*cols/2;
|
||||
memcpy(readbuf, hp+offset, stride*(sizeof *readbuf));
|
||||
pointerswap(&readbuf, &writebuf);
|
||||
|
||||
next = mulmod_size_t(hn, r, m);
|
||||
hp = matrix + next*cols/2;
|
||||
|
||||
while (next != hn) {
|
||||
|
||||
memcpy(readbuf, hp+offset, stride*(sizeof *readbuf));
|
||||
memcpy(hp+offset, writebuf, stride*(sizeof *writebuf));
|
||||
pointerswap(&readbuf, &writebuf);
|
||||
|
||||
done[next/dbits] |= mpd_bits[next%dbits];
|
||||
|
||||
next = mulmod_size_t(next, r, m);
|
||||
hp = matrix + next*cols/2;
|
||||
|
||||
}
|
||||
|
||||
memcpy(hp+offset, writebuf, stride*(sizeof *writebuf));
|
||||
|
||||
done[hn/dbits] |= mpd_bits[hn%dbits];
|
||||
}
|
||||
}
|
||||
|
||||
mpd_free(done);
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* In-place transpose of a square matrix */
|
||||
static inline void
|
||||
squaretrans(mpd_uint_t *buf, mpd_size_t cols)
|
||||
{
|
||||
mpd_uint_t tmp;
|
||||
mpd_size_t idest, isrc;
|
||||
mpd_size_t r, c;
|
||||
|
||||
for (r = 0; r < cols; r++) {
|
||||
c = r+1;
|
||||
isrc = r*cols + c;
|
||||
idest = c*cols + r;
|
||||
for (c = r+1; c < cols; c++) {
|
||||
tmp = buf[isrc];
|
||||
buf[isrc] = buf[idest];
|
||||
buf[idest] = tmp;
|
||||
isrc += 1;
|
||||
idest += cols;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Transpose 2^n * 2^n matrix. For cache efficiency, the matrix is split into
|
||||
* square blocks with side length 'SIDE'. First, the blocks are transposed,
|
||||
* then a square transposition is done on each individual block.
|
||||
*/
|
||||
static void
|
||||
squaretrans_pow2(mpd_uint_t *matrix, mpd_size_t size)
|
||||
{
|
||||
mpd_uint_t buf1[SIDE*SIDE];
|
||||
mpd_uint_t buf2[SIDE*SIDE];
|
||||
mpd_uint_t *to, *from;
|
||||
mpd_size_t b = size;
|
||||
mpd_size_t r, c;
|
||||
mpd_size_t i;
|
||||
|
||||
while (b > SIDE) b >>= 1;
|
||||
|
||||
for (r = 0; r < size; r += b) {
|
||||
|
||||
for (c = r; c < size; c += b) {
|
||||
|
||||
from = matrix + r*size + c;
|
||||
to = buf1;
|
||||
for (i = 0; i < b; i++) {
|
||||
memcpy(to, from, b*(sizeof *to));
|
||||
from += size;
|
||||
to += b;
|
||||
}
|
||||
squaretrans(buf1, b);
|
||||
|
||||
if (r == c) {
|
||||
to = matrix + r*size + c;
|
||||
from = buf1;
|
||||
for (i = 0; i < b; i++) {
|
||||
memcpy(to, from, b*(sizeof *to));
|
||||
from += b;
|
||||
to += size;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
else {
|
||||
from = matrix + c*size + r;
|
||||
to = buf2;
|
||||
for (i = 0; i < b; i++) {
|
||||
memcpy(to, from, b*(sizeof *to));
|
||||
from += size;
|
||||
to += b;
|
||||
}
|
||||
squaretrans(buf2, b);
|
||||
|
||||
to = matrix + c*size + r;
|
||||
from = buf1;
|
||||
for (i = 0; i < b; i++) {
|
||||
memcpy(to, from, b*(sizeof *to));
|
||||
from += b;
|
||||
to += size;
|
||||
}
|
||||
|
||||
to = matrix + r*size + c;
|
||||
from = buf2;
|
||||
for (i = 0; i < b; i++) {
|
||||
memcpy(to, from, b*(sizeof *to));
|
||||
from += b;
|
||||
to += size;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
* In-place transposition of a 2^n x 2^n or a 2^n x (2*2^n)
|
||||
* or a (2*2^n) x 2^n matrix.
|
||||
*/
|
||||
int
|
||||
transpose_pow2(mpd_uint_t *matrix, mpd_size_t rows, mpd_size_t cols)
|
||||
{
|
||||
mpd_size_t size = mul_size_t(rows, cols);
|
||||
|
||||
assert(ispower2(rows));
|
||||
assert(ispower2(cols));
|
||||
|
||||
if (cols == rows) {
|
||||
squaretrans_pow2(matrix, rows);
|
||||
}
|
||||
else if (cols == mul_size_t(2, rows)) {
|
||||
if (!swap_halfrows_pow2(matrix, rows, cols, FORWARD_CYCLE)) {
|
||||
return 0;
|
||||
}
|
||||
squaretrans_pow2(matrix, rows);
|
||||
squaretrans_pow2(matrix+(size/2), rows);
|
||||
}
|
||||
else if (rows == mul_size_t(2, cols)) {
|
||||
squaretrans_pow2(matrix, cols);
|
||||
squaretrans_pow2(matrix+(size/2), cols);
|
||||
if (!swap_halfrows_pow2(matrix, cols, rows, BACKWARD_CYCLE)) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
else {
|
||||
abort(); /* GCOV_NOT_REACHED */
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
62
third_party/python/Modules/_decimal/libmpdec/transpose.h
vendored
Normal file
62
third_party/python/Modules/_decimal/libmpdec/transpose.h
vendored
Normal file
|
@ -0,0 +1,62 @@
|
|||
/*
|
||||
* Copyright (c) 2008-2016 Stefan Krah. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
|
||||
#ifndef TRANSPOSE_H
|
||||
#define TRANSPOSE_H
|
||||
|
||||
|
||||
#include "mpdecimal.h"
|
||||
#include <stdio.h>
|
||||
|
||||
|
||||
/* Internal header file: all symbols have local scope in the DSO */
|
||||
MPD_PRAGMA(MPD_HIDE_SYMBOLS_START)
|
||||
|
||||
|
||||
enum {FORWARD_CYCLE, BACKWARD_CYCLE};
|
||||
|
||||
|
||||
void std_trans(mpd_uint_t dest[], mpd_uint_t src[], mpd_size_t rows, mpd_size_t cols);
|
||||
int transpose_pow2(mpd_uint_t *matrix, mpd_size_t rows, mpd_size_t cols);
|
||||
void transpose_3xpow2(mpd_uint_t *matrix, mpd_size_t rows, mpd_size_t cols);
|
||||
|
||||
|
||||
static inline void pointerswap(mpd_uint_t **a, mpd_uint_t **b)
|
||||
{
|
||||
mpd_uint_t *tmp;
|
||||
|
||||
tmp = *b;
|
||||
*b = *a;
|
||||
*a = tmp;
|
||||
}
|
||||
|
||||
|
||||
MPD_PRAGMA(MPD_HIDE_SYMBOLS_END) /* restore previous scope rules */
|
||||
|
||||
|
||||
#endif
|
669
third_party/python/Modules/_decimal/libmpdec/typearith.h
vendored
Normal file
669
third_party/python/Modules/_decimal/libmpdec/typearith.h
vendored
Normal file
|
@ -0,0 +1,669 @@
|
|||
/*
|
||||
* Copyright (c) 2008-2016 Stefan Krah. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
|
||||
#ifndef TYPEARITH_H
|
||||
#define TYPEARITH_H
|
||||
|
||||
|
||||
#include "mpdecimal.h"
|
||||
|
||||
|
||||
/*****************************************************************************/
|
||||
/* Low level native arithmetic on basic types */
|
||||
/*****************************************************************************/
|
||||
|
||||
|
||||
/** ------------------------------------------------------------
|
||||
** Double width multiplication and division
|
||||
** ------------------------------------------------------------
|
||||
*/
|
||||
|
||||
#if defined(CONFIG_64)
|
||||
#if defined(ANSI)
|
||||
#if defined(HAVE_UINT128_T)
|
||||
static inline void
|
||||
_mpd_mul_words(mpd_uint_t *hi, mpd_uint_t *lo, mpd_uint_t a, mpd_uint_t b)
|
||||
{
|
||||
__uint128_t hl;
|
||||
|
||||
hl = (__uint128_t)a * b;
|
||||
|
||||
*hi = hl >> 64;
|
||||
*lo = (mpd_uint_t)hl;
|
||||
}
|
||||
|
||||
static inline void
|
||||
_mpd_div_words(mpd_uint_t *q, mpd_uint_t *r, mpd_uint_t hi, mpd_uint_t lo,
|
||||
mpd_uint_t d)
|
||||
{
|
||||
__uint128_t hl;
|
||||
|
||||
hl = ((__uint128_t)hi<<64) + lo;
|
||||
*q = (mpd_uint_t)(hl / d); /* quotient is known to fit */
|
||||
*r = (mpd_uint_t)(hl - (__uint128_t)(*q) * d);
|
||||
}
|
||||
#else
|
||||
static inline void
|
||||
_mpd_mul_words(mpd_uint_t *hi, mpd_uint_t *lo, mpd_uint_t a, mpd_uint_t b)
|
||||
{
|
||||
uint32_t w[4], carry;
|
||||
uint32_t ah, al, bh, bl;
|
||||
uint64_t hl;
|
||||
|
||||
ah = (uint32_t)(a>>32); al = (uint32_t)a;
|
||||
bh = (uint32_t)(b>>32); bl = (uint32_t)b;
|
||||
|
||||
hl = (uint64_t)al * bl;
|
||||
w[0] = (uint32_t)hl;
|
||||
carry = (uint32_t)(hl>>32);
|
||||
|
||||
hl = (uint64_t)ah * bl + carry;
|
||||
w[1] = (uint32_t)hl;
|
||||
w[2] = (uint32_t)(hl>>32);
|
||||
|
||||
hl = (uint64_t)al * bh + w[1];
|
||||
w[1] = (uint32_t)hl;
|
||||
carry = (uint32_t)(hl>>32);
|
||||
|
||||
hl = ((uint64_t)ah * bh + w[2]) + carry;
|
||||
w[2] = (uint32_t)hl;
|
||||
w[3] = (uint32_t)(hl>>32);
|
||||
|
||||
*hi = ((uint64_t)w[3]<<32) + w[2];
|
||||
*lo = ((uint64_t)w[1]<<32) + w[0];
|
||||
}
|
||||
|
||||
/*
|
||||
* By Henry S. Warren: http://www.hackersdelight.org/HDcode/divlu.c.txt
|
||||
* http://www.hackersdelight.org/permissions.htm:
|
||||
* "You are free to use, copy, and distribute any of the code on this web
|
||||
* site, whether modified by you or not. You need not give attribution."
|
||||
*
|
||||
* Slightly modified, comments are mine.
|
||||
*/
|
||||
static inline int
|
||||
nlz(uint64_t x)
|
||||
{
|
||||
int n;
|
||||
|
||||
if (x == 0) return(64);
|
||||
|
||||
n = 0;
|
||||
if (x <= 0x00000000FFFFFFFF) {n = n +32; x = x <<32;}
|
||||
if (x <= 0x0000FFFFFFFFFFFF) {n = n +16; x = x <<16;}
|
||||
if (x <= 0x00FFFFFFFFFFFFFF) {n = n + 8; x = x << 8;}
|
||||
if (x <= 0x0FFFFFFFFFFFFFFF) {n = n + 4; x = x << 4;}
|
||||
if (x <= 0x3FFFFFFFFFFFFFFF) {n = n + 2; x = x << 2;}
|
||||
if (x <= 0x7FFFFFFFFFFFFFFF) {n = n + 1;}
|
||||
|
||||
return n;
|
||||
}
|
||||
|
||||
static inline void
|
||||
_mpd_div_words(mpd_uint_t *q, mpd_uint_t *r, mpd_uint_t u1, mpd_uint_t u0,
|
||||
mpd_uint_t v)
|
||||
{
|
||||
const mpd_uint_t b = 4294967296;
|
||||
mpd_uint_t un1, un0,
|
||||
vn1, vn0,
|
||||
q1, q0,
|
||||
un32, un21, un10,
|
||||
rhat, t;
|
||||
int s;
|
||||
|
||||
assert(u1 < v);
|
||||
|
||||
s = nlz(v);
|
||||
v = v << s;
|
||||
vn1 = v >> 32;
|
||||
vn0 = v & 0xFFFFFFFF;
|
||||
|
||||
t = (s == 0) ? 0 : u0 >> (64 - s);
|
||||
un32 = (u1 << s) | t;
|
||||
un10 = u0 << s;
|
||||
|
||||
un1 = un10 >> 32;
|
||||
un0 = un10 & 0xFFFFFFFF;
|
||||
|
||||
q1 = un32 / vn1;
|
||||
rhat = un32 - q1*vn1;
|
||||
again1:
|
||||
if (q1 >= b || q1*vn0 > b*rhat + un1) {
|
||||
q1 = q1 - 1;
|
||||
rhat = rhat + vn1;
|
||||
if (rhat < b) goto again1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Before again1 we had:
|
||||
* (1) q1*vn1 + rhat = un32
|
||||
* (2) q1*vn1*b + rhat*b + un1 = un32*b + un1
|
||||
*
|
||||
* The statements inside the if-clause do not change the value
|
||||
* of the left-hand side of (2), and the loop is only exited
|
||||
* if q1*vn0 <= rhat*b + un1, so:
|
||||
*
|
||||
* (3) q1*vn1*b + q1*vn0 <= un32*b + un1
|
||||
* (4) q1*v <= un32*b + un1
|
||||
* (5) 0 <= un32*b + un1 - q1*v
|
||||
*
|
||||
* By (5) we are certain that the possible add-back step from
|
||||
* Knuth's algorithm D is never required.
|
||||
*
|
||||
* Since the final quotient is less than 2**64, the following
|
||||
* must be true:
|
||||
*
|
||||
* (6) un32*b + un1 - q1*v <= UINT64_MAX
|
||||
*
|
||||
* This means that in the following line, the high words
|
||||
* of un32*b and q1*v can be discarded without any effect
|
||||
* on the result.
|
||||
*/
|
||||
un21 = un32*b + un1 - q1*v;
|
||||
|
||||
q0 = un21 / vn1;
|
||||
rhat = un21 - q0*vn1;
|
||||
again2:
|
||||
if (q0 >= b || q0*vn0 > b*rhat + un0) {
|
||||
q0 = q0 - 1;
|
||||
rhat = rhat + vn1;
|
||||
if (rhat < b) goto again2;
|
||||
}
|
||||
|
||||
*q = q1*b + q0;
|
||||
*r = (un21*b + un0 - q0*v) >> s;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* END ANSI */
|
||||
#elif defined(ASM)
|
||||
static inline void
|
||||
_mpd_mul_words(mpd_uint_t *hi, mpd_uint_t *lo, mpd_uint_t a, mpd_uint_t b)
|
||||
{
|
||||
mpd_uint_t h, l;
|
||||
|
||||
__asm__ ( "mulq %3\n\t"
|
||||
: "=d" (h), "=a" (l)
|
||||
: "%a" (a), "rm" (b)
|
||||
: "cc"
|
||||
);
|
||||
|
||||
*hi = h;
|
||||
*lo = l;
|
||||
}
|
||||
|
||||
static inline void
|
||||
_mpd_div_words(mpd_uint_t *q, mpd_uint_t *r, mpd_uint_t hi, mpd_uint_t lo,
|
||||
mpd_uint_t d)
|
||||
{
|
||||
mpd_uint_t qq, rr;
|
||||
|
||||
__asm__ ( "divq %4\n\t"
|
||||
: "=a" (qq), "=d" (rr)
|
||||
: "a" (lo), "d" (hi), "rm" (d)
|
||||
: "cc"
|
||||
);
|
||||
|
||||
*q = qq;
|
||||
*r = rr;
|
||||
}
|
||||
/* END GCC ASM */
|
||||
#elif defined(MASM)
|
||||
#include <intrin.h>
|
||||
#pragma intrinsic(_umul128)
|
||||
|
||||
static inline void
|
||||
_mpd_mul_words(mpd_uint_t *hi, mpd_uint_t *lo, mpd_uint_t a, mpd_uint_t b)
|
||||
{
|
||||
*lo = _umul128(a, b, hi);
|
||||
}
|
||||
|
||||
void _mpd_div_words(mpd_uint_t *q, mpd_uint_t *r, mpd_uint_t hi, mpd_uint_t lo,
|
||||
mpd_uint_t d);
|
||||
|
||||
/* END MASM (_MSC_VER) */
|
||||
#else
|
||||
#error "need platform specific 128 bit multiplication and division"
|
||||
#endif
|
||||
|
||||
#define DIVMOD(q, r, v, d) *q = v / d; *r = v - *q * d
|
||||
static inline void
|
||||
_mpd_divmod_pow10(mpd_uint_t *q, mpd_uint_t *r, mpd_uint_t v, mpd_uint_t exp)
|
||||
{
|
||||
assert(exp <= 19);
|
||||
|
||||
if (exp <= 9) {
|
||||
if (exp <= 4) {
|
||||
switch (exp) {
|
||||
case 0: *q = v; *r = 0; break;
|
||||
case 1: DIVMOD(q, r, v, 10UL); break;
|
||||
case 2: DIVMOD(q, r, v, 100UL); break;
|
||||
case 3: DIVMOD(q, r, v, 1000UL); break;
|
||||
case 4: DIVMOD(q, r, v, 10000UL); break;
|
||||
}
|
||||
}
|
||||
else {
|
||||
switch (exp) {
|
||||
case 5: DIVMOD(q, r, v, 100000UL); break;
|
||||
case 6: DIVMOD(q, r, v, 1000000UL); break;
|
||||
case 7: DIVMOD(q, r, v, 10000000UL); break;
|
||||
case 8: DIVMOD(q, r, v, 100000000UL); break;
|
||||
case 9: DIVMOD(q, r, v, 1000000000UL); break;
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (exp <= 14) {
|
||||
switch (exp) {
|
||||
case 10: DIVMOD(q, r, v, 10000000000ULL); break;
|
||||
case 11: DIVMOD(q, r, v, 100000000000ULL); break;
|
||||
case 12: DIVMOD(q, r, v, 1000000000000ULL); break;
|
||||
case 13: DIVMOD(q, r, v, 10000000000000ULL); break;
|
||||
case 14: DIVMOD(q, r, v, 100000000000000ULL); break;
|
||||
}
|
||||
}
|
||||
else {
|
||||
switch (exp) {
|
||||
case 15: DIVMOD(q, r, v, 1000000000000000ULL); break;
|
||||
case 16: DIVMOD(q, r, v, 10000000000000000ULL); break;
|
||||
case 17: DIVMOD(q, r, v, 100000000000000000ULL); break;
|
||||
case 18: DIVMOD(q, r, v, 1000000000000000000ULL); break;
|
||||
case 19: DIVMOD(q, r, v, 10000000000000000000ULL); break; /* GCOV_NOT_REACHED */
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* END CONFIG_64 */
|
||||
#elif defined(CONFIG_32)
|
||||
#if defined(ANSI)
|
||||
#if !defined(LEGACY_COMPILER)
|
||||
static inline void
|
||||
_mpd_mul_words(mpd_uint_t *hi, mpd_uint_t *lo, mpd_uint_t a, mpd_uint_t b)
|
||||
{
|
||||
mpd_uuint_t hl;
|
||||
|
||||
hl = (mpd_uuint_t)a * b;
|
||||
|
||||
*hi = hl >> 32;
|
||||
*lo = (mpd_uint_t)hl;
|
||||
}
|
||||
|
||||
static inline void
|
||||
_mpd_div_words(mpd_uint_t *q, mpd_uint_t *r, mpd_uint_t hi, mpd_uint_t lo,
|
||||
mpd_uint_t d)
|
||||
{
|
||||
mpd_uuint_t hl;
|
||||
|
||||
hl = ((mpd_uuint_t)hi<<32) + lo;
|
||||
*q = (mpd_uint_t)(hl / d); /* quotient is known to fit */
|
||||
*r = (mpd_uint_t)(hl - (mpd_uuint_t)(*q) * d);
|
||||
}
|
||||
/* END ANSI + uint64_t */
|
||||
#else
|
||||
static inline void
|
||||
_mpd_mul_words(mpd_uint_t *hi, mpd_uint_t *lo, mpd_uint_t a, mpd_uint_t b)
|
||||
{
|
||||
uint16_t w[4], carry;
|
||||
uint16_t ah, al, bh, bl;
|
||||
uint32_t hl;
|
||||
|
||||
ah = (uint16_t)(a>>16); al = (uint16_t)a;
|
||||
bh = (uint16_t)(b>>16); bl = (uint16_t)b;
|
||||
|
||||
hl = (uint32_t)al * bl;
|
||||
w[0] = (uint16_t)hl;
|
||||
carry = (uint16_t)(hl>>16);
|
||||
|
||||
hl = (uint32_t)ah * bl + carry;
|
||||
w[1] = (uint16_t)hl;
|
||||
w[2] = (uint16_t)(hl>>16);
|
||||
|
||||
hl = (uint32_t)al * bh + w[1];
|
||||
w[1] = (uint16_t)hl;
|
||||
carry = (uint16_t)(hl>>16);
|
||||
|
||||
hl = ((uint32_t)ah * bh + w[2]) + carry;
|
||||
w[2] = (uint16_t)hl;
|
||||
w[3] = (uint16_t)(hl>>16);
|
||||
|
||||
*hi = ((uint32_t)w[3]<<16) + w[2];
|
||||
*lo = ((uint32_t)w[1]<<16) + w[0];
|
||||
}
|
||||
|
||||
/*
|
||||
* By Henry S. Warren: http://www.hackersdelight.org/HDcode/divlu.c.txt
|
||||
* http://www.hackersdelight.org/permissions.htm:
|
||||
* "You are free to use, copy, and distribute any of the code on this web
|
||||
* site, whether modified by you or not. You need not give attribution."
|
||||
*
|
||||
* Slightly modified, comments are mine.
|
||||
*/
|
||||
static inline int
|
||||
nlz(uint32_t x)
|
||||
{
|
||||
int n;
|
||||
|
||||
if (x == 0) return(32);
|
||||
|
||||
n = 0;
|
||||
if (x <= 0x0000FFFF) {n = n +16; x = x <<16;}
|
||||
if (x <= 0x00FFFFFF) {n = n + 8; x = x << 8;}
|
||||
if (x <= 0x0FFFFFFF) {n = n + 4; x = x << 4;}
|
||||
if (x <= 0x3FFFFFFF) {n = n + 2; x = x << 2;}
|
||||
if (x <= 0x7FFFFFFF) {n = n + 1;}
|
||||
|
||||
return n;
|
||||
}
|
||||
|
||||
static inline void
|
||||
_mpd_div_words(mpd_uint_t *q, mpd_uint_t *r, mpd_uint_t u1, mpd_uint_t u0,
|
||||
mpd_uint_t v)
|
||||
{
|
||||
const mpd_uint_t b = 65536;
|
||||
mpd_uint_t un1, un0,
|
||||
vn1, vn0,
|
||||
q1, q0,
|
||||
un32, un21, un10,
|
||||
rhat, t;
|
||||
int s;
|
||||
|
||||
assert(u1 < v);
|
||||
|
||||
s = nlz(v);
|
||||
v = v << s;
|
||||
vn1 = v >> 16;
|
||||
vn0 = v & 0xFFFF;
|
||||
|
||||
t = (s == 0) ? 0 : u0 >> (32 - s);
|
||||
un32 = (u1 << s) | t;
|
||||
un10 = u0 << s;
|
||||
|
||||
un1 = un10 >> 16;
|
||||
un0 = un10 & 0xFFFF;
|
||||
|
||||
q1 = un32 / vn1;
|
||||
rhat = un32 - q1*vn1;
|
||||
again1:
|
||||
if (q1 >= b || q1*vn0 > b*rhat + un1) {
|
||||
q1 = q1 - 1;
|
||||
rhat = rhat + vn1;
|
||||
if (rhat < b) goto again1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Before again1 we had:
|
||||
* (1) q1*vn1 + rhat = un32
|
||||
* (2) q1*vn1*b + rhat*b + un1 = un32*b + un1
|
||||
*
|
||||
* The statements inside the if-clause do not change the value
|
||||
* of the left-hand side of (2), and the loop is only exited
|
||||
* if q1*vn0 <= rhat*b + un1, so:
|
||||
*
|
||||
* (3) q1*vn1*b + q1*vn0 <= un32*b + un1
|
||||
* (4) q1*v <= un32*b + un1
|
||||
* (5) 0 <= un32*b + un1 - q1*v
|
||||
*
|
||||
* By (5) we are certain that the possible add-back step from
|
||||
* Knuth's algorithm D is never required.
|
||||
*
|
||||
* Since the final quotient is less than 2**32, the following
|
||||
* must be true:
|
||||
*
|
||||
* (6) un32*b + un1 - q1*v <= UINT32_MAX
|
||||
*
|
||||
* This means that in the following line, the high words
|
||||
* of un32*b and q1*v can be discarded without any effect
|
||||
* on the result.
|
||||
*/
|
||||
un21 = un32*b + un1 - q1*v;
|
||||
|
||||
q0 = un21 / vn1;
|
||||
rhat = un21 - q0*vn1;
|
||||
again2:
|
||||
if (q0 >= b || q0*vn0 > b*rhat + un0) {
|
||||
q0 = q0 - 1;
|
||||
rhat = rhat + vn1;
|
||||
if (rhat < b) goto again2;
|
||||
}
|
||||
|
||||
*q = q1*b + q0;
|
||||
*r = (un21*b + un0 - q0*v) >> s;
|
||||
}
|
||||
#endif /* END ANSI + LEGACY_COMPILER */
|
||||
|
||||
/* END ANSI */
|
||||
#elif defined(ASM)
|
||||
static inline void
|
||||
_mpd_mul_words(mpd_uint_t *hi, mpd_uint_t *lo, mpd_uint_t a, mpd_uint_t b)
|
||||
{
|
||||
mpd_uint_t h, l;
|
||||
|
||||
__asm__ ( "mull %3\n\t"
|
||||
: "=d" (h), "=a" (l)
|
||||
: "%a" (a), "rm" (b)
|
||||
: "cc"
|
||||
);
|
||||
|
||||
*hi = h;
|
||||
*lo = l;
|
||||
}
|
||||
|
||||
static inline void
|
||||
_mpd_div_words(mpd_uint_t *q, mpd_uint_t *r, mpd_uint_t hi, mpd_uint_t lo,
|
||||
mpd_uint_t d)
|
||||
{
|
||||
mpd_uint_t qq, rr;
|
||||
|
||||
__asm__ ( "divl %4\n\t"
|
||||
: "=a" (qq), "=d" (rr)
|
||||
: "a" (lo), "d" (hi), "rm" (d)
|
||||
: "cc"
|
||||
);
|
||||
|
||||
*q = qq;
|
||||
*r = rr;
|
||||
}
|
||||
/* END GCC ASM */
|
||||
#elif defined(MASM)
|
||||
static inline void __cdecl
|
||||
_mpd_mul_words(mpd_uint_t *hi, mpd_uint_t *lo, mpd_uint_t a, mpd_uint_t b)
|
||||
{
|
||||
mpd_uint_t h, l;
|
||||
|
||||
__asm {
|
||||
mov eax, a
|
||||
mul b
|
||||
mov h, edx
|
||||
mov l, eax
|
||||
}
|
||||
|
||||
*hi = h;
|
||||
*lo = l;
|
||||
}
|
||||
|
||||
static inline void __cdecl
|
||||
_mpd_div_words(mpd_uint_t *q, mpd_uint_t *r, mpd_uint_t hi, mpd_uint_t lo,
|
||||
mpd_uint_t d)
|
||||
{
|
||||
mpd_uint_t qq, rr;
|
||||
|
||||
__asm {
|
||||
mov eax, lo
|
||||
mov edx, hi
|
||||
div d
|
||||
mov qq, eax
|
||||
mov rr, edx
|
||||
}
|
||||
|
||||
*q = qq;
|
||||
*r = rr;
|
||||
}
|
||||
/* END MASM (_MSC_VER) */
|
||||
#else
|
||||
#error "need platform specific 64 bit multiplication and division"
|
||||
#endif
|
||||
|
||||
#define DIVMOD(q, r, v, d) *q = v / d; *r = v - *q * d
|
||||
static inline void
|
||||
_mpd_divmod_pow10(mpd_uint_t *q, mpd_uint_t *r, mpd_uint_t v, mpd_uint_t exp)
|
||||
{
|
||||
assert(exp <= 9);
|
||||
|
||||
if (exp <= 4) {
|
||||
switch (exp) {
|
||||
case 0: *q = v; *r = 0; break;
|
||||
case 1: DIVMOD(q, r, v, 10UL); break;
|
||||
case 2: DIVMOD(q, r, v, 100UL); break;
|
||||
case 3: DIVMOD(q, r, v, 1000UL); break;
|
||||
case 4: DIVMOD(q, r, v, 10000UL); break;
|
||||
}
|
||||
}
|
||||
else {
|
||||
switch (exp) {
|
||||
case 5: DIVMOD(q, r, v, 100000UL); break;
|
||||
case 6: DIVMOD(q, r, v, 1000000UL); break;
|
||||
case 7: DIVMOD(q, r, v, 10000000UL); break;
|
||||
case 8: DIVMOD(q, r, v, 100000000UL); break;
|
||||
case 9: DIVMOD(q, r, v, 1000000000UL); break; /* GCOV_NOT_REACHED */
|
||||
}
|
||||
}
|
||||
}
|
||||
/* END CONFIG_32 */
|
||||
|
||||
/* NO CONFIG */
|
||||
#else
|
||||
#error "define CONFIG_64 or CONFIG_32"
|
||||
#endif /* CONFIG */
|
||||
|
||||
|
||||
static inline void
|
||||
_mpd_div_word(mpd_uint_t *q, mpd_uint_t *r, mpd_uint_t v, mpd_uint_t d)
|
||||
{
|
||||
*q = v / d;
|
||||
*r = v - *q * d;
|
||||
}
|
||||
|
||||
static inline void
|
||||
_mpd_idiv_word(mpd_ssize_t *q, mpd_ssize_t *r, mpd_ssize_t v, mpd_ssize_t d)
|
||||
{
|
||||
*q = v / d;
|
||||
*r = v - *q * d;
|
||||
}
|
||||
|
||||
|
||||
/** ------------------------------------------------------------
|
||||
** Arithmetic with overflow checking
|
||||
** ------------------------------------------------------------
|
||||
*/
|
||||
|
||||
/* The following macros do call exit() in case of an overflow.
|
||||
If the library is used correctly (i.e. with valid context
|
||||
parameters), such overflows cannot occur. The macros are used
|
||||
as sanity checks in a couple of strategic places and should
|
||||
be viewed as a handwritten version of gcc's -ftrapv option. */
|
||||
|
||||
static inline mpd_size_t
|
||||
add_size_t(mpd_size_t a, mpd_size_t b)
|
||||
{
|
||||
if (a > MPD_SIZE_MAX - b) {
|
||||
mpd_err_fatal("add_size_t(): overflow: check the context"); /* GCOV_NOT_REACHED */
|
||||
}
|
||||
return a + b;
|
||||
}
|
||||
|
||||
static inline mpd_size_t
|
||||
sub_size_t(mpd_size_t a, mpd_size_t b)
|
||||
{
|
||||
if (b > a) {
|
||||
mpd_err_fatal("sub_size_t(): overflow: check the context"); /* GCOV_NOT_REACHED */
|
||||
}
|
||||
return a - b;
|
||||
}
|
||||
|
||||
#if MPD_SIZE_MAX != MPD_UINT_MAX
|
||||
#error "adapt mul_size_t() and mulmod_size_t()"
|
||||
#endif
|
||||
|
||||
static inline mpd_size_t
|
||||
mul_size_t(mpd_size_t a, mpd_size_t b)
|
||||
{
|
||||
mpd_uint_t hi, lo;
|
||||
|
||||
_mpd_mul_words(&hi, &lo, (mpd_uint_t)a, (mpd_uint_t)b);
|
||||
if (hi) {
|
||||
mpd_err_fatal("mul_size_t(): overflow: check the context"); /* GCOV_NOT_REACHED */
|
||||
}
|
||||
return lo;
|
||||
}
|
||||
|
||||
static inline mpd_size_t
|
||||
add_size_t_overflow(mpd_size_t a, mpd_size_t b, mpd_size_t *overflow)
|
||||
{
|
||||
mpd_size_t ret;
|
||||
|
||||
*overflow = 0;
|
||||
ret = a + b;
|
||||
if (ret < a) *overflow = 1;
|
||||
return ret;
|
||||
}
|
||||
|
||||
static inline mpd_size_t
|
||||
mul_size_t_overflow(mpd_size_t a, mpd_size_t b, mpd_size_t *overflow)
|
||||
{
|
||||
mpd_uint_t lo;
|
||||
|
||||
_mpd_mul_words((mpd_uint_t *)overflow, &lo, (mpd_uint_t)a,
|
||||
(mpd_uint_t)b);
|
||||
return lo;
|
||||
}
|
||||
|
||||
static inline mpd_ssize_t
|
||||
mod_mpd_ssize_t(mpd_ssize_t a, mpd_ssize_t m)
|
||||
{
|
||||
mpd_ssize_t r = a % m;
|
||||
return (r < 0) ? r + m : r;
|
||||
}
|
||||
|
||||
static inline mpd_size_t
|
||||
mulmod_size_t(mpd_size_t a, mpd_size_t b, mpd_size_t m)
|
||||
{
|
||||
mpd_uint_t hi, lo;
|
||||
mpd_uint_t q, r;
|
||||
|
||||
_mpd_mul_words(&hi, &lo, (mpd_uint_t)a, (mpd_uint_t)b);
|
||||
_mpd_div_words(&q, &r, hi, lo, (mpd_uint_t)m);
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
|
||||
#endif /* TYPEARITH_H */
|
||||
|
||||
|
||||
|
650
third_party/python/Modules/_decimal/libmpdec/umodarith.h
vendored
Normal file
650
third_party/python/Modules/_decimal/libmpdec/umodarith.h
vendored
Normal file
|
@ -0,0 +1,650 @@
|
|||
/*
|
||||
* Copyright (c) 2008-2016 Stefan Krah. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
|
||||
#ifndef UMODARITH_H
|
||||
#define UMODARITH_H
|
||||
|
||||
|
||||
#include "constants.h"
|
||||
#include "mpdecimal.h"
|
||||
#include "typearith.h"
|
||||
|
||||
|
||||
/* Bignum: Low level routines for unsigned modular arithmetic. These are
|
||||
used in the fast convolution functions for very large coefficients. */
|
||||
|
||||
|
||||
/**************************************************************************/
|
||||
/* ANSI modular arithmetic */
|
||||
/**************************************************************************/
|
||||
|
||||
|
||||
/*
|
||||
* Restrictions: a < m and b < m
|
||||
* ACL2 proof: umodarith.lisp: addmod-correct
|
||||
*/
|
||||
static inline mpd_uint_t
|
||||
addmod(mpd_uint_t a, mpd_uint_t b, mpd_uint_t m)
|
||||
{
|
||||
mpd_uint_t s;
|
||||
|
||||
s = a + b;
|
||||
s = (s < a) ? s - m : s;
|
||||
s = (s >= m) ? s - m : s;
|
||||
|
||||
return s;
|
||||
}
|
||||
|
||||
/*
|
||||
* Restrictions: a < m and b < m
|
||||
* ACL2 proof: umodarith.lisp: submod-2-correct
|
||||
*/
|
||||
static inline mpd_uint_t
|
||||
submod(mpd_uint_t a, mpd_uint_t b, mpd_uint_t m)
|
||||
{
|
||||
mpd_uint_t d;
|
||||
|
||||
d = a - b;
|
||||
d = (a < b) ? d + m : d;
|
||||
|
||||
return d;
|
||||
}
|
||||
|
||||
/*
|
||||
* Restrictions: a < 2m and b < 2m
|
||||
* ACL2 proof: umodarith.lisp: section ext-submod
|
||||
*/
|
||||
static inline mpd_uint_t
|
||||
ext_submod(mpd_uint_t a, mpd_uint_t b, mpd_uint_t m)
|
||||
{
|
||||
mpd_uint_t d;
|
||||
|
||||
a = (a >= m) ? a - m : a;
|
||||
b = (b >= m) ? b - m : b;
|
||||
|
||||
d = a - b;
|
||||
d = (a < b) ? d + m : d;
|
||||
|
||||
return d;
|
||||
}
|
||||
|
||||
/*
|
||||
* Reduce double word modulo m.
|
||||
* Restrictions: m != 0
|
||||
* ACL2 proof: umodarith.lisp: section dw-reduce
|
||||
*/
|
||||
static inline mpd_uint_t
|
||||
dw_reduce(mpd_uint_t hi, mpd_uint_t lo, mpd_uint_t m)
|
||||
{
|
||||
mpd_uint_t r1, r2, w;
|
||||
|
||||
_mpd_div_word(&w, &r1, hi, m);
|
||||
_mpd_div_words(&w, &r2, r1, lo, m);
|
||||
|
||||
return r2;
|
||||
}
|
||||
|
||||
/*
|
||||
* Subtract double word from a.
|
||||
* Restrictions: a < m
|
||||
* ACL2 proof: umodarith.lisp: section dw-submod
|
||||
*/
|
||||
static inline mpd_uint_t
|
||||
dw_submod(mpd_uint_t a, mpd_uint_t hi, mpd_uint_t lo, mpd_uint_t m)
|
||||
{
|
||||
mpd_uint_t d, r;
|
||||
|
||||
r = dw_reduce(hi, lo, m);
|
||||
d = a - r;
|
||||
d = (a < r) ? d + m : d;
|
||||
|
||||
return d;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_64
|
||||
|
||||
/**************************************************************************/
|
||||
/* 64-bit modular arithmetic */
|
||||
/**************************************************************************/
|
||||
|
||||
/*
|
||||
* A proof of the algorithm is in literature/mulmod-64.txt. An ACL2
|
||||
* proof is in umodarith.lisp: section "Fast modular reduction".
|
||||
*
|
||||
* Algorithm: calculate (a * b) % p:
|
||||
*
|
||||
* a) hi, lo <- a * b # Calculate a * b.
|
||||
*
|
||||
* b) hi, lo <- R(hi, lo) # Reduce modulo p.
|
||||
*
|
||||
* c) Repeat step b) until 0 <= hi * 2**64 + lo < 2*p.
|
||||
*
|
||||
* d) If the result is less than p, return lo. Otherwise return lo - p.
|
||||
*/
|
||||
|
||||
static inline mpd_uint_t
|
||||
x64_mulmod(mpd_uint_t a, mpd_uint_t b, mpd_uint_t m)
|
||||
{
|
||||
mpd_uint_t hi, lo, x, y;
|
||||
|
||||
|
||||
_mpd_mul_words(&hi, &lo, a, b);
|
||||
|
||||
if (m & (1ULL<<32)) { /* P1 */
|
||||
|
||||
/* first reduction */
|
||||
x = y = hi;
|
||||
hi >>= 32;
|
||||
|
||||
x = lo - x;
|
||||
if (x > lo) hi--;
|
||||
|
||||
y <<= 32;
|
||||
lo = y + x;
|
||||
if (lo < y) hi++;
|
||||
|
||||
/* second reduction */
|
||||
x = y = hi;
|
||||
hi >>= 32;
|
||||
|
||||
x = lo - x;
|
||||
if (x > lo) hi--;
|
||||
|
||||
y <<= 32;
|
||||
lo = y + x;
|
||||
if (lo < y) hi++;
|
||||
|
||||
return (hi || lo >= m ? lo - m : lo);
|
||||
}
|
||||
else if (m & (1ULL<<34)) { /* P2 */
|
||||
|
||||
/* first reduction */
|
||||
x = y = hi;
|
||||
hi >>= 30;
|
||||
|
||||
x = lo - x;
|
||||
if (x > lo) hi--;
|
||||
|
||||
y <<= 34;
|
||||
lo = y + x;
|
||||
if (lo < y) hi++;
|
||||
|
||||
/* second reduction */
|
||||
x = y = hi;
|
||||
hi >>= 30;
|
||||
|
||||
x = lo - x;
|
||||
if (x > lo) hi--;
|
||||
|
||||
y <<= 34;
|
||||
lo = y + x;
|
||||
if (lo < y) hi++;
|
||||
|
||||
/* third reduction */
|
||||
x = y = hi;
|
||||
hi >>= 30;
|
||||
|
||||
x = lo - x;
|
||||
if (x > lo) hi--;
|
||||
|
||||
y <<= 34;
|
||||
lo = y + x;
|
||||
if (lo < y) hi++;
|
||||
|
||||
return (hi || lo >= m ? lo - m : lo);
|
||||
}
|
||||
else { /* P3 */
|
||||
|
||||
/* first reduction */
|
||||
x = y = hi;
|
||||
hi >>= 24;
|
||||
|
||||
x = lo - x;
|
||||
if (x > lo) hi--;
|
||||
|
||||
y <<= 40;
|
||||
lo = y + x;
|
||||
if (lo < y) hi++;
|
||||
|
||||
/* second reduction */
|
||||
x = y = hi;
|
||||
hi >>= 24;
|
||||
|
||||
x = lo - x;
|
||||
if (x > lo) hi--;
|
||||
|
||||
y <<= 40;
|
||||
lo = y + x;
|
||||
if (lo < y) hi++;
|
||||
|
||||
/* third reduction */
|
||||
x = y = hi;
|
||||
hi >>= 24;
|
||||
|
||||
x = lo - x;
|
||||
if (x > lo) hi--;
|
||||
|
||||
y <<= 40;
|
||||
lo = y + x;
|
||||
if (lo < y) hi++;
|
||||
|
||||
return (hi || lo >= m ? lo - m : lo);
|
||||
}
|
||||
}
|
||||
|
||||
static inline void
|
||||
x64_mulmod2c(mpd_uint_t *a, mpd_uint_t *b, mpd_uint_t w, mpd_uint_t m)
|
||||
{
|
||||
*a = x64_mulmod(*a, w, m);
|
||||
*b = x64_mulmod(*b, w, m);
|
||||
}
|
||||
|
||||
static inline void
|
||||
x64_mulmod2(mpd_uint_t *a0, mpd_uint_t b0, mpd_uint_t *a1, mpd_uint_t b1,
|
||||
mpd_uint_t m)
|
||||
{
|
||||
*a0 = x64_mulmod(*a0, b0, m);
|
||||
*a1 = x64_mulmod(*a1, b1, m);
|
||||
}
|
||||
|
||||
static inline mpd_uint_t
|
||||
x64_powmod(mpd_uint_t base, mpd_uint_t exp, mpd_uint_t umod)
|
||||
{
|
||||
mpd_uint_t r = 1;
|
||||
|
||||
while (exp > 0) {
|
||||
if (exp & 1)
|
||||
r = x64_mulmod(r, base, umod);
|
||||
base = x64_mulmod(base, base, umod);
|
||||
exp >>= 1;
|
||||
}
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
/* END CONFIG_64 */
|
||||
#else /* CONFIG_32 */
|
||||
|
||||
|
||||
/**************************************************************************/
|
||||
/* 32-bit modular arithmetic */
|
||||
/**************************************************************************/
|
||||
|
||||
#if defined(ANSI)
|
||||
#if !defined(LEGACY_COMPILER)
|
||||
/* HAVE_UINT64_T */
|
||||
static inline mpd_uint_t
|
||||
std_mulmod(mpd_uint_t a, mpd_uint_t b, mpd_uint_t m)
|
||||
{
|
||||
return ((mpd_uuint_t) a * b) % m;
|
||||
}
|
||||
|
||||
static inline void
|
||||
std_mulmod2c(mpd_uint_t *a, mpd_uint_t *b, mpd_uint_t w, mpd_uint_t m)
|
||||
{
|
||||
*a = ((mpd_uuint_t) *a * w) % m;
|
||||
*b = ((mpd_uuint_t) *b * w) % m;
|
||||
}
|
||||
|
||||
static inline void
|
||||
std_mulmod2(mpd_uint_t *a0, mpd_uint_t b0, mpd_uint_t *a1, mpd_uint_t b1,
|
||||
mpd_uint_t m)
|
||||
{
|
||||
*a0 = ((mpd_uuint_t) *a0 * b0) % m;
|
||||
*a1 = ((mpd_uuint_t) *a1 * b1) % m;
|
||||
}
|
||||
/* END HAVE_UINT64_T */
|
||||
#else
|
||||
/* LEGACY_COMPILER */
|
||||
static inline mpd_uint_t
|
||||
std_mulmod(mpd_uint_t a, mpd_uint_t b, mpd_uint_t m)
|
||||
{
|
||||
mpd_uint_t hi, lo, q, r;
|
||||
_mpd_mul_words(&hi, &lo, a, b);
|
||||
_mpd_div_words(&q, &r, hi, lo, m);
|
||||
return r;
|
||||
}
|
||||
|
||||
static inline void
|
||||
std_mulmod2c(mpd_uint_t *a, mpd_uint_t *b, mpd_uint_t w, mpd_uint_t m)
|
||||
{
|
||||
*a = std_mulmod(*a, w, m);
|
||||
*b = std_mulmod(*b, w, m);
|
||||
}
|
||||
|
||||
static inline void
|
||||
std_mulmod2(mpd_uint_t *a0, mpd_uint_t b0, mpd_uint_t *a1, mpd_uint_t b1,
|
||||
mpd_uint_t m)
|
||||
{
|
||||
*a0 = std_mulmod(*a0, b0, m);
|
||||
*a1 = std_mulmod(*a1, b1, m);
|
||||
}
|
||||
/* END LEGACY_COMPILER */
|
||||
#endif
|
||||
|
||||
static inline mpd_uint_t
|
||||
std_powmod(mpd_uint_t base, mpd_uint_t exp, mpd_uint_t umod)
|
||||
{
|
||||
mpd_uint_t r = 1;
|
||||
|
||||
while (exp > 0) {
|
||||
if (exp & 1)
|
||||
r = std_mulmod(r, base, umod);
|
||||
base = std_mulmod(base, base, umod);
|
||||
exp >>= 1;
|
||||
}
|
||||
|
||||
return r;
|
||||
}
|
||||
#endif /* ANSI CONFIG_32 */
|
||||
|
||||
|
||||
/**************************************************************************/
|
||||
/* Pentium Pro modular arithmetic */
|
||||
/**************************************************************************/
|
||||
|
||||
/*
|
||||
* A proof of the algorithm is in literature/mulmod-ppro.txt. The FPU
|
||||
* control word must be set to 64-bit precision and truncation mode
|
||||
* prior to using these functions.
|
||||
*
|
||||
* Algorithm: calculate (a * b) % p:
|
||||
*
|
||||
* p := prime < 2**31
|
||||
* pinv := (long double)1.0 / p (precalculated)
|
||||
*
|
||||
* a) n = a * b # Calculate exact product.
|
||||
* b) qest = n * pinv # Calculate estimate for q = n / p.
|
||||
* c) q = (qest+2**63)-2**63 # Truncate qest to the exact quotient.
|
||||
* d) r = n - q * p # Calculate remainder.
|
||||
*
|
||||
* Remarks:
|
||||
*
|
||||
* - p = dmod and pinv = dinvmod.
|
||||
* - dinvmod points to an array of three uint32_t, which is interpreted
|
||||
* as an 80 bit long double by fldt.
|
||||
* - Intel compilers prior to version 11 do not seem to handle the
|
||||
* __GNUC__ inline assembly correctly.
|
||||
* - random tests are provided in tests/extended/ppro_mulmod.c
|
||||
*/
|
||||
|
||||
#if defined(PPRO)
|
||||
#if defined(ASM)
|
||||
|
||||
/* Return (a * b) % dmod */
|
||||
static inline mpd_uint_t
|
||||
ppro_mulmod(mpd_uint_t a, mpd_uint_t b, double *dmod, uint32_t *dinvmod)
|
||||
{
|
||||
mpd_uint_t retval;
|
||||
|
||||
__asm__ (
|
||||
"fildl %2\n\t"
|
||||
"fildl %1\n\t"
|
||||
"fmulp %%st, %%st(1)\n\t"
|
||||
"fldt (%4)\n\t"
|
||||
"fmul %%st(1), %%st\n\t"
|
||||
"flds %5\n\t"
|
||||
"fadd %%st, %%st(1)\n\t"
|
||||
"fsubrp %%st, %%st(1)\n\t"
|
||||
"fldl (%3)\n\t"
|
||||
"fmulp %%st, %%st(1)\n\t"
|
||||
"fsubrp %%st, %%st(1)\n\t"
|
||||
"fistpl %0\n\t"
|
||||
: "=m" (retval)
|
||||
: "m" (a), "m" (b), "r" (dmod), "r" (dinvmod), "m" (MPD_TWO63)
|
||||
: "st", "memory"
|
||||
);
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
/*
|
||||
* Two modular multiplications in parallel:
|
||||
* *a0 = (*a0 * w) % dmod
|
||||
* *a1 = (*a1 * w) % dmod
|
||||
*/
|
||||
static inline void
|
||||
ppro_mulmod2c(mpd_uint_t *a0, mpd_uint_t *a1, mpd_uint_t w,
|
||||
double *dmod, uint32_t *dinvmod)
|
||||
{
|
||||
__asm__ (
|
||||
"fildl %2\n\t"
|
||||
"fildl (%1)\n\t"
|
||||
"fmul %%st(1), %%st\n\t"
|
||||
"fxch %%st(1)\n\t"
|
||||
"fildl (%0)\n\t"
|
||||
"fmulp %%st, %%st(1) \n\t"
|
||||
"fldt (%4)\n\t"
|
||||
"flds %5\n\t"
|
||||
"fld %%st(2)\n\t"
|
||||
"fmul %%st(2)\n\t"
|
||||
"fadd %%st(1)\n\t"
|
||||
"fsub %%st(1)\n\t"
|
||||
"fmull (%3)\n\t"
|
||||
"fsubrp %%st, %%st(3)\n\t"
|
||||
"fxch %%st(2)\n\t"
|
||||
"fistpl (%0)\n\t"
|
||||
"fmul %%st(2)\n\t"
|
||||
"fadd %%st(1)\n\t"
|
||||
"fsubp %%st, %%st(1)\n\t"
|
||||
"fmull (%3)\n\t"
|
||||
"fsubrp %%st, %%st(1)\n\t"
|
||||
"fistpl (%1)\n\t"
|
||||
: : "r" (a0), "r" (a1), "m" (w),
|
||||
"r" (dmod), "r" (dinvmod),
|
||||
"m" (MPD_TWO63)
|
||||
: "st", "memory"
|
||||
);
|
||||
}
|
||||
|
||||
/*
|
||||
* Two modular multiplications in parallel:
|
||||
* *a0 = (*a0 * b0) % dmod
|
||||
* *a1 = (*a1 * b1) % dmod
|
||||
*/
|
||||
static inline void
|
||||
ppro_mulmod2(mpd_uint_t *a0, mpd_uint_t b0, mpd_uint_t *a1, mpd_uint_t b1,
|
||||
double *dmod, uint32_t *dinvmod)
|
||||
{
|
||||
__asm__ (
|
||||
"fildl %3\n\t"
|
||||
"fildl (%2)\n\t"
|
||||
"fmulp %%st, %%st(1)\n\t"
|
||||
"fildl %1\n\t"
|
||||
"fildl (%0)\n\t"
|
||||
"fmulp %%st, %%st(1)\n\t"
|
||||
"fldt (%5)\n\t"
|
||||
"fld %%st(2)\n\t"
|
||||
"fmul %%st(1), %%st\n\t"
|
||||
"fxch %%st(1)\n\t"
|
||||
"fmul %%st(2), %%st\n\t"
|
||||
"flds %6\n\t"
|
||||
"fldl (%4)\n\t"
|
||||
"fxch %%st(3)\n\t"
|
||||
"fadd %%st(1), %%st\n\t"
|
||||
"fxch %%st(2)\n\t"
|
||||
"fadd %%st(1), %%st\n\t"
|
||||
"fxch %%st(2)\n\t"
|
||||
"fsub %%st(1), %%st\n\t"
|
||||
"fxch %%st(2)\n\t"
|
||||
"fsubp %%st, %%st(1)\n\t"
|
||||
"fxch %%st(1)\n\t"
|
||||
"fmul %%st(2), %%st\n\t"
|
||||
"fxch %%st(1)\n\t"
|
||||
"fmulp %%st, %%st(2)\n\t"
|
||||
"fsubrp %%st, %%st(3)\n\t"
|
||||
"fsubrp %%st, %%st(1)\n\t"
|
||||
"fxch %%st(1)\n\t"
|
||||
"fistpl (%2)\n\t"
|
||||
"fistpl (%0)\n\t"
|
||||
: : "r" (a0), "m" (b0), "r" (a1), "m" (b1),
|
||||
"r" (dmod), "r" (dinvmod),
|
||||
"m" (MPD_TWO63)
|
||||
: "st", "memory"
|
||||
);
|
||||
}
|
||||
/* END PPRO GCC ASM */
|
||||
#elif defined(MASM)
|
||||
|
||||
/* Return (a * b) % dmod */
|
||||
static inline mpd_uint_t __cdecl
|
||||
ppro_mulmod(mpd_uint_t a, mpd_uint_t b, double *dmod, uint32_t *dinvmod)
|
||||
{
|
||||
mpd_uint_t retval;
|
||||
|
||||
__asm {
|
||||
mov eax, dinvmod
|
||||
mov edx, dmod
|
||||
fild b
|
||||
fild a
|
||||
fmulp st(1), st
|
||||
fld TBYTE PTR [eax]
|
||||
fmul st, st(1)
|
||||
fld MPD_TWO63
|
||||
fadd st(1), st
|
||||
fsubp st(1), st
|
||||
fld QWORD PTR [edx]
|
||||
fmulp st(1), st
|
||||
fsubp st(1), st
|
||||
fistp retval
|
||||
}
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
/*
|
||||
* Two modular multiplications in parallel:
|
||||
* *a0 = (*a0 * w) % dmod
|
||||
* *a1 = (*a1 * w) % dmod
|
||||
*/
|
||||
static inline mpd_uint_t __cdecl
|
||||
ppro_mulmod2c(mpd_uint_t *a0, mpd_uint_t *a1, mpd_uint_t w,
|
||||
double *dmod, uint32_t *dinvmod)
|
||||
{
|
||||
__asm {
|
||||
mov ecx, dmod
|
||||
mov edx, a1
|
||||
mov ebx, dinvmod
|
||||
mov eax, a0
|
||||
fild w
|
||||
fild DWORD PTR [edx]
|
||||
fmul st, st(1)
|
||||
fxch st(1)
|
||||
fild DWORD PTR [eax]
|
||||
fmulp st(1), st
|
||||
fld TBYTE PTR [ebx]
|
||||
fld MPD_TWO63
|
||||
fld st(2)
|
||||
fmul st, st(2)
|
||||
fadd st, st(1)
|
||||
fsub st, st(1)
|
||||
fmul QWORD PTR [ecx]
|
||||
fsubp st(3), st
|
||||
fxch st(2)
|
||||
fistp DWORD PTR [eax]
|
||||
fmul st, st(2)
|
||||
fadd st, st(1)
|
||||
fsubrp st(1), st
|
||||
fmul QWORD PTR [ecx]
|
||||
fsubp st(1), st
|
||||
fistp DWORD PTR [edx]
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Two modular multiplications in parallel:
|
||||
* *a0 = (*a0 * b0) % dmod
|
||||
* *a1 = (*a1 * b1) % dmod
|
||||
*/
|
||||
static inline void __cdecl
|
||||
ppro_mulmod2(mpd_uint_t *a0, mpd_uint_t b0, mpd_uint_t *a1, mpd_uint_t b1,
|
||||
double *dmod, uint32_t *dinvmod)
|
||||
{
|
||||
__asm {
|
||||
mov ecx, dmod
|
||||
mov edx, a1
|
||||
mov ebx, dinvmod
|
||||
mov eax, a0
|
||||
fild b1
|
||||
fild DWORD PTR [edx]
|
||||
fmulp st(1), st
|
||||
fild b0
|
||||
fild DWORD PTR [eax]
|
||||
fmulp st(1), st
|
||||
fld TBYTE PTR [ebx]
|
||||
fld st(2)
|
||||
fmul st, st(1)
|
||||
fxch st(1)
|
||||
fmul st, st(2)
|
||||
fld DWORD PTR MPD_TWO63
|
||||
fld QWORD PTR [ecx]
|
||||
fxch st(3)
|
||||
fadd st, st(1)
|
||||
fxch st(2)
|
||||
fadd st, st(1)
|
||||
fxch st(2)
|
||||
fsub st, st(1)
|
||||
fxch st(2)
|
||||
fsubrp st(1), st
|
||||
fxch st(1)
|
||||
fmul st, st(2)
|
||||
fxch st(1)
|
||||
fmulp st(2), st
|
||||
fsubp st(3), st
|
||||
fsubp st(1), st
|
||||
fxch st(1)
|
||||
fistp DWORD PTR [edx]
|
||||
fistp DWORD PTR [eax]
|
||||
}
|
||||
}
|
||||
#endif /* PPRO MASM (_MSC_VER) */
|
||||
|
||||
|
||||
/* Return (base ** exp) % dmod */
|
||||
static inline mpd_uint_t
|
||||
ppro_powmod(mpd_uint_t base, mpd_uint_t exp, double *dmod, uint32_t *dinvmod)
|
||||
{
|
||||
mpd_uint_t r = 1;
|
||||
|
||||
while (exp > 0) {
|
||||
if (exp & 1)
|
||||
r = ppro_mulmod(r, base, dmod, dinvmod);
|
||||
base = ppro_mulmod(base, base, dmod, dinvmod);
|
||||
exp >>= 1;
|
||||
}
|
||||
|
||||
return r;
|
||||
}
|
||||
#endif /* PPRO */
|
||||
#endif /* CONFIG_32 */
|
||||
|
||||
|
||||
#endif /* UMODARITH_H */
|
||||
|
||||
|
||||
|
57
third_party/python/Modules/_decimal/libmpdec/vccompat.h
vendored
Normal file
57
third_party/python/Modules/_decimal/libmpdec/vccompat.h
vendored
Normal file
|
@ -0,0 +1,57 @@
|
|||
/*
|
||||
* Copyright (c) 2008-2016 Stefan Krah. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
|
||||
#ifndef VCCOMPAT_H
|
||||
#define VCCOMPAT_H
|
||||
|
||||
|
||||
/* Visual C fixes: no stdint.h, no snprintf ... */
|
||||
#ifdef _MSC_VER
|
||||
#undef inline
|
||||
#define inline __inline
|
||||
#undef random
|
||||
#define random rand
|
||||
#undef srandom
|
||||
#define srandom srand
|
||||
#undef snprintf
|
||||
#define snprintf sprintf_s
|
||||
#define HAVE_SNPRINTF
|
||||
#undef strncasecmp
|
||||
#define strncasecmp _strnicmp
|
||||
#undef strcasecmp
|
||||
#define strcasecmp _stricmp
|
||||
#undef strtoll
|
||||
#define strtoll _strtoi64
|
||||
#define strdup _strdup
|
||||
#endif
|
||||
|
||||
|
||||
#endif /* VCCOMPAT_H */
|
||||
|
||||
|
||||
|
48
third_party/python/Modules/_decimal/libmpdec/vcdiv64.asm
vendored
Normal file
48
third_party/python/Modules/_decimal/libmpdec/vcdiv64.asm
vendored
Normal file
|
@ -0,0 +1,48 @@
|
|||
;
|
||||
; Copyright (c) 2008-2016 Stefan Krah. All rights reserved.
|
||||
;
|
||||
; Redistribution and use in source and binary forms, with or without
|
||||
; modification, are permitted provided that the following conditions
|
||||
; are met:
|
||||
;
|
||||
; 1. Redistributions of source code must retain the above copyright
|
||||
; notice, this list of conditions and the following disclaimer.
|
||||
;
|
||||
; 2. Redistributions in binary form must reproduce the above copyright
|
||||
; notice, this list of conditions and the following disclaimer in the
|
||||
; documentation and/or other materials provided with the distribution.
|
||||
;
|
||||
; THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS "AS IS" AND
|
||||
; ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
; IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
; ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
; FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
; DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
; OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
; HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
; LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
; OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
; SUCH DAMAGE.
|
||||
;
|
||||
|
||||
|
||||
PUBLIC _mpd_div_words
|
||||
_TEXT SEGMENT
|
||||
q$ = 8
|
||||
r$ = 16
|
||||
hi$ = 24
|
||||
lo$ = 32
|
||||
d$ = 40
|
||||
_mpd_div_words PROC
|
||||
mov r10, rdx
|
||||
mov rdx, r8
|
||||
mov rax, r9
|
||||
div QWORD PTR d$[rsp]
|
||||
mov QWORD PTR [r10], rdx
|
||||
mov QWORD PTR [rcx], rax
|
||||
ret 0
|
||||
_mpd_div_words ENDP
|
||||
_TEXT ENDS
|
||||
END
|
||||
|
||||
|
232
third_party/python/Modules/_decimal/libmpdec/vcstdint.h
vendored
Normal file
232
third_party/python/Modules/_decimal/libmpdec/vcstdint.h
vendored
Normal file
|
@ -0,0 +1,232 @@
|
|||
// ISO C9x compliant stdint.h for Microsoft Visual Studio
|
||||
// Based on ISO/IEC 9899:TC2 Committee draft (May 6, 2005) WG14/N1124
|
||||
//
|
||||
// Copyright (c) 2006-2008 Alexander Chemeris
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are met:
|
||||
//
|
||||
// 1. Redistributions of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
//
|
||||
// 2. Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
//
|
||||
// 3. The name of the author may be used to endorse or promote products
|
||||
// derived from this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
||||
// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
|
||||
// EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
|
||||
// OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||
// WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
|
||||
// OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
||||
// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef _MSC_VER // [
|
||||
#error "Use this header only with Microsoft Visual C++ compilers!"
|
||||
#endif // _MSC_VER ]
|
||||
|
||||
#ifndef _MSC_STDINT_H_ // [
|
||||
#define _MSC_STDINT_H_
|
||||
|
||||
#if _MSC_VER > 1000
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
#include <limits.h>
|
||||
|
||||
// For Visual Studio 6 in C++ mode wrap <wchar.h> include with 'extern "C++" {}'
|
||||
// or compiler give many errors like this:
|
||||
// error C2733: second C linkage of overloaded function 'wmemchr' not allowed
|
||||
#if (_MSC_VER < 1300) && defined(__cplusplus)
|
||||
extern "C++" {
|
||||
#endif
|
||||
# include <wchar.h>
|
||||
#if (_MSC_VER < 1300) && defined(__cplusplus)
|
||||
}
|
||||
#endif
|
||||
|
||||
// Define _W64 macros to mark types changing their size, like intptr_t.
|
||||
#ifndef _W64
|
||||
# if !defined(__midl) && (defined(_X86_) || defined(_M_IX86)) && _MSC_VER >= 1300
|
||||
# define _W64 __w64
|
||||
# else
|
||||
# define _W64
|
||||
# endif
|
||||
#endif
|
||||
|
||||
|
||||
// 7.18.1 Integer types
|
||||
|
||||
// 7.18.1.1 Exact-width integer types
|
||||
typedef __int8 int8_t;
|
||||
typedef __int16 int16_t;
|
||||
typedef __int32 int32_t;
|
||||
typedef __int64 int64_t;
|
||||
typedef unsigned __int8 uint8_t;
|
||||
typedef unsigned __int16 uint16_t;
|
||||
typedef unsigned __int32 uint32_t;
|
||||
typedef unsigned __int64 uint64_t;
|
||||
|
||||
// 7.18.1.2 Minimum-width integer types
|
||||
typedef int8_t int_least8_t;
|
||||
typedef int16_t int_least16_t;
|
||||
typedef int32_t int_least32_t;
|
||||
typedef int64_t int_least64_t;
|
||||
typedef uint8_t uint_least8_t;
|
||||
typedef uint16_t uint_least16_t;
|
||||
typedef uint32_t uint_least32_t;
|
||||
typedef uint64_t uint_least64_t;
|
||||
|
||||
// 7.18.1.3 Fastest minimum-width integer types
|
||||
typedef int8_t int_fast8_t;
|
||||
typedef int16_t int_fast16_t;
|
||||
typedef int32_t int_fast32_t;
|
||||
typedef int64_t int_fast64_t;
|
||||
typedef uint8_t uint_fast8_t;
|
||||
typedef uint16_t uint_fast16_t;
|
||||
typedef uint32_t uint_fast32_t;
|
||||
typedef uint64_t uint_fast64_t;
|
||||
|
||||
// 7.18.1.4 Integer types capable of holding object pointers
|
||||
#ifdef _WIN64 // [
|
||||
typedef __int64 intptr_t;
|
||||
typedef unsigned __int64 uintptr_t;
|
||||
#else // _WIN64 ][
|
||||
typedef _W64 int intptr_t;
|
||||
typedef _W64 unsigned int uintptr_t;
|
||||
#endif // _WIN64 ]
|
||||
|
||||
// 7.18.1.5 Greatest-width integer types
|
||||
typedef int64_t intmax_t;
|
||||
typedef uint64_t uintmax_t;
|
||||
|
||||
|
||||
// 7.18.2 Limits of specified-width integer types
|
||||
|
||||
#if !defined(__cplusplus) || defined(__STDC_LIMIT_MACROS) // [ See footnote 220 at page 257 and footnote 221 at page 259
|
||||
|
||||
// 7.18.2.1 Limits of exact-width integer types
|
||||
#define INT8_MIN ((int8_t)_I8_MIN)
|
||||
#define INT8_MAX _I8_MAX
|
||||
#define INT16_MIN ((int16_t)_I16_MIN)
|
||||
#define INT16_MAX _I16_MAX
|
||||
#define INT32_MIN ((int32_t)_I32_MIN)
|
||||
#define INT32_MAX _I32_MAX
|
||||
#define INT64_MIN ((int64_t)_I64_MIN)
|
||||
#define INT64_MAX _I64_MAX
|
||||
#define UINT8_MAX _UI8_MAX
|
||||
#define UINT16_MAX _UI16_MAX
|
||||
#define UINT32_MAX _UI32_MAX
|
||||
#define UINT64_MAX _UI64_MAX
|
||||
|
||||
// 7.18.2.2 Limits of minimum-width integer types
|
||||
#define INT_LEAST8_MIN INT8_MIN
|
||||
#define INT_LEAST8_MAX INT8_MAX
|
||||
#define INT_LEAST16_MIN INT16_MIN
|
||||
#define INT_LEAST16_MAX INT16_MAX
|
||||
#define INT_LEAST32_MIN INT32_MIN
|
||||
#define INT_LEAST32_MAX INT32_MAX
|
||||
#define INT_LEAST64_MIN INT64_MIN
|
||||
#define INT_LEAST64_MAX INT64_MAX
|
||||
#define UINT_LEAST8_MAX UINT8_MAX
|
||||
#define UINT_LEAST16_MAX UINT16_MAX
|
||||
#define UINT_LEAST32_MAX UINT32_MAX
|
||||
#define UINT_LEAST64_MAX UINT64_MAX
|
||||
|
||||
// 7.18.2.3 Limits of fastest minimum-width integer types
|
||||
#define INT_FAST8_MIN INT8_MIN
|
||||
#define INT_FAST8_MAX INT8_MAX
|
||||
#define INT_FAST16_MIN INT16_MIN
|
||||
#define INT_FAST16_MAX INT16_MAX
|
||||
#define INT_FAST32_MIN INT32_MIN
|
||||
#define INT_FAST32_MAX INT32_MAX
|
||||
#define INT_FAST64_MIN INT64_MIN
|
||||
#define INT_FAST64_MAX INT64_MAX
|
||||
#define UINT_FAST8_MAX UINT8_MAX
|
||||
#define UINT_FAST16_MAX UINT16_MAX
|
||||
#define UINT_FAST32_MAX UINT32_MAX
|
||||
#define UINT_FAST64_MAX UINT64_MAX
|
||||
|
||||
// 7.18.2.4 Limits of integer types capable of holding object pointers
|
||||
#ifdef _WIN64 // [
|
||||
# define INTPTR_MIN INT64_MIN
|
||||
# define INTPTR_MAX INT64_MAX
|
||||
# define UINTPTR_MAX UINT64_MAX
|
||||
#else // _WIN64 ][
|
||||
# define INTPTR_MIN INT32_MIN
|
||||
# define INTPTR_MAX INT32_MAX
|
||||
# define UINTPTR_MAX UINT32_MAX
|
||||
#endif // _WIN64 ]
|
||||
|
||||
// 7.18.2.5 Limits of greatest-width integer types
|
||||
#define INTMAX_MIN INT64_MIN
|
||||
#define INTMAX_MAX INT64_MAX
|
||||
#define UINTMAX_MAX UINT64_MAX
|
||||
|
||||
// 7.18.3 Limits of other integer types
|
||||
|
||||
#ifdef _WIN64 // [
|
||||
# define PTRDIFF_MIN _I64_MIN
|
||||
# define PTRDIFF_MAX _I64_MAX
|
||||
#else // _WIN64 ][
|
||||
# define PTRDIFF_MIN _I32_MIN
|
||||
# define PTRDIFF_MAX _I32_MAX
|
||||
#endif // _WIN64 ]
|
||||
|
||||
#define SIG_ATOMIC_MIN INT_MIN
|
||||
#define SIG_ATOMIC_MAX INT_MAX
|
||||
|
||||
#ifndef SIZE_MAX // [
|
||||
# ifdef _WIN64 // [
|
||||
# define SIZE_MAX _UI64_MAX
|
||||
# else // _WIN64 ][
|
||||
# define SIZE_MAX _UI32_MAX
|
||||
# endif // _WIN64 ]
|
||||
#endif // SIZE_MAX ]
|
||||
|
||||
// WCHAR_MIN and WCHAR_MAX are also defined in <wchar.h>
|
||||
#ifndef WCHAR_MIN // [
|
||||
# define WCHAR_MIN 0
|
||||
#endif // WCHAR_MIN ]
|
||||
#ifndef WCHAR_MAX // [
|
||||
# define WCHAR_MAX _UI16_MAX
|
||||
#endif // WCHAR_MAX ]
|
||||
|
||||
#define WINT_MIN 0
|
||||
#define WINT_MAX _UI16_MAX
|
||||
|
||||
#endif // __STDC_LIMIT_MACROS ]
|
||||
|
||||
|
||||
// 7.18.4 Limits of other integer types
|
||||
|
||||
#if !defined(__cplusplus) || defined(__STDC_CONSTANT_MACROS) // [ See footnote 224 at page 260
|
||||
|
||||
// 7.18.4.1 Macros for minimum-width integer constants
|
||||
|
||||
#define INT8_C(val) val##i8
|
||||
#define INT16_C(val) val##i16
|
||||
#define INT32_C(val) val##i32
|
||||
#define INT64_C(val) val##i64
|
||||
|
||||
#define UINT8_C(val) val##ui8
|
||||
#define UINT16_C(val) val##ui16
|
||||
#define UINT32_C(val) val##ui32
|
||||
#define UINT64_C(val) val##ui64
|
||||
|
||||
// 7.18.4.2 Macros for greatest-width integer constants
|
||||
#define INTMAX_C INT64_C
|
||||
#define UINTMAX_C UINT64_C
|
||||
|
||||
#endif // __STDC_CONSTANT_MACROS ]
|
||||
|
||||
|
||||
#endif // _MSC_STDINT_H_ ]
|
Loading…
Add table
Add a link
Reference in a new issue