VirtualBox

Ignore:
Timestamp:
Aug 6, 2014 10:14:47 AM (11 years ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
95402
Message:

RTBigNum: Two assembly optimizations related to RTBigNumModExp. Use 64-bit element type on 64-bit hosts (instead of 32-bit everywhere). Fixed some bugs in the bit operations, which apparently didn't affect x86 or AMD64.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Runtime/common/math/bignum.cpp

    r52050 r52290  
    2929*   Header Files                                                               *
    3030*******************************************************************************/
     31/*#ifdef IN_RING3
     32# define RTMEM_WRAP_TO_EF_APIS
     33#endif*/
    3134#include "internal/iprt.h"
    3235#include <iprt/bignum.h>
     
    4043
    4144
     45/*******************************************************************************
     46*   Defined Constants And Macros                                               *
     47*******************************************************************************/
     48/** Allocation alignment in elements. */
     49#ifndef RTMEM_WRAP_TO_EF_APIS
     50# define RTBIGNUM_ALIGNMENT             4U
     51#else
     52# define RTBIGNUM_ALIGNMENT             1U
     53#endif
     54
    4255/** The max size (in bytes) of an elements array. */
    4356#define RTBIGNUM_MAX_SIZE               _4M
     57
     58
     59/** Assert the validity of a big number structure pointer in strict builds. */
     60#ifdef RT_STRICT
     61# define RTBIGNUM_ASSERT_VALID(a_pBigNum) \
     62    do { \
     63        AssertPtr(a_pBigNum); \
     64        Assert(!(a_pBigNum)->fCurScrambled); \
     65        Assert(   (a_pBigNum)->cUsed == (a_pBigNum)->cAllocated \
     66               || ASMMemIsAllU32(&(a_pBigNum)->pauElements[(a_pBigNum)->cUsed], \
     67                                 ((a_pBigNum)->cAllocated - (a_pBigNum)->cUsed) * RTBIGNUM_ELEMENT_SIZE, 0) == NULL); \
     68    } while (0)
     69#else
     70# define RTBIGNUM_ASSERT_VALID(a_pBigNum) do {} while (0)
     71#endif
     72
     73
     74/** Enable assembly optimizations. */
     75#if defined(RT_ARCH_AMD64) || defined(RT_ARCH_X86)
     76# define IPRT_BIGINT_WITH_ASM
     77#endif
     78
     79
     80/** @def RTBIGNUM_ZERO_ALIGN
     81 * For calculating the rtBigNumEnsureExtraZeroElements argument from cUsed.
     82 * This has to do with 64-bit assembly instruction operating as RTBIGNUMELEMENT
     83 * was 64-bit on some hosts.
     84 */
     85#if defined(IPRT_BIGINT_WITH_ASM) && ARCH_BITS == 64 && RTBIGNUM_ELEMENT_SIZE == 4 && defined(RT_LITTLE_ENDIAN)
     86# define RTBIGNUM_ZERO_ALIGN(a_cUsed)   RT_ALIGN_32(a_cUsed, 2)
     87#elif defined(IPRT_BIGINT_WITH_ASM)
     88# define RTBIGNUM_ZERO_ALIGN(a_cUsed)   (a_cUsed)
     89#else
     90# define RTBIGNUM_ZERO_ALIGN(a_cUsed)   (a_cUsed)
     91#endif
     92
     93
     94/*******************************************************************************
     95*   Internal Functions                                                         *
     96*******************************************************************************/
     97#ifdef IPRT_BIGINT_WITH_ASM
     98/* bignum-amd64-x86.asm: */
     99DECLASM(void) rtBigNumMagnitudeSubAssemblyWorker(RTBIGNUMELEMENT *pauResult, RTBIGNUMELEMENT const *pauMinuend,
     100                                                 RTBIGNUMELEMENT const *pauSubtrahend, uint32_t cUsed);
     101DECLASM(void) rtBigNumMagnitudeSubThisAssemblyWorker(RTBIGNUMELEMENT *pauMinuendResult, RTBIGNUMELEMENT const *pauSubtrahend,
     102                                                     uint32_t cUsed);
     103DECLASM(RTBIGNUMELEMENT) rtBigNumMagnitudeShiftLeftOneAssemblyWorker(RTBIGNUMELEMENT *pauElements, uint32_t cUsed,
     104                                                                     RTBIGNUMELEMENT uCarry);
     105#endif
    44106
    45107
     
    110172 * @param   pBigNum         The big number.
    111173 * @param   cNewUsed        The new cUsed value.
    112  */
    113 static int rtBigNumGrow(PRTBIGNUM pBigNum, uint32_t cNewUsed)
    114 {
     174 * @param   cMinElements    The minimum number of elements.
     175 */
     176static int rtBigNumGrow(PRTBIGNUM pBigNum, uint32_t cNewUsed, uint32_t cMinElements)
     177{
     178    Assert(cMinElements >= cNewUsed);
    115179    uint32_t const cbOld = pBigNum->cAllocated * RTBIGNUM_ELEMENT_SIZE;
    116     uint32_t const cNew  = RT_ALIGN_32(cNewUsed, 4);
     180    uint32_t const cNew  = RT_ALIGN_32(cMinElements, RTBIGNUM_ALIGNMENT);
    117181    uint32_t const cbNew = cNew * RTBIGNUM_ELEMENT_SIZE;
    118182    Assert(cbNew > cbOld);
     
    140204 * Changes the cUsed member, growing the pauElements array if necessary.
    141205 *
    142  * No assumptions about the value of any added elements should be made. This
    143  * method is mainly for resizing result values where the caller will repopulate
    144  * the element values short after this call.
     206 * Any elements added to the array will be initialized to zero.
    145207 *
    146208 * @returns IPRT status code.
     
    152214    if (pBigNum->cAllocated >= cNewUsed)
    153215    {
     216        if (pBigNum->cUsed > cNewUsed)
     217            RT_BZERO(&pBigNum->pauElements[cNewUsed], (pBigNum->cUsed - cNewUsed) * RTBIGNUM_ELEMENT_SIZE);
     218#ifdef RT_STRICT
     219        else if (pBigNum->cUsed != cNewUsed)
     220            Assert(ASMMemIsAllU32(&pBigNum->pauElements[pBigNum->cUsed],
     221                                  (cNewUsed - pBigNum->cUsed) * RTBIGNUM_ELEMENT_SIZE, 0) == NULL);
     222#endif
    154223        pBigNum->cUsed = cNewUsed;
    155224        return VINF_SUCCESS;
    156225    }
    157     return rtBigNumGrow(pBigNum, cNewUsed);
    158 }
     226    return rtBigNumGrow(pBigNum, cNewUsed, cNewUsed);
     227}
     228
     229
     230/**
     231 * Extended version of rtBigNumSetUsed that also allow specifying the number of
     232 * zero elements required.
     233 *
     234 * @returns IPRT status code.
     235 * @param   pBigNum         The big number.
     236 * @param   cNewUsed        The new cUsed value.
     237 * @param   cMinElements    The minimum number of elements allocated. The
     238 *                          difference between @a cNewUsed and @a cMinElements
     239 *                          is initialized to zero because all free elements are
     240 *                          zero.
     241 */
     242DECLINLINE(int) rtBigNumSetUsedEx(PRTBIGNUM pBigNum, uint32_t cNewUsed, uint32_t cMinElements)
     243{
     244    if (pBigNum->cAllocated >= cMinElements)
     245    {
     246        if (pBigNum->cUsed > cNewUsed)
     247            RT_BZERO(&pBigNum->pauElements[cNewUsed], (pBigNum->cUsed - cNewUsed) * RTBIGNUM_ELEMENT_SIZE);
     248#ifdef RT_STRICT
     249        else if (pBigNum->cUsed != cNewUsed)
     250            Assert(ASMMemIsAllU32(&pBigNum->pauElements[pBigNum->cUsed],
     251                                  (cNewUsed - pBigNum->cUsed) * RTBIGNUM_ELEMENT_SIZE, 0) == NULL);
     252#endif
     253        pBigNum->cUsed = cNewUsed;
     254        return VINF_SUCCESS;
     255    }
     256    return rtBigNumGrow(pBigNum, cNewUsed, cMinElements);
     257}
     258
     259
     260/**
     261 * For ensuring zero padding of pauElements for sub/add with carry assembly
     262 * operations.
     263 *
     264 * @returns IPRT status code.
     265 * @param   pBigNum         The big number.
     266 * @param   cElements       The number of elements that must be in the elements
     267 *                          array array, where those after pBigNum->cUsed must
     268 *                          be zero.
     269 */
     270DECLINLINE(int) rtBigNumEnsureExtraZeroElements(PRTBIGNUM pBigNum, uint32_t cElements)
     271{
     272    if (pBigNum->cAllocated >= cElements)
     273    {
     274        Assert(   pBigNum->cAllocated == pBigNum->cUsed
     275               || ASMMemIsAllU32(&pBigNum->pauElements[pBigNum->cUsed],
     276                                 (pBigNum->cAllocated - pBigNum->cUsed) * RTBIGNUM_ELEMENT_SIZE, 0) == NULL);
     277        return VINF_SUCCESS;
     278    }
     279    return rtBigNumGrow(pBigNum, pBigNum->cUsed, cElements);
     280}
     281
    159282
    160283/**
     
    321444    if (pBigNum->cUsed)
    322445    {
    323         pBigNum->cAllocated = RT_ALIGN_32(pBigNum->cUsed, 4);
     446        pBigNum->cAllocated = RT_ALIGN_32(pBigNum->cUsed, RTBIGNUM_ALIGNMENT);
    324447        if (pBigNum->fSensitive)
    325448            pBigNum->pauElements = (RTBIGNUMELEMENT *)RTMemSaferAllocZ(pBigNum->cAllocated * RTBIGNUM_ELEMENT_SIZE);
     
    415538                pBigNum->pauElements[i] = 0U - pBigNum->pauElements[i] - 1U;
    416539        }
     540
     541        /*
     542         * Clear unused elements.
     543         */
     544        if (pBigNum->cUsed != pBigNum->cAllocated)
     545        {
     546            RTBIGNUMELEMENT *puUnused = &pBigNum->pauElements[pBigNum->cUsed];
     547            AssertCompile(RTBIGNUM_ALIGNMENT <= 4);
     548            switch (pBigNum->cAllocated - pBigNum->cUsed)
     549            {
     550                default: AssertFailed();
     551                case 3: *puUnused++ = 0;
     552                case 2: *puUnused++ = 0;
     553                case 1: *puUnused++ = 0;
     554            }
     555        }
     556        RTBIGNUM_ASSERT_VALID(pBigNum);
    417557    }
    418558
     
    455595    {
    456596        /* Duplicate the element array. */
    457         pBigNum->cAllocated = RT_ALIGN_32(pBigNum->cUsed, 4);
     597        pBigNum->cAllocated = RT_ALIGN_32(pBigNum->cUsed, RTBIGNUM_ALIGNMENT);
    458598        if (pBigNum->fSensitive)
    459599            pBigNum->pauElements = (RTBIGNUMELEMENT *)RTMemSaferAllocZ(pBigNum->cAllocated * RTBIGNUM_ELEMENT_SIZE);
     
    461601            pBigNum->pauElements = (RTBIGNUMELEMENT *)RTMemAlloc(pBigNum->cAllocated * RTBIGNUM_ELEMENT_SIZE);
    462602        if (RT_LIKELY(pBigNum->pauElements))
     603        {
    463604            memcpy(pBigNum->pauElements, pSrc->pauElements, pBigNum->cUsed * RTBIGNUM_ELEMENT_SIZE);
     605            if (pBigNum->cUsed != pBigNum->cAllocated)
     606                RT_BZERO(&pBigNum->pauElements[pBigNum->cUsed], (pBigNum->cAllocated - pBigNum->cUsed) * RTBIGNUM_ELEMENT_SIZE);
     607        }
    464608        else
    465609        {
     
    477621    if (RT_SUCCESS(rc))
    478622    {
     623        RTBIGNUM_ASSERT_VALID(pSrc);
    479624        rc = rtBigNumCloneInternal(pBigNum, pSrc);
    480625        if (RT_SUCCESS(rc))
     
    512657    if (RT_SUCCESS(rc))
    513658    {
     659        RTBIGNUM_ASSERT_VALID(pDst);
    514660        rc = rtBigNumUnscramble((PRTBIGNUM)pSrc);
    515661        if (RT_SUCCESS(rc))
    516662        {
     663            RTBIGNUM_ASSERT_VALID(pSrc);
    517664            if (   pDst->fSensitive == pSrc->fSensitive
    518665                || pDst->fSensitive)
     
    520667                if (pDst->cAllocated >= pSrc->cUsed)
    521668                {
     669                    if (pDst->cUsed > pSrc->cUsed)
     670                        RT_BZERO(&pDst->pauElements[pSrc->cUsed], (pDst->cUsed - pSrc->cUsed) * RTBIGNUM_ELEMENT_SIZE);
    522671                    pDst->cUsed     = pSrc->cUsed;
    523672                    pDst->fNegative = pSrc->fNegative;
     
    526675                else
    527676                {
    528                     rc = rtBigNumGrow(pDst, pSrc->cUsed);
     677                    rc = rtBigNumGrow(pDst, pSrc->cUsed, pSrc->cUsed);
    529678                    if (RT_SUCCESS(rc))
    530679                    {
     
    610759    if (RT_SUCCESS(rc))
    611760    {
     761        RTBIGNUM_ASSERT_VALID(pBigNum);
    612762        rc = VINF_SUCCESS;
    613763        if (pBigNum->cUsed != 0)
     
    681831    if (RT_SUCCESS(rc))
    682832    {
     833        RTBIGNUM_ASSERT_VALID(pLeft);
    683834        rc = rtBigNumUnscramble(pRight);
    684835        if (RT_SUCCESS(rc))
    685836        {
     837            RTBIGNUM_ASSERT_VALID(pRight);
    686838            if (pLeft->fNegative == pRight->fNegative)
    687839            {
     
    720872    if (RT_SUCCESS(rc))
    721873    {
     874        RTBIGNUM_ASSERT_VALID(pLeft);
    722875        if (!pLeft->fNegative)
    723876        {
     
    767920    if (RT_SUCCESS(rc))
    768921    {
     922        RTBIGNUM_ASSERT_VALID(pLeft);
    769923        if (pLeft->fNegative == (iRight < 0))
    770924        {
     
    843997
    844998/**
     999 * Copies the magnitude of on number (@a pSrc) to another (@a pBigNum).
     1000 *
     1001 * The variables must be unscrambled.  The sign flag is not considered nor
     1002 * touched.
     1003 *
     1004 * @returns IPRT status code.
     1005 * @param   pDst            The destination number.
     1006 * @param   pSrc            The source number.
     1007 */
     1008DECLINLINE(int) rtBigNumMagnitudeCopy(PRTBIGNUM pDst, PCRTBIGNUM pSrc)
     1009{
     1010    int rc = rtBigNumSetUsed(pDst, pSrc->cUsed);
     1011    if (RT_SUCCESS(rc))
     1012        memcpy(pDst->pauElements, pSrc->pauElements, pSrc->cUsed * RTBIGNUM_ELEMENT_SIZE);
     1013    return rc;
     1014}
     1015
     1016
     1017/**
    8451018 * Does addition with carry.
    8461019 *
     
    9531126    Assert(pMinuend->cUsed >= pSubtrahend->cUsed);
    9541127
    955     int rc = rtBigNumSetUsed(pResult, pMinuend->cUsed);
    956     if (RT_SUCCESS(rc))
     1128    int rc;
     1129    if (pSubtrahend->cUsed)
    9571130    {
    9581131        /*
    959          * The primitive way, as usual.
     1132         * Resize the result. In the assembly case, ensure that all three arrays
     1133         * has the same number of used entries, possibly with an extra zero
     1134         * element on 64-bit systems.
    9601135         */
    961         RTBIGNUMELEMENT fBorrow = 0;
    962         for (uint32_t i = 0; i < pMinuend->cUsed; i++)
    963             pResult->pauElements[i] = rtBigNumElementSubWithBorrow(pMinuend->pauElements[i],
    964                                                                    rtBigNumGetElement(pSubtrahend, i),
    965                                                                    &fBorrow);
    966         Assert(fBorrow == 0);
    967 
    968         /*
    969          * Trim the result.
    970          */
    971         rtBigNumStripTrailingZeros(pResult);
    972     }
     1136        rc = rtBigNumSetUsedEx(pResult, pMinuend->cUsed, RTBIGNUM_ZERO_ALIGN(pMinuend->cUsed));
     1137#ifdef IPRT_BIGINT_WITH_ASM
     1138        if (RT_SUCCESS(rc))
     1139            rc = rtBigNumEnsureExtraZeroElements((PRTBIGNUM)pMinuend, RTBIGNUM_ZERO_ALIGN(pMinuend->cUsed));
     1140        if (RT_SUCCESS(rc))
     1141            rc = rtBigNumEnsureExtraZeroElements((PRTBIGNUM)pSubtrahend, RTBIGNUM_ZERO_ALIGN(pMinuend->cUsed));
     1142#endif
     1143        if (RT_SUCCESS(rc))
     1144        {
     1145#ifdef IPRT_BIGINT_WITH_ASM
     1146            /*
     1147             * Call assembly to do the work.
     1148             */
     1149            rtBigNumMagnitudeSubAssemblyWorker(pResult->pauElements, pMinuend->pauElements,
     1150                                               pSubtrahend->pauElements, pMinuend->cUsed);
     1151# ifdef RT_STRICT
     1152            RTBIGNUMELEMENT fBorrow = 0;
     1153            for (uint32_t i = 0; i < pMinuend->cUsed; i++)
     1154            {
     1155                RTBIGNUMELEMENT uCorrect = rtBigNumElementSubWithBorrow(pMinuend->pauElements[i], rtBigNumGetElement(pSubtrahend, i), &fBorrow);
     1156                AssertMsg(pResult->pauElements[i] == uCorrect, ("[%u]=%#x, expected %#x\n", i, pResult->pauElements[i], uCorrect));
     1157            }
     1158# endif
     1159#else
     1160            /*
     1161             * The primitive C way.
     1162             */
     1163            RTBIGNUMELEMENT fBorrow = 0;
     1164            for (uint32_t i = 0; i < pMinuend->cUsed; i++)
     1165                pResult->pauElements[i] = rtBigNumElementSubWithBorrow(pMinuend->pauElements[i],
     1166                                                                       rtBigNumGetElement(pSubtrahend, i),
     1167                                                                       &fBorrow);
     1168            Assert(fBorrow == 0);
     1169#endif
     1170
     1171            /*
     1172             * Trim the result.
     1173             */
     1174            rtBigNumStripTrailingZeros(pResult);
     1175        }
     1176    }
     1177    /*
     1178     * Special case: Subtrahend is zero.
     1179     */
     1180    else
     1181        rc = rtBigNumMagnitudeCopy(pResult, pMinuend);
    9731182
    9741183    return rc;
     
    9841193 * @a pSubtrahend.
    9851194 *
     1195 * @returns IPRT status code (memory alloc error).
    9861196 * @param   pMinuendResult      What to subtract from and return as result.
    9871197 * @param   pSubtrahend         What to subtract.
    9881198 */
    989 static void rtBigNumMagnitudeSubThis(PRTBIGNUM pMinuendResult, PCRTBIGNUM pSubtrahend)
     1199static int rtBigNumMagnitudeSubThis(PRTBIGNUM pMinuendResult, PCRTBIGNUM pSubtrahend)
    9901200{
    9911201    Assert(!pMinuendResult->fCurScrambled); Assert(!pSubtrahend->fCurScrambled);
     
    9931203    Assert(pMinuendResult->cUsed >= pSubtrahend->cUsed);
    9941204
     1205#ifdef IPRT_BIGINT_WITH_ASM
     1206    /*
     1207     * Use the assembly worker. Requires same sized element arrays, so zero extend them.
     1208     */
     1209    int rc = rtBigNumEnsureExtraZeroElements(pMinuendResult, RTBIGNUM_ZERO_ALIGN(pMinuendResult->cUsed));
     1210    if (RT_SUCCESS(rc))
     1211        rc = rtBigNumEnsureExtraZeroElements((PRTBIGNUM)pSubtrahend, RTBIGNUM_ZERO_ALIGN(pMinuendResult->cUsed));
     1212    if (RT_FAILURE(rc))
     1213        return rc;
     1214    rtBigNumMagnitudeSubThisAssemblyWorker(pMinuendResult->pauElements, pSubtrahend->pauElements, pMinuendResult->cUsed);
     1215#else
    9951216    /*
    9961217     * The primitive way, as usual.
     
    10021223                                                                      &fBorrow);
    10031224    Assert(fBorrow == 0);
     1225#endif
    10041226
    10051227    /*
     
    10071229     */
    10081230    rtBigNumStripTrailingZeros(pMinuendResult);
     1231
     1232    return VINF_SUCCESS;
    10091233}
    10101234
     
    10181242    if (RT_SUCCESS(rc))
    10191243    {
     1244        RTBIGNUM_ASSERT_VALID(pResult);
    10201245        rc = rtBigNumUnscramble((PRTBIGNUM)pAugend);
    10211246        if (RT_SUCCESS(rc))
    10221247        {
     1248            RTBIGNUM_ASSERT_VALID(pAugend);
    10231249            rc = rtBigNumUnscramble((PRTBIGNUM)pAddend);
    10241250            if (RT_SUCCESS(rc))
    10251251            {
     1252                RTBIGNUM_ASSERT_VALID(pAddend);
     1253
    10261254                /*
    10271255                 * Same sign: Add magnitude, keep sign.
     
    10711299    if (RT_SUCCESS(rc))
    10721300    {
     1301        RTBIGNUM_ASSERT_VALID(pResult);
    10731302        if (pMinuend != pSubtrahend)
    10741303        {
     
    10761305            if (RT_SUCCESS(rc))
    10771306            {
     1307                RTBIGNUM_ASSERT_VALID(pMinuend);
    10781308                rc = rtBigNumUnscramble((PRTBIGNUM)pSubtrahend);
    10791309                if (RT_SUCCESS(rc))
    10801310                {
     1311                    RTBIGNUM_ASSERT_VALID(pSubtrahend);
     1312
    10811313                    /*
    10821314                     * Different sign: Add magnitude, keep sign of first.
     
    11171349            /* zero. */
    11181350            pResult->fNegative = 0;
    1119             pResult->cUsed     = 0;
     1351            rtBigNumSetUsed(pResult, 0);
    11201352        }
    11211353        rtBigNumScramble(pResult);
     
    11611393    {
    11621394        pResult->fNegative = 0;
    1163         pResult->cUsed = 0;
     1395        rtBigNumSetUsed(pResult, 0);
    11641396        return VINF_SUCCESS;
    11651397    }
     
    12201452    if (RT_SUCCESS(rc))
    12211453    {
     1454        RTBIGNUM_ASSERT_VALID(pResult);
    12221455        rc = rtBigNumUnscramble((PRTBIGNUM)pMultiplicand);
    12231456        if (RT_SUCCESS(rc))
    12241457        {
     1458            RTBIGNUM_ASSERT_VALID(pMultiplicand);
    12251459            rc = rtBigNumUnscramble((PRTBIGNUM)pMultiplier);
    12261460            if (RT_SUCCESS(rc))
    12271461            {
     1462                RTBIGNUM_ASSERT_VALID(pMultiplier);
     1463
    12281464                /*
    12291465                 * The sign values follow XOR rules:
     
    12471483
    12481484/**
    1249  * Copies the magnitude of on number (@a pSrc) to another (@a pBigNum).
    1250  *
    1251  * The variables must be unscrambled.  The sign flag is not considered nor
    1252  * touched.
    1253  *
    1254  * @returns IPRT status code.
    1255  * @param   pDst            The destination number.
    1256  * @param   pSrc            The source number.
    1257  */
    1258 DECLINLINE(int) rtBigNumMagnitudeCopy(PRTBIGNUM pDst, PCRTBIGNUM pSrc)
    1259 {
    1260     int rc = rtBigNumSetUsed(pDst, pSrc->cUsed);
    1261     if (RT_SUCCESS(rc))
    1262         memcpy(pDst->pauElements, pSrc->pauElements, pSrc->cUsed * RTBIGNUM_ELEMENT_SIZE);
    1263     return rc;
    1264 }
    1265 
    1266 
    1267 /**
    12681485 * Clears a bit in the magnitude of @a pBigNum.
    12691486 *
     
    12781495    if (iElement < pBigNum->cUsed)
    12791496    {
     1497        iBit &= RTBIGNUM_ELEMENT_BITS - 1;
    12801498        pBigNum->pauElements[iElement] &= ~RTBIGNUM_ELEMENT_BIT(iBit);
    12811499        if (iElement + 1 == pBigNum->cUsed && !pBigNum->pauElements[iElement])
     
    13001518    if (RT_SUCCESS(rc))
    13011519    {
     1520        iBit &= RTBIGNUM_ELEMENT_BITS - 1;
    13021521        pBigNum->pauElements[iElement] |= RTBIGNUM_ELEMENT_BIT(iBit);
    13031522        return VINF_SUCCESS;
     
    13391558    uint32_t iElement = iBit / RTBIGNUM_ELEMENT_BITS;
    13401559    if (iElement < pBigNum->cUsed)
     1560    {
     1561        iBit &= RTBIGNUM_ELEMENT_BITS - 1;
    13411562        return (pBigNum->pauElements[iElement] >> iBit) & 1;
     1563    }
    13421564    return 0;
    13431565}
     
    13591581    /* Do the shifting. */
    13601582    uint32_t cUsed = pBigNum->cUsed;
     1583#ifdef IPRT_BIGINT_WITH_ASM
     1584    uCarry = rtBigNumMagnitudeShiftLeftOneAssemblyWorker(pBigNum->pauElements, cUsed, uCarry);
     1585#else
    13611586    for (uint32_t i = 0; i < cUsed; i++)
    13621587    {
     
    13651590        uCarry = uTmp >> (RTBIGNUM_ELEMENT_BITS - 1);
    13661591    }
     1592#endif
    13671593
    13681594    /* If we still carry a bit, we need to increase the size. */
     
    13991625     * special case and the initial state of the general case.
    14001626     */
    1401     pQuotient->cUsed = 0;
    1402     pRemainder->cUsed = 0;
     1627    rtBigNumSetUsed(pQuotient, 0);
     1628    rtBigNumSetUsed(pRemainder, 0);
    14031629
    14041630    /*
     
    14471673        {
    14481674            if (iDiff != 0)
    1449                 rtBigNumMagnitudeSubThis(pRemainder, pDivisor);
     1675            {
     1676                rc = rtBigNumMagnitudeSubThis(pRemainder, pDivisor);
     1677                AssertRCBreak(rc);
     1678            }
    14501679            else
    1451                 pRemainder->cUsed = 0;
     1680                rtBigNumSetUsed(pRemainder, 0);
    14521681            rc = rtBigNumMagnitudeSetBit(pQuotient, iBit);
    14531682            AssertRCBreak(rc);
     
    14711700    if (RT_SUCCESS(rc))
    14721701    {
     1702        RTBIGNUM_ASSERT_VALID(pQuotient);
    14731703        rc = rtBigNumUnscramble(pRemainder);
    14741704        if (RT_SUCCESS(rc))
    14751705        {
     1706            RTBIGNUM_ASSERT_VALID(pRemainder);
    14761707            rc = rtBigNumUnscramble((PRTBIGNUM)pDividend);
    14771708            if (RT_SUCCESS(rc))
    14781709            {
     1710                RTBIGNUM_ASSERT_VALID(pDividend);
    14791711                rc = rtBigNumUnscramble((PRTBIGNUM)pDivisor);
    14801712                if (RT_SUCCESS(rc))
    14811713                {
     1714                    RTBIGNUM_ASSERT_VALID(pDivisor);
     1715
    14821716                    /*
    14831717                     * The sign value of the remainder is the same as the dividend.
     
    15311765     * special case and the initial state of the general case.
    15321766     */
    1533     pRemainder->cUsed = 0;
     1767    rtBigNumSetUsed(pRemainder, 0);
    15341768
    15351769    /*
     
    15731807        {
    15741808            if (iDiff != 0)
    1575                 rtBigNumMagnitudeSubThis(pRemainder, pDivisor);
     1809            {
     1810                rc = rtBigNumMagnitudeSubThis(pRemainder, pDivisor);
     1811                AssertRCBreak(rc);
     1812            }
    15761813            else
    1577                 pRemainder->cUsed = 0;
    1578             AssertRCBreak(rc);
     1814                rtBigNumSetUsed(pRemainder, 0);
    15791815        }
    15801816    }
     
    15881824RTDECL(int) RTBigNumModulo(PRTBIGNUM pRemainder, PCRTBIGNUM pDividend, PCRTBIGNUM pDivisor)
    15891825{
    1590      Assert(pRemainder != pDividend); Assert(pRemainder != pDivisor);
     1826    Assert(pRemainder != pDividend); Assert(pRemainder != pDivisor);
    15911827    AssertReturn(pRemainder->fSensitive >= (pDividend->fSensitive | pDivisor->fSensitive), VERR_BIGNUM_SENSITIVE_INPUT);
    15921828
     
    15941830    if (RT_SUCCESS(rc))
    15951831    {
     1832        RTBIGNUM_ASSERT_VALID(pRemainder);
    15961833        rc = rtBigNumUnscramble((PRTBIGNUM)pDividend);
    15971834        if (RT_SUCCESS(rc))
    15981835        {
     1836            RTBIGNUM_ASSERT_VALID(pDividend);
    15991837            rc = rtBigNumUnscramble((PRTBIGNUM)pDivisor);
    16001838            if (RT_SUCCESS(rc))
    16011839            {
     1840                RTBIGNUM_ASSERT_VALID(pDivisor);
     1841
    16021842                /*
    16031843                 * The sign value of the remainder is the same as the dividend.
     
    17181958    if (RT_SUCCESS(rc))
    17191959    {
     1960        RTBIGNUM_ASSERT_VALID(pResult);
    17201961        rc = rtBigNumUnscramble((PRTBIGNUM)pBase);
    17211962        if (RT_SUCCESS(rc))
    17221963        {
     1964            RTBIGNUM_ASSERT_VALID(pBase);
    17231965            rc = rtBigNumUnscramble((PRTBIGNUM)pExponent);
    17241966            if (RT_SUCCESS(rc))
    17251967            {
     1968                RTBIGNUM_ASSERT_VALID(pExponent);
    17261969                if (!pExponent->fNegative)
    17271970                {
     
    17712014    if (pModulus->cUsed == 1 && pModulus->pauElements[0] == 1)
    17722015    {
    1773         pResult->cUsed = 0;
     2016        rtBigNumSetUsed(pResult, 0);
    17742017        return VINF_SUCCESS;
    17752018    }
     
    18672110    if (RT_SUCCESS(rc))
    18682111    {
     2112        RTBIGNUM_ASSERT_VALID(pResult);
    18692113        rc = rtBigNumUnscramble((PRTBIGNUM)pBase);
    18702114        if (RT_SUCCESS(rc))
    18712115        {
     2116            RTBIGNUM_ASSERT_VALID(pBase);
    18722117            rc = rtBigNumUnscramble((PRTBIGNUM)pExponent);
    18732118            if (RT_SUCCESS(rc))
    18742119            {
     2120                RTBIGNUM_ASSERT_VALID(pExponent);
    18752121                rc = rtBigNumUnscramble((PRTBIGNUM)pModulus);
    18762122                if (RT_SUCCESS(rc))
    18772123                {
     2124                    RTBIGNUM_ASSERT_VALID(pModulus);
    18782125                    if (!pExponent->fNegative)
    18792126                    {
Note: See TracChangeset for help on using the changeset viewer.

© 2025 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette