Skip to main content

bigfixed/
index.rs

1// BigFixeds can be indexed by position (wrt Digit) or bit. If bit precision is not possible it may convert to the corresponding position index.
2
3pub use std::{
4    convert::{
5        From,
6        TryFrom
7    },
8    fmt,
9    ops::{
10        Add, AddAssign,
11        Neg,
12        Sub, SubAssign,
13        Mul, MulAssign,
14        Range
15    },
16    cmp::{
17        PartialEq,
18        PartialOrd,
19        Ordering,
20        max
21    },
22    num::{
23        TryFromIntError
24    },
25    error::{
26        Error
27    }
28};
29
30use crate::{digit::*, macros::*};
31
32#[derive(Clone, Copy, Eq)]
33pub enum Index {
34    Position(isize),
35    Bit(isize)
36}
37
38pub use Index::*;
39
40#[derive(Clone, Copy, Eq, PartialEq, Debug)]
41pub enum IndexError {
42    AdditionOverflow,
43    MultiplicationOverflow,
44    IntegerCastOverflow
45}
46
47impl fmt::Display for IndexError {
48    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
49        write!(f, "{:?}", self)
50    }
51}
52
53impl Error for IndexError {}
54
55impl From<TryFromIntError> for IndexError {
56    fn from(_x: TryFromIntError) -> IndexError {
57        IntegerCastOverflow
58    } 
59}
60
61pub use IndexError::*;
62
63impl Index {
64    // fails for very large inputs
65    pub fn castsize(x: usize) -> Result<isize, IndexError> {
66        Ok(TryFrom::try_from(x)?)
67    }
68    // fails for negative inputs
69    pub fn uncastsize(x: isize) -> Result<usize, IndexError> {
70        Ok(TryFrom::try_from(x)?)
71    }
72    // fails for very large inputs
73    pub fn position_to_bit(x: isize) -> Result<isize, IndexError> {
74        x.checked_mul(DIGITBITS as isize).ok_or(MultiplicationOverflow)
75    }
76
77    pub fn bit_to_position(x: isize) -> isize {
78        x.div_euclid(DIGITBITS as isize)
79    }
80
81    pub fn saturating_unsigned(x: isize) -> usize {
82        Index::uncastsize(max(0, x)).unwrap()
83    }
84
85    pub fn cast(&self) -> Result<Index, IndexError> {
86        match self {
87            Position(x) => Ok(Bit(Index::position_to_bit(*x)?)),
88            Bit(x) => Ok(Bit(Index::bit_to_position(*x)))
89        }
90    }
91
92    pub fn cast_to_position(&self) -> Index {
93        match self {
94            Position(_) => *self,
95            Bit(x) => Position(Index::bit_to_position(*x))
96        }
97    }
98
99    pub fn bit_position_excess(&self) -> isize {
100        match self {
101            Position(_) => 0,
102            Bit(x) => x.rem_euclid(DIGITBITS as isize)
103        }
104    }
105
106    pub fn cast_to_bit(&self) -> Result<Index, IndexError> {
107        match self {
108            Position(x) => Ok(Bit(Index::position_to_bit(*x)?)),
109            Bit(_) => Ok(*self)
110        }
111    }
112
113    pub fn saturating_nonnegative(&self) -> Index {
114        match self {
115            Position(x) => Position(max(0, *x)),
116            Bit(x) => Bit(max(0, *x))
117        }
118    }
119
120    pub fn value(&self) -> isize {
121        isize::from(self)
122    }
123
124    pub fn unsigned_value(&self) -> usize {
125        Index::saturating_unsigned(self.value())
126    }
127
128    pub fn bit_value(&self) -> Result<isize, IndexError> {
129        return Ok(self.cast_to_bit()?.value())
130    }
131    
132    pub fn neg(self) -> Result<Index, IndexError> {
133        match self {
134            Position(x) => Ok(Position(x.checked_neg().ok_or(IntegerCastOverflow)?)),
135            Bit(x) => Ok(Bit(x.checked_neg().ok_or(IntegerCastOverflow)?))
136        }
137    }
138}
139
140// format convention: (position), [bit], so 2[(0)] == 2, 2[(1)] == 0, 2[[0]] = 0, 2[[1]] == 1
141
142macro_rules! formatter {
143    ($fmt_type: ident, $key: expr) => {
144        impl fmt::$fmt_type for Index {
145            fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
146                match self {
147                    Position(x) => {
148                        write!(f, "(").ok();
149                        write!(f, $key, x).ok();
150                        write!(f, ")")
151                    }, Bit(x) => {
152                        write!(f, "[").ok();
153                        write!(f, $key, x).ok();
154                        write!(f, "]")
155                    }
156                }
157            }
158        }
159    };
160}
161
162formatter!(Display, "{}");
163formatter!(Debug, "{:?}");
164formatter!(Octal, "{:o}");
165formatter!(LowerHex, "{:x}");
166formatter!(UpperHex, "{:X}");
167formatter!(Binary, "{:b}");
168
169impl From<&Index> for isize {
170    fn from(a: &Index) -> isize {
171        match a {
172            Position(x) => *x,
173            Bit(x) => *x
174        }
175    }
176}
177
178impl From<Index> for isize {
179    fn from(a: Index) -> isize {
180        isize::from(&a)
181    }
182}
183
184impl From<&Index> for usize {
185    fn from(a: &Index) -> usize {
186        match a.saturating_nonnegative() {
187            Position(x) => x as usize,
188            Bit(x) => x as usize
189        }
190    }
191}
192
193impl From<Index> for usize {
194    fn from(a: Index) -> usize {
195        usize::from(&a)
196    }
197}
198
199unary_copy!(Neg, neg, Index, neg, Index, IndexError);
200
201impl Add for &Index {
202    type Output = Result<Index, IndexError>;
203    fn add(self, other: &Index) -> Result<Index, IndexError> {
204        let a;
205        let b;
206        let position;
207        match (self, other) {
208            (Position(x), Position(y)) => {
209                a = *x;
210                b = *y;
211                position = true;
212            },
213            (Bit(x), Bit(y)) => {
214                a = *x;
215                b = *y;
216                position = false;
217            },
218            (Position(x), Bit(y)) => {
219                a = Index::position_to_bit(*x)?;
220                b = *y;
221                position = false;
222            },
223            (Bit(x), Position(y)) => {
224                a = *x;
225                b = Index::position_to_bit(*y)?;
226                position = false;
227            }
228        };
229        let sum = a.checked_add(b).ok_or(AdditionOverflow)?;
230        if position {
231            Ok(Position(sum))
232        } else {
233            Ok(Bit(sum))
234        }
235    }
236}
237
238op_to_op_assign!(
239    Add, add,
240    AddAssign, add_assign,
241    Index, Index,
242    Index, IndexError
243);
244
245impl Add<&usize> for &Index {
246    type Output = Result<Index, IndexError>;
247    fn add(self, other: &usize) -> Result<Index, IndexError> {
248        match self {
249            Position(x) => {
250                Ok(Position(x.checked_add(Index::castsize(*other)?).ok_or(AdditionOverflow)?))
251            },
252            Bit(x) => {
253                Ok(Bit(x.checked_add(Index::castsize(*other)?).ok_or(AdditionOverflow)?))
254            }
255        }
256    }
257}
258
259op_to_op_assign!(
260    Add, add,
261    AddAssign, add_assign,
262    Index, usize,
263    Index, IndexError
264);
265
266impl Add<&Index> for usize {
267    type Output = Result<Index, IndexError>;
268    fn add(self, other: &Index) -> Result<Index, IndexError> {
269        match other {
270            Position(x) => Ok(Position(x.checked_add(Index::castsize(self)?).ok_or(AdditionOverflow)?)),
271            Bit(x) => Ok(Bit(x.checked_add(Index::castsize(self)?).ok_or(AdditionOverflow)?)),
272        }
273    }
274}
275
276impl Add<Index> for usize {
277    type Output = Result<Index, IndexError>;
278    fn add(self, other: Index) -> Result<Index, IndexError> {
279        self + &other
280    }
281}
282
283impl Add<&isize> for &Index {
284    type Output = Result<Index, IndexError>;
285    fn add(self, other: &isize) -> Result<Index, IndexError> {
286        match self {
287            Position(x) => {
288                Ok(Position(x.checked_add(*other).ok_or(AdditionOverflow)?))
289            },
290            Bit(x) => {
291                Ok(Bit(x.checked_add(*other).ok_or(AdditionOverflow)?))
292            }
293        }
294    }
295}
296
297op_to_op_assign!(
298    Add, add,
299    AddAssign, add_assign,
300    Index, isize,
301    Index, IndexError
302);
303
304impl Add<&Index> for isize {
305    type Output = Result<Index, IndexError>;
306    fn add(self, other: &Index) -> Result<Index, IndexError> {
307        match other {
308            Position(x) => Ok(Position(self.checked_add(*x).ok_or(AdditionOverflow)?)),
309            Bit(x) => Ok(Bit(self.checked_add(*x).ok_or(AdditionOverflow)?))
310        }
311    }
312}
313
314impl Add<Index> for isize {
315    type Output = Result<Index, IndexError>;
316    fn add(self, other: Index) -> Result<Index, IndexError> {
317        self + &other
318    }
319}
320
321impl Sub for &Index {
322    type Output = Result<Index, IndexError>;
323    fn sub(self, other: &Index) -> Result<Index, IndexError> {
324        let a;
325        let b;
326        let position;
327        match (self, other) {
328            (Position(x), Position(y)) => {
329                a = *x;
330                b = *y;
331                position = true;
332            },
333            (Bit(x), Bit(y)) => {
334                a = *x;
335                b = *y;
336                position = false;
337            },
338            (Position(x), Bit(y)) => {
339                a = Index::position_to_bit(*x)?;
340                b = *y;
341                position = false;
342            },
343            (Bit(x), Position(y)) => {
344                a = *x;
345                b = Index::position_to_bit(*y)?;
346                position = false;
347            }
348        };
349        let diff = a.checked_sub(b).ok_or(AdditionOverflow)?;
350        if position {
351            Ok(Position(diff))
352        } else {
353            Ok(Bit(diff))
354        }
355    }
356}
357
358op_to_op_assign!(
359    Sub, sub,
360    SubAssign, sub_assign,
361    Index, Index,
362    Index, IndexError
363);
364
365impl Sub<&usize> for &Index {
366    type Output = Result<Index, IndexError>;
367    fn sub(self, other: &usize) -> Result<Index, IndexError> {
368        match self {
369            Position(x) => {
370                Ok(Position(x.checked_sub(Index::castsize(*other)?).ok_or(AdditionOverflow)?))
371            },
372            Bit(x) => {
373                Ok(Bit(x.checked_sub(Index::castsize(*other)?).ok_or(AdditionOverflow)?))
374            }
375        }
376    }
377}
378
379op_to_op_assign!(
380    Sub, sub,
381    SubAssign, sub_assign,
382    Index, usize,
383    Index, IndexError
384);
385
386impl Sub<&Index> for usize {
387    type Output = Result<Index, IndexError>;
388    fn sub(self, other: &Index) -> Result<Index, IndexError> {
389        match other {
390            Position(x) => Ok(Position(Index::castsize(self)?.checked_sub(*x).ok_or(AdditionOverflow)?)),
391            Bit(x) => Ok(Bit(Index::castsize(self)?.checked_sub(*x).ok_or(AdditionOverflow)?)),
392        }
393    }
394}
395
396impl Sub<Index> for usize {
397    type Output = Result<Index, IndexError>;
398    fn sub(self, other: Index) -> Result<Index, IndexError> {
399        self - &other
400    }
401}
402
403impl Sub<&isize> for &Index {
404    type Output = Result<Index, IndexError>;
405    fn sub(self, other: &isize) -> Result<Index, IndexError> {
406        match self {
407            Position(x) => {
408                Ok(Position(x.checked_sub(*other).ok_or(AdditionOverflow)?))
409            },
410            Bit(x) => {
411                Ok(Bit(x.checked_sub(*other).ok_or(AdditionOverflow)?))
412            }
413        }
414    }
415}
416
417op_to_op_assign!(
418    Sub, sub,
419    SubAssign, sub_assign,
420    Index, isize,
421    Index, IndexError
422);
423
424impl Sub<&Index> for isize {
425    type Output = Result<Index, IndexError>;
426    fn sub(self, other: &Index) -> Result<Index, IndexError> {
427        match other {
428            Position(x) => Ok(Position(self.checked_sub(*x).ok_or(AdditionOverflow)?)),
429            Bit(x) => Ok(Bit(self.checked_sub(*x).ok_or(AdditionOverflow)?))
430        }
431    }
432}
433
434impl Sub<Index> for isize {
435    type Output = Result<Index, IndexError>;
436    fn sub(self, other: Index) -> Result<Index, IndexError> {
437        self - &other
438    }
439}
440
441impl Mul for &Index {
442    type Output = Result<Index, IndexError>;
443    fn mul(self, other: &Index) -> Result<Index, IndexError> {
444        let a;
445        let b;
446        let position;
447        match (self, other) {
448            (Position(x), Position(y)) => {
449                a = *x;
450                b = *y;
451                position = true;
452            },
453            (Bit(x), Bit(y)) => {
454                a = *x;
455                b = *y;
456                position = false;
457            },
458            (Position(x), Bit(y)) => {
459                a = Index::position_to_bit(*x)?;
460                b = *y;
461                position = false;
462            },
463            (Bit(x), Position(y)) => {
464                a = *x;
465                b = Index::position_to_bit(*y)?;
466                position = false;
467            }
468        };
469        let prod = a.checked_mul(b).ok_or(AdditionOverflow)?;
470        if position {
471            Ok(Position(prod))
472        } else {
473            Ok(Bit(prod))
474        }
475    }
476}
477
478op_to_op_assign!(
479    Mul, mul,
480    MulAssign, mul_assign,
481    Index, Index,
482    Index, IndexError
483);
484
485impl Mul<&usize> for &Index {
486    type Output = Result<Index, IndexError>;
487    fn mul(self, other: &usize) -> Result<Index, IndexError> {
488        match self {
489            Position(x) => {
490                Ok(Position(x.checked_mul(Index::castsize(*other)?).ok_or(AdditionOverflow)?))
491            },
492            Bit(x) => {
493                Ok(Bit(x.checked_mul(Index::castsize(*other)?).ok_or(AdditionOverflow)?))
494            }
495        }
496    }
497}
498
499op_to_op_assign!(
500    Mul, mul,
501    MulAssign, mul_assign,
502    Index, usize,
503    Index, IndexError
504);
505
506impl Mul<&Index> for usize {
507    type Output = Result<Index, IndexError>;
508    fn mul(self, other: &Index) -> Result<Index, IndexError> {
509        match other {
510            Position(x) => Ok(Position(x.checked_mul(Index::castsize(self)?).ok_or(AdditionOverflow)?)),
511            Bit(x) => Ok(Bit(x.checked_mul(Index::castsize(self)?).ok_or(AdditionOverflow)?)),
512        }
513    }
514}
515
516impl Mul<Index> for usize {
517    type Output = Result<Index, IndexError>;
518    fn mul(self, other: Index) -> Result<Index, IndexError> {
519        self * &other
520    }
521}
522
523impl Mul<&isize> for &Index {
524    type Output = Result<Index, IndexError>;
525    fn mul(self, other: &isize) -> Result<Index, IndexError> {
526        match self {
527            Position(x) => {
528                Ok(Position(x.checked_mul(*other).ok_or(AdditionOverflow)?))
529            },
530            Bit(x) => {
531                Ok(Bit(x.checked_mul(*other).ok_or(AdditionOverflow)?))
532            }
533        }
534    }
535}
536
537op_to_op_assign!(
538    Mul, mul,
539    MulAssign, mul_assign,
540    Index, isize,
541    Index, IndexError
542);
543
544impl Mul<&Index> for isize {
545    type Output = Result<Index, IndexError>;
546    fn mul(self, other: &Index) -> Result<Index, IndexError> {
547        match other {
548            Position(x) => Ok(Position(self.checked_mul(*x).ok_or(AdditionOverflow)?)),
549            Bit(x) => Ok(Bit(self.checked_mul(*x).ok_or(AdditionOverflow)?))
550        }
551    }
552}
553
554impl Mul<Index> for isize {
555    type Output = Result<Index, IndexError>;
556    fn mul(self, other: Index) -> Result<Index, IndexError> {
557        self * &other
558    }
559}
560
561impl PartialEq for Index {
562    fn eq(&self, other: &Index) -> bool {
563        match (self, other) {
564            (Position(x), Position(y)) => x == y,
565            (Bit(x), Bit(y)) => x == y,
566            (Position(x), Bit(y)) => {
567                *x == Index::bit_to_position(*y)
568            },
569            (Bit(x), Position(y)) => {
570                *y == Index::bit_to_position(*x)
571            }
572        }
573    }
574}
575
576impl PartialEq<isize> for Index {
577    fn eq(&self, other: &isize) -> bool {
578        match self {
579            Position(x) => *x == *other,
580            Bit(x) => *x == *other
581        }
582    }
583}
584
585impl PartialEq<usize> for Index {
586    fn eq(&self, other: &usize) -> bool {
587        let o = Index::castsize(*other).unwrap();
588        match self {
589            Position(x) => *x == o,
590            Bit(x) => *x == o
591        }
592    }
593}
594
595impl PartialOrd for Index {
596    fn partial_cmp(&self, other: &Index) -> Option<Ordering> {
597        match (self, other) {
598            (Position(x), Position(y)) => x.partial_cmp(y),
599            (Bit(x), Bit(y)) => x.partial_cmp(y),
600            (Position(x), Bit(y)) => {
601                match Index::position_to_bit(*x) {
602                    Ok(z) => z.partial_cmp(y),
603                    Err(_) => None
604                }
605            },
606            (Bit(x), Position(y)) => {
607                match Index::position_to_bit(*y) {
608                    Ok(z) => x.partial_cmp(&z),
609                    Err(_) => None
610                }
611            }
612        }
613    }
614}
615
616impl Ord for Index {
617    fn cmp(&self, other: &Index) -> Ordering {
618        self.partial_cmp(other).unwrap()
619    }
620}
621
622impl PartialOrd<isize> for Index {
623    fn partial_cmp(&self, other: &isize) -> Option<Ordering> {
624        match self {
625            Position(x) => x.partial_cmp(other),
626            Bit(x) => x.partial_cmp(other)
627        }
628    }
629}
630
631impl PartialOrd<usize> for Index {
632    fn partial_cmp(&self, other: &usize) -> Option<Ordering> {
633        let o = &Index::castsize(*other).unwrap();
634        match self {
635            Position(x) => x.partial_cmp(o),
636            Bit(x) => x.partial_cmp(o)
637        }
638    }
639}
640