• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

kaidokert / fixed-bigint-rs / Ab2lBEvLbiheB4tmBVqE7QPaHqsqRG8la

12 Feb 2025 07:34AM UTC coverage: 83.686% (+1.9%) from 81.766%
Ab2lBEvLbiheB4tmBVqE7QPaHqsqRG8la

push

github

web-flow
More complete ops coverage (#42)

80 of 107 new or added lines in 3 files covered. (74.77%)

51 existing lines in 3 files now uncovered.

672 of 803 relevant lines covered (83.69%)

13.69 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

96.85
/src/fixeduint/bit_ops_impl.rs
1
use super::{FixedUInt, MachineWord};
2

3
use crate::patch_num_traits::{OverflowingShl, OverflowingShr};
4

5
use num_traits::Zero;
6

7
impl<T: MachineWord, const N: usize> core::ops::Not for FixedUInt<T, N> {
8
    type Output = Self;
9
    fn not(self) -> <Self as core::ops::Not>::Output {
3✔
10
        let mut ret = Self::zero();
3✔
11
        for i in 0..N {
9✔
12
            ret.array[i] = !self.array[i]
3✔
13
        }
14
        ret
3✔
15
    }
16
}
17

18
impl<T: MachineWord, const N: usize> core::ops::BitAnd<&FixedUInt<T, N>> for &FixedUInt<T, N> {
19
    type Output = FixedUInt<T, N>;
20
    fn bitand(self, other: &FixedUInt<T, N>) -> Self::Output {
10✔
21
        let mut ret = Self::Output::zero();
10✔
22
        for i in 0..N {
30✔
23
            ret.array[i] = self.array[i] & other.array[i]
10✔
24
        }
25
        ret
10✔
26
    }
27
}
28

29
impl<T: MachineWord, const N: usize> core::ops::BitAnd for FixedUInt<T, N> {
30
    type Output = Self;
31
    fn bitand(self, other: Self) -> Self::Output {
10✔
32
        (&self).bitand(&other)
10✔
33
    }
34
}
35

36
impl<T: MachineWord, const N: usize> core::ops::BitAnd<&FixedUInt<T, N>> for FixedUInt<T, N> {
37
    type Output = Self;
38
    fn bitand(self, other: &FixedUInt<T, N>) -> Self::Output {
1✔
39
        (&self).bitand(other)
1✔
40
    }
41
}
42

43
impl<T: MachineWord, const N: usize> core::ops::BitAnd<FixedUInt<T, N>> for &FixedUInt<T, N> {
44
    type Output = FixedUInt<T, N>;
45
    fn bitand(self, other: FixedUInt<T, N>) -> Self::Output {
1✔
46
        self.bitand(&other)
1✔
47
    }
48
}
49

50
impl<T: MachineWord, const N: usize> core::ops::BitAndAssign for FixedUInt<T, N> {
51
    fn bitand_assign(&mut self, other: Self) {
6✔
52
        for i in 0..N {
12✔
53
            self.array[i] &= other.array[i]
6✔
54
        }
55
    }
56
}
57

58
impl<T: MachineWord, const N: usize> core::ops::BitOr<&FixedUInt<T, N>> for &FixedUInt<T, N> {
59
    type Output = FixedUInt<T, N>;
60
    fn bitor(self, other: &FixedUInt<T, N>) -> Self::Output {
13✔
61
        let mut ret = Self::Output::zero();
13✔
62
        for i in 0..N {
39✔
63
            ret.array[i] = self.array[i] | other.array[i]
13✔
64
        }
65
        ret
13✔
66
    }
67
}
68

69
impl<T: MachineWord, const N: usize> core::ops::BitOr for FixedUInt<T, N> {
70
    type Output = Self;
71
    fn bitor(self, other: Self) -> Self::Output {
13✔
72
        (&self).bitor(&other)
13✔
73
    }
74
}
75

76
impl<T: MachineWord, const N: usize> core::ops::BitOr<&FixedUInt<T, N>> for FixedUInt<T, N> {
77
    type Output = Self;
78
    fn bitor(self, other: &FixedUInt<T, N>) -> Self::Output {
1✔
79
        (&self).bitor(other)
1✔
80
    }
81
}
82

83
impl<T: MachineWord, const N: usize> core::ops::BitOr<FixedUInt<T, N>> for &FixedUInt<T, N> {
84
    type Output = FixedUInt<T, N>;
85
    fn bitor(self, other: FixedUInt<T, N>) -> Self::Output {
1✔
86
        self.bitor(&other)
1✔
87
    }
88
}
89

90
impl<T: MachineWord, const N: usize> core::ops::BitOrAssign for FixedUInt<T, N> {
91
    fn bitor_assign(&mut self, other: Self) {
24✔
92
        for i in 0..N {
50✔
93
            self.array[i] |= other.array[i]
26✔
94
        }
95
    }
96
}
97

98
impl<T: MachineWord, const N: usize> core::ops::BitXor<&FixedUInt<T, N>> for &FixedUInt<T, N> {
99
    type Output = FixedUInt<T, N>;
100
    fn bitxor(self, other: &FixedUInt<T, N>) -> Self::Output {
7✔
101
        let mut ret = Self::Output::zero();
7✔
102
        for i in 0..N {
21✔
103
            ret.array[i] = self.array[i] ^ other.array[i]
7✔
104
        }
105
        ret
7✔
106
    }
107
}
108

109
impl<T: MachineWord, const N: usize> core::ops::BitXor for FixedUInt<T, N> {
110
    type Output = Self;
111
    fn bitxor(self, other: Self) -> Self::Output {
7✔
112
        (&self).bitxor(&other)
7✔
113
    }
114
}
115

116
impl<T: MachineWord, const N: usize> core::ops::BitXor<&FixedUInt<T, N>> for FixedUInt<T, N> {
117
    type Output = Self;
118
    fn bitxor(self, other: &FixedUInt<T, N>) -> Self::Output {
1✔
119
        (&self).bitxor(other)
1✔
120
    }
121
}
122

123
impl<T: MachineWord, const N: usize> core::ops::BitXor<FixedUInt<T, N>> for &FixedUInt<T, N> {
124
    type Output = FixedUInt<T, N>;
125
    fn bitxor(self, other: FixedUInt<T, N>) -> Self::Output {
1✔
126
        self.bitxor(&other)
1✔
127
    }
128
}
129

130
impl<T: MachineWord, const N: usize> core::ops::BitXorAssign for FixedUInt<T, N> {
131
    fn bitxor_assign(&mut self, other: Self) {
6✔
132
        for i in 0..N {
12✔
133
            self.array[i] ^= other.array[i]
6✔
134
        }
135
    }
136
}
137

138
impl<T: MachineWord, const N: usize> OverflowingShl for FixedUInt<T, N> {
139
    fn overflowing_shl(self, bits: u32) -> (Self, bool) {
6✔
140
        let bitsu = bits as usize;
6✔
141
        let (shift, overflow) = if bitsu >= Self::BIT_SIZE {
18✔
142
            (bitsu & (Self::BIT_SIZE - 1), true)
6✔
143
        } else {
144
            (bitsu, false)
6✔
145
        };
146
        let res = core::ops::Shl::<usize>::shl(self, shift);
6✔
147
        (res, overflow)
6✔
148
    }
149
}
150

151
impl<T: MachineWord, const N: usize> core::ops::Shl<u32> for FixedUInt<T, N> {
152
    type Output = Self;
153
    fn shl(self, bits: u32) -> <Self as core::ops::Shl<u32>>::Output {
10✔
154
        core::ops::Shl::<usize>::shl(self, bits as usize)
10✔
155
    }
156
}
157

158
impl<T: MachineWord, const N: usize> core::ops::Shl<usize> for FixedUInt<T, N> {
159
    type Output = Self;
160
    fn shl(self, bits: usize) -> <Self as core::ops::Shl<usize>>::Output {
10✔
161
        // This copy can be avoided
162
        let mut result = self;
10✔
163
        Self::shl_impl(&mut result, bits);
10✔
164
        result
12✔
165
    }
166
}
167

168
impl<T: MachineWord, const N: usize> core::ops::Shl<&'_ usize> for FixedUInt<T, N> {
169
    type Output = Self;
170
    fn shl(self, bits: &usize) -> <Self as core::ops::Shl<usize>>::Output {
1✔
171
        let mut result = self;
1✔
172
        Self::shl_impl(&mut result, *bits);
1✔
173
        result
1✔
174
    }
175
}
176

