Coverage Report

Created: 2025-06-13 06:10

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