From f9ca8e2d20f1c29381906a83bc66f818362bc651 Mon Sep 17 00:00:00 2001 From: ser1zw Date: Sun, 9 Jan 2011 03:05:52 +0900 Subject: [PATCH] fixed CvMat#eigenvv, removed CvMat#eigenvv!, and added some tests --- ext/cvmat.cpp | 30 ++++++++-------------------- test/test_cvmat.rb | 50 ++++++++++++++++++++++++++++++++++++++++++---- 2 files changed, 54 insertions(+), 26 deletions(-) diff --git a/ext/cvmat.cpp b/ext/cvmat.cpp index 069c1d6..89e031b 100644 --- a/ext/cvmat.cpp +++ b/ext/cvmat.cpp @@ -281,7 +281,6 @@ void define_ruby_class() rb_define_method(rb_klass, "svd", RUBY_METHOD_FUNC(rb_svd), -1); rb_define_method(rb_klass, "svbksb", RUBY_METHOD_FUNC(rb_svbksb), -1); rb_define_method(rb_klass, "eigenvv", RUBY_METHOD_FUNC(rb_eigenvv), -1); - rb_define_method(rb_klass, "eigenvv!", RUBY_METHOD_FUNC(rb_eigenvv_bang), -1); rb_define_method(rb_klass, "calc_covar_matrix", RUBY_METHOD_FUNC(rb_calc_covar_matrix), -1); rb_define_method(rb_klass, "mahalonobis", RUBY_METHOD_FUNC(rb_mahalonobis), -1); @@ -2331,21 +2330,6 @@ rb_svbksb(int argc, VALUE *argv, VALUE self) rb_raise(rb_eNotImpError, ""); } -/* - * call-seq: - * eigenvv([eps = 0.0]) -> [eigen_vectors(cvmat), eigen_values(cvmat)] - * - * Computes eigenvalues and eigenvectors of symmetric matrix. - * self should be symmetric square matrix. - * - * see #eigenvv! - */ -VALUE -rb_eigenvv(int argc, VALUE *argv, VALUE self) -{ - return rb_eigenvv_bang(argc, argv, copy(self)); -} - /* * call-seq: * eigenvv!([eps = 0.0]) -> [eigen_vectors(cvmat), eigen_values(cvmat)] @@ -2355,21 +2339,23 @@ rb_eigenvv(int argc, VALUE *argv, VALUE self) * * self * eigen_vectors(i,:)' = eigen_values(i) * eigen_vectors(i,:)' * - * The contents of self is destroyed by this method. - * * Currently the function is slower than #svd yet less accurate, so if self is known to be positively-defined * (e.g., it is a convariation matrix), it is recommanded to use #svd to find eigenvalues and eigenvectors of self, * especially if eigenvectors are not required. */ VALUE -rb_eigenvv_bang(int argc, VALUE *argv, VALUE self) +rb_eigenvv(int argc, VALUE *argv, VALUE self) { - VALUE epsilon; - double eps = rb_scan_args(argc, argv, "01", &epsilon) < 1 ? 0.0 : NUM2DBL(epsilon); + VALUE epsilon, lowindex, highindex; + rb_scan_args(argc, argv, "03", &epsilon, &lowindex, &highindex); + double eps = (NIL_P(epsilon)) ? 0.0 : NUM2DBL(epsilon); + int lowidx = (NIL_P(lowindex)) ? -1 : NUM2INT(lowindex); + int highidx = (NIL_P(highindex)) ? -1 : NUM2INT(highindex); + CvSize size = cvGetSize(CVARR(self)); int type = cvGetElemType(CVARR(self)); VALUE eigen_vectors = new_object(size, type), eigen_values = new_object(size.height, 1, type); - cvEigenVV(CVARR(self), CVARR(eigen_vectors), CVARR(eigen_values), eps); + cvEigenVV(CVARR(self), CVARR(eigen_vectors), CVARR(eigen_values), eps, lowidx, highidx); return rb_ary_new3(2, eigen_vectors, eigen_values); } diff --git a/test/test_cvmat.rb b/test/test_cvmat.rb index 0b901ec..bd213fd 100755 --- a/test/test_cvmat.rb +++ b/test/test_cvmat.rb @@ -1722,15 +1722,57 @@ class TestCvMat < OpenCVTestCase m0 = create_cvmat(3, 3, :cv32f, 1) { |j, i, c| CvScalar.new(elems1[c]) } - m1 = create_cvmat(3, 1, :cv32f, 1) { |j, i, c| + b = create_cvmat(3, 1, :cv32f, 1) { |j, i, c| CvScalar.new(elems2[c]) } - m2 = m0.solve(m1) + + m1 = m0.solve(b) + m2 = m0.solve(b, :lu) + m3 = m0.solve(b, :svd) + m4 = m0.solve(b, :svd_sym) + m5 = m0.solve(b, :svd_symmetric) expected = [2, -2, 1] - assert_each_cvscalar(m2, 0.001) { |j, i, c| - CvScalar.new(expected[c]) + [m1, m2, m3, m4, m5].each { |m| + assert_equal(b.width, m.width) + assert_equal(m0.height, m.height) + assert_each_cvscalar(m, 0.001) { |j, i, c| + CvScalar.new(expected[c]) + } } end + + def test_svd + flunk('CvMat#svd is not implemented yet') + end + + def test_svdksb + flunk('CvMat#svdksb is not implemented yet') + end + + def test_eigenvv + elems = [6, -2, -3, 7] + m0 = create_cvmat(2, 2, :cv32f, 1) { |j, i, c| + CvScalar.new(elems[c]) + } + + v1 = m0.eigenvv + v2 = m0.eigenvv(10 ** -15) + v3 = m0.eigenvv(10 ** -15, 1, 1) + + [v1, v2].each { |vec, val| + assert_in_delta(-0.615, vec[0, 0][0], 0.01) + assert_in_delta(0.788, vec[0, 1][0], 0.01) + assert_in_delta(0.788, vec[1, 0][0], 0.01) + assert_in_delta(0.615, vec[1, 1][0], 0.01) + assert_in_delta(8.562, val[0][0], 0.01) + assert_in_delta(4.438, val[1][0], 0.01) + } + + vec3, val3 = v3 + assert_in_delta(-0.615, vec3[0, 0][0], 0.01) + assert_in_delta(0.788, vec3[0, 1][0], 0.01) + assert_in_delta(8.562, val3[0][0], 0.01) + end end