ov-flt-re-mat.cc

Go to the documentation of this file.
00001 /*
00002 
00003 Copyright (C) 1996-2012 John W. Eaton
00004 Copyright (C) 2009-2010 VZLU Prague
00005 
00006 This file is part of Octave.
00007 
00008 Octave is free software; you can redistribute it and/or modify it
00009 under the terms of the GNU General Public License as published by the
00010 Free Software Foundation; either version 3 of the License, or (at your
00011 option) any later version.
00012 
00013 Octave is distributed in the hope that it will be useful, but WITHOUT
00014 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
00015 FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
00016 for more details.
00017 
00018 You should have received a copy of the GNU General Public License
00019 along with Octave; see the file COPYING.  If not, see
00020 <http://www.gnu.org/licenses/>.
00021 
00022 */
00023 
00024 #ifdef HAVE_CONFIG_H
00025 #include <config.h>
00026 #endif
00027 
00028 #include <climits>
00029 
00030 #include <iostream>
00031 #include <vector>
00032 
00033 #include "data-conv.h"
00034 #include "lo-ieee.h"
00035 #include "lo-utils.h"
00036 #include "lo-specfun.h"
00037 #include "lo-mappers.h"
00038 #include "mach-info.h"
00039 #include "mx-base.h"
00040 #include "quit.h"
00041 #include "oct-locbuf.h"
00042 
00043 #include "defun.h"
00044 #include "gripes.h"
00045 #include "oct-obj.h"
00046 #include "oct-lvalue.h"
00047 #include "oct-stream.h"
00048 #include "ops.h"
00049 #include "ov-base.h"
00050 #include "ov-base-mat.h"
00051 #include "ov-base-mat.cc"
00052 #include "ov-scalar.h"
00053 #include "ov-float.h"
00054 #include "ov-flt-complex.h"
00055 #include "ov-re-mat.h"
00056 #include "ov-flt-re-mat.h"
00057 #include "ov-flt-cx-mat.h"
00058 #include "ov-re-sparse.h"
00059 #include "ov-flt-re-diag.h"
00060 #include "ov-flt-cx-diag.h"
00061 #include "ov-type-conv.h"
00062 #include "pr-output.h"
00063 #include "variables.h"
00064 #include "ops.h"
00065 
00066 #include "byte-swap.h"
00067 #include "ls-oct-ascii.h"
00068 #include "ls-utils.h"
00069 #include "ls-hdf5.h"
00070 
00071 #if ! defined (UCHAR_MAX)
00072 #define UCHAR_MAX 255
00073 #endif
00074 
00075 template class octave_base_matrix<FloatNDArray>;
00076 
00077 DEFINE_OCTAVE_ALLOCATOR (octave_float_matrix);
00078 
00079 DEFINE_OV_TYPEID_FUNCTIONS_AND_DATA (octave_float_matrix, "float matrix", "single");
00080 
00081 octave_base_value *
00082 octave_float_matrix::try_narrowing_conversion (void)
00083 {
00084   octave_base_value *retval = 0;
00085 
00086   if (matrix.nelem () == 1)
00087     retval = new octave_float_scalar (matrix (0));
00088 
00089   return retval;
00090 }
00091 
00092 double
00093 octave_float_matrix::double_value (bool) const
00094 {
00095   double retval = lo_ieee_nan_value ();
00096 
00097   if (numel () > 0)
00098     {
00099       gripe_implicit_conversion ("Octave:array-as-scalar",
00100                                  "real matrix", "real scalar");
00101 
00102       retval = matrix (0, 0);
00103     }
00104   else
00105     gripe_invalid_conversion ("real matrix", "real scalar");
00106 
00107   return retval;
00108 }
00109 
00110 float
00111 octave_float_matrix::float_value (bool) const
00112 {
00113   float retval = lo_ieee_float_nan_value ();
00114 
00115   if (numel () > 0)
00116     {
00117       gripe_implicit_conversion ("Octave:array-as-scalar",
00118                                  "real matrix", "real scalar");
00119 
00120       retval = matrix (0, 0);
00121     }
00122   else
00123     gripe_invalid_conversion ("real matrix", "real scalar");
00124 
00125   return retval;
00126 }
00127 
00128 // FIXME
00129 
00130 Matrix
00131 octave_float_matrix::matrix_value (bool) const
00132 {
00133   return Matrix (matrix.matrix_value ());
00134 }
00135 
00136 FloatMatrix
00137 octave_float_matrix::float_matrix_value (bool) const
00138 {
00139   return matrix.matrix_value ();
00140 }
00141 
00142 Complex
00143 octave_float_matrix::complex_value (bool) const
00144 {
00145   double tmp = lo_ieee_nan_value ();
00146 
00147   Complex retval (tmp, tmp);
00148 
00149   if (rows () > 0 && columns () > 0)
00150     {
00151       gripe_implicit_conversion ("Octave:array-as-scalar",
00152                                  "real matrix", "complex scalar");
00153 
00154       retval = matrix (0, 0);
00155     }
00156   else
00157     gripe_invalid_conversion ("real matrix", "complex scalar");
00158 
00159   return retval;
00160 }
00161 
00162 FloatComplex
00163 octave_float_matrix::float_complex_value (bool) const
00164 {
00165   double tmp = lo_ieee_float_nan_value ();
00166 
00167   FloatComplex retval (tmp, tmp);
00168 
00169   if (rows () > 0 && columns () > 0)
00170     {
00171       gripe_implicit_conversion ("Octave:array-as-scalar",
00172                                  "real matrix", "complex scalar");
00173 
00174       retval = matrix (0, 0);
00175     }
00176   else
00177     gripe_invalid_conversion ("real matrix", "complex scalar");
00178 
00179   return retval;
00180 }
00181 
00182 // FIXME
00183 
00184 ComplexMatrix
00185 octave_float_matrix::complex_matrix_value (bool) const
00186 {
00187   return ComplexMatrix (matrix.matrix_value ());
00188 }
00189 
00190 FloatComplexMatrix
00191 octave_float_matrix::float_complex_matrix_value (bool) const
00192 {
00193   return FloatComplexMatrix (matrix.matrix_value ());
00194 }
00195 
00196 ComplexNDArray
00197 octave_float_matrix::complex_array_value (bool) const
00198 {
00199   return ComplexNDArray (matrix);
00200 }
00201 
00202 FloatComplexNDArray
00203 octave_float_matrix::float_complex_array_value (bool) const
00204 {
00205   return FloatComplexNDArray (matrix);
00206 }
00207 
00208 NDArray
00209 octave_float_matrix::array_value (bool) const
00210 {
00211   return NDArray (matrix);
00212 }
00213 
00214 boolNDArray
00215 octave_float_matrix::bool_array_value (bool warn) const
00216 {
00217   if (matrix.any_element_is_nan ())
00218     gripe_nan_to_logical_conversion ();
00219   else if (warn && matrix.any_element_not_one_or_zero ())
00220     gripe_logical_conversion ();
00221 
00222   return boolNDArray (matrix);
00223 }
00224 
00225 charNDArray
00226 octave_float_matrix::char_array_value (bool) const
00227 {
00228   charNDArray retval (dims ());
00229 
00230   octave_idx_type nel = numel ();
00231 
00232   for (octave_idx_type i = 0; i < nel; i++)
00233     retval.elem (i) = static_cast<char>(matrix.elem (i));
00234 
00235   return retval;
00236 }
00237 
00238 SparseMatrix
00239 octave_float_matrix::sparse_matrix_value (bool) const
00240 {
00241   return SparseMatrix (matrix_value ());
00242 }
00243 
00244 SparseComplexMatrix
00245 octave_float_matrix::sparse_complex_matrix_value (bool) const
00246 {
00247   // FIXME Need a SparseComplexMatrix (Matrix) constructor to make
00248   // this function more efficient. Then this should become
00249   // return SparseComplexMatrix (matrix.matrix_value ());
00250   return SparseComplexMatrix (sparse_matrix_value ());
00251 }
00252 
00253 octave_value
00254 octave_float_matrix::diag (octave_idx_type k) const
00255 {
00256   octave_value retval;
00257   if (k == 0 && matrix.ndims () == 2
00258       && (matrix.rows () == 1 || matrix.columns () == 1))
00259     retval = FloatDiagMatrix (DiagArray2<float> (matrix));
00260   else
00261     retval = octave_base_matrix<FloatNDArray>::diag (k);
00262 
00263   return retval;
00264 }
00265 
00266 octave_value
00267 octave_float_matrix::convert_to_str_internal (bool, bool, char type) const
00268 {
00269   octave_value retval;
00270   dim_vector dv = dims ();
00271   octave_idx_type nel = dv.numel ();
00272 
00273   charNDArray chm (dv);
00274 
00275   bool warned = false;
00276 
00277   for (octave_idx_type i = 0; i < nel; i++)
00278     {
00279       octave_quit ();
00280 
00281       float d = matrix (i);
00282 
00283       if (xisnan (d))
00284         {
00285           gripe_nan_to_character_conversion ();
00286           return retval;
00287         }
00288       else
00289         {
00290           int ival = NINT (d);
00291 
00292           if (ival < 0 || ival > UCHAR_MAX)
00293             {
00294               // FIXME -- is there something
00295               // better we could do?
00296 
00297               ival = 0;
00298 
00299               if (! warned)
00300                 {
00301                   ::warning ("range error for conversion to character value");
00302                   warned = true;
00303                 }
00304             }
00305 
00306           chm (i) = static_cast<char> (ival);
00307         }
00308     }
00309 
00310   retval = octave_value (chm, type);
00311 
00312   return retval;
00313 }
00314 
00315 bool
00316 octave_float_matrix::save_ascii (std::ostream& os)
00317 {
00318   dim_vector d = dims ();
00319 
00320   if (d.length () > 2)
00321     {
00322       FloatNDArray tmp = float_array_value ();
00323 
00324       os << "# ndims: " << d.length () << "\n";
00325 
00326       for (int i=0; i < d.length (); i++)
00327         os << " " << d (i);
00328 
00329       os << "\n" << tmp;
00330     }
00331   else
00332     {
00333       // Keep this case, rather than use generic code above for backward
00334       // compatiability. Makes load_ascii much more complex!!
00335       os << "# rows: " << rows () << "\n"
00336          << "# columns: " << columns () << "\n";
00337 
00338       os << float_matrix_value ();
00339     }
00340 
00341   return true;
00342 }
00343 
00344 bool
00345 octave_float_matrix::load_ascii (std::istream& is)
00346 {
00347   bool success = true;
00348 
00349   string_vector keywords(2);
00350 
00351   keywords[0] = "ndims";
00352   keywords[1] = "rows";
00353 
00354   std::string kw;
00355   octave_idx_type val = 0;
00356 
00357   if (extract_keyword (is, keywords, kw, val, true))
00358     {
00359       if (kw == "ndims")
00360         {
00361           int mdims = static_cast<int> (val);
00362 
00363           if (mdims >= 0)
00364             {
00365               dim_vector dv;
00366               dv.resize (mdims);
00367 
00368               for (int i = 0; i < mdims; i++)
00369                 is >> dv(i);
00370 
00371               if (is)
00372                 {
00373                   FloatNDArray tmp(dv);
00374 
00375                   is >> tmp;
00376 
00377                   if (is)
00378                     matrix = tmp;
00379                   else
00380                     {
00381                       error ("load: failed to load matrix constant");
00382                       success = false;
00383                     }
00384                 }
00385               else
00386                 {
00387                   error ("load: failed to read dimensions");
00388                   success = false;
00389                 }
00390             }
00391           else
00392             {
00393               error ("load: failed to extract number of dimensions");
00394               success = false;
00395             }
00396         }
00397       else if (kw == "rows")
00398         {
00399           octave_idx_type nr = val;
00400           octave_idx_type nc = 0;
00401 
00402           if (nr >= 0 && extract_keyword (is, "columns", nc) && nc >= 0)
00403             {
00404               if (nr > 0 && nc > 0)
00405                 {
00406                   FloatMatrix tmp (nr, nc);
00407                   is >> tmp;
00408                   if (is)
00409                     matrix = tmp;
00410                   else
00411                     {
00412                       error ("load: failed to load matrix constant");
00413                       success = false;
00414                     }
00415                 }
00416               else if (nr == 0 || nc == 0)
00417                 matrix = FloatMatrix (nr, nc);
00418               else
00419                 panic_impossible ();
00420             }
00421           else
00422             {
00423               error ("load: failed to extract number of rows and columns");
00424               success = false;
00425             }
00426         }
00427       else
00428         panic_impossible ();
00429     }
00430   else
00431     {
00432       error ("load: failed to extract number of rows and columns");
00433       success = false;
00434     }
00435 
00436   return success;
00437 }
00438 
00439 bool
00440 octave_float_matrix::save_binary (std::ostream& os, bool&)
00441 {
00442 
00443   dim_vector d = dims ();
00444   if (d.length() < 1)
00445     return false;
00446 
00447   // Use negative value for ndims to differentiate with old format!!
00448   int32_t tmp = - d.length();
00449   os.write (reinterpret_cast<char *> (&tmp), 4);
00450   for (int i = 0; i < d.length (); i++)
00451     {
00452       tmp = d(i);
00453       os.write (reinterpret_cast<char *> (&tmp), 4);
00454     }
00455 
00456   FloatNDArray m = float_array_value ();
00457   save_type st = LS_FLOAT;
00458   if (d.numel () > 8192) // FIXME -- make this configurable.
00459     {
00460       float max_val, min_val;
00461       if (m.all_integers (max_val, min_val))
00462         st = get_save_type (max_val, min_val);
00463     }
00464 
00465   const float *mtmp = m.data ();
00466   write_floats (os, mtmp, st, d.numel ());
00467 
00468   return true;
00469 }
00470 
00471 bool
00472 octave_float_matrix::load_binary (std::istream& is, bool swap,
00473                                  oct_mach_info::float_format fmt)
00474 {
00475   char tmp;
00476   int32_t mdims;
00477   if (! is.read (reinterpret_cast<char *> (&mdims), 4))
00478     return false;
00479   if (swap)
00480     swap_bytes<4> (&mdims);
00481   if (mdims < 0)
00482     {
00483       mdims = - mdims;
00484       int32_t di;
00485       dim_vector dv;
00486       dv.resize (mdims);
00487 
00488       for (int i = 0; i < mdims; i++)
00489         {
00490           if (! is.read (reinterpret_cast<char *> (&di), 4))
00491             return false;
00492           if (swap)
00493             swap_bytes<4> (&di);
00494           dv(i) = di;
00495         }
00496 
00497       // Convert an array with a single dimension to be a row vector.
00498       // Octave should never write files like this, other software
00499       // might.
00500 
00501       if (mdims == 1)
00502         {
00503           mdims = 2;
00504           dv.resize (mdims);
00505           dv(1) = dv(0);
00506           dv(0) = 1;
00507         }
00508 
00509       if (! is.read (reinterpret_cast<char *> (&tmp), 1))
00510         return false;
00511 
00512       FloatNDArray m(dv);
00513       float *re = m.fortran_vec ();
00514       read_floats (is, re, static_cast<save_type> (tmp), dv.numel (), swap, fmt);
00515       if (error_state || ! is)
00516         return false;
00517       matrix = m;
00518     }
00519   else
00520     {
00521       int32_t nr, nc;
00522       nr = mdims;
00523       if (! is.read (reinterpret_cast<char *> (&nc), 4))
00524         return false;
00525       if (swap)
00526         swap_bytes<4> (&nc);
00527       if (! is.read (reinterpret_cast<char *> (&tmp), 1))
00528         return false;
00529       FloatMatrix m (nr, nc);
00530       float *re = m.fortran_vec ();
00531       octave_idx_type len = nr * nc;
00532       read_floats (is, re, static_cast<save_type> (tmp), len, swap, fmt);
00533       if (error_state || ! is)
00534         return false;
00535       matrix = m;
00536     }
00537   return true;
00538 }
00539 
00540 #if defined (HAVE_HDF5)
00541 
00542 bool
00543 octave_float_matrix::save_hdf5 (hid_t loc_id, const char *name, bool)
00544 {
00545   dim_vector dv = dims ();
00546   int empty = save_hdf5_empty (loc_id, name, dv);
00547   if (empty)
00548     return (empty > 0);
00549 
00550   int rank = dv.length ();
00551   hid_t space_hid = -1, data_hid = -1;
00552   bool retval = true;
00553   FloatNDArray m = array_value ();
00554 
00555   OCTAVE_LOCAL_BUFFER (hsize_t, hdims, rank);
00556 
00557   // Octave uses column-major, while HDF5 uses row-major ordering
00558   for (int i = 0; i < rank; i++)
00559     hdims[i] = dv (rank-i-1);
00560 
00561   space_hid = H5Screate_simple (rank, hdims, 0);
00562 
00563   if (space_hid < 0) return false;
00564 
00565   hid_t save_type_hid = H5T_NATIVE_FLOAT;
00566 
00567 #if HAVE_HDF5_INT2FLOAT_CONVERSIONS
00568   // hdf5 currently doesn't support float/integer conversions
00569   else
00570     {
00571       float max_val, min_val;
00572 
00573       if (m.all_integers (max_val, min_val))
00574         save_type_hid
00575           = save_type_to_hdf5 (get_save_type (max_val, min_val));
00576     }
00577 #endif /* HAVE_HDF5_INT2FLOAT_CONVERSIONS */
00578 #if HAVE_HDF5_18
00579   data_hid = H5Dcreate (loc_id, name, save_type_hid, space_hid,
00580                         H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT);
00581 #else
00582   data_hid = H5Dcreate (loc_id, name, save_type_hid, space_hid,
00583                         H5P_DEFAULT);
00584 #endif
00585   if (data_hid < 0)
00586     {
00587       H5Sclose (space_hid);
00588       return false;
00589     }
00590 
00591   float *mtmp = m.fortran_vec ();
00592   retval = H5Dwrite (data_hid, H5T_NATIVE_FLOAT, H5S_ALL, H5S_ALL,
00593                      H5P_DEFAULT, mtmp) >= 0;
00594 
00595   H5Dclose (data_hid);
00596   H5Sclose (space_hid);
00597 
00598   return retval;
00599 }
00600 
00601 bool
00602 octave_float_matrix::load_hdf5 (hid_t loc_id, const char *name)
00603 {
00604   bool retval = false;
00605 
00606   dim_vector dv;
00607   int empty = load_hdf5_empty (loc_id, name, dv);
00608   if (empty > 0)
00609     matrix.resize(dv);
00610   if (empty)
00611       return (empty > 0);
00612 
00613 #if HAVE_HDF5_18
00614   hid_t data_hid = H5Dopen (loc_id, name, H5P_DEFAULT);
00615 #else
00616   hid_t data_hid = H5Dopen (loc_id, name);
00617 #endif
00618   hid_t space_id = H5Dget_space (data_hid);
00619 
00620   hsize_t rank = H5Sget_simple_extent_ndims (space_id);
00621 
00622   if (rank < 1)
00623     {
00624       H5Sclose (space_id);
00625       H5Dclose (data_hid);
00626       return false;
00627     }
00628 
00629   OCTAVE_LOCAL_BUFFER (hsize_t, hdims, rank);
00630   OCTAVE_LOCAL_BUFFER (hsize_t, maxdims, rank);
00631 
00632   H5Sget_simple_extent_dims (space_id, hdims, maxdims);
00633 
00634   // Octave uses column-major, while HDF5 uses row-major ordering
00635   if (rank == 1)
00636     {
00637       dv.resize (2);
00638       dv(0) = 1;
00639       dv(1) = hdims[0];
00640     }
00641   else
00642     {
00643       dv.resize (rank);
00644       for (hsize_t i = 0, j = rank - 1; i < rank; i++, j--)
00645         dv(j) = hdims[i];
00646     }
00647 
00648   FloatNDArray m (dv);
00649   float *re = m.fortran_vec ();
00650   if (H5Dread (data_hid, H5T_NATIVE_FLOAT, H5S_ALL, H5S_ALL,
00651                H5P_DEFAULT, re) >= 0)
00652     {
00653       retval = true;
00654       matrix = m;
00655     }
00656 
00657   H5Sclose (space_id);
00658   H5Dclose (data_hid);
00659 
00660   return retval;
00661 }
00662 
00663 #endif
00664 
00665 void
00666 octave_float_matrix::print_raw (std::ostream& os,
00667                           bool pr_as_read_syntax) const
00668 {
00669   octave_print_internal (os, matrix, pr_as_read_syntax,
00670                          current_print_indent_level ());
00671 }
00672 
00673 mxArray *
00674 octave_float_matrix::as_mxArray (void) const
00675 {
00676   mxArray *retval = new mxArray (mxSINGLE_CLASS, dims (), mxREAL);
00677 
00678   float *pr = static_cast<float *> (retval->get_data ());
00679 
00680   mwSize nel = numel ();
00681 
00682   const float *p = matrix.data ();
00683 
00684   for (mwIndex i = 0; i < nel; i++)
00685     pr[i] = p[i];
00686 
00687   return retval;
00688 }
00689 
00690 // This uses a smarter strategy for doing the complex->real mappers.  We
00691 // allocate an array for a real result and keep filling it until a complex
00692 // result is produced.
00693 static octave_value
00694 do_rc_map (const FloatNDArray& a, FloatComplex (&fcn) (float))
00695 {
00696   octave_idx_type n = a.numel ();
00697   NoAlias<FloatNDArray> rr (a.dims ());
00698 
00699   for (octave_idx_type i = 0; i < n; i++)
00700     {
00701       octave_quit ();
00702 
00703       FloatComplex tmp = fcn (a(i));
00704       if (tmp.imag () == 0.0)
00705         rr(i) = tmp.real ();
00706       else
00707         {
00708           NoAlias<FloatComplexNDArray> rc (a.dims ());
00709 
00710           for (octave_idx_type j = 0; j < i; j++)
00711             rc(j) = rr(j);
00712 
00713           rc(i) = tmp;
00714 
00715           for (octave_idx_type j = i+1; j < n; j++)
00716             {
00717               octave_quit ();
00718 
00719               rc(j) = fcn (a(j));
00720             }
00721 
00722           return new octave_float_complex_matrix (rc);
00723         }
00724     }
00725 
00726   return rr;
00727 }
00728 
00729 octave_value
00730 octave_float_matrix::map (unary_mapper_t umap) const
00731 {
00732   switch (umap)
00733     {
00734     case umap_imag:
00735       return FloatNDArray (matrix.dims (), 0.0);
00736 
00737     case umap_real:
00738     case umap_conj:
00739       return matrix;
00740 
00741     // Mappers handled specially.
00742 #define ARRAY_METHOD_MAPPER(UMAP, FCN) \
00743     case umap_ ## UMAP: \
00744       return octave_value (matrix.FCN ())
00745 
00746       ARRAY_METHOD_MAPPER (abs, abs);
00747       ARRAY_METHOD_MAPPER (isnan, isnan);
00748       ARRAY_METHOD_MAPPER (isinf, isinf);
00749       ARRAY_METHOD_MAPPER (finite, isfinite);
00750 
00751 #define ARRAY_MAPPER(UMAP, TYPE, FCN) \
00752     case umap_ ## UMAP: \
00753       return octave_value (matrix.map<TYPE> (FCN))
00754 
00755 #define RC_ARRAY_MAPPER(UMAP, TYPE, FCN) \
00756     case umap_ ## UMAP: \
00757       return do_rc_map (matrix, FCN)
00758 
00759       RC_ARRAY_MAPPER (acos, FloatComplex, rc_acos);
00760       RC_ARRAY_MAPPER (acosh, FloatComplex, rc_acosh);
00761       ARRAY_MAPPER (angle, float, ::arg);
00762       ARRAY_MAPPER (arg, float, ::arg);
00763       RC_ARRAY_MAPPER (asin, FloatComplex, rc_asin);
00764       ARRAY_MAPPER (asinh, float, ::asinhf);
00765       ARRAY_MAPPER (atan, float, ::atanf);
00766       RC_ARRAY_MAPPER (atanh, FloatComplex, rc_atanh);
00767       ARRAY_MAPPER (erf, float, ::erff);
00768       ARRAY_MAPPER (erfinv, float, ::erfinv);
00769       ARRAY_MAPPER (erfc, float, ::erfcf);
00770       ARRAY_MAPPER (erfcx, float, ::erfcx);
00771       ARRAY_MAPPER (gamma, float, xgamma);
00772       RC_ARRAY_MAPPER (lgamma, FloatComplex, rc_lgamma);
00773       ARRAY_MAPPER (cbrt, float, ::cbrtf);
00774       ARRAY_MAPPER (ceil, float, ::ceilf);
00775       ARRAY_MAPPER (cos, float, ::cosf);
00776       ARRAY_MAPPER (cosh, float, ::coshf);
00777       ARRAY_MAPPER (exp, float, ::expf);
00778       ARRAY_MAPPER (expm1, float, ::expm1f);
00779       ARRAY_MAPPER (fix, float, ::fix);
00780       ARRAY_MAPPER (floor, float, ::floorf);
00781       RC_ARRAY_MAPPER (log, FloatComplex, rc_log);
00782       RC_ARRAY_MAPPER (log2, FloatComplex, rc_log2);
00783       RC_ARRAY_MAPPER (log10, FloatComplex, rc_log10);
00784       RC_ARRAY_MAPPER (log1p, FloatComplex, rc_log1p);
00785       ARRAY_MAPPER (round, float, xround);
00786       ARRAY_MAPPER (roundb, float, xroundb);
00787       ARRAY_MAPPER (signum, float, ::signum);
00788       ARRAY_MAPPER (sin, float, ::sinf);
00789       ARRAY_MAPPER (sinh, float, ::sinhf);
00790       RC_ARRAY_MAPPER (sqrt, FloatComplex, rc_sqrt);
00791       ARRAY_MAPPER (tan, float, ::tanf);
00792       ARRAY_MAPPER (tanh, float, ::tanhf);
00793       ARRAY_MAPPER (isna, bool, octave_is_NA);
00794 
00795     default:
00796       return octave_base_value::map (umap);
00797     }
00798 }
00799 
00800 DEFUN (single, args, ,
00801   "-*- texinfo -*-\n\
00802 @deftypefn {Built-in Function} {} single (@var{x})\n\
00803 Convert @var{x} to single precision type.\n\
00804 @seealso{double}\n\
00805 @end deftypefn")
00806 {
00807   // The OCTAVE_TYPE_CONV_BODY3 macro declares retval, so they go
00808   // inside their own scopes, and we don't declare retval here to
00809   // avoid a shadowed declaration warning.
00810 
00811   if (args.length () == 1)
00812     {
00813       if (args(0).is_diag_matrix ())
00814         {
00815           if (args(0).is_complex_type ())
00816             {
00817               OCTAVE_TYPE_CONV_BODY3 (single, octave_float_complex_diag_matrix, octave_float_complex);
00818             }
00819           else
00820             {
00821               OCTAVE_TYPE_CONV_BODY3 (single, octave_float_diag_matrix, octave_float_scalar);
00822             }
00823         }
00824       else if (args(0).is_sparse_type ())
00825         {
00826           error ("single: sparse type does not support single precision");
00827         }
00828       else if (args(0).is_complex_type ())
00829         {
00830           OCTAVE_TYPE_CONV_BODY3 (single, octave_float_complex_matrix, octave_float_complex);
00831         }
00832       else
00833         {
00834           OCTAVE_TYPE_CONV_BODY3 (single, octave_float_matrix, octave_float_scalar);
00835         }
00836     }
00837   else
00838     print_usage ();
00839 
00840   return octave_value ();
00841 }
00842 
00843 /*
00844 
00845 %!assert (class (single(1)), "single")
00846 %!assert (class (single(1 + i)), "single")
00847 %!assert (class (single (int8 (1))), "single")
00848 %!assert (class (single (uint8 (1))), "single")
00849 %!assert (class (single (int16 (1))), "single")
00850 %!assert (class (single (uint16 (1))), "single")
00851 %!assert (class (single (int32 (1))), "single")
00852 %!assert (class (single (uint32 (1))), "single")
00853 %!assert (class (single (int64 (1))), "single")
00854 %!assert (class (single (uint64 (1))), "single")
00855 %!assert (class (single (true)), "single")
00856 %!assert (class (single ("A")), "single")
00857 %!error (single (sparse (1)))
00858 %!test
00859 %! x = diag ([1 3 2]);
00860 %! y = single (x);
00861 %! assert (class (x), "double");
00862 %! assert (class (y), "single");
00863 %!test
00864 %! x = diag ([i 3 2]);
00865 %! y = single (x);
00866 %! assert (class (x), "double");
00867 %! assert (class (y), "single");
00868 
00869 */
00870 
 All Classes Files Functions Variables Typedefs Enumerations Enumerator Friends Defines