cpython/Modules/_decimal/libmpdec/basearith.c

/*
 * Copyright (c) 2008-2020 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 <stdio.h>

#include "basearith.h"
#include "constants.h"
#include "typearith.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)
{}

/*
 * 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)
{}

/*
 * 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)
{}

/* Increment u. The calling function has to handle a possible carry. */
mpd_uint_t
_mpd_baseincr(mpd_uint_t *u, mpd_size_t n)
{}

/*
 * 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)
{}

/*
 * 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)
{}

/* 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)
{}

/*
 * 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)
{}

/*
 * 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)
{}

/*
 * 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)
{}

/*
 * 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)
{}

/*
 * 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)
{}


/*********************************************************************/
/*                      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)
{}

/* 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)
{}

/* 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)
{}

/*
 * 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)
{}