ov-scalar.cc

Go to the documentation of this file.
00001 /*
00002 
00003 Copyright (C) 1996-2012 John W. Eaton
00004 
00005 This file is part of Octave.
00006 
00007 Octave is free software; you can redistribute it and/or modify it
00008 under the terms of the GNU General Public License as published by the
00009 Free Software Foundation; either version 3 of the License, or (at your
00010 option) any later version.
00011 
00012 Octave is distributed in the hope that it will be useful, but WITHOUT
00013 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
00014 FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
00015 for more details.
00016 
00017 You should have received a copy of the GNU General Public License
00018 along with Octave; see the file COPYING.  If not, see
00019 <http://www.gnu.org/licenses/>.
00020 
00021 */
00022 
00023 #ifdef HAVE_CONFIG_H
00024 #include <config.h>
00025 #endif
00026 
00027 #include <iostream>
00028 
00029 #include "data-conv.h"
00030 #include "mach-info.h"
00031 #include "lo-specfun.h"
00032 #include "lo-mappers.h"
00033 
00034 #include "defun.h"
00035 #include "gripes.h"
00036 #include "oct-obj.h"
00037 #include "oct-stream.h"
00038 #include "ov-scalar.h"
00039 #include "ov-float.h"
00040 #include "ov-base.h"
00041 #include "ov-base-scalar.h"
00042 #include "ov-base-scalar.cc"
00043 #include "ov-re-mat.h"
00044 #include "ov-typeinfo.h"
00045 #include "pr-output.h"
00046 #include "xdiv.h"
00047 #include "xpow.h"
00048 #include "ops.h"
00049 
00050 #include "ls-oct-ascii.h"
00051 #include "ls-hdf5.h"
00052 
00053 template class octave_base_scalar<double>;
00054 
00055 DEFINE_OCTAVE_ALLOCATOR (octave_scalar);
00056 
00057 DEFINE_OV_TYPEID_FUNCTIONS_AND_DATA (octave_scalar, "scalar", "double");
00058 
00059 static octave_base_value *
00060 default_numeric_demotion_function (const octave_base_value& a)
00061 {
00062   CAST_CONV_ARG (const octave_scalar&);
00063 
00064   return new octave_float_scalar (v.float_value ());
00065 }
00066 
00067 octave_base_value::type_conv_info
00068 octave_scalar::numeric_demotion_function (void) const
00069 {
00070   return octave_base_value::type_conv_info(default_numeric_demotion_function,
00071                                            octave_float_scalar::static_type_id ());
00072 }
00073 
00074 octave_value
00075 octave_scalar::do_index_op (const octave_value_list& idx, bool resize_ok)
00076 {
00077   // FIXME -- this doesn't solve the problem of
00078   //
00079   //   a = 1; a([1,1], [1,1], [1,1])
00080   //
00081   // and similar constructions.  Hmm...
00082 
00083   // FIXME -- using this constructor avoids narrowing the
00084   // 1x1 matrix back to a scalar value.  Need a better solution
00085   // to this problem.
00086 
00087   octave_value tmp (new octave_matrix (matrix_value ()));
00088 
00089   return tmp.do_index_op (idx, resize_ok);
00090 }
00091 
00092 octave_value
00093 octave_scalar::resize (const dim_vector& dv, bool fill) const
00094 {
00095   if (fill)
00096     {
00097       NDArray retval (dv, NDArray::resize_fill_value());
00098 
00099       if (dv.numel ())
00100         retval(0) = scalar;
00101 
00102       return retval;
00103     }
00104   else
00105     {
00106       NDArray retval (dv);
00107 
00108       if (dv.numel ())
00109         retval(0) = scalar;
00110 
00111       return retval;
00112     }
00113 }
00114 
00115 octave_value
00116 octave_scalar::convert_to_str_internal (bool, bool, char type) const
00117 {
00118   octave_value retval;
00119 
00120   if (xisnan (scalar))
00121     gripe_nan_to_character_conversion ();
00122   else
00123     {
00124       int ival = NINT (scalar);
00125 
00126       if (ival < 0 || ival > UCHAR_MAX)
00127         {
00128           // FIXME -- is there something better we could do?
00129 
00130           ival = 0;
00131 
00132           ::warning ("range error for conversion to character value");
00133         }
00134 
00135       retval = octave_value (std::string (1, static_cast<char> (ival)), type);
00136     }
00137 
00138   return retval;
00139 }
00140 
00141 bool
00142 octave_scalar::save_ascii (std::ostream& os)
00143 {
00144   double d = double_value ();
00145 
00146   octave_write_double (os, d);
00147 
00148   os << "\n";
00149 
00150   return true;
00151 }
00152 
00153 bool
00154 octave_scalar::load_ascii (std::istream& is)
00155 {
00156   scalar = octave_read_value<double> (is);
00157   if (!is)
00158     {
00159       error ("load: failed to load scalar constant");
00160       return false;
00161     }
00162 
00163   return true;
00164 }
00165 
00166 bool
00167 octave_scalar::save_binary (std::ostream& os, bool& /* save_as_floats */)
00168 {
00169   char tmp = LS_DOUBLE;
00170   os.write (reinterpret_cast<char *> (&tmp), 1);
00171   double dtmp = double_value ();
00172   os.write (reinterpret_cast<char *> (&dtmp), 8);
00173 
00174   return true;
00175 }
00176 
00177 bool
00178 octave_scalar::load_binary (std::istream& is, bool swap,
00179                             oct_mach_info::float_format fmt)
00180 {
00181   char tmp;
00182   if (! is.read (reinterpret_cast<char *> (&tmp), 1))
00183     return false;
00184 
00185   double dtmp;
00186   read_doubles (is, &dtmp, static_cast<save_type> (tmp), 1, swap, fmt);
00187   if (error_state || ! is)
00188     return false;
00189 
00190   scalar = dtmp;
00191   return true;
00192 }
00193 
00194 #if defined (HAVE_HDF5)
00195 
00196 bool
00197 octave_scalar::save_hdf5 (hid_t loc_id, const char *name,
00198                           bool /* save_as_floats */)
00199 {
00200   hsize_t dimens[3];
00201   hid_t space_hid = -1, data_hid = -1;
00202   bool retval = true;
00203 
00204   space_hid = H5Screate_simple (0, dimens, 0);
00205   if (space_hid < 0) return false;
00206 
00207 #if HAVE_HDF5_18
00208   data_hid = H5Dcreate (loc_id, name, H5T_NATIVE_DOUBLE, space_hid,
00209                         H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT);
00210 #else
00211   data_hid = H5Dcreate (loc_id, name, H5T_NATIVE_DOUBLE, space_hid,
00212                         H5P_DEFAULT);
00213 #endif
00214   if (data_hid < 0)
00215     {
00216       H5Sclose (space_hid);
00217       return false;
00218     }
00219 
00220   double tmp = double_value ();
00221   retval = H5Dwrite (data_hid, H5T_NATIVE_DOUBLE, H5S_ALL, H5S_ALL,
00222                      H5P_DEFAULT, &tmp) >= 0;
00223 
00224   H5Dclose (data_hid);
00225   H5Sclose (space_hid);
00226 
00227   return retval;
00228 }
00229 
00230 bool
00231 octave_scalar::load_hdf5 (hid_t loc_id, const char *name)
00232 {
00233 #if HAVE_HDF5_18
00234   hid_t data_hid = H5Dopen (loc_id, name, H5P_DEFAULT);
00235 #else
00236   hid_t data_hid = H5Dopen (loc_id, name);
00237 #endif
00238   hid_t space_id = H5Dget_space (data_hid);
00239 
00240   hsize_t rank = H5Sget_simple_extent_ndims (space_id);
00241 
00242   if (rank != 0)
00243     {
00244       H5Dclose (data_hid);
00245       return false;
00246     }
00247 
00248   double dtmp;
00249   if (H5Dread (data_hid, H5T_NATIVE_DOUBLE, H5S_ALL, H5S_ALL,
00250                H5P_DEFAULT, &dtmp) < 0)
00251     {
00252       H5Dclose (data_hid);
00253       return false;
00254     }
00255 
00256   scalar = dtmp;
00257 
00258   H5Dclose (data_hid);
00259 
00260   return true;
00261 }
00262 
00263 #endif
00264 
00265 mxArray *
00266 octave_scalar::as_mxArray (void) const
00267 {
00268   mxArray *retval = new mxArray (mxDOUBLE_CLASS, 1, 1, mxREAL);
00269 
00270   double *pr = static_cast<double *> (retval->get_data ());
00271 
00272   pr[0] = scalar;
00273 
00274   return retval;
00275 }
00276 
00277 octave_value
00278 octave_scalar::map (unary_mapper_t umap) const
00279 {
00280   switch (umap)
00281     {
00282     case umap_imag:
00283       return 0.0;
00284 
00285     case umap_real:
00286     case umap_conj:
00287       return scalar;
00288 
00289 #define SCALAR_MAPPER(UMAP, FCN) \
00290     case umap_ ## UMAP: \
00291       return octave_value (FCN (scalar))
00292 
00293       SCALAR_MAPPER (abs, ::fabs);
00294       SCALAR_MAPPER (acos, rc_acos);
00295       SCALAR_MAPPER (acosh, rc_acosh);
00296       SCALAR_MAPPER (angle, ::arg);
00297       SCALAR_MAPPER (arg, ::arg);
00298       SCALAR_MAPPER (asin, rc_asin);
00299       SCALAR_MAPPER (asinh, ::asinh);
00300       SCALAR_MAPPER (atan, ::atan);
00301       SCALAR_MAPPER (atanh, rc_atanh);
00302       SCALAR_MAPPER (erf, ::erf);
00303       SCALAR_MAPPER (erfinv, ::erfinv);
00304       SCALAR_MAPPER (erfc, ::erfc);
00305       SCALAR_MAPPER (erfcx, ::erfcx);
00306       SCALAR_MAPPER (gamma, xgamma);
00307       SCALAR_MAPPER (lgamma, rc_lgamma);
00308       SCALAR_MAPPER (cbrt, ::cbrt);
00309       SCALAR_MAPPER (ceil, ::ceil);
00310       SCALAR_MAPPER (cos, ::cos);
00311       SCALAR_MAPPER (cosh, ::cosh);
00312       SCALAR_MAPPER (exp, ::exp);
00313       SCALAR_MAPPER (expm1, ::expm1);
00314       SCALAR_MAPPER (fix, ::fix);
00315       SCALAR_MAPPER (floor, gnulib::floor);
00316       SCALAR_MAPPER (log, rc_log);
00317       SCALAR_MAPPER (log2, rc_log2);
00318       SCALAR_MAPPER (log10, rc_log10);
00319       SCALAR_MAPPER (log1p, rc_log1p);
00320       SCALAR_MAPPER (round, xround);
00321       SCALAR_MAPPER (roundb, xroundb);
00322       SCALAR_MAPPER (signum, ::signum);
00323       SCALAR_MAPPER (sin, ::sin);
00324       SCALAR_MAPPER (sinh, ::sinh);
00325       SCALAR_MAPPER (sqrt, rc_sqrt);
00326       SCALAR_MAPPER (tan, ::tan);
00327       SCALAR_MAPPER (tanh, ::tanh);
00328       SCALAR_MAPPER (finite, xfinite);
00329       SCALAR_MAPPER (isinf, xisinf);
00330       SCALAR_MAPPER (isna, octave_is_NA);
00331       SCALAR_MAPPER (isnan, xisnan);
00332 
00333     default:
00334       if (umap >= umap_xisalnum && umap <= umap_xtoupper)
00335         {
00336           octave_value str_conv = convert_to_str (true, true);
00337           return error_state ? octave_value () : str_conv.map (umap);
00338         }
00339       else
00340         return octave_base_value::map (umap);
00341     }
00342 }
00343 
00344 bool
00345 octave_scalar::fast_elem_insert_self (void *where, builtin_type_t btyp) const
00346 {
00347 
00348   // Support inline real->complex conversion.
00349   if (btyp == btyp_double)
00350     {
00351       *(reinterpret_cast<double *>(where)) = scalar;
00352       return true;
00353     }
00354   else if (btyp == btyp_complex)
00355     {
00356       *(reinterpret_cast<Complex *>(where)) = scalar;
00357       return true;
00358     }
00359   else
00360     return false;
00361 }
 All Classes Files Functions Variables Typedefs Enumerations Enumerator Friends Defines