177
impl<T: MachineWord, const N: usize> num_traits::WrappingShl for FixedUInt<T, N> {
178
    fn wrapping_shl(&self, bits: u32) -> Self {
6✔
179
        self.overflowing_shl(bits).0
6✔
180
    }
181
}
182

183
impl<T: MachineWord, const N: usize> num_traits::CheckedShl for FixedUInt<T, N> {
184
    fn checked_shl(&self, bits: u32) -> Option<Self> {
6✔
185
        let res = self.overflowing_shl(bits);
6✔
186
        if res.1 {
12✔
187
            None
6✔
188
        } else {
189
            Some(res.0)
6✔
190
        }
191
    }
192
}
193

194
// SaturatingShl doesn't exist
195

196
impl<T: MachineWord, const N: usize> core::ops::ShlAssign<usize> for FixedUInt<T, N> {
197
    fn shl_assign(&mut self, bits: usize) {
21✔
198
        Self::shl_impl(self, bits);
21✔
199
    }
200
}
201

202
impl<T: MachineWord, const N: usize> core::ops::ShlAssign<&'_ usize> for FixedUInt<T, N> {
UNCOV
203
    fn shl_assign(&mut self, bits: &usize) {
×
UNCOV
204
        Self::shl_impl(self, *bits);
×
205
    }
