1 /*
2  * International Chemical Identifier (InChI)
3  * Version 1
4  * Software version 1.04
5  * September 9, 2011
6  *
7  * The InChI library and programs are free software developed under the
8  * auspices of the International Union of Pure and Applied Chemistry (IUPAC).
9  * Originally developed at NIST. Modifications and additions by IUPAC
10  * and the InChI Trust.
11  *
12  * IUPAC/InChI-Trust Licence for the International Chemical Identifier (InChI)
13  * Software version 1.0.
14  * Copyright (C) IUPAC and InChI Trust Limited
15  *
16  * This library is free software; you can redistribute it and/or modify it under the
17  * terms of the IUPAC/InChI Trust Licence for the International Chemical Identifier
18  * (InChI) Software version 1.0; either version 1.0 of the License, or
19  * (at your option) any later version.
20  *
21  * This library is distributed in the hope that it will be useful,
22  * but WITHOUT ANY WARRANTY; without even the implied warranty of
23  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
24  * See the IUPAC/InChI Trust Licence for the International Chemical Identifier (InChI)
25  * Software version 1.0 for more details.
26  *
27  * You should have received a copy of the IUPAC/InChI Trust Licence for the
28  * International Chemical Identifier (InChI) Software version 1.0 along with
29  * this library; if not, write to:
30  *
31  * The InChI Trust
32  * c/o FIZ CHEMIE Berlin
33  * Franklinstrasse 11
34  * 10587 Berlin
35  * GERMANY
36  *
37  */
38 
39 
40 #ifndef __ICHIRVRS_H__
41 #define __ICHIRVRS_H__
42 
43 #define ICHICONST      const
44 
45 #define RI_ERR_ALLOC   (-1)
46 #define RI_ERR_SYNTAX  (-2)
47 #define RI_ERR_PROGR   (-3)
48 #define RI_ERR_EOL     (-4)
49 #define RI_ERR_EOF     (0)
50 
51 
52 #define NO_VALUE_INT    9999
53 #define NOT_READ_INT    9998 /* has not been read yet */
54 
55 #define VALUE_OCTET    8     /* number of electrons in a full shell */
56 
57 #define INC_EDGE_LIST_DEFAULT  64
58 
59 typedef struct tagXYZCoord {
60     double xyz[3];
61 } XYZ_COORD;
62 
63 typedef struct tagStructRestoreMode {
64     int bMetalAddFlower;       /* 1 => allow adjustable metal valence and charge; 0=> use std charge/valence */
65     /* the following three apply only if bMetalAddFlower = 1 */
66     int nMetalMinBondOrder;    /* edge_flow=f means bond order=cMetalMinBondOrder+f */
67     int nMetalInitEdgeFlow;    /* one bond contribution to metal's (st-cap - st-flow) = */
68                                /*   (nMetalInitBondOrder-nMetalMinBondOrder) - nMetalInitEdgeFlow */
69     int nMetalInitBondOrder;   /* >= nMetalMinBondOrder + nMetalInitEdgeFlow */
70     /* same for metal-endpoint bonds */
71     int nMetal2EndpointMinBondOrder;
72     int nMetal2EndpointInitBondOrder;
73     int nMetal2EndpointInitEdgeFlow;
74     int nMetalFlowerParam_D;      /* additional edge capacity for canceling radicals */
75     int nMetalMaxCharge_D;        /* cap and/or flow for metal charge group */
76     int bStereoRemovesMetalFlag;  /* 1=> treat stereogenic atoms and atoms connected by a stereo bond as non-metals */
77 
78     int bFixStereoBonds;       /* 1=> forbid stereogenic double bonds from changing */
79 } SRM;
80 
81 typedef struct tagReversedInChI {
82     PINChI2     *pINChI[INCHI_NUM];
83     PINChI_Aux2 *pINChI_Aux[INCHI_NUM];
84     int          num_components[INCHI_NUM];
85     int          nRetVal;
86 } REV_INCHI;
87 
88 /**************************************/
89 #define BFS_Q_CLEAR  (-1)
90 #define BFS_Q_FREE   (-2)
91 typedef struct tagBfsQueue {
92     QUEUE   *q;
93     AT_RANK *nAtomLevel;
94     S_CHAR  *cSource;
95     int      num_at;
96     AT_RANK  min_ring_size;  /* 8 => detect 7-member and smaller rings */
97 } BFS_Q;
98 /**************************************/
99 
100 #define EXTRACT_STRUCT_NUMBER 1
101 
102 /* additional Mobile-H parities to be added to Fixed-H parities  */
103 /* This allows one to set parities that exist in Mobile-H layer only */
104 typedef struct tagInpAtomAddParities {
105     /* cml 0D parities */
106     S_CHAR        bUsed0DParity;          /* bit=1 => stereobond; bit=2 => stereocenter */
107     /* cml tetrahedral parity */
108     S_CHAR        p_parity;
109     AT_NUMB       p_orig_at_num[MAX_NUM_STEREO_ATOM_NEIGH];
110     /* cml bond parities */
111     S_CHAR        sb_ord[MAX_NUM_STEREO_BONDS];  /* stereo bond/neighbor ordering number, starts from 0 */
112     /* neighbors on both sides of stereobond have same sign=> trans/T/E, diff. signs => cis/C/Z */
113     S_CHAR        sn_ord[MAX_NUM_STEREO_BONDS]; /* ord. num. of the neighbor adjacent to the SB; starts from 0;
114                                                    -1 means removed explicit H */
115     /* neighbors on both sides of stereobond have same parity => trans/T/E/2, diff. parities => cis/C/Z/1 */
116     S_CHAR        sb_parity[MAX_NUM_STEREO_BONDS];
117     AT_NUMB       sn_orig_at_num[MAX_NUM_STEREO_BONDS]; /* orig. at number of sn_ord[] neighbors */
118 } inp_ATOM_STEREO;
119 
120 #define FIX_STEREO_BOND_ORDER  0   /* 1=> fix stereobonds; treat metal as non-metal if it is stereogenic or has a stereobond */
121 
122 #define METAL_FREE_CHARGE_VAL  1  /* 1=> allow free changing charges/valences of metals; initial bond order=0 or 1 */
123 #define ALLOW_METAL_BOND_ZERO  1  /* 1=> allow zero flow (bobd order) to metals */
124 
125 #if ( ALLOW_METAL_BOND_ZERO == 1 )
126 /* INIT_METAL_BOND_ZERO=1 => INIT_METAL_BOND_FLOW=0 */
127 #define INIT_METAL_BOND_ZERO   0  /* 1=> initialize zero order bond to metals */
128 #define INIT_METAL_BOND_FLOW   1  /* 1=> init flow=1, 0 => init. flow = 0 */
129 #else
130 #define INIT_METAL_BOND_ZERO   0
131 #define INIT_METAL_BOND_FLOW   0  /* always 0 */
132 #endif
133 
134 #define I2A_FLAG_FIXEDH  0x0001
135 #define I2A_FLAG_RECMET  0x0002
136 
137 #define EL_NUMBER_H  1
138 
139 
140 #define ATYPE_H   1
141 #define ATYPE_Na  2
142 #define ATYPE_Mg  3
143 #define ATYPE_B   4
144 #define ATYPE_C   5
145 #define ATYPE_N   6
146 #define ATYPE_O   7
147 #define ATYPE_Cl  8
148 
149 
150 /* first  bonds valence for charge = c is cValence[0][c+VAL_BASE]; VAL_MIN_CHARGE <= c <= VAL_MAX_CHARGE */
151 /* second bonds valence for charge = c is cValence[1][c+VAL_BASE]; VAL_MIN_CHARGE <= c <= VAL_MAX_CHARGE */
152 /* total number of valences is 2 = VAL_NUMBER */
153 /* neutral bond valence orders are cValence[0][VAL_NEUTR_ORDER], cValence[1][VAL_NEUTR_ORDER] */
154 #define VAL_BASE         ( 1)
155 #define VAL_MIN_CHARGE   (-1)
156 #define VAL_MAX_CHARGE   ( 1)
157 #define VAL_NUMBER       ( 2)
158 #define VAL_NEUTR_ORDER  (VAL_MAX_CHARGE-VAL_MIN_CHARGE+1)
159 #define VAL_LENGTH       (VAL_NEUTR_ORDER+1)
160 #define VAL_NEGAT_CHARGE    0
161 #define VAL_NEUTR_CHARGE    1
162 #define VAL_POSIT_CHARGE    2
163 
164 typedef struct tagAtomIonPrperies {
165     /* char cValence[VAL_NUMBER][VAL_LENGTH]; */ /* ordering numbers of minimal valence, 0-based */
166     char   cDoNotAddH;         /* InChI does not add H to this element */
167     char   cMetal;             /* the element is a metal */
168     char   cNumBondsToMetal;   /* number of bonds to metal */
169     char   cInitFlowToMetal;    /* sum of init flow to metal atoms */
170     char   cInitValenceToMetal; /* sum of init adjusted bond orders to metal atoms */
171     char   cInitOrigValenceToMetal; /* sum of init bond orders to metal atoms */
172     char   cMaxFlowToMetal;    /* max total edge flow to metal atoms */
173     char   cInitFreeValences;  /* number of 'dots' to connect; charges are marked separately */
174     S_CHAR cInitCharge;        /* initial charge on the atom (not included in ChargeStruct */
175     char   cNumValenceElectrons;
176     char   cPeriodicRowNumber;
177     char   cMinRingSize;       /* min ring size for atoms that have 2 bonds only */
178     U_CHAR cPeriodicNumber;  /* number in Periodic Table of elements */
179     S_CHAR cnListIndex;        /* (index in the cnList) + 1; 0 => none */
180     int    nCMinusGroupEdge;   /* (index of the edge to the atom's (-) group) + 1 */
181     int    nCPlusGroupEdge;    /* (index of the edge to the atom's (+) group) + 1 */
182     int    nMetalGroupEdge;    /* index of the edge to the atom's M-group + 1 */
183     int    nTautGroupEdge;     /* index of the edge from the atom to the t-group + 1 */
184 } VAL_AT;
185 
186 
187 /******************************************************************************************************/
188 #define INI_NUM_TCGROUPS 16
189 #define INC_NUM_TCGROUPS 16
190 
191 typedef enum tagTgRestoreFlags {
192     TGRF_MINUS_FIRST = 1
193 } TGRF;
194 typedef struct tagTCGroup {
195     int type;    /* group type */
196     int ord_num; /* ordering number within the type, typically t-group number */
197     int num_edges;
198     /* charge group specific */
199     int st_cap;
200     int st_flow;
201     int edges_cap;
202     int edges_flow;
203     int nVertexNumber; /* group vertex number; 0 = unassigned */
204     int nForwardEdge;  /* edge index: from c-group to central Y-connecting vertex
205                           or from supergroup to (+/-) vertex; 0 => unassigned */
206     int nBackwardEdge; /* edge index: from central Y-connecting vertex
207                           to supergroup; 0 => unassigned */
208     /* tautomeric group specific */
209     short tg_num_H;      /* number of H in a tautomeric group */
210     short tg_num_Minus;  /* negative charge on t-group */
211     Vertex tg_set_Minus;  /* the vertex+1 that has to have (-) */
212     short tg_RestoreFlags; /* Set (-) to first memberst of a t-group (usually, N) */
213 } TC_GROUP;
214 
215 typedef enum tagTCGroupTypes {
216     TCG_None = -1, /* so far only ord=0 is used */
217                    /* group type      ord */
218     TCG_Plus0 = 0, /* BNS_VT_C_POS      0 */
219     TCG_Plus1,     /* BNS_VT_C_POS      1 */
220     TCG_Minus0,    /* BNS_VT_C_NEG      0 */
221     TCG_Minus1,    /* BNS_VT_C_NEG      1 */
222     TCG_Plus_C0,   /* BNS_VT_C_POS_C    0 */
223     TCG_Plus_C1,   /* BNS_VT_C_POS_C    1 */
224     TCG_Minus_C0,  /* BNS_VT_C_NEG_C    0 */
225     TCG_Minus_C1,  /* BNS_VT_C_NEG_C    1 */
226     TCG_Plus_M0,   /* BNS_VT_C_POS_M    0 */
227     TCG_Plus_M1,   /* BNS_VT_C_POS_M    1 */
228     TCG_Minus_M0,  /* BNS_VT_C_NEG_M    0 */
229     TCG_Minus_M1,  /* BNS_VT_C_NEG_M    1 */
230     TCG_MeFlower0, /* BNS_VT_M_GROUP    0 */  /* base */
231     TCG_MeFlower1, /* BNS_VT_M_GROUP    1 */
232     TCG_MeFlower2, /* BNS_VT_M_GROUP    2 */
233     TCG_MeFlower3, /* BNS_VT_M_GROUP    3 */
234 
235     TCG_Plus,      /* BNS_VT_C_POS_ALL  0 */
236     TCG_Minus,     /* BNS_VT_C_NEG_ALL  0 */
237 
238     NUM_TCGROUP_TYPES /* number of group types */
239 }TCGR_TYPE;
240 
241 typedef struct tagAllTCGroups {
242     TC_GROUP *pTCG;
243     int      num_tc_groups; /* number of charge groups and metal-flower vertices */
244     int      max_tc_groups; /* number of allocated of pTCG[] elements */
245     int      nGroup[NUM_TCGROUP_TYPES];  /* tagTCGroupTypes */
246     int      nVertices;  /* total number of vertices */
247     int      nEdges;     /* total number of edges */
248     int      nAddIedges; /* additional increase of number of iedges for edge switching to another group */
249     int      num_atoms;  /* number of atoms */
250     int      num_bonds;  /* number of bonds */
251     int      num_tgroups;       /* number t-groups */
252     int      num_tgroup_edges;  /* number of edges to t-groups */
253     /* charges */
254     int      tgroup_charge;     /* total charge of all t-groups */
255     int      charge_on_atoms;   /* charge permanently sitting on atoms */
256     int      added_charge;      /* charge added to the c-groups */
257     int      total_charge;      /* total charge of the component */
258     int      total_electrons;   /* total number of electrons on all atoms */
259     int      total_electrons_metals; /* total number of electrons on unbonded metals */
260 
261     int      num_metal_atoms;   /* number of metal atoms */
262     int      num_metal_bonds;   /* number of atom-metal bonds */
263     /* excess_charge = total_charge - added_charge - tgroup_charge: add to metals etc. */
264 
265     int      nEdge4charge;      /* edge used to add charges; neighbor1=supercharge, another = (+/-) vertex */
266     int      nEdgePlus;         /* edge to (+) supergroup; 0 means none */
267     int      nEdgeMinus;        /* edge to (-) supergroup; 0 means none */
268     int      iComponent;        /* component number */
269     int      iAtNoOffset;       /* first atom number -- always 0 for now */
270 } ALL_TC_GROUPS;
271 
272 /**************************************/
273 #define EDGE_LIST_CLEAR  (-1)
274 #define EDGE_LIST_FREE   (-2)
275 
276 typedef struct tagEdgeList {
277     int num_alloc;
278     int num_edges;
279     EdgeIndex *pnEdges;
280 } EDGE_LIST;
281 /**************************************/
282 
283 #define BOND_MARK_STEREO 0x10
284 #define BOND_TYPE_STEREO (BOND_TYPE_SINGLE | BOND_MARK_STEREO)
285 
286 /* local */
287 #define RESET_EDGE_FORBIDDEN_MASK 0
288 
289 #define TREAT_ATOM_AS_METAL 99
290 
291 
292 /************************************************************************************/
293 typedef struct tagChargeValence {
294     int nValence;
295     int nCharge;
296     int nValenceOrderingNumber;
297 } CHARGE_VAL;
298 
299 #define MY_CONST  const
300 /*************************************************************************************/
301 typedef struct tagChargeChangeCandidate {
302     Vertex iat;
303     char   num_bonds;
304     char   chem_valence;
305     char   cMetal;
306     char   cNumBondsToMetal;
307     char   cNumValenceElectrons;
308     char   cPeriodicRowNumber;
309     char   cNumChargeStates;
310     U_CHAR el_number;
311 } CC_CAND;
312 
313 typedef struct tagOneComponentRemovedAndExchangeableH {
314     NUM_H   nNumRemovedProtons;
315     NUM_H   nNumRemovedIsotopicH[NUM_H_ISOTOPES]; /* isotopic H that may be exchanged and considered
316                                                      randomly distributed, including removed protons */
317 } COMPONENT_REM_PROTONS;
318 
319 typedef struct tagRemovedAndExchangeableH {
320     /* totals for Mobile-H layer */
321     NUM_H   nNumRemovedProtons;
322     NUM_H   nNumRemovedIsotopicH[NUM_H_ISOTOPES]; /* isotopic H that may be exchanged and considered
323                                                      randomly distributed, including removed protons */
324     /* for individual components from comparing Fixed-H vs Mobile-H formulas; NULL if not available */
325     COMPONENT_REM_PROTONS *pNumProtons;
326 } REM_PROTONS;
327 
328 typedef struct tagInputInChI {
329     INChI      *pInpInChI[INCHI_NUM][TAUT_NUM];
330     int         nNumComponents[INCHI_NUM][TAUT_NUM];
331     REM_PROTONS nNumProtons[INCHI_NUM][TAUT_NUM];
332     int         s[INCHI_NUM][TAUT_NUM][2];  /* s[0=non-iso, 1=iso] = 0,1,2,3 <= regular /s; -1=> "/s" (empty) */
333     long        num_inp;
334     inp_ATOM   *atom;      /* the whole restored structure made out of all components */
335     int         num_atoms; /* number of atoms including explicit H */
336     int         num_explicit_H; /* number of explicit H in the atom */
337     INCHI_MODE  CompareInchiFlags[INCHI_NUM][TAUT_NUM];
338 } InpInChI;
339 
340 typedef struct tagStructFromInChI {
341     /* InChI component -> Structure result */
342     inp_ATOM        *at;  /* length = num_atoms + num_deleted_H, zero pint struct for BNS->struct conversion */
343     inp_ATOM_STEREO *st;  /* additional stereo that exists only in Mobile-H layer */
344     inp_ATOM        *at2; /* length = num_atoms + num_deleted_H, the conversion result */
345 
346     /* information from InChI only */
347     T_GROUP_INFO  ti; /* from original InChI[0] if Mobile-H from the beginning or later from InChI[1] if Fixed-H  */
348     AT_NUMB      *endpoint; /* from original InChI[1] in case of Fixed-H only */
349     S_CHAR       *fixed_H;  /* from original InChI[0] in case of Fixed-H only */
350     XYZ_COORD    *pXYZ;
351     int           num_atoms;
352     int           num_deleted_H; /* if requested and Fixed-H InChI is available */
353     int           nNumRemovedProtonsMobHInChI; /* number of protons removed from Mobile-H struct in original InChI */
354     S_CHAR        charge;
355     char          bIsotopic;
356 
357     /* InChI -> Structure conversion parms and intermediate data */
358     BN_STRUCT *pBNS;
359     BN_DATA   *pBD;
360     ICHICONST SRM       *pSrm;
361 
362     /* InChI layer to reverse */
363     char        bMobileH;
364     char        iINCHI;
365     char        bFixedHExists; /* fixed-H InChI exists or not */
366 
367     /* InChI -> Struct component -> Full InChI result (both disconnected and connected if exist) */
368     REV_INCHI  RevInChI;
369     int        nRemovedProtonsByNormFromRevrs; /* number of H(+) removed by normalization after
370                                                  Struct Restore and before Add/Remove Protons */
371     int        nNumRemovedProtonsByRevrs;       /* number of H(+) removed by the reconstruction,
372                                                    before Add/Remove Protons, only from TAUT_YES */
373 
374     int        bExtract; /* for debugging */
375 
376     /* single component InChI calculation */
377     INChI         *pOneINChI[TAUT_NUM];       /* InChI of restored structure */
378     INChI_Aux     *pOneINChI_Aux[TAUT_NUM];
379     INP_ATOM_DATA *pOne_norm_data[TAUT_NUM];  /* normalized restored structure */
380     S_CHAR        *pOne_fixed_H;              /* !!! from normalized restored structure in case of Fixed-H only */
381     T_GROUP_INFO   One_ti;                    /* t-groups of normalized canonicalized restored structure */
382     int            nOneINChI_bMobileH;        /* type of restored structure InChI */
383     int            nNumRemovedProtons;        /* =0 for Fixed-H, = num. removed protons in case of Mobile-H InChI */
384                                               /* in case of Fixed-H processing see pStruct->One_ti.tni.nNumRemovedProtons */
385     AT_NUMB       *nAtno2Canon[TAUT_NUM];     /* nAtno2Canon[restored_at_no][*] = (atom canon number in restored struct)-1*/
386     AT_NUMB       *nCanon2Atno[TAUT_NUM];     /* nCanon2Atno[(atom canon number in restored struct)-1][*] = restored_at_no; */
387 
388     int            nError;
389     /* other parms */
390     char        iInchiRec; /* index in the original InChI array */
391     char        iMobileH;  /* index in the original InChI array */
392     char        bDeleted;  /* InChI component marked as Deleted, means a proton in Mobile-H layer */
393     /* struct. ordering number "Structure: nnn" if present */
394     long        num_inp_actual;
395 
396     /* utility data */
397     BFS_Q   *pbfsq;
398     VAL_AT  *pVA;
399 
400     int   nLink; /* same as in INChI */
401     int   bPostProcessed; /* recalculate after add/remove protons */
402 
403     /* TAUT_YES layer charges */
404     int nChargeRevrs;  /* component charge of the reconstructed structure, TAUT_YES layer */
405     int nChargeInChI;  /* component charge from the original InChI, TAUT_YES layer */
406 } StrFromINChI;
407 
408 
409 #define EL_TYPE_O     0x0001
410 #define EL_TYPE_S     0x0002
411 #define EL_TYPE_N     0x0004
412 #define EL_TYPE_P     0x0008
413 #define EL_TYPE_C     0x0010
414 #define EL_TYPE_X     0x0020 /* any not metal */
415 #define EL_TYPE_MASK  0x003f
416 #define EL_TYPE_OSt   0x0100 /* terminal -OH, -O(-), -SH, -S(-), ... from fix_special_bonds(...) */
417 #define EL_TYPE_PT    0x0200 /* may be a tautomeric endpoint */
418 
419 /* the atom to which the node is attached has number 1; added atoms have numbers 2,3,... */
420 #define MAX_CN_VAL 3
421 typedef struct tagVertCapFlow {
422     S_SHORT type;
423     S_CHAR  cap;
424     S_CHAR  flow;
425     S_CHAR  valence;
426 } VCF;
427 typedef struct tagEdgeCapFlow {
428     S_SHORT neigh;
429     S_CHAR  cap;
430     S_CHAR  bForbiddenEdge;
431     S_CHAR  flow;
432 } ECF;
433 typedef struct tagChargeNodes {
434     VCF v;
435     ECF e[MAX_CN_VAL];
436 } C_NODE;
437 
438 
439 #define cn_bits_N  1  /* Neutral: charge =  0 */
440 #define cn_bits_P  2  /* Plus 1:  charge = +1 */
441 #define cn_bits_M  4  /* Minus 1: charge = -1 */
442 #define cn_bits_shift 3
443 #define MAX_NUM_CN_BITS 4
444 #define MAKE_CN_BITS(A, B, C, D ) (( (( ((D) << cn_bits_shift | (C)) << cn_bits_shift ) | (B)) << cn_bits_shift ) | (A))
445 
446 #define cn_bits_PNPN MAKE_CN_BITS(cn_bits_P, cn_bits_N, cn_bits_P, cn_bits_N)
447 #define cn_bits_NPNP MAKE_CN_BITS(cn_bits_N, cn_bits_P, cn_bits_N, cn_bits_P)
448 #define cn_bits_NPN MAKE_CN_BITS(cn_bits_N, cn_bits_P, cn_bits_N, 0)
449 #define cn_bits_PNP MAKE_CN_BITS(cn_bits_P, cn_bits_N, cn_bits_P, 0)
450 #define cn_bits_MNP  MAKE_CN_BITS(cn_bits_M, cn_bits_N, cn_bits_P, 0)
451 #define cn_bits_PNM  MAKE_CN_BITS(cn_bits_P, cn_bits_N, cn_bits_M, 0)
452 #define cn_bits_EN  MAKE_CN_BITS(cn_bits_P | cn_bits_M, cn_bits_N, 0, 0)
453 #define cn_bits_NMN  MAKE_CN_BITS(cn_bits_N, cn_bits_M, cn_bits_N, 0)
454 #define cn_bits_NE  MAKE_CN_BITS(cn_bits_N, cn_bits_P | cn_bits_M, 0, 0)
455 #define cn_bits_NEN  MAKE_CN_BITS(cn_bits_N, cn_bits_M | cn_bits_N, cn_bits_N, 0)
456 #define cn_bits_NP  MAKE_CN_BITS(cn_bits_N, cn_bits_P, 0, 0)
457 #define cn_bits_PN  MAKE_CN_BITS(cn_bits_P, cn_bits_N, 0, 0)
458 #define cn_bits_NM  MAKE_CN_BITS(cn_bits_N, cn_bits_M, 0, 0)
459 #define cn_bits_MN  MAKE_CN_BITS(cn_bits_M, cn_bits_N, 0, 0)
460 #define cn_bits_P_  MAKE_CN_BITS(cn_bits_P, 0, 0, 0)
461 #define cn_bits_M_  MAKE_CN_BITS(cn_bits_M, 0, 0, 0)
462 #define cn_bits_N_  MAKE_CN_BITS(cn_bits_N, 0, 0, 0)
463 #define cn_bits_Me (-1)
464 
465 #define cnListIndexMe (17)  /* index of {cnMe, cn_bits_Me,... } element of cnList[] */
466 
467 extern int cnListNumEl;  /* number of elements in cnList[] */
468 
469 typedef struct tagChargeNodeList {
470     MY_CONST C_NODE *pCN;
471              int     bits;
472              int     nInitialCharge;
473              int     len;
474 } CN_LIST;
475 
476 extern MY_CONST CN_LIST cnList[];
477 
478 /************************ fixed H comparison ******************************************************/
479 #define MAX_DIFF_FIXH 256
480 #define MAX_DIFF_MOBH 256
481 typedef struct tagAtomsCmpTwoFixedH {
482     AT_NUMB endptInChI;
483     AT_NUMB endptRevrs;
484     AT_NUMB atomNumber;
485     U_CHAR nValElectr;
486     U_CHAR nPeriodNum;
487     S_CHAR nFixHInChI;
488     S_CHAR nFixHRevrs;
489     S_CHAR nMobHInChI;
490     S_CHAR nMobHRevrs;
491     S_CHAR nNumHRevrs;
492     S_CHAR nAtChargeRevrs;
493     S_CHAR nValue; /* flag(s) */
494 } CMP2FHATOMS;
495 
496 typedef struct tagStructCmpTwoFixedH {
497     CMP2FHATOMS c2at[MAX_DIFF_FIXH];
498     short  len_c2at;
499     short  nNumRemHInChI;
500     short  nNumRemHRevrs;
501     short  nNumTgInChI;
502     short  nNumTgRevrs;
503     short  nNumEndpInChI;
504     short  nNumEndpRevrs;
505     short  nNumTgDiffMinus; /* number of would-be-identical t-groups that have different number of (-) */
506     short  nNumTgDiffH;     /* number of would-be-identical t-groups that have different number of H */
507     short  nNumTgMInChI;    /* number of (-) in orig. InChI t-groups */
508     short  nNumTgHInChI;    /* number of H in orig. InChI t-groups */
509     short  nNumTgMRevrs;    /* number of (-) in reversed structure t-groups */
510     short  nNumTgHRevrs;    /* number of H in reversed structure t-groups */
511     S_CHAR nChargeFixHInChI;
512     S_CHAR nChargeMobHInChI;
513     S_CHAR nChargeFixHRevrs;
514     S_CHAR nChargeMobHRevrs;
515     S_CHAR nChargeFixHRevrsNonMetal; /* charge does not include charges on metals */
516     S_CHAR nChargeMobHRevrsNonMetal; /* charge does not include charges on metals */
517     char   bFixedHLayerExistsRevrs;
518     char   bHasDifference;
519     U_CHAR nNumDiffMobH;
520 
521 } CMP2FHINCHI;
522 
523 /************************ Mobile H comparison *********************************************/
524 typedef struct tagAtomsCmpTwoMobileH {
525     AT_NUMB endptInChI;
526     AT_NUMB endptRevrs;
527     AT_NUMB atomNumber;
528     U_CHAR nValElectr;
529     U_CHAR nPeriodNum;
530     S_CHAR nMobHInChI; /* number of H on the atom in the orig. InChI */
531     S_CHAR nMobHRevrs; /* number of H on the atom in InChI from the reconstructed structure */
532     S_CHAR nNumHRevrs; /* number of H on the atom in the being reconstructed structure */
533     S_CHAR nAtChargeRevrs;
534     S_CHAR nValue;         /* flag(s) */
535 } CMP2MHATOMS;
536 
537 typedef struct tagStructCmpTwoMobileH {
538     CMP2MHATOMS c2at[MAX_DIFF_FIXH];
539     short len_c2at;
540     short nNumRemHInChI;
541     short nNumRemHRevrs;
542     short nNumTgInChI;
543     short nNumTgRevrs;
544     short nNumEndpInChI;
545     short nNumEndpRevrs;
546     short nNumTgDiffMinus;   /* number of would-be-identical t-groups that have different number of (-) */
547     short nNumTgDiffH;       /* number of would-be-identical t-groups that have different number of H */
548 
549     short nNumTgMInChI;      /* number of (-) in orig. InChI t-groups */
550     short nNumTgHInChI;      /* number of H in orig. InChI t-groups */
551     short nNumTgOInChI;      /* number of tautomeric O,S,Se in orig. InChI t-groups */
552     short nNumTgNInChI;      /* number of tautomeric N in orig. InChI t-groups */
553 
554     short nNumTgMRevrs;      /* number of (-) in reversed structure t-groups */
555     short nNumTgHRevrs;      /* number of H in reversed structure t-groups */
556     short nNumTgORevrs;      /* number of tautomeric O,S,Se in reversed structure t-groups */
557     short nNumTgNRevrs;       /* number of tautomeric N in reversed structure t-groups */
558 
559     short nNumTgOMinusRevrs;   /* number of -O(-)  on endpoints found in restored structure */
560     short nNumTgOHRevrs;       /* number of -OH    on endpoints found in restored structure */
561     short nNumTgDBORevrs;      /* number of =O     on endpoints found in restored structure */
562     short nNumTgNMinusRevrs;   /* number of -N(-)- on endpoints found in restored structure */
563     short nNumTgNHMinusRevrs;  /* number of -NH(-) on endpoints found in restored structure */
564     short nNumTgNHRevrs;       /* number of -NH-   on endpoints found in restored structure */
565     short nNumTgNH2Revrs;      /* number of -NH2   on endpoints found in restored structure */
566     short nNumTgDBNHRevrs;     /* number of =NH    on endpoints found in restored structure */
567     short nNumTgDBNMinusRevrs; /* number of =N(-)  on endpoints found in restored structure */
568     short nNumTgDBNRevrs;      /* number of =N-    on endpoints found in restored structure */
569 
570     short nNumTgOMinusInChI;   /* number of -O(-)  on endpoints according to original InChI */
571     short nNumTgOHInChI;       /* number of -OH    on endpoints according to original InChI */
572     short nNumTgDBOInChI;      /* number of =O     on endpoints according to original InChI */
573     short nNumTgNMinusInChI;   /* number of -N(-)- on endpoints according to original InChI */
574     short nNumTgNHMinusInChI;  /* number of -NH(-) on endpoints according to original InChI */
575     short nNumTgNHInChI;       /* number of -NH-   on endpoints according to original InChI */
576     short nNumTgNH2InChI;      /* number of -NH2   on endpoints according to original InChI */
577     short nNumTgDBNHInChI;     /* number of =NH    on endpoints according to original InChI */
578     short nNumTgDBNMinusInChI; /* number of =N(-)  on endpoints according to original InChI */
579     short nNumTgDBNInChI;      /* number of =N-    on endpoints according to original InChI */
580 
581     S_CHAR nChargeMobHInChI;
582     S_CHAR nChargeMobHRevrs;
583     S_CHAR nChargeMobHRevrsNonMetal; /* charge does not include charges on metals; later add ion pairs rejection */
584     char   bFixedHLayerExistsRevrs;
585     char   bHasDifference;
586     U_CHAR nNumDiffMobH;
587 } CMP2MHINCHI;
588 
589 
590 #ifndef COMPILE_ALL_CPP
591 #ifdef __cplusplus
592 extern "C" {
593 #endif
594 #endif
595 
596 int OneInChI2Atom( ICHICONST INPUT_PARMS *ip, STRUCT_DATA *sd, const char *szCurHdr, long num_inp,
597                    StrFromINChI *pStruct, int iComponent, int iAtNoOffset, int bHasSomeFixedH, INChI *pInChI[]);
598 int get_sp_element_type( int nPeriodicNumber, int *nRow );
599 int get_bonds_valences( int nPeriodicNum, int bonds_valence, int num_H, VAL_AT *pVA );
600 
601 
602 /* local prototypes */
603 int AddExplicitDeletedH( inp_ATOM *at, int jv, int num_at, int *iDeletedH, int *iH, int nNumDeletedH, int bTwoStereo );
604 int bFindCumuleneChain( inp_ATOM *at, AT_NUMB i1, AT_NUMB i2, AT_NUMB nCumulene[], int nMaxLen );
605 int set_bond_type( inp_ATOM *at, AT_NUMB i1, AT_NUMB i2, int bType );
606 int set_cumulene_0D_parity( inp_ATOM *at, inp_ATOM_STEREO *st, int num_at, int idelH1, int i1, int i2, int idelH2, int parity, int len );
607 int set_atom_0D_parity( inp_ATOM *at, inp_ATOM_STEREO *st, int num_at, int num_deleted_H, int i1, int parity );
608 int GetTgroupInfoFromInChI( T_GROUP_INFO *ti, inp_ATOM *at, AT_NUMB *endpoint, INChI *pInChI );
609 int FillOutpStructEndpointFromInChI( INChI *pInChI, AT_NUMB **pEndpoint );
610 int SetStereoBondTypeFor0DParity( inp_ATOM *at, int i1, int m1 );
611 int SetStereoBondTypesFrom0DStereo( StrFromINChI *pStruct, INChI *pInChI);
612 void CopyAt2St( inp_ATOM *at, inp_ATOM_STEREO * st, int num_atoms );
613 void CopySt2At( inp_ATOM *at, inp_ATOM_STEREO * st, int num_atoms );
614 int RestoreAtomConnectionsSetStereo( StrFromINChI *pStruct, int iComponent, int iAtNoOffset, INChI *pInChI, INChI *pInChIMobH);
615 int RestoreAtomMakeBNS( ICHICONST INPUT_PARMS *ip, STRUCT_DATA *sd, StrFromINChI *pStruct, int iComponent,
616                         int iAtNoOffset, INChI *pInChI[], const char *szCurHdr, long num_inp, int bHasSomeFixedH );
617 int nAddSuperCGroups( ALL_TC_GROUPS *pTCGroups );
618 
619 int AddCGroups2TCGBnStruct( BN_STRUCT *pBNS, StrFromINChI *pStruct, VAL_AT *pVA,
620                             ALL_TC_GROUPS *pTCGroups, int nMaxAddEdges );
621 int AddTGroups2TCGBnStruct( BN_STRUCT *pBNS, StrFromINChI *pStruct, VAL_AT *pVA,
622                             ALL_TC_GROUPS *pTCGroups, int nMaxAddEdges );
623 BN_STRUCT* AllocateAndInitTCGBnStruct( StrFromINChI *pStruct, VAL_AT *pVA,
624                                        ALL_TC_GROUPS *pTCGroups,
625                                        int nMaxAddAtoms, int nMaxAddEdges,
626                                        int max_altp, int *pNum_changed_bonds );
627 int nCountBnsSizes( inp_ATOM *at, int num_at, int nAddEdges2eachAtom, int nAddVertices,
628                     T_GROUP_INFO *ti, VAL_AT *pVA, ICHICONST SRM *pSrm, ALL_TC_GROUPS *pTCGroups );
629 int GetAtomRestoreInfo( inp_ATOM *atom, int iat, VAL_AT *pVArray, ICHICONST SRM *pSrm, int bMobileH, AT_NUMB *endpoint );
630 int AddEdgeFlow( int edge_cap, int edge_flow, BNS_EDGE *e01, BNS_VERTEX *pv0 /*src*/,
631                   BNS_VERTEX *pv1/*dest*/, int *tot_st_cap, int *tot_st_flow );
632 void SetEdgeCapFlow( BNS_EDGE *e, int edge_cap, int edge_flow );
633 
634 void AddStCapFlow( BNS_VERTEX *vert_ficpoint, int *tot_st_flow, int *tot_st_cap, int cap, int flow );
635 void SetStCapFlow( BNS_VERTEX *vert_ficpoint, int *tot_st_flow, int *tot_st_cap, int cap, int flow );
636 
637 int ConnectSuperCGroup( int nTCG_Plus, int nAddGroups[], int num_add,
638                    int *pcur_num_vertices, int *pcur_num_edges,
639                    int *tot_st_cap, int *tot_st_flow,
640                    BN_STRUCT *pBNS, ALL_TC_GROUPS *pTCGroups );
641 int ConnectTwoVertices( BNS_VERTEX *p1, BNS_VERTEX *p2, BNS_EDGE *e, BN_STRUCT *pBNS, int bClearEdge );
642 
643 int nTautEndpointEdgeCap( inp_ATOM *at, VAL_AT *pVA, int i );
644 
645 /*
646 int GetAtomBondFlow( inp_ATOM *atom, VAL_AT *pVA, ICHICONST SRM *pSrm, int iat, int ineigh );
647 void GetAtomStCapFlow( inp_ATOM *atom, VAL_AT *pVA, ICHICONST SRM *pSrm, int iat, int *pCap, int *pFlow );
648 int GetAtomToMCGroupInitEdgeCapFlow( EdgeFlow *nEdgeCap, EdgeFlow *nEdgeFlow, ICHICONST SRM *pSrm, inp_ATOM *at, VAL_AT *pVA, int iat );
649 void GetAtomToMetalInitEdgeCapFlow( EdgeFlow *nEdgeCap, EdgeFlow *nEdgeFlow );
650 */
651 int AtomStcapStflow( inp_ATOM *atom, VAL_AT *pVA, ICHICONST SRM *pSrm, int iat, int *pnStcap, int *pnStflow,
652                      EdgeFlow *pnMGroupEdgeCap, EdgeFlow *pnMGroupEdgeFlow );
653 int BondFlowMaxcapMinorder( inp_ATOM *atom, VAL_AT *pVA, ICHICONST SRM *pSrm, int iat, int ineigh,
654                             int *pnMaxcap, int *pnMinorder, int *pbNeedsFlower );
655 
656 
657 
658 int clean_charge_val( CHARGE_VAL *pChargeVal, int len, inp_ATOM *atom, VAL_AT *pVA, int iat, int bIsMetal, int bMobileH, AT_NUMB *endpoint );
659 int ReallocTCGroups( ALL_TC_GROUPS *pTCGroups, int nAdd );
660 int RegisterTCGroup( ALL_TC_GROUPS *pTCGroups, int nGroupType, int nGroupOrdNum,
661                      int nVertexCap, int nVertexFlow, int nEdgeCap, int nEdgeFlow, int nNumEdges);
662 int CopyBnsToAtom( StrFromINChI *pStruct, BN_STRUCT  *pBNS, VAL_AT *pVA, ALL_TC_GROUPS *pTCGroups, int bAllowZeroBondOrder );
663 int CheckBnsConsistency( StrFromINChI *pStruct, BN_STRUCT  *pBNS, VAL_AT *pVA, ALL_TC_GROUPS *pTCGroups, int bNoRad );
664 
665 int RunBnsRestore1( ICHICONST INPUT_PARMS *ip, STRUCT_DATA *sd, BN_STRUCT *pBNS, BN_DATA *pBD, StrFromINChI *pStruct,
666                     VAL_AT *pVA, ALL_TC_GROUPS *pTCGroups, INChI *pInChI[], long num_inp, int bHasSomeFixedH);
667 int RunBnsRestoreOnce( BN_STRUCT *pBNS, BN_DATA *pBD, VAL_AT *pVA, ALL_TC_GROUPS *pTCGroups );
668 int nNumEdgesToCnVertex( MY_CONST C_NODE *pCN, int len, int v );
669 int ConnectMetalFlower( int *pcur_num_vertices, int *pcur_num_edges,
670                         int *tot_st_cap, int *tot_st_flow, ICHICONST SRM *pSrm,
671                         BN_STRUCT *pBNS, ALL_TC_GROUPS *pTCGroups );
672 int AddRadicalToMetal( int *tot_st_cap, int *tot_st_flow, ICHICONST SRM *pSrm, BN_STRUCT *pBNS, ALL_TC_GROUPS *pTCGroups );
673 int bMayBeACationInMobileHLayer( inp_ATOM *at, VAL_AT *pVA, int iat, int bMobileH );
674 
675 int MakeOneInChIOutOfStrFromINChI( ICHICONST INPUT_PARMS *ip, STRUCT_DATA *sd, StrFromINChI *pStruct, inp_ATOM *at2, inp_ATOM *at3, ALL_TC_GROUPS *pTCGroups );
676 void IncrZeroBondsAndClearEndpts(inp_ATOM *at, int num_at, int iComponent);
677 void IncrZeroBonds(inp_ATOM *at, int num_at, int iComponent );
678 void ClearEndpts(inp_ATOM *at, int num_at );
679 int DisplayRestoredComponent( StrFromINChI *pStruct, int iComponent, int iAtNoOffset, INChI *pInChI, const char *szCurHdr );
680 int cmp_charge_val( const void *a1, const void *a2 );
681 
682 int EvaluateChargeChanges( BN_STRUCT *pBNS, VAL_AT *pVA, int *pnDeltaH, int *pnDeltaCharge, int *pnNumVisitedAtoms );
683 int RunBnsTestOnce( BN_STRUCT *pBNS, BN_DATA *pBD, VAL_AT *pVA, Vertex *pvFirst, Vertex *pvLast,
684                     int *pPathLen, int *pnDeltaH, int *pnDeltaCharge, int *pnNumVisitedAtoms  );
685 int comp_cc_cand( const void *a1, const void *a2 );
686 int MoveRadToAtomsAddCharges( BN_STRUCT *pBNS, BN_DATA *pBD, StrFromINChI *pStruct,
687                     inp_ATOM *at, inp_ATOM *at2, VAL_AT *pVA, ALL_TC_GROUPS *pTCGroups, int forbidden_mask );
688 void RemoveForbiddenBondFlowBits( BN_STRUCT *pBNS, int forbidden_edge_mask_int );
689 int PlusFromDB_N_DB_O_to_Metal(BN_STRUCT *pBNS, BN_DATA *pBD, StrFromINChI *pStruct,
690                      inp_ATOM *at, inp_ATOM *at2, VAL_AT *pVA, ALL_TC_GROUPS *pTCGroups,
691                      int *pnNumRunBNS, int *pnTotalDelta, int forbidden_edge_mask);
692 int AdjustTgroupsToForbiddenEdges2( BN_STRUCT *pBNS, inp_ATOM *at, VAL_AT *pVA, int num_atoms, int forbidden_mask );
693 int AllocEdgeList( EDGE_LIST *pEdges, int nLen );
694 int AddToEdgeList( EDGE_LIST *pEdges, int iedge, int nAddLen );
695 int RemoveFromEdgeListByIndex( EDGE_LIST *pEdges, int index );
696 int RemoveFromEdgeListByValue( EDGE_LIST *pEdges, int iedge );
697 int FindInEdgeList( EDGE_LIST *pEdges, int iedge );
698 int AllocBfsQueue( BFS_Q *pQ, int num_at, int min_ring_size );
699 void RemoveForbiddenEdgeMask( BN_STRUCT *pBNS, EDGE_LIST *pEdges, int forbidden_edge_mask );
700 void SetForbiddenEdgeMask( BN_STRUCT *pBNS, EDGE_LIST *pEdges, int forbidden_edge_mask );
701 int ForbidCarbonChargeEdges( BN_STRUCT *pBNS, ALL_TC_GROUPS *pTCGroups, EDGE_LIST *pCarbonChargeEdges, int forbidden_edge_mask );
702 int ForbidMetalCarbonEdges( BN_STRUCT *pBNS, inp_ATOM *at, int num_at, VAL_AT *pVA,
703                            ALL_TC_GROUPS *pTCGroups, EDGE_LIST *pMetalCarbonEdges, int forbidden_edge_mask );
704 int ForbidNintrogenPlus2BondsInSmallRings( BN_STRUCT *pBNS, inp_ATOM *at, int num_at,
705                                            VAL_AT *pVA, int min_ring_size, ALL_TC_GROUPS *pTCGroups,
706                                            EDGE_LIST *pNplus2BondsEdges, int forbidden_edge_mask );
707 int RearrangePlusMinusEdgesFlow( BN_STRUCT *pBNS, BN_DATA *pBD, VAL_AT *pVA,
708                                  ALL_TC_GROUPS *pTCGroups, int forbidden_edge_mask );
709 int IncrementZeroOrderBondsToHeteroat( BN_STRUCT *pBNS, BN_DATA *pBD, StrFromINChI *pStruct,
710                                             inp_ATOM *at, inp_ATOM *at2,
711                                             VAL_AT *pVA, ALL_TC_GROUPS *pTCGroups,
712                                             int *pnNumRunBNS, int *pnTotalDelta,
713                                             int forbidden_edge_mask);
714 int MoveChargeFromHeteroatomsToMetals( BN_STRUCT *pBNS, BN_DATA *pBD, StrFromINChI *pStruct,
715                                        inp_ATOM *at, inp_ATOM *at2,
716                                        VAL_AT *pVA, ALL_TC_GROUPS *pTCGroups,
717                                        int *pnNumRunBNS, int *pnTotalDelta,
718                                        int forbidden_edge_mask);
719 int EliminateChargeSeparationOnHeteroatoms( BN_STRUCT *pBNS, BN_DATA *pBD, StrFromINChI *pStruct,
720                                             inp_ATOM *at, inp_ATOM *at2,
721                                             VAL_AT *pVA, ALL_TC_GROUPS *pTCGroups,
722                                             int *pnNumRunBNS, int *pnTotalDelta,
723                                             int forbidden_edge_mask, int forbidden_stereo_edge_mask);
724 int MovePlusFromS2DiaminoCarbon( BN_STRUCT *pBNS, BN_DATA *pBD, StrFromINChI *pStruct,
725                     inp_ATOM *at, inp_ATOM *at2,
726                     VAL_AT *pVA, ALL_TC_GROUPS *pTCGroups,
727                     int *pnNumRunBNS, int *pnTotalDelta, int forbidden_edge_mask);
728 int RestoreCyanoGroup( BN_STRUCT *pBNS, BN_DATA *pBD, StrFromINChI *pStruct,
729                      inp_ATOM *at, inp_ATOM *at2, VAL_AT *pVA, ALL_TC_GROUPS *pTCGroups,
730                      int *pnNumRunBNS, int *pnTotalDelta, int forbidden_edge_mask);
731 int RestoreIsoCyanoGroup( BN_STRUCT *pBNS, BN_DATA *pBD, StrFromINChI *pStruct,
732                      inp_ATOM *at, inp_ATOM *at2, VAL_AT *pVA, ALL_TC_GROUPS *pTCGroups,
733                      int *pnNumRunBNS, int *pnTotalDelta, int forbidden_edge_mask);
734 int RestoreNNNgroup( BN_STRUCT *pBNS, BN_DATA *pBD, StrFromINChI *pStruct,
735                      inp_ATOM *at, inp_ATOM *at2, VAL_AT *pVA, ALL_TC_GROUPS *pTCGroups,
736                      int *pnNumRunBNS, int *pnTotalDelta, int forbidden_edge_mask);
737 int FixMetal_Nminus_Ominus( BN_STRUCT *pBNS, BN_DATA *pBD, StrFromINChI *pStruct,
738                      inp_ATOM *at, inp_ATOM *at2, VAL_AT *pVA, ALL_TC_GROUPS *pTCGroups,
739                      int *pnNumRunBNS, int *pnTotalDelta, int forbidden_edge_mask);
740 int EliminateNitrogen5Val3Bonds(BN_STRUCT *pBNS, BN_DATA *pBD, StrFromINChI *pStruct,
741                      inp_ATOM *at, inp_ATOM *at2, VAL_AT *pVA, ALL_TC_GROUPS *pTCGroups,
742                      int *pnNumRunBNS, int *pnTotalDelta, int forbidden_edge_mask);
743 int Convert_SIV_to_SVI(BN_STRUCT *pBNS, BN_DATA *pBD, StrFromINChI *pStruct,
744                      inp_ATOM *at, inp_ATOM *at2, VAL_AT *pVA, ALL_TC_GROUPS *pTCGroups,
745                      int *pnNumRunBNS, int *pnTotalDelta, int forbidden_edge_mask);
746 int MoveMobileHToAvoidFixedBonds(BN_STRUCT *pBNS, BN_DATA *pBD, StrFromINChI *pStruct,
747                               inp_ATOM *at, inp_ATOM *at2, VAL_AT *pVA, ALL_TC_GROUPS *pTCGroups,
748                               int *pnNumRunBNS, int *pnTotalDelta, int forbidden_edge_mask);
749 int RemoveRadFromMobileHEndpoint(BN_STRUCT *pBNS, BN_DATA *pBD, StrFromINChI *pStruct,
750                               inp_ATOM *at, inp_ATOM *at2, VAL_AT *pVA, ALL_TC_GROUPS *pTCGroups,
751                               int *pnNumRunBNS, int *pnTotalDelta, int forbidden_edge_mask);
752 int RemoveRadFromMobileHEndpointFixH(BN_STRUCT *pBNS, BN_DATA *pBD, StrFromINChI *pStruct,
753                               inp_ATOM *at, inp_ATOM *at2, VAL_AT *pVA, ALL_TC_GROUPS *pTCGroups,
754                               int *pnNumRunBNS, int *pnTotalDelta, int forbidden_edge_mask);
755 int MoveChargeToMakeCenerpoints(BN_STRUCT *pBNS, BN_DATA *pBD, StrFromINChI *pStruct,
756                               inp_ATOM *at, inp_ATOM *at2, VAL_AT *pVA, ALL_TC_GROUPS *pTCGroups,
757                               int *pnNumRunBNS, int *pnTotalDelta, int forbidden_edge_mask);
758 int CheckAndRefixStereobonds(BN_STRUCT *pBNS, BN_DATA *pBD, StrFromINChI *pStruct,
759                               inp_ATOM *at, inp_ATOM *at2, VAL_AT *pVA, ALL_TC_GROUPS *pTCGroups,
760                               int *pnNumRunBNS, int *pnTotalDelta, int forbidden_edge_mask);
761 int MoveChargeToRemoveCenerpoints(BN_STRUCT *pBNS, BN_DATA *pBD, StrFromINChI *pStruct,
762                               inp_ATOM *at, inp_ATOM *at2, VAL_AT *pVA, ALL_TC_GROUPS *pTCGroups,
763                               int *pnNumRunBNS, int *pnTotalDelta, int forbidden_edge_mask);
764 int MakeSingleBondsMetal2ChargedHeteroat(BN_STRUCT *pBNS, BN_DATA *pBD, StrFromINChI *pStruct,
765                               inp_ATOM *at, inp_ATOM *at2, VAL_AT *pVA, ALL_TC_GROUPS *pTCGroups,
766                               int *pnNumRunBNS, int *pnTotalDelta, int forbidden_edge_mask);
767 int SaltBondsToCoordBonds(BN_STRUCT *pBNS, BN_DATA *pBD, StrFromINChI *pStruct,
768                           inp_ATOM *at, inp_ATOM *at2, VAL_AT *pVA, ALL_TC_GROUPS *pTCGroups,
769                           int *pnNumRunBNS, int *pnTotalDelta, int forbidden_edge_mask);
770 int FixLessHydrogenInFormula( BN_STRUCT *pBNS, BN_DATA *pBD, StrFromINChI *pStruct, inp_ATOM *at,
771                               inp_ATOM *at2, inp_ATOM *atf, VAL_AT *pVA, ALL_TC_GROUPS *pTCGroups,
772                               int *pnNumRunBNS, int *pnTotalDelta, int forbidden_edge_mask );
773 int FixMoreHydrogenInFormula( BN_STRUCT *pBNS, BN_DATA *pBD, StrFromINChI *pStruct, inp_ATOM *at,
774                               inp_ATOM *at2, inp_ATOM *atf, VAL_AT *pVA, ALL_TC_GROUPS *pTCGroups,
775                               int *pnNumRunBNS, int *pnTotalDelta, int forbidden_edge_mask );
776 int FixAddProtonForADP( BN_STRUCT *pBNS, BN_DATA *pBD, StrFromINChI *pStruct, inp_ATOM *at,
777                               inp_ATOM *at2, inp_ATOM *atf, VAL_AT *pVA, ALL_TC_GROUPS *pTCGroups, ICR *picr,
778                               int *pnNumRunBNS, int *pnTotalDelta, int forbidden_edge_mask );
779 int ConnectDisconnectedH( inp_ATOM *at, int num_atoms, int num_deleted_H );
780 int DisconnectedConnectedH( inp_ATOM *at, int num_atoms, int num_deleted_H );
781 int MakeInChIOutOfStrFromINChI2( ICHICONST INPUT_PARMS *ip_inp, STRUCT_DATA *sd_inp, StrFromINChI *pStruct,
782                                  int iComponent, int iAtNoOffset, long num_inp );
783 int GetChargeFlowerUpperEdge( BN_STRUCT *pBNS, VAL_AT *pVA, int nChargeEdge );
784 int get_pVA_atom_type( VAL_AT *pVA, inp_ATOM *at, int iat, int bond_type );
785 
786 int NormalizeAndCompare(ICHICONST INPUT_PARMS *ip, STRUCT_DATA *sd, BN_STRUCT *pBNS, BN_DATA *pBD,
787                         StrFromINChI *pStruct, inp_ATOM *at, inp_ATOM *at2, inp_ATOM *at3, VAL_AT *pVA,
788                         ALL_TC_GROUPS *pTCGroups, INChI *pInChI[], long num_inp, int bHasSomeFixedH,
789                         int *pnNumRunBNS, int *pnTotalDelta, int forbidden_edge_mask, int forbidden_stereo_edge_mask);
790 /* call InChI normalization only */
791 int NormalizeStructure( ICHICONST INPUT_PARMS *ip, STRUCT_DATA *sd, BN_STRUCT *pBNS,
792                         StrFromINChI *pStruct, inp_ATOM *at, inp_ATOM *at2,
793                         VAL_AT *pVA, ALL_TC_GROUPS *pTCGroups,
794                         inp_ATOM *at_norm, inp_ATOM *at_fixed_bonds_out, T_GROUP_INFO *t_group_info );
795 /* create one InChI */
796 int MakeOneInChIOutOfStrFromINChI2( ICHICONST INPUT_PARMS *ip, STRUCT_DATA *sd, BN_STRUCT *pBNS, StrFromINChI *pStruct,
797                                     inp_ATOM *at, inp_ATOM *at2, inp_ATOM *at3, VAL_AT *pVA, ALL_TC_GROUPS *pTCGroups,
798                                     T_GROUP_INFO **t_group_info, inp_ATOM **at_norm, inp_ATOM **at_prep );
799 /* fixed-H */
800 int  FillOutExtraFixedHDataRestr( StrFromINChI *pStruct );
801 int  FillOutExtraFixedHDataInChI( StrFromINChI *pStruct, INChI *pInChI[] );
802 int FixFixedHRestoredStructure(ICHICONST INPUT_PARMS *ip, STRUCT_DATA *sd, BN_STRUCT *pBNS, BN_DATA *pBD,
803                         StrFromINChI *pStruct, inp_ATOM *at, inp_ATOM *at2, inp_ATOM *at3, VAL_AT *pVA,
804                         ALL_TC_GROUPS *pTCGroups, T_GROUP_INFO **ti, inp_ATOM **at_norm, inp_ATOM **at_prep,
805                         INChI *pInChI[], long num_inp, int bHasSomeFixedH, int *pnNumRunBNS, int *pnTotalDelta,
806                         int forbidden_edge_mask, int forbidden_stereo_edge_mask);
807 int FixRemoveExtraTautEndpoints( BN_STRUCT *pBNS, BN_DATA *pBD, StrFromINChI *pStruct, inp_ATOM *at,
808                               inp_ATOM *at2, inp_ATOM *atf, inp_ATOM *atn, VAL_AT *pVA, ALL_TC_GROUPS *pTCGroups, ICR *picr,
809                               int *pnNumRunBNS, int *pnTotalDelta, int forbidden_edge_mask );
810 int FillOutCMP2FHINCHI( StrFromINChI *pStruct, inp_ATOM *at2, VAL_AT *pVA, INChI *pInChI[], CMP2FHINCHI *pc2i );
811 int FillOutCMP2MHINCHI( StrFromINChI *pStruct, ALL_TC_GROUPS *pTCGroups, inp_ATOM *at2,
812                         VAL_AT *pVA, INChI *pInChI[], CMP2MHINCHI *pc2i );
813 
814 int bHas_N_V( inp_ATOM *at2, int num_atoms );
815 
816 int GetPlusMinusVertex( BN_STRUCT *pBNS, ALL_TC_GROUPS *pTCGroups, int bCheckForbiddenPlus, int bCheckForbiddenMinus );
817 int FixMobileHRestoredStructure(ICHICONST INPUT_PARMS *ip, STRUCT_DATA *sd, BN_STRUCT *pBNS, BN_DATA *pBD,
818                         StrFromINChI *pStruct, inp_ATOM *at, inp_ATOM *at2, inp_ATOM *at3, VAL_AT *pVA,
819                         ALL_TC_GROUPS *pTCGroups, T_GROUP_INFO **ppt_group_info, inp_ATOM **ppat_norm,
820                         inp_ATOM **ppat_prep, INChI *pInChI[], long num_inp, int bHasSomeFixedH,
821                         int *pnNumRunBNS, int *pnTotalDelta, int forbidden_edge_mask, int forbidden_stereo_edge_mask);
822 
823 int FixRestoredStructureStereo( INCHI_MODE cmpInChI, ICR *icr, INCHI_MODE cmpInChI2, ICR *icr2,
824                         ICHICONST INPUT_PARMS *ip, STRUCT_DATA *sd, BN_STRUCT *pBNS, BN_DATA *pBD,
825                         StrFromINChI *pStruct, inp_ATOM *at, inp_ATOM *at2, inp_ATOM *at3, VAL_AT *pVA,
826                         ALL_TC_GROUPS *pTCGroups, T_GROUP_INFO **ppt_group_info, inp_ATOM **ppat_norm,
827                         inp_ATOM **ppat_prep, INChI *pInChI[], long num_inp,
828                         int *pnNumRunBNS, int *pnTotalDelta, int forbidden_edge_mask, int forbidden_stereo_edge_mask);
829 
830 int AddRemProtonsInRestrStruct( ICHICONST INPUT_PARMS *ip,  STRUCT_DATA *sd, long num_inp,
831                                 int bHasSomeFixedH,
832                                 StrFromINChI *pStruct, int num_components,
833                                 StrFromINChI *pStructR, int num_componentsR,
834                                 NUM_H *pProtonBalance, int *recmet_change_balance );
835 int AllInchiToStructure( ICHICONST INPUT_PARMS *ip, STRUCT_DATA *sd, long num_inp, char *szCurHdr,
836                          ICHICONST SRM *pSrm, int bReqNonTaut, StrFromINChI *pStruct[INCHI_NUM][TAUT_NUM],
837                          InpInChI *pOneInput );
838 int AddProtonAndIsoHBalanceToMobHStruct( ICHICONST INPUT_PARMS *ip, STRUCT_DATA *sd,
839                                         long num_inp, int bHasSomeFixedH, char *szCurHdr,
840                              StrFromINChI *pStruct[INCHI_NUM][TAUT_NUM], InpInChI *pOneInput);
841 int InChI2Atom( ICHICONST INPUT_PARMS *ip,  STRUCT_DATA *sd, const char *szCurHdr, long num_inp,
842                 StrFromINChI *pStruct, int iComponent, int iAtNoOffset, int  bI2A_Flag, int bHasSomeFixedH, InpInChI *pOneInput);
843 
844 int MarkDisconectedIdenticalToReconnected ( InpInChI *pOneInput );
845 void RemoveFixHInChIIdentical2MobH( InpInChI *pOneInput );
846 void SetUpSrm( SRM *pSrm );
847 void FreeInpInChI( InpInChI *pOneInput );
848 void FreeStrFromINChI( StrFromINChI *pStruct[INCHI_NUM][TAUT_NUM], int nNumComponents[INCHI_NUM][TAUT_NUM] );
849 int OldPrintCompareOneOrigInchiToRevInChI(StrFromINChI *pStruct, INChI *pInChI[TAUT_NUM], int bMobileH,
850                                           int iComponent, long num_inp, char *szCurHdr);
851 int CompareOneOrigInchiToRevInChI(StrFromINChI *pStruct, INChI *pInChI[TAUT_NUM], int bMobileH, int iComponent,
852                                   long num_inp, char *szCurHdr,
853                                   COMPONENT_REM_PROTONS *nCurRemovedProtons, INCHI_MODE CompareInchiFlags[]);
854 int CompareTwoPairsOfInChI( INChI *pInChI1[TAUT_NUM], INChI *pInChI2[TAUT_NUM],
855                             int bMobileH, INCHI_MODE CompareInchiFlags[] );
856 INCHI_MODE CompareReversedINChI3( INChI *i1 /* InChI from reversed struct */, INChI *i2 /* input InChI */,
857                                   INChI_Aux *a1, INChI_Aux *a2, int *err );
858 INCHI_MODE CompareReversedStereoINChI3( INChI_Stereo *s1/* InChI from reversed struct */, INChI_Stereo *s2 /* input InChI */, ICR *picr);
859 int CompareAllOrigInchiToRevInChI(StrFromINChI *pStruct[INCHI_NUM][TAUT_NUM], InpInChI *pOneInput, int bReqNonTaut,
860                                   long num_inp, char *szCurHdr);
861 int CompareAllDisconnectedOrigInchiToRevInChI(StrFromINChI *pStruct[INCHI_NUM][TAUT_NUM],
862                                               InpInChI *pOneInput, int bHasSomeFixedH,
863                                               long num_inp, char *szCurHdr);
864 int insertions_sort_AT_NUMB( AT_NUMB *base, int num );
865 
866 int AddRemIsoProtonsInRestrStruct( ICHICONST INPUT_PARMS *ip,  STRUCT_DATA *sd, long num_inp, int bHasSomeFixedH,
867                                 StrFromINChI *pStruct, int num_components,
868                                 StrFromINChI *pStructR, int num_componentsR,
869                                 NUM_H pProtonBalance[], NUM_H recmet_change_balance[] );
870 int OutputInChIOutOfStrFromINChI(ICHICONST INPUT_PARMS *ip_inp, STRUCT_DATA *sd_inp,
871                                  long num_inp, int bINChIOutputOptions,
872                                  INCHI_IOSTREAM *pout, INCHI_IOSTREAM *plog,
873                                  InpInChI *pOneInput, int bHasSomeFixedH,
874                                  unsigned char save_opt_bits);
875 
876 int MergeStructureComponents( ICHICONST INPUT_PARMS *ip, STRUCT_DATA *sd, long num_inp, char *szCurHdr,
877                          ICHICONST SRM *pSrm, int bReqNonTaut, StrFromINChI *pStruct[INCHI_NUM][TAUT_NUM],
878                          InpInChI *pOneInput );
879 int AddOneMsg( char *szMsg, int used_len, int tot_len, const char *szAddMsg, const char *szDelim );
880 int FillOutCompareMessage( char *szMsg, int nLenMsg, INCHI_MODE bits[] );
881 void clear_t_group_info( T_GROUP_INFO *ti );
882 int bInpInchiComponentExists( InpInChI *pOneInput, int iINCHI, int bMobileH, int k );
883 int bInpInchiComponentDeleted( InpInChI *pOneInput, int iInChI, int bMobileH, int k );
884 int bRevInchiComponentExists( StrFromINChI *pStruct, int iInChI, int bMobileH, int k );
885 int bRevInchiComponentDeleted( StrFromINChI *pStruct, int iInChI, int bMobileH, int k );
886 int DetectInpInchiCreationOptions ( InpInChI *pOneInput, int *bHasReconnected, int *bHasMetal,
887                                     int *bHasFixedH, int *sFlag, int *bTautFlag );
888 int DisplayStructureComponents( ICHICONST INPUT_PARMS *ip, STRUCT_DATA *sd, long num_inp, char *szCurHdr,
889                          ICHICONST SRM *pSrm, int bReqNonTaut, StrFromINChI *pStruct[INCHI_NUM][TAUT_NUM],
890                          InpInChI *pOneInput );
891 int DisplayOneRestoredComponent( StrFromINChI *pStruct, inp_ATOM *at,
892                                  int iComponent, int nNumComponents, int bMobileH,
893                                  const char *szCurHdr );
894 int DisplayAllRestoredComponents( inp_ATOM *at, int num_at, const char *szCurHdr );
895 int CountStereoTypes( INChI *pInChI, int *num_known_SB, int *num_known_SC,
896                                      int *num_unk_und_SB, int *num_unk_und_SC,
897                                      int *num_SC_PIII, int *num_SC_AsIII);
898 int GetNumNeighborsFromInchi( INChI *pInChI, AT_NUMB nAtNumber );
899 int bIsUnsatCarbonInASmallRing( inp_ATOM *at, VAL_AT *pVA, int iat, BFS_Q *pbfsq, int min_ring_size );
900 
901 int MakeProtonComponent( StrFromINChI *pStruct, int iComponent, int num_prot );
902 
903 /* extra configurarion */
904 #define KEEP_METAL_EDGE_FLOW                 0  /* counterexample: mdb0-1738.sdf.txt */
905 #define MOVE_CHARGES_FROM_HETEREO_TO_METAL   0  /* disabled */
906 #define FIX_ADD_PROTON_FOR_ADP               0  /* not used */
907 
908 #ifndef COMPILE_ALL_CPP
909 #ifdef __cplusplus
910 }
911 #endif
912 #endif
913 
914 
915 #endif
916