Coverage Report

Created: 2025-12-30 07:10

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-2025  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
195k
#define howmany(x, y) (((x) + (y) - 1) / (y))
49
#endif
50
#ifndef MAX
51
773k
#define MAX(a, b) ((a) >= (b) ? (a) : (b))
52
#endif
53
#ifndef MIN
54
2.07M
#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
4.79M
#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
38.0k
{
78
38.0k
  txSlot* slot;
79
38.0k
  mxPush(mxObjectPrototype);
80
38.0k
  slot = fxLastProperty(the, fxNewObjectInstance(the));
81
38.0k
  slot = fxNextHostFunctionProperty(the, slot, mxCallback(fx_BigInt_prototype_toString), 0, mxID(_toLocaleString), XS_DONT_ENUM_FLAG);
82
38.0k
  slot = fxNextHostFunctionProperty(the, slot, mxCallback(fx_BigInt_prototype_toString), 0, mxID(_toString), XS_DONT_ENUM_FLAG);
83
38.0k
  slot = fxNextHostFunctionProperty(the, slot, mxCallback(fx_BigInt_prototype_valueOf), 0, mxID(_valueOf), XS_DONT_ENUM_FLAG);
84
38.0k
  slot = fxNextStringXProperty(the, slot, "BigInt", mxID(_Symbol_toStringTag), XS_DONT_ENUM_FLAG | XS_DONT_SET_FLAG);
85
38.0k
  mxBigIntPrototype = *the->stack;
86
38.0k
  slot = fxBuildHostConstructor(the, mxCallback(fx_BigInt), 1, mxID(_BigInt));
87
38.0k
  mxBigIntConstructor = *the->stack;
88
38.0k
  slot = fxLastProperty(the, slot);
89
38.0k
  slot = fxNextHostFunctionProperty(the, slot, mxCallback(fx_BigInt_asIntN), 2, mxID(_asIntN), XS_DONT_ENUM_FLAG);
90
38.0k
  slot = fxNextHostFunctionProperty(the, slot, mxCallback(fx_BigInt_asUintN), 2, mxID(_asUintN), XS_DONT_ENUM_FLAG);
91
38.0k
  slot = fxNextHostFunctionProperty(the, slot, mxCallback(fx_BigInt_bitLength), 1, mxID(_bitLength), XS_DONT_ENUM_FLAG);
92
38.0k
  slot = fxNextHostFunctionProperty(the, slot, mxCallback(fx_BigInt_fromArrayBuffer), 1, mxID(_fromArrayBuffer), XS_DONT_ENUM_FLAG);
93
38.0k
  mxPop();
94
38.0k
}
95
96
void fx_BigInt(txMachine* the)
97
2.11k
{
98
2.11k
  if (mxTarget->kind != XS_UNDEFINED_KIND)
99
1
    mxTypeError("new: BigInt");
100
2.11k
  if (mxArgc > 0)
101
2.11k
    *mxResult = *mxArgv(0);
102
2.11k
  fxToPrimitive(the, mxResult, XS_NUMBER_HINT);
103
2.11k
  if (mxResult->kind == XS_NUMBER_KIND) {
104
179
    int fpclass = c_fpclassify(mxResult->value.number);
105
179
    txNumber check = c_trunc(mxResult->value.number);
106
179
    if ((fpclass != C_FP_NAN) && (fpclass != C_FP_INFINITE) && (mxResult->value.number == check))
107
159
      fxNumberToBigInt(the, mxResult);
108
20
    else
109
20
      mxRangeError("cannot coerce number to bigint");
110
179
  }
111
1.93k
  else if (mxResult->kind == XS_INTEGER_KIND) {
112
140
    fxIntegerToBigInt(the, mxResult);
113
140
  }
114
1.79k
  else
115
1.79k
    fxToBigInt(the, mxResult, 1);
116
2.11k
}
117
118
txNumber fx_BigInt_asAux(txMachine* the)
119
22.0k
{
120
22.0k
  txNumber value, index;
121
22.0k
  if (mxArgc < 1)
122
7
    index = 0;
123
22.0k
  else {
124
22.0k
    if (mxArgv(0)->kind == XS_UNDEFINED_KIND)
125
1.30k
      index = 0;
126
20.7k
    else {
127
20.7k
      value = fxToNumber(the, mxArgv(0));
128
20.7k
      if (c_isnan(value))
129
790
        index = 0;
130
19.9k
      else {
131
19.9k
        value = c_trunc(value);
132
19.9k
        if (value < 0)
133
23
          mxRangeError("index < 0");
134
19.9k
        index = value;
135
19.9k
        if (index <= 0)
136
4.16k
          index = 0;
137
15.7k
        else if (index > C_MAX_SAFE_INTEGER)
138
15
          index = C_MAX_SAFE_INTEGER;
139
19.9k
        if (value != index)
140
15
          mxRangeError("invalid index");
141
19.9k
      }
142
20.7k
    }
143
22.0k
  }
144
22.0k
  if (mxArgc < 2)
145
17
    mxTypeError("no bigint");
146
22.0k
  return index;
147
22.0k
}
148
149
void fx_BigInt_asIntN(txMachine* the)
150
11.9k
{
151
11.9k
  txInteger index = (txInteger)fx_BigInt_asAux(the);
152
11.9k
  txBigInt* arg = fxToBigInt(the, mxArgv(1), 1);
153
11.9k
  txBigInt* result;
154
11.9k
  if (fxBigInt_iszero(arg)) {
155
1.42k
    result = fxBigInt_dup(the, arg);
156
1.42k
  }
157
10.5k
  else {
158
10.5k
    txBigInt* bits = fxBigInt_ulsl1(the, C_NULL, (txBigInt *)&gxBigIntOne, index);
159
10.5k
    txBigInt* mask = fxBigInt_usub(the, C_NULL, bits, (txBigInt *)&gxBigIntOne);
160
10.5k
    result = fxBigInt_uand(the, C_NULL, arg, mask);
161
10.5k
    if ((arg->sign) && !fxBigInt_iszero(result))
162
3.78k
      result = fxBigInt_usub(the, C_NULL, bits, result);
163
10.5k
    if (index && fxBigInt_comp(result, fxBigInt_ulsl1(the, C_NULL, (txBigInt *)&gxBigIntOne, index - 1)) >= 0)
164
5.15k
      result = fxBigInt_sub(the, C_NULL, result, bits);
165
10.5k
    result = fxBigInt_fit(the, result);
166
10.5k
  }
167
11.9k
  mxResult->value.bigint = *result;
168
11.9k
  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
11.9k
}
176
177
void fx_BigInt_asUintN(txMachine* the)
178
10.0k
{
179
10.0k
  txInteger index = (txInteger)fx_BigInt_asAux(the);
180
10.0k
  txBigInt* arg = fxToBigInt(the, mxArgv(1), 1);
181
10.0k
  txBigInt* result;
182
10.0k
  if (fxBigInt_iszero(arg)) {
183
2.46k
    result = fxBigInt_dup(the, arg);
184
2.46k
  }
185
7.59k
  else {
186
7.59k
    txBigInt* bits = fxBigInt_ulsl1(the, C_NULL, (txBigInt *)&gxBigIntOne, index);
187
7.59k
    txBigInt* mask = fxBigInt_sub(the, C_NULL, bits, (txBigInt *)&gxBigIntOne);
188
7.59k
    result = fxBigInt_uand(the, C_NULL, arg, mask);
189
7.59k
    if ((arg->sign) && !fxBigInt_iszero(result))
190
4.11k
      result = fxBigInt_usub(the, C_NULL, bits, result);
191
7.59k
    result = fxBigInt_fit(the, result);
192
7.59k
  }
193
10.0k
  mxResult->value.bigint = *result;
194
10.0k
  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
10.0k
}
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
3
      arrayBuffer = slot;
224
3
  }
225
4
  if (!arrayBuffer)
226
1
    mxTypeError("argument: not an ArrayBuffer instance");
227
3
  bufferInfo = arrayBuffer->next;
228
3
  length = bufferInfo->value.bufferInfo.length;
229
3
  if ((mxArgc > 1) && fxToBoolean(the, mxArgv(1)))
230
1
    sign = 1;
231
3
  if ((mxArgc > 2) && fxToBoolean(the, mxArgv(2)))
232
0
    endian = EndianLittle;
233
3
    if (sign)
234
1
        length--;
235
3
  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
1
  bigint = fxBigInt_alloc(the, howmany(length, sizeof(txU4)));
242
1
  bigint->data[bigint->size - 1] = 0;
243
1
  src = (txU1*)(arrayBuffer->value.arrayBuffer.address);
244
1
  dst = (txU1*)(bigint->data);
245
1
  if (sign)
246
0
    bigint->sign = *src++;
247
#if mxBigEndian
248
  if (endian != EndianLittle) {
249
#else
250
1
  if (endian != EndianBig) {
251
0
#endif  
252
0
    c_memcpy(dst, src, length);
253
0
  }
254
1
  else {
255
1
    dst += length;
256
2
    while (length > 0) {
257
1
      dst--;
258
1
      *dst = *src;
259
1
      src++;
260
1
      length--;
261
1
    }
262
1
  }
263
1
  length = bigint->size - 1;
264
1
  while (length && (bigint->data[length] == 0))
265
0
    length--;
266
1
  bigint->size = length + 1;
267
1
  mxPullSlot(mxResult);
268
1
}
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
84
    radix = 10;
278
166k
  else if (mxIsUndefined(mxArgv(0)))
279
12
    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
