1
0
mirror of https://git.dev.opencascade.org/repos/occt.git synced 2025-04-04 18:06:22 +03:00
occt/src/math/math_VectorBase.lxx
dpasukhi 1103eb60af 0033370: Foundation Classes - Moving into STL and Boost functionality
NCollection containers update:
  - NCollection_Array1 - updated functionality
  - NCollection_Array2 - NCollection_Array1 as a wrapper for 2array
  - NCollection_Vector -> NCollection_DynamicArray was renamed and reworked.
TCollection:
  - Use static empty string to avoid allocations on empty string
 NCollection allocators update:
  - NCollection_Allocator - allocator that used Standard::Allocate
  - NCollection_OccAllocator - allocator-wrapper that used OCC BaseAllocator objects
  - NCollection_IncAllocator - rework to increase performance
Standard:
  - Rework functionality to use different allocation libs
  - Implement basic of new way to wrap allocations tools
  - Define 4 ways to allocation (defines in configure stage)
 Additional changes:
  - Hash function uses std::hash functionality
   - size_t as a hash value
  - New HashUtils with Murmur and FVN hash algo for x32 and x64
  - Deprecated _0.cxx and .gxx DE classes reorganized
  - Create own utility for std memory
  - Update Standard_Transient to be more platform-independent
 Math TK changes:
  - math_Vector -> match_BaseVector<>
    - Buffer decreased to cash 32 elements instead of 512
2023-12-04 13:37:09 +00:00

525 lines
17 KiB
Plaintext

