00001 /* just some information about this file */ 00002 #define DOUBLEARRAY_VERSION "1.1.0" 00003 #define DOUBLEARRAY_DATE "23-Jun-2003" 00004 00005 /* structures and typedefs */ 00006 00007 /** @file 00008 * @anchor DoubleArray 00009 * Fault-tolerant structure to store one or more double values. 00010 * 00011 * This structure provides a fault-tolerant way to store several double values. The individual values 00012 * are accessed via their index @b starting @b from @b zero. Therefore, the index of the element with 00013 * the highest index number is one less than @c numberOfElements. The memory allocation of the structure 00014 * is managed via the @ref DoubleArray_create and @ref DoubleArray_destroy functions. 00015 * 00016 * The structure is created with @ref DoubleArray_create, destroyed with @ref DoubleArray_destroy and 00017 * displayed with @ref DoubleArray_display. The structure could also be displayed with function 00018 * @ref DoubleArray_displayIntegers; the individual values of the elements are than treated as integers. 00019 * It could be copied with the function @ref DoubleArray_copy. The number of elements of a structure 00020 * could be found out via @ref DoubleArray_getNumberOfElements. Elements could be assigned values with 00021 * @ref DoubleArray_setValue and the value of an element could be obtained with @ref DoubleArray_getValue. 00022 * 00023 * If an element is accessed via @ref DoubleArray_setValue or @ref DoubleArray_getValue and the index 00024 * is higher than @c numberOfElements - 1 (maximum index of this structure) the define @ref 00025 * IndexOutOfBoundsError is called and the program aborts. 00026 * 00027 * <B>Description of the members:</B><BR><BR> 00028 * @c value - the double values of the structure<BR> 00029 * @c numberOfElements - number of elements in the structure 00030 * @author Uli Fechner 00031 * @version 01/24/2003 - Uli Fechner - initial release 00032 * @version 05/20/2003 - Uli Fechner - added function @ref DoubleArray_calculateMeanAndSd 00033 * @version 05/22/2003 - Uli Fechner - added the member @c identifier und the functions @ref 00034 * DoubleArray_createWithIdentifier and DoubleArray_getIdentifier; adjusted the function @ref 00035 * DoubleArray_copy accordingly 00036 * @version 05/23/2003 - Uli Fechner - SPECIAL MODIFICATION for the RankIt program: added function 00037 * @ref DoubleArray_lessThan 00038 * @version 06/16/2003 - v1.0.1 - Uli Fechner - SPECIAL MODIFICATION for the RankIt program: several 00039 * adjustments in function @ref DoubleArray_calculateMeanAndSd 00040 * @version 06/23/2003 - v1.1.0 - Uli Fechner - bugfix in function @ref DoubleArray_calculateMeanAndSd 00041 * @@code 00042 */ 00043 typedef struct 00044 { 00045 double* value; 00046 int numberOfElements; 00047 int identifier; 00048 } DoubleArray; 00049 /** @endcode */ 00050 00051 00052 /** A pointer to structure @ref DoubleArray is assigned the name @c DoubleArrayPtr. */ 00053 typedef DoubleArray* DoubleArrayPtr; 00054 00055 00056 /* function prototypes */ 00057 00058 DoubleArrayPtr DoubleArray_create( const int numberOfElements ); 00059 00060 DoubleArrayPtr DoubleArray_createWithIdentifier( const int numberOfElements, const int identifier ); 00061 00062 void DoubleArray_destroy( DoubleArrayPtr dAPtr ); 00063 00064 void DoubleArray_display( void* dAPtr, FILE* outputStream ); 00065 00066 void DoubleArray_displayIntegers( const DoubleArrayPtr dAPtr, FILE* outputStream ); 00067 00068 DoubleArrayPtr DoubleArray_copy( const DoubleArrayPtr dAPtr ); 00069 00070 int DoubleArray_getIdentifier( const DoubleArrayPtr dAPtr ); 00071 00072 int DoubleArray_getNumberOfElements( const DoubleArrayPtr dAPtr ); 00073 00074 void DoubleArray_setValue( const DoubleArrayPtr dAPtr, const int index, const double value ); 00075 00076 double DoubleArray_getValue( const DoubleArrayPtr dAPtr, const int index ); 00077 00078 DoubleArrayPtr DoubleArray_calculateMeanAndSd( const DoubleArrayPtr dAPtr ); 00079 00080 int DoubleArray_lessThan( void* dAPtr1, void* dAPtr2 ); 00081 00082 00083 /* functions */ 00084 00085 /** Creates a @ref DoubleArray structure. 00086 * 00087 * A @ref DoubleArray structure is created. The number of elements of the structure is given as an 00088 * argument and is not dynamic during the lifetime of a structure @ref DoubleArray. 00089 * 00090 * @param numberOfElements the number of elements of the newly created structure 00091 * @retval DoubleArrayPtr pointer on the newly created structure @ref DoubleArray 00092 * @author Uli Fechner 00093 * @version 01/24/2003 - Uli Fechner - initial release 00094 */ 00095 DoubleArrayPtr DoubleArray_create( const int numberOfElements ) 00096 { 00097 DoubleArrayPtr dAPtr; 00098 00099 if( !( dAPtr = calloc( 1, sizeof( DoubleArray ) ) ) ) 00100 MemoryError( "dAPtr", "DoubleArray_create" ); 00101 00102 dAPtr->numberOfElements = numberOfElements; 00103 00104 if( numberOfElements == 0 ) 00105 dAPtr->value = NULL; 00106 00107 else 00108 { 00109 if( !( dAPtr->value = calloc( numberOfElements, sizeof( double ) ) ) ) 00110 MemoryError( "dAPtr->value", "DoubleArray_create" ); 00111 } 00112 00113 return dAPtr; 00114 } 00115 00116 00117 /** Creates a @ref DoubleArray structure with an identifier. 00118 * 00119 * A @ref DoubleArray structure is created. The number of elements of the structure is given as an 00120 * argument and is not dynamic during the lifetime of a structure @ref DoubleArray. The second 00121 * argument is an integer that serves as a unique identifier of this @ref DoubleArray. This function 00122 * for the creation of a @ref DoubleArray is useful, if the @ref DoubleArray is part of an array of 00123 * DoubleArrays. 00124 * 00125 * @param numberOfElements the number of elements of the newly created structure 00126 * @param identifier integer that serves as a unique identifier 00127 * @retval DoubleArrayPtr pointer on the newly created structure @ref DoubleArray 00128 * @author Uli Fechner 00129 * @version 05/22/2003 - Uli Fechner - initial release 00130 */ 00131 DoubleArrayPtr DoubleArray_createWithIdentifier( const int numberOfElements, const int identifier ) 00132 { 00133 DoubleArrayPtr dAPtr; 00134 00135 if( !( dAPtr = calloc( 1, sizeof( DoubleArray ) ) ) ) 00136 MemoryError( "dAPtr", "DoubleArray_create" ); 00137 00138 dAPtr->numberOfElements = numberOfElements; 00139 dAPtr->identifier = identifier; 00140 00141 if( numberOfElements == 0 ) 00142 dAPtr->value = NULL; 00143 00144 else 00145 { 00146 if( !( dAPtr->value = calloc( numberOfElements, sizeof( double ) ) ) ) 00147 MemoryError( "dAPtr->value", "DoubleArray_create" ); 00148 } 00149 00150 return dAPtr; 00151 } 00152 00153 00154 /** Destroys a structure @ref DoubleArray. 00155 * 00156 * The structure @ref DoubleArray the pointer @c dAPtr refers to is destroyed. All allocated memory of 00157 * the structure is automatically freed. 00158 * 00159 * @param dAPtr pointer on the structure @ref DoubleArray that should be destroyed 00160 * @author Uli Fechner 00161 * @version 01/24/2003 - Uli Fechner - initial release 00162 */ 00163 void DoubleArray_destroy( DoubleArrayPtr dAPtr ) 00164 { 00165 if( dAPtr != NULL ) 00166 { 00167 if( dAPtr->value != NULL ) 00168 free( dAPtr->value ); 00169 free( dAPtr ); 00170 } 00171 else 00172 { 00173 fprintf( stderr, "\n\nERROR: Function 'DoubleArray_destroy' could not destroy a structure\n" ); 00174 fprintf( stderr, "'DoubleArray' that has not been created before!\n" ); 00175 AbortProgram; 00176 } 00177 } 00178 00179 00180 /** Copies a structure @ref DoubleArray. 00181 * 00182 * A copy of the structure @ref DoubleArray referred to by @c dAPtr is made. The copy lives in its own 00183 * memory and contains all elements the template contains (sometimes called @c deepcopy). 00184 * 00185 * @param dAPtr pointer on the structure @ref DoubleArray that should be copied 00186 * @retval DoubleArrayPtr pointer on structure @ref DoubleArray containing the copy 00187 * @author Uli Fechner 00188 * @version 01/24/2003 - Uli Fechner - initial release 00189 * @version 05/22/2003 - Uli Fechner - added the copying of the identifier 00190 */ 00191 DoubleArrayPtr DoubleArray_copy( const DoubleArrayPtr dAPtr ) 00192 { 00193 int counter; 00194 DoubleArrayPtr copyOfDAPtr; 00195 00196 if( dAPtr == NULL ) 00197 { 00198 fprintf( stderr, "\n\nERROR: Function 'DoubleArray_copy' could not copy a structure\n" ); 00199 fprintf( stderr, "'DoubleArray' that is empty!\n" ); 00200 AbortProgram; 00201 } 00202 00203 if( !( copyOfDAPtr = calloc( 1, sizeof( DoubleArray ) ) ) ) 00204 MemoryError( "copyOfDAPtr", "DoubleArray_copy" ); 00205 00206 copyOfDAPtr->numberOfElements = DoubleArray_getNumberOfElements( dAPtr ); 00207 copyOfDAPtr->identifier = DoubleArray_getIdentifier( dAPtr ); 00208 00209 if( DoubleArray_getNumberOfElements( dAPtr ) == 0 ) 00210 copyOfDAPtr->value = NULL; 00211 00212 else 00213 { 00214 if( !( copyOfDAPtr->value = calloc( DoubleArray_getNumberOfElements( dAPtr ), sizeof( double ) ) ) ) 00215 MemoryError( "copyOfDAPtr->value", "DoubleArray_copy" ); 00216 } 00217 00218 for( counter = 0; counter < DoubleArray_getNumberOfElements( dAPtr ); counter++ ) 00219 DoubleArray_setValue( copyOfDAPtr, counter, DoubleArray_getValue( dAPtr, counter ) ); 00220 00221 return copyOfDAPtr; 00222 } 00223 00224 /** Displays a structure @ref DoubleArray. 00225 * 00226 * The structure @ref DoubleArray the pointer @c dAPtr refers to is displayed on the FILE* @c 00227 * outputStream. 00228 * 00229 * @param dAPtr pointer on the structure @ref DoubleArray that should be displayed 00230 * @param outputStream FILE* on the stream the output should be sent to 00231 * @author Uli Fechner 00232 * @version 01/24/2003 - Uli Fechner - initial release 00233 */ 00234 void DoubleArray_display( void* dAPtr, FILE* outputStream ) 00235 { 00236 int counter; /* simple counter variable in for loop */ 00237 00238 if( dAPtr == NULL ) 00239 { 00240 fprintf( stderr, "\n\nERROR: Function 'DoubleArray_display' could not display a structure\n" ); 00241 fprintf( stderr, "'DoubleArray' that is empty!\n" ); 00242 AbortProgram; 00243 } 00244 00245 for( counter = 0; counter < DoubleArray_getNumberOfElements( dAPtr ); counter++ ) 00246 fprintf( outputStream, "%.6f ", DoubleArray_getValue( dAPtr, counter ) ); 00247 fprintf( outputStream, "\n" ); 00248 } 00249 00250 /** Displays a structure @ref DoubleArray. 00251 * 00252 * The structure @ref DoubleArray the pointer @c dAPtr refers to is displayed on the FILE* @c 00253 * outputStream. The values of each element contained in @ref DoubleArray are treated as integers. 00254 * 00255 * @param dAPtr pointer on the structure @ref DoubleArray that should be displayed 00256 * @param outputStream FILE* on the stream the output should be sent to 00257 * @author Uli Fechner 00258 * @version 01/24/2003 - Uli Fechner - initial release 00259 */ 00260 void DoubleArray_displayIntegers( const DoubleArrayPtr dAPtr, FILE* outputStream ) 00261 { 00262 int counter; /* simple counter variable in for loop */ 00263 00264 if( dAPtr == NULL ) 00265 { 00266 fprintf( stderr, "\n\nERROR: Function 'DoubleArray_display' could not display a structure\n" ); 00267 fprintf( stderr, "'DoubleArray' that is empty!\n" ); 00268 AbortProgram; 00269 } 00270 00271 for( counter = 0; counter < DoubleArray_getNumberOfElements( dAPtr ); counter++ ) 00272 fprintf( outputStream, "%d ", (int) DoubleArray_getValue( dAPtr, counter ) ); 00273 fprintf( outputStream, "\n" ); 00274 } 00275 00276 00277 /** Returns the identifier of a structure @ref DoubleArray. 00278 * 00279 * @param dAPtr pointer on the structure @ref DoubleArray of which the number of elements should be returned 00280 * @retval int unique identifier of the structure @ref DoubleArray 00281 * @author Uli Fechner 00282 * @version 05/22/2003 - Uli Fechner - initial release 00283 */ 00284 int DoubleArray_getIdentifier( const DoubleArrayPtr dAPtr ) 00285 { 00286 return dAPtr->identifier; 00287 } 00288 00289 /** Returns the number of elements of a structure @ref DoubleArray. 00290 * 00291 * The number of elements of the structure @ref DoubleArray the pointer @c dAPtr refers to is returned. 00292 * 00293 * @param dAPtr pointer on the structure @ref DoubleArray of which the number of elements should be returned 00294 * @retval int number of elements of the structure @ref DoubleArray 00295 * @author Uli Fechner 00296 * @version 01/24/2003 - Uli Fechner - initial release 00297 */ 00298 int DoubleArray_getNumberOfElements( const DoubleArrayPtr dAPtr ) 00299 { 00300 return dAPtr->numberOfElements; 00301 } 00302 00303 00304 /** The element with index @c index of structure @ref DoubleArray is assigned the value @c value. 00305 * 00306 * The value @c value is assigned to the element with index @c index of the structure @ref DoubleArray 00307 * @c dAPtr points on. If the index @c index is greater than (@c numberOfElements - 1 ), the program 00308 * aborts with the call of the define @ref IndexOutOfBoundsError. 00309 * 00310 * @param dAPtr pointer on the structure @ref DoubleArray that contains the element 00311 * @param index index of the element the value @c value should be assigned to 00312 * @param value value that should be assigned to the element with index @c index 00313 * @author Uli Fechner 00314 * @version 01/24/2003 - Uli Fechner - initial release 00315 */ 00316 void DoubleArray_setValue( const DoubleArrayPtr dAPtr, const int index, const double value ) 00317 { 00318 if( index >= DoubleArray_getNumberOfElements( dAPtr ) ) 00319 IndexOutOfBoundsError( "DoubleArray", DoubleArray_getNumberOfElements( dAPtr ), index ); 00320 00321 (dAPtr->value)[ index ] = value; 00322 } 00323 00324 /** The value of the element with index @c index of structure @ref DoubleArray is returned. 00325 * 00326 * The value of the element with index @c index of the structure @ref DoubleArray @c dAPtr points on is 00327 * returned. If the index @c index is greater than (@c numberOfElements - 1 ), the program aborts with 00328 * the call of the define @ref IndexOutOfBoundsError. 00329 * 00330 * @param dAPtr pointer on the structure @ref DoubleArray that contains the element 00331 * @param index index of the element the value should be returned 00332 * @retval double the value of the element with index @c index 00333 * @author Uli Fechner 00334 * @version 01/24/2003 - Uli Fechner - initial release 00335 */ 00336 double DoubleArray_getValue( const DoubleArrayPtr dAPtr, const int index ) 00337 { 00338 if( index < DoubleArray_getNumberOfElements( dAPtr ) ) 00339 return (dAPtr->value)[ index ]; 00340 else 00341 IndexOutOfBoundsError( "DoubleArray", DoubleArray_getNumberOfElements( dAPtr ), index ); 00342 } 00343 00344 00345 /** The mean and standard deviation of the values contained in one @ref DoubleArray is calculated. 00346 * 00347 * The return value of this function is a DoubleArrayPtr. The corresponding @ref DoubleArray contains 00348 * two values: 00349 * @li 1st value - arithmetic mean 00350 * @li 2nd value - standard deviation 00351 * 00352 * @param dAPtr pointer on the structure @ref DoubleArray that contains the elements 00353 * @retval DoubleArrayPtr DoubleArray with two values: mean and standard deviation 00354 * @author Uli Fechner 00355 * @version 05/20/2003 - Uli Fechner - initial release 00356 * @version 05/23/2003 - Uli Fechner - SPECIAL MODIFICATION for the RankIt program (see remarks) 00357 * @version 06/16/2003 - Uli Fechner - SPECIAL MODIFICATION for the RankIt program (see remarks) 00358 * @version 06/23/2003 - Uli Fechner - IMPORTANT bugifx: the standard deviation for the active compounds 00359 * was not calculated correctly 00360 */ 00361 DoubleArrayPtr DoubleArray_calculateMeanAndSd( const DoubleArrayPtr dAPtr ) 00362 { 00363 int counter; /* simpler counter variable in for loop */ 00364 int numberOfElements; /* number of elements of the DoubleArray */ 00365 double mean = 0.0f; /* used to store the calculated mean value */ 00366 double standardDeviation = 0.0f; /* used to store the calculated standard deviation */ 00367 /* DoubleArray that contains two values: first the mean and second the standard deviation of dAPtr */ 00368 DoubleArrayPtr dAMeanAndSd; 00369 /* if one value of the DoubleArray is zero the mean is divided by numberOfElements - 1 */ 00370 int zeroContained = BOOLEAN_FALSE; 00371 00372 for( counter = 0; counter < DoubleArray_getNumberOfElements( dAPtr ); counter++ ) 00373 if( ( (int) DoubleArray_getValue( dAPtr, counter ) ) == 0 ) 00374 zeroContained = BOOLEAN_TRUE; 00375 00376 dAMeanAndSd = DoubleArray_create( 2 ); 00377 numberOfElements = DoubleArray_getNumberOfElements( dAPtr ); 00378 00379 /* calculating the mean */ 00380 for( counter = 0; counter < numberOfElements; counter++ ) 00381 mean += DoubleArray_getValue( dAPtr, counter ); 00382 /* if one element of the DoubleArray is zero the mean is divided by numberOfElements - 1. 00383 This is a special modification for the rankIt program. The element that is zero indicates that 00384 the corresponding Compound is an active compound. Every active compound is one time the query 00385 structure. Hence, it has no real rank for this similarity search and the mean has to be calculated 00386 with one element less than the other, non-active compounds. */ 00387 mean /= numberOfElements - zeroContained; 00388 DoubleArray_setValue( dAMeanAndSd, 0, mean ); 00389 00390 /* if there is only one element in daPtr and this element is zero the mean is set to zero */ 00391 if( numberOfElements - zeroContained == 0 ) 00392 DoubleArray_setValue( dAMeanAndSd, 0, 0.0f ); 00393 00394 /* calculating the standard deviation */ 00395 for( counter = 0; counter < numberOfElements; counter++ ) 00396 { 00397 if( DoubleArray_getValue( dAPtr, counter ) != 0 ) 00398 standardDeviation += pow( mean - DoubleArray_getValue( dAPtr, counter ), 2 ); 00399 } 00400 standardDeviation /= ( numberOfElements - 1 - zeroContained ); 00401 standardDeviation = sqrt( standardDeviation ); 00402 DoubleArray_setValue( dAMeanAndSd, 1, standardDeviation ); 00403 00404 /* it does not make any sense to calculate a standard deviation if there are only 2 values and one 00405 of these two is zero, i.e. the compound is an active compound OR if there is only one value at all */ 00406 if( ( numberOfElements == 2 && zeroContained == BOOLEAN_TRUE ) || ( numberOfElements ==1 ) ) 00407 DoubleArray_setValue( dAMeanAndSd, 1, 0.0f ); 00408 00409 return dAMeanAndSd; 00410 } 00411 00412 /** Evaluates if the @c first value of @c dAPtr1 is less than that of @c dAPtr2. 00413 * 00414 * The function returns @ref BOOLEAN_TRUE if the @c first value of @c dAPtr 1 is less than the 00415 * @c first value of @c dAPtr2 and @ref BOOLEAN_FALSE if this condition is not matched. 00416 * 00417 * @param dAPtr1 pointer on the first structure @ref DoubleArray 00418 * @param dAPtr2 pointer on the second structure @ref DoubleArray 00419 * @author Uli Fechner 00420 * @version 05/23/2003 - Uli Fechner - initial release 00421 */ 00422 int DoubleArray_lessThan( void* dAPtr1, void* dAPtr2 ) 00423 { 00424 if( DoubleArray_getValue( dAPtr1, 0 ) < DoubleArray_getValue( dAPtr2, 0 ) ) 00425 return BOOLEAN_TRUE; 00426 else 00427 return BOOLEAN_FALSE; 00428 }