Coverage Report

Created: 2026-11-12 06:41

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/moddable/xs/sources/xsBigInt.c
Line
Count
Source
1
/*
2
 * Copyright (c) 2016-2026  Moddable Tech, Inc.
3
 *
4
 *   This file is part of the Moddable SDK Runtime.
5
 * 
6
 *   The Moddable SDK Runtime is free software: you can redistribute it and/or modify
7
 *   it under the terms of the GNU Lesser General Public License as published by
8
 *   the Free Software Foundation, either version 3 of the License, or
9
 *   (at your option) any later version.
10
 * 
11
 *   The Moddable SDK Runtime is distributed in the hope that it will be useful,
12
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of
13
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14
 *   GNU Lesser General Public License for more details.
15
 * 
16
 *   You should have received a copy of the GNU Lesser General Public License
17
 *   along with the Moddable SDK Runtime.  If not, see <http://www.gnu.org/licenses/>.
18
 *
19
 * This file incorporates work covered by the following copyright and  
20
 * permission notice:  
21
 *
22
 *       Copyright (C) 2010-2016 Marvell International Ltd.
23
 *       Copyright (C) 2002-2010 Kinoma, Inc.
24
 *
25
 *       Licensed under the Apache License, Version 2.0 (the "License");
26
 *       you may not use this file except in compliance with the License.
27
 *       You may obtain a copy of the License at
28
 *
29
 *        http://www.apache.org/licenses/LICENSE-2.0
30
 *
31
 *       Unless required by applicable law or agreed to in writing, software
32
 *       distributed under the License is distributed on an "AS IS" BASIS,
33
 *       WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
34
 *       See the License for the specific language governing permissions and
35
 *       limitations under the License.
36
 */
