1 /*=========================================================================
2  *
3  *  Copyright Insight Software Consortium
4  *
5  *  Licensed under the Apache License, Version 2.0 (the "License");
6  *  you may not use this file except in compliance with the License.
7  *  You may obtain a copy of the License at
8  *
9  *         http://www.apache.org/licenses/LICENSE-2.0.txt
10  *
11  *  Unless required by applicable law or agreed to in writing, software
12  *  distributed under the License is distributed on an "AS IS" BASIS,
13  *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  *  See the License for the specific language governing permissions and
15  *  limitations under the License.
16  *
17  *=========================================================================*/
18 #ifndef itkNumericTraitsCovariantVectorPixel_h
19 #define itkNumericTraitsCovariantVectorPixel_h
20 
21 #include "itkNumericTraits.h"
22 #include "itkCovariantVector.h"
23 
24 namespace itk
25 {
26 /**
27  * \brief Define numeric traits for CovariantVector.
28  * \tparam T Component type of CovariantVector
29  * \tparam D Dimension of the CovariantVector
30  *
31  * We provide here a generic implementation based on creating types of
32  * CovariantVector whose components are the types of the NumericTraits from
33  * the original CovariantVector components. This implementation require
34  * support for partial specializations, since it is based on the
35  * concept that:
36  *   NumericTraits<CovariantVector<T,D>>  is defined piecewise by
37  *   CovariantVector<NumericTraits<T>>
38  *
39  * \sa NumericTraits
40  * \ingroup DataRepresentation
41  * \ingroup ITKCommon
42  */
43 template< typename T, unsigned int D >
44 class NumericTraits< CovariantVector< T, D > >
45 {
46 private:
47 
48   using ElementAbsType = typename NumericTraits< T >::AbsType;
49   using ElementAccumulateType = typename NumericTraits< T >::AccumulateType;
50   using ElementFloatType = typename NumericTraits< T >::FloatType;
51   using ElementPrintType = typename NumericTraits< T >::PrintType;
52   using ElementRealType = typename NumericTraits< T >::RealType;
53 
54 public:
55 
56   /** Return the type of the native component type. */
57   using ValueType = T;
58 
59   using Self = CovariantVector< T, D >;
60 
61   /** Unsigned component type */
62   using AbsType = CovariantVector< ElementAbsType, D >;
63 
64   /** Accumulation of addition and multiplication. */
65   using AccumulateType = CovariantVector< ElementAccumulateType, D >;
66 
67   /** Typedef for operations that use floating point instead of real precision
68     */
69   using FloatType = CovariantVector< ElementFloatType, D >;
70 
71   /** Return the type that can be printed. */
72   using PrintType = CovariantVector< ElementPrintType, D >;
73 
74   /** Type for real-valued scalar operations. */
75   using RealType = CovariantVector< ElementRealType, D >;
76 
77   /** Type for real-valued scalar operations. */
78   using ScalarRealType = ElementRealType;
79 
80   /** Measurement vector type */
81   using MeasurementVectorType = Self;
82 
83   /** Component wise defined element
84    *
85    * \note minimum value for floating pointer types is defined as
86    * minimum positive normalize value.
87    */
max(const Self &)88   static const Self max(const Self &)
89   {
90     return Self( NumericTraits< T >::max() );
91   }
92 
min(const Self &)93   static const Self min(const Self &)
94   {
95     return Self( NumericTraits< T >::min() );
96   }
97 
max()98   static const Self max()
99   {
100     return Self( NumericTraits< T >::max() );
101   }
102 
min()103   static const Self min()
104   {
105     return Self( NumericTraits< T >::min() );
106   }
107 
NonpositiveMin()108   static const Self NonpositiveMin()
109   {
110     return Self( NumericTraits< T >::NonpositiveMin() );
111   }
112 
ZeroValue()113   static const Self ZeroValue()
114   {
115     return Self( NumericTraits< T >::ZeroValue() );
116   }
117 
OneValue()118   static const Self OneValue()
119   {
120     return Self( NumericTraits< T >::OneValue() );
121   }
122 
NonpositiveMin(const Self &)123   static const Self NonpositiveMin(const Self &)
124   {
125     return NonpositiveMin();
126   }
127 
ZeroValue(const Self &)128   static const Self ZeroValue(const Self &)
129   {
130     return ZeroValue();
131   }
132 
OneValue(const Self &)133   static const Self OneValue(const Self &)
134   {
135     return OneValue();
136   }
137 
138   static constexpr bool IsSigned = NumericTraits< ValueType >::IsSigned;
139   static constexpr bool IsInteger = NumericTraits< ValueType >::IsInteger;
140   static constexpr bool IsComplex = NumericTraits< ValueType >::IsComplex;
141 
142   /** Fixed length vectors cannot be resized, so an exception will
143    *  be thrown if the input size is not valid.  If the size is valid
144    *  the vector will be filled with zeros. */
SetLength(CovariantVector<T,D> & m,const unsigned int s)145   static void SetLength(CovariantVector< T, D > & m, const unsigned int s)
146   {
147     if ( s != D )
148       {
149       itkGenericExceptionMacro(<< "Cannot set the size of a CovariantVector of length "
150                                << D << " to " << s);
151       }
152     m.Fill(NumericTraits< T >::ZeroValue());
153   }
154 
155   /** Return the length of the vector. */
GetLength(const CovariantVector<T,D> &)156   static unsigned int GetLength(const CovariantVector< T, D > &)
157   {
158     return D;
159   }
160 
161   /** Return the length of the vector. */
GetLength()162   static unsigned int GetLength()
163   {
164     return D;
165   }
166 
AssignToArray(const Self & v,MeasurementVectorType & mv)167   static void AssignToArray( const Self & v, MeasurementVectorType & mv )
168   {
169     mv = v;
170   }
171 
172   template<typename TArray>
AssignToArray(const Self & v,TArray & mv)173   static void AssignToArray( const Self & v, TArray & mv )
174   {
175     for( unsigned int i=0; i<D; i++ )
176       {
177       mv[i] = v[i];
178       }
179   }
180 
181   /** \note: the functions are preferred over the member variables as
182    * they are defined for all partial specialization
183    */
184   static const Self ITKCommon_EXPORT Zero;
185   static const Self ITKCommon_EXPORT One;
186 };
187 } // end namespace itk
188 
189 #endif // itkNumericTraitsCovariantVectorPixel_h
190