1.96k
{
292
1.96k
  txSlot* slot = fxBigIntCheck(the, mxThis);
293
1.96k
  if (!slot) mxTypeError("this: not a bigint");
294
44
  mxResult->kind = slot->kind;
295
44
  mxResult->value = slot->value;
296
44
}
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
168k
{
316
168k
  txSlot* result = C_NULL;
317
168k
  if ((it->kind == XS_BIGINT_KIND) || (it->kind == XS_BIGINT_X_KIND))
318
166k
    result = it;
319
2.02k
  else if (it->kind == XS_REFERENCE_KIND) {
320
1.97k
    txSlot* instance = it->value.reference;
321
1.97k
    it = instance->next;
322
1.97k
    if ((it) && (it->flag & XS_INTERNAL_FLAG) && ((it->kind == XS_BIGINT_KIND) || (it->kind == XS_BIGINT_X_KIND)))
323
59
      result = it;
324
1.97k
  }
325
168k
  return result;
326
168k
}
327
328
void fxBigIntCoerce(txMachine* the, txSlot* slot)
329
1.62M
{
330
1.62M
  fxToBigInt(the, slot, 1);
331
1.62M
}
332
333
txBoolean fxBigIntCompare(txMachine* the, txBoolean less, txBoolean equal, txBoolean more, txSlot* left, txSlot* right)
334
6.29M
{
335
6.29M
  int result;
336
6.29M
  txNumber delta = 0;
337
6.29M
  if (mxBigIntIsNaN(&left->value.bigint))
338
0
    return less & more & !equal;
339
6.29M
  if (right->kind == XS_STRING_KIND)
340
1.93M
    fxStringToBigInt(the, right, 1);
341
6.29M
  if ((right->kind != XS_BIGINT_KIND) && (right->kind != XS_BIGINT_X_KIND)) {
342
4.15M
    fxToNumber(the, right);
343
4.15M
    result = c_fpclassify(right->value.number);
344
4.15M
    if (result == C_FP_NAN)
345
96.3k
      return less & more & !equal;
346
4.06M
    if (result == C_FP_INFINITE)
347
8.71k
      return (right->value.number > 0) ? less : more;
348
4.05M
    delta = right->value.number - c_trunc(right->value.number);
349
4.05M
    fxNumberToBigInt(the, right);
350
4.05M
  }
351
6.19M
  if (mxBigIntIsNaN(&right->value.bigint))
352
1.76M
    return less & more & !equal;
353
4.42M
  result = fxBigInt_comp(&left->value.bigint, &right->value.bigint);
354
4.42M
  if (result < 0)
355
1.59M
    return less;
356
2.83M
    if (result > 0)
357
2.82M
        return more;
358
8.82k
  if (delta > 0)
359
1.83k
    return less;
360
6.98k
  if (delta < 0)
361
2.01k
    return more;
362
4.97k
  return equal;
363
6.98k
}
364
365
void fxBigIntDecode(txMachine* the, txSize size)
366
10.8M
{
367
10.8M
  txBigInt* bigint;
368
10.8M
  mxPushUndefined();
369
10.8M
  bigint = &the->stack->value.bigint;
370
10.8M
  bigint->data = fxNewChunk(the, size);
371
10.8M
  bigint->size = size >> 2;
372
10.8M
  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
10.8M
  c_memcpy(bigint->data, the->code, size);
388
10.8M
#endif  
389
10.8M
  the->stack->kind = XS_BIGINT_KIND;
390
10.8M
}
391
392
#endif  
393
394
void fxBigIntEncode(txByte* code, txBigInt* bigint, txSize size)
395
42.3k
{
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
42.3k
  c_memcpy(code, bigint->data, size);
411
42.3k
#endif
412
42.3k
}
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
5
    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
126k
{
434
126k
  return bigint->size * sizeof(txU4);
435
126k
}
436
437
txSize fxBigIntMaximum(txSize length)
438
165k
{
439
165k
  return sizeof(txU4) * (1 + (((txSize)c_ceil((txNumber)length * c_log(10) / c_log(2))) / 32));
440
165k
}
441
442
txSize fxBigIntMaximumB(txSize length)
443
1.46k
{
444
1.46k
  return sizeof(txU4) * (1 + howmany(1, mxBigIntWordSize) + (length / 32));
445
1.46k
}
446
447
txSize fxBigIntMaximumO(txSize length)
448
618
{
449
618
  return sizeof(txU4) * (1 + howmany(3, mxBigIntWordSize) + ((length * 3) / 32));
450
618
}
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
165k
{
459
165k
  txU4 data[1] = { 0 };
460
165k
  txBigInt digit = { .sign=0, .size=1, .data=data };
461
165k
  bigint->sign = 0;
462
165k
  bigint->size = 1;
463
165k
  bigint->data[0] = 0;
464
488k
  while (length) {
465
322k
    char c = *p++;
466
322k
    data[0] = c - '0';
467
322k
    fxBigInt_uadd(NULL, bigint, fxBigInt_umul1(NULL, bigint, bigint, 10), &digit);
468
322k
    length--;
469
322k
  }
470
165k
  if ((bigint->size > 1) || (bigint->data[0] != 0))
471
86.1k
    bigint->sign = sign;
472
165k
}
473
474
void fxBigIntParseB(txBigInt* bigint, txString p, txSize length)
475
1.46k
{
476
1.46k
  txU4 data[1] = { 0 };
477
1.46k
  txBigInt digit = { .sign=0, .size=1, .data=data };
478
1.46k
  bigint->sign = 0;
479
1.46k
  bigint->size = 1;
480
1.46k
  bigint->data[0] = 0;
481
6.31k
  while (length) {
482
4.85k
    char c = *p++;
483
4.85k
    data[0] = c - '0';
484
4.85k
    fxBigInt_uadd(NULL, bigint, fxBigInt_ulsl1(NULL, bigint, bigint, 1), &digit);
485
4.85k
    length--;
486
4.85k
  }
487
1.46k
}
488
489
void fxBigIntParseO(txBigInt* bigint, txString p, txSize length)
490
618
{
491
618
  txU4 data[1] = { 0 };
492
618
  txBigInt digit = { .sign=0, .size=1, .data=data };
493
618
  bigint->sign = 0;
494
618
  bigint->size = 1;
495
618
  bigint->data[0] = 0;
496
3.43k
  while (length) {
497
2.81k
    char c = *p++;
498
2.81k
    data[0] = c - '0';
499
2.81k
    fxBigInt_uadd(NULL, bigint, fxBigInt_ulsl1(NULL, bigint, bigint, 3), &digit);
500
2.81k
    length--;
501
2.81k
  }
502
618
}
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.58M
  while (length) {
512
1.41M
    char c = *p++;
513
1.41M
    if (('0' <= c) && (c <= '9'))
514
176k
      data[0] = c - '0';
515
1.23M
    else if (('a' <= c) && (c <= 'f'))
516
377k
      data[0] = 10 + c - 'a';
517
860k
    else
518
860k
      data[0] = 10 + c - 'A';
519
1.41M
    fxBigInt_uadd(NULL, bigint, fxBigInt_ulsl1(NULL, bigint, bigint, 4), &digit);
520
1.41M
    length--;
521
1.41M
  }
522
172k
}
523
524
#ifndef mxCompile
525
526
void fxBigintToArrayBuffer(txMachine* the, txSlot* slot, txU4 total, txBoolean sign, int endian)
527
21.0k
{
528
21.0k
  txBigInt* bigint = fxToBigInt(the, slot, 1);
529
21.0k
  txU4 length = howmany(fxBigInt_bitsize(bigint), 8);
530
21.0k
  txU4 offset = 0;
531
21.0k
  txU1 *src, *dst;
532
21.0k
  if (length == 0)
533
21.0k
    length = 1;
534
21.0k
  if (length < total) {
535
13.7k
    if (endian == EndianBig)
536
13.7k
      offset = total - length;
537
13.7k
  }
538
7.26k
  else {
539
7.26k
    total = length;
540
7.26k
  }
541
21.0k
  if (sign) {
542
7.26k
    if (total >= 0x7FFFFFFF)
543
0
      mxRangeError("byteLength too big");
544
7.26k
    offset++;
545
7.26k
    total++;
546
7.26k
  }
547
21.0k
  fxConstructArrayBufferResult(the, mxThis, total);
548
21.0k
  src = (txU1*)(bigint->data);
549
21.0k
  dst = (txU1*)(mxResult->value.reference->next->value.arrayBuffer.address);
550
21.0k
  if (sign)
551
7.25k
    *dst = bigint->sign;
552
21.0k
  dst += offset;
553
#if mxBigEndian
554
  if (endian != EndianLittle) {
555
#else
556
21.0k
  if (endian != EndianBig) {
557
1
#endif  
558
1
    c_memcpy(dst, src, length);
559
1
  }
560
21.0k
  else {
561
21.0k
    src += length;
562
42.1k
    while (length > 0) {
563
21.0k
      src--;
564
21.0k
      *dst = *src;
565
21.0k
      dst++;
566
21.0k
      length--;
567
21.0k
    }
568
21.0k
  }
569
21.0k
}
570
571
txNumber fxBigIntToNumber(txMachine* the, txSlot* slot)
572
555
{
573
555
  txBigInt* bigint = &slot->value.bigint;
574
555
  txNumber base = 4294967296;
575
555
  txNumber number = 0;
576
555
  int i;
577
17.8k
  for (i = bigint->size; --i >= 0;)
578
17.2k
    number = (number * base) + bigint->data[i];
579
555
  if (bigint->sign)
580
11
    number = -number;
581
555
  slot->value.number = number;
582
555
  slot->kind = XS_NUMBER_KIND;
583
555
  return number;
584
555
}
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, 470427017},
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, 20537907},
620
    { 5, 24300000},
621
    { 5, 28430241},
622
    { 5, 32768000},
623
    { 5, 39135393},
624
    { 5, 45435424},
625
    { 5, 52521875},
626
    { 5, 60466176}
