SDDSlib
Loading...
Searching...
No Matches
SDDSutils.c
1/*************************************************************************\
2* Copyright (c) 2002 The University of Chicago, as Operator of Argonne
3* National Laboratory.
4* Copyright (c) 2002 The Regents of the University of California, as
5* Operator of Los Alamos National Laboratory.
6* This file is distributed subject to a Software License Agreement found
7* in the file LICENSE that is included with this distribution.
8\*************************************************************************/
9
10/* file: utils.c
11 * contents: utility routines for SDDS applications
12 * M. Borland, 1995
13 $Log: not supported by cvs2svn $
14 Revision 1.15 2005/11/29 18:28:54 shang
15 added getSDDSMatchingNames()
16
17 Revision 1.14 2003/09/02 19:16:01 soliday
18 Cleaned up code for Linux.
19
20 Revision 1.13 2002/11/25 23:20:50 borland
21 Fixed bug resulting in freeing of same memory twice in multiplyColumnUnits().
22
23 Revision 1.12 2002/10/17 15:50:52 soliday
24 Fixed a memory allocation error.
25
26 Revision 1.11 2002/08/14 17:12:35 soliday
27 Added Open License
28
29 Revision 1.10 2001/10/25 21:58:11 borland
30 Moved greatestProductOfSmallPrimes() and makeFreqUnits() from sddsfft.c
31 to this location for use by sddsfft.c and sddsnaff.c .
32
33 Revision 1.6 2000/04/13 18:00:17 soliday
34 Removed break statements after return statements.
35
36 Revision 1.5 1999/09/14 18:28:50 soliday
37 replace_stringn is no longer defined locally
38
39 Revision 1.4 1999/05/25 19:01:33 soliday
40 Removed compiler warning on linux.
41
42 Revision 1.3 1999/05/05 14:37:27 borland
43 Fixed bug in SDDS_CompareParameterValues (wasn't compare string data
44 correctly).
45
46 * Revision 1.2 1996/05/29 21:42:15 borland
47 * Added new program sddsrowstats. Improved error messages in SDDSutils.c
48 * routine (expandColumnPairNames).
49 *
50 * Revision 1.1 1995/09/06 14:55:43 saunders
51 * First test release of SDDS1.5
52 *
53 */
54
55#include "mdb.h"
56#include "SDDS.h"
57#include "SDDSutils.h"
58
59long appendToStringArray(char ***item, long items, char *newItem) {
60 if (!(*item = SDDS_Realloc(*item, sizeof(**item) * (items + 1))))
61 SDDS_Bomb("allocation failure in appendToStringArray");
62 if (!SDDS_CopyString((*item) + items, newItem)) {
63 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors);
64 exit(1);
65 }
66 return items + 1;
67}
68
69long expandColumnPairNames(SDDS_DATASET *SDDSin, char ***name, char ***errorName, long names, char **excludeName,
70 long excludeNames, long typeMode, long typeValue) {
71 long i, j, names1, errorNames1, names2;
72 char **name1, **errorName1, **name2, **errorName2;
73
74 if (!names || !*name)
75 return 0;
76 name2 = errorName1 = errorName2 = NULL;
77 names2 = errorNames1 = 0;
78 for (i = 0; i < names; i++) {
79 switch (typeMode) {
80 case FIND_ANY_TYPE:
81 case FIND_NUMERIC_TYPE:
82 case FIND_INTEGER_TYPE:
83 case FIND_FLOATING_TYPE:
84 names1 = SDDS_MatchColumns(SDDSin, excludeNames ? NULL : &name1, SDDS_MATCH_STRING, typeMode,
85 (*name)[i], SDDS_0_PREVIOUS | SDDS_OR);
86 break;
87 case FIND_SPECIFIED_TYPE:
88 if (!SDDS_VALID_TYPE(typeValue))
89 SDDS_Bomb("invalid type value in expandColumnPairNames");
90 names1 = SDDS_MatchColumns(SDDSin, excludeNames ? NULL : &name1, SDDS_MATCH_STRING, typeMode, typeValue,
91 (*name)[i], SDDS_0_PREVIOUS | SDDS_OR);
92 break;
93 default:
94 SDDS_Bomb("invalid typeMode in expandColumnPairNames");
95 exit(1);
96 break;
97 }
98 if (names1 == 0)
99 continue;
100 if (names1 == -1) {
101 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors);
102 SDDS_Bomb("unable to perform column name match in expandColumnPairNames");
103 }
104
105 if (excludeNames) {
106 for (j = 0; j < excludeNames; j++)
107 if (!(names1 = SDDS_MatchColumns(SDDSin, (j == excludeNames - 1 ? &name1 : 0),
108 SDDS_MATCH_STRING, FIND_ANY_TYPE,
109 excludeName[j], SDDS_NEGATE_MATCH | SDDS_AND)))
110 break;
111 }
112 if (!names1)
113 continue;
114 moveToStringArray(&name2, &names2, name1, names1);
115 if (errorName && *errorName && (*errorName)[i]) {
116 if (strstr((*errorName)[i], "%s")) {
117 if (!(errorName1 = (char **)malloc(sizeof(*errorName1) * names1)))
118 SDDS_Bomb("allocation failure in expandColumnPairNames");
119 errorNames1 = names1;
120 for (j = 0; j < names1; j++) {
121 if (!(errorName1[j] = (char *)malloc(sizeof(**errorName1) *
122 strlen(name1[j]) +
123 strlen((*errorName)[i]) + 1)))
124 SDDS_Bomb("allocation failure in expandColumnPairNames");
125 replace_stringn(errorName1[j], (*errorName)[i], "%s", name1[j], 1);
126 if (SDDS_CheckColumn(SDDSin, errorName1[j], NULL, SDDS_ANY_NUMERIC_TYPE, stderr) != SDDS_CHECK_OKAY)
127 exit(1);
128 }
129 } else if (names1 == 1) {
130 errorNames1 = 1;
131 if (!(errorName1 = (char **)malloc(sizeof(*errorName1))))
132 SDDS_Bomb("allocation failure in expandColumnPairNames");
133 if (!SDDS_CopyString(errorName1, (*errorName)[i]))
134 return 0;
135 } else
136 SDDS_Bomb("%s template must be employed with error names when primary name has wildcards");
137 names2 -= names1;
138 moveToStringArray(&errorName2, &names2, errorName1, errorNames1);
139 free(errorName1);
140 free(name1);
141 }
142 }
143 if (names2 == 0)
144 return 0;
145 SDDS_FreeStringArray(*name, names);
146 *name = name2;
147 if (errorName) {
148 if (*errorName)
149 SDDS_FreeStringArray(*errorName, names);
150 *errorName = errorName2;
151 }
152 return names2;
153}
154
155void moveToStringArray(char ***target, long *targets, char **source, long sources) {
156 long i, j;
157 if (!sources)
158 return;
159 *target = SDDS_Realloc(*target, sizeof(**target) * (*targets + sources));
160 for (i = 0; i < sources; i++) {
161 for (j = 0; j < *targets; j++)
162 if (strcmp(source[i], (*target)[j]) == 0)
163 break;
164 if (j == *targets) {
165 (*target)[j] = source[i];
166 *targets += 1;
167 }
168 }
169}
170
171char *multiplyColumnUnits(SDDS_DATASET *SDDSin, char *name1, char *name2) {
172 char buffer[SDDS_MAXLINE];
173 char *units1, *units2;
174
175 if (SDDS_GetColumnInformation(SDDSin, "units", &units1, SDDS_GET_BY_NAME, name1) != SDDS_STRING ||
176 SDDS_GetColumnInformation(SDDSin, "units", &units2, SDDS_GET_BY_NAME, name2) != SDDS_STRING)
177 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
178 if (units1 && !SDDS_StringIsBlank(units1)) {
179 strcpy(buffer, units1);
180 free(units1);
181 units1 = NULL;
182 if (units2 && !SDDS_StringIsBlank(units2)) {
183 strcat(buffer, " ");
184 strcat(buffer, units2);
185 free(units2);
186 units2 = NULL;
187 }
188 } else if (units2 && !SDDS_StringIsBlank(units2)) {
189 strcpy(buffer, units2);
190 free(units2);
191 units2 = NULL;
192 } else
193 buffer[0] = 0;
194 if (units1)
195 free(units1);
196 if (units2)
197 free(units2);
198 SDDS_CopyString(&units1, buffer);
199 return units1;
200}
201
202char *divideColumnUnits(SDDS_DATASET *SDDSin, char *name1, char *name2) {
203 char buffer[SDDS_MAXLINE];
204 char *units1, *units2;
205
206 if (SDDS_GetColumnInformation(SDDSin, "units", &units1, SDDS_GET_BY_NAME, name1) != SDDS_STRING ||
207 SDDS_GetColumnInformation(SDDSin, "units", &units2, SDDS_GET_BY_NAME, name2) != SDDS_STRING)
208 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
209 if (units1 && !SDDS_StringIsBlank(units1)) {
210 strcpy(buffer, units1);
211 free(units1);
212 units1 = NULL;
213 if (units2 && !SDDS_StringIsBlank(units2)) {
214 strcat(buffer, "/(");
215 strcat(buffer, units2);
216 strcat(buffer, ")");
217 free(units2);
218 units2 = NULL;
219 }
220 } else if (units2 && !SDDS_StringIsBlank(units2)) {
221 strcpy(buffer, "1/(");
222 strcat(buffer, units2);
223 strcat(buffer, ")");
224 free(units2);
225 units2 = NULL;
226 } else
227 buffer[0] = 0;
228 if (units1)
229 free(units1);
230 if (units2)
231 free(units2);
232 SDDS_CopyString(&units1, buffer);
233 return units1;
234}
235
236long SDDS_CompareParameterValues(void *param1, void *param2, long type) {
237 double ddiff;
238 int64_t ldiff;
239 char cdiff;
240
241 switch (type) {
242 case SDDS_FLOAT:
243 ddiff = *((float *)param1) - *((float *)param2);
244 return ddiff < 0 ? -1 : ddiff > 0 ? 1 : 0;
245 case SDDS_DOUBLE:
246 ddiff = *((double *)param1) - *((double *)param2);
247 return ddiff < 0 ? -1 : ddiff > 0 ? 1 : 0;
248 case SDDS_LONG64:
249 ldiff = *((int64_t *)param1) - *((int64_t *)param2);
250 return ldiff < 0 ? -1 : ldiff > 0 ? 1 : 0;
251 case SDDS_LONG:
252 ldiff = *((int32_t *)param1) - *((int32_t *)param2);
253 return ldiff < 0 ? -1 : ldiff > 0 ? 1 : 0;
254 case SDDS_SHORT:
255 ldiff = *((short *)param1) - *((short *)param2);
256 return ldiff < 0 ? -1 : ldiff > 0 ? 1 : 0;
257 case SDDS_CHARACTER:
258 cdiff = (short)*((char *)param1) - (short)*((char *)param2);
259 return cdiff < 0 ? -1 : cdiff > 0 ? 1 : 0;
260 case SDDS_STRING:
261 return strcmp(*(char **)param1, *(char **)param2);
262 default:
263 SDDS_SetError("Problem doing data comparison--invalid data type (SDDS_CompareParameterValues)");
264 SDDS_PrintErrors(stderr, SDDS_EXIT_PrintErrors | SDDS_VERBOSE_PrintErrors);
265 exit(1);
266 }
267}
268
269char *makeFrequencyUnits(SDDS_DATASET *SDDSin, char *indepName) {
270 char *timeUnits;
271 char *units;
272 long reciprocal = 0, end;
273
274 if (SDDS_GetColumnInformation(SDDSin, "units", &timeUnits, SDDS_GET_BY_NAME, indepName) != SDDS_STRING)
275 return 0;
276 if (timeUnits) {
277 while (1) {
278 end = strlen(timeUnits) - 1;
279 if (timeUnits[0] == '(' && timeUnits[end] == ')') {
280 timeUnits[end] = 0;
281 strslide(timeUnits, 1);
282 } else if (timeUnits[0] == '1' && timeUnits[1] == '/' && timeUnits[2] == '(' && timeUnits[end] == ')') {
283 timeUnits[end] = 0;
284 strslide(timeUnits, 3);
285 reciprocal = !reciprocal;
286 } else
287 break;
288 }
289 }
290 if (!timeUnits || SDDS_StringIsBlank(timeUnits)) {
291 units = tmalloc(sizeof(*units) * 1);
292 units[0] = 0;
293 return units;
294 }
295
296 if (reciprocal) {
297 if (!SDDS_CopyString(&units, timeUnits))
298 return NULL;
299 return units;
300 }
301
302 units = tmalloc(sizeof(*units) * (strlen(timeUnits) + 5));
303 if (strchr(timeUnits, ' '))
304 sprintf(units, "1/(%s)", timeUnits);
305 else
306 sprintf(units, "1/%s", timeUnits);
307 return units;
308}
309
310#define MAXPRIMES 25
311int64_t greatestProductOfSmallPrimes(int64_t rows)
312/* doesn't really find the greatest product, but simply a large one */
313{
314 int64_t bestResult = 0, result, nPrimes;
315 static int64_t prime[MAXPRIMES] = {2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67,
316 71, 73, 79, 83, 89, 97};
317
318 for (nPrimes = 1; nPrimes <= MAXPRIMES; nPrimes++) {
319 if ((result = greatestProductOfSmallPrimes1(rows, prime, nPrimes)) > bestResult &&
320 result <= rows)
321 bestResult = result;
322 }
323 if (bestResult == 0)
324 SDDS_Bomb("couldn't find acceptable number of rows for truncation/padding");
325 return bestResult;
326}
327
328int64_t greatestProductOfSmallPrimes1(int64_t rows, int64_t *primeList, int64_t nPrimes) {
329 int64_t iprime, product, remains, bestFactor = 0;
330 double remainder, smallestRemainder;
331
332 remains = rows;
333 product = 1;
334 while (remains > 2) {
335 smallestRemainder = LONG_MAX;
336 for (iprime = 0; iprime < nPrimes; iprime++) {
337 remainder = remains - primeList[iprime] * ((long)(remains / primeList[iprime]));
338 if (remainder < smallestRemainder) {
339 smallestRemainder = remainder;
340 bestFactor = primeList[iprime];
341 }
342 if (remainder == 0)
343 break;
344 }
345 remains /= bestFactor;
346 product *= bestFactor;
347 }
348 return product * remains;
349}
SDDS (Self Describing Data Set) Data Types Definitions and Function Prototypes.
int32_t SDDS_GetColumnInformation(SDDS_DATASET *SDDS_dataset, char *field_name, void *memory, int32_t mode,...)
Retrieves information about a specified column in the SDDS dataset.
Definition SDDS_info.c:41
int32_t SDDS_FreeStringArray(char **string, int64_t strings)
Frees an array of strings by deallocating each individual string.
void SDDS_SetError(char *error_text)
Records an error message in the SDDS error stack.
Definition SDDS_utils.c:379
int32_t SDDS_CheckColumn(SDDS_DATASET *SDDS_dataset, char *name, char *units, int32_t type, FILE *fp_message)
Checks if a column exists in the SDDS dataset with the specified name, units, and type.
void SDDS_PrintErrors(FILE *fp, int32_t mode)
Prints recorded error messages to a specified file stream.
Definition SDDS_utils.c:432
int32_t SDDS_StringIsBlank(char *s)
Checks if a string is blank (contains only whitespace characters).
int32_t SDDS_MatchColumns(SDDS_DATASET *SDDS_dataset, char ***nameReturn, int32_t matchMode, int32_t typeMode,...)
Matches and retrieves column names from an SDDS dataset based on specified criteria.
void SDDS_Bomb(char *message)
Terminates the program after printing an error message and recorded errors.
Definition SDDS_utils.c:342
int32_t SDDS_CopyString(char **target, const char *source)
Copies a source string to a target string with memory allocation.
Definition SDDS_utils.c:856
void * SDDS_Realloc(void *old_ptr, size_t new_size)
Reallocates memory to a new size.
Definition SDDS_utils.c:677
#define SDDS_VALID_TYPE(type)
Validates whether the given type identifier is within the defined range of SDDS types.
Definition SDDStypes.h:149
#define SDDS_FLOAT
Identifier for the float data type.
Definition SDDStypes.h:43
#define SDDS_STRING
Identifier for the string data type.
Definition SDDStypes.h:85
#define SDDS_LONG
Identifier for the signed 32-bit integer data type.
Definition SDDStypes.h:61
#define SDDS_SHORT
Identifier for the signed short integer data type.
Definition SDDStypes.h:73
#define SDDS_CHARACTER
Identifier for the character data type.
Definition SDDStypes.h:91
#define SDDS_ANY_NUMERIC_TYPE
Special identifier used by SDDS_Check*() routines to accept any numeric type.
Definition SDDStypes.h:157
#define SDDS_DOUBLE
Identifier for the double data type.
Definition SDDStypes.h:37
#define SDDS_LONG64
Identifier for the signed 64-bit integer data type.
Definition SDDStypes.h:49
void * tmalloc(uint64_t size_of_block)
Allocates a memory block of the specified size with zero initialization.
Definition array.c:59
int replace_stringn(char *t, char *s, char *orig, char *repl, long count_limit)
Replace a limited number of occurrences of one string with another string.
char * strslide(char *s, long distance)
Slides character data within a string by a specified distance.
Definition strslide.c:32