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() ***/