mirror of
https://git.dev.opencascade.org/repos/occt.git
synced 2025-07-15 12:35:51 +03:00
Foundation Classes, math_DoubleTab - Rework to NCollection container (#607)
- Refactors `math_DoubleTab` to use `NCollection_Array2` as its underlying container - Eemoves the old C‐array implementation, and updates collection classes to improve move semantics and bounds manipulation. - Rework `math_DoubleTab` to wrap `NCollection_Array2`, with buffer optimization for small sizes - Enhance `NCollection_Array2` and `NCollection_Array1` with proper move semantics and bound‐updating methods - Remove legacy `.lxx`/`.cxx` implementations, add tests and update CMake file lists
This commit is contained in:
parent
878cd2f6d6
commit
ceafdb0436
@ -4,5 +4,6 @@ set(OCCT_TKMath_GTests_FILES_LOCATION "${CMAKE_CURRENT_LIST_DIR}")
|
||||
set(OCCT_TKMath_GTests_FILES
|
||||
Bnd_BoundSortBox_Test.cxx
|
||||
ElCLib_Test.cxx
|
||||
math_DoubleTab_Test.cxx
|
||||
math_Matrix_Test.cxx
|
||||
)
|
||||
|
215
src/FoundationClasses/TKMath/GTests/math_DoubleTab_Test.cxx
Normal file
215
src/FoundationClasses/TKMath/GTests/math_DoubleTab_Test.cxx
Normal file
@ -0,0 +1,215 @@
|
||||
// Copyright (c) 2025 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 <math_DoubleTab.hxx>
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
#include <Standard_Real.hxx>
|
||||
#include <Standard_Integer.hxx>
|
||||
#include <Precision.hxx>
|
||||
|
||||
// Tests for constructors
|
||||
TEST(MathDoubleTabTest, DefaultConstructor)
|
||||
{
|
||||
// Test standard constructor with ranges
|
||||
math_DoubleTab aTab(1, 3, 1, 3);
|
||||
|
||||
// Initialize with test values
|
||||
aTab.Init(5.0);
|
||||
|
||||
// Check all values are set to 5.0
|
||||
for (Standard_Integer anI = 1; anI <= 3; anI++)
|
||||
{
|
||||
for (Standard_Integer aJ = 1; aJ <= 3; aJ++)
|
||||
{
|
||||
EXPECT_DOUBLE_EQ(aTab.Value(anI, aJ), 5.0);
|
||||
EXPECT_DOUBLE_EQ(aTab(anI, aJ), 5.0); // Test operator()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
TEST(MathDoubleTabTest, ExternalArrayConstructor)
|
||||
{
|
||||
// Create external array
|
||||
Standard_Real anArray[9] = {1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0};
|
||||
|
||||
// Create math_DoubleTab from external array
|
||||
math_DoubleTab aTab(anArray, 1, 3, 1, 3);
|
||||
|
||||
// Check values are correctly accessed
|
||||
Standard_Integer anIndex = 0;
|
||||
for (Standard_Integer anI = 1; anI <= 3; anI++)
|
||||
{
|
||||
for (Standard_Integer aJ = 1; aJ <= 3; aJ++)
|
||||
{
|
||||
EXPECT_DOUBLE_EQ(aTab.Value(anI, aJ), anArray[anIndex]);
|
||||
anIndex++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
TEST(MathDoubleTabTest, CopyConstructor)
|
||||
{
|
||||
// Create original array
|
||||
math_DoubleTab aOriginal(1, 3, 1, 3);
|
||||
aOriginal.Init(10.0);
|
||||
|
||||
// Set some specific values
|
||||
aOriginal.Value(1, 1) = 1.5;
|
||||
aOriginal.Value(2, 2) = 2.5;
|
||||
aOriginal.Value(3, 3) = 3.5;
|
||||
|
||||
// Create copy
|
||||
math_DoubleTab aCopy(aOriginal);
|
||||
|
||||
// Check values are copied correctly
|
||||
EXPECT_DOUBLE_EQ(aCopy.Value(1, 1), 1.5);
|
||||
EXPECT_DOUBLE_EQ(aCopy.Value(2, 2), 2.5);
|
||||
EXPECT_DOUBLE_EQ(aCopy.Value(3, 3), 3.5);
|
||||
EXPECT_DOUBLE_EQ(aCopy.Value(1, 2), 10.0); // Check other values too
|
||||
}
|
||||
|
||||
// Tests for basic operations
|
||||
TEST(MathDoubleTabTest, InitOperation)
|
||||
{
|
||||
math_DoubleTab aTab(0, 2, 0, 2);
|
||||
|
||||
// Initialize with specific value
|
||||
aTab.Init(7.5);
|
||||
|
||||
// Check all elements are set
|
||||
for (Standard_Integer anI = 0; anI <= 2; anI++)
|
||||
{
|
||||
for (Standard_Integer aJ = 0; aJ <= 2; aJ++)
|
||||
{
|
||||
EXPECT_DOUBLE_EQ(aTab.Value(anI, aJ), 7.5);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
TEST(MathDoubleTabTest, ValueAccess)
|
||||
{
|
||||
math_DoubleTab aTab(1, 2, 1, 2);
|
||||
|
||||
// Set values using Value method
|
||||
aTab.Value(1, 1) = 11.0;
|
||||
aTab.Value(1, 2) = 12.0;
|
||||
aTab.Value(2, 1) = 21.0;
|
||||
aTab.Value(2, 2) = 22.0;
|
||||
|
||||
// Check values using operator()
|
||||
EXPECT_DOUBLE_EQ(aTab(1, 1), 11.0);
|
||||
EXPECT_DOUBLE_EQ(aTab(1, 2), 12.0);
|
||||
EXPECT_DOUBLE_EQ(aTab(2, 1), 21.0);
|
||||
EXPECT_DOUBLE_EQ(aTab(2, 2), 22.0);
|
||||
}
|
||||
|
||||
TEST(MathDoubleTabTest, OperatorAccess)
|
||||
{
|
||||
math_DoubleTab aTab(-1, 1, -1, 1);
|
||||
|
||||
// Set values using operator()
|
||||
aTab(-1, -1) = -11.0;
|
||||
aTab(-1, 0) = -10.0;
|
||||
aTab(-1, 1) = -9.0;
|
||||
aTab(0, -1) = -1.0;
|
||||
aTab(0, 0) = 0.0;
|
||||
aTab(0, 1) = 1.0;
|
||||
aTab(1, -1) = 9.0;
|
||||
aTab(1, 0) = 10.0;
|
||||
aTab(1, 1) = 11.0;
|
||||
|
||||
// Check values using Value method
|
||||
EXPECT_DOUBLE_EQ(aTab.Value(-1, -1), -11.0);
|
||||
EXPECT_DOUBLE_EQ(aTab.Value(-1, 0), -10.0);
|
||||
EXPECT_DOUBLE_EQ(aTab.Value(-1, 1), -9.0);
|
||||
EXPECT_DOUBLE_EQ(aTab.Value(0, -1), -1.0);
|
||||
EXPECT_DOUBLE_EQ(aTab.Value(0, 0), 0.0);
|
||||
EXPECT_DOUBLE_EQ(aTab.Value(0, 1), 1.0);
|
||||
EXPECT_DOUBLE_EQ(aTab.Value(1, -1), 9.0);
|
||||
EXPECT_DOUBLE_EQ(aTab.Value(1, 0), 10.0);
|
||||
EXPECT_DOUBLE_EQ(aTab.Value(1, 1), 11.0);
|
||||
}
|
||||
|
||||
TEST(MathDoubleTabTest, CopyMethod)
|
||||
{
|
||||
// Create source array
|
||||
math_DoubleTab aSource(1, 2, 1, 2);
|
||||
aSource.Value(1, 1) = 100.0;
|
||||
aSource.Value(1, 2) = 200.0;
|
||||
aSource.Value(2, 1) = 300.0;
|
||||
aSource.Value(2, 2) = 400.0;
|
||||
|
||||
// Create destination array
|
||||
math_DoubleTab aDest(1, 2, 1, 2);
|
||||
aDest.Init(0.0);
|
||||
|
||||
// Copy from source to destination
|
||||
aSource.Copy(aDest);
|
||||
|
||||
// Check values are copied
|
||||
EXPECT_DOUBLE_EQ(aDest.Value(1, 1), 100.0);
|
||||
EXPECT_DOUBLE_EQ(aDest.Value(1, 2), 200.0);
|
||||
EXPECT_DOUBLE_EQ(aDest.Value(2, 1), 300.0);
|
||||
EXPECT_DOUBLE_EQ(aDest.Value(2, 2), 400.0);
|
||||
}
|
||||
|
||||
// Tests for buffer optimization
|
||||
TEST(MathDoubleTabTest, SmallArrayOptimization)
|
||||
{
|
||||
// Test that small arrays (<=16 elements) use buffer optimization
|
||||
// 4x4 = 16 elements, should use buffer
|
||||
math_DoubleTab aSmallTab(1, 4, 1, 4);
|
||||
aSmallTab.Init(42.0);
|
||||
|
||||
// Set and read values to ensure it works correctly
|
||||
aSmallTab.Value(2, 3) = 123.45;
|
||||
EXPECT_DOUBLE_EQ(aSmallTab.Value(2, 3), 123.45);
|
||||
EXPECT_DOUBLE_EQ(aSmallTab.Value(1, 1), 42.0);
|
||||
}
|
||||
|
||||
TEST(MathDoubleTabTest, LargeArrayAllocation)
|
||||
{
|
||||
// Test that large arrays (>16 elements) allocate memory
|
||||
// 5x5 = 25 elements, should allocate
|
||||
math_DoubleTab aLargeTab(1, 5, 1, 5);
|
||||
aLargeTab.Init(99.99);
|
||||
|
||||
// Set and read values to ensure it works correctly
|
||||
aLargeTab.Value(3, 4) = 987.65;
|
||||
EXPECT_DOUBLE_EQ(aLargeTab.Value(3, 4), 987.65);
|
||||
EXPECT_DOUBLE_EQ(aLargeTab.Value(1, 1), 99.99);
|
||||
}
|
||||
|
||||
// Tests for edge cases
|
||||
TEST(MathDoubleTabTest, SingleElement)
|
||||
{
|
||||
// Test with single element array
|
||||
math_DoubleTab aSingle(5, 5, 10, 10);
|
||||
aSingle.Value(5, 10) = 777.0;
|
||||
|
||||
EXPECT_DOUBLE_EQ(aSingle.Value(5, 10), 777.0);
|
||||
EXPECT_DOUBLE_EQ(aSingle(5, 10), 777.0);
|
||||
}
|
||||
|
||||
TEST(MathDoubleTabTest, NegativeIndices)
|
||||
{
|
||||
// Test with negative indices
|
||||
math_DoubleTab aNegTab(-5, -1, -3, -1);
|
||||
aNegTab.Init(-1.0);
|
||||
|
||||
aNegTab.Value(-3, -2) = -999.0;
|
||||
EXPECT_DOUBLE_EQ(aNegTab.Value(-3, -2), -999.0);
|
||||
EXPECT_DOUBLE_EQ(aNegTab.Value(-5, -3), -1.0);
|
||||
}
|
@ -31,9 +31,7 @@ set(OCCT_math_FILES
|
||||
math_DirectPolynomialRoots.cxx
|
||||
math_DirectPolynomialRoots.hxx
|
||||
math_DirectPolynomialRoots.lxx
|
||||
math_DoubleTab.cxx
|
||||
math_DoubleTab.hxx
|
||||
math_DoubleTab.lxx
|
||||
math_EigenValuesSearcher.cxx
|
||||
math_EigenValuesSearcher.hxx
|
||||
math_FRPR.cxx
|
||||
|
@ -1,103 +0,0 @@
|
||||
// Copyright (c) 1997-1999 Matra Datavision
|
||||
// Copyright (c) 1999-2014 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.
|
||||
|
||||
// Lpa, le 7/02/92
|
||||
|
||||
#include <math_DoubleTab.hxx>
|
||||
#include <Standard_OutOfRange.hxx>
|
||||
|
||||
// macro to get size of C array
|
||||
#define CARRAY_LENGTH(arr) (int)(sizeof(arr) / sizeof(arr[0]))
|
||||
|
||||
void math_DoubleTab::Allocate()
|
||||
{
|
||||
Standard_Integer RowNumber = UppR - LowR + 1;
|
||||
Standard_Integer ColNumber = UppC - LowC + 1;
|
||||
|
||||
if (isAllocated)
|
||||
Addr = (Standard_Real*)Standard::Allocate(RowNumber * ColNumber * sizeof(Standard_Real));
|
||||
}
|
||||
|
||||
math_DoubleTab::math_DoubleTab(const Standard_Integer LowerRow,
|
||||
const Standard_Integer UpperRow,
|
||||
const Standard_Integer LowerCol,
|
||||
const Standard_Integer UpperCol)
|
||||
: Addr(Buf),
|
||||
isAllocated((UpperRow - LowerRow + 1) * (UpperCol - LowerCol + 1) > CARRAY_LENGTH(Buf)),
|
||||
LowR(LowerRow),
|
||||
UppR(UpperRow),
|
||||
LowC(LowerCol),
|
||||
UppC(UpperCol)
|
||||
{
|
||||
Allocate();
|
||||
}
|
||||
|
||||
math_DoubleTab::math_DoubleTab(const Standard_Address Tab,
|
||||
const Standard_Integer LowerRow,
|
||||
const Standard_Integer UpperRow,
|
||||
const Standard_Integer LowerCol,
|
||||
const Standard_Integer UpperCol)
|
||||
: Addr(Tab),
|
||||
isAllocated(Standard_False),
|
||||
LowR(LowerRow),
|
||||
UppR(UpperRow),
|
||||
LowC(LowerCol),
|
||||
UppC(UpperCol)
|
||||
{
|
||||
Allocate();
|
||||
}
|
||||
|
||||
void math_DoubleTab::Init(const Standard_Real InitValue)
|
||||
{
|
||||
for (Standard_Integer anIndex = 0; anIndex < (UppR - LowR + 1) * (UppC - LowC + 1); anIndex++)
|
||||
{
|
||||
((Standard_Real*)Addr)[anIndex] = InitValue;
|
||||
}
|
||||
}
|
||||
|
||||
math_DoubleTab::math_DoubleTab(const math_DoubleTab& Other)
|
||||
: Addr(Buf),
|
||||
isAllocated((Other.UppR - Other.LowR + 1) * (Other.UppC - Other.LowC + 1)
|
||||
> CARRAY_LENGTH(Buf)),
|
||||
LowR(Other.LowR),
|
||||
UppR(Other.UppR),
|
||||
LowC(Other.LowC),
|
||||
UppC(Other.UppC)
|
||||
{
|
||||
Allocate();
|
||||
memmove(Addr, Other.Addr, (int)((UppR - LowR + 1) * (UppC - LowC + 1) * sizeof(Standard_Real)));
|
||||
}
|
||||
|
||||
void math_DoubleTab::Free()
|
||||
{
|
||||
// free the data
|
||||
if (isAllocated)
|
||||
{
|
||||
Standard::Free(Addr);
|
||||
}
|
||||
|
||||
Addr = 0;
|
||||
}
|
||||
|
||||
void math_DoubleTab::SetLowerRow(const Standard_Integer LowerRow)
|
||||
{
|
||||
UppR = UppR - LowR + LowerRow;
|
||||
LowR = LowerRow;
|
||||
}
|
||||
|
||||
void math_DoubleTab::SetLowerCol(const Standard_Integer LowerCol)
|
||||
{
|
||||
UppC = UppC - LowC + LowerCol;
|
||||
LowC = LowerCol;
|
||||
}
|
@ -20,60 +20,104 @@
|
||||
#include <Standard.hxx>
|
||||
#include <Standard_DefineAlloc.hxx>
|
||||
#include <Standard_Handle.hxx>
|
||||
#include <NCollection_Array2.hxx>
|
||||
|
||||
#include <Standard_Real.hxx>
|
||||
#include <Standard_Boolean.hxx>
|
||||
|
||||
#include <array>
|
||||
|
||||
class math_DoubleTab
|
||||
{
|
||||
static const Standard_Integer THE_BUFFER_SIZE = 16;
|
||||
|
||||
public:
|
||||
DEFINE_STANDARD_ALLOC
|
||||
DEFINE_STANDARD_ALLOC;
|
||||
DEFINE_NCOLLECTION_ALLOC;
|
||||
|
||||
Standard_EXPORT math_DoubleTab(const Standard_Integer LowerRow,
|
||||
const Standard_Integer UpperRow,
|
||||
const Standard_Integer LowerCol,
|
||||
const Standard_Integer UpperCol);
|
||||
|
||||
Standard_EXPORT math_DoubleTab(const Standard_Address Tab,
|
||||
const Standard_Integer LowerRow,
|
||||
const Standard_Integer UpperRow,
|
||||
const Standard_Integer LowerCol,
|
||||
const Standard_Integer UpperCol);
|
||||
|
||||
Standard_EXPORT void Init(const Standard_Real InitValue);
|
||||
|
||||
Standard_EXPORT math_DoubleTab(const math_DoubleTab& Other);
|
||||
|
||||
void Copy(math_DoubleTab& Other) const;
|
||||
|
||||
Standard_EXPORT void SetLowerRow(const Standard_Integer LowerRow);
|
||||
|
||||
Standard_EXPORT void SetLowerCol(const Standard_Integer LowerCol);
|
||||
|
||||
Standard_Real& Value(const Standard_Integer RowIndex, const Standard_Integer ColIndex) const;
|
||||
|
||||
Standard_Real& operator()(const Standard_Integer RowIndex, const Standard_Integer ColIndex) const
|
||||
public:
|
||||
//! Constructor for ranges [theLowerRow..theUpperRow, theLowerCol..theUpperCol]
|
||||
math_DoubleTab(const Standard_Integer theLowerRow,
|
||||
const Standard_Integer theUpperRow,
|
||||
const Standard_Integer theLowerCol,
|
||||
const Standard_Integer theUpperCol)
|
||||
: myBuffer{},
|
||||
myArray(
|
||||
(theUpperRow - theLowerRow + 1) * (theUpperCol - theLowerCol + 1) <= THE_BUFFER_SIZE
|
||||
? NCollection_Array2<Standard_Real>(*myBuffer.data(),
|
||||
theLowerRow,
|
||||
theUpperRow,
|
||||
theLowerCol,
|
||||
theUpperCol)
|
||||
: NCollection_Array2<Standard_Real>(theLowerRow, theUpperRow, theLowerCol, theUpperCol))
|
||||
{
|
||||
return Value(RowIndex, ColIndex);
|
||||
}
|
||||
|
||||
Standard_EXPORT void Free();
|
||||
public:
|
||||
//! Constructor from external data array
|
||||
math_DoubleTab(const Standard_Address theTab,
|
||||
const Standard_Integer theLowerRow,
|
||||
const Standard_Integer theUpperRow,
|
||||
const Standard_Integer theLowerCol,
|
||||
const Standard_Integer theUpperCol)
|
||||
: myArray(*static_cast<const Standard_Real*>(theTab),
|
||||
theLowerRow,
|
||||
theUpperRow,
|
||||
theLowerCol,
|
||||
theUpperCol)
|
||||
{
|
||||
}
|
||||
|
||||
~math_DoubleTab() { Free(); }
|
||||
//! Initialize all elements with theInitValue
|
||||
void Init(const Standard_Real theInitValue) { myArray.Init(theInitValue); }
|
||||
|
||||
//! Copy constructor
|
||||
math_DoubleTab(const math_DoubleTab& theOther)
|
||||
: myArray(theOther.myArray)
|
||||
{
|
||||
}
|
||||
|
||||
//! Copy data to theOther
|
||||
void Copy(math_DoubleTab& theOther) const { theOther.myArray.Assign(myArray); }
|
||||
|
||||
//! Set lower row index
|
||||
void SetLowerRow(const Standard_Integer theLowerRow) { myArray.UpdateLowerRow(theLowerRow); }
|
||||
|
||||
//! Set lower column index
|
||||
void SetLowerCol(const Standard_Integer theLowerCol) { myArray.UpdateLowerCol(theLowerCol); }
|
||||
|
||||
//! Access element at (theRowIndex, theColIndex)
|
||||
const Standard_Real& Value(const Standard_Integer theRowIndex,
|
||||
const Standard_Integer theColIndex) const
|
||||
{
|
||||
return myArray.Value(theRowIndex, theColIndex);
|
||||
}
|
||||
|
||||
//! Change element at (theRowIndex, theColIndex)
|
||||
Standard_Real& Value(const Standard_Integer theRowIndex, const Standard_Integer theColIndex)
|
||||
{
|
||||
return myArray.ChangeValue(theRowIndex, theColIndex);
|
||||
}
|
||||
|
||||
//! Operator() - alias to Value
|
||||
const Standard_Real& operator()(const Standard_Integer theRowIndex,
|
||||
const Standard_Integer theColIndex) const
|
||||
{
|
||||
return Value(theRowIndex, theColIndex);
|
||||
}
|
||||
|
||||
//! Operator() - alias to ChangeValue
|
||||
Standard_Real& operator()(const Standard_Integer theRowIndex, const Standard_Integer theColIndex)
|
||||
{
|
||||
return Value(theRowIndex, theColIndex);
|
||||
}
|
||||
|
||||
//! Destructor
|
||||
~math_DoubleTab() = default;
|
||||
|
||||
protected:
|
||||
private:
|
||||
Standard_EXPORT void Allocate();
|
||||
|
||||
Standard_Address Addr;
|
||||
Standard_Real Buf[16]{};
|
||||
Standard_Boolean isAllocated;
|
||||
Standard_Integer LowR;
|
||||
Standard_Integer UppR;
|
||||
Standard_Integer LowC;
|
||||
Standard_Integer UppC;
|
||||
std::array<Standard_Real, THE_BUFFER_SIZE> myBuffer;
|
||||
NCollection_Array2<Standard_Real> myArray;
|
||||
};
|
||||
|
||||
#include <math_DoubleTab.lxx>
|
||||
|
||||
#endif // _math_DoubleTab_HeaderFile
|
||||
|
@ -1,30 +0,0 @@
|
||||
// Copyright (c) 1997-1999 Matra Datavision
|
||||
// Copyright (c) 1999-2014 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.
|
||||
|
||||
// Lpa, le 7/02/92
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include <Standard_OutOfRange.hxx>
|
||||
|
||||
inline Standard_Real& math_DoubleTab::Value(const Standard_Integer RowIndex,
|
||||
const Standard_Integer ColIndex) const
|
||||
{
|
||||
return ((Standard_Real*)Addr)[(UppC - LowC + 1) * (RowIndex - LowR) + (ColIndex - LowC)];
|
||||
}
|
||||
|
||||
inline void math_DoubleTab::Copy(math_DoubleTab& Other) const
|
||||
{
|
||||
memmove(Other.Addr, Addr, (int)((UppR - LowR + 1) * (UppC - LowC + 1) * sizeof(Standard_Real)));
|
||||
}
|
@ -349,13 +349,24 @@ public:
|
||||
//! An exception is raised if the dimensions are different.
|
||||
Standard_EXPORT void Subtract(const math_Matrix& Left, const math_Matrix& Right);
|
||||
|
||||
//! Accesses the value of index <Row>
|
||||
//! and <Col> of a matrix.
|
||||
//! An exception is raised if <Row> and <Col> are not
|
||||
//! in the correct range.
|
||||
const Standard_Real& Value(const Standard_Integer Row, const Standard_Integer Col) const;
|
||||
|
||||
//! Accesses (in read or write mode) the value of index <Row>
|
||||
//! and <Col> of a matrix.
|
||||
//! An exception is raised if <Row> and <Col> are not
|
||||
//! in the correct range.
|
||||
Standard_Real& Value(const Standard_Integer Row, const Standard_Integer Col) const;
|
||||
Standard_Real& Value(const Standard_Integer Row, const Standard_Integer Col);
|
||||
|
||||
Standard_Real& operator()(const Standard_Integer Row, const Standard_Integer Col) const
|
||||
const Standard_Real& operator()(const Standard_Integer Row, const Standard_Integer Col) const
|
||||
{
|
||||
return Value(Row, Col);
|
||||
}
|
||||
|
||||
Standard_Real& operator()(const Standard_Integer Row, const Standard_Integer Col)
|
||||
{
|
||||
return Value(Row, Col);
|
||||
}
|
||||
|
@ -27,14 +27,23 @@ inline math_Matrix operator*(const Standard_Real Left, const math_Matrix& Right)
|
||||
return Right.Multiplied(Left);
|
||||
}
|
||||
|
||||
inline Standard_Real& math_Matrix::Value(const Standard_Integer Row,
|
||||
const Standard_Integer Col) const
|
||||
inline const Standard_Real& math_Matrix::Value(const Standard_Integer Row,
|
||||
const Standard_Integer Col) const
|
||||
{
|
||||
Standard_RangeError_Raise_if(((Row < LowerRowIndex) || (Row > UpperRowIndex)
|
||||
|| (Col < LowerColIndex) || (Col > UpperColIndex)),
|
||||
" ");
|
||||
|
||||
return Array(Row, Col);
|
||||
return Array.Value(Row, Col);
|
||||
}
|
||||
|
||||
inline Standard_Real& math_Matrix::Value(const Standard_Integer Row, const Standard_Integer Col)
|
||||
{
|
||||
Standard_RangeError_Raise_if(((Row < LowerRowIndex) || (Row > UpperRowIndex)
|
||||
|| (Col < LowerColIndex) || (Col > UpperColIndex)),
|
||||
" ");
|
||||
|
||||
return Array.Value(Row, Col);
|
||||
}
|
||||
|
||||
inline Standard_Integer math_Matrix::RowNumber() const
|
||||
|
@ -3,6 +3,7 @@ set(OCCT_TKernel_GTests_FILES_LOCATION "${CMAKE_CURRENT_LIST_DIR}")
|
||||
|
||||
set(OCCT_TKernel_GTests_FILES
|
||||
NCollection_Array1_Test.cxx
|
||||
NCollection_Array2_Test.cxx
|
||||
NCollection_BaseAllocator_Test.cxx
|
||||
NCollection_DataMap_Test.cxx
|
||||
NCollection_DoubleMap_Test.cxx
|
||||
|
@ -16,16 +16,7 @@
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
// Test fixture for NCollection_Array1 tests
|
||||
class NCollection_Array1Test : public testing::Test
|
||||
{
|
||||
protected:
|
||||
void SetUp() override {}
|
||||
|
||||
void TearDown() override {}
|
||||
};
|
||||
|
||||
TEST_F(NCollection_Array1Test, DefaultConstructor)
|
||||
TEST(NCollection_Array1Test, DefaultConstructor)
|
||||
{
|
||||
// Default constructor should not compile as it's explicitly deleted
|
||||
// NCollection_Array1<Standard_Integer> anArray;
|
||||
@ -37,7 +28,7 @@ TEST_F(NCollection_Array1Test, DefaultConstructor)
|
||||
EXPECT_EQ(10, anArray.Upper());
|
||||
}
|
||||
|
||||
TEST_F(NCollection_Array1Test, ConstructorWithBounds)
|
||||
TEST(NCollection_Array1Test, ConstructorWithBounds)
|
||||
{
|
||||
// Test constructor with explicit bounds
|
||||
NCollection_Array1<Standard_Integer> anArray(1, 5);
|
||||
@ -46,7 +37,7 @@ TEST_F(NCollection_Array1Test, ConstructorWithBounds)
|
||||
EXPECT_EQ(5, anArray.Upper());
|
||||
}
|
||||
|
||||
TEST_F(NCollection_Array1Test, ConstructorWithNegativeBounds)
|
||||
TEST(NCollection_Array1Test, ConstructorWithNegativeBounds)
|
||||
{
|
||||
// Test constructor with negative bounds
|
||||
NCollection_Array1<Standard_Integer> anArray(-3, 2);
|
||||
@ -55,7 +46,7 @@ TEST_F(NCollection_Array1Test, ConstructorWithNegativeBounds)
|
||||
EXPECT_EQ(2, anArray.Upper());
|
||||
}
|
||||
|
||||
TEST_F(NCollection_Array1Test, AssignmentValue)
|
||||
TEST(NCollection_Array1Test, AssignmentValue)
|
||||
{
|
||||
NCollection_Array1<Standard_Integer> anArray(1, 5);
|
||||
|
||||
@ -78,7 +69,7 @@ TEST_F(NCollection_Array1Test, AssignmentValue)
|
||||
}
|
||||
}
|
||||
|
||||
TEST_F(NCollection_Array1Test, CopyConstructor)
|
||||
TEST(NCollection_Array1Test, CopyConstructor)
|
||||
{
|
||||
NCollection_Array1<Standard_Integer> anArray1(1, 5);
|
||||
|
||||
@ -106,7 +97,7 @@ TEST_F(NCollection_Array1Test, CopyConstructor)
|
||||
EXPECT_NE(anArray1(3), anArray2(3));
|
||||
}
|
||||
|
||||
TEST_F(NCollection_Array1Test, ValueAccess)
|
||||
TEST(NCollection_Array1Test, ValueAccess)
|
||||
{
|
||||
NCollection_Array1<Standard_Integer> anArray(1, 5);
|
||||
|
||||
@ -124,7 +115,7 @@ TEST_F(NCollection_Array1Test, ValueAccess)
|
||||
}
|
||||
}
|
||||
|
||||
TEST_F(NCollection_Array1Test, ChangeValueAccess)
|
||||
TEST(NCollection_Array1Test, ChangeValueAccess)
|
||||
{
|
||||
NCollection_Array1<Standard_Integer> anArray(1, 5);
|
||||
|
||||
@ -153,7 +144,7 @@ TEST_F(NCollection_Array1Test, ChangeValueAccess)
|
||||
}
|
||||
}
|
||||
|
||||
TEST_F(NCollection_Array1Test, AssignmentOperator)
|
||||
TEST(NCollection_Array1Test, AssignmentOperator)
|
||||
{
|
||||
NCollection_Array1<Standard_Integer> anArray1(1, 5);
|
||||
|
||||
@ -179,7 +170,7 @@ TEST_F(NCollection_Array1Test, AssignmentOperator)
|
||||
}
|
||||
}
|
||||
|
||||
TEST_F(NCollection_Array1Test, Move)
|
||||
TEST(NCollection_Array1Test, Move)
|
||||
{
|
||||
NCollection_Array1<Standard_Integer> anArray1(1, 5);
|
||||
|
||||
@ -199,15 +190,12 @@ TEST_F(NCollection_Array1Test, Move)
|
||||
EXPECT_EQ(1, anArray2.Lower());
|
||||
EXPECT_EQ(5, anArray2.Upper());
|
||||
|
||||
// Original array is keep referecing the same data
|
||||
EXPECT_EQ(anArray1.Lower(), anArray2.Lower());
|
||||
EXPECT_EQ(anArray1.Upper(), anArray2.Upper());
|
||||
EXPECT_EQ(anArray1(1), anArray2(1));
|
||||
EXPECT_EQ(anArray1(2), anArray2(2));
|
||||
EXPECT_EQ(5, anArray1.Length());
|
||||
// Original array is not keep referecing the same data
|
||||
EXPECT_EQ(anArray1.Length(), 0);
|
||||
EXPECT_EQ(anArray1.Lower(), 1);
|
||||
}
|
||||
|
||||
TEST_F(NCollection_Array1Test, Init)
|
||||
TEST(NCollection_Array1Test, Init)
|
||||
{
|
||||
NCollection_Array1<Standard_Integer> anArray(1, 5);
|
||||
|
||||
@ -221,7 +209,7 @@ TEST_F(NCollection_Array1Test, Init)
|
||||
}
|
||||
}
|
||||
|
||||
TEST_F(NCollection_Array1Test, SetValue)
|
||||
TEST(NCollection_Array1Test, SetValue)
|
||||
{
|
||||
NCollection_Array1<Standard_Integer> anArray(1, 5);
|
||||
|
||||
@ -232,7 +220,7 @@ TEST_F(NCollection_Array1Test, SetValue)
|
||||
EXPECT_EQ(123, anArray(3));
|
||||
}
|
||||
|
||||
TEST_F(NCollection_Array1Test, FirstLast)
|
||||
TEST(NCollection_Array1Test, FirstLast)
|
||||
{
|
||||
NCollection_Array1<Standard_Integer> anArray(5, 10);
|
||||
|
||||
@ -251,7 +239,7 @@ TEST_F(NCollection_Array1Test, FirstLast)
|
||||
EXPECT_EQ(10101, anArray.Last());
|
||||
}
|
||||
|
||||
TEST_F(NCollection_Array1Test, STLIteration)
|
||||
TEST(NCollection_Array1Test, STLIteration)
|
||||
{
|
||||
NCollection_Array1<Standard_Integer> anArray(1, 5);
|
||||
for (Standard_Integer i = anArray.Lower(); i <= anArray.Upper(); i++)
|
||||
@ -268,7 +256,7 @@ TEST_F(NCollection_Array1Test, STLIteration)
|
||||
}
|
||||
}
|
||||
|
||||
TEST_F(NCollection_Array1Test, Resize)
|
||||
TEST(NCollection_Array1Test, Resize)
|
||||
{
|
||||
NCollection_Array1<Standard_Integer> anArray(1, 5);
|
||||
for (Standard_Integer i = anArray.Lower(); i <= anArray.Upper(); i++)
|
||||
@ -311,7 +299,7 @@ TEST_F(NCollection_Array1Test, Resize)
|
||||
}
|
||||
}
|
||||
|
||||
TEST_F(NCollection_Array1Test, ChangeValue)
|
||||
TEST(NCollection_Array1Test, ChangeValue)
|
||||
{
|
||||
NCollection_Array1<Standard_Integer> anArray(1, 5);
|
||||
anArray.Init(42);
|
||||
@ -329,7 +317,7 @@ TEST_F(NCollection_Array1Test, ChangeValue)
|
||||
EXPECT_EQ(42, anArray(5));
|
||||
}
|
||||
|
||||
TEST_F(NCollection_Array1Test, IteratorAccess)
|
||||
TEST(NCollection_Array1Test, IteratorAccess)
|
||||
{
|
||||
NCollection_Array1<Standard_Integer> anArray(1, 5);
|
||||
for (Standard_Integer i = 1; i <= 5; i++)
|
||||
|
321
src/FoundationClasses/TKernel/GTests/NCollection_Array2_Test.cxx
Normal file
321
src/FoundationClasses/TKernel/GTests/NCollection_Array2_Test.cxx
Normal file
@ -0,0 +1,321 @@
|
||||
// Copyright (c) 2025 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 <NCollection_Array2.hxx>
|
||||
#include <Standard_Integer.hxx>
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
// --- Constructor Tests ---
|
||||
|
||||
TEST(NCollection_Array2Test, DefaultConstructor)
|
||||
{
|
||||
NCollection_Array2<Standard_Integer> anArray;
|
||||
EXPECT_EQ(0, anArray.Length());
|
||||
EXPECT_EQ(0, anArray.NbRows());
|
||||
EXPECT_EQ(0, anArray.NbColumns());
|
||||
}
|
||||
|
||||
TEST(NCollection_Array2Test, ConstructorWithBounds)
|
||||
{
|
||||
NCollection_Array2<Standard_Integer> anArray(1, 5, 1, 10);
|
||||
EXPECT_EQ(50, anArray.Length());
|
||||
EXPECT_EQ(5, anArray.NbRows());
|
||||
EXPECT_EQ(10, anArray.NbColumns());
|
||||
EXPECT_EQ(1, anArray.LowerRow());
|
||||
EXPECT_EQ(5, anArray.UpperRow());
|
||||
EXPECT_EQ(1, anArray.LowerCol());
|
||||
EXPECT_EQ(10, anArray.UpperCol());
|
||||
}
|
||||
|
||||
TEST(NCollection_Array2Test, ConstructorWithNegativeBounds)
|
||||
{
|
||||
NCollection_Array2<Standard_Integer> anArray(-2, 2, -5, 5); // 5 rows, 11 cols
|
||||
EXPECT_EQ(55, anArray.Length());
|
||||
EXPECT_EQ(5, anArray.NbRows());
|
||||
EXPECT_EQ(11, anArray.NbColumns());
|
||||
EXPECT_EQ(-2, anArray.LowerRow());
|
||||
EXPECT_EQ(2, anArray.UpperRow());
|
||||
EXPECT_EQ(-5, anArray.LowerCol());
|
||||
EXPECT_EQ(5, anArray.UpperCol());
|
||||
}
|
||||
|
||||
// --- Data Access and Manipulation ---
|
||||
|
||||
TEST(NCollection_Array2Test, ValueAccess)
|
||||
{
|
||||
NCollection_Array2<Standard_Integer> anArray(1, 3, 1, 4);
|
||||
for (Standard_Integer aRowIter = anArray.LowerRow(); aRowIter <= anArray.UpperRow(); ++aRowIter)
|
||||
{
|
||||
for (Standard_Integer aColIter = anArray.LowerCol(); aColIter <= anArray.UpperCol(); ++aColIter)
|
||||
{
|
||||
anArray.SetValue(aRowIter, aColIter, aRowIter * 100 + aColIter);
|
||||
}
|
||||
}
|
||||
|
||||
for (Standard_Integer aRowIter = anArray.LowerRow(); aRowIter <= anArray.UpperRow(); ++aRowIter)
|
||||
{
|
||||
for (Standard_Integer aColIter = anArray.LowerCol(); aColIter <= anArray.UpperCol(); ++aColIter)
|
||||
{
|
||||
EXPECT_EQ(aRowIter * 100 + aColIter, anArray.Value(aRowIter, aColIter));
|
||||
EXPECT_EQ(aRowIter * 100 + aColIter, anArray(aRowIter, aColIter)); // Using operator()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
TEST(NCollection_Array2Test, ChangeValueAccess)
|
||||
{
|
||||
NCollection_Array2<Standard_Integer> anArray(0, 2, 0, 3);
|
||||
for (Standard_Integer aRowIter = anArray.LowerRow(); aRowIter <= anArray.UpperRow(); ++aRowIter)
|
||||
{
|
||||
for (Standard_Integer aColIter = anArray.LowerCol(); aColIter <= anArray.UpperCol(); ++aColIter)
|
||||
{
|
||||
anArray.ChangeValue(aRowIter, aColIter) = aRowIter * 100 + aColIter;
|
||||
}
|
||||
}
|
||||
|
||||
// Verify initial values
|
||||
EXPECT_EQ(102, anArray(1, 2));
|
||||
|
||||
// Modify a value
|
||||
anArray.ChangeValue(1, 2) = 999;
|
||||
EXPECT_EQ(999, anArray(1, 2));
|
||||
}
|
||||
|
||||
TEST(NCollection_Array2Test, Init)
|
||||
{
|
||||
NCollection_Array2<Standard_Integer> anArray(1, 5, 1, 5);
|
||||
anArray.Init(42);
|
||||
for (Standard_Integer aRowIter = anArray.LowerRow(); aRowIter <= anArray.UpperRow(); ++aRowIter)
|
||||
{
|
||||
for (Standard_Integer aColIter = anArray.LowerCol(); aColIter <= anArray.UpperCol(); ++aColIter)
|
||||
{
|
||||
EXPECT_EQ(42, anArray(aRowIter, aColIter));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// --- Copy and Move Semantics ---
|
||||
|
||||
TEST(NCollection_Array2Test, CopyConstructor)
|
||||
{
|
||||
NCollection_Array2<Standard_Integer> anArray1(1, 3, 1, 4);
|
||||
anArray1.Init(123);
|
||||
|
||||
NCollection_Array2<Standard_Integer> anArray2(anArray1);
|
||||
|
||||
// Verify dimensions and data are copied
|
||||
EXPECT_EQ(anArray1.Length(), anArray2.Length());
|
||||
EXPECT_EQ(anArray1.NbRows(), anArray2.NbRows());
|
||||
EXPECT_EQ(anArray1.NbColumns(), anArray2.NbColumns());
|
||||
EXPECT_EQ(anArray1(2, 3), anArray2(2, 3));
|
||||
|
||||
// Modify original to ensure it was a deep copy
|
||||
anArray1.SetValue(2, 3, 999);
|
||||
EXPECT_EQ(123, anArray2(2, 3));
|
||||
EXPECT_NE(anArray1(2, 3), anArray2(2, 3));
|
||||
}
|
||||
|
||||
TEST(NCollection_Array2Test, AssignmentOperator)
|
||||
{
|
||||
NCollection_Array2<Standard_Integer> anArray1(1, 3, 1, 4);
|
||||
anArray1.Init(123);
|
||||
|
||||
NCollection_Array2<Standard_Integer> anArray2(1, 3, 1, 4);
|
||||
anArray2.Init(0);
|
||||
|
||||
anArray2 = anArray1; // Assign
|
||||
|
||||
// Verify data is copied
|
||||
EXPECT_EQ(123, anArray2(2, 3));
|
||||
|
||||
// Modify original to ensure it was a deep copy
|
||||
anArray1.SetValue(2, 3, 999);
|
||||
EXPECT_EQ(123, anArray2(2, 3));
|
||||
}
|
||||
|
||||
TEST(NCollection_Array2Test, MoveConstructor)
|
||||
{
|
||||
NCollection_Array2<Standard_Integer> anArray1(1, 5, 1, 10);
|
||||
anArray1.SetValue(3, 7, 123);
|
||||
|
||||
// Move construct
|
||||
NCollection_Array2<Standard_Integer> anArray2(std::move(anArray1));
|
||||
|
||||
// Verify new array has the data and dimensions
|
||||
EXPECT_EQ(50, anArray2.Length());
|
||||
EXPECT_EQ(5, anArray2.NbRows());
|
||||
EXPECT_EQ(10, anArray2.NbColumns());
|
||||
EXPECT_EQ(1, anArray2.LowerRow());
|
||||
EXPECT_EQ(10, anArray2.UpperCol());
|
||||
EXPECT_EQ(123, anArray2(3, 7));
|
||||
|
||||
// Verify the moved-from array is empty
|
||||
EXPECT_EQ(0, anArray1.Length());
|
||||
EXPECT_EQ(0, anArray1.NbRows());
|
||||
}
|
||||
|
||||
TEST(NCollection_Array2Test, MoveAssignment)
|
||||
{
|
||||
NCollection_Array2<Standard_Integer> anArray1(1, 5, 1, 10);
|
||||
anArray1.SetValue(3, 7, 123);
|
||||
|
||||
NCollection_Array2<Standard_Integer> anArray2;
|
||||
anArray2 = std::move(anArray1); // Move assignment
|
||||
|
||||
// Verify new array has the data and dimensions
|
||||
EXPECT_EQ(50, anArray2.Length());
|
||||
EXPECT_EQ(5, anArray2.NbRows());
|
||||
EXPECT_EQ(123, anArray2(3, 7));
|
||||
|
||||
// Verify the moved-from array is empty
|
||||
EXPECT_EQ(0, anArray1.Length());
|
||||
}
|
||||
|
||||
// --- Resizing and Re-indexing ---
|
||||
|
||||
TEST(NCollection_Array2Test, Resize)
|
||||
{
|
||||
NCollection_Array2<Standard_Integer> anArray(1, 4, 1, 5); // 4x5 array
|
||||
for (Standard_Integer aRowIter = 1; aRowIter <= 4; ++aRowIter)
|
||||
{
|
||||
for (Standard_Integer aColIter = 1; aColIter <= 5; ++aColIter)
|
||||
{
|
||||
anArray(aRowIter, aColIter) = aRowIter * 100 + aColIter;
|
||||
}
|
||||
}
|
||||
|
||||
// Resize to be larger, keeping data
|
||||
anArray.Resize(0, 5, 0, 6, Standard_True); // New size 6x7
|
||||
|
||||
// Verify new dimensions
|
||||
EXPECT_EQ(6, anArray.NbRows());
|
||||
EXPECT_EQ(7, anArray.NbColumns());
|
||||
EXPECT_EQ(0, anArray.LowerRow());
|
||||
EXPECT_EQ(6, anArray.UpperCol());
|
||||
|
||||
// Verify original data is preserved in the correct locations
|
||||
for (Standard_Integer aRowIter = 0; aRowIter <= 3; ++aRowIter)
|
||||
{
|
||||
for (Standard_Integer aColIter = 0; aColIter <= 4; ++aColIter)
|
||||
{
|
||||
EXPECT_EQ((aRowIter + 1) * 100 + (aColIter + 1), anArray(aRowIter, aColIter));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
TEST(NCollection_Array2Test, ReIndex_UpdateBounds)
|
||||
{
|
||||
NCollection_Array2<Standard_Integer> anArray(1, 5, 1, 10); // 5x10 array
|
||||
|
||||
// Test updating lower bounds
|
||||
anArray.UpdateLowerRow(0);
|
||||
anArray.UpdateLowerCol(0);
|
||||
EXPECT_EQ(0, anArray.LowerRow());
|
||||
EXPECT_EQ(4, anArray.UpperRow()); // 0 + 5 - 1
|
||||
EXPECT_EQ(0, anArray.LowerCol());
|
||||
EXPECT_EQ(9, anArray.UpperCol()); // 0 + 10 - 1
|
||||
EXPECT_EQ(5, anArray.NbRows()); // Size should not change
|
||||
EXPECT_EQ(10, anArray.NbColumns());
|
||||
|
||||
// Test updating upper bounds (which shifts the lower bounds)
|
||||
anArray.UpdateUpperRow(10); // Request upper row to be 10
|
||||
anArray.UpdateUpperCol(20); // Request upper col to be 20
|
||||
EXPECT_EQ(10, anArray.UpperRow());
|
||||
EXPECT_EQ(20, anArray.UpperCol());
|
||||
EXPECT_EQ(6, anArray.LowerRow()); // Lower is now 10 - 5 + 1
|
||||
EXPECT_EQ(11, anArray.LowerCol()); // Lower is now 20 - 10 + 1
|
||||
EXPECT_EQ(5, anArray.NbRows()); // Size should not change
|
||||
EXPECT_EQ(10, anArray.NbColumns());
|
||||
}
|
||||
|
||||
// --- Iteration ---
|
||||
|
||||
TEST(NCollection_Array2Test, STLIteration)
|
||||
{
|
||||
NCollection_Array2<Standard_Integer> anArray(1, 2, 1, 3); // 2x3 array
|
||||
for (Standard_Integer aRowIter = 1; aRowIter <= 2; ++aRowIter)
|
||||
{
|
||||
for (Standard_Integer aColIter = 1; aColIter <= 3; ++aColIter)
|
||||
{
|
||||
anArray(aRowIter, aColIter) = aRowIter * 10 + aColIter; // 11, 12, 13, 21, 22, 23
|
||||
}
|
||||
}
|
||||
|
||||
// Test range-based for loop
|
||||
std::vector<Standard_Integer> aExpectedValues = {11, 12, 13, 21, 22, 23};
|
||||
int anIndex = 0;
|
||||
for (const auto& aValue : anArray)
|
||||
{
|
||||
EXPECT_EQ(aExpectedValues[anIndex++], aValue);
|
||||
}
|
||||
EXPECT_EQ(6, anIndex); // Ensure all elements were visited
|
||||
}
|
||||
|
||||
TEST(NCollection_Array2Test, Resize_ChangeShapeSameSize)
|
||||
{
|
||||
// This test checks for data scrambling when resizing to a different shape
|
||||
// with the same total number of elements.
|
||||
NCollection_Array2<Standard_Integer> anArray(1, 4, 1, 6); // 4x6 = 24 elements
|
||||
Standard_Integer anExpectedValue = 0;
|
||||
for (Standard_Integer aRowIter = 1; aRowIter <= 4; ++aRowIter)
|
||||
{
|
||||
for (Standard_Integer aColIter = 1; aColIter <= 6; ++aColIter)
|
||||
{
|
||||
anArray(aRowIter, aColIter) = anExpectedValue++;
|
||||
}
|
||||
}
|
||||
|
||||
// Resize to 6x4 (24 elements), copying data
|
||||
anArray.Resize(1, 6, 1, 4, Standard_True);
|
||||
|
||||
// Verify new dimensions
|
||||
EXPECT_EQ(6, anArray.NbRows());
|
||||
EXPECT_EQ(4, anArray.NbColumns());
|
||||
EXPECT_EQ(24, anArray.Length());
|
||||
|
||||
// Verify the common 4x4 sub-matrix was not scrambled.
|
||||
// This will fail if the copy logic in Resize is incorrect.
|
||||
for (Standard_Integer anElemInd = anArray.Lower(); anElemInd < anArray.Lower() + 16; ++anElemInd)
|
||||
{
|
||||
EXPECT_EQ(anElemInd - anArray.Lower(),
|
||||
static_cast<NCollection_Array1<Standard_Integer>&>(anArray).Value(anElemInd));
|
||||
}
|
||||
}
|
||||
|
||||
TEST(NCollection_Array2Test, ReIndex_Interference)
|
||||
{
|
||||
// This test explicitly verifies that UpdateUpperRow modifies the LowerRow,
|
||||
// showing how the separate update methods can interfere with each other.
|
||||
NCollection_Array2<Standard_Integer> anArray(1, 10, 1, 1); // A 10x1 array
|
||||
const Standard_Integer anInitialNbRows = anArray.NbRows();
|
||||
|
||||
// 1. User sets a new lower bound.
|
||||
anArray.UpdateLowerRow(5);
|
||||
EXPECT_EQ(5, anArray.LowerRow());
|
||||
EXPECT_EQ(14, anArray.UpperRow()); // Upper bound is now 5 + 10 - 1
|
||||
|
||||
// 2. User then sets a new upper bound, expecting the lower bound to stay at 5.
|
||||
anArray.UpdateUpperRow(12);
|
||||
|
||||
// 3. Verify the final state.
|
||||
EXPECT_EQ(12, anArray.UpperRow()); // The upper bound is set as requested.
|
||||
|
||||
// Verify that the lower bound was changed to accommodate the new upper bound,
|
||||
// undoing the previous call to UpdateLowerRow.
|
||||
EXPECT_EQ(3, anArray.LowerRow()); // Lower bound is now 12 - 10 + 1 = 3
|
||||
EXPECT_NE(5, anArray.LowerRow()); // It is no longer 5.
|
||||
|
||||
// The total number of rows should never change during these operations.
|
||||
EXPECT_EQ(anInitialNbRows, anArray.NbRows());
|
||||
}
|
@ -171,7 +171,10 @@ public:
|
||||
myPointer(theOther.myPointer),
|
||||
myIsOwner(theOther.myIsOwner)
|
||||
{
|
||||
theOther.myIsOwner = false;
|
||||
theOther.myIsOwner = false;
|
||||
theOther.myPointer = nullptr;
|
||||
theOther.mySize = 0;
|
||||
theOther.myLowerBound = 1;
|
||||
}
|
||||
|
||||
virtual ~NCollection_Array1()
|
||||
@ -241,11 +244,14 @@ public:
|
||||
destroy(myPointer, 0, mySize);
|
||||
myAllocator.deallocate(myPointer, mySize);
|
||||
}
|
||||
myLowerBound = theOther.myLowerBound;
|
||||
mySize = theOther.mySize;
|
||||
myPointer = theOther.myPointer;
|
||||
myIsOwner = theOther.myIsOwner;
|
||||
theOther.myIsOwner = false;
|
||||
myLowerBound = theOther.myLowerBound;
|
||||
mySize = theOther.mySize;
|
||||
myPointer = theOther.myPointer;
|
||||
myIsOwner = theOther.myIsOwner;
|
||||
theOther.myIsOwner = false;
|
||||
theOther.myPointer = nullptr;
|
||||
theOther.mySize = 0;
|
||||
theOther.myLowerBound = 1;
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
@ -146,6 +146,10 @@ public:
|
||||
myLowerCol(theOther.LowerCol()),
|
||||
mySizeCol(theOther.NbColumns())
|
||||
{
|
||||
theOther.myLowerRow = 1;
|
||||
theOther.mySizeRow = 0;
|
||||
theOther.myLowerCol = 1;
|
||||
theOther.mySizeCol = 0;
|
||||
}
|
||||
|
||||
//! C array-based constructor
|
||||
@ -195,6 +199,24 @@ public:
|
||||
//! UpperCol
|
||||
Standard_Integer UpperCol() const { return myLowerCol + static_cast<int>(mySizeCol) - 1; }
|
||||
|
||||
//! Updates lower row
|
||||
void UpdateLowerRow(const Standard_Integer theLowerRow) { myLowerRow = theLowerRow; }
|
||||
|
||||
//! Updates lower column
|
||||
void UpdateLowerCol(const Standard_Integer theLowerCol) { myLowerCol = theLowerCol; }
|
||||
|
||||
//! Updates upper row
|
||||
void UpdateUpperRow(const Standard_Integer theUpperRow)
|
||||
{
|
||||
myLowerRow = myLowerRow - UpperRow() + theUpperRow;
|
||||
}
|
||||
|
||||
//! Updates upper column
|
||||
void UpdateUpperCol(const Standard_Integer theUpperCol)
|
||||
{
|
||||
myLowerCol = myLowerCol - UpperCol() + theUpperCol;
|
||||
}
|
||||
|
||||
//! Assignment
|
||||
NCollection_Array2& Assign(const NCollection_Array2& theOther)
|
||||
{
|
||||
@ -203,6 +225,7 @@ public:
|
||||
return *this;
|
||||
}
|
||||
NCollection_Array1<TheItemType>::Assign(theOther);
|
||||
// Current implementation disable changing bounds by assigning
|
||||
return *this;
|
||||
}
|
||||
|
||||
@ -216,10 +239,14 @@ public:
|
||||
return *this;
|
||||
}
|
||||
NCollection_Array1<TheItemType>::Move(theOther);
|
||||
myLowerRow = theOther.myLowerRow;
|
||||
mySizeRow = theOther.mySizeRow;
|
||||
myLowerCol = theOther.myLowerCol;
|
||||
mySizeCol = theOther.mySizeCol;
|
||||
myLowerRow = theOther.myLowerRow;
|
||||
mySizeRow = theOther.mySizeRow;
|
||||
myLowerCol = theOther.myLowerCol;
|
||||
mySizeCol = theOther.mySizeCol;
|
||||
theOther.myLowerRow = 1;
|
||||
theOther.mySizeRow = 0;
|
||||
theOther.myLowerCol = 1;
|
||||
theOther.mySizeCol = 0;
|
||||
return *this;
|
||||
}
|
||||
|
||||
@ -296,31 +323,34 @@ public:
|
||||
{
|
||||
Standard_RangeError_Raise_if(theRowUpper < theRowLower || theColUpper < theColLower,
|
||||
"NCollection_Array2::Resize");
|
||||
myLowerRow = theRowLower;
|
||||
myLowerCol = theColLower;
|
||||
if (!theToCopyData)
|
||||
{
|
||||
NCollection_Array1<TheItemType>::Resize(
|
||||
BeginPosition(theRowLower, theRowUpper, theColLower, theColUpper),
|
||||
LastPosition(theRowLower, theRowUpper, theColLower, theColUpper),
|
||||
false);
|
||||
mySizeRow = theRowUpper - theRowLower + 1;
|
||||
mySizeCol = theColUpper - theColLower + 1;
|
||||
mySizeRow = theRowUpper - theRowLower + 1;
|
||||
mySizeCol = theColUpper - theColLower + 1;
|
||||
myLowerRow = theRowLower;
|
||||
myLowerCol = theColLower;
|
||||
return;
|
||||
}
|
||||
NCollection_Array1<TheItemType> aTmpMovedCopy(std::move(*this));
|
||||
const size_t aNewNbRows = theRowUpper - theRowLower + 1;
|
||||
const size_t aNewNbCols = theColUpper - theColLower + 1;
|
||||
const size_t aNbRowsToCopy = std::min<size_t>(mySizeRow, aNewNbRows);
|
||||
const size_t aNbColsToCopy = std::min<size_t>(mySizeCol, aNewNbCols);
|
||||
|
||||
NCollection_Array2<TheItemType> aTmpMovedCopy(std::move(*this));
|
||||
TheItemType* anOldPointer = &aTmpMovedCopy.ChangeFirst();
|
||||
NCollection_Array1<TheItemType>::Resize(
|
||||
BeginPosition(theRowLower, theRowUpper, theColLower, theColUpper),
|
||||
LastPosition(theRowLower, theRowUpper, theColLower, theColUpper),
|
||||
false);
|
||||
const size_t aNewNbRows = theRowUpper - theRowLower + 1;
|
||||
const size_t aNewNbCols = theColUpper - theColLower + 1;
|
||||
const size_t aNbRowsToCopy = std::min<size_t>(mySizeRow, aNewNbRows);
|
||||
const size_t aNbColsToCopy = std::min<size_t>(mySizeCol, aNewNbCols);
|
||||
mySizeRow = aNewNbRows;
|
||||
mySizeCol = aNewNbCols;
|
||||
size_t aOldInter = 0;
|
||||
mySizeRow = aNewNbRows;
|
||||
mySizeCol = aNewNbCols;
|
||||
myLowerRow = theRowLower;
|
||||
myLowerCol = theColLower;
|
||||
size_t aOldInter = 0;
|
||||
for (size_t aRowIter = 0; aRowIter < aNbRowsToCopy; ++aRowIter)
|
||||
{
|
||||
for (size_t aColIter = 0; aColIter < aNbColsToCopy; ++aColIter)
|
||||
|
Loading…
x
Reference in New Issue
Block a user