627
};
628
629
void fxBigintToString(txMachine* the, txSlot* slot, txU4 radix)
630
181k
{
631
181k
  static const char gxDigits[] ICACHE_FLASH_ATTR = "0123456789abcdefghijklmnopqrstuvwxyz";
632
181k
  txSize length, offset;
633
181k
  txSlot* result;
634
181k
  txSlot* stack;
635
181k
  if (0 == radix) radix = 10;
636
181k
  const BaseChunk32 *bc = base_chunks32 + (radix - 2);
637
638
181k
  if (mxBigIntIsNaN(&slot->value.bigint)) {
639
0
    fxStringX(the, slot, "NaN");
640
0
    return;
641
0
  }
642
181k
  mxBigInt_meter(slot->value.bigint.size);
643
644
181k
  mxPushUndefined();
645
181k
  result = the->stack;
646
  
647
181k
  mxPushSlot(slot);
648
181k
  fxBigInt_dup(the, &the->stack->value.bigint);
649
181k
  stack = the->stack;
650
651
181k
  length = 1 + bc->k + (txSize)c_ceil((txNumber)(stack->value.bigint.size + 1) * 32 * c_log(2) / c_log(radix));
652
181k
  if (stack->value.bigint.sign)
653
84.4k
    length++;
654
181k
  offset = length;
655
181k
  result->value.string = fxNewChunk(the, length);
656
181k
  result->kind = XS_STRING_KIND;
657
658
181k
  result->value.string[--offset] = 0;
659
181k
  int32_t nonZeroWords = stack->value.bigint.size;
660
183k
  do {
661
183k
    uint64_t carry = 0;
662
1.74M
    for (uint32_t i = stack->value.bigint.size - 1, count = nonZeroWords, base_to_k = bc->base_to_k; count > 0; --count) {
663
1.56M
      carry = (carry << 32) | stack->value.bigint.data[i];
664
1.56M
      stack->value.bigint.data[i--] = (uint32_t)(carry / base_to_k);
665
1.56M
      carry %= base_to_k;
666
1.56M
    }
667
183k
    uint32_t remainder = (uint32_t)carry, k = bc->k;
668
5.29M
    do {
669
5.29M
      result->value.string[--offset] = c_read8(gxDigits + (remainder % radix));
670
5.29M
            remainder /= radix;
671
5.29M
        } while (--k);
672
673
366k
    while (nonZeroWords && (0 == stack->value.bigint.data[stack->value.bigint.size - nonZeroWords]))
674
183k
      nonZeroWords -= 1;
675
183k
  } while (nonZeroWords);
676
677
4.91M
  while (('0' == result->value.string[offset]) && result->value.string[offset + 1])
678
4.73M
    offset++;
679
680
181k
  if (stack->value.bigint.sign)
681
84.4k
    result->value.string[--offset] = '-';
682
181k
  c_memmove(result->value.string, result->value.string + offset, length - offset);
683
684
181k
  mxPop();
685
181k
  mxPop();
686
181k
  mxPullSlot(slot);
687
181k
}
688
689
txS8 fxToBigInt64(txMachine* the, txSlot* slot)
690
1.62M
{
691
1.62M
  return (txS8)fxToBigUint64(the, slot);
692
1.62M
}
693
694
txU8 fxToBigUint64(txMachine* the, txSlot* slot)
695
1.62M
{
696
1.62M
  txBigInt* bigint = fxToBigInt(the, slot, 1);
697
1.62M
  txU8 result = bigint->data[0];
698
1.62M
  if (bigint->size > 1)
699
211
    result |= (txU8)(bigint->data[1]) << 32;
700
1.62M
  if (bigint->sign && result) {
701
41
    result--;
702
41
    result = 0xFFFFFFFFFFFFFFFFll - result;
703
41
  }
704
1.62M
  return result;
705
1.62M
}
706
707
txBigInt* fxIntegerToBigInt(txMachine* the, txSlot* slot)
708
140
{
709
140
  txInteger integer = slot->value.integer;
710
140
  txBigInt* bigint = &slot->value.bigint;
711
140
  txU1 sign = 0;
712
140
  if (integer < 0) {
713
0
    integer = -integer;
714
0
    sign = 1;
715
0
  }
716
140
  bigint->data = fxNewChunk(the, sizeof(txU4));
717
140
  bigint->data[0] = (txU4)integer;
718
140
  bigint->sign = sign;
719
140
  bigint->size = 1;
720
140
  slot->kind = XS_BIGINT_KIND;
721
140
  return bigint;
722
140
}
723
724
txBigInt* fxNumberToBigInt(txMachine* the, txSlot* slot)
725
4.05M
{
726
4.05M
  txBigInt* bigint = &slot->value.bigint;
727
4.05M
  txNumber number = slot->value.number;
728
4.05M
  txNumber limit = 4294967296;
729
4.05M
  txU1 sign = 0;
730
4.05M
  txU2 size = 1;
731
4.05M
  if (number < 0) {
732
2.09M
    number = -number;
733
2.09M
    sign = 1;
734
2.09M
  }
735
5.82M
  while (number >= limit) {
736
1.76M
    size++;
737
1.76M
    number /= limit;
738
1.76M
  }
739
4.05M
  bigint->data = fxNewChunk(the, fxMultiplyChunkSizes(the, size, sizeof(txU4)));
740
4.05M
  bigint->size = size;
741
9.87M
  while (size > 0) {
742
5.82M
    txU4 part = (txU4)number;
743
5.82M
    number -= part;
744
5.82M
    size--;
745
5.82M
    bigint->data[size] = part;
746
5.82M
    number *= limit;
747
5.82M
  }
748
4.05M
  bigint->sign = sign;
749
4.05M
  slot->kind = XS_BIGINT_KIND;
750
4.05M
  return bigint;
751
4.05M
}
752
753
txBigInt* fxStringToBigInt(txMachine* the, txSlot* slot, txFlag whole)
754
1.95M
{
755
1.95M
  txString s = slot->value.string;
756
1.95M
  txString p = fxSkipSpaces(s);
757
1.95M
  txSize offset, length;
758
1.95M
  txInteger sign = 0;
759
1.95M
  txBigInt bigint = {.sign=0, .size=0, .data=C_NULL };
760
1.95M
  char c = *p;
761
1.95M
  if (c == '0') {
762
1.92M
    char d = *(p + 1);
763
1.92M
    if (whole && ((d == 'B') || (d == 'b') || (d == 'O') || (d == 'o') || (d == 'X') || (d == 'x'))) {
764
1.43M
      p += 2;
765
1.43M
      offset = mxPtrDiff(p - s);
766
1.43M
      if ((d == 'B') || (d == 'b')) {
767
5.11k
        while (((c = *p)) && ('0' <= c) && (c <= '1'))
768
3.65k
          p++;
769
1.46k
        length = mxPtrDiff(p - s - offset);
770
1.46k
        p = fxSkipSpaces(p);
771
1.46k
        if ((length > 0) && (*p == 0)) {
772
1.43k
          bigint.data = fxNewChunk(the, fxBigIntMaximumB(length));
773
1.43k
          fxBigIntParseB(&bigint, slot->value.string + offset, length);
774
1.43k
        }
775
1.46k
      }
776
1.43M
      else if ((d == 'O') || (d == 'o')) {
777
291
        while (((c = *p)) && ('0' <= c) && (c <= '7'))
778
257
          p++;
779
34
        length = mxPtrDiff(p - s - offset);
780
34
        p = fxSkipSpaces(p);
781
34
        if ((length > 0) && (*p == 0)) {
782
22
          bigint.data = fxNewChunk(the, fxBigIntMaximumO(length));
783
22
          fxBigIntParseO(&bigint, slot->value.string + offset, length);
784
22
        }
785
34
      }
786
1.43M
      else if ((d == 'X') || (d == 'x')) {
787
5.91M
        while (((c = *p)) && ((('0' <= c) && (c <= '9')) || (('a' <= c) && (c <= 'f')) || (('A' <= c) && (c <= 'F'))))
788
4.48M
          p++;
789
1.43M
        length = mxPtrDiff(p - s - offset);
790
1.43M
        p = fxSkipSpaces(p);
791
1.43M
        if ((length > 0) && (*p == 0)) {
792
171k
          bigint.data = fxNewChunk(the, fxBigIntMaximumX(length));
793
171k
          fxBigIntParseX(&bigint, slot->value.string + offset, length);
794
171k
        }
795
1.43M
      }
796
1.43M
      goto bail;
797
1.43M
    }
798
1.92M
  }
799
526k
  if (c == '-') {
800
529
    sign = 1;
801
529
    p++;
802
529
  }
803
525k
  else if (c == '+') {
804
547
    p++;
805
547
  }
806
526k
  offset = mxPtrDiff(p - s);
807
1.03M
  while (((c = *p)) && ('0' <= c) && (c <= '9'))
808
513k
    p++;
809
526k
  length = mxPtrDiff(p - s - offset);
810
526k
  p = fxSkipSpaces(p);
811
526k
  if (*p == 0) {
812
22.4k
    bigint.data = fxNewChunk(the, fxBigIntMaximum(length));
813
22.4k
    fxBigIntParse(&bigint, slot->value.string + offset, length, sign);
814
22.4k
  }
815
1.95M
bail:
816
1.95M
  if (bigint.data) {
817
195k
    slot->value.bigint = bigint;
818
195k
    slot->kind = XS_BIGINT_KIND;
819
195k
  }
820
1.76M
  else {
821
1.76M
    slot->value.bigint = gxBigIntNaN;
822
1.76M
    slot->kind = XS_BIGINT_X_KIND;
823
1.76M
  }
824
1.95M
  return &slot->value.bigint;
825
526k
}
826
827
txBigInt* fxToBigInt(txMachine* the, txSlot* slot, txFlag strict)
828
3.29M
{
829
3.29M
again:
830
3.29M
  switch (slot->kind) {
831
4.76k
  case XS_BOOLEAN_KIND:
832
4.76k
    slot->value.bigint = *fxBigInt_dup(the, (txBigInt *)((slot->value.boolean) ? &gxBigIntOne : &gxBigIntZero));
833
4.76k
    slot->kind = XS_BIGINT_KIND;
834
4.76k
    break;
835
16
  case XS_INTEGER_KIND:
836
16
    if (strict)
837
16
      mxTypeError("cannot coerce number to bigint");
838
0
    fxIntegerToBigInt(the, slot); 
839
0
    break;
840
10
  case XS_NUMBER_KIND:
841
10
    if (strict)
842
10
      mxTypeError("cannot coerce number to bigint");
843
0
    fxNumberToBigInt(the, slot);  
844
0
    break;
845
22.9k
  case XS_STRING_KIND:
846
22.9k
  case XS_STRING_X_KIND:
847
22.9k
    fxStringToBigInt(the, slot, 1);
848
22.9k
    if (mxBigIntIsNaN(&slot->value.bigint))
849
321
      mxSyntaxError("cannot coerce string to bigint");
850
22.6k
    break;
851
3.26M
  case XS_BIGINT_KIND:
852
3.26M
  case XS_BIGINT_X_KIND:
853
3.26M
    break;
854
17
  case XS_SYMBOL_KIND:
855
17
    mxTypeError("cannot coerce symbol to bigint");
856
0
    break;
857
174
  case XS_REFERENCE_KIND:
858
174
    fxToPrimitive(the, slot, XS_NUMBER_HINT);
859
174
    goto again;
860
52
  default:
861
52
    mxTypeError("cannot coerce to bigint");
862
0
    break;
863
3.29M
  }
864
3.29M
  return &slot->value.bigint;
865
3.29M
}
866
867
void fxFromBigInt64(txMachine* the, txSlot* slot, txS8 it)
868
1.62M
{
869
1.62M
  txU1 sign = 0;
870
1.62M
  txU8 value = 0;
871
1.62M
  if (it < 0) {
872
62
    if (it & 0x7FFFFFFFFFFFFFFFll)
873
62
      value = -it;
874
0
    else
875
0
      value = (txU8)it;
876
62
    sign = 1;
877
62
  }
878
1.62M
  else
879
1.62M
    value = it;
880
1.62M
  if (value > 0x00000000FFFFFFFFll) {
881
92
    slot->value.bigint.data = fxNewChunk(the, 2 * sizeof(txU4));
882
92
    slot->value.bigint.data[0] = (txU4)value;
883
92
    slot->value.bigint.data[1] = (txU4)(value >> 32);
884
92
    slot->value.bigint.size = 2;
885
92
  }
886
1.62M
  else {
887
1.62M
    slot->value.bigint.data = fxNewChunk(the, sizeof(txU4));
888
1.62M
    slot->value.bigint.data[0] = (txU4)value;
889
1.62M
    slot->value.bigint.size = 1;
890
1.62M
  }
891
1.62M
    slot->value.bigint.sign = sign;
892
1.62M
  slot->kind = XS_BIGINT_KIND;
893
1.62M
}
894
895
void fxFromBigUint64(txMachine* the, txSlot* slot, txU8 value)
896
131
{
897
131
  if (value > 0x00000000FFFFFFFFll) {
898
88
    slot->value.bigint.data = fxNewChunk(the, 2 * sizeof(txU4));
899
88
    slot->value.bigint.data[0] = (txU4)(value);
900
88
    slot->value.bigint.data[1] = (txU4)(value >> 32);
901
88
    slot->value.bigint.size = 2;
902
88
  }
903
43
  else {
904
43
    slot->value.bigint.data = fxNewChunk(the, sizeof(txU4));
905
43
    slot->value.bigint.data[0] = (txU4)value;
906
43
    slot->value.bigint.size = 1;
907
43
  }
908
131
    slot->value.bigint.sign = 0;
909
131
  slot->kind = XS_BIGINT_KIND;
910
131
}
911
912
#endif
913
914
txBigInt *fxBigInt_alloc(txMachine* the, txU4 size)
915
13.4M
{
916
13.4M
#ifndef mxCompile
917
13.4M
  txBigInt* bigint;
918
13.4M
  if (size > 0xFFFF) {
919
3
    fxAbort(the, XS_NOT_ENOUGH_MEMORY_EXIT);
920
3
  }
921
13.4M
  mxPushUndefined();
922
13.4M
  bigint = &the->stack->value.bigint;
923
13.4M
  bigint->data = fxNewChunk(the, fxMultiplyChunkSizes(the, size, sizeof(txU4)));
924
13.4M
  bigint->size = size;
925
13.4M
  bigint->sign = 0;
926
13.4M
  the->stack->kind = XS_BIGINT_KIND;
927
13.4M
  return bigint;
928
#else
929
  return NULL;
930
#endif
931
13.4M
}
932
933
void fxBigInt_free(txMachine* the, txBigInt *bigint)
934
3.34M
{
935
3.34M
#ifndef mxCompile
936
3.34M
  if (bigint == &the->stack->value.bigint)
937
3.34M
    the->stack++;
938
//  else
939
//    fprintf(stderr, "oops\n");
940
3.34M
#endif
941
3.34M
}
942
943
int fxBigInt_comp(txBigInt *a, txBigInt *b)
944
4.43M
{
945
4.43M
  if (a->sign != b->sign)
946
2.23M
    return(a->sign ? -1: 1);
947
2.20M
  else if (a->sign)
948
752k
    return(fxBigInt_ucomp(b, a));
949
1.44M
  else
950
1.44M
    return(fxBigInt_ucomp(a, b));
951
4.43M
}
952
953
int fxBigInt_ucomp(txBigInt *a, txBigInt *b)
954
4.67M
{
955
4.67M
  int i;
956
957
4.67M
  if (a->size != b->size)
958
1.55M
    return(a->size > b->size ? 1: -1);
959
4.24M
  for (i = a->size; --i >= 0;) {
960
3.55M
    if (a->data[i] != b->data[i])
961
2.42M
      return(a->data[i] > b->data[i] ? 1: -1);
962
3.55M
  }
963
690k
  return(0);
964
3.11M
}
965
966
int fxBigInt_iszero(txBigInt *a)
967
8.18M
{
968
8.18M
  return(a->size == 1 && a->data[0] == 0);
969
8.18M
}
970
971
void
972
fxBigInt_fill0(txBigInt *r)
973
711k
{
974
711k
  c_memset(r->data, 0, r->size * sizeof(txU4));
975
711k
}
976
977
void fxBigInt_copy(txBigInt *a, txBigInt *b)
978
7.15M
{
979
7.15M
  c_memmove(a->data, b->data, b->size * sizeof(txU4));
980
7.15M
  a->size = b->size;
981
7.15M
  a->sign = b->sign;
982
7.15M
}
983
984
txBigInt *fxBigInt_dup(txMachine* the, txBigInt *a)
985
190k
{
986
190k
  txBigInt *r = fxBigInt_alloc(the, a->size);
987
190k
  fxBigInt_copy(r, a);
988
190k
  return(r);
989
190k
}
990
991
int
992
fxBigInt_ffs(txBigInt *a)
993
276k
{
994
276k
  int i;
995
276k
  txU4 w = a->data[a->size - 1];
996
997
8.69M
  for (i = 0; i < (int)mxBigIntWordSize && !(w & ((txU4)1 << (mxBigIntWordSize - 1 - i))); i++)
998
8.41M
    ;
999
276k
  return(i);
1000
276k
}
1001
1002
txBigInt *fxBigInt_fit(txMachine* the, txBigInt *r)
1003
634k
{
1004
634k
  int i = r->size;
1005
3.08M
  while (i > 0) {
1006
2.96M
    i--;
1007
2.96M
    if (r->data[i])
1008
517k
      break;
1009
2.96M
  }
1010
634k
  r->size = (txU2)(i + 1);
1011
634k
  mxBigInt_meter(r->size);
1012
634k
  return r;
1013
634k
}
1014
1015
1016
#if mxWindows
1017
int
1018
fxBigInt_bitsize(txBigInt *e)
1019
{
1020
  return(e->size * mxBigIntWordSize - fxBigInt_ffs(e));
1021
}
1022
#else
1023
int
1024
fxBigInt_bitsize(txBigInt *a)
1025
80.9k
{
1026
80.9k
  int i = a->size;
1027
80.9k
  txU4 w;
1028
104k
  while (i > 0) {
1029
80.9k
    i--;
1030
80.9k
    w = a->data[i];
1031
80.9k
    if (w) {
1032
57.5k
      int c = __builtin_clz(w);
1033
57.5k
      return (i * mxBigIntWordSize) + mxBigIntWordSize - c;
1034
57.5k
    }
1035
80.9k
  }
1036
23.3k
  return 0;
1037
80.9k
}
1038
#endif
1039
1040
int fxBigInt_isset(txBigInt *e, txU4 i)
1041
275k
{
1042
275k
  txU4 w = e->data[i / mxBigIntWordSize];
1043
275k
  return((w & ((txU4)1 << (i % mxBigIntWordSize))) != 0);
1044
275k
}
1045
1046
/*
1047
 * bitwise operations
1048
 */
