Branch data Line data Source code
1 : : /*
2 : : * International Chemical Identifier (InChI)
3 : : * Version 1
4 : : * Software version 1.07
5 : : * April 30, 2024
6 : : *
7 : : * MIT License
8 : : *
9 : : * Copyright (c) 2024 IUPAC and InChI Trust
10 : : *
11 : : * Permission is hereby granted, free of charge, to any person obtaining a copy
12 : : * of this software and associated documentation files (the "Software"), to deal
13 : : * in the Software without restriction, including without limitation the rights
14 : : * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
15 : : * copies of the Software, and to permit persons to whom the Software is
16 : : * furnished to do so, subject to the following conditions:
17 : : *
18 : : * The above copyright notice and this permission notice shall be included in all
19 : : * copies or substantial portions of the Software.
20 : : *
21 : : * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
22 : : * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
23 : : * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
24 : : * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
25 : : * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
26 : : * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
27 : : * SOFTWARE.
28 : : *
29 : : * The InChI library and programs are free software developed under the
30 : : * auspices of the International Union of Pure and Applied Chemistry (IUPAC).
31 : : * Originally developed at NIST.
32 : : * Modifications and additions by IUPAC and the InChI Trust.
33 : : * Some portions of code were developed/changed by external contributors
34 : : * (either contractor or volunteer) which are listed in the file
35 : : * 'External-contributors' included in this distribution.
36 : : *
37 : : * info@inchi-trust.org
38 : : *
39 : : */
40 : :
41 : : #include <stdlib.h>
42 : : #include <ctype.h>
43 : : #include <string.h>
44 : : #include <math.h>
45 : : #include <float.h>
46 : : #include <limits.h>
47 : :
48 : : #include "mode.h"
49 : : #include "mol_fmt.h"
50 : :
51 : : #include "ichierr.h"
52 : : #include "util.h"
53 : : #include "ichi_io.h"
54 : :
55 : : #include "bcf_s.h"
56 : :
57 : : /*
58 : : MolFile related procedures - 2
59 : :
60 : : */
61 : :
62 : : /****************************************************************************
63 : : Read n chars and find where they are terminated with space or trailing 0
64 : : ****************************************************************************/
65 : 1692 : int MolfileStrnread(char *dest,
66 : : char *source,
67 : : int len,
68 : : char **first_space)
69 : : {
70 : : /* required len >= 0; dest must have at least len+1 bytes */
71 : :
72 : : int i, c;
73 : :
74 [ + + ]: 1692 : if (len > 0)
75 : : {
76 : 1584 : strncpy(dest, source, len);
77 : : }
78 : 1692 : dest[len] = '\0';
79 : :
80 [ + + ]: 1692 : len = (len > 0) ? (int)strlen(dest) : 0;
81 : :
82 [ + + + - : 2967 : for (i = ( len - 1 ); i >= 0 && 0 != ( c = source[i] ) && isspace( UCINT c ); i--);
+ + ]
83 : :
84 : 1692 : *first_space = dest + ((long long)i + 1); /* first blank or zero terminating byte in dest */ /* djb-rwth: cast operator added */
85 : :
86 : 1692 : return len; /* number of actually processed bytes excluding zero terminator */
87 : : }
88 : :
89 : : /****************************************************************************
90 : : * Extract the 'data' in the mol file field at given text position 'line_ptr'
91 : : *
92 : : *
93 : : * 1. 'field_len' for MOL_FMT_STRING_DATA does not include trailing zero,
94 : : * that is actual length of the string pointed by 'data'
95 : : * should be at least field_len+1 bytes.
96 : : * For numerical data 'field_len' is length of input data field
97 : : * For numerical integral data field_len <= 0 means read up to first
98 : : * non-numeric character as strtod() does ("free format")
99 : : * 2. return value: for MOL_FMT_STRING_DATA: number of bytes excluding trailing zero
100 : : * for all others: 1=success; 0 = empty; -1= error
101 : : * 3. on exit *line_ptr points to the next byte after the last entered
102 : : *
103 : : *
104 : : ****************************************************************************/
105 : 2389 : int MolfileReadField(void *data,
106 : : int field_len,
107 : : int data_type,
108 : : char **line_ptr)
109 : : {
110 : 2389 : char *p = *line_ptr, *q, *p_end;
111 : 2389 : int i, c, len, ret = 1;
112 : : long ldata;
113 : : double ddata;
114 : :
115 : 2389 : int DEFINITE_LENGTH_FIELD = 0;
116 : 2389 : int FIELD_ENDS_AT_FIRST_NON_DIGIT = 0;
117 : 2389 : int TOO_LONG_FIELD = 0;
118 : :
119 [ + + ]: 2389 : if (field_len > MOL_FMT_MAX_VALUE_LEN)
120 : : {
121 : 162 : TOO_LONG_FIELD = 1;
122 : : }
123 [ - + ]: 2227 : else if (field_len <= 0)
124 : : {
125 : 0 : FIELD_ENDS_AT_FIRST_NON_DIGIT = 1;
126 : : }
127 : : else
128 : : {
129 : 2227 : DEFINITE_LENGTH_FIELD = 1;
130 : : }
131 : :
132 [ + + + + : 2389 : switch (data_type)
- ]
133 : : {
134 : 575 : case MOL_FMT_STRING_DATA:
135 : : /* pass by all leading spaces */
136 : 575 : for (i = 0;
137 [ + + + + : 1595 : i < field_len && 0 != (c = p[i]) && isspace(UCINT c);
+ + ]
138 : 1020 : i++)
139 : : {
140 : : ;
141 : : }
142 : :
143 : 575 : len = MolfileStrnread((char *)data, &p[i], field_len - i, &q);
144 : :
145 : 575 : ret = ( q - (char*) data );/* actual data length */
146 : 575 : *q = '\0'; /* add zero termination to data if it is not there yet*/
147 : 575 : *line_ptr += ( (long long)len + (long long)i ); /* ptr to the 1st byte of the next input field or to zero termination */ /* djb-rwth: cast operators added */
148 : 575 : break;
149 : :
150 : 904 : case MOL_FMT_CHAR_INT_DATA:
151 : : case MOL_FMT_SHORT_INT_DATA:
152 : : case MOL_FMT_LONG_INT_DATA:
153 : : {
154 : : char str[MOL_FMT_MAX_VALUE_LEN + 1];
155 : 904 : ldata = 0L;
156 [ - + ]: 904 : if (TOO_LONG_FIELD)
157 : : {
158 : 0 : ret = -1;
159 : : }
160 [ + - ]: 904 : else if (DEFINITE_LENGTH_FIELD)
161 : : {
162 : : /* fixed length */
163 : 904 : *line_ptr += (len = MolfileStrnread(str, p, field_len, &q));
164 : :
165 : 904 : *q = '\0';
166 [ + + + + ]: 904 : if (!len || !(q - str))
167 : : {
168 : 106 : ret = 0; /* empty string */
169 : : }
170 : : else
171 : : {
172 [ - + ]: 798 : if ((ldata = strtol(str, &p_end, 10), p_end != q))
173 : : {
174 : 0 : ret = -1; /* wrong data: incompletely interpreted */
175 : : }
176 : : }
177 : : }
178 [ # # ]: 0 : else if (FIELD_ENDS_AT_FIRST_NON_DIGIT)
179 : : {
180 : : /* free format: field_len <= 0 */
181 : 0 : ldata = strtol(p, &p_end, 10);
182 : 0 : *line_ptr += (len = p_end - p);
183 [ # # ]: 0 : if (len == 0)
184 : : {
185 : 0 : ret = 0;
186 : : }
187 : : }
188 : : else
189 : : {
190 : : /* should not come here */
191 : 0 : ret = -1;
192 : : }
193 : :
194 [ + + + - ]: 904 : switch (data_type)
195 : : {
196 : 522 : case MOL_FMT_CHAR_INT_DATA:
197 [ + - + - ]: 522 : if (SCHAR_MIN <= ldata && ldata <= SCHAR_MAX)
198 : : {
199 : : /* from || to &&: 11-19-96 */
200 : 522 : *(S_CHAR *)data = (S_CHAR)ldata;
201 : : }
202 : : else
203 : : {
204 : 0 : *(S_CHAR *)data = (S_CHAR)0;
205 : 0 : ret = -1;
206 : : }
207 : 522 : break;
208 : 328 : case MOL_FMT_SHORT_INT_DATA:
209 [ + - + - ]: 328 : if (SHRT_MIN <= ldata && ldata <= SHRT_MAX)
210 : : {
211 : 328 : *(S_SHORT *)data = (S_SHORT)ldata;
212 : : }
213 : : else
214 : : {
215 : 0 : *(S_SHORT *)data = (S_SHORT)0;
216 : 0 : ret = -1;
217 : : }
218 : 328 : break;
219 : 54 : case MOL_FMT_LONG_INT_DATA:
220 [ + - + - ]: 54 : if (LONG_MIN < ldata && ldata < LONG_MAX)
221 : : {
222 : 54 : *(long *)data = (long)ldata;
223 : : }
224 : : else
225 : : {
226 : 0 : *(long *)data = 0L;
227 : 0 : ret = -1;
228 : : }
229 : 54 : break;
230 : 0 : default:
231 : 0 : ret = -1;
232 : : }
233 : : } /* MOL_FMT_CHAR_INT_DATA... */
234 : 904 : break;
235 : :
236 : 213 : case MOL_FMT_DOUBLE_DATA:
237 : : case MOL_FMT_FLOAT_DATA:
238 : : {
239 : : char str[MOL_FMT_MAX_VALUE_LEN + 1];
240 : :
241 [ - + ]: 213 : if (TOO_LONG_FIELD)
242 : : {
243 : 0 : ret = -1;
244 : 0 : ddata = 0.0;
245 : : }
246 [ + - ]: 213 : else if (DEFINITE_LENGTH_FIELD)
247 : : {
248 : 213 : *line_ptr += (len = MolfileStrnread(str, p, field_len, &q));
249 : 213 : *q = '\0';
250 [ + + + + ]: 213 : if (!len || !(q - str))
251 : : {
252 : : /* empty string */
253 : 106 : ddata = 0.0;
254 : 106 : ret = 0;
255 : : }
256 [ - + ]: 107 : else if ((ddata = strtod(str, &p_end), p_end != q))
257 : : {
258 : : /* wrong data */
259 : 0 : ret = -1;
260 : : }
261 : : }
262 [ # # ]: 0 : else if (FIELD_ENDS_AT_FIRST_NON_DIGIT)
263 : : {
264 : : /* free format */
265 : 0 : ddata = strtod(p, &p_end);
266 : 0 : *line_ptr += (len = p_end - p);
267 [ # # ]: 0 : if (len == 0)
268 : : {
269 : 0 : ret = 0;
270 : : }
271 : : }
272 : : else
273 : : {
274 : : /* should not come here */
275 : 0 : ret = -1; /* djb-rwth: addressing coverity ID #499478 -- see the original comment above */
276 : : }
277 : :
278 [ + - - ]: 213 : switch (data_type)
279 : : {
280 : :
281 : 213 : case MOL_FMT_DOUBLE_DATA:
282 [ + - + - ]: 213 : if (ddata != HUGE_VAL && /*ldata*/ ddata != -HUGE_VAL)
283 : : { /* replaced ldata with ddata 6-30-98 DCh */
284 : 213 : *(double *)data = ddata;
285 : : }
286 : : else
287 : : {
288 : 0 : *(double *)data = 0.0;
289 : 0 : ret = -1;
290 : : }
291 : 213 : break;
292 : :
293 : 0 : case MOL_FMT_FLOAT_DATA:
294 [ # # ]: 0 : if (fabs(ddata) <= (double)FLT_MIN)
295 : : {
296 : 0 : *(float *)data = 0.0;
297 : : }
298 [ # # ]: 0 : else if (fabs(ddata) >= (double)FLT_MAX)
299 : : {
300 : 0 : *(float *)data = 0.0;
301 : 0 : ret = -1;
302 : : }
303 : : else
304 : : {
305 : 0 : *(float *)data = (float)ddata;
306 : : }
307 : 0 : break;
308 : : }
309 : : } /* MOL_FMT_DOUBLE_DATA... */
310 : 213 : break;
311 : :
312 : 697 : case MOL_FMT_JUMP_TO_RIGHT:
313 : : {
314 : :
315 [ + + + - ]: 2718 : for (i = 0; i < field_len && p[i]; i++)
316 : : ;
317 : :
318 : 697 : *line_ptr += i;
319 : 697 : ret = i;
320 : : }
321 : 697 : break;
322 : :
323 : 0 : default:
324 : 0 : ret = -1;
325 : : }
326 : :
327 : 2389 : return ret;
328 : : }
329 : :
330 : : /****************************************************************************
331 : : Read molfile number from the name line like "Structure #22"
332 : : ****************************************************************************/
333 : 54 : long MolfileExtractStrucNum(MOL_FMT_HEADER_BLOCK *pHdr)
334 : : {
335 : : static char sStruct[] = "Structure #";
336 : : static char sINCHI[] = INCHI_NAME;
337 : 54 : long lMolfileNumber = 0;
338 : 54 : char *p, *q = NULL;
339 : :
340 [ + - ]: 54 : if (pHdr)
341 : : {
342 [ - + ]: 54 : if (!inchi_memicmp(pHdr->molname, sStruct, sizeof(sStruct) - 1))
343 : : {
344 : 0 : p = pHdr->molname + sizeof(sStruct) - 1;
345 : 0 : lMolfileNumber = strtol(p, &q, 10);
346 : 0 : p = pHdr->line2;
347 [ # # # # : 0 : if (!q || *q ||
# # ]
348 : 0 : inchi_memicmp(p, sINCHI, sizeof(sINCHI) - 1) ||
349 [ # # ]: 0 : !strstr(p + sizeof(sINCHI) - 1, "SDfile Output"))
350 : : {
351 : 0 : lMolfileNumber = 0;
352 : : }
353 : : }
354 : : }
355 : :
356 : 54 : return lMolfileNumber;
357 : : }
358 : :
359 : : /****************************************************************************
360 : : Check if MOL file contains no structure
361 : : ****************************************************************************/
362 : 108 : int MolfileHasNoChemStruc(MOL_FMT_DATA *mfdata)
363 : : {
364 [ + - - + ]: 108 : if (!mfdata || !mfdata->ctab.atoms)
365 : : {
366 : 0 : return 1;
367 : : }
368 : :
369 [ - + ]: 108 : if (mfdata->ctab.n_atoms <= 0)
370 : : {
371 : 0 : return 1;
372 : : }
373 : :
374 [ + - - + ]: 108 : if (0 < mfdata->ctab.n_bonds && !mfdata->ctab.bonds)
375 : : {
376 : 0 : return 1;
377 : : }
378 : :
379 : 108 : return 0;
380 : : }
381 : :
382 : : /****************************************************************************
383 : : Copy MOL-formatted data of SDF record or Molfile to another file
384 : : ****************************************************************************/
385 : 0 : int MolfileSaveCopy(INCHI_IOSTREAM *inp_file,
386 : : long fPtrStart,
387 : : long fPtrEnd,
388 : : FILE *outfile,
389 : : long num)
390 : : {
391 : : char line[MOL_FMT_INPLINELEN], *p;
392 : : long fPtr;
393 : 0 : int ret = 1;
394 : : char szNumber[32];
395 : :
396 [ # # ]: 0 : if (inp_file->type == INCHI_IOS_TYPE_FILE)
397 : : {
398 : :
399 : 0 : FILE *infile = inp_file->f;
400 : :
401 [ # # ]: 0 : if (!infile)
402 : : {
403 : 0 : return 1;
404 : : }
405 : :
406 [ # # ]: 0 : if (!outfile)
407 : : {
408 : 0 : return 1;
409 : : }
410 : :
411 [ # # # # ]: 0 : if (fPtrStart < 0L && fPtrEnd <= fPtrStart)
412 : : {
413 : 0 : return 1;
414 : : }
415 : :
416 [ # # ]: 0 : if (0 != fseek(infile, fPtrStart, SEEK_SET))
417 : : {
418 : 0 : return 1;
419 : : }
420 : :
421 [ # # ]: 0 : while (fPtrEnd > (fPtr = ftell(infile)) && fPtr >= 0L
422 [ # # # # ]: 0 : && inchi_fgetsLf(line, sizeof(line) - 1, inp_file))
423 : : {
424 : :
425 : 0 : line[sizeof(line) - 1] = '\0'; /* unnecessary extra precaution */
426 : :
427 [ # # # # ]: 0 : if (fPtr == fPtrStart && num)
428 : : {
429 : : int len;
430 : 0 : lrtrim(line, &len);
431 [ # # ]: 0 : len = sprintf(szNumber, "#%ld%s", num, len ? "/" : "");
432 : 0 : mystrncpy(line + len, line, sizeof(line) - len - 1);
433 : 0 : memcpy(line, szNumber, len);
434 : : }
435 : :
436 [ # # ]: 0 : if (!strchr(line, '\n'))
437 : : {
438 : 0 : p = line + strlen(line);
439 : 0 : p[0] = '\n';
440 : 0 : p[1] = '\0';
441 : : }
442 : :
443 : 0 : fputs(line, outfile);
444 : : }
445 : :
446 : 0 : ret = fseek(infile, fPtrEnd, SEEK_SET);
447 : : }
448 : 0 : else if (inp_file->type == INCHI_IOS_TYPE_STRING)
449 : : {
450 : : ;
451 : : }
452 : : else
453 : : {
454 : : ;
455 : : }
456 : :
457 : 0 : return ret;
458 : : }
459 : :
460 : :
461 : : #define MIN_STDATA_X_COORD 0.0
462 : : #define MAX_STDATA_X_COORD 256.0
463 : : #define MIN_STDATA_Y_COORD 0.0
464 : : #define MAX_STDATA_Y_COORD 256.0
465 : : #define MIN_STDATA_Z_COORD 0.0
466 : : #define MAX_STDATA_Z_COORD 256.0
467 : : #define MAX_STDATA_AVE_BOND_LENGTH 20.0
468 : : #define MIN_STDATA_AVE_BOND_LENGTH 10.0
469 : :
470 : :
471 : : /****************************************************************************
472 : : Get xyz dimensionality and normalization factors
473 : : ****************************************************************************/
474 : 54 : int MolfileGetXYZDimAndNormFactors(MOL_FMT_DATA *mfdata,
475 : : int find_norm_factors,
476 : : double *x0,
477 : : double *y0,
478 : : double *z0,
479 : : double *xmin,
480 : : double *ymin,
481 : : double *zmin,
482 : : double *scaler,
483 : : int *err,
484 : : char *pStrErr)
485 : :
486 : : {
487 : : int i;
488 : 54 : int num_dimensions = 0, num_atoms, num_bonds;
489 : 54 : double max_x = -1.0e32, max_y = -1.0e32, max_z = -1.0e32;
490 : 54 : double min_x = 1.0e32, min_y = 1.0e32, min_z = 1.0e32;
491 : 54 : double macheps = 1.0e-10, small_coeff = 0.00001;
492 : 54 : double x_coeff, y_coeff, z_coeff, coeff = 1.0, average_bond_length;
493 : :
494 : 54 : *x0 = MIN_STDATA_X_COORD;
495 : 54 : *y0 = MIN_STDATA_Y_COORD;
496 : 54 : *z0 = MIN_STDATA_Z_COORD;
497 : 54 : *xmin = *ymin = *zmin = 0.0;
498 : 54 : *scaler = coeff;
499 : :
500 [ - + ]: 54 : if (MolfileHasNoChemStruc(mfdata))
501 : : {
502 : 0 : goto exit_function;
503 : : }
504 : :
505 : 54 : num_atoms = mfdata->ctab.n_atoms;
506 [ + + ]: 673 : for (i = 0; i < num_atoms; i++)
507 : : {
508 [ + + ]: 619 : max_x = inchi_max(mfdata->ctab.atoms[i].fx, max_x);
509 [ + + ]: 619 : min_x = inchi_min(mfdata->ctab.atoms[i].fx, min_x);
510 [ + + ]: 619 : max_y = inchi_max(mfdata->ctab.atoms[i].fy, max_y);
511 [ + + ]: 619 : min_y = inchi_min(mfdata->ctab.atoms[i].fy, min_y);
512 [ + + ]: 619 : max_z = inchi_max(mfdata->ctab.atoms[i].fz, max_z);
513 [ + + ]: 619 : min_z = inchi_min(mfdata->ctab.atoms[i].fz, min_z);
514 : : }
515 : :
516 : 54 : num_bonds = 0;
517 : 54 : average_bond_length = 0.0;
518 [ + + ]: 622 : for (i = 0; i < mfdata->ctab.n_bonds; i++)
519 : : {
520 : : double dx, dy, dz;
521 : 568 : int a1 = mfdata->ctab.bonds[i].atnum1 - 1;
522 : 568 : int a2 = mfdata->ctab.bonds[i].atnum2 - 1;
523 : :
524 [ + - + - : 568 : if (a1 < 0 || a1 >= num_atoms ||
+ - ]
525 [ + - - + ]: 568 : a2 < 0 || a2 >= num_atoms ||
526 : : a1 == a2)
527 : : {
528 : 0 : *err |= 1; /* bond for invalid atom number(s); ignored */
529 : 0 : TREAT_ERR(*err, 0, "Bond to nonexistent atom");
530 : 0 : continue;
531 : : }
532 : :
533 : 568 : dx = mfdata->ctab.atoms[a1].fx - mfdata->ctab.atoms[a2].fx;
534 : 568 : dy = mfdata->ctab.atoms[a1].fy - mfdata->ctab.atoms[a2].fy;
535 : 568 : dz = mfdata->ctab.atoms[a1].fz - mfdata->ctab.atoms[a2].fz;
536 : :
537 : 568 : average_bond_length += sqrt(dx*dx + dy*dy + dz*dz);
538 : 568 : num_bonds++;
539 : : }
540 : :
541 [ - + ]: 54 : if (max_x - min_x <= small_coeff * (fabs(max_x) + fabs(min_x)))
542 : : {
543 : 0 : x_coeff = 0.0;
544 : : }
545 : : else
546 : : {
547 : 54 : x_coeff = (MAX_STDATA_X_COORD - MIN_STDATA_X_COORD) / (max_x - min_x);
548 : : }
549 : :
550 [ - + ]: 54 : if (max_y - min_y <= small_coeff * (fabs(max_y) + fabs(min_y)))
551 : : {
552 : 0 : y_coeff = 0.0;
553 : : }
554 : : else
555 : : {
556 : 54 : y_coeff = (MAX_STDATA_Y_COORD - MIN_STDATA_Y_COORD) / (max_y - min_y);
557 : : }
558 : :
559 [ + + ]: 54 : if (max_z - min_z <= small_coeff * (fabs(max_z) + fabs(min_z)))
560 : : {
561 : 53 : z_coeff = 0.0;
562 : : }
563 : : else
564 : : {
565 : 1 : z_coeff = (MAX_STDATA_Z_COORD - MIN_STDATA_Z_COORD) / (max_z - min_z);
566 : : }
567 : :
568 [ - - + + ]: 54 : num_dimensions = ((x_coeff > macheps || y_coeff > macheps) && fabs(z_coeff) < macheps)
569 : : ? 2
570 [ - + + - ]: 108 : : ( fabs( z_coeff ) > macheps ) ? 3 : 0;
571 : :
572 : :
573 [ + - ]: 54 : if (!find_norm_factors)
574 : : {
575 : 54 : goto exit_function;
576 : : }
577 : :
578 : : /* Find normalization parameters */
579 [ # # # # ]: 0 : switch (num_dimensions)
580 : : {
581 : 0 : case 0:
582 : 0 : coeff = 0.0;
583 : 0 : break;
584 : :
585 : 0 : case 2:
586 : : /* choose the smallest stretching coefficient */
587 [ # # # # ]: 0 : if (x_coeff > macheps && y_coeff > macheps)
588 : : {
589 [ # # ]: 0 : coeff = inchi_min(x_coeff, y_coeff);
590 : : }
591 [ # # ]: 0 : else if (x_coeff > macheps)
592 : : {
593 : 0 : coeff = x_coeff;
594 : : }
595 [ # # ]: 0 : else if (y_coeff > macheps)
596 : : {
597 : 0 : coeff = y_coeff;
598 : : }
599 : : else
600 : : {
601 : 0 : coeff = 1.0;
602 : : }
603 : 0 : break;
604 : :
605 : 0 : case 3:
606 : : /* choose the smallest stretching coefficient */
607 [ # # # # ]: 0 : if (x_coeff > macheps && y_coeff > macheps)
608 : : {
609 [ # # ]: 0 : coeff = inchi_min(x_coeff, y_coeff);
610 [ # # ]: 0 : coeff = inchi_min(coeff, z_coeff);
611 : : }
612 [ # # ]: 0 : else if (x_coeff > macheps)
613 : : {
614 [ # # ]: 0 : coeff = inchi_min(x_coeff, z_coeff);
615 : : }
616 [ # # ]: 0 : else if (y_coeff > macheps)
617 : : {
618 [ # # ]: 0 : coeff = inchi_min(y_coeff, z_coeff);
619 : : }
620 : : else
621 : : {
622 : 0 : coeff = z_coeff;
623 : : }
624 : 0 : break;
625 : :
626 : 0 : default:
627 : 0 : coeff = 0.0;
628 : : }
629 : :
630 [ # # ]: 0 : if (num_bonds > 0)
631 : : {
632 : :
633 : 0 : average_bond_length /= (double)num_bonds;
634 [ # # ]: 0 : if (average_bond_length * coeff > MAX_STDATA_AVE_BOND_LENGTH)
635 : : {
636 : 0 : coeff = MAX_STDATA_AVE_BOND_LENGTH / average_bond_length; /* avoid too long bonds */
637 : : }
638 [ # # ]: 0 : else if (average_bond_length * coeff < macheps)
639 : : {
640 : 0 : coeff = 1.0; /* all lengths are of zero length */
641 : : }
642 [ # # ]: 0 : else if (average_bond_length * coeff < MIN_STDATA_AVE_BOND_LENGTH)
643 : : {
644 : 0 : coeff = MIN_STDATA_AVE_BOND_LENGTH / average_bond_length; /* avoid too short bonds */
645 : : }
646 : : }
647 : :
648 : 0 : exit_function:;
649 : :
650 : 54 : *x0 = min_x;
651 : 54 : *y0 = min_y;
652 : 54 : *z0 = min_z;
653 : 54 : *xmin = MIN_STDATA_X_COORD;
654 : 54 : *ymin = MIN_STDATA_Y_COORD;
655 : 54 : *zmin = MIN_STDATA_Z_COORD;
656 : 54 : *scaler = coeff;
657 : :
658 : 54 : return num_dimensions;
659 : : }
660 : :
661 : : /****************************************************************************
662 : : Clean up MOL-format parser data
663 : : ****************************************************************************/
664 : 54 : MOL_FMT_DATA *FreeMolfileData(MOL_FMT_DATA *mfdata)
665 : : {
666 [ + - ]: 54 : if (mfdata)
667 : : {
668 : :
669 [ + - ]: 54 : if (mfdata->ctab.atoms)
670 : : {
671 [ + - ]: 54 : inchi_free(mfdata->ctab.atoms);
672 : : }
673 : :
674 [ + - ]: 54 : if (mfdata->ctab.bonds)
675 : : {
676 [ + - ]: 54 : inchi_free(mfdata->ctab.bonds);
677 : : }
678 : :
679 [ - + ]: 54 : if (mfdata->ctab.coords)
680 : : {
681 [ # # ]: 0 : inchi_free(mfdata->ctab.coords);
682 : : }
683 : :
684 : : /*if ( 0!=mfdata->ctab.sgroups.used )*/
685 : 54 : MolFmtSgroups_Free(&(mfdata->ctab.sgroups));
686 : :
687 [ + + ]: 54 : if (mfdata->ctab.v3000)
688 : : {
689 : 48 : DeleteMolfileV3000Info(mfdata->ctab.v3000);
690 : : }
691 : :
692 [ + - ]: 54 : inchi_free(mfdata);
693 : 54 : mfdata = NULL;
694 : : }
695 : :
696 : 54 : return mfdata;
697 : : }
|