Skip to content

Commit 3833937

Browse files
committed
v2.1.0
1 parent 1b5bd9a commit 3833937

File tree

13 files changed

+179
-52
lines changed

13 files changed

+179
-52
lines changed

CHANGELOG.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,11 @@ _(none)_
66

77
---
88

9+
## 2.1.0 (2024-01-28)
10+
* *Feature*: Implement `#inc` and `#dec`.
11+
* *Improvement*: Improve `#add` performance.
12+
* *bugfix*: Fix `++` and `--` operators for negative numbers.
13+
914
## 2.0.0 (2024-01-27)
1015
* *Breaking*: Renamed `#cmp` to `#compareTo`.
1116
* *Breaking*: Renamed `#neg` to `#negate`.

README.md

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -94,10 +94,18 @@ Returns the negation of this MpZ (`-this`).
9494

9595
Returns the sum of this MpZ and `rhs`.
9696

97+
#### `#inc(): MpZ`
98+
99+
Returns the increment of this MpZ (`this + 1`).
100+
97101
#### `#sub(rhs: i32 | u32 | i64 | u64 | MpZ): MpZ`
98102

99103
Returns the difference of this MpZ and the `rhs`.
100104

105+
#### `#dec(): MpZ`
106+
107+
Returns the decrement of this MpZ (`this - 1`).
108+
101109
#### `#mul(rhs: i32 | u32 | i64 | u64 | MpZ): MpZ`
102110

103111
Returns the product of this MpZ and the `rhs` (`this * rhs`).

assembly/__benches__/add.ts

Lines changed: 23 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -26,26 +26,26 @@ suite('add large', () => {
2626
});
2727
});
2828

29-
// const c = 0xbeef;
30-
// const mpzC = blackbox(MpZ.from(c));
31-
// const bigIntC = blackbox(BigInt.from(c));
32-
33-
// suite('add small', () => {
34-
// bench('MpZ#_uaddToU32 (small)', () => {
35-
// // @ts-ignore
36-
// blackbox(mpzA._uaddToU32(c));
37-
// });
38-
39-
// bench('MpZ#__uadd (small)', () => {
40-
// // @ts-ignore
41-
// blackbox(mpzA.__uadd(mpzC));
42-
// });
43-
44-
// bench('MpZ#add (small)', () => {
45-
// blackbox(mpzA.add(mpzC));
46-
// });
47-
48-
// bench('BigInt#add (small)', () => {
49-
// blackbox(bigIntA.add(bigIntC));
50-
// });
51-
// });
29+
const c = 0xbeef;
30+
const mpzC = blackbox(MpZ.from(c));
31+
const bigIntC = blackbox(BigInt.from(c));
32+
33+
suite('add small', () => {
34+
bench('MpZ#_uaddToU32 (small)', () => {
35+
// @ts-ignore
36+
blackbox(mpzA._uaddToU32(c));
37+
});
38+
39+
bench('MpZ#__uadd (small)', () => {
40+
// @ts-ignore
41+
blackbox(mpzA.__uadd(mpzC));
42+
});
43+
44+
bench('MpZ#add (small)', () => {
45+
blackbox(mpzA.add(mpzC));
46+
});
47+
48+
bench('BigInt#add (small)', () => {
49+
blackbox(bigIntA.add(bigIntC));
50+
});
51+
});

assembly/__benches__/div.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -72,4 +72,4 @@ suite('mul very large', () => {
7272
bench('BigInt#mul (very large)', () => {
7373
blackbox(f3.mul(f4));
7474
});
75-
});
75+
});

assembly/__benches__/to-string.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -55,4 +55,4 @@ suite('to string (large)', () => {
5555
// bench('BigInt#toString(16) (large)', () => {
5656
// blackbox(f2.toString(16));
5757
// });
58-
});
58+
});

assembly/__tests__/add-sub.spec.ts

