qFALL-math advanced types
For all basic types Z, Zq
and Q
, there exists a matrix MatZ, MatZq
and MatQ
.
They can be instantiated from strings or as zero matrices with their entries set manually
with the functions set_entry()
, set_row
and set_column
.
There also exist polynomials like PolyZ, PolyZq
and PolyQ
, which can be instantiated from strings
or as zero polynomials with their coefficients set manually with the function set_coeff()
.
Furthermore, we provide ring elements like PolynomialRingZq
, which can be instantiated from strings or their components.
Matrices, polynomials and rings support all common arithmetic operations, among other functionalities.
These three advanced types and their functionalities are presented in the following sections with examples of how to use them.
Instantiate advanced types
MatZ
, MatZq
and MatQ
can be instantiated from strings or as 0 matrices.
use qfall_math::{integer::MatZ, integer_mod_q::MatZq, rational::MatQ};
use std::str::FromStr;
fn matrix_instantiations() {
// instantiations using new
// the first number is the number of rows and the second one the number of columns
let matz = MatZ::new(5, 10);
let matzq = MatZq::new(5, 10, 13);
let matq = MatQ::new(5, 10);
// instantiations using strings
// the content of a matrix is written in square brackets and
// one row of the matrix consists of numbers divided by commas in a square bracket
let matz = MatZ::from_str("[[1,2],[3,4]]").unwrap();
let matzq = MatZq::from_str("[[1,2],[3,4]] mod 5").unwrap();
let matq = MatQ::from_str("[[1/2,2],[3/4,4]]").unwrap();
// instantiations using components
let matz = MatZ::from(&matzq);
let matq = MatQ::from(&matz);
}
PolyZ
, PolyZq
and PolyQ
can be instantiated from strings and their components.
use qfall_math::{
integer::PolyOverZ,
integer_mod_q::{Modulus, PolyOverZq},
rational::PolyOverQ,
};
use std::str::FromStr;
fn polynomial_instantiations() {
// instantiations using strings
// the first number is the number of coefficients in the polynomial,
// which is followed by the coefficients in ascending order
let polyz = PolyOverZ::from_str("4 0 1 2 3").unwrap();
let polyzq = PolyOverZq::from_str("4 0 1 -2 3 mod 42").unwrap();
let polyq = PolyOverQ::from_str("5 0 1/3 2/10 -3/2 1").unwrap();
// instantiations using components
let modulus = Modulus::from_str("100").unwrap();
let polyzq = PolyOverZq::from(&modulus);
let polyzq = PolyOverZq::from((&polyz, &modulus));
let polyq = PolyOverQ::from(&polyz);
}
PolynomialRingZq
can be instantiated from strings or its components.
use qfall_math::integer::PolyOverZ;
use qfall_math::integer_mod_q::{ModulusPolynomialRingZq, PolynomialRingZq};
use std::str::FromStr;
fn ring_instantiations() {
// instantiations using components
let modulus = ModulusPolynomialRingZq::from_str("4 1 0 0 1 mod 17").unwrap();
let poly = PolyOverZ::from_str("4 -1 0 1 1").unwrap();
let poly_ring = PolynomialRingZq::from((&poly, &modulus));
}
Manipulation of advanced types
Entries from matrices can be set manually with the functions set_entry()
, set_row()
and set_column()
.
Their entries/rows/columns can be swapped with the functions swap_entries()
/swap_row()
/swap_column()
.
Rows/Columns of matrices can be reversed with the functions reverse_rows()
/reverse_columns()
and
sorted with the functions sort_by_rows()
/sort_by_columns()
.
Coefficients of polynomials and ring elements can be set manually with the function set_coeff()
.
use qfall_math::{
integer::{MatZ, PolyOverZ},
traits::*,
};
use std::str::FromStr;
fn manipulation() {
let mut matz_1 = MatZ::from_str("[[1,2,3],[4,5,6]]").unwrap();
let matz_2 = MatZ::from_str("[[5,2,7],[4,2,1]]").unwrap();
let mut polyz = PolyOverZ::from_str("4 -1 0 1 1").unwrap();
matz_1.set_entry(1, 2, 8).unwrap();
matz_1.set_row(0, &matz_2, 1).unwrap();
polyz.set_coeff(2, 6).unwrap();
}
Note that for all set_*()
functions, there is a corresponding get_*()
function.
MatZq, PolyZq, PolynomialRingZq and their Moduli
Just like Zq
, the advanced types MatZq
, PolyZq
and PolynomialRingZq
have special roles
since they do not only contain a value but also a context object represented by their moduli.
A modulus object is of type Modulus
or in the case of a PolynomialRingZq
of type ModulusPolynomialRingZq
.
The modulus Modulus
can be instantiated from a Z
greater or equal to two, and the modulus ModulusPolynomialRingZq
can be instantiated from a PolyZq
.
use qfall_math::integer_mod_q::{Modulus, ModulusPolynomialRingZq, PolyOverZq};
use std::str::FromStr;
fn instantiate_moduli() {
let modulus = Modulus::from(42);
let polyzq = PolyOverZq::from_str("4 1 0 0 1 mod 17").unwrap();
let modulus_poly = ModulusPolynomialRingZq::from(&polyzq);
}
Both moduli can be shared among different values and, if shared, reduce runtime and reduce storage usage, since only the reference counter goes up, and the modulus is not cloned.
use qfall_math::{
integer::MatZ,
integer_mod_q::{MatZq, Modulus, Zq},
};
use std::str::FromStr;
fn shared_moduli() {
let modulus = Modulus::from(42);
let matz_1 = MatZ::from_str("[[1,2,3],[4,5,6]]]").unwrap();
let matz_2 = MatZ::from_str("[[17,42],[89, 100]]]").unwrap();
let zq_1 = Zq::from((17, 42));
let zq_2 = Zq::from((24, 42));
let matzq_1 = MatZq::from_mat_z_modulus(&matz_1, &modulus);
let matzq_2 = MatZq::from_mat_z_modulus(&matz_2, &modulus);
}
Matrices as Vectors
We do not have explicit vector types like VecZ
, VecZq
and VecQ
, but all matrices can serve as vectors if they have the correct dimensions.
So a MatZ
matrix with dimensions 1 x n
is a row vector and a matrix
with dimensions n x 1
a column vector.
This property can be checked with the function is_vector()
.
use qfall_math::{
integer::{MatPolyOverZ, MatZ},
integer_mod_q::{MatPolynomialRingZq, ModulusPolynomialRingZq},
};
use std::str::FromStr;
fn vectors() {
let vecz = MatZ::from_str("[[1/2,2,3/4]]").unwrap();
let poly_vec = MatPolyOverZ::from_str("[[4 -1 0 1 1],[2 12 4]]").unwrap();
let modulus = ModulusPolynomialRingZq::from_str("4 1 0 0 1 mod 42").unwrap();
let poly_ring_vec =
MatPolynomialRingZq::from_poly_over_z_modulus_polynomial_ring_zq(&poly_vec, &modulus);
let is_vector = vecz.is_vector();
let is_vector = poly_vec.is_vector();
let is_vector = poly_ring_vec.is_vector();
let dot_product = vecz.dot_product(&vecz);
let norm = vecz.norm_eucl_sqrd();
}
Note that matrices with dimensions 1 x 1
are seen as both row and column vectors.
Converting types
All reasonable types can be converted between one another,
e.g. we can define a MatQ
from a MatZ
or a PolyQ
from a PolyZ
.
use qfall_math::{
integer::{MatZ, PolyOverZ},
rational::{MatQ, PolyOverQ},
};
use std::str::FromStr;
fn conversions() {
let matz = MatZ::from_str("[[1,2],[3,4]]").unwrap();
let matq = MatQ::from(&matz);
let polyz = PolyOverZ::from_str("4 1 2 3 4").unwrap();
let polyq = PolyOverQ::from(&polyz);
}
Arithmetics
All advanced types (except moduli) support basic arithmetics. Among these are multiplication, addition and subtraction.
use qfall_math::{
integer::PolyOverZ,
integer_mod_q::{ModulusPolynomialRingZq, PolynomialRingZq},
rational::MatQ,
};
use std::str::FromStr;
fn basic_arithmetics() {
let matq = MatQ::from_str("[[1/2,2,3/4],[4,5/10,6]]").unwrap();
let polyz = PolyOverZ::from_str("4 -1 0 1 1").unwrap();
let polyz_2 = PolyOverZ::from_str("4 -1 0 1 2").unwrap();
let modulus = ModulusPolynomialRingZq::from_str("4 1 0 0 1 mod 42").unwrap();
let poly_ring = PolynomialRingZq::from((&polyz, &modulus));
let add = &matq + &matq;
let sub = &polyz_2 - &polyz;
let mul = &poly_ring * &poly_ring;
}
Printing your Results
You can print the values of all advanced types with the print!
or println!
command or
convert them into strings with .to_string()
.
use qfall_math::{
integer::PolyOverZ,
integer_mod_q::{ModulusPolynomialRingZq, PolynomialRingZq},
rational::MatQ,
};
use std::str::FromStr;
fn print() {
let matq = MatQ::from_str("[[1/2,2,3/4],[4,5/10,6]]").unwrap();
let polyz = PolyOverZ::from_str("4 -1 0 1 1").unwrap();
let modulus = ModulusPolynomialRingZq::from_str("4 1 0 0 1 mod 42").unwrap();
let poly_ring = PolynomialRingZq::from((&polyz, &modulus));
// print them directly
println!("{matq}");
println!("{polyz}");
println!("{modulus}");
println!("{poly_ring}");
// turn them into a string first
let matq_string = matq.to_string();
let polyz_string = polyz.to_string();
let modulus_string = modulus.to_string();
let poly_ring_string = poly_ring.to_string();
println!("{}", matq_string);
println!("{}", polyz_string);
println!("{}", modulus_string);
println!("{}", poly_ring_string);
}