1 : // Copyright (C) 2000, International Business Machines
2 : // Corporation and others. All Rights Reserved.
3 :
4 : #ifndef CoinHelperFunctions_H
5 : #define CoinHelperFunctions_H
6 : #if defined(_MSC_VER)
7 : # include <direct.h>
8 : # define getcwd _getcwd
9 : #else
10 : # include <unistd.h>
11 : #endif
12 :
13 : #include <cstdio>
14 : #include "CoinError.hpp"
15 : #include "CoinFinite.hpp"
16 : //#############################################################################
17 :
18 : /** This helper function copies an array to another location using Duff's
19 : device (for a speedup of ~2). The arrays are given by pointers to their
20 : first entries and by the size of the source array. Overlapping arrays are
21 : handled correctly. */
22 :
23 : template <class T> inline void
24 78103 : CoinCopyN(register const T* from, const int size, register T* to)
25 : {
26 78103 : if (size == 0 || from == to)
27 0 : return;
28 :
29 78103 : if (size < 0)
30 0 : throw CoinError("trying to copy negative number of entries",
31 : "CoinCopyN", "");
32 :
33 78103 : register int n = (size + 7) / 8;
34 78103 : if (to > from) {
35 402 : register const T* downfrom = from + size;
36 402 : register T* downto = to + size;
37 : // Use Duff's device to copy
38 402 : switch (size % 8) {
39 9306 : case 0: do{ *--downto = *--downfrom;
40 4623 : case 7: *--downto = *--downfrom;
41 4623 : case 6: *--downto = *--downfrom;
42 4623 : case 5: *--downto = *--downfrom;
43 4623 : case 4: *--downto = *--downfrom;
44 4682 : case 3: *--downto = *--downfrom;
45 4683 : case 2: *--downto = *--downfrom;
46 4683 : case 1: *--downto = *--downfrom;
47 : }while(--n>0);
48 : }
49 : } else {
50 : // Use Duff's device to copy
51 77701 : --from;
52 77701 : --to;
53 77701 : switch (size % 8) {
54 160163 : case 0: do{ *++to = *++from;
55 44630 : case 7: *++to = *++from;
56 48375 : case 6: *++to = *++from;
57 54099 : case 5: *++to = *++from;
58 61201 : case 4: *++to = *++from;
59 87726 : case 3: *++to = *++from;
60 114720 : case 2: *++to = *++from;
61 117652 : case 1: *++to = *++from;
62 : }while(--n>0);
63 : }
64 : }
65 : }
66 :
67 : //-----------------------------------------------------------------------------
68 :
69 : /** This helper function copies an array to another location using Duff's
70 : device (for a speedup of ~2). The source array is given by its first and
71 : "after last" entry; the target array is given by its first entry.
72 : Overlapping arrays are handled correctly. */
73 : template <class T> inline void
74 : CoinCopy(register const T* first, register const T* last, register T* to)
75 : {
76 : CoinCopyN(first, last - first, to);
77 : }
78 :
79 : //-----------------------------------------------------------------------------
80 :
81 : /** This helper function copies an array to another location. The two arrays
82 : must not overlap (otherwise an exception is thrown). For speed 8 entries
83 : are copied at a time. The arrays are given by pointers to their first
84 : entries and by the size of the source array.
85 :
86 : Note JJF - the speed claim seems to be false on IA32 so I have added
87 : CoinMemcpyN which can be used for atomic data */
88 : template <class T> inline void
89 : CoinDisjointCopyN(register const T* from, const int size, register T* to)
90 : {
91 : #ifndef _MSC_VER
92 : if (size == 0 || from == to)
93 : return;
94 :
95 : if (size < 0)
96 : throw CoinError("trying to copy negative number of entries",
97 : "CoinDisjointCopyN", "");
98 :
99 : #if 0
100 : /* There is no point to do this test. If to and from are from different
101 : blocks then dist is undefined, so this can crash correct code. It's
102 : better to trust the user that the arrays are really disjoint. */
103 : const long dist = to - from;
104 : if (-size < dist && dist < size)
105 : throw CoinError("overlapping arrays", "CoinDisjointCopyN", "");
106 : #endif
107 :
108 : for (register int n = size / 8; n > 0; --n, from += 8, to += 8) {
109 : to[0] = from[0];
110 : to[1] = from[1];
111 : to[2] = from[2];
112 : to[3] = from[3];
113 : to[4] = from[4];
114 : to[5] = from[5];
115 : to[6] = from[6];
116 : to[7] = from[7];
117 : }
118 : switch (size % 8) {
119 : case 7: to[6] = from[6];
120 : case 6: to[5] = from[5];
121 : case 5: to[4] = from[4];
122 : case 4: to[3] = from[3];
123 : case 3: to[2] = from[2];
124 : case 2: to[1] = from[1];
125 : case 1: to[0] = from[0];
126 : case 0: break;
127 : }
128 : #else
129 : CoinCopyN(from, size, to);
130 : #endif
131 : }
132 :
133 : //-----------------------------------------------------------------------------
134 :
135 : /** This helper function copies an array to another location. The two arrays
136 : must not overlap (otherwise an exception is thrown). For speed 8 entries
137 : are copied at a time. The source array is given by its first and "after
138 : last" entry; the target array is given by its first entry. */
139 : template <class T> inline void
140 : CoinDisjointCopy(register const T* first, register const T* last,
141 : register T* to)
142 : {
143 : CoinDisjointCopyN(first, static_cast<int>(last - first), to);
144 : }
145 :
146 : //-----------------------------------------------------------------------------
147 :
148 : /*! \brief Return an array of length \p size filled with input from \p array,
149 : or null if \p array is null.
150 : */
151 :
152 : template <class T> inline T*
153 : CoinCopyOfArray( const T * array, const int size)
154 : {
155 : if (array) {
156 : T * arrayNew = new T[size];
157 : memcpy(arrayNew,array,size*sizeof(T));
158 : return arrayNew;
159 : } else {
160 : return NULL;
161 : }
162 : }
163 :
164 : /*! \brief Return an array of length \p size filled with input from \p array,
165 : or filled with (scalar) \p value if \p array is null
166 : */
167 :
168 : template <class T> inline T*
169 : CoinCopyOfArray( const T * array, const int size, T value)
170 : {
171 : T * arrayNew = new T[size];
172 : if (array) {
173 : memcpy(arrayNew,array,size*sizeof(T));
174 : } else {
175 : int i;
176 : for (i=0;i<size;i++)
177 : arrayNew[i] = value;
178 : }
179 : return arrayNew;
180 : }
181 :
182 :
183 : /*! \brief Return an array of length \p size filled with input from \p array,
184 : or filled with zero if \p array is null
185 : */
186 :
187 : template <class T> inline T*
188 : CoinCopyOfArrayOrZero( const T * array , const int size)
189 : {
190 : T * arrayNew = new T[size];
191 : if (array) {
192 : memcpy(arrayNew,array,size*sizeof(T));
193 : } else {
194 : memset(arrayNew,0,size*sizeof(T));
195 : }
196 : return arrayNew;
197 : }
198 :
199 :
200 : //-----------------------------------------------------------------------------
201 :
202 : /** This helper function copies an array to another location. The two arrays
203 : must not overlap (otherwise an exception is thrown). For speed 8 entries
204 : are copied at a time. The arrays are given by pointers to their first
205 : entries and by the size of the source array.
206 :
207 : Note JJF - the speed claim seems to be false on IA32 so I have added
208 : alternative coding if USE_MEMCPY defined*/
209 : template <class T> inline void
210 : CoinMemcpyN(register const T* from, const int size, register T* to)
211 : {
212 : #ifndef _MSC_VER
213 : #ifdef USE_MEMCPY
214 : // Use memcpy - seems a lot faster on Intel with gcc
215 : #ifndef NDEBUG
216 : // Some debug so check
217 : if (size < 0)
218 : throw CoinError("trying to copy negative number of entries",
219 : "CoinMemcpyN", "");
220 :
221 : #if 0
222 : /* There is no point to do this test. If to and from are from different
223 : blocks then dist is undefined, so this can crash correct code. It's
224 : better to trust the user that the arrays are really disjoint. */
225 : const long dist = to - from;
226 : if (-size < dist && dist < size)
227 : throw CoinError("overlapping arrays", "CoinMemcpyN", "");
228 : #endif
229 : #endif
230 : memcpy(to,from,size*sizeof(T));
231 : #else
232 : if (size == 0 || from == to)
233 : return;
234 :
235 : if (size < 0)
236 : throw CoinError("trying to copy negative number of entries",
237 : "CoinMemcpyN", "");
238 :
239 : #if 0
240 : /* There is no point to do this test. If to and from are from different
241 : blocks then dist is undefined, so this can crash correct code. It's
242 : better to trust the user that the arrays are really disjoint. */
243 : const long dist = to - from;
244 : if (-size < dist && dist < size)
245 : throw CoinError("overlapping arrays", "CoinMemcpyN", "");
246 : #endif
247 :
248 : for (register int n = size / 8; n > 0; --n, from += 8, to += 8) {
249 : to[0] = from[0];
250 : to[1] = from[1];
251 : to[2] = from[2];
252 : to[3] = from[3];
253 : to[4] = from[4];
254 : to[5] = from[5];
255 : to[6] = from[6];
256 : to[7] = from[7];
257 : }
258 : switch (size % 8) {
259 : case 7: to[6] = from[6];
260 : case 6: to[5] = from[5];
261 : case 5: to[4] = from[4];
262 : case 4: to[3] = from[3];
263 : case 3: to[2] = from[2];
264 : case 2: to[1] = from[1];
265 : case 1: to[0] = from[0];
266 : case 0: break;
267 : }
268 : #endif
269 : #else
270 : CoinCopyN(from, size, to);
271 : #endif
272 : }
273 :
274 : //-----------------------------------------------------------------------------
275 :
276 : /** This helper function copies an array to another location. The two arrays
277 : must not overlap (otherwise an exception is thrown). For speed 8 entries
278 : are copied at a time. The source array is given by its first and "after
279 : last" entry; the target array is given by its first entry. */
280 : template <class T> inline void
281 : CoinMemcpy(register const T* first, register const T* last,
282 : register T* to)
283 : {
284 : CoinMemcpyN(first, static_cast<int>(last - first), to);
285 : }
286 :
287 : //#############################################################################
288 :
289 : /** This helper function fills an array with a given value. For speed 8 entries
290 : are filled at a time. The array is given by a pointer to its first entry
291 : and its size.
292 :
293 : Note JJF - the speed claim seems to be false on IA32 so I have added
294 : CoinZero to allow for memset. */
295 : template <class T> inline void
296 709 : CoinFillN(register T* to, const int size, register const T value)
297 : {
298 709 : if (size == 0)
299 0 : return;
300 :
301 709 : if (size < 0)
302 0 : throw CoinError("trying to fill negative number of entries",
303 : "CoinFillN", "");
304 :
305 : #if 1
306 8977 : for (register int n = size / 8; n > 0; --n, to += 8) {
307 8268 : to[0] = value;
308 8268 : to[1] = value;
309 8268 : to[2] = value;
310 8268 : to[3] = value;
311 8268 : to[4] = value;
312 8268 : to[5] = value;
313 8268 : to[6] = value;
314 8268 : to[7] = value;
315 : }
316 709 : switch (size % 8) {
317 171 : case 7: to[6] = value;
318 259 : case 6: to[5] = value;
319 337 : case 5: to[4] = value;
320 378 : case 4: to[3] = value;
321 421 : case 3: to[2] = value;
322 463 : case 2: to[1] = value;
323 548 : case 1: to[0] = value;
324 : case 0: break;
325 : }
326 : #else
327 : // Use Duff's device to fill
328 : register int n = (size + 7) / 8;
329 : --to;
330 : switch (size % 8) {
331 : case 0: do{ *++to = value;
332 : case 7: *++to = value;
333 : case 6: *++to = value;
334 : case 5: *++to = value;
335 : case 4: *++to = value;
336 : case 3: *++to = value;
337 : case 2: *++to = value;
338 : case 1: *++to = value;
339 : }while(--n>0);
340 : }
341 : #endif
342 : }
343 :
344 : //-----------------------------------------------------------------------------
345 :
346 : /** This helper function fills an array with a given value. For speed 8
347 : entries are filled at a time. The array is given by its first and "after
348 : last" entry. */
349 : template <class T> inline void
350 : CoinFill(register T* first, register T* last, const T value)
351 : {
352 : CoinFillN(first, last - first, value);
353 : }
354 :
355 : //#############################################################################
356 :
357 : /** This helper function fills an array with zero. For speed 8 entries
358 : are filled at a time. The array is given by a pointer to its first entry
359 : and its size.
360 :
361 : Note JJF - the speed claim seems to be false on IA32 so I have allowed
362 : for memset as an alternative */
363 : template <class T> inline void
364 : CoinZeroN(register T* to, const int size)
365 : {
366 : #ifdef USE_MEMCPY
367 : // Use memset - seems faster on Intel with gcc
368 : #ifndef NDEBUG
369 : // Some debug so check
370 : if (size < 0)
371 : throw CoinError("trying to fill negative number of entries",
372 : "CoinZeroN", "");
373 : #endif
374 : memset(to,0,size*sizeof(T));
375 : #else
376 : if (size == 0)
377 : return;
378 :
379 : if (size < 0)
380 : throw CoinError("trying to fill negative number of entries",
381 : "CoinZeroN", "");
382 : #if 1
383 : for (register int n = size / 8; n > 0; --n, to += 8) {
384 : to[0] = 0;
385 : to[1] = 0;
386 : to[2] = 0;
387 : to[3] = 0;
388 : to[4] = 0;
389 : to[5] = 0;
390 : to[6] = 0;
391 : to[7] = 0;
392 : }
393 : switch (size % 8) {
394 : case 7: to[6] = 0;
395 : case 6: to[5] = 0;
396 : case 5: to[4] = 0;
397 : case 4: to[3] = 0;
398 : case 3: to[2] = 0;
399 : case 2: to[1] = 0;
400 : case 1: to[0] = 0;
401 : case 0: break;
402 : }
403 : #else
404 : // Use Duff's device to fill
405 : register int n = (size + 7) / 8;
406 : --to;
407 : switch (size % 8) {
408 : case 0: do{ *++to = 0;
409 : case 7: *++to = 0;
410 : case 6: *++to = 0;
411 : case 5: *++to = 0;
412 : case 4: *++to = 0;
413 : case 3: *++to = 0;
414 : case 2: *++to = 0;
415 : case 1: *++to = 0;
416 : }while(--n>0);
417 : }
418 : #endif
419 : #endif
420 : }
421 : /// This Debug helper function checks an array is all zero
422 : inline void
423 : CoinCheckDoubleZero(double * to, const int size)
424 : {
425 : int n=0;
426 : for (int j=0;j<size;j++) {
427 : if (to[j])
428 : n++;
429 : }
430 : if (n) {
431 : printf("array of length %d should be zero has %d nonzero\n",size,n);
432 : }
433 : }
434 : /// This Debug helper function checks an array is all zero
435 : inline void
436 : CoinCheckIntZero(int * to, const int size)
437 : {
438 : int n=0;
439 : for (int j=0;j<size;j++) {
440 : if (to[j])
441 : n++;
442 : }
443 : if (n) {
444 : printf("array of length %d should be zero has %d nonzero\n",size,n);
445 : }
446 : }
447 :
448 : //-----------------------------------------------------------------------------
449 :
450 : /** This helper function fills an array with a given value. For speed 8
451 : entries are filled at a time. The array is given by its first and "after
452 : last" entry. */
453 : template <class T> inline void
454 : CoinZero(register T* first, register T* last)
455 : {
456 : CoinZeroN(first, last - first);
457 : }
458 :
459 : //#############################################################################
460 :
461 : /** Return the larger (according to <code>operator<()</code> of the arguments.
462 : This function was introduced because for some reason compiler tend to
463 : handle the <code>max()</code> function differently. */
464 : template <class T> inline T
465 68976708 : CoinMax(register const T x1, register const T x2)
466 : {
467 68976708 : return (x1 > x2) ? x1 : x2;
468 : }
469 :
470 : //-----------------------------------------------------------------------------
471 :
472 : /** Return the smaller (according to <code>operator<()</code> of the arguments.
473 : This function was introduced because for some reason compiler tend to
474 : handle the min() function differently. */
475 : template <class T> inline T
476 : CoinMin(register const T x1, register const T x2)
477 : {
478 : return (x1 < x2) ? x1 : x2;
479 : }
480 :
481 : //-----------------------------------------------------------------------------
482 :
483 : /** Return the absolute value of the argument. This function was introduced
484 : because for some reason compiler tend to handle the abs() function
485 : differently. */
486 : template <class T> inline T
487 : CoinAbs(const T value)
488 : {
489 : return value<0 ? -value : value;
490 : }
491 :
492 : //#############################################################################
493 :
494 : /** This helper function tests whether the entries of an array are sorted
495 : according to operator<. The array is given by a pointer to its first entry
496 : and by its size. */
497 : template <class T> inline bool
498 : CoinIsSorted(register const T* first, const int size)
499 : {
500 : if (size == 0)
501 : return true;
502 :
503 : if (size < 0)
504 : throw CoinError("negative number of entries", "CoinIsSorted", "");
505 :
506 : #if 1
507 : // size1 is the number of comparisons to be made
508 : const int size1 = size - 1;
509 : for (register int n = size1 / 8; n > 0; --n, first += 8) {
510 : if (first[8] < first[7]) return false;
511 : if (first[7] < first[6]) return false;
512 : if (first[6] < first[5]) return false;
513 : if (first[5] < first[4]) return false;
514 : if (first[4] < first[3]) return false;
515 : if (first[3] < first[2]) return false;
516 : if (first[2] < first[1]) return false;
517 : if (first[1] < first[0]) return false;
518 : }
519 :
520 : switch (size1 % 8) {
521 : case 7: if (first[7] < first[6]) return false;
522 : case 6: if (first[6] < first[5]) return false;
523 : case 5: if (first[5] < first[4]) return false;
524 : case 4: if (first[4] < first[3]) return false;
525 : case 3: if (first[3] < first[2]) return false;
526 : case 2: if (first[2] < first[1]) return false;
527 : case 1: if (first[1] < first[0]) return false;
528 : case 0: break;
529 : }
530 : #else
531 : register const T* next = first;
532 : register const T* last = first + size;
533 : for (++next; next != last; first = next, ++next)
534 : if (*next < *first)
535 : return false;
536 : #endif
537 : return true;
538 : }
539 :
540 : //-----------------------------------------------------------------------------
541 :
542 : /** This helper function tests whether the entries of an array are sorted
543 : according to operator<. The array is given by its first and "after
544 : last" entry. */
545 : template <class T> inline bool
546 : CoinIsSorted(register const T* first, register const T* last)
547 : {
548 : return CoinIsSorted(first, static_cast<int>(last - first));
549 : }
550 :
551 : //#############################################################################
552 :
553 : /** This helper function fills an array with the values init, init+1, init+2,
554 : etc. For speed 8 entries are filled at a time. The array is given by a
555 : pointer to its first entry and its size. */
556 : template <class T> inline void
557 : CoinIotaN(register T* first, const int size, register T init)
558 : {
559 : if (size == 0)
560 : return;
561 :
562 : if (size < 0)
563 : throw CoinError("negative number of entries", "CoinIotaN", "");
564 :
565 : #if 1
566 : for (register int n = size / 8; n > 0; --n, first += 8, init += 8) {
567 : first[0] = init;
568 : first[1] = init + 1;
569 : first[2] = init + 2;
570 : first[3] = init + 3;
571 : first[4] = init + 4;
572 : first[5] = init + 5;
573 : first[6] = init + 6;
574 : first[7] = init + 7;
575 : }
576 : switch (size % 8) {
577 : case 7: first[6] = init + 6;
578 : case 6: first[5] = init + 5;
579 : case 5: first[4] = init + 4;
580 : case 4: first[3] = init + 3;
581 : case 3: first[2] = init + 2;
582 : case 2: first[1] = init + 1;
583 : case 1: first[0] = init;
584 : case 0: break;
585 : }
586 : #else
587 : // Use Duff's device to fill
588 : register int n = (size + 7) / 8;
589 : --first;
590 : --init;
591 : switch (size % 8) {
592 : case 0: do{ *++first = ++init;
593 : case 7: *++first = ++init;
594 : case 6: *++first = ++init;
595 : case 5: *++first = ++init;
596 : case 4: *++first = ++init;
597 : case 3: *++first = ++init;
598 : case 2: *++first = ++init;
599 : case 1: *++first = ++init;
600 : }while(--n>0);
601 : }
602 : #endif
603 : }
604 :
605 : //-----------------------------------------------------------------------------
606 :
607 : /** This helper function fills an array with the values init, init+1, init+2,
608 : etc. For speed 8 entries are filled at a time. The array is given by its
609 : first and "after last" entry. */
610 : template <class T> inline void
611 : CoinIota(T* first, const T* last, T init)
612 : {
613 : CoinIotaN(first, last-first, init);
614 : }
615 :
616 : //#############################################################################
617 :
618 : /** This helper function deletes certain entries from an array. The array is
619 : given by pointers to its first and "after last" entry (first two
620 : arguments). The positions of the entries to be deleted are given in the
621 : integer array specified by the last two arguments (again, first and "after
622 : last" entry). */
623 : template <class T> inline T *
624 : CoinDeleteEntriesFromArray(register T * arrayFirst, register T * arrayLast,
625 : const int * firstDelPos, const int * lastDelPos)
626 : {
627 : int delNum = lastDelPos - firstDelPos;
628 : if (delNum == 0)
629 : return arrayLast;
630 :
631 : if (delNum < 0)
632 : throw CoinError("trying to delete negative number of entries",
633 : "CoinDeleteEntriesFromArray", "");
634 :
635 : int * delSortedPos = NULL;
636 : if (! (CoinIsSorted(firstDelPos, lastDelPos) &&
637 : std::adjacent_find(firstDelPos, lastDelPos) == lastDelPos)) {
638 : // the positions of the to be deleted is either not sorted or not unique
639 : delSortedPos = new int[delNum];
640 : CoinDisjointCopy(firstDelPos, lastDelPos, delSortedPos);
641 : std::sort(delSortedPos, delSortedPos + delNum);
642 : delNum = std::unique(delSortedPos, delSortedPos + delNum) - delSortedPos;
643 : }
644 : const int * delSorted = delSortedPos ? delSortedPos : firstDelPos;
645 :
646 : const int last = delNum - 1;
647 : int size = delSorted[0];
648 : for (int i = 0; i < last; ++i) {
649 : const int copyFirst = delSorted[i] + 1;
650 : const int copyLast = delSorted[i+1];
651 : CoinCopy(arrayFirst + copyFirst, arrayFirst + copyLast,
652 : arrayFirst + size);
653 : size += copyLast - copyFirst;
654 : }
655 : const int copyFirst = delSorted[last] + 1;
656 : const int copyLast = arrayLast - arrayFirst;
657 : CoinCopy(arrayFirst + copyFirst, arrayFirst + copyLast,
658 : arrayFirst + size);
659 : size += copyLast - copyFirst;
660 :
661 : if (delSortedPos)
662 : delete[] delSortedPos;
663 :
664 : return arrayFirst + size;
665 : }
666 :
667 : //#############################################################################
668 : /* Thanks to Stefano Gliozzi for providing an operating system
669 : independent random number generator. */
670 : /// Seed random number generator
671 : inline void CoinSeedRandom(int iseed)
672 : {
673 : #if defined COIN_OWN_RANDOM_32
674 : double CoinDrand48(bool isSeed = false, unsigned long seed=1);
675 : CoinDrand48(true, iseed);
676 : #else
677 : int jseed;
678 : jseed = iseed + 69822;
679 : #if defined(_MSC_VER) || defined(__MINGW32__) || defined(__CYGWIN32__)
680 : srand(jseed);
681 : #else
682 : srand48(jseed);
683 : #endif
684 : #endif // end else COIN_OWN_RANDOM
685 : }
686 :
687 : /// Return random number between 0 and 1.
688 : #if defined COIN_OWN_RANDOM_32
689 : // linear congruential generator. given the seed, the generated numbers are
690 : // always the same regardless the (32 bit) architecture. This allows to
691 : // build & test in different environments (i.e. Wintel, Linux/Intel AIX Power5)
692 : // getting in most cases the same optimization path.
693 : inline double CoinDrand48(bool isSeed = false, unsigned long seed=1)
694 : {
695 : static unsigned last;
696 : if (isSeed) {
697 : last = seed;
698 : } else {
699 : last = 1664525*last+1013904223;
700 : return (((double) last)/4294967296.0);
701 : }
702 : return(0.0);
703 : }
704 : #else
705 : inline double CoinDrand48()
706 : {
707 : double retVal;
708 : #if defined(_MSC_VER) || defined(__MINGW32__) || defined(__CYGWIN32__)
709 : retVal=rand();
710 : retVal=retVal/(double) RAND_MAX;
711 : #else
712 : retVal = drand48();
713 : #endif
714 : return retVal;
715 : }
716 : #endif
717 :
718 : //#############################################################################
719 :
720 : /** This function figures out whether file names should contain slashes or
721 : backslashes as directory separator */
722 : inline char CoinFindDirSeparator()
723 : {
724 : int size = 1000;
725 : char* buf = 0;
726 : while (true) {
727 : buf = new char[size];
728 : if (getcwd(buf, size))
729 : break;
730 : delete[] buf;
731 : buf = 0;
732 : size = 2*size;
733 : }
734 : // if first char is '/' then it's unix and the dirsep is '/'. otherwise we
735 : // assume it's dos and the dirsep is '\'
736 : char dirsep = buf[0] == '/' ? '/' : '\\';
737 : delete[] buf;
738 : return dirsep;
739 : }
740 : //#############################################################################
741 :
742 : inline int CoinStrNCaseCmp(const char* s0, const char* s1,
743 : const size_t len)
744 : {
745 : for (size_t i = 0; i < len; ++i) {
746 : if (s0[i] == 0) {
747 : return s1[i] == 0 ? 0 : -1;
748 : }
749 : if (s1[i] == 0) {
750 : return 1;
751 : }
752 : const int c0 = tolower(s0[i]);
753 : const int c1 = tolower(s1[i]);
754 : if (c0 < c1)
755 : return -1;
756 : if (c0 > c1)
757 : return 1;
758 : }
759 : return 0;
760 : }
761 :
762 : //#############################################################################
763 :
764 : /// Swap the arguments.
765 : template <class T> inline void CoinSwap (T &x, T &y)
766 : {
767 : T t = x;
768 : x = y;
769 : y = t;
770 : }
771 :
772 : //#############################################################################
773 :
774 : /** This helper function copies an array to file
775 : Returns 0 if OK, 1 if bad write.
776 : */
777 :
778 : template <class T> inline int
779 : CoinToFile( const T* array, int size, FILE * fp)
780 : {
781 : int numberWritten;
782 : if (array&&size) {
783 : numberWritten = fwrite(&size,sizeof(int),1,fp);
784 : if (numberWritten!=1)
785 : return 1;
786 : numberWritten = fwrite(array,sizeof(T),size,fp);
787 : if (numberWritten!=size)
788 : return 1;
789 : } else {
790 : size = 0;
791 : numberWritten = fwrite(&size,sizeof(int),1,fp);
792 : if (numberWritten!=1)
793 : return 1;
794 : }
795 : return 0;
796 : }
797 :
798 : //#############################################################################
799 :
800 : /** This helper function copies an array from file and creates with new.
801 : Passed in array is ignored i.e. not deleted.
802 : But if NULL and size does not match and newSize 0 then leaves as NULL and 0
803 : Returns 0 if OK, 1 if bad read, 2 if size did not match.
804 : */
805 :
806 : template <class T> inline int
807 : CoinFromFile( T* &array, int size, FILE * fp,int & newSize)
808 : {
809 : int numberRead;
810 : numberRead = fread(&newSize,sizeof(int),1,fp);
811 : if (numberRead!=1)
812 : return 1;
813 : int returnCode=0;
814 : if (size!=newSize&&(newSize||array))
815 : returnCode=2;
816 : if (newSize) {
817 : array = new T [newSize];
818 : numberRead = fread(array,sizeof(T),newSize,fp);
819 : if (numberRead!=newSize)
820 : returnCode=1;
821 : } else {
822 : array = NULL;
823 : }
824 : return returnCode;
825 : }
826 :
827 : //#############################################################################
828 :
829 : /// Cube Root
830 : inline double CoinCbrt(double x)
831 : {
832 : #if defined(_MSC_VER)
833 : return pow(x,(1./3.));
834 : #else
835 : return cbrt(x);
836 : #endif
837 : }
838 :
839 : #endif
|