source: EcnlProtoTool/trunk/mruby-1.3.0/include/mruby/numeric.h@ 331

Last change on this file since 331 was 331, checked in by coas-nagasima, 6 years ago

prototoolに関連するプロジェクトをnewlibからmuslを使うよう変更・更新
ntshellをnewlibの下位の実装から、muslのsyscallの実装に変更・更新
以下のOSSをアップデート
・mruby-1.3.0
・musl-1.1.18
・onigmo-6.1.3
・tcc-0.9.27
以下のOSSを追加
・openssl-1.1.0e
・curl-7.57.0
・zlib-1.2.11
以下のmrbgemsを追加
・iij/mruby-digest
・iij/mruby-env
・iij/mruby-errno
・iij/mruby-iijson
・iij/mruby-ipaddr
・iij/mruby-mock
・iij/mruby-require
・iij/mruby-tls-openssl

  • Property svn:eol-style set to native
  • Property svn:mime-type set to text/x-chdr;charset=UTF-8
File size: 4.2 KB
Line 
1/*
2** 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 */
17MRB_BEGIN_DECL
18
19#define POSFIXABLE(f) ((f) <= MRB_INT_MAX)
20#define NEGFIXABLE(f) ((f) >= MRB_INT_MIN)
21#define FIXABLE(f) (POSFIXABLE(f) && NEGFIXABLE(f))
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
29MRB_API mrb_value mrb_flo_to_fixnum(mrb_state *mrb, mrb_value val);
30MRB_API mrb_value mrb_fixnum_to_str(mrb_state *mrb, mrb_value x, int base);
31/* ArgumentError if format string doesn't match /%(\.[0-9]+)?[aAeEfFgG]/ */
32MRB_API mrb_value mrb_float_to_str(mrb_state *mrb, mrb_value x, const char *fmt);
33MRB_API mrb_float mrb_to_flo(mrb_state *mrb, mrb_value x);
34
35mrb_value mrb_fixnum_plus(mrb_state *mrb, mrb_value x, mrb_value y);
36mrb_value mrb_fixnum_minus(mrb_state *mrb, mrb_value x, mrb_value y);
37mrb_value mrb_fixnum_mul(mrb_state *mrb, mrb_value x, mrb_value y);
38mrb_value mrb_num_div(mrb_state *mrb, mrb_value x, mrb_value y);
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
71static inline mrb_bool
72mrb_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
77static inline mrb_bool
78mrb_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
83static inline mrb_bool
84mrb_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
93#define MRB_UINT_MAKE2(n) uint ## n ## _t
94#define MRB_UINT_MAKE(n) MRB_UINT_MAKE2(n)
95#define mrb_uint MRB_UINT_MAKE(MRB_INT_BIT)
96
97#define MRB_INT_OVERFLOW_MASK ((mrb_uint)1 << (MRB_INT_BIT - 1 - MRB_FIXNUM_SHIFT))
98
99static inline mrb_bool
100mrb_int_add_overflow(mrb_int augend, mrb_int addend, mrb_int *sum)
101{
102 mrb_uint x = (mrb_uint)augend;
103 mrb_uint y = (mrb_uint)addend;
104 mrb_uint z = (mrb_uint)(x + y);
105 *sum = (mrb_int)z;
106 return !!(((x ^ z) & (y ^ z)) & MRB_INT_OVERFLOW_MASK);
107}
108
109static inline mrb_bool
110mrb_int_sub_overflow(mrb_int minuend, mrb_int subtrahend, mrb_int *difference)
111{
112 mrb_uint x = (mrb_uint)minuend;
113 mrb_uint y = (mrb_uint)subtrahend;
114 mrb_uint z = (mrb_uint)(x - y);
115 *difference = (mrb_int)z;
116 return !!(((x ^ z) & (~y ^ z)) & MRB_INT_OVERFLOW_MASK);
117}
118
119static inline mrb_bool
120mrb_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;
145#endif
146}
147
148#undef MRB_INT_OVERFLOW_MASK
149#undef mrb_uint
150#undef MRB_UINT_MAKE
151#undef MRB_UINT_MAKE2
152
153#endif
154
155MRB_END_DECL
156
157#endif /* MRUBY_NUMERIC_H */
Note: See TracBrowser for help on using the repository browser.