qfall-math 0.1.1

Mathematical foundations for rapid prototyping of lattice-based cryptography
Documentation
// Copyright © 2023 Marvin Beckmann, Marcel Luca Schmidt
//
// This file is part of qFALL-math.
//
// qFALL-math is free software: you can redistribute it and/or modify it under
// the terms of the Mozilla Public License Version 2.0 as published by the
// Mozilla Foundation. See <https://mozilla.org/en-US/MPL/2.0/>.

//! This module implements macros which are used to explicitly implement
//! traits taking input of one of our types. These types can be constructed
//! from other values. These macros will implement the trait for the other types.
//!
//! Example:
//! [`Z`](crate::integer::Z) implements the [`From`] trait for
//! [`i8`],[`i16`], ... -> hence it is be beneficial if one
//! does not have to first create a [`Z`](crate::integer::Z), but if one can directly
//! pass the value to other functions taking in a [`Z`](crate::integer::Z). These macros
//! shall implement the traits for the other types as well.

/// Implements a specified trait using implicit conversions to a bridge type.
///
/// - ['Mul'](std::ops::Mul) with signature
///   `($bridge_type, $type, $output_type, Mul Scalar for $source_type)`
/// - ['Div'](std::ops::Div) with signature
///   `($bridge_type, $type, $output_type, Div Scalar for $source_type)`
/// - ['Rem'](std::ops::Rem) with signature
///   `($bridge_type, $type, Rem for $source_type)`
/// - ['PartialEq'](std::cmp::PartialEq) with signature
///   `($bridge_type, $type, PartialEq for $source_type)`
/// - ['PartialOrd'](std::cmp::PartialOrd) with signature
///   `($bridge_type, $type, PartialEq for $source_type)`
///
/// # Examples
/// ```compile_fail
/// implement_for_others!(Z, MatZ, MatZ, Mul Scalar for i8 i16 i32 i64 u8 u16 u32 u64);
/// implement_for_others!(Z, Q, PartialEq for fmpz i8 i16 i32 i64 u8 u16 u32 u64);
/// implement_for_others!(Z, Q, PartialOrd for fmpz i8 i16 i32 i64 u8 u16 u32 u64);
/// implement_for_others!(Z, PolyOverZ, Rem for i8 i16 i32 i64 u8 u16 u32 u64);
/// ```
macro_rules! implement_for_others {
    // [`Mul`] trait scalar
    ($bridge_type:ident, $type:ident, $output_type:ident, Mul Scalar for $($source_type:ident)*) => {
        $(#[doc(hidden)] impl Mul<$source_type> for &$type {
            type Output = $output_type;
            paste::paste! {
                #[doc = "Documentation can be found at [`" $type "::mul`]."]
                fn mul(self, scalar: $source_type) -> Self::Output {
                    self.mul($bridge_type::from(scalar))
                }
            }
        }

        #[doc(hidden)]
        impl Mul<$source_type> for $type {
            type Output = $output_type;
            paste::paste! {
                #[doc = "Documentation can be found at [`" $type "::mul`]."]
                fn mul(self, scalar: $source_type) -> Self::Output {
                    self.mul($bridge_type::from(scalar))
                }
            }
        }

        #[doc(hidden)]
        impl Mul<&$type> for $source_type {
            type Output = $output_type;
            paste::paste! {
                #[doc = "Documentation can be found at [`" $type "::mul`]."]
                fn mul(self, matrix: &$type) -> Self::Output {
                    matrix.mul($bridge_type::from(self))
                }
            }
        }

        #[doc(hidden)]
        impl Mul<$type> for $source_type {
            type Output = $output_type;
            paste::paste! {
                #[doc = "Documentation can be found at [`" $type "::mul`]."]
                fn mul(self, matrix: $type) -> Self::Output {
                    matrix.mul($bridge_type::from(self))
                }
            }
        })*
    };

    // [`Div`] trait scalar
    ($bridge_type:ident, $type:ident, $output_type:ident, Div Scalar for $($source_type:ident)*) => {
        $(#[doc(hidden)] impl Div<$source_type> for &$type {
            type Output = $output_type;
            paste::paste! {
                #[doc = "Documentation can be found at [`" $type "::div`]."]
                fn div(self, scalar: $source_type) -> Self::Output {
                    self.div($bridge_type::from(scalar))
                }
            }
        }

        #[doc(hidden)]
        impl Div<$source_type> for $type {
            type Output = $output_type;
            paste::paste! {
                #[doc = "Documentation can be found at [`" $type "::div`]."]
                fn div(self, scalar: $source_type) -> Self::Output {
                    self.div($bridge_type::from(scalar))
                }
            }
        })*
    };

    // [`Rem`] trait scalar
    ($bridge_type:ident, $type:ident, Rem for $($source_type:ident)*) => {
        $(#[doc(hidden)] impl Rem<$source_type> for &$type {
            type Output = $type;
            paste::paste! {
                #[doc = "Documentation can be found at [`" $type "::rem`]."]
                fn rem(self, modulus: $source_type) -> Self::Output {
                    self.rem($bridge_type::from(modulus))
                }
            }
        }

        impl Rem<$source_type> for $type {
            type Output = $type;
            paste::paste! {
                #[doc = "Documentation can be found at [`" $type "::rem`]."]
                fn rem(self, modulus: $source_type) -> Self::Output {
                    self.rem($bridge_type::from(modulus))
                }
            }
        })*
    };

    // [`PartialEq`] trait
    ($bridge_type:ident, $type:ident, PartialEq for $($source_type:ident)*) => {
        $(#[doc(hidden)] impl PartialEq<$source_type> for $type {
            paste::paste! {
                #[doc = "Documentation can be found at [`" $type "::partialEq`]."]
                fn eq(&self, other: &$source_type) -> bool {
                    self.eq(&$bridge_type::from(other))
                }
            }
        }

        #[doc(hidden)] impl PartialEq<$type> for $source_type {
            paste::paste! {
                #[doc = "Documentation can be found at [`" $type "::partialEq`]."]
                fn eq(&self, other: &$type) -> bool {
                    other.eq(&$bridge_type::from(self))
                }
            }
        })*
    };

    // [`PartialOrd`] trait
    ($bridge_type:ident, $type:ident, PartialOrd for $($source_type:ident)*) => {
        $(#[doc(hidden)] impl PartialOrd<$source_type> for $type {
            paste::paste! {
                #[doc = "Documentation can be found at [`" $type "::partialEq`]."]
                fn partial_cmp(&self, other: &$source_type) -> Option<Ordering> {
                    self.partial_cmp(&$bridge_type::from(other))
                }
            }
        }

        #[doc(hidden)] impl PartialOrd<$type> for $source_type {
            paste::paste! {
                #[doc = "Documentation can be found at [`" $type "::partialEq`]."]
                fn partial_cmp(&self, other: &$type) -> Option<Ordering> {
                    $bridge_type::from(self).partial_cmp(other)
                }
            }
        })*
    };
}

