#[cfg(feature = "integer")]
use crate::Integer;
#[cfg(feature = "rational")]
use crate::Rational;
use crate::complex::MiniComplex;
use crate::ext::xmpfr;
use crate::ext::xmpfr::{EXP_ZERO, OptFloat, ordering1, raw_round};
use crate::float::Round;
use crate::misc;
use crate::misc::VecLike;
use crate::{Complex, Float};
use az::StrictCast;
use core::cmp::Ordering;
use core::ffi::{c_int, c_long, c_ulong};
use core::mem::MaybeUninit;
use core::ptr::NonNull;
use gmp_mpfr_sys::gmp;
use gmp_mpfr_sys::gmp::limb_t;
use gmp_mpfr_sys::mpc;
use gmp_mpfr_sys::mpc::{mpc_t, rnd_t};
use gmp_mpfr_sys::mpfr::{mpfr_t, prec_t};
pub trait OptComplex: Copy {
const IS_SOME: bool;
type Part: OptFloat;
fn mpc(self) -> *const mpc_t;
fn mpc_or(self, default: *mut mpc_t) -> *const mpc_t;
fn parts(self) -> (Self::Part, Self::Part);
fn unwrap<'a>(self) -> &'a Complex
where
Self: 'a;
}
impl OptComplex for () {
const IS_SOME: bool = false;
type Part = ();
#[inline(always)]
fn mpc(self) -> *const mpc_t {
unreachable!("unwrapping ()");
}
#[inline(always)]
fn mpc_or(self, default: *mut mpc_t) -> *const mpc_t {
default.cast_const()
}
#[inline(always)]
fn parts(self) -> ((), ()) {
((), ())
}
#[inline(always)]
fn unwrap<'a>(self) -> &'a Complex
where
Self: 'a,
{
unreachable!("unwrapping ()");
}
}
impl<'a> OptComplex for &'a Complex {
const IS_SOME: bool = true;
type Part = &'a Float;
#[inline(always)]
fn mpc(self) -> *const mpc_t {
self.as_raw()
}
#[inline(always)]
fn mpc_or(self, _default: *mut mpc_t) -> *const mpc_t {
self.as_raw()
}
#[inline(always)]
fn parts(self) -> (&'a Float, &'a Float) {
(self.real(), self.imag())
}
#[inline(always)]
fn unwrap<'b>(self) -> &'b Complex
where
Self: 'b,
{
self
}
}
pub type Round2 = (Round, Round);
pub const NEAREST2: Round2 = (Round::Nearest, Round::Nearest);
pub type Ordering2 = (Ordering, Ordering);
#[inline]
pub fn raw_round2(round: Round2) -> rnd_t {
match (round.0, round.1) {
(Round::Nearest, Round::Nearest) => mpc::RNDNN,
(Round::Nearest, Round::Zero) => mpc::RNDNZ,
(Round::Nearest, Round::Up) => mpc::RNDNU,
(Round::Nearest, Round::Down) => mpc::RNDND,
(Round::Nearest, Round::AwayZero) => mpc::RNDNA,
(Round::Zero, Round::Nearest) => mpc::RNDZN,
(Round::Zero, Round::Zero) => mpc::RNDZZ,
(Round::Zero, Round::Up) => mpc::RNDZU,
(Round::Zero, Round::Down) => mpc::RNDZD,
(Round::Zero, Round::AwayZero) => mpc::RNDZA,
(Round::Up, Round::Nearest) => mpc::RNDUN,
(Round::Up, Round::Zero) => mpc::RNDUZ,
(Round::Up, Round::Up) => mpc::RNDUU,
(Round::Up, Round::Down) => mpc::RNDUD,
(Round::Up, Round::AwayZero) => mpc::RNDUA,
(Round::Down, Round::Nearest) => mpc::RNDDN,
(Round::Down, Round::Zero) => mpc::RNDDZ,
(Round::Down, Round::Up) => mpc::RNDDU,
(Round::Down, Round::Down) => mpc::RNDDD,
(Round::Down, Round::AwayZero) => mpc::RNDDA,
(Round::AwayZero, Round::Nearest) => mpc::RNDAN,
(Round::AwayZero, Round::Zero) => mpc::RNDAZ,
(Round::AwayZero, Round::Up) => mpc::RNDAU,
(Round::AwayZero, Round::Down) => mpc::RNDAD,
(Round::AwayZero, Round::AwayZero) => mpc::RNDAA,
}
}
#[inline]
pub fn ordering2(ord: c_int) -> Ordering2 {
let first = mpc::INEX_RE(ord).cmp(&0);
let second = mpc::INEX_IM(ord).cmp(&0);
(first, second)
}
#[inline]
fn ordering4(ord: c_int) -> (Ordering2, Ordering2) {
(ordering2(mpc::INEX1(ord)), ordering2(mpc::INEX2(ord)))
}
macro_rules! unsafe_wrap {
(fn $fn:ident($($op:ident: $O:ident),* $(; $param:ident: $T:ty)*) -> $deleg:path) => {
#[inline]
pub fn $fn<$($O: OptComplex),*>(
rop: &mut Complex,
$($op: $O,)*
$($param: $T,)*
rnd: Round2,
) -> Ordering2 {
let rop = rop.as_raw_mut();
$(let $op = $op.mpc_or(rop);)*
ordering2(unsafe { $deleg(rop, $($op,)* $($param.into(),)* raw_round2(rnd)) })
}
};
}
#[inline]
pub fn neg<O: OptComplex>(rop: &mut Complex, op: O, rnd: Round2) -> Ordering2 {
if O::IS_SOME {
ordering2(unsafe { mpc::neg(rop.as_raw_mut(), op.mpc(), raw_round2(rnd)) })
} else {
(
xmpfr::neg(rop.mut_real(), (), rnd.0),
xmpfr::neg(rop.mut_imag(), (), rnd.1),
)
}
}
#[inline]
pub fn mul_i<O: OptComplex>(rop: &mut Complex, op: O, neg: bool, rnd: Round2) -> Ordering2 {
let rop = rop.as_raw_mut();
let op = op.mpc_or(rop);
ordering2(unsafe { mpc::mul_i(rop, op, if neg { -1 } else { 0 }, raw_round2(rnd)) })
}
#[inline]
pub fn recip<O: OptComplex>(rop: &mut Complex, op: O, rnd: Round2) -> Ordering2 {
ui_div(rop, 1, op, rnd)
}
#[inline]
pub fn rootofunity(rop: &mut Complex, n: u32, k: u32, rnd: Round2) -> Ordering2 {
ordering2(unsafe { mpc::rootofunity(rop.as_raw_mut(), n.into(), k.into(), raw_round2(rnd)) })
}
#[inline]
pub fn sin_cos<O: OptComplex>(
rop_sin: &mut Complex,
rop_cos: &mut Complex,
op: O,
rnd: Round2,
) -> (Ordering2, Ordering2) {
let rop_sin = rop_sin.as_raw_mut();
let rop_cos = rop_cos.as_raw_mut();
let op = op.mpc_or(rop_sin);
ordering4(unsafe { mpc::sin_cos(rop_sin, rop_cos, op, raw_round2(rnd), raw_round2(rnd)) })
}
pub fn sum<'a, I>(rop: &mut Complex, values: I, rnd: Round2) -> Ordering2
where
I: Iterator<Item = &'a Complex>,
{
let pointers = values.map(Complex::as_raw).collect::<VecLike<_>>();
unsafe { sum_raw(rop.as_raw_mut(), pointers.as_slice(), rnd) }
}
pub fn sum_including_old<'a, I>(rop: &mut Complex, values: I, rnd: Round2) -> Ordering2
where
I: Iterator<Item = &'a Complex>,
{
let rop = rop.as_raw_mut();
let capacity = values.size_hint().0.checked_add(1).expect("overflow");
let mut pointers = VecLike::new();
pointers.reserve(capacity);
pointers.push(rop.cast_const());
pointers.extend(values.map(Complex::as_raw));
unsafe { sum_raw(rop, pointers.as_slice(), rnd) }
}
pub unsafe fn sum_raw(rop: *mut mpc_t, pointers: &[*const mpc_t], rnd: Round2) -> Ordering2 {
let n = pointers.len().strict_cast();
let tab = misc::cast_ptr(pointers.as_ptr());
let rnd = raw_round2(rnd);
ordering2(unsafe { mpc::sum(rop, tab, n, rnd) })
}
pub fn dot<'a, I>(rop: &mut Complex, values: I, rnd: Round2) -> Ordering2
where
I: Iterator<Item = (&'a Complex, &'a Complex)>,
{
let (pointers_a, pointers_b): (VecLike<_>, VecLike<_>) =
values.map(|(a, b)| (a.as_raw(), b.as_raw())).unzip();
unsafe {
dot_raw(
rop.as_raw_mut(),
pointers_a.as_slice(),
pointers_b.as_slice(),
rnd,
)
}
}
pub fn dot_including_old<'a, I>(rop: &mut Complex, values: I, rnd: Round2) -> Ordering2
where
I: Iterator<Item = (&'a Complex, &'a Complex)>,
{
const LIMB_ONE: limb_t = 1;
const LIMB_MSB: limb_t = LIMB_ONE << (gmp::LIMB_BITS - 1);
const ONE: mpc_t = mpc_t {
re: mpfr_t {
prec: 1,
sign: 1,
exp: 1,
d: unsafe { NonNull::new_unchecked((&LIMB_MSB as *const limb_t).cast_mut()) },
},
im: mpfr_t {
prec: 1,
sign: 1,
exp: EXP_ZERO,
d: unsafe { NonNull::new_unchecked((&LIMB_MSB as *const limb_t).cast_mut()) },
},
};
let rop = rop.as_raw_mut();
let capacity = values.size_hint().0.checked_add(1).expect("overflow");
let mut pointers_a = VecLike::new();
let mut pointers_b = VecLike::new();
pointers_a.reserve(capacity);
pointers_b.reserve(capacity);
pointers_a.push(rop.cast_const());
pointers_b.push(&ONE as *const mpc_t);
for a_b in values {
pointers_a.push(a_b.0.as_raw());
pointers_b.push(a_b.1.as_raw());
}
unsafe { dot_raw(rop, pointers_a.as_slice(), pointers_b.as_slice(), rnd) }
}
unsafe fn dot_raw(
rop: *mut mpc_t,
pointers_a: &[*const mpc_t],
pointers_b: &[*const mpc_t],
rnd: Round2,
) -> Ordering2 {
debug_assert_eq!(pointers_a.len(), pointers_b.len());
let n = pointers_a.len().strict_cast();
let a = misc::cast_ptr(pointers_a.as_ptr());
let b = misc::cast_ptr(pointers_b.as_ptr());
let rnd = raw_round2(rnd);
ordering2(unsafe { mpc::dot(rop, a, b, n, rnd) })
}
unsafe_wrap! { fn set(op: O) -> mpc::set }
unsafe_wrap! { fn proj(op: O) -> mpc::proj }
unsafe_wrap! { fn sqr(op: O) -> mpc::sqr }
unsafe_wrap! { fn sqrt(op: O) -> mpc::sqrt }
unsafe_wrap! { fn conj(op: O) -> mpc::conj }
unsafe_wrap! { fn log(op: O) -> mpc::log }
unsafe_wrap! { fn log2(op: O) -> mpc::log2 }
unsafe_wrap! { fn log10(op: O) -> mpc::log10 }
unsafe_wrap! { fn exp(op: O) -> mpc::exp }
unsafe_wrap! { fn exp2(op: O) -> mpc::exp2 }
unsafe_wrap! { fn exp10(op: O) -> mpc::exp10 }
unsafe_wrap! { fn sin(op: O) -> mpc::sin }
unsafe_wrap! { fn cos(op: O) -> mpc::cos }
unsafe_wrap! { fn tan(op: O) -> mpc::tan }
unsafe_wrap! { fn sinh(op: O) -> mpc::sinh }
unsafe_wrap! { fn cosh(op: O) -> mpc::cosh }
unsafe_wrap! { fn tanh(op: O) -> mpc::tanh }
unsafe_wrap! { fn asin(op: O) -> mpc::asin }
unsafe_wrap! { fn acos(op: O) -> mpc::acos }
unsafe_wrap! { fn atan(op: O) -> mpc::atan }
unsafe_wrap! { fn asinh(op: O) -> mpc::asinh }
unsafe_wrap! { fn acosh(op: O) -> mpc::acosh }
unsafe_wrap! { fn atanh(op: O) -> mpc::atanh }
unsafe_wrap! { fn agm(op1: O, op2: P) -> mpc::agm }
unsafe_wrap! { fn fma(op1: O, op2: P, op3: Q) -> mpc::fma }
unsafe_wrap! { fn add(op1: O, op2: P) -> mpc::add }
unsafe_wrap! { fn sub(op1: O, op2: P) -> mpc::sub }
unsafe_wrap! { fn mul(op1: O, op2: P) -> mpc::mul }
unsafe_wrap! { fn div(op1: O, op2: P) -> mpc::div }
unsafe_wrap! { fn pow(op1: O, op2: P) -> mpc::pow }
unsafe_wrap! { fn shl_i32(op1: O; op2: i32) -> mpc::mul_2si }
unsafe_wrap! { fn shr_i32(op1: O; op2: i32) -> mpc::div_2si }
unsafe_wrap! { fn shl_u32(op1: O; op2: u32) -> mpc::mul_2ui }
unsafe_wrap! { fn shr_u32(op1: O; op2: u32) -> mpc::div_2ui }
unsafe_wrap! { fn shl_isize(op1: O; op2: isize) -> mul_2isize }
unsafe_wrap! { fn shr_isize(op1: O; op2: isize) -> div_2isize }
unsafe_wrap! { fn shl_usize(op1: O; op2: usize) -> mul_2usize }
unsafe_wrap! { fn shr_usize(op1: O; op2: usize) -> div_2usize }
#[inline]
unsafe fn mul_2isize(rop: *mut mpc_t, op1: *const mpc_t, op2: isize, rnd: rnd_t) -> c_int {
let op2 = op2.strict_cast();
unsafe { mpc::mul_2si(rop, op1, op2, rnd) }
}
#[inline]
unsafe fn div_2isize(rop: *mut mpc_t, op1: *const mpc_t, op2: isize, rnd: rnd_t) -> c_int {
let op2 = op2.strict_cast();
unsafe { mpc::div_2si(rop, op1, op2, rnd) }
}
#[inline]
unsafe fn mul_2usize(rop: *mut mpc_t, op1: *const mpc_t, op2: usize, rnd: rnd_t) -> c_int {
let op2 = op2.strict_cast();
unsafe { mpc::mul_2ui(rop, op1, op2, rnd) }
}
#[inline]
unsafe fn div_2usize(rop: *mut mpc_t, op1: *const mpc_t, op2: usize, rnd: rnd_t) -> c_int {
let op2 = op2.strict_cast();
unsafe { mpc::div_2ui(rop, op1, op2, rnd) }
}
#[inline]
pub fn write_new_nan(dst: &mut MaybeUninit<Complex>, prec_real: prec_t, prec_imag: prec_t) {
unsafe {
let inner_ptr = misc::cast_ptr_mut(dst.as_mut_ptr());
mpc::init3(inner_ptr, prec_real, prec_imag);
}
}
#[inline]
pub fn write_real_imag(dst: &mut MaybeUninit<Complex>, real: Float, imag: Float) {
unsafe {
let inner_ptr = misc::cast_ptr_mut(dst.as_mut_ptr());
let real_ptr = misc::cast_ptr_mut::<_, Float>(mpc::realref(inner_ptr));
real_ptr.write(real);
let imag_ptr = misc::cast_ptr_mut::<_, Float>(mpc::imagref(inner_ptr));
imag_ptr.write(imag);
}
}
#[inline]
pub const fn realref_const(c: &Complex) -> &Float {
unsafe { &*misc::cast_ptr(mpc::realref_const(c.as_raw())) }
}
#[inline]
pub const fn imagref_const(c: &Complex) -> &Float {
unsafe { &*misc::cast_ptr(mpc::imagref_const(c.as_raw())) }
}
#[inline]
pub fn realref(c: &mut Complex) -> &mut Float {
unsafe { &mut *misc::cast_ptr_mut(mpc::realref(c.as_raw_mut())) }
}
#[inline]
pub fn imagref(c: &mut Complex) -> &mut Float {
unsafe { &mut *misc::cast_ptr_mut(mpc::imagref(c.as_raw_mut())) }
}
#[inline]
pub fn realref_imagref(c: &mut Complex) -> (&mut Float, &mut Float) {
let c = c.as_raw_mut();
unsafe {
(
&mut *misc::cast_ptr_mut(mpc::realref(c)),
&mut *misc::cast_ptr_mut(mpc::imagref(c)),
)
}
}
#[inline]
pub const fn split(c: Complex) -> (Float, Float) {
let raw = c.into_raw();
unsafe { (Float::from_raw(raw.re), Float::from_raw(raw.im)) }
}
#[inline]
pub fn abs(f: &mut Float, c: &Complex, round: Round) -> Ordering {
ordering1(unsafe { mpc::abs(f.as_raw_mut(), c.as_raw(), raw_round(round)) })
}
#[inline]
pub fn arg(f: &mut Float, c: &Complex, round: Round) -> Ordering {
ordering1(unsafe { mpc::arg(f.as_raw_mut(), c.as_raw(), raw_round(round)) })
}
#[inline]
pub fn norm(f: &mut Float, c: &Complex, round: Round) -> Ordering {
ordering1(unsafe { mpc::norm(f.as_raw_mut(), c.as_raw(), raw_round(round)) })
}
#[inline]
pub fn cmp_abs(op1: &Complex, op2: &Complex) -> Ordering {
ordering1(unsafe { mpc::cmp_abs(op1.as_raw(), op2.as_raw()) })
}
macro_rules! sum_forward {
(fn $name:ident($T:ty) -> $func:path) => {
#[inline]
pub fn $name<O: OptComplex>(rop: &mut Complex, op1: O, op2: $T, rnd: Round2) -> Ordering2 {
let op1 = op1.parts();
(
$func(rop.mut_real(), op1.0, op2, rnd.0),
xmpfr::set(rop.mut_imag(), op1.1, rnd.1),
)
}
};
}
macro_rules! sub_reverse {
(fn $name:ident($T:ty) -> $func:path) => {
#[inline]
pub fn $name<O: OptComplex>(rop: &mut Complex, op1: $T, op2: O, rnd: Round2) -> Ordering2 {
let op2 = op2.parts();
(
$func(rop.mut_real(), op1, op2.0, rnd.0),
xmpfr::neg(rop.mut_imag(), op2.1, rnd.1),
)
}
};
}
macro_rules! prod_forward {
(fn $name:ident($T:ty) -> $func:path) => {
#[inline]
pub fn $name<O: OptComplex>(rop: &mut Complex, op1: O, op2: $T, rnd: Round2) -> Ordering2 {
let op1 = op1.parts();
(
$func(rop.mut_real(), op1.0, op2, rnd.0),
$func(rop.mut_imag(), op1.1, op2, rnd.1),
)
}
};
}
macro_rules! div_reverse {
(fn $name:ident($T:ty) -> $func:path) => {
#[inline]
pub fn $name<O: OptComplex>(rop: &mut Complex, op1: $T, op2: O, rnd: Round2) -> Ordering2 {
let mut op1 = MiniComplex::from(op1);
div(rop, op1.borrow_excl(), op2, rnd)
}
};
}
sum_forward! { fn add_ui(c_ulong) -> xmpfr::add_ui }
sum_forward! { fn add_si(c_long) -> xmpfr::add_si }
sum_forward! { fn add_d(f64) -> xmpfr::add_d }
#[cfg(feature = "integer")]
sum_forward! { fn add_z(&Integer) -> xmpfr::add_z }
#[cfg(feature = "rational")]
sum_forward! { fn add_q(&Rational) -> xmpfr::add_q }
sum_forward! { fn sub_ui(c_ulong) -> xmpfr::sub_ui }
sum_forward! { fn sub_si(c_long) -> xmpfr::sub_si }
sum_forward! { fn sub_d(f64) -> xmpfr::sub_d }
#[cfg(feature = "integer")]
sum_forward! { fn sub_z(&Integer) -> xmpfr::sub_z }
#[cfg(feature = "rational")]
sum_forward! { fn sub_q(&Rational) -> xmpfr::sub_q }
sub_reverse! { fn ui_sub(c_ulong) -> xmpfr::ui_sub }
sub_reverse! { fn si_sub(c_long) -> xmpfr::si_sub }
sub_reverse! { fn d_sub(f64) -> xmpfr::d_sub }
#[cfg(feature = "integer")]
sub_reverse! { fn z_sub(&Integer) -> xmpfr::z_sub }
#[cfg(feature = "rational")]
sub_reverse! { fn q_sub(&Rational) -> xmpfr::q_sub }
prod_forward! { fn mul_ui(c_ulong) -> xmpfr::mul_ui }
prod_forward! { fn mul_si(c_long) -> xmpfr::mul_si }
prod_forward! { fn mul_d(f64) -> xmpfr::mul_d }
#[cfg(feature = "integer")]
prod_forward! { fn mul_z(&Integer) -> xmpfr::mul_z }
#[cfg(feature = "rational")]
prod_forward! { fn mul_q(&Rational) -> xmpfr::mul_q }
prod_forward! { fn div_ui(c_ulong) -> xmpfr::div_ui }
prod_forward! { fn div_si(c_long) -> xmpfr::div_si }
prod_forward! { fn div_d(f64) -> xmpfr::div_d }
#[cfg(feature = "integer")]
prod_forward! { fn div_z(&Integer) -> xmpfr::div_z }
#[cfg(feature = "rational")]
prod_forward! { fn div_q(&Rational) -> xmpfr::div_q }
div_reverse! { fn ui_div(c_ulong) -> xmpfr::ui_div }
div_reverse! { fn si_div(c_long) -> xmpfr::si_div }
div_reverse! { fn d_div(f64) -> xmpfr::d_div }
#[inline]
pub fn mulsub<O: OptComplex>(
rop: &mut Complex,
mul1: &Complex,
mul2: &Complex,
sub: O,
rnd: Round2,
) -> Ordering2 {
if O::IS_SOME {
let sub = sub.unwrap();
fma(rop, mul1, mul2, &*sub.as_neg(), rnd)
} else {
neg(rop, (), (Round::Zero, Round::Zero));
fma(rop, mul1, mul2, (), rnd)
}
}
#[inline]
pub fn submul<O: OptComplex>(
rop: &mut Complex,
add: O,
mul1: &Complex,
mul2: &Complex,
rnd: Round2,
) -> Ordering2 {
fma(rop, &*mul1.as_neg(), mul2, add, rnd)
}
#[inline]
pub fn add_fr<O: OptComplex>(rop: &mut Complex, op1: O, op2: &Float, rnd: Round2) -> Ordering2 {
let rop = rop.as_raw_mut();
let op1 = op1.mpc_or(rop);
ordering2(unsafe { mpc::add_fr(rop, op1, op2.as_raw(), raw_round2(rnd)) })
}
#[inline]
pub fn sub_fr<O: OptComplex>(rop: &mut Complex, op1: O, op2: &Float, rnd: Round2) -> Ordering2 {
let rop = rop.as_raw_mut();
let op1 = op1.mpc_or(rop);
ordering2(unsafe { mpc::sub_fr(rop, op1, op2.as_raw(), raw_round2(rnd)) })
}
#[inline]
pub fn fr_sub<O: OptComplex>(rop: &mut Complex, op1: &Float, op2: O, rnd: Round2) -> Ordering2 {
let rop = rop.as_raw_mut();
let op2 = op2.mpc_or(rop);
ordering2(unsafe { mpc::fr_sub(rop, op1.as_raw(), op2, raw_round2(rnd)) })
}
#[inline]
pub fn mul_fr<O: OptComplex>(rop: &mut Complex, op1: O, op2: &Float, rnd: Round2) -> Ordering2 {
let rop = rop.as_raw_mut();
let op1 = op1.mpc_or(rop);
ordering2(unsafe { mpc::mul_fr(rop, op1, op2.as_raw(), raw_round2(rnd)) })
}
#[inline]
pub fn div_fr<O: OptComplex>(rop: &mut Complex, op1: O, op2: &Float, rnd: Round2) -> Ordering2 {
let rop = rop.as_raw_mut();
let op1 = op1.mpc_or(rop);
ordering2(unsafe { mpc::div_fr(rop, op1, op2.as_raw(), raw_round2(rnd)) })
}
#[inline]
pub fn fr_div<O: OptComplex>(rop: &mut Complex, op1: &Float, op2: O, rnd: Round2) -> Ordering2 {
let rop = rop.as_raw_mut();
let op2 = op2.mpc_or(rop);
ordering2(unsafe { mpc::fr_div(rop, op1.as_raw(), op2, raw_round2(rnd)) })
}
#[inline]
pub fn pow_fr<O: OptComplex>(rop: &mut Complex, op1: O, op2: &Float, rnd: Round2) -> Ordering2 {
let rop = rop.as_raw_mut();
let op1 = op1.mpc_or(rop);
ordering2(unsafe { mpc::pow_fr(rop, op1, op2.as_raw(), raw_round2(rnd)) })
}
#[inline]
#[cfg(feature = "integer")]
pub fn pow_z<O: OptComplex>(rop: &mut Complex, op1: O, op2: &Integer, rnd: Round2) -> Ordering2 {
let rop = rop.as_raw_mut();
let op1 = op1.mpc_or(rop);
ordering2(unsafe { mpc::pow_z(rop, op1, op2.as_raw(), raw_round2(rnd)) })
}