1
/* -*- mode: c; tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil -*- */
3
/*********************************************************************
4
* Clustal Omega - Multiple sequence alignment
6
* Copyright (C) 2010 University College Dublin
8
* Clustal-Omega is free software; you can redistribute it and/or
9
* modify it under the terms of the GNU General Public License as
10
* published by the Free Software Foundation; either version 2 of the
11
* License, or (at your option) any later version.
13
* This file is part of Clustal-Omega.
15
********************************************************************/
18
* RCS $Id: util.c 235 2011-04-13 14:13:19Z andreas $
37
/* struct for QSortAndTrackIndex and SortAndTrackIndexCmp[Asc|Desc] */
47
* @brief Copy of squid's FileExists(). Copied here to make squid independent.
50
CheckIfFileExists(char *pcFilename)
53
if ((prFile = fopen(pcFilename, "r"))) {
59
/* end of CheckIfFileExists */
63
* @brief Allocates memory (malloc)
68
* calling function name
70
* calling function line
72
* @return void pointer to the newly allocated memory
74
* @note use provided macro CKMALLOC() which automatically adds
75
* function name and line number
79
CkMalloc(size_t bytes, const char *function, const int line)
83
if(NULL == (ret = malloc(bytes * sizeof(char)))) {
84
Log(&rLog, LOG_FATAL, "Out of memory (requested from %s:%d)\n", function, line);
89
/*** end: ckmalloc ***/
94
* @brief Allocates memory (calloc). Memory will be
98
* Allocate space for count objects
100
* Objects are of this size
101
* @param[in] function
102
* calling function name
104
* calling function line
106
* @return void pointer to the newly allocated and zeroed memory (calloc).
108
* @note use provided macro CKCALLOC() which automatically adds
109
* function name and line number
114
CkCalloc(size_t count, size_t size, const char *function, const int line)
118
if(NULL == (ret = calloc(count, size))) {
119
Log(&rLog, LOG_FATAL, "Out of memory (requested from %s:%d)\n",
126
/*** end: CkCalloc ***/
130
* @brief Reallocates memory
133
* Pointer to memory to be reallocated
136
* @param[in] function
137
* calling function name
139
* calling function line
141
* @return void pointer to the newly allocated memory
143
* @note use provided macro CKREALLOC() which automatically adds
144
* function name and line number
148
CkRealloc(void *ptr, size_t bytes, const char *function, const int line)
152
if(NULL == (ret = realloc(ptr, bytes))) {
153
Log(&rLog, LOG_FATAL, "FATAL: Out of memory (requested from %s:%d)\n",
159
/*** end: ckrealloc ***/
165
* @brief Frees memory
168
* Pointer to memory to be freed
169
* @param[in] function
170
* calling function name
172
* calling function line
174
* @return void pointer to the now zeroed memory
176
* @note use provided macro CKFREE()
180
CkFree(void *ptr, const char *function, const int line)
183
Log(&rLog, LOG_WARN, "Bad call to CkFree from %s:%d (pointer was NULL)\n", function, line);
190
/*** end: CkFree ***/
196
* @brief safe version of strdup
199
* String to copy from
201
* @return copy of string
203
* @note src is not allowed to be NULL.
207
CkStrdup(const char *src)
212
/*cp = strdup(src); always makes trouble... */
213
cp = (char *) CKMALLOC(strlen(src) +1);
218
/*** end: CkStrdup ***/
224
* @brief Creates an int array of size len with len-1 random but unique
225
* integers with values 0--len-1. This is "a modified version of
226
* Fisher-Yates known as Durstenfeld-Fisher-Yates or
227
* Knuth-Fisher-Yates". See
228
* http://stackoverflow.com/questions/196017/unique-random-numbers-in-o1
231
* The permutation array. Has to be preallocated
233
* Length of the permutation array
237
PermutationArray(int **perm, const int len)
243
srand((unsigned int) time(0));
244
(*perm) = (int *) CKMALLOC(len * sizeof(int));
246
for (i=0; i<len; i++) {
252
/* randno = addrand((unsigned long) len); / returns 0--n-1 */
253
randno = (rand()%len);
256
tmp = (*perm)[randno];
257
(*perm)[randno] = (*perm)[max];
264
/*** end: PermutationArray() ***/
269
* @brief Creates an array filled with random, but unique ints of
270
* given range. Implementation of the Floyd algorithm. See
271
* http://stackoverflow.com/questions/1608181/unique-random-numbers-in-an-integer-array-in-the-c-programming-language
272
* Assuming M is the length of the desired array and N is the numeric
273
* range: "This approach has the complexity of about O(M) (depends on
274
* the search structure used), so it is better suitable when M << N.
275
* This approach keeps track of already generated random numbers, so
276
* it requires extra memory. However, the beauty of it is that it does
277
* not make any of those horrendous "trial and error" iterations,
278
* trying to find an unused random number. This algorithm is
279
* guaranteed to generate one unique random number after each single
280
* call to the random number generator."
282
* @warning This won't work if max_value<=array_len. Only use for
283
* cases where array_len<<max_value
286
* Preallocated int array whose values will be set
287
* @param[in] array_len
289
* @param[in] max_value
293
RandomUniqueIntArray(int *array, const int array_len, const int max_value)
298
assert(array_len<max_value);
299
srand((unsigned int) time(0));
300
is_used = (bool *) CKCALLOC(max_value, sizeof(bool));
304
for (in = max_value - array_len; in < max_value && im < array_len; ++in) {
305
int r = rand() % (in + 1);
306
if (is_used[r]==TRUE) {
307
r = in; /* use 'in' instead of generated number */
309
assert(! is_used[r]);
314
assert(im == array_len);
320
/*** end: RandomUniqueIntArray() ***/
325
* @brief int comparison function for qsort
329
IntCmp(const void *a, const void *b)
331
const int *ia = (const int *)a;
332
const int *ib = (const int *)b;
335
/*** end: IntCmp() ***/
342
* @brief Compare two sortwithindex_t pointers and return the
343
* difference between the int value of the 1st sortwithindex_t and the
344
* 2nd. Used for ascending sort order in QSortWithIndexes()/
346
* @see SortAndTrackIndexCmpDesc() and QSortAndTrackIndex()
349
SortAndTrackIndexCmpAsc(const void *a, const void *b)
351
const sortwithindex_t *a_t = (const sortwithindex_t *)a;
352
const sortwithindex_t *b_t = (const sortwithindex_t *)b;
354
const int ia = (const int) a_t->piValue;
355
const int ib = (const int) b_t->piValue;
358
/*** end: SortAndTrackIndexCmpAsc ***/
364
* @brief Compare two sortwithindex_t pointers and return the
365
* difference between the int value of the 2nd sortwithindex_t and the
366
* 1st. Used for descending sort order in QSortWithIndexes()
368
* @see SortAndTrackIndexCmpDesc() and QSortAndTrackIndex()
371
SortAndTrackIndexCmpDesc(const void *a, const void *b)
373
const sortwithindex_t *a_t = (const sortwithindex_t *)a;
374
const sortwithindex_t *b_t = (const sortwithindex_t *)b;
376
const int ia = (const int) a_t->piValue;
377
const int ib = (const int) b_t->piValue;
380
/*** end: SortAndTrackIndexCmpDesc ***/
386
* @brief Sort a given int array in ascending or descending order,
387
* while keeping track of the element order.
389
* @param[out] piSortedIndices
390
* Will contain the indices of the sorted elements. Has to be preallocated.
391
* @param[out] piArrayToSort
392
* Array with values to sort. Will only be overwritten if
393
* bOverwriteArrayToSort it true.
394
* @param[in] iArrayLen
395
* Number of elements in piArrayToSort.
397
* Sort order. 'a' for ascending, 'd' for descending.
398
* @param[in] bOverwriteArrayToSort
399
* If false do not overwrite the array to sort.
403
QSortAndTrackIndex(int *piSortedIndices, int *piArrayToSort,
404
const int iArrayLen, const char cOrder,
405
const bool bOverwriteArrayToSort)
407
int iCtr; /**< aux */
409
sortwithindex_t *prSort;
412
assert(NULL!=piSortedIndices);
414
assert(NULL!=piArrayToSort);
415
assert('a'==cOrder || 'd'==cOrder);
417
prSort = (sortwithindex_t *) CKMALLOC(iArrayLen * sizeof(sortwithindex_t));
419
for (iCtr=0; iCtr<iArrayLen; iCtr++) {
420
prSort[iCtr].piIndex = iCtr;
421
prSort[iCtr].piValue = piArrayToSort[iCtr];
423
LOG_DEBUG("b4 sort: prSort idx %d = val %d",
424
prSort[iCtr].piIndex, prSort[iCtr].piValue);
429
qsort(prSort, iArrayLen, sizeof(sortwithindex_t), SortAndTrackIndexCmpAsc);
430
} else if ('d'==cOrder) {
431
qsort(prSort, iArrayLen, sizeof(sortwithindex_t), SortAndTrackIndexCmpDesc);
433
Log(&rLog, LOG_FATAL, "Internal error: unknown order %c", cOrder);
436
for (iCtr=0; iCtr<iArrayLen; iCtr++) {
437
piSortedIndices[iCtr] = prSort[iCtr].piIndex;
439
if (bOverwriteArrayToSort) {
440
piArrayToSort[iCtr] = prSort[iCtr].piValue;
443
LOG_DEBUG("after sort: prSort idx %d = val %d",
444
prSort[iCtr].piIndex, prSort[iCtr].piValue);
451
/*** end: QSortWithIndexes() ***/
457
* @brief Test if file is writable. File may or may not exist.
459
* @param[in] pcFileName
462
* @return True if file is writable at the time of calling
466
FileIsWritable(char *pcFileName)
468
bool bFileAlreadyExisted;
472
if (0 != CheckIfFileExists(pcFileName)) {
473
bFileAlreadyExisted = TRUE;
475
bFileAlreadyExisted = FALSE;
478
if (NULL == (prFilePointer=fopen(pcFileName, "a"))) {
482
if (0 != fclose(prFilePointer)) {
483
Log(&rLog, LOG_ERROR, "Couldn't close temporily created file %s. Expect trouble...");
488
LOG_DEBUG("%s existed?=%d writable=%d", pcFileName,
489
(TRUE==bFileAlreadyExisted? 1 : 0),
490
(TRUE==bIsWritable? 1:0));
493
/* delete if file didn't exist before and was created here
496
if (FALSE==bFileAlreadyExisted && TRUE==bIsWritable) {
497
if (0 != remove(pcFileName)) {
498
Log(&rLog, LOG_ERROR, "Removing of temporarily created file %s failed. Expect trouble...");
503
/*** end: FileIsWritable() ***/