1049
1050
txBigInt *fxBigInt_not(txMachine* the, txBigInt *r, txBigInt *a)
1051
532k
{
1052
532k
  if (a->sign)
1053
1.43k
    r = fxBigInt_usub(the, r, a, (txBigInt *)&gxBigIntOne);
1054
531k
  else {
1055
531k
    r = fxBigInt_uadd(the, r, a, (txBigInt *)&gxBigIntOne);
1056
531k
    r->sign = 1;
1057
531k
  }
1058
532k
  return(r);
1059
532k
}
1060
1061
txBigInt *fxBigInt_and(txMachine* the, txBigInt *r, txBigInt *a, txBigInt *b)
1062
22.1k
{
1063
22.1k
  txBigInt *aa, *bb;
1064
22.1k
  int i;
1065
22.1k
  if (a->sign) {
1066
12.2k
    if (b->sign)
1067
11.8k
      goto AND_MINUS_MINUS;
1068
444
    aa = a;
1069
444
    a = b;
1070
444
    b = aa; 
1071
444
    goto AND_PLUS_MINUS;
1072
12.2k
  }
1073
9.90k
  if (b->sign)
1074
7.18k
    goto AND_PLUS_MINUS;
1075
2.71k
  return fxBigInt_fit(the, fxBigInt_uand(the, r, a, b));
1076
7.63k
AND_PLUS_MINUS:
1077
// GMP: OP1 & -OP2 == OP1 & ~(OP2 - 1)
1078
7.63k
  if (r == NULL)
1079
7.63k
    r = fxBigInt_alloc(the, a->size);
1080
7.63k
  bb = fxBigInt_usub(the, NULL, b, (txBigInt *)&gxBigIntOne);
1081
7.63k
    if (a->size > bb->size) {
1082
7.73k
    for (i = 0; i < bb->size; i++)
1083
4.11k
      r->data[i] = a->data[i] & ~bb->data[i];
1084
18.2k
    for (; i < a->size; i++)
1085
14.6k
      r->data[i] = a->data[i];
1086
3.62k
    }
1087
4.00k
    else {
1088
9.57k
    for (i = 0; i < a->size; i++)
1089
5.56k
      r->data[i] = a->data[i] & ~bb->data[i];
1090
4.00k
    }
1091
7.63k
    fxBigInt_free(the, bb);
1092
7.63k
  return fxBigInt_fit(the, r);
1093
11.8k
AND_MINUS_MINUS:
1094
// GMP: -((-OP1) & (-OP2)) = -(~(OP1 - 1) & ~(OP2 - 1)) == ~(~(OP1 - 1) & ~(OP2 - 1)) + 1 == ((OP1 - 1) | (OP2 - 1)) + 1
1095
11.8k
  if (r == NULL)
1096
11.8k
    r = fxBigInt_alloc(the, MAX(a->size, b->size) + 1);
1097
11.8k
  aa = fxBigInt_usub(the, NULL, a, (txBigInt *)&gxBigIntOne);
1098
11.8k
  bb = fxBigInt_usub(the, NULL, b, (txBigInt *)&gxBigIntOne);
1099
11.8k
  r = fxBigInt_uor(the, r, aa, bb);
1100
11.8k
  r = fxBigInt_uadd(the, r, r, (txBigInt *)&gxBigIntOne);
1101
11.8k
  r->sign = 1;
1102
11.8k
  fxBigInt_free(the, bb);
1103
11.8k
  fxBigInt_free(the, aa);
1104
11.8k
  return fxBigInt_fit(the, r);
1105
9.90k
}
1106
1107
txBigInt *fxBigInt_uand(txMachine* the, txBigInt *r, txBigInt *a, txBigInt *b)
1108
59.5k
{
1109
59.5k
  int i;
1110
59.5k
  if (a->size > b->size) {
1111
11.8k
    txBigInt *t = b;
1112
11.8k
    b = a;
1113
11.8k
    a = t;
1114
11.8k
  }
1115
59.5k
  if (r == NULL)
1116
20.6k
    r = fxBigInt_alloc(the, a->size);
1117
38.9k
  else
1118
38.9k
    r->size = a->size;
1119
348k
  for (i = 0; i < a->size; i++)
1120
288k
    r->data[i] = a->data[i] & b->data[i];
1121
59.5k
  return(r);
1122
59.5k
}
1123
1124
txBigInt *fxBigInt_or(txMachine* the, txBigInt *r, txBigInt *a, txBigInt *b)
1125
152k
{
1126
152k
  txBigInt *aa, *bb;
1127
152k
  int i;
1128
152k
  mxBigInt_meter(MAX(a->size, b->size));
1129
152k
  if (a->sign) {
1130
151k
    if (b->sign)
1131
38.9k
      goto OR_MINUS_MINUS;
1132
112k
    aa = a;
1133
112k
    a = b;
1134
112k
    b = aa; 
1135
112k
    goto OR_PLUS_MINUS;
1136
151k
  }
1137
1.36k
  if (b->sign)
1138
744
    goto OR_PLUS_MINUS;
1139
623
  return fxBigInt_fit(the, fxBigInt_uor(the, r, a, b));
1140
113k
OR_PLUS_MINUS:
1141
// GMP: -(OP1 | (-OP2)) = -(OP1 | ~(OP2 - 1)) == ~(OP1 | ~(OP2 - 1)) + 1 == (~OP1 & (OP2 - 1)) + 1
1142
113k
  if (r == NULL)
1143
113k
    r = fxBigInt_alloc(the, b->size + 1);
1144
113k
  bb = fxBigInt_usub(the, NULL, b, (txBigInt *)&gxBigIntOne);
1145
113k
    if (a->size < bb->size) {
1146
293k
    for (i = 0; i < a->size; i++)
1147
187k
      r->data[i] = ~a->data[i] & bb->data[i];
1148
1.81M
    for (; i < bb->size; i++)
1149
1.70M
      r->data[i] = bb->data[i];
1150
106k
  }
1151
7.07k
  else {
1152
15.0k
    for (i = 0; i < bb->size; i++)
1153
7.96k
      r->data[i] = ~a->data[i] & bb->data[i];
1154
7.07k
  }
1155
113k
  r->size = bb->size;
1156
113k
  r = fxBigInt_uadd(the, r, r, (txBigInt *)&gxBigIntOne);
1157
113k
  r->sign = 1;
1158
113k
  fxBigInt_free(the, bb);
1159
113k
  return fxBigInt_fit(the, r);
1160
38.9k
OR_MINUS_MINUS:
1161
// GMP: -((-OP1) | (-OP2)) = -(~(OP1 - 1) | ~(OP2 - 1)) == ~(~(OP1 - 1) | ~(OP2 - 1)) + 1 = = ((OP1 - 1) & (OP2 - 1)) + 1
1162
38.9k
  if (r == NULL)
1163
38.9k
    r = fxBigInt_alloc(the, MIN(a->size, b->size) + 1);
1164
38.9k
  aa = fxBigInt_usub(the, NULL, a, (txBigInt *)&gxBigIntOne);
1165
38.9k
  bb = fxBigInt_usub(the, NULL, b, (txBigInt *)&gxBigIntOne);
1166
38.9k
  r = fxBigInt_uand(the, r, aa, bb);
1167
38.9k
  r = fxBigInt_uadd(the, r, r, (txBigInt *)&gxBigIntOne);
1168
38.9k
  r->sign = 1;
1169
38.9k
  fxBigInt_free(the, bb);
1170
38.9k
  fxBigInt_free(the, aa);
1171
38.9k
  return fxBigInt_fit(the, r);
1172
1.36k
}
1173
1174
txBigInt *fxBigInt_uor(txMachine* the, txBigInt *r, txBigInt *a, txBigInt *b)
1175
12.4k
{
1176
12.4k
  int i;
1177
12.4k
  if (a->size < b->size) {
1178
4.43k
    txBigInt *t = b;
1179
4.43k
    b = a;
1180
4.43k
    a = t;
1181
4.43k
  }
1182
12.4k
  if (r == NULL)
1183
623
    r = fxBigInt_alloc(the, a->size);
1184
11.8k
  else
1185
11.8k
    r->size = a->size;
1186
27.2k
  for (i = 0; i < b->size; i++)
1187
14.8k
    r->data[i] = a->data[i] | b->data[i];
1188
131k
  for (; i < a->size; i++)
1189
118k
    r->data[i] = a->data[i];
1190
12.4k
  return(r);
1191
12.4k
}
1192
1193
txBigInt *fxBigInt_xor(txMachine* the, txBigInt *r, txBigInt *a, txBigInt *b)
1194
96.7k
{
1195
96.7k
  txBigInt *aa, *bb;
1196
96.7k
  if (a->sign) {
1197
2.69k
    if (b->sign)
1198
2.41k
      goto XOR_MINUS_MINUS;
1199
284
    aa = a;
1200
284
    a = b;
1201
284
    b = aa; 
1202
284
    goto XOR_PLUS_MINUS;
1203
2.69k
  }
1204
94.0k
  if (b->sign)
1205
93.1k
    goto XOR_PLUS_MINUS;
1206
890
  return fxBigInt_fit(the, fxBigInt_uxor(the, r, a, b));
1207
93.4k
XOR_PLUS_MINUS:
1208
// GMP: -(OP1 ^ (-OP2)) == -(OP1 ^ ~(OP2 - 1)) == ~(OP1 ^ ~(OP2 - 1)) + 1 == (OP1 ^ (OP2 - 1)) + 1
1209
93.4k
  if (r == NULL)
1210
93.4k
    r = fxBigInt_alloc(the, MAX(a->size, b->size) + 1);
1211
93.4k
  bb = fxBigInt_usub(the, NULL, b, (txBigInt *)&gxBigIntOne);
1212
93.4k
  r = fxBigInt_uxor(the, r, a, bb);
1213
93.4k
  r = fxBigInt_uadd(the, r, r, (txBigInt *)&gxBigIntOne);
1214
93.4k
  r->sign = 1;
1215
93.4k
  fxBigInt_free(the, bb);
1216
93.4k
  return fxBigInt_fit(the, r);
1217
2.41k
XOR_MINUS_MINUS:
1218
// GMP: (-OP1) ^ (-OP2) == ~(OP1 - 1) ^ ~(OP2 - 1) == (OP1 - 1) ^ (OP2 - 1)
1219
2.41k
  if (r == NULL)
1220
2.41k
    r = fxBigInt_alloc(the, MAX(a->size, b->size));
1221
2.41k
  aa = fxBigInt_usub(the, NULL, a, (txBigInt *)&gxBigIntOne);
1222
2.41k
  bb = fxBigInt_usub(the, NULL, b, (txBigInt *)&gxBigIntOne);
1223
2.41k
  r = fxBigInt_uxor(the, r, aa, bb);
1224
2.41k
  fxBigInt_free(the, bb);
1225
2.41k
  fxBigInt_free(the, aa);
1226
2.41k
  return fxBigInt_fit(the, r);
1227
94.0k
}
1228
1229
txBigInt *fxBigInt_uxor(txMachine* the, txBigInt *r, txBigInt *a, txBigInt *b)
1230
96.7k
{
1231
96.7k
  int i;
1232
96.7k
  if (a->size < b->size) {
1233
1.68k
    txBigInt *t = b;
1234
1.68k
    b = a;
1235
1.68k
    a = t;
1236
1.68k
  }
1237
96.7k
  if (r == NULL)
1238
890
    r = fxBigInt_alloc(the, a->size);
1239
95.8k
  else
1240
95.8k
    r->size = a->size;
1241
227k
  for (i = 0; i < b->size; i++)
1242
130k
    r->data[i] = a->data[i] ^ b->data[i];
1243
2.74M
  for (; i < a->size; i++)
1244
2.65M
    r->data[i] = a->data[i];
1245
96.7k
  return(r);
1246
96.7k
}
1247
1248
txBigInt *fxBigInt_lsl(txMachine* the, txBigInt *r, txBigInt *a, txBigInt *b)
1249
318k
{
1250
318k
  if (b->sign) {
1251
144k
    if (a->sign) {
1252
5.47k
      r = fxBigInt_ulsr1(the, r, a, b->data[0]);
1253
5.47k
            if (b->data[0])
1254
5.47k
                r = fxBigInt_uadd(the, C_NULL, r, (txBigInt *)&gxBigIntOne);
1255
5.47k
      r->sign = 1;
1256
5.47k
    }
1257
139k
    else
1258
139k
      r = fxBigInt_ulsr1(the, r, a, b->data[0]);
1259
144k
  }
1260
173k
  else {
1261
173k
    r = fxBigInt_ulsl1(the, r, a, b->data[0]);
1262
173k
    r->sign = a->sign;
1263
173k
  }
1264
318k
  return fxBigInt_fit(the, r);
1265
318k
}
1266
1267
txBigInt *fxBigInt_ulsl1(txMachine* the, txBigInt *r, txBigInt *a, txU4 sw)
1268
2.46M
{
1269
2.46M
  txU4 wsz, bsz;
1270
2.46M
  int n;
1271
1272
2.46M
  wsz = sw / mxBigIntWordSize;
1273
2.46M
  bsz = sw % mxBigIntWordSize;
1274
2.46M
  n = a->size + wsz + ((bsz == 0) ? 0 : 1);
1275
2.46M
  if (r == NULL) 
1276
1.04M
    r = fxBigInt_alloc(the, n);
1277
2.46M
  if (bsz == 0) {
1278
295k
    c_memmove(&r->data[wsz], a->data, a->size * sizeof(txU4));
1279
295k
    c_memset(r->data, 0, wsz * sizeof(txU4));
1280
295k
    r->size = a->size + wsz;
1281
295k
  }
1282
2.16M
  else {
1283
2.16M
    r->data[a->size + wsz] = a->data[a->size - 1] >> (mxBigIntWordSize - bsz);
1284
64.8M
    for (n = a->size; --n >= 1;)
1285
62.6M
      r->data[n + wsz] = (a->data[n] << bsz) | (a->data[n - 1] >> (mxBigIntWordSize - bsz));
1286
2.16M
    r->data[wsz] = a->data[0] << bsz;
1287
    /* clear the remaining part */
1288
3.31M
    for (n = wsz; --n >= 0;)
1289
1.14M
      r->data[n] = 0;
1290
    /* adjust r */
1291
2.16M
    r->size = a->size + wsz + (r->data[a->size + wsz] == 0 ? 0: 1);
1292
2.16M
  }
1293
2.46M
  return(r);
1294
2.46M
}
1295
1296
txBigInt *fxBigInt_lsr(txMachine* the, txBigInt *r, txBigInt *a, txBigInt *b)
1297
26.6k
{
1298
26.6k
  if (b->sign) {
1299
15.9k
    r = fxBigInt_ulsl1(the, r, a, b->data[0]);
1300
15.9k
    r->sign = a->sign;
1301
15.9k
  }
1302
10.7k
  else {
1303
10.7k
    if (a->sign) {
1304
7.42k
      r = fxBigInt_ulsr1(the, r, a, b->data[0]);
1305
7.42k
            if (b->data[0])
1306
7.39k
                r = fxBigInt_uadd(the, C_NULL, r, (txBigInt *)&gxBigIntOne);
1307
7.42k
      r->sign = 1;
1308
7.42k
    }
1309
3.28k
    else
1310
3.28k
      r = fxBigInt_ulsr1(the, r, a, b->data[0]);
1311
10.7k
  }
1312
26.6k
  return fxBigInt_fit(the, r);
1313
26.6k
}
1314
1315
txBigInt *fxBigInt_ulsr1(txMachine* the, txBigInt *r, txBigInt *a, txU4 sw)
1316
494k
{
1317
494k
  int wsz, bsz;
1318
494k
  int i, n;
1319
1320
494k
  wsz = sw / mxBigIntWordSize;
1321
494k
  bsz = sw % mxBigIntWordSize;
1322
494k
  n = a->size - wsz;
1323
494k
  if (n <= 0) {
1324
73.7k
    if (r == NULL) r = fxBigInt_alloc(the, 1);
1325
73.7k
    r->size = 1;
1326
73.7k
    r->data[0] = 0;
1327
73.7k
    return(r);
1328
73.7k
  }
1329
  /* 'r' can be the same as 'a' */
1330
420k
  if (r == NULL)
1331
81.8k
    r = fxBigInt_alloc(the, n);
1332
420k
  if (bsz == 0) {
1333
182k
    c_memmove(r->data, &a->data[wsz], n * sizeof(txU4));
1334
182k
    r->size = n;
1335
182k
  }
1336
238k
  else {
1337
276k
    for (i = 0; i < n - 1; i++)
1338
37.9k
      r->data[i] = (a->data[i + wsz] >> bsz) | (a->data[i + wsz + 1] << (mxBigIntWordSize - bsz));
1339
238k
    r->data[i] = a->data[i + wsz] >> bsz;
1340
238k
    r->size = (n > 1 && r->data[n - 1] == 0) ? n - 1: n;
1341
238k
  }
1342
420k
  return(r);
1343
494k
}
1344
1345
txBigInt *fxBigInt_nop(txMachine* the, txBigInt *r, txBigInt *a, txBigInt *b)
1346
805
{
1347
805
#ifndef mxCompile
1348
805
  mxTypeError("no such operation");
1349
0
#endif
1350
0
  return C_NULL;
1351
805
}
1352
1353
/*
1354
 * arithmetic
1355
 */
