norman 0.0.4

Implementations of different norms for elements of vector spaces
Documentation
/******************************************************************************
 * Copyright 2019 Manuel Simon
 * This file is part of the norman library.
 *
 * Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
 * https://www.apache.org/licenses/LICENSE-2.0> or the MIT license
 * <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your
 * option. This file may not be copied, modified, or distributed
 * except according to those terms.
 *****************************************************************************/

//! A collection of norm descriptors.
//!
//! A norm descriptor specifies a norm. The most important ones
//! are the [`Abs`](desc::Abs)-norm for primitive floating point types
//! and complex numbers,
//! [`Sup`](desc::Sup) for the supremum norm,
//! and [`PNorm`](desc::PNorm) which represents a mathematical _p_-norm.

use std::num::NonZeroU32;

use noisy_float::prelude::R32;

/// A norm that is defined by an absolute value function on a field.
///
/// This is used for implementing the norms on types which represent
/// a mathematical field, like the primitive floating point types
/// (representing the field of real numbers) or the [`num_complex::Complex`] types
/// (representing the field of complex numbers).
///
/// It can be seen as the most _primitive_ kind of norm.
///
/// It is the only kind of norm that is used for further generic implementations,
/// i.e. there are impls of the form `impl<T: Norm<Abs>> Norm<SomeNorm> for SomeType<T>`.
#[derive(Debug, Clone, Copy, Default, PartialEq, Eq, Hash)]
pub struct Abs {}

impl Abs {
    /// Creates an `Abs` norm.
    pub fn new() -> Self {
        Abs {}
    }
}

/// A norm descriptor that represents the supremum norm.
///
/// As the supremum norm does not need additional specification,
/// there is only one value of this type: [`Sup::new()`](Sup::new).
#[derive(Debug, Clone, Copy, Default, PartialEq, Eq, Hash)]
pub struct Sup {}

impl Sup {
    /// Creates a `Sup`.
    pub fn new() -> Self {
        Sup {}
    }
}

/// A norm descriptor that represents an integral-valued
/// _p_-norm.
///
/// Create one with [`new`](PNorm::new).
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub struct PNorm {
    pub(crate) p: NonZeroU32
}

impl Default for PNorm {
    fn default() -> Self {
        PNorm {
            p: NonZeroU32::new(2).unwrap()
        }
    }
}

impl PNorm {
    /// Creates a descriptor of the `p`-norm.
    ///
    /// # Panics
    ///
    /// If `p` is zero.
    pub fn new(p: u32) -> Self {
        PNorm {
            p: NonZeroU32::new(p).unwrap()
        }
    }

    /// Creates a descriptor of the euclidean norm, i.e. the 2-norm.
    pub fn eucl() -> Self {
        PNorm {
            p: NonZeroU32::new(2).unwrap()
        }
    }

    /// Creates a descriptor of the 1-norm.
    pub fn p1() -> Self {
        PNorm {
            p: NonZeroU32::new(1).unwrap()
        }
    }
}

/// A descriptor that represents a real-valued _p_-norm.
///
/// Create one with [`new`](PNormReal::new) or [`from_f32`](PNormReal::from_f32).
///
/// If you only need a real valued _p_, consider using
/// [`PNorm`] instead since it only calculates integral powers.
///
/// Negative values for _p_ are completely allowed and there will be no
/// bad behaviour if one tries to calculate a _p_-norm with a negative _p_,
/// but the result will probably be mathematical nonsense.
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub struct PNormReal {
    pub(crate) p: R32
}

impl PNormReal {
    /// Creates a descriptor of the `p`-norm.
    ///
    /// A “NaN-norm” or “Inf-norm” does not make sense,
    /// so p-norms are represented by a [`noisy_float`] which cannot be Nan
    /// or +/- Infinity.
    pub fn new(p: R32) -> Self {
        PNormReal {
            p
        }
    }

    /// Creates a descriptor of the `p`-norm.
    pub fn from_u16(p: u16) -> Self {
        PNormReal {
            p: R32::from_f32(<f32 as From<u16>>::from(p))
        }
    }

    /// Creates a descriptor of the `p`-norm.
    ///
    /// # Panics
    ///
    /// If `p` is NaN or +/- Infinity
    pub fn from_f32(p: f32) -> Self {
        PNormReal {
            p: R32::from_f32(p)
        }
    }

    /// Creates a descriptor of the euclidean norm, i.e. the 2-norm.
    pub fn eucl() -> Self {
        PNormReal {
            p: R32::from_f32(2.0)
        }
    }

    /// Creates a descriptor of the 1-norm.
    pub fn p1() -> Self {
        PNormReal {
            p: R32::from_f32(1.0)
        }
    }
}