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 : : #define SB_DEPTH 6
14 : :
15 : : /*
16 : : static int deep_map_stereo_atoms4=0;
17 : : */
18 : :
19 : : /****************************************************************************
20 : : map_stereo_bonds4 and map_stereo_atoms4 use
21 : : the following members of CANON_STAT *pCS:
22 : :
23 : : pCS->bKeepSymmRank // ??? almost unused, replaced with nSymmStereo != NULL ???
24 : : pCS->bFirstCT
25 : : pCS->bStereoIsBetter
26 : : pCS->lNumNeighListIter
27 : : pCS->lNumBreakTies
28 : : pCS->lNumRejectedCT
29 : : pCS->lNumTotCT
30 : : pCS->lNumEqualCT
31 : : pCS->lNumDecreasedCT
32 : : pCS->bExtract (bRELEASE_VERSION == 0)
33 : : pCS->ulTimeOutTime
34 : :
35 : : pCS->bRankUsedForStereo
36 : : pCS->bAtomUsedForStereo
37 : :
38 : : pCS->LinearCTStereoDble
39 : : pCS->LinearCTStereoCarb
40 : : pCS->nLenLinearCTStereoCarb
41 : : pCS->nLenLinearCTStereoDble
42 : :
43 : : pCS->nPrevAtomNumber
44 : : ****************************************************************************/
45 : :
46 : :
47 : : /****************************************************************************/
48 : 109 : int map_stereo_bonds4( struct tagINCHI_CLOCK *ic,
49 : : CANON_GLOBALS *pCG,
50 : : sp_ATOM *at,
51 : : int num_atoms,
52 : : int num_at_tg,
53 : : int num_max,
54 : : int bAllene,
55 : : const AT_RANK *nCanonRankFrom,
56 : : const AT_RANK *nAtomNumberCanonFrom, /* non-stereo canon ranking */
57 : : AT_RANK *nCanonRankTo, /* output canonical stereo numbering*/
58 : : const AT_RANK *nSymmRank,
59 : : AT_RANK **pRankStack1 /* from */,
60 : : AT_RANK **pRankStack2 /* to */,
61 : : AT_RANK *nTempRank,
62 : : int nNumMappedRanksInput,
63 : : AT_RANK *nSymmStereo,
64 : : NEIGH_LIST *NeighList,
65 : : CANON_STAT *pCS,
66 : : CUR_TREE *cur_tree,
67 : : int nNumMappedBonds,
68 : : int vABParityUnknown )
69 : : {
70 : 109 : int nTotSuccess = 0; /* 1=>full mapping has been completed;
71 : : * 2=>obtained a better stereo;
72 : : * 4=>restart (stereo bond or atom removed from the stereo CT)
73 : : */
74 : 109 : int tpos1 = 0;
75 : : AT_STEREO_DBLE prevBond;
76 : 109 : memset( &prevBond, 0, sizeof( prevBond ) ); /* djb-rwth: memset_s C11/Annex K variant? */
77 : 109 : tpos1 = CurTreeGetPos( cur_tree );
78 : :
79 : 0 : total_restart:
80 : :
81 [ + - ]: 109 : if (!nNumMappedBonds)
82 : : {
83 : :
84 : 109 : memset( pCS->bRankUsedForStereo, 0, sizeof( pCS->bRankUsedForStereo[0] )*num_atoms ); /* djb-rwth: memset_s C11/Annex K variant? */
85 : 109 : SetUseAtomForStereo( pCS->bAtomUsedForStereo, at, num_atoms );
86 : :
87 [ + - + - : 109 : if (pCS->bFirstCT && nSymmStereo && !pCS->bKeepSymmRank)
+ - ]
88 : : {
89 : : int i;
90 [ + + ]: 1221 : for (i = 0; i < num_at_tg; i++)
91 : : {
92 : : /* nSymmStereo[i] = min. {k | at[k] stereo eq. to at[i]} */
93 : 1112 : nSymmStereo[i] = i; /* for union-join to keep track of stereo-equivalent atoms */
94 : : }
95 : : }
96 : : #ifdef FIX_STEREOCOUNT_ERR
97 [ + - ]: 109 : if (pCS->bFirstCT)
98 : : {
99 : 109 : CurTreeSetPos( cur_tree, tpos1 = 0 );
100 : : }
101 : : #endif
102 : : }
103 : :
104 [ - + ]: 109 : if (nNumMappedBonds < pCS->nLenLinearCTStereoDble)
105 : : {
106 : :
107 : : int at_rank1, at_rank2, bStereoIsBetterWasSetHere;
108 : : /* AT_RANK *nRankFrom=*pRankStack1++, AT_RANK *nAtomNumberFrom=pRankStack1++; */
109 : : /* AT_RANK *nRankTo =*pRankStack2++, AT_RANK *nAtomNumberTo =pRankStack2++; */
110 : : AT_RANK canon_min1, canon_min2;
111 : : int bFirstCanonRank;
112 : : int i, j, j1, j2, at_from1, at_from2, at_to1, at_to2, iMax, c;
113 : : int nStackPtr[SB_DEPTH], nNumMappedRanks[SB_DEPTH], LastMappedTo1;
114 : : int istk, istk2, istk3, bAddStack, nNumAtTo1Success;
115 : : int ret1, ret2, parity1, parity2;
116 : :
117 : : AT_RANK at_rank_canon1; /* = pCS->LinearCTStereoDble[nNumMappedBonds].at_num1; */ /* canonical numbers of atoms */
118 : : AT_RANK at_rank_canon2; /* = pCS->LinearCTStereoDble[nNumMappedBonds].at_num2; */ /* adjacent to the stereogenic bond */
119 : : int nNumChoices, nNumUnkn, nNumUndf, nNumBest, nNumWorse, nNumCalc, sb_parity_calc;
120 : 0 : int stereo_bond_parity = 0, prev_stereo_bond_parity, pass, bAllParitiesIdentical, bAllParitiesIdentical2;
121 : : AT_STEREO_DBLE prevBond2;
122 : :
123 : 0 : prevBond = pCS->LinearCTStereoDble[nNumMappedBonds];
124 : 0 : bFirstCanonRank = 1;
125 : 0 : canon_min1 = canon_min2 = 0;
126 : : /*
127 : : // find candidates for atom_from1, atom_to1; they must have identical mapping ranks
128 : : at_rank1=pRankStack1[0][at_from1=nAtomNumberCanonFrom[(int)at_rank_canon1 - 1]]; // rank "from" for mapping
129 : : at_rank2=pRankStack1[0][at_from2=nAtomNumberCanonFrom[(int)at_rank_canon2 - 1]]; // rank "from" for mapping
130 : : */
131 [ # # ]: 0 : if (nNumMappedBonds)
132 : : {
133 : 0 : at_rank_canon1 = pCS->LinearCTStereoDble[nNumMappedBonds - 1].at_num1;
134 : 0 : at_rank_canon2 = pCS->LinearCTStereoDble[nNumMappedBonds - 1].at_num2;
135 : : }
136 : : else
137 : : {
138 : 0 : at_rank_canon1 = 0;
139 : 0 : at_rank_canon2 = 0;
140 : : }
141 : 0 : goto bypass_next_canon_ranks_check;
142 : :
143 : 0 : next_canon_ranks:
144 : :
145 : : /* Save time: avoid calling Next_SB_At_CanonRanks2() */
146 [ # # ]: 0 : if ((!pCS->bStereoIsBetter /* ??? && !pCS->bFirstCT ???*/ &&
147 [ # # ]: 0 : at_rank_canon1 > pCS->LinearCTStereoDble[nNumMappedBonds].at_num1) ||
148 [ # # ]: 0 : (at_rank_canon1 == pCS->LinearCTStereoDble[nNumMappedBonds].at_num1 &&
149 [ # # ]: 0 : at_rank_canon2 >= pCS->LinearCTStereoDble[nNumMappedBonds].at_num2)) /* djb-rwth: addressing LLVM warning */
150 : : {
151 : :
152 [ # # ]: 0 : if (!nTotSuccess)
153 : : {
154 : 0 : pCS->LinearCTStereoDble[nNumMappedBonds] = prevBond;
155 : : }
156 : 0 : CurTreeSetPos( cur_tree, tpos1 );
157 : 0 : return nTotSuccess;
158 : : }
159 : :
160 : 0 : bypass_next_canon_ranks_check:
161 : :
162 : 0 : CurTreeSetPos( cur_tree, tpos1 );
163 : :
164 : : /* find next available canon. numbers for a stereogenic bond pair of atoms */
165 : : /* process allenes AFTER all double bonds and odd-number-of-double-bonds cumulenes */
166 [ # # ]: 0 : if (!( ret1 = Next_SB_At_CanonRanks2( &at_rank_canon1, &at_rank_canon2, /* canonical numbers */
167 : : &canon_min1, &canon_min2,
168 : : &bFirstCanonRank, pCS->bAtomUsedForStereo,
169 : : pRankStack1, pRankStack2,
170 : : nCanonRankFrom, nAtomNumberCanonFrom,
171 : : at, num_atoms, bAllene ) ))
172 : : {
173 : : /* failed to find next stereo bond to assign parity */
174 [ # # # # ]: 0 : if (!bAllene && bFirstCanonRank)
175 : : {
176 : : /* all stereobond have been processed; try to find allene to continue */
177 : 0 : AT_RANK at_rank_canon1_Allene = 0, canon_min1_Allene = 0;
178 : 0 : AT_RANK at_rank_canon2_Allene = 0, canon_min2_Allene = 0;
179 [ # # ]: 0 : if ((ret1 = Next_SB_At_CanonRanks2( &at_rank_canon1_Allene, &at_rank_canon2_Allene,
180 : : &canon_min1_Allene, &canon_min2_Allene,
181 : : &bFirstCanonRank, pCS->bAtomUsedForStereo,
182 : : pRankStack1, pRankStack2,
183 : : nCanonRankFrom, nAtomNumberCanonFrom,
184 : : at, num_atoms, 1 ))) /* djb-rwth: addressing LLVM warning */
185 : : {
186 : 0 : at_rank_canon1 = at_rank_canon1_Allene;
187 : 0 : at_rank_canon2 = at_rank_canon2_Allene;
188 : 0 : canon_min1 = canon_min1_Allene;
189 : 0 : canon_min2 = canon_min2_Allene;
190 : 0 : bAllene = 1; /* switch to allenes */
191 : : }
192 : : }
193 : : }
194 : :
195 [ # # # # ]: 0 : if (!ret1 || (!pCS->bStereoIsBetter &&
196 [ # # ]: 0 : ( at_rank_canon1 > pCS->LinearCTStereoDble[nNumMappedBonds].at_num1 ||
197 [ # # ]: 0 : (at_rank_canon1 == pCS->LinearCTStereoDble[nNumMappedBonds].at_num1 &&
198 [ # # ]: 0 : at_rank_canon2 > pCS->LinearCTStereoDble[nNumMappedBonds].at_num2) ))) /* djb-rwth: addressing LLVM warnings */
199 : : {
200 : : /* new ranks provide greater pCS->LinearCTStereoDble[nNumMappedBonds] and therefore rejected */
201 [ # # ]: 0 : if (!nTotSuccess)
202 : : {
203 : 0 : pCS->LinearCTStereoDble[nNumMappedBonds] = prevBond; /* restore stereo bond CT for the current bond */
204 : : }
205 : 0 : return nTotSuccess;
206 : : }
207 : :
208 : : /* current stereo bond initialization */
209 : 0 : nNumChoices = 0;
210 : 0 : nNumUnkn = 0;
211 : 0 : nNumUndf = 0;
212 : 0 : nNumBest = 0;
213 : 0 : nNumWorse = 0;
214 : 0 : nNumCalc = 0;
215 : 0 : pass = 0;
216 : 0 : prev_stereo_bond_parity = 0;
217 : :
218 : 0 : at_rank1 = pRankStack1[0][at_from1 = nAtomNumberCanonFrom[(int) at_rank_canon1 - 1]]; /* atom 1 rank "from" for mapping */
219 : 0 : at_rank2 = pRankStack1[0][at_from2 = nAtomNumberCanonFrom[(int) at_rank_canon2 - 1]]; /* atom 2 rank "from" for mapping */
220 : : /* we are going to map bond (at[at_from1], at[at_from2]) and
221 : : canonical ranks of its atoms (at_rank_canon1, at_rank_canon2)
222 : : onto a stereogenic bond (at[at_to1], at[at_to2])
223 : : */
224 : 0 : iMax = at_rank1 - 1;
225 : : /* test correctness: sorted pRankStack2[0][] and pRankStack1[0][] should have same ranks for both atoms */
226 [ # # ]: 0 : if (at_rank1 != pRankStack2[0][pRankStack2[1][at_rank1 - 1]] ||
227 [ # # ]: 0 : at_rank2 != pRankStack2[0][pRankStack2[1][at_rank2 - 1]])
228 : : {
229 : : /* program error: "from" and "to" mapping ranks are not equal */
230 : 0 : return CT_STEREOCOUNT_ERR; /* <BRKPT> */
231 : : }
232 : : /* -- do not check stereo features of "from" atoms:
233 : : -- in case of "bond/charge isomerism" they may be missing.
234 : : if ( !at[at_from1].stereo_bond_neighbor[0] ||
235 : : !at[at_from2].stereo_bond_neighbor[0] )
236 : : return CT_STEREOCOUNT_ERR; // program error
237 : : */
238 : :
239 : : /* find out if we have a choice in mapping: check all possible pairs (at_to1, at_to2)
240 : : such that at_from1 is possibly constitutionally equivalent to at_to1, at_from2 to at_to2 */
241 [ # # # # ]: 0 : for (j1 = 0; j1 <= iMax && at_rank1 == pRankStack2[0][at_to1 = pRankStack2[1][iMax - j1]]; j1++)
242 : : {
243 [ # # ]: 0 : if (!at[at_to1].stereo_bond_neighbor[0])
244 : 0 : continue; /* at_to1 does not belong to a stereo bond */
245 [ # # ]: 0 : for (j2 = 0; j2 < MAX_NUM_STEREO_BONDS &&
246 [ # # ]: 0 : ( at_to2 = at[at_to1].stereo_bond_neighbor[j2] ); j2++)
247 : : {
248 : 0 : at_to2--;
249 [ # # ]: 0 : if (pRankStack1[0][at_from2] != pRankStack2[0][at_to2])
250 : 0 : continue; /* at_from2 cannot be mapped on at_to2 */
251 : 0 : stereo_bond_parity = PARITY_VAL( at[at_to1].stereo_bond_parity[j2] );
252 : 0 : i = 0;
253 [ # # # # : 0 : switch (stereo_bond_parity)
# # # ]
254 : : {
255 : :
256 : 0 : case AB_PARITY_UNDF: nNumUndf++;
257 : 0 : break; /* 4 */
258 : 0 : case AB_PARITY_UNKN: nNumUnkn++;
259 : 0 : break; /* 3 (occurs if forced different to UNDF)*/
260 : :
261 : 0 : case BEST_PARITY: nNumBest++; break; /* 1 */
262 : 0 : case WORSE_PARITY: nNumWorse++; break; /* 2 */
263 : 0 : case AB_PARITY_CALC: nNumCalc++; break; /* 6 */
264 : 0 : case AB_PARITY_NONE: i++; break; /* 0 */
265 : : }
266 : 0 : nNumChoices += !i;
267 : : }
268 : : }
269 [ # # ]: 0 : if (nNumChoices != nNumCalc + nNumUndf + nNumUnkn + nNumBest + nNumWorse)
270 : : {
271 : 0 : return CT_STEREOCOUNT_ERR; /* program error */ /* <BRKPT> */
272 : : }
273 [ # # ]: 0 : if (!nNumChoices)
274 : : {
275 : 0 : goto next_canon_ranks;
276 : : }
277 : : /* Determine the first parity to search */
278 : 0 : sb_parity_calc = ( nNumCalc > 0 ) ? BEST_PARITY : 0;
279 : :
280 : : /* ==============================================================
281 : : Search sequence: sb_parity_calc stereo_bond_parity
282 : : ==============================================================
283 : : BEST_PARITY (calc) BEST_PARITY BEST_PARITY
284 : : BEST_PARITY (known) BEST_PARITY WORSE_PARITY or 0
285 : : WORSE_PARITY (calc) WORSE_PARITY WORSE_PARITY
286 : : WORSE_PARITY (known) WORSE_PARITY 0
287 : : AB_PARITY_UNKN(known) AB_PARITY_UNKN 0
288 : : AB_PARITY_UNDF(known) AB_PARITY_UNDF 0
289 : :
290 : : if (sb_parity_calc==stereo_bond_parity) then "calc" else "known"
291 : : */
292 : :
293 : 0 : repeat_all:
294 : :
295 [ # # ]: 0 : if (!nNumMappedBonds)
296 : 0 : pCS->bStereoIsBetter = 0; /* the first stereo feature in the canonical CT; moved here 7-13-2002 */
297 : :
298 [ # # ]: 0 : if (!pass++)
299 : : {
300 : : /* select the smallest (best) parity to search */
301 [ # # ]: 0 : if (sb_parity_calc)
302 : : {
303 : 0 : stereo_bond_parity = BEST_PARITY;
304 : : }
305 : : else
306 : : {
307 [ # # ]: 0 : stereo_bond_parity = nNumBest ? BEST_PARITY :
308 [ # # ]: 0 : nNumWorse ? WORSE_PARITY :
309 [ # # ]: 0 : nNumUnkn ? AB_PARITY_UNKN :
310 [ # # ]: 0 : nNumUndf ? AB_PARITY_UNDF : AB_PARITY_NONE;
311 : : }
312 : : }
313 : : else
314 : : {
315 : : /* second pass: since the first pass failed, search for a worse result */
316 : 0 : prev_stereo_bond_parity = stereo_bond_parity;
317 : 0 : i = NextStereoParity2Test( &stereo_bond_parity, &sb_parity_calc,
318 : : nNumBest, nNumWorse, nNumUnkn, nNumUndf, nNumCalc, vABParityUnknown );
319 [ # # # ]: 0 : switch (i)
320 : : {
321 : 0 : case 0:
322 : 0 : break; /* obtained next parity to test */
323 : 0 : case 1:
324 : 0 : goto next_canon_ranks;
325 : 0 : default:
326 : 0 : return i; /* program error */
327 : : }
328 : : }
329 [ # # ]: 0 : if (stereo_bond_parity == AB_PARITY_NONE)
330 : : {
331 : : /* error? */
332 : 0 : return CT_STEREOCOUNT_ERR; /* <BRKPT> */
333 : : }
334 : : /* check if the new requested parity is good (small) enough */
335 [ # # ]: 0 : if (!pCS->bStereoIsBetter)
336 : : {
337 : 0 : c = CompareLinCtStereoDoubleToValues( nTotSuccess ? pCS->LinearCTStereoDble + nNumMappedBonds : &prevBond,
338 [ # # ]: 0 : at_rank_canon1, at_rank_canon2, (U_CHAR) stereo_bond_parity );
339 [ # # ]: 0 : if (c < 0)
340 : : {
341 [ # # ]: 0 : if (!nTotSuccess)
342 : : {
343 : 0 : pCS->LinearCTStereoDble[nNumMappedBonds] = prevBond;
344 : : }
345 : 0 : CurTreeSetPos( cur_tree, tpos1 );
346 : 0 : return nTotSuccess;
347 : : }
348 : : }
349 : :
350 : 0 : bAllParitiesIdentical = 0;
351 : : /* djb-rwth: removing redundant code */
352 : 0 : LastMappedTo1 = -1;
353 : 0 : bStereoIsBetterWasSetHere = 0;
354 : : /* djb-rwth: removing redundant code */
355 : :
356 [ # # # # ]: 0 : if (!nNumMappedBonds && prev_stereo_bond_parity != stereo_bond_parity)
357 : 0 : pCS->bStereoIsBetter = 0; /* the first stereo feature in the canonical CT; moved here 5-24-2002 */
358 : :
359 [ # # ]: 0 : if (prev_stereo_bond_parity != stereo_bond_parity)
360 : : {
361 : 0 : CurTreeSetPos( cur_tree, tpos1 ); /* start over */
362 : : }
363 : :
364 : : /* Mapping: here at_rank1 = nRankTo, at_to1 = nAtomNumberTo */
365 [ # # # # ]: 0 : for (j1 = 0; j1 <= iMax && at_rank1 == pRankStack2[0][at_to1 = pRankStack2[1][iMax - j1]]; j1++)
366 : : {
367 : 0 : nNumAtTo1Success = 0;
368 [ # # ]: 0 : if (!at[at_to1].stereo_bond_neighbor[0])
369 : 0 : continue; /* at_to1 does not belong to a stereo bond */
370 [ # # # # ]: 0 : if (tpos1 < CurTreeGetPos( cur_tree ) &&
371 [ # # ]: 0 : 1 == CurTreeIsLastRank( cur_tree, at_rank_canon1 ) &&
372 : 0 : 1 == CurTreeIsLastAtomEqu( cur_tree, at_to1, nSymmStereo ))
373 : : {
374 : : /* at_to1 is known to be stereogenically equivalent to another atom tried with at_rank_canon1 */
375 : 0 : continue;
376 : : }
377 : 0 : bAllParitiesIdentical2 = 0;
378 [ # # # # ]: 0 : for (j2 = 0; j2 < MAX_NUM_STEREO_BONDS && ( at_to2 = at[at_to1].stereo_bond_neighbor[j2] ); j2++)
379 : : {
380 : : EQ_NEIGH EN1[2], EN2[2];
381 : : int bond_parity, num1, num2;
382 : : AT_RANK at_rank_canon_n1, at_rank_canon_n2;
383 : :
384 : 0 : at_to2--;
385 [ # # ]: 0 : if (pRankStack1[0][at_from2] != pRankStack2[0][at_to2])
386 : 0 : continue; /* at_from2 cannot be mapped on at_to2 even without mapping at_from1 to at_to1 */
387 : :
388 : : /* check whether the bond parity corresponds to the requested bond parity */
389 [ # # # # ]: 0 : if (PARITY_KNOWN( at[at_to1].stereo_bond_parity[j2] ))
390 : : {
391 [ # # ]: 0 : if (stereo_bond_parity == sb_parity_calc)
392 : : {
393 : 0 : continue; /* requested parity to be calculated, found known parity */
394 : : }
395 [ # # ]: 0 : if (stereo_bond_parity != PARITY_VAL( at[at_to1].stereo_bond_parity[j2] ))
396 : : {
397 : 0 : continue; /* parity differs from the requested parity */
398 : : }
399 : : }
400 : : else
401 [ # # ]: 0 : if (PARITY_CALCULATE( at[at_to1].stereo_bond_parity[j2] ))
402 : : {
403 [ # # ]: 0 : if (stereo_bond_parity != sb_parity_calc)
404 : : {
405 : 0 : continue; /* requested known parity, found parity to be calculated */
406 : : }
407 : : }
408 : : else
409 : : {
410 : 0 : return CT_STEREOCOUNT_ERR; /* unknown parity type */ /* <BRKPT> */
411 : : }
412 : : /* initialize stack pointer nStackPtr[istk] for "hand-made" recursion */
413 : : /* stacks are pRankStack1[], pRankStack2[], nNumMappedRanks[] */
414 : 0 : istk = 0;
415 : 0 : nStackPtr[0] = 0;
416 : 0 : nNumMappedRanks[0] = nNumMappedRanksInput;
417 : 0 : bAddStack = 0;
418 [ # # ]: 0 : bAllParitiesIdentical = ( ( at[at_to1].stereo_bond_parity[j2] & KNOWN_PARITIES_EQL ) ) &&
419 [ # # # # ]: 0 : PARITY_KNOWN( at[at_to1].stereo_bond_parity[j2] );
420 : :
421 [ # # # # ]: 0 : if (!bAllParitiesIdentical && !nNumCalc &&
422 [ # # ]: 0 : ( !nNumUndf + !nNumUnkn + !nNumBest + !nNumWorse ) == 3)
423 : : {
424 : : /* only one kind of bond parity is present; check whether all parities are really same */
425 : 0 : bAllParitiesIdentical = All_SB_Same( at_rank_canon1, at_rank_canon2, /* canonical numbers */
426 : : pRankStack1, pRankStack2,
427 : : nAtomNumberCanonFrom, at );
428 [ # # ]: 0 : if (bAllParitiesIdentical < 0)
429 : : {
430 : 0 : return CT_STEREOCOUNT_ERR; /* <BRKPT> */
431 : : }
432 : : }
433 : :
434 : : /*****************************************************************
435 : : * do the mapping only if parities are not same
436 : : */
437 [ # # ]: 0 : if (!bAllParitiesIdentical)
438 : : {
439 : : /* map atom 1 or reuse previous mapping */
440 [ # # ]: 0 : if (LastMappedTo1 != at_to1)
441 : : {
442 : : /* avoid repetitve mapping to the same first at_to1 using LastMappedTo1 variable */
443 : : /* map atom 1 */
444 : 0 : ret1 = map_an_atom2( pCG, num_at_tg, num_max, at_from1, at_to1,
445 : 0 : nTempRank, nNumMappedRanks[istk], &nNumMappedRanks[istk + 1], pCS,
446 : 0 : NeighList, pRankStack1 + nStackPtr[istk], pRankStack2 + nStackPtr[istk],
447 : : &bAddStack );
448 [ # # # # ]: 0 : if (RETURNED_ERROR( ret1 ))
449 : : {
450 : 0 : return ret1; /* error */
451 : : }
452 : 0 : nStackPtr[istk + 1] = nStackPtr[istk] + bAddStack;
453 : 0 : LastMappedTo1 = at_to1;
454 [ # # ]: 0 : if (bAddStack)
455 : : {
456 [ # # # # ]: 0 : if (tpos1 == CurTreeGetPos( cur_tree ) ||
457 : 0 : 0 == CurTreeIsLastRank( cur_tree, at_rank_canon1 ))
458 : : {
459 : 0 : CurTreeAddRank( cur_tree, at_rank_canon1 );
460 : : }
461 : 0 : CurTreeAddAtom( cur_tree, at_to1 );
462 : : }
463 : : }
464 : 0 : istk++; /* = 1 */
465 : : /* check if we can map atom 2 */
466 [ # # ]: 0 : if (pRankStack1[nStackPtr[istk]][at_from2] != pRankStack2[nStackPtr[istk]][at_to2])
467 : : {
468 : : /*
469 : : * This may happen when:
470 : : * A) Charge/bond isomerism, for example cyclopentadiene(-), or
471 : : * B) possibly stereogenic bond in an alternating ring has heighbors
472 : : * in 2 symmetrically attached rings.
473 : : * Such an alternating bond cannot be mapped on possibly stereogenic bond
474 : : * that has neighbors belonging to 1 of the symmetrically attached rings only.
475 : : * For example:
476 : : * A---B---C---D If all atoms are Carbons then B, C, F, G are constitutionally
477 : : * || || || || equivalent. However, bonds B-C, F-G are not equivalent to
478 : : * || || || || B-F and C-G and cannot be mapped on them.
479 : : * E---F---G---H If at_from1=B, at_from2=F, at_to1=B, then at_from2 cannot be mapped on at_to2=C
480 : : * If at_from1=B, at_from2=F, at_to1=C, then at_from2 cannot be mapped on at_to2=B
481 : : * etc.
482 : : */
483 [ # # ]: 0 : if (sb_parity_calc != stereo_bond_parity)
484 : : {
485 : : /* can be passed only once for each bond */
486 : 0 : nNumChoices--;
487 : 0 : nNumUndf -= ( stereo_bond_parity == AB_PARITY_UNDF );
488 : 0 : nNumUnkn -= ( stereo_bond_parity == AB_PARITY_UNKN );
489 : 0 : nNumBest -= ( stereo_bond_parity == BEST_PARITY );
490 : 0 : nNumWorse -= ( stereo_bond_parity == WORSE_PARITY );
491 : : /* nNumCalc = nNumChoices - (nNumUndf + nNumUnkn + nNumBest + nNumWorse); */
492 : : }
493 : : else
494 [ # # ]: 0 : if (sb_parity_calc == BEST_PARITY)
495 : : {
496 : : /* can be passed 2 times: for BEST_PARITY and WORSE_PARITY in this order */
497 : 0 : nNumChoices--; /* do not repeate for WORSE_PARITY */
498 : 0 : nNumCalc--;
499 : : }
500 : 0 : continue; /* Happens for ID=80036,80253,91354,95532,101532,103788 */
501 : : }
502 [ # # ]: 0 : if (nStackPtr[istk] > nStackPtr[istk - 1])
503 : : {
504 : 0 : bAllParitiesIdentical2 = All_SB_Same( at_rank_canon1, at_rank_canon2,
505 : 0 : pRankStack1 + nStackPtr[istk], pRankStack2 + nStackPtr[istk],
506 : : nAtomNumberCanonFrom, at );
507 [ # # ]: 0 : if (bAllParitiesIdentical2 < 0)
508 : : {
509 : 0 : return CT_STEREOBOND_ERROR; /* <BRKPT> */
510 : : }
511 : : }
512 : : else
513 : : {
514 : 0 : bAllParitiesIdentical2 = 0;
515 : : }
516 [ # # ]: 0 : if (bAllParitiesIdentical2)
517 : : {
518 : : /* do no mapping when all equivalent bonds have same parity */
519 : : /* stereo_bond_parity = PARITY_VAL(at[at_to1].stereo_bond_parity[j2]); */
520 : 0 : ClearPreviousMappings( pRankStack1 + nStackPtr[istk] + 2 );
521 : : }
522 : : else
523 : : {
524 [ # # # # ]: 0 : if (tpos1 < CurTreeGetPos( cur_tree ) &&
525 [ # # ]: 0 : 1 == CurTreeIsLastRank( cur_tree, at_rank_canon2 ) &&
526 : 0 : 1 == CurTreeIsLastAtomEqu( cur_tree, at_to2, nSymmStereo ))
527 : : {
528 : 0 : continue;
529 : : }
530 : : /* map atom 2 */
531 : 0 : ret2 = map_an_atom2( pCG, num_at_tg, num_max, at_from2, at_to2,
532 : 0 : nTempRank, nNumMappedRanks[istk], &nNumMappedRanks[istk + 1], pCS,
533 : 0 : NeighList, pRankStack1 + nStackPtr[istk], pRankStack2 + nStackPtr[istk],
534 : : &bAddStack );
535 [ # # # # ]: 0 : if (RETURNED_ERROR( ret2 ))
536 : : {
537 : 0 : return ret2; /* program error */
538 : : }
539 : 0 : nStackPtr[istk + 1] = nStackPtr[istk] + bAddStack;
540 : 0 : istk++; /* = 2 */
541 [ # # ]: 0 : if (bAddStack)
542 : : {
543 [ # # # # ]: 0 : if (tpos1 == CurTreeGetPos( cur_tree ) ||
544 : 0 : 0 == CurTreeIsLastRank( cur_tree, at_rank_canon2 ))
545 : : {
546 : 0 : CurTreeAddRank( cur_tree, at_rank_canon2 );
547 : : }
548 : 0 : CurTreeAddAtom( cur_tree, at_to2 );
549 : : }
550 : : }
551 : : }
552 : : else
553 : : {
554 : : /* do no mapping when all equivalent bonds have same parity */
555 : : /* stereo_bond_parity = PARITY_VAL(at[at_to1].stereo_bond_parity[j2]); */
556 : 0 : ClearPreviousMappings( pRankStack1 + 2 );
557 : : }
558 : :
559 : : /* we have a precalculated (known) bond parity */
560 : :
561 : : /************************************************************
562 : : *
563 : : * Known Bond Parity case: do not map stereo bond neighbors
564 : : */
565 [ # # ]: 0 : if (stereo_bond_parity != sb_parity_calc) /* parity is known */
566 : : {
567 : : /* accept bond parity and do not map the neighbors */
568 : 0 : bond_parity = stereo_bond_parity;
569 : : /* same code as under " make a decision to accept current mapping" comment below */
570 : : /* with one exception: istk instead of istk3 */
571 : 0 : c = CompareLinCtStereoDoubleToValues( pCS->LinearCTStereoDble + nNumMappedBonds,
572 : 0 : at_rank_canon1, at_rank_canon2, (U_CHAR) bond_parity );
573 [ # # # # ]: 0 : if (c < 0 && !pCS->bStereoIsBetter)
574 : : {
575 : : /* reject */
576 : :
577 : 0 : pCS->lNumRejectedCT++;
578 : : /* remove failed atom2 from the tree */
579 [ # # # # ]: 0 : if (tpos1 < CurTreeGetPos( cur_tree ) &&
580 : 0 : 1 == CurTreeIsLastRank( cur_tree, at_rank_canon2 ))
581 : : {
582 : 0 : CurTreeRemoveIfLastAtom( cur_tree, at_to2 );
583 : 0 : CurTreeRemoveLastRankIfNoAtoms( cur_tree );
584 : : }
585 : 0 : continue; /* to next at_to2; Reject this at_to2: not a minimal CT. */
586 : : }
587 : : else
588 : : {
589 : : /* accept */
590 : :
591 [ # # # # ]: 0 : if (c > 0 && !pCS->bStereoIsBetter)
592 : : {
593 : : /* bond entry is less than the previusly found */
594 : 0 : pCS->bStereoIsBetter = bStereoIsBetterWasSetHere = 1;
595 : 0 : prevBond2 = pCS->LinearCTStereoDble[nNumMappedBonds];
596 : : }
597 : 0 : pCS->LinearCTStereoDble[nNumMappedBonds].at_num1 = at_rank_canon1;
598 : 0 : pCS->LinearCTStereoDble[nNumMappedBonds].at_num2 = at_rank_canon2;
599 : 0 : pCS->LinearCTStereoDble[nNumMappedBonds].parity = bond_parity;
600 : : /* recursive call */
601 : 0 : pCS->bRankUsedForStereo[at_from1] ++;
602 : 0 : pCS->bRankUsedForStereo[at_from2] ++;
603 [ # # ]: 0 : if (!bAllParitiesIdentical)
604 : : {
605 : 0 : pCS->bAtomUsedForStereo[at_to1] --;
606 : 0 : pCS->bAtomUsedForStereo[at_to2] --;
607 : : }
608 : 0 : ret2 = map_stereo_bonds4( ic, pCG, at, num_atoms, num_at_tg, num_max, bAllene, nCanonRankFrom, nAtomNumberCanonFrom, nCanonRankTo,
609 : 0 : nSymmRank, pRankStack1 + nStackPtr[istk], pRankStack2 + nStackPtr[istk],
610 : : nTempRank, nNumMappedRanks[istk], nSymmStereo, NeighList,
611 : : pCS, cur_tree, nNumMappedBonds + 1,
612 : : vABParityUnknown );
613 [ # # ]: 0 : if (!bAllParitiesIdentical)
614 : : {
615 : 0 : pCS->bAtomUsedForStereo[at_to1] ++;
616 : 0 : pCS->bAtomUsedForStereo[at_to2] ++;
617 : : }
618 : 0 : pCS->bRankUsedForStereo[at_from1] --;
619 : 0 : pCS->bRankUsedForStereo[at_from2] --;
620 [ # # ]: 0 : if (ret2 == 4)
621 : : {
622 [ # # ]: 0 : if (nNumMappedBonds)
623 : : {
624 : 0 : return ret2;
625 : : }
626 : : else
627 : : {
628 : 0 : pCS->bFirstCT = 1;
629 : 0 : goto total_restart;
630 : : }
631 : : }
632 : :
633 [ # # # # ]: 0 : if (RETURNED_ERROR( ret2 ))
634 : : {
635 [ # # ]: 0 : if (ret2 == CT_TIMEOUT_ERR)
636 : 0 : return ret2;
637 : : else
638 : 0 : return ret2; /* program error */
639 : : }
640 [ # # ]: 0 : if (ret2 > 0)
641 : : {
642 : 0 : nTotSuccess |= 1;
643 : 0 : nNumAtTo1Success++;
644 [ # # # # ]: 0 : if (bStereoIsBetterWasSetHere || ( ret2 & 2 ))
645 : : {
646 : 0 : CurTreeKeepLastAtomsOnly( cur_tree, tpos1, 1 ); /* start over */
647 : 0 : nTotSuccess |= 2; /* Obtained a smaller CT */
648 : : }
649 : : }
650 : : else
651 : : {
652 [ # # ]: 0 : if (bStereoIsBetterWasSetHere)
653 : : { /* rollback */
654 : 0 : pCS->bStereoIsBetter = 0;
655 : 0 : pCS->LinearCTStereoDble[nNumMappedBonds] = prevBond2;
656 : : }
657 : : /* remove failed atom2 from the tree */
658 [ # # # # ]: 0 : if (tpos1 < CurTreeGetPos( cur_tree ) &&
659 : 0 : 1 == CurTreeIsLastRank( cur_tree, at_rank_canon2 ))
660 : : {
661 : 0 : CurTreeRemoveIfLastAtom( cur_tree, at_to2 );
662 : 0 : CurTreeRemoveLastRankIfNoAtoms( cur_tree );
663 : : }
664 : : /*
665 : : if ( 1 == CurTreeIsLastRank( cur_tree, at_rank_canon1 ) ) {
666 : : CurTreeRemoveLastAtom( cur_tree, at_to1 );
667 : : CurTreeRemoveLastRankIfNoAtoms( cur_tree );
668 : : }
669 : : */
670 : : }
671 : 0 : bStereoIsBetterWasSetHere = 0;
672 : : }
673 [ # # # # ]: 0 : if (bAllParitiesIdentical || bAllParitiesIdentical2)
674 : : {
675 : : break; /* j2 cycle, at_to2 (no need to repeat) */
676 : : }
677 : 0 : continue; /* to next at_to2 */
678 : : }
679 : : /***************************************************************************
680 : : *
681 : : * Unknown Bond Parity case: may need to map stereo bond neighbors
682 : : *
683 : : ****************************************************************************
684 : : * Ranks are not known in advance
685 : : * check if at_from1/at_to1 half-bond has neighbors with equal mapping ranks
686 : : */
687 : :
688 : 0 : parity1 = parity_of_mapped_half_bond( at_from1, at_to1, at_from2, at_to2, at, &EN1[0],
689 : 0 : nCanonRankFrom, pRankStack1[nStackPtr[istk]], pRankStack2[nStackPtr[istk]] );
690 : : /* old approach -- before E/Z parities
691 : : parity1 = parity_of_mapped_atom2( pCG, at_from1, at_to1, at, &EN1[0],
692 : : nCanonRankFrom, pRankStack1[nStackPtr[istk]], pRankStack2[nStackPtr[istk]] );
693 : : */
694 : : /* the following commented out statement is not needed here. */
695 : : /* parity2 = parity_of_mapped_atom2( pCG, at_from2, at_to2, at, &EN2[0],
696 : : nCanonRankFrom, pRankStack1[nStackPtr[istk]],
697 : : pRankStack2[nStackPtr[istk]] );
698 : : */
699 [ # # ]: 0 : if (!parity1)
700 : : {
701 : 0 : return CT_STEREOCOUNT_ERR; /* program error */ /* <BRKPT> */
702 : : }
703 [ # # ]: 0 : num1 = parity1 > 0 ? 1 : 2; /* parity < 0 means additional mapping is needed to set parity */
704 : :
705 : : /* --- try all possible mappings of the stereo bond ending atoms' neighbors --- */
706 : 0 : at_rank_canon_n1 = 0;
707 : : /* djb-rwth: removing redundant code */
708 [ # # ]: 0 : for (i = 0; i < num1; i++)
709 : : {
710 : 0 : int at_from_n1, at_to_n1, at_no_n1_num_success = 0;
711 : 0 : istk2 = istk;
712 [ # # ]: 0 : if (num1 == 2)
713 : : {
714 : 0 : at_rank_canon_n1 = nCanonRankFrom[EN1[0].from_at];
715 : : /* an additional neighbor mapping is necessary; */
716 : : /* we need to map only one at_from1 neighbor to make all neighbors have different ranks */
717 : :
718 : 0 : at_from_n1 = EN1[0].from_at;
719 : 0 : at_to_n1 = EN1[0].to_at[i];
720 : :
721 [ # # # # ]: 0 : if (tpos1 < CurTreeGetPos( cur_tree ) &&
722 [ # # ]: 0 : 1 == CurTreeIsLastRank( cur_tree, at_rank_canon_n1 ) &&
723 : 0 : 1 == CurTreeIsLastAtomEqu( cur_tree, at_to_n1, nSymmStereo ))
724 : 0 : continue;
725 : : /*
726 : : if ( nSymmStereo && !pCS->bFirstCT ) {
727 : : if ( i && nSymmStereo[at_to_n1] == nSymmStereo[(int)EN1[0].to_at[0]] ) {
728 : : continue; // do not test stereo equivalent atoms except the first one
729 : : }
730 : : }
731 : : */
732 : : /* neighbors are tied. Untie them by breaking a tie on ONE of them. */
733 : 0 : ret1 = map_an_atom2( pCG, num_at_tg, num_max, at_from_n1, at_to_n1,
734 : 0 : nTempRank, nNumMappedRanks[istk2], &nNumMappedRanks[istk2 + 1], pCS,
735 : 0 : NeighList, pRankStack1 + nStackPtr[istk2], pRankStack2 + nStackPtr[istk2],
736 : : &bAddStack );
737 [ # # # # ]: 0 : if (RETURNED_ERROR( ret1 ))
738 : : {
739 : 0 : return ret1; /* program error */ /* <BRKPT> */
740 : : }
741 : 0 : nStackPtr[istk2 + 1] = nStackPtr[istk2] + bAddStack;
742 : 0 : istk2++; /* <= 3 */
743 : : /* debug */
744 [ # # ]: 0 : if (istk2 >= SB_DEPTH)
745 : : {
746 : 0 : return CT_OVERFLOW; /* program error */ /* <BRKPT> */
747 : : }
748 [ # # ]: 0 : if (bAddStack)
749 : : {
750 [ # # # # ]: 0 : if (tpos1 == CurTreeGetPos( cur_tree ) ||
751 : 0 : 0 == CurTreeIsLastRank( cur_tree, at_rank_canon_n1 ))
752 : : {
753 : 0 : CurTreeAddRank( cur_tree, at_rank_canon_n1 );
754 : : }
755 : 0 : CurTreeAddAtom( cur_tree, at_to_n1 );
756 : : }
757 : :
758 : :
759 : : /* now that all at_from1 neighbors have been mapped the parity must be defined */
760 : 0 : parity1 = parity_of_mapped_half_bond( at_from1, at_to1, at_from2, at_to2, at, &EN1[1],
761 : 0 : nCanonRankFrom, pRankStack1[nStackPtr[istk2]], pRankStack2[nStackPtr[istk2]] );
762 [ # # ]: 0 : if (parity1 <= 0)
763 : 0 : return CT_STEREOCOUNT_ERR; /* program error */ /* <BRKPT> */
764 : : }
765 : : else
766 : : {
767 : 0 : nNumMappedRanks[istk2 + 1] = nNumMappedRanks[istk2];
768 : 0 : nStackPtr[istk2 + 1] = nStackPtr[istk2];
769 : 0 : istk2++; /* <= 3 */
770 : : }
771 : :
772 : : /* check if at_from2/at_to2 half-bond has neighbors with equal mapping ranks */
773 : 0 : parity2 = parity_of_mapped_half_bond( at_from2, at_to2, at_from1, at_to1, at, &EN2[0],
774 : 0 : nCanonRankFrom, pRankStack1[nStackPtr[istk2]], pRankStack2[nStackPtr[istk2]] );
775 [ # # ]: 0 : if (!parity2)
776 : : {
777 : 0 : return CT_STEREOCOUNT_ERR; /* program error */ /* <BRKPT> */
778 : : }
779 [ # # ]: 0 : num2 = parity2 > 0 ? 1 : 2;
780 : 0 : at_rank_canon_n2 = 0;
781 [ # # ]: 0 : for (j = 0; j < num2; j++)
782 : : {
783 : 0 : int at_from_n2, at_to_n2 = 0;
784 : 0 : istk3 = istk2;
785 [ # # ]: 0 : if (num2 == 2)
786 : : {
787 : 0 : at_rank_canon_n2 = nCanonRankFrom[EN2[0].from_at];
788 : : /* we need to map only one at_from2 neighbor to make its neighbors have different ranks */
789 : 0 : at_from_n2 = EN2[0].from_at;
790 : 0 : at_to_n2 = EN2[0].to_at[j];
791 : :
792 [ # # # # ]: 0 : if (tpos1 < CurTreeGetPos( cur_tree ) &&
793 [ # # ]: 0 : 1 == CurTreeIsLastRank( cur_tree, at_rank_canon_n2 ) &&
794 : 0 : 1 == CurTreeIsLastAtomEqu( cur_tree, at_to_n2, nSymmStereo ))
795 : 0 : continue;
796 : :
797 : : /*
798 : : if ( nSymmStereo && !pCS->bFirstCT ) {
799 : : if ( j && nSymmStereo[at_to_n2] == nSymmStereo[(int)EN2[0].to_at[0]] ) {
800 : : continue; // do not test stereo equivalent atoms except the first one
801 : : }
802 : : }
803 : : */
804 : : /* neighbors are tied. Untie them by breaking a tie on ONE of them. */
805 : 0 : ret1 = map_an_atom2( pCG, num_at_tg, num_max, at_from_n2, at_to_n2,
806 : 0 : nTempRank, nNumMappedRanks[istk3], &nNumMappedRanks[istk3 + 1], pCS,
807 : 0 : NeighList, pRankStack1 + nStackPtr[istk3],
808 : 0 : pRankStack2 + nStackPtr[istk3],
809 : : &bAddStack );
810 [ # # # # ]: 0 : if (RETURNED_ERROR( ret1 ))
811 : : {
812 : 0 : return ret1; /* program error */
813 : : }
814 : 0 : nStackPtr[istk3 + 1] = nStackPtr[istk3] + bAddStack;
815 : 0 : istk3++; /* <= 4 */
816 : :
817 [ # # ]: 0 : if (bAddStack)
818 : : {
819 [ # # # # ]: 0 : if (tpos1 == CurTreeGetPos( cur_tree ) ||
820 : 0 : 0 == CurTreeIsLastRank( cur_tree, at_rank_canon_n2 ))
821 : : {
822 : 0 : CurTreeAddRank( cur_tree, at_rank_canon_n2 );
823 : : }
824 : 0 : CurTreeAddAtom( cur_tree, at_to_n2 );
825 : : }
826 : :
827 : 0 : parity2 = parity_of_mapped_half_bond( at_from2, at_to2, at_from1, at_to1, at, &EN2[1],
828 : 0 : nCanonRankFrom, pRankStack1[nStackPtr[istk3]], pRankStack2[nStackPtr[istk3]] );
829 [ # # ]: 0 : if (parity2 <= 0)
830 : : {
831 : 0 : return CT_STEREOCOUNT_ERR; /* program error */ /* <BRKPT> */
832 : : }
833 : : }
834 : : else
835 : : {
836 : : /* no additional mapping is needed to set atom's parity */
837 : 0 : nNumMappedRanks[istk3 + 1] = nNumMappedRanks[istk3];
838 : 0 : nStackPtr[istk3 + 1] = nStackPtr[istk3];
839 : 0 : istk3++; /* <= 4 */
840 : : }
841 : :
842 : : /*******************************************************************
843 : : * at this point the stereo bond is fully mapped to find its parity
844 : : *******************************************************************/
845 : :
846 [ # # # # ]: 0 : if (parity1 <= 0 || parity2 <= 0)
847 : : {
848 : 0 : return CT_STEREOCOUNT_ERR; /* program error */ /* <BRKPT> */
849 : : }
850 : :
851 : : /* find current bond parity AB_PARITY_ODD */
852 [ # # # # : 0 : if (ATOM_PARITY_WELL_DEF( parity1 ) && ATOM_PARITY_WELL_DEF( parity2 ))
# # # # ]
853 : : {
854 : 0 : bond_parity = 2 - ( parity1 + parity2 ) % 2;
855 : : }
856 : : else
857 : : {
858 : 0 : bond_parity = inchi_max( parity1, parity2 );
859 : : }
860 [ # # # # : 0 : if (ATOM_PARITY_WELL_DEF( bond_parity ) && at[at_to1].stereo_bond_z_prod[j2] < 0)
# # ]
861 : 0 : bond_parity = 2 - ( bond_parity + 1 ) % 2; /* invert the bond parity */
862 : :
863 : :
864 : : /********************************************************
865 : : * make a decision whether to accept the current mapping
866 : : */
867 : 0 : c = CompareLinCtStereoDoubleToValues( pCS->LinearCTStereoDble + nNumMappedBonds,
868 : 0 : at_rank_canon1, at_rank_canon2, (U_CHAR) bond_parity );
869 [ # # # # ]: 0 : if (sb_parity_calc != bond_parity ||
870 [ # # ]: 0 : (c < 0 && !pCS->bStereoIsBetter)) /* djb-rwth: addressing LLVM warning */
871 : : {
872 : : /* reject */
873 : 0 : pCS->lNumRejectedCT++;
874 : : /* remove failed atom2 from the tree */
875 [ # # # # ]: 0 : if (tpos1 < CurTreeGetPos( cur_tree ) &&
876 : 0 : 1 == CurTreeIsLastRank( cur_tree, at_rank_canon_n2 ))
877 : : {
878 : 0 : CurTreeRemoveIfLastAtom( cur_tree, at_to_n2 );
879 : 0 : CurTreeRemoveLastRankIfNoAtoms( cur_tree );
880 : : }
881 : 0 : continue; /* Reject: not a minimal CT. */
882 : : }
883 : : else
884 : : {
885 : :
886 : : /* try to accept */
887 : :
888 [ # # # # ]: 0 : if (c > 0 && !pCS->bStereoIsBetter)
889 : : {
890 : : /* bond_parity is less than the previusly found */
891 : 0 : pCS->bStereoIsBetter = bStereoIsBetterWasSetHere = 1;
892 : 0 : prevBond2 = pCS->LinearCTStereoDble[nNumMappedBonds];
893 : : }
894 : : /* accept */
895 : 0 : pCS->LinearCTStereoDble[nNumMappedBonds].at_num1 = at_rank_canon1;
896 : 0 : pCS->LinearCTStereoDble[nNumMappedBonds].at_num2 = at_rank_canon2;
897 : 0 : pCS->LinearCTStereoDble[nNumMappedBonds].parity = bond_parity;
898 : : /* recursive call */
899 : 0 : pCS->bRankUsedForStereo[at_from1] ++;
900 : 0 : pCS->bRankUsedForStereo[at_from2] ++;
901 : 0 : pCS->bAtomUsedForStereo[at_to1] --;
902 : 0 : pCS->bAtomUsedForStereo[at_to2] --;
903 : 0 : ret2 = map_stereo_bonds4( ic, pCG, at, num_atoms, num_at_tg, num_max, bAllene, nCanonRankFrom, nAtomNumberCanonFrom, nCanonRankTo,
904 : 0 : nSymmRank, pRankStack1 + nStackPtr[istk3], pRankStack2 + nStackPtr[istk3],
905 : : nTempRank, nNumMappedRanks[istk3], nSymmStereo, NeighList,
906 : : pCS, cur_tree, nNumMappedBonds + 1,
907 : : vABParityUnknown );
908 : 0 : pCS->bRankUsedForStereo[at_from1] --;
909 : 0 : pCS->bRankUsedForStereo[at_from2] --;
910 : 0 : pCS->bAtomUsedForStereo[at_to1] ++;
911 : 0 : pCS->bAtomUsedForStereo[at_to2] ++;
912 [ # # ]: 0 : if (ret2 == 4)
913 : : {
914 [ # # ]: 0 : if (nNumMappedBonds)
915 : : {
916 : 0 : return ret2;
917 : : }
918 : : else
919 : : {
920 : 0 : pCS->bFirstCT = 1;
921 : 0 : goto total_restart;
922 : : }
923 : : }
924 [ # # # # ]: 0 : if (RETURNED_ERROR( ret2 ))
925 : : {
926 : 0 : return ret2; /* program error */ /* djb-rwth: fixing coverity ID #499569 */
927 : : }
928 [ # # ]: 0 : if (ret2 > 0)
929 : : {
930 : 0 : nTotSuccess |= 1;
931 : 0 : nNumAtTo1Success++;
932 [ # # # # ]: 0 : if (bStereoIsBetterWasSetHere || ( ret2 & 2 ))
933 : : {
934 : 0 : CurTreeKeepLastAtomsOnly( cur_tree, tpos1, 1 ); /* start over */
935 : 0 : nTotSuccess |= 2; /* Obtained a smaller CT */
936 : : }
937 : 0 : at_no_n1_num_success++;
938 : : }
939 : : else
940 : : {
941 [ # # ]: 0 : if (bStereoIsBetterWasSetHere)
942 : : { /* rollback */
943 : 0 : pCS->bStereoIsBetter = 0;
944 : 0 : pCS->LinearCTStereoDble[nNumMappedBonds] = prevBond2;
945 : : }
946 [ # # # # ]: 0 : if (tpos1 < CurTreeGetPos( cur_tree ) &&
947 : 0 : 1 == CurTreeIsLastRank( cur_tree, at_rank_canon_n2 ))
948 : : {
949 : 0 : CurTreeRemoveIfLastAtom( cur_tree, at_to_n2 );
950 : 0 : CurTreeRemoveLastRankIfNoAtoms( cur_tree );
951 : : }
952 : : }
953 : 0 : bStereoIsBetterWasSetHere = 0;
954 : : }
955 : : } /* end choices in mapping neighbors of the 2nd half-bond */
956 [ # # # # ]: 0 : if (tpos1 < CurTreeGetPos( cur_tree ) &&
957 : 0 : 1 == CurTreeIsLastRank( cur_tree, at_rank_canon_n2 ))
958 : : {
959 : 0 : CurTreeRemoveLastRank( cur_tree );
960 : : }
961 : : /* added 2006-07-20 */
962 [ # # # # : 0 : if (!at_no_n1_num_success && tpos1 < CurTreeGetPos( cur_tree ) &&
# # ]
963 : 0 : 1 == CurTreeIsLastRank( cur_tree, at_rank_canon_n1 ))
964 : : {
965 : 0 : CurTreeRemoveIfLastAtom( cur_tree, at_to_n1 );
966 : : }
967 : : } /* end choices in mapping neighbors of the 1st half-bond */
968 [ # # # # ]: 0 : if (tpos1 < CurTreeGetPos( cur_tree ) &&
969 : 0 : 1 == CurTreeIsLastRank( cur_tree, at_rank_canon_n1 ))
970 : : {
971 : 0 : CurTreeRemoveLastRank( cur_tree );
972 : : }
973 : : } /* end of choices in mapping at_from2 */
974 [ # # # # ]: 0 : if (tpos1 < CurTreeGetPos( cur_tree ) &&
975 : 0 : 1 == CurTreeIsLastRank( cur_tree, at_rank_canon2 ))
976 : : {
977 : 0 : CurTreeRemoveLastRank( cur_tree );
978 : : }
979 [ # # ]: 0 : if (!nNumAtTo1Success)
980 : : {
981 [ # # # # ]: 0 : if (tpos1 < CurTreeGetPos( cur_tree ) &&
982 : 0 : 1 == CurTreeIsLastRank( cur_tree, at_rank_canon1 ))
983 : : {
984 : 0 : CurTreeRemoveIfLastAtom( cur_tree, at_to1 );
985 : 0 : CurTreeRemoveLastRankIfNoAtoms( cur_tree );
986 : : }
987 : : }
988 [ # # ]: 0 : if (bAllParitiesIdentical /*&& !nSymmStereo*/)
989 : : {
990 : 0 : break;
991 : : }
992 : : } /* end of choices in mapping at_from1 */
993 : :
994 [ # # # # ]: 0 : if (tpos1 < CurTreeGetPos( cur_tree ) &&
995 : 0 : 1 == CurTreeIsLastRank( cur_tree, at_rank_canon1 ))
996 : : {
997 : 0 : CurTreeRemoveLastRank( cur_tree );
998 : : }
999 : : else
1000 : : {
1001 : : /* CurTree consistecy check (debug only) */
1002 [ # # ]: 0 : if (tpos1 != CurTreeGetPos( cur_tree ))
1003 : : {
1004 : 0 : return CT_STEREOCOUNT_ERR; /* <BRKPT> */
1005 : : }
1006 : : }
1007 : :
1008 [ # # # # ]: 0 : if (!nTotSuccess || stereo_bond_parity == sb_parity_calc)
1009 : : {
1010 : 0 : goto repeat_all; /* repeat with next parity if no success or with the same parity, now known */
1011 : : }
1012 : :
1013 : : /* Previously the control flow never came here... */
1014 [ # # ]: 0 : if (!nTotSuccess)
1015 : : {
1016 : 0 : pCS->LinearCTStereoDble[nNumMappedBonds] = prevBond;
1017 : 0 : CurTreeSetPos( cur_tree, tpos1 );
1018 : : /* Occurs when atoms are not really equvalent ( -O= without positive charge in "aromatic" ring) */
1019 : 0 : return 0; /* Happens for ID=92439,100318,100319 when EXCL_ALL_AROM_BOND_PARITY=0 and
1020 : : * nNumChoices=0.
1021 : : * Results from impossible previous mapping of symmetric relatively
1022 : : * to a central ring aromatic circles while central ring is not symmetrical due to
1023 : : * alternate bonds (in the central ring number of pi-electrons, atoms and bonds
1024 : : * are symmetrical).
1025 : : * Does not happen when alternate bonds of the central ring
1026 : : * are treated as aromatic by attaching a (+) charge to the oxygen.
1027 : : */
1028 : : }
1029 : : }
1030 : : else
1031 : : {
1032 : : int ret;
1033 : :
1034 [ + - ]: 109 : if (!nNumMappedBonds)
1035 : : {
1036 : 109 : pCS->bStereoIsBetter = 0; /* the first stereo feature in the canonical CT has not been processed yet */
1037 : : }
1038 : :
1039 [ - + ]: 109 : if (nNumMappedBonds < pCS->nLenLinearCTStereoDble)
1040 : : {
1041 : 0 : prevBond = pCS->LinearCTStereoDble[nNumMappedBonds];
1042 : : }
1043 : :
1044 : : /*deep_map_stereo_atoms4=0;*/
1045 : :
1046 : : /* all stereo bonds have been mapped; now start processing stereo atoms... */
1047 : 109 : ret = map_stereo_atoms4( ic, pCG, at, num_atoms, num_at_tg, num_max, nCanonRankFrom, nAtomNumberCanonFrom, nCanonRankTo,
1048 : : nSymmRank, pRankStack1, pRankStack2, nTempRank, nNumMappedRanksInput,
1049 : : nSymmStereo, NeighList, pCS, cur_tree, 0, vABParityUnknown );
1050 : :
1051 [ - + ]: 109 : if (ret == 4)
1052 : : {
1053 [ # # ]: 0 : if (nNumMappedBonds)
1054 : : {
1055 : 0 : return ret;
1056 : : }
1057 : : else
1058 : : {
1059 : 0 : pCS->bFirstCT = 1;
1060 : 0 : goto total_restart;
1061 : : }
1062 : : }
1063 [ + - - + ]: 109 : if (RETURNED_ERROR( ret ))
1064 : : {
1065 [ # # ]: 0 : if (ret == CT_TIMEOUT_ERR)
1066 : 0 : return ret;
1067 : : else
1068 : 0 : return ret; /* program error */
1069 : : }
1070 [ + - ]: 109 : if (ret > 0)
1071 : : {
1072 : 109 : nTotSuccess |= 1;
1073 [ + + ]: 109 : if (ret & 2)
1074 : : {
1075 : 41 : CurTreeKeepLastAtomsOnly( cur_tree, tpos1, 1 ); /* start over */
1076 : 41 : nTotSuccess |= 2; /* Obtained a smaller CT */
1077 : : }
1078 : : }
1079 : : }
1080 [ - + - - ]: 109 : if (!nTotSuccess && pCS->nLenLinearCTStereoDble &&
1081 [ # # ]: 0 : nNumMappedBonds < pCS->nLenLinearCTStereoDble)
1082 : : {
1083 : 0 : pCS->LinearCTStereoDble[nNumMappedBonds] = prevBond;
1084 : : }
1085 : :
1086 : 109 : return nTotSuccess; /* ok */
1087 : : }
1088 : :
1089 : :
1090 : : /****************************************************************************/
1091 : 476 : int map_stereo_atoms4( struct tagINCHI_CLOCK *ic,
1092 : : CANON_GLOBALS *pCG,
1093 : : sp_ATOM *at,
1094 : : int num_atoms,
1095 : : int num_at_tg,
1096 : : int num_max,
1097 : : const AT_RANK *nCanonRankFrom,
1098 : : const AT_RANK *nAtomNumberCanonFrom,
1099 : : AT_RANK *nCanonRankTo, /* canonical numbering to be mapped */
1100 : : const AT_RANK *nSymmRank,
1101 : : AT_RANK **pRankStack1/*from*/,
1102 : : AT_RANK **pRankStack2/*to*/,
1103 : : AT_RANK *nTempRank,
1104 : : int nNumMappedRanksInput,
1105 : : AT_RANK *nSymmStereo,
1106 : : NEIGH_LIST *NeighList,
1107 : : CANON_STAT *pCS,
1108 : : CUR_TREE *cur_tree,
1109 : : int nNumMappedAtoms,
1110 : : int vABParityUnknown )
1111 : : {
1112 : : /*
1113 : : * Do not check whether "from" atoms have any stereo features.
1114 : : */
1115 : 476 : int nTotSuccess = 0;
1116 : : AT_STEREO_CARB prevAtom;
1117 : : int tpos1;
1118 : :
1119 : 476 : memset( &prevAtom, 0, sizeof( prevAtom ) );
1120 : :
1121 : 476 : tpos1 = CurTreeGetPos( cur_tree );
1122 : :
1123 [ + + ]: 476 : if (nNumMappedAtoms < pCS->nLenLinearCTStereoCarb)
1124 : : {
1125 : : /* AT_RANK *nRankFrom=*pRankStack1++, AT_RANK *nAtomNumberFrom=pRankStack1++; */
1126 : : /* AT_RANK *nRankTo =*pRankStack2++, AT_RANK *nAtomNumberTo =pRankStack2++; */
1127 : : int j1, at_from1, at_to1, /*at_from2, at_to2,*/ iMax, lvl, bStereoIsBetterWasSetHere;
1128 : 367 : int istk, bAddStack, nNumAtTo1Success, c, bFirstTime = 1, bAllParitiesIdentical; /* djb-rwth: removing redundant variables */
1129 : : EQ_NEIGH EN[5], *pEN;
1130 : : int nStackPtr[5], nMappedRanks[5], j[5], *nSP, *nMR, bLastLvlFailed;
1131 : :
1132 : : AT_RANK at_rank_canon1, cr[5], at_to[5];
1133 : 367 : AT_RANK canon_rank1_min = 0;
1134 : : int at_rank1; /* rank for mapping */
1135 : : int nNumChoices, nNumUnkn, nNumUndf, nNumWorse, nNumBest, nNumCalc;
1136 : 367 : int stereo_center_parity = 0, sb_parity_calc, pass; /* djb-rwth: removing redundant variable */
1137 : : AT_STEREO_CARB prevAtom2;
1138 : :
1139 : 367 : prevAtom = pCS->LinearCTStereoCarb[nNumMappedAtoms]; /* save to restore in case of failure */
1140 [ + + ]: 367 : at_rank_canon1 = nNumMappedAtoms ? pCS->LinearCTStereoCarb[nNumMappedAtoms - 1].at_num : 0;
1141 : :
1142 : 367 : goto bypass_next_canon_rank_check;
1143 : :
1144 : 0 : next_canon_rank:
1145 : :
1146 [ # # ]: 0 : if (!pCS->bStereoIsBetter /*??? && !pCS->bFirstCT ???*/ &&
1147 [ # # ]: 0 : at_rank_canon1 >= pCS->LinearCTStereoCarb[nNumMappedAtoms].at_num)
1148 : : {
1149 : : /* cannot find next available canonical number */
1150 [ # # ]: 0 : if (!nTotSuccess)
1151 : : {
1152 : 0 : pCS->LinearCTStereoCarb[nNumMappedAtoms] = prevAtom; /* restore because of failure */
1153 : : }
1154 : 0 : CurTreeSetPos( cur_tree, tpos1 );
1155 : 0 : return nTotSuccess;
1156 : : }
1157 : :
1158 : 0 : bypass_next_canon_rank_check:
1159 : :
1160 : 367 : CurTreeSetPos( cur_tree, tpos1 );
1161 : :
1162 : : /* find next available canon. number for a stereogenic atom */
1163 [ + - ]: 367 : if (!Next_SC_At_CanonRank2( &at_rank_canon1, &canon_rank1_min, &bFirstTime,
1164 : : pCS->bAtomUsedForStereo, pRankStack1, pRankStack2,
1165 : 367 : nAtomNumberCanonFrom, num_atoms ) ||
1166 [ + + ]: 367 : (!pCS->bStereoIsBetter &&
1167 [ - + ]: 286 : at_rank_canon1 > pCS->LinearCTStereoCarb[nNumMappedAtoms].at_num)) /* djb-rwth: addressing LLVM warning */
1168 : : {
1169 : : /* cannot find next available canonical number */
1170 [ # # ]: 0 : if (!nTotSuccess)
1171 : : {
1172 : 0 : pCS->LinearCTStereoCarb[nNumMappedAtoms] = prevAtom; /* restore because of failure */
1173 : : }
1174 : 0 : return nTotSuccess;
1175 : : }
1176 : :
1177 : 367 : nNumChoices = 0;
1178 : 367 : nNumUnkn = 0;
1179 : 367 : nNumUndf = 0;
1180 : 367 : nNumBest = 0;
1181 : 367 : nNumWorse = 0;
1182 : 367 : nNumCalc = 0;
1183 : 367 : pass = 0;
1184 : : /* djb-rwth: removing redundant code */
1185 : :
1186 : : /* get mapping rank for the canon. number */
1187 : 367 : at_rank1 = pRankStack1[0][at_from1 = (int) nAtomNumberCanonFrom[at_rank_canon1 - 1]];
1188 : 367 : iMax = at_rank1 - 1;
1189 : : /* for debug only */
1190 [ - + ]: 367 : if (at_rank1 != pRankStack2[0][pRankStack2[1][at_rank1 - 1]])
1191 : : {
1192 : 0 : return CT_STEREOCOUNT_ERR; /* program error */ /* <BRKPT> */
1193 : : }
1194 : :
1195 : : /* count special parities of the not mapped yet "to" atoms */
1196 [ + - + + ]: 738 : for (j1 = 0; j1 <= iMax && at_rank1 == pRankStack2[0][at_to1 = pRankStack2[1][iMax - j1]]; j1++)
1197 : : {
1198 [ + - + - ]: 371 : if (!at[at_to1].stereo_bond_neighbor[0] && pCS->bAtomUsedForStereo[at_to1] == STEREO_AT_MARK)
1199 : : {
1200 : 371 : int no_choice = 0;
1201 : 371 : stereo_center_parity = PARITY_VAL( at[at_to1].stereo_atom_parity );
1202 [ + - + + : 371 : switch (stereo_center_parity)
- - - ]
1203 : : {
1204 : :
1205 : 33 : case AB_PARITY_UNDF: nNumUndf++; break; /* 4 */
1206 : :
1207 : 0 : case AB_PARITY_UNKN: nNumUnkn++;
1208 : 0 : break; /* 3 */
1209 : :
1210 : 169 : case BEST_PARITY: nNumBest++; break; /* 1 */
1211 : 169 : case WORSE_PARITY: nNumWorse++; break; /* 2 */
1212 : 0 : case AB_PARITY_CALC: nNumCalc++; break;
1213 : 0 : case AB_PARITY_NONE: no_choice++; break; /* 0 */
1214 : : }
1215 : 371 : nNumChoices += !no_choice;
1216 : : }
1217 : : }
1218 : :
1219 [ - + ]: 367 : if (nNumChoices != nNumCalc + nNumUndf + nNumUnkn + nNumBest + nNumWorse)
1220 : : {
1221 : 0 : return CT_STEREOCOUNT_ERR; /* program error */ /* <BRKPT> */
1222 : : }
1223 [ - + ]: 367 : if (!nNumChoices)
1224 : : {
1225 : 0 : goto next_canon_rank;
1226 : : }
1227 : : /* Determine the first parity to search */
1228 : 367 : sb_parity_calc = ( nNumCalc > 0 ) ? BEST_PARITY : 0;
1229 : :
1230 : : /* ==============================================================
1231 : : Search sequence: sb_parity_calc stereo_center_parity
1232 : : ==============================================================
1233 : : BEST_PARITY (calc) BEST_PARITY BEST_PARITY
1234 : : BEST_PARITY (known) BEST_PARITY WORSE_PARITY or 0
1235 : : WORSE_PARITY (calc) WORSE_PARITY WORSE_PARITY
1236 : : WORSE_PARITY (known) WORSE_PARITY 0
1237 : : AB_PARITY_UNKN(known) AB_PARITY_UNKN 0
1238 : : AB_PARITY_UNDF(known) AB_PARITY_UNDF 0
1239 : :
1240 : : if (sb_parity_calc==stereo_center_parity) then "calc" else "known"
1241 : : */
1242 : :
1243 : 367 : repeat_all:
1244 : :
1245 [ + - ]: 367 : if (!pass++)
1246 : : {
1247 : : /* select the smallest parity to search */
1248 [ - + ]: 367 : if (sb_parity_calc)
1249 : : {
1250 : 0 : stereo_center_parity = BEST_PARITY;
1251 : : }
1252 : : else
1253 : : {
1254 [ + + ]: 567 : stereo_center_parity = nNumBest ? BEST_PARITY :
1255 [ + + ]: 233 : nNumWorse ? WORSE_PARITY :
1256 [ + - ]: 66 : nNumUnkn ? AB_PARITY_UNKN :
1257 [ + - ]: 33 : nNumUndf ? AB_PARITY_UNDF : AB_PARITY_NONE;
1258 : : }
1259 : : }
1260 : : else
1261 : : {
1262 : : /* djb-rwth: removing redundant code */
1263 : 0 : j1 = NextStereoParity2Test( &stereo_center_parity, &sb_parity_calc,
1264 : : nNumBest, nNumWorse, nNumUnkn, nNumUndf, nNumCalc,
1265 : : vABParityUnknown );
1266 [ # # # ]: 0 : switch (j1)
1267 : : {
1268 : 0 : case 0:
1269 : 0 : break; /* obtained next parity to test */
1270 : 0 : case 1:
1271 : 0 : goto next_canon_rank;
1272 : 0 : default:
1273 : 0 : return j1; /* program error */
1274 : : }
1275 : : }
1276 : :
1277 [ - + ]: 367 : if (stereo_center_parity == AB_PARITY_NONE)
1278 : : {
1279 : : /* error? */
1280 : 0 : return CT_STEREOCOUNT_ERR; /* <BRKPT> */
1281 : : }
1282 : :
1283 : : /* check if the new requested parity is small enough */
1284 [ + + ]: 367 : if (!pCS->bStereoIsBetter)
1285 : : {
1286 : 286 : c = CompareLinCtStereoAtomToValues( nTotSuccess ? pCS->LinearCTStereoCarb + nNumMappedAtoms : &prevAtom,
1287 [ - + ]: 286 : at_rank_canon1, (U_CHAR) stereo_center_parity );
1288 [ - + ]: 286 : if (c < 0)
1289 : : {
1290 [ # # ]: 0 : if (!nTotSuccess)
1291 : : {
1292 : 0 : pCS->LinearCTStereoCarb[nNumMappedAtoms] = prevAtom;
1293 : : }
1294 : 0 : CurTreeSetPos( cur_tree, tpos1 );
1295 : 0 : return nTotSuccess;
1296 : : }
1297 : : }
1298 : :
1299 : : /* djb-rwth: removing redundant code */
1300 : 367 : bStereoIsBetterWasSetHere = 0;
1301 : : /* djb-rwth: removing redundant code */
1302 : 367 : CurTreeSetPos( cur_tree, tpos1 ); /* start over */
1303 : :
1304 : : /*
1305 : : if ( prev_stereo_center_parity != stereo_center_parity ) {
1306 : : CurTreeSetPos( cur_tree, tpos1 );
1307 : : }
1308 : : */
1309 : : /* nRankTo nAtomNumberTo */
1310 [ + - + - ]: 367 : for (j1 = 0; j1 <= iMax && at_rank1 == pRankStack2[0][at_to1 = pRankStack2[1][iMax - j1]]; j1++)
1311 : : {
1312 : : int ret, ret1, ret2, parity1;
1313 : 367 : nNumAtTo1Success = 0;
1314 : : /*
1315 : : if ( !(at[at_to1].stereo_atom_parity && !at[at_to1].stereo_bond_neighbor[0] &&
1316 : : pCS->bAtomUsedForStereo[at_to1] == STEREO_AT_MARK ) )
1317 : : */
1318 [ + - + - ]: 367 : if (!at[at_to1].stereo_atom_parity || at[at_to1].stereo_bond_neighbor[0] ||
1319 [ - + ]: 367 : pCS->bAtomUsedForStereo[at_to1] != STEREO_AT_MARK) /* simplify 12-17-2003 */
1320 : : {
1321 : 0 : continue;
1322 : : }
1323 : : /* Do not map on non-stereogenic atom constitutionally
1324 : : * equivalent to a steregenic atom. Here
1325 : : * at[at_to1] is not a sterereo center; | |
1326 : : * bonds tautomerism is a usual cause. -P(+)-CH=P-
1327 : : * For example, consider a fragment: | |
1328 : : * The two atoms P may be constitutionally
1329 : : * equivalent, P(+) may be seen as a stereocenter
1330 : : * while another P has a double bond (Now such a P(V) IS a stereocenter).
1331 : : */
1332 : :
1333 : : /* check whether the stereocenter parity corresponds to the requested stereocenter parity */
1334 [ + - + - ]: 367 : if (PARITY_KNOWN( at[at_to1].stereo_atom_parity ))
1335 : : {
1336 [ - + ]: 367 : if (stereo_center_parity == sb_parity_calc)
1337 : : {
1338 : 0 : continue; /* requested parity to be calculated, found known parity */
1339 : : }
1340 [ - + ]: 367 : if (stereo_center_parity != PARITY_VAL( at[at_to1].stereo_atom_parity ))
1341 : : {
1342 : 0 : continue; /* parity differs from the requested parity */
1343 : : }
1344 : : }
1345 : : else
1346 : : {
1347 [ # # ]: 0 : if (PARITY_CALCULATE( at[at_to1].stereo_atom_parity ))
1348 : : {
1349 [ # # ]: 0 : if (stereo_center_parity != sb_parity_calc)
1350 : : {
1351 : 0 : continue; /* requested known parity, found patity to be calculated */
1352 : : }
1353 : : }
1354 : : else
1355 : : {
1356 : 0 : return CT_STEREOCOUNT_ERR; /* unknown parity type */
1357 : : }
1358 : : }
1359 : :
1360 [ + - ]: 734 : bAllParitiesIdentical = ( ( at[at_to1].stereo_atom_parity & KNOWN_PARITIES_EQL ) &&
1361 [ + - + - ]: 367 : PARITY_KNOWN( at[at_to1].stereo_atom_parity ) );
1362 : :
1363 [ - + - - ]: 367 : if (!bAllParitiesIdentical && !nNumCalc &&
1364 [ # # ]: 0 : ( !nNumUndf + !nNumUnkn + !nNumBest + !nNumWorse ) == 3)
1365 : : {
1366 : : /* only one kind of stereocenter parity is present; check whether all parities are really same */
1367 : 0 : bAllParitiesIdentical = All_SC_Same( at_rank_canon1, /* canonical number */
1368 : : pRankStack1, pRankStack2,
1369 : : nAtomNumberCanonFrom, at );
1370 [ # # ]: 0 : if (bAllParitiesIdentical < 0)
1371 : : {
1372 : 0 : return CT_STEREOCOUNT_ERR;
1373 : : }
1374 : : }
1375 [ - + - - ]: 367 : if (tpos1 < CurTreeGetPos( cur_tree ) &&
1376 [ # # ]: 0 : 1 == CurTreeIsLastRank( cur_tree, at_rank_canon1 ) &&
1377 : 0 : 1 == CurTreeIsLastAtomEqu( cur_tree, at_to1, nSymmStereo ))
1378 : : {
1379 : 0 : continue;
1380 : : }
1381 : :
1382 : :
1383 : : /* initialize stack pointer nStackPtr[istk] for "hand-made" recursion */
1384 : : /* stacks are pRankStack1[], pRankStack2[], nNumMappedRanks[] */
1385 : 367 : istk = 0;
1386 : 367 : nStackPtr[istk] = 0;
1387 : 367 : nMappedRanks[istk] = nNumMappedRanksInput;
1388 : 367 : bAddStack = 0;
1389 : : /* if all equivalent atoms have same known parity, do not map any of them here */
1390 [ - + ]: 367 : if (!bAllParitiesIdentical)
1391 : : {
1392 : : /* map the central atom */
1393 : : /* this mapping is always possible */
1394 : 0 : ret1 = map_an_atom2( pCG, num_at_tg, num_max, at_from1, at_to1,
1395 : 0 : nTempRank, nMappedRanks[istk], &nMappedRanks[istk + 1], pCS,
1396 : 0 : NeighList, pRankStack1 + nStackPtr[istk], pRankStack2 + nStackPtr[istk],
1397 : : &bAddStack );
1398 [ # # # # ]: 0 : if (RETURNED_ERROR( ret1 ))
1399 : : {
1400 : 0 : return ret1; /* error */
1401 : : }
1402 : 0 : nStackPtr[istk + 1] = nStackPtr[istk] + bAddStack;
1403 : 0 : istk++;
1404 : : }
1405 : : else
1406 : : {
1407 : 367 : ClearPreviousMappings( pRankStack1 + 2 ); /* precaution */
1408 : : }
1409 : :
1410 : : /*********************************************************************************
1411 : : *
1412 : : * Unknown Stereocenter Parity case: possibly need to map stereo center neighbors
1413 : : */
1414 [ - + ]: 367 : if (stereo_center_parity == sb_parity_calc)
1415 : : {
1416 : : /* find out the parity */
1417 : 0 : parity1 = parity_of_mapped_atom2( pCG, at_from1, at_to1, at, &EN[istk],
1418 : 0 : nCanonRankFrom, pRankStack1[nStackPtr[istk]],
1419 : 0 : pRankStack2[nStackPtr[istk]] );
1420 : : /* if parity is well-defined then returned EN[istk].num_to=0 */
1421 [ # # ]: 0 : if (!parity1)
1422 : : {
1423 : 0 : return CT_STEREOCOUNT_ERR; /* program error */ /* <BRKPT> */
1424 : : }
1425 [ # # # # ]: 0 : if (!EN[istk].num_to && parity1 != sb_parity_calc)
1426 : : {
1427 : 0 : continue; /* looking for the parity value = sb_parity_calc */
1428 : : }
1429 : : }
1430 : : else
1431 : : {
1432 : : /* Known parity */
1433 : 367 : parity1 = stereo_center_parity;
1434 : 367 : EN[istk].num_to = 0;
1435 : : }
1436 : :
1437 : : /***********************************************************************
1438 : : * no need to map the neighbors: parity is known or has been calculated
1439 : : */
1440 [ - + - - ]: 367 : if ((stereo_center_parity == sb_parity_calc && !EN[istk].num_to) ||
1441 : : /* now well-defined, but unknown in advance atom parity OR */
1442 [ + - ]: 367 : stereo_center_parity != sb_parity_calc) /* djb-rwth: addressing LLVM warning */
1443 : : /* known in advance parity = stereo_center_parity */
1444 : : {
1445 : : /* do not need to map the neighbors */
1446 : 367 : c = CompareLinCtStereoAtomToValues( pCS->LinearCTStereoCarb + nNumMappedAtoms,
1447 : 367 : at_rank_canon1, (U_CHAR) parity1 );
1448 [ - + - - ]: 367 : if (c < 0 && !pCS->bStereoIsBetter)
1449 : : {
1450 : : /* reject */
1451 : 0 : pCS->lNumRejectedCT++;
1452 : 0 : continue; /* Reject: not a minimal CT. Should not happen */
1453 : : }
1454 : : else
1455 : : {
1456 : : /* accept */
1457 [ - + ]: 367 : if (bAddStack)
1458 : : {
1459 [ # # # # ]: 0 : if (tpos1 == CurTreeGetPos( cur_tree ) ||
1460 : 0 : 0 == CurTreeIsLastRank( cur_tree, at_rank_canon1 ))
1461 : : {
1462 : 0 : CurTreeAddRank( cur_tree, at_rank_canon1 );
1463 : : }
1464 : 0 : CurTreeAddAtom( cur_tree, at_to1 );
1465 : : }
1466 : :
1467 [ + + + + ]: 367 : if (c > 0 && !pCS->bStereoIsBetter)
1468 : : {
1469 : : /* stereo center entry is less than the previusly found */
1470 : 41 : pCS->bStereoIsBetter = bStereoIsBetterWasSetHere = 1;
1471 : 41 : prevAtom2 = pCS->LinearCTStereoCarb[nNumMappedAtoms];
1472 : : }
1473 : 367 : pCS->LinearCTStereoCarb[nNumMappedAtoms].parity = parity1;
1474 : 367 : pCS->LinearCTStereoCarb[nNumMappedAtoms].at_num = at_rank_canon1;
1475 : 367 : pCS->bRankUsedForStereo[at_from1] = 3;
1476 : : #if ( FIX_ChCh_STEREO_CANON_BUG == 1 )
1477 [ - + ]: 367 : if (!bAllParitiesIdentical)
1478 : : #endif
1479 : 0 : pCS->bAtomUsedForStereo[at_to1] -= STEREO_AT_MARK;
1480 : :
1481 : :
1482 : 367 : ret = map_stereo_atoms4( ic, pCG,
1483 : : at, num_atoms, num_at_tg, num_max,
1484 : : nCanonRankFrom,
1485 : : nAtomNumberCanonFrom,
1486 : : nCanonRankTo,
1487 : : nSymmRank,
1488 : 367 : pRankStack1 + nStackPtr[istk],
1489 : 367 : pRankStack2 + nStackPtr[istk],
1490 : : nTempRank,
1491 : : nMappedRanks[istk],
1492 : : nSymmStereo,
1493 : : NeighList,
1494 : : pCS,
1495 : : cur_tree,
1496 : : nNumMappedAtoms + 1,
1497 : : vABParityUnknown );
1498 : :
1499 : 367 : pCS->bRankUsedForStereo[at_from1] = 0;
1500 : : #if ( FIX_ChCh_STEREO_CANON_BUG == 1 )
1501 [ - + ]: 367 : if (!bAllParitiesIdentical)
1502 : : #endif
1503 : 0 : pCS->bAtomUsedForStereo[at_to1] += STEREO_AT_MARK;
1504 : :
1505 [ - + ]: 367 : if (ret == 4)
1506 : : {
1507 : 0 : return ret;
1508 : : }
1509 : :
1510 [ + - - + ]: 367 : if (RETURNED_ERROR( ret ))
1511 : : {
1512 : 0 : return ret; /* program error */ /* djb-rwth: fixing coverity ID #499567 */
1513 : : }
1514 : :
1515 [ + - ]: 367 : if (ret > 0)
1516 : : {
1517 : 367 : nTotSuccess |= 1;
1518 : 367 : nNumAtTo1Success++;
1519 [ + + + + ]: 367 : if (bStereoIsBetterWasSetHere || ( ret & 2 ))
1520 : : {
1521 : 76 : CurTreeKeepLastAtomsOnly( cur_tree, tpos1, 1 ); /* start over */
1522 : 76 : nTotSuccess |= 2; /* Obtained a smaller CT */
1523 : : }
1524 : : }
1525 : : else
1526 : : {
1527 [ # # ]: 0 : if (bStereoIsBetterWasSetHere)
1528 : : {
1529 : 0 : pCS->bStereoIsBetter = 0;
1530 : 0 : pCS->LinearCTStereoCarb[nNumMappedAtoms] = prevAtom2;
1531 : : }
1532 : : /* remove failed atom1 from the tree */
1533 : :
1534 [ # # # # ]: 0 : if (tpos1 < CurTreeGetPos( cur_tree ) &&
1535 : 0 : 1 == CurTreeIsLastRank( cur_tree, at_rank_canon1 ))
1536 : : {
1537 : 0 : CurTreeRemoveIfLastAtom( cur_tree, at_to1 );
1538 : 0 : CurTreeRemoveLastRankIfNoAtoms( cur_tree );
1539 : : }
1540 : : }
1541 : 367 : bStereoIsBetterWasSetHere = 0;
1542 : : }
1543 : :
1544 : : /*
1545 : : if ( (at[at_to1].stereo_atom_parity & KNOWN_PARITIES_EQL ) &&
1546 : : ATOM_PARITY_KNOWN(stereo_center_parity) && !nSymmStereo ) { // ??? add && !nSymmStereo ???
1547 : : break; // do not repeat for the same kind of stereo atom with the parity known in advance
1548 : : }
1549 : : */
1550 [ + - ]: 367 : if (bAllParitiesIdentical)
1551 : : {
1552 : 367 : break; /* do not repeat for the same kind of stereo atom with the parity known in advance */
1553 : : }
1554 : 0 : continue;
1555 : : }
1556 : :
1557 : : /***************************************************
1558 : : *
1559 : : * Need to map the neighbors
1560 : : */
1561 [ # # ]: 0 : if (stereo_center_parity != sb_parity_calc)
1562 : : {
1563 : 0 : return CT_STEREOCOUNT_ERR; /* program error */ /* <BRKPT> */
1564 : : }
1565 : : /* -- has already been calculated --
1566 : : parity1 = parity_of_mapped_atom2( pCG, at_from1, at_to1, at, &EN[istk],
1567 : : nCanonRankFrom, pRankStack1[nStackPtr[istk]], pRankStack2[nStackPtr[istk]] );
1568 : : */
1569 [ # # ]: 0 : if (!parity1)
1570 : : {
1571 : 0 : return CT_STEREOCOUNT_ERR; /* 1/25/2002 */ /* <BRKPT> */
1572 : : }
1573 : :
1574 [ # # ]: 0 : if (bAddStack)
1575 : : {
1576 [ # # # # ]: 0 : if (tpos1 == CurTreeGetPos( cur_tree ) ||
1577 : 0 : 0 == CurTreeIsLastRank( cur_tree, at_rank_canon1 ))
1578 : : {
1579 : 0 : CurTreeAddRank( cur_tree, at_rank_canon1 );
1580 : : }
1581 : 0 : CurTreeAddAtom( cur_tree, at_to1 );
1582 : : }
1583 : : /******************************************************
1584 : : * Need to fix the neighbors to define the atom parity
1585 : : ******************************************************/
1586 : : /* a recursion replaced with the hand-made stack */
1587 : 0 : lvl = 0; /* the "recursion" depth level */
1588 : 0 : nSP = &nStackPtr[istk];
1589 : 0 : nMR = &nMappedRanks[istk];
1590 : 0 : pEN = &EN[istk];
1591 : 0 : bLastLvlFailed = 0;
1592 : :
1593 : : /* entering "recursion" depth level lvl */
1594 : 0 : next_lvl:
1595 [ # # ]: 0 : if (pEN[lvl].num_to)
1596 : : {
1597 : : /* Found tied neighbors. Try all transpositions of the tied neighbors.
1598 : : * j is a number of the "to" tied neighbor in the pEN[lvl].to_at[*] to
1599 : : * which the pEN[lvl].from_at "from" neighbor's canonical number is mapped
1600 : : */
1601 : 0 : j[lvl] = 0;
1602 : 0 : next_j:
1603 : 0 : cr[lvl] = nCanonRankFrom[pEN[lvl].from_at];
1604 : 0 : at_to[lvl] = pEN[lvl].to_at[j[lvl]];
1605 [ # # # # : 0 : if (j[lvl] && tpos1 < CurTreeGetPos( cur_tree ) &&
# # ]
1606 [ # # ]: 0 : 1 == CurTreeIsLastRank( cur_tree, cr[lvl] ) &&
1607 : 0 : 1 == CurTreeIsLastAtomEqu( cur_tree, at_to[lvl], nSymmStereo ))
1608 : : {
1609 : 0 : lvl++;
1610 : 0 : bLastLvlFailed = 0;
1611 : 0 : goto backup; /* do not test stereo equivalent atoms except the first one */
1612 : : }
1613 : :
1614 : 0 : ret2 = map_an_atom2( pCG, num_at_tg, num_max,
1615 : 0 : pEN[lvl].from_at, /* from */
1616 : 0 : pEN[lvl].to_at[j[lvl]], /* to */
1617 : 0 : nTempRank, nMR[lvl], &nMR[lvl + 1], pCS,
1618 : 0 : NeighList, pRankStack1 + nSP[lvl], pRankStack2 + nSP[lvl],
1619 : : &bAddStack );
1620 : :
1621 [ # # # # ]: 0 : if (RETURNED_ERROR( ret2 ))
1622 : : {
1623 : 0 : return ret2; /* program error */
1624 : : }
1625 : :
1626 : : /* next recursion depth level */
1627 [ # # ]: 0 : if (bAddStack)
1628 : : {
1629 [ # # # # ]: 0 : if (tpos1 == CurTreeGetPos( cur_tree ) ||
1630 : 0 : 0 == CurTreeIsLastRank( cur_tree, cr[lvl] ))
1631 : : {
1632 : 0 : CurTreeAddRank( cur_tree, cr[lvl] );
1633 : : }
1634 : 0 : CurTreeAddAtom( cur_tree, at_to[lvl] );
1635 : : }
1636 : 0 : nSP[lvl + 1] = nSP[lvl] + bAddStack;
1637 : 0 : lvl++; /* upon increment lvl = number of additionally mapped neighbors
1638 : : * (entering next recursion level) */
1639 : :
1640 : : /* check if the mapping has defined the parity */
1641 : 0 : parity1 = parity_of_mapped_atom2( pCG, at_from1, at_to1, at, &pEN[lvl],
1642 : 0 : nCanonRankFrom, pRankStack1[nSP[lvl]], pRankStack2[nSP[lvl]] );
1643 : :
1644 [ # # ]: 0 : if (!parity1)
1645 : : {
1646 : 0 : return CT_STEREOCOUNT_ERR; /* 1/25/2002 */ /* <BRKPT> */
1647 : : }
1648 [ # # ]: 0 : if (parity1 < 0)
1649 : : {
1650 : 0 : goto next_lvl; /* we need at least one more mapping to define the parity */
1651 : : }
1652 : :
1653 : : /**********************************************************
1654 : : *
1655 : : * Check the parity
1656 : : *
1657 : : **********************************************************
1658 : : * make a decision whether to accept the current mapping */
1659 : :
1660 : 0 : c = CompareLinCtStereoAtomToValues( pCS->LinearCTStereoCarb + nNumMappedAtoms,
1661 : 0 : at_rank_canon1, (U_CHAR) parity1 );
1662 [ # # # # ]: 0 : if (sb_parity_calc != parity1 ||
1663 [ # # ]: 0 : (c < 0 && !pCS->bStereoIsBetter)) /* djb-rwth: addressing LLVM warning */
1664 : : {
1665 : 0 : pCS->lNumRejectedCT++;
1666 : 0 : bLastLvlFailed = 1;
1667 : : }
1668 : : else
1669 : : /* the parity has been defined (all neighbors have untied ranks) */
1670 : : /* if ( bAcceptAllParities || parity1 == BEST_PARITY ) */
1671 : : {
1672 : : /*********************************************************************
1673 : : *
1674 : : * Process the parity here. We are at the top of the recursion stack.
1675 : : *
1676 : : *********************************************************************/
1677 : : /* try to accept current neighbors mapping */
1678 [ # # # # ]: 0 : if (c > 0 && !pCS->bStereoIsBetter)
1679 : : {
1680 : 0 : pCS->bStereoIsBetter = bStereoIsBetterWasSetHere = 1;
1681 : 0 : prevAtom2 = pCS->LinearCTStereoCarb[nNumMappedAtoms];
1682 : : }
1683 : 0 : pCS->LinearCTStereoCarb[nNumMappedAtoms].parity = parity1;
1684 : 0 : pCS->LinearCTStereoCarb[nNumMappedAtoms].at_num = at_rank_canon1;
1685 : 0 : pCS->bRankUsedForStereo[at_from1] = 3;
1686 : 0 : pCS->bAtomUsedForStereo[at_to1] -= STEREO_AT_MARK;
1687 : :
1688 : 0 : ret = map_stereo_atoms4( ic, pCG, at, num_atoms, num_at_tg, num_max, nCanonRankFrom, nAtomNumberCanonFrom, nCanonRankTo,
1689 : 0 : nSymmRank, pRankStack1 + nSP[lvl], pRankStack2 + nSP[lvl],
1690 : 0 : nTempRank, nMR[lvl], nSymmStereo, NeighList,
1691 : : pCS, cur_tree, nNumMappedAtoms + 1,
1692 : : vABParityUnknown );
1693 : :
1694 : 0 : pCS->bRankUsedForStereo[at_from1] = 0;
1695 : 0 : pCS->bAtomUsedForStereo[at_to1] += STEREO_AT_MARK;
1696 [ # # ]: 0 : if (ret == 4)
1697 : : {
1698 : 0 : return ret;
1699 : : }
1700 [ # # # # ]: 0 : if (RETURNED_ERROR( ret ))
1701 : : {
1702 [ # # ]: 0 : if (ret == CT_TIMEOUT_ERR)
1703 : 0 : return ret;
1704 : : else
1705 : 0 : return ret; /* program error */
1706 : : }
1707 [ # # ]: 0 : if (ret > 0)
1708 : : {
1709 : 0 : nTotSuccess |= 1;
1710 : 0 : nNumAtTo1Success++;
1711 [ # # # # ]: 0 : if (bStereoIsBetterWasSetHere || ( ret & 2 ))
1712 : : {
1713 : 0 : CurTreeKeepLastAtomsOnly( cur_tree, tpos1, 1 ); /* start over */
1714 : 0 : nTotSuccess |= 2; /* Obtained a smaller CT */
1715 : : }
1716 : : }
1717 : : else
1718 : : {
1719 [ # # ]: 0 : if (bStereoIsBetterWasSetHere)
1720 : : {
1721 : 0 : pCS->bStereoIsBetter = 0;
1722 : 0 : pCS->LinearCTStereoCarb[nNumMappedAtoms] = prevAtom2;
1723 : : }
1724 : 0 : bLastLvlFailed = 1;
1725 : : }
1726 : 0 : bStereoIsBetterWasSetHere = 0;
1727 : :
1728 : : /* avoid redundant repetitions: */
1729 : : /* check if neighbors mappings have altered another stereo center parity */
1730 [ # # # # ]: 0 : if (!nSymmStereo && !might_change_other_atom_parity( at, num_atoms, at_to1,
1731 : 0 : pRankStack2[nSP[lvl]] /* ranks after neigbors mapping */,
1732 : 0 : pRankStack2[nStackPtr[istk]] /* ranks before the mapping neighbors */ ))
1733 : : {
1734 : 0 : goto done;
1735 : : }
1736 : : }
1737 : : /* Continue the cycle. Go to the previous "recursion" level */
1738 : 0 : backup:
1739 [ # # ]: 0 : while (lvl-- > 0)
1740 : : {
1741 : :
1742 : 0 : j[lvl] ++; /* next neighbor at this level */
1743 [ # # ]: 0 : if (j[lvl] < pEN[lvl].num_to)
1744 : : {
1745 [ # # ]: 0 : if (bLastLvlFailed)
1746 : : {
1747 [ # # # # ]: 0 : if (tpos1 < CurTreeGetPos( cur_tree ) &&
1748 : 0 : 1 == CurTreeIsLastRank( cur_tree, cr[lvl] ))
1749 : : {
1750 : 0 : CurTreeRemoveIfLastAtom( cur_tree, at_to[lvl] );
1751 : 0 : CurTreeRemoveLastRankIfNoAtoms( cur_tree );
1752 : : }
1753 : 0 : bLastLvlFailed = 0;
1754 : : }
1755 : : /* Done with this level. Go back one level */
1756 : 0 : goto next_j;
1757 : : }
1758 : : /* remove failed atom from the tree */
1759 [ # # # # ]: 0 : if (tpos1 < CurTreeGetPos( cur_tree ) &&
1760 : 0 : 1 == CurTreeIsLastRank( cur_tree, cr[lvl] ))
1761 : : {
1762 : 0 : CurTreeRemoveLastRank( cur_tree );
1763 : : }
1764 : : }
1765 : 0 : goto done;
1766 : : }
1767 : : else
1768 : : {
1769 : 0 : cr[lvl] = 0;
1770 : : }
1771 : :
1772 : 0 : done:; /* at this point lvl=0. */
1773 [ # # ]: 0 : if (!nNumAtTo1Success)
1774 : : {
1775 [ # # # # ]: 0 : if (tpos1 < CurTreeGetPos( cur_tree ) &&
1776 : 0 : 1 == CurTreeIsLastRank( cur_tree, at_rank_canon1 ))
1777 : : {
1778 : 0 : CurTreeRemoveIfLastAtom( cur_tree, at_to1 );
1779 : 0 : CurTreeRemoveLastRankIfNoAtoms( cur_tree );
1780 : : }
1781 : : }
1782 : : } /* end of stereo atom mapping cycle */
1783 : :
1784 [ - + - - ]: 367 : if (tpos1 < CurTreeGetPos( cur_tree ) &&
1785 : 0 : 1 == CurTreeIsLastRank( cur_tree, at_rank_canon1 ))
1786 : : {
1787 : 0 : CurTreeRemoveLastRank( cur_tree );
1788 : : }
1789 : : else
1790 : : {
1791 : : /* CurTree consistency check (debug only) */
1792 [ - + ]: 367 : if (tpos1 != CurTreeGetPos( cur_tree ))
1793 : : {
1794 : 0 : return CT_STEREOCOUNT_ERR; /* <BRKPT> */
1795 : : }
1796 : : }
1797 : :
1798 [ + - - + ]: 367 : if (!nTotSuccess || stereo_center_parity == sb_parity_calc)
1799 : : {
1800 : 0 : goto repeat_all; /* repeat with next parity if no success or with the same parity, now known */
1801 : : }
1802 : : }
1803 : :
1804 : : else
1805 : : {
1806 : :
1807 : : /****************************************************
1808 : : *
1809 : : * All stereogenic atoms and bonds have been mapped
1810 : : *
1811 : : ****************************************************/
1812 : :
1813 [ - + - - ]: 109 : if ((UserAction && USER_ACTION_QUIT == ( *UserAction )( )) ||
1814 [ - + - - ]: 109 : (ConsoleQuit && ( *ConsoleQuit )( ))) /* djb-rwth: addressing LLVM warning */
1815 : : {
1816 : 0 : return CT_USER_QUIT_ERR;
1817 : : }
1818 : :
1819 [ + + + - ]: 109 : if (pCS->bStereoIsBetter || pCS->bFirstCT)
1820 : 109 : {
1821 : : /* All stereo atoms have been mapped. Current stereo name is better than all previous.
1822 : : * Create new numbering for the new CT
1823 : : * break all remaining "from" ties
1824 : : */
1825 : : int i1, ret;
1826 : : AT_RANK rc, n1, n2;
1827 : :
1828 : 109 : ret = BreakAllTies( pCG, num_at_tg, num_max, pRankStack1,
1829 : : NeighList, nTempRank, pCS );
1830 : :
1831 [ + - - + ]: 109 : if (RETURNED_ERROR( ret ))
1832 : : {
1833 : 0 : return ret;
1834 : : }
1835 : :
1836 : : /* break all remaining "from" ties */
1837 : 109 : ret = BreakAllTies( pCG, num_at_tg, num_max, pRankStack2,
1838 : : NeighList, nTempRank, pCS );
1839 : :
1840 [ + - - + ]: 109 : if (RETURNED_ERROR( ret ))
1841 : : {
1842 : 0 : return ret;
1843 : : }
1844 : : /* move stack pointers to the "nAtomNumber[*]" after all ties are broken */
1845 : 109 : pRankStack1 += 2;
1846 : 109 : pRankStack2 += 2;
1847 : : /* Now final mapping ranks of "to" atom (*pRankStack2)[i] and "from" atom (*pRankStack1)[i]
1848 : : * are equal and all ranks are different, that is, we have a full mapping
1849 : : * Copy so far best canonical numbering from "from" to "to".
1850 : : */
1851 : 109 : memset( pCS->nPrevAtomNumber, 0, num_at_tg * sizeof( pCS->nPrevAtomNumber[0] ) ); /* djb-rwth: memset_s C11/Annex K variant? */
1852 [ + + ]: 1221 : for (i1 = 0; i1 < num_at_tg; i1++)
1853 : : {
1854 : 1112 : n1 = pRankStack1[1][i1];
1855 : 1112 : rc = nCanonRankFrom[n1]; /* new canon. rank */
1856 : 1112 : n2 = pRankStack2[1][i1]; /* orig. atom number */
1857 : 1112 : nCanonRankTo[n2] = rc; /* assign new canon. number to the atom */
1858 : : /* use this array to find stereo-equivalent atoms */
1859 : 1112 : pCS->nPrevAtomNumber[rc - 1] = n2; /* ord. number of the atom having canon. rank = rc */
1860 : 1112 : nSymmStereo[i1] = i1; /* restart search for stereo equivalent atoms */
1861 : : /* check mapping correctness */
1862 [ + - ]: 1112 : if (pRankStack1[0][n1] != pRankStack2[0][n2] ||
1863 [ - + ]: 1112 : nSymmRank[n1] != nSymmRank[n2])
1864 : : {
1865 : 0 : return CT_STEREO_CANON_ERR; /* stereo mapping error */
1866 : : }
1867 : : }
1868 : : /* statistics */
1869 : 109 : pCS->lNumTotCT++;
1870 : 109 : pCS->lNumEqualCT = 1;
1871 : 109 : pCS->lNumDecreasedCT++;
1872 : 109 : pCS->bStereoIsBetter = 0; /* prepare to start over */
1873 : 109 : nTotSuccess = 1;
1874 : 109 : pCS->bFirstCT = 0;
1875 : :
1876 : : #if ( REMOVE_CALC_NONSTEREO == 1 ) /* { */
1877 [ + - ]: 109 : if (!( pCS->nMode & CMODE_REDNDNT_STEREO ))
1878 : : {
1879 : 109 : i1 = RemoveCalculatedNonStereo( pCG, at, num_atoms, num_at_tg,
1880 : : pRankStack1, pRankStack2, nTempRank, NeighList,
1881 : : nSymmRank, nCanonRankTo, pCS->nPrevAtomNumber, pCS,
1882 : : vABParityUnknown );
1883 [ + - - + ]: 109 : if (RETURNED_ERROR( i1 ))
1884 : : {
1885 : 0 : return i1;
1886 : : }
1887 [ - + ]: 109 : if (i1 < 0)
1888 : : {
1889 : : #if ( bRELEASE_VERSION == 0 )
1890 : : pCS->bExtract |= EXTR_REMOVE_PARITY_WARNING;
1891 : : #endif
1892 : 0 : i1 = -( 1 + i1 );
1893 : : }
1894 [ - + ]: 109 : if (i1 > 0)
1895 : : {
1896 : 0 : return 4; /* total restart: due to newly found stereo equivalence */
1897 : : /* the length of the stereo CT has changed */
1898 : : }
1899 : : }
1900 : : #endif /* } REMOVE_CALC_NONSTEREO */
1901 : :
1902 : : /* djb-rwth: removing redundant code */
1903 : : }
1904 : : else
1905 : : {
1906 : : /* current stereo name is same as previous. We do not need a full mapping. */
1907 [ # # ]: 0 : if (nSymmStereo)
1908 : : {
1909 : 0 : int num_changes = 0;
1910 : : AT_RANK r, n1, n2, r_max, cr;
1911 : 0 : r_max = (AT_RANK) num_at_tg;
1912 [ # # ]: 0 : for (r = 1; r <= r_max; r++)
1913 : : {
1914 [ # # ]: 0 : if (bUniqueAtNbrFromMappingRank( pRankStack1, r, &n1 ))
1915 : : {
1916 [ # # ]: 0 : if (bUniqueAtNbrFromMappingRank( pRankStack2, r, &n2 ))
1917 : : {
1918 : : /* atoms at[n1], at[n2] have identical untied mapping rank r */
1919 : 0 : cr = nCanonRankFrom[(int) n1] - 1; /* (new at[n2] canonical rank)-1 */
1920 : : /* pCS->nPrevAtomNumber[(int)cr] = */
1921 : : /* previous ordering number of an atom with the canon. rank = cr+1; */
1922 : : /* make this atom equivalent to atom at[n2]: */
1923 : 0 : num_changes += nJoin2Mcrs( nSymmStereo, pCS->nPrevAtomNumber[(int) cr], n2 );
1924 : : }
1925 : : else
1926 : : {
1927 : 0 : return CT_MAPCOUNT_ERR; /* mapping ranks must be either both tied or untied. */ /* <BRKPT> */
1928 : : }
1929 : : }
1930 : : }
1931 [ # # ]: 0 : if (num_changes)
1932 : : { /* compress trees to stars */
1933 [ # # ]: 0 : for (r = r_max - 1; r; r--)
1934 : : {
1935 : 0 : nGetMcr( nSymmStereo, r );
1936 : : }
1937 : : }
1938 : : }
1939 : : /* statistics */
1940 : 0 : pCS->lNumEqualCT++;
1941 : 0 : pCS->lNumTotCT++;
1942 : 0 : nTotSuccess = 1;
1943 : : }
1944 [ - + ]: 109 : if (bInchiTimeIsOver( ic, pCS->ulTimeOutTime ))
1945 : : {
1946 : 0 : return CT_TIMEOUT_ERR;
1947 : : }
1948 : : }
1949 [ - + - - ]: 476 : if (!nTotSuccess && nNumMappedAtoms < pCS->nLenLinearCTStereoCarb)
1950 : : {
1951 : 0 : pCS->LinearCTStereoCarb[nNumMappedAtoms] = prevAtom;
1952 : 0 : CurTreeSetPos( cur_tree, tpos1 );
1953 : : }
1954 : :
1955 : 476 : return nTotSuccess; /* return to the previous level of the recursion. */
1956 : : }
|