Skip to content

Commit 69be136

Browse files
Attempt at computing spectral norm using eigenvalues. Requires comparison operators and static cast to double, not possible for Bparser
1 parent b44c9d7 commit 69be136

File tree

3 files changed

+60
-6
lines changed

3 files changed

+60
-6
lines changed

include/array.hh

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1257,11 +1257,17 @@ public:
12571257
case 2: //matrix
12581258
{
12591259
//Spectral norm
1260-
Throw() << "norm2(matrix) not yet implemented" << "\n";
1261-
Shape s; //empty Shape for scalar
1260+
Throw() << "norm2(matrix) is not yet possible" << "\n";
1261+
/*Shape s; //empty Shape for scalar
12621262
Array r(s);
1263-
//r.elements_[0U] = *wrap_array(a);
1264-
return r;
1263+
1264+
Eigen::MatrixX<details::ScalarWrapper> m( wrap_array(a) );
1265+
1266+
r.elements_[0U] = *details::sqrt((m.adjoint()*m).eigenvalues().real().maxCoeff());
1267+
//computing eigenvalues would require static cast to double and comparison operators (<,<=,>,>=,!=,==)
1268+
//something which we cannot support
1269+
return r;*/
1270+
break;
12651271
}
12661272
default:
12671273
Throw() << "Norms are not avaiable for ND tensors" << "\n";

include/scalar_wrapper.hh

Lines changed: 49 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212

1313
#include "scalar_node.hh"
1414
#include <Eigen/Core>
15+
//#include <Eigen/Eigenvalues> //impossible
1516

1617
namespace bparser {
1718
namespace details {
@@ -23,6 +24,10 @@ namespace bparser {
2324
ScalarWrapper(double d) : node(ScalarNode::create_const(d)) { ; }
2425
ScalarWrapper(ScalarNodePtr existing_ptr) : node(existing_ptr) { ; }
2526

27+
inline ScalarWrapper operator+() const {
28+
return ScalarWrapper(*this);
29+
}
30+
2631
inline ScalarWrapper operator-() const {
2732
return un_op<_minus_>(*this);
2833
}
@@ -36,14 +41,29 @@ namespace bparser {
3641
return bin_op<_add_>(*this, b);
3742
}
3843

44+
inline ScalarWrapper& operator-=(const ScalarWrapper& b) {
45+
node = bin_op<_sub_>(*this, b).get();
46+
return *this;
47+
}
48+
3949
inline ScalarWrapper operator-(const ScalarWrapper& b) const {
4050
return bin_op<_sub_>(*this, b);
4151
}
4252

53+
inline ScalarWrapper& operator*=(const ScalarWrapper& b) {
54+
node = bin_op<_mul_>(*this, b).get();
55+
return *this;
56+
}
57+
4358
inline ScalarWrapper operator*(const ScalarWrapper& b) const {
4459
return bin_op<_mul_>(*this, b);
4560
}
4661

62+
inline ScalarWrapper& operator/=(const ScalarWrapper& b) {
63+
node = bin_op<_div_>(*this, b).get();
64+
return *this;
65+
}
66+
4767
inline ScalarWrapper operator/(const ScalarWrapper& b) const {
4868
return bin_op<_div_>(*this, b);
4969
}
@@ -53,6 +73,34 @@ namespace bparser {
5373
return *(***this).values_ == *(**b).values_;
5474
return false;
5575
}
76+
/* These do not make any sense with what we are trying to achieve
77+
inline bool operator!=(const ScalarWrapper& b) const {
78+
return !((*this) == b);
79+
}
80+
81+
inline bool operator<(const ScalarWrapper& b) const {
82+
if ((*this).is_constant() && (*this).have_same_result_storage(b))
83+
return *(***this).values_ < *(**b).values_;
84+
return false;
85+
}
86+
87+
inline bool operator<=(const ScalarWrapper& b) const {
88+
if ((*this).is_constant() && (*this).have_same_result_storage(b))
89+
return *(***this).values_ <= *(**b).values_;
90+
return false;
91+
}
92+
93+
inline bool operator>=(const ScalarWrapper& b) const {
94+
if ((*this).is_constant() && (*this).have_same_result_storage(b))
95+
return *(***this).values_ >= *(**b).values_;
96+
return false;
97+
}
98+
99+
inline bool operator>(const ScalarWrapper& b) const {
100+
if ((*this).is_constant() && (*this).have_same_result_storage(b))
101+
return *(***this).values_ > *(**b).values_;
102+
return false;
103+
}*/
56104

57105

58106
inline ScalarNodePtr operator*() const { //dereference
@@ -111,7 +159,7 @@ namespace bparser {
111159
inline ScalarWrapper abs2(const ScalarWrapper& s) {
112160
return s*s;
113161
}
114-
162+
115163

116164
UN_OP(sqrt)
117165
//UN_OP(exp)

test/test_parser.cc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -264,7 +264,7 @@ void test_expression() {
264264
BP_ASSERT(test_expr("norm1([-4,-3,-2,-1,0,1,2,3,4])", {20}, {}));
265265
BP_ASSERT(test_expr("norm1([[-4,-3,-2],[-1,0,1],[2,3,4]])", { 7 }, {}));
266266
BP_ASSERT(test_expr("norm2([-4,-3,-2,-1,0,1,2,3,4])", { 7.745966692414834 }, {}));
267-
//BP_ASSERT(test_expr("norm2([[-4,-3,-2],[-1,0,1],[2,3,4]])", { 7.3484692283495345 }, {}));
267+
//BP_ASSERT(test_expr("norm2([[-4,-3,-2],[-1,0,1],[2,3,4]])", { 7.3484692283495345 }, {})); //Spectral norm uses eigenvalues/singular values. Eigen uses comparison operators in the algorithm. Bparser does not like that
268268
BP_ASSERT(test_expr("normfro([[-4,-3,-2],[-1,0,1],[2,3,4]])", { 7.745966692414834 }, {}));
269269
BP_ASSERT(test_expr("norminf([-4,-3,-2,-1,0,1,2,3,4])", { 4 }, {}));
270270
BP_ASSERT(test_expr("norminf([[-4,-3,-2],[-1,0,1],[2,3,4]])", { 9 }, {}));

0 commit comments

Comments
 (0)