206
}
207

208
impl<T: MachineWord, const N: usize> OverflowingShr for FixedUInt<T, N> {
209
    fn overflowing_shr(self, bits: u32) -> (Self, bool) {
6✔
210
        let bitsu = bits as usize;
6✔
211
        let (shift, overflow) = if bitsu >= Self::BIT_SIZE {
18✔
212
            (bitsu & (Self::BIT_SIZE - 1), true)
6✔
213
        } else {
214
            (bitsu, false)
6✔
215
        };
216
        let res = core::ops::Shr::<usize>::shr(self, shift);
6✔
217
        (res, overflow)
6✔
218
    }
219
}
220

221
impl<T: MachineWord, const N: usize> core::ops::Shr<u32> for FixedUInt<T, N> {
222
    type Output = Self;
223
    fn shr(self, bits: u32) -> <Self as core::ops::Shr<u32>>::Output {
10✔
224
        core::ops::Shr::<usize>::shr(self, bits as usize)
10✔
225
    }
226
}
227

228
impl<T: MachineWord, const N: usize> core::ops::Shr<usize> for FixedUInt<T, N> {
229
    type Output = Self;
230
    fn shr(self, bits: usize) -> <Self as core::ops::Shr<usize>>::Output {
10✔
231
        // Technically, this copy can be avoided
232
        let mut result = self;
10✔
233
        Self::shr_impl(&mut result, bits);
10✔
234
        result
12✔
235
    }
236
}
237

238
impl<T: MachineWord, const N: usize> core::ops::Shr<&'_ usize> for FixedUInt<T, N> {
239
    type Output = Self;
240
    fn shr(self, bits: &usize) -> <Self as core::ops::Shr<usize>>::Output {
1✔
241
        let mut result = self;
1✔
242
        Self::shr_impl(&mut result, *bits);
1✔
243
        result
1✔
244
    }
245
}
246

247
impl<T: MachineWord, const N: usize> num_traits::WrappingShr for FixedUInt<T, N> {
248
    fn wrapping_shr(&self, bits: u32) -> Self {
6✔
249
        self.overflowing_shr(bits).0
6✔
250
    }
251
}
252

