[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[lmi-commits] [lmi] master 14ee3ed 5/5: Add and test some useful reducti
From: |
Greg Chicares |
Subject: |
[lmi-commits] [lmi] master 14ee3ed 5/5: Add and test some useful reductions |
Date: |
Sun, 21 Mar 2021 21:10:53 -0400 (EDT) |
branch: master
commit 14ee3ed571facdc3f14aa7c31edde0c9e07b7625
Author: Gregory W. Chicares <gchicares@sbcglobal.net>
Commit: Gregory W. Chicares <gchicares@sbcglobal.net>
Add and test some useful reductions
---
et_vector.hpp | 74 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
et_vector_test.cpp | 49 ++++++++++++++++++++++++++++++++++++
2 files changed, 123 insertions(+)
diff --git a/et_vector.hpp b/et_vector.hpp
index cd4db2f..c6c501d 100644
--- a/et_vector.hpp
+++ b/et_vector.hpp
@@ -48,6 +48,8 @@
#include "et_vector_redirect.hpp"
#include "ssize_lmi.hpp"
+#include <algorithm> // max(), min()
+#include <cmath> // INFINITY
#include <sstream>
#include <stdexcept>
#include <vector>
@@ -204,4 +206,76 @@ inline std::vector<T>& operator<<=(std::vector<T>& t,
Expression<X> const& x)
return t = Eval(x);
}
+/// AND-reduction, like APL's "and slash". (Short-circuiting.)
+
+template<typename X>
+inline bool AllOf(Expression<X> const& x)
+{
+ for(int i = 0, n = Rho(x); i < n; ++i)
+ {
+ if(!forEach(x, EvalLeaf1(i), OpCombine())) {return false;}
+ }
+ return true;
+}
+
+/// OR-reduction, like APL's "or slash". (Short-circuiting.)
+
+template<typename X>
+inline bool AnyOf(Expression<X> const& x)
+{
+ for(int i = 0, n = Rho(x); i < n; ++i)
+ {
+ if(forEach(x, EvalLeaf1(i), OpCombine())) {return true;}
+ }
+ return false;
+}
+
+template<typename X>
+inline auto SumOf(Expression<X> const& x)
+{
+ using Deduced = decltype(forEach(x, EvalLeaf1(0), OpCombine()));
+ Deduced z(0);
+ for(int i = 0, n = Rho(x); i < n; ++i)
+ {
+ z += forEach(x, EvalLeaf1(i), OpCombine());
+ }
+ return z;
+}
+
+template<typename X>
+inline auto ProductOf(Expression<X> const& x)
+{
+ using Deduced = decltype(forEach(x, EvalLeaf1(0), OpCombine()));
+ Deduced z(1);
+ for(int i = 0, n = Rho(x); i < n; ++i)
+ {
+ z *= forEach(x, EvalLeaf1(i), OpCombine());
+ }
+ return z;
+}
+
+template<typename X>
+inline auto MaxOf(Expression<X> const& x)
+{
+ using Deduced = decltype(forEach(x, EvalLeaf1(0), OpCombine()));
+ Deduced z(-INFINITY);
+ for(int i = 0, n = Rho(x); i < n; ++i)
+ {
+ z = std::max(z, forEach(x, EvalLeaf1(i), OpCombine()));
+ }
+ return z;
+}
+
+template<typename X>
+inline auto MinOf(Expression<X> const& x)
+{
+ using Deduced = decltype(forEach(x, EvalLeaf1(0), OpCombine()));
+ Deduced z(INFINITY);
+ for(int i = 0, n = Rho(x); i < n; ++i)
+ {
+ z = std::min(z, forEach(x, EvalLeaf1(i), OpCombine()));
+ }
+ return z;
+}
+
#endif // et_vector_hpp
diff --git a/et_vector_test.cpp b/et_vector_test.cpp
index 881ca3d..71815f0 100644
--- a/et_vector_test.cpp
+++ b/et_vector_test.cpp
@@ -151,5 +151,54 @@ int test_main(int, char*[])
LMI_TEST(r2 == v4);
}
+ // Test reductions.
+ //
+ // Unary '+' is not defined for std::vector, but it is for PETE
+ // expressions, so '+v' converts a std::vector 'v' into a PETE
+ // expression.
+ {
+ std::vector<double> v0 = { 0.0, 0.0, 0.0};
+ std::vector<double> v1 = { 0.0, 1.0, 0.0};
+ std::vector<double> v2 = { 1.0, 1.0, 1.0};
+ std::vector<double> v3 = {-1.0, 0.0, 6.5};
+ std::vector<double> v4 = {-1.0, 4.0, 6.5};
+
+ LMI_TEST(false == AllOf(+v0));
+ LMI_TEST(false == AllOf(+v1));
+ LMI_TEST(true == AllOf(+v2));
+ LMI_TEST(false == AllOf(+v3));
+ LMI_TEST(true == AllOf(+v4));
+
+ LMI_TEST(false == AnyOf(+v0));
+ LMI_TEST(true == AnyOf(+v1));
+ LMI_TEST(true == AnyOf(+v2));
+ LMI_TEST(true == AnyOf(+v3));
+ LMI_TEST(true == AnyOf(+v4));
+
+ LMI_TEST_EQUAL( 0.0, SumOf(+v0));
+ LMI_TEST_EQUAL( 1.0, SumOf(+v1));
+ LMI_TEST_EQUAL( 3.0, SumOf(+v2));
+ LMI_TEST_EQUAL( 5.5, SumOf(+v3));
+ LMI_TEST_EQUAL( 9.5, SumOf(+v4));
+
+ LMI_TEST_EQUAL( 0.0, ProductOf(+v0));
+ LMI_TEST_EQUAL( 0.0, ProductOf(+v1));
+ LMI_TEST_EQUAL( 1.0, ProductOf(+v2));
+ LMI_TEST_EQUAL( 0.0, ProductOf(+v3));
+ LMI_TEST_EQUAL(-26.0, ProductOf(+v4));
+
+ LMI_TEST_EQUAL( 0.0, MaxOf(+v0));
+ LMI_TEST_EQUAL( 1.0, MaxOf(+v1));
+ LMI_TEST_EQUAL( 1.0, MaxOf(+v2));
+ LMI_TEST_EQUAL( 6.5, MaxOf(+v3));
+ LMI_TEST_EQUAL( 6.5, MaxOf(+v4));
+
+ LMI_TEST_EQUAL( 0.0, MinOf(+v0));
+ LMI_TEST_EQUAL( 0.0, MinOf(+v1));
+ LMI_TEST_EQUAL( 1.0, MinOf(+v2));
+ LMI_TEST_EQUAL(-1.0, MinOf(+v3));
+ LMI_TEST_EQUAL(-1.0, MinOf(+v4));
+ }
+
return 0;
}