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 itkVariableLengthVector_h 19 #define itkVariableLengthVector_h 20 21 #include <cassert> 22 #include <algorithm> 23 #include "itkNumericTraits.h" 24 #include "itkStaticAssert.h" 25 #include "itkMetaProgrammingLibrary.h" 26 #include "itkEnableIf.h" 27 #include "itkIsBaseOf.h" 28 #include "itkIsNumber.h" 29 #include "itkPromoteType.h" 30 #include "itkBinaryOperationConcept.h" 31 32 namespace itk 33 { 34 35 template <typename TExpr1, typename TExpr2, typename TBinaryOp> 36 struct VariableLengthVectorExpression; 37 38 /** \class VariableLengthVector 39 * \brief Represents an array whose length can be defined at run-time. 40 * 41 * This class is templated over the data type. This data-type is meant 42 * to be a scalar, such as float, double etc... 43 * 44 * \note 45 * ITK itself provides several classes that can serve as \c Arrays. 46 * \li FixedArray - Compile time fixed length arrays that's intended to 47 * represent an enumerated collection of \c n entities. 48 * 49 * \li Array - Run time resizeable array that is intended to hold a 50 * collection of \c n entities 51 * 52 * \li Vector - Compile time fixed length array that is intended to hold 53 * a collection of \c n data types. A vector usually has a mathematical meaning. 54 * It should only be used when mathematical operations such as addition, 55 * multiplication by a scalar, product etc make sense. 56 * 57 * \li VariableLengthVector - Run time array that is intended to hold a collection 58 * of scalar data types. Again, it should be used only when mathematical 59 * operations on it are relevant. If not, use an Array. 60 * 61 * \li Point - Represents the spatial coordinates of a spatial location. Operators 62 * on Point reflect geometrical concepts. 63 * 64 * \par For the reasons listed above, you cannot instantiate 65 * \code VariableLengthVector< bool > \endcode. 66 * 67 * \par 68 * Design Considerations: We do not derive from \c vnl_vector to avoid being 69 * limited by the explicit template instantiations of vnl_vector and other 70 * hacks that vnl folks have been forced to use. 71 * 72 * \note 73 * This work is part of the National Alliance for Medical Image Computing 74 * (NAMIC), funded by the National Institutes of Health through the NIH Roadmap 75 * for Medical Research, Grant U54 EB005149. 76 * 77 * \sa CovariantVector 78 * \sa SymmetricSecondRankTensor 79 * \sa RGBPixel 80 * \sa DiffusionTensor3D 81 * \ingroup DataRepresentation 82 * \ingroup ITKCommon 83 * 84 * \wiki 85 * \wikiexample{SimpleOperations/VariableLengthVector,Variable length vector} 86 * \endwiki 87 * 88 * \invariant If \c m_LetArrayManageMemory is true, \c m_Data is deletable 89 * (whether it's null or pointing to something with no elements. i.e. \c 90 * m_NumElements may be 0 and yet \c m_Data may be not null.) 91 */ 92 template< typename TValue > 93 class ITK_TEMPLATE_EXPORT VariableLengthVector 94 { 95 public: 96 /**\name Policies 97 * The following Policies will be used by \c itk::VariableLengthVector::SetSize 98 */ 99 //@{ 100 /** \c VariableLengthVector empty base-class for allocation policies. 101 * All Allocation Policies are expected to inherit from this empty base 102 * class. 103 * 104 * \sa \c itk::VariableLengthVector::SetSize 105 * \sa \c NeverReallocate 106 * \sa \c ShrinkToFit 107 * \sa \c DontShrinkToFit 108 * \ingroup ITKCommon 109 * \ingroup DataRepresentation 110 */ 111 struct AllocateRootPolicy {}; 112 113 /** \c VariableLengthVector Allocation Policy: Always reallocate memory. 114 * This policy, when used from \c VariableLengthVector::SetSize(), always 115 * implies that the previous internal buffer will be reallocated. Even if 116 * enough memory was available. 117 * \return true (always) 118 * 119 * \sa \c itk::VariableLengthVector::SetSize 120 * \sa \c NeverReallocate 121 * \sa \c ShrinkToFit 122 * \sa \c DontShrinkToFit 123 * \ingroup ITKCommon 124 * \ingroup DataRepresentation 125 */ 126 struct AlwaysReallocate : AllocateRootPolicy 127 { operatorAlwaysReallocate128 bool operator()(unsigned int itkNotUsed(newSize), unsigned int itkNotUsed(oldSize)) const 129 { 130 return true; 131 } 132 }; 133 134 /** \c VariableLengthVector Allocation Policy: Never reallocate memory. 135 * This policy, when used from \c VariableLengthVector::SetSize(), always 136 * implies that the previous internal buffer will be kept. Even if not enough 137 * memory was available. 138 * 139 * The typical use case of this policy is to make sure a \c 140 * VariableLengthVector is not a proxy object. 141 * \return false (always) 142 * 143 * \pre <tt>oldSize == newSize</tt>, checked by assertion 144 * 145 * \sa \c itk::VariableLengthVector::SetSize 146 * \sa \c AlwaysReallocate 147 * \sa \c ShrinkToFit 148 * \sa \c DontShrinkToFit 149 * \ingroup ITKCommon 150 * \ingroup DataRepresentation 151 */ 152 struct NeverReallocate : AllocateRootPolicy 153 { operatorNeverReallocate154 bool operator()(unsigned int newSize, unsigned int oldSize) const 155 { 156 (void) newSize; 157 (void) oldSize; 158 itkAssertInDebugAndIgnoreInReleaseMacro(newSize == oldSize && "SetSize is expected to never change the VariableLengthVector size..."); 159 return true; 160 } 161 }; 162 163 /** \c VariableLengthVector Allocation Policy: reallocate memory only when 164 * size changes. 165 * This policy, when used from \c VariableLengthVector::SetSize(), will 166 * reallocate the internal buffer only if the size of the \c 167 * VariableLengthVector changes. 168 * \return whether \c newSize differs from \c oldSize 169 * 170 * \note The name is related to \c DontShrinkToFit reallocation policy that 171 * will avoid reallocating when enough memory has already been allocated. 172 * 173 * \sa \c itk::VariableLengthVector::SetSize 174 * \sa \c AlwaysReallocate 175 * \sa \c NeverReallocate 176 * \sa \c DontShrinkToFit 177 * \ingroup ITKCommon 178 * \ingroup DataRepresentation 179 */ 180 struct ShrinkToFit : AllocateRootPolicy 181 { operatorShrinkToFit182 bool operator()(unsigned int newSize, unsigned int oldSize) const 183 { return newSize != oldSize; } 184 }; 185 186 /** \c VariableLengthVector Allocation Policy: reallocate memory only when 187 * size increases. 188 * This policy, when used from \c VariableLengthVector::SetSize(), will 189 * reallocate the internal buffer only if the new size requested for the \c 190 * VariableLengthVector increases. 191 * \return whether \c newSize is bigger than \c oldSize 192 * 193 * \warning Unlike classes like \c std::vector<>, \c VariableLengthVector has 194 * no capacity concept: the size of the \c VariableLengthVector is its 195 * capacity. However, this will help a class without capacity to emulate one. 196 * The consequence is that reallocations will occur with scenarios such as 197 * the following: 198 \code 199 VariableLengthVector<...> v; 200 v.SetSize(42); 201 v.SetSize(12); // no reallocation 202 v.SetSize(42); // pointless reallocation (given this policy) 203 \endcode 204 * 205 * \sa \c itk::VariableLengthVector::SetSize 206 * \sa \c AlwaysReallocate 207 * \sa \c NeverReallocate 208 * \sa \c ShrinkToFit 209 * \ingroup ITKCommon 210 * \ingroup DataRepresentation 211 */ 212 struct DontShrinkToFit : AllocateRootPolicy 213 { operatorDontShrinkToFit214 bool operator()(unsigned int newSize, unsigned int oldSize) const 215 { return newSize > oldSize; } 216 }; 217 218 /** \c VariableLengthVector empty base-class for values Keeping policies. 219 * All Values Keeping Policies are expected to inherit from this empty base 220 * class. 221 * 222 * The preconditions common to all sub classes are: 223 * \pre This policy is only meant to be executed in case of reallocation, 224 * i.e. \c oldBuffer and \c newBuffer are expected to differ (unchecked). 225 * \pre This presumes \c TValue assignment is a \c noexcept operation. 226 * \pre \c newBuffer is not null (pre-conditions imposed by some 227 * implementations of \c std::copy()) 228 * \pre `[oldBuffer, oldBuffer+oldSize)` is a valid range 229 * 230 * \sa \c itk::VariableLengthVector::SetSize 231 * \sa \c KeepOldValues 232 * \sa \c DumpOldValues 233 * \ingroup ITKCommon 234 * \ingroup DataRepresentation 235 */ 236 struct KeepValuesRootPolicy {}; 237 238 /** \c VariableLengthVector Invariability Policy: Always keep old values. 239 * This policy, when used from \c VariableLengthVector::SetSize(), always 240 * copies <tt>min(newSize,oldSize)</tt> previous values from the previous 241 * internal buffer to the new one 242 * 243 * \pre This policy is only meant to be executed in case of reallocation, 244 * i.e. \c oldBuffer and \c newBuffer are expected to differ (unchecked). 245 * \pre This presumes \c TValue assignment is a \c noexcept operation. 246 * \pre \c newBuffer is not null (pre-conditions imposed by some 247 * implementations of \c std::copy()) 248 * \pre `[oldBuffer, oldBuffer+oldSize)` is a valid range 249 * 250 * This behaviour mimics \c std::vector<>::resize() behaviour. However, it 251 * makes to sense from \c VariableLengthVector::operator=() 252 * 253 * \sa \c itk::VariableLengthVector::SetSize 254 * \sa \c KeepValuesRootPolicy 255 * \sa \c DumpOldValues 256 * \ingroup ITKCommon 257 * \ingroup DataRepresentation 258 */ 259 struct KeepOldValues : KeepValuesRootPolicy 260 { 261 template <typename TValue2> operatorKeepOldValues262 void operator()( 263 unsigned int newSize, unsigned int oldSize, 264 TValue2 * oldBuffer, TValue2 * newBuffer) const 265 { 266 itkAssertInDebugAndIgnoreInReleaseMacro(newBuffer); 267 const std::size_t nb = std::min(newSize, oldSize); 268 itkAssertInDebugAndIgnoreInReleaseMacro(nb == 0 || (nb > 0 && oldBuffer != nullptr)); 269 std::copy(oldBuffer, oldBuffer+nb, newBuffer); 270 } 271 }; 272 273 /** \c VariableLengthVector Invariability Policy: Never keep old values. 274 * This policy, when used from \c VariableLengthVector::SetSize(), is a no-op. 275 * It won't try to copy previous values from the previous internal buffer to 276 * the new one. 277 * 278 * \pre This policy is only meant to be executed in case of reallocation, 279 * i.e. \c oldBuffer and \c newBuffer are expected to differ (unchecked). 280 * 281 * This behaviour particularly fits \c VariableLengthVector::operator=() 282 * 283 * \sa \c itk::VariableLengthVector::SetSize 284 * \sa \c KeepValuesRootPolicy 285 * \sa \c DumpOldValues 286 * \ingroup ITKCommon 287 * \ingroup DataRepresentation 288 */ 289 struct DumpOldValues : KeepValuesRootPolicy 290 { 291 template <typename TValue2> operatorDumpOldValues292 void operator()( 293 unsigned int itkNotUsed(newSize), unsigned int itkNotUsed(oldSize), 294 TValue2 * itkNotUsed(oldBuffer), TValue2 * itkNotUsed(newBuffer)) const 295 { 296 } 297 }; 298 //@} 299 300 301 /** The element type stored at each location in the Array. */ 302 using ValueType = TValue; 303 using ComponentType = TValue; 304 using RealValueType = typename NumericTraits< ValueType >::RealType; 305 using Self = VariableLengthVector; 306 307 /** Typedef used to indicate the number of elements in the vector */ 308 using ElementIdentifier = unsigned int; 309 310 /** Default constructor. It is created with an empty array 311 * it has to be allocated later by assignment, \c SetSize() or \c Reserve(). 312 * \post \c m_Data is null 313 * \post \c m_NumElements is 0 314 * \post \c m_LetArrayManageMemory is true 315 */ 316 VariableLengthVector(); 317 318 /** Constructor with size. 319 * Size can only be changed by assignment, \c SetSize() or \c Reserve(). 320 * \post \c m_Data is not null and points to an array of \c m_NumElements, 321 * even if \c m_NumElements is 0 322 * \post values are left uninitialized. 323 * \post \c m_NumElements is \c dimension 324 * \post \c m_LetArrayManageMemory is true 325 */ 326 explicit VariableLengthVector(unsigned int dimension); 327 328 /** Constructor that initializes array with contents from a user supplied 329 * buffer. 330 * The pointer to the buffer and the length is specified. By default, the 331 * array does not manage the memory of the buffer. It merely points to that 332 * location and it is the user's responsibility to delete it. 333 * If \c LetArrayManageMemory is true, then this class will free the 334 * memory when this object is destroyed. 335 * 336 * \post `m_Data == data` 337 * \post values are left unmodified 338 * \post `m_NumElements == sz` 339 * \post `m_LetArrayManageMemory == LetArrayManageMemory` 340 */ 341 VariableLengthVector(ValueType *data, unsigned int sz, 342 bool LetArrayManageMemory = false); 343 344 /** Constructor that initializes array with contents from a user supplied 345 * buffer. 346 * The pointer to the buffer and the length is specified. By default, the 347 * array does not manage the memory of the buffer. It merely points to that 348 * location and it is the user's responsibility to delete it. 349 * If \c LetArrayManageMemory is true, then this class will free the 350 * memory when this object is destroyed. 351 * 352 * \warning This overload receives a non-modiable array, and yet it will let 353 * the end-user try to modify it through \c VariableLengthVector interface. 354 * Use this constructor with care as this may lead to undefined behaviour. 355 * Prefer using `VariableLengthVector<const TValue>` instead of 356 * `VariableLengthVector<TValue>` in case we which to use this constructor. 357 * 358 * \post `m_Data == data` 359 * \post values are left unmodified 360 * \post `m_NumElements == sz` 361 * \post `m_LetArrayManageMemory == LetArrayManageMemory` 362 */ 363 VariableLengthVector(const ValueType *data, unsigned int sz, 364 bool LetArrayManageMemory = false); 365 366 /** Copy constructor. The reason why the copy constructor and the assignment 367 * operator are templated is that it will allow implicit casts to be 368 * performed. For instance: 369 \code 370 VariableLengthVector< int > vI; 371 VariableLengthVector< float > vF( vI ); 372 or for instance vF = static_cast< VariableLengthVector< float > >( vI ); 373 \endcode 374 * \note However that static casting in this way will imply the allocation of 375 * a temporary \c VariableLengthVector. Prefer to directly use the assignment 376 * converting operator in code where uses of \c static_cast<> would be 377 * required. 378 * 379 * \post \c m_Data is not null and points to an array of \c m_NumElements, 380 * if \c m_NumElements is 0, otherwise it's null. 381 * \post values are left uninitialized. 382 * \post \c m_NumElements is \c v.GetSize() 383 * \post \c m_LetArrayManageMemory is true 384 */ 385 template< typename T > VariableLengthVector(const VariableLengthVector<T> & v)386 VariableLengthVector(const VariableLengthVector< T > & v) 387 { 388 m_NumElements = v.Size(); 389 m_LetArrayManageMemory = true; 390 if (m_NumElements != 0) 391 { 392 m_Data = this->AllocateElements(m_NumElements); 393 itkAssertInDebugAndIgnoreInReleaseMacro(m_Data != nullptr); 394 for ( ElementIdentifier i = 0; i < m_NumElements; ++i ) 395 { 396 this->m_Data[i] = static_cast< ValueType >( v[i] ); 397 } 398 } 399 else 400 { 401 m_Data = nullptr; 402 } 403 } 404 405 /** Copy constructor. Overrides the default non-templated copy constructor 406 * that the compiler provides. 407 * \post \c m_Data is not null and points to an array of \c m_NumElements, 408 * if \c m_NumElements is 0, otherwise it's null. 409 * \post values are left uninitialized. 410 * \post \c m_NumElements is \c v.GetSize() 411 * \post \c m_LetArrayManageMemory is true 412 */ 413 VariableLengthVector(const VariableLengthVector< TValue > & v); 414 415 /** Swaps two \c VariableLengthVector 's. 416 * \pre Expects either none of the \c VariableLengthVector to act as a proxy, 417 * or both, checked with an assertion. 418 * \post \c *this and \c old contents are swapped. 419 * \param[in,out] v other \c VariableLengthVector to be swapped with. 420 * \throw None 421 * \sa \c itk::swap() 422 */ Swap(Self & v)423 void Swap(Self & v) noexcept 424 { 425 itkAssertInDebugAndIgnoreInReleaseMacro(m_LetArrayManageMemory == v.m_LetArrayManageMemory); 426 using std::swap; 427 swap(v.m_Data , m_Data); 428 swap(v.m_NumElements, m_NumElements); 429 } 430 431 /** C++11 Move Constructor. 432 * \post \c v is destructible and assignable. 433 * \post `m_NumElements == 0` 434 * \post `m_LetArrayManageMemory == true` 435 * \post `m_Data == nullptr` 436 * \post Built object contains old \c v data. 437 */ 438 VariableLengthVector(Self && v) noexcept; 439 440 /** C++11 Move assignement operator. 441 * \pre \c v shall not be the same as the current object 442 * \post \c v is destructible and assignable. 443 * \post `m_NumElements == 0` 444 * \post `m_LetArrayManageMemory == true` 445 * \post `m_Data == nullptr` 446 * \post Current object contains old \c v data. 447 */ 448 Self & operator=(Self && v) noexcept; 449 450 /** Constructor from an Expression Template vector. 451 * \tparam TExpr1 Type of the left sub-expression 452 * \tparam TExpr2 Type of the right sub-expression 453 * \tparam TBinaryOp Binary Operation to apply to both sub-expressions. 454 * \param[in] rhs Non evaluated Expression Template. 455 * 456 * Builds the new \c VariableLengthVector with an expression template. The 457 * code loops over all components from the template expression, and evaluates 458 * them on the fly to fill the content of the new vector. 459 * 460 * \post \c m_Data is not null and points to an array of \c m_NumElements, 461 * even if \c m_NumElements is 0 462 * \post `*this == rhs` 463 * \post \c m_NumElements is \c rhs.GetSize() 464 * \post \c m_LetArrayManageMemory is true 465 */ 466 template <typename TExpr1, typename TExpr2, typename TBinaryOp> 467 VariableLengthVector(VariableLengthVectorExpression<TExpr1, TExpr2, TBinaryOp> const& rhs); 468 /** Assignment from an Expression Template vector. 469 * \tparam TExpr1 Type of the left sub-expression 470 * \tparam TExpr2 Type of the right sub-expression 471 * \tparam TBinaryOp Binary Operation to apply to both sub-expressions. 472 * \param[in] rhs Non evaluated Expression Template. 473 * 474 * Resets the new \c VariableLengthVector with an expression template. The 475 * code loops over all components from the template expression, and evaluates 476 * them on the fly to fill the content of the current vector. 477 * 478 * \post if called on a \c VariableLengthVector proxy, the referenced values 479 * are left unchanged. 480 * \post \c m_Data is not null and points to an array of \c m_NumElements, 481 * if \c m_NumElements is not 0. \c m_Data may be null otherwise (an empty 482 * vector is assigned into another empty vector) 483 * \post \c m_LetArrayManageMemory is true 484 * \post `GetSize() == rhs.GetSize()` 485 * \post `*this == rhs` 486 */ 487 template <typename TExpr1, typename TExpr2, typename TBinaryOp> 488 Self & operator=(VariableLengthVectorExpression<TExpr1, TExpr2, TBinaryOp> const& rhs); 489 490 /** Set the all the elements of the array to the specified value. 491 * \pre This function may be called on empty vectors, it's a no-op. 492 */ 493 void Fill(TValue const & v); 494 495 /** Converting assignment operator. 496 * \note Ensures a <em>String Exception Guarantee</em>: resists to 497 * self-assignment, and no changes are made if memory cannot be allocated to 498 * hold the new elements. This presumes \c TValue assignment is a \c 499 * noexcept operation. 500 * 501 * \post if called on a \c VariableLengthVector proxy, the referenced values 502 * are left unchanged. 503 * \post \c m_LetArrayManageMemory is true 504 * \post <tt>GetSize() == v.GetSize()</tt>, modulo precision 505 * \post <tt>*this == v</tt> 506 */ 507 template< typename T > 508 Self & operator=(const VariableLengthVector< T > & v) 509 { 510 // No self assignment test is done. Indeed: 511 // - the operator already resists self assignment through a strong exception 512 // guarantee 513 // - the test becomes a pessimization as we never write 514 // VLV<const TValue> vcref(v.GetDataPointer(), v.GetSize()); 515 // ...; 516 // v = vcref; 517 ElementIdentifier const N = v.Size(); 518 this->SetSize( N, DontShrinkToFit(), DumpOldValues() ); 519 for ( ElementIdentifier i = 0; i < N; ++i ) 520 { 521 this->m_Data[i] = static_cast< ValueType >( v[i] ); 522 } 523 return *this; 524 } 525 526 /** Copy-Assignment operator. 527 * \note Ensures a <em>String Exception Guarantee</em>: resists to 528 * self-assignment, and no changes are made if memory cannot be allocated to 529 * hold the new elements. This is expecting \c TValue assignment is a \c 530 * noexcept operation. 531 * 532 * \post if called on a \c VariableLengthVector proxy, the referenced values 533 * are left unchanged. 534 * \post \c m_Data is not null and points to an array of \c m_NumElements, 535 * if \c m_NumElements is not 0. \c m_Data may be null otherwise (an empty 536 * vector is assigned into another empty vector) 537 * \post \c m_LetArrayManageMemory is true 538 * \post <tt>GetSize() == v.GetSize()</tt> 539 * \post <tt>*this == v</tt> 540 */ 541 Self & operator=(const Self & v); 542 543 /** Fast Assignment. 544 * \pre \c m_LetArrayManageMemory is true: the \c VariableLengthVector is not 545 * a proxy, checked with an assertion. Call <tt>SetSize(GetSize(), NeverReallocate(), 546 * DumpOldValues())</tt> to ensure a vector is not a proxy anymore. 547 * \pre current size is identical to the one from the right hand side 548 * operand, checked with an assertion. 549 * \pre Doesn't not support empty vectors. 550 */ 551 Self & FastAssign(const Self & v); 552 553 /** Assignment operator from a numeric value. 554 * \pre This assumes \c m_LetArrayManageMemory is true, but it is unchecked. 555 * If this operator is called on a \c VariableLengthVector proxy, referenced 556 * values will be overwritten. 557 * \post Elements in `[m_Data, m_Data+GetSize())` will be equal to \c v, modulo 558 * precision 559 */ 560 Self & operator=(TValue const & v); 561 562 /** Return the number of elements in the Array */ Size()563 unsigned int Size() const { return m_NumElements; } GetSize()564 unsigned int GetSize() const { return m_NumElements; } GetNumberOfElements()565 unsigned int GetNumberOfElements() const { return m_NumElements; } 566 567 /** Return reference to the element at specified index. No range checking. */ 568 TValue & operator[](unsigned int i) { return this->m_Data[i]; } 569 /** Return reference to the element at specified index. No range checking. */ 570 TValue const & operator[](unsigned int i) const { return this->m_Data[i]; } 571 572 /** Get one element */ GetElement(unsigned int i)573 const TValue & GetElement(unsigned int i) const { return m_Data[i]; } 574 575 /** Set one element */ SetElement(unsigned int i,const TValue & value)576 void SetElement(unsigned int i, const TValue & value) { m_Data[i] = value; } 577 578 /** Resizes the vector. 579 * \tparam TReallocatePolicy Policy that determines precisely the conditions 580 * under which the internal buffer shall be reallocated. It shall inherit 581 * from \c AllocateRootPolicy. 582 * \tparam TKeepValuesPolicy Policy that determines whether old elements 583 * shall be kept. It shall inherit from \c KeepValuesRootPolicy. 584 * 585 * \internal 586 * The purpose of this overload is to fine tune what \c SetSize() does. Some 587 * users seem to need to always reallocate, or to maintain old elements. 588 * However, some usages require fast resizing. In the assignment operators 589 * cases, we don't need to reallocate anything if we have enough memory, and 590 * we certainly do not need to maintain previous values as they'll get 591 * overridden with new ones. 592 * \internal 593 * If we could assert that \c VariableLengthVector proxies would (shall!) 594 * never be assigned anything, we could benefit from a version that won't 595 * check \c m_LetArrayManageMemory. 596 * 597 * \pre `m_NumElements == sz` if \c TReallocatePolicy is \c NeverReallocate 598 * \post `m_NumElements == sz` 599 * \post \c m_LetArrayManageMemory is true 600 * \post In case of reallocation, old \c m_Data buffer is deleted. 601 * \post If \c TKeepValuesPolicy is \c KeepOldValues, old values are 602 * garanteed to be kept, otherwise, it'll depend on the reallocation policy 603 * and the old and new vector size. 604 * \sa \c AlwaysReallocate 605 * \sa \c NeverReallocate 606 * \sa \c ShrinkToFit 607 * \sa \c DontShrinkToFit 608 * \sa \c KeepOldValues 609 * \sa \c DumpOldValues 610 */ 611 template <typename TReallocatePolicy, typename TKeepValuesPolicy> 612 void SetSize(unsigned int sz, 613 TReallocatePolicy reallocatePolicy, 614 TKeepValuesPolicy keepValues); 615 616 /** Set the size to that given. 617 * 618 * If \c destroyExistingData is \c false: 619 * If the array already contains data, the existing data is copied over and 620 * new space is allocated, if necessary. If the length to reserve is less 621 * than the current number of elements, then an appropriate number of elements 622 * are discarded. 623 * If \c true, the size is set destructively to the length given. If the 624 * length is different from the current length, existing data will be lost. 625 * The default is \c true. */ 626 void SetSize(unsigned int sz, bool destroyExistingData = true) 627 { 628 // Stays compatible with previous code version 629 // And works around the fact C++03 template functions can't have default 630 // arguments on template types. 631 if (destroyExistingData) 632 { 633 SetSize(sz, AlwaysReallocate(), KeepOldValues()); 634 } 635 else 636 { 637 SetSize(sz, ShrinkToFit(), KeepOldValues()); 638 } 639 } 640 641 /** Destroy data that is allocated internally, if \c LetArrayManageMemory is 642 * true. */ 643 void DestroyExistingData(); 644 645 /** Set the pointer from which the data is imported. 646 * If "LetArrayManageMemory" is false, then the application retains 647 * the responsibility of freeing the memory for this data. If 648 * "LetArrayManageMemory" is true, then this class will free the 649 * memory when this object is destroyed. 650 * \warning The size of the new \c data shall match vector current size. 651 * Prefer the other overload. 652 * \post old \c m_Data is deleted iff \c m_LetArrayManageMemory is true 653 * \post `m_Data == data` 654 * \post `m_LetArrayManageMemory ==LetArrayManageMemory` 655 * \post \c Size() is left unmodified. 656 */ 657 void SetData(TValue *data, bool LetArrayManageMemory = false); 658 659 /** Similar to the previous method. In the above method, the size must be 660 * separately set prior to using user-supplied data. This introduces an 661 * unnecessary allocation step to be performed. This method avoids it 662 * and should be used to import data wherever possible to avoid this. 663 * Set the pointer from which the data is imported. 664 * If "LetArrayManageMemory" is false, then the application retains 665 * the responsibility of freeing the memory for this data. If 666 * "LetArrayManageMemory" is true, then this class will free the 667 * memory when this object is destroyed. 668 * \post old \c m_Data is deleted iff \c m_LetArrayManageMemory is true 669 * \post `m_Data == data` 670 * \post `m_LetArrayManageMemory ==LetArrayManageMemory` 671 * \post `m_NumElements == sz` 672 */ 673 void SetData(TValue *data, unsigned int sz, bool LetArrayManageMemory = false); 674 675 /** This destructor is not virtual for performance reasons. However, this 676 * means that subclasses cannot allocate memory. 677 * 678 * \internal 679 * More precisally, this class has value semantics (copiable, assignable, 680 * comparable). It's hardly compatible with public inheritance: slicing would 681 * always be there somewhere to annoy us if we try to inherit publicaly from 682 * such a class. 683 * As a consequence, having the destructor virtual makes hardly any sense. 684 */ 685 ~VariableLengthVector(); 686 687 /** Reserves memory of a certain length. 688 * 689 * If the array already contains data, the existing data is copied over and 690 * new space is allocated, if necessary. If the length to reserve is less 691 * than the current number of elements, then an appropriate number of elements 692 * are discarded. 693 * \post \c m_Data is not null and can hold \c size elements. 694 * \post \c m_LetArrayManageMemory may be left unchanged if there already are 695 * enough elements. 696 * 697 * \note You may prefer instead 698 * `SetSize(N, DontShrinkToFit(), KeepOldValues());` that ensures that the 699 * array is not a proxy at the end of the operation. 700 */ 701 void Reserve(ElementIdentifier size); 702 703 /** Allocate memory of certain size and return it. 704 * \return a non-null pointer to an array of \c size elements (0 is a valid 705 * parameter). 706 */ 707 TValue * AllocateElements(ElementIdentifier size) const; 708 GetDataPointer()709 const TValue * GetDataPointer() const { return m_Data; } 710 711 /** Prefix operator that subtracts 1 from each element of the 712 * vector. */ 713 Self & operator--() 714 { 715 for ( ElementIdentifier i = 0; i < m_NumElements; i++ ) 716 { 717 this->m_Data[i] -= static_cast< ValueType >( 1.0 ); 718 } 719 return *this; 720 } 721 722 /** Prefix operator that adds 1 to each element of the vector. */ 723 Self & operator++() // prefix operator ++v; 724 { 725 for ( ElementIdentifier i = 0; i < m_NumElements; i++ ) 726 { 727 this->m_Data[i] += static_cast< ValueType >( 1.0 ); 728 } 729 return *this; 730 } 731 732 /** Postfix operator that subtracts 1 from each element of the 733 * vector. */ 734 Self operator--(int) // postfix operator v--; 735 { 736 Self tmp(*this); 737 738 --tmp; 739 return tmp; 740 } 741 742 /** Postfix operator that adds 1 to each element of the vector. */ 743 Self operator++(int) // postfix operator v++; 744 { 745 Self tmp(*this); 746 747 ++tmp; 748 return tmp; 749 } 750 751 /** Element-wise subtraction of vector 'v' from the current 752 * vector. The vectors do not have to have the same element 753 * type. The input vector elements are cast to the current vector 754 * element type before the subtraction is performed. 755 * 756 * \throw None 757 * \note For efficiency, the length of the vectors is not checked; 758 * they are assumed to have the same length. */ 759 template< typename T > 760 Self & operator-= 761 (const VariableLengthVector< T > & v) 762 { 763 itkAssertInDebugAndIgnoreInReleaseMacro( m_NumElements == v.GetSize() ); 764 for ( ElementIdentifier i = 0; i < m_NumElements; i++ ) 765 { 766 m_Data[i] -= static_cast< ValueType >( v[i] ); 767 } 768 return *this; 769 } 770 771 /** Subtract scalar 's' from each element of the current vector. */ 772 Self & operator-=(TValue s) 773 { 774 for ( ElementIdentifier i = 0; i < m_NumElements; i++ ) 775 { 776 m_Data[i] -= s; 777 } 778 return *this; 779 } 780 781 /** Element-wise addition of vector 'v' to the current vector. The 782 * vectors do not have to have the same element type. The input 783 * vector elements are cast to the current vector element type 784 * before the addition is performed. 785 * 786 * \throw None 787 * \note For efficiency, the length of the vectors is not checked; 788 * they are assumed to have the same length. */ 789 template< typename T > 790 Self & operator+= 791 (const VariableLengthVector< T > & v) 792 { 793 itkAssertInDebugAndIgnoreInReleaseMacro( m_NumElements == v.GetSize() ); 794 for ( ElementIdentifier i = 0; i < m_NumElements; i++ ) 795 { 796 m_Data[i] += static_cast< ValueType >( v[i] ); 797 } 798 return *this; 799 } 800 801 /** Add scalar 's' to each element of the vector. */ 802 Self & operator+=(TValue s) 803 { 804 for ( ElementIdentifier i = 0; i < m_NumElements; i++ ) 805 { 806 m_Data[i] += s; 807 } 808 return *this; 809 } 810 811 /** Compound addition operator with a expression template vector. 812 * \tparam TExpr1 Type of the left sub-expression 813 * \tparam TExpr2 Type of the right sub-expression 814 * \tparam TBinaryOp Binary Operation to apply to both sub-expressions. 815 * \param[in] rhs Non evaluated Expression Template. 816 * 817 * \pre `Size() == rhs.Size()`, checked with an assertion 818 * \note The elements of the expression template are evaluated one by one. 819 */ 820 template <typename TExpr1, typename TExpr2, typename TBinaryOp> 821 Self& operator+=(VariableLengthVectorExpression<TExpr1,TExpr2,TBinaryOp> const& rhs) 822 { 823 itkAssertInDebugAndIgnoreInReleaseMacro(rhs.Size() == Size()); 824 for ( ElementIdentifier i = 0; i < m_NumElements; ++i ) 825 { 826 m_Data[i] += static_cast<ValueType>(rhs[i]); 827 } 828 return *this; 829 } 830 831 /** Compound subtraction operator with a expression template vector. 832 * \tparam TExpr1 Type of the left sub-expression 833 * \tparam TExpr2 Type of the right sub-expression 834 * \tparam TBinaryOp Binary Operation to apply to both sub-expressions. 835 * \param[in] rhs Non evaluated Expression Template. 836 * 837 * \pre `Size() == rhs.Size()`, checked with an assertion 838 * \note The elements of the expression template are evaluated one by one. 839 */ 840 template <typename TExpr1, typename TExpr2, typename TBinaryOp> 841 Self& operator-=(VariableLengthVectorExpression<TExpr1,TExpr2,TBinaryOp> const& rhs) 842 { 843 itkAssertInDebugAndIgnoreInReleaseMacro(rhs.Size() == Size()); 844 for ( ElementIdentifier i = 0; i < m_NumElements; ++i ) 845 { 846 m_Data[i] -= static_cast<ValueType>(rhs[i]); 847 } 848 return *this; 849 } 850 851 /** Multiply each element of the vector by a scalar 's'. The scalar 852 * value is cast to the current vector element type prior to 853 * multiplication. 854 * \throw None 855 */ 856 template< typename T > 857 Self & operator*=(T s) 858 { 859 const ValueType & sc = static_cast<ValueType>(s); 860 for ( ElementIdentifier i = 0; i < m_NumElements; i++ ) 861 { 862 m_Data[i] *= sc; 863 } 864 return *this; 865 } 866 867 /** Multiply each element of the vector by a scalar 's'. 868 * \throw None 869 */ 870 Self & operator*=(TValue s) 871 { 872 for ( ElementIdentifier i = 0; i < m_NumElements; i++ ) 873 { 874 m_Data[i] *= s; 875 } 876 return *this; 877 } 878 879 /** Divide vector elements by a scalar 's'. The vector does not 880 * have to have the same element type as the scalar type. Both the 881 * scalar and vector elements are cast to the RealValueType prior to 882 * division, and the result is cast to the ValueType. 883 * \throw None 884 */ 885 template< typename T > 886 Self & operator/=(T s) 887 { 888 const RealValueType sc = s; 889 for ( ElementIdentifier i = 0; i < m_NumElements; i++ ) 890 { 891 m_Data[i] = static_cast< ValueType >( 892 static_cast< RealValueType >( m_Data[i] ) 893 / sc ); 894 } 895 return *this; 896 } 897 898 /** Negates each vector element. 899 * \warning This operator has a non standard semantics. Instead of returning 900 * a new \c VariableLengthVector, it modifies the current object. 901 */ 902 Self & operator-(); // negation operator 903 904 bool operator==(const Self & v) const; 905 906 bool operator!=(const Self & v) const; 907 908 /** Returns vector's Euclidean Norm */ 909 RealValueType GetNorm() const; 910 911 /** Returns vector's squared Euclidean Norm */ 912 RealValueType GetSquaredNorm() const; 913 914 /** letArrayManageMemory getter. */ IsAProxy()915 bool IsAProxy() const { return ! m_LetArrayManageMemory;} 916 917 private: 918 bool m_LetArrayManageMemory{true}; // if true, the array is responsible 919 // for memory of data 920 TValue * m_Data; // Array to hold data 921 ElementIdentifier m_NumElements{0}; 922 }; 923 924 /// \cond HIDE_META_PROGRAMMING 925 namespace mpl { 926 /** Tells whether a type is an array type for which the support of arithmetic 927 * operations is done with Expression Template. 928 * \note For the moment, only \c itk::VariableLengthVector<> is supported. It 929 * could be extented to other types of ITK arrays. 930 * \ingroup MetaProgrammingLibrary 931 * \ingroup ITKCommon 932 * \sa \c VariableLengthVector 933 * \sa \c VariableLengthVectorExpression 934 */ 935 template <typename T> 936 struct IsArray : FalseType {}; 937 938 /// \cond SPECIALIZATION_IMPLEMENTATION 939 template <typename T> 940 struct IsArray<itk::VariableLengthVector<T> > : TrueType {}; 941 942 template <typename TExpr1, typename TExpr2, typename TBinaryOp> 943 struct IsArray<VariableLengthVectorExpression<TExpr1, TExpr2,TBinaryOp> > : TrueType {}; 944 /// \endcond 945 } // namespace mpl 946 /// \endcond 947 948 namespace Details 949 { 950 /// \cond HIDE_META_PROGRAMMING 951 /** Helper Trait for VLV expression template: returns the value type. 952 * \tparam TExpr Expression type 953 * \return \c Type The value type behind \c TExpr (\c TExpr in case of a 954 * numerical type, \c TExpr::ValueType in case of the \c VariableLengthVector, 955 * etc.) 956 * 957 * Also defines \c Load() that permits to fetch the i-th element in case of an 958 * array, array expression, or just the number in case of a number. 959 * \ingroup ITKCommon 960 * \sa \c VariableLengthVector 961 * \sa \c VariableLengthVectorExpression 962 */ 963 template <typename TExpr> struct GetType 964 { 965 using Type = TExpr; 966 /** Fetches the i-th element from an array (expression). 967 * \note the default unspecialized behaviour returns the input number \c v. 968 */ 969 static Type Load(Type const& v, unsigned int idx) 970 { (void)idx; return v; } 971 }; 972 973 /** Helper function for VLV expression templates: returns the common size. 974 * \param[in] lhs left hand side expression 975 * \param[in] rhs right hand side expression 976 * \note The default overload assumes both operands are \c VariableLengthVector 977 * (or expression) arrays 978 * \pre asserts both arrays have the same size. 979 * \ingroup ITKCommon 980 * \sa \c VariableLengthVector 981 * \sa \c VariableLengthVectorExpression 982 */ 983 template <typename TExpr1, typename TExpr2> 984 inline 985 typename mpl::EnableIf<mpl::And<mpl::IsArray<TExpr1>, mpl::IsArray<TExpr2> >, unsigned int>::Type 986 GetSize(TExpr1 const& lhs, TExpr2 const& rhs) 987 { 988 (void)rhs; 989 itkAssertInDebugAndIgnoreInReleaseMacro(lhs.Size() == rhs.Size()); 990 return lhs.Size(); 991 } 992 993 /// \cond SPECIALIZATION_IMPLEMENTATION 994 /** Helper function for VLV expression templates: returns the common size. 995 * \param[in] lhs left hand side expression 996 * \param[in] rhs right hand side expression 997 * \note This overload assumes that only the first operand is a \c 998 * VariableLengthVector (or expression) array. 999 * \ingroup ITKCommon 1000 * \sa \c VariableLengthVector 1001 * \sa \c VariableLengthVectorExpression 1002 */ 1003 template <typename TExpr1, typename TExpr2> 1004 inline 1005 typename mpl::EnableIf<mpl::And<mpl::IsArray<TExpr1>, mpl::Not<mpl::IsArray<TExpr2> > >, unsigned int>::Type 1006 GetSize(TExpr1 const& lhs, TExpr2 const& itkNotUsed(rhs)) 1007 { 1008 return lhs.Size(); 1009 } 1010 1011 /** Helper function for VLV expression templates: returns the common size. 1012 * \param[in] lhs left hand side expression 1013 * \param[in] rhs right hand side expression 1014 * \note This overload assumes that only the second operand is a \c 1015 * VariableLengthVector (or expression) array. 1016 * \ingroup ITKCommon 1017 * \sa \c VariableLengthVector 1018 * \sa \c VariableLengthVectorExpression 1019 */ 1020 template <typename TExpr1, typename TExpr2> 1021 inline 1022 typename mpl::EnableIf<mpl::And<mpl::IsArray<TExpr2>, mpl::Not<mpl::IsArray<TExpr1> > >, unsigned int>::Type 1023 GetSize(TExpr1 const& itkNotUsed(lhs), TExpr2 const& rhs) 1024 { 1025 return rhs.Size(); 1026 } 1027 1028 template <typename T> 1029 struct GetType<VariableLengthVector<T> > 1030 { 1031 using Type = T; 1032 static Type Load(VariableLengthVector<T> const& v, unsigned int idx) 1033 { return v[idx]; } 1034 }; 1035 template <typename TExpr1, typename TExpr2, typename TBinaryOp> 1036 struct GetType<VariableLengthVectorExpression<TExpr1, TExpr2, TBinaryOp> > 1037 { 1038 using Type = typename VariableLengthVectorExpression<TExpr1, TExpr2, TBinaryOp>::ResType; 1039 static Type Load(VariableLengthVectorExpression<TExpr1, TExpr2, TBinaryOp> const& v, unsigned int idx) 1040 { return v[idx]; } 1041 }; 1042 /// \endcond 1043 1044 namespace op 1045 { 1046 /** Tells whether objects from two types can be added or subtracted. 1047 * The operation is authorized if and only if: 1048 * - both are arrays, 1049 * - or one operand is an array while the second is a number. 1050 * \note As this traits is dedicated to help overload binary operators, it 1051 * shall not be used to help overload `operator+()` between floats for instance. 1052 * Hence, the case where both operands are numbers is rejected. 1053 * 1054 * \sa \c mpl::IsArray<> to know the exact array types recognized as \em array by this traits 1055 * \ingroup MetaProgrammingLibrary 1056 * \ingroup ITKCommon 1057 */ 1058 template <typename TExpr1, typename TExpr2> 1059 struct CanBeAddedOrSubtracted 1060 : mpl::Or< mpl::And<mpl::IsArray<TExpr1>, mpl::IsArray<TExpr2> >, 1061 mpl::And<mpl::IsArray<TExpr1>, mpl::IsNumber<TExpr2> >, 1062 mpl::And<mpl::IsNumber<TExpr1>, mpl::IsArray<TExpr2> > 1063 > 1064 {}; 1065 1066 /** Tells whether objects from two types can be multiplied. 1067 * The operation is authorized if and only if: 1068 * - one operand is an array while the second is a number. 1069 * \note As this traits is dedicated to help overload `operator*()`, it 1070 * shall not be used to help overload the operator between floats for instance. 1071 * Hence, the case where both operands are numbers is rejected. 1072 * 1073 * \sa \c mpl::IsArray<> to know the exact array types recognized as \em array by this traits 1074 * \ingroup MetaProgrammingLibrary 1075 * \ingroup ITKCommon 1076 */ 1077 template <typename TExpr1, typename TExpr2> 1078 struct CanBeMultiplied 1079 : mpl::Or< mpl::And<mpl::IsArray<TExpr1>, mpl::IsNumber<TExpr2> >, 1080 mpl::And<mpl::IsNumber<TExpr1>, mpl::IsArray<TExpr2> > 1081 > 1082 {}; 1083 1084 /** Tells whether objects from two types can be multiplied. 1085 * The operation is authorized if and only if: 1086 * - the first operand is an array while the second is a number. 1087 * \note As this traits is dedicated to help overload `operator/()`, it 1088 * shall not be used to help overload the operator between floats for instance. 1089 * Hence, the case where both operands are numbers is rejected. 1090 * 1091 * \sa \c mpl::IsArray<> to know the exact array types recognized as \em array by this traits 1092 * \ingroup MetaProgrammingLibrary 1093 * \ingroup ITKCommon 1094 */ 1095 template <typename TExpr1, typename TExpr2> 1096 struct CanBeDivided 1097 : mpl::And<mpl::IsArray<TExpr1>, mpl::IsNumber<TExpr2> > 1098 {}; 1099 1100 } // op namespace 1101 } // Details namespace 1102 /// \endcond 1103 1104 /** Expression Template for \c VariableLengthVector. 1105 * Contains an expression template that models a binary operation between two 1106 * sub expressions (of type \c VariableLengthVector, or \c VariableLengthVectorExpression) 1107 * \tparam TExpr1 Type of the left sub-expression 1108 * \tparam TExpr2 Type of the right sub-expression 1109 * \tparam TBinaryOp Binary Operation to apply to both sub-expressions. 1110 * 1111 * \note We permit to add a `VariableLengthVector<float>` with a 1112 * `VariableLengthVector<double>`, the result will be of type 1113 * `VariableLengthVector<double>`. 1114 * 1115 * \warning Explicitly static casting an expression to a 1116 * \c VariableLengthVector<> will defeat the purpose of the optimization 1117 * implemented here. It's thus best to let the expression automatically adjust 1118 * to the type with the most precision. 1119 * Eventually, when assigning to the final destination (a 1120 * \c VariableLengthVector<>), a casting on-the-fly could be realized by the 1121 * assignment operator, or by the copy constructor. 1122 * 1123 * \todo Add support for unary operations like `operator-()`. 1124 * 1125 * \ingroup DataRepresentation 1126 * \ingroup ITKCommon 1127 */ 1128 template <typename TExpr1, typename TExpr2, typename TBinaryOp> 1129 struct VariableLengthVectorExpression 1130 { 1131 VariableLengthVectorExpression(TExpr1 const& lhs, TExpr2 const& rhs) 1132 : m_lhs(lhs), m_rhs(rhs) 1133 { 1134 // Not neccessary actually as end-user/developper is not expected to 1135 // provide new BinaryOperations 1136 itkStaticAssert( 1137 (itk::mpl::IsBaseOf<Details::op::BinaryOperationConcept, TBinaryOp>::Value), 1138 "The Binary Operation shall inherit from BinaryOperationConcept"); 1139 } 1140 1141 /// Returns the size of the vector expression. 1142 unsigned int Size() const{ return Details::GetSize(m_lhs, m_rhs); } 1143 1144 /// Vector type of the Result Expression 1145 using ResType = typename mpl::PromoteType< 1146 typename Details::GetType<TExpr1>::Type, 1147 typename Details::GetType<TExpr2>::Type>::Type; 1148 /// Real type of the elements 1149 using RealValueType = typename NumericTraits< ResType > ::RealType; 1150 1151 /** Element access operator. 1152 * \pre `idx < Size()` 1153 * \internal 1154 * This is where the magic happens. Instead of building a new vector based on 1155 * the two input vectors, we compute each element on-the-fly when 1156 * requested(by a \c VariableLengthVector constructor or an assignment 1157 * operator). 1158 * 1159 * \c Load() is in charge of fetching the i-th element of the sub-expressions 1160 */ 1161 ResType operator[](unsigned int idx) const 1162 { 1163 itkAssertInDebugAndIgnoreInReleaseMacro(idx < Size()); 1164 return TBinaryOp::Apply( 1165 Details::GetType<TExpr1>::Load(m_lhs, idx), 1166 Details::GetType<TExpr2>::Load(m_rhs, idx)); 1167 } 1168 1169 /** Returns vector's Euclidean Norm */ 1170 RealValueType GetNorm() const; 1171 1172 /** Returns vector's squared Euclidean Norm */ 1173 RealValueType GetSquaredNorm() const; 1174 1175 private: 1176 TExpr1 const& m_lhs; 1177 TExpr2 const& m_rhs; 1178 }; 1179 1180 /** Addition involving a \c VariableLengthVector. 1181 * This operation is generic and takes: 1182 * - two arrays, 1183 * - or one array and one number (on either side) 1184 * \return an expression template proxy object. 1185 * \throw None As no allocation will be performed. 1186 * \relates itk::VariableLengthVector 1187 * \sa \c mpl::IsArray<> to know the exact array types recognized as \em array by this traits 1188 */ 1189 template <typename TExpr1, typename TExpr2> 1190 inline 1191 typename mpl::EnableIf<Details::op::CanBeAddedOrSubtracted<TExpr1,TExpr2>, VariableLengthVectorExpression<TExpr1, TExpr2, Details::op::Plus> >::Type 1192 operator+(TExpr1 const& lhs, TExpr2 const& rhs) 1193 { return VariableLengthVectorExpression<TExpr1, TExpr2, Details::op::Plus>(lhs, rhs); } 1194 1195 /** Subtraction involving a \c VariableLengthVector. 1196 * This operation is generic and takes: 1197 * - two arrays, 1198 * - or one array and one number (on either side) 1199 * \return an expression template proxy object. 1200 * \throw None As no allocation will be performed. 1201 * \relates itk::VariableLengthVector 1202 * \sa \c mpl::IsArray<> to know the exact array types recognized as \em array by this traits 1203 */ 1204 template <typename TExpr1, typename TExpr2> 1205 inline 1206 typename mpl::EnableIf<Details::op::CanBeAddedOrSubtracted<TExpr1,TExpr2>, VariableLengthVectorExpression<TExpr1, TExpr2, Details::op::Sub> >::Type 1207 operator-(TExpr1 const& lhs, TExpr2 const& rhs) 1208 { return VariableLengthVectorExpression<TExpr1, TExpr2, Details::op::Sub>(lhs, rhs); } 1209 1210 /** Multiplication between a \c VariableLengthVector and a scalar. 1211 * This operation is generic and takes one array and one number (on either 1212 * side). 1213 * \return an expression template proxy object. 1214 * \throw None As no allocation will be performed. 1215 * \relates itk::VariableLengthVector 1216 * \sa \c mpl::IsArray<> to know the exact array types recognized as \em array by this traits 1217 */ 1218 template <typename TExpr1, typename TExpr2> 1219 inline 1220 typename mpl::EnableIf<Details::op::CanBeMultiplied<TExpr1,TExpr2>, VariableLengthVectorExpression<TExpr1, TExpr2, Details::op::Mult> >::Type 1221 operator*(TExpr1 const& lhs, TExpr2 const& rhs) 1222 { return VariableLengthVectorExpression<TExpr1, TExpr2, Details::op::Mult>(lhs, rhs); } 1223 1224 /** Division of a \c VariableLengthVector by a scalar. 1225 * This operation is generic and takes one array and one number. 1226 * \return an expression template proxy object. 1227 * \throw None As no allocation will be performed. 1228 * \relates itk::VariableLengthVector 1229 * \sa \c mpl::IsArray<> to know the exact array types recognized as \em array by this traits 1230 */ 1231 template <typename TExpr1, typename TExpr2> 1232 inline 1233 typename mpl::EnableIf<Details::op::CanBeDivided<TExpr1,TExpr2>, VariableLengthVectorExpression<TExpr1, TExpr2, Details::op::Div> >::Type 1234 operator/(TExpr1 const& lhs, TExpr2 const& rhs) 1235 { return VariableLengthVectorExpression<TExpr1, TExpr2, Details::op::Div>(lhs, rhs); } 1236 1237 /** Serialization of \c VariableLengthVectorExpression 1238 * \relates itk::VariableLengthVectorExpression 1239 */ 1240 template <typename TExpr1, typename TExpr2, typename TBinaryOp> 1241 std::ostream & operator<<(std::ostream &os, VariableLengthVectorExpression<TExpr1, TExpr2, TBinaryOp> const& v) 1242 { 1243 os << "["; 1244 if (v.Size() != 0) 1245 { 1246 os << v[0]; 1247 for (unsigned int i = 1, N = v.Size(); i != N; ++i) 1248 { 1249 os << ", " << v[i]; 1250 } 1251 } 1252 return os << "]"; 1253 } 1254 1255 /** Returns vector's Euclidean Norm. 1256 * \tparam TExpr must be an array 1257 * \sa \c mpl::IsArray<> to know the exact array types recognized as \em array by this traits 1258 * \relates itk::VariableLengthVectorExpression 1259 */ 1260 template <typename TExpr> 1261 inline 1262 typename mpl::EnableIf<mpl::IsArray<TExpr>, typename TExpr::RealValueType>::Type 1263 GetNorm(TExpr const& v) 1264 { 1265 return static_cast<typename TExpr::RealValueType>( 1266 std::sqrt(static_cast<double>(GetSquaredNorm(v)))); 1267 } 1268 1269 /** Returns vector's squared Euclidean Norm. 1270 * \tparam TExpr must be an array 1271 * \sa \c mpl::IsArray<> to know the exact array types recognized as \em array by this traits 1272 * \relates itk::VariableLengthVectorExpression 1273 */ 1274 template <typename TExpr> 1275 inline 1276 typename mpl::EnableIf<mpl::IsArray<TExpr>, typename TExpr::RealValueType>::Type 1277 GetSquaredNorm(TExpr const& v) 1278 { 1279 using RealValueType = typename TExpr::RealValueType; 1280 RealValueType sum = 0.0; 1281 for ( unsigned int i = 0, N=v.Size(); i < N; ++i ) 1282 { 1283 const RealValueType value = v[i]; 1284 sum += value * value; 1285 } 1286 return sum; 1287 } 1288 1289 /**\name Serialization */ 1290 //@{ 1291 /** Serialization of \c VariableLengthVector 1292 * \relates itk::VariableLengthVector 1293 */ 1294 template< typename TValue > 1295 std::ostream & operator<<(std::ostream & os, const VariableLengthVector< TValue > & arr) 1296 { 1297 const unsigned int length = arr.Size(); 1298 const signed int last = (unsigned int)length - 1; 1299 1300 os << "["; 1301 for ( signed int i = 0; i < last; ++i ) 1302 { 1303 os << arr[i] << ", "; 1304 } 1305 if ( length >= 1 ) 1306 { 1307 os << arr[last]; 1308 } 1309 os << "]"; 1310 return os; 1311 } 1312 //@} 1313 1314 /**\name Standard compliance functions */ 1315 //@{ 1316 /** \c swap() overload for \c VariableLengthVector 1317 * \throw None 1318 * \relates itk::VariableLengthVector 1319 * \internal 1320 * This overload follows C++ standard naming convention. This is required to 1321 * permit \c VariableLengthVector to be exchanged by standard algorithms that 1322 * take advantage of Koening Namespace Lookup (a.k.a. Argument Dependant 1323 * Lookup). e.g. 1324 \code 1325 template <typename T> f(T & l, T & r) 1326 { 1327 using std::swap; 1328 swap(l,r); 1329 ... 1330 } 1331 * \endcode 1332 */ 1333 template <typename T> 1334 inline 1335 void swap(VariableLengthVector<T> &l_, VariableLengthVector<T> &r_) noexcept 1336 { 1337 l_.Swap(r_); 1338 } 1339 //@} 1340 1341 } // namespace itk 1342 1343 #include "itkNumericTraitsVariableLengthVectorPixel.h" 1344 1345 #ifndef ITK_MANUAL_INSTANTIATION 1346 #include "itkVariableLengthVector.hxx" 1347 #endif 1348 1349 #endif 1350