LCOV - code coverage report
Current view: top level - src - ichister.c (source / functions) Coverage Total Hit
Test: InChI Unit Test Coverage Lines: 38.5 % 1632 628
Test Date: 2026-05-04 07:05:02 Functions: 65.1 % 43 28
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 26.9 % 1633 439

             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 <math.h>
      42                 :             : #include <string.h>
      43                 :             : 
      44                 :             : #include "mode.h"
      45                 :             : #include "ichister.h"
      46                 :             : #include "ichiring.h"
      47                 :             : #include "ichi.h"
      48                 :             : #include "ichitaut.h"
      49                 :             : #include "ichicomp.h"
      50                 :             : #include "ichicant.h"
      51                 :             : #include "util.h"
      52                 :             : 
      53                 :             : #include "bcf_s.h"
      54                 :             : 
      55                 :             : #define    ZTYPE_DOWN     (-1)  /*  should be equal to -ZTYPE_UP */
      56                 :             : #define    ZTYPE_NONE     0
      57                 :             : #define    ZTYPE_UP       1     /*  should be equal to -ZTYPE_DOWN */
      58                 :             : #define    ZTYPE_3D       3
      59                 :             : #define    ZTYPE_EITHER   9999
      60                 :             : 
      61                 :             : #define ARR_DIM 3 /* djb-rwth: default dimension of arrays */
      62                 :             : 
      63                 :             : /*  criteria for ill-defined */
      64                 :             : #define MIN_ANGLE             0.10    /*  5.73 degrees */ /* treshold for proximity to in-line angle of 180 deg */
      65                 :             : #define MIN_SINE              0.03    /*min edge/plane angle in case the tetrahedra has significantly different edge length */
      66                 :             : #define MIN_ANGLE_RELAXED     0.001
      67                 :             : #define MIN_SINE_RELAXED      0.001
      68                 :             : #define MIN_ANGLE_DBOND       0.087156 /* 5 degrees = max angle considered as too small for unambiguous double bond stereo */
      69                 :             : #define MIN_SINE_OUTSIDE      0.06   /*  min edge/plane angle to determine whether the central atom is outside of the tetrahedra */
      70                 :             : #define MIN_SINE_SQUARE       0.125  /*  min edge/plane angle in case the tetrahedra is somewhat close to a parallelogram */
      71                 :             : #define MIN_SINE_EDGE         0.167  /*  min sine/(min.edge) ratio to avoid undefined in case of long edges */
      72                 :             : #define MIN_LEN_STRAIGHT      1.900  /*  min length of two normalized to 1 bonds in a straight line */
      73                 :             : #define MAX_SINE              0.70710678118654752440084436210485 /*  1/sqrt(2)=sin(pi/4) */
      74                 :             : #define MIN_BOND_LEN          0.000001
      75                 :             : #define ZERO_LENGTH           MIN_BOND_LEN
      76                 :             : #define ZERO_FLOAT            1.0e-12
      77                 :             : #define BOND_PARITY_UNDEFINED 64
      78                 :             : #if ( STEREO_CENTER_BONDS_NORM == 1 )
      79                 :             : #define MPY_SINE              1.00  /*  was 3.0 */
      80                 :             : #define MAX_EDGE_RATIO        2.50   /*  max max/min edge ratio for a tetrahedra close to a parallelogram  */
      81                 :             : #else
      82                 :             : #define MPY_SINE              3.00
      83                 :             : #define MAX_EDGE_RATIO        6.00   /*  max max/min edge ratio for a tetrahedra close to a parallelogram  */
      84                 :             : #endif
      85                 :             : /*  local prototypes */
      86                 :             : static int save_a_stereo_bond( int z_prod, int result_action,
      87                 :             :                         int at1, int ord1, AT_NUMB *stereo_bond_neighbor1, S_CHAR *stereo_bond_ord1, S_CHAR *stereo_bond_z_prod1, S_CHAR *stereo_bond_parity1,
      88                 :             :                         int at2, int ord2, AT_NUMB *stereo_bond_neighbor2, S_CHAR *stereo_bond_ord2, S_CHAR *stereo_bond_z_prod2, S_CHAR *stereo_bond_parity2 );
      89                 :             : static double get_z_coord( inp_ATOM* at, int cur_atom, int neigh_no, int *nType, int bPointedEdgeStereo );
      90                 :             : static double len3( const double c[] );
      91                 :             : static double len2( const double c[] );
      92                 :             : static void* diff3( const double a[], const double b[], double result[] );
      93                 :             : static void add3( const double a[], const double b[], double result[] );
      94                 :             : static void mult3( const double a[], double b, double result[] );
      95                 :             : /* static double* copy3(const double a[], double result[]); */
      96                 :             : static void change_sign3( const double a[], double result[] );
      97                 :             : double dot_prod3( const double a[], const double b[] );
      98                 :             : static int dot_prodchar3( const S_CHAR a[], const S_CHAR b[] );
      99                 :             : static double triple_prod( double a[], double b[], double c[], double *sine_value );
     100                 :             : static double triple_prod_and_min_abs_sine( double at_coord[][3], double *min_sine );
     101                 :             : static int are_3_vect_in_one_plane( double at_coord[][3], double min_sine );
     102                 :             : static int triple_prod_char( inp_ATOM *at, int at_1, int i_next_at_1, S_CHAR *z_dir1,
     103                 :             :                                            int at_2, int i_next_at_2, S_CHAR *z_dir2 );
     104                 :             : 
     105                 :             : static int CompDble( const void *a1, const void *a2, void * );
     106                 :             : static int Get2DTetrahedralAmbiguity( CANON_GLOBALS *pCG, double at_coord[][3], int bAddExplicitNeighbor, int bFix2DstereoBorderCase, double vMinAngle );
     107                 :             : static double triple_prod_and_min_abs_sine2( double at_coord[][3], double central_at_coord[], int bAddedExplicitNeighbor,
     108                 :             :                                             double *min_sine, int *bAmbiguous, double vMinSine );
     109                 :             : static int are_4at_in_one_plane( double at_coord[][3], double min_sine );
     110                 :             : static int bInpAtomHasRequirdNeigh( inp_ATOM *at, int cur_at, int RequirdNeighType, int NumDbleBonds, int bStereoAtZz );
     111                 :             : static int bIsSuitableHeteroInpAtom( inp_ATOM  *at );
     112                 :             : static int bIsOxide( inp_ATOM  *at, int cur_at );
     113                 :             : static int half_stereo_bond_parity( inp_ATOM *at, int cur_at, inp_ATOM *at_removed_H, int num_removed_H, S_CHAR *z_dir,
     114                 :             :                                    int bPointedEdgeStereo, int vABParityUnknown );
     115                 :             : static int get_allowed_stereo_bond_type( int bond_type );
     116                 :             : static int can_be_a_stereo_bond_with_isotopic_H( inp_ATOM *at, int cur_at, INCHI_MODE nMode );
     117                 :             : static int half_stereo_bond_action( int nParity, int bUnknown, int bIsotopic, int vABParityUnknown );
     118                 :             : static int set_stereo_bonds_parity( sp_ATOM *out_at, inp_ATOM *at, int at_1, inp_ATOM *at_removed_H, int num_removed_H,
     119                 :             :                                    INCHI_MODE nMode, QUEUE *q, AT_RANK *nAtomLevel,
     120                 :             :                                    S_CHAR *cSource, AT_RANK min_sb_ring_size,
     121                 :             :                                    int bPointedEdgeStereo, int vABParityUnknown );
     122                 :             : static int can_be_a_stereo_atom_with_isotopic_H( inp_ATOM *at, int cur_at, int bPointedEdgeStereo, int bStereoAtZz );
     123                 :             : static int set_stereo_atom_parity( CANON_GLOBALS *pCG, sp_ATOM *out_at, inp_ATOM *at, int cur_at, inp_ATOM *at_removed_H, int num_removed_H,
     124                 :             :                                   int bPointedEdgeStereo, int vABParityUnknown, int LooseTSACheck, int bStereoAtZz );
     125                 :             : /*
     126                 :             : int get_opposite_sb_atom( inp_ATOM *at, int cur_atom, int icur2nxt, int *pnxt_atom, int *pinxt2cur, int *pinxt_sb_parity_ord );
     127                 :             : */
     128                 :             : int ReconcileCmlIncidentBondParities( inp_ATOM *at, int cur_atom, int prev_atom, S_CHAR *visited, int bDisconnected );
     129                 :             : int comp_AT_NUMB( const void* a1, const void* a2, void * );
     130                 :             : int GetHalfStereobond0DParity( inp_ATOM *at, int cur_at, AT_NUMB nSbNeighOrigAtNumb[], int nNumExplictAttachments, int bond_parity, int nFlag );
     131                 :             : int GetStereocenter0DParity( CANON_GLOBALS *pCG, inp_ATOM *at, int cur_at, int j1, AT_NUMB nSbNeighOrigAtNumb[], int nFlag );
     132                 :             : int GetSbNeighOrigAtNumb( inp_ATOM *at, int cur_at, inp_ATOM *at_removed_H, int num_removed_H, AT_NUMB nSbNeighOrigAtNumb[] );
     133                 :             : int FixSb0DParities( inp_ATOM *at, /* inp_ATOM *at_removed_H, int num_removed_H,*/ int chain_length,
     134                 :             :                      int at_1, int i_next_at_1, S_CHAR z_dir1[],
     135                 :             :                      int at_2, int i_next_at_2, S_CHAR z_dir2[],
     136                 :             :                      int *pparity1, int *pparity2 );
     137                 :             : 
     138                 :             : 
     139                 :             : /****************************************************************************/
     140                 :           0 : int comp_AT_NUMB( const void* a1, const void* a2, void *p )
     141                 :             : {
     142                 :           0 :     return (int)(*(const AT_NUMB*)a1) - (int)(*(const AT_NUMB*)a2);
     143                 :             : }
     144                 :             : 
     145                 :             : 
     146                 :             : /****************************************************************************/
     147                 :         597 : double get_z_coord( inp_ATOM* at,
     148                 :             :                     int cur_atom,
     149                 :             :                     int neigh_no,
     150                 :             :                     int *nType,
     151                 :             :                     int bPointedEdgeStereo )
     152                 :             : {
     153                 :         597 :     int stereo_value = at[cur_atom].bond_stereo[neigh_no];
     154                 :         597 :     int stereo_type = abs( stereo_value );
     155                 :         597 :     int neigh = (int) at[cur_atom].neighbor[neigh_no];
     156                 :         597 :     double z = at[neigh].z - at[cur_atom].z;
     157                 :             :     int    bFlat;
     158                 :             : 
     159         [ +  - ]:         597 :     if ((bFlat = ( fabs( z ) < ZERO_LENGTH ))) /* djb-rwth: addressing LLVM warning */
     160                 :             :     {
     161                 :             :         int i;
     162         [ +  + ]:        2388 :         for (i = 0; i < at[cur_atom].valence; i++)
     163                 :             :         {
     164         [ -  + ]:        1791 :             if (fabs( at[cur_atom].z - at[(int) at[cur_atom].neighbor[i]].z ) > ZERO_LENGTH)
     165                 :             :             {
     166                 :           0 :                 bFlat = 0;
     167                 :           0 :                 break;
     168                 :             :             }
     169                 :             :         }
     170                 :             :     }
     171                 :             : 
     172         [ +  - ]:         597 :     if (bFlat)
     173                 :             :     {
     174   [ +  -  +  - ]:         597 :         if (!bPointedEdgeStereo || bPointedEdgeStereo * stereo_value >= 0)
     175                 :             :         {
     176                 :             :             /* bPointedEdgeStereo > 0: define stereo from pointed end of the stereo bond only */
     177                 :             :             /* bPointedEdgeStereo < 0: define stereo from wide end of the stereo bond only (case of removed H) */
     178   [ +  +  -  +  :         597 :             switch (stereo_type)
                      - ]
     179                 :             :             {
     180                 :             :                 /*  1=Up (solid triangle), 6=Down (Dashed triangle), 4=Either (zigzag triangle) */
     181                 :         420 :                 case 0: /*  No stereo */
     182                 :         420 :                     *nType = ZTYPE_NONE;
     183                 :         420 :                     break;
     184                 :         146 :                 case STEREO_SNGL_UP: /*  1= Up */
     185                 :         146 :                     *nType = ZTYPE_UP;
     186                 :         146 :                     break;
     187                 :           0 :                 case STEREO_SNGL_EITHER: /*  4 = Either */
     188                 :           0 :                     *nType = ZTYPE_EITHER;
     189                 :           0 :                     break;
     190                 :          31 :                 case STEREO_SNGL_DOWN: /*  6 = Down */
     191                 :          31 :                     *nType = ZTYPE_DOWN;
     192                 :          31 :                     break;
     193                 :           0 :                 default:
     194                 :           0 :                     *nType = ZTYPE_NONE; /*  ignore unexpected values */
     195                 :             :             }
     196   [ -  +  -  -  :         597 :             if (stereo_value < 0 && ( *nType == ZTYPE_DOWN || *nType == ZTYPE_UP ))
                   -  - ]
     197                 :           0 :                 *nType = -*nType;
     198                 :             :         }
     199                 :             :         else
     200                 :             :         {
     201                 :           0 :             *nType = ZTYPE_NONE; /* no stereo */
     202                 :             :         }
     203                 :             :     }
     204                 :             :     else
     205                 :             :     {
     206   [ #  #  #  # ]:           0 :         if (stereo_type == STEREO_SNGL_EITHER &&
     207         [ #  # ]:           0 :             ( !bPointedEdgeStereo || bPointedEdgeStereo * stereo_value >= 0 ))
     208                 :             :         {
     209                 :           0 :             *nType = ZTYPE_EITHER;
     210                 :             :         }
     211                 :             :         else
     212                 :             :         {
     213                 :           0 :             *nType = ZTYPE_3D;
     214                 :             :         }
     215                 :             :     }
     216                 :             : 
     217                 :         597 :     return z;
     218                 :             : }
     219                 :             : 
     220                 :             : /****************************************************************************/
     221                 :        3960 : double len3( const double c[] ) /* djb-rwth: avoiding uninitialised values */
     222                 :             : {
     223                 :        3960 :     double tmpar[ARR_DIM] = { 0.0 };
     224                 :             : #if USE_BCF
     225                 :             :     memcpy_s(tmpar, ARR_DIM * sizeof(c[0]), c, ARR_DIM * sizeof(c[0]));
     226                 :             : #else
     227                 :        3960 :     memcpy(tmpar, c, ARR_DIM * sizeof(c[0]));
     228                 :             : #endif
     229                 :        3960 :     return sqrt(pow(tmpar[0],2.0) + pow(tmpar[1],2.0) + pow(tmpar[2],2.0) );
     230                 :             : }
     231                 :             : 
     232                 :             : 
     233                 :             : /****************************************************************************/
     234                 :         597 : double len2( const double c[] ) /* djb-rwth: avoiding uninitialised values */
     235                 :             : {
     236                 :         597 :     double tmpar[ARR_DIM - 1] = { 0,0 };
     237                 :             : #if USE_BCF
     238                 :             :     memcpy_s(tmpar, (ARR_DIM - 1) * sizeof(c[0]), c, (ARR_DIM - 1) * sizeof(c[0]));
     239                 :             : #else
     240                 :         597 :     memcpy(tmpar, c, (ARR_DIM - 1) * sizeof(c[0]));
     241                 :             : #endif
     242                 :         597 :     return sqrt(pow(tmpar[0],2.0) + pow(tmpar[1],2.0));
     243                 :             : }
     244                 :             : 
     245                 :             : 
     246                 :             : /****************************************************************************/
     247                 :        1416 : void* diff3( const double a[], const double b[], double result[] ) /* djb-rwth: changed function type */
     248                 :             : {
     249                 :             : 
     250                 :        1416 :     result[0] = a[0] - b[0];
     251                 :        1416 :     result[1] = a[1] - b[1];
     252                 :        1416 :     result[2] = a[2] - b[2];
     253                 :             : 
     254                 :        1416 :     return result;
     255                 :             : }
     256                 :             : 
     257                 :             : 
     258                 :             : /****************************************************************************/
     259                 :         597 : void add3( const double a[], const double b[], double result[] ) /* djb-rwth: changed function type */
     260                 :             : {
     261                 :         597 :     result[0] = a[0] + b[0];
     262                 :         597 :     result[1] = a[1] + b[1];
     263                 :         597 :     result[2] = a[2] + b[2];
     264                 :             : 
     265                 :             :     /* return result; */
     266                 :         597 : }
     267                 :             : 
     268                 :             : 
     269                 :             : /****************************************************************************/
     270                 :         597 : void mult3( const double a[], double b, double result[] ) /* djb-rwth: changed function type */
     271                 :             : {
     272                 :         597 :     result[0] = a[0] * b;
     273                 :         597 :     result[1] = a[1] * b;
     274                 :         597 :     result[2] = a[2] * b;
     275                 :             : 
     276                 :             :     /* return result; */
     277                 :         597 : }
     278                 :             : 
     279                 :             : 
     280                 :             : /****************************************************************************/
     281                 :             : /* double* copy3(const double a[], double result[]) -- djb-rwth: removing the function completely
     282                 :             : {
     283                 :             :     result[0] = a[0];
     284                 :             :     result[1] = a[1];
     285                 :             :     result[2] = a[2];
     286                 :             : 
     287                 :             :     return result;
     288                 :             : } */
     289                 :             : 
     290                 :             : 
     291                 :             : /****************************************************************************/
     292                 :         177 : void change_sign3( const double a[], double result[] ) /* djb-rwth: changed function type */
     293                 :             : {
     294                 :         177 :     result[0] = -a[0];
     295                 :         177 :     result[1] = -a[1];
     296                 :         177 :     result[2] = -a[2];
     297                 :             : 
     298                 :             :     /* return result; */
     299                 :         177 : }
     300                 :             : 
     301                 :             : 
     302                 :             : /****************************************************************************/
     303                 :        1416 : double dot_prod3( const double a[], const double b[] )
     304                 :             : {
     305                 :        1416 :     return a[0]*b[0] + a[1]*b[1] + a[2]*b[2];
     306                 :             : }
     307                 :             : 
     308                 :             : 
     309                 :             : /****************************************************************************/
     310                 :           0 : int dot_prodchar3( const S_CHAR a[], const S_CHAR b[] )
     311                 :             : {
     312                 :           0 :     int prod = ( (int)a[0]*(int)b[0] + (int)a[1]*(int)b[1] + (int)a[2]*(int)b[2] ) / 100;
     313         [ #  # ]:           0 :     if (prod > 100)
     314                 :             :     {
     315                 :           0 :         prod = 100;
     316                 :             :     }
     317                 :             :     else
     318                 :             :     {
     319         [ #  # ]:           0 :         if (prod < -100)
     320                 :             :         {
     321                 :           0 :             prod = -100;
     322                 :             :         }
     323                 :             :     }
     324                 :             : 
     325                 :           0 :     return prod;
     326                 :             : }
     327                 :             : 
     328                 :             : 
     329                 :             : /****************************************************************************/
     330                 :        2124 : void* cross_prod3( const double a[], const double b[], double result[] ) /* djb-rwth: changed function type */
     331                 :             : {
     332                 :             :     double tmp[3];
     333                 :             : 
     334                 :        2124 :     tmp[0] = ( a[1] * b[2] - a[2] * b[1] );
     335                 :        2124 :     tmp[1] = -( a[0] * b[2] - a[2] * b[0] );
     336                 :        2124 :     tmp[2] = ( a[0] * b[1] - a[1] * b[0] );
     337                 :             : 
     338                 :        2124 :     result[0] = tmp[0];
     339                 :        2124 :     result[1] = tmp[1];
     340                 :        2124 :     result[2] = tmp[2];
     341                 :             : 
     342                 :        2124 :     return result;
     343                 :             : }
     344                 :             : 
     345                 :             : 
     346                 :             : /****************************************************************************/
     347                 :        1416 : double triple_prod( double a[], double b[], double c[], double *sine_value )
     348                 :             : {
     349                 :             :     double ab[3], dot_prod_ab_c, abs_c, abs_ab;
     350                 :        1416 :     cross_prod3( a, b, ab );
     351                 :             :     /* ab[0] =  (a[1]*b[2]-a[2]*b[1]); */
     352                 :             :     /* ab[1] = -(a[0]*b[2]-a[2]*b[0]); */
     353                 :             :     /* ab[2] =  (a[0]*b[1]-a[1]*b[0]); */
     354                 :        1416 :     dot_prod_ab_c = dot_prod3( ab, c );
     355                 :             :     /* dot_prod_ab_c   =  ab[0]*c[0] + ab[1]*c[1] + ab[2]*c[2]; */
     356         [ +  + ]:        1416 :     if (sine_value)
     357                 :             :     {
     358                 :         708 :         abs_c = len3( c );
     359                 :             :         /* abs_c  = sqrt( c[0]*c[0]   + c[1]*c[1]   + c[2]*c[2] ); */
     360                 :         708 :         abs_ab = len3( ab );
     361                 :             :         /* abs_ab = sqrt( ab[0]*ab[0] + ab[1]*ab[1] + ab[2]*ab[2] ); */
     362                 :             : 
     363   [ +  -  +  - ]:         708 :         if (abs_c > 1.e-7 /* otherwise c has zero length */ && abs_ab > 1.e-7 /* otherwise a is parallel to b*/)
     364                 :             :         {
     365                 :         708 :             *sine_value = MPY_SINE * dot_prod_ab_c / ( abs_c * abs_ab );
     366                 :             :             /*  *sine_value = dot_prod_ab_c / ( abs_c * abs_ab); */
     367                 :             :         }
     368                 :             :         else
     369                 :             :         {
     370                 :           0 :             *sine_value = 0.0;
     371                 :             :         }
     372                 :             :     }
     373                 :             : 
     374                 :        1416 :     return dot_prod_ab_c;
     375                 :             : }
     376                 :             : 
     377                 :             : 
     378                 :             : /****************************************************************************/
     379                 :         471 : int CompDble( const void *a1, const void *a2, void *p )
     380                 :             : {
     381                 :         471 :     double *pDoubleForSort = (double *) p;
     382                 :         471 :     double diff = pDoubleForSort[*(const int*) a1] - pDoubleForSort[*(const int*) a2];
     383         [ +  + ]:         471 :     if (diff > 0.0)
     384                 :             :     {
     385                 :         305 :         return 1;
     386                 :             :     }
     387         [ +  - ]:         166 :     if (diff < 0.0)
     388                 :             :     {
     389                 :         166 :         return -1;
     390                 :             :     }
     391                 :           0 :     return 0;
     392                 :             : }
     393                 :             : 
     394                 :             : 
     395                 :             : /****************************************************************************/
     396                 :             : #define T2D_OKAY  1
     397                 :             : #define T2D_WARN  2
     398                 :             : #define T2D_UNDF  4
     399                 :             : 
     400                 :             : 
     401                 :             : /****************************************************************************/
     402                 :         177 : int Get2DTetrahedralAmbiguity( CANON_GLOBALS *pCG,
     403                 :             :                                double at_coord[][3],
     404                 :             :                                int bAddExplicitNeighbor,
     405                 :             :                                int bFix2DstereoBorderCase,
     406                 :             :                                double vMinAngle )
     407                 :             : {
     408                 :             :     /*    const double one_pi = 2.0*atan2(1.0 , 0.0 ); */
     409                 :         177 :     const double one_pi = 3.14159265358979323846; /* M_PI */
     410                 :         177 :     const double two_pi = 2.0*one_pi;
     411                 :         177 :     const double dAngleAndPiMaxDiff = 2.0*atan2( 1.0, sqrt( 7.0 ) ); /*  min sine between 2 InPlane bonds */
     412                 :             :     double *pDoubleForSort;
     413                 :             :     int    nBondType[MAX_NUM_STEREO_ATOM_NEIGH], nBondOrder[MAX_NUM_STEREO_ATOM_NEIGH];
     414                 :             :     double dBondDirection[MAX_NUM_STEREO_ATOM_NEIGH];
     415                 :             :     volatile double dAngle, dAlpha, dLimit, dBisector;
     416                 :             :     /* 2010-02-10  added 'volatile': workaround ensuring proper behavior for gcc 32-bit */
     417                 :             :     /* cml-enabled compiles at >=O1 for SID484922 and alike (both lin&win had problems) */
     418         [ +  - ]:         177 :     int  nNumNeigh = MAX_NUM_STEREO_ATOM_NEIGH - ( bAddExplicitNeighbor != 0 );
     419                 :         177 :     int  i, num_Up, num_Dn, bPrev_Up, cur_len_Up, cur_first_Up, len_Up, first_Up = 0; /* djb-rwth: initialisation required to avoid garbage values */
     420                 :         177 :     int  ret = 0;
     421                 :             : 
     422         [ +  + ]:         708 :     for (i = 0, num_Up = num_Dn = 0; i < nNumNeigh; i++)
     423                 :             :     {
     424                 :         531 :         dAngle = atan2( at_coord[i][1], at_coord[i][0] ); /*  range from -pi to +pi */
     425         [ +  + ]:         531 :         if (dAngle < 0.0)
     426                 :             :         {
     427                 :         261 :             dAngle += two_pi;
     428                 :             :         }
     429                 :         531 :         dBondDirection[i] = dAngle;
     430   [ +  +  +  + ]:         531 :         nBondType[i] = ( at_coord[i][2] > 0.0 ) ? 1 : ( at_coord[i][2] < 0.0 ) ? -1 : 0; /* z-coord sign */
     431         [ +  + ]:         531 :         if (nBondType[i] > 0)
     432                 :             :         {
     433                 :         146 :             num_Up++;
     434                 :             :         }
     435                 :             :         else
     436                 :             :         {
     437         [ +  + ]:         385 :             if (nBondType[i] < 0)
     438                 :             :             {
     439                 :          31 :                 num_Dn++;
     440                 :             :             }
     441                 :             :         }
     442                 :         531 :         nBondOrder[i] = i;
     443                 :             :     }
     444         [ +  + ]:         177 :     if (num_Up < num_Dn)
     445                 :             :     {
     446         [ +  + ]:         124 :         for (i = 0; i < nNumNeigh; i++)
     447                 :             :         {
     448                 :          93 :             nBondType[i] = -nBondType[i];
     449                 :             :         }
     450                 :          31 :         inchi_swap( (char*) &num_Dn, (char*) &num_Up, sizeof( num_Dn ) );
     451                 :             :     }
     452         [ -  + ]:         177 :     if (!num_Up)
     453                 :             :     {
     454                 :           0 :         return T2D_UNDF;
     455                 :             :     }
     456                 :             : 
     457                 :             :     /*  Sort according to the bond orientations */
     458                 :         177 :     pDoubleForSort = dBondDirection;
     459                 :         177 :     insertions_sort( pDoubleForSort, nBondOrder, nNumNeigh,
     460                 :             :                      sizeof( nBondOrder[0] ), CompDble );
     461                 :             : 
     462                 :             :     /*  Find the longest contiguous sequence of Up bonds */
     463         [ -  + ]:         177 :     if (num_Up == nNumNeigh)
     464                 :             :     {
     465                 :             :         /*  all bonds are Up */
     466                 :           0 :         len_Up = cur_len_Up = nNumNeigh; /* added cur_len_Up initialization 1/8/2002 */
     467                 :           0 :         first_Up = 0;
     468                 :             :     }
     469                 :             :     else
     470                 :             :     {
     471                 :             :         /*  at least one bond is not Up */
     472                 :         177 :         cur_len_Up = len_Up = bPrev_Up = 0;
     473                 :             :         /* prev. cycle header version ---
     474                 :             :         for ( i = 0; 1; i ++ )
     475                 :             :         {
     476                 :             :             if ( i >= nNumNeigh && !bPrev_Up )
     477                 :             :             {
     478                 :             :                 break;
     479                 :             :             }
     480                 :             :         ----------
     481                 :             :         }
     482                 :             :         */
     483                 :             : 
     484                 :             :         /* look at all bonds and continue (circle therough the beginning) as long as the current bond is Up */
     485   [ +  +  +  + ]:         780 :         for (i = 0; i < nNumNeigh || bPrev_Up; i++)
     486                 :             :         {
     487         [ +  + ]:         603 :             if (nBondType[nBondOrder[i % nNumNeigh]] > 0)
     488                 :             :             {
     489         [ -  + ]:         177 :                 if (bPrev_Up)
     490                 :             :                 {
     491                 :           0 :                     cur_len_Up++; /* uncrement number of Up bonds in current contiguous sequence of them */
     492                 :             :                 }
     493                 :             :                 else
     494                 :             :                 {
     495                 :         177 :                     bPrev_Up = 1; /* start new contiguous sequence of Up bonds */
     496                 :         177 :                     cur_len_Up = 1;
     497                 :         177 :                     cur_first_Up = i % nNumNeigh;
     498                 :             :                 }
     499                 :             :             }
     500                 :             :             else
     501                 :             :             {
     502         [ +  + ]:         426 :                 if (bPrev_Up)
     503                 :             :                 { /* end of contiguous sequence of Up bonds */
     504         [ +  - ]:         177 :                     if (cur_len_Up > len_Up)
     505                 :             :                     {
     506                 :         177 :                         first_Up = cur_first_Up; /* store the sequence because it is longer than the ptrvious one */
     507                 :         177 :                         len_Up = cur_len_Up;
     508                 :             :                     }
     509                 :         177 :                     bPrev_Up = 0;
     510                 :             :                 }
     511                 :             :             }
     512                 :             :         }
     513                 :             :     }
     514                 :             : #if ( FIX_2D_STEREO_BORDER_CASE == 1 )
     515                 :             :     /* check if the bonds with ordering numbers first_Up+len_Up and first_Up+len_Up+1 */
     516                 :             :     /* have identical angles. In this case switch their order to enlarge the Up sequence */
     517                 :             : #define ZERO_ANGLE  0.000001
     518                 :             :     if (nNumNeigh - len_Up >= 2)
     519                 :             :     {
     520                 :             :         int next1, next2;
     521                 :             :         for (i = 1; i < nNumNeigh - len_Up; i++)
     522                 :             :         {
     523                 :             :             next2 = ( first_Up + len_Up + i ) % nNumNeigh; /* the 2nd after Up sequence */
     524                 :             :             if (nBondType[nBondOrder[next2]] > 0)
     525                 :             :             {
     526                 :             :                 next1 = ( first_Up + len_Up ) % nNumNeigh; /* the 1st after Up sequence */
     527                 :             :                 dAngle = dBondDirection[nBondOrder[next1]] - dBondDirection[nBondOrder[next2]];
     528                 :             :                 if (fabs( dAngle ) < ZERO_ANGLE)
     529                 :             :                 {
     530                 :             :                     inchi_swap( (char*) &nBondOrder[next1], (char*) &nBondOrder[next2], sizeof( nBondOrder[0] ) );
     531                 :             :                     len_Up++;
     532                 :             :                     break;
     533                 :             :                 }
     534                 :             :             }
     535                 :             :         }
     536                 :             :     }
     537                 :             :     /* Check whether the not-Up bond (located before the found first-Up) has */
     538                 :             :     /* same angle as the Up bond that precedes this not-Up bond */
     539                 :             :     if (nNumNeigh - len_Up >= 2)
     540                 :             :     {
     541                 :             :         int next1, next2;
     542                 :             :         for (i = 1; i < nNumNeigh - len_Up; i++)
     543                 :             :         {
     544                 :             :             next2 = ( first_Up + nNumNeigh - i - 1 ) % nNumNeigh; /* the 2nd before Up sequence */
     545                 :             :             if (nBondType[nBondOrder[next2]] > 0)
     546                 :             :             {
     547                 :             :                 next1 = ( first_Up + nNumNeigh - 1 ) % nNumNeigh; /* the 1st before Up sequence */
     548                 :             :                 dAngle = dBondDirection[nBondOrder[next1]] - dBondDirection[nBondOrder[next2]];
     549                 :             :                 if (fabs( dAngle ) < ZERO_ANGLE)
     550                 :             :                 {
     551                 :             :                     inchi_swap( (char*) &nBondOrder[next1], (char*) &nBondOrder[next2], sizeof( nBondOrder[0] ) );
     552                 :             :                     first_Up = next1;
     553                 :             :                     len_Up++;
     554                 :             :                     break;
     555                 :             :                 }
     556                 :             :             }
     557                 :             :         }
     558                 :             :     }
     559                 :             : #else
     560         [ +  - ]:         177 :     if (bFix2DstereoBorderCase)
     561                 :             :     {
     562                 :             :         /* Check if the bonds with ordering numbers first_Up+len_Up and first_Up+len_Up+1 */
     563                 :             :         /* have identical angles. In this case switch their order to enlarge the Up sequence */
     564                 :             : #define ZERO_ANGLE  0.000001
     565         [ +  - ]:         177 :         if (nNumNeigh - len_Up >= 2)
     566                 :             :         {
     567                 :             :             int next1, next2;
     568         [ +  + ]:         354 :             for (i = 1; i < nNumNeigh - len_Up; i++)
     569                 :             :             {
     570                 :         177 :                 next2 = ( first_Up + len_Up + i ) % nNumNeigh; /* the 2nd after Up sequence */
     571         [ -  + ]:         177 :                 if (nBondType[nBondOrder[next2]] > 0)
     572                 :             :                 {
     573                 :           0 :                     next1 = ( first_Up + len_Up ) % nNumNeigh; /* the 1st after Up sequence */
     574                 :           0 :                     dAngle = dBondDirection[nBondOrder[next1]] - dBondDirection[nBondOrder[next2]];
     575         [ #  # ]:           0 :                     if (fabs( dAngle ) < ZERO_ANGLE)
     576                 :             :                     {
     577                 :           0 :                         inchi_swap( (char*) &nBondOrder[next1], (char*) &nBondOrder[next2], sizeof( nBondOrder[0] ) );
     578                 :           0 :                         len_Up++;
     579                 :           0 :                         break;
     580                 :             :                     }
     581                 :             :                 }
     582                 :             :             }
     583                 :             :         }
     584                 :             : 
     585                 :             :         /* Check whether the not-Up bond (located before the found first-Up) has */
     586                 :             :         /* same angle as the Up bond that precedes this not-Up bond */
     587         [ +  - ]:         177 :         if (nNumNeigh - len_Up >= 2)
     588                 :             :         {
     589                 :             :             int next1, next2;
     590         [ +  + ]:         354 :             for (i = 1; i < nNumNeigh - len_Up; i++)
     591                 :             :             {
     592                 :         177 :                 next2 = ( first_Up + nNumNeigh - i - 1 ) % nNumNeigh; /* the 2nd before Up sequence */
     593         [ -  + ]:         177 :                 if (nBondType[nBondOrder[next2]] > 0)
     594                 :             :                 {
     595                 :           0 :                     next1 = ( first_Up + nNumNeigh - 1 ) % nNumNeigh; /* the 1st before Up sequence */
     596                 :           0 :                     dAngle = dBondDirection[nBondOrder[next1]] - dBondDirection[nBondOrder[next2]];
     597         [ #  # ]:           0 :                     if (fabs( dAngle ) < ZERO_ANGLE)
     598                 :             :                     {
     599                 :           0 :                         inchi_swap( (char*) &nBondOrder[next1], (char*) &nBondOrder[next2], sizeof( nBondOrder[0] ) );
     600                 :           0 :                         first_Up = next1;
     601                 :           0 :                         len_Up++;
     602                 :           0 :                         break;
     603                 :             :                     }
     604                 :             :                 }
     605                 :             :             }
     606                 :             :         }
     607                 :             :     }
     608                 :             : #endif
     609                 :             :     /*  Turn all the bonds around the center so that */
     610                 :             :     /*  the 1st Up bond has zero radian direction */
     611                 :         177 :     dAlpha = dBondDirection[nBondOrder[first_Up]];
     612         [ +  + ]:         708 :     for (i = 0; i < nNumNeigh; i++)
     613                 :             :     {
     614         [ +  + ]:         531 :         if (i == nBondOrder[first_Up])
     615                 :             :         {
     616                 :         177 :             dBondDirection[i] = 0.0;
     617                 :             :         }
     618                 :             :         else
     619                 :             :         {
     620                 :         354 :             dAngle = dBondDirection[i] - dAlpha;
     621         [ +  + ]:         354 :             if (dAngle < 0.0)
     622                 :             :             {
     623                 :         156 :                 dAngle += two_pi;
     624                 :             :             }
     625                 :         354 :             dBondDirection[i] = dAngle;
     626                 :             :         }
     627                 :             :     }
     628                 :             : 
     629                 :             :     /********************************************************
     630                 :             :      * Process particular cases
     631                 :             :      ********************************************************/
     632                 :             : 
     633         [ +  - ]:         177 :     if (nNumNeigh == 3)
     634                 :             :     {
     635                 :             :         /************************ 3 bonds ************************/
     636   [ -  +  -  -  :         177 :         switch (num_Up)
                      - ]
     637                 :             :         {
     638                 :             : 
     639                 :           0 :             case 0:    /* 0 Up */
     640                 :           0 :                 return T2D_UNDF;
     641                 :             : 
     642                 :         177 :             case 1:    /* 1 Up */
     643         [ -  + ]:         177 :                 if (num_Dn)
     644                 :             :                 {
     645                 :             : #ifdef _DEBUG
     646                 :             :                     if (num_Dn != 1)  /*  debug only */
     647                 :             :                     {
     648                 :             :                         return -1;
     649                 :             :                     }
     650                 :             : #endif
     651                 :           0 :                     ret = ( T2D_UNDF | T2D_WARN );
     652                 :             :                 }
     653                 :             :                 else
     654                 :             :                 {
     655                 :         177 :                     dAngle = dBondDirection[nBondOrder[( first_Up + 2 ) % nNumNeigh]] -
     656                 :         177 :                         dBondDirection[nBondOrder[( first_Up + 1 ) % nNumNeigh]];
     657                 :             : 
     658         [ -  + ]:         177 :                     if (dAngle < 0.0)
     659                 :             :                     {
     660                 :           0 :                         dAngle += two_pi;
     661                 :             :                     }
     662   [ -  +  -  - ]:         177 :                     if (dAngle - one_pi < -vMinAngle || dAngle - one_pi > vMinAngle)
     663                 :             :                     {
     664                 :         177 :                         ret = T2D_OKAY;
     665                 :             :                     }
     666                 :             :                     else
     667                 :             :                     {
     668                 :           0 :                         ret = ( T2D_UNDF | T2D_WARN );
     669                 :             :                     }
     670                 :             :                 }
     671                 :         177 :                 break;
     672                 :             : 
     673                 :           0 :             case 2:    /* 2 Up */
     674         [ #  # ]:           0 :                 if (num_Dn)
     675                 :             :                 {
     676                 :           0 :                     dAlpha = dBondDirection[nBondOrder[( first_Up + 1 ) % nNumNeigh]] -
     677                 :           0 :                         dBondDirection[nBondOrder[( first_Up ) % nNumNeigh]];
     678                 :             : 
     679         [ #  # ]:           0 :                     if (dAlpha < 0.0)
     680                 :             :                     {
     681                 :           0 :                         dAlpha += two_pi;
     682                 :             :                     }
     683                 :             : 
     684         [ #  # ]:           0 :                     if (dAlpha > one_pi - vMinAngle)
     685                 :             :                     {
     686                 :           0 :                         ret = T2D_OKAY;
     687                 :             :                     }
     688         [ #  # ]:           0 :                     else if (dAlpha < two_pi / 3.0 - vMinAngle)
     689                 :             :                     {
     690                 :           0 :                         ret = ( T2D_UNDF | T2D_WARN );
     691                 :             :                     }
     692                 :             :                     else
     693                 :             :                     {
     694                 :             :                         /*  angle between 2 Up bonds is between 120 and 180 degrees */
     695                 :             :                         /*  direction of the (Alpha angle bisector) + 180 degrees    */
     696                 :           0 :                         dBisector = dBondDirection[nBondOrder[( first_Up ) % nNumNeigh]];
     697                 :           0 :                         dBisector += dBondDirection[nBondOrder[( first_Up + 1 ) % nNumNeigh]];
     698                 :           0 :                         dBisector /= 2.0;
     699                 :           0 :                         dBisector -= one_pi;
     700         [ #  # ]:           0 :                         if (dBisector < 0.0)
     701                 :             :                         {
     702                 :           0 :                             dBisector += two_pi;
     703                 :             :                         }
     704         [ #  # ]:           0 :                         if (dAlpha < two_pi / 3.0 + vMinAngle)
     705                 :             :                         {
     706                 :             :                             /*  dAlpha is inside ( 2pi/3 - eps, 2pi/3 + eps ) interval */
     707                 :           0 :                             dLimit = vMinAngle * 3.0 / 2.0;
     708                 :             :                         }
     709                 :             :                         else
     710                 :             :                         {
     711                 :           0 :                             dLimit = dAlpha * 3.0 / 2.0 - one_pi;
     712                 :             :                         }
     713                 :             : 
     714                 :           0 :                         dAngle = dBondDirection[nBondOrder[( first_Up + 2 ) % nNumNeigh]];
     715                 :             : 
     716         [ #  # ]:           0 :                         if (dBisector - dAngle < -dLimit ||
     717         [ #  # ]:           0 :                               dBisector - dAngle >  dLimit)
     718                 :             :                         {
     719                 :           0 :                             ret = ( T2D_UNDF | T2D_WARN );
     720                 :             :                         }
     721                 :             :                         else
     722                 :             :                         {
     723                 :           0 :                             ret = T2D_OKAY;
     724                 :             :                         }
     725                 :             :                     }
     726                 :             :                 } /* if ( num_Dn )  */
     727                 :             :                 else
     728                 :             :                 {
     729                 :           0 :                     ret = T2D_OKAY;
     730                 :             :                 }
     731                 :           0 :                 break;
     732                 :             : 
     733                 :           0 :             case 3:    /* 3 Up */
     734                 :           0 :                 ret = T2D_OKAY;
     735                 :           0 :                 break;
     736                 :             : 
     737                 :           0 :             default:/* other Up */
     738                 :           0 :                 return -1;
     739                 :             :         } /* eof switch( num_Up ) at  nNumNeigh == 3 */
     740                 :             :     }
     741                 :             : 
     742         [ #  # ]:           0 :     else if (nNumNeigh == 4)
     743                 :             :     {
     744                 :             :         /******************************* 4 bonds ********************/
     745   [ #  #  #  #  :           0 :         switch (num_Up)
                   #  # ]
     746                 :             :         {
     747                 :             : 
     748                 :           0 :             case 0:    /* 0 Up */
     749                 :           0 :                 return T2D_UNDF;
     750                 :             : 
     751                 :           0 :             case 1:    /* 1 Up */
     752         [ #  # ]:           0 :                 if (num_Dn)
     753                 :             :                 {
     754         [ #  # ]:           0 :                     if (nBondType[nBondOrder[( first_Up + 2 ) % nNumNeigh]] < 0)
     755                 :             :                     {
     756                 :             :                         /*
     757                 :             :                         * Up, In Plane, Dn, In Plane. Undefined if angle between
     758                 :             :                         * two In Plane bonds is wuthin pi +/- 2*arcsine(1/sqrt(8)) interval
     759                 :             :                         * That is, 138.5 to 221.4 degrees; for certainty the interval is
     760                 :             :                         * increased by 5.7 degrees at each end to
     761                 :             :                         * 134.8 to 227.1 degrees
     762                 :             :                         */
     763                 :           0 :                         dAngle = dBondDirection[nBondOrder[( first_Up + 3 ) % nNumNeigh]] -
     764                 :           0 :                             dBondDirection[nBondOrder[( first_Up + 1 ) % nNumNeigh]];
     765         [ #  # ]:           0 :                         if (dAngle < 0.0)
     766                 :             :                         {
     767                 :           0 :                             dAngle += two_pi;
     768                 :             :                         }
     769         [ #  # ]:           0 :                         if (fabs( dAngle - one_pi ) < dAngleAndPiMaxDiff + vMinAngle)
     770                 :             :                         {
     771                 :           0 :                             ret = ( T2D_UNDF | T2D_WARN );
     772                 :             :                         }
     773                 :             :                         else
     774                 :             :                         {
     775                 :           0 :                             ret = T2D_OKAY;
     776                 :             :                         }
     777                 :             :                     }
     778                 :             :                     else
     779                 :             :                     {
     780                 :           0 :                         ret = T2D_OKAY;
     781                 :             :                     }
     782                 :             : #ifdef _DEBUG
     783                 :             :                     if (num_Dn != 1)  /*  debug only */
     784                 :             :                     {
     785                 :             :                         return -1;
     786                 :             :                     }
     787                 :             : #endif
     788                 :             :                 }
     789                 :             :                 else
     790                 :             :                 {
     791                 :           0 :                     ret = T2D_OKAY;
     792                 :           0 :                     dAngle = dBondDirection[nBondOrder[( first_Up + 3 ) % nNumNeigh]] -
     793                 :           0 :                         dBondDirection[nBondOrder[( first_Up + 1 ) % nNumNeigh]];
     794         [ #  # ]:           0 :                     if (dAngle < 0.0)
     795                 :             :                     {
     796                 :           0 :                         dAngle += two_pi;
     797                 :             :                     }
     798         [ #  # ]:           0 :                     if (dAngle < one_pi - vMinAngle)
     799                 :             :                     {
     800                 :           0 :                         ret |= T2D_WARN;
     801                 :             :                     }
     802                 :             :                 }
     803                 :           0 :                 break;
     804                 :             : 
     805                 :           0 :             case 2:    /* 2 Up */
     806                 :             : #if ( FIX_2D_STEREO_BORDER_CASE == 1 )
     807                 :             :                 if (len_Up == 1)
     808                 :             :                 {
     809                 :             :                     ret = T2D_OKAY;
     810                 :             :                 }
     811                 :             :                 else
     812                 :             :                 {
     813                 :             :                     dAngle = dBondDirection[nBondOrder[( first_Up + 3 ) % nNumNeigh]] -
     814                 :             :                         dBondDirection[nBondOrder[( first_Up + 0 ) % nNumNeigh]];
     815                 :             :                     dAngle = fabs( two_pi - dAngle );
     816                 :             :                     dAlpha = dBondDirection[nBondOrder[( first_Up + 2 ) % nNumNeigh]] -
     817                 :             :                         dBondDirection[nBondOrder[( first_Up + 1 ) % nNumNeigh]];
     818                 :             :                     dAlpha = fabs( dAlpha );
     819                 :             :                     if (dAngle < 2.0 * ZERO_ANGLE && dAlpha > vMinAngle ||
     820                 :             :                          dAlpha < 2.0 * ZERO_ANGLE && dAngle > vMinAngle)
     821                 :             :                     {
     822                 :             :                         ret = ( T2D_OKAY | T2D_WARN );
     823                 :             :                     }
     824                 :             :                     else
     825                 :             :                     {
     826                 :             :                         ret = ( T2D_UNDF | T2D_WARN );
     827                 :             :                     }
     828                 :             :                 }
     829                 :             : #else
     830         [ #  # ]:           0 :                 if (bFix2DstereoBorderCase)
     831                 :             :                 {
     832                 :             :                     /* bug fix */
     833         [ #  # ]:           0 :                     if (len_Up == 1)
     834                 :             :                     {
     835                 :           0 :                         ret = T2D_OKAY;
     836                 :             :                     }
     837                 :             :                     else
     838                 :             :                     {
     839                 :           0 :                         dAngle = dBondDirection[nBondOrder[( first_Up + 3 ) % nNumNeigh]] -
     840                 :           0 :                             dBondDirection[nBondOrder[( first_Up + 0 ) % nNumNeigh]];
     841                 :           0 :                         dAngle = fabs( two_pi - dAngle );
     842                 :           0 :                         dAlpha = dBondDirection[nBondOrder[( first_Up + 2 ) % nNumNeigh]] -
     843                 :           0 :                             dBondDirection[nBondOrder[( first_Up + 1 ) % nNumNeigh]];
     844                 :           0 :                         dAlpha = fabs( dAlpha );
     845   [ #  #  #  # ]:           0 :                         if ((dAngle < 2.0 * ZERO_ANGLE && dAlpha > vMinAngle) ||
     846   [ #  #  #  # ]:           0 :                              (dAlpha < 2.0 * ZERO_ANGLE && dAngle > vMinAngle)) /* djb-rwth: addressing LLVM warnings */
     847                 :             :                         {
     848                 :           0 :                             ret = ( T2D_OKAY | T2D_WARN );
     849                 :             :                         }
     850                 :             :                         else
     851                 :             :                         {
     852                 :           0 :                             ret = ( T2D_UNDF | T2D_WARN );
     853                 :             :                         }
     854                 :             :                     }
     855                 :             :                 }
     856                 :             :                 else
     857                 :             :                 {
     858                 :             :                     /* original InChI v. 1 bug */
     859         [ #  # ]:           0 :                     if (cur_len_Up == 1)
     860                 :             :                     {
     861                 :           0 :                         ret = T2D_OKAY;
     862                 :             :                     }
     863                 :             :                     else
     864                 :             :                     {
     865                 :           0 :                         ret = ( T2D_UNDF | T2D_WARN );
     866                 :             :                     }
     867                 :             :                 }
     868                 :             : #endif
     869                 :           0 :                 break;
     870                 :             : 
     871                 :           0 :             case 3:    /* 3 Up */
     872                 :           0 :                 ret = T2D_OKAY;
     873                 :           0 :                 dAngle = dBondDirection[nBondOrder[( first_Up + 2 ) % nNumNeigh]] -
     874                 :           0 :                     dBondDirection[nBondOrder[( first_Up + 0 ) % nNumNeigh]];
     875         [ #  # ]:           0 :                 if (dAngle < 0.0)
     876                 :             :                 {
     877                 :           0 :                     dAngle += two_pi;
     878                 :             :                 }
     879         [ #  # ]:           0 :                 if (dAngle < one_pi - vMinAngle)
     880                 :             :                 {
     881                 :           0 :                     ret |= T2D_WARN;
     882                 :             :                 }
     883                 :           0 :                 break;
     884                 :             : 
     885                 :           0 :             case 4:    /* 4 Up */
     886                 :           0 :                 ret = ( T2D_UNDF | T2D_WARN );
     887                 :           0 :                 break;
     888                 :             : 
     889                 :           0 :             default:/* other Up */
     890                 :           0 :                 return -1; /*  program error */
     891                 :             :         } /* eof switch( num_Up ) at  nNumNeigh == 4 */
     892                 :             : 
     893                 :             : 
     894         [ #  # ]:           0 :         if (ret == T2D_OKAY)
     895                 :             :         {
     896                 :             :             /*  Check whether all bonds are inside a less than 180 degrees sector */
     897         [ #  # ]:           0 :             for (i = 0; i < nNumNeigh; i++)
     898                 :             :             {
     899                 :           0 :                 dAngle = dBondDirection[nBondOrder[( i + nNumNeigh - 1 ) % nNumNeigh]] -
     900                 :           0 :                     dBondDirection[nBondOrder[i % nNumNeigh]];
     901         [ #  # ]:           0 :                 if (dAngle < 0.0)
     902                 :             :                 {
     903                 :           0 :                     dAngle += two_pi;
     904                 :             :                 }
     905         [ #  # ]:           0 :                 if (dAngle < one_pi - vMinAngle)
     906                 :             :                 {
     907                 :           0 :                     ret |= T2D_WARN;
     908                 :           0 :                     break;
     909                 :             :                 }
     910                 :             :             }
     911                 :             :         }
     912                 :             :     } /* eof nNumNeigh == 4 */
     913                 :             : 
     914                 :             :     else
     915                 :             :     {
     916                 :             :         /*************************** number of bonds != 3 or 4 ******************/
     917                 :             : 
     918                 :           0 :         return -1; /*  error */
     919                 :             :     }
     920                 :             : 
     921                 :         177 :     return ret;
     922                 :             : }
     923                 :             : 
     924                 :             : 
     925                 :             : /****************************************************************************/
     926                 :         177 : double triple_prod_and_min_abs_sine2( double at_coord[][3],
     927                 :             :                                       double central_at_coord[],
     928                 :             :                                       int bAddedExplicitNeighbor,
     929                 :             :                                       double *min_sine,
     930                 :             :                                       int *bAmbiguous,
     931                 :             :                                       double vMinSine )
     932                 :             : {
     933                 :         177 :     double min_sine_value = 9999.0, sine_value, min_edge_len, max_edge_len, min_edge_len_NoExplNeigh, max_edge_len_NoExplNeigh;
     934                 :             :     double s0, s1, s2, s3, e01, e02, e03, e12, e13, e23, tmp[3], e[3][3];
     935                 :             :     double prod, ret, central_prod[4];
     936                 :             :     int    bLongEdges;
     937                 :             : 
     938         [ -  + ]:         177 :     if (!min_sine)
     939                 :             :     {
     940                 :           0 :         return triple_prod( at_coord[0], at_coord[1], at_coord[2], NULL );
     941                 :             :     }
     942                 :             : 
     943                 :         177 :     ret = triple_prod( at_coord[0], at_coord[1], at_coord[2], &sine_value );
     944                 :         177 :     sine_value = MPY_SINE * fabs( sine_value );
     945                 :             : 
     946                 :         177 :     diff3( at_coord[1], at_coord[0], e[2] );
     947                 :         177 :     diff3( at_coord[0], at_coord[2], e[1] );
     948                 :         177 :     diff3( at_coord[2], at_coord[1], e[0] );
     949                 :             : 
     950                 :             :     /*  lengths of the 6 edges of the tetrahedra */
     951                 :         177 :     e03 = len3( at_coord[0] ); /* 1 */
     952                 :         177 :     e13 = len3( at_coord[1] );
     953                 :         177 :     e23 = len3( at_coord[2] ); /* includes added neighbor if bAddedExplicitNeighbor*/
     954                 :         177 :     e02 = len3( e[1] );        /* includes added neighbor if bAddedExplicitNeighbor*/
     955                 :         177 :     e12 = len3( e[0] );        /* includes added neighbor if bAddedExplicitNeighbor*/
     956                 :         177 :     e01 = len3( e[2] );
     957                 :             : 
     958                 :             :     /*  min & max edge length */
     959                 :         177 :     max_edge_len =
     960                 :         177 :         min_edge_len = e03;
     961                 :             : 
     962         [ +  + ]:         177 :     if (min_edge_len > e13)
     963                 :             :     {
     964                 :         122 :         min_edge_len = e13;
     965                 :             :     }
     966         [ +  + ]:         177 :     if (min_edge_len > e01)
     967                 :             :     {
     968                 :          75 :         min_edge_len = e01;
     969                 :             :     }
     970                 :         177 :     min_edge_len_NoExplNeigh = min_edge_len;
     971                 :             : 
     972         [ +  - ]:         177 :     if (min_edge_len > e23)
     973                 :             :     {
     974                 :         177 :         min_edge_len = e23;
     975                 :             :     }
     976         [ +  + ]:         177 :     if (min_edge_len > e02)
     977                 :             :     {
     978                 :          65 :         min_edge_len = e02;
     979                 :             :     }
     980         [ +  + ]:         177 :     if (min_edge_len > e12)
     981                 :             :     {
     982                 :          29 :         min_edge_len = e12;
     983                 :             :     }
     984                 :             : 
     985         [ +  + ]:         177 :     if (max_edge_len < e13)
     986                 :             :     {
     987                 :          55 :         max_edge_len = e13;
     988                 :             :     }
     989         [ +  + ]:         177 :     if (max_edge_len < e01)
     990                 :             :     {
     991                 :           9 :         max_edge_len = e01;
     992                 :             :     }
     993                 :         177 :     max_edge_len_NoExplNeigh = max_edge_len;
     994                 :             : 
     995         [ -  + ]:         177 :     if (max_edge_len < e23)
     996                 :             :     {
     997                 :           0 :         max_edge_len = e23;
     998                 :             :     }
     999         [ -  + ]:         177 :     if (max_edge_len < e02)
    1000                 :             :     {
    1001                 :           0 :         max_edge_len = e02;
    1002                 :             :     }
    1003         [ -  + ]:         177 :     if (max_edge_len < e12)
    1004                 :             :     {
    1005                 :           0 :         max_edge_len = e12;
    1006                 :             :     }
    1007                 :             : 
    1008         [ -  + ]:         177 :     if (!bAddedExplicitNeighbor)
    1009                 :             :     {
    1010                 :           0 :         min_edge_len_NoExplNeigh = min_edge_len;
    1011                 :           0 :         max_edge_len_NoExplNeigh = max_edge_len;
    1012                 :             :     }
    1013                 :             : 
    1014                 :         177 :     bLongEdges = bAddedExplicitNeighbor
    1015                 :         177 :         ? ( max_edge_len_NoExplNeigh < MAX_EDGE_RATIO * min_edge_len_NoExplNeigh )
    1016         [ +  - ]:         177 :         : ( max_edge_len < MAX_EDGE_RATIO * min_edge_len );
    1017                 :             : 
    1018   [ +  -  -  +  :         177 :     if (sine_value > vMinSine && ( min_sine || bAmbiguous )) /* djb-rwth: fixing coverity ID #499548 -- unresolved issue -- revision required */
                   -  - ]
    1019                 :             :     {
    1020         [ +  - ]:         177 :         if (min_sine)
    1021                 :             :         {
    1022                 :         177 :             prod = fabs( ret );
    1023                 :             :             /*  tetrahedra height = volume(prod) / area of a plane(cross_prod) */
    1024                 :             :             /*  (instead of a tetrahedra calculate parallelogram/parallelepiped area/volume) */
    1025                 :             : 
    1026                 :             :             /*  4 heights from each of the 4 vertices to the opposite plane */
    1027                 :         177 :             s0 = prod / len3((double *)cross_prod3( at_coord[1], at_coord[2], tmp ) ); /* djb-rwth: cast operator added for compatibility */
    1028                 :         177 :             s1 = prod / len3((double *)cross_prod3( at_coord[0], at_coord[2], tmp ) ); /* djb-rwth: cast operator added for compatibility */
    1029                 :         177 :             s2 = prod / len3((double *)cross_prod3( at_coord[0], at_coord[1], tmp ) ); /* djb-rwth: cast operator added for compatibility */
    1030                 :         177 :             s3 = prod / len3((double *)cross_prod3( e[0], e[1], tmp ) ); /* djb-rwth: cast operator added for compatibility */
    1031                 :             :             /*  abs. value of a sine of an angle between each tetrahedra edge and plane */
    1032                 :             :             /*  sine = height / edge length */
    1033         [ +  - ]:         177 :             if (( sine_value = s0 / e01 ) < min_sine_value)
    1034                 :             :             {
    1035                 :         177 :                 min_sine_value = sine_value;
    1036                 :             :             }
    1037         [ -  + ]:         177 :             if (( sine_value = s0 / e02 ) < min_sine_value)
    1038                 :             :             {
    1039                 :           0 :                 min_sine_value = sine_value;
    1040                 :             :             }
    1041         [ +  + ]:         177 :             if (( sine_value = s0 / e03 ) < min_sine_value)
    1042                 :             :             {
    1043                 :         138 :                 min_sine_value = sine_value;
    1044                 :             :             }
    1045                 :             : 
    1046         [ +  + ]:         177 :             if (( sine_value = s1 / e01 ) < min_sine_value)
    1047                 :             :             {
    1048                 :          55 :                 min_sine_value = sine_value;
    1049                 :             :             }
    1050         [ -  + ]:         177 :             if (( sine_value = s1 / e12 ) < min_sine_value)
    1051                 :             :             {
    1052                 :           0 :                 min_sine_value = sine_value;
    1053                 :             :             }
    1054         [ +  + ]:         177 :             if (( sine_value = s1 / e13 ) < min_sine_value)
    1055                 :             :             {
    1056                 :          53 :                 min_sine_value = sine_value;
    1057                 :             :             }
    1058                 :             : 
    1059         [ +  - ]:         177 :             if (( sine_value = s2 / e02 ) < min_sine_value)
    1060                 :             :             {
    1061                 :         177 :                 min_sine_value = sine_value;
    1062                 :             :             }
    1063         [ +  + ]:         177 :             if (( sine_value = s2 / e12 ) < min_sine_value)
    1064                 :             :             {
    1065                 :         122 :                 min_sine_value = sine_value;
    1066                 :             :             }
    1067         [ +  + ]:         177 :             if (( sine_value = s2 / e23 ) < min_sine_value)
    1068                 :             :             {
    1069                 :           9 :                 min_sine_value = sine_value;
    1070                 :             :             }
    1071                 :             : 
    1072         [ -  + ]:         177 :             if (( sine_value = s3 / e03 ) < min_sine_value)
    1073                 :             :             {
    1074                 :           0 :                 min_sine_value = sine_value;
    1075                 :             :             }
    1076         [ -  + ]:         177 :             if (( sine_value = s3 / e13 ) < min_sine_value)
    1077                 :             :             {
    1078                 :           0 :                 min_sine_value = sine_value;
    1079                 :             :             }
    1080         [ -  + ]:         177 :             if (( sine_value = s3 / e23 ) < min_sine_value)
    1081                 :             :             {
    1082                 :           0 :                 min_sine_value = sine_value;
    1083                 :             :             }
    1084                 :             :             /*  actually use triple sine */
    1085                 :         177 :             *min_sine = sine_value = MPY_SINE * min_sine_value;
    1086                 :             :         }
    1087                 :             : 
    1088   [ +  -  +  - ]:         177 :         if (bAmbiguous && sine_value >= vMinSine)
    1089                 :             :         {
    1090                 :             :             /*  Check whether the central atom is outside the tetrahedra (0,0,0), at_coord[0,1,2] */
    1091                 :             :             /*  compare the tetrahedra volume and the volume of a tetrahedra having central_at_coord[] vertex */
    1092                 :             :             int i;
    1093                 :         177 :             diff3( central_at_coord, at_coord[0], tmp );
    1094                 :         177 :             central_prod[0] = triple_prod( at_coord[0], at_coord[1], central_at_coord, NULL );
    1095                 :         177 :             central_prod[1] = triple_prod( at_coord[1], at_coord[2], central_at_coord, NULL );
    1096                 :         177 :             central_prod[2] = triple_prod( at_coord[2], at_coord[0], central_at_coord, NULL );
    1097                 :         177 :             central_prod[3] = triple_prod( e[2], e[1], tmp, NULL );
    1098         [ +  + ]:         885 :             for (i = 0; i <= 3; i++)
    1099                 :             :             {
    1100         [ -  + ]:         708 :                 if (central_prod[i] / ret < -MIN_SINE_OUTSIDE)
    1101                 :             :                 {
    1102                 :           0 :                     *bAmbiguous |= AMBIGUOUS_STEREO;
    1103                 :           0 :                     break;
    1104                 :             :                 }
    1105                 :             :             }
    1106                 :             :         }
    1107                 :             : #if ( STEREO_CENTER_BONDS_NORM == 1 )
    1108                 :             : 
    1109   [ +  -  -  +  :         177 :         if (bLongEdges && !bAddedExplicitNeighbor && max_edge_len >= MIN_LEN_STRAIGHT)
                   -  - ]
    1110                 :             :         {
    1111                 :             :             /*  possible planar tetragon */
    1112         [ #  # ]:           0 :             if (sine_value < MIN_SINE_SQUARE)
    1113                 :             :             {
    1114                 :           0 :                 *min_sine = vMinSine / 2.0; /*  force parity to be undefined */
    1115   [ #  #  #  # ]:           0 :                 if (bAmbiguous && !*bAmbiguous)
    1116                 :             :                 {
    1117                 :           0 :                     *bAmbiguous |= AMBIGUOUS_STEREO;
    1118                 :             :                 }
    1119                 :             :             }
    1120                 :             :         }
    1121                 :             : 
    1122   [ +  -  -  +  :         177 :         if (bLongEdges && sine_value < MIN_SINE_SQUARE && sine_value < MIN_SINE_EDGE * min_edge_len_NoExplNeigh)
                   -  - ]
    1123                 :             :         {
    1124                 :           0 :             *min_sine = vMinSine / 2.0; /*  force parity to be undefined */
    1125   [ #  #  #  # ]:           0 :             if (bAmbiguous && !*bAmbiguous)
    1126                 :             :             {
    1127                 :           0 :                 *bAmbiguous |= AMBIGUOUS_STEREO;
    1128                 :             :             }
    1129                 :             :         }
    1130                 :             : #endif
    1131                 :             :     }
    1132                 :             :     else
    1133                 :             :     {
    1134         [ #  # ]:           0 :         if (min_sine)
    1135                 :             :         {
    1136                 :           0 :             *min_sine = sine_value;
    1137                 :             :         }
    1138                 :             :     }
    1139                 :             : 
    1140                 :         177 :     return ret;
    1141                 :             : }
    1142                 :             : 
    1143                 :             : 
    1144                 :             : /****************************************************************************/
    1145                 :         177 : double triple_prod_and_min_abs_sine( double at_coord[][3], double *min_sine )
    1146                 :             : {
    1147                 :         177 :     double min_sine_value = 9999.0, sine_value;
    1148                 :         177 :     double prod = 0.0;
    1149                 :             : 
    1150         [ -  + ]:         177 :     if (!min_sine)
    1151                 :             :     {
    1152                 :           0 :         return triple_prod( at_coord[0], at_coord[1], at_coord[2], NULL );
    1153                 :             :     }
    1154                 :             : 
    1155                 :         177 :     prod = triple_prod( at_coord[0], at_coord[1], at_coord[2], &sine_value ); /* djb-rwth: ignoring LLVM warning: variable used to store function return value */
    1156                 :         177 :     sine_value = fabs( sine_value );
    1157         [ -  + ]:         177 :     min_sine_value = inchi_min( min_sine_value, sine_value );
    1158                 :             : 
    1159                 :         177 :     prod = triple_prod( at_coord[1], at_coord[2], at_coord[0], &sine_value ); /* djb-rwth: ignoring LLVM warning: variable used to store function return value */
    1160                 :         177 :     sine_value = fabs( sine_value );
    1161         [ +  + ]:         177 :     min_sine_value = inchi_min( min_sine_value, sine_value );
    1162                 :             : 
    1163                 :         177 :     prod = triple_prod( at_coord[2], at_coord[0], at_coord[1], &sine_value ); /* djb-rwth: ignoring LLVM warning: variable used to store function return value */
    1164                 :         177 :     sine_value = fabs( sine_value );
    1165         [ +  + ]:         177 :     min_sine_value = inchi_min( min_sine_value, sine_value );
    1166                 :             : 
    1167                 :         177 :     *min_sine = min_sine_value;
    1168                 :             : 
    1169                 :         177 :     return prod;
    1170                 :             : }
    1171                 :             : 
    1172                 :             : 
    1173                 :             : /****************************************************************************
    1174                 :             :   Find if point (0,0,0)a and 3 atoms are in one plane
    1175                 :             : ****************************************************************************/
    1176                 :         177 : int are_3_vect_in_one_plane( double at_coord[][3], double min_sine )
    1177                 :             : {
    1178                 :             :     double actual_min_sine;
    1179                 :             :     double prod; /* djb-rwth: ignoring LLVM warning: variable used to store function return value */
    1180                 :             : 
    1181                 :         177 :     prod = triple_prod_and_min_abs_sine( at_coord, &actual_min_sine ); /* djb-rwth: ignoring LLVM warning: variable used to store function return value */
    1182                 :             : 
    1183                 :         177 :     return actual_min_sine <= min_sine;
    1184                 :             : }
    1185                 :             : 
    1186                 :             : 
    1187                 :             : /****************************************************************************
    1188                 :             :   Find if 4 atoms are in one plane
    1189                 :             : ****************************************************************************/
    1190                 :           0 : int are_4at_in_one_plane( double at_coord[][3], double min_sine )
    1191                 :             : {
    1192                 :             :     double actual_min_sine, min_actual_min_sine;
    1193                 :             :     double coord[3][3], prod; /* djb-rwth: ignoring LLVM warning: variable used to store function return value */
    1194                 :             :     int i, k, j;
    1195         [ #  # ]:           0 :     for (k = 0; k < 4; k++)
    1196                 :             :     {
    1197         [ #  # ]:           0 :         for (i = j = 0; i < 4; i++)
    1198                 :             :         {
    1199         [ #  # ]:           0 :             if (i != k)
    1200                 :             :             {
    1201                 :           0 :                 diff3( at_coord[i], at_coord[k], coord[j] );
    1202                 :           0 :                 j++;
    1203                 :             :             }
    1204                 :             :         }
    1205                 :             : 
    1206                 :           0 :         prod = triple_prod_and_min_abs_sine( coord, &actual_min_sine ); /* djb-rwth: ignoring LLVM warning: variable used to store function return value */
    1207   [ #  #  #  # ]:           0 :         if (!k || actual_min_sine < min_actual_min_sine)
    1208                 :             :         {
    1209                 :           0 :             min_actual_min_sine = actual_min_sine;
    1210                 :             :         }
    1211                 :             :     }
    1212                 :             : 
    1213                 :           0 :     return min_actual_min_sine <= min_sine;
    1214                 :             : }
    1215                 :             : 
    1216                 :             : 
    1217                 :             : /****************************************************************************/
    1218                 :           0 : int triple_prod_char( inp_ATOM *at,
    1219                 :             :                       int at_1,
    1220                 :             :                       int i_next_at_1,
    1221                 :             :                       S_CHAR *z_dir1,
    1222                 :             :                       int at_2,
    1223                 :             :                       int i_next_at_2,
    1224                 :             :                       S_CHAR *z_dir2 )
    1225                 :             : {
    1226                 :             :     inp_ATOM *at1, *at2;
    1227                 :             :     double    pnt[3][3], len;
    1228                 :             :     int       i;
    1229                 :           0 :     int       ret = 0;
    1230                 :             : 
    1231                 :           0 :     at1 = at + at_1;
    1232                 :           0 :     at2 = at + at[at_1].neighbor[i_next_at_1];
    1233                 :             : 
    1234                 :           0 :     pnt[0][0] = at2->x - at1->x;
    1235                 :           0 :     pnt[0][1] = at2->y - at1->y;
    1236                 :           0 :     pnt[0][2] = at2->z - at1->z;
    1237                 :             : 
    1238                 :           0 :     at2 = at + at_2;
    1239                 :           0 :     at1 = at + at[at_2].neighbor[i_next_at_2];
    1240                 :             : 
    1241                 :           0 :     pnt[1][0] = at2->x - at1->x;
    1242                 :           0 :     pnt[1][1] = at2->y - at1->y;
    1243                 :           0 :     pnt[1][2] = at2->z - at1->z;
    1244                 :             :     /*
    1245                 :             :      *  resultant pnt vector directions:
    1246                 :             :      *
    1247                 :             :      *         pnt[0]              pnt[1]
    1248                 :             :      *
    1249                 :             :      *   [at_1]---->[...]    [...]---->[at_2]
    1250                 :             :      *
    1251                 :             :      *
    1252                 :             :      *  add3 below: (pnt[0] + pnt[1]) -> pnt[1]
    1253                 :             :      */
    1254                 :           0 :     add3( pnt[0], pnt[1], pnt[1] );
    1255                 :             : 
    1256         [ #  # ]:           0 :     for (i = 0; i < 3; i++)
    1257                 :             :     {
    1258                 :           0 :         pnt[0][i] = (double) z_dir1[i];
    1259                 :           0 :         pnt[2][i] = (double) z_dir2[i];
    1260                 :             :     }
    1261         [ #  # ]:           0 :     for (i = 0; i < 3; i++)
    1262                 :             :     {
    1263                 :           0 :         len = len3( pnt[i] );
    1264         [ #  # ]:           0 :         if (len < MIN_BOND_LEN)
    1265                 :             :         {
    1266   [ #  #  #  #  :           0 :             if (i == 1 && ( at[at_1].bUsed0DParity || at[at_2].bUsed0DParity ))
                   #  # ]
    1267                 :             :             {
    1268                 :           0 :                 pnt[i][0] = 0.0;
    1269                 :           0 :                 pnt[i][1] = 1.0;
    1270                 :           0 :                 pnt[i][2] = 0.0;
    1271                 :           0 :                 len = 1.0; /* standard at_1-->at_2 vector coordinates in case of 0D allene */
    1272                 :             :             }
    1273                 :             :             else
    1274                 :             :             {
    1275                 :           0 :                 goto exit_function; /*  too short bond */
    1276                 :             :             }
    1277                 :             :         }
    1278                 :           0 :         mult3( pnt[i], 1.0 / len, pnt[i] );
    1279                 :             :     }
    1280                 :             : 
    1281                 :           0 :     len = 100.0*triple_prod( pnt[0], pnt[1], pnt[2], NULL );
    1282                 :             : 
    1283                 :             :     /*
    1284                 :             :      *   ^ pnt[0]
    1285                 :             :      *   |                         The orientation on this diagram
    1286                 :             :      *   |                         produces len = -100
    1287                 :             :      *  [at_1]------>[at_2]
    1288                 :             :      *        pnt[1]    /
    1289                 :             :      *                 /
    1290                 :             :      *                / pnt[2]  (up from the plane)
    1291                 :             :      *               v
    1292                 :             :      *
    1293                 :             :      * Note: len is invariant upon at_1 <--> at_2 transposition because
    1294                 :             :      *       triple product changes sign upon pnt[0]<-->pnt[2] transposition and
    1295                 :             :      *       triple product changes sign upon pnt[1]--> -pnt[1] change of direction:
    1296                 :             :      *
    1297                 :             :      * triple_prod(pnt[0],  pnt[1], pnt[2], NULL ) =
    1298                 :             :      * triple_prod(pnt[2], -pnt[1], pnt[0], NULL )
    1299                 :             :      *
    1300                 :             :      */
    1301                 :             : 
    1302         [ #  # ]:           0 :     ret = len >= 0.0 ? (int) ( floor( len + 0.5 ) ) : -(int) ( floor( 0.5 - len ) );
    1303                 :             : 
    1304                 :           0 : exit_function:
    1305                 :             : 
    1306                 :           0 :     return ret;
    1307                 :             : }
    1308                 :             : 
    1309                 :             : 
    1310                 :             : /****************************************************************************/
    1311                 :             : 
    1312                 :             : 
    1313                 :             : #if ( NEW_STEREOCENTER_CHECK == 1 ) /* { */
    1314                 :             : 
    1315                 :             : 
    1316                 :             : /****************************************************************************/
    1317                 :         784 : int bInpAtomHasRequirdNeigh( inp_ATOM *at,
    1318                 :             :                              int cur_at,
    1319                 :             :                              int RequirdNeighType,
    1320                 :             :                              int NumDbleBonds,
    1321                 :             :                              int bStereoAtZz )
    1322                 :             : {
    1323                 :             :     /* RequirdNeighType:
    1324                 :             :           reqired neighbor types (bitmap):
    1325                 :             :                0 => any neighbors
    1326                 :             :                1 => no terminal hydrogen atom neighbors
    1327                 :             :                2 => no terminal -X and -XH together (don't care about -X, -XH bond type, charge, radical)
    1328                 :             :                     (X = tautomeric endpoint atom)
    1329                 :             :        NumDbleBonds:
    1330                 :             :           if non-zero then allow double, alternating and tautomeric bonds
    1331                 :             :     */
    1332                 :             :     int i, j, ni, nj, bond_type, num_1s, num_mult, num_other;
    1333                 :             : 
    1334         [ -  + ]:         784 :     if (at[cur_at].endpoint)
    1335                 :             :     {
    1336                 :             :         /*  tautomeric endpoint cannot be a stereo center */
    1337                 :           0 :         return 0;
    1338                 :             :     }
    1339                 :             : 
    1340   [ -  +  -  - ]:         784 :     if (( 1 & RequirdNeighType ) && at[cur_at].num_H)
    1341                 :             :     {
    1342                 :           0 :         return 0;
    1343                 :             :     }
    1344                 :             : 
    1345         [ -  + ]:         784 :     if (2 & RequirdNeighType)
    1346                 :             :     {
    1347         [ #  # ]:           0 :         for (i = 0; i < at[cur_at].valence; i++)
    1348                 :             :         {
    1349                 :           0 :             ni = (int) at[cur_at].neighbor[i];
    1350   [ #  #  #  # ]:           0 :             if (at[ni].valence != 1 ||
    1351                 :           0 :                  !get_endpoint_valence( at[ni].el_number ))
    1352                 :             :             {
    1353                 :           0 :                 continue;
    1354                 :             :             }
    1355         [ #  # ]:           0 :             for (j = i + 1; j < at[cur_at].valence; j++)
    1356                 :             :             {
    1357                 :           0 :                 nj = (int) at[cur_at].neighbor[j];
    1358         [ #  # ]:           0 :                 if (at[nj].valence != 1 ||
    1359   [ #  #  #  # ]:           0 :                      at[ni].el_number != at[nj].el_number ||
    1360                 :           0 :                      !get_endpoint_valence( at[nj].el_number ))
    1361                 :             :                 {
    1362                 :           0 :                     continue;
    1363                 :             :                 }
    1364                 :             :                 /*
    1365                 :             :                  * if (at[ni].num_H != at[nj].num_H) then the atoms (neighbors of at[cur_at]
    1366                 :             :                  * are tautomeric endpoints and are indistinguishable => cur_at is not stereogenic
    1367                 :             :                  * if (at[ni].num_H == at[nj].num_H) then the neighbors are indistinguishable
    1368                 :             :                  * and cur_at will be found non-sterogenic later
    1369                 :             :                  * get_endpoint_valence() check will not allow the neighbors to be carbons
    1370                 :             :                  * Therefore the following "if" is not needed; we may just return 0.
    1371                 :             :                  */
    1372   [ #  #  #  # ]:           0 :                 if (at[ni].num_H != at[nj].num_H && strcmp( at[ni].elname, "C" ))
    1373                 :             :                 {
    1374                 :           0 :                     return 0; /*  found -X and -XH neighbors */
    1375                 :             :                 }
    1376                 :             :             }
    1377                 :             :         }
    1378                 :             :     }
    1379                 :             : 
    1380         [ +  - ]:         784 :     if (0==bStereoAtZz)
    1381                 :             :     {
    1382                 :             :         /* No stereo allowed at centers connected to pseudoelement atoms "Zz","Zy" */
    1383                 :             :         int nbr, inbr;
    1384         [ +  + ]:        2520 :         for (inbr = 0; inbr < at[cur_at].valence; inbr++)
    1385                 :             :         {
    1386                 :        1736 :             nbr = (int) at[cur_at].neighbor[inbr];
    1387   [ +  -  -  + ]:        1736 :             if (!strcmp( at[nbr].elname, "Zz" ) || !strcmp( at[nbr].elname, "Zy" ))
    1388                 :             :             {
    1389                 :           0 :                 return 0;
    1390                 :             :             }
    1391                 :             :         }
    1392                 :             :     }
    1393                 :             : 
    1394                 :         784 :     num_1s = num_mult = num_other = 0;
    1395                 :             : 
    1396         [ +  + ]:        2520 :     for (i = 0; i < at[cur_at].valence; i++)
    1397                 :             :     {
    1398                 :        1736 :         bond_type = ( at[cur_at].bond_type[i] & ~BOND_MARK_ALL );
    1399      [ +  -  - ]:        1736 :         switch (bond_type)
    1400                 :             :         {
    1401                 :        1736 :             case BOND_SINGLE:
    1402                 :        1736 :                 num_1s++;
    1403                 :        1736 :                 break;
    1404                 :           0 :             case BOND_DOUBLE:
    1405                 :             :             case BOND_ALTERN:
    1406                 :             :             case BOND_TAUTOM:
    1407                 :             :             case BOND_ALT12NS:
    1408                 :           0 :                 num_mult++;
    1409                 :           0 :                 break;
    1410                 :           0 :             default:
    1411                 :           0 :                 num_other++;
    1412                 :           0 :                 break;
    1413                 :             :         }
    1414                 :             :     }
    1415                 :             : 
    1416         [ -  + ]:         784 :     if (num_other)
    1417                 :             :     {
    1418                 :           0 :         return 0;
    1419                 :             :     }
    1420                 :             : 
    1421   [ -  +  -  -  :         784 :     if ((NumDbleBonds && NumDbleBonds > num_mult) ||
                   +  - ]
    1422         [ -  + ]:         784 :          (!NumDbleBonds && at[cur_at].valence != num_1s)) /* djb-rwth: addressing LLVM warning */
    1423                 :             :     {
    1424                 :           0 :         return 0;
    1425                 :             :     }
    1426                 :             : 
    1427                 :         784 :     return 1;
    1428                 :             : }
    1429                 :             : 
    1430                 :             : 
    1431                 :             : /****************************************************************************/
    1432                 :        1238 : int bCanInpAtomBeAStereoCenter( inp_ATOM *at,
    1433                 :             :                                 int cur_at,
    1434                 :             :                                 int bPointedEdgeStereo,
    1435                 :             :                                 int bStereoAtZz )
    1436                 :             : {
    1437                 :             : /*************************************************************************************
    1438                 :             :  * current version
    1439                 :             :  *************************************************************************************
    1440                 :             :  *       Use #define to split the stereocenter description table into parts
    1441                 :             :  *       to make it easier to read
    1442                 :             :  *
    1443                 :             :  *                      --------- 4 single bonds stereocenters -------
    1444                 :             :  *                       0       1       2       3      4       5
    1445                 :             :  *
    1446                 :             :  *                       |       |       |       |      |       |
    1447                 :             :  *                      -C-     -Si-    -Ge-    -Sn-   >As[+]  >B[-]
    1448                 :             :  *                       |       |       |       |      |       |
    1449                 :             :  */
    1450                 :             : #define SZELEM1         "C\000","Si",   "Ge",   "Sn",   "As", "B\000",
    1451                 :             : #define CCHARGE1         0,      0,      0,      0,      1,   -1,
    1452                 :             : #define CNUMBONDSANDH1   4,      4,      4,      4,      4,    4,
    1453                 :             : #define CCHEMVALENCEH1   4,      4,      4,      4,      4,    4,
    1454                 :             : #define CHAS3MEMBRING1   0,      0,      0,      0,      0,    0,
    1455                 :             : #define CREQUIRDNEIGH1   0,      0,      0,      0,      3,    0,
    1456                 :             : /*
    1457                 :             :  *                      --------------- S, Se stereocenters ----------
    1458                 :             :  *                       6       7       8       9      10     11    12    13
    1459                 :             :  *
    1460                 :             :  *                               |       |      ||             |     |     ||
    1461                 :             :  *                      -S=     =S=     -S[+]   >S[+]   -Se=  =Se=  -Se[+] >Se[+]
    1462                 :             :  *                       |       |       |       |       |     |     |      |
    1463                 :             :  */
    1464                 :             : #define SZELEM2         "S\000","S\000","S\000","S\000","Se", "Se", "Se",  "Se",
    1465                 :             : #define CCHARGE2         0,      0,      1,      1,      0,    0,    1,     1,
    1466                 :             : #define CNUMBONDSANDH2   3,      4,      3,      4,      3,    4,    3,     4,
    1467                 :             : #define CCHEMVALENCEH2   4,      6,      3,      5,      4,    6,    3,     5,
    1468                 :             : #define CHAS3MEMBRING2   0,      0,      0,      0,      0,    0,    0,     0,
    1469                 :             : #define CREQUIRDNEIGH2   3,      3,      3,      3,      3,    3,    3,     3,
    1470                 :             : /*
    1471                 :             :  *                      ------------------ N, P stereocenters -----------------
    1472                 :             :  *                        14     15       16     17     18       19       20
    1473                 :             :  *
    1474                 :             :  *                                                             Phosphine Arsine
    1475                 :             :  *                                      X---Y
    1476                 :             :  *                        |      |       \ /     |       |       \ /      \ /
    1477                 :             :  *                       =N-    >N[+]     N     >P[+]   =P-       P        As
    1478                 :             :  *                        |      |        |      |       |        |        |
    1479                 :             :  */
    1480                 :             : #define SZELEM3         "N\000","N\000","N\000","P\000","P\000","P\000", "As",
    1481                 :             : #define CCHARGE3         0,      1,      0,      1,      0,      0,       0,
    1482                 :             : #define CNUMBONDSANDH3   4,      4,      3,      4,      4,      3,       3,
    1483                 :             : #define CCHEMVALENCEH3   5,      4,      3,      4,      5,      3,       3,
    1484                 :             : #define CHAS3MEMBRING3   0,      0,      1,      0,      0,      0,       0,
    1485                 :             : #define CREQUIRDNEIGH3   3,      3,      1,      3,      3,      2,       2,
    1486                 :             : 
    1487                 :             : #define PHOSPHINE_STEREO  19  /* the number must match Phosphine number in the comments, see above */
    1488                 :             : #define ARSINE_STEREO     20  /* the number must match Arsine number in the comments, see above */
    1489                 :             : 
    1490                 :             :     static const char        szElem[][3] = { SZELEM1         SZELEM2         SZELEM3 };
    1491                 :             :     static const S_CHAR        cCharge[] = { CCHARGE1        CCHARGE2        CCHARGE3 };
    1492                 :             :     static const S_CHAR  cNumBondsAndH[] = { CNUMBONDSANDH1  CNUMBONDSANDH2  CNUMBONDSANDH3 };
    1493                 :             :     static const S_CHAR  cChemValenceH[] = { CCHEMVALENCEH1  CCHEMVALENCEH2  CCHEMVALENCEH3 };
    1494                 :             :     static const S_CHAR  cHas3MembRing[] = { CHAS3MEMBRING1  CHAS3MEMBRING2  CHAS3MEMBRING3 };
    1495                 :             :     static const S_CHAR  cRequirdNeigh[] = { CREQUIRDNEIGH1  CREQUIRDNEIGH2  CREQUIRDNEIGH3 };
    1496                 :             : 
    1497                 :             :     static const int n = sizeof( szElem ) / sizeof( szElem[0] );
    1498                 :             :     /* reqired neighbor types (bitmap):
    1499                 :             :        0 => check bonds only
    1500                 :             :        1 => no terminal hydrogen atom neighbors
    1501                 :             :        2 => no terminal -X and -XH together (don't care the bond type, charge, radical)
    1502                 :             :             (X = tautomeric endpoint atom)
    1503                 :             :        Note: whenever cChemValenceH[] > cNumBondsAndH[]
    1504                 :             :              the tautomeric and/or alternating bonds
    1505                 :             :              are permitted
    1506                 :             : 
    1507                 :             :     */
    1508                 :        1238 :     int i, ret = 0;
    1509         [ +  + ]:       10772 :     for (i = 0; i < n; i++)
    1510                 :             :     {
    1511         [ +  + ]:       10318 :         if (!strcmp( at[cur_at].elname, szElem[i] ) &&
    1512         [ +  + ]:         934 :             ( at[cur_at].charge == cCharge[i]
    1513                 :             : #ifdef ALLOW_NO_CHARGE_ON_STEREO_CENTERS
    1514                 :             :               || at[cur_at].charge == 0
    1515                 :             : #endif
    1516                 :         896 :               ) &&
    1517   [ -  +  -  - ]:         896 :               ( !at[cur_at].radical || at[cur_at].radical == 1 ) &&
    1518         [ +  + ]:         896 :              at[cur_at].valence + at[cur_at].num_H == cNumBondsAndH[i] &&
    1519   [ +  +  -  + ]:         856 :              at[cur_at].chem_bonds_valence + at[cur_at].num_H == cChemValenceH[i] &&
    1520   [ +  +  +  - ]:        1602 :              ( cHas3MembRing[i] ? is_atom_in_3memb_ring( at, cur_at ) : 1 ) &&
    1521                 :         784 :              bInpAtomHasRequirdNeigh( at, cur_at, cRequirdNeigh[i], cChemValenceH[i] - cNumBondsAndH[i], bStereoAtZz ))
    1522                 :             :             /*
    1523                 :             :             if (!strcmp( at[cur_at].elname, szElem[i] ) &&
    1524                 :             :              at[cur_at].charge == cCharge[i] &&
    1525                 :             :              ( !at[cur_at].radical || at[cur_at].radical == 1 ) &&
    1526                 :             :              at[cur_at].valence + at[cur_at].num_H == cNumBondsAndH[i] &&
    1527                 :             :              at[cur_at].chem_bonds_valence + at[cur_at].num_H == cChemValenceH[i] &&
    1528                 :             :              ( cHas3MembRing[i] ? is_atom_in_3memb_ring( at, cur_at ) : 1 ) &&
    1529                 :             :              bInpAtomHasRequirdNeigh( at, cur_at, cRequirdNeigh[i], cChemValenceH[i] - cNumBondsAndH[i], bStereoAtZz ))*/
    1530                 :             :         {
    1531                 :         784 :             ret = cNumBondsAndH[i];
    1532                 :         784 :             break;
    1533                 :             :         }
    1534                 :             :     }
    1535                 :             : 
    1536   [ -  +  -  - ]:        1238 :     if (i == PHOSPHINE_STEREO && !( bPointedEdgeStereo & PES_BIT_PHOSPHINE_STEREO ))
    1537                 :             :     {
    1538                 :           0 :         ret = 0;
    1539                 :             :     }
    1540   [ -  +  -  - ]:        1238 :     if (i == ARSINE_STEREO && !( bPointedEdgeStereo & PES_BIT_ARSINE_STEREO ))
    1541                 :             :     {
    1542                 :           0 :         ret = 0;
    1543                 :             :     }
    1544                 :             : 
    1545                 :        1238 :     return ret;
    1546                 :             : }
    1547                 :             : 
    1548                 :             : 
    1549                 :             : #else /* } NEW_STEREOCENTER_CHECK { */
    1550                 :             : 
    1551                 :             : 
    1552                 :             : /****************************************************************************/
    1553                 :             : int bCanAtomBeAStereoCenter( char *elname, S_CHAR charge, S_CHAR radical )
    1554                 :             : {
    1555                 :             :     static const char   szElem[][3] = { "C\000", "Si", "Ge", "N\000", "P\000", "As", "B\000" };
    1556                 :             :     static const S_CHAR   cCharge[] = { 0,        0,    0,   1,       1,       1,    -1 };
    1557                 :             :     int i, ret = 0;
    1558                 :             :     for (i = 0; i < sizeof( szElem ) / sizeof( szElem[0] ); i++)
    1559                 :             :     {
    1560                 :             :         if (!strcmp( elname, szElem[i] ) && ( charge == cCharge[i] ))
    1561                 :             :         {
    1562                 :             :             ret = ( !radical || radical == RADICAL_SINGLET );
    1563                 :             :             break;
    1564                 :             :         }
    1565                 :             :     }
    1566                 :             :     return ret;
    1567                 :             : }
    1568                 :             : #endif /* } NEW_STEREOCENTER_CHECK */
    1569                 :             : 
    1570                 :             : 
    1571                 :             : /****************************************************************************
    1572                 :             :  used for atoms adjacent to stereogenic bonds only
    1573                 :             : ****************************************************************************/
    1574                 :           0 : int bAtomHasValence3( char *elname, S_CHAR charge, S_CHAR radical )
    1575                 :             : {
    1576                 :             :     static const char   szElem[][3] = { "N\000" };
    1577                 :             :     static const S_CHAR   cCharge[] = { 0, };
    1578                 :           0 :     int i, ret = 0;
    1579         [ #  # ]:           0 :     for (i = 0; i < (int) ( sizeof( szElem ) / sizeof( szElem[0] ) ); i++)
    1580                 :             :     {
    1581   [ #  #  #  # ]:           0 :         if (!strcmp( elname, szElem[i] ) && ( charge == cCharge[i] ))
    1582                 :             :         {
    1583   [ #  #  #  # ]:           0 :             ret = ( !radical || radical == RADICAL_SINGLET );
    1584                 :           0 :             break;
    1585                 :             :         }
    1586                 :             :     }
    1587                 :           0 :     return ret;
    1588                 :             : }
    1589                 :             : 
    1590                 :             : 
    1591                 :             : /****************************************************************************
    1592                 :             :  used for atoms adjacent to stereogenic bonds only
    1593                 :             : ****************************************************************************/
    1594                 :         252 : int bCanAtomHaveAStereoBond( char *elname, S_CHAR charge, S_CHAR radical )
    1595                 :             : {
    1596                 :             :     static const char   szElem[][3] = { "C\000", "Si", "Ge", "N\000", "N\000" };
    1597                 :             :     static const S_CHAR   cCharge[] = { 0,        0,    0,   0,       1, };
    1598                 :             :     static const int       n = sizeof( szElem ) / sizeof( szElem[0] );
    1599                 :         252 :     int i, ret = 0;
    1600         [ +  + ]:        1004 :     for (i = 0; i < n; i++)
    1601                 :             :     {
    1602   [ +  +  +  + ]:         874 :         if (!strcmp( elname, szElem[i] ) && ( charge == cCharge[i] ))
    1603                 :             :         {
    1604   [ -  +  -  - ]:         122 :             ret = ( !radical || radical == RADICAL_SINGLET );
    1605                 :         122 :             break;
    1606                 :             :         }
    1607                 :             :     }
    1608                 :         252 :     return ret;
    1609                 :             : }
    1610                 :             : 
    1611                 :             : 
    1612                 :             : /****************************************************************************
    1613                 :             :  used for atoms adjacent to stereogenic bonds only
    1614                 :             : ****************************************************************************/
    1615                 :           0 : int bCanAtomBeMiddleAllene( char *elname, S_CHAR charge, S_CHAR radical )
    1616                 :             : {
    1617                 :             :     static const char   szElem[][3] = { "C\000", "Si", "Ge", };
    1618                 :             :     static const S_CHAR   cCharge[] = { 0,        0,    0, };
    1619                 :             :     static const int       n = sizeof( szElem ) / sizeof( szElem[0] );
    1620                 :           0 :     int i, ret = 0;
    1621         [ #  # ]:           0 :     for (i = 0; i < n; i++)
    1622                 :             :     {
    1623   [ #  #  #  # ]:           0 :         if (!strcmp( elname, szElem[i] ) && ( charge == cCharge[i] ))
    1624                 :             :         {
    1625   [ #  #  #  # ]:           0 :             ret = ( !radical || radical == RADICAL_SINGLET );
    1626                 :           0 :             break;
    1627                 :             :         }
    1628                 :             :     }
    1629                 :           0 :     return ret;
    1630                 :             : }
    1631                 :             : 
    1632                 :             : 
    1633                 :             : /****************************************************************************/
    1634                 :          24 : int bIsSuitableHeteroInpAtom( inp_ATOM  *at )
    1635                 :             : {
    1636                 :             :     int val, num_H;
    1637         [ +  - ]:          24 :     if (0 == at->charge &&
    1638   [ -  +  -  -  :          48 :         ( !at->radical || RADICAL_SINGLET == at->radical ) &&
                   -  + ]
    1639                 :          24 :          0 < ( val = get_endpoint_valence( at->el_number ) ))
    1640                 :             :     {
    1641                 :           0 :         num_H = at->num_H;
    1642         [ #  # ]:           0 :         if (val == at->chem_bonds_valence + num_H)
    1643                 :             :         {
    1644      [ #  #  # ]:           0 :             switch (val)
    1645                 :             :             {
    1646                 :           0 :                 case 2: /* O */
    1647   [ #  #  #  # ]:           0 :                     if (!num_H && 1 == at->valence)
    1648                 :             :                     {
    1649                 :           0 :                         return 0; /* =O */
    1650                 :             :                     }
    1651                 :           0 :                     break;        /* not found */
    1652                 :           0 :                 case 3: /* N */
    1653   [ #  #  #  # ]:           0 :                     if ((1 == at->valence && 1 == num_H) ||
    1654   [ #  #  #  # ]:           0 :                          (2 == at->valence && 0 == num_H)) /* djb-rwth: addressing LLVM warnings */
    1655                 :             :                     {
    1656                 :           0 :                         return 1; /* =N- or =NH */
    1657                 :             :                     }
    1658                 :           0 :                     break;        /* not found */
    1659                 :             :             }
    1660                 :             :         }
    1661                 :             :     }
    1662                 :          24 :     return -1;
    1663                 :             : }
    1664                 :             : 
    1665                 :             : 
    1666                 :             : /****************************************************************************/
    1667                 :           0 : int bIsOxide( inp_ATOM  *at, int cur_at )
    1668                 :             : {
    1669                 :             :     int i, bond_type;
    1670                 :           0 :     inp_ATOM  *a = at + cur_at, *an;
    1671         [ #  # ]:           0 :     for (i = 0; i < a->valence; i++)
    1672                 :             :     {
    1673                 :           0 :         bond_type = ( a->bond_type[i] &= ~BOND_MARK_ALL );
    1674         [ #  # ]:           0 :         if (bond_type == BOND_DOUBLE)
    1675                 :             :         {
    1676                 :           0 :             an = at + (int) a->neighbor[i];
    1677         [ #  # ]:           0 :             if (1 == an->valence &&
    1678   [ #  #  #  #  :           0 :                  !an->charge && !an->num_H && !an->radical &&
             #  #  #  # ]
    1679                 :           0 :                  2 == get_endpoint_valence( an->el_number ))
    1680                 :             :             {
    1681                 :           0 :                 return 1;
    1682                 :             :             }
    1683                 :             :         }
    1684                 :             :         else
    1685                 :             :         {
    1686   [ #  #  #  # ]:           0 :             if (bond_type == BOND_TAUTOM || bond_type == BOND_ALT12NS)
    1687                 :             :             {
    1688                 :           0 :                 an = at + (int) a->neighbor[i];
    1689   [ #  #  #  # ]:           0 :                 if (1 == an->valence &&
    1690                 :           0 :                      2 == get_endpoint_valence( an->el_number ))
    1691                 :             :                 {
    1692                 :           0 :                     return 1;
    1693                 :             :                 }
    1694                 :             :             }
    1695                 :             :         }
    1696                 :             :     }
    1697                 :             : 
    1698                 :           0 :     return 0;
    1699                 :             : }
    1700                 :             : 
    1701                 :             : 
    1702                 :             : /****************************************************************************
    1703                 :             :  used for atoms adjacent to stereogenic bonds only
    1704                 :             :  ****************************************************************************/
    1705                 :           8 : int bCanAtomBeTerminalAllene( char *elname, S_CHAR charge, S_CHAR radical )
    1706                 :             : {
    1707                 :             :     static const char   szElem[][3] = { "C\000", "Si", "Ge", };
    1708                 :             :     static const S_CHAR   cCharge[] = { 0,        0,    0, };
    1709                 :             :     static const int       n = sizeof( szElem ) / sizeof( szElem[0] );
    1710                 :           8 :     int i, ret = 0;
    1711         [ +  - ]:           8 :     for (i = 0; i < n; i++)
    1712                 :             :     {
    1713   [ +  -  +  - ]:           8 :         if (!strcmp( elname, szElem[i] ) && ( charge == cCharge[i] ))
    1714                 :             :         {
    1715   [ -  +  -  - ]:           8 :             ret = ( !radical || radical == RADICAL_SINGLET );
    1716                 :           8 :             break;
    1717                 :             :         }
    1718                 :             :     }
    1719                 :             : 
    1720                 :           8 :     return ret;
    1721                 :             : }
    1722                 :             : 
    1723                 :             : 
    1724                 :             : /****************************************************************************/
    1725                 :           0 : int GetHalfStereobond0DParity( inp_ATOM *at,
    1726                 :             :                                int cur_at,
    1727                 :             :                                AT_NUMB nSbNeighOrigAtNumb[],
    1728                 :             :                                int nNumExplictAttachments,
    1729                 :             :                                int bond_parity,
    1730                 :             :                                int nFlag )
    1731                 :             : {
    1732                 :             :     int m, last_parity, cur_parity;
    1733                 :             :     int i, icur2nxt, icur2neigh, cur_order_parity, nxt_at;
    1734                 :             :     AT_NUMB nNextSbAtOrigNumb;
    1735                 :             :     /* find atom parities for all valid streobonds incident to at[cur_at] */
    1736   [ #  #  #  # ]:           0 :     for (m = 0, last_parity = 0; m < MAX_NUM_STEREO_BONDS && at[cur_at].sb_parity[m]; m++)
    1737                 :             :     {
    1738                 :           0 :         icur2nxt = icur2neigh = -1; /* ordering number of neighbors in nSbNeighOrigAtNumb[] */
    1739                 :           0 :         cur_parity = 0;             /* parity for mth stereobond incident to the cur_at */
    1740                 :           0 :         nxt_at = at[cur_at].neighbor[(int)at[cur_at].sb_ord[m]]; /* djb-rwth: fixing coverity ID #499549 */
    1741   [ #  #  #  # ]:           0 :         if (0 <= at[cur_at].sb_ord[m] && at[cur_at].sb_ord[m] < at[cur_at].valence &&
    1742         [ #  # ]:           0 :              at[nxt_at].valence <= MAX_NUM_STEREO_BONDS && /* make sure it is a valid stereobond */
    1743         [ #  # ]:           0 :              ( nNextSbAtOrigNumb = at[nxt_at].orig_at_number ))
    1744                 :             :         {
    1745                 :             :             /* since at[cur_at].sn_ord[m] = -1 for explicit H use at[cur_at].sn_orig_at_num[m] */
    1746         [ #  # ]:           0 :             for (i = 0; i < nNumExplictAttachments; i++)
    1747                 :             :             {
    1748         [ #  # ]:           0 :                 if (at[cur_at].sn_orig_at_num[m] == nSbNeighOrigAtNumb[i])
    1749                 :             :                 {
    1750                 :           0 :                     icur2neigh = i; /* neighbor */
    1751                 :             :                 }
    1752                 :             :                 else
    1753                 :             :                 {
    1754         [ #  # ]:           0 :                     if (nNextSbAtOrigNumb == nSbNeighOrigAtNumb[i])
    1755                 :             :                     {
    1756                 :           0 :                         icur2nxt = i; /* atom connected by a stereobond */
    1757                 :             :                     }
    1758                 :             :                 }
    1759                 :             :             }
    1760   [ #  #  #  # ]:           0 :             if (icur2neigh >= 0 && icur2nxt >= 0)
    1761                 :             :             {
    1762   [ #  #  #  # ]:           0 :                 if (ATOM_PARITY_WELL_DEF( at[cur_at].sb_parity[m] ))
    1763                 :             :                 {
    1764                 :             :                     /* parity of at[cur_atom] neighbor permutation to reach this order: { next_atom, neigh_atom, ...} */
    1765                 :           0 :                     cur_order_parity = ( icur2nxt + icur2neigh + ( icur2nxt > icur2neigh ) - 1 ) % 2;
    1766                 :           0 :                     cur_parity = 2 - ( cur_order_parity + at[cur_at].sb_parity[m] ) % 2;
    1767                 :             :                 }
    1768                 :             :                 else
    1769                 :             :                 {
    1770                 :             :                              /* unknowm/undef parities do not depend on the neighbor order */
    1771                 :           0 :                     cur_parity = at[cur_at].sb_parity[m];
    1772                 :             :                 }
    1773                 :             :             }
    1774                 :             :         }
    1775                 :             :         else
    1776                 :             :         {
    1777                 :           0 :             continue;
    1778                 :             :         }
    1779                 :             :         /* use a well-known parity if available; if not then use preferably the unknown */
    1780         [ #  # ]:           0 :         if (!last_parity)
    1781                 :             :         {
    1782                 :           0 :             last_parity = cur_parity;
    1783                 :             :         }
    1784                 :             :         else
    1785                 :             :         {
    1786   [ #  #  #  # ]:           0 :             if (last_parity != cur_parity && cur_parity)
    1787                 :             :             {
    1788   [ #  #  #  # ]:           0 :                 if (ATOM_PARITY_WELL_DEF( last_parity ))
    1789                 :             :                 {
    1790   [ #  #  #  # ]:           0 :                     if (ATOM_PARITY_WELL_DEF( cur_parity ))
    1791                 :             :                     {
    1792                 :           0 :                         last_parity = 0; /* error: all well-defined parities should be same */
    1793                 :           0 :                         break;
    1794                 :             :                     }
    1795                 :             :                 }
    1796                 :             :                 else
    1797                 :             :                 {
    1798   [ #  #  #  # ]:           0 :                     if (ATOM_PARITY_WELL_DEF( cur_parity ))
    1799                 :             :                     {
    1800                 :             :                         /* replace unknown/undefined parity with well-known */
    1801                 :           0 :                         last_parity = cur_parity;
    1802                 :             :                     }
    1803                 :             :                     else
    1804                 :             :                     {
    1805                 :             :                         /* select min unknown/undefined parity (out of AB_PARITY_UNKN and AB_PARITY_UNDF) */
    1806                 :           0 :                         last_parity = inchi_min( cur_parity, last_parity );
    1807                 :             :                     }
    1808                 :             :                 }
    1809                 :             :             }
    1810                 :             :         }
    1811                 :             :     }
    1812                 :             : 
    1813         [ #  # ]:           0 :     if (last_parity)
    1814                 :             :     {
    1815                 :           0 :         bond_parity = last_parity;
    1816                 :           0 :         at[cur_at].bUsed0DParity |= nFlag; /* set flag: used stereobond 0D parity */
    1817                 :             :     }
    1818                 :             : 
    1819                 :           0 :     return bond_parity;
    1820                 :             : }
    1821                 :             : 
    1822                 :             : 
    1823                 :             : /****************************************************************************/
    1824                 :           0 : int FixSb0DParities( inp_ATOM *at,
    1825                 :             :                      /* inp_ATOM *at_removed_H,
    1826                 :             :                      int num_removed_H,*/
    1827                 :             :                      int chain_length,
    1828                 :             :                      int at_1,
    1829                 :             :                      int i_next_at_1,
    1830                 :             :                      S_CHAR z_dir1[],
    1831                 :             :                      int at_2,
    1832                 :             :                      int i_next_at_2,
    1833                 :             :                      S_CHAR z_dir2[],
    1834                 :             :                      int *pparity1,
    1835                 :             :                      int *pparity2 )
    1836                 :             : {
    1837                 :             :     int k, parity1, parity2, abs_parity1, abs_parity2;
    1838                 :             :     int j1, j2, parity_sign;
    1839                 :             :     /*
    1840                 :             :     AT_NUMB nSbNeighOrigAtNumb1[MAX_NUM_STEREO_BOND_NEIGH], nSbNeighOrigAtNumb2[MAX_NUM_STEREO_BOND_NEIGH];
    1841                 :             :     int     nNumExplictAttachments1, nNumExplictAttachments2;
    1842                 :             :     */
    1843                 :           0 :     parity1 = parity2 = AB_PARITY_NONE;
    1844                 :           0 :     j1 = j2 = -1;
    1845   [ #  #  #  # ]:           0 :     parity_sign = ( *pparity1 < 0 || *pparity2 < 0 ) ? -1 : 1;
    1846                 :             : 
    1847                 :           0 :     abs_parity1 = abs( *pparity1 );
    1848                 :           0 :     abs_parity2 = abs( *pparity2 );
    1849                 :             : 
    1850   [ #  #  #  # ]:           0 :     for (k = 0; k < MAX_NUM_STEREO_BONDS && at[at_1].sb_parity[k]; k++)
    1851                 :             :     {
    1852         [ #  # ]:           0 :         if (at[at_1].sb_ord[k] == i_next_at_1)
    1853                 :             :         {
    1854                 :           0 :             parity1 = at[at_1].sb_parity[k];
    1855                 :           0 :             j1 = k;
    1856                 :             :         }
    1857                 :             :     }
    1858   [ #  #  #  # ]:           0 :     for (k = 0; k < MAX_NUM_STEREO_BONDS && at[at_2].sb_parity[k]; k++)
    1859                 :             :     {
    1860         [ #  # ]:           0 :         if (at[at_2].sb_ord[k] == i_next_at_2)
    1861                 :             :         {
    1862                 :           0 :             parity2 = at[at_2].sb_parity[k];
    1863                 :           0 :             j2 = k;
    1864                 :             :         }
    1865                 :             :     }
    1866   [ #  #  #  #  :           0 :     switch (( j1 >= 0 ) + 2 * ( j2 >= 0 ))
                   #  # ]
    1867                 :             :     {
    1868                 :           0 :         case 0:
    1869                 :             :             /* the bond has no 0D parity */
    1870                 :           0 :             *pparity1 = *pparity2 = parity_sign * AB_PARITY_UNDF;
    1871                 :           0 :             return 0;
    1872                 :           0 :         case 1:
    1873                 :             :         case 2:
    1874                 :             :             /* 0D parity data error */
    1875                 :           0 :             *pparity1 = *pparity2 = AB_PARITY_NONE;
    1876                 :           0 :             return -1;
    1877                 :           0 :         case 3:
    1878                 :             :             /* the bond has 0D parity */
    1879   [ #  #  #  #  :           0 :             switch (!( ATOM_PARITY_WELL_DEF( abs_parity1 ) && ATOM_PARITY_WELL_DEF( parity1 ) ) +
             #  #  #  # ]
    1880   [ #  #  #  #  :           0 :                      2 * !( ATOM_PARITY_WELL_DEF( abs_parity2 ) && ATOM_PARITY_WELL_DEF( parity2 ) ))
          #  #  #  #  #  
             #  #  #  # ]
    1881                 :             :             {
    1882                 :           0 :                 case 0:
    1883                 :             :                     /* both parities are well-defined; continue */
    1884                 :           0 :                     break;
    1885                 :           0 :                 case 1:
    1886                 :             :                     /* 0D parity not well-defined for at_1 */
    1887   [ #  #  #  # ]:           0 :                     *pparity1 = parity_sign * ( ATOM_PARITY_WELL_DEF( parity1 ) ? abs_parity1 :
    1888   [ #  #  #  # ]:           0 :                                                ATOM_PARITY_WELL_DEF( abs_parity1 ) ? parity1 :
    1889                 :             :                                                inchi_min( abs_parity1, parity1 ) );
    1890                 :           0 :                     *pparity2 = parity_sign * abs_parity2;
    1891                 :           0 :                     return -1;
    1892                 :           0 :                 case 2:
    1893                 :             :                     /* 0D parity not well-defined for at_2 */
    1894                 :           0 :                     *pparity1 = parity_sign * abs_parity1;
    1895   [ #  #  #  # ]:           0 :                     *pparity2 = parity_sign * ( ATOM_PARITY_WELL_DEF( parity2 ) ? abs_parity2 :
    1896   [ #  #  #  # ]:           0 :                                                ATOM_PARITY_WELL_DEF( abs_parity2 ) ? parity2 :
    1897                 :             :                                                inchi_min( abs_parity2, parity2 ) );
    1898                 :           0 :                     return -1;
    1899                 :           0 :                 case 3:
    1900   [ #  #  #  # ]:           0 :                     abs_parity1 = ( ATOM_PARITY_WELL_DEF( parity1 ) ? abs_parity1 :
    1901   [ #  #  #  # ]:           0 :                                     ATOM_PARITY_WELL_DEF( abs_parity1 ) ? parity1 :
    1902                 :             :                                     inchi_min( abs_parity1, parity1 ) );
    1903   [ #  #  #  # ]:           0 :                     abs_parity2 = ( ATOM_PARITY_WELL_DEF( parity2 ) ? abs_parity2 :
    1904   [ #  #  #  # ]:           0 :                                     ATOM_PARITY_WELL_DEF( abs_parity2 ) ? parity2 :
    1905                 :             :                                     inchi_min( abs_parity2, parity2 ) );
    1906                 :           0 :                     *pparity1 = *pparity2 = parity_sign * inchi_min( abs_parity1, abs_parity2 );
    1907                 :             :                     /*return (parity1 == parity2)? 0 : -1;*/
    1908                 :           0 :                     return -1;
    1909                 :             :             }
    1910                 :           0 :             break;
    1911                 :             :     }
    1912                 :             :     /* we are here if both end-atoms of the bond have well-defined 0D parities */
    1913                 :             :     /*
    1914                 :             :     nNumExplictAttachments1 = GetSbNeighOrigAtNumb( at, at_1, at_removed_H, num_removed_H, nSbNeighOrigAtNumb1 );
    1915                 :             :     nNumExplictAttachments2 = GetSbNeighOrigAtNumb( at, at_2, at_removed_H, num_removed_H, nSbNeighOrigAtNumb2 );
    1916                 :             :     parity1 = GetHalfStereobond0DParity( at, at_1, nSbNeighOrigAtNumb1, nNumExplictAttachments1, *pparity1, 0 );
    1917                 :             :     parity2 = GetHalfStereobond0DParity( at, at_2, nSbNeighOrigAtNumb2, nNumExplictAttachments2, *pparity2, 0 );
    1918                 :             :     */
    1919                 :           0 :     *pparity1 = parity_sign * abs_parity1;
    1920                 :           0 :     *pparity2 = parity_sign * abs_parity2;
    1921                 :             : 
    1922         [ #  # ]:           0 :     if (chain_length % 2)
    1923                 :             :     {
    1924                 :             :         /* allene; chain_length = (number of double bonds) - 1 */
    1925                 :             :         /*
    1926                 :             :         int zer1 = ( !z_dir1[0] && !z_dir1[1] && !z_dir1[2] );
    1927                 :             :         int zer2 = ( !z_dir2[0] && !z_dir2[1] && !z_dir2[2] );
    1928                 :             :         */
    1929                 :           0 :         int bWrong_z_dir1 = ( 0 != ( at[at_1].bUsed0DParity & FlagSB_0D ) );
    1930                 :           0 :         int bWrong_z_dir2 = ( 0 != ( at[at_2].bUsed0DParity & FlagSB_0D ) );
    1931                 :             : 
    1932   [ #  #  #  # ]:           0 :         if (bWrong_z_dir1 && bWrong_z_dir2)
    1933                 :             :         {
    1934                 :           0 :             goto set_default;
    1935                 :             :         }
    1936                 :             :         else
    1937                 :             :         {
    1938   [ #  #  #  # ]:           0 :             if (bWrong_z_dir1 || bWrong_z_dir2)
    1939                 :             :             {
    1940                 :             :                 double r12[3], zi1[3], zi2[3], abs_r12, abs_zi2;
    1941                 :             :                 int    at_i1, at_i2, j; /* djb-rwth: ignoring LLVM warning: variables used */
    1942                 :             :                 S_CHAR   z_dir[3];
    1943                 :           0 :                 r12[0] = at[at_2].x - at[at_1].x;
    1944                 :           0 :                 r12[1] = at[at_2].y - at[at_1].y;
    1945                 :           0 :                 r12[2] = at[at_2].z - at[at_1].z;
    1946                 :           0 :                 abs_r12 = len3( r12 );
    1947         [ #  # ]:           0 :                 if (abs_r12 < MIN_BOND_LEN)
    1948                 :             :                 {
    1949                 :           0 :                     goto set_default;
    1950                 :             :                 }
    1951                 :             :                 /* make r12[] point to the atom with 'good' z_dir[] */
    1952         [ #  # ]:           0 :                 if (bWrong_z_dir1)
    1953                 :             :                 {
    1954                 :           0 :                     at_i1 = at_2; /* has good z_dir2[] */ /* djb-rwth: ignoring LLVM warning: variable used */
    1955                 :           0 :                     at_i2 = at_1; /* has bad  z_dir1[] */ /* djb-rwth: ignoring LLVM warning: variable used */
    1956                 :           0 :                     zi1[0] = z_dir2[0];
    1957                 :           0 :                     zi1[1] = z_dir2[1];
    1958                 :           0 :                     zi1[2] = z_dir2[2];
    1959                 :           0 :                     mult3( r12, 1.0 / abs_r12, r12 ); /* make length = 1 */
    1960                 :             :                 }
    1961                 :             :                 else
    1962                 :             :                 {
    1963                 :           0 :                     at_i1 = at_1; /* has good z_dir1[] */ /* djb-rwth: ignoring LLVM warning: variable used */
    1964                 :           0 :                     at_i2 = at_2; /* has bad  z_dir2[] */ /* djb-rwth: ignoring LLVM warning: variable used */
    1965                 :           0 :                     zi1[0] = z_dir1[0];
    1966                 :           0 :                     zi1[1] = z_dir1[1];
    1967                 :           0 :                     zi1[2] = z_dir1[2];
    1968                 :           0 :                     mult3( r12, -1.0 / abs_r12, r12 ); /* make length = 1 */
    1969                 :             :                 }
    1970                 :           0 :                 cross_prod3( r12, zi1, zi2 );
    1971                 :           0 :                 abs_zi2 = len3( zi2 );
    1972                 :           0 :                 mult3( zi2, 100.0 / abs_zi2, zi2 ); /* make length = 100 */
    1973         [ #  # ]:           0 :                 for (j = 0; j < 3; j++)
    1974                 :             :                 {
    1975         [ #  # ]:           0 :                     z_dir[j] = (S_CHAR) ( zi2[j] >= 0.0 ? floor( 0.5 + zi2[j] ) :
    1976                 :           0 :                                                        -floor( 0.5 - zi2[j] ) ); /*  abs(z_dir) = 100 */
    1977                 :             :                 }
    1978         [ #  # ]:           0 :                 if (bWrong_z_dir1)
    1979                 :             :                 {
    1980                 :           0 :                     memcpy(z_dir1, z_dir, sizeof(z_dir));
    1981                 :             :                 }
    1982                 :             :                 else
    1983                 :             :                 {
    1984                 :           0 :                     memcpy(z_dir2, z_dir, sizeof(z_dir));
    1985                 :             :                 }
    1986                 :             :             }
    1987                 :             :         }
    1988                 :           0 :         return 0;
    1989                 :             : 
    1990                 :           0 :     set_default:
    1991                 :             :         /* z_dir1[] = x-direction; z_dir2[] = z-direction; r12[] = y-direction */
    1992                 :           0 :         z_dir1[0] = 100;
    1993                 :           0 :         z_dir1[1] = z_dir1[2] = 0;
    1994                 :           0 :         z_dir2[0] = z_dir2[1] = 0;
    1995                 :           0 :         z_dir2[2] = 100;
    1996                 :             :     }
    1997                 :             : 
    1998                 :           0 :     return 0;
    1999                 :             : }
    2000                 :             : 
    2001                 :             : 
    2002                 :             : /****************************************************************************
    2003                 :             :  without this InChI fails on reconstructed  CID=450438
    2004                 :             :  (isotopic, Unknown SB adjacent to SB with known parity)
    2005                 :             : ****************************************************************************/
    2006                 :           0 : int FixUnkn0DStereoBonds( inp_ATOM *at, int num_at )
    2007                 :             : {
    2008                 :           0 :     int i, m, num = 0;
    2009                 :             : 
    2010                 :             :     /* Add usual Unknown stereobond descriptors to each Unknown bond */
    2011         [ #  # ]:           0 :     for (i = 0; i < num_at; i++)
    2012                 :             :     {
    2013   [ #  #  #  # ]:           0 :         for (m = 0; m < MAX_NUM_STEREO_BONDS && at[i].sb_parity[m]; m++)
    2014                 :             :         {
    2015         [ #  # ]:           0 :             if (AB_PARITY_UNKN == at[i].sb_parity[m])
    2016                 :             :             {
    2017                 :           0 :                 at[i].bond_stereo[(int) at[i].sb_ord[m]] = STEREO_DBLE_EITHER;
    2018                 :           0 :                 num++;
    2019                 :             :             }
    2020                 :             :         }
    2021                 :             :     }
    2022                 :             : #ifdef NEVER
    2023                 :             :     if (num)
    2024                 :             :     {
    2025                 :             :         int j;
    2026                 :             :         /* how to remove Unknown stereo bond parities */
    2027                 :             :         for (i = 0; i < num_at; i++)
    2028                 :             :         {
    2029                 :             :             for (m = 0; m < MAX_NUM_STEREO_BONDS && at[i].sb_parity[m]; m++)
    2030                 :             :             {
    2031                 :             :                 if (AB_PARITY_UNKN == at[i].sb_parity[m])
    2032                 :             :                 {
    2033                 :             :                     for (j = m + 1; j < MAX_NUM_STEREO_BONDS; j++)
    2034                 :             :                     {
    2035                 :             :                         at[i].sb_parity[j - 1] = at[i].sb_parity[j];
    2036                 :             :                         at[i].sb_ord[j - 1] = at[i].sb_ord[j];
    2037                 :             :                         at[i].sn_ord[j - 1] = at[i].sn_ord[j];
    2038                 :             :                         at[i].sn_orig_at_num[j - 1] = at[i].sn_orig_at_num[j];
    2039                 :             :                     }
    2040                 :             :                     at[i].sb_parity[j - 1] = 0;
    2041                 :             :                     at[i].sb_ord[j - 1] = 0;
    2042                 :             :                     at[i].sn_ord[j - 1] = 0;
    2043                 :             :                     at[i].sn_orig_at_num[j - 1] = 0;
    2044                 :             :                 }
    2045                 :             :             }
    2046                 :             :         }
    2047                 :             :     }
    2048                 :             : #endif
    2049                 :             : 
    2050                 :           0 :     return num;
    2051                 :             : }
    2052                 :             : 
    2053                 :             : 
    2054                 :             : /*======================================================================================================
    2055                 :             : 
    2056                 :             : half_stereo_bond_parity() General Description:
    2057                 :             : 
    2058                 :             :     A) find projections of 3 bonds on a reasonable plane defined
    2059                 :             :        by a vector z_dir perpendicular to the plane
    2060                 :             :     B) calculate parity
    2061                 :             : 
    2062                 :             : half_stereo_bond_parity() Detailed Description:
    2063                 :             : 
    2064                 :             :     1) Find at_coord[] = vectors from the central atoms to its neighbors
    2065                 :             :     2) If only 2 neighbors are present, then create a reasonable 3rd neighbor
    2066                 :             :        (an implicit H or a fictitious atom in case of =NX) coordinates
    2067                 :             :     3) Normalize at_coord[] to unit length
    2068                 :             :     4) Find unit vector pnt[2] perpendicular to the plane containing
    2069                 :             :        at_coord[] arrow ends.
    2070                 :             :        Even though it is not necessary, make z-coordinate of pnt[2] positive.
    2071                 :             :        ** pnt[2] has the new z-axis direction **
    2072                 :             :     5) Let pnt[0] = perpendicular to pnt[2] component of at_coord[0];
    2073                 :             :        Normalize pnt[0] to unit length.
    2074                 :             :        ** pnt[0] has the new x-axis direction **
    2075                 :             :     6) Let pnt[1] = pnt[2] x pnt[0] (cross-product);
    2076                 :             :        ** pnt[1] has the new y-axis direction **
    2077                 :             :     7) Find at_coord[] in the new xyz-basis and normalize their xy-projections
    2078                 :             :        to a unit length
    2079                 :             :     8) In the new xy-plane find (counterclockwise) angles:
    2080                 :             :        tmp1 = (from at_coord[0] to at_coord[1])
    2081                 :             :        tmp2 = (from at_coord[0] to at_coord[2])
    2082                 :             :     9) Calculate the parity: if tmp1 < tmp2 then 1 (odd) else 2 (even)
    2083                 :             :        (even: looking from the arrow end of the new z-axis, 0, 1, and 2 neighbors
    2084                 :             :         are in clockwise order)
    2085                 :             :    10) Calculate z_dir = 100*pnt[2].
    2086                 :             : 
    2087                 :             :    Note1. If z_dir vectors of atoms located at the opposite ends of a double bond have approximately
    2088                 :             :           opposite directions (that is, their dot-product is negative) then the parity of the
    2089                 :             :           stereogenic bond calculated from half-bond-parities should be inverted
    2090                 :             : 
    2091                 :             :    Note2. In case of a tetrahedral cumulene a triple product (z_dir1, (1->2), z_dir2) is used instead
    2092                 :             :           of the dot-product. (1->2) is a vector from the atom#1 to the atom #2. This triple product
    2093                 :             :           is invariant with respect to the atom numbering because it does not change upon (1,2)
    2094                 :             :           permutation.
    2095                 :             : 
    2096                 :             :   Stereo ambiguity in case of 2 neighbors:
    2097                 :             :   ----------------------------------------
    2098                 :             :   Undefined: single-double bond angle > pi - arcsin(0.03) = 178.28164199834454285275613218975 degrees
    2099                 :             :   Ambiguous: single-double bond angle > 175 degrees = pi - 0.087156 Rad
    2100                 :             : 
    2101                 :             :    Return values
    2102                 :             :    (cases: I=only in case of isotopic H atoms the neighbors are different,
    2103                 :             :            N=in case of non-isotopic H atoms the neighbors are different)
    2104                 :             : 
    2105                 :             :   -4 = AB_PARITY_UNDF => atom is adjacent to a stereogenic bond, but the geometry is undefined, I
    2106                 :             :   -3 = AB_PARITY_UNKN => atom is adjacent to a stereogenic bond, but the geometry is not known to the iuser, I
    2107                 :             :   -2 =-AB_PARITY_EVEN => parity of an atom adjacent to a stereogenic bond, I
    2108                 :             :   -1 =-AB_PARITY_ODD  => parity of an atom adjacent to a stereogenic bond, I
    2109                 :             :    0 = AB_PARITY_NONE => the atom is not adjacent to a stereogenic bond
    2110                 :             :    1 = AB_PARITY_ODD  => parity of an atom adjacent to a stereogenic bond, N&I
    2111                 :             :    2 = AB_PARITY_EVEN => parity of an atom adjacent to a stereogenic bond, N&I
    2112                 :             :    3 = AB_PARITY_UNKN => atom is adjacent to a stereogenic bond, but the geometry is not known to the iuser, N&I
    2113                 :             :    4 = AB_PARITY_UNDF => atom is adjacent to a stereogenic bond, but the geometry is undefined, N&I
    2114                 :             :    5 = AB_PARITY_IISO => atom constitutionally equivalent to this atom may be adjacent to a stereogenic bond, I
    2115                 :             : 
    2116                 :             : 
    2117                 :             : =====================================================================================================*/
    2118                 :             : 
    2119                 :             : 
    2120                 :             : /****************************************************************************/
    2121                 :           0 : int half_stereo_bond_parity( inp_ATOM *at,
    2122                 :             :                              int cur_at,
    2123                 :             :                              inp_ATOM *at_removed_H,
    2124                 :             :                              int num_removed_H,
    2125                 :             :                              S_CHAR *z_dir,
    2126                 :             :                              int bPointedEdgeStereo,
    2127                 :             :                              int vABParityUnknown )
    2128                 :             : {
    2129                 :             :     double at_coord[MAX_NUM_STEREO_BOND_NEIGH][3], c, s, tmp[3], tmp1, tmp2, min_tmp, max_tmp, z;
    2130                 :             :     double temp[3], pnt[3][3];
    2131                 :           0 :     int j, k, p0, p1, p2, next, bValence3 = 0, num_z, nType, num_either_single; /* djb-rwth: ignoring LLVM warning: variable used in switch statement; removing redundant variables */
    2132                 :             :     int nNumExplictAttachments;
    2133                 :           0 :     int bond_parity = AB_PARITY_UNDF;
    2134                 :           0 :     int    num_H = 0, num_iH, num_eH = 0, num_nH = 0 /* = num_iso_H[0] */;
    2135                 :             :     int    num_iso_H[NUM_H_ISOTOPES + 1];
    2136                 :             :     int    index_H[5]; /*  cannot have more than 4 elements: 1 H, 1 1H, 1 D, 1 T atom(s) */
    2137                 :             :     /*    const double one_pi = 2.0*atan2(1.0 , 0.0 ); */
    2138                 :           0 :     const double one_pi = 3.14159265358979323846; /* M_PI */
    2139                 :           0 :     const double two_pi = 2.0*one_pi;
    2140                 :           0 :     int    bIgnoreIsotopicH = ( 0 != ( at[cur_at].cFlags & AT_FLAG_ISO_H_POINT ) );
    2141                 :             :     AT_NUMB nSbNeighOrigAtNumb[MAX_NUM_STEREO_BOND_NEIGH];
    2142                 :             : 
    2143                 :             : 
    2144   [ #  #  #  #  :           0 :     if (z_dir && !z_dir[0] && !z_dir[1] && !z_dir[2])
             #  #  #  # ]
    2145                 :             :     {
    2146                 :           0 :         z_dir[2] = 100;
    2147                 :             :     }
    2148                 :             : 
    2149                 :           0 :     num_H = at[cur_at].num_H;
    2150         [ #  # ]:           0 :     if (num_H > NUM_H_ISOTOPES)
    2151                 :             :     {
    2152                 :           0 :         return 0; /*  at least 2 H atoms are isotopically identical */
    2153                 :             :     }
    2154                 :             : 
    2155         [ #  # ]:           0 :     if (MAX_NUM_STEREO_BOND_NEIGH < at[cur_at].valence + num_H ||
    2156         [ #  # ]:           0 :          MIN_NUM_STEREO_BOND_NEIGH > at[cur_at].valence + num_H)
    2157                 :             :     {
    2158                 :           0 :         return 0;
    2159                 :             :     }
    2160                 :             : 
    2161         [ #  # ]:           0 :     if (!bCanAtomHaveAStereoBond( at[cur_at].elname, at[cur_at].charge, at[cur_at].radical ))
    2162                 :             :     {
    2163                 :           0 :         return 0;
    2164                 :             :     }
    2165                 :             : 
    2166         [ #  # ]:           0 :     if (!bIgnoreIsotopicH)
    2167                 :             :     {
    2168         [ #  # ]:           0 :         for (j = 0, num_nH = num_H; j < NUM_H_ISOTOPES; j++)
    2169                 :             :         {
    2170         [ #  # ]:           0 :             if (( k = (int) at[cur_at].num_iso_H[j] ) > 1)
    2171                 :             :             {
    2172                 :           0 :                 return AB_PARITY_IISO;  /*  two or more identical isotopic H atoms */
    2173                 :             :             }
    2174                 :           0 :             num_nH -= k;
    2175                 :             :         }
    2176                 :             :     }
    2177                 :             : 
    2178                 :             :     /*  at this point num_nH = number of non-isotopic H atoms */
    2179         [ #  # ]:           0 :     if (num_nH > 1)
    2180                 :             :     {
    2181                 :           0 :         return AB_PARITY_IISO; /*  two or more identical non-isotopic H atoms */
    2182                 :             :     }
    2183                 :             : 
    2184         [ #  # ]:           0 :     if (num_nH < 0)
    2185                 :             :     {
    2186                 :           0 :         return CT_ISO_H_ERR;  /*  program error */ /*   <BRKPT> */
    2187                 :             :     }
    2188                 :             : 
    2189         [ #  # ]:           0 :     for (j = 0; j < MAX_NUM_STEREO_BOND_NEIGH; j++) /* djb-rwth: avoiding garbage values with proper initialisation */
    2190                 :             :     {
    2191         [ #  # ]:           0 :         for (k = 0; k < 3; k++)
    2192                 :             :         {
    2193                 :           0 :             at_coord[j][k] = 0; 
    2194                 :             :         }
    2195                 :             :     }
    2196                 :             : 
    2197                 :             :     /********************************************************************
    2198                 :             :      * Note. At this point all (implicit and explicit) isotopic
    2199                 :             :      * terminal H neighbors are either different or not present.
    2200                 :             :      ********************************************************************/
    2201                 :             : 
    2202                 :             :     /*  locate explicit hydrogen atoms */
    2203                 :             :     /*  (at_removed_H are sorted in ascending isotopic H mass order, non-isotopic first) */
    2204                 :           0 :     memset( num_iso_H, 0, sizeof( num_iso_H ) ); /* djb-rwth: memset_s C11/Annex K variant? */
    2205   [ #  #  #  # ]:           0 :     if (at_removed_H && num_removed_H > 0)
    2206                 :             :     {
    2207         [ #  # ]:           0 :         for (j = 0; j < num_removed_H; j++)
    2208                 :             :         {
    2209         [ #  # ]:           0 :             if (at_removed_H[j].neighbor[0] == cur_at)
    2210                 :             :             {
    2211         [ #  # ]:           0 :                 k = bIgnoreIsotopicH ? 0 : at_removed_H[j].iso_atw_diff;
    2212   [ #  #  #  # ]:           0 :                 if (0 <= k && k <= NUM_H_ISOTOPES)
    2213                 :             :                 {
    2214         [ #  # ]:           0 :                     if (++num_iso_H[k] > 1)   /*  num_iso_H[0] = number of non-isotopic H atoms */
    2215                 :           0 :                         return CT_ISO_H_ERR;    /*  program error in counting hydrogens */ /*   <BRKPT> */
    2216                 :           0 :                     index_H[num_eH++] = j;
    2217                 :             :                 }
    2218                 :             :                 else
    2219                 :             :                 {
    2220                 :           0 :                     return CT_ISO_H_ERR;  /*  program error */ /*   <BRKPT> */
    2221                 :             :                 }
    2222                 :             :             }
    2223                 :             :         }
    2224                 :           0 :         num_iH = num_H - num_eH; /*  number of implicit non-isotopic and isotopic H atoms */
    2225         [ #  # ]:           0 :         if (num_iH > 1)
    2226                 :             :         {
    2227                 :             :             /*  more than one implicit H: cannot reconstruct the geometry */
    2228                 :           0 :             bond_parity = -AB_PARITY_UNDF;
    2229                 :           0 :             goto exit_function;
    2230                 :             :         }
    2231                 :             :     }
    2232                 :             :     /* djb-rwth: removing redundant code */
    2233                 :             :     /*  at this point num_iH = number of implicit non-isotopic and isotopic H atoms */
    2234         [ #  # ]:           0 :     if (at[cur_at].valence + num_eH < MIN_NUM_STEREO_BOND_NEIGH)
    2235                 :             :     {
    2236                 :             :         /*  =NH or =CHD when no explicit H is present */
    2237         [ #  # ]:           0 :         return num_H == 1 ? AB_PARITY_UNDF : -AB_PARITY_UNDF;
    2238                 :             :     }
    2239                 :             : 
    2240                 :           0 :     bValence3 = bAtomHasValence3( at[cur_at].elname, at[cur_at].charge, at[cur_at].radical );
    2241                 :             :     /*
    2242                 :             :      * Can one explicit hydrogen be added to make asymmetric configuration?
    2243                 :             :      * For now we can add 1 H atom in case of an appropriate geometry if:
    2244                 :             :      * (a) one non-isotopic H (even if explicit isotopic H atoms are present), or
    2245                 :             :      * (b) one isotopic or non-isotopic H if NO explicit isotopic or non-isotopic H atom is present
    2246                 :             :      * This makes sense only in case chem. valence = 4. In case of chem. valence = 3, do not check.
    2247                 :             :      */
    2248   [ #  #  #  #  :           0 :     if (at[cur_at].valence + num_eH == MIN_NUM_STEREO_BOND_NEIGH && !bValence3 &&
                   #  # ]
    2249   [ #  #  #  # ]:           0 :          !(/*(a)*/ (1 == num_nH && !num_iso_H[0]) ||
    2250         [ #  # ]:           0 :              /*(b)*/ (1 == num_H && !num_eH )) /* djb-rwth: addressing LLVM warnings */
    2251                 :             :        )
    2252                 :             :     {
    2253                 :           0 :         goto exit_function;
    2254                 :             :         /* return num_H == 1? AB_PARITY_UNDF : -AB_PARITY_UNDF; */
    2255                 :             :     }
    2256                 :             : 
    2257                 :             :     /*  store neighbors coordinates */
    2258                 :           0 :     num_z = num_either_single = 0; /* djb-rwth: ignoring LLVM warning: variable used for switch statement; removing redundant code */
    2259         [ #  # ]:           0 :     for (k = nNumExplictAttachments = 0; k < 2; k++)
    2260                 :             :     {
    2261      [ #  #  # ]:           0 :         switch (k)
    2262                 :             :         {
    2263                 :           0 :             case 0:
    2264         [ #  # ]:           0 :                 for (j = 0; j < num_eH; j++, nNumExplictAttachments++)
    2265                 :             :                 {
    2266                 :           0 :                     next = index_H[j];
    2267                 :           0 :                     at_coord[nNumExplictAttachments][0] = at_removed_H[next].x - at[cur_at].x;
    2268                 :           0 :                     at_coord[nNumExplictAttachments][1] = at_removed_H[next].y - at[cur_at].y;
    2269                 :           0 :                     nSbNeighOrigAtNumb[nNumExplictAttachments] = at_removed_H[next].orig_at_number;
    2270                 :             :                     /* use the fact that (at_removed_H - at) = (number of atoms except removed explicit H) */
    2271                 :           0 :                     z = -get_z_coord( at, (int) ( at_removed_H - at ) + next,
    2272                 :             :                                       0 /*neighbor #*/,
    2273                 :             :                                       &nType,
    2274                 :           0 :                                       -( bPointedEdgeStereo & PES_BIT_POINT_EDGE_STEREO ) );
    2275   [ #  #  #  # ]:           0 :                     switch (nType)
    2276                 :             :                     {
    2277                 :           0 :                         case ZTYPE_EITHER:
    2278                 :           0 :                             num_either_single++; /*  bond in "Either" direction. */
    2279                 :           0 :                             break;
    2280                 :           0 :                         case ZTYPE_UP:
    2281                 :             :                         case ZTYPE_DOWN:
    2282                 :           0 :                             nType = -nType; /*  at_removed_H[] contains bonds TO the center, not from */
    2283                 :           0 :                             z = len2( at_coord[nNumExplictAttachments] );
    2284                 :             :                             /*
    2285                 :             :                             z = sqrt( at_coord[nNumExplictAttachments][0]*at_coord[nNumExplictAttachments][0]
    2286                 :             :                                     + at_coord[nNumExplictAttachments][1]*at_coord[nNumExplictAttachments][1] );
    2287                 :             :                             */
    2288         [ #  # ]:           0 :                             if (nType == ZTYPE_DOWN)
    2289                 :             :                             {
    2290                 :           0 :                                 z = -z;
    2291                 :             :                             }
    2292                 :             :                             /*  no break; here */
    2293                 :             :                         case ZTYPE_3D:
    2294                 :           0 :                             num_z++;
    2295                 :             :                     }
    2296                 :           0 :                     at_coord[nNumExplictAttachments][2] = z;
    2297                 :             :                 }
    2298                 :           0 :                 break;
    2299                 :           0 :             case 1:
    2300         [ #  # ]:           0 :                 for (j = 0; j < at[cur_at].valence; j++, nNumExplictAttachments++)
    2301                 :             :                 {
    2302                 :           0 :                     next = at[cur_at].neighbor[j];
    2303                 :           0 :                     at_coord[nNumExplictAttachments][0] = at[next].x - at[cur_at].x;
    2304                 :           0 :                     at_coord[nNumExplictAttachments][1] = at[next].y - at[cur_at].y;
    2305                 :           0 :                     nSbNeighOrigAtNumb[nNumExplictAttachments] = at[next].orig_at_number;
    2306                 :             : 
    2307                 :           0 :                     z = get_z_coord( at, cur_at, j /*neighbor #*/, &nType, ( bPointedEdgeStereo & PES_BIT_POINT_EDGE_STEREO ) );
    2308   [ #  #  #  # ]:           0 :                     switch (nType)
    2309                 :             :                     {
    2310                 :           0 :                         case ZTYPE_EITHER:
    2311                 :           0 :                             num_either_single++; /*  bond in "Either" direction. */
    2312                 :           0 :                             break;
    2313                 :           0 :                         case ZTYPE_UP:
    2314                 :             :                         case ZTYPE_DOWN:
    2315                 :           0 :                             z = len2( at_coord[nNumExplictAttachments] );
    2316                 :             :                             /*
    2317                 :             :                             z = sqrt( at_coord[nNumExplictAttachments][0]*at_coord[nNumExplictAttachments][0]
    2318                 :             :                                     + at_coord[nNumExplictAttachments][1]*at_coord[nNumExplictAttachments][1] );
    2319                 :             :                             */
    2320         [ #  # ]:           0 :                             if (nType == ZTYPE_DOWN)
    2321                 :             :                             {
    2322                 :           0 :                                 z = -z;
    2323                 :             :                             }
    2324                 :             :                             /*  no break; here */
    2325                 :             :                         case ZTYPE_3D:
    2326                 :           0 :                             num_z++;
    2327                 :             :                     }
    2328                 :           0 :                     at_coord[nNumExplictAttachments][2] = z;
    2329                 :             :                 }
    2330                 :           0 :                 break;
    2331                 :             :         }
    2332                 :             :     }
    2333                 :             : 
    2334         [ #  # ]:           0 :     if (num_either_single)
    2335                 :             :     {
    2336                 :           0 :         bond_parity = vABParityUnknown /*AB_PARITY_UNKN*/;  /*  single bond is 'unknown' */
    2337                 :           0 :         goto exit_function;
    2338                 :             :     }
    2339                 :             : 
    2340                 :             :     /* nNumExplictAttachments is a total number of attachments, including removed explicit terminal hydrogens */
    2341         [ #  # ]:           0 :     if (nNumExplictAttachments == 2)
    2342                 :             :     {
    2343                 :             :         /*  create coordinates of the implicit hydrogen (or a fictitious atom in case of ==N-X ), */
    2344                 :             :         /*  coord[2][], attached to the cur_at. */
    2345         [ #  # ]:           0 :         for (j = 0; j < 3; j++)
    2346                 :             :         {
    2347                 :           0 :             at_coord[2][j] = -( at_coord[0][j] + at_coord[1][j] );
    2348                 :             :         }
    2349                 :           0 :         nSbNeighOrigAtNumb[nNumExplictAttachments] = 0; /* implicit H or lone pair */
    2350                 :             :     }
    2351         [ #  # ]:           0 :     for (j = 0; j < 3; j++)
    2352                 :             :     {
    2353                 :           0 :         tmp[j] = len3( at_coord[j] );
    2354                 :             :     }
    2355   [ #  #  #  #  :           0 :     min_tmp = inchi_min( tmp[0], inchi_min( tmp[1], tmp[2] ) );
                   #  # ]
    2356   [ #  #  #  #  :           0 :     max_tmp = inchi_max( tmp[0], inchi_max( tmp[1], tmp[2] ) );
                   #  # ]
    2357   [ #  #  #  # ]:           0 :     if (min_tmp < MIN_BOND_LEN || min_tmp < MIN_SINE*max_tmp)
    2358                 :             :     {
    2359                 :             :         /*  all bonds or some of bonds are too short */
    2360         [ #  # ]:           0 :         if (at[cur_at].sb_parity[0])
    2361                 :             :         {
    2362                 :             :             /* use bond psrity; the reconciliation in ReconcileAllCmlBondParities()
    2363                 :             :             * has made all ways to calculate parity produce same result
    2364                 :             :             */
    2365                 :           0 :             bond_parity = GetHalfStereobond0DParity( at, cur_at, nSbNeighOrigAtNumb,
    2366                 :             :                                                      nNumExplictAttachments, bond_parity, FlagSB_0D );
    2367                 :             :         }
    2368                 :             : 
    2369                 :           0 :         goto exit_function;
    2370                 :             :     }
    2371                 :             :     /*  normalize lengths to 1 */
    2372         [ #  # ]:           0 :     for (j = 0; j < 3; j++)
    2373                 :             :     {
    2374                 :           0 :         mult3( at_coord[j], 1.0 / tmp[j], at_coord[j] );
    2375                 :             :     }
    2376                 :             : 
    2377                 :             :     /*  find projections of at_coord vector differences on the plane containing their arrowhead ends */
    2378         [ #  # ]:           0 :     for (j = 0; j < 3; j++)
    2379                 :             :     {
    2380                 :             :         /*  pnt[0..2] = {0-1, 1-2, 2-0} */
    2381                 :           0 :         tmp[j] = len3((double *)diff3( at_coord[j], at_coord[( j + 1 ) % 3], pnt[j] ) ); /* djb-rwth: cast operator added for compatibility */
    2382         [ #  # ]:           0 :         if (tmp[j] < MIN_SINE)
    2383                 :             :         {
    2384                 :           0 :             goto exit_function; /*  angle #i-cur_at-#j is too small */
    2385                 :             :         }
    2386                 :           0 :         mult3( pnt[j], 1.0 / tmp[j], pnt[j] ); /* 2003-10-06 */
    2387                 :             :     }
    2388                 :             :     /*  find pnt[p2], a vector perpendicular to the plane, and its length tmp[p2] */
    2389                 :             :     /*  replace previous pnt[p2], tmp[p2] with new values; the old values do not have any additional */
    2390                 :             :     /*  information because pnt[p0]+pnt[p1]+pnt[p2]=0 */
    2391                 :             :     /*  10-6-2003: a cross-product of one pair pnt[j], pnt[(j+1)%3] can be very small. Find the larges one */
    2392                 :           0 :     tmp1 = len3((double *)cross_prod3( pnt[0], pnt[1], temp ) ); /* djb-rwth: cast operator added for compatibility */
    2393         [ #  # ]:           0 :     for (j = 1, k = 0; j < 3; j++)
    2394                 :             :     {
    2395                 :           0 :         tmp2 = len3((double *)cross_prod3( pnt[j], pnt[( j + 1 ) % 3], temp ) ); /* djb-rwth: cast operator added for compatibility */
    2396         [ #  # ]:           0 :         if (tmp2 > tmp1)
    2397                 :             :         {
    2398                 :           0 :             tmp1 = tmp2;
    2399                 :           0 :             k = j;
    2400                 :             :         }
    2401                 :             :     }
    2402                 :             :     /* previously p0=0, p1=1, p2=2 */
    2403                 :           0 :     p0 = k;
    2404                 :           0 :     p1 = ( k + 1 ) % 3;
    2405                 :           0 :     p2 = ( k + 2 ) % 3;
    2406                 :           0 :     tmp[p2] = len3((double *)cross_prod3( pnt[p0], pnt[p1], pnt[p2] ) ); /* djb-rwth: cast operator added for compatibility */
    2407         [ #  # ]:           0 :     if (tmp[p2] < MIN_SINE*tmp[p0] * tmp[p1])
    2408                 :             :     {
    2409                 :           0 :         goto exit_function; /*  pnt[p0] is almost colinear to pnt[p1] */
    2410                 :             :     }
    2411                 :             :     /*  new basis: pnt[p0], pnt[p1], pnt[p2]; set z-coord sign and make abs(pnt[p2]) = 1 */
    2412         [ #  # ]:           0 :     mult3( pnt[p2], ( pnt[p2][2] > 0.0 ? 1.0 : -1.0 ) / tmp[p2], pnt[p2] ); /*  unit vector in the new z-axis direction */
    2413                 :             : 
    2414                 :           0 :     min_tmp = dot_prod3( at_coord[0], pnt[p2] ); /*  non-planarity measure (sine): hight of at_coord[] pyramid */
    2415                 :           0 :     mult3( pnt[p2], min_tmp, pnt[p0] ); /*  vector height of the pyramid, ideally 0 */
    2416                 :             :     /*  find new pnt[p0] = projection of at_coord[p0] on plane orthogonal to pnt[p2] */
    2417                 :           0 :     tmp[p0] = len3((double *)diff3( at_coord[0], pnt[p0], pnt[p0] ) ); /* djb-rwth: cast operator added for compatibility */
    2418                 :           0 :     mult3( pnt[p0], 1.0 / tmp[p0], pnt[p0] );  /*  new x axis basis vector */
    2419                 :           0 :     cross_prod3( pnt[p2], pnt[p0], pnt[p1] ); /*  new y axis basis vector */
    2420                 :             :     /*  find at_coord in the new basis of {pnt[p0], pnt[p1], pnt[p2]} */
    2421         [ #  # ]:           0 :     for (j = 0; j < 3; j++)
    2422                 :             :     {
    2423                 :             :         /* copy3(at_coord[j], temp);-- djb-rwth: removing copy3 function */
    2424                 :           0 :         memcpy(temp, at_coord[j], sizeof(at_coord[j]));
    2425         [ #  # ]:           0 :         for (k = 0; k < 3; k++)
    2426                 :             :         {
    2427                 :           0 :             at_coord[j][k] = dot_prod3( temp, pnt[( k + p0 ) % 3] );
    2428                 :             :         }
    2429                 :             :         /*  new xy plane projection length */
    2430                 :           0 :         tmp[j] = sqrt( at_coord[j][0] * at_coord[j][0] + at_coord[j][1] * at_coord[j][1] );
    2431                 :             :         /*  make new xy plane projection length = 1 */
    2432                 :           0 :         mult3( at_coord[j], 1.0 / tmp[j], at_coord[j] );
    2433                 :             :     }
    2434                 :             : 
    2435                 :           0 :     s = fabs( at_coord[1][0] * at_coord[2][1] - at_coord[1][1] * at_coord[2][0] ); /*  1-2 sine */
    2436                 :           0 :     c = at_coord[1][0] * at_coord[2][0] + at_coord[1][1] * at_coord[2][1];   /*  1-2 cosine */
    2437   [ #  #  #  # ]:           0 :     if (s < MIN_SINE && c > 0.5)
    2438                 :             :     {
    2439                 :           0 :         goto exit_function; /*  bonds to neigh. 1 and 2 have almost same direction; relative angles are undefined */
    2440                 :             :     }
    2441                 :           0 :     c = at_coord[0][0]; /*  cosine of the angle between new Ox axis and a bond to the neighbor 0. Should be 1 */
    2442                 :           0 :     s = at_coord[0][1]; /*  sine. Should be 0 */
    2443                 :             :     /*  turn vectors so that vector #1 (at_coord[0]) becomes {1, 0} */
    2444         [ #  # ]:           0 :     for (j = 0; j < MAX_NUM_STEREO_BOND_NEIGH; j++)
    2445                 :             :     {
    2446                 :           0 :         tmp1 = c*at_coord[j][0] + s*at_coord[j][1];
    2447                 :           0 :         tmp2 = -s*at_coord[j][0] + c*at_coord[j][1];
    2448                 :           0 :         at_coord[j][0] = tmp1;
    2449                 :           0 :         at_coord[j][1] = tmp2;
    2450                 :             :     }
    2451                 :             :     /*  counterclockwise angles from the direction to neigh 0 to to directions to neighbors 1 and 2: */
    2452                 :           0 :     tmp1 = atan2( at_coord[1][1], at_coord[1][0] ); /*  range -pi and +pi */
    2453                 :           0 :     tmp2 = atan2( at_coord[2][1], at_coord[2][0] );
    2454         [ #  # ]:           0 :     if (tmp1 < 0.0)
    2455                 :             :     {
    2456                 :           0 :         tmp1 += two_pi; /*  range 0 to 2*pi */
    2457                 :             :     }
    2458         [ #  # ]:           0 :     if (tmp2 < 0.0)
    2459                 :             :     {
    2460                 :           0 :         tmp2 += two_pi;
    2461                 :             :     }
    2462                 :             :     /*-----------------------------------
    2463                 :             :                         Example
    2464                 :             :       1 \               case tmp1 < tmp2
    2465                 :             :          \              parity is odd
    2466                 :             :           \             (counterclockwise)
    2467                 :             :            A------- 0
    2468                 :             :           /
    2469                 :             :          /
    2470                 :             :       2 /
    2471                 :             : 
    2472                 :             :     ------------------------------------*/
    2473         [ #  # ]:           0 :     bond_parity = 2 - ( tmp1 < tmp2 );
    2474         [ #  # ]:           0 :     for (j = 0; j < 3; j++)
    2475                 :             :     {
    2476         [ #  # ]:           0 :         if (z_dir)
    2477         [ #  # ]:           0 :             z_dir[j] = (S_CHAR) ( pnt[p2][j] >= 0.0 ? floor( 0.5 + 100.0 * pnt[p2][j] ) :
    2478                 :           0 :                                                -floor( 0.5 - 100.0 * pnt[p2][j] ) ); /*  abs(z_dir) = 100 */
    2479                 :             :     }
    2480                 :             :     /*  check for ambiguity */
    2481         [ #  # ]:           0 :     if (nNumExplictAttachments > 2)
    2482                 :             :     {
    2483         [ #  # ]:           0 :         min_tmp = inchi_min( tmp1, tmp2 );
    2484         [ #  # ]:           0 :         max_tmp = inchi_max( tmp1, tmp2 );
    2485   [ #  #  #  #  :           0 :         if (min_tmp > one_pi - MIN_SINE || max_tmp < one_pi + MIN_SINE || max_tmp - min_tmp > one_pi - MIN_SINE)
                   #  # ]
    2486                 :             :         {
    2487                 :           0 :             at[cur_at].bAmbiguousStereo |= AMBIGUOUS_STEREO;
    2488                 :             :         }
    2489                 :             :         else /* 3D ambiguity 8-28-2002 */
    2490                 :             :         {
    2491         [ #  # ]:           0 :             if (fabs( at_coord[0][2] ) > MAX_SINE)
    2492                 :             :             { /*  all fabs(at_coord[j][2] (j=0..2) must be equal */
    2493                 :           0 :                 at[cur_at].bAmbiguousStereo |= AMBIGUOUS_STEREO;
    2494                 :             :             }
    2495                 :             :         }
    2496                 :             :     }
    2497                 :             :     else
    2498                 :             :     {
    2499         [ #  # ]:           0 :         if (nNumExplictAttachments == 2)
    2500                 :             :         {  /* 10-6-2003: added */
    2501                 :           0 :             min_tmp = fabs( tmp1 - one_pi );
    2502         [ #  # ]:           0 :             if (min_tmp < MIN_SINE)
    2503                 :             :             {
    2504                 :           0 :                 bond_parity = AB_PARITY_UNDF; /* consider as undefined 10-6-2003 */
    2505                 :             :             }
    2506                 :             :             else
    2507                 :             :             {
    2508         [ #  # ]:           0 :                 if (min_tmp < MIN_ANGLE_DBOND)
    2509                 :             :                 {
    2510                 :           0 :                     at[cur_at].bAmbiguousStereo |= AMBIGUOUS_STEREO;
    2511                 :             :                 }
    2512                 :             :             }
    2513                 :             :         }
    2514                 :             :     }
    2515                 :             : 
    2516                 :             :     /*  for 3 neighbors moving implicit H to the index=0 from index=2 position */
    2517                 :             :     /*  can be done in 2 transpositions and does not change atom's parity */
    2518                 :             : 
    2519                 :           0 : exit_function:
    2520                 :             : 
    2521   [ #  #  #  #  :           0 :     if (num_H > 1 && bond_parity > 0 && !( bond_parity & AB_PARITY_0D ) /*&& PARITY_WELL_DEF(bond_parity)*/)
                   #  # ]
    2522                 :             :     {
    2523                 :             :         /*
    2524                 :             :          * stereo only if isotopes are counted.             Do not inverse
    2525                 :             :          * Examples:                                        sign for this:
    2526                 :             :          *     H                            D
    2527                 :             :          *    /                            /                    H
    2528                 :             :          * ==C                      or  ==CH                   /
    2529                 :             :          *    \                                             ==N  (bValence3=1)
    2530                 :             :          *     D
    2531                 :             :          * two explicit         one explicit H isotope (D),
    2532                 :             :          * isotopic H atoms     one implicit H
    2533                 :             :          */
    2534                 :           0 :         bond_parity = -bond_parity; /*  refers to isotopically substituted structure only */
    2535                 :             :     }
    2536                 :             : 
    2537                 :           0 :     return bond_parity;
    2538                 :             : }
    2539                 :             : 
    2540                 :             : 
    2541                 :             : /****************************************************************************/
    2542                 :           0 : int save_a_stereo_bond( int z_prod,
    2543                 :             :                         int result_action,
    2544                 :             :                         int at1,
    2545                 :             :                         int ord1,
    2546                 :             :                         AT_NUMB *stereo_bond_neighbor1,
    2547                 :             :                         S_CHAR *stereo_bond_ord1,
    2548                 :             :                         S_CHAR *stereo_bond_z_prod1,
    2549                 :             :                         S_CHAR *stereo_bond_parity1,
    2550                 :             :                         int at2,
    2551                 :             :                         int ord2,
    2552                 :             :                         AT_NUMB *stereo_bond_neighbor2,
    2553                 :             :                         S_CHAR *stereo_bond_ord2,
    2554                 :             :                         S_CHAR *stereo_bond_z_prod2,
    2555                 :             :                         S_CHAR *stereo_bond_parity2 )
    2556                 :             : {
    2557                 :             :     int i1, i2;
    2558                 :             : 
    2559   [ #  #  #  # ]:           0 :     for (i1 = 0; i1 < MAX_NUM_STEREO_BONDS && stereo_bond_neighbor1[i1]; i1++)
    2560                 :             :     {
    2561                 :             :         ;
    2562                 :             :     }
    2563   [ #  #  #  # ]:           0 :     for (i2 = 0; i2 < MAX_NUM_STEREO_BONDS && stereo_bond_neighbor2[i2]; i2++)
    2564                 :             :     {
    2565                 :             :         ;
    2566                 :             :     }
    2567                 :             : 
    2568   [ #  #  #  # ]:           0 :     if (i1 == MAX_NUM_STEREO_BONDS || i2 == MAX_NUM_STEREO_BONDS)
    2569                 :             :     {
    2570                 :           0 :         return 0;
    2571                 :             :     }
    2572                 :             : 
    2573                 :           0 :     stereo_bond_parity1[i1] =
    2574                 :           0 :         stereo_bond_parity2[i2] = result_action;
    2575                 :             : 
    2576                 :           0 :     stereo_bond_neighbor1[i1] = (AT_NUMB) ( at2 + 1 );
    2577                 :           0 :     stereo_bond_ord1[i1] = (S_CHAR) ord1;
    2578                 :           0 :     stereo_bond_neighbor2[i2] = (AT_NUMB) ( at1 + 1 );
    2579                 :           0 :     stereo_bond_ord2[i2] = (S_CHAR) ord2;
    2580                 :           0 :     stereo_bond_z_prod1[i1] =
    2581                 :           0 :         stereo_bond_z_prod2[i2] = (S_CHAR) z_prod;
    2582                 :             : 
    2583                 :           0 :     return 1;
    2584                 :             : }
    2585                 :             : 
    2586                 :             : 
    2587                 :             : /****************************************************************************/
    2588                 :         206 : int get_allowed_stereo_bond_type( int bond_type )
    2589                 :             : {
    2590                 :             : #if (ALLOW_TAUT_ATTACHMENTS_TO_STEREO_BONDS == 0 )
    2591                 :             :     if (( bond_type & ~BOND_MARK_ALL ) == BOND_TAUTOM)
    2592                 :             :     {
    2593                 :             :         return 0; /*  no tautomer bonds allowed */
    2594                 :             :     }
    2595                 :             :     else
    2596                 :             : #endif
    2597                 :             : #if ( EXCL_ALL_AROM_BOND_PARITY  == 1 )  /* { */
    2598                 :             :     /*  a stereo bond cannot belong to an aromatic atom */
    2599                 :             :         if (( bond_type &= ~BOND_MARK_ALL ) == BOND_ALTERN)
    2600                 :             :         {
    2601                 :             :             return 0;
    2602                 :             :         }
    2603                 :             : #else  /* } { */
    2604                 :             : #if ( ADD_6MEMB_AROM_BOND_PARITY == 1 )
    2605                 :             :     /*  accept any aromatic bond as a stereo bond */
    2606         [ +  + ]:         206 :     if (( bond_type &= ~BOND_MARK_ALL ) == BOND_ALTERN)
    2607                 :             : #else
    2608                 :             :     /*  accept only aromatic bonds in non-6-member rings */
    2609                 :             :     if (( bond_type &= ~BOND_MARK_ALL ) == BOND_ALTERN) )
    2610                 :             : #endif
    2611                 :             :     {
    2612                 :          96 :         return BOND_ALTERN;
    2613                 :             :     }
    2614                 :             : #endif  /* } */
    2615                 :             :     else
    2616                 :             :     {
    2617                 :             :         /*  at this point BOND_MARK_ALL bits have been removed from bond_type */
    2618   [ +  +  +  - ]:         110 :         if (bond_type == BOND_DOUBLE || bond_type == BOND_SINGLE)
    2619                 :             :         {
    2620                 :         110 :             return bond_type;
    2621                 :             :         }
    2622                 :             : #if (ALLOW_TAUT_ATTACHMENTS_TO_STEREO_BONDS == 1 )
    2623                 :             :         else
    2624                 :             :         {
    2625         [ #  # ]:           0 :             if (bond_type == BOND_TAUTOM)
    2626                 :             :             {
    2627                 :           0 :                 return BOND_TAUTOM;
    2628                 :             :             }
    2629                 :             :         }
    2630                 :             : #endif
    2631                 :             :     }
    2632                 :             : 
    2633                 :           0 :     return 0; /*  wrong bond type */
    2634                 :             : }
    2635                 :             : 
    2636                 :             : 
    2637                 :             : /****************************************************************************/
    2638                 :         227 : int can_be_a_stereo_bond_with_isotopic_H( inp_ATOM *at,
    2639                 :             :                                           int cur_at,
    2640                 :             :                                           INCHI_MODE nMode )
    2641                 :             : {
    2642                 :             :     int i, j, next_at, num_stereo_bonds, bFound;
    2643                 :             :     int bond_type, num_2s, num_alt;
    2644                 :             :     int num_2s_next, num_alt_next, num_wrong_bonds_1, num_wrong_bonds_2;
    2645                 :             : #if ( N_V_STEREOBONDS == 1 )
    2646                 :             :     int n2sh, num_2s_hetero[2], num_2s_hetero_next[2], next_next_at, type_N, type_N_next;
    2647                 :             : #endif
    2648                 :             : 
    2649         [ +  + ]:         227 :     if (MAX_NUM_STEREO_BOND_NEIGH < at[cur_at].valence + at[cur_at].num_H ||
    2650         [ +  + ]:         222 :          MIN_NUM_STEREO_BOND_NEIGH > at[cur_at].valence + at[cur_at].num_H)
    2651                 :             :     {
    2652                 :         125 :         return 0;
    2653                 :             :     }
    2654         [ +  + ]:         102 :     if (!bCanAtomHaveAStereoBond( at[cur_at].elname, at[cur_at].charge, at[cur_at].radical ))
    2655                 :             :     {
    2656                 :          65 :         return 0;
    2657                 :             :     }
    2658                 :             : 
    2659                 :             :     /*  Count bonds and find the second atom on the stereo bond */
    2660                 :          37 :     num_2s = num_alt = num_wrong_bonds_1 = 0;
    2661                 :             : #if ( N_V_STEREOBONDS == 1 )
    2662                 :          37 :     num_2s_hetero[0] = num_2s_hetero[1] = type_N = 0;
    2663   [ +  +  +  -  :          43 :     if (0 == at[cur_at].num_H && 0 == at[cur_at].charge && 0 == at[cur_at].radical &&
             +  -  -  + ]
    2664                 :           6 :          3 == get_endpoint_valence( at[cur_at].el_number ))
    2665                 :             :     {
    2666   [ #  #  #  # ]:           0 :         if (2 == at[cur_at].valence && 3 == at[cur_at].chem_bonds_valence)
    2667                 :             :         {
    2668                 :           0 :             type_N = 1;
    2669                 :             :         }
    2670                 :             :         else
    2671                 :             :         {
    2672   [ #  #  #  # ]:           0 :             if (3 == at[cur_at].valence && 5 == at[cur_at].chem_bonds_valence)
    2673                 :             :             {
    2674                 :           0 :                 type_N = 2; /* unfortunately includes >N# */
    2675                 :             :             }
    2676                 :             :         }
    2677                 :             :     }
    2678                 :             : #endif
    2679         [ +  + ]:         100 :     for (i = 0, num_stereo_bonds = 0; i < at[cur_at].valence; i++)
    2680                 :             :     {
    2681                 :          63 :         bFound = 0;
    2682                 :          63 :         next_at = at[cur_at].neighbor[i];
    2683                 :          63 :         bond_type = get_allowed_stereo_bond_type( (int) at[cur_at].bond_type[i] );
    2684         [ +  + ]:          63 :         if (bond_type == BOND_ALTERN)
    2685                 :             :         {
    2686                 :          24 :             num_alt++;
    2687   [ +  +  +  - ]:          24 :             if (cur_at > next_at && !( nMode & CMODE_NO_ALT_SBONDS ))
    2688                 :             :             {
    2689                 :          12 :                 bFound = 1;
    2690                 :             :             }
    2691                 :             :         }
    2692                 :             :         else
    2693                 :             :         {
    2694         [ +  + ]:          39 :             if (bond_type == BOND_DOUBLE)
    2695                 :             :             {
    2696                 :           8 :                 num_2s++;
    2697                 :             : #if ( N_V_STEREOBONDS == 1 )
    2698         [ -  + ]:           8 :                 if (0 <= ( n2sh = bIsSuitableHeteroInpAtom( at + next_at ) ))
    2699                 :             :                 {
    2700                 :           0 :                     num_2s_hetero[n2sh] ++; /* n2sh=0 -> =N- or =NH; n2sh=1 -> =O */
    2701                 :             :                 }
    2702                 :             : #endif
    2703         [ +  + ]:           8 :                 if (cur_at > next_at)
    2704                 :           4 :                     bFound = 1;
    2705                 :             :             }
    2706                 :             :             else
    2707                 :             :             {
    2708   [ -  +  -  - ]:          31 :                 if (bond_type != BOND_SINGLE && bond_type != BOND_TAUTOM)
    2709                 :             :                 {
    2710                 :           0 :                     num_wrong_bonds_1++;
    2711                 :             : #if ( ONE_BAD_SB_NEIGHBOR == 1 )
    2712   [ #  #  #  #  :           0 :                     if (num_wrong_bonds_1 > 1 || (num_wrong_bonds_1 && 2 >= at[cur_at].valence)) /* djb-rwth: addressing LLVM warning */
                   #  # ]
    2713                 :             :                     {
    2714                 :           0 :                         return 0; /* wrong bond type */
    2715                 :             :                     }
    2716                 :             :                     else
    2717                 :             :                     {
    2718                 :           0 :                         continue;
    2719                 :             :                     }
    2720                 :             : #else
    2721                 :             :                     return 0; /*  wrong bond type */
    2722                 :             : #endif
    2723                 :             :                 }
    2724                 :             :             }
    2725                 :             :         }
    2726                 :             : 
    2727         [ +  + ]:          63 :         if (bFound)
    2728                 :             :         {
    2729                 :             :             /*  check "next_at" atom on the opposite side of the bond */
    2730         [ +  - ]:          16 :             if (MAX_NUM_STEREO_BOND_NEIGH < at[next_at].valence + at[next_at].num_H ||
    2731         [ -  + ]:          16 :                  MIN_NUM_STEREO_BOND_NEIGH > at[next_at].valence + at[next_at].num_H)
    2732                 :             :             {
    2733                 :           0 :                 continue;
    2734                 :             :             }
    2735         [ -  + ]:          16 :             if (!bCanAtomHaveAStereoBond( at[next_at].elname, at[next_at].charge, at[next_at].radical ))
    2736                 :             :             {
    2737                 :           0 :                 continue;
    2738                 :             :             }
    2739                 :             :             /*  next atom neighbors */
    2740                 :          16 :             num_2s_next = num_alt_next = num_wrong_bonds_2 = 0;
    2741                 :             : #if ( N_V_STEREOBONDS == 1 )
    2742                 :          16 :             num_2s_hetero_next[0] = num_2s_hetero_next[1] = type_N_next = 0;
    2743   [ +  +  +  -  :          24 :             if (0 == at[next_at].num_H && 0 == at[next_at].charge && 0 == at[next_at].radical &&
             +  -  -  + ]
    2744                 :           8 :                  3 == get_endpoint_valence( at[next_at].el_number ))
    2745                 :             :             {
    2746   [ #  #  #  # ]:           0 :                 if (2 == at[next_at].valence && 3 == at[next_at].chem_bonds_valence)
    2747                 :             :                 {
    2748                 :           0 :                     type_N_next = 1; /* -N= */
    2749                 :             :                 }
    2750                 :             :                 else
    2751                 :             :                 {
    2752   [ #  #  #  # ]:           0 :                     if (3 == at[next_at].valence && 5 == at[next_at].chem_bonds_valence)
    2753                 :             :                     {
    2754                 :           0 :                         type_N_next = 2; /* unfortunately includes >N# */
    2755                 :             :                     }
    2756                 :             :                 }
    2757                 :             :             }
    2758                 :             : #endif
    2759         [ +  + ]:          56 :             for (j = 0; j < at[next_at].valence; j++)
    2760                 :             :             {
    2761                 :          40 :                 bond_type = get_allowed_stereo_bond_type( (int) at[next_at].bond_type[j] );
    2762         [ +  + ]:          40 :                 if (bond_type == BOND_ALTERN)
    2763                 :             :                 {
    2764                 :          24 :                     num_alt_next++;
    2765                 :             :                 }
    2766                 :             :                 else
    2767                 :             :                 {
    2768         [ +  + ]:          16 :                     if (bond_type == BOND_DOUBLE)
    2769                 :             :                     {
    2770                 :           4 :                         num_2s_next++;
    2771                 :             : #if ( N_V_STEREOBONDS == 1 )
    2772                 :           4 :                         next_next_at = at[next_at].neighbor[j];
    2773         [ -  + ]:           4 :                         if (0 <= ( n2sh = bIsSuitableHeteroInpAtom( at + next_next_at ) ))
    2774                 :             :                         {
    2775                 :           0 :                             num_2s_hetero_next[n2sh] ++; /* n2sh=0 -> =N- or =NH; n2sh=1 -> =O */
    2776                 :             :                         }
    2777                 :             : #endif
    2778                 :             :                     }
    2779                 :             :                     else
    2780                 :             :                     {
    2781   [ -  +  -  - ]:          12 :                         if (bond_type != BOND_SINGLE && bond_type != BOND_TAUTOM)
    2782                 :             :                         {
    2783                 :           0 :                             num_wrong_bonds_2++;
    2784                 :             : #if ( ONE_BAD_SB_NEIGHBOR == 1 )
    2785   [ #  #  #  #  :           0 :                             if (num_wrong_bonds_1 > 1 || (num_wrong_bonds_1 && 2 >= at[cur_at].valence)) /* djb-rwth: addressing LLVM warning */
                   #  # ]
    2786                 :             :                             {
    2787                 :             :                                 break; /* wrong bond type */
    2788                 :             :                             }
    2789                 :             :                             else
    2790                 :             :                             {
    2791                 :           0 :                                 continue;
    2792                 :             :                             }
    2793                 :             : #else
    2794                 :             :                             break; /*  wrong bond type */
    2795                 :             : #endif
    2796                 :             :                         }
    2797                 :             :                     }
    2798                 :             :                 }
    2799                 :             :             }
    2800                 :             :             /* figure out whether the at[cur_at]--at[next_at] bond may not be stereogenic */
    2801                 :             : 
    2802                 :             : #if ( N_V_STEREOBONDS == 1 )
    2803   [ -  +  -  - ]:          16 :             if (3 == ( type_N | type_N_next ) &&
    2804   [ #  #  #  # ]:           0 :                 ( (2 == type_N && !bIsOxide( at, cur_at )) ||
    2805         [ #  # ]:           0 :                     (2 == type_N_next && !bIsOxide( at, next_at )) )) /* djb-rwth: addressing LLVM warnings */
    2806                 :             :             {
    2807                 :           0 :                 bFound = 0;
    2808                 :             :             }
    2809                 :             :             else
    2810                 :             : #endif
    2811                 :             :             {
    2812         [ +  - ]:          16 :                 if (j < at[next_at].valence ||                  /* at[next_at] has a wrong bond type*/
    2813         [ -  + ]:          16 :                     ( num_alt_next > 0 ) + ( num_2s_next > 0 ) != 1     /* only one type of stereogenic bond permitted */
    2814                 :             :                        )
    2815                 :             :                 {
    2816                 :           0 :                     bFound = 0;
    2817                 :             :                 }
    2818                 :             :                 else
    2819                 :             :                 {
    2820         [ -  + ]:          16 :                     if (2 < num_2s_next)
    2821                 :             :                     {
    2822                 :           0 :                         bFound = 0;
    2823                 :             :                     }
    2824                 :             :                     else
    2825                 :             :                     {
    2826         [ -  + ]:          16 :                         if (2 == num_2s_next)
    2827                 :             :                         {
    2828         [ #  # ]:           0 :                             if (2 == at[next_at].valence)
    2829                 :             :                             {
    2830                 :             :                                 ; /* only one double bond permitted except cumulenes */
    2831                 :             : #if ( N_V_STEREOBONDS == 1 )
    2832                 :             :                             }
    2833                 :             :                             else
    2834                 :             :                             {
    2835         [ #  # ]:           0 :                                 if (1 == ( num_2s_hetero_next[0] | num_2s_hetero_next[1] ) &&
    2836         [ #  # ]:           0 :                                         3 == at[next_at].valence + at[next_at].num_H &&
    2837   [ #  #  #  # ]:           0 :                                         5 == at[next_at].chem_bonds_valence + at[next_at].num_H &&
    2838         [ #  # ]:           0 :                                         3 == get_endpoint_valence( at[next_at].el_number ) &&
    2839         [ #  # ]:           0 :                                         ( !type_N || bIsOxide( at, next_at ) ))
    2840                 :             :                                 {
    2841                 :             :                                     ; /*
    2842                 :             :                                        *   found:
    2843                 :             :                                        *
    2844                 :             :                                        *    \      /    \      /    \      /
    2845                 :             :                                        *     \    /      \    /      \    /
    2846                 :             :                                        *      N==C   or   N==C   or   N==N
    2847                 :             :                                        *    //    \     //    \     //    \
    2848                 :             :                                        *   O  ^    \   N  ^    \   O  ^    \
    2849                 :             :                                        *      |           |           |
    2850                 :             :                                        *      |           |           |
    2851                 :             :                                        *      at[next_at] at[next_at] at[next_at]
    2852                 :             :                                        */
    2853                 :             : #endif
    2854                 :             :                                 }
    2855                 :             :                                 else
    2856                 :             :                                 {
    2857                 :           0 :                                     bFound = 0;
    2858                 :             :                                 }
    2859                 :             :                             }
    2860                 :             :                         }
    2861                 :             :                     }
    2862                 :             :                 }
    2863                 :             :             }
    2864                 :             :         }
    2865         [ +  + ]:          63 :         if (bFound)
    2866                 :             :         {
    2867                 :          16 :             num_stereo_bonds++;
    2868                 :             :         }
    2869                 :             :     }
    2870                 :             : 
    2871   [ +  +  +  + ]:          37 :     if (( num_alt > 0 ) + ( num_2s > 0 ) != 1 || !num_stereo_bonds)
    2872                 :             :     {
    2873                 :          23 :         return 0;
    2874                 :             :     }
    2875                 :             : 
    2876         [ -  + ]:          14 :     if (num_2s > 1)
    2877                 :             :     {
    2878                 :             : #if ( N_V_STEREOBONDS == 1 )
    2879         [ #  # ]:           0 :         if (2 == num_2s &&
    2880         [ #  # ]:           0 :              1 == ( num_2s_hetero[0] | num_2s_hetero[1] ) &&
    2881         [ #  # ]:           0 :              3 == at[cur_at].valence + at[cur_at].num_H &&
    2882   [ #  #  #  # ]:           0 :              5 == at[cur_at].chem_bonds_valence + at[cur_at].num_H &&
    2883                 :           0 :              3 == get_endpoint_valence( at[cur_at].el_number ))
    2884                 :             :         {
    2885                 :             :             ;
    2886                 :             :         }
    2887                 :             :         else
    2888                 :             :         {
    2889                 :           0 :             return 0;
    2890                 :             :         }
    2891                 :             : #else
    2892                 :             :         return 0;
    2893                 :             : #endif
    2894                 :             :     }
    2895                 :             : 
    2896                 :          14 :     return num_stereo_bonds;
    2897                 :             : }
    2898                 :             : 
    2899                 :             : 
    2900                 :             : /****************************************************************************/
    2901                 :           0 : int half_stereo_bond_action( int nParity,
    2902                 :             :                              int bUnknown,
    2903                 :             :                              int bIsotopic,
    2904                 :             :                              int vABParityUnknown )
    2905                 :             : {
    2906                 :             : #define AB_NEGATIVE 0x10
    2907                 :             : #define AB_UNKNOWN  0x20
    2908                 :             :     int nAction;
    2909                 :             : 
    2910         [ #  # ]:           0 :     if (nParity == AB_PARITY_NONE)
    2911                 :             :     {
    2912                 :           0 :         return AB_PARITY_NONE;
    2913                 :             :     }
    2914                 :             : 
    2915                 :             :     /*  Unknown (type 1) in the parity value may come from the 'Either' single bond only */
    2916                 :             :     /*  Treat it as a known single bond geometry and unknown (Either) double bond */
    2917         [ #  # ]:           0 :     if (nParity == vABParityUnknown /*AB_PARITY_UNKN*/)
    2918                 :             :     {
    2919                 :           0 :         nParity = AB_PARITY_ODD | AB_UNKNOWN;
    2920                 :             :     }
    2921         [ #  # ]:           0 :     if (nParity == -vABParityUnknown /*AB_PARITY_UNKN*/)
    2922                 :             :     {
    2923                 :           0 :         nParity = AB_PARITY_ODD | AB_UNKNOWN | AB_NEGATIVE;
    2924                 :             :     }
    2925                 :             : 
    2926                 :             :     /*  make positive, replace AB_PARITY_EVEN with AB_PARITY_ODD  */
    2927         [ #  # ]:           0 :     if (nParity < 0)
    2928                 :             :     {
    2929         [ #  # ]:           0 :         nParity = ( ( nParity == -AB_PARITY_EVEN ) ? AB_PARITY_ODD : ( -nParity ) ) | AB_NEGATIVE;
    2930                 :             :     }
    2931                 :             :     else
    2932                 :             :     {
    2933         [ #  # ]:           0 :         if (nParity == AB_PARITY_EVEN)
    2934                 :             :         {
    2935                 :           0 :             nParity = AB_PARITY_ODD;
    2936                 :             :         }
    2937                 :             :     }
    2938                 :             : 
    2939                 :             :     /*  Unknown (type 2): was detected in the double bond attribute */
    2940                 :             :     /*  (this 'unknown' came from 'Either' double bond) */
    2941                 :             :     /*  Treat both unknowns in the same way */
    2942         [ #  # ]:           0 :     if (bUnknown)
    2943                 :             :     {
    2944                 :           0 :         nParity |= AB_UNKNOWN;
    2945                 :             :     }
    2946                 :             : 
    2947         [ #  # ]:           0 :     if (bIsotopic)
    2948                 :             :     {
    2949   [ #  #  #  #  :           0 :         switch (nParity)
                      # ]
    2950                 :             :         {
    2951                 :           0 :             case AB_PARITY_ODD:
    2952                 :             :             case AB_PARITY_ODD | AB_NEGATIVE:
    2953                 :           0 :                 nAction = AB_PARITY_CALC;
    2954                 :           0 :                 break;
    2955                 :           0 :             case AB_PARITY_ODD | AB_UNKNOWN:
    2956                 :             :             case AB_PARITY_UNDF | AB_UNKNOWN:
    2957                 :             :             case AB_PARITY_ODD | AB_UNKNOWN | AB_NEGATIVE:
    2958                 :             :             case AB_PARITY_UNDF | AB_UNKNOWN | AB_NEGATIVE:
    2959                 :           0 :                 nAction = vABParityUnknown /*AB_PARITY_UNKN*/;
    2960                 :           0 :                 break;
    2961                 :           0 :             case AB_PARITY_IISO:
    2962                 :             :             case AB_PARITY_IISO | AB_UNKNOWN:
    2963                 :           0 :                 nAction = AB_PARITY_NONE;
    2964                 :           0 :                 break;
    2965                 :           0 :             case AB_PARITY_UNDF:
    2966                 :             :             case AB_PARITY_UNDF | AB_NEGATIVE:
    2967                 :           0 :                 nAction = AB_PARITY_UNDF;
    2968                 :           0 :                 break;
    2969                 :           0 :             default:
    2970                 :           0 :                 nAction = -1; /*  program error */
    2971                 :             :         }
    2972                 :             :     }
    2973                 :             :     else
    2974                 :             :     {
    2975                 :             :      /*  Non-isotopic */
    2976   [ #  #  #  #  :           0 :         switch (nParity)
                      # ]
    2977                 :             :         {
    2978                 :           0 :             case AB_PARITY_ODD:
    2979                 :           0 :                 nAction = AB_PARITY_CALC;
    2980                 :           0 :                 break;
    2981                 :           0 :             case AB_PARITY_ODD | AB_UNKNOWN:
    2982                 :             :             case AB_PARITY_UNDF | AB_UNKNOWN:
    2983                 :           0 :                 nAction = vABParityUnknown /*AB_PARITY_UNKN*/;
    2984                 :           0 :                 break;
    2985                 :             :             /* case AB_PARITY_ODD  | AB_UNKNOWN | AB_NEGATIVE: */
    2986                 :           0 :             case AB_PARITY_UNDF:
    2987                 :           0 :                 nAction = AB_PARITY_UNDF;
    2988                 :           0 :                 break;
    2989                 :           0 :             case AB_PARITY_ODD | AB_UNKNOWN | AB_NEGATIVE:
    2990                 :             :             case AB_PARITY_ODD | AB_NEGATIVE:
    2991                 :             :             case AB_PARITY_IISO:
    2992                 :             :             case AB_PARITY_IISO | AB_UNKNOWN:
    2993                 :             :             case AB_PARITY_UNDF | AB_NEGATIVE:
    2994                 :             :             case AB_PARITY_UNDF | AB_UNKNOWN | AB_NEGATIVE:
    2995                 :           0 :                 nAction = AB_PARITY_NONE;
    2996                 :           0 :                 break;
    2997                 :           0 :             default:
    2998                 :           0 :                 nAction = -1; /*  program error */
    2999                 :             :         }
    3000                 :             :     }
    3001                 :             : 
    3002                 :           0 :     return nAction;
    3003                 :             : #undef AB_NEGATIVE
    3004                 :             : #undef AB_UNKNOWN
    3005                 :             : }
    3006                 :             : 
    3007                 :             : 
    3008                 :             : /****************************************************************************/
    3009                 :         420 : int set_stereo_bonds_parity( sp_ATOM *out_at,
    3010                 :             :                              inp_ATOM *at,
    3011                 :             :                              int at_1,
    3012                 :             :                              inp_ATOM *at_removed_H,
    3013                 :             :                              int num_removed_H,
    3014                 :             :                              INCHI_MODE nMode, QUEUE *q,
    3015                 :             :                              AT_RANK *nAtomLevel,
    3016                 :             :                              S_CHAR *cSource,
    3017                 :             :                              AT_RANK min_sb_ring_size,
    3018                 :             :                              int bPointedEdgeStereo,
    3019                 :             :                              int vABParityUnknown )
    3020                 :             : {
    3021                 :             :     int j, k, i_next_at_1, i_next_at_2, at_2, next_at_2, num_stereo_bonds, bFound, bAllene; /* djb-rwth: removing redundant variables */
    3022                 :             :     int bond_type, num_2s_1, num_alt_1;
    3023                 :             :     int num_2s_2, num_alt_2;
    3024                 :             : #if ( ONE_BAD_SB_NEIGHBOR == 1 )
    3025                 :             :     int num_wrong_bonds_1, num_wrong_bonds_2;
    3026                 :             : #endif
    3027                 :             : #if ( N_V_STEREOBONDS == 1 )
    3028                 :             :     int n2sh, num_2s_hetero[2], num_2s_hetero_next[2], next_next_at, type_N, type_N_next;
    3029                 :             : #endif
    3030                 :             :     int num_stored_isotopic_stereo_bonds; /* djb-rwth: removing redundant variables/code */
    3031                 :             :     int chain_length, num_chains, cur_chain_length;
    3032                 :             :     int all_at_2[MAX_NUM_STEREO_BONDS];
    3033                 :             :     int all_pos_1[MAX_NUM_STEREO_BONDS], all_pos_2[MAX_NUM_STEREO_BONDS];
    3034                 :             :     S_CHAR all_unkn[MAX_NUM_STEREO_BONDS];
    3035                 :         420 :     int /*at_1_parity, at_2_parity,*/ nUnknown, stop = 0;
    3036                 :             : 
    3037                 :             :     /* at_1_parity = AB_PARITY_NONE; */ /*  do not know */
    3038                 :             : 
    3039                 :             :     /*  Check valence */
    3040         [ +  + ]:         420 :     if (MAX_NUM_STEREO_BOND_NEIGH < at[at_1].valence + at[at_1].num_H ||
    3041         [ +  + ]:         222 :          MIN_NUM_STEREO_BOND_NEIGH > at[at_1].valence + at[at_1].num_H)
    3042                 :             :     {
    3043                 :         318 :         return 0;
    3044                 :             :     }
    3045         [ +  + ]:         102 :     if (!bCanAtomHaveAStereoBond( at[at_1].elname, at[at_1].charge, at[at_1].radical ))
    3046                 :             :     {
    3047                 :          65 :         return 0;
    3048                 :             :     }
    3049         [ -  + ]:          37 :     if (at[at_1].c_point)
    3050                 :             :     {
    3051                 :           0 :         return 0; /* rejects atoms that can lose or gain a (positive) charge. 01-24-2003 */
    3052                 :             :     }
    3053                 :             : 
    3054                 :             :     /*  middle cumulene atoms, for example, =C=, should be ignored here */
    3055                 :             :     /*  only atoms at the ends of cumulene chains are considered. */
    3056   [ +  +  -  +  :          37 :     if (!at[at_1].num_H && 2 == at[at_1].valence &&
                   -  - ]
    3057         [ #  # ]:           0 :          BOND_DOUBLE == get_allowed_stereo_bond_type( (int) at[at_1].bond_type[0] ) &&
    3058                 :           0 :          BOND_DOUBLE == get_allowed_stereo_bond_type( (int) at[at_1].bond_type[1] ))
    3059                 :             :     {
    3060                 :           0 :         return 0;
    3061                 :             :     }
    3062                 :             : 
    3063                 :             :     /*  count bonds and find the second atom on the stereo bond */
    3064                 :          37 :     num_2s_1 = num_alt_1 = 0;
    3065                 :          37 :     chain_length = 0;
    3066                 :          37 :     num_chains = 0;
    3067                 :             : #if ( ONE_BAD_SB_NEIGHBOR == 1 )
    3068                 :          37 :     num_wrong_bonds_1 = 0;
    3069                 :             : #endif
    3070                 :             : #if ( N_V_STEREOBONDS == 1 )
    3071                 :          37 :     num_2s_hetero[0] = num_2s_hetero[1] = type_N = 0;
    3072   [ +  +  +  -  :          43 :     if (0 == at[at_1].num_H && 0 == at[at_1].charge && 0 == at[at_1].radical &&
             +  -  -  + ]
    3073                 :           6 :          3 == get_endpoint_valence( at[at_1].el_number ))
    3074                 :             :     {
    3075   [ #  #  #  # ]:           0 :         if (2 == at[at_1].valence && 3 == at[at_1].chem_bonds_valence)
    3076                 :             :         {
    3077                 :           0 :             type_N = 1;
    3078                 :             :         }
    3079                 :             :         else
    3080                 :             :         {
    3081   [ #  #  #  # ]:           0 :             if (3 == at[at_1].valence && 5 == at[at_1].chem_bonds_valence)
    3082                 :             :             {
    3083                 :           0 :                 type_N = 2; /* unfortunately includes >N# */
    3084                 :             :             }
    3085                 :             :         }
    3086                 :             :     }
    3087                 :             : #endif
    3088         [ +  + ]:         100 :     for (i_next_at_1 = 0, num_stereo_bonds = 0; i_next_at_1 < at[at_1].valence; i_next_at_1++)
    3089                 :             :     {
    3090                 :          63 :         nUnknown = ( at[at_1].bond_stereo[i_next_at_1] == STEREO_DBLE_EITHER );
    3091                 :          63 :         bond_type = get_allowed_stereo_bond_type( (int) at[at_1].bond_type[i_next_at_1] );
    3092                 :          63 :         at_2 = -1; /* not found */
    3093   [ +  +  +  + ]:          63 :         if (bond_type == BOND_ALTERN ||
    3094                 :             :              bond_type == BOND_DOUBLE)
    3095                 :             :         {
    3096                 :          32 :             at_2 = at[at_1].neighbor[i_next_at_1]; /* djb-rwth: removing redundant code */
    3097                 :          32 :             next_at_2 = at_1;
    3098                 :             :         }
    3099   [ +  +  +  - ]:          63 :         switch (bond_type)
    3100                 :             :         {
    3101                 :          24 :             case BOND_ALTERN:
    3102                 :          24 :                 num_alt_1++;
    3103                 :             : #if ( FIND_RING_SYSTEMS == 1 )
    3104         [ -  + ]:          24 :                 if (at[at_1].nRingSystem != at[at_2].nRingSystem)
    3105                 :             :                 {
    3106                 :           0 :                     continue; /* reject alt. bond connecting different ring systems */
    3107                 :             :                 }
    3108                 :             : #endif
    3109   [ +  -  -  + ]:          48 :                 if (( nMode & CMODE_NO_ALT_SBONDS ) ||
    3110                 :          24 :                      !bCanAtomHaveAStereoBond( at[at_2].elname, at[at_2].charge, at[at_2].radical ))
    3111                 :             :                 {
    3112                 :           0 :                     continue; /*  reject non-stereogenic bond to neighbor ord. #i_next_at_1 */
    3113                 :             :                 }
    3114                 :          24 :                 break;
    3115                 :           8 :             case BOND_DOUBLE:
    3116                 :             :                 /*  check for cumulene/allene */
    3117                 :           8 :                 num_2s_1++;
    3118                 :           8 :                 cur_chain_length = 0;
    3119         [ +  - ]:           8 :                 if (bCanAtomBeTerminalAllene( at[at_1].elname, at[at_1].charge, at[at_1].radical ))
    3120                 :             :                 {
    3121                 :             :                     /*
    3122                 :             :                      * Example of cumulene
    3123                 :             :                      * chain length = 2:     >X=C=C=Y<
    3124                 :             :                      *                        | | | |
    3125                 :             :                      *  1st cumulene atom= at_1 | | at_2 =last cumlene chain atom
    3126                 :             :                      *  next to at_1=   next_at_1 next_at_2  =previous to at_2
    3127                 :             :                      *
    3128                 :             :                      *  chain length odd:  stereocenter on the middle atom ( 1=> allene )
    3129                 :             :                      *  chain length even: "long stereogenic bond"
    3130                 :             :                      */
    3131                 :           8 :                     while (( bAllene =
    3132   [ #  #  #  # ]:           0 :                         !at[at_2].num_H && at[at_2].valence == 2 &&
    3133   [ -  +  -  - ]:           8 :                         BOND_DOUBLE == get_allowed_stereo_bond_type( (int) at[at_2].bond_type[0] ) &&
    3134   [ -  +  -  - ]:           8 :                         BOND_DOUBLE == get_allowed_stereo_bond_type( (int) at[at_2].bond_type[1] ) ) &&
    3135                 :           0 :                             bCanAtomBeMiddleAllene( at[at_2].elname, at[at_2].charge, at[at_2].radical ))
    3136                 :             :                     {
    3137                 :           0 :                         k = ( (int) at[at_2].neighbor[0] == next_at_2 ); /*  opposite neighbor position */
    3138                 :           0 :                         next_at_2 = at_2;
    3139                 :           0 :                         nUnknown += ( at[at_2].bond_stereo[k] == STEREO_DBLE_EITHER );
    3140                 :           0 :                         at_2 = (int) at[at_2].neighbor[k];
    3141                 :           0 :                         cur_chain_length++;  /*  count =C= atoms */
    3142                 :             :                     }
    3143         [ -  + ]:           8 :                     if (cur_chain_length)
    3144                 :             :                     {
    3145                 :           0 :                         num_chains++;
    3146   [ #  #  #  # ]:           0 :                         if (bAllene /* at the end of the chain atom Y is =Y=, not =Y< or =Y- */ ||
    3147                 :           0 :                              !bCanAtomBeTerminalAllene( at[at_2].elname, at[at_2].charge, at[at_2].radical ))
    3148                 :             :                         {
    3149                 :           0 :                             cur_chain_length = 0; /* djb-rwth: ignoring LLVM warning: value used */
    3150                 :           0 :                             continue; /*  ignore: does not fit cumulene description; go to check next at_1 neighbor */
    3151                 :             :                         }
    3152                 :           0 :                         chain_length = cur_chain_length; /*  accept a stereogenic cumulele */
    3153                 :             :                     }
    3154                 :             :                 }
    3155                 :             : #if ( N_V_STEREOBONDS == 1 )
    3156   [ +  -  -  + ]:          16 :                 if (!cur_chain_length &&
    3157                 :           8 :                      0 <= ( n2sh = bIsSuitableHeteroInpAtom( at + at_2 ) ))
    3158                 :             :                 {
    3159                 :           0 :                     num_2s_hetero[n2sh] ++; /* n2sh=0 -> =N- or =NH; n2sh=1 -> =O */
    3160                 :             :                 }
    3161                 :             : #endif
    3162   [ +  -  -  + ]:          16 :                 if (!cur_chain_length &&
    3163                 :           8 :                      !bCanAtomHaveAStereoBond( at[at_2].elname, at[at_2].charge, at[at_2].radical ))
    3164                 :             :                 {
    3165                 :           0 :                     continue; /*  reject non-stereogenic bond to neighbor #i_next_at_1 */
    3166                 :             :                 }
    3167                 :             : 
    3168                 :           8 :                 break;
    3169                 :             : 
    3170                 :          31 :             case BOND_SINGLE:
    3171                 :             :             case BOND_TAUTOM:
    3172                 :          31 :                 continue; /*  reject non-stereogenic bond to neighbor #i_next_at_1 */
    3173                 :           0 :             default:
    3174                 :             : #if ( ONE_BAD_SB_NEIGHBOR == 1 )
    3175                 :           0 :                 num_wrong_bonds_1++;
    3176                 :           0 :                 continue;
    3177                 :             : #else
    3178                 :             :                 return 0; /*  wrong bond type; */
    3179                 :             : #endif
    3180                 :             :         }
    3181                 :             : 
    3182                 :             :         /*  Check atom at the opposite end of possibly stereogenic bond */
    3183                 :             : 
    3184   [ +  -  +  + ]:          32 :         bFound = ( at_2 >= 0 && at_1 > at_2 ); /*  i_next_at_1 = at_1 stereogenic bond neighbor attachment number */
    3185                 :             : 
    3186         [ +  + ]:          32 :         if (bFound)
    3187                 :             :         {
    3188                 :             :             /*  Check "at_2" atom on the opposite side of the bond or cumulene chain */
    3189         [ +  - ]:          16 :             if (MAX_NUM_STEREO_BOND_NEIGH < at[at_2].valence + at[at_2].num_H ||
    3190         [ -  + ]:          16 :                  MIN_NUM_STEREO_BOND_NEIGH > at[at_2].valence + at[at_2].num_H)
    3191                 :           0 :                 continue;
    3192                 :             : 
    3193                 :             :             /*  Check at_2 neighbors and bonds */
    3194                 :          16 :             num_2s_2 = num_alt_2 = 0;
    3195                 :             : #if ( N_V_STEREOBONDS == 1 )
    3196                 :          16 :             num_2s_hetero_next[0] = num_2s_hetero_next[1] = type_N_next = 0;
    3197   [ +  +  +  -  :          24 :             if (0 == at[at_2].num_H && 0 == at[at_2].charge && 0 == at[at_2].radical &&
             +  -  -  + ]
    3198                 :           8 :                  3 == get_endpoint_valence( at[at_2].el_number ))
    3199                 :             :             {
    3200   [ #  #  #  # ]:           0 :                 if (2 == at[at_2].valence && 3 == at[at_2].chem_bonds_valence)
    3201                 :             :                 {
    3202                 :           0 :                     type_N_next = 1; /* -N= */
    3203                 :             :                 }
    3204                 :             :                 else
    3205                 :             :                 {
    3206   [ #  #  #  # ]:           0 :                     if (3 == at[at_2].valence && 5 == at[at_2].chem_bonds_valence)
    3207                 :             :                     {
    3208                 :           0 :                         type_N_next = 2; /* unfortunately includes >N# */
    3209                 :             :                     }
    3210                 :             :                 }
    3211                 :             :             }
    3212                 :             : #endif
    3213                 :          16 :             i_next_at_2 = -1;  /*  unassigned mark */
    3214                 :             : #if ( ONE_BAD_SB_NEIGHBOR == 1 )
    3215                 :          16 :             num_wrong_bonds_2 = 0;
    3216                 :             : #endif
    3217         [ +  + ]:          56 :             for (j = 0; j < at[at_2].valence; j++)
    3218                 :             :             {
    3219                 :          40 :                 bond_type = get_allowed_stereo_bond_type( (int) at[at_2].bond_type[j] );
    3220         [ -  + ]:          40 :                 if (!bond_type)
    3221                 :             :                 {
    3222                 :             : #if ( ONE_BAD_SB_NEIGHBOR == 1 )
    3223                 :           0 :                     num_wrong_bonds_2++;
    3224                 :           0 :                     continue;  /*  this bond type is not allowed to be adjacent to a stereo bond */
    3225                 :             : #else
    3226                 :             :                     break;
    3227                 :             : #endif
    3228                 :             :                 }
    3229         [ +  + ]:          40 :                 if (bond_type == BOND_DOUBLE)
    3230                 :             :                 {
    3231                 :           4 :                     num_2s_2++;
    3232                 :             : #if ( N_V_STEREOBONDS == 1 )
    3233                 :           4 :                     next_next_at = at[at_2].neighbor[j];
    3234         [ -  + ]:           4 :                     if (0 <= ( n2sh = bIsSuitableHeteroInpAtom( at + next_next_at ) ))
    3235                 :             :                     {
    3236                 :           0 :                         num_2s_hetero_next[n2sh] ++; /* n2sh=0 -> =N- or =NH; n2sh=1 -> =O */
    3237                 :             :                     }
    3238                 :             : #endif
    3239                 :             :                 }
    3240                 :             :                 else
    3241                 :             :                 {
    3242                 :          36 :                     num_alt_2 += ( bond_type == BOND_ALTERN );
    3243                 :             :                 }
    3244         [ +  + ]:          40 :                 if ((int) at[at_2].neighbor[j] == next_at_2)
    3245                 :             :                 {
    3246                 :          16 :                     i_next_at_2 = j; /*  assigned */
    3247                 :             :                 }
    3248                 :             :             }
    3249         [ +  - ]:          16 :             if (
    3250                 :             : #if ( ONE_BAD_SB_NEIGHBOR == 1 )
    3251   [ -  +  -  - ]:          16 :                  num_wrong_bonds_2 > 1 || (num_wrong_bonds_2 && 2 >= at[at_2].valence) || /* djb-rwth: addressing LLVM warning */
    3252                 :             : #else
    3253                 :             :                  j < at[at_2].valence /* "next" has a wrong bond type*/ ||
    3254                 :             : #endif
    3255   [ +  -  -  + ]:          16 : ( num_alt_2 > 0 ) + ( num_2s_2 > 0 ) != 1 || /* all double XOR all alt bonds only */
    3256                 :             :  /* num_2s_2 > 1  ||*/ /* only one double bond permitted */
    3257                 :             :                   i_next_at_2 < 0 /* atom next to the opposite atom not found */)
    3258                 :             :             {
    3259                 :           0 :                 bFound = 0;
    3260                 :             :             }
    3261                 :             :             else
    3262         [ -  + ]:          16 :                 if (at[at_2].c_point)
    3263                 :             :                 {
    3264                 :           0 :                     bFound = 0; /* rejects atoms that can lose or gain a (positive) charge. 01-24-2003 */
    3265                 :             :                 }
    3266                 :             :                 else
    3267         [ -  + ]:          16 :                     if (num_2s_2 > 2)
    3268                 :             :                     {
    3269                 :           0 :                         bFound = 0;
    3270                 :             :                     }
    3271                 :             :                     else
    3272                 :             : #if ( N_V_STEREOBONDS == 1 )
    3273   [ -  +  -  -  :          16 :                         if ( 3==( type_N | type_N_next ) && ( (2==type_N && !bIsOxide( at, at_1 )) ||
             -  -  -  - ]
    3274         [ #  # ]:           0 :                              (2==type_N_next && !bIsOxide( at, at_2 )) )) /* djb-rwth: addressing LLVM warnings */
    3275                 :             :                         {
    3276                 :           0 :                             bFound = 0;
    3277                 :             :                         }
    3278                 :             :                         else
    3279                 :             : #endif
    3280                 :             :                         {
    3281         [ -  + ]:          16 :                             if (2 == num_2s_2)
    3282                 :             :                             {
    3283                 :             : #if ( N_V_STEREOBONDS == 1 )
    3284         [ #  # ]:           0 :                                 if (!chain_length &&
    3285         [ #  # ]:           0 :                                      1 == ( num_2s_hetero_next[0] | num_2s_hetero_next[1] ) &&
    3286         [ #  # ]:           0 :                                      3 == at[at_2].valence + at[at_2].num_H &&
    3287   [ #  #  #  # ]:           0 :                                      5 == at[at_2].chem_bonds_valence + at[at_2].num_H &&
    3288         [ #  # ]:           0 :                                      3 == get_endpoint_valence( at[at_2].el_number ) &&
    3289         [ #  # ]:           0 :                                      ( !type_N || bIsOxide( at, at_2 ) ))
    3290                 :             :                                 {
    3291                 :             :                                     /*
    3292                 :             :                                      *   found:
    3293                 :             :                                      *
    3294                 :             :                                      *    \      /    \      /    \      /
    3295                 :             :                                      *     \    /      \    /      \    /
    3296                 :             :                                      *      N==C   or   N==C   or   N==N
    3297                 :             :                                      *    //    \     //    \     //    \
    3298                 :             :                                      *   O  ^    \   N  ^    \   O  ^    \
    3299                 :             :                                      *      |           |           |
    3300                 :             :                                      *      |           |           |
    3301                 :             :                                      *      at[at_2]    at[at_2]    at[at_2]
    3302                 :             :                                      */
    3303                 :             :                                     ;
    3304                 :             :                                 }
    3305                 :             :                                 else
    3306                 :             :                                 {
    3307                 :           0 :                                     bFound = 0;
    3308                 :             :                                 }
    3309                 :             : #else
    3310                 :             :                                 bFound = 0;
    3311                 :             : #endif
    3312                 :             :                                 }
    3313                 :             :                             }
    3314                 :             : 
    3315   [ -  +  -  - ]:          16 :             if (chain_length && num_alt_2)
    3316                 :             :             {
    3317                 :           0 :                 return 0; /*  allow no alt bonds in cumulenes */
    3318                 :             :             }
    3319                 :             :         }
    3320                 :             : 
    3321         [ +  + ]:          32 :         if (bFound)
    3322                 :             :         {
    3323                 :          16 :             all_pos_1[num_stereo_bonds] = i_next_at_1; /* neighbor to at_1 position */
    3324                 :          16 :             all_pos_2[num_stereo_bonds] = i_next_at_2; /* neighbor to at_2 position */
    3325                 :          16 :             all_at_2[num_stereo_bonds] = at_2;        /* at_2 */
    3326                 :          16 :             all_unkn[num_stereo_bonds] = nUnknown;    /* stereogenic bond has Unknown configuration */
    3327                 :             :             /*
    3328                 :             :             if ( (at[at_1].bUsed0DParity & 2) || (at[at_2].bUsed0DParity & 2) ) {
    3329                 :             :                 for ( k = 0; k < MAX_NUM_STEREO_BONDS && at[at_1].sb_parity[k]; k ++ ) {
    3330                 :             :                     if ( at[at_1].sb_neigh[k] == i_next_at_1 ) {
    3331                 :             :                         if ( at[at_1].sb_parity[k] == AB_PARITY_UNKN && !nUnknown ) {
    3332                 :             :                             all_unkn[num_stereo_bonds] = 1;
    3333                 :             :                         }
    3334                 :             :                         break;
    3335                 :             :                     }
    3336                 :             :                 }
    3337                 :             :             }
    3338                 :             :             */
    3339                 :          16 :             num_stereo_bonds++;
    3340                 :             :         }
    3341                 :             :     }
    3342         [ -  + ]:          37 :     if (num_chains > 1)
    3343                 :             :     {
    3344                 :           0 :         return 0; /*  cannot be more than 1 cumulene chain. */
    3345                 :             :     }
    3346                 :             : #if ( ONE_BAD_SB_NEIGHBOR == 1 )
    3347   [ +  -  -  +  :          37 :     if (num_wrong_bonds_1 > 1 || (num_wrong_bonds_1 && 2 >= at[at_1].valence)) /* djb-rwth: addressing LLVM warning */
                   -  - ]
    3348                 :             :     {
    3349                 :           0 :         return 0; /* wrong bond type */
    3350                 :             :     }
    3351                 :             : #endif
    3352                 :             :     /*  Accept only short chains for now */
    3353                 :             :     /*  chain_length=1: >C=C=C<      tetrahedral center, allene */
    3354                 :             :     /*  chain_length=2: >C=C=C=C<    stereogenic bond, cumulene */
    3355   [ -  +  -  -  :          37 :     if (chain_length && ( num_stereo_bonds != 1 || num_alt_1 || chain_length > MAX_CUMULENE_LEN ))
             -  -  -  - ]
    3356                 :             :     {
    3357                 :           0 :         return 0;
    3358                 :             :     }
    3359                 :             : 
    3360                 :             :     /*  We need 1 double bond/chain XOR up to 3 arom. bonds */
    3361                 :             :     /*  to have a stereogenic bond */
    3362   [ +  +  +  + ]:          37 :     if (( num_alt_1 > 0 ) + ( num_2s_1 > 0 ) != 1 || !num_stereo_bonds /*|| num_2s_1 > 1*/)
    3363                 :          23 :         return 0;
    3364                 :             : 
    3365         [ -  + ]:          14 :     if (num_2s_1 > 1)
    3366                 :             :     {
    3367                 :             : #if ( N_V_STEREOBONDS == 1 )
    3368   [ #  #  #  # ]:           0 :         if (2 == num_2s_1 &&
    3369                 :           0 :              2 == type_N &&
    3370         [ #  # ]:           0 :              1 == ( num_2s_hetero[0] | num_2s_hetero[1] ) &&
    3371         [ #  # ]:           0 :              3 == at[at_1].valence + at[at_1].num_H &&
    3372   [ #  #  #  # ]:           0 :              5 == at[at_1].chem_bonds_valence + at[at_1].num_H &&
    3373                 :           0 :              3 == get_endpoint_valence( at[at_1].el_number ))
    3374                 :             :         {
    3375                 :             :             ;
    3376                 :             :         }
    3377                 :             :         else
    3378                 :             :         {
    3379                 :           0 :             return 0;
    3380                 :             :         }
    3381                 :             : #else
    3382                 :             :         return 0;
    3383                 :             : #endif
    3384                 :             :     }
    3385                 :             : 
    3386                 :             :     /* ================== Calculate parities ====================== */
    3387                 :             : 
    3388                 :             : 
    3389                 :             :     /*  Find possibly stereo bonds and save them */
    3390                 :          14 :     num_stored_isotopic_stereo_bonds = 0;
    3391                 :             :     /* djb-rwth: removing redundant code */
    3392         [ +  + ]:          30 :     for (k = 0; k < num_stereo_bonds; k++)
    3393                 :             :     {
    3394                 :             : 
    3395                 :             :         int cur_parity, next_parity, abs_cur_parity, abs_next_parity, dot_prod_z;
    3396                 :             :         S_CHAR z_dir1[3], z_dir2[3]; /*  3D vectors for half stereo bond parity direction */
    3397                 :          16 :         int  chain_len_bits = MAKE_BITS_CUMULENE_LEN( chain_length );
    3398                 :             :         int  cur_parity_defined, next_parity_defined;
    3399                 :             :         int  cur_action, next_action, result_action;
    3400                 :             : 
    3401                 :          16 :         at_2 = all_at_2[k];
    3402                 :          16 :         i_next_at_1 = all_pos_1[k];
    3403                 :             : 
    3404                 :             : #if ( MIN_SB_RING_SIZE > 0 )
    3405         [ +  - ]:          16 :         if (at[at_1].nRingSystem == at[at_2].nRingSystem)
    3406                 :             :         {
    3407                 :             :             /*  check min. ring size only if both double bond/cumulene */
    3408                 :             :             /*  ending atoms belong to the same ring system */
    3409                 :          16 :             j = is_bond_in_Nmax_memb_ring( at, at_1, i_next_at_1, q, nAtomLevel, cSource, min_sb_ring_size );
    3410         [ +  - ]:          16 :             if (j > 0)
    3411                 :             :             {
    3412                 :          16 :                 continue;
    3413                 :             :             }
    3414                 :             :             else
    3415                 :             :             {
    3416         [ #  # ]:           0 :                 if (j < 0)
    3417                 :             :                 {
    3418                 :           0 :                     return CT_STEREOBOND_ERROR;
    3419                 :             :                 }
    3420                 :             :             }
    3421                 :             :         }
    3422                 :             : #endif
    3423                 :             : 
    3424                 :           0 :         i_next_at_2 = all_pos_2[k];
    3425                 :           0 :         nUnknown = all_unkn[k];
    3426                 :           0 :         memset( z_dir1, 0, sizeof( z_dir1 ) ); /* djb-rwth: memset_s C11/Annex K variant? */
    3427                 :           0 :         memset( z_dir2, 0, sizeof( z_dir2 ) ); /* djb-rwth: memset_s C11/Annex K variant? */
    3428                 :             : 
    3429                 :             :         /********************************************************************************
    3430                 :             :          * Find atom parities (negative means parity due to H-isotopes only)
    3431                 :             :          * and half stereo bond parity directions z_dir1, z_dir2.
    3432                 :             :          *
    3433                 :             :          * Bond can have unknown or undefined parity or no parity because of:
    3434                 :             :          * 1. Geometry (poorly defined, cannot calculate, for example linear =C-F
    3435                 :             :          *    or =CHD with no geometry) -- Undefined parity
    3436                 :             :          *                                                              H
    3437                 :             :          * 2. Identical H atoms (no parity in principle, for example =C<  )
    3438                 :             :          *    -- No parity                                              H
    3439                 :             :          *
    3440                 :             :          * 3. The user said double bond stereo is unknown
    3441                 :             :          *    or at least one of single bonds is in unknown direction
    3442                 :             :          *    -- Unknown parity
    3443                 :             :          *
    3444                 :             :          * These 3 cases (see above) are referred below as 1, 2, 3.
    3445                 :             :          * Each of the cases may be present or not (2 possibilities)
    3446                 :             :          * Total number of combination is 2*2*2=8
    3447                 :             :          *
    3448                 :             :          * Since a case when all 3 are not present is a well-defined parity,
    3449                 :             :          * we do not consider this case here. Then 2*2*2-1=7 cases are left.
    3450                 :             :          *
    3451                 :             :          * If several cases are present, list them below separated by "+".
    3452                 :             :          * For example, 1+2 means (1) undefined geometry and (2) no parity
    3453                 :             :          * is possible because of identical H atoms.
    3454                 :             :          *
    3455                 :             :          * N) Decision table, Non-isotopic, 2*2*2-1=7 cases:
    3456                 :             :          * =================================================
    3457                 :             :          * none     : 2+any: 1+2(e.g.=CH2); 1+2+3; 2; 2+3  AB_PARITY_NONE=0
    3458                 :             :          * undefined: 1                                    AB_PARITY_UNDF
    3459                 :             :          * unknown  : 1+3; 3                               AB_PARITY_UNKN
    3460                 :             :          *
    3461                 :             :          * I) Decision table, Isotopic, 2*2*2-1=7 cases:
    3462                 :             :          * =============================================
    3463                 :             :          * none     : none
    3464                 :             :          * undefined: 1; 1+2; 1+2+3; 2; 2+3
    3465                 :             :          * unknown  : 1+3; 3
    3466                 :             :          *
    3467                 :             :          * Note: When defining identical atoms H atoms in case 2,
    3468                 :             :          *       Isotopic and Non-isotopic cases are different:
    3469                 :             :          *  N: do NOT take into account the isotopic composition of H atoms
    3470                 :             :          *  I: DO take into account the isotopic composition of H atoms
    3471                 :             :          *     (it is assumed that H isotopes are always different)
    3472                 :             :          *
    3473                 :             :          * half_stereo_bond_parity() returns:
    3474                 :             :          * ==================================
    3475                 :             :          * Note: half_stereo_bond_parity() is unaware of case 3.
    3476                 :             :          *
    3477                 :             :          * can't be a half of a stereo bond    AB_PARITY_NONE
    3478                 :             :          * 1, isotopic & non-isotopic:         AB_PARITY_UNDF
    3479                 :             :          * 1, isotopic only                   -AB_PARITY_UNDF
    3480                 :             :          * 2, no parity: identical H isotopes  AB_PARITY_IISO
    3481                 :             :          * 3, 'Either' single bond(s)          AB_PARITY_UNKN ???
    3482                 :             :          * 3, 'Either' single bond(s), iso H  -AB_PARITY_UNKN ???
    3483                 :             :          * defined parity                      AB_PARITY_ODD,  AB_PARITY_EVEN
    3484                 :             :          * defined parity for isotopic only:  -AB_PARITY_ODD, -AB_PARITY_EVEN
    3485                 :             :          *
    3486                 :             :          * Resultant value for the stereo bond parity
    3487                 :             :          * ---+-------------------+-------+--------+----------------+
    3488                 :             :          * 3? | half_stereo_bond_ | N or I| case 1,| bond parity    |
    3489                 :             :          *    |  parity()=        |       | 2 or 3 |                |
    3490                 :             :          * ---+-------------------+-------+--------+----------------+
    3491                 :             :          *   ( AB_PARITY_ODD/EVEN) => N&I: -       => AB_PARITY_CALC (=6, calc.later)
    3492                 :             :          * 3+( AB_PARITY_ODD/EVEN) => N&I: 3       => AB_PARITY_UNKN (=3)
    3493                 :             :          *   (-AB_PARITY_ODD/EVEN) => N:   2       => AB_PARITY_NONE (=0)
    3494                 :             :          *   (-AB_PARITY_ODD/EVEN) => I:   -       => AB_PARITY_CALC
    3495                 :             :          * 3+(-AB_PARITY_ODD/EVEN) => N:   2+3     => AB_PARITY_UNDF (=4)
    3496                 :             :          * 3+(-AB_PARITY_ODD/EVEN) => I:   3       => AB_PARITY_UNKN
    3497                 :             :          *   ( AB_PARITY_IISO )    => N:   1+2, 2  => AB_PARITY_NONE (=0)
    3498                 :             :          *   ( AB_PARITY_IISO )    => I:   1+2, 2  => AB_PARITY_UNDF
    3499                 :             :          * 3+( AB_PARITY_IISO )    => N:  1+2+3,2+3=> AB_PARITY_NONE
    3500                 :             :          * 3+( AB_PARITY_IISO )    => I:  1+2+3,2+3=> AB_PARITY_UNDF
    3501                 :             :          *   ( AB_PARITY_UNDF )    => N&I: 1       => AB_PARITY_UNDF
    3502                 :             :          * 3+( AB_PARITY_UNDF )    => N&I: 1+3     => AB_PARITY_UNKN
    3503                 :             :          *   (-AB_PARITY_UNDF )    => N:   1+2     => AB_PARITY_NONE
    3504                 :             :          *   (-AB_PARITY_UNDF )    => I:   1       => AB_PARITY_UNDF
    3505                 :             :          * 3+(-AB_PARITY_UNDF )    => N:   1+2+3   => AB_PARITY_NONE
    3506                 :             :          * 3+(-AB_PARITY_UNDF )    => I:   1+3     => AB_PARITY_UNKN
    3507                 :             :          * ---+-------------------+-------+--------+----------------+
    3508                 :             : 
    3509                 :             :          * If bond parity is undefined because abs(dot_prod_z) < MIN_DOT_PROD
    3510                 :             :          * then replace: AB_PARITY_CALC
    3511                 :             :          *         with: AB_PARITY_UNDF
    3512                 :             :          * Joining two half_bond_parity() results:
    3513                 :             :          *
    3514                 :             :          *
    3515                 :             :          * atom1 \ atom2   | AB_PARITY_NONE  AB_PARITY_UNKN  AB_PARITY_UNDF  AB_PARITY_CALC
    3516                 :             :          * ----------------+---------------------------------------------------------------
    3517                 :             :          *0=AB_PARITY_NONE | AB_PARITY_NONE  AB_PARITY_NONE  AB_PARITY_NONE  AB_PARITY_NONE
    3518                 :             :          *3=AB_PARITY_UNKN |                 AB_PARITY_UNKN  AB_PARITY_UNKN  AB_PARITY_UNKN
    3519                 :             :          *4=AB_PARITY_UNDF |                                 AB_PARITY_UNDF  AB_PARITY_UNDF
    3520                 :             :          *6=AB_PARITY_CALC |                                                 AB_PARITY_CALC
    3521                 :             :          *
    3522                 :             :          * that is, take min out of the two
    3523                 :             :          *********************************************************************************/
    3524                 :             : 
    3525                 :           0 :         cur_parity = half_stereo_bond_parity( at, at_1, at_removed_H, num_removed_H,
    3526                 :             :                                                 z_dir1, bPointedEdgeStereo, vABParityUnknown );
    3527                 :           0 :         next_parity = half_stereo_bond_parity( at, at_2, at_removed_H, num_removed_H,
    3528                 :             :                                                 z_dir2, bPointedEdgeStereo, vABParityUnknown );
    3529                 :             : 
    3530   [ #  #  #  #  :           0 :         if (RETURNED_ERROR( cur_parity ) || RETURNED_ERROR( next_parity ))
             #  #  #  # ]
    3531                 :             :         {
    3532                 :           0 :             return CT_CALC_STEREO_ERR;
    3533                 :             :         }
    3534   [ #  #  #  # ]:           0 :         if (( at[at_1].bUsed0DParity & FlagSB_0D ) || ( at[at_2].bUsed0DParity & FlagSB_0D )) /* djb-rwth: condition corrected */
    3535                 :             :         {
    3536                 :           0 :             FixSb0DParities( at, /* at_removed_H, num_removed_H,*/ chain_length,
    3537                 :             :                              at_1, i_next_at_1, z_dir1,
    3538                 :             :                              at_2, i_next_at_2, z_dir2, &cur_parity, &next_parity );
    3539                 :             :         }
    3540                 :             : 
    3541   [ #  #  #  # ]:           0 :         if (cur_parity == AB_PARITY_NONE || abs( cur_parity ) == AB_PARITY_IISO)
    3542                 :             :         {
    3543                 :           0 :             continue;
    3544                 :             :         }
    3545   [ #  #  #  # ]:           0 :         if (next_parity == AB_PARITY_NONE || abs( next_parity ) == AB_PARITY_IISO)
    3546                 :             :         {
    3547                 :           0 :             continue;
    3548                 :             :         }
    3549                 :             : 
    3550                 :           0 :         cur_action = half_stereo_bond_action( cur_parity, nUnknown, 0, vABParityUnknown ); /*  -1 => program error */
    3551                 :           0 :         next_action = half_stereo_bond_action( next_parity, nUnknown, 0, vABParityUnknown );
    3552                 :           0 :         result_action = inchi_min( cur_action, next_action );
    3553                 :             : 
    3554         [ #  # ]:           0 :         if (result_action == -1)
    3555                 :             :         {
    3556                 :           0 :             stop = 1; /*  program error <BRKPT> */
    3557                 :             :         }
    3558                 :             : 
    3559                 :           0 :         abs_cur_parity = abs( cur_parity );
    3560                 :           0 :         abs_next_parity = abs( next_parity );
    3561   [ #  #  #  # ]:           0 :         cur_parity_defined = ATOM_PARITY_WELL_DEF( abs_cur_parity );
    3562   [ #  #  #  # ]:           0 :         next_parity_defined = ATOM_PARITY_WELL_DEF( abs_next_parity );
    3563                 :             : 
    3564   [ #  #  #  # ]:           0 :         if (cur_parity_defined && next_parity_defined)
    3565                 :             :         {
    3566                 :             :             /*  find how the whole bond parity depend on geometry */
    3567                 :             :             /*  if dot_prod_z < 0 then bond_parity := 3-bond_parity */
    3568                 :             :             /*  can be done only for a well-defined geometry */
    3569                 :             :             /*
    3570                 :             :             dot_prod_z  = (chain_len_bits & BIT_CUMULENE_CHI)?
    3571                 :             :                            triple_prod_char( at, at_1, i_next_at_1, z_dir1, at_2, i_next_at_2, z_dir2 ) :
    3572                 :             :                            dot_prodchar3(z_dir1, z_dir2);
    3573                 :             :             */
    3574                 :             : 
    3575         [ #  # ]:           0 :             dot_prod_z = ( chain_len_bits && BOND_CHAIN_LEN( chain_len_bits ) % 2 )
    3576                 :           0 :                 ?  triple_prod_char( at, at_1, i_next_at_1, z_dir1, at_2, i_next_at_2, z_dir2 )
    3577         [ #  # ]:           0 :                 :  dot_prodchar3( z_dir1, z_dir2 );
    3578                 :             : 
    3579   [ #  #  #  # ]:           0 :             if (abs( dot_prod_z ) < MIN_DOT_PROD)
    3580                 :             :             {
    3581                 :             :                 /*  The geometry is not well-defined. Eliminate AB_PARITY_CALC */
    3582                 :           0 :                 result_action = inchi_min( result_action, AB_PARITY_UNDF );
    3583                 :             :             }
    3584                 :             :         }
    3585                 :             :         else
    3586                 :             :         {
    3587                 :           0 :             dot_prod_z = 0;
    3588                 :             :         }
    3589                 :             : 
    3590   [ #  #  #  # ]:           0 :         if (result_action != AB_PARITY_NONE && result_action != -1)
    3591                 :             :         {
    3592                 :             :             /*  Stereo, no isotopes (only positive) */
    3593   [ #  #  #  # ]:           0 :             if (cur_parity > 0 && next_parity > 0)
    3594                 :             :             {
    3595         [ #  # ]:           0 :                 if (save_a_stereo_bond( dot_prod_z, result_action | chain_len_bits,
    3596                 :           0 :                     at_1, i_next_at_1, out_at[at_1].stereo_bond_neighbor,
    3597                 :           0 :                     out_at[at_1].stereo_bond_ord, out_at[at_1].stereo_bond_z_prod,
    3598                 :           0 :                     out_at[at_1].stereo_bond_parity,
    3599                 :           0 :                     at_2, i_next_at_2, out_at[at_2].stereo_bond_neighbor,
    3600                 :           0 :                     out_at[at_2].stereo_bond_ord, out_at[at_2].stereo_bond_z_prod,
    3601                 :           0 :                     out_at[at_2].stereo_bond_parity ))
    3602                 :             :                 {
    3603   [ #  #  #  # ]:           0 :                     if (!out_at[at_1].parity ||
    3604   [ #  #  #  # ]:           0 :                          (cur_parity_defined && !ATOM_PARITY_WELL_DEF( abs( out_at[at_1].parity )) )) /* djb-rwth: addressing LLVM warning */
    3605                 :             :                     {
    3606                 :           0 :                         out_at[at_1].parity = cur_parity;
    3607                 :           0 :                         memcpy(out_at[at_1].z_dir, z_dir1, sizeof(out_at[0].z_dir));
    3608                 :             :                     }
    3609   [ #  #  #  # ]:           0 :                     if (!out_at[at_2].parity ||
    3610   [ #  #  #  # ]:           0 :                          (next_parity_defined && !ATOM_PARITY_WELL_DEF( abs( out_at[at_2].parity )) )) /* djb-rwth: addressing LLVM warning */
    3611                 :             :                     {
    3612                 :           0 :                         out_at[at_2].parity = next_parity;
    3613                 :           0 :                         memcpy(out_at[at_2].z_dir, z_dir2, sizeof(out_at[0].z_dir));
    3614                 :             :                     }
    3615                 :           0 :                     out_at[at_1].bAmbiguousStereo |= at[at_1].bAmbiguousStereo;
    3616                 :           0 :                     out_at[at_2].bAmbiguousStereo |= at[at_2].bAmbiguousStereo;
    3617                 :             :                     /* djb-rwth: removing redundant code */
    3618                 :             :                 }
    3619                 :             :             }
    3620                 :             :         }
    3621                 :             : 
    3622                 :             :         /*  Stereo + isotopic (all non-zero) */
    3623                 :           0 :         cur_action = half_stereo_bond_action( cur_parity, nUnknown, 1, vABParityUnknown ); /*  -1 => program error */
    3624                 :           0 :         next_action = half_stereo_bond_action( next_parity, nUnknown, 1, vABParityUnknown );
    3625                 :           0 :         result_action = inchi_min( cur_action, next_action );
    3626                 :           0 :         cur_parity = abs_cur_parity;
    3627                 :           0 :         next_parity = abs_next_parity;
    3628   [ #  #  #  # ]:           0 :         if (result_action != AB_PARITY_NONE && result_action != -1)
    3629                 :             :         {
    3630                 :             :             /*  Stereo, isotopic */
    3631   [ #  #  #  # ]:           0 :             if (cur_parity > 0 && next_parity > 0)
    3632                 :             :             {
    3633         [ #  # ]:           0 :                 if (save_a_stereo_bond( dot_prod_z, result_action | chain_len_bits,
    3634                 :           0 :                     at_1, i_next_at_1, out_at[at_1].stereo_bond_neighbor2,
    3635                 :           0 :                     out_at[at_1].stereo_bond_ord2, out_at[at_1].stereo_bond_z_prod2,
    3636                 :           0 :                     out_at[at_1].stereo_bond_parity2,
    3637                 :           0 :                     at_2, i_next_at_2, out_at[at_2].stereo_bond_neighbor2,
    3638                 :           0 :                     out_at[at_2].stereo_bond_ord2, out_at[at_2].stereo_bond_z_prod2,
    3639                 :           0 :                     out_at[at_2].stereo_bond_parity2 ))
    3640                 :             :                 {
    3641   [ #  #  #  # ]:           0 :                     if (!out_at[at_1].parity2 ||
    3642   [ #  #  #  # ]:           0 :                          (cur_parity_defined && !ATOM_PARITY_WELL_DEF( abs( out_at[at_1].parity2 )) )) /* djb-rwth: addressing LLVM warning */
    3643                 :             :                     {
    3644                 :           0 :                         out_at[at_1].parity2 = cur_parity /*| chain_len_bits*/;
    3645         [ #  # ]:           0 :                         if (!out_at[at_1].parity)
    3646                 :             :                         {
    3647                 :           0 :                             memcpy(out_at[at_1].z_dir, z_dir1, sizeof(out_at[0].z_dir));
    3648                 :             :                         }
    3649                 :             :                     }
    3650   [ #  #  #  # ]:           0 :                     if (!out_at[at_2].parity2 || /* next line changed from abs(out_at[at_2].parity) 2006-03-05 */
    3651   [ #  #  #  # ]:           0 :                          (next_parity_defined && !ATOM_PARITY_WELL_DEF( abs( out_at[at_2].parity2 )) )) /* djb-rwth: addressing LLVM warning */
    3652                 :             :                     {
    3653                 :           0 :                         out_at[at_2].parity2 = next_parity /*| chain_len_bits*/;
    3654         [ #  # ]:           0 :                         if (!out_at[at_2].parity)
    3655                 :             :                         {
    3656                 :           0 :                             memcpy(out_at[at_2].z_dir, z_dir2, sizeof(out_at[0].z_dir));
    3657                 :             :                         }
    3658                 :             :                     }
    3659                 :           0 :                     out_at[at_1].bAmbiguousStereo |= at[at_1].bAmbiguousStereo;
    3660                 :           0 :                     out_at[at_2].bAmbiguousStereo |= at[at_2].bAmbiguousStereo;
    3661                 :           0 :                     num_stored_isotopic_stereo_bonds++;
    3662                 :             :                 }
    3663                 :             :             }
    3664                 :             :         }
    3665                 :             :         else
    3666                 :             :         {
    3667         [ #  # ]:           0 :             if (result_action == -1)
    3668                 :             :             {
    3669                 :           0 :                 stop = 1; /*  program error? <BRKPT> */
    3670                 :             :             }
    3671                 :             :         }
    3672                 :             :     }
    3673                 :             : 
    3674         [ -  + ]:          14 :     if (stop)
    3675                 :             :     {
    3676                 :           0 :         return CT_CALC_STEREO_ERR;
    3677                 :             :     }
    3678                 :             : 
    3679                 :          14 :     return /*num_stored_stereo_bonds+*/ num_stored_isotopic_stereo_bonds;
    3680                 :             : }
    3681                 :             : 
    3682                 :             : 
    3683                 :             : #if ( NEW_STEREOCENTER_CHECK == 1 )
    3684                 :             : 
    3685                 :             : /* int bCanInpAtomBeAStereoCenter( inp_ATOM *at, int cur_at, int bStereoAtZz ) */
    3686                 :             : 
    3687                 :             : /****************************************************************************
    3688                 :             :  If isotopic H, D, T added, can the atom be a stereo center?
    3689                 :             : ****************************************************************************/
    3690                 :         619 : int can_be_a_stereo_atom_with_isotopic_H( inp_ATOM *at,
    3691                 :             :                                           int cur_at,
    3692                 :             :                                           int bPointedEdgeStereo,
    3693                 :             :                                           int bStereoAtZz )
    3694                 :             : {
    3695                 :             :     int nNumNeigh;
    3696         [ +  + ]:         619 :     if (( nNumNeigh = bCanInpAtomBeAStereoCenter( at, cur_at, bPointedEdgeStereo, bStereoAtZz ) ) &&
    3697         [ +  - ]:         392 :          at[cur_at].valence + at[cur_at].num_H == nNumNeigh &&
    3698         [ +  - ]:         392 :          at[cur_at].num_H <= NUM_H_ISOTOPES
    3699                 :             :        )
    3700                 :             :     {
    3701                 :         392 :         return 1;
    3702                 :             :     }
    3703                 :             : 
    3704                 :         227 :     return 0;
    3705                 :             : }
    3706                 :             : 
    3707                 :             : 
    3708                 :             : #else
    3709                 :             : 
    3710                 :             : /****************************************************************************/
    3711                 :             : int can_be_a_stereo_atom_with_isotopic_H( inp_ATOM *at, int cur_at )
    3712                 :             : {
    3713                 :             :     int j, ret = 0;
    3714                 :             :     if (bCanAtomBeAStereoCenter( at[cur_at].elname, at[cur_at].charge, at[cur_at].radical ) &&
    3715                 :             :          at[cur_at].valence + at[cur_at].num_H == MAX_NUM_STEREO_ATOM_NEIGH &&
    3716                 :             :          at[cur_at].num_H < MAX_NUM_STEREO_ATOM_NEIGH
    3717                 :             :        )
    3718                 :             :     {
    3719                 :             :         for (j = 0, ret = 1; ret && j < at[cur_at].valence; j++)
    3720                 :             :         {
    3721                 :             :             if (( at[cur_at].bond_type[j] & ~BOND_MARK_ALL ) != BOND_SINGLE)
    3722                 :             :             {
    3723                 :             :                 ret = 0;
    3724                 :             :             }
    3725                 :             :         }
    3726                 :             :     }
    3727                 :             : 
    3728                 :             :     return ret;
    3729                 :             : }
    3730                 :             : #endif
    3731                 :             : 
    3732                 :             : 
    3733                 :             : /****************************************************************************/
    3734                 :          22 : int GetStereocenter0DParity( CANON_GLOBALS *pCG,
    3735                 :             :                              inp_ATOM *at,
    3736                 :             :                              int cur_at,
    3737                 :             :                              int j1,
    3738                 :             :                              AT_NUMB nSbNeighOrigAtNumb[],
    3739                 :             :                              int nFlag )
    3740                 :             : {
    3741                 :          22 :     int parity = AB_PARITY_NONE;
    3742   [ -  +  -  -  :          22 :     if (at[cur_at].p_parity && ( j1 == MAX_NUM_STEREO_ATOM_NEIGH - 1 || j1 == MAX_NUM_STEREO_ATOM_NEIGH ))
                   -  - ]
    3743                 :             :     {
    3744                 :             :         int i, num_trans_inp, num_trans_neigh;
    3745                 :             :         AT_NUMB nInpNeighOrigAtNumb[MAX_NUM_STEREO_ATOM_NEIGH];
    3746         [ #  # ]:           0 :         for (i = 0; i < MAX_NUM_STEREO_ATOM_NEIGH; i++)
    3747                 :             :         {
    3748                 :           0 :             nInpNeighOrigAtNumb[i] = at[cur_at].p_orig_at_num[i];
    3749         [ #  # ]:           0 :             if (nInpNeighOrigAtNumb[i] == at[cur_at].orig_at_number)
    3750                 :             :             {
    3751                 :           0 :                 nInpNeighOrigAtNumb[i] = 0; /* lone pair or explicit H */
    3752                 :             :             }
    3753                 :             :         }
    3754                 :             : 
    3755                 :           0 :         num_trans_inp = insertions_sort( pCG, nInpNeighOrigAtNumb, MAX_NUM_STEREO_ATOM_NEIGH, sizeof( nInpNeighOrigAtNumb[0] ), comp_AT_NUMB );
    3756                 :           0 :         num_trans_neigh = insertions_sort( pCG, nSbNeighOrigAtNumb, j1, sizeof( nSbNeighOrigAtNumb[0] ), comp_AT_NUMB );
    3757                 :             : 
    3758                 :             :         if (j1 == MAX_NUM_STEREO_ATOM_NEIGH - 1)
    3759                 :             :         {
    3760                 :             :             ;
    3761                 :             :             /*num_trans_neigh += j1;*/
    3762                 :             :             /* the lone pair or implicit H is implicitly at the top of the list */
    3763                 :             :         }
    3764         [ #  # ]:           0 :         if (!memcmp( nInpNeighOrigAtNumb + MAX_NUM_STEREO_ATOM_NEIGH - j1, nSbNeighOrigAtNumb, j1 * sizeof( AT_NUMB ) ))
    3765                 :             :         {
    3766   [ #  #  #  # ]:           0 :             if (ATOM_PARITY_WELL_DEF( at[cur_at].p_parity ))
    3767                 :             :             {
    3768                 :           0 :                 parity = 2 - ( num_trans_inp + num_trans_neigh + at[cur_at].p_parity ) % 2;
    3769                 :             :             }
    3770                 :             :             else
    3771                 :             :             {
    3772                 :           0 :                 parity = at[cur_at].p_parity;
    3773                 :             :             }
    3774                 :           0 :             at[cur_at].bUsed0DParity |= nFlag; /* 0D parity used for streocenter parity */
    3775                 :             :         }
    3776                 :             :     }
    3777                 :             : 
    3778                 :          22 :     return parity;
    3779                 :             : }
    3780                 :             : 
    3781                 :             : 
    3782                 :             : /****************************************************************************
    3783                 :             :  Get stereo atom parity for the current order of attachments
    3784                 :             :  The result in at[cur_at].parity is valid for previously removed
    3785                 :             :  explicit hydrogen atoms, including isotopic ones, that are located in at_removed_H[]
    3786                 :             :  The return value is a calculated parity.
    3787                 :             : ****************************************************************************/
    3788                 :             : #define ADD_EXPLICIT_HYDROGEN_NEIGH  1
    3789                 :             : #define ADD_EXPLICIT_LONE_PAIR_NEIGH 2
    3790                 :         619 : int set_stereo_atom_parity( CANON_GLOBALS *pCG,
    3791                 :             :                             sp_ATOM *out_at,
    3792                 :             :                             inp_ATOM *at,
    3793                 :             :                             int cur_at,
    3794                 :             :                             inp_ATOM *at_removed_H,
    3795                 :             :                             int num_removed_H,
    3796                 :             :                             int bPointedEdgeStereo,
    3797                 :             :                             int vABParityUnknown,
    3798                 :             :                             int LooseTSACheck,
    3799                 :             :                             int bStereoAtZz )
    3800                 :             : {
    3801                 :             :     int    j, k, next_at, num_z, j1, nType, num_explicit_H, tot_num_iso_H, nMustHaveNumNeigh;
    3802                 :             :     int    num_explicit_iso_H[NUM_H_ISOTOPES + 1];
    3803                 :             :                     /*  numbers of removed hydrogen atoms   */
    3804                 :             :     int    index_H[MAX_NUM_STEREO_ATOM_NEIGH];
    3805                 :             :                     /*  cannot have more than 4 elements: 1 H, 1 D, 1 T atom(s) */
    3806                 :             :     double z, sum_xyz[3], min_sine, triple_product;
    3807                 :             :     double at_coord[MAX_NUM_STEREO_ATOM_NEIGH][3];
    3808                 :         619 :     double bond_len_xy[4], rmax = 0.0, rmin = 0.0;
    3809                 :             :     double at_coord_center[3];
    3810                 :         619 :     int    parity, bAmbiguous = 0, bAddExplicitNeighbor = 0, b2D = 0, n2DTetrahedralAmbiguity = 0;
    3811                 :         619 :     int    bIgnoreIsotopicH = ( 0 != ( at[cur_at].cFlags & AT_FLAG_ISO_H_POINT ) );
    3812                 :             :     AT_NUMB nSbNeighOrigAtNumb[MAX_NUM_STEREO_ATOM_NEIGH];
    3813                 :             : 
    3814                 :         619 :     double vMinAngle = MIN_ANGLE;
    3815                 :         619 :     double vMinSine = MIN_SINE;
    3816         [ -  + ]:         619 :     if (LooseTSACheck)
    3817                 :             :     {
    3818                 :             :         /* Relax check for principal 3-atomic angles close to 180 deg, for 2D tetrahedron, to account for           */
    3819                 :             :         /* large cycles drawn as appear after applying some structure 'cleaning' algorithms/softwares               */
    3820                 :             : 
    3821         [ #  # ]:           0 :         if (at[cur_at].nNumAtInRingSystem >= 3) /* Ensure that central atom is in ring (ideally, one should check   */
    3822                 :             :                                                 /* also that neighbors are in-ring, and for large enough ring)      */
    3823                 :             :         {
    3824                 :           0 :             vMinAngle = MIN_ANGLE_RELAXED;
    3825                 :           0 :             vMinSine = MIN_SINE_RELAXED;
    3826                 :             :         }
    3827                 :             :     }
    3828                 :             : 
    3829                 :         619 :     out_at[cur_at].parity =
    3830                 :         619 :         out_at[cur_at].parity2 =
    3831                 :         619 :         out_at[cur_at].stereo_atom_parity =
    3832                 :         619 :         out_at[cur_at].stereo_atom_parity2 =
    3833                 :             :         AB_PARITY_NONE;
    3834                 :         619 :     parity = AB_PARITY_NONE;
    3835                 :             : 
    3836                 :         619 :     memset( num_explicit_iso_H, 0, sizeof( num_explicit_iso_H ) ); /* djb-rwth: memset_s C11/Annex K variant? */
    3837                 :         619 :     num_explicit_H = 0;
    3838                 :             : 
    3839                 :             : #if ( NEW_STEREOCENTER_CHECK == 1 )
    3840         [ +  + ]:         619 :     if (!( nMustHaveNumNeigh = bCanInpAtomBeAStereoCenter( at, cur_at, bPointedEdgeStereo, bStereoAtZz ) ) ||
    3841         [ -  + ]:         392 :          at[cur_at].num_H > NUM_H_ISOTOPES)
    3842                 :             :     {
    3843                 :         227 :         goto exit_function;
    3844                 :             :     }
    3845                 :             : #else
    3846                 :             :     nMustHaveNumNeigh = MAX_NUM_STEREO_ATOM_NEIGH;
    3847                 :             :     if (!bCanAtomBeAStereoCenter( at[cur_at].elname, at[cur_at].charge, at[cur_at].radical ) ||
    3848                 :             :          at[cur_at].valence + at[cur_at].num_H != nMustHaveNumNeigh ||
    3849                 :             :          at[cur_at].num_H > NUM_H_ISOTOPES
    3850                 :             :        )
    3851                 :             :     {
    3852                 :             :         goto exit_function;
    3853                 :             :     }
    3854                 :             :     for (j = 0; j < at[cur_at].valence; j++)
    3855                 :             :     {
    3856                 :             :         if (( at[cur_at].bond_type[j] & ~BOND_MARK_ALL ) != BOND_SINGLE)
    3857                 :             :         {
    3858                 :             :             goto exit_function;
    3859                 :             :         }
    3860                 :             :     }
    3861                 :             : #endif
    3862                 :             : 
    3863                 :             :     /*  numbers of isotopic H atoms */
    3864         [ +  + ]:        1568 :     for (j = 0, tot_num_iso_H = 0; j < NUM_H_ISOTOPES; j++)
    3865                 :             :     {
    3866         [ -  + ]:        1176 :         if (at[cur_at].num_iso_H[j] > 1)
    3867                 :             :         {
    3868                 :           0 :             goto exit_function; /*  two or more identical hydrogen isotopic neighbors */
    3869                 :             :         }
    3870                 :        1176 :         tot_num_iso_H += at[cur_at].num_iso_H[j];
    3871                 :             :     }
    3872         [ -  + ]:         392 :     if (bIgnoreIsotopicH)
    3873                 :             :     {
    3874                 :           0 :         tot_num_iso_H = 0; /* isotopic H considered subject to exchange => ignore isotopic */
    3875                 :             :     }
    3876                 :             :     /*  number of non-isotopic H atoms */
    3877         [ +  + ]:         392 :     if (at[cur_at].num_H - tot_num_iso_H > 1)
    3878                 :             :     {
    3879                 :         193 :         goto exit_function; /*  two or more identical hydrogen non-isotopic neighbors */
    3880                 :             :     }
    3881                 :             : 
    3882                 :             :     /*  count removed explicit terminal hydrogens attached to at[cur_at]. */
    3883                 :             :     /*  the result is num_explicit_H. */
    3884                 :             :     /*  Removed hydrogens are sorted in increasing isotopic shift order */
    3885   [ +  -  -  + ]:         199 :     if (at_removed_H && num_removed_H > 0)
    3886                 :             :     {
    3887         [ #  # ]:           0 :         for (j = 0; j < num_removed_H; j++)
    3888                 :             :         {
    3889         [ #  # ]:           0 :             if (at_removed_H[j].neighbor[0] == cur_at)
    3890                 :             :             {
    3891                 :           0 :                 k = at_removed_H[j].iso_atw_diff;
    3892                 :             :                 /*  iso_atw_diff values: H=>0, 1H=>1, D=2H=>2, T=3H=>3 */
    3893   [ #  #  #  #  :           0 :                 if (k < 0 || k > NUM_H_ISOTOPES || bIgnoreIsotopicH)
                   #  # ]
    3894                 :             :                 {
    3895                 :           0 :                     k = 0; /*  treat wrong H isotopes as non-isotopic H */
    3896                 :             :                 }
    3897                 :           0 :                 num_explicit_iso_H[k] ++;
    3898                 :           0 :                 index_H[num_explicit_H++] = j;
    3899                 :             :             }
    3900                 :             :         }
    3901                 :             :     }
    3902                 :             : 
    3903                 :             :     /*  coordinates initialization */
    3904                 :         199 :     num_z = 0;
    3905                 :         199 :     sum_xyz[0] = sum_xyz[1] = sum_xyz[2] = 0.0;
    3906                 :             : 
    3907                 :         199 :     at_coord_center[0]      =
    3908                 :         199 :         at_coord_center[1]  =
    3909                 :         199 :         at_coord_center[2]  =
    3910                 :             :         0.0;
    3911                 :             : 
    3912                 :             :         /*  fill out stereo center neighbors coordinates */
    3913                 :             :         /*  and obtain the parity from the geometry */
    3914                 :             : 
    3915         [ +  + ]:         597 :     for (k = 0, j1 = 0; k < 2; k++)
    3916                 :             :     {
    3917      [ +  +  - ]:         398 :         switch (k)
    3918                 :             :         {
    3919                 :             : 
    3920                 :         199 :             case 0:
    3921                 :             :                 /*   add coordinates of removed hydrogens */
    3922         [ -  + ]:         199 :                 for (j = 0; j < num_explicit_H; j++, j1++)
    3923                 :             :                 {
    3924                 :           0 :                     next_at = index_H[j];
    3925                 :             :                     /*  Use bond description located at removed_H atom */
    3926                 :             :                     /*  minus sign at get_z_coord: at_removed_H[] contains bonds TO at[cur_at], not FROM it. */
    3927                 :             :                     /*  Note: &at[(at_removed_H-at)+ next_at] == &at_removed_H[next_at] */
    3928                 :           0 :                     z = -get_z_coord( at,
    3929                 :           0 :                                       (int) ( at_removed_H - at ) + next_at,
    3930                 :             :                                       0 /*neighbor #*/,
    3931                 :             :                                       &nType,
    3932                 :           0 :                                       -( bPointedEdgeStereo & PES_BIT_POINT_EDGE_STEREO ) );
    3933   [ #  #  #  # ]:           0 :                     switch (nType)
    3934                 :             :                     {
    3935                 :           0 :                         case ZTYPE_EITHER:
    3936                 :           0 :                             parity = vABParityUnknown /*AB_PARITY_UNKN*/; /*  no parity: bond in "Either" direction. */
    3937                 :           0 :                             goto exit_function;
    3938                 :           0 :                         case ZTYPE_UP:
    3939                 :             :                         case ZTYPE_DOWN:
    3940                 :           0 :                             nType = -nType; /*  at_removed_H[] contains bonds TO the center, not from */
    3941                 :           0 :                             b2D++;
    3942                 :             :                             /*  no break; here */
    3943                 :           0 :                         case ZTYPE_3D:
    3944                 :           0 :                             num_z++;
    3945                 :             :                     }
    3946                 :             : 
    3947         [ #  # ]:           0 :                     if (j1 < MAX_NUM_STEREO_ATOM_NEIGH) /* djb-rwth: fixing oss-fuzz issue #71142 */
    3948                 :             :                     {
    3949                 :           0 :                         nSbNeighOrigAtNumb[j1] = at_removed_H[next_at].orig_at_number;
    3950                 :           0 :                         at_coord[j1][0] = at_removed_H[next_at].x - at[cur_at].x;
    3951                 :           0 :                         at_coord[j1][1] = at_removed_H[next_at].y - at[cur_at].y;
    3952                 :           0 :                         bond_len_xy[j1] = len2(at_coord[j1]);
    3953                 :             :                         /* bond_len_xy[j1] = sqrt(at_coord[j1][0]*at_coord[j1][0]+at_coord[j1][1]*at_coord[j1][1]); */
    3954         [ #  # ]:           0 :                         at_coord[j1][2] = (nType == ZTYPE_3D ? z : nType == ZTYPE_UP
    3955         [ #  # ]:           0 :                             ? bond_len_xy[j1] : nType == ZTYPE_DOWN
    3956         [ #  # ]:           0 :                             ? -bond_len_xy[j1] : 0.0);
    3957                 :             :                     }
    3958                 :             :                     else
    3959                 :             :                     {
    3960                 :           0 :                         break;
    3961                 :             :                     }
    3962                 :             :                 }
    3963                 :         199 :                 break;
    3964                 :         199 :             case 1:
    3965                 :             :                 /*  add all coordinates of other neighboring atoms */
    3966         [ +  + ]:         796 :                 for (j = 0; j < at[cur_at].valence; j++, j1++)
    3967                 :             :                 {
    3968                 :         597 :                     next_at = at[cur_at].neighbor[j];
    3969                 :         597 :                     z = get_z_coord( at, cur_at, j, &nType, ( bPointedEdgeStereo & PES_BIT_POINT_EDGE_STEREO ) );
    3970   [ -  +  -  + ]:         597 :                     switch (nType)
    3971                 :             :                     {
    3972                 :           0 :                         case ZTYPE_EITHER:
    3973                 :           0 :                             parity = vABParityUnknown /*AB_PARITY_UNKN*/; /*  unknown parity: bond in "Either" direction. */
    3974                 :           0 :                             goto exit_function;
    3975                 :         177 :                         case ZTYPE_UP:
    3976                 :             :                         case ZTYPE_DOWN:
    3977                 :         177 :                             b2D++;
    3978                 :         177 :                         case ZTYPE_3D:
    3979                 :         177 :                             num_z++;
    3980                 :             :                     }
    3981                 :             : 
    3982         [ +  - ]:         597 :                     if (j1 < MAX_NUM_STEREO_ATOM_NEIGH) /* djb-rwth: fixing oss-fuzz issue #71142 */
    3983                 :             :                     {
    3984                 :         597 :                         nSbNeighOrigAtNumb[j1] = at[next_at].orig_at_number;
    3985                 :         597 :                         at_coord[j1][0] = at[next_at].x - at[cur_at].x;
    3986                 :         597 :                         at_coord[j1][1] = at[next_at].y - at[cur_at].y;
    3987                 :         597 :                         bond_len_xy[j1] = len2(at_coord[j1]);
    3988                 :             :                         /* bond_len_xy[j1] = sqrt(at_coord[j1][0]*at_coord[j1][0]+at_coord[j1][1]*at_coord[j1][1]); */
    3989         [ +  - ]:        1194 :                         at_coord[j1][2] = (nType == ZTYPE_3D ? z :
    3990         [ +  + ]:        1048 :                             nType == ZTYPE_UP ? bond_len_xy[j1] :
    3991         [ +  + ]:         451 :                             nType == ZTYPE_DOWN ? -bond_len_xy[j1] : 0.0);
    3992                 :             :                     }
    3993                 :             :                     else
    3994                 :             :                     {
    3995                 :           0 :                         break;
    3996                 :             :                     }
    3997                 :             :                 }
    3998                 :         199 :                 break;
    3999                 :             :         }
    4000                 :             :     }
    4001                 :             :     /* j1 is the number of explicit neighbors (that is, all neighbors except implicit H) */
    4002   [ +  -  +  + ]:         199 :     b2D = ( b2D == num_z && num_z );  /*  1 => two-dimensional */
    4003                 :             : 
    4004         [ +  - ]:         199 :     if (MAX_NUM_STEREO_ATOM_NEIGH != at[cur_at].valence + num_explicit_H &&
    4005         [ -  + ]:         199 :          MAX_NUM_STEREO_ATOM_NEIGH - 1 != at[cur_at].valence + num_explicit_H)
    4006                 :             :     {
    4007                 :             :         /*  not enough geometry data to find the central atom parity */
    4008         [ #  # ]:           0 :         if (nMustHaveNumNeigh == at[cur_at].valence + at[cur_at].num_H &&
    4009         [ #  # ]:           0 :             at[cur_at].num_H > 1)
    4010                 :             :         {
    4011                 :             :             /*  only isotopic parity is possible; no non-isotopic parity */
    4012         [ #  # ]:           0 :             if (parity == vABParityUnknown /*AB_PARITY_UNKN*/)
    4013                 :             :             {
    4014                 :           0 :                 parity = -vABParityUnknown /*AB_PARITY_UNKN*/; /*  the user marked the center as "unknown" */
    4015                 :             :             }
    4016                 :             :             else
    4017                 :             :             {
    4018                 :           0 :                 parity = -AB_PARITY_UNDF; /*  not enough geometry; only isotopic parity is possible */
    4019                 :             :             }
    4020                 :             :         }
    4021                 :             :         else
    4022                 :             :         {
    4023                 :           0 :             parity = AB_PARITY_NONE;      /*  not a stereocenter at all */
    4024                 :             :         }
    4025                 :           0 :         goto exit_function;
    4026                 :             :     }
    4027                 :             :     /*  make all vector lengths equal to 1; exit if too short. 9-10-2002 */
    4028         [ +  + ]:         796 :     for (j = 0; j < j1; j++)
    4029                 :             :     {
    4030                 :         597 :         z = len3( at_coord[j] );
    4031         [ -  + ]:         597 :         if (z < MIN_BOND_LEN)
    4032                 :             :         {
    4033                 :             :             /* bond length is too small: use 0D parities */
    4034         [ #  # ]:           0 :             if (AB_PARITY_NONE == ( parity = GetStereocenter0DParity( pCG, at, cur_at,
    4035                 :             :                                                                       j1,nSbNeighOrigAtNumb,
    4036                 :             :                                                                       FlagSC_0D ) ))
    4037                 :             :             {
    4038                 :           0 :                 parity = AB_PARITY_UNDF;
    4039                 :             :             }
    4040                 :           0 :             goto exit_function;
    4041                 :             :         }
    4042                 :             : #if ( STEREO_CENTER_BONDS_NORM == 1 )
    4043                 :             :         else
    4044                 :             :         {
    4045                 :         597 :             mult3( at_coord[j], 1.0 / z, at_coord[j] );
    4046                 :             :         }
    4047                 :             : #endif
    4048   [ +  +  +  + ]:         597 :         rmax = j ? inchi_max( rmax, z ) : z;
    4049   [ +  +  +  + ]:         597 :         rmin = j ? inchi_min( rmin, z ) : z;
    4050                 :             :     }
    4051         [ -  + ]:         199 :     if (rmin / rmax < MIN_SINE)
    4052                 :             :     {
    4053                 :             :         /* bond ratio is too small: use 0D parities */
    4054         [ #  # ]:           0 :         if (AB_PARITY_NONE == ( parity = GetStereocenter0DParity( pCG, at, cur_at, j1,
    4055                 :             :             nSbNeighOrigAtNumb,
    4056                 :             :             FlagSC_0D ) ))
    4057                 :             :         {
    4058                 :           0 :             parity = AB_PARITY_UNDF;
    4059                 :             :         }
    4060                 :           0 :         goto exit_function;
    4061                 :             :     }
    4062         [ +  + ]:         796 :     for (j = 0; j < j1; j++)
    4063                 :             :     {
    4064                 :         597 :         add3( sum_xyz, at_coord[j], sum_xyz );
    4065                 :             :     }
    4066                 :             : 
    4067                 :             :     /*  Here j1 is a number of neighbors including explicit terminal isotopic H */
    4068                 :             :     /*  num_explicit_iso_H[0] = number of explicit non-isotopic hydrogen atom neighbors */
    4069                 :         199 :     j = j1;
    4070                 :             :     /*  Add Explicit Neighbor */
    4071         [ +  - ]:         199 :     if (j1 == MAX_NUM_STEREO_ATOM_NEIGH - 1)
    4072                 :             :     {
    4073                 :             :         /*  Add an explicit neighbor if possible */
    4074         [ -  + ]:         199 :         if (nMustHaveNumNeigh == MAX_NUM_STEREO_ATOM_NEIGH - 1)
    4075                 :             :         {
    4076                 :           0 :             bAddExplicitNeighbor = ADD_EXPLICIT_LONE_PAIR_NEIGH;
    4077                 :             :         }
    4078                 :             :         else
    4079                 :             :         {
    4080         [ +  - ]:         199 :             if (nMustHaveNumNeigh == MAX_NUM_STEREO_ATOM_NEIGH)
    4081                 :             :             {
    4082                 :             :                 /*  Check whether an explicit non-isotopic hydrogen can be added */
    4083                 :             :                 /*  to an atom that is a stereogenic atom */
    4084         [ +  - ]:         199 :                 if (1 == at[cur_at].num_H - num_explicit_H &&     /*  the atom has only one one implicit hydrogen */
    4085         [ +  - ]:         199 :                     1 == at[cur_at].num_H - tot_num_iso_H)
    4086                 :             :                 {
    4087                 :             :                     /*  this hydrogen is non-isotopic */
    4088                 :         199 :                     bAddExplicitNeighbor = ADD_EXPLICIT_HYDROGEN_NEIGH;
    4089                 :             :                 }
    4090                 :             :             }
    4091                 :             :         }
    4092                 :             :     }
    4093                 :             : 
    4094         [ +  - ]:         199 :     if (bAddExplicitNeighbor)
    4095                 :             :     {
    4096                 :             :         /***********************************************************
    4097                 :             :          * May happen only if (j1 == MAX_NUM_STEREO_ATOM_NEIGH-1)
    4098                 :             :          * 3 neighbors only, no H-neighbors. Create and add coordinates of an implicit H
    4099                 :             :          * or a fake 4th neighbor, that is, a lone pair
    4100                 :             :          */
    4101         [ -  + ]:         199 :         if (parity == vABParityUnknown /*AB_PARITY_UNKN*/)
    4102                 :             :         {
    4103                 :           0 :             goto exit_function;  /*  the user insists the parity is unknown and the isotopic */
    4104                 :             :                                  /*  composition of the neighbors does not contradict */
    4105                 :             :         }
    4106                 :             :         else
    4107                 :             :         {
    4108   [ +  +  -  + ]:         199 :             if (num_z == 0 || are_3_vect_in_one_plane( at_coord, vMinSine ))
    4109                 :             :             {
    4110                 :             :                 /*  "hydrogen down" rule is needed to resolve an ambiguity */
    4111         [ -  + ]:          22 :                 if (num_z > 0)
    4112                 :             :                 {
    4113                 :           0 :                     bAmbiguous |= AMBIGUOUS_STEREO;
    4114                 :             :                 }
    4115                 :             : #if ( APPLY_IMPLICIT_H_DOWN_RULE == 1 )  /* { */
    4116                 :             :                 /*  Although H should be at the top of the list, add it to the bottom. */
    4117                 :             :                 /*  This will be taken care of later by inverting parity 1<->2 */
    4118                 :             :                 at_coord[j][0] = 0.0;
    4119                 :             :                 at_coord[j][1] = 0.0;
    4120                 :             : #if ( STEREO_CENTER_BONDS_NORM == 1 )
    4121                 :             :                 at_coord[j][2] = -1.0;
    4122                 :             : #else
    4123                 :             :                 at_coord[j][2] = -( bond_len_xy[0] + bond_len_xy[1] + bond_len_xy[2] ) / 3.0;
    4124                 :             : #endif
    4125                 :             : #else /* } APPLY_IMPLICIT_H_DOWN_RULE { */
    4126                 :             : #if (ALWAYS_SET_STEREO_PARITY == 1)
    4127                 :             :                 parity = AB_PARITY_EVEN; /*  suppose atoms are pre-sorted (testing) */
    4128                 :             : #else
    4129                 :             :                 /* All 3 bonds are in one plane: try to get 0D parities */
    4130         [ +  - ]:          22 :                 if (AB_PARITY_NONE == ( parity = GetStereocenter0DParity( pCG, at, cur_at,
    4131                 :             :                                                                           j1,
    4132                 :             :                                                                           nSbNeighOrigAtNumb,
    4133                 :             :                                                                           FlagSC_0D ) ))
    4134                 :             :                 {
    4135                 :          22 :                     parity = AB_PARITY_UNDF;
    4136                 :             :                 }
    4137                 :             :                 /*parity =  AB_PARITY_UNDF;*/ /*  no parity can be calculated found */
    4138                 :             : #endif
    4139                 :          22 :                 goto exit_function;
    4140                 :             : #endif /* } APPLY_IMPLICIT_H_DOWN_RULE */
    4141                 :             :             }
    4142                 :             :             else
    4143                 :             :             {
    4144                 :             :                 /*  we have enough information to find implicit hydrogen coordinates */
    4145                 :             :                 /*
    4146                 :             :                 at_coord[j][0] = -sum_x;
    4147                 :             :                 at_coord[j][1] = -sum_y;
    4148                 :             :                 at_coord[j][2] = -sum_z;
    4149                 :             :                 */
    4150                 :             :                 /* copy3(sum_xyz, at_coord[j]); -- djb-rwth: removing copy3 function */
    4151                 :         177 :                 memcpy(at_coord[j], sum_xyz, sizeof(sum_xyz));
    4152                 :         177 :                 change_sign3( at_coord[j], at_coord[j] );
    4153                 :         177 :                 z = len3( at_coord[j] );
    4154                 :             : #if ( FIX_STEREO_SCALING_BUG == 1 )
    4155                 :             :                 if (z > 1.0)
    4156                 :             :                 {
    4157                 :             :                     rmax *= z;
    4158                 :             :                 }
    4159                 :             :                 else
    4160                 :             :                 {
    4161                 :             :                     rmin *= z;
    4162                 :             :                 }
    4163                 :             : #else
    4164                 :             :                 /* Comparing the original bond lengths to lenghts derived from normalized to 1 */
    4165                 :             :                 /* This bug leads to pronouncing legitimate stereogenic atoms */
    4166                 :             :                 /* connected by 3 bonds "undefined" if in a nicely drawn 2D structure */
    4167                 :             :                 /* bond lengths are about 20 or greater. Reported by Reinhard Dunkel 2005-08-05 */
    4168         [ +  - ]:         177 :                 if (bPointedEdgeStereo & PES_BIT_FIX_SP3_BUG)
    4169                 :             :                 {
    4170                 :             :                     /* coordinate scaling bug fixed here */
    4171         [ -  + ]:         177 :                     if (z > 1.0)
    4172                 :             :                     {
    4173                 :           0 :                         rmax *= z;
    4174                 :             :                     }
    4175                 :             :                     else
    4176                 :             :                     {
    4177                 :         177 :                         rmin *= z;
    4178                 :             :                     }
    4179                 :             :                 }
    4180                 :             :                 else
    4181                 :             :                 {
    4182                 :             :                     /* original InChI v.1 bug */
    4183         [ #  # ]:           0 :                     rmax = inchi_max( rmax, z );
    4184         [ #  # ]:           0 :                     rmin = inchi_min( rmin, z );
    4185                 :             :                 }
    4186                 :             : #endif
    4187   [ +  -  -  + ]:         177 :                 if (z < MIN_BOND_LEN || rmin / rmax < MIN_SINE)
    4188                 :             :                 {
    4189                 :             :                     /* the new 4th bond is too short: try to get 0D parities */
    4190         [ #  # ]:           0 :                     if (AB_PARITY_NONE == ( parity = GetStereocenter0DParity( pCG, at, cur_at, j1, nSbNeighOrigAtNumb, FlagSC_0D ) ))
    4191                 :             :                     {
    4192                 :           0 :                         parity = AB_PARITY_UNDF;
    4193                 :             :                     }
    4194                 :           0 :                     goto exit_function;
    4195                 :             :                 }
    4196                 :             : #if ( STEREO_CENTER_BOND4_NORM == 1 )
    4197                 :             :                 else
    4198                 :             :                 {
    4199                 :             :                     mult3( at_coord[j], 1.0 / z, at_coord[j] );
    4200                 :             :                 }
    4201                 :             : #endif
    4202                 :             :             }
    4203                 :             :         }
    4204                 :             :     }
    4205                 :             : 
    4206         [ #  # ]:           0 :     else if (j1 != MAX_NUM_STEREO_ATOM_NEIGH)
    4207                 :             :     {
    4208         [ #  # ]:           0 :         if (parity == vABParityUnknown /*AB_PARITY_UNKN*/)
    4209                 :             :         {
    4210                 :           0 :             parity = -AB_PARITY_UNDF; /*  isotopic composition of H-neighbors contradicts 'unknown' */
    4211                 :             :         }
    4212                 :           0 :         goto exit_function;
    4213                 :             :     }
    4214                 :             : 
    4215                 :             :     else /*  j1 == MAX_NUM_STEREO_ATOM_NEIGH */
    4216                 :             :     {
    4217   [ #  #  #  # ]:           0 :         if (num_z == 0 || are_4at_in_one_plane( at_coord, vMinSine ))
    4218                 :             :         {
    4219                 :             :             /*  all four neighours in xy plane: undefined geometry. */
    4220         [ #  # ]:           0 :             if (num_z > 0)
    4221                 :             :             {
    4222                 :           0 :                 bAmbiguous |= AMBIGUOUS_STEREO;
    4223                 :             :             }
    4224         [ #  # ]:           0 :             if (parity != vABParityUnknown /*AB_PARITY_UNKN*/)
    4225                 :             :             {
    4226                 :             : #if (ALWAYS_SET_STEREO_PARITY == 1)
    4227                 :             :                 parity = AB_PARITY_EVEN; /*  suppose atoms are pre-sorted (testing) */
    4228                 :             : #else
    4229                 :             :                 /* All 4 bonds are in one plane: try to get 0D parities */
    4230         [ #  # ]:           0 :                 if (AB_PARITY_NONE == ( parity = GetStereocenter0DParity( pCG, at, cur_at, j1, nSbNeighOrigAtNumb, FlagSC_0D ) ))
    4231                 :             :                 {
    4232                 :           0 :                     parity = AB_PARITY_UNDF;
    4233                 :             :                 }
    4234   [ #  #  #  # ]:           0 :                 else if (ATOM_PARITY_WELL_DEF( parity ))
    4235                 :             :                 {
    4236                 :           0 :                     bAmbiguous &= ~AMBIGUOUS_STEREO; /* 0D parity has resolved the ambiguity */
    4237                 :             :                 }
    4238                 :             : #endif
    4239                 :             :             }
    4240                 :           0 :             goto exit_function;
    4241                 :             :         }
    4242                 :             :     }
    4243                 :             : 
    4244                 :             :     /***********************************************************
    4245                 :             :     * At this point we have 4 neighboring atoms.
    4246                 :             :     * check for tetrahedral ambiguity in 2D case
    4247                 :             :     */
    4248         [ +  - ]:         177 :     if (b2D)
    4249                 :             :     {
    4250                 :             : 
    4251                 :         177 :         n2DTetrahedralAmbiguity = Get2DTetrahedralAmbiguity( pCG,at_coord,
    4252                 :             :                                                              bAddExplicitNeighbor,
    4253                 :             :                                                              ( bPointedEdgeStereo & PES_BIT_FIX_SP3_BUG ),
    4254                 :             :                                                              vMinAngle );
    4255                 :             : 
    4256         [ +  - ]:         177 :         if (0 < n2DTetrahedralAmbiguity)
    4257                 :             :         {
    4258         [ -  + ]:         177 :             if (T2D_WARN & n2DTetrahedralAmbiguity)
    4259                 :             :             {
    4260                 :           0 :                 bAmbiguous |= AMBIGUOUS_STEREO;
    4261                 :             :             }
    4262         [ -  + ]:         177 :             if (T2D_UNDF & n2DTetrahedralAmbiguity)
    4263                 :             :             {
    4264         [ #  # ]:           0 :                 if (parity != vABParityUnknown /*AB_PARITY_UNKN*/)
    4265                 :             :                 {
    4266                 :             : #if (ALWAYS_SET_STEREO_PARITY == 1)
    4267                 :             :                     parity = AB_PARITY_EVEN; /*  suppose atoms are pre-sorted (testing) */
    4268                 :             : #else
    4269                 :           0 :                     parity = AB_PARITY_UNDF; /*  no parity */
    4270                 :             : #endif
    4271                 :             :                 }
    4272                 :           0 :                 goto exit_function;
    4273                 :             :             }
    4274                 :             :         }
    4275         [ #  # ]:           0 :         else if (n2DTetrahedralAmbiguity < 0)
    4276                 :             :         {
    4277                 :           0 :             bAmbiguous |= AMBIGUOUS_STEREO_ERROR; /*  error */
    4278                 :           0 :             parity = AB_PARITY_UNDF;
    4279                 :           0 :             goto exit_function;
    4280                 :             :         }
    4281                 :             :     }
    4282                 :             : 
    4283                 :             :     /************************************************************/
    4284                 :             :     /*  Move coordinates origin to the neighbor #0 */
    4285         [ +  + ]:         708 :     for (j = 1; j < MAX_NUM_STEREO_ATOM_NEIGH; j++)
    4286                 :             :     {
    4287                 :         531 :         diff3( at_coord[j], at_coord[0], at_coord[j] );
    4288                 :             :     }
    4289                 :         177 :     diff3( at_coord_center, at_coord[0], at_coord_center );
    4290                 :             : 
    4291                 :             :     /*
    4292                 :             :     for ( k = 0; k < 3; k++ )
    4293                 :             :     {
    4294                 :             :         for ( j = 1; j < MAX_NUM_STEREO_ATOM_NEIGH; j ++ )
    4295                 :             :         {
    4296                 :             :             at_coord[j][k] -= at_coord[0][k];
    4297                 :             :         }
    4298                 :             :         at_coord_center[k] -= at_coord[0][k];
    4299                 :             :     }
    4300                 :             :     */
    4301                 :             : 
    4302                 :             : 
    4303                 :             :     /********************************************************
    4304                 :             :      *  Find the central (cur_at) atom's parity
    4305                 :             :      *  (orientation of atoms #1-3 when looking from #0)
    4306                 :             :      ********************************************************/
    4307                 :         177 :     triple_product = triple_prod_and_min_abs_sine2( &at_coord[1], at_coord_center, bAddExplicitNeighbor, &min_sine, &bAmbiguous, vMinSine );
    4308                 :             : 
    4309                 :             :     /*
    4310                 :             :      *  Check for tetrahedral ambiguity -- leave it out for now
    4311                 :             :      */
    4312   [ +  -  -  +  :         177 :     if (fabs( triple_product ) > ZERO_FLOAT && ( min_sine > vMinSine || (fabs( min_sine ) > ZERO_FLOAT && ( n2DTetrahedralAmbiguity & T2D_OKAY )) )) /* djb-rwth: addressing LLVM warning */
             -  -  -  - ]
    4313                 :             :     {
    4314                 :             :          /* Even => sorted in correct order, Odd=>transposed */
    4315         [ +  + ]:         177 :         parity = triple_product > 0.0 ? AB_PARITY_EVEN : AB_PARITY_ODD;
    4316                 :             :         /* if ( num_explicit_H && at[cur_at].removed_H_parity % 2 )  */
    4317                 :             :               /* odd transposition of the removed implicit H */
    4318                 :             :         /*     out_at[cur_at].parity = 3 - out_at[cur_at].parity; */
    4319                 :             : 
    4320                 :             :         /*  moved; see below */
    4321                 :             :         /* out_at[cur_at].bAmbiguousStereo |= bAmbiguous; */
    4322                 :             :         /* at[cur_at].bAmbiguousStereo |= bAmbiguous; */
    4323                 :             : 
    4324                 :             :         /*  for 4 attached atoms, moving the implicit H from index=3 to index=0 */
    4325                 :             :         /*  can be done in odd number (3) transpositions: (23)(12)(01), which inverts the parity */
    4326         [ +  - ]:         177 :         if (j1 == MAX_NUM_STEREO_ATOM_NEIGH - 1)
    4327                 :             :         {
    4328                 :         177 :             parity = 3 - parity;
    4329                 :             :         }
    4330                 :             :     }
    4331                 :             :     else
    4332                 :             :     {
    4333                 :             : #if (ALWAYS_SET_STEREO_PARITY == 1)
    4334                 :             :         parity = AT_PARITY_EVEN; /*  suppose atoms are pre-sorted (testing) */
    4335                 :             : #else
    4336         [ #  # ]:           0 :         if (num_z > 0)
    4337                 :             :         {
    4338                 :           0 :             bAmbiguous |= AMBIGUOUS_STEREO;
    4339                 :             :         }
    4340                 :           0 :         parity = AB_PARITY_UNDF; /*  no parity: 4 bonds are in one plane. */
    4341                 :             : #endif
    4342                 :             :     }
    4343                 :             : 
    4344                 :         619 : exit_function:
    4345                 :             : 
    4346         [ +  + ]:         619 :     if (parity)
    4347                 :             :     {
    4348                 :         199 :         out_at[cur_at].bAmbiguousStereo |= bAmbiguous;
    4349                 :         199 :         at[cur_at].bAmbiguousStereo |= bAmbiguous;
    4350                 :             :     }
    4351                 :             : 
    4352                 :             :     /*  Non-isotopic parity */
    4353   [ +  +  +  + ]:         619 :     if (at[cur_at].num_H > 1 || parity <= 0)
    4354                 :             :     {
    4355                 :             :         ; /*  no non-isotopic parity */
    4356                 :             :     }
    4357                 :             :     else
    4358                 :             :     {
    4359                 :         199 :         out_at[cur_at].parity = parity;
    4360                 :             :     }
    4361                 :             : 
    4362                 :             :     /*  isotopic parity */
    4363   [ +  -  -  + ]:         619 :     if (parity == -AB_PARITY_UNDF || parity == -vABParityUnknown /*AB_PARITY_UNKN*/)
    4364                 :             :     {
    4365                 :           0 :         parity = -parity;
    4366                 :             :     }
    4367         [ -  + ]:         619 :     if (parity < 0)
    4368                 :             :     {
    4369                 :           0 :         parity = AB_PARITY_NONE;
    4370                 :             :     }
    4371                 :         619 :     out_at[cur_at].parity2 = parity;
    4372                 :             : 
    4373                 :         619 :     parity = PARITY_VAL( out_at[cur_at].parity );
    4374   [ +  +  +  + ]:         619 :     out_at[cur_at].stereo_atom_parity = ATOM_PARITY_WELL_DEF( parity ) ? AB_PARITY_CALC : parity;
    4375                 :         619 :     parity = PARITY_VAL( out_at[cur_at].parity2 );
    4376   [ +  +  +  + ]:         619 :     out_at[cur_at].stereo_atom_parity2 = ATOM_PARITY_WELL_DEF( parity ) ? AB_PARITY_CALC : parity;
    4377                 :             :     /*
    4378                 :             :     out_at[cur_at].parity2 = out_at[cur_at].parity; // save for stereo + isotopic canon.
    4379                 :             :     if ( out_at[cur_at].parity ) {
    4380                 :             :         if ( num_explicit_H > 1 || j1 == MAX_NUM_STEREO_ATOM_NEIGH-1 && num_explicit_H ) {
    4381                 :             :             //              X   H      X
    4382                 :             :             // for example,  >C<   or   >C-D
    4383                 :             :             //              Y   D      Y
    4384                 :             :             // parity exists for stereo + isotopic atoms canonicalization only
    4385                 :             :             out_at[cur_at].parity  = 0;
    4386                 :             :         }
    4387                 :             :     }
    4388                 :             :     returning 0 means this can be an adjacent to a stereogenic bond atom
    4389                 :             :     */
    4390                 :             : 
    4391                 :         619 :     return (int) out_at[cur_at].parity2;
    4392                 :             : }
    4393                 :             : #undef ADD_EXPLICIT_HYDROGEN_NEIGH
    4394                 :             : #undef ADD_EXPLICIT_LONE_PAIR_NEIGH
    4395                 :             : 
    4396                 :             : 
    4397                 :             : /****************************************************************************/
    4398                 :          69 : int set_stereo_parity( CANON_GLOBALS *pCG,
    4399                 :             :                        inp_ATOM* at,
    4400                 :             :                        sp_ATOM* at_output,
    4401                 :             :                        int num_at,
    4402                 :             :                        int num_removed_H,
    4403                 :             :                        int *nMaxNumStereoAtoms,
    4404                 :             :                        int *nMaxNumStereoBonds,
    4405                 :             :                        INCHI_MODE nMode,
    4406                 :             :                        int bPointedEdgeStereo,
    4407                 :             :                        int vABParityUnknown,
    4408                 :             :                        int bLooseTSACheck,
    4409                 :             :                        int bStereoAtZz )
    4410                 :             : {
    4411                 :          69 :     int num_3D_stereo_atoms = 0;
    4412                 :          69 :     int num_stereo_bonds = 0; /* added to fix allene stereo bug reported for FClC=C=CFCl by Burt Leland - 2009-02-05 DT */
    4413                 :             : 
    4414                 :          69 :     int i, is_stereo, num_stereo, max_stereo_atoms = 0, max_stereo_bonds = 0;
    4415                 :          69 :     QUEUE *q = NULL;
    4416                 :          69 :     AT_RANK *nAtomLevel = NULL;
    4417                 :          69 :     S_CHAR  *cSource = NULL;
    4418                 :          69 :     AT_RANK min_sb_ring_size = 0;
    4419                 :             : 
    4420                 :             :     /**********************************************************
    4421                 :             :      *
    4422                 :             :      * Note: this parity reflects only relative positions of
    4423                 :             :      *       the atoms-neighbors and their ordering in the
    4424                 :             :      *       lists of neighbors.
    4425                 :             :      *
    4426                 :             :      *       To obtain the actual parity, the parity of a number
    4427                 :             :      *       of neighbors transpositions (to obtain a sorted
    4428                 :             :      *       list of numbers assigned to the atoms) should be
    4429                 :             :      *       added.
    4430                 :             :      *
    4431                 :             :      **********************************************************/
    4432                 :             : 
    4433                 :             :     /*********************************************************************************
    4434                 :             : 
    4435                 :             :      An example of parity=1 for stereogenic center, tetrahedral asymmetric atom
    4436                 :             : 
    4437                 :             : 
    4438                 :             : 
    4439                 :             :                   (1)
    4440                 :             :                    |
    4441                 :             :                    |
    4442                 :             :                [C] |
    4443                 :             :                    |
    4444                 :             :          (2)------(0)
    4445                 :             :                   /
    4446                 :             :                 /
    4447                 :             :               /
    4448                 :             :             /
    4449                 :             :          (3)
    4450                 :             : 
    4451                 :             : 
    4452                 :             :      Notation: (n) is a tetrahedral atom neighbor; n is an index of a neighbor in
    4453                 :             :      the central_at->neighbor[] array : neighbor atom number is central_at->neighbor[n].
    4454                 :             : 
    4455                 :             :      (0)-(1), (0)-(2), (0)-(3) are lines connecting atom [C] neighbors to neighbor (0)
    4456                 :             :      (0), (1) and (2) are in the plane
    4457                 :             :      (0)-(3) is directed from the plain to the viewer
    4458                 :             :      [C] is somewhere between (0), (1), (2), (3)
    4459                 :             :      Since (1)-(2)-(3)  are in a clockwise order when looking from (0), parity is 2, or even;
    4460                 :             :      otherwise parity would be 1, or odd.
    4461                 :             : 
    4462                 :             :     **********************************************************************************
    4463                 :             : 
    4464                 :             :       Examples of a stereogenic bond.
    4465                 :             : 
    4466                 :             :       Notation:   [atom number], (index of a neighbor):
    4467                 :             :                   [1] and [2] are atoms connected by the stereogenic bond
    4468                 :             :                   numbers in () are indexes of neighbors of [1] or [2].
    4469                 :             :                   (12 x 16)z = z-component of [1]-[2] and [1]-[6] cross-product
    4470                 :             : 
    4471                 :             :                                      atom [1]                     atom [2]
    4472                 :             :      [8]                    [4]      prod01 = (12 x 16)z < 0      prod01 = (21 x 24)z < 0
    4473                 :             :        \                    /        prod02 = (12 x 18)z > 0      prod02 = (21 x 25)z > 0
    4474                 :             :         (2)               (1)        0 transpositions because     0 transpositions because
    4475                 :             :           \              /           double bond is in 0 posit.   double bond is in 0 position
    4476                 :             :           [1]==(0)(0)==[2]           0 = (prod01 > prod02)        0 = (prod01 > prod02)
    4477                 :             :           /              \
    4478                 :             :         (1)               (2)        result: parity = 2, even     result: parity=2, even
    4479                 :             :        /                    \
    4480                 :             :      [6]                    [5]
    4481                 :             : 
    4482                 :             : 
    4483                 :             : 
    4484                 :             :                                      atom [1]                     atom [2]
    4485                 :             :      [8]                    [5]      prod01 = (12 x 18)z > 0      prod01 = (21 x 24)z > 0
    4486                 :             :        \                    /        prod02 = (12 x 16)z < 0      prod02 = (21 x 25)z < 0
    4487                 :             :         (0)               (2)        2 transpositions to move     1 transposition to move
    4488                 :             :           \              /           at [2] from 2 to 0 pos.      at [1] from 1 to 0 position
    4489                 :             :           [1]==(2)(1)==[2]           1 = (prod01 > prod02)        1 = (prod01 > prod02)
    4490                 :             :           /              \
    4491                 :             :         (1)               (0)        result: parity = (1+2)       result: parity=(1+1)
    4492                 :             :        /                    \        2-(1+2)%2 = 1, odd           2-(1+1)%2 = 2, even
    4493                 :             :      [6]                    [4]
    4494                 :             : 
    4495                 :             : 
    4496                 :             :     ***********************************************************************************
    4497                 :             :     Note: atoms' numbers [1], [2], [4],... are not used to calculate parity at this
    4498                 :             :           point. They will be used for each numbering in the canonicalization.
    4499                 :             :     Note: parity=3 for a stereo atom means entered undefined bond direction
    4500                 :             :           parity=4 for an atom means parity cannot be determined from the given geometry
    4501                 :             :     ***********************************************************************************/
    4502                 :             : 
    4503   [ +  -  -  + ]:          69 :     if (!at_output || !at)
    4504                 :             :     {
    4505                 :           0 :         return -1;
    4506                 :             :     }
    4507                 :             : 
    4508                 :             :     /*  Clear stereo descriptors */
    4509         [ +  + ]:         688 :     for (i = 0; i < num_at; i++)
    4510                 :             :     {
    4511                 :         619 :         at_output[i].parity = 0;
    4512                 :         619 :         at_output[i].parity2 = 0;
    4513                 :         619 :         memset( &at_output[i].stereo_bond_neighbor[0], 0, sizeof( at_output[0].stereo_bond_neighbor ) ); /* djb-rwth: memset_s C11/Annex K variant? */
    4514                 :         619 :         memset( &at_output[i].stereo_bond_neighbor2[0], 0, sizeof( at_output[0].stereo_bond_neighbor2 ) ); /* djb-rwth: memset_s C11/Annex K variant? */
    4515                 :         619 :         memset( &at_output[i].stereo_bond_ord[0], 0, sizeof( at_output[0].stereo_bond_ord ) ); /* djb-rwth: memset_s C11/Annex K variant? */
    4516                 :         619 :         memset( &at_output[i].stereo_bond_ord2[0], 0, sizeof( at_output[0].stereo_bond_ord2 ) ); /* djb-rwth: memset_s C11/Annex K variant? */
    4517                 :         619 :         memset( &at_output[i].stereo_bond_z_prod[0], 0, sizeof( at_output[0].stereo_bond_z_prod ) ); /* djb-rwth: memset_s C11/Annex K variant? */
    4518                 :         619 :         memset( &at_output[i].stereo_bond_z_prod2[0], 0, sizeof( at_output[0].stereo_bond_z_prod2 ) ); /* djb-rwth: memset_s C11/Annex K variant? */
    4519                 :         619 :         memset( &at_output[i].stereo_bond_parity[0], 0, sizeof( at_output[0].stereo_bond_parity ) ); /* djb-rwth: memset_s C11/Annex K variant? */
    4520                 :         619 :         memset( &at_output[i].stereo_bond_parity2[0], 0, sizeof( at_output[0].stereo_bond_parity2 ) ); /* djb-rwth: memset_s C11/Annex K variant? */
    4521                 :             :     }
    4522                 :             : 
    4523                 :             :     /*  Estimate max numbers of stereo atoms and bonds if isotopic H are added */
    4524   [ -  +  -  - ]:          69 :     if (nMaxNumStereoAtoms || nMaxNumStereoBonds)
    4525                 :             :     {
    4526         [ +  + ]:         688 :         for (i = 0; i < num_at; i++) /* djb-rwth: removing redundant code */
    4527                 :             :         {
    4528                 :             :             int num;
    4529                 :         619 :             num = can_be_a_stereo_atom_with_isotopic_H( at, i, bPointedEdgeStereo, bStereoAtZz );
    4530         [ +  + ]:         619 :             if (num)
    4531                 :             :             {
    4532                 :         392 :                 max_stereo_atoms += num;
    4533                 :             :             }
    4534                 :             :             else
    4535                 :             :             {
    4536         [ +  + ]:         227 :                 if (( num = can_be_a_stereo_bond_with_isotopic_H( at, i, nMode ) ))
    4537                 :             :                 {
    4538                 :             :                     /*  accept cumulenes */
    4539                 :          14 :                     max_stereo_bonds += num;
    4540                 :             :                 }
    4541                 :             :             }
    4542                 :             :         }
    4543         [ +  - ]:          69 :         if (nMaxNumStereoAtoms)
    4544                 :             :         {
    4545                 :          69 :             *nMaxNumStereoAtoms = max_stereo_atoms;
    4546                 :             :         }
    4547         [ +  - ]:          69 :         if (nMaxNumStereoBonds)
    4548                 :             :         {
    4549                 :          69 :             *nMaxNumStereoBonds = max_stereo_bonds;
    4550                 :             :         }
    4551                 :             :     }
    4552                 :             : 
    4553                 :             :     /*  Calculate stereo descriptors */
    4554                 :             : #if ( MIN_SB_RING_SIZE > 0 )
    4555                 :          69 :     min_sb_ring_size = (AT_RANK) ( ( ( nMode & REQ_MODE_MIN_SB_RING_MASK ) >> REQ_MODE_MIN_SB_RING_SHFT ) & AT_RANK_MASK );
    4556         [ +  - ]:          69 :     if (min_sb_ring_size >= 3)
    4557                 :             :     {
    4558                 :             :         /* Create BFS data structure for finding for each stereo bond its min. ring sizes */
    4559                 :          69 :         q = QueueCreate( num_at + 1, sizeof( qInt ) );
    4560                 :          69 :         nAtomLevel = (AT_RANK*) inchi_calloc( num_at, sizeof( nAtomLevel[0] ) );
    4561                 :          69 :         cSource = (S_CHAR *) inchi_calloc( num_at, sizeof( cSource[0] ) );
    4562   [ +  -  +  -  :          69 :         if (!q || !cSource || !nAtomLevel)
                   -  + ]
    4563                 :             :         {
    4564                 :           0 :             q = QueueDelete(q); /* djb-rwth: fixing coverity ID #499562 */
    4565         [ #  # ]:           0 :             inchi_free(nAtomLevel); /* djb-rwth: avoiding memory leak */
    4566         [ #  # ]:           0 :             inchi_free(cSource); /* djb-rwth: avoiding memory leak */
    4567                 :           0 :             num_3D_stereo_atoms = CT_OUT_OF_RAM;
    4568                 :           0 :             goto exit_function;
    4569                 :             :         }
    4570                 :             :     }
    4571                 :             :     else
    4572                 :             :     {
    4573                 :           0 :         min_sb_ring_size = 2;
    4574                 :             :     }
    4575                 :             : #endif
    4576                 :             : 
    4577                 :             :     /* Main cycle: set stereo parities */
    4578         [ +  + ]:         688 :     for (i = 0, num_stereo = 0; i < num_at; i++)
    4579                 :             :     {
    4580                 :         619 :         is_stereo = set_stereo_atom_parity( pCG, at_output, at, i, at + num_at, num_removed_H,
    4581                 :             :                                             bPointedEdgeStereo, vABParityUnknown, bLooseTSACheck, bStereoAtZz );
    4582         [ +  + ]:         619 :         if (is_stereo)
    4583                 :             :         {
    4584   [ +  -  +  + ]:         199 :             num_3D_stereo_atoms += ATOM_PARITY_WELL_DEF( is_stereo );
    4585                 :             :         }
    4586                 :             :         else
    4587                 :             :         {
    4588                 :         420 :             is_stereo = set_stereo_bonds_parity( at_output, at, i, at + num_at,
    4589                 :             :                                                  num_removed_H, nMode,q,
    4590                 :             :                                                  nAtomLevel, cSource,
    4591                 :             :                                                  min_sb_ring_size,
    4592                 :             :                                                  bPointedEdgeStereo,
    4593                 :             :                                                  vABParityUnknown );
    4594   [ +  -  -  + ]:         420 :             if (RETURNED_ERROR( is_stereo ))
    4595                 :             :             {
    4596                 :           0 :                 num_3D_stereo_atoms = is_stereo;
    4597                 :           0 :                 break;
    4598                 :             :             }
    4599                 :         420 :             num_stereo_bonds += ( is_stereo != 0 ); /* added to fix bug reported by Burt Leland - 2009-02-05 DT */
    4600                 :             :         }
    4601                 :         619 :         num_stereo += ( is_stereo != 0 );
    4602                 :             :         /* djb-rwth: removing redundant code */
    4603                 :             :     }
    4604                 :             : 
    4605                 :             :     /* Added to fix bug reported by Burt Leland - 2009-02-05 DT */
    4606   [ -  +  -  - ]:          69 :     if (max_stereo_atoms < num_3D_stereo_atoms && nMaxNumStereoAtoms)
    4607                 :             :     {
    4608                 :           0 :         *nMaxNumStereoAtoms = num_3D_stereo_atoms;
    4609                 :             :     }
    4610   [ -  +  -  - ]:          69 :     if (max_stereo_bonds < num_stereo_bonds && nMaxNumStereoBonds)
    4611                 :             :     {
    4612                 :           0 :         *nMaxNumStereoBonds = num_stereo_bonds;
    4613                 :             :     }
    4614                 :             : 
    4615                 :             :     /*
    4616                 :             :     if ( (nMode & REQ_MODE_SC_IGN_ALL_UU )
    4617                 :             :     REQ_MODE_SC_IGN_ALL_UU
    4618                 :             :     REQ_MODE_SB_IGN_ALL_UU
    4619                 :             :     */
    4620                 :             : 
    4621                 :             : #if ( MIN_SB_RING_SIZE > 0 )
    4622         [ +  - ]:          69 :     if (q)
    4623                 :             :     {
    4624                 :          69 :         q = QueueDelete( q ); /* djb-rwth: ignoring LLVM warning: variable used to store function return value */
    4625                 :             :     }
    4626         [ +  - ]:          69 :     if (nAtomLevel)
    4627                 :             :     {
    4628         [ +  - ]:          69 :         inchi_free( nAtomLevel );
    4629                 :             :     }
    4630         [ -  + ]:          69 :     if (cSource)
    4631                 :             :     {
    4632         [ -  + ]:          69 :         inchi_free( cSource );
    4633                 :             :     }
    4634                 :             : 
    4635                 :           0 : exit_function:
    4636                 :             : #endif
    4637                 :             : 
    4638                 :          69 :     return num_3D_stereo_atoms;
    4639                 :             : }
    4640                 :             : 
    4641                 :             : 
    4642                 :             : /*****************************************************************
    4643                 :             :  *  Functions that disconnect bonds
    4644                 :             :  *
    4645                 :             :  *=== During Preprocessing ===
    4646                 :             :  *
    4647                 :             :  *  RemoveInpAtBond
    4648                 :             :  *  DisconnectMetalSalt (is not aware of bond parities)
    4649                 :             :  *  DisconnectAmmoniumSalt
    4650                 :             :  *
    4651                 :             :  *=== Before Normalization ===
    4652                 :             :  *
    4653                 :             :  *  remove_terminal_HDT
    4654                 :             :  *
    4655                 :             :  *=== During the Normalization ===
    4656                 :             :  *
    4657                 :             :  *  AddOrRemoveExplOrImplH
    4658                 :             :  *
    4659                 :             :  *****************************************************************/
    4660                 :             : 
    4661                 :             : 
    4662                 :             : /****************************************************************************/
    4663                 :           1 : int ReconcileAllCmlBondParities( inp_ATOM *at,
    4664                 :             :                                  int num_atoms,
    4665                 :             :                                  int bDisconnected )
    4666                 :             : {
    4667                 :           1 :     int i, ret = 0;
    4668                 :           1 :     S_CHAR *visited = (S_CHAR*) inchi_calloc( num_atoms, sizeof( *visited ) );
    4669         [ -  + ]:           1 :     if (!visited)
    4670                 :             :     {
    4671                 :           0 :         return -1; /* out of RAM */
    4672                 :             :     }
    4673         [ +  + ]:          12 :     for (i = 0; i < num_atoms; i++)
    4674                 :             :     {
    4675   [ -  +  -  -  :          11 :         if (at[i].sb_parity[0] && !visited[i] && !( bDisconnected && is_el_a_metal( at[i].el_number ) ))
             -  -  -  - ]
    4676                 :             :         {
    4677         [ #  # ]:           0 :             if ((ret = ReconcileCmlIncidentBondParities( at, i, -1, visited, bDisconnected ))) /* djb-rwth: addressing LLVM warning */
    4678                 :             :             {
    4679                 :           0 :                 break; /* error */
    4680                 :             :             }
    4681                 :             :         }
    4682                 :             :     }
    4683         [ +  - ]:           1 :     inchi_free( visited );
    4684                 :             : 
    4685                 :           1 :     return ret;
    4686                 :             : }
    4687                 :             : 
    4688                 :             : 
    4689                 :             : /****************************************************************************/
    4690                 :           0 : int ReconcileCmlIncidentBondParities( inp_ATOM *at,
    4691                 :             :                                       int cur_atom,
    4692                 :             :                                       int prev_atom,
    4693                 :             :                                       S_CHAR *visited,
    4694                 :             :                                       int bDisconnected )
    4695                 :             : {
    4696                 :             :     /* visited = 0 or parity => atom has not been visited
    4697                 :             :                  10 + parity => currently is on the stack + its final parity
    4698                 :             :                  20 + parity => has been visited; is not on the stack anymore + its final parity */
    4699                 :           0 :     int i, j, nxt_atom, ret = 0, len;
    4700                 :             :     int icur2nxt, icur2neigh;   /* cur atom neighbors */
    4701                 :             :     int inxt2cur, inxt2neigh;   /* next atom neighbors */
    4702                 :             :     int cur_parity, nxt_parity;
    4703                 :             :     int cur_order_parity, nxt_order_parity, cur_sb_parity, nxt_sb_parity, bCurMask, bNxtMask;
    4704                 :             :     /* !(bDisconnected && is_el_a_metal(at[i].el_number) */
    4705                 :             : 
    4706         [ #  # ]:           0 :     if (at[cur_atom].valence > MAX_NUM_STEREO_BONDS)
    4707                 :             :     {
    4708                 :           0 :         return 0; /* ignore */
    4709                 :             :     }
    4710                 :             : 
    4711         [ #  # ]:           0 :     if (!at[cur_atom].sb_parity[0])
    4712                 :             :     {
    4713                 :           0 :         return 1; /* wrong call */
    4714                 :             :     }
    4715                 :             : 
    4716         [ #  # ]:           0 :     if (visited[cur_atom] >= 10)
    4717                 :             :     {
    4718                 :           0 :         return 2; /* program error */
    4719                 :             :     }
    4720                 :             : 
    4721                 :           0 :     cur_parity = visited[cur_atom] % 10;
    4722                 :             : 
    4723                 :           0 :     visited[cur_atom] += 10;
    4724                 :             : 
    4725   [ #  #  #  # ]:           0 :     for (i = 0; i < MAX_NUM_STEREO_BONDS && at[cur_atom].sb_parity[i]; i++)
    4726                 :             :     {
    4727                 :           0 :         icur2nxt = (int) at[cur_atom].sb_ord[i];
    4728                 :           0 :         len = get_opposite_sb_atom( at, cur_atom, icur2nxt, &nxt_atom, &inxt2cur, &j );
    4729         [ #  # ]:           0 :         if (!len)
    4730                 :             :         {
    4731                 :           0 :             return 4; /* could not find the opposite atom: bond parity data error */
    4732                 :             :         }
    4733         [ #  # ]:           0 :         if (nxt_atom == prev_atom)
    4734                 :             :         {
    4735                 :           0 :             continue;
    4736                 :             :         }
    4737         [ #  # ]:           0 :         if (visited[nxt_atom] >= 20)
    4738                 :             :         {
    4739                 :           0 :             continue; /* back edge, second visit: ignore */
    4740                 :             :         }
    4741         [ #  # ]:           0 :         if (at[nxt_atom].valence > MAX_NUM_STEREO_BONDS)
    4742                 :             :         {
    4743                 :           0 :             continue; /* may be treated only after metal disconnection */
    4744                 :             :         }
    4745                 :             : 
    4746   [ #  #  #  # ]:           0 :         if (bDisconnected && ( at[cur_atom].sb_parity[i] & SB_PARITY_FLAG ))
    4747                 :             :         {
    4748                 :           0 :             cur_sb_parity = ( at[cur_atom].sb_parity[i] >> SB_PARITY_SHFT );
    4749                 :           0 :             bCurMask = 3 << SB_PARITY_SHFT;
    4750                 :             :         }
    4751                 :             :         else
    4752                 :             :         {
    4753                 :           0 :             cur_sb_parity = ( at[cur_atom].sb_parity[i] & SB_PARITY_MASK );
    4754                 :           0 :             bCurMask = 3;
    4755                 :             :         }
    4756   [ #  #  #  # ]:           0 :         if (bDisconnected && ( at[nxt_atom].sb_parity[j] & SB_PARITY_FLAG ))
    4757                 :             :         {
    4758                 :           0 :             nxt_sb_parity = ( at[nxt_atom].sb_parity[j] >> SB_PARITY_SHFT );
    4759                 :           0 :             bNxtMask = 3 << SB_PARITY_SHFT;
    4760                 :             :         }
    4761                 :             :         else
    4762                 :             :         {
    4763                 :           0 :             nxt_sb_parity = ( at[nxt_atom].sb_parity[j] & SB_PARITY_MASK );
    4764                 :           0 :             bNxtMask = 3;
    4765                 :             :         }
    4766                 :             : 
    4767   [ #  #  #  #  :           0 :         if (!ATOM_PARITY_WELL_DEF( cur_sb_parity ) ||
                   #  # ]
    4768         [ #  # ]:           0 :              !ATOM_PARITY_WELL_DEF( nxt_sb_parity ))
    4769                 :             :         {
    4770         [ #  # ]:           0 :             if (cur_sb_parity == nxt_sb_parity)
    4771                 :             :             {
    4772                 :           0 :                 continue;
    4773                 :             :                 /* goto move_forward;       */
    4774                 :             :                 /* bypass unknown/undefined */
    4775                 :             :             }
    4776                 :           0 :             return 3; /* sb parities do not match: bond parity data error */
    4777                 :             :         }
    4778                 :             : 
    4779                 :           0 :         icur2neigh = (int) at[cur_atom].sn_ord[i];
    4780                 :           0 :         inxt2neigh = (int) at[nxt_atom].sn_ord[j];
    4781                 :             :         /* Parity of at[cur_atom].neighbor[] premutation to reach this order: { next_atom, neigh_atom, ...} */
    4782                 :             : 
    4783                 :             :         /* 1. move next_atom  from position=icur2nxt to position=0 =>
    4784                 :             :          *         icur2nxt permutations
    4785                 :             :          * 2. move neigh_atom from position=inxt2neigh+(inxt2cur > inxt2neigh) to position=1 =>
    4786                 :             :          *         inxt2neigh+(inxt2cur > inxt2neigh)-1 permutations.
    4787                 :             :          * Note if (inxt2cur > inxt2neigh) then move #1 increments neigh_atom position
    4788                 :             :          * Note add 4 because icur2neigh may be negative due to isotopic H removal
    4789                 :             :          */
    4790                 :           0 :         cur_order_parity = ( 4 + icur2nxt + icur2neigh + ( icur2neigh > icur2nxt ) ) % 2;
    4791                 :             : 
    4792                 :             :         /* Same for next atom: */
    4793                 :             :         /* parity of at[nxt_atom].neighbor[] premutation to reach this order: { cur_atom, neigh_atom, ...} */
    4794                 :           0 :         nxt_order_parity = ( 4 + inxt2cur + inxt2neigh + ( inxt2neigh > inxt2cur ) ) % 2;
    4795                 :           0 :         nxt_parity = visited[nxt_atom] % 10;
    4796                 :             : 
    4797         [ #  # ]:           0 :         if (!cur_parity)
    4798                 :             :         {
    4799                 :           0 :             cur_parity = 2 - ( cur_order_parity + cur_sb_parity ) % 2;
    4800                 :           0 :             visited[cur_atom] += cur_parity;
    4801                 :             :         }
    4802                 :             :         else
    4803                 :             :         {
    4804         [ #  # ]:           0 :             if (cur_parity != 2 - ( cur_order_parity + cur_sb_parity ) % 2)
    4805                 :             :             {
    4806                 :             :                 /***** Reconcile bond parities *****/
    4807                 :             : 
    4808                 :             :                 /* Each bond parity is split into two values located at the end atoms.
    4809                 :             :                    For T (trans) the values are (1,1) or (2,2)
    4810                 :             :                    For C (cis)   the values are (1,2) or (2,1)
    4811                 :             :                    The fact that one pair = another with inverted parities, namely
    4812                 :             :                    Inv(1,1) = (2,2) and Inv(1,2) = (2,1), allows to
    4813                 :             :                    simultaneouly invert parities of the current bond end atoms
    4814                 :             :                    (at[cur_atom].sb_parity[i], at[nxt_atom].sb_parity[j])
    4815                 :             :                    so that the final current atom parity cur_parity
    4816                 :             :                    calculated later in stereochemical canonicalization for
    4817                 :             :                    each stereobond incident with the current atomis same.
    4818                 :             :                    Achieving this is called here RECONCILIATION.
    4819                 :             :                    If at the closure of an aromatic circuit the parities of
    4820                 :             :                    next atom cannot be reconciled with already calculated then
    4821                 :             :                    this function returns 5 (error).
    4822                 :             :                 */
    4823                 :           0 :                 at[cur_atom].sb_parity[i] ^= bCurMask;
    4824                 :           0 :                 at[nxt_atom].sb_parity[j] ^= bNxtMask;
    4825                 :             :                 /* djb-rwth: removing redundant code */
    4826                 :           0 :                 nxt_sb_parity ^= 3;
    4827                 :             :             }
    4828                 :             :         }
    4829                 :             : 
    4830         [ #  # ]:           0 :         if (!nxt_parity)
    4831                 :             :         {
    4832                 :           0 :             nxt_parity = 2 - ( nxt_order_parity + nxt_sb_parity ) % 2;
    4833                 :           0 :             visited[nxt_atom] += nxt_parity;
    4834                 :             :         }
    4835                 :             :         else
    4836                 :             :         {
    4837         [ #  # ]:           0 :             if (nxt_parity != 2 - ( nxt_order_parity + nxt_sb_parity ) % 2)
    4838                 :             :             {
    4839                 :           0 :                 return 5; /* algorithm does not work for Mebius-like structures */
    4840                 :             :             }
    4841                 :             :         }
    4842                 :             : 
    4843                 :             :         /* Move_forward: */
    4844         [ #  # ]:           0 :         if (visited[nxt_atom] < 10)
    4845                 :             :         {
    4846                 :           0 :             ret = ReconcileCmlIncidentBondParities( at, nxt_atom, cur_atom, visited, bDisconnected );
    4847         [ #  # ]:           0 :             if (ret)
    4848                 :             :             {
    4849                 :           0 :                 break;
    4850                 :             :             }
    4851                 :             :         }
    4852                 :             :     }
    4853                 :           0 :     visited[cur_atom] += 10; /* all bonds incident to the current atom have
    4854                 :             :                                 been processed or an error occurred. */
    4855                 :             : 
    4856                 :           0 :     return ret;
    4857                 :             : }
    4858                 :             : 
    4859                 :             : 
    4860                 :             : /****************************************************************************/
    4861                 :           0 : int get_opposite_sb_atom( inp_ATOM *at,
    4862                 :             :                           int cur_atom,
    4863                 :             :                           int icur2nxt,
    4864                 :             :                           int *pnxt_atom,
    4865                 :             :                           int *pinxt2cur,
    4866                 :             :                           int *pinxt_sb_parity_ord )
    4867                 :             : {
    4868                 :             :     AT_NUMB nxt_atom;
    4869                 :             :     int     j, len;
    4870                 :             : 
    4871                 :           0 :     len = 0;
    4872         [ #  # ]:           0 :     while (len++ < 20)
    4873                 :             :     {
    4874                 :             :         /* Arbitrarily set cumulene length limit to avoid infinite loop */
    4875                 :           0 :         nxt_atom = at[cur_atom].neighbor[icur2nxt];
    4876   [ #  #  #  # ]:           0 :         for (j = 0; j < MAX_NUM_STEREO_BONDS && at[nxt_atom].sb_parity[j]; j++)
    4877                 :             :         {
    4878         [ #  # ]:           0 :             if (cur_atom == at[nxt_atom].neighbor[(int) at[nxt_atom].sb_ord[j]])
    4879                 :             :             {
    4880                 :             :                 /* Found the opposite atom */
    4881                 :           0 :                 *pnxt_atom = nxt_atom;
    4882                 :           0 :                 *pinxt2cur = at[nxt_atom].sb_ord[j];
    4883                 :           0 :                 *pinxt_sb_parity_ord = j;
    4884                 :           0 :                 return len;
    4885                 :             :             }
    4886                 :             :         }
    4887         [ #  # ]:           0 :         if (j)
    4888                 :             :         {
    4889                 :           0 :             return 0; /* reached atom(s) with stereobond (sb) parity, the opposite atom has not been found */
    4890                 :             :         }
    4891   [ #  #  #  # ]:           0 :         if (at[nxt_atom].valence == 2 && 2 * BOND_TYPE_DOUBLE == at[nxt_atom].chem_bonds_valence)
    4892                 :             :         {
    4893                 :             :             /* Follow cumulene =X= path */
    4894                 :           0 :             icur2nxt = ( at[nxt_atom].neighbor[0] == cur_atom );
    4895                 :           0 :             cur_atom = nxt_atom;
    4896                 :             :         }
    4897                 :             :         else
    4898                 :             :         {
    4899                 :           0 :             return 0; /* neither atom with a sb parity not middle cumulene could be reached */
    4900                 :             :         }
    4901                 :             :     }
    4902                 :             : 
    4903                 :           0 :     return 0; /* too long chain of cumulene was found */
    4904                 :             : }
        

Generated by: LCOV version 2.0-1