Branch data Line data Source code
1 : : /*
2 : : * SPDX-License-Identifier: MIT
3 : : * Copyright (c) 2024 IUPAC and InChI Trust
4 : : */
5 : :
6 : : #include <string.h>
7 : :
8 : : #include "mode.h"
9 : : #include "ichicomn.h"
10 : :
11 : : #include "bcf_s.h"
12 : :
13 : : /****************************************************************************
14 : : Check if all equivalent to cr1 possibly stereogenic atoms:
15 : : 1) have KNOWN parity, and
16 : : 2) their parities are same
17 : : ****************************************************************************/
18 : 0 : int All_SC_Same( AT_RANK canon_rank1, /* canonical number */
19 : : const ppAT_RANK pRankStack1,
20 : : const ppAT_RANK pRankStack2,
21 : : const AT_RANK *nAtomNumberCanonFrom,
22 : : const sp_ATOM *at )
23 : : {
24 : 0 : int n1 = (int) nAtomNumberCanonFrom[(int) canon_rank1 - 1];
25 : 0 : AT_RANK r1 = pRankStack1[0][n1];
26 : 0 : int iMax1 = (int) r1;
27 : : int i1, s1;
28 : 0 : int bFound = 0, stereo_atom_parity = -1;
29 : :
30 : : /* find one stereo atom such that canon_rank1 can be mapped on it */
31 [ # # # # ]: 0 : for (i1 = 1; i1 <= iMax1 && r1 == pRankStack2[0][s1 = (int) pRankStack2[1][iMax1 - i1]]; i1++)
32 : : {
33 [ # # ]: 0 : if (at[s1].stereo_bond_neighbor[0])
34 : : {
35 : 0 : bFound = 0; /* at[s1] is not sp3-stereogenic: it belongs to a stereobond */
36 : 0 : break;
37 : : }
38 : : else
39 [ # # ]: 0 : if (i1 == 1)
40 : : {
41 : 0 : stereo_atom_parity = PARITY_VAL( at[s1].stereo_atom_parity );
42 [ # # # # ]: 0 : if (!ATOM_PARITY_KNOWN( stereo_atom_parity ))
43 : : {
44 : 0 : bFound = 0; /* at[s1] does not have a KNOWN parity */
45 : 0 : break;
46 : : }
47 : : }
48 : : else
49 [ # # ]: 0 : if (stereo_atom_parity != PARITY_VAL( at[s1].stereo_atom_parity ))
50 : : {
51 : 0 : bFound = 0; /* two equivalent atoms have different parities */
52 : 0 : break;
53 : : }
54 : 0 : bFound++;
55 : : }
56 : :
57 : 0 : return bFound;
58 : : }
59 : :
60 : :
61 : : /****************************************************************************
62 : : get next available (not mapped yet) rank for a stereo center atom
63 : : ****************************************************************************/
64 : 367 : int Next_SC_At_CanonRank2( AT_RANK *canon_rank1, /* 1st call input: largest canon number mapped so far or 0 */
65 : : /* output: suggested canon. rank > than input if success */
66 : : AT_RANK *canon_rank1_min, /* 1st call:0 next calls: first tried canon. number */
67 : : int *bFirstTime, /* 1 at the time of the 1st call */
68 : : S_CHAR *bAtomUsedForStereo, /* STEREO_AT_MARK if the atom has not been mapped yet */
69 : : const ppAT_RANK pRankStack1, /* mapping ranks/sort order of atoms with canon. numbers (from) */
70 : : const ppAT_RANK pRankStack2, /* mapping ranks/sort order of atoms with stereo (to) */
71 : : const AT_RANK *nAtomNumberCanonFrom, /* sorted order of the canon. numbers */
72 : : int num_atoms )
73 : : {
74 : 367 : AT_RANK canon_rank1_inp = *canon_rank1;
75 : : AT_RANK cr1; /* canonical rank (canonical number) */
76 : : AT_RANK r1; /* mapping rank */
77 : : int n1; /* ord. number of an atom with the canon. number */
78 : : int s1; /* ord. number of an atom with stereo */
79 : 367 : int i1, bFound = 0;
80 : : int iMax1;
81 : :
82 [ - + ]: 367 : if (canon_rank1_inp < *canon_rank1_min)
83 : : {
84 : 0 : canon_rank1_inp = *canon_rank1_min;
85 : : }
86 : : else
87 : : {
88 [ + + ]: 367 : if (canon_rank1_inp < 1)
89 : : {
90 : 106 : canon_rank1_inp = 1;
91 : : }
92 : : else
93 : : {
94 : 261 : canon_rank1_inp++; /* next canonical rank */
95 : : }
96 : : }
97 : 367 : cr1 = canon_rank1_inp;
98 : :
99 [ + - ]: 733 : while ((int) cr1 <= num_atoms)
100 : : {
101 : 733 : n1 = (int) nAtomNumberCanonFrom[(int) cr1 - 1]; /* atom1 (which has canon. rank cr1) ord. number */
102 : 733 : iMax1 = (int) ( r1 = pRankStack1[0][n1] ); /* mapping rank of atom1 */
103 : : /* find atoms "to" to which the canon. number can be mapped; they have mapping rank r1, number s1 */
104 [ + + + + ]: 1165 : for (i1 = 1; i1 <= iMax1 && r1 == pRankStack2[0][s1 = (int) pRankStack2[1][iMax1 - i1]]; i1++)
105 : : {
106 : : /* looking for a stereo center atom that has mapping rank r1 */
107 [ + + ]: 799 : if (bAtomUsedForStereo[s1] == STEREO_AT_MARK)
108 : : {
109 : : /* found a sterogenic atom that has not been mapped yet */
110 : 367 : bFound = 1;
111 : 367 : break;
112 : : }
113 : : }
114 [ + + ]: 733 : if (bFound)
115 : : {
116 : : /* one sterogenic not mapped yet atom "to" has been found */
117 [ + - ]: 367 : if (*bFirstTime)
118 : : {
119 : 367 : *canon_rank1_min = cr1;
120 : 367 : *bFirstTime = 0;
121 : : }
122 : 367 : break;
123 : : }
124 : : else
125 : : {
126 : : /* a not mapped yet stereogenic atom has not found */
127 : : /* for the mapping rank r1 defined by the canonical rank cr1; try next cr1 */
128 : 366 : cr1++;
129 : : }
130 : : }
131 [ + - ]: 367 : if (bFound)
132 : : {
133 : : /* success */
134 : 367 : *canon_rank1 = cr1;
135 : 367 : return 1;
136 : : }
137 : :
138 : 0 : return 0;
139 : : }
140 : :
141 : :
142 : : /****************************************************************************/
143 : 51 : int CompareLinCtStereoDble( AT_STEREO_DBLE *LinearCTStereoDble1,
144 : : int nLenLinearCTStereoDble1,
145 : : AT_STEREO_DBLE *LinearCTStereoDble2,
146 : : int nLenLinearCTStereoDble2 )
147 : : {
148 : 51 : int i, num, ret = 0;
149 : :
150 : : /* compare double bonds */
151 [ - + - - ]: 51 : if (LinearCTStereoDble1 && LinearCTStereoDble2)
152 : : {
153 : 0 : num = inchi_min( nLenLinearCTStereoDble1, nLenLinearCTStereoDble2 );
154 [ # # ]: 0 : for (i = 0; i < num; i++)
155 : : {
156 [ # # ]: 0 : if ((ret = (int) LinearCTStereoDble1[i].at_num1 - (int) LinearCTStereoDble2[i].at_num1)) /* djb-rwth: addressing LLVM warning */
157 : 0 : break;
158 [ # # ]: 0 : if ((ret = (int) LinearCTStereoDble1[i].at_num2 - (int) LinearCTStereoDble2[i].at_num2)) /* djb-rwth: addressing LLVM warning */
159 : 0 : break;
160 [ # # ]: 0 : if ((ret = (int) LinearCTStereoDble1[i].parity - (int) LinearCTStereoDble2[i].parity)) /* djb-rwth: addressing LLVM warning */
161 : 0 : break;
162 : : }
163 [ # # ]: 0 : if (!ret)
164 : : {
165 : 0 : ret = nLenLinearCTStereoDble1 - nLenLinearCTStereoDble2;
166 : : }
167 : : }
168 : : else
169 : : {
170 [ - + - - ]: 51 : if (LinearCTStereoDble1 && nLenLinearCTStereoDble1 > 0)
171 : : {
172 : 0 : ret = 1;
173 : : }
174 : : else
175 : : {
176 [ - + - - ]: 51 : if (LinearCTStereoDble2 && nLenLinearCTStereoDble2 > 0)
177 : : {
178 : 0 : ret = -1;
179 : : }
180 : : }
181 : : }
182 : :
183 : 51 : return ret;
184 : : }
185 : :
186 : :
187 : : /****************************************************************************/
188 : 51 : int CompareLinCtStereoCarb( AT_STEREO_CARB *LinearCTStereoCarb1,
189 : : int nLenLinearCTStereoCarb1,
190 : : AT_STEREO_CARB *LinearCTStereoCarb2,
191 : : int nLenLinearCTStereoCarb2 )
192 : : {
193 : 51 : int i, num, ret = 0;
194 : :
195 : : /* compare stereocenters */
196 [ + - + - ]: 51 : if (LinearCTStereoCarb1 && LinearCTStereoCarb2)
197 : : {
198 : 51 : num = inchi_min( nLenLinearCTStereoCarb1, nLenLinearCTStereoCarb2 );
199 [ + - ]: 53 : for (i = 0; i < num; i++)
200 : : {
201 [ - + ]: 53 : if ((ret = (int) LinearCTStereoCarb1[i].at_num - (int) LinearCTStereoCarb2[i].at_num)) /* djb-rwth: addressing LLVM warning */
202 : 0 : break;
203 [ + + ]: 53 : if ((ret = (int) LinearCTStereoCarb1[i].parity - (int) LinearCTStereoCarb2[i].parity)) /* djb-rwth: addressing LLVM warning */
204 : 51 : break;
205 : : }
206 [ - + ]: 51 : if (!ret)
207 : : {
208 : 0 : ret = nLenLinearCTStereoCarb1 - nLenLinearCTStereoCarb2;
209 : : }
210 : : }
211 : : else
212 [ # # # # ]: 0 : if (LinearCTStereoCarb1 && nLenLinearCTStereoCarb1 > 0)
213 : : {
214 : 0 : ret = 1;
215 : : }
216 : : else
217 [ # # # # ]: 0 : if (LinearCTStereoCarb2 && nLenLinearCTStereoCarb2 > 0)
218 : : {
219 : 0 : ret = -1;
220 : : }
221 : :
222 : 51 : return ret;
223 : : }
224 : :
225 : :
226 : : /****************************************************************************/
227 : 51 : int CompareLinCtStereo( AT_STEREO_DBLE *LinearCTStereoDble1,
228 : : int nLenLinearCTStereoDble1,
229 : : AT_STEREO_CARB *LinearCTStereoCarb1,
230 : : int nLenLinearCTStereoCarb1,
231 : : AT_STEREO_DBLE *LinearCTStereoDble2,
232 : : int nLenLinearCTStereoDble2,
233 : : AT_STEREO_CARB *LinearCTStereoCarb2,
234 : : int nLenLinearCTStereoCarb2 )
235 : : {
236 : : int ret;
237 : :
238 : : /* compare double bonds */
239 : 51 : ret = CompareLinCtStereoDble( LinearCTStereoDble1, nLenLinearCTStereoDble1,
240 : : LinearCTStereoDble2, nLenLinearCTStereoDble2 );
241 [ + - ]: 51 : if (!ret)
242 : : {
243 : 51 : ret = CompareLinCtStereoCarb( LinearCTStereoCarb1, nLenLinearCTStereoCarb1,
244 : :
245 : : LinearCTStereoCarb2, nLenLinearCTStereoCarb2 );
246 : : }
247 : 51 : return ret;
248 : : }
249 : :
250 : :
251 : : /****************************************************************************/
252 : 653 : int CompareLinCtStereoAtomToValues( AT_STEREO_CARB *LinearCTStereoCarb,
253 : : AT_RANK at_rank_canon1,
254 : : U_CHAR parity )
255 : : {
256 [ - + ]: 653 : if (LinearCTStereoCarb->at_num CT_GREATER_THAN at_rank_canon1)
257 : : {
258 : 0 : return 1;
259 : : }
260 [ - + ]: 653 : if (LinearCTStereoCarb->at_num != at_rank_canon1)
261 : : {
262 : 0 : return -1;
263 : : }
264 [ + + ]: 653 : if (LinearCTStereoCarb->parity CT_GREATER_THAN parity)
265 : : {
266 : 117 : return 1;
267 : : }
268 [ - + ]: 536 : if (LinearCTStereoCarb->parity != parity)
269 : : {
270 : 0 : return -1;
271 : : }
272 : :
273 : 536 : return 0;
274 : : }
275 : :
276 : :
277 : : /****************************************************************************
278 : : Find atom number from the mapping rank and return 1, or
279 : : if the mapping rank is tied and the atom number is not unique then return 0
280 : : ****************************************************************************/
281 : 0 : int bUniqueAtNbrFromMappingRank( AT_RANK **pRankStack, AT_RANK nAtRank, AT_NUMB *nAtNumber )
282 : : {
283 : 0 : int r = (int) nAtRank - 1;
284 : 0 : AT_NUMB i = pRankStack[1][r];
285 [ # # # # ]: 0 : if (nAtRank == pRankStack[0][(int) i] &&
286 [ # # ]: 0 : ( !r || nAtRank != pRankStack[0][pRankStack[1][r - 1]] )
287 : : )
288 : : {
289 : 0 : *nAtNumber = i;
290 : 0 : return 1;
291 : : }
292 : :
293 : 0 : return 0;
294 : : }
295 : :
296 : :
297 : : /****************************************************************************
298 : : Get minimal set (class) representative and partially compress the partitioning
299 : : mcr = minimal class representative.
300 : : ****************************************************************************/
301 : 0 : AT_RANK nGetMcr( AT_RANK *nEqArray, AT_RANK n )
302 : : {
303 : : AT_RANK n1, n2, mcr; /* recursive version is much shorter. */
304 : :
305 : 0 : n1 = nEqArray[(int) n];
306 [ # # ]: 0 : if (n == n1)
307 : : {
308 : 0 : return n;
309 : : }
310 : : /* 1st pass: find mcr */
311 [ # # ]: 0 : while (n1 != ( n2 = nEqArray[(int) n1] ))
312 : : {
313 : 0 : n1 = n2;
314 : : }
315 : : /* 2nd pass: copy mcr to each element of the set starting from nEqArray[n] */
316 : 0 : mcr = n1;
317 : 0 : n1 = n;
318 [ # # ]: 0 : while ( /*n1*/ mcr != ( n2 = nEqArray[(int) n1] ))
319 : : {
320 : 0 : nEqArray[(int) n1] = mcr;
321 : 0 : n1 = n2;
322 : : }
323 : :
324 : 0 : return ( mcr );
325 : : }
326 : :
327 : :
328 : : /****************************************************************************
329 : : Join 2 sets (classes) that have members n1 and n2
330 : : ****************************************************************************/
331 : 0 : int nJoin2Mcrs( AT_RANK *nEqArray, AT_RANK n1, AT_RANK n2 )
332 : : {
333 : 0 : n1 = nGetMcr( nEqArray, n1 );
334 : 0 : n2 = nGetMcr( nEqArray, n2 );
335 [ # # ]: 0 : if (n1 < n2)
336 : : {
337 : 0 : nEqArray[n2] = n1;
338 : 0 : return 1; /* a change has been made */
339 : : }
340 [ # # ]: 0 : if (n2 < n1)
341 : : {
342 : 0 : nEqArray[n1] = n2;
343 : 0 : return 1; /* a change has been made */
344 : : }
345 : :
346 : 0 : return 0; /* no changes */
347 : : }
348 : :
349 : : /*********************************************************************************
350 : : * For all pairs of atoms that are: *
351 : : * (a) connected by a possibly stereogenic bond *
352 : : * (b) "equivalent" at this point to canon_rank1-canon_rank2 : *
353 : : * Check if they: *
354 : : * 1) are connected by a stereo bond or cumulene bonds of the same length *
355 : : * 2) have KNOWN parity, and *
356 : : * 3) their parities are same *
357 : : *********************************************************************************/
358 : 0 : int All_SB_Same( AT_RANK canon_rank1,
359 : : AT_RANK canon_rank2, /* canonical numbers */
360 : : const ppAT_RANK pRankStack1,
361 : : const ppAT_RANK pRankStack2,
362 : : const AT_RANK *nAtomNumberCanonFrom,
363 : : sp_ATOM *at )
364 : : {
365 : 0 : int n1 = (int) nAtomNumberCanonFrom[(int) canon_rank1 - 1]; /* at1 has canon_rank1 */
366 : 0 : int n2 = (int) nAtomNumberCanonFrom[(int) canon_rank2 - 1]; /* at2 has canon_rank2 */
367 : 0 : AT_RANK r1 = pRankStack1[0][n1]; /* at1 mapping rank */
368 : 0 : AT_RANK r2 = pRankStack1[0][n2]; /* at2 mapping rank */
369 : : AT_RANK rNeigh1, rNeigh2;
370 : 0 : int iMax1 = (int) r1;
371 : : /* int iMax2 = (int)r2; */
372 : 0 : int i1, i2, s1 = 0, s2 = 0, k1 = 0, k2, m, k, num_equal;
373 : 0 : int bNotFound = 1, cumulene_len, stereo_bond_parity;
374 : :
375 : : /* at the first atom that possibly may have canon_rank1 find one stereo bond such that */
376 : : /* canon_rank1-canon_rank2 possibly may be mapped on it */
377 [ # # # # ]: 0 : for (i1 = 1; i1 <= iMax1 && r1 == pRankStack2[0][s1 = (int) pRankStack2[1][iMax1 - i1]]; i1++)
378 : : {
379 : : /* at[n1] may be possible to map on at[s1] */
380 : 0 : for (k1 = 0, s2 = 0, bNotFound = 1;
381 [ # # # # ]: 0 : k1 < MAX_NUM_STEREO_BONDS && ( s2 = (int) at[s1].stereo_bond_neighbor[k1] ) &&
382 [ # # ]: 0 : ( bNotFound = ( r2 != pRankStack2[0][--s2] ) ); k1++)
383 : : ; /* continue until the 1st at[s2] (to which at[n2] may be mapped) have been found */
384 [ # # ]: 0 : if (!bNotFound)
385 : : {
386 : 0 : break; /* stop at 1st found */
387 : : }
388 : : }
389 [ # # ]: 0 : if (bNotFound)
390 : : {
391 : 0 : return -1; /* error: no mapping exists */
392 : : }
393 [ # # # # : 0 : for (k2 = 0, m = 0; k2 < MAX_NUM_STEREO_BONDS && ( m = (int) at[s2].stereo_bond_neighbor[k2] ) && m - 1 != s1; k2++)
# # ]
394 : : ;
395 [ # # ]: 0 : if (m - 1 != s1)
396 : : {
397 : 0 : return -1; /* program error: stereo bond in opposite direction not found */
398 : : }
399 : 0 : stereo_bond_parity = at[s1].stereo_bond_parity[k1];
400 [ # # # # ]: 0 : if (!PARITY_KNOWN( stereo_bond_parity ))
401 : : {
402 : 0 : return 0;
403 : : }
404 : 0 : cumulene_len = BOND_CHAIN_LEN( stereo_bond_parity );
405 : 0 : rNeigh1 = pRankStack2[0][(int) at[s1].neighbor[(int) at[s1].stereo_bond_ord[k1]]];
406 : 0 : rNeigh2 = pRankStack2[0][(int) at[s2].neighbor[(int) at[s2].stereo_bond_ord[k2]]];
407 : :
408 : 0 : num_equal = 0;
409 : : /* Search among ALL neighbors because sometimes a stereo bond may be mapped on a non-stereo bond. */
410 : : /* If is so then return 0: not all mappings are stereo-equivalent */
411 [ # # # # ]: 0 : for (s1 = 1; s1 <= iMax1 && r1 == pRankStack2[0][i1 = (int) pRankStack2[1][iMax1 - s1]]; s1++)
412 : : {
413 [ # # ]: 0 : for (k = 0; k < at[i1].valence; k++)
414 : : {
415 : 0 : n1 = at[i1].neighbor[k];
416 [ # # ]: 0 : if (rNeigh1 != pRankStack2[0][n1])
417 : : {
418 : 0 : continue; /* wrong neighbor */
419 : : }
420 [ # # ]: 0 : if (cumulene_len)
421 : : {
422 : : int prev, next, len, j;
423 [ # # ]: 0 : for (prev = i1, len = 0, next = n1; len < cumulene_len; len++)
424 : : {
425 [ # # # # ]: 0 : if (at[next].valence == 2 && !at[next].num_H)
426 : : {
427 : 0 : j = ( (int) at[next].neighbor[0] == prev );
428 : 0 : prev = next;
429 : 0 : next = at[next].neighbor[j];
430 : : }
431 : : else
432 : : {
433 : : break; /* cannot continue */
434 : : }
435 : : }
436 [ # # ]: 0 : if (len != cumulene_len ||
437 [ # # ]: 0 : r2 != pRankStack2[0][next] ||
438 [ # # ]: 0 : rNeigh2 != pRankStack2[0][prev])
439 : : {
440 : : /* cumulene chain not found */
441 : 0 : continue;
442 : : }
443 : 0 : i2 = next;
444 : : }
445 : : else
446 : : {
447 : 0 : i2 = n1;
448 : : }
449 : : /* find if a stereogenic bond between at[i1]-at[i2] exists */
450 : 0 : for (k1 = 0; k1 < MAX_NUM_STEREO_BONDS &&
451 [ # # # # : 0 : ( m = (int) at[i1].stereo_bond_neighbor[k1] ) && m - 1 != i2; k1++)
# # ]
452 : : ;
453 [ # # ]: 0 : if (m - 1 != i2)
454 : : {
455 : 0 : return 0;
456 : : }
457 : 0 : for (k2 = 0; k2 < MAX_NUM_STEREO_BONDS &&
458 [ # # # # : 0 : ( m = (int) at[i2].stereo_bond_neighbor[k2] ) && m - 1 != i1; k2++)
# # ]
459 : : ;
460 [ # # ]: 0 : if (m - 1 != i1)
461 : : {
462 : 0 : return 0;
463 : : }
464 [ # # ]: 0 : if (at[i1].stereo_bond_parity[k1] != at[i2].stereo_bond_parity[k2])
465 : : {
466 : 0 : return -1; /* program error */
467 : : }
468 [ # # ]: 0 : if (stereo_bond_parity != at[i1].stereo_bond_parity[k1])
469 : : {
470 : 0 : return 0;
471 : : }
472 : 0 : num_equal++;
473 : : }
474 : : }
475 : :
476 : 0 : return num_equal;
477 : : }
478 : :
479 : :
480 : : /****************************************************************************
481 : : get min. ranks for the stereo bond atoms
482 : : ****************************************************************************/
483 : 0 : int Next_SB_At_CanonRanks2( AT_RANK *canon_rank1,
484 : : AT_RANK *canon_rank2, /* canonical numbers */
485 : : AT_RANK *canon_rank1_min,
486 : : AT_RANK *canon_rank2_min,
487 : : int *bFirstTime,
488 : : S_CHAR *bAtomUsedForStereo,
489 : : const ppAT_RANK pRankStack1,
490 : : const ppAT_RANK pRankStack2,
491 : : const AT_RANK *nCanonRankFrom,
492 : : const AT_RANK *nAtomNumberCanonFrom,
493 : : const sp_ATOM *at,
494 : : int num_atoms,
495 : : int bAllene )
496 : : {
497 : 0 : AT_RANK canon_rank1_inp = *canon_rank1;
498 : 0 : AT_RANK canon_rank2_inp = *canon_rank2;
499 : : AT_RANK cr1, cr2; /* canonical ranks (canonical numbers) */
500 : : AT_RANK r1, r2; /* mapping ranks */
501 : : int n1, n2; /* ord. numbers of atoms with stereo */
502 : : int s1, s2; /* ord. numbers of atoms with canon. numbers */
503 : : int i1, i2, k, m;
504 : : int iMax1, iMax2;
505 : :
506 [ # # ]: 0 : if (canon_rank1_inp < *canon_rank1_min ||
507 [ # # ]: 0 : (canon_rank1_inp == *canon_rank1_min &&
508 [ # # ]: 0 : canon_rank2_inp < *canon_rank2_min)) /* djb-rwth: addressing LLVM warning */
509 : : {
510 : :
511 : 0 : canon_rank1_inp = *canon_rank1_min;
512 : 0 : canon_rank2_inp = *canon_rank2_min;
513 : : }
514 : : else
515 [ # # ]: 0 : if (canon_rank1_inp < 2)
516 : : {
517 : 0 : canon_rank1_inp = 2;
518 : 0 : canon_rank2_inp = 0;
519 : : }
520 : 0 : cr1 = canon_rank1_inp;
521 : 0 : cr2 = num_atoms; /* initialize. 1/8/2002 */
522 [ # # ]: 0 : while ((int) cr1 <= num_atoms)
523 : : {
524 : 0 : cr2 = cr1;
525 : 0 : n1 = (int) nAtomNumberCanonFrom[(int) cr1 - 1]; /* atom1=at[n1] (which has canon. rank) ord. number */
526 : 0 : iMax1 = (int) ( r1 = pRankStack1[0][n1] ); /* mapping rank of atom1 */
527 [ # # # # ]: 0 : for (i1 = 1; i1 <= iMax1 && r1 == pRankStack2[0][s1 = (int) pRankStack2[1][iMax1 - i1]]; i1++)
528 : : {
529 : : /* looking for a stereo bond atom that has mapping rank r1 */
530 : : /* found at[s1] such that rank cr1 can be mapped on at[s1] because cr1 and s1 have equal */
531 : : /* mapping rank = r1. Check at[s1] stereo bonds */
532 [ # # # # ]: 0 : if (bAtomUsedForStereo[s1] && bAtomUsedForStereo[s1] < STEREO_AT_MARK)
533 : : {
534 [ # # # # ]: 0 : for (k = 0; k < MAX_NUM_STEREO_BONDS && ( s2 = (int) at[s1].stereo_bond_neighbor[k] ); k++) /* djb-rwth: removing redundant code */
535 : : {
536 : : /* stereo bond at[s1]-at[s2] has been found */
537 [ # # ]: 0 : if (bAtomUsedForStereo[--s2])
538 : : {
539 : : /* stereo bonds have not been mapped. however, this check is not needed */
540 : 0 : int cumulene_len = BOND_CHAIN_LEN( at[s1].stereo_bond_parity[k] );
541 [ # # # # ]: 0 : if ((cumulene_len % 2 && !bAllene) || /* 09-26-2003 */
542 [ # # # # ]: 0 : (!( cumulene_len % 2 ) && bAllene)) /* djb-rwth: addressing LLVM warning */
543 : : { /* 08-17-2003 Fix05 */
544 : 0 : continue;
545 : : }
546 : 0 : iMax2 = (int) ( r2 = pRankStack2[0][s2] ); /* mapping rank of atom2 */
547 : : /* Go back to canonical ranks and find an atom that has mapping rank r2 */
548 : : /* and is connected to the atom with canonical rank cr1 (possibly by cumulene chain) */
549 : : /* These cr1-cr2 canon. ranks possibly can be mapped on at[s1]-at[s2] stereo bond */
550 [ # # # # ]: 0 : for (i2 = 1; i2 <= iMax2 && r2 == pRankStack1[0][n2 = (int) pRankStack1[1][iMax2 - i2]]; i2++)
551 : : {
552 [ # # ]: 0 : if (cumulene_len)
553 : : {
554 : : int prev, next, len, j;
555 [ # # ]: 0 : for (m = 0; m < at[n1].valence; m++)
556 : : {
557 [ # # ]: 0 : for (prev = n1, len = 0, next = (int) at[n1].neighbor[m]; len < cumulene_len; len++)
558 : : {
559 [ # # # # ]: 0 : if (at[next].valence == 2 && !at[next].num_H)
560 : : {
561 : 0 : j = ( (int) at[next].neighbor[0] == prev );
562 : 0 : prev = next;
563 : 0 : next = at[next].neighbor[j];
564 : : }
565 : : else
566 : : {
567 : : break; /* cannot continue */
568 : : }
569 : : }
570 [ # # # # ]: 0 : if (len == cumulene_len && n2 == next)
571 : : {
572 : 0 : break;
573 : : }
574 : : }
575 : : }
576 : : else
577 : : {
578 [ # # # # ]: 0 : for (m = 0; m < at[n1].valence && n2 != (int) at[n1].neighbor[m]; m++)
579 : : ;
580 : : }
581 [ # # ]: 0 : if (m < at[n1].valence &&
582 [ # # ]: 0 : nCanonRankFrom[n2] < cr2 &&
583 [ # # ]: 0 : nCanonRankFrom[n2] > canon_rank2_inp)
584 : : {
585 : :
586 : 0 : cr2 = nCanonRankFrom[n2]; /* found a candidate for cr2 */
587 : : }
588 : : }
589 : : }
590 : : }
591 : : }
592 : : }
593 [ # # ]: 0 : if (cr2 >= cr1)
594 : : {
595 : : /* not found for this r1 */
596 : 0 : cr1++;
597 : 0 : canon_rank2_inp = 0;
598 : : }
599 : : else
600 : : {
601 : : /* found cr2 < cr1 */
602 [ # # ]: 0 : if (*bFirstTime)
603 : : {
604 : 0 : *canon_rank1_min = cr1;
605 : 0 : *canon_rank2_min = cr2;
606 : 0 : *bFirstTime = 0;
607 : : }
608 : 0 : break;
609 : : }
610 : : }
611 [ # # # # ]: 0 : if (cr1 > cr2 && cr1 <= num_atoms)
612 : : {
613 : : /* success */
614 : 0 : *canon_rank1 = cr1;
615 : 0 : *canon_rank2 = cr2;
616 : 0 : return 1;
617 : : }
618 : :
619 : 0 : return 0;
620 : : }
621 : :
622 : :
623 : : /****************************************************************************/
624 : 0 : int NextStereoParity2Test( int *stereo_bond_parity,
625 : : int *sb_parity_calc,
626 : : int nNumBest,
627 : : int nNumWorse,
628 : : int nNumUnkn,
629 : : int nNumUndf,
630 : : int nNumCalc,
631 : : int vABParityUnknown )
632 : : {
633 : : /* sequence of (stereo_bond_parity, sb_parity_calc) pairs:
634 : :
635 : : (BEST_PARITY, BEST_PARITY) <calc>
636 : : |
637 : : (BEST_PARITY, WORSE_PARITY) <known>
638 : : |
639 : : (WORSE_PARITY, WORSE_PARITY) <calc> (BEST_PARITY, 0) <known>
640 : : \___________________________________________/
641 : : |
642 : : (WORSE_PARITY, 0) <known>
643 : : |
644 : : (AB_PARITY_UNKN, 0) <known>
645 : : |
646 : : (AB_PARITY_UNDF, 0) <known>
647 : : |
648 : : <next pair of ranks>
649 : : Meaning:
650 : : stereo_bond_parity is the parity we are looking for
651 : : stereo_bond_parity==sb_parity_calc => parity to be calculated from canonical numbers
652 : : stereo_bond_parity!=sb_parity_calc => parity is already known
653 : : */
654 : 0 : get_next_parity:
655 [ # # # # : 0 : switch (*stereo_bond_parity)
# ]
656 : : {
657 : 0 : case BEST_PARITY:
658 [ # # # # ]: 0 : switch (*sb_parity_calc)
659 : : {
660 : 0 : case 0: /* BEST_PARITY(known) : (BEST_PARITY, 0) -> */
661 : 0 : *stereo_bond_parity = WORSE_PARITY; /* WORSE_PARITY(known): (WORSE_PARITY, 0) */
662 [ # # ]: 0 : if (!nNumWorse)
663 : : {
664 : 0 : goto get_next_parity;
665 : : }
666 : 0 : break;
667 : 0 : case BEST_PARITY: /* BEST_PARITY(calc) : (BEST_PARITY, BEST_PARITY) -> */
668 : 0 : *sb_parity_calc = WORSE_PARITY; /* BEST_PARITY(known): (BEST_PARITY, WORSE_PARITY) */
669 [ # # ]: 0 : if (!nNumBest)
670 : : {
671 : 0 : goto get_next_parity;
672 : : }
673 : 0 : break;
674 : 0 : case WORSE_PARITY: /* BEST_PARITY(known): (BEST_PARITY, WORSE_PARITY)-> */
675 : 0 : *stereo_bond_parity = WORSE_PARITY; /* WORSE_PARITY(calc): (WORSE_PARITY,WORSE_PARITY) */
676 [ # # ]: 0 : if (!nNumCalc)
677 : : { /* added 12-17-2003 */
678 : 0 : goto get_next_parity;
679 : : }
680 : 0 : break;
681 : : }
682 : 0 : break;
683 : 0 : case WORSE_PARITY:
684 [ # # # # ]: 0 : switch (*sb_parity_calc)
685 : : {
686 : 0 : case 0: /* WORSE_PARITY(known) : (WORSE_PARITY, 0) -> */
687 : 0 : *stereo_bond_parity = vABParityUnknown /* AB_PARITY_UNKN */;/* AB_PARITY_UNKN(known): (AB_PARITY_UNKN, 0) */
688 [ # # ]: 0 : if (!nNumUnkn)
689 : : {
690 : 0 : goto get_next_parity;
691 : : }
692 : 0 : break;
693 : 0 : case BEST_PARITY: /* error */
694 : 0 : return CT_STEREOCOUNT_ERR; /* <BRKPT> */
695 : 0 : case WORSE_PARITY: /* WORSE_PARITY(calc) : (WORSE_PARITY,WORSE_PARITY)-> */
696 : 0 : *sb_parity_calc = 0; /* WORSE_PARITY(known): (WORSE_PARITY, 0) */
697 [ # # ]: 0 : if (!nNumWorse)
698 : : {
699 : 0 : goto get_next_parity;
700 : : }
701 : 0 : break;
702 : : }
703 : 0 : break;
704 : :
705 : 0 : case AB_PARITY_UNKN: /* AB_PARITY_UNKN(known): (AB_PARITY_UNKN, 0) -> */
706 [ # # ]: 0 : if (*sb_parity_calc) /* error */
707 : : {
708 : 0 : return CT_STEREOCOUNT_ERR; /* <BRKPT> */
709 : : }
710 : 0 : *stereo_bond_parity = AB_PARITY_UNDF; /* AB_PARITY_UNDF(known): (AB_PARITY_UNDF, 0) */
711 [ # # ]: 0 : if (!nNumUndf)
712 : : {
713 : 0 : return 1; /*goto next_canon_ranks;*/
714 : : }
715 : 0 : break;
716 : :
717 : 0 : case AB_PARITY_UNDF: /* AB_PARITY_UNDF(known): (AB_PARITY_UNDF, 0) -> */
718 [ # # ]: 0 : if (*sb_parity_calc)
719 : : { /* error */
720 : 0 : return CT_STEREOCOUNT_ERR; /* <BRKPT> */
721 : : }
722 : 0 : return 1; /*goto next_canon_ranks;*/ /* next canon ranks */
723 : : }
724 : 0 : return 0;
725 : : }
726 : :
727 : :
728 : : /****************************************************************************/
729 : 0 : int CompareLinCtStereoDoubleToValues( AT_STEREO_DBLE *LinearCTStereoDble,
730 : : AT_RANK at_rank_canon1,
731 : : AT_RANK at_rank_canon2,
732 : : U_CHAR bond_parity )
733 : : {
734 [ # # ]: 0 : if (LinearCTStereoDble->at_num1 CT_GREATER_THAN at_rank_canon1)
735 : : {
736 : 0 : return 1;
737 : : }
738 [ # # ]: 0 : if (LinearCTStereoDble->at_num1 != at_rank_canon1)
739 : : {
740 : 0 : return -1;
741 : : }
742 [ # # ]: 0 : if (LinearCTStereoDble->at_num2 CT_GREATER_THAN at_rank_canon2)
743 : : {
744 : 0 : return 1;
745 : : }
746 [ # # ]: 0 : if (LinearCTStereoDble->at_num2 != at_rank_canon2)
747 : : {
748 : 0 : return -1;
749 : : }
750 [ # # ]: 0 : if (LinearCTStereoDble->parity CT_GREATER_THAN bond_parity)
751 : : {
752 : 0 : return 1;
753 : : }
754 [ # # ]: 0 : if (LinearCTStereoDble->parity != bond_parity)
755 : : {
756 : 0 : return -1;
757 : : }
758 : :
759 : 0 : return 0;
760 : : }
761 : :
762 : :
763 : : /****************************************************************************
764 : : Set for at[i]:
765 : : 0 if atom has no parity
766 : : STEREO_AT_MARK=8 if atom has stereo parity and has no stereo bonds
767 : : num_stereo_bonds number of stereogenic bonds adjacent to the atom <= 3
768 : : ****************************************************************************/
769 : 109 : void SetUseAtomForStereo( S_CHAR *bAtomUsedForStereo, sp_ATOM *at, int num_atoms )
770 : : {
771 : : int i, k;
772 : 109 : memset( bAtomUsedForStereo, 0, sizeof( bAtomUsedForStereo[0] )*num_atoms ); /* djb-rwth: memset_s C11/Annex K variant? */
773 [ + + ]: 1215 : for (i = 0; i < num_atoms; i++)
774 : : {
775 [ + + ]: 1106 : if (at[i].parity)
776 : : {
777 [ + - - + ]: 367 : for (k = 0; k < MAX_NUM_STEREO_BONDS && at[i].stereo_bond_neighbor[k]; k++)
778 : : {
779 : : ;
780 : : }
781 [ - + ]: 367 : bAtomUsedForStereo[i] = k ? k : STEREO_AT_MARK;
782 : : }
783 : : }
784 : 109 : }
785 : :
786 : :
787 : : /****************************************************************************/
788 : 58 : int CurTreeAlloc( CUR_TREE *cur_tree, int num_atoms )
789 : : {
790 [ + - ]: 58 : if (cur_tree)
791 : : {
792 [ - + - - : 58 : if (cur_tree->tree && cur_tree->max_len > 0 && !( cur_tree->max_len % num_atoms ))
- - ]
793 : : {
794 : : /* do not reallocate */
795 : 0 : cur_tree->cur_len = 0;
796 : 0 : cur_tree->incr_len = num_atoms;
797 : 0 : memset( cur_tree->tree, 0, cur_tree->max_len * sizeof( cur_tree->tree[0] ) ); /* djb-rwth: memset_s C11/Annex K variant? */
798 : 0 : return 0; /* ok */
799 : : }
800 [ - + ]: 58 : inchi_free( cur_tree->tree );
801 : 58 : memset( cur_tree, 0, sizeof( *cur_tree ) ); /* djb-rwth: memset_s C11/Annex K variant? */
802 [ + - ]: 58 : if ((cur_tree->tree = (AT_NUMB *) inchi_calloc( num_atoms, sizeof( cur_tree->tree[0] ) ))) /* djb-rwth: addressing LLVM warning */
803 : : {
804 : 58 : cur_tree->incr_len =
805 : 58 : cur_tree->max_len = num_atoms;
806 : 58 : return 0; /* ok */
807 : : }
808 : : }
809 : :
810 : 0 : return -1; /* error */ /* <BRKPT> */
811 : : }
812 : :
813 : :
814 : : /****************************************************************************/
815 : 0 : int CurTreeReAlloc( CUR_TREE *cur_tree )
816 : : {
817 [ # # ]: 0 : if (cur_tree)
818 : : {
819 [ # # # # : 0 : if (cur_tree->tree && cur_tree->max_len > 0 && cur_tree->incr_len > 0)
# # ]
820 : : {
821 : 0 : void *p = cur_tree->tree;
822 [ # # ]: 0 : if ((cur_tree->tree = (AT_NUMB *) inchi_calloc( (long long)cur_tree->max_len + (long long)cur_tree->incr_len, sizeof( cur_tree->tree[0] ) ))) /* djb-rwth: cast operators added; addressing LLVM warning */
823 : : {
824 : 0 : memcpy(cur_tree->tree, p, cur_tree->cur_len * sizeof(cur_tree->tree[0]));
825 [ # # ]: 0 : inchi_free( p );
826 : 0 : cur_tree->max_len += cur_tree->incr_len;
827 : 0 : return 0; /* ok */
828 : : }
829 : : }
830 : : }
831 : :
832 : 0 : return -1; /* error */ /* <BRKPT> */
833 : : }
834 : :
835 : :
836 : 161 : /****************************************************************************/void CurTreeFree( CUR_TREE *cur_tree )
837 : : {
838 [ + + ]: 161 : if (cur_tree)
839 : : {
840 [ + - ]: 58 : inchi_free( cur_tree->tree );
841 : 58 : memset( cur_tree, 0, sizeof( *cur_tree ) ); /* djb-rwth: memset_s C11/Annex K variant? */
842 : : }
843 : 161 : }
844 : :
845 : :
846 : 0 : /****************************************************************************/int CurTreeAddRank( CUR_TREE *cur_tree, AT_NUMB rank )
847 : : {
848 [ # # ]: 0 : if (cur_tree)
849 : : {
850 [ # # ]: 0 : if (cur_tree->cur_len + 2 > cur_tree->max_len)
851 : : {
852 [ # # ]: 0 : if (CurTreeReAlloc( cur_tree ))
853 : : {
854 : 0 : return -1; /* error */ /* <BRKPT> */
855 : : }
856 : : }
857 : 0 : cur_tree->tree[cur_tree->cur_len++] = rank;
858 : 0 : cur_tree->tree[cur_tree->cur_len++] = 1;
859 : 0 : return 0;
860 : : }
861 : :
862 : 0 : return -1; /* error */ /* <BRKPT> */
863 : : }
864 : :
865 : :
866 : : /****************************************************************************/
867 : 0 : int CurTreeIsLastRank( CUR_TREE *cur_tree, AT_NUMB rank )
868 : : {
869 [ # # # # ]: 0 : if (cur_tree && cur_tree->cur_len > 0)
870 : : {
871 : : int rank_pos;
872 : 0 : rank_pos = cur_tree->cur_len - 1;
873 : 0 : rank_pos -= cur_tree->tree[rank_pos];
874 [ # # ]: 0 : if (rank_pos >= 0)
875 : : {
876 : 0 : return ( rank == cur_tree->tree[rank_pos] );
877 : : }
878 : : }
879 : :
880 : 0 : return 0; /* not found */
881 : : }
882 : :
883 : :
884 : : /****************************************************************************/
885 : 0 : int CurTreeRemoveLastRankIfNoAtoms( CUR_TREE *cur_tree )
886 : : {
887 [ # # # # : 0 : if (cur_tree && cur_tree->tree && cur_tree->cur_len >= 2)
# # ]
888 : : {
889 [ # # ]: 0 : if (1 == cur_tree->tree[cur_tree->cur_len - 1])
890 : : {
891 : 0 : return CurTreeRemoveLastRank( cur_tree ); /* 0=> success, -1=>failed */
892 : : }
893 : 0 : return 1; /* cannot remove */
894 : : }
895 : 0 : return -1; /* error */ /* <BRKPT> */
896 : : }
897 : :
898 : :
899 : : /****************************************************************************/
900 : 0 : int CurTreeAddAtom( CUR_TREE *cur_tree, int at_no )
901 : : {
902 [ # # ]: 0 : if (cur_tree)
903 : : {
904 [ # # ]: 0 : if (cur_tree->cur_len + 1 > cur_tree->max_len)
905 : : {
906 [ # # ]: 0 : if (CurTreeReAlloc( cur_tree ))
907 : : {
908 : 0 : return -1; /* error */ /* <BRKPT> */
909 : : }
910 : : }
911 [ # # ]: 0 : if (cur_tree->cur_len > 0)
912 : : {
913 : 0 : AT_NUMB new_len = cur_tree->tree[--cur_tree->cur_len] + 1;
914 : 0 : cur_tree->tree[cur_tree->cur_len++] = (AT_NUMB) at_no;
915 : 0 : cur_tree->tree[cur_tree->cur_len++] = new_len;
916 : 0 : return 0;
917 : : }
918 : : }
919 : :
920 : 0 : return -1;
921 : : }
922 : :
923 : :
924 : : /****************************************************************************/
925 : 117 : void CurTreeKeepLastAtomsOnly( CUR_TREE *cur_tree, int tpos, int shift )
926 : : { /* on first entry: shift = 1; other values may occur in subsequent recursion */
927 : : /* cur_tree[cur_tree->cur_len - shift] is the length of a segment */
928 : : /* action: remove all atoms except the last from all segments
929 : : that have length value positon to the right from tpos */
930 : : int cur_length_pos;
931 [ + - + - : 117 : if (cur_tree && cur_tree->tree && ( cur_length_pos = cur_tree->cur_len - shift ) > tpos)
- + ]
932 : : {
933 [ # # ]: 0 : if (cur_tree->tree[cur_length_pos] > 2)
934 : : {
935 : : /* current segment contains more than 1 atom. Leave in the segment: rank, the last atom, length value */
936 : : /* subtract (old segment length)-(new segment length) from the tree length */
937 : : /* actual segment length including segment length value = (cur_tree->tree[cur_length_pos]+1) */
938 : 0 : cur_tree->cur_len -= (int) cur_tree->tree[cur_length_pos] - 2;
939 : 0 : memmove(cur_tree->tree + cur_length_pos - cur_tree->tree[cur_length_pos] + 1, /* 1st atom pos */
940 : 0 : cur_tree->tree + cur_length_pos - 1, /* last atom in the current segment position */
941 : 0 : ((long long)shift + 1) * sizeof(cur_tree->tree[0])); /* djb-rwth: cast operator added */
942 : : /* (current segment length) distance from the last tree element has not changed */
943 : 0 : cur_tree->tree[cur_tree->cur_len - shift] = 2;
944 : : /* add 3 to move to the previous segment length position */
945 : 0 : shift += 3; /* lenghth = 3 accounts for 3 currently present. segment items:
946 : : (1) the last atom, (2) rank, (3) length value */
947 : : }
948 : : else
949 : : {
950 : 0 : shift += (int) cur_tree->tree[cur_length_pos] + 1; /* cur_tree->cur_len - (previous segment length position) */
951 : : }
952 : 0 : CurTreeKeepLastAtomsOnly( cur_tree, tpos, shift );
953 : : }
954 : 117 : }
955 : :
956 : :
957 : : /****************************************************************************/
958 : 0 : int CurTreeRemoveIfLastAtom( CUR_TREE *cur_tree, int at_no )
959 : : {
960 [ # # # # : 0 : if (cur_tree && cur_tree->tree && cur_tree->cur_len > 2)
# # ]
961 : : {
962 : 0 : AT_NUMB len = cur_tree->tree[cur_tree->cur_len - 1];
963 [ # # # # ]: 0 : if (len >= 2 && (int) cur_tree->tree[cur_tree->cur_len - 2] == at_no)
964 : : {
965 : 0 : cur_tree->tree[--cur_tree->cur_len - 1] = len - 1;
966 : 0 : return 0;
967 : : }
968 : 0 : return 1; /* not found */
969 : : }
970 : :
971 : 0 : return -1; /* error */ /* <BRKPT> */
972 : : }
973 : :
974 : :
975 : : /****************************************************************************/
976 : 1686 : int CurTreeGetPos( CUR_TREE *cur_tree )
977 : : {
978 [ + - ]: 1686 : if (cur_tree)
979 : : {
980 : 1686 : return cur_tree->cur_len;
981 : : }
982 : :
983 : 0 : return -1;
984 : : }
985 : :
986 : :
987 : : /****************************************************************************/
988 : 894 : int CurTreeSetPos( CUR_TREE *cur_tree, int len )
989 : : {
990 [ + - ]: 894 : if (cur_tree)
991 : : {
992 : 894 : cur_tree->cur_len = len;
993 : 894 : return 0;
994 : : }
995 : :
996 : 0 : return -1;
997 : : }
998 : :
999 : :
1000 : : /****************************************************************************/
1001 : 0 : int CurTreeRemoveLastRank( CUR_TREE *cur_tree )
1002 : : {
1003 [ # # # # ]: 0 : if (cur_tree && cur_tree->cur_len > 0)
1004 : : {
1005 : 0 : cur_tree->cur_len -= cur_tree->tree[cur_tree->cur_len - 1] + 1;
1006 [ # # ]: 0 : if (cur_tree->cur_len >= 0)
1007 : : {
1008 : 0 : return 0;
1009 : : }
1010 : : }
1011 : :
1012 : 0 : return -1;
1013 : : }
1014 : :
1015 : :
1016 : : /****************************************************************************
1017 : : Find if the atom is equivalent to already successfully tried current atoms
1018 : : ****************************************************************************/
1019 : 0 : int CurTreeIsLastAtomEqu( CUR_TREE *cur_tree, int at_no, AT_NUMB *nSymmStereo )
1020 : : {
1021 [ # # # # : 0 : if (cur_tree && cur_tree->tree && nSymmStereo && cur_tree->cur_len > 1)
# # # # ]
1022 : : {
1023 : 0 : AT_NUMB nEq = nSymmStereo[at_no];
1024 : 0 : int end = cur_tree->cur_len - 1;
1025 : 0 : int len = cur_tree->tree[end] - 1;
1026 [ # # ]: 0 : for (; len > 0; len--)
1027 : : {
1028 [ # # ]: 0 : if (nSymmStereo[(int) cur_tree->tree[end - len]] == nEq)
1029 : 0 : return 1;
1030 : : }
1031 : 0 : return 0;
1032 : : }
1033 : :
1034 : 0 : return -1; /* error */ /* <BRKPT> */
1035 : : }
1036 : :
1037 : :
1038 : : #ifdef NEVER /* not used */
1039 : : /****************************************************************************/
1040 : : int CurTreeRemoveLastAtom( CUR_TREE *cur_tree )
1041 : : {
1042 : : if (cur_tree && cur_tree->tree && cur_tree->cur_len > 2)
1043 : : {
1044 : : AT_NUMB len = cur_tree->tree[--cur_tree->cur_len];
1045 : : if (len >= 2)
1046 : : {
1047 : : cur_tree->tree[cur_tree->cur_len - 1] = len - 1;
1048 : : return 0;
1049 : : }
1050 : : }
1051 : : return -1;
1052 : : }
1053 : :
1054 : :
1055 : : /****************************************************************************/
1056 : : int CurTreeReplaceLastRank( CUR_TREE *cur_tree, AT_NUMB rank )
1057 : : {
1058 : : if (!CurTreeRemoveLastRank( cur_tree ))
1059 : : {
1060 : : return CurTreeAddRank( cur_tree, rank );
1061 : : }
1062 : : return -1;
1063 : : }
1064 : :
1065 : :
1066 : : /****************************************************************************
1067 : : returns cur_tree->cur_len for the block containing the rank
1068 : : ****************************************************************************/
1069 : : int CurTreeFindTheRankPos( CUR_TREE *cur_tree, AT_NUMB rank )
1070 : : {
1071 : : int i, k;
1072 : : if (cur_tree && cur_tree->tree && ( i = cur_tree->cur_len ) > 0)
1073 : : {
1074 : : while (0 <= ( k = i - (int) cur_tree->tree[i - 1] - 1 ))
1075 : : {
1076 : : if (cur_tree->tree[k] == rank)
1077 : : {
1078 : : return i;
1079 : : }
1080 : : i = k;
1081 : : }
1082 : : }
1083 : :
1084 : : return -1; /* error */ /* <BRKPT> */
1085 : : }
1086 : : #endif
|