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