1993
|
1 // Template array classes |
237
|
2 /* |
|
3 |
2847
|
4 Copyright (C) 1996, 1997 John W. Eaton |
237
|
5 |
|
6 This file is part of Octave. |
|
7 |
|
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 |
|
10 Free Software Foundation; either version 2, or (at your option) any |
|
11 later version. |
|
12 |
|
13 Octave is distributed in the hope that it will be useful, but WITHOUT |
|
14 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or |
|
15 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License |
|
16 for more details. |
|
17 |
|
18 You should have received a copy of the GNU General Public License |
|
19 along with Octave; see the file COPYING. If not, write to the Free |
1315
|
20 Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. |
237
|
21 |
|
22 */ |
|
23 |
4192
|
24 #if defined (__GNUG__) && defined (USE_PRAGMA_INTERFACE_IMPLEMENTATION) |
1296
|
25 #pragma implementation |
|
26 #endif |
|
27 |
237
|
28 #ifdef HAVE_CONFIG_H |
1192
|
29 #include <config.h> |
237
|
30 #endif |
|
31 |
1367
|
32 #include <cassert> |
449
|
33 |
3503
|
34 #include <iostream> |
1560
|
35 |
237
|
36 #include "Array.h" |
4513
|
37 #include "Array-idx.h" |
1560
|
38 #include "idx-vector.h" |
|
39 #include "lo-error.h" |
|
40 |
1360
|
41 // One dimensional array class. Handles the reference counting for |
|
42 // all the derived classes. |
237
|
43 |
|
44 template <class T> |
1619
|
45 Array<T>::~Array (void) |
|
46 { |
|
47 if (--rep->count <= 0) |
|
48 delete rep; |
|
49 |
|
50 delete [] idx; |
4513
|
51 } |
|
52 |
|
53 // A guess (should be quite conservative). |
|
54 #define MALLOC_OVERHEAD 1024 |
|
55 |
|
56 template <class T> |
|
57 int |
|
58 Array<T>::get_size (int r, int c) |
|
59 { |
|
60 // XXX KLUGE XXX |
|
61 |
|
62 // If an allocation of an array with r * c elements of type T |
|
63 // would cause an overflow in the allocator when computing the |
|
64 // size of the allocation, then return a value which, although |
|
65 // not equivalent to the actual request, should be too large for |
|
66 // most current hardware, but not so large to cause the |
|
67 // allocator to barf on computing retval * sizeof (T). |
|
68 |
|
69 static int nl; |
|
70 static double dl |
|
71 = frexp (static_cast<double> |
|
72 (INT_MAX - MALLOC_OVERHEAD) / sizeof (T), &nl); |
|
73 |
|
74 // This value should be an integer. If we return this value and |
|
75 // things work the way we expect, we should be paying a visit to |
|
76 // new_handler in no time flat. |
|
77 static int max_items = static_cast<int> (ldexp (dl, nl)); |
|
78 |
|
79 int nr, nc; |
|
80 double dr = frexp (static_cast<double> (r), &nr); |
|
81 double dc = frexp (static_cast<double> (c), &nc); |
|
82 |
|
83 int nt = nr + nc; |
|
84 double dt = dr * dc; |
|
85 |
|
86 if (dt <= 0.5) |
|
87 { |
|
88 nt--; |
|
89 dt *= 2; |
|
90 |
|
91 if (dt <= 0.5) |
|
92 nt--; |
|
93 } |
|
94 |
|
95 return (nt < nl || (nt == nl && dt < dl)) ? r * c : max_items; |
237
|
96 } |
|
97 |
|
98 template <class T> |
4513
|
99 int |
|
100 Array<T>::get_size (int r, int c, int p) |
237
|
101 { |
4513
|
102 // XXX KLUGE XXX |
|
103 |
|
104 // If an allocation of an array with r * c * p elements of type T |
|
105 // would cause an overflow in the allocator when computing the |
|
106 // size of the allocation, then return a value which, although |
|
107 // not equivalent to the actual request, should be too large for |
|
108 // most current hardware, but not so large to cause the |
|
109 // allocator to barf on computing retval * sizeof (T). |
|
110 |
|
111 static int nl; |
|
112 static double dl |
|
113 = frexp (static_cast<double> |
|
114 (INT_MAX - MALLOC_OVERHEAD) / sizeof (T), &nl); |
|
115 |
|
116 // This value should be an integer. If we return this value and |
|
117 // things work the way we expect, we should be paying a visit to |
|
118 // new_handler in no time flat. |
|
119 static int max_items = static_cast<int> (ldexp (dl, nl)); |
|
120 |
|
121 int nr, nc, np; |
|
122 double dr = frexp (static_cast<double> (r), &nr); |
|
123 double dc = frexp (static_cast<double> (c), &nc); |
|
124 double dp = frexp (static_cast<double> (p), &np); |
|
125 |
|
126 int nt = nr + nc + np; |
|
127 double dt = dr * dc * dp; |
|
128 |
|
129 if (dt <= 0.5) |
659
|
130 { |
4513
|
131 nt--; |
|
132 dt *= 2; |
237
|
133 |
4513
|
134 if (dt <= 0.5) |
|
135 nt--; |
659
|
136 } |
1619
|
137 |
4513
|
138 return (nt < nl || (nt == nl && dt < dl)) ? r * c * p : max_items; |
237
|
139 } |
|
140 |
|
141 template <class T> |
4513
|
142 int |
|
143 Array<T>::get_size (const dim_vector& ra_idx) |
237
|
144 { |
4513
|
145 // XXX KLUGE XXX |
|
146 |
|
147 // If an allocation of an array with r * c elements of type T |
|
148 // would cause an overflow in the allocator when computing the |
|
149 // size of the allocation, then return a value which, although |
|
150 // not equivalent to the actual request, should be too large for |
|
151 // most current hardware, but not so large to cause the |
|
152 // allocator to barf on computing retval * sizeof (T). |
|
153 |
|
154 static int nl; |
|
155 static double dl |
|
156 = frexp (static_cast<double> |
|
157 (INT_MAX - MALLOC_OVERHEAD) / sizeof (T), &nl); |
|
158 |
|
159 // This value should be an integer. If we return this value and |
|
160 // things work the way we expect, we should be paying a visit to |
|
161 // new_handler in no time flat. |
|
162 |
|
163 static int max_items = static_cast<int> (ldexp (dl, nl)); |
|
164 |
|
165 int retval = max_items; |
|
166 |
|
167 int n = ra_idx.length (); |
|
168 |
|
169 int nt = 0; |
|
170 double dt = 1; |
|
171 |
|
172 for (int i = 0; i < n; i++) |
237
|
173 { |
4513
|
174 int nra_idx; |
|
175 double dra_idx = frexp (static_cast<double> (ra_idx(i)), &nra_idx); |
|
176 |
|
177 nt += nra_idx; |
|
178 dt *= dra_idx; |
237
|
179 } |
|
180 |
4513
|
181 if (dt <= 0.5) |
|
182 { |
|
183 nt--; |
|
184 dt *= 2; |
237
|
185 |
4513
|
186 if (dt <= 0.5) |
|
187 nt--; |
237
|
188 } |
|
189 |
4513
|
190 if (nt < nl || (nt == nl && dt < dl)) |
|
191 { |
|
192 retval = 1; |
|
193 |
|
194 for (int i = 0; i < n; i++) |
|
195 retval *= ra_idx(i); |
|
196 } |
|
197 |
|
198 return retval; |
237
|
199 } |
|
200 |
4513
|
201 #undef MALLOC_OVERHEAD |
|
202 |
237
|
203 template <class T> |
4513
|
204 int |
|
205 Array<T>::compute_index (const Array<int>& ra_idx) const |
237
|
206 { |
4513
|
207 int retval = -1; |
|
208 |
|
209 int n = dimensions.length (); |
|
210 |
|
211 if (n > 0 && n == ra_idx.length ()) |
237
|
212 { |
4513
|
213 retval = ra_idx(--n); |
237
|
214 |
4513
|
215 while (--n >= 0) |
|
216 { |
|
217 retval *= dimensions(n); |
|
218 retval += ra_idx(n); |
|
219 } |
|
220 } |
|
221 else |
|
222 (*current_liboctave_error_handler) |
|
223 ("Array<T>::compute_index: invalid ra_idxing operation"); |
237
|
224 |
4513
|
225 return retval; |
237
|
226 } |
|
227 |
4513
|
228 #if 0 |
|
229 |
237
|
230 template <class T> |
4513
|
231 int |
|
232 Array<T>::compute_index (int i, int j) const |
237
|
233 { |
4513
|
234 int retval = -1; |
|
235 |
|
236 int n = dimensions.length (); |
|
237 |
|
238 if (n == 2) |
|
239 retval = j*dimensions(0)+i; |
|
240 else if (n == 1 && j == 0) |
|
241 retval = i; |
|
242 else |
|
243 (*current_liboctave_error_handler) |
|
244 ("Array<T>::compute_index: invalid ra_idxing operation"); |
|
245 |
|
246 return retval; |
237
|
247 } |
4513
|
248 |
|
249 #endif |
|
250 |
2049
|
251 template <class T> |
|
252 T |
2109
|
253 Array<T>::range_error (const char *fcn, int n) const |
2049
|
254 { |
2109
|
255 (*current_liboctave_error_handler) ("%s (%d): range error", fcn, n); |
2049
|
256 return T (); |
|
257 } |
|
258 |
|
259 template <class T> |
|
260 T& |
2109
|
261 Array<T>::range_error (const char *fcn, int n) |
2049
|
262 { |
2109
|
263 (*current_liboctave_error_handler) ("%s (%d): range error", fcn, n); |
2049
|
264 static T foo; |
|
265 return foo; |
|
266 } |
|
267 |
3933
|
268 template <class T> |
4513
|
269 T |
|
270 Array<T>::range_error (const char *fcn, int i, int j) const |
|
271 { |
|
272 (*current_liboctave_error_handler) |
|
273 ("%s (%d, %d): range error", fcn, i, j); |
|
274 return T (); |
|
275 } |
|
276 |
|
277 template <class T> |
|
278 T& |
|
279 Array<T>::range_error (const char *fcn, int i, int j) |
|
280 { |
|
281 (*current_liboctave_error_handler) |
|
282 ("%s (%d, %d): range error", fcn, i, j); |
|
283 static T foo; |
|
284 return foo; |
|
285 } |
|
286 |
|
287 template <class T> |
|
288 T |
|
289 Array<T>::range_error (const char *fcn, int i, int j, int k) const |
|
290 { |
|
291 (*current_liboctave_error_handler) |
|
292 ("%s (%d, %d, %d): range error", fcn, i, j, k); |
|
293 return T (); |
|
294 } |
|
295 |
|
296 template <class T> |
|
297 T& |
|
298 Array<T>::range_error (const char *fcn, int i, int j, int k) |
|
299 { |
|
300 (*current_liboctave_error_handler) |
|
301 ("%s (%d, %d, %d): range error", fcn, i, j, k); |
|
302 static T foo; |
|
303 return foo; |
|
304 } |
|
305 |
|
306 template <class T> |
|
307 T |
|
308 Array<T>::range_error (const char *fcn, const Array<int>& ra_idx) const |
|
309 { |
|
310 // XXX FIXME XXX -- report index values too! |
|
311 |
|
312 (*current_liboctave_error_handler) ("range error in Array"); |
|
313 |
|
314 return T (); |
|
315 } |
|
316 |
|
317 template <class T> |
|
318 T& |
|
319 Array<T>::range_error (const char *fcn, const Array<int>& ra_idx) |
|
320 { |
|
321 // XXX FIXME XXX -- report index values too! |
|
322 |
|
323 (*current_liboctave_error_handler) ("range error in Array"); |
|
324 |
|
325 static T foo; |
|
326 return foo; |
|
327 } |
|
328 |
|
329 template <class T> |
|
330 void |
|
331 Array<T>::resize_no_fill (int n) |
|
332 { |
|
333 if (n < 0) |
|
334 { |
|
335 (*current_liboctave_error_handler) |
|
336 ("can't resize to negative dimension"); |
|
337 return; |
|
338 } |
|
339 |
|
340 if (n == length ()) |
|
341 return; |
|
342 |
|
343 typename Array<T>::ArrayRep *old_rep = rep; |
|
344 const T *old_data = data (); |
|
345 int old_len = length (); |
|
346 |
|
347 rep = new typename Array<T>::ArrayRep (n); |
|
348 |
|
349 dimensions = dim_vector (n); |
|
350 |
|
351 if (old_data && old_len > 0) |
|
352 { |
|
353 int min_len = old_len < n ? old_len : n; |
|
354 |
|
355 for (int i = 0; i < min_len; i++) |
|
356 xelem (i) = old_data[i]; |
|
357 } |
|
358 |
|
359 if (--old_rep->count <= 0) |
|
360 delete old_rep; |
|
361 } |
|
362 |
|
363 template <class T> |
|
364 void |
|
365 Array<T>::resize_no_fill (const dim_vector& dims) |
|
366 { |
|
367 int n = dims.length (); |
|
368 |
|
369 for (int i = 0; i < n; i++) |
|
370 { |
|
371 if (dims(i) < 0) |
|
372 { |
|
373 (*current_liboctave_error_handler) |
|
374 ("can't resize to negative dimension"); |
|
375 return; |
|
376 } |
|
377 } |
|
378 |
|
379 bool no_change = true; |
|
380 |
|
381 for (int i = 0; i < n; i++) |
|
382 { |
|
383 if (dims(i) != dimensions(i)) |
|
384 { |
|
385 no_change = false; |
|
386 break; |
|
387 } |
|
388 } |
|
389 |
|
390 if (no_change) |
|
391 return; |
|
392 |
|
393 int old_len = length (); |
|
394 |
|
395 typename Array<T>::ArrayRep *old_rep = rep; |
|
396 const T *old_data = data (); |
|
397 |
|
398 rep = new typename Array<T>::ArrayRep (get_size (dims)); |
|
399 |
|
400 dim_vector old_dimensions = dimensions; |
|
401 |
|
402 dimensions = dims; |
|
403 |
|
404 Array<int> ra_idx (dimensions.length (), 0); |
|
405 |
|
406 for (int i = 0; i < old_len; i++) |
|
407 { |
|
408 if (index_in_bounds (ra_idx, dimensions)) |
|
409 xelem (ra_idx) = old_data[i]; |
|
410 |
|
411 increment_index (ra_idx, dimensions); |
|
412 } |
|
413 |
|
414 if (--old_rep->count <= 0) |
|
415 delete old_rep; |
|
416 } |
|
417 |
|
418 template <class T> |
|
419 void |
|
420 Array<T>::resize_no_fill (int r, int c) |
|
421 { |
|
422 if (r < 0 || c < 0) |
|
423 { |
|
424 (*current_liboctave_error_handler) |
|
425 ("can't resize to negative dimension"); |
|
426 return; |
|
427 } |
|
428 |
|
429 if (r == dim1 () && c == dim2 ()) |
|
430 return; |
|
431 |
|
432 typename Array<T>::ArrayRep *old_rep = Array<T>::rep; |
|
433 const T *old_data = data (); |
|
434 |
|
435 int old_d1 = dim1 (); |
|
436 int old_d2 = dim2 (); |
|
437 int old_len = length (); |
|
438 |
|
439 rep = new typename Array<T>::ArrayRep (get_size (r, c)); |
|
440 |
|
441 dimensions = dim_vector (r, c); |
|
442 |
|
443 if (old_data && old_len > 0) |
|
444 { |
|
445 int min_r = old_d1 < r ? old_d1 : r; |
|
446 int min_c = old_d2 < c ? old_d2 : c; |
|
447 |
|
448 for (int j = 0; j < min_c; j++) |
|
449 for (int i = 0; i < min_r; i++) |
|
450 xelem (i, j) = old_data[old_d1*j+i]; |
|
451 } |
|
452 |
|
453 if (--old_rep->count <= 0) |
|
454 delete old_rep; |
|
455 } |
|
456 |
|
457 template <class T> |
|
458 void |
|
459 Array<T>::resize_no_fill (int r, int c, int p) |
|
460 { |
|
461 if (r < 0 || c < 0 || p < 0) |
|
462 { |
|
463 (*current_liboctave_error_handler) |
|
464 ("can't resize to negative dimension"); |
|
465 return; |
|
466 } |
|
467 |
|
468 if (r == dim1 () && c == dim2 () && p == dim3 ()) |
|
469 return; |
|
470 |
|
471 typename Array<T>::ArrayRep *old_rep = rep; |
|
472 const T *old_data = data (); |
|
473 |
|
474 int old_d1 = dim1 (); |
|
475 int old_d2 = dim2 (); |
|
476 int old_d3 = dim3 (); |
|
477 int old_len = length (); |
|
478 |
|
479 int ts = get_size (get_size (r, c), p); |
|
480 |
|
481 rep = new typename Array<T>::ArrayRep (ts); |
|
482 |
|
483 dimensions = dim_vector (r, c, p); |
|
484 |
|
485 if (old_data && old_len > 0) |
|
486 { |
|
487 int min_r = old_d1 < r ? old_d1 : r; |
|
488 int min_c = old_d2 < c ? old_d2 : c; |
|
489 int min_p = old_d3 < p ? old_d3 : p; |
|
490 |
|
491 for (int k = 0; k < min_p; k++) |
|
492 for (int j = 0; j < min_c; j++) |
|
493 for (int i = 0; i < min_r; i++) |
|
494 xelem (i, j, k) = old_data[old_d1*(old_d2*k+j)+i]; |
|
495 } |
|
496 |
|
497 if (--old_rep->count <= 0) |
|
498 delete old_rep; |
|
499 } |
|
500 |
|
501 template <class T> |
|
502 void |
|
503 Array<T>::resize_and_fill (int n, const T& val) |
|
504 { |
|
505 if (n < 0) |
|
506 { |
|
507 (*current_liboctave_error_handler) |
|
508 ("can't resize to negative dimension"); |
|
509 return; |
|
510 } |
|
511 |
|
512 if (n == length ()) |
|
513 return; |
|
514 |
|
515 typename Array<T>::ArrayRep *old_rep = rep; |
|
516 const T *old_data = data (); |
|
517 int old_len = length (); |
|
518 |
|
519 rep = new typename Array<T>::ArrayRep (n); |
|
520 |
|
521 dimensions = dim_vector (n); |
|
522 |
|
523 int min_len = old_len < n ? old_len : n; |
|
524 |
|
525 if (old_data && old_len > 0) |
|
526 { |
|
527 for (int i = 0; i < min_len; i++) |
|
528 xelem (i) = old_data[i]; |
|
529 } |
|
530 |
|
531 for (int i = old_len; i < n; i++) |
|
532 xelem (i) = val; |
|
533 |
|
534 if (--old_rep->count <= 0) |
|
535 delete old_rep; |
|
536 } |
|
537 |
|
538 template <class T> |
|
539 void |
|
540 Array<T>::resize_and_fill (int r, int c, const T& val) |
|
541 { |
|
542 if (r < 0 || c < 0) |
|
543 { |
|
544 (*current_liboctave_error_handler) |
|
545 ("can't resize to negative dimension"); |
|
546 return; |
|
547 } |
|
548 |
|
549 if (r == dim1 () && c == dim2 ()) |
|
550 return; |
|
551 |
|
552 typename Array<T>::ArrayRep *old_rep = Array<T>::rep; |
|
553 const T *old_data = data (); |
|
554 |
|
555 int old_d1 = dim1 (); |
|
556 int old_d2 = dim2 (); |
|
557 int old_len = length (); |
|
558 |
|
559 rep = new typename Array<T>::ArrayRep (get_size (r, c)); |
|
560 |
|
561 dimensions = dim_vector (r, c); |
|
562 |
|
563 int min_r = old_d1 < r ? old_d1 : r; |
|
564 int min_c = old_d2 < c ? old_d2 : c; |
|
565 |
|
566 if (old_data && old_len > 0) |
|
567 { |
|
568 for (int j = 0; j < min_c; j++) |
|
569 for (int i = 0; i < min_r; i++) |
|
570 xelem (i, j) = old_data[old_d1*j+i]; |
|
571 } |
|
572 |
|
573 for (int j = 0; j < min_c; j++) |
|
574 for (int i = min_r; i < r; i++) |
|
575 xelem (i, j) = val; |
|
576 |
|
577 for (int j = min_c; j < c; j++) |
|
578 for (int i = 0; i < r; i++) |
|
579 xelem (i, j) = val; |
|
580 |
|
581 if (--old_rep->count <= 0) |
|
582 delete old_rep; |
|
583 } |
|
584 |
|
585 template <class T> |
|
586 void |
|
587 Array<T>::resize_and_fill (int r, int c, int p, const T& val) |
|
588 { |
|
589 if (r < 0 || c < 0 || p < 0) |
|
590 { |
|
591 (*current_liboctave_error_handler) |
|
592 ("can't resize to negative dimension"); |
|
593 return; |
|
594 } |
|
595 |
|
596 if (r == dim1 () && c == dim2 () && p == dim3 ()) |
|
597 return; |
|
598 |
|
599 typename Array<T>::ArrayRep *old_rep = rep; |
|
600 const T *old_data = data (); |
|
601 |
|
602 int old_d1 = dim1 (); |
|
603 int old_d2 = dim2 (); |
|
604 int old_d3 = dim3 (); |
|
605 |
|
606 int old_len = length (); |
|
607 |
|
608 int ts = get_size (get_size (r, c), p); |
|
609 |
|
610 rep = new typename Array<T>::ArrayRep (ts); |
|
611 |
|
612 dimensions = dim_vector (r, c, p); |
|
613 |
|
614 int min_r = old_d1 < r ? old_d1 : r; |
|
615 int min_c = old_d2 < c ? old_d2 : c; |
|
616 int min_p = old_d3 < p ? old_d3 : p; |
|
617 |
|
618 if (old_data && old_len > 0) |
|
619 for (int k = 0; k < min_p; k++) |
|
620 for (int j = 0; j < min_c; j++) |
|
621 for (int i = 0; i < min_r; i++) |
|
622 xelem (i, j, k) = old_data[old_d1*(old_d2*k+j)+i]; |
|
623 |
|
624 // XXX FIXME XXX -- if the copy constructor is expensive, this may |
|
625 // win. Otherwise, it may make more sense to just copy the value |
|
626 // everywhere when making the new ArrayRep. |
|
627 |
|
628 for (int k = 0; k < min_p; k++) |
|
629 for (int j = min_c; j < c; j++) |
|
630 for (int i = 0; i < min_r; i++) |
|
631 xelem (i, j, k) = val; |
|
632 |
|
633 for (int k = 0; k < min_p; k++) |
|
634 for (int j = 0; j < c; j++) |
|
635 for (int i = min_r; i < r; i++) |
|
636 xelem (i, j, k) = val; |
|
637 |
|
638 for (int k = min_p; k < p; k++) |
|
639 for (int j = 0; j < c; j++) |
|
640 for (int i = 0; i < r; i++) |
|
641 xelem (i, j, k) = val; |
|
642 |
|
643 if (--old_rep->count <= 0) |
|
644 delete old_rep; |
|
645 } |
|
646 |
|
647 template <class T> |
|
648 void |
|
649 Array<T>::resize_and_fill (const dim_vector& dims, const T& val) |
|
650 { |
|
651 int n = dims.length (); |
|
652 |
|
653 for (int i = 0; i < n; i++) |
|
654 { |
|
655 if (dims(i) < 0) |
|
656 { |
|
657 (*current_liboctave_error_handler) |
|
658 ("can't resize to negative dimension"); |
|
659 return; |
|
660 } |
|
661 } |
|
662 |
|
663 bool no_change = true; |
|
664 |
|
665 for (int i = 0; i < n; i++) |
|
666 { |
|
667 if (dims(i) != dimensions(i)) |
|
668 { |
|
669 no_change = false; |
|
670 break; |
|
671 } |
|
672 } |
|
673 |
|
674 if (no_change) |
|
675 return; |
|
676 |
|
677 typename Array<T>::ArrayRep *old_rep = rep; |
|
678 const T *old_data = data (); |
|
679 |
|
680 int old_len = length (); |
|
681 |
|
682 int len = get_size (dims); |
|
683 |
|
684 rep = new typename Array<T>::ArrayRep (len); |
|
685 |
|
686 dim_vector old_dimensions = dimensions; |
|
687 |
|
688 dimensions = dims; |
|
689 |
|
690 Array<int> ra_idx (dimensions.length (), 0); |
|
691 |
|
692 // XXX FIXME XXX -- it is much simpler to fill the whole array |
|
693 // first, but probably slower for large arrays, or if the assignment |
|
694 // operator for the type T is expensive. OTOH, the logic for |
|
695 // deciding whether an element needs the copied value or the filled |
|
696 // value might be more expensive. |
|
697 |
|
698 for (int i = 0; i < len; i++) |
|
699 rep->elem (i) = val; |
|
700 |
|
701 for (int i = 0; i < old_len; i++) |
|
702 { |
|
703 if (index_in_bounds (ra_idx, dimensions)) |
|
704 xelem (ra_idx) = old_data[i]; |
|
705 |
|
706 increment_index (ra_idx, dimensions); |
|
707 } |
|
708 |
|
709 if (--old_rep->count <= 0) |
|
710 delete old_rep; |
|
711 } |
|
712 |
|
713 template <class T> |
|
714 Array<T>& |
|
715 Array<T>::insert (const Array<T>& a, int r, int c) |
|
716 { |
|
717 int a_rows = a.rows (); |
|
718 int a_cols = a.cols (); |
|
719 |
|
720 if (r < 0 || r + a_rows > rows () || c < 0 || c + a_cols > cols ()) |
|
721 { |
|
722 (*current_liboctave_error_handler) ("range error for insert"); |
|
723 return *this; |
|
724 } |
|
725 |
|
726 for (int j = 0; j < a_cols; j++) |
|
727 for (int i = 0; i < a_rows; i++) |
|
728 elem (r+i, c+j) = a.elem (i, j); |
|
729 |
|
730 return *this; |
|
731 } |
|
732 |
|
733 template <class T> |
|
734 Array<T>& |
|
735 Array<T>::insert (const Array<T>& a, const Array<int>& ra_idx) |
|
736 { |
|
737 int n = ra_idx.length (); |
|
738 |
|
739 if (n == dimensions.length ()) |
|
740 { |
|
741 dim_vector a_dims = a.dims (); |
|
742 |
|
743 for (int i = 0; i < n; i++) |
|
744 { |
|
745 if (ra_idx(i) < 0 || ra_idx(i) + a_dims(i) > dimensions(i)) |
|
746 { |
|
747 (*current_liboctave_error_handler) |
|
748 ("Array<T>::insert: range error for insert"); |
|
749 return *this; |
|
750 } |
|
751 } |
|
752 |
|
753 #if 0 |
|
754 // XXX FIXME XXX -- need to copy elements |
|
755 |
|
756 for (int j = 0; j < a_cols; j++) |
|
757 for (int i = 0; i < a_rows; i++) |
|
758 elem (r+i, c+j) = a.elem (i, j); |
|
759 #endif |
|
760 |
|
761 } |
|
762 else |
|
763 (*current_liboctave_error_handler) |
|
764 ("Array<T>::insert: invalid indexing operation"); |
|
765 |
|
766 return *this; |
|
767 } |
|
768 |
|
769 template <class T> |
|
770 void |
|
771 Array<T>::maybe_delete_dims (void) |
|
772 { |
|
773 int ndims = dimensions.length (); |
|
774 |
|
775 dim_vector new_dims (1, 1); |
|
776 |
|
777 bool delete_dims = true; |
|
778 |
|
779 for (int i = ndims - 1; i >= 0; i--) |
|
780 { |
|
781 if (delete_dims) |
|
782 { |
|
783 if (dimensions(i) != 1) |
|
784 { |
|
785 delete_dims = false; |
|
786 |
|
787 new_dims = dim_vector (i + 1, dimensions(i)); |
|
788 } |
|
789 } |
|
790 else |
|
791 new_dims(i) = dimensions(i); |
|
792 } |
|
793 |
|
794 if (ndims != new_dims.length ()) |
|
795 dimensions = new_dims; |
|
796 } |
|
797 |
|
798 template <class T> |
|
799 Array<T> |
|
800 Array<T>::transpose (void) const |
|
801 { |
|
802 int nr = dim1 (); |
|
803 int nc = dim2 (); |
|
804 |
|
805 if (nr > 1 && nc > 1) |
|
806 { |
|
807 Array<T> result (dim_vector (nc, nr)); |
|
808 |
|
809 for (int j = 0; j < nc; j++) |
|
810 for (int i = 0; i < nr; i++) |
|
811 result.xelem (j, i) = xelem (i, j); |
|
812 |
|
813 return result; |
|
814 } |
|
815 else |
|
816 { |
|
817 // Fast transpose for vectors and empty matrices |
|
818 return Array<T> (*this, dim_vector (nc, nr)); |
|
819 } |
|
820 } |
|
821 |
|
822 template <class T> |
|
823 T * |
|
824 Array<T>::fortran_vec (void) |
|
825 { |
|
826 if (rep->count > 1) |
|
827 { |
|
828 --rep->count; |
|
829 rep = new typename Array<T>::ArrayRep (*rep); |
|
830 } |
|
831 return rep->data; |
|
832 } |
|
833 |
|
834 template <class T> |
3933
|
835 void |
|
836 Array<T>::print_info (std::ostream& os, const std::string& prefix) const |
|
837 { |
|
838 os << prefix << "rep address: " << rep << "\n" |
|
839 << prefix << "rep->len: " << rep->len << "\n" |
|
840 << prefix << "rep->data: " << static_cast<void *> (rep->data) << "\n" |
|
841 << prefix << "rep->count: " << rep->count << "\n"; |
4513
|
842 |
|
843 // 2D info: |
|
844 // |
|
845 // << prefix << "rows: " << rows () << "\n" |
|
846 // << prefix << "cols: " << cols () << "\n"; |
3933
|
847 } |
|
848 |
237
|
849 /* |
|
850 ;;; Local Variables: *** |
|
851 ;;; mode: C++ *** |
|
852 ;;; End: *** |
|
853 */ |