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().