GNU Octave 7.1.0
A high-level interpreted language, primarily intended for numerical computations, mostly compatible with Matlab
sylvester.cc
Go to the documentation of this file.
1////////////////////////////////////////////////////////////////////////
2//
3// Copyright (C) 1996-2022 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 "defun.h"
31#include "error.h"
32#include "errwarn.h"
33#include "ovl.h"
34
35OCTAVE_NAMESPACE_BEGIN
36
37DEFUN (sylvester, args, ,
38 doc: /* -*- texinfo -*-
39@deftypefn {} {@var{X} =} sylvester (@var{A}, @var{B}, @var{C})
40Solve the Sylvester equation.
41
42The Sylvester equation is defined as:
43@tex
44$$
45 A X + X B = C
46$$
47@end tex
48@ifnottex
49
50@example
51A X + X B = C
52@end example
53
54@end ifnottex
55The solution is computed using standard @sc{lapack} subroutines.
56
57For example:
58
59@example
60@group
61sylvester ([1, 2; 3, 4], [5, 6; 7, 8], [9, 10; 11, 12])
62 @result{} [ 0.50000, 0.66667; 0.66667, 0.50000 ]
63@end group
64@end example
65@end deftypefn */)
66{
67 if (args.length () != 3)
68 print_usage ();
69
70 octave_value retval;
71
72 octave_value arg_a = args(0);
73 octave_value arg_b = args(1);
74 octave_value arg_c = args(2);
75
76 octave_idx_type a_nr = arg_a.rows ();
77 octave_idx_type a_nc = arg_a.columns ();
78
79 octave_idx_type b_nr = arg_b.rows ();
80 octave_idx_type b_nc = arg_b.columns ();
81
82 octave_idx_type c_nr = arg_c.rows ();
83 octave_idx_type c_nc = arg_c.columns ();
84
85 bool isfloat = arg_a.is_single_type ()
86 || arg_b.is_single_type ()
87 || arg_c.is_single_type ();
88
89 if (arg_a.isempty () || arg_b.isempty () || arg_c.isempty ())
90 {
91 if (isfloat)
92 return ovl (FloatMatrix ());
93 else
94 return ovl (Matrix ());
95 }
96
97 // Arguments are not empty, so check for correct dimensions.
98
99 if (a_nr != a_nc)
100 err_square_matrix_required ("sylvester", "A");
101 if (b_nr != b_nc)
102 err_square_matrix_required ("sylvester", "B");
103 if (a_nr != c_nr || b_nr != c_nc)
105
106 if (isfloat)
107 {
108 if (arg_a.iscomplex ()
109 || arg_b.iscomplex ()
110 || arg_c.iscomplex ())
111 {
112 // Do everything in complex arithmetic;
113
117
118 retval = Sylvester (ca, cb, cc);
119 }
120 else
121 {
122 // Do everything in real arithmetic.
123
124 FloatMatrix ca = arg_a.float_matrix_value ();
125 FloatMatrix cb = arg_b.float_matrix_value ();
126 FloatMatrix cc = arg_c.float_matrix_value ();
127
128 retval = Sylvester (ca, cb, cc);
129 }
130 }
131 else
132 {
133 if (arg_a.iscomplex ()
134 || arg_b.iscomplex ()
135 || arg_c.iscomplex ())
136 {
137 // Do everything in complex arithmetic;
138
142
143 retval = Sylvester (ca, cb, cc);
144 }
145 else
146 {
147 // Do everything in real arithmetic.
148
149 Matrix ca = arg_a.matrix_value ();
150 Matrix cb = arg_b.matrix_value ();
151 Matrix cc = arg_c.matrix_value ();
152
153 retval = Sylvester (ca, cb, cc);
154 }
155 }
156
157 return retval;
158}
159
160/*
161%!assert (sylvester ([1, 2; 3, 4], [5, 6; 7, 8], [9, 10; 11, 12]), [1/2, 2/3; 2/3, 1/2], sqrt (eps))
162%!assert (sylvester (single ([1, 2; 3, 4]), single ([5, 6; 7, 8]), single ([9, 10; 11, 12])), single ([1/2, 2/3; 2/3, 1/2]), sqrt (eps ("single")))
163
164## Test input validation
165%!error sylvester ()
166%!error sylvester (1)
167%!error sylvester (1,2)
168%!error sylvester (1, 2, 3, 4)
169%!error <A must be a square matrix> sylvester (ones (2,3), ones (2,2), ones (2,2))
170%!error <B must be a square matrix> sylvester (ones (2,2), ones (2,3), ones (2,2))
171%!error <nonconformant matrices> sylvester (ones (2,2), ones (2,2), ones (3,3))
172*/
173
174OCTAVE_NAMESPACE_END
ComplexMatrix Sylvester(const ComplexMatrix &a, const ComplexMatrix &b, const ComplexMatrix &c)
Definition: CMatrix.cc:3243
Definition: dMatrix.h:42
ComplexMatrix complex_matrix_value(bool frc_str_conv=false) const
Definition: ov.h:916
octave_idx_type rows(void) const
Definition: ov.h:590
octave_idx_type columns(void) const
Definition: ov.h:592
FloatMatrix float_matrix_value(bool frc_str_conv=false) const
Definition: ov.h:901
bool isempty(void) const
Definition: ov.h:646
bool is_single_type(void) const
Definition: ov.h:743
Matrix matrix_value(bool frc_str_conv=false) const
Definition: ov.h:898
FloatComplexMatrix float_complex_matrix_value(bool frc_str_conv=false) const
Definition: ov.h:920
bool iscomplex(void) const
Definition: ov.h:786
OCTINTERP_API 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 err_square_matrix_required(const char *fcn, const char *name)
Definition: errwarn.cc:122
void err_nonconformant(const char *op, octave_idx_type op1_len, octave_idx_type op2_len)
octave_value_list ovl(const OV_Args &... args)
Construct an octave_value_list with less typing.
Definition: ovl.h:211