#include "mcc_fpn.h"
#include <ctype.h>
mcc_fpn_t mcc_fpn_set_inf( mcc_fpn_t mcc );
mcc_fpn_t mcc_fpn_make( mcc_fpn_t tmp, mcc_fpn_t ret );
mcc_fpn_t mcc_fpn_read(
char *txt,
mcc_fpn_t *gcc,
mcc_fpn_t tmp,
mcc_fpn_t ret );
mcc_big_t mcc_big_set_inf( mcc_big_t mcc );
mcc_big_t mcc_big_make( mcc_big_t tmp, mcc_big_t ret );
mcc_big_t mcc_big_read(
char *txt,
mcc_big_t *gcc,
mcc_big_t tmp,
mcc_big_t ret );
void printb( char const *pfx, void * addr, size_t bits, char const *sfx ) {
mcc_bit_t b = {0};
b.seg = addr;
b.bit = 1;
b = mcc__bit_op_add( b, bits );
printf("%s",pfx);
while ( b.b ) {
b = mcc_bit_op_dec(b);
putchar( '0' + !!(*(b.seg) & b.bit) );
}
printf("%s",sfx);
}
typedef struct waswasnot {
uint was;
uint not;
} waswasnot_t;
waswasnot_t waswasnot_add( waswasnot_t num, waswasnot_t val ) {
num.was += val.was;
num.not += val.not;
return num;
}
void waswasnot_put( char *pfx, char *txt, waswasnot_t num, char *sfx ) {
printf("%s was %s %u, ", pfx, txt, num.was );
printf("%s not %s %u%s", pfx, txt, num.not, sfx );
}
typedef struct fpn_stats {
uint count;
waswasnot_t eql;
waswasnot_t mul;
waswasnot_t nil;
waswasnot_t inc;
waswasnot_t shl;
waswasnot_t inf;
} fpn_stats_t;
void fpn_stats_put( char *txt, char *pfx, fpn_stats_t stats ) {
float right = stats.eql.was, total = stats.count;
if ( !txt ) txt = "";
if ( !pfx ) pfx = "";
printf("%s() %s count %u %s\n", __func__, pfx, stats.count, txt );
waswasnot_put( pfx, "eql", stats.eql, "\n" );
waswasnot_put( pfx, "nil", stats.nil, "\n" );
waswasnot_put( pfx, "inc", stats.inc, "\n" );
waswasnot_put( pfx, "shl", stats.shl, "\n" );
waswasnot_put( pfx, "mul", stats.mul, "\n" );
waswasnot_put( pfx, "inf", stats.inf, "\n" );
printf( "%f%% Correct\n", (right / total) * 100.0 );
}
void details(
fpn_stats_t *dst, char const *txt,
mcc_fpn_t gcc, mcc_fpn_t mcc ) {
FPN_UNION _gcc = {0}, _mcc = {0};
ullong g = gcc.raw, m = mcc.raw;
fpn_stats_t stats = {0};
mcc_fpn_limits_t limits = mcc.limits;
stats.eql.was = (gcc.raw == mcc.raw);
stats.eql.not = !(stats.eql.was);
if ( stats.eql.was ) goto details_add;
_gcc.raw = gcc.raw;
_mcc.raw = mcc.raw;
_gcc.sig = 0;
_mcc.sig = 0;
stats.nil.was = (_gcc.raw && !(_mcc.raw));
stats.nil.not = (!(_gcc.raw) && _mcc.raw);
if ( stats.nil.was || stats.nil.not ) goto details_add;
stats.inf.was = (_gcc.exp != mcc.inf && _mcc.exp >= mcc.inf);
stats.inf.not = (_gcc.exp >= mcc.inf && _mcc.exp != mcc.inf);
if ( stats.inf.was || stats.inf.not ) goto details_add;
stats.inc.was = (gcc.raw == (mcc.raw - 1));
stats.inc.not = (gcc.raw == (mcc.raw + 1));
if ( stats.inc.was || stats.inc.not ) goto details_add;
stats.mul.was = (_gcc.exp == (_mcc.exp - 1));
stats.mul.not = (_gcc.exp == (_mcc.exp + 1));
if ( stats.mul.was || stats.mul.not ) goto details_add;
stats.shl.was = ((_gcc.man << 1) == _mcc.man);
stats.shl.not = (!(stats.shl.was) && _gcc.man == (_mcc.man << 1));
if ( stats.shl.was || stats.shl.not ) goto details_add;
_gcc.raw = gcc.raw;
_mcc.raw = mcc.raw;
printf( "given %s\n", txt );
printf( "expect " FPN_PRIe ", " FPN_PRIf "\n", _gcc.fpn, _gcc.fpn );
printf( "result " FPN_PRIe ", " FPN_PRIf "\n", _mcc.fpn, _mcc.fpn );
printb( "gcc = ", &(gcc.raw), bitsof(gcc.raw), "\n" );
printb( "mcc = ", &(mcc.raw), bitsof(mcc.raw), "\n" );
printb( "gcc mantissa = ", &g, limits.man_bits, "\n" );
printb( "mcc mantissa = ", &m, limits.man_bits, "\n" );
g >>= limits.man_bits;
m >>= limits.man_bits;
printb( "gcc exponent = ", &g, limits.exp_bits, "\n" );
printb( "mcc exponent = ", &m, limits.exp_bits, "\n" );
g >>= limits.exp_bits;
m >>= limits.exp_bits;
printb( "gcc negative = ", &g, 1, "\n" );
printb( "mcc negative = ", &m, 1, "\n" );
printf( "tmp.base = %llu\n", (ullong)mcc.base );
printf( "tmp.neg = %llu\n", (ullong)(mcc.neg) );
printf( "tmp.num = %llu\n", (ullong)(mcc.num) );
printf( "tmp.fpn = %llu\n", (ullong)(mcc.fpn) );
printf( "tmp.one = %llu\n", (ullong)(mcc.one) );
printf( "tmp.tmp = %llu\n", (ullong)(mcc.tmp) );
printf( "tmp.pos = %ld\n", mcc.pos );
printf( "tmp.exp = %ld\n", mcc.exp );
printf( "gcc.pos = %ld\n", gcc.pos );
printf( "gcc.exp = %ld\n", gcc.exp );
details_add:
dst->count++;
dst->eql = waswasnot_add( dst->eql, stats.eql );
dst->nil = waswasnot_add( dst->nil, stats.nil );
dst->inc = waswasnot_add( dst->inc, stats.inc );
dst->shl = waswasnot_add( dst->shl, stats.shl );
dst->mul = waswasnot_add( dst->mul, stats.mul );
dst->inf = waswasnot_add( dst->inf, stats.inf );
}
int main() {
mcc_fpn_t gcc = {0}, mcc = {0}, tmp;
mcc_fpn_limits_t limits = {0};
char txt[bitsof(double)] = {0};
int i, j, k, c = 36, e = c, f = c;
fpn_stats_t stats = {0};
mcc.one = 1;
mcc.base = 10;
limits.exp_bias = FPN_MAX_EXP;
limits.exp_bits = FPN_EXP_BIT;
limits.max_exp_digits = FPN_MAX_10_EXP;
limits.min_exp_digits = FPN_MIN_10_EXP;
limits.max_exp = FPN_MAX_EXP;
limits.min_exp = FPN_MIN_EXP;
limits.man_bits = FPN_MAN_BIT;
mcc.limits = limits;
mcc.rounds = FLT_ROUNDS;
mcc.epsilon = FLT_EPSILON;
mcc = mcc_fpn_set_inf( mcc );
printf("Numbers limited to: %d.%de+/-%d\n", c, f, e );
printf( "mcc.rounds = %ld\n", mcc.rounds );
printf( "mcc.epsilon = %ld\n", mcc.epsilon );
#if 0
printf( "limits.exp_bias = %ld\n", limits.exp_bias );
printf( "limits.exp_bits = %ld\n", limits.exp_bits );
printf( "limits.max_exp_digits = %ld\n", limits.max_exp_digits );
printf( "limits.min_exp_digits = %ld\n", limits.min_exp_digits );
printf( "limits.max_exp = %ld\n", limits.max_exp );
printf( "limits.min_exp = %ld\n", limits.min_exp );
printf( "limits.man_bits = %ld\n", limits.man_bits );
#endif
for ( i = 0; i <= e; ++i ) {
for ( j = 0; j <= c; ++j ) {
for ( k = 0; k < f; ++k ) {
memset( txt, 0, bitsof(double) );
snprintf( txt, bitsof(double), "%d.%de%d", j, k, i );
tmp = mcc_fpn_read( txt, &gcc, mcc, mcc );
details( &stats, txt, gcc, tmp );
memset( txt, 0, bitsof(double) );
snprintf( txt, bitsof(double), "%d.%de%d", j, k, -i );
tmp = mcc_fpn_read( txt, &gcc, mcc, mcc );
details( &stats, txt, gcc, tmp );
}
}
}
fpn_stats_put( NULL, NULL, stats );
return 0;
}
long mcc_geti( long c, int l, int h ) {
if ( c >= '0' && c <= '9' )
return c - '0';
else if ( c >= 'A' && c <= 'Z' )
return (c - 'A') + h;
else if ( c >= 'a' && c <= 'z' )
return (c - 'a') + l;
return -1;
}
mcc_fpn_t mcc_fpn_set_inf( mcc_fpn_t mcc ) {
mcc.inf = 0;
mcc.inf = ~(mcc.inf);
mcc.inf <<= mcc.limits.exp_bits;
mcc.inf = ~(mcc.inf);
return mcc;
}
mcc_fpn_t mcc_fpn_make( mcc_fpn_t mcc, mcc_fpn_t tmp ) {
mcc_fpn_limits_t limits = mcc.limits;
mcc.raw = 0;
tmp = mcc;
if ( tmp.pos > 0 || !(mcc.num) || !(mcc.one) ) goto mcc_fpn_sig;
if ( !(tmp.num % tmp.one) ) {
tmp.num /= tmp.one;
tmp.one = 1;
tmp.pos = 0;
}
while ( tmp.exp > 0 ) {
if ( tmp.pos == 0 || tmp.one == 1 ) break;
tmp.one /= tmp.base;
tmp.pos++;
tmp.exp--;
}
if ( tmp.exp > limits.max_exp || tmp.exp < limits.min_exp ) {
mcc_fpn_inf:
tmp.raw = mcc.inf;
goto mcc_fpn_exp;
}
for ( ; tmp.exp > 0; tmp.exp-- ) {
tmp.tmp = tmp.num;
tmp.num *= mcc.base;
if ( tmp.num <= tmp.tmp ) goto mcc_fpn_inf;
}
for ( ; tmp.exp < 0; tmp.exp++ ) {
tmp.tmp = tmp.one;
tmp.one *= mcc.base;
if ( tmp.one <= tmp.tmp ) goto mcc_fpn_sig;
}
tmp.fpn = tmp.num % tmp.one;
tmp.num /= tmp.one;
if ( !(tmp.fpn) ) tmp.one = 1;
tmp.pos = 0;
if ( tmp.num ) {
for ( tmp.tmp = tmp.num;
tmp.tmp > 1; tmp.pos++, tmp.tmp >>= 1 );
}
else {
for ( tmp.tmp = tmp.one;
tmp.tmp > tmp.fpn; tmp.pos--, tmp.tmp >>= 1 );
if ( tmp.tmp == tmp.fpn && tmp.pos < -1 ) tmp.pos--;
}
mcc.pos = tmp.pos;
tmp.raw = limits.exp_bias + (tmp.pos - 1);
if ( tmp.raw > mcc.inf ) goto mcc_fpn_inf;
mcc.raw = tmp.num;
if ( tmp.pos > limits.man_bits ) {
tmp.pos -= limits.man_bits;
tmp.fpn = 0;
tmp.fpn = ~(tmp.fpn);
tmp.fpn <<= tmp.pos;
tmp.fpn = ~(tmp.fpn);
tmp.fpn &= tmp.num;
tmp.one <<= tmp.pos;
mcc.raw = tmp.num >> tmp.pos;
tmp.tmp = tmp.one / 2;
if ( tmp.fpn > tmp.tmp ) mcc.raw++;
else if ( tmp.fpn == tmp.tmp ) {
switch ( mcc.rounds ) {
case 1: if ( mcc.raw & 1u ) mcc.raw++; break;
}
}
}
else {
mcc.raw = tmp.num;
tmp.tmp = tmp.fpn;
if ( tmp.pos < -8 ) {
tmp.tmp <<= -(tmp.pos + 8);
mcc.raw <<= -(tmp.pos + 8);
tmp.pos = -8;
}
for ( ; tmp.pos < limits.man_bits; tmp.pos++ ) {
tmp.tmp *= 2;
mcc.raw <<= 1;
if ( tmp.tmp >= tmp.one ) {
mcc.raw |= 1;
tmp.tmp -= tmp.one;
}
}
tmp.tmp *= 2;
if ( tmp.tmp >= tmp.one ) mcc.raw++;
}
tmp.tmp = (bitsof(mcc.raw) - limits.man_bits);
mcc.raw <<= tmp.tmp;
mcc.raw >>= tmp.tmp;
mcc_fpn_exp:
tmp.raw <<= limits.man_bits;
mcc.raw |= tmp.raw;
mcc_fpn_sig:
tmp.neg <<= (limits.man_bits + limits.exp_bits);
mcc.raw |= tmp.neg;
mcc.num = tmp.num;
mcc.one = tmp.one;
mcc.fpn = tmp.fpn;
return mcc;
}
mcc_fpn_t mcc_fpn_read(
char *txt,
mcc_fpn_t *gcc,
mcc_fpn_t tmp,
mcc_fpn_t fpn
) {
char *text, sig;
int c = 0, l = 10, h = 10;
char e = 'e', E = 'E';
FPN_UNION lib = {0};
while ( isspace(*txt) ) ++txt;
text = txt;
switch ( *txt ) {
case '-': tmp.neg = 1;
case '+': ++txt;
}
if ( *txt == '0' ) {
++txt;
switch ( *txt ) {
case 'b': case 'B':
++txt;
tmp.base = 2;
break;
case 'x': case 'X':
++txt;
tmp.base = 16;
break;
}
if ( tmp.base > 36 )
l = 36;
}
while ( *txt ) {
c = mcc_geti( *txt, l, h );
if ( c < 0 || c >= tmp.base ) break;
++txt;
tmp.num *= tmp.base;
tmp.num += c;
}
tmp.pos = 0;
if ( *txt == '.' ) {
++txt;
while ( *txt ) {
c = mcc_geti( *txt, l, h );
if ( c < 0 || c >= tmp.base ) break;
++txt;
tmp.one *= tmp.base;
tmp.num *= tmp.base;
tmp.num += c;
tmp.pos--;
}
}
if ( *txt == e || *txt == E ) {
++txt;
switch ( *txt ) { case '-': case '+': sig = *txt; ++txt; }
while ( *txt ) {
c = mcc_geti( *txt, l, h );
if ( c < 0 || c >= tmp.base ) break;
++txt;
tmp.exp *= tmp.base;
tmp.exp += c;
}
if ( sig == '-' ) tmp.exp = -(tmp.exp);
}
*gcc = tmp;
if ( tmp.base == 10 ) sscanf( text, FPN_SCNe, &(lib.fpn) );
else if ( tmp.base == 16 ) sscanf( text, FPN_SCNa, &(lib.fpn) );
gcc->raw = lib.raw;
fpn = tmp;
return mcc_fpn_make( fpn, tmp );
}
mcc_big_t mcc_big_set_inf( mcc_big_t big ) {
int ret = mcc_int_validate( &(big.inf) );
mcc_fpn_limits_t limits = big.limits;
if ( ret != EXIT_SUCCESS ) {
printf( "Error: %08X, %s\n", ret, strerror(ret) );
}
memset( big.inf.zero.seg, ~0u, big.inf.size );
mcc___int_op_shl( &(big.inf), limits.exp_bits );
mcc__int_op_not( &(big.inf) );
return big;
}
int mcc_big_validiate( mcc_big_t *mcc_big ) {
int ret;
if ( !mcc_big ) return EDESTADDRREQ;
ret = mcc_int_validate( &(mcc_big->base) );
if ( ret != EXIT_SUCCESS ) return ret;
return EXIT_SUCCESS;
}
mcc_big_t mcc_big_make( mcc_big_t mcc, mcc_big_t tmp ) {
int ret = mcc_big_validiate(&mcc), dir = 0;
mcc_uhuge_t _one = 1;
mcc_uint_t one = {0};
mcc_fpn_limits_t limits = mcc.limits;
if ( ret != EXIT_SUCCESS ) {
printf("Error: %08X, %s\n", ret, strerror(ret) );
return mcc;
}
ret = mcc_big_validiate(&tmp);
if ( ret != EXIT_SUCCESS ) {
printf("Error: %08X, %s\n", ret, strerror(ret) );
return mcc;
}
mcc_int_wrap( &one, &_one, sizeof(_one) );
if ( tmp.pos > 0 ||
mcc__int_is_nil(&(mcc.num)) || mcc__int_is_nil(&(mcc.one)) )
goto mcc_big_sig;
switch ( dir ) {
case 1: mcc__int_op_inc( &(mcc.raw) ); break;
case -1: mcc__int_op_dec( &(mcc.raw) ); break;
}
mcc_big_sig:
mcc___int_op_shl( &(tmp.neg), limits.man_bits + limits.exp_bits );
return mcc;
}
mcc_big_t mcc_big_read(
char *txt,
mcc_big_t *gcc,
mcc_big_t tmp,
mcc_big_t big
) {
return big;
}
#include <limits.h>
#include <inttypes.h>
#include "mcc_vint.h"
mcc_bit_t mcc_bit_op_inc( mcc_bit_t num ) {
mcc_int_seg_t max = 0;
max = ~max;
if ( num.b == max ) {
memset( &num, 0, sizeof(num) );
return num;
}
++(num.b);
num.bit <<= 1;
if ( !(num.bit) ) {
num.bit = 1;
++(num.i);
++(num.seg);
}
return num;
}
mcc_bit_t mcc_bit_op_dec( mcc_bit_t num ) {
if ( !num.b ) {
memset(&num,0,sizeof(num));
return num;
}
--(num.b);
num.bit >>= 1;
if ( !(num.bit) ) {
num.bit = MCC__INT_SEG_END_BIT;
--(num.i);
--(num.seg);
}
return num;
}
mcc_bit_t mcc_bit_op_dec_for_bit( mcc_bit_t stop, mcc_bit_t zero ) {
while ( stop.b > zero.b ) {
stop = mcc_bit_op_dec(stop);
if ( *(stop.seg) & stop.bit )
return stop;
}
return stop;
}
#define MCC_BIT_SLOW
mcc_bit_t mcc__bit_op_add( mcc_bit_t num, mcc_int_seg_t bits ) {
#ifdef MCC_BIT_SLOW
while ( bits-- ) {
num = mcc_bit_op_inc(num);
if ( !(num.bit) ) return num;
}
return num;
#else
mcc_int_seg_t i = num.bit;
if ( i == 1u ) goto mcc__bit_op_add_bytes;
while ( bits && i ) {
--bits; i <<= 1u;
num = mcc_bit_op_inc(num);
if ( !(num.bit) ) return num;
}
mcc__bit_op_add_bytes:
if ( !bits ) return num;
i = num.b;
num.b += bits;
if ( num.b < i ) {
memset( &num, 0, sizeof(num) );
return num;
}
i = bits / bitsof(i);
num.i += i;
num.seg += i;
num.bit = 1u << (bits %= bitsof(i));
return num;
#endif
}
mcc_bit_t mcc__bit_op_sub( mcc_bit_t num, mcc_int_seg_t bits ) {
#ifdef MCC_BIT_SLOW
while ( bits-- ) {
num = mcc_bit_op_dec(num);
if ( !(num.bit) ) return num;
}
return num;
#else
mcc_int_seg_t i = num.bit;
if ( i == MCC__INT_SEG_END_BIT ) goto mcc__bit_op_sub_bytes;
while ( bits && i ) {
--bits;
i >>= 1;
num = mcc_bit_op_dec( num );
if ( !(num.bit) ) return num;
}
mcc__bit_op_sub_bytes:
if ( !bits ) return num;
i = num.b;
num.b -= bits;
if ( num.b > i ) {
memset( &num, 0, sizeof(num) );
return num;
}
i = bits / bitsof(i);
num.i -= i;
num.seg -= i;
num.bit >>= (bits % bitsof(i));
return num;
#endif
}
int mcc_bit_op_cmp( mcc_bit_t num, mcc_bit_t val ) {
if ( num.b > val.b ) return 1;
if ( num.b < val.b ) return -1;
return 0;
}
#ifndef INC_BITMATH
int test( mcc_test_t num, char *op, mcc_test_t val );
char *operations[] = {
"==", "!=", "!", ">", ">=", "<", "<=",
"~", "<<", ">>", "|", "&", "^",
"++", "+", "*", "--", "-", "/", "%",
NULL };
typedef time_t mcc_rnd_t;
long mcc__rnd( mcc_rnd_t *ctx, long min, long max ) {
/* With bit unitialised it should be much harder to predict
* if 1 or 0 will be recieved */
mcc_rnd_t bit = 1, seed = time(NULL), mov = 0;
long val;
if ( ctx ) mov = *ctx;
bit <<= mov++;
if ( !bit || bit > seed ) {
bit = 1;
mov = 0;
}
val = (seed & bit) ? 1 : 0;
bit <<= 1;
if ( ctx ) *ctx = mov;
if ( min > max ) min = max;
if ( min != max ) {
seed *= clock();
bit = ~((~0u) << mov);
val = (seed & bit);
if ( val > max ) val = max;
val -= (min >= 0) ? min : -min;
return ( val < min ) ? min : val;
}
return val ? max : min;
}
#define mcc_rnd( ctx ) mcc__rnd( ctx, LONG_MIN, LONG_MAX )
int main() {
mcc_test_t i, j;
mcc_rnd_t ctx;
for ( j = 0; j < 10; ++j ) {
for ( i = 0; operations[i]; ++i ) {
test( mcc_rnd(&ctx), operations[i], mcc_rnd(&ctx) );
}
}
return 0;
}
#endif
int mcc_int_validate( mcc__int_t const * const num ) {
if ( !num || !(num->zero.seg) || !(num->stop.seg) )
return EADDRNOTAVAIL;
if ( mcc_bit_op_cmp( num->zero, num->stop ) > 0 ) return ERANGE;
return EXIT_SUCCESS;
}
int mcc_int_validate2( mcc__int_t const * const num, mcc__int_t const * const val ) {
int ret = mcc_int_validate( num );
switch ( ret ) {
case EXIT_SUCCESS: break;
case EADDRNOTAVAIL: return EDESTADDRREQ;
default: return ret;
}
return mcc_int_validate( val );
}
int mcc_int_validate3( mcc__int_t const * const num, mcc__int_t const * const val, mcc__int_t const * const var ) {
int ret = mcc_int_validate2( num, val );
if ( ret != EXIT_SUCCESS ) return ret;
ret = mcc_int_validate(var);
if ( ret != EXIT_SUCCESS )
return (ret == EADDRNOTAVAIL) ? EDESTADDRREQ : ret;
if ( var->size < num->size ) return ERANGE;
return EXIT_SUCCESS;
}
void mcc_int_print( mcc__int_t num, mcc_int_seg_t min ) {
int ret = mcc_int_validate(&num);
mcc_int_seg_t nb;
if ( ret != EXIT_SUCCESS ) return;
nb = num.stop.b - num.zero.b;
while ( min-- > nb ) putchar('0');
while ( nb-- ) {
num.stop = mcc_bit_op_dec(num.stop);
putchar('0' + !!(*(num.stop.seg) & num.stop.bit) );
}
}
int mcc_int_wrap( mcc__int_t *var, void *addr, size_t size ) {
if ( !var ) return EDESTADDRREQ;
if ( !addr ) return EADDRNOTAVAIL;
if ( !size ) return ERANGE;
(void)memset( var, 0, sizeof(mcc__int_t) );
var->size = size;
var->zero.seg = addr;
var->zero.bit = 1;
var->stop = mcc__bit_op_add( var->zero, size * CHAR_BIT );
return EXIT_SUCCESS;
}
int mcc_int_size( mcc__int_t *dst, size_t size ) {
mcc_int_seg_t *mem;
size_t nodes;
if ( !size ) {
if ( dst->zero.seg ) free( dst->zero.seg );
memset( dst, 0, sizeof(mcc_int_seg_t) );
return EXIT_SUCCESS;
}
nodes = size / sizeof(mcc_int_seg_t);
if ( size % sizeof(mcc_int_seg_t) ) ++nodes;
size = nodes * sizeof(mcc_int_seg_t);
if ( !(dst->zero.seg) ) mem = malloc( size );
else mem = realloc( dst->zero.seg, size );
if ( !mem ) ENOMEM;
(void)memset( &(dst->zero), 0, sizeof(mcc_bit_t) );
dst->zero.seg = mem;
dst->zero.bit = 1;
dst->size = size;
dst->stop = mcc__bit_op_add( dst->zero, size * CHAR_BIT );
return EXIT_SUCCESS;
}
int mcc_int_size_and_fill( mcc__int_t *dst, void const *src, size_t size ) {
int ret = mcc_int_size( dst, size );
if ( ret != EXIT_SUCCESS ) return ret;
(void)memset( dst->zero.seg, 0, dst->size );
(void)memcpy( dst->zero.seg, src, size );
return EXIT_SUCCESS;
}
int mcc__int_op_cmp( mcc__int_t const * const num, mcc__int_t const * const val ) {
mcc_bit_t n = {0}, v = {0};
mcc_int_seg_t nb = 0, vb = 0;
int nn0 = 0, vn0 = 0;
if ( mcc_int_validate(num) == EXIT_SUCCESS ) {
n = mcc_bit_op_dec_for_bit(num->stop, num->zero);
nn0 = (*(n.seg) & n.bit) ? 1 : 0;
nb = n.b - num->zero.b;
}
if ( mcc_int_validate(val) == EXIT_SUCCESS ) {
v = mcc_bit_op_dec_for_bit(val->stop, val->zero);
vn0 = (*(v.seg) & v.bit) ? 1 : 0;
vb = v.b - val->zero.b;
}
if ( !(n.bit) ) return -vn0;
if ( !(v.bit) ) return nn0;
if ( nb != vb ) return (nb > vb) ? 1 : -1;
while ( nb ) {
if ( nb ) {
n = mcc_bit_op_dec_for_bit( n, num->zero );
nb = n.b - num->zero.b;
}
if ( vb ) {
v = mcc_bit_op_dec_for_bit( v, val->zero );
vb = v.b - val->zero.b;
}
if ( nb != vb ) return ( nb > vb ) ? 1 : -1;
}
nb = (*(n.seg) & n.bit) ? 1 : 0;
vb = (*(v.seg) & v.bit) ? 1 : 0;
if ( nb != vb ) return (nb > vb) ? 1 : -1;
return 0;
}
int biclamp1( mcc__int_t *num ) {
int ret = mcc_int_validate(num);
mcc_bit_t one, pos;
if ( ret != EXIT_SUCCESS ) return ret;
one = mcc_bit_op_dec(pos = num->stop);
while ( pos.i == one.i ) {
if ( !(*(pos.seg) & pos.bit) )
*(pos.seg) |= pos.bit;
}
return EXIT_SUCCESS;
}
int biclamp0( mcc__int_t *num ) {
int ret = mcc_int_validate(num);
mcc_bit_t one, pos;
if ( ret != EXIT_SUCCESS ) return ret;
one = mcc_bit_op_dec(pos = num->stop);
while ( pos.i == one.i ) {
if ( *(pos.seg) & pos.bit )
*(pos.seg) ^= pos.bit;
}
return EXIT_SUCCESS;
}
int mcc__int_op_not( mcc__int_t *num ) {
int ret = mcc_int_validate( num );
mcc_bit_t n;
if ( ret != EXIT_SUCCESS ) return ret;
n = num->zero;
while ( n.b < num->stop.b ) {
*(n.seg) ^= n.bit;
n = mcc_bit_op_inc(n);
}
return EXIT_SUCCESS;
}
int mcc__int_op_aor( mcc__int_t *num, mcc__int_t const * const val ) {
int ret = mcc_int_validate2( num, val );
mcc_bit_t n, v, e;
if ( ret != EXIT_SUCCESS ) return ret;
n = num->zero;
v = val->zero;
e = (mcc_bit_op_cmp(num->stop, val->stop) < 0) ? num->stop : val->stop;
while ( n.b < e.b && v.b < e.b ) {
if ( *(v.seg) & v.bit )
*(n.seg) |= n.bit;
n = mcc_bit_op_inc(n);
v = mcc_bit_op_inc(v);
}
return EXIT_SUCCESS;
}
int mcc__int_op_xor( mcc__int_t *num, mcc__int_t const * const val ) {
int ret = mcc_int_validate2( num, val );
mcc_bit_t n, v, e;
if ( ret != EXIT_SUCCESS ) return ret;
n = num->zero;
v = val->zero;
e = (mcc_bit_op_cmp(num->stop, val->stop) < 0) ? num->stop : val->stop;
while ( n.b < e.b && v.b < e.b ) {
if ( *(v.seg) & v.bit )
*(n.seg) ^= n.bit;
n = mcc_bit_op_inc(n);
v = mcc_bit_op_inc(v);
}
return EXIT_SUCCESS;
}
int mcc__int_op_and( mcc__int_t *num, mcc__int_t const * const val ) {
int ret = mcc_int_validate2( num, val );
mcc_bit_t n, v, e;
if ( ret != EXIT_SUCCESS ) return ret;
n = num->zero;
v = val->zero;
e = (mcc_bit_op_cmp(num->stop, val->stop) < 0) ? num->stop : val->stop;
while ( n.b < e.b && v.b < e.b ) {
if ( !(*(v.seg) & v.bit) && *(n.seg) & n.bit )
*(n.seg) ^= n.bit;
n = mcc_bit_op_inc(n);
v = mcc_bit_op_inc(v);
}
while ( n.b < num->stop.b ) {
if ( *(n.seg) & n.bit )
*(n.seg) ^= n.bit;
n = mcc_bit_op_inc(n);
}
return EXIT_SUCCESS;
}
int mcc___int_op_shl( mcc__int_t *num, mcc_int_seg_t bits ) {
int ret = mcc_int_validate( num );
mcc_bit_t n, v;
mcc_int_seg_t max_bits;
if ( ret != EXIT_SUCCESS ) return ret;
max_bits = (num->stop.b - num->zero.b);
if ( bits >= max_bits )
bits %= max_bits;
if ( !bits ) return EXIT_SUCCESS;
n = num->stop;
v = mcc__bit_op_sub( n, bits );
while ( v.b > num->zero.b ) {
n = mcc_bit_op_dec(n);
v = mcc_bit_op_dec(v);
if ( *(v.seg) & v.bit )
*(n.seg) |= n.bit;
else if ( *(n.seg) & n.bit )
*(n.seg) ^= n.bit;
}
while ( n.b > num->zero.b ) {
n = mcc_bit_op_dec(n);
if ( *(n.seg) & n.bit ) {
*(n.seg) ^= n.bit;
ret = EOVERFLOW;
}
}
return ret;
}
int mcc___int_op_shr( mcc__int_t *num, mcc_int_seg_t bits ) {
int ret = mcc_int_validate( num );
mcc_bit_t n, v;
mcc_int_seg_t max_bits;
if ( ret != EXIT_SUCCESS ) return ret;
max_bits = (num->stop.b - num->zero.b);
if ( bits >= max_bits )
bits %= max_bits;
if ( !bits ) return EXIT_SUCCESS;
n = num->zero;
v = mcc__bit_op_add( n, bits );
while ( v.b < num->stop.b ) {
if ( *(v.seg) & v.bit )
*(n.seg) |= n.bit;
else if ( *(n.seg) & n.bit )
*(n.seg) ^= n.bit;
n = mcc_bit_op_inc(n);
v = mcc_bit_op_inc(v);
}
while ( n.b < num->stop.b ) {
if ( *(n.seg) & n.bit ) {
ret = EOVERFLOW;
*(n.seg) ^= n.bit;
}
n = mcc_bit_op_inc(n);
}
return ret;
}
int mcc__int_op_inc( mcc__int_t *num ) {
mcc_bit_t n;
_Bool c = 1;
int ret = mcc_int_validate( num );
if ( ret != EXIT_SUCCESS ) return ret;
n = num->zero;
for ( ; n.b < num->stop.b; n = mcc_bit_op_inc(n) ) {
*(n.seg) ^= n.bit;
if ( *(n.seg) & n.bit ) {
c = 0;
break;
}
}
return c ? EOVERFLOW : EXIT_SUCCESS;
}
int mcc__int_op_add( mcc__int_t *num, mcc__int_t const * const val ) {
mcc_bit_t n, v, stop;
mcc_int_seg_t b = 0, bits, nb, vb;
_Bool c = 0;
int ret = mcc_int_validate2( num, val );
if ( ret != EXIT_SUCCESS ) return ret;
n = num->zero;
v = val->zero;
nb = num->stop.b - num->zero.b;
vb = val->stop.b - val->zero.b;
bits = (nb < vb) ? nb : vb;
stop = (mcc_bit_op_cmp(num->stop,val->stop) < 0) ? num->stop : val->stop;
for ( ; b < bits; ++b ) {
if ( c ) {
*(n.seg) ^= n.bit;
if ( *(n.seg) & n.bit )
c = 0;
}
if ( *(v.seg) & v.bit ) {
*(n.seg) ^= n.bit;
if ( !(*(n.seg) & n.bit) )
c = 1;
}
n = mcc_bit_op_inc(n);
v = mcc_bit_op_inc(v);
}
if ( c ) {
for ( ; n.b < stop.b; n = mcc_bit_op_inc(n) ) {
*(n.seg) ^= n.bit;
if ( *(n.seg) & n.bit ) {
c = 0;
break;
}
}
}
return c ? EOVERFLOW : EXIT_SUCCESS;
}
int add_uint( mcc__int_t *num, mcc__int_t *val ) {
int ret = mcc__int_op_add( num, val );
if ( ret == EOVERFLOW ) {
memset( num->zero.seg, -1, num->size );
ret = biclamp0( num );
}
return ret;
}
int add_int( mcc__int_t *num, mcc__int_t *val ) {
int ret = mcc_int_validate2(num,val);
mcc__int_t tmp;
if ( ret != EXIT_SUCCESS ) return ret;
tmp = *num;
tmp.stop = mcc_bit_op_dec(tmp.stop);
ret = mcc__int_op_add( &tmp, val );
if ( ret == EOVERFLOW ) {
memset( num->zero.seg, -1, num->size );
ret = biclamp0( &tmp );
}
return ret;
}
int mcc__int_op_dec( mcc__int_t *num ) {
mcc_bit_t n;
_Bool c = 1;
int ret = mcc_int_validate( num );
if ( ret != EXIT_SUCCESS ) return ret;
n = num->zero;
for ( ; n.b < num->stop.b; n = mcc_bit_op_inc(n) ) {
*(n.seg) ^= n.bit;
if ( !(*(n.seg) & n.bit) ) {
c = 0;
break;
}
}
return c ? EOVERFLOW : EXIT_SUCCESS;
}
int mcc__int_op_sub( mcc__int_t *num, mcc__int_t const * const val ) {
mcc_bit_t n, v, s;
_Bool c = 0;
mcc_int_seg_t b = 0, bits = 0, nb, vb;
int ret = mcc_int_validate2( num, val );
if ( ret != EXIT_SUCCESS ) return ret;
n = num->zero;
v = val->zero;
s = val->stop;
//s = mcc_bit_op_inc(mcc_bit_op_dec_for_bit(s, val->zero));
nb = num->stop.b - num->zero.b;
vb = s.b - val->zero.b;
bits = (nb < vb) ? nb : vb;
for ( ; b < bits; ++b, n = mcc_bit_op_inc(n), v = mcc_bit_op_inc(v) ) {
if ( c ) {
if ( *(n.seg) & n.bit )
c = 0;
*(n.seg) ^= n.bit;
}
if ( *(v.seg) & v.bit ) {
*(n.seg) ^= n.bit;
if ( *(n.seg) & n.bit )
c = 1;
}
}
if ( c ) {
for ( ; b < nb; ++b, n = mcc_bit_op_inc(n) ) {
*(n.seg) ^= n.bit;
if ( !(*(n.seg) & n.bit ) ) {
c = 0;
break;
}
}
}
return c ? EOVERFLOW : EXIT_SUCCESS;
}
int mcc___int_op_mul( mcc__int_t *num, mcc__int_t const * const val, mcc__int_t *tmp ) {
int ret = mcc_int_validate3( num, val, tmp );
mcc_bit_t v, s;
mcc_int_seg_t bits = 0;
if ( ret != EXIT_SUCCESS ) return ret;
s = mcc_bit_op_inc(mcc_bit_op_dec_for_bit( val->stop, val->zero ));
memset( tmp->zero.seg, 0, tmp->size );
memcpy( tmp->zero.seg, num->zero.seg, num->size );
memset( num->zero.seg, 0, num->size );
for ( v = val->zero; v.b < s.b; v = mcc_bit_op_inc(v) ) {
if ( *(v.seg) & v.bit ) {
(void)mcc___int_op_shl( tmp, bits );
if ( mcc__int_op_add( num, tmp ) == EOVERFLOW )
ret = EOVERFLOW;
bits = 0;
}
++bits;
}
return ret;
}
int mcc__int_op_mul( mcc__int_t *num, mcc__int_t const * const val ) {
int ret = mcc_int_validate2( num, val );
mcc__int_t tmp = {0};
if ( ret != EXIT_SUCCESS ) return ret;
ret = mcc_int_size_and_fill( &tmp, num->zero.seg, num->size );
if ( ret != EXIT_SUCCESS ) return ret;
ret = mcc___int_op_mul( num, val, &tmp );
(void)mcc_int_size( &tmp, 0 );
return ret;
}
int mcc___int_op_div( mcc__int_t *num, mcc__int_t const * const val, mcc__int_t *rem ) {
int ret = mcc_int_validate3( num, val, rem );
mcc__int_t seg = {0}, tmp = {0};
mcc_bit_t quo;
if ( ret != EXIT_SUCCESS ) return ret;
(void)memset( rem->zero.seg, 0, rem->size );
(void)memcpy( rem->zero.seg, num->zero.seg, num->size );
(void)memset( num->zero.seg, 0, num->size );
#if 1
if ( mcc__int_is_nil( val ) ) return EXIT_SUCCESS;
#else
if ( mcc__int_is_nil( val ) ) {
assert( !mcc__int_is_nil( val ) );
return EXIT_SUCCESS;
}
#endif
tmp = *val;
tmp.stop = mcc_bit_op_inc(mcc_bit_op_dec_for_bit( tmp.stop, tmp.zero ));
seg = *rem;
seg.zero = seg.stop;
quo = num->stop;
while ( mcc__int_is_gte( rem, &tmp ) ) {
seg.zero = mcc_bit_op_dec(seg.zero);
quo = mcc_bit_op_dec( quo );
if ( mcc__int_is_gte( &seg, &tmp ) ) {
if ( mcc__int_op_sub( &seg, &tmp ) == EOVERFLOW )
ret = EOVERFLOW;
*(quo.seg) |= quo.bit;
}
}
return ret;
}
int mcc__int_op_div( mcc__int_t *num, mcc__int_t const * const val ) {
int ret = mcc_int_validate2( num, val );
mcc__int_t rem = {0};
if ( ret != EXIT_SUCCESS ) return ret;
ret = mcc_int_size( &rem, num->size );
if ( ret != EXIT_SUCCESS ) return ret;
ret = mcc___int_op_div( num, val, &rem );
(void)mcc_int_size( &rem, 0 );
return ret;
}
int mcc__int_op_mod( mcc__int_t *num, mcc__int_t const * const val ) {
int ret = mcc_int_validate2( num, val );
mcc__int_t rem = {0};
if ( ret != EXIT_SUCCESS ) return ret;
ret = mcc_int_size( &rem, num->size );
if ( ret != EXIT_SUCCESS ) return ret;
ret = mcc___int_op_div( num, val, &rem );
(void)memcpy( num->zero.seg, rem.zero.seg, num->size );
(void)mcc_int_size( &rem, 0 );
return ret;
}
int mcc__int_op_shl( mcc__int_t *num, mcc__int_t const * const val ) {
int ret = mcc_int_validate2( num, val );
mcc__int_t tmp = {0}, cpy = {0}, rem = {0};
mcc_int_seg_t move = 0, bits = 0;
if ( ret != EXIT_SUCCESS ) return ret;
bits = num->stop.b - num->zero.b;
ret = mcc_int_wrap( &tmp, &bits, sizeof(bits) );
if ( ret != EXIT_SUCCESS ) return ret;
ret = mcc_int_wrap( &rem, &move, sizeof(move) );
if ( ret != EXIT_SUCCESS ) return ret;
move = *(val->zero.seg);
if ( mcc__int_is_gte( val, &tmp ) ) {
ret = mcc_int_size_and_fill( &cpy, val->zero.seg, val->size );
if ( ret != EXIT_SUCCESS ) return ret;
mcc___int_op_shl( &cpy, bits );
mcc___int_op_shr( &cpy, bits );
mcc_int_size( &cpy, 0 );
if ( ret != EXIT_SUCCESS ) return ret;
}
return mcc___int_op_shl(num, move );
}
int mcc__int_op_shr( mcc__int_t *num, mcc__int_t const * const val ) {
int ret = mcc_int_validate2( num, val );
mcc__int_t tmp = {0}, cpy = {0}, rem = {0};
mcc_int_seg_t move = 0, bits = 0;
if ( ret != EXIT_SUCCESS ) return ret;
bits = num->stop.b - num->zero.b;
ret = mcc_int_wrap( &tmp, &bits, sizeof(bits) );
if ( ret != EXIT_SUCCESS ) return ret;
ret = mcc_int_wrap( &rem, &move, sizeof(move) );
if ( ret != EXIT_SUCCESS ) return ret;
move = *(val->zero.seg);
if ( mcc__int_is_gte( val, &tmp ) ) {
ret = mcc_int_size_and_fill( &cpy, val->zero.seg, val->size );
if ( ret != EXIT_SUCCESS ) return ret;
mcc___int_op_shl( &cpy, bits );
mcc___int_op_shr( &cpy, bits );
mcc_int_size( &cpy, 0 );
if ( ret != EXIT_SUCCESS ) return ret;
}
return mcc___int_op_shr(num, move );
}
int mcc__int_to_num( mcc__int_t *dst, uintmax_t num ) {
int ret = mcc__int_op_xor( dst, dst );
mcc__int_t tmp = {0};
if ( ret != EXIT_SUCCESS ) return ret;
(void)mcc_int_wrap( &tmp, &num, sizeof(num) );
return mcc__int_op_aor( dst, &tmp );
}
#ifndef INC_BITMATH
int test( mcc_test_t num, char *op, mcc_test_t val ) {
int ret = EXIT_FAILURE;
mcc_test_t rem = num, b4 = num;
mcc__int_t _num = {0}, _val = {0}, _rem = {0};
(void)mcc_int_size_and_fill( &_num, &num, sizeof(num) );
(void)mcc_int_size_and_fill( &_val, &val, sizeof(num) );
(void)mcc_int_size_and_fill( &_rem, &num, sizeof(num) );
switch ( *op ) {
case 0: ret = EILSEQ; goto fail;
case '~': num = ~num; mcc__int_op_not( &_num ); goto done;
case '|': num |= val; mcc__int_op_aor( &_num, &_val ); goto done;
case '^': num ^= val; mcc__int_op_xor( &_num, &_val ); goto done;
case '&': num &= val; mcc__int_op_and( &_num, &_val ); goto done;
case '+':
if ( op[1] == '+' )
{ num++; mcc__int_op_inc( &_num ); }
else
{ num += val; mcc__int_op_add( &_num, &_val ); }
goto done;
case '*': num *= val; mcc__int_op_mul( &_num, &_val ); goto done;
case '-':
if ( op[1] == '+' )
{ num--; mcc__int_op_dec( &_num ); }
else
{ num -= val; mcc__int_op_sub( &_num, &_val ); }
goto done;
case '/':
if ( val ) { rem %= val; num /= val; }
else { rem = num; num = 0; }
mcc___int_op_div( &_num, &_val, &_rem );
goto done;
case '%':
if ( val ) { rem %= val; num = rem; }
else { rem = num; }
mcc___int_op_div( &_num, &_val, &_rem );
memcpy( _num.zero.seg, _rem.zero.seg, _num.size );
goto done;
case '=':
if ( op[1] != '=' ) goto fail;
num = (num == val);
mcc__int_to_num( &_num, mcc__int_is_eql( &_num, &_val ) );
goto done;
case '!':
if ( op[1] == '\0' ) {
num = !num;
mcc__int_to_num( &_num, mcc__int_is_nil( &_num ) );
}
else if ( op[1] == '=' ) {
num = (num != val);
mcc__int_to_num( &_num, mcc__int_is_neq( &_num, &_val ) );
}
goto done;
case '>':
if ( op[1] == '>' ) {
num >>= val;
mcc__int_op_shr( &_num, &_val );
}
else if ( op[1] == '=' ) {
num = (num >= val);
mcc__int_to_num( &_num, mcc__int_is_gte( &_num, &_val ) );
}
else {
num = (num > val);
mcc__int_to_num( &_num, mcc__int_is_gth( &_num, &_val ) );
}
goto done;
case '<':
if ( op[1] == '<' ) {
num <<= val;
mcc__int_op_shl( &_num, &_val );
}
else if ( op[1] == '=' ) {
num = (num <= val);
mcc__int_to_num( &_num, mcc__int_is_lte( &_num, &_val ) );
}
else {
num = (num < val);
mcc__int_to_num( &_num, mcc__int_is_lth( &_num, &_val ) );
}
goto done;
}
done:
if ( *((mcc_test_t*)(_num.zero.seg)) == num )
ret = EXIT_SUCCESS;
else
printf( "_num = %08" MCC_TEST_PRI_PFX "X, "
"num = %08" MCC_TEST_PRI_PFX "X, "
"b4 = %08" MCC_TEST_PRI_PFX "X, "
"val = %" MCC_TEST_PRI_PFX "u, "
"_rem = %08" MCC_TEST_PRI_PFX "X, "
"rem = %08" MCC_TEST_PRI_PFX "X "
"op = '%s'\n",
*((mcc_test_t*)(_num.zero.seg)), num, b4, val,
*((mcc_test_t*)(_rem.zero.seg)), rem, op );
fail:
mcc_int_size( &_num, 0 );
mcc_int_size( &_val, 0 );
mcc_int_size( &_rem, 0 );
return ret;
}
#endif
#ifndef INC_MCC_FPN_H
#define INC_MCC_FPN_H
#include <float.h>
#include "mcc_vint.h"
typedef signed char schar;
typedef unsigned char uchar;
typedef unsigned long ulong;
typedef signed long long sllong;
typedef unsigned long long ullong;
#if 1
#define mcc_huge __int128
#define MCC_UHUGE_MAX ((unsigned __int128)-1)
#define MCC_HUGE_MAX ((__int128)(MCC_UHUGE_MAX >> 1))
#define MCC_HUGE_MIN ((__int128)~(MCC_UHUGE_MAX >> 1))
#else
#define mcc_huge long long
#define MCC_UHUGE_MAX ULLONG_MAX
#define MCC_HUGE_MAX LLONG_MAX
#define MCC_HUGE_MIN LLONG_MIN
#endif
typedef signed mcc_huge mcc_huge_t;
typedef unsigned mcc_huge mcc_uhuge_t;
#ifdef HALF_MANT_DIG
#define HALF_PRIa "%ha"
#define HALF_PRIf "%hf"
#define HALF_PRIe "%he"
#define HALF_SCNa "%ha"
#define HALF_SCNf "%hf"
#define HALF_SCNe "%he"
#define HALF_MAN_BIT (HALF_MANT_DIG - 1)
#define HALF_EXP_BIT (bitsof(half) - HALF_MANT_DIG)
#endif
#define FLT_PRIa "%a"
#define FLT_PRIf "%f"
#define FLT_PRIe "%e"
#define FLT_SCNa "%a"
#define FLT_SCNf "%f"
#define FLT_SCNe "%e"
#define FLT_MAN_BIT (FLT_MANT_DIG - 1)
#define FLT_EXP_BIT (bitsof(float) - FLT_MANT_DIG)
typedef union FLT_UNION
{
float fpn;
mcc_uhuge_t raw;
struct
{
mcc_uhuge_t man:FLT_MAN_BIT;
mcc_uhuge_t exp:FLT_EXP_BIT;
mcc_uhuge_t sig:1;
};
} FLT_UNION;
#define DBL_PRIa "%la"
#define DBL_PRIf "%lf"
#define DBL_PRIe "%le"
#define DBL_SCNa "%la"
#define DBL_SCNf "%lf"
#define DBL_SCNe "%le"
#define DBL_MAN_BIT (DBL_MANT_DIG - 1)
#define DBL_EXP_BIT (bitsof(double) - DBL_MANT_DIG)
typedef union DBL_UNION
{
double fpn;
mcc_uhuge_t raw;
struct
{
mcc_uhuge_t man:DBL_MAN_BIT;
mcc_uhuge_t exp:DBL_EXP_BIT;
mcc_uhuge_t sig:1;
};
} DBL_UNION;
#define LDBL_PRIa "%lla"
#define LDBL_PRIf "%llf"
#define LDBL_PRIe "%lle"
#define LDBL_SCNa "%lla"
#define LDBL_SCNf "%llf"
#define LDBL_SCNe "%lle"
#define LDBL_MAN_BIT (LDBL_MANT_DIG - 1)
#define LDBL_EXP_BIT (bitsof(long double) - LDBL_MANT_DIG)
typedef union LDBL_UNION
{
long double fpn;
mcc_uhuge_t raw;
struct
{
mcc_uhuge_t man:LDBL_MAN_BIT;
mcc_uhuge_t exp:LDBL_EXP_BIT;
mcc_uhuge_t sig:1;
};
} LDBL_UNION;
#define FPN_PFX(VAL) FLT##_##VAL
#define FPN_MAX FPN_PFX(_MAX)
#define FPN_PRIa FPN_PFX(PRIa)
#define FPN_PRIf FPN_PFX(PRIf)
#define FPN_PRIe FPN_PFX(PRIe)
#define FPN_SCNa FPN_PFX(SCNa)
#define FPN_SCNf FPN_PFX(SCNf)
#define FPN_SCNe FPN_PFX(SCNe)
#define FPN_DIG FPN_PFX(DIG)
#define FPN_EPSILON FPN_PFX(EPSILON)
#define FPN_MAN_BIT FPN_PFX(MAN_BIT)
#define FPN_MANT_DIG FPN_PFX(MANT_DIG)
#define FPN_EXP_BIT FPN_PFX(EXP_BIT)
#define FPN_MAX_EXP FPN_PFX(MAX_EXP)
#define FPN_MIN_EXP FPN_PFX(MIN_EXP)
#define FPN_MAX_10_EXP FPN_PFX(MAX_10_EXP)
#define FPN_MIN_10_EXP FPN_PFX(MIN_10_EXP)
typedef FPN_PFX(UNION) FPN_UNION;
typedef struct mcc_fpn_limits {
ulong exp_bias;
long man_bits;
long exp_bits;
long max_exp;
long min_exp;
long max_exp_digits;
long min_exp_digits;
} mcc_fpn_limits_t;
typedef struct mcc_fpn {
long rounds;
long epsilon;
long pos;
long exp;
mcc_uhuge_t base;
mcc_uhuge_t inf;
mcc_uhuge_t neg;
mcc_uhuge_t num;
mcc_uhuge_t fpn;
mcc_uhuge_t one;
mcc_uhuge_t tmp;
mcc_uhuge_t raw;
mcc_fpn_limits_t limits;
} mcc_fpn_t;
typedef struct mcc_big {
long rounds;
long epsilon;
long pos;
long exp;
mcc_uint_t inf;
mcc_uint_t base;
mcc_uint_t neg;
mcc_uint_t num;
mcc_uint_t fpn;
mcc_uint_t one;
mcc_uint_t tmp;
mcc_uint_t raw;
mcc_fpn_limits_t limits;
} mcc_big_t;
#endif
#ifndef INC_MCC_VINT_H
#define INC_MCC_VINT_H
#include <limits.h>
#include <inttypes.h>
#include <errno.h>
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include <time.h>
#include <assert.h>
#define bitsof(T) (CHAR_BIT * sizeof(T))
#define INC_BITMATH
#define MCC__INT_USE_HUGE
typedef unsigned int mcc_test_t;
#define MCC_TEST_END_BIT (~(UINT_MAX >> 1))
#define MCC_TEST_PRI_PFX ""
#ifndef MCC__INT_USE_HUGE
//#define MCC__INT_USE_TEST
#define MCC__INT_USE_CHAR
#endif
#ifdef MCC__INT_USE_TEST
typedef mcc_test_t mcc_int_seg_t;
#define MCC__INT_SEG_END_BIT MCC_TEST_END_BIT
#define MCC__INT_SEG_PRI_PFX MCC_TEST_PRI_PFX
#elif defined( MCC__INT_USE_CHAR )
typedef unsigned char mcc_int_seg_t;
#define MCC__INT_SEG_END_BIT (~(UCHAR_MAX >> 1))
#define MCC__INT_SEG_PRI_PFX ""
#elif defined( MCC__INT_USE_HUGE )
typedef unsigned __int128 mcc_int_seg_t;
#define MCC__INT_SEG_END_BIT (~((~((unsigned __int128)0u)) >> 1))
#define MCC__INT_SEG_PRI_PFX "I128"
#else
typedef unsigned long mcc_int_seg_t;
#define MCC__INT_SEG_END_BIT (~(ULONG_MAX >> 1))
#define MCC__INT_SEG_PRI_PFX "l"
#endif
typedef struct mcc_bit {
mcc_int_seg_t i;
mcc_int_seg_t *seg;
mcc_int_seg_t b;
mcc_int_seg_t bit;
} mcc_bit_t;
int mcc_bit_op_cmp( mcc_bit_t num, mcc_bit_t val );
mcc_bit_t mcc_bit_op_inc( mcc_bit_t num );
mcc_bit_t mcc_bit_op_dec( mcc_bit_t num );
mcc_bit_t mcc__bit_op_add( mcc_bit_t num, mcc_int_seg_t bits );
mcc_bit_t mcc__bit_op_sub( mcc_bit_t num, mcc_int_seg_t bits );
mcc_bit_t mcc_bit_op_dec_for_bit( mcc_bit_t stop, mcc_bit_t zero );
typedef struct mcc__int {
int exit;
size_t size;
/* Tells shallow functions to free memory before exit */
_Bool temp;
mcc_bit_t zero, stop;
} mcc__int_t, mcc_int_t, mcc_uint_t;
int mcc_int_validate( mcc__int_t const * const num );
int mcc_int_validate2( mcc__int_t const * const num, mcc__int_t const * const val );
int mcc_int_validate3( mcc__int_t const * const num, mcc__int_t const * const val, mcc__int_t const * const var );
void mcc_int_print( mcc__int_t num, mcc_int_seg_t min );
int mcc_int_wrap( mcc__int_t *var, void *addr, size_t size );
int mcc_int_size( mcc__int_t *dst, size_t size );
int mcc_int_size_and_fill( mcc__int_t *dst, void const *src, size_t size );
int mcc__int_op_cmp( mcc__int_t const * const num, mcc__int_t const * const val );
#define mcc__int_is_nil( num ) (mcc__int_op_cmp( num, NULL ) == 0)
#define mcc__int_is_eql( num, val ) (mcc__int_op_cmp( num, val ) == 0)
#define mcc__int_is_neq( num, val ) (mcc__int_op_cmp( num, val ) != 0)
#define mcc__int_is_gth( num, val ) (mcc__int_op_cmp( num, val ) > 0)
#define mcc__int_is_gte( num, val ) (mcc__int_op_cmp( num, val ) >= 0)
#define mcc__int_is_lth( num, val ) (mcc__int_op_cmp( num, val ) < 0)
#define mcc__int_is_lte( num, val ) (mcc__int_op_cmp( num, val ) <= 0)
int mcc__int_op_not( mcc__int_t *num );
int mcc__int_op_inc( mcc__int_t *num );
int mcc__int_op_dec( mcc__int_t *num );
int mcc__int_op_aor( mcc__int_t *num, mcc__int_t const * const val );
int mcc__int_op_xor( mcc__int_t *num, mcc__int_t const * const val );
int mcc__int_op_and( mcc__int_t *num, mcc__int_t const * const val );
int mcc___int_op_shl( mcc__int_t *num, mcc_int_seg_t bits );
int mcc___int_op_shr( mcc__int_t *num, mcc_int_seg_t bits );
int mcc__int_op_shl( mcc__int_t *num, mcc__int_t const * const val );
int mcc__int_op_shr( mcc__int_t *num, mcc__int_t const * const val );
int mcc__int_op_add( mcc__int_t *num, mcc__int_t const * const val );
int mcc___int_op_mul( mcc__int_t *num, mcc__int_t const * const val, mcc__int_t *tmp );
int mcc__int_op_mul( mcc__int_t *num, mcc__int_t const * const val );
int mcc__int_op_sub( mcc__int_t *num, mcc__int_t const * const val );
int mcc___int_op_div( mcc__int_t *num, mcc__int_t const * const val, mcc__int_t *rem );
int mcc__int_op_div( mcc__int_t *num, mcc__int_t const * const val );
int mcc__int_op_mod( mcc__int_t *num, mcc__int_t const * const val );
#endif