LCOV - code coverage report
Current view: top level - src - ichirvr1.c (source / functions) Coverage Total Hit
Test: InChI Unit Test Coverage Lines: 0.0 % 2222 0
Test Date: 2026-05-04 07:05:02 Functions: 0.0 % 52 0
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 0.0 % 1672 0

             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 <string.h>
      43                 :             : 
      44                 :             : /* */
      45                 :             : /*#define CHECK_WIN32_VC_HEAP*/
      46                 :             : 
      47                 :             : #include "mode.h"
      48                 :             : 
      49                 :             : #if ( READ_INCHI_STRING == 1 )
      50                 :             : 
      51                 :             : #include "ichitime.h"
      52                 :             : #include "ichirvrs.h"
      53                 :             : #include "ichicant.h"
      54                 :             : #include "ichi_io.h"
      55                 :             : /* djb-rwth: these two headers have to be included as well */
      56                 :             : #include "ichimain.h"
      57                 :             : #include "inpdef.h"
      58                 :             : 
      59                 :             : #include "bcf_s.h"
      60                 :             : 
      61                 :             : /**************************************************************************************************
      62                 :             : 
      63                 :             :   ChargeStruct fictitios structures MY_CONST CN_LIST cnList[*]
      64                 :             :   ============================================================
      65                 :             : 
      66                 :             : 
      67                 :             :   bond         flow      (+)  => Positive charge c-group
      68                 :             :   -----------------      (-)  => Negative charge c-group
      69                 :             :   Single        0        (+C) => Positive charge group for C, Si, Ge, Sn, Pb
      70                 :             :   Double        1        (-C) => Negative charge group for C, Si, Ge, Sn, Pb
      71                 :             :   Triple        2        (.)  => additional one unit of st_cap
      72                 :             : 
      73                 :             :   A) Interpretation:
      74                 :             : 
      75                 :             :   X-(-)  or X=(+)  => zero charge
      76                 :             :   X=(-)  or X-(+)  => charge = -1 or +1, respectively
      77                 :             : 
      78                 :             :   B) Information to keep:
      79                 :             : 
      80                 :             :   ordering zero-based number of the edge
      81                 :             :   to (+) or (-) from the Interpretation (A) section
      82                 :             : 
      83                 :             :   vCap  = vertex cap
      84                 :             :   vFlow = vertex flow
      85                 :             :   val   = number of edges incident to the vertex
      86                 :             :   neigh = 1-based ordering number of the adjacent vertex; 0 => no more adjacent vertices
      87                 :             :   cap   = cap of the edge to the adjacent vertex
      88                 :             :   flow  = flow of the edge to the adjacent vertex
      89                 :             : 
      90                 :             :   atom (c-point) always has number 1
      91                 :             :   c-group(s) always are the last vertices
      92                 :             :   always adjacent_neigh_number > vertex_number, that is, neigh > vertex
      93                 :             : 
      94                 :             :   Contribution to the Total Charge:
      95                 :             :   ----------------------------------
      96                 :             :   edge_cap(+) - edge_flow(+) - edge_flow(-) - Delta(+) - Delta(-)
      97                 :             : 
      98                 :             :   where edge_cap(+)  is edge capacity to c-group (+);
      99                 :             :         edge_flow(+) is edge capacity to c-group (?), (?)= (+) or (-);
     100                 :             :         Delta(?) = st_cap(?) - st_floe(?) of the c-group vertex (?), (?)= (+) or (-);
     101                 :             : 
     102                 :             : ***************************************************************************************************/
     103                 :             : /**************************************************************************************************
     104                 :             : 
     105                 :             :  Important:
     106                 :             :  vCap and vFlow      Note: since metal charge group (vert. 2-4) MUST be registered before
     107                 :             :  marked with empty         the "metal flower" (5-8) all charge group vertex numbers are
     108                 :             :  comments for vertices     less than metal flower vertices: (2,3,4) < (5,6,7,8)
     109                 :             :  1 and 5(M) should         This MAY be neded for c-group enumeration. The order is:
     110                 :             :  be set separately         t-groups, c-groups, M-flower. All types BNS_VT_M_GROUP allows to avoid duplications.
     111                 :             : 
     112                 :             :               3(+)
     113                 :             :                ||         (Metal)
     114                 :             :                ||          \|/       init charge=0; MAX_METAL_CHARGE = 16
     115                 :             :    4(-)  5(M)  2           -Fe-                     CAP(BOND_TO_BNS_VT_M_GROUP) = NUM_BONDS*CAP
     116                 :             :       \   |   /             |
     117                 :             :         \ | /
     118                 :             :           1              X(V), V=valence
     119                 :             : */
     120                 :             : MY_CONST C_NODE cnMe[5] = {
     121                 :             :     /*  vertex type       vCap  vFlow val;  neigh cap flow; neigh cap flow; neigh cap flow    vertex */
     122                 :             :     { {BNS_VERT_TYPE_ATOM,0/**/ ,0/**/,3}, {{ 2, 16,0, 0 },{ 4,  16,0, 0 }, { 0,  0,0, 0 }} },  /* 1 */
     123                 :             :     { {BNS_VT_CHRG_STRUCT,16,   16,    2}, {{ 3, 16,0,16 },{ 0,   0,0, 0 }, { 0,  0,0, 0 }} },  /* 2 */
     124                 :             :     { {BNS_VT_C_POS_M,    16,   16,    1}, {{ 0,  0,0, 0 },{ 0,   0,0, 2 }, { 0,  0,0, 0 }} },  /* 3 */
     125                 :             :     { {BNS_VT_C_NEG_M,    0 + 16,  0,    1}, {{ 0,  0,0, 0 },{ 0,   0,0, 0 }, { 0,  0,0, 0 }} },  /* 4 */
     126                 :             :     { {BNS_VT_M_GROUP,    0/**/ ,0/**/,3}, {{ 1,  3,0, 0 },{ 0,   0,0, 0 }, { 0,  0,0, 0 }} },  /* 5 */
     127                 :             : };
     128                 :             : /*
     129                 :             : #define cn_bits_Me (-1)
     130                 :             : */
     131                 :             : 
     132                 :             : /**************************************************************************************************
     133                 :             :      c=2     5(+.)
     134                 :             :      _____  /          (PNPN)
     135                 :             :     4=====3             ||||       init charge=0
     136                 :             :  c=2 \   / c=1          -N-
     137                 :             :        2                 |
     138                 :             :       ||||
     139                 :             :        1              X+(V), X(V+1), X+(V+2), X(V+3); V=valence
     140                 :             : */
     141                 :             : MY_CONST C_NODE cnPNPN[5] = {
     142                 :             :     /*  vertex type       vCap  vFlow val;  neigh cap flow; neigh cap flow; neigh cap flow    vertex */
     143                 :             :     { {BNS_VERT_TYPE_ATOM, 3,    3,    1}, {{ 2,  3,0, 3 },{ 0,   0,0, 0 }, { 0,  0,0, 0 }} },  /* 1 */
     144                 :             :     { {BNS_VT_CHRG_STRUCT, 3,    3,    3}, {{ 3,  1,0, 0 },{ 4,   2,0, 0 }, { 0,  0,0, 0 }} },  /* 2 */
     145                 :             :     { {BNS_VT_CHRG_STRUCT, 2,    2,    3}, {{ 5,  1,0, 0 },{ 4,   2,0, 2 }, { 0,  0,0, 0 }} },  /* 3 */
     146                 :             :     { {BNS_VT_CHRG_STRUCT, 2,    2,    2}, {{ 0,  0,0, 0 },{ 0,   0,0, 0 }, { 0,  0,0, 0 }} },  /* 4 */
     147                 :             :     { {BNS_VT_C_POS,       1 + 1,  0,    1}, {{ 0,  0,0, 0 },{ 0,   0,0, 0 }, { 0,  0,0, 0 }} },  /* 5 */
     148                 :             : };
     149                 :             : /*
     150                 :             : #define cn_bits_PNPN MAKE_CN_BITS(cn_bits_P, cn_bits_N, cn_bits_P, cn_bits_N)
     151                 :             : */
     152                 :             : /**************************************************************************************************
     153                 :             :              5(+)
     154                 :             :      c=1   //          (NPNP)
     155                 :             :     4=====3             ||||       init charge=0
     156                 :             :  c=1 \   / c=2          -N-
     157                 :             :        2                 |
     158                 :             :       ||||
     159                 :             :        1              X(V), X+(V+1), X(V+2), X+(V+3); V=valence
     160                 :             : */
     161                 :             : MY_CONST C_NODE cnNPNP[5] = {
     162                 :             :     /*  vertex type       vCap  vFlow val;  neigh cap flow; neigh cap flow; neigh cap flow    vertex */
     163                 :             :     { {BNS_VERT_TYPE_ATOM, 3,    3,    1}, {{ 2,  3,0, 3 },{ 0,   0,0, 0 }, { 0,  0,0, 0 }} },  /* 1 */
     164                 :             :     { {BNS_VT_CHRG_STRUCT, 3,    3,    3}, {{ 3,  2,0, 0 },{ 4,   1,0, 0 }, { 0,  0,0, 0 }} },  /* 2 */
     165                 :             :     { {BNS_VT_CHRG_STRUCT, 2,    2,    3}, {{ 5,  1,0, 1 },{ 4,   1,0, 1 }, { 0,  0,0, 0 }} },  /* 3 */
     166                 :             :     { {BNS_VT_CHRG_STRUCT, 1,    1,    2}, {{ 0,  0,0, 0 },{ 0,   0,0, 0 }, { 0,  0,0, 0 }} },  /* 4 */
     167                 :             :     { {BNS_VT_C_POS,       0 + 1,  1,    1}, {{ 0,  0,0, 0 },{ 0,   0,0, 0 }, { 0,  0,0, 0 }} },  /* 5 */
     168                 :             : };
     169                 :             : /*
     170                 :             : #define cn_bits_NPNP MAKE_CN_BITS(cn_bits_N, cn_bits_P, cn_bits_N, cn_bits_P)
     171                 :             : */
     172                 :             : /********************* end new ********************************************************************/
     173                 :             : 
     174                 :             : 
     175                 :             : /**************************************************************************************************
     176                 :             :              5(+)
     177                 :             :            //          (NPN)
     178                 :             :     4=====3             |||       init charge=0
     179                 :             :      \   /              -N-
     180                 :             :        2                 |
     181                 :             :       |||
     182                 :             :        1              X(V), X+(V+1), X(V+2); V=valence
     183                 :             : */
     184                 :             : MY_CONST C_NODE cnNPN[5] = {
     185                 :             :     /*  vertex type       vCap  vFlow val;  neigh cap flow; neigh cap flow; neigh cap flow    vertex */
     186                 :             :     { {BNS_VERT_TYPE_ATOM, 2,    2,    1}, {{ 2,  2,0, 2 },{ 0,   0,0, 0 }, { 0,  0,0, 0 }} },  /* 1 */
     187                 :             :     { {BNS_VT_CHRG_STRUCT, 2,    2,    3}, {{ 3,  1,0, 0 },{ 4,   1,0, 0 }, { 0,  0,0, 0 }} },  /* 2 */
     188                 :             :     { {BNS_VT_CHRG_STRUCT, 2,    2,    3}, {{ 5,  1,0, 1 },{ 4,   1,0, 1 }, { 0,  0,0, 0 }} },  /* 3 */
     189                 :             :     { {BNS_VT_CHRG_STRUCT, 1,    1,    2}, {{ 0,  0,0, 0 },{ 0,   0,0, 0 }, { 0,  0,0, 0 }} },  /* 4 */
     190                 :             :     { {BNS_VT_C_POS,       1,    1,    1}, {{ 0,  0,0, 0 },{ 0,   0,0, 0 }, { 0,  0,0, 0 }} },  /* 5 */
     191                 :             : };
     192                 :             : /*
     193                 :             : #define cn_bits_NPN MAKE_CN_BITS(cn_bits_N, cn_bits_P, cn_bits_N, 0)
     194                 :             : */
     195                 :             : /**************************************************************************************************
     196                 :             :              5(+.)
     197                 :             :             /          (PNP)
     198                 :             :     4=====3             |||       init charge=0
     199                 :             :      \   /             -Cl-
     200                 :             :        2                /\
     201                 :             :       |||
     202                 :             :        1              X+(V), X(V+1), X+(V+2); V=valence
     203                 :             : */
     204                 :             : MY_CONST C_NODE cnPNP[5] = {
     205                 :             :     /*  vertex type       vCap  vFlow val;  neigh cap flow; neigh cap flow; neigh cap flow    vertex */
     206                 :             :     { {BNS_VERT_TYPE_ATOM, 2,    2,    1}, {{ 2,  2,0, 2 },{ 0,   0,0, 0 }, { 0,  0,0, 0 }} },  /* 1 */
     207                 :             :     { {BNS_VT_CHRG_STRUCT, 2,    2,    3}, {{ 3,  1,0, 0 },{ 4,   1,0, 0 }, { 0,  0,0, 0 }} },  /* 2 */
     208                 :             :     { {BNS_VT_CHRG_STRUCT, 1,    1,    3}, {{ 5,  1,0, 0 },{ 4,   1,0, 1 }, { 0,  0,0, 0 }} },  /* 3 */
     209                 :             :     { {BNS_VT_CHRG_STRUCT, 1,    1,    2}, {{ 0,  0,0, 0 },{ 0,   0,0, 0 }, { 0,  0,0, 0 }} },  /* 4 */
     210                 :             :     { {BNS_VT_C_POS,       1 + 1,  0,    1}, {{ 0,  0,0, 0 },{ 0,   0,0, 0 }, { 0,  0,0, 0 }} },  /* 5 */
     211                 :             : };
     212                 :             : /*
     213                 :             : #define cn_bits_PNP MAKE_CN_BITS(cn_bits_P, cn_bits_N, cn_bits_P, 0)
     214                 :             : */
     215                 :             : /**************************************************************************************************
     216                 :             : 
     217                 :             :                       (MNP)
     218                 :             :                        \ /        init charge=0
     219                 :             :                         N(.)
     220                 :             :    3(-)  2(+)          / \
     221                 :             :       \ //
     222                 :             :       1(.)           X-(V), X(V+1), X+(V+2); V=valence
     223                 :             : */
     224                 :             : MY_CONST C_NODE cnMNP[3] = {
     225                 :             :     /*  vertex type       vCap  vFlow val;  neigh cap flow; neigh cap flow; neigh cap flow    vertex */
     226                 :             :     { {BNS_VERT_TYPE_ATOM, 2,    1,    2}, {{ 2,  1,0, 1 },{ 3,   1,0, 0 }, { 0,  0,0, 0 }} },  /* 1 */
     227                 :             :     { {BNS_VT_C_POS,       1,    1,    1}, {{ 0,  0,0, 0 },{ 0,   0,0, 0 }, { 0,  0,0, 0 }} },  /* 2 */
     228                 :             :     { {BNS_VT_C_NEG,       0 + 1,  0,    1}, {{ 0,  0,0, 0 },{ 0,   0,0, 0 }, { 0,  0,0, 0 }} }   /* 3 */
     229                 :             : };
     230                 :             : /*
     231                 :             : #define cn_bits_MNP  MAKE_CN_BITS(cn_bits_M, cn_bits_N, cn_bits_P, 0)
     232                 :             : */
     233                 :             : #ifdef NEVER
     234                 :             : /************************** not used **************************************************************
     235                 :             :                         (PNM)
     236                 :             :  5(-)      4(+)         \\ /
     237                 :             :    \       //             B(.)    init charge=0
     238                 :             :     3     2              / \
     239                 :             :      \\  /
     240                 :             :        1(.)           X+(V), X(V+1), X+(V+2); V=valence
     241                 :             : */
     242                 :             : MY_CONST C_NODE cnPNM[5] = {
     243                 :             :     /*  vertex type       vCap  vFlow val;  neigh cap flow; neigh cap flow; neigh cap flow    vertex */
     244                 :             :     { {BNS_VERT_TYPE_ATOM, 2,    1,    2}, {{ 2,  1,0, 0 },{ 3,   1,0, 1 }, { 0,  0,0, 0 }} },  /* 1 */
     245                 :             :     { {BNS_VT_CHRG_STRUCT, 1,    1,    2}, {{ 4,  1,0, 1 },{ 0,   0,0, 0 }, { 0,  0,0, 0 }} },  /* 2 */
     246                 :             :     { {BNS_VT_CHRG_STRUCT, 1,    1,    2}, {{ 5,  1,0, 0 },{ 0,   0,0, 0 }, { 0,  0,0, 0 }} },  /* 3 */
     247                 :             :     { {BNS_VT_C_POS,       1,    1,    1}, {{ 0,  0,0, 0 },{ 0,   0,0, 0 }, { 0,  0,0, 0 }} },  /* 4 */
     248                 :             :     { {BNS_VT_C_NEG,       0 + 1,  0,    1}, {{ 0,  0,0, 0 },{ 0,   0,0, 0 }, { 0,  0,0, 0 }} },  /* 5 */
     249                 :             : };
     250                 :             : 
     251                 :             : #define cn_bits_PNM  MAKE_CN_BITS(cn_bits_P, cn_bits_N, cn_bits_M, 0)
     252                 :             : 
     253                 :             : #endif
     254                 :             : 
     255                 :             : /**************************************************************************************************
     256                 :             :    4(-)   3(+.)        (PNM)
     257                 :             :      \   /              |||        init charge=0
     258                 :             :        2               --P--
     259                 :             :       |||               / \
     260                 :             :        1              X-(V), X(V+1), X+(V+2); V=valence
     261                 :             : */
     262                 :             : MY_CONST C_NODE cnPNM[4] = {
     263                 :             :     /*  vertex type       vCap  vFlow val;  neigh cap flow; neigh cap flow; neigh cap flow    vertex */
     264                 :             :     { {BNS_VERT_TYPE_ATOM, 2,    2,    1}, {{ 2,  2,0, 2 },{ 0,   0,0, 0 }, { 0,  0,0, 0 }} },  /* 1 */
     265                 :             :     { {BNS_VT_CHRG_STRUCT, 2,    2,    3}, {{ 3,  1,0, 0 },{ 4,   1,0, 0 }, { 0,  0,0, 0 }} },  /* 2 */
     266                 :             :     { {BNS_VT_C_POS,       1 + 1,  0,    1}, {{ 0,  0,0, 0 },{ 0,   0,0, 0 }, { 0,  0,0, 0 }} },  /* 3 */
     267                 :             :     { {BNS_VT_C_NEG,       0 + 1,  0,    1}, {{ 0,  0,0, 0 },{ 0,   0,0, 0 }, { 0,  0,0, 0 }} },  /* 4 */
     268                 :             : }; /* explanaton of vCap:  ^ ^  */
     269                 :             : /*         additional dot:/   \ capacity of the edge to (+) or (-) vertex */
     270                 :             : /*
     271                 :             : #define cn_bits_PNM  MAKE_CN_BITS(cn_bits_P, cn_bits_N, cn_bits_M, 0)
     272                 :             : */
     273                 :             : /**************************************************************************************************
     274                 :             :            5(+C)
     275                 :             :           //                        init charge=0
     276                 :             :  6(-C)  4
     277                 :             :      \ /               (EN)  E=either +1 or -1
     278                 :             :       3                 |
     279                 :             :       ||               -C(.)-
     280                 :             :       2                 |
     281                 :             :       |
     282                 :             :       1(.)            X-(V), X+(V), X(V+1); V=valence
     283                 :             : */
     284                 :             : MY_CONST C_NODE cnEN[6] = {
     285                 :             :     /*  vertex type       vCap  vFlow val;  neigh cap flow; neigh cap flow; neigh cap flow    vertex */
     286                 :             :     { {BNS_VERT_TYPE_ATOM, 1,    0,    1}, {{ 2,  1,0, 0 },{ 0,   0,0, 0 }, { 0,  0,0, 0 }} },  /* 1 */
     287                 :             :     { {BNS_VT_CHRG_STRUCT, 1,    1,    2}, {{ 3,  1,0, 1 },{ 0,   0,0, 0 }, { 0,  0,0, 0 }} },  /* 2 */
     288                 :             :     { {BNS_VT_CHRG_STRUCT, 1,    1,    3}, {{ 4,  1,0, 0 },{ 6,   1,0, 0 }, { 0,  0,0, 0 }} },  /* 3 */
     289                 :             :     { {BNS_VT_CHRG_STRUCT, 1,    1,    2}, {{ 5,  1,0, 1 },{ 0,   0,0, 0 }, { 0,  0,0, 0 }} },  /* 4 */
     290                 :             :     { {BNS_VT_C_POS_C,     0 + 1,  1,    1}, {{ 0,  0,0, 0 },{ 0,   0,0, 0 }, { 0,  0,0, 0 }} },  /* 5 */
     291                 :             :     { {BNS_VT_C_NEG_C,     0 + 1,  0,    1}, {{ 0,  0,0, 0 },{ 0,   0,0, 0 }, { 0,  0,0, 0 }} }   /* 6 */
     292                 :             : };
     293                 :             : /*
     294                 :             : #define cn_bits_EN  MAKE_CN_BITS(cn_bits_P | cn_bits_M, cn_bits_N, 0, 0)
     295                 :             : */
     296                 :             : /**************************************************************************************************
     297                 :             :              5(-)
     298                 :             :             /          (NMN)        init charge=0
     299                 :             :     4=====3             |||
     300                 :             :      \   /              -X-
     301                 :             :        2                /\
     302                 :             :       |||
     303                 :             :        1              X(V), X-(V+1), X(V+2); V=valence
     304                 :             : */
     305                 :             : MY_CONST C_NODE cnNMN[5] = {
     306                 :             :     /*  vertex type       vCap  vFlow val;  neigh cap flow; neigh cap flow; neigh cap flow    vertex */
     307                 :             :     { {BNS_VERT_TYPE_ATOM, 2,    2,    1}, {{ 2,  2,0, 2 },{ 0,   0,0, 0 }, { 0,  0,0, 0 }} },  /* 1 */
     308                 :             :     { {BNS_VT_CHRG_STRUCT, 2,    2,    3}, {{ 3,  1,0, 0 },{ 4,   1,0, 0 }, { 0,  0,0, 0 }} },  /* 2 */
     309                 :             :     { {BNS_VT_CHRG_STRUCT, 1,    1,    3}, {{ 5,  1,0, 0 },{ 4,   1,0, 1 }, { 0,  0,0, 0 }} },  /* 3 */
     310                 :             :     { {BNS_VT_CHRG_STRUCT, 1,    1,    2}, {{ 0,  0,0, 0 },{ 0,   0,0, 0 }, { 0,  0,0, 0 }} },  /* 4 */
     311                 :             :     { {BNS_VT_C_NEG,       0 + 1,  0,    1}, {{ 0,  0,0, 0 },{ 0,   0,0, 0 }, { 0,  0,0, 0 }} }   /* 5 */
     312                 :             : };
     313                 :             : /*
     314                 :             : #define cn_bits_NMN  MAKE_CN_BITS(cn_bits_N, cn_bits_M, cn_bits_N, 0)
     315                 :             : */
     316                 :             : /**************************************************************************************************
     317                 :             :            4(+)
     318                 :             :           //           (NE)  E=either +1 or -1
     319                 :             :   5(-)  3               ||
     320                 :             :      \ /               -X-          init charge=0
     321                 :             :       2                 |
     322                 :             :       ||
     323                 :             :       1               X(V), X+(V+1), X-(V+1); V=valence
     324                 :             : */
     325                 :             : MY_CONST C_NODE cnNE[5] = {
     326                 :             :     /*  vertex type       vCap  vFlow val;  neigh cap flow; neigh cap flow; neigh cap flow    vertex */
     327                 :             :     { {BNS_VERT_TYPE_ATOM, 1,    1,    1}, {{ 2,  1,0, 1 },{ 0,   0,0, 0 }, { 0,  0,0, 0 }} },  /* 1 */
     328                 :             :     { {BNS_VT_CHRG_STRUCT, 1,    1,    3}, {{ 3,  1,0, 0 },{ 5,   1,0, 0 }, { 0,  0,0, 0 }} },  /* 2 */
     329                 :             :     { {BNS_VT_CHRG_STRUCT, 1,    1,    2}, {{ 4,  1,0, 1 },{ 0,   0,0, 0 }, { 0,  0,0, 0 }} },  /* 3 */
     330                 :             :     { {BNS_VT_C_POS,       0 + 1,  1,    1}, {{ 0,  0,0, 0 },{ 0,   0,0, 0 }, { 0,  0,0, 0 }} },  /* 4 */
     331                 :             :     { {BNS_VT_C_NEG,       0 + 1,  0,    1}, {{ 0,  0,0, 0 },{ 0,   0,0, 0 }, { 0,  0,0, 0 }} }   /* 5 */
     332                 :             : };
     333                 :             : /*
     334                 :             : #define cn_bits_NE  MAKE_CN_BITS(cn_bits_N, cn_bits_P | cn_bits_M, 0, 0)
     335                 :             : */
     336                 :             : /**************************************************************************************************
     337                 :             : 6(-)         5(+)
     338                 :             :   \        //          (NEN)
     339                 :             :     4=====3             |||         init charge=0
     340                 :             :      \   /              -X-
     341                 :             :        2                 |
     342                 :             :       |||
     343                 :             :        1              X(V), X+(V+1), X-(V+1), X(V+2); V=valence
     344                 :             : */
     345                 :             : MY_CONST C_NODE cnNEN[6] = {
     346                 :             :     /*  vertex type       vCap  vFlow val;  neigh cap flow; neigh cap flow; neigh cap flow    vertex */
     347                 :             :     { {BNS_VERT_TYPE_ATOM, 2,    2,    1}, {{ 2,  2,0, 2 },{ 0,   0,0, 0 }, { 0,  0,0, 0 }} },  /* 1 */
     348                 :             :     { {BNS_VT_CHRG_STRUCT, 2,    2,    3}, {{ 3,  1,0, 0 },{ 4,   1,0, 0 }, { 0,  0,0, 0 }} },  /* 2 */
     349                 :             :     { {BNS_VT_CHRG_STRUCT, 2,    2,    3}, {{ 5,  1,0, 1 },{ 4,   1,0, 1 }, { 0,  0,0, 0 }} },  /* 3 */
     350                 :             :     { {BNS_VT_CHRG_STRUCT, 1,    1,    3}, {{ 6,  1,0, 0 },{ 0,   0,0, 0 }, { 0,  0,0, 0 }} },  /* 4 */
     351                 :             :     { {BNS_VT_C_POS,       0 + 1,  1,    1}, {{ 0,  0,0, 0 },{ 0,   0,0, 0 }, { 0,  0,0, 0 }} },  /* 5 */
     352                 :             :     { {BNS_VT_C_NEG,       0 + 1,  0,    1}, {{ 0,  0,0, 0 },{ 0,   0,0, 0 }, { 0,  0,0, 0 }} },  /* 6 */
     353                 :             : };
     354                 :             : /*
     355                 :             : #define cn_bits_NEN  MAKE_CN_BITS(cn_bits_N, cn_bits_M | cn_bits_N, cn_bits_N, 0)
     356                 :             : */
     357                 :             : /*=======================================================*/
     358                 :             : /**************************************************************************************************
     359                 :             :                         (NP)
     360                 :             :                          ||
     361                 :             :                         -X-         init charge=0
     362                 :             :       2(+)               |
     363                 :             :       ||
     364                 :             :        1              X(V), X+(V+1); V=valence
     365                 :             : */
     366                 :             : MY_CONST C_NODE cnNP[2] = {
     367                 :             :     /*  vertex type       vCap  vFlow val;  neigh cap flow; neigh cap flow; neigh cap flow    vertex */
     368                 :             :     { {BNS_VERT_TYPE_ATOM, 1,    1,    1}, {{ 2,  1,0, 1 },{ 0,   0,0, 0 }, { 0,  0,0, 0 }} },  /* 1 */
     369                 :             :     { {BNS_VT_C_POS,       0 + 1,  1,    1}, {{ 0,  0,0, 0 },{ 0,   0,0, 0 }, { 0,  0,0, 0 }} },  /* 2 */
     370                 :             : };
     371                 :             : /*
     372                 :             : #define cn_bits_NP  MAKE_CN_BITS(cn_bits_N, cn_bits_P, 0, 0)
     373                 :             : */
     374                 :             : /**************************************************************************************************
     375                 :             :                         (PN)
     376                 :             :       3(+.)              ||         init charge=0  [because cap(+)-flow(+)-Delta=1-0-1=0]
     377                 :             :        |                -X-
     378                 :             :        2                 |
     379                 :             :       ||
     380                 :             :        1              X+(V), X(V+1); V=valence
     381                 :             : */
     382                 :             : MY_CONST C_NODE cnPN[3] = {
     383                 :             :     /*  vertex type       vCap  vFlow val;  neigh cap flow; neigh cap flow; neigh cap flow    vertex */
     384                 :             :     { {BNS_VERT_TYPE_ATOM, 1,    1,    1}, {{ 2,  1,0, 1 },{ 0,   0,0, 0 }, { 0,  0,0, 0 }} },  /* 1 */
     385                 :             :     { {BNS_VT_CHRG_STRUCT, 1,    1,    2}, {{ 3,  1,0, 0 },{ 0,   0,0, 0 }, { 0,  0,0, 0 }} },  /* 2 */
     386                 :             :     { {BNS_VT_C_POS,       1 + 1,  0,    1}, {{ 0,  0,0, 0 },{ 0,   0,0, 0 }, { 0,  0,0, 0 }} },  /* 3 */
     387                 :             : };
     388                 :             : /*
     389                 :             : #define cn_bits_PN  MAKE_CN_BITS(cn_bits_P, cn_bits_N, 0, 0)
     390                 :             : */
     391                 :             : /**************************************************************************************************
     392                 :             :                         (NM)
     393                 :             :       3(-)               ||         init charge=0
     394                 :             :        |                -X-
     395                 :             :        2                 |
     396                 :             :       ||
     397                 :             :        1              X(V), X-(V+1); V=valence
     398                 :             : */
     399                 :             : MY_CONST C_NODE cnNM[3] = {
     400                 :             :     /*  vertex type       vCap  vFlow; val; neigh cap flow; neigh cap flow; neigh cap flow    vertex */
     401                 :             :     { {BNS_VERT_TYPE_ATOM, 1,    1,    1}, {{ 2,  1,0, 1 },{ 0,   0,0, 0 }, { 0,  0,0, 0 }} },  /* 1 */
     402                 :             :     { {BNS_VT_CHRG_STRUCT, 1,    1,    2}, {{ 3,  1,0, 0 },{ 0,   0,0, 0 }, { 0,  0,0, 0 }} },  /* 2 */
     403                 :             :     { {BNS_VT_C_NEG,       0 + 1,  0,    1}, {{ 0,  0,0, 0 },{ 0,   0,0, 0 }, { 0,  0,0, 0 }} },  /* 3 */
     404                 :             : };
     405                 :             : /*
     406                 :             : #define cn_bits_NM  MAKE_CN_BITS(cn_bits_N, cn_bits_M, 0, 0)
     407                 :             : */
     408                 :             : /**************************************************************************************************
     409                 :             :                         (MN)
     410                 :             :                          |
     411                 :             :                         -X-         init charge=0
     412                 :             :       2(-)               |
     413                 :             :        |
     414                 :             :        1(.)           X-(V), X(V+1); V=valence
     415                 :             : */
     416                 :             : MY_CONST C_NODE cnMN[2] = {
     417                 :             :     /*  vertex type       vCap  vFlow val;  neigh cap flow; neigh cap flow; neigh cap flow    vertex */
     418                 :             :     { {BNS_VERT_TYPE_ATOM, 1,    0,    1}, {{ 2,  1,0, 0 },{ 0,   0,0, 0 }, { 0,  0,0, 0 }} },  /* 1 */
     419                 :             :     { {BNS_VT_C_NEG,       0 + 1,  0,    1}, {{ 0,  0,0, 0 },{ 0,   0,0, 0 }, { 0,  0,0, 0 }} },  /* 2 */
     420                 :             : };
     421                 :             : /*
     422                 :             : #define cn_bits_MN  MAKE_CN_BITS(cn_bits_M, cn_bits_N, 0, 0)
     423                 :             : */
     424                 :             : /**************************************************************************************************
     425                 :             :                         (P)
     426                 :             :                          |
     427                 :             :                         -X-         init charge=0
     428                 :             :       2(+.)              |
     429                 :             :        |
     430                 :             :        1              X+(V); V=valence; all chemical (real) bonds to X have cap=0
     431                 :             : */
     432                 :             : MY_CONST C_NODE cnP_[2] = {
     433                 :             :     /*  vertex type       vCap  vFlow val;  neigh cap flow; neigh cap flow; neigh cap flow    vertex */
     434                 :             :     { {BNS_VERT_TYPE_ATOM, 0,    0,    1}, {{ 2,  1,1, 0 },{ 0,   0,0, 0 }, { 0,  0,0, 0 }} },  /* 1 */
     435                 :             :     { {BNS_VT_C_POS,       1 + 1,  0,    1}, {{ 0,  0,0, 0 },{ 0,   0,0, 0 }, { 0,  0,0, 0 }} },  /* 2 */
     436                 :             : };
     437                 :             : /*
     438                 :             : #define cn_bits_P_  MAKE_CN_BITS(cn_bits_P, 0, 0, 0)
     439                 :             : */
     440                 :             : #ifdef NEVER
     441                 :             : /**************************************************************************************************
     442                 :             :                         (M)
     443                 :             :                          |
     444                 :             :                         -X-         init charge=-1 on atom
     445                 :             :       2(-)               |
     446                 :             :        |
     447                 :             :        1(.)           X+(V); V=valence; all chemical (real) bonds to X have cap=0
     448                 :             : */
     449                 :             : MY_CONST C_NODE cnM_[2] = {
     450                 :             :     /*  vertex type       vCap  vFlow val;  neigh cap flow; neigh cap flow; neigh cap flow    vertex */
     451                 :             :     { {BNS_VERT_TYPE_ATOM, 1,    0,    1}, {{ 2,  1,0, 0 },{ 0,   0,0, 0 }, { 0,  0,0, 0 }} },  /* 1 */
     452                 :             :     { {BNS_VT_C_NEG,       0 + 1,  0,    1}, {{ 0,  0,0, 0 },{ 0,   0,0, 0 }, { 0,  0,0, 0 }} },  /* 2 */
     453                 :             : };
     454                 :             : #endif
     455                 :             : 
     456                 :             : MY_CONST C_NODE cnM_[1] = {
     457                 :             :     /*  vertex type       vCap  vFlow val;  neigh cap flow; neigh cap flow; neigh cap flow    vertex */
     458                 :             :     { {BNS_VERT_TYPE_ATOM, 0,    0,    0}, {{ 0,  0,0, 0 },{ 0,   0,0, 0 }, { 0,  0,0, 0 }} },  /* 1 */
     459                 :             : };
     460                 :             : /*
     461                 :             : #define cn_bits_M_  MAKE_CN_BITS(cn_bits_M, 0, 0, 0)
     462                 :             : */
     463                 :             : /**************************************************************************************************
     464                 :             : 
     465                 :             : 
     466                 :             :                         -X-         init charge=0
     467                 :             :                          |
     468                 :             : 
     469                 :             :        1              X(V); V=valence;
     470                 :             : */
     471                 :             : MY_CONST C_NODE cnN_[1] = {
     472                 :             :     /*  vertex type       vCap  vFlow val;  neigh cap flow; neigh cap flow; neigh cap flow    vertex */
     473                 :             :     { {BNS_VERT_TYPE_ATOM, 0,    0,    0}, {{ 0,  0,0, 0 },{ 0,   0,0, 0 }, { 0,  0,0, 0 }} },  /* 1 */
     474                 :             : };
     475                 :             : /*
     476                 :             : #define cn_bits_N_  MAKE_CN_BITS(cn_bits_N, 0, 0, 0)
     477                 :             : */
     478                 :             : /**************************************************************************************************/
     479                 :             : 
     480                 :             : 
     481                 :             : MY_CONST CN_LIST cnList[] = {
     482                 :             :     {cnPNPN, cn_bits_PNPN, 0, sizeof( cnPNPN ) / sizeof( cnPNPN[0] )},    /*  0 */
     483                 :             :     {cnNPNP, cn_bits_NPNP, 0, sizeof( cnNPNP ) / sizeof( cnNPNP[0] )},    /*  1 */
     484                 :             :     {cnNPN,  cn_bits_NPN,  0, sizeof( cnNPN ) / sizeof( cnNPN[0] )},      /*  2 */
     485                 :             :     {cnPNP,  cn_bits_PNP,  0, sizeof( cnPNP ) / sizeof( cnPNP[0] )},      /*  3 */
     486                 :             :     {cnMNP,  cn_bits_MNP,  0, sizeof( cnMNP ) / sizeof( cnMNP[0] )},      /*  4 */
     487                 :             :     {cnPNM,  cn_bits_PNM,  0, sizeof( cnPNM ) / sizeof( cnPNM[0] )},      /*  5 */
     488                 :             :     {cnEN,   cn_bits_EN ,  0, sizeof( cnEN ) / sizeof( cnEN[0] )},        /*  6 */
     489                 :             :     {cnNMN,  cn_bits_NMN,  0, sizeof( cnNMN ) / sizeof( cnNMN[0] )},      /*  7 */
     490                 :             :     {cnNE,   cn_bits_NE ,  0, sizeof( cnNE ) / sizeof( cnNE[0] )},        /*  8 */
     491                 :             :     {cnNEN,  cn_bits_NEN,  0, sizeof( cnNEN ) / sizeof( cnNEN[0] )},      /*  9 */
     492                 :             :     {cnNP,   cn_bits_NP,   0, sizeof( cnNP ) / sizeof( cnNP[0] )},        /* 10 */
     493                 :             :     {cnPN,   cn_bits_PN,   0, sizeof( cnPN ) / sizeof( cnPN[0] )},        /* 11 */
     494                 :             :     {cnNM,   cn_bits_NM,   0, sizeof( cnNM ) / sizeof( cnNM[0] )},        /* 12 */
     495                 :             :     {cnMN,   cn_bits_MN,   0, sizeof( cnMN ) / sizeof( cnMN[0] )},        /* 13 */
     496                 :             :     {cnP_,   cn_bits_P_,   0, sizeof( cnP_ ) / sizeof( cnP_[0] )},        /* 14 */
     497                 :             :     {cnM_,   cn_bits_M_,  -1, sizeof( cnM_ ) / sizeof( cnM_[0] )},        /* 15 */
     498                 :             :     {cnN_,   cn_bits_N_,   0, sizeof( cnN_ ) / sizeof( cnN_[0] )},        /* 16 */
     499                 :             :     {cnMe,   cn_bits_Me,   0, sizeof( cnMe ) / sizeof( cnMe[0] )}         /* 17 */
     500                 :             : };
     501                 :             : 
     502                 :             : #define cnListIndexMe (17)  /* index of {cnMe, cn_bits_Me,... } element of cnList[] */
     503                 :             : 
     504                 :             : const int cnListNumEl = (int) ( sizeof( cnList ) / sizeof( cnList[0] ) );
     505                 :             : 
     506                 :             : 
     507                 :             : 
     508                 :             : /****************************************************************************/
     509                 :           0 : void clear_t_group_info( T_GROUP_INFO *ti )
     510                 :             : {
     511         [ #  # ]:           0 :     if (!ti)
     512                 :             :     {
     513                 :           0 :         return;
     514                 :             :     }
     515                 :             :     else
     516                 :             :     {
     517                 :           0 :         T_GROUP   *t_group = ti->t_group;
     518                 :           0 :         int       max_num_t_groups = ti->max_num_t_groups;
     519                 :           0 :         AT_NUMB   *tGroupNumber = ti->tGroupNumber;
     520                 :           0 :         int       num_t_groups = ti->num_t_groups;
     521                 :           0 :         AT_NUMB   *nEndpointAtomNumber = ti->nEndpointAtomNumber;
     522                 :           0 :         int       nNumEndpoints = ti->nNumEndpoints;
     523                 :           0 :         AT_NUMB   *nIsotopicEndpointAtomNumber = ti->nIsotopicEndpointAtomNumber;
     524                 :           0 :         int       nNumIsotopicEndpoints = ti->nNumIsotopicEndpoints;
     525                 :           0 :         memset( ti, 0, sizeof( *ti ) ); /* djb-rwth: memset_s C11/Annex K variant? */
     526         [ #  # ]:           0 :         if (t_group)
     527                 :             :         {
     528                 :           0 :             memset( t_group, 0, sizeof( t_group[0] )*max_num_t_groups ); /* djb-rwth: memset_s C11/Annex K variant? */
     529                 :             :         }
     530                 :             :         else
     531                 :             :         {
     532                 :           0 :             max_num_t_groups = 0;
     533                 :             :         }
     534         [ #  # ]:           0 :         if (tGroupNumber)
     535                 :             :         {
     536                 :           0 :             memset( tGroupNumber, 0, sizeof( tGroupNumber[0] )*num_t_groups ); /* djb-rwth: memset_s C11/Annex K variant? */
     537                 :             :         }
     538                 :             :         else
     539                 :             :         {
     540                 :           0 :             num_t_groups = 0;
     541                 :             :         }
     542         [ #  # ]:           0 :         if (nEndpointAtomNumber)
     543                 :             :         {
     544                 :           0 :             memset( nEndpointAtomNumber, 0, sizeof( nEndpointAtomNumber[0] )*nNumEndpoints ); /* djb-rwth: memset_s C11/Annex K variant? */
     545                 :             :         }
     546                 :             :         else
     547                 :             :         {
     548                 :           0 :             nNumEndpoints = 0;
     549                 :             :         }
     550         [ #  # ]:           0 :         if (nIsotopicEndpointAtomNumber)
     551                 :             :         {
     552                 :           0 :             memset( nIsotopicEndpointAtomNumber, 0, sizeof( nIsotopicEndpointAtomNumber[0] )*nNumIsotopicEndpoints ); /* djb-rwth: memset_s C11/Annex K variant? */
     553                 :             :         }
     554                 :             :         else
     555                 :             :         {
     556                 :           0 :             nNumIsotopicEndpoints = 0;
     557                 :             :         }
     558                 :             : 
     559                 :           0 :         ti->t_group = t_group;
     560                 :           0 :         ti->max_num_t_groups = max_num_t_groups;
     561                 :           0 :         ti->tGroupNumber = tGroupNumber;
     562                 :           0 :         ti->num_t_groups = num_t_groups;
     563                 :           0 :         ti->nEndpointAtomNumber = nEndpointAtomNumber;
     564                 :           0 :         ti->nNumEndpoints = nNumEndpoints;
     565                 :           0 :         ti->nIsotopicEndpointAtomNumber = nIsotopicEndpointAtomNumber;
     566                 :             : 
     567                 :           0 :         ti->nNumIsotopicEndpoints = nNumIsotopicEndpoints;
     568                 :             :     }
     569                 :             : 
     570                 :           0 :     return;
     571                 :             : }
     572                 :             : 
     573                 :             : 
     574                 :             : /****************************************************************************/
     575                 :           0 : int GetTgroupInfoFromInChI( T_GROUP_INFO *ti,
     576                 :             :                             inp_ATOM *at,
     577                 :             :                             AT_NUMB *endpoint,
     578                 :             :                             INChI *pInChI )
     579                 :             : {
     580                 :             :     int ret, i, j, k, itg, num_atoms, len_tg, num_t_groups; /* djb-rwth: removing redundant variables */
     581                 :           0 :     AT_NUMB   *tGroupNumber = NULL;
     582                 :             :     /* djb-rwth: removing redundant variables */
     583                 :           0 :     AT_NUMB   *tiGroupNumber = NULL;
     584                 :             : 
     585                 :           0 :     ret = 0;
     586                 :             : 
     587                 :           0 :     clear_t_group_info( ti );
     588   [ #  #  #  # ]:           0 :     if (pInChI && pInChI->lenTautomer > 1 &&
     589   [ #  #  #  # ]:           0 :          pInChI->nTautomer && pInChI->nTautomer[0] > 0)
     590                 :             :     {
     591                 :           0 :         num_atoms = pInChI->nNumberOfAtoms;
     592                 :             :         /* djb-rwth: removing redundant code */
     593                 :           0 :         num_t_groups = pInChI->nTautomer[0];
     594                 :           0 :         len_tg = pInChI->lenTautomer - T_GROUP_HDR_LEN*pInChI->nTautomer[0] - 1; /* number of endpoints */
     595                 :             : 
     596                 :             :         /* allocation ti->t_group */
     597   [ #  #  #  # ]:           0 :         if (ti->max_num_t_groups != num_atoms / 2 + 1 || !ti->t_group)
     598                 :             :         {
     599                 :           0 :             ti->max_num_t_groups = num_atoms / 2 + 1;
     600         [ #  # ]:           0 :             if (ti->t_group)
     601         [ #  # ]:           0 :                 inchi_free( ti->t_group );
     602                 :           0 :             ti->t_group = (T_GROUP *) inchi_calloc( (long long)ti->max_num_t_groups + 1, sizeof( ti->t_group[0] ) ); /* djb-rwth: correcting 0 bytes allocation */
     603                 :             :         }
     604                 :             : 
     605                 :             :         /* allocation ti->tGroupNumber */
     606   [ #  #  #  # ]:           0 :         if (ti->num_t_groups != num_t_groups || !ti->tGroupNumber)
     607                 :             :         {
     608                 :           0 :             ti->num_t_groups = num_t_groups;
     609         [ #  # ]:           0 :             if (ti->tGroupNumber)
     610         [ #  # ]:           0 :                 inchi_free( ti->tGroupNumber );
     611                 :           0 :             ti->tGroupNumber = (AT_NUMB *) inchi_calloc( ( (long long)ti->num_t_groups + 1 )*TGSO_TOTAL_LEN, sizeof( ti->tGroupNumber[0] ) ); /* djb-rwth: cast operator added */
     612                 :             :         }
     613                 :             : 
     614                 :             :         /* allocation ti->tGroupNumber */
     615   [ #  #  #  # ]:           0 :         if (len_tg != ti->nNumEndpoints || !ti->nEndpointAtomNumber)
     616                 :             :         {
     617                 :           0 :             ti->nNumEndpoints = len_tg;
     618         [ #  # ]:           0 :             if (ti->nEndpointAtomNumber)
     619         [ #  # ]:           0 :                 inchi_free( ti->nEndpointAtomNumber );
     620                 :           0 :             ti->nEndpointAtomNumber = (AT_NUMB *) inchi_calloc( (long long)len_tg + 1, sizeof( ti->nEndpointAtomNumber[0] ) ); /* djb-rwth: cast operator added */
     621                 :             :         }
     622                 :             : 
     623                 :             :         /* check */
     624   [ #  #  #  #  :           0 :         if (!ti->t_group || !ti->tGroupNumber || !ti->nEndpointAtomNumber)
                   #  # ]
     625                 :             :         {
     626                 :           0 :             ret = RI_ERR_ALLOC;
     627                 :           0 :             goto exit_function;
     628                 :             :         }
     629                 :             : 
     630                 :           0 :         tGroupNumber = ti->tGroupNumber;
     631                 :             :         /* djb-rwth: removing redundant code */
     632                 :           0 :         tiGroupNumber = tGroupNumber + TGSO_SYMM_IORDER * (long long)ti->num_t_groups; /* djb-rwth: cast operator added */
     633                 :             : 
     634                 :             : 
     635                 :             :         INCHI_HEAPCHK
     636                 :             : 
     637                 :           0 :             j = 1; /* index in pInChI->nTautomer[] */
     638                 :           0 :         i = 0; /* index in ti->nEndpointAtomNumber[] */
     639                 :             : 
     640                 :             :         /* djb-rwth: fixing oss-fuzz issues #67681, #67641 */
     641   [ #  #  #  # ]:           0 :         for (itg = 0; itg < pInChI->nTautomer[0] && itg <= ti->max_num_t_groups; itg++)
     642                 :             :         {
     643                 :           0 :             len_tg = pInChI->nTautomer[j]; /* t-group length not including pInChI->nTautomer[j] */
     644                 :           0 :             ti->t_group[itg].num[0] = pInChI->nTautomer[j + 1] + pInChI->nTautomer[j + 2]; /* num mobile H & (-) */
     645                 :           0 :             ti->t_group[itg].num[1] = pInChI->nTautomer[j + 2]; /* num mobile (-) */
     646                 :           0 :             tGroupNumber[itg] = tiGroupNumber[itg] = itg; /* index */
     647                 :           0 :             ti->t_group[itg].nGroupNumber = /*tSymmRank[itg] = tiSymmRank[itg] =*/ itg + 1; /* t-group number */
     648                 :           0 :             j += T_GROUP_HDR_LEN;   /* skip t-group header */
     649                 :           0 :             len_tg -= T_GROUP_HDR_LEN - 1;
     650                 :             : 
     651                 :           0 :             ti->t_group[itg].nNumEndpoints = len_tg;
     652                 :           0 :             ti->t_group[itg].nFirstEndpointAtNoPos = i;
     653                 :             : 
     654         [ #  # ]:           0 :             while (len_tg > 0)
     655                 :             :             {
     656                 :           0 :                 k = ti->nEndpointAtomNumber[i] = pInChI->nTautomer[j] - 1; /* djb-rwth: buffer overrun avoided implicitly in loop condition */
     657                 :             : #if ( FIX_GAF_2019_1==1 )
     658   [ #  #  #  # ]:           0 :                 if (k<0 || k>num_atoms)
     659                 :             :                 {
     660                 :           0 :                     ret = RI_ERR_PROGR;
     661                 :           0 :                     goto exit_function;
     662                 :             :                 }
     663                 :             : #endif
     664         [ #  # ]:           0 :                 if (at)
     665                 :             :                 {
     666                 :           0 :                     at[k].endpoint = itg + 1;
     667                 :             :                 }
     668         [ #  # ]:           0 :                 if (endpoint)
     669                 :             :                 {
     670                 :           0 :                     endpoint[k] = itg + 1;
     671                 :             :                 }
     672                 :           0 :                 len_tg--;
     673                 :           0 :                 j++;
     674                 :           0 :                 i++;
     675                 :             :             }
     676                 :             :         }
     677                 :             : 
     678         [ #  # ]:           0 :         if (i != ti->nNumEndpoints)
     679                 :             :         {
     680                 :           0 :             ret = RI_ERR_PROGR;
     681                 :             :         }
     682                 :             : 
     683                 :             :         INCHI_HEAPCHK
     684                 :             :     }
     685                 :             : 
     686                 :           0 : exit_function:
     687                 :           0 :     return ret;
     688                 :             : }
     689                 :             : 
     690                 :             : 
     691                 :             : /****************************************************************************/
     692                 :           0 : int FillOutpStructEndpointFromInChI( INChI *pInChI, AT_NUMB **pEndpoint )
     693                 :             : {
     694                 :           0 :     int num_at = pInChI->nNumberOfAtoms;
     695                 :           0 :     AT_NUMB *endpoint = *pEndpoint;
     696                 :             :     int     itg, i, j, k, len_tg;
     697                 :             : 
     698   [ #  #  #  # ]:           0 :     if (!endpoint && !( endpoint = (AT_NUMB*) inchi_malloc( num_at * sizeof( endpoint[0] ) ) ))
     699                 :             :     {
     700                 :           0 :         return RI_ERR_ALLOC;
     701                 :             :     }
     702                 :             : 
     703                 :           0 :     memset( endpoint, 0, num_at * sizeof( endpoint[0] ) ); /* djb-rwth: memset_s C11/Annex K variant? */
     704   [ #  #  #  # ]:           0 :     if (pInChI->lenTautomer <= 1 || !pInChI->nTautomer)
     705                 :             :     {
     706                 :           0 :         goto exit_function;
     707                 :             :     }
     708                 :             : 
     709                 :           0 :     j = 1; /* index in pInChI->nTautomer[] */
     710                 :           0 :     i = 0; /* index in ti->nEndpointAtomNumber[] */
     711         [ #  # ]:           0 :     for (itg = 0; itg < pInChI->nTautomer[0]; itg++)
     712                 :             :     {
     713                 :           0 :         len_tg = pInChI->nTautomer[j]; /* t-group length not including pInChI->nTautomer[j] */
     714                 :           0 :         j += T_GROUP_HDR_LEN;   /* skip t-group header */
     715                 :           0 :         len_tg -= T_GROUP_HDR_LEN - 1;
     716                 :             :         /* ti->t_group[itg].nNumEndpoints = len_tg; */
     717         [ #  # ]:           0 :         for (; 0 < len_tg--; j++, i++)
     718                 :             :         {
     719                 :           0 :             k = pInChI->nTautomer[j] - 1;
     720                 :           0 :             endpoint[k] = itg + 1;
     721                 :             :         }
     722                 :             :     }
     723                 :             : 
     724                 :           0 : exit_function:
     725                 :           0 :     *pEndpoint = endpoint;
     726                 :             : 
     727                 :           0 :     return 0;
     728                 :             : }
     729                 :             : 
     730                 :             : 
     731                 :             : /************************************************************************************/
     732                 :           0 : int cmp_charge_val( const void *a1, const void *a2, void *p )
     733                 :             : {
     734                 :           0 :     const CHARGE_VAL *p1 = (const CHARGE_VAL *) a1;
     735                 :           0 :     const CHARGE_VAL *p2 = (const CHARGE_VAL *) a2;
     736                 :             :     int    diff;
     737                 :             : 
     738         [ #  # ]:           0 :     if ((diff = (int) p1->nValence - (int) p2->nValence))  /* smaller valence first */ /* djb-rwth: addressing LLVM warning */
     739                 :           0 :         return diff;
     740         [ #  # ]:           0 :     if ((diff = abs( (int) p1->nCharge ) - abs( (int) p2->nCharge ))) /* smaller abs charge first */ /* djb-rwth: addressing LLVM warning */
     741                 :           0 :         return diff;
     742         [ #  # ]:           0 :     if ((diff = (int) p2->nCharge - (int) p1->nCharge)) /* (+) first, (-) second */ /* djb-rwth: addressing LLVM warning */
     743                 :           0 :         return diff;
     744                 :           0 :     return (int) p1->nValenceOrderingNumber - (int) p2->nValenceOrderingNumber;
     745                 :             : }
     746                 :             : 
     747                 :             : 
     748                 :             : /************************************************************************************/
     749                 :           0 : int bMayBeACationInMobileHLayer( inp_ATOM *at, VAL_AT *pVA, int iat, int bMobileH )
     750                 :             : {
     751                 :             :     int    j, neigh;
     752                 :             :     U_CHAR cVal;  /* moved from below 2024-09-01 DT */
     753   [ #  #  #  # ]:           0 :     if (!bMobileH || !at[iat].num_H)
     754                 :             :     {
     755                 :           0 :         return 1;
     756                 :             :     }
     757                 :             : 
     758                 :             :     /* cVal, cation valence */
     759      [ #  #  # ]:           0 :     switch ( at[iat].el_number ) {
     760                 :           0 :         case EL_NUMBER_N: /* fallthrough */
     761                 :             :         case EL_NUMBER_P:
     762                 :           0 :             cVal = 4;
     763                 :           0 :             break;
     764                 :           0 :         case EL_NUMBER_O: /* fallthrough */
     765                 :             :         case EL_NUMBER_S:
     766                 :             :         case EL_NUMBER_SE:
     767                 :             :         case EL_NUMBER_TE:
     768                 :           0 :             cVal = 3;
     769                 :           0 :             break;
     770                 :           0 :         default:
     771                 :           0 :             return 1;    
     772                 :             :     }
     773                 :             : 
     774         [ #  # ]:           0 :     if (at[iat].valence + at[iat].num_H <= cVal)
     775                 :             :     {
     776         [ #  # ]:           0 :         for (j = 0; j < at[iat].valence; j++)
     777                 :             :         {
     778                 :           0 :             neigh = at[iat].neighbor[j];
     779   [ #  #  #  #  :           0 :             if (at[neigh].valence == 4 && at[neigh].chem_bonds_valence == 4 && !at[neigh].num_H &&
                   #  # ]
     780   [ #  #  #  # ]:           0 :                     pVA[neigh].cNumValenceElectrons == 3 && pVA[neigh].cPeriodicRowNumber == 1)
     781                 :             :             {
     782                 :           0 :                 return 1;
     783                 :             :             }
     784                 :             :         }
     785                 :           0 :         return 0;
     786                 :             :     }
     787                 :           0 :     return 1;
     788                 :             : }
     789                 :             : 
     790                 :             : 
     791                 :             : /************************************************************************************/
     792                 :           0 : int clean_charge_val( struct tagCANON_GLOBALS *pCG, CHARGE_VAL *pChargeVal, int len, inp_ATOM *atom, VAL_AT *pVA,
     793                 :             :                       int iat, int bIsMetal, int bMobileH, AT_NUMB *endpoint )
     794                 :             : {
     795                 :           0 :     inp_ATOM *at = atom + iat;
     796                 :           0 :     int nPeriodicNum = at->el_number;
     797                 :           0 :     int num_bonds = at->valence;
     798                 :           0 :     int min_valence = at->valence + at->num_H;
     799                 :             :     /* in fixed-H case treat tautomeric -O as tautomeric to avoid #O(+) */
     800                 :           0 :     int bTautomeric = ( at->endpoint != 0 );
     801   [ #  #  #  #  :           0 :     int bFixedHTautomeric = !bMobileH && ( endpoint && endpoint[iat] &&
                   #  # ]
     802   [ #  #  #  # ]:           0 :                             pVA[iat].cNumValenceElectrons == 6 && 1 == num_bonds &&
     803   [ #  #  #  # ]:           0 :                             !at->num_H && !bIsMetal );
     804                 :             :     /* int bIsMetal      = is_el_a_metal( nPeriodicNum );*/
     805                 :           0 :     int bDoNotAddH = if_skip_add_H( nPeriodicNum );
     806                 :             :     int nPeriod, nNumEqAbsCharges;
     807                 :           0 :     int nNumValenceEl = get_sp_element_type( nPeriodicNum, &nPeriod ) - 1;
     808                 :             : 
     809                 :             :     int i, j;
     810                 :             : 
     811         [ #  # ]:           0 :     if (!len)
     812                 :           0 :         return len;
     813                 :             : 
     814                 :           0 :     insertions_sort( pCG, pChargeVal, len, sizeof( pChargeVal[0] ), cmp_charge_val );
     815                 :             : 
     816                 :             :     /* metals -- very preliminary code */
     817   [ #  #  #  # ]:           0 :     if (bIsMetal && bDoNotAddH)
     818                 :             :     {
     819                 :             : /* keep the 1st found */
     820                 :           0 :         return inchi_min( 1, len );
     821                 :             :     }
     822                 :             :     /* Mobile-H layer cannot have H on positively charged N, P (all IV), O, S, Se, Te (all III) */
     823                 :             : 
     824                 :             :     /*
     825                 :             :     if ( abs( pChargeVal[0].nCharge ) > 1 && pChargeVal[0].nValence >= min_valence ) {
     826                 :             :         return inchi_min( 1, len );
     827                 :             :     }
     828                 :             :     */
     829                 :           0 :     nNumEqAbsCharges = 0;
     830   [ #  #  #  #  :           0 :     for (i = j = 0; i < len && j < ( nNumEqAbsCharges ? 3 + nNumEqAbsCharges : 4 ); i++)
                   #  # ]
     831                 :             :     {
     832                 :             :         /* for now accept only charge = 0, -1, +1 */
     833         [ #  # ]:           0 :         if (abs( pChargeVal[i].nCharge ) > 1)
     834                 :             :         {
     835                 :           0 :             continue;
     836                 :             :         }
     837         [ #  # ]:           0 :         if (BOND_TYPE_TRIPLE + BOND_TYPE_DOUBLE * ( min_valence - 1 ) < pChargeVal[i].nValence)
     838                 :             :         {
     839                 :           0 :             continue; /* not more than one triple and the rest - double bonds per atom */
     840                 :             :         }
     841   [ #  #  #  #  :           0 :         if (( bTautomeric || (j && bFixedHTautomeric) ) && pChargeVal[i].nCharge < 0) /* djb-rwth: addressing LLVM warning */
             #  #  #  # ]
     842                 :             :         {
     843                 :           0 :             continue; /* negative charge must be included in the tautomeric group */
     844                 :             :         }
     845   [ #  #  #  #  :           0 :         if (( bTautomeric || bFixedHTautomeric ) && pChargeVal[i].nCharge > 0)
                   #  # ]
     846                 :             :         {
     847                 :           0 :             continue; /* positive charge for now cannot reach a tautomeric group */
     848                 :             :         }
     849   [ #  #  #  #  :           0 :         if (j && !bMayBeACationInMobileHLayer( atom, pVA, iat, bMobileH ) && pChargeVal[i].nCharge > 0)
                   #  # ]
     850                 :             :         {
     851         [ #  # ]:           0 :             if (i + 1 < len &&
     852         [ #  # ]:           0 :                  pChargeVal[i].nValence == pChargeVal[i + 1].nValence &&
     853         [ #  # ]:           0 :                  pChargeVal[i].nCharge == -pChargeVal[i + 1].nCharge)
     854                 :             :             {
     855                 :             :                 /* (-) if exists is always after (+) */
     856                 :           0 :                 i += 1; /* also skip the next element */
     857                 :             :             }
     858                 :           0 :             continue; /* in case of Mobile-H, a hydrogen cannot be on a (+)-charged heteroatom */
     859                 :             :         }
     860                 :             : 
     861                 :             :         /* accept same valence opposite charges only for C and its group in Periodic Table */
     862   [ #  #  #  # ]:           0 :         if (j && !bTautomeric &&
     863         [ #  # ]:           0 :              pChargeVal[i].nValence == pChargeVal[j - 1].nValence &&
     864         [ #  # ]:           0 :              pChargeVal[i].nCharge == -pChargeVal[j - 1].nCharge)
     865                 :             :         {
     866   [ #  #  #  #  :           0 :             if (nNumValenceEl == VALUE_OCTET / 2 && pChargeVal[i].nCharge && !nNumEqAbsCharges)
                   #  # ]
     867                 :             :             {
     868                 :           0 :                 pChargeVal[j++] = pChargeVal[i];
     869                 :           0 :                 nNumEqAbsCharges++;
     870                 :             :             }
     871                 :           0 :             continue;
     872                 :             :         }
     873                 :             :         /* do not accept valence=5 for neutral NHn in case of not Mobile-H 2005-01-26 ???? */
     874   [ #  #  #  #  :           0 :         if (nNumValenceEl == 5 && nPeriod == 1 && at->num_H &&
             #  #  #  # ]
     875         [ #  # ]:           0 :              j && !bMobileH &&
     876   [ #  #  #  # ]:           0 :              pChargeVal[i].nValence == 5 && !pChargeVal[i].nCharge)
     877                 :             :         {
     878                 :           0 :             continue;
     879                 :             :         }
     880                 :             :         /* do not accept gaps in allowed valences */
     881   [ #  #  #  # ]:           0 :         if (j && pChargeVal[i].nValence > pChargeVal[j - 1].nValence + 1)
     882                 :             :         {
     883                 :           0 :             break;
     884                 :             :         }
     885                 :           0 :         pChargeVal[j++] = pChargeVal[i];
     886                 :             :     }
     887                 :           0 :     len = j;
     888   [ #  #  #  #  :           0 :     if (!nNumEqAbsCharges && num_bonds < 3 && len == 4)
                   #  # ]
     889                 :             :     {
     890                 :           0 :         len--; /* prohibit =S#  where # is a triple bond */
     891                 :             :     }
     892                 :           0 :     return len;
     893                 :             : }
     894                 :             : 
     895                 :             : 
     896                 :             : /****************************************************************************
     897                 :             : int GetAtomRestoreInfo( CANON_GLOBALS *pCG, inp_ATOM *atom, int iat, VAL_AT *pVArray )
     898                 :             : 
     899                 :             : 
     900                 :             :     pVA->cDoNotAddH
     901                 :             :     pVA->cMetal
     902                 :             :     pVA->cNumValenceElectrons
     903                 :             :     pVA->cPeriodicRowNumber
     904                 :             :     pVA->cInitFreeValences
     905                 :             :     pVA->cnListIndex        = index+1
     906                 :             : 
     907                 :             : return value:
     908                 :             :      -1 => error
     909                 :             :       0 => do not know what to do; leave the atom unchanged
     910                 :             :       1 => success
     911                 :             : ****************************************************************************/
     912                 :           0 : int GetAtomRestoreInfo(struct tagCANON_GLOBALS* pCG,
     913                 :             :     inp_ATOM* atom, int iat, VAL_AT* pVArray,
     914                 :             :     ICHICONST SRM* pSrm, int bMobileH, AT_NUMB* endpoint)
     915                 :             : {
     916                 :             :     /* #defines from util.c */
     917                 :             : #define MIN_ATOM_CHARGE        (-2)
     918                 :             : #define MAX_ATOM_CHARGE         2
     919                 :             : #define NEUTRAL_STATE          (-MIN_ATOM_CHARGE)
     920                 :             : #define NUM_ATOM_CHARGES       (MAX_ATOM_CHARGE - MIN_ATOM_CHARGE + 1)
     921                 :             : #define MAX_NUM_VALENCES        5  /* max. number + 1 to provide zero termination */
     922                 :             : 
     923                 :             :     int i, j, j2, k, k2, charge, cur_charge, num_non_bonding_electrons;
     924                 :             :     int nNumStates, nNumSelectedStates, num_H, num_bonds;
     925                 :             :     int nOctetNeutralValenceExcess, nFirstNeutralValenceExcess;
     926                 :             :     int nFoundNeutralValenceExcess, nFoundNeutralValenceOrdNumber;
     927                 :             :     int nLastFoundValenceOrdNumber, nLastFoundValenceState;
     928                 :             :     int cn_bits, cn_bits_array[5], len_cn_bits_array;
     929                 :           0 :     inp_ATOM* at = atom + iat;
     930                 :           0 :     VAL_AT* pVA = pVArray + iat;
     931                 :           0 :     int nPeriodicNum = at->el_number;
     932                 :             :     int cur_chem_valence, cur_chem_valence_fixed, min_chem_valence, known_chem_valence;
     933                 :             :     int metal_bonds_chem_valence, not_metal_bonds_chem_valence, alt_bonds_delta_valence, bonds_chem_valence, bond_type;
     934                 :             :     CHARGE_VAL  ChargeVal[NUM_ATOM_CHARGES * MAX_NUM_VALENCES];
     935                 :             : 
     936                 :           0 :     memset(ChargeVal, 0, sizeof(ChargeVal));
     937                 :             : 
     938                 :           0 :     pVA->cDoNotAddH = if_skip_add_H(nPeriodicNum);  /* InChI never adds H to this atom */
     939                 :             :     /*pVA->cMetal     = is_el_a_metal( nPeriodicNum );*/ /* the atom is a metal */
     940                 :             : 
     941                 :             :     /* count bonds to metal atoms; metals have already been marked */
     942                 :           0 :     metal_bonds_chem_valence = not_metal_bonds_chem_valence = alt_bonds_delta_valence = 0;
     943                 :             : 
     944         [ #  # ]:           0 :     if (pVA->cMetal)
     945                 :             :     {
     946                 :           0 :         j = at->valence; /* all bonds to metal */
     947         [ #  # ]:           0 :         for (i = k = j2 = k2 = 0; i < at->valence; i++)
     948                 :             :         {
     949                 :           0 :             bond_type = (at->bond_type[i] & BOND_TYPE_MASK);
     950         [ #  # ]:           0 :             if (bond_type <= BOND_TYPE_TRIPLE)
     951                 :             :             {
     952                 :           0 :                 metal_bonds_chem_valence += inchi_max(BOND_TYPE_SINGLE, bond_type);
     953                 :             :             }
     954                 :             :             else
     955                 :             :             {
     956                 :           0 :                 metal_bonds_chem_valence += BOND_TYPE_SINGLE;
     957                 :           0 :                 k++; /* count alternating bonds */
     958                 :             :             }
     959                 :             :         }
     960                 :             :     }
     961                 :             :     else
     962                 :             :     {
     963         [ #  # ]:           0 :         for (i = j = j2 = k = k2 = 0; i < at->valence; i++)
     964                 :             :         {
     965                 :           0 :             bond_type = (at->bond_type[i] & BOND_TYPE_MASK);
     966         [ #  # ]:           0 :             if (pVArray[(int)at->neighbor[i]].cMetal)
     967                 :             :             {
     968                 :           0 :                 j++;  /* number of bonds to metal atoms */
     969         [ #  # ]:           0 :                 if (bond_type <= BOND_TYPE_TRIPLE)
     970                 :             :                 {
     971                 :           0 :                     metal_bonds_chem_valence += inchi_max(BOND_TYPE_SINGLE, bond_type);
     972                 :             :                 }
     973                 :             :                 else
     974                 :             :                 {
     975                 :           0 :                     metal_bonds_chem_valence += BOND_TYPE_SINGLE;
     976                 :           0 :                     k++; /* count alternating bonds */
     977                 :             :                 }
     978                 :             :             }
     979                 :             :             else
     980                 :             :             {
     981                 :           0 :                 j2++;
     982         [ #  # ]:           0 :                 if (bond_type <= BOND_TYPE_TRIPLE)
     983                 :             :                 {
     984                 :           0 :                     not_metal_bonds_chem_valence += inchi_max(BOND_TYPE_SINGLE, bond_type);
     985                 :             :                 }
     986                 :             :                 else
     987                 :             :                 {
     988                 :           0 :                     not_metal_bonds_chem_valence += BOND_TYPE_SINGLE;
     989                 :           0 :                     k2++; /* count alternating bonds */
     990                 :             :                 }
     991                 :             :             }
     992                 :             :         }
     993                 :             :     }
     994                 :             : 
     995                 :           0 :     bonds_chem_valence = metal_bonds_chem_valence + not_metal_bonds_chem_valence;
     996                 :             : 
     997         [ #  # ]:           0 :     if (at->chem_bonds_valence > bonds_chem_valence)
     998                 :             :     {
     999         [ #  # ]:           0 :         if (at->chem_bonds_valence - bonds_chem_valence > 1)
    1000                 :             :         {
    1001                 :           0 :             at->chem_bonds_valence = bonds_chem_valence + 1;  /* should not happen */
    1002                 :             :         }
    1003                 :           0 :         alt_bonds_delta_valence = at->chem_bonds_valence - bonds_chem_valence;
    1004                 :             :     }
    1005                 :             : 
    1006                 :           0 :     pVA->cNumBondsToMetal = j;
    1007                 :             : 
    1008         [ #  # ]:           0 :     if (nPeriodicNum == EL_NUMBER_H)
    1009                 :             :     {
    1010                 :             :         /* ignore bridging H; ??? later add ??? */
    1011                 :           0 :         return 0;
    1012                 :             :     }
    1013                 :             : 
    1014                 :           0 :     num_H = at->num_H;
    1015                 :           0 :     num_bonds = at->valence;
    1016                 :             : 
    1017   [ #  #  #  # ]:           0 :     if (!num_bonds && !num_H)
    1018                 :             :     {
    1019                 :           0 :         return 0; /* do not know the answer: isolated atom */
    1020                 :             :     }
    1021                 :             :     /* at the beginning all bonds are single */
    1022                 :           0 :     min_chem_valence = num_bonds + num_H;
    1023                 :           0 :     cur_chem_valence = bonds_chem_valence + alt_bonds_delta_valence + num_H; /* includes double & alternating bond contribution */
    1024                 :             : 
    1025                 :             :     /* number of non-bonding electrons in case of all single bonds */
    1026                 :           0 :     num_non_bonding_electrons = (int)pVA->cNumValenceElectrons - min_chem_valence;
    1027                 :             :     /* Octet rule: charge = bonds_valence + NumValenceElectrons - 8 */
    1028                 :           0 :     charge = min_chem_valence + (int)pVA->cNumValenceElectrons - VALUE_OCTET; /* wrong */
    1029                 :             : 
    1030                 :             :     /* typical (ad hoc) minimal neutral valence */
    1031                 :           0 :     known_chem_valence = (pVA->cNumValenceElectrons > VALUE_OCTET / 2) ?
    1032         [ #  # ]:           0 :         VALUE_OCTET - pVA->cNumValenceElectrons :
    1033                 :           0 :         pVA->cNumValenceElectrons;
    1034                 :             :     /* excess of typical valence over all-single-bonds valence */
    1035                 :           0 :     nOctetNeutralValenceExcess = known_chem_valence - min_chem_valence;
    1036                 :             :     /*  (NB=num.bonds, NV=neutral valence, NVX=neutral valence excess, LFVS=last found valence state, val.=valence)
    1037                 :             : 
    1038                 :             :        element NB  knownFst octet Last  octetNVX  firstNVX foundNVX chargeLFVS  LFVS
    1039                 :             :                    valence  val.  NV>=
    1040                 :             : 
    1041                 :             :        -B       1    3        3    3        2         2   =     2        +2
    1042                 :             :        >B       2    3        3    3        1         1   =     1        +1
    1043                 :             :        >B-      3    3        3    3        0         0   =     0         0
    1044                 :             :        >B<      4    3        3    3       -1        -1   <>   N/A       -1
    1045                 :             : 
    1046                 :             :        -C       1    4        4    4        3         3   =     3        N/A
    1047                 :             :        >C       2    4        4    4        2         2   =     2        +2  (-2)
    1048                 :             :        >C-      3    4        4    4        1         1   =     1        +1  (-1)
    1049                 :             :        >C<      4    4        4    4        0         0   =     0         0
    1050                 :             :        C(V)     5    4        4    N/A     -1        -1   <>   N/A       N/A
    1051                 :             : 
    1052                 :             :        -Si      1    4        4    4        3         3   =     3        N/A
    1053                 :             :        >Si      2    4        4    4        2         2   =     2        +2  (-2)
    1054                 :             :        >Si-     3    4        4    4        1         1   =     1        +1  (-1)
    1055                 :             :        >Si-     4    4        4    4        0         0   =     0         0
    1056                 :             :        Si(V)    5    4        4    N/A     -1        -1   <>   N/A       -1
    1057                 :             : 
    1058                 :             :        -N       1    3        3    3        2         2   =     2        -2
    1059                 :             :        >N       2    3        3    3        1         1   =     1        -1
    1060                 :             :        >N-      3    3        3    3        0         0   =     0         0  (+2)
    1061                 :             :        >N<      4    3        3    5       -1        -1   <>    1        +1
    1062                 :             :        N(V)     5    3        3    5       -2        -2   <>    0         0
    1063                 :             :        N(VI)    6    3        3    N/A     -3        -3   <>   N/A       N/A
    1064                 :             :        N(VII)   7    3        3    N/A     -4        -4   <>   N/A       N/A
    1065                 :             : 
    1066                 :             :        -P       1    3        3    3        2         2   =     2        -2
    1067                 :             :        >P       2    3        3    3        1         1   =     1        -1
    1068                 :             :        >P-      3    3        3    3        0         0   =     0         0  (-2, +2)
    1069                 :             :        >P<      4    3        3    5       -1        -1   <>    1        +1  (-1)
    1070                 :             :        P(V)     5    3        3    5       -2        -2   <>    0         0  (-2)
    1071                 :             :        P(VI)    6    3        3    N/A     -3        -3   <>   N/A       -1
    1072                 :             :        P(VII)   7    3        3    N/A     -4        -4   <>   N/A       -2
    1073                 :             :        P(VIII)  8    3        3    N/A     -5        -5   <>   N/A       N/A
    1074                 :             : 
    1075                 :             :        -O       1    2        2    2        1         1   =     1        -1
    1076                 :             :        >O       2    2        2    2        0         0   =     0         0
    1077                 :             :        >O-      3    2        2    N/A     -1        -1   <>   N/A       +1
    1078                 :             :        >O<      4    2        2    N/A     -2        -2   <>   N/A       +2
    1079                 :             :        O(V)     5    2        2    N/A     -3        -3   <>   N/A       +1
    1080                 :             :        O(VI)    6    2        2    N/A     -4        -4   <>   N/A       N/A
    1081                 :             : 
    1082                 :             :        -S       1    2        2    2        1         1   =     1        -1
    1083                 :             :        >S       2    2        2    2        0         0   =     0         0       NPNP - prohibit
    1084                 :             :        >S-      3    2        2    4       -1        -1   <>    1        +1  (-1) PNPN
    1085                 :             :        >S<      4    2        2    4       -2        -2   <>    0         0  (+2)
    1086                 :             :        S(V)     5    2        2    6       -3        -3   <>    1        +1  (-1)
    1087                 :             :        S(VI)    6    2        2    6       -4        -4   <>    0         0
    1088                 :             :        S(VII)   7    2        2    N/A     -5        -5   <>    0        -1
    1089                 :             :        S(VIII)  8    2        2    N/A     -6        -6   <>   N/A       N/A
    1090                 :             : 
    1091                 :             :        -F       1    1        1    1        0         0   =     0         0
    1092                 :             :        >F       2    1        1    1       -1        -1   <>   N/A       +1
    1093                 :             :        >F-      3    1        1    1       -2        -2   <>   N/A       +2
    1094                 :             :        >F<      4    1        1    1       -3        -3   <>   N/A       N/A
    1095                 :             :        F(V)     5    1        1    1       -4        -4   <>   N/A       +2
    1096                 :             :        F(VI)    6    1        1    1       -5        -5   <>   N/A       N/A
    1097                 :             : 
    1098                 :             :        -Cl      1    1        1    1        0         0   =     0         0      NPNP - prohibit
    1099                 :             :        >Cl      2    1        1    3       -1        -1   <>    1        +1      PNPN - prohibit
    1100                 :             :        >Cl-     3    1        1    3       -2        -2   <>    0         0 (+2) NPNP
    1101                 :             :        >Cl<     4    1        1    5       -3        -3   <>    1        +1      PNPN
    1102                 :             :        Cl(V)    5    1        1    5       -4        -4   <>    0         0
    1103                 :             :        Cl(VI)   6    1        1    7       -5        -5   <>    1        +1
    1104                 :             :        Cl(VII)  7    1        1    7       -6        -6   <>    0         0
    1105                 :             :        Cl(VIII) 8    1        1    N/A     -7        -7   <>   N/A       N/A
    1106                 :             : 
    1107                 :             : 
    1108                 :             :       NB                 = num_bonds+num_H
    1109                 :             : 
    1110                 :             :       knownFst valence   = nFirstNeutralValenceExcess + min_chem_valence
    1111                 :             :       octet val.         = nOctetNeutralValenceExcess + min_chem_valence
    1112                 :             :       Last NV>=          = nFoundNeutralValenceExcess + min_chem_valence
    1113                 :             : 
    1114                 :             :       octetNVX           = nOctetNeutralValenceExcess
    1115                 :             :       firstNVX           = nFirstNeutralValenceExcess
    1116                 :             :       foundNVX           = nFoundNeutralValenceExcess
    1117                 :             : 
    1118                 :             :       chargeLFVS         = ChargeVal[nLastFoundValenceState].nCharge
    1119                 :             : 
    1120                 :             :     */
    1121                 :             :     /* minimal known neutral atom valence; different for Sn(2/4), Tl(1/3), Pb(2/4): (known/typical ad hoc) */
    1122                 :           0 :     known_chem_valence = get_el_valence( nPeriodicNum, 0, 0 );
    1123                 :             : 
    1124         [ #  # ]:           0 :     if (pSrm->bMetalAddFlower)
    1125                 :             :     {
    1126                 :             :         /* bond orders of bonds to metal may be as they are (pSrm->nMetalInitBondOrder==1)
    1127                 :             :                                         or decreased by one (pSrm->nMetalInitBondOrder==0)
    1128                 :             :            nMetalInitBondOrder == nMetalMinBondOrder + nMetalInitEdgeFlow
    1129                 :             :         */
    1130                 :           0 :         cur_chem_valence_fixed = cur_chem_valence - pVA->cNumBondsToMetal * ( 1 - pSrm->nMetalInitBondOrder );
    1131                 :           0 :         pVA->cInitOrigValenceToMetal = metal_bonds_chem_valence;
    1132                 :           0 :         pVA->cInitValenceToMetal = metal_bonds_chem_valence - pVA->cNumBondsToMetal * ( 1 - pSrm->nMetalInitBondOrder );
    1133                 :           0 :         pVA->cInitFlowToMetal = pVA->cInitValenceToMetal - pVA->cNumBondsToMetal * pSrm->nMetalMinBondOrder;
    1134         [ #  # ]:           0 :         if (pVA->cMetal)
    1135                 :             :         {
    1136                 :           0 :             pVA->cInitFreeValences += alt_bonds_delta_valence;
    1137                 :             :         }
    1138         [ #  # ]:           0 :         if (pSrm->nMetalInitEdgeFlow < pSrm->nMetalInitBondOrder - pSrm->nMetalMinBondOrder)
    1139                 :             :         {
    1140                 :             :             /* single bond has zero initial flow + 2 radicals at incident atoms */
    1141         [ #  # ]:           0 :             if (pVA->cInitFlowToMetal <= pVA->cNumBondsToMetal)
    1142                 :             :             {
    1143         [ #  # ]:           0 :                 if (pVA->cMetal)
    1144                 :             :                 {
    1145                 :           0 :                     pVA->cInitFreeValences += pVA->cInitFlowToMetal;
    1146                 :             :                 }
    1147                 :           0 :                 pVA->cInitFlowToMetal = 0;
    1148                 :             :             }
    1149                 :             :             else
    1150                 :             :             {
    1151         [ #  # ]:           0 :                 if (pVA->cMetal)
    1152                 :             :                 {
    1153                 :           0 :                     pVA->cInitFreeValences += pVA->cNumBondsToMetal * ( 1 - pSrm->nMetalInitEdgeFlow );
    1154                 :             :                 }
    1155                 :           0 :                 pVA->cInitFlowToMetal -= pVA->cNumBondsToMetal * ( 1 - pSrm->nMetalInitEdgeFlow );
    1156                 :             :             }
    1157                 :             :         }
    1158                 :             :     }
    1159                 :             :     else
    1160                 :             :     {
    1161                 :             :         /* treat metal atoms as ordinary non-metal atoms */
    1162                 :           0 :         cur_chem_valence_fixed = cur_chem_valence;
    1163                 :           0 :         pVA->cInitFlowToMetal = metal_bonds_chem_valence - pVA->cNumBondsToMetal;
    1164                 :           0 :         pVA->cInitValenceToMetal = metal_bonds_chem_valence;
    1165                 :           0 :         pVA->cInitOrigValenceToMetal = metal_bonds_chem_valence;
    1166                 :             :     }
    1167                 :             : 
    1168                 :             : 
    1169   [ #  #  #  # ]:           0 :     if (pVA->cMetal && pSrm->bMetalAddFlower)
    1170                 :             :     {
    1171                 :           0 :         pVA->cnListIndex = cnListIndexMe + 1;
    1172                 :             :         /*
    1173                 :             :         pVA->cInitOrigValenceToMetal += alt_bonds_delta_valence;
    1174                 :             :         pVA->cInitValenceToMetal     += alt_bonds_delta_valence;
    1175                 :             :         pVA->cInitFreeValences = (pSrm->nMetalInitBondOrder + alt_bonds_delta_valence
    1176                 :             :                                  - (pSrm->nMetalMinBondOrder + pSrm->nMetalInitEdgeFlow)) * pVA->cNumBondsToMetal;
    1177                 :             :         */
    1178                 :           0 :         return 0;  /* metal */
    1179                 :             :     }
    1180                 :             : 
    1181         [ #  # ]:           0 :     if (!known_chem_valence)
    1182                 :             :     {
    1183                 :             :         /* a noble gas like He, Ne, ... */
    1184                 :           0 :         pVA->cInitFreeValences = at->chem_bonds_valence - at->valence;
    1185                 :           0 :         return TREAT_ATOM_AS_METAL; /* do not know anything about this atom; needs 2nd pass */
    1186                 :             :     }
    1187                 :             : 
    1188                 :           0 :     nFirstNeutralValenceExcess = known_chem_valence - min_chem_valence;
    1189                 :             : 
    1190                 :           0 :     nFoundNeutralValenceExcess = NO_VALUE_INT;
    1191                 :           0 :     nFoundNeutralValenceOrdNumber = NO_VALUE_INT;
    1192                 :           0 :     nLastFoundValenceOrdNumber = NO_VALUE_INT;
    1193                 :           0 :     nLastFoundValenceState = NO_VALUE_INT;
    1194                 :             : 
    1195                 :             :     /* find the lowest known valence >= all-single-bonds valence */
    1196         [ #  # ]:           0 :     for (cur_charge = MIN_ATOM_CHARGE, nNumStates = 0; cur_charge <= MAX_ATOM_CHARGE; cur_charge++)
    1197                 :             :     {
    1198         [ #  # ]:           0 :         for (i = 0; i < MAX_NUM_VALENCES; i++)
    1199                 :             :         {
    1200                 :           0 :             known_chem_valence = get_el_valence(nPeriodicNum, cur_charge, i);
    1201   [ #  #  #  # ]:           0 :             if (cur_chem_valence_fixed > known_chem_valence || !known_chem_valence)
    1202                 :             :             {
    1203                 :           0 :                 continue; /* known valence < all-single-bonds valence */
    1204                 :             :             }
    1205         [ #  # ]:           0 :             if (BOND_TYPE_TRIPLE + BOND_TYPE_DOUBLE * (num_bonds - 1) + num_H < known_chem_valence)
    1206                 :             :             {
    1207                 :           0 :                 continue; /* not more than one triple and the rest - double bonds per atom */
    1208                 :             :             }
    1209                 :             : 
    1210                 :             :             /* keep all found */
    1211                 :           0 :             ChargeVal[nNumStates].nValence = known_chem_valence;
    1212                 :           0 :             ChargeVal[nNumStates].nCharge = cur_charge;
    1213                 :           0 :             ChargeVal[nNumStates].nValenceOrderingNumber = i;
    1214   [ #  #  #  # ]:           0 :             if (!cur_charge && nFoundNeutralValenceExcess == NO_VALUE_INT)
    1215                 :             :             {
    1216                 :             :                 /* neutral state; compare to the lowest typical valence */
    1217                 :           0 :                 nFoundNeutralValenceExcess = known_chem_valence - min_chem_valence;
    1218                 :           0 :                 nFoundNeutralValenceOrdNumber = i;
    1219                 :             :             }
    1220         [ #  # ]:           0 :             if (min_chem_valence == known_chem_valence)
    1221                 :             :             {
    1222         [ #  # ]:           0 :                 if (nLastFoundValenceState == NO_VALUE_INT)
    1223                 :             :                 {
    1224                 :             :                     /* accept the first found */
    1225                 :           0 :                     nLastFoundValenceState = nNumStates;
    1226                 :             :                 }
    1227                 :             :                 else
    1228         [ #  # ]:           0 :                     if (abs(ChargeVal[nLastFoundValenceState].nCharge) >= abs(cur_charge))
    1229                 :             :                     {
    1230                 :             :                         /* accept smaller abs(charge); if abs(charges) are same, accept (+) */
    1231                 :           0 :                         nLastFoundValenceState = nNumStates;
    1232                 :             :                     }
    1233                 :             :             }
    1234                 :             : 
    1235                 :           0 :             nNumStates++;
    1236                 :             :         }
    1237                 :             :     }
    1238                 :             : 
    1239                 :             :     /***********************************************************************************/
    1240                 :             :     /* select only appropriate charge & valence so that a suitable ChargeStruct exists */
    1241                 :             :     /***********************************************************************************/
    1242                 :             : 
    1243                 :           0 :     nNumSelectedStates = clean_charge_val( pCG, ChargeVal, nNumStates, atom,
    1244                 :           0 :                                            pVArray, iat, pVA->cMetal,
    1245                 :             :                                            bMobileH, endpoint );
    1246                 :             : 
    1247         [ #  # ]:           0 :     if (!nNumSelectedStates)
    1248                 :             :     {
    1249                 :           0 :         return TREAT_ATOM_AS_METAL; /* nothing to do */
    1250                 :             :     }
    1251                 :             : 
    1252                 :             :     /***********************************************************************************/
    1253                 :             :     /*       Find an appropriate ChargeStruct index for the ChargeVal found            */
    1254                 :             :     /***********************************************************************************/
    1255                 :           0 :     cn_bits = 0;
    1256                 :           0 :     memset( cn_bits_array, 0, sizeof( cn_bits_array ) ); /* djb-rwth: memset_s C11/Annex K variant? */
    1257                 :             :     /***** set bits identifying a suitable ChargeStruct ******/
    1258   [ #  #  #  # ]:           0 :     for (i = len_cn_bits_array = 0; i < nNumSelectedStates && len_cn_bits_array < 4; i++)
    1259                 :             :     {
    1260   [ #  #  #  # ]:           0 :         switch (ChargeVal[i].nCharge)
    1261                 :             :         {
    1262                 :           0 :             case -1:
    1263                 :           0 :                 cn_bits_array[len_cn_bits_array] |= cn_bits_M; /* Minus 1 */
    1264                 :           0 :                 break;
    1265                 :           0 :             case 0:
    1266                 :           0 :                 cn_bits_array[len_cn_bits_array] |= cn_bits_N; /* Neutral */
    1267                 :           0 :                 break;
    1268                 :           0 :             case 1:
    1269                 :           0 :                 cn_bits_array[len_cn_bits_array] |= cn_bits_P; /* Plus 1 */
    1270                 :           0 :                 break;
    1271                 :           0 :             default:
    1272                 :           0 :                 return RI_ERR_PROGR; /* program error */
    1273                 :             :         }
    1274         [ #  # ]:           0 :         if (i + 1 < nNumSelectedStates &&
    1275         [ #  # ]:           0 :              ChargeVal[i].nValence == ChargeVal[i + 1].nValence &&
    1276         [ #  # ]:           0 :              ChargeVal[i].nCharge &&
    1277         [ #  # ]:           0 :              ChargeVal[i].nCharge == -ChargeVal[i + 1].nCharge)
    1278                 :             :         {
    1279                 :             :             ; /* add opposite charge to the same element of cn_bits_array[] */
    1280                 :             :         }
    1281                 :             :         else
    1282                 :             :         {
    1283                 :           0 :             len_cn_bits_array++;
    1284                 :             :         }
    1285                 :             :     }
    1286   [ #  #  #  # ]:           0 :     if (!len_cn_bits_array || len_cn_bits_array > 4)
    1287                 :             :     {
    1288                 :           0 :         return RI_ERR_PROGR; /* program error */
    1289                 :             :     }
    1290                 :             :     /* accommodate added 4-state ChargeStruct: +/- cannot be in case of 4 states */
    1291   [ #  #  #  # ]:           0 :     if (len_cn_bits_array + 1 == nNumSelectedStates && nNumSelectedStates == 4)
    1292                 :             :     {
    1293                 :           0 :         len_cn_bits_array--;
    1294                 :           0 :         nNumSelectedStates--;
    1295                 :           0 :         cn_bits_array[len_cn_bits_array] = 0;
    1296                 :             :     }
    1297                 :             :     /* fix for terminal hydrogenless -C as in isocyano or CO: there is no just cnE_[] ChargeStruct */
    1298         [ #  # ]:           0 :     if (len_cn_bits_array == 1 &&
    1299         [ #  # ]:           0 :          cn_bits_array[0] == ( cn_bits_P | cn_bits_M ) &&
    1300         [ #  # ]:           0 :          ChargeVal[0].nValence + 1 > BOND_TYPE_TRIPLE + BOND_TYPE_DOUBLE * ( num_bonds - 1 ) + num_H)
    1301                 :             :     {
    1302                 :           0 :         cn_bits_array[len_cn_bits_array++] = cn_bits_N;
    1303                 :           0 :         ChargeVal[nNumSelectedStates].nValence = ChargeVal[nNumSelectedStates - 1].nValence;
    1304                 :           0 :         ChargeVal[nNumSelectedStates].nCharge = 0;
    1305                 :           0 :         ChargeVal[nNumSelectedStates].nValenceOrderingNumber = 0;
    1306                 :             :     }
    1307                 :             : 
    1308                 :           0 : make_cn_bits:
    1309                 :           0 :     cn_bits = MAKE_CN_BITS( cn_bits_array[0], cn_bits_array[1], cn_bits_array[2], cn_bits_array[3] );
    1310                 :             : 
    1311                 :             :     /*********** find ChargeStructure **************/
    1312         [ #  # ]:           0 :     for (i = 0, j = -1; i < cnListNumEl; i++)
    1313                 :             :     {
    1314         [ #  # ]:           0 :         if (cnList[i].bits == cn_bits)
    1315                 :             :         {
    1316                 :           0 :             j = i;
    1317                 :           0 :             break; /* found */
    1318                 :             :         }
    1319                 :             :     }
    1320                 :             : 
    1321         [ #  # ]:           0 :     if (j < 0)
    1322                 :             :     {
    1323                 :             :         /* ChargeStructure was not found */
    1324   [ #  #  #  # ]:           0 :         if (1 < len_cn_bits_array && len_cn_bits_array + 1 == nNumSelectedStates)
    1325                 :             :         {
    1326                 :             : /* a pair of opposite charges was combined */
    1327                 :           0 :             len_cn_bits_array--;
    1328                 :           0 :             cn_bits_array[len_cn_bits_array] = 0;
    1329                 :           0 :             goto make_cn_bits;
    1330                 :             :         }
    1331         [ #  # ]:           0 :         else if (nNumSelectedStates == 4)
    1332                 :             :         {
    1333                 :             :             /* reduce number of states */
    1334                 :           0 :             len_cn_bits_array--;
    1335                 :           0 :             cn_bits_array[len_cn_bits_array] = 0;
    1336                 :           0 :             nNumSelectedStates--;
    1337                 :           0 :             goto make_cn_bits;
    1338                 :             :         }
    1339                 :           0 :         return RI_ERR_PROGR; /* charge structure not found */
    1340                 :             :     }
    1341                 :             : 
    1342                 :             :     /********** ChargeStructure has been found **********/
    1343                 :           0 :     pVA->cnListIndex = j + 1; /* charge structure index + 1 */
    1344                 :           0 :     pVA->cInitCharge = cnList[j].nInitialCharge;
    1345                 :             :     /********** Calculate "Free Valence" ****************/
    1346                 :             : #if ( ALLOW_METAL_BOND_ZERO == 1 )
    1347                 :             : 
    1348                 :             : #if ( INIT_METAL_BOND_ZERO == 1 )
    1349                 :             :     if (pVA->cMetal)
    1350                 :             :     {
    1351                 :             :         j = 0;
    1352                 :             :     }
    1353                 :             :     else
    1354                 :             :     {
    1355                 :             :         j = ChargeVal[0].nValence - cur_chem_valence_fixed;
    1356                 :             :     }
    1357                 :             : #else
    1358                 :           0 :     j = ChargeVal[0].nValence - cur_chem_valence_fixed;
    1359                 :             : #endif
    1360                 :             : 
    1361                 :             : #else
    1362                 :             :     j = ChargeVal[0].nValence - cur_chem_valence_fixed;
    1363                 :             : #endif
    1364         [ #  # ]:           0 :     if (j < 0)
    1365                 :             :     {
    1366                 :           0 :         return RI_ERR_PROGR; /* program error */
    1367                 :             :     }
    1368                 :           0 :     pVA->cInitFreeValences = j; /* number of initial unsatisfied valences; should be combined with */
    1369                 :             :                                 /* (cap - flow) of vertex=0 in the charge structure[pVA->cnListIndex-1] */
    1370                 :           0 :     return 1; /* success */
    1371                 :             : 
    1372                 :             : #undef MIN_ATOM_CHARGE
    1373                 :             : #undef MAX_ATOM_CHARGE
    1374                 :             : #undef NEUTRAL_STATE
    1375                 :             : #undef NUM_ATOM_CHARGES
    1376                 :             : #undef MAX_NUM_VALENCES
    1377                 :             : }
    1378                 :             : 
    1379                 :             : 
    1380                 :             : #ifdef NEVER
    1381                 :             : /****************************************************************************/
    1382                 :             : int get_bonds_valences( int nPeriodicNum, int bonds_valence, int num_H, VAL_AT *pVA )
    1383                 :             : {
    1384                 :             :     int i, j, charge, chem_valence, known_chem_valence;
    1385                 :             : #define MAX_NUM_VALENCES 5  /* defined in util.c */
    1386                 :             : 
    1387                 :             :     memset( pVA, 0, sizeof( pVA[0] ) );
    1388                 :             : 
    1389                 :             :     if (!bonds_valence && !num_H)
    1390                 :             :         return 0; /* do not know the answer */
    1391                 :             : 
    1392                 :             :     chem_valence = bonds_valence + num_H;
    1393                 :             :     for (charge = VAL_MIN_CHARGE; charge <= VAL_MAX_CHARGE; charge++)
    1394                 :             :     {
    1395                 :             :         for (i = 0, j = 0; i < MAX_NUM_VALENCES, j < VAL_NUMBER; i++)
    1396                 :             :         {
    1397                 :             :             if (chem_valence <= ( known_chem_valence = get_el_valence( nPeriodicNum, charge, i ) ))
    1398                 :             :             {
    1399                 :             :                 if (!charge)
    1400                 :             :                 {
    1401                 :             :                     pVA->cValence[j][VAL_NEUTR_ORDER] = i + 1;
    1402                 :             :                 }
    1403                 :             :                 pVA->cValence[j++][charge + VAL_BASE] = known_chem_valence - num_H;
    1404                 :             :             }
    1405                 :             :         }
    1406                 :             :     }
    1407                 :             :     pVA->cDoNotAddH = if_skip_add_H( nPeriodicNum );
    1408                 :             :     pVA->cMetal = is_el_a_metal( nPeriodicNum );
    1409                 :             :     return pVA->cValence[0][VAL_BASE];  /* 0 means do not know the answer */
    1410                 :             : #undef MAX_NUM_VALENCES
    1411                 :             : }
    1412                 :             : #endif
    1413                 :             : /*********** calculate s or p-element type ************/
    1414                 :           0 : int get_sp_element_type( int nPeriodicNumber, int *nRow )
    1415                 :             : /*
    1416                 :             :                                                 num  el
    1417                 :             :                                                 el   neg
    1418                 :             :    1 => H                          ATYPE_H   1    1  21
    1419                 :             :    2 => Li, Na, K,  Rb, Cs, Fr     ATYPE_Na  2    1  10 09 08 08 07
    1420                 :             :    3 => Be, Mg, Ca, Sr, Ba, Ra     ATYPE_Mg  3    2  15 12 10 10 09
    1421                 :             :    4 => B,  Al, Ga, In, Tl         ATYPE_B   4    3  20 15 18 17 18
    1422                 :             :    5 => C,  Si, Ge, Sn, Pb         ATYPE_C   5    4  25 18 18 18 18
    1423                 :             :    6 => N,  P,  As, Sb, Bi         ATYPE_N   6    5  30 21 20 19 19
    1424                 :             :    7 => O,  S,  Se, Te, Po         ATYPE_O   7    6  35 25 24 21 20
    1425                 :             :    8 => F,  Cl, Br, I,  At         ATYPE_Cl  8    7  40 30 28 25 22
    1426                 :             : 
    1427                 :             : number of valence electrons = (type>1)? type-1: type
    1428                 :             : 
    1429                 :             :   */
    1430                 :             : {
    1431                 :           0 :     int row = 0, type = 0;
    1432         [ #  # ]:           0 :     if (nPeriodicNumber == 1)
    1433                 :             :     {
    1434                 :           0 :         type = 1; /* H: 1 */
    1435                 :           0 :         row = 0;
    1436                 :             :     }
    1437         [ #  # ]:           0 :     else if (nPeriodicNumber == 2)
    1438                 :             :     {
    1439                 :           0 :         type = 0; row = 0;
    1440                 :             :     }
    1441         [ #  # ]:           0 :     else if (nPeriodicNumber <= 10)
    1442                 :             :     {
    1443                 :             :         /* Li: 2, Be: 3, B: 4, C: 5, N: 6, O: 7, F: 8, Ne: 9; later subtract 1 */
    1444                 :           0 :         type = nPeriodicNumber - 1; row = 1;
    1445                 :             :     }
    1446         [ #  # ]:           0 :     else if (nPeriodicNumber <= 18)
    1447                 :             :     {
    1448                 :           0 :         type = nPeriodicNumber - 9; row = 2;
    1449                 :             :     }
    1450         [ #  # ]:           0 :     else if (nPeriodicNumber <= 20)
    1451                 :             :     {
    1452                 :           0 :         type = nPeriodicNumber - 17; row = 3;
    1453                 :             :     }
    1454         [ #  # ]:           0 :     else if (nPeriodicNumber <= 30)
    1455                 :             :     {
    1456                 :           0 :         type = 0; row = 3;
    1457                 :             :     }
    1458         [ #  # ]:           0 :     else if (nPeriodicNumber <= 36)
    1459                 :             :     {
    1460                 :           0 :         type = nPeriodicNumber - 27; row = 3;
    1461                 :             :     }
    1462         [ #  # ]:           0 :     else if (nPeriodicNumber <= 38)
    1463                 :             :     {
    1464                 :           0 :         type = nPeriodicNumber - 35; row = 4;
    1465                 :             :     }
    1466         [ #  # ]:           0 :     else if (nPeriodicNumber <= 48)
    1467                 :             :     {
    1468                 :           0 :         type = 0; row = 4;
    1469                 :             :     }
    1470         [ #  # ]:           0 :     else if (nPeriodicNumber <= 54)
    1471                 :             :     {
    1472                 :           0 :         type = nPeriodicNumber - 45; row = 4;
    1473                 :             :     }
    1474         [ #  # ]:           0 :     else if (nPeriodicNumber <= 56)
    1475                 :             :     {
    1476                 :           0 :         type = nPeriodicNumber - 53; row = 5;
    1477                 :             :     }
    1478         [ #  # ]:           0 :     else if (nPeriodicNumber <= 80)
    1479                 :             :     {
    1480                 :           0 :         type = 0; row = 5;
    1481                 :             :     }
    1482         [ #  # ]:           0 :     else if (nPeriodicNumber <= 86)
    1483                 :             :     {
    1484                 :           0 :         type = nPeriodicNumber - 77; row = 5;
    1485                 :             :     }
    1486         [ #  # ]:           0 :     else if (nPeriodicNumber <= 88)
    1487                 :             :     {
    1488                 :           0 :         type = nPeriodicNumber - 85; row = 6;
    1489                 :             :     }
    1490                 :             :     else
    1491                 :             :     {
    1492                 :           0 :         type = 0; row = 6;
    1493                 :             :     }
    1494                 :             : 
    1495                 :           0 :     *nRow = row;
    1496                 :             : 
    1497         [ #  # ]:           0 :     return type == 9 ? 0 : type;
    1498                 :             : }
    1499                 :             : 
    1500                 :             : 
    1501                 :             : /****************************************************************************/
    1502                 :           0 : int ReallocTCGroups( ALL_TC_GROUPS *pTCGroups, int nAdd )
    1503                 :             : {
    1504                 :           0 :     TC_GROUP *pTCGroup = (TC_GROUP *) inchi_malloc( sizeof( pTCGroup[0] )*( (long long)pTCGroups->max_tc_groups + nAdd ) ); /* djb-rwth: cast operator added */
    1505                 :             : 
    1506         [ #  # ]:           0 :     if (pTCGroup)
    1507                 :             :     {
    1508         [ #  # ]:           0 :         if (pTCGroups->num_tc_groups)
    1509                 :             :         {
    1510                 :           0 :             memcpy(pTCGroup, pTCGroups->pTCG, sizeof(pTCGroup[0]) * pTCGroups->num_tc_groups);
    1511                 :             :         }
    1512                 :           0 :         memset( pTCGroup + pTCGroups->max_tc_groups, 0, sizeof( pTCGroup[0] )*nAdd ); /* djb-rwth: memset_s C11/Annex K variant? */
    1513         [ #  # ]:           0 :         if (pTCGroups->pTCG)
    1514                 :             :         {
    1515         [ #  # ]:           0 :             inchi_free( pTCGroups->pTCG );
    1516                 :             :         }
    1517                 :           0 :         pTCGroups->pTCG = pTCGroup;
    1518                 :           0 :         pTCGroups->max_tc_groups += nAdd;
    1519                 :           0 :         return 0;
    1520                 :             :     }
    1521                 :             : 
    1522                 :           0 :     return RI_ERR_ALLOC;
    1523                 :             : }
    1524                 :             : 
    1525                 :             : 
    1526                 :             : /****************************************************************************/
    1527                 :           0 : int RegisterTCGroup( ALL_TC_GROUPS *pTCGroups, int nGroupType, int nGroupOrdNum,
    1528                 :             :                      int nVertexCap, int nVertexFlow, int nEdgeCap, int nEdgeFlow, int nNumEdges )
    1529                 :             : {
    1530                 :           0 :     int i, ret = 0;
    1531                 :             : 
    1532                 :             :     /* search */
    1533         [ #  # ]:           0 :     for (i = 0; i < pTCGroups->num_tc_groups; i++)
    1534                 :             :     {
    1535         [ #  # ]:           0 :         if (pTCGroups->pTCG[i].type == nGroupType &&
    1536         [ #  # ]:           0 :              pTCGroups->pTCG[i].ord_num == nGroupOrdNum)
    1537                 :             :         {
    1538                 :           0 :             break;
    1539                 :             :         }
    1540                 :             :     }
    1541                 :             : 
    1542         [ #  # ]:           0 :     if (i == pTCGroups->num_tc_groups)
    1543                 :             :     {
    1544                 :             :         /* add one more group */
    1545         [ #  # ]:           0 :         if (pTCGroups->num_tc_groups == pTCGroups->max_tc_groups)
    1546                 :             :         {
    1547                 :           0 :             ret = ReallocTCGroups( pTCGroups, INC_NUM_TCGROUPS );
    1548         [ #  # ]:           0 :             if (ret)
    1549                 :             :             {
    1550                 :           0 :                 goto exit_function;
    1551                 :             :             }
    1552                 :             :         }
    1553                 :             : 
    1554                 :           0 :         ret = i + 1; /* added new group */
    1555                 :           0 :         pTCGroups->num_tc_groups++;
    1556                 :           0 :         pTCGroups->pTCG[i].type = nGroupType;
    1557                 :           0 :         pTCGroups->pTCG[i].ord_num = nGroupOrdNum;
    1558                 :             :     }
    1559                 :             : 
    1560                 :           0 :     pTCGroups->pTCG[i].num_edges += nNumEdges;
    1561                 :             : 
    1562                 :           0 :     pTCGroups->pTCG[i].st_cap += nVertexCap;
    1563                 :           0 :     pTCGroups->pTCG[i].st_flow += nVertexFlow;
    1564                 :             : 
    1565                 :           0 :     pTCGroups->pTCG[i].edges_cap += nEdgeCap;
    1566                 :           0 :     pTCGroups->pTCG[i].edges_flow += nEdgeFlow;
    1567                 :             : 
    1568                 :           0 : exit_function:
    1569                 :           0 :     return ret;
    1570                 :             : }
    1571                 :             : 
    1572                 :             : 
    1573                 :             : /****************************************************************************/
    1574                 :           0 : int nTautEndpointEdgeCap( inp_ATOM *at, VAL_AT *pVA, int i )
    1575                 :             : {
    1576                 :             :     /* There are 3 sources of cap-flow = number of unsatisfied valences:
    1577                 :             :        -----------------------------------------------------------------
    1578                 :             :        1. pVA[i].cInitFreeValences
    1579                 :             :        2. pCN[0].v.cap - pCN[0].v.flow
    1580                 :             :        3. st[i].chem_bonds_valence - SUM(SINGLE, DOUBLE, TRIPLE bond orders)
    1581                 :             :           Reasons: (a) This sum will not include 'ALTERN' bonds
    1582                 :             :                    (b) until now at[i].chem_bonds_valence was used as a
    1583                 :             :                        number of satisfied valences. In case of adjacent
    1584                 :             :                        stereobonds marked as BOND_TYPE_ALTERN the value of
    1585                 :             :                        at[i].chem_bonds_valence may be = at[i].valence+1.
    1586                 :             :        4. Since tautomerism is defined for a neutral atom, do not add
    1587                 :             :           initial flows from the atom to the ChargeStruct
    1588                 :             :           CORRECTION: tautomeric endpoints do not have ChargeStruct.
    1589                 :             : 
    1590                 :             :      */
    1591                 :             :     int j, k, nEdgeCap, bonds_valence, stereo_bond_excess_valence;
    1592         [ #  # ]:           0 :     MY_CONST C_NODE *pCN = pVA[i].cnListIndex > 0 ? cnList[pVA[i].cnListIndex - 1].pCN : NULL;
    1593                 :             : 
    1594                 :             : 
    1595                 :             :     /* 1: free valences to reach the minimum known atom valence */
    1596                 :           0 :     nEdgeCap = pVA[i].cInitFreeValences;
    1597                 :             : 
    1598                 :             :     /* 2: atom free valence in the ChargeStruct */
    1599         [ #  # ]:           0 :     if (pCN)
    1600                 :             :     {
    1601                 :           0 :         nEdgeCap += pCN[0].v.cap - pCN[0].v.flow; /* normally should not happen */
    1602                 :             :     }
    1603                 :             : 
    1604                 :             :     /* 3: atom free valence due to known from stereochemistry stereogenic bond types */
    1605                 :             :     /*
    1606                 :             :     for ( j = 0, bonds_valence = 0; j < at[i].valence; j ++ )
    1607                 :             :     {
    1608                 :             :         if ( at[i].bond_type[j] <= BOND_TYPE_TRIPLE )
    1609                 :             :         {
    1610                 :             :             bonds_valence += at[i].bond_type[j];
    1611                 :             :         }
    1612                 :             :     }
    1613                 :             :     */
    1614                 :             : 
    1615                 :             :     /* bonds > SINGLE are assumed fixed stereobonds; fixed bond cannot increase t-group edge flow */
    1616   [ #  #  #  # ]:           0 :     for (stereo_bond_excess_valence = 0, j = 0; j < MAX_NUM_STEREO_BONDS && at[i].sb_parity[j]; j++)
    1617                 :             :     {
    1618                 :           0 :         k = at[i].sb_ord[j];
    1619         [ #  # ]:           0 :         if (at[i].bond_type[k] < BOND_TYPE_TRIPLE)
    1620                 :             :         {
    1621                 :           0 :             stereo_bond_excess_valence += at[i].bond_type[k] - BOND_TYPE_SINGLE;
    1622                 :             :         }
    1623                 :             :     }
    1624                 :             : 
    1625                 :             :     /*
    1626                 :             :     bonds_valence = (at[i].chem_bonds_valence - bonds_valence) + (bonds_valence -at[i].valence - stereo_bond_excess_valence);
    1627                 :             :     */
    1628                 :           0 :     bonds_valence = ( at[i].chem_bonds_valence - at[i].valence ) - stereo_bond_excess_valence;
    1629                 :             : 
    1630                 :             : 
    1631                 :             :     /*---- add 1, 2, 3 ----*/
    1632         [ #  # ]:           0 :     if (bonds_valence >= 0)
    1633                 :             :     {
    1634                 :           0 :         nEdgeCap += bonds_valence;
    1635                 :             :     }
    1636                 :             :     else
    1637                 :             :     {
    1638                 :           0 :         nEdgeCap = RI_ERR_PROGR;
    1639                 :             :     }
    1640                 :             : 
    1641                 :           0 :     return nEdgeCap;
    1642                 :             : }
    1643                 :             : 
    1644                 :             : 
    1645                 :             : /****************************************************************************/
    1646                 :             : /* If Metal flowers are allowed ( pSrm->bMetalAddFlower != 0), then:                                  */
    1647                 :             : /*                                                                                                    */
    1648                 :             : /*   bond to a metal atom                min_bond_order[i] = pSrm->nMetalMinBondOrder                 */
    1649                 :             : /*   taut endpoint - metal               min_bond_order[i] = pSrm->nMetal2EndpointMinBondOrder        */
    1650                 :             : /*   single bond to metal atom:      initial_bond_order[i] = pSrm->nMetalInitBondOrder                */
    1651                 :             : /*   n-order bond to metal atom      initial_bond_order[i] = pSrm->nMetalInitBondOrder + n-1          */
    1652                 :             : /*                                 = bond_order[i]-BOND_TYPE_SINGLE+pSrm->nMetalInitBondOrder         */
    1653                 :             : /*   single t-endpoint--atom bond    initial_bond_order[i] = pSrm->nMetal2EndpointInitBondOrder       */
    1654                 :             : /*   n-order t-endpoint--metal bond  initial_bond_order[i] = pSrm->nMetal2EndpointInitBondOrder+n-1   */
    1655                 :             : /*                                 = bond_order[i]-BOND_TYPE_SINGLE+pSrm->nMetal2EndpointInitBondOrder*/
    1656                 :             : /*                                                                                                    */
    1657                 :             : /* Exceptions from simple atom-metal conditions:                                                      */
    1658                 :             : /*   1. Atom is a tautomeric endpoint: use pSrm->nMetal2Endpoint* instead of pSrm->nMetal*            */
    1659                 :             : /*   2. Atom is sp3-stereogenic and pSrm->bFixStereoBonds != 0: use atom-atom rules                   */
    1660                 :             : /*   3. Atom has a sp2-stereo   and pSrm->bFixStereoBonds != 0: use atom-atom rules                   */
    1661                 :             : /*                                                                                                    */
    1662                 :             : /* Atom-atom rules (applies to all atoms if pSrm->bMetalAddFlower=0)                                  */
    1663                 :             : /*                                                                                                    */
    1664                 :             : /*   min_bond_order[i]      = BOND_TYPE_SINGLE  (BOND_TYPE_SINGLE = 1)                                */
    1665                 :             : /*   initial_bond_order[i]  = bond_type[i]                                                            */
    1666                 :             : /*                                                                                                    */
    1667                 :             : /* General rules:                                                                                     */
    1668                 :             : /*   initial_bond_flow[i]   = initial_bond_order[i]-min_bond_order[i]                                 */
    1669                 :             : /*   atom[k] initial_st_cap = at[k].chem_bonds_valence - SUM{i; initial_bond_order[i]}                */
    1670                 :             : /*   bond_cap[i]            =  BOND_TYPE_TRIPLE - min_bond_order[i]                                   */
    1671                 :             : /*     (reason: quadruple and higher order bonds are not allowed)                                     */
    1672                 :             : /* Exception: in case of metal-atom bond, if pSrm->nMetal2EndpointInitEdgeFlow = 0 AND                */
    1673                 :             : /* pSrm->nMetalInitBondOrder - pSrm->nMetalMinBondOrder = 1 then                                      */
    1674                 :             : /*   reduce bond to metal order by 1 and increase st_cap of both neighbors by 1:                      */
    1675                 :             : /*   initial_bond_flow[i] --; metal_initial_st_cap += num_bonds;                                      */
    1676                 :             : /* ==== Note: ONLY the INCREASE is already included in pVA->cInitFreeValences of both atoms           */
    1677                 :             : /*                                                                                                    */
    1678                 :             : /* Notes: initial_st_cap does not include:                                                            */
    1679                 :             : /*   1. atom[k] additional st_cap from ChargeStruct pCN[0].v.cap                                      */
    1680                 :             : /*   2. pVA[k].cInitFreeValences due to a difference between the smallest known valence and st_cap    */
    1681                 :             : /*                                                                                                    */
    1682                 :             : /*  here k=atom at[k] index,                                                                          */
    1683                 :             : /*       i=bond index; i = 0..at[k].valence;                                                          */
    1684                 :             : /*       SUM{i; M[i]} is a sum of M[i] over all i                                                     */
    1685                 :             : /*       bond_order[i] = at[k].bond_type[i] >= BOND_TYPE_SINGLE - input bond order                    */
    1686                 :             : /****************************************************************************/
    1687                 :             : 
    1688                 :             : /***************** new *************************************************************************************/
    1689                 :             : 
    1690                 :           0 : int BondFlowMaxcapMinorder( inp_ATOM *atom,
    1691                 :             :                             VAL_AT *pVA,
    1692                 :             :                             ICHICONST SRM *pSrm,
    1693                 :             :                             int iat,
    1694                 :             :                             int ineigh,
    1695                 :             :                             int *pnMaxcap,
    1696                 :             :                             int *pnMinorder,
    1697                 :             :                             int *pbNeedsFlower )
    1698                 :             : {
    1699                 :             : 
    1700                 :           0 :     int nFlow, nMaxcap, nMinorder, nInitorder, bNeedsFlower = 0;
    1701                 :           0 :     inp_ATOM *at = atom + iat;
    1702                 :           0 :     int       neigh = at->neighbor[ineigh];
    1703                 :           0 :     int       bond_type = at->bond_type[ineigh] & BOND_TYPE_MASK;
    1704                 :           0 :     int       nMetal = ( 0 != pVA[iat].cMetal ) + ( 0 != pVA[neigh].cMetal );
    1705                 :           0 :     int       nEndpoint = ( 0 != at->endpoint ) + ( 0 != atom[neigh].endpoint );
    1706   [ #  #  #  #  :           0 :     int       nStereo = ( at->p_parity || at->sb_parity[0] ) + ( atom[neigh].p_parity || atom[neigh].sb_parity[0] );
             #  #  #  # ]
    1707                 :             : 
    1708         [ #  # ]:           0 :     if (bond_type > BOND_TYPE_TRIPLE)
    1709                 :             :     {
    1710                 :           0 :         bond_type = BOND_TYPE_SINGLE;
    1711                 :             :     }
    1712                 :             : 
    1713                 :             :     /* M=metal, A=non-metal atom, e=endpoint */
    1714   [ #  #  #  #  :           0 :     if ((nStereo && pSrm->bFixStereoBonds) || !nMetal || !pSrm->bMetalAddFlower) /* djb-rwth: addressing LLVM warning */
             #  #  #  # ]
    1715                 :             :     {
    1716                 :             :         /* atom-atom rules, no metal atoms involved (1: A-A, A-Ae, Ae-Ae) */
    1717                 :           0 :         nMinorder = BOND_TYPE_SINGLE;
    1718                 :           0 :         nInitorder = bond_type;
    1719                 :           0 :         nFlow = nInitorder - nMinorder;
    1720                 :             :     }
    1721   [ #  #  #  # ]:           0 :     else if (nMetal && !nEndpoint)
    1722                 :             :     {
    1723                 :             :         /* M-a, M-M */
    1724                 :             :         /* atom - metal or metal-metal, none of them is an endpoint (2: M-M, M-A) */
    1725                 :           0 :         nMinorder = pSrm->nMetalMinBondOrder;
    1726                 :           0 :         nInitorder = pSrm->nMetalInitBondOrder + bond_type - BOND_TYPE_SINGLE;
    1727                 :           0 :         nFlow = nInitorder - nMinorder;
    1728         [ #  # ]:           0 :         if (!pSrm->nMetalInitEdgeFlow &&
    1729   [ #  #  #  # ]:           0 :              pSrm->nMetalInitBondOrder > pSrm->nMetalMinBondOrder &&
    1730                 :             :              nFlow > 0)
    1731                 :             :         {
    1732                 :             :             /* reduce initial flow by 1 and increase st_cap on metal by 1 */
    1733                 :           0 :             nFlow--;
    1734                 :             :         }
    1735                 :           0 :         bNeedsFlower = ( 0 != pVA[iat].cMetal );
    1736                 :             :     }
    1737                 :             :     else
    1738   [ #  #  #  #  :           0 :         if ((pVA[iat].cMetal && !at->endpoint && !pVA[neigh].cMetal && atom[neigh].endpoint) ||
             #  #  #  # ]
    1739   [ #  #  #  #  :           0 :              (pVA[neigh].cMetal && !atom[neigh].endpoint && !pVA[iat].cMetal && at->endpoint)) /* djb-rwth: addressing LLVM warnings */
             #  #  #  # ]
    1740                 :             :         {
    1741                 :             :             /* M-ae */
    1742                 :             :             /* metal connected to a non-metal endpoint (3: M-Ae) */
    1743                 :           0 :             nMinorder = pSrm->nMetal2EndpointMinBondOrder;
    1744                 :           0 :             nInitorder = pSrm->nMetal2EndpointInitBondOrder + bond_type - BOND_TYPE_SINGLE;
    1745                 :           0 :             nFlow = nInitorder - nMinorder;
    1746         [ #  # ]:           0 :             if (!pSrm->nMetal2EndpointInitEdgeFlow &&
    1747   [ #  #  #  # ]:           0 :                  pSrm->nMetal2EndpointInitBondOrder > pSrm->nMetal2EndpointMinBondOrder &&
    1748                 :             :                  nFlow > 0)
    1749                 :             :             {
    1750                 :             :                 /* reduce initial flow by 1 and increase st_cap on metal by 1 */
    1751                 :           0 :                 nFlow--;
    1752                 :             :             }
    1753                 :           0 :             bNeedsFlower = ( 0 != pVA[iat].cMetal );
    1754                 :             :         }
    1755                 :             :         else
    1756                 :             :         {
    1757                 :             :             /* endpoint is metal => no flower (4: M-Me, Me-Me, Me-A, Me-Ae) */
    1758                 :           0 :             nMinorder = pSrm->nMetal2EndpointMinBondOrder;
    1759                 :           0 :             nInitorder = pSrm->nMetal2EndpointInitBondOrder + bond_type - BOND_TYPE_SINGLE;
    1760                 :           0 :             nFlow = nInitorder - nMinorder;
    1761         [ #  # ]:           0 :             if (!pSrm->nMetal2EndpointInitEdgeFlow &&
    1762   [ #  #  #  # ]:           0 :                  pSrm->nMetal2EndpointInitBondOrder > pSrm->nMetal2EndpointMinBondOrder &&
    1763                 :             :                  nFlow > 0)
    1764                 :             :             {
    1765                 :             : /* reduce initial flow by 1 and increase st_cap on metal by 1 */
    1766                 :           0 :                 nFlow--;
    1767                 :             :             }
    1768   [ #  #  #  # ]:           0 :             bNeedsFlower = ( pVA[iat].cMetal && !at->endpoint );
    1769                 :             :         }
    1770                 :             : 
    1771                 :           0 :     nMaxcap = BOND_TYPE_TRIPLE - nMinorder;
    1772         [ #  # ]:           0 :     if (pnMaxcap)
    1773                 :             :     {
    1774                 :           0 :         *pnMaxcap = nMaxcap;
    1775                 :             :     }
    1776         [ #  # ]:           0 :     if (pnMinorder)
    1777                 :             :     {
    1778                 :           0 :         *pnMinorder = nMinorder;
    1779                 :             :     }
    1780         [ #  # ]:           0 :     if (pbNeedsFlower)
    1781                 :             :     {
    1782                 :           0 :         *pbNeedsFlower = bNeedsFlower;
    1783                 :             :     }
    1784                 :             : 
    1785                 :           0 :     return nFlow;
    1786                 :             : }
    1787                 :             : 
    1788                 :             : 
    1789                 :             : /*********** new *******************************************************************************************/
    1790                 :           0 : int AtomStcapStflow( inp_ATOM *atom, VAL_AT *pVA, ICHICONST SRM *pSrm, int iat, int *pnStcap, int *pnStflow,
    1791                 :             :                      EdgeFlow *pnMGroupEdgeCap, EdgeFlow *pnMGroupEdgeFlow )
    1792                 :             : {
    1793                 :             :     int ineigh, bFlower;
    1794                 :           0 :     int nStflow = 0, nMaxBondCap, nMinBondOrder, bNeedsFlower = 0;
    1795                 :           0 :     int valence = atom[iat].valence;
    1796                 :           0 :     int nStcap = atom[iat].chem_bonds_valence;
    1797                 :           0 :     int nMGroupEdgeCap = 0, nMGroupEdgeFlow = 0, nFlow;
    1798                 :             : 
    1799         [ #  # ]:           0 :     if (pSrm->bMetalAddFlower)
    1800                 :             :     {
    1801                 :           0 :         nStcap -= pVA[iat].cInitOrigValenceToMetal - pVA[iat].cInitValenceToMetal;
    1802                 :             :     }
    1803                 :             : 
    1804         [ #  # ]:           0 :     for (ineigh = 0; ineigh < valence; ineigh++)
    1805                 :             :     {
    1806                 :           0 :         nFlow = BondFlowMaxcapMinorder( atom, pVA, pSrm, iat, ineigh, &nMaxBondCap, &nMinBondOrder, &bFlower );
    1807                 :           0 :         nStflow += nFlow;
    1808                 :           0 :         nStcap -= nMinBondOrder;
    1809         [ #  # ]:           0 :         if (bFlower)
    1810                 :             :         {
    1811                 :           0 :             bNeedsFlower++;
    1812                 :           0 :             nMGroupEdgeFlow += nFlow;
    1813                 :           0 :             nMGroupEdgeCap += BOND_TYPE_TRIPLE - nMinBondOrder + pSrm->nMetalMaxCharge_D;
    1814                 :             :         }
    1815                 :             :     }
    1816                 :             : 
    1817         [ #  # ]:           0 :     if (pnStcap)
    1818                 :             :     {
    1819         [ #  # ]:           0 :         *pnStcap = bNeedsFlower ? nStflow : nStcap; /* initially, metal atoms are not radicals */
    1820                 :             :     }
    1821         [ #  # ]:           0 :     if (pnStflow)
    1822                 :             :     {
    1823                 :           0 :         *pnStflow = nStflow;
    1824                 :             :     }
    1825         [ #  # ]:           0 :     if (pnMGroupEdgeFlow)
    1826                 :             :     {
    1827                 :           0 :         *pnMGroupEdgeFlow = nMGroupEdgeCap - nMGroupEdgeFlow;
    1828                 :             :     }
    1829         [ #  # ]:           0 :     if (pnMGroupEdgeCap)
    1830                 :             :     {
    1831                 :           0 :         *pnMGroupEdgeCap = nMGroupEdgeCap;
    1832                 :             :     }
    1833                 :             : 
    1834                 :           0 :     return bNeedsFlower; /* number of variable bonds to metal */
    1835                 :             : }
    1836                 :             : 
    1837                 :             : 
    1838                 :             : /**************************************************************************************
    1839                 :             : int nCountBnsSizes( inp_ATOM *at, int num_at, int nAddEdges2eachAtom, int nAddVertices,
    1840                 :             :                     T_GROUP_INFO *ti, VAL_AT *pVA, ALL_TC_GROUPS *pTCGroups )
    1841                 :             : 
    1842                 :             : fills out totals:
    1843                 :             : 
    1844                 :             :   pTCGroups->num_atoms        = number of atoms
    1845                 :             :   pTCGroups->num_bonds        = number of bonds between atoms
    1846                 :             :   pTCGroups->num_tgroups      = number of tautomeric groups
    1847                 :             :   pTCGroups->num_tgroup_edges = number of edges to tautomeric groups
    1848                 :             :   pTCGroups->tgroup_charge    = total charge on thautomeric atoms (negative)
    1849                 :             :   pTCGroups->num_tc_groups    = total number of all groups
    1850                 :             :   pTCGroups->nVertices        = total number of vertices excluding groups interconnections
    1851                 :             :   pTCGroups->nEdges           = total number of edges excluding groups interconnections
    1852                 :             : 
    1853                 :             : creates entries for the groups and adds to each group:
    1854                 :             : 
    1855                 :             :   TC_GROUP::type       =  BNS_VERT_TYPE_TGROUP, BNS_VT_C_POS, BNS_VT_C_NEG, BNS_VT_C_POS_C, BNS_VT_C_NEG_C
    1856                 :             :   TC_GROUP::ord_num    =  ordering number within the type, e.g. t-group number
    1857                 :             :   TC_GROUP::st_cap     =  all from the atoms in ChargeStruct or tautomeric group info.
    1858                 :             :   TC_GROUP::st_flow    =  all from the atoms in ChargeStruct (0 for t-groups).
    1859                 :             :   TC_GROUP::num_edges  =  number of edges to the atoms or ChargeStruct vertices.
    1860                 :             :   TC_GROUP::edges_cap  =  sum of all incoming edge caps; see also nTautEndpointEdgeCap(..).
    1861                 :             :   TC_GROUP::edges_flow =  sum of all incoming edge flows; 0 for t-groups.
    1862                 :             : 
    1863                 :             :   TC_GROUP::nVertexNumber - NO FILLED WITH ANYTHING
    1864                 :             : 
    1865                 :             :   Note: the nDelta = st_cap - st_flow needs to be preserved when adding more vertices
    1866                 :             : 
    1867                 :             : Return value: =0 => success
    1868                 :             :               <0 => error
    1869                 :             :  **************************************************************************************/
    1870                 :           0 : int nCountBnsSizes( inp_ATOM *at, int num_at, int nAddEdges2eachAtom, int nAddVertices,
    1871                 :             :                     T_GROUP_INFO *ti, VAL_AT *pVA, ICHICONST SRM *pSrm, ALL_TC_GROUPS *pTCGroups )
    1872                 :             : {
    1873                 :           0 :     int i, j, n, k, ret = 0, nBonds, nOtherEdges, nVertices, bMetalAtoms, bNeedsFlower;
    1874                 :             :     int nTgroupEdges, nTgroupEdgesFromTg, nTotNegChargInTgroups, cap, flow;
    1875                 :           0 :     MY_CONST C_NODE *pCN = NULL;
    1876                 :           0 :     nVertices = nBonds = nOtherEdges = nTgroupEdges = nTgroupEdgesFromTg = nTotNegChargInTgroups = 0;
    1877                 :             : 
    1878                 :             :     /* count metal atoms and electrons */
    1879         [ #  # ]:           0 :     for (i = 0; i < num_at; i++)
    1880                 :             :     {
    1881                 :           0 :         pTCGroups->num_metal_atoms += ( pVA[i].cMetal != 0 );
    1882                 :           0 :         pTCGroups->num_metal_bonds += pVA[i].cNumBondsToMetal;
    1883                 :           0 :         pTCGroups->total_electrons += at[i].el_number;
    1884         [ #  # ]:           0 :         pTCGroups->total_electrons_metals += pVA[i].cMetal ? at[i].el_number : 0;
    1885                 :             :     }
    1886                 :           0 :     pTCGroups->total_electrons -= pTCGroups->total_charge;
    1887                 :           0 :     pTCGroups->num_metal_bonds /= 2;
    1888                 :             : 
    1889                 :             :     /* register tautomeric groups */
    1890         [ #  # ]:           0 :     for (i = 0; i < ti->num_t_groups; i++)
    1891                 :             :     {
    1892                 :           0 :         ret = RegisterTCGroup( pTCGroups,
    1893                 :             :                                BNS_VERT_TYPE_TGROUP,
    1894                 :           0 :                                ti->t_group[i].nGroupNumber,
    1895                 :           0 :                                ti->t_group[i].num[0] /* st_cap */,
    1896                 :             :                                0 /* st_flow */,
    1897                 :             :                                0 /* edge cap */,
    1898                 :             :                                0 /* edge flow */,
    1899                 :           0 :                                ti->t_group[i].nNumEndpoints /* num Edges */
    1900                 :             :         );
    1901         [ #  # ]:           0 :         if (ret < 0)
    1902                 :             :         {
    1903                 :           0 :             goto exit_function;
    1904                 :             :         }
    1905                 :             : 
    1906                 :             :         /* edges to tautomeric groups */
    1907                 :           0 :         nOtherEdges += ti->t_group[i].nNumEndpoints;
    1908                 :           0 :         nTgroupEdgesFromTg += ti->t_group[i].nNumEndpoints;
    1909                 :             :         /* total negative charge in t-groups */
    1910                 :           0 :         nTotNegChargInTgroups += ti->t_group[i].num[1];
    1911         [ #  # ]:           0 :         if (ret > 0)
    1912                 :             :         {
    1913                 :             :             /* should always happen since this is the first time this t-group is added */
    1914                 :           0 :             j = ret - 1;
    1915                 :           0 :             pTCGroups->pTCG[j].tg_num_H = ti->t_group[i].num[0] - ti->t_group[i].num[1];
    1916                 :           0 :             pTCGroups->pTCG[j].tg_num_Minus = ti->t_group[i].num[1];
    1917                 :             :         }
    1918                 :             :     }
    1919                 :             : 
    1920                 :           0 :     bMetalAtoms = 0;
    1921                 :             : 
    1922                 :           0 : repeat_for_metals:
    1923                 :             : 
    1924                 :             :     /* count vertices and register ChargeValence groups */
    1925                 :             :     /* for now an atom may belong either to a t-group or to a ChargeValence group, but not to both */
    1926         [ #  # ]:           0 :     for (i = 0; i < num_at; i++)
    1927                 :             :     {
    1928                 :             :         /* number of bonds */
    1929                 :           0 :         nBonds += at[i].valence;
    1930                 :             :         /* Process ChargeStruct vertices and edges */
    1931         [ #  # ]:           0 :         if (pVA[i].cnListIndex)
    1932                 :             :         {
    1933                 :             :             /* count vertices & edges in the ChargeValence Substructure attached to an atom */
    1934                 :             :             /* Important: unlike inp_ATOM, each edge e appears in pCN[*].e[*] only ONE time */
    1935                 :           0 :             int     len = cnList[j = pVA[i].cnListIndex - 1].len;
    1936                 :           0 :             int     bits = cnList[j].bits;
    1937                 :             :             int     type, neigh_type; /* djb-rwth: removing redundant variables */
    1938                 :           0 :             pCN = cnList[j].pCN;
    1939                 :             : 
    1940                 :             :             /* first process all non-metals, after that -- all metals */
    1941         [ #  # ]:           0 :             if (( bits != cn_bits_Me ) != !bMetalAtoms)
    1942                 :             :             {
    1943                 :           0 :                 continue;
    1944                 :             :             }
    1945                 :             :             /* djb-rwth: removing redundant code */
    1946         [ #  # ]:           0 :             for (j = 0; j < len; j++)
    1947                 :             :             {
    1948                 :           0 :                 type = pCN[j].v.type; /* ChargeStruct vertex type: atom is the first, c-groups are last */
    1949                 :             : 
    1950                 :             :                 /* process all pCN[j] neighbors */
    1951   [ #  #  #  # ]:           0 :                 for (k = 0; k < MAX_CN_VAL && ( n = pCN[j].e[k].neigh ); k++)
    1952                 :             :                 {
    1953                 :           0 :                     nOtherEdges++;  /* edges inside ChargeStruct */
    1954                 :           0 :                     n--; /* neighbor vertex position inside cnList[j].pCN */
    1955                 :           0 :                     neigh_type = pCN[n].v.type; /* type of the neighboring atom */
    1956                 :             : 
    1957         [ #  # ]:           0 :                     if (IS_BNS_VT_C_GR( neigh_type ))
    1958                 :             :                     {
    1959                 :             :                         /* register this edge to a CN-group vertex */
    1960   [ #  #  #  # ]:           0 :                         cap = !bMetalAtoms ? pCN[j].e[k].cap : pCN[j].e[k].cap ? pSrm->nMetalMaxCharge_D : 0;
    1961   [ #  #  #  # ]:           0 :                         flow = !bMetalAtoms ? pCN[j].e[k].flow : pCN[j].e[k].flow ? pSrm->nMetalMaxCharge_D : 0;
    1962                 :             : 
    1963                 :           0 :                         ret = RegisterTCGroup( pTCGroups,
    1964                 :             :                                                neigh_type,
    1965                 :             :                                                0 /* ord_num*/,
    1966                 :             :                                                0 /* st_cap */,
    1967                 :             :                                                0 /* st_flow */,
    1968                 :             :                                                cap /* edge cap*/,
    1969                 :             :                                                flow /* edge flow */,
    1970                 :             :                                                1 /* nNumEdges*/ );
    1971         [ #  # ]:           0 :                         if (ret < 0)
    1972                 :             :                         {
    1973                 :           0 :                             goto exit_function;
    1974                 :             :                         }
    1975         [ #  # ]:           0 :                         if (ret > 0)
    1976                 :             :                         {
    1977                 :             :                             /* the group has just been created; add one more edge to (+/-) or supergroup */
    1978                 :           0 :                             ret = RegisterTCGroup( pTCGroups,
    1979                 :             :                                                    neigh_type,
    1980                 :             :                                                    0 /* ord_num*/,
    1981                 :             :                                                    0 /* st_cap */,
    1982                 :             :                                                    0 /* st_flow */,
    1983                 :             :                                                    0 /* edge cap*/,
    1984                 :             :                                                    0/* edge flow*/,
    1985                 :             :                                                    1 /* nNumEdges*/ );
    1986         [ #  # ]:           0 :                             if (ret < 0)
    1987                 :             :                             {
    1988                 :           0 :                                 goto exit_function;
    1989                 :             :                             }
    1990                 :           0 :                             nOtherEdges++;
    1991                 :             :                         }
    1992                 :             :                     }
    1993                 :             : 
    1994         [ #  # ]:           0 :                     if (IS_BNS_VT_C_GR( type ))
    1995                 :             :                     {
    1996                 :             :                         /* register this edge to a CN-group vertex; normally this does not happen */
    1997                 :             : 
    1998   [ #  #  #  # ]:           0 :                         cap = !bMetalAtoms ? pCN[j].e[k].cap : pCN[j].e[k].cap ? pSrm->nMetalMaxCharge_D : 0;
    1999   [ #  #  #  # ]:           0 :                         flow = !bMetalAtoms ? pCN[j].e[k].flow : pCN[j].e[k].flow ? pSrm->nMetalMaxCharge_D : 0;
    2000                 :             : 
    2001                 :           0 :                         ret = RegisterTCGroup( pTCGroups, type, 0 /* ord_num*/,
    2002                 :             :                                                0 /* st_cap */, 0 /* st_flow */,
    2003                 :             :                                                cap /* edge cap*/, flow /* edge flow */, 1 /* nNumEdges*/ );
    2004         [ #  # ]:           0 :                         if (ret < 0)
    2005                 :             :                         {
    2006                 :           0 :                             goto exit_function;
    2007                 :             :                         }
    2008         [ #  # ]:           0 :                         if (ret > 0)
    2009                 :             :                         {
    2010                 :             :                             /* the group has just been created; add one more edge to (+/-) or supergroup */
    2011                 :           0 :                             ret = RegisterTCGroup( pTCGroups, type, 0 /* ord_num*/,
    2012                 :             :                                                    0 /* st_cap */, 0 /* st_flow */,
    2013                 :             :                                                    0 /* edge cap*/, 0/* edge flow*/, 1 /* nNumEdges*/ );
    2014         [ #  # ]:           0 :                             if (ret < 0)
    2015                 :             :                             {
    2016                 :           0 :                                 goto exit_function;
    2017                 :             :                             }
    2018                 :           0 :                             nOtherEdges++;
    2019                 :             :                         }
    2020                 :             :                     }
    2021                 :             :                 } /* end of the current vertex pCN[j] neighbors */
    2022                 :             : 
    2023                 :             :                 /* process  pCN[j] vertex */
    2024                 :             : 
    2025         [ #  # ]:           0 :                 if (type & BNS_VERT_TYPE_ATOM)
    2026                 :             :                 {
    2027                 :           0 :                     continue;  /* do not count regular atoms here */
    2028                 :             :                 }
    2029   [ #  #  #  # ]:           0 :                 if (IS_BNS_VT_CHRG_STRUCT( type ))
    2030                 :             :                 {
    2031                 :           0 :                     nVertices++;
    2032                 :           0 :                     continue;
    2033                 :             :                 }
    2034                 :             : 
    2035   [ #  #  #  # ]:           0 :                 if (pSrm->bMetalAddFlower && IS_BNS_VT_M_GR( type ))
    2036                 :           0 :                 {
    2037                 :             :                     /* special treatment: flow and cap are known as well as structure */
    2038                 :             :                     /* initial bond valence to metal is either 0 or 1 */
    2039                 :             :                     EdgeFlow nEdgeFlow, nEdgeCap;
    2040                 :             : 
    2041                 :           0 :                     bNeedsFlower = AtomStcapStflow( at, pVA, pSrm, i, NULL /*pnStcap*/, NULL /*pnStflow*/,
    2042                 :             :                                                     &nEdgeCap, &nEdgeFlow );
    2043         [ #  # ]:           0 :                     if (!bNeedsFlower)
    2044                 :             :                     {
    2045                 :           0 :                         ret = RI_ERR_PROGR;
    2046                 :           0 :                         goto exit_function;
    2047                 :             :                     }
    2048                 :             :                     /*
    2049                 :             :                     GetAtomToMCGroupInitEdgeCapFlow( &nEdgeCap, &nEdgeFlow, pSrm, at,  pVA, i );
    2050                 :             :                     GetAtomToMCGroupInitEdgeCapFlow( &nEdgeCap, &nEdgeFlow, pSrm );
    2051                 :             :                     */
    2052                 :             :                     /* the 1st is the flower base */
    2053                 :             :                     /* atom - G0 edge and G0 vertex */
    2054                 :           0 :                     ret = RegisterTCGroup( pTCGroups,
    2055                 :             :                                            type,
    2056                 :             :                                            0 /* ord_num*/,
    2057                 :             :                                            /*pVA[i].cInitFreeValences*/
    2058                 :             :                                            0 /* st_cap */,
    2059                 :             :                                            0 /* st_flow */,
    2060                 :             :                                            (int) nEdgeCap,
    2061                 :             :                                            (int) nEdgeFlow,
    2062                 :             :                                            1 /* nNumEdges*/ );
    2063         [ #  # ]:           0 :                     if (ret < 0)
    2064                 :             :                     {
    2065                 :           0 :                         goto exit_function;
    2066                 :             :                     }
    2067                 :             :                     /* count edge atom-G0 */
    2068                 :           0 :                     nOtherEdges++;
    2069         [ #  # ]:           0 :                     if (ret > 0)
    2070                 :             :                     {
    2071                 :             :                         /* first time registration: add G0-G1 and G0-G2 edges to G0 */
    2072                 :             : 
    2073                 :           0 :                         ret = RegisterTCGroup( pTCGroups,
    2074                 :             :                                                type,
    2075                 :             :                                                0 /* ord_num*/,
    2076                 :             :                                                0 /* st_cap */,
    2077                 :             :                                                0 /* st_flow */,
    2078                 :             :                                                0,/* edge cap*/
    2079                 :             :                                                0 /*edge flow*/,
    2080                 :             :                                                2 /* nNumEdges*/ );
    2081                 :             : 
    2082         [ #  # ]:           0 :                         if (ret < 0)
    2083                 :             :                         {
    2084                 :           0 :                             goto exit_function;
    2085                 :             :                         }
    2086                 :             : 
    2087                 :             :                         /* first time registration: add G1; it has 3 edges */
    2088                 :             : 
    2089                 :           0 :                         ret = RegisterTCGroup( pTCGroups,
    2090                 :             :                                                type,
    2091                 :             :                                                1 /* ord_num*/,
    2092                 :             :                                                0 /* st_cap */,
    2093                 :             :                                                0 /* st_flow */,
    2094                 :             :                                                0,/* edge cap*/
    2095                 :             :                                                0 /*edge flow*/,
    2096                 :             :                                                3 /* nNumEdges*/ );
    2097                 :             : 
    2098         [ #  # ]:           0 :                         if (ret <= 0)
    2099                 :             :                         {
    2100         [ #  # ]:           0 :                             ret = !ret ? RI_ERR_PROGR : ret;
    2101                 :           0 :                             goto exit_function;
    2102                 :             :                         }
    2103                 :             : 
    2104                 :             :                         /* first time registration: add G2; it has 3 edges */
    2105                 :             : 
    2106                 :           0 :                         ret = RegisterTCGroup( pTCGroups,
    2107                 :             :                                                type,
    2108                 :             :                                                2 /* ord_num*/,
    2109                 :             :                                                0 /* st_cap */,
    2110                 :             :                                                0 /* st_flow */,
    2111                 :             :                                                0,/* edge cap*/
    2112                 :             :                                                0 /*edge flow*/,
    2113                 :             :                                                3 /* nNumEdges*/ );
    2114                 :             : 
    2115         [ #  # ]:           0 :                         if (ret <= 0)
    2116                 :             :                         {
    2117         [ #  # ]:           0 :                             ret = !ret ? RI_ERR_PROGR : ret;
    2118                 :           0 :                             goto exit_function;
    2119                 :             :                         }
    2120                 :             : 
    2121                 :             :                         /* first time registration: add G3; it has 2 edges */
    2122                 :             : 
    2123                 :           0 :                         ret = RegisterTCGroup( pTCGroups,
    2124                 :             :                                                type,
    2125                 :             :                                                3 /* ord_num*/,
    2126                 :             :                                                0 /* st_cap */,
    2127                 :             :                                                0 /* st_flow */,
    2128                 :             :                                                0,/* edge cap*/
    2129                 :             :                                                0 /*edge flow*/,
    2130                 :             :                                                2 /* nNumEdges*/ );
    2131                 :             : 
    2132         [ #  # ]:           0 :                         if (ret <= 0)
    2133                 :             :                         {
    2134         [ #  # ]:           0 :                             ret = !ret ? RI_ERR_PROGR : ret;
    2135                 :           0 :                             goto exit_function;
    2136                 :             :                         }
    2137                 :             :                         /* count added metal flower vertices: G0, G1, G2, G3 */
    2138                 :           0 :                         nVertices += 4;
    2139                 :             :                         /* count added metal flower edges: C0-C1, C0-C2, C1-C2, C1-C3, C2-C3 */
    2140                 :           0 :                         nOtherEdges += 5;
    2141                 :             :                         /* add connections of G0 to G1 and G2 */
    2142                 :             :                     }
    2143                 :           0 :                     continue;
    2144                 :             :                 }
    2145                 :             : 
    2146                 :           0 :                 nVertices++; /* count BNS_VT_C_POS* types; all contain BNS_VERT_TYPE_C_GROUP bit */
    2147         [ #  # ]:           0 :                 if (!IS_BNS_VT_C_GR( type ))
    2148                 :             :                 {  /* check */
    2149                 :           0 :                     ret = RI_ERR_PROGR;
    2150                 :           0 :                     goto exit_function;
    2151                 :             :                 }
    2152                 :             :                 /* add st_cap and st_flow for a charge group */
    2153   [ #  #  #  # ]:           0 :                 cap = !bMetalAtoms ? pCN[j].v.cap : pCN[j].v.cap ? pSrm->nMetalMaxCharge_D : 0;
    2154   [ #  #  #  # ]:           0 :                 flow = !bMetalAtoms ? pCN[j].v.flow : pCN[j].v.flow ? pSrm->nMetalMaxCharge_D : 0;
    2155                 :             : 
    2156                 :           0 :                 ret = RegisterTCGroup( pTCGroups, type, 0 /* ord_num*/,
    2157                 :             :                                        cap /* st-cap*/, flow /* st-flow */,
    2158                 :             :                                        0 /* edge cap */, 0 /* edge flow */, 0 /* edges already counted */ );
    2159         [ #  # ]:           0 :                 if (ret < 0)
    2160                 :             :                 {
    2161                 :           0 :                     goto exit_function;
    2162                 :             :                 }
    2163                 :             :             }
    2164                 :             :         }
    2165                 :             :         else
    2166                 :             :         {
    2167                 :           0 :             pCN = NULL;
    2168                 :             :         }
    2169                 :             : 
    2170                 :             :         /* count edge caps to t-groups */
    2171         [ #  # ]:           0 :         if (at[i].endpoint)
    2172                 :             :         {
    2173                 :           0 :             int nEdgeCap = nTautEndpointEdgeCap( at, pVA, i );
    2174                 :           0 :             nTgroupEdges++;
    2175         [ #  # ]:           0 :             if (nEdgeCap < 0)
    2176                 :             :             {
    2177                 :           0 :                 ret = nEdgeCap;
    2178                 :           0 :                 goto exit_function;
    2179                 :             :             }
    2180                 :             : 
    2181                 :             :             /* add number of unsatisfied valences for a t-group; the unknown flow = 0 */
    2182                 :           0 :             ret = RegisterTCGroup( pTCGroups,
    2183                 :             :                                    BNS_VERT_TYPE_TGROUP,
    2184                 :           0 :                                    at[i].endpoint,
    2185                 :             :                                    0 /* st_cap */,
    2186                 :             :                                    0 /* st_flow */,
    2187                 :             :                                    nEdgeCap /* edge cap */,
    2188                 :             :                                    0 /* edge flow */,
    2189                 :             :                                    0 /* t-group edges have already been counted */ );
    2190         [ #  # ]:           0 :             if (ret < 0)
    2191                 :             :             {
    2192                 :           0 :                 goto exit_function;
    2193                 :             :             }
    2194                 :             :         }
    2195                 :             :     }
    2196                 :             : 
    2197   [ #  #  #  # ]:           0 :     if (!bMetalAtoms && pTCGroups->num_metal_atoms)
    2198                 :             :     {
    2199                 :           0 :         bMetalAtoms = 1;
    2200                 :           0 :         nBonds = 0; /* added 2006-05-15 */
    2201                 :           0 :         goto repeat_for_metals;
    2202                 :             :     }
    2203                 :             : 
    2204                 :             :     /* count real atoms and bonds */
    2205                 :           0 :     nBonds /= 2;
    2206                 :           0 :     pTCGroups->num_atoms = num_at;
    2207                 :           0 :     pTCGroups->num_bonds = nBonds;
    2208                 :             : 
    2209                 :           0 :     pTCGroups->num_tgroups = ti->num_t_groups;
    2210                 :           0 :     pTCGroups->num_tgroup_edges = nTgroupEdges;
    2211                 :           0 :     pTCGroups->tgroup_charge = -nTotNegChargInTgroups;
    2212                 :             : 
    2213   [ #  #  #  # ]:           0 :     if (0 <= ret && nTgroupEdgesFromTg != nTgroupEdges)
    2214                 :             :     {
    2215                 :           0 :         ret = BNS_PROGRAM_ERR;
    2216                 :             :     }
    2217                 :             : 
    2218                 :           0 :     nVertices += num_at;
    2219                 :             : 
    2220                 :             : 
    2221                 :             :     /* count other vertices */
    2222                 :           0 :     nVertices += ti->num_t_groups;
    2223                 :           0 :     nBonds += nOtherEdges;
    2224                 :             : 
    2225                 :             :     /* return edges and vertices */
    2226                 :           0 :     pTCGroups->nVertices = nVertices;
    2227                 :           0 :     pTCGroups->nEdges = nBonds;
    2228                 :             : 
    2229                 :             : 
    2230                 :           0 : exit_function:
    2231                 :           0 :     return ret;
    2232                 :             : }
    2233                 :             : 
    2234                 :             : 
    2235                 :             : /****************************************************************
    2236                 :             :   int nAddSuperCGroups( ALL_TC_GROUPS *pTCGroups )
    2237                 :             : 
    2238                 :             :   1. adds BNS_VT_C_POS_ALL and BNS_VT_C_NEG_ALL ONLY if both
    2239                 :             :      {TCG_Plus0  and TCG_Plus_C0} and/or
    2240                 :             :      {TCG_Minus0 and TCG_Minus_C0} are present, respectively
    2241                 :             : 
    2242                 :             :   2. fills pTCGroups->nGroup[]:
    2243                 :             : 
    2244                 :             :   pTCGroups->nGroup[k] < 0  => does not exist
    2245                 :             :   pTCGroups->nGroup[k] = i  => the group is pTCGroups->pTCG[i]
    2246                 :             : 
    2247                 :             :     where           group           group
    2248                 :             :       k =           type            number
    2249                 :             :     TCG_Plus0       BNS_VT_C_POS      0
    2250                 :             :     TCG_Plus1,      BNS_VT_C_POS      1
    2251                 :             :     TCG_Minus0,     BNS_VT_C_NEG      0
    2252                 :             :     TCG_Minus1,     BNS_VT_C_NEG      1
    2253                 :             :     TCG_Plus_C0,    BNS_VT_C_POS_C    0
    2254                 :             :     TCG_Plus_C1,    BNS_VT_C_POS_C    1
    2255                 :             :     TCG_Minus_C0,   BNS_VT_C_NEG_C    0
    2256                 :             :     TCG_Minus_C1,   BNS_VT_C_NEG_C    1
    2257                 :             :     TCG_Plus,       BNS_VT_C_POS_ALL  0
    2258                 :             :     TCG_Minus,      BNS_VT_C_NEG_ALL  0
    2259                 :             : 
    2260                 :             : only groups with number 0 are processed
    2261                 :             : 
    2262                 :             :   3. If only one of the groups in pairs mentioned in (1) above
    2263                 :             :      is present then
    2264                 :             : 
    2265                 :             :      pTCGroups->nGroup[TCG_Plus] := pTCGroups->nGroup[TCG_Plus0] or
    2266                 :             :      pTCGroups->nGroup[TCG_Plus] := pTCGroups->nGroup[TCG_Plus_C0];
    2267                 :             :      an additional BNS_VT_C_POS_ALL vertex is not created
    2268                 :             : 
    2269                 :             :      same for pTCGroups->nGroup[TCG_Minus] and BNS_VT_C_NEG_ALL
    2270                 :             : 
    2271                 :             :   4. Adds to these new "supergroups" (TCG_Plus, TCG_Minus)
    2272                 :             :      descriptions in pTCGroups->pTCG[k]
    2273                 :             :      st_cap, st_flow, edges cap and flow from the corresponding
    2274                 :             :      groups {TCG_Plus0  and TCG_Plus_C0}. Same for the Minus groups.
    2275                 :             :      Stores indexes k in
    2276                 :             :      pTCGroups->nGroup[TCG_Plus], pTCGroups->nGroup[TCG_Minus]
    2277                 :             : 
    2278                 :             :  ****************************************************************/
    2279                 :           0 : int nAddSuperCGroups( ALL_TC_GROUPS *pTCGroups )
    2280                 :             : {
    2281                 :           0 :     int i, k, n, n1, n2, n3, ret = 0, nNumToConnect; /* djb-rwth: removing redundant variables */
    2282                 :             : 
    2283         [ #  # ]:           0 :     for (i = 0; i < pTCGroups->num_tc_groups; i++)
    2284                 :             :     {
    2285         [ #  # ]:           0 :         if (pTCGroups->pTCG[i].type & BNS_VERT_TYPE_TGROUP)
    2286                 :             :         {
    2287                 :             :             /* djb-rwth: removing redundant code */
    2288                 :           0 :             continue; /* t-group */
    2289                 :             :         }
    2290         [ #  # ]:           0 :         if (IS_BNS_VT_C_GR( pTCGroups->pTCG[i].type ) ||
    2291         [ #  # ]:           0 :              IS_BNS_VT_M_GR( pTCGroups->pTCG[i].type ))
    2292                 :             :         {
    2293                 :             :             /* ChargeValence (cn) group */
    2294   [ #  #  #  #  :           0 :             switch (pTCGroups->pTCG[i].type)
             #  #  #  # ]
    2295                 :             :             {
    2296                 :           0 :                 case BNS_VT_C_POS:
    2297                 :           0 :                     k = TCG_Plus0;
    2298                 :           0 :                     break;
    2299                 :           0 :                 case BNS_VT_C_NEG:
    2300                 :           0 :                     k = TCG_Minus0;
    2301                 :           0 :                     break;
    2302                 :           0 :                 case BNS_VT_C_POS_C:
    2303                 :           0 :                     k = TCG_Plus_C0;
    2304                 :           0 :                     break;
    2305                 :           0 :                 case BNS_VT_C_NEG_C:
    2306                 :           0 :                     k = TCG_Minus_C0;
    2307                 :           0 :                     break;
    2308                 :           0 :                 case BNS_VT_C_POS_M:
    2309                 :           0 :                     k = TCG_Plus_M0;
    2310                 :           0 :                     break;
    2311                 :           0 :                 case BNS_VT_C_NEG_M:
    2312                 :           0 :                     k = TCG_Minus_M0;
    2313                 :           0 :                     break;
    2314                 :           0 :                 case BNS_VT_M_GROUP:
    2315   [ #  #  #  #  :           0 :                     switch (pTCGroups->pTCG[i].ord_num)
                      # ]
    2316                 :             :                     {
    2317                 :           0 :                         case 0:
    2318                 :           0 :                             k = TCG_MeFlower0;
    2319                 :           0 :                             break;
    2320                 :           0 :                         case 1:
    2321                 :           0 :                             k = TCG_MeFlower1;
    2322                 :           0 :                             break;
    2323                 :           0 :                         case 2:
    2324                 :           0 :                             k = TCG_MeFlower2;
    2325                 :           0 :                             break;
    2326                 :           0 :                         case 3:
    2327                 :           0 :                             k = TCG_MeFlower3;
    2328                 :           0 :                             break;
    2329                 :           0 :                         default:
    2330                 :           0 :                             ret = RI_ERR_PROGR; /* unexpected group type */
    2331                 :           0 :                             goto exit_function;
    2332                 :             :                     }
    2333                 :           0 :                     break;
    2334                 :             : 
    2335                 :           0 :                 default:
    2336                 :           0 :                     ret = RI_ERR_PROGR; /* unexpected group type */
    2337                 :           0 :                     goto exit_function;
    2338                 :             :             }
    2339                 :             : 
    2340   [ #  #  #  #  :           0 :             if (pTCGroups->nGroup[k] >= 0 || (pTCGroups->pTCG[i].ord_num && !IS_BNS_VT_M_GR( pTCGroups->pTCG[i].type ))) /* djb-rwth: addressing LLVM warning */
                   #  # ]
    2341                 :             :             {
    2342                 :           0 :                 ret = RI_ERR_PROGR;
    2343                 :           0 :                 goto exit_function;
    2344                 :             :             }
    2345                 :           0 :             pTCGroups->nGroup[k] = i; /* ordering number of the Charge group, starting from 0 */
    2346                 :             :         }
    2347                 :             :     }
    2348                 :             : 
    2349                 :             :     /* add (+) supergroup */
    2350                 :           0 :     n1 = pTCGroups->nGroup[TCG_Plus0];
    2351                 :           0 :     n2 = pTCGroups->nGroup[TCG_Plus_C0];
    2352                 :           0 :     n3 = pTCGroups->nGroup[TCG_Plus_M0];
    2353                 :           0 :     nNumToConnect = ( n1 >= 0 ) + ( n2 >= 0 ) + ( n3 >= 0 );
    2354                 :             : 
    2355         [ #  # ]:           0 :     if (nNumToConnect)
    2356                 :             :     {
    2357                 :             :         /* if both groups are present then add a supergroup */
    2358                 :           0 :         ret = RegisterTCGroup( pTCGroups,
    2359                 :             :                                BNS_VT_C_POS_ALL,
    2360                 :             :                                0,
    2361                 :             :                                0 /* st_cap */,
    2362                 :             :                                0 /* st_flow */,
    2363                 :             :                                0 /* edge cap */,
    2364                 :             :                                0 /* edge flow */,
    2365                 :             :                                1 + nNumToConnect
    2366                 :             :                                 /* one more edge to connect to */
    2367                 :             :         /* an additional (+/-) vertex */ );
    2368                 :             : 
    2369         [ #  # ]:           0 :         if (ret <= 0)
    2370                 :             :         {
    2371         [ #  # ]:           0 :             ret = !ret ? RI_ERR_PROGR : ret;
    2372                 :           0 :             goto exit_function;
    2373                 :             :         }
    2374                 :             : 
    2375                 :           0 :         pTCGroups->nGroup[TCG_Plus] = ret - 1; /* newly added group number */
    2376                 :           0 :         pTCGroups->nVertices += 2; /* two vertices including itself */
    2377                 :           0 :         pTCGroups->nEdges += 1 + nNumToConnect; /* one more edge to connect to an additional (+/-) vertex */
    2378                 :             :     }
    2379                 :             : 
    2380                 :             :     /* add (-) supergroup */
    2381                 :           0 :     n1 = pTCGroups->nGroup[TCG_Minus0];
    2382                 :           0 :     n2 = pTCGroups->nGroup[TCG_Minus_C0];
    2383                 :           0 :     n3 = pTCGroups->nGroup[TCG_Minus_M0];
    2384                 :           0 :     nNumToConnect = ( n1 >= 0 ) + ( n2 >= 0 ) + ( n3 >= 0 );
    2385         [ #  # ]:           0 :     if (nNumToConnect)
    2386                 :             :     {
    2387                 :             :         /* if both groups are present then add a supergroup */
    2388                 :             : 
    2389                 :           0 :         ret = RegisterTCGroup( pTCGroups,
    2390                 :             :                                BNS_VT_C_NEG_ALL,
    2391                 :             :                                0,
    2392                 :             :                                0 /* st_cap */,
    2393                 :             :                                0 /* st_flow */,
    2394                 :             :                                0 /* edge cap */,
    2395                 :             :                                0 /* edge flow */,
    2396                 :             :                                1 + nNumToConnect /* one more edge to connect to an additional (+/-) vertex */ );
    2397                 :             : 
    2398         [ #  # ]:           0 :         if (ret < 0)
    2399                 :             :         {
    2400                 :           0 :             goto exit_function;
    2401                 :             :         }
    2402                 :           0 :         pTCGroups->nGroup[TCG_Minus] = ret - 1; /* newly added group number */
    2403                 :           0 :         pTCGroups->nVertices += 2; /* needs two vertices including itself */
    2404                 :           0 :         pTCGroups->nEdges += 1 + nNumToConnect; /* one more edge to connect to an additional (+/-) vertex */
    2405                 :             :     }
    2406                 :             : 
    2407                 :             :     /* add neutralization vertex: (+)-()=(-) connection */
    2408                 :           0 :     k = pTCGroups->nGroup[TCG_Minus];
    2409                 :           0 :     n = pTCGroups->nGroup[TCG_Plus];
    2410                 :           0 :     nNumToConnect = ( k >= 0 ) + ( n >= 0 );
    2411         [ #  # ]:           0 :     if (nNumToConnect)
    2412                 :             :     {
    2413                 :           0 :         pTCGroups->nVertices += 1;
    2414                 :           0 :         pTCGroups->nEdges += nNumToConnect; /* one edge per super-c-group */
    2415                 :             :     }
    2416                 :             : 
    2417                 :           0 :     ret = 0;
    2418                 :             : 
    2419                 :           0 : exit_function:
    2420                 :           0 :     return ret;
    2421                 :             : }
    2422                 :             : 
    2423                 :             : 
    2424                 :             : /*********************************************************************************/
    2425                 :           0 : int AddTGroups2TCGBnStruct( BN_STRUCT *pBNS,
    2426                 :             :                             StrFromINChI *pStruct,
    2427                 :             :                             VAL_AT *pVA,
    2428                 :             :                             ALL_TC_GROUPS *pTCGroups,
    2429                 :             :                             int nMaxAddEdges )
    2430                 :             : {
    2431                 :           0 :     int ret = 0;
    2432                 :           0 :     inp_ATOM *at = pStruct->at;
    2433                 :           0 :     int       num_atoms = pStruct->num_atoms;
    2434                 :             :     int tot_st_cap, tot_st_flow;
    2435                 :             :     /* ret = ReInitBnStruct( pBNS ); */
    2436                 :             : 
    2437         [ #  # ]:           0 :     if (pTCGroups->num_tgroups /* tgi && tgi->num_t_groups && tgi->t_group*/)
    2438                 :             :     {
    2439                 :             :         int         i, k, endpoint, /*centerpoint,*/ fictpoint;
    2440                 :           0 :         int         num_tg = pTCGroups->num_tgroups;
    2441                 :           0 :         int         num_edges = pBNS->num_edges;
    2442                 :           0 :         int         num_vertices = pBNS->num_vertices;
    2443                 :             :         BNS_VERTEX *vert_ficpoint, *vert_ficpoint_prev;  /* fictitious vertex describing t-group */
    2444                 :             :         BNS_VERTEX *vert_endpoint;
    2445                 :             :         BNS_EDGE   *edge;      /* edge between that vertex and the tautomeric endpoint */
    2446                 :           0 :         int        nMaxTGroupNumber = 0;
    2447                 :             :         /*ENDPOINT_INFO eif;*/
    2448                 :             : 
    2449                 :             :         /* Debug: check overflow */
    2450         [ #  # ]:           0 :         if (num_vertices + num_tg >= pBNS->max_vertices)
    2451                 :             :         {
    2452                 :           0 :             return BNS_VERT_EDGE_OVFL;
    2453                 :             :         }
    2454         [ #  # ]:           0 :         if (num_edges + pTCGroups->num_tgroup_edges >= pBNS->max_edges)
    2455                 :             :         {
    2456                 :           0 :             return BNS_VERT_EDGE_OVFL;
    2457                 :             :         }
    2458                 :             : 
    2459                 :             :         /* find the largest t-group ID */
    2460         [ #  # ]:           0 :         for (i = 0; i < pTCGroups->num_tc_groups; i++)
    2461                 :             :         {
    2462         [ #  # ]:           0 :             if (pTCGroups->pTCG[i].type & BNS_VERT_TYPE_TGROUP)
    2463                 :             :             {
    2464                 :           0 :                 k = pTCGroups->pTCG[i].ord_num;
    2465         [ #  # ]:           0 :                 if (k <= 0)
    2466                 :             :                 {
    2467                 :           0 :                     return BNS_CPOINT_ERR; /* t-group does not have a number or has a wrong number */
    2468                 :             :                 }
    2469         [ #  # ]:           0 :                 if (k > pTCGroups->num_tc_groups)
    2470                 :             :                 {
    2471                 :           0 :                     return BNS_CPOINT_ERR; /* t-group has a wrong number */
    2472                 :             :                 }
    2473         [ #  # ]:           0 :                 if (k != nMaxTGroupNumber + 1)
    2474                 :             :                 {
    2475                 :           0 :                     return BNS_CPOINT_ERR; /* t-group numbers are not contiguously ascending */
    2476                 :             :                 }
    2477                 :           0 :                 nMaxTGroupNumber = k;
    2478                 :             :             }
    2479                 :             :             else
    2480                 :             :             {
    2481                 :           0 :                 break; /* t-groups are contiguous and first in the list */
    2482                 :             :             }
    2483                 :             :         }
    2484                 :             : 
    2485         [ #  # ]:           0 :         if (i != num_tg)
    2486                 :             :         {
    2487                 :           0 :             return BNS_CPOINT_ERR; /* number of t-groups is wrong */
    2488                 :             :         }
    2489                 :             : 
    2490                 :             :         /* since t-group IDs may be not contiguous, clear all vertices that will be added.
    2491                 :             :            all-zeroes-vertex will be ignored by the BNS
    2492                 :             :         */
    2493                 :           0 :         memset( pBNS->vert + num_vertices, 0, nMaxTGroupNumber * sizeof( pBNS->vert[0] ) ); /* djb-rwth: memset_s C11/Annex K variant? */
    2494                 :             : 
    2495                 :             :         /* initialize new fictitious vertices */
    2496                 :           0 :         vert_ficpoint_prev = pBNS->vert + num_vertices - 1;
    2497                 :             : 
    2498                 :           0 :         tot_st_cap = tot_st_flow = 0;
    2499                 :             : 
    2500         [ #  # ]:           0 :         for (i = 0; i < num_tg; i++, vert_ficpoint_prev = vert_ficpoint)
    2501                 :             :         {
    2502                 :             :             /*
    2503                 :             :               vert_ficpoint-1 is the last vertex;
    2504                 :             :               vert_ficpoint   is the vertex that is being added
    2505                 :             :               Note: nGroupNumber are not contiguous
    2506                 :             :             */
    2507                 :           0 :             vert_ficpoint = pBNS->vert + num_vertices + pTCGroups->pTCG[i].ord_num - 1;
    2508                 :           0 :             vert_ficpoint->iedge = vert_ficpoint_prev->iedge + vert_ficpoint_prev->max_adj_edges;
    2509                 :           0 :             vert_ficpoint->max_adj_edges = pTCGroups->pTCG[i].num_edges + nMaxAddEdges + BNS_ADD_SUPER_TGROUP;
    2510                 :           0 :             vert_ficpoint->num_adj_edges = 0;
    2511                 :           0 :             vert_ficpoint->st_edge.flow = vert_ficpoint->st_edge.flow0 = 0;
    2512                 :           0 :             vert_ficpoint->st_edge.cap = vert_ficpoint->st_edge.cap0 = pTCGroups->pTCG[i].st_cap;
    2513                 :           0 :             tot_st_cap += pTCGroups->pTCG[i].st_cap;
    2514                 :           0 :             vert_ficpoint->type = pTCGroups->pTCG[i].type;
    2515                 :           0 :             pTCGroups->pTCG[i].nVertexNumber = (int) ( vert_ficpoint - pBNS->vert );
    2516                 :             :         }
    2517                 :             : 
    2518         [ #  # ]:           0 :         for (endpoint = 0; endpoint < num_atoms; endpoint++)
    2519                 :             :         {
    2520         [ #  # ]:           0 :             if (!at[endpoint].endpoint)
    2521                 :           0 :                 continue;
    2522                 :           0 :             fictpoint = at[endpoint].endpoint + num_vertices - 1;
    2523                 :           0 :             vert_ficpoint = pBNS->vert + fictpoint;  /* t-group vertex */
    2524                 :           0 :             vert_endpoint = pBNS->vert + endpoint;   /* endpoint vertex */
    2525                 :             :             /* Debug: check overflow */
    2526         [ #  # ]:           0 :             if (fictpoint >= pBNS->max_vertices ||
    2527         [ #  # ]:           0 :                  num_edges >= pBNS->max_edges ||
    2528         [ #  # ]:           0 :                  vert_ficpoint->num_adj_edges >= vert_ficpoint->max_adj_edges ||
    2529         [ #  # ]:           0 :                  vert_endpoint->num_adj_edges >= vert_endpoint->max_adj_edges)
    2530                 :             :             {
    2531                 :           0 :                 ret = BNS_VERT_EDGE_OVFL;
    2532                 :           0 :                 break;
    2533                 :             :             }
    2534                 :             : 
    2535                 :             : #ifdef NEVER
    2536                 :             :             /* obtain donor/acceptor info */
    2537                 :             :             if (!nGetEndpointInfo( at, endpoint, &eif ))
    2538                 :             :             {
    2539                 :             :                 ret = BNS_BOND_ERR;
    2540                 :             :                 break;
    2541                 :             :             }
    2542                 :             : #endif
    2543                 :             : 
    2544                 :           0 :             vert_endpoint->type |= BNS_VERT_TYPE_ENDPOINT;
    2545                 :             : 
    2546                 :             : #ifdef NEVER
    2547                 :             :             /* set capacity = 1 to the edges from the endpoint to the centerpoint(s) */
    2548                 :             :             for (k = 0; k < vert_endpoint->num_adj_edges; k++)
    2549                 :             :             {
    2550                 :             :                 int iedge = vert_endpoint->iedge[k];
    2551                 :             :                 if (!pBNS->edge[iedge].cap)
    2552                 :             :                 {
    2553                 :             : /* single bond, possibly between endpoint and centerpoint */
    2554                 :             :                     centerpoint = ( pBNS->edge[iedge].neighbor12 ^ endpoint );
    2555                 :             :                     if (centerpoint < pBNS->num_atoms &&
    2556                 :             :                          pBNS->vert[centerpoint].st_edge.cap >= 1)
    2557                 :             :                     {
    2558                 :             :                         int bond_type = ( at[endpoint].bond_type[k] & BOND_TYPE_MASK );
    2559                 :             :                         if (bond_type == BOND_TAUTOM ||
    2560                 :             :                             bond_type == BOND_ALTERN ||
    2561                 :             :                             bond_type == BOND_ALT12NS ||
    2562                 :             :                             bond_type == BOND_SINGLE)
    2563                 :             :                         {
    2564                 :             :                             pBNS->edge[iedge].cap = 1;
    2565                 :             :                         }
    2566                 :             :                     }
    2567                 :             :                 }
    2568                 :             :             }
    2569                 :             : #endif
    2570                 :             : 
    2571                 :             :             /* create a new edge connecting endpoint to the new fictitious t-group vertex vert_ficpoint */
    2572                 :           0 :             edge = pBNS->edge + num_edges;
    2573                 :           0 :             edge->cap = vert_endpoint->st_edge.cap - vert_endpoint->st_edge.flow;
    2574                 :           0 :             edge->cap = inchi_min( edge->cap, MAX_TGROUP_EDGE_CAP );
    2575                 :           0 :             edge->cap = inchi_max( edge->cap, 0 );
    2576                 :           0 :             edge->flow = 0;
    2577                 :           0 :             edge->pass = 0;
    2578                 :             : 
    2579                 :             : #if ( RESET_EDGE_FORBIDDEN_MASK == 1 )
    2580                 :             :             edge->forbidden &= pBNS->edge_forbidden_mask;
    2581                 :             : #endif
    2582                 :             : 
    2583                 :             : #ifdef NEVER
    2584                 :             :             /* later include case when the charge change allows the endpoint to become tautomeric */
    2585                 :             :             /* mark endoint having moveable H atom with flow=1 */
    2586                 :             : 
    2587                 :             :             /* -- old "no charges" version -- */
    2588                 :             :             /* if (at[endpoint].chem_bonds_valence == at[endpoint].valence) */
    2589                 :             :             /* -- the following line takes charges into account -- */
    2590                 :             :             if (eif.cDonor) /* means the endpoint has an H-atom to donate */
    2591                 :             :             {
    2592                 :             :                 /* increment edge flow */
    2593                 :             :                 edge->flow++;
    2594                 :             :                 /* increment one vertex st-flow & cap */
    2595                 :             :                 vert_ficpoint->st_edge.flow++;
    2596                 :             :                 vert_ficpoint->st_edge.cap++;
    2597                 :             :                 /* increment another vertex st-flow & cap */
    2598                 :             :                 vert_endpoint->st_edge.flow++;
    2599                 :             :                 vert_endpoint->st_edge.cap++;
    2600                 :             :             }
    2601                 :             : #endif
    2602                 :             : 
    2603                 :             :             /* connect edge to endpoint and fictpoint and increment the counters of neighbors and edges */
    2604                 :           0 :             ret = ConnectTwoVertices( vert_endpoint, vert_ficpoint, edge, pBNS, 0 );
    2605   [ #  #  #  # ]:           0 :             if (IS_BNS_ERROR( ret ))
    2606                 :             :             {
    2607                 :           0 :                 break;
    2608                 :             :             }
    2609                 :           0 :             num_edges++;
    2610                 :           0 :             edge->cap0 = edge->cap;
    2611                 :           0 :             edge->flow0 = edge->flow;
    2612                 :           0 :             pVA[endpoint].nTautGroupEdge = num_edges; /* edge index + 1 */
    2613                 :             :         }
    2614                 :             : 
    2615                 :           0 :         pBNS->num_edges = num_edges;
    2616                 :           0 :         pBNS->num_vertices += nMaxTGroupNumber;
    2617                 :           0 :         pBNS->num_t_groups = num_tg;
    2618                 :           0 :         pBNS->tot_st_cap += tot_st_cap;
    2619                 :           0 :         pBNS->tot_st_flow += tot_st_flow;
    2620                 :             :     }
    2621                 :             : 
    2622                 :           0 :     return ret;
    2623                 :             : }
    2624                 :             : 
    2625                 :             : 
    2626                 :             : /*****************************************************************************************************/
    2627                 :           0 : int ConnectTwoVertices( BNS_VERTEX *p1, BNS_VERTEX *p2, BNS_EDGE *e, BN_STRUCT *pBNS, int bClearEdge )
    2628                 :             : {
    2629                 :           0 :     int ip1 = (int) ( p1 - pBNS->vert );
    2630                 :           0 :     int ip2 = (int) ( p2 - pBNS->vert );
    2631                 :           0 :     int ie = (int) ( e - pBNS->edge );
    2632                 :             : 
    2633                 :             :     /* debug: check bounds */
    2634   [ #  #  #  # ]:           0 :     if (ip1 >= pBNS->max_vertices || ip1 < 0 ||
    2635   [ #  #  #  # ]:           0 :          ip2 >= pBNS->max_vertices || ip2 < 0 ||
    2636   [ #  #  #  # ]:           0 :          ie >= pBNS->max_edges || ie < 0 ||
    2637         [ #  # ]:           0 :          ( p1->iedge - pBNS->iedge ) < 0 ||
    2638         [ #  # ]:           0 :          ( p1->iedge - pBNS->iedge ) + p1->max_adj_edges > pBNS->max_iedges ||
    2639         [ #  # ]:           0 :          ( p2->iedge - pBNS->iedge ) < 0 ||
    2640         [ #  # ]:           0 :          ( p2->iedge - pBNS->iedge ) + p2->max_adj_edges > pBNS->max_iedges ||
    2641         [ #  # ]:           0 :          p1->num_adj_edges >= p1->max_adj_edges ||
    2642         [ #  # ]:           0 :          p2->num_adj_edges >= p2->max_adj_edges)
    2643                 :             :     {
    2644                 :           0 :         return BNS_VERT_EDGE_OVFL;
    2645                 :             :     }
    2646                 :             :     /* clear the edge */
    2647         [ #  # ]:           0 :     if (bClearEdge)
    2648                 :             :     {
    2649                 :           0 :         memset( e, 0, sizeof( *e ) ); /* djb-rwth: memset_s C11/Annex K variant? */
    2650                 :             :     }
    2651                 :             :     else
    2652   [ #  #  #  # ]:           0 :         if (e->neighbor1 || e->neighbor12)
    2653                 :             :         {
    2654                 :           0 :             return BNS_PROGRAM_ERR;
    2655                 :             :         }
    2656                 :             : 
    2657                 :             :         /* connect */
    2658                 :           0 :     e->neighbor1 = inchi_min( ip1, ip2 );
    2659                 :           0 :     e->neighbor12 = ip1 ^ ip2;
    2660                 :           0 :     p1->iedge[p1->num_adj_edges] = ie;
    2661                 :           0 :     p2->iedge[p2->num_adj_edges] = ie;
    2662                 :           0 :     e->neigh_ord[ip1 > ip2] = p1->num_adj_edges++;
    2663                 :             : 
    2664                 :           0 :     e->neigh_ord[ip1 < ip2] = p2->num_adj_edges++;
    2665                 :           0 :     return 0;
    2666                 :             : }
    2667                 :             : 
    2668                 :             : 
    2669                 :             : /***********************************************************************************************************
    2670                 :             :                      METAL ATOMS' FLOWER - Provides a source/sink of "free valences"
    2671                 :             :  ***********************************************************************************************************
    2672                 :             : 
    2673                 :             :                     c1+...+cn = 2c+dc  - total cap and flow of edges to the flower base from metal atoms
    2674                 :             :                     f1+...+fn = 2f+df    they should allow changing bonds to metals from 0-order to triple
    2675                 :             :                     dc,df = 0 or 1       hence c=3*n, f=0 (initial zero bond order) or n
    2676                 :             :  Gi=vertex(M-group)
    2677                 :             :  Ci=its st_cap                  [C3,F3]  C0 = F0 = 2c + 2D + dc    (st_cap & st_flow)
    2678                 :             :  Fi=its st_flow               G3         C2 = F2 =  c + 2D
    2679                 :             :                               / \        C1 = F1 =  c + 2D + dc-df
    2680                 :             :  ci=cap of edge i       cx,fx/   \cy,fy  C3 = F3 =  0
    2681                 :             :  fi=edge flow               /     \                                             Constraints
    2682                 :             :                     [C2,F2]/ cd,fd \[C1,F1]                                     -----------------
    2683                 :             :                          G2--------G1                                           fa+fb+2f+df=F0=C0
    2684                 :             :                           \        /          ca =  c + 2D         (edge cap)   fa+fd      =F2=C2
    2685                 :             :                       ca,fa \    / cb,fb      fa =  c +  D - f     (edge flow)  fb+fd      =C1=F1
    2686                 :             :                              \  /                                               fi <= ci
    2687                 :             :                               G0 [C0,F0]      cb =  c + 2D + dc                 -----------------
    2688                 :             :                               /\              fb =  c +  D + dc - (f + df)
    2689                 :             :    ci=3, fi=0 or 1   c1,f1  /... \ cn,fn                            ------------------------------------
    2690                 :             :                           /       \           cd =  c + 2D          D is an arbitrary integer > 0
    2691                 :             :    all n Metal atoms:    M1 ...    Mn         fd =  f +  D          it allows to apply
    2692                 :             :                                                                     C3++ (add st_flow to cancel radicals)
    2693                 :             :   For each Mi add cap and flow=cap            cx = cy = D           D times.
    2694                 :             :   to M-charge group                           fx = fy = 0
    2695                 :             :        --------------------------------------------------------------------------------------
    2696                 :             :                  |  f=0                   |  f=c, dc>=df         |  0 <= 2f+df <= 2c+dc
    2697                 :             :          edge    +------------------------+-----------+----------+-------------+-------------
    2698                 :             :                  |  flow      |  rescap   |  flow     |  rescap  |  flow       |  rescap
    2699                 :             :        ----------+------------+-----------+-----------+----------+-------------+-------------
    2700                 :             :         f1+..+fn |  df        |  2c+dc-df |  2c+df    |  dc-df   |  2f+df      |  2c-2f+dc-df
    2701                 :             :               fa |  c+D       |  D        |  D        |  c+D     |  c+D-f      |  c+D
    2702                 :             :               fb |  c+D+dc-df |  D+df     |  D+dc-df  |  c+D+df  |  c+D+dc-f-df|  c+D+df
    2703                 :             :               fd |  D         |  c+D      |  c+D      |  D       |  f+D        |  D
    2704                 :             :        --------------------------------------------------------------------------------------
    2705                 :             : ***********************************************************************************************************/
    2706                 :           0 : int AddRadicalToMetal(int* tot_st_cap, int* tot_st_flow, ICHICONST SRM* pSrm, BN_STRUCT* pBNS, ALL_TC_GROUPS* pTCGroups)
    2707                 :             : {
    2708                 :           0 :     int iG0 = pTCGroups->nGroup[TCG_MeFlower0]; /* index in pTCGroups->pTCG[] */
    2709                 :           0 :     int iG1 = pTCGroups->nGroup[TCG_MeFlower1];
    2710                 :           0 :     int iG2 = pTCGroups->nGroup[TCG_MeFlower2];
    2711                 :           0 :     int iG3 = pTCGroups->nGroup[TCG_MeFlower3];
    2712                 :           0 :     int n = (iG0 >= 0) + (iG1 >= 0) + (iG2 >= 0) + (iG3 >= 0);
    2713                 :             :     int vG0, vG1, vG2, vG3;  /* M-vertex number */
    2714                 :           0 :     BNS_VERTEX* pG0 = NULL, * pG1 = NULL, * pG2 = NULL, * pG3 = NULL;
    2715                 :             : 
    2716         [ #  # ]:           0 :     if (pTCGroups->num_metal_atoms &&
    2717         [ #  # ]:           0 :         pSrm->bMetalAddFlower &&
    2718   [ #  #  #  # ]:           0 :         *tot_st_cap % 2 &&
    2719                 :             :         n == 4)
    2720                 :             :     {
    2721                 :           0 :         vG0 = pTCGroups->pTCG[iG0].nVertexNumber;
    2722                 :           0 :         vG1 = pTCGroups->pTCG[iG1].nVertexNumber;
    2723                 :           0 :         vG2 = pTCGroups->pTCG[iG2].nVertexNumber;
    2724                 :           0 :         vG3 = pTCGroups->pTCG[iG3].nVertexNumber;
    2725                 :             : 
    2726                 :           0 :         pG0 = pBNS->vert + vG0;
    2727                 :           0 :         pG1 = pBNS->vert + vG1;
    2728                 :           0 :         pG2 = pBNS->vert + vG2;
    2729                 :           0 :         pG3 = pBNS->vert + vG3;
    2730                 :             : 
    2731                 :             :         /* add 1 unit to metal flower st_cap */
    2732                 :           0 :         pG3->st_edge.cap++;
    2733                 :           0 :         pG3->st_edge.cap0++;
    2734                 :           0 :         (*tot_st_cap)++;
    2735                 :           0 :         return 1;
    2736                 :             :     }
    2737                 :             : 
    2738                 :           0 :     return 0;
    2739                 :             : }
    2740                 :             : 
    2741                 :             : 
    2742                 :             : /***********************************************************************************************************/
    2743                 :           0 : int ConnectMetalFlower( int *pcur_num_vertices, int *pcur_num_edges,
    2744                 :             :                         int *tot_st_cap, int *tot_st_flow, ICHICONST SRM *pSrm,
    2745                 :             :                         BN_STRUCT *pBNS, ALL_TC_GROUPS *pTCGroups )
    2746                 :             : {
    2747                 :           0 :     int iG0 = pTCGroups->nGroup[TCG_MeFlower0]; /* index in pTCGroups->pTCG[] */
    2748                 :           0 :     int iG1 = pTCGroups->nGroup[TCG_MeFlower1];
    2749                 :           0 :     int iG2 = pTCGroups->nGroup[TCG_MeFlower2];
    2750                 :           0 :     int iG3 = pTCGroups->nGroup[TCG_MeFlower3];
    2751                 :           0 :     int n = ( iG0 >= 0 ) + ( iG1 >= 0 ) + ( iG2 >= 0 ) + ( iG3 >= 0 );
    2752                 :             :     int vG0, vG1, vG2, vG3;  /* M-vertex number */
    2753                 :           0 :     int cur_num_edges = *pcur_num_edges;
    2754                 :           0 :     int cur_num_vertices = *pcur_num_vertices;
    2755                 :           0 :     BNS_VERTEX *pG0 = NULL, *pG1 = NULL, *pG2 = NULL, *pG3 = NULL;
    2756                 :           0 :     BNS_EDGE   *ea = NULL, *eb = NULL, *ed = NULL, *ex = NULL, *ey = NULL, *e;
    2757                 :             :     int         ia, ib, id, ix, iy;
    2758                 :             :     int         c, f, dc, df, ca, fa, cb, fb, cd, fd, cx, fx, cy, fy;
    2759                 :             :     int         C0, F0, C1, F1, C2, F2, C3, F3, D;
    2760                 :           0 :     int         ret = 0, i;
    2761                 :             : 
    2762         [ #  # ]:           0 :     if (0 == n)
    2763                 :             :     {
    2764                 :           0 :         goto exit_function;
    2765                 :             :     }
    2766                 :             : 
    2767         [ #  # ]:           0 :     if (4 != n)
    2768                 :             :     {
    2769                 :           0 :         ret = RI_ERR_PROGR;
    2770                 :           0 :         goto exit_function;
    2771                 :             :     }
    2772                 :             : 
    2773                 :           0 :     vG0 = pTCGroups->pTCG[iG0].nVertexNumber;
    2774                 :           0 :     vG1 = pTCGroups->pTCG[iG1].nVertexNumber;
    2775                 :           0 :     vG2 = pTCGroups->pTCG[iG2].nVertexNumber;
    2776                 :           0 :     vG3 = pTCGroups->pTCG[iG3].nVertexNumber;
    2777                 :             : 
    2778                 :           0 :     pG0 = pBNS->vert + vG0;
    2779                 :           0 :     pG1 = pBNS->vert + vG1;
    2780                 :           0 :     pG2 = pBNS->vert + vG2;
    2781                 :           0 :     pG3 = pBNS->vert + vG3;
    2782                 :             : 
    2783                 :             :     /* count G0 edges cap and flow (currently only atoms are connected to G0) */
    2784         [ #  # ]:           0 :     for (i = 0, c = 0, f = 0; i < pG0->num_adj_edges; i++)
    2785                 :             :     {
    2786                 :           0 :         e = pBNS->edge + pG0->iedge[i];
    2787                 :           0 :         c += e->cap;
    2788                 :           0 :         f += e->flow;
    2789                 :             :     }
    2790                 :             : 
    2791                 :             :     /* consistency checks */
    2792         [ #  # ]:           0 :     if (!IS_BNS_VT_M_GR( pTCGroups->pTCG[iG0].type ) &&
    2793         [ #  # ]:           0 :         ( pTCGroups->pTCG[iG0].edges_cap != pG0->st_edge.cap ||
    2794         [ #  # ]:           0 :             pTCGroups->pTCG[iG0].edges_flow != pG0->st_edge.flow ))
    2795                 :             :     {
    2796                 :           0 :         ret = RI_ERR_PROGR;
    2797                 :           0 :         goto exit_function;
    2798                 :             :     }
    2799                 :             : 
    2800         [ #  # ]:           0 :     if (pTCGroups->pTCG[iG0].edges_cap != c ||
    2801         [ #  # ]:           0 :          pTCGroups->pTCG[iG0].edges_flow != f)
    2802                 :             :     {
    2803                 :           0 :         ret = RI_ERR_PROGR;
    2804                 :           0 :         goto exit_function;
    2805                 :             :     }
    2806                 :             : 
    2807                 :             :     /* get new edges */
    2808                 :             : 
    2809                 :           0 :     ea = pBNS->edge + (ia = cur_num_edges++);
    2810                 :           0 :     eb = pBNS->edge + (ib = cur_num_edges++);
    2811                 :           0 :     ed = pBNS->edge + (id = cur_num_edges++);
    2812                 :           0 :     ex = pBNS->edge + (ix = cur_num_edges++);
    2813                 :           0 :     ey = pBNS->edge + (iy = cur_num_edges++);
    2814                 :             : 
    2815                 :             :     /* connect vertices with edges */
    2816                 :           0 :     ret = ConnectTwoVertices( pG0, pG1, eb, pBNS, 1 );
    2817   [ #  #  #  # ]:           0 :     if (IS_BNS_ERROR( ret ))
    2818                 :             :     {
    2819                 :           0 :         goto exit_function;
    2820                 :             :     }
    2821                 :             : 
    2822                 :           0 :     ret = ConnectTwoVertices( pG0, pG2, ea, pBNS, 1 );
    2823                 :             : 
    2824   [ #  #  #  # ]:           0 :     if (IS_BNS_ERROR( ret ))
    2825                 :             :     {
    2826                 :           0 :         goto exit_function;
    2827                 :             :     }
    2828                 :             : 
    2829                 :           0 :     ret = ConnectTwoVertices( pG1, pG2, ed, pBNS, 1 );
    2830                 :             : 
    2831   [ #  #  #  # ]:           0 :     if (IS_BNS_ERROR( ret ))
    2832                 :             :     {
    2833                 :           0 :         goto exit_function;
    2834                 :             :     }
    2835                 :             : 
    2836                 :           0 :     ret = ConnectTwoVertices( pG1, pG3, ey, pBNS, 1 );
    2837                 :             : 
    2838   [ #  #  #  # ]:           0 :     if (IS_BNS_ERROR( ret ))
    2839                 :             :     {
    2840                 :           0 :         goto exit_function;
    2841                 :             :     }
    2842                 :             : 
    2843                 :           0 :     ret = ConnectTwoVertices( pG2, pG3, ex, pBNS, 1 );
    2844                 :             : 
    2845   [ #  #  #  # ]:           0 :     if (IS_BNS_ERROR( ret ))
    2846                 :             :     {
    2847                 :           0 :         goto exit_function;
    2848                 :             :     }
    2849                 :             : 
    2850                 :             :     /* calculate caps and flows */
    2851                 :             : 
    2852                 :           0 :     dc = c % 2;
    2853                 :           0 :     c /= 2;
    2854                 :           0 :     df = f % 2;
    2855                 :           0 :     f /= 2;
    2856                 :             : 
    2857                 :           0 :     D = pSrm->nMetalFlowerParam_D;
    2858                 :             : 
    2859                 :           0 :     C0 = F0 = 2 * c + 2 * D + dc;
    2860                 :           0 :     C1 = F1 = c + 2 * D + dc - df;
    2861                 :           0 :     C2 = F2 = c + 2 * D;
    2862                 :           0 :     C3 = F3 = 0;
    2863                 :             : 
    2864                 :           0 :     ca = c + 2 * D;
    2865                 :           0 :     fa = c + D - f;
    2866                 :             : 
    2867                 :           0 :     cb = c + 2 * D + dc;
    2868                 :           0 :     fb = c + D + dc - ( f + df );
    2869                 :             : 
    2870                 :           0 :     cd = c + 2 * D;
    2871                 :           0 :     fd = f + D;
    2872                 :             : 
    2873                 :           0 :     cx = cy = D;
    2874                 :           0 :     fx = fy = 0;
    2875                 :             : 
    2876                 :             :     /* check overflow */
    2877   [ #  #  #  #  :           0 :     if (C0 >= EDGE_FLOW_ST_MASK || F0 >= EDGE_FLOW_ST_MASK ||
                   #  # ]
    2878   [ #  #  #  # ]:           0 :          C1 >= EDGE_FLOW_ST_MASK || F1 >= EDGE_FLOW_ST_MASK ||
    2879   [ #  #  #  # ]:           0 :          C2 >= EDGE_FLOW_ST_MASK || F2 >= EDGE_FLOW_ST_MASK ||
    2880         [ #  # ]:           0 :          C3 >= EDGE_FLOW_ST_MASK || F3 >= EDGE_FLOW_ST_MASK)
    2881                 :             :     {
    2882                 :           0 :         return BNS_PROGRAM_ERR; /* cannot handle too large st-cap or st-flow */
    2883                 :             :     }
    2884                 :             : 
    2885                 :             :     /* set st caps and flows */
    2886                 :             : 
    2887                 :           0 :     SetStCapFlow( pG0, tot_st_flow, tot_st_cap, C0, F0 );
    2888                 :           0 :     SetStCapFlow( pG1, tot_st_flow, tot_st_cap, C1, F1 );
    2889                 :           0 :     SetStCapFlow( pG2, tot_st_flow, tot_st_cap, C2, F2 );
    2890                 :           0 :     SetStCapFlow( pG3, tot_st_flow, tot_st_cap, C3, F3 );
    2891                 :             : 
    2892                 :           0 :     SetEdgeCapFlow( ea, ca, fa );
    2893                 :           0 :     SetEdgeCapFlow( eb, cb, fb );
    2894                 :           0 :     SetEdgeCapFlow( ed, cd, fd );
    2895                 :           0 :     SetEdgeCapFlow( ex, cx, fx );
    2896                 :           0 :     SetEdgeCapFlow( ey, cy, fy );
    2897                 :             : 
    2898                 :             : 
    2899                 :           0 :     *pcur_num_edges = cur_num_edges;
    2900                 :           0 :     *pcur_num_vertices = cur_num_vertices;
    2901                 :             : 
    2902                 :           0 :     ret = 0;
    2903                 :             : 
    2904                 :           0 : exit_function:
    2905                 :             : 
    2906                 :           0 :     return ret;
    2907                 :             : }
    2908                 :             : 
    2909                 :             : 
    2910                 :             : /********************************************************************************/
    2911                 :           0 : void SetEdgeCapFlow( BNS_EDGE *e, int edge_cap, int edge_flow )
    2912                 :             : {
    2913                 :           0 :     e->cap = e->cap0 = edge_cap;
    2914                 :           0 :     e->flow = e->flow0 = edge_flow;
    2915                 :           0 : }
    2916                 :             : 
    2917                 :             : 
    2918                 :             : /*********************************************************************************
    2919                 :             :   Add cap and flow to an edge
    2920                 :             :   Add edge flow to the source vertex st_flow
    2921                 :             :   Add edge cap & flow to the destination vertex cap and flow
    2922                 :             :  *********************************************************************************/
    2923                 :           0 : int AddEdgeFlow( int edge_cap, int edge_flow, BNS_EDGE *e01, BNS_VERTEX *pSrc /*src*/,
    2924                 :             :                   BNS_VERTEX *pDst/*dest*/, int *tot_st_cap, int *tot_st_flow )
    2925                 :             : {
    2926                 :             : 
    2927                 :             :     /* overflow check */
    2928   [ #  #  #  #  :           0 :     if (e01->cap < 0 || edge_cap < 0 || (int) e01->cap + edge_cap >= EDGE_FLOW_MASK)
                   #  # ]
    2929                 :             :     {
    2930                 :           0 :         return BNS_PROGRAM_ERR;
    2931                 :             :     }
    2932                 :             : 
    2933   [ #  #  #  # ]:           0 :     if (pDst->st_edge.cap < 0 || (int) pDst->st_edge.cap + edge_cap >= EDGE_FLOW_ST_MASK ||
    2934   [ #  #  #  # ]:           0 :          pDst->st_edge.flow < 0 || (int) pDst->st_edge.flow + edge_flow >= EDGE_FLOW_ST_MASK ||
    2935   [ #  #  #  # ]:           0 :          pSrc->st_edge.cap < 0 || pSrc->st_edge.flow < 0 ||
    2936         [ #  # ]:           0 :          (int) pSrc->st_edge.flow + edge_flow >= EDGE_FLOW_ST_MASK)
    2937                 :             :     {
    2938                 :           0 :         return BNS_PROGRAM_ERR;
    2939                 :             :     }
    2940                 :             : 
    2941                 :             :     /* add flow */
    2942                 :           0 :     e01->cap += edge_cap;
    2943                 :           0 :     e01->flow += edge_flow;
    2944                 :           0 :     e01->cap0 = e01->cap;
    2945                 :           0 :     e01->flow0 = e01->flow;
    2946                 :             : 
    2947                 :           0 :     pDst->st_edge.cap += edge_cap;
    2948                 :           0 :     pDst->st_edge.cap0 = pDst->st_edge.cap;
    2949                 :           0 :     *tot_st_cap += edge_cap;
    2950                 :             : 
    2951                 :           0 :     pDst->st_edge.flow += edge_flow;
    2952                 :           0 :     pDst->st_edge.flow0 = pDst->st_edge.flow;
    2953                 :           0 :     *tot_st_flow += edge_flow;
    2954                 :             : 
    2955                 :           0 :     pSrc->st_edge.flow += edge_flow;
    2956                 :           0 :     pSrc->st_edge.flow0 = pSrc->st_edge.flow;
    2957                 :           0 :     *tot_st_flow += edge_flow;
    2958                 :             : 
    2959                 :             : /*
    2960                 :             :     pDst->st_edge.cap  += e01->cap;
    2961                 :             :     pDst->st_edge.cap0  = pDst->st_edge.cap;
    2962                 :             :     *tot_st_cap       += e01->cap;
    2963                 :             : 
    2964                 :             :     pDst->st_edge.flow += e01->flow;
    2965                 :             :     pDst->st_edge.flow0 = pDst->st_edge.flow;
    2966                 :             :     *tot_st_flow      += e01->flow;
    2967                 :             : 
    2968                 :             :     pSrc->st_edge.flow += e01->flow;
    2969                 :             :     pSrc->st_edge.flow0 = pSrc->st_edge.flow;
    2970                 :             :     *tot_st_flow      += e01->flow;
    2971                 :             : */
    2972                 :           0 :     return 0;
    2973                 :             : }
    2974                 :             : 
    2975                 :             : 
    2976                 :             : /**************************************************************
    2977                 :             :      (+) and (-) group V - connection
    2978                 :             :      ================================
    2979                 :             : 
    2980                 :             :   BNS_VERT_TYPE__AUX    (+/-)-connection
    2981                 :             :                     (v)  st_cap  =
    2982                 :             :                     / \  st_flow = (cap0 - Delta0 - flow0) + (cap1 - Delta1 -flow1)
    2983                 :             :                    /   \
    2984                 :             :                   /     \   cap  =  cap1
    2985                 :             :                  /       \  flow = (cap1 - Delta1 - flow1)
    2986                 :             :                 /         \
    2987                 :             :               (-)         (+)  st_cap  = cap1
    2988                 :             :              /   \       /   \ st_flow = cap1 - Delta1
    2989                 :             :             /cap0 \     /cap1 \
    2990                 :             :              flow0       flow1
    2991                 :             : 
    2992                 :             : ***************************************************************
    2993                 :             : 
    2994                 :             :      (+) supergroup Y - connection
    2995                 :             :      ==============================
    2996                 :             : 
    2997                 :             :                            (+) BNS_VT_C_POS_ALL  (+) supergroup
    2998                 :             :       Delta0                |                    ==============
    2999                 :             :       not shown             |  cap  = cap0+cap1
    3000                 :             :                             |  flow = flow0+flow1-Delta0-Delta1
    3001                 :             :        BNS_VERT_TYPE__AUX  (y) <------------------ additional vertex: st_cap  = cap0+cap1
    3002                 :             :                            / \                                        st_flow = cap0+cap1
    3003                 :             :          cap=cap0         /   \  cap  = cap1
    3004                 :             :          flow=cap0-flow0 /     \ flow = cap1 - flow1 - Delta1
    3005                 :             :              -Delta0    /       \
    3006                 :             :                 not-C (+)       (+) Carbons         st_cap  = cap1
    3007                 :             :          BNS_VT_C_POS / \       / \ BNS_VT_C_POS_C  st_flow = cap1 - Delta1
    3008                 :             :                      /   \     /   \
    3009                 :             :         totals      cap0        cap1 = sum of all cap  going up into (+) from atoms or ChargeStruct
    3010                 :             :         to (+):     flow0       flow1= sum of all flow going up into (+)
    3011                 :             :                    Delta0       Delta1 = st_cap(+)-st_flow(+) before connection
    3012                 :             :   Observations
    3013                 :             :   ============
    3014                 :             :   A. Any Delta > 0 on (+) or (-) group decreases total (signed) charge by Delta
    3015                 :             : 
    3016                 :             :   B. Any alt path from an atom through ChargeStruct to an atom
    3017                 :             :      does not change the total charge
    3018                 :             : 
    3019                 :             :   C. st_flow(+/-) = cap(+)-flow(+)-Delta(+) + cap(-)-flow(-)-Delta(-) =
    3020                 :             :                   = charge(+) + |max (-) charge| + charge(-) = const
    3021                 :             :      (charge conservation)
    3022                 :             : 
    3023                 :             :   D. To decrease total charge: increase st_cap on (+) or (-) group, including supergroup
    3024                 :             :   E. To increase total charge: increase st_cap on any (y) or (v)-connecting vertex
    3025                 :             : 
    3026                 :             :   F. To cancel charges:
    3027                 :             :        1. Forbid (+/-)-(+) or (+/-)-(-) edge
    3028                 :             :        2. Add delta>0 to (+/-) st_cap
    3029                 :             :        3. Add same delta to (+) or (-) st_cap
    3030                 :             : 
    3031                 :             : 
    3032                 :             : ****************************************************************/
    3033                 :             : 
    3034                 :             : /************************************************************************************
    3035                 :             :      j2,j3 < j1 < j0
    3036                 :             : 
    3037                 :             :                                 (+/-) <---- next step; if does not exist then
    3038                 :             :                                 /   \                  st_cap1' := st_flow1'
    3039                 :             :                                /     \
    3040                 :             :                               /       \ st_cap1' := cap01'
    3041                 :             :                         pv1 (+)super    st_flow1':= cap01'-flow01' = flow02'+flow03'
    3042                 :             :                         j1   |
    3043                 :             :                              |           cap01' := st_cap0'
    3044                 :             :                              |           flow01':= st_cap0'-flow02'-flow03'
    3045                 :             :                              |
    3046                 :             :                              |           st_cap0' :=
    3047                 :             :                             ( )  pv0,j0  st_flow0':= cap2+st_cap3
    3048                 :             :                            /   \
    3049                 :             :                           /     \   cap03'  = cap3
    3050                 :             :                          /       \  flow03' = cap3 - flow3 - Delta3
    3051                 :             :                         /         \
    3052                 :             :    st_cap2, st_flow2  (+)         (+C)        st_cap3'  := cap3
    3053                 :             :                       pv2,j2      pv3,j3      st_flow3' := cap3-Delta3
    3054                 :             :                     /    \       /    \       Delta3    := st_cap3 - st_flow3
    3055                 :             :                 cap2, flow2     cap3, flow3 = sums of incoming
    3056                 :             :  **************************************************************************************/
    3057                 :             : 
    3058                 :           0 : int ConnectSuperCGroup( int nSuperCGroup, int nAddGroups[], int num_add,
    3059                 :             :                         int *pcur_num_vertices, int *pcur_num_edges,
    3060                 :             :                         int *tot_st_cap, int *tot_st_flow,
    3061                 :             :                         BN_STRUCT *pBNS, ALL_TC_GROUPS *pTCGroups )
    3062                 :             : {
    3063                 :           0 :     BNS_EDGE   **e0X = NULL, *e;
    3064                 :           0 :     BNS_VERTEX **pvX = NULL, *pv0 = NULL, *pv1 = NULL, *pv = NULL;
    3065                 :           0 :     int         *jX = NULL, *iX = NULL;
    3066                 :           0 :     int        i, j, num_groups, j0, i1, j1, iXX, ret = 0, fst = 0;
    3067                 :           0 :     int        cur_num_vertices = *pcur_num_vertices;
    3068                 :           0 :     int        cur_num_edges = *pcur_num_edges;
    3069                 :             : 
    3070         [ #  # ]:           0 :     if (nSuperCGroup >= 0)
    3071                 :             :     {
    3072                 :           0 :         i1 = pTCGroups->nGroup[nSuperCGroup]; /* the supergroup */
    3073         [ #  # ]:           0 :         if (i1 < 0)
    3074                 :           0 :             return 0;
    3075                 :             :     }
    3076                 :             :     else
    3077                 :             :     {
    3078                 :           0 :         i1 = -1;
    3079                 :           0 :         fst = 1;
    3080                 :             :     }
    3081                 :             : 
    3082         [ #  # ]:           0 :     for (i = num_groups = 0; i < num_add; i++)
    3083                 :             :     {
    3084                 :           0 :         iXX = pTCGroups->nGroup[nAddGroups[i]];
    3085   [ #  #  #  # ]:           0 :         num_groups += ( iXX >= 0 && iXX != i1 );
    3086                 :             :     }
    3087         [ #  # ]:           0 :     if (num_groups < 1)
    3088                 :             :     {  /* Y connect only 2 or more groups; V connects even 1 group */
    3089                 :           0 :         return 0;
    3090                 :             :     }
    3091                 :             : 
    3092                 :           0 :     e0X = (BNS_EDGE   **) inchi_calloc( (long long)num_groups + 1, sizeof( e0X[0] ) ); /* djb-rwth: cast operator added */
    3093                 :           0 :     pvX = (BNS_VERTEX **) inchi_calloc( (long long)num_groups + 1, sizeof( pvX[0] ) ); /* djb-rwth: cast operator added */
    3094                 :           0 :     jX = (int         *) inchi_calloc( (long long)num_groups + 1, sizeof( jX[0] ) ); /* djb-rwth: cast operator added */
    3095                 :           0 :     iX = (int         *) inchi_calloc( (long long)num_groups + 1, sizeof( iX[0] ) ); /* djb-rwth: cast operator added */
    3096                 :             : 
    3097   [ #  #  #  #  :           0 :     if (!e0X || !pvX || !jX || !iX)
             #  #  #  # ]
    3098                 :             :     {
    3099                 :           0 :         ret = RI_ERR_ALLOC;
    3100                 :           0 :         goto exit_function;
    3101                 :             :     }
    3102                 :             : 
    3103                 :             :     /* create vert_ficpoint -- central Y-connection vertex */
    3104                 :             : 
    3105                 :           0 :     j0 = cur_num_vertices;
    3106                 :           0 :     pv0 = pBNS->vert + j0; /* center of the Y-connection; has number j0 */
    3107                 :           0 :     pv0->iedge = ( pv0 - 1 )->iedge + ( pv0 - 1 )->max_adj_edges;
    3108                 :           0 :     pv0->max_adj_edges = num_groups + 1 + BNS_ADD_EDGES; /* Y-connection num. edges */
    3109                 :           0 :     pv0->num_adj_edges = 0; /* nothing connected yet */
    3110                 :           0 :     pv0->type = BNS_VT_YVCONNECTOR;
    3111                 :           0 :     cur_num_vertices++;
    3112                 :             : 
    3113         [ #  # ]:           0 :     if (fst == 0)
    3114                 :             :     {
    3115                 :             :         /* find super c-group vertex pv1, number j1 */
    3116                 :           0 :         jX[0] = j1 = pTCGroups->pTCG[i1].nVertexNumber;
    3117                 :           0 :         iX[0] = i1;
    3118                 :           0 :         pvX[0] = pv1 = pBNS->vert + j1;
    3119                 :             :     }
    3120                 :             : 
    3121                 :             :     /* find other c-group vertices */
    3122         [ #  # ]:           0 :     for (i = 0, j = 1; i < num_add; i++)
    3123                 :             :     {
    3124                 :           0 :         iXX = pTCGroups->nGroup[nAddGroups[i]];
    3125   [ #  #  #  # ]:           0 :         if (( iXX >= 0 ) && ( iXX != i1 ))
    3126                 :             :         {
    3127                 :           0 :             iX[j] = iXX;
    3128                 :           0 :             jX[j] = pTCGroups->pTCG[iXX].nVertexNumber;
    3129                 :           0 :             pvX[j] = pBNS->vert + jX[j];
    3130                 :           0 :             j++;
    3131                 :             :         }
    3132                 :             :     }
    3133                 :             : 
    3134                 :             :     /* grab (num_groups+1) free edges */
    3135         [ #  # ]:           0 :     for (i = fst; i <= num_groups; i++)
    3136                 :             :     {
    3137                 :           0 :         e = e0X[i] = pBNS->edge + cur_num_edges;
    3138                 :           0 :         pv = pvX[i];
    3139                 :           0 :         j = jX[i];
    3140                 :           0 :         iXX = iX[i];
    3141                 :             :         /* connect all to pv0 */
    3142                 :           0 :         ret = ConnectTwoVertices( pv0, pv, e, pBNS, 1 );
    3143   [ #  #  #  # ]:           0 :         if (IS_BNS_ERROR( ret ))
    3144                 :             :         {
    3145                 :           0 :             goto exit_function;
    3146                 :             :         }
    3147         [ #  # ]:           0 :         if (i)
    3148                 :             :         {
    3149                 :             :             /* from c-group to central Y-connecting vertex of from supergroup to (+/-) vertex */
    3150                 :           0 :             pTCGroups->pTCG[iX[i]].nForwardEdge = cur_num_edges;
    3151                 :             :         }
    3152                 :             :         else
    3153                 :             :         {
    3154                 :             :             /* from central Y-connecting vertex to supergroup */
    3155                 :           0 :             pTCGroups->pTCG[iX[i]].nBackwardEdge = cur_num_edges;
    3156                 :             :         }
    3157                 :           0 :         cur_num_edges++;
    3158                 :             :     }
    3159                 :             : 
    3160                 :             :     /* set flow and cap for incoming into pv0 edges */
    3161         [ #  # ]:           0 :     for (i = 1; i <= num_groups; i++)
    3162                 :             :     {
    3163                 :           0 :         int nDelta = pTCGroups->pTCG[iX[i]].st_cap - pTCGroups->pTCG[iX[i]].edges_cap;
    3164                 :           0 :         int edge_cap = pTCGroups->pTCG[iX[i]].edges_cap + nDelta; /* added nDelta */
    3165                 :           0 :         int edge_flow = pTCGroups->pTCG[iX[i]].edges_cap - pTCGroups->pTCG[iX[i]].edges_flow /*-nDelta*/;
    3166                 :             : 
    3167                 :           0 :         ret = AddEdgeFlow( edge_cap, edge_flow,
    3168                 :           0 :                      e0X[i], pvX[i]/*src*/, pv0 /* dest*/, tot_st_cap, tot_st_flow );
    3169                 :             : 
    3170   [ #  #  #  # ]:           0 :         if (IS_BNS_ERROR( ret ))
    3171                 :             :         {
    3172                 :           0 :             goto exit_function;
    3173                 :             :         }
    3174                 :             :     }
    3175                 :             : 
    3176         [ #  # ]:           0 :     if (fst == 0)
    3177                 :             :     {
    3178                 :             :         /* set flow and cap for going out of pv0 and into pv1 edge */
    3179                 :           0 :         int edge_cap = pv0->st_edge.cap;
    3180                 :           0 :         int edge_flow = pv0->st_edge.cap - pv0->st_edge.flow;
    3181                 :             : 
    3182                 :           0 :         ret = AddEdgeFlow( pv0->st_edge.cap, pv0->st_edge.cap - pv0->st_edge.flow,
    3183                 :             :                      e0X[0], pv0/*src*/, pv1 /* dest*/, tot_st_cap, tot_st_flow );
    3184                 :             : 
    3185   [ #  #  #  # ]:           0 :         if (IS_BNS_ERROR( ret ))
    3186                 :             :         {
    3187                 :           0 :             goto exit_function;
    3188                 :             :         }
    3189                 :             : 
    3190                 :           0 :         pTCGroups->pTCG[iX[0]].edges_cap += edge_cap;
    3191                 :           0 :         pTCGroups->pTCG[iX[0]].edges_flow += edge_flow;
    3192                 :           0 :         pTCGroups->pTCG[iX[0]].st_cap += edge_cap;
    3193                 :           0 :         pTCGroups->pTCG[iX[0]].st_flow += edge_flow;
    3194                 :             :     }
    3195                 :             :     else
    3196                 :             :     {
    3197                 :             :         /* no supergroup => change cap to flow */
    3198                 :           0 :         *tot_st_cap += pv0->st_edge.flow - pv0->st_edge.cap;
    3199                 :           0 :         pv0->st_edge.cap += pv0->st_edge.flow - pv0->st_edge.cap;
    3200                 :           0 :         pv0->st_edge.cap0 = pv0->st_edge.cap;
    3201                 :             :     }
    3202                 :             : 
    3203                 :           0 :     *pcur_num_vertices = cur_num_vertices;
    3204                 :           0 :     *pcur_num_edges = cur_num_edges;
    3205                 :           0 :     ret = num_groups;
    3206                 :             : 
    3207                 :           0 : exit_function:
    3208   [ #  #  #  # ]:           0 :     if (e0X) inchi_free( e0X );
    3209   [ #  #  #  # ]:           0 :     if (pvX) inchi_free( pvX );
    3210   [ #  #  #  # ]:           0 :     if (jX) inchi_free( jX );
    3211   [ #  #  #  # ]:           0 :     if (iX) inchi_free( iX );
    3212                 :             : 
    3213                 :           0 :     return ret;
    3214                 :             : }
    3215                 :             : 
    3216                 :             : 
    3217                 :             : /*********************************************************************************/
    3218                 :           0 : void AddStCapFlow( BNS_VERTEX *vert_ficpoint, int *tot_st_flow, int *tot_st_cap, int cap, int flow )
    3219                 :             : {
    3220                 :           0 :     vert_ficpoint->st_edge.flow += flow;
    3221                 :           0 :     *tot_st_flow += flow;
    3222                 :           0 :     vert_ficpoint->st_edge.cap += cap;
    3223                 :           0 :     *tot_st_cap += cap;
    3224                 :             : 
    3225                 :           0 :     vert_ficpoint->st_edge.flow0 = vert_ficpoint->st_edge.flow;
    3226                 :           0 :     vert_ficpoint->st_edge.cap0 = vert_ficpoint->st_edge.cap;
    3227                 :           0 : }
    3228                 :             : 
    3229                 :             : 
    3230                 :             : /*********************************************************************************/
    3231                 :           0 : void SetStCapFlow( BNS_VERTEX *vert_ficpoint, int *tot_st_flow, int *tot_st_cap, int cap, int flow )
    3232                 :             : {
    3233                 :           0 :     *tot_st_flow += flow - vert_ficpoint->st_edge.flow;
    3234                 :           0 :     vert_ficpoint->st_edge.flow = flow;
    3235                 :           0 :     *tot_st_cap += cap - vert_ficpoint->st_edge.cap;
    3236                 :           0 :     vert_ficpoint->st_edge.cap = cap;
    3237                 :             : 
    3238                 :           0 :     vert_ficpoint->st_edge.flow0 = vert_ficpoint->st_edge.flow;
    3239                 :           0 :     vert_ficpoint->st_edge.cap0 = vert_ficpoint->st_edge.cap;
    3240                 :           0 : }
    3241                 :             : 
    3242                 :             : 
    3243                 :             : /*********************************************************************************
    3244                 :             : int AddCGroups2TCGBnStruct( BN_STRUCT *pBNS, StrFromINChI *pStruct,
    3245                 :             :                             VAL_AT *pVA, ALL_TC_GROUPS *pTCGroups )
    3246                 :             : 
    3247                 :             : 
    3248                 :             :  *********************************************************************************/
    3249                 :           0 : int AddCGroups2TCGBnStruct( BN_STRUCT *pBNS, StrFromINChI *pStruct, VAL_AT *pVA,
    3250                 :             :                             ALL_TC_GROUPS *pTCGroups, int nMaxAddEdges )
    3251                 :             : {
    3252                 :           0 :     int ret = 0, ret1, ret2, ret3, bNeedsFlower; /* djb-rwth: ignoring LLVM warning: variable used to store function return value */
    3253                 :           0 :     inp_ATOM *at = pStruct->at;
    3254                 :           0 :     int       num_atoms = pStruct->num_atoms;
    3255                 :             :     /*int       num_tg           = pTCGroups->num_tgroups;*/
    3256                 :           0 :     int       num_cg = pTCGroups->num_tc_groups - pTCGroups->num_tgroups;
    3257                 :           0 :     int       fst_cg_vertex = pBNS->num_vertices;
    3258                 :           0 :     int       fst_cg_group = pTCGroups->num_tgroups;
    3259                 :           0 :     int       num_vertices = pBNS->num_vertices;
    3260                 :           0 :     int       num_edges = pBNS->num_edges;
    3261                 :           0 :     int       cg_charge = 0;
    3262                 :           0 :     ICHICONST SRM *pSrm = pStruct->pSrm;
    3263                 :             : 
    3264                 :             :     /* ret = ReInitBnStruct( pBNS ); */
    3265                 :             : 
    3266         [ #  # ]:           0 :     if (num_cg > 0)
    3267                 :             :     {
    3268                 :             :     /* if ( cgi && cgi->num_c_groups && cgi->c_group ) */
    3269                 :             :         int         i, i1, i2, j, j1, j2, k, k1, k2, n, c_point, c_neigh, cap, flow;
    3270                 :             :         int         cur_num_vertices, cur_num_edges;
    3271                 :             :         BNS_VERTEX *vert_ficpoint, *vert_ficpoint_prev, *vert_ficpoint_base;  /* fictitious vertex describing charge c-group */
    3272                 :             :         BNS_VERTEX *pv1, *pv2;
    3273                 :             :         BNS_EDGE   *edge;      /* edge between that vertex and the tautomeric c_point */
    3274                 :           0 :         int        nMaxCGroupNumber = 0;
    3275                 :             :         MY_CONST C_NODE *pCN;
    3276                 :             :         int              cn_len, cn_bits, bMetalAtoms;
    3277                 :             :         int              type;
    3278                 :             :         int        tot_st_cap, tot_st_flow;
    3279                 :             :         int        nAddGroups[16];
    3280                 :             : 
    3281                 :             : 
    3282                 :             :         /* Debug: check overflow */
    3283         [ #  # ]:           0 :         if (num_vertices >= pBNS->max_vertices)
    3284                 :             :         {
    3285                 :           0 :             return BNS_VERT_EDGE_OVFL;
    3286                 :             :         }
    3287                 :             : 
    3288                 :           0 :         nMaxCGroupNumber = num_cg;
    3289                 :             :         /* clear all vertices not used until now */
    3290                 :           0 :         memset( pBNS->vert + num_vertices, 0, ( (long long)pBNS->max_vertices - num_vertices ) * sizeof( pBNS->vert[0] ) ); /* djb-rwth: cast operator added; memset_s C11/Annex K variant? */
    3291                 :           0 :         tot_st_cap = pBNS->tot_st_cap;
    3292                 :           0 :         tot_st_flow = pBNS->tot_st_flow;
    3293                 :             : 
    3294                 :             :         /*****************************************/
    3295                 :             :         /* initialize new fictitious vertices    */
    3296                 :             :         /* representing c-point groups, c-groups */
    3297                 :             :         /*****************************************/
    3298                 :           0 :         vert_ficpoint_prev = pBNS->vert + fst_cg_vertex - 1;
    3299                 :             : 
    3300         [ #  # ]:           0 :         for (i = 0; i < num_cg; i++)
    3301                 :             :         {
    3302                 :             :             /*
    3303                 :             :               vert_ficpoint-1 is the last vertex;
    3304                 :             :               vert_ficpoint   is the being added vertex
    3305                 :             :               Note: nGroupNumber are not contiguous
    3306                 :             :             */
    3307                 :           0 :             vert_ficpoint = vert_ficpoint_prev + 1;
    3308                 :           0 :             vert_ficpoint->iedge = vert_ficpoint_prev->iedge + vert_ficpoint_prev->max_adj_edges;
    3309                 :           0 :             vert_ficpoint->max_adj_edges = pTCGroups->pTCG[i + fst_cg_group].num_edges + nMaxAddEdges;
    3310                 :           0 :             vert_ficpoint->num_adj_edges = 0;
    3311                 :             : 
    3312                 :           0 :             vert_ficpoint->st_edge.flow += pTCGroups->pTCG[i + fst_cg_group].st_flow;
    3313                 :           0 :             tot_st_flow += pTCGroups->pTCG[i + fst_cg_group].st_flow;
    3314                 :           0 :             vert_ficpoint->st_edge.cap += pTCGroups->pTCG[i + fst_cg_group].st_cap;
    3315                 :           0 :             tot_st_cap += pTCGroups->pTCG[i + fst_cg_group].st_cap;
    3316                 :             : 
    3317                 :           0 :             vert_ficpoint->st_edge.flow0 = vert_ficpoint->st_edge.flow;
    3318                 :           0 :             vert_ficpoint->st_edge.cap0 = vert_ficpoint->st_edge.cap;
    3319                 :             : 
    3320                 :           0 :             vert_ficpoint->type = pTCGroups->pTCG[i + fst_cg_group].type;
    3321                 :             :             /* save the vertex number */
    3322                 :           0 :             pTCGroups->pTCG[i + fst_cg_group].nVertexNumber = (int) ( vert_ficpoint - pBNS->vert );
    3323                 :             : 
    3324                 :           0 :             vert_ficpoint_prev = vert_ficpoint; /* keep track of iedges */
    3325                 :             :         }
    3326                 :             : 
    3327                 :           0 :         cur_num_vertices = (int) ( vert_ficpoint_prev - pBNS->vert ) + 1;
    3328                 :           0 :         cur_num_edges = num_edges;
    3329                 :             : 
    3330                 :             :         /*************************************************************/
    3331                 :             :         /* pass 1:                                                   */
    3332                 :             :         /* create ChargeStruct for c-points and connect them to      */
    3333                 :             :         /* the vertices representing c-point groups;                 */
    3334                 :             :         /* set final atom st_cap, st_flow                            */
    3335                 :             :         /*************************************************************/
    3336         [ #  # ]:           0 :         for (c_point = 0; c_point < num_atoms; c_point++)
    3337                 :             :         {
    3338         [ #  # ]:           0 :             if (!( k = pVA[c_point].cnListIndex ))
    3339                 :           0 :                 continue;  /* not a c-point */
    3340                 :             : 
    3341                 :           0 :             k--;
    3342                 :           0 :             pCN = cnList[k].pCN;   /* pointer to the ChargeStruct */
    3343                 :           0 :             cn_len = cnList[k].len;   /* length of the ChargeStruct  */
    3344                 :           0 :             cn_bits = cnList[k].bits;  /* bits: for M-recognition */
    3345                 :             :             /* cn_bits = cnList[k].bits; */ /* ChargeStruct type */
    3346                 :           0 :             bMetalAtoms = ( cn_bits == cn_bits_Me );
    3347                 :           0 :             vert_ficpoint_base = vert_ficpoint_prev; /* add aux vertices after this */
    3348                 :             : 
    3349                 :             :             /* create disconnected auxiliary vertices of the at[c_point] ChargeStruct; add to them st_flow & st_cap */
    3350         [ #  # ]:           0 :             for (i1 = 0; i1 < cn_len; i1++)
    3351                 :             :             {
    3352   [ #  #  #  # ]:           0 :                 if (!IS_BNS_VT_CHRG_STRUCT( pCN[i1].v.type ))
    3353                 :             :                 {
    3354                 :           0 :                     continue;
    3355                 :             :                 }
    3356                 :             :                 /* the atom is always the first; the attached c-points are always the last */
    3357                 :           0 :                 vert_ficpoint = vert_ficpoint_base + i1; /* i1 = 1, 2,.. less number of attached c-points */
    3358                 :           0 :                 vert_ficpoint->iedge = vert_ficpoint_prev->iedge + vert_ficpoint_prev->max_adj_edges;
    3359                 :           0 :                 vert_ficpoint->max_adj_edges = pCN[i1].v.valence; /* do not add additional edges to aux vertices */
    3360                 :           0 :                 vert_ficpoint->num_adj_edges = 0;
    3361                 :             : 
    3362   [ #  #  #  # ]:           0 :                 cap = !bMetalAtoms ? pCN[i1].v.cap : pCN[i1].v.cap ? pSrm->nMetalMaxCharge_D : 0;
    3363   [ #  #  #  # ]:           0 :                 flow = !bMetalAtoms ? pCN[i1].v.flow : pCN[i1].v.flow ? pSrm->nMetalMaxCharge_D : 0;
    3364                 :             : 
    3365                 :           0 :                 AddStCapFlow( vert_ficpoint, &tot_st_flow, &tot_st_cap, cap, flow );
    3366                 :           0 :                 vert_ficpoint->type = pCN[i1].v.type; /* =BNS_VERT_TYPE__AUX */
    3367                 :             : 
    3368                 :           0 :                 vert_ficpoint_prev = vert_ficpoint; /* the last one will be vert_ficpoint for the next c-point */
    3369                 :           0 :                 cur_num_vertices = (int) ( vert_ficpoint - pBNS->vert ) + 1;
    3370                 :             : 
    3371         [ #  # ]:           0 :                 if (vert_ficpoint->iedge + vert_ficpoint->max_adj_edges - pBNS->iedge >= pBNS->max_iedges)
    3372                 :             :                 {
    3373                 :           0 :                     return BNS_VERT_EDGE_OVFL;
    3374                 :             :                 }
    3375         [ #  # ]:           0 :                 if (cur_num_vertices >= pBNS->max_vertices)
    3376                 :             :                 {
    3377                 :           0 :                     return BNS_VERT_EDGE_OVFL;
    3378                 :             :                 }
    3379                 :             :             }
    3380                 :             : 
    3381                 :             :             /* connect the vertices with new edges, add edge flow and cap */
    3382         [ #  # ]:           0 :             for (i1 = 0; i1 < cn_len; i1++)
    3383                 :             :             {
    3384                 :           0 :                 pv1 = NULL;
    3385                 :           0 :                 k1 = -1;
    3386                 :             : 
    3387                 :             :                 /* find vertex corresponding to i1 */
    3388                 :             : 
    3389         [ #  # ]:           0 :                 if (pCN[i1].v.type & BNS_VERT_TYPE_ATOM)
    3390                 :             :                 {
    3391                 :           0 :                     pv1 = pBNS->vert + c_point; /* may be only one atom -- the current c_point at i1==0 */
    3392                 :             :                     /* add atom vertex st_cap and st_flow */
    3393   [ #  #  #  # ]:           0 :                     cap = !bMetalAtoms ? pCN[i1].v.cap : pCN[i1].v.cap ? pSrm->nMetalMaxCharge_D : 0;
    3394   [ #  #  #  # ]:           0 :                     flow = !bMetalAtoms ? pCN[i1].v.flow : pCN[i1].v.flow ? pSrm->nMetalMaxCharge_D : 0;
    3395                 :           0 :                     AddStCapFlow( pv1, &tot_st_flow, &tot_st_cap, cap, flow );
    3396                 :             :                 }
    3397                 :             : 
    3398         [ #  # ]:           0 :                 else if (IS_BNS_VT_C_GR( pCN[i1].v.type ))
    3399                 :             :                 {
    3400                 :             :                     /* find c-group vertex by looking for its type */
    3401         [ #  # ]:           0 :                     for (j = 0; j < num_cg; j++)
    3402                 :             :                     {
    3403         [ #  # ]:           0 :                         if (pCN[i1].v.type == pBNS->vert[fst_cg_vertex + j].type)
    3404                 :             :                         {
    3405                 :           0 :                             pv1 = pBNS->vert + fst_cg_vertex + j;
    3406                 :           0 :                             break;
    3407                 :             :                         }
    3408                 :             :                     }
    3409                 :             :                     /* index of the pTCGroups->pTCG[] */
    3410         [ #  # ]:           0 :                     if (pv1)
    3411                 :             :                     {
    3412                 :           0 :                         k1 = j + fst_cg_group;
    3413         [ #  # ]:           0 :                         if (pTCGroups->pTCG[k1].type != pCN[i1].v.type ||
    3414         [ #  # ]:           0 :                              pTCGroups->pTCG[k1].ord_num)
    3415                 :             :                         {
    3416                 :           0 :                             return RI_ERR_PROGR;
    3417                 :             :                         }
    3418                 :             :                     }
    3419                 :             :                 }
    3420                 :             : 
    3421         [ #  # ]:           0 :                 else if (IS_BNS_VT_M_GR( pCN[i1].v.type ))
    3422                 :             :                 {
    3423                 :           0 :                     k1 = pTCGroups->nGroup[TCG_MeFlower0];
    3424         [ #  # ]:           0 :                     if (k1 < 0 ||
    3425         [ #  # ]:           0 :                          pTCGroups->pTCG[k1].type != pCN[i1].v.type ||
    3426         [ #  # ]:           0 :                              pTCGroups->pTCG[k1].ord_num ||
    3427         [ #  # ]:           0 :                              !pSrm->bMetalAddFlower)
    3428                 :             :                     {
    3429                 :           0 :                         return RI_ERR_PROGR;
    3430                 :             :                     }
    3431                 :           0 :                     pv1 = pBNS->vert + pTCGroups->pTCG[k1].nVertexNumber;
    3432                 :             :                 }
    3433                 :             : 
    3434   [ #  #  #  # ]:           0 :                 else if (IS_BNS_VT_CHRG_STRUCT( pCN[i1].v.type ))
    3435                 :             :                 {
    3436                 :             :                     /* aux vertex */
    3437                 :           0 :                     pv1 = vert_ficpoint_base + i1;
    3438                 :             :                 }
    3439                 :             : 
    3440         [ #  # ]:           0 :                 if (!pv1)
    3441                 :             :                 {
    3442                 :           0 :                     return BNS_BOND_ERR;
    3443                 :             :                 }
    3444                 :             : 
    3445                 :             :                 /* connect pairs of vertices with new edges */
    3446   [ #  #  #  # ]:           0 :                 for (k = 0; k < MAX_CN_VAL && ( i2 = pCN[i1].e[k].neigh ); k++)
    3447                 :             :                 {
    3448                 :           0 :                     pv2 = NULL;
    3449                 :           0 :                     k2 = -1;
    3450                 :           0 :                     i2--; /* neighbor */
    3451                 :             : 
    3452                 :             :                     /* find vertex corresponding to i2 */
    3453                 :             : 
    3454         [ #  # ]:           0 :                     if (pCN[i2].v.type & BNS_VERT_TYPE_ATOM)
    3455                 :             :                     {
    3456                 :           0 :                         pv2 = pBNS->vert + c_point;
    3457   [ #  #  #  # ]:           0 :                         cap = !bMetalAtoms ? pCN[i2].v.cap : pCN[i2].v.cap ? pSrm->nMetalMaxCharge_D : 0;
    3458   [ #  #  #  # ]:           0 :                         flow = !bMetalAtoms ? pCN[i2].v.flow : pCN[i2].v.flow ? pSrm->nMetalMaxCharge_D : 0;
    3459                 :             :                         /* add atom vertex st_cap and st_flow; this normally should not happen */
    3460                 :           0 :                         AddStCapFlow( pv2, &tot_st_flow, &tot_st_cap, cap, flow );
    3461                 :             :                     }
    3462                 :             : 
    3463         [ #  # ]:           0 :                     else if (IS_BNS_VT_C_GR( pCN[i2].v.type ))
    3464                 :             :                     {
    3465                 :             :                         /* find c-group vertex by looking for its type */
    3466         [ #  # ]:           0 :                         for (j = 0; j < num_cg; j++)
    3467                 :             :                         {
    3468         [ #  # ]:           0 :                             if (pCN[i2].v.type == pBNS->vert[fst_cg_vertex + j].type)
    3469                 :             :                             {
    3470                 :           0 :                                 pv2 = pBNS->vert + fst_cg_vertex + j;
    3471                 :           0 :                                 break;
    3472                 :             :                             }
    3473                 :             :                         }
    3474         [ #  # ]:           0 :                         if (pv2)
    3475                 :             :                         {
    3476                 :           0 :                             k2 = j + fst_cg_group;
    3477         [ #  # ]:           0 :                             if (pTCGroups->pTCG[k2].type != pCN[i2].v.type ||
    3478         [ #  # ]:           0 :                                  pTCGroups->pTCG[k2].ord_num)
    3479                 :             :                             {
    3480                 :           0 :                                 return RI_ERR_PROGR;
    3481                 :             :                             }
    3482                 :             :                         }
    3483                 :             :                     }
    3484                 :             : 
    3485         [ #  # ]:           0 :                     else if (IS_BNS_VT_M_GR( pCN[i2].v.type ))
    3486                 :             :                     {
    3487                 :           0 :                         k2 = pTCGroups->nGroup[TCG_MeFlower0];
    3488         [ #  # ]:           0 :                         if (k2 < 0 ||
    3489         [ #  # ]:           0 :                              pTCGroups->pTCG[k2].type != pCN[i2].v.type ||
    3490         [ #  # ]:           0 :                                  pTCGroups->pTCG[k2].ord_num ||
    3491         [ #  # ]:           0 :                                  !pSrm->bMetalAddFlower)
    3492                 :             :                         {
    3493                 :           0 :                             return RI_ERR_PROGR;
    3494                 :             :                         }
    3495                 :           0 :                         pv2 = pBNS->vert + pTCGroups->pTCG[k2].nVertexNumber;
    3496                 :             :                     }
    3497                 :             : 
    3498   [ #  #  #  # ]:           0 :                     else if (IS_BNS_VT_CHRG_STRUCT( pCN[i2].v.type ))
    3499                 :             :                     {
    3500                 :           0 :                         pv2 = vert_ficpoint_base + i2;
    3501                 :             :                     }
    3502                 :             : 
    3503                 :             :                     /* connect pv1 and pv2 */
    3504   [ #  #  #  #  :           0 :                     if (!pv1 || !pv2 || pv1 == pv2)
                   #  # ]
    3505                 :             :                     {
    3506                 :           0 :                         return BNS_BOND_ERR;
    3507                 :             :                     }
    3508                 :             : 
    3509                 :           0 :                     j1 = (int)(pv1 - pBNS->vert);
    3510                 :           0 :                     j2 = (int)(pv2 - pBNS->vert);
    3511                 :             : 
    3512                 :             :                     /* create a new edge connecting pv1 and pv2 */
    3513                 :           0 :                     edge = pBNS->edge + cur_num_edges;
    3514   [ #  #  #  # ]:           0 :                     if ((IS_BNS_VT_M_GR( pCN[i1].v.type ) && IS_BNS_VT_ATOM( pCN[i2].v.type )) ||
    3515   [ #  #  #  # ]:           0 :                          (IS_BNS_VT_M_GR( pCN[i2].v.type ) && IS_BNS_VT_ATOM( pCN[i1].v.type ))) /* djb-rwth: addressing LLVM warnings */
    3516                 :           0 :                     {
    3517                 :             :                         /* at[c_point] is a metal or is treated as a metal; connect it to M-group */
    3518                 :             :                         /* metal - M-group (i.e. Metal-Flower) edge */
    3519                 :             :                         int nStCap, nStFlow;
    3520                 :           0 :                         bNeedsFlower = AtomStcapStflow( at, pVA, pSrm, c_point, &nStCap, &nStFlow, &edge->cap, &edge->flow );
    3521                 :             :                         /* GetAtomToMCGroupInitEdgeCapFlow( &edge->cap, &edge->flow, pSrm, at, pVA, c_point ); */
    3522         [ #  # ]:           0 :                         if (!bNeedsFlower)
    3523                 :             :                         {
    3524                 :           0 :                             return RI_ERR_PROGR;
    3525                 :             :                         }
    3526                 :           0 :                         pVA[c_point].nMetalGroupEdge = cur_num_edges + 1;
    3527                 :             :                         /* pBNS->vert[c_point].st_edge.cap  += edge->flow;*/ /* where was this done ???*/
    3528                 :           0 :                         pBNS->vert[c_point].st_edge.flow += edge->flow;
    3529                 :           0 :                         pBNS->vert[c_point].st_edge.cap += edge->flow + pVA[c_point].cInitFreeValences;
    3530                 :           0 :                         pBNS->vert[c_point].st_edge.flow0 = pBNS->vert[c_point].st_edge.flow;
    3531                 :           0 :                         pBNS->vert[c_point].st_edge.cap0 = pBNS->vert[c_point].st_edge.cap;
    3532                 :           0 :                         tot_st_flow += edge->flow;
    3533                 :           0 :                         tot_st_cap += edge->flow + pVA[c_point].cInitFreeValences;
    3534                 :             :                     }
    3535                 :             :                     else
    3536                 :             :                     {
    3537   [ #  #  #  # ]:           0 :                         edge->cap = !bMetalAtoms ? pCN[i1].e[k].cap : pCN[i1].e[k].cap ? pSrm->nMetalMaxCharge_D : 0;
    3538   [ #  #  #  # ]:           0 :                         edge->flow = !bMetalAtoms ? pCN[i1].e[k].flow : pCN[i1].e[k].flow ? pSrm->nMetalMaxCharge_D : 0;
    3539                 :             :                     }
    3540                 :             : 
    3541                 :           0 :                     edge->forbidden = pCN[i1].e[k].bForbiddenEdge ? BNS_EDGE_FORBIDDEN_MASK : 0;
    3542                 :             : 
    3543                 :             :                     /* c-group incoming edges cap and flow needed in ConnectSuperCGroup() */
    3544                 :             :                     /*
    3545                 :             :                     if ( k1 >= 0 ) {
    3546                 :             :                         pTCGroups->pTCG[k1].edges_cap  += pCN[i1].e[k].cap;
    3547                 :             :                         pTCGroups->pTCG[k1].edges_flow += pCN[i1].e[k].flow;
    3548                 :             :                     }
    3549                 :             :                     if ( k2 >= 0 ) {
    3550                 :             :                         pTCGroups->pTCG[k2].edges_cap  += pCN[i1].e[k].cap;
    3551                 :             :                         pTCGroups->pTCG[k2].edges_flow += pCN[i1].e[k].flow;
    3552                 :             :                     }
    3553                 :             :                     */
    3554                 :             : 
    3555                 :           0 :                     edge->pass = 0;
    3556                 :             : 
    3557                 :             : #if ( RESET_EDGE_FORBIDDEN_MASK == 1 )
    3558                 :             :                     edge->forbidden &= pBNS->edge_forbidden_mask;
    3559                 :             : #endif
    3560                 :             : 
    3561                 :             :                     /* check edge overflow */
    3562         [ #  # ]:           0 :                     if (pv1->num_adj_edges >= pv1->max_adj_edges ||
    3563         [ #  # ]:           0 :                          pv2->num_adj_edges >= pv2->max_adj_edges ||
    3564         [ #  # ]:           0 :                          cur_num_edges >= pBNS->max_edges)
    3565                 :             :                     {
    3566                 :           0 :                         return BNS_VERT_EDGE_OVFL;
    3567                 :             :                     }
    3568                 :             : 
    3569                 :             :                     /* connect edge to the incident vertices and increment the counters of neighbors and edges */
    3570                 :             : 
    3571                 :           0 :                     ret = ConnectTwoVertices( pv1, pv2, edge, pBNS, 0 );
    3572                 :             : 
    3573   [ #  #  #  # ]:           0 :                     if (IS_BNS_ERROR( ret ))
    3574                 :             :                     {
    3575                 :           0 :                         return ret;
    3576                 :             :                     }
    3577                 :             : 
    3578                 :           0 :                     edge->cap0 = edge->cap;
    3579                 :           0 :                     edge->flow0 = edge->flow;
    3580                 :             : 
    3581                 :             :                     /* save the edge index */
    3582         [ #  # ]:           0 :                     type = IS_BNS_VT_C_GR( pv1->type ) ? pv1->type :
    3583         [ #  # ]:           0 :                         IS_BNS_VT_C_GR( pv2->type ) ? pv2->type : 0;
    3584         [ #  # ]:           0 :                     if (type)
    3585                 :             :                     {
    3586                 :             :                         /* the edge connects to a c-group */
    3587         [ #  # ]:           0 :                         if (type & BNS_VERT_TYPE_C_NEGATIVE)
    3588                 :             :                         {
    3589                 :           0 :                             pVA[c_point].nCMinusGroupEdge = cur_num_edges + 1;
    3590                 :             :                         }
    3591                 :             :                         else
    3592                 :             :                         {
    3593                 :           0 :                             pVA[c_point].nCPlusGroupEdge = cur_num_edges + 1;
    3594                 :             :                         }
    3595                 :             :                     }
    3596                 :           0 :                     cur_num_edges++; /* end of new edge creation */
    3597                 :             :                 }
    3598                 :             :             }
    3599                 :             :         }
    3600                 :             : 
    3601                 :             : 
    3602                 :             :         /*************************************************************/
    3603                 :             :         /* pass 2:                                                   */
    3604                 :             :         /* adjust bond cap, flow from the final atom st_cap, st_flow */
    3605                 :             :         /*************************************************************/
    3606         [ #  # ]:           0 :         for (c_point = 0; c_point < num_atoms; c_point++)
    3607                 :             :         {
    3608                 :             :             int st_cap, st_cap2, max_edge_flow;
    3609                 :           0 :             pv1 = pBNS->vert + c_point;  /* atom vertex */
    3610                 :           0 :             st_cap = pv1->st_edge.cap;
    3611         [ #  # ]:           0 :             for (k = 0; k < pv1->num_adj_edges; k++)
    3612                 :             :             {
    3613                 :           0 :                 edge = pBNS->edge + pv1->iedge[k];      /* incident edge */
    3614                 :           0 :                 c_neigh = edge->neighbor12 ^ c_point;   /* adjacent vertex */
    3615                 :           0 :                 pv2 = pBNS->vert + c_neigh;
    3616   [ #  #  #  # ]:           0 :                 if (c_neigh > c_point || !( pv2->type & BNS_VERT_TYPE_ATOM ))
    3617                 :             :                 {
    3618                 :           0 :                     continue;
    3619                 :             :                 }
    3620                 :             :                 /* adjacent vertex is an atom; the edge is a bond; process each bond only once */
    3621                 :           0 :                 st_cap2 = pv2->st_edge.cap;
    3622                 :             :                 /* the edge flow <= min( incident atom st_caps) */
    3623                 :           0 :                 max_edge_flow = inchi_min( st_cap, st_cap2 );
    3624                 :             :                 /* bond order <= triple bond (flow=2) */
    3625   [ #  #  #  # ]:           0 :                 if (((pSrm->bMetalAddFlower && !pSrm->nMetalMinBondOrder &&
    3626   [ #  #  #  # ]:           0 :                     ( pVA[c_point].cMetal && pVA[c_point].cNumBondsToMetal)) ||
    3627   [ #  #  #  # ]:           0 :                         (pVA[c_neigh].cMetal && pVA[c_neigh].cNumBondsToMetal) )) /* djb-rwth: addressing LLVM warnings */
    3628                 :             :                 {
    3629                 :           0 :                     max_edge_flow = inchi_min( max_edge_flow, MAX_BOND_EDGE_CAP + 1 );
    3630                 :             :                 }
    3631                 :             :                 else
    3632                 :             :                 {
    3633                 :           0 :                     max_edge_flow = inchi_min( max_edge_flow, MAX_BOND_EDGE_CAP );
    3634                 :             :                 }
    3635         [ #  # ]:           0 :                 if (at[c_point].bond_type[k] == BOND_TYPE_SINGLE)
    3636                 :             :                 {
    3637                 :             :                     /* the bond has not been changed due to stereo */
    3638                 :           0 :                     edge->cap = edge->cap0 = max_edge_flow;
    3639                 :             :                 }
    3640                 :             :             }
    3641                 :             :         }
    3642                 :             : 
    3643                 :             :         /***********************************************************/
    3644                 :             :         /**************                                 ************/
    3645                 :             :         /************** connect M-flower with new edges ************/
    3646                 :             :         /**************                                 ************/
    3647                 :             :         /***********************************************************/
    3648                 :             : 
    3649                 :           0 :         ret = ConnectMetalFlower( &cur_num_vertices, &cur_num_edges, &tot_st_cap, &tot_st_flow, pSrm, pBNS, pTCGroups );
    3650                 :             : 
    3651         [ #  # ]:           0 :         if (ret < 0)
    3652                 :             :         {
    3653                 :           0 :             goto exit_function;
    3654                 :             :         }
    3655                 :             : 
    3656                 :             :         /***********************************************************/
    3657                 :             :         /**************                                 ************/
    3658                 :             :         /************** add additional vertices & edges ************/
    3659                 :             :         /************** to connect c-groups             ************/
    3660                 :             :         /**************                                 ************/
    3661                 :             :         /***********************************************************/
    3662                 :             : 
    3663                 :             :         /* (+) supergroup, Y-connection */
    3664                 :             : 
    3665                 :           0 :         k = 0;
    3666                 :           0 :         nAddGroups[k++] = TCG_Plus0;
    3667                 :           0 :         nAddGroups[k++] = TCG_Plus_C0;
    3668                 :           0 :         nAddGroups[k++] = TCG_Plus_M0;
    3669                 :             : 
    3670                 :           0 :         ret1 = ConnectSuperCGroup( TCG_Plus,
    3671                 :             :                                    nAddGroups,
    3672                 :             :                                    k,
    3673                 :             :                                    &cur_num_vertices,
    3674                 :             :                                    &cur_num_edges,
    3675                 :             :                                    &tot_st_cap,
    3676                 :             :                                    &tot_st_flow,
    3677                 :             :                                    pBNS,
    3678                 :             :                                    pTCGroups ); /* djb-rwth: ignoring LLVM warning: variable used to store function return value */
    3679                 :             : 
    3680                 :             :         /* (-) supergroup, Y-connection */
    3681                 :             : 
    3682                 :           0 :         k = 0;
    3683                 :           0 :         nAddGroups[k++] = TCG_Minus0;
    3684                 :           0 :         nAddGroups[k++] = TCG_Minus_C0;
    3685                 :           0 :         nAddGroups[k++] = TCG_Minus_M0;
    3686                 :             : 
    3687                 :           0 :         ret2 = ConnectSuperCGroup( TCG_Minus,
    3688                 :             :                                    nAddGroups,
    3689                 :             :                                    k,
    3690                 :             :                                    &cur_num_vertices,
    3691                 :             :                                    &cur_num_edges,
    3692                 :             :                                    &tot_st_cap,
    3693                 :             :                                    &tot_st_flow,
    3694                 :             :                                    pBNS,
    3695                 :             :                                    pTCGroups ); /* djb-rwth: ignoring LLVM warning: variable used to store function return value */
    3696                 :             : 
    3697                 :             :         /******** connect (+) and (-) ***************/
    3698                 :             : 
    3699                 :           0 :         k = 0;
    3700                 :           0 :         nAddGroups[k++] = TCG_Plus;
    3701                 :           0 :         nAddGroups[k++] = TCG_Minus;
    3702                 :             : 
    3703                 :           0 :         ret3 = ConnectSuperCGroup( -1,
    3704                 :             :                                     nAddGroups,
    3705                 :             :                                     k,
    3706                 :             :                                     &cur_num_vertices,
    3707                 :             :                                     &cur_num_edges,
    3708                 :             :                                     &tot_st_cap,
    3709                 :             :                                     &tot_st_flow,
    3710                 :             :                                     pBNS,
    3711                 :             :                                     pTCGroups );
    3712                 :             : 
    3713                 :             :         /* Take care of the full charge */
    3714                 :             : 
    3715                 :           0 :         cg_charge = pTCGroups->total_charge - pTCGroups->tgroup_charge - pTCGroups->charge_on_atoms;
    3716                 :           0 :         ret = 1;
    3717         [ #  # ]:           0 :         if (ret3 > 0)
    3718                 :             :         {
    3719                 :             :             /* (+) and (-) or at least one of them have been connected */
    3720                 :           0 :             int nVertPlusMinus = cur_num_vertices - 1;
    3721                 :           0 :             BNS_VERTEX *pVertPlusMinus = pBNS->vert + nVertPlusMinus;
    3722                 :           0 :             BNS_VERTEX *pVertPlus = NULL, *pVertMinus = NULL, *pVert = NULL;
    3723                 :           0 :             BNS_EDGE   *pEdgePlus = NULL, *pEdgeMinus = NULL, *pEdge = NULL;
    3724                 :           0 :             n = pTCGroups->nGroup[TCG_Plus] >= 0;   /* (+)-supergroup exists */
    3725                 :           0 :             k = pTCGroups->nGroup[TCG_Minus] >= 0;  /* (-)-supergroup exists */
    3726                 :             : 
    3727   [ #  #  #  # ]:           0 :             if (pVertPlusMinus->num_adj_edges == 2 && k + n == 2)
    3728                 :             :             {
    3729                 :           0 :                 pEdgePlus = pBNS->edge + pVertPlusMinus->iedge[0];  /* TCG_Plus was the 1st */
    3730                 :           0 :                 pEdgeMinus = pBNS->edge + pVertPlusMinus->iedge[1];  /* TCG_Minus was the 2nd */
    3731                 :             :             }
    3732                 :             : 
    3733   [ #  #  #  # ]:           0 :             else if (pVertPlusMinus->num_adj_edges == 1 && k + n == 1)
    3734                 :             :             {
    3735         [ #  # ]:           0 :                 if (pTCGroups->nGroup[TCG_Plus] >= 0)
    3736                 :             :                 {
    3737                 :           0 :                     pEdgePlus = pBNS->edge + pVertPlusMinus->iedge[0];
    3738                 :             :                 }
    3739         [ #  # ]:           0 :                 else if (pTCGroups->nGroup[TCG_Minus] >= 0)
    3740                 :             :                 {
    3741                 :           0 :                     pEdgeMinus = pBNS->edge + pVertPlusMinus->iedge[0];
    3742                 :             :                 }
    3743                 :             :             }
    3744                 :             : 
    3745         [ #  # ]:           0 :             else if (k + n)
    3746                 :             :             {
    3747                 :             :                 /* program error check */
    3748                 :           0 :                 ret = BNS_BOND_ERR;
    3749                 :           0 :                 goto exit_function;
    3750                 :             :             }
    3751                 :             : 
    3752         [ #  # ]:           0 :             if (pEdgePlus)
    3753                 :             :             {
    3754                 :           0 :                 pVertPlus = pBNS->vert + ( pEdgePlus->neighbor12 ^ nVertPlusMinus );
    3755                 :             :             }
    3756         [ #  # ]:           0 :             if (pEdgeMinus)
    3757                 :             :             {
    3758                 :           0 :                 pVertMinus = pBNS->vert + ( pEdgeMinus->neighbor12 ^ nVertPlusMinus );
    3759                 :             :             }
    3760                 :             : 
    3761         [ #  # ]:           0 :             pVert = pVertPlus ? pVertPlus : pVertMinus ? pVertMinus : NULL;
    3762         [ #  # ]:           0 :             pEdge = pEdgePlus ? pEdgePlus : pEdgeMinus ? pEdgeMinus : NULL;
    3763         [ #  # ]:           0 :             if (pEdgeMinus)
    3764                 :             :             {
    3765                 :           0 :                 pTCGroups->nEdgeMinus = (int) ( pEdgeMinus - pBNS->edge );
    3766                 :             :             }
    3767         [ #  # ]:           0 :             if (pEdgePlus)
    3768                 :             :             {
    3769                 :           0 :                 pTCGroups->nEdgePlus = (int) ( pEdgePlus - pBNS->edge );
    3770                 :             :             }
    3771         [ #  # ]:           0 :             if (pEdge)
    3772                 :             :             {
    3773                 :           0 :                 pTCGroups->nEdge4charge = (int) ( pEdge - pBNS->edge );
    3774                 :             :             }
    3775                 :             : 
    3776                 :             :             /* set total charge */
    3777                 :             : 
    3778   [ #  #  #  # ]:           0 :             if (pVert && pEdge)
    3779                 :             :             {
    3780                 :             :                 /* do not check rescaps for now */
    3781         [ #  # ]:           0 :                 if (cg_charge > 0)
    3782                 :             :                 {
    3783                 :           0 :                     pVertPlusMinus->st_edge.cap += cg_charge;
    3784                 :           0 :                     tot_st_cap += cg_charge;
    3785                 :           0 :                     pVertPlusMinus->st_edge.cap0 = pVertPlusMinus->st_edge.cap;
    3786                 :             :                 }
    3787                 :             : 
    3788         [ #  # ]:           0 :                 if (cg_charge < 0)
    3789                 :             :                 {
    3790                 :           0 :                     pVert->st_edge.cap -= cg_charge;
    3791                 :           0 :                     tot_st_cap -= cg_charge;
    3792                 :           0 :                     pVert->st_edge.cap0 = pVert->st_edge.cap;
    3793                 :             : 
    3794         [ #  # ]:           0 :                     if (pEdge->cap - pEdge->flow + cg_charge < 0)
    3795                 :             :                     {
    3796                 :             :                         /* 2006-02-06: increase edge capacity to avoid clogging */
    3797                 :           0 :                         pEdge->cap = pEdge->flow - cg_charge;
    3798                 :             :                     }
    3799                 :             :                 }
    3800                 :           0 :                 pTCGroups->added_charge = cg_charge;
    3801                 :             :             }
    3802   [ #  #  #  #  :           0 :             if (!cg_charge || ( pVert && pEdge ))
                   #  # ]
    3803                 :             :             {
    3804                 :           0 :                 ret = 2;
    3805                 :             :             }
    3806                 :             :         }
    3807                 :             : 
    3808                 :           0 :         AddRadicalToMetal( &tot_st_cap, &tot_st_flow, pSrm, pBNS, pTCGroups );
    3809                 :             : 
    3810                 :             : 
    3811                 :           0 :         pBNS->num_edges = cur_num_edges;
    3812                 :           0 :         pBNS->num_vertices = cur_num_vertices;
    3813                 :           0 :         pBNS->num_c_groups = num_cg;
    3814                 :           0 :         pBNS->tot_st_cap = tot_st_cap;
    3815                 :           0 :         pBNS->tot_st_flow = tot_st_flow;
    3816                 :             :     }
    3817                 :             : 
    3818                 :           0 : exit_function:
    3819                 :           0 :     return ret;
    3820                 :             : }
    3821                 :             : 
    3822                 :             : 
    3823                 :             : /********************************************************************************/
    3824                 :           0 : int nNumEdgesToCnVertex( MY_CONST C_NODE *pCN, int len, int v )
    3825                 :             : {
    3826                 :           0 :     int i, j, n, num_edges, v1 = v + 1;
    3827         [ #  # ]:           0 :     for (i = 0, num_edges = 0; i < len; i++)
    3828                 :             :     {
    3829   [ #  #  #  # ]:           0 :         for (j = 0; j < MAX_CN_VAL && ( n = pCN[i].e[j].neigh ); j++)
    3830                 :             :         {
    3831   [ #  #  #  # ]:           0 :             num_edges += ( i == v || n == v1 );
    3832                 :             :         }
    3833                 :             :     }
    3834                 :           0 :     return num_edges;
    3835                 :             : }
    3836                 :             : 
    3837                 :             : 
    3838                 :             : /*********************************************************************************
    3839                 :             : BN_STRUCT* AllocateAndInitTCGBnStruct( StrFromINChI *pStruct, VAL_AT *pVA,
    3840                 :             :                                        ALL_TC_GROUPS *pTCGroups,
    3841                 :             :                                        int nMaxAddAtoms, int nMaxAddEdges,
    3842                 :             :                                        int max_altp, int *pNum_changed_bonds )
    3843                 :             : allocate BN_STRUCT that has:
    3844                 :             : 
    3845                 :             :   pBNS->max_vertices = pTCGroups->nVertices + nMaxAddAtoms
    3846                 :             :   pBNS->max_edges    = pTCGroups->nEdges +
    3847                 :             :                        pBNS->max_vertices * (nMaxAddEdges + NUM_KINDS_OF_GROUPS)
    3848                 :             :   pBNS->max_iedges   = 2*pBNS->max_edges + pTCGroups->nAddIedges
    3849                 :             : 
    3850                 :             :   pBNS->len_alt_path = pBNS->max_vertices + iALTP_HDR_LEN + 1 +
    3851                 :             :                        max( pBNS->max_vertices/2, 16 )
    3852                 :             :   pBNS->max_altp     = max_altp
    3853                 :             : 
    3854                 :             : other members:
    3855                 :             : 
    3856                 :             :   pBNS->num_atoms       = num_atoms;
    3857                 :             :   pBNS->num_bonds       = num_bonds;
    3858                 :             :   pBNS->num_added_atoms = 0;
    3859                 :             :   pBNS->num_t_groups    = 0;
    3860                 :             :   pBNS->num_c_groups    = 0;
    3861                 :             :   pBNS->nMaxAddAtoms    = nMaxAddAtoms;
    3862                 :             :   pBNS->nMaxAddEdges    = nMaxAddEdges;
    3863                 :             : 
    3864                 :             : atom vertices and bond edges:
    3865                 :             :   --- vertex(atom) ---
    3866                 :             :   st_cap  = (at[].chem_bonds_valence - at[].valence) + pVA[].cInitFreeValences
    3867                 :             :   st_flow = SUM{bond_orders; ALT_BOND counted as SINGLE} - at[].valence
    3868                 :             :   --- edge(bond) ---
    3869                 :             :   flow    = bond_order - 1; for ALT_BOND flow = 0
    3870                 :             :   cap     = min(min(st_cap of neighbors),2); for ALT_BOND cap = 1
    3871                 :             :   max number of edges per atom = number of bonds +
    3872                 :             :                              number of edges to ChargeStruct +
    3873                 :             :                              1 (if atom is a tautomeric endpoint) +
    3874                 :             :                              nMaxAddEdges
    3875                 :             :   --- NOTE ---
    3876                 :             :   Here are not included nDelta(dots) from ChargeStruct and flow to ChargeStruct
    3877                 :             : 
    3878                 :             :  *********************************************************************************/
    3879                 :           0 : BN_STRUCT* AllocateAndInitTCGBnStruct( StrFromINChI *pStruct, VAL_AT *pVA,
    3880                 :             :                                        ALL_TC_GROUPS *pTCGroups,
    3881                 :             :                                        int nMaxAddAtoms, int nMaxAddEdges,
    3882                 :             :                                        int max_altp, int *pNum_changed_bonds )
    3883                 :             : {
    3884                 :           0 :     inp_ATOM *at = pStruct->at;
    3885                 :           0 :     int          num_atoms = pStruct->num_atoms;
    3886                 :           0 :     ICHICONST SRM *pSrm = pStruct->pSrm;
    3887                 :             : 
    3888                 :           0 :     BN_STRUCT   *pBNS = NULL;
    3889                 :             :     BNS_VERTEX  *vert;
    3890                 :             :     BNS_IEDGE   *iedge;
    3891                 :             : 
    3892                 :           0 :     int    neigh, num_changed_bonds = 0;
    3893                 :             :     U_CHAR bond_type, bond_mark;
    3894                 :             :     int bNeedsFlower1, bNeedsFlower2, min_order;
    3895                 :             : 
    3896                 :             :     int i, j, k, m, n_edges, num_bonds, num_edges;
    3897                 :             :     int f1, f2, c1, c2, edge_cap, edge_flow, st_cap, st_flow, flag_alt_bond;
    3898                 :             :     int tot_st_cap, tot_st_flow;
    3899                 :             :     int max_tg, max_edges, max_vertices, len_alt_path, max_iedges, num_iedges, num_altp;
    3900                 :             : 
    3901                 :             :     /* count vertices */
    3902                 :           0 :     max_tg = pTCGroups->num_tgroups;
    3903                 :             :     /* +1 for a super-tautomeric group */
    3904                 :             :     /* max_vertices = num_atoms + nMaxAddAtoms + max_tg + 1; */
    3905                 :           0 :     max_vertices = pTCGroups->nVertices + nMaxAddAtoms;
    3906                 :             : 
    3907                 :             :     /* count edges */
    3908                 :           0 :     num_changed_bonds = 0;
    3909                 :           0 :     num_bonds = pTCGroups->num_bonds;
    3910                 :             : 
    3911                 :             :     /* each atom has enough edges to belong to a tautomeric group + nMaxAddEdges */
    3912                 :             :     /* number of atoms is large enough to accommodate max. possible number of t-groups + nMaxAddAtoms */
    3913                 :             :     /* max_altp cannot be larger than BN_MAX_ALTP = 16 */
    3914                 :           0 :     num_edges = pTCGroups->nEdges;
    3915                 :             : 
    3916                 :             :     /* +max_tg for edges between t-groups and super-tautomeric group */
    3917                 :           0 :     max_edges = num_edges + ( nMaxAddEdges + NUM_KINDS_OF_GROUPS )*max_vertices;
    3918                 :           0 :     max_iedges = 2 * max_edges + pTCGroups->nAddIedges;
    3919                 :           0 :     len_alt_path = max_vertices + iALTP_HDR_LEN + 1; /* may overflow if an edge is traversed in 2 directions */
    3920         [ #  # ]:           0 :     len_alt_path += inchi_max( max_vertices / 2, 16 ); /* to avoid the overflow */
    3921                 :             : 
    3922         [ #  # ]:           0 :     if (!(pBNS = (BN_STRUCT*)inchi_calloc(1, sizeof(BN_STRUCT))) ||
    3923         [ #  # ]:           0 :         !(pBNS->edge = (BNS_EDGE*)inchi_calloc(max_edges, sizeof(BNS_EDGE))) ||
    3924         [ #  # ]:           0 :         !(pBNS->vert = (BNS_VERTEX*)inchi_calloc(max_vertices, sizeof(BNS_VERTEX))) ||
    3925         [ #  # ]:           0 :         !(pBNS->iedge = (BNS_IEDGE*)inchi_calloc(max_iedges, sizeof(BNS_IEDGE))))
    3926                 :             :     {
    3927                 :           0 :         return DeAllocateBnStruct( pBNS );
    3928                 :             :     }
    3929                 :             : 
    3930                 :             :     /* alt path init (standard spell) */
    3931   [ #  #  #  # ]:           0 :     for (num_altp = 0; num_altp < max_altp && num_altp < BN_MAX_ALTP; num_altp++)
    3932                 :             :     {
    3933         [ #  # ]:           0 :         if (!( pBNS->altp[num_altp] = (BNS_ALT_PATH*) inchi_calloc( len_alt_path, sizeof( BNS_ALT_PATH ) ) ))
    3934                 :             :         {
    3935                 :           0 :             return DeAllocateBnStruct( pBNS );
    3936                 :             :         }
    3937                 :           0 :         ALTP_ALLOCATED_LEN( pBNS->altp[num_altp] ) = len_alt_path;
    3938                 :           0 :         pBNS->len_alt_path = len_alt_path;  /* ??? duplication ??? */
    3939                 :             :         /* re-init */
    3940                 :           0 :         ALTP_DELTA( pBNS->altp[num_altp] ) = 0;
    3941                 :           0 :         ALTP_START_ATOM( pBNS->altp[num_altp] ) = NO_VERTEX;
    3942                 :           0 :         ALTP_END_ATOM( pBNS->altp[num_altp] ) = NO_VERTEX;
    3943                 :           0 :         ALTP_PATH_LEN( pBNS->altp[num_altp] ) = 0;
    3944                 :             :     }
    3945                 :           0 :     pBNS->alt_path = NULL;
    3946                 :           0 :     pBNS->num_altp = 0;
    3947                 :           0 :     pBNS->max_altp = num_altp;
    3948                 :             : 
    3949                 :             : 
    3950                 :             :     /* fill vertices (no connectivity) */
    3951                 :           0 :     iedge = pBNS->iedge;
    3952                 :           0 :     num_iedges = 0;
    3953                 :           0 :     tot_st_cap = tot_st_flow = 0;
    3954         [ #  # ]:           0 :     for (i = 0; i < num_atoms; i++)
    3955                 :             :     {
    3956                 :             :         /* count edges incident to pBNS->vert[i] */
    3957                 :           0 :         k = at[i].valence + ( at[i].endpoint != 0 ) + ( nMaxAddEdges /*+ NUM_KINDS_OF_GROUPS*/ );
    3958         [ #  # ]:           0 :         if (( j = pVA[i].cnListIndex - 1 ) >= 0)
    3959                 :             :         {
    3960                 :             :             /* add number of neighbors in the ChargeStruct */
    3961                 :           0 :             k += nNumEdgesToCnVertex( cnList[j].pCN, cnList[j].len, 0 );
    3962                 :             :         }
    3963                 :             :         /* set max number of edges for the vertex */
    3964                 :           0 :         pBNS->vert[i].max_adj_edges = k;
    3965                 :           0 :         pBNS->vert[i].iedge = iedge;
    3966                 :           0 :         iedge += k;
    3967                 :             :         /* add atom vertex cap */
    3968                 :           0 :         st_cap = 0;
    3969                 :           0 :         st_flow = 0;
    3970                 :           0 :         bNeedsFlower1 = AtomStcapStflow( at, pVA, pSrm, i, &c1, &f1, NULL, NULL );
    3971                 :             :         /* pVA[i].cNumBondsToMetal = bNeedsFlower1; */
    3972                 :             :         /* GetAtomStCapFlow( at, pVA, pSrm, i, &c1, &f1 ); */
    3973                 :           0 :         st_cap += c1;
    3974         [ #  # ]:           0 :         st_cap += bNeedsFlower1 ? 0 : pVA[i].cInitFreeValences;
    3975                 :           0 :         pBNS->vert[i].st_edge.cap = st_cap; /* the 1st time st_cap is set */
    3976                 :           0 :         pBNS->vert[i].st_edge.cap0 = pBNS->vert[i].st_edge.cap;
    3977                 :           0 :         tot_st_cap += st_cap;
    3978                 :             :     }
    3979                 :             : 
    3980                 :           0 :     num_iedges = (int) ( iedge - pBNS->iedge );
    3981         [ #  # ]:           0 :     if (max_iedges - num_iedges < ( nMaxAddEdges + NUM_KINDS_OF_GROUPS )*max_vertices)
    3982                 :             :     {
    3983                 :           0 :         return DeAllocateBnStruct( pBNS );
    3984                 :             :     }
    3985                 :             : 
    3986                 :           0 :     pBNS->num_atoms = num_atoms;      /* number of real atoms */
    3987                 :           0 :     pBNS->num_added_atoms = 0;
    3988                 :           0 :     pBNS->num_t_groups = 0;              /* number of added t-groups */
    3989                 :           0 :     pBNS->num_c_groups = 0;
    3990                 :           0 :     pBNS->nMaxAddAtoms = nMaxAddAtoms;
    3991                 :           0 :     pBNS->nMaxAddEdges = nMaxAddEdges;
    3992                 :             : 
    3993                 :           0 :     pBNS->num_vertices = num_atoms;      /* current number of vertices, in general a sum of
    3994                 :             :                                                pBNS->num_atoms
    3995                 :             :                                                pBNS->num_t_groups
    3996                 :             :                                                number of c-groups
    3997                 :             :                                                number of auxiliary vertices
    3998                 :             :                                                pBNS->num_added_atoms
    3999                 :             :                                             */
    4000                 :           0 :     pBNS->max_vertices = max_vertices;
    4001                 :             : 
    4002                 :             : 
    4003                 :           0 :     pBNS->num_bonds = num_bonds;      /* number of real edges (bonds) */
    4004                 :           0 :     pBNS->max_edges = max_edges;
    4005                 :           0 :     pBNS->max_iedges = max_iedges;
    4006                 :             : 
    4007                 :             : 
    4008                 :             :     /*
    4009                 :             :        To remove t-groups and added atoms:
    4010                 :             : 
    4011                 :             :         for ( i = 0; i < pBNS->num_atoms; i ++ )
    4012                 :             :         {
    4013                 :             :             for ( j = pBNS->vert[i].num_adj_edges-1; 0 <= j; j -- )
    4014                 :             :             {
    4015                 :             :                 k = pBNS->edge[pBNS->vert[i].iedge[j]].neighbor12 ^ i;
    4016                 :             :                 if ( pBNS->vert[k].type & BNS_VERT_TYPE_ATOM )
    4017                 :             :                 {
    4018                 :             :                     pBNS->vert[i].num_adj_edges = j+1;
    4019                 :             :                     break;
    4020                 :             :                 }
    4021                 :             :             }
    4022                 :             :         }
    4023                 :             : 
    4024                 :             :        pBNS->num_vertices    = pBNS->num_atoms;
    4025                 :             :        pBNS->num_edges       = pBNS->num_bonds;
    4026                 :             :        pBNS->num_added_atoms = 0;
    4027                 :             :        pBNS->num_t_groups    = 0;
    4028                 :             :        pBNS->num_added_edges = 0;
    4029                 :             : 
    4030                 :             :        ALTP_DELTA(pBNS->alt_path)      = 0;
    4031                 :             :        ALTP_START_ATOM(pBNS->alt_path) = NO_VERTEX;
    4032                 :             :        ALTP_END_ATOM(pBNS->alt_path)   = NO_VERTEX;
    4033                 :             :        ALTP_PATH_LEN(pBNS->alt_path)   = 0;
    4034                 :             : 
    4035                 :             :     */
    4036                 :             : 
    4037                 :             : 
    4038                 :             :     /* add and fill edges and connectivity */
    4039         [ #  # ]:           0 :     for (i = 0, n_edges = 0; i < num_atoms; i++)
    4040                 :             :     {
    4041                 :           0 :         vert = pBNS->vert + i; /* pointer to the ith vertex */
    4042                 :           0 :         st_cap = 0;
    4043                 :           0 :         st_flow = 0;
    4044                 :           0 :         flag_alt_bond = 0;
    4045         [ #  # ]:           0 :         for (j = 0; j < at[i].valence; j++)
    4046                 :             :         {
    4047                 :           0 :             neigh = at[i].neighbor[j];
    4048                 :             :             /* find this bond at the neighbor */
    4049         [ #  # ]:           0 :             for (k = 0; k < at[neigh].valence; k++)
    4050                 :             :             {
    4051         [ #  # ]:           0 :                 if (at[neigh].neighbor[k] == i)
    4052                 :             :                 {
    4053                 :           0 :                     break;
    4054                 :             :                 }
    4055                 :             :             }
    4056                 :           0 :             bond_type = ( at[i].bond_type[j] & BOND_TYPE_MASK );
    4057                 :           0 :             bond_mark = ( at[i].bond_type[j] & ~BOND_TYPE_MASK );
    4058   [ #  #  #  #  :           0 :             if (bond_type != BOND_SINGLE && bond_type != BOND_DOUBLE && bond_type != BOND_TRIPLE)
                   #  # ]
    4059                 :             :             {
    4060                 :             :                 /* make unknown bonds single */
    4061                 :           0 :                 bond_type = BOND_SINGLE;
    4062                 :           0 :                 at[i].bond_type[j] = bond_mark | bond_type;
    4063                 :           0 :                 num_changed_bonds++;
    4064                 :             :             }
    4065         [ #  # ]:           0 :             if (neigh > i)
    4066                 :             :             {
    4067                 :             :                 /* this is the first time we encounter this bond */
    4068                 :           0 :                 bNeedsFlower1 = AtomStcapStflow( at, pVA, pSrm, i, &c1, &f1, NULL, NULL );
    4069                 :             :                 /* GetAtomStCapFlow( at, pVA, pSrm, i, &c1, &f1 ); */
    4070         [ #  # ]:           0 :                 c1 += bNeedsFlower1 ? 0 : pVA[i].cInitFreeValences;  /* elevate cap to the lowest valence in ChargeStruct */
    4071                 :           0 :                 bNeedsFlower2 = AtomStcapStflow( at, pVA, pSrm, neigh, &c2, &f2, NULL, NULL );
    4072                 :             :                 /* GetAtomStCapFlow( at, pVA, pSrm, neigh, &c2, &f2 ); */
    4073         [ #  # ]:           0 :                 c2 += bNeedsFlower2 ? 0 : pVA[neigh].cInitFreeValences; /* elevate cap to the lowest valence in ChargeStruct */
    4074                 :             : 
    4075                 :             :                 /* at this point -O would have st_cap=st_flow=0 because the lowest valence=1 for charge=-1 */
    4076                 :             :                 /* however, if -O belongs to a t-group its cap would be 1, flow = 0 */
    4077                 :             :                 /*f1 = MAX_AT_FLOW(at[i]);*/
    4078                 :             :                 /*f2 = MAX_AT_FLOW(at[neigh]);*/
    4079                 :             : 
    4080                 :           0 :                 edge_flow = BondFlowMaxcapMinorder( at, pVA, pSrm, i, j, &edge_cap, &min_order, NULL );
    4081                 :             : 
    4082                 :           0 :                 pBNS->edge[n_edges].neighbor1 = (AT_NUMB) i;
    4083                 :           0 :                 pBNS->edge[n_edges].neighbor12 = (AT_NUMB) ( i ^ neigh );
    4084                 :           0 :                 pBNS->edge[n_edges].flow =
    4085                 :           0 :                     pBNS->edge[n_edges].flow0 = edge_flow;
    4086                 :           0 :                 pBNS->edge[n_edges].cap =
    4087                 :           0 :                     pBNS->edge[n_edges].cap0 = edge_cap;
    4088                 :           0 :                 pBNS->edge[n_edges].neigh_ord[0] = j;  /* iedge to neigh index at vertex[i],     i < neigh */
    4089                 :           0 :                 pBNS->edge[n_edges].neigh_ord[1] = k;  /* iedge to i     index at vertex[neigh], i < neigh */
    4090                 :           0 :                 pBNS->edge[n_edges].pass = 0;
    4091                 :           0 :                 pBNS->edge[n_edges].forbidden = 0; /* may be forbidden if edge_flow = 1: stereogenic fixed double bond */
    4092         [ #  # ]:           0 :                 if (bond_type == BOND_TYPE_DOUBLE)
    4093                 :             :                 {
    4094                 :             :                     /* forbid changing stereogenic double bonds */
    4095   [ #  #  #  # ]:           0 :                     for (m = 0; m < MAX_NUM_STEREO_BONDS && at[i].sb_parity[m]; m++)
    4096                 :             :                     {
    4097         [ #  # ]:           0 :                         if (at[i].sb_ord[m] == j)
    4098                 :             :                         {
    4099                 :           0 :                             pBNS->edge[n_edges].forbidden |= BNS_EDGE_FORBIDDEN_MASK;
    4100                 :           0 :                             break;
    4101                 :             :                         }
    4102                 :             :                     }
    4103                 :             :                 }
    4104         [ #  # ]:           0 :                 if (pBNS->vert[neigh].iedge) /* djb-rwth: fixing a NULL pointer dereference */
    4105                 :             :                 {
    4106                 :           0 :                     vert->iedge[j] = pBNS->vert[neigh].iedge[k] = n_edges++; /* same iedge index as neighbor index in at[] */
    4107                 :             :                 }
    4108                 :             :             }
    4109                 :             :             else
    4110                 :             :             {
    4111                 :             :                 /* this is the second time we encounter this bond. It was stored at */
    4112                 :           0 :                 int  iedge2 = pBNS->vert[neigh].iedge[k];
    4113                 :           0 :                 edge_cap = pBNS->edge[iedge2].cap;
    4114                 :           0 :                 edge_flow = pBNS->edge[iedge2].flow;
    4115                 :             :             }
    4116                 :           0 :             st_flow += edge_flow;
    4117                 :             :             /*
    4118                 :             :             st_cap  += edge_cap;
    4119                 :             :             */
    4120                 :             :         }
    4121                 :             : 
    4122                 :           0 :         vert->num_adj_edges = j;
    4123                 :             :         /*
    4124                 :             :         vert->st_edge.cap   =
    4125                 :             :         vert->st_edge.cap0  = st_cap;
    4126                 :             :         */
    4127                 :           0 :         vert->st_edge.flow =
    4128                 :           0 :             vert->st_edge.flow0 = st_flow;
    4129                 :           0 :         vert->type = BNS_VERT_TYPE_ATOM;
    4130                 :             :         /*
    4131                 :             :         tot_st_cap  += vert->st_edge.cap;
    4132                 :             :         */
    4133                 :           0 :         tot_st_flow += vert->st_edge.flow;
    4134                 :             :     }
    4135                 :             : 
    4136                 :           0 :     *pNum_changed_bonds = num_changed_bonds / 2;
    4137                 :             : 
    4138                 :           0 :     pBNS->num_edges = n_edges;   /* number of edges */
    4139                 :           0 :     pBNS->num_iedges = num_iedges;
    4140                 :           0 :     pBNS->num_added_edges = 0;
    4141                 :             : 
    4142                 :           0 :     pBNS->tot_st_cap = tot_st_cap;
    4143                 :           0 :     pBNS->tot_st_flow = tot_st_flow;
    4144                 :             : 
    4145                 :             : /* exit_function: */
    4146                 :             : 
    4147                 :           0 :     return pBNS;
    4148                 :             : }
    4149                 :             : 
    4150                 :             : 
    4151                 :             : /****************************************************************************/
    4152                 :           0 : void IncrZeroBondsAndClearEndpts( inp_ATOM *at, int num_at, int iComponent )
    4153                 :             : {
    4154                 :             :     int i, j;
    4155         [ #  # ]:           0 :     for (i = 0; i < num_at; i++)
    4156                 :             :     {
    4157                 :           0 :         at[i].endpoint = 0;
    4158                 :           0 :         at[i].component = iComponent;
    4159         [ #  # ]:           0 :         for (j = 0; j < at[i].valence; j++)
    4160                 :             :         {
    4161         [ #  # ]:           0 :             if (!at[i].bond_type[j])
    4162                 :             :             {
    4163                 :           0 :                 at[i].bond_type[j] = BOND_TYPE_SINGLE;
    4164                 :           0 :                 at[i].chem_bonds_valence += BOND_TYPE_SINGLE;
    4165                 :             :             }
    4166                 :             :         }
    4167                 :             :     }
    4168                 :           0 : }
    4169                 :             : 
    4170                 :             : 
    4171                 :             : /****************************************************************************/
    4172                 :           0 : void IncrZeroBonds( inp_ATOM *at, int num_at, int iComponent )
    4173                 :             : {
    4174                 :             :     int i, j;
    4175         [ #  # ]:           0 :     for (i = 0; i < num_at; i++)
    4176                 :             :     {
    4177                 :           0 :         at[i].component = iComponent;
    4178         [ #  # ]:           0 :         for (j = 0; j < at[i].valence; j++)
    4179                 :             :         {
    4180         [ #  # ]:           0 :             if (!at[i].bond_type[j])
    4181                 :             :             {
    4182                 :           0 :                 at[i].bond_type[j] = BOND_TYPE_SINGLE;
    4183                 :           0 :                 at[i].chem_bonds_valence += BOND_TYPE_SINGLE;
    4184                 :             :             }
    4185                 :             :         }
    4186                 :             :     }
    4187                 :           0 : }
    4188                 :             : 
    4189                 :             : 
    4190                 :             : /****************************************************************************/
    4191                 :           0 : void ClearEndpts( inp_ATOM *at, int num_at )
    4192                 :             : {
    4193                 :             :     int i;
    4194         [ #  # ]:           0 :     for (i = 0; i < num_at; i++)
    4195                 :             :     {
    4196                 :           0 :         at[i].endpoint = 0;
    4197                 :             :     }
    4198                 :           0 : }
    4199                 :             : 
    4200                 :             : 
    4201                 :             : /****************************************************************************/
    4202                 :             : #define ANY_VERT_TYPE(X) (((X) & (BNS_VERT_TYPE_ATOM | BNS_VERT_TYPE_TGROUP | BNS_VERT_TYPE_C_GROUP)) && \
    4203                 :             :                            !((X) & (BNS_VERT_TYPE_SUPER_TGROUP)))
    4204                 :             : #define GRP_VERT_TYPE(X) (((X) & (BNS_VERT_TYPE_TGROUP | BNS_VERT_TYPE_C_GROUP)) && \
    4205                 :             :                            !((X) & (BNS_VERT_TYPE_SUPER_TGROUP)))
    4206                 :             : 
    4207                 :             : typedef struct tagVertexFlow
    4208                 :             : {
    4209                 :             :     int        type;
    4210                 :             :     Vertex     v;
    4211                 :             :     EdgeIndex  e_In;
    4212                 :             :     EdgeIndex  e_Out;
    4213                 :             :     EdgeFlow   delta_In;
    4214                 :             :     EdgeFlow   delta_Out;
    4215                 :             :     Vertex     bUsed; /* indicates the charge edge belongs to already processed atom */
    4216                 :             : } VF;
    4217                 :             : #define NUM_VF 3
    4218                 :             : #define VF_USED_IN  1
    4219                 :             : #define VF_USED_OUT 2
    4220                 :             : #define VF_USED_ALL (VF_USED_IN | VF_USED_OUT)
    4221                 :             : 
    4222                 :             : 
    4223                 :             : 
    4224                 :             : int GetDeltaChargeFromVF( BN_STRUCT *pBNS, VAL_AT *pVA, VF *vf );
    4225                 :             : 
    4226                 :             : 
    4227                 :             : 
    4228                 :             : /****************************************************************************/
    4229                 :           0 : int GetDeltaChargeFromVF( BN_STRUCT *pBNS, VAL_AT *pVA, VF *vf )
    4230                 :             : {
    4231                 :           0 :     int i, v = NO_VERTEX;
    4232   [ #  #  #  #  :           0 :     int ieIn1 = ( !( vf->bUsed & VF_USED_IN ) && vf->e_In >= 0 && vf->delta_In ) ? vf->e_In + 1 : NO_VERTEX;
                   #  # ]
    4233   [ #  #  #  #  :           0 :     int ieOut1 = ( !( vf->bUsed & VF_USED_OUT ) && vf->e_Out >= 0 && vf->delta_Out ) ? vf->e_Out + 1 : NO_VERTEX;
                   #  # ]
    4234                 :             :     int nInitCharge, nPlusFlow, nMinusFlow, nDeltaCharge, nNumDeltaCharge, eCPlus, eCMinus;
    4235                 :             : 
    4236         [ #  # ]:           0 :     if (!( vf->type & BNS_VERT_TYPE_C_GROUP ) ||
    4237   [ #  #  #  # ]:           0 :         ( vf->type & BNS_VERT_TYPE_SUPER_TGROUP ) ||
    4238         [ #  # ]:           0 :         ( ieIn1 == NO_VERTEX && ieOut1 == NO_VERTEX ))
    4239                 :             :     {
    4240                 :           0 :         return 0;
    4241                 :             :     }
    4242         [ #  # ]:           0 :     if (vf->type & BNS_VERT_TYPE_C_NEGATIVE)
    4243                 :             :     {
    4244                 :             :         /* negative charge edge */
    4245         [ #  # ]:           0 :         for (i = 0; i < pBNS->num_atoms; i++)
    4246                 :             :         {
    4247   [ #  #  #  # ]:           0 :             if (pVA[i].nCMinusGroupEdge == ieIn1 || pVA[i].nCMinusGroupEdge == ieOut1)
    4248                 :             :             {
    4249                 :           0 :                 v = i;
    4250                 :           0 :                 break;
    4251                 :             :             }
    4252                 :             :         }
    4253                 :             :     }
    4254                 :             :     else
    4255                 :             :     {
    4256                 :             :         /* positive charge edge */
    4257         [ #  # ]:           0 :         for (i = 0; i < pBNS->num_atoms; i++)
    4258                 :             :         {
    4259   [ #  #  #  # ]:           0 :             if (pVA[i].nCPlusGroupEdge == ieIn1 || pVA[i].nCPlusGroupEdge == ieOut1)
    4260                 :             :             {
    4261                 :           0 :                 v = i;
    4262                 :           0 :                 break;
    4263                 :             :             }
    4264                 :             :         }
    4265                 :             :     }
    4266                 :             : 
    4267         [ #  # ]:           0 :     if (v == NO_VERTEX)
    4268                 :           0 :         return 0;
    4269                 :             : 
    4270                 :           0 :     nInitCharge = pVA[v].cInitCharge;
    4271                 :           0 :     nPlusFlow = nMinusFlow = 0;
    4272                 :           0 :     nNumDeltaCharge = 0;
    4273                 :             : 
    4274         [ #  # ]:           0 :     if (( eCPlus = pVA[v].nCPlusGroupEdge - 1 ) >= 0)
    4275                 :             :     {
    4276                 :           0 :         nPlusFlow = pBNS->edge[eCPlus].cap
    4277                 :           0 :             - pBNS->edge[eCPlus].flow;
    4278                 :             :     }
    4279                 :             : 
    4280         [ #  # ]:           0 :     if (( eCMinus = pVA[v].nCMinusGroupEdge - 1 ) >= 0)
    4281                 :             :     {
    4282                 :           0 :         nMinusFlow = -pBNS->edge[eCMinus].flow;
    4283                 :             :     }
    4284                 :           0 :     nInitCharge += nPlusFlow + nMinusFlow;
    4285                 :             : 
    4286                 :           0 :     nDeltaCharge = 0;
    4287                 :             : 
    4288         [ #  # ]:           0 :     if (!( vf[0].bUsed & VF_USED_OUT ))
    4289                 :             :     {
    4290   [ #  #  #  # ]:           0 :         if (vf[0].e_Out == eCPlus || vf[0].e_Out == eCMinus)
    4291                 :             :         {
    4292                 :           0 :             nDeltaCharge -= vf[0].delta_Out;
    4293                 :           0 :             vf[0].bUsed |= VF_USED_OUT;
    4294                 :             :         }
    4295                 :             :     }
    4296                 :             : 
    4297         [ #  # ]:           0 :     if (!( vf[0].bUsed & VF_USED_IN ))
    4298                 :             :     {
    4299   [ #  #  #  # ]:           0 :         if (vf[0].e_In == eCPlus || vf[0].e_In == eCMinus)
    4300                 :             :         {
    4301                 :           0 :             nDeltaCharge -= vf[0].delta_In;
    4302                 :           0 :             vf[0].bUsed |= VF_USED_IN;
    4303                 :             :         }
    4304                 :             :     }
    4305                 :             : 
    4306   [ #  #  #  # ]:           0 :     if (!nInitCharge && nDeltaCharge)
    4307                 :             :     {
    4308                 :           0 :         nNumDeltaCharge++;
    4309                 :             :     }
    4310   [ #  #  #  # ]:           0 :     else if (nInitCharge && 0 == nInitCharge + nDeltaCharge)
    4311                 :             :     {
    4312                 :           0 :         nNumDeltaCharge--;
    4313                 :             :     }
    4314                 :             : 
    4315                 :           0 :     return nNumDeltaCharge;
    4316                 :             : }
    4317                 :             : 
    4318                 :             : 
    4319                 :             : /****************************************************************************/
    4320                 :           0 : int EvaluateChargeChanges( BN_STRUCT *pBNS, VAL_AT *pVA, int *pnDeltaH, int *pnDeltaCharge, int *pnNumVisitedAtoms )
    4321                 :             : {
    4322                 :           0 :     int       pass, i, j, v0, v1, v2, v, ineigh1, /*ineigh2,*/ vLast, n, delta, ret, ie, err = 0;
    4323                 :             :     BNS_EDGE *edge;
    4324                 :             :     int       nDeltaH, nDeltaCharge, iPrev, nInitCharge, nPlusFlow, nMinusFlow;
    4325                 :           0 :     int       nNumDeltaH = 0;
    4326                 :           0 :     int       nNumDeltaCharge = 0;
    4327                 :           0 :     int       nNumVisitedAtoms = 0;
    4328                 :             :     VF   vf[NUM_VF + 1];
    4329                 :             : 
    4330                 :           0 :     *pnDeltaH = 0;
    4331                 :           0 :     *pnDeltaCharge = 0;
    4332                 :           0 :     *pnNumVisitedAtoms = 0;
    4333                 :             : 
    4334         [ #  # ]:           0 :     for (pass = pBNS->num_altp - 1, ret = 0; 0 <= pass; pass--)
    4335                 :             :     {
    4336                 :             : 
    4337                 :           0 :         pBNS->alt_path = pBNS->altp[pass];
    4338                 :           0 :         v1 = ALTP_START_ATOM( pBNS->alt_path );
    4339                 :           0 :         n = ALTP_PATH_LEN( pBNS->alt_path );
    4340                 :           0 :         delta = ALTP_DELTA( pBNS->alt_path );
    4341                 :           0 :         vLast = ALTP_END_ATOM( pBNS->alt_path );
    4342                 :           0 :         v0 = v2 = NO_VERTEX;
    4343                 :             : 
    4344                 :           0 :         memset( vf, 0, sizeof( vf ) ); /* djb-rwth: memset_s C11/Annex K variant? */
    4345         [ #  # ]:           0 :         for (i = 0; i < (int) ( sizeof( vf ) / sizeof( vf[0] ) ); i++)
    4346                 :             :         {
    4347                 :           0 :             vf[i].v = NO_VERTEX; /* = -2 */
    4348                 :           0 :             vf[i].e_In = NO_VERTEX;
    4349                 :           0 :             vf[i].e_Out = NO_VERTEX;
    4350                 :             :         }
    4351                 :           0 :         iPrev = 0;
    4352                 :             :         /* add to the queue */
    4353   [ #  #  #  # ]:           0 :         if (ANY_VERT_TYPE( pBNS->vert[v1].type ))
    4354                 :             :         {
    4355         [ #  # ]:           0 :             if (pBNS->vert[v1].type & BNS_VERT_TYPE_ATOM)
    4356                 :             :             {
    4357                 :           0 :                 nNumVisitedAtoms++;
    4358                 :             :             }
    4359                 :           0 :             vf[2].type = pBNS->vert[v1].type;
    4360                 :           0 :             vf[2].v = v1;
    4361                 :           0 :             iPrev = 2;
    4362                 :             :         }
    4363                 :             : 
    4364                 :           0 :         nNumDeltaH = 0;
    4365                 :           0 :         nNumDeltaCharge = 0;
    4366                 :           0 :         nNumVisitedAtoms = 0;
    4367                 :             : 
    4368         [ #  # ]:           0 :         for (i = 0; i < n; i++, delta = -delta, v0 = v1, v1 = v2) /* djb-rwth: removing redundant code */
    4369                 :             :         {
    4370                 :           0 :             ineigh1 = ALTP_THIS_ATOM_NEIGHBOR( pBNS->alt_path, i );  /* v1->v2 neighbor */
    4371                 :             :             /*ineigh2 = ALTP_NEXT_ATOM_NEIGHBOR(pBNS->alt_path, i);*/  /* v2->v1 neighbor */
    4372                 :           0 :             edge = pBNS->edge + ( ie = pBNS->vert[v1].iedge[ineigh1] );
    4373                 :             :             /* follow the BN Structure, not the inp_ATOM, to take care of swithching to
    4374                 :             :                t-groups, c-groups or other fictitious edges/vertices
    4375                 :             :             */
    4376                 :             : 
    4377         [ #  # ]:           0 :             if (iPrev)
    4378                 :             :             {
    4379                 :             :                 /* add exit delta and edge */
    4380                 :           0 :                 vf[2].e_Out = ie;
    4381                 :           0 :                 vf[2].delta_Out = delta;
    4382                 :             :             }
    4383                 :             : 
    4384                 :           0 :             v2 = edge->neighbor12 ^ v1;  /* next vertex */
    4385         [ #  # ]:           0 :             if (pBNS->vert[v2].type & BNS_VERT_TYPE_ATOM)
    4386                 :             :             {
    4387                 :           0 :                 nNumVisitedAtoms++;
    4388                 :             :             }
    4389                 :             : 
    4390   [ #  #  #  #  :           0 :             if (( ANY_VERT_TYPE( pBNS->vert[v2].type ) || i == n - 1 ) &&
                   #  # ]
    4391   [ #  #  #  # ]:           0 :                 ( vf[0].type & BNS_VERT_TYPE_C_GROUP ) && vf[0].bUsed != VF_USED_ALL)
    4392                 :             :             {
    4393                 :             :                 /* unused vertex is about to be discarded */
    4394                 :           0 :                 nNumDeltaCharge += GetDeltaChargeFromVF( pBNS, pVA, &vf[0] );
    4395                 :             :             }
    4396                 :             : 
    4397   [ #  #  #  # ]:           0 :             if (ANY_VERT_TYPE( pBNS->vert[v2].type ))
    4398                 :             :             {
    4399                 :             :                 /* shift the queue */
    4400                 :           0 :                 vf[0] = vf[1];
    4401                 :           0 :                 vf[1] = vf[2];
    4402                 :           0 :                 vf[2] = vf[3]; /* make vf[2] empty */
    4403                 :             :                 /* add next vertex */
    4404                 :           0 :                 vf[2].v = v2;
    4405                 :           0 :                 vf[2].type = pBNS->vert[v2].type;
    4406                 :           0 :                 vf[2].e_In = ie;
    4407                 :           0 :                 vf[2].delta_In = delta;
    4408                 :           0 :                 iPrev = 2; /* indicates a newly added vertex */
    4409                 :             :             }
    4410         [ #  # ]:           0 :             else if (i == n - 1)
    4411                 :             :             {
    4412                 :             :                 /* shift the queue */
    4413                 :           0 :                 vf[0] = vf[1];
    4414                 :           0 :                 vf[1] = vf[2];
    4415                 :           0 :                 vf[2] = vf[3]; /* make vf[2] empty */
    4416                 :           0 :                 iPrev = 1; /* indicates the last vertex */
    4417                 :             :             }
    4418                 :             :             else
    4419                 :             :             {
    4420                 :           0 :                 iPrev = 0; /* no new vertex has been added */
    4421                 :             :             }
    4422                 :             : 
    4423   [ #  #  #  # ]:           0 :             if (iPrev && ( vf[1].type & BNS_VERT_TYPE_ATOM ))
    4424                 :             :             {
    4425                 :             :                 /* a new vertex has just been added and  */
    4426                 :             :                 /* an atom is in the middle of the queue */
    4427                 :             :                 EdgeIndex eCPlus, eCMinus;
    4428                 :           0 :                 v = vf[1].v;
    4429                 :           0 :                 nInitCharge = pVA[v].cInitCharge;
    4430                 :           0 :                 nPlusFlow = nMinusFlow = 0;
    4431         [ #  # ]:           0 :                 if (( eCPlus = pVA[v].nCPlusGroupEdge - 1 ) >= 0)
    4432                 :             :                 {
    4433                 :           0 :                     nPlusFlow = pBNS->edge[eCPlus].cap
    4434                 :           0 :                         - pBNS->edge[eCPlus].flow;
    4435                 :             :                 }
    4436         [ #  # ]:           0 :                 if (( eCMinus = pVA[v].nCMinusGroupEdge - 1 ) >= 0)
    4437                 :             :                 {
    4438                 :           0 :                     nMinusFlow = -pBNS->edge[eCMinus].flow;
    4439                 :             :                 }
    4440                 :           0 :                 nInitCharge += nPlusFlow + nMinusFlow;
    4441                 :             : 
    4442                 :           0 :                 nDeltaH = nDeltaCharge = 0;
    4443                 :             : 
    4444         [ #  # ]:           0 :                 if (vf[0].type & BNS_VERT_TYPE_TGROUP)
    4445                 :             :                 {
    4446                 :           0 :                     nDeltaH -= delta;
    4447                 :             :                 }
    4448         [ #  # ]:           0 :                 else if (( vf[0].type & BNS_VERT_TYPE_C_GROUP ) &&
    4449         [ #  # ]:           0 :                          !( vf[0].bUsed & VF_USED_OUT ))
    4450                 :             :                 {
    4451   [ #  #  #  # ]:           0 :                     if (vf[0].e_Out == eCPlus || vf[0].e_Out == eCMinus)
    4452                 :             :                     {
    4453                 :           0 :                         nDeltaCharge -= vf[0].delta_Out;
    4454                 :           0 :                         vf[0].bUsed |= VF_USED_OUT;
    4455                 :             :                     }
    4456                 :             :                 }
    4457                 :             : 
    4458         [ #  # ]:           0 :                 if (vf[2].type & BNS_VERT_TYPE_TGROUP)
    4459                 :             :                 {
    4460                 :           0 :                     nDeltaH += delta;
    4461                 :             :                 }
    4462         [ #  # ]:           0 :                 else if (( vf[2].type & BNS_VERT_TYPE_C_GROUP ) &&
    4463         [ #  # ]:           0 :                          !( vf[2].bUsed & VF_USED_IN ))
    4464                 :             :                 {
    4465   [ #  #  #  # ]:           0 :                     if (vf[2].e_In == eCPlus || vf[2].e_In == eCMinus)
    4466                 :             :                     {
    4467                 :           0 :                         nDeltaCharge -= vf[2].delta_In;
    4468                 :           0 :                         vf[2].bUsed |= VF_USED_IN;
    4469                 :             :                     }
    4470                 :             :                 }
    4471                 :             : 
    4472   [ #  #  #  # ]:           0 :                 if (!nInitCharge && nDeltaCharge)
    4473                 :             :                 {
    4474                 :           0 :                     nNumDeltaCharge++;
    4475                 :             :                 }
    4476   [ #  #  #  # ]:           0 :                 else if (nInitCharge && 0 == nInitCharge + nDeltaCharge)
    4477                 :             :                 {
    4478                 :           0 :                     nNumDeltaCharge--;
    4479                 :             :                 }
    4480                 :             : 
    4481                 :           0 :                 nNumDeltaH += abs( nDeltaH );
    4482                 :             :                 /* nNumDeltaCharge += abs(nDeltaCharge); */
    4483                 :           0 :                 vf[1].bUsed = VF_USED_ALL;
    4484                 :             :             }
    4485                 :             :         }
    4486                 :             : 
    4487         [ #  # ]:           0 :         for (j = 0; j < 3; j++)
    4488                 :             :         {
    4489                 :           0 :             nNumDeltaCharge += GetDeltaChargeFromVF( pBNS, pVA, &vf[j] );
    4490                 :             :         }
    4491                 :             : 
    4492                 :           0 :         *pnDeltaH += nNumDeltaH;
    4493                 :           0 :         *pnDeltaCharge += nNumDeltaCharge;
    4494                 :           0 :         *pnNumVisitedAtoms += nNumVisitedAtoms;
    4495                 :             : 
    4496                 :             : 
    4497         [ #  # ]:           0 :         if (v2 != vLast)
    4498                 :             :         {
    4499                 :           0 :             err = BNS_PROGRAM_ERR;
    4500                 :             :         }
    4501                 :             :     }
    4502         [ #  # ]:           0 :     return err ? err : ret;
    4503                 :             : }
    4504                 :             : 
    4505                 :             : 
    4506                 :             : /****************************************************************************/
    4507                 :           0 : int RunBnsTestOnce( BN_STRUCT *pBNS, BN_DATA *pBD, VAL_AT *pVA, Vertex *pvFirst, Vertex *pvLast,
    4508                 :             :                     int *pPathLen, int *pnDeltaH, int *pnDeltaCharge, int *pnNumVisitedAtoms )
    4509                 :             : {
    4510                 :           0 :     int bChangeFlow = 0; /* do not change flow */
    4511                 :             :     int delta, ret, ret2, pass; /* djb-rwth: ignoring LLVM warning: variable used to store function return value */
    4512                 :             : 
    4513                 :           0 :     ReInitBnStructAltPaths( pBNS );
    4514                 :           0 :     pass = 0;
    4515                 :           0 :     pBNS->alt_path = pBNS->altp[pass];
    4516                 :           0 :     pBNS->num_altp = 0;
    4517                 :           0 :     pBNS->bChangeFlow = 0;
    4518                 :           0 :     delta = BalancedNetworkSearch( pBNS, pBD, bChangeFlow );
    4519         [ #  # ]:           0 :     if (delta > 0)
    4520                 :             :     {
    4521                 :           0 :         pBNS->alt_path = pBNS->altp[pass];
    4522                 :           0 :         *pvFirst = ALTP_START_ATOM( pBNS->alt_path );
    4523                 :           0 :         *pPathLen = ALTP_PATH_LEN( pBNS->alt_path );
    4524                 :           0 :         *pvLast = ALTP_END_ATOM( pBNS->alt_path );
    4525                 :           0 :         pBNS->num_altp++;
    4526                 :           0 :         ret2 = EvaluateChargeChanges( pBNS, pVA, pnDeltaH, pnDeltaCharge, pnNumVisitedAtoms ); /* djb-rwth: ignoring LLVM warning: variable used to store function return value */
    4527                 :             :     }
    4528                 :             :     else
    4529                 :             :     {
    4530                 :           0 :         *pvFirst = NO_VERTEX;
    4531                 :           0 :         *pPathLen = 0;
    4532                 :           0 :         *pvLast = NO_VERTEX;
    4533                 :           0 :         ret2 = 0;
    4534                 :             :     }
    4535                 :             : 
    4536                 :           0 :     ReInitBnStructAltPaths( pBNS );
    4537                 :             : 
    4538                 :           0 :     ret = ReInitBnData( pBD );
    4539                 :             : 
    4540         [ #  # ]:           0 :     return ( delta >= 0 && ret > 0 ) ? -ret
    4541         [ #  # ]:           0 :         : delta;
    4542                 :             : }
    4543                 :             : 
    4544                 :             : 
    4545                 :             : /****************************************************************************/
    4546                 :           0 : int RunBnsRestoreOnce( BN_STRUCT *pBNS, BN_DATA *pBD, VAL_AT *pVA, ALL_TC_GROUPS *pTCGroups )
    4547                 :             : {
    4548                 :             :     /* run BNS for the first time */
    4549                 :           0 :     int nTotalDelta = 0, ret = 0;
    4550                 :             :     int nDelta;
    4551                 :             : 
    4552                 :           0 :     ReInitBnStructAltPaths( pBNS );
    4553                 :             : 
    4554                 :             :     do
    4555                 :             :     {
    4556                 :           0 :         nDelta = RunBalancedNetworkSearch( pBNS, pBD, BNS_EF_CHNG_FLOW );
    4557   [ #  #  #  # ]:           0 :         if (IS_BNS_ERROR( nDelta ))
    4558                 :             :         {
    4559                 :           0 :             ret = nDelta;
    4560                 :           0 :             goto exit_function;
    4561                 :             :         }
    4562                 :           0 :         nTotalDelta += nDelta;
    4563                 :           0 :         ReInitBnStructAltPaths( pBNS );
    4564                 :           0 :         ret = ReInitBnData( pBD );
    4565         [ #  # ]:           0 :         if (ret > 0)
    4566                 :             :         {
    4567                 :           0 :             ret = -ret;
    4568                 :           0 :             goto exit_function;
    4569                 :             :         }
    4570                 :             :     }
    4571   [ #  #  #  # ]:           0 :     while (nDelta > 0 && ret == 0);
    4572                 :             : 
    4573                 :           0 :     pBNS->tot_st_flow += 2 * nTotalDelta;
    4574                 :             : 
    4575                 :           0 :     ret = nTotalDelta;
    4576                 :             : 
    4577                 :           0 : exit_function:
    4578                 :           0 :     return ret;
    4579                 :             : }
    4580                 :             : 
    4581                 :             : 
    4582                 :             : /****************************************************************************/
    4583                 :             : /* djb-rwth: this function is completely senseless -- discussion required */
    4584                 :           0 : int comp_cc_cand( const void *a1, const void *a2 )
    4585                 :             : {
    4586                 :           0 :     const CC_CAND *p1 = (const CC_CAND *) a1;
    4587                 :           0 :     const CC_CAND *p2 = (const CC_CAND *) a2;
    4588                 :             :     int            ret;
    4589                 :             : 
    4590         [ #  # ]:           0 :     if ((ret = (int) p2->cMetal - (int) p1->cMetal)) /* djb-rwth: addressing LLVM warning */
    4591                 :           0 :         return ret; /* metal first */
    4592         [ #  # ]:           0 :     if ((ret = (int) p2->cNumBondsToMetal - (int) p1->cNumBondsToMetal)) /* djb-rwth: addressing LLVM warning */
    4593                 :           0 :         return ret; /* connected to metal first */
    4594         [ #  # ]:           0 :     if ((ret = (int) p2->cPeriodicRowNumber - (int) p1->cPeriodicRowNumber)) /* djb-rwth: addressing LLVM warning */
    4595                 :           0 :         return ret; /* heaviest first */
    4596         [ #  # ]:           0 :     if ((ret = (int) p2->num_bonds - (int) p1->num_bonds)) /* djb-rwth: addressing LLVM warning */
    4597                 :           0 :         return ret; /* more bonds first */
    4598         [ #  # ]:           0 :     if ((ret = (int) p1->chem_valence - (int) p2->chem_valence)) /* djb-rwth: addressing LLVM warning */
    4599                 :           0 :         return ret; /* less bond order first */
    4600   [ #  #  #  # ]:           0 :     if ((!p1->cNumValenceElectrons && p2->cNumValenceElectrons)) /* djb-rwth: addressing LLVM warning */
    4601                 :           0 :         return -1; /* no valence electrons first */
    4602   [ #  #  #  # ]:           0 :     if ((!p2->cNumValenceElectrons && p1->cNumValenceElectrons)) /* djb-rwth: addressing LLVM warning */
    4603                 :           0 :         return -1; /* no valence electrons first */
    4604         [ #  # ]:           0 :     if (((int) p2->cNumValenceElectrons - (int) p1->cNumValenceElectrons)) /* djb-rwth: addressing LLVM warning */
    4605                 :           0 :         return ret; /* more valence electrons first */
    4606                 :           0 :     ret = (int) p2->iat - (int) p1->iat; /* greater canon number first */
    4607                 :             : 
    4608                 :           0 :     return ret;
    4609                 :             : }
    4610                 :             : 
    4611                 :             : 
    4612                 :             : /*****************************************************************************************************
    4613                 :             : Locate E1=C-E2 where
    4614                 :             :          e ev  are the edges
    4615                 :             : 
    4616                 :             :        E1 and E2 are atoms that belong to the same t-group
    4617                 :             :        C         is an atom that does not belong to any t-group
    4618                 :             :        e         is a forbidden edge
    4619                 :             :        ev        is not a forbidden edge
    4620                 :             : 
    4621                 :             :   Make changes so that:
    4622                 :             :        E1(d)-C(d)-E2
    4623                 :             : 
    4624                 :             :        where (d) means doublet radical
    4625                 :             : 
    4626                 :             : */
    4627                 :             : /**************************************************************************************************/
    4628                 :           0 : int get_pVA_atom_type( VAL_AT *pVA, inp_ATOM *at, int iat, int bond_type )
    4629                 :             : {
    4630                 :           0 :     int type = 0, val;
    4631         [ #  # ]:           0 :     if (pVA[iat].cNumValenceElectrons == 4)
    4632                 :             :     {
    4633         [ #  # ]:           0 :         if (pVA[iat].cPeriodicRowNumber == 1)
    4634                 :             :         {
    4635                 :           0 :             type |= EL_TYPE_C;
    4636                 :             :         }
    4637                 :             :     }
    4638                 :             : 
    4639         [ #  # ]:           0 :     else if (pVA[iat].cNumValenceElectrons == 6)
    4640                 :             :     {
    4641         [ #  # ]:           0 :         if (pVA[iat].cPeriodicRowNumber == 1)
    4642                 :             :         {
    4643                 :           0 :             type |= EL_TYPE_O;
    4644                 :             :         }
    4645         [ #  # ]:           0 :         else if (pVA[iat].cPeriodicRowNumber < 5)
    4646                 :             :         {
    4647                 :           0 :             type |= EL_TYPE_S;
    4648                 :             :         }
    4649         [ #  # ]:           0 :         if (bond_type == BOND_TYPE_SINGLE &&
    4650   [ #  #  #  # ]:           0 :             ( type & ( EL_TYPE_O | EL_TYPE_S ) ) &&
    4651         [ #  # ]:           0 :              1 == nNoMetalBondsValence( at, iat ) &&
    4652                 :           0 :              1 == nNoMetalNumBonds( at, iat ))
    4653                 :             :         {
    4654                 :           0 :             type |= EL_TYPE_OSt;
    4655                 :             :         }
    4656                 :             :     }
    4657                 :             : 
    4658         [ #  # ]:           0 :     else if (pVA[iat].cNumValenceElectrons == 5)
    4659                 :             :     {
    4660         [ #  # ]:           0 :         if (pVA[iat].cPeriodicRowNumber == 1)
    4661                 :             :         {
    4662                 :           0 :             type |= EL_TYPE_N;
    4663                 :             :         }
    4664                 :             :         else
    4665                 :             :         {
    4666                 :           0 :             type |= EL_TYPE_P;
    4667                 :             :         }
    4668                 :             :     }
    4669                 :             : 
    4670         [ #  # ]:           0 :     else if (!is_el_a_metal( pVA[iat].cPeriodicNumber ))
    4671                 :             :     {
    4672                 :           0 :         type |= EL_TYPE_X;
    4673                 :             :     }
    4674                 :             : 
    4675                 :             :     /* check for possibility to be a tautomeric endpoint (that is, be a Mobile H site) */
    4676                 :           0 :     val = get_endpoint_valence( at[iat].el_number );
    4677                 :             : 
    4678   [ #  #  #  #  :           0 :     if (val && val > at[iat].valence && !at[iat].radical &&
                   #  # ]
    4679   [ #  #  #  # ]:           0 :          -1 <= at[iat].charge && at[iat].charge <= 0 &&
    4680         [ #  # ]:           0 :          val == at[iat].chem_bonds_valence - at[iat].charge + at[iat].num_H)
    4681                 :             :     {
    4682                 :           0 :         type |= EL_TYPE_PT;
    4683                 :             :     }
    4684                 :             : 
    4685                 :           0 :     return type;
    4686                 :             : }
    4687                 :             : 
    4688                 :             : 
    4689                 :             : /*************************************************************************************/
    4690                 :           0 : int AllocEdgeList( EDGE_LIST *pEdges, int nLen )
    4691                 :             : {
    4692      [ #  #  # ]:           0 :     switch (nLen)
    4693                 :             :     {
    4694                 :           0 :         case EDGE_LIST_FREE:
    4695         [ #  # ]:           0 :             if (NULL != pEdges->pnEdges)
    4696                 :             :             {
    4697         [ #  # ]:           0 :                 inchi_free( pEdges->pnEdges );
    4698                 :             :             }
    4699                 :             :             /* fall through */
    4700                 :             :         case EDGE_LIST_CLEAR:
    4701                 :           0 :             memset( pEdges, 0, sizeof( *pEdges ) ); /* djb-rwth: memset_s C11/Annex K variant? */
    4702                 :           0 :             break;
    4703                 :           0 :         default:
    4704   [ #  #  #  # ]:           0 :             if (nLen > 0 && nLen != pEdges->num_alloc)
    4705                 :             :             {
    4706                 :           0 :                 EdgeIndex *tmp_edges = pEdges->pnEdges;
    4707                 :           0 :                 int        tmp_num = pEdges->num_edges;
    4708                 :           0 :                 pEdges->pnEdges = (EdgeIndex *) inchi_calloc( nLen, sizeof( pEdges->pnEdges[0] ) );
    4709         [ #  # ]:           0 :                 if (!pEdges->pnEdges)
    4710                 :             :                 {
    4711                 :           0 :                     return RI_ERR_ALLOC;
    4712                 :             :                 }
    4713                 :           0 :                 tmp_num = inchi_min( tmp_num, nLen );
    4714   [ #  #  #  # ]:           0 :                 if (tmp_edges && tmp_num > 0)
    4715                 :             :                 {
    4716                 :           0 :                     memcpy(pEdges->pnEdges, tmp_edges, tmp_num * sizeof(pEdges->pnEdges[0]));
    4717                 :           0 :                     pEdges->num_edges = tmp_num;
    4718                 :             :                 }
    4719                 :             :                 else
    4720                 :             :                 {
    4721                 :           0 :                     pEdges->num_edges = 0;
    4722                 :             :                 }
    4723         [ #  # ]:           0 :                 if (tmp_edges)
    4724                 :             :                 {
    4725         [ #  # ]:           0 :                     inchi_free( tmp_edges );
    4726                 :             :                 }
    4727                 :           0 :                 pEdges->num_alloc = nLen;
    4728                 :           0 :                 return 0;
    4729                 :             :             }
    4730                 :           0 :             break;
    4731                 :             :     }
    4732                 :             : 
    4733                 :           0 :     return 0;
    4734                 :             : }
    4735                 :             : 
    4736                 :             : 
    4737                 :             : /********************************************************************/
    4738                 :           0 : int AddToEdgeList( EDGE_LIST *pEdges, int iedge, int nAddLen )
    4739                 :             : {
    4740         [ #  # ]:           0 :     if (pEdges->num_alloc == pEdges->num_edges)
    4741                 :             :     {
    4742                 :             :         int ret;
    4743         [ #  # ]:           0 :         if (nAddLen <= 0)
    4744                 :             :         {
    4745                 :           0 :             return RI_ERR_PROGR;
    4746                 :             :         }
    4747         [ #  # ]:           0 :         if ((ret = AllocEdgeList( pEdges, pEdges->num_alloc + nAddLen ))) /* djb-rwth: addressing LLVM warning */
    4748                 :             :         {
    4749                 :           0 :             return ret;
    4750                 :             :         }
    4751                 :             :     }
    4752                 :             : 
    4753                 :           0 :     pEdges->pnEdges[pEdges->num_edges++] = (EdgeIndex) iedge;
    4754                 :           0 :     return 0;
    4755                 :             : }
    4756                 :             : 
    4757                 :             : 
    4758                 :             : /********************************************************************/
    4759                 :           0 : int RemoveFromEdgeListByIndex( EDGE_LIST *pEdges, int index )
    4760                 :             : {
    4761                 :             :     int len;
    4762         [ #  # ]:           0 :     if (0 <= ( len = pEdges->num_edges - index - 1 ))
    4763                 :             :     {
    4764         [ #  # ]:           0 :         if (len)
    4765                 :             :         {
    4766                 :           0 :             memmove(pEdges->pnEdges + index, pEdges->pnEdges + index + 1, len * sizeof(pEdges->pnEdges[0]));
    4767                 :             :         }
    4768                 :           0 :         pEdges->num_edges--;
    4769                 :           0 :         pEdges->pnEdges[pEdges->num_edges] = 0;
    4770                 :           0 :         return 0;
    4771                 :             :     }
    4772                 :           0 :     return -1;
    4773                 :             : }
    4774                 :             : 
    4775                 :             : 
    4776                 :             : /********************************************************************/
    4777                 :           0 : int FindInEdgeList( EDGE_LIST *pEdges, int iedge )
    4778                 :             : {
    4779                 :             :     int i;
    4780                 :           0 :     EdgeIndex ie = iedge;
    4781         [ #  # ]:           0 :     for (i = pEdges->num_edges - 1; 0 <= i; i--)
    4782                 :             :     {
    4783         [ #  # ]:           0 :         if (ie == pEdges->pnEdges[i])
    4784                 :             :         {
    4785                 :           0 :             return i;
    4786                 :             :         }
    4787                 :             :     }
    4788                 :             : 
    4789                 :           0 :     return -1;
    4790                 :             : }
    4791                 :             : 
    4792                 :             : 
    4793                 :             : /********************************************************************/
    4794                 :           0 : int RemoveFromEdgeListByValue( EDGE_LIST *pEdges, int iedge )
    4795                 :             : {
    4796                 :           0 :     int i, ret, n = 0;
    4797                 :           0 :     EdgeIndex ie = iedge;
    4798         [ #  # ]:           0 :     for (i = pEdges->num_edges - 1; 0 <= i; i--)
    4799                 :             :     {
    4800         [ #  # ]:           0 :         if (ie == pEdges->pnEdges[i])
    4801                 :             :         {
    4802         [ #  # ]:           0 :             if ((ret = RemoveFromEdgeListByIndex( pEdges, i ))) /* djb-rwth: addressing LLVM warning */
    4803                 :             :             {
    4804                 :           0 :                 return ret;
    4805                 :             :             }
    4806                 :           0 :             n++;
    4807                 :             :         }
    4808                 :             :     }
    4809                 :             : 
    4810                 :           0 :     return n;
    4811                 :             : }
    4812                 :             : 
    4813                 :             : 
    4814                 :             : /********************************************************************/
    4815                 :           0 : int AllocBfsQueue( BFS_Q *pQ, int num_at, int min_ring_size )
    4816                 :             : {
    4817                 :           0 :     int ret = 0;
    4818      [ #  #  # ]:           0 :     switch (num_at)
    4819                 :             :     {
    4820                 :           0 :         case BFS_Q_FREE:
    4821         [ #  # ]:           0 :             if (pQ->q)
    4822                 :             :             {
    4823                 :           0 :                 pQ->q = QueueDelete( pQ->q );
    4824                 :             :             }
    4825         [ #  # ]:           0 :             if (pQ->nAtomLevel)
    4826                 :             :             {
    4827         [ #  # ]:           0 :                 inchi_free( pQ->nAtomLevel );
    4828                 :             :             }
    4829         [ #  # ]:           0 :             if (pQ->cSource)
    4830                 :             :             {
    4831         [ #  # ]:           0 :                 inchi_free( pQ->cSource );
    4832                 :             :             }
    4833                 :             :             /* fall through */
    4834                 :             :         case BFS_Q_CLEAR:
    4835                 :           0 :             memset( pQ, 0, sizeof( *pQ ) ); /* djb-rwth: memset_s C11/Annex K variant? */
    4836                 :           0 :             return 0;
    4837                 :             : 
    4838                 :           0 :         default:
    4839         [ #  # ]:           0 :             if (num_at <= 0)
    4840                 :             :             {
    4841                 :           0 :                 ret = RI_ERR_PROGR;
    4842                 :           0 :                 goto exit_function;
    4843                 :             :             }
    4844         [ #  # ]:           0 :             if (num_at > pQ->num_at)
    4845                 :             :             {
    4846         [ #  # ]:           0 :                 if (pQ->num_at)
    4847                 :             :                 {
    4848                 :           0 :                     AllocBfsQueue( pQ, BFS_Q_FREE, 0 );
    4849                 :             :                 }
    4850                 :           0 :                 pQ->q = QueueCreate( num_at + 1, sizeof( qInt ) );
    4851                 :           0 :                 pQ->nAtomLevel = (AT_RANK*) inchi_calloc( num_at, sizeof( pQ->nAtomLevel[0] ) );
    4852                 :           0 :                 pQ->cSource = (S_CHAR *) inchi_calloc( num_at, sizeof( pQ->cSource[0] ) );
    4853   [ #  #  #  #  :           0 :                 if (!pQ->q || !pQ->cSource || !pQ->nAtomLevel)
                   #  # ]
    4854                 :             :                 {
    4855                 :           0 :                     ret = RI_ERR_ALLOC;
    4856                 :           0 :                     goto exit_function;
    4857                 :             :                 }
    4858                 :           0 :                 pQ->num_at = num_at;
    4859                 :             :             }
    4860                 :           0 :             pQ->min_ring_size = min_ring_size;
    4861                 :             :     }
    4862                 :             : 
    4863                 :           0 : exit_function:
    4864                 :           0 :     return ret;
    4865                 :             : }
    4866                 :             : 
    4867                 :             : 
    4868                 :             : /*************************************************************************************/
    4869                 :           0 : void RemoveForbiddenEdgeMask( BN_STRUCT *pBNS, EDGE_LIST *pEdges, int forbidden_edge_mask )
    4870                 :             : {
    4871                 :           0 :     int i, mask = ~forbidden_edge_mask;
    4872         [ #  # ]:           0 :     for (i = 0; i < pEdges->num_edges; i++)
    4873                 :             :     {
    4874                 :           0 :         pBNS->edge[pEdges->pnEdges[i]].forbidden &= mask;
    4875                 :             :     }
    4876                 :           0 : }
    4877                 :             : 
    4878                 :             : 
    4879                 :             : /*************************************************************************************/
    4880                 :           0 : void SetForbiddenEdgeMask( BN_STRUCT *pBNS, EDGE_LIST *pEdges, int forbidden_edge_mask )
    4881                 :             : {
    4882                 :             :     int i;
    4883         [ #  # ]:           0 :     for (i = 0; i < pEdges->num_edges; i++)
    4884                 :             :     {
    4885                 :           0 :         pBNS->edge[pEdges->pnEdges[i]].forbidden |= forbidden_edge_mask;
    4886                 :             :     }
    4887                 :           0 : }
    4888                 :             : 
    4889                 :             : 
    4890                 :             : /****************************************************************************/
    4891                 :           0 : void RemoveForbiddenBondFlowBits( BN_STRUCT *pBNS, int forbidden_edge_mask_int )
    4892                 :             : {
    4893                 :             :     BNS_EDGE   *e;
    4894                 :             :     int         i;
    4895                 :           0 :     int         inv_forbidden_edge_mask = ~forbidden_edge_mask_int;
    4896         [ #  # ]:           0 :     for (i = 0, e = pBNS->edge; i < pBNS->num_bonds; i++, e++)
    4897                 :             :     {
    4898                 :           0 :         e->forbidden &= inv_forbidden_edge_mask;
    4899                 :             :     }
    4900                 :           0 : }
    4901                 :             : 
    4902                 :             : 
    4903                 :             : /******************************************************************************************************
    4904                 :             :          upper   vc
    4905                 :             :          edge   /
    4906                 :             :      v1[i0]---v0
    4907                 :             :        \     /
    4908                 :             :         \   /
    4909                 :             :          \ /
    4910                 :             :           v1[i1]
    4911                 :             :           |
    4912                 :             :           |
    4913                 :             :           atom
    4914                 :             : */
    4915                 :           0 : int GetChargeFlowerUpperEdge( BN_STRUCT *pBNS, VAL_AT *pVA, int nChargeEdge )
    4916                 :             : {
    4917                 :           0 :     int ret = NO_VERTEX, i, j, k, i0, i1;
    4918                 :             :     Vertex  v0, v1[3], vc, v_t, v;
    4919                 :             :     BNS_EDGE   *pe, *pe1[3], *pe_t;
    4920                 :             :     BNS_VERTEX *pv0, *pv1[3], *pv_t;
    4921                 :             : 
    4922         [ #  # ]:           0 :     if (nChargeEdge < 0)
    4923                 :             :     {
    4924                 :           0 :         goto exit_function;
    4925                 :             :     }
    4926                 :             : 
    4927                 :           0 :     pe = pBNS->edge + nChargeEdge;
    4928                 :           0 :     vc = pe->neighbor1; /* charge vertex */
    4929         [ #  # ]:           0 :     if (!IS_BNS_VT_C_GR( pBNS->vert[vc].type ))
    4930                 :             :     {
    4931                 :           0 :         vc = vc ^ pe->neighbor12;
    4932                 :             :     }
    4933                 :             : 
    4934                 :           0 :     v0 = vc ^ pe->neighbor12; /* ChargeStruct vertex ? */
    4935                 :           0 :     pv0 = pBNS->vert + v0;
    4936         [ #  # ]:           0 :     if (IS_BNS_VT_ATOM( pv0->type ))
    4937                 :             :     {
    4938                 :           0 :         goto exit_function; /* no charge flower exists */
    4939                 :             :     }
    4940                 :             : 
    4941                 :             :     /* 2 edges from v0 */
    4942   [ #  #  #  # ]:           0 :     for (i = j = 0; i < pv0->num_adj_edges && j < 3; i++)
    4943                 :             :     {
    4944                 :           0 :         pe1[j] = pBNS->edge + pv0->iedge[i];
    4945   [ #  #  #  # ]:           0 :         if (vc != ( v1[j] = pe1[j]->neighbor12 ^ v0 ) &&
    4946                 :           0 :             ( pv1[j] = pBNS->vert + v1[j],
    4947   [ #  #  #  # ]:           0 :                 !IS_BNS_VT_ATOM( pv1[j]->type ) && !IS_BNS_VT_C_GR( pv1[j]->type ) ))
    4948                 :             :         {
    4949                 :           0 :             j++;
    4950                 :             :         }
    4951                 :             :     }
    4952                 :             : 
    4953   [ #  #  #  # ]:           0 :     if (j != 2 || i != pv0->num_adj_edges)
    4954                 :             :     {
    4955                 :           0 :         goto exit_function;
    4956                 :             :     }
    4957                 :             : 
    4958         [ #  # ]:           0 :     if (pv1[1]->num_adj_edges == 2 &&
    4959         [ #  # ]:           0 :          pv1[0]->num_adj_edges == 3)
    4960                 :             :     {
    4961                 :           0 :         i0 = 1;
    4962                 :           0 :         i1 = 0;
    4963                 :             :     }
    4964         [ #  # ]:           0 :     else if (pv1[0]->num_adj_edges == 2 &&
    4965         [ #  # ]:           0 :          pv1[1]->num_adj_edges == 3)
    4966                 :             :     {
    4967                 :           0 :         i0 = 0;
    4968                 :           0 :         i1 = 1;
    4969                 :             :     }
    4970                 :             :     else
    4971                 :             :     {
    4972                 :           0 :         goto exit_function;
    4973                 :             :     }
    4974                 :             : 
    4975                 :             :     /* additional check: traverse edges around v1[i1] */
    4976                 :           0 :     pv_t = pv1[i1];
    4977                 :           0 :     v_t = v1[i1];
    4978         [ #  # ]:           0 :     for (i = k = 0; i < pv_t->num_adj_edges; i++)
    4979                 :             :     {
    4980                 :           0 :         pe_t = pBNS->edge + pv_t->iedge[i];
    4981                 :           0 :         v = pe_t->neighbor12 ^ v_t; /* v1[i1] neighbor */
    4982         [ #  # ]:           0 :         if (v == v0)
    4983                 :             :         {
    4984                 :           0 :             k += 1;
    4985                 :             :         }
    4986         [ #  # ]:           0 :         if (v == v1[i0])
    4987                 :             :         {
    4988                 :           0 :             k += 2;
    4989                 :             :         }
    4990         [ #  # ]:           0 :         if (IS_BNS_VT_ATOM( pBNS->vert[v].type ))
    4991                 :             :         {
    4992                 :           0 :             k += 4;
    4993                 :             :         }
    4994                 :             :     }
    4995         [ #  # ]:           0 :     if (k != 7)
    4996                 :             :     {
    4997                 :           0 :         goto exit_function;
    4998                 :             :     }
    4999                 :             : 
    5000                 :           0 :     ret = (int) ( pe1[i0] - pBNS->edge );
    5001                 :             : 
    5002                 :           0 : exit_function:
    5003                 :           0 :     return ret;
    5004                 :             : }
    5005                 :             : 
    5006                 :             : 
    5007                 :             : 
    5008                 :             : #if (INCLUDE_NORMALIZATION_ENTRY_POINT == 1 )
    5009                 :             : /********************************************************************************************
    5010                 :             : input: allocate (num_at+num_deleted_H) atoms in inp_ATOM *at_norm, *at_fixed_bonds_out
    5011                 :             :        allocate t_group_info
    5012                 :             : *********************************************************************************************/
    5013                 :             : int NormalizeStructure( ICHICONST INPUT_PARMS *ip, STRUCT_DATA *sd, BN_STRUCT *pBNS,
    5014                 :             :                         StrFromINChI *pStruct, inp_ATOM *at, inp_ATOM *at2,
    5015                 :             :                         VAL_AT *pVA, ALL_TC_GROUPS *pTCGroups,
    5016                 :             :                         inp_ATOM *at_norm, inp_ATOM *at_fixed_bonds_out, T_GROUP_INFO *t_group_info )
    5017                 :             : {
    5018                 :             :     int i, ret, num_endpoints, nLenTaut;
    5019                 :             :     int num_at = pStruct->num_atoms;
    5020                 :             :     int num_deleted_H = pStruct->num_deleted_H;
    5021                 :             :     int len_at = num_at + num_deleted_H;
    5022                 :             :     /*
    5023                 :             :     T_GROUP_INFO tgi;
    5024                 :             :     T_GROUP_INFO *t_group_info = &tgi;
    5025                 :             :     inp_ATOM *at_fixed_bonds_out = NULL;
    5026                 :             :     inp_ATOM *at_norm = NULL;
    5027                 :             : 
    5028                 :             :     at_norm = (inp_ATOM *)inchi_calloc( len_at, sizeof(at_norm[0]) );
    5029                 :             :     at_fixed_bonds_out = (inp_ATOM *)inchi_calloc( len_at, sizeof(at_fixed_bonds_out[0]) );
    5030                 :             :     if ( !at_norm || !at_fixed_bonds_out ) {
    5031                 :             :         if ( at_norm ) inchi_free( at_norm );
    5032                 :             :         if ( at_fixed_bonds_out ) inchi_free( at_fixed_bonds_out );
    5033                 :             :         ret = RI_ERR_ALLOC;
    5034                 :             :         goto exit_function;
    5035                 :             :     }
    5036                 :             :     */
    5037                 :             : /* call normalization only */
    5038                 :             :     memset( t_group_info, 0, sizeof( t_group_info[0] ) );
    5039                 :             :     t_group_info->tni.nNumRemovedExplicitH = pStruct->num_deleted_H;
    5040                 :             :     t_group_info->bTautFlags = ip->bTautFlags;
    5041                 :             :     t_group_info->bTautFlagsDone = 0; /* (ip->bTautFlagsDone | sd->bTautFlagsDone[INCHI_BAS]);*/
    5042                 :             : 
    5043                 :             :     memcpy( at2, at, len_at * sizeof( at2[0] ) );
    5044                 :             :     pStruct->at = at2;
    5045                 :             :     ret = CopyBnsToAtom( pStruct, pBNS, pVA, pTCGroups, 1 );
    5046                 :             :     pStruct->at = at;
    5047                 :             :     if (ret < 0)
    5048                 :             :     {
    5049                 :             :         goto exit_function;
    5050                 :             :     }
    5051                 :             : #if ( FIND_RING_SYSTEMS == 1 )
    5052                 :             :     ret = MarkRingSystemsInp( at2, num_at, 0 );
    5053                 :             :     if (ret < 0)
    5054                 :             :     {
    5055                 :             :         goto exit_function;
    5056                 :             :     }
    5057                 :             : #endif
    5058                 :             :     memcpy( at_norm, at2, len_at * sizeof( at_norm[0] ) );
    5059                 :             :     for (i = 0, num_endpoints = 0; i < num_at; i++)
    5060                 :             :     {
    5061                 :             :         num_endpoints += ( 0 != at_norm[i].endpoint );
    5062                 :             :         at_norm[i].endpoint = 0;
    5063                 :             :     }
    5064                 :             : 
    5065                 :             :     ret = mark_alt_bonds_and_taut_groups( ic, pCG, at_norm, at_fixed_bonds_out, num_at, t_group_info,
    5066                 :             :                                            NULL /* &inpbTautFlags*/, NULL /*inpbTautFlagsDone*/ );
    5067                 :             :     if (ret < 0)
    5068                 :             :     {
    5069                 :             :         goto exit_function;/*  out of RAM or other normalization problem */
    5070                 :             :     }
    5071                 :             :     /* after normalization, t_group_info->t_group[i].num[0] = number of H + number of (-)   */
    5072                 :             :     /*                         t_group_info->t_group[i].num[1] = number of (-)              */
    5073                 :             : 
    5074                 :             :     /* --- count t-groups, remove (-)-only t-groups, replace -------------------------------*/
    5075                 :             :     /* t_group_info->t_group[i].num[0] with                                                 */
    5076                 :             :     /* t_group_info->t_group[i].num[0]-t_group_info->t_group[i].num[1]                      */
    5077                 :             :     nLenTaut = CountTautomerGroupsInpAt( at_norm, num_at, t_group_info );
    5078                 :             :     ret = nLenTaut;
    5079                 :             : exit_function:
    5080                 :             :     return ret;
    5081                 :             : }
    5082                 :             : #endif
    5083                 :             : 
    5084                 :             : 
    5085                 :             : 
    5086                 :             : /****************************************************************************/
    5087                 :           0 : int MakeOneInChIOutOfStrFromINChI2( struct tagCANON_GLOBALS *pCG,
    5088                 :             :                                     INCHI_CLOCK *ic,
    5089                 :             :                                     ICHICONST INPUT_PARMS *ip_inp,
    5090                 :             :                                     STRUCT_DATA *sd_inp,
    5091                 :             :                                     BN_STRUCT *pBNS, StrFromINChI *pStruct,
    5092                 :             :                                     inp_ATOM *at, inp_ATOM *at2, inp_ATOM *at3,
    5093                 :             :                                     VAL_AT *pVA, ALL_TC_GROUPS *pTCGroups,
    5094                 :             :                                     T_GROUP_INFO **t_group_info,
    5095                 :             :                                     inp_ATOM **at_norm, inp_ATOM **at_prep )
    5096                 :             : {
    5097                 :             :     int ret;
    5098                 :             :     INPUT_PARMS ip_loc, *ip;
    5099                 :             :     STRUCT_DATA sd_loc, *sd;
    5100                 :             : 
    5101                 :           0 :     ip_loc = *ip_inp;
    5102                 :           0 :     sd_loc = *sd_inp;
    5103                 :           0 :     ip = &ip_loc;
    5104                 :           0 :     sd = &sd_loc;
    5105                 :             : 
    5106                 :           0 :     memset( sd, 0, sizeof( *sd ) ); /* djb-rwth: memset_s C11/Annex K variant? */
    5107                 :             : 
    5108                 :             :     /* create structure out of BNS */
    5109                 :           0 :     memcpy(at2, at, ((long long)pStruct->num_atoms + (long long)pStruct->num_deleted_H) * sizeof(at2[0])); /* djb-rwth: cast operator added */
    5110                 :           0 :     pStruct->at = at2;
    5111                 :           0 :     ret = CopyBnsToAtom( pStruct, pBNS, pVA, pTCGroups, 1 );
    5112                 :           0 :     pStruct->at = at;
    5113         [ #  # ]:           0 :     if (ret < 0)
    5114                 :             :     {
    5115                 :           0 :         goto exit_function;/*  out of RAM or other normalization problem */
    5116                 :             :     }
    5117                 :             : 
    5118                 :           0 :     pStruct->at = at;
    5119                 :             : 
    5120                 :           0 :     ret = MakeOneInChIOutOfStrFromINChI( pCG, ic, ip, sd, pStruct,
    5121                 :             :                                          at2, at3, pTCGroups );
    5122                 :             : 
    5123         [ #  # ]:           0 :     if (ret < 0)
    5124                 :             :     {
    5125                 :           0 :         goto exit_function;/*  out of RAM or other normalization problem */
    5126                 :             :     }
    5127         [ #  # ]:           0 :     if (at_norm)
    5128                 :             :     {
    5129                 :           0 :         *at_norm = pStruct->pOne_norm_data[0]->at;
    5130                 :             :     }
    5131         [ #  # ]:           0 :     if (at_prep)
    5132                 :             :     {
    5133   [ #  #  #  # ]:           0 :         if (pStruct->pOne_norm_data[0]->bTautPreprocessed && pStruct->pOne_norm_data[0]->at_fixed_bonds)
    5134                 :             :         {
    5135                 :           0 :             *at_prep = pStruct->pOne_norm_data[0]->at_fixed_bonds;
    5136                 :             :         }
    5137                 :             :         else
    5138                 :             :         /* get preprocessed structure in case of Fixed-H */
    5139   [ #  #  #  #  :           0 :             if (pStruct->iMobileH == TAUT_NON && pStruct->pOne_norm_data[1] && pStruct->pOne_norm_data[1]->bTautPreprocessed)
                   #  # ]
    5140                 :             :             {
    5141                 :           0 :                 *at_prep = pStruct->pOne_norm_data[1]->at_fixed_bonds;
    5142                 :             :             }
    5143                 :             :             else
    5144                 :             :             {
    5145                 :           0 :                 *at_prep = NULL;
    5146                 :             :             }
    5147                 :             :     }
    5148         [ #  # ]:           0 :     if (t_group_info)
    5149                 :             :     {
    5150         [ #  # ]:           0 :         if (pStruct->iMobileH == TAUT_YES &&
    5151         [ #  # ]:           0 :              pStruct->One_ti.num_t_groups &&
    5152   [ #  #  #  # ]:           0 :              pStruct->One_ti.t_group && pStruct->One_ti.nEndpointAtomNumber)
    5153                 :             :         {
    5154                 :           0 :             *t_group_info = &pStruct->One_ti;
    5155                 :             :         }
    5156                 :             :         else
    5157                 :             :         {
    5158                 :           0 :             *t_group_info = NULL;
    5159                 :             :         }
    5160                 :             :     }
    5161                 :             : 
    5162                 :           0 : exit_function:
    5163                 :           0 :     return ret;
    5164                 :             : }
    5165                 :             : 
    5166                 :             : 
    5167                 :             : /****************************************************************************/
    5168                 :           0 : int MakeOneInChIOutOfStrFromINChI( struct tagCANON_GLOBALS *pCG,
    5169                 :             :                                    INCHI_CLOCK *ic,
    5170                 :             :                                    ICHICONST INPUT_PARMS *ip,
    5171                 :             :                                    STRUCT_DATA *sd,
    5172                 :             :                                    StrFromINChI *pStruct,
    5173                 :             :                                    inp_ATOM *at2,
    5174                 :             :                                    inp_ATOM *at3,
    5175                 :             :                                    ALL_TC_GROUPS *pTCGroups )
    5176                 :             : {
    5177                 :             : 
    5178                 :           0 :     INCHI_MODE     bTautFlags = ip->bTautFlags | TG_FLAG_H_ALREADY_REMOVED;
    5179                 :           0 :     INCHI_MODE     bTautFlagsDone = 0; /*(ip->bTautFlagsDone | sd->bTautFlagsDone[INCHI_BAS]);*/
    5180                 :             :     INChI       *cur_INChI[TAUT_NUM];
    5181                 :             :     INChI_Aux   *cur_INChI_Aux[TAUT_NUM];
    5182                 :             :     int           i, j, k;
    5183                 :           0 :     int           iComponent = pTCGroups->iComponent;
    5184                 :           0 :     int           len_at = pStruct->num_atoms + pStruct->num_deleted_H;
    5185                 :           0 :     int           num_atoms = pStruct->num_atoms;
    5186                 :             :     long          ulStructTime;
    5187                 :             : 
    5188                 :             :     INP_ATOM_DATA InpCurAtData;
    5189                 :             :     INP_ATOM_DATA *inp_cur_data;
    5190                 :             : 
    5191                 :             :     INP_ATOM_DATA InpNormAtData, InpNormTautData;
    5192                 :             :     INP_ATOM_DATA *inp_norm_data[TAUT_NUM]; /*  = { &InpNormAtData, &InpNormTautData }; */
    5193                 :             : 
    5194                 :           0 :     int            bOrigCoord = 0;
    5195                 :           0 :     int            num_at, ret = RI_ERR_PROGR;
    5196                 :             :     struct tagInchiTime ulMaxTime;
    5197                 :             : 
    5198                 :           0 :     T_GROUP_INFO *t_group_info = NULL;
    5199                 :             :     /* initialization */
    5200                 :           0 :     inp_cur_data = &InpCurAtData;
    5201                 :           0 :     inp_norm_data[TAUT_NON] = &InpNormAtData;
    5202                 :           0 :     inp_norm_data[TAUT_YES] = &InpNormTautData;
    5203                 :             : 
    5204                 :           0 :     memset( inp_cur_data, 0, sizeof( *inp_cur_data ) ); /* djb-rwth: memset_s C11/Annex K variant? */
    5205                 :           0 :     memset( inp_norm_data[TAUT_NON], 0, sizeof( *inp_norm_data[0] ) ); /* djb-rwth: memset_s C11/Annex K variant? */
    5206                 :           0 :     memset( inp_norm_data[TAUT_YES], 0, sizeof( *inp_norm_data[0] ) ); /* djb-rwth: memset_s C11/Annex K variant? */
    5207                 :           0 :     ulStructTime = sd->ulStructTime;
    5208                 :           0 :     memset( sd, 0, sizeof( *sd ) ); /* djb-rwth: memset_s C11/Annex K variant? */
    5209                 :             : 
    5210                 :             :     /* deallocate old results */
    5211                 :           0 :     free_t_group_info( &pStruct->One_ti );
    5212         [ #  # ]:           0 :     for (k = 0; k < TAUT_NUM; k++)
    5213                 :             :     {
    5214                 :           0 :         Free_INChI( &pStruct->pOneINChI[k] );
    5215                 :           0 :         Free_INChI_Aux( &pStruct->pOneINChI_Aux[k] );
    5216         [ #  # ]:           0 :         if (pStruct->pOne_norm_data[k])
    5217                 :             :         {
    5218                 :           0 :             FreeInpAtomData( pStruct->pOne_norm_data[k] );
    5219         [ #  # ]:           0 :             inchi_free( pStruct->pOne_norm_data[k] );
    5220                 :           0 :             pStruct->pOne_norm_data[k] = NULL;
    5221                 :             :         }
    5222                 :           0 :         cur_INChI[k] = NULL;
    5223                 :           0 :         cur_INChI_Aux[k] = NULL;
    5224                 :             :     }
    5225                 :             : 
    5226                 :           0 :     memcpy(at3, at2, sizeof(at3[0]) * len_at);
    5227                 :             : 
    5228                 :             :     /* prepare the structure */
    5229                 :           0 :     IncrZeroBondsAndClearEndpts( at3, num_atoms, iComponent + 1 );
    5230                 :             : 
    5231                 :           0 :     CopySt2At( at3, pStruct->st, pStruct->num_atoms );
    5232                 :             : 
    5233                 :           0 :     FixUnkn0DStereoBonds( at3, pStruct->num_atoms );
    5234                 :             : 
    5235                 :           0 :     ret = ReconcileAllCmlBondParities( at3, pStruct->num_atoms, 0 );
    5236                 :             : 
    5237         [ #  # ]:           0 :     if (ret < 0)
    5238                 :             :     {
    5239                 :           0 :         goto exit_function;
    5240                 :             :     }
    5241                 :             : 
    5242         [ #  # ]:           0 :     if (0 < fix_odd_things( num_atoms, at3, 1, ip->bFixNonUniformDraw ))
    5243                 :             :     {
    5244         [ #  # ]:           0 :         if (sd->nErrorType < _IS_WARNING)
    5245                 :             :         {
    5246                 :           0 :             sd->nErrorType = _IS_WARNING;
    5247                 :             :         }
    5248                 :           0 :         sd->bTautFlagsDone[INCHI_BAS] |= TG_FLAG_FIX_ODD_THINGS_DONE;
    5249                 :             :     }
    5250                 :             : 
    5251                 :             :     /* allocate and set parameters */
    5252                 :           0 :     inp_cur_data->at = at3;
    5253                 :           0 :     inp_cur_data->num_at = num_atoms;
    5254                 :           0 :     inp_cur_data->num_removed_H = pStruct->num_deleted_H;
    5255                 :             : 
    5256                 :           0 :     bTautFlagsDone &= ~( TG_FLAG_FOUND_ISOTOPIC_H_DONE | TG_FLAG_FOUND_ISOTOPIC_ATOM_DONE );
    5257                 :             : 
    5258         [ #  # ]:           0 :     if ((i = bNumHeterAtomHasIsotopicH( at3, num_atoms ))) /* djb-rwth: addressing LLVM warning */
    5259                 :             :     {
    5260         [ #  # ]:           0 :         if (i & 1)
    5261                 :             :         {
    5262                 :           0 :             bTautFlagsDone |= TG_FLAG_FOUND_ISOTOPIC_H_DONE;
    5263                 :             :         }
    5264         [ #  # ]:           0 :         if (i & 2)
    5265                 :             :         {
    5266                 :           0 :             bTautFlagsDone |= TG_FLAG_FOUND_ISOTOPIC_ATOM_DONE;
    5267                 :             :         }
    5268                 :             :     }
    5269                 :             : 
    5270                 :           0 :     memset( &ulMaxTime, 0, sizeof( ulMaxTime ) ); /* djb-rwth: memset_s C11/Annex K variant? */
    5271                 :             : 
    5272                 :             :     /*  allocate memory for non-tautimeric (k=0) and tautomeric (k=1) results */
    5273         [ #  # ]:           0 :     for (k = 0; k < TAUT_NUM; k++)
    5274                 :             :     {
    5275                 :             : 
    5276   [ #  #  #  # ]:           0 :         if (!pStruct->bMobileH || k == pStruct->bMobileH)
    5277                 :           0 :         {
    5278                 :             :             /* pStruct->bMobileH=0: k = 0, 1   => allow allocation of both Fixed-H and Mobile-H InChI
    5279                 :             :                pStruct->bMobileH=1: k = 1 only => allow allocation of only Mobile-H InChI              */
    5280                 :             : 
    5281                 :             :             /* djb-rwth: introducing variables for correct nAllocMode expression */
    5282                 :           0 :             int nAM1 = 0, nAM2 = 0;
    5283                 :           0 :             int nAllocMode = 0;   /* copied from below 2024-09-01 DT */
    5284                 :             : 
    5285         [ #  # ]:           0 :             if (k == TAUT_YES)
    5286                 :           0 :                 nAM1 = REQ_MODE_TAUT;
    5287                 :             : 
    5288         [ #  # ]:           0 :             if (bTautFlagsDone & (TG_FLAG_FOUND_ISOTOPIC_H_DONE | TG_FLAG_FOUND_ISOTOPIC_ATOM_DONE))
    5289                 :           0 :                 nAM2 = ip->nMode & REQ_MODE_ISO;
    5290                 :             : 
    5291                 :           0 :             nAllocMode = nAM1 | nAM2; /* djb-rwth: original sequence of bit-wise operations had to be rewritten */
    5292                 :             : 
    5293   [ #  #  #  #  :           0 :             if ((k == TAUT_NON && ( ip->nMode & REQ_MODE_BASIC )) ||
                   #  # ]
    5294         [ #  # ]:           0 :                  (k == TAUT_YES && ( ip->nMode & REQ_MODE_TAUT ))) /* djb-rwth: addressing LLVM warnings */
    5295                 :             :             {
    5296                 :             :                 /*  alloc INChI and INChI_Aux only if ip->nMode allows this */
    5297                 :           0 :                 cur_INChI[k] = Alloc_INChI( inp_cur_data->at, inp_cur_data->num_at, &inp_cur_data->num_bonds,
    5298                 :             :                                               &inp_cur_data->num_isotopic, nAllocMode );
    5299                 :           0 :                 cur_INChI_Aux[k] = Alloc_INChI_Aux( inp_cur_data->num_at,
    5300                 :             :                                               inp_cur_data->num_isotopic, nAllocMode, bOrigCoord );
    5301         [ #  # ]:           0 :                 if (cur_INChI_Aux[k])
    5302                 :             :                 {
    5303                 :           0 :                     cur_INChI_Aux[k]->bIsIsotopic = inp_cur_data->num_isotopic;
    5304                 :             :                 }
    5305                 :             : 
    5306                 :             :                 /*  alloc memory for the output structure: non-tautomeric and tautomeric (for displaying) */
    5307                 :           0 :                 CreateInpAtomData( inp_norm_data[k], inp_cur_data->num_at + inp_cur_data->num_removed_H, k );
    5308                 :             : 
    5309                 :           0 :                 inp_norm_data[k]->num_removed_H = inp_cur_data->num_removed_H;
    5310                 :             :             }
    5311                 :             :             else
    5312                 :             :             {
    5313                 :           0 :                 FreeInpAtomData( inp_norm_data[k] );
    5314                 :             :             }
    5315                 :             :         }
    5316                 :             :         else
    5317                 :             :         {
    5318                 :           0 :             FreeInpAtomData( inp_norm_data[k] );
    5319                 :             :         }
    5320                 :             :     }
    5321                 :             : 
    5322                 :           0 :     k = pStruct->bMobileH;
    5323                 :             : 
    5324                 :             :     /* In case of Fixed-H we have to create InChI for both Fixed-H and Mobile-H */
    5325                 :             : 
    5326                 :           0 :     num_at = Create_INChI( pCG,
    5327                 :             :                            ic,
    5328                 :             :                            (INPUT_PARMS *) ip,
    5329                 :             :                            cur_INChI,
    5330                 :             :                            cur_INChI_Aux,
    5331                 :             :                            NULL,
    5332                 :             :                            inp_cur_data->at,
    5333                 :             :                            inp_norm_data,
    5334                 :           0 :                            inp_cur_data->num_at + inp_cur_data->num_removed_H,
    5335                 :           0 :                            ip->nMode,
    5336                 :             :                            &bTautFlags,
    5337                 :             :                            &bTautFlagsDone,
    5338                 :             :                            NULL /* &ulMaxTime*/,
    5339                 :           0 :                            &pStruct->One_ti,
    5340                 :           0 :                            sd->pStrErrStruct );
    5341                 :             : 
    5342                 :           0 :     SetConnectedComponentNumber( inp_cur_data->at, inp_cur_data->num_at, iComponent + 1 ); /*  normalization alters structure component number */
    5343                 :             : 
    5344                 :             :     /* Detect InChI errors */
    5345                 :             : 
    5346         [ #  # ]:           0 :     if (num_at < 0)
    5347                 :             :     {
    5348                 :           0 :         ret = num_at;
    5349                 :             :     }
    5350   [ #  #  #  # ]:           0 :     else if (cur_INChI[k] && cur_INChI[k]->nErrorCode)
    5351                 :             :     {
    5352                 :           0 :         ret = cur_INChI[k]->nErrorCode;
    5353                 :             :     }
    5354   [ #  #  #  # ]:           0 :     else if (cur_INChI_Aux[k] && cur_INChI_Aux[k]->nErrorCode)
    5355                 :             :     {
    5356                 :           0 :         ret = cur_INChI_Aux[k]->nErrorCode;
    5357                 :             :     }
    5358                 :             :     else
    5359                 :             :     {
    5360                 :           0 :         ret = 0;
    5361                 :             :     }
    5362                 :             : 
    5363                 :             :     /* Fill out the output */
    5364                 :             : 
    5365         [ #  # ]:           0 :     if (!ret) /* djb-rwth: fixing a NULL pointer dereference */
    5366                 :             :     {
    5367                 :           0 :         int bMobileH = pStruct->bMobileH;
    5368         [ #  # ]:           0 :         if (bMobileH == TAUT_NON &&
    5369         [ #  # ]:           0 :              0 == cur_INChI[TAUT_NON]->nNumberOfAtoms &&
    5370         [ #  # ]:           0 :              0 < cur_INChI[TAUT_YES]->nNumberOfAtoms)
    5371                 :             :         {
    5372                 :             :             /* tautomerism or H(+) removal/addition was not discovered */
    5373                 :           0 :             bMobileH = TAUT_YES;
    5374                 :             :         }
    5375                 :             : 
    5376         [ #  # ]:           0 :         if (cur_INChI[1])
    5377                 :           0 :             pStruct->nChargeRevrs = cur_INChI[TAUT_YES]->nTotalCharge; /* djb-rwth: fixing a NULL pointer dereference */
    5378                 :             : 
    5379                 :           0 :         pStruct->pOneINChI[0] = cur_INChI[bMobileH];
    5380                 :           0 :         pStruct->pOneINChI_Aux[0] = cur_INChI_Aux[bMobileH];
    5381                 :           0 :         pStruct->nOneINChI_bMobileH = bMobileH;
    5382                 :           0 :         cur_INChI[bMobileH] = NULL;  /* remove pointer to avoid deallocation at exit_function */
    5383                 :           0 :         cur_INChI_Aux[bMobileH] = NULL;  /* remove pointer to avoid deallocation at exit_function */
    5384                 :             : 
    5385         [ #  # ]:           0 :         pStruct->nNumRemovedProtons = ( pStruct->iMobileH == TAUT_YES ) ? pStruct->One_ti.tni.nNumRemovedProtons : 0;
    5386                 :             : 
    5387                 :             : 
    5388                 :             :         /* set correct t-group numbers to endpoints */
    5389                 :             : 
    5390                 :           0 :         t_group_info = &pStruct->One_ti;
    5391                 :             : 
    5392   [ #  #  #  #  :           0 :         if (t_group_info->num_t_groups && t_group_info->t_group && t_group_info->nEndpointAtomNumber)
                   #  # ]
    5393                 :             :         {
    5394                 :           0 :             inp_ATOM     *at_norm = inp_norm_data[TAUT_YES]->at;
    5395                 :           0 :             int          num_at_norm = inp_norm_data[TAUT_YES]->num_at;
    5396         [ #  # ]:           0 :             for (i = 0; i < num_at_norm; i++)
    5397                 :             :             {
    5398                 :           0 :                 at_norm[i].endpoint = 0;
    5399                 :             :             }
    5400         [ #  # ]:           0 :             for (i = 0; i < t_group_info->num_t_groups; i++)
    5401                 :             :             {
    5402                 :           0 :                 k = t_group_info->t_group[i].nFirstEndpointAtNoPos;
    5403                 :             :                 /* add number of mobile (-) to the number of mobile H */
    5404                 :           0 :                 t_group_info->t_group[i].num[0] += t_group_info->t_group[i].num[1];
    5405         [ #  # ]:           0 :                 for (j = 0; j < t_group_info->t_group[i].nNumEndpoints; j++, k++)
    5406                 :             :                 {
    5407                 :           0 :                     at_norm[t_group_info->nEndpointAtomNumber[k]].endpoint = t_group_info->t_group[i].nGroupNumber;
    5408                 :             :                 }
    5409                 :             :             }
    5410                 :             :         }
    5411                 :             : 
    5412                 :           0 :         pStruct->pOne_norm_data[0] = (INP_ATOM_DATA *) inchi_malloc( sizeof( pStruct->pOne_norm_data[0][0] ) );
    5413                 :             : 
    5414         [ #  # ]:           0 :         if (pStruct->pOne_norm_data[0])
    5415                 :             :         {
    5416                 :           0 :             memcpy(pStruct->pOne_norm_data[0], inp_norm_data[bMobileH], sizeof(pStruct->pOne_norm_data[0][0]));
    5417                 :           0 :             memset( inp_norm_data[bMobileH], 0, sizeof( *inp_norm_data[0] ) ); /* djb-rwth: memset_s C11/Annex K variant? */
    5418                 :             :         }
    5419                 :             :         else
    5420                 :             :         {
    5421                 :           0 :             ret = RI_ERR_ALLOC;
    5422                 :             :         }
    5423                 :             : 
    5424   [ #  #  #  # ]:           0 :         if (bMobileH == TAUT_NON && cur_INChI[TAUT_YES]->nNumberOfAtoms > 0)
    5425                 :             :         {
    5426         [ #  # ]:           0 :             int bMobileHalt = ALT_TAUT( bMobileH ); /* = TAUT_YES */
    5427                 :           0 :             pStruct->pOneINChI[1] = cur_INChI[bMobileHalt];
    5428                 :           0 :             pStruct->pOneINChI_Aux[1] = cur_INChI_Aux[bMobileHalt];
    5429                 :           0 :             cur_INChI[bMobileHalt] = NULL;
    5430                 :           0 :             cur_INChI_Aux[bMobileHalt] = NULL;
    5431                 :           0 :             pStruct->pOne_norm_data[1] = (INP_ATOM_DATA *) inchi_malloc( sizeof( pStruct->pOne_norm_data[0][0] ) );
    5432         [ #  # ]:           0 :             if (pStruct->pOne_norm_data[1])
    5433                 :             :             {
    5434                 :           0 :                 memcpy(pStruct->pOne_norm_data[1], inp_norm_data[bMobileHalt], sizeof(pStruct->pOne_norm_data[0][0]));
    5435                 :           0 :                 memset( inp_norm_data[bMobileHalt], 0, sizeof( *inp_norm_data[0] ) ); /* djb-rwth: memset_s C11/Annex K variant? */
    5436                 :             :             }
    5437                 :             :             else
    5438                 :             :             {
    5439                 :           0 :                 ret = RI_ERR_ALLOC;
    5440                 :             :             }
    5441                 :             :         }
    5442                 :             :     }
    5443                 :             :     else
    5444                 :             :     {
    5445                 :             : #if ( bRELEASE_VERSION != 1 )
    5446                 :             : #ifndef TARGET_API_LIB
    5447                 :             :         fprintf( stdout, "ERROR: Create_INChI returned %d\n", ret );
    5448                 :             : #endif
    5449                 :             : #endif
    5450                 :             :     }
    5451                 :             : 
    5452                 :           0 : exit_function:
    5453                 :             :     /* deallocate unused */
    5454         [ #  # ]:           0 :     for (k = 0; k < TAUT_NUM; k++)
    5455                 :             :     {
    5456                 :           0 :         Free_INChI( &cur_INChI[k] );
    5457                 :           0 :         Free_INChI_Aux( &cur_INChI_Aux[k] );
    5458                 :           0 :         FreeInpAtomData( inp_norm_data[k] );
    5459                 :             :     }
    5460                 :           0 :     sd->ulStructTime = ulStructTime;
    5461                 :             : 
    5462                 :           0 :     return ret;
    5463                 :             : }
    5464                 :             : 
    5465                 :             : 
    5466                 :             : /****************************************************************************
    5467                 :             : Input:
    5468                 :             :        at[].num_H       = total number of all terminal H connected to the atom
    5469                 :             :        at[].num_iso_H[] = numbers of isotopic H among at[].num_H
    5470                 :             :        Explicit H are disconnected
    5471                 :             :        Calculate InChI with normalization only in MakeOneInChIOutOfStrFromINChI()
    5472                 :             :        with (TG_FLAG_H_ALREADY_REMOVED & bTautFlags) != 0
    5473                 :             : Output:
    5474                 :             :        at[].num_H       = number of implicit non-isotopic H connected to the atom
    5475                 :             :        at[].num_iso_H[] = numbers of implicit isotopic H (not included in at[].num_H)
    5476                 :             :        Explicit H are connected
    5477                 :             :        Calculate InChI with full preprocessing MakeInChIOutOfStrFromINChI2()
    5478                 :             :        with (TG_FLAG_H_ALREADY_REMOVED & bTautFlags) == 0
    5479                 :             : ****************************************************************************/
    5480                 :           0 : int ConnectDisconnectedH( inp_ATOM *at, int num_atoms, int num_deleted_H )
    5481                 :             : {
    5482                 :             :     int i, j, k, n, m, num_H;
    5483                 :           0 :     int tot_atoms = num_atoms + num_deleted_H;
    5484                 :             : 
    5485         [ #  # ]:           0 :     for (i = num_atoms; i < tot_atoms; i = j)
    5486                 :             :     {
    5487                 :           0 :         k = at[i].neighbor[0]; /* a[k] is the atom connected to the explicit hydrogen at[i] */
    5488                 :             : 
    5489   [ #  #  #  # ]:           0 :         for (j = i; j < tot_atoms && at[j].neighbor[0] == k; j++)
    5490                 :             :         {
    5491                 :             :             ;
    5492                 :             :         }
    5493                 :             : 
    5494                 :           0 :         num_H = j - i; /* number of explicit H for at[k] */
    5495         [ #  # ]:           0 :         if (num_H > at[k].num_H)
    5496                 :             :         {
    5497                 :           0 :             return RI_ERR_PROGR;
    5498                 :             :         }
    5499         [ #  # ]:           0 :         if (num_H + at[k].valence > MAXVAL)
    5500                 :             :         {
    5501                 :           0 :             return RI_ERR_SYNTAX;
    5502                 :             :         }
    5503                 :             : 
    5504                 :             :         /* insert links to explicit H before all other links in the connection list */
    5505                 :           0 :         n = at[k].valence;
    5506                 :           0 :         memmove(at[k].neighbor + num_H, at[k].neighbor, sizeof(at[k].neighbor[0]) * n);
    5507                 :           0 :         memmove(at[k].bond_stereo + num_H, at[k].bond_stereo, sizeof(at[k].bond_stereo[0]) * n);
    5508                 :           0 :         memmove(at[k].bond_type + num_H, at[k].bond_type, sizeof(at[k].bond_type[0]) * n);
    5509         [ #  # ]:           0 :         for (n = 0; n < num_H; n++)
    5510                 :             :         {
    5511                 :           0 :             at[k].neighbor[n] = i + n;
    5512                 :           0 :             at[k].bond_stereo[n] = 0;
    5513                 :           0 :             at[k].bond_type[n] = BOND_TYPE_SINGLE;
    5514                 :             :         }
    5515                 :             : 
    5516   [ #  #  #  # ]:           0 :         for (m = 0; m < MAX_NUM_STEREO_BONDS && at[k].sb_parity[m]; m++)
    5517                 :             :         {
    5518                 :           0 :             at[k].sb_ord[m] += num_H;
    5519         [ #  # ]:           0 :             if (at[k].sn_ord[m] < 0)
    5520                 :             :             {
    5521         [ #  # ]:           0 :                 for (n = i; n < j; n++)
    5522                 :             :                 {
    5523         [ #  # ]:           0 :                     if (at[n].orig_at_number == at[k].sn_orig_at_num[m])
    5524                 :             :                     {
    5525                 :           0 :                         at[k].sn_ord[m] = n - i;
    5526                 :           0 :                         break;
    5527                 :             :                     }
    5528                 :             :                 }
    5529                 :             : 
    5530         [ #  # ]:           0 :                 if (n == j)
    5531                 :             :                 {
    5532                 :           0 :                     return RI_ERR_PROGR;
    5533                 :             :                 }
    5534                 :             :             }
    5535                 :             :             else
    5536                 :             :             {
    5537                 :           0 :                 at[k].sn_ord[m] += num_H;
    5538                 :             :             }
    5539                 :             :         }
    5540                 :             : 
    5541                 :           0 :         at[k].valence += num_H;
    5542                 :           0 :         at[k].chem_bonds_valence += num_H;
    5543                 :           0 :         at[k].num_H -= num_H; /* cannot be negative */
    5544                 :             : 
    5545                 :             :         /*memset( at[k].num_iso_H, 0, sizeof(at[0].num_iso_H) );*/ /* attached H must carry all isotopic shifts */
    5546         [ #  # ]:           0 :         for (n = i; n < j; n++)
    5547                 :             :         {
    5548                 :           0 :             at[n].chem_bonds_valence = BOND_TYPE_SINGLE;
    5549                 :             :         }
    5550                 :             : 
    5551                 :             :         /* isotopic H */
    5552   [ #  #  #  # ]:           0 :         for (m = j - 1; i <= m && at[m].iso_atw_diff > 0; m--)
    5553                 :             :         {
    5554         [ #  # ]:           0 :             if (at[m].iso_atw_diff > NUM_H_ISOTOPES)
    5555                 :             :             {
    5556                 :           0 :                 return RI_ERR_PROGR;
    5557                 :             :             }
    5558         [ #  # ]:           0 :             if (0 >= at[k].num_iso_H[(int) at[m].iso_atw_diff - 1] --)
    5559                 :             :             {
    5560                 :           0 :                 return RI_ERR_PROGR;
    5561                 :             :             }
    5562                 :             :         }
    5563                 :             :     }
    5564                 :             : 
    5565                 :             :     /* subtract isotopic H */
    5566         [ #  # ]:           0 :     for (i = 0; i < num_atoms; i++)
    5567                 :             :     {
    5568         [ #  # ]:           0 :         for (m = 0; m < NUM_H_ISOTOPES; m++)
    5569                 :             :         {
    5570                 :           0 :             at[i].num_H -= at[i].num_iso_H[m];
    5571                 :             :         }
    5572         [ #  # ]:           0 :         if (0 > at[i].num_H)
    5573                 :             :         {
    5574                 :           0 :             return RI_ERR_PROGR;
    5575                 :             :         }
    5576                 :             :     }
    5577                 :             : 
    5578                 :           0 :     return tot_atoms;
    5579                 :             : }
    5580                 :             : 
    5581                 :             : 
    5582                 :             : /******************************************************************************************************
    5583                 :             : Input:
    5584                 :             :        at[].num_H       = number of implicit non-isotopic H connected to the atom
    5585                 :             :        at[].num_iso_H[] = numbers of implicit isotopic H (not included in at[].num_H)
    5586                 :             :        Explicit H are connected
    5587                 :             :        Calculate InChI with (TG_FLAG_H_ALREADY_REMOVED & bTautFlags) == 0
    5588                 :             : Output:
    5589                 :             :        at[].num_H       = total number of all terminal H connected to the atom
    5590                 :             :        at[].num_iso_H[] = numbers of isotopic H among at[].num_H
    5591                 :             :        Explicit H are disconnected
    5592                 :             :        Calculate InChI with (TG_FLAG_H_ALREADY_REMOVED & bTautFlags) != 0
    5593                 :             : *******************************************************************************************************/
    5594                 :           0 : int DisconnectedConnectedH( inp_ATOM *at, int num_atoms, int num_deleted_H )
    5595                 :             : {
    5596                 :             :     int i, j, k, n, m, num_H, num_iso_H;
    5597                 :           0 :     int tot_atoms = num_atoms + num_deleted_H;
    5598                 :           0 :     S_CHAR ctmp = '0';
    5599                 :             : 
    5600                 :             :     /* add implicit isotopic H to total implicit H */
    5601         [ #  # ]:           0 :     for (i = 0; i < num_atoms; i++)
    5602                 :             :     {
    5603         [ #  # ]:           0 :         for (m = 0; m < NUM_H_ISOTOPES; m++)
    5604                 :             :         {
    5605                 :           0 :             at[i].num_H += at[i].num_iso_H[m];
    5606                 :             :         }
    5607                 :             :     }
    5608                 :             : 
    5609         [ #  # ]:           0 :     for (i = num_atoms; i < tot_atoms; i = j)
    5610                 :             :     {
    5611                 :           0 :         k = at[i].neighbor[0]; /* a[k] is the atom connected to the explicit hydrogen at[i] */
    5612                 :             : 
    5613   [ #  #  #  # ]:           0 :         for (j = i; j < tot_atoms && at[j].neighbor[0] == k; j++)
    5614                 :             :         {
    5615                 :           0 :             at[j].chem_bonds_valence = 0;
    5616                 :             :         }
    5617                 :           0 :         num_H = j - i; /* number of explicit H for at[k] */
    5618                 :             : 
    5619                 :             :         /* verify correct number of explicit H */
    5620   [ #  #  #  # ]:           0 :         for (n = 0; n < at[k].valence && at[k].neighbor[n] >= num_atoms; n++)
    5621                 :             :         {
    5622                 :             :             ;
    5623                 :             :         }
    5624         [ #  # ]:           0 :         if (n != num_H)
    5625                 :             :         {
    5626                 :           0 :             return RI_ERR_PROGR;
    5627                 :             :         }
    5628                 :             : 
    5629                 :             :         /* remove bonds to explicit H located in front of all other bonds in the connection list */
    5630                 :           0 :         at[k].valence -= num_H; /* djb-rwth: use of cast operators avoided */
    5631                 :           0 :         n = at[k].valence; /* new number of bonds */ 
    5632                 :           0 :         at[k].chem_bonds_valence -= num_H; /* new no-H valence */
    5633         [ #  # ]:           0 :         if (n)
    5634                 :             :         {
    5635                 :           0 :             memmove(at[k].neighbor, at[k].neighbor + num_H, sizeof(at[k].neighbor[0]) * n);
    5636                 :           0 :             memmove(at[k].bond_stereo, at[k].bond_stereo + num_H, sizeof(at[k].bond_stereo[0]) * n);
    5637                 :           0 :             memmove(at[k].bond_type, at[k].bond_type + num_H, sizeof(at[k].bond_type[0]) * n);
    5638                 :             :         }
    5639                 :             :         /* clear the 'tails' */
    5640                 :           0 :         memset( at[k].neighbor + n, 0, sizeof( at[k].neighbor[0] ) * num_H ); /* djb-rwth: memset_s C11/Annex K variant? */
    5641                 :           0 :         memset( at[k].bond_stereo + n, 0, sizeof( at[k].bond_stereo[0] ) * num_H ); /* djb-rwth: memset_s C11/Annex K variant? */
    5642                 :           0 :         memset( at[k].bond_type + n, 0, sizeof( at[k].bond_type[0] ) * num_H ); /* djb-rwth: memset_s C11/Annex K variant? */
    5643                 :             : 
    5644   [ #  #  #  # ]:           0 :         for (m = 0; m < MAX_NUM_STEREO_BONDS && at[k].sb_parity[m]; m++)
    5645                 :             :         {
    5646                 :           0 :             at[k].sb_ord[m] -= num_H;
    5647   [ #  #  #  # ]:           0 :             if (0 <= at[k].sn_ord[m] && at[k].sn_ord[m] < num_H)
    5648                 :             :             {
    5649                 :           0 :                 at[k].sn_ord[m] = -1; /* disconnected explicit H */
    5650                 :             :             }
    5651                 :             :         }
    5652                 :             :         /* add explicit isotopic H (already included in num_H) */
    5653   [ #  #  #  # ]:           0 :         for (num_iso_H = 0, m = j - 1; i <= m && at[m].iso_atw_diff > 0; m--)
    5654                 :             :         {
    5655         [ #  # ]:           0 :             if (at[m].iso_atw_diff > NUM_H_ISOTOPES)
    5656                 :             :             {
    5657                 :           0 :                 return RI_ERR_PROGR;
    5658                 :             :             }
    5659                 :           0 :             at[k].num_iso_H[(int) at[m].iso_atw_diff - 1] ++;
    5660                 :             :         }
    5661                 :           0 :         at[k].num_H += num_H; /* add all explicit H including isotopic */
    5662                 :             :     }
    5663                 :             : 
    5664                 :           0 :     return tot_atoms;
    5665                 :             : }
    5666                 :             : 
    5667                 :             : 
    5668                 :             : /****************************************************************************/
    5669                 :           0 : int MakeInChIOutOfStrFromINChI2( INCHI_CLOCK *ic,
    5670                 :             :                                  CANON_GLOBALS *pCG,
    5671                 :             :                                  ICHICONST INPUT_PARMS *ip_inp,
    5672                 :             :                                  STRUCT_DATA *sd_inp,
    5673                 :             :                                  StrFromINChI *pStruct,
    5674                 :             :                                  int iComponent,
    5675                 :             :                                  int iAtNoOffset,
    5676                 :             :                                  long num_inp )
    5677                 :             : {
    5678                 :             :     char szTitle[MAX_SDF_HEADER + MAX_SDF_VALUE + 256];
    5679                 :             : 
    5680                 :             :     int   len, ret;
    5681                 :             :     /*
    5682                 :             :     PINChI2     *pINChI[INCHI_NUM];
    5683                 :             :     PINChI_Aux2 *pINChI_Aux[INCHI_NUM];
    5684                 :             :     */
    5685                 :             :     INPUT_PARMS local_ip;
    5686                 :             :     STRUCT_DATA local_sd;
    5687                 :           0 :     INPUT_PARMS *ip = &local_ip;
    5688                 :           0 :     STRUCT_DATA *sd = &local_sd;
    5689                 :             : 
    5690                 :             :     ORIG_ATOM_DATA OrigAtData; /* 0=> disconnected, 1=> original */
    5691                 :           0 :     ORIG_ATOM_DATA *orig_inp_data = &OrigAtData;
    5692                 :             :     ORIG_ATOM_DATA PrepAtData[2]; /* 0=> disconnected, 1=> original */
    5693                 :           0 :     ORIG_ATOM_DATA *prep_inp_data = PrepAtData;
    5694                 :             : 
    5695                 :             :     INCHI_IOS_STRING temp_string_container;
    5696                 :           0 :     INCHI_IOS_STRING *strbuf = &temp_string_container;
    5697                 :           0 :     memset( strbuf, 0, sizeof( *strbuf ) ); /* djb-rwth: memset_s C11/Annex K variant? */
    5698                 :             : 
    5699         [ #  # ]:           0 :     if (0 >= inchi_strbuf_init(strbuf, INCHI_STRBUF_INITIAL_SIZE, INCHI_STRBUF_SIZE_INCREMENT))
    5700                 :             :     {
    5701                 :           0 :         ret = RI_ERR_ALLOC;
    5702                 :           0 :         goto early_exit_error; /* djb-rwth: avoiding garbage value */
    5703                 :             :     }
    5704                 :             : 
    5705                 :             :     /* djb-rwth: fixing oss-fuzz issue #70552 */
    5706   [ #  #  #  #  :           0 :     if (!ip_inp || !sd_inp || !pStruct)
                   #  # ]
    5707                 :             :     {
    5708                 :           0 :         ret = RI_ERR_ALLOC;
    5709                 :           0 :         goto early_exit_error; /* djb-rwth: avoiding garbage value */
    5710                 :             :     }
    5711                 :             : 
    5712                 :           0 :     *ip = *ip_inp;
    5713                 :           0 :     ip->bDisplay = 0;
    5714                 :           0 :     ip->bDisplayCompositeResults = 0;
    5715                 :           0 :     ip->bDisplayEachComponentINChI = 0;
    5716                 :           0 :     ip->bDisplayIfRestoreWarnings = 0;
    5717                 :           0 :     ip->bINChIOutputOptions = INCHI_OUT_NO_AUX_INFO;
    5718                 :             : 
    5719                 :             :     /*
    5720                 :             :     if ( pStruct->bMobileH ) {
    5721                 :             :         ip->nMode &= ~REQ_MODE_BASIC;
    5722                 :             :         ip->nMode |= REQ_MODE_TAUT;
    5723                 :             :     } else {
    5724                 :             :         ip->nMode |= (REQ_MODE_TAUT | REQ_MODE_BASIC);
    5725                 :             :     }
    5726                 :             :     */
    5727                 :             : 
    5728                 :           0 :     memset( sd, 0, sizeof( *sd ) ); /* djb-rwth: memset_s C11/Annex K variant? */
    5729                 :           0 :     sd->fPtrStart = -1;
    5730                 :           0 :     sd->fPtrEnd = -1;
    5731                 :             : 
    5732                 :             :     /*
    5733                 :             :     if ( ip->nMode & REQ_MODE_STEREO ) {
    5734                 :             :         if ( ip->nMode & (REQ_MODE_RELATIVE_STEREO | REQ_MODE_RACEMIC_STEREO) ) {
    5735                 :             :             sd->bChiralFlag |= FLAG_INP_AT_NONCHIRAL;
    5736                 :             :         } else {
    5737                 :             :             sd->bChiralFlag |= FLAG_INP_AT_CHIRAL;
    5738                 :             :         }
    5739                 :             :     }
    5740                 :             :     */
    5741                 :             : 
    5742                 :           0 :     memset( orig_inp_data, 0, sizeof( *orig_inp_data ) ); /* djb-rwth: memset_s C11/Annex K variant? */
    5743                 :           0 :     memset( prep_inp_data, 0, 2 * sizeof( *prep_inp_data ) ); /* djb-rwth: memset_s C11/Annex K variant? */
    5744                 :           0 :     memset( pStruct->RevInChI.pINChI, 0, sizeof( pStruct->RevInChI.pINChI ) ); /* djb-rwth: memset_s C11/Annex K variant? */
    5745                 :           0 :     memset( pStruct->RevInChI.pINChI_Aux, 0, sizeof( pStruct->RevInChI.pINChI_Aux ) ); /* djb-rwth: memset_s C11/Annex K variant? */
    5746                 :           0 :     memset( szTitle, 0, sizeof( szTitle ) ); /* djb-rwth: memset_s C11/Annex K variant? */
    5747                 :             : 
    5748                 :           0 :     len = sizeof( orig_inp_data->at[0] )*( (long long)pStruct->num_atoms + (long long)pStruct->num_deleted_H ); /* djb-rwth: cast operators added */
    5749                 :             : 
    5750                 :           0 :     orig_inp_data->at = (inp_ATOM *) inchi_malloc( len );
    5751                 :             : 
    5752         [ #  # ]:           0 :     if (orig_inp_data->at)
    5753                 :             :     {
    5754                 :             :         /*memcpy( orig_inp_data->at, pStruct->at2, len );*/
    5755                 :             :         /*ret = ConnectDisconnectedH( orig_inp_data->at, pStruct->num_atoms, pStruct->num_deleted_H );*/
    5756                 :             : 
    5757                 :           0 :         CopySt2At( pStruct->at2, pStruct->st, pStruct->num_atoms );
    5758                 :             : 
    5759                 :           0 :         ret = ConnectDisconnectedH( pStruct->at2, pStruct->num_atoms, pStruct->num_deleted_H );
    5760         [ #  # ]:           0 :         if (ret < 0)
    5761                 :             :         {
    5762                 :           0 :             goto exit_error;
    5763                 :             :         }
    5764                 :             : 
    5765                 :           0 :         orig_inp_data->num_inp_atoms = ret;
    5766                 :             :         /* connections changed => reconcile parities even if they were reconciled before */
    5767                 :             :         /* remove t-group markings and increment zero-order bonds,
    5768                 :             :            otherwise MakeInChIOutOfStrFromINChI2() woild fail */
    5769                 :             :         /*
    5770                 :             :         IncrZeroBondsAndClearEndpts(pStruct->at2, pStruct->num_atoms, iComponent+1);
    5771                 :             :         */
    5772                 :             : 
    5773                 :           0 :         IncrZeroBonds( pStruct->at2, pStruct->num_atoms, iComponent + 1 );
    5774                 :             : 
    5775                 :             :         /* CopySt2At() moved to the position before ConnectDisconnectedH() because
    5776                 :             :            in case stereo exists only in Mobile-H layer and the processd here
    5777                 :             :            component is restored in Fixed-H layer the parities needed by
    5778                 :             :            ConnectDisconnectedH() must be there before calling
    5779                 :             :            ConnectDisconnectedH()
    5780                 :             :         */
    5781                 :             :         /*CopySt2At( pStruct->at2, pStruct->st, pStruct->num_atoms );*/
    5782                 :             : 
    5783                 :           0 :         ret = ReconcileAllCmlBondParities( pStruct->at2, orig_inp_data->num_inp_atoms, 0 );
    5784         [ #  # ]:           0 :         if (ret < 0)
    5785                 :             :         {
    5786                 :           0 :             goto exit_error;
    5787                 :             :         }
    5788                 :             : 
    5789                 :             : #if USE_BCF
    5790                 :             :         memcpy_s( orig_inp_data->at, (long long)len, pStruct->at2, len ); /* djb-rwth: function replaced with its safe C11 variant */
    5791                 :             : #else
    5792                 :           0 :         memcpy(orig_inp_data->at, pStruct->at2, len);
    5793                 :             : #endif
    5794                 :             : 
    5795                 :           0 :         ClearEndpts( orig_inp_data->at, pStruct->num_atoms );
    5796                 :             : 
    5797         [ #  # ]:           0 :         if (FixUnkn0DStereoBonds( orig_inp_data->at, pStruct->num_atoms ))
    5798                 :             :         {
    5799                 :           0 :             ret = ReconcileAllCmlBondParities( pStruct->at2, orig_inp_data->num_inp_atoms, 0 );
    5800         [ #  # ]:           0 :             if (ret < 0)
    5801                 :             :             {
    5802                 :           0 :                 goto exit_error;
    5803                 :             :             }
    5804                 :             :         }
    5805                 :             :         /* keep endpoint[] markings in at2[] for subsequent add/remove protons */
    5806                 :             :     }
    5807                 :             :     else
    5808                 :             :     {
    5809                 :           0 :         ret = RI_ERR_ALLOC;
    5810                 :           0 :         goto exit_error;
    5811                 :             :     }
    5812                 :             : 
    5813                 :           0 :     memset( sd->num_components, 0, sizeof( sd->num_components ) ); /* djb-rwth: memset_s C11/Annex K variant? */
    5814                 :           0 :     memset( sd->num_taut, 0, sizeof( sd->num_taut ) ); /* djb-rwth: memset_s C11/Annex K variant? */
    5815                 :           0 :     memset( sd->num_non_taut, 0, sizeof( sd->num_non_taut ) ); /* djb-rwth: memset_s C11/Annex K variant? */
    5816                 :           0 :     memset( sd->bTautFlagsDone, 0, sizeof( sd->bTautFlagsDone ) ); /* djb-rwth: memset_s C11/Annex K variant? */
    5817                 :           0 :     memset( sd->bTautFlags, 0, sizeof( sd->bTautFlags ) ); /* djb-rwth: memset_s C11/Annex K variant? */
    5818                 :             : 
    5819                 :             : 
    5820                 :           0 :     ret = ProcessOneStructure( ic, pCG, sd, ip, szTitle,
    5821                 :           0 :                                pStruct->RevInChI.pINChI,
    5822                 :           0 :                                pStruct->RevInChI.pINChI_Aux,
    5823                 :             :                                NULL /*inp_file*/,
    5824                 :             :                                NULL /*log_file*/,
    5825                 :             :                                NULL /*out_file*/,
    5826                 :             :                                NULL /*prb_file*/,
    5827                 :             :                                orig_inp_data, prep_inp_data,
    5828                 :             :                                num_inp, strbuf,
    5829                 :             :                                0 /* save_opt_bits */ );
    5830                 :             : 
    5831                 :           0 :     memcpy(pStruct->RevInChI.num_components, sd->num_components, sizeof(pStruct->RevInChI.num_components));
    5832                 :           0 :     memcpy(sd_inp->pStrErrStruct, sd->pStrErrStruct, sizeof(sd_inp->pStrErrStruct));
    5833                 :           0 :     pStruct->RevInChI.nRetVal = ret;
    5834                 :             : 
    5835                 :             :     /* translate returned value */
    5836   [ #  #  #  #  :           0 :     if (ret == _IS_ERROR || ret == _IS_FATAL || ret == _IS_UNKNOWN)
                   #  # ]
    5837                 :             :     {
    5838                 :           0 :         ret = RI_ERR_PROGR;
    5839                 :             :     }
    5840         [ #  # ]:           0 :     else if (ret == _IS_OKAY)
    5841                 :             :     {
    5842                 :           0 :         ret = 0;
    5843                 :             :     }
    5844         [ #  # ]:           0 :     else if (ret == _IS_WARNING)
    5845                 :             :     {
    5846                 :           0 :         ret = 1;
    5847                 :             :     }
    5848                 :             :     else
    5849                 :             :     {
    5850                 :           0 :         ret = RI_ERR_PROGR;
    5851                 :             :     }
    5852                 :             : 
    5853                 :             :     /* save total charge from Mobile-H layer */
    5854                 :             : 
    5855                 :           0 :     pStruct->nChargeRevrs = 0;
    5856         [ #  # ]:           0 :     if (ret >= 0)
    5857                 :             :     {
    5858         [ #  # ]:           0 :         if (bRevInchiComponentExists( pStruct, INCHI_REC, TAUT_YES, 0 ))
    5859                 :             :         {
    5860                 :           0 :             pStruct->nChargeRevrs = pStruct->RevInChI.pINChI[INCHI_REC][0][TAUT_YES]->nTotalCharge;
    5861                 :             :         }
    5862         [ #  # ]:           0 :         else if (bRevInchiComponentExists( pStruct, INCHI_BAS, TAUT_YES, 0 ))
    5863                 :             :         {
    5864                 :           0 :             pStruct->nChargeRevrs = pStruct->RevInChI.pINChI[INCHI_BAS][0][TAUT_YES]->nTotalCharge;
    5865                 :             :         }
    5866                 :             :     }
    5867                 :             : 
    5868                 :             :     /* free structure data */
    5869                 :           0 :     FreeOrigAtData( orig_inp_data );
    5870                 :           0 :     FreeOrigAtData( prep_inp_data );
    5871                 :           0 :     FreeOrigAtData( prep_inp_data + 1 );
    5872                 :             : 
    5873                 :           0 : exit_error:
    5874                 :             : #if ( FIX_GAF_2019_2==1 )
    5875         [ #  # ]:           0 :     if (orig_inp_data->at)
    5876                 :             :     {
    5877                 :           0 :         FreeInpAtom(&orig_inp_data->at);
    5878                 :             :     }
    5879                 :             : #endif
    5880                 :           0 : early_exit_error:
    5881                 :           0 :     inchi_strbuf_close( strbuf );
    5882                 :             : 
    5883                 :           0 :     return ret;
    5884                 :             : }
    5885                 :             : 
    5886                 :             : 
    5887                 :             : /****************************************************************************/
    5888                 :           0 : int OutputInChIOutOfStrFromINChI( struct tagINCHI_CLOCK *ic,
    5889                 :             :                                   struct tagCANON_GLOBALS *pCG,
    5890                 :             :                                   ICHICONST INPUT_PARMS *ip_inp,
    5891                 :             :                                   STRUCT_DATA *sd_inp,
    5892                 :             :                                   long num_inp,
    5893                 :             :                                   int bINChIOutputOptions,
    5894                 :             :                                   INCHI_IOSTREAM *pout,
    5895                 :             :                                   INCHI_IOSTREAM *plog,
    5896                 :             :                                   InpInChI *pOneInput,
    5897                 :             :                                   int bHasSomeFixedH,
    5898                 :             :                                   unsigned char save_opt_bits )
    5899                 :             : {
    5900                 :             :     char szTitle[MAX_SDF_HEADER + MAX_SDF_VALUE + 256];
    5901                 :             : 
    5902                 :             :     int   len, ret;
    5903                 :             : /*
    5904                 :             :     PINChI2     *pINChI[INCHI_NUM];
    5905                 :             :     PINChI_Aux2 *pINChI_Aux[INCHI_NUM];
    5906                 :             : */
    5907                 :             :     REV_INCHI   RevInChI;
    5908                 :             : 
    5909                 :             :     INPUT_PARMS local_ip;
    5910                 :             :     STRUCT_DATA local_sd;
    5911                 :           0 :     INPUT_PARMS *ip = &local_ip;
    5912                 :           0 :     STRUCT_DATA *sd = &local_sd;
    5913                 :             : 
    5914                 :             :     ORIG_ATOM_DATA OrigAtData; /* 0=> disconnected, 1=> original */
    5915                 :           0 :     ORIG_ATOM_DATA *orig_inp_data = &OrigAtData;
    5916                 :             :     ORIG_ATOM_DATA PrepAtData[2]; /* 0=> disconnected, 1=> original */
    5917                 :           0 :     ORIG_ATOM_DATA *prep_inp_data = PrepAtData;
    5918                 :             : 
    5919                 :             :     INCHI_IOS_STRING temp_string_container;
    5920                 :           0 :     INCHI_IOS_STRING *strbuf = &temp_string_container;
    5921                 :           0 :     memset( strbuf, 0, sizeof( *strbuf ) ); /* djb-rwth: memset_s C11/Annex K variant? */
    5922                 :             : 
    5923         [ #  # ]:           0 :     if (0 >= inchi_strbuf_init( strbuf, INCHI_STRBUF_INITIAL_SIZE, INCHI_STRBUF_SIZE_INCREMENT ))
    5924                 :             :     {
    5925                 :           0 :         ret = RI_ERR_ALLOC;
    5926                 :           0 :         goto exit_error;
    5927                 :             :     }
    5928                 :             : 
    5929                 :           0 :     *ip = *ip_inp;
    5930                 :           0 :     ip->bNoStructLabels = 1;
    5931                 :           0 :     ip->bDisplay = 0;
    5932                 :           0 :     ip->bDisplayCompositeResults = 0;
    5933                 :           0 :     ip->bDisplayEachComponentINChI = 0;
    5934                 :           0 :     ip->bDisplayIfRestoreWarnings = 0;
    5935                 :             : 
    5936                 :             : #if ( I2S_MODIFY_OUTPUT == 1 )
    5937                 :             :     if (bINChIOutputOptions & INCHI_OUT_SDFILE_ONLY)
    5938                 :             :     {
    5939                 :             :         ip->bINChIOutputOptions = bINChIOutputOptions & ~( INCHI_OUT_PLAIN_TEXT | INCHI_OUT_PLAIN_TEXT_COMMENTS );
    5940                 :             :     }
    5941                 :             :     else
    5942                 :             :     {
    5943                 :             :         if (bINChIOutputOptions & INCHI_OUT_PLAIN_TEXT)
    5944                 :             :         {
    5945                 :             :             ip->bINChIOutputOptions = (bINChIOutputOptions & ~INCHI_OUT_SDFILE_ONLY) | INCHI_OUT_EMBED_REC; /* djb-rwth: addressing LLVM warning */
    5946                 :             :         }
    5947                 :             :         else
    5948                 :             :         {
    5949                 :             :             if (bINChIOutputOptions & ( INCHI_OUT_NO_AUX_INFO | INCHI_OUT_SHORT_AUX_INFO | INCHI_OUT_ONLY_AUX_INFO | INCHI_OUT_TABBED_OUTPUT ))
    5950                 :             :             {
    5951                 :             :                 ip->bINChIOutputOptions = ( INCHI_OUT_PLAIN_TEXT | INCHI_OUT_EMBED_REC | bINChIOutputOptions );
    5952                 :             :             }
    5953                 :             :             else
    5954                 :             :             {
    5955                 :             :                 ip->bINChIOutputOptions = ( INCHI_OUT_PLAIN_TEXT | INCHI_OUT_EMBED_REC );
    5956                 :             :             }
    5957                 :             :         }
    5958                 :             :     }
    5959                 :             : #else
    5960                 :           0 :     ip->bINChIOutputOptions = ( INCHI_OUT_PLAIN_TEXT | INCHI_OUT_EMBED_REC );
    5961                 :             : #endif
    5962                 :             : 
    5963         [ #  # ]:           0 :     if (bHasSomeFixedH)
    5964                 :             :     {
    5965                 :           0 :         ip->nMode |= ( REQ_MODE_TAUT | REQ_MODE_BASIC );
    5966                 :             :     }
    5967                 :             :     else
    5968                 :             :     {
    5969                 :           0 :         ip->nMode &= ~REQ_MODE_BASIC;
    5970                 :           0 :         ip->nMode |= REQ_MODE_TAUT;
    5971                 :             :     }
    5972                 :             : 
    5973                 :           0 :     memset( sd, 0, sizeof( *sd ) ); /* djb-rwth: memset_s C11/Annex K variant? */
    5974                 :           0 :     sd->fPtrStart = -1;
    5975                 :           0 :     sd->fPtrEnd = -1;
    5976                 :             :     /*
    5977                 :             :     if ( ip->nMode & REQ_MODE_STEREO ) {
    5978                 :             :         if ( ip->nMode & (REQ_MODE_RELATIVE_STEREO | REQ_MODE_RACEMIC_STEREO) ) {
    5979                 :             :             sd->bChiralFlag |= FLAG_INP_AT_NONCHIRAL;
    5980                 :             :         } else {
    5981                 :             :             sd->bChiralFlag |= FLAG_INP_AT_CHIRAL;
    5982                 :             :         }
    5983                 :             :     }
    5984                 :             :     */
    5985                 :           0 :     memset( orig_inp_data, 0, sizeof( *orig_inp_data ) ); /* djb-rwth: memset_s C11/Annex K variant? */
    5986                 :           0 :     memset( prep_inp_data, 0, 2 * sizeof( *prep_inp_data ) ); /* djb-rwth: memset_s C11/Annex K variant? */
    5987                 :           0 :     memset( RevInChI.pINChI, 0, sizeof( RevInChI.pINChI ) ); /* djb-rwth: memset_s C11/Annex K variant? */
    5988                 :           0 :     memset( RevInChI.pINChI_Aux, 0, sizeof( RevInChI.pINChI_Aux ) ); /* djb-rwth: memset_s C11/Annex K variant? */
    5989                 :             : 
    5990                 :           0 :     len = sizeof( orig_inp_data->at[0] ) * pOneInput->num_atoms;
    5991                 :           0 :     orig_inp_data->at = (inp_ATOM *) inchi_malloc( len );
    5992                 :           0 :     orig_inp_data->szCoord = (MOL_COORD *) inchi_calloc( pOneInput->num_atoms, sizeof( orig_inp_data->szCoord[0] ) );
    5993                 :             : 
    5994                 :           0 :     orig_inp_data->polymer = pOneInput->polymer;
    5995                 :           0 :     orig_inp_data->v3000 = pOneInput->v3000;
    5996                 :           0 :     pOneInput->polymer = NULL;
    5997                 :           0 :     pOneInput->v3000 = NULL;
    5998                 :           0 :     orig_inp_data->valid_polymer = pOneInput->valid_polymer;
    5999                 :             : 
    6000   [ #  #  #  # ]:           0 :     if (orig_inp_data->at && orig_inp_data->szCoord)
    6001                 :           0 :     {
    6002                 :             :         int i, k;
    6003                 :           0 :         memcpy(orig_inp_data->at, pOneInput->atom, len);
    6004                 :           0 :         orig_inp_data->num_inp_atoms = pOneInput->num_atoms;
    6005                 :           0 :         ClearEndpts( orig_inp_data->at, orig_inp_data->num_inp_atoms );
    6006                 :             :         /* otherwise fails on CID=450438 */
    6007         [ #  # ]:           0 :         if (FixUnkn0DStereoBonds( orig_inp_data->at, orig_inp_data->num_inp_atoms ))
    6008                 :             :         {
    6009                 :           0 :             ret = ReconcileAllCmlBondParities( orig_inp_data->at, orig_inp_data->num_inp_atoms, 0 );
    6010         [ #  # ]:           0 :             if (ret < 0)
    6011                 :             :             {
    6012                 :             :                 /* djb-rwth: fixing a NULL pointer dereference */
    6013                 :           0 :                 free(orig_inp_data->at);
    6014                 :           0 :                 free(orig_inp_data->szCoord);
    6015                 :           0 :                 goto exit_error;
    6016                 :             :             }
    6017                 :             :         }
    6018                 :             : 
    6019                 :             :         /* To obtain rA,rB,rC in AuxInfo we have to emulate input coordinates; make all of them zeroes */
    6020         [ #  # ]:           0 :         for (i = 0; i < pOneInput->num_atoms; i++)
    6021                 :             :         {
    6022         [ #  # ]:           0 :             for (k = 0; k < NUM_COORD*LEN_COORD; k += LEN_COORD)
    6023                 :             :             {
    6024                 :           0 :                 orig_inp_data->szCoord[i][k] = '0';
    6025                 :             :             }
    6026                 :             :         }
    6027                 :             :     }
    6028                 :             :     else
    6029                 :             :     {
    6030                 :             :         /* djb-rwth: fixing a NULL pointer dereference */
    6031                 :           0 :         ret = RI_ERR_ALLOC;
    6032                 :           0 :         free(orig_inp_data->at);
    6033                 :           0 :         free(orig_inp_data->szCoord);
    6034                 :           0 :         goto exit_error;
    6035                 :             :     }
    6036                 :             : 
    6037                 :           0 :     memset( sd->num_components, 0, sizeof( sd->num_components ) ); /* djb-rwth: memset_s C11/Annex K variant? */
    6038                 :           0 :     memset( sd->num_taut, 0, sizeof( sd->num_taut ) ); /* djb-rwth: memset_s C11/Annex K variant? */
    6039                 :           0 :     memset( sd->num_non_taut, 0, sizeof( sd->num_non_taut ) ); /* djb-rwth: memset_s C11/Annex K variant? */
    6040                 :           0 :     memset( sd->bTautFlagsDone, 0, sizeof( sd->bTautFlagsDone ) ); /* djb-rwth: memset_s C11/Annex K variant? */
    6041                 :           0 :     memset( sd->bTautFlags, 0, sizeof( sd->bTautFlags ) ); /* djb-rwth: memset_s C11/Annex K variant? */
    6042                 :           0 :     memset( szTitle, 0, sizeof( szTitle ) ); /* djb-rwth: memset_s C11/Annex K variant? */
    6043                 :             : 
    6044                 :             : 
    6045                 :             : 
    6046                 :           0 :     ret = ProcessOneStructure( ic, pCG, sd, ip, szTitle,
    6047                 :             :                                RevInChI.pINChI,
    6048                 :             :                                RevInChI.pINChI_Aux,
    6049                 :             :                                NULL /*inp_file*/,
    6050                 :             :                                plog /*log_file*/,
    6051                 :             :                                pout /*out_file*/,
    6052                 :             :                                NULL /*prb_file*/,
    6053                 :             :                                orig_inp_data, prep_inp_data,
    6054                 :             :                                num_inp, strbuf, save_opt_bits );
    6055                 :             : 
    6056                 :           0 :     memcpy(RevInChI.num_components, sd->num_components, sizeof(RevInChI.num_components));
    6057                 :             :     /*
    6058                 :             :     memcpy(sd_inp->pStrErrStruct, sd->pStrErrStruct, sizeof(sd_inp->pStrErrStruct) );
    6059                 :             :     */
    6060                 :             : 
    6061                 :           0 :     RevInChI.nRetVal = ret;
    6062                 :             : 
    6063                 :             :     /* translate returned value */
    6064   [ #  #  #  #  :           0 :     if (ret == _IS_ERROR || ret == _IS_FATAL || ret == _IS_UNKNOWN)
                   #  # ]
    6065                 :             :     {
    6066                 :           0 :         ret = RI_ERR_PROGR;
    6067                 :             :     }
    6068         [ #  # ]:           0 :     else if (ret == _IS_OKAY)
    6069                 :             :     {
    6070                 :           0 :         ret = 0;
    6071                 :             :     }
    6072         [ #  # ]:           0 :     else if (ret == _IS_WARNING)
    6073                 :             :     {
    6074                 :           0 :         ret = 1;
    6075                 :             :     }
    6076                 :             :     else
    6077                 :             :     {
    6078                 :           0 :         ret = RI_ERR_PROGR;
    6079                 :             :     }
    6080                 :             : 
    6081                 :             :     /* free structure data */
    6082                 :           0 :     FreeOrigAtData( orig_inp_data );
    6083                 :           0 :     FreeOrigAtData( prep_inp_data );
    6084                 :           0 :     FreeOrigAtData( prep_inp_data + 1 );
    6085                 :           0 :     FreeAllINChIArrays( RevInChI.pINChI,
    6086                 :             :                         RevInChI.pINChI_Aux,
    6087                 :             :                         RevInChI.num_components );
    6088                 :             : 
    6089                 :             : 
    6090                 :           0 : exit_error:
    6091                 :           0 :     inchi_strbuf_close( strbuf );
    6092                 :             : 
    6093                 :           0 :     return ret;
    6094                 :             : }
    6095                 :             : #endif
        

Generated by: LCOV version 2.0-1