online compiler and debugger for c/c++

code. compile. run. debug. share.
Source Code    Language
#include "mcc_vflt.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_put; 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; details_put: _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 ); } mcc_big_t fill_big( mcc_fpn_t mcc, mcc_big_t big, uchar *base, size_t perN ) { size_t size = perN / 2; big.limits = mcc.limits; big.rounds = mcc.rounds; big.epsilon = mcc.epsilon; big.base = mcc_vint_wrap( 0, base, size ); big.inf = mcc_vint_wrap( 0, &(base[perN]), size ); big.neg = mcc_vint_wrap( 0, &(base[perN * 2]), size ); big.num = mcc_vint_wrap( 0, &(base[perN * 3]), size ); big.fpn = mcc_vint_wrap( 0, &(base[perN * 4]), size ); big.one = mcc_vint_wrap( 0, &(base[perN * 5]), size ); big.tmp = mcc_vint_wrap( 0, &(base[perN * 6]), size ); big.raw = mcc_vint_wrap( 0, &(base[perN * 7]), size ); return big; } int main() { mcc_fpn_t gcc = {0}, mcc = {0}, tmp; mcc_big_t big_gcc = {0}, big_mcc = {0}, big_tmp = {0}; 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}, big_stats = {0}; size_t size = 0; uchar *addr = NULL; 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 size = (limits.max_exp / CHAR_BIT) * 2; addr = malloc( limits.max_exp * 4 ); if ( !addr ) return EXIT_FAILURE; big_gcc = fill_big( mcc, big_gcc, addr, size ); big_mcc = fill_big( mcc, big_mcc, &(addr[size * 8]), size ); big_tmp = fill_big( mcc, big_tmp, &(addr[size * 16]), size ); 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 ); mcc_big_read( txt, &big_gcc, big_mcc, big_tmp ); gcc.raw = *((mcc_uhuge_t*)(big_gcc.raw.zero.seg)); tmp.raw = *((mcc_uhuge_t*)(big_mcc.raw.zero.seg)); details( &big_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 ); mcc_big_read( txt, &big_gcc, big_mcc, big_tmp ); gcc.raw = *((mcc_uhuge_t*)(big_gcc.raw.zero.seg)); tmp.raw = *((mcc_uhuge_t*)(big_mcc.raw.zero.seg)); details( &big_stats, txt, gcc, tmp ); } } } fpn_stats_put( NULL, NULL, stats ); fpn_stats_put( "Big", NULL, big_stats ); free(addr); 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; 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 0 if ( tmp.pos < -8 ) { tmp.tmp <<= -(tmp.pos + 8); mcc.raw <<= -(tmp.pos + 8); tmp.pos = -8; } #endif 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_vint_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___vint_op_shl( big.inf, limits.exp_bits ); mcc__vint_op_not( big.inf ); return big; } int mcc_big_validiate( mcc_big_t *mcc_big ) { int ret; if ( !mcc_big ) return EDESTADDRREQ; ret = mcc_vint_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); mcc_vint_seg_t bits = 0; mcc_uhuge_t _one = 1, size, need; 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; } need = ((limits.exp_bits + limits.man_bits + 1) / CHAR_BIT); size = (limits.max_exp / CHAR_MAX) + 1; if ( size <= (need * 4) || tmp.pos > 0 || mcc__vint_is_nil(mcc.num) || mcc__vint_is_nil(mcc.one) || tmp.raw.size < need || tmp.inf.size < need || tmp.neg.size < need || tmp.fpn.size < size || tmp.num.size < size || tmp.one.size < size || tmp.tmp.size < size || tmp.base.size < size || mcc.raw.size < need || mcc.inf.size < need || mcc.neg.size < need || mcc.fpn.size < size || mcc.num.size < size || mcc.one.size < size || mcc.tmp.size < size || mcc.base.size < size ) goto mcc_big_sig; one = mcc_vint_wrap( 0, &_one, sizeof(_one) ); mcc_vint_fill( tmp.tmp, tmp.num ); mcc___vint_op_div( tmp.tmp, tmp.one, tmp.fpn ); if ( mcc__vint_is_nil( mcc.fpn ) ) { (void)mcc_vint_fill( tmp.num, tmp.tmp ); (void)mcc_vint_fill( tmp.one, one ); tmp.pos = 0; } while ( tmp.exp > 0 ) { if ( tmp.pos == 0 || mcc__vint_is_eql( tmp.one, one ) ) break; (void)mcc___vint_op_div( tmp.one, tmp.base, tmp.tmp ); tmp.pos++; tmp.exp--; } if ( tmp.exp > limits.max_exp || tmp.exp < limits.min_exp ) { mcc_big_inf: mcc_vint_fill( tmp.raw, mcc.inf ); goto mcc_big_exp; } for ( ; tmp.exp > 0; tmp.exp-- ) { if ( mcc___vint_op_mul( tmp.num, tmp.base, tmp.tmp ) == EOVERFLOW ) goto mcc_big_inf; } for ( ; tmp.exp < 0; tmp.exp++ ) { if ( mcc___vint_op_mul( tmp.one, tmp.base, tmp.tmp ) == EOVERFLOW ) goto mcc_big_sig; } (void)mcc___vint_op_div( tmp.num, tmp.one, tmp.fpn ); if ( mcc__vint_is_nil( tmp.fpn ) ) mcc_vint_fill( tmp.one, one ); tmp.pos = 0; if ( mcc__vint_is_gte( tmp.num, one ) ) { for ( mcc_vint_fill( tmp.tmp, tmp.num ); mcc__vint_is_gth( tmp.tmp, one ); tmp.pos++, mcc___vint_op_shr( tmp.tmp, 1 ) ); } else { for ( mcc_vint_fill( tmp.tmp, tmp.one ); mcc__vint_is_gth( tmp.tmp, tmp.fpn ); tmp.pos--, mcc___vint_op_shr( tmp.tmp, 1 ) ); if ( mcc__vint_is_eql( tmp.tmp, tmp.fpn ) ) tmp.pos--; } mcc.pos = tmp.pos; mcc_vint_fill( tmp.raw, mcc_vint_wrap( 1, &(limits.exp_bias), sizeof(limits.exp_bias) ) ); if ( mcc__vint_is_gth( tmp.raw, mcc.inf ) ) goto mcc_big_inf; if ( tmp.pos > limits.man_bits ) { tmp.pos -= limits.man_bits; mcc__vint_op_xor( tmp.fpn, tmp.fpn ); mcc__vint_op_not( tmp.fpn ); mcc___vint_op_shl( tmp.fpn, tmp.pos ); mcc__vint_op_not( tmp.fpn ); mcc__vint_op_and( tmp.fpn, tmp.num ); mcc___vint_op_shl( tmp.one, tmp.pos ); mcc_vint_fill( tmp.tmp, tmp.num ); mcc___vint_op_shr( tmp.tmp, tmp.pos ); mcc_vint_fill( mcc.raw, tmp.tmp ); mcc_vint_fill( tmp.tmp, tmp.one ); mcc___vint_op_shr( tmp.tmp, 1 ); ret = mcc__vint_op_cmp( tmp.fpn, tmp.tmp ); if ( ret > 0 ) mcc__vint_op_inc( mcc.raw ); else if ( ret == 0 ) { switch ( mcc.rounds ) { case 1: if ( *(mcc.raw.zero.seg) & mcc.raw.zero.bit ) mcc__vint_op_inc( mcc.raw ); break; } } } else { mcc_vint_fill( mcc.raw, tmp.num ); mcc_vint_fill( tmp.tmp, tmp.fpn ); for ( ; tmp.pos < limits.man_bits; tmp.pos++ ) { bits++; mcc___vint_op_shl( tmp.tmp, 1 ); if ( mcc__vint_is_gte( tmp.tmp, tmp.one ) ) { (void)mcc__vint_op_sub( tmp.tmp, tmp.one ); (void)mcc___vint_op_shl( tmp.num, bits ); *(tmp.num.zero.seg) |= tmp.num.zero.bit; bits = 0; } } if ( bits ) (void)mcc___vint_op_shl( tmp.num, bits ); } bits = (mcc.raw.stop.b - mcc.raw.zero.b) - limits.man_bits; mcc___vint_op_shl( mcc.raw, bits ); mcc___vint_op_shr( mcc.raw, bits ); mcc_big_exp: mcc___vint_op_shl( tmp.raw, limits.exp_bits ); mcc__vint_op_aor( mcc.raw, tmp.raw ); mcc_big_sig: mcc___vint_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 ) { char *text, sig; int c = 0, l = 10, h = 10; char e = 'e', E = 'E'; FPN_UNION lib = {0}; mcc__vint_t C = mcc_vint_wrap( 1, &c, sizeof(c) ); while ( isspace(*txt) ) ++txt; text = txt; (void)mcc__vint_op_xor( tmp.neg, tmp.neg ); switch ( *txt ) { case '-': *(tmp.neg.zero.seg) = tmp.neg.zero.bit; case '+': ++txt; } if ( *txt == '0' ) { ++txt; switch ( *txt ) { case 'b': case 'B': ++txt; c = 2; mcc_vint_fill( tmp.base, C ); break; case 'x': case 'X': ++txt; c = 16; mcc_vint_fill( tmp.base, C ); break; } c = 36; if ( mcc__vint_is_gth( tmp.base, C ) ) l = 36; } while ( *txt ) { c = mcc_geti( *txt, l, h ); if ( c < 0 || mcc__vint_is_gte( C, tmp.base ) ) break; ++txt; if ( mcc___vint_op_mul( tmp.num, tmp.base, tmp.tmp ) == EOVERFLOW ) { (void)mcc_vint_fill( big.raw, big.neg ); (void)mcc___vint_op_shl( big.raw, big.limits.exp_bits ); (void)mcc__vint_op_aor( big.raw, big.inf ); (void)mcc___vint_op_shl( big.raw, big.limits.man_bits ); return big; } (void)mcc__vint_op_add( tmp.num, C ); } tmp.pos = 0; if ( *txt == '.' ) { ++txt; while ( *txt ) { c = mcc_geti( *txt, l, h ); if ( c < 0 || mcc__vint_is_gte( C, tmp.base ) ) break; ++txt; if ( mcc___vint_op_mul( tmp.num, tmp.base, tmp.tmp ) == EOVERFLOW ) { (void)mcc_vint_fill( big.raw, big.neg ); (void)mcc___vint_op_shl( big.raw, big.limits.exp_bits ); (void)mcc___vint_op_shl( big.raw, big.limits.man_bits ); return big; } (void)mcc__vint_op_add( tmp.num, C ); (void)mcc___vint_op_mul( tmp.one, tmp.base, tmp.tmp ); 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 || mcc__vint_is_gte( C, tmp.base ) ) break; ++txt; tmp.exp *= *(tmp.base.zero.seg); tmp.exp += c; } if ( sig == '-' ) tmp.exp = -(tmp.exp); } *gcc = tmp; mcc_vint_fill( gcc->inf, tmp.inf ); mcc_vint_fill( gcc->num, tmp.num ); mcc_vint_fill( gcc->fpn, tmp.fpn ); mcc_vint_fill( gcc->one, tmp.one ); mcc_vint_fill( C, tmp.base ); if ( c == 10 ) sscanf( text, FPN_SCNe, &(lib.fpn) ); else if ( c == 16 ) sscanf( text, FPN_SCNa, &(lib.fpn) ); mcc_vint_to_val( gcc->raw, lib.raw ); mcc_vint_fill( big.inf, tmp.inf ); mcc_vint_fill( big.num, tmp.num ); mcc_vint_fill( big.fpn, tmp.fpn ); mcc_vint_fill( big.one, tmp.one ); return mcc_big_make( big, tmp ); }
#include <limits.h> #include <inttypes.h> #include "mcc_vint.h" mcc_bit_t mcc_bit_op_inc( mcc_bit_t num ) { mcc_vint_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_vint_seg_t bits ) { #ifdef MCC_BIT_SLOW while ( bits-- ) { num = mcc_bit_op_inc(num); if ( !(num.bit) ) return num; } return num; #else mcc_vint_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_vint_seg_t bits ) { #ifdef MCC_BIT_SLOW while ( bits-- ) { num = mcc_bit_op_dec(num); if ( !(num.bit) ) return num; } return num; #else mcc_vint_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_vint_validate( mcc__vint_t *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_vint_validate2( mcc__vint_t *num, mcc__vint_t *val ) { int ret = mcc_vint_validate( num ); switch ( ret ) { case EXIT_SUCCESS: break; case EADDRNOTAVAIL: return EDESTADDRREQ; default: return ret; } return mcc_vint_validate( val ); } int mcc_vint_validate3( mcc__vint_t *num, mcc__vint_t *val, mcc__vint_t *var ) { int ret = mcc_vint_validate2( num, val ); if ( ret != EXIT_SUCCESS ) return ret; ret = mcc_vint_validate(var); if ( ret != EXIT_SUCCESS ) return (ret == EADDRNOTAVAIL) ? EDESTADDRREQ : ret; if ( var->size < num->size ) return ERANGE; return EXIT_SUCCESS; } void mcc_vint_print( mcc__vint_t num, mcc_vint_seg_t min ) { int ret = mcc_vint_validate(&num); mcc_vint_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) ); } } mcc__vint_t mcc_vint_wrap( bool has_sign, void *addr, size_t size ) { mcc__vint_t tmp = {0}; if ( !addr || !size ) return tmp; tmp.size = size; tmp.zero.seg = addr; tmp.zero.bit = 1; tmp.stop = mcc__bit_op_add( tmp.zero, size * CHAR_BIT ); if ( has_sign ) tmp.sign = mcc_bit_op_dec( tmp.stop ); return tmp; } int mcc_vint_size( mcc__vint_t *num, size_t size ) { mcc_vint_seg_t *mem; size_t nodes; if ( !size ) { if ( num->zero.seg ) free( num->zero.seg ); memset( num, 0, sizeof(mcc__vint_t) ); return EXIT_SUCCESS; } nodes = size / sizeof(mcc_vint_seg_t); if ( size % sizeof(mcc_vint_seg_t) ) ++nodes; size = nodes * sizeof(mcc_vint_seg_t); if ( !(num->zero.seg) ) mem = malloc( size ); else mem = realloc( num->zero.seg, size ); if ( !mem ) ENOMEM; (void)memset( &(num->zero), 0, sizeof(mcc_bit_t) ); num->zero.seg = mem; num->zero.bit = 1; num->size = size; num->stop = mcc__bit_op_add( num->zero, size * CHAR_BIT ); return EXIT_SUCCESS; } int mcc__vint_get_sign( mcc_vint_t num ) { if ( num.sign.seg ) return (*(num.sign.seg) & num.sign.bit) ? 1 : 0; return -1; } int mcc_vint_fill( mcc__vint_t num, mcc__vint_t val ) { (void)mcc__vint_op_xor( num, num ); if ( mcc__vint_get_sign(val) == 1 ) { (void)mcc__vint_op_not( num ); return mcc__vint_op_and( num, val ); } return mcc__vint_op_aor( num, val ); } int mcc_vint_size_and_fill( mcc__vint_t *num, mcc__vint_t val ) { int ret = mcc_vint_size( num, val.size ); if ( ret != EXIT_SUCCESS ) return ret; return mcc_vint_fill( *num, val ); } int mcc__vint_op_cmp( mcc__vint_t num, mcc__vint_t val ) { mcc_bit_t n = {0}, v = {0}; mcc_vint_seg_t nb = 0, vb = 0; int nn0 = 0, vn0 = 0; if ( mcc_vint_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_vint_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__vint_t num ) { int ret = mcc_vint_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__vint_t num ) { int ret = mcc_vint_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__vint_op_not( mcc__vint_t num ) { int ret = mcc_vint_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__vint_op_aor( mcc__vint_t num, mcc__vint_t val ) { int ret = mcc_vint_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__vint_op_xor( mcc__vint_t num, mcc__vint_t val ) { int ret = mcc_vint_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__vint_op_and( mcc__vint_t num, mcc__vint_t val ) { int ret = mcc_vint_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___vint_op_shl( mcc__vint_t num, mcc_vint_seg_t bits ) { int ret = mcc_vint_validate( &num ); mcc_bit_t n, v; mcc_vint_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___vint_op_shr( mcc__vint_t num, mcc_vint_seg_t bits ) { int ret = mcc_vint_validate( &num ); mcc_bit_t n, v; mcc_vint_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__vint_op_inc( mcc__vint_t num ) { mcc_bit_t n; _Bool c = 1; int ret = mcc_vint_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__vint_op_add( mcc__vint_t num, mcc__vint_t val ) { mcc_bit_t n, v, stop; mcc_vint_seg_t b = 0, bits, nb, vb; _Bool c = 0; int ret = mcc_vint_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__vint_t num, mcc__vint_t val ) { int ret = mcc__vint_op_add( num, val ); if ( ret == EOVERFLOW ) { memset( num.zero.seg, -1, num.size ); ret = biclamp0( num ); } return ret; } int add_int( mcc__vint_t num, mcc__vint_t val ) { int ret = mcc_vint_validate2( &num, &val ); mcc__vint_t tmp; if ( ret != EXIT_SUCCESS ) return ret; tmp = num; tmp.stop = mcc_bit_op_dec(tmp.stop); ret = mcc__vint_op_add( tmp, val ); if ( ret == EOVERFLOW ) { memset( num.zero.seg, -1, num.size ); ret = biclamp0( tmp ); } return ret; } int mcc__vint_op_dec( mcc__vint_t num ) { mcc_bit_t n; _Bool c = 1; int ret = mcc_vint_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__vint_op_sub( mcc__vint_t num, mcc__vint_t val ) { mcc_bit_t n, v, s; _Bool c = 0; mcc_vint_seg_t b = 0, bits = 0, nb, vb; int ret = mcc_vint_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___vint_op_mul( mcc__vint_t num, mcc__vint_t val, mcc__vint_t tmp ) { int ret = mcc_vint_validate3( &num, &val, &tmp ); mcc_bit_t v, s; mcc_vint_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___vint_op_shl( tmp, bits ); if ( mcc__vint_op_add( num, tmp ) == EOVERFLOW ) ret = EOVERFLOW; bits = 0; } ++bits; } return ret; } int mcc__vint_op_mul( mcc__vint_t num, mcc__vint_t val ) { int ret = mcc_vint_validate2( &num, &val ); mcc__vint_t tmp = {0}; if ( ret != EXIT_SUCCESS ) return ret; ret = mcc_vint_size_and_fill( &tmp, num ); if ( ret != EXIT_SUCCESS ) return ret; ret = mcc___vint_op_mul( num, val, tmp ); (void)mcc_vint_size( &tmp, 0 ); return ret; } int mcc___vint_op_div( mcc__vint_t num, mcc__vint_t val, mcc__vint_t rem ) { int ret = mcc_vint_validate3( &num, &val, &rem ); mcc__vint_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 ( mcc__vint_is_nil( val ) ) return EXIT_SUCCESS; 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__vint_is_gte( rem, tmp ) ) { seg.zero = mcc_bit_op_dec(seg.zero); quo = mcc_bit_op_dec( quo ); if ( mcc__vint_is_gte( seg, tmp ) ) { if ( mcc__vint_op_sub( seg, tmp ) == EOVERFLOW ) ret = EOVERFLOW; *(quo.seg) |= quo.bit; } } return ret; } int mcc__vint_op_div( mcc__vint_t num, mcc__vint_t val ) { int ret = mcc_vint_validate2( &num, &val ); mcc__vint_t rem = {0}; if ( ret != EXIT_SUCCESS ) return ret; ret = mcc_vint_size( &rem, num.size ); if ( ret != EXIT_SUCCESS ) return ret; ret = mcc___vint_op_div( num, val, rem ); (void)mcc_vint_size( &rem, 0 ); return ret; } int mcc__vint_op_mod( mcc__vint_t num, mcc__vint_t val ) { int ret = mcc_vint_validate2( &num, &val ); mcc__vint_t rem = {0}; if ( ret != EXIT_SUCCESS ) return ret; ret = mcc_vint_size( &rem, num.size ); if ( ret != EXIT_SUCCESS ) return ret; ret = mcc___vint_op_div( num, val, rem ); (void)memcpy( num.zero.seg, rem.zero.seg, num.size ); (void)mcc_vint_size( &rem, 0 ); return ret; } int mcc__vint_op_shl( mcc__vint_t num, mcc__vint_t val ) { int ret = mcc_vint_validate2( &num, &val ); mcc__vint_t tmp = {0}, cpy = {0}; mcc_vint_seg_t move = 0, bits = 0; if ( ret != EXIT_SUCCESS ) return ret; bits = num.stop.b - num.zero.b; tmp = mcc_vint_wrap( 0, &bits, sizeof(bits) ); move = *(val.zero.seg); if ( mcc__vint_is_gte( val, tmp ) ) { ret = mcc_vint_size_and_fill( &cpy, val ); if ( ret != EXIT_SUCCESS ) return ret; mcc___vint_op_shl( cpy, bits ); mcc___vint_op_shr( cpy, bits ); mcc_vint_size( &cpy, 0 ); if ( ret != EXIT_SUCCESS ) return ret; } return mcc___vint_op_shl(num, move ); } int mcc__vint_op_shr( mcc__vint_t num, mcc__vint_t val ) { int ret = mcc_vint_validate2( &num, &val ); mcc__vint_t tmp = {0}, cpy = {0}; mcc_vint_seg_t move = 0, bits = 0; if ( ret != EXIT_SUCCESS ) return ret; bits = num.stop.b - num.zero.b; tmp = mcc_vint_wrap( 0, &bits, sizeof(bits) ); move = *(val.zero.seg); if ( mcc__vint_is_gte( val, tmp ) ) { ret = mcc_vint_size_and_fill( &cpy, val ); if ( ret != EXIT_SUCCESS ) return ret; mcc___vint_op_shl( cpy, bits ); mcc___vint_op_shr( cpy, bits ); mcc_vint_size( &cpy, 0 ); if ( ret != EXIT_SUCCESS ) return ret; } return mcc___vint_op_shr( num, move ); } #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__vint_t _num = {0}, _val = {0}, _rem = {0}; (void)mcc_vint_size_and_fill( &_num, &num, sizeof(num) ); (void)mcc_vint_size_and_fill( &_val, &val, sizeof(num) ); (void)mcc_vint_size_and_fill( &_rem, &num, sizeof(num) ); switch ( *op ) { case 0: ret = EILSEQ; goto fail; case '~': num = ~num; mcc__vint_op_not( &_num ); goto done; case '|': num |= val; mcc__vint_op_aor( &_num, &_val ); goto done; case '^': num ^= val; mcc__vint_op_xor( &_num, &_val ); goto done; case '&': num &= val; mcc__vint_op_and( &_num, &_val ); goto done; case '+': if ( op[1] == '+' ) { num++; mcc__vint_op_inc( &_num ); } else { num += val; mcc__vint_op_add( &_num, &_val ); } goto done; case '*': num *= val; mcc__vint_op_mul( &_num, &_val ); goto done; case '-': if ( op[1] == '+' ) { num--; mcc__vint_op_dec( &_num ); } else { num -= val; mcc__vint_op_sub( &_num, &_val ); } goto done; case '/': if ( val ) { rem %= val; num /= val; } else { rem = num; num = 0; } mcc___vint_op_div( &_num, &_val, &_rem ); goto done; case '%': if ( val ) { rem %= val; num = rem; } else { rem = num; } mcc___vint_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__vint_to_num( &_num, mcc__vint_is_eql( &_num, &_val ) ); goto done; case '!': if ( op[1] == '\0' ) { num = !num; mcc__vint_to_num( &_num, mcc__vint_is_nil( &_num ) ); } else if ( op[1] == '=' ) { num = (num != val); mcc__vint_to_num( &_num, mcc__vint_is_neq( &_num, &_val ) ); } goto done; case '>': if ( op[1] == '>' ) { num >>= val; mcc__vint_op_shr( &_num, &_val ); } else if ( op[1] == '=' ) { num = (num >= val); mcc__vint_to_num( &_num, mcc__vint_is_gte( &_num, &_val ) ); } else { num = (num > val); mcc__vint_to_num( &_num, mcc__vint_is_gth( &_num, &_val ) ); } goto done; case '<': if ( op[1] == '<' ) { num <<= val; mcc__vint_op_shl( &_num, &_val ); } else if ( op[1] == '=' ) { num = (num <= val); mcc__vint_to_num( &_num, mcc__vint_is_lte( &_num, &_val ) ); } else { num = (num < val); mcc__vint_to_num( &_num, mcc__vint_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_vint_size( &_num, 0 ); mcc_vint_size( &_val, 0 ); mcc_vint_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 <stdbool.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_vint_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_vint_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_vint_seg_t; #define MCC__INT_SEG_END_BIT (~((~((unsigned __int128)0u)) >> 1)) #define MCC__INT_SEG_PRI_PFX "I128" #else typedef unsigned long mcc_vint_seg_t; #define MCC__INT_SEG_END_BIT (~(ULONG_MAX >> 1)) #define MCC__INT_SEG_PRI_PFX "l" #endif typedef struct mcc_bit { mcc_vint_seg_t i; mcc_vint_seg_t *seg; mcc_vint_seg_t b; mcc_vint_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_vint_seg_t bits ); mcc_bit_t mcc__bit_op_sub( mcc_bit_t num, mcc_vint_seg_t bits ); mcc_bit_t mcc_bit_op_dec_for_bit( mcc_bit_t stop, mcc_bit_t zero ); typedef struct mcc__vint { int exit; size_t size; mcc_bit_t zero, stop, sign; } mcc__vint_t, mcc_vint_t, mcc_uint_t; int mcc__vint_get_sign( mcc__vint_t num ); int mcc_vint_validate( mcc__vint_t *num ); int mcc_vint_validate2( mcc__vint_t *num, mcc__vint_t *val ); int mcc_vint_validate3( mcc__vint_t *num, mcc__vint_t *val, mcc__vint_t *var ); void mcc_vint_print( mcc__vint_t num, mcc_vint_seg_t min ); mcc__vint_t mcc_vint_wrap( bool has_sign, void *addr, size_t size ); int mcc_vint_size( mcc__vint_t *num, size_t size ); int mcc_vint_fill( mcc__vint_t num, mcc__vint_t val ); #define mcc_vint_to_val( NUM, VAL ) \ mcc_vint_fill( (NUM), mcc_vint_wrap( -(-(VAL) < 0), &(VAL), sizeof(VAL) ) ) int mcc_vint_size_and_fill( mcc__vint_t *num, mcc__vint_t val ); int mcc__vint_op_cmp( mcc__vint_t num, mcc__vint_t val ); #define mcc__vint_is_nil( num ) (mcc__vint_op_cmp( num, (mcc__vint_t){0} ) == 0) #define mcc__vint_is_eql( num, val ) (mcc__vint_op_cmp( num, val ) == 0) #define mcc__vint_is_neq( num, val ) (mcc__vint_op_cmp( num, val ) != 0) #define mcc__vint_is_gth( num, val ) (mcc__vint_op_cmp( num, val ) > 0) #define mcc__vint_is_gte( num, val ) (mcc__vint_op_cmp( num, val ) >= 0) #define mcc__vint_is_lth( num, val ) (mcc__vint_op_cmp( num, val ) < 0) #define mcc__vint_is_lte( num, val ) (mcc__vint_op_cmp( num, val ) <= 0) int mcc__vint_op_not( mcc__vint_t num ); int mcc__vint_op_inc( mcc__vint_t num ); int mcc__vint_op_dec( mcc__vint_t num ); int mcc__vint_op_aor( mcc__vint_t num, mcc__vint_t val ); int mcc__vint_op_xor( mcc__vint_t num, mcc__vint_t val ); int mcc__vint_op_and( mcc__vint_t num, mcc__vint_t val ); int mcc___vint_op_shl( mcc__vint_t num, mcc_vint_seg_t bits ); int mcc___vint_op_shr( mcc__vint_t num, mcc_vint_seg_t bits ); int mcc__vint_op_shl( mcc__vint_t num, mcc__vint_t val ); int mcc__vint_op_shr( mcc__vint_t num, mcc__vint_t val ); int mcc__vint_op_add( mcc__vint_t num, mcc__vint_t val ); int mcc___vint_op_mul( mcc__vint_t num, mcc__vint_t val, mcc__vint_t tmp ); int mcc__vint_op_mul( mcc__vint_t num, mcc__vint_t val ); int mcc__vint_op_sub( mcc__vint_t num, mcc__vint_t val ); int mcc___vint_op_div( mcc__vint_t num, mcc__vint_t val, mcc__vint_t rem ); int mcc__vint_op_div( mcc__vint_t num, mcc__vint_t val ); int mcc__vint_op_mod( mcc__vint_t num, mcc__vint_t val ); #endif

Compiling Program...

Command line arguments:
Standard Input: Interactive Console Text

                

                

Program is not being debugged. Click "Debug" button to start program in debug mode.

#FunctionFile:Line
VariableValue
RegisterValue
ExpressionValue