rino 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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
|
+
|