37
38
#include "xsAll.h"
39
40
#ifndef mxCompile
41
static txSlot* fxBigIntCheck(txMachine* the, txSlot* it);
42
static txBigInt* fxIntegerToBigInt(txMachine* the, txSlot* slot);
43
static txBigInt* fxNumberToBigInt(txMachine* the, txSlot* slot);
44
static txBigInt* fxStringToBigInt(txMachine* the, txSlot* slot, txFlag whole);
45
#endif
46
47
#ifndef howmany
48
228k
#define howmany(x, y) (((x) + (y) - 1) / (y))
49
#endif
50
#ifndef MAX
51
1.55M
#define MAX(a, b) ((a) >= (b) ? (a) : (b))
52
#endif
53
#ifndef MIN
54
2.98M
#define MIN(a, b) ((a) <= (b) ? (a) : (b))
55
#endif
56
57
const txU4 gxDataOne[1] = { 1 };
58
const txU4 gxDataZero[1] = { 0 };
59
const txBigInt gxBigIntNaN = { .sign=0, .size=0, .data=(txU4*)gxDataZero };
60
const txBigInt gxBigIntOne = { .sign=0, .size=1, .data=(txU4*)gxDataOne };
61
const txBigInt gxBigIntZero = { .sign=0, .size=1, .data=(txU4*)gxDataZero };
62
63
static txBigInt *fxBigInt_fit(txMachine* the, txBigInt *r);
64
65
#ifdef mxMetering
66
static void fxBigInt_meter(txMachine* the, int n);
67
6.34M
#define mxBigInt_meter(N) if (the) fxBigInt_meter(the, N)
68
#else
69
#define mxBigInt_meter(N)
70
#endif
71
72
// BYTE CODE
73
74
#ifndef mxCompile
75
76
void fxBuildBigInt(txMachine* the)
77
30.4k
{
78
30.4k
  txSlot* slot;
79
30.4k
  mxPush(mxObjectPrototype);
80
30.4k
  slot = fxLastProperty(the, fxNewObjectInstance(the));
81
30.4k
  slot = fxNextHostFunctionProperty(the, slot, mxCallback(fx_BigInt_prototype_toString), 0, mxID(_toLocaleString), XS_DONT_ENUM_FLAG);
82
30.4k
  slot = fxNextHostFunctionProperty(the, slot, mxCallback(fx_BigInt_prototype_toString), 0, mxID(_toString), XS_DONT_ENUM_FLAG);
83
30.4k
  slot = fxNextHostFunctionProperty(the, slot, mxCallback(fx_BigInt_prototype_valueOf), 0, mxID(_valueOf), XS_DONT_ENUM_FLAG);
84
30.4k
  slot = fxNextStringXProperty(the, slot, "BigInt", mxID(_Symbol_toStringTag), XS_DONT_ENUM_FLAG | XS_DONT_SET_FLAG);
85
30.4k
  mxBigIntPrototype = *the->stack;
86
30.4k
  slot = fxBuildHostConstructor(the, mxCallback(fx_BigInt), 1, mxID(_BigInt));
87
30.4k
  mxBigIntConstructor = *the->stack;
88
30.4k
  slot = fxLastProperty(the, slot);
89
30.4k
  slot = fxNextHostFunctionProperty(the, slot, mxCallback(fx_BigInt_asIntN), 2, mxID(_asIntN), XS_DONT_ENUM_FLAG);
90
30.4k
  slot = fxNextHostFunctionProperty(the, slot, mxCallback(fx_BigInt_asUintN), 2, mxID(_asUintN), XS_DONT_ENUM_FLAG);
91
30.4k
  slot = fxNextHostFunctionProperty(the, slot, mxCallback(fx_BigInt_bitLength), 1, mxID(_bitLength), XS_DONT_ENUM_FLAG);
92
30.4k
  slot = fxNextHostFunctionProperty(the, slot, mxCallback(fx_BigInt_fromArrayBuffer), 1, mxID(_fromArrayBuffer), XS_DONT_ENUM_FLAG);
93
30.4k
  mxPop();
94
30.4k
}
95
96
void fx_BigInt(txMachine* the)
97
2.51k
{
98
2.51k
  if (mxHasTarget)
99
1
    mxTypeError("new: BigInt");
100
2.50k
  if (mxArgc > 0)
101
2.50k
    *mxResult = *mxArgv(0);
102
2.50k
  fxToPrimitive(the, mxResult, XS_NUMBER_HINT);
103
2.50k
  if (mxResult->kind == XS_NUMBER_KIND) {
104
185
    int fpclass = c_fpclassify(mxResult->value.number);
105
185
    txNumber check = c_trunc(mxResult->value.number);
106
185
    if ((fpclass != C_FP_NAN) && (fpclass != C_FP_INFINITE) && (mxResult->value.number == check))
107
167
      fxNumberToBigInt(the, mxResult);
108
18
    else
109
18
      mxRangeError("cannot coerce number to bigint");
110
185
  }
111
2.32k
  else if (mxResult->kind == XS_INTEGER_KIND) {
112
411
    fxIntegerToBigInt(the, mxResult);
113
411
  }
114
1.91k
  else
115
1.91k
    fxToBigInt(the, mxResult, 1);
116
2.50k
}
117
118
txNumber fx_BigInt_asAux(txMachine* the)
119
11.4k
{
120
11.4k
  txNumber value, index;
121
11.4k
  if (mxArgc < 1)
122
4
    index = 0;
123
11.4k
  else {
124
11.4k
    if (mxArgv(0)->kind == XS_UNDEFINED_KIND)
125
935
      index = 0;
126
10.5k
    else {
127
10.5k
      value = fxToNumber(the, mxArgv(0));
128
10.5k
      if (c_isnan(value))
129
33
        index = 0;
130
10.5k
      else {
131
10.5k
        value = c_trunc(value);
132
10.5k
        if (value < 0)
133
13
          mxRangeError("index < 0");
134
10.4k
        index = value;
135
10.4k
        if (index <= 0)
136
1.64k
          index = 0;
137
8.84k
        else if (index > C_MAX_SAFE_INTEGER)
138
5
          index = C_MAX_SAFE_INTEGER;
139
10.4k
        if (value != index)
140
5
          mxRangeError("invalid index");
141
10.4k
      }
142
10.5k
    }
143
11.4k
  }
144
11.4k
  if (mxArgc < 2)
145
9
    mxTypeError("no bigint");
146
11.4k
  return index;
147
11.4k
}
148
149
void fx_BigInt_asIntN(txMachine* the)
150
6.96k
{
151
6.96k
  txInteger index = (txInteger)fx_BigInt_asAux(the);
152
6.96k
  txBigInt* arg = fxToBigInt(the, mxArgv(1), 1);
153
6.96k
  txBigInt* result;
154
6.96k
  if (fxBigInt_iszero(arg)) {
155
967
    result = fxBigInt_dup(the, arg);
156
967
  }
157
6.00k
  else {
158
6.00k
    txBigInt* bits = fxBigInt_ulsl1(the, C_NULL, (txBigInt *)&gxBigIntOne, index);
159
6.00k
    txBigInt* mask = fxBigInt_usub(the, C_NULL, bits, (txBigInt *)&gxBigIntOne);
160
6.00k
    result = fxBigInt_uand(the, C_NULL, arg, mask);
161
6.00k
    if ((arg->sign) && !fxBigInt_iszero(result))
162
1.39k
      result = fxBigInt_usub(the, C_NULL, bits, result);
163
6.00k
    if (index && fxBigInt_comp(result, fxBigInt_ulsl1(the, C_NULL, (txBigInt *)&gxBigIntOne, index - 1)) >= 0)
164
1.62k
      result = fxBigInt_sub(the, C_NULL, result, bits);
165
6.00k
    result = fxBigInt_fit(the, result);
166
6.00k
  }
167
6.96k
  mxResult->value.bigint = *result;
168
6.96k
  mxResult->kind = XS_BIGINT_KIND;
169
//  txBigInt* bits = fxBigInt_ulsl1(the, C_NULL, (txBigInt *)&gxBigIntOne, index);
170
//  txBigInt* result = fxBigInt_mod(the, C_NULL, fxToBigInt(the, mxArgv(1), 1), bits);
171
//  if (index && fxBigInt_comp(result, fxBigInt_ulsl1(the, C_NULL, (txBigInt *)&gxBigIntOne, index - 1)) >= 0)
172
//    result = fxBigInt_sub(the, C_NULL, result, bits);
173
//  mxResult->value.bigint = *result;
174
//  mxResult->kind = XS_BIGINT_KIND;
175
6.96k
}
176
177
void fx_BigInt_asUintN(txMachine* the)
178
4.50k
{
179
4.50k
  txInteger index = (txInteger)fx_BigInt_asAux(the);
180
4.50k
  txBigInt* arg = fxToBigInt(the, mxArgv(1), 1);
181
4.50k
  txBigInt* result;
182
4.50k
  if (fxBigInt_iszero(arg)) {
183
1.59k
    result = fxBigInt_dup(the, arg);
184
1.59k
  }
185
2.91k
  else {
186
2.91k
    txBigInt* bits = fxBigInt_ulsl1(the, C_NULL, (txBigInt *)&gxBigIntOne, index);
187
2.91k
    txBigInt* mask = fxBigInt_sub(the, C_NULL, bits, (txBigInt *)&gxBigIntOne);
188
2.91k
    result = fxBigInt_uand(the, C_NULL, arg, mask);
189
2.91k
    if ((arg->sign) && !fxBigInt_iszero(result))
190
975
      result = fxBigInt_usub(the, C_NULL, bits, result);
191
2.91k
    result = fxBigInt_fit(the, result);
192
2.91k
  }
193
4.50k
  mxResult->value.bigint = *result;
194
4.50k
  mxResult->kind = XS_BIGINT_KIND;
195
//  fxToBigInt(the, mxArgv(1), 1);
196
//  mxResult->value.bigint = *fxBigInt_mod(the, C_NULL, &mxArgv(1)->value.bigint, fxBigInt_ulsl1(the, C_NULL, (txBigInt *)&gxBigIntOne, index));
197
//  mxResult->kind = XS_BIGINT_KIND;
198
4.50k
}
199
200
void fx_BigInt_bitLength(txMachine *the)
201
0
{
202
0
  txBigInt* arg = fxToBigInt(the, mxArgv(0), 1);
203
0
  mxResult->value.integer = fxBigInt_bitsize(arg);;
204
0
  mxResult->kind = XS_INTEGER_KIND;
205
0
}
206
207
void fx_BigInt_fromArrayBuffer(txMachine* the)
208
4
{
209
4
  txSlot* slot;
210
4
  txSlot* arrayBuffer = C_NULL;
211
4
  txSlot* bufferInfo;
212
4
  txBoolean sign = 0;
213
4
  int endian = EndianBig;
214
4
  txInteger length;
215
4
  txBigInt* bigint;
216
4
  txU1 *src, *dst;
217
4
  if (mxArgc < 1)
218
0
    mxTypeError("no argument");
219
4
  slot = mxArgv(0);
220
4
  if (slot->kind == XS_REFERENCE_KIND) {
221
3
    slot = slot->value.reference->next;
222
3
    if (slot && (slot->kind == XS_ARRAY_BUFFER_KIND))
223
2
      arrayBuffer = slot;
224
3
  }
225
4
  if (!arrayBuffer)
226
2
    mxTypeError("argument: not an ArrayBuffer instance");
227
2
  bufferInfo = arrayBuffer->next;
228
2
  length = bufferInfo->value.bufferInfo.length;
229
2
  if ((mxArgc > 1) && fxToBoolean(the, mxArgv(1)))
230
1
    sign = 1;
231
2
  if ((mxArgc > 2) && fxToBoolean(the, mxArgv(2)))
232
0
    endian = EndianLittle;
233
2
  if (sign)
234
1
    length--;
235
2
  if (length <= 0) {
236
2
    mxSyntaxError("argument: invalid ArrayBuffer instance");
237
//    mxResult->value.bigint = gxBigIntNaN;
238
//    mxResult->kind = XS_BIGINT_X_KIND;
239
0
    return;
240
2
  }
241
0
  bigint = fxBigInt_alloc(the, howmany(length, sizeof(txU4)));
242
0
  bigint->data[bigint->size - 1] = 0;
243
0
  src = (txU1*)(arrayBuffer->value.arrayBuffer.address);
244
0
  dst = (txU1*)(bigint->data);
245
0
  if (sign)
246
0
    bigint->sign = *src++;
247
#if mxBigEndian
248
  if (endian != EndianLittle) {
249
#else
250
0
  if (endian != EndianBig) {
251
0
#endif  
252
0
    c_memcpy(dst, src, length);
253
0
  }
254
0
  else {
255
0
    dst += length;
256
0
    while (length > 0) {
257
0
      dst--;
258
0
      *dst = *src;
259
0
      src++;
260
0
      length--;
261
0
    }
262
0
  }
263
0
  length = bigint->size - 1;
264
0
  while (length && (bigint->data[length] == 0))
265
0
    length--;
266
0
  bigint->size = length + 1;
267
0
  mxPullSlot(mxResult);
268
0
}
269
270
void fx_BigInt_prototype_toString(txMachine* the)
271
166k
{
272
166k
  txSlot* slot;
273
166k
  txU4 radix;
274
166k
  slot = fxBigIntCheck(the, mxThis);
275
166k
  if (!slot) mxTypeError("this: not a bigint");
276
166k
  if (mxArgc == 0)
277
59
    radix = 10;
278
166k
  else if (mxIsUndefined(mxArgv(0)))
279
6
    radix = 10;
280
166k
  else {
281
166k
    radix = fxToInteger(the, mxArgv(0));
282
166k
    if ((radix < 2) || (36 < radix))
283
32
      mxRangeError("invalid radix");
284
166k
  }
285
166k
  mxPushSlot(slot);
286
166k
  fxBigintToString(the, the->stack, radix);
287
166k
  mxPullSlot(mxResult);
288
166k
}
289
290
void fx_BigInt_prototype_valueOf(txMachine* the)
291
114
{
292
114
  txSlot* slot = fxBigIntCheck(the, mxThis);
293
114
  if (!slot) mxTypeError("this: not a bigint");
294
18
  mxResult->kind = slot->kind;
295
18
  mxResult->value = slot->value;
296
18
}
297
298
void fxBigInt(txMachine* the, txSlot* slot, txU1 sign, txU2 size, txU4* data)
299
0
{
300
0
  txBigInt* bigint = fxBigInt_alloc(the, size);
301
0
  c_memcpy(bigint->data, data, size * sizeof(txU4));
302
0
  bigint->sign = sign;
303
0
  mxPullSlot(slot);
304
0
}
305
306
void fxBigIntX(txMachine* the, txSlot* slot, txU1 sign, txU2 size, txU4* data)
307
0
{
308
0
  slot->value.bigint.data = data;
309
0
  slot->value.bigint.size = size;
310
0
  slot->value.bigint.sign = sign;
311
0
  slot->kind = XS_BIGINT_X_KIND;
312
0
}
313
314
txSlot* fxBigIntCheck(txMachine* the, txSlot* it)
315
166k
{
316
166k
  txSlot* result = C_NULL;
317
166k
  if ((it->kind == XS_BIGINT_KIND) || (it->kind == XS_BIGINT_X_KIND))
318
166k
    result = it;
319
136
  else if (it->kind == XS_REFERENCE_KIND) {
320
106
    txSlot* instance = it->value.reference;
321
106
    it = instance->next;
322
106
    if ((it) && (it->flag & XS_INTERNAL_FLAG) && ((it->kind == XS_BIGINT_KIND) || (it->kind == XS_BIGINT_X_KIND)))
323
18
      result = it;
324
106
  }
325
166k
  return result;
326
166k
}
327
328
void fxBigIntCoerce(txMachine* the, txSlot* slot)
329
221
{
330
221
  fxToBigInt(the, slot, 1);
331
221
}
332
333
txBoolean fxBigIntCompare(txMachine* the, txBoolean less, txBoolean equal, txBoolean more, txSlot* left, txSlot* right)
334
5.40M
{
335
5.40M
  int result;
336
5.40M
  txNumber delta = 0;
337
5.40M
  if (mxBigIntIsNaN(&left->value.bigint))
338
0
    return less & more & !equal;
339
5.40M
  if (right->kind == XS_STRING_KIND)
340
1.42M
    fxStringToBigInt(the, right, 1);
341
5.40M
  if ((right->kind != XS_BIGINT_KIND) && (right->kind != XS_BIGINT_X_KIND)) {
342
3.91M
    fxToNumber(the, right);
343
3.91M
    result = c_fpclassify(right->value.number);
344
3.91M
    if (result == C_FP_NAN)
345
71.5k
      return less & more & !equal;
346
3.84M
    if (result == C_FP_INFINITE)
347
113k
      return (right->value.number > 0) ? less : more;
348
3.73M
    delta = right->value.number - c_trunc(right->value.number);
349
3.73M
    fxNumberToBigInt(the, right);
350
3.73M
  }
351
5.21M
  if (mxBigIntIsNaN(&right->value.bigint))
352
1.25M
    return less & more & !equal;
353
3.96M
  result = fxBigInt_comp(&left->value.bigint, &right->value.bigint);
354
3.96M
  if (result < 0)
355
2.11M
    return less;
356
1.85M
  if (result > 0)
357
1.84M
    return more;
358
3.77k
  if (delta > 0)
359
872
    return less;
360
2.90k
  if (delta < 0)
361
1.69k
    return more;
362
1.20k
  return equal;
363
2.90k
}
364
365
void fxBigIntDecode(txMachine* the, txSize size)
366
11.1M
{
367
11.1M
  txBigInt* bigint;
368
11.1M
  mxPushUndefined();
369
11.1M
  bigint = &the->stack->value.bigint;
370
11.1M
  bigint->data = fxNewChunk(the, size);
371
11.1M
  bigint->size = size >> 2;
372
11.1M
  bigint->sign = 0;
373
#if mxBigEndian
374
  {
375
    txS1* src = (txS1*)the->code;
376
    txS1* dst = (txS1*)bigint->data;
377
    while (size) {
378
      dst[3] = *src++;
379
      dst[2] = *src++;
380
      dst[1] = *src++;
381
      dst[0] = *src++;
382
      dst += 4;
383
      size--;
384
    }
385
  }
386
#else
387
11.1M
  c_memcpy(bigint->data, the->code, size);
388
11.1M
#endif  
389
11.1M
  the->stack->kind = XS_BIGINT_KIND;
390
11.1M
}
391
392
#endif  
393
394
void fxBigIntEncode(txByte* code, txBigInt* bigint, txSize size)
395
12.5k
{
396
#if mxBigEndian
397
  {
398
    txS1* src = (txS1*)bigint->data;
399
    txS1* dst = (txS1*)code;
400
    while (size) {
401
      dst[3] = *src++;
402
      dst[2] = *src++;
403
      dst[1] = *src++;
404
      dst[0] = *src++;
405
      dst += 4;
406
      size--;
407
    }
408
  }
409
#else
410
12.5k
  c_memcpy(code, bigint->data, size);
411
12.5k
#endif
412
12.5k
}
413
414
#ifndef mxCompile
415
txSlot* fxBigIntToInstance(txMachine* the, txSlot* slot)
416
1.01M
{
417
1.01M
  txSlot* instance;
418
1.01M
  txSlot* internal;
419
1.01M
  mxPush(mxBigIntPrototype);
420
1.01M
  instance = fxNewObjectInstance(the);
421
1.01M
  internal = instance->next = fxNewSlot(the);
422
1.01M
  internal->flag = XS_INTERNAL_FLAG;
423
1.01M
  internal->kind = slot->kind;
424
1.01M
  internal->value = slot->value;
425
1.01M
  if (the->frame->flag & XS_STRICT_FLAG)
426
0
    instance->flag |= XS_DONT_PATCH_FLAG;
427
1.01M
  mxPullSlot(slot);
428
1.01M
  return instance;
429
1.01M
}
430
#endif
431
432
txSize fxBigIntMeasure(txBigInt* bigint)
433
37.5k
{
434
37.5k
  return bigint->size * sizeof(txU4);
435
37.5k
}
436
437
txSize fxBigIntMaximum(txSize length)
438
89.3k
{
439
89.3k
  return sizeof(txU4) * (1 + (((txSize)c_ceil((txNumber)length * c_log(10) / c_log(2))) / 32));
440
89.3k
}
441
442
txSize fxBigIntMaximumB(txSize length)
443
1.39k
{
444
1.39k
  return sizeof(txU4) * (1 + howmany(1, mxBigIntWordSize) + (length / 32));
445
1.39k
}
446
447
txSize fxBigIntMaximumO(txSize length)
448
356
{
449
356
  return sizeof(txU4) * (1 + howmany(3, mxBigIntWordSize) + ((length * 3) / 32));
450
356
}
451
452
txSize fxBigIntMaximumX(txSize length)
453
172k
{
454
172k
  return sizeof(txU4) * (1 + howmany(4, mxBigIntWordSize) + ((length * 4) / 32));
455
172k
}
456
457
void fxBigIntParse(txBigInt* bigint, txString p, txSize length, txInteger sign)
458
89.3k
{
459
89.3k
  txU4 data[1] = { 0 };
460
89.3k
  txBigInt digit = { .sign=0, .size=1, .data=data };
461
89.3k
  bigint->sign = 0;
462
89.3k
  bigint->size = 1;
463
89.3k
  bigint->data[0] = 0;
464
189k
  while (length) {
465
99.7k
    char c = *p++;
466
99.7k
    data[0] = c - '0';
467
99.7k
    fxBigInt_uadd(NULL, bigint, fxBigInt_umul1(NULL, bigint, bigint, 10), &digit);
468
99.7k
    length--;
469
99.7k
  }
470
89.3k
  if ((bigint->size > 1) || (bigint->data[0] != 0))
471
38.6k
    bigint->sign = sign;
472
89.3k
}
473
474
void fxBigIntParseB(txBigInt* bigint, txString p, txSize length)
475
1.39k
{
476
1.39k
  txU4 data[1] = { 0 };
477
1.39k
  txBigInt digit = { .sign=0, .size=1, .data=data };
478
1.39k
  bigint->sign = 0;
479
1.39k
  bigint->size = 1;
480
1.39k
  bigint->data[0] = 0;
481
4.07k
  while (length) {
482
2.67k
    char c = *p++;
483
2.67k
    data[0] = c - '0';
484
2.67k
    fxBigInt_uadd(NULL, bigint, fxBigInt_ulsl1(NULL, bigint, bigint, 1), &digit);
485
2.67k
    length--;
486
2.67k
  }
487
1.39k
}
488
489
void fxBigIntParseO(txBigInt* bigint, txString p, txSize length)
490
356
{
491
356
  txU4 data[1] = { 0 };
492
356
  txBigInt digit = { .sign=0, .size=1, .data=data };
493
356
  bigint->sign = 0;
494
356
  bigint->size = 1;
495
356
  bigint->data[0] = 0;
496
2.10k
  while (length) {
497
1.75k
    char c = *p++;
498
1.75k
    data[0] = c - '0';
499
1.75k
    fxBigInt_uadd(NULL, bigint, fxBigInt_ulsl1(NULL, bigint, bigint, 3), &digit);
500
1.75k
    length--;
501
1.75k
  }
502
356
}
503
504
void fxBigIntParseX(txBigInt* bigint, txString p, txSize length)
505
172k
{
506
172k
  txU4 data[1] = { 0 };
507
172k
  txBigInt digit = { .sign=0, .size=1, .data=data };
508
172k
  bigint->sign = 0;
509
172k
  bigint->size = 1;
510
172k
  bigint->data[0] = 0;
511
1.55M
  while (length) {
512
1.38M
    char c = *p++;
513
1.38M
    if (('0' <= c) && (c <= '9'))
514
179k
      data[0] = c - '0';
515
1.20M
    else if (('a' <= c) && (c <= 'f'))
516
347k
      data[0] = 10 + c - 'a';
517
859k
    else
518
859k
      data[0] = 10 + c - 'A';
519
1.38M
    fxBigInt_uadd(NULL, bigint, fxBigInt_ulsl1(NULL, bigint, bigint, 4), &digit);
520
1.38M
    length--;
521
1.38M
  }
522
172k
}
523
524
#ifndef mxCompile
525
526
void fxBigintToArrayBuffer(txMachine* the, txSlot* slot, txU4 total, txBoolean sign, int endian)
527
53.6k
{
528
53.6k
  txBigInt* bigint = fxToBigInt(the, slot, 1);
529
53.6k
  txU4 length = howmany(fxBigInt_bitsize(bigint), 8);
530
53.6k
  txU4 offset = 0;
531
53.6k
  txU1 *src, *dst;
532
53.6k
  if (length == 0)
533
53.6k
    length = 1;
534
53.6k
  if (length < total) {
535
26.8k
    if (endian == EndianBig)
536
26.8k
      offset = total - length;
537
26.8k
  }
538
26.8k
  else {
539
26.8k
    total = length;
540
26.8k
  }
541
53.6k
  if (sign) {
542
9.33k
    if (total >= 0x7FFFFFFF)
543
0
      mxRangeError("byteLength too big");
544
9.33k
    offset++;
545
9.33k
    total++;
546
9.33k
  }
547
53.6k
  fxConstructArrayBufferResult(the, mxThis, total);
548
53.6k
  src = (txU1*)(bigint->data);
549
53.6k
  dst = (txU1*)(mxResult->value.reference->next->value.arrayBuffer.address);
550
53.6k
  if (sign)
551
9.33k
    *dst = bigint->sign;
552
53.6k
  dst += offset;
553
#if mxBigEndian
554
  if (endian != EndianLittle) {
555
#else
556
53.6k
  if (endian != EndianBig) {
557
1
#endif  
558
1
    c_memcpy(dst, src, length);
559
1
  }
560
53.6k
  else {
561
53.6k
    src += length;
562
107k
    while (length > 0) {
563
53.6k
      src--;
564
53.6k
      *dst = *src;
565
53.6k
      dst++;
566
53.6k
      length--;
567
53.6k
    }
568
53.6k
  }
569
53.6k
}
570
571
txNumber fxBigIntToNumber(txMachine* the, txSlot* slot)
572
636
{
573
636
  txBigInt* bigint = &slot->value.bigint;
574
636
  txNumber base = 4294967296;
575
636
  txNumber number = 0;
576
636
  int i;
577
1.43k
  for (i = bigint->size; --i >= 0;)
578
801
    number = (number * base) + bigint->data[i];
579
636
  if (bigint->sign)
580
264
    number = -number;
581
636
  slot->value.number = number;
582
636
  slot->kind = XS_NUMBER_KIND;
583
636
  return number;
584
636
}
585
586
typedef struct {
587
  uint32_t k;
588
  uint32_t base_to_k;
589
} BaseChunk32;
590
591
static const BaseChunk32 base_chunks32[] ICACHE_FLASH_ATTR = {
592
  {31, 0x80000000},
593
  {19, 1162261467},
594
  {15, 1073741824},
595
  {13, 1220703125},
596
  {12, 2176782336},
597
  {11, 1977326743},
598
  {10, 1073741824},
599
  {10, 3486784401},
600
  { 9, 1000000000},   // base 10
601
  { 8, 214358881},
602
  { 8, 429981696},
603
  { 7, 62748517},
604
  { 7, 105413504},
605
  { 7, 170859375},
606
  { 7, 268435456},
607
  { 6, 24137569},
608
  { 6, 34012224},
609
  { 6, 47045881},
610
  { 6, 64000000},
611
  { 6, 85766121},
612
  { 6, 113379904},
613
  { 6, 148035889},
614
  { 6, 191102976},
615
  { 5, 9765625},
616
  { 5, 11881376},
617
  { 5, 14348907},
618
  { 5, 17210368},
619
  { 5, 20511149},
620
  { 5, 24300000},
621
  { 5, 28629151},
622
  { 5, 33554432},
623
  { 5, 39135393},
624
  { 5, 45435424},
625
  { 5, 52521875},
626
  { 5, 60466176}
627
};
628
629
void fxBigintToString(txMachine* the, txSlot* slot, txU4 radix)
630
177k
{
631
177k
  static const char gxDigits[] ICACHE_FLASH_ATTR = "0123456789abcdefghijklmnopqrstuvwxyz";
632
177k
  txSize length, offset;
633
177k
  txSlot* result;
634
177k
  txSlot* stack;
635
177k
  if (0 == radix) radix = 10;
636
177k
  const BaseChunk32 *bc = base_chunks32 + (radix - 2);
637
638
177k
  if (mxBigIntIsNaN(&slot->value.bigint)) {
639
0
    fxStringX(the, slot, "NaN");
640
0
    return;
641
0
  }
642
177k
  mxBigInt_meter(slot->value.bigint.size);
643
644
177k
  mxPushUndefined();
645
177k
  result = the->stack;
646
  
647
177k
  mxPushSlot(slot);
648
177k
  fxBigInt_dup(the, &the->stack->value.bigint);
649
177k
  stack = the->stack;
650
651
177k
  length = 1 + bc->k + (txSize)c_ceil((txNumber)(stack->value.bigint.size + 1) * 32 * c_log(2) / c_log(radix));
652
177k
  if (stack->value.bigint.sign)
653
84.6k
    length++;
654
177k
  offset = length;
655
177k
  result->value.string = fxNewChunk(the, length);
656
177k
  result->kind = XS_STRING_KIND;
657
658
177k
  result->value.string[--offset] = 0;
659
177k
  int32_t nonZeroWords = stack->value.bigint.size;
660
308k
  do {
661
308k
    uint64_t carry = 0;
662
38.0M
    for (uint32_t i = nonZeroWords - 1, count = nonZeroWords, base_to_k = bc->base_to_k; count > 0; --count) {
663
37.6M
      carry = (carry << 32) | stack->value.bigint.data[i];
664
37.6M
      stack->value.bigint.data[i--] = (uint32_t)(carry / base_to_k);
665
37.6M
      carry %= base_to_k;
666
37.6M
    }
667
308k
    uint32_t remainder = (uint32_t)carry, k = bc->k;
668
6.42M
    do {
669
6.42M
      result->value.string[--offset] = c_read8(gxDigits + (remainder % radix));
670
6.42M
      remainder /= radix;
671
6.42M
    } while (--k);
672
673
609k
    while (nonZeroWords && (0 == stack->value.bigint.data[nonZeroWords - 1]))
674
300k
      nonZeroWords -= 1;
675
308k
  } while (nonZeroWords);
676
677
4.88M
  while (('0' == result->value.string[offset]) && result->value.string[offset + 1])
678
4.71M
    offset++;
679
680
177k
  if (stack->value.bigint.sign)
681
84.6k
    result->value.string[--offset] = '-';
682
177k
  c_memmove(result->value.string, result->value.string + offset, length - offset);
683
684
177k
  mxPop();
685
177k
  mxPop();
686
177k
  mxPullSlot(slot);
687
177k
}
688
689
txS8 fxToBigInt64(txMachine* the, txSlot* slot)
690
143
{
691
143
  return (txS8)fxToBigUint64(the, slot);
692
143
}
693
694
txU8 fxToBigUint64(txMachine* the, txSlot* slot)
695
372
{
696
372
  txBigInt* bigint = fxToBigInt(the, slot, 1);
697
372
  txU8 result = bigint->data[0];
698
372
  if (bigint->size > 1)
699
179
    result |= (txU8)(bigint->data[1]) << 32;
700
372
  if (bigint->sign && result) {
701
32
    result--;
702
32
    result = 0xFFFFFFFFFFFFFFFFll - result;
703
32
  }
704
372
  return result;
705
372
}
706
707
txBigInt* fxIntegerToBigInt(txMachine* the, txSlot* slot)
708
411
{
709
411
  txInteger integer = slot->value.integer;
710
411
  txBigInt* bigint = &slot->value.bigint;
711
411
  txU1 sign = 0;
712
411
  txU4 uint;
713
411
  if (integer < 0) {
714
17
    uint = (-2147483648 == integer) ? 2147483648 : -integer;
715
17
    sign = 1;
716
17
  }
717
394
  else
718
394
    uint = integer;
719
411
  bigint->data = fxNewChunk(the, sizeof(txU4));
720
411
  bigint->data[0] = uint;
721
411
  bigint->sign = sign;
722
411
  bigint->size = 1;
723
411
  slot->kind = XS_BIGINT_KIND;
724
411
  return bigint;
725
411
}
726
727
txBigInt* fxNumberToBigInt(txMachine* the, txSlot* slot)
728
3.73M
{
729
3.73M
  txBigInt* bigint = &slot->value.bigint;
730
3.73M
  txNumber number = slot->value.number;
731
3.73M
  txNumber limit = 4294967296;
732
3.73M
  txU1 sign = 0;
733
3.73M
  txU2 size = 1;
734
3.73M
  if (number < 0) {
735
1.44M
    number = -number;
736
1.44M
    sign = 1;
737
1.44M
  }
738
5.68M
  while (number >= limit) {
739
1.95M
    size++;
740
1.95M
    number /= limit;
741
1.95M
  }
742
3.73M
  bigint->data = fxNewChunk(the, fxMultiplyChunkSizes(the, size, sizeof(txU4)));
743
3.73M
  bigint->size = size;
744
9.42M
  while (size > 0) {
745
5.68M
    txU4 part = (txU4)number;
746
5.68M
    number -= part;
747
5.68M
    size--;
748
5.68M
    bigint->data[size] = part;
749
5.68M
    number *= limit;
750
5.68M
  }
751
3.73M
  bigint->sign = sign;
752
3.73M
  slot->kind = XS_BIGINT_KIND;
753
3.73M
  return bigint;
754
3.73M
}
755
756
txBigInt* fxStringToBigInt(txMachine* the, txSlot* slot, txFlag whole)
757
1.47M
{
758
1.47M
  txString s = slot->value.string;
759
1.47M
  txString p = fxSkipSpaces(s);
760
1.47M
  txSize offset, length;
761
1.47M
  txInteger sign = 0;
762
1.47M
  txBigInt bigint = {.sign=0, .size=0, .data=C_NULL };
763
1.47M
  char c = *p;
764
1.47M
  if (c == '0') {
765
1.42M
    char d = *(p + 1);
766
1.42M
    if (whole && ((d == 'B') || (d == 'b') || (d == 'O') || (d == 'o') || (d == 'X') || (d == 'x'))) {
767
1.14M
      p += 2;
768
1.14M
      offset = mxPtrDiff(p - s);
769
1.14M
      if ((d == 'B') || (d == 'b')) {
770
176k
        while (((c = *p)) && ('0' <= c) && (c <= '1'))
771
1.72k
          p++;
772
175k
        length = mxPtrDiff(p - s - offset);
773
175k
        p = fxSkipSpaces(p);
774
175k
        if ((length > 0) && (*p == 0)) {
775
1.37k
          bigint.data = fxNewChunk(the, fxBigIntMaximumB(length));
776
1.37k
          fxBigIntParseB(&bigint, slot->value.string + offset, length);
777
1.37k
        }
778
175k
      }
779
973k
      else if ((d == 'O') || (d == 'o')) {
780
1.34k
        while (((c = *p)) && ('0' <= c) && (c <= '7'))
781
1.09k
          p++;
782
246
        length = mxPtrDiff(p - s - offset);
783
246
        p = fxSkipSpaces(p);
784
246
        if ((length > 0) && (*p == 0)) {
785
22
          bigint.data = fxNewChunk(the, fxBigIntMaximumO(length));
786
22
          fxBigIntParseO(&bigint, slot->value.string + offset, length);
787
22
        }
788
246
      }
789
973k
      else if ((d == 'X') || (d == 'x')) {
790
5.18M
        while (((c = *p)) && ((('0' <= c) && (c <= '9')) || (('a' <= c) && (c <= 'f')) || (('A' <= c) && (c <= 'F'))))
791
4.20M
          p++;
792
973k
        length = mxPtrDiff(p - s - offset);
793
973k
        p = fxSkipSpaces(p);
794
973k
        if ((length > 0) && (*p == 0)) {
795
172k
          bigint.data = fxNewChunk(the, fxBigIntMaximumX(length));
796
172k
          fxBigIntParseX(&bigint, slot->value.string + offset, length);
797
172k
        }
798
973k
      }
799
1.14M
      goto bail;
800
1.14M
    }
801
1.42M
  }
802
323k
  if (c == '-') {
803
195
    sign = 1;
804
195
    p++;
805
195
  }
806
322k
  else if (c == '+') {
807
100
    p++;
808
100
  }
809
323k
  offset = mxPtrDiff(p - s);
810
605k
  while (((c = *p)) && ('0' <= c) && (c <= '9'))
811
281k
    p++;
812
323k
  length = mxPtrDiff(p - s - offset);
813
323k
  p = fxSkipSpaces(p);
814
323k
  if (*p == 0) {
815
44.4k
    bigint.data = fxNewChunk(the, fxBigIntMaximum(length));
816
44.4k
    fxBigIntParse(&bigint, slot->value.string + offset, length, sign);
817
44.4k
  }
818
1.47M
bail:
819
1.47M
  if (bigint.data) {
820
218k
    slot->value.bigint = bigint;
821
218k
    slot->kind = XS_BIGINT_KIND;
822
218k
  }
823
1.25M
  else {
824
1.25M
    slot->value.bigint = gxBigIntNaN;
825
1.25M
    slot->kind = XS_BIGINT_X_KIND;
826
1.25M
  }
827
1.47M
  return &slot->value.bigint;
828
323k
}
829
830
txBigInt* fxToBigInt(txMachine* the, txSlot* slot, txFlag strict)
831
67.6k
{
832
67.7k
again:
833
67.7k
  switch (slot->kind) {
834
12.4k
  case XS_BOOLEAN_KIND:
835
12.4k
    slot->value.bigint = *fxBigInt_dup(the, (txBigInt *)((slot->value.boolean) ? &gxBigIntOne : &gxBigIntZero));
836
12.4k
    slot->kind = XS_BIGINT_KIND;
837
12.4k
    break;
838
10
  case XS_INTEGER_KIND:
839
10
    if (strict)
840
10
      mxTypeError("cannot coerce number to bigint");
841
0
    fxIntegerToBigInt(the, slot); 
842
0
    break;
843
9
  case XS_NUMBER_KIND:
844
9
    if (strict)
845
9
      mxTypeError("cannot coerce number to bigint");
846
0
    fxNumberToBigInt(the, slot);  
847
0
    break;
848
46.3k
  case XS_STRING_KIND:
849
46.3k
  case XS_STRING_X_KIND:
850
46.3k
    fxStringToBigInt(the, slot, 1);
851
46.3k
    if (mxBigIntIsNaN(&slot->value.bigint))
852
490
      mxSyntaxError("cannot coerce string to bigint");
853
45.8k
    break;
854
45.8k
  case XS_BIGINT_KIND:
855
8.79k
  case XS_BIGINT_X_KIND:
856
8.79k
    break;
857
14
  case XS_SYMBOL_KIND:
858
14
    mxTypeError("cannot coerce symbol to bigint");
859
0
    break;
860
103
  case XS_REFERENCE_KIND:
861
103
    fxToPrimitive(the, slot, XS_NUMBER_HINT);
862
103
    goto again;
863
36
  default:
864
36
    mxTypeError("cannot coerce to bigint");
865
0
    break;
866
67.7k
  }
867
67.0k
  return &slot->value.bigint;
868
67.7k
}
869
870
void fxFromBigInt64(txMachine* the, txSlot* slot, txS8 it)
871
274
{
872
274
  txU1 sign = 0;
873
274
  txU8 value = 0;
874
274
  if (it < 0) {
875
72
    if (it & 0x7FFFFFFFFFFFFFFFll)
876
72
      value = -it;
877
0
    else
878
0
      value = (txU8)it;
879
72
    sign = 1;
880
72
  }
881
202
  else
882
202
    value = it;
883
274
  if (value > 0x00000000FFFFFFFFll) {
884
158
    slot->value.bigint.data = fxNewChunk(the, 2 * sizeof(txU4));
885
158
    slot->value.bigint.data[0] = (txU4)value;
886
158
    slot->value.bigint.data[1] = (txU4)(value >> 32);
887
158
    slot->value.bigint.size = 2;
888
158
  }
889
116
  else {
890
116
    slot->value.bigint.data = fxNewChunk(the, sizeof(txU4));
891
116
    slot->value.bigint.data[0] = (txU4)value;
892
116
    slot->value.bigint.size = 1;
893
116
  }
894
274
    slot->value.bigint.sign = sign;
895
274
  slot->kind = XS_BIGINT_KIND;
896
274
}
897
898
void fxFromBigUint64(txMachine* the, txSlot* slot, txU8 value)
899
101
{
900
101
  if (value > 0x00000000FFFFFFFFll) {
901
70
    slot->value.bigint.data = fxNewChunk(the, 2 * sizeof(txU4));
902
70
    slot->value.bigint.data[0] = (txU4)(value);
903
70
    slot->value.bigint.data[1] = (txU4)(value >> 32);
904
70
    slot->value.bigint.size = 2;
905
70
  }
906
31
  else {
907
31
    slot->value.bigint.data = fxNewChunk(the, sizeof(txU4));
908
31
    slot->value.bigint.data[0] = (txU4)value;
909
31
    slot->value.bigint.size = 1;
910
31
  }
911
101
    slot->value.bigint.sign = 0;
912
101
  slot->kind = XS_BIGINT_KIND;
913
101
}
914
915
#endif
916
917
txBigInt *fxBigInt_alloc(txMachine* the, txU4 size)
918
14.0M
{
919
14.0M
#ifndef mxCompile
920
14.0M
  txBigInt* bigint;
921
14.0M
  if (size > 0xFFFF) {
922
1
    fxAbort(the, XS_NOT_ENOUGH_MEMORY_EXIT);
923
1
  }
924
14.0M
  mxPushUndefined();
925
14.0M
  bigint = &the->stack->value.bigint;
926
14.0M
  bigint->data = fxNewChunk(the, fxMultiplyChunkSizes(the, size, sizeof(txU4)));
927
14.0M
  bigint->size = size;
928
14.0M
  bigint->sign = 0;
929
14.0M
  the->stack->kind = XS_BIGINT_KIND;
930
14.0M
  return bigint;
931
#else
932
  return NULL;
933
#endif
934
14.0M
}
935
936
void fxBigInt_free(txMachine* the, txBigInt *bigint)
937
2.67M
{
938
2.67M
#ifndef mxCompile
939
2.67M
  if (bigint == &the->stack->value.bigint)
940
2.67M
    the->stack++;
941
//  else
942
//    fprintf(stderr, "oops\n");
943
2.67M
#endif
944
2.67M
}
945
946
int fxBigInt_comp(txBigInt *a, txBigInt *b)
947
3.97M
{
948
3.97M
  if (a->sign != b->sign)
949
2.26M
    return(a->sign ? -1: 1);
950
1.70M
  else if (a->sign)
951
477k
    return(fxBigInt_ucomp(b, a));
952
1.22M
  else
953
1.22M
    return(fxBigInt_ucomp(a, b));
954
3.97M
}
955
956
int fxBigInt_ucomp(txBigInt *a, txBigInt *b)
957
4.12M
{
958
4.12M
  int i;
959
960
4.12M
  if (a->size != b->size)
961
2.17M
    return(a->size > b->size ? 1: -1);
962
2.14M
  for (i = a->size; --i >= 0;) {
963
2.05M
    if (a->data[i] != b->data[i])
964
1.86M
      return(a->data[i] > b->data[i] ? 1: -1);
965
2.05M
  }
966
91.3k
  return(0);
967
1.95M
}
968
969
int fxBigInt_iszero(txBigInt *a)
970
9.38M
{
971
9.38M
  return(a->size == 1 && a->data[0] == 0);
972
9.38M
}
973
974
void
975
fxBigInt_fill0(txBigInt *r)
976
726k
{
977
726k
  c_memset(r->data, 0, r->size * sizeof(txU4));
978
726k
}
979
980
void fxBigInt_copy(txBigInt *a, txBigInt *b)
981
8.30M
{
982
8.30M
  c_memmove(a->data, b->data, b->size * sizeof(txU4));
983
8.30M
  a->size = b->size;
984
8.30M
  a->sign = b->sign;
985
8.30M
}
986
987
txBigInt *fxBigInt_dup(txMachine* the, txBigInt *a)
988
192k
{
989
192k
  txBigInt *r = fxBigInt_alloc(the, a->size);
990
192k
  fxBigInt_copy(r, a);
991
192k
  return(r);
992
192k
}
993
994
int
995
fxBigInt_ffs(txBigInt *a)
996
6.50k
{
997
6.50k
  int i;
998
6.50k
  txU4 w = a->data[a->size - 1];
999
1000
170k
  for (i = 0; i < (int)mxBigIntWordSize && !(w & ((txU4)1 << (mxBigIntWordSize - 1 - i))); i++)
1001
163k
    ;
1002
6.50k
  return(i);
1003
6.50k
}
1004
1005
txBigInt *fxBigInt_fit(txMachine* the, txBigInt *r)
1006
1.07M
{
1007
1.07M
  int i = r->size;
1008
1.18M
  while (i > 0) {
1009
1.15M
    i--;
1010
1.15M
    if (r->data[i])
1011
1.05M
      break;
1012
1.15M
  }
1013
1.07M
  r->size = (txU2)(i + 1);
1014
1.07M
  mxBigInt_meter(r->size);
1015
1.07M
  return r;
1016
1.07M
}
1017
1018
1019
#if mxWindows
1020
int
1021
fxBigInt_bitsize(txBigInt *e)
1022
{
1023
  return(e->size * mxBigIntWordSize - fxBigInt_ffs(e));
1024
}
1025
#else
1026
int
1027
fxBigInt_bitsize(txBigInt *a)
1028
201k
{
1029
201k
  int i = a->size;
1030
201k
  txU4 w;
1031
257k
  while (i > 0) {
1032
201k
    i--;
1033
201k
    w = a->data[i];
1034
201k
    if (w) {
1035
146k
      int c = __builtin_clz(w);
1036
146k
      return (i * mxBigIntWordSize) + mxBigIntWordSize - c;
1037
146k
    }
1038
201k
  }
1039
55.7k
  return 0;
1040
201k
}
1041
#endif
1042
1043
int fxBigInt_isset(txBigInt *e, txU4 i)
1044
485k
{
1045
485k
  txU4 w = e->data[i / mxBigIntWordSize];
1046
485k
  return((w & ((txU4)1 << (i % mxBigIntWordSize))) != 0);
1047
485k
}
1048
1049
/*
1050
 * bitwise operations
1051
 */
1052
1053
txBigInt *fxBigInt_not(txMachine* the, txBigInt *r, txBigInt *a)
1054
359k
{
1055
359k
  if (a->sign)
1056
257
    r = fxBigInt_usub(the, r, a, (txBigInt *)&gxBigIntOne);
1057
359k
  else {
1058
359k
    r = fxBigInt_uadd(the, r, a, (txBigInt *)&gxBigIntOne);
1059
359k
    r->sign = 1;
1060
359k
  }
1061
359k
  return(r);
1062
359k
}
1063
1064
txBigInt *fxBigInt_and(txMachine* the, txBigInt *r, txBigInt *a, txBigInt *b)
1065
3.94k
{
1066
3.94k
  txBigInt *aa, *bb;
1067
3.94k
  int i;
1068
3.94k
  if (a->sign) {
1069
1.97k
    if (b->sign)
1070
1.64k
      goto AND_MINUS_MINUS;
1071
332
    aa = a;
1072
332
    a = b;
1073
332
    b = aa; 
1074
332
    goto AND_PLUS_MINUS;
1075
1.97k
  }
1076
1.97k
  if (b->sign)
1077
1.22k
    goto AND_PLUS_MINUS;
1078
741
  return fxBigInt_fit(the, fxBigInt_uand(the, r, a, b));
1079
1.56k
AND_PLUS_MINUS:
1080
// GMP: OP1 & -OP2 == OP1 & ~(OP2 - 1)
1081
1.56k
  if (r == NULL)
1082
1.56k
    r = fxBigInt_alloc(the, a->size);
1083
1.56k
  bb = fxBigInt_usub(the, NULL, b, (txBigInt *)&gxBigIntOne);
1084
1.56k
    if (a->size > bb->size) {
1085
2.91k
    for (i = 0; i < bb->size; i++)
1086
1.90k
      r->data[i] = a->data[i] & ~bb->data[i];
1087
8.43k
    for (; i < a->size; i++)
1088
7.43k
      r->data[i] = a->data[i];
1089
1.00k
    }
1090
554
    else {
1091
1.17k
    for (i = 0; i < a->size; i++)
1092
617
      r->data[i] = a->data[i] & ~bb->data[i];
1093
554
    }
1094
1.56k
    fxBigInt_free(the, bb);
1095
1.56k
  return fxBigInt_fit(the, r);
1096
1.64k
AND_MINUS_MINUS:
1097
// GMP: -((-OP1) & (-OP2)) = -(~(OP1 - 1) & ~(OP2 - 1)) == ~(~(OP1 - 1) & ~(OP2 - 1)) + 1 == ((OP1 - 1) | (OP2 - 1)) + 1
1098
1.64k
  if (r == NULL)
1099
1.64k
    r = fxBigInt_alloc(the, MAX(a->size, b->size) + 1);
1100
1.64k
  aa = fxBigInt_usub(the, NULL, a, (txBigInt *)&gxBigIntOne);
1101
1.64k
  bb = fxBigInt_usub(the, NULL, b, (txBigInt *)&gxBigIntOne);
1102
1.64k
  r = fxBigInt_uor(the, r, aa, bb);
1103
1.64k
  r = fxBigInt_uadd(the, r, r, (txBigInt *)&gxBigIntOne);
1104
1.64k
  r->sign = 1;
1105
1.64k
  fxBigInt_free(the, bb);
1106
1.64k
  fxBigInt_free(the, aa);
1107
1.64k
  return fxBigInt_fit(the, r);
1108
1.97k
}
1109
1110
txBigInt *fxBigInt_uand(txMachine* the, txBigInt *r, txBigInt *a, txBigInt *b)
1111
127k
{
1112
127k
  int i;
1113
127k
  if (a->size > b->size) {
1114
101k
    txBigInt *t = b;
1115
101k
    b = a;
1116
101k
    a = t;
1117
101k
  }
1118
127k
  if (r == NULL)
1119
9.50k
    r = fxBigInt_alloc(the, a->size);
1120
118k
  else
1121
118k
    r->size = a->size;
1122
777k
  for (i = 0; i < a->size; i++)
1123
649k
    r->data[i] = a->data[i] & b->data[i];
1124
127k
  return(r);
1125
127k
}
1126
1127
txBigInt *fxBigInt_or(txMachine* the, txBigInt *r, txBigInt *a, txBigInt *b)
1128
532k
{
1129
532k
  txBigInt *aa, *bb;
1130
532k
  int i;
1131
532k
  mxBigInt_meter(MAX(a->size, b->size));
1132
532k
  if (a->sign) {
1133
480k
    if (b->sign)
1134
118k
      goto OR_MINUS_MINUS;
1135
362k
    aa = a;
1136
362k
    a = b;
1137
362k
    b = aa; 
1138
362k
    goto OR_PLUS_MINUS;
1139
480k
  }
1140
52.0k
  if (b->sign)
1141
50.2k
    goto OR_PLUS_MINUS;
1142
1.80k
  return fxBigInt_fit(the, fxBigInt_uor(the, r, a, b));
1143
412k
OR_PLUS_MINUS:
1144
// GMP: -(OP1 | (-OP2)) = -(OP1 | ~(OP2 - 1)) == ~(OP1 | ~(OP2 - 1)) + 1 == (~OP1 & (OP2 - 1)) + 1
1145
412k
  if (r == NULL)
1146
412k
    r = fxBigInt_alloc(the, b->size + 1);
1147
412k
  bb = fxBigInt_usub(the, NULL, b, (txBigInt *)&gxBigIntOne);
1148
412k
    if (a->size < bb->size) {
1149
289k
    for (i = 0; i < a->size; i++)
1150
148k
      r->data[i] = ~a->data[i] & bb->data[i];
1151
580k
    for (; i < bb->size; i++)
1152
439k
      r->data[i] = bb->data[i];
1153
141k
  }
1154
271k
  else {
1155
693k
    for (i = 0; i < bb->size; i++)
1156
422k
      r->data[i] = ~a->data[i] & bb->data[i];
1157
271k
  }
1158
412k
  r->size = bb->size;
1159
412k
  r = fxBigInt_uadd(the, r, r, (txBigInt *)&gxBigIntOne);
1160
412k
  r->sign = 1;
1161
412k
  fxBigInt_free(the, bb);
1162
412k
  return fxBigInt_fit(the, r);
1163
118k
OR_MINUS_MINUS:
1164
// GMP: -((-OP1) | (-OP2)) = -(~(OP1 - 1) | ~(OP2 - 1)) == ~(~(OP1 - 1) | ~(OP2 - 1)) + 1 = = ((OP1 - 1) & (OP2 - 1)) + 1
1165
118k
  if (r == NULL)
1166
118k
    r = fxBigInt_alloc(the, MIN(a->size, b->size) + 1);
1167
118k
  aa = fxBigInt_usub(the, NULL, a, (txBigInt *)&gxBigIntOne);
1168
118k
  bb = fxBigInt_usub(the, NULL, b, (txBigInt *)&gxBigIntOne);
1169
118k
  r = fxBigInt_uand(the, r, aa, bb);
1170
118k
  r = fxBigInt_uadd(the, r, r, (txBigInt *)&gxBigIntOne);
1171
118k
  r->sign = 1;
1172
118k
  fxBigInt_free(the, bb);
1173
118k
  fxBigInt_free(the, aa);
1174
118k
  return fxBigInt_fit(the, r);
1175
52.0k
}
1176
1177
txBigInt *fxBigInt_uor(txMachine* the, txBigInt *r, txBigInt *a, txBigInt *b)
1178
3.45k
{
1179
3.45k
  int i;
1180
3.45k
  if (a->size < b->size) {
1181
1.91k
    txBigInt *t = b;
1182
1.91k
    b = a;
1183
1.91k
    a = t;
1184
1.91k
  }
1185
3.45k
  if (r == NULL)
1186
1.80k
    r = fxBigInt_alloc(the, a->size);
1187
1.64k
  else
1188
1.64k
    r->size = a->size;
1189
8.22k
  for (i = 0; i < b->size; i++)
1190
4.77k
    r->data[i] = a->data[i] | b->data[i];
1191
259k
  for (; i < a->size; i++)
1192
256k
    r->data[i] = a->data[i];
1193
3.45k
  return(r);
1194
3.45k
}
1195
1196
txBigInt *fxBigInt_xor(txMachine* the, txBigInt *r, txBigInt *a, txBigInt *b)
1197
309k
{
1198
309k
  txBigInt *aa, *bb;
1199
309k
  if (a->sign) {
1200
7.82k
    if (b->sign)
1201
7.68k
      goto XOR_MINUS_MINUS;
1202
135
    aa = a;
1203
135
    a = b;
1204
135
    b = aa; 
1205
135
    goto XOR_PLUS_MINUS;
1206
7.82k
  }
1207
301k
  if (b->sign)
1208
284k
    goto XOR_PLUS_MINUS;
1209
16.6k
  return fxBigInt_fit(the, fxBigInt_uxor(the, r, a, b));
1210
284k
XOR_PLUS_MINUS:
1211
// GMP: -(OP1 ^ (-OP2)) == -(OP1 ^ ~(OP2 - 1)) == ~(OP1 ^ ~(OP2 - 1)) + 1 == (OP1 ^ (OP2 - 1)) + 1
1212
284k
  if (r == NULL)
1213
284k
    r = fxBigInt_alloc(the, MAX(a->size, b->size) + 1);
1214
284k
  bb = fxBigInt_usub(the, NULL, b, (txBigInt *)&gxBigIntOne);
1215
284k
  r = fxBigInt_uxor(the, r, a, bb);
1216
284k
  r = fxBigInt_uadd(the, r, r, (txBigInt *)&gxBigIntOne);
1217
284k
  r->sign = 1;
1218
284k
  fxBigInt_free(the, bb);
1219
284k
  return fxBigInt_fit(the, r);
1220
7.68k
XOR_MINUS_MINUS:
1221
// GMP: (-OP1) ^ (-OP2) == ~(OP1 - 1) ^ ~(OP2 - 1) == (OP1 - 1) ^ (OP2 - 1)
1222
7.68k
  if (r == NULL)
1223
7.68k
    r = fxBigInt_alloc(the, MAX(a->size, b->size));
1224
7.68k
  aa = fxBigInt_usub(the, NULL, a, (txBigInt *)&gxBigIntOne);
1225
7.68k
  bb = fxBigInt_usub(the, NULL, b, (txBigInt *)&gxBigIntOne);
1226
7.68k
  r = fxBigInt_uxor(the, r, aa, bb);
1227
7.68k
  fxBigInt_free(the, bb);
1228
7.68k
  fxBigInt_free(the, aa);
1229
7.68k
  return fxBigInt_fit(the, r);
1230
301k
}
1231
1232
txBigInt *fxBigInt_uxor(txMachine* the, txBigInt *r, txBigInt *a, txBigInt *b)
1233
309k
{
1234
309k
  int i;
1235
309k
  if (a->size < b->size) {
1236
74.5k
    txBigInt *t = b;
1237
74.5k
    b = a;
1238
74.5k
    a = t;
1239
74.5k
  }
1240
309k
  if (r == NULL)
1241
16.6k
    r = fxBigInt_alloc(the, a->size);
1242
292k
  else
1243
292k
    r->size = a->size;
1244
655k
  for (i = 0; i < b->size; i++)
1245
346k
    r->data[i] = a->data[i] ^ b->data[i];
1246
7.39M
  for (; i < a->size; i++)
1247
7.08M
    r->data[i] = a->data[i];
1248
309k
  return(r);
1249
309k
}
1250
1251
txBigInt *fxBigInt_lsl(txMachine* the, txBigInt *r, txBigInt *a, txBigInt *b)
1252
1.60k
{
1253
1.60k
  if (b->sign) {
1254
584
    if (a->sign) {
1255
280
      r = fxBigInt_ulsr1(the, r, a, b->data[0]);
1256
280
            if (b->data[0])
1257
279
                r = fxBigInt_uadd(the, C_NULL, r, (txBigInt *)&gxBigIntOne);
1258
280
      r->sign = 1;
1259
280
    }
1260
304
    else
1261
304
      r = fxBigInt_ulsr1(the, r, a, b->data[0]);
1262
584
  }
1263
1.02k
  else {
1264
1.02k
    r = fxBigInt_ulsl1(the, r, a, b->data[0]);
1265
1.02k
    r->sign = a->sign;
1266
1.02k
  }
1267
1.60k
  return fxBigInt_fit(the, r);
1268
1.60k
}
1269
1270
txBigInt *fxBigInt_ulsl1(txMachine* the, txBigInt *r, txBigInt *a, txU4 sw)
1271
1.45M
{
1272
1.45M
  txU4 wsz, bsz;
1273
1.45M
  int n;
1274
1275
1.45M
  wsz = sw / mxBigIntWordSize;
1276
1.45M
  bsz = sw % mxBigIntWordSize;
1277
1.45M
  n = a->size + wsz + ((bsz == 0) ? 0 : 1);
1278
1.45M
  if (r == NULL) 
1279
60.9k
    r = fxBigInt_alloc(the, n);
1280
1.45M
  if (bsz == 0) {
1281
11.1k
    c_memmove(&r->data[wsz], a->data, a->size * sizeof(txU4));
1282
11.1k
    c_memset(r->data, 0, wsz * sizeof(txU4));
1283
11.1k
    r->size = a->size + wsz;
1284
11.1k
  }
1285
1.44M
  else {
1286
1.44M
    r->data[a->size + wsz] = a->data[a->size - 1] >> (mxBigIntWordSize - bsz);
1287
1.60M
    for (n = a->size; --n >= 1;)
1288
164k
      r->data[n + wsz] = (a->data[n] << bsz) | (a->data[n - 1] >> (mxBigIntWordSize - bsz));
1289
1.44M
    r->data[wsz] = a->data[0] << bsz;
1290
    /* clear the remaining part */
1291
4.58M
    for (n = wsz; --n >= 0;)
1292
3.14M
      r->data[n] = 0;
1293
    /* adjust r */
1294
1.44M
    r->size = a->size + wsz + (r->data[a->size + wsz] == 0 ? 0: 1);
1295
1.44M
  }
1296
1.45M
  return(r);
1297
1.45M
}
1298
1299
txBigInt *fxBigInt_lsr(txMachine* the, txBigInt *r, txBigInt *a, txBigInt *b)
1300
224k
{
1301
224k
  if (b->sign) {
1302
26.2k
    r = fxBigInt_ulsl1(the, r, a, b->data[0]);
1303
26.2k
    r->sign = a->sign;
1304
26.2k
  }
1305
198k
  else {
1306
198k
    if (a->sign) {
1307
150k
      r = fxBigInt_ulsr1(the, r, a, b->data[0]);
1308
150k
            if (b->data[0])
1309
148k
                r = fxBigInt_uadd(the, C_NULL, r, (txBigInt *)&gxBigIntOne);
1310
150k
      r->sign = 1;
1311
150k
    }
1312
47.7k
    else
1313
47.7k
      r = fxBigInt_ulsr1(the, r, a, b->data[0]);
1314
198k
  }
1315
224k
  return fxBigInt_fit(the, r);
1316
224k
}
1317
1318
txBigInt *fxBigInt_ulsr1(txMachine* the, txBigInt *r, txBigInt *a, txU4 sw)
1319
350k
{
1320
350k
  int wsz, bsz;
1321
350k
  int i, n;
1322
1323
350k
  wsz = sw / mxBigIntWordSize;
1324
350k
  bsz = sw % mxBigIntWordSize;
1325
350k
  n = a->size - wsz;
1326
350k
  if (n <= 0) {
1327
97.7k
    if (r == NULL) r = fxBigInt_alloc(the, 1);
1328
97.7k
    r->size = 1;
1329
97.7k
    r->data[0] = 0;
1330
97.7k
    return(r);
1331
97.7k
  }
1332
  /* 'r' can be the same as 'a' */
1333
253k
  if (r == NULL)
1334
100k
    r = fxBigInt_alloc(the, n);
1335
253k
  if (bsz == 0) {
1336
76.5k
    c_memmove(r->data, &a->data[wsz], n * sizeof(txU4));
1337
76.5k
    r->size = n;
1338
76.5k
  }
1339
176k
  else {
1340
199k
    for (i = 0; i < n - 1; i++)
1341
22.5k
      r->data[i] = (a->data[i + wsz] >> bsz) | (a->data[i + wsz + 1] << (mxBigIntWordSize - bsz));
1342
176k
    r->data[i] = a->data[i + wsz] >> bsz;
1343
176k
    r->size = (n > 1 && r->data[n - 1] == 0) ? n - 1: n;
1344
176k
  }
1345
253k
  return(r);
1346
350k
}
1347
1348
txBigInt *fxBigInt_nop(txMachine* the, txBigInt *r, txBigInt *a, txBigInt *b)
1349
71.0k
{
1350
71.0k
#ifndef mxCompile
1351
71.0k
  mxTypeError("no such operation");
1352
0
#endif
1353
0
  return C_NULL;
1354
71.0k
}
1355
1356
/*
1357
 * arithmetic
1358
 */
1359
1360
txBigInt *fxBigInt_add(txMachine* the, txBigInt *rr, txBigInt *aa, txBigInt *bb)
1361
1.23M
{
1362
1.23M
  if ((aa->sign ^ bb->sign) == 0) {
1363
948k
    rr = fxBigInt_uadd(the, rr, aa, bb);
1364
948k
    if (aa->sign)
1365
1.22k
      rr->sign = 1;
1366
948k
  }
1367
291k
  else {
1368
291k
    if (!aa->sign)
1369
2.05k
      rr = fxBigInt_usub(the, rr, aa, bb);
1370
289k
    else
1371
289k
      rr = fxBigInt_usub(the, rr, bb, aa);
1372
291k
  }
1373
1.23M
  mxBigInt_meter(rr->size);
1374
1.23M
  return(rr);
1375
1.23M
}
1376
1377
txBigInt *fxBigInt_dec(txMachine* the, txBigInt *r, txBigInt *a)
1378
19
{
1379
19
  return fxBigInt_sub(the, r, a, (txBigInt *)&gxBigIntOne);
1380
19
}
1381
1382
txBigInt *fxBigInt_inc(txMachine* the, txBigInt *r, txBigInt *a)
1383
1.23M
{
1384
1.23M
  return fxBigInt_add(the, r, a, (txBigInt *)&gxBigIntOne);
1385
1.23M
}
1386
1387
txBigInt *fxBigInt_neg(txMachine* the, txBigInt *r, txBigInt *a)
1388
6.51M
{
1389
6.51M
  if (r == NULL)
1390
6.51M
    r = fxBigInt_alloc(the, a->size);
1391
6.51M
  fxBigInt_copy(r, a);
1392
6.51M
  if (!fxBigInt_iszero(a))
1393
5.97M
    r->sign = !a->sign;
1394
6.51M
  return(r);
1395
6.51M
}
1396
1397
txBigInt *fxBigInt_sub(txMachine* the, txBigInt *rr, txBigInt *aa, txBigInt *bb)
1398
10.9k
{
1399
10.9k
  if ((aa->sign ^ bb->sign) == 0) {
1400
9.79k
    if (!aa->sign)
1401
9.31k
      rr = fxBigInt_usub(the, rr, aa, bb);
1402
487
    else
1403
487
      rr = fxBigInt_usub(the, rr, bb, aa);
1404
9.79k
  }
1405
1.11k
  else {
1406
1.11k
    txU1 sign = aa->sign; /* could be replaced if rr=aa */
1407
1.11k
    rr = fxBigInt_uadd(the, rr, aa, bb);
1408
1.11k
    rr->sign = sign;
1409
1.11k
  }
1410
10.9k
  mxBigInt_meter(rr->size);
1411
10.9k
  return(rr);
1412
10.9k
}
1413
1414
#if __has_builtin(__builtin_add_overflow)
1415
static int fxBigInt_uadd_prim(txU4 *rp, txU4 *ap, txU4 *bp, int an, int bn)
1416
3.76M
{
1417
3.76M
  txU4 c = 0;
1418
3.76M
  int i;
1419
1420
7.53M
  for (i = 0; i < an; i++) {
1421
#ifdef __ets__
1422
  unsigned int r;
1423
  if (__builtin_uadd_overflow(ap[i], bp[i], &r)) {
1424
    rp[i] = r + c;
1425
    c = 1;
1426
  }
1427
  else {
1428
    unsigned int t;
1429
    c = __builtin_uadd_overflow(r, c, &t);
1430
    rp[i] = t;
1431
  }
1432
#else
1433
3.76M
    unsigned int r = rp[i];
1434
3.76M
    c = __builtin_uadd_overflow(ap[i], bp[i], &r) | (txU4)__builtin_uadd_overflow(r, c, &r);
1435
3.76M
    rp[i] = r;
1436
3.76M
#endif
1437
3.76M
  }
1438
3.97M
  for (; c && (i < bn); i++) { {
1439
205k
    unsigned int t;
1440
205k
    c = __builtin_uadd_overflow(1, bp[i], &t);
1441
205k
    rp[i] = t;
1442
205k
  }
1443
205k
  }
1444
12.3M
  for (; i < bn; i++) {
1445
8.57M
    rp[i] = bp[i];
1446
8.57M
  }
1447
3.76M
  return(c);
1448
3.76M
}
1449
#else
1450
static int fxBigInt_uadd_prim(txU4 *rp, txU4 *ap, txU4 *bp, int an, int bn)
1451
{
1452
  txU4 a, b, t, r, c = 0;
1453
  int i;
1454
1455
  for (i = 0; i < an; i++) {
1456
    a = ap[i];
1457
    b = bp[i];
1458
    t = a + b;
1459
    r = t + c;
1460
    rp[i] = r;
1461
    c = t < a || r < t;
1462
  }
1463
  for (; i < bn; i++) {
1464
    r = bp[i] + c;
1465
    rp[i] = r;
1466
    c = r < c;
1467
  }
1468
  return(c);
1469
}
1470
#endif
1471
1472
txBigInt *fxBigInt_uadd(txMachine* the, txBigInt *rr, txBigInt *aa, txBigInt *bb)
1473
3.76M
{
1474
3.76M
  txBigInt *x, *y;
1475
3.76M
  int c;
1476
1477
3.76M
  if (aa->size < bb->size) {
1478
54
    x = aa;
1479
54
    y = bb;
1480
54
  }
1481
3.76M
  else {
1482
3.76M
    x = bb;
1483
3.76M
    y = aa;
1484
3.76M
  }
1485
3.76M
  if (rr == NULL)
1486
1.45M
    rr = fxBigInt_alloc(the, y->size + 1);
1487
3.76M
  c = fxBigInt_uadd_prim(rr->data, x->data, y->data, x->size, y->size);
1488
  /* CAUTION: rr may equals aa or bb. do not touch until here */
1489
3.76M
  rr->size = y->size;
1490
3.76M
  rr->sign = 0;
1491
3.76M
  if (c != 0)
1492
1.77k
    rr->data[rr->size++] = 1;
1493
3.76M
  return(rr);
1494
3.76M
}
1495
1496
txBigInt *fxBigInt_usub(txMachine* the, txBigInt *rr, txBigInt *aa, txBigInt *bb)
1497
1.33M
{
1498
1.33M
  int i, n;
1499
1.33M
  txU4 a, b, r, t;
1500
1.33M
  txU4 *ap, *bp, *rp;
1501
1.33M
  txU4 c = 0;
1502
1503
1.33M
  if (rr == NULL)
1504
1.26M
    rr = fxBigInt_alloc(the, MAX(aa->size, bb->size));
1505
1.33M
  rr->sign = (aa->size < bb->size ||
1506
1.26M
        (aa->size == bb->size && fxBigInt_ucomp(aa, bb) < 0));
1507
1.33M
  if (rr->sign) {
1508
276k
    txBigInt *tt = aa;
1509
276k
    aa = bb;
1510
276k
    bb = tt;
1511
276k
  }
1512
1.33M
  ap = aa->data;
1513
1.33M
  bp = bb->data;
1514
1.33M
  rp = rr->data;
1515
1.33M
  n = MIN(aa->size, bb->size);
1516
296M
  for (i = 0; i < n; i++) {
1517
295M
    a = ap[i];
1518
295M
    b = bp[i];
1519
295M
    t = a - b;
1520
295M
    r = t - c;
1521
295M
    rp[i] = r;
1522
295M
    c = a < b || r > t;
1523
295M
  }
1524
1.33M
  if (aa->size >= bb->size) {
1525
1.33M
    n = aa->size;
1526
10.5M
    for (; i < n; i++) {
1527
9.20M
      t = ap[i];
1528
9.20M
      r = t - c;
1529
9.20M
      rp[i] = r;
1530
9.20M
      c = r > t;
1531
9.20M
    }
1532
1.33M
  }
1533
0
  else {
1534
0
    n = bb->size;
1535
0
    for (; i < n; i++) {
1536
0
      t = 0 - bp[i];
1537
0
      r = t - c;
1538
0
      rp[i] = r;
1539
0
      c = r > t;
1540
0
    }
1541
0
  }
1542
  /* remove leading 0s */
1543
1.44M
  while (--i > 0 && rp[i] == 0)
1544
103k
    ;
1545
1.33M
  rr->size = i + 1;
1546
1.33M
  return(rr);
1547
1.33M
}
1548
1549
txBigInt *fxBigInt_mul(txMachine* the, txBigInt *rr, txBigInt *aa, txBigInt *bb)
1550
91.6k
{
1551
91.6k
  rr = fxBigInt_umul(the, rr, aa, bb);
1552
91.6k
  if ((aa->sign != bb->sign) && !fxBigInt_iszero(rr))
1553
7.03k
    rr->sign = 1;
1554
91.6k
  mxBigInt_meter(rr->size);
1555
91.6k
  return(rr);
1556
91.6k
}
1557
1558
txBigInt *fxBigInt_umul(txMachine* the, txBigInt *rr, txBigInt *aa, txBigInt *bb)
1559
307k
{
1560
307k
  txU4 b;
1561
307k
  txU4 *ap, *bp, *rp;
1562
307k
  txU4 c = 0;
1563
307k
  int i, j, n, m;
1564
1565
307k
  if (rr == NULL)
1566
91.6k
    rr = fxBigInt_alloc(the, aa->size + bb->size);
1567
307k
  fxBigInt_fill0(rr);
1568
307k
  ap = aa->data;
1569
307k
  bp = bb->data;
1570
307k
  rp = rr->data;
1571
307k
  n = bb->size;
1572
930k
  for (i = 0, j = 0; i < n; i++) {
1573
622k
    b = bp[i];
1574
622k
    c = 0;
1575
622k
    m = aa->size;
1576
40.3M
    for (j = 0; j < m; j++)
1577
39.7M
      mxBigIntMulAdd(ap[j], b, rp[i + j], c, rp[i + j], c);
1578
622k
    rp[i + j] = c;
1579
622k
  }
1580
  /* remove leading 0s */
1581
563k
  for (n = i + j; --n > 0 && rp[n] == 0;)
1582
255k
    ;
1583
307k
  rr->size = n + 1;
1584
307k
  rr->sign = 0;
1585
307k
  return(rr);
1586
307k
}
1587
1588
txBigInt *fxBigInt_umul1(txMachine* the, txBigInt *r, txBigInt *a, txU4 b)
1589
325k
{
1590
325k
  int i, n;
1591
325k
  txU4 c = 0;
1592
325k
  txU4 *ap, *rp;
1593
1594
325k
  if (r == NULL)
1595
74.1k
    r = fxBigInt_alloc(the, a->size + 1);
1596
325k
  ap = a->data;
1597
325k
  rp = r->data;
1598
325k
  n = a->size;
1599
296M
  for (i = 0; i < n; i++)
1600
295M
    mxBigIntMulAdd(ap[i], b, c, 0, rp[i], c);
1601
325k
  if (c != 0)
1602
151k
    rp[i] = c;
1603
174k
  else {
1604
    /* remove leading 0s */
1605
616k
    while (--i > 0 && rp[i] == 0)
1606
442k
      ;
1607
174k
  }
1608
325k
  r->size = i + 1;
1609
325k
  return(r);
1610
325k
}
1611
1612
txBigInt *fxBigInt_exp(txMachine* the, txBigInt *r, txBigInt *a, txBigInt *b)
1613
147k
{
1614
147k
#ifndef mxCompile
1615
147k
  if (b->sign)
1616
14
    mxRangeError("negative exponent");
1617
147k
#endif
1618
147k
  if (fxBigInt_iszero(b)) {
1619
73.5k
    if (r == NULL)
1620
73.5k
      r = fxBigInt_alloc(the, 1);
1621
0
    else {
1622
0
      r->size = 1;
1623
0
      r->sign = 0;
1624
0
    }
1625
73.5k
    r->data[0] = 1;
1626
73.5k
  }
1627
74.1k
  else {
1628
74.1k
    int i = fxBigInt_bitsize(b) - 1;
1629
74.1k
    int odd = fxBigInt_isset(b, i);
1630
74.1k
    txU4 c = fxBigInt_bitsize(a);
1631
74.1k
    txBigInt *t = fxBigInt_umul1(the, NULL, b, c);
1632
74.1k
    t = fxBigInt_ulsr1(the, t, t, 5);
1633
74.1k
#ifndef mxCompile
1634
74.1k
    if ((t->size > 1) || (t->data[0] > 0xFFFF))
1635
15
      mxRangeError("too big exponent");
1636
74.1k
#endif
1637
74.1k
    c = 2 + t->data[0];
1638
74.1k
    fxBigInt_free(the, t);
1639
74.1k
        if (r == NULL)
1640
74.1k
      r = fxBigInt_alloc(the, c);
1641
74.1k
      t = fxBigInt_alloc(the, c);
1642
74.1k
        fxBigInt_copy(r, a);
1643
485k
    while (i > 0) {
1644
411k
            i--;
1645
411k
      t = fxBigInt_sqr(the, t, r);
1646
411k
      if ((odd = fxBigInt_isset(b, i))) {
1647
216k
        r->size = c;
1648
216k
        r = fxBigInt_umul(the, r, t, a);
1649
216k
      }
1650
195k
      else {
1651
195k
        txBigInt u = *r;
1652
195k
        *r = *t;
1653
195k
        *t = u;
1654
195k
      }
1655
411k
      t->size = c;
1656
411k
    }
1657
74.1k
    r->sign = a->sign & odd;
1658
74.1k
    fxBigInt_free(the, t);
1659
74.1k
  }
1660
147k
  mxBigInt_meter(r->size);
1661
147k
  return(r);
1662
147k
}
1663
1664
txBigInt *fxBigInt_sqr(txMachine* the, txBigInt *r, txBigInt *a)
1665
411k
{
1666
411k
  int i, j, t;
1667
411k
  txU4 *ap, *rp;
1668
411k
  txU4 ai, c, cc;
1669
411k
  txU4 overflow = 0;  /* overflow flag of 'u' */
1670
1671
411k
  if (r == NULL)
1672
0
    r = fxBigInt_alloc(the, a->size * 2);
1673
411k
  fxBigInt_fill0(r);
1674
411k
  t = a->size;
1675
411k
  ap = a->data;
1676
411k
  rp = r->data;
1677
1678
5.89M
  for (i = 0; i < t - 1; i++) {
1679
5.48M
    mxBigIntMulAdd(ap[i], ap[i], rp[i * 2], 0, rp[i * 2], c);
1680
5.48M
    cc = 0;
1681
5.48M
    ai = ap[i];
1682
530M
    for (j = i + 1; j < t; j++) {
1683
      /* ov:hi:lo = 2 * ai * aj + cc:c + rp[k]; the sum is below 2^65 so ov is 0 or 1 */
1684
525M
      int k = i + j;
1685
525M
      txU4 lo, hi, ov, carry;
1686
525M
      mxBigIntMulAdd(ai, ap[j], 0, 0, lo, hi);
1687
525M
      ov = hi >> (mxBigIntWordSize - 1);
1688
525M
      hi = (hi << 1) | (lo >> (mxBigIntWordSize - 1));
1689
525M
      lo <<= 1;
1690
525M
      lo += c; carry = lo < c; hi += carry; ov += hi < carry;
1691
525M
      hi += cc; ov += hi < cc;
1692
525M
      lo += rp[k]; carry = lo < rp[k]; hi += carry; ov += hi < carry;
1693
525M
      rp[k] = lo;
1694
525M
      c = hi;
1695
525M
      cc = ov;
1696
525M
    }
1697
5.48M
    c += overflow;
1698
5.48M
    rp[i + t] = c;    /* c = u */
1699
5.48M
    overflow = cc || c < overflow;
1700
5.48M
  }
1701
  /* the last loop */
1702
411k
  mxBigIntMulAdd(ap[i], ap[i], rp[i * 2], 0, rp[i * 2], c);
1703
411k
  rp[i + t] = c + overflow;
1704
1705
  /* remove leading 0s */
1706
698k
  for (i = 2*t; --i > 0 && rp[i] == 0;)
1707
287k
    ;
1708
411k
  r->size = i + 1;
1709
411k
  return(r);
1710
411k
}
1711
1712
txBigInt *fxBigInt_div(txMachine* the, txBigInt *q, txBigInt *a, txBigInt *b)
1713
5.52k
{
1714
5.52k
#ifndef mxCompile
1715
5.52k
  if (fxBigInt_iszero(b))
1716
2
    mxRangeError("zero divider");
1717
5.52k
#endif
1718
5.52k
  q = fxBigInt_udiv(the, q, a, b, C_NULL);
1719
5.52k
  if (!fxBigInt_iszero(q)) {
1720
3.59k
    if (a->sign)
1721
1.09k
      q->sign = !q->sign;
1722
3.59k
    if (b->sign)
1723
935
      q->sign = !q->sign;
1724
3.59k
  }
1725
5.52k
  mxBigInt_meter(q->size);
1726
5.52k
  return(q);
1727
5.52k
}
1728
1729
txBigInt *fxBigInt_mod(txMachine* the, txBigInt *r, txBigInt *a, txBigInt *b)
1730
0
{
1731
0
  txBigInt *q;
1732
0
  mxBigInt_meter(((a->size - b->size) * (a->size + b->size)));
1733
0
  if (r == NULL)
1734
0
    r = fxBigInt_alloc(the, a->sign ? b->size : MIN(a->size, b->size));
1735
0
  q = fxBigInt_udiv(the, NULL, a, b, &r);
1736
0
  if (a->sign) {
1737
0
    if (!fxBigInt_iszero(r))
1738
0
      r = fxBigInt_sub(the, r, b, r);
1739
0
  }
1740
0
  fxBigInt_free(the, q);
1741
0
  mxBigInt_meter(r->size);
1742
0
  return(r);
1743
0
}
1744
1745
txBigInt *fxBigInt_rem(txMachine* the, txBigInt *r, txBigInt *a, txBigInt *b)
1746
1.52M
{
1747
1.52M
  txBigInt *q;
1748
1.52M
#ifndef mxCompile
1749
1.52M
  if (fxBigInt_iszero(b))
1750
1
    mxRangeError("zero divider");
1751
1.52M
#endif
1752
1.52M
  mxBigInt_meter(((a->size - b->size) * (a->size + b->size)));
1753
1.52M
  if (r == NULL)
1754
1.52M
    r = fxBigInt_alloc(the, MIN(a->size, b->size));
1755
1.52M
  q = fxBigInt_udiv(the, NULL, a, b, &r);
1756
1.52M
  if (a->sign) {
1757
1.15M
    if (!fxBigInt_iszero(r))
1758
1.15M
            r->sign = !r->sign;
1759
1.15M
  }
1760
1.52M
  fxBigInt_free(the, q);
1761
1.52M
  mxBigInt_meter(r->size);
1762
1.52M
  return(r);
1763
1.52M
}
1764
1765
static void fxBigInt_makepoly(txBigInt *r, txBigInt *a, int t)
1766
81.6k
{
1767
81.6k
  int n;
1768
81.6k
  txU4 *rp, *ap;
1769
1770
  /* make up a polynomial a_t*b^n + a_{t-1}*b^{n-1} + ... */
1771
81.6k
  n = r->size;
1772
81.6k
  rp = &r->data[n];
1773
81.6k
  ap = a->data;
1774
320k
  while (--n >= 0) {
1775
238k
    *--rp = t < 0 ? 0: ap[t];
1776
238k
    --t;
1777
238k
  }
1778
81.6k
}
1779
1780
#if BN_NO_ULDIVMOD
1781
static txU8
1782
div64_32(txU8 a, txU4 b)
1783
{
1784
  txU4 high = (txU4)(a >> 32);
1785
  txU8 r = 0, bb = b, d = 1;
1786
1787
  if (high >= b) {
1788
    high /= b;
1789
    r = (txU8)high << 32;
1790
    a -= (txU8)(high * b) << 32;
1791
  }
1792
  while ((long long)bb > 0 && bb < a) {
1793
    bb += bb;
1794
    d += d;
1795
  }
1796
  do {
1797
    if (a >= bb) {
1798
      a -= bb;
1799
      r += d;
1800
    }
1801
    bb >>= 1;
1802
    d >>= 1;
1803
  } while (d != 0);
1804
  return r;
1805
}
1806
#endif
1807
1808
txBigInt *fxBigInt_udiv(txMachine* the, txBigInt *q, txBigInt *a, txBigInt *b, txBigInt **r)
1809
1.53M
{
1810
1.53M
  int sw;
1811
1.53M
  txBigInt *nb, *na, *tb, *a2, *b2, *tb2, *tb3;
1812
1.53M
  int i, n, t;
1813
1.53M
  txU4 *qp, *ap, *bp;
1814
1.53M
#define mk_dword(p, i)  (((txU8)(p)[i] << mxBigIntWordSize) | (p)[i - 1])
1815
1816
1.53M
  if (fxBigInt_ucomp(a, b) < 0) {
1817
1.52M
    if (q == NULL) {
1818
1.52M
      q = fxBigInt_alloc(the, 1);
1819
1.52M
    }
1820
0
    else {
1821
0
      q->sign = 0;
1822
0
      q->size = 1;
1823
0
    }
1824
1.52M
    q->data[0] = 0;
1825
1.52M
    if (r != NULL) {
1826
1.52M
      if (*r == NULL)
1827
0
        *r = fxBigInt_dup(the, a);
1828
1.52M
      else
1829
1.52M
        fxBigInt_copy(*r, a);
1830
1.52M
      (*r)->sign = 0;
1831
1.52M
    }
1832
1.52M
    return(q);
1833
1.52M
  }
1834
1835
  /* CAUTION: if q is present, it must take account of normalization */
1836
6.50k
  if (q == NULL)
1837
6.50k
    q = fxBigInt_alloc(the, a->size - b->size + 2);
1838
6.50k
  if (r != NULL && *r == NULL)
1839
0
    *r = fxBigInt_alloc(the, b->size);
1840
1841
  /* normalize */
1842
6.50k
  sw = fxBigInt_ffs(b);
1843
6.50k
  nb = fxBigInt_ulsl1(the, NULL, b, sw);
1844
6.50k
  na = fxBigInt_ulsl1(the, NULL, a, sw);
1845
6.50k
  t = nb->size - 1; /* the size must not change from 'b' */
1846
6.50k
  n = na->size - 1;
1847
1848
  /* adjust size of q */
1849
6.50k
  q->size = na->size - nb->size + 1;
1850
6.50k
  fxBigInt_fill0(q);  /* set 0 to quotient */
1851
1852
  /* process the most significant word */
1853
6.50k
  tb = fxBigInt_ulsl1(the, NULL, nb, (n - t) * mxBigIntWordSize);  /* y*b^n */
1854
6.50k
  if (fxBigInt_ucomp(na, tb) >= 0) {
1855
1.93k
    q->data[q->size - 1]++;
1856
1.93k
    fxBigInt_sub(C_NULL, na, na, tb);
1857
    /* since nomalization done, must be na < tb here */
1858
1.93k
  }
1859
1860
  /* prepare the constant for the adjustment: y_t*b + y_{t-1} */
1861
6.50k
  b2 = fxBigInt_alloc(the, 2);
1862
6.50k
  fxBigInt_makepoly(b2, nb, t);
1863
  /* and allocate for temporary buffer */
1864
6.50k
  a2 = fxBigInt_alloc(the, 3);
1865
6.50k
  tb2 = fxBigInt_alloc(the, 3);
1866
6.50k
  tb3 = fxBigInt_alloc(the, tb->size + 1);
1867
1868
6.50k
  qp = &q->data[q->size - 1];
1869
6.50k
  ap = na->data;
1870
6.50k
  bp = nb->data;
1871
81.6k
  for (i = n; i >= t + 1; --i) {
1872
75.1k
    txU4 tq;
1873
1874
    /* the first estimate */
1875
#if BN_NO_ULDIVMOD
1876
    tq = (ap[i] == bp[t]) ? ~(txU4)0: (txU4)div64_32(mk_dword(ap, i), bp[t]);
1877
#else
1878
75.1k
    tq = (ap[i] == bp[t]) ? ~(txU4)0: (txU4)(mk_dword(ap, i) / bp[t]);
1879
75.1k
#endif
1880
1881
    /* adjust */
1882
75.1k
    fxBigInt_makepoly(a2, na, i);
1883
76.7k
    while (fxBigInt_ucomp(fxBigInt_umul1(the, tb2, b2, tq), a2) > 0)
1884
1.56k
      --tq;
1885
1886
    /* next x */
1887
75.1k
    fxBigInt_ulsr1(the, tb, tb, mxBigIntWordSize);
1888
75.1k
    fxBigInt_usub(the, na, na, fxBigInt_umul1(the, tb3, tb, tq));
1889
75.1k
    if (na->sign) {
1890
0
      fxBigInt_add(the, na, na, tb);
1891
0
      --tq;
1892
0
    }
1893
75.1k
    *--qp = tq;
1894
75.1k
  }
1895
6.50k
  if (r != NULL)
1896
2.91k
    *r = fxBigInt_ulsr1(the, *r, na, sw);
1897
  /* remove leading 0s from q */
1898
11.0k
  for (i = q->size; --i > 0 && q->data[i] == 0;)
1899
4.57k
    ;
1900
6.50k
  q->size = i + 1;
1901
  
1902
6.50k
  fxBigInt_free(the, tb3);
1903
6.50k
  fxBigInt_free(the, tb2);
1904
6.50k
  fxBigInt_free(the, a2);
1905
6.50k
  fxBigInt_free(the, b2);
1906
6.50k
  fxBigInt_free(the, tb);
1907
6.50k
  fxBigInt_free(the, na);
1908
6.50k
  fxBigInt_free(the, nb);
1909
6.50k
  return(q);
1910
1.53M
}
1911
1912
#ifdef mxMetering
1913
void fxBigInt_meter(txMachine* the, int n)
1914
6.34M
{
1915
6.34M
  n--;
1916
6.34M
  the->meterIndex += n * XS_BIGINT_METERING;
1917
6.34M
}
1918
#endif
1919