online compiler and debugger for c/c++

code. compile. run. debug. share.
Source Code    Language
#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)) typedef unsigned int mcc_test_t; #define MCC_TEST_END_BIT (~(UINT_MAX >> 1)) #define MCC_TEST_PRI_PFX "" #define INC_BITMATH #define MCC__INT_USE_HUGE #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; 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 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) { 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 * dst, mcc_int_seg_t * src, size_t count) { if (!dst) return EDESTADDRREQ; if (!src) return EADDRNOTAVAIL; if (!count) return ERANGE; (void) memset (dst, 0, sizeof (mcc__int_t)); dst->size = count * sizeof (mcc_int_seg_t); dst->zero.seg = src; dst->zero.bit = 1; dst->stop = mcc__bit_op_add (dst->zero, dst->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; } #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 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_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) { n = mcc_bit_op_dec (n); if (*(n.seg) & n.bit) *(n.seg) ^= n.bit; } return EXIT_SUCCESS; } 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.bit > 1u) { if (*(n.seg) & n.bit) *(n.seg) ^= n.bit; n = mcc_bit_op_inc (n); } if (n.i < num->stop.i) { n.i = num->stop.i - n.i; memset (n.seg, 0, n.i * sizeof (mcc_int_seg_t)); } return 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_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, 1); if (ret != EXIT_SUCCESS) return ret; ret = mcc_int_wrap (&rem, &move, 1); 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, 1); if (ret != EXIT_SUCCESS) return ret; ret = mcc_int_wrap (&rem, &move, 1); 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, mcc_int_seg_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, 1); 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 |= 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 '+': num += val; mcc__int_op_add (&_num, &_val); goto done; case '*': num *= val; mcc__int_op_mul (&_num, &_val); goto done; case '-': 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 #include <float.h> #ifndef INC_BITMATH #define bitsof(T) (CHAR_BIT * sizeof(T)) #include <limits.h> #include <inttypes.h> #include <errno.h> #include <string.h> #include <stdlib.h> #include <stdio.h> #endif 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_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_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_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_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_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_flexable_fpn { long man_bits; long exp_bits; mcc_uhuge_t negative; mcc_uhuge_t num; mcc_uhuge_t one; mcc_uhuge_t fpn; long exp; long max_exp; long min_exp; long max_exp_digits; long min_exp_digits; ulong exp_bias; mcc_uhuge_t base; mcc_uhuge_t raw; } mcc_flexable_fpn_t; #define FPN_MAKE big_make mcc_flexable_fpn_t fpn_make (mcc_flexable_fpn_t flex); mcc_flexable_fpn_t big_make (mcc_flexable_fpn_t flex); mcc_flexable_fpn_t fpn_read (char *text, FPN_UNION * gcc, mcc_flexable_fpn_t flex); char *fpn_text[] = { "0", "1", "10", "16", "100", "101", "0.1", "0.01", "0.001", "0.101", "1.1", "1.01", "1.001", "1.101", "3.14", "1e+1", "1e+8", "1e+10", "1e+100", "3e+1", "1e-1", "1e-8", "1e-10", "1e-100", "3e-1", ".1e+1", ".1e+8", ".1e+10", ".1e+100", ".3e+1", ".1e-1", ".1e-8", ".1e-10", ".1e-100", ".3e-1", "1.1e+1", "1.1e+8", "1.1e+10", "1.1e+100", "3.1e+1", "1.1e-1", "1.1e-8", "1.1e-10", "1.1e-100", "3.1e-1", "3.14e+1", "3.14e+8", "3.14e+10", "3.14e+100", "3.14e-1", "3.14e-8", "3.14e-10", "3.14e-100", "-0", "-1", "-10", "-16", "-100", "-101", "-0.1", "-0.01", "-0.001", "-0.101", "-1.1", "-1.01", "-1.001", "-1.101", "-3.14", "-1e+1", "-1e+8", "-1e+10", "-1e+100", "-3e+1", "-1e-1", "-1e-8", "-1e-10", "-1e-100", "-3e-1", "-0.1e+1", "-0.1e+8", "-0.1e+10", "-0.1e+100", "-0.3e+1", "-0.1e-1", "-0.1e-8", "-0.1e-10", "-0.1e-100", "-0.3e-1", "-1.1e+1", "-1.1e+8", "-1.1e+10", "-1.1e+100", "-3.1e+1", "-1.1e-1", "-1.1e-8", "-1.1e-10", "-1.1e-100", "-3.1e-1", "-3.14e+1", "-3.14e+8", "-3.14e+10", "-3.14e+100", "-3.14e-1", "-3.14e-8", "-3.14e-10", "-3.14e-100", "0xA", "0xA0", "0xA6", "0xA00", "0xA0A", "0x0.A", "0x0.0A", "0x0.00A", "0x0.A0A", "0xA.A", "0xA.0A", "0xA.00A", "0xA.A0A", "0xC.A4", "0xAp+A", "0xAp+F", "0xAp+A0", "0xAp+A00", "0xCp+A", "0xAp-A", "0xAp-F", "0xAp-A0", "0xAp-A00", "0xCp-A", "0x0.Ap+A", "0x0.Ap+F", "0x0.Ap+A0", "0x0.Ap+A00", "0x0.Cp+A", "0x0.Ap-A", "0x0.Ap-F", "0x0.Ap-A0", "0x0.Ap-A00", "0x0.Cp-A", "0xA.Ap+A", "0xA.Ap+F", "0xA.Ap+A0", "0xA.Ap+A00", "0xC.Ap+A", "0xA.Ap-A", "0xA.Ap-F", "0xA.Ap-A0", "0xA.Ap-A00", "0xC.Ap-A", "0xC.A4p+A", "0xC.A4p+F", "0xC.A4p+A0", "0xC.A4p+A00", "0xC.A4p-A", "0xC.A4p-F", "0xC.A4p-A0", "0xC.A4p-A00", "-0xA", "-0xA0", "-0x10", "-0xA00", "-0xA0A", "-0x0.A", "-0x0.0A", "-0x0.00A", "-0x0.A0A", "-0xA.A", "-0xA.0A", "-0xA.00A", "-0xA.A0A", "-0xC.A4", "-0xAp+A", "-0xAp+F", "-0xAp+A0", "-0xAp+A00", "-0xCp+A", "-0xAp-A", "-0xAp-F", "-0xAp-A0", "-0xAp-A00", "-0xCp-A", "-0x0.Ap+A", "-0x0.Ap+F", "-0x0.Ap+A0", "-0x0.Ap+A00", "-0x0.Cp+A", "-0x0.Ap-A", "-0x0.Ap-F", "-0x0.Ap-A0", "-0x0.Ap-A00", "-0x0.Cp-A", "-0xA.Ap+A", "-0xA.Ap+F", "-0xA.Ap+A0", "-0xA.Ap+A00", "-0xC.Ap+A", "-0xA.Ap-A", "-0xA.Ap-F", "-0xA.Ap-A0", "-0xA.Ap-A00", "-0xC.Ap-A", "-0xC.A4p+A", "-0xC.A4p+F", "-0xC.A4p+A0", "-0xC.A4p+A00", "-0xC.A4p-A", "-0xC.A4p-F", "-0xC.A4p-A0", "-0xC.A4p-A00", NULL }; void printb (char const *text, void const *addr, size_t const bits) { size_t size = bits / CHAR_BIT, b = 0; uchar const *a = addr; uchar val, bit; if (bits % CHAR_BIT) ++size; printf ("%s", text); while (size--) { for (val = a[size], bit = 1; bit; val <<= 1, bit <<= 1, ++b) putchar ('0' + ! !(val & SCHAR_MIN)); if (b >= bits) return; } } mcc_flexable_fpn_t copy_of_temp = { 0 }; size_t tested = 0, offby1 = 0, notinf = 0, wasinf = 0, noteql = 0; _Bool check (char *text, FPN_UNION gcc, FPN_UNION mcc, mcc_flexable_fpn_t flex) { _Bool same = (gcc.raw == mcc.raw), similar = 0, inf = 0; FPN_UNION tmp = mcc; ulong val; tmp.raw--; ++tested; noteql += !same; if (gcc.exp != mcc.exp) { inf = (gcc.exp == UCHAR_MAX || mcc.exp == UCHAR_MAX); notinf += (gcc.exp == UCHAR_MAX); wasinf += (mcc.exp == UCHAR_MAX); } similar = (gcc.man == tmp.man); offby1 += similar; if (!same) { if (!similar && !inf) { printb ("gcc = ", &gcc, bitsof (mcc_uhuge_t)); putchar ('\n'); printb ("mcc = ", &mcc, bitsof (mcc_uhuge_t)); putchar ('\n'); val = gcc.exp; printb ("gcc.exp = ", &val, 11); putchar ('\n'); val = mcc.exp; printb ("mcc.exp = ", &val, 11); putchar ('\n'); printf ("fpn t = " FPN_SCNe " m = " FPN_SCNe "\n", gcc.fpn, mcc.fpn); } if (inf) { printf ("one = %llu, ", (ullong) (flex.one)); printf ("given %s", flex.negative ? "-" : ""); if (flex.base == 10) { if (flex.exp < 0) printf ("%llu.%llue%ld", (ullong) (flex.num), (ullong) (flex.fpn), flex.exp); else printf ("%llu.%llue+%ld", (ullong) (flex.num), (ullong) (flex.fpn), flex.exp); } else { if (flex.exp < 0) printf ("%llX.%llXp-%lX", (ullong) (flex.num), (ullong) (flex.fpn), flex.exp); else printf ("%llX.%llXp+%lX", (ullong) (flex.num), (ullong) (flex.fpn), flex.exp); } printf (", value %s", text); } } return !same; } void tried (char *pfx, size_t count, size_t not_eql, size_t off_by1, size_t not_inf, size_t was_inf) { char *space = pfx ? " " : ""; if (!pfx) pfx = ""; printf ("%s%sTried = %zu, " "%s%sWrong = %zu, " "%s%sOff By 1 = %zu, " "%s%sNot Inf = %zu, " "%s%sWas Inf = %zu\n", pfx, space, count, pfx, space, not_eql, pfx, space, off_by1, pfx, space, not_inf, pfx, space, was_inf); } #define TEST_INT 1 #define TEST_NEG 0 #define TEST_FPN 0 #define TEST_BOTH 0 #define TEST_RAW 1 #define TEST_TEXT 1 void exponent (mcc_flexable_fpn_t flex, size_t limit) { mcc_flexable_fpn_t temp; FPN_UNION gcc = { 0 }, mcc = { 0}; size_t i = 0; char text[128] = { 0 }, etxt[8] = { 0}; if (flex.exp >= 0) snprintf (etxt, 8, "e+%ld", flex.exp); else if (flex.exp < 0) snprintf (etxt, 8, "e%ld", flex.exp); #if TEST_INT for (i = 0; i <= limit; ++i) { snprintf (text, 128, "%zu.0%s", i, etxt); #if TEST_RAW sscanf (text, FPN_SCNe, &(gcc.fpn)); temp = flex; temp.num = i; temp.one = 1; mcc.raw = (temp = FPN_MAKE (temp)).raw; #else mcc.raw = (temp = fpn_read (text, &gcc, flex)).raw; #endif check (text, gcc, mcc, temp); putchar ('\n'); #if TEST_NEG snprintf (text, 128, "-%zu.0%s", i, etxt); #if TEST_RAW sscanf (text, FPN_SCNe, &(gcc.fpn)); temp = flex; temp.negative = 1; temp.num = i; temp.one = 1; mcc.raw = (temp = FPN_MAKE (temp)).raw; #else mcc.raw = (temp = fpn_read (text, &gcc, flex)).raw; #endif check (text, gcc, mcc, temp); putchar ('\n'); #endif } #endif #if TEST_FPN for (i = 0; i <= limit; ++i) { snprintf (text, 128, "0.%zu%s", i, etxt); #if TEST_RAW sscanf (text, FPN_SCNe, &(gcc.fpn)); temp = flex; temp.fpn = i; temp.one = 1; while (temp.one <= temp.fpn) temp.one *= temp.base; mcc.raw = (temp = FPN_MAKE (temp)).raw; #else mcc.raw = (temp = fpn_read (text, &gcc, flex)).raw; #endif check (text, gcc, mcc, temp); putchar ('\n'); #if TEST_NEG snprintf (text, 128, "-0.%zu%s", i, etxt); #if TEST_RAW sscanf (text, FPN_SCNe, &(gcc.fpn)); temp = flex; temp.negative = 1; temp.fpn = i; temp.one = 1; while (temp.one <= temp.fpn) temp.one *= temp.base; mcc.raw = (temp = FPN_MAKE (temp)).raw; #else mcc.raw = (temp = fpn_read (text, &gcc, flex)).raw; #endif check (text, gcc, mcc, temp); putchar ('\n'); #endif } #endif #if TEST_BOTH for (i = 0; i <= limit; ++i) { snprintf (text, 128, "%zu.%zu%s", i, i, etxt); #if TEST_RAW sscanf (text, FPN_SCNe, &(gcc.fpn)); temp = flex; temp.num = i; temp.fpn = i; while (temp.one <= temp.fpn) temp.one *= temp.base; mcc.raw = (temp = FPN_MAKE (temp)).raw; #else mcc.raw = (temp = fpn_read (text, &gcc, flex)).raw; #endif check (text, gcc, mcc, temp); putchar ('\n'); #if TEST_NEG snprintf (text, 128, "-%zu.%zu%s", i, i, etxt); #if TEST_RAW sscanf (text, FPN_SCNe, &(gcc.fpn)); temp = flex; temp.negative = 1; temp.num = i; temp.fpn = i; temp.one = 1; while (temp.one <= temp.fpn) temp.one *= temp.base; mcc.raw = (temp = FPN_MAKE (temp)).raw; #else mcc.raw = (temp = fpn_read (text, &gcc, flex)).raw; #endif check (text, gcc, mcc, temp); putchar ('\n'); #endif } #endif } size_t scenario = 0; int main () { size_t i = 0; //, limit = FPN_MAX_10_EXP; #if TEST_TEXT FPN_UNION gcc, mcc; #endif mcc_flexable_fpn_t flex = { 0 }, temp; #if 0 printf ("FPN_DIG %d\n", FPN_DIG); printf ("FPN_EXP_BIT %lu\n", FPN_EXP_BIT); printf ("FPN_EPSILON %le\n", FPN_EPSILON); printf ("FPN_MAX_EXP %d\n", FPN_MAX_EXP); printf ("FPN_MIN_EXP %d\n", FPN_MIN_EXP); printf ("FPN_MAX_10_EXP %d\n", FPN_MAX_10_EXP); printf ("FPN_MIN_10_EXP %d\n", FPN_MIN_10_EXP); printf ("FPN_MANT_DIG %d\n", FPN_MANT_DIG); printf ("FPN_MAN_BIT %d\n", FPN_MAN_BIT); #endif flex.one = 1; flex.base = 10; flex.exp_bias = FPN_MAX_EXP; flex.exp_bits = FPN_EXP_BIT; flex.max_exp_digits = FPN_MAX_10_EXP; flex.min_exp_digits = FPN_MIN_10_EXP; flex.max_exp = FPN_MAX_EXP; flex.min_exp = FPN_MIN_EXP; flex.man_bits = FPN_MAN_BIT; #if 0 temp = flex; for (i = 0; i <= limit; ++i) { temp.exp = i; exponent (temp, limit); temp.exp = -(temp.exp); } tried (NULL, tested, noteql, offby1, notinf, wasinf); printf ("scenario = %zu\n", scenario); #endif #if TEST_TEXT tested = 0; noteql = 0; offby1 = 0; notinf = 0; wasinf = 0; for (i = 0; fpn_text[i]; ++i) { mcc.raw = (temp = fpn_read (fpn_text[i], &gcc, flex)).raw; check (fpn_text[i], gcc, mcc, temp); putchar ('\n'); } while (fpn_text[i]) ++i; printf ("Strings = %zu\n", i); tried ("Text", tested, noteql, offby1, notinf, wasinf); #endif return 0; } mcc_flexable_fpn_t fpn_make (mcc_flexable_fpn_t flex) { mcc_flexable_fpn_t temp = flex; long pos = 0, pos_max = flex.man_bits; mcc_uhuge_t NUM, inf = 0; mcc_int_t num = { 0 }, fpn = { 0}, one = { 0}, base = { 0}; inf = ~inf; inf <<= flex.exp_bits; inf = ~inf; flex.raw = 0; temp.negative <<= temp.man_bits; temp.negative <<= temp.exp_bits; if (!(temp.num) && !(temp.fpn)) goto fpn_sign; /* Use exponent */ pos = temp.exp; temp.raw = 0; temp.raw = ~(temp.raw); temp.raw <<= temp.max_exp - 1; temp.raw = ~(temp.raw); if (pos < temp.min_exp_digits || pos > temp.max_exp_digits) { fpn_inf: flex.raw = 0; temp.raw = inf; goto fpn_exp; } (void) mcc_int_wrap (&num, &(temp.num), 1); (void) mcc_int_wrap (&fpn, &(temp.fpn), 1); (void) mcc_int_wrap (&one, &(temp.one), 1); (void) mcc_int_wrap (&base, &(temp.base), 1); while (pos > 0 && temp.fpn) { if (mcc__int_op_mul (&num, &base) == EOVERFLOW) goto fpn_inf; temp.one /= temp.base; if (temp.fpn >= temp.one) { NUM = temp.fpn / temp.one; temp.num += NUM; temp.fpn -= NUM * temp.one; } --pos; } while (pos > 0) { if (mcc__int_op_mul (&num, &base) == EOVERFLOW) goto fpn_inf; --pos; } (void) memset (&num, 0, sizeof (num)); (void) mcc_int_wrap (&num, &NUM, 1); while (pos < 0 && temp.num) { NUM = temp.num % temp.base; temp.num /= temp.base; if (mcc__int_op_mul (&num, &one) == EOVERFLOW) goto fpn_inf; temp.fpn += NUM; if (mcc__int_op_mul (&one, &base) == EOVERFLOW) goto fpn_inf; pos++; } while (pos < 0) { if (mcc__int_op_mul (&one, &base) == EOVERFLOW) goto fpn_inf; pos++; } /* Set exponent */ pos = 0; if (temp.num) { NUM = temp.num; while (NUM > 1u) { NUM >>= 1; ++pos; } if (pos > temp.max_exp) goto fpn_inf; } else { NUM = temp.fpn; while (NUM && NUM < temp.one) { NUM <<= 1; --pos; } if (pos < temp.min_exp) goto fpn_inf; } temp.raw = temp.exp_bias + pos - 1; if (temp.raw >= inf) goto fpn_inf; /* Set mantissa */ flex.raw = temp.num; if (pos > pos_max) { pos -= pos_max; flex.raw >>= pos - 1; temp.fpn = flex.raw & 1u; flex.raw >>= 1; temp.one = 2; } else { for (; pos < pos_max; ++pos) { temp.fpn *= 2; flex.raw <<= 1; if (temp.fpn >= temp.one) { flex.raw |= 1; temp.fpn -= temp.one; } } } temp.fpn *= 2; if (temp.fpn >= temp.one) flex.raw++; temp.one = bitsof (mcc_uhuge_t) - (temp.man_bits); flex.raw <<= temp.one; flex.raw >>= temp.one; fpn_exp: flex.raw |= (temp.raw << temp.man_bits); fpn_sign: flex.raw |= temp.negative; copy_of_temp = temp; return flex; } mcc_flexable_fpn_t big_make (mcc_flexable_fpn_t flex) { int ret = 0; mcc_flexable_fpn_t temp = flex; long pos = 0, pos_max = flex.man_bits; mcc_int_t NUM = { 0 }, num = { 0}, fpn = { 0}, one = { 0}, base = { 0}, rem = { 0}, tmp = { 0}; mcc_uhuge_t inf = 0; inf = ~inf; inf <<= flex.exp_bits; inf = ~inf; flex.raw = 0; temp.negative <<= temp.man_bits; temp.negative <<= temp.exp_bits; if (!(temp.num) && !(temp.fpn)) goto big_sign; ret = mcc_int_size (&num, (temp.max_exp / CHAR_BIT) + 1); if (ret != EXIT_SUCCESS) goto big_sign; ret = mcc_int_size (&rem, num.size); if (ret != EXIT_SUCCESS) goto big_sign; ret = mcc_int_size (&fpn, num.size); if (ret != EXIT_SUCCESS) goto big_sign; ret = mcc_int_size (&NUM, num.size); if (ret != EXIT_SUCCESS) goto big_sign; ret = mcc_int_size (&one, num.size); if (ret != EXIT_SUCCESS) goto big_sign; ret = mcc_int_size (&tmp, num.size); if (ret != EXIT_SUCCESS) goto big_sign; ret = mcc_int_size (&base, num.size); if (ret != EXIT_SUCCESS) goto big_sign; memset (NUM.zero.seg, 0, NUM.size); memset (num.zero.seg, 0, num.size); memset (fpn.zero.seg, 0, fpn.size); memset (one.zero.seg, 0, one.size); memset (base.zero.seg, 0, base.size); memset (tmp.zero.seg, 0, tmp.size); memcpy (num.zero.seg, &temp.num, sizeof (temp.num)); memcpy (fpn.zero.seg, &temp.fpn, sizeof (temp.fpn)); memcpy (one.zero.seg, &temp.one, sizeof (temp.one)); memcpy (base.zero.seg, &temp.base, sizeof (temp.base)); *(tmp.zero.seg) = 1; while (NUM.stop.bit > 1) num.stop = mcc_bit_op_dec (NUM.stop); while (num.stop.bit > 1) num.stop = mcc_bit_op_dec (num.stop); while (fpn.stop.bit > 1) fpn.stop = mcc_bit_op_dec (fpn.stop); while (one.stop.bit > 1) one.stop = mcc_bit_op_dec (one.stop); while (base.stop.bit > 1) base.stop = mcc_bit_op_dec (base.stop); while (tmp.stop.bit > 1) tmp.stop = mcc_bit_op_dec (tmp.stop); /* Use exponent */ pos = temp.exp; if (pos < temp.min_exp || pos > temp.max_exp) { big_inf: flex.raw = 0; temp.raw = inf; goto big_exp; } while (pos > 0 && !mcc__int_is_nil (&fpn)) { if (mcc__int_op_mul (&num, &base) == EOVERFLOW) goto big_inf; mcc___int_op_div (&one, &base, &rem); if (mcc__int_is_gte (&fpn, &one)) { memcpy (NUM.zero.seg, fpn.zero.seg, fpn.size); mcc___int_op_div (&NUM, &one, &rem); mcc__int_op_add (&num, &NUM); mcc__int_op_mul (&NUM, &one); mcc__int_op_sub (&fpn, &NUM); } --pos; } while (pos > 0) { if (mcc__int_op_mul (&num, &base) == EOVERFLOW) goto big_inf; --pos; } while (pos < 0 && !mcc__int_is_nil (&num)) { mcc___int_op_div (&num, &base, &NUM); if (mcc__int_op_mul (&NUM, &one) == EOVERFLOW) goto big_inf; mcc__int_op_add (&fpn, &NUM); if (mcc__int_op_mul (&one, &base) == EOVERFLOW) goto big_inf; pos++; } while (pos < 0) { if (mcc__int_op_mul (&one, &base) == EOVERFLOW) goto big_inf; pos++; } /* Set exponent */ pos = 0; if (!mcc__int_is_nil (&num)) { memcpy (NUM.zero.seg, num.zero.seg, num.size); while (mcc__int_is_gth (&NUM, &tmp)) { mcc___int_op_shr (&NUM, 1); ++pos; } if (pos > temp.max_exp) goto big_inf; } else { memcpy (NUM.zero.seg, fpn.zero.seg, fpn.size); while (!mcc__int_is_nil (&NUM) && mcc__int_is_lth (&NUM, &one)) { mcc___int_op_shl (&NUM, 1); --pos; } if (pos < temp.min_exp) goto big_inf; } temp.raw = temp.exp_bias + pos - 1; if (temp.raw >= inf) goto big_inf; /* Set mantissa */ memcpy (&(flex.raw), num.zero.seg, sizeof (mcc_uhuge_t)); if (pos > pos_max) { memset (fpn.zero.seg, 0, fpn.size); memset (one.zero.seg, 0, one.size); pos -= pos_max; mcc___int_op_shr (&num, pos - 1); *(fpn.zero.seg) = (*(num.zero.seg) & 1u); mcc___int_op_shr (&num, 1); memcpy (&(flex.raw), num.zero.seg, sizeof (mcc_uhuge_t)); *(one.zero.seg) = 2; } else { *(tmp.zero.seg) = 2; for (; pos < pos_max; ++pos) { mcc___int_op_shl (&fpn, 1); //mcc___int_op_mul( &fpn, &tmp, &NUM ); flex.raw <<= 1; if (mcc__int_is_gte (&fpn, &one)) { flex.raw |= 1; mcc__int_op_sub (&fpn, &one); } } } mcc___int_op_shl (&fpn, 1); if (mcc__int_is_gte (&fpn, &one)) flex.raw++; temp.one = (bitsof (mcc_uhuge_t) - temp.man_bits); flex.raw <<= temp.one; flex.raw >>= temp.one; big_exp: flex.raw |= (temp.raw << temp.man_bits); big_sign: flex.raw |= temp.negative; copy_of_temp = temp; mcc_int_size (&base, 0); mcc_int_size (&one, 0); mcc_int_size (&NUM, 0); mcc_int_size (&fpn, 0); mcc_int_size (&rem, 0); mcc_int_size (&num, 0); return flex; } mcc_flexable_fpn_t fpn_read (char *text, FPN_UNION * gcc, mcc_flexable_fpn_t flex) { uchar *txt = (uchar *) text; ulong c; gcc->raw = 0; flex.raw = 0; flex.base = 10; flex.negative = (*txt == '-'); if (flex.negative || *txt == '+') ++txt; if (*txt == '0') { ++txt; if (*txt == 'x' || *txt == 'X') { flex.base = 16; ++txt; } } if (flex.base == 10) sscanf (text, FPN_SCNf, &(gcc->fpn)); else sscanf (text, FPN_SCNa, &(gcc->fpn)); while (*txt == '0') ++txt; for (flex.num = 0; *txt; ++txt) { if (*txt >= '0' && *txt <= '9') c = *txt - '0'; else if (*txt >= 'A' && *txt <= 'F') c = 10 + (*txt - 'A'); else if (*txt >= 'a' && *txt <= 'f') c = 10 + (*txt - 'a'); else break; if (c >= flex.base) break; flex.num *= flex.base; flex.num += c; } flex.one = 1; flex.fpn = 0; if (*txt == '.') { for (++txt; *txt; ++txt) { if (*txt >= '0' && *txt <= '9') c = *txt - '0'; else if (*txt >= 'A' && *txt <= 'F') c = 10 + (*txt - 'A'); else if (*txt >= 'a' && *txt <= 'f') c = 10 + (*txt - 'a'); else break; if (c >= flex.base) break; flex.one *= flex.base; flex.fpn *= flex.base; flex.fpn += c; } } if (*txt == 'e' || *txt == 'E') { if (*(++txt) == '-') { for (++txt; *txt; ++txt) { if (*txt >= '0' && *txt <= '9') c = *txt - '0'; else if (*txt >= 'A' && *txt <= 'F') c = 10 + (*txt - 'A'); else if (*txt >= 'a' && *txt <= 'f') c = 10 + (*txt - 'f'); else break; if (c >= flex.base) break; flex.exp *= flex.base; flex.exp -= c; } } else { for (++txt; *txt; ++txt) { if (*txt >= '0' && *txt <= '9') c = *txt - '0'; else if (*txt >= 'A' && *txt <= 'F') c = 10 + (*txt - 'A'); else if (*txt >= 'a' && *txt <= 'f') c = 10 + (*txt - 'f'); else break; if (c >= flex.base) break; flex.exp *= flex.base; flex.exp += c; } } } return FPN_MAKE (flex); }

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