devela/num/int/num_trait/
impls.rs

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
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
// devela::num::int::num_trait::impls
//
//! Implementations of `NumInt` for primitives.
//

#[cfg(feature = "_int_usize")]
use crate::isize_up;
#[allow(unused_imports)]
use crate::GcdReturn;
#[cfg(feature = "alloc")]
use crate::Vec;
use crate::{Int, NumInt, NumResult as Result, ValueQuant};

/// $t:     the primitive type
/// $cap:   the capability feature that enables the given implementation. E.g "_int_i8".
///
/// $ut:    the unsigned type of the same size as $t, only for signed (used for midpoint).
/// $ucap:  the feature that enables some methods related to `$ut`. E.g "_int_i8". (only for signed)
///
/// $io:    the signed output primitive type (upcasted for unsigned, same as $t for signed).
/// $iocap: the capability feature that enables some ops with signed output primitive type.
///         also corresponds to $iup in impl_modulo, for example.
macro_rules! impl_int {
    () => {
        impl_int![signed
            i8:"_int_i8"|u8:"_int_u8",
            i16:"_int_i16"|u16:"_int_u16",
            i32:"_int_i32"|u32:"_int_u32",
            i64:"_int_i64"|u64:"_int_u64",
            i128:"_int_i128"|u128:"_int_u128",
            isize:"_int_isize"|usize:"_int_usize"
        ];
        impl_int![unsigned
            u8:"_int_u8"|i16:"_int_i16",
            u16:"_int_u16"|i32:"_int_i32",
            u32:"_int_u32"|i64:"_int_i64",
            u64:"_int_u64"|i128:"_int_i128",
            u128:"_int_u128"|i128:"_int_i128"
        ];
        #[cfg(target_pointer_width = "32")]
        impl_int![unsigned usize:"_int_usize"|isize_up:"_int_i64"];
        #[cfg(target_pointer_width = "64")]
        impl_int![unsigned usize:"_int_usize"|isize_up:"_int_i128"];
    };

    // Implements `NumInt` for signed integer types
    // --------------------------------------------------------------------------------------------
    (signed $($t:ident : $cap:literal | $ut:ident : $ucap:literal),+) => {
        $( impl_int![@signed $t:$cap | $ut:$ucap]; )+
    };
    (@signed $t:ident : $cap:literal | $ut:ident:$ucap:literal) => { $crate::paste! {
        #[cfg(feature = $cap )]
        #[cfg_attr(feature = "nightly_doc", doc(cfg(feature = $cap)))]
        impl NumInt for $t {
            type OutI = $t;

            impl_int![common_body_iu];

            /* core */

            fn int_gcd_ext(self, other: Self::Rhs)
                -> Result<GcdReturn<Self::Out, Self::OutI>> {
                match Int(self).gcd_ext(other) {
                    GcdReturn { gcd, x, y } => Ok(GcdReturn { gcd: gcd.0, x: x.0, y: y.0 }) }}
            fn int_ref_gcd_ext(&self, other: &Self::Rhs)
                -> Result<GcdReturn<Self::Out, Self::OutI>> {
                match Int(*self).gcd_ext(*other) {
                    GcdReturn { gcd, x, y } => Ok(GcdReturn { gcd: gcd.0, x: x.0, y: y.0 }) }}

            #[cfg(feature = $ucap )]
            #[cfg_attr(feature = "nightly_doc", doc(cfg(feature = $ucap)))]
            fn int_midpoint(self, other: Self::Rhs) -> Result<Self::Out> {
                Ok(Int(self).midpoint(other).0) }
            #[cfg(feature = $ucap )]
            #[cfg_attr(feature = "nightly_doc", doc(cfg(feature = $ucap)))]
            fn int_ref_midpoint(&self, other: &Self::Rhs) -> Result<Self::Out> {
                Ok(Int(*self).midpoint(*other).0) }

            /* modulo */

            fn int_modulo_mul_inv(self, modulus: Self) -> Result<Self> {
                Int(self).modulo_mul_inv(modulus).map(|n|n.0) }
            fn int_ref_modulo_mul_inv(&self, modulus: &Self) -> Result<Self> {
                Int(*self).modulo_mul_inv(*modulus).map(|n|n.0) }

            fn int_modulo_div(self, other: Self, modulus: Self) -> Result<Self> {
                Int(self).modulo_div(other, modulus).map(|n|n.0) }
            fn int_ref_modulo_div(&self, other: &Self, modulus: &Self) -> Result<Self> {
                Int(*self).modulo_div(*other, *modulus).map(|n|n.0) }

            /* sqrt roots */

            fn int_sqrt_ceil(self) -> Result<Self::Out> {
                Int(self).sqrt_ceil().map(|n|n.0) }
            fn int_ref_sqrt_ceil(&self) -> Result<Self::Out> {
                Int(*self).sqrt_ceil().map(|n|n.0) }

            fn int_sqrt_floor(self) -> Result<Self::Out> {
                Int(self).sqrt_floor().map(|n|n.0) }
            fn int_ref_sqrt_floor(&self) -> Result<Self::Out> {
                Int(*self).sqrt_floor().map(|n|n.0) }

            fn int_sqrt_round(self) -> Result<Self::Out> {
                Int(self).sqrt_round().map(|n|n.0) }
            fn int_ref_sqrt_round(&self) -> Result<Self::Out> {
                Int(*self).sqrt_round().map(|n|n.0) }
        }
    }};

    // Implements `Num` for unsigned integer types
    // --------------------------------------------------------------------------------------------
    (unsigned $($t:ident : $cap:literal | $io:ident : $iocap:literal),+) => {
        $( impl_int![@unsigned $t:$cap | $io:$iocap]; )+
    };
    (@unsigned $t:ident : $cap:literal | $io:ident : $iocap:literal) => { $crate::paste! {
        #[cfg(feature = $cap )]
        #[cfg_attr(feature = "nightly_doc", doc(cfg(feature = $cap)))]
        impl NumInt for $t {
            type OutI = $io;

            impl_int![common_body_iu];

            /* core */

            #[cfg(all(feature = $iocap, feature = "cast"))]
            #[cfg_attr(feature = "nightly_doc", doc(cfg(all(feature = $iocap, feature = "cast"))))]
            fn int_gcd_ext(self, other: Self::Rhs)
                -> Result<GcdReturn<Self::Out, Self::OutI>> {
                Int(self).gcd_ext(other)
                    .map(|res| GcdReturn { gcd: res.gcd.0, x: res.x.0, y: res.y.0 }) }
            #[cfg(all(feature = $iocap, feature = "cast"))]
            #[cfg_attr(feature = "nightly_doc", doc(cfg(all(feature = $iocap, feature = "cast"))))]
            fn int_ref_gcd_ext(&self, other: &Self::Rhs)
                -> Result<GcdReturn<Self::Out, Self::OutI>> {
                Int(*self).gcd_ext(*other)
                    .map(|res| GcdReturn { gcd: res.gcd.0, x: res.x.0, y: res.y.0 }) }

            fn int_midpoint(self, other: Self::Rhs) -> Result<Self::Out> {
                Ok(Int(self).midpoint(other).0) }
            fn int_ref_midpoint(&self, other: &Self::Rhs) -> Result<Self::Out> {
                Ok(Int(*self).midpoint(*other).0) }

            /* modulo */

            #[cfg(all(feature = $iocap, feature = "cast"))]
            #[cfg_attr(feature = "nightly_doc", doc(cfg(all(feature = $iocap, feature = "cast"))))]
            fn int_modulo_mul_inv(self, modulus: Self) -> Result<Self> {
                Int(self).modulo_mul_inv(modulus).map(|n|n.0) }
            #[cfg(all(feature = $iocap, feature = "cast"))]
            #[cfg_attr(feature = "nightly_doc", doc(cfg(all(feature = $iocap, feature = "cast"))))]
            fn int_ref_modulo_mul_inv(&self, modulus: &Self) -> Result<Self> {
                Int(*self).modulo_mul_inv(*modulus).map(|n|n.0) }

            #[cfg(all(feature = $iocap, feature = "cast"))]
            #[cfg_attr(feature = "nightly_doc", doc(cfg(all(feature = $iocap, feature = "cast"))))]
            fn int_modulo_div(self, other: Self, modulus: Self) -> Result<Self> {
                Int(self).modulo_div(other, modulus).map(|n|n.0) }
            #[cfg(all(feature = $iocap, feature = "cast"))]
            #[cfg_attr(feature = "nightly_doc", doc(cfg(all(feature = $iocap, feature = "cast"))))]
            fn int_ref_modulo_div(&self, other: &Self, modulus: &Self) -> Result<Self> {
                Int(*self).modulo_div(*other, *modulus).map(|n|n.0) }

            /* sqrt roots */

            fn int_sqrt_ceil(self) -> Result<Self::Out> {
                Ok(Int(self).sqrt_ceil().0) }
            fn int_ref_sqrt_ceil(&self) -> Result<Self::Out> {
                Ok(Int(*self).sqrt_ceil().0) }

            fn int_sqrt_floor(self) -> Result<Self::Out> {
                Ok(Int(self).sqrt_floor().0) }
            fn int_ref_sqrt_floor(&self) -> Result<Self::Out> {
                Ok(Int(*self).sqrt_floor().0) }

            fn int_sqrt_round(self) -> Result<Self::Out> {
                Int(self).sqrt_round().map(|n|n.0) }
            fn int_ref_sqrt_round(&self) -> Result<Self::Out> {
                Int(*self).sqrt_round().map(|n|n.0) }
        }
    }};

    // Inner helpers for repeated common bodies for signed and unsigned
    // ============================================================================================
    (common_body_iu) => {
        /* base */

        fn int_digital_root(self) -> Result<Self::Out> {
            Ok(Int(self).digital_root().0) }
        fn int_ref_digital_root(&self) -> Result<Self::Out> {
            Ok(Int(*self).digital_root().0) }
        fn int_digital_root_base(self, base: Self::Rhs) -> Result<Self::Out> {
            Ok(Int(self).digital_root_base(base).0) }
        fn int_ref_digital_root_base(&self, base: &Self::Rhs) -> Result<Self::Out> {
            Ok(Int(*self).digital_root_base(*base).0) }

        fn int_digits(self) -> Result<Self::Out> {
            Ok(Int(self).digits().0) }
        fn int_ref_digits(&self) -> Result<Self::Out> {
            Ok(Int(*self).digits().0) }
        fn int_digits_sign(self) -> Result<Self::Out> {
            Ok(Int(self).digits_sign().0) }
        fn int_ref_digits_sign(&self) -> Result<Self::Out> {
            Ok(Int(*self).digits_sign().0) }
        fn int_digits_base(self, base: Self::Rhs) -> Result<Self::Out> {
            Ok(Int(self).digits_base(base).0) }
        fn int_ref_digits_base(&self, base: &Self::Rhs) -> Result<Self::Out> {
            Ok(Int(*self).digits_base(*base).0) }
        fn int_digits_base_sign(self, base: Self::Rhs) -> Result<Self::Out> {
            Ok(Int(self).digits_base_sign(base).0) }
        fn int_ref_digits_base_sign(&self, base: &Self::Rhs) -> Result<Self::Out> {
            Ok(Int(*self).digits_base_sign(*base).0) }

        /* core */

        fn int_abs(self) -> Result<Self::Out> { Ok(Int(self).abs().0) }
        fn int_ref_abs(&self) -> Result<Self::Out> { Ok(Int(*self).abs().0) }

        fn int_is_even(self) -> Result<bool> { Ok(Int(self).is_even()) }
        fn int_ref_is_even(&self) -> Result<bool> { Ok(Int(*self).is_even()) }
        fn int_is_odd(self) -> Result<bool> { Ok(Int(self).is_odd()) }
        fn int_ref_is_odd(&self) -> Result<bool> { Ok(Int(*self).is_odd()) }

        fn int_gcd(self, other: Self::Rhs) -> Result<Self::Out> {
            Ok(Int(self).gcd(other).0) }
        fn int_ref_gcd(&self, other: &Self::Rhs) -> Result<Self::Out> {
            Ok(Int(*self).gcd(*other).0) }
        // NOTE: the rest are sign-specific

        fn int_lcm(self, other: Self::Rhs) -> Result<Self::Out> {
            match Int(self).lcm(other) { Ok(res) => Ok(res.0), Err(e) => Err(e) } }
        fn int_ref_lcm(&self, other: &Self::Rhs) -> Result<Self::Out> {
            match Int(*self).lcm(*other) { Ok(res) => Ok(res.0), Err(e) => Err(e) } }

        #[cfg(feature = "cast")]
        #[cfg_attr(feature = "nightly_doc", doc(cfg(feature = "cast")))]
        fn int_scale(self, min: Self::Rhs, max: Self::Rhs, a: Self::Rhs, b: Self::Rhs)
            -> Result<Self::Out> where Self: Sized { Int(self).scale(min, max, a, b).map(|n|n.0) }
        #[cfg(feature = "cast")]
        #[cfg_attr(feature = "nightly_doc", doc(cfg(feature = "cast")))]
        fn int_ref_scale(&self, min: &Self::Rhs, max: &Self::Rhs, a: &Self::Rhs, b: &Self::Rhs)
            -> Result<Self::Out> { Int(*self).scale(*min, *max, *a, *b).map(|n|n.0) }

        fn int_scale_wrap(self, min: Self::Rhs, max: Self::Rhs, a: Self::Rhs, b: Self::Rhs)
            -> Result<Self::Out> where Self: Sized { Ok(Int(self).scale_wrap(min, max, a, b).0) }
        fn int_ref_scale_wrap(&self, min: &Self::Rhs, max: &Self::Rhs, a: &Self::Rhs, b: &Self::Rhs)
            -> Result<Self::Out> { Ok(Int(*self).scale_wrap(*min, *max, *a, *b).0) }

        /* combinatorics */

        fn int_factorial(self) -> Result<Self::Out> {
            Int(self).factorial().map(|n|n.0) }
        fn int_ref_factorial(&self) -> Result<Self::Out> {
            Int(*self).factorial().map(|n|n.0) }
        fn int_subfactorial(self) -> Result<Self::Out> {
            Int(self).subfactorial().map(|n|n.0) }
        fn int_ref_subfactorial(&self) -> Result<Self::Out> {
            Int(*self).subfactorial().map(|n|n.0) }

        fn int_permute(self, r: Self) -> Result<Self::Out> {
            Int(self).permute(r).map(|n|n.0) }
        fn int_ref_permute(&self, r: &Self) -> Result<Self::Out> {
            Int(*self).permute(*r).map(|n|n.0) }
        #[cfg(feature = "cast")]
        #[cfg_attr(feature = "nightly_doc", doc(cfg(feature = "cast")))]
        fn int_permute_rep(self, r: Self) -> Result<Self::Out> {
            Int(self).permute_rep(r).map(|n|n.0) }
        #[cfg(feature = "cast")]
        #[cfg_attr(feature = "nightly_doc", doc(cfg(feature = "cast")))]
        fn int_ref_permute_rep(&self, r: &Self) -> Result<Self::Out> {
            Int(*self).permute_rep(*r).map(|n|n.0) }

        fn int_combine(self, r: Self) -> Result<Self::Out> {
            Int(self).combine(r).map(|n|n.0) }
        fn int_ref_combine(&self, r: &Self) -> Result<Self::Out> {
            Int(*self).combine(*r).map(|n|n.0) }
        fn int_combine_rep(self, r: Self) -> Result<Self::Out> {
            Int(self).combine_rep(r).map(|n|n.0) }
        fn int_ref_combine_rep(&self, r: &Self) -> Result<Self::Out> {
            Int(*self).combine_rep(*r).map(|n|n.0) }

        /* division */

        fn int_div_rem(self, b: Self::Rhs) -> Result<[Self::Out; 2]> {
            let [d, r] = Int(self).div_rem(b); Ok([d.0, r.0]) }
        fn int_div_ceil(self, b: Self) -> Result<Self::Out> {
            Ok(Int(self).div_ceil(b).0) }
        fn int_div_floor(self, b: Self) -> Result<Self::Out> {
            Ok(Int(self).div_floor(b).0) }
        fn int_div_ties_away(self, b: Self) -> Result<Self::Out> {
            Ok(Int(self).div_ties_away(b).0) }
        fn int_div_ties_towards(self, b: Self) -> Result<Self::Out> {
            Ok(Int(self).div_ties_towards(b).0) }
        fn int_div_ties_even(self, b: Self) -> Result<Self::Out> {
            Ok(Int(self).div_ties_even(b).0) }
        fn int_div_ties_odd(self, b: Self) -> Result<Self::Out> {
            Ok(Int(self).div_ties_odd(b).0) }

        /* factors (allocating) */

        #[cfg(feature = "alloc")]
        #[cfg_attr(feature = "nightly_doc", doc(cfg(feature = "alloc")))]
        fn int_factors(self) -> Result<Vec<Self::Out>> { Ok(Int(self).factors()) }
        #[cfg(feature = "alloc")]
        #[cfg_attr(feature = "nightly_doc", doc(cfg(feature = "alloc")))]
        fn int_ref_factors(&self) -> Result<Vec<Self::Out>> { Ok(Int(*self).factors()) }
        #[cfg(feature = "alloc")]
        #[cfg_attr(feature = "nightly_doc", doc(cfg(feature = "alloc")))]
        fn int_factors_proper(self) -> Result<Vec<Self::Out>> { Ok(Int(self).factors_proper()) }
        #[cfg(feature = "alloc")]
        #[cfg_attr(feature = "nightly_doc", doc(cfg(feature = "alloc")))]
        fn int_ref_factors_proper(&self) -> Result<Vec<Self::Out>> {
            Ok(Int(*self).factors_proper()) }
        #[cfg(feature = "alloc")]
        #[cfg_attr(feature = "nightly_doc", doc(cfg(feature = "alloc")))]
        fn int_factors_prime(self) -> Result<Vec<Self::Out>> { Ok(Int(self).factors_prime()) }
        #[cfg(feature = "alloc")]
        #[cfg_attr(feature = "nightly_doc", doc(cfg(feature = "alloc")))]
        fn int_ref_factors_prime(&self) -> Result<Vec<Self::Out>> {
            Ok(Int(*self).factors_prime()) }
        #[cfg(feature = "alloc")]
        #[cfg_attr(feature = "nightly_doc", doc(cfg(feature = "alloc")))]
        fn int_factors_prime_unique(self) -> Result<Vec<Self::Out>> {
            Ok(Int(self).factors_prime_unique()) }
        #[cfg(feature = "alloc")]
        #[cfg_attr(feature = "nightly_doc", doc(cfg(feature = "alloc")))]
        fn int_ref_factors_prime_unique(&self) -> Result<Vec<Self::Out>> {
            Ok(Int(*self).factors_prime_unique()) }

        /* factors (non-allocating) */

        fn int_factors_buf(self, fbuf: &mut [Self::Out], upfbuf: &mut [Self::Out])
            -> Result<(usize, usize)> { Int(self).factors_buf(fbuf, upfbuf) }
        fn int_ref_factors_buf(&self, fbuf: &mut [Self::Out], upfbuf: &mut [Self::Out])
            -> Result<(usize, usize)> { Int(*self).factors_buf(fbuf, upfbuf) }

        fn int_factors_proper_buf(self, fbuf: &mut [Self], upfbuf: &mut [Self])
            -> Result<(usize, usize)> { Int(self).factors_proper_buf(fbuf, upfbuf) }
        fn int_ref_factors_proper_buf(&self, fbuf: &mut [Self::Out], upfbuf: &mut [Self::Out])
            -> Result<(usize, usize)> { Int(*self).factors_proper_buf(fbuf, upfbuf) }

        fn int_factors_prime_buf(self, buffer: &mut [Self])
            -> Result<usize> { Int(self).factors_prime_buf(buffer) }
        fn int_ref_factors_prime_buf(&self, buffer: &mut [Self::Out])
         -> Result<usize> { Int(*self).factors_prime_buf(buffer) }

        fn int_factors_prime_unique_buf(self, buffer: &mut [Self])
            -> Result<usize> { Int(self).factors_prime_unique_buf(buffer) }
        fn int_ref_factors_prime_unique_buf(&self, buffer: &mut [Self::Out])
         -> Result<usize> { Int(*self).factors_prime_unique_buf(buffer) }

        /* modulo */

        fn int_modulo(self, modulus: Self) -> Result<Self> {
            Int(self).modulo(modulus).map(|n|n.0) }
        fn int_ref_modulo(&self, modulus: &Self) -> Result<Self> {
            Int(*self).modulo(*modulus).map(|n|n.0) }

        fn int_modulo_add(self, other: Self, modulus: Self) -> Result<Self> {
            Int(self).modulo_add(other, modulus).map(|n|n.0) }
        fn int_ref_modulo_add(&self, other: &Self, modulus: &Self) -> Result<Self> {
            Int(*self).modulo_add(*other, *modulus).map(|n|n.0) }
        fn int_modulo_add_cycles(self, other: Self, modulus: Self)
            -> Result<ValueQuant<Self, Self>> {
            Int(self).modulo_add_cycles(other, modulus)
                .map(|res| ValueQuant { v: res.v.0, q: res.q.0 }) }
        fn int_ref_modulo_add_cycles(&self, other: &Self, modulus: &Self)
            -> Result<ValueQuant<Self, Self>> {
            Int(*self).modulo_add_cycles(*other, *modulus)
                .map(|res| ValueQuant { v: res.v.0, q: res.q.0 }) }
        fn int_modulo_add_inv(self, modulus: Self) -> Result<Self> {
            Int(self).modulo_add_inv(modulus).map(|n|n.0) }
        fn int_ref_modulo_add_inv(&self, modulus: &Self) -> Result<Self> {
            Int(*self).modulo_add_inv(*modulus).map(|n|n.0) }

        fn int_modulo_sub(self, other: Self, modulus: Self) -> Result<Self> {
            Int(self).modulo_sub(other, modulus).map(|n|n.0) }
        fn int_ref_modulo_sub(&self, other: &Self, modulus: &Self) -> Result<Self> {
            Int(*self).modulo_sub(*other, *modulus).map(|n|n.0) }
        fn int_modulo_sub_cycles(self, other: Self, modulus: Self)
            -> Result<ValueQuant<Self, Self>> {
            Int(self).modulo_sub_cycles(other, modulus)
                .map(|res| ValueQuant { v: res.v.0, q: res.q.0 }) }
        fn int_ref_modulo_sub_cycles(&self, other: &Self, modulus: &Self)
            -> Result<ValueQuant<Self, Self>> {
            Int(*self).modulo_sub_cycles(*other, *modulus)
                .map(|res| ValueQuant { v: res.v.0, q: res.q.0 }) }

        fn int_modulo_mul(self, other: Self, modulus: Self) -> Result<Self> {
            Int(self).modulo_mul(other, modulus).map(|n|n.0) }
        fn int_ref_modulo_mul(&self, other: &Self, modulus: &Self) -> Result<Self> {
            Int(*self).modulo_mul(*other, *modulus).map(|n|n.0) }
        fn int_modulo_mul_cycles(self, other: Self, modulus: Self)
            -> Result<ValueQuant<Self, Self>> {
            Int(self).modulo_mul_cycles(other, modulus)
                .map(|res| ValueQuant { v: res.v.0, q: res.q.0 }) }
        fn int_ref_modulo_mul_cycles(&self, other: &Self, modulus: &Self)
            -> Result<ValueQuant<Self, Self>> {
            Int(*self).modulo_mul_cycles(*other, *modulus)
                .map(|res| ValueQuant { v: res.v.0, q: res.q.0 }) }

        /* primes */

        fn int_is_prime(self) -> Result<bool> { Ok(Int(self).is_prime()) }
        fn int_ref_is_prime(&self) -> Result<bool> { Ok(Int(*self).is_prime()) }

        fn int_prime_nth(self) -> Result<Self::Out> { Int(self).prime_nth().map(|n|n.0) }
        fn int_ref_prime_nth(&self) -> Result<Self::Out> { Int(*self).prime_nth().map(|n|n.0) }

        fn int_prime_pi(self) -> Result<usize> { Ok(Int(self).prime_pi()) }
        fn int_ref_prime_pi(&self) -> Result<usize> { Ok(Int(*self).prime_pi()) }

        fn int_totient(self) -> Result<Self::Out> { Ok(Int(self).totient().0) }
        fn int_ref_totient(&self) -> Result<Self::Out> { Ok(Int(*self).totient().0) }

        /* sqrt roots */

        fn int_is_square(self) -> Result<bool> { Ok(Int(self).is_square()) }
        fn int_ref_is_square(&self) -> Result<bool> { Ok(Int(*self).is_square()) }
        // NOTE: the rest are sign-specific

        /* roots */

        fn int_root_ceil(self, nth: u32) -> Result<Self::Out> {
            Int(self).root_ceil(nth).map(|n|n.0) }
        fn int_ref_root_ceil(&self, nth: u32) -> Result<Self::Out> {
            Int(*self).root_ceil(nth).map(|n|n.0) }

        fn int_root_floor(self, nth: u32) -> Result<Self::Out> {
            Int(self).root_floor(nth).map(|n|n.0) }
        fn int_ref_root_floor(&self, nth: u32) -> Result<Self::Out> {
            Int(*self).root_floor(nth).map(|n|n.0) }
    };
}
impl_int!();