mod ops;
mod conv;
use crate::*;
use flint_sys::fq_default as fq;
use std::ffi::CString;
use std::fmt;
use std::hash::{Hash, Hasher};
use std::mem::{ManuallyDrop, MaybeUninit};
use std::rc::Rc;
pub(crate) struct FqCtx(fq::fq_default_ctx_struct);
impl fmt::Debug for FqCtx {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("FqCtx")
.field("type_", &self.0.type_)
.finish()
}
}
impl Drop for FqCtx {
fn drop(&mut self) {
unsafe {
fq::fq_default_ctx_clear(&mut self.0);
}
}
}
impl FqCtx {
#[inline]
pub fn new<P, K>(p: P, k: K) -> Self
where
P: AsRef<Integer>,
K: TryInto<i64>,
<K as TryInto<i64>>::Error: fmt::Debug
{
let p = p.as_ref();
assert!(p.is_prime());
unsafe { Self::new_unchecked(p, k) }
}
pub unsafe fn new_unchecked<P, K>(p: P, k: K) -> Self
where
P: AsRef<Integer>,
K: TryInto<i64>,
<K as TryInto<i64>>::Error: fmt::Debug
{
let k = k.try_into().expect("Exponent too large!");
assert!(k > 0);
let var = CString::new("o").unwrap();
let mut ctx = MaybeUninit::uninit();
fq::fq_default_ctx_init(
ctx.as_mut_ptr(),
p.as_ref().as_ptr(),
k,
var.as_ptr()
);
FqCtx(ctx.assume_init())
}
}
#[derive(Clone, Debug)]
pub struct FinFldCtx {
inner: Rc<FqCtx>,
}
impl Eq for FinFldCtx {}
impl PartialEq for FinFldCtx {
fn eq(&self, rhs: &FinFldCtx) -> bool {
Rc::ptr_eq(&self.inner, &rhs.inner) || self.modulus() == rhs.modulus()
}
}
impl fmt::Display for FinFldCtx {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(
f,
"Context for finite field of order {}^{}",
self.prime(),
self.degree()
)
}
}
impl Hash for FinFldCtx {
fn hash<H: Hasher>(&self, state: &mut H) {
self.modulus().hash(state)
}
}
impl FinFldCtx {
#[inline]
pub fn new<P, K>(p: P, k: K) -> Self
where
P: Into<Integer>,
K: TryInto<i64>,
<K as TryInto<i64>>::Error: fmt::Debug
{
FinFldCtx {
inner: Rc::new(FqCtx::new(p.into(), k))
}
}
#[inline]
pub unsafe fn new_unchecked<P, K>(p: P, k: K) -> Self
where
P: Into<Integer>,
K: TryInto<i64>,
<K as TryInto<i64>>::Error: fmt::Debug
{
FinFldCtx {
inner: Rc::new(FqCtx::new_unchecked(p.into(), k))
}
}
#[inline]
pub fn as_ptr(&self) -> &fq::fq_default_ctx_struct {
&self.inner.0
}
#[inline]
pub fn modulus(&self) -> IntModPoly {
let ctx = IntModCtx::new(self.prime());
let mut res = IntModPoly::zero(&ctx);
unsafe {
fq::fq_default_ctx_modulus(res.as_mut_ptr(), self.as_ptr());
}
res
}
#[inline]
pub fn prime(&self) -> Integer {
let mut res = Integer::default();
unsafe {
fq::fq_default_ctx_prime(res.as_mut_ptr(), self.as_ptr());
}
res
}
#[inline]
pub fn degree(&self) -> i64 {
unsafe { fq::fq_default_ctx_degree(self.as_ptr()) }
}
#[inline]
pub fn order(&self) -> Integer {
let mut res = Integer::default();
unsafe {
fq::fq_default_ctx_order(res.as_mut_ptr(), self.as_ptr());
}
res
}
}
pub struct FinFldElem {
inner: fq::fq_default_struct,
ctx: FinFldCtx,
}
impl AsRef<FinFldElem> for FinFldElem {
fn as_ref(&self) -> &FinFldElem {
self
}
}
impl Clone for FinFldElem {
fn clone(&self) -> Self {
let mut res = FinFldElem::zero(self.context());
unsafe {
fq::fq_default_set(res.as_mut_ptr(), self.as_ptr(), self.ctx_as_ptr());
}
res
}
}
impl fmt::Debug for FinFldElem {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("FinFldElem")
.field("ctx", &self.ctx)
.finish()
}
}
impl fmt::Display for FinFldElem {
#[inline]
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
IntModPoly::from(self).fmt(f)
}
}
impl Drop for FinFldElem {
fn drop(&mut self) {
unsafe { fq::fq_default_clear(self.as_mut_ptr(), self.ctx_as_ptr()) }
}
}
impl Hash for FinFldElem {
fn hash<H: Hasher>(&self, state: &mut H) {
self.context().hash(state);
IntPoly::from(self).hash(state);
}
}
impl<T: Into<IntPoly>> NewCtx<T, FinFldCtx> for FinFldElem {
fn new(src: T, ctx: &FinFldCtx) -> Self {
let mut res = FinFldElem::zero(ctx);
unsafe {
fq::fq_default_set_fmpz_poly(
res.as_mut_ptr(),
src.into().as_ptr(),
ctx.as_ptr()
);
}
res
}
}
impl NewCtx<&IntPoly, FinFldCtx> for FinFldElem {
fn new(src: &IntPoly, ctx: &FinFldCtx) -> Self {
let mut res = FinFldElem::zero(ctx);
unsafe {
fq::fq_default_set_fmpz_poly(
res.as_mut_ptr(),
src.as_ptr(),
ctx.as_ptr()
);
}
res
}
}
impl FinFldElem {
#[inline]
pub fn zero(ctx: &FinFldCtx) -> FinFldElem {
let mut z = MaybeUninit::uninit();
unsafe {
fq::fq_default_init(z.as_mut_ptr(), ctx.as_ptr());
FinFldElem::from_raw(z.assume_init(), ctx.clone())
}
}
#[inline]
pub fn one(ctx: &FinFldCtx) -> FinFldElem {
let mut res = FinFldElem::zero(ctx);
unsafe {
fq::fq_default_one(res.as_mut_ptr(), ctx.as_ptr());
}
res
}
#[inline]
pub fn zero_assign(&mut self) {
unsafe { fq::fq_default_zero(self.as_mut_ptr(), self.ctx_as_ptr()) }
}
#[inline]
pub fn one_assign(&mut self) {
unsafe { fq::fq_default_one(self.as_mut_ptr(), self.ctx_as_ptr()) }
}
#[inline]
pub const fn as_ptr(&self) -> *const fq::fq_default_struct {
&self.inner
}
#[inline]
pub fn as_mut_ptr(&mut self) -> *mut fq::fq_default_struct {
&mut self.inner
}
#[inline]
pub fn ctx_as_ptr(&self) -> &fq::fq_default_ctx_struct {
self.context().as_ptr()
}
#[inline]
pub const unsafe fn from_raw(
inner: fq::fq_default_struct,
ctx: FinFldCtx
) -> FinFldElem {
FinFldElem { inner, ctx }
}
#[inline]
pub const fn into_raw(self) -> fq::fq_default_struct {
let inner = self.inner;
let _ = ManuallyDrop::new(self);
inner
}
#[inline]
pub const fn context(&self) -> &FinFldCtx {
&self.ctx
}
#[inline]
pub fn modulus(&self) -> IntModPoly {
self.context().modulus()
}
#[inline]
pub fn prime(&self) -> Integer {
self.context().prime()
}
#[inline]
pub fn degree(&self) -> i64 {
self.context().degree()
}
#[inline]
pub fn order(&self) -> Integer {
self.context().order()
}
}