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
use std::{error::Error, fmt::{self, Display}};

/// More concise syntax for implementing `Error` and `Display` for both structs and enums
macro_rules! impl_err {
    ($s:ty, $e:expr) => {
        impl Error for $s {}
        impl Display for $s {
            fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
                write!(f, $e)
            }
        }
    };
    ( $s:ty, $($p:path, $e:expr),* ) => {
        impl Error for $s {}
        impl Display for $s {
            fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
                match self {
                    $($p => write!(f, $e),)*
                }
            }
        }
    };
}

#[derive(Debug)]
pub struct NxNInversionError;
impl_err!(
    NxNInversionError, 
    "matrix could not be inverted"
);

#[derive(Debug)]
pub struct NxNCreationError;
impl_err!(
    NxNCreationError,
    "columns did not form an nxn matrix"
);

#[derive(Debug)]
pub struct NxNMultiplicationError;
impl_err!(
    NxNMultiplicationError,
    "failed to multiply matrix by vector."
);

#[derive(Debug)]
pub struct VecMultiplicationError;
impl_err!(
    VecMultiplicationError,
    "tried to dot vectors of different sizes"
);

#[derive(Debug)]
pub enum SolverDivisionByZeroError {
    NewtonRaphsonDivByZeroError,
    MVNewtonRaphsonDivByZeroError,
    GoldSectionSearchDivByZeroError
}
impl_err!(
    SolverDivisionByZeroError,
    SolverDivisionByZeroError::NewtonRaphsonDivByZeroError,     "newton-raphson solver tried to divide by zero",
    SolverDivisionByZeroError::MVNewtonRaphsonDivByZeroError,   "multivariate newton-raphson solver tried to divide by zero",
    SolverDivisionByZeroError::GoldSectionSearchDivByZeroError, "golden section search solver tried to divide by zero"
);

#[derive(Debug)]
pub struct RoundingError;
impl_err!(
    RoundingError,
    "number not valid for rounding"
);

/// Error type for issues with the conditional expression formatter in `nexsys::parsing`
#[derive(Debug)]
pub enum ConditionFormatError {
    ConditionalSyntax,
    Comparator
}
impl_err!(
    ConditionFormatError,
    ConditionFormatError::ConditionalSyntax,    "conditional statement failed to compile",
    ConditionFormatError::Comparator,           "invalid comparison operator. valid operators are: <, >, <=, >=, ==, !="
);

#[derive(Debug)]
pub struct ConversionFormatError;
impl_err!(
    ConversionFormatError,
    "conversion factor failed to compile"
);

#[derive(Debug)]
pub struct ConstFormatError;
impl_err!(
    ConstFormatError,
    "constant failed to compile"
);

#[derive(Debug)]
pub struct UnitConversionError;
impl_err!(
    UnitConversionError,
    "failed to identify conversion factors"
);

#[derive(Debug)]
pub struct SolverConvergenceError;
impl_err!(
    SolverConvergenceError,
    "solver algorithm did not converge. consider allowing non-convergent solutions, or try to remove discontinuities from your system"
);