pub(crate) use implement_for_others;

/// Implements a specified trait for an owned input using the traits
/// implementation for a borrowed input.
/// Several traits are already supported:
///
/// - [`Evaluate`](crate::traits::Evaluate) with the signature
///   `($bridge_type, $output_type, $type, Evaluate)`
/// - [`From`] with the signature
///   `($source_type, $type, From)`
/// - [`SetCoefficient`](crate::traits::SetCoefficient) with the signature
///   `($bridge_type, $type, SetCoefficient)`
/// - [`MatrixSetEntry`](crate::traits::MatrixSetEntry) with the signature
///   `($bridge_type, $type, SetCoefficient)`
///
/// # Examples
/// ```compile_fail
/// implement_for_owned!(Q, Q, PolyOverQ, Evaluate);
/// implement_for_owned!(Zq, PolyOverZq, From);
/// implement_for_owned!(Z, PolyOverZ, SetCoefficient);
/// implement_for_owned!(Z, MatZq, MatrixSetEntry);
/// ```
macro_rules! implement_for_owned {
    // [`Evaluate`] trait
    ($source_type:ident, $output_type:ident, $type:ident, Evaluate) => {
        impl Evaluate<$source_type, $output_type> for $type {
            paste::paste! {
                #[doc = "Documentation can be found at [`" $type "::evaluate`] for &[`" $source_type "`]."]
            fn evaluate(
                &self,
                value: $source_type
            ) -> $output_type {
                self.evaluate(&value)
            }
            }
        }
    };

    // [`From`] trait
    ($source_type:ident, $type:ident, From) => {
        impl From<$source_type> for $type {
            paste::paste! {
                #[doc = "Documentation can be found at [`" $type "::from`] for &[`" $source_type "`]."]
            fn from(
                value: $source_type
            ) -> Self {
                Self::from(&value)
            }
            }
        }
    };

    // [`SetCoefficient`] trait
    ($source_type:ident, $type:ident, SetCoefficient) => {
        impl SetCoefficient<$source_type> for $type {
            paste::paste! {
                #[doc = "Documentation can be found at [`" $type "::set_coeff`] for &[`" $source_type "`]."]
            unsafe fn set_coeff_unchecked(
                &mut self,
                index: i64,
                value: $source_type,
            ) {
                unsafe { self.set_coeff_unchecked(index, &value) }
            }
            }
        }
    };

    // [`MatrixSetEntry`] trait
    ($source_type:ident, $type:ident, MatrixSetEntry) => {
        impl MatrixSetEntry<$source_type> for $type {
            paste::paste! {
                #[doc = "Documentation can be found at [`" $type "::set_entry`] for &[`" $source_type "`]."]
                fn set_entry(
                    &mut self,
                    row: impl TryInto<i64> + Display,
                    column: impl TryInto<i64> + Display,
                    value: $source_type,
                ) -> Result<(), MathError> {
                    self.set_entry(row, column, &value)
                }

                #[doc = "Documentation can be found at [`" $type "::set_entry`] for &[`" $source_type "`]."]
                unsafe fn set_entry_unchecked(
                    &mut self,
                    row: i64,
                    column: i64,
                    value: $source_type,
                ) {
                    unsafe { self.set_entry_unchecked(row, column, &value) };
                }
            }
        }
    };
}

