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