Skip to content

Commit

Permalink
Support EQ and NE for array and struct
Browse files Browse the repository at this point in the history
  • Loading branch information
mx990 committed Mar 22, 2024
1 parent f916f46 commit c808a83
Show file tree
Hide file tree
Showing 6 changed files with 105 additions and 22 deletions.
17 changes: 0 additions & 17 deletions src/core/datatypes/forte_array.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -40,23 +40,6 @@ void CIEC_ARRAY::setValue(const CIEC_ANY &paValue) {
}
}

bool CIEC_ARRAY::equals(const CIEC_ANY &paOther) const {
if (paOther.getDataTypeID() == CIEC_ANY::e_ARRAY) {
auto &otherArray = static_cast<const CIEC_ARRAY &>(paOther);
if (getLowerBound() != otherArray.getLowerBound() || getUpperBound() != otherArray.getUpperBound()) {
return false;
}

for (intmax_t i = getLowerBound(), end = getUpperBound(); i <= end; ++i) {
if (!operator[](i).equals(otherArray[i])) {
return false;
}
}
return true;
}
return false;
}

int CIEC_ARRAY::toString(char *paValue, size_t paBufferSize) const {
int nBytesUsed = -1;

Expand Down
26 changes: 24 additions & 2 deletions src/core/datatypes/forte_array.h
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,24 @@
/** \brief A common supertype for all CIEC_ARRAY variants, providing the minimal interface an array must provide
*/
class CIEC_ARRAY : public CIEC_ANY_DERIVED {
public:
friend bool operator==(const CIEC_ARRAY &paLeft, const CIEC_ARRAY &paRight) {
if (paLeft.getLowerBound() != paRight.getLowerBound() || paLeft.getUpperBound() != paRight.getUpperBound()) {
return false;
}

for (intmax_t i = paLeft.getLowerBound(), end = paLeft.getUpperBound(); i <= end; ++i) {
if (!paLeft[i].equals(paRight[i])) {
return false;
}
}
return true;
}

friend bool operator!=(const CIEC_ARRAY &paLeft, const CIEC_ARRAY &paRight) {
return !(paLeft == paRight);
}

public:
using value_type = CIEC_ANY;
using pointer = value_type *;
using const_pointer = const value_type *;
Expand Down Expand Up @@ -93,7 +110,12 @@ class CIEC_ARRAY : public CIEC_ANY_DERIVED {

void setValue(const CIEC_ANY &paValue) override;

[[nodiscard]] bool equals(const CIEC_ANY &paOther) const override;
[[nodiscard]] bool equals(const CIEC_ANY &paOther) const override {
if (paOther.getDataTypeID() == CIEC_ANY::e_ARRAY) {
return *this == static_cast<const CIEC_ARRAY &>(paOther);
}
return false;
}

[[nodiscard]] int toString(char *paValue, size_t paBufferSize) const override;

Expand Down
19 changes: 18 additions & 1 deletion src/core/datatypes/forte_array_common.h
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,24 @@
*/
template<typename T>
class CIEC_ARRAY_COMMON : public CIEC_ARRAY {
public:
friend bool operator==(const CIEC_ARRAY_COMMON &paLeft, const CIEC_ARRAY_COMMON &paRight) {
if (paLeft.getLowerBound() != paRight.getLowerBound() || paLeft.getUpperBound() != paRight.getUpperBound()) {
return false;
}

for (intmax_t i = paLeft.getLowerBound(), end = paLeft.getUpperBound(); i <= end; ++i) {
if (!func_EQ(paLeft[i], paRight[i])) {
return false;
}
}
return true;
}

friend bool operator!=(const CIEC_ARRAY_COMMON &paLeft, const CIEC_ARRAY_COMMON &paRight) {
return !(paLeft == paRight);
}

public:
using value_type = T;
using pointer = value_type *;
using const_pointer = const value_type *;
Expand Down
10 changes: 10 additions & 0 deletions src/core/datatypes/forte_struct.h
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,16 @@
#include "forte_any_derived.h"

class CIEC_STRUCT : public CIEC_ANY_DERIVED{
template <typename T, std::enable_if_t<std::is_base_of_v<CIEC_STRUCT, T>, int> = 0>
friend bool operator==(const T &paLeft, const T &paRight) {
return paLeft.equals(paRight);
}

template <typename T, std::enable_if_t<std::is_base_of_v<CIEC_STRUCT, T>, int> = 0>
friend bool operator!=(const T &paLeft, const T &paRight) {
return !(paLeft == paRight);
}

public:
//! Indicator for invalid array member index positions
static constexpr size_t csmNIndex = -1;
Expand Down
8 changes: 6 additions & 2 deletions src/core/iec61131_functions.h
Original file line number Diff line number Diff line change
Expand Up @@ -425,7 +425,9 @@ CIEC_BOOL func_EQ(const T &paIn1, const U &paIn2, const Args& ... args) {

template<typename T, typename U>
CIEC_BOOL func_EQ(const T &paIN1, const U &paIN2) {
if constexpr (forte::core::mpl::are_of_subtype_v<CIEC_ANY_BIT, T, U>) { //ANY_BITs can be also partial accesses
if constexpr (forte::core::mpl::has_equality_v<T, U>) {
return CIEC_BOOL(paIN1 == paIN2);
} else if constexpr (forte::core::mpl::are_of_subtype_v<CIEC_ANY_BIT, T, U>) { //ANY_BITs can be also partial accesses
using tTClass = typename forte::core::mpl::get_equivalent_CIEC_class_t<T>;
using tUClass = typename forte::core::mpl::get_equivalent_CIEC_class_t<U>;
using tImplicitCastType = typename forte::core::mpl::get_castable_type_t<tTClass, tUClass>;
Expand Down Expand Up @@ -539,7 +541,9 @@ CIEC_BOOL func_LT(const T &paIN1, const T &paIN2) {

template<typename T, typename U>
CIEC_BOOL func_NE(const T &paIN1, const U &paIN2) {
if constexpr (forte::core::mpl::are_of_subtype_v<CIEC_ANY_BIT, T, U>) { //ANY_BITs can be also partial accesses
if constexpr (forte::core::mpl::has_equality_v<T, U>) {
return CIEC_BOOL(paIN1 != paIN2);
} else if constexpr (forte::core::mpl::are_of_subtype_v<CIEC_ANY_BIT, T, U>) { //ANY_BITs can be also partial accesses
using tTClass = typename forte::core::mpl::get_equivalent_CIEC_class_t<T>;
using tUClass = typename forte::core::mpl::get_equivalent_CIEC_class_t<U>;
using tImplicitCastType = typename forte::core::mpl::get_castable_type_t<tTClass, tUClass>;
Expand Down
47 changes: 47 additions & 0 deletions tests/core/iec61131_functionstests.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,9 @@ class CIEC_EndianessTestStruct : public CIEC_STRUCT {

CIEC_EndianessTestStruct() = default;

CIEC_EndianessTestStruct(CIEC_BOOL paVar1, CIEC_DINT paVar2, CIEC_LWORD paVar3)
: Var1(paVar1), Var2(paVar2), Var3(paVar3) {}

size_t getStructSize() const override {
return 3;
}
Expand Down Expand Up @@ -438,6 +441,28 @@ BOOST_AUTO_TEST_CASE(eq_false_variadic_4)
BOOST_TEST(func_EQ(number1, number2, number3, number4) == false);
}

BOOST_AUTO_TEST_CASE(eq_array_fixed)
{
CIEC_ARRAY_FIXED<CIEC_INT, 0, 1> array1 = {17_INT, 4_INT};
CIEC_ARRAY_FIXED<CIEC_INT, 0, 1> array2 = {17_INT, 4_INT};
CIEC_ARRAY_FIXED<CIEC_INT, 0, 1> array3 = {21_INT, 42_INT};
CIEC_ARRAY_FIXED<CIEC_INT, 0, 2> array4 = {17_INT, 4_INT, 21_INT};
CIEC_ARRAY_FIXED<CIEC_DINT, 0, 1> array5 = {17_DINT, 4_DINT};
BOOST_TEST(func_EQ(array1, array2) == true);
BOOST_TEST(func_EQ(array1, array3) == false);
BOOST_TEST(func_EQ(array1, array4) == false);
BOOST_TEST(func_EQ(array1, array5) == false);
}

BOOST_AUTO_TEST_CASE(eq_struct)
{
CIEC_EndianessTestStruct struct1(true_BOOL, 17_DINT, 4_LWORD);
CIEC_EndianessTestStruct struct2(true_BOOL, 17_DINT, 4_LWORD);
CIEC_EndianessTestStruct struct3(true_BOOL, 21_DINT, 42_LWORD);
BOOST_TEST(func_EQ(struct1, struct2) == true);
BOOST_TEST(func_EQ(struct1, struct3) == false);
}

BOOST_AUTO_TEST_CASE(gt_true) {
BOOST_TEST(func_GT(100_SINT, 90_INT) == true);
}
Expand Down Expand Up @@ -580,6 +605,28 @@ BOOST_AUTO_TEST_CASE(ne_false_mixed_types)
BOOST_TEST(func_NE(nLint1, nInt2) == true);
}

BOOST_AUTO_TEST_CASE(ne_array_fixed)
{
CIEC_ARRAY_FIXED<CIEC_INT, 0, 1> array1 = {17_INT, 4_INT};
CIEC_ARRAY_FIXED<CIEC_INT, 0, 1> array2 = {17_INT, 4_INT};
CIEC_ARRAY_FIXED<CIEC_INT, 0, 1> array3 = {21_INT, 42_INT};
CIEC_ARRAY_FIXED<CIEC_INT, 0, 2> array4 = {17_INT, 4_INT, 21_INT};
CIEC_ARRAY_FIXED<CIEC_DINT, 0, 1> array5 = {17_DINT, 4_DINT};
BOOST_TEST(func_NE(array1, array2) == false);
BOOST_TEST(func_NE(array1, array3) == true);
BOOST_TEST(func_NE(array1, array4) == true);
BOOST_TEST(func_NE(array1, array5) == true);
}

BOOST_AUTO_TEST_CASE(ne_struct)
{
CIEC_EndianessTestStruct struct1(true_BOOL, 17_DINT, 4_LWORD);
CIEC_EndianessTestStruct struct2(true_BOOL, 17_DINT, 4_LWORD);
CIEC_EndianessTestStruct struct3(true_BOOL, 21_DINT, 42_LWORD);
BOOST_TEST(func_NE(struct1, struct2) == false);
BOOST_TEST(func_NE(struct1, struct3) == true);
}

BOOST_AUTO_TEST_CASE(implicit_bool_casts)
{
bool bSame = std::is_same<CIEC_BOOL, forte::core::mpl::implicit_cast<CIEC_BOOL, CIEC_BOOL>::type>::value;
Expand Down

0 comments on commit c808a83

Please sign in to comment.