Started work on factor.h/cpp unit tests
authorJoris Mooij <joris.mooij@tuebingen.mpg.de>
Thu, 1 Apr 2010 08:09:26 +0000 (10:09 +0200)
committerJoris Mooij <joris.mooij@tuebingen.mpg.de>
Thu, 1 Apr 2010 08:09:26 +0000 (10:09 +0200)
Makefile
tests/unit/factor.cpp [new file with mode: 0644]

index 7fc5f8c..36a5788 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -122,7 +122,7 @@ examples : examples/example$(EE) examples/example_bipgraph$(EE) examples/example
 
 matlabs : matlab/dai$(ME) matlab/dai_readfg$(ME) matlab/dai_writefg$(ME) matlab/dai_potstrength$(ME)
 
-unittests : tests/unit/var$(EE) tests/unit/smallset$(EE) tests/unit/varset$(EE) tests/unit/graph$(EE) tests/unit/bipgraph$(EE) tests/unit/weightedgraph$(EE) tests/unit/enum$(EE) tests/unit/enum$(EE) tests/unit/util$(EE) tests/unit/properties$(EE) tests/unit/index$(EE) tests/unit/prob$(EE)
+unittests : tests/unit/var$(EE) tests/unit/smallset$(EE) tests/unit/varset$(EE) tests/unit/graph$(EE) tests/unit/bipgraph$(EE) tests/unit/weightedgraph$(EE) tests/unit/enum$(EE) tests/unit/enum$(EE) tests/unit/util$(EE) tests/unit/properties$(EE) tests/unit/index$(EE) tests/unit/prob$(EE) tests/unit/factor$(EE)
        echo Running unit tests...
        tests/unit/var$(EE)
        tests/unit/smallset$(EE)
@@ -135,6 +135,7 @@ unittests : tests/unit/var$(EE) tests/unit/smallset$(EE) tests/unit/varset$(EE)
        tests/unit/properties$(EE)
        tests/unit/index$(EE)
        tests/unit/prob$(EE)
+       tests/unit/factor$(EE)
 
 tests : tests/testdai$(EE) tests/testem/testem$(EE) tests/testbbp$(EE) $(unittests)
 
@@ -218,6 +219,8 @@ tests/unit/index$(EE) : tests/unit/index.cpp $(HEADERS) $(LIB)/libdai$(LE)
        $(CC) $(CCO)$@ $< $(LIBS) $(BOOSTLIBS_UTF)
 tests/unit/prob$(EE) : tests/unit/prob.cpp $(HEADERS) $(LIB)/libdai$(LE)
        $(CC) $(CCO)$@ $< $(LIBS) $(BOOSTLIBS_UTF)
+tests/unit/factor$(EE) : tests/unit/factor.cpp $(HEADERS) $(LIB)/libdai$(LE)
+       $(CC) $(CCO)$@ $< $(LIBS) $(BOOSTLIBS_UTF)
 
 
 # TESTS
