PageRenderTime 76ms CodeModel.GetById 24ms RepoModel.GetById 0ms app.codeStats 1ms

/erts/emulator/beam/big.c

https://github.com/bsmr-erlang/otp
C | 3005 lines | 2384 code | 332 blank | 289 comment | 508 complexity | fcda0a9c7953a3d6a96c853caf8f07d5 MD5 | raw file
Possible License(s): BSD-3-Clause, LGPL-2.1, MPL-2.0-no-copyleft-exception, Apache-2.0

Large files files are truncated, but you can click here to view the full file

  1. /*
  2. * %CopyrightBegin%
  3. *
  4. * Copyright Ericsson AB 1996-2018. 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. #ifdef HAVE_CONFIG_H
  21. # include "config.h"
  22. #endif
  23. #include "sys.h"
  24. #include "erl_vm.h"
  25. #include "global.h"
  26. #include "big.h"
  27. #include "error.h"
  28. #include "bif.h"
  29. #define ZERO_DIGITS(v, sz) do { \
  30. dsize_t _t_sz = sz; \
  31. ErtsDigit* _t_v = v; \
  32. while(_t_sz--) *_t_v++ = 0; \
  33. } while(0)
  34. #define MOVE_DIGITS(dst, src, sz) do { \
  35. dsize_t _t_sz = sz; \
  36. ErtsDigit* _t_dst; \
  37. ErtsDigit* _t_src; \
  38. if (dst < src) { \
  39. _t_dst = dst; \
  40. _t_src = src; \
  41. while(_t_sz--) *_t_dst++ = *_t_src++; \
  42. } \
  43. else if (dst > src) { \
  44. _t_dst = (dst)+((sz)-1); \
  45. _t_src = (src)+((sz)-1); \
  46. while(_t_sz--) *_t_dst-- = *_t_src--; \
  47. } \
  48. } while(0)
  49. /* add a and b with carry in + out */
  50. #define DSUMc(a,b,c,s) do { \
  51. ErtsDigit ___cr = (c); \
  52. ErtsDigit ___xr = (a)+(___cr); \
  53. ErtsDigit ___yr = (b); \
  54. ___cr = (___xr < ___cr); \
  55. ___xr = ___yr + ___xr; \
  56. ___cr += (___xr < ___yr); \
  57. s = ___xr; \
  58. c = ___cr; \
  59. } while(0)
  60. /* add a and b with carry out */
  61. #define DSUM(a,b,c,s) do { \
  62. ErtsDigit ___xr = (a); \
  63. ErtsDigit ___yr = (b); \
  64. ___xr = ___yr + ___xr; \
  65. s = ___xr; \
  66. c = (___xr < ___yr); \
  67. } while(0)
  68. #define DSUBb(a,b,r,d) do { \
  69. ErtsDigit ___cr = (r); \
  70. ErtsDigit ___xr = (a); \
  71. ErtsDigit ___yr = (b)+___cr; \
  72. ___cr = (___yr < ___cr); \
  73. ___yr = ___xr - ___yr; \
  74. ___cr += (___yr > ___xr); \
  75. d = ___yr; \
  76. r = ___cr; \
  77. } while(0)
  78. #define DSUB(a,b,r,d) do { \
  79. ErtsDigit ___xr = (a); \
  80. ErtsDigit ___yr = (b); \
  81. ___yr = ___xr - ___yr; \
  82. r = (___yr > ___xr); \
  83. d = ___yr; \
  84. } while(0)
  85. /* type a constant as a ErtsDigit - to get shifts correct */
  86. #define DCONST(n) ((ErtsDigit)(n))
  87. /*
  88. * BIG_HAVE_DOUBLE_DIGIT is defined if we have defined
  89. * the type ErtsDoubleDigit which MUST have
  90. * sizeof(ErtsDoubleDigit) >= sizeof(ErtsDigit)
  91. */
  92. #ifdef BIG_HAVE_DOUBLE_DIGIT
  93. /* ErtsDoubleDigit => ErtsDigit */
  94. #define DLOW(x) ((ErtsDigit)(x))
  95. #define DHIGH(x) ((ErtsDigit)(((ErtsDoubleDigit)(x)) >> D_EXP))
  96. /* ErtsDigit => ErtsDoubleDigit */
  97. #define DLOW2HIGH(x) (((ErtsDoubleDigit)(x)) << D_EXP)
  98. #define DDIGIT(a1,a0) (DLOW2HIGH(a1) + (a0))
  99. #define DMULc(a,b,c,p) do { \
  100. ErtsDoubleDigit _t = ((ErtsDoubleDigit)(a))*(b) + (c); \
  101. p = DLOW(_t); \
  102. c = DHIGH(_t); \
  103. } while(0)
  104. #define DMUL(a,b,c1,c0) do { \
  105. ErtsDoubleDigit _t = ((ErtsDoubleDigit)(a))*(b); \
  106. c0 = DLOW(_t); \
  107. c1 = DHIGH(_t); \
  108. } while(0)
  109. #define DDIV(a1,a0,b,q) do { \
  110. ErtsDoubleDigit _t = DDIGIT((a1),(a0)); \
  111. q = _t / (b); \
  112. } while(0)
  113. #define DDIV2(a1,a0,b1,b0,q) do { \
  114. ErtsDoubleDigit _t = DDIGIT((a1),(a0)); \
  115. q = _t / DDIGIT((b1),(b0)); \
  116. } while(0)
  117. #define DREM(a1,a0,b,r) do { \
  118. ErtsDoubleDigit _t = DDIGIT((a1),(a0)); \
  119. r = _t % (b); \
  120. } while(0)
  121. #else
  122. /* If we do not have double digit then we have some more work to do */
  123. #define H_EXP (D_EXP >> 1)
  124. #define LO_MASK ((ErtsDigit)((DCONST(1) << H_EXP)-1))
  125. #define HI_MASK ((ErtsDigit)(LO_MASK << H_EXP))
  126. #define DGT(a,b) ((a)>(b))
  127. #define DEQ(a,b) ((a)==(b))
  128. #define D2GT(a1,a0,b1,b0) (DGT(a1,b1) || (((a1)==(b1)) && DGT(a0,b0)))
  129. #define D2EQ(a1,a0,b1,b0) (DEQ(a1,b1) && DEQ(a0,b0))
  130. #define D2LT(a1,a0,b1,b0) D2GT(b1,b0,a1,a0)
  131. #define D2GTE(a1,a0,b1,b0) (!D2LT(a1,a0,b1,b0))
  132. #define D2LTE(a1,a0,b1,b0) (!D2GT(a1,a0,b1,b0))
  133. /* Add (A+B), A=(a1B+a0) B=(b1B+b0) */
  134. #define D2ADD(a1,a0,b1,b0,c1,c0) do { \
  135. ErtsDigit __ci = 0; \
  136. DSUM(a0,b0,__ci,c0); \
  137. DSUMc(a1,b1,__ci,c1); \
  138. } while(0)
  139. /* Subtract (A-B), A=(a1B+a0), B=(b1B+b0) (A>=B) */
  140. #define D2SUB(a1,a0,b1,b0,c1,c0) do { \
  141. ErtsDigit __bi; \
  142. DSUB(a0,b0,__bi,c0); \
  143. DSUBb(a1,b1,__bi,c1); \
  144. } while(0)
  145. /* Left shift (multiply by 2) (A <<= 1 where A=a1*B+a0) */
  146. #define D2LSHIFT1(a1,a0) do { \
  147. a1 = ((a0) >> (D_EXP-1)) | ((a1)<<1); \
  148. a0 = (a0) << 1; \
  149. } while(0)
  150. /* Right shift (divide by 2) (A >>= 1 where A=a1*B+a0) */
  151. #define D2RSHIFT1(a1,a0) do { \
  152. a0 = (((a1) & 1) << (D_EXP-1)) | ((a0)>>1); \
  153. a1 = ((a1) >> 1); \
  154. } while(0)
  155. /* Calculate a*b + d1 and store double prec result in d1, d0 */
  156. #define DMULc(a,b,d1,d0) do { \
  157. ErtsHalfDigit __a0 = (a); \
  158. ErtsHalfDigit __a1 = ((a) >> H_EXP); \
  159. ErtsHalfDigit __b0 = (b); \
  160. ErtsHalfDigit __b1 = ((b) >> H_EXP); \
  161. ErtsDigit __a0b0 = (ErtsDigit)__a0*__b0; \
  162. ErtsDigit __a0b1 = (ErtsDigit)__a0*__b1; \
  163. ErtsDigit __a1b0 = (ErtsDigit)__a1*__b0; \
  164. ErtsDigit __a1b1 = (ErtsDigit)__a1*__b1; \
  165. ErtsDigit __p0,__p1,__p2,__c0; \
  166. DSUM(__a0b0,d1,__c0,__p0); \
  167. DSUM((__c0<<H_EXP),(__p0>>H_EXP),__p2,__p1); \
  168. DSUM(__p1,__a0b1,__c0,__p1); \
  169. __p2 += __c0; \
  170. DSUM(__p1,__a1b0,__c0,__p1); \
  171. __p2 += __c0; \
  172. DSUM(__p1,__a1b1<<H_EXP,__c0,__p1); \
  173. __p2 += __c0; \
  174. DSUM(__a1b1, (__p2<<H_EXP),__c0,__p2); \
  175. d1 = (__p2 & HI_MASK) | (__p1 >> H_EXP); \
  176. d0 = (__p1 << H_EXP) | (__p0 & LO_MASK); \
  177. } while(0)
  178. #define DMUL(a,b,d1,d0) do { \
  179. ErtsDigit _ds = 0; \
  180. DMULc(a,b,_ds,d0); \
  181. d1 = _ds; \
  182. } while(0)
  183. /* Calculate a*(Bb1 + b0) + d2 = a*b1B + a*b0 + d2 */
  184. #define D2MULc(a,b1,b0,d2,d1,d0) do { \
  185. DMULc(a, b0, d2, d0); \
  186. DMULc(a, b1, d2, d1); \
  187. } while(0)
  188. /* Calculate s in a = 2^s*a1 */
  189. /* NOTE since D2PF is used by other macros variables is prefixed bt __ */
  190. #if D_EXP == 64
  191. #define D2PF(a, s) do { \
  192. ErtsDigit __x = (a); \
  193. int __s = 0; \
  194. if (__x <= 0x00000000FFFFFFFF) { __s += 32; __x <<= 32; } \
  195. if (__x <= 0x0000FFFFFFFFFFFF) { __s += 16; __x <<= 16; } \
  196. if (__x <= 0x00FFFFFFFFFFFFFF) { __s += 8; __x <<= 8; } \
  197. if (__x <= 0x0FFFFFFFFFFFFFFF) { __s += 4; __x <<= 4; } \
  198. if (__x <= 0x3FFFFFFFFFFFFFFF) { __s += 2; __x <<= 2; } \
  199. if (__x <= 0x7FFFFFFFFFFFFFFF) { __s += 1; } \
  200. s = __s; \
  201. } while(0)
  202. #elif D_EXP == 32
  203. #define D2PF(a, s) do { \
  204. ErtsDigit __x = (a); \
  205. int __s = 0; \
  206. if (__x <= 0x0000FFFF) { __s += 16; __x <<= 16; } \
  207. if (__x <= 0x00FFFFFF) { __s += 8; __x <<= 8; } \
  208. if (__x <= 0x0FFFFFFF) { __s += 4; __x <<= 4; } \
  209. if (__x <= 0x3FFFFFFF) { __s += 2; __x <<= 2; } \
  210. if (__x <= 0x7FFFFFFF) { __s += 1; } \
  211. s = __s; \
  212. } while(0)
  213. #elif D_EXP == 16
  214. #define D2PF(a, s) do { \
  215. ErtsDigit __x = (a); \
  216. int __s = 0; \
  217. if (__x <= 0x00FF) { __s += 8; __x <<= 8; } \
  218. if (__x <= 0x0FFF) { __s += 4; __x <<= 4; } \
  219. if (__x <= 0x3FFF) { __s += 2; __x <<= 2; } \
  220. if (__x <= 0x7FFF) { __s += 1; } \
  221. s = __s; \
  222. } while(0)
  223. #elif D_EXP == 8
  224. #define D2PF(a, s) do { \
  225. ErtsDigit __x = (a); \
  226. int __s = 0; \
  227. if (__x <= 0x0F) { __s += 4; __x <<= 4; } \
  228. if (__x <= 0x3F) { __s += 2; __x <<= 2; } \
  229. if (__x <= 0x7F) { __s += 1; } \
  230. s = _s; \
  231. } while(0)
  232. #endif
  233. /* Calculate q = (a1B + a0) / b, assume a1 < b */
  234. #define DDIVREM(a1,a0,b,q,r) do { \
  235. ErtsDigit _a1 = (a1); \
  236. ErtsDigit _a0 = (a0); \
  237. ErtsDigit _b = (b); \
  238. ErtsHalfDigit _un1, _un0; \
  239. ErtsHalfDigit _vn1, _vn0; \
  240. ErtsDigit _q1, _q0; \
  241. ErtsDigit _un32, _un21, _un10; \
  242. ErtsDigit _rh; \
  243. Sint _s; \
  244. D2PF(_b, _s); \
  245. _b = _b << _s; \
  246. _vn1 = _b >> H_EXP; \
  247. _vn0 = _b & LO_MASK; \
  248. /* If needed to avoid undefined behaviour */ \
  249. if (_s) _un32 = (_a1 << _s) | ((_a0>>(D_EXP-_s)) & (-_s >> (D_EXP-1))); \
  250. else _un32 = _a1; \
  251. _un10 = _a0 << _s; \
  252. _un1 = _un10 >> H_EXP; \
  253. _un0 = _un10 & LO_MASK; \
  254. _q1 = _un32/_vn1; \
  255. _rh = _un32 - _q1*_vn1; \
  256. while ((_q1 >= (DCONST(1)<<H_EXP))||(_q1*_vn0 > (_rh<<H_EXP)+_un1)) { \
  257. _q1--; \
  258. _rh += _vn1; \
  259. if (_rh >= (DCONST(1)<<H_EXP)) break; \
  260. } \
  261. _un21 = (_un32<<H_EXP) + _un1 - _q1*_b; \
  262. _q0 = _un21/_vn1; \
  263. _rh = _un21 - _q0*_vn1; \
  264. while ((_q0 >= (DCONST(1)<<H_EXP))||(_q0*_vn0 > ((_rh<<H_EXP)+_un0))) { \
  265. _q0--; \
  266. _rh += _vn1; \
  267. if (_rh >= (DCONST(1)<<H_EXP)) break; \
  268. } \
  269. r = ((_un21<<H_EXP) + _un0 - _q0*_b) >> _s; \
  270. q = (_q1<<H_EXP) + _q0; \
  271. } while(0)
  272. /* divide any a=(a1*B + a0) with b */
  273. #define DDIVREM2(a1,a0,b,q1,q0,r) do { \
  274. ErtsDigit __a1 = (a1); \
  275. ErtsDigit __b = (b); \
  276. q1 = __a1 / __b; \
  277. DDIVREM(__a1 % __b, (a0), __b, q0, r); \
  278. } while(0)
  279. /* Calculate q = (a1B + a0) % b */
  280. #define DREM(a1,a0,b,r) do { \
  281. ErtsDigit __a1 = (a1); \
  282. ErtsDigit __b = (b); \
  283. ERTS_DECLARE_DUMMY(ErtsDigit __q0); \
  284. DDIVREM((__a1 % __b), (a0), __b, __q0, r); \
  285. } while(0)
  286. #define DDIV(a1,a0,b,q) do { \
  287. ERTS_DECLARE_DUMMY(ErtsDigit _tmp); \
  288. DDIVREM(a1,a0,b,q,_tmp); \
  289. } while(0)
  290. /* Calculate q, r A = Bq+R when, assume A1 >= B */
  291. #if (SIZEOF_VOID_P == 8)
  292. #define QUOT_LIM 0x7FFFFFFFFFFFFFFF
  293. #else
  294. #define QUOT_LIM 0x7FFFFFFF
  295. #endif
  296. #define D2DIVREM(a1,a0,b1,b0,q0,r1,r0) do { \
  297. ErtsDigit _a1 = (a1); \
  298. ErtsDigit _a0 = (a0); \
  299. ErtsDigit _b1 = (b1); \
  300. ErtsDigit _b0 = (b0); \
  301. ErtsDigit _q = 0; \
  302. int _as = 1; \
  303. while(D2GTE(_a1,_a0,_b1,_b0)) { \
  304. ErtsDigit _q1; \
  305. ErtsDigit _t2=0, _t1, _t0; \
  306. if ((_b1 == 1) && (_a1 > 1)) \
  307. _q1 = _a1 / 2; \
  308. else if ((_a1 > QUOT_LIM) && (_b1 < _a1)) \
  309. _q1 = _a1/(_b1+1); \
  310. else \
  311. _q1 = _a1/_b1; \
  312. if (_as<0) \
  313. _q -= _q1; \
  314. else \
  315. _q += _q1; \
  316. D2MULc(_q1, _b1, _b0, _t2, _t1, _t0); \
  317. ASSERT(_t2 == 0); \
  318. if (D2GT(_t1,_t0,_a1,_a0)) { \
  319. D2SUB(_t1,_t0,_a1,_a0,_a1,_a0); \
  320. _as = -_as; \
  321. } \
  322. else { \
  323. D2SUB(_a1,_a0,_t1,_t0,_a1,_a0); \
  324. } \
  325. } \
  326. if (_as < 0) { \
  327. _q--; \
  328. D2SUB(_b1,_b0,_a1,_a0,_a1,_a0); \
  329. } \
  330. q0 = _q; \
  331. r1 = _a1; \
  332. r0 = _a0; \
  333. } while(0)
  334. /* Calculate q, r A = Bq+R when assume B>0 */
  335. #define D2DIVREM_0(a1,a0,b1,b0,q1,q0,r1,r0) do { \
  336. ErtsDigit _a1 = (a1); \
  337. ErtsDigit _a0 = (a0); \
  338. ErtsDigit _b1 = (b1); \
  339. ErtsDigit _b0 = (b0); \
  340. if (D2EQ(_a1,_a0,0,0)) { \
  341. q1 = q0 = 0; \
  342. r1 = r0 = 0; \
  343. } \
  344. else { \
  345. ErtsDigit _res1 = 0; \
  346. ErtsDigit _res0 = 0; \
  347. ErtsDigit _d1 = 0; \
  348. ErtsDigit _d0 = 1; \
  349. ErtsDigit _e1 = (1 << (D_EXP-1)); \
  350. ErtsDigit _e0 = 0; \
  351. while(_e1 && !(_a1 & _e1)) \
  352. _e1 >>= 1; \
  353. if (_e1 == 0) { \
  354. _e0 = (1 << (D_EXP-1)); \
  355. while(_e0 && !(_a0 & _e0)) \
  356. _e0 >>= 1; \
  357. } \
  358. if (D2GT(_b1,_b0,0,0)) { \
  359. while(D2GT(_e1,_e0,_b1,_b0)) { \
  360. D2LSHIFT1(_b1,_b0); \
  361. D2LSHIFT1(_d1,_d0); \
  362. } \
  363. } \
  364. do { \
  365. if (!D2GT(_b1,_b0,_a1,_a0)) { \
  366. D2SUB(_a1,_a0, _b1, _b0, _a1, _a0); \
  367. D2ADD(_d1,_d0, _res1,_res0, _res1, _res0); \
  368. } \
  369. D2RSHIFT1(_b1,_b0); \
  370. D2RSHIFT1(_d1,_d0); \
  371. } while (!D2EQ(_d1,_d0,0,0)); \
  372. r1 = _a1; \
  373. r0 = _a0; \
  374. q1 = _res1; \
  375. q0 = _res0; \
  376. } \
  377. } while(0)
  378. #define DDIV2(a1,a0,b1,b0,q) do { \
  379. ERTS_DECLARE_DUMMY(ErtsDigit _tmp_r1); \
  380. ERTS_DECLARE_DUMMY(ErtsDigit _tmp_r0); \
  381. D2DIVREM(a1,a0,b1,b0,q,_tmp_r1,_tmp_r0); \
  382. } while(0)
  383. #endif
  384. /* Forward declaration of lookup tables (See below in this file) used in list to
  385. * integer conversions for different bases. Also used in bignum printing.
  386. */
  387. static const byte digits_per_sint_lookup[36-1];
  388. static const byte digits_per_small_lookup[36-1];
  389. static const Sint largest_power_of_base_lookup[36-1];
  390. static const double lg2_lookup[36-1];
  391. static ERTS_INLINE byte get_digits_per_signed_int(Uint base) {
  392. return digits_per_sint_lookup[base-2];
  393. }
  394. static ERTS_INLINE byte get_digits_per_small(Uint base) {
  395. return digits_per_small_lookup[base-2];
  396. }
  397. static ERTS_INLINE Sint get_largest_power_of_base(Uint base) {
  398. return largest_power_of_base_lookup[base-2];
  399. }
  400. static ERTS_INLINE double lookup_log2(Uint base) {
  401. return lg2_lookup[base - 2];
  402. }
  403. /*
  404. ** compare two number vectors
  405. */
  406. static int I_comp(ErtsDigit* x, dsize_t xl, ErtsDigit* y, dsize_t yl)
  407. {
  408. if (xl < yl)
  409. return -1;
  410. else if (xl > yl)
  411. return 1;
  412. else {
  413. if (x == y)
  414. return 0;
  415. x += (xl-1);
  416. y += (yl-1);
  417. while((xl > 0) && (*x == *y)) {
  418. x--;
  419. y--;
  420. xl--;
  421. }
  422. if (xl == 0)
  423. return 0;
  424. return (*x < *y) ? -1 : 1;
  425. }
  426. }
  427. /*
  428. ** Add digits in x and y and store them in r
  429. ** assumption: (xl >= yl)
  430. */
  431. static dsize_t I_add(ErtsDigit* x, dsize_t xl, ErtsDigit* y, dsize_t yl, ErtsDigit* r)
  432. {
  433. dsize_t sz = xl;
  434. register ErtsDigit yr, xr;
  435. register ErtsDigit c = 0;
  436. ASSERT(xl >= yl);
  437. xl -= yl;
  438. do {
  439. xr = *x++ + c;
  440. yr = *y++;
  441. c = (xr < c);
  442. xr = yr + xr;
  443. c += (xr < yr);
  444. *r++ = xr;
  445. } while(--yl);
  446. while(xl--) {
  447. xr = *x++ + c;
  448. c = (xr < c);
  449. *r++ = xr;
  450. }
  451. if (c) {
  452. *r = 1;
  453. return sz+1;
  454. }
  455. return sz;
  456. }
  457. /*
  458. ** Add a digits in v1 and store result in vr
  459. */
  460. static dsize_t D_add(ErtsDigit* x, dsize_t xl, ErtsDigit c, ErtsDigit* r)
  461. {
  462. dsize_t sz = xl;
  463. register ErtsDigit xr;
  464. while(xl--) {
  465. xr = *x++ + c;
  466. c = (xr < c);
  467. *r++ = xr;
  468. }
  469. if (c) {
  470. *r = 1;
  471. return sz+1;
  472. }
  473. return sz;
  474. }
  475. /*
  476. ** Subtract digits v2 from v1 and store result in v3
  477. ** Assert I_comp(x, xl, y, yl) >= 0
  478. **
  479. */
  480. static dsize_t I_sub(ErtsDigit* x, dsize_t xl, ErtsDigit* y, dsize_t yl, ErtsDigit* r)
  481. {
  482. ErtsDigit* r0 = r;
  483. register ErtsDigit yr, xr;
  484. register ErtsDigit c = 0;
  485. ASSERT(I_comp(x, xl, y, yl) >= 0);
  486. xl -= yl;
  487. do {
  488. yr = *y++ + c;
  489. xr = *x++;
  490. c = (yr < c);
  491. yr = xr - yr;
  492. c += (yr > xr);
  493. *r++ = yr;
  494. } while(--yl);
  495. while(xl--) {
  496. xr = *x++;
  497. yr = xr - c;
  498. c = (yr > xr);
  499. *r++ = yr;
  500. }
  501. do {
  502. r--;
  503. } while(*r == 0 && r != r0);
  504. return (r - r0) + 1;
  505. }
  506. /*
  507. ** Subtract digit d from v1 and store result in vr
  508. */
  509. static dsize_t D_sub(ErtsDigit* x, dsize_t xl, ErtsDigit c, ErtsDigit* r)
  510. {
  511. ErtsDigit* r0 = r;
  512. register ErtsDigit yr, xr;
  513. ASSERT(I_comp(x, xl, x, 1) >= 0);
  514. while(xl--) {
  515. xr = *x++;
  516. yr = xr - c;
  517. c = (yr > xr);
  518. *r++ = yr;
  519. }
  520. do {
  521. r--;
  522. } while(*r == 0 && r != r0);
  523. return (r - r0) + 1;
  524. }
  525. /*
  526. ** subtract Z000...0 - y and store result in r, return new size
  527. */
  528. static dsize_t Z_sub(ErtsDigit* y, dsize_t yl, ErtsDigit* r)
  529. {
  530. ErtsDigit* r0 = r;
  531. register ErtsDigit yr;
  532. register ErtsDigit c = 0;
  533. while(yl--) {
  534. yr = *y++ + c;
  535. c = (yr < c);
  536. yr = 0 - yr;
  537. c += (yr > 0);
  538. *r++ = yr;
  539. }
  540. do {
  541. r--;
  542. } while(*r == 0 && r != r0);
  543. return (r - r0) + 1;
  544. }
  545. /*
  546. ** Multiply digits in x with digits in y and store in r
  547. ** Assumption: digits in r must be 0 (upto the size of x)
  548. */
  549. static dsize_t I_mul(ErtsDigit* x, dsize_t xl, ErtsDigit* y, dsize_t yl, ErtsDigit* r)
  550. {
  551. ErtsDigit* r0 = r;
  552. ErtsDigit* rt = r;
  553. while(xl--) {
  554. ErtsDigit cp = 0;
  555. ErtsDigit c = 0;
  556. dsize_t n = yl;
  557. ErtsDigit* yt = y;
  558. ErtsDigit d;
  559. ErtsDigit p;
  560. d = *x;
  561. x++;
  562. rt = r;
  563. switch(d) {
  564. case 0:
  565. rt = rt + n;
  566. break;
  567. case 1:
  568. while(n--) {
  569. DSUMc(*yt, *rt, c, p);
  570. *rt++ = p;
  571. yt++;
  572. }
  573. break;
  574. case 2:
  575. while(n--) {
  576. p = *yt;
  577. DSUMc(p, p, cp, p);
  578. DSUMc(p, *rt, c, p);
  579. *rt++ = p;
  580. yt++;
  581. }
  582. break;
  583. default:
  584. while(n--) {
  585. DMULc(d,*yt, cp, p);
  586. DSUMc(p,*rt, c, p);
  587. *rt++ = p;
  588. yt++;
  589. }
  590. break;
  591. }
  592. *rt = c + cp;
  593. r++;
  594. }
  595. if (*rt == 0)
  596. return (rt - r0);
  597. else
  598. return (rt - r0) + 1;
  599. }
  600. /*
  601. ** Square digits in x store in r (x & r may point into a common area)
  602. ** Assumption: x is destroyed if common area and digits in r are zero
  603. ** to the size of xl+1
  604. */
  605. static dsize_t I_sqr(ErtsDigit* x, dsize_t xl, ErtsDigit* r)
  606. {
  607. ErtsDigit d;
  608. ErtsDigit* r0 = r;
  609. ErtsDigit* s = r;
  610. if ((r + xl) == x) /* "Inline" operation */
  611. *x = 0;
  612. while(xl--) {
  613. ErtsDigit* y;
  614. ErtsDigit y_0 = 0, y_1 = 0, y_2 = 0, y_3 = 0;
  615. ErtsDigit b0, b1;
  616. ErtsDigit z0, z1, z2;
  617. ErtsDigit t;
  618. dsize_t y_l = xl;
  619. d = *x;
  620. x++;
  621. y = x;
  622. s = r;
  623. DMUL(d, d, b1, b0);
  624. DSUMc(*s, b0, y_3, t);
  625. *s++ = t;
  626. z1 = b1;
  627. while(y_l--) {
  628. DMUL(d, *y, b1, b0);
  629. y++;
  630. DSUMc(b0, b0, y_0, z0);
  631. DSUMc(z0, z1, y_2, z2);
  632. DSUMc(*s, z2, y_3, t);
  633. *s++ = t;
  634. DSUMc(b1, b1, y_1, z1);
  635. }
  636. z0 = y_0;
  637. DSUMc(z0, z1, y_2, z2);
  638. DSUMc(*s, z2, y_3, t);
  639. *s = t;
  640. if (xl != 0) {
  641. s++;
  642. t = (y_1+y_2+y_3);
  643. *s = t;
  644. r += 2;
  645. }
  646. else {
  647. ASSERT((y_1+y_2+y_3) == 0);
  648. }
  649. }
  650. if (*s == 0)
  651. return (s - r0);
  652. else
  653. return (s - r0) + 1;
  654. }
  655. /*
  656. ** Multiply digits d with digits in x and store in r
  657. */
  658. static dsize_t D_mul(ErtsDigit* x, dsize_t xl, ErtsDigit d, ErtsDigit* r)
  659. {
  660. ErtsDigit c = 0;
  661. dsize_t rl = xl;
  662. ErtsDigit p;
  663. switch(d) {
  664. case 0:
  665. ZERO_DIGITS(r, 1);
  666. return 1;
  667. case 1:
  668. if (x != r)
  669. MOVE_DIGITS(r, x, xl);
  670. return xl;
  671. case 2:
  672. while(xl--) {
  673. p = *x;
  674. DSUMc(p, p, c, p);
  675. *r++ = p;
  676. x++;
  677. }
  678. break;
  679. default:
  680. while(xl--) {
  681. DMULc(d, *x, c, p);
  682. *r++ = p;
  683. x++;
  684. }
  685. break;
  686. }
  687. if (c == 0)
  688. return rl;
  689. *r = c;
  690. return rl+1;
  691. }
  692. /*
  693. ** Multiply and subtract
  694. ** calculate r(i) = x(i) - d*y(i)
  695. ** assumption: xl = yl || xl == yl+1
  696. **
  697. ** Return size of r
  698. ** 0 means borrow
  699. */
  700. static dsize_t D_mulsub(ErtsDigit* x, dsize_t xl, ErtsDigit d,
  701. ErtsDigit* y, dsize_t yl, ErtsDigit* r)
  702. {
  703. ErtsDigit c = 0;
  704. ErtsDigit b = 0;
  705. ErtsDigit c0;
  706. ErtsDigit* r0 = r;
  707. ErtsDigit s;
  708. ASSERT(xl == yl || xl == yl+1);
  709. xl -= yl;
  710. while(yl--) {
  711. DMULc(d, *y, c, c0);
  712. DSUBb(*x, c0, b, s);
  713. *r++ = s;
  714. x++;
  715. y++;
  716. }
  717. if (xl == 0) {
  718. if (c != 0 || b != 0)
  719. return 0;
  720. }
  721. else { /* xl == 1 */
  722. DSUBb(*x, c, b, s);
  723. *r++ = s;
  724. }
  725. if (b != 0) return 0;
  726. do {
  727. r--;
  728. } while(*r == 0 && r != r0);
  729. return (r - r0) + 1;
  730. }
  731. /*
  732. ** Divide digits in x with a digit,
  733. ** quotient is returned in q and remainder digit in r
  734. ** x and q may be equal
  735. */
  736. static dsize_t D_div(ErtsDigit* x, dsize_t xl, ErtsDigit d, ErtsDigit* q, ErtsDigit* r)
  737. {
  738. ErtsDigit* xp = x + (xl-1);
  739. ErtsDigit* qp = q + (xl-1);
  740. dsize_t qsz = xl;
  741. ErtsDigit a1;
  742. a1 = *xp;
  743. xp--;
  744. if (d > a1) {
  745. if (xl == 1) {
  746. *r = a1;
  747. *qp = 0;
  748. return 1;
  749. }
  750. qsz--;
  751. qp--;
  752. }
  753. do {
  754. ErtsDigit q0, a0, b0;
  755. ERTS_DECLARE_DUMMY(ErtsDigit b);
  756. ERTS_DECLARE_DUMMY(ErtsDigit b1);
  757. if (d > a1) {
  758. a0 = *xp;
  759. xp--;
  760. }
  761. else {
  762. a0 = a1; a1 = 0;
  763. }
  764. DDIV(a1, a0, d, q0);
  765. DMUL(d, q0, b1, b0);
  766. DSUB(a0,b0, b, a1);
  767. *qp = q0;
  768. qp--;
  769. } while (xp >= x);
  770. *r = a1;
  771. return qsz;
  772. }
  773. /*
  774. ** Divide digits in x with digits in y and return qutient in q
  775. ** and remainder in r
  776. ** assume that integer(x) > integer(y)
  777. ** Return remainder in x (length int rl)
  778. ** Return quotient size
  779. */
  780. static dsize_t I_div(ErtsDigit* x, dsize_t xl, ErtsDigit* y, dsize_t yl,
  781. ErtsDigit* q, ErtsDigit* r, dsize_t* rlp)
  782. {
  783. ErtsDigit* rp;
  784. ErtsDigit* qp;
  785. ErtsDigit b1 = y[yl-1];
  786. ErtsDigit b2 = y[yl-2];
  787. ErtsDigit a1;
  788. ErtsDigit a2;
  789. int r_signed = 0;
  790. dsize_t ql;
  791. dsize_t rl;
  792. if (x != r)
  793. MOVE_DIGITS(r, x, xl);
  794. rp = r + (xl-yl);
  795. rl = xl;
  796. ZERO_DIGITS(q, xl-yl+1);
  797. qp = q + (xl-yl);
  798. ql = 0;
  799. /* Adjust length */
  800. a1 = rp[yl-1];
  801. a2 = rp[yl-2];
  802. if (b1 < a1 || (b1 == a1 && b2 <= a2))
  803. ql = 1;
  804. do {
  805. ErtsDigit q0;
  806. dsize_t nsz = yl;
  807. dsize_t nnsz;
  808. a1 = rp[yl-1];
  809. a2 = rp[yl-2];
  810. if (b1 < a1)
  811. DDIV2(a1,a2,b1,b2,q0);
  812. else if (b1 > a1) {
  813. DDIV(a1,a2,b1,q0);
  814. nsz++;
  815. rp--;
  816. qp--;
  817. ql++;
  818. }
  819. else { /* (b1 == a1) */
  820. if (b2 <= a2)
  821. q0 = 1;
  822. else {
  823. q0 = D_MASK;
  824. nsz++;
  825. rp--;
  826. qp--;
  827. ql++;
  828. }
  829. }
  830. if (r_signed)
  831. ql = D_sub(qp, ql, q0, qp);
  832. else
  833. ql = D_add(qp, ql, q0, qp);
  834. if ((nnsz = D_mulsub(rp, nsz, q0, y, yl, rp)) == 0) {
  835. nnsz = Z_sub(r, rl, r);
  836. if (nsz > (rl-nnsz))
  837. nnsz = nsz - (rl-nnsz);
  838. else
  839. nnsz = 1;
  840. r_signed = !r_signed;
  841. }
  842. if ((nnsz == 1) && (*rp == 0))
  843. nnsz = 0;
  844. rp = rp - (yl-nnsz);
  845. rl -= (nsz-nnsz);
  846. qp = qp - (yl-nnsz);
  847. ql += (yl-nnsz);
  848. } while (I_comp(r, rl, y, yl) >= 0);
  849. ql -= (q - qp);
  850. qp = q;
  851. if (rl == 0)
  852. rl = 1;
  853. while(rl > 1 && r[rl-1] == 0) /* Remove "trailing zeroes" */
  854. --rl;
  855. if (r_signed && (rl > 1 || *r != 0)) {
  856. rl = I_sub(y, yl, r, rl, r);
  857. ql = D_sub(qp, ql, 1, qp);
  858. }
  859. *rlp = rl;
  860. return ql;
  861. }
  862. /*
  863. ** Remainder of digits in x and a digit d
  864. */
  865. static ErtsDigit D_rem(ErtsDigit* x, dsize_t xl, ErtsDigit d)
  866. {
  867. ErtsDigit rem = 0;
  868. x += (xl-1);
  869. do {
  870. if (rem != 0)
  871. DREM(rem, *x, d, rem);
  872. else
  873. DREM(0, *x, d, rem);
  874. x--;
  875. xl--;
  876. } while(xl > 0);
  877. return rem;
  878. }
  879. /*
  880. ** Remainder of x and y
  881. **
  882. ** Assumtions: xl >= yl, yl > 1
  883. ** r must contain at least xl number of digits
  884. */
  885. static dsize_t I_rem(ErtsDigit* x, dsize_t xl, ErtsDigit* y, dsize_t yl, ErtsDigit* r)
  886. {
  887. ErtsDigit* rp;
  888. ErtsDigit b1 = y[yl-1];
  889. ErtsDigit b2 = y[yl-2];
  890. ErtsDigit a1;
  891. ErtsDigit a2;
  892. int r_signed = 0;
  893. dsize_t rl;
  894. if (x != r)
  895. MOVE_DIGITS(r, x, xl);
  896. rp = r + (xl-yl);
  897. rl = xl;
  898. do {
  899. ErtsDigit q0;
  900. dsize_t nsz = yl;
  901. dsize_t nnsz;
  902. a1 = rp[yl-1];
  903. a2 = rp[yl-2];
  904. if (b1 < a1)
  905. DDIV2(a1,a2,b1,b2,q0);
  906. else if (b1 > a1) {
  907. DDIV(a1,a2,b1,q0);
  908. nsz++;
  909. rp--;
  910. }
  911. else { /* (b1 == a1) */
  912. if (b2 <= a2)
  913. q0 = 1;
  914. else {
  915. q0 = D_MASK;
  916. nsz++;
  917. rp--;
  918. }
  919. }
  920. if ((nnsz = D_mulsub(rp, nsz, q0, y, yl, rp)) == 0) {
  921. nnsz = Z_sub(r, rl, r);
  922. if (nsz > (rl-nnsz))
  923. nnsz = nsz - (rl-nnsz);
  924. else
  925. nnsz = 1;
  926. r_signed = !r_signed;
  927. }
  928. if (nnsz == 1 && *rp == 0)
  929. nnsz = 0;
  930. rp = rp - (yl-nnsz);
  931. rl -= (nsz-nnsz);
  932. } while (I_comp(r, rl, y, yl) >= 0);
  933. if (rl == 0)
  934. rl = 1;
  935. while(rl > 1 && r[rl-1] == 0) /* Remove "trailing zeroes" */
  936. --rl;
  937. if (r_signed && (rl > 1 || *r != 0))
  938. rl = I_sub(y, yl, r, rl, r);
  939. return rl;
  940. }
  941. /*
  942. ** Remove trailing digits from bitwise operations
  943. */
  944. static dsize_t I_btrail(ErtsDigit* r0, ErtsDigit* r, short sign)
  945. {
  946. /* convert negative numbers to one complement */
  947. if (sign) {
  948. dsize_t rl;
  949. ErtsDigit d;
  950. /* 1 remove all 0xffff words */
  951. do {
  952. r--;
  953. } while(((d = *r) == D_MASK) && (r != r0));
  954. /* 2 complement high digit */
  955. if (d == D_MASK)
  956. *r = 0;
  957. else {
  958. ErtsDigit prev_mask = 0;
  959. ErtsDigit mask = (DCONST(1) << (D_EXP-1));
  960. while((d & mask) == mask) {
  961. prev_mask = mask;
  962. mask = (prev_mask >> 1) | (DCONST(1)<<(D_EXP-1));
  963. }
  964. *r = ~d & ~prev_mask;
  965. }
  966. rl = (r - r0) + 1;
  967. while(r != r0) {
  968. r--;
  969. *r = ~*r;
  970. }
  971. return D_add(r0, rl, 1, r0);
  972. }
  973. do {
  974. r--;
  975. } while(*r == 0 && r != r0);
  976. return (r - r0) + 1;
  977. }
  978. /*
  979. ** Bitwise and
  980. */
  981. static dsize_t I_band(ErtsDigit* x, dsize_t xl, short xsgn,
  982. ErtsDigit* y, dsize_t yl, short ysgn, ErtsDigit* r)
  983. {
  984. ErtsDigit* r0 = r;
  985. short sign = xsgn && ysgn;
  986. ASSERT(xl >= yl);
  987. xl -= yl;
  988. if (!xsgn) {
  989. if (!ysgn) {
  990. while(yl--)
  991. *r++ = *x++ & *y++;
  992. }
  993. else {
  994. ErtsDigit b;
  995. ErtsDigit c;
  996. DSUB(*y,1,b,c);
  997. *r++ = *x++ & ~c;
  998. y++;
  999. yl--;
  1000. while(yl--) {
  1001. DSUBb(*y,0,b,c);
  1002. *r++ = *x++ & ~c;
  1003. y++;
  1004. }
  1005. while (xl--) {
  1006. *r++ = *x++;
  1007. }
  1008. }
  1009. }
  1010. else {
  1011. if (!ysgn) {
  1012. ErtsDigit b;
  1013. ErtsDigit c;
  1014. DSUB(*x,1,b,c);
  1015. *r = ~c & *y;
  1016. x++; y++; r++;
  1017. yl--;
  1018. while(yl--) {
  1019. DSUBb(*x,0,b,c);
  1020. *r++ = ~c & *y++;
  1021. x++;
  1022. }
  1023. }
  1024. else {
  1025. ErtsDigit b1, b2;
  1026. ErtsDigit c1, c2;
  1027. DSUB(*x,1,b1,c1);
  1028. DSUB(*y,1,b2,c2);
  1029. *r++ = ~c1 & ~c2;
  1030. x++; y++;
  1031. yl--;
  1032. while(yl--) {
  1033. DSUBb(*x,0,b1,c1);
  1034. DSUBb(*y,0,b2,c2);
  1035. *r++ = ~c1 & ~c2;
  1036. x++; y++;
  1037. }
  1038. while(xl--) {
  1039. DSUBb(*x,0,b1,c1);
  1040. *r++ = ~c1;
  1041. x++;
  1042. }
  1043. }
  1044. }
  1045. return I_btrail(r0, r, sign);
  1046. }
  1047. /*
  1048. * Bitwise 'or'.
  1049. */
  1050. static dsize_t
  1051. I_bor(ErtsDigit* x, dsize_t xl, short xsgn, ErtsDigit* y,
  1052. dsize_t yl, short ysgn, ErtsDigit* r)
  1053. {
  1054. ErtsDigit* r0 = r;
  1055. short sign = xsgn || ysgn;
  1056. ASSERT(xl >= yl);
  1057. xl -= yl;
  1058. if (!xsgn) {
  1059. if (!ysgn) {
  1060. while(yl--)
  1061. *r++ = *x++ | *y++;
  1062. while(xl--)
  1063. *r++ = *x++;
  1064. }
  1065. else {
  1066. ErtsDigit b;
  1067. ErtsDigit c;
  1068. DSUB(*y,1,b,c);
  1069. *r++ = *x++ | ~c;
  1070. y++;
  1071. yl--;
  1072. while(yl--) {
  1073. DSUBb(*y,0,b,c);
  1074. *r++ = *x++ | ~c;
  1075. y++;
  1076. }
  1077. }
  1078. }
  1079. else {
  1080. if (!ysgn) {
  1081. ErtsDigit b;
  1082. ErtsDigit c;
  1083. DSUB(*x,1,b,c);
  1084. *r++ = ~c | *y++;
  1085. x++;
  1086. yl--;
  1087. while(yl--) {
  1088. DSUBb(*x,0,b,c);
  1089. *r++ = ~c | *y++;
  1090. x++;
  1091. }
  1092. while(xl--) {
  1093. DSUBb(*x,0,b,c);
  1094. *r++ = ~c;
  1095. x++;
  1096. }
  1097. }
  1098. else {
  1099. ErtsDigit b1, b2;
  1100. ErtsDigit c1, c2;
  1101. DSUB(*x,1,b1,c1);
  1102. DSUB(*y,1,b2,c2);
  1103. *r++ = ~c1 | ~c2;
  1104. x++; y++;
  1105. yl--;
  1106. while(yl--) {
  1107. DSUBb(*x,0,b1,c1);
  1108. DSUBb(*y,0,b2,c2);
  1109. *r++ = ~c1 | ~c2;
  1110. x++; y++;
  1111. }
  1112. }
  1113. }
  1114. return I_btrail(r0, r, sign);
  1115. }
  1116. /*
  1117. ** Bitwise xor
  1118. */
  1119. static dsize_t I_bxor(ErtsDigit* x, dsize_t xl, short xsgn,
  1120. ErtsDigit* y, dsize_t yl, short ysgn, ErtsDigit* r)
  1121. {
  1122. ErtsDigit* r0 = r;
  1123. short sign = xsgn != ysgn;
  1124. ASSERT(xl >= yl);
  1125. xl -= yl;
  1126. if (!xsgn) {
  1127. if (!ysgn) {
  1128. while(yl--)
  1129. *r++ = *x++ ^ *y++;
  1130. while(xl--)
  1131. *r++ = *x++;
  1132. }
  1133. else {
  1134. ErtsDigit b;
  1135. ErtsDigit c;
  1136. DSUB(*y,1,b,c);
  1137. *r++ = *x++ ^ ~c;
  1138. y++;
  1139. yl--;
  1140. while(yl--) {
  1141. DSUBb(*y,0,b,c);
  1142. *r++ = *x++ ^ ~c;
  1143. y++;
  1144. }
  1145. while(xl--)
  1146. *r++ = ~*x++;
  1147. }
  1148. }
  1149. else {
  1150. if (!ysgn) {
  1151. ErtsDigit b;
  1152. ErtsDigit c;
  1153. DSUB(*x,1,b,c);
  1154. *r++ = ~c ^ *y++;
  1155. x++;
  1156. yl--;
  1157. while(yl--) {
  1158. DSUBb(*x,0,b,c);
  1159. *r++ = ~c ^ *y++;
  1160. x++;
  1161. }
  1162. while(xl--) {
  1163. DSUBb(*x,0,b,c);
  1164. *r++ = ~c;
  1165. x++;
  1166. }
  1167. }
  1168. else {
  1169. ErtsDigit b1, b2;
  1170. ErtsDigit c1, c2;
  1171. DSUB(*x,1,b1,c1);
  1172. DSUB(*y,1,b2,c2);
  1173. *r++ = ~c1 ^ ~c2;
  1174. x++; y++;
  1175. yl--;
  1176. while(yl--) {
  1177. DSUBb(*x,0,b1,c1);
  1178. DSUBb(*y,0,b2,c2);
  1179. *r++ = ~c1 ^ ~c2;
  1180. x++; y++;
  1181. }
  1182. while(xl--) {
  1183. DSUBb(*x,0,b1,c1);
  1184. *r++ = c1;
  1185. x++;
  1186. }
  1187. }
  1188. }
  1189. return I_btrail(r0, r, sign);
  1190. }
  1191. /*
  1192. ** Bitwise not simulated as
  1193. ** bnot -X == (X - 1)
  1194. ** bnot +X == -(X + 1)
  1195. */
  1196. static dsize_t I_bnot(ErtsDigit* x, dsize_t xl, short xsgn, ErtsDigit* r)
  1197. {
  1198. if (xsgn)
  1199. return D_add(x, xl, 1, r);
  1200. else
  1201. return D_sub(x, xl, 1, r);
  1202. }
  1203. /*
  1204. ** Arithmetic left shift or right
  1205. */
  1206. static dsize_t I_lshift(ErtsDigit* x, dsize_t xl, Sint y,
  1207. short sign, ErtsDigit* r)
  1208. {
  1209. if (y == 0) {
  1210. MOVE_DIGITS(r, x, xl);
  1211. return xl;
  1212. }
  1213. else if (xl == 1 && *x == 0) {
  1214. *r = 0;
  1215. return 1;
  1216. }
  1217. else {
  1218. Uint ay = (y < 0) ? -y : y;
  1219. Uint bw = ay / D_EXP;
  1220. Uint sw = ay % D_EXP;
  1221. dsize_t rl;
  1222. ErtsDigit a1=0;
  1223. ErtsDigit a0=0;
  1224. if (y > 0) { /* shift left */
  1225. rl = xl + bw + 1;
  1226. while(bw--)
  1227. *r++ = 0;
  1228. if (sw) { /* NOTE! x >> 32 is not = 0! */
  1229. while(xl--) {
  1230. a0 = (*x << sw) | a1;
  1231. a1 = (*x >> (D_EXP - sw));
  1232. *r++ = a0;
  1233. x++;
  1234. }
  1235. }
  1236. else {
  1237. while(xl--) {
  1238. *r++ = *x++;
  1239. }
  1240. }
  1241. if (a1 == 0)
  1242. return rl-1;
  1243. *r = a1;
  1244. return rl;
  1245. }
  1246. else { /* shift right */
  1247. ErtsDigit* r0 = r;
  1248. int add_one = 0;
  1249. if (xl <= bw) {
  1250. if (sign)
  1251. *r = 1;
  1252. else
  1253. *r = 0;
  1254. return 1;
  1255. }
  1256. if (sign) {
  1257. Uint zl = bw;
  1258. ErtsDigit* z = x;
  1259. while(zl--) {
  1260. if (*z != 0) {
  1261. add_one = 1;
  1262. break;
  1263. }
  1264. z++;
  1265. }
  1266. }
  1267. rl = xl - bw;
  1268. x += (xl-1);
  1269. r += (rl-1);
  1270. xl -= bw;
  1271. if (sw) { /* NOTE! x >> 32 is not = 0! */
  1272. while(xl--) {
  1273. a1 = (*x >> sw) | a0;
  1274. a0 = (*x << (D_EXP-sw));
  1275. *r-- = a1;
  1276. x--;
  1277. }
  1278. }
  1279. else {
  1280. while(xl--) {
  1281. *r-- = *x--;
  1282. }
  1283. }
  1284. if (sign && (a0 != 0))
  1285. add_one = 1;
  1286. if (r[rl] == 0) {
  1287. if (rl == 1) {
  1288. if (sign)
  1289. r[1] = 1;
  1290. return 1;
  1291. }
  1292. rl--;
  1293. }
  1294. if (add_one)
  1295. return D_add(r0, rl, 1, r0);
  1296. return rl;
  1297. }
  1298. }
  1299. }
  1300. /*
  1301. ** Return log(x)/log(2)
  1302. */
  1303. static int I_lg(ErtsDigit* x, dsize_t xl)
  1304. {
  1305. dsize_t sz = xl - 1;
  1306. ErtsDigit d = x[sz];
  1307. sz *= D_EXP;
  1308. while(d != 0) {
  1309. d >>= 1;
  1310. sz++;
  1311. }
  1312. return sz - 1;
  1313. }
  1314. /*
  1315. ** Create bigint on heap if necessary. Like the previously existing
  1316. ** make_small_or_big(), except for a HAlloc() instead of an
  1317. ** ArithAlloc().
  1318. ** NOTE: Only use erts_make_integer(), when order of heap fragments is
  1319. ** guaranteed to be correct.
  1320. */
  1321. Eterm
  1322. erts_make_integer(Uint x, Process *p)
  1323. {
  1324. Eterm* hp;
  1325. if (IS_USMALL(0,x))
  1326. return make_small(x);
  1327. else {
  1328. hp = HAlloc(p, BIG_UINT_HEAP_SIZE);
  1329. return uint_to_big(x,hp);
  1330. }
  1331. }
  1332. /*
  1333. * As erts_make_integer, but from a whole UWord.
  1334. */
  1335. Eterm
  1336. erts_make_integer_from_uword(UWord x, Process *p)
  1337. {
  1338. Eterm* hp;
  1339. if (IS_USMALL(0,x))
  1340. return make_small(x);
  1341. else {
  1342. hp = HAlloc(p, BIG_UWORD_HEAP_SIZE(x));
  1343. return uword_to_big(x,hp);
  1344. }
  1345. }
  1346. /*
  1347. ** convert Uint to bigint
  1348. ** (must only be used if x is to big to be stored as a small)
  1349. */
  1350. Eterm uint_to_big(Uint x, Eterm *y)
  1351. {
  1352. *y = make_pos_bignum_header(1);
  1353. BIG_DIGIT(y, 0) = x;
  1354. return make_big(y);
  1355. }
  1356. /*
  1357. ** convert UWord to bigint
  1358. ** (must only be used if x is to big to be stored as a small)
  1359. ** Allocation is tricky, the heap need has to be calculated
  1360. ** with the macro BIG_UWORD_HEAP_SIZE(x)
  1361. */
  1362. Eterm uword_to_big(UWord x, Eterm *y)
  1363. {
  1364. *y = make_pos_bignum_header(1);
  1365. BIG_DIGIT(y, 0) = x;
  1366. return make_big(y);
  1367. }
  1368. /*
  1369. ** convert signed int to bigint
  1370. */
  1371. Eterm small_to_big(Sint x, Eterm *y)
  1372. {
  1373. Uint xu;
  1374. if (x >= 0) {
  1375. xu = x;
  1376. *y = make_pos_bignum_header(1);
  1377. } else {
  1378. xu = -(Uint)x;
  1379. *y = make_neg_bignum_header(1);
  1380. }
  1381. BIG_DIGIT(y, 0) = xu;
  1382. return make_big(y);
  1383. }
  1384. Eterm erts_uint64_to_big(Uint64 x, Eterm **hpp)
  1385. {
  1386. Eterm *hp = *hpp;
  1387. #if defined(ARCH_32)
  1388. if (x >= (((Uint64) 1) << 32)) {
  1389. *hp = make_pos_bignum_header(2);
  1390. BIG_DIGIT(hp, 0) = (Uint) (x & ((Uint) 0xffffffff));
  1391. BIG_DIGIT(hp, 1) = (Uint) ((x >> 32) & ((Uint) 0xffffffff));
  1392. *hpp += 3;
  1393. }
  1394. else
  1395. #endif
  1396. {
  1397. *hp = make_pos_bignum_header(1);
  1398. BIG_DIGIT(hp, 0) = (Uint) x;
  1399. *hpp += 2;
  1400. }
  1401. return make_big(hp);
  1402. }
  1403. Eterm erts_sint64_to_big(Sint64 x, Eterm **hpp)
  1404. {
  1405. Eterm *hp = *hpp;
  1406. Uint64 ux;
  1407. int neg;
  1408. if (x >= 0) {
  1409. neg = 0;
  1410. ux = x;
  1411. }
  1412. else {
  1413. neg = 1;
  1414. ux = -(Uint64)x;
  1415. }
  1416. #if defined(ARCH_32)
  1417. if (ux >= (((Uint64) 1) << 32)) {
  1418. if (neg)
  1419. *hp = make_neg_bignum_header(2);
  1420. else
  1421. *hp = make_pos_bignum_header(2);
  1422. BIG_DIGIT(hp, 0) = (Uint) (ux & ((Uint) 0xffffffff));
  1423. BIG_DIGIT(hp, 1) = (Uint) ((ux >> 32) & ((Uint) 0xffffffff));
  1424. *hpp += 3;
  1425. }
  1426. else
  1427. #endif
  1428. {
  1429. if (neg)
  1430. *hp = make_neg_bignum_header(1);
  1431. else
  1432. *hp = make_pos_bignum_header(1);
  1433. BIG_DIGIT(hp, 0) = (Uint) ux;
  1434. *hpp += 2;
  1435. }
  1436. return make_big(hp);
  1437. }
  1438. Eterm
  1439. erts_uint64_array_to_big(Uint **hpp, int neg, int len, Uint64 *array)
  1440. {
  1441. Uint *headerp;
  1442. int i, pot_digits, digits;
  1443. headerp = *hpp;
  1444. pot_digits = digits = 0;
  1445. for (i = 0; i < len; i++) {
  1446. #if defined(ARCH_32)
  1447. Uint low_val = array[i] & ((Uint) 0xffffffff);
  1448. Uint high_val = (array[i] >> 32) & ((Uint) 0xffffffff);
  1449. BIG_DIGIT(headerp, pot_digits) = low_val;
  1450. pot_digits++;
  1451. if (low_val)
  1452. digits = pot_digits;
  1453. BIG_DIGIT(headerp, pot_digits) = high_val;
  1454. pot_digits++;
  1455. if (high_val)
  1456. digits = pot_digits;
  1457. #else
  1458. Uint val = array[i];
  1459. BIG_DIGIT(headerp, pot_digits) = val;
  1460. pot_digits++;
  1461. if (val)
  1462. digits = pot_digits;
  1463. #endif
  1464. }
  1465. if (neg)
  1466. *headerp = make_neg_bignum_header(digits);
  1467. else
  1468. *headerp = make_pos_bignum_header(digits);
  1469. *hpp = headerp + 1 + digits;
  1470. return make_big(headerp);
  1471. }
  1472. /*
  1473. ** Convert a bignum to a double float
  1474. */
  1475. int
  1476. big_to_double(Wterm x, double* resp)
  1477. {
  1478. double d = 0.0;
  1479. Eterm* xp = big_val(x);
  1480. dsize_t xl = BIG_SIZE(xp);
  1481. ErtsDigit* s = BIG_V(xp) + xl;
  1482. short xsgn = BIG_SIGN(xp);
  1483. double dbase = ((double)(D_MASK)+1);
  1484. #ifndef NO_FPE_SIGNALS
  1485. volatile unsigned long *fpexnp = erts_get_current_fp_exception();
  1486. #endif
  1487. __ERTS_SAVE_FP_EXCEPTION(fpexnp);
  1488. __ERTS_FP_CHECK_INIT(fpexnp);
  1489. while (xl--) {
  1490. d = d * dbase + *--s;
  1491. __ERTS_FP_ERROR(fpexnp, d, __ERTS_RESTORE_FP_EXCEPTION(fpexnp); return -1);
  1492. }
  1493. *resp = xsgn ? -d : d;
  1494. __ERTS_FP_ERROR(fpexnp,*resp,;);
  1495. __ERTS_RESTORE_FP_EXCEPTION(fpexnp);
  1496. return 0;
  1497. }
  1498. /*
  1499. * Logic has been copied from erl_bif_guard.c and slightly
  1500. * modified to use a static instead of dynamic heap
  1501. */
  1502. Eterm
  1503. double_to_big(double x, Eterm *heap, Uint hsz)
  1504. {
  1505. int is_negative;
  1506. int ds;
  1507. ErtsDigit* xp;
  1508. Eterm res;
  1509. int i;
  1510. size_t sz;
  1511. Eterm* hp;
  1512. double dbase;
  1513. if (x >= 0) {
  1514. is_negative = 0;
  1515. } else {
  1516. is_negative = 1;
  1517. x = -x;
  1518. }
  1519. /* Unscale & (calculate exponent) */
  1520. ds = 0;
  1521. dbase = ((double) (D_MASK) + 1);
  1522. while (x >= 1.0) {
  1523. x /= dbase; /* "shift" right */
  1524. ds++;
  1525. }
  1526. sz = BIG_NEED_SIZE(ds); /* number of words including arity */
  1527. hp = heap;
  1528. res = make_big(hp);
  1529. xp = (ErtsDigit*) (hp + 1);
  1530. ASSERT(ds < hsz);
  1531. for (i = ds - 1; i >= 0; i--) {
  1532. ErtsDigit d;
  1533. x *= dbase; /* "shift" left */
  1534. d = x; /* trunc */
  1535. xp[i] = d; /* store digit */
  1536. x -= d; /* remove integer part */
  1537. }
  1538. while ((ds & (BIG_DIGITS_PER_WORD - 1)) != 0) {
  1539. xp[ds++] = 0;
  1540. }
  1541. if (is_negative) {
  1542. *hp = make_neg_bignum_header(sz-1);
  1543. } else {
  1544. *hp = make_pos_bignum_header(sz-1);
  1545. }
  1546. return res;
  1547. }
  1548. /*
  1549. ** Estimate the number of digits in given base (include sign)
  1550. */
  1551. int big_integer_estimate(Wterm x, Uint base)
  1552. {
  1553. Eterm* xp = big_val(x);
  1554. int lg = I_lg(BIG_V(xp), BIG_SIZE(xp));
  1555. int lgBase = ((lg + 1) / lookup_log2(base)) + 1;
  1556. if (BIG_SIGN(xp)) lgBase++; /* add sign */
  1557. return lgBase + 1; /* add null */
  1558. }
  1559. /*
  1560. ** Convert a bignum into a string of numbers in given base
  1561. */
  1562. static Uint write_big(Wterm x, int base, void (*write_func)(void *, char),
  1563. void *arg)
  1564. {
  1565. Eterm* xp = big_val(x);
  1566. ErtsDigit* dx = BIG_V(xp);
  1567. dsize_t xl = BIG_SIZE(xp);
  1568. short sign = BIG_SIGN(xp);
  1569. ErtsDigit rem;
  1570. Uint n = 0;
  1571. const Uint digits_per_Sint = get_digits_per_signed_int(base);
  1572. const Sint largest_pow_of_base = get_largest_power_of_base(base);
  1573. if (xl == 1 && *dx < largest_pow_of_base) {
  1574. rem = *dx;
  1575. if (rem == 0) {
  1576. (*write_func)(arg, '0'); n++;
  1577. } else {
  1578. while(rem) {
  1579. int digit = rem % base;
  1580. if (digit < 10) {
  1581. (*write_func)(arg, digit + '0'); n++;
  1582. } else {
  1583. (*write_func)(arg, 'A' + (digit - 10)); n++;
  1584. }
  1585. rem /= base;
  1586. }
  1587. }
  1588. } else {
  1589. ErtsDigit* tmp = (ErtsDigit*) erts_alloc(ERTS_ALC_T_TMP,
  1590. sizeof(ErtsDigit) * xl);
  1591. dsize_t tmpl = xl;
  1592. MOVE_DIGITS(tmp, dx, xl);
  1593. while(1) {
  1594. tmpl = D_div(tmp, tmpl, largest_pow_of_base, tmp, &rem);
  1595. if (tmpl == 1 && *tmp == 0) {
  1596. while(rem) {
  1597. int digit = rem % base;
  1598. if (digit < 10) {
  1599. (*write_func)(arg, digit + '0'); n++;
  1600. } else {
  1601. (*write_func)(arg, 'A' + (digit - 10)); n++;
  1602. }
  1603. rem /= base;
  1604. }
  1605. break;
  1606. } else {
  1607. Uint i = digits_per_Sint;
  1608. while(i--) {
  1609. int digit = rem % base;
  1610. if (digit < 10) {
  1611. (*write_func)(arg, digit + '0'); n++;
  1612. } else {
  1613. (*write_func)(arg, 'A' + (digit - 10)); n++;
  1614. }
  1615. rem /= base;
  1616. }
  1617. }
  1618. }
  1619. erts_free(ERTS_ALC_T_TMP, (void *) tmp);
  1620. }
  1621. if (sign) {
  1622. (*write_func)(arg, '-'); n++;
  1623. }
  1624. return n;
  1625. }
  1626. struct big_list__ {
  1627. Eterm *hp;
  1628. Eterm res;
  1629. };
  1630. static void
  1631. write_list(void *arg, char c)
  1632. {
  1633. struct big_list__ *blp = (struct big_list__ *) arg;
  1634. blp->res = CONS(blp->hp, make_small(c), blp->res);
  1635. blp->hp += 2;
  1636. }
  1637. Eterm erts_big_to_list(Eterm x, int base, Eterm **hpp)
  1638. {
  1639. struct big_list__ bl;
  1640. bl.hp = *hpp;
  1641. bl.res = NIL;
  1642. write_big(x, base, write_list, (void *) &bl);
  1643. *hpp = bl.hp;
  1644. return bl.res;
  1645. }
  1646. static void
  1647. write_string(void *arg, char c)
  1648. {
  1649. *(--(*((char **) arg))) = c;
  1650. }
  1651. char *erts_big_to_string(Wterm x, int base, char *buf, Uint buf_sz)
  1652. {
  1653. char *big_str = buf + buf_sz - 1;
  1654. *big_str = '\0';
  1655. write_big(x, base, write_string, (void*)&big_str);
  1656. ASSERT(buf <= big_str && big_str <= buf + buf_sz - 1);
  1657. return big_str;
  1658. }
  1659. /* Bignum to binary bytes
  1660. * e.g. 1 bsl 64 -> "18446744073709551616"
  1661. */
  1662. Uint erts_big_to_binary_bytes(Eterm x, int base, char *buf, Uint buf_sz)
  1663. {
  1664. char *big_str = buf + buf_sz;
  1665. Uint n;
  1666. n = write_big(x, base, write_string, (void *) &big_str);
  1667. ASSERT(buf <= big_str && big_str <= buf + buf_sz);
  1668. return n;
  1669. }
  1670. /*
  1671. ** Normalize a bignum given thing pointer length in digits and a sign
  1672. ** patch zero if odd length
  1673. */
  1674. static Eterm big_norm(Eterm *x, dsize_t xl, short sign)
  1675. {
  1676. Uint arity;
  1677. if (xl == 1) {
  1678. Uint y = BIG_DIGIT(x, 0);
  1679. if (D_EXP < SMALL_BITS || IS_USMALL(sign, y)) {
  1680. if (sign)
  1681. return make_small(-((Sint)y));
  1682. else
  1683. return make_small(y);
  1684. }
  1685. }
  1686. /* __alpha__: This was fixed */
  1687. if ((arity = BIG_NEED_SIZE(xl)-1) > BIG_ARITY_MAX)
  1688. return NIL; /* signal error (too big) */
  1689. if (sign) {
  1690. *x = make_neg_bignum_header(arity);
  1691. }
  1692. else {
  1693. *x = make_pos_bignum_header(arity);
  1694. }
  1695. return make_big(x);
  1696. }
  1697. /*
  1698. ** Compare bignums
  1699. */
  1700. int big_comp(Wterm x, Wterm y)
  1701. {
  1702. Eterm* xp = big_val(x);
  1703. Eterm* yp = big_val(y);
  1704. if (BIG_SIGN(xp) == BIG_SIGN(yp)) {
  1705. int c = I_comp(BIG_V(xp), BIG_SIZE(xp), BIG_V(yp), BIG_SIZE(yp));
  1706. if (BIG_SIGN(xp))
  1707. return -c;
  1708. else
  1709. return c;
  1710. }
  1711. else
  1712. return BIG_SIGN(xp) ? -1 : 1;
  1713. }
  1714. /*
  1715. ** Unsigned compare
  1716. */
  1717. int big_ucomp(Eterm x, Eterm y)
  1718. {
  1719. Eterm* xp = big_val(x);
  1720. Eterm* yp = big_val(y);
  1721. return I_comp(BIG_V(xp), BIG_SIZE(xp), BIG_V(yp), BIG_SIZE(yp));
  1722. }
  1723. /*
  1724. ** Return number of bytes in the bignum
  1725. */
  1726. dsize_t big_bytes(Eterm x)
  1727. {
  1728. Eterm* xp = big_val(x);
  1729. dsize_t sz = BIG_SIZE(xp);
  1730. ErtsDigit d = BIG_DIGIT(xp, sz-1);
  1731. sz = (sz-1) * sizeof(ErtsDigit);
  1732. while (d != 0) {
  1733. ++sz;
  1734. d >>= 8;
  1735. }
  1736. return sz;
  1737. }
  1738. /*
  1739. ** Load a bignum from bytes
  1740. ** xsz is the number of bytes in xp
  1741. ** *r is untouched if number fits in small
  1742. */
  1743. Eterm bytes_to_big(byte *xp, dsize_t xsz, int xsgn, Eterm *r)
  1744. {
  1745. ErtsDigit* rwp = BIG_V(r);
  1746. dsize_t rsz = 0;
  1747. ErtsDigit d;
  1748. int i;
  1749. while(xsz > sizeof(ErtsDigit)) {
  1750. d = 0;
  1751. for(i = sizeof(ErtsDigit); --i >= 0;)
  1752. d = (d << 8) | xp[i];
  1753. *rwp = d;
  1754. rwp++;
  1755. xsz -= sizeof(ErtsDigit);
  1756. xp += sizeof(ErtsDigit);
  1757. rsz++;
  1758. }
  1759. if (xsz > 0) {
  1760. d = 0;
  1761. for(i = xsz; --i >= 0;)
  1762. d = (d << 8) | xp[i];
  1763. if (++rsz == 1 && IS_USMALL(xsgn,d)) {
  1764. if (xsgn) d = -d;
  1765. return make_small(d);
  1766. }
  1767. *rwp = d;
  1768. rwp++;
  1769. }
  1770. if (rsz > BIG_ARITY_MAX)
  1771. return NIL;
  1772. if (xsgn) {
  1773. *r = make_neg_bignum_header(rsz);
  1774. }
  1775. else {
  1776. *r = make_pos_bignum_header(rsz);
  1777. }
  1778. return make_big(r);
  1779. }
  1780. /*
  1781. ** Store digits in the array of bytes pointed to by p
  1782. */
  1783. byte* big_to_bytes(Eterm x, byte *p)
  1784. {
  1785. ErtsDigit* xr = big_v(x);
  1786. dsize_t xl = big_size(x);
  1787. ErtsDigit d;
  1788. int i;
  1789. while(xl > 1) {
  1790. d = *xr;
  1791. xr++;
  1792. for(i = 0; i < sizeof(ErtsDigit); ++i) {
  1793. p[i] = d & 0xff;
  1794. d >>= 8;
  1795. }
  1796. p += sizeof(ErtsDigit);
  1797. xl--;
  1798. }
  1799. d = *xr;
  1800. do {
  1801. *p++ = d & 0xff;
  1802. d >>= 8;
  1803. } while (d != 0);
  1804. return p;
  1805. }
  1806. /*
  1807. * Converts a positive term (small or bignum) to an Uint.
  1808. *
  1809. * Fails returning 0 if the term is neither a small nor a bignum,
  1810. * if it's negative, or the big number does not fit in an Uint;
  1811. * in addition the error reason, BADARG or SYSTEM_LIMIT, will be
  1812. * stored in *up.
  1813. *
  1814. * Otherwise returns a non-zero value and the converted number
  1815. * in *up.
  1816. */
  1817. int
  1818. term_to_Uint(Eterm term, Uint *up)
  1819. {
  1820. if (is_small(term)) {
  1821. Sint i = signed_val(term);
  1822. if (i < 0) {
  1823. *up = BADARG;
  1824. return 0;
  1825. }
  1826. *up = (Uint) i;
  1827. return 1;
  1828. } else if (is_big(term)) {
  1829. ErtsDigit* xr = big_v(term);
  1830. dsize_t xl = big_size(term);
  1831. Uint uval = 0;
  1832. int n = 0;
  1833. if (big_sign(term)) {
  1834. *up = BADARG;
  1835. return 0;
  1836. } else if (xl*D_EXP > sizeof(Uint)*8) {
  1837. *up = SYSTEM_LIMIT;
  1838. return 0;
  1839. }
  1840. while (xl-- > 0) {
  1841. uval |= ((Uint)(*xr++)) << n;
  1842. n += D_EXP;
  1843. }
  1844. *up = uval;
  1845. return 1;
  1846. } else {
  1847. *up = BADARG;
  1848. return 0;
  1849. }
  1850. }
  1851. /* same as term_to_Uint()
  1852. but also accept larger bignums by masking
  1853. */
  1854. int
  1855. term_to_Uint_mask(Eterm term, Uint *up)
  1856. {
  1857. if (is_small(term)) {
  1858. Sint i = signed_val(term);
  1859. if (i < 0) {
  1860. *up = BADARG;
  1861. return 0;
  1862. }
  1863. *up = (Uint) i;
  1864. return 1;
  1865. } else if (is_big(term) && !big_sign(term)) {
  1866. ErtsDigit* xr = big_v(term);
  1867. ERTS_CT_ASSERT(sizeof(ErtsDigit) == sizeof(Uint));
  1868. *up = (Uint)*xr; /* just pick first word */
  1869. return 1;
  1870. } else {
  1871. *up = BADARG;
  1872. return 0;
  1873. }
  1874. }
  1875. int
  1876. term_to_UWord(Eterm term, UWord *up)
  1877. {
  1878. #if SIZEOF_VOID_P == ERTS_SIZEOF_ETERM
  1879. return term_to_Uint(term,up);
  1880. #else
  1881. if (is_small(term)) {
  1882. Sint i = signed_val(term);
  1883. if (i < 0) {
  1884. *up = BADARG;
  1885. return 0;
  1886. }
  1887. *up = (UWord) i;
  1888. return 1;
  1889. } else if (is_big(term)) {
  1890. ErtsDigit* xr = big_v(term);
  1891. dsize_t xl = big_size(term);
  1892. UWord uval = 0;
  1893. int n = 0;
  1894. if (big_sign(term)) {
  1895. *up = BADARG;
  1896. return 0;
  1897. } else if (xl*D_EXP > sizeof(UWord)*8) {
  1898. *up = SYSTEM_LIMIT;
  1899. return 0;
  1900. }
  1901. while (xl-- > 0) {
  1902. uval |= ((UWord)(*xr++)) << n;
  1903. n += D_EXP;
  1904. }
  1905. *up = uval;
  1906. return 1;
  1907. } else {
  1908. *up = BADARG;
  1909. return 0;
  1910. }
  1911. #endif
  1912. }
  1913. int
  1914. term_to_Uint64(Eterm term, Uint64 *up)
  1915. {
  1916. #if SIZEOF_VOID_P == 8
  1917. return term_to_UWord(term,up);
  1918. #else
  1919. if (is_small(term)) {
  1920. Sint i = signed_val(term);
  1921. if (i < 0) {
  1922. *up = BADARG;
  1923. return 0;
  1924. }
  1925. *up = (Uint64) i;
  1926. return 1;
  1927. } else if (is_big(term)) {
  1928. ErtsDigit* xr = big_v(term);
  1929. dsize_t xl = big_size(term);
  1930. Uint64 uval = 0;
  1931. int n = 0;
  1932. if (big_sign(term)) {
  1933. *up = BADARG;
  1934. return 0;
  1935. } else if (xl*D_EXP > sizeof(Uint64)*8) {
  1936. *up = SYSTEM_LIMIT;
  1937. return 0;
  1938. }
  1939. while (xl-- > 0) {
  1940. uval |= ((Uint64)(*xr++)) << n;
  1941. n += D_EXP;
  1942. }
  1943. *up = uval;
  1944. return 1;
  1945. } else {
  1946. *up = BADARG;
  1947. return 0;
  1948. }
  1949. #endif
  1950. }
  1951. int term_to_Sint(Eterm term, Sint *sp)
  1952. {
  1953. if (is_small(term)) {
  1954. *sp = signed_val(term);
  1955. return 1;
  1956. } else if (is_big(term)) {
  1957. ErtsDigit* xr = big_v(term);
  1958. dsize_t xl = big_size(term);
  1959. int sign = big_sign(term);
  1960. Uint uval = 0;
  1961. int n = 0;
  1962. if (xl*D_EXP > sizeof(Uint)*8) {
  1963. return 0;
  1964. }
  1965. while (xl-- > 0) {
  1966. uval |= ((Uint)(*xr++)) << n;
  1967. n += D_EXP;
  1968. }
  1969. if (sign) {
  1970. uval = -uval;
  1971. if ((Sint)uval > 0)
  1972. return 0;
  1973. } else {
  1974. if ((Sint)uval < 0)
  1975. return 0;
  1976. }
  1977. *sp = uval;
  1978. return 1;
  1979. } else {
  1980. return 0;
  1981. }
  1982. }
  1983. #if HAVE_INT64
  1984. int term_to_Sint64(Eterm term, Sint64 *sp)
  1985. {
  1986. #if ERTS_SIZEOF_ETERM == 8
  1987. return term_to_Sint(term, sp);
  1988. #else
  1989. if (is_small(term)) {
  1990. *sp = signed_val(term);
  1991. return 1;
  1992. } else if (is_big(term)) {
  1993. ErtsDigit* xr = big_v(term);
  1994. dsize_t xl = big_size(term);
  1995. int sign = big_sign(term);
  1996. Uint64 uval = 0;
  1997. int n = 0;
  1998. if (xl*D_EXP > sizeof(Uint64)*8) {
  1999. return 0;
  2000. }
  2001. while (xl-- > 0) {
  2002. uval |= ((Uint64)(*xr++)) << n;
  2003. n += D_EXP;
  2004. }
  2005. if (sign) {
  2006. uval = -uval;
  2007. if ((Sint64)uval > 0)
  2008. return 0;
  2009. } else {
  2010. if ((Sint64)uval < 0)
  2011. return 0;
  2012. }
  2013. *sp = uval;
  2014. return 1;
  2015. } else {
  2016. return 0;
  2017. }
  2018. #endif
  2019. }
  2020. #endif /* HAVE_INT64 */
  2021. /*
  2022. ** Add and subtract
  2023. */
  2024. static Eterm B_plus_minus(ErtsDigit *x, dsize_t xl, short xsgn,
  2025. ErtsDigit *y, dsize_t yl, short ysgn, Eterm *r)
  2026. {
  2027. if (xsgn == ysgn) {
  2028. if (xl > yl)
  2029. return big_norm(r, I_add(x,xl,y,yl,BIG_V(r)), xsgn);
  2030. else
  2031. return big_norm(r, I_add(y,yl,x,xl,BIG_V(r)), xsgn);
  2032. }
  2033. else {
  2034. int comp = I_comp(x, xl, y, yl);
  2035. if (comp == 0)
  2036. return make_small(0);
  2037. else if (comp > 0)
  2038. return big_norm(r, I_sub(x,xl,y,yl,BIG_V(r)), xsgn);
  2039. else
  2040. return big_norm(r, I_sub(y,yl,x,xl,BIG_V(r)), ysgn);
  2041. }
  2042. }
  2043. /*
  2044. ** Add bignums
  2045. */
  2046. Eterm big_plus(Wterm x, Wterm y, Eterm *r)
  2047. {
  2048. Eterm* xp = big_val(x);
  2049. Eterm* yp = big_val(y);
  2050. return B_plus_minus(BIG_V(xp),BIG_SIZE(xp),(short) BIG_SIGN(xp),
  2051. BIG_V(yp),BIG_SIZE(yp),(short) BIG_SIGN(yp), r);
  2052. }
  2053. /*
  2054. ** Subtract bignums
  2055. */
  2056. Eterm big_minus(Eterm x, Eterm y, Eterm *r)
  2057. {
  2058. Eterm* xp = big_val(x);
  2059. Eterm* yp = big_val(y);
  2060. return B_plus_minus(BIG_V(xp),BIG_SIZE(xp),(short) BIG_SIGN(xp),
  2061. BIG_V(yp),BIG_SIZE(yp),(short) !BIG_SIGN(yp), r);
  2062. }
  2063. /*
  2064. ** Multiply smallnums
  2065. */
  2066. Eterm small_times(Sint x, Sint y, Eterm *r)
  2067. {
  2068. short sign = (x<0) != (y<0);
  2069. ErtsDigit xu = (x > 0) ? x : -x;
  2070. ErtsDigit yu = (y > 0) ? y : -y;
  2071. ErtsDigit d1=0;
  2072. ErtsDigit d0;
  2073. Uint arity;
  2074. DMULc(xu, yu, d1, d0);
  2075. if (!d1 && ((D_EXP < SMALL_BITS) || IS_USMALL(sign, d0))) {
  2076. if (sign)
  2077. return make_small(-((Sint)d0));
  2078. else
  2079. return make_small(d0);
  2080. }
  2081. BIG_DIGIT(r,0) = d0;
  2082. arity = d1 ? 2 : 1;
  2083. if (sign)
  2084. *r = make_neg_bignum_header(arity);
  2085. else
  2086. *r = make_pos_bignum_header(arity);
  2087. if (d1)
  2088. BIG_DIGIT(r,1) = d1;
  2089. return make_big(r);
  2090. }
  2091. /*
  2092. ** Multiply bignums
  2093. */
  2094. Eterm big_times(Eterm x, Eterm y, Eterm *r)
  2095. {
  2096. Eterm* xp = big_val(x);
  2097. Eterm* yp = big_val(y);
  2098. short sign = BIG_SIGN(xp) != BIG_SIGN(yp);
  2099. dsize_t xsz = BIG_SIZE(xp);
  2100. dsize_t ysz = BIG_SIZE(yp);
  2101. dsize_t rsz;
  2102. if (ysz == 1)
  2103. rsz = D_mul(BIG_V(xp), xsz, BIG_DIGIT(yp, 0), BIG_V(r));
  2104. else if (xsz == 1)
  2105. rsz = D_mul(BIG_V(yp), ysz, BIG_DIGIT(xp, 0), BIG_V(r));
  2106. else if (xp == yp) {
  2107. ZERO_DIGITS(BIG_V(r), xsz+1);
  2108. rsz = I_sqr(BIG_V(xp), xsz, BIG_V(r));
  2109. }
  2110. else if (xsz >= ysz) {
  2111. ZERO_DIGITS(BIG_V(r), xsz);
  2112. rsz = I_mul(BIG_V(xp), xsz, BIG_V(yp), ysz, BIG_V(r));
  2113. }
  2114. else {
  2115. ZERO_DIGITS(BIG_V(r), ysz);
  2116. rsz = I_mul(BIG_V(yp), ysz, BIG_V(xp), xsz, BIG_V(r));
  2117. }
  2118. return big_norm(r, rsz, sign);
  2119. }
  2120. /*
  2121. ** Divide bignums
  2122. */
  2123. Eterm big_div(Eterm x, Eterm y, Eterm *q)
  2124. {
  2125. Eterm* xp = big_val(x);
  2126. Eterm* yp = big_val(y);
  2127. short sign = BIG_SIGN(xp) != BIG_SIGN(yp);
  2128. dsize_t xsz = BIG_SIZE(xp);
  2129. dsize_t ysz = BIG_SIZE(yp);
  2130. dsize_t qsz;
  2131. if (ysz == 1) {
  2132. ErtsDigit rem;
  2133. qsz = D_div(BIG_V(xp), xsz, BIG_DIGIT(yp,0), BIG_V(q), &rem);
  2134. }
  2135. else {
  2136. Eterm* remp;
  2137. dsize_t rem_sz;
  2138. qsz = xsz - ysz + 1;
  2139. remp = q + BIG_NEED_SIZE(qsz);
  2140. qsz = I_div(BIG_V(xp), xsz, BIG_V(yp), ysz, BIG_V(q), BIG_V(remp),
  2141. &rem_sz);
  2142. }
  2143. return big_norm(q, qsz, sign);
  2144. }
  2145. /*
  2146. ** Remainder
  2147. */
  2148. Eterm big_rem(Eterm x, Eterm y, Eterm *r)
  2149. {
  2150. Eterm* xp = big_val(x);
  2151. Eterm* yp = big_val(y);
  2152. short sign = BIG_SIGN(xp);
  2153. dsize_t xsz = BIG_SIZE(xp);
  2154. dsize_t ysz = BIG_SIZE(yp);
  2155. if (ysz == 1) {
  2156. ErtsDigit rem;
  2157. rem = D_rem(BIG_V(xp), xsz, BIG_DIGIT(yp,0));
  2158. if (IS_USMALL(sign, rem)) {
  2159. if (sign)
  2160. return make_small(-(Sint)rem);
  2161. else
  2162. return make_small(rem);
  2163. }
  2164. else {
  2165. if (sign)
  2166. *r = make_neg_bignum_header(1);
  2167. else
  2168. *r = make_pos_bignum_header(1);
  2169. BIG_DIGIT(r, 0) = rem;
  2170. return make_big(r);
  2171. }
  2172. }
  2173. else {
  2174. dsize_t rsz = I_rem(BIG_V(xp), xsz, BIG_V(yp), ysz, BIG_V(r));
  2175. return big_norm(r, rsz, sign);
  2176. }
  2177. }
  2178. Eterm big_band(Eterm x, Eterm y, Eterm *r)
  2179. {
  2180. Eterm* xp = big_val(x);
  2181. Eterm* yp = big_val(y);
  2182. short xsgn = BIG_SIGN(xp);
  2183. short ysgn = BIG_SIGN(yp);
  2184. short sign = xsgn && ysgn;
  2185. dsize_t xsz = BIG_SIZE(xp);
  2186. dsize_t ysz = BIG_SIZE(yp);
  2187. if (xsz >= ysz)
  2188. return big_norm(r,I_band(BIG_V(xp),xsz,xsgn,
  2189. BIG_V(yp),ysz,ysgn,
  2190. BIG_V(r)),sign);
  2191. else
  2192. return big_norm(r,I_band(BIG_V(yp),ysz,ysgn,
  2193. BIG_V(xp),xsz,xsgn,
  2194. BIG_V(r)),sign);
  2195. }
  2196. Eterm big_bor(Eterm x, Eterm y, Eterm *r)
  2197. {
  2198. Eterm* xp = big_val(x);
  2199. Eterm* yp = big_val(y);
  2200. short xsgn = BIG_SIGN(xp);
  2201. short ysgn = BIG_SIGN(yp);
  2202. short sign = (xsgn || ysgn);
  2203. dsize_t xsz = BIG_SIZE(xp);
  2204. dsize_t ysz = BIG_SIZE(yp);
  2205. if (xsz >= ysz)
  2206. return big_norm(r,I_bor(BIG_V(xp),xsz,xsgn,
  2207. BIG_V(yp),ysz,ysgn,
  2208. BIG_V(r)),sign);
  2209. else
  2210. return big_norm(r,I_bor(BIG_V(yp),ysz,ysgn,
  2211. BIG_V(xp),xsz,xsgn,
  2212. BIG_V(r)),sign);
  2213. }
  2214. Eterm big_bxor(Eterm x, Eterm y, Eterm *r)
  2215. {
  2216. Eterm* xp = big_val(x);
  2217. Eterm* yp = big_val(y);
  2218. short xsgn = BIG_SIGN(xp);
  2219. short ysgn = BIG_SIGN(yp);
  2220. short sign = (xsgn != ysgn);
  2221. dsize_t xsz = BIG_SIZE(xp);
  2222. dsize_t ysz = BIG_SIZE(yp);
  2223. if (xsz >= ysz)
  2224. return big_norm(r,I_bxor(BIG_V(xp),xsz,xsgn,
  2225. BIG_V(yp),ysz,ysgn,
  2226. BIG_V(r)),sign);
  2227. else

Large files files are truncated, but you can click here to view the full file