comparison src/pt-mat.cc @ 1827:effa9400766f

[project @ 1996-02-02 14:07:51 by jwe]
author jwe
date Fri, 02 Feb 1996 14:10:10 +0000
parents a02f140ed897
children 003570e69c7b
comparison
equal deleted inserted replaced
1826:b14829582cc4 1827:effa9400766f
1 // pt-mat.cc -*- C++ -*- 1 // pt-mat.cc -*- C++ -*-
2 /* 2 /*
3 3
4 Copyright (C) 1992, 1993, 1994, 1995 John W. Eaton 4 Copyright (C) 1996 John W. Eaton
5 5
6 This file is part of Octave. 6 This file is part of Octave.
7 7
8 Octave is free software; you can redistribute it and/or modify it 8 Octave is free software; you can redistribute it and/or modify it
9 under the terms of the GNU General Public License as published by the 9 under the terms of the GNU General Public License as published by the
44 44
45 // General matrices. This list type is much more work to handle than 45 // General matrices. This list type is much more work to handle than
46 // constant matrices, but it allows us to construct matrices from 46 // constant matrices, but it allows us to construct matrices from
47 // other matrices, variables, and functions. 47 // other matrices, variables, and functions.
48 48
49 tree_matrix::~tree_matrix (void) 49 // But first, some internal classes that make our job much easier.
50 { 50
51 delete element; 51 class
52 delete next; 52 tm_row_const
53 } 53 {
54 54 private:
55 int 55
56 tree_matrix::is_matrix_constant (void) const 56 class
57 { 57 tm_row_const_rep : public SLList<tree_constant>
58 const tree_matrix *list = this; 58 {
59 59 public:
60 while (list) 60
61 { 61 tm_row_const_rep (void)
62 tree_expression *elem = list->element; 62 : SLList<tree_constant> (), count (1), nr (0), nc (0),
63 63 all_str (false), is_cmplx (false), ok (false) { }
64 if (! elem->is_constant ()) 64
65 return 0; 65 tm_row_const_rep (const tree_matrix_row& mr)
66 66 : SLList<tree_constant> (), count (1), nr (0), nc (0),
67 list = list->next; 67 all_str (false), is_cmplx (false), ok (false)
68 } 68 { init (mr); }
69 69
70 return 1; 70 ~tm_row_const_rep (void) { }
71 } 71
72 72 int count;
73 tree_matrix * 73
74 tree_matrix::chain (tree_expression *t, tree_matrix::dir d) 74 int nr;
75 { 75 int nc;
76 tree_matrix *tmp = new tree_matrix (t, d); 76
77 tmp->next = this; 77 bool all_str;
78 return tmp; 78 bool is_cmplx;
79 } 79
80 80 bool ok;
81 tree_matrix * 81
82 tree_matrix::reverse (void) 82 void init (const tree_matrix_row&);
83 { 83
84 tree_matrix *list = this; 84 private:
85 tree_matrix *next; 85
86 tree_matrix *prev = 0; 86 tm_row_const_rep (const tm_row_const_rep&);
87 87
88 while (list) 88 tm_row_const_rep& operator =
89 { 89 (const tm_row_const_rep&);
90 next = list->next; 90 };
91 list->next = prev; 91
92 prev = list; 92 public:
93 list = next; 93
94 } 94 tm_row_const (void) : rep (0) { }
95 return prev; 95
96 } 96 tm_row_const (const tree_matrix_row& mr)
97 97 : rep (new tm_row_const_rep (mr)) { }
98 int 98
99 tree_matrix::length (void) 99 tm_row_const (const tm_row_const& x) : rep (x.rep)
100 { 100 {
101 tree_matrix *list = this; 101 if (rep)
102 int len = 0; 102 rep->count++;
103 while (list) 103 }
104 { 104
105 len++; 105 tm_row_const& operator = (const tm_row_const& x)
106 list = list->next; 106 {
107 } 107 if (this != &x && rep != x.rep)
108 return len; 108 {
109 if (rep && --rep->count == 0)
110 delete rep;
111
112 rep = x.rep;
113
114 if (rep)
115 rep->count++;
116 }
117
118 return *this;
119 }
120
121 ~tm_row_const (void)
122 {
123 if (rep && --rep->count == 0)
124 delete rep;
125 }
126
127 int rows (void) { return rep->nr; }
128 int cols (void) { return rep->nc; }
129
130 bool all_strings (void) const { return rep->all_str; }
131 bool is_complex (void) const { return rep->is_cmplx; }
132
133 tree_constant& operator () (Pix p) { return rep->operator () (p); }
134
135 const tree_constant& operator () (Pix p) const
136 { return rep->operator () (p); }
137
138 Pix first (void) const { return rep->first (); }
139 void next (Pix& p) const { rep->next (p); }
140
141 operator void* () const
142 {
143 return (rep && rep->ok) ? (void *) -1 : (void *) 0;
144 }
145
146 private:
147
148 tm_row_const_rep *rep;
149 };
150
151 void
152 tm_row_const::tm_row_const_rep::init (const tree_matrix_row& mr)
153 {
154 all_str = true;
155
156 int empties_ok = user_pref.empty_list_elements_ok;
157
158 bool first_elem = true;
159
160 for (Pix p = mr.first (); p != 0; mr.next (p))
161 {
162 tree_expression *elt = mr (p);
163
164 tree_constant tmp = elt->eval (false);
165
166 if (error_state || tmp.is_undefined ())
167 break;
168 else
169 {
170 int this_elt_nr = tmp.rows ();
171 int this_elt_nc = tmp.columns ();
172
173 if (this_elt_nr == 0 || this_elt_nc == 0)
174 {
175 if (empties_ok < 0)
176 warning ("empty matrix found in matrix list");
177 else if (empties_ok == 0)
178 {
179 ::error ("empty matrix found in matrix list");
180 break;
181 }
182 }
183 else
184 {
185 if (first_elem)
186 {
187 first_elem = false;
188
189 nr = this_elt_nr;
190 }
191 else if (this_elt_nr != nr)
192 {
193 ::error ("number of rows must match");
194 break;
195 }
196
197 nc += this_elt_nc;
198
199 append (tmp);
200 }
201
202 if (all_str && ! tmp.is_string ())
203 all_str = false;
204
205 if (! is_cmplx && tmp.is_complex_type ())
206 is_cmplx = true;
207 }
208 }
209
210 ok = ! error_state;
211 }
212
213 template class SLNode<tm_row_const>;
214 template class SLList<tm_row_const>;
215
216 class
217 tm_const : public SLList<tm_row_const>
218 {
219 public:
220
221 tm_const (const tree_matrix& tm)
222 : SLList<tm_row_const> (), nr (0), nc (0), all_str (false),
223 is_cmplx (false), ok (false)
224 { init (tm); }
225
226 ~tm_const (void) { }
227
228 int rows (void) const { return nr; }
229 int cols (void) const { return nc; }
230
231 bool all_strings (void) const { return all_str; }
232 bool is_complex (void) const { return is_cmplx; }
233
234 operator void* () const { return ok ? (void *) -1 : (void *) 0; }
235
236 private:
237
238 int nr;
239 int nc;
240
241 bool all_str;
242 bool is_cmplx;
243
244 bool ok;
245
246 tm_const (void);
247
248 tm_const (const tm_const&);
249
250 tm_const& operator = (const tm_const&);
251
252 void init (const tree_matrix& tm);
253 };
254
255 void
256 tm_const::init (const tree_matrix& tm)
257 {
258 all_str = true;
259
260 int empties_ok = user_pref.empty_list_elements_ok;
261
262 bool first_elem = true;
263
264 // Just eval and figure out if what we have is complex or all
265 // strings. We can't check columns until we know that this is a
266 // numeric matrix -- collections of strings can have elements of
267 // different lengths.
268
269 for (Pix p = tm.first (); p != 0; tm.next (p))
270 {
271 tree_matrix_row *elt = tm (p);
272
273 tm_row_const tmp (*elt);
274
275 if (tmp)
276 {
277 if (all_str && ! tmp.all_strings ())
278 all_str = false;
279
280 if (! is_cmplx && tmp.is_complex ())
281 is_cmplx = true;
282
283 append (tmp);
284 }
285 else
286 break;
287 }
288
289 if (! error_state)
290 {
291 for (Pix p = first (); p != 0; next (p))
292 {
293 tm_row_const elt = this->operator () (p);
294
295 int this_elt_nr = elt.rows ();
296 int this_elt_nc = elt.cols ();
297
298 if (this_elt_nr == 0 || this_elt_nc == 0)
299 {
300 if (empties_ok < 0)
301 warning ("empty matrix found in matrix list");
302 else if (empties_ok == 0)
303 {
304 ::error ("empty matrix found in matrix list");
305 break;
306 }
307 }
308 else
309 {
310 if (first_elem)
311 {
312 first_elem = false;
313
314 nc = this_elt_nc;
315 }
316 else if (all_str)
317 {
318 if (this_elt_nc > nc)
319 nc = this_elt_nc;
320 }
321 else if (this_elt_nc != nc)
322 {
323 ::error ("number of columns must match");
324 break;
325 }
326
327 nr += this_elt_nr;
328 }
329 }
330 }
331
332 ok = ! error_state;
333 }
334
335 bool
336 tree_matrix_row::is_matrix_constant (void) const
337 {
338 for (Pix p = first (); p != 0; next (p))
339 {
340 tree_expression *elt = this->operator () (p);
341
342 if (! elt->is_constant ())
343 return false;
344 }
345
346 return true;
109 } 347 }
110 348
111 tree_return_list * 349 tree_return_list *
112 tree_matrix::to_return_list (void) 350 tree_matrix_row::to_return_list (void)
113 { 351 {
114 tree_return_list *retval = 0; 352 tree_return_list *retval = 0;
115 353
116 tree_matrix *list; 354 bool first_elem = true;
117 355
118 for (list = this; list; list = list->next) 356 for (Pix p = first (); p != 0; next (p))
119 { 357 {
120 tree_expression *elem = list->element; 358 tree_expression *elt = this->operator () (p);
121 359
122 int is_id = elem->is_identifier (); 360 bool is_id = elt->is_identifier ();
123 361
124 int is_idx_expr = elem->is_index_expression (); 362 bool is_idx_expr = elt->is_index_expression ();
125 363
126 if (is_id || is_idx_expr) 364 if (is_id || is_idx_expr)
127 { 365 {
128 tree_index_expression *idx_expr; 366 tree_index_expression *idx_expr;
367
129 if (is_id) 368 if (is_id)
130 { 369 {
131 tree_identifier *id = (tree_identifier *) elem; 370 tree_identifier *id = (tree_identifier *) elt;
132 idx_expr = new tree_index_expression (id); 371 idx_expr = new tree_index_expression (id);
133 } 372 }
134 else 373 else
135 idx_expr = (tree_index_expression *) elem; 374 idx_expr = (tree_index_expression *) elt;
136 375
137 if (list == this) 376 if (first_elem)
138 retval = new tree_return_list (idx_expr); 377 {
378 first_elem = false;
379
380 retval = new tree_return_list (idx_expr);
381 }
139 else 382 else
140 retval->append (idx_expr); 383 retval->append (idx_expr);
141 } 384 }
142 else 385 else
143 { 386 {
148 } 391 }
149 392
150 return retval; 393 return retval;
151 } 394 }
152 395
396 void
397 tree_matrix_row::print_code (ostream& os)
398 {
399 Pix p = first ();
400
401 while (p)
402 {
403 tree_expression *elt = this->operator () (p);
404
405 next (p);
406
407 if (elt)
408 {
409 elt->print_code (os);
410
411 if (p)
412 os << ", ";
413 }
414 }
415 }
416
417 bool
418 tree_matrix::is_matrix_constant (void) const
419 {
420 for (Pix p = first (); p != 0; next (p))
421 {
422 tree_matrix_row *elt = this->operator () (p);
423
424 if (! elt->is_matrix_constant ())
425 return false;
426 }
427
428 return true;
429 }
430
153 // Just about as ugly as it gets. 431 // Just about as ugly as it gets.
154
155 struct const_matrix_list
156 {
157 tree_matrix::dir direction;
158 tree_constant elem;
159 int nr;
160 int nc;
161 };
162
163 // Less ugly than before, anyway. 432 // Less ugly than before, anyway.
433 // Looking better all the time.
164 434
165 tree_constant 435 tree_constant
166 tree_matrix::eval (int /* print */) 436 tree_matrix::eval (bool /* print */)
167 { 437 {
168 tree_constant retval; 438 tree_constant retval;
169 439
170 if (error_state) 440 tm_const tmp (*this);
171 return retval; 441
172 442 if (tmp)
173 // Just count the elements without looking at them. 443 {
174
175 int total_len = length ();
176
177 // Easier to deal with this later instead of a tree_matrix
178 // structure.
179
180 const_matrix_list *list = new const_matrix_list [total_len];
181
182 // Stats we want to keep track of.
183
184 int all_strings = 1;
185
186 int found_complex = 0;
187
188 int row_total = 0;
189 int col_total = 0;
190
191 int row_height = 0;
192
193 int cols_this_row = 0;
194
195 int first_row = 1;
196
197 int empties_ok = user_pref.empty_list_elements_ok;
198
199 tree_matrix *ptr = this;
200
201 // Stuff for the result matrix or string. Declared here so that we
202 // don't get warnings from gcc about the goto crossing the
203 // initialization of these values.
204
205 int put_row = 0;
206 int put_col = 0;
207
208 int prev_nr = 0;
209 int prev_nc = 0;
210
211 Matrix m;
212 ComplexMatrix cm;
213 charMatrix chm;
214
215 // Eliminate empties and gather stats.
216
217 int found_new_row_in_empties = 0;
218
219 int len = 0;
220 for (int i = 0; i < total_len; i++)
221 {
222 tree_expression *elem = ptr->element;
223 if (! elem)
224 {
225 retval = tree_constant (Matrix ());
226 goto done;
227 }
228
229 tree_constant tmp = elem->eval (0);
230 if (error_state || tmp.is_undefined ())
231 {
232 retval = tree_constant ();
233 goto done;
234 }
235
236 int nr = tmp.rows (); 444 int nr = tmp.rows ();
237 int nc = tmp.columns (); 445 int nc = tmp.cols ();
238 446
239 dir direct = ptr->direction; 447 Matrix m;
240 448 ComplexMatrix cm;
241 if (nr == 0 || nc == 0) 449 charMatrix chm;
242 { 450
243 if (empties_ok < 0) 451 // Now, extract the values from the individual elements and
244 warning ("empty matrix found in matrix list"); 452 // insert them in the result matrix.
245 else if (empties_ok == 0) 453
246 { 454 bool all_strings = tmp.all_strings ();
247 ::error ("empty matrix found in matrix list"); 455 bool found_complex = tmp.is_complex ();
248 retval = tree_constant (); 456
249 goto done; 457 if (all_strings)
250 } 458 chm.resize (nr, nc, 0);
251 459 else if (found_complex)
252 if (direct == md_down) 460 cm.resize (nr, nc, 0.0);
253 found_new_row_in_empties = 1;
254
255 goto next;
256 }
257
258 if (found_new_row_in_empties)
259 {
260 found_new_row_in_empties = 0;
261 list[len].direction = md_down;
262 }
263 else 461 else
264 list[len].direction = direct; 462 m.resize (nr, nc, 0.0);
265 463
266 list[len].elem = tmp; 464 int put_row = 0;
267 list[len].nr = nr; 465
268 list[len].nc = nc; 466 for (Pix p = tmp.first (); p != 0; tmp.next (p))
269 467 {
270 if (all_strings && ! tmp.is_string ()) 468 int put_col = 0;
271 all_strings = 0; 469
272 470 tm_row_const row = tmp (p);
273 if (! found_complex && tmp.is_complex_type ()) 471
274 found_complex = 1; 472 for (Pix q = row.first (); q != 0; row.next (q))
275 473 {
276 len++; 474 tree_constant elt = row (q);
277 475
278 next: 476 if (found_complex)
279 477 {
280 ptr = ptr->next; 478 if (elt.is_real_scalar ())
281 } 479 cm (put_row, put_col) = elt.double_value ();
282 480 else if (elt.is_real_matrix () || elt.is_range ())
283 // if (all_strings) 481 cm.insert (elt.matrix_value (), put_row, put_col);
284 // cerr << "all strings\n"; 482 else if (elt.is_complex_scalar ())
285 483 cm (put_row, put_col) = elt.complex_value ();
286 // Compute size of result matrix, and check to see that the dimensions 484 else
287 // of all the elements will match up properly. 485 {
288 486 ComplexMatrix cm_elt = elt.complex_matrix_value ();
289 for (int i = 0; i < len; i++) 487
290 { 488 if (error_state)
291 dir direct = list[i].direction; 489 goto done;
292 490
293 int nr = list[i].nr; 491 cm.insert (cm_elt, put_row, put_col);
294 int nc = list[i].nc; 492 }
295 493 }
296 if (i == 0) 494 else
297 { 495 {
298 row_total = nr; 496 if (elt.is_real_scalar ())
299 col_total = nc; 497 m (put_row, put_col) = elt.double_value ();
300 498 else if (elt.is_string () && all_strings)
301 row_height = nr; 499 {
302 cols_this_row = nc; 500 charMatrix chm_elt = elt.all_strings ();
303 } 501
304 else 502 if (error_state)
305 { 503 goto done;
306 switch (direct) 504
307 { 505 chm.insert (chm_elt, put_row, put_col);
308 case md_right: 506 }
309 { 507 else
310 if (nr != row_height) 508 {
311 { 509 Matrix m_elt = elt.matrix_value ();
312 ::error ("number of rows must match"); 510
313 goto done; 511 if (error_state)
314 } 512 goto done;
315 else 513
316 { 514 m.insert (m_elt, put_row, put_col);
317 cols_this_row += nc; 515 }
318 516 }
319 if (first_row) 517
320 col_total = cols_this_row; 518 if (all_strings && chm.rows () > 0 && chm.cols () > 0)
321 else if (all_strings && cols_this_row > col_total) 519 retval = tree_constant (chm, true);
322 col_total = cols_this_row; 520 else if (found_complex)
323 } 521 retval = cm;
324 } 522 else
325 break; 523 retval = m;
326 524
327 case md_down: 525 put_col += elt.columns ();
328 { 526 }
329 if (cols_this_row != col_total && ! all_strings) 527
330 { 528 put_row += row.rows ();
331 ::error ("number of columns must match"); 529 }
332 goto done; 530 }
333 } 531
334 first_row = 0; 532 done:
335 row_total += nr;
336 row_height = nr;
337 cols_this_row = nc;
338 }
339 break;
340
341 default:
342 panic_impossible ();
343 break;
344 }
345 }
346 }
347
348 // Don't forget to check to see if the last element will fit.
349
350 if (all_strings && cols_this_row > col_total)
351 {
352 col_total = cols_this_row;
353 }
354 else if (cols_this_row != col_total)
355 {
356 ::error ("number of columns must match");
357 goto done;
358 }
359
360 // Now, extract the values from the individual elements and insert
361 // them in the result matrix.
362
363 if (all_strings)
364 chm.resize (row_total, col_total, 0);
365 else if (found_complex)
366 cm.resize (row_total, col_total, 0.0);
367 else
368 m.resize (row_total, col_total, 0.0);
369
370 for (int i = 0; i < len; i++)
371 {
372 tree_constant tmp = list[i].elem;
373
374 int nr = list[i].nr;
375 int nc = list[i].nc;
376
377 if (nr == 0 || nc == 0)
378 continue;
379
380 if (i == 0)
381 {
382 put_row = 0;
383 put_col = 0;
384 }
385 else
386 {
387 switch (list[i].direction)
388 {
389 case md_right:
390 put_col += prev_nc;
391 break;
392
393 case md_down:
394 put_row += prev_nr;
395 put_col = 0;
396 break;
397
398 default:
399 panic_impossible ();
400 break;
401 }
402 }
403
404 if (found_complex)
405 {
406 if (tmp.is_real_scalar ())
407 {
408 cm (put_row, put_col) = tmp.double_value ();
409 }
410 else if (tmp.is_real_matrix () || tmp.is_range ())
411 {
412 cm.insert (tmp.matrix_value (), put_row, put_col);
413 }
414 else if (tmp.is_complex_scalar ())
415 {
416 cm (put_row, put_col) = tmp.complex_value ();
417 }
418 else
419 {
420 ComplexMatrix cm_tmp = tmp.complex_matrix_value ();
421
422 if (error_state)
423 goto done;
424
425 cm.insert (cm_tmp, put_row, put_col);
426 }
427 }
428 else
429 {
430 if (tmp.is_real_scalar ())
431 {
432 m (put_row, put_col) = tmp.double_value ();
433 }
434 else if (tmp.is_string () && all_strings)
435 {
436 charMatrix chm_tmp = tmp.all_strings ();
437
438 if (error_state)
439 goto done;
440
441 chm.insert (chm_tmp, put_row, put_col);
442 }
443 else
444 {
445 Matrix m_tmp = tmp.matrix_value ();
446
447 if (error_state)
448 goto done;
449
450 m.insert (m_tmp, put_row, put_col);
451 }
452 }
453
454 prev_nr = nr;
455 prev_nc = nc;
456 }
457
458 if (all_strings && chm.rows () > 0 && chm.cols () > 0)
459 retval = tree_constant (chm, 1);
460 else if (found_complex)
461 retval = cm;
462 else
463 retval = m;
464
465 done:
466 delete [] list;
467 533
468 return retval; 534 return retval;
469 } 535 }
470 536
471 void 537 void
476 if (in_parens) 542 if (in_parens)
477 os << "("; 543 os << "(";
478 544
479 os << "["; 545 os << "[";
480 546
481 tree_matrix *list = this; 547 Pix p = first ();
482 548
483 while (list) 549 while (p)
484 { 550 {
485 list->element->print_code (os); 551 tree_matrix_row *elt = this->operator () (p);
486 552
487 list = list->next; 553 next (p);
488 554
489 if (list) 555 if (elt)
490 { 556 {
491 switch (list->direction) 557 elt->print_code (os);
492 { 558
493 case md_right: 559 if (p)
494 os << ", "; 560 os << "; ";
495 break;
496
497 case md_down:
498 os << "; ";
499 break;
500
501 default:
502 break;
503 }
504 } 561 }
505 } 562 }
506 563
507 os << "]"; 564 os << "]";
508 565