~ubuntu-branches/debian/stretch/openbabel/stretch

« back to all changes in this revision

Viewing changes to src/formats/inchi103/ichirvr6.c

  • Committer: Package Import Robot
  • Author(s): Daniel Leidert
  • Date: 2013-05-22 19:08:27 UTC
  • mfrom: (1.1.11) (7.1.9 sid)
  • Revision ID: package-import@ubuntu.com-20130522190827-72q0fnx5y2nm3bc0
Tags: 2.3.2+dfsg-1
* New upstream release.
* debian/control: Dropped DM-Upload-Allowed field.
  (Standards-Version): Bumped to 3.9.4.
* debian/copyright: Massive update.
* debian/upstream: Author name update.
* debian/get-orig-source.sh: Remove the windows-*/ directory too.
* debian/openbabel.install: Removed roundtrip manpage.
* debian/openbabel-gui.install: Fixed manpage name.
* debian/openbabel-gui.links: Removed unused file.
* debian/rules: Enable OpenMP. Disable tests on `nocheck'.
* debian/patches/gaussformat_nosym.patch: Dropped. Applied upstream.
* debian/patches/moldenformat_coordonly.patch: Ditto.
* debian/patches/obspectrophore_man.patch: Ditto.
* debian/patches/fix_ftbfs.patch: Added.
  - Fix several FTBFS issues in upstream build system.
* debian/patches/series: Adjusted.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/*
2
 
 * International Chemical Identifier (InChI)
3
 
 * Version 1
4
 
 * Software version 1.03
5
 
 * May 9, 2010
6
 
 *
7
 
 * Originally developed at NIST
8
 
 * Modifications and additions by IUPAC and the InChI Trust
9
 
 *
10
 
 * The InChI library and programs are free software developed under the
11
 
 * auspices of the International Union of Pure and Applied Chemistry (IUPAC);
12
 
 * you can redistribute this software and/or modify it under the terms of 
13
 
 * the GNU Lesser General Public License as published by the Free Software 
14
 
 * Foundation:
15
 
 * http://www.opensource.org/licenses/lgpl-2.1.php
16
 
 */
17
 
 
18
 
 
19
 
#include <stdio.h>
20
 
#include <stdlib.h>
21
 
#include <string.h>
22
 
 
23
 
/*#define CHECK_WIN32_VC_HEAP*/
24
 
#include "mode.h"
25
 
 
26
 
#if( READ_INCHI_STRING == 1 )
27
 
 
28
 
#include "ichi.h"
29
 
#include "ichitime.h"
30
 
 
31
 
#include "inpdef.h"
32
 
#include "ichimain.h"
33
 
#include "ichierr.h"
34
 
#include "incomdef.h"
35
 
#include "ichiring.h"
36
 
#include "extr_ct.h"
37
 
#include "ichitaut.h"
38
 
#include "ichinorm.h"
39
 
#include "util.h"
40
 
 
41
 
#include "ichicomp.h"
42
 
#include "ichister.h"
43
 
 
44
 
#include "ichi_bns.h"
45
 
 
46
 
#include "strutil.h"
47
 
 
48
 
#include "ichirvrs.h"
49
 
 
50
 
 
51
 
#define INC_ADD_EDGE 64
52
 
/***********************************************************************************************/
53
 
int FixRestoredStructureStereo( INCHI_MODE cmpInChI, ICR *icr, INCHI_MODE cmpInChI2, ICR *icr2,
54
 
                        ICHICONST INPUT_PARMS *ip, STRUCT_DATA *sd, BN_STRUCT *pBNS, BN_DATA *pBD,
55
 
                        StrFromINChI *pStruct, inp_ATOM *at, inp_ATOM *at2, inp_ATOM *at3, VAL_AT *pVA,
56
 
                        ALL_TC_GROUPS *pTCGroups, T_GROUP_INFO **ppt_group_info, inp_ATOM **ppat_norm,
57
 
                        inp_ATOM **ppat_prep, INChI *pInChI[], long num_inp,
58
 
                        int *pnNumRunBNS, int *pnTotalDelta, int forbidden_edge_mask, int forbidden_stereo_edge_mask)
59
 
{
60
 
    /*--------- process extra or missing Fixed-H on non-tautomeric atoms ------*/
61
 
    /* at2 should be the most recently restored atom, Fixed-H */
62
 
    int i, j, k, delta, tot_succes, max_success, cur_success, ret = 0;
63
 
    int err, iOrigInChI, iRevrInChI;
64
 
    int j12, v1, v2, e, vRad;
65
 
    BNS_VERTEX *pv1, *pv2, *pvRad;
66
 
    BNS_EDGE   *pe, *peRad;
67
 
    EDGE_LIST AllChargeEdges, CurrEdges, NFlowerEdges, OtherNFlowerEdges, FixedStereoEdges, AllRadList;
68
 
    EDGE_LIST TautMinusEdges[2]; /* 0 -> O & O(+), 1=> N & N(+) */
69
 
 
70
 
    Vertex     vPathStart, vPathEnd;
71
 
    int        nPathLen, nDeltaH, nDeltaCharge, nNumVisitedAtoms;
72
 
    INChI_Stereo *pStereoInChI, *pStereo2InChI, *pStereoRevrs, *pStereo2Revrs; 
73
 
    
74
 
    /* Stereo */
75
 
 
76
 
    /* currently being processed layer */
77
 
    pStereoInChI = (pInChI[0]->StereoIsotopic &&
78
 
               pInChI[0]->StereoIsotopic->nNumberOfStereoBonds +
79
 
               pInChI[0]->StereoIsotopic->nNumberOfStereoCenters)?
80
 
               pInChI[0]->StereoIsotopic : pInChI[0]->Stereo;
81
 
 
82
 
    /* mobile-H layer in case of Fixed-H */
83
 
    pStereo2InChI = (pStruct->bMobileH == TAUT_YES || !pInChI[1] ||
84
 
               !pInChI[1]->nNumberOfAtoms || pInChI[1]->bDeleted)?
85
 
                        NULL:
86
 
               (pInChI[1]->StereoIsotopic &&
87
 
               pInChI[1]->StereoIsotopic->nNumberOfStereoBonds +
88
 
               pInChI[1]->StereoIsotopic->nNumberOfStereoCenters)?
89
 
                        pInChI[1]->StereoIsotopic :
90
 
                        pInChI[1]->Stereo;
91
 
 
92
 
    /* currently being processed layer */
93
 
    pStereoRevrs = (pStruct->pOneINChI[0]->StereoIsotopic &&
94
 
               pStruct->pOneINChI[0]->StereoIsotopic->nNumberOfStereoBonds +
95
 
               pStruct->pOneINChI[0]->StereoIsotopic->nNumberOfStereoCenters)?
96
 
               pStruct->pOneINChI[0]->StereoIsotopic : pStruct->pOneINChI[0]->Stereo;
97
 
 
98
 
    /* mobile-H layer in case of Fixed-H */
99
 
    pStereo2Revrs = (pStruct->bMobileH == TAUT_YES || !pStruct->pOneINChI[1] ||
100
 
               !pStruct->pOneINChI[1]->nNumberOfAtoms || pStruct->pOneINChI[1]->bDeleted)?
101
 
                        NULL:
102
 
               (pStruct->pOneINChI[1]->StereoIsotopic &&
103
 
               pStruct->pOneINChI[1]->StereoIsotopic->nNumberOfStereoBonds +
104
 
               pStruct->pOneINChI[1]->StereoIsotopic->nNumberOfStereoCenters)?
105
 
                        pStruct->pOneINChI[1]->StereoIsotopic :
106
 
                        pStruct->pOneINChI[1]->Stereo;
107
 
    
108
 
    INCHI_HEAPCHK
109
 
 
110
 
    AllocEdgeList( &AllChargeEdges, EDGE_LIST_CLEAR );
111
 
    AllocEdgeList( &CurrEdges, EDGE_LIST_CLEAR );
112
 
    AllocEdgeList( &NFlowerEdges, EDGE_LIST_CLEAR );
113
 
    AllocEdgeList( &OtherNFlowerEdges, EDGE_LIST_CLEAR );
114
 
    AllocEdgeList( &FixedStereoEdges, EDGE_LIST_CLEAR );
115
 
    AllocEdgeList( &AllRadList, EDGE_LIST_CLEAR );
116
 
 
117
 
    AllocEdgeList( TautMinusEdges+0, EDGE_LIST_CLEAR );
118
 
    AllocEdgeList( TautMinusEdges+1, EDGE_LIST_CLEAR );
119
 
 
120
 
    cmpInChI = CompareReversedINChI2( pStruct->pOneINChI[0], pInChI[0], pStruct->pOneINChI_Aux[0], NULL /*INChI_Aux *v2*/, icr, &err );
121
 
    if ( cmpInChI & IDIF_PROBLEM ) {
122
 
        ret = RI_ERR_PROGR; /* severe restore problem */
123
 
        goto exit_function;
124
 
    }
125
 
    if ( err ) {
126
 
        ret = RI_ERR_ALLOC;
127
 
        goto exit_function;
128
 
    }
129
 
 
130
 
    cmpInChI2 = 0;
131
 
 
132
 
    if ( pStruct->bMobileH == TAUT_NON ) {
133
 
        /* these indexes are used to compare Mobile-H InChI */
134
 
        iOrigInChI = (pInChI[1] && pInChI[1]->nNumberOfAtoms && !pInChI[1]->bDeleted)? 1 : 0;
135
 
        iRevrInChI = (pStruct->pOneINChI[1] &&pStruct->pOneINChI[1]->nNumberOfAtoms && !pStruct->pOneINChI[1]->bDeleted)? 1 : 0;
136
 
    } else {
137
 
        iOrigInChI = 0;
138
 
        iRevrInChI = 0;
139
 
    }
140
 
 
141
 
    memset ( icr2, 0, sizeof(*icr2) );
142
 
    if ( iRevrInChI || iOrigInChI ) {
143
 
        /* additional mobile-H compare in case of Fixed-H */
144
 
        cmpInChI2 = CompareReversedINChI2( pStruct->pOneINChI[iRevrInChI], pInChI[iOrigInChI], pStruct->pOneINChI_Aux[iRevrInChI], NULL /*INChI_Aux *v2*/, icr2, &err );
145
 
        if ( cmpInChI & IDIF_PROBLEM ) {
146
 
            ret = RI_ERR_PROGR; /* severe restore problem */
147
 
            goto exit_function;
148
 
        }
149
 
        if ( err ) {
150
 
            ret = RI_ERR_ALLOC;
151
 
            goto exit_function;
152
 
        }
153
 
    }
154
 
 
155
 
 
156
 
    if ( !(cmpInChI & IDIFF_SB) && !(cmpInChI2 & IDIFF_SB) ) {
157
 
        goto exit_function;
158
 
    }
159
 
    /* need to temporarily remove fixing of stereogenic bonds */
160
 
    for ( i = 0; i < pStruct->num_atoms; i ++ ) {
161
 
        pv1 = pBNS->vert + i;
162
 
        for ( j = 0; j < at2[i].valence; j ++ ) {
163
 
            pe = pBNS->edge + (e=pv1->iedge[j]);
164
 
            if ( j == pe->neighbor1 ) {
165
 
                /* do not store same bond 2 times */
166
 
                if ( (pe->forbidden & forbidden_stereo_edge_mask) &&
167
 
                     (ret = AddToEdgeList( &FixedStereoEdges, e, INC_ADD_EDGE ) ) ) {
168
 
                    goto exit_function;
169
 
                }
170
 
            }
171
 
        }
172
 
    }
173
 
 
174
 
 
175
 
    tot_succes  = 0;
176
 
    cur_success = 0;
177
 
    if ( (cmpInChI & IDIF_SB_MISS) && (!cmpInChI2 || (cmpInChI2 & IDIF_SB_MISS)) &&
178
 
         0 < (max_success = pBNS->tot_st_cap - pBNS->tot_st_flow) ) {
179
 
        /*----------------------------------------------------*/
180
 
        /* case 01: extra stereogenic bond, radical present   */
181
 
        /* X=N-O*  => X=N=O and eliminate radical             */
182
 
        /*----------------------------------------------------*/
183
 
        int aN;
184
 
        BNS_VERTEX *pvO, *pvN;
185
 
        BNS_EDGE   *peNO;
186
 
 
187
 
        RemoveForbiddenEdgeMask( pBNS, &FixedStereoEdges, forbidden_stereo_edge_mask  );
188
 
 
189
 
        for ( i = 0; i < icr->num_sb_in2_only && cur_success < max_success; i ++ ) {
190
 
            j12 = icr->sb_in2_only[i];
191
 
            pv1 = pBNS->vert + (v1 = pStereoInChI->nBondAtom1[j12]-1);
192
 
            pv2 = pBNS->vert + (v2 = pStereoInChI->nBondAtom2[j12]-1);
193
 
            for ( k = 0; k < at2[v1].valence; k ++ ) {
194
 
                pe = pBNS->edge + (e = pv1->iedge[k]);
195
 
                if ( v2 == (pe->neighbor12 ^ v1) )
196
 
                    break; /* the edge has been found */
197
 
            }
198
 
            if ( k == at2[v1].valence ) {
199
 
                ret = RI_ERR_SYNTAX;
200
 
                goto exit_function;
201
 
            }
202
 
            /* check v1 */
203
 
            pv1->st_edge.cap --;
204
 
            pv1->st_edge.flow --;
205
 
            pv2->st_edge.flow --;
206
 
            pe->flow --; /* new radical on v2 */
207
 
            vRad = NO_VERTEX;
208
 
            ret = RunBnsTestOnce( pBNS, pBD, pVA, &vPathStart, &vPathEnd, &nPathLen,
209
 
                                  &nDeltaH, &nDeltaCharge, &nNumVisitedAtoms );
210
 
            pv1->st_edge.cap ++;
211
 
            pv1->st_edge.flow ++;
212
 
            pv2->st_edge.flow ++;
213
 
            pe->flow ++; /* remove new radical on v2 */
214
 
 
215
 
            if ( ret == 1 /*&& !nDeltaH*/ && !nDeltaCharge && (v2 == vPathStart || v2 == vPathEnd) ) {
216
 
                vRad = (v2 == vPathStart)? vPathEnd : vPathStart;
217
 
            } else {
218
 
                pv2->st_edge.cap --;
219
 
                pv2->st_edge.flow --;
220
 
                pv1->st_edge.flow --;
221
 
                pe->flow --; /* new radical on v1 */
222
 
                vRad = NO_VERTEX;
223
 
                ret = RunBnsTestOnce( pBNS, pBD, pVA, &vPathStart, &vPathEnd, &nPathLen,
224
 
                                      &nDeltaH, &nDeltaCharge, &nNumVisitedAtoms );
225
 
                pv2->st_edge.cap ++;
226
 
                pv2->st_edge.flow ++;
227
 
                pv1->st_edge.flow ++;
228
 
                pe->flow ++; /* remove new radical on v1 */
229
 
                if ( ret == 1 /*&& !nDeltaH*/ && !nDeltaCharge && (v1 == vPathStart || v1 == vPathEnd) ) {
230
 
                    vRad = (v1 == vPathStart)? vPathEnd : vPathStart;
231
 
                }
232
 
            }
233
 
            if ( vRad == NO_VERTEX ) {
234
 
                continue; /* radical did not affect this bond */
235
 
            }
236
 
            pvRad = pBNS->vert + vRad;
237
 
            /* detect =N-O*  */
238
 
            if ( pVA[vRad].cNumValenceElectrons == 6 && at2[vRad].valence == 1 &&
239
 
                 (peRad = pBNS->edge + pvRad->iedge[0])->flow == 0 &&
240
 
                 pVA[aN = peRad->neighbor12 ^ vRad].cNumValenceElectrons == 5 &&
241
 
                 at2[aN].valence == 2 ) {
242
 
                /*------------------------------------------------------------ 
243
 
                  Fix Metal disconnection/normalization inconsistency :
244
 
                                         disconnected  restored
245
 
                  R=N(+)-M     R=N--M     R=N  + M     R=N   + M                         
246
 
                    |       ->   ||    ->   ||     ->    |
247
 
                    O(-)         O          O            O* <- radical                        
248
 
 
249
 
                  The correct     R=N    + M(+)      
250
 
                  disconnection     |
251
 
                  would be this:    O(-)        
252
 
                --------------------------------------------------------------*/
253
 
                pvN  = pBNS->vert + aN;
254
 
                pvO  = pvRad;
255
 
                peNO = peRad;
256
 
 
257
 
                /* N-O*  => N=O */
258
 
                peNO->flow ++;
259
 
                pvO->st_edge.flow ++;
260
 
                pvN->st_edge.cap  ++;
261
 
                pvN->st_edge.flow ++;
262
 
                pBNS->tot_st_cap  += 1;
263
 
                pBNS->tot_st_flow += 2;
264
 
                cur_success ++;
265
 
            } else {
266
 
                /* all other radicals that affect stereo */
267
 
                delta = pvRad->st_edge.cap - pvRad->st_edge.flow;
268
 
                pvRad->st_edge.cap -= delta;
269
 
                pBNS->tot_st_cap   -= delta;
270
 
            }
271
 
        }
272
 
/*exit_case_01:*/
273
 
        SetForbiddenEdgeMask( pBNS, &FixedStereoEdges, forbidden_stereo_edge_mask  );
274
 
        if ( cur_success ) {
275
 
            tot_succes += cur_success;
276
 
            /* recalculate InChI from the structure */
277
 
            if ( 0 > (ret = MakeOneInChIOutOfStrFromINChI2( ip, sd, pBNS, pStruct, at, at2, at3, pVA, pTCGroups,
278
 
                                                            ppt_group_info, ppat_norm, ppat_prep ) ) ) {
279
 
                goto exit_function;
280
 
            }
281
 
            if ( ret = FillOutExtraFixedHDataRestr( pStruct ) ) {
282
 
                goto exit_function;
283
 
            }
284
 
            /*
285
 
            if ( ret = FillOutCMP2MHINCHI( pStruct, pTCGroups, at2, pVA, pInChI, pc2i ) ) {
286
 
                goto exit_function;
287
 
            }
288
 
            */
289
 
            cmpInChI = CompareReversedINChI2( pStruct->pOneINChI[0], pInChI[0], pStruct->pOneINChI_Aux[0], NULL /*INChI_Aux *v2*/, icr, &err );
290
 
            if ( cmpInChI & IDIF_PROBLEM ) {
291
 
                ret = RI_ERR_PROGR; /* severe restore problem */
292
 
                goto exit_function;
293
 
            }
294
 
            if ( err ) {
295
 
                ret = RI_ERR_ALLOC;
296
 
                goto exit_function;
297
 
            }
298
 
            cmpInChI2 = 0;
299
 
            memset ( icr2, 0, sizeof(*icr2) );
300
 
            if ( iRevrInChI || iOrigInChI ) {
301
 
                /* additional mobile-H compare in case of Fixed-H */
302
 
                cmpInChI2 = CompareReversedINChI2( pStruct->pOneINChI[iRevrInChI], pInChI[iOrigInChI], pStruct->pOneINChI_Aux[iRevrInChI], NULL /*INChI_Aux *v2*/, icr2, &err );
303
 
                if ( cmpInChI & IDIF_PROBLEM ) {
304
 
                    ret = RI_ERR_PROGR; /* severe restore problem */
305
 
                    goto exit_function;
306
 
                }
307
 
                if ( err ) {
308
 
                    ret = RI_ERR_ALLOC;
309
 
                    goto exit_function;
310
 
                }
311
 
            }
312
 
 
313
 
            pStereoRevrs = (pStruct->pOneINChI[0]->StereoIsotopic &&
314
 
                       pStruct->pOneINChI[0]->StereoIsotopic->nNumberOfStereoBonds +
315
 
                       pStruct->pOneINChI[0]->StereoIsotopic->nNumberOfStereoCenters)?
316
 
                       pStruct->pOneINChI[0]->StereoIsotopic : pStruct->pOneINChI[0]->Stereo;
317
 
 
318
 
            
319
 
            pStereo2Revrs = (pStruct->bMobileH == TAUT_YES || !pStruct->pOneINChI[1] ||
320
 
                       !pStruct->pOneINChI[1]->nNumberOfAtoms || pStruct->pOneINChI[1]->bDeleted)?
321
 
                                NULL:
322
 
                       (pStruct->pOneINChI[1]->StereoIsotopic &&
323
 
                       pStruct->pOneINChI[1]->StereoIsotopic->nNumberOfStereoBonds +
324
 
                       pStruct->pOneINChI[1]->StereoIsotopic->nNumberOfStereoCenters)?
325
 
                                pStruct->pOneINChI[1]->StereoIsotopic :
326
 
                                pStruct->pOneINChI[1]->Stereo;
327
 
 
328
 
        }
329
 
    }
330
 
 
331
 
    cur_success = 0;
332
 
    if ( !(cmpInChI & IDIF_SB_MISS) && (cmpInChI2 & IDIF_SB_MISS) &&
333
 
         icr2->num_sb_in2_only &&
334
 
         0 < (max_success = pBNS->tot_st_cap - pBNS->tot_st_flow) ) {
335
 
        /*----------------------------------------------------*/
336
 
        /* case 02: missing stereogenic bond in Mobile-H only */
337
 
        /* X=N-O*  => X=N=O and eliminate radical             */
338
 
        /*----------------------------------------------------*/
339
 
        int retC, ret2C, retS, ret2S;
340
 
        INCHI_MODE cmpInChI_Prev, cmpInChI2_Prev;
341
 
        ICR  icr_Prev, icr2_Prev;
342
 
 
343
 
        /* blind attepmt */
344
 
        icr_Prev       = *icr;
345
 
        icr2_Prev      = *icr2;
346
 
        cmpInChI_Prev  = cmpInChI;
347
 
        cmpInChI2_Prev = cmpInChI2;
348
 
        for ( i = AllRadList.num_edges = 0; i < pStruct->num_atoms; i ++ ) {
349
 
            if ( pBNS->vert[i].st_edge.cap - pBNS->vert[i].st_edge.flow == 1 &&
350
 
                 (ret = AddToEdgeList( &AllRadList, i, INC_ADD_EDGE ) ) ) {
351
 
                goto exit_function;
352
 
            }
353
 
        }
354
 
        for ( i = 0; i < AllRadList.num_edges; i ++ ) {
355
 
            j = AllRadList.pnEdges[i];
356
 
            pBNS->vert[j].st_edge.cap -= 1;
357
 
            pBNS->tot_st_cap -= 1;
358
 
        }
359
 
        /*-------------------------------------------------*/
360
 
        /* re-create InChI and see whether it looks better */
361
 
        /*-------------------------------------------------*/
362
 
        if ( 0 > (ret = MakeOneInChIOutOfStrFromINChI2( ip, sd, pBNS, pStruct, at, at2, at3, pVA, pTCGroups,
363
 
                                                        ppt_group_info, ppat_norm, ppat_prep ) ) ) {
364
 
            goto exit_function;
365
 
        }
366
 
        if ( ret = FillOutExtraFixedHDataRestr( pStruct ) ) {
367
 
            goto exit_function;
368
 
        }
369
 
        /*
370
 
        if ( ret = FillOutCMP2MHINCHI( pStruct, pTCGroups, at2, pVA, pInChI, pc2i ) ) {
371
 
            goto exit_function;
372
 
        }
373
 
        */
374
 
        cmpInChI = CompareReversedINChI2( pStruct->pOneINChI[0], pInChI[0], pStruct->pOneINChI_Aux[0], NULL /*INChI_Aux *v2*/, icr, &err );
375
 
        if ( cmpInChI & IDIF_PROBLEM ) {
376
 
            ret = RI_ERR_PROGR; /* severe restore problem */
377
 
            goto exit_function;
378
 
        }
379
 
        if ( err ) {
380
 
            ret = RI_ERR_ALLOC;
381
 
            goto exit_function;
382
 
        }
383
 
        cmpInChI2 = 0;
384
 
        memset ( icr2, 0, sizeof(*icr2) );
385
 
        if ( iRevrInChI || iOrigInChI ) {
386
 
            /* additional mobile-H compare in case of Fixed-H */
387
 
            cmpInChI2 = CompareReversedINChI2( pStruct->pOneINChI[iRevrInChI], pInChI[iOrigInChI], pStruct->pOneINChI_Aux[iRevrInChI], NULL /*INChI_Aux *v2*/, icr2, &err );
388
 
            if ( cmpInChI & IDIF_PROBLEM ) {
389
 
                ret = RI_ERR_PROGR; /* severe restore problem */
390
 
                goto exit_function;
391
 
            }
392
 
            if ( err ) {
393
 
                ret = RI_ERR_ALLOC;
394
 
                goto exit_function;
395
 
            }
396
 
        }
397
 
        retC  = CompareIcr( icr, &icr_Prev, NULL, NULL, IDIFF_CONSTIT );
398
 
        retS  = CompareIcr( icr, &icr_Prev, NULL, NULL, IDIFF_STEREO );
399
 
        ret2C = CompareIcr( icr2, &icr2_Prev, NULL, NULL, IDIFF_CONSTIT );
400
 
        ret2S = CompareIcr( icr2, &icr2_Prev, NULL, NULL, IDIFF_STEREO );
401
 
 
402
 
        if ( 0 >= retC &&
403
 
             0 >= retS &&
404
 
             0 >= ret2C &&
405
 
             0 > ret2S ) {
406
 
            ; /* accept */
407
 
        } else {
408
 
            /* reject */
409
 
            for ( i = 0; i < AllRadList.num_edges; i ++ ) {
410
 
                j = AllRadList.pnEdges[i];
411
 
                pBNS->vert[j].st_edge.cap += 1;
412
 
                pBNS->tot_st_cap += 1;
413
 
            }
414
 
 
415
 
            /*-------------------------------------------------*/
416
 
            /* re-create InChI-- return to previous state      */
417
 
            /*-------------------------------------------------*/
418
 
            if ( 0 > (ret = MakeOneInChIOutOfStrFromINChI2( ip, sd, pBNS, pStruct, at, at2, at3, pVA, pTCGroups,
419
 
                                                            ppt_group_info, ppat_norm, ppat_prep ) ) ) {
420
 
                goto exit_function;
421
 
            }
422
 
            if ( ret = FillOutExtraFixedHDataRestr( pStruct ) ) {
423
 
                goto exit_function;
424
 
            }
425
 
            /*
426
 
            if ( ret = FillOutCMP2MHINCHI( pStruct, pTCGroups, at2, pVA, pInChI, pc2i ) ) {
427
 
                goto exit_function;
428
 
            }
429
 
            */
430
 
            cmpInChI = CompareReversedINChI2( pStruct->pOneINChI[0], pInChI[0], pStruct->pOneINChI_Aux[0], NULL /*INChI_Aux *v2*/, icr, &err );
431
 
            if ( cmpInChI & IDIF_PROBLEM ) {
432
 
                ret = RI_ERR_PROGR; /* severe restore problem */
433
 
                goto exit_function;
434
 
            }
435
 
            if ( err ) {
436
 
                ret = RI_ERR_ALLOC;
437
 
                goto exit_function;
438
 
            }
439
 
            cmpInChI2 = 0;
440
 
            memset ( icr2, 0, sizeof(*icr2) );
441
 
            if ( iRevrInChI || iOrigInChI ) {
442
 
                /* additional mobile-H compare in case of Fixed-H */
443
 
                cmpInChI2 = CompareReversedINChI2( pStruct->pOneINChI[iRevrInChI], pInChI[iOrigInChI], pStruct->pOneINChI_Aux[iRevrInChI], NULL /*INChI_Aux *v2*/, icr2, &err );
444
 
                if ( cmpInChI & IDIF_PROBLEM ) {
445
 
                    ret = RI_ERR_PROGR; /* severe restore problem */
446
 
                    goto exit_function;
447
 
                }
448
 
                if ( err ) {
449
 
                    ret = RI_ERR_ALLOC;
450
 
                    goto exit_function;
451
 
                }
452
 
            }
453
 
            pStereoRevrs = (pStruct->pOneINChI[0]->StereoIsotopic &&
454
 
                       pStruct->pOneINChI[0]->StereoIsotopic->nNumberOfStereoBonds +
455
 
                       pStruct->pOneINChI[0]->StereoIsotopic->nNumberOfStereoCenters)?
456
 
                       pStruct->pOneINChI[0]->StereoIsotopic : pStruct->pOneINChI[0]->Stereo;
457
 
 
458
 
            
459
 
            pStereo2Revrs = (pStruct->bMobileH == TAUT_YES || !pStruct->pOneINChI[1] ||
460
 
                       !pStruct->pOneINChI[1]->nNumberOfAtoms || pStruct->pOneINChI[1]->bDeleted)?
461
 
                                NULL:
462
 
                       (pStruct->pOneINChI[1]->StereoIsotopic &&
463
 
                       pStruct->pOneINChI[1]->StereoIsotopic->nNumberOfStereoBonds +
464
 
                       pStruct->pOneINChI[1]->StereoIsotopic->nNumberOfStereoCenters)?
465
 
                                pStruct->pOneINChI[1]->StereoIsotopic :
466
 
                                pStruct->pOneINChI[1]->Stereo;
467
 
        }
468
 
/*exit_case_02:;*/
469
 
    }
470
 
 
471
 
    cur_success = 0;
472
 
    if ( pStruct->bMobileH == TAUT_NON && (cmpInChI & IDIF_SB_EXTRA_UNDF) &&
473
 
         pStruct->endpoint ) {
474
 
        /*------------------------------------------------------*/
475
 
        /* case 03: extra stereogenic bond in Fixed-H  only     */
476
 
        /* in Mobile-H this bond is not stereogenic.            */
477
 
        /* Since this bond parity is not known, it is UNDEFINED */
478
 
        /*------------------------------------------------------*/
479
 
        int bDone, num_endpoints;
480
 
 
481
 
        TautMinusEdges[0].num_edges = 0;
482
 
        TautMinusEdges[1].num_edges = 0;
483
 
        AllChargeEdges.num_edges = 0;
484
 
        /* in1 => in restored structure; in2 => in original InChI */
485
 
        for ( i = 0; i < icr->num_sb_undef_in1_only; i ++ ) {
486
 
            j12 = icr->sb_undef_in1_only[i];
487
 
            pv1 = pBNS->vert + (v1 = pStereoRevrs->nBondAtom1[j12]-1);
488
 
            pv2 = pBNS->vert + (v2 = pStereoRevrs->nBondAtom2[j12]-1);
489
 
 
490
 
            if ( pStereo2Revrs ) {
491
 
                /* reject if it is extra in Mobile-H also */
492
 
                if ( icr2->num_sb_undef_in1_only ) {
493
 
                    for ( j = 0; j < icr2->num_sb_undef_in1_only; j ++ ) {
494
 
                        k = icr2->sb_undef_in1_only[j];
495
 
                        if ( v1 == pStereo2Revrs->nBondAtom1[k] &&
496
 
                             v2 == pStereo2Revrs->nBondAtom2[k] ) {
497
 
                            break;
498
 
                        }
499
 
                    }
500
 
                    if ( j < icr->num_sb_in1_only ) {
501
 
                        continue; /* extra stereobond in Mobile H also */
502
 
                    }
503
 
                }
504
 
            }
505
 
            /* reject if it is a stereobond in Mobile-H also */
506
 
            if ( pStereo2InChI && pStereo2InChI->nNumberOfStereoBonds ) {
507
 
                for ( j = 0; j < pStereo2InChI->nNumberOfStereoBonds; j ++ ) {
508
 
                    if ( v1 == pStereo2InChI->nBondAtom1[j] &&
509
 
                         v2 == pStereo2InChI->nBondAtom1[j]  ) {
510
 
                        break;
511
 
                    }
512
 
                }
513
 
                if ( j < pStereo2InChI->nNumberOfStereoBonds ) {
514
 
                    continue; /* ignore this extra stereo bond: it is in Mobile-H */
515
 
                }
516
 
            }
517
 
            /* find the edge between v1 and v2 */
518
 
            for ( k = 0; k < at2[v1].valence; k ++ ) {
519
 
                pe = pBNS->edge + (e = pv1->iedge[k]);
520
 
                if ( v2 == (pe->neighbor12 ^ v1) )
521
 
                    break; /* the edge has been found */
522
 
            }
523
 
            if ( k == at2[v1].valence ) {
524
 
                ret = RI_ERR_SYNTAX;
525
 
                goto exit_function;
526
 
            }
527
 
            /* Fix all charges except negative charges on tautomeric endpoints */
528
 
            if ( !AllChargeEdges.num_edges && !TautMinusEdges[0].num_edges && !TautMinusEdges[1].num_edges ) {
529
 
                for ( j = 0; j < pStruct->num_atoms; j ++ ) {
530
 
                    if ( (k=pVA[j].nCMinusGroupEdge-1) >= 0 && !pBNS->edge[k].forbidden ) {
531
 
                        if ( !pStruct->endpoint[j] ) {
532
 
                            if (ret = AddToEdgeList( &AllChargeEdges, k, INC_ADD_EDGE ) ) {
533
 
                                goto exit_function;
534
 
                            }
535
 
                        } else
536
 
                        if ( pVA[j].cNumValenceElectrons == 6 ) {
537
 
                            /* O */
538
 
                            if (ret = AddToEdgeList( TautMinusEdges+0, k, INC_ADD_EDGE ) ) {
539
 
                                goto exit_function;
540
 
                            }
541
 
                        } else {
542
 
                            /* N */
543
 
                            if (ret = AddToEdgeList( TautMinusEdges+1, k, INC_ADD_EDGE ) ) {
544
 
                                goto exit_function;
545
 
                            }
546
 
                        }
547
 
                    }
548
 
                    if ( (k=pVA[j].nCPlusGroupEdge-1) >= 0 && !pBNS->edge[k].forbidden ) {
549
 
                        if ( ret = AddToEdgeList( &AllChargeEdges, k, INC_ADD_EDGE ) ) {
550
 
                            goto exit_function;
551
 
                        }
552
 
                        /* in addition, disallow N(V) creation by forbidding charge flower edge that has flow=1 */
553
 
                        if ( pVA[j].cNumValenceElectrons == 5 && !pVA[j].cMetal && /* N, P, As */
554
 
                             NO_VERTEX != (k = GetChargeFlowerUpperEdge( pBNS, pVA, k ))) {
555
 
 
556
 
                            if ( !pBNS->edge[j].forbidden && pBNS->edge[k].flow ) {
557
 
                                if ( ret = AddToEdgeList( &AllChargeEdges, k, INC_ADD_EDGE ) ) {
558
 
                                    goto exit_function;
559
 
                                }
560
 
                            }
561
 
                        }
562
 
                    }
563
 
                }
564
 
            }
565
 
            if ( !pe->flow )
566
 
                continue;
567
 
            /* fix all charges except tautomeric; first allow only O, then only N, finally both N and O */
568
 
            SetForbiddenEdgeMask( pBNS, &AllChargeEdges, forbidden_edge_mask  );
569
 
            for ( k = 1, bDone = 0; k < 4 && !bDone; k ++ ) {
570
 
                /* fix tautomeric charges */
571
 
                num_endpoints = (TautMinusEdges+0)->num_edges + (TautMinusEdges+1)->num_edges;
572
 
                if ( k == 2 ) {
573
 
                    /* fix charges on O */
574
 
                    SetForbiddenEdgeMask( pBNS, TautMinusEdges+0, forbidden_edge_mask  );
575
 
                    num_endpoints -= (TautMinusEdges+0)->num_edges;
576
 
                }
577
 
                if ( k == 1 ) {
578
 
                    SetForbiddenEdgeMask( pBNS, TautMinusEdges+1, forbidden_edge_mask  );
579
 
                    num_endpoints -= (TautMinusEdges+1)->num_edges;
580
 
                }
581
 
                if ( num_endpoints >= 2 ) {
582
 
                    delta = 1;
583
 
                    pv1 = pBNS->vert + (v1 = pe->neighbor1);
584
 
                    pv2 = pBNS->vert + (v2 = pe->neighbor12 ^ v1);
585
 
 
586
 
                    pe->forbidden |= forbidden_edge_mask; /* fix stereobond */
587
 
                    pe->flow -= delta;                    /* decrement stereobond order */
588
 
                    pv1->st_edge.flow -= delta;
589
 
                    pv2->st_edge.flow -= delta;
590
 
                    pBNS->tot_st_flow -= 2*delta;
591
 
 
592
 
                    ret = RunBnsTestOnce( pBNS, pBD, pVA, &vPathStart, &vPathEnd, &nPathLen,
593
 
                                          &nDeltaH, &nDeltaCharge, &nNumVisitedAtoms );
594
 
 
595
 
                    if ( ret == 1 && (vPathEnd == v1 && vPathStart == v2 ||
596
 
                                      vPathEnd == v2 && vPathStart == v1) && nDeltaCharge == 0 ) {
597
 
                        /* Negative charge has been moved, no change in number of charges */
598
 
                        ret = RunBnsRestoreOnce( pBNS, pBD, pVA, pTCGroups );
599
 
                        if ( ret > 0 ) {
600
 
                            (*pnNumRunBNS) ++;
601
 
                            cur_success ++; /* 01 */
602
 
                            bDone = 1;
603
 
                        }
604
 
                    } else {
605
 
                        pe->forbidden &= ~forbidden_edge_mask;
606
 
                        pe->flow += delta;
607
 
                        pv1->st_edge.flow += delta;
608
 
                        pv2->st_edge.flow += delta;
609
 
                        pBNS->tot_st_flow += 2*delta;
610
 
                    }
611
 
                }
612
 
                /* unfix tautomeric charges */
613
 
                if ( k == 2 )
614
 
                    RemoveForbiddenEdgeMask( pBNS, TautMinusEdges+0, forbidden_edge_mask  );
615
 
                if ( k == 1 )
616
 
                    RemoveForbiddenEdgeMask( pBNS, TautMinusEdges+1, forbidden_edge_mask  );
617
 
            }
618
 
            RemoveForbiddenEdgeMask( pBNS, &AllChargeEdges, forbidden_edge_mask  );
619
 
        }
620
 
/*exit_case_03:*/
621
 
        if ( cur_success ) {
622
 
            tot_succes += cur_success;
623
 
            /* recalculate InChI from the structure */
624
 
            if ( 0 > (ret = MakeOneInChIOutOfStrFromINChI2( ip, sd, pBNS, pStruct, at, at2, at3, pVA, pTCGroups,
625
 
                                                            ppt_group_info, ppat_norm, ppat_prep ) ) ) {
626
 
                goto exit_function;
627
 
            }
628
 
            if ( ret = FillOutExtraFixedHDataRestr( pStruct ) ) {
629
 
                goto exit_function;
630
 
            }
631
 
            /*
632
 
            if ( ret = FillOutCMP2MHINCHI( pStruct, pTCGroups, at2, pVA, pInChI, pc2i ) ) {
633
 
                goto exit_function;
634
 
            }
635
 
            */
636
 
            cmpInChI = CompareReversedINChI2( pStruct->pOneINChI[0], pInChI[0], pStruct->pOneINChI_Aux[0], NULL /*INChI_Aux *v2*/, icr, &err );
637
 
            if ( cmpInChI & IDIF_PROBLEM ) {
638
 
                ret = RI_ERR_PROGR; /* severe restore problem */
639
 
                goto exit_function;
640
 
            }
641
 
            if ( err ) {
642
 
                ret = RI_ERR_ALLOC;
643
 
                goto exit_function;
644
 
            }
645
 
            cmpInChI2 = 0;
646
 
            memset ( icr2, 0, sizeof(*icr2) );
647
 
            if ( iRevrInChI || iOrigInChI ) {
648
 
                /* additional mobile-H compare in case of Fixed-H */
649
 
                cmpInChI2 = CompareReversedINChI2( pStruct->pOneINChI[iRevrInChI], pInChI[iOrigInChI], pStruct->pOneINChI_Aux[iRevrInChI], NULL /*INChI_Aux *v2*/, icr2, &err );
650
 
                if ( cmpInChI & IDIF_PROBLEM ) {
651
 
                    ret = RI_ERR_PROGR; /* severe restore problem */
652
 
                    goto exit_function;
653
 
                }
654
 
                if ( err ) {
655
 
                    ret = RI_ERR_ALLOC;
656
 
                    goto exit_function;
657
 
                }
658
 
            }
659
 
            pStereoRevrs = (pStruct->pOneINChI[0]->StereoIsotopic &&
660
 
                       pStruct->pOneINChI[0]->StereoIsotopic->nNumberOfStereoBonds +
661
 
                       pStruct->pOneINChI[0]->StereoIsotopic->nNumberOfStereoCenters)?
662
 
                       pStruct->pOneINChI[0]->StereoIsotopic : pStruct->pOneINChI[0]->Stereo;
663
 
 
664
 
            
665
 
            pStereo2Revrs = (pStruct->bMobileH == TAUT_YES || !pStruct->pOneINChI[1] ||
666
 
                       !pStruct->pOneINChI[1]->nNumberOfAtoms || pStruct->pOneINChI[1]->bDeleted)?
667
 
                                NULL:
668
 
                       (pStruct->pOneINChI[1]->StereoIsotopic &&
669
 
                       pStruct->pOneINChI[1]->StereoIsotopic->nNumberOfStereoBonds +
670
 
                       pStruct->pOneINChI[1]->StereoIsotopic->nNumberOfStereoCenters)?
671
 
                                pStruct->pOneINChI[1]->StereoIsotopic :
672
 
                                pStruct->pOneINChI[1]->Stereo;
673
 
 
674
 
        }
675
 
    }
676
 
 
677
 
    cur_success = 0;
678
 
    if ( (cmpInChI & IDIF_SB_EXTRA_UNDF) ) {
679
 
        /*------------------------------------------------------*/
680
 
        /* case 04: extra stereogenic bond                      */
681
 
        /* Since this bond parity is not known, it is UNDEFINED */
682
 
        /*------------------------------------------------------*/
683
 
        int bDone, num_endpoints;
684
 
 
685
 
        TautMinusEdges[0].num_edges = 0;
686
 
        TautMinusEdges[1].num_edges = 0;
687
 
        AllChargeEdges.num_edges = 0;
688
 
        /* in1 => in restored structure; in2 => in original InChI */
689
 
        for ( i = 0; i < icr->num_sb_undef_in1_only; i ++ ) {
690
 
            j12 = icr->sb_undef_in1_only[i];
691
 
            pv1 = pBNS->vert + (v1 = pStereoRevrs->nBondAtom1[j12]-1);
692
 
            pv2 = pBNS->vert + (v2 = pStereoRevrs->nBondAtom2[j12]-1);
693
 
 
694
 
            /* find the edge between v1 and v2 */
695
 
            for ( k = 0; k < at2[v1].valence; k ++ ) {
696
 
                pe = pBNS->edge + (e = pv1->iedge[k]);
697
 
                if ( v2 == (pe->neighbor12 ^ v1) )
698
 
                    break; /* the edge has been found */
699
 
            }
700
 
            if ( k == at2[v1].valence ) {
701
 
                ret = RI_ERR_SYNTAX;
702
 
                goto exit_function;
703
 
            }
704
 
            if ( pStereo2Revrs ) {
705
 
                /* reject if it is not extra in Mobile-H also */
706
 
                if ( icr2->num_sb_undef_in1_only ) {
707
 
                    for ( j = 0; j < icr2->num_sb_undef_in1_only; j ++ ) {
708
 
                        k = icr2->sb_undef_in1_only[j];
709
 
                        if ( v1 == pStereo2Revrs->nBondAtom1[k] &&
710
 
                             v2 == pStereo2Revrs->nBondAtom2[k] ) {
711
 
                            break;
712
 
                        }
713
 
                    }
714
 
                    if ( j == icr->num_sb_in1_only ) {
715
 
                        continue; /* extra stereobond only in Fixed-H, not in Mobile H also */
716
 
                    }
717
 
                }
718
 
            }
719
 
            
720
 
            /* Fix all charges except negative charges on tautomeric endpoints */
721
 
            if ( !AllChargeEdges.num_edges && !TautMinusEdges[0].num_edges && !TautMinusEdges[1].num_edges ) {
722
 
                for ( j = 0; j < pStruct->num_atoms; j ++ ) {
723
 
                    if ( (k=pVA[j].nCMinusGroupEdge-1) >= 0 && !pBNS->edge[k].forbidden ) {
724
 
                        if (ret = AddToEdgeList( &AllChargeEdges, k, INC_ADD_EDGE ) ) {
725
 
                            goto exit_function;
726
 
                        }
727
 
                    }
728
 
                    if ( (k=pVA[j].nCPlusGroupEdge-1) >= 0 && !pBNS->edge[k].forbidden ) {
729
 
                        int bMayBeUnfixed = !at2[j].num_H && !(pStruct->endpoint && pStruct->endpoint[j]);
730
 
                        if ( bMayBeUnfixed && pVA[j].cNumValenceElectrons == 6 || 
731
 
                             pVA[j].cNumValenceElectrons == 5 && pVA[j].cPeriodicRowNumber > 1 ) {
732
 
                            /* O & P */
733
 
                            if (ret = AddToEdgeList( TautMinusEdges+0, k, INC_ADD_EDGE ) ) {
734
 
                                goto exit_function;
735
 
                            }
736
 
                        } else
737
 
                        if ( bMayBeUnfixed &&
738
 
                             pVA[j].cNumValenceElectrons == 5 && pVA[j].cPeriodicRowNumber == 1 ) {
739
 
                            /* N */
740
 
                            if (ret = AddToEdgeList( TautMinusEdges+1, k, INC_ADD_EDGE ) ) {
741
 
                                goto exit_function;
742
 
                            }
743
 
                        } else {
744
 
                            if ( ret = AddToEdgeList( &AllChargeEdges, k, INC_ADD_EDGE ) ) {
745
 
                                goto exit_function;
746
 
                            }
747
 
                        }
748
 
                        /* in addition, disallow N(V) creation by forbidding charge flower edge that has flow=1 */
749
 
                        if ( pVA[j].cNumValenceElectrons == 5 && !pVA[j].cMetal && /* N, P, As */
750
 
                             NO_VERTEX != (k = GetChargeFlowerUpperEdge( pBNS, pVA, k ))) {
751
 
                            if ( !pBNS->edge[j].forbidden && pBNS->edge[k].flow ) {
752
 
                                if ( ret = AddToEdgeList( &AllChargeEdges, k, INC_ADD_EDGE ) ) {
753
 
                                    goto exit_function;
754
 
                                }
755
 
                            }
756
 
                        }
757
 
                    }
758
 
                }
759
 
            }
760
 
            if ( !pe->flow )
761
 
                continue;
762
 
            /* fix all charges except tautomeric; first allow only O, then only N, finally both N and O */
763
 
            SetForbiddenEdgeMask( pBNS, &AllChargeEdges, forbidden_edge_mask  );
764
 
            for ( k = 1, bDone = 0; k < 4 && !bDone; k ++ ) {
765
 
                /* fix positive charges on heteroatoms */
766
 
                num_endpoints = (TautMinusEdges+0)->num_edges + (TautMinusEdges+1)->num_edges;
767
 
                if ( k == 2 ) {
768
 
                    /* fix charges on O */
769
 
                    SetForbiddenEdgeMask( pBNS, TautMinusEdges+0, forbidden_edge_mask  );
770
 
                    num_endpoints -= (TautMinusEdges+0)->num_edges;
771
 
                }
772
 
                if ( k == 1 ) {
773
 
                    /* fix charges on N */
774
 
                    SetForbiddenEdgeMask( pBNS, TautMinusEdges+1, forbidden_edge_mask  );
775
 
                    num_endpoints -= (TautMinusEdges+1)->num_edges;
776
 
                }
777
 
                if ( num_endpoints >= 2 ) {
778
 
                    delta = 1;
779
 
                    pv1 = pBNS->vert + (v1 = pe->neighbor1);
780
 
                    pv2 = pBNS->vert + (v2 = pe->neighbor12 ^ v1);
781
 
 
782
 
                    pe->forbidden |= forbidden_edge_mask; /* fix stereobond */
783
 
                    pe->flow -= delta;                    /* decrement stereobond order */
784
 
                    pv1->st_edge.flow -= delta;
785
 
                    pv2->st_edge.flow -= delta;
786
 
                    pBNS->tot_st_flow -= 2*delta;
787
 
 
788
 
                    ret = RunBnsTestOnce( pBNS, pBD, pVA, &vPathStart, &vPathEnd, &nPathLen,
789
 
                                          &nDeltaH, &nDeltaCharge, &nNumVisitedAtoms );
790
 
 
791
 
                    if ( ret == 1 && (vPathEnd == v1 && vPathStart == v2 ||
792
 
                                      vPathEnd == v2 && vPathStart == v1) && nDeltaCharge == 0 ) {
793
 
                        /* Negative charge has been moved, no change in number of charges */
794
 
                        ret = RunBnsRestoreOnce( pBNS, pBD, pVA, pTCGroups );
795
 
                        if ( ret > 0 ) {
796
 
                            (*pnNumRunBNS) ++;
797
 
                            cur_success ++; /* 01 */
798
 
                            bDone = 1;
799
 
                        }
800
 
                    } else {
801
 
                        pe->forbidden &= ~forbidden_edge_mask;
802
 
                        pe->flow += delta;
803
 
                        pv1->st_edge.flow += delta;
804
 
                        pv2->st_edge.flow += delta;
805
 
                        pBNS->tot_st_flow += 2*delta;
806
 
                    }
807
 
                }
808
 
                /* unfix tautomeric charges */
809
 
                if ( k == 2 )
810
 
                    RemoveForbiddenEdgeMask( pBNS, TautMinusEdges+0, forbidden_edge_mask  );
811
 
                if ( k == 1 )
812
 
                    RemoveForbiddenEdgeMask( pBNS, TautMinusEdges+1, forbidden_edge_mask  );
813
 
            }
814
 
            RemoveForbiddenEdgeMask( pBNS, &AllChargeEdges, forbidden_edge_mask  );
815
 
        }
816
 
/*exit_case_04:*/
817
 
        if ( cur_success ) {
818
 
            tot_succes += cur_success;
819
 
            /* recalculate InChI from the structure */
820
 
            if ( 0 > (ret = MakeOneInChIOutOfStrFromINChI2( ip, sd, pBNS, pStruct, at, at2, at3, pVA, pTCGroups,
821
 
                                                            ppt_group_info, ppat_norm, ppat_prep ) ) ) {
822
 
                goto exit_function;
823
 
            }
824
 
            if ( ret = FillOutExtraFixedHDataRestr( pStruct ) ) {
825
 
                goto exit_function;
826
 
            }
827
 
            /*
828
 
            if ( ret = FillOutCMP2MHINCHI( pStruct, pTCGroups, at2, pVA, pInChI, pc2i ) ) {
829
 
                goto exit_function;
830
 
            }
831
 
            */
832
 
            cmpInChI = CompareReversedINChI2( pStruct->pOneINChI[0], pInChI[0], pStruct->pOneINChI_Aux[0], NULL /*INChI_Aux *v2*/, icr, &err );
833
 
            if ( cmpInChI & IDIF_PROBLEM ) {
834
 
                ret = RI_ERR_PROGR; /* severe restore problem */
835
 
                goto exit_function;
836
 
            }
837
 
            if ( err ) {
838
 
                ret = RI_ERR_ALLOC;
839
 
                goto exit_function;
840
 
            }
841
 
            cmpInChI2 = 0;
842
 
            memset ( icr2, 0, sizeof(*icr2) );
843
 
            if ( iRevrInChI || iOrigInChI ) {
844
 
                /* additional mobile-H compare in case of Fixed-H */
845
 
                cmpInChI2 = CompareReversedINChI2( pStruct->pOneINChI[iRevrInChI], pInChI[iOrigInChI], pStruct->pOneINChI_Aux[iRevrInChI], NULL /*INChI_Aux *v2*/, icr2, &err );
846
 
                if ( cmpInChI & IDIF_PROBLEM ) {
847
 
                    ret = RI_ERR_PROGR; /* severe restore problem */
848
 
                    goto exit_function;
849
 
                }
850
 
                if ( err ) {
851
 
                    ret = RI_ERR_ALLOC;
852
 
                    goto exit_function;
853
 
                }
854
 
            }
855
 
            pStereoRevrs = (pStruct->pOneINChI[0]->StereoIsotopic &&
856
 
                       pStruct->pOneINChI[0]->StereoIsotopic->nNumberOfStereoBonds +
857
 
                       pStruct->pOneINChI[0]->StereoIsotopic->nNumberOfStereoCenters)?
858
 
                       pStruct->pOneINChI[0]->StereoIsotopic : pStruct->pOneINChI[0]->Stereo;
859
 
 
860
 
            
861
 
            pStereo2Revrs = (pStruct->bMobileH == TAUT_YES || !pStruct->pOneINChI[1] ||
862
 
                       !pStruct->pOneINChI[1]->nNumberOfAtoms || pStruct->pOneINChI[1]->bDeleted)?
863
 
                                NULL:
864
 
                       (pStruct->pOneINChI[1]->StereoIsotopic &&
865
 
                       pStruct->pOneINChI[1]->StereoIsotopic->nNumberOfStereoBonds +
866
 
                       pStruct->pOneINChI[1]->StereoIsotopic->nNumberOfStereoCenters)?
867
 
                                pStruct->pOneINChI[1]->StereoIsotopic :
868
 
                                pStruct->pOneINChI[1]->Stereo;
869
 
 
870
 
        }
871
 
    }
872
 
 
873
 
    cur_success = 0;
874
 
    if ( pStruct->bMobileH == TAUT_YES &&
875
 
         (cmpInChI & IDIF_SB_EXTRA_UNDF &&
876
 
         !pStruct->ti.num_t_groups)
877
 
         /*pStruct->bMobileH == TAUT_NON && (cmpInChI2 & IDIF_SB_EXTRA_UNDF)*/) {
878
 
        /*----------------------------------------------------------*/
879
 
        /* case 05: extra stereogenic bond on =NH2(+), (B, Mobile-H)*/
880
 
        /*                   H             H                        */
881
 
        /* original: N(+)=-N<   ->  N--==N/                         */
882
 
        /* (A)               H                                      */
883
 
        /*                             double bond is marked as     */
884
 
        /*                             not stereogenic due to       */
885
 
        /*                             its change during proton     */
886
 
        /*                             removal => No Stereo bond    */
887
 
        /*                             (=NH may be tautomeric)      */
888
 
        /*                                                          */
889
 
        /*                   H             H                        */
890
 
        /* original: N=-N(+)<   ->  N--==N/                         */
891
 
        /* (B)               H                                      */
892
 
        /*                             double bond was not          */
893
 
        /*                             changed during proton        */
894
 
        /* In Fixed-H this bond        removal => Undef Stereo      */
895
 
        /* may not be stereogenic      (=NH is not tautomeric)      */
896
 
        /* (a) due to (+) movement                                  */
897
 
        /* (b) due to symmetry (2H), even if isotopic               */
898
 
        /*                                                          */
899
 
        /* Fixed-H: move (+) to or from NH2 for Undef or No stereo  */
900
 
        /*          respectively                                    */
901
 
        /* Mobile-H: Add H(+) to =NH and move the charge to =N-     */
902
 
        /*           to eliminate Undef stereo                      */
903
 
        /*          Move charge from N to -NH2 to create            */
904
 
        /*           Undef Stereo                                   */
905
 
        /* Since this bond parity is not known, it is UNDEFINED     */
906
 
        /*                                                          */
907
 
        /* Solution: Add H(+) to =NH and move charge to -N=         */
908
 
        /*                                                          */
909
 
        /*----------------------------------------------------------*/
910
 
        int aN, aC, i1, i2, vPlusMinus;
911
 
        AllChargeEdges.num_edges = 0;
912
 
        /* in1 => in restored structure; in2 => in original InChI */
913
 
        for ( i = 0; i < icr->num_sb_undef_in1_only; i ++ ) {
914
 
            j12 = icr->sb_undef_in1_only[i];
915
 
            pv1 = pBNS->vert + (v1 = pStereoRevrs->nBondAtom1[j12]-1);
916
 
            pv2 = pBNS->vert + (v2 = pStereoRevrs->nBondAtom2[j12]-1);
917
 
            /* indicators of -NH: */
918
 
            i1 = at2[v1].valence == 1 && at2[v1].num_H == 1 && !at2[v1].endpoint &&
919
 
                 pVA[v1].cNumValenceElectrons == 5 && pVA[v1].cPeriodicRowNumber == 1;
920
 
            i2 = at2[v2].valence == 1 && at2[v2].num_H == 1 && !at2[v2].endpoint &&
921
 
                 pVA[v2].cNumValenceElectrons == 5 && pVA[v2].cPeriodicRowNumber == 1;
922
 
            if ( !i1 && !i2  || i1 && i2 ) {
923
 
                continue;
924
 
            }
925
 
            /* find the edge between v1 and v2 */
926
 
            for ( k = 0; k < at2[v1].valence; k ++ ) {
927
 
                pe = pBNS->edge + (e = pv1->iedge[k]);
928
 
                if ( v2 == (pe->neighbor12 ^ v1) )
929
 
                    break; /* the edge has been found */
930
 
            }
931
 
            if ( k == at2[v1].valence ) {
932
 
                ret = RI_ERR_SYNTAX;
933
 
                goto exit_function;
934
 
            }
935
 
            if ( pe->flow != 1 ) {
936
 
                continue; /* already charged */
937
 
            }
938
 
            aN = i1? v1 : v2; /* -NH atom */
939
 
            aC = i1? v2 : v1; /* neighbor */
940
 
            /* Replace =NH with -NH2
941
 
               Create such a charge on some -N< that may be moved to NH2 to remove H(+):
942
 
               transformation:
943
 
               from:  HN=C-=-N=(+vert)-Y=(+super)-(+/-)
944
 
               to:   2HN-C*-=-N=(+vert)-Y=(+super)-(+/-)*
945
 
               Run BNS to obtain:
946
 
                     2HN-C=-=N(+)-(+vert)=Y-(+super)=(+/-)
947
 
            */
948
 
            vPlusMinus = GetPlusMinusVertex( pBNS, pTCGroups, 1, 0 );
949
 
            if ( NO_VERTEX == vPlusMinus ) {
950
 
                break; /* cannot do anything */
951
 
            }
952
 
            /* increase edges to -Y-(+/-)-Y- capacities */
953
 
            delta = 1;
954
 
            for ( i1 = 0; i1 < pBNS->vert[vPlusMinus].num_adj_edges; i1 ++ ) {
955
 
                i2 = pBNS->edge[pBNS->vert[vPlusMinus].iedge[i1]].neighbor12 ^ vPlusMinus;
956
 
                for ( k = 0; k < pBNS->vert[i2].num_adj_edges; k ++ ) {
957
 
                    pBNS->edge[pBNS->vert[i2].iedge[k]].cap += delta;
958
 
                }
959
 
            }
960
 
            /* Fix all charges except (+) on -N< */
961
 
            if ( !AllChargeEdges.num_edges ) {
962
 
                for ( j = 0; j < pStruct->num_atoms; j ++ ) {
963
 
                    if ( (k=pVA[j].nCMinusGroupEdge-1) >= 0 && !pBNS->edge[k].forbidden ) {
964
 
                        if (ret = AddToEdgeList( &AllChargeEdges, k, INC_ADD_EDGE ) ) {
965
 
                            goto exit_function;
966
 
                        }
967
 
                    }
968
 
                    if ( (k=pVA[j].nCPlusGroupEdge-1) >= 0 && !pBNS->edge[k].forbidden ) {
969
 
                        if ( pVA[j].cNumValenceElectrons == 5 && pVA[j].cPeriodicRowNumber == 1 &&
970
 
                             !at2[j].num_H && at2[j].valence == 3 &&
971
 
                             !(at2[j].endpoint || pStruct->endpoint && pStruct->endpoint[j]) ) {
972
 
                                 ; /* do not fix -N< or =N(+)< */
973
 
                        } else {
974
 
                            /* all others */
975
 
                            if (ret = AddToEdgeList( TautMinusEdges+0, k, INC_ADD_EDGE ) ) {
976
 
                                goto exit_function;
977
 
                            }
978
 
                        } 
979
 
                        /* in addition, disallow N(V) creation by forbidding charge flower edge that has flow=1 */
980
 
                        if ( pVA[j].cNumValenceElectrons == 5 && !pVA[j].cMetal && /* N, P, As */
981
 
                             NO_VERTEX != (k = GetChargeFlowerUpperEdge( pBNS, pVA, k ))) {
982
 
                            if ( !pBNS->edge[j].forbidden && pBNS->edge[k].flow ) {
983
 
                                if ( ret = AddToEdgeList( &AllChargeEdges, k, INC_ADD_EDGE ) ) {
984
 
                                    goto exit_function;
985
 
                                }
986
 
                            }
987
 
                        }
988
 
                    }
989
 
                }
990
 
            }
991
 
            /* Make bond to =NH single, add radical to aC */
992
 
            pe->flow                    -= delta; /* make single bond */
993
 
            pBNS->vert[aN].st_edge.flow -= delta;
994
 
            pBNS->vert[aN].st_edge.cap  -= delta; /* avoid radical on N */
995
 
            pBNS->vert[aC].st_edge.flow -= delta; /* create radical on C */
996
 
            pBNS->vert[vPlusMinus].st_edge.cap += delta; /* create radical on (+/-) */
997
 
            pBNS->tot_st_flow           -=  2*delta;
998
 
            /* fix C-NH bond */
999
 
            if ( ret = AddToEdgeList( &AllChargeEdges, e, INC_ADD_EDGE ) ) {
1000
 
                goto exit_function;
1001
 
            }
1002
 
            /* pBNS->tot_st_cap is unchanged */
1003
 
            /* find all aC edges except pe to fix them */
1004
 
            /* 2. Check whether it would work and do if it would */
1005
 
            SetForbiddenEdgeMask( pBNS, &AllChargeEdges, forbidden_edge_mask  );/* fix aC edges */
1006
 
            pe->cap ++;
1007
 
            ret = RunBnsTestOnce( pBNS, pBD, pVA, &vPathStart, &vPathEnd, &nPathLen,
1008
 
                                  &nDeltaH, &nDeltaCharge, &nNumVisitedAtoms );
1009
 
 
1010
 
            if ( ret == 1 && (vPathEnd == vPlusMinus && vPathStart == aC ||
1011
 
                              vPathEnd == aC && vPathStart == vPlusMinus) && nDeltaCharge == 1 ) {
1012
 
                /* Negative charge has been moved, no change in number of charges */
1013
 
                ret = RunBnsRestoreOnce( pBNS, pBD, pVA, pTCGroups );
1014
 
                if ( ret > 0 ) {
1015
 
                    (*pnNumRunBNS) ++;
1016
 
                    /* 3. Add  H to -NH and register increaded charge */
1017
 
                    pStruct->at[aN].num_H ++;
1018
 
                    pTCGroups->total_charge ++;
1019
 
                    cur_success ++; /* 01 */
1020
 
                }
1021
 
            } else {
1022
 
                pe->flow                    += delta; /* make single bond */
1023
 
                pBNS->vert[aN].st_edge.flow += delta;
1024
 
                pBNS->vert[aN].st_edge.cap  += delta; /* avoid radical on N */
1025
 
                pBNS->vert[aC].st_edge.flow += delta; /* create radical on C */
1026
 
                pBNS->vert[vPlusMinus].st_edge.cap -= delta; /* create radical on (+/-) */
1027
 
                pBNS->tot_st_flow           +=  2*delta;
1028
 
                RemoveForbiddenEdgeMask( pBNS, &AllChargeEdges, forbidden_edge_mask  );/* fix aC edges */
1029
 
                AllChargeEdges.num_edges --; /* remove pe from the list */
1030
 
                CurrEdges.num_edges = 0;
1031
 
                continue; /* should not happen */
1032
 
            }
1033
 
            RemoveForbiddenEdgeMask( pBNS, &AllChargeEdges, forbidden_edge_mask  );/* fix aC edges */
1034
 
            AllChargeEdges.num_edges --; /* remove pe from the list */
1035
 
            CurrEdges.num_edges = 0;
1036
 
        }
1037
 
/*exit_case_05:*/
1038
 
        if ( cur_success ) {
1039
 
            tot_succes += cur_success;
1040
 
            /* recalculate InChI from the structure */
1041
 
            if ( 0 > (ret = MakeOneInChIOutOfStrFromINChI2( ip, sd, pBNS, pStruct, at, at2, at3, pVA, pTCGroups,
1042
 
                                                            ppt_group_info, ppat_norm, ppat_prep ) ) ) {
1043
 
                goto exit_function;
1044
 
            }
1045
 
            if ( ret = FillOutExtraFixedHDataRestr( pStruct ) ) {
1046
 
                goto exit_function;
1047
 
            }
1048
 
            /*
1049
 
            if ( ret = FillOutCMP2MHINCHI( pStruct, pTCGroups, at2, pVA, pInChI, pc2i ) ) {
1050
 
                goto exit_function;
1051
 
            }
1052
 
            */
1053
 
            cmpInChI = CompareReversedINChI2( pStruct->pOneINChI[0], pInChI[0], pStruct->pOneINChI_Aux[0], NULL /*INChI_Aux *v2*/, icr, &err );
1054
 
            if ( cmpInChI & IDIF_PROBLEM ) {
1055
 
                ret = RI_ERR_PROGR; /* severe restore problem */
1056
 
                goto exit_function;
1057
 
            }
1058
 
            if ( err ) {
1059
 
                ret = RI_ERR_ALLOC;
1060
 
                goto exit_function;
1061
 
            }
1062
 
            cmpInChI2 = 0;
1063
 
            memset ( icr2, 0, sizeof(*icr2) );
1064
 
            if ( iRevrInChI || iOrigInChI ) {
1065
 
                /* additional mobile-H compare in case of Fixed-H */
1066
 
                cmpInChI2 = CompareReversedINChI2( pStruct->pOneINChI[iRevrInChI], pInChI[iOrigInChI], pStruct->pOneINChI_Aux[iRevrInChI], NULL /*INChI_Aux *v2*/, icr2, &err );
1067
 
                if ( cmpInChI & IDIF_PROBLEM ) {
1068
 
                    ret = RI_ERR_PROGR; /* severe restore problem */
1069
 
                    goto exit_function;
1070
 
                }
1071
 
                if ( err ) {
1072
 
                    ret = RI_ERR_ALLOC;
1073
 
                    goto exit_function;
1074
 
                }
1075
 
            }
1076
 
            pStereoRevrs = (pStruct->pOneINChI[0]->StereoIsotopic &&
1077
 
                       pStruct->pOneINChI[0]->StereoIsotopic->nNumberOfStereoBonds +
1078
 
                       pStruct->pOneINChI[0]->StereoIsotopic->nNumberOfStereoCenters)?
1079
 
                       pStruct->pOneINChI[0]->StereoIsotopic : pStruct->pOneINChI[0]->Stereo;
1080
 
 
1081
 
            
1082
 
            pStereo2Revrs = (pStruct->bMobileH == TAUT_YES || !pStruct->pOneINChI[1] ||
1083
 
                       !pStruct->pOneINChI[1]->nNumberOfAtoms || pStruct->pOneINChI[1]->bDeleted)?
1084
 
                                NULL:
1085
 
                       (pStruct->pOneINChI[1]->StereoIsotopic &&
1086
 
                       pStruct->pOneINChI[1]->StereoIsotopic->nNumberOfStereoBonds +
1087
 
                       pStruct->pOneINChI[1]->StereoIsotopic->nNumberOfStereoCenters)?
1088
 
                                pStruct->pOneINChI[1]->StereoIsotopic :
1089
 
                                pStruct->pOneINChI[1]->Stereo;
1090
 
 
1091
 
        }
1092
 
    }
1093
 
 
1094
 
    cur_success = 0;
1095
 
    if ( pStruct->bMobileH == TAUT_NON && pStereo2Revrs /* added check 2006-04-05 */ &&
1096
 
         (cmpInChI2 & IDIF_SB_EXTRA_UNDF &&
1097
 
         !pStruct->ti.num_t_groups)
1098
 
         /*pStruct->bMobileH == TAUT_NON && (cmpInChI2 & IDIF_SB_EXTRA_UNDF)*/) {
1099
 
        /*----------------------------------------------------------*/
1100
 
        /* case 06: extra stereogenic bond on =NH2(+), (B, Fixed-H) */
1101
 
        /*                   H                H        ===========  */
1102
 
        /* original: N(+)=-N<   ->  N--==N(+)<                      */
1103
 
        /* (A)               H                H                     */
1104
 
        /*                             double bond in Mobile-H      */
1105
 
        /*                             layer has Undef stereo       */
1106
 
        /*                                                          */
1107
 
        /*                                                          */
1108
 
        /* Fixed-H: move (+) to or from NH2 for Undef or No stereo  */
1109
 
        /*          respectively                                    */
1110
 
        /* Mobile-H: Add H(+) to =NH and move the charge to =N-     */
1111
 
        /*           to eliminate Undef stereo                      */
1112
 
        /*          Move charge from N to -NH2 to create            */
1113
 
        /*           Undef Stereo                                   */
1114
 
        /* Since this bond parity is not known, it is UNDEFINED     */
1115
 
        /*                                                          */
1116
 
        /* Solution: Move (+) from -NH2(+) to othe -N<              */
1117
 
        /*                                                          */
1118
 
        /*----------------------------------------------------------*/
1119
 
        int aN, aC, i1, i2, ePlus;
1120
 
        BNS_EDGE   *pePlus;
1121
 
        AllChargeEdges.num_edges = 0;
1122
 
        /* in1 => in restored structure; in2 => in original InChI */
1123
 
        for ( i = 0; i < icr2->num_sb_undef_in1_only; i ++ ) {
1124
 
            j12 = icr2->sb_undef_in1_only[i];
1125
 
            pv1 = pBNS->vert + (v1 = pStereo2Revrs->nBondAtom1[j12]-1);
1126
 
            pv2 = pBNS->vert + (v2 = pStereo2Revrs->nBondAtom2[j12]-1);
1127
 
            /* indicators of -NH: */
1128
 
            i1 = at2[v1].valence == 1 && at2[v1].num_H == 2 && !at2[v1].endpoint &&
1129
 
                 pVA[v1].cNumValenceElectrons == 5 && pVA[v1].cPeriodicRowNumber == 1;
1130
 
            i2 = at2[v2].valence == 1 && at2[v2].num_H == 2 && !at2[v2].endpoint &&
1131
 
                 pVA[v2].cNumValenceElectrons == 5 && pVA[v2].cPeriodicRowNumber == 1;
1132
 
            if ( !i1 && !i2  || i1 && i2 ) {
1133
 
                continue;
1134
 
            }
1135
 
            /* find the edge between v1 and v2 */
1136
 
            for ( k = 0; k < at2[v1].valence; k ++ ) {
1137
 
                pe = pBNS->edge + (e = pv1->iedge[k]);
1138
 
                if ( v2 == (pe->neighbor12 ^ v1) )
1139
 
                    break; /* the edge has been found */
1140
 
            }
1141
 
            if ( k == at2[v1].valence ) {
1142
 
                ret = RI_ERR_SYNTAX;
1143
 
                goto exit_function;
1144
 
            }
1145
 
            if ( pe->flow != 1 ) {
1146
 
                continue; /* already charged */
1147
 
            }
1148
 
            aN = i1? v1 : v2; /* -NH atom */
1149
 
            aC = i1? v2 : v1; /* neighbor */
1150
 
            if ( 0 > (ePlus = pVA[aN].nCPlusGroupEdge-1) ||
1151
 
                 (pePlus = pBNS->edge + ePlus)->flow ||  /* must be (+) charged */
1152
 
                 pePlus->forbidden ) {
1153
 
                continue;
1154
 
            }
1155
 
            /* Move (+) from =NH2(+) to some other -N<
1156
 
            */
1157
 
            /* Fix all charges except (+) on -N< */
1158
 
            if ( !AllChargeEdges.num_edges ) {
1159
 
                for ( j = 0; j < pStruct->num_atoms; j ++ ) {
1160
 
                    if ( (k=pVA[j].nCMinusGroupEdge-1) >= 0 && !pBNS->edge[k].forbidden ) {
1161
 
                        if (ret = AddToEdgeList( &AllChargeEdges, k, INC_ADD_EDGE ) ) {
1162
 
                            goto exit_function;
1163
 
                        }
1164
 
                    }
1165
 
                    if ( (k=pVA[j].nCPlusGroupEdge-1) >= 0 && !pBNS->edge[k].forbidden ) {
1166
 
                        if ( pVA[j].cNumValenceElectrons == 5 && pVA[j].cPeriodicRowNumber == 1 &&
1167
 
                             !at2[j].num_H && at2[j].valence == 3 &&
1168
 
                             !(at2[j].endpoint || pStruct->endpoint && pStruct->endpoint[j]) ) {
1169
 
                                 ; /* do not fix -N< or =N(+)< */
1170
 
                        } else {
1171
 
                            /* all others */
1172
 
                            if (ret = AddToEdgeList( TautMinusEdges+0, k, INC_ADD_EDGE ) ) {
1173
 
                                goto exit_function;
1174
 
                            }
1175
 
                        } 
1176
 
                        /* in addition, disallow N(V) creation by forbidding charge flower edge that has flow=1 */
1177
 
                        if ( pVA[j].cNumValenceElectrons == 5 && !pVA[j].cMetal && /* N, P, As */
1178
 
                             NO_VERTEX != (k = GetChargeFlowerUpperEdge( pBNS, pVA, k ))) {
1179
 
                            if ( !pBNS->edge[j].forbidden && pBNS->edge[k].flow ) {
1180
 
                                if ( ret = AddToEdgeList( &AllChargeEdges, k, INC_ADD_EDGE ) ) {
1181
 
                                    goto exit_function;
1182
 
                                }
1183
 
                            }
1184
 
                        }
1185
 
                    }
1186
 
                }
1187
 
            }
1188
 
            /* pePlus edge is already fixed; unfix it */
1189
 
            /* To decrement (+) on =NH2(+) decrement its double bond order */
1190
 
            delta = 1;
1191
 
            if ( !pe->flow )
1192
 
                continue;
1193
 
            pv1 = pBNS->vert + (v1 = pe->neighbor1);
1194
 
            pv2 = pBNS->vert + (v2 = pe->neighbor12 ^ v1);
1195
 
 
1196
 
            delta = 1;
1197
 
            pe->flow -= delta;
1198
 
            pv1->st_edge.flow -= delta;
1199
 
            pv2->st_edge.flow -= delta;
1200
 
            pBNS->tot_st_flow -= 2*delta;
1201
 
 
1202
 
            pe->forbidden     |= forbidden_edge_mask;
1203
 
            pePlus->forbidden &= ~forbidden_edge_mask;
1204
 
 
1205
 
            ret = RunBnsTestOnce( pBNS, pBD, pVA, &vPathStart, &vPathEnd, &nPathLen,
1206
 
                                  &nDeltaH, &nDeltaCharge, &nNumVisitedAtoms );
1207
 
 
1208
 
            if ( ret == 1 && (vPathEnd == v1 && vPathStart == v2 ||
1209
 
                              vPathEnd == v2 && vPathStart == v1) && nDeltaCharge == 0 ) {
1210
 
                /* (+)charge was just moved, no change in number of charges */
1211
 
                ret = RunBnsRestoreOnce( pBNS, pBD, pVA, pTCGroups );
1212
 
                if ( ret > 0 ) {
1213
 
                    (*pnNumRunBNS) ++;
1214
 
                    cur_success ++; /* 01 */
1215
 
                }
1216
 
            } else {
1217
 
                pe->flow += delta; /* roll back */
1218
 
                pv1->st_edge.flow += delta;
1219
 
                pv2->st_edge.flow += delta;
1220
 
                pBNS->tot_st_flow += 2*delta;
1221
 
            }
1222
 
            pe->forbidden     &= ~forbidden_edge_mask;
1223
 
            RemoveForbiddenEdgeMask( pBNS, &AllChargeEdges, forbidden_edge_mask  );/* fix aC edges */
1224
 
        }
1225
 
/*exit_case_06:*/
1226
 
        if ( cur_success ) {
1227
 
            tot_succes += cur_success;
1228
 
            /* recalculate InChI from the structure */
1229
 
            if ( 0 > (ret = MakeOneInChIOutOfStrFromINChI2( ip, sd, pBNS, pStruct, at, at2, at3, pVA, pTCGroups,
1230
 
                                                            ppt_group_info, ppat_norm, ppat_prep ) ) ) {
1231
 
                goto exit_function;
1232
 
            }
1233
 
            if ( ret = FillOutExtraFixedHDataRestr( pStruct ) ) {
1234
 
                goto exit_function;
1235
 
            }
1236
 
            /*
1237
 
            if ( ret = FillOutCMP2MHINCHI( pStruct, pTCGroups, at2, pVA, pInChI, pc2i ) ) {
1238
 
                goto exit_function;
1239
 
            }
1240
 
            */
1241
 
            cmpInChI = CompareReversedINChI2( pStruct->pOneINChI[0], pInChI[0], pStruct->pOneINChI_Aux[0], NULL /*INChI_Aux *v2*/, icr2, &err );
1242
 
            if ( cmpInChI & IDIF_PROBLEM ) {
1243
 
                ret = RI_ERR_PROGR; /* severe restore problem */
1244
 
                goto exit_function;
1245
 
            }
1246
 
            if ( err ) {
1247
 
                ret = RI_ERR_ALLOC;
1248
 
                goto exit_function;
1249
 
            }
1250
 
            cmpInChI2 = 0;
1251
 
            memset ( icr2, 0, sizeof(*icr2) );
1252
 
            if ( iRevrInChI || iOrigInChI ) {
1253
 
                /* additional mobile-H compare in case of Fixed-H */
1254
 
                cmpInChI2 = CompareReversedINChI2( pStruct->pOneINChI[iRevrInChI], pInChI[iOrigInChI], pStruct->pOneINChI_Aux[iRevrInChI], NULL /*INChI_Aux *v2*/, icr2, &err );
1255
 
                if ( cmpInChI & IDIF_PROBLEM ) {
1256
 
                    ret = RI_ERR_PROGR; /* severe restore problem */
1257
 
                    goto exit_function;
1258
 
                }
1259
 
                if ( err ) {
1260
 
                    ret = RI_ERR_ALLOC;
1261
 
                    goto exit_function;
1262
 
                }
1263
 
            }
1264
 
            pStereoRevrs = (pStruct->pOneINChI[0]->StereoIsotopic &&
1265
 
                       pStruct->pOneINChI[0]->StereoIsotopic->nNumberOfStereoBonds +
1266
 
                       pStruct->pOneINChI[0]->StereoIsotopic->nNumberOfStereoCenters)?
1267
 
                       pStruct->pOneINChI[0]->StereoIsotopic : pStruct->pOneINChI[0]->Stereo;
1268
 
 
1269
 
            
1270
 
            pStereo2Revrs = (pStruct->bMobileH == TAUT_YES || !pStruct->pOneINChI[1] ||
1271
 
                       !pStruct->pOneINChI[1]->nNumberOfAtoms || pStruct->pOneINChI[1]->bDeleted)?
1272
 
                                NULL:
1273
 
                       (pStruct->pOneINChI[1]->StereoIsotopic &&
1274
 
                       pStruct->pOneINChI[1]->StereoIsotopic->nNumberOfStereoBonds +
1275
 
                       pStruct->pOneINChI[1]->StereoIsotopic->nNumberOfStereoCenters)?
1276
 
                                pStruct->pOneINChI[1]->StereoIsotopic :
1277
 
                                pStruct->pOneINChI[1]->Stereo;
1278
 
 
1279
 
        }
1280
 
    }
1281
 
 
1282
 
 
1283
 
exit_function:
1284
 
    SetForbiddenEdgeMask( pBNS, &FixedStereoEdges, forbidden_stereo_edge_mask  );
1285
 
    AllocEdgeList( &AllChargeEdges, EDGE_LIST_FREE );
1286
 
    AllocEdgeList( &CurrEdges, EDGE_LIST_FREE );
1287
 
    AllocEdgeList( &NFlowerEdges, EDGE_LIST_FREE );
1288
 
    AllocEdgeList( &OtherNFlowerEdges, EDGE_LIST_FREE );
1289
 
    AllocEdgeList( &FixedStereoEdges, EDGE_LIST_FREE );
1290
 
    AllocEdgeList( &AllRadList, EDGE_LIST_FREE ); /* eliminate memory leak */
1291
 
    AllocEdgeList( TautMinusEdges+0, EDGE_LIST_FREE );
1292
 
    AllocEdgeList( TautMinusEdges+1, EDGE_LIST_FREE );
1293
 
 
1294
 
    return ret;
1295
 
}
1296
 
#endif