1356
1357
txBigInt *fxBigInt_add(txMachine* the, txBigInt *rr, txBigInt *aa, txBigInt *bb)
1358
1.20M
{
1359
1.20M
  if ((aa->sign ^ bb->sign) == 0) {
1360
894k
    rr = fxBigInt_uadd(the, rr, aa, bb);
1361
894k
    if (aa->sign)
1362
2.85k
      rr->sign = 1;
1363
894k
  }
1364
311k
  else {
1365
311k
    if (!aa->sign)
1366
1.33k
      rr = fxBigInt_usub(the, rr, aa, bb);
1367
310k
    else
1368
310k
      rr = fxBigInt_usub(the, rr, bb, aa);
1369
311k
  }
1370
1.20M
  mxBigInt_meter(rr->size);
1371
1.20M
  return(rr);
1372
1.20M
}
1373
1374
txBigInt *fxBigInt_dec(txMachine* the, txBigInt *r, txBigInt *a)
1375
2
{
1376
2
  return fxBigInt_sub(the, r, a, (txBigInt *)&gxBigIntOne);
1377
2
}
1378
1379
txBigInt *fxBigInt_inc(txMachine* the, txBigInt *r, txBigInt *a)
1380
1.20M
{
1381
1.20M
  return fxBigInt_add(the, r, a, (txBigInt *)&gxBigIntOne);
1382
1.20M
}
1383
1384
txBigInt *fxBigInt_neg(txMachine* the, txBigInt *r, txBigInt *a)
1385
6.02M
{
1386
6.02M
  if (r == NULL)
1387
6.02M
    r = fxBigInt_alloc(the, a->size);
1388
6.02M
  fxBigInt_copy(r, a);
1389
6.02M
  if (!fxBigInt_iszero(a))
1390
5.87M
    r->sign = !a->sign;
1391
6.02M
  return(r);
1392
6.02M
}
1393
1394
txBigInt *fxBigInt_sub(txMachine* the, txBigInt *rr, txBigInt *aa, txBigInt *bb)
1395
163k
{
1396
163k
  if ((aa->sign ^ bb->sign) == 0) {
1397
162k
    if (!aa->sign)
1398
161k
      rr = fxBigInt_usub(the, rr, aa, bb);
1399
459
    else
1400
459
      rr = fxBigInt_usub(the, rr, bb, aa);
1401
162k
  }
1402
787
  else {
1403
787
    txU1 sign = aa->sign; /* could be replaced if rr=aa */
1404
787
    rr = fxBigInt_uadd(the, rr, aa, bb);
1405
787
    rr->sign = sign;
1406
787
  }
1407
163k
  mxBigInt_meter(rr->size);
1408
163k
  return(rr);
1409
163k
}
1410
1411
#if __has_builtin(__builtin_add_overflow)
1412
static int fxBigInt_uadd_prim(txU4 *rp, txU4 *ap, txU4 *bp, int an, int bn)
1413
3.44M
{
1414
3.44M
  txU4 c = 0;
1415
3.44M
  int i;
1416
1417
6.88M
  for (i = 0; i < an; i++) {
1418
#ifdef __ets__
1419
  unsigned int r;
1420
  if (__builtin_uadd_overflow(ap[i], bp[i], &r)) {
1421
    rp[i] = r + c;
1422
    c = 1;
1423
  }
1424
  else {
1425
    unsigned int t;
1426
    c = __builtin_uadd_overflow(r, c, &t);
1427
    rp[i] = t;
1428
  }
1429
#else
1430
3.44M
    unsigned int r = rp[i];
1431
3.44M
    c = __builtin_uadd_overflow(ap[i], bp[i], &r) | (txU4)__builtin_uadd_overflow(r, c, &r);
1432
3.44M
    rp[i] = r;
1433
3.44M
#endif
1434
3.44M
  }
1435
3.51M
  for (; c && (i < bn); i++) { {
1436
75.9k
    unsigned int t;
1437
75.9k
    c = __builtin_uadd_overflow(1, bp[i], &t);
1438
75.9k
    rp[i] = t;
1439
75.9k
  }
1440
75.9k
  }
1441
71.8M
  for (; i < bn; i++) {
1442
68.4M
    rp[i] = bp[i];
1443
68.4M
  }
1444
3.44M
  return(c);
1445
3.44M
}
1446
#else
1447
static int fxBigInt_uadd_prim(txU4 *rp, txU4 *ap, txU4 *bp, int an, int bn)
1448
{
1449
  txU4 a, b, t, r, c = 0;
1450
  int i;
1451
1452
  for (i = 0; i < an; i++) {
1453
    a = ap[i];
1454
    b = bp[i];
1455
    t = a + b;
1456
    r = t + c;
1457
    rp[i] = r;
1458
    c = t < a || r < t;
1459
  }
1460
  for (; i < bn; i++) {
1461
    r = bp[i] + c;
1462
    rp[i] = r;
1463
    c = r < c;
1464
  }
1465
  return(c);
1466
}
1467
#endif
1468
1469
txBigInt *fxBigInt_uadd(txMachine* the, txBigInt *rr, txBigInt *aa, txBigInt *bb)
1470
3.44M
{
1471
3.44M
  txBigInt *x, *y;
1472
3.44M
  int c;
1473
1474
3.44M
  if (aa->size < bb->size) {
1475
621
    x = aa;
1476
621
    y = bb;
1477
621
  }
1478
3.44M
  else {
1479
3.44M
    x = bb;
1480
3.44M
    y = aa;
1481
3.44M
  }
1482
3.44M
  if (rr == NULL)
1483
1.43M
    rr = fxBigInt_alloc(the, y->size + 1);
1484
3.44M
  c = fxBigInt_uadd_prim(rr->data, x->data, y->data, x->size, y->size);
1485
  /* CAUTION: rr may equals aa or bb. do not touch until here */
1486
3.44M
  rr->size = y->size;
1487
3.44M
  rr->sign = 0;
1488
3.44M
  if (c != 0)
1489
4.91k
    rr->data[rr->size++] = 1;
1490
3.44M
  return(rr);
1491
3.44M
}
1492
1493
txBigInt *fxBigInt_usub(txMachine* the, txBigInt *rr, txBigInt *aa, txBigInt *bb)
1494
995k
{
1495
995k
  int i, n;
1496
995k
  txU4 a, b, r, t;
1497
995k
  txU4 *ap, *bp, *rp;
1498
995k
  txU4 c = 0;
1499
1500
995k
  if (rr == NULL)
1501
666k
    rr = fxBigInt_alloc(the, MAX(aa->size, bb->size));
1502
995k
  rr->sign = (aa->size < bb->size ||
1503
944k
        (aa->size == bb->size && fxBigInt_ucomp(aa, bb) < 0));
1504
995k
  if (rr->sign) {
1505
315k
    txBigInt *tt = aa;
1506
315k
    aa = bb;
1507
315k
    bb = tt;
1508
315k
  }
1509
995k
  ap = aa->data;
1510
995k
  bp = bb->data;
1511
995k
  rp = rr->data;
1512
995k
  n = MIN(aa->size, bb->size);
1513
335M
  for (i = 0; i < n; i++) {
1514
334M
    a = ap[i];
1515
334M
    b = bp[i];
1516
334M
    t = a - b;
1517
334M
    r = t - c;
1518
334M
    rp[i] = r;
1519
334M
    c = a < b || r > t;
1520
334M
  }
1521
995k
  if (aa->size >= bb->size) {
1522
995k
    n = aa->size;
1523
8.04M
    for (; i < n; i++) {
1524
7.04M
      t = ap[i];
1525
7.04M
      r = t - c;
1526
7.04M
      rp[i] = r;
1527
7.04M
      c = r > t;
1528
7.04M
    }
1529
995k
  }
1530
0
  else {
1531
0
    n = bb->size;
1532
0
    for (; i < n; i++) {
1533
0
      t = 0 - bp[i];
1534
0
      r = t - c;
1535
0
      rp[i] = r;
1536
0
      c = r > t;
1537
0
    }
1538
0
  }
1539
  /* remove leading 0s */
1540
1.18M
  while (--i > 0 && rp[i] == 0)
1541
192k
    ;
1542
995k
  rr->size = i + 1;
1543
995k
  return(rr);
1544
995k
}
1545
1546
txBigInt *fxBigInt_mul(txMachine* the, txBigInt *rr, txBigInt *aa, txBigInt *bb)
1547
80.8k
{
1548
80.8k
  rr = fxBigInt_umul(the, rr, aa, bb);
1549
80.8k
  if ((aa->sign != bb->sign) && !fxBigInt_iszero(rr))
1550
1.56k
    rr->sign = 1;
1551
80.8k
  mxBigInt_meter(rr->size);
1552
80.8k
  return(rr);
1553
80.8k
}
1554
1555
txBigInt *fxBigInt_umul(txMachine* the, txBigInt *rr, txBigInt *aa, txBigInt *bb)
1556
189k
{
1557
189k
  txU8 a, b, r;
1558
189k
  txU4 *ap, *bp, *rp;
1559
189k
  txU4 c = 0;
1560
189k
  int i, j, n, m;
1561
1562
189k
  if (rr == NULL)
1563
80.8k
    rr = fxBigInt_alloc(the, aa->size + bb->size);
1564
189k
  fxBigInt_fill0(rr);
1565
189k
  ap = aa->data;
1566
189k
  bp = bb->data;
1567
189k
  rp = rr->data;
1568
189k
  n = bb->size;
1569
588k
  for (i = 0, j = 0; i < n; i++) {
1570
398k
    b = (txU8)bp[i];
1571
398k
    c = 0;
1572
398k
    m = aa->size;
1573
17.8M
    for (j = 0; j < m; j++) {
1574
17.4M
      a = (txU8)ap[j];
1575
17.4M
      r = a * b + c;
1576
17.4M
      r += (txU8)rp[i + j];
1577
17.4M
      rp[i + j] = mxBigIntLowWord(r);
1578
17.4M
      c = mxBigIntHighWord(r);
1579
17.4M
    }
1580
398k
    rp[i + j] = c;
1581
398k
  }
1582
  /* remove leading 0s */
1583
367k
  for (n = i + j; --n > 0 && rp[n] == 0;)
1584
178k
    ;
1585
189k
  rr->size = n + 1;
1586
189k
  rr->sign = 0;
1587
189k
  return(rr);
1588
189k
}
1589
1590
txBigInt *fxBigInt_umul1(txMachine* the, txBigInt *r, txBigInt *a, txU4 b)
1591
716k
{
1592
716k
  int i, n;
1593
716k
  txU4 c = 0;
1594
716k
  txU4 *ap, *rp;
1595
716k
  txU8 wa, wr;
1596
1597
716k
  if (r == NULL)
1598
29.9k
    r = fxBigInt_alloc(the, a->size + 1);
1599
716k
  ap = a->data;
1600
716k
  rp = r->data;
1601
716k
  n = a->size;
1602
337M
  for (i = 0; i < n; i++) {
1603
336M
    wa = (txU8)ap[i];
1604
336M
    wr = wa * b + c;
1605
336M
    c = mxBigIntHighWord(wr);
1606
336M
    rp[i] = mxBigIntLowWord(wr);
1607
336M
  }
1608
716k
  if (c != 0)
1609
376k
    rp[i] = c;
1610
340k
  else {
1611
    /* remove leading 0s */
1612
1.44M
    while (--i > 0 && rp[i] == 0)
1613
1.10M
      ;
1614
340k
  }
1615
716k
  r->size = i + 1;
1616
716k
  return(r);
1617
716k
}
1618
1619
txBigInt *fxBigInt_exp(txMachine* the, txBigInt *r, txBigInt *a, txBigInt *b)
1620
29.9k
{
1621
29.9k
#ifndef mxCompile
1622
29.9k
  if (b->sign)
1623
2
    mxRangeError("negative exponent");
1624
29.9k
#endif
1625
29.9k
  if (fxBigInt_iszero(b)) {
1626
26
    if (r == NULL)
1627
26
      r = fxBigInt_alloc(the, 1);
1628
0
    else {
1629
0
      r->size = 1;
1630
0
      r->sign = 0;
1631
0
    }
1632
26
    r->data[0] = 1;
1633
26
  }
1634
29.9k
  else {
1635
29.9k
    int i = fxBigInt_bitsize(b) - 1;
1636
29.9k
    int odd = fxBigInt_isset(b, i);
1637
29.9k
    txU4 c = fxBigInt_bitsize(a);
1638
29.9k
    txBigInt *t = fxBigInt_umul1(the, NULL, b, c);
1639
29.9k
    t = fxBigInt_ulsr1(the, t, t, 5);
1640
29.9k
#ifndef mxCompile
1641
29.9k
    if ((t->size > 1) || (t->data[0] > 0xFFFF))
1642
22
      mxRangeError("too big exponent");
1643
29.9k
#endif
1644
29.9k
    c = 2 + t->data[0];
1645
29.9k
    fxBigInt_free(the, t);
1646
29.9k
        if (r == NULL)
1647
29.9k
      r = fxBigInt_alloc(the, c);
1648
29.9k
      t = fxBigInt_alloc(the, c);
1649
29.9k
        fxBigInt_copy(r, a);
1650
275k
    while (i > 0) {
1651
245k
            i--;
1652
245k
      t = fxBigInt_sqr(the, t, r);
1653
245k
      if ((odd = fxBigInt_isset(b, i))) {
1654
109k
        r->size = c;
1655
109k
        r = fxBigInt_umul(the, r, t, a);
1656
109k
      }
1657
136k
      else {
1658
136k
        txBigInt u = *r;
1659
136k
        *r = *t;
1660
136k
        *t = u;
1661
136k
      }
1662
245k
      t->size = c;
1663
245k
    }
1664
29.9k
    r->sign = a->sign & odd;
1665
29.9k
    fxBigInt_free(the, t);
1666
29.9k
  }
1667
29.9k
  mxBigInt_meter(r->size);
1668
29.9k
  return(r);
1669
29.9k
}
1670
1671
txBigInt *fxBigInt_sqr(txMachine* the, txBigInt *r, txBigInt *a)
1672
245k
{
1673
245k
  int i, j, t;
1674
245k
  txU4 *ap, *rp;
1675
245k
  txU8 uv, t1, t2, t3, ai;
1676
245k
  txU4 c, cc;
1677
245k
  txU4 overflow = 0;  /* overflow flag of 'u' */
1678
1679
245k
  if (r == NULL)
1680
0
    r = fxBigInt_alloc(the, a->size * 2);
1681
245k
  fxBigInt_fill0(r);
1682
245k
  t = a->size;
1683
245k
  ap = a->data;
1684
245k
  rp = r->data;
1685
1686
2.58M
  for (i = 0; i < t - 1; i++) {
1687
2.33M
    uv = (txU8)ap[i] * ap[i] + rp[i * 2];
1688
2.33M
    rp[i * 2] = mxBigIntLowWord(uv);
1689
2.33M
    c = mxBigIntHighWord(uv);
1690
2.33M
    cc = 0;
1691
2.33M
    ai = ap[i];
1692
423M
    for (j = i + 1; j < t; j++) {
1693
421M
      int k = i + j;
1694
421M
      t1 = ai * ap[j];
1695
421M
      t2 = t1 + c + ((txU8)cc << mxBigIntWordSize);  /* 'cc:c' must be <= 2(b-1) so no overflow here */
1696
421M
      t3 = t1 + t2;
1697
421M
      uv = t3 + rp[k];
1698
421M
      cc = t3 < t1 || uv < t3;
1699
421M
      c = (txU4)mxBigIntHighWord(uv);
1700
421M
      rp[k] = mxBigIntLowWord(uv);
1701
421M
    }
1702
2.33M
    c += overflow;
1703
2.33M
    rp[i + t] = c;    /* c = u */
1704
2.33M
    overflow = cc || c < overflow;
1705
2.33M
  }
1706
  /* the last loop */
1707
245k
  uv = (txU8)ap[i] * ap[i] + rp[i * 2];
1708
245k
  rp[i * 2] = mxBigIntLowWord(uv);
1709
245k
  rp[i + t] = mxBigIntHighWord(uv) + overflow;
1710
1711
  /* remove leading 0s */
1712
455k
  for (i = 2*t; --i > 0 && rp[i] == 0;)
1713
209k
    ;
1714
245k
  r->size = i + 1;
1715
245k
  return(r);
1716
245k
}
1717
1718
txBigInt *fxBigInt_div(txMachine* the, txBigInt *q, txBigInt *a, txBigInt *b)
1719
274k
{
1720
274k
#ifndef mxCompile
1721
274k
  if (fxBigInt_iszero(b))
1722
1.50k
    mxRangeError("zero divider");
1723
272k
#endif
1724
272k
  q = fxBigInt_udiv(the, q, a, b, C_NULL);
1725
272k
  if (!fxBigInt_iszero(q)) {
1726
149k
    if (a->sign)
1727
146k
      q->sign = !q->sign;
1728
149k
    if (b->sign)
1729
146k
      q->sign = !q->sign;
1730
149k
  }
1731
272k
  mxBigInt_meter(q->size);
1732
272k
  return(q);
1733
274k
}
1734
1735
txBigInt *fxBigInt_mod(txMachine* the, txBigInt *r, txBigInt *a, txBigInt *b)
1736
0
{
1737
0
  txBigInt *q;
1738
0
  mxBigInt_meter(((a->size - b->size) * (a->size + b->size)));
1739
0
  if (r == NULL)
1740
0
    r = fxBigInt_alloc(the, a->sign ? b->size : MIN(a->size, b->size));
1741
0
  q = fxBigInt_udiv(the, NULL, a, b, &r);
1742
0
  if (a->sign) {
1743
0
    if (!fxBigInt_iszero(r))
1744
0
      r = fxBigInt_sub(the, r, b, r);
1745
0
  }
1746
0
  fxBigInt_free(the, q);
1747
0
  mxBigInt_meter(r->size);
1748
0
  return(r);
1749
0
}
1750
1751
txBigInt *fxBigInt_rem(txMachine* the, txBigInt *r, txBigInt *a, txBigInt *b)
1752
1.03M
{
1753
1.03M
  txBigInt *q;
1754
1.03M
#ifndef mxCompile
1755
1.03M
  if (fxBigInt_iszero(b))
1756
3
    mxRangeError("zero divider");
1757
1.03M
#endif
1758
1.03M
  mxBigInt_meter(((a->size - b->size) * (a->size + b->size)));
1759
1.03M
  if (r == NULL)
1760
1.03M
    r = fxBigInt_alloc(the, MIN(a->size, b->size));
1761
1.03M
  q = fxBigInt_udiv(the, NULL, a, b, &r);
1762
1.03M
  if (a->sign) {
1763
514k
    if (!fxBigInt_iszero(r))
1764
514k
            r->sign = !r->sign;
1765
514k
  }
1766
1.03M
  fxBigInt_free(the, q);
1767
1.03M
  mxBigInt_meter(r->size);
1768
1.03M
  return(r);
1769
1.03M
}
1770
1771
static void fxBigInt_makepoly(txBigInt *r, txBigInt *a, int t)
1772
458k
{
1773
458k
  int n;
1774
458k
  txU4 *rp, *ap;
1775
1776
  /* make up a polynomial a_t*b^n + a_{t-1}*b^{n-1} + ... */
1777
458k
  n = r->size;
1778
458k
  rp = &r->data[n];
1779
458k
  ap = a->data;
1780
1.55M
  while (--n >= 0) {
1781
1.09M
    *--rp = t < 0 ? 0: ap[t];
1782
1.09M
    --t;
1783
1.09M
  }
1784
458k
}
1785
1786
#if BN_NO_ULDIVMOD
1787
static txU8
1788
div64_32(txU8 a, txU4 b)
1789
{
1790
  txU4 high = (txU4)(a >> 32);
1791
  txU8 r = 0, bb = b, d = 1;
1792
1793
  if (high >= b) {
1794
    high /= b;
1795
    r = (txU8)high << 32;
1796
    a -= (txU8)(high * b) << 32;
1797
  }
1798
  while ((long long)bb > 0 && bb < a) {
1799
    bb += bb;
1800
    d += d;
1801
  }
1802
  do {
1803
    if (a >= bb) {
1804
      a -= bb;
1805
      r += d;
1806
    }
1807
    bb >>= 1;
1808
    d >>= 1;
1809
  } while (d != 0);
1810
  return r;
1811
}
1812
#endif
1813
1814
txBigInt *fxBigInt_udiv(txMachine* the, txBigInt *q, txBigInt *a, txBigInt *b, txBigInt **r)
1815
1.30M
{
1816
1.30M
  int sw;
1817
1.30M
  txBigInt *nb, *na, *tb, *a2, *b2, *tb2, *tb3;
1818
1.30M
  int i, n, t;
1819
1.30M
  txU4 *qp, *ap, *bp;
1820
1.30M
#define mk_dword(p, i)  (((txU8)(p)[i] << mxBigIntWordSize) | (p)[i - 1])
1821
1822
1.30M
  if (fxBigInt_ucomp(a, b) < 0) {
1823
1.03M
    if (q == NULL) {
1824
1.03M
      q = fxBigInt_alloc(the, 1);
1825
1.03M
    }
1826
0
    else {
1827
0
      q->sign = 0;
1828
0
      q->size = 1;
1829
0
    }
1830
1.03M
    q->data[0] = 0;
1831
1.03M
    if (r != NULL) {
1832
909k
      if (*r == NULL)
1833
0
        *r = fxBigInt_dup(the, a);
1834
909k
      else
1835
909k
        fxBigInt_copy(*r, a);
1836
909k
      (*r)->sign = 0;
1837
909k
    }
1838
1.03M
    return(q);
1839
1.03M
  }
1840
1841
  /* CAUTION: if q is present, it must take account of normalization */
1842
276k
  if (q == NULL)
1843
276k
    q = fxBigInt_alloc(the, a->size - b->size + 2);
1844
276k
  if (r != NULL && *r == NULL)
1845
0
    *r = fxBigInt_alloc(the, b->size);
1846
1847
  /* normalize */
1848
276k
  sw = fxBigInt_ffs(b);
1849
276k
  nb = fxBigInt_ulsl1(the, NULL, b, sw);
1850
276k
  na = fxBigInt_ulsl1(the, NULL, a, sw);
1851
276k
  t = nb->size - 1; /* the size must not change from 'b' */
1852
276k
  n = na->size - 1;
1853
1854
  /* adjust size of q */
1855
276k
  q->size = na->size - nb->size + 1;
1856
276k
  fxBigInt_fill0(q);  /* set 0 to quotient */
1857
1858
  /* process the most significant word */
1859
276k
  tb = fxBigInt_ulsl1(the, NULL, nb, (n - t) * mxBigIntWordSize);  /* y*b^n */
1860
276k
  if (fxBigInt_ucomp(na, tb) >= 0) {
1861
147k
    q->data[q->size - 1]++;
1862
147k
    fxBigInt_sub(C_NULL, na, na, tb);
1863
    /* since nomalization done, must be na < tb here */
1864
147k
  }
1865
1866
  /* prepare the constant for the adjustment: y_t*b + y_{t-1} */
1867
276k
  b2 = fxBigInt_alloc(the, 2);
1868
276k
  fxBigInt_makepoly(b2, nb, t);
1869
  /* and allocate for temporary buffer */
1870
276k
  a2 = fxBigInt_alloc(the, 3);
1871
276k
  tb2 = fxBigInt_alloc(the, 3);
1872
276k
  tb3 = fxBigInt_alloc(the, tb->size + 1);
1873
1874
276k
  qp = &q->data[q->size - 1];
1875
276k
  ap = na->data;
1876
276k
  bp = nb->data;
1877
458k
  for (i = n; i >= t + 1; --i) {
1878
181k
    txU4 tq;
1879
1880
    /* the first estimate */
1881
#if BN_NO_ULDIVMOD
1882
    tq = (ap[i] == bp[t]) ? ~(txU4)0: (txU4)div64_32(mk_dword(ap, i), bp[t]);
1883
#else
1884
181k
    tq = (ap[i] == bp[t]) ? ~(txU4)0: (txU4)(mk_dword(ap, i) / bp[t]);
1885
181k
#endif
1886
1887
    /* adjust */
1888
181k
    fxBigInt_makepoly(a2, na, i);
1889
182k
    while (fxBigInt_ucomp(fxBigInt_umul1(the, tb2, b2, tq), a2) > 0)
1890
158
      --tq;
1891
1892
    /* next x */
1893
181k
    fxBigInt_ulsr1(the, tb, tb, mxBigIntWordSize);
1894
181k
    fxBigInt_usub(the, na, na, fxBigInt_umul1(the, tb3, tb, tq));
1895
181k
    if (na->sign) {
1896
0
      fxBigInt_add(the, na, na, tb);
1897
0
      --tq;
1898
0
    }
1899
181k
    *--qp = tq;
1900
181k
  }
1901
276k
  if (r != NULL)
1902
126k
    *r = fxBigInt_ulsr1(the, *r, na, sw);
1903
  /* remove leading 0s from q */
1904
404k
  for (i = q->size; --i > 0 && q->data[i] == 0;)
1905
128k
    ;
1906
276k
  q->size = i + 1;
1907
  
1908
276k
  fxBigInt_free(the, tb3);
1909
276k
  fxBigInt_free(the, tb2);
1910
276k
  fxBigInt_free(the, a2);
1911
276k
  fxBigInt_free(the, b2);
1912
276k
  fxBigInt_free(the, tb);
1913
276k
  fxBigInt_free(the, na);
1914
276k
  fxBigInt_free(the, nb);
1915
276k
  return(q);
1916
1.30M
}
1917
1918
#ifdef mxMetering
1919
void fxBigInt_meter(txMachine* the, int n)
1920
4.64M
{
1921
4.64M
  n--;
1922
4.64M
  the->meterIndex += n * XS_BIGINT_METERING;
1923
4.64M
}
1924
#endif
1925