Changeset 331 for EcnlProtoTool/trunk/mruby-1.3.0/include/mruby/numeric.h
- Timestamp:
- Jan 21, 2018, 12:10:09 AM (6 years ago)
- Location:
- EcnlProtoTool/trunk/mruby-1.3.0
- Files:
-
- 1 edited
- 1 moved
Legend:
- Unmodified
- Added
- Removed
-
EcnlProtoTool/trunk/mruby-1.3.0/include/mruby/numeric.h
r321 r331 8 8 #define MRUBY_NUMERIC_H 9 9 10 #include " mruby/common.h"10 #include "common.h" 11 11 12 12 /** … … 21 21 #define FIXABLE(f) (POSFIXABLE(f) && NEGFIXABLE(f)) 22 22 23 #ifdef MRB_INT64 24 #define FIXABLE_FLOAT(f) FIXABLE((mrb_int)(f)) 25 #else 26 #define FIXABLE_FLOAT(f) FIXABLE(f) 27 #endif 28 23 29 MRB_API mrb_value mrb_flo_to_fixnum(mrb_state *mrb, mrb_value val); 24 30 MRB_API mrb_value mrb_fixnum_to_str(mrb_state *mrb, mrb_value x, int base); … … 32 38 mrb_value mrb_num_div(mrb_state *mrb, mrb_value x, mrb_value y); 33 39 40 #ifndef __has_builtin 41 #define __has_builtin(x) 0 42 #endif 43 44 #if (defined(__GNUC__) && __GNUC__ >= 5) || \ 45 (__has_builtin(__builtin_add_overflow) && \ 46 __has_builtin(__builtin_sub_overflow) && \ 47 __has_builtin(__builtin_mul_overflow)) 48 # define MRB_HAVE_TYPE_GENERIC_CHECKED_ARITHMETIC_BUILTINS 49 #endif 50 51 /* 52 // Clang 3.8 and 3.9 have problem compiling mruby in 32-bit mode, when MRB_INT64 is set 53 // because of missing __mulodi4 and similar functions in its runtime. We need to use custom 54 // implementation for them. 55 */ 56 #ifdef MRB_HAVE_TYPE_GENERIC_CHECKED_ARITHMETIC_BUILTINS 57 #if defined(__clang__) && (__clang_major__ == 3) && (__clang_minor__ >= 8) && \ 58 defined(MRB_32BIT) && defined(MRB_INT64) 59 #undef MRB_HAVE_TYPE_GENERIC_CHECKED_ARITHMETIC_BUILTINS 60 #endif 61 #endif 62 63 #ifdef MRB_HAVE_TYPE_GENERIC_CHECKED_ARITHMETIC_BUILTINS 64 65 #ifndef MRB_WORD_BOXING 66 # define WBCHK(x) 0 67 #else 68 # define WBCHK(x) !FIXABLE(x) 69 #endif 70 71 static inline mrb_bool 72 mrb_int_add_overflow(mrb_int augend, mrb_int addend, mrb_int *sum) 73 { 74 return __builtin_add_overflow(augend, addend, sum) || WBCHK(*sum); 75 } 76 77 static inline mrb_bool 78 mrb_int_sub_overflow(mrb_int minuend, mrb_int subtrahend, mrb_int *difference) 79 { 80 return __builtin_sub_overflow(minuend, subtrahend, difference) || WBCHK(*difference); 81 } 82 83 static inline mrb_bool 84 mrb_int_mul_overflow(mrb_int multiplier, mrb_int multiplicand, mrb_int *product) 85 { 86 return __builtin_mul_overflow(multiplier, multiplicand, product) || WBCHK(*product); 87 } 88 89 #undef WBCHK 90 91 #else 92 34 93 #define MRB_UINT_MAKE2(n) uint ## n ## _t 35 94 #define MRB_UINT_MAKE(n) MRB_UINT_MAKE2(n) … … 37 96 38 97 #define MRB_INT_OVERFLOW_MASK ((mrb_uint)1 << (MRB_INT_BIT - 1 - MRB_FIXNUM_SHIFT)) 39 40 /* Idea from Potion: https://github.com/perl11/potion (MIT) */41 #if (defined(__clang__) && ((__clang_major__ > 3) || (__clang_major__ == 3 && __clang_minor__ >= 4))) \42 || (defined(__GNUC__) && __GNUC__ >= 5)43 44 static inline mrb_bool45 mrb_int_add_overflow(mrb_int augend, mrb_int addend, mrb_int *sum)46 {47 mrb_bool of;48 49 #ifdef MRB_INT6450 long long val;51 of = __builtin_saddll_overflow(augend, addend, &val) ||52 #else53 int val;54 of = __builtin_sadd_overflow(augend, addend, &val) ||55 #endif56 (val > MRB_INT_MAX) || (val < MRB_INT_MIN);57 58 *sum = (mrb_int) val;59 return of;60 }61 62 static inline mrb_bool63 mrb_int_sub_overflow(mrb_int minuend, mrb_int subtrahend, mrb_int *difference)64 {65 mrb_bool of;66 67 #ifdef MRB_INT6468 long long val;69 of = __builtin_ssubll_overflow(minuend, subtrahend, &val) ||70 #else71 int val;72 of = __builtin_ssub_overflow(minuend, subtrahend, &val) ||73 #endif74 (val > MRB_INT_MAX) || (val < MRB_INT_MIN);75 76 *difference = (mrb_int) val;77 return of;78 }79 #else80 98 81 99 static inline mrb_bool … … 99 117 } 100 118 119 static inline mrb_bool 120 mrb_int_mul_overflow(mrb_int multiplier, mrb_int multiplicand, mrb_int *product) 121 { 122 #if MRB_INT_BIT == 32 123 int64_t n = (int64_t)multiplier * multiplicand; 124 *product = (mrb_int)n; 125 return !FIXABLE(n); 126 #else 127 if (multiplier > 0) { 128 if (multiplicand > 0) { 129 if (multiplier > MRB_INT_MAX / multiplicand) return TRUE; 130 } 131 else { 132 if (multiplicand < MRB_INT_MAX / multiplier) return TRUE; 133 } 134 } 135 else { 136 if (multiplicand > 0) { 137 if (multiplier < MRB_INT_MAX / multiplicand) return TRUE; 138 } 139 else { 140 if (multiplier != 0 && multiplicand < MRB_INT_MAX / multiplier) return TRUE; 141 } 142 } 143 *product = multiplier * multiplicand; 144 return FALSE; 101 145 #endif 146 } 102 147 103 148 #undef MRB_INT_OVERFLOW_MASK … … 106 151 #undef MRB_UINT_MAKE2 107 152 153 #endif 154 108 155 MRB_END_DECL 109 156
Note:
See TracChangeset
for help on using the changeset viewer.