Skip to content

Commit aefe8f7

Browse files
committed
docs: add doc comment for DynamicModint
1 parent 749c4d8 commit aefe8f7

File tree

1 file changed

+59
-4
lines changed

1 file changed

+59
-4
lines changed

src/modint.zig

Lines changed: 59 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@ const assert = std.debug.assert;
77
/// # Constraints
88
///
99
/// - `m >= 1` (otherwise a compile error)
10-
///
1110
pub fn StaticModint(comptime m: comptime_int) type {
1211
if (m < 1) {
1312
@compileError("m must be greater than or equal to 1");
@@ -108,7 +107,7 @@ pub fn StaticModint(comptime m: comptime_int) type {
108107
};
109108
}
110109

111-
/// Returns `self / v (mod m)` (i.e. `self * inv(v)`).
110+
/// Returns `self / v (mod m)` (i.e., `self * inv(v)`).
112111
///
113112
/// # Panics
114113
///
@@ -181,40 +180,72 @@ pub fn StaticModint(comptime m: comptime_int) type {
181180
};
182181
}
183182

183+
/// Modint for `mod = 998244353`.
184184
pub const Modint998244353 = StaticModint(998244353);
185+
/// Modint for `mod = 1000000007`.
185186
pub const Modint1000000007 = StaticModint(1000000007);
186187

