use super::ffi;
use super::integer::FlintInteger;
pub(crate) struct FlintMat {
inner: ffi::FmpzMatStruct,
}
impl FlintMat {
pub(crate) fn new(rows: usize, cols: usize) -> Self {
assert!(rows <= i64::MAX as usize && cols <= i64::MAX as usize);
#[cfg(not(flint3_stride))]
let mut inner = ffi::FmpzMatStruct {
entries: std::ptr::null_mut(),
r: 0,
c: 0,
rows: std::ptr::null_mut(),
};
#[cfg(flint3_stride)]
let mut inner = ffi::FmpzMatStruct {
entries: std::ptr::null_mut(),
r: 0,
c: 0,
stride: 0,
};
unsafe { ffi::fmpz_mat_init(&mut inner, rows as ffi::slong, cols as ffi::slong) };
Self { inner }
}
pub(crate) fn rows(&self) -> usize {
self.inner.r as usize
}
pub(crate) fn cols(&self) -> usize {
self.inner.c as usize
}
unsafe fn entry_ptr(&mut self, i: usize, j: usize) -> *mut ffi::fmpz {
debug_assert!(i < self.rows() && j < self.cols());
#[cfg(not(flint3_stride))]
{
let row_start = *self.inner.rows.add(i);
row_start.add(j)
}
#[cfg(flint3_stride)]
{
let stride = self.inner.stride as usize;
self.inner.entries.add(i * stride + j)
}
}
pub(crate) unsafe fn entry_const(&self, i: usize, j: usize) -> *const ffi::fmpz {
debug_assert!(i < self.rows() && j < self.cols());
#[cfg(not(flint3_stride))]
{
let row_start = *self.inner.rows.add(i);
row_start.add(j)
}
#[cfg(flint3_stride)]
{
let stride = self.inner.stride as usize;
self.inner.entries.add(i * stride + j)
}
}
pub(crate) fn set_entry(&mut self, i: usize, j: usize, v: &FlintInteger) {
unsafe {
let e = self.entry_ptr(i, j);
ffi::fmpz_set(e, v.inner_ptr());
}
}
pub(crate) fn get_flint(&self, i: usize, j: usize) -> FlintInteger {
let mut out = FlintInteger::new();
unsafe {
ffi::fmpz_set(out.inner_mut_ptr(), self.entry_const(i, j));
}
out
}
pub(crate) fn hnf_transform(&self, h: &mut FlintMat, u: &mut FlintMat) {
unsafe {
ffi::fmpz_mat_hnf_transform(&mut h.inner, &mut u.inner, &self.inner);
}
}
}
#[cfg(test)]
impl FlintMat {
pub(crate) fn snf_diagonal(&self, s: &mut FlintMat) {
unsafe {
ffi::fmpz_mat_snf(&mut s.inner, &self.inner);
}
}
pub(crate) fn is_in_hnf(&self) -> bool {
unsafe { ffi::fmpz_mat_is_in_hnf(&self.inner) != 0 }
}
pub(crate) fn is_in_snf(&self) -> bool {
unsafe { ffi::fmpz_mat_is_in_snf(&self.inner) != 0 }
}
pub(crate) fn equals(&self, other: &FlintMat) -> bool {
unsafe { ffi::fmpz_mat_equal(&self.inner, &other.inner) != 0 }
}
}
impl Drop for FlintMat {
fn drop(&mut self) {
unsafe { ffi::fmpz_mat_clear(&mut self.inner) };
}
}