1 /*
2  * %CopyrightBegin%
3  *
4  * Copyright Ericsson AB 1996-2020. All Rights Reserved.
5  *
6  * Licensed under the Apache License, Version 2.0 (the "License");
7  * you may not use this file except in compliance with the License.
8  * You may obtain a copy of the License at
9  *
10  *     http://www.apache.org/licenses/LICENSE-2.0
11  *
12  * Unless required by applicable law or agreed to in writing, software
13  * distributed under the License is distributed on an "AS IS" BASIS,
14  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15  * See the License for the specific language governing permissions and
16  * limitations under the License.
17  *
18  * %CopyrightEnd%
19  */
20 
21 #ifndef __BIG_H__
22 #define __BIG_H__
23 
24 #include "sys.h"
25 #include "global.h"
26 
27 typedef Uint     ErtsDigit;
28 
29 #if (SIZEOF_VOID_P == 4) && defined(SIZEOF_LONG_LONG) && (SIZEOF_LONG_LONG == 8)
30 /* Assume 32-bit machine with long long support */
31 typedef Uint64   ErtsDoubleDigit;
32 typedef Uint16   ErtsHalfDigit;
33 #define BIG_HAVE_DOUBLE_DIGIT 1
34 
35 #elif (SIZEOF_VOID_P == 4)
36 /* Assume 32-bit machine with no long support */
37 #undef  BIG_HAVE_DOUBLE_DIGIT
38 typedef Uint16   ErtsHalfDigit;
39 
40 #elif (SIZEOF_VOID_P == 8)
41 /* Assume 64-bit machine, does it exist 128 bit long long long ? */
42 #undef  BIG_HAVE_DOUBLE_DIGIT
43 typedef Uint32   ErtsHalfDigit;
44 #else
45 #error "cannot determine machine size"
46 #endif
47 
48 typedef Uint  dsize_t;	 /* Vector size type */
49 
50 #define D_EXP (ERTS_SIZEOF_ETERM*8)
51 #define D_MASK     ((ErtsDigit)(-1))      /* D_BASE-1 */
52 
53 /* macros for bignum objects */
54 #define big_v(x)       BIG_V(big_val(x))
55 #define big_sign(x)    BIG_SIGN(big_val(x))
56 #define big_arity(x)   BIG_ARITY(big_val(x))
57 #define big_digit(x,i) BIG_DIGIT(big_val(x),i)
58 #define big_size(x)    BIG_SIZE(big_val(x))
59 
60 
61 /* macros for thing pointers */
62 
63 #define BIG_V(xp)        ((ErtsDigit*)((xp)+1))
64 #define BIG_SIGN(xp)     (!!bignum_header_is_neg(*xp))
65 #define BIG_ARITY(xp)    ((Uint)bignum_header_arity(*(xp)))
66 #define BIG_DIGIT(xp,i)  *(BIG_V(xp)+(i))
67 #define BIG_DIGITS_PER_WORD (sizeof(Uint)/sizeof(ErtsDigit))
68 
69 #define BIG_SIZE(xp)  BIG_ARITY(xp)
70 
71 /* Check for small */
72 #define IS_USMALL(sgn,x)  ((sgn) ? ((x) <= MAX_SMALL+1) : ((x) <= MAX_SMALL))
73 
74 /*
75  * It seems that both clang and gcc will generate sub-optimal code
76  * for the more obvious way to write the range check:
77  *
78  *    #define IS_SSMALL(x)  (((x) >= MIN_SMALL) && ((x) <= MAX_SMALL))
79  *
80  * Note that IS_SSMALL() may be used in the 32-bit emulator with
81  * a Uint64 argument. Therefore, we must test the size of the argument
82  * to ensure that the cast does not discard the high-order 32 bits.
83  */
84 #if defined(ARCH_32)
85 #  define _IS_SSMALL32(x) (((Uint32) ((((x)) >> (SMALL_BITS-1)) + 1)) < 2)
86 #else
87 #  define _IS_SSMALL32(x) (1)
88 #endif
89 #define _IS_SSMALL64(x) (((Uint64) ((((x)) >> (SMALL_BITS-1)) + 1)) < 2)
90 #define IS_SSMALL(x) (sizeof(x) == sizeof(Uint32) ? _IS_SSMALL32(x) : _IS_SSMALL64(x))
91 
92 /* The heap size needed for a bignum */
93 #define BIG_NEED_SIZE(x)  ((x) + 1)
94 #define BIG_NEED_FOR_BITS(bits) BIG_NEED_SIZE(((bits)-1)/D_EXP + 1)
95 
96 #define BIG_UINT_HEAP_SIZE (1 + 1)	/* always, since sizeof(Uint) <= sizeof(Eterm) */
97 
98 #define BIG_UWORD_HEAP_SIZE(UW) BIG_UINT_HEAP_SIZE
99 
100 #if defined(ARCH_32)
101 
102 #define ERTS_UINT64_BIG_HEAP_SIZE__(X) \
103   ((X) >= (((Uint64) 1) << 32) ? (1 + 2) : (1 + 1))
104 #define ERTS_SINT64_HEAP_SIZE(X)				\
105   (IS_SSMALL((X))						\
106    ? 0								\
107    : ERTS_UINT64_BIG_HEAP_SIZE__((X) >= 0 ? (X) : -(Uint64)(X)))
108 #define ERTS_UINT64_HEAP_SIZE(X)				\
109   (IS_USMALL(0, (X)) ? 0 : ERTS_UINT64_BIG_HEAP_SIZE__((X)))
110 #define ERTS_MAX_SINT64_HEAP_SIZE (1 + 2)
111 #define ERTS_MAX_UINT64_HEAP_SIZE (1 + 2)
112 #define ERTS_UINT64_ARRAY_TO_BIG_MAX_HEAP_SZ(LEN) (2*(LEN)+1)
113 
114 #else
115 
116 #define ERTS_SINT64_HEAP_SIZE(X)				\
117   (IS_SSMALL((X)) ? 0 : (1 + 1))
118 #define ERTS_UINT64_HEAP_SIZE(X)				\
119   (IS_USMALL(0, (X)) ? 0 : (1 + 1))
120 #define ERTS_MAX_SINT64_HEAP_SIZE (1 + 1)
121 #define ERTS_MAX_UINT64_HEAP_SIZE (1 + 1)
122 #define ERTS_UINT64_ARRAY_TO_BIG_MAX_HEAP_SZ(LEN) ((LEN)+1)
123 
124 #endif
125 
126 int big_integer_estimate(Wterm, Uint base);
127 Eterm erts_big_to_list(Eterm, int base, Eterm**);
128 char *erts_big_to_string(Wterm x, int base, char *buf, Uint buf_sz);
129 Uint erts_big_to_binary_bytes(Eterm x, int base, char *buf, Uint buf_sz);
130 
131 Eterm small_times(Sint, Sint, Eterm*);
132 
133 Eterm big_plus(Wterm, Wterm, Eterm*);
134 Eterm big_minus(Eterm, Eterm, Eterm*);
135 Eterm big_times(Eterm, Eterm, Eterm*);
136 Eterm big_div(Eterm, Eterm, Eterm*);
137 Eterm big_rem(Eterm, Eterm, Eterm*);
138 
139 Eterm big_plus_small(Eterm, Uint, Eterm*);
140 Eterm big_times_small(Eterm, Uint, Eterm*);
141 
142 Eterm big_band(Eterm, Eterm, Eterm*);
143 Eterm big_bor(Eterm, Eterm, Eterm*);
144 Eterm big_bxor(Eterm, Eterm, Eterm*);
145 Eterm big_bnot(Eterm, Eterm*);
146 
147 Eterm big_lshift(Eterm, Sint, Eterm*);
148 int big_comp (Wterm, Wterm);
149 int big_ucomp (Eterm, Eterm);
150 int big_to_double(Wterm x, double* resp);
151 Eterm double_to_big(double, Eterm*, Uint hsz);
152 Eterm small_to_big(Sint, Eterm*);
153 Eterm uint_to_big(Uint, Eterm*);
154 Eterm uword_to_big(UWord, Eterm*);
155 Eterm erts_make_integer(Uint, Process *);
156 Eterm erts_make_integer_from_uword(UWord x, Process *p);
157 
158 dsize_t big_bytes(Eterm);
159 Eterm bytes_to_big(byte*, dsize_t, int, Eterm*);
160 byte* big_to_bytes(Eterm, byte*);
161 
162 int term_to_Uint(Eterm, Uint*);
163 int term_to_Uint_mask(Eterm, Uint*);
164 int term_to_UWord(Eterm, UWord*);
165 int term_to_Sint(Eterm, Sint*);
166 #if HAVE_INT64
167 Eterm erts_uint64_array_to_big(Uint **, int, int, Uint64 *);
168 int term_to_Uint64(Eterm, Uint64*);
169 int term_to_Sint64(Eterm, Sint64*);
170 #endif
171 int term_to_Uint32(Eterm, Uint32*);
172 
173 
174 Uint32 big_to_uint32(Eterm b);
175 int term_equals_2pow32(Eterm);
176 
177 Eterm erts_uint64_to_big(Uint64, Eterm **);
178 Eterm erts_sint64_to_big(Sint64, Eterm **);
179 
180 Eterm erts_chars_to_integer(Process *, char*, Uint, const int);
181 
182 /* How list_to_integer classifies the input, was it even a string? */
183 typedef enum {
184     LTI_BAD_STRUCTURE = 0,
185     LTI_NO_INTEGER    = 1,
186     LTI_SOME_INTEGER  = 2,
187     LTI_ALL_INTEGER   = 3
188 } LTI_result_t;
189 
190 LTI_result_t erts_list_to_integer(Process *BIF_P, Eterm orig_list,
191                                   const Uint base,
192                                   Eterm *integer_out, Eterm *tail_out);
193 #endif
194