LCOV - code coverage report
Current view: top level - src - mol_fmt2.c (source / functions) Coverage Total Hit
Test: InChI Unit Test Coverage Lines: 60.2 % 264 159
Test Date: 2026-10-14 12:14:55 Functions: 85.7 % 7 6
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 48.7 % 232 113

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

Generated by: LCOV version 2.0-1