From b0057954d3f6dda266b21c5e9c4e3062d9097849 Mon Sep 17 00:00:00 2001 From: lambday Date: Sat, 18 May 2013 13:08:15 +0530 Subject: [PATCH] Jacobi Elliptic Functions added --- src/configure | 41 +++++ .../mathematics/JacobiEllipticFunctions.cpp | 134 ++++++++++++++ .../mathematics/JacobiEllipticFunctions.h | 164 ++++++++++++++++++ .../JacobiEllipticFunctions_unittest.cc | 164 ++++++++++++++++++ tests/unit/multiclass/MCLDA_unittest.cc | 2 + 5 files changed, 505 insertions(+) create mode 100644 src/shogun/mathematics/JacobiEllipticFunctions.cpp create mode 100644 src/shogun/mathematics/JacobiEllipticFunctions.h create mode 100644 tests/unit/mathematics/JacobiEllipticFunctions_unittest.cc diff --git a/src/configure b/src/configure index ed5fc33b4b7..69c9730c250 100755 --- a/src/configure +++ b/src/configure @@ -103,6 +103,7 @@ _mosek=auto _arpack=auto _nlopt=auto _eigen3=auto +_arprec=no _gmock=auto _gtest=auto _bigstates=yes @@ -1435,6 +1436,7 @@ Optional features: --enable-superlu enable SuperLU [auto] --enable-nlopt enable NLOPT [auto] --enable-eigen3 enable Eigen3 [auto] + --enable-arprec enable Arprec [disabled] --enable-cplex enable code using CPLEX [auto] --enable-lpsolve enable code using lpsolve [auto] --enable-glpk enable code using GLPK [auto] @@ -1462,6 +1464,7 @@ Optional features: --disable-superlu disable SuperLU [auto] --disable-nlopt disable NLOPT [auto] --disable-eigen3 disable Eigen3 [auto] + --disable-arprec disable Arprec [disabled] --disable-gmock disable google mocking framework [auto] --disable-gtest disable google testing framework [auto] --disable-cplex disable code using CPLEX [auto] @@ -1693,6 +1696,8 @@ EOF --enable-nlopt) _nlopt=yes ;; --disable-eigen3) _eigen3=no ;; --enable-eigen3) _eigen3=yes ;; + --disable-arprec) _arprec=no ;; + --enable-arprec) _arprec=yes ;; --disable-gtest) _gtest=no ;; --enable-gtest) _gtest=yes ;; --disable-gmock) _gmock=no ;; @@ -3675,6 +3680,41 @@ EOF fi } +check_arprec() +{ + if test "$_arprec" = yes || test "$_arprec" = auto + then + cat > $TMPCXX << EOF +#include +#include + +int main() +{ + mp::mp_init(100,NULL,true); + mp_real pi=mp_real::_pi; + mp_complex sin_u=sin(mp_complex(20)); + mp::mp_finalize(); + return 0; +} +EOF + echocheck "ARPREC support" + if cxx_check -larprec + then + echores "yes" + HAVE_ARPREC='#define HAVE_ARPREC 1' + DEFINES="$DEFINES -DHAVE_ARPREC" + POSTLINKFLAGS="$POSTLINKFLAGS -larprec" + else + if test "$_arprec" = yes + then + die "ARPREC not found" + else + echores "no" + fi + fi + fi +} + check_mosek() { if test "$_mosek" = yes || test "$_mosek" = auto @@ -5589,6 +5629,7 @@ check_mosek check_arpack check_nlopt check_eigen3 +check_arprec check_cplex check_glpk check_lzo diff --git a/src/shogun/mathematics/JacobiEllipticFunctions.cpp b/src/shogun/mathematics/JacobiEllipticFunctions.cpp new file mode 100644 index 00000000000..3366903f25c --- /dev/null +++ b/src/shogun/mathematics/JacobiEllipticFunctions.cpp @@ -0,0 +1,134 @@ +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * Written (W) 2013 Soumyajit De + * + * KRYLSTAT Copyright 2011 by Erlend Aune under GPL2+ + * (few parts rewritten and adjusted for shogun) + */ + +#include + +using namespace shogun; + +void CJacobiEllipticFunctions::ellKKP(Real L, Real &K, Real &Kp) +{ + REQUIRE(L>=0.0, + "CJacobiEllipticFunctions::ellKKP(): \ + Parameter L should be non-negative\n"); +#ifdef HAVE_ARPREC + const Real eps=Real(std::numeric_limits::epsilon()); + const Real pi=mp_real::_pi; +#else + const Real eps=std::numeric_limits::epsilon(); + const Real pi=M_PI; +#endif //HAVE_ARPREC + if (L>10.0) + { + K=pi*0.5; + Kp=pi*L+log(4.0); + } + else + { + Real m=exp(-2.0*pi*L); + Real mp=1.0-m; + if (m::max()); + } + else if (mp::max()); + Kp=compute_quarter_period(sqrt(m)); + } + else + { + K=compute_quarter_period(sqrt(mp)); + Kp=compute_quarter_period(sqrt(m)); + } + } +} + +void CJacobiEllipticFunctions + ::ellPJC(Complex u, Real m, Complex &sn, Complex &cn, Complex &dn) +{ + REQUIRE(m>=0.0 && m<=1.0, + "CJacobiEllipticFunctions::ellPJC(): \ + Parameter m should be >=0 and <=1\n"); + +#ifdef HAVE_ARPREC + const Real eps=sqrt(mp_real::_eps); +#else + const Real eps=sqrt(std::numeric_limits::epsilon()); +#endif //HAVE_ARPREC + if (m>=(1.0-eps)) + { +#ifdef HAVE_ARPREC + std::complex _u(dble(u.real),dble(u.imag)); + std::complex t=tanh(_u); + std::complex b=cosh(_u); + std::complex twon=b*sinh(_u); + std::complex ai=0.25*(1.0-dble(m)); + std::complex _sn=t+ai*(twon-_u)/(b*b); + std::complex phi=1.0/b; + std::complex _cn=phi-ai*(twon-_u); + std::complex _dn=phi+ai*(twon+_u); + sn=mp_complex(_sn.real(),_sn.imag()); + cn=mp_complex(_cn.real(),_cn.imag()); + dn=mp_complex(_dn.real(),_dn.imag()); +#else + Complex t=tanh(u); + Complex b=cosh(u); + Complex ai=0.25*(1.0-m); + Complex twon=b*sinh(u); + sn=t+ai*(twon-u)/(b*b); + Complex phi=Real(1.0)/b; + ai*=t*phi; + cn=phi-ai*(twon-u); + dn=phi+ai*(twon+u); +#endif //HAVE_ARPREC + } + else + { + const Real prec=4.0*eps; + const index_t MAX_ITER=128; + index_t i=0; + Real kappa[MAX_ITER]; + + while (iprec) + { + Real k; + if (m>0.001) + { + Real mp=sqrt(1.0-m); + k=(1.0-mp)/(1.0+mp); + } + else + k=poly_six(m/4.0); + u/=(1.0+k); + m=k*k; + kappa[i++]=k; + } + Complex sin_u=sin(u); + Complex cos_u=cos(u); + Complex t=Real(0.25*m)*(u-sin_u*cos_u); + sn=sin_u-t*cos_u; + cn=cos_u+t*sin_u; + dn=Real(1.0)+Real(0.5*m)*(cos_u*cos_u); + + i--; + while (i>=0) + { + Real k=kappa[i--]; + Complex ksn2=k*(sn*sn); + Complex d=Real(1.0)+ksn2; + sn*=(1.0+k)/d; + cn*=dn/d; + dn=(Real(1.0)-ksn2)/d; + } + } +} diff --git a/src/shogun/mathematics/JacobiEllipticFunctions.h b/src/shogun/mathematics/JacobiEllipticFunctions.h new file mode 100644 index 00000000000..4a5fa9f8df1 --- /dev/null +++ b/src/shogun/mathematics/JacobiEllipticFunctions.h @@ -0,0 +1,164 @@ +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * Written (W) 2013 Soumyajit De + * + * KRYLSTAT Copyright 2011 by Erlend Aune under GPL2+ + * (few parts rewritten and adjusted for shogun) + * + * NOTE: For higher precision, the methods in this class rely on an external + * library, ARPREC (http://crd-legacy.lbl.gov/~dhbailey/mpdist/), in absense of + * which they fallback to shogun datatypes. To use it with shogun, configure + * ARPREC with "./configure 'CXX c++ -fPIC'" in order to link. + */ + +#ifndef __JACOBI_ELLIPTIC_FUNCTIONS_H_ +#define __JACOBI_ELLIPTIC_FUNCTIONS_H_ + +#include +#include +#include +#include +#include + +#ifdef HAVE_ARPREC +#include +#include +#endif //HAVE_ARPREC + +namespace shogun +{ + +/** @brief Class that contains methods for computing Jacobi elliptic functions + * related to complex analysis. These functions are inverse of the elliptic + * integral of first kind, i.e. + * \f[ + * u(k,m)=\int_{0}^{k}\frac{dt}{\sqrt{(1-t^{2})(1-m^{2}t^{2})}} + * =\int_{0}^{\varphi}\frac{d\theta}{\sqrt{(1-m^{2}sin^{2}\theta)}} + * \f] + * where \f$k=sin\varphi\f$, \f$t=sin\theta\f$ and parameter \f$m, 0\le m + * \le 1\f$ is called modulus. There main Jacobi elliptic functions are defined + * as \f$sn(u,m)=k=sin\theta\f$, \f$cn(u,m)=cos\theta=\sqrt{1-sn(u,m)^{2}}\f$ + * and \f$dn(u,m)=\sqrt{1-m^{2}sn(u,m)^{2}}\f$. + * For \f$k=1\f$, i.e. \f$\varphi=\frac{\pi}{2}\f$, \f$u(1,m)=K(m)\f$ is known + * as the complete elliptic integral of first kind. Similarly, \f$u(1,m))= + * K'(m')\f$, \f$m'=\sqrt{1-m^{2}}\f$ is called the complementary complete + * elliptic integral of first kind. Jacobi functions are double periodic with + * quardratic periods \f$K\f$ and \f$K'\f$. + * + * This class provides two sets of methods for computing \f$K,K'\f$, and + * \f$sn,cn,dn\f$. Useful for computing rational approximation of matrix + * functions given by Cauchy's integral formula, etc. + */ +class CJacobiEllipticFunctions: public CSGObject +{ +#ifdef HAVE_ARPREC + typedef mp_real Real; + typedef mp_complex Complex; +#else + typedef float64_t Real; + typedef std::complex Complex; +#endif //HAVE_ARPREC +private: + static inline Real compute_quarter_period(Real b) + { +#ifdef HAVE_ARPREC + const Real eps=mp_real::_eps; + const Real pi=mp_real::_pi; +#else + const Real eps=std::numeric_limits::epsilon(); + const Real pi=M_PI; +#endif //HAVE_ARPREC + Real a=1.0; + Real mm=1.0; + + int64_t p=2; + do + { + Real a_new=(a+b)*0.5; + Real b_new=sqrt(a*b); + Real c=(a-b)*0.5; + mm=Real(p)*c*c; + p<<=1; + a=a_new; + b=b_new; + } while (mm>eps); + return pi*0.5/a; + } + + static inline Real poly_six(Real x) + { + return (132*pow(x,6)+42*pow(x,5)+14*pow(x,4)+5*pow(x,3)+2*pow(x,2)+x); + } + +public: + /** Computes the quarter periods (K and K') of Jacobian elliptic functions + * (see class description). + * @param L + * @param K the quarter period (to be computed) on the Real axis + * @param Kp the quarter period (to be computed) on the Imaginary axis + * computed + */ + static void ellKKP(Real L, Real &K, Real &Kp); + + /** Computes three main Jacobi elliptic functions, \f$sn(u,m)\f$, + * \f$cn(u,m)\f$ and \f$dn(u,m)\f$ (see class description). + * @param u the elliptic integral of the first kind \f$u(k,m)\f$ + * @param m the modulus parameter, \f$0\le m \le 1\f$ + * @param sn Jacobi elliptic function sn(u,m) + * @param cn Jacobi elliptic function cn(u,m) + * @param dn Jacobi elliptic function dn(u,m) + */ + static void ellPJC(Complex u, Real m, Complex &sn, Complex &cn, Complex &dn); + +#ifdef HAVE_ARPREC + /** Wrapper method for ellKKP if ARPREC is present (for high precision) + * @param L + * @param K the quarter period (to be computed) on the Real axis + * @param Kp the quarter period (to be computed) on the Imaginary axis + * computed + */ + static void ellKKP(float64_t L, float64_t &K, float64_t &Kp) + { + mp::mp_init(100, NULL, true); + mp_real _K, _Kp; + ellKKP(mp_real(L), _K, _Kp); + K=dble(_K); + Kp=dble(_Kp); + mp::mp_finalize(); + } + + /** Wrapper method for ellPJC if ARPREC is present (for high precision) + * @param u the elliptic integral of the first kind \f$u(k,m)\f$ + * @param m the modulus parameter, \f$0\le m \le 1\f$ + * @param sn Jacobi elliptic function sn(u,m) + * @param cn Jacobi elliptic function cn(u,m) + * @param dn Jacobi elliptic function dn(u,m) + */ + static void ellPJC(std::complex u, float64_t m, + std::complex &sn, std::complex &cn, + std::complex &dn) + { + mp::mp_init(100, NULL, true); + mp_complex _sn, _cn, _dn; + ellPJC(mp_complex(u.real(),u.imag()), mp_real(m), _sn, _cn, _dn); + sn=std::complex(dble(_sn.real),dble(_sn.imag)); + cn=std::complex(dble(_cn.real),dble(_cn.imag)); + dn=std::complex(dble(_dn.real),dble(_dn.imag)); + mp::mp_finalize(); + } +#endif //HAVE_ARPREC + + /** @return object name */ + virtual const char* get_name() const + { + return "JacobiEllipticFunctions"; + } +}; + +} + +#endif /* __JACOBI_ELLIPTIC_FUNCTIONS_H_ */ diff --git a/tests/unit/mathematics/JacobiEllipticFunctions_unittest.cc b/tests/unit/mathematics/JacobiEllipticFunctions_unittest.cc new file mode 100644 index 00000000000..5eb0f41c39f --- /dev/null +++ b/tests/unit/mathematics/JacobiEllipticFunctions_unittest.cc @@ -0,0 +1,164 @@ +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * Written (W) 2013 Soumyajit De + */ + +#include +#include +#include + +#ifdef HAVE_ARPREC +#include +#include +#endif //HAVE_ARPREC + +using namespace shogun; + +typedef float64_t Real; +typedef std::complex Complex; + +TEST(JacobiEllipticFunctions, ellKKP) +{ + Real K, Kp; +#ifdef HAVE_ARPREC + CJacobiEllipticFunctions::ellKKP(0.9999999999, K, Kp); + EXPECT_NEAR(K, 1.57153044117197637775, 1E-19); + EXPECT_NEAR(Kp, 4.52953569660335286784, 1E-19); + + CJacobiEllipticFunctions::ellKKP(10.1, K, Kp); + EXPECT_NEAR(K, 1.57079632679489655800, 1E-19); + EXPECT_NEAR(Kp, 33.11638016237679948972, 1E-19); + + CJacobiEllipticFunctions::ellKKP(10.0, K, Kp); + EXPECT_NEAR(K, 1.57079632679489655800, 1E-19); + EXPECT_EQ(Kp, std::numeric_limits::max()); + + CJacobiEllipticFunctions::ellKKP(0.0, K, Kp); + EXPECT_EQ(K, std::numeric_limits::max()); + EXPECT_NEAR(Kp, 1.5707963267948965580, 1E-19); +#else + CJacobiEllipticFunctions::ellKKP(0.9999999999, K, Kp); + EXPECT_NEAR(K, 1.57153044117197637775, 1E-15); + EXPECT_NEAR(Kp, 4.52953569660335286784, 1E-15); + + CJacobiEllipticFunctions::ellKKP(10.1, K, Kp); + EXPECT_NEAR(K, 1.57079632679489655800, 1E-15); + EXPECT_NEAR(Kp, 33.11638016237679948972, 1E-15); + + CJacobiEllipticFunctions::ellKKP(10.0, K, Kp); + EXPECT_NEAR(K, 1.57079632679489655800, 1E-15); + EXPECT_EQ(Kp, std::numeric_limits::max()); + + CJacobiEllipticFunctions::ellKKP(0.0, K, Kp); + EXPECT_EQ(K, std::numeric_limits::max()); + EXPECT_NEAR(Kp, 1.5707963267948965580, 1E-15); +#endif //HAVE_ARPREC +} + +TEST(JacobiEllipticFunctions, ellPJC) +{ + Complex sn, cn, dn; +#ifdef HAVE_ARPREC + CJacobiEllipticFunctions::ellPJC(Complex(0.5,0.0), 0.0, sn, cn, dn); + EXPECT_NEAR(sn.real(), 0.47942553860420300538, 1E-19); + EXPECT_NEAR(cn.real(), 0.87758256189037275874, 1E-19); + EXPECT_NEAR(dn.real(), 1.0, 1E-19); + EXPECT_NEAR(sn.imag(), 0.0, 1E-19); + EXPECT_NEAR(cn.imag(), 0.0, 1E-19); + EXPECT_NEAR(dn.imag(), 0.0, 1E-19); + + CJacobiEllipticFunctions::ellPJC(Complex(0.5,0.5), 0.0, sn, cn, dn); + EXPECT_NEAR(sn.real(), 0.54061268571315335141, 1E-19); + EXPECT_NEAR(cn.real(), 0.98958488339991990124, 1E-19); + EXPECT_NEAR(dn.real(), 1.0, 1E-19); + EXPECT_NEAR(sn.imag(), 0.45730415318424921800, 1E-19); + EXPECT_NEAR(cn.imag(), -0.24982639750046153893, 1E-19); + EXPECT_NEAR(dn.imag(), 0.0, 1E-19); + + CJacobiEllipticFunctions::ellPJC(Complex(0.5,0.5), 0.5, sn, cn, dn); + EXPECT_NEAR(sn.real(), 0.55284325098354925032, 1E-19); + EXPECT_NEAR(cn.real(), 0.96941944802337476350, 1E-19); + EXPECT_NEAR(dn.real(), 0.97703467549246159063, 1E-19); + EXPECT_NEAR(sn.imag(), 0.43032986483620772056, 1E-19); + EXPECT_NEAR(cn.imag(), -0.24540972636400421036, 1E-19); + EXPECT_NEAR(dn.imag(), -0.12174847394819815483, 1E-19); + + CJacobiEllipticFunctions::ellPJC(Complex(0.2,0.0), 0.99, sn, cn, dn); + EXPECT_NEAR(sn.real(), 0.19738823726686019477, 1E-19); + EXPECT_NEAR(cn.real(), 0.98032539689058428856, 1E-19); + EXPECT_NEAR(dn.real(), 0.98052409707808552142, 1E-19); + EXPECT_NEAR(sn.imag(), 0.0, 1E-19); + EXPECT_NEAR(cn.imag(), 0.0, 1E-19); + EXPECT_NEAR(dn.imag(), 0.0, 1E-19); + + CJacobiEllipticFunctions::ellPJC(Complex(0.7,0.4), + 0.9999999999999999, sn, cn, dn); + EXPECT_NEAR(sn.real(), 0.66873789889962576005, 1E-19); + EXPECT_NEAR(cn.real(), 0.81197156278765458826, 1E-19); + EXPECT_NEAR(dn.real(), 0.81197156278765469928, 1E-19); + EXPECT_NEAR(sn.imag(), 0.25191557357137611683, 1E-19); + EXPECT_NEAR(cn.imag(), -0.20747708305429035658, 1E-19); + EXPECT_NEAR(dn.imag(), -0.20747708305429032882, 1E-19); + + CJacobiEllipticFunctions::ellPJC(Complex(0.5,0.5), 1.0L-1E-16, sn, cn, dn); + EXPECT_NEAR(sn.real(), 0.56408314126749847794, 1E-19); + EXPECT_NEAR(cn.real(), 0.94997886761549465984, 1E-19); + EXPECT_NEAR(dn.real(), 0.94997886761549465984, 1E-19); + EXPECT_NEAR(sn.imag(), 0.40389645531602574868, 1E-19); + EXPECT_NEAR(cn.imag(), -0.23982763093808803778, 1E-19); + EXPECT_NEAR(dn.imag(), -0.23982763093808801003, 1E-19); +#else + CJacobiEllipticFunctions::ellPJC(Complex(0.5,0.0), 0.0, sn, cn, dn); + EXPECT_NEAR(sn.real(), 0.47942553860420300538, 1E-15); + EXPECT_NEAR(cn.real(), 0.87758256189037275874, 1E-15); + EXPECT_NEAR(dn.real(), 1.0, 1E-15); + EXPECT_NEAR(sn.imag(), 0.0, 1E-15); + EXPECT_NEAR(cn.imag(), 0.0, 1E-15); + EXPECT_NEAR(dn.imag(), 0.0, 1E-15); + + CJacobiEllipticFunctions::ellPJC(Complex(0.5,0.5), 0.0, sn, cn, dn); + EXPECT_NEAR(sn.real(), 0.54061268571315335141, 1E-15); + EXPECT_NEAR(cn.real(), 0.98958488339991990124, 1E-15); + EXPECT_NEAR(dn.real(), 1.0, 1E-15); + EXPECT_NEAR(sn.imag(), 0.45730415318424921800, 1E-15); + EXPECT_NEAR(cn.imag(), -0.24982639750046153893, 1E-15); + EXPECT_NEAR(dn.imag(), 0.0, 1E-15); + + CJacobiEllipticFunctions::ellPJC(Complex(0.5,0.5), 0.5, sn, cn, dn); + EXPECT_NEAR(sn.real(), 0.55284325098354925032, 1E-15); + EXPECT_NEAR(cn.real(), 0.96941944802337476350, 1E-10);//low precision + EXPECT_NEAR(dn.real(), 0.97703467549246159063, 1E-15); + EXPECT_NEAR(sn.imag(), 0.43032986483620772056, 1E-15); + EXPECT_NEAR(cn.imag(), -0.24540972636400421036, 1E-10);//low precision + EXPECT_NEAR(dn.imag(), -0.12174847394819815483, 1E-15); + + CJacobiEllipticFunctions::ellPJC(Complex(0.2,0.0), 0.99, sn, cn, dn); + EXPECT_NEAR(sn.real(), 0.19738823726686019477, 1E-15); + EXPECT_NEAR(cn.real(), 0.98032539689058428856, 1E-8);//low precision + EXPECT_NEAR(dn.real(), 0.98052409707808552142, 1E-15); + EXPECT_NEAR(sn.imag(), 0.0, 1E-15); + EXPECT_NEAR(cn.imag(), 0.0, 1E-15); + EXPECT_NEAR(dn.imag(), 0.0, 1E-15); + + CJacobiEllipticFunctions::ellPJC(Complex(0.7,0.4), + 0.9999999999999999, sn, cn, dn); + EXPECT_NEAR(sn.real(), 0.66873789889962576005, 1E-15); + EXPECT_NEAR(cn.real(), 0.81197156278765458826, 1E-15); + EXPECT_NEAR(dn.real(), 0.81197156278765469928, 1E-15); + EXPECT_NEAR(sn.imag(), 0.25191557357137611683, 1E-15); + EXPECT_NEAR(cn.imag(), -0.20747708305429035658, 1E-15); + EXPECT_NEAR(dn.imag(), -0.20747708305429032882, 1E-15); + + CJacobiEllipticFunctions::ellPJC(Complex(0.5,0.5), 1.0L-1E-16, sn, cn, dn); + EXPECT_NEAR(sn.real(), 0.56408314126749847794, 1E-15); + EXPECT_NEAR(cn.real(), 0.94997886761549465984, 1E-15); + EXPECT_NEAR(dn.real(), 0.94997886761549465984, 1E-15); + EXPECT_NEAR(sn.imag(), 0.40389645531602574868, 1E-15); + EXPECT_NEAR(cn.imag(), -0.23982763093808803778, 1E-15); + EXPECT_NEAR(dn.imag(), -0.23982763093808801003, 1E-15); +#endif //HAVE_ARPREC +} diff --git a/tests/unit/multiclass/MCLDA_unittest.cc b/tests/unit/multiclass/MCLDA_unittest.cc index 5952721dfec..8a09ec58301 100644 --- a/tests/unit/multiclass/MCLDA_unittest.cc +++ b/tests/unit/multiclass/MCLDA_unittest.cc @@ -3,6 +3,7 @@ #include #include #include +#ifdef HAVE_EIGEN3 #define NUM 50 #define DIMS 2 @@ -37,3 +38,4 @@ TEST(MCLDA, train_and_apply) SG_UNREF(output); SG_UNREF(lda); } +#endif //HAVE_EIGEN3