1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161
/****************************************************************************** * 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) } } }