Mercurial > hg > octave-max
comparison liboctave/Array.cc @ 9840:c0b54271904b
improve safe numel() calculation for arrays
author | Jaroslav Hajek <highegg@gmail.com> |
---|---|
date | Thu, 19 Nov 2009 15:48:33 +0100 |
parents | 3e8b4c80ae63 |
children | ead4f9c82a9a |
comparison
equal
deleted
inserted
replaced
9839:3e8b4c80ae63 | 9840:c0b54271904b |
---|---|
100 Array<T>::clear (const dim_vector& dv) | 100 Array<T>::clear (const dim_vector& dv) |
101 { | 101 { |
102 if (--rep->count <= 0) | 102 if (--rep->count <= 0) |
103 delete rep; | 103 delete rep; |
104 | 104 |
105 rep = new ArrayRep (get_size (dv)); | 105 rep = new ArrayRep (dv.safe_numel ()); |
106 slice_data = rep->data; | 106 slice_data = rep->data; |
107 slice_len = rep->len; | 107 slice_len = rep->len; |
108 | 108 |
109 dimensions = dv; | 109 dimensions = dv; |
110 } | 110 } |
159 retval = Array<T> (*this, new_dimensions); | 159 retval = Array<T> (*this, new_dimensions); |
160 } | 160 } |
161 | 161 |
162 return retval; | 162 return retval; |
163 } | 163 } |
164 | |
165 // KLUGE | |
166 | |
167 // The following get_size functions will throw a std::bad_alloc () | |
168 // exception if the requested size is larger than can be indexed by | |
169 // octave_idx_type. This may be smaller than the actual amount of | |
170 // memory that can be safely allocated on a system. However, if we | |
171 // don't fail here, we can end up with a mysterious crash inside a | |
172 // function that is iterating over an array using octave_idx_type | |
173 // indices. | |
174 | |
175 // A guess (should be quite conservative). | |
176 #define MALLOC_OVERHEAD 1024 | |
177 | |
178 template <class T> | |
179 octave_idx_type | |
180 Array<T>::get_size (octave_idx_type r, octave_idx_type c) | |
181 { | |
182 static int nl; | |
183 static double dl | |
184 = frexp (static_cast<double> | |
185 (std::numeric_limits<octave_idx_type>::max() - MALLOC_OVERHEAD) / sizeof (T), &nl); | |
186 | |
187 int nr, nc; | |
188 double dr = frexp (static_cast<double> (r), &nr); // r = dr * 2^nr | |
189 double dc = frexp (static_cast<double> (c), &nc); // c = dc * 2^nc | |
190 | |
191 int nt = nr + nc; | |
192 double dt = dr * dc; | |
193 | |
194 if (dt < 0.5) | |
195 { | |
196 nt--; | |
197 dt *= 2; | |
198 } | |
199 | |
200 if (nt < nl || (nt == nl && dt < dl)) | |
201 return r * c; | |
202 else | |
203 { | |
204 throw std::bad_alloc (); | |
205 return 0; | |
206 } | |
207 } | |
208 | |
209 template <class T> | |
210 octave_idx_type | |
211 Array<T>::get_size (octave_idx_type r, octave_idx_type c, octave_idx_type p) | |
212 { | |
213 static int nl; | |
214 static double dl | |
215 = frexp (static_cast<double> | |
216 (std::numeric_limits<octave_idx_type>::max() - MALLOC_OVERHEAD) / sizeof (T), &nl); | |
217 | |
218 int nr, nc, np; | |
219 double dr = frexp (static_cast<double> (r), &nr); | |
220 double dc = frexp (static_cast<double> (c), &nc); | |
221 double dp = frexp (static_cast<double> (p), &np); | |
222 | |
223 int nt = nr + nc + np; | |
224 double dt = dr * dc * dp; | |
225 | |
226 if (dt < 0.5) | |
227 { | |
228 nt--; | |
229 dt *= 2; | |
230 | |
231 if (dt < 0.5) | |
232 { | |
233 nt--; | |
234 dt *= 2; | |
235 } | |
236 } | |
237 | |
238 if (nt < nl || (nt == nl && dt < dl)) | |
239 return r * c * p; | |
240 else | |
241 { | |
242 throw std::bad_alloc (); | |
243 return 0; | |
244 } | |
245 } | |
246 | |
247 template <class T> | |
248 octave_idx_type | |
249 Array<T>::get_size (const dim_vector& ra_idx) | |
250 { | |
251 static int nl; | |
252 static double dl | |
253 = frexp (static_cast<double> | |
254 (std::numeric_limits<octave_idx_type>::max() - MALLOC_OVERHEAD) / sizeof (T), &nl); | |
255 | |
256 int n = ra_idx.length (); | |
257 | |
258 int nt = 0; | |
259 double dt = 1; | |
260 | |
261 for (int i = 0; i < n; i++) | |
262 { | |
263 int nra_idx; | |
264 double dra_idx = frexp (static_cast<double> (ra_idx(i)), &nra_idx); | |
265 | |
266 nt += nra_idx; | |
267 dt *= dra_idx; | |
268 | |
269 if (dt < 0.5) | |
270 { | |
271 nt--; | |
272 dt *= 2; | |
273 } | |
274 } | |
275 | |
276 if (nt < nl || (nt == nl && dt < dl)) | |
277 { | |
278 octave_idx_type retval = 1; | |
279 | |
280 for (int i = 0; i < n; i++) | |
281 retval *= ra_idx(i); | |
282 | |
283 return retval; | |
284 } | |
285 else | |
286 { | |
287 throw std::bad_alloc (); | |
288 return 0; | |
289 } | |
290 } | |
291 | |
292 #undef MALLOC_OVERHEAD | |
293 | 164 |
294 template <class T> | 165 template <class T> |
295 octave_idx_type | 166 octave_idx_type |
296 Array<T>::compute_index (const Array<octave_idx_type>& ra_idx) const | 167 Array<T>::compute_index (const Array<octave_idx_type>& ra_idx) const |
297 { | 168 { |