GNU Octave  3.8.0
A high-level interpreted language, primarily intended for numerical computations, mostly compatible with Matlab
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Pages
ov-scalar.cc
Go to the documentation of this file.
1 /*
2 
3 Copyright (C) 1996-2013 John W. Eaton
4 
5 This file is part of Octave.
6 
7 Octave is free software; you can redistribute it and/or modify it
8 under the terms of the GNU General Public License as published by the
9 Free Software Foundation; either version 3 of the License, or (at your
10 option) any later version.
11 
12 Octave is distributed in the hope that it will be useful, but WITHOUT
13 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
14 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
15 for more details.
16 
17 You should have received a copy of the GNU General Public License
18 along with Octave; see the file COPYING. If not, see
19 <http://www.gnu.org/licenses/>.
20 
21 */
22 
23 #ifdef HAVE_CONFIG_H
24 #include <config.h>
25 #endif
26 
27 #include <iostream>
28 
29 #include "data-conv.h"
30 #include "mach-info.h"
31 #include "lo-specfun.h"
32 #include "lo-mappers.h"
33 
34 #include "defun.h"
35 #include "gripes.h"
36 #include "mxarray.h"
37 #include "oct-obj.h"
38 #include "oct-stream.h"
39 #include "ov-scalar.h"
40 #include "ov-float.h"
41 #include "ov-base.h"
42 #include "ov-base-scalar.h"
43 #include "ov-base-scalar.cc"
44 #include "ov-re-mat.h"
45 #include "ov-typeinfo.h"
46 #include "pr-output.h"
47 #include "xdiv.h"
48 #include "xpow.h"
49 #include "ops.h"
50 
51 #include "ls-oct-ascii.h"
52 #include "ls-hdf5.h"
53 
54 template class octave_base_scalar<double>;
55 
57 
59 
60 static octave_base_value *
62 {
64 
65  return new octave_float_scalar (v.float_value ());
66 }
67 
70 {
74 }
75 
77 octave_scalar::do_index_op (const octave_value_list& idx, bool resize_ok)
78 {
79  // FIXME: this doesn't solve the problem of
80  //
81  // a = 1; a([1,1], [1,1], [1,1])
82  //
83  // and similar constructions. Hmm...
84 
85  // FIXME: using this constructor avoids narrowing the
86  // 1x1 matrix back to a scalar value. Need a better solution
87  // to this problem.
88 
90 
91  return tmp.do_index_op (idx, resize_ok);
92 }
93 
95 octave_scalar::resize (const dim_vector& dv, bool fill) const
96 {
97  if (fill)
98  {
99  NDArray retval (dv, 0);
100 
101  if (dv.numel ())
102  retval(0) = scalar;
103 
104  return retval;
105  }
106  else
107  {
108  NDArray retval (dv);
109 
110  if (dv.numel ())
111  retval(0) = scalar;
112 
113  return retval;
114  }
115 }
116 
119 {
120  return DiagMatrix (Array<double> (dim_vector (1, 1), scalar), m, n);
121 }
122 
125 {
126  octave_value retval;
127 
128  if (xisnan (scalar))
130  else
131  {
132  int ival = NINT (scalar);
133 
134  if (ival < 0 || ival > std::numeric_limits<unsigned char>::max ())
135  {
136  // FIXME: is there something better we could do?
137 
138  ival = 0;
139 
140  ::warning ("range error for conversion to character value");
141  }
142 
143  retval = octave_value (std::string (1, static_cast<char> (ival)), type);
144  }
145 
146  return retval;
147 }
148 
149 bool
150 octave_scalar::save_ascii (std::ostream& os)
151 {
152  double d = double_value ();
153 
154  octave_write_double (os, d);
155 
156  os << "\n";
157 
158  return true;
159 }
160 
161 bool
162 octave_scalar::load_ascii (std::istream& is)
163 {
164  scalar = octave_read_value<double> (is);
165  if (!is)
166  {
167  error ("load: failed to load scalar constant");
168  return false;
169  }
170 
171  return true;
172 }
173 
174 bool
175 octave_scalar::save_binary (std::ostream& os, bool& /* save_as_floats */)
176 {
177  char tmp = LS_DOUBLE;
178  os.write (reinterpret_cast<char *> (&tmp), 1);
179  double dtmp = double_value ();
180  os.write (reinterpret_cast<char *> (&dtmp), 8);
181 
182  return true;
183 }
184 
185 bool
186 octave_scalar::load_binary (std::istream& is, bool swap,
188 {
189  char tmp;
190  if (! is.read (reinterpret_cast<char *> (&tmp), 1))
191  return false;
192 
193  double dtmp;
194  read_doubles (is, &dtmp, static_cast<save_type> (tmp), 1, swap, fmt);
195  if (error_state || ! is)
196  return false;
197 
198  scalar = dtmp;
199  return true;
200 }
201 
202 #if defined (HAVE_HDF5)
203 
204 bool
205 octave_scalar::save_hdf5 (hid_t loc_id, const char *name,
206  bool /* save_as_floats */)
207 {
208  hsize_t dimens[3];
209  hid_t space_hid = -1, data_hid = -1;
210  bool retval = true;
211 
212  space_hid = H5Screate_simple (0, dimens, 0);
213  if (space_hid < 0) return false;
214 
215 #if HAVE_HDF5_18
216  data_hid = H5Dcreate (loc_id, name, H5T_NATIVE_DOUBLE, space_hid,
217  H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT);
218 #else
219  data_hid = H5Dcreate (loc_id, name, H5T_NATIVE_DOUBLE, space_hid,
220  H5P_DEFAULT);
221 #endif
222  if (data_hid < 0)
223  {
224  H5Sclose (space_hid);
225  return false;
226  }
227 
228  double tmp = double_value ();
229  retval = H5Dwrite (data_hid, H5T_NATIVE_DOUBLE, H5S_ALL, H5S_ALL,
230  H5P_DEFAULT, &tmp) >= 0;
231 
232  H5Dclose (data_hid);
233  H5Sclose (space_hid);
234 
235  return retval;
236 }
237 
238 bool
239 octave_scalar::load_hdf5 (hid_t loc_id, const char *name)
240 {
241 #if HAVE_HDF5_18
242  hid_t data_hid = H5Dopen (loc_id, name, H5P_DEFAULT);
243 #else
244  hid_t data_hid = H5Dopen (loc_id, name);
245 #endif
246  hid_t space_id = H5Dget_space (data_hid);
247 
248  hsize_t rank = H5Sget_simple_extent_ndims (space_id);
249 
250  if (rank != 0)
251  {
252  H5Dclose (data_hid);
253  return false;
254  }
255 
256  double dtmp;
257  if (H5Dread (data_hid, H5T_NATIVE_DOUBLE, H5S_ALL, H5S_ALL,
258  H5P_DEFAULT, &dtmp) < 0)
259  {
260  H5Dclose (data_hid);
261  return false;
262  }
263 
264  scalar = dtmp;
265 
266  H5Dclose (data_hid);
267 
268  return true;
269 }
270 
271 #endif
272 
273 mxArray *
275 {
276  mxArray *retval = new mxArray (mxDOUBLE_CLASS, 1, 1, mxREAL);
277 
278  double *pr = static_cast<double *> (retval->get_data ());
279 
280  pr[0] = scalar;
281 
282  return retval;
283 }
284 
287 {
288  switch (umap)
289  {
290  case umap_imag:
291  return 0.0;
292 
293  case umap_real:
294  case umap_conj:
295  return scalar;
296 
297 #define SCALAR_MAPPER(UMAP, FCN) \
298  case umap_ ## UMAP: \
299  return octave_value (FCN (scalar))
300 
301  SCALAR_MAPPER (abs, ::fabs);
304  SCALAR_MAPPER (angle, ::arg);
305  SCALAR_MAPPER (arg, ::arg);
308  SCALAR_MAPPER (atan, ::atan);
310  SCALAR_MAPPER (erf, ::erf);
313  SCALAR_MAPPER (erfc, ::erfc);
315  SCALAR_MAPPER (erfi, ::erfi);
318  SCALAR_MAPPER (lgamma, rc_lgamma);
319  SCALAR_MAPPER (cbrt, ::cbrt);
320  SCALAR_MAPPER (ceil, ::ceil);
321  SCALAR_MAPPER (cos, ::cos);
322  SCALAR_MAPPER (cosh, ::cosh);
323  SCALAR_MAPPER (exp, ::exp);
325  SCALAR_MAPPER (fix, ::fix);
327  SCALAR_MAPPER (log, rc_log);
328  SCALAR_MAPPER (log2, rc_log2);
329  SCALAR_MAPPER (log10, rc_log10);
331  SCALAR_MAPPER (round, xround);
332  SCALAR_MAPPER (roundb, xroundb);
334  SCALAR_MAPPER (sin, ::sin);
335  SCALAR_MAPPER (sinh, ::sinh);
336  SCALAR_MAPPER (sqrt, rc_sqrt);
337  SCALAR_MAPPER (tan, ::tan);
338  SCALAR_MAPPER (tanh, ::tanh);
339  SCALAR_MAPPER (finite, xfinite);
340  SCALAR_MAPPER (isinf, xisinf);
341  SCALAR_MAPPER (isna, octave_is_NA);
342  SCALAR_MAPPER (isnan, xisnan);
344 
345  default:
346  if (umap >= umap_xisalnum && umap <= umap_xtoupper)
347  {
348  octave_value str_conv = convert_to_str (true, true);
349  return error_state ? octave_value () : str_conv.map (umap);
350  }
351  else
352  return octave_base_value::map (umap);
353  }
354 }
355 
356 bool
358 {
359 
360  // Support inline real->complex conversion.
361  if (btyp == btyp_double)
362  {
363  *(reinterpret_cast<double *>(where)) = scalar;
364  return true;
365  }
366  else if (btyp == btyp_complex)
367  {
368  *(reinterpret_cast<Complex *>(where)) = scalar;
369  return true;
370  }
371  else
372  return false;
373 }