From 850c6d8a2b908869492ed0627c5906f7eee9c81f Mon Sep 17 00:00:00 2001 From: Gael Guennebaud Date: Sun, 11 Jul 2010 10:58:58 +0200 Subject: [PATCH 01/41] fix unused warning --- Eigen/src/Core/products/GeneralMatrixVector.h | 1 + 1 file changed, 1 insertion(+) diff --git a/Eigen/src/Core/products/GeneralMatrixVector.h b/Eigen/src/Core/products/GeneralMatrixVector.h index 0997746ef..9713b4849 100644 --- a/Eigen/src/Core/products/GeneralMatrixVector.h +++ b/Eigen/src/Core/products/GeneralMatrixVector.h @@ -266,6 +266,7 @@ static EIGEN_DONT_INLINE void ei_cache_friendly_product_rowmajor_times_vector( Scalar* res, Index resIncr, Scalar alpha) { + EIGEN_UNUSED_VARIABLE(rhsIncr); ei_internal_assert(rhsIncr==1); #ifdef _EIGEN_ACCUMULATE_PACKETS #error _EIGEN_ACCUMULATE_PACKETS has already been defined From 19a70ae939911505839358d8e3ba72c51e47b254 Mon Sep 17 00:00:00 2001 From: Gael Guennebaud Date: Sun, 11 Jul 2010 11:01:17 +0200 Subject: [PATCH 02/41] fix doc compilation on non 32bits systems --- .../Tutorial_ReductionsVisitorsBroadcasting_maxnorm.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/doc/examples/Tutorial_ReductionsVisitorsBroadcasting_maxnorm.cpp b/doc/examples/Tutorial_ReductionsVisitorsBroadcasting_maxnorm.cpp index cb46887b6..049c747b0 100644 --- a/doc/examples/Tutorial_ReductionsVisitorsBroadcasting_maxnorm.cpp +++ b/doc/examples/Tutorial_ReductionsVisitorsBroadcasting_maxnorm.cpp @@ -2,13 +2,14 @@ #include using namespace std; +using namespace Eigen; int main() { - Eigen::MatrixXf mat(2,4); + MatrixXf mat(2,4); mat << 1, 2, 6, 9, 3, 1, 7, 2; - int maxIndex; + MatrixXf::Index maxIndex; float maxNorm = mat.colwise().sum().maxCoeff(&maxIndex); std::cout << "Maximum sum at position " << maxIndex << std::endl; From 8e776c94c173e3c8ea7ec32648f8b2f09bf09b37 Mon Sep 17 00:00:00 2001 From: Jitse Niesen Date: Mon, 12 Jul 2010 12:02:31 +0100 Subject: [PATCH 03/41] Tutorial page 1: Put code and output side-by-side. --- doc/C01_TutorialMatrixClass.dox | 47 ++++++++++++++----- .../tut_matrix_coefficient_accessors.cpp | 1 - 2 files changed, 36 insertions(+), 12 deletions(-) diff --git a/doc/C01_TutorialMatrixClass.dox b/doc/C01_TutorialMatrixClass.dox index 27788b2b2..b5d7ec0c7 100644 --- a/doc/C01_TutorialMatrixClass.dox +++ b/doc/C01_TutorialMatrixClass.dox @@ -132,13 +132,15 @@ Vector4d c(5.0, 6.0, 7.0, 8.0); The primary coefficient accessors and mutators in Eigen are the overloaded parenthesis operators. For matrices, the row index is always passed first. For vectors, just pass one index. The numbering starts at 0. This example is self-explanatory: -\include tut_matrix_coefficient_accessors.cpp -Output: \verbinclude tut_matrix_coefficient_accessors.out -Note that the syntax -\code -m(index) -\endcode + +
+Example: \include tut_matrix_coefficient_accessors.cpp + +Output: \verbinclude tut_matrix_coefficient_accessors.out +
+ +Note that the syntax m(index) is not restricted to vectors, it is also available for general matrices, meaning index-based access in the array of coefficients. This however depends on the matrix's storage order. All Eigen matrices default to column-major storage order, but this can be changed to row-major, see \ref TopicStorageOrders "Storage orders". @@ -149,17 +151,29 @@ would make matrix[i,j] compile to the same thing as matrix[j] ! \section TutorialMatrixCommaInitializer Comma-initialization -Matrix and vector coefficients can be conveniently set using the so-called \em comma-initializer syntax. +%Matrix and vector coefficients can be conveniently set using the so-called \em comma-initializer syntax. For now, it is enough to know this example: -\include Tutorial_commainit_01.cpp + + +
+Example: \include Tutorial_commainit_01.cpp + Output: \verbinclude Tutorial_commainit_01.out +
+ + The right-hand side can also contain matrix expressions as discussed in \ref TutorialAdvancedInitialization "this page". \section TutorialMatrixSizesResizing Resizing The current size of a matrix can be retrieved by \link EigenBase::rows() rows()\endlink, \link EigenBase::cols() cols() \endlink and \link EigenBase::size() size()\endlink. These methods return the number of rows, the number of columns and the number of coefficients, respectively. Resizing a dynamic-size matrix is done by the \link DenseStorageBase::resize(Index,Index) resize() \endlink method. -For example: \include tut_matrix_resize.cpp + + +
+Example: \include tut_matrix_resize.cpp + Output: \verbinclude tut_matrix_resize.out +
The resize() method is a no-operation if the actual matrix size doesn't change; otherwise it is destructive: the values of the coefficients may change. If you want a conservative variant of resize() which does not change the coefficients, use \link DenseStorageBase::conservativeResize() conservativeResize()\endlink, see \ref TopicResizing "this page" for more details. @@ -167,14 +181,25 @@ If you want a conservative variant of resize() which does not change the coeffic All these methods are still available on fixed-size matrices, for the sake of API uniformity. Of course, you can't actually resize a fixed-size matrix. Trying to change a fixed size to an actually different value will trigger an assertion failure; but the following code is legal: -\include tut_matrix_resize_fixed_size.cpp + + +
+Example: \include tut_matrix_resize_fixed_size.cpp + Output: \verbinclude tut_matrix_resize_fixed_size.out +
+ \section TutorialMatrixAssignment Assignment and resizing Assignment is the action of copying a matrix into another, using \c operator=. Eigen resizes the matrix on the left-hand side automatically so that it matches the size of the matrix on the right-hand size. For example: -\include tut_matrix_assignment_resizing.cpp + + +
+Example: \include tut_matrix_assignment_resizing.cpp + Output: \verbinclude tut_matrix_assignment_resizing.out +
Of course, if the left-hand side is of fixed size, resizing it is not allowed. diff --git a/doc/examples/tut_matrix_coefficient_accessors.cpp b/doc/examples/tut_matrix_coefficient_accessors.cpp index 6d982b6e1..c2da17158 100644 --- a/doc/examples/tut_matrix_coefficient_accessors.cpp +++ b/doc/examples/tut_matrix_coefficient_accessors.cpp @@ -15,5 +15,4 @@ int main() v(0) = 4; v(1) = v(0) - 1; std::cout << "Here is the vector v:\n" << v << std::endl; - } From 6ba5d2c90c83ba169e51c3b2936636e0a05c3c76 Mon Sep 17 00:00:00 2001 From: Christoph Hertzberg Date: Mon, 12 Jul 2010 23:30:47 +0200 Subject: [PATCH 04/41] Implemented SSE optimized double-precision Quaternion multiplication --- Eigen/src/Geometry/arch/Geometry_SSE.h | 54 ++++++++++++++++++++++++++ 1 file changed, 54 insertions(+) diff --git a/Eigen/src/Geometry/arch/Geometry_SSE.h b/Eigen/src/Geometry/arch/Geometry_SSE.h index 080b87d4b..0078e4aab 100644 --- a/Eigen/src/Geometry/arch/Geometry_SSE.h +++ b/Eigen/src/Geometry/arch/Geometry_SSE.h @@ -64,4 +64,58 @@ struct ei_cross3_impl } }; + + + +template +struct ei_quat_product +{ + inline static Quaternion run(const QuaternionBase& _a, const QuaternionBase& _b) + { + const Packet2d mask = _mm_castsi128_pd(_mm_set_epi32(0x0,0x0,0x80000000,0x0)); + + Quaternion res; + + const double* a = _a.coeffs().data(); + Packet2d b_xy = _b.coeffs().template packet(0); + Packet2d b_zw = _b.coeffs().template packet(2); + Packet2d a_xx = ei_pset1(a[0]); + Packet2d a_yy = ei_pset1(a[1]); + Packet2d a_zz = ei_pset1(a[2]); + Packet2d a_ww = ei_pset1(a[3]); + + // two temporaries: + Packet2d t1, t2; + + /* + * t1 = ww*xy + yy*zw + * t2 = zz*xy - xx*zw + * res.xy = t1 +/- swap(t2) + */ + t1 = ei_padd(ei_pmul(a_ww, b_xy), ei_pmul(a_yy, b_zw)); + t2 = ei_psub(ei_pmul(a_zz, b_xy), ei_pmul(a_xx, b_zw)); +#ifdef __SSE3__ + ei_pstore(&res.x(), _mm_addsub_pd(t1, ei_preverse(t2))); +#else + ei_pstore(&res.x(), ei_padd(t1, ei_pxor(mask,ei_preverse(t2)))); +#endif + + /* + * t1 = ww*zw - yy*xy + * t2 = zz*zw + xx*xy + * res.zw = t1 -/+ swap(t2) = swap( swap(t1) +/- t2) + */ + t1 = ei_psub(ei_pmul(a_ww, b_zw), ei_pmul(a_yy, b_xy)); + t2 = ei_padd(ei_pmul(a_zz, b_zw), ei_pmul(a_xx, b_xy)); +#ifdef __SSE3__ + ei_pstore(&res.z(), ei_preverse(_mm_addsub_pd(ei_preverse(t1), t2))); +#else + ei_pstore(&res.z(), ei_psub(t1, ei_pxor(mask,ei_preverse(t2)))); +#endif + + return res; +} +}; + + #endif // EIGEN_GEOMETRY_SSE_H From 140ad0908d9646c3c44dfe65ee4274c12c324770 Mon Sep 17 00:00:00 2001 From: Jitse Niesen Date: Mon, 12 Jul 2010 22:45:57 +0100 Subject: [PATCH 05/41] Tutorial page 3: add more cwise operations, condense rest. --- doc/C03_TutorialArrayClass.dox | 143 +++++++++++------- .../Tutorial_ArrayClass_accessors.cpp | 8 +- doc/examples/Tutorial_ArrayClass_addition.cpp | 9 +- .../Tutorial_ArrayClass_addition_scalar.cpp | 17 --- .../Tutorial_ArrayClass_cwise_other.cpp | 19 +++ doc/examples/Tutorial_ArrayClass_interop.cpp | 20 +-- .../Tutorial_ArrayClass_interop_array.cpp | 34 ----- .../Tutorial_ArrayClass_interop_matrix.cpp | 25 +-- doc/examples/Tutorial_ArrayClass_mult.cpp | 6 +- 9 files changed, 121 insertions(+), 160 deletions(-) delete mode 100644 doc/examples/Tutorial_ArrayClass_addition_scalar.cpp create mode 100644 doc/examples/Tutorial_ArrayClass_cwise_other.cpp delete mode 100644 doc/examples/Tutorial_ArrayClass_interop_array.cpp diff --git a/doc/C03_TutorialArrayClass.dox b/doc/C03_TutorialArrayClass.dox index 0828bf39b..92bcebe9d 100644 --- a/doc/C03_TutorialArrayClass.dox +++ b/doc/C03_TutorialArrayClass.dox @@ -7,7 +7,7 @@ namespace Eigen { \li \b Next: \ref TutorialBlockOperations This tutorial aims to provide an overview and explanations on how to use -Eigen's \link ArrayBase Array \endlink class +Eigen's Array class. \b Table \b of \b contents - \ref TutorialArrayClassIntro @@ -15,6 +15,7 @@ Eigen's \link ArrayBase Array \endlink class - \ref TutorialArrayClassAccess - \ref TutorialArrayClassAddSub - \ref TutorialArrayClassMult + - \ref TutorialArrayClassCwiseOther - \ref TutorialArrayClassConvert \section TutorialArrayClassIntro What is the Array class? @@ -27,17 +28,17 @@ such as adding a constant to every coefficient in the array or multiplying two a \section TutorialArrayClassTypes Array types Array is a class template taking the same template parameters as Matrix. -As with Matrix, the first 3 template parameters are mandatory: +As with Matrix, the first three template parameters are mandatory: \code Array \endcode -And the last 3 template parameters are optional. Since this is exactly the same as for Matrix, -we won't reexplain it and just refer to \ref TutorialMatrixClass "this page". +The last three template parameters are optional. Since this is exactly the same as for Matrix, +we won't explain it again here and just refer to \ref TutorialMatrixClass. Eigen also provides typedefs for some common cases, in a way that is similar to the Matrix typedefs but with some slight differences, as the word "array" is used for both 1-dimensional and 2-dimensional arrays. We adopt that convention that typedefs of the form ArrayNt stand for 1-dimensional arrays, where N and t are -as in the Matrix typedefs explained on \ref TutorialMatrixClass "this page". For 2-dimensional arrays, we +the size and the scalar type, as in the Matrix typedefs explained on \ref TutorialMatrixClass "this page". For 2-dimensional arrays, we use typedefs of the form ArrayNNt. Some examples are shown in the following table: @@ -71,69 +72,103 @@ use typedefs of the form ArrayNNt. Some examples are shown in the following tabl \section TutorialArrayClassAccess Accessing values inside an Array -Write and read access to coefficients of an array expression is done in the same way as with matrix expressions. -For example: -\include Tutorial_ArrayClass_accessors.cpp -Output: -\verbinclude Tutorial_ArrayClass_accessors.out +The parenthesis operator is overloaded to provide write and read access to the coefficients of an array, just as with matrices. +Furthermore, the \c << operator can be used to initialize arrays (via the comma initializer) or to print them. -For more information about the comma initializer, refer to \ref TutorialAdvancedInitialization "this page". +
+
+Example: \include Tutorial_ArrayClass_accessors.cpp + +Output: \verbinclude Tutorial_ArrayClass_accessors.out +
+ +For more information about the comma initializer, see \ref TutorialAdvancedInitialization. -\section TutorialArrayClassAddSub Addition and substraction +\section TutorialArrayClassAddSub Addition and subtraction + +Adding and subtracting two arrays is the same as for matrices. +The operation is valid if both arrays have the same size, and the addition or subtraction is done coefficient-wise. + +Arrays also support expressions of the form array + scalar which add a scalar to each coefficient in the array. +This provides a functionality that is not directly available for Matrix objects. + + +
+Example: \include Tutorial_ArrayClass_addition.cpp + +Output: \verbinclude Tutorial_ArrayClass_addition.out +
-Adding and substracting two arrays has the same result as for Matrices. -This is valid as long as both arrays have the same sizes: - -\include Tutorial_ArrayClass_addition.cpp -Output: -\verbinclude Tutorial_ArrayClass_addition.out - -It is also allowed to add a scalar to each coefficient in an Array, -providing a functionality that was not available for Matrix objects: - -\include Tutorial_ArrayClass_addition_scalar.cpp -Output: -\verbinclude Tutorial_ArrayClass_addition_scalar.out - - -\subsection TutorialArrayClassMult Array multiplication +\section TutorialArrayClassMult Array multiplication First of all, of course you can multiply an array by a scalar, this works in the same way as matrices. Where arrays -are fundamentally different from matrices, is when you multiply two arrays together. While Matrices interprete -multiplication as matrix product, arrays interprete multiplication as coefficient-wise product. For example: +are fundamentally different from matrices, is when you multiply two together. Matrices interpret +multiplication as the matrix product and arrays interpret multiplication as the coefficient-wise product. Thus, two +arrays can be multiplied if they have the same size. -\include Tutorial_ArrayClass_mult.cpp -Output: -\verbinclude Tutorial_ArrayClass_mult.out + +
+Example: \include Tutorial_ArrayClass_mult.cpp + +Output: \verbinclude Tutorial_ArrayClass_mult.out +
+\section TutorialArrayClassCwiseOther Other coefficient-wise operations + +The Array class defined other coefficient-wise operations besides the addition, subtraction and multiplication +operators described about. For example, the \link ArrayBase::abs() .abs() \endlink method takes the absolute +value of each coefficient, while \link ArrayBase::sqrt() .sqrt() \endlink computes the square root of the +coefficients. If you have two arrays of the same size, you can call \link ArrayBase::min() .min() \endlink to +construct the array whose coefficients are the minimum of the corresponding coefficients of the two given +arrays. These operations are illustrated in the following example. + + +
+Example: \include Tutorial_ArrayClass_cwise_other.cpp + +Output: \verbinclude Tutorial_ArrayClass_cwise_other.out +
+ +More coefficient-wise operations can be found in the \ref QuickRefPage. + \section TutorialArrayClassConvert Converting between array and matrix expressions -It is possible to wrap a matrix expression as an array expression and conversely. This gives access to all operations -regardless of the choice of declaring objects as arrays or as matrices. +When should you use objects of the Matrix class and when should you use objects of the Array class? You cannot +apply Matrix operations on arrays, or Array operations on matrices. Thus, if you need to do linear algebraic +operations such as matrix multiplication, then you should use matrices; if you need to do coefficient-wise +operations, then you should use arrays. However, sometimes it is not that simple, but you need to use both +Matrix and Array operations. In that case, you need to convert a matrix to an array or reversely. This gives +access to all operations regardless of the choice of declaring objects as arrays or as matrices. -\link MatrixBase Matrix expressions \endlink have a \link MatrixBase::array() .array() \endlink method that -'converts' them into \link ArrayBase array expressions \endlink, so that coefficient-wise operations +\link MatrixBase Matrix expressions \endlink have an \link MatrixBase::array() .array() \endlink method that +'converts' them into \link ArrayBase array expressions\endlink, so that coefficient-wise operations can be applied easily. Conversely, \link ArrayBase array expressions \endlink have a \link ArrayBase::matrix() .matrix() \endlink method. As with all Eigen expression abstractions, this doesn't have any runtime cost (provided that you let your compiler optimize). - Both \link MatrixBase::array() .array() \endlink and \link ArrayBase::matrix() .matrix() \endlink can be used as rvalues and as lvalues. -Mixing matrices and arrays in an expression is forbidden with Eigen. However, +Mixing matrices and arrays in an expression is forbidden with Eigen. For instance, you cannot add a amtrix and +array directly; the operands of a \c + operator should either both be matrices or both be arrays. However, it is easy to convert from one to the other with \link MatrixBase::array() .array() \endlink and -\link ArrayBase::matrix() .matrix() \endlink. +\link ArrayBase::matrix() .matrix()\endlink. The exception to this rule is the assignment operator: it is +allowed to assign a matrix expression to an array variable, or to assign an array expression to a matrix +variable. -On the other hand, assigning a matrix (resp. array) expression to an array (resp. matrix) expression is allowed. +The following example shows how to use array operations on a Matrix object by employing the +\link MatrixBase::array() .array() \endlink method. For example, the statement +result = m.array() * n.array() takes two matrices \c m and \c n, converts them both to an array, uses +* to multiply them coefficient-wise and assigns the result to the matrix variable \c result (this is legal +because Eigen allows assigning array expressions to matrix variables). -\subsection TutorialArrayClassInteropMatrix Matrix to array example -The following example shows how to use array operations on a Matrix object by employing -the \link MatrixBase::array() .array() \endlink method: +As a matter of fact, this usage case is so common that Eigen provides a \link MatrixBase::cwiseProduct() +.cwiseProduct() \endlink method for matrices to compute the coefficient-wise product. This is also shown in +the example program.
\include Tutorial_ArrayClass_interop_matrix.cpp @@ -143,21 +178,13 @@ Output: \verbinclude Tutorial_ArrayClass_interop_matrix.out
+Similarly, if \c array1 and \c array2 are arrays, then the expression array1.matrix() * array2.matrix() +computes their matrix product. -\subsection TutorialArrayClassInteropArray Array to matrix example -The following example shows how to use matrix operations with an Array -object by employing the \link ArrayBase::matrix() .matrix() \endlink method: - - -
-\include Tutorial_ArrayClass_interop_array.cpp - -Output: -\verbinclude Tutorial_ArrayClass_interop_array.out -
- -\subsection TutorialArrayClassInteropCombination Example with combinations of .array() and .matrix() -Here is a more advanced example: +Here is a more advanced example. The expression (m.array() + 4).matrix() * m adds 4 to every +coefficient in the matrix \c m and then computes the matrix product of the result with \c m. Similarly, the +expression (m.array() * n.array()).matrix() * m computes the coefficient-wise product of the matrices +\c m and \c n and then the matrix product of the result with \c m.
\include Tutorial_ArrayClass_interop.cpp diff --git a/doc/examples/Tutorial_ArrayClass_accessors.cpp b/doc/examples/Tutorial_ArrayClass_accessors.cpp index 812ba61a4..dc720ff58 100644 --- a/doc/examples/Tutorial_ArrayClass_accessors.cpp +++ b/doc/examples/Tutorial_ArrayClass_accessors.cpp @@ -8,17 +8,17 @@ int main() { ArrayXXf m(2,2); - //assign some values coefficient by coefficient + // assign some values coefficient by coefficient m(0,0) = 1.0; m(0,1) = 2.0; - m(1,0) = 3.0; m(1,1) = 4.0; + m(1,0) = 3.0; m(1,1) = m(0,1) + m(1,0); - //print values to standard output + // print values to standard output cout << m << endl << endl; // using the comma-initializer is also allowed m << 1.0,2.0, 3.0,4.0; - //print values to standard output + // print values to standard output cout << m << endl; } diff --git a/doc/examples/Tutorial_ArrayClass_addition.cpp b/doc/examples/Tutorial_ArrayClass_addition.cpp index eae1957bd..480ffb00f 100644 --- a/doc/examples/Tutorial_ArrayClass_addition.cpp +++ b/doc/examples/Tutorial_ArrayClass_addition.cpp @@ -8,15 +8,16 @@ int main() { ArrayXXf a(3,3); ArrayXXf b(3,3); - a << 1,2,3, 4,5,6, 7,8,9; - b << 1,2,3, 1,2,3, 1,2,3; - cout << "a + b = " << endl - << a + b << endl; + // Adding two arrays + cout << "a + b = " << endl << a + b << endl << endl; + + // Subtracting a scalar from an array + cout << "a - 2 = " << endl << a - 2 << endl; } diff --git a/doc/examples/Tutorial_ArrayClass_addition_scalar.cpp b/doc/examples/Tutorial_ArrayClass_addition_scalar.cpp deleted file mode 100644 index 1c2665287..000000000 --- a/doc/examples/Tutorial_ArrayClass_addition_scalar.cpp +++ /dev/null @@ -1,17 +0,0 @@ -#include -#include - -using namespace Eigen; -using namespace std; - -int main() -{ - ArrayXXf a(3,3); - - a << 1,2,3, - 4,5,6, - 7,8,9; - - cout << "a + 2 = " << endl - << a + 2 << endl; -} diff --git a/doc/examples/Tutorial_ArrayClass_cwise_other.cpp b/doc/examples/Tutorial_ArrayClass_cwise_other.cpp new file mode 100644 index 000000000..d9046c63d --- /dev/null +++ b/doc/examples/Tutorial_ArrayClass_cwise_other.cpp @@ -0,0 +1,19 @@ +#include +#include + +using namespace Eigen; +using namespace std; + +int main() +{ + ArrayXf a = ArrayXf::Random(5); + a *= 2; + cout << "a =" << endl + << a << endl; + cout << "a.abs() =" << endl + << a.abs() << endl; + cout << "a.abs().sqrt() =" << endl + << a.abs().sqrt() << endl; + cout << "a.min(a.abs().sqrt()) =" << endl + << a.min(a.abs().sqrt()) << endl; +} diff --git a/doc/examples/Tutorial_ArrayClass_interop.cpp b/doc/examples/Tutorial_ArrayClass_interop.cpp index 72ac5d307..371f07068 100644 --- a/doc/examples/Tutorial_ArrayClass_interop.cpp +++ b/doc/examples/Tutorial_ArrayClass_interop.cpp @@ -8,31 +8,15 @@ int main() { MatrixXf m(2,2); MatrixXf n(2,2); - MatrixXf result(2,2); - //initialize matrices m << 1,2, 3,4; - n << 5,6, 7,8; - // mix of array and matrix operations - // first coefficient-wise addition - // then the result is used with matrix multiplication result = (m.array() + 4).matrix() * m; - - cout << "-- Combination 1: --" << endl - << result << endl << endl; - - - // mix of array and matrix operations - // first coefficient-wise multiplication - // then the result is used with matrix multiplication + cout << "-- Combination 1: --" << endl << result << endl << endl; result = (m.array() * n.array()).matrix() * m; - - cout << "-- Combination 2: --" << endl - << result << endl << endl; - + cout << "-- Combination 2: --" << endl << result << endl << endl; } diff --git a/doc/examples/Tutorial_ArrayClass_interop_array.cpp b/doc/examples/Tutorial_ArrayClass_interop_array.cpp deleted file mode 100644 index c2cb6bf3f..000000000 --- a/doc/examples/Tutorial_ArrayClass_interop_array.cpp +++ /dev/null @@ -1,34 +0,0 @@ -#include -#include - -using namespace Eigen; -using namespace std; - -int main() -{ - ArrayXXf m(2,2); - ArrayXXf n(2,2); - - ArrayXXf result(2,2); - - //initialize arrays - m << 1,2, - 3,4; - - n << 5,6, - 7,8; - - - // --> array multiplication - result = m * n; - - cout << "-- Array m*n: --" << endl - << result << endl << endl; - - - // --> Matrix multiplication - result = m.matrix() * n.matrix(); - - cout << "-- Matrix m*n: --" << endl - << result << endl << endl; -} diff --git a/doc/examples/Tutorial_ArrayClass_interop_matrix.cpp b/doc/examples/Tutorial_ArrayClass_interop_matrix.cpp index b3d48b6ae..101427511 100644 --- a/doc/examples/Tutorial_ArrayClass_interop_matrix.cpp +++ b/doc/examples/Tutorial_ArrayClass_interop_matrix.cpp @@ -8,34 +8,19 @@ int main() { MatrixXf m(2,2); MatrixXf n(2,2); - MatrixXf result(2,2); - //initialize matrices m << 1,2, 3,4; - n << 5,6, 7,8; - - // --> matrix multiplication result = m * n; - - cout << "-- Matrix m*n: --" << endl - << result << endl << endl; - - - // --> coeff-wise multiplication + cout << "-- Matrix m*n: --" << endl << result << endl << endl; result = m.array() * n.array(); - - cout << "-- Array m*n: --" << endl - << result << endl << endl; - - - // ->> coeff-wise addition of a scalar + cout << "-- Array m*n: --" << endl << result << endl << endl; + result = m.cwiseProduct(n); + cout << "-- With cwiseProduct: --" << endl << result << endl << endl; result = m.array() + 4; - - cout << "-- Array m + 4: --" << endl - << result << endl << endl; + cout << "-- Array m + 4: --" << endl << result << endl << endl; } diff --git a/doc/examples/Tutorial_ArrayClass_mult.cpp b/doc/examples/Tutorial_ArrayClass_mult.cpp index 27c83e040..6cb439ff7 100644 --- a/doc/examples/Tutorial_ArrayClass_mult.cpp +++ b/doc/examples/Tutorial_ArrayClass_mult.cpp @@ -8,13 +8,9 @@ int main() { ArrayXXf a(2,2); ArrayXXf b(2,2); - a << 1,2, 3,4; - b << 5,6, 7,8; - - cout << "a * b = " << endl - << a * b << endl; + cout << "a * b = " << endl << a * b << endl; } From c36316f2845287b913b303641479aef45b14c3fe Mon Sep 17 00:00:00 2001 From: Jitse Niesen Date: Tue, 13 Jul 2010 10:14:58 +0100 Subject: [PATCH 06/41] Change EXPAND_AS_DEFINED doxygen configuration option. Add macros so that MatrixBase::cwiseProduct() and ArrayBase::min() are documented, and remove one macro which is no longer used. --- doc/Doxyfile.in | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/doc/Doxyfile.in b/doc/Doxyfile.in index da5d291f9..091ce5639 100644 --- a/doc/Doxyfile.in +++ b/doc/Doxyfile.in @@ -1217,12 +1217,14 @@ PREDEFINED = EIGEN_EMPTY_STRUCT \ # The macro definition that is found in the sources will be used. # Use the PREDEFINED tag if you want to use a different macro definition. -EXPAND_AS_DEFINED = EIGEN_MAKE_SCALAR_OPS \ - EIGEN_MAKE_TYPEDEFS \ +EXPAND_AS_DEFINED = EIGEN_MAKE_TYPEDEFS \ EIGEN_MAKE_FIXED_TYPEDEFS \ EIGEN_MAKE_TYPEDEFS_ALL_SIZES \ + EIGEN_MAKE_CWISE_BINARY_OP \ EIGEN_CWISE_UNOP_RETURN_TYPE \ EIGEN_CWISE_BINOP_RETURN_TYPE \ + EIGEN_CWISE_PRODUCT_RETURN_TYPE \ + EIGEN_CURRENT_STORAGE_BASE_CLASS \ _EIGEN_GENERIC_PUBLIC_INTERFACE # If the SKIP_FUNCTION_MACROS tag is set to YES (the default) then From e4f3759c4daca39545cb5efb26e08c94efbd9ee0 Mon Sep 17 00:00:00 2001 From: Gael Guennebaud Date: Tue, 13 Jul 2010 13:29:35 +0200 Subject: [PATCH 07/41] add a bench for quaternion multiplication --- bench/quatmul.cpp | 47 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 47 insertions(+) create mode 100644 bench/quatmul.cpp diff --git a/bench/quatmul.cpp b/bench/quatmul.cpp new file mode 100644 index 000000000..d91a4b01b --- /dev/null +++ b/bench/quatmul.cpp @@ -0,0 +1,47 @@ +#include +#include +#include +#include + +using namespace Eigen; + +template +EIGEN_DONT_INLINE void quatmul_default(const Quat& a, const Quat& b, Quat& c) +{ + c = a * b; +} + +template +EIGEN_DONT_INLINE void quatmul_novec(const Quat& a, const Quat& b, Quat& c) +{ + c = ei_quat_product<0, Quat, Quat, typename Quat::Scalar, Aligned>::run(a,b); +} + +template void bench(const std::string& label) +{ + int tries = 10; + int rep = 1000000; + BenchTimer t; + + Quat a(4, 1, 2, 3); + Quat b(2, 3, 4, 5); + Quat c; + + std::cout.precision(3); + + BENCH(t, tries, rep, quatmul_default(a,b,c)); + std::cout << label << " default " << 1e3*t.best(CPU_TIMER) << "ms \t" << 1e-6*double(rep)/(t.best(CPU_TIMER)) << " M mul/s\n"; + + BENCH(t, tries, rep, quatmul_novec(a,b,c)); + std::cout << label << " novec " << 1e3*t.best(CPU_TIMER) << "ms \t" << 1e-6*double(rep)/(t.best(CPU_TIMER)) << " M mul/s\n"; +} + +int main() +{ + bench("float "); + bench("double"); + + return 0; + +} + From b0bd1cfa059983925456630c02fbaf0a76db8aae Mon Sep 17 00:00:00 2001 From: Jitse Niesen Date: Wed, 14 Jul 2010 10:16:12 +0100 Subject: [PATCH 08/41] Tutorial page 4: add some text, diversify examples. Use \verbinclude for output text to disable syntax highlighting. Give tables consistent look. --- doc/C02_TutorialMatrixArithmetic.dox | 18 +- doc/C04_TutorialBlockOperations.dox | 195 ++++++++---------- ...TutorialReductionsVisitorsBroadcasting.dox | 2 +- ...orial_BlockOperations_block_assignment.cpp | 23 +-- .../Tutorial_BlockOperations_colrow.cpp | 11 +- .../Tutorial_BlockOperations_corner.cpp | 20 +- .../Tutorial_BlockOperations_print_block.cpp | 20 +- .../Tutorial_BlockOperations_vector.cpp | 20 +- 8 files changed, 127 insertions(+), 182 deletions(-) diff --git a/doc/C02_TutorialMatrixArithmetic.dox b/doc/C02_TutorialMatrixArithmetic.dox index df2360d40..d076c8048 100644 --- a/doc/C02_TutorialMatrixArithmetic.dox +++ b/doc/C02_TutorialMatrixArithmetic.dox @@ -43,7 +43,7 @@ also have the same \c Scalar type, as Eigen doesn't do automatic type promotion. Example: \include tut_arithmetic_add_sub.cpp -Output: \include tut_arithmetic_add_sub.out +Output: \verbinclude tut_arithmetic_add_sub.out
\section TutorialArithmeticScalarMulDiv Scalar multiplication and division @@ -59,7 +59,7 @@ Multiplication and division by a scalar is very simple too. The operators at han Example: \include tut_arithmetic_scalar_mul_div.cpp -Output: \include tut_arithmetic_scalar_mul_div.out +Output: \verbinclude tut_arithmetic_scalar_mul_div.out @@ -93,7 +93,7 @@ The transpose \f$ a^T \f$, conjugate \f$ \bar{a} \f$, and adjoint (i.e., conjuga Example: \include tut_arithmetic_transpose_conjugate.cpp -Output: \include tut_arithmetic_transpose_conjugate.out +Output: \verbinclude tut_arithmetic_transpose_conjugate.out For real matrices, \c conjugate() is a no-operation, and so \c adjoint() is 100% equivalent to \c transpose(). @@ -103,7 +103,7 @@ As for basic arithmetic operators, \c transpose() and \c adjoint() simply return Example: \include tut_arithmetic_transpose_aliasing.cpp -Output: \include tut_arithmetic_transpose_aliasing.out +Output: \verbinclude tut_arithmetic_transpose_aliasing.out This is the so-called \ref TopicAliasing "aliasing issue". In "debug mode", i.e., when \ref TopicAssertions "assertions" have not been disabled, such common pitfalls are automatically detected. @@ -112,7 +112,7 @@ For \em in-place transposition, as for instance in a = a.transpose(), s Example: \include tut_arithmetic_transpose_inplace.cpp -Output: \include tut_arithmetic_transpose_inplace.out +Output: \verbinclude tut_arithmetic_transpose_inplace.out There is also the \link MatrixBase::adjointInPlace() adjointInPlace()\endlink function for complex matrices. @@ -129,7 +129,7 @@ two operators: Example: \include tut_arithmetic_matrix_mul.cpp -Output: \include tut_arithmetic_matrix_mul.out +Output: \verbinclude tut_arithmetic_matrix_mul.out Note: if you read the above paragraph on expression templates and are worried that doing \c m=m*m might cause @@ -154,7 +154,7 @@ The above-discussed \c operator* cannot be used to compute dot and cross product Example: \include tut_arithmetic_dot_cross.cpp -Output: \include tut_arithmetic_dot_cross.out +Output: \verbinclude tut_arithmetic_dot_cross.out Remember that cross product is only for vectors of size 3. Dot product is for vectors of any sizes. @@ -168,7 +168,7 @@ Eigen also provides some reduction operations to reduce a given matrix or vector Example: \include tut_arithmetic_redux_basic.cpp -Output: \include tut_arithmetic_redux_basic.out +Output: \verbinclude tut_arithmetic_redux_basic.out The \em trace of a matrix, as returned by the function \link MatrixBase::trace() trace()\endlink, is the sum of the diagonal coefficients and can also be computed as efficiently using a.diagonal().sum(), as we will see later on. @@ -179,7 +179,7 @@ There also exist variants of the \c minCoeff and \c maxCoeff functions returning Example: \include tut_arithmetic_redux_minmax.cpp -Output: \include tut_arithmetic_redux_minmax.out +Output: \verbinclude tut_arithmetic_redux_minmax.out diff --git a/doc/C04_TutorialBlockOperations.dox b/doc/C04_TutorialBlockOperations.dox index 70773a463..b45cbfbc8 100644 --- a/doc/C04_TutorialBlockOperations.dox +++ b/doc/C04_TutorialBlockOperations.dox @@ -13,21 +13,22 @@ provided that you let your compiler optimize. \b Table \b of \b contents - \ref TutorialBlockOperationsUsing - - \ref TutorialBlockOperationsSyntax - - \ref TutorialBlockOperationsSyntaxColumnRows - - \ref TutorialBlockOperationsSyntaxCorners + - \ref TutorialBlockOperationsSyntaxColumnRows + - \ref TutorialBlockOperationsSyntaxCorners + - \ref TutorialBlockOperationsSyntaxVectors + \section TutorialBlockOperationsUsing Using block operations The most general block operation in Eigen is called \link DenseBase::block() .block() \endlink. -This function returns a block of size (p,q) whose origin is at (i,j) by using -the following syntax: +This function returns a block of size (p,q) whose origin is at (i,j). +There are two versions, whose syntax is as follows: - - + + - +
\b Block \b operationDefault \b version
\b %Block \b operationDefault version Optimized version when the
size is known at compile time
Block of size (p,q), starting at (i,j)
%Block of size (p,q), starting at (i,j) \code matrix.block(i,j,p,q);\endcode \code @@ -35,7 +36,15 @@ matrix.block(i,j);\endcode
-Therefore, if we want to print the values of a block inside a matrix we can simply write: +The default version is a method which takes four arguments. It can always be used. The optimized version +takes two template arguments (the size of the block) and two normal arguments (the position of the block). +It can only be used if the size of the block is known at compile time, but it may be faster than the +non-optimized version, especially if the size of the block is small. Both versions can be used on fixed-size +and dynamic-size matrices and arrays. + +The following program uses the default and optimized versions to print the values of several blocks inside a +matrix. + @@ -44,10 +53,15 @@ Output: \verbinclude Tutorial_BlockOperations_print_block.out
\include Tutorial_BlockOperations_print_block.cpp
+In the above example the \link DenseBase::block() .block() \endlink function was employed +to read the values inside matrix \p m . However, blocks can also be used as lvalues, meaning that you can +assign to a block. -In the previous example the \link DenseBase::block() .block() \endlink function was employed -to read the values inside matrix \p m . Blocks can also be used to perform operations and -assignments within matrices or arrays of different size: +This is illustrated in the following example, which uses arrays instead of matrices. The coefficients of the +5-by-5 array \c n are first all set to 0.6, but then the 3-by-3 block in the middle is set to the values in +\c m . The penultimate line shows that blocks can be combined with matrices and arrays to create more complex +expressions. Blocks of an array are an array expression, and thus the multiplication here is coefficient-wise +multiplication.
\include Tutorial_BlockOperations_block_assignment.cpp @@ -57,55 +71,38 @@ Output: \verbinclude Tutorial_BlockOperations_block_assignment.out
+The \link DenseBase::block() .block() \endlink method is used for general block operations, but there are +other methods for special cases. These are described in the rest of this page. -Blocks can also be combined with matrices and arrays to create more complex expressions: -\code - MatrixXf m(3,3), n(2,2); - MatrixXf p(3,3); - - m.block(0,0,2,2) = m.block(0,0,2,2) * n + p.block(1,1,2,2); -\endcode +\section TutorialBlockOperationsSyntaxColumnRows Columns and rows -It is important to point out that \link DenseBase::block() .block() \endlink is the -general case for a block operation but there are many other useful block operations, -as described in the next section. - -\section TutorialBlockOperationsSyntax Block operation syntax -The following tables show a summary of Eigen's block operations and how they are applied to -fixed- and dynamic-sized Eigen objects. - -\subsection TutorialBlockOperationsSyntaxColumnRows Columns and rows -Other extremely useful block operations are \link DenseBase::col() .col() \endlink and -\link DenseBase::row() .row() \endlink which provide access to a -specific row or column. This is a special case in the sense that the syntax for fixed- and -dynamic-sized objects is exactly the same: +Individual columns and rows are special cases of blocks. Eigen provides methods to easily access them: +\link DenseBase::col() .col() \endlink and \link DenseBase::row() .row()\endlink. There is no syntax variant +for an optimized version. - + +matrix.row(i);\endcode +matrix.row(i);\endcode +matrix.col(j);\endcode +matrix.col(j);\endcode
\b Block \b operation
\b %Block \b operation Default version Optimized version when the
size is known at compile time
ith row \link DenseBase::row() * \endlink \code -MatrixXf m; -std::cout << m.row(i);\endcode \code -Matrix3f m; -std::cout << m.row(i);\endcode
jth column \link DenseBase::col() * \endlink \code -MatrixXf m; -std::cout << m.col(j);\endcode \code -Matrix3f m; -std::cout << m.col(j);\endcode
-A simple example demonstrating these feature follows: +The argument for \p col() and \p row() is the index of the column or row to be accessed, starting at +0. Therefore, \p col(0) will access the first column and \p col(1) the second one.
C++ code: @@ -113,94 +110,83 @@ C++ code: Output: -\include Tutorial_BlockOperations_colrow.out +\verbinclude Tutorial_BlockOperations_colrow.out
-\b NOTE: the argument for \p col() and \p row() is the index of the column or row to be accessed, -starting at 0. Therefore, \p col(0) will access the first column and \p col(1) the second one. +\section TutorialBlockOperationsSyntaxCorners Corner-related operations +Eigen also provides special methods for blocks that are flushed against one of the corners or sides of a +matrix or array. For instance, \link DenseBase::topLeftCorner() .topLeftCorner() \endlink can be used to refer +to a block in the top-left corner of a matrix. Use matrix.topLeftCorner(p,q) to access the block +consisting of the coefficients matrix(i,j) with \c i < \c p and \c j < \c q. As an other +example, blocks consisting of whole rows flushed against the top side of the matrix can be accessed by +\link DenseBase::topRows() .topRows() \endlink. + +The different possibilities are summarized in the following table: -\subsection TutorialBlockOperationsSyntaxCorners Corner-related operations - + +matrix.topLeftCorner(p,q);\endcode +matrix.topLeftCorner();\endcode +matrix.bottomLeftCorner(p,q);\endcode +matrix.bottomLeftCorner();\endcode +matrix.topRightCorner(p,q);\endcode +matrix.topRightCorner();\endcode +matrix.bottomRightCorner(p,q);\endcode +matrix.bottomRightCorner();\endcode - +matrix.topRows(q);\endcode +matrix.topRows();\endcode - +matrix.bottomRows(q);\endcode +matrix.bottomRows();\endcode - +matrix.leftCols(p);\endcode +matrix.leftCols

();\endcode

- +matrix.rightCols(q);\endcode +matrix.rightCols();\endcode
\b Block \b operation
\b %Block \b operation Default version Optimized version when the
size is known at compile time
Top-left p by q block \link DenseBase::topLeftCorner() * \endlink \code -MatrixXf m; -std::cout << m.topLeftCorner(p,q);\endcode \code -Matrix3f m; -std::cout << m.topLeftCorner();\endcode
Bottom-left p by q block \link DenseBase::bottomLeftCorner() * \endlink \code -MatrixXf m; -std::cout << m.bottomLeftCorner(p,q);\endcode \code -Matrix3f m; -std::cout << m.bottomLeftCorner();\endcode
Top-right p by q block \link DenseBase::topRightCorner() * \endlink \code -MatrixXf m; -std::cout << m.topRightCorner(p,q);\endcode \code -Matrix3f m; -std::cout << m.topRightCorner();\endcode
Bottom-right p by q block \link DenseBase::bottomRightCorner() * \endlink \code -MatrixXf m; -std::cout << m.bottomRightCorner(p,q);\endcode \code -Matrix3f m; -std::cout << m.bottomRightCorner();\endcode
Block containing the first q rows +
%Block containing the first q rows \link DenseBase::topRows() * \endlink \code -MatrixXf m; -std::cout << m.topRows(q);\endcode \code -Matrix3f m; -std::cout << m.topRows();\endcode
Block containing the last q rows +
%Block containing the last q rows \link DenseBase::bottomRows() * \endlink \code -MatrixXf m; -std::cout << m.bottomRows(q);\endcode \code -Matrix3f m; -std::cout << m.bottomRows();\endcode
Block containing the first p columns +
%Block containing the first p columns \link DenseBase::leftCols() * \endlink \code -MatrixXf m; -std::cout << m.leftCols(p);\endcode \code -Matrix3f m; -std::cout << m.leftCols

();\endcode

Block containing the last q columns +
%Block containing the last q columns \link DenseBase::rightCols() * \endlink \code -MatrixXf m; -std::cout << m.rightCols(q);\endcode \code -Matrix3f m; -std::cout << m.rightCols();\endcode
- -Here is a simple example showing the power of the operations presented above: +Here is a simple example illustrating the use of the operations presented above:
C++ code: @@ -208,49 +194,38 @@ C++ code: Output: -\include Tutorial_BlockOperations_corner.out +\verbinclude Tutorial_BlockOperations_corner.out
+\section TutorialBlockOperationsSyntaxVectors Block operations for vectors - - - - - -\subsection TutorialBlockOperationsSyntaxVectors Block operations for vectors -Eigen also provides a set of block operations designed specifically for vectors: +Eigen also provides a set of block operations designed specifically for vectors and one-dimensional arrays: - + - +vector.head(n);\endcode +vector.head();\endcode - +vector.tail(n);\endcode +vector.tail();\endcode - +vector.segment(i,n);\endcode +vector.segment(i);\endcode
\b Block \b operation
\b %Block \b operation Default version Optimized version when the
size is known at compile time
Block containing the first \p n elements +
%Block containing the first \p n elements \link DenseBase::head() * \endlink \code -VectorXf v; -std::cout << v.head(n);\endcode \code -Vector3f v; -std::cout << v.head();\endcode
Block containing the last \p n elements +
%Block containing the last \p n elements \link DenseBase::tail() * \endlink \code -VectorXf v; -std::cout << v.tail(n);\endcode \code -Vector3f m; -std::cout << v.tail();\endcode
Block containing \p n elements, starting at position \p i +
%Block containing \p n elements, starting at position \p i \link DenseBase::segment() * \endlink \code -VectorXf v; -std::cout << v.segment(i,n);\endcode \code -Vector3f m; -std::cout << v.segment(i);\endcode
@@ -262,7 +237,7 @@ C++ code: Output: -\include Tutorial_BlockOperations_vector.out +\verbinclude Tutorial_BlockOperations_vector.out \li \b Next: \ref TutorialAdvancedInitialization diff --git a/doc/C07_TutorialReductionsVisitorsBroadcasting.dox b/doc/C07_TutorialReductionsVisitorsBroadcasting.dox index 1930d7a94..93d18f47b 100644 --- a/doc/C07_TutorialReductionsVisitorsBroadcasting.dox +++ b/doc/C07_TutorialReductionsVisitorsBroadcasting.dox @@ -30,7 +30,7 @@ which returns the addition of all the coefficients inside a given matrix or arra Example: \include tut_arithmetic_redux_basic.cpp -Output: \include tut_arithmetic_redux_basic.out +Output: \verbinclude tut_arithmetic_redux_basic.out The \em trace of a matrix, as returned by the function \c trace(), is the sum of the diagonal coefficients and can also be computed as efficiently using a.diagonal().sum(), as we will see later on. diff --git a/doc/examples/Tutorial_BlockOperations_block_assignment.cpp b/doc/examples/Tutorial_BlockOperations_block_assignment.cpp index 0419a500f..56ca69a6e 100644 --- a/doc/examples/Tutorial_BlockOperations_block_assignment.cpp +++ b/doc/examples/Tutorial_BlockOperations_block_assignment.cpp @@ -6,26 +6,13 @@ using namespace Eigen; int main() { - MatrixXf m(3,3), n(2,2); - + Array33f m; m << 1,2,3, 4,5,6, 7,8,9; - - // assignment through a block operation, - // block as rvalue - n = m.block(0,0,2,2); - - //print n + Array n = Array::Constant(0.6); + n.block(1,1,3,3) = m; cout << "n = " << endl << n << endl << endl; - - - n << 1,1, - 1,1; - - // block as lvalue - m.block(0,0,2,2) = n; - - //print m - cout << "m = " << endl << m << endl; + Array33f res = n.block(0,0,3,3) * m; + cout << "res =" << endl << res << endl; } diff --git a/doc/examples/Tutorial_BlockOperations_colrow.cpp b/doc/examples/Tutorial_BlockOperations_colrow.cpp index e639324b2..e98263057 100644 --- a/doc/examples/Tutorial_BlockOperations_colrow.cpp +++ b/doc/examples/Tutorial_BlockOperations_colrow.cpp @@ -1,15 +1,14 @@ #include #include -using namespace Eigen; int main() { - MatrixXf m(3,3); - + Eigen::MatrixXf m(3,3); m << 1,2,3, 4,5,6, 7,8,9; - - std::cout << "2nd Row: " - << m.row(1) << std::endl; + std::cout << "2nd Row: " << m.row(1) << std::endl; + m.col(0) += m.col(2); + std::cout << "m after adding third column to first:\n"; + std::cout << m << std::endl; } diff --git a/doc/examples/Tutorial_BlockOperations_corner.cpp b/doc/examples/Tutorial_BlockOperations_corner.cpp index 96c6df62b..3a31507aa 100644 --- a/doc/examples/Tutorial_BlockOperations_corner.cpp +++ b/doc/examples/Tutorial_BlockOperations_corner.cpp @@ -2,26 +2,16 @@ #include using namespace std; -using namespace Eigen; int main() { - MatrixXf m(4,4); - + Eigen::Matrix4f m; m << 1, 2, 3, 4, 5, 6, 7, 8, 9, 10,11,12, 13,14,15,16; - - //print first two columns - cout << "-- leftCols(2) --" << endl - << m.leftCols(2) << endl << endl; - - //print last two rows - cout << "-- bottomRows(2) --" << endl - << m.bottomRows(2) << endl << endl; - - //print top-left 2x3 corner - cout << "-- topLeftCorner(2,3) --" << endl - << m.topLeftCorner(2,3) << endl; + cout << "m.leftCols(2) =" << endl << m.leftCols(2) << endl << endl; + cout << "m.bottomRows<2>() =" << endl << m.bottomRows<2>() << endl << endl; + m.topLeftCorner(1,3) = m.bottomRightCorner(3,1).transpose(); + cout << "After assignment, m = " << endl << m << endl; } diff --git a/doc/examples/Tutorial_BlockOperations_print_block.cpp b/doc/examples/Tutorial_BlockOperations_print_block.cpp index a2d0db864..0fdefecdf 100644 --- a/doc/examples/Tutorial_BlockOperations_print_block.cpp +++ b/doc/examples/Tutorial_BlockOperations_print_block.cpp @@ -1,14 +1,18 @@ #include #include -using namespace Eigen; int main() { - MatrixXf m(3,3); - - m << 1,2,3, - 4,5,6, - 7,8,9; - - std::cout << m.block(0,0,2,2) << std::endl; + Eigen::MatrixXf m(4,4); + m << 1, 2, 3, 4, + 5, 6, 7, 8, + 9,10,11,12, + 13,14,15,16; + std::cout << "Block in the middle" << std::endl; + std::cout << m.block<2,2>(1,1) << std::endl << std::endl; + for (int i = 1; i < 4; ++i) + { + std::cout << "Block of size " << i << std::endl; + std::cout << m.block(0,0,i,i) << std::endl << std::endl; + } } diff --git a/doc/examples/Tutorial_BlockOperations_vector.cpp b/doc/examples/Tutorial_BlockOperations_vector.cpp index 211b55472..4a0b02342 100644 --- a/doc/examples/Tutorial_BlockOperations_vector.cpp +++ b/doc/examples/Tutorial_BlockOperations_vector.cpp @@ -2,23 +2,13 @@ #include using namespace std; -using namespace Eigen; int main() { - VectorXf v(6); - + Eigen::ArrayXf v(6); v << 1, 2, 3, 4, 5, 6; - - //print first three elements - cout << "-- head(3) --" << endl - << v.head(3) << endl << endl; - - //print last three elements - cout << "-- tail(3) --" << endl - << v.tail(3) << endl << endl; - - //print between 2nd and 5th elem. inclusive - cout << "-- segment(1,4) --" << endl - << v.segment(1,4) << endl; + cout << "v.head(3) =" << endl << v.head(3) << endl << endl; + cout << "v.tail<3>() = " << endl << v.tail<3>() << endl << endl; + v.segment(1,4) *= 2; + cout << "after 'v.segment(1,4) *= 2', v =" << endl << v << endl; } From 90d6fc0e28d8f955b0b6efdd6ee9b62facd357c6 Mon Sep 17 00:00:00 2001 From: Gael Guennebaud Date: Wed, 14 Jul 2010 22:49:34 +0200 Subject: [PATCH 09/41] fix ei_aligned_delete for null pointers and non trivial dtors --- Eigen/src/Core/util/Memory.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Eigen/src/Core/util/Memory.h b/Eigen/src/Core/util/Memory.h index 1b89525a8..75c3e5ec4 100644 --- a/Eigen/src/Core/util/Memory.h +++ b/Eigen/src/Core/util/Memory.h @@ -315,7 +315,8 @@ template inline T* ei_construct_elements_of_array(T *ptr, size_t siz template inline void ei_destruct_elements_of_array(T *ptr, size_t size) { // always destruct an array starting from the end. - while(size) ptr[--size].~T(); + if(ptr) + while(size) ptr[--size].~T(); } /***************************************************************************** From d4d4382b187fc7e1dcabdf0d2358226ced7ff4b5 Mon Sep 17 00:00:00 2001 From: Gael Guennebaud Date: Wed, 14 Jul 2010 22:50:03 +0200 Subject: [PATCH 10/41] use dummy_precision by default instead of 0 --- test/main.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/main.h b/test/main.h index 604685c26..1104adaa6 100644 --- a/test/main.h +++ b/test/main.h @@ -282,7 +282,7 @@ namespace Eigen namespace Eigen { -template inline typename NumTraits::Real test_precision() { return T(0); } +template inline typename NumTraits::Real test_precision() { return NumTraits::dummy_precision(); } template<> inline float test_precision() { return 1e-3f; } template<> inline double test_precision() { return 1e-6; } template<> inline float test_precision >() { return test_precision(); } From cf9edd995810de7575685d1164590f06edbcab3d Mon Sep 17 00:00:00 2001 From: Gael Guennebaud Date: Wed, 14 Jul 2010 23:31:38 +0200 Subject: [PATCH 11/41] fix compilation for non trivial types --- Eigen/src/Householder/Householder.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Eigen/src/Householder/Householder.h b/Eigen/src/Householder/Householder.h index f943a0852..c45e6469d 100644 --- a/Eigen/src/Householder/Householder.h +++ b/Eigen/src/Householder/Householder.h @@ -65,7 +65,7 @@ void MatrixBase::makeHouseholder( EIGEN_STATIC_ASSERT_VECTOR_ONLY(EssentialPart) VectorBlock tail(derived(), 1, size()-1); - RealScalar tailSqNorm = size()==1 ? 0 : tail.squaredNorm(); + RealScalar tailSqNorm = size()==1 ? RealScalar(0) : tail.squaredNorm(); Scalar c0 = coeff(0); if(tailSqNorm == RealScalar(0) && ei_imag(c0)==RealScalar(0)) From 87e89fea4e05f2f516bf6efb3986a8ee9aee6de6 Mon Sep 17 00:00:00 2001 From: Gael Guennebaud Date: Thu, 15 Jul 2010 16:29:04 +0200 Subject: [PATCH 12/41] add a support module for MPFR C++ with basic unit testing --- cmake/FindGMP.cmake | 21 + cmake/FindMPFR.cmake | 21 + doc/unsupported_modules.dox | 3 + unsupported/Eigen/MPRealSupport | 160 ++ unsupported/doc/examples/CMakeLists.txt | 2 + unsupported/test/CMakeLists.txt | 13 +- unsupported/test/mpreal.cpp | 408 +++ unsupported/test/mpreal.h | 3122 +++++++++++++++++++++++ unsupported/test/mpreal_support.cpp | 42 + 9 files changed, 3790 insertions(+), 2 deletions(-) create mode 100644 cmake/FindGMP.cmake create mode 100644 cmake/FindMPFR.cmake create mode 100644 unsupported/Eigen/MPRealSupport create mode 100644 unsupported/test/mpreal.cpp create mode 100644 unsupported/test/mpreal.h create mode 100644 unsupported/test/mpreal_support.cpp diff --git a/cmake/FindGMP.cmake b/cmake/FindGMP.cmake new file mode 100644 index 000000000..1f0273960 --- /dev/null +++ b/cmake/FindGMP.cmake @@ -0,0 +1,21 @@ +# Try to find the GNU Multiple Precision Arithmetic Library (GMP) +# See http://gmplib.org/ + +if (GMP_INCLUDES AND GMP_LIBRARIES) + set(GMP_FIND_QUIETLY TRUE) +endif (GMP_INCLUDES AND GMP_LIBRARIES) + +find_path(GMP_INCLUDES + NAMES + gmp.h + PATHS + $ENV{GMPDIR} + ${INCLUDE_INSTALL_DIR} +) + +find_library(GMP_LIBRARIES gmp PATHS $ENV{GMPDIR} ${LIB_INSTALL_DIR}) + +include(FindPackageHandleStandardArgs) +find_package_handle_standard_args(GMP DEFAULT_MSG + GMP_INCLUDES GMP_LIBRARIES) +mark_as_advanced(GMP_INCLUDES GMP_LIBRARIES) diff --git a/cmake/FindMPFR.cmake b/cmake/FindMPFR.cmake new file mode 100644 index 000000000..3aa97f0b4 --- /dev/null +++ b/cmake/FindMPFR.cmake @@ -0,0 +1,21 @@ +# Try to find the MPFR library +# See http://www.mpfr.org/ + +if (MPFR_INCLUDES AND MPFR_LIBRARIES) + set(MPFR_FIND_QUIETLY TRUE) +endif (MPFR_INCLUDES AND MPFR_LIBRARIES) + +find_path(MPFR_INCLUDES + NAMES + mpfr.h + PATHS + $ENV{GMPDIR} + ${INCLUDE_INSTALL_DIR} +) + +find_library(MPFR_LIBRARIES mpfr PATHS $ENV{GMPDIR} ${LIB_INSTALL_DIR}) + +include(FindPackageHandleStandardArgs) +find_package_handle_standard_args(MPFR DEFAULT_MSG + MPFR_INCLUDES MPFR_LIBRARIES) +mark_as_advanced(MPFR_INCLUDES MPFR_LIBRARIES) diff --git a/doc/unsupported_modules.dox b/doc/unsupported_modules.dox index dff74ca1b..9f0517c4c 100644 --- a/doc/unsupported_modules.dox +++ b/doc/unsupported_modules.dox @@ -61,4 +61,7 @@ namespace Eigen { /** \ingroup Unsupported_modules * \defgroup SparseExtra_Module */ +/** \ingroup Unsupported_modules + * \defgroup MpfrcxxSupport_Module */ + } // namespace Eigen diff --git a/unsupported/Eigen/MPRealSupport b/unsupported/Eigen/MPRealSupport new file mode 100644 index 000000000..abc719ba7 --- /dev/null +++ b/unsupported/Eigen/MPRealSupport @@ -0,0 +1,160 @@ +// This file is part of a joint effort between Eigen, a lightweight C++ template library +// for linear algebra, and MPFR C++, a C++ interface to MPFR library (http://www.holoborodko.com/pavel/) +// +// Copyright (C) 2010 Pavel Holoborodko +// Copyright (C) 2010 Konstantin Holoborodko +// Copyright (C) 2010 Gael Guennebaud +// +// Eigen is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 3 of the License, or (at your option) any later version. +// +// Alternatively, 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 2 of +// the License, or (at your option) any later version. +// +// Eigen is distributed in the hope that it will be useful, but WITHOUT ANY +// WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +// FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License or the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License and a copy of the GNU General Public License along with +// this library. If not, see . +// +// Contributors: +// Brian Gladman, Helmut Jarausch, Fokko Beekhof, Ulrich Mutze, Heinz van Saanen, Pere Constans + +#ifndef EIGEN_MPREALSUPPORT_MODULE_H +#define EIGEN_MPREALSUPPORT_MODULE_H + +#include +#include + +namespace Eigen { + + /** \defgroup MPRealSupport_Module MPFRC++ Support module + * + * \code + * #include + * \endcode + * + * This module provides support for multi precision floating point numbers + * via the MPFR C++ + * library which itself is built upon MPFR/GMP. + * + * Here is an example: + * +\code +#include +#include +#include +using namespace mpfr; +using namespace Eigen; +int main() +{ + // set precision to 256 bits (double has only 53 bits) + mpreal::set_default_prec(256); + // Declare matrix and vector types with multi-precision scalar type + typedef Matrix MatrixXmp; + typedef Matrix VectorXmp; + + MatrixXmp A = MatrixXmp::Random(100,100); + VectorXmp b = VectorXmp::Random(100); + + // Solve Ax=b using LU + VectorXmp x = A.lu().solve(b); + std::cout << "relative error: " << (A*x - b).norm() / b.norm() << std::endl; + return 0; +} +\endcode + * + */ + + template<> struct NumTraits + : GenericNumTraits + { + enum { + IsInteger = 0, + IsSigned = 1, + IsComplex = 0, + ReadCost = 10, + AddCost = 10, + MulCost = 40 + }; + + typedef mpfr::mpreal Real; + typedef mpfr::mpreal NonInteger; + + inline static mpfr::mpreal highest() { return mpfr::mpreal_max(mpfr::mpreal::get_default_prec()); } + inline static mpfr::mpreal lowest() { return -mpfr::mpreal_max(mpfr::mpreal::get_default_prec()); } + + inline static Real epsilon() + { + return mpfr::machine_epsilon(mpfr::mpreal::get_default_prec()); + } + inline static Real dummy_precision() + { + unsigned int weak_prec = ((mpfr::mpreal::get_default_prec()-1)*90)/100; + return mpfr::machine_epsilon(weak_prec); + } + }; + + template<> mpfr::mpreal ei_random() + { +#if (MPFR_VERSION >= MPFR_VERSION_NUM(3,0,0)) + static gmp_randstate_t state; + static bool isFirstTime = true; + + if(isFirstTime) + { + gmp_randinit_default(state); + gmp_randseed_ui(state,(unsigned)time(NULL)); + isFirstTime = false; + } + + return mpfr::urandom(state)*2-1; +#else + return mpfr::mpreal(ei_random()); +#endif + } + + template<> mpfr::mpreal ei_random(const mpfr::mpreal& a, const mpfr::mpreal& b) + { + return a + (b-a) * ei_random(); + } +} + +namespace mpfr { + + inline const mpreal& ei_conj(const mpreal& x) { return x; } + inline const mpreal& ei_real(const mpreal& x) { return x; } + inline mpreal ei_imag(const mpreal&) { return 0.0; } + inline mpreal ei_abs(const mpreal& x) { return fabs(x); } + inline mpreal ei_abs2(const mpreal& x) { return x*x; } + inline mpreal ei_sqrt(const mpreal& x) { return sqrt(x); } + inline mpreal ei_exp(const mpreal& x) { return exp(x); } + inline mpreal ei_log(const mpreal& x) { return log(x); } + inline mpreal ei_sin(const mpreal& x) { return sin(x); } + inline mpreal ei_cos(const mpreal& x) { return cos(x); } + inline mpreal ei_pow(const mpreal& x, mpreal& y) { return pow(x, y); } + + bool ei_isMuchSmallerThan(const mpreal& a, const mpreal& b, const mpreal& prec) + { + return ei_abs(a) <= abs(b) * prec; + } + + inline bool ei_isApprox(const mpreal& a, const mpreal& b, const mpreal& prec) + { + return ei_abs(a - b) <= min(abs(a), abs(b)) * prec; + } + + inline bool ei_isApproxOrLessThan(const mpreal& a, const mpreal& b, const mpreal& prec) + { + return a <= b || ei_isApprox(a, b, prec); + } +} + +#endif // EIGEN_MPREALSUPPORT_MODULE_H diff --git a/unsupported/doc/examples/CMakeLists.txt b/unsupported/doc/examples/CMakeLists.txt index 61af3e5a5..978f9afd8 100644 --- a/unsupported/doc/examples/CMakeLists.txt +++ b/unsupported/doc/examples/CMakeLists.txt @@ -2,6 +2,8 @@ FILE(GLOB examples_SRCS "*.cpp") ADD_CUSTOM_TARGET(unsupported_examples) +INCLUDE_DIRECTORIES(../../../unsupported ../../../unsupported/test) + FOREACH(example_src ${examples_SRCS}) GET_FILENAME_COMPONENT(example ${example_src} NAME_WE) ADD_EXECUTABLE(example_${example} ${example_src}) diff --git a/unsupported/test/CMakeLists.txt b/unsupported/test/CMakeLists.txt index c7cfc8881..db051caec 100644 --- a/unsupported/test/CMakeLists.txt +++ b/unsupported/test/CMakeLists.txt @@ -55,10 +55,10 @@ include_directories(../../test ../../unsupported ../../Eigen) if(ADOLC_FOUND) include_directories(${ADOLC_INCLUDES}) - ei_add_property(EIGEN_TESTED_BACKENDS "Adolc") + ei_add_property(EIGEN_TESTED_BACKENDS "Adolc, ") ei_add_test(forward_adolc " " ${ADOLC_LIBRARIES}) else(ADOLC_FOUND) - ei_add_property(EIGEN_MISSING_BACKENDS "Adolc") + ei_add_property(EIGEN_MISSING_BACKENDS "Adolc, ") endif(ADOLC_FOUND) ei_add_test(NonLinearOptimization) @@ -70,6 +70,15 @@ ei_add_test(matrix_function) ei_add_test(alignedvector3) ei_add_test(FFT) +find_package(MPFR) +if(MPFR_FOUND) + include_directories(${MPFR_INCLUDES}) + ei_add_property(EIGEN_TESTED_BACKENDS "MPFR C++, ") + ei_add_test(mpreal_support " " ${MPFR_LIBRARIES} ) +else() + ei_add_property(EIGEN_MISSING_BACKENDS "MPFR C++, ") +endif() + ei_add_test(sparse_llt " " "${SPARSE_LIBS}") ei_add_test(sparse_ldlt " " "${SPARSE_LIBS}") ei_add_test(sparse_lu " " "${SPARSE_LIBS}") diff --git a/unsupported/test/mpreal.cpp b/unsupported/test/mpreal.cpp new file mode 100644 index 000000000..bb34c246d --- /dev/null +++ b/unsupported/test/mpreal.cpp @@ -0,0 +1,408 @@ +/* + Multi-precision real number class. C++ wrapper fo MPFR library. + Project homepage: http://www.holoborodko.com/pavel/ + Contact e-mail: pavel@holoborodko.com + + Copyright (c) 2008-2010 Pavel Holoborodko + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + + Contributors: + Brian Gladman, Helmut Jarausch, Fokko Beekhof, Ulrich Mutze, + Heinz van Saanen, Pere Constans, Dmitriy Gubanov +*/ + +#include +#include "mpreal.h" + +using std::ws; +using std::cerr; +using std::endl; +using std::string; +using std::ostream; +using std::istream; + +namespace mpfr{ + +mp_rnd_t mpreal::default_rnd = mpfr_get_default_rounding_mode(); +mp_prec_t mpreal::default_prec = mpfr_get_default_prec(); +int mpreal::default_base = 10; +int mpreal::double_bits = -1; + +// Default constructor: creates mp number and initializes it to 0. +mpreal::mpreal() +{ + mpfr_init2(mp,default_prec); + mpfr_set_ui(mp,0,default_rnd); +} + +mpreal::mpreal(const mpreal& u) +{ + mpfr_init2(mp,mpfr_get_prec(u.mp)); + mpfr_set(mp,u.mp,default_rnd); +} + +mpreal::mpreal(const mpfr_t u) +{ + mpfr_init2(mp,mpfr_get_prec(u)); + mpfr_set(mp,u,default_rnd); +} + +mpreal::mpreal(const mpf_t u) +{ + mpfr_init2(mp,mpf_get_prec(u)); + mpfr_set_f(mp,u,default_rnd); +} + +mpreal::mpreal(const mpz_t u, mp_prec_t prec, mp_rnd_t mode) +{ + mpfr_init2(mp,prec); + mpfr_set_z(mp,u,mode); +} + +mpreal::mpreal(const mpq_t u, mp_prec_t prec, mp_rnd_t mode) +{ + mpfr_init2(mp,prec); + mpfr_set_q(mp,u,mode); +} + +mpreal::mpreal(const double u, mp_prec_t prec, mp_rnd_t mode) +{ + if(double_bits == -1 || fits_in_bits(u, double_bits)) + { + mpfr_init2(mp,prec); + mpfr_set_d(mp,u,mode); + } + else + throw conversion_overflow(); +} + +mpreal::mpreal(const long double u, mp_prec_t prec, mp_rnd_t mode) +{ + mpfr_init2(mp,prec); + mpfr_set_ld(mp,u,mode); +} + +mpreal::mpreal(const unsigned long int u, mp_prec_t prec, mp_rnd_t mode) +{ + mpfr_init2(mp,prec); + mpfr_set_ui(mp,u,mode); +} + +mpreal::mpreal(const unsigned int u, mp_prec_t prec, mp_rnd_t mode) +{ + mpfr_init2(mp,prec); + mpfr_set_ui(mp,u,mode); +} + +mpreal::mpreal(const long int u, mp_prec_t prec, mp_rnd_t mode) +{ + mpfr_init2(mp,prec); + mpfr_set_si(mp,u,mode); +} + +mpreal::mpreal(const int u, mp_prec_t prec, mp_rnd_t mode) +{ + mpfr_init2(mp,prec); + mpfr_set_si(mp,u,mode); +} + +mpreal::mpreal(const char* s, mp_prec_t prec, int base, mp_rnd_t mode) +{ + mpfr_init2(mp,prec); + mpfr_set_str(mp, s, base, mode); +} + +mpreal::~mpreal() +{ + mpfr_clear(mp); +} + +// Operators - Assignment +mpreal& mpreal::operator=(const char* s) +{ + mpfr_t t; + if(0==mpfr_init_set_str(t,s,default_base,default_rnd)) + { + mpfr_set(mp,t,mpreal::default_rnd); + mpfr_clear(t); + }else{ + mpfr_clear(t); + // cerr<<"fail to convert string"<p2?(p3>p1?p3:p1):(p2>p1?p2:p1)); + + mpfr_fma(a.mp,v1.mp,v2.mp,v3.mp,rnd_mode); + return a; +} + +const mpreal fms (const mpreal& v1, const mpreal& v2, const mpreal& v3, mp_rnd_t rnd_mode) +{ + mpreal a; + mp_prec_t p1, p2, p3; + + p1 = v1.get_prec(); + p2 = v2.get_prec(); + p3 = v3.get_prec(); + + a.set_prec(p3>p2?(p3>p1?p3:p1):(p2>p1?p2:p1)); + + mpfr_fms(a.mp,v1.mp,v2.mp,v3.mp,rnd_mode); + return a; +} + +const mpreal agm (const mpreal& v1, const mpreal& v2, mp_rnd_t rnd_mode) +{ + mpreal a; + mp_prec_t p1, p2; + + p1 = v1.get_prec(); + p2 = v2.get_prec(); + + a.set_prec(p1>p2?p1:p2); + + mpfr_agm(a.mp, v1.mp, v2.mp, rnd_mode); + + return a; +} + +const mpreal hypot (const mpreal& x, const mpreal& y, mp_rnd_t rnd_mode) +{ + mpreal a; + mp_prec_t yp, xp; + + yp = y.get_prec(); + xp = x.get_prec(); + + a.set_prec(yp>xp?yp:xp); + + mpfr_hypot(a.mp, x.mp, y.mp, rnd_mode); + + return a; +} + +const mpreal sum (const mpreal tab[], unsigned long int n, mp_rnd_t rnd_mode) +{ + mpreal x; + mpfr_ptr* t; + unsigned long int i; + + t = new mpfr_ptr[n]; + for (i=0;ixp?yp:xp); + + mpfr_remainder(a.mp, x.mp, y.mp, rnd_mode); + + return a; +} + +const mpreal remquo (long* q, const mpreal& x, const mpreal& y, mp_rnd_t rnd_mode) +{ + mpreal a; + mp_prec_t yp, xp; + + yp = y.get_prec(); + xp = x.get_prec(); + + a.set_prec(yp>xp?yp:xp); + + mpfr_remquo(a.mp,q, x.mp, y.mp, rnd_mode); + + return a; +} + +template +std::string to_string(T t, std::ios_base & (*f)(std::ios_base&)) +{ + std::ostringstream oss; + oss << f << t; + return oss.str(); +} + +mpreal::operator std::string() const +{ + return to_string(); +} + +string mpreal::to_string(size_t n, int b, mp_rnd_t mode) const +{ + char *s, *ns = NULL; + size_t slen, nslen; + mp_exp_t exp; + string out; + + if(mpfr_inf_p(mp)) + { + if(mpfr_sgn(mp)>0) return "+@Inf@"; + else return "-@Inf@"; + } + + if(mpfr_zero_p(mp)) return "0"; + if(mpfr_nan_p(mp)) return "@NaN@"; + + + s = mpfr_get_str(NULL,&exp,b,0,mp,mode); + ns = mpfr_get_str(NULL,&exp,b,n,mp,mode); + + if(s!=NULL && ns!=NULL) + { + slen = strlen(s); + nslen = strlen(ns); + if(nslen<=slen) + { + mpfr_free_str(s); + s = ns; + slen = nslen; + } + else { + mpfr_free_str(ns); + } + + // Make human eye-friendly formatting if possible + if (exp>0 && static_cast(exp)s+exp) ptr--; + + if(ptr==s+exp) out = string(s,exp+1); + else out = string(s,exp+1)+'.'+string(s+exp+1,ptr-(s+exp+1)+1); + + //out = string(s,exp+1)+'.'+string(s+exp+1); + } + else + { + // Remove zeros starting from right end + char* ptr = s+slen-1; + while (*ptr=='0' && ptr>s+exp-1) ptr--; + + if(ptr==s+exp-1) out = string(s,exp); + else out = string(s,exp)+'.'+string(s+exp,ptr-(s+exp)+1); + + //out = string(s,exp)+'.'+string(s+exp); + } + + }else{ // exp<0 || exp>slen + if(s[0]=='-') + { + // Remove zeros starting from right end + char* ptr = s+slen-1; + while (*ptr=='0' && ptr>s+1) ptr--; + + if(ptr==s+1) out = string(s,2); + else out = string(s,2)+'.'+string(s+2,ptr-(s+2)+1); + + //out = string(s,2)+'.'+string(s+2); + } + else + { + // Remove zeros starting from right end + char* ptr = s+slen-1; + while (*ptr=='0' && ptr>s) ptr--; + + if(ptr==s) out = string(s,1); + else out = string(s,1)+'.'+string(s+1,ptr-(s+1)+1); + + //out = string(s,1)+'.'+string(s+1); + } + + // Make final string + if(--exp) + { + if(exp>0) out += "e+"+mpfr::to_string(exp,std::dec); + else out += "e"+mpfr::to_string(exp,std::dec); + } + } + + mpfr_free_str(s); + return out; + }else{ + return "conversion error!"; + } +} + +////////////////////////////////////////////////////////////////////////// +// I/O +ostream& operator<<(ostream& os, const mpreal& v) +{ + return os<>(istream &is, mpreal& v) +{ + char c; + string s = ""; + mpfr_t t; + + if(is.good()) + { + is>>ws; + while ((c = is.get())!=EOF) + { + if(c ==' ' || c == '\t' || c == '\n' || c == '\r') + { + is.putback(c); + break; + } + s += c; + } + + if(s.size() != 0) + { + // Protect current value from alternation in case of input error + // so some error handling(roll back) procedure can be used + if(0==mpfr_init_set_str(t,s.c_str(),mpreal::default_base,mpreal::default_rnd)) + { + mpfr_set(v.mp,t,mpreal::default_rnd); + mpfr_clear(t); + + }else{ + mpfr_clear(t); + cerr<<"error reading from istream"< +#include +#include +#include +#include +#include + +#include + +// Detect compiler using signatures from http://predef.sourceforge.net/ +#if defined(__GNUC__) && defined(__INTEL_COMPILER) + #define IsInf(x) isinf(x) // GNU C/C++ + Intel ICC compiler + +#elif defined(__GNUC__) + #define IsInf(x) std::isinf(x) // GNU C/C++ + +#elif defined(_MSC_VER) + #define IsInf(x) (!_finite(x)) // Microsoft Visual C++ + +#else + #define IsInf(x) std::isinf(x) // C99 conformance +#endif + +namespace mpfr { + +class mpreal { +private: + mpfr_t mp; + +public: + static mp_rnd_t default_rnd; + static mp_prec_t default_prec; + static int default_base; + static int double_bits; + +public: + // Constructors && type conversion + mpreal(); + mpreal(const mpreal& u); + + mpreal(const mpfr_t u); + mpreal(const mpf_t u); + + mpreal(const mpz_t u, mp_prec_t prec = default_prec, mp_rnd_t mode = default_rnd); + mpreal(const mpq_t u, mp_prec_t prec = default_prec, mp_rnd_t mode = default_rnd); + mpreal(const double u, mp_prec_t prec = default_prec, mp_rnd_t mode = default_rnd); + mpreal(const long double u, mp_prec_t prec = default_prec, mp_rnd_t mode = default_rnd); + mpreal(const unsigned long int u, mp_prec_t prec = default_prec, mp_rnd_t mode = default_rnd); + mpreal(const unsigned int u, mp_prec_t prec = default_prec, mp_rnd_t mode = default_rnd); + mpreal(const long int u, mp_prec_t prec = default_prec, mp_rnd_t mode = default_rnd); + mpreal(const int u, mp_prec_t prec = default_prec, mp_rnd_t mode = default_rnd); + mpreal(const char* s, mp_prec_t prec = default_prec, int base = default_base, mp_rnd_t mode = default_rnd); + + ~mpreal(); + + // Operations + // = + // +, -, *, /, ++, --, <<, >> + // *=, +=, -=, /=, + // <, >, ==, <=, >= + + // = + mpreal& operator=(const mpreal& v); + mpreal& operator=(const mpf_t v); + mpreal& operator=(const mpz_t v); + mpreal& operator=(const mpq_t v); + mpreal& operator=(const long double v); + mpreal& operator=(const double v); + mpreal& operator=(const unsigned long int v); + mpreal& operator=(const unsigned int v); + mpreal& operator=(const long int v); + mpreal& operator=(const int v); + mpreal& operator=(const char* s); + + // + + mpreal& operator+=(const mpreal& v); + mpreal& operator+=(const mpf_t v); + mpreal& operator+=(const mpz_t v); + mpreal& operator+=(const mpq_t v); + mpreal& operator+=(const long double u); + mpreal& operator+=(const double u); + mpreal& operator+=(const unsigned long int u); + mpreal& operator+=(const unsigned int u); + mpreal& operator+=(const long int u); + mpreal& operator+=(const int u); + const mpreal operator+() const; + mpreal& operator++ (); + const mpreal operator++ (int); + + // - + mpreal& operator-=(const mpreal& v); + mpreal& operator-=(const mpz_t v); + mpreal& operator-=(const mpq_t v); + mpreal& operator-=(const long double u); + mpreal& operator-=(const double u); + mpreal& operator-=(const unsigned long int u); + mpreal& operator-=(const unsigned int u); + mpreal& operator-=(const long int u); + mpreal& operator-=(const int u); + const mpreal operator-() const; + friend const mpreal operator-(const unsigned long int b, const mpreal& a); + friend const mpreal operator-(const unsigned int b, const mpreal& a); + friend const mpreal operator-(const long int b, const mpreal& a); + friend const mpreal operator-(const int b, const mpreal& a); + friend const mpreal operator-(const double b, const mpreal& a); + mpreal& operator-- (); + const mpreal operator-- (int); + + // * + mpreal& operator*=(const mpreal& v); + mpreal& operator*=(const mpz_t v); + mpreal& operator*=(const mpq_t v); + mpreal& operator*=(const long double v); + mpreal& operator*=(const double v); + mpreal& operator*=(const unsigned long int v); + mpreal& operator*=(const unsigned int v); + mpreal& operator*=(const long int v); + mpreal& operator*=(const int v); + + // / + mpreal& operator/=(const mpreal& v); + mpreal& operator/=(const mpz_t v); + mpreal& operator/=(const mpq_t v); + mpreal& operator/=(const long double v); + mpreal& operator/=(const double v); + mpreal& operator/=(const unsigned long int v); + mpreal& operator/=(const unsigned int v); + mpreal& operator/=(const long int v); + mpreal& operator/=(const int v); + friend const mpreal operator/(const unsigned long int b, const mpreal& a); + friend const mpreal operator/(const unsigned int b, const mpreal& a); + friend const mpreal operator/(const long int b, const mpreal& a); + friend const mpreal operator/(const int b, const mpreal& a); + friend const mpreal operator/(const double b, const mpreal& a); + + //<<= Fast Multiplication by 2^u + mpreal& operator<<=(const unsigned long int u); + mpreal& operator<<=(const unsigned int u); + mpreal& operator<<=(const long int u); + mpreal& operator<<=(const int u); + + //>>= Fast Division by 2^u + mpreal& operator>>=(const unsigned long int u); + mpreal& operator>>=(const unsigned int u); + mpreal& operator>>=(const long int u); + mpreal& operator>>=(const int u); + + // Boolean Operators + friend bool operator > (const mpreal& a, const mpreal& b); + friend bool operator >= (const mpreal& a, const mpreal& b); + friend bool operator < (const mpreal& a, const mpreal& b); + friend bool operator <= (const mpreal& a, const mpreal& b); + friend bool operator == (const mpreal& a, const mpreal& b); + friend bool operator != (const mpreal& a, const mpreal& b); + + // Type Conversion operators + inline operator long double() const; + inline operator double() const; + inline operator float() const; + inline operator unsigned long() const; + inline operator unsigned int() const; + inline operator long() const; + operator std::string() const; + inline operator mpfr_ptr(); + + // Math Functions + friend const mpreal sqr(const mpreal& v, mp_rnd_t rnd_mode = mpreal::default_rnd); + friend const mpreal sqrt(const mpreal& v, mp_rnd_t rnd_mode = mpreal::default_rnd); + friend const mpreal sqrt(const unsigned long int v, mp_rnd_t rnd_mode = mpreal::default_rnd); + friend const mpreal cbrt(const mpreal& v, mp_rnd_t rnd_mode = mpreal::default_rnd); + friend const mpreal root(const mpreal& v, unsigned long int k, mp_rnd_t rnd_mode = mpreal::default_rnd); + friend const mpreal pow(const mpreal& a, const mpreal& b, mp_rnd_t rnd_mode = mpreal::default_rnd); + friend const mpreal pow(const mpreal& a, const mpz_t b, mp_rnd_t rnd_mode = mpreal::default_rnd); + friend const mpreal pow(const mpreal& a, const unsigned long int b, mp_rnd_t rnd_mode = mpreal::default_rnd); + friend const mpreal pow(const mpreal& a, const long int b, mp_rnd_t rnd_mode = mpreal::default_rnd); + friend const mpreal pow(const unsigned long int a, const mpreal& b, mp_rnd_t rnd_mode = mpreal::default_rnd); + friend const mpreal pow(const unsigned long int a, const unsigned long int b, mp_rnd_t rnd_mode = mpreal::default_rnd); + friend const mpreal fabs(const mpreal& v, mp_rnd_t rnd_mode = mpreal::default_rnd); + friend const mpreal abs(const mpreal& v, mp_rnd_t rnd_mode = mpreal::default_rnd); + friend const mpreal dim(const mpreal& a, const mpreal& b, mp_rnd_t rnd_mode = mpreal::default_rnd); + friend inline const mpreal mul_2ui(const mpreal& v, unsigned long int k, mp_rnd_t rnd_mode = mpreal::default_rnd); + friend inline const mpreal mul_2si(const mpreal& v, long int k, mp_rnd_t rnd_mode = mpreal::default_rnd); + friend inline const mpreal div_2ui(const mpreal& v, unsigned long int k, mp_rnd_t rnd_mode = mpreal::default_rnd); + friend inline const mpreal div_2si(const mpreal& v, long int k, mp_rnd_t rnd_mode = mpreal::default_rnd); + friend int cmpabs(const mpreal& a,const mpreal& b); + + friend const mpreal log (const mpreal& v, mp_rnd_t rnd_mode = mpreal::default_rnd); + friend const mpreal log2 (const mpreal& v, mp_rnd_t rnd_mode = mpreal::default_rnd); + friend const mpreal log10(const mpreal& v, mp_rnd_t rnd_mode = mpreal::default_rnd); + friend const mpreal exp (const mpreal& v, mp_rnd_t rnd_mode = mpreal::default_rnd); + friend const mpreal exp2 (const mpreal& v, mp_rnd_t rnd_mode = mpreal::default_rnd); + friend const mpreal exp10(const mpreal& v, mp_rnd_t rnd_mode = mpreal::default_rnd); + + friend const mpreal cos(const mpreal& v, mp_rnd_t rnd_mode = mpreal::default_rnd); + friend const mpreal sin(const mpreal& v, mp_rnd_t rnd_mode = mpreal::default_rnd); + friend const mpreal tan(const mpreal& v, mp_rnd_t rnd_mode = mpreal::default_rnd); + friend const mpreal sec(const mpreal& v, mp_rnd_t rnd_mode = mpreal::default_rnd); + friend const mpreal csc(const mpreal& v, mp_rnd_t rnd_mode = mpreal::default_rnd); + friend const mpreal cot(const mpreal& v, mp_rnd_t rnd_mode = mpreal::default_rnd); + friend int sin_cos(mpreal& s, mpreal& c, const mpreal& v, mp_rnd_t rnd_mode = mpreal::default_rnd); + + friend const mpreal acos (const mpreal& v, mp_rnd_t rnd_mode = mpreal::default_rnd); + friend const mpreal asin (const mpreal& v, mp_rnd_t rnd_mode = mpreal::default_rnd); + friend const mpreal atan (const mpreal& v, mp_rnd_t rnd_mode = mpreal::default_rnd); + friend const mpreal atan2 (const mpreal& y, const mpreal& x, mp_rnd_t rnd_mode = mpreal::default_rnd); + friend const mpreal cosh (const mpreal& v, mp_rnd_t rnd_mode = mpreal::default_rnd); + friend const mpreal sinh (const mpreal& v, mp_rnd_t rnd_mode = mpreal::default_rnd); + friend const mpreal tanh (const mpreal& v, mp_rnd_t rnd_mode = mpreal::default_rnd); + friend const mpreal sech (const mpreal& v, mp_rnd_t rnd_mode = mpreal::default_rnd); + friend const mpreal csch (const mpreal& v, mp_rnd_t rnd_mode = mpreal::default_rnd); + friend const mpreal coth (const mpreal& v, mp_rnd_t rnd_mode = mpreal::default_rnd); + + friend const mpreal acosh (const mpreal& v, mp_rnd_t rnd_mode = mpreal::default_rnd); + friend const mpreal asinh (const mpreal& v, mp_rnd_t rnd_mode = mpreal::default_rnd); + friend const mpreal atanh (const mpreal& v, mp_rnd_t rnd_mode = mpreal::default_rnd); + friend const mpreal fac_ui (unsigned long int v, mp_rnd_t rnd_mode = mpreal::default_rnd); + friend const mpreal log1p (const mpreal& v, mp_rnd_t rnd_mode = mpreal::default_rnd); + friend const mpreal expm1 (const mpreal& v, mp_rnd_t rnd_mode = mpreal::default_rnd); + friend const mpreal eint (const mpreal& v, mp_rnd_t rnd_mode = mpreal::default_rnd); + + friend const mpreal gamma (const mpreal& v, mp_rnd_t rnd_mode = mpreal::default_rnd); + friend const mpreal lngamma (const mpreal& v, mp_rnd_t rnd_mode = mpreal::default_rnd); + friend const mpreal lgamma (const mpreal& v, int *signp, mp_rnd_t rnd_mode = mpreal::default_rnd); + friend const mpreal zeta (const mpreal& v, mp_rnd_t rnd_mode = mpreal::default_rnd); + friend const mpreal erf (const mpreal& v, mp_rnd_t rnd_mode = mpreal::default_rnd); + friend const mpreal erfc (const mpreal& v, mp_rnd_t rnd_mode = mpreal::default_rnd); + friend const mpreal _j0 (const mpreal& v, mp_rnd_t rnd_mode = mpreal::default_rnd); + friend const mpreal _j1 (const mpreal& v, mp_rnd_t rnd_mode = mpreal::default_rnd); + friend const mpreal _jn (long n, const mpreal& v, mp_rnd_t rnd_mode = mpreal::default_rnd); + friend const mpreal _y0 (const mpreal& v, mp_rnd_t rnd_mode = mpreal::default_rnd); + friend const mpreal _y1 (const mpreal& v, mp_rnd_t rnd_mode = mpreal::default_rnd); + friend const mpreal _yn (long n, const mpreal& v, mp_rnd_t rnd_mode = mpreal::default_rnd); + friend const mpreal fma (const mpreal& v1, const mpreal& v2, const mpreal& v3, mp_rnd_t rnd_mode = mpreal::default_rnd); + friend const mpreal fms (const mpreal& v1, const mpreal& v2, const mpreal& v3, mp_rnd_t rnd_mode = mpreal::default_rnd); + friend const mpreal agm (const mpreal& v1, const mpreal& v2, mp_rnd_t rnd_mode = mpreal::default_rnd); + friend const mpreal hypot (const mpreal& x, const mpreal& y, mp_rnd_t rnd_mode = mpreal::default_rnd); + friend const mpreal sum (const mpreal tab[], unsigned long int n, mp_rnd_t rnd_mode = mpreal::default_rnd); + friend int sgn(const mpreal& v); // -1 or +1 + +// MPFR 2.4.0 Specifics +#if (MPFR_VERSION >= MPFR_VERSION_NUM(2,4,0)) + friend int sinh_cosh(mpreal& s, mpreal& c, const mpreal& v, mp_rnd_t rnd_mode = mpreal::default_rnd); + friend const mpreal li2(const mpreal& v, mp_rnd_t rnd_mode = mpreal::default_rnd); + friend const mpreal fmod (const mpreal& x, const mpreal& y, mp_rnd_t rnd_mode = mpreal::default_rnd); + friend const mpreal rec_sqrt(const mpreal& v, mp_rnd_t rnd_mode = mpreal::default_rnd); +#endif + +// MPFR 3.0.0 Specifics +#if (MPFR_VERSION >= MPFR_VERSION_NUM(3,0,0)) + friend const mpreal digamma(const mpreal& v, mp_rnd_t rnd_mode = mpreal::default_rnd); + friend const mpreal urandom (gmp_randstate_t& state,mp_rnd_t rnd_mode = mpreal::default_rnd); // use gmp_randinit_default() to init state, gmp_randclear() to clear + friend bool _isregular(const mpreal& v); +#endif + + // Exponent and mantissa manipulation + friend const mpreal frexp(const mpreal& v, mp_exp_t* exp); + friend const mpreal ldexp(const mpreal& v, mp_exp_t exp); + + // Splits mpreal value into fractional and integer parts. + // Returns fractional part and stores integer part in n. + friend const mpreal modf(const mpreal& v, mpreal& n); + + // Constants + // don't forget to call mpfr_free_cache() for every thread where you are using const-functions + friend const mpreal const_log2 (mp_prec_t prec = mpreal::default_prec, mp_rnd_t rnd_mode = mpreal::default_rnd); + friend const mpreal const_pi (mp_prec_t prec = mpreal::default_prec, mp_rnd_t rnd_mode = mpreal::default_rnd); + friend const mpreal const_euler (mp_prec_t prec = mpreal::default_prec, mp_rnd_t rnd_mode = mpreal::default_rnd); + friend const mpreal const_catalan (mp_prec_t prec = mpreal::default_prec, mp_rnd_t rnd_mode = mpreal::default_rnd); + // returns +inf iff sign>=0 otherwise -inf + friend const mpreal const_infinity(int sign = 1, mp_prec_t prec = mpreal::default_prec, mp_rnd_t rnd_mode = mpreal::default_rnd); + + // Output/ Input + friend std::ostream& operator<<(std::ostream& os, const mpreal& v); + friend std::istream& operator>>(std::istream& is, mpreal& v); + + // Integer Related Functions + friend const mpreal rint (const mpreal& v, mp_rnd_t rnd_mode = mpreal::default_rnd); + friend const mpreal ceil (const mpreal& v); + friend const mpreal floor(const mpreal& v); + friend const mpreal round(const mpreal& v); + friend const mpreal trunc(const mpreal& v); + friend const mpreal rint_ceil (const mpreal& v, mp_rnd_t rnd_mode = mpreal::default_rnd); + friend const mpreal rint_floor(const mpreal& v, mp_rnd_t rnd_mode = mpreal::default_rnd); + friend const mpreal rint_round(const mpreal& v, mp_rnd_t rnd_mode = mpreal::default_rnd); + friend const mpreal rint_trunc(const mpreal& v, mp_rnd_t rnd_mode = mpreal::default_rnd); + friend const mpreal frac (const mpreal& v, mp_rnd_t rnd_mode = mpreal::default_rnd); + friend const mpreal remainder (const mpreal& x, const mpreal& y, mp_rnd_t rnd_mode = mpreal::default_rnd); + friend const mpreal remquo (long* q, const mpreal& x, const mpreal& y, mp_rnd_t rnd_mode = mpreal::default_rnd); + + // Miscellaneous Functions + friend const mpreal nexttoward (const mpreal& x, const mpreal& y); + friend const mpreal nextabove (const mpreal& x); + friend const mpreal nextbelow (const mpreal& x); + + // use gmp_randinit_default() to init state, gmp_randclear() to clear + friend const mpreal urandomb (gmp_randstate_t& state); + +// MPFR < 2.4.2 Specifics +#if (MPFR_VERSION <= MPFR_VERSION_NUM(2,4,2)) + friend const mpreal random2 (mp_size_t size, mp_exp_t exp); +#endif + + // Instance Checkers + friend bool _isnan(const mpreal& v); + friend bool _isinf(const mpreal& v); + friend bool _isnum(const mpreal& v); + friend bool _iszero(const mpreal& v); + friend bool _isint(const mpreal& v); + + // Set/Get instance properties + inline mp_prec_t get_prec() const; + inline void set_prec(mp_prec_t prec, mp_rnd_t rnd_mode = default_rnd); // Change precision with rounding mode + + // Set mpreal to +-inf, NaN + void set_inf(int sign = +1); + void set_nan(); + + // sign = -1 or +1 + void set_sign(int sign, mp_rnd_t rnd_mode = default_rnd); + + //Exponent + mp_exp_t get_exp(); + int set_exp(mp_exp_t e); + int check_range (int t, mp_rnd_t rnd_mode = default_rnd); + int subnormalize (int t,mp_rnd_t rnd_mode = default_rnd); + + // Inexact conversion from float + inline bool fits_in_bits(double x, int n); + + // Set/Get global properties + static void set_default_prec(mp_prec_t prec); + static mp_prec_t get_default_prec(); + static void set_default_base(int base); + static int get_default_base(); + static void set_double_bits(int dbits); + static int get_double_bits(); + static void set_default_rnd(mp_rnd_t rnd_mode); + static mp_rnd_t get_default_rnd(); + static mp_exp_t get_emin (void); + static mp_exp_t get_emax (void); + static mp_exp_t get_emin_min (void); + static mp_exp_t get_emin_max (void); + static mp_exp_t get_emax_min (void); + static mp_exp_t get_emax_max (void); + static int set_emin (mp_exp_t exp); + static int set_emax (mp_exp_t exp); + + // Get/Set conversions + // Convert mpreal to string with n significant digits in base b + // n = 0 -> convert with the maximum available digits + std::string to_string(size_t n = 0, int b = default_base, mp_rnd_t mode = default_rnd) const; + + // Efficient swapping of two mpreal values + friend void swap(mpreal& x, mpreal& y); + + //Min Max - macros is evil. Needed for systems which defines max and min globally as macros (e.g. Windows) + //Hope that globally defined macros use > < operations only + #ifndef max + friend const mpreal max(const mpreal& x, const mpreal& y); + #endif + + #ifndef min + friend const mpreal min(const mpreal& x, const mpreal& y); + #endif +}; + +////////////////////////////////////////////////////////////////////////// +// Exceptions +class conversion_overflow : public std::exception { +public: + std::string why() { return "inexact conversion from floating point"; } +}; + +////////////////////////////////////////////////////////////////////////// +// + Addition +const mpreal operator+(const mpreal& a, const mpreal& b); + +// + Fast specialized addition - implemented through fast += operations +const mpreal operator+(const mpreal& a, const mpz_t b); +const mpreal operator+(const mpreal& a, const mpq_t b); +const mpreal operator+(const mpreal& a, const long double b); +const mpreal operator+(const mpreal& a, const double b); +const mpreal operator+(const mpreal& a, const unsigned long int b); +const mpreal operator+(const mpreal& a, const unsigned int b); +const mpreal operator+(const mpreal& a, const long int b); +const mpreal operator+(const mpreal& a, const int b); +const mpreal operator+(const mpreal& a, const char* b); +const mpreal operator+(const char* a, const mpreal& b); +const std::string operator+(const mpreal& a, const std::string b); +const std::string operator+(const std::string a, const mpreal& b); + +const mpreal operator+(const mpz_t b, const mpreal& a); +const mpreal operator+(const mpq_t b, const mpreal& a); +const mpreal operator+(const long double b, const mpreal& a); +const mpreal operator+(const double b, const mpreal& a); +const mpreal operator+(const unsigned long int b, const mpreal& a); +const mpreal operator+(const unsigned int b, const mpreal& a); +const mpreal operator+(const long int b, const mpreal& a); +const mpreal operator+(const int b, const mpreal& a); + +////////////////////////////////////////////////////////////////////////// +// - Subtraction +const mpreal operator-(const mpreal& a, const mpreal& b); + +// - Fast specialized subtraction - implemented through fast -= operations +const mpreal operator-(const mpreal& a, const mpz_t b); +const mpreal operator-(const mpreal& a, const mpq_t b); +const mpreal operator-(const mpreal& a, const long double b); +const mpreal operator-(const mpreal& a, const double b); +const mpreal operator-(const mpreal& a, const unsigned long int b); +const mpreal operator-(const mpreal& a, const unsigned int b); +const mpreal operator-(const mpreal& a, const long int b); +const mpreal operator-(const mpreal& a, const int b); +const mpreal operator-(const mpreal& a, const char* b); +const mpreal operator-(const char* a, const mpreal& b); + +const mpreal operator-(const mpz_t b, const mpreal& a); +const mpreal operator-(const mpq_t b, const mpreal& a); +const mpreal operator-(const long double b, const mpreal& a); +//const mpreal operator-(const double b, const mpreal& a); + +////////////////////////////////////////////////////////////////////////// +// * Multiplication +const mpreal operator*(const mpreal& a, const mpreal& b); + +// * Fast specialized multiplication - implemented through fast *= operations +const mpreal operator*(const mpreal& a, const mpz_t b); +const mpreal operator*(const mpreal& a, const mpq_t b); +const mpreal operator*(const mpreal& a, const long double b); +const mpreal operator*(const mpreal& a, const double b); +const mpreal operator*(const mpreal& a, const unsigned long int b); +const mpreal operator*(const mpreal& a, const unsigned int b); +const mpreal operator*(const mpreal& a, const long int b); +const mpreal operator*(const mpreal& a, const int b); + +const mpreal operator*(const mpz_t b, const mpreal& a); +const mpreal operator*(const mpq_t b, const mpreal& a); +const mpreal operator*(const long double b, const mpreal& a); +const mpreal operator*(const double b, const mpreal& a); +const mpreal operator*(const unsigned long int b, const mpreal& a); +const mpreal operator*(const unsigned int b, const mpreal& a); +const mpreal operator*(const long int b, const mpreal& a); +const mpreal operator*(const int b, const mpreal& a); + +////////////////////////////////////////////////////////////////////////// +// / Division +const mpreal operator/(const mpreal& a, const mpreal& b); + +// / Fast specialized division - implemented through fast /= operations +const mpreal operator/(const mpreal& a, const mpz_t b); +const mpreal operator/(const mpreal& a, const mpq_t b); +const mpreal operator/(const mpreal& a, const long double b); +const mpreal operator/(const mpreal& a, const double b); +const mpreal operator/(const mpreal& a, const unsigned long int b); +const mpreal operator/(const mpreal& a, const unsigned int b); +const mpreal operator/(const mpreal& a, const long int b); +const mpreal operator/(const mpreal& a, const int b); + +const mpreal operator/(const long double b, const mpreal& a); + +////////////////////////////////////////////////////////////////////////// +// Shifts operators - Multiplication/Division by a power of 2 +const mpreal operator<<(const mpreal& v, const unsigned long int k); +const mpreal operator<<(const mpreal& v, const unsigned int k); +const mpreal operator<<(const mpreal& v, const long int k); +const mpreal operator<<(const mpreal& v, const int k); + +const mpreal operator>>(const mpreal& v, const unsigned long int k); +const mpreal operator>>(const mpreal& v, const unsigned int k); +const mpreal operator>>(const mpreal& v, const long int k); +const mpreal operator>>(const mpreal& v, const int k); + +////////////////////////////////////////////////////////////////////////// +// Boolean operators +bool operator < (const mpreal& a, const unsigned long int b); +bool operator < (const mpreal& a, const unsigned int b); +bool operator < (const mpreal& a, const long int b); +bool operator < (const mpreal& a, const int b); +bool operator < (const mpreal& a, const long double b); +bool operator < (const mpreal& a, const double b); + +bool operator < (const unsigned long int a,const mpreal& b); +bool operator < (const unsigned int a, const mpreal& b); +bool operator < (const long int a, const mpreal& b); +bool operator < (const int a, const mpreal& b); +bool operator < (const long double a, const mpreal& b); +bool operator < (const double a, const mpreal& b); + +bool operator > (const mpreal& a, const unsigned long int b); +bool operator > (const mpreal& a, const unsigned int b); +bool operator > (const mpreal& a, const long int b); +bool operator > (const mpreal& a, const int b); +bool operator > (const mpreal& a, const long double b); +bool operator > (const mpreal& a, const double b); + +bool operator > (const unsigned long int a,const mpreal& b); +bool operator > (const unsigned int a, const mpreal& b); +bool operator > (const long int a, const mpreal& b); +bool operator > (const int a, const mpreal& b); +bool operator > (const long double a, const mpreal& b); +bool operator > (const double a, const mpreal& b); + +bool operator >= (const mpreal& a, const unsigned long int b); +bool operator >= (const mpreal& a, const unsigned int b); +bool operator >= (const mpreal& a, const long int b); +bool operator >= (const mpreal& a, const int b); +bool operator >= (const mpreal& a, const long double b); +bool operator >= (const mpreal& a, const double b); + +bool operator >= (const unsigned long int a,const mpreal& b); +bool operator >= (const unsigned int a, const mpreal& b); +bool operator >= (const long int a, const mpreal& b); +bool operator >= (const int a, const mpreal& b); +bool operator >= (const long double a, const mpreal& b); +bool operator >= (const double a, const mpreal& b); + +bool operator <= (const mpreal& a, const unsigned long int b); +bool operator <= (const mpreal& a, const unsigned int b); +bool operator <= (const mpreal& a, const long int b); +bool operator <= (const mpreal& a, const int b); +bool operator <= (const mpreal& a, const long double b); +bool operator <= (const mpreal& a, const double b); + +bool operator <= (const unsigned long int a,const mpreal& b); +bool operator <= (const unsigned int a, const mpreal& b); +bool operator <= (const long int a, const mpreal& b); +bool operator <= (const int a, const mpreal& b); +bool operator <= (const long double a, const mpreal& b); +bool operator <= (const double a, const mpreal& b); + +bool operator == (const mpreal& a, const unsigned long int b); +bool operator == (const mpreal& a, const unsigned int b); +bool operator == (const mpreal& a, const long int b); +bool operator == (const mpreal& a, const int b); +bool operator == (const mpreal& a, const long double b); +bool operator == (const mpreal& a, const double b); + +bool operator == (const unsigned long int a,const mpreal& b); +bool operator == (const unsigned int a, const mpreal& b); +bool operator == (const long int a, const mpreal& b); +bool operator == (const int a, const mpreal& b); +bool operator == (const long double a, const mpreal& b); +bool operator == (const double a, const mpreal& b); + +bool operator != (const mpreal& a, const unsigned long int b); +bool operator != (const mpreal& a, const unsigned int b); +bool operator != (const mpreal& a, const long int b); +bool operator != (const mpreal& a, const int b); +bool operator != (const mpreal& a, const long double b); +bool operator != (const mpreal& a, const double b); + +bool operator != (const unsigned long int a,const mpreal& b); +bool operator != (const unsigned int a, const mpreal& b); +bool operator != (const long int a, const mpreal& b); +bool operator != (const int a, const mpreal& b); +bool operator != (const long double a, const mpreal& b); +bool operator != (const double a, const mpreal& b); + +////////////////////////////////////////////////////////////////////////// +// sqrt +const mpreal sqrt(const unsigned int v, mp_rnd_t rnd_mode = mpreal::default_rnd); +const mpreal sqrt(const long int v, mp_rnd_t rnd_mode = mpreal::default_rnd); +const mpreal sqrt(const int v, mp_rnd_t rnd_mode = mpreal::default_rnd); +const mpreal sqrt(const long double v, mp_rnd_t rnd_mode = mpreal::default_rnd); +const mpreal sqrt(const double v, mp_rnd_t rnd_mode = mpreal::default_rnd); + +////////////////////////////////////////////////////////////////////////// +// pow +const mpreal pow(const mpreal& a, const unsigned int b, mp_rnd_t rnd_mode = mpreal::default_rnd); +const mpreal pow(const mpreal& a, const int b, mp_rnd_t rnd_mode = mpreal::default_rnd); +const mpreal pow(const mpreal& a, const long double b, mp_rnd_t rnd_mode = mpreal::default_rnd); +const mpreal pow(const mpreal& a, const double b, mp_rnd_t rnd_mode = mpreal::default_rnd); + +const mpreal pow(const unsigned int a, const mpreal& b, mp_rnd_t rnd_mode = mpreal::default_rnd); +const mpreal pow(const long int a, const mpreal& b, mp_rnd_t rnd_mode = mpreal::default_rnd); +const mpreal pow(const int a, const mpreal& b, mp_rnd_t rnd_mode = mpreal::default_rnd); +const mpreal pow(const long double a, const mpreal& b, mp_rnd_t rnd_mode = mpreal::default_rnd); +const mpreal pow(const double a, const mpreal& b, mp_rnd_t rnd_mode = mpreal::default_rnd); + +const mpreal pow(const unsigned long int a, const unsigned int b, mp_rnd_t rnd_mode = mpreal::default_rnd); +const mpreal pow(const unsigned long int a, const long int b, mp_rnd_t rnd_mode = mpreal::default_rnd); +const mpreal pow(const unsigned long int a, const int b, mp_rnd_t rnd_mode = mpreal::default_rnd); +const mpreal pow(const unsigned long int a, const long double b, mp_rnd_t rnd_mode = mpreal::default_rnd); +const mpreal pow(const unsigned long int a, const double b, mp_rnd_t rnd_mode = mpreal::default_rnd); + +const mpreal pow(const unsigned int a, const unsigned long int b, mp_rnd_t rnd_mode = mpreal::default_rnd); +const mpreal pow(const unsigned int a, const unsigned int b, mp_rnd_t rnd_mode = mpreal::default_rnd); +const mpreal pow(const unsigned int a, const long int b, mp_rnd_t rnd_mode = mpreal::default_rnd); +const mpreal pow(const unsigned int a, const int b, mp_rnd_t rnd_mode = mpreal::default_rnd); +const mpreal pow(const unsigned int a, const long double b, mp_rnd_t rnd_mode = mpreal::default_rnd); +const mpreal pow(const unsigned int a, const double b, mp_rnd_t rnd_mode = mpreal::default_rnd); + +const mpreal pow(const long int a, const unsigned long int b, mp_rnd_t rnd_mode = mpreal::default_rnd); +const mpreal pow(const long int a, const unsigned int b, mp_rnd_t rnd_mode = mpreal::default_rnd); +const mpreal pow(const long int a, const long int b, mp_rnd_t rnd_mode = mpreal::default_rnd); +const mpreal pow(const long int a, const int b, mp_rnd_t rnd_mode = mpreal::default_rnd); +const mpreal pow(const long int a, const long double b, mp_rnd_t rnd_mode = mpreal::default_rnd); +const mpreal pow(const long int a, const double b, mp_rnd_t rnd_mode = mpreal::default_rnd); + +const mpreal pow(const int a, const unsigned long int b, mp_rnd_t rnd_mode = mpreal::default_rnd); +const mpreal pow(const int a, const unsigned int b, mp_rnd_t rnd_mode = mpreal::default_rnd); +const mpreal pow(const int a, const long int b, mp_rnd_t rnd_mode = mpreal::default_rnd); +const mpreal pow(const int a, const int b, mp_rnd_t rnd_mode = mpreal::default_rnd); +const mpreal pow(const int a, const long double b, mp_rnd_t rnd_mode = mpreal::default_rnd); +const mpreal pow(const int a, const double b, mp_rnd_t rnd_mode = mpreal::default_rnd); + +const mpreal pow(const long double a, const long double b, mp_rnd_t rnd_mode = mpreal::default_rnd); +const mpreal pow(const long double a, const unsigned long int b, mp_rnd_t rnd_mode = mpreal::default_rnd); +const mpreal pow(const long double a, const unsigned int b, mp_rnd_t rnd_mode = mpreal::default_rnd); +const mpreal pow(const long double a, const long int b, mp_rnd_t rnd_mode = mpreal::default_rnd); +const mpreal pow(const long double a, const int b, mp_rnd_t rnd_mode = mpreal::default_rnd); + +const mpreal pow(const double a, const double b, mp_rnd_t rnd_mode = mpreal::default_rnd); +const mpreal pow(const double a, const unsigned long int b, mp_rnd_t rnd_mode = mpreal::default_rnd); +const mpreal pow(const double a, const unsigned int b, mp_rnd_t rnd_mode = mpreal::default_rnd); +const mpreal pow(const double a, const long int b, mp_rnd_t rnd_mode = mpreal::default_rnd); +const mpreal pow(const double a, const int b, mp_rnd_t rnd_mode = mpreal::default_rnd); + +////////////////////////////////////////////////////////////////////////// +// Estimate machine epsilon for the given precision +inline const mpreal machine_epsilon(mp_prec_t prec); +inline const mpreal mpreal_min(mp_prec_t prec); +inline const mpreal mpreal_max(mp_prec_t prec); + +////////////////////////////////////////////////////////////////////////// +// Implementation of inline functions +////////////////////////////////////////////////////////////////////////// + +////////////////////////////////////////////////////////////////////////// +// Operators - Assignment +inline mpreal& mpreal::operator=(const mpreal& v) +{ + if (this!= &v) mpfr_set(mp,v.mp,default_rnd); + return *this; +} + +inline mpreal& mpreal::operator=(const mpf_t v) +{ + mpfr_set_f(mp,v,default_rnd); + return *this; +} + +inline mpreal& mpreal::operator=(const mpz_t v) +{ + mpfr_set_z(mp,v,default_rnd); + return *this; +} + +inline mpreal& mpreal::operator=(const mpq_t v) +{ + mpfr_set_q(mp,v,default_rnd); + return *this; +} + +inline mpreal& mpreal::operator=(const long double v) +{ + mpfr_set_ld(mp,v,default_rnd); + return *this; +} + +inline mpreal& mpreal::operator=(const double v) +{ + if(double_bits == -1 || fits_in_bits(v, double_bits)) + { + mpfr_set_d(mp,v,default_rnd); + } + else + throw conversion_overflow(); + + return *this; +} + +inline mpreal& mpreal::operator=(const unsigned long int v) +{ + mpfr_set_ui(mp,v,default_rnd); + return *this; +} + +inline mpreal& mpreal::operator=(const unsigned int v) +{ + mpfr_set_ui(mp,v,default_rnd); + return *this; +} + +inline mpreal& mpreal::operator=(const long int v) +{ + mpfr_set_si(mp,v,default_rnd); + return *this; +} + +inline mpreal& mpreal::operator=(const int v) +{ + mpfr_set_si(mp,v,default_rnd); + return *this; +} + +////////////////////////////////////////////////////////////////////////// +// + Addition +inline mpreal& mpreal::operator+=(const mpreal& v) +{ + mpfr_add(mp,mp,v.mp,default_rnd); + return *this; +} + +inline mpreal& mpreal::operator+=(const mpf_t u) +{ + *this += mpreal(u); + return *this; +} + +inline mpreal& mpreal::operator+=(const mpz_t u) +{ + mpfr_add_z(mp,mp,u,default_rnd); + return *this; +} + +inline mpreal& mpreal::operator+=(const mpq_t u) +{ + mpfr_add_q(mp,mp,u,default_rnd); + return *this; +} + +inline mpreal& mpreal::operator+= (const long double u) +{ + return *this += mpreal(u); +} + +inline mpreal& mpreal::operator+= (const double u) +{ +#if (MPFR_VERSION >= MPFR_VERSION_NUM(2,4,0)) + mpfr_add_d(mp,mp,u,default_rnd); + return *this; +#else + return *this += mpreal(u); +#endif +} + +inline mpreal& mpreal::operator+=(const unsigned long int u) +{ + mpfr_add_ui(mp,mp,u,default_rnd); + return *this; +} + +inline mpreal& mpreal::operator+=(const unsigned int u) +{ + mpfr_add_ui(mp,mp,u,default_rnd); + return *this; +} + +inline mpreal& mpreal::operator+=(const long int u) +{ + mpfr_add_si(mp,mp,u,default_rnd); + return *this; +} + +inline mpreal& mpreal::operator+=(const int u) +{ + mpfr_add_si(mp,mp,u,default_rnd); + return *this; +} + +inline const mpreal mpreal::operator+()const +{ + return mpreal(*this); +} + +inline const mpreal operator+(const mpreal& a, const mpreal& b) +{ + // prec(a+b) = max(prec(a),prec(b)) + if(a.get_prec()>b.get_prec()) return mpreal(a) += b; + else return mpreal(b) += a; +} + +inline const std::string operator+(const mpreal& a, const std::string b) +{ + return (std::string)a+b; +} + +inline const std::string operator+(const std::string a, const mpreal& b) +{ + return a+(std::string)b; +} + +inline const mpreal operator+(const mpreal& a, const mpz_t b) +{ + return mpreal(a) += b; +} + +inline const mpreal operator+(const mpreal& a, const char* b) +{ + return a+mpreal(b); +} + +inline const mpreal operator+(const char* a, const mpreal& b) +{ + return mpreal(a)+b; + +} + +inline const mpreal operator+(const mpreal& a, const mpq_t b) +{ + return mpreal(a) += b; +} + +inline const mpreal operator+(const mpreal& a, const long double b) +{ + return mpreal(a) += b; +} + +inline const mpreal operator+(const mpreal& a, const double b) +{ + return mpreal(a) += b; +} + +inline const mpreal operator+(const mpreal& a, const unsigned long int b) +{ + return mpreal(a) += b; +} + +inline const mpreal operator+(const mpreal& a, const unsigned int b) +{ + return mpreal(a) += b; +} + +inline const mpreal operator+(const mpreal& a, const long int b) +{ + return mpreal(a) += b; +} + +inline const mpreal operator+(const mpreal& a, const int b) +{ + return mpreal(a) += b; +} + +inline const mpreal operator+(const mpz_t b, const mpreal& a) +{ + return mpreal(a) += b; +} + +inline const mpreal operator+(const mpq_t b, const mpreal& a) +{ + return mpreal(a) += b; +} + +inline const mpreal operator+(const long double b, const mpreal& a) +{ + return mpreal(a) += b; +} + +inline const mpreal operator+(const double b, const mpreal& a) +{ + return mpreal(a) += b; +} + +inline const mpreal operator+(const unsigned long int b, const mpreal& a) +{ + return mpreal(a) += b; +} + +inline const mpreal operator+(const unsigned int b, const mpreal& a) +{ + return mpreal(a) += b; +} + +inline const mpreal operator+(const long int b, const mpreal& a) +{ + return mpreal(a) += b; +} + +inline const mpreal operator+(const int b, const mpreal& a) +{ + return mpreal(a) += b; +} + +inline mpreal& mpreal::operator++() +{ + *this += 1; + return *this; +} + +inline const mpreal mpreal::operator++ (int) +{ + mpreal x(*this); + *this += 1; + return x; +} + +inline mpreal& mpreal::operator--() +{ + *this -= 1; + return *this; +} + +inline const mpreal mpreal::operator-- (int) +{ + mpreal x(*this); + *this -= 1; + return x; +} + +////////////////////////////////////////////////////////////////////////// +// - Subtraction +inline mpreal& mpreal::operator-= (const mpreal& v) +{ + mpfr_sub(mp,mp,v.mp,default_rnd); + return *this; +} + +inline mpreal& mpreal::operator-=(const mpz_t v) +{ + mpfr_sub_z(mp,mp,v,default_rnd); + return *this; +} + +inline mpreal& mpreal::operator-=(const mpq_t v) +{ + mpfr_sub_q(mp,mp,v,default_rnd); + return *this; +} + +inline mpreal& mpreal::operator-=(const long double v) +{ + return *this -= mpreal(v); +} + +inline mpreal& mpreal::operator-=(const double v) +{ +#if (MPFR_VERSION >= MPFR_VERSION_NUM(2,4,0)) + mpfr_sub_d(mp,mp,v,default_rnd); + return *this; +#else + return *this -= mpreal(v); +#endif +} + +inline mpreal& mpreal::operator-=(const unsigned long int v) +{ + mpfr_sub_ui(mp,mp,v,default_rnd); + return *this; +} + +inline mpreal& mpreal::operator-=(const unsigned int v) +{ + mpfr_sub_ui(mp,mp,v,default_rnd); + return *this; +} + +inline mpreal& mpreal::operator-=(const long int v) +{ + mpfr_sub_si(mp,mp,v,default_rnd); + return *this; +} + +inline mpreal& mpreal::operator-=(const int v) +{ + mpfr_sub_si(mp,mp,v,default_rnd); + return *this; +} + +inline const mpreal mpreal::operator-()const +{ + mpreal u(*this); + mpfr_neg(u.mp,u.mp,default_rnd); + return u; +} + +inline const mpreal operator-(const mpreal& a, const mpreal& b) +{ + // prec(a-b) = max(prec(a),prec(b)) + if(a.get_prec()>b.get_prec()) return mpreal(a) -= b; + else return -(mpreal(b) -= a); +} + +inline const mpreal operator-(const mpreal& a, const mpz_t b) +{ + return mpreal(a) -= b; +} + +inline const mpreal operator-(const mpreal& a, const mpq_t b) +{ + return mpreal(a) -= b; +} + +inline const mpreal operator-(const mpreal& a, const long double b) +{ + return mpreal(a) -= b; +} + +inline const mpreal operator-(const mpreal& a, const double b) +{ + return mpreal(a) -= b; +} + +inline const mpreal operator-(const mpreal& a, const unsigned long int b) +{ + return mpreal(a) -= b; +} + +inline const mpreal operator-(const mpreal& a, const unsigned int b) +{ + return mpreal(a) -= b; +} + +inline const mpreal operator-(const mpreal& a, const long int b) +{ + return mpreal(a) -= b; +} + +inline const mpreal operator-(const mpreal& a, const int b) +{ + return mpreal(a) -= b; +} + +inline const mpreal operator-(const mpz_t b, const mpreal& a) +{ + return -(mpreal(a) -= b); +} + +inline const mpreal operator-(const mpq_t b, const mpreal& a) +{ + return -(mpreal(a) -= b); +} + +inline const mpreal operator-(const long double b, const mpreal& a) +{ + return -(mpreal(a) -= b); +} + +inline const mpreal operator-(const double b, const mpreal& a) +{ +#if (MPFR_VERSION >= MPFR_VERSION_NUM(2,4,0)) + mpreal x(a); + mpfr_d_sub(x.mp,b,a.mp,mpreal::default_rnd); + return x; +#else + return -(mpreal(a) -= b); +#endif +} + +inline const mpreal operator-(const unsigned long int b, const mpreal& a) +{ + mpreal x(a); + mpfr_ui_sub(x.mp,b,a.mp,mpreal::default_rnd); + return x; +} + +inline const mpreal operator-(const unsigned int b, const mpreal& a) +{ + mpreal x(a); + mpfr_ui_sub(x.mp,b,a.mp,mpreal::default_rnd); + return x; +} + +inline const mpreal operator-(const long int b, const mpreal& a) +{ + mpreal x(a); + mpfr_si_sub(x.mp,b,a.mp,mpreal::default_rnd); + return x; +} + +inline const mpreal operator-(const int b, const mpreal& a) +{ + mpreal x(a); + mpfr_si_sub(x.mp,b,a.mp,mpreal::default_rnd); + return x; +} + +inline const mpreal operator-(const mpreal& a, const char* b) +{ + return a-mpreal(b); +} + +inline const mpreal operator-(const char* a, const mpreal& b) +{ + return mpreal(a)-b; +} + +////////////////////////////////////////////////////////////////////////// +// * Multiplication +inline mpreal& mpreal::operator*= (const mpreal& v) +{ + mpfr_mul(mp,mp,v.mp,default_rnd); + return *this; +} + +inline mpreal& mpreal::operator*=(const mpz_t v) +{ + mpfr_mul_z(mp,mp,v,default_rnd); + return *this; +} + +inline mpreal& mpreal::operator*=(const mpq_t v) +{ + mpfr_mul_q(mp,mp,v,default_rnd); + return *this; +} + +inline mpreal& mpreal::operator*=(const long double v) +{ + return *this *= mpreal(v); +} + +inline mpreal& mpreal::operator*=(const double v) +{ +#if (MPFR_VERSION >= MPFR_VERSION_NUM(2,4,0)) + mpfr_mul_d(mp,mp,v,default_rnd); + return *this; +#else + return *this *= mpreal(v); +#endif +} + +inline mpreal& mpreal::operator*=(const unsigned long int v) +{ + mpfr_mul_ui(mp,mp,v,default_rnd); + return *this; +} + +inline mpreal& mpreal::operator*=(const unsigned int v) +{ + mpfr_mul_ui(mp,mp,v,default_rnd); + return *this; +} + +inline mpreal& mpreal::operator*=(const long int v) +{ + mpfr_mul_si(mp,mp,v,default_rnd); + return *this; +} + +inline mpreal& mpreal::operator*=(const int v) +{ + mpfr_mul_si(mp,mp,v,default_rnd); + return *this; +} + +inline const mpreal operator*(const mpreal& a, const mpreal& b) +{ + // prec(a*b) = max(prec(a),prec(b)) + if(a.get_prec()>b.get_prec()) return mpreal(a) *= b; + else return mpreal(b) *= a; +} + +inline const mpreal operator*(const mpreal& a, const mpz_t b) +{ + return mpreal(a) *= b; +} + +inline const mpreal operator*(const mpreal& a, const mpq_t b) +{ + return mpreal(a) *= b; +} + +inline const mpreal operator*(const mpreal& a, const long double b) +{ + return mpreal(a) *= b; +} + +inline const mpreal operator*(const mpreal& a, const double b) +{ + return mpreal(a) *= b; +} + +inline const mpreal operator*(const mpreal& a, const unsigned long int b) +{ + return mpreal(a) *= b; +} + +inline const mpreal operator*(const mpreal& a, const unsigned int b) +{ + return mpreal(a) *= b; +} + +inline const mpreal operator*(const mpreal& a, const long int b) +{ + return mpreal(a) *= b; +} + +inline const mpreal operator*(const mpreal& a, const int b) +{ + return mpreal(a) *= b; +} + +inline const mpreal operator*(const mpz_t b, const mpreal& a) +{ + return mpreal(a) *= b; +} + +inline const mpreal operator*(const mpq_t b, const mpreal& a) +{ + return mpreal(a) *= b; +} + +inline const mpreal operator*(const long double b, const mpreal& a) +{ + return mpreal(a) *= b; +} + +inline const mpreal operator*(const double b, const mpreal& a) +{ + return mpreal(a) *= b; +} + +inline const mpreal operator*(const unsigned long int b, const mpreal& a) +{ + return mpreal(a) *= b; +} + +inline const mpreal operator*(const unsigned int b, const mpreal& a) +{ + return mpreal(a) *= b; +} + +inline const mpreal operator*(const long int b, const mpreal& a) +{ + return mpreal(a) *= b; +} + +inline const mpreal operator*(const int b, const mpreal& a) +{ + return mpreal(a) *= b; +} + +////////////////////////////////////////////////////////////////////////// +// / Division +inline mpreal& mpreal::operator/=(const mpreal& v) +{ + mpfr_div(mp,mp,v.mp,default_rnd); + return *this; +} + +inline mpreal& mpreal::operator/=(const mpz_t v) +{ + mpfr_div_z(mp,mp,v,default_rnd); + return *this; +} + +inline mpreal& mpreal::operator/=(const mpq_t v) +{ + mpfr_div_q(mp,mp,v,default_rnd); + return *this; +} + +inline mpreal& mpreal::operator/=(const long double v) +{ + return *this /= mpreal(v); +} + +inline mpreal& mpreal::operator/=(const double v) +{ +#if (MPFR_VERSION >= MPFR_VERSION_NUM(2,4,0)) + mpfr_div_d(mp,mp,v,default_rnd); + return *this; +#else + return *this /= mpreal(v); +#endif +} + +inline mpreal& mpreal::operator/=(const unsigned long int v) +{ + mpfr_div_ui(mp,mp,v,default_rnd); + return *this; +} + +inline mpreal& mpreal::operator/=(const unsigned int v) +{ + mpfr_div_ui(mp,mp,v,default_rnd); + return *this; +} + +inline mpreal& mpreal::operator/=(const long int v) +{ + mpfr_div_si(mp,mp,v,default_rnd); + return *this; +} + +inline mpreal& mpreal::operator/=(const int v) +{ + mpfr_div_si(mp,mp,v,default_rnd); + return *this; +} + +inline const mpreal operator/(const mpreal& a, const mpreal& b) +{ + mpreal x(a); + mp_prec_t pb; + mp_prec_t pa; + + // prec(a/b) = max(prec(a),prec(b)) + pa = a.get_prec(); + pb = b.get_prec(); + if(pb>pa) x.set_prec(pb); + + return x /= b; +} + +inline const mpreal operator/(const mpreal& a, const mpz_t b) +{ + return mpreal(a) /= b; +} + +inline const mpreal operator/(const mpreal& a, const mpq_t b) +{ + return mpreal(a) /= b; +} + +inline const mpreal operator/(const mpreal& a, const long double b) +{ + return mpreal(a) /= b; +} + +inline const mpreal operator/(const mpreal& a, const double b) +{ + return mpreal(a) /= b; +} + +inline const mpreal operator/(const mpreal& a, const unsigned long int b) +{ + return mpreal(a) /= b; +} + +inline const mpreal operator/(const mpreal& a, const unsigned int b) +{ + return mpreal(a) /= b; +} + +inline const mpreal operator/(const mpreal& a, const long int b) +{ + return mpreal(a) /= b; +} + +inline const mpreal operator/(const mpreal& a, const int b) +{ + return mpreal(a) /= b; +} + +inline const mpreal operator/(const unsigned long int b, const mpreal& a) +{ + mpreal x(a); + mpfr_ui_div(x.mp,b,a.mp,mpreal::default_rnd); + return x; +} + +inline const mpreal operator/(const unsigned int b, const mpreal& a) +{ + mpreal x(a); + mpfr_ui_div(x.mp,b,a.mp,mpreal::default_rnd); + return x; +} + +inline const mpreal operator/(const long int b, const mpreal& a) +{ + mpreal x(a); + mpfr_si_div(x.mp,b,a.mp,mpreal::default_rnd); + return x; +} + +inline const mpreal operator/(const int b, const mpreal& a) +{ + mpreal x(a); + mpfr_si_div(x.mp,b,a.mp,mpreal::default_rnd); + return x; +} + +inline const mpreal operator/(const long double b, const mpreal& a) +{ + mpreal x(b); + return x/a; +} + +inline const mpreal operator/(const double b, const mpreal& a) +{ +#if (MPFR_VERSION >= MPFR_VERSION_NUM(2,4,0)) + mpreal x(a); + mpfr_d_div(x.mp,b,a.mp,mpreal::default_rnd); + return x; +#else + mpreal x(b); + return x/a; +#endif +} + +////////////////////////////////////////////////////////////////////////// +// Shifts operators - Multiplication/Division by power of 2 +inline mpreal& mpreal::operator<<=(const unsigned long int u) +{ + mpfr_mul_2ui(mp,mp,u,default_rnd); + return *this; +} + +inline mpreal& mpreal::operator<<=(const unsigned int u) +{ + mpfr_mul_2ui(mp,mp,static_cast(u),default_rnd); + return *this; +} + +inline mpreal& mpreal::operator<<=(const long int u) +{ + mpfr_mul_2si(mp,mp,u,default_rnd); + return *this; +} + +inline mpreal& mpreal::operator<<=(const int u) +{ + mpfr_mul_2si(mp,mp,static_cast(u),default_rnd); + return *this; +} + +inline mpreal& mpreal::operator>>=(const unsigned long int u) +{ + mpfr_div_2ui(mp,mp,u,default_rnd); + return *this; +} + +inline mpreal& mpreal::operator>>=(const unsigned int u) +{ + mpfr_div_2ui(mp,mp,static_cast(u),default_rnd); + return *this; +} + +inline mpreal& mpreal::operator>>=(const long int u) +{ + mpfr_div_2si(mp,mp,u,default_rnd); + return *this; +} + +inline mpreal& mpreal::operator>>=(const int u) +{ + mpfr_div_2si(mp,mp,static_cast(u),default_rnd); + return *this; +} + +inline const mpreal operator<<(const mpreal& v, const unsigned long int k) +{ + return mul_2ui(v,k); +} + +inline const mpreal operator<<(const mpreal& v, const unsigned int k) +{ + return mul_2ui(v,static_cast(k)); +} + +inline const mpreal operator<<(const mpreal& v, const long int k) +{ + return mul_2si(v,k); +} + +inline const mpreal operator<<(const mpreal& v, const int k) +{ + return mul_2si(v,static_cast(k)); +} + +inline const mpreal operator>>(const mpreal& v, const unsigned long int k) +{ + return div_2ui(v,k); +} + +inline const mpreal operator>>(const mpreal& v, const long int k) +{ + return div_2si(v,k); +} + +inline const mpreal operator>>(const mpreal& v, const unsigned int k) +{ + return div_2ui(v,static_cast(k)); +} + +inline const mpreal operator>>(const mpreal& v, const int k) +{ + return div_2si(v,static_cast(k)); +} + +// mul_2ui +inline const mpreal mul_2ui(const mpreal& v, unsigned long int k, mp_rnd_t rnd_mode) +{ + mpreal x(v); + mpfr_mul_2ui(x.mp,v.mp,k,rnd_mode); + return x; +} + +// mul_2si +inline const mpreal mul_2si(const mpreal& v, long int k, mp_rnd_t rnd_mode) +{ + mpreal x(v); + mpfr_mul_2si(x.mp,v.mp,k,rnd_mode); + return x; +} + +inline const mpreal div_2ui(const mpreal& v, unsigned long int k, mp_rnd_t rnd_mode) +{ + mpreal x(v); + mpfr_div_2ui(x.mp,v.mp,k,rnd_mode); + return x; +} + +inline const mpreal div_2si(const mpreal& v, long int k, mp_rnd_t rnd_mode) +{ + mpreal x(v); + mpfr_div_2si(x.mp,v.mp,k,rnd_mode); + return x; +} + +////////////////////////////////////////////////////////////////////////// +//Boolean operators +inline bool operator > (const mpreal& a, const mpreal& b) +{ + return (mpfr_greater_p(a.mp,b.mp)!=0); +} + +inline bool operator > (const mpreal& a, const unsigned long int b) +{ + return a>mpreal(b); +} + +inline bool operator > (const mpreal& a, const unsigned int b) +{ + return a>mpreal(b); +} + +inline bool operator > (const mpreal& a, const long int b) +{ + return a>mpreal(b); +} + +inline bool operator > (const mpreal& a, const int b) +{ + return a>mpreal(b); +} + +inline bool operator > (const mpreal& a, const long double b) +{ + return a>mpreal(b); +} + +inline bool operator > (const mpreal& a, const double b) +{ + return a>mpreal(b); +} + +inline bool operator > (const unsigned long int a, const mpreal& b) +{ + return mpreal(a)>b; +} + +inline bool operator > (const unsigned int a, const mpreal& b) +{ + return mpreal(a)>b; +} + +inline bool operator > (const long int a, const mpreal& b) +{ + return mpreal(a)>b; +} + +inline bool operator > (const int a, const mpreal& b) +{ + return mpreal(a)>b; +} + +inline bool operator > (const long double a, const mpreal& b) +{ + return mpreal(a)>b; +} + +inline bool operator > (const double a, const mpreal& b) +{ + return mpreal(a)>b; +} + +inline bool operator >= (const mpreal& a, const mpreal& b) +{ + return (mpfr_greaterequal_p(a.mp,b.mp)!=0); +} + +inline bool operator >= (const mpreal& a, const unsigned long int b) +{ + return a>=mpreal(b); +} + +inline bool operator >= (const mpreal& a, const unsigned int b) +{ + return a>=mpreal(b); +} + +inline bool operator >= (const mpreal& a, const long int b) +{ + return a>=mpreal(b); +} + +inline bool operator >= (const mpreal& a, const int b) +{ + return a>=mpreal(b); +} + +inline bool operator >= (const mpreal& a, const long double b) +{ + return a>=mpreal(b); +} + +inline bool operator >= (const mpreal& a, const double b) +{ + return a>=mpreal(b); +} + +inline bool operator >= (const unsigned long int a,const mpreal& b) +{ + return mpreal(a)>=b; +} + +inline bool operator >= (const unsigned int a, const mpreal& b) +{ + return mpreal(a)>=b; +} + +inline bool operator >= (const long int a, const mpreal& b) +{ + return mpreal(a)>=b; +} + +inline bool operator >= (const int a, const mpreal& b) +{ + return mpreal(a)>=b; +} + +inline bool operator >= (const long double a, const mpreal& b) +{ + return mpreal(a)>=b; +} + +inline bool operator >= (const double a, const mpreal& b) +{ + return mpreal(a)>=b; +} + +inline bool operator < (const mpreal& a, const mpreal& b) +{ + return (mpfr_less_p(a.mp,b.mp)!=0); +} + +inline bool operator < (const mpreal& a, const unsigned long int b) +{ + return a= MPFR_VERSION_NUM(3,0,0)) +inline bool _isregular(const mpreal& v) +{ + return (mpfr_regular_p(v.mp)); +} +#endif // MPFR 3.0.0 Specifics + +////////////////////////////////////////////////////////////////////////// +// Type Converters +inline mpreal::operator double() const +{ + return mpfr_get_d(mp,default_rnd); +} + +inline mpreal::operator float() const +{ + return (float)mpfr_get_d(mp,default_rnd); +} + +inline mpreal::operator long double() const +{ + return mpfr_get_ld(mp,default_rnd); +} + +inline mpreal::operator unsigned long() const +{ + return mpfr_get_ui(mp,default_rnd); +} + +inline mpreal::operator unsigned int() const +{ + return static_cast(mpfr_get_ui(mp,default_rnd)); +} + +inline mpreal::operator long() const +{ + return mpfr_get_si(mp,default_rnd); +} + +inline mpreal::operator mpfr_ptr() +{ + return mp; +} + +////////////////////////////////////////////////////////////////////////// +// Set/Get number properties +inline int sgn(const mpreal& v) +{ + int r = mpfr_signbit(v.mp); + return (r>0?-1:1); +} + +inline void mpreal::set_sign(int sign, mp_rnd_t rnd_mode) +{ + mpfr_setsign(mp,mp,(sign<0?1:0),rnd_mode); +} + +inline mp_prec_t mpreal::get_prec() const +{ + return mpfr_get_prec(mp); +} + +inline void mpreal::set_prec(mp_prec_t prec, mp_rnd_t rnd_mode) +{ + mpfr_prec_round(mp,prec,rnd_mode); +} + +inline void mpreal::set_inf(int sign) +{ + mpfr_set_inf(mp,sign); +} + +inline void mpreal::set_nan() +{ + mpfr_set_nan(mp); +} + +inline mp_exp_t mpreal::get_exp () +{ + return mpfr_get_exp(mp); +} + +inline int mpreal::set_exp (mp_exp_t e) +{ + return mpfr_set_exp(mp,e); +} + +inline const mpreal frexp(const mpreal& v, mp_exp_t* exp) +{ + mpreal x(v); + *exp = x.get_exp(); + x.set_exp(0); + return x; +} + +inline const mpreal ldexp(const mpreal& v, mp_exp_t exp) +{ + mpreal x(v); + + // rounding is not important since we just increasing the exponent + mpfr_mul_2si(x.mp,x.mp,exp,mpreal::default_rnd); + return x; +} + +inline const mpreal machine_epsilon(mp_prec_t prec) +{ + // smallest eps such that 1.0+eps != 1.0 + // depends (of cause) on the precision + mpreal x(1,prec); + return nextabove(x)-x; +} + +inline const mpreal mpreal_min(mp_prec_t prec) +{ + // min = 1/2*2^emin = 2^(emin-1) + + mpreal x(1,prec); + return x <<= mpreal::get_emin()-1; +} + +inline const mpreal mpreal_max(mp_prec_t prec) +{ + // max = (1-eps)*2^emax, assume eps = 0?, + // and use emax-1 to prevent value to be +inf + // max = 2^(emax-1) + + mpreal x(1,prec); + return x <<= mpreal::get_emax()-1; +} + +inline const mpreal modf(const mpreal& v, mpreal& n) +{ + mpreal frac(v); + + // rounding is not important since we are using the same number + mpfr_frac(frac.mp,frac.mp,mpreal::default_rnd); + mpfr_trunc(n.mp,v.mp); + return frac; +} + +inline int mpreal::check_range (int t, mp_rnd_t rnd_mode) +{ + return mpfr_check_range(mp,t,rnd_mode); +} + +inline int mpreal::subnormalize (int t,mp_rnd_t rnd_mode) +{ + return mpfr_subnormalize(mp,t,rnd_mode); +} + +inline mp_exp_t mpreal::get_emin (void) +{ + return mpfr_get_emin(); +} + +inline int mpreal::set_emin (mp_exp_t exp) +{ + return mpfr_set_emin(exp); +} + +inline mp_exp_t mpreal::get_emax (void) +{ + return mpfr_get_emax(); +} + +inline int mpreal::set_emax (mp_exp_t exp) +{ + return mpfr_set_emax(exp); +} + +inline mp_exp_t mpreal::get_emin_min (void) +{ + return mpfr_get_emin_min(); +} + +inline mp_exp_t mpreal::get_emin_max (void) +{ + return mpfr_get_emin_max(); +} + +inline mp_exp_t mpreal::get_emax_min (void) +{ + return mpfr_get_emax_min(); +} + +inline mp_exp_t mpreal::get_emax_max (void) +{ + return mpfr_get_emax_max(); +} + +////////////////////////////////////////////////////////////////////////// +// Mathematical Functions +////////////////////////////////////////////////////////////////////////// +inline const mpreal sqr(const mpreal& v, mp_rnd_t rnd_mode) +{ + mpreal x(v); + mpfr_sqr(x.mp,x.mp,rnd_mode); + return x; +} + +inline const mpreal sqrt(const mpreal& v, mp_rnd_t rnd_mode) +{ + mpreal x(v); + mpfr_sqrt(x.mp,x.mp,rnd_mode); + return x; +} + +inline const mpreal sqrt(const unsigned long int v, mp_rnd_t rnd_mode) +{ + mpreal x; + mpfr_sqrt_ui(x.mp,v,rnd_mode); + return x; +} + +inline const mpreal sqrt(const unsigned int v, mp_rnd_t rnd_mode) +{ + return sqrt(static_cast(v),rnd_mode); +} + +inline const mpreal sqrt(const long int v, mp_rnd_t rnd_mode) +{ + if (v>=0) return sqrt(static_cast(v),rnd_mode); + else return mpreal(); // NaN +} + +inline const mpreal sqrt(const int v, mp_rnd_t rnd_mode) +{ + if (v>=0) return sqrt(static_cast(v),rnd_mode); + else return mpreal(); // NaN +} + +inline const mpreal sqrt(const long double v, mp_rnd_t rnd_mode) +{ + return sqrt(mpreal(v),rnd_mode); +} + +inline const mpreal sqrt(const double v, mp_rnd_t rnd_mode) +{ + return sqrt(mpreal(v),rnd_mode); +} + +inline const mpreal cbrt(const mpreal& v, mp_rnd_t rnd_mode) +{ + mpreal x(v); + mpfr_cbrt(x.mp,x.mp,rnd_mode); + return x; +} + +inline const mpreal root(const mpreal& v, unsigned long int k, mp_rnd_t rnd_mode) +{ + mpreal x(v); + mpfr_root(x.mp,x.mp,k,rnd_mode); + return x; +} + +inline const mpreal fabs(const mpreal& v, mp_rnd_t rnd_mode) +{ + mpreal x(v); + mpfr_abs(x.mp,x.mp,rnd_mode); + return x; +} + +inline const mpreal abs(const mpreal& v, mp_rnd_t rnd_mode) +{ + mpreal x(v); + mpfr_abs(x.mp,x.mp,rnd_mode); + return x; +} + +inline const mpreal dim(const mpreal& a, const mpreal& b, mp_rnd_t rnd_mode) +{ + mpreal x(a); + mpfr_dim(x.mp,a.mp,b.mp,rnd_mode); + return x; +} + +inline int cmpabs(const mpreal& a,const mpreal& b) +{ + return mpfr_cmpabs(a.mp,b.mp); +} + +inline const mpreal log (const mpreal& v, mp_rnd_t rnd_mode) +{ + mpreal x(v); + mpfr_log(x.mp,v.mp,rnd_mode); + return x; +} + +inline const mpreal log2(const mpreal& v, mp_rnd_t rnd_mode) +{ + mpreal x(v); + mpfr_log2(x.mp,v.mp,rnd_mode); + return x; +} + +inline const mpreal log10(const mpreal& v, mp_rnd_t rnd_mode) +{ + mpreal x(v); + mpfr_log10(x.mp,v.mp,rnd_mode); + return x; +} + +inline const mpreal exp(const mpreal& v, mp_rnd_t rnd_mode) +{ + mpreal x(v); + mpfr_exp(x.mp,v.mp,rnd_mode); + return x; +} + +inline const mpreal exp2(const mpreal& v, mp_rnd_t rnd_mode) +{ + mpreal x(v); + mpfr_exp2(x.mp,v.mp,rnd_mode); + return x; +} + +inline const mpreal exp10(const mpreal& v, mp_rnd_t rnd_mode) +{ + mpreal x(v); + mpfr_exp10(x.mp,v.mp,rnd_mode); + return x; +} + +inline const mpreal cos(const mpreal& v, mp_rnd_t rnd_mode) +{ + mpreal x(v); + mpfr_cos(x.mp,v.mp,rnd_mode); + return x; +} + +inline const mpreal sin(const mpreal& v, mp_rnd_t rnd_mode) +{ + mpreal x(v); + mpfr_sin(x.mp,v.mp,rnd_mode); + return x; +} + +inline const mpreal tan(const mpreal& v, mp_rnd_t rnd_mode) +{ + mpreal x(v); + mpfr_tan(x.mp,v.mp,rnd_mode); + return x; +} + +inline const mpreal sec(const mpreal& v, mp_rnd_t rnd_mode) +{ + mpreal x(v); + mpfr_sec(x.mp,v.mp,rnd_mode); + return x; +} + +inline const mpreal csc(const mpreal& v, mp_rnd_t rnd_mode) +{ + mpreal x(v); + mpfr_csc(x.mp,v.mp,rnd_mode); + return x; +} + +inline const mpreal cot(const mpreal& v, mp_rnd_t rnd_mode) +{ + mpreal x(v); + mpfr_cot(x.mp,v.mp,rnd_mode); + return x; +} + +inline int sin_cos(mpreal& s, mpreal& c, const mpreal& v, mp_rnd_t rnd_mode) +{ + return mpfr_sin_cos(s.mp,c.mp,v.mp,rnd_mode); +} + +inline const mpreal acos (const mpreal& v, mp_rnd_t rnd_mode) +{ + mpreal x(v); + mpfr_acos(x.mp,v.mp,rnd_mode); + return x; +} + +inline const mpreal asin (const mpreal& v, mp_rnd_t rnd_mode) +{ + mpreal x(v); + mpfr_asin(x.mp,v.mp,rnd_mode); + return x; +} + +inline const mpreal atan (const mpreal& v, mp_rnd_t rnd_mode) +{ + mpreal x(v); + mpfr_atan(x.mp,v.mp,rnd_mode); + return x; +} + +inline const mpreal atan2 (const mpreal& y, const mpreal& x, mp_rnd_t rnd_mode) +{ + mpreal a; + mp_prec_t yp, xp; + + yp = y.get_prec(); + xp = x.get_prec(); + + a.set_prec(yp>xp?yp:xp); + + mpfr_atan2(a.mp, y.mp, x.mp, rnd_mode); + + return a; +} + +inline const mpreal cosh (const mpreal& v, mp_rnd_t rnd_mode) +{ + mpreal x(v); + mpfr_cosh(x.mp,v.mp,rnd_mode); + return x; +} + +inline const mpreal sinh (const mpreal& v, mp_rnd_t rnd_mode) +{ + mpreal x(v); + mpfr_sinh(x.mp,v.mp,rnd_mode); + return x; +} + +inline const mpreal tanh (const mpreal& v, mp_rnd_t rnd_mode) +{ + mpreal x(v); + mpfr_tanh(x.mp,v.mp,rnd_mode); + return x; +} + +inline const mpreal sech (const mpreal& v, mp_rnd_t rnd_mode) +{ + mpreal x(v); + mpfr_sech(x.mp,v.mp,rnd_mode); + return x; +} + +inline const mpreal csch (const mpreal& v, mp_rnd_t rnd_mode) +{ + mpreal x(v); + mpfr_csch(x.mp,v.mp,rnd_mode); + return x; +} + +inline const mpreal coth (const mpreal& v, mp_rnd_t rnd_mode) +{ + mpreal x(v); + mpfr_coth(x.mp,v.mp,rnd_mode); + return x; +} + +inline const mpreal acosh (const mpreal& v, mp_rnd_t rnd_mode) +{ + mpreal x(v); + mpfr_acosh(x.mp,v.mp,rnd_mode); + return x; +} + +inline const mpreal asinh (const mpreal& v, mp_rnd_t rnd_mode) +{ + mpreal x(v); + mpfr_asinh(x.mp,v.mp,rnd_mode); + return x; +} + +inline const mpreal atanh (const mpreal& v, mp_rnd_t rnd_mode) +{ + mpreal x(v); + mpfr_atanh(x.mp,v.mp,rnd_mode); + return x; +} + +inline const mpreal fac_ui (unsigned long int v, mp_rnd_t rnd_mode) +{ + mpreal x; + mpfr_fac_ui(x.mp,v,rnd_mode); + return x; +} + +inline const mpreal log1p (const mpreal& v, mp_rnd_t rnd_mode) +{ + mpreal x(v); + mpfr_log1p(x.mp,v.mp,rnd_mode); + return x; +} + +inline const mpreal expm1 (const mpreal& v, mp_rnd_t rnd_mode) +{ + mpreal x(v); + mpfr_expm1(x.mp,v.mp,rnd_mode); + return x; +} + +inline const mpreal eint (const mpreal& v, mp_rnd_t rnd_mode) +{ + mpreal x(v); + mpfr_eint(x.mp,v.mp,rnd_mode); + return x; +} + +inline const mpreal gamma (const mpreal& v, mp_rnd_t rnd_mode) +{ + mpreal x(v); + mpfr_gamma(x.mp,v.mp,rnd_mode); + return x; +} + +inline const mpreal lngamma (const mpreal& v, mp_rnd_t rnd_mode) +{ + mpreal x(v); + mpfr_lngamma(x.mp,v.mp,rnd_mode); + return x; +} + +inline const mpreal lgamma (const mpreal& v, int *signp, mp_rnd_t rnd_mode) +{ + mpreal x(v); + mpfr_lgamma(x.mp,signp,v.mp,rnd_mode); + return x; +} + +inline const mpreal zeta (const mpreal& v, mp_rnd_t rnd_mode) +{ + mpreal x(v); + mpfr_zeta(x.mp,v.mp,rnd_mode); + return x; +} + +inline const mpreal erf (const mpreal& v, mp_rnd_t rnd_mode) +{ + mpreal x(v); + mpfr_erf(x.mp,v.mp,rnd_mode); + return x; +} + +inline const mpreal erfc (const mpreal& v, mp_rnd_t rnd_mode) +{ + mpreal x(v); + mpfr_erfc(x.mp,v.mp,rnd_mode); + return x; +} + +inline const mpreal _j0 (const mpreal& v, mp_rnd_t rnd_mode) +{ + mpreal x(v); + mpfr_j0(x.mp,v.mp,rnd_mode); + return x; +} + +inline const mpreal _j1 (const mpreal& v, mp_rnd_t rnd_mode) +{ + mpreal x(v); + mpfr_j1(x.mp,v.mp,rnd_mode); + return x; +} + +inline const mpreal _jn (long n, const mpreal& v, mp_rnd_t rnd_mode) +{ + mpreal x(v); + mpfr_jn(x.mp,n,v.mp,rnd_mode); + return x; +} + +inline const mpreal _y0 (const mpreal& v, mp_rnd_t rnd_mode) +{ + mpreal x(v); + mpfr_y0(x.mp,v.mp,rnd_mode); + return x; +} + +inline const mpreal _y1 (const mpreal& v, mp_rnd_t rnd_mode) +{ + mpreal x(v); + mpfr_y1(x.mp,v.mp,rnd_mode); + return x; +} + +inline const mpreal _yn (long n, const mpreal& v, mp_rnd_t rnd_mode) +{ + mpreal x(v); + mpfr_yn(x.mp,n,v.mp,rnd_mode); + return x; +} + +////////////////////////////////////////////////////////////////////////// +// MPFR 2.4.0 Specifics +#if (MPFR_VERSION >= MPFR_VERSION_NUM(2,4,0)) + +inline int sinh_cosh(mpreal& s, mpreal& c, const mpreal& v, mp_rnd_t rnd_mode) +{ + return mpfr_sinh_cosh(s.mp,c.mp,v.mp,rnd_mode); +} + +inline const mpreal li2(const mpreal& v, mp_rnd_t rnd_mode) +{ + mpreal x(v); + mpfr_li2(x.mp,v.mp,rnd_mode); + return x; +} + +inline const mpreal fmod (const mpreal& x, const mpreal& y, mp_rnd_t rnd_mode) +{ + mpreal a; + mp_prec_t yp, xp; + + yp = y.get_prec(); + xp = x.get_prec(); + + a.set_prec(yp>xp?yp:xp); + + mpfr_fmod(a.mp, x.mp, y.mp, rnd_mode); + + return a; +} + +inline const mpreal rec_sqrt(const mpreal& v, mp_rnd_t rnd_mode) +{ + mpreal x(v); + mpfr_rec_sqrt(x.mp,v.mp,rnd_mode); + return x; +} +#endif // MPFR 2.4.0 Specifics + +////////////////////////////////////////////////////////////////////////// +// MPFR 3.0.0 Specifics +#if (MPFR_VERSION >= MPFR_VERSION_NUM(3,0,0)) +inline const mpreal digamma(const mpreal& v, mp_rnd_t rnd_mode) +{ + mpreal x(v); + mpfr_digamma(x.mp,v.mp,rnd_mode); + return x; +} +#endif // MPFR 3.0.0 Specifics + +////////////////////////////////////////////////////////////////////////// +// Constants +inline const mpreal const_log2 (mp_prec_t prec, mp_rnd_t rnd_mode) +{ + mpreal x; + x.set_prec(prec); + mpfr_const_log2(x.mp,rnd_mode); + return x; +} + +inline const mpreal const_pi (mp_prec_t prec, mp_rnd_t rnd_mode) +{ + mpreal x; + x.set_prec(prec); + mpfr_const_pi(x.mp,rnd_mode); + return x; +} + +inline const mpreal const_euler (mp_prec_t prec, mp_rnd_t rnd_mode) +{ + mpreal x; + x.set_prec(prec); + mpfr_const_euler(x.mp,rnd_mode); + return x; +} + +inline const mpreal const_catalan (mp_prec_t prec, mp_rnd_t rnd_mode) +{ + mpreal x; + x.set_prec(prec); + mpfr_const_catalan(x.mp,rnd_mode); + return x; +} + +inline const mpreal const_infinity (int sign, mp_prec_t prec, mp_rnd_t rnd_mode) +{ + mpreal x; + x.set_prec(prec,rnd_mode); + mpfr_set_inf(x.mp, sign); + return x; +} + +////////////////////////////////////////////////////////////////////////// +// Integer Related Functions +inline const mpreal rint(const mpreal& v, mp_rnd_t rnd_mode) +{ + mpreal x(v); + mpfr_rint(x.mp,v.mp,rnd_mode); + return x; +} + +inline const mpreal ceil(const mpreal& v) +{ + mpreal x(v); + mpfr_ceil(x.mp,v.mp); + return x; + +} + +inline const mpreal floor(const mpreal& v) +{ + mpreal x(v); + mpfr_floor(x.mp,v.mp); + return x; +} + +inline const mpreal round(const mpreal& v) +{ + mpreal x(v); + mpfr_round(x.mp,v.mp); + return x; +} + +inline const mpreal trunc(const mpreal& v) +{ + mpreal x(v); + mpfr_trunc(x.mp,v.mp); + return x; +} + +inline const mpreal rint_ceil (const mpreal& v, mp_rnd_t rnd_mode) +{ + mpreal x(v); + mpfr_rint_ceil(x.mp,v.mp,rnd_mode); + return x; +} + +inline const mpreal rint_floor(const mpreal& v, mp_rnd_t rnd_mode) +{ + mpreal x(v); + mpfr_rint_floor(x.mp,v.mp,rnd_mode); + return x; +} + +inline const mpreal rint_round(const mpreal& v, mp_rnd_t rnd_mode) +{ + mpreal x(v); + mpfr_rint_round(x.mp,v.mp,rnd_mode); + return x; +} + +inline const mpreal rint_trunc(const mpreal& v, mp_rnd_t rnd_mode) +{ + mpreal x(v); + mpfr_rint_trunc(x.mp,v.mp,rnd_mode); + return x; +} + +inline const mpreal frac (const mpreal& v, mp_rnd_t rnd_mode) +{ + mpreal x(v); + mpfr_frac(x.mp,v.mp,rnd_mode); + return x; +} + +////////////////////////////////////////////////////////////////////////// +// Miscellaneous Functions +inline void swap(mpreal& a, mpreal& b) +{ + mpfr_swap(a.mp,b.mp); +} + +#ifndef max +inline const mpreal max(const mpreal& x, const mpreal& y) +{ + return (x>y?x:y); +} +#endif + +#ifndef min +inline const mpreal min(const mpreal& x, const mpreal& y) +{ + return (x= MPFR_VERSION_NUM(3,0,0)) +// use gmp_randinit_default() to init state, gmp_randclear() to clear +inline const mpreal urandom (gmp_randstate_t& state,mp_rnd_t rnd_mode) +{ + mpreal x; + mpfr_urandom(x.mp,state,rnd_mode); + return x; +} +#endif + +#if (MPFR_VERSION <= MPFR_VERSION_NUM(2,4,2)) +inline const mpreal random2 (mp_size_t size, mp_exp_t exp) +{ + mpreal x; + mpfr_random2(x.mp,size,exp); + return x; +} +#endif + +////////////////////////////////////////////////////////////////////////// +// Set/Get global properties +inline void mpreal::set_default_prec(mp_prec_t prec) +{ + default_prec = prec; + mpfr_set_default_prec(prec); +} + +inline mp_prec_t mpreal::get_default_prec() +{ + return mpfr_get_default_prec(); +} + +inline void mpreal::set_default_base(int base) +{ + default_base = base; +} + +inline int mpreal::get_default_base() +{ + return default_base; +} + +inline void mpreal::set_default_rnd(mp_rnd_t rnd_mode) +{ + default_rnd = rnd_mode; + mpfr_set_default_rounding_mode(rnd_mode); +} + +inline mp_rnd_t mpreal::get_default_rnd() +{ + return mpfr_get_default_rounding_mode(); +} + +inline void mpreal::set_double_bits(int dbits) +{ + double_bits = dbits; +} + +inline int mpreal::get_double_bits() +{ + return double_bits; +} + +inline bool mpreal::fits_in_bits(double x, int n) +{ + int i; + double t; + return IsInf(x) || (std::modf ( std::ldexp ( std::frexp ( x, &i ), n ), &t ) == 0.0); +} + +inline const mpreal pow(const mpreal& a, const mpreal& b, mp_rnd_t rnd_mode) +{ + mpreal x(a); + mpfr_pow(x.mp,x.mp,b.mp,rnd_mode); + return x; +} + +inline const mpreal pow(const mpreal& a, const mpz_t b, mp_rnd_t rnd_mode) +{ + mpreal x(a); + mpfr_pow_z(x.mp,x.mp,b,rnd_mode); + return x; +} + +inline const mpreal pow(const mpreal& a, const unsigned long int b, mp_rnd_t rnd_mode) +{ + mpreal x(a); + mpfr_pow_ui(x.mp,x.mp,b,rnd_mode); + return x; +} + +inline const mpreal pow(const mpreal& a, const unsigned int b, mp_rnd_t rnd_mode) +{ + return pow(a,static_cast(b),rnd_mode); +} + +inline const mpreal pow(const mpreal& a, const long int b, mp_rnd_t rnd_mode) +{ + mpreal x(a); + mpfr_pow_si(x.mp,x.mp,b,rnd_mode); + return x; +} + +inline const mpreal pow(const mpreal& a, const int b, mp_rnd_t rnd_mode) +{ + return pow(a,static_cast(b),rnd_mode); +} + +inline const mpreal pow(const mpreal& a, const long double b, mp_rnd_t rnd_mode) +{ + return pow(a,mpreal(b),rnd_mode); +} + +inline const mpreal pow(const mpreal& a, const double b, mp_rnd_t rnd_mode) +{ + return pow(a,mpreal(b),rnd_mode); +} + +inline const mpreal pow(const unsigned long int a, const mpreal& b, mp_rnd_t rnd_mode) +{ + mpreal x(a); + mpfr_ui_pow(x.mp,a,b.mp,rnd_mode); + return x; +} + +inline const mpreal pow(const unsigned int a, const mpreal& b, mp_rnd_t rnd_mode) +{ + return pow(static_cast(a),b,rnd_mode); +} + +inline const mpreal pow(const long int a, const mpreal& b, mp_rnd_t rnd_mode) +{ + if (a>=0) return pow(static_cast(a),b,rnd_mode); + else return pow(mpreal(a),b,rnd_mode); +} + +inline const mpreal pow(const int a, const mpreal& b, mp_rnd_t rnd_mode) +{ + if (a>=0) return pow(static_cast(a),b,rnd_mode); + else return pow(mpreal(a),b,rnd_mode); +} + +inline const mpreal pow(const long double a, const mpreal& b, mp_rnd_t rnd_mode) +{ + return pow(mpreal(a),b,rnd_mode); +} + +inline const mpreal pow(const double a, const mpreal& b, mp_rnd_t rnd_mode) +{ + return pow(mpreal(a),b,rnd_mode); +} + +// pow unsigned long int +inline const mpreal pow(const unsigned long int a, const unsigned long int b, mp_rnd_t rnd_mode) +{ + mpreal x(a); + mpfr_ui_pow_ui(x.mp,a,b,rnd_mode); + return x; +} + +inline const mpreal pow(const unsigned long int a, const unsigned int b, mp_rnd_t rnd_mode) +{ + return pow(a,static_cast(b),rnd_mode); //mpfr_ui_pow_ui +} + +inline const mpreal pow(const unsigned long int a, const long int b, mp_rnd_t rnd_mode) +{ + if(b>0) return pow(a,static_cast(b),rnd_mode); //mpfr_ui_pow_ui + else return pow(a,mpreal(b),rnd_mode); //mpfr_ui_pow +} + +inline const mpreal pow(const unsigned long int a, const int b, mp_rnd_t rnd_mode) +{ + if(b>0) return pow(a,static_cast(b),rnd_mode); //mpfr_ui_pow_ui + else return pow(a,mpreal(b),rnd_mode); //mpfr_ui_pow +} + +inline const mpreal pow(const unsigned long int a, const long double b, mp_rnd_t rnd_mode) +{ + return pow(a,mpreal(b),rnd_mode); //mpfr_ui_pow +} + +inline const mpreal pow(const unsigned long int a, const double b, mp_rnd_t rnd_mode) +{ + return pow(a,mpreal(b),rnd_mode); //mpfr_ui_pow +} + +// pow unsigned int +inline const mpreal pow(const unsigned int a, const unsigned long int b, mp_rnd_t rnd_mode) +{ + return pow(static_cast(a),b,rnd_mode); //mpfr_ui_pow_ui +} + +inline const mpreal pow(const unsigned int a, const unsigned int b, mp_rnd_t rnd_mode) +{ + return pow(static_cast(a),static_cast(b),rnd_mode); //mpfr_ui_pow_ui +} + +inline const mpreal pow(const unsigned int a, const long int b, mp_rnd_t rnd_mode) +{ + if(b>0) return pow(static_cast(a),static_cast(b),rnd_mode); //mpfr_ui_pow_ui + else return pow(static_cast(a),mpreal(b),rnd_mode); //mpfr_ui_pow +} + +inline const mpreal pow(const unsigned int a, const int b, mp_rnd_t rnd_mode) +{ + if(b>0) return pow(static_cast(a),static_cast(b),rnd_mode); //mpfr_ui_pow_ui + else return pow(static_cast(a),mpreal(b),rnd_mode); //mpfr_ui_pow +} + +inline const mpreal pow(const unsigned int a, const long double b, mp_rnd_t rnd_mode) +{ + return pow(static_cast(a),mpreal(b),rnd_mode); //mpfr_ui_pow +} + +inline const mpreal pow(const unsigned int a, const double b, mp_rnd_t rnd_mode) +{ + return pow(static_cast(a),mpreal(b),rnd_mode); //mpfr_ui_pow +} + +// pow long int +inline const mpreal pow(const long int a, const unsigned long int b, mp_rnd_t rnd_mode) +{ + if (a>0) return pow(static_cast(a),b,rnd_mode); //mpfr_ui_pow_ui + else return pow(mpreal(a),b,rnd_mode); //mpfr_pow_ui +} + +inline const mpreal pow(const long int a, const unsigned int b, mp_rnd_t rnd_mode) +{ + if (a>0) return pow(static_cast(a),static_cast(b),rnd_mode); //mpfr_ui_pow_ui + else return pow(mpreal(a),static_cast(b),rnd_mode); //mpfr_pow_ui +} + +inline const mpreal pow(const long int a, const long int b, mp_rnd_t rnd_mode) +{ + if (a>0) + { + if(b>0) return pow(static_cast(a),static_cast(b),rnd_mode); //mpfr_ui_pow_ui + else return pow(static_cast(a),mpreal(b),rnd_mode); //mpfr_ui_pow + }else{ + return pow(mpreal(a),b,rnd_mode); // mpfr_pow_si + } +} + +inline const mpreal pow(const long int a, const int b, mp_rnd_t rnd_mode) +{ + if (a>0) + { + if(b>0) return pow(static_cast(a),static_cast(b),rnd_mode); //mpfr_ui_pow_ui + else return pow(static_cast(a),mpreal(b),rnd_mode); //mpfr_ui_pow + }else{ + return pow(mpreal(a),static_cast(b),rnd_mode); // mpfr_pow_si + } +} + +inline const mpreal pow(const long int a, const long double b, mp_rnd_t rnd_mode) +{ + if (a>=0) return pow(static_cast(a),mpreal(b),rnd_mode); //mpfr_ui_pow + else return pow(mpreal(a),mpreal(b),rnd_mode); //mpfr_pow +} + +inline const mpreal pow(const long int a, const double b, mp_rnd_t rnd_mode) +{ + if (a>=0) return pow(static_cast(a),mpreal(b),rnd_mode); //mpfr_ui_pow + else return pow(mpreal(a),mpreal(b),rnd_mode); //mpfr_pow +} + +// pow int +inline const mpreal pow(const int a, const unsigned long int b, mp_rnd_t rnd_mode) +{ + if (a>0) return pow(static_cast(a),b,rnd_mode); //mpfr_ui_pow_ui + else return pow(mpreal(a),b,rnd_mode); //mpfr_pow_ui +} + +inline const mpreal pow(const int a, const unsigned int b, mp_rnd_t rnd_mode) +{ + if (a>0) return pow(static_cast(a),static_cast(b),rnd_mode); //mpfr_ui_pow_ui + else return pow(mpreal(a),static_cast(b),rnd_mode); //mpfr_pow_ui +} + +inline const mpreal pow(const int a, const long int b, mp_rnd_t rnd_mode) +{ + if (a>0) + { + if(b>0) return pow(static_cast(a),static_cast(b),rnd_mode); //mpfr_ui_pow_ui + else return pow(static_cast(a),mpreal(b),rnd_mode); //mpfr_ui_pow + }else{ + return pow(mpreal(a),b,rnd_mode); // mpfr_pow_si + } +} + +inline const mpreal pow(const int a, const int b, mp_rnd_t rnd_mode) +{ + if (a>0) + { + if(b>0) return pow(static_cast(a),static_cast(b),rnd_mode); //mpfr_ui_pow_ui + else return pow(static_cast(a),mpreal(b),rnd_mode); //mpfr_ui_pow + }else{ + return pow(mpreal(a),static_cast(b),rnd_mode); // mpfr_pow_si + } +} + +inline const mpreal pow(const int a, const long double b, mp_rnd_t rnd_mode) +{ + if (a>=0) return pow(static_cast(a),mpreal(b),rnd_mode); //mpfr_ui_pow + else return pow(mpreal(a),mpreal(b),rnd_mode); //mpfr_pow +} + +inline const mpreal pow(const int a, const double b, mp_rnd_t rnd_mode) +{ + if (a>=0) return pow(static_cast(a),mpreal(b),rnd_mode); //mpfr_ui_pow + else return pow(mpreal(a),mpreal(b),rnd_mode); //mpfr_pow +} + +// pow long double +inline const mpreal pow(const long double a, const long double b, mp_rnd_t rnd_mode) +{ + return pow(mpreal(a),mpreal(b),rnd_mode); +} + +inline const mpreal pow(const long double a, const unsigned long int b, mp_rnd_t rnd_mode) +{ + return pow(mpreal(a),b,rnd_mode); //mpfr_pow_ui +} + +inline const mpreal pow(const long double a, const unsigned int b, mp_rnd_t rnd_mode) +{ + return pow(mpreal(a),static_cast(b),rnd_mode); //mpfr_pow_ui +} + +inline const mpreal pow(const long double a, const long int b, mp_rnd_t rnd_mode) +{ + return pow(mpreal(a),b,rnd_mode); // mpfr_pow_si +} + +inline const mpreal pow(const long double a, const int b, mp_rnd_t rnd_mode) +{ + return pow(mpreal(a),static_cast(b),rnd_mode); // mpfr_pow_si +} + +inline const mpreal pow(const double a, const double b, mp_rnd_t rnd_mode) +{ + return pow(mpreal(a),mpreal(b),rnd_mode); +} + +inline const mpreal pow(const double a, const unsigned long int b, mp_rnd_t rnd_mode) +{ + return pow(mpreal(a),b,rnd_mode); // mpfr_pow_ui +} + +inline const mpreal pow(const double a, const unsigned int b, mp_rnd_t rnd_mode) +{ + return pow(mpreal(a),static_cast(b),rnd_mode); // mpfr_pow_ui +} + +inline const mpreal pow(const double a, const long int b, mp_rnd_t rnd_mode) +{ + return pow(mpreal(a),b,rnd_mode); // mpfr_pow_si +} + +inline const mpreal pow(const double a, const int b, mp_rnd_t rnd_mode) +{ + return pow(mpreal(a),static_cast(b),rnd_mode); // mpfr_pow_si +} +} + +// Explicit specialization of std::swap for mpreal numbers +// Thus standard algorithms will use efficient version of swap (due to Koenig lookup) +// Non-throwing swap C++ idiom: http://en.wikibooks.org/wiki/More_C%2B%2B_Idioms/Non-throwing_swap +namespace std +{ + template <> + inline void swap(mpfr::mpreal& x, mpfr::mpreal& y) + { + return mpfr::swap(x, y); + } +} + +#endif /* __MP_REAL_H__ */ diff --git a/unsupported/test/mpreal_support.cpp b/unsupported/test/mpreal_support.cpp new file mode 100644 index 000000000..32570f092 --- /dev/null +++ b/unsupported/test/mpreal_support.cpp @@ -0,0 +1,42 @@ +#include "main.h" +#include + +using namespace mpfr; +using namespace std; +using namespace Eigen; + +void test_mpreal_support() +{ + // set precision to 256 bits (double has only 53 bits) + mpreal::set_default_prec(256); + typedef Matrix MatrixXmp; + + std::cerr << "epsilon = " << NumTraits::epsilon() << "\n"; + std::cerr << "dummy_precision = " << NumTraits::dummy_precision() << "\n"; + std::cerr << "highest = " << NumTraits::highest() << "\n"; + std::cerr << "lowest = " << NumTraits::lowest() << "\n"; + + for(int i = 0; i < g_repeat; i++) { + int s = ei_random(1,100); + MatrixXmp A = MatrixXmp::Random(s,s); + MatrixXmp B = MatrixXmp::Random(s,s); + MatrixXmp S = A.adjoint() * A; + MatrixXmp X; + + // Cholesky + X = S.selfadjointView().llt().solve(B); + VERIFY_IS_APPROX((S.selfadjointView()*X).eval(),B); + + // partial LU + X = A.lu().solve(B); + VERIFY_IS_APPROX((A*X).eval(),B); + + // symmetric eigenvalues + SelfAdjointEigenSolver eig(S); + VERIFY_IS_EQUAL(eig.info(), Success); + VERIFY_IS_APPROX((S.selfadjointView() * eig.eigenvectors()), + eig.eigenvectors() * eig.eigenvalues().asDiagonal()); + } +} + +#include "mpreal.cpp" From 84fdbded4d8a7fae0cbd6fb5836f2aa0e442f356 Mon Sep 17 00:00:00 2001 From: Gael Guennebaud Date: Thu, 15 Jul 2010 20:39:20 +0200 Subject: [PATCH 13/41] add support for strictly triangular matrix in trmm though it is not really useful --- .../Core/products/TriangularMatrixMatrix.h | 22 +++++++++++++------ test/product_trmm.cpp | 9 +++++++- 2 files changed, 23 insertions(+), 8 deletions(-) diff --git a/Eigen/src/Core/products/TriangularMatrixMatrix.h b/Eigen/src/Core/products/TriangularMatrixMatrix.h index be9362958..98305f993 100644 --- a/Eigen/src/Core/products/TriangularMatrixMatrix.h +++ b/Eigen/src/Core/products/TriangularMatrixMatrix.h @@ -75,7 +75,7 @@ struct ei_product_triangular_matrix_matrix Blocking; enum { SmallPanelWidth = EIGEN_PLAIN_ENUM_MAX(Blocking::mr,Blocking::nr), - IsLower = (Mode&Lower) == Lower + IsLower = (Mode&Lower) == Lower, + SetDiag = (Mode&(ZeroDiag|UnitDiag)) ? 0 : 1 }; Index kc = depth; // cache block size along the K direction @@ -127,7 +128,10 @@ struct ei_product_triangular_matrix_matrix triangularBuffer; triangularBuffer.setZero(); - triangularBuffer.diagonal().setOnes(); + if((Mode&ZeroDiag)==ZeroDiag) + triangularBuffer.diagonal().setZero(); + else + triangularBuffer.diagonal().setOnes(); ei_gebp_kernel gebp_kernel; ei_gemm_pack_lhs pack_lhs; @@ -169,7 +173,7 @@ struct ei_product_triangular_matrix_matrix Blocking; enum { SmallPanelWidth = EIGEN_PLAIN_ENUM_MAX(Blocking::mr,Blocking::nr), - IsLower = (Mode&Lower) == Lower + IsLower = (Mode&Lower) == Lower, + SetDiag = (Mode&(ZeroDiag|UnitDiag)) ? 0 : 1 }; Index kc = depth; // cache block size along the K direction @@ -252,7 +257,10 @@ struct ei_product_triangular_matrix_matrix triangularBuffer; triangularBuffer.setZero(); - triangularBuffer.diagonal().setOnes(); + if((Mode&ZeroDiag)==ZeroDiag) + triangularBuffer.diagonal().setZero(); + else + triangularBuffer.diagonal().setOnes(); ei_gebp_kernel gebp_kernel; ei_gemm_pack_lhs pack_lhs; @@ -300,7 +308,7 @@ struct ei_product_triangular_matrix_matrix void trmm(int size,int /*othersize*/) DenseIndex cols = ei_random(1,size); MatrixColMaj triV(rows,cols), triH(cols,rows), upTri(cols,rows), loTri(rows,cols), - unitUpTri(cols,rows), unitLoTri(rows,cols); + unitUpTri(cols,rows), unitLoTri(rows,cols), strictlyUpTri(cols,rows), strictlyLoTri(rows,cols); MatrixColMaj ge1(rows,cols), ge2(cols,rows), ge3; MatrixRowMaj rge3; @@ -48,6 +48,8 @@ template void trmm(int size,int /*othersize*/) upTri = triH.template triangularView(); unitLoTri = triV.template triangularView(); unitUpTri = triH.template triangularView(); + strictlyLoTri = triV.template triangularView(); + strictlyUpTri = triH.template triangularView(); ge1.setRandom(); ge2.setRandom(); @@ -72,6 +74,11 @@ template void trmm(int size,int /*othersize*/) VERIFY_IS_APPROX( rge3.noalias() = ge2 * triV.template triangularView(), ge2 * unitLoTri); VERIFY_IS_APPROX( ge3 = ge2 * triV.template triangularView(), ge2 * unitLoTri); VERIFY_IS_APPROX( ge3 = (s1*triV).adjoint().template triangularView() * ge2.adjoint(), ei_conj(s1) * unitLoTri.adjoint() * ge2.adjoint()); + + VERIFY_IS_APPROX( ge3 = triV.template triangularView() * ge2, strictlyLoTri * ge2); + VERIFY_IS_APPROX( rge3.noalias() = ge2 * triV.template triangularView(), ge2 * strictlyLoTri); + VERIFY_IS_APPROX( ge3 = ge2 * triV.template triangularView(), ge2 * strictlyLoTri); + VERIFY_IS_APPROX( ge3 = (s1*triV).adjoint().template triangularView() * ge2.adjoint(), ei_conj(s1) * strictlyLoTri.adjoint() * ge2.adjoint()); } void test_product_trmm() From 6a370f50c72a320a4a5a2740e881b61601d2a917 Mon Sep 17 00:00:00 2001 From: Gael Guennebaud Date: Thu, 15 Jul 2010 20:45:45 +0200 Subject: [PATCH 14/41] MPRealSupport was missing --- bench/bench_gemm.cpp | 8 +++++--- unsupported/Eigen/CMakeLists.txt | 2 +- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/bench/bench_gemm.cpp b/bench/bench_gemm.cpp index 06a124f8f..d04c24f44 100644 --- a/bench/bench_gemm.cpp +++ b/bench/bench_gemm.cpp @@ -10,8 +10,8 @@ using namespace std; using namespace Eigen; #ifndef SCALAR -#define SCALAR std::complex -// #define SCALAR double +// #define SCALAR std::complex +#define SCALAR float #endif typedef SCALAR Scalar; @@ -87,7 +87,9 @@ void blas_gemm(const MatrixXd& a, const MatrixXd& b, MatrixXd& c) template EIGEN_DONT_INLINE void gemm(const M& a, const M& b, M& c) { - c.noalias() += a * b; + //c.noalias() += a * b; + for(int i=0;i Date: Fri, 16 Jul 2010 14:02:20 +0200 Subject: [PATCH 15/41] fix sum()/prod() on empty matrix making sure this does not affect fixed sized object, extend related unit tests including partial reduction --- Eigen/src/Core/Redux.h | 9 ++++++++- test/array_for_matrix.cpp | 4 ++++ test/redux.cpp | 11 +++++++++++ 3 files changed, 23 insertions(+), 1 deletion(-) diff --git a/Eigen/src/Core/Redux.h b/Eigen/src/Core/Redux.h index b1dd7d727..504a51229 100644 --- a/Eigen/src/Core/Redux.h +++ b/Eigen/src/Core/Redux.h @@ -183,7 +183,7 @@ struct ei_redux_impl typedef typename Derived::Index Index; static EIGEN_STRONG_INLINE Scalar run(const Derived& mat, const Func& func) { - ei_assert(mat.rows()>0 && mat.cols()>0 && "you are using a non initialized matrix"); + ei_assert(mat.rows()>0 && mat.cols()>0 && "you are using an empty matrix"); Scalar res; res = mat.coeffByOuterInner(0, 0); for(Index i = 1; i < mat.innerSize(); ++i) @@ -210,6 +210,7 @@ struct ei_redux_impl static Scalar run(const Derived& mat, const Func& func) { const Index size = mat.size(); + ei_assert(size && "you are using an empty matrix"); const Index packetSize = ei_packet_traits::size; const Index alignedStart = ei_first_aligned(mat); enum { @@ -253,6 +254,7 @@ struct ei_redux_impl static Scalar run(const Derived& mat, const Func& func) { + ei_assert(mat.rows()>0 && mat.cols()>0 && "you are using an empty matrix"); const Index innerSize = mat.innerSize(); const Index outerSize = mat.outerSize(); enum { @@ -294,6 +296,7 @@ struct ei_redux_impl0 && mat.cols()>0 && "you are using an empty matrix"); Scalar res = func.predux(ei_redux_vec_unroller::run(mat,func)); if (VectorizedSize != Size) res = func(res,ei_redux_novec_unroller::run(mat,func)); @@ -345,6 +348,8 @@ template EIGEN_STRONG_INLINE typename ei_traits::Scalar DenseBase::sum() const { + if(SizeAtCompileTime==0 || (SizeAtCompileTime==Dynamic && size()==0)) + return Scalar(0); return this->redux(Eigen::ei_scalar_sum_op()); } @@ -370,6 +375,8 @@ template EIGEN_STRONG_INLINE typename ei_traits::Scalar DenseBase::prod() const { + if(SizeAtCompileTime==0 || (SizeAtCompileTime==Dynamic && size()==0)) + return Scalar(1); return this->redux(Eigen::ei_scalar_product_op()); } diff --git a/test/array_for_matrix.cpp b/test/array_for_matrix.cpp index 01e31d05b..3699b861a 100644 --- a/test/array_for_matrix.cpp +++ b/test/array_for_matrix.cpp @@ -72,6 +72,10 @@ template void array_for_matrix(const MatrixType& m) VERIFY_IS_APPROX(m3.rowwise() += rv1, m1.rowwise() + rv1); m3 = m1; VERIFY_IS_APPROX(m3.rowwise() -= rv1, m1.rowwise() - rv1); + + // empty objects + VERIFY_IS_APPROX(m1.block(0,0,0,cols).colwise().sum(), RowVectorType::Zero(cols)); + VERIFY_IS_APPROX(m1.block(0,0,rows,0).rowwise().prod(), ColVectorType::Ones(rows)); } template void comparisons(const MatrixType& m) diff --git a/test/redux.cpp b/test/redux.cpp index b28252903..9a1df71a8 100644 --- a/test/redux.cpp +++ b/test/redux.cpp @@ -64,6 +64,10 @@ template void matrixRedux(const MatrixType& m) VERIFY_IS_APPROX(m1.block(r0,c0,r1,c1).prod(), m1.block(r0,c0,r1,c1).eval().prod()); VERIFY_IS_APPROX(m1.block(r0,c0,r1,c1).real().minCoeff(), m1.block(r0,c0,r1,c1).real().eval().minCoeff()); VERIFY_IS_APPROX(m1.block(r0,c0,r1,c1).real().maxCoeff(), m1.block(r0,c0,r1,c1).real().eval().maxCoeff()); + + // test empty objects + VERIFY_IS_APPROX(m1.block(r0,c0,0,0).sum(), Scalar(0)); + VERIFY_IS_APPROX(m1.block(r0,c0,0,0).prod(), Scalar(1)); } template void vectorRedux(const VectorType& w) @@ -124,6 +128,13 @@ template void vectorRedux(const VectorType& w) VERIFY_IS_APPROX(minc, v.real().segment(i, size-2*i).minCoeff()); VERIFY_IS_APPROX(maxc, v.real().segment(i, size-2*i).maxCoeff()); } + + // test empty objects + VERIFY_IS_APPROX(v.head(0).sum(), Scalar(0)); + VERIFY_IS_APPROX(v.tail(0).prod(), Scalar(1)); + VERIFY_RAISES_ASSERT(v.head(0).mean()); + VERIFY_RAISES_ASSERT(v.head(0).minCoeff()); + VERIFY_RAISES_ASSERT(v.head(0).maxCoeff()); } void test_redux() From 6ab9e8632f0799c66bb7cae43592ebbb2db64bb6 Mon Sep 17 00:00:00 2001 From: Gael Guennebaud Date: Fri, 16 Jul 2010 16:38:58 +0200 Subject: [PATCH 16/41] fix bad fuzzy comparison in 3x3 tridiagonalization --- Eigen/src/Eigenvalues/Tridiagonalization.h | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Eigen/src/Eigenvalues/Tridiagonalization.h b/Eigen/src/Eigenvalues/Tridiagonalization.h index 611b89730..ed0b78047 100644 --- a/Eigen/src/Eigenvalues/Tridiagonalization.h +++ b/Eigen/src/Eigenvalues/Tridiagonalization.h @@ -458,7 +458,7 @@ struct ei_tridiagonalization_inplace_selector }; /** \internal - * Specialization for 3x3 matrices. + * Specialization for 3x3 real matrices. * Especially useful for plane fitting. */ template @@ -472,7 +472,7 @@ struct ei_tridiagonalization_inplace_selector { diag[0] = ei_real(mat(0,0)); RealScalar v1norm2 = ei_abs2(mat(2,0)); - if (ei_isMuchSmallerThan(v1norm2, RealScalar(1))) + if(v1norm2 == RealScalar(0) && ei_imag(mat(1,0))==RealScalar(0)) { diag[1] = ei_real(mat(1,1)); diag[2] = ei_real(mat(2,2)); @@ -495,8 +495,8 @@ struct ei_tridiagonalization_inplace_selector if (extractQ) { mat << 1, 0, 0, - 0, m01, m02, - 0, m02, -m01; + 0, m01, m02, + 0, m02, -m01; } } } From 883a8cbb2cf85f140ca0e0c8ca6064512cc61884 Mon Sep 17 00:00:00 2001 From: Gael Guennebaud Date: Fri, 16 Jul 2010 18:22:00 +0200 Subject: [PATCH 17/41] disable the optimized 3x3 path for complexes which was not working at all --- Eigen/src/Eigenvalues/Tridiagonalization.h | 32 ++++++++++++---------- 1 file changed, 17 insertions(+), 15 deletions(-) diff --git a/Eigen/src/Eigenvalues/Tridiagonalization.h b/Eigen/src/Eigenvalues/Tridiagonalization.h index ed0b78047..977ac6dba 100644 --- a/Eigen/src/Eigenvalues/Tridiagonalization.h +++ b/Eigen/src/Eigenvalues/Tridiagonalization.h @@ -384,7 +384,9 @@ void ei_tridiagonalization_inplace(MatrixType& matA, CoeffVectorType& hCoeffs) } // forward declaration, implementation at the end of this file -template +template::IsComplex> struct ei_tridiagonalization_inplace_selector; /** \brief Performs a full tridiagonalization in place @@ -439,7 +441,7 @@ void ei_tridiagonalization_inplace(MatrixType& mat, DiagonalType& diag, SubDiago /** \internal * General full tridiagonalization */ -template +template struct ei_tridiagonalization_inplace_selector { typedef typename Tridiagonalization::CoeffVectorType CoeffVectorType; @@ -462,7 +464,7 @@ struct ei_tridiagonalization_inplace_selector * Especially useful for plane fitting. */ template -struct ei_tridiagonalization_inplace_selector +struct ei_tridiagonalization_inplace_selector { typedef typename MatrixType::Scalar Scalar; typedef typename MatrixType::RealScalar RealScalar; @@ -470,14 +472,14 @@ struct ei_tridiagonalization_inplace_selector template static void run(MatrixType& mat, DiagonalType& diag, SubDiagonalType& subdiag, bool extractQ) { - diag[0] = ei_real(mat(0,0)); + diag[0] = mat(0,0); RealScalar v1norm2 = ei_abs2(mat(2,0)); - if(v1norm2 == RealScalar(0) && ei_imag(mat(1,0))==RealScalar(0)) + if(v1norm2 == RealScalar(0)) { - diag[1] = ei_real(mat(1,1)); - diag[2] = ei_real(mat(2,2)); - subdiag[0] = ei_real(mat(1,0)); - subdiag[1] = ei_real(mat(2,1)); + diag[1] = mat(1,1); + diag[2] = mat(2,2); + subdiag[0] = mat(1,0); + subdiag[1] = mat(2,1); if (extractQ) mat.setIdentity(); } @@ -485,13 +487,13 @@ struct ei_tridiagonalization_inplace_selector { RealScalar beta = ei_sqrt(ei_abs2(mat(1,0)) + v1norm2); RealScalar invBeta = RealScalar(1)/beta; - Scalar m01 = ei_conj(mat(1,0)) * invBeta; - Scalar m02 = ei_conj(mat(2,0)) * invBeta; - Scalar q = RealScalar(2)*m01*ei_conj(mat(2,1)) + m02*(mat(2,2) - mat(1,1)); - diag[1] = ei_real(mat(1,1) + m02*q); - diag[2] = ei_real(mat(2,2) - m02*q); + Scalar m01 = mat(1,0) * invBeta; + Scalar m02 = mat(2,0) * invBeta; + Scalar q = RealScalar(2)*m01*mat(2,1) + m02*(mat(2,2) - mat(1,1)); + diag[1] = mat(1,1) + m02*q; + diag[2] = mat(2,2) - m02*q; subdiag[0] = beta; - subdiag[1] = ei_real(ei_conj(mat(2,1)) - m01 * q); + subdiag[1] = mat(2,1) - m01 * q; if (extractQ) { mat << 1, 0, 0, From fb041c260c7e8162050034f19c5a228de8f7741e Mon Sep 17 00:00:00 2001 From: Gael Guennebaud Date: Fri, 16 Jul 2010 22:25:35 +0200 Subject: [PATCH 18/41] fix for empty matrices --- Eigen/src/Core/products/GeneralBlockPanelKernel.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Eigen/src/Core/products/GeneralBlockPanelKernel.h b/Eigen/src/Core/products/GeneralBlockPanelKernel.h index cf133f68f..c8eeeff4d 100644 --- a/Eigen/src/Core/products/GeneralBlockPanelKernel.h +++ b/Eigen/src/Core/products/GeneralBlockPanelKernel.h @@ -122,7 +122,7 @@ void computeProductBlockingSizes(std::ptrdiff_t& k, std::ptrdiff_t& m, std::ptrd ei_manage_caching_sizes(GetAction, &l1, &l2); k = std::min(k, l1/kdiv); - std::ptrdiff_t _m = l2/(4 * sizeof(LhsScalar) * k); + std::ptrdiff_t _m = k>0 ? l2/(4 * sizeof(LhsScalar) * k) : 0; if(_m Date: Fri, 16 Jul 2010 22:26:07 +0200 Subject: [PATCH 19/41] re-enable writing to reversed objects --- Eigen/src/Core/Reverse.h | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/Eigen/src/Core/Reverse.h b/Eigen/src/Core/Reverse.h index 5a96aeeb3..5858e684c 100644 --- a/Eigen/src/Core/Reverse.h +++ b/Eigen/src/Core/Reverse.h @@ -59,7 +59,7 @@ struct ei_traits > LinearAccess = ( (Direction==BothDirections) && (int(_MatrixTypeNested::Flags)&PacketAccessBit) ) ? LinearAccessBit : 0, - Flags = int(_MatrixTypeNested::Flags) & (HereditaryBits | PacketAccessBit | LinearAccess), + Flags = int(_MatrixTypeNested::Flags) & (HereditaryBits | PacketAccessBit | LinearAccess | DirectAccessBit), CoeffReadCost = _MatrixTypeNested::CoeffReadCost }; @@ -109,6 +109,11 @@ template class Reverse inline Index rows() const { return m_matrix.rows(); } inline Index cols() const { return m_matrix.cols(); } + inline Index innerStride() const + { + return -m_matrix.innerStride(); + } + inline Scalar& operator()(Index row, Index col) { ei_assert(row >= 0 && row < rows() && col >= 0 && col < cols()); From f59226e901c5af32c71d6087c84db8ff968ac413 Mon Sep 17 00:00:00 2001 From: Gael Guennebaud Date: Fri, 16 Jul 2010 22:27:24 +0200 Subject: [PATCH 20/41] fix compilation of blas lib --- bench/btl/libs/C_BLAS/blas.h | 2 +- blas/level1_impl.h | 4 +- blas/level3_impl.h | 178 +++++++++++++++++++---------------- blas/xerbla.cpp | 2 +- 4 files changed, 98 insertions(+), 88 deletions(-) diff --git a/bench/btl/libs/C_BLAS/blas.h b/bench/btl/libs/C_BLAS/blas.h index 1da288dd4..07cd9efd2 100644 --- a/bench/btl/libs/C_BLAS/blas.h +++ b/bench/btl/libs/C_BLAS/blas.h @@ -11,7 +11,7 @@ typedef long BLASLONG; typedef unsigned long BLASULONG; #endif -int BLASFUNC(xerbla)(char *, int *info, int); +int BLASFUNC(xerbla)(const char *, int *info, int); float BLASFUNC(sdot) (int *, float *, int *, float *, int *); float BLASFUNC(sdsdot)(int *, float *, float *, int *, float *, int *); diff --git a/blas/level1_impl.h b/blas/level1_impl.h index 9b79da6d5..5ea80064f 100644 --- a/blas/level1_impl.h +++ b/blas/level1_impl.h @@ -30,8 +30,6 @@ int EIGEN_BLAS_FUNC(axpy)(int *n, RealScalar *palpha, RealScalar *px, int *incx, Scalar* y = reinterpret_cast(py); Scalar alpha = *reinterpret_cast(palpha); -// std::cerr << "axpy " << *n << " " << alpha << " " << *incx << " " << *incy << "\n"; - if(*incx==1 && *incy==1) vector(y,*n) += alpha * vector(x,*n); else if(*incx>0 && *incy>0) vector(y,*n,*incy) += alpha * vector(x,*n,*incx); else if(*incx>0 && *incy<0) vector(y,*n,-*incy).reverse() += alpha * vector(x,*n,*incx); @@ -126,7 +124,7 @@ int EIGEN_CAT(EIGEN_CAT(i,SCALAR_SUFFIX),amax_)(int *n, RealScalar *px, int *inc if(*n<=0) return 0; - int ret; + DenseIndex ret; if(*incx==1) vector(x,*n).cwiseAbs().maxCoeff(&ret); else vector(x,*n,std::abs(*incx)).cwiseAbs().maxCoeff(&ret); diff --git a/blas/level3_impl.h b/blas/level3_impl.h index 9f04ddcb0..099a04889 100644 --- a/blas/level3_impl.h +++ b/blas/level3_impl.h @@ -27,7 +27,7 @@ int EIGEN_BLAS_FUNC(gemm)(char *opa, char *opb, int *m, int *n, int *k, RealScalar *palpha, RealScalar *pa, int *lda, RealScalar *pb, int *ldb, RealScalar *pbeta, RealScalar *pc, int *ldc) { // std::cerr << "in gemm " << *opa << " " << *opb << " " << *m << " " << *n << " " << *k << " " << *lda << " " << *ldb << " " << *ldc << " " << *palpha << " " << *pbeta << "\n"; - typedef void (*functype)(int, int, int, const Scalar *, int, const Scalar *, int, Scalar *, int, Scalar, Eigen::GemmParallelInfo*); + typedef void (*functype)(DenseIndex, DenseIndex, DenseIndex, const Scalar *, DenseIndex, const Scalar *, DenseIndex, Scalar *, DenseIndex, Scalar, ei_level3_blocking&, Eigen::GemmParallelInfo*); static functype func[12]; static bool init = false; @@ -35,15 +35,15 @@ int EIGEN_BLAS_FUNC(gemm)(char *opa, char *opb, int *m, int *n, int *k, RealScal { for(int k=0; k<12; ++k) func[k] = 0; - func[NOTR | (NOTR << 2)] = (ei_general_matrix_matrix_product::run); - func[TR | (NOTR << 2)] = (ei_general_matrix_matrix_product::run); - func[ADJ | (NOTR << 2)] = (ei_general_matrix_matrix_product::run); - func[NOTR | (TR << 2)] = (ei_general_matrix_matrix_product::run); - func[TR | (TR << 2)] = (ei_general_matrix_matrix_product::run); - func[ADJ | (TR << 2)] = (ei_general_matrix_matrix_product::run); - func[NOTR | (ADJ << 2)] = (ei_general_matrix_matrix_product::run); - func[TR | (ADJ << 2)] = (ei_general_matrix_matrix_product::run); - func[ADJ | (ADJ << 2)] = (ei_general_matrix_matrix_product::run); + func[NOTR | (NOTR << 2)] = (ei_general_matrix_matrix_product::run); + func[TR | (NOTR << 2)] = (ei_general_matrix_matrix_product::run); + func[ADJ | (NOTR << 2)] = (ei_general_matrix_matrix_product::run); + func[NOTR | (TR << 2)] = (ei_general_matrix_matrix_product::run); + func[TR | (TR << 2)] = (ei_general_matrix_matrix_product::run); + func[ADJ | (TR << 2)] = (ei_general_matrix_matrix_product::run); + func[NOTR | (ADJ << 2)] = (ei_general_matrix_matrix_product::run); + func[TR | (ADJ << 2)] = (ei_general_matrix_matrix_product::run); + func[ADJ | (ADJ << 2)] = (ei_general_matrix_matrix_product::run); init = true; } @@ -62,19 +62,23 @@ int EIGEN_BLAS_FUNC(gemm)(char *opa, char *opb, int *m, int *n, int *k, RealScal } if(beta!=Scalar(1)) + { if(beta==Scalar(0)) matrix(c, *m, *n, *ldc).setZero(); else matrix(c, *m, *n, *ldc) *= beta; + } - func[code](*m, *n, *k, a, *lda, b, *ldb, c, *ldc, alpha, 0); + ei_gemm_blocking_space blocking(*m,*n,*k); + + func[code](*m, *n, *k, a, *lda, b, *ldb, c, *ldc, alpha, blocking, 0); return 0; } int EIGEN_BLAS_FUNC(trsm)(char *side, char *uplo, char *opa, char *diag, int *m, int *n, RealScalar *palpha, RealScalar *pa, int *lda, RealScalar *pb, int *ldb) { // std::cerr << "in trsm " << *side << " " << *uplo << " " << *opa << " " << *diag << " " << *m << "," << *n << " " << *palpha << " " << *lda << " " << *ldb<< "\n"; - typedef void (*functype)(int, int, const Scalar *, int, Scalar *, int); + typedef void (*functype)(DenseIndex, DenseIndex, const Scalar *, DenseIndex, Scalar *, DenseIndex); static functype func[32]; static bool init = false; @@ -83,38 +87,38 @@ int EIGEN_BLAS_FUNC(trsm)(char *side, char *uplo, char *opa, char *diag, int *m, for(int k=0; k<32; ++k) func[k] = 0; - func[NOTR | (LEFT << 2) | (UP << 3) | (NUNIT << 4)] = (ei_triangular_solve_matrix::run); - func[TR | (LEFT << 2) | (UP << 3) | (NUNIT << 4)] = (ei_triangular_solve_matrix::run); - func[ADJ | (LEFT << 2) | (UP << 3) | (NUNIT << 4)] = (ei_triangular_solve_matrix::run); + func[NOTR | (LEFT << 2) | (UP << 3) | (NUNIT << 4)] = (ei_triangular_solve_matrix::run); + func[TR | (LEFT << 2) | (UP << 3) | (NUNIT << 4)] = (ei_triangular_solve_matrix::run); + func[ADJ | (LEFT << 2) | (UP << 3) | (NUNIT << 4)] = (ei_triangular_solve_matrix::run); - func[NOTR | (RIGHT << 2) | (UP << 3) | (NUNIT << 4)] = (ei_triangular_solve_matrix::run); - func[TR | (RIGHT << 2) | (UP << 3) | (NUNIT << 4)] = (ei_triangular_solve_matrix::run); - func[ADJ | (RIGHT << 2) | (UP << 3) | (NUNIT << 4)] = (ei_triangular_solve_matrix::run); + func[NOTR | (RIGHT << 2) | (UP << 3) | (NUNIT << 4)] = (ei_triangular_solve_matrix::run); + func[TR | (RIGHT << 2) | (UP << 3) | (NUNIT << 4)] = (ei_triangular_solve_matrix::run); + func[ADJ | (RIGHT << 2) | (UP << 3) | (NUNIT << 4)] = (ei_triangular_solve_matrix::run); - func[NOTR | (LEFT << 2) | (LO << 3) | (NUNIT << 4)] = (ei_triangular_solve_matrix::run); - func[TR | (LEFT << 2) | (LO << 3) | (NUNIT << 4)] = (ei_triangular_solve_matrix::run); - func[ADJ | (LEFT << 2) | (LO << 3) | (NUNIT << 4)] = (ei_triangular_solve_matrix::run); + func[NOTR | (LEFT << 2) | (LO << 3) | (NUNIT << 4)] = (ei_triangular_solve_matrix::run); + func[TR | (LEFT << 2) | (LO << 3) | (NUNIT << 4)] = (ei_triangular_solve_matrix::run); + func[ADJ | (LEFT << 2) | (LO << 3) | (NUNIT << 4)] = (ei_triangular_solve_matrix::run); - func[NOTR | (RIGHT << 2) | (LO << 3) | (NUNIT << 4)] = (ei_triangular_solve_matrix::run); - func[TR | (RIGHT << 2) | (LO << 3) | (NUNIT << 4)] = (ei_triangular_solve_matrix::run); - func[ADJ | (RIGHT << 2) | (LO << 3) | (NUNIT << 4)] = (ei_triangular_solve_matrix::run); + func[NOTR | (RIGHT << 2) | (LO << 3) | (NUNIT << 4)] = (ei_triangular_solve_matrix::run); + func[TR | (RIGHT << 2) | (LO << 3) | (NUNIT << 4)] = (ei_triangular_solve_matrix::run); + func[ADJ | (RIGHT << 2) | (LO << 3) | (NUNIT << 4)] = (ei_triangular_solve_matrix::run); - func[NOTR | (LEFT << 2) | (UP << 3) | (UNIT << 4)] = (ei_triangular_solve_matrix::run); - func[TR | (LEFT << 2) | (UP << 3) | (UNIT << 4)] = (ei_triangular_solve_matrix::run); - func[ADJ | (LEFT << 2) | (UP << 3) | (UNIT << 4)] = (ei_triangular_solve_matrix::run); + func[NOTR | (LEFT << 2) | (UP << 3) | (UNIT << 4)] = (ei_triangular_solve_matrix::run); + func[TR | (LEFT << 2) | (UP << 3) | (UNIT << 4)] = (ei_triangular_solve_matrix::run); + func[ADJ | (LEFT << 2) | (UP << 3) | (UNIT << 4)] = (ei_triangular_solve_matrix::run); - func[NOTR | (RIGHT << 2) | (UP << 3) | (UNIT << 4)] = (ei_triangular_solve_matrix::run); - func[TR | (RIGHT << 2) | (UP << 3) | (UNIT << 4)] = (ei_triangular_solve_matrix::run); - func[ADJ | (RIGHT << 2) | (UP << 3) | (UNIT << 4)] = (ei_triangular_solve_matrix::run); + func[NOTR | (RIGHT << 2) | (UP << 3) | (UNIT << 4)] = (ei_triangular_solve_matrix::run); + func[TR | (RIGHT << 2) | (UP << 3) | (UNIT << 4)] = (ei_triangular_solve_matrix::run); + func[ADJ | (RIGHT << 2) | (UP << 3) | (UNIT << 4)] = (ei_triangular_solve_matrix::run); - func[NOTR | (LEFT << 2) | (LO << 3) | (UNIT << 4)] = (ei_triangular_solve_matrix::run); - func[TR | (LEFT << 2) | (LO << 3) | (UNIT << 4)] = (ei_triangular_solve_matrix::run); - func[ADJ | (LEFT << 2) | (LO << 3) | (UNIT << 4)] = (ei_triangular_solve_matrix::run); + func[NOTR | (LEFT << 2) | (LO << 3) | (UNIT << 4)] = (ei_triangular_solve_matrix::run); + func[TR | (LEFT << 2) | (LO << 3) | (UNIT << 4)] = (ei_triangular_solve_matrix::run); + func[ADJ | (LEFT << 2) | (LO << 3) | (UNIT << 4)] = (ei_triangular_solve_matrix::run); - func[NOTR | (RIGHT << 2) | (LO << 3) | (UNIT << 4)] = (ei_triangular_solve_matrix::run); - func[TR | (RIGHT << 2) | (LO << 3) | (UNIT << 4)] = (ei_triangular_solve_matrix::run); - func[ADJ | (RIGHT << 2) | (LO << 3) | (UNIT << 4)] = (ei_triangular_solve_matrix::run); + func[NOTR | (RIGHT << 2) | (LO << 3) | (UNIT << 4)] = (ei_triangular_solve_matrix::run); + func[TR | (RIGHT << 2) | (LO << 3) | (UNIT << 4)] = (ei_triangular_solve_matrix::run); + func[ADJ | (RIGHT << 2) | (LO << 3) | (UNIT << 4)] = (ei_triangular_solve_matrix::run); init = true; } @@ -148,7 +152,7 @@ int EIGEN_BLAS_FUNC(trsm)(char *side, char *uplo, char *opa, char *diag, int *m, int EIGEN_BLAS_FUNC(trmm)(char *side, char *uplo, char *opa, char *diag, int *m, int *n, RealScalar *palpha, RealScalar *pa, int *lda, RealScalar *pb, int *ldb) { // std::cerr << "in trmm " << *side << " " << *uplo << " " << *opa << " " << *diag << " " << *m << " " << *n << " " << *lda << " " << *ldb << " " << *palpha << "\n"; - typedef void (*functype)(int, int, const Scalar *, int, const Scalar *, int, Scalar *, int, Scalar); + typedef void (*functype)(DenseIndex, DenseIndex, DenseIndex, const Scalar *, DenseIndex, const Scalar *, DenseIndex, Scalar *, DenseIndex, Scalar); static functype func[32]; static bool init = false; if(!init) @@ -156,37 +160,37 @@ int EIGEN_BLAS_FUNC(trmm)(char *side, char *uplo, char *opa, char *diag, int *m, for(int k=0; k<32; ++k) func[k] = 0; - func[NOTR | (LEFT << 2) | (UP << 3) | (NUNIT << 4)] = (ei_product_triangular_matrix_matrix::run); - func[TR | (LEFT << 2) | (UP << 3) | (NUNIT << 4)] = (ei_product_triangular_matrix_matrix::run); - func[ADJ | (LEFT << 2) | (UP << 3) | (NUNIT << 4)] = (ei_product_triangular_matrix_matrix::run); + func[NOTR | (LEFT << 2) | (UP << 3) | (NUNIT << 4)] = (ei_product_triangular_matrix_matrix::run); + func[TR | (LEFT << 2) | (UP << 3) | (NUNIT << 4)] = (ei_product_triangular_matrix_matrix::run); + func[ADJ | (LEFT << 2) | (UP << 3) | (NUNIT << 4)] = (ei_product_triangular_matrix_matrix::run); - func[NOTR | (RIGHT << 2) | (UP << 3) | (NUNIT << 4)] = (ei_product_triangular_matrix_matrix::run); - func[TR | (RIGHT << 2) | (UP << 3) | (NUNIT << 4)] = (ei_product_triangular_matrix_matrix::run); - func[ADJ | (RIGHT << 2) | (UP << 3) | (NUNIT << 4)] = (ei_product_triangular_matrix_matrix::run); + func[NOTR | (RIGHT << 2) | (UP << 3) | (NUNIT << 4)] = (ei_product_triangular_matrix_matrix::run); + func[TR | (RIGHT << 2) | (UP << 3) | (NUNIT << 4)] = (ei_product_triangular_matrix_matrix::run); + func[ADJ | (RIGHT << 2) | (UP << 3) | (NUNIT << 4)] = (ei_product_triangular_matrix_matrix::run); - func[NOTR | (LEFT << 2) | (LO << 3) | (NUNIT << 4)] = (ei_product_triangular_matrix_matrix::run); - func[TR | (LEFT << 2) | (LO << 3) | (NUNIT << 4)] = (ei_product_triangular_matrix_matrix::run); - func[ADJ | (LEFT << 2) | (LO << 3) | (NUNIT << 4)] = (ei_product_triangular_matrix_matrix::run); + func[NOTR | (LEFT << 2) | (LO << 3) | (NUNIT << 4)] = (ei_product_triangular_matrix_matrix::run); + func[TR | (LEFT << 2) | (LO << 3) | (NUNIT << 4)] = (ei_product_triangular_matrix_matrix::run); + func[ADJ | (LEFT << 2) | (LO << 3) | (NUNIT << 4)] = (ei_product_triangular_matrix_matrix::run); - func[NOTR | (RIGHT << 2) | (LO << 3) | (NUNIT << 4)] = (ei_product_triangular_matrix_matrix::run); - func[TR | (RIGHT << 2) | (LO << 3) | (NUNIT << 4)] = (ei_product_triangular_matrix_matrix::run); - func[ADJ | (RIGHT << 2) | (LO << 3) | (NUNIT << 4)] = (ei_product_triangular_matrix_matrix::run); + func[NOTR | (RIGHT << 2) | (LO << 3) | (NUNIT << 4)] = (ei_product_triangular_matrix_matrix::run); + func[TR | (RIGHT << 2) | (LO << 3) | (NUNIT << 4)] = (ei_product_triangular_matrix_matrix::run); + func[ADJ | (RIGHT << 2) | (LO << 3) | (NUNIT << 4)] = (ei_product_triangular_matrix_matrix::run); - func[NOTR | (LEFT << 2) | (UP << 3) | (UNIT << 4)] = (ei_product_triangular_matrix_matrix::run); - func[TR | (LEFT << 2) | (UP << 3) | (UNIT << 4)] = (ei_product_triangular_matrix_matrix::run); - func[ADJ | (LEFT << 2) | (UP << 3) | (UNIT << 4)] = (ei_product_triangular_matrix_matrix::run); + func[NOTR | (LEFT << 2) | (UP << 3) | (UNIT << 4)] = (ei_product_triangular_matrix_matrix::run); + func[TR | (LEFT << 2) | (UP << 3) | (UNIT << 4)] = (ei_product_triangular_matrix_matrix::run); + func[ADJ | (LEFT << 2) | (UP << 3) | (UNIT << 4)] = (ei_product_triangular_matrix_matrix::run); - func[NOTR | (RIGHT << 2) | (UP << 3) | (UNIT << 4)] = (ei_product_triangular_matrix_matrix::run); - func[TR | (RIGHT << 2) | (UP << 3) | (UNIT << 4)] = (ei_product_triangular_matrix_matrix::run); - func[ADJ | (RIGHT << 2) | (UP << 3) | (UNIT << 4)] = (ei_product_triangular_matrix_matrix::run); + func[NOTR | (RIGHT << 2) | (UP << 3) | (UNIT << 4)] = (ei_product_triangular_matrix_matrix::run); + func[TR | (RIGHT << 2) | (UP << 3) | (UNIT << 4)] = (ei_product_triangular_matrix_matrix::run); + func[ADJ | (RIGHT << 2) | (UP << 3) | (UNIT << 4)] = (ei_product_triangular_matrix_matrix::run); - func[NOTR | (LEFT << 2) | (LO << 3) | (UNIT << 4)] = (ei_product_triangular_matrix_matrix::run); - func[TR | (LEFT << 2) | (LO << 3) | (UNIT << 4)] = (ei_product_triangular_matrix_matrix::run); - func[ADJ | (LEFT << 2) | (LO << 3) | (UNIT << 4)] = (ei_product_triangular_matrix_matrix::run); + func[NOTR | (LEFT << 2) | (LO << 3) | (UNIT << 4)] = (ei_product_triangular_matrix_matrix::run); + func[TR | (LEFT << 2) | (LO << 3) | (UNIT << 4)] = (ei_product_triangular_matrix_matrix::run); + func[ADJ | (LEFT << 2) | (LO << 3) | (UNIT << 4)] = (ei_product_triangular_matrix_matrix::run); - func[NOTR | (RIGHT << 2) | (LO << 3) | (UNIT << 4)] = (ei_product_triangular_matrix_matrix::run); - func[TR | (RIGHT << 2) | (LO << 3) | (UNIT << 4)] = (ei_product_triangular_matrix_matrix::run); - func[ADJ | (RIGHT << 2) | (LO << 3) | (UNIT << 4)] = (ei_product_triangular_matrix_matrix::run); + func[NOTR | (RIGHT << 2) | (LO << 3) | (UNIT << 4)] = (ei_product_triangular_matrix_matrix::run); + func[TR | (RIGHT << 2) | (LO << 3) | (UNIT << 4)] = (ei_product_triangular_matrix_matrix::run); + func[ADJ | (RIGHT << 2) | (LO << 3) | (UNIT << 4)] = (ei_product_triangular_matrix_matrix::run); init = true; } @@ -208,9 +212,9 @@ int EIGEN_BLAS_FUNC(trmm)(char *side, char *uplo, char *opa, char *diag, int *m, matrix(b,*m,*n,*ldb).setZero(); if(SIDE(*side)==LEFT) - func[code](*m, *n, a, *lda, tmp.data(), tmp.outerStride(), b, *ldb, alpha); + func[code](*m, *n, *m, a, *lda, tmp.data(), tmp.outerStride(), b, *ldb, alpha); else - func[code](*n, *m, tmp.data(), tmp.outerStride(), a, *lda, b, *ldb, alpha); + func[code](*n, *m, *n, tmp.data(), tmp.outerStride(), a, *lda, b, *ldb, alpha); return 1; } @@ -233,16 +237,18 @@ int EIGEN_BLAS_FUNC(symm)(char *side, char *uplo, int *m, int *n, RealScalar *pa } if(beta!=Scalar(1)) + { if(beta==Scalar(0)) matrix(c, *m, *n, *ldc).setZero(); else matrix(c, *m, *n, *ldc) *= beta; + } if(SIDE(*side)==LEFT) - if(UPLO(*uplo)==UP) ei_product_selfadjoint_matrix::run(*m, *n, a, *lda, b, *ldb, c, *ldc, alpha); - else if(UPLO(*uplo)==LO) ei_product_selfadjoint_matrix::run(*m, *n, a, *lda, b, *ldb, c, *ldc, alpha); + if(UPLO(*uplo)==UP) ei_product_selfadjoint_matrix::run(*m, *n, a, *lda, b, *ldb, c, *ldc, alpha); + else if(UPLO(*uplo)==LO) ei_product_selfadjoint_matrix::run(*m, *n, a, *lda, b, *ldb, c, *ldc, alpha); else return 0; else if(SIDE(*side)==RIGHT) - if(UPLO(*uplo)==UP) ei_product_selfadjoint_matrix::run(*m, *n, b, *ldb, a, *lda, c, *ldc, alpha); - else if(UPLO(*uplo)==LO) ei_product_selfadjoint_matrix::run(*m, *n, b, *ldb, a, *lda, c, *ldc, alpha); + if(UPLO(*uplo)==UP) ei_product_selfadjoint_matrix::run(*m, *n, b, *ldb, a, *lda, c, *ldc, alpha); + else if(UPLO(*uplo)==LO) ei_product_selfadjoint_matrix::run(*m, *n, b, *ldb, a, *lda, c, *ldc, alpha); else return 0; else return 0; @@ -255,7 +261,7 @@ int EIGEN_BLAS_FUNC(symm)(char *side, char *uplo, int *m, int *n, RealScalar *pa int EIGEN_BLAS_FUNC(syrk)(char *uplo, char *op, int *n, int *k, RealScalar *palpha, RealScalar *pa, int *lda, RealScalar *pbeta, RealScalar *pc, int *ldc) { // std::cerr << "in syrk " << *uplo << " " << *op << " " << *n << " " << *k << " " << *palpha << " " << *lda << " " << *pbeta << " " << *ldc << "\n"; - typedef void (*functype)(int, int, const Scalar *, int, Scalar *, int, Scalar); + typedef void (*functype)(DenseIndex, DenseIndex, const Scalar *, DenseIndex, Scalar *, DenseIndex, Scalar); static functype func[8]; static bool init = false; @@ -264,13 +270,13 @@ int EIGEN_BLAS_FUNC(syrk)(char *uplo, char *op, int *n, int *k, RealScalar *palp for(int k=0; k<8; ++k) func[k] = 0; - func[NOTR | (UP << 2)] = (ei_selfadjoint_product::run); - func[TR | (UP << 2)] = (ei_selfadjoint_product::run); - func[ADJ | (UP << 2)] = (ei_selfadjoint_product::run); + func[NOTR | (UP << 2)] = (ei_selfadjoint_product::run); + func[TR | (UP << 2)] = (ei_selfadjoint_product::run); + func[ADJ | (UP << 2)] = (ei_selfadjoint_product::run); - func[NOTR | (LO << 2)] = (ei_selfadjoint_product::run); - func[TR | (LO << 2)] = (ei_selfadjoint_product::run); - func[ADJ | (LO << 2)] = (ei_selfadjoint_product::run); + func[NOTR | (LO << 2)] = (ei_selfadjoint_product::run); + func[TR | (LO << 2)] = (ei_selfadjoint_product::run); + func[ADJ | (LO << 2)] = (ei_selfadjoint_product::run); init = true; } @@ -289,8 +295,10 @@ int EIGEN_BLAS_FUNC(syrk)(char *uplo, char *op, int *n, int *k, RealScalar *palp } if(beta!=Scalar(1)) + { if(UPLO(*uplo)==UP) matrix(c, *n, *n, *ldc).triangularView() *= beta; else matrix(c, *n, *n, *ldc).triangularView() *= beta; + } func[code](*n, *k, a, *lda, c, *ldc, alpha); @@ -337,13 +345,17 @@ int EIGEN_BLAS_FUNC(hemm)(char *side, char *uplo, int *m, int *n, RealScalar *pa matrix(c, *m, *n, *ldc) *= beta; if(SIDE(*side)==LEFT) - if(UPLO(*uplo)==UP) ei_product_selfadjoint_matrix::run(*m, *n, a, *lda, b, *ldb, c, *ldc, alpha); - else if(UPLO(*uplo)==LO) ei_product_selfadjoint_matrix::run(*m, *n, a, *lda, b, *ldb, c, *ldc, alpha); + { + if(UPLO(*uplo)==UP) ei_product_selfadjoint_matrix::run(*m, *n, a, *lda, b, *ldb, c, *ldc, alpha); + else if(UPLO(*uplo)==LO) ei_product_selfadjoint_matrix::run(*m, *n, a, *lda, b, *ldb, c, *ldc, alpha); else return 0; + } else if(SIDE(*side)==RIGHT) - if(UPLO(*uplo)==UP) ei_product_selfadjoint_matrix::run(*m, *n, b, *ldb, a, *lda, c, *ldc, alpha); - else if(UPLO(*uplo)==LO) ei_product_selfadjoint_matrix::run(*m, *n, b, *ldb, a, *lda, c, *ldc, alpha); + { + if(UPLO(*uplo)==UP) ei_product_selfadjoint_matrix::run(*m, *n, b, *ldb, a, *lda, c, *ldc, alpha); + else if(UPLO(*uplo)==LO) ei_product_selfadjoint_matrix::run(*m, *n, b, *ldb, a, *lda, c, *ldc, alpha); else return 0; + } else { return 0; @@ -356,7 +368,7 @@ int EIGEN_BLAS_FUNC(hemm)(char *side, char *uplo, int *m, int *n, RealScalar *pa // c = alpha*conj(a')*a + beta*c for op = 'C'or'c' int EIGEN_BLAS_FUNC(herk)(char *uplo, char *op, int *n, int *k, RealScalar *palpha, RealScalar *pa, int *lda, RealScalar *pbeta, RealScalar *pc, int *ldc) { - typedef void (*functype)(int, int, const Scalar *, int, Scalar *, int, Scalar); + typedef void (*functype)(DenseIndex, DenseIndex, const Scalar *, DenseIndex, Scalar *, DenseIndex, Scalar); static functype func[8]; static bool init = false; @@ -365,11 +377,11 @@ int EIGEN_BLAS_FUNC(herk)(char *uplo, char *op, int *n, int *k, RealScalar *palp for(int k=0; k<8; ++k) func[k] = 0; - func[NOTR | (UP << 2)] = (ei_selfadjoint_product::run); - func[ADJ | (UP << 2)] = (ei_selfadjoint_product::run); + func[NOTR | (UP << 2)] = (ei_selfadjoint_product::run); + func[ADJ | (UP << 2)] = (ei_selfadjoint_product::run); - func[NOTR | (LO << 2)] = (ei_selfadjoint_product::run); - func[ADJ | (LO << 2)] = (ei_selfadjoint_product::run); + func[NOTR | (LO << 2)] = (ei_selfadjoint_product::run); + func[ADJ | (LO << 2)] = (ei_selfadjoint_product::run); init = true; } diff --git a/blas/xerbla.cpp b/blas/xerbla.cpp index 2e7ad6eff..bda1d2f46 100644 --- a/blas/xerbla.cpp +++ b/blas/xerbla.cpp @@ -6,7 +6,7 @@ extern "C" { #endif -int xerbla_(char * msg, int *info, int) +int xerbla_(const char * msg, int *info, int) { std::cerr << "Eigen BLAS ERROR #" << *info << ": " << msg << "\n"; return 0; From cbd6fe323c77ae93c3fbd7ee300a2deeebf39554 Mon Sep 17 00:00:00 2001 From: Gael Guennebaud Date: Fri, 16 Jul 2010 23:30:06 +0200 Subject: [PATCH 21/41] fix a couple a issue with blas (new TRMM api, and enforece column major) --- blas/common.h | 6 +++--- blas/level3_impl.h | 13 +++++++------ 2 files changed, 10 insertions(+), 9 deletions(-) diff --git a/blas/common.h b/blas/common.h index fa211b141..843e64ab7 100644 --- a/blas/common.h +++ b/blas/common.h @@ -86,15 +86,15 @@ enum Conj = IsComplex }; -typedef Map, 0, OuterStride > MatrixType; +typedef Map, 0, OuterStride<> > MatrixType; typedef Map, 0, InnerStride > StridedVectorType; typedef Map > CompactVectorType; template -Map, 0, OuterStride > +Map, 0, OuterStride<> > matrix(T* data, int rows, int cols, int stride) { - return Map, 0, OuterStride >(data, rows, cols, OuterStride(stride)); + return Map, 0, OuterStride<> >(data, rows, cols, OuterStride<>(stride)); } template diff --git a/blas/level3_impl.h b/blas/level3_impl.h index 099a04889..ff7ed6752 100644 --- a/blas/level3_impl.h +++ b/blas/level3_impl.h @@ -63,10 +63,8 @@ int EIGEN_BLAS_FUNC(gemm)(char *opa, char *opb, int *m, int *n, int *k, RealScal if(beta!=Scalar(1)) { - if(beta==Scalar(0)) - matrix(c, *m, *n, *ldc).setZero(); - else - matrix(c, *m, *n, *ldc) *= beta; + if(beta==Scalar(0)) matrix(c, *m, *n, *ldc).setZero(); + else matrix(c, *m, *n, *ldc) *= beta; } ei_gemm_blocking_space blocking(*m,*n,*k); @@ -207,14 +205,17 @@ int EIGEN_BLAS_FUNC(trmm)(char *side, char *uplo, char *opa, char *diag, int *m, return 0; } + if(*m==0 || *n==0) + return 1; + // FIXME find a way to avoid this copy - Matrix tmp = matrix(b,*m,*n,*ldb); + Matrix tmp = matrix(b,*m,*n,*ldb); matrix(b,*m,*n,*ldb).setZero(); if(SIDE(*side)==LEFT) func[code](*m, *n, *m, a, *lda, tmp.data(), tmp.outerStride(), b, *ldb, alpha); else - func[code](*n, *m, *n, tmp.data(), tmp.outerStride(), a, *lda, b, *ldb, alpha); + func[code](*m, *n, *n, tmp.data(), tmp.outerStride(), a, *lda, b, *ldb, alpha); return 1; } From 2d78023815e623b026852d8369433711bf18b07e Mon Sep 17 00:00:00 2001 From: Gael Guennebaud Date: Sat, 17 Jul 2010 11:57:54 +0200 Subject: [PATCH 22/41] fix hemm to not use the imaginary part of the diagonal entries --- Eigen/src/Core/products/SelfadjointMatrixMatrix.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Eigen/src/Core/products/SelfadjointMatrixMatrix.h b/Eigen/src/Core/products/SelfadjointMatrixMatrix.h index d8fa1bd9c..4a95ad5e1 100644 --- a/Eigen/src/Core/products/SelfadjointMatrixMatrix.h +++ b/Eigen/src/Core/products/SelfadjointMatrixMatrix.h @@ -136,7 +136,7 @@ struct ei_symm_pack_rhs for (Index w=0 ; w Date: Sat, 17 Jul 2010 11:59:09 +0200 Subject: [PATCH 23/41] fix level3 blas: it now passes all computational tests --- blas/level3_impl.h | 152 +++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 139 insertions(+), 13 deletions(-) diff --git a/blas/level3_impl.h b/blas/level3_impl.h index ff7ed6752..38b2637c3 100644 --- a/blas/level3_impl.h +++ b/blas/level3_impl.h @@ -243,6 +243,30 @@ int EIGEN_BLAS_FUNC(symm)(char *side, char *uplo, int *m, int *n, RealScalar *pa else matrix(c, *m, *n, *ldc) *= beta; } + if(*m==0 || *n==0) + { + return 1; + } + + #if ISCOMPLEX + // FIXME add support for symmetric complex matrix + int size = (SIDE(*side)==LEFT) ? (*m) : (*n); + Matrix matA(size,size); + if(UPLO(*uplo)==UP) + { + matA.triangularView() = matrix(a,size,size,*lda); + matA.triangularView() = matrix(a,size,size,*lda).transpose(); + } + else if(UPLO(*uplo)==LO) + { + matA.triangularView() = matrix(a,size,size,*lda); + matA.triangularView() = matrix(a,size,size,*lda).transpose(); + } + if(SIDE(*side)==LEFT) + matrix(c, *m, *n, *ldc) += alpha * matA * matrix(b, *m, *n, *ldb); + else if(SIDE(*side)==RIGHT) + matrix(c, *m, *n, *ldc) += alpha * matrix(b, *m, *n, *ldb) * matA; + #else if(SIDE(*side)==LEFT) if(UPLO(*uplo)==UP) ei_product_selfadjoint_matrix::run(*m, *n, a, *lda, b, *ldb, c, *ldc, alpha); else if(UPLO(*uplo)==LO) ei_product_selfadjoint_matrix::run(*m, *n, a, *lda, b, *ldb, c, *ldc, alpha); @@ -253,6 +277,7 @@ int EIGEN_BLAS_FUNC(symm)(char *side, char *uplo, int *m, int *n, RealScalar *pa else return 0; else return 0; + #endif return 0; } @@ -301,7 +326,25 @@ int EIGEN_BLAS_FUNC(syrk)(char *uplo, char *op, int *n, int *k, RealScalar *palp else matrix(c, *n, *n, *ldc).triangularView() *= beta; } + #if ISCOMPLEX + // FIXME add support for symmetric complex matrix + if(UPLO(*uplo)==UP) + { + if(OP(*op)==NOTR) + matrix(c, *n, *n, *ldc).triangularView() += alpha * matrix(a,*n,*k,*lda) * matrix(a,*n,*k,*lda).transpose(); + else + matrix(c, *n, *n, *ldc).triangularView() += alpha * matrix(a,*k,*n,*lda).transpose() * matrix(a,*k,*n,*lda); + } + else + { + if(OP(*op)==NOTR) + matrix(c, *n, *n, *ldc).triangularView() += alpha * matrix(a,*n,*k,*lda) * matrix(a,*n,*k,*lda).transpose(); + else + matrix(c, *n, *n, *ldc).triangularView() += alpha * matrix(a,*k,*n,*lda).transpose() * matrix(a,*k,*n,*lda); + } + #else func[code](*n, *k, a, *lda, c, *ldc, alpha); + #endif return 0; } @@ -316,8 +359,44 @@ int EIGEN_BLAS_FUNC(syr2k)(char *uplo, char *op, int *n, int *k, RealScalar *pal Scalar alpha = *reinterpret_cast(palpha); Scalar beta = *reinterpret_cast(pbeta); - // TODO - std::cerr << "Eigen BLAS: _syr2k is not implemented yet\n"; + if(*n<=0 || *k<0) + { + return 0; + } + + if(beta!=Scalar(1)) + { + if(UPLO(*uplo)==UP) matrix(c, *n, *n, *ldc).triangularView() *= beta; + else matrix(c, *n, *n, *ldc).triangularView() *= beta; + } + + if(*k==0) + return 1; + + if(OP(*op)==NOTR) + { + if(UPLO(*uplo)==UP) + { + matrix(c, *n, *n, *ldc).triangularView() + += alpha *matrix(a, *n, *k, *lda)*matrix(b, *n, *k, *ldb).transpose() + + alpha*matrix(b, *n, *k, *ldb)*matrix(a, *n, *k, *lda).transpose(); + } + else if(UPLO(*uplo)==LO) + matrix(c, *n, *n, *ldc).triangularView() + += alpha*matrix(a, *n, *k, *lda)*matrix(b, *n, *k, *ldb).transpose() + + alpha*matrix(b, *n, *k, *ldb)*matrix(a, *n, *k, *lda).transpose(); + } + else if(OP(*op)==TR || OP(*op)==ADJ) + { + if(UPLO(*uplo)==UP) + matrix(c, *n, *n, *ldc).triangularView() + += alpha*matrix(a, *k, *n, *lda).transpose()*matrix(b, *k, *n, *ldb) + + alpha*matrix(b, *k, *n, *ldb).transpose()*matrix(a, *k, *n, *lda); + else if(UPLO(*uplo)==LO) + matrix(c, *n, *n, *ldc).triangularView() + += alpha*matrix(a, *k, *n, *lda).transpose()*matrix(b, *k, *n, *ldb) + + alpha*matrix(b, *k, *n, *ldb).transpose()*matrix(a, *k, *n, *lda); + } return 0; } @@ -342,19 +421,30 @@ int EIGEN_BLAS_FUNC(hemm)(char *side, char *uplo, int *m, int *n, RealScalar *pa return 0; } - if(beta!=Scalar(1)) + if(beta==Scalar(0)) + matrix(c, *m, *n, *ldc).setZero(); + else if(beta!=Scalar(1)) matrix(c, *m, *n, *ldc) *= beta; + + if(*m==0 || *n==0) + { + return 1; + } if(SIDE(*side)==LEFT) { - if(UPLO(*uplo)==UP) ei_product_selfadjoint_matrix::run(*m, *n, a, *lda, b, *ldb, c, *ldc, alpha); - else if(UPLO(*uplo)==LO) ei_product_selfadjoint_matrix::run(*m, *n, a, *lda, b, *ldb, c, *ldc, alpha); + if(UPLO(*uplo)==UP) ei_product_selfadjoint_matrix + ::run(*m, *n, a, *lda, b, *ldb, c, *ldc, alpha); + else if(UPLO(*uplo)==LO) ei_product_selfadjoint_matrix + ::run(*m, *n, a, *lda, b, *ldb, c, *ldc, alpha); else return 0; } else if(SIDE(*side)==RIGHT) { - if(UPLO(*uplo)==UP) ei_product_selfadjoint_matrix::run(*m, *n, b, *ldb, a, *lda, c, *ldc, alpha); - else if(UPLO(*uplo)==LO) ei_product_selfadjoint_matrix::run(*m, *n, b, *ldb, a, *lda, c, *ldc, alpha); + if(UPLO(*uplo)==UP) matrix(c,*m,*n,*ldc) += alpha * matrix(b,*m,*n,*ldb) * matrix(a,*n,*n,*lda).selfadjointView();/*ei_product_selfadjoint_matrix + ::run(*m, *n, b, *ldb, a, *lda, c, *ldc, alpha);*/ + else if(UPLO(*uplo)==LO) ei_product_selfadjoint_matrix + ::run(*m, *n, b, *ldb, a, *lda, c, *ldc, alpha); else return 0; } else @@ -421,24 +511,60 @@ int EIGEN_BLAS_FUNC(herk)(char *uplo, char *op, int *n, int *k, RealScalar *palp } // c = alpha*a*conj(b') + conj(alpha)*b*conj(a') + beta*c, for op = 'N'or'n' -// c = alpha*conj(b')*a + conj(alpha)*conj(a')*b + beta*c, for op = 'C'or'c' +// c = alpha*conj(a')*b + conj(alpha)*conj(b')*a + beta*c, for op = 'C'or'c' int EIGEN_BLAS_FUNC(her2k)(char *uplo, char *op, int *n, int *k, RealScalar *palpha, RealScalar *pa, int *lda, RealScalar *pb, int *ldb, RealScalar *pbeta, RealScalar *pc, int *ldc) { Scalar* a = reinterpret_cast(pa); Scalar* b = reinterpret_cast(pb); Scalar* c = reinterpret_cast(pc); Scalar alpha = *reinterpret_cast(palpha); - Scalar beta = *reinterpret_cast(pbeta); + RealScalar beta = *pbeta; - if(*n<0 || *k<0) + if(*n<=0 || *k<0) { return 0; } - // TODO - std::cerr << "Eigen BLAS: _her2k is not implemented yet\n"; + if(beta!=RealScalar(1)) + { + if(UPLO(*uplo)==UP) matrix(c, *n, *n, *ldc).triangularView() *= beta; + else matrix(c, *n, *n, *ldc).triangularView() *= beta; - return 0; + matrix(c, *n, *n, *ldc).diagonal().real() *= beta; + matrix(c, *n, *n, *ldc).diagonal().imag().setZero(); + } + else if(*k>0 && alpha!=Scalar(0)) + matrix(c, *n, *n, *ldc).diagonal().imag().setZero(); + + if(*k==0) + return 1; + + if(OP(*op)==NOTR) + { + if(UPLO(*uplo)==UP) + { + matrix(c, *n, *n, *ldc).triangularView() + += alpha *matrix(a, *n, *k, *lda)*matrix(b, *n, *k, *ldb).adjoint() + + ei_conj(alpha)*matrix(b, *n, *k, *ldb)*matrix(a, *n, *k, *lda).adjoint(); + } + else if(UPLO(*uplo)==LO) + matrix(c, *n, *n, *ldc).triangularView() + += alpha*matrix(a, *n, *k, *lda)*matrix(b, *n, *k, *ldb).adjoint() + + ei_conj(alpha)*matrix(b, *n, *k, *ldb)*matrix(a, *n, *k, *lda).adjoint(); + } + else if(OP(*op)==ADJ) + { + if(UPLO(*uplo)==UP) + matrix(c, *n, *n, *ldc).triangularView() + += alpha*matrix(a, *k, *n, *lda).adjoint()*matrix(b, *k, *n, *ldb) + + ei_conj(alpha)*matrix(b, *k, *n, *ldb).adjoint()*matrix(a, *k, *n, *lda); + else if(UPLO(*uplo)==LO) + matrix(c, *n, *n, *ldc).triangularView() + += alpha*matrix(a, *k, *n, *lda).adjoint()*matrix(b, *k, *n, *ldb) + + ei_conj(alpha)*matrix(b, *k, *n, *ldb).adjoint()*matrix(a, *k, *n, *lda); + } + + return 1; } #endif // ISCOMPLEX From 2a820d41df2fcbf34d14d538ba8280271a96ad92 Mon Sep 17 00:00:00 2001 From: Gael Guennebaud Date: Sat, 17 Jul 2010 13:49:43 +0200 Subject: [PATCH 24/41] finish/fix level1 blas, all test pass --- bench/btl/libs/C_BLAS/blas.h | 8 +-- blas/common.h | 1 + blas/level1_impl.h | 99 +++++++++++++++++++++++++----------- 3 files changed, 73 insertions(+), 35 deletions(-) diff --git a/bench/btl/libs/C_BLAS/blas.h b/bench/btl/libs/C_BLAS/blas.h index 07cd9efd2..ab3d44052 100644 --- a/bench/btl/libs/C_BLAS/blas.h +++ b/bench/btl/libs/C_BLAS/blas.h @@ -38,10 +38,10 @@ void BLASFUNC(zdotc) (double *, int *, double *, int *, double *, int *); void BLASFUNC(xdotu) (double *, int *, double *, int *, double *, int *); void BLASFUNC(xdotc) (double *, int *, double *, int *, double *, int *); #else -float BLASFUNC(cdotu) (int *, float *, int *, float *, int *); -float BLASFUNC(cdotc) (int *, float *, int *, float *, int *); -double BLASFUNC(zdotu) (int *, double *, int *, double *, int *); -double BLASFUNC(zdotc) (int *, double *, int *, double *, int *); +std::complex BLASFUNC(cdotu) (int *, float *, int *, float *, int *); +std::complex BLASFUNC(cdotc) (int *, float *, int *, float *, int *); +std::complex BLASFUNC(zdotu) (int *, double *, int *, double *, int *); +std::complex BLASFUNC(zdotc) (int *, double *, int *, double *, int *); double BLASFUNC(xdotu) (int *, double *, int *, double *, int *); double BLASFUNC(xdotc) (int *, double *, int *, double *, int *); #endif diff --git a/blas/common.h b/blas/common.h index 843e64ab7..5e7117dee 100644 --- a/blas/common.h +++ b/blas/common.h @@ -26,6 +26,7 @@ #define EIGEN_BLAS_COMMON_H #include +#include #ifndef SCALAR #error the token SCALAR must be defined to compile this file diff --git a/blas/level1_impl.h b/blas/level1_impl.h index 5ea80064f..1665310c4 100644 --- a/blas/level1_impl.h +++ b/blas/level1_impl.h @@ -153,44 +153,36 @@ Scalar EIGEN_BLAS_FUNC(sdot)(int *n, RealScalar *px, int *incx, RealScalar *py, #if ISCOMPLEX // computes a dot product of a conjugated vector with another vector. -void EIGEN_BLAS_FUNC(dotc)(RealScalar* dot, int *n, RealScalar *px, int *incx, RealScalar *py, int *incy) +Scalar EIGEN_BLAS_FUNC(dotc)(int *n, RealScalar *px, int *incx, RealScalar *py, int *incy) { - - std::cerr << "Eigen BLAS: _dotc is not implemented yet\n"; - - return; - - // TODO: find how to return a complex to fortran - // std::cerr << "_dotc " << *n << " " << *incx << " " << *incy << "\n"; Scalar* x = reinterpret_cast(px); Scalar* y = reinterpret_cast(py); - if(*incx==1 && *incy==1) - *reinterpret_cast(dot) = vector(x,*n).dot(vector(y,*n)); - else - *reinterpret_cast(dot) = vector(x,*n,*incx).dot(vector(y,*n,*incy)); + Scalar res; + if(*incx==1 && *incy==1) res = (vector(x,*n).dot(vector(y,*n))); + else if(*incx>0 && *incy>0) res = (vector(x,*n,*incx).dot(vector(y,*n,*incy))); + else if(*incx<0 && *incy>0) res = (vector(x,*n,-*incx).reverse().dot(vector(y,*n,*incy))); + else if(*incx>0 && *incy<0) res = (vector(x,*n,*incx).dot(vector(y,*n,-*incy).reverse())); + else if(*incx<0 && *incy<0) res = (vector(x,*n,-*incx).reverse().dot(vector(y,*n,-*incy).reverse())); + return res; } // computes a vector-vector dot product without complex conjugation. -void EIGEN_BLAS_FUNC(dotu)(RealScalar* dot, int *n, RealScalar *px, int *incx, RealScalar *py, int *incy) +Scalar EIGEN_BLAS_FUNC(dotu)(int *n, RealScalar *px, int *incx, RealScalar *py, int *incy) { - std::cerr << "Eigen BLAS: _dotu is not implemented yet\n"; - - return; - - // TODO: find how to return a complex to fortran - // std::cerr << "_dotu " << *n << " " << *incx << " " << *incy << "\n"; Scalar* x = reinterpret_cast(px); Scalar* y = reinterpret_cast(py); - - if(*incx==1 && *incy==1) - *reinterpret_cast(dot) = (vector(x,*n).cwiseProduct(vector(y,*n))).sum(); - else - *reinterpret_cast(dot) = (vector(x,*n,*incx).cwiseProduct(vector(y,*n,*incy))).sum(); + Scalar res; + if(*incx==1 && *incy==1) res = (vector(x,*n).cwiseProduct(vector(y,*n))).sum(); + else if(*incx>0 && *incy>0) res = (vector(x,*n,*incx).cwiseProduct(vector(y,*n,*incy))).sum(); + else if(*incx<0 && *incy>0) res = (vector(x,*n,-*incx).reverse().cwiseProduct(vector(y,*n,*incy))).sum(); + else if(*incx>0 && *incy<0) res = (vector(x,*n,*incx).cwiseProduct(vector(y,*n,-*incy).reverse())).sum(); + else if(*incx<0 && *incy<0) res = (vector(x,*n,-*incx).reverse().cwiseProduct(vector(y,*n,-*incy).reverse())).sum(); + return res; } #endif // ISCOMPLEX @@ -251,15 +243,60 @@ int EIGEN_BLAS_FUNC(rot)(int *n, RealScalar *px, int *incx, RealScalar *py, int int EIGEN_BLAS_FUNC(rotg)(RealScalar *pa, RealScalar *pb, RealScalar *pc, RealScalar *ps) { - Scalar a = *reinterpret_cast(pa); - Scalar b = *reinterpret_cast(pb); - Scalar* c = reinterpret_cast(pc); + Scalar& a = *reinterpret_cast(pa); + Scalar& b = *reinterpret_cast(pb); + RealScalar* c = pc; Scalar* s = reinterpret_cast(ps); - PlanarRotation r; - r.makeGivens(a,b); - *c = r.c(); - *s = r.s(); + #if !ISCOMPLEX + Scalar r,z; + Scalar aa = ei_abs(a); + Scalar ab = ei_abs(b); + if((aa+ab)==Scalar(0)) + { + *c = 1; + *s = 0; + r = 0; + z = 0; + } + else + { + r = ei_sqrt(a*a + b*b); + Scalar amax = aa>ab ? a : b; + r = amax>0 ? r : -r; + *c = a/r; + *s = b/r; + z = 1; + if (aa > ab) z = *s; + if (ab > aa && *c!=RealScalar(0)) + z = Scalar(1)/ *c; + } + *pa = r; + *pb = z; + #else + Scalar alpha; + RealScalar norm,scale; + if(ei_abs(a)==RealScalar(0)) + { + *c = RealScalar(0); + *s = Scalar(1); + a = b; + } + else + { + scale = ei_abs(a) + ei_abs(b); + norm = scale*ei_sqrt((ei_abs2(a/scale))+ (ei_abs2(b/scale))); + alpha = a/ei_abs(a); + *c = ei_abs(a)/norm; + *s = alpha*ei_conj(b)/norm; + a = alpha*norm; + } + #endif + +// PlanarRotation r; +// r.makeGivens(a,b); +// *c = r.c(); +// *s = r.s(); return 0; } From ea27678153351f3b0507dc3525d95560629ac0e6 Mon Sep 17 00:00:00 2001 From: Gael Guennebaud Date: Sun, 18 Jul 2010 17:10:11 +0200 Subject: [PATCH 25/41] fix compilation of ei_tridiagonalization_inplace_selector for 1x1 matrix --- Eigen/src/Eigenvalues/ComplexEigenSolver.h | 4 ++-- Eigen/src/Eigenvalues/Tridiagonalization.h | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/Eigen/src/Eigenvalues/ComplexEigenSolver.h b/Eigen/src/Eigenvalues/ComplexEigenSolver.h index 08276c5c0..7bf1d140e 100644 --- a/Eigen/src/Eigenvalues/ComplexEigenSolver.h +++ b/Eigen/src/Eigenvalues/ComplexEigenSolver.h @@ -291,8 +291,8 @@ void ComplexEigenSolver::doComputeEigenvectors(RealScalar matrixnorm ComplexScalar z = m_schur.matrixT().coeff(i,i) - m_schur.matrixT().coeff(k,k); if(z==ComplexScalar(0)) { - // If the i-th and k-th eigenvalue are equal, then z equals 0. - // Use a small value instead, to prevent division by zero. + // If the i-th and k-th eigenvalue are equal, then z equals 0. + // Use a small value instead, to prevent division by zero. ei_real_ref(z) = NumTraits::epsilon() * matrixnorm; } m_matX.coeffRef(i,k) = m_matX.coeff(i,k) / z; diff --git a/Eigen/src/Eigenvalues/Tridiagonalization.h b/Eigen/src/Eigenvalues/Tridiagonalization.h index 977ac6dba..4211981af 100644 --- a/Eigen/src/Eigenvalues/Tridiagonalization.h +++ b/Eigen/src/Eigenvalues/Tridiagonalization.h @@ -507,8 +507,8 @@ struct ei_tridiagonalization_inplace_selector /** \internal * Trivial specialization for 1x1 matrices */ -template -struct ei_tridiagonalization_inplace_selector +template +struct ei_tridiagonalization_inplace_selector { typedef typename MatrixType::Scalar Scalar; From 78d3c54631e0ca25cde3efab6ba0445f83ef3514 Mon Sep 17 00:00:00 2001 From: Gael Guennebaud Date: Sun, 18 Jul 2010 17:26:06 +0200 Subject: [PATCH 26/41] add a small bench demoing the possibilities of a direct 3x3 eigen decomposition --- bench/eig33.cpp | 139 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 139 insertions(+) create mode 100644 bench/eig33.cpp diff --git a/bench/eig33.cpp b/bench/eig33.cpp new file mode 100644 index 000000000..2016c2c01 --- /dev/null +++ b/bench/eig33.cpp @@ -0,0 +1,139 @@ +#include +#include +#include +#include +#include + +using namespace Eigen; +using namespace std; + +template +inline void computeRoots (const Matrix& rkA, Roots& adRoot) +{ + typedef typename Matrix::Scalar Scalar; + const Scalar msInv3 = 1.0/3.0; + const Scalar msRoot3 = ei_sqrt(Scalar(3.0)); + + Scalar dA00 = rkA(0,0); + Scalar dA01 = rkA(0,1); + Scalar dA02 = rkA(0,2); + Scalar dA11 = rkA(1,1); + Scalar dA12 = rkA(1,2); + Scalar dA22 = rkA(2,2); + + // The characteristic equation is x^3 - c2*x^2 + c1*x - c0 = 0. The + // eigenvalues are the roots to this equation, all guaranteed to be + // real-valued, because the matrix is symmetric. + Scalar dC0 = dA00*dA11*dA22 + Scalar(2)*dA01*dA02*dA12 - dA00*dA12*dA12 - dA11*dA02*dA02 - dA22*dA01*dA01; + Scalar dC1 = dA00*dA11 - dA01*dA01 + dA00*dA22 - dA02*dA02 + dA11*dA22 - dA12*dA12; + Scalar dC2 = dA00 + dA11 + dA22; + + // Construct the parameters used in classifying the roots of the equation + // and in solving the equation for the roots in closed form. + Scalar dC2Div3 = dC2*msInv3; + Scalar dADiv3 = (dC1 - dC2*dC2Div3)*msInv3; + if (dADiv3 > Scalar(0)) + dADiv3 = Scalar(0); + + Scalar dMBDiv2 = Scalar(0.5)*(dC0 + dC2Div3*(Scalar(2)*dC2Div3*dC2Div3 - dC1)); + + Scalar dQ = dMBDiv2*dMBDiv2 + dADiv3*dADiv3*dADiv3; + if (dQ > Scalar(0)) + dQ = Scalar(0); + + // Compute the eigenvalues by solving for the roots of the polynomial. + Scalar dMagnitude = ei_sqrt(-dADiv3); + Scalar dAngle = std::atan2(ei_sqrt(-dQ),dMBDiv2)*msInv3; + Scalar dCos = ei_cos(dAngle); + Scalar dSin = ei_sin(dAngle); + adRoot(0) = dC2Div3 + 2.f*dMagnitude*dCos; + adRoot(1) = dC2Div3 - dMagnitude*(dCos + msRoot3*dSin); + adRoot(2) = dC2Div3 - dMagnitude*(dCos - msRoot3*dSin); + + // Sort in increasing order. + if (adRoot(0) >= adRoot(1)) + std::swap(adRoot(0),adRoot(1)); + if (adRoot(1) >= adRoot(2)) + { + std::swap(adRoot(1),adRoot(2)); + if (adRoot(0) >= adRoot(1)) + std::swap(adRoot(0),adRoot(1)); + } +} + +template +void eigen33(const Matrix& mat, Matrix& evecs, Vector& evals) +{ + typedef typename Matrix::Scalar Scalar; + // Scale the matrix so its entries are in [-1,1]. The scaling is applied + // only when at least one matrix entry has magnitude larger than 1. + + Scalar scale = mat.cwiseAbs()/*.template triangularView()*/.maxCoeff(); + scale = std::max(scale,Scalar(1)); + Matrix scaledMat = mat / scale; + + // Compute the eigenvalues +// scaledMat.setZero(); + computeRoots(scaledMat,evals); + + // compute the eigen vectors + // here we assume 3 differents eigenvalues + + // "optimized version" which appears to be slower with gcc! +// Vector base; +// Scalar alpha, beta; +// base << scaledMat(1,0) * scaledMat(2,1), +// scaledMat(1,0) * scaledMat(2,0), +// -scaledMat(1,0) * scaledMat(1,0); +// for(int k=0; k<2; ++k) +// { +// alpha = scaledMat(0,0) - evals(k); +// beta = scaledMat(1,1) - evals(k); +// evecs.col(k) = (base + Vector(-beta*scaledMat(2,0), -alpha*scaledMat(2,1), alpha*beta)).normalized(); +// } +// evecs.col(2) = evecs.col(0).cross(evecs.col(1)).normalized(); + + // naive version + Matrix tmp; + tmp = scaledMat; + tmp.diagonal().array() -= evals(0); + evecs.col(0) = tmp.row(0).cross(tmp.row(1)).normalized(); + + tmp = scaledMat; + tmp.diagonal().array() -= evals(1); + evecs.col(1) = tmp.row(0).cross(tmp.row(1)).normalized(); + + tmp = scaledMat; + tmp.diagonal().array() -= evals(2); + evecs.col(2) = tmp.row(0).cross(tmp.row(1)).normalized(); + + // Rescale back to the original size. + evals *= scale; +} + +int main() +{ + BenchTimer t; + int tries = 10; + int rep = 400000; + typedef Matrix3f Mat; + typedef Vector3f Vec; + Mat A = Mat::Random(3,3); + A = A.adjoint() * A; + + SelfAdjointEigenSolver eig(A); + BENCH(t, tries, rep, eig.compute(A)); + std::cout << "Eigen: " << t.best() << "s\n"; + + Mat evecs; + Vec evals; + BENCH(t, tries, rep, eigen33(A,evecs,evals)); + std::cout << "Direct: " << t.best() << "s\n\n"; + + std::cerr << "Eigenvalue/eigenvector diffs:\n"; + std::cerr << (evals - eig.eigenvalues()).transpose() << "\n"; + for(int k=0;k<3;++k) + if(evecs.col(k).dot(eig.eigenvectors().col(k))<0) + evecs.col(k) = -evecs.col(k); + std::cerr << evecs - eig.eigenvectors() << "\n\n"; +} From cac147ba10dc82927c95c9c70bb35a4afa66ac45 Mon Sep 17 00:00:00 2001 From: Gael Guennebaud Date: Mon, 19 Jul 2010 10:45:06 +0200 Subject: [PATCH 27/41] add support for determinant on empty matrix --- Eigen/src/LU/Determinant.h | 2 ++ test/determinant.cpp | 3 +++ 2 files changed, 5 insertions(+) diff --git a/Eigen/src/LU/Determinant.h b/Eigen/src/LU/Determinant.h index d0b70a31c..ea7db9c0f 100644 --- a/Eigen/src/LU/Determinant.h +++ b/Eigen/src/LU/Determinant.h @@ -47,6 +47,8 @@ template::Scalar run(const Derived& m) { + if(Derived::ColsAtCompileTime==Dynamic && m.rows()==0) + return typename ei_traits::Scalar(1); return m.partialPivLu().determinant(); } }; diff --git a/test/determinant.cpp b/test/determinant.cpp index 494fa5eab..8112131b7 100644 --- a/test/determinant.cpp +++ b/test/determinant.cpp @@ -61,6 +61,9 @@ template void determinant(const MatrixType& m) m2 = m1; m2.row(i) *= x; VERIFY_IS_APPROX(m2.determinant(), m1.determinant() * x); + + // check empty matrix + VERIFY_IS_APPROX(m2.block(0,0,0,0).determinant(), Scalar(1)); } void test_determinant() From abd5faf7840ecb0b086c37f13c8276a547203cf7 Mon Sep 17 00:00:00 2001 From: Jitse Niesen Date: Mon, 19 Jul 2010 12:26:52 +0100 Subject: [PATCH 28/41] Require at least MPFR version 2.3.0, because we use mpfr_signbit. Code in FindMPFR.cmake is taken from FindEigen2.cmake . --- cmake/FindMPFR.cmake | 70 +++++++++++++++++++++++++++++++-- unsupported/test/CMakeLists.txt | 2 +- 2 files changed, 67 insertions(+), 5 deletions(-) diff --git a/cmake/FindMPFR.cmake b/cmake/FindMPFR.cmake index 3aa97f0b4..aa4c2cd7d 100644 --- a/cmake/FindMPFR.cmake +++ b/cmake/FindMPFR.cmake @@ -1,9 +1,23 @@ # Try to find the MPFR library # See http://www.mpfr.org/ +# +# This module supports requiring a minimum version, e.g. you can do +# find_package(MPFR 2.3.0) +# to require version 2.3.0 to newer of MPFR. +# +# Once done this will define +# +# MPFR_FOUND - system has MPFR lib with correct version +# MPFR_INCLUDES - the MPFR include directory +# MPFR_LIBRARIES - the MPFR library +# MPFR_VERSION - MPFR version -if (MPFR_INCLUDES AND MPFR_LIBRARIES) - set(MPFR_FIND_QUIETLY TRUE) -endif (MPFR_INCLUDES AND MPFR_LIBRARIES) +# Copyright (c) 2006, 2007 Montel Laurent, +# Copyright (c) 2008, 2009 Gael Guennebaud, +# Copyright (c) 2010 Jitse Niesen, +# Redistribution and use is allowed according to the terms of the BSD license. + +# Set MPFR_INCLUDES find_path(MPFR_INCLUDES NAMES @@ -13,9 +27,57 @@ find_path(MPFR_INCLUDES ${INCLUDE_INSTALL_DIR} ) +# Set MPFR_FIND_VERSION to 1.0.0 if no minimum version is specified + +if(NOT MPFR_FIND_VERSION) + if(NOT MPFR_FIND_VERSION_MAJOR) + set(MPFR_FIND_VERSION_MAJOR 1) + endif(NOT MPFR_FIND_VERSION_MAJOR) + if(NOT MPFR_FIND_VERSION_MINOR) + set(MPFR_FIND_VERSION_MINOR 0) + endif(NOT MPFR_FIND_VERSION_MINOR) + if(NOT MPFR_FIND_VERSION_PATCH) + set(MPFR_FIND_VERSION_PATCH 0) + endif(NOT MPFR_FIND_VERSION_PATCH) + + set(MPFR_FIND_VERSION "${MPFR_FIND_VERSION_MAJOR}.${MPFR_FIND_VERSION_MINOR}.${MPFR_FIND_VERSION_PATCH}") +endif(NOT MPFR_FIND_VERSION) + + +if(MPFR_INCLUDES) + + # Set MPFR_VERSION + + file(READ "${MPFR_INCLUDES}/mpfr.h" _mpfr_version_header) + + string(REGEX MATCH "define[ \t]+MPFR_VERSION_MAJOR[ \t]+([0-9]+)" _mpfr_major_version_match "${_mpfr_version_header}") + set(MPFR_MAJOR_VERSION "${CMAKE_MATCH_1}") + string(REGEX MATCH "define[ \t]+MPFR_VERSION_MINOR[ \t]+([0-9]+)" _mpfr_minor_version_match "${_mpfr_version_header}") + set(MPFR_MINOR_VERSION "${CMAKE_MATCH_1}") + string(REGEX MATCH "define[ \t]+MPFR_VERSION_PATCHLEVEL[ \t]+([0-9]+)" _mpfr_patchlevel_version_match "${_mpfr_version_header}") + set(MPFR_PATCHLEVEL_VERSION "${CMAKE_MATCH_1}") + + set(MPFR_VERSION ${MPFR_MAJOR_VERSION}.${MPFR_MINOR_VERSION}.${MPFR_PATCHLEVEL_VERSION}) + + # Check whether found version exceeds minimum version + + if(${MPFR_VERSION} VERSION_LESS ${MPFR_FIND_VERSION}) + set(MPFR_VERSION_OK FALSE) + message(STATUS "MPFR version ${MPFR_VERSION} found in ${MPFR_INCLUDES}, " + "but at least version ${MPFR_FIND_VERSION} is required") + else(${MPFR_VERSION} VERSION_LESS ${MPFR_FIND_VERSION}) + set(MPFR_VERSION_OK TRUE) + endif(${MPFR_VERSION} VERSION_LESS ${MPFR_FIND_VERSION}) + +endif(MPFR_INCLUDES) + +# Set MPFR_LIBRARIES + find_library(MPFR_LIBRARIES mpfr PATHS $ENV{GMPDIR} ${LIB_INSTALL_DIR}) +# Epilogue + include(FindPackageHandleStandardArgs) find_package_handle_standard_args(MPFR DEFAULT_MSG - MPFR_INCLUDES MPFR_LIBRARIES) + MPFR_INCLUDES MPFR_LIBRARIES MPFR_VERSION_OK) mark_as_advanced(MPFR_INCLUDES MPFR_LIBRARIES) diff --git a/unsupported/test/CMakeLists.txt b/unsupported/test/CMakeLists.txt index db051caec..5bad3282d 100644 --- a/unsupported/test/CMakeLists.txt +++ b/unsupported/test/CMakeLists.txt @@ -70,7 +70,7 @@ ei_add_test(matrix_function) ei_add_test(alignedvector3) ei_add_test(FFT) -find_package(MPFR) +find_package(MPFR 2.3.0) if(MPFR_FOUND) include_directories(${MPFR_INCLUDES}) ei_add_property(EIGEN_TESTED_BACKENDS "MPFR C++, ") From 3abbdfd621420a97b794ea52492486d7f12679c8 Mon Sep 17 00:00:00 2001 From: Jitse Niesen Date: Tue, 20 Jul 2010 21:55:22 +0100 Subject: [PATCH 29/41] Add (set)LinSpaced to quick reference guide. --- doc/QuickReference.dox | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/doc/QuickReference.dox b/doc/QuickReference.dox index edd00988d..83d2bc2d7 100644 --- a/doc/QuickReference.dox +++ b/doc/QuickReference.dox @@ -218,11 +218,13 @@ x = FixedXD::Zero(); x = FixedXD::Ones(); x = FixedXD::Constant(value); x = FixedXD::Random(); +x = FixedXD::LinSpaced(low, high, size); x.setZero(); x.setOnes(); x.setConstant(value); x.setRandom(); +x.setLinSpaced(low, high, size); \endcode @@ -234,11 +236,13 @@ x = Dynamic2D::Zero(rows, cols); x = Dynamic2D::Ones(rows, cols); x = Dynamic2D::Constant(rows, cols, value); x = Dynamic2D::Random(rows, cols); +N/A x.setZero(rows, cols); x.setOnes(rows, cols); x.setConstant(rows, cols, value); x.setRandom(rows, cols); +N/A \endcode @@ -250,11 +254,13 @@ x = Dynamic1D::Zero(size); x = Dynamic1D::Ones(size); x = Dynamic1D::Constant(size, value); x = Dynamic1D::Random(size); +x = Dynamic1D::LinSpaced(low, high, size); x.setZero(size); x.setOnes(size); x.setConstant(size, value); x.setRandom(size); +x.setLinSpaced(low, high, size); \endcode From 95f2e7f3f5ebdda92d7c16e2aa3df291b54a4d2f Mon Sep 17 00:00:00 2001 From: Gael Guennebaud Date: Wed, 21 Jul 2010 10:57:01 +0200 Subject: [PATCH 30/41] introduce a new LvalueBit flag and split DenseCoeffBase into three level of accessors --- Eigen/src/Core/BandMatrix.h | 2 +- Eigen/src/Core/Block.h | 2 +- Eigen/src/Core/CwiseUnaryView.h | 2 +- Eigen/src/Core/DenseCoeffsBase.h | 28 +++++++++++++++---- Eigen/src/Core/Diagonal.h | 2 +- Eigen/src/Core/DiagonalMatrix.h | 5 +++- Eigen/src/Core/Reverse.h | 2 +- Eigen/src/Core/util/Constants.h | 12 ++++++++ Eigen/src/Core/util/ForwardDeclarations.h | 5 +++- Eigen/src/Core/util/XprHelper.h | 4 +-- .../src/Eigenvalues/HessenbergDecomposition.h | 6 ++-- Eigen/src/Sparse/DynamicSparseMatrix.h | 2 +- Eigen/src/Sparse/SparseMatrix.h | 2 +- Eigen/src/Sparse/SparseVector.h | 2 +- 14 files changed, 56 insertions(+), 20 deletions(-) diff --git a/Eigen/src/Core/BandMatrix.h b/Eigen/src/Core/BandMatrix.h index e846b38e5..2f94d12dc 100644 --- a/Eigen/src/Core/BandMatrix.h +++ b/Eigen/src/Core/BandMatrix.h @@ -55,7 +55,7 @@ struct ei_traits > ColsAtCompileTime = Cols, MaxRowsAtCompileTime = Rows, MaxColsAtCompileTime = Cols, - Flags = 0 + Flags = LvalueBit }; }; diff --git a/Eigen/src/Core/Block.h b/Eigen/src/Core/Block.h index f888d5ea0..7d9ae500d 100644 --- a/Eigen/src/Core/Block.h +++ b/Eigen/src/Core/Block.h @@ -93,7 +93,7 @@ struct ei_traits > : ei_tr && (InnerStrideAtCompileTime == 1) ? PacketAccessBit : 0, FlagsLinearAccessBit = (RowsAtCompileTime == 1 || ColsAtCompileTime == 1) ? LinearAccessBit : 0, - Flags0 = ei_traits::Flags & (HereditaryBits | MaskPacketAccessBit | DirectAccessBit), + Flags0 = ei_traits::Flags & (HereditaryBits | MaskPacketAccessBit | LvalueBit | DirectAccessBit), Flags1 = Flags0 | FlagsLinearAccessBit, Flags = (Flags1 & ~RowMajorBit) | (IsRowMajor ? RowMajorBit : 0) }; diff --git a/Eigen/src/Core/CwiseUnaryView.h b/Eigen/src/Core/CwiseUnaryView.h index 612b28f1f..37c58223e 100644 --- a/Eigen/src/Core/CwiseUnaryView.h +++ b/Eigen/src/Core/CwiseUnaryView.h @@ -48,7 +48,7 @@ struct ei_traits > typedef typename MatrixType::Nested MatrixTypeNested; typedef typename ei_cleantype::type _MatrixTypeNested; enum { - Flags = (ei_traits<_MatrixTypeNested>::Flags & (HereditaryBits | LinearAccessBit | DirectAccessBit)), + Flags = (ei_traits<_MatrixTypeNested>::Flags & (HereditaryBits | LvalueBit | LinearAccessBit | DirectAccessBit)), CoeffReadCost = ei_traits<_MatrixTypeNested>::CoeffReadCost + ei_functor_traits::Cost, MatrixTypeInnerStride = ei_inner_stride_at_compile_time::ret, // need to cast the sizeof's from size_t to int explicitly, otherwise: diff --git a/Eigen/src/Core/DenseCoeffsBase.h b/Eigen/src/Core/DenseCoeffsBase.h index 6802cea24..0b348c81d 100644 --- a/Eigen/src/Core/DenseCoeffsBase.h +++ b/Eigen/src/Core/DenseCoeffsBase.h @@ -25,15 +25,15 @@ #ifndef EIGEN_DENSECOEFFSBASE_H #define EIGEN_DENSECOEFFSBASE_H -template -class DenseCoeffsBase : public EigenBase +template +class DenseCoeffsBase : public EigenBase { public: typedef typename ei_traits::StorageKind StorageKind; typedef typename ei_traits::Index Index; typedef typename ei_traits::Scalar Scalar; typedef typename ei_packet_traits::type PacketScalar; - typedef typename ei_meta_if::ret, + typedef typename ei_meta_if::Flags&LvalueBit), const Scalar&, typename ei_meta_if::ret, Scalar, const Scalar>::ret >::ret CoeffReturnType; @@ -239,11 +239,11 @@ class DenseCoeffsBase : public EigenBase }; template -class DenseCoeffsBase : public DenseCoeffsBase +class DenseCoeffsBase : public DenseCoeffsBase { public: - typedef DenseCoeffsBase Base; + typedef DenseCoeffsBase Base; typedef typename ei_traits::StorageKind StorageKind; typedef typename ei_traits::Index Index; @@ -512,6 +512,23 @@ class DenseCoeffsBase : public DenseCoeffsBase } #endif +}; + +template +class DenseCoeffsBase : public DenseCoeffsBase +{ + public: + + typedef DenseCoeffsBase Base; + typedef typename ei_traits::Index Index; + typedef typename ei_traits::Scalar Scalar; + typedef typename NumTraits::Real RealScalar; + + using Base::rows; + using Base::cols; + using Base::size; + using Base::derived; + /** \returns the pointer increment between two consecutive elements within a slice in the inner direction. * * \sa outerStride(), rowStride(), colStride() @@ -531,6 +548,7 @@ class DenseCoeffsBase : public DenseCoeffsBase return derived().outerStride(); } + // FIXME shall we remove it ? inline Index stride() const { return Derived::IsVectorAtCompileTime ? innerStride() : outerStride(); diff --git a/Eigen/src/Core/Diagonal.h b/Eigen/src/Core/Diagonal.h index 8c2eacd96..0b7d14179 100644 --- a/Eigen/src/Core/Diagonal.h +++ b/Eigen/src/Core/Diagonal.h @@ -62,7 +62,7 @@ struct ei_traits > MatrixType::MaxColsAtCompileTime) : (EIGEN_SIZE_MIN_PREFER_FIXED(MatrixType::MaxRowsAtCompileTime, MatrixType::MaxColsAtCompileTime) - AbsDiagIndex), MaxColsAtCompileTime = 1, - Flags = (unsigned int)_MatrixTypeNested::Flags & (HereditaryBits | LinearAccessBit | DirectAccessBit) & ~RowMajorBit, + Flags = (unsigned int)_MatrixTypeNested::Flags & (HereditaryBits | LinearAccessBit | LvalueBit | DirectAccessBit) & ~RowMajorBit, CoeffReadCost = _MatrixTypeNested::CoeffReadCost, MatrixTypeOuterStride = ei_outer_stride_at_compile_time::ret, InnerStrideAtCompileTime = MatrixTypeOuterStride == Dynamic ? Dynamic : MatrixTypeOuterStride+1, diff --git a/Eigen/src/Core/DiagonalMatrix.h b/Eigen/src/Core/DiagonalMatrix.h index 8c4200a6f..0c0525028 100644 --- a/Eigen/src/Core/DiagonalMatrix.h +++ b/Eigen/src/Core/DiagonalMatrix.h @@ -105,6 +105,9 @@ struct ei_traits typedef Matrix<_Scalar,SizeAtCompileTime,1,0,MaxSizeAtCompileTime,1> DiagonalVectorType; typedef Dense StorageKind; typedef DenseIndex Index; + enum { + Flags = LvalueBit + }; }; template @@ -213,7 +216,7 @@ struct ei_traits > ColsAtCompileTime = DiagonalVectorType::SizeAtCompileTime, MaxRowsAtCompileTime = DiagonalVectorType::SizeAtCompileTime, MaxColsAtCompileTime = DiagonalVectorType::SizeAtCompileTime, - Flags = 0 + Flags = ei_traits::Flags & LvalueBit }; }; diff --git a/Eigen/src/Core/Reverse.h b/Eigen/src/Core/Reverse.h index 5858e684c..6051f7366 100644 --- a/Eigen/src/Core/Reverse.h +++ b/Eigen/src/Core/Reverse.h @@ -59,7 +59,7 @@ struct ei_traits > LinearAccess = ( (Direction==BothDirections) && (int(_MatrixTypeNested::Flags)&PacketAccessBit) ) ? LinearAccessBit : 0, - Flags = int(_MatrixTypeNested::Flags) & (HereditaryBits | PacketAccessBit | LinearAccess | DirectAccessBit), + Flags = int(_MatrixTypeNested::Flags) & (HereditaryBits | LvalueBit | PacketAccessBit | LinearAccess), CoeffReadCost = _MatrixTypeNested::CoeffReadCost }; diff --git a/Eigen/src/Core/util/Constants.h b/Eigen/src/Core/util/Constants.h index d758c2a0b..2c100c809 100644 --- a/Eigen/src/Core/util/Constants.h +++ b/Eigen/src/Core/util/Constants.h @@ -139,6 +139,14 @@ const unsigned int DirectAccessBit = 0x20; * means the first coefficient packet is guaranteed to be aligned */ const unsigned int AlignedBit = 0x40; +/** \ingroup flags + * + * Means the expression is writable. Note that DirectAccessBit implies LvalueBit. + * Internaly, it is mainly used to enable the writable coeff accessors, and makes + * the read-only coeff accessors to return by const reference. + */ +const unsigned int LvalueBit = 0x80; + const unsigned int NestByRefBit = 0x100; // list of flags that are inherited by default @@ -234,6 +242,10 @@ enum { IsSparse }; +enum AccessorLevels { + ReadOnlyAccessors, WriteAccessors, DirectAccessors +}; + enum DecompositionOptions { Pivoting = 0x01, // LDLT, NoPivoting = 0x02, // LDLT, diff --git a/Eigen/src/Core/util/ForwardDeclarations.h b/Eigen/src/Core/util/ForwardDeclarations.h index 310ffa4b3..c3ff9d7c4 100644 --- a/Eigen/src/Core/util/ForwardDeclarations.h +++ b/Eigen/src/Core/util/ForwardDeclarations.h @@ -36,7 +36,10 @@ template struct ei_has_direct_access template struct EigenBase; template class DenseBase; -template::ret> +template::Flags & DirectAccessBit) ? DirectAccessors + : (ei_traits::Flags & LvalueBit) ? WriteAccessors + : ReadOnlyAccessors> class DenseCoeffsBase; template struct ei_size_at_compile_time @@ -355,7 +355,7 @@ template::type> template struct ei_are_flags_consistent { - enum { ret = true }; + enum { ret = EIGEN_IMPLIES(bool(Flags&DirectAccessBit), bool(Flags&LvalueBit)) }; }; template::XprKind> diff --git a/Eigen/src/Eigenvalues/HessenbergDecomposition.h b/Eigen/src/Eigenvalues/HessenbergDecomposition.h index 0f2b78e27..79554187a 100644 --- a/Eigen/src/Eigenvalues/HessenbergDecomposition.h +++ b/Eigen/src/Eigenvalues/HessenbergDecomposition.h @@ -130,7 +130,7 @@ template class HessenbergDecomposition { if(matrix.rows()<2) { - m_isInitialized = true; + m_isInitialized = true; return; } m_hCoeffs.resize(matrix.rows()-1,1); @@ -160,7 +160,7 @@ template class HessenbergDecomposition m_matrix = matrix; if(matrix.rows()<2) { - m_isInitialized = true; + m_isInitialized = true; return *this; } m_hCoeffs.resize(matrix.rows()-1,1); @@ -360,7 +360,7 @@ template struct HessenbergDecompositionMatrixHReturnType result = m_hess.packedMatrix(); Index n = result.rows(); if (n>2) - result.bottomLeftCorner(n-2, n-2).template triangularView().setZero(); + result.bottomLeftCorner(n-2, n-2).template triangularView().setZero(); } Index rows() const { return m_hess.packedMatrix().rows(); } diff --git a/Eigen/src/Sparse/DynamicSparseMatrix.h b/Eigen/src/Sparse/DynamicSparseMatrix.h index 69e1f55ba..620f09289 100644 --- a/Eigen/src/Sparse/DynamicSparseMatrix.h +++ b/Eigen/src/Sparse/DynamicSparseMatrix.h @@ -54,7 +54,7 @@ struct ei_traits > ColsAtCompileTime = Dynamic, MaxRowsAtCompileTime = Dynamic, MaxColsAtCompileTime = Dynamic, - Flags = _Flags | NestByRefBit, + Flags = _Flags | NestByRefBit | LvalueBit, CoeffReadCost = NumTraits::ReadCost, SupportedAccessPatterns = OuterRandomAccessPattern }; diff --git a/Eigen/src/Sparse/SparseMatrix.h b/Eigen/src/Sparse/SparseMatrix.h index ecf8efbe7..820cf2884 100644 --- a/Eigen/src/Sparse/SparseMatrix.h +++ b/Eigen/src/Sparse/SparseMatrix.h @@ -54,7 +54,7 @@ struct ei_traits > ColsAtCompileTime = Dynamic, MaxRowsAtCompileTime = Dynamic, MaxColsAtCompileTime = Dynamic, - Flags = _Options | NestByRefBit, + Flags = _Options | NestByRefBit | LvalueBit, CoeffReadCost = NumTraits::ReadCost, SupportedAccessPatterns = InnerRandomAccessPattern }; diff --git a/Eigen/src/Sparse/SparseVector.h b/Eigen/src/Sparse/SparseVector.h index dfe79a3b2..c5d0a6981 100644 --- a/Eigen/src/Sparse/SparseVector.h +++ b/Eigen/src/Sparse/SparseVector.h @@ -48,7 +48,7 @@ struct ei_traits > ColsAtCompileTime = IsColVector ? 1 : Dynamic, MaxRowsAtCompileTime = RowsAtCompileTime, MaxColsAtCompileTime = ColsAtCompileTime, - Flags = _Options | NestByRefBit, + Flags = _Options | NestByRefBit | LvalueBit, CoeffReadCost = NumTraits::ReadCost, SupportedAccessPatterns = InnerRandomAccessPattern }; From 4b474fdb34338e6e78f71ac0d49dc34703a57696 Mon Sep 17 00:00:00 2001 From: Martin Senst Date: Tue, 20 Jul 2010 21:25:43 +0200 Subject: [PATCH 31/41] Relax assertion to allow for matrices with cols() == 0 and/or rows() == 0. --- Eigen/src/Core/DenseStorageBase.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Eigen/src/Core/DenseStorageBase.h b/Eigen/src/Core/DenseStorageBase.h index 6886e3f97..9b4a645e6 100644 --- a/Eigen/src/Core/DenseStorageBase.h +++ b/Eigen/src/Core/DenseStorageBase.h @@ -483,8 +483,8 @@ class DenseStorageBase : public ei_dense_xpr_base::type template EIGEN_STRONG_INLINE void _init2(Index rows, Index cols, typename ei_enable_if::type* = 0) { - ei_assert(rows > 0 && (RowsAtCompileTime == Dynamic || RowsAtCompileTime == rows) - && cols > 0 && (ColsAtCompileTime == Dynamic || ColsAtCompileTime == cols)); + ei_assert(rows >= 0 && (RowsAtCompileTime == Dynamic || RowsAtCompileTime == rows) + && cols >= 0 && (ColsAtCompileTime == Dynamic || ColsAtCompileTime == cols)); m_storage.resize(rows*cols,rows,cols); EIGEN_INITIALIZE_BY_ZERO_IF_THAT_OPTION_IS_ENABLED } From 464fc297cfb95a56064472a82b200fdac754ab8c Mon Sep 17 00:00:00 2001 From: Manoj Rajagopalan Date: Sat, 26 Jun 2010 17:37:17 -0400 Subject: [PATCH 32/41] Included definitions for rowRange() and colRange() member functions of DenseBase --- Eigen/src/Core/Block.h | 110 ++++++++++++++++++++++++++++++++++++- Eigen/src/Core/DenseBase.h | 8 +++ 2 files changed, 117 insertions(+), 1 deletion(-) diff --git a/Eigen/src/Core/Block.h b/Eigen/src/Core/Block.h index 7d9ae500d..5fb7126e6 100644 --- a/Eigen/src/Core/Block.h +++ b/Eigen/src/Core/Block.h @@ -679,9 +679,62 @@ DenseBase::bottomRows() const +/** \returns a block consisting of a range of rows of *this. + * + * \param startRow the index of the first row in the block + * \param numRows the number of rows in the block + * + * Example: \include MatrixBase_rowRange_int.cpp + * Output: \verbinclude MatrixBase_rowRange_int.out + * + * \sa class Block, block(Index,Index,Index,Index) + */ +template +inline typename DenseBase::RowsBlockXpr DenseBase + ::rowRange(Index startRow, Index numRows) +{ + return RowsBlockXpr(derived(), startRow, 0, numRows, cols()); +} + +/** This is the const version of rowRange(Index,Index).*/ +template +inline const typename DenseBase::RowsBlockXpr +DenseBase::rowRange(Index startRow, Index numRows) const +{ + return RowsBlockXpr(derived(), startRow, 0, numRows, cols()); +} + +/** \returns a block consisting of a range of rows of *this. + * + * \param N the number of rows in the block + * \param startRow the index of the first row in the block + * + * Example: \include MatrixBase_template_int_rowRange.cpp + * Output: \verbinclude MatrixBase_template_int_rowRange.out + * + * \sa class Block, block(Index,Index,Index,Index) + */ +template +template +inline typename DenseBase::template NRowsBlockXpr::Type +DenseBase::rowRange(Index startRow) +{ + return typename DenseBase::template NRowsBlockXpr::Type(derived(), startRow, 0, N, cols()); +} + +/** This is the const version of rowRange().*/ +template +template +inline const typename DenseBase::template NRowsBlockXpr::Type +DenseBase::rowRange(Index startRow) const +{ + return typename DenseBase::template NRowsBlockXpr::Type(derived(), startRow, 0, N, cols()); +} -/** \returns a block consisting of the top columns of *this. + + +/** \returns a block consisting of the left columns of *this. * * \param n the number of columns in the block * @@ -788,6 +841,61 @@ DenseBase::rightCols() const +/** \returns a block consisting of a range of columns of *this. + * + * \param startCol the index of the first column in the block + * \param numCols the number of columns in the block + * + * Example: \include MatrixBase_colRange_int.cpp + * Output: \verbinclude MatrixBase_colRange_int.out + * + * \sa class Block, block(Index,Index,Index,Index) + */ +template +inline typename DenseBase::ColsBlockXpr DenseBase + ::colRange(Index startCol, Index numCols) +{ + return ColsBlockXpr(derived(), 0, startCol, rows(), numCols); +} + +/** This is the const version of colRange(Index,Index).*/ +template +inline const typename DenseBase::ColsBlockXpr +DenseBase::colRange(Index startCol, Index numCols) const +{ + return ColsBlockXpr(derived(), 0, startCol, rows(), numCols); +} + +/** \returns a block consisting of a range of columns of *this. + * + * \param N the number of columns in the block + * \param startCol the index of the first column in the block + * + * Example: \include MatrixBase_template_int_colRange.cpp + * Output: \verbinclude MatrixBase_template_int_colRange.out + * + * \sa class Block, block(Index,Index,Index,Index) + */ +template +template +inline typename DenseBase::template NColsBlockXpr::Type +DenseBase::colRange(Index startCol) +{ + return typename NColsBlockXpr::Type(derived(), 0, startCol, rows(), N); +} + +/** This is the const version of colRange().*/ +template +template +inline const typename DenseBase::template NColsBlockXpr::Type +DenseBase::colRange(Index startCol) const +{ + return typename NColsBlockXpr::Type(derived(), 0, startCol, rows(), N); +} + + + + /** \returns a fixed-size expression of a block in *this. * diff --git a/Eigen/src/Core/DenseBase.h b/Eigen/src/Core/DenseBase.h index 8c1e24fec..c42c4b8d1 100644 --- a/Eigen/src/Core/DenseBase.h +++ b/Eigen/src/Core/DenseBase.h @@ -327,10 +327,14 @@ template class DenseBase const RowsBlockXpr topRows(Index n) const; RowsBlockXpr bottomRows(Index n); const RowsBlockXpr bottomRows(Index n) const; + RowsBlockXpr rowRange(Index startRow, Index numRows); + const RowsBlockXpr rowRange(Index startRow, Index numRows) const; ColsBlockXpr leftCols(Index n); const ColsBlockXpr leftCols(Index n) const; ColsBlockXpr rightCols(Index n); const ColsBlockXpr rightCols(Index n) const; + ColsBlockXpr colRange(Index startCol, Index numCols); + const ColsBlockXpr colRange(Index startCol, Index numCols) const; template Block topLeftCorner(); template const Block topLeftCorner() const; @@ -345,10 +349,14 @@ template class DenseBase template const typename NRowsBlockXpr::Type topRows() const; template typename NRowsBlockXpr::Type bottomRows(); template const typename NRowsBlockXpr::Type bottomRows() const; + template typename NRowsBlockXpr::Type rowRange(Index startRow); + template const typename NRowsBlockXpr::Type rowRange(Index startRow) const; template typename NColsBlockXpr::Type leftCols(); template const typename NColsBlockXpr::Type leftCols() const; template typename NColsBlockXpr::Type rightCols(); template const typename NColsBlockXpr::Type rightCols() const; + template typename NColsBlockXpr::Type colRange(Index startCol); + template const typename NColsBlockXpr::Type colRange(Index startCol) const; template Block block(Index startRow, Index startCol); From 6e5bed69dcef0781c949412cd5ac0a31a6525c7f Mon Sep 17 00:00:00 2001 From: Manoj Rajagopalan Date: Tue, 29 Jun 2010 12:39:58 -0400 Subject: [PATCH 33/41] Included tests for middleRows() and middleCols() --- test/corners.cpp | 23 ++++++++++++++++++----- 1 file changed, 18 insertions(+), 5 deletions(-) diff --git a/test/corners.cpp b/test/corners.cpp index 70d12fded..fe2b205d7 100644 --- a/test/corners.cpp +++ b/test/corners.cpp @@ -45,13 +45,20 @@ template void corners(const MatrixType& m) COMPARE_CORNER(bottomLeftCorner(r,c), block(rows-r,0,r,c)); COMPARE_CORNER(bottomRightCorner(r,c), block(rows-r,cols-c,r,c)); + Index sr = ei_random(1,rows) - 1; + Index nr = ei_random(1,rows-sr); + Index sc = ei_random(1,cols) - 1; + Index nc = ei_random(1,cols-sc); + COMPARE_CORNER(topRows(r), block(0,0,r,cols)); + COMPARE_CORNER(middleRows(sr,nr), block(sr,0,nr,cols)); COMPARE_CORNER(bottomRows(r), block(rows-r,0,r,cols)); COMPARE_CORNER(leftCols(c), block(0,0,rows,c)); + COMPARE_CORNER(middleCols(sc,nc), block(0,sc,rows,nc)); COMPARE_CORNER(rightCols(c), block(0,cols-c,rows,c)); } -template void corners_fixedsize() +template void corners_fixedsize() { MatrixType matrix = MatrixType::Random(); const MatrixType const_matrix = MatrixType::Random(); @@ -60,7 +67,9 @@ template void corners_fixedsize() rows = MatrixType::RowsAtCompileTime, cols = MatrixType::ColsAtCompileTime, r = CRows, - c = CCols + c = CCols, + sr = SRows, + sc = SCols }; VERIFY_IS_EQUAL((matrix.template topLeftCorner()), (matrix.template block(0,0))); @@ -69,8 +78,10 @@ template void corners_fixedsize() VERIFY_IS_EQUAL((matrix.template bottomRightCorner()), (matrix.template block(rows-r,cols-c))); VERIFY_IS_EQUAL((matrix.template topRows()), (matrix.template block(0,0))); + VERIFY_IS_EQUAL((matrix.template middleRows(sr)), (matrix.template block(sr,0))); VERIFY_IS_EQUAL((matrix.template bottomRows()), (matrix.template block(rows-r,0))); VERIFY_IS_EQUAL((matrix.template leftCols()), (matrix.template block(0,0))); + VERIFY_IS_EQUAL((matrix.template middleCols(sc)), (matrix.template block(0,sc))); VERIFY_IS_EQUAL((matrix.template rightCols()), (matrix.template block(0,cols-c))); VERIFY_IS_EQUAL((const_matrix.template topLeftCorner()), (const_matrix.template block(0,0))); @@ -79,8 +90,10 @@ template void corners_fixedsize() VERIFY_IS_EQUAL((const_matrix.template bottomRightCorner()), (const_matrix.template block(rows-r,cols-c))); VERIFY_IS_EQUAL((const_matrix.template topRows()), (const_matrix.template block(0,0))); + VERIFY_IS_EQUAL((const_matrix.template middleRows(sr)), (const_matrix.template block(sr,0))); VERIFY_IS_EQUAL((const_matrix.template bottomRows()), (const_matrix.template block(rows-r,0))); VERIFY_IS_EQUAL((const_matrix.template leftCols()), (const_matrix.template block(0,0))); + VERIFY_IS_EQUAL((const_matrix.template middleCols(sc)), (const_matrix.template block(0,sc))); VERIFY_IS_EQUAL((const_matrix.template rightCols()), (const_matrix.template block(0,cols-c))); } @@ -93,8 +106,8 @@ void test_corners() CALL_SUBTEST_4( corners(MatrixXcf(5, 7)) ); CALL_SUBTEST_5( corners(MatrixXf(21, 20)) ); - CALL_SUBTEST_1(( corners_fixedsize, 1, 1>() )); - CALL_SUBTEST_2(( corners_fixedsize() )); - CALL_SUBTEST_3(( corners_fixedsize,4,7>() )); + CALL_SUBTEST_1(( corners_fixedsize, 1, 1, 0, 0>() )); + CALL_SUBTEST_2(( corners_fixedsize() )); + CALL_SUBTEST_3(( corners_fixedsize,4,7,5,2>() )); } } From 5c58582a082b622b768bc7d8358e3d1f68c03b62 Mon Sep 17 00:00:00 2001 From: Manoj Rajagopalan Date: Tue, 29 Jun 2010 14:31:39 -0400 Subject: [PATCH 34/41] Renamed DenseBase::{row,col}Range() to DenseBase::middle{Rows,Cols}() --- Eigen/src/Core/Block.h | 40 +++++++++++++++++++------------------- Eigen/src/Core/DenseBase.h | 16 +++++++-------- 2 files changed, 28 insertions(+), 28 deletions(-) diff --git a/Eigen/src/Core/Block.h b/Eigen/src/Core/Block.h index 5fb7126e6..498757ad9 100644 --- a/Eigen/src/Core/Block.h +++ b/Eigen/src/Core/Block.h @@ -684,22 +684,22 @@ DenseBase::bottomRows() const * \param startRow the index of the first row in the block * \param numRows the number of rows in the block * - * Example: \include MatrixBase_rowRange_int.cpp - * Output: \verbinclude MatrixBase_rowRange_int.out + * Example: \include MatrixBase_middleRows_int.cpp + * Output: \verbinclude MatrixBase_middleRows_int.out * * \sa class Block, block(Index,Index,Index,Index) */ template inline typename DenseBase::RowsBlockXpr DenseBase - ::rowRange(Index startRow, Index numRows) + ::middleRows(Index startRow, Index numRows) { return RowsBlockXpr(derived(), startRow, 0, numRows, cols()); } -/** This is the const version of rowRange(Index,Index).*/ +/** This is the const version of middleRows(Index,Index).*/ template inline const typename DenseBase::RowsBlockXpr -DenseBase::rowRange(Index startRow, Index numRows) const +DenseBase::middleRows(Index startRow, Index numRows) const { return RowsBlockXpr(derived(), startRow, 0, numRows, cols()); } @@ -709,24 +709,24 @@ DenseBase::rowRange(Index startRow, Index numRows) const * \param N the number of rows in the block * \param startRow the index of the first row in the block * - * Example: \include MatrixBase_template_int_rowRange.cpp - * Output: \verbinclude MatrixBase_template_int_rowRange.out + * Example: \include MatrixBase_template_int_middleRows.cpp + * Output: \verbinclude MatrixBase_template_int_middleRows.out * * \sa class Block, block(Index,Index,Index,Index) */ template template inline typename DenseBase::template NRowsBlockXpr::Type -DenseBase::rowRange(Index startRow) +DenseBase::middleRows(Index startRow) { return typename DenseBase::template NRowsBlockXpr::Type(derived(), startRow, 0, N, cols()); } -/** This is the const version of rowRange().*/ +/** This is the const version of middleRows().*/ template template inline const typename DenseBase::template NRowsBlockXpr::Type -DenseBase::rowRange(Index startRow) const +DenseBase::middleRows(Index startRow) const { return typename DenseBase::template NRowsBlockXpr::Type(derived(), startRow, 0, N, cols()); } @@ -846,22 +846,22 @@ DenseBase::rightCols() const * \param startCol the index of the first column in the block * \param numCols the number of columns in the block * - * Example: \include MatrixBase_colRange_int.cpp - * Output: \verbinclude MatrixBase_colRange_int.out + * Example: \include MatrixBase_middleCols_int.cpp + * Output: \verbinclude MatrixBase_middleCols_int.out * * \sa class Block, block(Index,Index,Index,Index) */ template inline typename DenseBase::ColsBlockXpr DenseBase - ::colRange(Index startCol, Index numCols) + ::middleCols(Index startCol, Index numCols) { return ColsBlockXpr(derived(), 0, startCol, rows(), numCols); } -/** This is the const version of colRange(Index,Index).*/ +/** This is the const version of middleCols(Index,Index).*/ template inline const typename DenseBase::ColsBlockXpr -DenseBase::colRange(Index startCol, Index numCols) const +DenseBase::middleCols(Index startCol, Index numCols) const { return ColsBlockXpr(derived(), 0, startCol, rows(), numCols); } @@ -871,24 +871,24 @@ DenseBase::colRange(Index startCol, Index numCols) const * \param N the number of columns in the block * \param startCol the index of the first column in the block * - * Example: \include MatrixBase_template_int_colRange.cpp - * Output: \verbinclude MatrixBase_template_int_colRange.out + * Example: \include MatrixBase_template_int_middleCols.cpp + * Output: \verbinclude MatrixBase_template_int_middleCols.out * * \sa class Block, block(Index,Index,Index,Index) */ template template inline typename DenseBase::template NColsBlockXpr::Type -DenseBase::colRange(Index startCol) +DenseBase::middleCols(Index startCol) { return typename NColsBlockXpr::Type(derived(), 0, startCol, rows(), N); } -/** This is the const version of colRange().*/ +/** This is the const version of middleCols().*/ template template inline const typename DenseBase::template NColsBlockXpr::Type -DenseBase::colRange(Index startCol) const +DenseBase::middleCols(Index startCol) const { return typename NColsBlockXpr::Type(derived(), 0, startCol, rows(), N); } diff --git a/Eigen/src/Core/DenseBase.h b/Eigen/src/Core/DenseBase.h index c42c4b8d1..6f5013e2d 100644 --- a/Eigen/src/Core/DenseBase.h +++ b/Eigen/src/Core/DenseBase.h @@ -327,14 +327,14 @@ template class DenseBase const RowsBlockXpr topRows(Index n) const; RowsBlockXpr bottomRows(Index n); const RowsBlockXpr bottomRows(Index n) const; - RowsBlockXpr rowRange(Index startRow, Index numRows); - const RowsBlockXpr rowRange(Index startRow, Index numRows) const; + RowsBlockXpr middleRows(Index startRow, Index numRows); + const RowsBlockXpr middleRows(Index startRow, Index numRows) const; ColsBlockXpr leftCols(Index n); const ColsBlockXpr leftCols(Index n) const; ColsBlockXpr rightCols(Index n); const ColsBlockXpr rightCols(Index n) const; - ColsBlockXpr colRange(Index startCol, Index numCols); - const ColsBlockXpr colRange(Index startCol, Index numCols) const; + ColsBlockXpr middleCols(Index startCol, Index numCols); + const ColsBlockXpr middleCols(Index startCol, Index numCols) const; template Block topLeftCorner(); template const Block topLeftCorner() const; @@ -349,14 +349,14 @@ template class DenseBase template const typename NRowsBlockXpr::Type topRows() const; template typename NRowsBlockXpr::Type bottomRows(); template const typename NRowsBlockXpr::Type bottomRows() const; - template typename NRowsBlockXpr::Type rowRange(Index startRow); - template const typename NRowsBlockXpr::Type rowRange(Index startRow) const; + template typename NRowsBlockXpr::Type middleRows(Index startRow); + template const typename NRowsBlockXpr::Type middleRows(Index startRow) const; template typename NColsBlockXpr::Type leftCols(); template const typename NColsBlockXpr::Type leftCols() const; template typename NColsBlockXpr::Type rightCols(); template const typename NColsBlockXpr::Type rightCols() const; - template typename NColsBlockXpr::Type colRange(Index startCol); - template const typename NColsBlockXpr::Type colRange(Index startCol) const; + template typename NColsBlockXpr::Type middleCols(Index startCol); + template const typename NColsBlockXpr::Type middleCols(Index startCol) const; template Block block(Index startRow, Index startCol); From c64c0f382fd3215c2df9b764a1a6b2565acc979f Mon Sep 17 00:00:00 2001 From: Manoj Rajagopalan Date: Wed, 30 Jun 2010 11:26:31 -0400 Subject: [PATCH 35/41] Examples for DenseBase::middle{Rows,Cols}() --- doc/examples/DenseBase_middleCols_int.cpp | 15 +++++++++++++++ doc/examples/DenseBase_middleRows_int.cpp | 15 +++++++++++++++ .../DenseBase_template_int_middleCols.cpp | 15 +++++++++++++++ .../DenseBase_template_int_middleRows.cpp | 15 +++++++++++++++ 4 files changed, 60 insertions(+) create mode 100644 doc/examples/DenseBase_middleCols_int.cpp create mode 100644 doc/examples/DenseBase_middleRows_int.cpp create mode 100644 doc/examples/DenseBase_template_int_middleCols.cpp create mode 100644 doc/examples/DenseBase_template_int_middleRows.cpp diff --git a/doc/examples/DenseBase_middleCols_int.cpp b/doc/examples/DenseBase_middleCols_int.cpp new file mode 100644 index 000000000..0ebd955ec --- /dev/null +++ b/doc/examples/DenseBase_middleCols_int.cpp @@ -0,0 +1,15 @@ +#include +#include + +using namespace Eigen; +using namespace std; + +int main(void) +{ + int const N = 5; + MatrixXi A(N,N); + A.setRandom(); + cout << "A =\n" << A << '\n' << endl; + cout << "A(1..3,:) =\n" << A.middleCols(1,3) << endl; + return 0; +} diff --git a/doc/examples/DenseBase_middleRows_int.cpp b/doc/examples/DenseBase_middleRows_int.cpp new file mode 100644 index 000000000..a6fe9e844 --- /dev/null +++ b/doc/examples/DenseBase_middleRows_int.cpp @@ -0,0 +1,15 @@ +#include +#include + +using namespace Eigen; +using namespace std; + +int main(void) +{ + int const N = 5; + MatrixXi A(N,N); + A.setRandom(); + cout << "A =\n" << A << '\n' << endl; + cout << "A(2..3,:) =\n" << A.middleRows(2,2) << endl; + return 0; +} diff --git a/doc/examples/DenseBase_template_int_middleCols.cpp b/doc/examples/DenseBase_template_int_middleCols.cpp new file mode 100644 index 000000000..6191d79c8 --- /dev/null +++ b/doc/examples/DenseBase_template_int_middleCols.cpp @@ -0,0 +1,15 @@ +#include +#include + +using namespace Eigen; +using namespace std; + +int main(void) +{ + int const N = 5; + MatrixXi A(N,N); + A.setRandom(); + cout << "A =\n" << A << '\n' << endl; + cout << "A(:,1..3) =\n" << A.middleCols<3>(1) << endl; + return 0; +} diff --git a/doc/examples/DenseBase_template_int_middleRows.cpp b/doc/examples/DenseBase_template_int_middleRows.cpp new file mode 100644 index 000000000..7e8b6573f --- /dev/null +++ b/doc/examples/DenseBase_template_int_middleRows.cpp @@ -0,0 +1,15 @@ +#include +#include + +using namespace Eigen; +using namespace std; + +int main(void) +{ + int const N = 5; + MatrixXi A(N,N); + A.setRandom(); + cout << "A =\n" << A << '\n' << endl; + cout << "A(1..3,:) =\n" << A.middleRows<3>(1) << endl; + return 0; +} From f1104a3b0faac4a6daf54b6a7474ab693a40e8d1 Mon Sep 17 00:00:00 2001 From: Gael Guennebaud Date: Wed, 21 Jul 2010 17:13:02 +0200 Subject: [PATCH 36/41] fix mandelbrot compilation, and make it use Array instead of Matrix --- demos/mandelbrot/mandelbrot.cpp | 15 ++++++++------- demos/mandelbrot/mandelbrot.h | 2 +- 2 files changed, 9 insertions(+), 8 deletions(-) diff --git a/demos/mandelbrot/mandelbrot.cpp b/demos/mandelbrot/mandelbrot.cpp index 14341b7e4..f89526cf6 100644 --- a/demos/mandelbrot/mandelbrot.cpp +++ b/demos/mandelbrot/mandelbrot.cpp @@ -23,6 +23,7 @@ // Eigen. If not, see . #include "mandelbrot.h" +#include #include #include #include @@ -45,7 +46,7 @@ template<> struct iters_before_test { enum { ret = 16 }; }; template void MandelbrotThread::render(int img_width, int img_height) { enum { packetSize = Eigen::ei_packet_traits::size }; // number of reals in a Packet - typedef Eigen::Matrix Packet; // wrap a Packet as a vector + typedef Eigen::Array Packet; // wrap a Packet as a vector enum { iters_before_test = iters_before_test::ret }; max_iter = (max_iter / iters_before_test) * iters_before_test; @@ -54,7 +55,7 @@ template void MandelbrotThread::render(int img_width, int img_hei const double xradius = widget->xradius; const double yradius = xradius * img_height / img_width; const int threadcount = widget->threadcount; - typedef Eigen::Matrix Vector2; + typedef Eigen::Array Vector2; Vector2 start(widget->center.x() - widget->xradius, widget->center.y() - yradius); Vector2 step(2*widget->xradius/img_width, 2*yradius/img_height); total_iter = 0; @@ -87,16 +88,16 @@ template void MandelbrotThread::render(int img_width, int img_hei { # define ITERATE \ pzr_buf = pzr; \ - pzr = pzr.cwise().square(); \ - pzr -= pzi.cwise().square(); \ + pzr = pzr.square(); \ + pzr -= pzi.square(); \ pzr += pcr; \ - pzi = (2*pzr_buf).cwise()*pzi; \ + pzi = (2*pzr_buf)*pzi; \ pzi += pci; ITERATE ITERATE ITERATE ITERATE } - pix_dont_diverge = ((pzr.cwise().square() + pzi.cwise().square()) + pix_dont_diverge = ((pzr.square() + pzi.square()) .eval() // temporary fix as what follows is not yet vectorized by Eigen - .cwise() <= Packet::Constant(4)) + <= Packet::Constant(4)) // the 4 here is not a magic value, it's a math fact that if // the square modulus is >4 then divergence is inevitable. .template cast(); diff --git a/demos/mandelbrot/mandelbrot.h b/demos/mandelbrot/mandelbrot.h index d0e3b6c96..950be82e2 100644 --- a/demos/mandelbrot/mandelbrot.h +++ b/demos/mandelbrot/mandelbrot.h @@ -25,7 +25,7 @@ #ifndef MANDELBROT_H #define MANDELBROT_H -#include +#include #include #include #include From 4393f20fea79bb176fc5658bd6793e949b5952f1 Mon Sep 17 00:00:00 2001 From: Gael Guennebaud Date: Wed, 21 Jul 2010 17:34:32 +0200 Subject: [PATCH 37/41] fix compilation of quaternion demo --- demos/opengl/quaternion_demo.cpp | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/demos/opengl/quaternion_demo.cpp b/demos/opengl/quaternion_demo.cpp index 1de645c05..c03a89cd5 100644 --- a/demos/opengl/quaternion_demo.cpp +++ b/demos/opengl/quaternion_demo.cpp @@ -25,10 +25,11 @@ #include "quaternion_demo.h" #include "icosphere.h" -#include +#include #include #include +#include #include #include #include @@ -187,8 +188,8 @@ public: Matrix3 toRotationMatrix(void) const { - Vector3 c = m_angles.cwise().cos(); - Vector3 s = m_angles.cwise().sin(); + Vector3 c = m_angles.array().cos(); + Vector3 s = m_angles.array().sin(); Matrix3 res; res << c.y()*c.z(), -c.y()*s.z(), s.y(), c.z()*s.x()*s.y()+c.x()*s.z(), c.x()*c.z()-s.x()*s.y()*s.z(), -c.y()*s.x(), From 8e21cef80ac997b3d05c8c349b3676cb16d04cfe Mon Sep 17 00:00:00 2001 From: Thomas Capricelli Date: Thu, 22 Jul 2010 13:15:15 +0200 Subject: [PATCH 38/41] fix typo --- doc/QuickReference.dox | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/QuickReference.dox b/doc/QuickReference.dox index 83d2bc2d7..0f6886f75 100644 --- a/doc/QuickReference.dox +++ b/doc/QuickReference.dox @@ -601,7 +601,7 @@ m3 -= s1 * m2.conjugate() * m1.adjoint().triangularView() \endcode Solving linear equations:\n \f$ M_2 := L_1^{-1} M_2 \f$ \n \f$ M_3 := {L_1^*}^{-1} M_3 \f$ \n -\f$ M_4 := M_3 U_1^{-1} \f$ +\f$ M_4 := M_4 U_1^{-1} \f$ \n \code L1.triangularView().solveInPlace(M2) L1.triangularView().adjoint().solveInPlace(M3) From 734469e43f37839f179a9f12915889f3df89d477 Mon Sep 17 00:00:00 2001 From: Hauke Heibel Date: Thu, 22 Jul 2010 14:04:00 +0200 Subject: [PATCH 39/41] Unified LinSpaced in order to be conform with other setter methods as e.g. Constant. --- Eigen/src/Core/CwiseNullaryOp.h | 36 ++++++++++++++++++++---- Eigen/src/Core/DenseBase.h | 11 ++++++-- Eigen/src/Core/Functors.h | 2 +- doc/snippets/DenseBase_LinSpaced.cpp | 4 +-- doc/snippets/DenseBase_LinSpaced_seq.cpp | 4 +-- doc/snippets/DenseBase_setLinSpaced.cpp | 2 +- test/nullary.cpp | 12 ++++---- 7 files changed, 51 insertions(+), 20 deletions(-) diff --git a/Eigen/src/Core/CwiseNullaryOp.h b/Eigen/src/Core/CwiseNullaryOp.h index 25041d1b7..97331fa26 100644 --- a/Eigen/src/Core/CwiseNullaryOp.h +++ b/Eigen/src/Core/CwiseNullaryOp.h @@ -240,16 +240,29 @@ DenseBase::Constant(const Scalar& value) * Example: \include DenseBase_LinSpaced_seq.cpp * Output: \verbinclude DenseBase_LinSpaced_seq.out * - * \sa setLinSpaced(const Scalar&,const Scalar&,Index), LinSpaced(Scalar,Scalar,Index), CwiseNullaryOp + * \sa setLinSpaced(Index,const Scalar&,const Scalar&), LinSpaced(Index,Scalar,Scalar), CwiseNullaryOp */ template EIGEN_STRONG_INLINE const typename DenseBase::SequentialLinSpacedReturnType -DenseBase::LinSpaced(Sequential_t, const Scalar& low, const Scalar& high, Index size) +DenseBase::LinSpaced(Sequential_t, Index size, const Scalar& low, const Scalar& high) { EIGEN_STATIC_ASSERT_VECTOR_ONLY(Derived) return DenseBase::NullaryExpr(size, ei_linspaced_op(low,high,size)); } +/** + * \copydoc DenseBase::LinSpaced(Sequential_t, Index, const Scalar&, const Scalar&) + * Special version for fixed size types which does not require the size parameter. + */ +template +EIGEN_STRONG_INLINE const typename DenseBase::SequentialLinSpacedReturnType +DenseBase::LinSpaced(Sequential_t, const Scalar& low, const Scalar& high) +{ + EIGEN_STATIC_ASSERT_VECTOR_ONLY(Derived) + EIGEN_STATIC_ASSERT_FIXED_SIZE(Derived) + return DenseBase::NullaryExpr(Derived::SizeAtCompileTime, ei_linspaced_op(low,high,Derived::SizeAtCompileTime)); +} + /** * \brief Sets a linearly space vector. * @@ -260,16 +273,29 @@ DenseBase::LinSpaced(Sequential_t, const Scalar& low, const Scalar& hig * Example: \include DenseBase_LinSpaced.cpp * Output: \verbinclude DenseBase_LinSpaced.out * - * \sa setLinSpaced(const Scalar&,const Scalar&,Index), LinSpaced(Sequential_t,const Scalar&,const Scalar&,Index), CwiseNullaryOp + * \sa setLinSpaced(Index,const Scalar&,const Scalar&), LinSpaced(Sequential_t,Index,const Scalar&,const Scalar&,Index), CwiseNullaryOp */ template EIGEN_STRONG_INLINE const typename DenseBase::RandomAccessLinSpacedReturnType -DenseBase::LinSpaced(const Scalar& low, const Scalar& high, Index size) +DenseBase::LinSpaced(Index size, const Scalar& low, const Scalar& high) { EIGEN_STATIC_ASSERT_VECTOR_ONLY(Derived) return DenseBase::NullaryExpr(size, ei_linspaced_op(low,high,size)); } +/** + * \copydoc DenseBase::LinSpaced(Index, const Scalar&, const Scalar&) + * Special version for fixed size types which does not require the size parameter. + */ +template +EIGEN_STRONG_INLINE const typename DenseBase::RandomAccessLinSpacedReturnType +DenseBase::LinSpaced(const Scalar& low, const Scalar& high) +{ + EIGEN_STATIC_ASSERT_VECTOR_ONLY(Derived) + EIGEN_STATIC_ASSERT_FIXED_SIZE(Derived) + return DenseBase::NullaryExpr(Derived::SizeAtCompileTime, ei_linspaced_op(low,high,Derived::SizeAtCompileTime)); +} + /** \returns true if all coefficients in this matrix are approximately equal to \a value, to within precision \a prec */ template bool DenseBase::isApproxToConstant @@ -360,7 +386,7 @@ DenseStorageBase::setConstant(Index rows, Index cols, const Scalar& val * \sa CwiseNullaryOp */ template -EIGEN_STRONG_INLINE Derived& DenseBase::setLinSpaced(const Scalar& low, const Scalar& high, Index size) +EIGEN_STRONG_INLINE Derived& DenseBase::setLinSpaced(Index size, const Scalar& low, const Scalar& high) { EIGEN_STATIC_ASSERT_VECTOR_ONLY(Derived) return derived() = Derived::NullaryExpr(size, ei_linspaced_op(low,high,size)); diff --git a/Eigen/src/Core/DenseBase.h b/Eigen/src/Core/DenseBase.h index 6f5013e2d..c84544ec3 100644 --- a/Eigen/src/Core/DenseBase.h +++ b/Eigen/src/Core/DenseBase.h @@ -398,9 +398,13 @@ template class DenseBase Constant(const Scalar& value); static const SequentialLinSpacedReturnType - LinSpaced(Sequential_t, const Scalar& low, const Scalar& high, Index size); + LinSpaced(Sequential_t, Index size, const Scalar& low, const Scalar& high); static const RandomAccessLinSpacedReturnType - LinSpaced(const Scalar& low, const Scalar& high, Index size); + LinSpaced(Index size, const Scalar& low, const Scalar& high); + static const SequentialLinSpacedReturnType + LinSpaced(Sequential_t, const Scalar& low, const Scalar& high); + static const RandomAccessLinSpacedReturnType + LinSpaced(const Scalar& low, const Scalar& high); template static const CwiseNullaryOp @@ -421,7 +425,8 @@ template class DenseBase void fill(const Scalar& value); Derived& setConstant(const Scalar& value); - Derived& setLinSpaced(const Scalar& low, const Scalar& high, Index size); + Derived& setLinSpaced(Index size, const Scalar& low, const Scalar& high); + Derived& setLinSpaced(const Scalar& low, const Scalar& high); Derived& setZero(); Derived& setOnes(); Derived& setRandom(); diff --git a/Eigen/src/Core/Functors.h b/Eigen/src/Core/Functors.h index 9084905aa..c3a3a92c4 100644 --- a/Eigen/src/Core/Functors.h +++ b/Eigen/src/Core/Functors.h @@ -573,7 +573,7 @@ template struct ei_linspaced_op template EIGEN_STRONG_INLINE const PacketScalar packetOp(Index i, Index = 0) const { return impl.packetOp(i); } // This proxy object handles the actual required temporaries, the different - // implementations (random vs. sequential access) as well as the piping + // implementations (random vs. sequential access) as well as the // correct piping to size 2/4 packet operations. const ei_linspaced_op_impl impl; }; diff --git a/doc/snippets/DenseBase_LinSpaced.cpp b/doc/snippets/DenseBase_LinSpaced.cpp index c8c3e972c..8e54b17fc 100644 --- a/doc/snippets/DenseBase_LinSpaced.cpp +++ b/doc/snippets/DenseBase_LinSpaced.cpp @@ -1,2 +1,2 @@ -cout << VectorXi::LinSpaced(7,10,4).transpose() << endl; -cout << VectorXd::LinSpaced(0.0,1.0,5).transpose() << endl; +cout << VectorXi::LinSpaced(4,7,10).transpose() << endl; +cout << VectorXd::LinSpaced(5,0.0,1.0).transpose() << endl; diff --git a/doc/snippets/DenseBase_LinSpaced_seq.cpp b/doc/snippets/DenseBase_LinSpaced_seq.cpp index 73873c4e9..f55c5085d 100644 --- a/doc/snippets/DenseBase_LinSpaced_seq.cpp +++ b/doc/snippets/DenseBase_LinSpaced_seq.cpp @@ -1,2 +1,2 @@ -cout << VectorXi::LinSpaced(Sequential,7,10,4).transpose() << endl; -cout << VectorXd::LinSpaced(Sequential,0.0,1.0,5).transpose() << endl; +cout << VectorXi::LinSpaced(Sequential,4,7,10).transpose() << endl; +cout << VectorXd::LinSpaced(Sequential,5,0.0,1.0).transpose() << endl; diff --git a/doc/snippets/DenseBase_setLinSpaced.cpp b/doc/snippets/DenseBase_setLinSpaced.cpp index a8ea73407..50871dfcc 100644 --- a/doc/snippets/DenseBase_setLinSpaced.cpp +++ b/doc/snippets/DenseBase_setLinSpaced.cpp @@ -1,3 +1,3 @@ VectorXf v; -v.setLinSpaced(0.5f,1.5f,5).transpose(); +v.setLinSpaced(5,0.5f,1.5f).transpose(); cout << v << endl; diff --git a/test/nullary.cpp b/test/nullary.cpp index c54999580..78d2e9117 100644 --- a/test/nullary.cpp +++ b/test/nullary.cpp @@ -59,7 +59,7 @@ void testVectorType(const VectorType& base) // check whether the result yields what we expect it to do VectorType m(base); - m.setLinSpaced(low,high,size); + m.setLinSpaced(size,low,high); VectorType n(size); for (int i=0; i::epsilon()*10e3 ); // random access version - m = VectorType::LinSpaced(low,high,size); + m = VectorType::LinSpaced(size,low,high); VERIFY( (m-n).norm() < std::numeric_limits::epsilon()*10e3 ); // These guys sometimes fail! This is not good. Any ideas how to fix them!? @@ -76,7 +76,7 @@ void testVectorType(const VectorType& base) //VERIFY( m(0) == low ); // sequential access version - m = VectorType::LinSpaced(Sequential,low,high,size); + m = VectorType::LinSpaced(Sequential,size,low,high); VERIFY( (m-n).norm() < std::numeric_limits::epsilon()*10e3 ); // These guys sometimes fail! This is not good. Any ideas how to fix them!? @@ -86,12 +86,12 @@ void testVectorType(const VectorType& base) // check whether everything works with row and col major vectors Matrix row_vector(size); Matrix col_vector(size); - row_vector.setLinSpaced(low,high,size); - col_vector.setLinSpaced(low,high,size); + row_vector.setLinSpaced(size,low,high); + col_vector.setLinSpaced(size,low,high); VERIFY( row_vector.isApprox(col_vector.transpose(), NumTraits::epsilon())); Matrix size_changer(size+50); - size_changer.setLinSpaced(low,high,size); + size_changer.setLinSpaced(size,low,high); VERIFY( size_changer.size() == size ); } From fa6d36e0f7453397627b5dd82acb64922b977686 Mon Sep 17 00:00:00 2001 From: Gael Guennebaud Date: Thu, 22 Jul 2010 15:57:01 +0200 Subject: [PATCH 40/41] fix SparseView: clean the nested matrix type --- Eigen/src/Sparse/SparseView.h | 9 +++++++-- test/sparse_basic.cpp | 7 +++++++ 2 files changed, 14 insertions(+), 2 deletions(-) diff --git a/Eigen/src/Sparse/SparseView.h b/Eigen/src/Sparse/SparseView.h index 3b656d5c8..5a152b255 100644 --- a/Eigen/src/Sparse/SparseView.h +++ b/Eigen/src/Sparse/SparseView.h @@ -31,18 +31,23 @@ struct ei_traits > : ei_traits { typedef int Index; typedef Sparse StorageKind; + enum { + Flags = int(ei_traits::Flags) & (RowMajorBit) + }; }; template class SparseView : public SparseMatrixBase > { typedef typename MatrixType::Nested MatrixTypeNested; + typedef typename ei_cleantype::type _MatrixTypeNested; public: EIGEN_SPARSE_PUBLIC_INTERFACE(SparseView) SparseView(const MatrixType& mat, const Scalar& m_reference = Scalar(0), typename NumTraits::Real m_epsilon = NumTraits::dummy_precision()) : m_matrix(mat), m_reference(m_reference), m_epsilon(m_epsilon) {} + class InnerIterator; inline Index rows() const { return m_matrix.rows(); } @@ -58,10 +63,10 @@ protected: }; template -class SparseView::InnerIterator : public MatrixTypeNested::InnerIterator +class SparseView::InnerIterator : public _MatrixTypeNested::InnerIterator { public: - typedef typename MatrixTypeNested::InnerIterator IterBase; + typedef typename _MatrixTypeNested::InnerIterator IterBase; InnerIterator(const SparseView& view, Index outer) : IterBase(view.m_matrix, outer), m_view(view) { diff --git a/test/sparse_basic.cpp b/test/sparse_basic.cpp index 3ebd59294..8c93909c6 100644 --- a/test/sparse_basic.cpp +++ b/test/sparse_basic.cpp @@ -250,6 +250,13 @@ template void sparse_basic(const SparseMatrixType& re VERIFY(countTrueNonZero==m2.nonZeros()); VERIFY_IS_APPROX(m2, refM2); } + + // test sparseView + { + DenseMatrix refMat2 = DenseMatrix::Zero(rows, rows); + SparseMatrixType m2(rows, rows); + VERIFY_IS_APPROX(m2.eval(), refMat2.sparseView().eval()); + } } void test_sparse_basic() From 96ba7cd6557769e01778441cdf7855295542aad0 Mon Sep 17 00:00:00 2001 From: Gael Guennebaud Date: Thu, 22 Jul 2010 16:08:58 +0200 Subject: [PATCH 41/41] add an OpenGL module simplifying the way you can pass Eigen's objects to GL --- Eigen/src/Core/util/StaticAssert.h | 1 + unsupported/Eigen/OpenGLSupport | 190 +++++++++++++++++++++++++++++ unsupported/test/CMakeLists.txt | 14 ++- unsupported/test/openglsupport.cpp | 61 +++++++++ 4 files changed, 265 insertions(+), 1 deletion(-) create mode 100644 unsupported/Eigen/OpenGLSupport create mode 100644 unsupported/test/openglsupport.cpp diff --git a/Eigen/src/Core/util/StaticAssert.h b/Eigen/src/Core/util/StaticAssert.h index 9d3169967..bf686975b 100644 --- a/Eigen/src/Core/util/StaticAssert.h +++ b/Eigen/src/Core/util/StaticAssert.h @@ -60,6 +60,7 @@ YOU_MIXED_MATRICES_OF_DIFFERENT_SIZES, THIS_METHOD_IS_ONLY_FOR_VECTORS_OF_A_SPECIFIC_SIZE, THIS_METHOD_IS_ONLY_FOR_MATRICES_OF_A_SPECIFIC_SIZE, + THIS_METHOD_IS_ONLY_FOR_OBJECTS_OF_A_SPECIFIC_SIZE, YOU_MADE_A_PROGRAMMING_MISTAKE, EIGEN_INTERNAL_COMPILATION_ERROR_OR_YOU_MADE_A_PROGRAMMING_MISTAKE, YOU_CALLED_A_FIXED_SIZE_METHOD_ON_A_DYNAMIC_SIZE_MATRIX_OR_VECTOR, diff --git a/unsupported/Eigen/OpenGLSupport b/unsupported/Eigen/OpenGLSupport new file mode 100644 index 000000000..2a9de99b0 --- /dev/null +++ b/unsupported/Eigen/OpenGLSupport @@ -0,0 +1,190 @@ +// This file is part of Eigen, a lightweight C++ template library +// for linear algebra. +// +// Copyright (C) 2010 Gael Guennebaud +// +// Eigen is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 3 of the License, or (at your option) any later version. +// +// Alternatively, 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 2 of +// the License, or (at your option) any later version. +// +// Eigen is distributed in the hope that it will be useful, but WITHOUT ANY +// WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +// FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License or the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License and a copy of the GNU General Public License along with +// Eigen. If not, see . + +#ifndef EIGEN_OPENGL_MODULE +#define EIGEN_OPENGL_MODULE + +#include +#include + +namespace Eigen { + +/** \ingroup Unsupported_modules + * \defgroup OpenGLSUpport_Module OpenGL Support module + * + * This module provides wrapper functions for a couple of OpenGL functions + * which simplify the way to pass Eigen's object to openGL. + * Here is an exmaple: + * + * \code + * // You need to add path_to_eigen/unsupported to your include path. + * #include + * // ... + * Vector3f x, y; + * Matrix3f rot; + * + * glVertex(y + x * rot); + * + * Quaternion q; + * glRotate(q); + * + * // ... + * \endcode + * + */ +//@{ + +#define EIGEN_GL_FUNC_DECLARATION(FUNC) \ +template< typename XprType, \ + typename Scalar = typename XprType::Scalar, \ + int Rows = XprType::RowsAtCompileTime, \ + int Cols = XprType::ColsAtCompileTime, \ + bool IsGLCompatible = bool(XprType::Flags&LinearAccessBit) \ + && bool(XprType::Flags&DirectAccessBit) \ + && (XprType::IsVectorAtCompileTime || (XprType::Flags&RowMajorBit)==0)> \ +struct EIGEN_CAT(EIGEN_CAT(ei_gl_,FUNC),_impl); \ + \ +template \ +struct EIGEN_CAT(EIGEN_CAT(ei_gl_,FUNC),_impl) { \ + inline static void run(const XprType& p) { \ + EIGEN_CAT(EIGEN_CAT(ei_gl_,FUNC),_impl)::type>::run(p); } \ +}; \ + \ +template inline void FUNC(const Eigen::DenseBase& p) { \ + EIGEN_CAT(EIGEN_CAT(ei_gl_,FUNC),_impl)::run(p.derived()); \ +} + + +#define EIGEN_GL_FUNC_SPECIALIZATION_MAT(FUNC,SCALAR,ROWS,COLS,SUFFIX) \ + template< typename XprType> struct EIGEN_CAT(EIGEN_CAT(ei_gl_,FUNC),_impl) { \ + inline static void run(const XprType& p) { FUNC##SUFFIX(p.data()); } \ + }; + + +#define EIGEN_GL_FUNC_SPECIALIZATION_VEC(FUNC,SCALAR,SIZE,SUFFIX) \ + template< typename XprType> struct EIGEN_CAT(EIGEN_CAT(ei_gl_,FUNC),_impl) { \ + inline static void run(const XprType& p) { FUNC##SUFFIX(p.data()); } \ + }; \ + template< typename XprType> struct EIGEN_CAT(EIGEN_CAT(ei_gl_,FUNC),_impl) { \ + inline static void run(const XprType& p) { FUNC##SUFFIX(p.data()); } \ + }; + +EIGEN_GL_FUNC_DECLARATION (glVertex) +EIGEN_GL_FUNC_SPECIALIZATION_VEC(glVertex,int, 2,2iv) +EIGEN_GL_FUNC_SPECIALIZATION_VEC(glVertex,short, 2,2sv) +EIGEN_GL_FUNC_SPECIALIZATION_VEC(glVertex,float, 2,2fv) +EIGEN_GL_FUNC_SPECIALIZATION_VEC(glVertex,double, 2,2dv) +EIGEN_GL_FUNC_SPECIALIZATION_VEC(glVertex,int, 3,3iv) +EIGEN_GL_FUNC_SPECIALIZATION_VEC(glVertex,short, 3,3sv) +EIGEN_GL_FUNC_SPECIALIZATION_VEC(glVertex,float, 3,3fv) +EIGEN_GL_FUNC_SPECIALIZATION_VEC(glVertex,double, 3,3dv) +EIGEN_GL_FUNC_SPECIALIZATION_VEC(glVertex,int, 4,4iv) +EIGEN_GL_FUNC_SPECIALIZATION_VEC(glVertex,short, 4,4sv) +EIGEN_GL_FUNC_SPECIALIZATION_VEC(glVertex,float, 4,4fv) +EIGEN_GL_FUNC_SPECIALIZATION_VEC(glVertex,double, 4,4dv) + +EIGEN_GL_FUNC_DECLARATION (glTexCoord) +EIGEN_GL_FUNC_SPECIALIZATION_VEC(glTexCoord,int, 2,2iv) +EIGEN_GL_FUNC_SPECIALIZATION_VEC(glTexCoord,short, 2,2sv) +EIGEN_GL_FUNC_SPECIALIZATION_VEC(glTexCoord,float, 2,2fv) +EIGEN_GL_FUNC_SPECIALIZATION_VEC(glTexCoord,double, 2,2dv) +EIGEN_GL_FUNC_SPECIALIZATION_VEC(glTexCoord,int, 3,3iv) +EIGEN_GL_FUNC_SPECIALIZATION_VEC(glTexCoord,short, 3,3sv) +EIGEN_GL_FUNC_SPECIALIZATION_VEC(glTexCoord,float, 3,3fv) +EIGEN_GL_FUNC_SPECIALIZATION_VEC(glTexCoord,double, 3,3dv) +EIGEN_GL_FUNC_SPECIALIZATION_VEC(glTexCoord,int, 4,4iv) +EIGEN_GL_FUNC_SPECIALIZATION_VEC(glTexCoord,short, 4,4sv) +EIGEN_GL_FUNC_SPECIALIZATION_VEC(glTexCoord,float, 4,4fv) +EIGEN_GL_FUNC_SPECIALIZATION_VEC(glTexCoord,double, 4,4dv) + +EIGEN_GL_FUNC_DECLARATION (glColor) +EIGEN_GL_FUNC_SPECIALIZATION_VEC(glColor,int, 2,2iv) +EIGEN_GL_FUNC_SPECIALIZATION_VEC(glColor,short, 2,2sv) +EIGEN_GL_FUNC_SPECIALIZATION_VEC(glColor,float, 2,2fv) +EIGEN_GL_FUNC_SPECIALIZATION_VEC(glColor,double, 2,2dv) +EIGEN_GL_FUNC_SPECIALIZATION_VEC(glColor,int, 3,3iv) +EIGEN_GL_FUNC_SPECIALIZATION_VEC(glColor,short, 3,3sv) +EIGEN_GL_FUNC_SPECIALIZATION_VEC(glColor,float, 3,3fv) +EIGEN_GL_FUNC_SPECIALIZATION_VEC(glColor,double, 3,3dv) +EIGEN_GL_FUNC_SPECIALIZATION_VEC(glColor,int, 4,4iv) +EIGEN_GL_FUNC_SPECIALIZATION_VEC(glColor,short, 4,4sv) +EIGEN_GL_FUNC_SPECIALIZATION_VEC(glColor,float, 4,4fv) +EIGEN_GL_FUNC_SPECIALIZATION_VEC(glColor,double, 4,4dv) + +EIGEN_GL_FUNC_DECLARATION (glNormal) +EIGEN_GL_FUNC_SPECIALIZATION_VEC(glNormal,int, 3,3iv) +EIGEN_GL_FUNC_SPECIALIZATION_VEC(glNormal,short, 3,3sv) +EIGEN_GL_FUNC_SPECIALIZATION_VEC(glNormal,float, 3,3fv) +EIGEN_GL_FUNC_SPECIALIZATION_VEC(glNormal,double, 3,3dv) + +inline void glScale2fv(const float* v) { glScalef(v[0], v[1], 1.f); } +inline void glScale2dv(const double* v) { glScaled(v[0], v[1], 1.0); } +inline void glScale3fv(const float* v) { glScalef(v[0], v[1], v[2]); } +inline void glScale3dv(const double* v) { glScaled(v[0], v[1], v[2]); } + +EIGEN_GL_FUNC_DECLARATION (glScale) +EIGEN_GL_FUNC_SPECIALIZATION_VEC(glScale,float, 2,2fv) +EIGEN_GL_FUNC_SPECIALIZATION_VEC(glScale,double, 2,2dv) +EIGEN_GL_FUNC_SPECIALIZATION_VEC(glScale,float, 3,3fv) +EIGEN_GL_FUNC_SPECIALIZATION_VEC(glScale,double, 3,3dv) + +inline void glTranslate2fv(const float* v) { glScalef(v[0], v[1], 1.f); } +inline void glTranslate2dv(const double* v) { glScaled(v[0], v[1], 1.0); } +inline void glTranslate3fv(const float* v) { glScalef(v[0], v[1], v[2]); } +inline void glTranslate3dv(const double* v) { glScaled(v[0], v[1], v[2]); } + +EIGEN_GL_FUNC_DECLARATION (glTranslate) +EIGEN_GL_FUNC_SPECIALIZATION_VEC(glTranslate,float, 2,2fv) +EIGEN_GL_FUNC_SPECIALIZATION_VEC(glTranslate,double, 2,2dv) +EIGEN_GL_FUNC_SPECIALIZATION_VEC(glTranslate,float, 3,3fv) +EIGEN_GL_FUNC_SPECIALIZATION_VEC(glTranslate,double, 3,3dv) + +EIGEN_GL_FUNC_DECLARATION (glMultMatrix) +EIGEN_GL_FUNC_SPECIALIZATION_MAT(glMultMatrix,float, 4,4,f) +EIGEN_GL_FUNC_SPECIALIZATION_MAT(glMultMatrix,double, 4,4,d) + +EIGEN_GL_FUNC_DECLARATION (glLoadMatrix) +EIGEN_GL_FUNC_SPECIALIZATION_MAT(glLoadMatrix,float, 4,4,f) +EIGEN_GL_FUNC_SPECIALIZATION_MAT(glLoadMatrix,double, 4,4,d) + +void glRotate(const Rotation2D& rot) +{ + glRotatef(rot.angle()*180.f/float(M_PI), 0.f, 0.f, 1.f); +} +void glRotate(const Rotation2D& rot) +{ + glRotated(rot.angle()*180.0/M_PI, 0.0, 0.0, 1.0); +} + +template void glRotate(const RotationBase& rot) +{ + Transform tr(rot); + glMultMatrix(tr.matrix()); +} + +//@} + +} + +#endif // EIGEN_OPENGL_MODULE diff --git a/unsupported/test/CMakeLists.txt b/unsupported/test/CMakeLists.txt index 5bad3282d..ad2b9296e 100644 --- a/unsupported/test/CMakeLists.txt +++ b/unsupported/test/CMakeLists.txt @@ -86,8 +86,20 @@ ei_add_test(sparse_extra " " " ") find_package(FFTW) if(FFTW_FOUND) + ei_add_property(EIGEN_TESTED_BACKENDS "fftw, ") ei_add_test(FFTW "-DEIGEN_FFTW_DEFAULT " "-lfftw3 -lfftw3f -lfftw3l" ) -endif(FFTW_FOUND) +else() + ei_add_property(EIGEN_MISSING_BACKENDS "fftw, ") +endif() + +find_package(OpenGL) +find_package(GLUT) +if(OPENGL_FOUND AND GLUT_FOUND) + ei_add_property(EIGEN_TESTED_BACKENDS "opengl, ") + ei_add_test(openglsupport "" "${GLUT_LIBRARY}" ) +else() + ei_add_property(EIGEN_MISSING_BACKENDS "opengl, ") +endif() find_package(GSL) if(GSL_FOUND AND GSL_VERSION_MINOR LESS 9) diff --git a/unsupported/test/openglsupport.cpp b/unsupported/test/openglsupport.cpp new file mode 100644 index 000000000..83b476917 --- /dev/null +++ b/unsupported/test/openglsupport.cpp @@ -0,0 +1,61 @@ +// This file is part of Eigen, a lightweight C++ template library +// for linear algebra. +// +// Copyright (C) 2010 Gael Guennebaud +// +// Eigen is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 3 of the License, or (at your option) any later version. +// +// Alternatively, 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 2 of +// the License, or (at your option) any later version. +// +// Eigen is distributed in the hope that it will be useful, but WITHOUT ANY +// WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +// FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License or the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License and a copy of the GNU General Public License along with +// Eigen. If not, see . + +#include +#include +#include +using namespace Eigen; + +int main(int argc, char **argv) +{ + glutInit(&argc, argv); + glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH); + glutInitWindowPosition (0,0); + glutInitWindowSize(10, 10); + + if(glutCreateWindow("Eigen") <= 0) + { + std::cerr << "Unable to create GLUT Window.\n"; + exit(1); + } + + Vector3f v3f; + Matrix3f rot; + glBegin(GL_POINTS); + + glVertex(v3f); + glVertex(2*v3f+v3f); + glVertex(rot*v3f); + + glEnd(); + + Quaterniond qd; + glRotate(qd); + + Matrix4f m44; + glLoadMatrix(m44); + glMultMatrix(m44); + + return 0; +}