4272N/A/*
4272N/A * Copyright (c) 2007, 2011, Oracle and/or its affiliates. All rights reserved.
4272N/A * Use is subject to license terms.
4272N/A *
4272N/A * This library is free software; you can redistribute it and/or
4272N/A * modify it under the terms of the GNU Lesser General Public
4272N/A * License as published by the Free Software Foundation; either
4272N/A * version 2.1 of the License, or (at your option) any later version.
1674N/A *
4272N/A * This library is distributed in the hope that it will be useful,
4272N/A * but WITHOUT ANY WARRANTY; without even the implied warranty of
4272N/A * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
4272N/A * Lesser General Public License for more details.
1674N/A *
4272N/A * You should have received a copy of the GNU Lesser General Public License
4272N/A * along with this library; if not, write to the Free Software Foundation,
4272N/A * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
1674N/A *
4272N/A * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
4272N/A * or visit www.oracle.com if you need additional information or have any
4272N/A * questions.
4272N/A */
4272N/A
4272N/A/* *********************************************************************
1674N/A *
1674N/A * The Original Code is the MPI Arbitrary Precision Integer Arithmetic library.
1674N/A *
1674N/A * The Initial Developer of the Original Code is
1674N/A * Michael J. Fromberger.
1674N/A * Portions created by the Initial Developer are Copyright (C) 1998
1674N/A * the Initial Developer. All Rights Reserved.
1674N/A *
1674N/A * Contributor(s):
1674N/A *
1674N/A *********************************************************************** */
1674N/A
4272N/A/* Bitwise logical operations on MPI values */
1674N/A
1674N/A#include "mpi-priv.h"
1674N/A#include "mplogic.h"
1674N/A
1674N/A/* {{{ Lookup table for population count */
1674N/A
1674N/Astatic unsigned char bitc[] = {
1674N/A 0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 4,
1674N/A 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5,
1674N/A 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5,
1674N/A 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
1674N/A 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5,
1674N/A 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
1674N/A 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
1674N/A 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7,
1674N/A 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5,
1674N/A 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
1674N/A 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
1674N/A 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7,
1674N/A 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
1674N/A 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7,
1674N/A 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7,
1674N/A 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8
1674N/A};
1674N/A
1674N/A/* }}} */
1674N/A
1674N/A/*
1674N/A mpl_rsh(a, b, d) - b = a >> d
1674N/A mpl_lsh(a, b, d) - b = a << d
1674N/A */
1674N/A
1674N/A/* {{{ mpl_rsh(a, b, d) */
1674N/A
1674N/Amp_err mpl_rsh(const mp_int *a, mp_int *b, mp_digit d)
1674N/A{
1674N/A mp_err res;
1674N/A
1674N/A ARGCHK(a != NULL && b != NULL, MP_BADARG);
1674N/A
1674N/A if((res = mp_copy(a, b)) != MP_OKAY)
1674N/A return res;
1674N/A
1674N/A s_mp_div_2d(b, d);
1674N/A
1674N/A return MP_OKAY;
1674N/A
1674N/A} /* end mpl_rsh() */
1674N/A
1674N/A/* }}} */
1674N/A
1674N/A/* {{{ mpl_lsh(a, b, d) */
1674N/A
1674N/Amp_err mpl_lsh(const mp_int *a, mp_int *b, mp_digit d)
1674N/A{
1674N/A mp_err res;
1674N/A
1674N/A ARGCHK(a != NULL && b != NULL, MP_BADARG);
1674N/A
1674N/A if((res = mp_copy(a, b)) != MP_OKAY)
1674N/A return res;
1674N/A
1674N/A return s_mp_mul_2d(b, d);
1674N/A
1674N/A} /* end mpl_lsh() */
1674N/A
1674N/A/* }}} */
1674N/A
1674N/A/*------------------------------------------------------------------------*/
1674N/A/*
1674N/A mpl_set_bit
1674N/A
1674N/A Returns MP_OKAY or some error code.
1674N/A Grows a if needed to set a bit to 1.
1674N/A */
1674N/Amp_err mpl_set_bit(mp_int *a, mp_size bitNum, mp_size value)
1674N/A{
1674N/A mp_size ix;
1674N/A mp_err rv;
1674N/A mp_digit mask;
1674N/A
1674N/A ARGCHK(a != NULL, MP_BADARG);
1674N/A
1674N/A ix = bitNum / MP_DIGIT_BIT;
1674N/A if (ix + 1 > MP_USED(a)) {
1674N/A rv = s_mp_pad(a, ix + 1);
1674N/A if (rv != MP_OKAY)
1674N/A return rv;
1674N/A }
1674N/A
1674N/A bitNum = bitNum % MP_DIGIT_BIT;
1674N/A mask = (mp_digit)1 << bitNum;
1674N/A if (value)
1674N/A MP_DIGIT(a,ix) |= mask;
1674N/A else
1674N/A MP_DIGIT(a,ix) &= ~mask;
1674N/A s_mp_clamp(a);
1674N/A return MP_OKAY;
1674N/A}
1674N/A
1674N/A/*
1674N/A mpl_get_bit
1674N/A
1674N/A returns 0 or 1 or some (negative) error code.
1674N/A */
1674N/Amp_err mpl_get_bit(const mp_int *a, mp_size bitNum)
1674N/A{
1674N/A mp_size bit, ix;
1674N/A mp_err rv;
1674N/A
1674N/A ARGCHK(a != NULL, MP_BADARG);
1674N/A
1674N/A ix = bitNum / MP_DIGIT_BIT;
1674N/A ARGCHK(ix <= MP_USED(a) - 1, MP_RANGE);
1674N/A
1674N/A bit = bitNum % MP_DIGIT_BIT;
1674N/A rv = (mp_err)(MP_DIGIT(a, ix) >> bit) & 1;
1674N/A return rv;
1674N/A}
1674N/A
1674N/A/*
1674N/A mpl_get_bits
1674N/A - Extracts numBits bits from a, where the least significant extracted bit
1674N/A is bit lsbNum. Returns a negative value if error occurs.
1674N/A - Because sign bit is used to indicate error, maximum number of bits to
1674N/A be returned is the lesser of (a) the number of bits in an mp_digit, or
1674N/A (b) one less than the number of bits in an mp_err.
1674N/A - lsbNum + numbits can be greater than the number of significant bits in
1674N/A integer a, as long as bit lsbNum is in the high order digit of a.
1674N/A */
1674N/Amp_err mpl_get_bits(const mp_int *a, mp_size lsbNum, mp_size numBits)
1674N/A{
1674N/A mp_size rshift = (lsbNum % MP_DIGIT_BIT);
1674N/A mp_size lsWndx = (lsbNum / MP_DIGIT_BIT);
1674N/A mp_digit * digit = MP_DIGITS(a) + lsWndx;
1674N/A mp_digit mask = ((1 << numBits) - 1);
1674N/A
1674N/A ARGCHK(numBits < CHAR_BIT * sizeof mask, MP_BADARG);
1674N/A ARGCHK(MP_HOWMANY(lsbNum, MP_DIGIT_BIT) <= MP_USED(a), MP_RANGE);
1674N/A
1674N/A if ((numBits + lsbNum % MP_DIGIT_BIT <= MP_DIGIT_BIT) ||
1674N/A (lsWndx + 1 >= MP_USED(a))) {
1674N/A mask &= (digit[0] >> rshift);
1674N/A } else {
1674N/A mask &= ((digit[0] >> rshift) | (digit[1] << (MP_DIGIT_BIT - rshift)));
1674N/A }
1674N/A return (mp_err)mask;
1674N/A}
1674N/A
1674N/A/*
1674N/A mpl_significant_bits
1674N/A returns number of significnant bits in abs(a).
1674N/A returns 1 if value is zero.
1674N/A */
1674N/Amp_err mpl_significant_bits(const mp_int *a)
1674N/A{
1674N/A mp_err bits = 0;
1674N/A int ix;
1674N/A
1674N/A ARGCHK(a != NULL, MP_BADARG);
1674N/A
1674N/A ix = MP_USED(a);
1674N/A for (ix = MP_USED(a); ix > 0; ) {
1674N/A mp_digit d;
1674N/A d = MP_DIGIT(a, --ix);
1674N/A if (d) {
1674N/A while (d) {
1674N/A ++bits;
1674N/A d >>= 1;
1674N/A }
1674N/A break;
1674N/A }
1674N/A }
1674N/A bits += ix * MP_DIGIT_BIT;
1674N/A if (!bits)
1674N/A bits = 1;
1674N/A return bits;
1674N/A}
1674N/A
1674N/A/*------------------------------------------------------------------------*/
1674N/A/* HERE THERE BE DRAGONS */