use super::Zq;
use crate::{
integer::{Z, fmpz_helpers::distance},
traits::AsInteger,
};
use flint_sys::fmpz::fmpz;
const ZERO_FMPZ: fmpz = fmpz(0);
pub(crate) fn length(value: &fmpz, modulus: &fmpz) -> Z {
let distance_zero = distance(&ZERO_FMPZ, value);
let distance_modulus = distance(value, modulus);
if distance_zero < distance_modulus {
distance_zero
} else {
distance_modulus
}
}
unsafe impl AsInteger for Zq {
unsafe fn into_fmpz(self) -> fmpz {
unsafe { AsInteger::into_fmpz(self.value) }
}
fn get_fmpz_ref(&self) -> Option<&fmpz> {
AsInteger::get_fmpz_ref(&self.value)
}
}
unsafe impl AsInteger for &Zq {
unsafe fn into_fmpz(self) -> fmpz {
unsafe { AsInteger::into_fmpz(&self.value) }
}
fn get_fmpz_ref(&self) -> Option<&fmpz> {
AsInteger::get_fmpz_ref(&self.value)
}
}
#[cfg(test)]
mod test_as_integer_zq {
use super::*;
#[test]
fn small_into_fmpz() {
let zq = Zq::from((42, 100));
let copy_1 = unsafe { Z::from_fmpz((&zq).into_fmpz()) };
let copy_2 = unsafe { Z::from_fmpz(zq.into_fmpz()) };
assert_eq!(copy_1, Z::from(42));
assert_eq!(copy_2, Z::from(42));
}
#[test]
fn large_into_fmpz() {
let z = Zq::from((u64::MAX - 1, u64::MAX));
let copy_1 = unsafe { Z::from_fmpz((&z).into_fmpz()) };
let copy_2 = unsafe { Z::from_fmpz(z.into_fmpz()) };
assert_eq!(copy_1, Z::from(u64::MAX - 1));
assert_eq!(copy_2, Z::from(u64::MAX - 1));
}
#[test]
fn memory_safety() {
let zq = Zq::from((i64::MAX - 1, i64::MAX));
let value = unsafe { (&zq).into_fmpz() };
assert_ne!(value.0, zq.value.value.0);
}
#[test]
#[allow(clippy::needless_borrow)]
fn get_ref_small() {
let zq = Zq::from((10, 100));
let zq_ref_value_1 = zq.get_fmpz_ref().unwrap();
let zq_ref_value_2 = (&zq).get_fmpz_ref().unwrap();
assert_eq!(zq.value.value.0, zq_ref_value_1.0);
assert_eq!(zq.value.value.0, zq_ref_value_2.0);
}
#[test]
#[allow(clippy::needless_borrow)]
fn get_ref_large() {
let zq = Zq::from((i64::MAX - 1, i64::MAX));
let zq_ref_value_1 = zq.get_fmpz_ref().unwrap();
let zq_ref_value_2 = (&zq).get_fmpz_ref().unwrap();
assert_eq!(zq.value.value.0, zq_ref_value_1.0);
assert_eq!(zq.value.value.0, zq_ref_value_2.0);
}
}
#[cfg(test)]
mod test_length {
use super::*;
use crate::integer::Z;
#[test]
fn small_values() {
let modulus = fmpz(15);
let pos_1 = fmpz(10);
let pos_2 = fmpz(7);
let zero = fmpz(0);
assert_eq!(Z::from(5), length(&pos_1, &modulus));
assert_eq!(Z::from(7), length(&pos_2, &modulus));
assert_eq!(Z::ZERO, length(&zero, &modulus));
assert_eq!(Z::ZERO, length(&modulus, &modulus));
}
#[test]
fn large_values() {
let modulus = Z::from(u64::MAX);
let pos_1 = Z::from(i64::MAX);
let pos_2 = Z::from(u64::MAX - 58);
assert_eq!(&Z::from(i64::MAX), &length(&pos_1.value, &modulus.value));
assert_eq!(Z::from(58), length(&pos_2.value, &modulus.value));
}
}