ACF $AcfVersion:0$
TFastVector.h
Go to the documentation of this file.
1// SPDX-License-Identifier: LGPL-2.1-or-later OR GPL-2.0-or-later OR GPL-3.0-or-later OR LicenseRef-ACF-Commercial
2#pragma once
3
4
5// STL includes
6#include <cstring>
7#include <initializer_list>
8
9// ACF includes
10#include <iser/IArchive.h>
11#include <iser/CArchiveTag.h>
12#include <imath/TVector.h>
13
14
15namespace imath
16{
17
18
121template <int MaxSize, class Element = double>
123{
124public:
125 typedef Element ElementType;
126
127 enum{
128 MAX_ELEMENTS_COUNT = MaxSize
129 };
130
135
139 explicit TFastVector(int componentsCount, const Element& value = Element());
140
145
149 TFastVector(std::initializer_list<Element> values);
150
151 template <int Size>
153 : m_elementsCount(Size)
154 {
155 Q_ASSERT(Size <= MaxSize);
156
157 for (int i = 0; i < Size; ++i){
158 m_elements[i] = vector[i];
159 }
160 }
161
165 int GetElementsCount() const;
166
172 bool SetElementsCount(int count, const Element& value = Element());
173
181 bool EnsureElementsCount(int count, const Element& value = Element());
182
186 const Element& GetElement(int i) const;
187
191 Element& GetElementRef(int i);
192
196 void SetElement(int i, const Element& value);
197
201 void Clear();
202
208 void SetElementsFrom(const TFastVector& vector, const Element& expansionValue = Element());
209
214
219
224
229 void ScaledCumulate(const TFastVector<MaxSize, Element>& vector, Element scale);
230
234 bool IsNull(Element tolerance = I_BIG_EPSILON) const;
235
239 Element GetDotProduct(const TFastVector<MaxSize, Element>& vector) const;
240
244 Element GetLength2() const;
248 Element GetLength() const;
249
253 Element GetDistance2(const TFastVector<MaxSize, Element>& vector) const;
254
258 Element GetDistance(const TFastVector<MaxSize, Element>& vector) const;
259
263 Element GetElementsSum() const;
264
270 bool Normalize(Element length = 1.0);
276 bool GetNormalized(TFastVector<MaxSize, Element>& result, Element length = 1.0) const;
277
286
290 bool Serialize(iser::IArchive& archive);
291
292 bool operator==(const TFastVector<MaxSize, Element>& vector) const;
293 bool operator!=(const TFastVector<MaxSize, Element>& vector) const;
294 bool operator<(const TFastVector<MaxSize, Element>& vector) const;
295 bool operator>(const TFastVector<MaxSize, Element>& vector) const;
296 bool operator<=(const TFastVector<MaxSize, Element>& vector) const;
297 bool operator>=(const TFastVector<MaxSize, Element>& vector) const;
298
300
305
307
312
313 const Element& operator[](int i) const;
314 Element& operator[](int i);
315
316protected:
317 Element m_elements[MaxSize];
319};
320
321
322// inline methods
323
324template <int MaxSize, class Element>
326: m_elementsCount(0)
327{
328}
329
330
331template <int MaxSize, class Element>
332inline TFastVector<MaxSize, Element>::TFastVector(int componentsCount, const Element& value)
333: m_elementsCount(qMin(MaxSize, componentsCount))
334{
335 for (int i = 0; i < m_elementsCount; ++i){
336 m_elements[i] = value;
337 }
338}
339
340
341template <int MaxSize, class Element>
343: m_elementsCount(vector.m_elementsCount)
344{
345 Q_ASSERT(m_elementsCount <= MaxSize);
346
347 std::memcpy(m_elements, vector.m_elements, sizeof(Element) * m_elementsCount);
348}
349
350
351template <int MaxSize, class Element>
352inline TFastVector<MaxSize, Element>::TFastVector(std::initializer_list<Element> values)
353: m_elementsCount(qMin(MaxSize, static_cast<int>(values.size())))
354{
355 Q_ASSERT(values.size() <= MaxSize);
356
357 for (int i = 0; i < m_elementsCount; ++i){
358 m_elements[i] = *(values.begin() + i);
359 }
360}
361
362
363template <int MaxSize, class Element>
365{
366 return m_elementsCount;
367}
368
369
370template <int MaxSize, class Element>
371inline bool TFastVector<MaxSize, Element>::SetElementsCount(int count, const Element& value)
372{
373 if (count <= MaxSize){
374 for (int i = m_elementsCount; i < count; ++i){
375 m_elements[i] = value;
376 }
377
378 m_elementsCount = count;
379
380 return true;
381 }
382 else{
383 return false;
384 }
385}
386
387
388template <int MaxSize, class Element>
389inline bool TFastVector<MaxSize, Element>::EnsureElementsCount(int count, const Element& value)
390{
391 if (count <= MaxSize){
392 if (m_elementsCount < count){
393 for (int i = m_elementsCount; i < count; ++i){
394 m_elements[i] = value;
395 }
396
397 m_elementsCount = count;
398 }
399
400 return true;
401 }
402 else{
403 return false;
404 }
405}
406
407
408template <int MaxSize, class Element>
409inline const Element& TFastVector<MaxSize, Element>::GetElement(int i) const
410{
411 Q_ASSERT(i >= 0);
412 Q_ASSERT(i < m_elementsCount);
413
414 return m_elements[i];
415}
416
417
418template <int MaxSize, class Element>
420{
421 Q_ASSERT(i >= 0);
422 Q_ASSERT(i < m_elementsCount);
423
424 return m_elements[i];
425}
426
427
428template <int MaxSize, class Element>
429inline void TFastVector<MaxSize, Element>::SetElement(int i, const Element& value)
430{
431 Q_ASSERT(i >= 0);
432 Q_ASSERT(i < m_elementsCount);
433
434 m_elements[i] = value;
435}
436
437
438template <int MaxSize, class Element>
440{
441 for (int i = 0; i < m_elementsCount; ++i){
442 m_elements[i] = 0.0;
443 }
444}
445
446
447template <int MaxSize, class Element>
449{
450 int commonSize = qMin(m_elementsCount, vector.m_elementsCount);
451 for (int i = 0; i < commonSize; ++i){
452 m_elements[i] += vector.m_elements[i];
453 }
454}
455
456
457template <int MaxSize, class Element>
459{
460 if (m_elementsCount < vector.m_elementsCount){
461 int i = 0;
462 for (; i < m_elementsCount; ++i){
463 m_elements[i] += vector.m_elements[i] * scale;
464 }
465
466 for (; i < vector.m_elementsCount; ++i){
467 m_elements[i] = vector.m_elements[i] * scale;
468 }
469
470 m_elementsCount = vector.m_elementsCount;
471 }
472 else{
473 for (int i = 0; i < vector.m_elementsCount; ++i){
474 m_elements[i] += vector.m_elements[i] * scale;
475 }
476 }
477}
478
479
480template <int MaxSize, class Element>
481void TFastVector<MaxSize, Element>::SetElementsFrom(const TFastVector& vector, const Element& expansionValue)
482{
483 int commonSize = qMin(m_elementsCount, vector.m_elementsCount);
484
485 for (int i = 0; i < commonSize; ++i){
486 SetElement(i, vector[i]);
487 }
488
489 for (int i = commonSize; i < m_elementsCount; ++i){
490 SetElement(i, expansionValue);
491 }
492}
493
494
495template <int MaxSize, class Element>
500
501
502template <int MaxSize, class Element>
504{
505
506 result = *this;
507 result.Translate(vector);
508}
509
510
511template <int MaxSize, class Element>
512inline bool TFastVector<MaxSize, Element>::IsNull(Element tolerance) const
513{
514 return GetLength2() <= tolerance * tolerance;
515}
516
517
518template <int MaxSize, class Element>
520{
521 Element retVal = 0.0;
522
523 int commonSize = qMin(m_elementsCount, vector.m_elementsCount);
524 for (int i = 0; i < commonSize; ++i){
525 retVal += m_elements[i] * vector.m_elements[i];
526 }
527
528 return retVal;
529}
530
531
532template <int MaxSize, class Element>
534{
535 return GetDotProduct(*this);
536}
537
538
539template <int MaxSize, class Element>
541{
542 return qSqrt(GetLength2());
543}
544
545
546template <int MaxSize, class Element>
548{
549 return (*this - vector).GetLength2();
550}
551
552
553template <int MaxSize, class Element>
555{
556 return qSqrt(GetDistance2(vector));
557}
558
559
560// operators
561
562template <int MaxSize, class Element>
564{
565 if (m_elementsCount != vector.m_elementsCount){
566 return false;
567 }
568
569 for (int i = 0; i < m_elementsCount; ++i){
570 if (m_elements[i] != vector.m_elements[i]){
571 return false;
572 }
573 }
574
575 return true;
576}
577
578
579template <int MaxSize, class Element>
581{
582 return !operator==(vector);
583}
584
585
586template <int MaxSize, class Element>
588{
589 int commonSize = qMin(m_elementsCount, vector.m_elementsCount);
590 for (int i = 0; i < commonSize; ++i){
591 if (m_elements[i] > vector.m_elements[i]){
592 return false;
593 }
594 else if (m_elements[i] < vector.m_elements[i]){
595 return true;
596 }
597 }
598
599 return m_elementsCount < vector.m_elementsCount;
600}
601
602
603template <int MaxSize, class Element>
605{
606 int commonSize = qMin(m_elementsCount, vector.m_elementsCount);
607 for (int i = 0; i < commonSize; ++i){
608 if (m_elements[i] > vector.m_elements[i]){
609 return true;
610 }
611 else if (m_elements[i] < vector.m_elements[i]){
612 return false;
613 }
614 }
615
616 return m_elementsCount > vector.m_elementsCount;
617}
618
619
620template <int MaxSize, class Element>
622{
623 int commonSize = qMin(m_elementsCount, vector.m_elementsCount);
624 for (int i = 0; i < commonSize; ++i){
625 if (m_elements[i] > vector.m_elements[i]){
626 return false;
627 }
628 else if (m_elements[i] < vector.m_elements[i]){
629 return true;
630 }
631 }
632
633 return m_elementsCount <= vector.m_elementsCount;
634}
635
636
637template <int MaxSize, class Element>
639{
640 int commonSize = qMin(m_elementsCount, vector.m_elementsCount);
641 for (int i = 0; i < commonSize; ++i){
642 if (m_elements[i] > vector.m_elements[i]){
643 return true;
644 }
645 else if (m_elements[i] < vector.m_elements[i]){
646 return false;
647 }
648 }
649
650 return m_elementsCount >= vector.m_elementsCount;
651}
652
653
654template <int MaxSize, class Element>
656{
657 m_elementsCount = vector.m_elementsCount;
658 Q_ASSERT(m_elementsCount < MaxSize);
659
660 for (int i = 0; i < m_elementsCount; ++i){
661 m_elements[i] = vector.m_elements[i];
662 }
663
664 return *this;
665}
666
667
668template <int MaxSize, class Element>
670{
671 if (m_elementsCount < vector.m_elementsCount){
672 int i = 0;
673 for (; i < m_elementsCount; ++i){
674 m_elements[i] += vector.m_elements[i];
675 }
676
677 for (; i < vector.m_elementsCount; ++i){
678 m_elements[i] = vector.m_elements[i];
679 }
680
681 m_elementsCount = vector.m_elementsCount;
682 }
683 else{
684 for (int i = 0; i < vector.m_elementsCount; ++i){
685 m_elements[i] += vector.m_elements[i];
686 }
687 }
688
689 return *this;
690}
691
692
693template <int MaxSize, class Element>
695{
696 if (m_elementsCount < vector.m_elementsCount){
697 int i = 0;
698 for (; i < m_elementsCount; ++i){
699 m_elements[i] -= vector.m_elements[i];
700 }
701
702 for (; i < vector.m_elementsCount; ++i){
703 m_elements[i] = -vector.m_elements[i];
704 }
705
706 m_elementsCount = vector.m_elementsCount;
707 }
708 else{
709 for (int i = 0; i < vector.m_elementsCount; ++i){
710 m_elements[i] -= vector.m_elements[i];
711 }
712 }
713
714 return *this;
715}
716
717
718template <int MaxSize, class Element>
720{
721 for (int i = 0; i < m_elementsCount; ++i){
722 m_elements[i] *= scalar;
723 }
724
725 return *this;
726}
727
728
729template <int MaxSize, class Element>
731{
732 for (int i = 0; i < m_elementsCount; ++i){
733 m_elements[i] /= scalar;
734 }
735
736 return *this;
737}
738
739
740template <int MaxSize, class Element>
742{
743 TFastVector<MaxSize, Element> retVal(*this);
744
745 for (int i = 0; i < m_elementsCount; ++i){
746 retVal.m_elements[i] = -m_elements[i];
747 }
748
749 return retVal;
750}
751
752
753template <int MaxSize, class Element>
755{
756 TFastVector<MaxSize, Element> retVal(*this);
757
758 retVal += vector;
759
760 return retVal;
761}
762
763
764template <int MaxSize, class Element>
766{
767 TFastVector<MaxSize, Element> retVal(*this);
768
769 retVal -= vector;
770
771 return retVal;
772}
773
774
775template <int MaxSize, class Element>
777{
778 TFastVector<MaxSize, Element> retVal(*this);
779
780 retVal *= scalar;
781
782 return retVal;
783}
784
785
786template <int MaxSize, class Element>
788{
789 TFastVector<MaxSize, Element> retVal(*this);
790
791 retVal /= scalar;
792
793 return retVal;
794}
795
796
797template <int MaxSize, class Element>
799{
800 Q_ASSERT(i >= 0);
801 Q_ASSERT(i < m_elementsCount);
802
803 return m_elements[i];
804}
805
806
807template <int MaxSize, class Element>
809{
810 Q_ASSERT(i >= 0);
811 Q_ASSERT(i < MaxSize);
812
813 return m_elements[i];
814}
815
816
817// public methods
818
819template <int MaxSize, class Element>
821{
822 Element retVal = 0;
823
824 for (int i = 0; i < m_elementsCount; ++i){
825 retVal += m_elements[i];
826 }
827
828 return retVal;
829}
830
831
832template <int MaxSize, class Element>
834{
835 Element isLength = GetLength();
836
837 Element proportion = isLength / length;
838
839 if (qAbs(proportion) > I_BIG_EPSILON){
840 for (int i = 0; i < m_elementsCount; ++i){
841 m_elements[i] = m_elements[i] / proportion;
842 }
843
844 return true;
845 }
846 else{
847 return false;
848 }
849}
850
851
852template <int MaxSize, class Element>
854{
855 result = *this;
856
857 return result.Normalize(length);
858}
859
860
861template <int MaxSize, class Element>
863{
864 int elementsCount = qMin(GetElementsCount(), vector.GetElementsCount());
865
866 result.SetElementsCount(elementsCount);
867
868 for (int i = 0; i < elementsCount; ++i){
869 result.SetElement(i, qMin(GetElement(i), vector.GetElement(i)));
870 }
871}
872
873
874template <int MaxSize, class Element>
876{
877 int elementsCount = qMin(GetElementsCount(), vector.GetElementsCount());
878
879 result.SetElementsCount(elementsCount);
880
881 for (int i = 0; i < elementsCount; ++i){
882 result.SetElement(i, qMax(GetElement(i), vector.GetElement(i)));
883 }
884}
885
886
887template <int MaxSize, class Element>
889{
890 bool retVal = true;
891
892 static iser::CArchiveTag elementsTag("Elements", "List of vector element", iser::CArchiveTag::TT_MULTIPLE);
893 static iser::CArchiveTag elementTag("Element", "Single vector element", iser::CArchiveTag::TT_LEAF, &elementsTag);
894
895 retVal = retVal && archive.BeginMultiTag(elementsTag, elementTag, m_elementsCount);
896
897 if (!retVal || (m_elementsCount > MaxSize)){
898 if (!archive.IsStoring()){
899 m_elementsCount = 0;
900 }
901
902 return false;
903 }
904
905 for (int i = 0; i < m_elementsCount; ++i){
906 retVal = retVal && archive.BeginTag(elementTag);
907 retVal = retVal && archive.Process(m_elements[i]);
908 retVal = retVal && archive.EndTag(elementTag);
909 }
910
911 retVal = retVal && archive.EndTag(elementsTag);
912
913 return retVal;
914}
915
916
917// related global functions
918
919template <int MaxSize, class Element>
920inline uint qHash(const TFastVector<MaxSize, Element>& v, uint seed = 0)
921{
922 uint retVal = seed;
923
924 int elementsCount = v.GetElementsCount();
925 for (int i = 0; i < elementsCount; ++i){
926 double element = v[i];
927
928 retVal = (retVal << 1) ^ *((uint*)&element) + 1;
929 }
930
931 return retVal;
932}
933
934
935} // namespace imath
936
937
Optimized implementation of a variable-size vector with compile-time maximum capacity.
TFastVector(std::initializer_list< Element > values)
Initializer list constructor.
TFastVector< MaxSize, Element > operator-() const
void Clear()
Set all coordinates to zero.
const Element & GetElement(int i) const
Get element at specified i.
bool GetNormalized(TFastVector< MaxSize, Element > &result, Element length=1.0) const
Return normalized vector with the same direction and specified length.
Element GetDistance(const TFastVector< MaxSize, Element > &vector) const
Return distance between two vectors.
TFastVector< MaxSize, Element > & operator-=(const TFastVector< MaxSize, Element > &vector)
Element GetLength2() const
Return euclidian length square.
bool Normalize(Element length=1.0)
Normalize vector to specified length.
void SetElementsFrom(const TFastVector &vector, const Element &expansionValue=Element())
Set elemenents from other vector without resizing.
TFastVector< MaxSize, Element > & operator/=(Element scalar)
bool operator<=(const TFastVector< MaxSize, Element > &vector) const
bool operator>=(const TFastVector< MaxSize, Element > &vector) const
Element GetElementsSum() const
Get simple sum of all elements.
bool SetElementsCount(int count, const Element &value=Element())
Set number of elements.
bool operator==(const TFastVector< MaxSize, Element > &vector) const
void SetElement(int i, const Element &value)
Set element at specified i.
void GetMaximal(const TFastVector< MaxSize, Element > &vector, TFastVector< MaxSize, Element > &result) const
Get vector with maximal elements values.
TFastVector< MaxSize, Element > operator+(const TFastVector< MaxSize, Element > &vector) const
int GetElementsCount() const
Get number of elements.
TFastVector()
Create an uninitialized point.
TFastVector< MaxSize, Element > & operator=(const TFastVector< MaxSize, Element > &vector)
TFastVector< MaxSize, Element > operator*(Element scalar) const
Element m_elements[MaxSize]
void ScaledCumulate(const TFastVector< MaxSize, Element > &vector, Element scale)
Add second vector scaled by specified factor.
bool operator<(const TFastVector< MaxSize, Element > &vector) const
void GetMinimal(const TFastVector< MaxSize, Element > &vector, TFastVector< MaxSize, Element > &result) const
Get vector with minimal elements values.
TFastVector< MaxSize, Element > & operator+=(const TFastVector< MaxSize, Element > &vector)
Element GetDotProduct(const TFastVector< MaxSize, Element > &vector) const
Return dot product of two vectors.
bool operator!=(const TFastVector< MaxSize, Element > &vector) const
bool IsNull(Element tolerance=I_BIG_EPSILON) const
Check if this vector is null.
Element & GetElementRef(int i)
Get reference to element at specified i.
bool EnsureElementsCount(int count, const Element &value=Element())
Ensure, that number of elements vector cannot be smaller that some value.
TFastVector< MaxSize, Element > GetTranslated(const TFastVector< MaxSize, Element > &vector)
Get translated point.
bool Serialize(iser::IArchive &archive)
Serialize this vector to specified archive.
TFastVector(const imath::TVector< Size, Element > &vector)
const Element & operator[](int i) const
bool operator>(const TFastVector< MaxSize, Element > &vector) const
Element GetDistance2(const TFastVector< MaxSize, Element > &vector) const
Return distance square between two vectors.
void Translate(const TFastVector< MaxSize, Element > &vector)
Translate the point.
TFastVector< MaxSize, Element > operator-(const TFastVector< MaxSize, Element > &vector) const
TFastVector(const TFastVector< MaxSize, Element > &vector)
Copy constructor.
TFastVector(int componentsCount, const Element &value=Element())
Create vector and initialize number of components.
void GetTranslated(const TFastVector< MaxSize, Element > &vector, TFastVector< MaxSize, Element > &result)
/overloaded
Element & operator[](int i)
TFastVector< MaxSize, Element > & operator*=(Element scalar)
Element GetLength() const
Return euclidian length.
TFastVector< MaxSize, Element > operator/(Element scalar) const
Implementation of fixed-size mathematical vector with specified type of elements.
Definition TVector.h:95
Process tag used to group data in archive stream.
Definition CArchiveTag.h:22
@ TT_LEAF
Leaf tag, it can contain only one primitive element.
Definition CArchiveTag.h:48
@ TT_MULTIPLE
Multiple tag containing variable number of child tags.
Definition CArchiveTag.h:42
Represents an input/output persistence archive for object serialization.
Definition IArchive.h:164
virtual bool Process(bool &value)=0
Processes (reads or writes) a boolean value.
virtual bool EndTag(const CArchiveTag &tag)=0
Ends a tagged section in the archive.
virtual bool BeginMultiTag(const CArchiveTag &tag, const CArchiveTag &subTag, int &count)=0
Begins a tagged section containing multiple elements of the same type.
virtual bool IsStoring() const =0
Checks if this archive is in storing (writing) or loading (reading) mode.
virtual bool BeginTag(const CArchiveTag &tag)=0
Begins a tagged section in the archive.
static const double I_BIG_EPSILON
Definition istd.h:26
Package with mathematical functions and algebraical primitives.
uint qHash(const TFastVector< MaxSize, Element > &v, uint seed=0)