Imported Upstream version 1.46.0
[platform/upstream/nghttp2.git] / third-party / mruby / include / mruby / numeric.h
1 /**
2 ** @file mruby/numeric.h - Numeric, Integer, Float, Fixnum class
3 **
4 ** See Copyright Notice in mruby.h
5 */
6
7 #ifndef MRUBY_NUMERIC_H
8 #define MRUBY_NUMERIC_H
9
10 #include "common.h"
11
12 /**
13  * Numeric class and it's sub-classes.
14  *
15  * Integer, Float and Fixnum
16  */
17 MRB_BEGIN_DECL
18
19 #define TYPED_POSFIXABLE(f,t) ((f) <= (t)MRB_INT_MAX)
20 #define TYPED_NEGFIXABLE(f,t) ((f) >= (t)MRB_INT_MIN)
21 #define TYPED_FIXABLE(f,t) (TYPED_POSFIXABLE(f,t) && TYPED_NEGFIXABLE(f,t))
22 #define POSFIXABLE(f) TYPED_POSFIXABLE(f,mrb_int)
23 #define NEGFIXABLE(f) TYPED_NEGFIXABLE(f,mrb_int)
24 #define FIXABLE(f) TYPED_FIXABLE(f,mrb_int)
25 #ifndef MRB_WITHOUT_FLOAT
26 #ifdef MRB_INT64
27 #define FIXABLE_FLOAT(f) ((f)>=-9223372036854775808.0 && (f)<9223372036854775808.0)
28 #else
29 #define FIXABLE_FLOAT(f) TYPED_FIXABLE(f,mrb_float)
30 #endif
31 #endif
32
33 #ifndef MRB_WITHOUT_FLOAT
34 MRB_API mrb_value mrb_flo_to_fixnum(mrb_state *mrb, mrb_value val);
35 #endif
36 MRB_API mrb_value mrb_fixnum_to_str(mrb_state *mrb, mrb_value x, mrb_int base);
37 /* ArgumentError if format string doesn't match /%(\.[0-9]+)?[aAeEfFgG]/ */
38 #ifndef MRB_WITHOUT_FLOAT
39 MRB_API mrb_value mrb_float_to_str(mrb_state *mrb, mrb_value x, const char *fmt);
40 MRB_API int mrb_float_to_cstr(mrb_state *mrb, char *buf, size_t len, const char *fmt, mrb_float f);
41 MRB_API mrb_float mrb_to_flo(mrb_state *mrb, mrb_value x);
42 MRB_API mrb_value mrb_int_value(mrb_state *mrb, mrb_float f);
43 #endif
44
45 MRB_API mrb_value mrb_num_plus(mrb_state *mrb, mrb_value x, mrb_value y);
46 MRB_API mrb_value mrb_num_minus(mrb_state *mrb, mrb_value x, mrb_value y);
47 MRB_API mrb_value mrb_num_mul(mrb_state *mrb, mrb_value x, mrb_value y);
48
49 #ifndef __has_builtin
50   #define __has_builtin(x) 0
51 #endif
52
53 #if (defined(__GNUC__) && __GNUC__ >= 5) ||   \
54     (__has_builtin(__builtin_add_overflow) && \
55      __has_builtin(__builtin_sub_overflow) && \
56      __has_builtin(__builtin_mul_overflow))
57 # define MRB_HAVE_TYPE_GENERIC_CHECKED_ARITHMETIC_BUILTINS
58 #endif
59
60 /*
61 // Clang 3.8 and 3.9 have problem compiling mruby in 32-bit mode, when MRB_INT64 is set
62 // because of missing __mulodi4 and similar functions in its runtime. We need to use custom
63 // implementation for them.
64 */
65 #ifdef MRB_HAVE_TYPE_GENERIC_CHECKED_ARITHMETIC_BUILTINS
66 #if defined(__clang__) && (__clang_major__ == 3) && (__clang_minor__ >= 8) && \
67     defined(MRB_32BIT) && defined(MRB_INT64)
68 #undef MRB_HAVE_TYPE_GENERIC_CHECKED_ARITHMETIC_BUILTINS
69 #endif
70 #endif
71
72 #ifdef MRB_HAVE_TYPE_GENERIC_CHECKED_ARITHMETIC_BUILTINS
73
74 #ifndef MRB_WORD_BOXING
75 # define WBCHK(x) 0
76 #else
77 # define WBCHK(x) !FIXABLE(x)
78 #endif
79
80 static inline mrb_bool
81 mrb_int_add_overflow(mrb_int augend, mrb_int addend, mrb_int *sum)
82 {
83   return __builtin_add_overflow(augend, addend, sum) || WBCHK(*sum);
84 }
85
86 static inline mrb_bool
87 mrb_int_sub_overflow(mrb_int minuend, mrb_int subtrahend, mrb_int *difference)
88 {
89   return __builtin_sub_overflow(minuend, subtrahend, difference) || WBCHK(*difference);
90 }
91
92 static inline mrb_bool
93 mrb_int_mul_overflow(mrb_int multiplier, mrb_int multiplicand, mrb_int *product)
94 {
95   return __builtin_mul_overflow(multiplier, multiplicand, product) || WBCHK(*product);
96 }
97
98 #undef WBCHK
99
100 #else
101
102 #define MRB_UINT_MAKE2(n) uint ## n ## _t
103 #define MRB_UINT_MAKE(n) MRB_UINT_MAKE2(n)
104 #define mrb_uint MRB_UINT_MAKE(MRB_INT_BIT)
105
106 #define MRB_INT_OVERFLOW_MASK ((mrb_uint)1 << (MRB_INT_BIT - 1 - MRB_FIXNUM_SHIFT))
107
108 static inline mrb_bool
109 mrb_int_add_overflow(mrb_int augend, mrb_int addend, mrb_int *sum)
110 {
111   mrb_uint x = (mrb_uint)augend;
112   mrb_uint y = (mrb_uint)addend;
113   mrb_uint z = (mrb_uint)(x + y);
114   *sum = (mrb_int)z;
115   return !!(((x ^ z) & (y ^ z)) & MRB_INT_OVERFLOW_MASK);
116 }
117
118 static inline mrb_bool
119 mrb_int_sub_overflow(mrb_int minuend, mrb_int subtrahend, mrb_int *difference)
120 {
121   mrb_uint x = (mrb_uint)minuend;
122   mrb_uint y = (mrb_uint)subtrahend;
123   mrb_uint z = (mrb_uint)(x - y);
124   *difference = (mrb_int)z;
125   return !!(((x ^ z) & (~y ^ z)) & MRB_INT_OVERFLOW_MASK);
126 }
127
128 static inline mrb_bool
129 mrb_int_mul_overflow(mrb_int multiplier, mrb_int multiplicand, mrb_int *product)
130 {
131 #if MRB_INT_BIT == 32
132   int64_t n = (int64_t)multiplier * multiplicand;
133   *product = (mrb_int)n;
134   return !FIXABLE(n);
135 #else
136   if (multiplier > 0) {
137     if (multiplicand > 0) {
138       if (multiplier > MRB_INT_MAX / multiplicand) return TRUE;
139     }
140     else {
141       if (multiplicand < MRB_INT_MAX / multiplier) return TRUE;
142     }
143   }
144   else {
145     if (multiplicand > 0) {
146       if (multiplier < MRB_INT_MAX / multiplicand) return TRUE;
147     }
148     else {
149       if (multiplier != 0 && multiplicand < MRB_INT_MAX / multiplier) return TRUE;
150     }
151   }
152   *product = multiplier * multiplicand;
153   return FALSE;
154 #endif
155 }
156
157 #undef MRB_INT_OVERFLOW_MASK
158 #undef mrb_uint
159 #undef MRB_UINT_MAKE
160 #undef MRB_UINT_MAKE2
161
162 #endif
163
164 #ifndef MRB_WITHOUT_FLOAT
165 # include <stdint.h>
166 # include <float.h>
167
168 # define MRB_FLT_RADIX          FLT_RADIX
169
170 # ifdef MRB_USE_FLOAT
171 #  define MRB_FLT_MANT_DIG      FLT_MANT_DIG
172 #  define MRB_FLT_EPSILON       FLT_EPSILON
173 #  define MRB_FLT_DIG           FLT_DIG
174 #  define MRB_FLT_MIN_EXP       FLT_MIN_EXP
175 #  define MRB_FLT_MIN           FLT_MIN
176 #  define MRB_FLT_MIN_10_EXP    FLT_MIN_10_EXP
177 #  define MRB_FLT_MAX_EXP       FLT_MAX_EXP
178 #  define MRB_FLT_MAX           FLT_MAX
179 #  define MRB_FLT_MAX_10_EXP    FLT_MAX_10_EXP
180
181 # else /* not MRB_USE_FLOAT */
182 #  define MRB_FLT_MANT_DIG      DBL_MANT_DIG
183 #  define MRB_FLT_EPSILON       DBL_EPSILON
184 #  define MRB_FLT_DIG           DBL_DIG
185 #  define MRB_FLT_MIN_EXP       DBL_MIN_EXP
186 #  define MRB_FLT_MIN           DBL_MIN
187 #  define MRB_FLT_MIN_10_EXP    DBL_MIN_10_EXP
188 #  define MRB_FLT_MAX_EXP       DBL_MAX_EXP
189 #  define MRB_FLT_MAX           DBL_MAX
190 #  define MRB_FLT_MAX_10_EXP    DBL_MAX_10_EXP
191 # endif /* MRB_USE_FLOAT */
192 #endif /* MRB_WITHOUT_FLOAT */
193
194 MRB_END_DECL
195
196 #endif  /* MRUBY_NUMERIC_H */