Skip to content

Commit

Permalink
tests: initial dense tensor unit tests (#164)
Browse files Browse the repository at this point in the history
- Added tests for constructors, add, sub, uminus, smul.
- Iterator test is work in progress with TODO where value needs to be checked. Need to confirm correct API here with Sam.
- Remaining tests are placeholder TEST_Fs to wrap before PR.
- tensor_fixture.h methods extended. `generic_tensor` replaced with more meaningful `make_ones_tensor`. Complementary functions `make_ns_tensor` used in new tests as LAL was only checking values where all coefficients were 1, but new tests check broader values. `make_tensor` takes a generic function for initialising each coefficient.
- `test_free_tensor` and `test_lie` updated with new fixture.
  • Loading branch information
alexallmont committed Dec 10, 2024
1 parent 6d24755 commit 2f32c0e
Show file tree
Hide file tree
Showing 6 changed files with 499 additions and 75 deletions.
5 changes: 4 additions & 1 deletion algebra/src/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,11 @@ add_subdirectory(libalgebra_lite_internal)
if (ROUGHPY_BUILD_TESTS)

add_executable(test_algebra
test_lie.cpp
tensor_fixture.cpp
tensor_fixture.h
test_dense_tensor.cpp
test_free_tensor.cpp
test_lie.cpp
)

target_link_libraries(test_algebra PRIVATE RoughPy::Algebra GTest::gtest)
Expand Down
48 changes: 48 additions & 0 deletions algebra/src/tensor_fixture.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
// Copyright (c) 2024 RoughPy Developers. All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
// 1. Redistributions of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer.
//
// 2. Redistributions in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation
// and/or other materials provided with the distribution.
//
// 3. Neither the name of the copyright holder nor the names of its contributors
// may be used to endorse or promote products derived from this software without
// specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGE.

#include "tensor_fixture.h"

namespace rpy {
namespace algebra {
namespace testing {

void TensorFixture::SetUp()
{
auto rational_poly_tpo = scalars::ScalarType::of<devices::rational_poly_scalar>();
if (!rational_poly_tpo) {
GTEST_FAIL();
}

rational_poly_tp = *rational_poly_tpo;
context = rpy::algebra::get_context(width, depth, rational_poly_tp);
}

} // namespace testing
} // namespace algebra
} // namespace rpy
117 changes: 117 additions & 0 deletions algebra/src/tensor_fixture.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,117 @@
// Copyright (c) 2024 RoughPy Developers. All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
// 1. Redistributions of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer.
//
// 2. Redistributions in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation
// and/or other materials provided with the distribution.
//
// 3. Neither the name of the copyright holder nor the names of its contributors
// may be used to endorse or promote products derived from this software without
// specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGE.

#ifndef ROUGHPY_ALGEBRA_SRC_TENSOR_FIXTURE_H
#define ROUGHPY_ALGEBRA_SRC_TENSOR_FIXTURE_H

#include <gtest/gtest.h>

#include "roughpy/core/ranges.h"
#include "roughpy/core/types.h"
#include "roughpy/algebra/context.h"
#include "roughpy/scalars/scalar_types.h"

namespace rpy {
namespace algebra {
namespace testing {

//! FIXME docs
//!
class TensorFixture : public ::testing::Test
{
protected:
const deg_t width = 2;
const deg_t depth = 5;
const scalars::ScalarType* rational_poly_tp;
rpy::algebra::context_pointer context;

protected:
void SetUp() override;

public:
//! Create free tensor with all coeffs 1 of width and depth and given char
RPY_NO_DISCARD FreeTensor make_ones_tensor(
char indeterminate_char
) const
{
FreeTensor result = make_tensor([indeterminate_char](size_t i) {
auto key = scalars::indeterminate_type(indeterminate_char, i);
auto coeff = scalars::rational_poly_scalar(key, scalars::rational_scalar_type(1));
return coeff;
});
return result;
}

//! Create free tensor with all coeffs N of width and depth and given char
RPY_NO_DISCARD FreeTensor make_ns_tensor(
char indeterminate_char,
scalars::rational_scalar_type n
) const
{
FreeTensor result = make_tensor([indeterminate_char, n](size_t i) {
auto key = scalars::indeterminate_type(indeterminate_char, i);
auto coeff = scalars::rational_poly_scalar(key, n);
return coeff;
});
return result;
}

//! Create free tensor with each coeff constructed from make_coeff_fn
//! defaulting to default tensor data size. Lambda signature is:
//! make_coeff_fn(size_t index) -> scalars::rational_poly_scalar
template <typename MakeCoeffFn>
RPY_NO_DISCARD FreeTensor make_tensor(
MakeCoeffFn&& make_coeff_fn
) const
{
using namespace rpy::scalars;

// Construct and allocate a rational polynomial
VectorConstructionData cons_data{
KeyScalarArray(rational_poly_tp),
VectorType::Dense
};
const dimn_t size = context->tensor_size(depth);
cons_data.data.allocate_scalars(size);

// Delegate the construction of each basis with coefficient
auto slice = cons_data.data.as_mut_slice<rational_poly_scalar>();
for (auto&& [i, coeff] : views::enumerate(slice)) {
coeff = make_coeff_fn(i);
}

FreeTensor result = context->construct_free_tensor(cons_data);
return result;
}
};

} // namespace testing
} // namespace algebra
} // namespace rpy

#endif // ROUGHPY_ALGEBRA_SRC_TENSOR_FIXTURE_H
Loading

0 comments on commit 2f32c0e

Please sign in to comment.