1 | /* $Id: CoinHelperFunctions.hpp 1448 2011-06-19 15:34:41Z stefan $ */ |
2 | // Copyright (C) 2000, International Business Machines |
3 | // Corporation and others. All Rights Reserved. |
4 | // This code is licensed under the terms of the Eclipse Public License (EPL). |
5 | |
6 | #ifndef CoinHelperFunctions_H |
7 | #define CoinHelperFunctions_H |
8 | |
9 | #include "CoinUtilsConfig.h" |
10 | |
11 | #if defined(_MSC_VER) |
12 | # include <direct.h> |
13 | # define getcwd _getcwd |
14 | #else |
15 | # include <unistd.h> |
16 | #endif |
17 | //#define USE_MEMCPY |
18 | |
19 | #include <cstdlib> |
20 | #include <cstdio> |
21 | #include <algorithm> |
22 | #include "CoinTypes.hpp" |
23 | #include "CoinError.hpp" |
24 | |
25 | // Compilers can produce better code if they know about __restrict |
26 | #ifndef COIN_RESTRICT |
27 | #ifdef COIN_USE_RESTRICT |
28 | #define COIN_RESTRICT __restrict |
29 | #else |
30 | #define COIN_RESTRICT |
31 | #endif |
32 | #endif |
33 | |
34 | //############################################################################# |
35 | |
36 | /** This helper function copies an array to another location using Duff's |
37 | device (for a speedup of ~2). The arrays are given by pointers to their |
38 | first entries and by the size of the source array. Overlapping arrays are |
39 | handled correctly. */ |
40 | |
41 | template <class T> inline void |
42 | CoinCopyN(const T* from, const int size, T* to) |
43 | { |
44 | if (size == 0 || from == to) |
45 | return; |
46 | |
47 | #ifndef NDEBUG |
48 | if (size < 0) |
49 | throw CoinError("trying to copy negative number of entries" , |
50 | "CoinCopyN" , "" ); |
51 | #endif |
52 | |
53 | int n = (size + 7) / 8; |
54 | if (to > from) { |
55 | const T* downfrom = from + size; |
56 | T* downto = to + size; |
57 | // Use Duff's device to copy |
58 | switch (size % 8) { |
59 | case 0: do{ *--downto = *--downfrom; |
60 | case 7: *--downto = *--downfrom; |
61 | case 6: *--downto = *--downfrom; |
62 | case 5: *--downto = *--downfrom; |
63 | case 4: *--downto = *--downfrom; |
64 | case 3: *--downto = *--downfrom; |
65 | case 2: *--downto = *--downfrom; |
66 | case 1: *--downto = *--downfrom; |
67 | }while(--n>0); |
68 | } |
69 | } else { |
70 | // Use Duff's device to copy |
71 | --from; |
72 | --to; |
73 | switch (size % 8) { |
74 | case 0: do{ *++to = *++from; |
75 | case 7: *++to = *++from; |
76 | case 6: *++to = *++from; |
77 | case 5: *++to = *++from; |
78 | case 4: *++to = *++from; |
79 | case 3: *++to = *++from; |
80 | case 2: *++to = *++from; |
81 | case 1: *++to = *++from; |
82 | }while(--n>0); |
83 | } |
84 | } |
85 | } |
86 | |
87 | //----------------------------------------------------------------------------- |
88 | |
89 | /** This helper function copies an array to another location using Duff's |
90 | device (for a speedup of ~2). The source array is given by its first and |
91 | "after last" entry; the target array is given by its first entry. |
92 | Overlapping arrays are handled correctly. |
93 | |
94 | All of the various CoinCopyN variants use an int for size. On 64-bit |
95 | architectures, the address diff last-first will be a 64-bit quantity. |
96 | Given that everything else uses an int, I'm going to choose to kick |
97 | the difference down to int. -- lh, 100823 -- |
98 | */ |
99 | template <class T> inline void |
100 | CoinCopy(const T* first, const T* last, T* to) |
101 | { |
102 | CoinCopyN(first, static_cast<int>(last-first), to); |
103 | } |
104 | |
105 | //----------------------------------------------------------------------------- |
106 | |
107 | /** This helper function copies an array to another location. The two arrays |
108 | must not overlap (otherwise an exception is thrown). For speed 8 entries |
109 | are copied at a time. The arrays are given by pointers to their first |
110 | entries and by the size of the source array. |
111 | |
112 | Note JJF - the speed claim seems to be false on IA32 so I have added |
113 | CoinMemcpyN which can be used for atomic data */ |
114 | template <class T> inline void |
115 | CoinDisjointCopyN(const T* from, const int size, T* to) |
116 | { |
117 | #ifndef _MSC_VER |
118 | if (size == 0 || from == to) |
119 | return; |
120 | |
121 | #ifndef NDEBUG |
122 | if (size < 0) |
123 | throw CoinError("trying to copy negative number of entries" , |
124 | "CoinDisjointCopyN" , "" ); |
125 | #endif |
126 | |
127 | #if 0 |
128 | /* There is no point to do this test. If to and from are from different |
129 | blocks then dist is undefined, so this can crash correct code. It's |
130 | better to trust the user that the arrays are really disjoint. */ |
131 | const long dist = to - from; |
132 | if (-size < dist && dist < size) |
133 | throw CoinError("overlapping arrays" , "CoinDisjointCopyN" , "" ); |
134 | #endif |
135 | |
136 | for (int n = size / 8; n > 0; --n, from += 8, to += 8) { |
137 | to[0] = from[0]; |
138 | to[1] = from[1]; |
139 | to[2] = from[2]; |
140 | to[3] = from[3]; |
141 | to[4] = from[4]; |
142 | to[5] = from[5]; |
143 | to[6] = from[6]; |
144 | to[7] = from[7]; |
145 | } |
146 | switch (size % 8) { |
147 | case 7: to[6] = from[6]; |
148 | case 6: to[5] = from[5]; |
149 | case 5: to[4] = from[4]; |
150 | case 4: to[3] = from[3]; |
151 | case 3: to[2] = from[2]; |
152 | case 2: to[1] = from[1]; |
153 | case 1: to[0] = from[0]; |
154 | case 0: break; |
155 | } |
156 | #else |
157 | CoinCopyN(from, size, to); |
158 | #endif |
159 | } |
160 | |
161 | //----------------------------------------------------------------------------- |
162 | |
163 | /** This helper function copies an array to another location. The two arrays |
164 | must not overlap (otherwise an exception is thrown). For speed 8 entries |
165 | are copied at a time. The source array is given by its first and "after |
166 | last" entry; the target array is given by its first entry. */ |
167 | template <class T> inline void |
168 | CoinDisjointCopy(const T* first, const T* last, |
169 | T* to) |
170 | { |
171 | CoinDisjointCopyN(first, static_cast<int>(last - first), to); |
172 | } |
173 | |
174 | //----------------------------------------------------------------------------- |
175 | |
176 | /*! \brief Return an array of length \p size filled with input from \p array, |
177 | or null if \p array is null. |
178 | */ |
179 | |
180 | template <class T> inline T* |
181 | CoinCopyOfArray( const T * array, const int size) |
182 | { |
183 | if (array) { |
184 | T * arrayNew = new T[size]; |
185 | std::memcpy(arrayNew,array,size*sizeof(T)); |
186 | return arrayNew; |
187 | } else { |
188 | return NULL; |
189 | } |
190 | } |
191 | |
192 | |
193 | /*! \brief Return an array of length \p size filled with first copySize from \p array, |
194 | or null if \p array is null. |
195 | */ |
196 | |
197 | template <class T> inline T* |
198 | CoinCopyOfArrayPartial( const T * array, const int size,const int copySize) |
199 | { |
200 | if (array||size) { |
201 | T * arrayNew = new T[size]; |
202 | assert (copySize<=size); |
203 | std::memcpy(arrayNew,array,copySize*sizeof(T)); |
204 | return arrayNew; |
205 | } else { |
206 | return NULL; |
207 | } |
208 | } |
209 | |
210 | /*! \brief Return an array of length \p size filled with input from \p array, |
211 | or filled with (scalar) \p value if \p array is null |
212 | */ |
213 | |
214 | template <class T> inline T* |
215 | CoinCopyOfArray( const T * array, const int size, T value) |
216 | { |
217 | T * arrayNew = new T[size]; |
218 | if (array) { |
219 | std::memcpy(arrayNew,array,size*sizeof(T)); |
220 | } else { |
221 | int i; |
222 | for (i=0;i<size;i++) |
223 | arrayNew[i] = value; |
224 | } |
225 | return arrayNew; |
226 | } |
227 | |
228 | |
229 | /*! \brief Return an array of length \p size filled with input from \p array, |
230 | or filled with zero if \p array is null |
231 | */ |
232 | |
233 | template <class T> inline T* |
234 | CoinCopyOfArrayOrZero( const T * array , const int size) |
235 | { |
236 | T * arrayNew = new T[size]; |
237 | if (array) { |
238 | std::memcpy(arrayNew,array,size*sizeof(T)); |
239 | } else { |
240 | std::memset(arrayNew,0,size*sizeof(T)); |
241 | } |
242 | return arrayNew; |
243 | } |
244 | |
245 | |
246 | //----------------------------------------------------------------------------- |
247 | |
248 | /** This helper function copies an array to another location. The two arrays |
249 | must not overlap (otherwise an exception is thrown). For speed 8 entries |
250 | are copied at a time. The arrays are given by pointers to their first |
251 | entries and by the size of the source array. |
252 | |
253 | Note JJF - the speed claim seems to be false on IA32 so I have added |
254 | alternative coding if USE_MEMCPY defined*/ |
255 | #ifndef COIN_USE_RESTRICT |
256 | template <class T> inline void |
257 | CoinMemcpyN(const T* from, const int size, T* to) |
258 | { |
259 | #ifndef _MSC_VER |
260 | #ifdef USE_MEMCPY |
261 | // Use memcpy - seems a lot faster on Intel with gcc |
262 | #ifndef NDEBUG |
263 | // Some debug so check |
264 | if (size < 0) |
265 | throw CoinError("trying to copy negative number of entries" , |
266 | "CoinMemcpyN" , "" ); |
267 | |
268 | #if 0 |
269 | /* There is no point to do this test. If to and from are from different |
270 | blocks then dist is undefined, so this can crash correct code. It's |
271 | better to trust the user that the arrays are really disjoint. */ |
272 | const long dist = to - from; |
273 | if (-size < dist && dist < size) |
274 | throw CoinError("overlapping arrays" , "CoinMemcpyN" , "" ); |
275 | #endif |
276 | #endif |
277 | std::memcpy(to,from,size*sizeof(T)); |
278 | #else |
279 | if (size == 0 || from == to) |
280 | return; |
281 | |
282 | #ifndef NDEBUG |
283 | if (size < 0) |
284 | throw CoinError("trying to copy negative number of entries" , |
285 | "CoinMemcpyN" , "" ); |
286 | #endif |
287 | |
288 | #if 0 |
289 | /* There is no point to do this test. If to and from are from different |
290 | blocks then dist is undefined, so this can crash correct code. It's |
291 | better to trust the user that the arrays are really disjoint. */ |
292 | const long dist = to - from; |
293 | if (-size < dist && dist < size) |
294 | throw CoinError("overlapping arrays" , "CoinMemcpyN" , "" ); |
295 | #endif |
296 | |
297 | for (int n = size / 8; n > 0; --n, from += 8, to += 8) { |
298 | to[0] = from[0]; |
299 | to[1] = from[1]; |
300 | to[2] = from[2]; |
301 | to[3] = from[3]; |
302 | to[4] = from[4]; |
303 | to[5] = from[5]; |
304 | to[6] = from[6]; |
305 | to[7] = from[7]; |
306 | } |
307 | switch (size % 8) { |
308 | case 7: to[6] = from[6]; |
309 | case 6: to[5] = from[5]; |
310 | case 5: to[4] = from[4]; |
311 | case 4: to[3] = from[3]; |
312 | case 3: to[2] = from[2]; |
313 | case 2: to[1] = from[1]; |
314 | case 1: to[0] = from[0]; |
315 | case 0: break; |
316 | } |
317 | #endif |
318 | #else |
319 | CoinCopyN(from, size, to); |
320 | #endif |
321 | } |
322 | #else |
323 | template <class T> inline void |
324 | CoinMemcpyN(const T * COIN_RESTRICT from, int size, T* COIN_RESTRICT to) |
325 | { |
326 | #ifdef USE_MEMCPY |
327 | std::memcpy(to,from,size*sizeof(T)); |
328 | #else |
329 | T * COIN_RESTRICT put = to; |
330 | const T * COIN_RESTRICT get = from; |
331 | for ( ; 0<size ; --size) |
332 | *put++ = *get++; |
333 | #endif |
334 | } |
335 | #endif |
336 | |
337 | //----------------------------------------------------------------------------- |
338 | |
339 | /** This helper function copies an array to another location. The two arrays |
340 | must not overlap (otherwise an exception is thrown). For speed 8 entries |
341 | are copied at a time. The source array is given by its first and "after |
342 | last" entry; the target array is given by its first entry. */ |
343 | template <class T> inline void |
344 | CoinMemcpy(const T* first, const T* last, |
345 | T* to) |
346 | { |
347 | CoinMemcpyN(first, static_cast<int>(last - first), to); |
348 | } |
349 | |
350 | //############################################################################# |
351 | |
352 | /** This helper function fills an array with a given value. For speed 8 entries |
353 | are filled at a time. The array is given by a pointer to its first entry |
354 | and its size. |
355 | |
356 | Note JJF - the speed claim seems to be false on IA32 so I have added |
357 | CoinZero to allow for memset. */ |
358 | template <class T> inline void |
359 | CoinFillN(T* to, const int size, const T value) |
360 | { |
361 | if (size == 0) |
362 | return; |
363 | |
364 | #ifndef NDEBUG |
365 | if (size < 0) |
366 | throw CoinError("trying to fill negative number of entries" , |
367 | "CoinFillN" , "" ); |
368 | #endif |
369 | #if 1 |
370 | for (int n = size / 8; n > 0; --n, to += 8) { |
371 | to[0] = value; |
372 | to[1] = value; |
373 | to[2] = value; |
374 | to[3] = value; |
375 | to[4] = value; |
376 | to[5] = value; |
377 | to[6] = value; |
378 | to[7] = value; |
379 | } |
380 | switch (size % 8) { |
381 | case 7: to[6] = value; |
382 | case 6: to[5] = value; |
383 | case 5: to[4] = value; |
384 | case 4: to[3] = value; |
385 | case 3: to[2] = value; |
386 | case 2: to[1] = value; |
387 | case 1: to[0] = value; |
388 | case 0: break; |
389 | } |
390 | #else |
391 | // Use Duff's device to fill |
392 | int n = (size + 7) / 8; |
393 | --to; |
394 | switch (size % 8) { |
395 | case 0: do{ *++to = value; |
396 | case 7: *++to = value; |
397 | case 6: *++to = value; |
398 | case 5: *++to = value; |
399 | case 4: *++to = value; |
400 | case 3: *++to = value; |
401 | case 2: *++to = value; |
402 | case 1: *++to = value; |
403 | }while(--n>0); |
404 | } |
405 | #endif |
406 | } |
407 | |
408 | //----------------------------------------------------------------------------- |
409 | |
410 | /** This helper function fills an array with a given value. For speed 8 |
411 | entries are filled at a time. The array is given by its first and "after |
412 | last" entry. */ |
413 | template <class T> inline void |
414 | CoinFill(T* first, T* last, const T value) |
415 | { |
416 | CoinFillN(first, last - first, value); |
417 | } |
418 | |
419 | //############################################################################# |
420 | |
421 | /** This helper function fills an array with zero. For speed 8 entries |
422 | are filled at a time. The array is given by a pointer to its first entry |
423 | and its size. |
424 | |
425 | Note JJF - the speed claim seems to be false on IA32 so I have allowed |
426 | for memset as an alternative */ |
427 | template <class T> inline void |
428 | CoinZeroN(T* to, const int size) |
429 | { |
430 | #ifdef USE_MEMCPY |
431 | // Use memset - seems faster on Intel with gcc |
432 | #ifndef NDEBUG |
433 | // Some debug so check |
434 | if (size < 0) |
435 | throw CoinError("trying to fill negative number of entries" , |
436 | "CoinZeroN" , "" ); |
437 | #endif |
438 | memset(to,0,size*sizeof(T)); |
439 | #else |
440 | if (size == 0) |
441 | return; |
442 | |
443 | #ifndef NDEBUG |
444 | if (size < 0) |
445 | throw CoinError("trying to fill negative number of entries" , |
446 | "CoinZeroN" , "" ); |
447 | #endif |
448 | #if 1 |
449 | for (int n = size / 8; n > 0; --n, to += 8) { |
450 | to[0] = 0; |
451 | to[1] = 0; |
452 | to[2] = 0; |
453 | to[3] = 0; |
454 | to[4] = 0; |
455 | to[5] = 0; |
456 | to[6] = 0; |
457 | to[7] = 0; |
458 | } |
459 | switch (size % 8) { |
460 | case 7: to[6] = 0; |
461 | case 6: to[5] = 0; |
462 | case 5: to[4] = 0; |
463 | case 4: to[3] = 0; |
464 | case 3: to[2] = 0; |
465 | case 2: to[1] = 0; |
466 | case 1: to[0] = 0; |
467 | case 0: break; |
468 | } |
469 | #else |
470 | // Use Duff's device to fill |
471 | int n = (size + 7) / 8; |
472 | --to; |
473 | switch (size % 8) { |
474 | case 0: do{ *++to = 0; |
475 | case 7: *++to = 0; |
476 | case 6: *++to = 0; |
477 | case 5: *++to = 0; |
478 | case 4: *++to = 0; |
479 | case 3: *++to = 0; |
480 | case 2: *++to = 0; |
481 | case 1: *++to = 0; |
482 | }while(--n>0); |
483 | } |
484 | #endif |
485 | #endif |
486 | } |
487 | /// This Debug helper function checks an array is all zero |
488 | inline void |
489 | CoinCheckDoubleZero(double * to, const int size) |
490 | { |
491 | int n=0; |
492 | for (int j=0;j<size;j++) { |
493 | if (to[j]) |
494 | n++; |
495 | } |
496 | if (n) { |
497 | printf("array of length %d should be zero has %d nonzero\n" ,size,n); |
498 | } |
499 | } |
500 | /// This Debug helper function checks an array is all zero |
501 | inline void |
502 | CoinCheckIntZero(int * to, const int size) |
503 | { |
504 | int n=0; |
505 | for (int j=0;j<size;j++) { |
506 | if (to[j]) |
507 | n++; |
508 | } |
509 | if (n) { |
510 | printf("array of length %d should be zero has %d nonzero\n" ,size,n); |
511 | } |
512 | } |
513 | |
514 | //----------------------------------------------------------------------------- |
515 | |
516 | /** This helper function fills an array with a given value. For speed 8 |
517 | entries are filled at a time. The array is given by its first and "after |
518 | last" entry. */ |
519 | template <class T> inline void |
520 | CoinZero(T* first, T* last) |
521 | { |
522 | CoinZeroN(first, last - first); |
523 | } |
524 | |
525 | //############################################################################# |
526 | |
527 | /** Returns strdup or NULL if original NULL */ |
528 | inline char * CoinStrdup(const char * name) |
529 | { |
530 | char* dup = nullptr; |
531 | if (name) { |
532 | const int len = static_cast<int>(strlen(name)); |
533 | dup = static_cast<char*>(malloc(len+1)); |
534 | CoinMemcpyN(name, len, dup); |
535 | dup[len] = 0; |
536 | } |
537 | return dup; |
538 | } |
539 | |
540 | //############################################################################# |
541 | |
542 | /** Return the larger (according to <code>operator<()</code> of the arguments. |
543 | This function was introduced because for some reason compiler tend to |
544 | handle the <code>max()</code> function differently. */ |
545 | template <class T> inline T |
546 | CoinMax(const T x1, const T x2) |
547 | { |
548 | return (x1 > x2) ? x1 : x2; |
549 | } |
550 | |
551 | //----------------------------------------------------------------------------- |
552 | |
553 | /** Return the smaller (according to <code>operator<()</code> of the arguments. |
554 | This function was introduced because for some reason compiler tend to |
555 | handle the min() function differently. */ |
556 | template <class T> inline T |
557 | CoinMin(const T x1, const T x2) |
558 | { |
559 | return (x1 < x2) ? x1 : x2; |
560 | } |
561 | |
562 | //----------------------------------------------------------------------------- |
563 | |
564 | /** Return the absolute value of the argument. This function was introduced |
565 | because for some reason compiler tend to handle the abs() function |
566 | differently. */ |
567 | template <class T> inline T |
568 | CoinAbs(const T value) |
569 | { |
570 | return value<0 ? -value : value; |
571 | } |
572 | |
573 | //############################################################################# |
574 | |
575 | /** This helper function tests whether the entries of an array are sorted |
576 | according to operator<. The array is given by a pointer to its first entry |
577 | and by its size. */ |
578 | template <class T> inline bool |
579 | CoinIsSorted(const T* first, const int size) |
580 | { |
581 | if (size == 0) |
582 | return true; |
583 | |
584 | #ifndef NDEBUG |
585 | if (size < 0) |
586 | throw CoinError("negative number of entries" , "CoinIsSorted" , "" ); |
587 | #endif |
588 | #if 1 |
589 | // size1 is the number of comparisons to be made |
590 | const int size1 = size - 1; |
591 | for (int n = size1 / 8; n > 0; --n, first += 8) { |
592 | if (first[8] < first[7]) return false; |
593 | if (first[7] < first[6]) return false; |
594 | if (first[6] < first[5]) return false; |
595 | if (first[5] < first[4]) return false; |
596 | if (first[4] < first[3]) return false; |
597 | if (first[3] < first[2]) return false; |
598 | if (first[2] < first[1]) return false; |
599 | if (first[1] < first[0]) return false; |
600 | } |
601 | |
602 | switch (size1 % 8) { |
603 | case 7: if (first[7] < first[6]) return false; |
604 | case 6: if (first[6] < first[5]) return false; |
605 | case 5: if (first[5] < first[4]) return false; |
606 | case 4: if (first[4] < first[3]) return false; |
607 | case 3: if (first[3] < first[2]) return false; |
608 | case 2: if (first[2] < first[1]) return false; |
609 | case 1: if (first[1] < first[0]) return false; |
610 | case 0: break; |
611 | } |
612 | #else |
613 | const T* next = first; |
614 | const T* last = first + size; |
615 | for (++next; next != last; first = next, ++next) |
616 | if (*next < *first) |
617 | return false; |
618 | #endif |
619 | return true; |
620 | } |
621 | |
622 | //----------------------------------------------------------------------------- |
623 | |
624 | /** This helper function tests whether the entries of an array are sorted |
625 | according to operator<. The array is given by its first and "after |
626 | last" entry. */ |
627 | template <class T> inline bool |
628 | CoinIsSorted(const T* first, const T* last) |
629 | { |
630 | return CoinIsSorted(first, static_cast<int>(last - first)); |
631 | } |
632 | |
633 | //############################################################################# |
634 | |
635 | /** This helper function fills an array with the values init, init+1, init+2, |
636 | etc. For speed 8 entries are filled at a time. The array is given by a |
637 | pointer to its first entry and its size. */ |
638 | template <class T> inline void |
639 | CoinIotaN(T* first, const int size, T init) |
640 | { |
641 | if (size == 0) |
642 | return; |
643 | |
644 | #ifndef NDEBUG |
645 | if (size < 0) |
646 | throw CoinError("negative number of entries" , "CoinIotaN" , "" ); |
647 | #endif |
648 | #if 1 |
649 | for (int n = size / 8; n > 0; --n, first += 8, init += 8) { |
650 | first[0] = init; |
651 | first[1] = init + 1; |
652 | first[2] = init + 2; |
653 | first[3] = init + 3; |
654 | first[4] = init + 4; |
655 | first[5] = init + 5; |
656 | first[6] = init + 6; |
657 | first[7] = init + 7; |
658 | } |
659 | switch (size % 8) { |
660 | case 7: first[6] = init + 6; |
661 | case 6: first[5] = init + 5; |
662 | case 5: first[4] = init + 4; |
663 | case 4: first[3] = init + 3; |
664 | case 3: first[2] = init + 2; |
665 | case 2: first[1] = init + 1; |
666 | case 1: first[0] = init; |
667 | case 0: break; |
668 | } |
669 | #else |
670 | // Use Duff's device to fill |
671 | int n = (size + 7) / 8; |
672 | --first; |
673 | --init; |
674 | switch (size % 8) { |
675 | case 0: do{ *++first = ++init; |
676 | case 7: *++first = ++init; |
677 | case 6: *++first = ++init; |
678 | case 5: *++first = ++init; |
679 | case 4: *++first = ++init; |
680 | case 3: *++first = ++init; |
681 | case 2: *++first = ++init; |
682 | case 1: *++first = ++init; |
683 | }while(--n>0); |
684 | } |
685 | #endif |
686 | } |
687 | |
688 | //----------------------------------------------------------------------------- |
689 | |
690 | /** This helper function fills an array with the values init, init+1, init+2, |
691 | etc. For speed 8 entries are filled at a time. The array is given by its |
692 | first and "after last" entry. */ |
693 | template <class T> inline void |
694 | CoinIota(T* first, const T* last, T init) |
695 | { |
696 | CoinIotaN(first, last-first, init); |
697 | } |
698 | |
699 | //############################################################################# |
700 | |
701 | /** This helper function deletes certain entries from an array. The array is |
702 | given by pointers to its first and "after last" entry (first two |
703 | arguments). The positions of the entries to be deleted are given in the |
704 | integer array specified by the last two arguments (again, first and "after |
705 | last" entry). */ |
706 | template <class T> inline T * |
707 | CoinDeleteEntriesFromArray(T * arrayFirst, T * arrayLast, |
708 | const int * firstDelPos, const int * lastDelPos) |
709 | { |
710 | int delNum = static_cast<int>(lastDelPos - firstDelPos); |
711 | if (delNum == 0) |
712 | return arrayLast; |
713 | |
714 | if (delNum < 0) |
715 | throw CoinError("trying to delete negative number of entries" , |
716 | "CoinDeleteEntriesFromArray" , "" ); |
717 | |
718 | int * delSortedPos = nullptr; |
719 | if (! (CoinIsSorted(firstDelPos, lastDelPos) && |
720 | std::adjacent_find(firstDelPos, lastDelPos) == lastDelPos)) { |
721 | // the positions of the to be deleted is either not sorted or not unique |
722 | delSortedPos = new int[delNum]; |
723 | CoinDisjointCopy(firstDelPos, lastDelPos, delSortedPos); |
724 | std::sort(delSortedPos, delSortedPos + delNum); |
725 | delNum = static_cast<int>(std::unique(delSortedPos, |
726 | delSortedPos+delNum) - delSortedPos); |
727 | } |
728 | const int * delSorted = delSortedPos ? delSortedPos : firstDelPos; |
729 | |
730 | const int last = delNum - 1; |
731 | int size = delSorted[0]; |
732 | for (int i = 0; i < last; ++i) { |
733 | const int copyFirst = delSorted[i] + 1; |
734 | const int copyLast = delSorted[i+1]; |
735 | CoinCopy(arrayFirst + copyFirst, arrayFirst + copyLast, |
736 | arrayFirst + size); |
737 | size += copyLast - copyFirst; |
738 | } |
739 | const int copyFirst = delSorted[last] + 1; |
740 | const int copyLast = static_cast<int>(arrayLast - arrayFirst); |
741 | CoinCopy(arrayFirst + copyFirst, arrayFirst + copyLast, |
742 | arrayFirst + size); |
743 | size += copyLast - copyFirst; |
744 | |
745 | if (delSortedPos) |
746 | delete[] delSortedPos; |
747 | |
748 | return arrayFirst + size; |
749 | } |
750 | |
751 | //############################################################################# |
752 | |
753 | #define COIN_OWN_RANDOM_32 |
754 | |
755 | #if defined COIN_OWN_RANDOM_32 |
756 | /* Thanks to Stefano Gliozzi for providing an operating system |
757 | independent random number generator. */ |
758 | |
759 | /*! \brief Return a random number between 0 and 1 |
760 | |
761 | A platform-independent linear congruential generator. For a given seed, the |
762 | generated sequence is always the same regardless of the (32-bit) |
763 | architecture. This allows to build & test in different environments, getting |
764 | in most cases the same optimization path. |
765 | |
766 | Set \p isSeed to true and supply an integer seed to set the seed |
767 | (vid. #CoinSeedRandom) |
768 | |
769 | \todo Anyone want to volunteer an upgrade for 64-bit architectures? |
770 | */ |
771 | inline double CoinDrand48 (bool isSeed = false, unsigned int seed = 1) |
772 | { |
773 | static unsigned int last = 123456; |
774 | if (isSeed) { |
775 | last = seed; |
776 | } else { |
777 | last = 1664525*last+1013904223; |
778 | return ((static_cast<double> (last))/4294967296.0); |
779 | } |
780 | return (0.0); |
781 | } |
782 | |
783 | /// Set the seed for the random number generator |
784 | inline void CoinSeedRandom(int iseed) |
785 | { |
786 | CoinDrand48(true, iseed); |
787 | } |
788 | |
789 | #else // COIN_OWN_RANDOM_32 |
790 | |
791 | #if defined(_MSC_VER) || defined(__MINGW32__) || defined(__CYGWIN32__) |
792 | |
793 | /// Return a random number between 0 and 1 |
794 | inline double CoinDrand48() { return rand() / (double) RAND_MAX; } |
795 | /// Set the seed for the random number generator |
796 | inline void CoinSeedRandom(int iseed) { srand(iseed + 69822); } |
797 | |
798 | #else |
799 | |
800 | /// Return a random number between 0 and 1 |
801 | inline double CoinDrand48() { return drand48(); } |
802 | /// Set the seed for the random number generator |
803 | inline void CoinSeedRandom(int iseed) { srand48(iseed + 69822); } |
804 | |
805 | #endif |
806 | |
807 | #endif // COIN_OWN_RANDOM_32 |
808 | |
809 | //############################################################################# |
810 | |
811 | /** This function figures out whether file names should contain slashes or |
812 | backslashes as directory separator */ |
813 | inline char CoinFindDirSeparator() |
814 | { |
815 | int size = 1000; |
816 | char* buf = nullptr; |
817 | while (true) { |
818 | buf = new char[size]; |
819 | if (getcwd(buf, size)) |
820 | break; |
821 | delete[] buf; |
822 | buf = nullptr; |
823 | size = 2*size; |
824 | } |
825 | // if first char is '/' then it's unix and the dirsep is '/'. otherwise we |
826 | // assume it's dos and the dirsep is '\' |
827 | char dirsep = buf[0] == '/' ? '/' : '\\'; |
828 | delete[] buf; |
829 | return dirsep; |
830 | } |
831 | //############################################################################# |
832 | |
833 | inline int CoinStrNCaseCmp(const char* s0, const char* s1, |
834 | const size_t len) |
835 | { |
836 | for (size_t i = 0; i < len; ++i) { |
837 | if (s0[i] == 0) { |
838 | return s1[i] == 0 ? 0 : -1; |
839 | } |
840 | if (s1[i] == 0) { |
841 | return 1; |
842 | } |
843 | const int c0 = tolower(s0[i]); |
844 | const int c1 = tolower(s1[i]); |
845 | if (c0 < c1) |
846 | return -1; |
847 | if (c0 > c1) |
848 | return 1; |
849 | } |
850 | return 0; |
851 | } |
852 | |
853 | //############################################################################# |
854 | |
855 | /// Swap the arguments. |
856 | template <class T> inline void CoinSwap (T &x, T &y) |
857 | { |
858 | T t = x; |
859 | x = y; |
860 | y = t; |
861 | } |
862 | |
863 | //############################################################################# |
864 | |
865 | /** This helper function copies an array to file |
866 | Returns 0 if OK, 1 if bad write. |
867 | */ |
868 | |
869 | template <class T> inline int |
870 | CoinToFile( const T* array, CoinBigIndex size, FILE * fp) |
871 | { |
872 | CoinBigIndex numberWritten; |
873 | if (array&&size) { |
874 | numberWritten = |
875 | static_cast<CoinBigIndex>(fwrite(&size,sizeof(int),1,fp)); |
876 | if (numberWritten!=1) |
877 | return 1; |
878 | numberWritten = |
879 | static_cast<CoinBigIndex>(fwrite(array,sizeof(T),size_t(size),fp)); |
880 | if (numberWritten!=size) |
881 | return 1; |
882 | } else { |
883 | size = 0; |
884 | numberWritten = |
885 | static_cast<CoinBigIndex>(fwrite(&size,sizeof(int),1,fp)); |
886 | if (numberWritten!=1) |
887 | return 1; |
888 | } |
889 | return 0; |
890 | } |
891 | |
892 | //############################################################################# |
893 | |
894 | /** This helper function copies an array from file and creates with new. |
895 | Passed in array is ignored i.e. not deleted. |
896 | But if NULL and size does not match and newSize 0 then leaves as NULL and 0 |
897 | Returns 0 if OK, 1 if bad read, 2 if size did not match. |
898 | */ |
899 | |
900 | template <class T> inline int |
901 | CoinFromFile( T* &array, CoinBigIndex size, FILE * fp, CoinBigIndex & newSize) |
902 | { |
903 | CoinBigIndex numberRead; |
904 | numberRead = |
905 | static_cast<CoinBigIndex>(fread(&newSize,sizeof(int),1,fp)); |
906 | if (numberRead!=1) |
907 | return 1; |
908 | int returnCode=0; |
909 | if (size!=newSize&&(newSize||array)) |
910 | returnCode=2; |
911 | if (newSize) { |
912 | array = new T [newSize]; |
913 | numberRead = |
914 | static_cast<CoinBigIndex>(fread(array,sizeof(T),newSize,fp)); |
915 | if (numberRead!=newSize) |
916 | returnCode=1; |
917 | } else { |
918 | array = NULL; |
919 | } |
920 | return returnCode; |
921 | } |
922 | |
923 | //############################################################################# |
924 | |
925 | /// Cube Root |
926 | #if 0 |
927 | inline double CoinCbrt(double x) |
928 | { |
929 | #if defined(_MSC_VER) |
930 | return pow(x,(1./3.)); |
931 | #else |
932 | return cbrt(x); |
933 | #endif |
934 | } |
935 | #endif |
936 | |
937 | //----------------------------------------------------------------------------- |
938 | |
939 | /// This helper returns "sizeof" as an int |
940 | #define CoinSizeofAsInt(type) (static_cast<int>(sizeof(type))) |
941 | /// This helper returns "strlen" as an int |
942 | inline int |
943 | CoinStrlenAsInt(const char * string) |
944 | { |
945 | return static_cast<int>(strlen(string)); |
946 | } |
947 | |
948 | /** Class for thread specific random numbers |
949 | */ |
950 | #if defined COIN_OWN_RANDOM_32 |
951 | class CoinThreadRandom { |
952 | public: |
953 | /**@name Constructors, destructor */ |
954 | |
955 | //@{ |
956 | /** Default constructor. */ |
957 | CoinThreadRandom() |
958 | { seed_=12345678;} |
959 | /** Constructor wih seed. */ |
960 | CoinThreadRandom(int seed) |
961 | { |
962 | seed_ = seed; |
963 | } |
964 | /** Destructor */ |
965 | ~CoinThreadRandom() {} |
966 | // Copy |
967 | CoinThreadRandom(const CoinThreadRandom & rhs) |
968 | { seed_ = rhs.seed_;} |
969 | // Assignment |
970 | CoinThreadRandom& operator=(const CoinThreadRandom & rhs) |
971 | { |
972 | if (this != &rhs) { |
973 | seed_ = rhs.seed_; |
974 | } |
975 | return *this; |
976 | } |
977 | |
978 | //@} |
979 | |
980 | /**@name Sets/gets */ |
981 | |
982 | //@{ |
983 | /** Set seed. */ |
984 | inline void setSeed(int seed) |
985 | { |
986 | seed_ = seed; |
987 | } |
988 | /** Get seed. */ |
989 | inline unsigned int getSeed() const |
990 | { |
991 | return seed_; |
992 | } |
993 | /// return a random number |
994 | inline double randomDouble() const |
995 | { |
996 | double retVal; |
997 | seed_ = 1664525*(seed_)+1013904223; |
998 | retVal = ((static_cast<double> (seed_))/4294967296.0); |
999 | return retVal; |
1000 | } |
1001 | //@} |
1002 | |
1003 | |
1004 | protected: |
1005 | /**@name Data members |
1006 | The data members are protected to allow access for derived classes. */ |
1007 | //@{ |
1008 | /// Current seed |
1009 | mutable unsigned int seed_; |
1010 | //@} |
1011 | }; |
1012 | #else |
1013 | class CoinThreadRandom { |
1014 | public: |
1015 | /**@name Constructors, destructor */ |
1016 | |
1017 | //@{ |
1018 | /** Default constructor. */ |
1019 | CoinThreadRandom() |
1020 | { seed_[0]=50000;seed_[1]=40000;seed_[2]=30000;} |
1021 | /** Constructor wih seed. */ |
1022 | CoinThreadRandom(const unsigned short seed[3]) |
1023 | { memcpy(seed_,seed,3*sizeof(unsigned short));} |
1024 | /** Constructor wih seed. */ |
1025 | CoinThreadRandom(int seed) |
1026 | { |
1027 | union { int i[2]; unsigned short int s[4];} put; |
1028 | put.i[0]=seed; |
1029 | put.i[1]=seed; |
1030 | memcpy(seed_,put.s,3*sizeof(unsigned short)); |
1031 | } |
1032 | /** Destructor */ |
1033 | ~CoinThreadRandom() {} |
1034 | // Copy |
1035 | CoinThreadRandom(const CoinThreadRandom & rhs) |
1036 | { memcpy(seed_,rhs.seed_,3*sizeof(unsigned short));} |
1037 | // Assignment |
1038 | CoinThreadRandom& operator=(const CoinThreadRandom & rhs) |
1039 | { |
1040 | if (this != &rhs) { |
1041 | memcpy(seed_,rhs.seed_,3*sizeof(unsigned short)); |
1042 | } |
1043 | return *this; |
1044 | } |
1045 | |
1046 | //@} |
1047 | |
1048 | /**@name Sets/gets */ |
1049 | |
1050 | //@{ |
1051 | /** Set seed. */ |
1052 | inline void setSeed(const unsigned short seed[3]) |
1053 | { memcpy(seed_,seed,3*sizeof(unsigned short));} |
1054 | /** Set seed. */ |
1055 | inline void setSeed(int seed) |
1056 | { |
1057 | union { int i[2]; unsigned short int s[4];} put; |
1058 | put.i[0]=seed; |
1059 | put.i[1]=seed; |
1060 | memcpy(seed_,put.s,3*sizeof(unsigned short)); |
1061 | } |
1062 | /// return a random number |
1063 | inline double randomDouble() const |
1064 | { |
1065 | double retVal; |
1066 | #if defined(_MSC_VER) || defined(__MINGW32__) || defined(__CYGWIN32__) |
1067 | retVal=rand(); |
1068 | retVal=retVal/(double) RAND_MAX; |
1069 | #else |
1070 | retVal = erand48(seed_); |
1071 | #endif |
1072 | return retVal; |
1073 | } |
1074 | //@} |
1075 | |
1076 | |
1077 | protected: |
1078 | /**@name Data members |
1079 | The data members are protected to allow access for derived classes. */ |
1080 | //@{ |
1081 | /// Current seed |
1082 | mutable unsigned short seed_[3]; |
1083 | //@} |
1084 | }; |
1085 | #endif |
1086 | #ifndef COIN_DETAIL |
1087 | #define COIN_DETAIL_PRINT(s) {} |
1088 | #else |
1089 | #define COIN_DETAIL_PRINT(s) s |
1090 | #endif |
1091 | #endif |
1092 | |