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