1993
|
1 // Template array classes |
1988
|
2 /* |
|
3 |
2847
|
4 Copyright (C) 1996, 1997 John W. Eaton |
1988
|
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 |
|
20 Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. |
|
21 |
|
22 */ |
|
23 |
4192
|
24 #if defined (__GNUG__) && defined (USE_PRAGMA_INTERFACE_IMPLEMENTATION) |
1988
|
25 #pragma implementation |
|
26 #endif |
|
27 |
|
28 #ifdef HAVE_CONFIG_H |
|
29 #include <config.h> |
|
30 #endif |
|
31 |
|
32 #include <cassert> |
|
33 |
3503
|
34 #include <iostream> |
1988
|
35 |
|
36 #include "Array2.h" |
|
37 |
|
38 #if defined (HEAVYWEIGHT_INDEXING) |
|
39 #include "idx-vector.h" |
|
40 #include "Array2-idx.h" |
|
41 #endif |
|
42 |
|
43 #include "lo-error.h" |
|
44 |
3665
|
45 // Two dimensional array class. |
|
46 |
4142
|
47 // A guess (should be quite conservative). |
|
48 #define MALLOC_OVERHEAD 1024 |
|
49 |
2109
|
50 template <class T> |
3473
|
51 int |
|
52 Array2<T>::get_size (int r, int c) const |
|
53 { |
|
54 // XXX KLUGE XXX |
|
55 |
|
56 // If an allocation of an array with r * c elements of type T |
|
57 // would cause an overflow in the allocator when computing the |
|
58 // size of the allocation, then return a value which, although |
|
59 // not equivalent to the actual request, should be too large for |
|
60 // most current hardware, but not so large to cause the |
|
61 // allocator to barf on computing retval * sizeof (T). |
|
62 |
|
63 static int nl; |
|
64 static double dl |
|
65 = frexp (static_cast<double> |
|
66 (INT_MAX - MALLOC_OVERHEAD) / sizeof (T), &nl); |
|
67 |
|
68 // This value should be an integer. If we return this value and |
|
69 // things work the way we expect, we should be paying a visit to |
|
70 // new_handler in no time flat. |
|
71 static int max_items = static_cast<int> (ldexp (dl, nl)); |
|
72 |
|
73 int nr, nc; |
|
74 double dr = frexp (static_cast<double> (r), &nr); |
|
75 double dc = frexp (static_cast<double> (c), &nc); |
|
76 |
|
77 int nt = nr + nc; |
|
78 double dt = dr * dc; |
|
79 |
|
80 if (dt <= 0.5) |
|
81 { |
|
82 nt--; |
|
83 dt *= 2; |
|
84 |
|
85 if (dt <= 0.5) |
|
86 nt--; |
|
87 } |
|
88 |
|
89 return (nt < nl || (nt == nl && dt < dl)) ? r * c : max_items; |
|
90 } |
|
91 |
4142
|
92 #undef MALLOC_OVERHEAD |
|
93 |
3473
|
94 template <class T> |
2109
|
95 T |
|
96 Array2<T>::range_error (const char *fcn, int i, int j) const |
|
97 { |
|
98 (*current_liboctave_error_handler) |
|
99 ("%s (%d, %d): range error", fcn, i, j); |
|
100 return T (); |
|
101 } |
|
102 |
|
103 template <class T> |
|
104 T& |
|
105 Array2<T>::range_error (const char *fcn, int i, int j) |
|
106 { |
|
107 (*current_liboctave_error_handler) |
|
108 ("%s (%d, %d): range error", fcn, i, j); |
|
109 static T foo; |
|
110 return foo; |
|
111 } |
|
112 |
1988
|
113 template <class T> |
|
114 void |
|
115 Array2<T>::resize (int r, int c) |
|
116 { |
|
117 if (r < 0 || c < 0) |
|
118 { |
2109
|
119 (*current_liboctave_error_handler) |
|
120 ("can't resize to negative dimension"); |
1988
|
121 return; |
|
122 } |
|
123 |
|
124 if (r == dim1 () && c == dim2 ()) |
|
125 return; |
|
126 |
4053
|
127 typename Array<T>::ArrayRep *old_rep = rep; |
1988
|
128 const T *old_data = data (); |
|
129 |
|
130 int old_d1 = dim1 (); |
|
131 int old_d2 = dim2 (); |
|
132 int old_len = length (); |
|
133 |
4054
|
134 rep = new typename Array<T>::ArrayRep (get_size (r, c)); |
1988
|
135 |
|
136 d1 = r; |
|
137 d2 = c; |
|
138 |
|
139 if (old_data && old_len > 0) |
|
140 { |
|
141 int min_r = old_d1 < r ? old_d1 : r; |
|
142 int min_c = old_d2 < c ? old_d2 : c; |
|
143 |
|
144 for (int j = 0; j < min_c; j++) |
|
145 for (int i = 0; i < min_r; i++) |
|
146 xelem (i, j) = old_data[old_d1*j+i]; |
|
147 } |
|
148 |
|
149 if (--old_rep->count <= 0) |
|
150 delete old_rep; |
|
151 } |
|
152 |
|
153 template <class T> |
|
154 void |
|
155 Array2<T>::resize (int r, int c, const T& val) |
|
156 { |
|
157 if (r < 0 || c < 0) |
|
158 { |
2109
|
159 (*current_liboctave_error_handler) |
|
160 ("can't resize to negative dimension"); |
1988
|
161 return; |
|
162 } |
|
163 |
|
164 if (r == dim1 () && c == dim2 ()) |
|
165 return; |
|
166 |
4053
|
167 typename Array<T>::ArrayRep *old_rep = rep; |
1988
|
168 const T *old_data = data (); |
2477
|
169 |
1988
|
170 int old_d1 = dim1 (); |
|
171 int old_d2 = dim2 (); |
|
172 int old_len = length (); |
|
173 |
4054
|
174 rep = new typename Array<T>::ArrayRep (get_size (r, c)); |
1988
|
175 |
|
176 d1 = r; |
|
177 d2 = c; |
|
178 |
|
179 int min_r = old_d1 < r ? old_d1 : r; |
|
180 int min_c = old_d2 < c ? old_d2 : c; |
|
181 |
|
182 if (old_data && old_len > 0) |
|
183 { |
|
184 for (int j = 0; j < min_c; j++) |
|
185 for (int i = 0; i < min_r; i++) |
|
186 xelem (i, j) = old_data[old_d1*j+i]; |
|
187 } |
|
188 |
|
189 for (int j = 0; j < min_c; j++) |
|
190 for (int i = min_r; i < r; i++) |
|
191 xelem (i, j) = val; |
|
192 |
|
193 for (int j = min_c; j < c; j++) |
|
194 for (int i = 0; i < r; i++) |
|
195 xelem (i, j) = val; |
|
196 |
|
197 if (--old_rep->count <= 0) |
|
198 delete old_rep; |
|
199 } |
|
200 |
|
201 template <class T> |
|
202 Array2<T>& |
|
203 Array2<T>::insert (const Array2<T>& a, int r, int c) |
|
204 { |
|
205 int a_rows = a.rows (); |
|
206 int a_cols = a.cols (); |
|
207 |
|
208 if (r < 0 || r + a_rows > rows () || c < 0 || c + a_cols > cols ()) |
|
209 { |
|
210 (*current_liboctave_error_handler) ("range error for insert"); |
|
211 return *this; |
|
212 } |
|
213 |
|
214 for (int j = 0; j < a_cols; j++) |
|
215 for (int i = 0; i < a_rows; i++) |
|
216 elem (r+i, c+j) = a.elem (i, j); |
|
217 |
|
218 return *this; |
|
219 } |
|
220 |
2815
|
221 template <class T> |
3225
|
222 Array2<T> |
|
223 Array2<T>::transpose (void) const |
|
224 { |
3731
|
225 if (d1 > 1 && d2 > 1) |
|
226 { |
|
227 Array2<T> result (d2, d1); |
|
228 |
|
229 for (int j = 0; j < d2; j++) |
|
230 for (int i = 0; i < d1; i++) |
|
231 result.xelem (j, i) = xelem (i, j); |
3225
|
232 |
3731
|
233 return result; |
|
234 } |
|
235 else |
|
236 { |
|
237 // Fast transpose for vectors and empty matrices |
|
238 return Array2<T> (*this, d2, d1); |
|
239 } |
3225
|
240 } |
|
241 |
3933
|
242 template <class T> |
|
243 void |
|
244 Array2<T>::print_info (std::ostream& os, const std::string& prefix) const |
|
245 { |
|
246 os << "\n" |
|
247 << prefix << "rows: " << rows () << "\n" |
|
248 << prefix << "cols: " << cols () << "\n"; |
|
249 |
|
250 Array<T>::print_info (os, prefix + " "); |
|
251 } |
|
252 |
1988
|
253 /* |
|
254 ;;; Local Variables: *** |
|
255 ;;; mode: C++ *** |
|
256 ;;; End: *** |
|
257 */ |