ov-re-diag.cc

Go to the documentation of this file.
00001 /*
00002 
00003 Copyright (C) 2008-2012 Jaroslav Hajek
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 "byte-swap.h"
00028 
00029 #include "ov-re-diag.h"
00030 #include "ov-flt-re-diag.h"
00031 #include "ov-base-diag.cc"
00032 #include "ov-scalar.h"
00033 #include "ov-re-mat.h"
00034 #include "ls-utils.h"
00035 
00036 template class octave_base_diag<DiagMatrix, Matrix>;
00037 
00038 DEFINE_OCTAVE_ALLOCATOR (octave_diag_matrix);
00039 
00040 DEFINE_OV_TYPEID_FUNCTIONS_AND_DATA (octave_diag_matrix, "diagonal matrix", "double");
00041 
00042 static octave_base_value *
00043 default_numeric_conversion_function (const octave_base_value& a)
00044 {
00045   CAST_CONV_ARG (const octave_diag_matrix&);
00046 
00047   return new octave_matrix (v.matrix_value ());
00048 }
00049 
00050 octave_base_value::type_conv_info
00051 octave_diag_matrix::numeric_conversion_function (void) const
00052 {
00053   return octave_base_value::type_conv_info (default_numeric_conversion_function,
00054                                             octave_matrix::static_type_id ());
00055 }
00056 
00057 static octave_base_value *
00058 default_numeric_demotion_function (const octave_base_value& a)
00059 {
00060   CAST_CONV_ARG (const octave_diag_matrix&);
00061 
00062   return new octave_float_diag_matrix (v.float_diag_matrix_value ());
00063 }
00064 
00065 octave_base_value::type_conv_info
00066 octave_diag_matrix::numeric_demotion_function (void) const
00067 {
00068   return octave_base_value::type_conv_info (default_numeric_demotion_function,
00069                                             octave_float_diag_matrix::static_type_id ());
00070 }
00071 
00072 octave_base_value *
00073 octave_diag_matrix::try_narrowing_conversion (void)
00074 {
00075   octave_base_value *retval = 0;
00076 
00077   if (matrix.nelem () == 1)
00078     retval = new octave_scalar (matrix (0, 0));
00079 
00080   return retval;
00081 }
00082 
00083 octave_value
00084 octave_diag_matrix::do_index_op (const octave_value_list& idx,
00085                                  bool resize_ok)
00086 {
00087   octave_value retval;
00088 
00089   // This hack is to allow constructing permutation matrices using
00090   // eye(n)(p,:), eye(n)(:,q) && eye(n)(p,q) where p & q are permutation
00091   // vectors.
00092   if (! resize_ok && idx.length () == 2 && matrix.is_multiple_of_identity (1))
00093     {
00094       idx_vector idx0 = idx(0).index_vector ();
00095       idx_vector idx1 = idx(1).index_vector ();
00096 
00097       if (! error_state)
00098         {
00099           bool left = idx0.is_permutation (matrix.rows ());
00100           bool right = idx1.is_permutation (matrix.cols ());
00101 
00102           if (left && right)
00103             {
00104               if (idx0.is_colon ()) left = false;
00105               if (idx1.is_colon ()) right = false;
00106               if (left && right)
00107                 retval = PermMatrix (idx0, false) * PermMatrix (idx1, true);
00108               else if (left)
00109                 retval = PermMatrix (idx0, false);
00110               else if (right)
00111                 retval = PermMatrix (idx1, true);
00112               else
00113                 {
00114                   retval = this;
00115                   this->count++;
00116                 }
00117             }
00118         }
00119     }
00120 
00121   // if error_state is set, we've already griped.
00122   if (! error_state && retval.is_undefined ())
00123     retval = octave_base_diag<DiagMatrix, Matrix>::do_index_op (idx, resize_ok);
00124 
00125   return retval;
00126 }
00127 
00128 DiagMatrix
00129 octave_diag_matrix::diag_matrix_value (bool) const
00130 {
00131   return matrix;
00132 }
00133 
00134 FloatDiagMatrix
00135 octave_diag_matrix::float_diag_matrix_value (bool) const
00136 {
00137   return FloatDiagMatrix (matrix);
00138 }
00139 
00140 ComplexDiagMatrix
00141 octave_diag_matrix::complex_diag_matrix_value (bool) const
00142 {
00143   return ComplexDiagMatrix (matrix);
00144 }
00145 
00146 FloatComplexDiagMatrix
00147 octave_diag_matrix::float_complex_diag_matrix_value (bool) const
00148 {
00149   return FloatComplexDiagMatrix (matrix);
00150 }
00151 
00152 octave_value
00153 octave_diag_matrix::map (unary_mapper_t umap) const
00154 {
00155   switch (umap)
00156     {
00157     case umap_abs:
00158       return matrix.abs ();
00159     case umap_real:
00160     case umap_conj:
00161       return matrix;
00162     case umap_imag:
00163       return DiagMatrix (matrix.rows (), matrix.cols (), 0.0);
00164     case umap_sqrt:
00165       {
00166         ComplexColumnVector tmp = matrix.diag ().map<Complex> (rc_sqrt);
00167         ComplexDiagMatrix retval (tmp);
00168         retval.resize (matrix.rows (), matrix.columns ());
00169         return retval;
00170       }
00171     default:
00172       return to_dense ().map (umap);
00173     }
00174 }
00175 
00176 bool
00177 octave_diag_matrix::save_binary (std::ostream& os, bool& save_as_floats)
00178 {
00179 
00180   int32_t r = matrix.rows (), c = matrix.cols ();
00181   os.write (reinterpret_cast<char *> (&r), 4);
00182   os.write (reinterpret_cast<char *> (&c), 4);
00183 
00184   Matrix m = Matrix (matrix.diag ());
00185   save_type st = LS_DOUBLE;
00186   if (save_as_floats)
00187     {
00188       if (m.too_large_for_float ())
00189         {
00190           warning ("save: some values too large to save as floats --");
00191           warning ("save: saving as doubles instead");
00192         }
00193       else
00194         st = LS_FLOAT;
00195     }
00196   else if (matrix.length () > 8192) // FIXME -- make this configurable.
00197     {
00198       double max_val, min_val;
00199       if (m.all_integers (max_val, min_val))
00200         st = get_save_type (max_val, min_val);
00201     }
00202 
00203   const double *mtmp = m.data ();
00204   write_doubles (os, mtmp, st, m.numel ());
00205 
00206   return true;
00207 }
00208 
00209 bool
00210 octave_diag_matrix::load_binary (std::istream& is, bool swap,
00211                                  oct_mach_info::float_format fmt)
00212 {
00213   int32_t r, c;
00214   char tmp;
00215   if (! (is.read (reinterpret_cast<char *> (&r), 4)
00216          && is.read (reinterpret_cast<char *> (&c), 4)
00217          && is.read (reinterpret_cast<char *> (&tmp), 1)))
00218     return false;
00219   if (swap)
00220     {
00221       swap_bytes<4> (&r);
00222       swap_bytes<4> (&c);
00223     }
00224 
00225   DiagMatrix m (r, c);
00226   double *re = m.fortran_vec ();
00227   octave_idx_type len = m.length ();
00228   read_doubles (is, re, static_cast<save_type> (tmp), len, swap, fmt);
00229   if (error_state || ! is)
00230     return false;
00231   matrix = m;
00232 
00233   return true;
00234 }
00235 
00236 bool
00237 octave_diag_matrix::chk_valid_scalar (const octave_value& val,
00238                                       double& x) const
00239 {
00240   bool retval = val.is_real_scalar ();
00241   if (retval)
00242     x = val.double_value ();
00243   return retval;
00244 }
 All Classes Files Functions Variables Typedefs Enumerations Enumerator Friends Defines