LCOV - code coverage report
Current view: top level - src - mol_fmt2.c (source / functions) Coverage Total Hit
Test: InChI Unit Test Coverage Lines: 55.7 % 264 147
Test Date: 2026-05-04 07:05:02 Functions: 85.7 % 7 6
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 42.2 % 232 98

             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                 :             : }
        

Generated by: LCOV version 2.0-1