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 itkNumericTraitsVariableLengthVectorPixel_h
19 #define itkNumericTraitsVariableLengthVectorPixel_h
20 
21 #include "itkVariableLengthVector.h"
22 
23 // This work is part of the National Alliance for Medical Image Computing
24 // (NAMIC), funded by the National Institutes of Health through the NIH Roadmap
25 // for Medical Research, Grant U54 EB005149.
26 
27 namespace itk
28 {
29 /**
30  * \brief Define numeric traits for VariableLengthVector.
31  * \tparam T Component type of VariableLenghtVector
32  *
33  * We provide here a generic implementation based on creating types of
34  * VariableLengthVector whose components are the types of the NumericTraits from
35  * the original VariableLengthVector components. This implementation require
36  * support for partial specializations, since it is based on the
37  * concept that:
38  *   NumericTraits<VariableLengthVector< T > >  is defined piecewise by
39  *   VariableLengthVector< NumericTraits< T > >
40  *
41  * \note The Zero(), One(), min() and max() methods here take
42  * references to a pixel as input.  This is due to the fact that the
43  * length of the VariableLengthVector is not known until
44  * run-time. Since the most common use of Zero and One is for
45  * comparison purposes or initialization of sums etc, this might just
46  * as easily be re-written with a pixel passed in as a reference and
47  * the length is inferred from this pixel.
48  *
49  * \sa NumericTraits
50  * \ingroup DataRepresentation
51  * \ingroup ITKCommon
52  */
53 template< typename T >
54 class NumericTraits< VariableLengthVector< T > >
55 {
56 public:
57 
58   using ElementAbsType = typename NumericTraits< T >::AbsType;
59   using ElementAccumulateType = typename NumericTraits< T >::AccumulateType;
60   using ElementFloatType = typename NumericTraits< T >::FloatType;
61   using ElementPrintType = typename NumericTraits< T >::PrintType;
62   using ElementRealType = typename NumericTraits< T >::RealType;
63 
64   /** Return the type of the native component type. */
65   using ValueType = T;
66 
67   using Self = VariableLengthVector< T >;
68 
69   /** Unsigned component type */
70   using AbsType = VariableLengthVector< ElementAbsType >;
71 
72   /** Accumulation of addition and multiplication. */
73   using AccumulateType = VariableLengthVector< ElementAccumulateType >;
74 
75   /** Typedef for operations that use floating point instead of real precision
76     */
77   using FloatType = VariableLengthVector< ElementFloatType >;
78 
79   /** Return the type that can be printed. */
80   using PrintType = VariableLengthVector< ElementPrintType >;
81 
82   /** Type for real-valued scalar operations. */
83   using RealType = VariableLengthVector< ElementRealType >;
84 
85   /** Type for real-valued scalar operations. */
86   using ScalarRealType = ElementRealType;
87 
88   /** Measurement vector type */
89   using MeasurementVectorType = Self;
90 
91   /** Component wise defined element
92    *
93    * \note minimum value for floating pointer types is defined as
94    * minimum positive normalize value.
95    */
max(const Self & a)96   static const Self max(const Self & a)
97   {
98     Self b( a.Size() );
99 
100     b.Fill( NumericTraits< T >::max() );
101     return b;
102   }
103 
min(const Self & a)104   static const Self min(const Self & a)
105   {
106     Self b( a.Size() );
107 
108     b.Fill( NumericTraits< T >::min() );
109     return b;
110   }
111 
ZeroValue(const Self & a)112   static const Self ZeroValue(const Self  & a)
113   {
114     Self b( a.Size() );
115 
116     b.Fill(NumericTraits< T >::ZeroValue());
117     return b;
118   }
119 
OneValue(const Self & a)120   static const Self OneValue(const Self & a)
121   {
122     Self b( a.Size() );
123 
124     b.Fill(NumericTraits< T >::OneValue());
125     return b;
126   }
127 
NonpositiveMin(const Self & a)128   static const Self NonpositiveMin(const Self & a)
129   {
130     Self b( a.Size() );
131     b.Fill( NumericTraits< T >::NonpositiveMin() );
132     return b;
133   }
134 
IsPositive(const Self & a)135   static bool IsPositive( const Self & a)
136   {
137     bool flag = false;
138     for (unsigned int i=0; i < GetLength( a ); i++)
139       {
140       if ( a[i] > NumericTraits< ValueType >::ZeroValue() )
141         {
142         flag = true;
143         }
144       }
145     return flag;
146   }
147 
IsNonpositive(const Self & a)148   static bool IsNonpositive( const Self & a)
149   {
150     bool flag = false;
151     for (unsigned int i=0; i < GetLength( a ); i++)
152       {
153       if ( ! (a[i] > 0.0 ) )
154         {
155         flag = true;
156         }
157       }
158     return flag;
159   }
160 
IsNegative(const Self & a)161   static bool IsNegative( const Self & a)
162   {
163     bool flag = false;
164     for (unsigned int i=0; i < GetLength( a ); i++)
165       {
166       if ( a[i] < NumericTraits< ValueType >::ZeroValue() )
167         {
168         flag = true;
169         }
170       }
171     return flag;
172   }
173 
IsNonnegative(const Self & a)174   static bool IsNonnegative( const Self & a)
175   {
176     bool flag = false;
177     for (unsigned int i=0; i < GetLength( a ); i++)
178       {
179       if ( ! (a[i] < 0.0 ))
180         {
181         flag = true;
182         }
183       }
184     return flag;
185   }
186 
187   static constexpr bool IsSigned = NumericTraits< ValueType >::IsSigned;
188   static constexpr bool IsInteger = NumericTraits< ValueType >::IsInteger;
189   static constexpr bool IsComplex = NumericTraits< ValueType >::IsComplex;
190 
191 
192   /** Resize the input vector to the specified size. */
SetLength(VariableLengthVector<T> & m,const unsigned int s)193   static void SetLength(VariableLengthVector< T > & m, const unsigned int s)
194   {
195     m.SetSize(s);
196     m.Fill(NumericTraits< T >::ZeroValue());
197   }
198 
199   /** Return the size of the vector. */
GetLength(const VariableLengthVector<T> & m)200   static unsigned int GetLength(const VariableLengthVector< T > & m)
201   {
202     return m.GetSize();
203   }
204 
AssignToArray(const Self & v,MeasurementVectorType & mv)205   static void AssignToArray( const Self & v, MeasurementVectorType & mv )
206   {
207     mv = v;
208   }
209 
210   template<typename TArray>
AssignToArray(const Self & v,TArray & mv)211   static void AssignToArray( const Self & v, TArray & mv )
212   {
213     for( unsigned int i=0; i<GetLength(v); i++ )
214       {
215       mv[i] = v[i];
216       }
217   }
218 
219 };
220 } // end namespace itk
221 
222 #endif // itkNumericTraitsVariableLengthVector_h
223