188+
/// Modular integer with a **runtime**-set modulus.
189+
///
190+
/// The modulus is shared across all values of the *same instantiation*
191+
/// `DynamicModint(id)`. Use different `id`s to keep separate global moduli.
187192
pub fn DynamicModint(id: comptime_int) type {
188193
return struct {
189194
const Self = @This();
190-
const _id = id;
195+
const _id = id; // disambiguates the type
191196

192-
val: u32,
197+
/// Shared Barrett reducer for this type instantiation.
193198
var bt = internal.Barrett.init(998244353);
194199

200+
/// Stored canonical representative in `[0, mod()-1]`.
201+
val: u32,
202+
203+
/// Returns the modulus.
195204
pub fn mod() u32 {
196205
return bt.umod();
197206
}
198207

208+
/// Sets the modulus for this type.
209+
/// It must be called first.
210+
///
211+
/// # Panics
212+
///
213+
/// Panics if `m == 0`.
199214
pub fn setMod(m: u32) void {
200215
if (m == 0) {
201216
@panic("the modulus must not be 0");
202217
}
203218
Self.bt = internal.Barrett.init(m);
204219
}
205220

221+
/// Constructs `DynamicModint` from a `v < m` without taking mod.
222+
/// It is the function for constant-factor speedup.
223+
///
224+
/// # Constraints
225+
///
226+
/// - `v` is less than `m`
227+
///
206228
pub fn raw(v: anytype) Self {
207229
return Self{
208230
.val = @intCast(v),
209231
};
210232
}
211233

234+
/// Returns the representative with casting to another integer `Type`.
235+
pub fn as(self: Self, Type: type) Type {
236+
return @intCast(self.val);
237+
}
238+
239+
/// Constructs a value reduced modulo `m`.
240+
/// Works for both signed and unsigned integers.
212241
pub fn init(v: anytype) Self {
213242
return Self{
214243
.val = takeMod(v),
215244
};
216245
}
217246

247+
/// Monoid sum over a slice, reduced mod `m`.
248+
/// Returns `Σ v[i] (mod m)`.
218249
pub fn sum(Type: type, v: []const Type) Self {
219250
var x = Self.init(0);
220251
for (v) |e| {
@@ -223,6 +254,8 @@ pub fn DynamicModint(id: comptime_int) type {
223254
return x;
224255
}
225256

257+
/// Monoid product over a slice, reduced mod `m`.
258+
/// Returns `∏ v[i] (mod m)`.
226259
pub fn product(Type: type, v: []const Type) Self {
227260
var x = Self.init(1);
228261
for (v) |e| {
@@ -231,6 +264,7 @@ pub fn DynamicModint(id: comptime_int) type {
231264
return x;
232265
}
233266

267+
/// `self + v (mod mod())`.
234268
pub inline fn add(self: Self, v: anytype) Self {
235269
const x = self.val + switch (@TypeOf(v)) {
236270
inline Self => v.val,
@@ -241,6 +275,7 @@ pub fn DynamicModint(id: comptime_int) type {
241275
};
242276
}
243277

278+
/// `self - v (mod mod())`.
244279
pub inline fn sub(self: Self, v: anytype) Self {
245280
const x = self.val -% switch (@TypeOf(v)) {
246281
inline Self => v.val,
@@ -251,6 +286,7 @@ pub fn DynamicModint(id: comptime_int) type {
251286
};
252287
}
253288

289+
/// `self * v (mod mod())` using Barrett reduction.
254290
pub inline fn mul(self: Self, v: anytype) Self {
255291
const x = bt.mul(self.val, switch (@TypeOf(v)) {
256292
inline Self => v.val,
@@ -261,6 +297,11 @@ pub fn DynamicModint(id: comptime_int) type {
261297
};
262298
}
263299

300+
/// `self / v (mod mod())` (i.e., `self * inv(v)`).
301+
///
302+
/// # Panics
303+
///
304+
/// Panics in debug if `v` is not invertible when `m` is composite.
264305
pub inline fn div(self: Self, v: anytype) Self {
265306
const x = switch (@TypeOf(v)) {
266307
inline Self => v.inv().val,
@@ -269,26 +310,32 @@ pub fn DynamicModint(id: comptime_int) type {
269310
return self.mul(x);
270311
}
271312

313+
/// In-place `+= v`.
272314
pub inline fn addAsg(self: *Self, v: anytype) void {
273315
self.val = self.add(v).val;
274316
}
275317

318+
/// In-place `-= v`.
276319
pub inline fn subAsg(self: *Self, v: anytype) void {
277320
self.val = self.sub(v).val;
278321
}
279322

323+
/// In-place `*= v`.
280324
pub inline fn mulAsg(self: *Self, v: anytype) void {
281325
self.val = self.mul(v).val;
282326
}
283327

328+
/// In-place `/= v`.
284329
pub inline fn divAsg(self: *Self, v: anytype) void {
285330
self.val = self.div(v).val;
286331
}
287332

333+
/// `-self (mod mod())`.
288334
pub inline fn negate(self: Self) Self {
289335
return Self.raw(0).sub(self.val);
290336
}
291337

338+
/// Returns `self` to the power of `n`.
292339
pub inline fn pow(self: Self, n: anytype) Self {
293340
assert(0 <= n);
294341
var x = self;
@@ -303,6 +350,11 @@ pub fn DynamicModint(id: comptime_int) type {
303350
return r;
304351
}
305352

353+
/// Retruns the multiplicative inverse of `self`.
354+
///
355+
/// # Panics
356+
///
357+
/// Panics if the multiplicative inverse does not exist.
306358
pub inline fn inv(self: Self) Self {
307359
const g, const x = internal.invGcd(self.val, mod());
308360
assert(g == 1);
@@ -311,13 +363,16 @@ pub fn DynamicModint(id: comptime_int) type {
311363
};
312364
}
313365

366+
/// Reduce `v` modulo current `mod()` to a canonical `u32` in `[0, mod()-1]`.
314367
fn takeMod(v: anytype) u32 {
315368
const m: i64 = @intCast(bt.umod());
316369
return @intCast(@mod(v, m));
317370
}
318371
};
319372
}
320373

374+
/// Alias handy for dynamic-mod situations where the `id` value is irrelevant.
375+
/// You will usually want your own `id` to keep moduli separate across modules.
321376
pub const Modint = DynamicModint(-1);
322377

323378
const testing = std.testing;

0 commit comments

Comments
 (0)