// Copyright (c) 1997-1999 Matra Datavision
// Copyright (c) 1999-2023 OPEN CASCADE SAS
//
// This file is part of Open CASCADE Technology software library.
//
// This library is free software; you can redistribute it and/or modify it under
// the terms of the GNU Lesser General Public License version 2.1 as published
// by the Free Software Foundation, with special exception defined in the file
// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
// distribution for complete text of the license and disclaimer of any warranty.
//
// Alternatively, this file may be used under the terms of Open CASCADE
// commercial license or contractual agreement.
#include <Standard_DimensionError.hxx>
#include <Standard_DivideByZero.hxx>
#include <Standard_RangeError.hxx>
#include <Standard_NullValue.hxx>
#include <stdio.h>
template<typename TheItemType>
math_VectorBase<TheItemType>::math_VectorBase(const Standard_Integer theLower,
const Standard_Integer theUpper) :
Array(*myBuffer.data(), theLower, theUpper, (theUpper - theLower + 1 <= math_VectorBase::THE_BUFFER_SIZE))
{}
template<typename TheItemType>
math_VectorBase<TheItemType>::math_VectorBase(const Standard_Integer theLower,
const Standard_Integer theUpper,
const TheItemType theInitialValue) :
Array(*myBuffer.data(), theLower, theUpper, (theUpper - theLower + 1 <= math_VectorBase::THE_BUFFER_SIZE))
{
Array.Init(theInitialValue);
}
template<typename TheItemType>
math_VectorBase<TheItemType>::math_VectorBase(const TheItemType* theTab,
const Standard_Integer theLower,
const Standard_Integer theUpper) :
Array(*theTab, theLower, theUpper)
{}
template<typename TheItemType>
math_VectorBase<TheItemType>::math_VectorBase(const gp_XY& theOther) :
Array(*myBuffer.data(), 1, 2)
{
Array(1) = static_cast<TheItemType>(theOther.X());
Array(2) = static_cast<TheItemType>(theOther.Y());
}
template<typename TheItemType>
math_VectorBase<TheItemType>::math_VectorBase(const gp_XYZ& theOther) :
Array(*myBuffer.data(), 1, 3)
{
Array(1) = static_cast<TheItemType>(theOther.X());
Array(2) = static_cast<TheItemType>(theOther.Y());
Array(3) = static_cast<TheItemType>(theOther.Z());
}
template<typename TheItemType>
void math_VectorBase<TheItemType>::Init(const TheItemType theInitialValue)
{
Array.Init(theInitialValue);
}
template<typename TheItemType>
math_VectorBase<TheItemType>::math_VectorBase(const math_VectorBase<TheItemType>& theOther) :
Array(theOther.Array)
{}
template<typename TheItemType>
void math_VectorBase<TheItemType>::SetLower(const Standard_Integer theLower)
{
Array.UpdateLowerBound(theLower);
}
template<typename TheItemType>
Standard_Real math_VectorBase<TheItemType>::Norm() const
{
Standard_Real Result = 0;
for (Standard_Integer Index = Lower(); Index <= Upper(); Index++)
{
Result = Result + Array(Index) * Array(Index);
}
return Sqrt(Result);
}
template<typename TheItemType>
Standard_Real math_VectorBase<TheItemType>::Norm2() const
{
Standard_Real Result = 0;
for (Standard_Integer Index = Lower(); Index <= Upper(); Index++)
{
Result = Result + Array(Index) * Array(Index);
}
return Result;
}
template<typename TheItemType>
Standard_Integer math_VectorBase<TheItemType>::Max() const
{
Standard_Integer I = 0;
Standard_Real X = RealFirst();
for (Standard_Integer Index = Lower(); Index <= Upper(); Index++)
{
if (Array(Index) > X)
{
X = Array(Index);
I = Index;
}
}
return I;
}
template<typename TheItemType>
Standard_Integer math_VectorBase<TheItemType>::Min() const
{
Standard_Integer I = 0;
Standard_Real X = RealLast();
for (Standard_Integer Index = Lower(); Index <= Upper(); Index++)
{
if (Array(Index) < X)
{
X = Array(Index);
I = Index;
}
}
return I;
}
template<typename TheItemType>
void math_VectorBase<TheItemType>::Set(const Standard_Integer theI1,
const Standard_Integer theI2,
const math_VectorBase<TheItemType>& theV)
{
Standard_RangeError_Raise_if((theI1 < Lower()) || (theI2 > Upper()) \
|| (theI1 > theI2) || (theI2 - theI1 + 1 != theV.Length()), \
"math_VectorBase::Set() - invalid indices");
Standard_Integer I = theV.Lower();
for (Standard_Integer Index = theI1; Index <= theI2; Index++)
{
Array(Index) = theV.Array(I);
I++;
}
}
template<typename TheItemType>
void math_VectorBase<TheItemType>::Normalize()
{
Standard_Real Result = Norm();
Standard_NullValue_Raise_if((Result <= RealEpsilon()), \
"math_VectorBase::Normalize() - vector has zero norm");
for (Standard_Integer Index = Lower(); Index <= Upper(); Index++)
{
Array(Index) = Array(Index) / Result;
}
}
template<typename TheItemType>
math_VectorBase<TheItemType> math_VectorBase<TheItemType>::Normalized() const
{
math_VectorBase Result = *this;
Result.Normalize();
return Result;
}
template<typename TheItemType>
void math_VectorBase<TheItemType>::Invert()
{
for (Standard_Integer Index = Lower(); Index <= (Lower() + Length()) >> 1; Index++)
{
Standard_Integer J = Upper() + Lower() - Index;
TheItemType aTemp = Array(Index);
Array(Index) = Array(J);
Array(J) = aTemp;
}
}
template<typename TheItemType>
math_VectorBase<TheItemType> math_VectorBase<TheItemType>::Inverse() const
{
math_VectorBase Result = *this;
Result.Invert();
return Result;
}
template<typename TheItemType>
math_VectorBase<TheItemType> math_VectorBase<TheItemType>::Multiplied(const TheItemType theRight) const
{
math_VectorBase Result(Lower(), Upper());
for (Standard_Integer Index = Lower(); Index <= Upper(); Index++)
{
Result.Array(Index) = Array(Index) * theRight;
}
return Result;
}
template<typename TheItemType>
math_VectorBase<TheItemType> math_VectorBase<TheItemType>::TMultiplied(const TheItemType theRight) const
{
math_VectorBase Result(Lower(), Upper());
for (Standard_Integer Index = Lower(); Index <= Upper(); Index++)
{
Result.Array(Index) = Array(Index) * theRight;
}
return Result;
}
template<typename TheItemType>
void math_VectorBase<TheItemType>::Multiply(const TheItemType theRight)
{
for (Standard_Integer Index = Lower(); Index <= Upper(); Index++)
{
Array(Index) = Array(Index) * theRight;
}
}
template<typename TheItemType>
void math_VectorBase<TheItemType>::Divide(const TheItemType theRight)
{
Standard_DivideByZero_Raise_if(Abs(theRight) <= RealEpsilon(), \
"math_VectorBase::Divide() - devisor is zero");
for (Standard_Integer Index = Lower(); Index <= Upper(); Index++)
{
Array(Index) = Array(Index) / theRight;
}
}
template<typename TheItemType>
math_VectorBase<TheItemType> math_VectorBase<TheItemType>::Divided(const TheItemType theRight) const
{
Standard_DivideByZero_Raise_if(Abs(theRight) <= RealEpsilon(), \
"math_VectorBase::Divided() - devisor is zero");
math_VectorBase temp = Multiplied(1. / theRight);
return temp;
}
template<typename TheItemType>
void math_VectorBase<TheItemType>::Add(const math_VectorBase<TheItemType>& theRight)
{
Standard_DimensionError_Raise_if(Length() != theRight.Length(), \
"math_VectorBase::Add() - input vector has wrong dimensions");
Standard_Integer I = theRight.Lower();
for (Standard_Integer Index = Lower(); Index <= Upper(); Index++)
{
Array(Index) = Array(Index) + theRight.Array(I);
I++;
}
}
template<typename TheItemType>
math_VectorBase<TheItemType> math_VectorBase<TheItemType>::Added(const math_VectorBase<TheItemType>& theRight) const
{
Standard_DimensionError_Raise_if(Length() != theRight.Length(), \
"math_VectorBase::Added() - input vector has wrong dimensions");
math_VectorBase Result(Lower(), Upper());
Standard_Integer I = theRight.Lower();
for (Standard_Integer Index = Lower(); Index <= Upper(); Index++)
{
Result.Array(Index) = Array(Index) + theRight.Array(I);
I++;
}
return Result;
}
template<typename TheItemType>
void math_VectorBase<TheItemType>::Subtract(const math_VectorBase<TheItemType>& theRight)
{
Standard_DimensionError_Raise_if(Length() != theRight.Length(), \
"math_VectorBase::Subtract() - input vector has wrong dimensions");
Standard_Integer I = theRight.Lower();
for (Standard_Integer Index = Lower(); Index <= Upper(); Index++)
{
Array(Index) = Array(Index) - theRight.Array(I);
I++;
}
}
template<typename TheItemType>
math_VectorBase<TheItemType> math_VectorBase<TheItemType>::Subtracted(const math_VectorBase<TheItemType>& theRight) const
{
Standard_DimensionError_Raise_if(Length() != theRight.Length(), \
"math_VectorBase::Subtracted() - input vector has wrong dimensions");
math_VectorBase Result(Lower(), Upper());
Standard_Integer I = theRight.Lower();
for (Standard_Integer Index = Lower(); Index <= Upper(); Index++)
{
Result.Array(Index) = Array(Index) - theRight.Array(I);
I++;
}
return Result;
}
template<typename TheItemType>
math_VectorBase<TheItemType> math_VectorBase<TheItemType>::Slice(const Standard_Integer theI1, const Standard_Integer theI2) const
{
Standard_RangeError_Raise_if((theI1 < Lower()) || (theI1 > Upper()) || (theI2 < Lower()) || (theI2 > Upper()), \
"math_VectorBase::Slice() - invalid indices");
if (theI2 >= theI1)
{
math_VectorBase Result(theI1, theI2);
for (Standard_Integer Index = theI1; Index <= theI2; Index++)
{
Result.Array(Index) = Array(Index);
}
return Result;
}
else
{
math_VectorBase Result(theI2, theI1);
for (Standard_Integer Index = theI1; Index >= theI2; Index--)
{
Result.Array(Index) = Array(Index);
}
return Result;
}
}
template<typename TheItemType>
void math_VectorBase<TheItemType>::Add(const math_VectorBase<TheItemType>& theLeft, const math_VectorBase<TheItemType>& theRight)
{
Standard_DimensionError_Raise_if((Length() != theRight.Length()) || (theRight.Length() != theLeft.Length()), \
"math_VectorBase::Add() - input vectors have wrong dimensions");
Standard_Integer I = theLeft.Lower();
Standard_Integer J = theRight.Lower();
for (Standard_Integer Index = Lower(); Index <= Upper(); Index++)
{
Array(Index) = theLeft.Array(I) + theRight.Array(J);
I++;
J++;
}
}
template<typename TheItemType>
void math_VectorBase<TheItemType>::Subtract(const math_VectorBase<TheItemType>& theLeft, const math_VectorBase<TheItemType>& theRight)
{
Standard_DimensionError_Raise_if((Length() != theRight.Length()) || (theRight.Length() != theLeft.Length()), \
"math_VectorBase::Subtract() - input vectors have wrong dimensions");
Standard_Integer I = theLeft.Lower();
Standard_Integer J = theRight.Lower();
for (Standard_Integer Index = Lower(); Index <= Upper(); Index++)
{
Array(Index) = theLeft.Array(I) - theRight.Array(J);
I++;
J++;
}
}
template<typename TheItemType>
void math_VectorBase<TheItemType>::Multiply(const math_Matrix& theLeft, const math_VectorBase<TheItemType>& theRight)
{
Standard_DimensionError_Raise_if((Length() != theLeft.RowNumber()) \
|| (theLeft.ColNumber() != theRight.Length()), \
"math_VectorBase::Multiply() - input matrix and /or vector have wrong dimensions");
Standard_Integer Index = Lower();
for (Standard_Integer I = theLeft.LowerRowIndex; I <= theLeft.UpperRowIndex; I++)
{
Array(Index) = 0.0;
Standard_Integer K = theRight.Lower();
for (Standard_Integer J = theLeft.LowerColIndex; J <= theLeft.UpperColIndex; J++)
{
Array(Index) = Array(Index) + theLeft.Array(I, J) * theRight.Array(K);
K++;
}
Index++;
}
}
template<typename TheItemType>
void math_VectorBase<TheItemType>::Multiply(const math_VectorBase<TheItemType>& theLeft, const math_Matrix& theRight)
{
Standard_DimensionError_Raise_if((Length() != theRight.ColNumber()) \
|| (theLeft.Length() != theRight.RowNumber()), \
"math_VectorBase::Multiply() - input matrix and /or vector have wrong dimensions");
Standard_Integer Index = Lower();
for (Standard_Integer J = theRight.LowerColIndex; J <= theRight.UpperColIndex; J++)
{
Array(Index) = 0.0;
Standard_Integer K = theLeft.Lower();
for (Standard_Integer I = theRight.LowerRowIndex; I <= theRight.UpperRowIndex; I++)
{
Array(Index) = Array(Index) + theLeft.Array(K) * theRight.Array(I, J);
K++;
}
Index++;
}
}
template<typename TheItemType>
void math_VectorBase<TheItemType>::TMultiply(const math_Matrix& theTLeft, const math_VectorBase<TheItemType>& theRight)
{
Standard_DimensionError_Raise_if((Length() != theTLeft.ColNumber()) \
|| (theTLeft.RowNumber() != theRight.Length()), \
"math_VectorBase::TMultiply() - input matrix and /or vector have wrong dimensions");
Standard_Integer Index = Lower();
for (Standard_Integer I = theTLeft.LowerColIndex; I <= theTLeft.UpperColIndex; I++)
{
Array(Index) = 0.0;
Standard_Integer K = theRight.Lower();
for (Standard_Integer J = theTLeft.LowerRowIndex; J <= theTLeft.UpperRowIndex; J++)
{
Array(Index) = Array(Index) + theTLeft.Array(J, I) * theRight.Array(K);
K++;
}
Index++;
}
}
template<typename TheItemType>
void math_VectorBase<TheItemType>::TMultiply(const math_VectorBase<TheItemType>& theLeft, const math_Matrix& theTRight)
{
Standard_DimensionError_Raise_if((Length() != theTRight.RowNumber()) \
|| (theLeft.Length() != theTRight.ColNumber()), \
"math_VectorBase::TMultiply() - input matrix and /or vector have wrong dimensions");
Standard_Integer Index = Lower();
for (Standard_Integer J = theTRight.LowerRowIndex; J <= theTRight.UpperRowIndex; J++)
{
Array(Index) = 0.0;
Standard_Integer K = theLeft.Lower();
for (Standard_Integer I = theTRight.LowerColIndex;
I <= theTRight.UpperColIndex; I++)
{
Array(Index) = Array(Index) + theLeft.Array(K) * theTRight.Array(J, I);
K++;
}
Index++;
}
}
template<typename TheItemType>
TheItemType math_VectorBase<TheItemType>::Multiplied(const math_VectorBase<TheItemType>& theRight) const
{
Standard_Real Result = 0;
Standard_DimensionError_Raise_if(Length() != theRight.Length(), \
"math_VectorBase::Multiplied() - input vector has wrong dimensions");
Standard_Integer I = theRight.Lower();
for (Standard_Integer Index = Lower(); Index <= Upper(); Index++)
{
Result = Result + Array(Index) * theRight.Array(I);
I++;
}
return Result;
}
template<typename TheItemType>
math_VectorBase<TheItemType> math_VectorBase<TheItemType>::Opposite()
{
math_VectorBase Result(Lower(), Upper());
for (Standard_Integer Index = Lower(); Index <= Upper(); Index++)
{
Result.Array(Index) = -Array(Index);
}
return Result;
}
template<typename TheItemType>
math_VectorBase<TheItemType> math_VectorBase<TheItemType>::Multiplied(const math_Matrix& theRight)const
{
Standard_DimensionError_Raise_if(Length() != theRight.RowNumber(), \
"math_VectorBase::Multiplied() - input matrix has wrong dimensions");
math_VectorBase Result(theRight.LowerColIndex, theRight.UpperColIndex);
for (Standard_Integer J2 = theRight.LowerColIndex; J2 <= theRight.UpperColIndex; J2++)
{
Result.Array(J2) = 0.0;
Standard_Integer theI2 = theRight.LowerRowIndex;
for (Standard_Integer I = Lower(); I <= Upper(); I++)
{
Result.Array(J2) = Result.Array(J2) + Array(I) * theRight.Array(theI2, J2);
theI2++;
}
}
return Result;
}
template<typename TheItemType>
void math_VectorBase<TheItemType>::Multiply(const TheItemType theLeft, const math_VectorBase<TheItemType>& theRight)
{
Standard_DimensionError_Raise_if((Length() != theRight.Length()), \
"math_VectorBase::Multiply() - input vector has wrong dimensions");
for (Standard_Integer I = Lower(); I <= Upper(); I++)
{
Array(I) = theLeft * theRight.Array(I);
}
}
template<typename TheItemType>
math_VectorBase<TheItemType>& math_VectorBase<TheItemType>::Initialized(const math_VectorBase<TheItemType>& theOther)
{
Standard_DimensionError_Raise_if(Length() != theOther.Length(), \
"math_VectorBase::Initialized() - input vector has wrong dimensions");
memmove(&Array.ChangeFirst(), &theOther.Array.First(), sizeof(TheItemType) * Array.Length());
return *this;
}
template<typename TheItemType>
void math_VectorBase<TheItemType>::Dump(Standard_OStream& theO) const
{
theO << "math_Vector of Length = " << Length() << "\n";
for (Standard_Integer Index = Lower(); Index <= Upper(); Index++)
{
theO << "math_Vector(" << Index << ") = " << Array(Index) << "\n";
}
}