use ark_ec::{
CurveConfig,
short_weierstrass::{Affine as SWAffine, SWCurveConfig},
twisted_edwards::{Affine as TEAffine, MontCurveConfig, TECurveConfig},
};
use ark_ff::{Field, One};
use ark_std::borrow::Cow;
use ark_std::vec::Vec;
pub trait MapConfig: TECurveConfig + SWCurveConfig + MontCurveConfig {
const MONT_A_OVER_THREE: <Self as CurveConfig>::BaseField;
const MONT_B_INV: <Self as CurveConfig>::BaseField;
}
pub fn sw_to_te<C: MapConfig>(point: &SWAffine<C>) -> Option<TEAffine<C>> {
let mx = <C as MontCurveConfig>::COEFF_B * point.x - C::MONT_A_OVER_THREE;
let my = <C as MontCurveConfig>::COEFF_B * point.y;
let v_denom = my.inverse()?;
let x_p_1 = mx + <<C as CurveConfig>::BaseField as One>::one();
let w_denom = x_p_1.inverse()?;
let v = mx * v_denom;
let w = (mx - <<C as CurveConfig>::BaseField as One>::one()) * w_denom;
Some(TEAffine::new_unchecked(v, w))
}
pub fn te_to_sw<C: MapConfig>(point: &TEAffine<C>) -> Option<SWAffine<C>> {
let v_denom = <<C as CurveConfig>::BaseField as One>::one() - point.y;
let w_denom = point.x - point.x * point.y;
let v_denom_inv = v_denom.inverse()?;
let w_denom_inv = w_denom.inverse()?;
let v_w_num = <<C as CurveConfig>::BaseField as One>::one() + point.y;
let v = v_w_num * v_denom_inv;
let w = v_w_num * w_denom_inv;
let x = C::MONT_B_INV * (v + C::MONT_A_OVER_THREE);
let y = C::MONT_B_INV * w;
Some(SWAffine::new_unchecked(x, y))
}
pub trait SWMapping<C: SWCurveConfig>: Sized {
fn from_sw(sw: SWAffine<C>) -> Option<Self>;
fn into_sw(self) -> Option<SWAffine<C>>;
fn to_sw_slice(slice: &[Self]) -> Option<Cow<'_, [SWAffine<C>]>>;
}
impl<C: SWCurveConfig> SWMapping<C> for SWAffine<C> {
#[inline(always)]
fn from_sw(sw: SWAffine<C>) -> Option<Self> {
Some(sw)
}
#[inline(always)]
fn into_sw(self) -> Option<SWAffine<C>> {
Some(self)
}
#[inline(always)]
fn to_sw_slice(slice: &[Self]) -> Option<Cow<'_, [SWAffine<C>]>> {
Some(Cow::Borrowed(slice))
}
}
impl<C: MapConfig> SWMapping<C> for TEAffine<C> {
#[inline(always)]
fn from_sw(sw: SWAffine<C>) -> Option<Self> {
sw_to_te(&sw)
}
#[inline(always)]
fn into_sw(self) -> Option<SWAffine<C>> {
te_to_sw(&self)
}
#[inline(always)]
fn to_sw_slice(slice: &[Self]) -> Option<Cow<'_, [SWAffine<C>]>> {
let pks;
#[cfg(feature = "parallel")]
{
use rayon::prelude::*;
pks = slice
.par_iter()
.map(|p| te_to_sw(p))
.collect::<Option<Vec<_>>>()?;
}
#[cfg(not(feature = "parallel"))]
{
pks = slice
.iter()
.map(|p| te_to_sw(p))
.collect::<Option<Vec<_>>>()?;
}
Some(Cow::Owned(pks))
}
}
pub trait TEMapping<C: TECurveConfig>: Sized {
fn from_te(te: TEAffine<C>) -> Option<Self>;
fn into_te(self) -> Option<TEAffine<C>>;
fn to_te_slice(slice: &[Self]) -> Option<Cow<'_, [TEAffine<C>]>>;
}
impl<C: TECurveConfig> TEMapping<C> for TEAffine<C> {
#[inline(always)]
fn from_te(te: TEAffine<C>) -> Option<Self> {
Some(te)
}
#[inline(always)]
fn into_te(self) -> Option<TEAffine<C>> {
Some(self)
}
#[inline(always)]
fn to_te_slice(slice: &[Self]) -> Option<Cow<'_, [TEAffine<C>]>> {
Some(Cow::Borrowed(slice))
}
}
impl<C: MapConfig> TEMapping<C> for SWAffine<C> {
#[inline(always)]
fn from_te(te: TEAffine<C>) -> Option<Self> {
te_to_sw(&te)
}
#[inline(always)]
fn into_te(self) -> Option<TEAffine<C>> {
sw_to_te(&self)
}
#[inline(always)]
fn to_te_slice(slice: &[Self]) -> Option<Cow<'_, [TEAffine<C>]>> {
let pks;
#[cfg(feature = "parallel")]
{
use rayon::prelude::*;
pks = slice
.par_iter()
.map(|p| sw_to_te(p))
.collect::<Option<Vec<_>>>()?;
}
#[cfg(not(feature = "parallel"))]
{
pks = slice
.iter()
.map(|p| sw_to_te(p))
.collect::<Option<Vec<_>>>()?;
}
Some(Cow::Owned(pks))
}
}