GNU Octave  6.2.0
A high-level interpreted language, primarily intended for numerical computations, mostly compatible with Matlab
lo-array-errwarn.cc
Go to the documentation of this file.
1 ////////////////////////////////////////////////////////////////////////
2 //
3 // Copyright (C) 2016-2021 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 <cinttypes>
31 #include <cmath>
32 
33 #include <sstream>
34 
35 #include "lo-array-errwarn.h"
36 #include "lo-error.h"
37 
38 namespace octave
39 {
40  // Text constants used to shorten code below.
41 
42  static const char *error_id_nonconformant_args
43  = "Octave:nonconformant-args";
44 
45  static const char *error_id_index_out_of_bounds
46  = "Octave:index-out-of-bounds";
47 
48  static const char *error_id_invalid_index = "Octave:invalid-index";
49 
51  = "Octave:nearly-singular-matrix";
52 
53  static const char *warning_id_singular_matrix = "Octave:singular-matrix";
54 
55  void
57  {
58  (*current_liboctave_error_handler)
59  ("invalid conversion from NaN to logical");
60  }
61 
62  void
64  {
65  (*current_liboctave_error_handler)
66  ("invalid conversion from NaN to character");
67  }
68 
69  void
70  err_nonconformant (const char *op,
71  octave_idx_type op1_len, octave_idx_type op2_len)
72  {
73  const char *err_id = error_id_nonconformant_args;
74 
75  (*current_liboctave_error_with_id_handler)
76  (err_id, "%s: nonconformant arguments (op1 len: %" OCTAVE_IDX_TYPE_FORMAT
77  ", op2 len: % " OCTAVE_IDX_TYPE_FORMAT ")",
78  op, op1_len, op2_len);
79  }
80 
81  void
82  err_nonconformant (const char *op,
83  octave_idx_type op1_nr, octave_idx_type op1_nc,
84  octave_idx_type op2_nr, octave_idx_type op2_nc)
85  {
86  const char *err_id = error_id_nonconformant_args;
87 
88  (*current_liboctave_error_with_id_handler)
89  (err_id, "%s: nonconformant arguments "
90  "(op1 is %" OCTAVE_IDX_TYPE_FORMAT "x%" OCTAVE_IDX_TYPE_FORMAT ", "
91  "op2 is %" OCTAVE_IDX_TYPE_FORMAT"x%" OCTAVE_IDX_TYPE_FORMAT ")",
92  op, op1_nr, op1_nc, op2_nr, op2_nc);
93  }
94 
95  void
96  err_nonconformant (const char *op,
97  const dim_vector& op1_dims, const dim_vector& op2_dims)
98  {
99  const char *err_id = error_id_nonconformant_args;
100 
101  std::string op1_dims_str = op1_dims.str ();
102  std::string op2_dims_str = op2_dims.str ();
103 
104  (*current_liboctave_error_with_id_handler)
105  (err_id, "%s: nonconformant arguments (op1 is %s, op2 is %s)",
106  op, op1_dims_str.c_str (), op2_dims_str.c_str ());
107  }
108 
109  void
111  octave_idx_type ext)
112  {
113  const char *err_id = error_id_index_out_of_bounds;
114 
115  (*current_liboctave_error_with_id_handler)
116  (err_id, "A(%s) = []: index out of bounds: value %" OCTAVE_IDX_TYPE_FORMAT
117  " out of bound %" OCTAVE_IDX_TYPE_FORMAT,
118  is1d ? "I" : "..,I,..", idx, ext);
119  }
120 
121  // Show the expression that caused the error, e.g., "A(-1,_)",
122  // "A(0+1i)", "A(_,3)". Show how many indices come before/after the
123  // offending one, e.g., (<error>), (<error>,_), or (_,<error>,...[x5]...)
124 
125  std::string
127  {
128  std::ostringstream buf;
129 
130  if (m_var.empty () || m_var == "<unknown>")
131  buf << "index ";
132  else
133  buf << m_var;
134 
135  bool show_parens = m_dim > 0;
136 
137  if (show_parens)
138  {
139  if (m_dim < 5)
140  {
141  buf << '(';
142 
143  for (octave_idx_type i = 1; i < m_dim; i++)
144  buf << "_,";
145  }
146  else
147  buf << "(...[x" << m_dim - 1 << "]...";
148  }
149 
150  buf << m_index;
151 
152  if (show_parens)
153  {
154  if (m_nd - m_dim < 5)
155  {
156  for (octave_idx_type i = 0; i < m_nd - m_dim; i++)
157  buf << ",_";
158 
159  if (m_nd >= m_dim)
160  buf << ')';
161  }
162  else
163  buf << "...[x" << m_nd - m_dim << "]...)";
164  }
165 
166  return buf.str ();
167  }
168 
170  {
171  public:
172 
173  invalid_index (const std::string& value, octave_idx_type ndim,
174  octave_idx_type dimen)
175  : index_exception (value, ndim, dimen)
176  {
177  // Virtual, but the one we want to call is defined in this class.
178  update_message ();
179  }
180 
181  void update_message (void)
182  {
183  static std::string exp
184  = std::to_string (std::numeric_limits<octave_idx_type>::digits);
185 
186  set_message (expression ()
187  + ": subscripts must be either integers 1 to (2^" + exp
188  + ")-1 or logicals");
189  }
190 
191  // ID of error to throw
192  const char * err_id (void) const
193  {
194  return error_id_invalid_index;
195  }
196  };
197 
198  // Complain if an index is negative, fractional, or too big.
199 
200  void
201  err_invalid_index (const std::string& idx, octave_idx_type nd,
202  octave_idx_type dim, const std::string&)
203  {
204  invalid_index e (idx, nd, dim);
205 
206  throw e;
207  }
208 
209  void
211  octave_idx_type dim, const std::string& var)
212  {
213  err_invalid_index (std::to_string (n + 1), nd, dim, var);
214  }
215 
216  void
218  const std::string& var)
219  {
220  std::ostringstream buf;
221  buf << n + 1;
222 
223  if (! std::isnan (n))
224  {
225  // if n not an integer, but would be printed as one, show diff
226  double nearest = std::floor (n + 1.5);
227  if (n + 1 != nearest && (buf.str ().find ('.') == std::string::npos))
228  buf << std::showpos << (n + 1 - nearest);
229  }
230 
231  err_invalid_index (buf.str (), nd, dim, var);
232  }
233 
234  // Complain for read access beyond the bounds of an array.
235 
237  {
238  public:
239 
240  out_of_range (const std::string& value, octave_idx_type nd,
242  const dim_vector& size)
243  : index_exception (value, nd, dim), m_size (size), m_extent (ext)
244  {
245  // Virtual, but the one we want to call is defined in this class.
246  update_message ();
247  }
248 
249  void update_message (void)
250  {
251  set_message (expression () + ": out of bound "
252  + std::to_string (m_extent)
253  + " (dimensions are " + m_size.str ('x') + ")");
254  }
255 
256  // ID of error to throw.
257  const char * err_id (void) const
258  {
260  }
261 
262  private:
263 
264  // Dimension of object being accessed.
266 
267  // Length of dimension being accessed.
269  };
270 
271  // Complain of an index that is out of range
272  void
274  octave_idx_type ext, const dim_vector& dv)
275  {
276  throw out_of_range (std::to_string (idx), nd, dim, ext, dv);
277  }
278 
279  void
281  {
282  (*current_liboctave_error_with_id_handler)
283  ("Octave:invalid-resize",
284  "Invalid resizing operation or ambiguous assignment to an out-of-bounds array element");
285  }
286 
287  void
288  warn_singular_matrix (double rcond)
289  {
290  if (rcond == 0.0)
291  {
292  (*current_liboctave_warning_with_id_handler)
294  "matrix singular to machine precision");
295  }
296  else
297  {
298  (*current_liboctave_warning_with_id_handler)
300  "matrix singular to machine precision, rcond = %g", rcond);
301  }
302  }
303 
304  // DEPRECATED in Octave 6.
305 
306  // Complain of an index that is out of range, but we don't know matrix size
307  void
309  octave_idx_type ext)
310  {
311  // The dim_vector setting here doesn't really make sense. However,
312  // this function has been deprecated and will be removed in version
313  // 8, so there's no need to attempt to fix it.
314 
315  throw out_of_range (std::to_string (idx), nd, dim, ext,
316  dim_vector (1, 1, 1, 1, 1, 1, 1));
317  }
318 }
319 
320 /* Tests in test/index.tst */
Vector representing the dimensions (size) of an Array.
Definition: dim-vector.h:95
std::string str(char sep='x') const
Definition: dim-vector.cc:85
std::string expression(void) const
const char * err_id(void) const
invalid_index(const std::string &value, octave_idx_type ndim, octave_idx_type dimen)
const char * err_id(void) const
out_of_range(const std::string &value, octave_idx_type nd, octave_idx_type dim, octave_idx_type ext, const dim_vector &size)
octave_idx_type m_extent
octave_idx_type n
Definition: mx-inlines.cc:753
bool isnan(bool)
Definition: lo-mappers.h:178
std::complex< T > floor(const std::complex< T > &x)
Definition: lo-mappers.h:130
static const char * error_id_index_out_of_bounds
void err_invalid_index(const std::string &idx, octave_idx_type nd, octave_idx_type dim, const std::string &)
void err_del_index_out_of_range(bool is1d, octave_idx_type idx, octave_idx_type ext)
void err_nan_to_logical_conversion(void)
void err_invalid_resize(void)
void err_index_out_of_range(int nd, int dim, octave_idx_type idx, octave_idx_type ext, const dim_vector &dv)
void warn_singular_matrix(double rcond)
static const char * error_id_nonconformant_args
static const char * warning_id_nearly_singular_matrix
static const char * warning_id_singular_matrix
void err_nan_to_character_conversion(void)
static const char * error_id_invalid_index
void err_nonconformant(const char *op, octave_idx_type op1_len, octave_idx_type op2_len)