00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023 #ifdef HAVE_CONFIG_H
00024 #include <config.h>
00025 #endif
00026
00027 #include "byte-swap.h"
00028
00029 #include "ov-perm.h"
00030 #include "ov-re-mat.h"
00031 #include "ov-scalar.h"
00032 #include "error.h"
00033 #include "gripes.h"
00034 #include "ops.h"
00035 #include "pr-output.h"
00036
00037 #include "ls-oct-ascii.h"
00038
00039 octave_value
00040 octave_perm_matrix::subsref (const std::string& type,
00041 const std::list<octave_value_list>& idx)
00042 {
00043 octave_value retval;
00044
00045 switch (type[0])
00046 {
00047 case '(':
00048 retval = do_index_op (idx.front ());
00049 break;
00050
00051 case '{':
00052 case '.':
00053 {
00054 std::string nm = type_name ();
00055 error ("%s cannot be indexed with %c", nm.c_str (), type[0]);
00056 }
00057 break;
00058
00059 default:
00060 panic_impossible ();
00061 }
00062
00063 return retval.next_subsref (type, idx);
00064 }
00065
00066 octave_value
00067 octave_perm_matrix::do_index_op (const octave_value_list& idx,
00068 bool resize_ok)
00069 {
00070 octave_value retval;
00071 octave_idx_type nidx = idx.length ();
00072 idx_vector idx0, idx1;
00073 if (nidx == 2)
00074 {
00075 idx0 = idx(0).index_vector ();
00076 idx1 = idx(1).index_vector ();
00077 }
00078
00079
00080
00081
00082
00083
00084 if (! error_state && nidx == 2)
00085 {
00086 bool left = idx0.is_permutation (matrix.rows ());
00087 bool right = idx1.is_permutation (matrix.cols ());
00088
00089 if (left && right)
00090 {
00091 if (idx0.is_colon ()) left = false;
00092 if (idx1.is_colon ()) right = false;
00093 if (left || right)
00094 {
00095 PermMatrix p = matrix;
00096 if (left)
00097 p = PermMatrix (idx0, false) * p;
00098 if (right)
00099 p = p * PermMatrix (idx1, true);
00100 retval = p;
00101 }
00102 else
00103 {
00104 retval = this;
00105 this->count++;
00106 }
00107 }
00108 }
00109
00110
00111 if (! error_state && ! retval.is_defined ())
00112 {
00113 if (nidx == 2 && ! resize_ok &&
00114 idx0.is_scalar () && idx1.is_scalar ())
00115 {
00116 retval = matrix.checkelem (idx0(0), idx1(0));
00117 }
00118 else
00119 retval = to_dense ().do_index_op (idx, resize_ok);
00120 }
00121
00122 return retval;
00123 }
00124
00125 bool
00126 octave_perm_matrix::is_true (void) const
00127 {
00128 return to_dense ().is_true ();
00129 }
00130
00131 double
00132 octave_perm_matrix::double_value (bool) const
00133 {
00134 double retval = lo_ieee_nan_value ();
00135
00136 if (numel () > 0)
00137 {
00138 gripe_implicit_conversion ("Octave:array-as-scalar",
00139 type_name (), "real scalar");
00140
00141 retval = matrix (0, 0);
00142 }
00143 else
00144 gripe_invalid_conversion (type_name (), "real scalar");
00145
00146 return retval;
00147 }
00148
00149 float
00150 octave_perm_matrix::float_value (bool) const
00151 {
00152 float retval = lo_ieee_float_nan_value ();
00153
00154 if (numel () > 0)
00155 {
00156 gripe_implicit_conversion ("Octave:array-as-scalar",
00157 type_name (), "real scalar");
00158
00159 retval = matrix (0, 0);
00160 }
00161 else
00162 gripe_invalid_conversion (type_name (), "real scalar");
00163
00164 return retval;
00165 }
00166
00167 Complex
00168 octave_perm_matrix::complex_value (bool) const
00169 {
00170 double tmp = lo_ieee_nan_value ();
00171
00172 Complex retval (tmp, tmp);
00173
00174 if (rows () > 0 && columns () > 0)
00175 {
00176 gripe_implicit_conversion ("Octave:array-as-scalar",
00177 type_name (), "complex scalar");
00178
00179 retval = matrix (0, 0);
00180 }
00181 else
00182 gripe_invalid_conversion (type_name (), "complex scalar");
00183
00184 return retval;
00185 }
00186
00187 FloatComplex
00188 octave_perm_matrix::float_complex_value (bool) const
00189 {
00190 float tmp = lo_ieee_float_nan_value ();
00191
00192 FloatComplex retval (tmp, tmp);
00193
00194 if (rows () > 0 && columns () > 0)
00195 {
00196 gripe_implicit_conversion ("Octave:array-as-scalar",
00197 type_name (), "complex scalar");
00198
00199 retval = matrix (0, 0);
00200 }
00201 else
00202 gripe_invalid_conversion (type_name (), "complex scalar");
00203
00204 return retval;
00205 }
00206
00207 #define FORWARD_MATRIX_VALUE(TYPE, PREFIX) \
00208 TYPE \
00209 octave_perm_matrix::PREFIX ## _value (bool frc_str_conv) const \
00210 { \
00211 return to_dense ().PREFIX ## _value (frc_str_conv); \
00212 }
00213
00214 SparseMatrix
00215 octave_perm_matrix::sparse_matrix_value (bool) const
00216 {
00217 return SparseMatrix (matrix);
00218 }
00219
00220 SparseBoolMatrix
00221 octave_perm_matrix::sparse_bool_matrix_value (bool) const
00222 {
00223 return SparseBoolMatrix (matrix);
00224 }
00225
00226 SparseComplexMatrix
00227 octave_perm_matrix::sparse_complex_matrix_value (bool) const
00228 {
00229 return SparseComplexMatrix (sparse_matrix_value ());
00230 }
00231
00232 FORWARD_MATRIX_VALUE (Matrix, matrix)
00233 FORWARD_MATRIX_VALUE (FloatMatrix, float_matrix)
00234 FORWARD_MATRIX_VALUE (ComplexMatrix, complex_matrix)
00235 FORWARD_MATRIX_VALUE (FloatComplexMatrix, float_complex_matrix)
00236
00237 FORWARD_MATRIX_VALUE (NDArray, array)
00238 FORWARD_MATRIX_VALUE (FloatNDArray, float_array)
00239 FORWARD_MATRIX_VALUE (ComplexNDArray, complex_array)
00240 FORWARD_MATRIX_VALUE (FloatComplexNDArray, float_complex_array)
00241
00242 FORWARD_MATRIX_VALUE (boolNDArray, bool_array)
00243 FORWARD_MATRIX_VALUE (charNDArray, char_array)
00244
00245 idx_vector
00246 octave_perm_matrix::index_vector (void) const
00247 {
00248 return to_dense ().index_vector ();
00249 }
00250
00251 octave_value
00252 octave_perm_matrix::convert_to_str_internal (bool pad, bool force, char type) const
00253 {
00254 return to_dense ().convert_to_str_internal (pad, force, type);
00255 }
00256
00257 bool
00258 octave_perm_matrix::save_ascii (std::ostream& os)
00259 {
00260 typedef octave_int<octave_idx_type> idx_int_type;
00261
00262 os << "# size: " << matrix.rows () << "\n";
00263 os << "# orient: " << (matrix.is_col_perm () ? 'c' : 'r') << '\n';
00264
00265 Array<octave_idx_type> pvec = matrix.pvec ();
00266 octave_idx_type n = pvec.length ();
00267 ColumnVector tmp (n);
00268 for (octave_idx_type i = 0; i < n; i++) tmp(i) = pvec(i) + 1;
00269 os << tmp;
00270
00271 return true;
00272 }
00273
00274 bool
00275 octave_perm_matrix::load_ascii (std::istream& is)
00276 {
00277 typedef octave_int<octave_idx_type> idx_int_type;
00278 octave_idx_type n;
00279 bool success = true;
00280 char orient;
00281
00282 if (extract_keyword (is, "size", n, true)
00283 && extract_keyword (is, "orient", orient, true))
00284 {
00285 bool colp = orient == 'c';
00286 ColumnVector tmp (n);
00287 is >> tmp;
00288 if (!is)
00289 {
00290 error ("load: failed to load permutation matrix constant");
00291 success = false;
00292 }
00293 else
00294 {
00295 Array<octave_idx_type> pvec (dim_vector (n, 1));
00296 for (octave_idx_type i = 0; i < n; i++) pvec(i) = tmp(i) - 1;
00297 matrix = PermMatrix (pvec, colp);
00298
00299
00300 dense_cache = octave_value ();
00301 }
00302 }
00303 else
00304 {
00305 error ("load: failed to extract size & orientation");
00306 success = false;
00307 }
00308
00309 return success;
00310 }
00311
00312 bool
00313 octave_perm_matrix::save_binary (std::ostream& os, bool&)
00314 {
00315
00316 int32_t sz = matrix.rows ();
00317 bool colp = matrix.is_col_perm ();
00318 os.write (reinterpret_cast<char *> (&sz), 4);
00319 os.write (reinterpret_cast<char *> (&colp), 1);
00320 os.write (reinterpret_cast<const char *> (matrix.data ()), matrix.byte_size ());
00321
00322 return true;
00323 }
00324
00325 bool
00326 octave_perm_matrix::load_binary (std::istream& is, bool swap,
00327 oct_mach_info::float_format )
00328 {
00329 int32_t sz;
00330 bool colp;
00331 if (! (is.read (reinterpret_cast<char *> (&sz), 4)
00332 && is.read (reinterpret_cast<char *> (&colp), 1)))
00333 return false;
00334
00335 MArray<octave_idx_type> m (dim_vector (sz, 1));
00336
00337 if (! is.read (reinterpret_cast<char *> (m.fortran_vec ()), m.byte_size ()))
00338 return false;
00339
00340 if (swap)
00341 {
00342 int nel = m.numel ();
00343 for (int i = 0; i < nel; i++)
00344 switch (sizeof (octave_idx_type))
00345 {
00346 case 8:
00347 swap_bytes<8> (&m(i));
00348 break;
00349 case 4:
00350 swap_bytes<4> (&m(i));
00351 break;
00352 case 2:
00353 swap_bytes<2> (&m(i));
00354 break;
00355 case 1:
00356 default:
00357 break;
00358 }
00359 }
00360
00361 matrix = PermMatrix (m, colp);
00362 return true;
00363 }
00364
00365 void
00366 octave_perm_matrix::print_raw (std::ostream& os,
00367 bool pr_as_read_syntax) const
00368 {
00369 return octave_print_internal (os, matrix, pr_as_read_syntax,
00370 current_print_indent_level ());
00371 }
00372
00373 mxArray *
00374 octave_perm_matrix::as_mxArray (void) const
00375 {
00376 return to_dense ().as_mxArray ();
00377 }
00378
00379 bool
00380 octave_perm_matrix::print_as_scalar (void) const
00381 {
00382 dim_vector dv = dims ();
00383
00384 return (dv.all_ones () || dv.any_zero ());
00385 }
00386
00387 void
00388 octave_perm_matrix::print (std::ostream& os, bool pr_as_read_syntax) const
00389 {
00390 print_raw (os, pr_as_read_syntax);
00391 newline (os);
00392 }
00393
00394 int
00395 octave_perm_matrix::write (octave_stream& os, int block_size,
00396 oct_data_conv::data_type output_type, int skip,
00397 oct_mach_info::float_format flt_fmt) const
00398 {
00399 return to_dense ().write (os, block_size, output_type, skip, flt_fmt);
00400 }
00401
00402 void
00403 octave_perm_matrix::print_info (std::ostream& os,
00404 const std::string& prefix) const
00405 {
00406 matrix.print_info (os, prefix);
00407 }
00408
00409
00410 octave_value
00411 octave_perm_matrix::to_dense (void) const
00412 {
00413 if (! dense_cache.is_defined ())
00414 dense_cache = Matrix (matrix);
00415
00416 return dense_cache;
00417 }
00418
00419 DEFINE_OCTAVE_ALLOCATOR (octave_perm_matrix);
00420
00421 DEFINE_OV_TYPEID_FUNCTIONS_AND_DATA (octave_perm_matrix,
00422 "permutation matrix", "double");
00423
00424 static octave_base_value *
00425 default_numeric_conversion_function (const octave_base_value& a)
00426 {
00427 CAST_CONV_ARG (const octave_perm_matrix&);
00428
00429 return new octave_matrix (v.matrix_value ());
00430 }
00431
00432 octave_base_value::type_conv_info
00433 octave_perm_matrix::numeric_conversion_function (void) const
00434 {
00435 return octave_base_value::type_conv_info (default_numeric_conversion_function,
00436 octave_matrix::static_type_id ());
00437 }
00438
00439 octave_base_value *
00440 octave_perm_matrix::try_narrowing_conversion (void)
00441 {
00442 octave_base_value *retval = 0;
00443
00444 if (matrix.nelem () == 1)
00445 retval = new octave_scalar (matrix (0, 0));
00446
00447 return retval;
00448 }
00449