snarkvm_console_types_field/
arithmetic.rsuse super::*;
impl<E: Environment> Neg for Field<E> {
type Output = Field<E>;
#[inline]
fn neg(self) -> Self::Output {
Field::new(-self.field)
}
}
impl<E: Environment> Add<Field<E>> for Field<E> {
type Output = Field<E>;
#[inline]
fn add(self, other: Field<E>) -> Self::Output {
Field::new(self.field + other.field)
}
}
impl<E: Environment> Add<&Field<E>> for Field<E> {
type Output = Field<E>;
#[inline]
fn add(self, other: &Field<E>) -> Self::Output {
Field::new(self.field + other.field)
}
}
impl<E: Environment> AddAssign<Field<E>> for Field<E> {
#[inline]
fn add_assign(&mut self, other: Field<E>) {
self.field += other.field;
}
}
impl<E: Environment> AddAssign<&Field<E>> for Field<E> {
#[inline]
fn add_assign(&mut self, other: &Field<E>) {
self.field += other.field;
}
}
impl<E: Environment> Sub<Field<E>> for Field<E> {
type Output = Field<E>;
#[inline]
fn sub(self, other: Field<E>) -> Self::Output {
Field::new(self.field - other.field)
}
}
impl<E: Environment> Sub<&Field<E>> for Field<E> {
type Output = Field<E>;
#[inline]
fn sub(self, other: &Field<E>) -> Self::Output {
Field::new(self.field - other.field)
}
}
impl<E: Environment> SubAssign<Field<E>> for Field<E> {
#[inline]
fn sub_assign(&mut self, other: Field<E>) {
self.field -= other.field;
}
}
impl<E: Environment> SubAssign<&Field<E>> for Field<E> {
#[inline]
fn sub_assign(&mut self, other: &Field<E>) {
self.field -= other.field;
}
}
impl<E: Environment> Mul<Field<E>> for Field<E> {
type Output = Field<E>;
#[inline]
fn mul(self, other: Field<E>) -> Self::Output {
Field::new(self.field * other.field)
}
}
impl<E: Environment> Mul<&Field<E>> for Field<E> {
type Output = Field<E>;
#[inline]
fn mul(self, other: &Field<E>) -> Self::Output {
Field::new(self.field * other.field)
}
}
impl<E: Environment> MulAssign<Field<E>> for Field<E> {
#[inline]
fn mul_assign(&mut self, other: Field<E>) {
self.field *= other.field;
}
}
impl<E: Environment> MulAssign<&Field<E>> for Field<E> {
#[inline]
fn mul_assign(&mut self, other: &Field<E>) {
self.field *= other.field;
}
}
impl<E: Environment> Div<Field<E>> for Field<E> {
type Output = Field<E>;
#[inline]
fn div(self, other: Field<E>) -> Self::Output {
match other.is_zero() {
true => E::halt(format!("Field division by zero: {self} / {other}")),
false => Field::new(self.field / other.field),
}
}
}
impl<E: Environment> Div<&Field<E>> for Field<E> {
type Output = Field<E>;
#[inline]
fn div(self, other: &Field<E>) -> Self::Output {
match other.is_zero() {
true => E::halt(format!("Field division by zero: {self} / {other}")),
false => Field::new(self.field / other.field),
}
}
}
impl<E: Environment> DivAssign<Field<E>> for Field<E> {
#[inline]
fn div_assign(&mut self, other: Field<E>) {
match other.is_zero() {
true => E::halt(format!("Field division by zero: {self} / {other}")),
false => self.field /= other.field,
}
}
}
impl<E: Environment> DivAssign<&Field<E>> for Field<E> {
#[inline]
fn div_assign(&mut self, other: &Field<E>) {
match other.is_zero() {
true => E::halt(format!("Field division by zero: {self} / {other}")),
false => self.field /= other.field,
}
}
}
impl<E: Environment> Pow<Field<E>> for Field<E> {
type Output = Field<E>;
#[inline]
fn pow(self, other: Field<E>) -> Self::Output {
Field::new(self.field.pow(other.field.to_bigint()))
}
}
impl<E: Environment> Pow<&Field<E>> for Field<E> {
type Output = Field<E>;
#[inline]
fn pow(self, other: &Field<E>) -> Self::Output {
Field::new(self.field.pow(other.field.to_bigint()))
}
}
impl<E: Environment> Double for Field<E> {
type Output = Field<E>;
#[inline]
fn double(&self) -> Self::Output {
Field::new(self.field.double())
}
}
impl<E: Environment> Inverse for Field<E> {
type Output = Field<E>;
#[inline]
fn inverse(&self) -> Result<Self::Output> {
match self.field.inverse() {
Some(inverse) => Ok(Field::new(inverse)),
None => bail!("Failed to invert a field element: {self}"),
}
}
}
impl<E: Environment> Square for Field<E> {
type Output = Field<E>;
#[inline]
fn square(&self) -> Self::Output {
Field::new(self.field.square())
}
}
impl<E: Environment> SquareRoot for Field<E> {
type Output = Field<E>;
#[inline]
fn square_root(&self) -> Result<Self::Output> {
match self.field.sqrt() {
Some(sqrt) => {
let sqrt = Field::new(sqrt);
let negative_sqrt: Field<E> = -sqrt;
match *(sqrt.is_less_than_or_equal(&negative_sqrt)) {
true => Ok(sqrt),
false => Ok(negative_sqrt),
}
}
None => bail!("Failed to square root a field element: {self}"),
}
}
}
impl<E: Environment> Field<E> {
#[inline]
pub fn even_square_root(&self) -> Result<Self> {
match self.field.sqrt() {
Some(sqrt) => {
let sqrt: Field<E> = Field::new(sqrt);
match *sqrt.to_bits_be().last().unwrap() {
true => Ok(-sqrt),
false => Ok(sqrt),
}
}
None => bail!("Failed to square root a field element: {self}"),
}
}
}
impl<E: Environment> Sum<Field<E>> for Field<E> {
#[inline]
fn sum<I: Iterator<Item = Field<E>>>(iter: I) -> Self {
iter.fold(Field::zero(), |a, b| a + b)
}
}
impl<'a, E: Environment> Sum<&'a Field<E>> for Field<E> {
#[inline]
fn sum<I: Iterator<Item = &'a Field<E>>>(iter: I) -> Self {
iter.fold(Field::zero(), |a, b| a + b)
}
}
impl<E: Environment> Product<Field<E>> for Field<E> {
#[inline]
fn product<I: Iterator<Item = Field<E>>>(iter: I) -> Self {
iter.fold(Field::one(), |a, b| a * b)
}
}
impl<'a, E: Environment> Product<&'a Field<E>> for Field<E> {
#[inline]
fn product<I: Iterator<Item = &'a Field<E>>>(iter: I) -> Self {
iter.fold(Field::one(), |a, b| a * b)
}
}
#[cfg(test)]
mod tests {
use super::*;
use snarkvm_console_network_environment::Console;
type CurrentEnvironment = Console;
#[test]
fn test_div_by_zero_fails() {
let one = Field::<CurrentEnvironment>::one();
let zero = Field::<CurrentEnvironment>::zero();
let result = std::panic::catch_unwind(|| one / zero);
assert!(result.is_err()); }
}