253
impl<T: MachineWord, const N: usize> num_traits::CheckedShr for FixedUInt<T, N> {
254
    fn checked_shr(&self, bits: u32) -> Option<Self> {
6✔
255
        let res = self.overflowing_shr(bits);
6✔
256
        if res.1 {
12✔
257
            None
6✔
258
        } else {
259
            Some(res.0)
6✔
260
        }
261
    }
262
}
263

264
// SaturatingShr doesn't exist
265

266
impl<T: MachineWord, const N: usize> core::ops::ShrAssign<usize> for FixedUInt<T, N> {
267
    fn shr_assign(&mut self, bits: usize) {
20✔
268
        Self::shr_impl(self, bits);
20✔
269
    }
270
}
271

272
impl<T: MachineWord, const N: usize> core::ops::ShrAssign<&'_ usize> for FixedUInt<T, N> {
UNCOV
273
    fn shr_assign(&mut self, bits: &usize) {
×
UNCOV
274
        Self::shr_impl(self, *bits);
×
275
    }
276
}
277

278
impl<T: MachineWord, const N: usize> core::ops::Shl<&usize> for &FixedUInt<T, N> {
279
    type Output = FixedUInt<T, N>;
280
    fn shl(self, bits: &usize) -> Self::Output {
1✔
281
        let mut result = *self;
1✔
282
        Self::Output::shl_impl(&mut result, *bits);
1✔
283
        result
1✔
284
    }
285
}
286

287
impl<T: MachineWord, const N: usize> core::ops::Shl<&u32> for &FixedUInt<T, N> {
288
    type Output = FixedUInt<T, N>;
289
    fn shl(self, bits: &u32) -> Self::Output {
1✔
290
        self.shl(&(*bits as usize))
1✔
291
    }
292
}
293

294
impl<T: MachineWord, const N: usize> core::ops::Shr<&usize> for &FixedUInt<T, N> {
295
    type Output = FixedUInt<T, N>;
296
    fn shr(self, bits: &usize) -> Self::Output {
1✔
297
        let mut result = *self;
1✔
298
        Self::Output::shr_impl(&mut result, *bits);
1✔
299
        result
1✔
300
    }
301
}
302

303
impl<T: MachineWord, const N: usize> core::ops::Shr<&u32> for &FixedUInt<T, N> {
304
    type Output = FixedUInt<T, N>;
305
    fn shr(self, bits: &u32) -> Self::Output {
1✔
306
        self.shr(&(*bits as usize))
1✔
307
    }
308
}
309

310
// Additional Shl implementations
311
impl<T: MachineWord, const N: usize> core::ops::Shl<usize> for &FixedUInt<T, N> {
312
    type Output = FixedUInt<T, N>;
313
    fn shl(self, bits: usize) -> Self::Output {
1✔
314
        self.shl(&bits)
1✔
315
    }
316
}
317

318
impl<T: MachineWord, const N: usize> core::ops::Shl<u32> for &FixedUInt<T, N> {
319
    type Output = FixedUInt<T, N>;
320
    fn shl(self, bits: u32) -> Self::Output {
1✔
321
        self.shl(&(bits as usize))
1✔
322
    }
323
}
324

325
impl<T: MachineWord, const N: usize> core::ops::Shl<&u32> for FixedUInt<T, N> {
326
    type Output = Self;
327
    fn shl(self, bits: &u32) -> Self::Output {
1✔
328
        self.shl(*bits)
1✔
329
    }
330
}
331

332
// Additional Shr implementations
333
impl<T: MachineWord, const N: usize> core::ops::Shr<usize> for &FixedUInt<T, N> {
334
    type Output = FixedUInt<T, N>;
335
    fn shr(self, bits: usize) -> Self::Output {
1✔
336
        self.shr(&bits)
1✔
337
    }
338
}
339

340
impl<T: MachineWord, const N: usize> core::ops::Shr<u32> for &FixedUInt<T, N> {
341
    type Output = FixedUInt<T, N>;
342
    fn shr(self, bits: u32) -> Self::Output {
1✔
343
        self.shr(&(bits as usize))
1✔
344
    }
345
}
346