pub(crate) use implement_for_owned;

/// Implements a trait with an empty implementation for the specified types
/// and their references.
/// This macro can be used for empty traits or to use just the
/// default implementation of a trait.
///
/// # Examples
/// ```compile_fail
/// implement_empty_trait!(IntoZ for u8 u16 u32 u64 i8 i16 i32 i64);
/// ```
macro_rules! implement_empty_trait_owned_ref {
    ($trait_name:ident for $($type:ty)*) => {
      $(
        impl $trait_name for $type {}
        impl $trait_name for &$type {}
      )*
    };
}
pub(crate) use implement_empty_trait_owned_ref;

/// Implements the `*trait*` for `*type*` using an implementation for `*other_type*`.
///
/// **Warning**: Only works for commutative operations.
///
/// Parameters:
/// - `trait`: the trait that is implemented
///   (e.g. [`PartialEq`],[`PartialOrd`], ...).
/// - `trait_function`: the function the trait implements
///   (e.g. eq for [`PartialEq`], ...).
/// - `type`: the type the trait is implemented for
///   (e.g. [`Z`](crate::integer::Z),[`Q`](crate::rational::Q))
/// - `other_type`: the type the second part of the computation.
/// - `output_type`: the type of the result (e.g. bool for [`PartialEq`], ...).
///
/// Returns the owned Implementation code for the `*trait*`
/// trait with the signature:
///
/// ```impl *trait<*other_type*>* for *type*```
macro_rules! implement_trait_reverse {
    ($trait:ident, $trait_function:ident, $type:ident, $other_type:ident, $output_type:ident) => {
        #[doc(hidden)]
        impl $trait<$other_type> for $type {
            paste::paste! {
                fn $trait_function(&self, other: &$other_type) -> $output_type {
                    other.$trait_function(self)
                }
            }
        }
    };
}

pub(crate) use implement_trait_reverse;