-
-
Notifications
You must be signed in to change notification settings - Fork 0
/
kPowerGen.ts
109 lines (95 loc) · 2.89 KB
/
kPowerGen.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
import { Generator } from "./generator";
import { Ops } from "../../ops/ops";
import { tryK, tryNumTerms } from "../../utils/try";
import { Powers } from "../../utils/powers";
import { Encoding } from "../encoding/encoding";
import { GenConfig } from "./genConfig";
export class KPowerGen<K, V> implements Generator<K, V> {
private cached: boolean;
private customs: V[];
private encoding: Encoding<V, unknown>;
private indexOps: Ops<K>;
private isStd: boolean;
private _K: number;
private neg: Powers<K, unknown>;
private pos: Powers<K, unknown>;
private v0: V;
private zero: unknown;
constructor(K: number, config: GenConfig<K, V, unknown>) {
tryK(K);
const cached = config.cached ?? true;
const customs = config.customs ?? [];
const encoding = config.encoding;
const indexOps = config.indexOps ?? config.ops;
if (encoding == null) {
throw new TypeError(`Missing encoding`);
}
if (indexOps == null) {
throw new TypeError(`Missing index operations`);
}
this.cached = cached;
this.customs = customs;
this.encoding = encoding;
this.indexOps = indexOps;
this.isStd = false;
this._K = K;
this.neg = new Powers(encoding.genNegK(K), indexOps, encoding, cached);
this.pos = new Powers(encoding.genK(K), indexOps, encoding, cached);
this.zero = encoding.genZero(K);
this.v0 = encoding.toValue(this.zero, 0);
this.setCustoms(customs);
}
get K(): number {
return this._K;
}
get(N: K): V {
const iOps = this.indexOps;
const T = iOps.cast(this.customs.length - 1);
if (iOps.sign(N) >= 0 && iOps.smallerEq(N, T)) {
return this.customs[iOps.toNumber(N)];
}
let data: unknown;
let delta: K;
N = iOps.minus(N, T);
const K = iOps.cast(this.K);
if (iOps.sign(N) > 0) {
const mod = iOps.mod(iOps.minus1(N), K);
delta = iOps.minus1(K);
N = iOps.trunc(iOps.dividedBy(N, K));
N = iOps.equal(mod, delta) ? N : iOps.plus1(N);
delta = iOps.plus(iOps.negative(delta), mod);
data = this.pos.get(N);
} else if (iOps.larger(N, iOps.negative(K))) {
delta = N;
data = this.zero;
} else {
delta = iOps.mod(N, K);
N = iOps.negative(N);
N = iOps.trunc(iOps.dividedBy(N, K));
data = this.neg.get(N);
}
const customs = this.isStd ? undefined : this.customs;
return this.encoding.toValue(data, iOps.toNumber(delta), customs);
}
getCached(): boolean {
return this.cached;
}
getCustoms(): V[] {
return this.customs;
}
setCached(value: boolean): void {
this.cached = value;
this.neg.setCached(value);
this.pos.setCached(value);
}
setCustoms(customs?: V[]): void {
if (customs == null || customs.length < 1) {
this.isStd = true;
this.customs = [this.v0];
} else {
tryNumTerms(this.K, customs);
this.isStd = false;
this.customs = customs;
}
}
}