/*========================================================================= * * Copyright NumFOCUS * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * https://www.apache.org/licenses/LICENSE-2.0.txt * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * *=========================================================================*/ #ifndef itkNumericTraitsVariableLengthVectorPixel_h #define itkNumericTraitsVariableLengthVectorPixel_h #include "itkVariableLengthVector.h" // This work is part of the National Alliance for Medical Image Computing // (NAMIC), funded by the National Institutes of Health through the NIH Roadmap // for Medical Research, Grant U54 EB005149. namespace itk { /** * \brief Define numeric traits for VariableLengthVector. * \tparam T Component type of VariableLengthVector * * We provide here a generic implementation based on creating types of * VariableLengthVector whose components are the types of the NumericTraits from * the original VariableLengthVector components. This implementation require * support for partial specializations, since it is based on the * concept that: * NumericTraits > is defined piecewise by * VariableLengthVector< NumericTraits< T > > * * \note The Zero(), One(), min() and max() methods here take * references to a pixel as input. This is due to the fact that the * length of the VariableLengthVector is not known until * run-time. Since the most common use of Zero and One is for * comparison purposes or initialization of sums etc, this might just * as easily be re-written with a pixel passed in as a reference and * the length is inferred from this pixel. * * \sa NumericTraits * \ingroup DataRepresentation * \ingroup ITKCommon */ template class NumericTraits> { public: using ElementAbsType = typename NumericTraits::AbsType; using ElementAccumulateType = typename NumericTraits::AccumulateType; using ElementFloatType = typename NumericTraits::FloatType; using ElementPrintType = typename NumericTraits::PrintType; using ElementRealType = typename NumericTraits::RealType; /** Return the type of the native component type. */ using ValueType = T; using Self = VariableLengthVector; /** Unsigned component type */ using AbsType = VariableLengthVector; /** Accumulation of addition and multiplication. */ using AccumulateType = VariableLengthVector; /** Typedef for operations that use floating point instead of real precision */ using FloatType = VariableLengthVector; /** Return the type that can be printed. */ using PrintType = VariableLengthVector; /** Type for real-valued scalar operations. */ using RealType = VariableLengthVector; /** Type for real-valued scalar operations. */ using ScalarRealType = ElementRealType; /** Measurement vector type */ using MeasurementVectorType = Self; /** Component wise defined element * * \note minimum value for floating pointer types is defined as * minimum positive normalize value. */ static const Self max(const Self & a) { Self b(a.Size()); b.Fill(NumericTraits::max()); return b; } static const Self min(const Self & a) { Self b(a.Size()); b.Fill(NumericTraits::min()); return b; } static const Self ZeroValue(const Self & a) { Self b(a.Size()); b.Fill(T{}); return b; } static const Self OneValue(const Self & a) { Self b(a.Size()); b.Fill(NumericTraits::OneValue()); return b; } static const Self NonpositiveMin(const Self & a) { Self b(a.Size()); b.Fill(NumericTraits::NonpositiveMin()); return b; } static bool IsPositive(const Self & a) { bool flag = false; for (unsigned int i = 0; i < GetLength(a); ++i) { if (a[i] > ValueType{}) { flag = true; } } return flag; } static bool IsNonpositive(const Self & a) { bool flag = false; for (unsigned int i = 0; i < GetLength(a); ++i) { if (!(a[i] > 0.0)) { flag = true; } } return flag; } static bool IsNegative(const Self & a) { bool flag = false; for (unsigned int i = 0; i < GetLength(a); ++i) { if (a[i] < ValueType{}) { flag = true; } } return flag; } static bool IsNonnegative(const Self & a) { bool flag = false; for (unsigned int i = 0; i < GetLength(a); ++i) { if (!(a[i] < 0.0)) { flag = true; } } return flag; } static constexpr bool IsSigned = std::is_signed_v; static constexpr bool IsInteger = std::is_integral_v; static constexpr bool IsComplex = NumericTraits::IsComplex; /** Resize the input vector to the specified size. */ static void SetLength(VariableLengthVector & m, const unsigned int s) { m.SetSize(s); m.Fill(T{}); } /** Return the size of the vector. */ static unsigned int GetLength(const VariableLengthVector & m) { return m.GetSize(); } static void AssignToArray(const Self & v, MeasurementVectorType & mv) { mv = v; } template static void AssignToArray(const Self & v, TArray & mv) { for (unsigned int i = 0; i < GetLength(v); ++i) { mv[i] = v[i]; } } }; } // end namespace itk #endif // itkNumericTraitsVariableLengthVector_h