Lines changed: 34 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -86,7 +86,7 @@ describe('operators', () => {
8686

8787
let x = MpZ.from(5);
8888
assertSame(x, 5);
89-
x += MpZ.from(1);
89+
x += MpZ.ONE;
9090
assertSame(x, 6);
9191
assertSame(x++, 6);
9292
assertSame(x, 7);
@@ -97,7 +97,39 @@ describe('operators', () => {
9797
assertSame(x, 7);
9898
assertSame(--x, 6);
9999
assertSame(x, 6);
100-
x -= MpZ.from(1);
100+
x -= MpZ.ONE;
101101
assertSame(x, 5);
102102
});
103+
104+
it('operators on negative values', () => {
105+
assertSame(MpZ.from(-0x5) + MpZ.from(-0x3), -8);
106+
assertSame(MpZ.from(-0x5) - MpZ.from(-0x3), -2);
107+
108+
let x = MpZ.from(-5);
109+
assertSame(x, -5);
110+
x += MpZ.from(-1);
111+
assertSame(x, -6);
112+
assertSame(x++, -6);
113+
assertSame(x, -5);
114+
assertSame(++x, -4);
115+
assertSame(x, -4);
116+
117+
assertSame(x--, -4);
118+
assertSame(x, -5);
119+
assertSame(--x, -6);
120+
assertSame(x, -6);
121+
x -= MpZ.from(-1);
122+
assertSame(x, -5);
123+
});
124+
125+
it('operators on zero', () => {
126+
let x = MpZ.from(0);
127+
x++;
128+
assertSame(x, 1);
129+
130+
x--;
131+
assertSame(x, 0);
132+
x--;
133+
assertSame(x, -1);
134+
});
103135
});

assembly/index.ts

Lines changed: 58 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -302,15 +302,14 @@ export class MpZ {
302302
const q = this.size;
303303
const z = new StaticArray<u32>(q + 1);
304304

305-
let k: u64 = 0;
305+
let k: bool = 0;
306306
for (let i: i32 = 0; i < q; ++i) {
307307
const lx = unchecked(this._data[i]);
308308
const ly = rhs.size > i ? unchecked(rhs._data[i]) : 0;
309-
k += u64(lx) + u64(ly);
310-
unchecked((z[i] = LOW(k)));
311-
k = HIGH(k);
309+
unchecked((z[i] = lx + ly + k));
310+
k = z[i] < lx || (k && z[i] === lx);
312311
}
313-
unchecked((z[q] = LOW(k)));
312+
unchecked((z[q] = k));
314313

315314
return new MpZ(z);
316315
}
@@ -330,6 +329,31 @@ export class MpZ {
330329
return new MpZ(z);
331330
}
332331

332+
/**
333+
* #### `#inc(): MpZ`
334+
*
335+
* Returns the increment of this MpZ (`this + 1`).
336+
*/
337+
@operator.prefix('++')
338+
@operator.postfix('++')
339+
inc(): MpZ {
340+
if (this.isNeg) return this._udec().negate(); // -a + 1 = -(a - 1)
341+
return this._uinc();
342+
}
343+
344+
protected _uinc(): MpZ {
345+
const q = this.size;
346+
const z = new StaticArray<u32>(q + 1);
347+
348+
let k: bool = 1;
349+
for (let i: i32 = 0; i < q; ++i) {
350+
unchecked((z[i] = k + this._data[i]));
351+
k = unchecked(z[i] < this._data[i]);
352+
}
353+
unchecked((z[q] = k));
354+
return new MpZ(z);
355+
}
356+
333357
// *** Subtraction ***
334358

335359
/**
@@ -393,6 +417,34 @@ export class MpZ {
393417
return new MpZ(z);
394418
}
395419

420+
/**
421+
* #### `#dec(): MpZ`
422+
*
423+
* Returns the decrement of this MpZ (`this - 1`).
424+
*/
425+
@operator.prefix('--')
426+
@operator.postfix('--')
427+
dec(): MpZ {
428+
if (this.isNeg) return this._uinc().negate(); // -a - 1 = -(a + 1)
429+
if (this.eqz()) return MpZ.ONE.negate();
430+
return this._udec();
431+
}
432+
433+
protected _udec(): MpZ {
434+
const q = this.size;
435+
const z = new StaticArray<u32>(q);
436+
437+
let k: bool = 1;
438+
for (let i: i32 = 0; i < q; ++i) {
439+
const lx = unchecked(this._data[i]);
440+
441+
unchecked((z[i] = lx - k));
442+
k = k > lx ? 1 : 0;
443+
}
444+
445+
return new MpZ(z);
446+
}
447+
396448
// *** Multiplication ***
397449

