qfall_math/error.rs
1// Copyright © 2023 Niklas Siemer
2//
3// This file is part of qFALL-math.
4//
5// qFALL-math is free software: you can redistribute it and/or modify it under
6// the terms of the Mozilla Public License Version 2.0 as published by the
7// Mozilla Foundation. See <https://mozilla.org/en-US/MPL/2.0/>.
8
9//! Contains our central error enum for easy error propagation.
10//!
11//! This module contains this crate's error enum. This enum can hold all sorts
12//! of errors occurring in this crate s.t. error propagation is simple for
13//! developers of this crate and all sorts of thrown errors and error types can
14//! be easily found and accessed by developers using this crate. Furthermore,
15//! the actual errors are wrapped s.t. all information about the error can be
16//! unwrapped again.
17
18// **For developers:**
19// - How to add an error to an `enum`? First of all, find a name
20// that is not too specific for your current case s.t. it could be used in other
21// contexts afterwards as well. Then, find the spot according to your chosen error
22// name in a alphanumerically sorted way in the list of supported errors in the doc
23// comment and inside the `enum` itself.
24// Afterwards, add the error to the list of implemented error
25// types in the doc comment of the `enum` with a short description when it is thrown.
26// Probably use this description for the doc comment above the implementation of
27// error in the `enum`. Then, add `#[error(<error msg>)]` to define the error message
28// output once your error is thrown. Below, write down `<error name>(<input>),` to
29// define the error with its name and possibly some inputs. The input can be of the
30// form [`String`], but also another error, whose conversion must be declared via
31// `#[from] OtherError`. It is best to use the existing structure as a guide. For any
32// further information, check out the here used [`thiserror`]-crate.
33
34use std::ffi::NulError;
35use thiserror::Error;
36
37/// [`MathError`] defines this crate's error enum, which can hold all sorts of
38/// errors occurring in this crate.
39///
40/// Implemented error types:
41/// - [`ConversionError`](MathError::ConversionError) is thrown if a conversion
42/// between types is not possible.
43/// - [`DivisionByZeroError`](MathError::DivisionByZeroError) is thrown if it is
44/// tried to perform a division by `0`.
45/// - [`InvalidExponent`](MathError::InvalidExponent) is thrown if an invalid
46/// exponent is used for a `pow` function.
47/// - [`InvalidIntegerInput`](MathError::InvalidIntegerInput) is thrown if an
48/// integer input is provided as parameter that does not meet the conditions
49/// of that function.
50/// - [`InvalidInterval`](MathError::InvalidInterval) is thrown if an invalid
51/// interval, e.g. of negative size, is provided.
52/// - [`InvalidModulus`](MathError::InvalidModulus) is thrown if an integer is
53/// provided, which is smaller than `2`.
54/// - [`NulError`](MathError::NulError) is thrown if a [`NulError`] is thrown,
55/// which currently only happens if an invalid string is given to construct
56/// a [`CString`](std::ffi::CString).
57/// - [`MismatchingMatrixDimension`](MathError::MismatchingMatrixDimension) is
58/// thrown if arithmetic is done with matrices of mismatching dimensions.
59/// - [`MismatchingModulus`](MathError::MismatchingModulus) is thrown if any
60/// function is called on two objects with different modulus where equal
61/// modulus is required.
62/// - [`NonPositive`](MathError::NonPositive) is thrown if the function expects
63/// a positive number, but a number smaller than `1` is provided.
64/// - [`NoSquareMatrix`](MathError::NoSquareMatrix) is thrown if a matrix is
65/// not square.
66/// - [`OutOfBounds`](MathError::OutOfBounds) is thrown if a provided index
67/// is not in a desired range.
68/// - [`VectorFunctionCalledOnNonVector`](MathError::VectorFunctionCalledOnNonVector)
69/// is thrown if a function defined on vectors was called on a matrix instance
70/// that is not a vector.
71///
72/// # Examples
73/// ```
74/// use qfall_math::{error::MathError, rational::Q};
75/// use std::str::FromStr;
76///
77/// fn parse_string_to_q() -> Result<(), MathError> {
78/// let text = "2/0";
79/// let q = Q::from_str(text)?;
80/// return Ok(());
81/// }
82/// ```
83#[derive(Error, Debug)]
84pub enum MathError {
85 /// Conversion error.
86 #[error("While performing the conversion an error occurred: {0}")]
87 ConversionError(String),
88
89 /// Division by zero error.
90 #[error("The division by zero is not possible {0}")]
91 DivisionByZeroError(String),
92
93 /// Invalid exponent.
94 #[error("Invalid exponent given: {0}")]
95 InvalidExponent(String),
96
97 /// Invalid integer was input to a specific function.
98 #[error("An invalid integer input was given as a parameter: {0}")]
99 InvalidIntegerInput(String),
100
101 /// Invalid interval provided.
102 #[error("An invalid interval was given: {0}")]
103 InvalidInterval(String),
104
105 /// Parse int to modulus error.
106 #[error("An invalid value should be parsed as a modulus {0}.")]
107 InvalidModulus(String),
108
109 /// Converts a [`NulError`], which currently only happens if an
110 /// invalid string is given to construct a [`CString`](std::ffi::CString).
111 #[error(
112 "A nul error occurred, which usually happens if an invalid \
113 string input is parsed to a CString {0}"
114 )]
115 NulError(#[from] NulError),
116
117 /// Mismatching matrix dimension error.
118 #[error("Mismatching matrix dimensions {0}")]
119 MismatchingMatrixDimension(String),
120
121 /// Mismatching modulus error.
122 #[error("Mismatching modulus.{0}")]
123 MismatchingModulus(String),
124
125 /// If an integer is not a positive number.
126 #[error(
127 "A function that can only be performed on positive values was \
128 performed on performed on a non-positive value, which is {0}."
129 )]
130 NonPositive(String),
131
132 /// If a matrix is not square.
133 #[error("The matrix is not square {0}")]
134 NoSquareMatrix(String),
135
136 /// If a provided index is out of bounds.
137 #[error(
138 "Invalid index submitted. The index is out of bounds.
139 The index has to {0}, and the provided value is {1}"
140 )]
141 OutOfBounds(String, String),
142
143 /// Some string to one of our data-types error occurred.
144 #[error("{0}")]
145 StringConversionError(#[from] StringConversionError),
146
147 /// If a function defined on vectors is called on a matrix that is not a vector.
148 #[error(
149 "Function named {0} is only defined for vectors and
150 was called on a matrix of dimension {1}x{2}"
151 )]
152 VectorFunctionCalledOnNonVector(String, i64, i64),
153}
154
155/// [`StringConversionError`] defines an error enum,
156/// which holds all [`String`] to data-type conversion errors.
157///
158/// Implemented error types:
159/// - [`InvalidMatrix`](StringConversionError::InvalidMatrix) is thrown if an
160/// invalid string input of a matrix is given.
161/// - [`InvalidStringToPolyInput`](StringConversionError::InvalidStringToPolyInput)
162/// is thrown if an invalid string is given to construct a polynomial.
163/// - [`InvalidStringToPolyMissingWhitespace`](StringConversionError::InvalidStringToPolyMissingWhitespace)
164/// is thrown if an invalid string is given to construct a polynomial which
165/// did not contain two whitespaces.
166/// - [`InvalidStringToPolyModulusInput`](StringConversionError::InvalidStringToPolyModulusInput)
167/// is thrown if an invalid string is given
168/// to construct a [`PolyOverZq`](crate::integer_mod_q::PolyOverZq), i.e. it is
169/// not formatted correctly.
170/// - [`InvalidStringToPolyRingZqInput`](StringConversionError::InvalidStringToPolyRingZqInput)
171/// is thrown if an invalid string is given
172/// to construct a [`PolynomialRingZq`](crate::integer_mod_q::PolynomialRingZq), i.e. it is
173/// not formatted correctly.
174/// - [`InvalidStringToQInput`](StringConversionError::InvalidStringToQInput)
175/// is thrown if an invalid string is given to construct a [`Q`](crate::rational::Q).
176/// - [`InvalidStringToZInput`](StringConversionError::InvalidStringToZInput)
177/// is thrown if an invalid string is given to construct a [`Z`](crate::integer::Z).
178/// - [`InvalidStringToZqInput`](StringConversionError::InvalidStringToZqInput)
179/// is thrown if an invalid string is given to construct a [`Zq`](crate::integer_mod_q::Zq).
180///
181/// # Examples
182/// ```
183/// use qfall_math::error::StringConversionError;
184///
185/// fn throws_error() -> Result<(), StringConversionError> {
186/// return Err(
187/// StringConversionError::InvalidMatrix(String::from(
188/// "Some silly mistake was made",
189/// )),
190/// );
191///
192/// Ok(())
193/// }
194/// ```
195#[derive(Error, Debug)]
196pub enum StringConversionError {
197 /// Invalid Matrix input error.
198 #[error("invalid Matrix. {0}")]
199 InvalidMatrix(String),
200
201 /// Parse string to poly error.
202 #[error(
203 "Invalid string input to parse to polynomial {0}\nThe format must
204 be '[#number of coefficients] [0th coefficient] [1st coefficient] ...'.
205 Note that the after the number of coefficients, there are two
206 whitespace."
207 )]
208 InvalidStringToPolyInput(String),
209
210 /// Parse string to poly error with missing whitespace.
211 #[error(
212 "Invalid string input to parse to polynomial {0}
213 The string did not contain two whitespace at the start. Please note,
214 that there have to two whitespace between number of coefficients
215 and the first coefficient"
216 )]
217 InvalidStringToPolyMissingWhitespace(String),
218
219 /// Parse string to poly with modulus error.
220 #[error(
221 "Invalid string input to parse to polynomial mod q {0}.
222 The format must \
223 be '[#number of coefficients] [0th coefficient] [1st coefficient] ... \
224 mod [modulus]'.
225 Note that after the number of coefficients, there are two \
226 whitespaces."
227 )]
228 InvalidStringToPolyModulusInput(String),
229
230 /// Parse string to [`PolynomialRingZq`](crate::integer_mod_q::PolynomialRingZq) error.
231 #[error(
232 "Invalid string input to parse to polynomial / polynomial mod q {0}.
233 The format must \
234 be `[#number of coefficients of element]⌴⌴[0th coefficient]⌴ \
235 [1st coefficient]⌴...⌴/⌴[#number of coefficients of polynomial modulus] \
236 ⌴⌴[0th coefficient]⌴[1st coefficient]⌴...⌴mod⌴[q]`.
237 Note that after the number of coefficients, there are two \
238 whitespaces."
239 )]
240 InvalidStringToPolyRingZqInput(String),
241
242 /// Parse string to [`Q`](crate::rational::Q) error
243 #[error("Invalid string input to parse to Q {0}")]
244 InvalidStringToQInput(String),
245
246 /// Parse string to [`Z`](crate::integer::Z) error.
247 #[error("Invalid string input to parse to Z {0}")]
248 InvalidStringToZInput(String),
249
250 /// Parse string to [`Zq`](crate::integer_mod_q::Zq) error.
251 #[error("Invalid string input to parse to Zq {0}")]
252 InvalidStringToZqInput(String),
253}