@@ -324,7 +327,7 @@ clean :
        -rm matlab/*$(ME)
        -rm examples/example$(EE) examples/example_bipgraph$(EE) examples/example_varset$(EE) examples/example_permute$(EE) examples/example_sprinkler$(EE) examples/example_sprinkler_gibbs$(EE) examples/example_sprinkler_em$(EE)
        -rm tests/testdai$(EE) tests/testem/testem$(EE) tests/testbbp$(EE)
-       -rm tests/unit/var$(EE) tests/unit/smallset$(EE) tests/unit/varset$(EE) tests/unit/graph$(EE) tests/unit/bipgraph$(EE) tests/unit/weightedgraph$(EE) tests/unit/enum$(EE) tests/unit/util$(EE) tests/unit/properties$(EE) tests/unit/index$(EE) tests/unit/prob$(EE)
+       -rm tests/unit/var$(EE) tests/unit/smallset$(EE) tests/unit/varset$(EE) tests/unit/graph$(EE) tests/unit/bipgraph$(EE) tests/unit/weightedgraph$(EE) tests/unit/enum$(EE) tests/unit/util$(EE) tests/unit/properties$(EE) tests/unit/index$(EE) tests/unit/prob$(EE) tests/unit/factor$(EE)
        -rm utils/fg2dot$(EE) utils/createfg$(EE) utils/fginfo$(EE)
        -rm -R doc
        -rm -R lib
@@ -362,6 +365,7 @@ clean :
        -del tests\unit\properties$(EE)
        -del tests\unit\index$(EE)
        -del tests\unit\prob$(EE)
+       -del tests\unit\factor$(EE)
        -del $(LIB)\libdai$(LE)
        -rmdir lib
 endif
diff --git a/tests/unit/factor.cpp b/tests/unit/factor.cpp
new file mode 100644 (file)
index 0000000..79c61a0
--- /dev/null
@@ -0,0 +1,757 @@
+/*  This file is part of libDAI - http://www.libdai.org/
+ *
+ *  libDAI is licensed under the terms of the GNU General Public License version
+ *  2, or (at your option) any later version. libDAI is distributed without any
+ *  warranty. See the file COPYING for more details.
+ *
+ *  Copyright (C) 2010  Joris Mooij      [joris dot mooij at libdai dot org]
+ */
+
+
+#define BOOST_TEST_DYN_LINK
+
+
+#include <dai/factor.h>
+#include <strstream>
+
+
+using namespace dai;
+
+
+const double tol = 1e-8;
+
+
+#define BOOST_TEST_MODULE FactorTest
+
+
+#include <boost/test/unit_test.hpp>
+#include <boost/test/floating_point_comparison.hpp>
+
+
+BOOST_AUTO_TEST_CASE( ConstructorsTest ) {
+    // check constructors
+    Factor x1;
+/*    BOOST_CHECK_EQUAL( x1.states(), 0 );
+    BOOST_CHECK( x1.p() == std::vector<Real>() );
+
+    Factor x2( 3 );
+    BOOST_CHECK_EQUAL( x2.states(), 3 );
+    BOOST_CHECK( x2.p() == std::vector<Real>( 3, 1.0 / 3.0 ) );
+    BOOST_CHECK_EQUAL( x2[0], 1.0 / 3.0 );
+    BOOST_CHECK_EQUAL( x2[1], 1.0 / 3.0 );
+    BOOST_CHECK_EQUAL( x2[2], 1.0 / 3.0 );
+
+    Factor x3( 4, 1.0 );
+    BOOST_CHECK_EQUAL( x3.states(), 4 );
+    BOOST_CHECK( x3.p() == std::vector<Real>( 4, 1.0 ) );
+    BOOST_CHECK_EQUAL( x3[0], 1.0 );
+    BOOST_CHECK_EQUAL( x3[1], 1.0 );
+    BOOST_CHECK_EQUAL( x3[2], 1.0 );
+    BOOST_CHECK_EQUAL( x3[3], 1.0 );
+    x3.set( 0, 0.5 );
+    x3.set( 1, 1.0 );
+    x3.set( 2, 2.0 );
+    x3.set( 3, 4.0 );
+
+    Factor x4( x3.begin(), x3.end() );
+    BOOST_CHECK_EQUAL( x4.states(), 4 );
+    BOOST_CHECK( x4.p() == x3.p() );
+    BOOST_CHECK_EQUAL( x4[0], 0.5 );
+    BOOST_CHECK_EQUAL( x4[1], 1.0 );
+    BOOST_CHECK_EQUAL( x4[2], 2.0 );
+    BOOST_CHECK_EQUAL( x4[3], 4.0 );
+
+    x3.p() = std::vector<Real>( 4, 2.5 );
+    Factor x5( x3.begin(), x3.end(), x3.states() );
+    BOOST_CHECK_EQUAL( x5.states(), 4 );
+    BOOST_CHECK( x5.p() == x3.p() );
+    BOOST_CHECK_EQUAL( x5[0], 2.5 );
+    BOOST_CHECK_EQUAL( x5[1], 2.5 );
+    BOOST_CHECK_EQUAL( x5[2], 2.5 );
+    BOOST_CHECK_EQUAL( x5[3], 2.5 );
+
+    std::vector<int> y( 3, 2 );
+    Factor x6( y );
+    BOOST_CHECK_EQUAL( x6.states(), 3 );
+    BOOST_CHECK( x6.p() == std::vector<Real>( 3, 2.0 ) );
+    BOOST_CHECK_EQUAL( x6[0], 2.0 );
+    BOOST_CHECK_EQUAL( x6[1], 2.0 );
+    BOOST_CHECK_EQUAL( x6[2], 2.0 );
+
+    Factor x7( x6 );
+    BOOST_CHECK( x7 == x6 );
+    
+    Factor x8 = x6;
+    BOOST_CHECK( x8 == x6 );*/
+}
+
+/*
+
+BOOST_AUTO_TEST_CASE( IteratorTest ) {
+    Prob x( 5, 0.0 );
+    size_t i;
+    for( i = 0; i < x.size(); i++ )
+        x.set( i, i );
+
+    i = 0;
+    for( Prob::const_iterator cit = x.begin(); cit != x.end(); cit++, i++ )
+        BOOST_CHECK_EQUAL( *cit, i );
+    
+    i = 0;
+    for( Prob::iterator it = x.begin(); it != x.end(); it++, i++ )
+        *it = 4 - i;
+    
+    i = 0;
+    for( Prob::const_iterator it = x.begin(); it != x.end(); it++, i++ )
+        BOOST_CHECK_EQUAL( *it, 4 - i );
+
+    i = 0;
+    for( Prob::const_reverse_iterator crit = x.rbegin(); crit != x.rend(); crit++, i++ )
+        BOOST_CHECK_EQUAL( *crit, i );
+
+    i = 0;
+    for( Prob::reverse_iterator rit = x.rbegin(); rit != x.rend(); rit++, i++ )
+        *rit = 2 * i;
+    
+    i = 0;
+    for( Prob::const_reverse_iterator crit = x.rbegin(); crit != x.rend(); crit++, i++ )
+        BOOST_CHECK_EQUAL( *crit, 2 * i );
+}
+
+
+BOOST_AUTO_TEST_CASE( QueriesTest ) {
+    Prob x( 5, 0.0 );
+    for( size_t i = 0; i < x.size(); i++ )
+        x.set( i, 2.0 - i );
+
+    // test accumulate, min, max, sum, sumAbs, maxAbs
+    BOOST_CHECK_EQUAL( x.sum(), 0.0 );
+    BOOST_CHECK_EQUAL( x.accumulate( 0.0, std::plus<Real>(), fo_id<Real>() ), 0.0 );
+    BOOST_CHECK_EQUAL( x.accumulate( 1.0, std::plus<Real>(), fo_id<Real>() ), 1.0 );
+    BOOST_CHECK_EQUAL( x.accumulate( -1.0, std::plus<Real>(), fo_id<Real>() ), -1.0 );
+    BOOST_CHECK_EQUAL( x.max(), 2.0 );
+    BOOST_CHECK_EQUAL( x.accumulate( -INFINITY, fo_max<Real>(), fo_id<Real>() ), 2.0 );
+    BOOST_CHECK_EQUAL( x.accumulate( 3.0, fo_max<Real>(), fo_id<Real>() ), 3.0 );
+    BOOST_CHECK_EQUAL( x.accumulate( -5.0, fo_max<Real>(), fo_id<Real>() ), 2.0 );
+    BOOST_CHECK_EQUAL( x.min(), -2.0 );
+    BOOST_CHECK_EQUAL( x.accumulate( INFINITY, fo_min<Real>(), fo_id<Real>() ), -2.0 );
+    BOOST_CHECK_EQUAL( x.accumulate( -3.0, fo_min<Real>(), fo_id<Real>() ), -3.0 );
+    BOOST_CHECK_EQUAL( x.accumulate( 5.0, fo_min<Real>(), fo_id<Real>() ), -2.0 );
+    BOOST_CHECK_EQUAL( x.sumAbs(), 6.0 );
+    BOOST_CHECK_EQUAL( x.accumulate( 0.0, std::plus<Real>(), fo_abs<Real>() ), 6.0 );
+    BOOST_CHECK_EQUAL( x.accumulate( 1.0, std::plus<Real>(), fo_abs<Real>() ), 7.0 );
+    BOOST_CHECK_EQUAL( x.accumulate( -1.0, std::plus<Real>(), fo_abs<Real>() ), 7.0 );
+    BOOST_CHECK_EQUAL( x.maxAbs(), 2.0 );
+    BOOST_CHECK_EQUAL( x.accumulate( 0.0, fo_max<Real>(), fo_abs<Real>() ), 2.0 );
+    BOOST_CHECK_EQUAL( x.accumulate( 1.0, fo_max<Real>(), fo_abs<Real>() ), 2.0 );
+    BOOST_CHECK_EQUAL( x.accumulate( -1.0, fo_max<Real>(), fo_abs<Real>() ), 2.0 );
+    BOOST_CHECK_EQUAL( x.accumulate( 3.0, fo_max<Real>(), fo_abs<Real>() ), 3.0 );
+    BOOST_CHECK_EQUAL( x.accumulate( -3.0, fo_max<Real>(), fo_abs<Real>() ), 3.0 );
+    x.set( 1, 1.0 );
+    BOOST_CHECK_EQUAL( x.maxAbs(), 2.0 );
+    BOOST_CHECK_EQUAL( x.accumulate( 0.0, fo_max<Real>(), fo_abs<Real>() ), 2.0 );
+    BOOST_CHECK_EQUAL( x.accumulate( 1.0, fo_max<Real>(), fo_abs<Real>() ), 2.0 );
+    BOOST_CHECK_EQUAL( x.accumulate( -1.0, fo_max<Real>(), fo_abs<Real>() ), 2.0 );
+    BOOST_CHECK_EQUAL( x.accumulate( 3.0, fo_max<Real>(), fo_abs<Real>() ), 3.0 );
+    BOOST_CHECK_EQUAL( x.accumulate( -3.0, fo_max<Real>(), fo_abs<Real>() ), 3.0 );
+    for( size_t i = 0; i < x.size(); i++ )
+        x.set( i, i ? (1.0 / i) : 0.0 );
+    BOOST_CHECK_EQUAL( x.accumulate( 0.0, std::plus<Real>(), fo_inv0<Real>() ), 10.0 );
+    x /= x.sum();
+
+    // test entropy
+    BOOST_CHECK( x.entropy() < Prob(5).entropy() );
+    for( size_t i = 1; i < 100; i++ )
+        BOOST_CHECK_CLOSE( Prob(i).entropy(), std::log(i), tol );
+
+    // test hasNaNs and hasNegatives
+    BOOST_CHECK( !Prob( 3, 0.0 ).hasNaNs() );
+    Real c = 0.0;
+    BOOST_CHECK( Prob( 3, c / c ).hasNaNs() );
+    BOOST_CHECK( !Prob( 3, 0.0 ).hasNegatives() );
+    BOOST_CHECK( !Prob( 3, 1.0 ).hasNegatives() );
+    BOOST_CHECK( Prob( 3, -1.0 ).hasNegatives() );
+    x.set( 0, 0.0 ); x.set( 1, 0.0 ); x.set( 2, -1.0 ); x.set( 3, 1.0 ); x.set( 4, 100.0 );
+    BOOST_CHECK( x.hasNegatives() );
+    x.set( 2, -INFINITY );
+    BOOST_CHECK( x.hasNegatives() );
+    x.set( 2, INFINITY );
+    BOOST_CHECK( !x.hasNegatives() );
+    x.set( 2, -1.0 );
+
+    // test argmax
+    BOOST_CHECK( x.argmax() == std::make_pair( (size_t)4, (Real)100.0 ) );
+    x.set( 4, 0.5 );
+    BOOST_CHECK( x.argmax() == std::make_pair( (size_t)3, (Real)1.0 ) );
+    x.set( 3, -2.0 );
+    BOOST_CHECK( x.argmax() == std::make_pair( (size_t)4, (Real)0.5 ) );
+    x.set( 4, -1.0 );
+    BOOST_CHECK( x.argmax() == std::make_pair( (size_t)0, (Real)0.0 ) );
+    x.set( 0, -2.0 );
+    BOOST_CHECK( x.argmax() == std::make_pair( (size_t)1, (Real)0.0 ) );
+    x.set( 1, -3.0 );
+    BOOST_CHECK( x.argmax() == std::make_pair( (size_t)2, (Real)-1.0 ) );
+    x.set( 2, -2.0 );
+    BOOST_CHECK( x.argmax() == std::make_pair( (size_t)4, (Real)-1.0 ) );
+
+    // test draw
+    for( size_t i = 0; i < x.size(); i++ )
+        x.set( i, i ? (1.0 / i) : 0.0 );
+    for( size_t repeat = 0; repeat < 10000; repeat++ ) {
+        BOOST_CHECK( x.draw() < x.size() );
+        BOOST_CHECK( x.draw() != 0 );
+    }
+    x.set( 2, 0.0 );
+    for( size_t repeat = 0; repeat < 10000; repeat++ ) {
+        BOOST_CHECK( x.draw() < x.size() );
+        BOOST_CHECK( x.draw() != 0 );
+        BOOST_CHECK( x.draw() != 2 );
+    }
+    x.set( 4, 0.0 );
+    for( size_t repeat = 0; repeat < 10000; repeat++ ) {
+        BOOST_CHECK( x.draw() < x.size() );
+        BOOST_CHECK( x.draw() != 0 );
+        BOOST_CHECK( x.draw() != 2 );
+        BOOST_CHECK( x.draw() != 4 );
+    }
+    x.set( 1, 0.0 );
+    for( size_t repeat = 0; repeat < 10000; repeat++ )
+        BOOST_CHECK( x.draw() == 3 );
+
+    // test <, ==
+    Prob a(3, 1.0), b(3, 1.0);
+    BOOST_CHECK( !(a < b) );
+    BOOST_CHECK( !(b < a) );
+    BOOST_CHECK( a == b );
+    a.set( 0, 0.0 );
+    BOOST_CHECK( a < b );
+    BOOST_CHECK( !(b < a) );
+    BOOST_CHECK( !(a == b) );
+    b.set( 2, 0.0 );
+    BOOST_CHECK( a < b );
+    BOOST_CHECK( !(b < a) );
+    BOOST_CHECK( !(a == b) );
+    b.set( 0, 0.0 );
+    BOOST_CHECK( !(a < b) );
+    BOOST_CHECK( b < a );
+    BOOST_CHECK( !(a == b) );
+    a.set( 1, 0.0 );
+    BOOST_CHECK( a < b );
+    BOOST_CHECK( !(b < a) );
+    BOOST_CHECK( !(a == b) );
+    b.set( 1, 0.0 );
+    BOOST_CHECK( !(a < b) );
+    BOOST_CHECK( b < a );
+    BOOST_CHECK( !(a == b) );
+    a.set( 2, 0.0 );
+    BOOST_CHECK( !(a < b) );
+    BOOST_CHECK( !(b < a) );
+    BOOST_CHECK( a == b );
+}
+
+
+BOOST_AUTO_TEST_CASE( UnaryTransformationsTest ) {
+    Prob x( 3 );
+    x.set( 0, -2.0 );
+    x.set( 1, 0.0 );
+    x.set( 2, 2.0 );
+
+    Prob y = -x;
+    Prob z = x.pwUnaryTr( std::negate<Real>() );
+    BOOST_CHECK_EQUAL( y[0], 2.0 );
+    BOOST_CHECK_EQUAL( y[1], 0.0 );
+    BOOST_CHECK_EQUAL( y[2], -2.0 );
+    BOOST_CHECK( y == z );
+
+    y = x.abs();
+    z = x.pwUnaryTr( fo_abs<Real>() );
+    BOOST_CHECK_EQUAL( y[0], 2.0 );
+    BOOST_CHECK_EQUAL( y[1], 0.0 );
+    BOOST_CHECK_EQUAL( y[2], 2.0 );
+    BOOST_CHECK( y == z );
+
+    y = x.exp();
+    z = x.pwUnaryTr( fo_exp<Real>() );
+    BOOST_CHECK_CLOSE( y[0], std::exp(-2.0), tol );
+    BOOST_CHECK_EQUAL( y[1], 1.0 );
+    BOOST_CHECK_CLOSE( y[2], 1.0 / y[0], tol );
+    BOOST_CHECK( y == z );
+
+    y = x.log(false);
+    z = x.pwUnaryTr( fo_log<Real>() );
+    BOOST_CHECK( isnan( y[0] ) );
+    BOOST_CHECK_EQUAL( y[1], -INFINITY );
+    BOOST_CHECK_CLOSE( y[2], std::log(2.0), tol );
+    BOOST_CHECK( !(y == z) );
+    y.set( 0, 0.0 );
+    z.set( 0, 0.0 );
+    BOOST_CHECK( y == z );
+
+    y = x.log(true);
+    z = x.pwUnaryTr( fo_log0<Real>() );
+    BOOST_CHECK( isnan( y[0] ) );
+    BOOST_CHECK_EQUAL( y[1], 0.0 );
+    BOOST_CHECK_EQUAL( y[2], std::log(2.0) );
+    BOOST_CHECK( !(y == z) );
+    y.set( 0, 0.0 );
+    z.set( 0, 0.0 );
+    BOOST_CHECK( y == z );
+
+    y = x.inverse(false);
+    z = x.pwUnaryTr( fo_inv<Real>() );
+    BOOST_CHECK_EQUAL( y[0], -0.5 );
+    BOOST_CHECK_EQUAL( y[1], INFINITY );
+    BOOST_CHECK_EQUAL( y[2], 0.5 );
+    BOOST_CHECK( y == z );
+
+    y = x.inverse(true);
+    z = x.pwUnaryTr( fo_inv0<Real>() );
+    BOOST_CHECK_EQUAL( y[0], -0.5 );
+    BOOST_CHECK_EQUAL( y[1], 0.0 );
+    BOOST_CHECK_EQUAL( y[2], 0.5 );
+    BOOST_CHECK( y == z );
+
+    x.set( 0, 2.0 );
+    y = x.normalized();
+    BOOST_CHECK_EQUAL( y[0], 0.5 );
+    BOOST_CHECK_EQUAL( y[1], 0.0 );
+    BOOST_CHECK_EQUAL( y[2], 0.5 );
+
+    y = x.normalized( Prob::NORMPROB );
+    BOOST_CHECK_EQUAL( y[0], 0.5 );
+    BOOST_CHECK_EQUAL( y[1], 0.0 );
+    BOOST_CHECK_EQUAL( y[2], 0.5 );
+
+    x.set( 0, -2.0 );
+    y = x.normalized( Prob::NORMLINF );
+    BOOST_CHECK_EQUAL( y[0], -1.0 );
+    BOOST_CHECK_EQUAL( y[1], 0.0 );
+    BOOST_CHECK_EQUAL( y[2], 1.0 );
+}
+
+
+BOOST_AUTO_TEST_CASE( UnaryOperationsTest ) {
+    Prob xorg(3);
+    xorg.set( 0, 2.0 );
+    xorg.set( 1, 0.0 );
+    xorg.set( 2, 1.0 );
+    Prob y(3);
+
+    Prob x = xorg;
+    BOOST_CHECK( x.setUniform() == Prob(3) );
+    BOOST_CHECK( x == Prob(3) );
+
+    y.set( 0, std::exp(2.0) );
+    y.set( 1, 1.0 );
+    y.set( 2, std::exp(1.0) );
+    x = xorg;
+    BOOST_CHECK( x.takeExp() == y );
+    BOOST_CHECK( x == y );
+    x = xorg;
+    BOOST_CHECK( x.pwUnaryOp( fo_exp<Real>() ) == y );
+    BOOST_CHECK( x == y );
+
+    y.set( 0, std::log(2.0) );
+    y.set( 1, -INFINITY );
+    y.set( 2, 0.0 );
+    x = xorg;
+    BOOST_CHECK( x.takeLog() == y );
+    BOOST_CHECK( x == y );
+    x = xorg;
+    BOOST_CHECK( x.takeLog(false) == y );
+    BOOST_CHECK( x == y );
+    x = xorg;
+    BOOST_CHECK( x.pwUnaryOp( fo_log<Real>() ) == y );
+    BOOST_CHECK( x == y );
+
+    y.set( 1, 0.0 );
+    x = xorg;
+    BOOST_CHECK( x.takeLog(true) == y );
+    BOOST_CHECK( x == y );
+    x = xorg;
+    BOOST_CHECK( x.pwUnaryOp( fo_log0<Real>() ) == y );
+    BOOST_CHECK( x == y );
+
+    y.set( 0, 2.0 / 3.0 );
+    y.set( 1, 0.0 / 3.0 );
+    y.set( 2, 1.0 / 3.0 );
+    x = xorg;
+    BOOST_CHECK_EQUAL( x.normalize(), 3.0 );
+    BOOST_CHECK( x == y );
+
+    x = xorg;
+    BOOST_CHECK_EQUAL( x.normalize( Prob::NORMPROB ), 3.0 );
+    BOOST_CHECK( x == y );
+
+    y.set( 0, 2.0 / 2.0 );
+    y.set( 1, 0.0 / 2.0 );
+    y.set( 2, 1.0 / 2.0 );
+    x = xorg;
+    BOOST_CHECK_EQUAL( x.normalize( Prob::NORMLINF ), 2.0 );
+    BOOST_CHECK( x == y );
+
+    xorg.set( 0, -2.0 );
+    y.set( 0, 2.0 );
+    y.set( 1, 0.0 );
+    y.set( 2, 1.0 );
+    x = xorg;
+    BOOST_CHECK( x.takeAbs() == y );
+    BOOST_CHECK( x == y );
+
+    for( size_t repeat = 0; repeat < 10000; repeat++ ) {
+        x.randomize();
+        for( size_t i = 0; i < x.size(); i++ ) {
+            BOOST_CHECK( x[i] < 1.0 );
+            BOOST_CHECK( x[i] >= 0.0 );
+        }
+    }
+}
+
+
+BOOST_AUTO_TEST_CASE( ScalarTransformationsTest ) {
+    Prob x(3);
+    x.set( 0, 2.0 );
+    x.set( 1, 0.0 );
+    x.set( 2, 1.0 );
+    Prob y(3);
+
+    y.set( 0, 3.0 ); y.set( 1, 1.0 ); y.set( 2, 2.0 );
+    BOOST_CHECK( (x + 1.0) == y );
+    y.set( 0, 0.0 ); y.set( 1, -2.0 ); y.set( 2, -1.0 );
+    BOOST_CHECK( (x + (-2.0)) == y );
+
+    y.set( 0, 1.0 ); y.set( 1, -1.0 ); y.set( 2, 0.0 );
+    BOOST_CHECK( (x - 1.0) == y );
+    y.set( 0, 4.0 ); y.set( 1, 2.0 ); y.set( 2, 3.0 );
+    BOOST_CHECK( (x - (-2.0)) == y );
+
+    BOOST_CHECK( (x * 1.0) == x );
+    y.set( 0, 4.0 ); y.set( 1, 0.0 ); y.set( 2, 2.0 );
+    BOOST_CHECK( (x * 2.0) == y );
+    y.set( 0, -1.0 ); y.set( 1, 0.0 ); y.set( 2, -0.5 );
+    BOOST_CHECK( (x * -0.5) == y );
+
+    BOOST_CHECK( (x / 1.0) == x );
+    y.set( 0, 1.0 ); y.set( 1, 0.0 ); y.set( 2, 0.5 );
+    BOOST_CHECK( (x / 2.0) == y );
+    y.set( 0, -4.0 ); y.set( 1, 0.0 ); y.set( 2, -2.0 );
+    BOOST_CHECK( (x / -0.5) == y );
+    BOOST_CHECK( (x / 0.0) == Prob(3, 0.0) );
+
+    BOOST_CHECK( (x ^ 1.0) == x );
+    BOOST_CHECK( (x ^ 0.0) == Prob(3, 1.0) );
+    y.set( 0, 4.0 ); y.set( 1, 0.0 ); y.set( 2, 1.0 );
+    BOOST_CHECK( (x ^ 2.0) == y );
+    y.set( 0, 1.0 / std::sqrt(2.0) ); y.set( 1, INFINITY ); y.set( 2, 1.0 );
+    Prob z = (x ^ -0.5);
+    BOOST_CHECK_CLOSE( z[0], y[0], tol );
+    BOOST_CHECK_EQUAL( z[1], y[1] );
+    BOOST_CHECK_CLOSE( z[2], y[2], tol );
+}
+
+
+BOOST_AUTO_TEST_CASE( ScalarOperationsTest ) {
+    Prob xorg(3), x(3);
+    xorg.set( 0, 2.0 );
+    xorg.set( 1, 0.0 );
+    xorg.set( 2, 1.0 );
+    Prob y(3);
+
+    x = xorg;
+    BOOST_CHECK( x.fill( 1.0 ) == Prob(3, 1.0) );
+    BOOST_CHECK( x == Prob(3, 1.0) );
+    BOOST_CHECK( x.fill( 2.0 ) == Prob(3, 2.0) );
+    BOOST_CHECK( x == Prob(3, 2.0) );
+    BOOST_CHECK( x.fill( 0.0 ) == Prob(3, 0.0) );
+    BOOST_CHECK( x == Prob(3, 0.0) );
+
+    x = xorg;
+    y.set( 0, 3.0 ); y.set( 1, 1.0 ); y.set( 2, 2.0 );
+    BOOST_CHECK( (x += 1.0) == y );
+    BOOST_CHECK( x == y );
+    y.set( 0, 1.0 ); y.set( 1, -1.0 ); y.set( 2, 0.0 );
+    BOOST_CHECK( (x += -2.0) == y );
+    BOOST_CHECK( x == y );
+
+    x = xorg;
+    y.set( 0, 1.0 ); y.set( 1, -1.0 ); y.set( 2, 0.0 );
+    BOOST_CHECK( (x -= 1.0) == y );
+    BOOST_CHECK( x == y );
+    y.set( 0, 3.0 ); y.set( 1, 1.0 ); y.set( 2, 2.0 );
+    BOOST_CHECK( (x -= -2.0) == y );
+    BOOST_CHECK( x == y );
+
+    x = xorg;
+    BOOST_CHECK( (x *= 1.0) == x );
+    BOOST_CHECK( x == x );
+    y.set( 0, 4.0 ); y.set( 1, 0.0 ); y.set( 2, 2.0 );
+    BOOST_CHECK( (x *= 2.0) == y );
+    BOOST_CHECK( x == y );
+    y.set( 0, -1.0 ); y.set( 1, 0.0 ); y.set( 2, -0.5 );
+    BOOST_CHECK( (x *= -0.25) == y );
+    BOOST_CHECK( x == y );
+
+    x = xorg;
+    BOOST_CHECK( (x /= 1.0) == x );
+    BOOST_CHECK( x == x );
+    y.set( 0, 1.0 ); y.set( 1, 0.0 ); y.set( 2, 0.5 );
+    BOOST_CHECK( (x /= 2.0) == y );
+    BOOST_CHECK( x == y );
+    y.set( 0, -4.0 ); y.set( 1, 0.0 ); y.set( 2, -2.0 );
+    BOOST_CHECK( (x /= -0.25) == y );
+    BOOST_CHECK( x == y );
+    BOOST_CHECK( (x /= 0.0) == Prob(3, 0.0) );
+    BOOST_CHECK( x == Prob(3, 0.0) );
+
+    x = xorg;
+    BOOST_CHECK( (x ^= 1.0) == x );
+    BOOST_CHECK( x == x );
+    BOOST_CHECK( (x ^= 0.0) == Prob(3, 1.0) );
+    BOOST_CHECK( x == Prob(3, 1.0) );
+    x = xorg;
+    y.set( 0, 4.0 ); y.set( 1, 0.0 ); y.set( 2, 1.0 );
+    BOOST_CHECK( (x ^= 2.0) == y );
+    BOOST_CHECK( x == y );
+    y.set( 0, 0.5 ); y.set( 1, INFINITY ); y.set( 2, 1.0 );
+    BOOST_CHECK( (x ^= -0.5) == y );
+    BOOST_CHECK( x == y );
+}
+
+
+BOOST_AUTO_TEST_CASE( VectorOperationsTest ) {
+    size_t N = 6;
+    Prob xorg(N), x(N);
+    xorg.set( 0, 2.0 ); xorg.set( 1, 0.0 ); xorg.set( 2, 1.0 ); xorg.set( 3, 0.0 ); xorg.set( 4, 2.0 ); xorg.set( 5, 3.0 );
+    Prob y(N);
+    y.set( 0, 0.5 ); y.set( 1, -1.0 ); y.set( 2, 0.0 ); y.set( 3, 0.0 ); y.set( 4, -2.0 ); y.set( 5, 3.0 );
+    Prob z(N), r(N);
+
+    z.set( 0, 2.5 ); z.set( 1, -1.0 ); z.set( 2, 1.0 ); z.set( 3, 0.0 ); z.set( 4, 0.0 ); z.set( 5, 6.0 );
+    x = xorg;
+    r = (x += y);
+    for( size_t i = 0; i < N; i++ )
+        BOOST_CHECK_CLOSE( r[i], z[i], tol );
+    BOOST_CHECK( x == z );
+    x = xorg;
+    BOOST_CHECK( x.pwBinaryOp( y, std::plus<Real>() ) == z );
+    BOOST_CHECK( x == z );
+
+    z.set( 0, 1.5 ); z.set( 1, 1.0 ); z.set( 2, 1.0 ); z.set( 3, 0.0 ); z.set( 4, 4.0 ); z.set( 5, 0.0 );
+    x = xorg;
+    r = (x -= y);
+    for( size_t i = 0; i < N; i++ )
+        BOOST_CHECK_CLOSE( r[i], z[i], tol );
+    BOOST_CHECK( x == z );
+    x = xorg;
+    BOOST_CHECK( x.pwBinaryOp( y, std::minus<Real>() ) == z );
+    BOOST_CHECK( x == z );
+
+    z.set( 0, 1.0 ); z.set( 1, 0.0 ); z.set( 2, 0.0 ); z.set( 3, 0.0 ); z.set( 4, -4.0 ); z.set( 5, 9.0 );
+    x = xorg;
+    r = (x *= y);
+    for( size_t i = 0; i < N; i++ )
+        BOOST_CHECK_CLOSE( r[i], z[i], tol );
+    BOOST_CHECK( x == z );
+    x = xorg;
+    BOOST_CHECK( x.pwBinaryOp( y, std::multiplies<Real>() ) == z );
+    BOOST_CHECK( x == z );
+
+    z.set( 0, 4.0 ); z.set( 1, 0.0 ); z.set( 2, 0.0 ); z.set( 3, 0.0 ); z.set( 4, -1.0 ); z.set( 5, 1.0 );
+    x = xorg;
+    r = (x /= y);
+    for( size_t i = 0; i < N; i++ )
+        BOOST_CHECK_CLOSE( r[i], z[i], tol );
+    BOOST_CHECK( x == z );
+    x = xorg;
+    BOOST_CHECK( x.pwBinaryOp( y, fo_divides0<Real>() ) == z );
+    BOOST_CHECK( x == z );
+
+    z.set( 0, 4.0 ); z.set( 1, 0.0 ); z.set( 2, INFINITY ); 
+    // z.set( 3, INFINITY );
+    z.set( 4, -1.0 ); z.set( 5, 1.0 );
+    x = xorg;
+    r = (x.divide( y ));
+    BOOST_CHECK_CLOSE( r[0], z[0], tol );
+    BOOST_CHECK_CLOSE( r[1], z[1], tol );
+    BOOST_CHECK_EQUAL( r[2], z[2] );
+    BOOST_CHECK( isnan(r[3]) );
+    BOOST_CHECK_CLOSE( r[4], z[4], tol );
+    BOOST_CHECK_CLOSE( r[5], z[5], tol );
+    x.set( 3, 0.0 ); r.set( 3, 0.0 );
+    BOOST_CHECK( x == r );
+    x = xorg;
+    r = x.pwBinaryOp( y, std::divides<Real>() );
+    BOOST_CHECK_CLOSE( r[0], z[0], tol );
+    BOOST_CHECK_CLOSE( r[1], z[1], tol );
+    BOOST_CHECK_EQUAL( r[2], z[2] );
+    BOOST_CHECK( isnan(r[3]) );
+    BOOST_CHECK_CLOSE( r[4], z[4], tol );
+    BOOST_CHECK_CLOSE( r[5], z[5], tol );
+    x.set( 3, 0.0 ); r.set( 3, 0.0 );
+    BOOST_CHECK( x == r );
+
+    z.set( 0, std::sqrt(2.0) ); z.set( 1, INFINITY ); z.set( 2, 1.0 ); z.set( 3, 1.0 ); z.set( 4, 0.25 ); z.set( 5, 27.0 );
+    x = xorg;
+    r = (x ^= y);
+    BOOST_CHECK_CLOSE( r[0], z[0], tol );
+    BOOST_CHECK_EQUAL( r[1], z[1] );
+    BOOST_CHECK_CLOSE( r[2], z[2], tol );
+    BOOST_CHECK_CLOSE( r[3], z[3], tol );
+    BOOST_CHECK_CLOSE( r[4], z[4], tol );
+    BOOST_CHECK_CLOSE( r[5], z[5], tol );
+    BOOST_CHECK( x == z );
+    x = xorg;
+    BOOST_CHECK( x.pwBinaryOp( y, fo_pow<Real>() ) == z );
+    BOOST_CHECK( x == z );
+}
+
+
+BOOST_AUTO_TEST_CASE( VectorTransformationsTest ) {
+    size_t N = 6;
+    Prob x(N);
+    x.set( 0, 2.0 ); x.set( 1, 0.0 ); x.set( 2, 1.0 ); x.set( 3, 0.0 ); x.set( 4, 2.0 ); x.set( 5, 3.0 );
+    Prob y(N);
+    y.set( 0, 0.5 ); y.set( 1, -1.0 ); y.set( 2, 0.0 ); y.set( 3, 0.0 ); y.set( 4, -2.0 ); y.set( 5, 3.0 );
+    Prob z(N), r(N);
+
+    z.set( 0, 2.5 ); z.set( 1, -1.0 ); z.set( 2, 1.0 ); z.set( 3, 0.0 ); z.set( 4, 0.0 ); z.set( 5, 6.0 );
+    r = x + y;
+    for( size_t i = 0; i < N; i++ )
+        BOOST_CHECK_CLOSE( r[i], z[i], tol );
+    z = x.pwBinaryTr( y, std::plus<Real>() );
+    BOOST_CHECK( r == z );
+
+    z.set( 0, 1.5 ); z.set( 1, 1.0 ); z.set( 2, 1.0 ); z.set( 3, 0.0 ); z.set( 4, 4.0 ); z.set( 5, 0.0 );
+    r = x - y;
+    for( size_t i = 0; i < N; i++ )
+        BOOST_CHECK_CLOSE( r[i], z[i], tol );
+    z = x.pwBinaryTr( y, std::minus<Real>() );
+    BOOST_CHECK( r == z );
+
+    z.set( 0, 1.0 ); z.set( 1, 0.0 ); z.set( 2, 0.0 ); z.set( 3, 0.0 ); z.set( 4, -4.0 ); z.set( 5, 9.0 );
+    r = x * y;
+    for( size_t i = 0; i < N; i++ )
+        BOOST_CHECK_CLOSE( r[i], z[i], tol );
+    z = x.pwBinaryTr( y, std::multiplies<Real>() );
+    BOOST_CHECK( r == z );
+
+    z.set( 0, 4.0 ); z.set( 1, 0.0 ); z.set( 2, 0.0 ); z.set( 3, 0.0 ); z.set( 4, -1.0 ); z.set( 5, 1.0 );
+    r = x / y;
+    for( size_t i = 0; i < N; i++ )
+        BOOST_CHECK_CLOSE( r[i], z[i], tol );
+    z = x.pwBinaryTr( y, fo_divides0<Real>() );
+    BOOST_CHECK( r == z );
+
+    z.set( 0, 4.0 ); z.set( 1, 0.0 ); z.set( 2, INFINITY ); 
+    // z.set( 3, INFINITY );
+    z.set( 4, -1.0 ); z.set( 5, 1.0 );
+    r = x.divided_by( y );
+    BOOST_CHECK_CLOSE( r[0], z[0], tol );
+    BOOST_CHECK_CLOSE( r[1], z[1], tol );
+    BOOST_CHECK_EQUAL( r[2], z[2] );
+    BOOST_CHECK( isnan(r[3]) );
+    BOOST_CHECK_CLOSE( r[4], z[4], tol );
+    BOOST_CHECK_CLOSE( r[5], z[5], tol );
+    z = x.pwBinaryTr( y, std::divides<Real>() );
+    BOOST_CHECK_CLOSE( r[0], z[0], tol );
+    BOOST_CHECK_CLOSE( r[1], z[1], tol );
+    BOOST_CHECK_EQUAL( r[2], z[2] );
+    BOOST_CHECK( isnan(r[3]) );
+    BOOST_CHECK_CLOSE( r[4], z[4], tol );
+    BOOST_CHECK_CLOSE( r[5], z[5], tol );
+
+    z.set( 0, std::sqrt(2.0) ); z.set( 1, INFINITY ); z.set( 2, 1.0 ); z.set( 3, 1.0 ); z.set( 4, 0.25 ); z.set( 5, 27.0 );
+    r = x ^ y;
+    BOOST_CHECK_CLOSE( r[0], z[0], tol );
+    BOOST_CHECK_EQUAL( r[1], z[1] );
+    BOOST_CHECK_CLOSE( r[2], z[2], tol );
+    BOOST_CHECK_CLOSE( r[3], z[3], tol );
+    BOOST_CHECK_CLOSE( r[4], z[4], tol );
+    BOOST_CHECK_CLOSE( r[5], z[5], tol );
+    z = x.pwBinaryTr( y, fo_pow<Real>() );
+    BOOST_CHECK( r == z );
+}
+
+
+BOOST_AUTO_TEST_CASE( RelatedFunctionsTest ) {
+    Prob x(3), y(3), z(3);
+    x.set( 0, 0.2 );
+    x.set( 1, 0.8 );
+    x.set( 2, 0.0 );
+    y.set( 0, 0.0 );
+    y.set( 1, 0.6 );
+    y.set( 2, 0.4 );
+
+    z = min( x, y );
+    BOOST_CHECK_EQUAL( z[0], 0.0 );
+    BOOST_CHECK_EQUAL( z[1], 0.6 );
+    BOOST_CHECK_EQUAL( z[2], 0.0 );
+    z = max( x, y );
+    BOOST_CHECK_EQUAL( z[0], 0.2 );
+    BOOST_CHECK_EQUAL( z[1], 0.8 );
+    BOOST_CHECK_EQUAL( z[2], 0.4 );
+
+    BOOST_CHECK_EQUAL( dist( x, x, Prob::DISTL1 ), 0.0 );
+    BOOST_CHECK_EQUAL( dist( y, y, Prob::DISTL1 ), 0.0 );
+    BOOST_CHECK_EQUAL( dist( x, y, Prob::DISTL1 ), 0.2 + 0.2 + 0.4 );
+    BOOST_CHECK_EQUAL( dist( y, x, Prob::DISTL1 ), 0.2 + 0.2 + 0.4 );
+    BOOST_CHECK_EQUAL( dist( x, y, Prob::DISTL1 ), x.innerProduct( y, 0.0, std::plus<Real>(), fo_absdiff<Real>() ) );
+    BOOST_CHECK_EQUAL( dist( y, x, Prob::DISTL1 ), y.innerProduct( x, 0.0, std::plus<Real>(), fo_absdiff<Real>() ) );
+    BOOST_CHECK_EQUAL( dist( x, x, Prob::DISTLINF ), 0.0 );
+    BOOST_CHECK_EQUAL( dist( y, y, Prob::DISTLINF ), 0.0 );
+    BOOST_CHECK_EQUAL( dist( x, y, Prob::DISTLINF ), 0.4 );
+    BOOST_CHECK_EQUAL( dist( y, x, Prob::DISTLINF ), 0.4 );
+    BOOST_CHECK_EQUAL( dist( x, y, Prob::DISTLINF ), x.innerProduct( y, 0.0, fo_max<Real>(), fo_absdiff<Real>() ) );
+    BOOST_CHECK_EQUAL( dist( y, x, Prob::DISTLINF ), y.innerProduct( x, 0.0, fo_max<Real>(), fo_absdiff<Real>() ) );
+    BOOST_CHECK_EQUAL( dist( x, x, Prob::DISTTV ), 0.0 );
+    BOOST_CHECK_EQUAL( dist( y, y, Prob::DISTTV ), 0.0 );
+    BOOST_CHECK_EQUAL( dist( x, y, Prob::DISTTV ), 0.5 * (0.2 + 0.2 + 0.4) );
+    BOOST_CHECK_EQUAL( dist( y, x, Prob::DISTTV ), 0.5 * (0.2 + 0.2 + 0.4) );
+    BOOST_CHECK_EQUAL( dist( x, y, Prob::DISTTV ), x.innerProduct( y, 0.0, std::plus<Real>(), fo_absdiff<Real>() ) / 2.0 );
+    BOOST_CHECK_EQUAL( dist( y, x, Prob::DISTTV ), y.innerProduct( x, 0.0, std::plus<Real>(), fo_absdiff<Real>() ) / 2.0 );
+    BOOST_CHECK_EQUAL( dist( x, x, Prob::DISTKL ), 0.0 );
+    BOOST_CHECK_EQUAL( dist( y, y, Prob::DISTKL ), 0.0 );
+    BOOST_CHECK_EQUAL( dist( x, y, Prob::DISTKL ), INFINITY );
+    BOOST_CHECK_EQUAL( dist( y, x, Prob::DISTKL ), INFINITY );
+    BOOST_CHECK_EQUAL( dist( x, y, Prob::DISTKL ), x.innerProduct( y, 0.0, std::plus<Real>(), fo_KL<Real>() ) );
+    BOOST_CHECK_EQUAL( dist( y, x, Prob::DISTKL ), y.innerProduct( x, 0.0, std::plus<Real>(), fo_KL<Real>() ) );
+    BOOST_CHECK_EQUAL( dist( x, x, Prob::DISTHEL ), 0.0 );
+    BOOST_CHECK_EQUAL( dist( y, y, Prob::DISTHEL ), 0.0 );
+    BOOST_CHECK_EQUAL( dist( x, y, Prob::DISTHEL ), 0.5 * (0.2 + std::pow(std::sqrt(0.8) - std::sqrt(0.6), 2.0) + 0.4) );
+    BOOST_CHECK_EQUAL( dist( y, x, Prob::DISTHEL ), 0.5 * (0.2 + std::pow(std::sqrt(0.8) - std::sqrt(0.6), 2.0) + 0.4) );
+    BOOST_CHECK_EQUAL( dist( x, y, Prob::DISTHEL ), x.innerProduct( y, 0.0, std::plus<Real>(), fo_Hellinger<Real>() ) / 2.0 );
+    BOOST_CHECK_EQUAL( dist( y, x, Prob::DISTHEL ), y.innerProduct( x, 0.0, std::plus<Real>(), fo_Hellinger<Real>() ) / 2.0 );
+    x.set( 1, 0.7 ); x.set( 2, 0.1 );
+    y.set( 0, 0.1 ); y.set( 1, 0.5 );
+    BOOST_CHECK_CLOSE( dist( x, y, Prob::DISTKL ), 0.2 * std::log(0.2 / 0.1) + 0.7 * std::log(0.7 / 0.5) + 0.1 * std::log(0.1 / 0.4), tol );
+    BOOST_CHECK_CLOSE( dist( y, x, Prob::DISTKL ), 0.1 * std::log(0.1 / 0.2) + 0.5 * std::log(0.5 / 0.7) + 0.4 * std::log(0.4 / 0.1), tol );
+    BOOST_CHECK_EQUAL( dist( x, y, Prob::DISTKL ), x.innerProduct( y, 0.0, std::plus<Real>(), fo_KL<Real>() ) );
+    BOOST_CHECK_EQUAL( dist( y, x, Prob::DISTKL ), y.innerProduct( x, 0.0, std::plus<Real>(), fo_KL<Real>() ) );
+
+    std::stringstream ss;
+    ss << x;
+    std::string s;
+    std::getline( ss, s );
+    BOOST_CHECK_EQUAL( s, std::string("(0.2, 0.7, 0.1)") );
+    std::stringstream ss2;
+    ss2 << y;
+    std::getline( ss2, s );
+    BOOST_CHECK_EQUAL( s, std::string("(0.1, 0.5, 0.4)") );
+
+    z = min( x, y );
+    BOOST_CHECK_EQUAL( z[0], 0.1 );
+    BOOST_CHECK_EQUAL( z[1], 0.5 );
+    BOOST_CHECK_EQUAL( z[2], 0.1 );
+    z = max( x, y );
+    BOOST_CHECK_EQUAL( z[0], 0.2 );
+    BOOST_CHECK_EQUAL( z[1], 0.7 );
+    BOOST_CHECK_EQUAL( z[2], 0.4 );
+
+    BOOST_CHECK_CLOSE( x.innerProduct( y, 0.0, std::plus<Real>(), std::multiplies<Real>() ), 0.2*0.1 + 0.7*0.5 + 0.1*0.4, tol );
+    BOOST_CHECK_CLOSE( y.innerProduct( x, 0.0, std::plus<Real>(), std::multiplies<Real>() ), 0.2*0.1 + 0.7*0.5 + 0.1*0.4, tol );
+    BOOST_CHECK_CLOSE( x.innerProduct( y, 1.0, std::plus<Real>(), std::multiplies<Real>() ), 1.0 + 0.2*0.1 + 0.7*0.5 + 0.1*0.4, tol );
+    BOOST_CHECK_CLOSE( y.innerProduct( x, 1.0, std::plus<Real>(), std::multiplies<Real>() ), 1.0 + 0.2*0.1 + 0.7*0.5 + 0.1*0.4, tol );
+    BOOST_CHECK_CLOSE( x.innerProduct( y, -1.0, std::plus<Real>(), std::multiplies<Real>() ), -1.0 + 0.2*0.1 + 0.7*0.5 + 0.1*0.4, tol );
+    BOOST_CHECK_CLOSE( y.innerProduct( x, -1.0, std::plus<Real>(), std::multiplies<Real>() ), -1.0 + 0.2*0.1 + 0.7*0.5 + 0.1*0.4, tol );
+}
+*/