1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111
|
/* _PDCLIB_bigint_sub( _PDCLIB_bigint_t *, _PDCLIB_bigint_t const * )
This file is part of the Public Domain C Library (PDCLib).
Permission is granted to use, modify, and / or redistribute at will.
*/
#ifndef REGTEST
#include "pdclib/_PDCLIB_internal.h"
#include <assert.h>
#include <stdint.h>
_PDCLIB_bigint_t * _PDCLIB_bigint_sub( _PDCLIB_bigint_t * _PDCLIB_restrict lhs, _PDCLIB_bigint_t const * _PDCLIB_restrict rhs )
{
int i;
unsigned carry = 0;
assert( _PDCLIB_bigint_cmp( lhs, rhs ) >= 0 );
for ( i = 0; i < rhs->size; ++i )
{
int newcarry;
if ( ( newcarry = ( lhs->data[i] < rhs->data[i] ) || ( carry && ( lhs->data[i] == rhs->data[i] ) ) ) )
{
lhs->data[i] += ( UINT32_C( 0xFFFFFFFF ) - rhs->data[i] ) + ( 1 - carry );
}
else
{
lhs->data[i] -= ( rhs->data[i] + carry );
}
carry = newcarry;
}
for ( ; carry; ++i )
{
if ( lhs->data[i] > 0 )
{
--lhs->data[i];
carry = 0;
}
else
{
lhs->data[i] = UINT32_C( 0xFFFFFFFF );
}
}
while ( lhs->size > 0 && lhs->data[ lhs->size - 1 ] == 0 )
{
--lhs->size;
}
return lhs;
}
#endif
#ifdef TEST
#include "_PDCLIB_test.h"
#include <stdint.h>
int main( void )
{
#ifndef REGTEST
_PDCLIB_bigint_t lhs, rhs, res;
uint_least32_t NUL = 0;
uint_least32_t SML = UINT32_C( 0x7FFFFFFF );
uint_least32_t MID = UINT32_C( 0x80000000 );
uint_least32_t LRG = UINT32_C( 0x80000001 );
uint_least32_t MAX = UINT32_C( 0xFFFFFFFF );
/* Building a large number substraction that covers all kinds of
cases. From rightmost digit to left:
*/
/* carry 0, lhs '9', rhs '5', newcarry 0, result '4' */
lhs.data[0] = MAX; rhs.data[0] = MID; res.data[0] = SML;
/* carry 0, lhs '0', rhs '0', newcarry 0, result '0' */
lhs.data[1] = NUL; rhs.data[1] = NUL; res.data[1] = NUL;
/* carry 0, lhs '0', rhs '6', newcarry 1, result '4' */
lhs.data[2] = NUL; rhs.data[2] = LRG; res.data[2] = SML;
/* carry 1, lhs '0', rhs '0', newcarry 1, result '9' */
lhs.data[3] = NUL; rhs.data[3] = NUL; res.data[3] = MAX;
/* carry 1, lhs '0', rhs '9', newcarry 1, result '0' */
lhs.data[4] = NUL; rhs.data[4] = MAX; res.data[4] = NUL;
/* carry 1, lhs '0', rhs '5', newcarry 1, result '4' */
lhs.data[5] = NUL; rhs.data[5] = MID; res.data[5] = SML;
/* carry 1, lhs '4', rhs '9', newcarry 1, result '4' */
lhs.data[6] = SML; rhs.data[6] = MAX; res.data[6] = SML;
/* carry 1, lhs '5', rhs '5', newcarry 1, result '9' */
lhs.data[7] = MID; rhs.data[7] = MID; res.data[7] = MAX;
/* carry 1, lhs '6', rhs '5', newcarry 0, result '0' */
lhs.data[8] = LRG; rhs.data[8] = MID; res.data[8] = NUL;
/* carry 0, lhs '5', rhs '9', newcarry 1, result '6' */
lhs.data[9] = MID; rhs.data[9] = MAX; res.data[9] = LRG;
/* carry 1, lhs '5', rhs '0', newcarry 0, result '4' */
lhs.data[10] = MID; rhs.data[10] = NUL; res.data[10] = SML;
/* carry 0, lhs '5', rhs '6', newcarry 1, result '9' */
lhs.data[11] = MID; rhs.data[11] = LRG; res.data[11] = MAX;
/* carry 1, lhs '6', rhs ---, newcarry 0, result '5' */
lhs.data[12] = LRG; res.data[12] = MID;
lhs.size = 13; rhs.size = 12; res.size = 13;
TESTCASE( _PDCLIB_bigint_cmp( _PDCLIB_bigint_sub( &lhs, &rhs ), &res ) == 0 );
#endif
return TEST_RESULTS;
}
#endif
|