use super::Factorization;
use crate::integer::Z;
use flint_sys::fmpz_factor::{_fmpz_factor_append, fmpz_factor_get_fmpz};
impl<Integer: Into<Z>> From<Integer> for Factorization {
fn from(factor: Integer) -> Self {
let factor = factor.into();
let mut out = Self::default();
unsafe { _fmpz_factor_append(&mut out.factors, &factor.value, 1) };
out
}
}
impl<Integer: Into<Z>> From<(Integer, Integer)> for Factorization {
fn from(factors: (Integer, Integer)) -> Self {
let factor_1 = factors.0.into();
let factor_2 = factors.1.into();
let mut out = Self::default();
unsafe { _fmpz_factor_append(&mut out.factors, &factor_1.value, 1) };
unsafe { _fmpz_factor_append(&mut out.factors, &factor_2.value, 1) };
out
}
}
impl From<&Factorization> for Vec<(Z, u64)> {
fn from(factors: &Factorization) -> Self {
let mut out = Vec::with_capacity(factors.factors.num as usize + 1);
if factors.factors.sign == -1 {
out.push((Z::MINUS_ONE, 1));
}
for i in 0..factors.factors.num {
let mut factor = Z::default();
unsafe { fmpz_factor_get_fmpz(&mut factor.value, &factors.factors, i) };
let exp = unsafe { *factors.factors.exp.offset(i.try_into().unwrap()) };
out.push((factor, exp));
}
if out.is_empty() && factors.factors.sign == 1 {
out.push((Z::ONE, 1));
}
out
}
}
impl From<&Vec<(Z, u64)>> for Factorization {
fn from(factors: &Vec<(Z, u64)>) -> Self {
let mut out = Factorization::default();
for (factor, exponent) in factors {
unsafe { _fmpz_factor_append(&mut out.factors, &factor.value, *exponent) };
}
out
}
}
#[cfg(test)]
mod tests_from_one {
use crate::utils::Factorization;
#[test]
fn from_one() {
let fac = Factorization::from(8);
assert_eq!("[(8, 1)]", fac.to_string());
}
#[test]
fn from_one_large() {
let fac = Factorization::from(i64::MAX);
assert_eq!(format!("[({}, 1)]", i64::MAX), fac.to_string());
}
#[test]
fn from_one_negative() {
let fac = Factorization::from(-8);
assert_eq!("[(-8, 1)]", fac.to_string());
}
#[test]
fn from_one_one() {
let fac = Factorization::from(1);
assert_eq!("[(1, 1)]", fac.to_string());
}
#[test]
fn from_one_zero() {
let fac = Factorization::from(0);
assert_eq!("[(0, 1)]", fac.to_string());
}
}
#[cfg(test)]
mod tests_from_two {
use crate::utils::Factorization;
#[test]
fn from_two() {
let fac = Factorization::from((8, 3));
assert_eq!("[(8, 1), (3, 1)]", fac.to_string());
}
#[test]
fn from_two_large() {
let fac = Factorization::from((i64::MAX, 3));
assert_eq!(format!("[({}, 1), (3, 1)]", i64::MAX), fac.to_string());
}
#[test]
fn from_two_negative() {
let fac = Factorization::from((-8, -3));
assert_eq!("[(-8, 1), (-3, 1)]", fac.to_string());
}
#[test]
fn from_two_zero_one() {
let fac = Factorization::from((0, 1));
assert_eq!("[(0, 1), (1, 1)]", fac.to_string());
}
#[test]
fn from_two_unrefined() {
let fac = Factorization::from((8, 8));
assert_eq!("[(8, 1), (8, 1)]", fac.to_string());
}
}
#[cfg(test)]
mod tests_from_factorization_for_vector {
use crate::{integer::Z, utils::Factorization};
#[test]
fn from_factorization() {
let fac = Factorization::from((4, 3));
let vec = Vec::<(Z, u64)>::from(&fac);
assert_eq!(Z::from(4), vec[0].0);
assert_eq!(Z::from(3), vec[1].0);
assert_eq!(1, vec[0].1);
assert_eq!(1, vec[1].1);
}
#[test]
fn from_factorization_large() {
let fac = Factorization::from((i64::MAX, 3));
let vec = Vec::<(Z, u64)>::from(&fac);
assert_eq!(Z::from(i64::MAX), vec[0].0);
assert_eq!(Z::from(3), vec[1].0);
assert_eq!(1, vec[0].1);
assert_eq!(1, vec[1].1);
}
#[test]
fn from_factorization_negative() {
let fac = Factorization::from((-i64::MAX, 3));
let vec = Vec::<(Z, u64)>::from(&fac);
assert_eq!(Z::from(-i64::MAX), vec[0].0);
assert_eq!(Z::from(3), vec[1].0);
assert_eq!(1, vec[0].1);
assert_eq!(1, vec[1].1);
}
#[test]
fn from_factorization_one_entry() {
let fac = Factorization::from(4);
let vec = Vec::<(Z, u64)>::from(&fac);
assert_eq!(Z::from(4), vec[0].0);
assert_eq!(1, vec[0].1);
}
#[test]
fn from_factorization_refined() {
let mut fac = Factorization::from((-1200, 20));
fac.refine();
let vec = Vec::<(Z, u64)>::from(&fac);
assert_eq!(Z::MINUS_ONE, vec[0].0);
assert_eq!(Z::from(3), vec[1].0);
assert_eq!(Z::from(20), vec[2].0);
assert_eq!(1, vec[0].1);
assert_eq!(1, vec[1].1);
assert_eq!(3, vec[2].1);
}
#[test]
fn from_factorization_one() {
let mut fac = Factorization::default();
fac.refine();
let vec = Vec::<(Z, u64)>::from(&fac);
assert_eq!(Z::ONE, vec[0].0);
assert_eq!(1, vec[0].1);
}
#[test]
fn from_factorization_minus_one() {
let mut fac = Factorization::from(-1);
fac.refine();
let vec = Vec::<(Z, u64)>::from(&fac);
assert_eq!(Z::MINUS_ONE, vec[0].0);
assert_eq!(1, vec[0].1);
}
#[test]
fn from_factorization_zero() {
let mut fac_1 = Factorization::from(0);
let mut fac_2 = Factorization::from((0, 1));
fac_1.refine();
fac_2.refine();
let vec_1 = Vec::<(Z, u64)>::from(&fac_1);
let vec_2 = Vec::<(Z, u64)>::from(&fac_2);
assert!(vec_1.is_empty());
assert!(vec_2.is_empty());
}
#[test]
fn doc_test() {
let fac = Factorization::from(10);
let _vec = Vec::<(Z, u64)>::from(&fac);
}
}
#[cfg(test)]
mod tests_from_vector_for_factorization {
use crate::{integer::Z, utils::Factorization};
#[test]
fn from_vector() {
let vec: Vec<(Z, u64)> = vec![(Z::from(3), 2), (Z::from(8), 2)];
let fac = Factorization::from(&vec);
assert_eq!("[(3, 2), (8, 2)]", fac.to_string());
}
#[test]
fn from_vector_large() {
let vec: Vec<(Z, u64)> = vec![(Z::from(i64::MAX), 2), (Z::from(8), 2)];
let fac = Factorization::from(&vec);
assert_eq!(format!("[({}, 2), (8, 2)]", i64::MAX), fac.to_string());
}
#[test]
fn from_vector_negative() {
let vec: Vec<(Z, u64)> = vec![(Z::from(-i64::MAX), 2), (Z::from(-8), 2)];
let fac = Factorization::from(&vec);
assert_eq!(format!("[(-{}, 2), (-8, 2)]", i64::MAX), fac.to_string());
}
#[test]
fn from_vector_one_entry() {
let vec: Vec<(Z, u64)> = vec![(Z::from(3), 2)];
let fac = Factorization::from(&vec);
assert_eq!("[(3, 2)]", fac.to_string());
}
#[test]
fn from_vector_no_entry() {
let vec: Vec<(Z, u64)> = vec![];
let fac = Factorization::from(&vec);
assert_eq!("[(1, 1)]", fac.to_string());
}
#[test]
fn from_vector_zero() {
let vec: Vec<(Z, u64)> = vec![(Z::ZERO, 1)];
let fac = Factorization::from(&vec);
assert_eq!("[(0, 1)]", fac.to_string());
}
}