online compiler and debugger for c/c++

code. compile. run. debug. share.
Source Code    Language
#include <float.h> #define INC_BITMATH #ifdef INC_BITMATH //#include "bimath.c" #include <limits.h> #include <inttypes.h> #include <errno.h> #include <string.h> #include <stdlib.h> #include <stdio.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 MCC__INT_USE_TEST //#define MCC__INT_USE_CHAR #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 "" #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_add( mcc_bit_t num, mcc_int_seg_t bits ) { 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; } mcc_bit_t mcc_bit_op_dec( mcc_bit_t num ) { mcc_bit_t tmp = num; if ( !tmp.b ) { memset(&num,0,sizeof(num)); return num; } --(tmp.b); tmp.bit >>= 1; if ( !(tmp.bit) ) { tmp.bit = MCC__INT_SEG_END_BIT; --(tmp.i); --(tmp.seg); } return tmp; } mcc_bit_t 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; } mcc_bit_t mcc__bit_op_sub( mcc_bit_t num, mcc_int_seg_t bits ) { 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; } int cmp_mcc_bit( 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 }; int main() { mcc_test_t i, j; for ( j = 0; j < 10000; ++j ) { for ( i = 0; operations[i]; ++i ) { test( j, operations[i], j ); } } return 0; } #endif typedef struct _bi { size_t size; mcc_bit_t zero, stop; } mcc_int_t; int mcc_int_validate( mcc_int_t const * const num ) { if ( !num || !(num->zero.seg) || !(num->stop.seg) ) return EADDRNOTAVAIL; if ( cmp_mcc_bit( 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 ); } 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; ++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; memset( &(dst->zero), 0, sizeof(mcc_bit_t) ); dst->zero.seg = mem; dst->zero.bit = 1; size -= sizeof(mcc_int_seg_t); 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; if ( num && num->zero.seg ) { n = dec_for_bit(num->stop, num->zero); nb = n.b - num->zero.b; } if ( val && val->zero.seg ) { v = dec_for_bit(val->stop, val->zero); vb = v.b - val->zero.b; } if ( !(n.bit) ) return v.bit ? -!!(*(v.seg) & v.bit) : 0; if ( !(v.bit) ) return n.bit ? !!(*(n.seg) & n.bit) : 0; if ( nb != vb ) return (nb > vb) ? 1 : -1; while ( nb ) { if ( nb ) { n = dec_for_bit( n, num->zero ); nb = n.b - num->zero.b; } if ( vb ) { v = 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 = (cmp_mcc_bit(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 = (cmp_mcc_bit(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 = (cmp_mcc_bit(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; if ( ret != EXIT_SUCCESS ) return ret; if ( !bits ) return EXIT_SUCCESS; if ( bits >= (num->stop.b - num->zero.b) ) return mcc__int_op_xor( num, num ); 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; if ( ret != EXIT_SUCCESS ) return ret; if ( !bits ) return EXIT_SUCCESS; if ( bits >= (num->stop.b - num->zero.b) ) bits %= (num->stop.b - num->zero.b); 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 = (cmp_mcc_bit(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_mul( mcc_int_t *num, mcc_int_t const * const val ) { int ret = mcc_int_validate2( num, val ); mcc_int_t tmp = {0}; mcc_bit_t v, s; mcc_int_seg_t bits = 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; s = mcc_bit_op_inc(dec_for_bit( val->stop, val->zero )); 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; } (void)mcc_int_size( &tmp, 0 ); 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 = mcc_bit_op_inc(dec_for_bit(val->stop, 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_div( mcc_int_t *num, mcc_int_t const * const val, mcc_int_t *rem ) { int ret = mcc_int_validate2( num, val ); mcc_int_t ref = {0}, seg = {0}, tmp = {0}; mcc_int_seg_t b = 0, nb = 0, bits = 0; if ( ret != EXIT_SUCCESS ) return ret; ret = mcc_int_validate(rem); if ( ret != EXIT_SUCCESS ) return (ret == EADDRNOTAVAIL) ? EDESTADDRREQ : ret; if ( rem->size < num->size ) return ERANGE; (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__int_is_eql( val, NULL ) ) return EXIT_SUCCESS; tmp = *val; tmp.stop = mcc_bit_op_inc(dec_for_bit( tmp.stop, tmp.zero )); ref = *rem; ref.stop = mcc_bit_op_inc(dec_for_bit( ref.stop, ref.zero )); seg = ref; seg.zero = seg.stop; nb = (seg.stop.b - rem->zero.b); while ( mcc__int_is_gte( &ref, &tmp ) ) { ++bits; ++b; seg.zero = mcc_bit_op_dec(seg.zero); if ( mcc__int_is_gte( &seg, &tmp ) ) { mcc__int_op_sub( &seg, &tmp ); mcc___int_op_shl( num, bits ); *(num->zero.seg) |= num->zero.bit; bits = 0; seg.stop = mcc_bit_op_inc(dec_for_bit( seg.stop, seg.zero )); } } if ( bits ) mcc___int_op_shl( num, bits ); if ( b < nb ) mcc___int_op_shl( num, nb - b ); return EXIT_SUCCESS; } 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; ret = mcc___int_op_div( &cpy, &tmp, &rem ); 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; ret = mcc___int_op_div( &cpy, &tmp, &rem ); mcc_int_size( &cpy, 0 ); if ( ret != EXIT_SUCCESS ) return ret; } return mcc___int_op_shr(num, move ); } #else #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_RADIX FPN_PFX(RADIX) #define FPN_ROUNDS FPN_PFX(ROUNDS) #define FPN_MAN_BIT FPN_PFX(MAN_BIT) #define FPN_MAN_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_EXP_DIG FPN_PFX(MAX_10_EXP) #define FPN_MIN_EXP_DIG 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; ulong base; mcc_uhuge_t raw; } mcc_flexable_fpn_t; #define FPN_MAKE fpn_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 offby1 = 0, notinf = 0, wasinf = 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--; 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 && !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 ); printf("read as %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(" with base %lu\n", flex.base ); printf ("value '%s'", text ); } return !same; } #define TEST_NEG 1 #define TEST_FPN 0 #define TEST_BOTH 0 void tried( char *pfx, size_t count, size_t wrong ) { if ( pfx ) printf( "%s Tried = %zu, %s Wrong = %zu\n", pfx, count, pfx, wrong ); else printf( "Tried = %zu, Wrong = %zu\n", count, wrong ); } size_t exponent( mcc_flexable_fpn_t flex, size_t limit, size_t *total ) { mcc_flexable_fpn_t temp; FPN_UNION gcc = {0}, mcc = {0}; size_t i = 0, j = 0, wrong = 0, total_wrong = 0; char text[128] = {0}, etxt[8] = {0}; if ( flex.exp > 0 ) snprintf(etxt, 8, "e+%02ld",flex.exp); else if ( flex.exp < 0 ) snprintf(etxt, 8, "e%02ld",flex.exp); flex.exp = 0; wrong = 0; for ( i = 0; i <= limit; ++i, ++j ) { snprintf(text,128,"%zu.000000%s",i,etxt); mcc.raw = (temp = fpn_read(text, &gcc, flex)).raw; wrong += check( text, gcc, mcc, temp ); putchar('\n'); #if TEST_NEG ++j; snprintf(text,128,"-%zu.000000%s",i,etxt); mcc.raw = (temp = fpn_read(text, &gcc, flex)).raw; wrong += check( text, gcc, mcc, temp ); putchar('\n'); #endif } total_wrong += wrong; #if TEST_FPN wrong = 0; for ( i = 0; i <= limit; ++i, ++j ) { snprintf(text,128,"0.%06zu%s",i,etxt); mcc.raw = (temp = fpn_read(text, &gcc, flex)).raw; wrong += check( text, gcc, mcc, temp ); putchar('\n'); #if TEST_NEG ++j; snprintf(text,128,"-0.%06zu%s",i,etxt); mcc.raw = (temp = fpn_read(text, &gcc, flex)).raw; wrong += check( text, gcc, mcc, temp ); putchar('\n'); #endif } total_wrong += wrong; #endif #if TEST_BOTH wrong = 0; for ( i = 0; i <= limit; ++i, ++j ) { snprintf(text,128,"%zu.%06zu%s",i,i,etxt); mcc.raw = (temp = fpn_read(text, &gcc, flex)).raw; wrong += check( text, gcc, mcc, temp ); putchar('\n'); #if TEST_NEG ++j; snprintf(text,128,"-%zu.%06zu%s",i,i,etxt); mcc.raw = (temp = fpn_read(text, &gcc, flex)).raw; wrong += check( text, gcc, mcc, temp ); putchar('\n'); #endif } total_wrong += wrong; #endif if ( total ) *total += j; return total_wrong; } int main () { size_t i = 0, limit = FPN_MAX_EXP_DIG, wrong = 0, total = 0; #if 0 FPN_UNION gcc, mcc; #endif mcc_flexable_fpn_t flex = {0}, temp; #if 0 printf("FLT_DIG %d\n", FLT_DIG ); printf("FLT_EXP_BIT %lu\n", FLT_EXP_BIT ); printf("FLT_EPSILON %le\n", FLT_EPSILON ); printf("FLT_MAX_EXP %d\n", FLT_MAX_EXP ); printf("FLT_MIN_EXP %d\n", FLT_MIN_EXP ); printf("FLT_MAX_10_EXP %d\n", FLT_MAX_10_EXP ); printf("FLT_MIN_10_EXP %d\n", FLT_MIN_10_EXP ); printf("FLT_MANT_DIG %d\n", FLT_MANT_DIG ); printf("FLT_MAN_BIT %d\n", FLT_MAN_BIT ); printf("FLT_RADIX %d\n", FLT_RADIX ); printf("FLT_ROUNDS %d\n", FLT_ROUNDS ); #endif flex.exp_bias = FPN_MAX_EXP; flex.exp_bits = FPN_EXP_BIT; flex.max_exp_digits = FPN_MAX_EXP_DIG; flex.min_exp_digits = FPN_MIN_EXP_DIG; flex.max_exp = FPN_MAX_EXP; flex.min_exp = FPN_MIN_EXP; flex.man_bits = FPN_MAN_BIT; temp = flex; for ( i = 0; i <= limit; ++i ) { temp.exp = i; wrong += exponent( temp, limit, &total ); temp.exp = -(temp.exp); } tried( "Total", total, wrong ); printf("Total Off By 1 %zu, Total Not Inf %zu, Total Was Inf %zu", offby1, notinf, wasinf ); #if 0 for ( i = 0; fpn_text[i] && i < 20; ++i ) { mcc.raw = (temp = fpn_read (fpn_text[i], &gcc, flex)); if ( check(fpn_text[i], gcc, mcc, temp) ) { printf (" index = %03zu\n", i ); ++wrong; } } limit = i; while (fpn_text[i]) ++i; printf( "Text Count = %zu, ", i ); tried( "Text", limit, wrong ); #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; flex.raw = 0; temp.negative <<= temp.man_bits; temp.negative <<= temp.exp_bits; if ( !(temp.num) && !(temp.fpn) ) goto fpn_sign; if ( temp.exp < temp.min_exp || temp.exp > temp.max_exp ) { fpn_inf: flex.raw = 0; temp.raw = 0; temp.raw = ~(temp.raw); temp.raw <<= temp.exp_bits; temp.raw = ~(temp.raw); goto fpn_exp; } /* Use exponent */ pos = temp.exp; temp.raw = 0; temp.raw = ~(temp.raw); temp.raw <<= temp.max_exp - 1; temp.raw = ~(temp.raw); while ( pos > 0 && temp.one > 1 ) { NUM = temp.num; temp.num *= temp.base; if ( temp.num <= NUM ) 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 ) { NUM = temp.num; temp.num *= temp.base; if ( temp.num <= NUM ) goto fpn_inf; --pos; } while ( pos < 0 && temp.num ) { NUM = temp.num % temp.base; temp.fpn += NUM * temp.one; NUM = temp.one; temp.one *= temp.base; if ( temp.one <= NUM ) goto fpn_inf; temp.num /= temp.base; pos++; } while ( pos < 0 ) { NUM = temp.one; temp.one *= temp.base; if ( temp.one <= NUM ) goto fpn_inf; pos++; } /* Calculate normal 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; } /* Set exponent and mantissa */ temp.raw = temp.exp_bias + pos - 1; flex.raw = temp.num; if ( pos > pos_max ) { pos -= pos_max; flex.raw >>= pos - 1; temp.fpn = 0; 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}; flex.raw = 0; temp.negative <<= temp.man_bits; temp.negative <<= temp.exp_bits; ret = mcc_int_size( &num, ((temp.man_bits + temp.exp_bits + 1) / CHAR_BIT) * 4 ); 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 ); memcpy( num.zero.seg, &temp.num, sizeof(mcc_uhuge_t) ); memset( fpn.zero.seg, 0, fpn.size ); memcpy( fpn.zero.seg, &temp.fpn, sizeof(mcc_uhuge_t) ); memset( NUM.zero.seg, 0, NUM.size ); memset( one.zero.seg, 0, one.size ); memcpy( one.zero.seg, &temp.one, sizeof(mcc_uhuge_t) ); memset( one.zero.seg, 0, one.size ); *(tmp.zero.seg) = 1; memset( base.zero.seg, 0, base.size ); memcpy( base.zero.seg, &temp.base, sizeof(ulong) ); if ( !(temp.num) && !(temp.fpn) ) goto big_sign; if ( temp.exp < temp.min_exp || temp.exp > temp.max_exp ) { big_inf: flex.raw = 0; temp.raw = 0; temp.raw = ~(temp.raw); temp.raw <<= temp.exp_bits; temp.raw = ~(temp.raw); goto big_exp; } /* Preserve exponent in case we need it later */ pos = temp.exp; num.stop = mcc__bit_op_add(num.zero,temp.max_exp); while ( pos > 0 && mcc__int_is_gth( &one, &tmp ) ) { 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 ) ) { memset( NUM.zero.seg, 0, NUM.size ); 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_op_div( &num, &base, &NUM ); mcc__int_op_mul( &NUM, &one ); mcc__int_op_add( &fpn, &NUM ); mcc__int_op_mul( &one, &base ); pos++; } if ( mcc__int_is_eql(&num,NULL) && mcc__int_is_eql(&fpn,NULL) ) goto big_inf; /* Calculate normal exponent */ pos = 0; memset( NUM.zero.seg, 0, NUM.size ); if ( temp.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_neq( &NUM, NULL ) && mcc__int_is_lth( &NUM, &one ) ) { mcc___int_op_shl( &NUM, 1 ); --pos; } if ( pos < temp.min_exp ) goto big_inf; } /* Set exponent and mantissa */ temp.raw = temp.exp_bias + pos - 1; memcpy( &(flex.raw), num.zero.seg, sizeof(mcc_uhuge_t) ); if ( pos > pos_max ) { pos -= pos_max; mcc___int_op_shr( &num, pos - 1 ); memset( fpn.zero.seg, 0, fpn.size ); *(fpn.zero.seg) = (*(num.zero.seg) & 1u); mcc___int_op_shr( &num, 1 ); memset( one.zero.seg, 0, one.size ); *(one.zero.seg) = 2; memcpy( &(flex.raw), num.zero.seg, sizeof(mcc_uhuge_t) ); } else { for ( ; pos < pos_max; ++pos) { mcc___int_op_shl( &fpn, 1 ); 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