398450
/**
@@ -948,7 +1000,7 @@ export class MpZ {
9481000
*/
9491001
// @ts-ignore
9501002
protected not(): MpZ {
951-
return this.isNeg ? this._usubU32(1) : this._uaddU32(1).negate();
1003+
return this.isNeg ? this._udec() : this._uinc().negate();
9521004
}
9531005

9541006
/**
@@ -1385,20 +1437,6 @@ export class MpZ {
13851437
return lhs.sub(rhs);
13861438
}
13871439

1388-
1389-
@operator.prefix('++')
1390-
@operator.postfix('++')
1391-
protected inc(): MpZ {
1392-
return this._uaddU32(1);
1393-
}
1394-
1395-
1396-
@operator.prefix('--')
1397-
@operator.postfix('--')
1398-
protected dec(): MpZ {
1399-
return this._usubU32(1);
1400-
}
1401-
14021440
/**
14031441
* ### Comparison Operators
14041442
*

assembly/main.ts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,10 @@ export function add(a: MpZ, b: MpZ): MpZ {
7777
return a + b;
7878
}
7979

80+
export function inc(a: MpZ): MpZ {
81+
return ++a;
82+
}
83+
8084
export function mul(a: MpZ, b: MpZ): MpZ {
8185
return a * b;
8286
}
@@ -101,6 +105,10 @@ export function sub(a: MpZ, b: MpZ): MpZ {
101105
return a - b;
102106
}
103107

108+
export function dec(a: MpZ): MpZ {
109+
return --a;
110+
}
111+
104112
export function eqz(a: MpZ): boolean {
105113
return a.eqz();
106114
}

docs/api/index.md

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,10 +45,18 @@ Returns the negation of this MpZ (`-this`).
4545

4646
Returns the sum of this MpZ and `rhs`.
4747

48+
#### `#inc(): MpZ`
49+
50+
Returns the increment of this MpZ (`this + 1`).
51+
4852
#### `#sub(rhs: i32 | u32 | i64 | u64 | MpZ): MpZ`
4953

5054
Returns the difference of this MpZ and the `rhs`.
5155

56+
#### `#dec(): MpZ`
57+
58+
Returns the decrement of this MpZ (`this - 1`).
59+
5260
#### `#mul(rhs: i32 | u32 | i64 | u64 | MpZ): MpZ`
5361

5462
Returns the product of this MpZ and the `rhs` (`this * rhs`).

examples/perfect.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ function isPrime32(p: i32): boolean {
1414
}
1515

1616
// Lucas-Lehmer primality test for Mersenne numbers
17-
function lucasLehmer(p: i32, Mp: MpZ = MpZ.ONE.mul_pow2(p).sub(1)): boolean {
17+
function lucasLehmer(p: i32, Mp: MpZ = MpZ.ONE.mul_pow2(p).dec()): boolean {
1818
let s = MpZ.from(4).rem(Mp);
1919

2020
for (let i = 1; i < p - 1; i++) {
@@ -32,7 +32,7 @@ for (let p = 2; p < 1500; p++) {
3232
u = u.mul_pow2(1);
3333
if (!isPrime32(p)) continue;
3434

35-
const Mp = u.sub(1);
35+
const Mp = u.dec();
3636
if (p === 2 || lucasLehmer(p, Mp)) {
3737
const perfect = Mp.mul(u.div_pow2(1));
3838
console.log(`${p} : ${trim(Mp)} : ${trim(perfect)}`);

0 commit comments

Comments
 (0)