GNU Octave  9.1.0
A high-level interpreted language, primarily intended for numerical computations, mostly compatible with Matlab
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
mgorth.cc
Go to the documentation of this file.
1 ////////////////////////////////////////////////////////////////////////
2 //
3 // Copyright (C) 2009-2024 The Octave Project Developers
4 //
5 // See the file COPYRIGHT.md in the top-level directory of this
6 // distribution or <https://octave.org/copyright/>.
7 //
8 // This file is part of Octave.
9 //
10 // Octave is free software: you can redistribute it and/or modify it
11 // under the terms of the GNU General Public License as published by
12 // the Free Software Foundation, either version 3 of the License, or
13 // (at your option) any later version.
14 //
15 // Octave is distributed in the hope that it will be useful, but
16 // WITHOUT ANY WARRANTY; without even the implied warranty of
17 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 // GNU General Public License for more details.
19 //
20 // You should have received a copy of the GNU General Public License
21 // along with Octave; see the file COPYING. If not, see
22 // <https://www.gnu.org/licenses/>.
23 //
24 ////////////////////////////////////////////////////////////////////////
25 
26 #if defined (HAVE_CONFIG_H)
27 # include "config.h"
28 #endif
29 
30 #include "oct-norm.h"
31 #include "defun.h"
32 #include "error.h"
33 #include "errwarn.h"
34 
36 
37 template <typename ColumnVector, typename Matrix, typename RowVector>
38 static void
39 do_mgorth (ColumnVector& x, const Matrix& V, RowVector& h)
40 {
41  octave_idx_type Vc = V.columns ();
42  h = RowVector (Vc + 1);
43  for (octave_idx_type j = 0; j < Vc; j++)
44  {
45  ColumnVector Vcj = V.column (j);
46  RowVector Vcjh = Vcj.hermitian ();
47  h(j) = Vcjh * x;
48  x -= h(j) * Vcj;
49  }
50 
51  h(Vc) = xnorm (x);
52  if (std::real (h(Vc)) > 0)
53  x /= h(Vc);
54 }
55 
56 DEFUN (mgorth, args, ,
57  doc: /* -*- texinfo -*-
58 @deftypefn {} {[@var{y}, @var{h}] =} mgorth (@var{x}, @var{v})
59 Orthogonalize a given column vector @var{x} with respect to a set of
60 orthonormal vectors comprising the columns of @var{v} using the modified
61 Gram-Schmidt method.
62 
63 On exit, @var{y} is a unit vector such that:
64 
65 @example
66 @group
67  norm (@var{y}) = 1
68  @var{v}' * @var{y} = 0
69  @var{x} = [@var{v}, @var{y}]*@var{h}'
70 @end group
71 @end example
72 
73 @end deftypefn */)
74 {
75  if (args.length () != 2)
76  print_usage ();
77 
78  octave_value arg_x = args(0);
79  octave_value arg_v = args(1);
80 
81  if (arg_v.ndims () != 2 || arg_x.ndims () != 2 || arg_x.columns () != 1
82  || arg_v.rows () != arg_x.rows ())
83  error ("mgorth: V should be a matrix, and X a column vector with"
84  " the same number of rows as V.");
85 
86  if (! arg_x.isnumeric () && ! arg_v.isnumeric ())
87  error ("mgorth: X and V must be numeric");
88 
89  octave_value_list retval;
90 
91  bool iscomplex = (arg_x.iscomplex () || arg_v.iscomplex ());
92  if (arg_x.is_single_type () || arg_v.is_single_type ())
93  {
94  if (iscomplex)
95  {
100  do_mgorth (x, V, h);
101  retval = ovl (x, h);
102  }
103  else
104  {
106  FloatMatrix V = arg_v.float_matrix_value ();
107  FloatRowVector h;
108  do_mgorth (x, V, h);
109  retval = ovl (x, h);
110  }
111  }
112  else
113  {
114  if (iscomplex)
115  {
119  do_mgorth (x, V, h);
120  retval = ovl (x, h);
121  }
122  else
123  {
125  Matrix V = arg_v.matrix_value ();
126  RowVector h;
127  do_mgorth (x, V, h);
128  retval = ovl (x, h);
129  }
130  }
131 
132  return retval;
133 }
134 
135 /*
136 %!test
137 %! for ii=1:100
138 %! assert (abs (mgorth (randn (5, 1), eye (5, 4))), [0 0 0 0 1]', eps);
139 %! endfor
140 
141 %!test
142 %! a = hilb (5);
143 %! a(:, 1) /= norm (a(:, 1));
144 %! for ii = 1:5
145 %! a(:, ii) = mgorth (a(:, ii), a(:, 1:ii-1));
146 %! endfor
147 %! assert (a' * a, eye (5), 1e10);
148 */
149 
150 OCTAVE_END_NAMESPACE(octave)
MArray< T > hermitian(T(*fcn)(const T &)=nullptr) const
Definition: MArray.h:102
Definition: dMatrix.h:42
int ndims() const
Definition: ov.h:551
octave_idx_type rows() const
Definition: ov.h:545
bool isnumeric() const
Definition: ov.h:750
ComplexMatrix complex_matrix_value(bool frc_str_conv=false) const
Definition: ov.h:871
bool is_single_type() const
Definition: ov.h:698
FloatColumnVector float_column_vector_value(bool frc_str_conv=false, bool frc_vec_conv=false) const
FloatComplexColumnVector float_complex_column_vector_value(bool frc_str_conv=false, bool frc_vec_conv=false) const
FloatMatrix float_matrix_value(bool frc_str_conv=false) const
Definition: ov.h:856
bool iscomplex() const
Definition: ov.h:741
ComplexColumnVector complex_column_vector_value(bool frc_str_conv=false, bool frc_vec_conv=false) const
ColumnVector column_vector_value(bool frc_str_conv=false, bool frc_vec_conv=false) const
octave_idx_type columns() const
Definition: ov.h:547
Matrix matrix_value(bool frc_str_conv=false) const
Definition: ov.h:853
FloatComplexMatrix float_complex_matrix_value(bool frc_str_conv=false) const
Definition: ov.h:875
ColumnVector real(const ComplexColumnVector &a)
Definition: dColVector.cc:137
OCTAVE_BEGIN_NAMESPACE(octave) static octave_value daspk_fcn
void print_usage(void)
Definition: defun-int.h:72
#define DEFUN(name, args_name, nargout_name, doc)
Macro to define a builtin function.
Definition: defun.h:56
void() error(const char *fmt,...)
Definition: error.cc:988
F77_RET_T const F77_INT const F77_INT const F77_INT const F77_DBLE const F77_DBLE F77_INT F77_DBLE * V
F77_RET_T const F77_DBLE * x
double xnorm(const ColumnVector &x, double p)
Definition: oct-norm.cc:610
octave_value_list ovl(const OV_Args &... args)
Construct an octave_value_list with less typing.
Definition: ovl.h:219