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

« back to all changes in this revision

Viewing changes to src/formats/inchi/ichimap1.c

  • Committer: Bazaar Package Importer
  • Author(s): Daniel Leidert (dale)
  • Date: 2009-07-17 00:18:06 UTC
  • mfrom: (6.1.1 sid)
  • Revision ID: james.westby@ubuntu.com-20090717001806-sy3mzs3e1d1adbs9
Tags: 2.2.2-2
* debian/control (Uploaders): Removed LI Daobing. Thanks for your work!
  (Standards-Version): Bumped to 3.8.2.
  (Vcs-Svn): Fixed vcs-field-uses-not-recommended-uri-format.
* debian/patches/537102_fix_tr1_memory_detection.patch: Added.
  - configure.in, configure, src/config.h.in: Fix detection of tr1/memory to
    prevent building the package with boost (closes: #537102).

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.02-beta
5
 
 * August 23, 2007
6
 
 * Developed at NIST
7
 
 *
8
 
 * The InChI library and programs are free software developed under the
9
 
 * auspices of the International Union of Pure and Applied Chemistry (IUPAC);
10
 
 * you can redistribute this software and/or modify it under the terms of 
11
 
 * the GNU Lesser General Public License as published by the Free Software 
12
 
 * Foundation:
13
 
 * http://www.opensource.org/licenses/lgpl-license.php
14
 
 */
15
 
 
16
 
 
17
 
#include <stdio.h>
18
 
#include <stdlib.h>
19
 
#include <string.h>
20
 
 
21
 
#include "mode.h"
22
 
 
23
 
#include "incomdef.h"
24
 
#include "extr_ct.h"
25
 
#include "ichitaut.h"
26
 
#include "ichicant.h"
27
 
#include "ichicomn.h"
28
 
 
29
 
#include "ichicomp.h"
30
 
 
31
 
 
32
 
 
33
 
 
34
 
/**************************************************************************************/
35
 
/*  Check if all equivalent to cr1 possibly stereogenic atoms: */
36
 
/*  1) have KNOWN parity, and */
37
 
/*  2) their parities are same */
38
 
/**************************************************************************************/
39
 
int All_SC_Same(  AT_RANK canon_rank1, /*  canonical number */
40
 
                  const ppAT_RANK pRankStack1, const ppAT_RANK pRankStack2,
41
 
                  const AT_RANK *nAtomNumberCanonFrom,
42
 
                  const sp_ATOM *at )
43
 
{
44
 
    int     n1 = (int)nAtomNumberCanonFrom[(int)canon_rank1-1];
45
 
    AT_RANK r1 = pRankStack1[0][n1];
46
 
    int     iMax1 = (int)r1;
47
 
    int     i1, s1;
48
 
    int     bFound=0, stereo_atom_parity=-1;
49
 
 
50
 
    /*  find one stereo atom such that canon_rank1 can be mapped on it */
51
 
    for ( i1 = 1; i1 <= iMax1 && r1 == pRankStack2[0][s1=(int)pRankStack2[1][iMax1-i1]]; i1++ ) {
52
 
        if ( at[s1].stereo_bond_neighbor[0] ) {
53
 
            bFound=0; /* at[s1] is not sp3-stereogenic: it belongs to a stereobond */
54
 
            break;
55
 
        } else
56
 
        if ( i1 == 1 ) {
57
 
            stereo_atom_parity = PARITY_VAL(at[s1].stereo_atom_parity);
58
 
            if ( !ATOM_PARITY_KNOWN(stereo_atom_parity) ) {
59
 
                bFound=0;  /* at[s1] does not have a KNOWN parity */
60
 
                break;
61
 
            }
62
 
        } else
63
 
        if ( stereo_atom_parity != PARITY_VAL(at[s1].stereo_atom_parity) ) {
64
 
            bFound=0; /* two equivalent atoms have different parities */
65
 
            break;
66
 
        }
67
 
        bFound ++;
68
 
    }
69
 
    return bFound;
70
 
}
71
 
/**************************************************************************************/
72
 
/*  get next available (not mapped yet) rank for a stereo center atom */
73
 
int Next_SC_At_CanonRank2( AT_RANK *canon_rank1,    /*  1st call input: largest canon number mapped so far or 0 */
74
 
                                                    /*  output: suggested canon. rank > than input if success */
75
 
                          AT_RANK *canon_rank1_min, /*  1st call:0 next calls: first tried canon. number */
76
 
                          int *bFirstTime,          /*  1 at the time of the 1st call  */
77
 
                          S_CHAR *bAtomUsedForStereo, /*  STEREO_AT_MARK if the atom has not been mapped yet */
78
 
                    const ppAT_RANK pRankStack1,    /*  mapping ranks/sort order of atoms with canon. numbers (from) */
79
 
                    const ppAT_RANK pRankStack2,    /*  mapping ranks/sort order of atoms with stereo (to) */
80
 
                    const AT_RANK *nAtomNumberCanonFrom, /*  sorted order of the canon. numbers */
81
 
                    int num_atoms )
82
 
{
83
 
    AT_RANK canon_rank1_inp = *canon_rank1;
84
 
    AT_RANK cr1;  /*  canonical rank (canonical number) */
85
 
    AT_RANK r1;   /*  mapping rank */
86
 
    int     n1;   /*  ord. number of an atom with the canon. number */
87
 
    int     s1;   /*  ord. number of an atom with stereo */
88
 
    int     i1, bFound=0;
89
 
    int     iMax1;
90
 
 
91
 
    if ( canon_rank1_inp <  *canon_rank1_min ) {
92
 
        canon_rank1_inp = *canon_rank1_min;
93
 
    } else
94
 
    if ( canon_rank1_inp < 1 ) {
95
 
        canon_rank1_inp = 1;
96
 
    } else {
97
 
        canon_rank1_inp ++; /*  next canonical rank */
98
 
    }
99
 
    cr1 = canon_rank1_inp;
100
 
    
101
 
    while ( (int) cr1 <= num_atoms ) {
102
 
        n1 = (int)nAtomNumberCanonFrom[(int)cr1-1]; /*  atom1 (which has canon. rank cr1) ord. number */
103
 
        iMax1 = (int)(r1 = pRankStack1[0][n1]); /*  mapping rank of atom1 */
104
 
        /*  find atoms "to" to which the canon. number can be mapped; they have mapping rank r1, number s1 */
105
 
        for ( i1 = 1; i1 <= iMax1 && r1 == pRankStack2[0][s1=(int)pRankStack2[1][iMax1-i1]]; i1++ ) {
106
 
            /*  looking for a stereo center atom that has mapping rank r1 */
107
 
            if ( bAtomUsedForStereo[s1] == STEREO_AT_MARK ) {
108
 
                /*  found a sterogenic atom that has not been mapped yet */
109
 
                bFound = 1;
110
 
                break;
111
 
            }
112
 
        }
113
 
        if ( bFound ) {
114
 
            /*  one stereogenic not mapped yet atom "to" has been found */
115
 
            if ( *bFirstTime ) {
116
 
                *canon_rank1_min = cr1;
117
 
                *bFirstTime = 0;
118
 
            }
119
 
            break;
120
 
        } else {
121
 
            /*  a not mapped yet stereogenic atom has not found */
122
 
            /*  for the mapping rank r1 defined by the canonical rank cr1; try next cr1 */
123
 
            cr1 ++;
124
 
        }
125
 
    }
126
 
    if ( bFound ) {
127
 
        /*  success */
128
 
        *canon_rank1 = cr1;
129
 
        return 1;
130
 
    }
131
 
    return 0;
132
 
}
133
 
/**********************************************************************/
134
 
int CompareLinCtStereoDble ( AT_STEREO_DBLE *LinearCTStereoDble1, int nLenLinearCTStereoDble1,
135
 
                             AT_STEREO_DBLE *LinearCTStereoDble2, int nLenLinearCTStereoDble2 )
136
 
{
137
 
    int i, num, ret = 0;
138
 
 
139
 
    /* compare double bonds */
140
 
    if ( LinearCTStereoDble1 && LinearCTStereoDble2 ) {
141
 
        num = inchi_min(nLenLinearCTStereoDble1, nLenLinearCTStereoDble2);
142
 
        for ( i = 0; i < num; i ++ ) {
143
 
            if ( ret = (int)LinearCTStereoDble1[i].at_num1 - (int)LinearCTStereoDble2[i].at_num1 )
144
 
                break;
145
 
            if ( ret = (int)LinearCTStereoDble1[i].at_num2 - (int)LinearCTStereoDble2[i].at_num2 )
146
 
                break;
147
 
            if ( ret = (int)LinearCTStereoDble1[i].parity - (int)LinearCTStereoDble2[i].parity )
148
 
                break;
149
 
        }
150
 
        if ( !ret ) {
151
 
            ret = nLenLinearCTStereoDble1 - nLenLinearCTStereoDble2;
152
 
        }
153
 
    } else
154
 
    if ( LinearCTStereoDble1 && nLenLinearCTStereoDble1 > 0 ) {
155
 
        ret = 1;
156
 
    } else
157
 
    if ( LinearCTStereoDble2 && nLenLinearCTStereoDble2 > 0 ) {
158
 
        ret = -1;
159
 
    }
160
 
    return ret;
161
 
}
162
 
/**********************************************************************/
163
 
int CompareLinCtStereoCarb ( AT_STEREO_CARB *LinearCTStereoCarb1, int nLenLinearCTStereoCarb1,
164
 
                             AT_STEREO_CARB *LinearCTStereoCarb2, int nLenLinearCTStereoCarb2 )
165
 
{
166
 
    int i, num, ret = 0;
167
 
 
168
 
    /* compare stereocenters */
169
 
    if ( LinearCTStereoCarb1 && LinearCTStereoCarb2 ) {
170
 
        num = inchi_min(nLenLinearCTStereoCarb1, nLenLinearCTStereoCarb2);
171
 
        for ( i = 0; i < num; i ++ ) {
172
 
            if ( ret = (int)LinearCTStereoCarb1[i].at_num - (int)LinearCTStereoCarb2[i].at_num )
173
 
                break;
174
 
            if ( ret = (int)LinearCTStereoCarb1[i].parity - (int)LinearCTStereoCarb2[i].parity )
175
 
                break;
176
 
        }
177
 
        if ( !ret ) {
178
 
            ret = nLenLinearCTStereoCarb1 - nLenLinearCTStereoCarb2;
179
 
        }
180
 
    } else
181
 
    if ( LinearCTStereoCarb1 && nLenLinearCTStereoCarb1 > 0 ) {
182
 
        ret = 1;
183
 
    } else
184
 
    if ( LinearCTStereoCarb2 && nLenLinearCTStereoCarb2 > 0 ) {
185
 
        ret = -1;
186
 
    }
187
 
 
188
 
    return ret;
189
 
}
190
 
/**********************************************************************/
191
 
int CompareLinCtStereo ( AT_STEREO_DBLE *LinearCTStereoDble1, int nLenLinearCTStereoDble1,
192
 
                         AT_STEREO_CARB *LinearCTStereoCarb1, int nLenLinearCTStereoCarb1,
193
 
                         AT_STEREO_DBLE *LinearCTStereoDble2, int nLenLinearCTStereoDble2,
194
 
                         AT_STEREO_CARB *LinearCTStereoCarb2, int nLenLinearCTStereoCarb2 )
195
 
{
196
 
    int ret;
197
 
 
198
 
    /* compare double bonds */
199
 
    ret = CompareLinCtStereoDble ( LinearCTStereoDble1, nLenLinearCTStereoDble1,
200
 
                                   LinearCTStereoDble2, nLenLinearCTStereoDble2 );
201
 
    if ( !ret ) {
202
 
        ret = CompareLinCtStereoCarb ( LinearCTStereoCarb1, nLenLinearCTStereoCarb1,
203
 
                                       LinearCTStereoCarb2, nLenLinearCTStereoCarb2 );
204
 
    }
205
 
    return ret;
206
 
}
207
 
/**************************************************************************************/
208
 
int CompareLinCtStereoAtomToValues( AT_STEREO_CARB *LinearCTStereoCarb,
209
 
                              AT_RANK at_rank_canon1, U_CHAR parity )
210
 
{
211
 
    if ( LinearCTStereoCarb->at_num CT_GREATER_THAN at_rank_canon1 )
212
 
        return 1;
213
 
    if ( LinearCTStereoCarb->at_num != at_rank_canon1 )
214
 
        return -1;
215
 
    if ( LinearCTStereoCarb->parity CT_GREATER_THAN parity )
216
 
        return 1;
217
 
    if ( LinearCTStereoCarb->parity != parity )
218
 
        return -1;
219
 
    return 0;
220
 
}
221
 
/**************************************************************************************/
222
 
/*  Find atom number from the mapping rank and return 1, or */
223
 
/*  if the mapping rank is tied and the atom number is not unique then return 0 */
224
 
int bUniqueAtNbrFromMappingRank( AT_RANK **pRankStack, AT_RANK nAtRank, AT_NUMB *nAtNumber )
225
 
{
226
 
    int       r = (int)nAtRank-1;
227
 
    AT_NUMB   i = pRankStack[1][r];
228
 
    if ( nAtRank == pRankStack[0][(int)i] &&
229
 
         (!r || nAtRank != pRankStack[0][pRankStack[1][r-1]])
230
 
       ) {
231
 
        *nAtNumber = i;
232
 
        return 1;
233
 
    }
234
 
    return 0;
235
 
}
236
 
/**************************************************************************************/
237
 
/*  Get minimal set (class) representative and partially compress the partitioning */
238
 
/*  mcr = minimal class representative. */
239
 
AT_RANK nGetMcr( AT_RANK *nEqArray, AT_RANK n )
240
 
{
241
 
    AT_RANK n1, n2, mcr; /*  recursive version is much shorter. */
242
 
    
243
 
    n1=nEqArray[(int)n];
244
 
    if ( n == n1 ) {
245
 
        return n;
246
 
    }
247
 
    /*  1st pass: find mcr */
248
 
    while ( n1 != (n2=nEqArray[(int)n1])) {
249
 
        n1 = n2;
250
 
    }
251
 
    /*  2nd pass: copy mcr to each element of the set starting from nEqArray[n] */
252
 
    mcr = n1;
253
 
    n1  = n;
254
 
    while ( /*n1*/ mcr != (n2=nEqArray[(int)n1]) ) {
255
 
        nEqArray[(int)n1]=mcr;
256
 
        n1 = n2;
257
 
    }
258
 
    return ( mcr );
259
 
}
260
 
/**************************************************************************************/
261
 
/*  Join 2 sets (classes) that have members n1 and n2 */
262
 
int nJoin2Mcrs( AT_RANK *nEqArray, AT_RANK n1, AT_RANK n2 )
263
 
{
264
 
    n1 = nGetMcr( nEqArray, n1 );
265
 
    n2 = nGetMcr( nEqArray, n2 );
266
 
    if ( n1 < n2 ) {
267
 
        nEqArray[n2] = n1;
268
 
        return 1; /*  a change has been made */
269
 
    }
270
 
    if ( n2 < n1 ) {
271
 
        nEqArray[n1] = n2;
272
 
        return 1; /*  a change has been made */
273
 
    }
274
 
    return 0; /*  no changes */
275
 
}
276
 
 
277
 
/*********************************************************************************
278
 
 *  For all pairs of atoms that are:                                             *     
279
 
 *  (a) connected by a possibly stereogenic bond                                 *
280
 
 *  (b) "equivalent" at this point to canon_rank1-canon_rank2 :                  *
281
 
 *  Check if they:                                                               *
282
 
 *  1) are connected by a stereo bond or cumulene bonds of the same length       *
283
 
 *  2) have KNOWN parity, and                                                    *
284
 
 *  3) their parities are same                                                   *
285
 
 *********************************************************************************/
286
 
int All_SB_Same(  AT_RANK canon_rank1, AT_RANK canon_rank2, /*  canonical numbers */
287
 
                  const ppAT_RANK pRankStack1, const ppAT_RANK pRankStack2,
288
 
                  const AT_RANK *nAtomNumberCanonFrom, sp_ATOM *at )
289
 
{
290
 
    int     n1 = (int)nAtomNumberCanonFrom[(int)canon_rank1-1]; /* at1 has canon_rank1 */
291
 
    int     n2 = (int)nAtomNumberCanonFrom[(int)canon_rank2-1]; /* at2 has canon_rank2 */
292
 
    AT_RANK r1 = pRankStack1[0][n1]; /* at1 mapping rank */
293
 
    AT_RANK r2 = pRankStack1[0][n2]; /* at2 mapping rank */
294
 
    AT_RANK rNeigh1, rNeigh2;
295
 
    int     iMax1 = (int)r1;
296
 
    /* int     iMax2 = (int)r2; */
297
 
    int     i1, i2, s1, s2, k1, k2, m, k, num_equal;
298
 
    int     bNotFound=1, cumulene_len, stereo_bond_parity;
299
 
 
300
 
    /*  at the first atom that possibly may have canon_rank1 find one stereo bond such that */
301
 
    /*  canon_rank1-canon_rank2 possibly may be mapped on it */
302
 
    for ( i1 = 1; i1 <= iMax1 && r1 == pRankStack2[0][s1=(int)pRankStack2[1][iMax1-i1]]; i1++ ) {
303
 
        /* at[n1] may be possible to map on at[s1] */
304
 
        for ( k1 = 0, s2= 0, bNotFound=1;
305
 
              k1 < MAX_NUM_STEREO_BONDS && (s2=(int)at[s1].stereo_bond_neighbor[k1]) &&
306
 
                                   (bNotFound = (r2 != pRankStack2[0][--s2])); k1 ++ )
307
 
            ; /* continue until the 1st at[s2] (to which at[n2] may be mapped) have been found */
308
 
        if ( !bNotFound ) {
309
 
          break; /* stop at 1st found */
310
 
        }
311
 
    }
312
 
    if ( bNotFound ) {
313
 
        return -1; /*  error: no mapping exists */
314
 
    }
315
 
    for ( k2 = 0, m = 0; k2 < MAX_NUM_STEREO_BONDS && (m=(int)at[s2].stereo_bond_neighbor[k2]) && m-1 != s1; k2 ++ )
316
 
        ;
317
 
    if ( m-1 != s1 ) {
318
 
        return -1; /*  program error: stereo bond in opposite direction not found */
319
 
    }
320
 
    stereo_bond_parity = at[s1].stereo_bond_parity[k1];
321
 
    if ( !PARITY_KNOWN(stereo_bond_parity) ) {
322
 
        return 0;
323
 
    }
324
 
    cumulene_len       = BOND_CHAIN_LEN(stereo_bond_parity);
325
 
    rNeigh1            = pRankStack2[0][(int)at[s1].neighbor[(int)at[s1].stereo_bond_ord[k1]]];
326
 
    rNeigh2            = pRankStack2[0][(int)at[s2].neighbor[(int)at[s2].stereo_bond_ord[k2]]];
327
 
 
328
 
    num_equal = 0;
329
 
    /*  Search among ALL neighbors because sometimes a stereo bond may be mapped on a non-stereo bond. */
330
 
    /*  If is so then return 0: not all mappings are stereo-equivalent */
331
 
    for ( s1 = 1; s1 <= iMax1 && r1 == pRankStack2[0][i1=(int)pRankStack2[1][iMax1-s1]]; s1++ ) {
332
 
        for ( k = 0; k < at[i1].valence; k ++ ) {
333
 
            n1 = at[i1].neighbor[k];
334
 
            if ( rNeigh1 != pRankStack2[0][n1] ) {
335
 
                continue; /*  wrong neighbor */
336
 
            }
337
 
            if ( cumulene_len ) {
338
 
                int prev, next, len, j;
339
 
                for ( prev=i1, len=0, next = n1; len < cumulene_len; len ++ ) {
340
 
                    if ( at[next].valence == 2 && !at[next].num_H ) {
341
 
                        j = ((int)at[next].neighbor[0] == prev);
342
 
                        prev = next;
343
 
                        next = at[next].neighbor[j];
344
 
                    } else {
345
 
                        break; /*  cannot continue */
346
 
                    }
347
 
                }
348
 
                if ( len     != cumulene_len ||
349
 
                     r2      != pRankStack2[0][next] ||
350
 
                     rNeigh2 != pRankStack2[0][prev] ) {
351
 
                    /*  cumulene chain not found */
352
 
                    continue;
353
 
                }
354
 
                i2 = next;
355
 
            } else {
356
 
                i2 = n1;
357
 
            }
358
 
            /*  find if a stereogenic bond between at[i1]-at[i2] exists */
359
 
            for ( k1 = 0; k1 < MAX_NUM_STEREO_BONDS &&
360
 
                          (m=(int)at[i1].stereo_bond_neighbor[k1]) && m-1 != i2; k1 ++ )
361
 
                ;
362
 
            if ( m-1 != i2 ) {
363
 
                return 0;
364
 
            }
365
 
            for ( k2 = 0; k2 < MAX_NUM_STEREO_BONDS &&
366
 
                          (m=(int)at[i2].stereo_bond_neighbor[k2]) && m-1 != i1; k2 ++ )
367
 
                ;
368
 
            if ( m-1 != i1 ) {
369
 
                return 0;
370
 
            }
371
 
            if ( at[i1].stereo_bond_parity[k1] != at[i2].stereo_bond_parity[k2] ) {
372
 
                return -1; /*  program error */
373
 
            }
374
 
            if ( stereo_bond_parity != at[i1].stereo_bond_parity[k1] ) {
375
 
                return 0;
376
 
            }
377
 
            num_equal ++;
378
 
        }
379
 
    }
380
 
    return num_equal;
381
 
}
382
 
                
383
 
/**************************************************************************************/
384
 
/*  get min. ranks for the stereo bond atoms */
385
 
int Next_SB_At_CanonRanks2( AT_RANK *canon_rank1, AT_RANK *canon_rank2, /*  canonical numbers */
386
 
                          AT_RANK *canon_rank1_min, AT_RANK *canon_rank2_min,
387
 
                          int *bFirstTime, S_CHAR *bAtomUsedForStereo,
388
 
                          const ppAT_RANK pRankStack1, const ppAT_RANK pRankStack2,
389
 
                          const AT_RANK *nCanonRankFrom, const AT_RANK *nAtomNumberCanonFrom,
390
 
                          const sp_ATOM *at, int num_atoms, int bAllene )
391
 
{
392
 
    AT_RANK canon_rank1_inp = *canon_rank1;
393
 
    AT_RANK canon_rank2_inp = *canon_rank2;
394
 
    AT_RANK cr1, cr2; /*  canonical ranks (canonical numbers) */
395
 
    AT_RANK r1, r2;   /*  mapping ranks */
396
 
    int     n1, n2;   /*  ord. numbers of atoms with stereo */
397
 
    int     s1, s2;   /*  ord. numbers of atoms with canon. numbers */
398
 
    int     i1, i2, k, m;
399
 
    int     iMax1, iMax2;
400
 
 
401
 
    if ( canon_rank1_inp <  *canon_rank1_min ||
402
 
         canon_rank1_inp == *canon_rank1_min &&
403
 
         canon_rank2_inp <  *canon_rank2_min ) {
404
 
 
405
 
        canon_rank1_inp = *canon_rank1_min;
406
 
        canon_rank2_inp = *canon_rank2_min;
407
 
    } else
408
 
    if ( canon_rank1_inp < 2 ) {
409
 
        canon_rank1_inp = 2;
410
 
        canon_rank2_inp = 0;
411
 
    }
412
 
    cr1 = canon_rank1_inp;
413
 
    cr2 = num_atoms; /* initialize. 1/8/2002 */
414
 
    while ( (int) cr1 <= num_atoms ) {
415
 
        cr2 = cr1;
416
 
        n1 = (int)nAtomNumberCanonFrom[(int)cr1-1]; /*  atom1=at[n1] (which has canon. rank) ord. number */
417
 
        iMax1 = (int)(r1 = pRankStack1[0][n1]); /*  mapping rank of atom1 */
418
 
        for ( i1 = 1; i1 <= iMax1 && r1 == pRankStack2[0][s1=(int)pRankStack2[1][iMax1-i1]]; i1++ ) {
419
 
            /*  looking for a stereo bond atom that has mapping rank r1 */
420
 
            /*  found at[s1] such that rank cr1 can be mapped on at[s1] because cr1 and s1 have equal */
421
 
            /*  mapping rank = r1. Check at[s1] stereo bonds */
422
 
            if ( bAtomUsedForStereo[s1] && bAtomUsedForStereo[s1] < STEREO_AT_MARK ) {
423
 
                for ( k = 0, s2 = 0; k < MAX_NUM_STEREO_BONDS && (s2=(int)at[s1].stereo_bond_neighbor[k]); k ++ ) {
424
 
                    /*  stereo bond at[s1]-at[s2] has been found */
425
 
                    if ( bAtomUsedForStereo[--s2] ) {
426
 
                        /*  stereo bonds have not been mapped. however, this check is not needed */
427
 
                        int cumulene_len = BOND_CHAIN_LEN(at[s1].stereo_bond_parity[k]);
428
 
                        if (   cumulene_len%2  && !bAllene || /* 09-26-2003 */
429
 
                             !(cumulene_len%2) &&  bAllene  ) { /* 08-17-2003 Fix05 */ 
430
 
                            continue;
431
 
                        }
432
 
                        iMax2 = (int)(r2 = pRankStack2[0][s2]); /*  mapping rank of atom2 */
433
 
                        /*  Go back to canonical ranks and find an atom that has mapping rank r2 */
434
 
                        /*  and is connected to the atom with canonical rank cr1 (possibly by cumulene chain) */
435
 
                        /*  These cr1-cr2 canon. ranks possibly can be mapped on at[s1]-at[s2] stereo bond */
436
 
                        for ( i2 = 1; i2 <= iMax2 && r2 == pRankStack1[0][n2=(int)pRankStack1[1][iMax2-i2]]; i2++ ) {
437
 
                            if ( cumulene_len ) {
438
 
                                int prev, next, len, j;
439
 
                                for ( m = 0; m < at[n1].valence; m ++ ) {
440
 
                                    for ( prev=n1, len=0, next = (int)at[n1].neighbor[m]; len < cumulene_len; len ++ ) {
441
 
                                        if ( at[next].valence == 2 && !at[next].num_H ) {
442
 
                                            j = ((int)at[next].neighbor[0] == prev);
443
 
                                            prev = next;
444
 
                                            next = at[next].neighbor[j];
445
 
                                        } else {
446
 
                                            break; /*  cannot continue */
447
 
                                        }
448
 
                                    }
449
 
                                    if ( len == cumulene_len && n2 == next ) {
450
 
                                        break;
451
 
                                    }
452
 
                                }
453
 
                            } else {
454
 
                                for ( m = 0; m < at[n1].valence && n2 != (int)at[n1].neighbor[m]; m ++ )
455
 
                                    ;
456
 
                            }
457
 
                            if ( m < at[n1].valence &&
458
 
                                 nCanonRankFrom[n2] < cr2 &&
459
 
                                 nCanonRankFrom[n2] > canon_rank2_inp ) {
460
 
 
461
 
                                cr2 = nCanonRankFrom[n2]; /*  found a candidate for cr2 */
462
 
                            }
463
 
                        }
464
 
                    }
465
 
                }
466
 
            }
467
 
        }
468
 
        if ( cr2 >= cr1 ) {
469
 
            /*  not found for this r1 */
470
 
            cr1 ++;
471
 
            canon_rank2_inp = 0;
472
 
        } else {
473
 
            /* found cr2 < cr1 */
474
 
            if ( *bFirstTime ) {
475
 
                *canon_rank1_min = cr1;
476
 
                *canon_rank2_min = cr2;
477
 
                *bFirstTime = 0;
478
 
            }
479
 
            break;
480
 
        }
481
 
    }
482
 
    if ( cr1 > cr2 && cr1 <= num_atoms ) {
483
 
        /*  success */
484
 
        *canon_rank1 = cr1;
485
 
        *canon_rank2 = cr2;
486
 
        return 1;
487
 
    }
488
 
    return 0;
489
 
}
490
 
/******************************************************************************************/
491
 
int NextStereoParity2Test( int *stereo_bond_parity, int *sb_parity_calc,
492
 
                           int nNumBest, int nNumWorse, int nNumUnkn, int nNumUndf, int nNumCalc)
493
 
{
494
 
    /* sequence of (stereo_bond_parity, sb_parity_calc) pairs:
495
 
 
496
 
          (BEST_PARITY, BEST_PARITY)  <calc>
497
 
                      |
498
 
          (BEST_PARITY, WORSE_PARITY) <known>
499
 
                      |
500
 
          (WORSE_PARITY, WORSE_PARITY) <calc>                (BEST_PARITY, 0) <known>
501
 
                       \___________________________________________/
502
 
                                              |
503
 
                                       (WORSE_PARITY, 0)   <known>
504
 
                                              |
505
 
                                       (AB_PARITY_UNKN, 0) <known>
506
 
                                              |
507
 
                                       (AB_PARITY_UNDF, 0) <known>
508
 
                                              |
509
 
                                       <next pair of ranks>
510
 
      Meaning:
511
 
      stereo_bond_parity is the parity we are looking for
512
 
      stereo_bond_parity==sb_parity_calc  => parity to be calculated from canonical numbers
513
 
      stereo_bond_parity!=sb_parity_calc  => parity is already known
514
 
     */
515
 
get_next_parity:
516
 
    switch ( *stereo_bond_parity ) {
517
 
    case BEST_PARITY:
518
 
        switch ( *sb_parity_calc ) {
519
 
        case 0:                                 /*  BEST_PARITY(known) : (BEST_PARITY, 0) -> */
520
 
            *stereo_bond_parity = WORSE_PARITY;  /*  WORSE_PARITY(known): (WORSE_PARITY, 0) */
521
 
            if ( !nNumWorse ) {
522
 
                goto get_next_parity;
523
 
            }
524
 
            break;
525
 
        case BEST_PARITY:                       /*  BEST_PARITY(calc) : (BEST_PARITY, BEST_PARITY) -> */
526
 
            *sb_parity_calc = WORSE_PARITY;      /*  BEST_PARITY(known): (BEST_PARITY, WORSE_PARITY) */
527
 
            if ( !nNumBest ) {
528
 
                goto get_next_parity;
529
 
            }
530
 
            break;
531
 
        case WORSE_PARITY:                      /*  BEST_PARITY(known): (BEST_PARITY, WORSE_PARITY)-> */
532
 
            *stereo_bond_parity = WORSE_PARITY;  /*  WORSE_PARITY(calc): (WORSE_PARITY,WORSE_PARITY) */
533
 
            if ( !nNumCalc ) { /* added 12-17-2003 */
534
 
                goto get_next_parity;
535
 
            }
536
 
            break;
537
 
        }
538
 
        break;
539
 
    case WORSE_PARITY:
540
 
        switch ( *sb_parity_calc ) {
541
 
        case 0:                                 /*  WORSE_PARITY(known)  : (WORSE_PARITY, 0) -> */
542
 
            *stereo_bond_parity = AB_PARITY_UNKN;/*  AB_PARITY_UNKN(known): (AB_PARITY_UNKN, 0) */
543
 
            if ( !nNumUnkn ) {
544
 
                goto get_next_parity;
545
 
            }
546
 
            break;
547
 
        case BEST_PARITY:                       /*  error */
548
 
            return CT_STEREOCOUNT_ERR;          /*   <BRKPT> */
549
 
        case WORSE_PARITY:                      /*  WORSE_PARITY(calc) : (WORSE_PARITY,WORSE_PARITY)-> */
550
 
            *sb_parity_calc = 0;                 /*  WORSE_PARITY(known): (WORSE_PARITY, 0) */
551
 
            if ( !nNumWorse ) {
552
 
                goto get_next_parity;
553
 
            }
554
 
            break;
555
 
        }
556
 
        break;
557
 
    case AB_PARITY_UNKN:                        /* AB_PARITY_UNKN(known): (AB_PARITY_UNKN, 0) -> */
558
 
        if ( *sb_parity_calc ) {                /*  error */
559
 
            return CT_STEREOCOUNT_ERR;          /*   <BRKPT> */
560
 
        }
561
 
        *stereo_bond_parity = AB_PARITY_UNDF;    /* AB_PARITY_UNDF(known): (AB_PARITY_UNDF, 0) */
562
 
        if ( !nNumUndf ) {
563
 
            return 1; /*goto next_canon_ranks;*/
564
 
        }
565
 
        break;                                  
566
 
    case AB_PARITY_UNDF:                        /*  AB_PARITY_UNDF(known): (AB_PARITY_UNDF, 0) -> */
567
 
        if ( *sb_parity_calc ) {                /*  error */
568
 
            return CT_STEREOCOUNT_ERR;          /*   <BRKPT> */
569
 
        }
570
 
        return 1; /*goto next_canon_ranks;*/     /*  next canon ranks */
571
 
    }
572
 
    return 0;
573
 
}
574
 
/**************************************************************************************/
575
 
int CompareLinCtStereoDoubleToValues( AT_STEREO_DBLE *LinearCTStereoDble,
576
 
                              AT_RANK at_rank_canon1, AT_RANK at_rank_canon2, U_CHAR bond_parity )
577
 
{
578
 
    if ( LinearCTStereoDble->at_num1 CT_GREATER_THAN at_rank_canon1 )
579
 
        return 1;
580
 
    if ( LinearCTStereoDble->at_num1 != at_rank_canon1 )
581
 
        return -1;
582
 
    if ( LinearCTStereoDble->at_num2 CT_GREATER_THAN at_rank_canon2 )
583
 
        return 1;
584
 
    if ( LinearCTStereoDble->at_num2 != at_rank_canon2 )
585
 
        return -1;
586
 
    if ( LinearCTStereoDble->parity CT_GREATER_THAN bond_parity )
587
 
        return 1;
588
 
    if ( LinearCTStereoDble->parity != bond_parity )
589
 
        return -1;
590
 
    return 0;
591
 
}
592
 
/**************************************************************************************/
593
 
/*  Set for at[i]: */
594
 
/*   0                  if atom has no parity */
595
 
/*   STEREO_AT_MARK=8   if atom has stereo parity and has no stereo bonds */
596
 
/*   num_stereo_bonds   number of stereogenic bonds adjacent to the atom <= 3   */
597
 
void SetUseAtomForStereo( S_CHAR *bAtomUsedForStereo, sp_ATOM *at, int num_atoms )
598
 
{
599
 
    int i, k;
600
 
    memset( bAtomUsedForStereo, 0, sizeof( bAtomUsedForStereo[0] )*num_atoms );
601
 
    for ( i = 0; i < num_atoms; i ++ ) {
602
 
        if ( at[i].parity ) {
603
 
            for ( k = 0; k < MAX_NUM_STEREO_BONDS && at[i].stereo_bond_neighbor[k]; k ++ )
604
 
                ;
605
 
            bAtomUsedForStereo[i] = k? k : STEREO_AT_MARK;
606
 
        }
607
 
    }
608
 
}
609
 
 
610
 
/*********************************************************************************
611
 
 * tree structure: one segment
612
 
 *
613
 
 *   canon. rank
614
 
 *   at.no       // orig. atom numbers on which the canon.
615
 
 *               // rank has been successfully mapped
616
 
 *   ...
617
 
 *   at.no       // except the last at.no: it is not known if
618
 
 *               // it has been mapped until all atoms are mapped
619
 
 *   num.at+1    // number of atoms in this segment plus one canon. rank
620
 
 *
621
 
 *********************************************************************************/
622
 
 
623
 
 
624
 
 /********************************************************************************
625
 
typedef struct tagCurTree {
626
 
    AT_NUMB  *tree;
627
 
    int       max_len;  // allocated length of tree in sizeof(tree[0]) units
628
 
    int       cur_len;  // currently used length
629
 
    int       incr_len; // reallocation increment
630
 
} CUR_TREE;
631
 
 *********************************************************************************/
632
 
 
633
 
 
634
 
/**************************************************************************************/
635
 
int CurTreeAlloc( CUR_TREE *cur_tree, int num_atoms )
636
 
{
637
 
    if ( cur_tree ) {
638
 
        if ( cur_tree->tree && cur_tree->max_len > 0 && !(cur_tree->max_len % num_atoms) ) {
639
 
            /*  do not reallocate */
640
 
            cur_tree->cur_len = 0;
641
 
            cur_tree->incr_len = num_atoms;
642
 
            memset( cur_tree->tree, 0, cur_tree->max_len * sizeof(cur_tree->tree[0]) );
643
 
            return 0; /*  ok */
644
 
        }
645
 
        inchi_free( cur_tree->tree );
646
 
        memset( cur_tree, 0, sizeof(*cur_tree) );
647
 
        if ( cur_tree->tree = (AT_NUMB *)inchi_calloc( num_atoms, sizeof(cur_tree->tree[0]) ) ) {
648
 
            cur_tree->incr_len =
649
 
            cur_tree->max_len  = num_atoms;
650
 
            return 0; /*  ok */
651
 
        }
652
 
    }
653
 
    return -1; /*  error */ /*   <BRKPT> */
654
 
}
655
 
/**************************************************************************************/
656
 
int CurTreeReAlloc( CUR_TREE *cur_tree )
657
 
{
658
 
    if ( cur_tree ) {
659
 
        if ( cur_tree->tree && cur_tree->max_len > 0 && cur_tree->incr_len > 0 ) {
660
 
            void *p = cur_tree->tree;
661
 
            if ( cur_tree->tree = (AT_NUMB *)inchi_calloc( cur_tree->max_len + cur_tree->incr_len, sizeof(cur_tree->tree[0]) ) ) {
662
 
                memcpy( cur_tree->tree, p, cur_tree->cur_len * sizeof(cur_tree->tree[0]) );
663
 
                inchi_free( p );
664
 
                cur_tree->max_len += cur_tree->incr_len;
665
 
                return 0; /*  ok */
666
 
            }
667
 
        }
668
 
    }
669
 
    return -1; /*  error */ /*   <BRKPT> */
670
 
}
671
 
/**************************************************************************************/
672
 
void CurTreeFree( CUR_TREE *cur_tree )
673
 
{
674
 
    if ( cur_tree ) {
675
 
        inchi_free( cur_tree->tree );
676
 
        memset( cur_tree, 0, sizeof(*cur_tree) );
677
 
    }
678
 
}
679
 
/**************************************************************************************/
680
 
int CurTreeAddRank( CUR_TREE *cur_tree, AT_NUMB rank )
681
 
{
682
 
    if ( cur_tree ) {
683
 
        if ( cur_tree->cur_len + 2 > cur_tree->max_len ) {
684
 
            if ( CurTreeReAlloc( cur_tree ) ) {
685
 
                return -1; /*  error */ /*   <BRKPT> */
686
 
            }
687
 
        }
688
 
        cur_tree->tree[cur_tree->cur_len++] = rank;
689
 
        cur_tree->tree[cur_tree->cur_len++] = 1;
690
 
        return 0;
691
 
    }
692
 
    return -1;  /*  error  */ /*   <BRKPT> */
693
 
}
694
 
/**************************************************************************************/
695
 
int CurTreeIsLastRank( CUR_TREE *cur_tree, AT_NUMB rank )
696
 
{
697
 
    if ( cur_tree && cur_tree->cur_len > 0 ) {
698
 
        int rank_pos;
699
 
        rank_pos = cur_tree->cur_len-1;
700
 
        rank_pos -= cur_tree->tree[rank_pos];
701
 
        if ( rank_pos >= 0 ) {
702
 
            return (rank == cur_tree->tree[rank_pos]);
703
 
        }
704
 
    }
705
 
    return 0;  /*  not found */
706
 
}
707
 
/**************************************************************************************/
708
 
int CurTreeRemoveLastRankIfNoAtoms( CUR_TREE *cur_tree )
709
 
{
710
 
    if ( cur_tree && cur_tree->tree && cur_tree->cur_len >= 2 ) {
711
 
        if ( 1 == cur_tree->tree[ cur_tree->cur_len - 1 ] ) {
712
 
            return CurTreeRemoveLastRank( cur_tree ); /*  0=> success, -1=>failed */
713
 
        }
714
 
        return 1; /*  cannot remove */
715
 
    }
716
 
    return -1; /*  error */ /*   <BRKPT> */
717
 
}
718
 
/**************************************************************************************/
719
 
int CurTreeAddAtom( CUR_TREE *cur_tree, int at_no )
720
 
{
721
 
    if ( cur_tree ) {
722
 
        if ( cur_tree->cur_len + 1 > cur_tree->max_len ) {
723
 
            if ( CurTreeReAlloc( cur_tree ) ) {
724
 
                return -1; /*  error */ /*   <BRKPT> */
725
 
            }
726
 
        }
727
 
        if ( cur_tree->cur_len > 0 ) {
728
 
            AT_NUMB new_len = cur_tree->tree[ --cur_tree->cur_len ] + 1;
729
 
            cur_tree->tree[cur_tree->cur_len++] = (AT_NUMB)at_no;
730
 
            cur_tree->tree[cur_tree->cur_len++] = new_len;
731
 
            return 0;
732
 
        }
733
 
    }
734
 
    return -1;
735
 
}
736
 
/**************************************************************************************/
737
 
void CurTreeKeepLastAtomsOnly( CUR_TREE *cur_tree, int tpos, int shift )
738
 
{   /*  on first entry: shift = 1; other values may occur in subsequent recursion */
739
 
    /*  cur_tree[cur_tree->cur_len - shift] is the length of a segment */
740
 
    /*  action: remove all atoms except the last from all segments
741
 
                that have length value positon to the right from tpos */
742
 
    int cur_length_pos;
743
 
    if ( cur_tree && cur_tree->tree && (cur_length_pos = cur_tree->cur_len - shift) > tpos ) {
744
 
        if ( cur_tree->tree[ cur_length_pos ] > 2 ) {
745
 
            /*  current segment contains more than 1 atom. Leave in the segment: rank, the last atom, length value */
746
 
            /*  subtract (old segment length)-(new segment length) from the tree length  */
747
 
            /*  actual segment length including segment length value = (cur_tree->tree[cur_length_pos]+1) */
748
 
            cur_tree->cur_len  -= (int)cur_tree->tree[ cur_length_pos ] - 2;
749
 
            memmove( cur_tree->tree + cur_length_pos - cur_tree->tree[ cur_length_pos ] + 1, /*  1st atom pos */
750
 
                     cur_tree->tree + cur_length_pos - 1,  /*  last atom in the current segment position */
751
 
                     (shift+1)*sizeof(cur_tree->tree[0]) ); 
752
 
            /*  (current segment length) distance from the last tree element has not changed */
753
 
            cur_tree->tree[ cur_tree->cur_len - shift] = 2;
754
 
            /*  add 3 to move to the previous segment length position */
755
 
            shift += 3; /*  lenghth = 3 accounts for 3 currently present. segment items:
756
 
                            (1) the last atom, (2) rank, (3) length value */
757
 
        } else {
758
 
            shift += (int)cur_tree->tree[ cur_length_pos ] + 1; /*  cur_tree->cur_len - (previous segment length position) */
759
 
        }
760
 
        CurTreeKeepLastAtomsOnly( cur_tree, tpos, shift );
761
 
    }
762
 
}
763
 
/**************************************************************************************/
764
 
int CurTreeRemoveIfLastAtom( CUR_TREE *cur_tree, int at_no )
765
 
{
766
 
    if ( cur_tree && cur_tree->tree && cur_tree->cur_len > 2 ) {
767
 
        AT_NUMB len = cur_tree->tree[ cur_tree->cur_len - 1 ];
768
 
        if ( len >= 2 && (int)cur_tree->tree[ cur_tree->cur_len - 2 ] == at_no ) {
769
 
            cur_tree->tree[--cur_tree->cur_len-1] = len-1;
770
 
            return 0;
771
 
        }
772
 
        return 1; /*  not found */
773
 
    }
774
 
    return -1; /*  error */ /*   <BRKPT> */
775
 
}
776
 
/**************************************************************************************/
777
 
int CurTreeGetPos( CUR_TREE *cur_tree )
778
 
{
779
 
    if ( cur_tree ) {
780
 
        return cur_tree->cur_len;
781
 
    }
782
 
    return -1;
783
 
}
784
 
/**************************************************************************************/
785
 
int CurTreeSetPos( CUR_TREE *cur_tree, int len )
786
 
{
787
 
    if ( cur_tree ) {
788
 
        cur_tree->cur_len = len;
789
 
        return 0;
790
 
    }
791
 
    return -1;
792
 
}
793
 
/**************************************************************************************/
794
 
int CurTreeRemoveLastRank( CUR_TREE *cur_tree )
795
 
{
796
 
    if ( cur_tree && cur_tree->cur_len > 0 ) {
797
 
        cur_tree->cur_len -= cur_tree->tree[cur_tree->cur_len-1]+1;
798
 
        if ( cur_tree->cur_len >= 0 ) {
799
 
            return 0;
800
 
        }
801
 
    }
802
 
    return -1;
803
 
}
804
 
/**************************************************************************************/
805
 
/*  Find if the atom is equivalent to already successfully tried current atoms */
806
 
int CurTreeIsLastAtomEqu( CUR_TREE *cur_tree, int at_no, AT_NUMB *nSymmStereo )
807
 
{
808
 
    if ( cur_tree && cur_tree->tree && nSymmStereo && cur_tree->cur_len > 1 ) {
809
 
        AT_NUMB nEq = nSymmStereo[at_no];
810
 
        int end = cur_tree->cur_len-1;
811
 
        int len = cur_tree->tree[end]-1;
812
 
        for ( ; len > 0; len -- ) {
813
 
            if ( nSymmStereo[(int)cur_tree->tree[end-len]] == nEq )
814
 
                return 1;
815
 
        }
816
 
        return 0;
817
 
    }
818
 
    return -1; /*  error */ /*   <BRKPT> */
819
 
}
820
 
#ifdef NEVER /* not used */
821
 
/**************************************************************************************/
822
 
int CurTreeRemoveLastAtom( CUR_TREE *cur_tree )
823
 
{
824
 
    if ( cur_tree && cur_tree->tree && cur_tree->cur_len > 2 ) {
825
 
        AT_NUMB len = cur_tree->tree[ --cur_tree->cur_len ];
826
 
        if ( len >= 2 ) {
827
 
            cur_tree->tree[cur_tree->cur_len-1] = len-1;
828
 
            return 0;
829
 
        }
830
 
    }
831
 
    return -1;
832
 
}
833
 
/**************************************************************************************/
834
 
int CurTreeReplaceLastRank( CUR_TREE *cur_tree, AT_NUMB rank )
835
 
{
836
 
    if ( !CurTreeRemoveLastRank( cur_tree ) ) {
837
 
        return CurTreeAddRank( cur_tree, rank );
838
 
    }
839
 
    return -1;
840
 
}
841
 
/**************************************************************************************/
842
 
/*  returns cur_tree->cur_len for the block containing the rank */
843
 
int CurTreeFindTheRankPos( CUR_TREE *cur_tree, AT_NUMB rank )
844
 
{
845
 
    int i, k;
846
 
    if ( cur_tree && cur_tree->tree && (i=cur_tree->cur_len) > 0 ) {
847
 
        while( 0 <= (k = i-(int)cur_tree->tree[i-1]-1) ) {  
848
 
            if ( cur_tree->tree[k] == rank ) {
849
 
                return i;
850
 
            }
851
 
            i = k;
852
 
        }
853
 
    }
854
 
    return -1; /*  error */ /*   <BRKPT> */
855
 
}
856
 
#endif
857
 
 
858