@pkmn/engine 0.1.0-dev.645b4750 → 0.1.0-dev.6ba42cd5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +1 -1
- package/README.md +12 -31
- package/build/pkg/addon/wasm.js.map +1 -1
- package/build/pkg/addon.d.ts +4 -4
- package/build/pkg/addon.js.map +1 -1
- package/build/tools/debug.js +19 -1
- package/build/tools/debug.js.map +1 -1
- package/build/tools/display/ui.jsx +1 -1
- package/build/tools/display/ui.jsx.map +1 -1
- package/build.zig +135 -225
- package/package.json +23 -21
- package/src/bin/install-pkmn-engine +22 -7
- package/src/lib/bindings/c.zig +27 -82
- package/src/lib/bindings/node.zig +7 -11
- package/src/lib/bindings/wasm.zig +6 -15
- package/src/lib/common/array.zig +5 -12
- package/src/lib/common/debug.zig +11 -21
- package/src/lib/common/js.zig +3 -9
- package/src/lib/common/optional.zig +11 -21
- package/src/lib/common/protocol.zig +176 -163
- package/src/lib/common/rational.zig +91 -173
- package/src/lib/common/util.zig +14 -46
- package/src/lib/gen1/calc.zig +46 -52
- package/src/lib/gen1/chance.zig +17 -32
- package/src/lib/gen1/data/types.zig +2 -2
- package/src/lib/gen1/data.zig +5 -5
- package/src/lib/gen1/helpers.zig +8 -10
- package/src/lib/gen1/mechanics.zig +23 -14
- package/src/lib/gen2/calc.zig +3 -6
- package/src/lib/gen2/chance.zig +12 -18
- package/src/lib/gen2/data/types.zig +6 -3
- package/src/lib/gen2/data.zig +8 -7
- package/src/lib/gen2/helpers.zig +4 -6
- package/src/lib/gen2/mechanics.zig +9 -9
- package/src/lib/napi.h +2 -0
- package/src/lib/node.zig +1 -5
- package/src/lib/pkmn.zig +91 -17
- package/src/lib/wasm.zig +2 -6
|
@@ -6,13 +6,6 @@ const expect = std.testing.expect;
|
|
|
6
6
|
const expectEqual = std.testing.expectEqual;
|
|
7
7
|
const expectError = std.testing.expectError;
|
|
8
8
|
|
|
9
|
-
const Int = if (@hasField(std.builtin.Type, "int")) .int else .Int;
|
|
10
|
-
const Float = if (@hasField(std.builtin.Type, "float")) .float else .Float;
|
|
11
|
-
const ComptimeInt =
|
|
12
|
-
if (@hasField(std.builtin.Type, "comptime_int")) .comptime_int else .ComptimeInt;
|
|
13
|
-
const ComptimeFloat =
|
|
14
|
-
if (@hasField(std.builtin.Type, "comptime_float")) .comptime_float else .ComptimeFloat;
|
|
15
|
-
|
|
16
9
|
/// Specialization of a rational number used by the engine to compute probabilties.
|
|
17
10
|
/// For performance reasons the rational is only reduced lazily and thus `reduce` must be
|
|
18
11
|
/// invoked explicitly before reading. Note that this laziness means that this implementation
|
|
@@ -23,14 +16,14 @@ pub fn Rational(comptime T: type) type {
|
|
|
23
16
|
// instead start reducing when we get sufficiently close to the limit of the mantissa
|
|
24
17
|
// (in our domain we expect updates to involve numbers < 2**10, so we should be safe
|
|
25
18
|
// not reducing before we are 2**10 away from "overflowing" the mantissa)
|
|
26
|
-
const o = if (@typeInfo(T) ==
|
|
19
|
+
const o = if (@typeInfo(T) == .float)
|
|
27
20
|
std.math.pow(T, 2, std.math.floatMantissaBits(T) - 10)
|
|
28
21
|
else
|
|
29
22
|
0;
|
|
30
23
|
|
|
31
24
|
const Err = switch (@typeInfo(T)) {
|
|
32
|
-
|
|
33
|
-
|
|
25
|
+
.int => error{Overflow},
|
|
26
|
+
.float => error{},
|
|
34
27
|
else => unreachable,
|
|
35
28
|
};
|
|
36
29
|
|
|
@@ -68,18 +61,17 @@ pub fn Rational(comptime T: type) type {
|
|
|
68
61
|
return mul_(T, o, r, s);
|
|
69
62
|
}
|
|
70
63
|
|
|
64
|
+
/// Compares two rationals using the identity (a/b) > (c/d) => ad > bc
|
|
65
|
+
pub fn cmp(r: *Self, s: anytype) Error!std.math.Order {
|
|
66
|
+
return cmp_(T, o, r, s);
|
|
67
|
+
}
|
|
68
|
+
|
|
71
69
|
/// Normalize the rational by reducing by the greatest common divisor.
|
|
72
70
|
pub fn reduce(r: *Self) void {
|
|
73
71
|
reduce_(r);
|
|
74
72
|
}
|
|
75
73
|
|
|
76
|
-
pub fn format(
|
|
77
|
-
self: Self,
|
|
78
|
-
comptime fmt: []const u8,
|
|
79
|
-
opts: std.fmt.FormatOptions,
|
|
80
|
-
writer: anytype,
|
|
81
|
-
) !void {
|
|
82
|
-
_ = .{ fmt, opts };
|
|
74
|
+
pub fn format(self: Self, writer: *std.Io.Writer) !void {
|
|
83
75
|
try writer.print("{d}/{d}", .{ self.p, self.q });
|
|
84
76
|
}
|
|
85
77
|
} else struct {
|
|
@@ -115,18 +107,17 @@ pub fn Rational(comptime T: type) type {
|
|
|
115
107
|
return mul_(T, o, r, s);
|
|
116
108
|
}
|
|
117
109
|
|
|
110
|
+
/// Compares two rationals using the identity (a/b) > (c/d) => ad > bc
|
|
111
|
+
pub fn cmp(r: *Self, s: anytype) Error!std.math.Order {
|
|
112
|
+
return cmp_(T, o, r, s);
|
|
113
|
+
}
|
|
114
|
+
|
|
118
115
|
/// Normalize the rational by reducing by the greatest common divisor.
|
|
119
116
|
pub fn reduce(r: *Self) void {
|
|
120
117
|
reduce_(r);
|
|
121
118
|
}
|
|
122
119
|
|
|
123
|
-
pub fn format(
|
|
124
|
-
self: Self,
|
|
125
|
-
comptime fmt: []const u8,
|
|
126
|
-
opts: std.fmt.FormatOptions,
|
|
127
|
-
writer: anytype,
|
|
128
|
-
) !void {
|
|
129
|
-
_ = .{ fmt, opts };
|
|
120
|
+
pub fn format(self: Self, writer: *std.Io.Writer) !void {
|
|
130
121
|
try writer.print("{d}/{d}", .{ self.p, self.q });
|
|
131
122
|
}
|
|
132
123
|
};
|
|
@@ -140,12 +131,12 @@ fn update_(comptime T: type, comptime o: comptime_int, r: anytype, p: anytype, q
|
|
|
140
131
|
// If our parameters are not fully reduced they may prematurely
|
|
141
132
|
// cause overflow/loss of precision after the multiplication below
|
|
142
133
|
assert(switch (@typeInfo(@TypeOf(p, q))) {
|
|
143
|
-
|
|
134
|
+
.comptime_int, .comptime_float => comptime gcd(p, q),
|
|
144
135
|
else => 1,
|
|
145
136
|
} == 1);
|
|
146
137
|
|
|
147
138
|
switch (@typeInfo(T)) {
|
|
148
|
-
|
|
139
|
+
.int => {
|
|
149
140
|
// Greedily attempt to multiply and if it fails, reduce and try again
|
|
150
141
|
multiplication(T, r, p, q) catch |err| switch (err) {
|
|
151
142
|
error.Overflow => {
|
|
@@ -155,16 +146,16 @@ fn update_(comptime T: type, comptime o: comptime_int, r: anytype, p: anytype, q
|
|
|
155
146
|
else => unreachable,
|
|
156
147
|
};
|
|
157
148
|
},
|
|
158
|
-
|
|
149
|
+
.float => {
|
|
159
150
|
// Reduce in situations where we're likely to start losing precision
|
|
160
151
|
if (r.q > o or r.p > o) r.reduce();
|
|
161
152
|
|
|
162
153
|
r.p *= switch (@typeInfo(@TypeOf(p))) {
|
|
163
|
-
|
|
154
|
+
.float, .comptime_float => p,
|
|
164
155
|
else => @floatFromInt(p),
|
|
165
156
|
};
|
|
166
157
|
r.q *= switch (@typeInfo(@TypeOf(q))) {
|
|
167
|
-
|
|
158
|
+
.float, .comptime_float => q,
|
|
168
159
|
else => @floatFromInt(q),
|
|
169
160
|
};
|
|
170
161
|
|
|
@@ -178,7 +169,7 @@ fn update_(comptime T: type, comptime o: comptime_int, r: anytype, p: anytype, q
|
|
|
178
169
|
|
|
179
170
|
fn add_(comptime T: type, comptime o: comptime_int, r: anytype, s: anytype) !void {
|
|
180
171
|
switch (@typeInfo(T)) {
|
|
181
|
-
|
|
172
|
+
.int => {
|
|
182
173
|
if (r.q == s.q) {
|
|
183
174
|
r.p = std.math.add(T, r.p, s.p) catch |err| switch (err) {
|
|
184
175
|
error.Overflow => val: {
|
|
@@ -199,7 +190,7 @@ fn add_(comptime T: type, comptime o: comptime_int, r: anytype, s: anytype) !voi
|
|
|
199
190
|
};
|
|
200
191
|
}
|
|
201
192
|
},
|
|
202
|
-
|
|
193
|
+
.float => {
|
|
203
194
|
if (r.q == s.q) {
|
|
204
195
|
if (r.p > o) r.reduce();
|
|
205
196
|
if (s.p > o) s.reduce();
|
|
@@ -223,7 +214,7 @@ fn add_(comptime T: type, comptime o: comptime_int, r: anytype, s: anytype) !voi
|
|
|
223
214
|
|
|
224
215
|
fn mul_(comptime T: type, comptime o: comptime_int, r: anytype, s: anytype) !void {
|
|
225
216
|
switch (@typeInfo(T)) {
|
|
226
|
-
|
|
217
|
+
.int => {
|
|
227
218
|
multiplication(T, r, s.p, s.q) catch |err| switch (err) {
|
|
228
219
|
error.Overflow => {
|
|
229
220
|
r.reduce();
|
|
@@ -233,7 +224,7 @@ fn mul_(comptime T: type, comptime o: comptime_int, r: anytype, s: anytype) !voi
|
|
|
233
224
|
else => unreachable,
|
|
234
225
|
};
|
|
235
226
|
},
|
|
236
|
-
|
|
227
|
+
.float => {
|
|
237
228
|
if (r.q > o or r.p > o) r.reduce();
|
|
238
229
|
if (s.q > o or s.p > o) s.reduce();
|
|
239
230
|
|
|
@@ -247,6 +238,41 @@ fn mul_(comptime T: type, comptime o: comptime_int, r: anytype, s: anytype) !voi
|
|
|
247
238
|
}
|
|
248
239
|
}
|
|
249
240
|
|
|
241
|
+
fn cmp_(comptime T: type, comptime o: comptime_int, r: anytype, s: anytype) !std.math.Order {
|
|
242
|
+
switch (@typeInfo(T)) {
|
|
243
|
+
.int => {
|
|
244
|
+
const ad = std.math.mul(T, r.p, s.q) catch |err| switch (err) {
|
|
245
|
+
error.Overflow => ad: {
|
|
246
|
+
r.reduce();
|
|
247
|
+
s.reduce();
|
|
248
|
+
break :ad try std.math.mul(T, r.p, s.q);
|
|
249
|
+
},
|
|
250
|
+
else => unreachable,
|
|
251
|
+
};
|
|
252
|
+
const bc = std.math.mul(T, r.q, s.p) catch |err| switch (err) {
|
|
253
|
+
error.Overflow => bc: {
|
|
254
|
+
r.reduce();
|
|
255
|
+
s.reduce();
|
|
256
|
+
break :bc try std.math.mul(T, r.q, s.p);
|
|
257
|
+
},
|
|
258
|
+
else => unreachable,
|
|
259
|
+
};
|
|
260
|
+
|
|
261
|
+
return std.math.order(ad, bc);
|
|
262
|
+
},
|
|
263
|
+
.float => {
|
|
264
|
+
if (r.q > o or r.p > o) r.reduce();
|
|
265
|
+
if (s.q > o or s.p > o) s.reduce();
|
|
266
|
+
|
|
267
|
+
const ad: T = r.p * s.q;
|
|
268
|
+
const bc: T = r.q * s.p;
|
|
269
|
+
|
|
270
|
+
return std.math.order(ad, bc);
|
|
271
|
+
},
|
|
272
|
+
else => unreachable,
|
|
273
|
+
}
|
|
274
|
+
}
|
|
275
|
+
|
|
250
276
|
fn reduce_(r: anytype) void {
|
|
251
277
|
const d = gcd(r.p, r.q);
|
|
252
278
|
if (d == 1) return;
|
|
@@ -268,12 +294,12 @@ fn multiplication(comptime T: type, r: anytype, p: anytype, q: anytype) !void {
|
|
|
268
294
|
|
|
269
295
|
fn addition(comptime T: type, r: anytype, p: anytype, q: anytype) !void {
|
|
270
296
|
// (a/b) + (c/d) = (ad+bc)/(bd)
|
|
271
|
-
const
|
|
272
|
-
const
|
|
273
|
-
const
|
|
297
|
+
const bd = try std.math.mul(T, r.q, q);
|
|
298
|
+
const ad = try std.math.mul(T, r.p, q);
|
|
299
|
+
const bc = try std.math.mul(T, r.q, p);
|
|
274
300
|
|
|
275
|
-
r.p = try std.math.add(T,
|
|
276
|
-
r.q =
|
|
301
|
+
r.p = try std.math.add(T, ad, bc);
|
|
302
|
+
r.q = bd;
|
|
277
303
|
}
|
|
278
304
|
|
|
279
305
|
fn gcd(p: anytype, q: anytype) @TypeOf(p, q) {
|
|
@@ -287,7 +313,7 @@ fn gcd(p: anytype, q: anytype) @TypeOf(p, q) {
|
|
|
287
313
|
};
|
|
288
314
|
|
|
289
315
|
switch (@typeInfo(T)) {
|
|
290
|
-
|
|
316
|
+
.int => {
|
|
291
317
|
// std.math.gcd but without some checks because we have a stricter range
|
|
292
318
|
var x: T = @intCast(p);
|
|
293
319
|
var y: T = @intCast(q);
|
|
@@ -328,8 +354,7 @@ fn gcd(p: anytype, q: anytype) @TypeOf(p, q) {
|
|
|
328
354
|
}
|
|
329
355
|
|
|
330
356
|
test gcd {
|
|
331
|
-
|
|
332
|
-
var prng = (if (@hasDecl(std, "Random")) std.Random else std.rand).DefaultPrng.init(seed);
|
|
357
|
+
var prng = std.Random.DefaultPrng.init(std.testing.random_seed);
|
|
333
358
|
var random = prng.random();
|
|
334
359
|
|
|
335
360
|
for (0..1000) |_| {
|
|
@@ -356,7 +381,8 @@ fn doTurn(r: anytype) !void {
|
|
|
356
381
|
|
|
357
382
|
test Rational {
|
|
358
383
|
inline for (.{ u64, u128, u256, f64 }) |t| {
|
|
359
|
-
|
|
384
|
+
const R = Rational(t);
|
|
385
|
+
var r: R = .{};
|
|
360
386
|
|
|
361
387
|
var c: t = 128;
|
|
362
388
|
_ = &c;
|
|
@@ -365,7 +391,7 @@ test Rational {
|
|
|
365
391
|
try doTurn(&r);
|
|
366
392
|
|
|
367
393
|
r.reduce();
|
|
368
|
-
try expectEqual(
|
|
394
|
+
try expectEqual(R{ .p = 75383, .q = 35550920704 }, r);
|
|
369
395
|
|
|
370
396
|
try r.update(1, 4);
|
|
371
397
|
if (t == u64) {
|
|
@@ -373,150 +399,42 @@ test Rational {
|
|
|
373
399
|
} else {
|
|
374
400
|
try doTurn(&r);
|
|
375
401
|
r.reduce();
|
|
376
|
-
try expectEqual(
|
|
402
|
+
try expectEqual(R{ .p = 5682596689, .q = 2527735925804191711232 }, r);
|
|
377
403
|
}
|
|
378
404
|
|
|
379
405
|
r.reset();
|
|
380
406
|
|
|
381
|
-
var s =
|
|
407
|
+
var s = R{ .p = 10, .q = 13 };
|
|
382
408
|
try r.mul(&s);
|
|
383
|
-
s =
|
|
409
|
+
s = R{ .p = 3, .q = 4 };
|
|
384
410
|
try r.mul(&s);
|
|
385
|
-
try expectEqual(
|
|
411
|
+
try expectEqual(R{ .p = 30, .q = 52 }, r);
|
|
386
412
|
|
|
387
|
-
s =
|
|
413
|
+
s = R{ .p = 1, .q = 3 };
|
|
388
414
|
try r.add(&s);
|
|
389
415
|
r.reduce();
|
|
390
|
-
try expectEqual(
|
|
391
|
-
}
|
|
392
|
-
}
|
|
416
|
+
try expectEqual(R{ .p = 71, .q = 78 }, r);
|
|
393
417
|
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
418
|
+
var u = R{ .p = 3, .q = 5 };
|
|
419
|
+
var v = R{ .p = 2, .q = 5 };
|
|
420
|
+
try expectEqual(u.cmp(&v), .gt);
|
|
421
|
+
v = R{ .p = 4, .q = 5 };
|
|
422
|
+
try expectEqual(u.cmp(&v), .lt);
|
|
398
423
|
|
|
399
|
-
|
|
400
|
-
|
|
424
|
+
v = R{ .p = 3, .q = 6 };
|
|
425
|
+
try expectEqual(u.cmp(&v), .gt);
|
|
426
|
+
v = R{ .p = 3, .q = 4 };
|
|
427
|
+
try expectEqual(u.cmp(&v), .lt);
|
|
401
428
|
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
pub fn init(alloc: std.mem.Allocator) !BigRational {
|
|
405
|
-
return .{ .val = try std.math.big.Rational.init(alloc) };
|
|
406
|
-
}
|
|
429
|
+
v = R{ .p = 3, .q = 5 };
|
|
430
|
+
try expectEqual(u.cmp(&v), .eq);
|
|
407
431
|
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
/// Resets the rational back to 1.
|
|
414
|
-
pub fn reset(r: *BigRational) !void {
|
|
415
|
-
try r.val.setInt(1);
|
|
416
|
-
}
|
|
417
|
-
|
|
418
|
-
/// Update the rational by multiplying its numerator by p and its denominator by q.
|
|
419
|
-
/// Both p and q must be >= 1.
|
|
420
|
-
pub fn update(r: *BigRational, p: anytype, q: anytype) !void {
|
|
421
|
-
assert(p >= 1);
|
|
422
|
-
assert(q >= 1);
|
|
423
|
-
|
|
424
|
-
var s = try std.math.big.Rational.init(r.val.p.allocator);
|
|
425
|
-
defer s.deinit();
|
|
426
|
-
try s.setRatio(p, q);
|
|
427
|
-
try r.val.mul(r.val, s);
|
|
428
|
-
}
|
|
429
|
-
|
|
430
|
-
/// Adds two rationals.
|
|
431
|
-
pub fn add(r: *BigRational, s: anytype) !void {
|
|
432
|
-
if (@hasField(@TypeOf(s.*), "val")) {
|
|
433
|
-
try r.val.add(r.val, s.val);
|
|
432
|
+
try doTurn(&u);
|
|
433
|
+
v = R{ .p = 4567216874, .q = 89124781931235 };
|
|
434
|
+
if (t == u64) {
|
|
435
|
+
try expectEqual(u.cmp(&v), error.Overflow);
|
|
434
436
|
} else {
|
|
435
|
-
|
|
436
|
-
defer t.deinit();
|
|
437
|
-
try t.setRatio(s.p, s.q);
|
|
438
|
-
try r.val.add(r.val, t);
|
|
437
|
+
try expectEqual(u.cmp(&v), .lt);
|
|
439
438
|
}
|
|
440
439
|
}
|
|
441
|
-
|
|
442
|
-
/// Multiplies two rationals.
|
|
443
|
-
pub fn mul(r: *BigRational, s: *const BigRational) !void {
|
|
444
|
-
try r.val.mul(r.val, s.val);
|
|
445
|
-
}
|
|
446
|
-
};
|
|
447
|
-
|
|
448
|
-
test BigRational {
|
|
449
|
-
var r = try BigRational.init(std.testing.allocator);
|
|
450
|
-
defer r.deinit();
|
|
451
|
-
var s = try std.math.big.Rational.init(std.testing.allocator);
|
|
452
|
-
defer s.deinit();
|
|
453
|
-
|
|
454
|
-
try r.reset();
|
|
455
|
-
|
|
456
|
-
var c: u8 = 128;
|
|
457
|
-
_ = &c;
|
|
458
|
-
|
|
459
|
-
try r.update(c, 256);
|
|
460
|
-
try doTurn(&r);
|
|
461
|
-
|
|
462
|
-
try s.setRatio(75383, 35550920704);
|
|
463
|
-
try expect((try s.order(r.val)) == .eq);
|
|
464
|
-
|
|
465
|
-
try r.update(1, 4);
|
|
466
|
-
try doTurn(&r);
|
|
467
|
-
|
|
468
|
-
try s.setRatio(5682596689, 2527735925804191711232);
|
|
469
|
-
try expect((try s.order(r.val)) == .eq);
|
|
470
|
-
|
|
471
|
-
try r.reset();
|
|
472
|
-
|
|
473
|
-
var t = try BigRational.init(std.testing.allocator);
|
|
474
|
-
defer t.deinit();
|
|
475
|
-
|
|
476
|
-
try t.val.setRatio(10, 13);
|
|
477
|
-
try r.mul(&t);
|
|
478
|
-
try t.val.setRatio(3, 4);
|
|
479
|
-
try r.mul(&t);
|
|
480
|
-
|
|
481
|
-
try s.setRatio(15, 26);
|
|
482
|
-
try expect((try s.order(r.val)) == .eq);
|
|
483
|
-
|
|
484
|
-
try t.val.setRatio(1, 3);
|
|
485
|
-
try r.add(&t);
|
|
486
|
-
|
|
487
|
-
try s.setRatio(71, 78);
|
|
488
|
-
try expect((try s.order(r.val)) == .eq);
|
|
489
|
-
}
|
|
490
|
-
|
|
491
|
-
test "minimum" {
|
|
492
|
-
// TODO: ziglang/zig#21069
|
|
493
|
-
if (builtin.mode == .ReleaseFast or builtin.mode == .ReleaseSmall) {
|
|
494
|
-
return error.SkipZigTest;
|
|
495
|
-
}
|
|
496
|
-
var r = try BigRational.init(std.testing.allocator);
|
|
497
|
-
defer r.deinit();
|
|
498
|
-
var s = try std.math.big.Rational.init(std.testing.allocator);
|
|
499
|
-
defer s.deinit();
|
|
500
|
-
|
|
501
|
-
try r.reset();
|
|
502
|
-
|
|
503
|
-
try r.update(1, 2); // Speed Tie
|
|
504
|
-
for (0..2) |_| {
|
|
505
|
-
try r.update(1, 2); // Confusion
|
|
506
|
-
try r.update(1, 2); // Infatuation
|
|
507
|
-
try r.update(3, 4); // Paralysis
|
|
508
|
-
// Population Bomb
|
|
509
|
-
for (0..10) |_| {
|
|
510
|
-
try r.update(9, 10); // Accuracy
|
|
511
|
-
try r.update(1, 15); // Damage roll
|
|
512
|
-
try r.update(1, 24); // Critical Hit
|
|
513
|
-
try r.update(9, 10); // King's Rock non-proc
|
|
514
|
-
}
|
|
515
|
-
}
|
|
516
|
-
|
|
517
|
-
const ZEROS = std.math.pow(u310, 10, 31);
|
|
518
|
-
const n = 36472996377170786403;
|
|
519
|
-
const d: u310 = 146267071761884981524886149560653378220687632500762654519853056 * ZEROS;
|
|
520
|
-
try s.setRatio(n, d);
|
|
521
|
-
try expect((try s.order(r.val)) == .eq);
|
|
522
440
|
}
|
package/src/lib/common/util.zig
CHANGED
|
@@ -3,11 +3,8 @@ const std = @import("std");
|
|
|
3
3
|
const expect = std.testing.expect;
|
|
4
4
|
const expectEqual = std.testing.expectEqual;
|
|
5
5
|
|
|
6
|
-
const Pointer = if (@hasField(std.builtin.Type, "pointer")) .pointer else .Pointer;
|
|
7
|
-
const One = if (@hasField(std.builtin.Type.Pointer.Size, "one")) .one else .One;
|
|
8
|
-
|
|
9
6
|
pub fn PointerType(comptime P: type, comptime C: type) type {
|
|
10
|
-
return if (@
|
|
7
|
+
return if (@typeInfo(P).pointer.is_const) *const C else *C;
|
|
11
8
|
}
|
|
12
9
|
|
|
13
10
|
test PointerType {
|
|
@@ -18,7 +15,7 @@ test PointerType {
|
|
|
18
15
|
pub fn isPointerTo(p: anytype, comptime P: type) bool {
|
|
19
16
|
const info = @typeInfo(@TypeOf(p));
|
|
20
17
|
return switch (info) {
|
|
21
|
-
|
|
18
|
+
.pointer => info.pointer.child == P,
|
|
22
19
|
else => false,
|
|
23
20
|
};
|
|
24
21
|
}
|
|
@@ -30,47 +27,18 @@ test isPointerTo {
|
|
|
30
27
|
try expect(isPointerTo(&s, S));
|
|
31
28
|
}
|
|
32
29
|
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
fn BytesAsValueReturnType(comptime T: type, comptime B: type) type {
|
|
39
|
-
return CopyPtrAttrs(B, One, T);
|
|
40
|
-
}
|
|
30
|
+
pub fn repeat(comptime xs: anytype, comptime n: usize) [xs.len * n]@TypeOf(xs[0]) {
|
|
31
|
+
comptime {
|
|
32
|
+
const T = @TypeOf(xs[0]);
|
|
33
|
+
var ts: [xs.len * n]T = undefined;
|
|
41
34
|
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
const args: std.builtin.Type.Pointer = if (@hasField(std.builtin.Type.Pointer, "sentinel")) .{
|
|
49
|
-
.size = size,
|
|
50
|
-
.is_const = info.is_const,
|
|
51
|
-
.is_volatile = info.is_volatile,
|
|
52
|
-
.is_allowzero = info.is_allowzero,
|
|
53
|
-
.alignment = info.alignment,
|
|
54
|
-
.address_space = info.address_space,
|
|
55
|
-
.child = child,
|
|
56
|
-
.sentinel = null,
|
|
57
|
-
} else .{
|
|
58
|
-
.size = size,
|
|
59
|
-
.is_const = info.is_const,
|
|
60
|
-
.is_volatile = info.is_volatile,
|
|
61
|
-
.is_allowzero = info.is_allowzero,
|
|
62
|
-
.alignment = info.alignment,
|
|
63
|
-
.address_space = info.address_space,
|
|
64
|
-
.child = child,
|
|
65
|
-
.sentinel_ptr = null,
|
|
66
|
-
};
|
|
67
|
-
return @Type(if (@hasField(std.builtin.Type, "pointer"))
|
|
68
|
-
.{ .pointer = args }
|
|
69
|
-
else
|
|
70
|
-
.{ .Pointer = args });
|
|
71
|
-
}
|
|
35
|
+
var i: usize = 0;
|
|
36
|
+
while (i < n) : (i += 1) {
|
|
37
|
+
for (xs, 0..) |v, j| {
|
|
38
|
+
ts[i * xs.len + j] = v;
|
|
39
|
+
}
|
|
40
|
+
}
|
|
72
41
|
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
return std.meta.fieldInfo(T, field).type;
|
|
42
|
+
return ts;
|
|
43
|
+
}
|
|
76
44
|
}
|