Mercurial > octave-nkf
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 /* |