mod conv;
use crate::{NewCtx, RatPoly};
use flint_sys::fmpq_poly::{fmpq_poly_struct, fmpq_poly_set};
use antic_sys::{
nf::*,
nf_elem::*
};
use std::ffi::{CStr, CString};
use std::fmt;
use std::hash::{Hash, Hasher};
use std::mem::{ManuallyDrop, MaybeUninit};
use std::rc::Rc;
#[derive(Debug)]
pub(crate) struct NfCtx(nf_struct);
impl Drop for NfCtx {
fn drop(&mut self) {
unsafe {
nf_clear(&mut self.0);
}
}
}
impl NfCtx {
pub fn new<T: AsRef<RatPoly>>(pol: T) -> Self {
let mut ctx = MaybeUninit::uninit();
unsafe {
nf_init(ctx.as_mut_ptr(), pol.as_ref().as_ptr());
NfCtx(ctx.assume_init())
}
}
}
#[derive(Clone, Debug)]
pub struct NumFldCtx {
inner: Rc<NfCtx>
}
impl Eq for NumFldCtx {}
impl PartialEq for NumFldCtx {
fn eq(&self, rhs: &NumFldCtx) -> bool {
Rc::ptr_eq(&self.inner, &rhs.inner)
|| (self.defining_polynomial() == rhs.defining_polynomial())
}
}
impl fmt::Display for NumFldCtx {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "Context for number field with defining polynomial {}",
self.defining_polynomial())
}
}
impl Hash for NumFldCtx {
fn hash<H: Hasher>(&self, state: &mut H) {
self.defining_polynomial().hash(state)
}
}
impl NumFldCtx {
#[inline]
pub fn new<T: Into<RatPoly>>(pol: T) -> Self {
NumFldCtx {
inner: Rc::new(NfCtx::new(pol.into()))
}
}
#[inline]
pub fn as_ptr(&self) -> *const nf_struct {
&self.inner.0
}
pub fn poly_as_ptr(&self) -> *const fmpq_poly_struct {
&self.inner.0.pol[0]
}
#[inline]
pub fn defining_polynomial(&self) -> RatPoly {
let mut res = RatPoly::default();
unsafe { fmpq_poly_set(res.as_mut_ptr(), self.poly_as_ptr()); }
res
}
}
pub struct NumFldElem {
pub(crate) inner: nf_elem_struct,
pub(crate) ctx: NumFldCtx
}
impl AsRef<NumFldElem> for NumFldElem {
fn as_ref(&self) -> &NumFldElem {
self
}
}
impl Clone for NumFldElem {
#[inline]
fn clone(&self) -> Self {
let mut res = NumFldElem::zero(self.context());
unsafe {
nf_elem_set_fmpq_poly(
res.as_mut_ptr(),
self.poly_as_ptr(),
self.ctx_as_ptr()
);
}
res
}
}
impl fmt::Display for NumFldElem {
#[inline]
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
let var = CString::new("x").unwrap();
unsafe {
let c_str = CStr::from_ptr(
nf_elem_get_str_pretty(
self.as_ptr(),
var.as_ptr(),
self.ctx_as_ptr()
)
);
write!(f, "{}", c_str.to_str().unwrap())
}
}
}
impl Drop for NumFldElem {
#[inline]
fn drop(&mut self) {
unsafe { nf_elem_clear(self.as_mut_ptr(), self.ctx_as_ptr()) }
}
}
impl<T: Into<RatPoly>> NewCtx<T, NumFldCtx> for NumFldElem {
fn new(src: T, ctx: &NumFldCtx) -> Self {
let mut res = NumFldElem::zero(&ctx);
unsafe {
nf_elem_set_fmpq_poly(
res.as_mut_ptr(),
src.into().as_ptr(),
ctx.as_ptr()
);
}
res
}
}
impl NewCtx<&RatPoly, NumFldCtx> for NumFldElem {
fn new(src: &RatPoly, ctx: &NumFldCtx) -> Self {
let mut res = NumFldElem::zero(&ctx);
unsafe {
nf_elem_set_fmpq_poly(
res.as_mut_ptr(),
src.as_ptr(),
ctx.as_ptr()
);
}
res
}
}
impl NumFldElem {
#[inline]
pub fn zero(ctx: &NumFldCtx) -> Self {
let mut z = MaybeUninit::uninit();
unsafe {
nf_elem_init(z.as_mut_ptr(), ctx.as_ptr());
NumFldElem::from_raw(z.assume_init(), ctx.clone())
}
}
#[inline]
pub const fn as_ptr(&self) -> *const nf_elem_struct {
&self.inner
}
#[inline]
pub fn as_mut_ptr(&mut self) -> *mut nf_elem_struct {
&mut self.inner
}
#[inline]
pub fn ctx_as_ptr(&self) -> *const nf_struct {
self.context().as_ptr()
}
#[inline]
pub fn poly_as_ptr(&self) -> *const fmpq_poly_struct {
self.context().poly_as_ptr()
}
#[inline]
pub const unsafe fn from_raw(inner: nf_elem_struct, ctx: NumFldCtx) -> Self {
NumFldElem { inner, ctx }
}
#[inline]
pub const fn into_raw(self) -> nf_elem_struct {
let ret = self.inner;
let _ = ManuallyDrop::new(self);
ret
}
#[inline]
pub const fn context(&self) -> &NumFldCtx {
&self.ctx
}
#[inline]
pub fn defining_polynomial(&self) -> RatPoly {
self.context().defining_polynomial()
}
}