qFALL-math basics
Rusts datatypes such as u64
and i64
are limited in the representable integers.
For example, the following code causes an overflow:
let overflow: u64 = u64::MAX + 1;
The library allows it to work with arbitrarily large integers without having to worry about overflows and memory allocation.
The most basic types are Z, Zq
and Q
.
All can be instantiated from rust types, as well as from strings and
also support all common arithmetic operations among other functionalities.
Instantiate basic types
Z, Zq
and Q
can be instantiated both from strings, as well as rust's basic math types.
use qfall_math::{integer::Z, integer_mod_q::Zq, rational::Q};
use std::str::FromStr;
fn basic_instantiations() {
// instantiations using rust types
let z = Z::from(42);
let zq = Zq::from((24, 42));
let q = Q::from((24, 42));
// instantiations using strings
let z = Z::from_str("42").unwrap();
let zq = Zq::from_str("24 mod 42").unwrap();
let q = Q::from_str("24/42").unwrap();
}
Zq and its Modulus
A special role can be assigned to Zq
, as it does not only contain a value but also a context object represented by its modulus.
A modulus object is of type Modulus
and can be instantiated from a Z
greater or equal to two.
use qfall_math::{integer::Z, integer_mod_q::Modulus};
fn instantiate_modulus() {
let z = Z::from(42);
let modulus = Modulus::from(&z);
let modulus = Modulus::from(42);
}
A modulus can be shared among different values and, if shared, reduces runtime and reduces storage usage.
use qfall_math::{
integer::Z,
integer_mod_q::{Modulus, Zq},
};
fn shared_modulus() {
let modulus = Modulus::from(42);
let zq_1 = Zq::from((17, &modulus));
let zq_2 = Zq::from((24, &modulus));
}
Converting types
All reasonable types can be converted between one another, e.g. we can define a Q
from a Z
.
use qfall_math::{integer::Z, rational::Q};
fn q_from_z() {
let z = Z::from(42);
let q = Q::from(&z);
}
Basic arithmetics
All types support basic arithmetics. Among them are multiplication, addition and subtraction.
use qfall_math::integer::Z;
fn basic_arithmetics() {
let z_1 = Z::from(42);
let z_2 = Z::from(24);
let add = &z_1 + &z_2;
let sub = &z_1 - &z_2;
let mul = &z_1 * &z_2;
}
Printing your Results
You can print the values of operations using print!
or println!
, or
convert them into strings with .tostring()
.
use qfall_math::integer_mod_q::Zq;
fn print() {
let zq_1 = Zq::from((24, 42));
let zq_2 = Zq::from((17, 42));
let zq = zq_1 - zq_2;
// print it directly
println!("{zq}");
// turn it into a string first
let zq_string = zq.to_string();
println!("{}", zq_string)
}
Error Handling
In our math crate, we have one file error.rs
, containing all our error types.
We use MathError
as our error enum that holds all sorts of errors occurring in
this crate and StringConversionError
for all errors that are related to the conversion of strings.
Errors are normally propagated through functions such that they can easily be handled or ignored with unwrap()
.
In cases where errors are easily visible, like "division by zero" errors, we do not propagate the error but panic instead.
That is to evade unnecessary uses of unwrap()
.