347
impl<T: MachineWord, const N: usize> core::ops::Shr<&u32> for FixedUInt<T, N> {
348
    type Output = Self;
349
    fn shr(self, bits: &u32) -> Self::Output {
1✔
350
        self.shr(*bits)
1✔
351
    }
352
}
353

354
#[cfg(test)]
355
mod tests {
356
    use super::*;
357

358
    #[test]
359
    fn test_bitand_combinations() {
360
        let a = FixedUInt::<u8, 2>::from(12u8); // 1100
361
        let b = FixedUInt::<u8, 2>::from(10u8); // 1010
362
        let expected = FixedUInt::<u8, 2>::from(8u8); // 1000
363

364
        // value & value
365
        assert_eq!(a & b, expected);
366
        // value & ref
367
        assert_eq!(a & &b, expected);
368
        // ref & value
369
        assert_eq!(&a & b, expected);
370
        // ref & ref
371
        assert_eq!(&a & &b, expected);
372
    }
373

374
    #[test]
375
    fn test_bitor_combinations() {
376
        let a = FixedUInt::<u8, 2>::from(12u8); // 1100
377
        let b = FixedUInt::<u8, 2>::from(10u8); // 1010
378
        let expected = FixedUInt::<u8, 2>::from(14u8); // 1110
379

380
        // value | value
381
        assert_eq!(a | b, expected);
382
        // value | ref
383
        assert_eq!(a | &b, expected);
384
        // ref | value
385
        assert_eq!(&a | b, expected);
386
        // ref | ref
387
        assert_eq!(&a | &b, expected);
388
    }
389

390
    #[test]
391
    fn test_bitxor_combinations() {
392
        let a = FixedUInt::<u8, 2>::from(12u8); // 1100
393
        let b = FixedUInt::<u8, 2>::from(10u8); // 1010
394
        let expected = FixedUInt::<u8, 2>::from(6u8); // 0110
395

396
        // value ^ value
397
        assert_eq!(a ^ b, expected);
398
        // value ^ ref
399
        assert_eq!(a ^ &b, expected);
400
        // ref ^ value
401
        assert_eq!(&a ^ b, expected);
402
        // ref ^ ref
403
        assert_eq!(&a ^ &b, expected);
404
    }
405

406
    #[test]
407
    fn test_shl_combinations() {
408
        let a = FixedUInt::<u8, 2>::from(2u8); // 0010
409
        let shift: usize = 2;
410
        let expected = FixedUInt::<u8, 2>::from(8u8); // 1000
411

412
        // value << value
413
        assert_eq!(a << shift, expected);
414
        // value << ref
415
        assert_eq!(a << &shift, expected);
416
        // ref << value
417
        assert_eq!(&a << shift, expected);
418
        // ref << ref
419
        assert_eq!(&a << &shift, expected);
420

421
        // Same with u32
422
        let shift32: u32 = 2;
423
        assert_eq!(a << shift32, expected);
424
        assert_eq!(a << &shift32, expected);
425
        assert_eq!(&a << shift32, expected);
426
        assert_eq!(&a << &shift32, expected);
427
    }
428

429
    #[test]
430
    fn test_shr_combinations() {
431
        let a = FixedUInt::<u8, 2>::from(8u8); // 1000
432
        let shift: usize = 2;
433
        let expected = FixedUInt::<u8, 2>::from(2u8); // 0010
434

435
        // value >> value
436
        assert_eq!(a >> shift, expected);
437
        // value >> ref
438
        assert_eq!(a >> &shift, expected);
439
        // ref >> value
440
        assert_eq!(&a >> shift, expected);
441
        // ref >> ref
442
        assert_eq!(&a >> &shift, expected);
443

444
        // Same with u32
445
        let shift32: u32 = 2;
446
        assert_eq!(a >> shift32, expected);
447
        assert_eq!(a >> &shift32, expected);
448
        assert_eq!(&a >> shift32, expected);
449
        assert_eq!(&a >> &shift32, expected);
450
    }
451
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc