Quellcodebibliothek Statistik Leitseite products/Sources/formale Sprachen/C/Firefox/security/nss/lib/freebl/mpi/   (Browser von der Mozilla Stiftung Version 136.0.1©)  Datei vom 10.2.2025 mit Größe 9 kB image not shown  

Quelle  mplogic.c   Sprache: C

 
/*
 *  mplogic.c
 *
 *  Bitwise logical operations on MPI values
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */


#include "mpi-priv.h"
#include "mplogic.h"

/* {{{ Lookup table for population count */

static unsigned char bitc[] = {
    0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 4,
    1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5,
    1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5,
    2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
    1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5,
    2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
    2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
    3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7,
    1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5,
    2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
    2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
    3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7,
    2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
    3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7,
    3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7,
    4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8
};

/* }}} */

/*------------------------------------------------------------------------*/
/*
  mpl_not(a, b)    - compute b = ~a
  mpl_and(a, b, c) - compute c = a & b
  mpl_or(a, b, c)  - compute c = a | b
  mpl_xor(a, b, c) - compute c = a ^ b
 */


/* {{{ mpl_not(a, b) */

mp_err
mpl_not(mp_int *a, mp_int *b)
{
    mp_err res;
    unsigned int ix;

    ARGCHK(a != NULL && b != NULL, MP_BADARG);

    if ((res = mp_copy(a, b)) != MP_OKAY)
        return res;

    /* This relies on the fact that the digit type is unsigned */
    for (ix = 0; ix < USED(b); ix++)
        DIGIT(b, ix) = ~DIGIT(b, ix);

    s_mp_clamp(b);

    return MP_OKAY;

/* end mpl_not() */

/* }}} */

/* {{{ mpl_and(a, b, c) */

mp_err
mpl_and(mp_int *a, mp_int *b, mp_int *c)
{
    mp_int *which, *other;
    mp_err res;
    unsigned int ix;

    ARGCHK(a != NULL && b != NULL && c != NULL, MP_BADARG);

    if (USED(a) <= USED(b)) {
        which = a;
        other = b;
    } else {
        which = b;
        other = a;
    }

    if ((res = mp_copy(which, c)) != MP_OKAY)
        return res;

    for (ix = 0; ix < USED(which); ix++)
        DIGIT(c, ix) &= DIGIT(other, ix);

    s_mp_clamp(c);

    return MP_OKAY;

/* end mpl_and() */

/* }}} */

/* {{{ mpl_or(a, b, c) */

mp_err
mpl_or(mp_int *a, mp_int *b, mp_int *c)
{
    mp_int *which, *other;
    mp_err res;
    unsigned int ix;

    ARGCHK(a != NULL && b != NULL && c != NULL, MP_BADARG);

    if (USED(a) >= USED(b)) {
        which = a;
        other = b;
    } else {
        which = b;
        other = a;
    }

    if ((res = mp_copy(which, c)) != MP_OKAY)
        return res;

    for (ix = 0; ix < USED(which); ix++)
        DIGIT(c, ix) |= DIGIT(other, ix);

    return MP_OKAY;

/* end mpl_or() */

/* }}} */

/* {{{ mpl_xor(a, b, c) */

mp_err
mpl_xor(mp_int *a, mp_int *b, mp_int *c)
{
    mp_int *which, *other;
    mp_err res;
    unsigned int ix;

    ARGCHK(a != NULL && b != NULL && c != NULL, MP_BADARG);

    if (USED(a) >= USED(b)) {
        which = a;
        other = b;
    } else {
        which = b;
        other = a;
    }

    if ((res = mp_copy(which, c)) != MP_OKAY)
        return res;

    for (ix = 0; ix < USED(which); ix++)
        DIGIT(c, ix) ^= DIGIT(other, ix);

    s_mp_clamp(c);

    return MP_OKAY;

/* end mpl_xor() */

/* }}} */

/*------------------------------------------------------------------------*/
/*
  mpl_rsh(a, b, d)     - b = a >> d
  mpl_lsh(a, b, d)     - b = a << d
 */


/* {{{ mpl_rsh(a, b, d) */

mp_err
mpl_rsh(const mp_int *a, mp_int *b, mp_digit d)
{
    mp_err res;

    ARGCHK(a != NULL && b != NULL, MP_BADARG);

    if ((res = mp_copy(a, b)) != MP_OKAY)
        return res;

    s_mp_div_2d(b, d);

    return MP_OKAY;

/* end mpl_rsh() */

/* }}} */

/* {{{ mpl_lsh(a, b, d) */

mp_err
mpl_lsh(const mp_int *a, mp_int *b, mp_digit d)
{
    mp_err res;

    ARGCHK(a != NULL && b != NULL, MP_BADARG);

    if ((res = mp_copy(a, b)) != MP_OKAY)
        return res;

    return s_mp_mul_2d(b, d);

/* end mpl_lsh() */

/* }}} */

/*------------------------------------------------------------------------*/
/*
  mpl_num_set(a, num)

  Count the number of set bits in the binary representation of a.
  Returns MP_OKAY and sets 'num' to be the number of such bits, if
  possible.  If num is NULL, the result is thrown away, but it is
  not considered an error.

  mpl_num_clear() does basically the same thing for clear bits.
 */


/* {{{ mpl_num_set(a, num) */

mp_err
mpl_num_set(mp_int *a, unsigned int *num)
{
    unsigned int ix, db, nset = 0;
    mp_digit cur;
    unsigned char reg;

    ARGCHK(a != NULL, MP_BADARG);

    for (ix = 0; ix < USED(a); ix++) {
        cur = DIGIT(a, ix);

        for (db = 0; db < sizeof(mp_digit); db++) {
            reg = (unsigned char)(cur >> (CHAR_BIT * db));

            nset += bitc[reg];
        }
    }

    if (num)
        *num = nset;

    return MP_OKAY;

/* end mpl_num_set() */

/* }}} */

/* {{{ mpl_num_clear(a, num) */

mp_err
mpl_num_clear(mp_int *a, unsigned int *num)
{
    unsigned int ix, db, nset = 0;
    mp_digit cur;
    unsigned char reg;

    ARGCHK(a != NULL, MP_BADARG);

    for (ix = 0; ix < USED(a); ix++) {
        cur = DIGIT(a, ix);

        for (db = 0; db < sizeof(mp_digit); db++) {
            reg = (unsigned char)(cur >> (CHAR_BIT * db));

            nset += bitc[UCHAR_MAX - reg];
        }
    }

    if (num)
        *num = nset;

    return MP_OKAY;

/* end mpl_num_clear() */

/* }}} */

/*------------------------------------------------------------------------*/
/*
  mpl_parity(a)

  Determines the bitwise parity of the value given.  Returns MP_EVEN
  if an even number of digits are set, MP_ODD if an odd number are
  set.
 */


/* {{{ mpl_parity(a) */

mp_err
mpl_parity(mp_int *a)
{
    unsigned int ix;
    int par = 0;
    mp_digit cur;

    ARGCHK(a != NULL, MP_BADARG);

    for (ix = 0; ix < USED(a); ix++) {
        int shft = (sizeof(mp_digit) * CHAR_BIT) / 2;

        cur = DIGIT(a, ix);

        /* Compute parity for current digit */
        while (shft != 0) {
            cur ^= (cur >> shft);
            shft >>= 1;
        }
        cur &= 1;

        /* XOR with running parity so far   */
        par ^= cur;
    }

    if (par)
        return MP_ODD;
    else
        return MP_EVEN;

/* end mpl_parity() */

/* }}} */

/*
  mpl_set_bit

  Returns MP_OKAY or some error code.
  Grows a if needed to set a bit to 1.
 */

mp_err
mpl_set_bit(mp_int *a, mp_size bitNum, mp_size value)
{
    mp_size ix;
    mp_err rv;
    mp_digit mask;

    ARGCHK(a != NULL, MP_BADARG);

    ix = bitNum / MP_DIGIT_BIT;
    if (ix + 1 > MP_USED(a)) {
        rv = s_mp_pad(a, ix + 1);
        if (rv != MP_OKAY)
            return rv;
    }

    bitNum = bitNum % MP_DIGIT_BIT;
    mask = (mp_digit)1 << bitNum;
    if (value)
        MP_DIGIT(a, ix) |= mask;
    else
        MP_DIGIT(a, ix) &= ~mask;
    s_mp_clamp(a);
    return MP_OKAY;
}

/*
  mpl_get_bit

  returns 0 or 1 or some (negative) error code.
 */

mp_err
mpl_get_bit(const mp_int *a, mp_size bitNum)
{
    mp_size bit, ix;
    mp_err rv;

    ARGCHK(a != NULL, MP_BADARG);

    ix = bitNum / MP_DIGIT_BIT;
    ARGCHK(ix <= MP_USED(a) - 1, MP_RANGE);

    bit = bitNum % MP_DIGIT_BIT;
    rv = (mp_err)(MP_DIGIT(a, ix) >> bit) & 1;
    return rv;
}

/*
  mpl_get_bits
  - Extracts numBits bits from a, where the least significant extracted bit
  is bit lsbNum.  Returns a negative value if error occurs.
  - Because sign bit is used to indicate error, maximum number of bits to
  be returned is the lesser of (a) the number of bits in an mp_digit, or
  (b) one less than the number of bits in an mp_err.
  - lsbNum + numbits can be greater than the number of significant bits in
  integer a, as long as bit lsbNum is in the high order digit of a.
 */

mp_err
mpl_get_bits(const mp_int *a, mp_size lsbNum, mp_size numBits)
{
    mp_size rshift = (lsbNum % MP_DIGIT_BIT);
    mp_size lsWndx = (lsbNum / MP_DIGIT_BIT);
    mp_digit *digit = MP_DIGITS(a) + lsWndx;
    mp_digit mask = ((1 << numBits) - 1);

    ARGCHK(numBits < CHAR_BIT * sizeof mask, MP_BADARG);
    ARGCHK(MP_HOWMANY(lsbNum, MP_DIGIT_BIT) <= MP_USED(a), MP_RANGE);

    if ((numBits + lsbNum % MP_DIGIT_BIT <= MP_DIGIT_BIT) ||
        (lsWndx + 1 >= MP_USED(a))) {
        mask &= (digit[0] >> rshift);
    } else {
        mask &= ((digit[0] >> rshift) | (digit[1] << (MP_DIGIT_BIT - rshift)));
    }
    return (mp_err)mask;
}

#define LZCNTLOOP(i)                               \
    do {                                           \
        x = d >> (i);                              \
        mask = (0 - x);                            \
        mask = (0 - (mask >> (MP_DIGIT_BIT - 1))); \
        bits += (i)&mask;                          \
        d ^= (x ^ d) & mask;                       \
    } while (0)

/*
  mpl_significant_bits
  returns number of significant bits in abs(a).
  In other words: floor(lg(abs(a))) + 1.
  returns 1 if value is zero.
 */

mp_size
mpl_significant_bits(const mp_int *a)
{
    /*
      start bits at 1.
      lg(0) = 0 => bits = 1 by function semantics.
      below does a binary search for the _position_ of the top bit set,
      which is floor(lg(abs(a))) for a != 0.
     */

    mp_size bits = 1;
    int ix;

    ARGCHK(a != NULL, MP_BADARG);

    for (ix = MP_USED(a); ix > 0;) {
        mp_digit d, x, mask;
        if ((d = MP_DIGIT(a, --ix)) == 0)
            continue;
#if !defined(MP_USE_UINT_DIGIT)
        LZCNTLOOP(32);
#endif
        LZCNTLOOP(16);
        LZCNTLOOP(8);
        LZCNTLOOP(4);
        LZCNTLOOP(2);
        LZCNTLOOP(1);
        break;
    }
    bits += ix * MP_DIGIT_BIT;
    return bits;
}

#undef LZCNTLOOP

/*------------------------------------------------------------------------*/
/* HERE THERE BE DRAGONS                                                  */

Messung V0.5
C=91 H=95 G=92

¤ Dauer der Verarbeitung: 0.23 Sekunden  (vorverarbeitet)  ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

Beweissystem der NASA

Beweissystem Isabelle

NIST Cobol Testsuite

Cephes Mathematical Library

Wiener Entwicklungsmethode

Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.

Bemerkung:

Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.