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