comparison src/data.cc @ 8303:b11c31849b44

improve norm computation capabilities
author Jaroslav Hajek <highegg@gmail.com>
date Fri, 31 Oct 2008 08:05:32 +0100
parents 6f2d95255911
children fa78cb8d8a5c
comparison
equal deleted inserted replaced
8302:f2e050b62199 8303:b11c31849b44
60 #include "parse.h" 60 #include "parse.h"
61 #include "pt-mat.h" 61 #include "pt-mat.h"
62 #include "utils.h" 62 #include "utils.h"
63 #include "variables.h" 63 #include "variables.h"
64 #include "pager.h" 64 #include "pager.h"
65 #include "xnorm.h"
65 66
66 #if ! defined (HAVE_HYPOTF) && defined (HAVE__HYPOTF) 67 #if ! defined (HAVE_HYPOTF) && defined (HAVE__HYPOTF)
67 #define hypotf _hypotf 68 #define hypotf _hypotf
68 #define HAVE_HYPOTF 1 69 #define HAVE_HYPOTF 1
69 #endif 70 #endif
4572 4573
4573 // Compute various norms of the vector X. 4574 // Compute various norms of the vector X.
4574 4575
4575 DEFUN (norm, args, , 4576 DEFUN (norm, args, ,
4576 "-*- texinfo -*-\n\ 4577 "-*- texinfo -*-\n\
4577 @deftypefn {Function File} {} norm (@var{a}, @var{p})\n\ 4578 @deftypefn {Function File} {} norm (@var{a}, @var{p}, @var{opt})\n\
4578 Compute the p-norm of the matrix @var{a}. If the second argument is\n\ 4579 Compute the p-norm of the matrix @var{a}. If the second argument is\n\
4579 missing, @code{p = 2} is assumed.\n\ 4580 missing, @code{p = 2} is assumed.\n\
4580 \n\ 4581 \n\
4581 If @var{a} is a matrix:\n\ 4582 If @var{a} is a matrix (or sparse matrix):\n\
4582 \n\ 4583 \n\
4583 @table @asis\n\ 4584 @table @asis\n\
4584 @item @var{p} = @code{1}\n\ 4585 @item @var{p} = @code{1}\n\
4585 1-norm, the largest column sum of the absolute values of @var{a}.\n\ 4586 1-norm, the largest column sum of the absolute values of @var{a}.\n\
4586 \n\ 4587 \n\
4592 Infinity norm, the largest row sum of the absolute values of @var{a}.\n\ 4593 Infinity norm, the largest row sum of the absolute values of @var{a}.\n\
4593 \n\ 4594 \n\
4594 @item @var{p} = @code{\"fro\"}\n\ 4595 @item @var{p} = @code{\"fro\"}\n\
4595 @cindex Frobenius norm\n\ 4596 @cindex Frobenius norm\n\
4596 Frobenius norm of @var{a}, @code{sqrt (sum (diag (@var{a}' * @var{a})))}.\n\ 4597 Frobenius norm of @var{a}, @code{sqrt (sum (diag (@var{a}' * @var{a})))}.\n\
4598 \n\
4599 @item other @var{p}, @code{@var{p} > 1}\n\
4600 @cindex general p-norm \n\
4601 maximum @code{norm (A*x, p)} such that @code{norm (x, p) == 1}\n\
4597 @end table\n\ 4602 @end table\n\
4598 \n\ 4603 \n\
4599 If @var{a} is a vector or a scalar:\n\ 4604 If @var{a} is a vector or a scalar:\n\
4600 \n\ 4605 \n\
4601 @table @asis\n\ 4606 @table @asis\n\
4606 @code{min (abs (@var{a}))}.\n\ 4611 @code{min (abs (@var{a}))}.\n\
4607 \n\ 4612 \n\
4608 @item @var{p} = @code{\"fro\"}\n\ 4613 @item @var{p} = @code{\"fro\"}\n\
4609 Frobenius norm of @var{a}, @code{sqrt (sumsq (abs (a)))}.\n\ 4614 Frobenius norm of @var{a}, @code{sqrt (sumsq (abs (a)))}.\n\
4610 \n\ 4615 \n\
4611 @item other\n\ 4616 @item @var{p} = 0\n\
4617 Hamming norm - the number of nonzero elements.\n\
4618 \n\
4619 @item other @var{p}, @code{@var{p} > 1}\n\
4612 p-norm of @var{a}, @code{(sum (abs (@var{a}) .^ @var{p})) ^ (1/@var{p})}.\n\ 4620 p-norm of @var{a}, @code{(sum (abs (@var{a}) .^ @var{p})) ^ (1/@var{p})}.\n\
4621 \n\
4622 @item other @var{p} @code{@var{p} < 1}\n\
4623 the p-pseudonorm defined as above.\n\
4613 @end table\n\ 4624 @end table\n\
4625 \n\
4626 If @code{\"rows\"} is given as @var{opt}, the norms of all rows of the matrix @var{a} are\n\
4627 returned as a column vector. Similarly, if @code{\"columns\"} or @code{\"cols\"} is passed\n\
4628 column norms are computed.\n\
4614 @seealso{cond, svd}\n\ 4629 @seealso{cond, svd}\n\
4615 @end deftypefn") 4630 @end deftypefn")
4616 { 4631 {
4617 // Currently only handles vector norms for full double/complex
4618 // vectors internally. Other cases are handled by __norm__.m.
4619
4620 octave_value_list retval; 4632 octave_value_list retval;
4621 4633
4622 int nargin = args.length (); 4634 int nargin = args.length ();
4623 4635
4624 if (nargin == 1 || nargin == 2) 4636 if (nargin >= 1 && nargin <= 3)
4625 { 4637 {
4626 octave_value x_arg = args(0); 4638 octave_value x_arg = args(0);
4627 4639
4628 if (x_arg.is_empty ()) 4640 if (x_arg.is_empty ())
4629 { 4641 {
4632 else 4644 else
4633 retval(0) = 0.0; 4645 retval(0) = 0.0;
4634 } 4646 }
4635 else if (x_arg.ndims () == 2) 4647 else if (x_arg.ndims () == 2)
4636 { 4648 {
4637 if ((x_arg.rows () == 1 || x_arg.columns () == 1) 4649 enum { sfmatrix, sfcols, sfrows, sffrob, sfinf } strflag = sfmatrix;
4638 && ! (x_arg.is_sparse_type () || x_arg.is_integer_type ())) 4650 if (nargin > 1 && args(nargin-1).is_string ())
4639 { 4651 {
4640 double p_val = 2; 4652 std::string str = args(nargin-1).string_value ();
4641 4653 if (str == "cols" || str == "columns")
4642 if (nargin == 2) 4654 strflag = sfcols;
4643 { 4655 else if (str == "rows")
4644 octave_value p_arg = args(1); 4656 strflag = sfrows;
4645 4657 else if (str == "fro")
4646 if (p_arg.is_string ()) 4658 strflag = sffrob;
4647 { 4659 else if (str == "inf")
4648 std::string p = args(1).string_value (); 4660 strflag = sfinf;
4649 4661 else
4650 if (p == "inf") 4662 error ("norm: unrecognized option: %s", str.c_str ());
4651 p_val = octave_Inf; 4663 // we've handled the last parameter, so act as if it was removed
4652 else if (p == "fro") 4664 nargin --;
4653 p_val = -1; 4665 }
4654 else 4666 else if (nargin > 1 && ! args(1).is_scalar_type ())
4655 error ("norm: unrecognized norm `%s'", p.c_str ()); 4667 gripe_wrong_type_arg ("norm", args(1), true);
4656 } 4668
4657 else 4669 if (! error_state)
4658 { 4670 {
4659 p_val = p_arg.double_value (); 4671 octave_value p_arg = (nargin > 1) ? args(1) : octave_value (2);
4660 4672 switch (strflag)
4661 if (error_state) 4673 {
4662 error ("norm: unrecognized norm value"); 4674 case sfmatrix:
4663 } 4675 retval(0) = xnorm (x_arg, p_arg);
4664 } 4676 break;
4665 4677 case sfcols:
4666 if (x_arg.is_single_type ()) 4678 retval(0) = xcolnorms (x_arg, p_arg);
4667 { 4679 break;
4668 if (! error_state) 4680 case sfrows:
4669 { 4681 retval(0) = xrownorms (x_arg, p_arg);
4670 if (x_arg.is_real_type ()) 4682 break;
4671 { 4683 case sffrob:
4672 MArray<float> x (x_arg.float_array_value ()); 4684 retval(0) = xfrobnorm (x_arg);
4673 4685 break;
4674 if (! error_state) 4686 case sfinf:
4675 retval(0) = x.norm (static_cast<float>(p_val)); 4687 retval(0) = xnorm (x_arg, octave_Inf);
4676 else 4688 break;
4677 error ("norm: expecting real vector"); 4689 }
4678 } 4690 }
4679 else
4680 {
4681 MArray<FloatComplex> x (x_arg.float_complex_array_value ());
4682
4683 if (! error_state)
4684 retval(0) = x.norm (static_cast<float>(p_val));
4685 else
4686 error ("norm: expecting complex vector");
4687 }
4688 }
4689 }
4690 else
4691 {
4692 if (! error_state)
4693 {
4694 if (x_arg.is_real_type ())
4695 {
4696 MArray<double> x (x_arg.array_value ());
4697
4698 if (! error_state)
4699 retval(0) = x.norm (p_val);
4700 else
4701 error ("norm: expecting real vector");
4702 }
4703 else
4704 {
4705 MArray<Complex> x (x_arg.complex_array_value ());
4706
4707 if (! error_state)
4708 retval(0) = x.norm (p_val);
4709 else
4710 error ("norm: expecting complex vector");
4711 }
4712 }
4713 }
4714 }
4715 else
4716 retval = feval ("__norm__", args);
4717 } 4691 }
4718 else 4692 else
4719 error ("norm: only valid for 2-D objects"); 4693 error ("norm: only valid for 2-D objects");
4720 } 4694 }
4721 else 4695 else
4722 print_usage (); 4696 print_usage ();
4723
4724 // Should not return a sparse type
4725 if (retval(0).is_sparse_type ())
4726 {
4727 if (retval(0).type_name () == "sparse matrix")
4728 retval(0) = retval(0).matrix_value ();
4729 else if (retval(0).type_name () == "sparse complex matrix")
4730 retval(0) = retval(0).complex_matrix_value ();
4731 else if (retval(0).type_name () == "sparse bool matrix")
4732 retval(0) = retval(0).bool_matrix_value ();
4733 }
4734 4697
4735 return retval; 4698 return retval;
4736 } 4699 }
4737 4700
4738 /* 4701 /*