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 "ichimain.h"
45 : : #include "ichimake.h"
46 : : #include "ichi_io.h"
47 : :
48 : : #include "bcf_s.h"
49 : :
50 : : /*
51 : :
52 : : Generate substrings of whole-structure InChI/AuxInfo
53 : :
54 : : */
55 : :
56 : :
57 : : /****************************************************************************
58 : : Produce Hill formula substring of the whole structure InChI string
59 : : ****************************************************************************/
60 : 54 : int str_HillFormula( INCHI_SORT *pINChISort,
61 : : INCHI_IOS_STRING *strbuf,
62 : : int *bOverflow,
63 : : int bOutType,
64 : : int num_components,
65 : : int bUseMulipliers )
66 : : {
67 : : int i, ii, nUsedLength0;
68 : : INCHI_SORT *is, *is0;
69 : : INChI *pINChI, *pINChI_Prev;
70 : : int mult, eq2prev, bNext;
71 : :
72 : 54 : nUsedLength0 = strbuf->nUsedLength;
73 : :
74 [ - + ]: 54 : if (!( is0 = pINChISort ))
75 : : {
76 : 0 : return nUsedLength0;
77 : : }
78 : 54 : i = 0;
79 [ - + - - : 54 : pINChI_Prev = ( 0 <= ( ii = GET_II( bOutType, is0 ) ) ) ? is0->pINChI[ii] : NULL;
- - - - -
- - - - -
+ - + - +
- - + - -
- - - - -
- - - - -
- - - - -
- - - - -
- - - - -
- - - - -
+ - ]
80 : 54 : mult = 0;
81 : 54 : bNext = 0;
82 : :
83 : : /* For each connected component */
84 [ + + ]: 123 : for (i++; i <= num_components; i++)
85 : : {
86 : :
87 : 84 : pINChI = ( i < num_components &&
88 [ - + - - : 15 : ( is = is0 + i, 0 <= ( ii = GET_II( bOutType, is ) ) ) )
- - - - -
- - - - -
+ - + - +
- - + - -
- - - - -
- - - - -
- - - - -
- - - - -
- - - - -
- - - - -
+ - ]
89 : : ? is->pINChI[ii]
90 [ + + ]: 84 : : NULL;
91 : :
92 [ + + ]: 69 : eq2prev = bUseMulipliers &&
93 [ + - ]: 15 : pINChI &&
94 : 15 : pINChI_Prev &&
95 [ + - ]: 15 : pINChI->szHillFormula &&
96 [ + - ]: 15 : pINChI_Prev->szHillFormula &&
97 [ + - + - ]: 153 : pINChI->szHillFormula[0] &&
98 [ + + ]: 15 : !strcmp( pINChI_Prev->szHillFormula, pINChI->szHillFormula );
99 : :
100 [ + + ]: 69 : if (eq2prev)
101 : : {
102 : 8 : mult++; /* mult = (number of non-empty equal items)-1 */
103 : 8 : continue;
104 : : }
105 : : else
106 : : {
107 : : int ok;
108 [ + + ]: 61 : if (bNext++)
109 : : {
110 : 7 : MakeDelim( ".", strbuf, bOverflow );
111 : : }
112 : :
113 : 122 : ok = pINChI_Prev &&
114 [ + - + - ]: 122 : pINChI_Prev->szHillFormula &&
115 [ + - ]: 61 : pINChI_Prev->szHillFormula[0];
116 : :
117 [ + - ]: 61 : if (ok)
118 : : {
119 : 61 : MakeMult( mult + 1, "", strbuf, 0, bOverflow );
120 : 61 : MakeHillFormulaString( pINChI_Prev->szHillFormula,
121 : : strbuf,
122 : : bOverflow );
123 : : }
124 : : }
125 : 61 : pINChI_Prev = pINChI;
126 : 61 : mult = 0; /* we do not know whether the item is empty */
127 : : }
128 : :
129 : 54 : return ( strbuf->nUsedLength - nUsedLength0 );
130 : : }
131 : :
132 : :
133 : : /****************************************************************************
134 : : Produce Hill formula substring of the whole structure InChI string:
135 : : 2nd appearance (FixedH).
136 : : ****************************************************************************/
137 : 0 : int str_HillFormula2( INCHI_SORT *pINChISort, /* non-taut */
138 : : INCHI_SORT *pINChISort2, /* taut */
139 : : INCHI_IOS_STRING *strbuf,
140 : : int *bOverflow,
141 : : int bOutType,
142 : : int num_components,
143 : : int bUseMulipliers )
144 : : {
145 : : int i, ii, ii2, nUsedLength0;
146 : : INCHI_SORT *is, *is2, *is0, *is20;
147 : : INChI *pINChI, *pINChI_Prev, *pINChI_Taut, *pINChI_Taut_Prev;
148 : : int mult, eq2prev, bNext, bEqToTaut;
149 : :
150 : 0 : is = NULL;
151 : 0 : is2 = NULL;
152 : 0 : is0 = pINChISort;
153 : 0 : is20 = pINChISort2;
154 : 0 : i = 0;
155 : 0 : nUsedLength0 = strbuf->nUsedLength;
156 : :
157 [ # # # # : 0 : pINChI_Prev = ( 0 <= ( ii = GET_II( bOutType, is0 ) ) ) ? is0->pINChI[ii] : NULL;
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # ]
158 [ # # # # : 0 : pINChI_Taut_Prev = ( 0 <= ( ii2 = GET_II( OUT_T1, is20 ) ) ) ? is20->pINChI[ii2] : NULL;
# # # # #
# ]
159 : 0 : mult = 0;
160 : 0 : bNext = 0;
161 : 0 : bEqToTaut = 1;
162 [ # # ]: 0 : bEqToTaut = bEqToTaut &&
163 [ # # ]: 0 : pINChI_Prev &&
164 : 0 : pINChI_Taut_Prev &&
165 [ # # ]: 0 : !pINChI_Taut_Prev->bDeleted &&
166 [ # # ]: 0 : pINChI_Prev->szHillFormula &&
167 [ # # # # ]: 0 : pINChI_Taut_Prev->szHillFormula &&
168 [ # # ]: 0 : !strcmp( pINChI_Prev->szHillFormula, pINChI_Taut_Prev->szHillFormula );
169 : :
170 : : /* For each connected component */
171 [ # # ]: 0 : for (i++; i <= num_components; i++)
172 : : {
173 [ # # # # : 0 : pINChI = ( i < num_components && ( is = is0 + i, 0 <= ( ii = GET_II( bOutType, is ) ) ) ) ? is->pINChI[ii] : NULL;
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # ]
174 [ # # # # : 0 : pINChI_Taut = ( i < num_components && ( is2 = is20 + i, 0 <= ( ii2 = GET_II( OUT_T1, is2 ) ) ) ) ? is2->pINChI[ii2] : NULL;
# # # # #
# # # ]
175 [ # # # # : 0 : if (bEqToTaut && ( pINChI || pINChI_Taut ))
# # ]
176 : : {
177 [ # # # # ]: 0 : bEqToTaut = pINChI && pINChI_Taut && !pINChI_Taut->bDeleted &&
178 [ # # # # : 0 : pINChI->szHillFormula && pINChI_Taut->szHillFormula &&
# # ]
179 [ # # ]: 0 : !strcmp( pINChI->szHillFormula, pINChI_Taut->szHillFormula );
180 : : }
181 : :
182 [ # # ]: 0 : eq2prev = bUseMulipliers &&
183 [ # # ]: 0 : pINChI && pINChI_Prev &&
184 [ # # ]: 0 : pINChI->szHillFormula &&
185 [ # # ]: 0 : pINChI_Prev->szHillFormula &&
186 [ # # # # ]: 0 : pINChI->szHillFormula[0] &&
187 [ # # ]: 0 : !strcmp( pINChI_Prev->szHillFormula, pINChI->szHillFormula );
188 : :
189 [ # # ]: 0 : if (eq2prev)
190 : : {
191 : 0 : mult++; /* mult = (number of non-empty equal items)-1 */
192 : 0 : continue;
193 : : }
194 : : else
195 : : {
196 [ # # ]: 0 : if (bNext++)
197 : : {
198 : 0 : MakeDelim( ".", strbuf, bOverflow );
199 : : }
200 [ # # # # : 0 : if (pINChI_Prev && pINChI_Prev->szHillFormula && pINChI_Prev->szHillFormula[0])
# # ]
201 : : {
202 : 0 : MakeMult( mult + 1, "", strbuf, 0, bOverflow );
203 : 0 : MakeHillFormulaString( pINChI_Prev->szHillFormula, strbuf, bOverflow );
204 : : }
205 : : }
206 : 0 : pINChI_Prev = pINChI;
207 : 0 : mult = 0; /* we do not know whether the item is empty */
208 : : }
209 : :
210 [ # # ]: 0 : if (bEqToTaut)
211 : 0 : strbuf->nUsedLength = nUsedLength0;
212 : :
213 : : {
214 : 0 : strbuf->pStr[strbuf->nUsedLength] = '\0';
215 : : }
216 : :
217 : 0 : return ( strbuf->nUsedLength - nUsedLength0 );
218 : : }
219 : :
220 : :
221 : : /****************************************************************************
222 : : Produce connections substring of InChI string for the whole structure
223 : : ****************************************************************************/
224 : 54 : int str_Connections( CANON_GLOBALS *pCG,
225 : : INCHI_SORT *pINChISort,
226 : : INCHI_IOS_STRING *strbuf,
227 : : int *bOverflow,
228 : : int bOutType,
229 : : int ATOM_MODE,
230 : : int num_components,
231 : : int bUseMulipliers )
232 : : {
233 : : int i, ii, nUsedLength0;
234 : : INCHI_SORT *is, *is0;
235 : : INChI *pINChI, *pINChI_Prev;
236 : : int mult, eq2prev, bNext, nNumEmpty;
237 : :
238 : 54 : nUsedLength0 = strbuf->nUsedLength;
239 [ - + ]: 54 : if (!( is0 = pINChISort ))
240 : : {
241 : 0 : return nUsedLength0;
242 : : }
243 : 54 : i = 0;
244 [ - + - - : 54 : pINChI_Prev = ( 0 <= ( ii = GET_II( bOutType, is0 ) ) ) ? is0->pINChI[ii] : NULL;
- - - - -
- - - - -
+ - + - +
- - + - -
- - - - -
- - - - -
- - - - -
- - - - -
- - - - -
- - - - -
+ - ]
245 : 54 : is = NULL;
246 : 54 : mult = 0;
247 : 54 : bNext = 0;
248 : 54 : nNumEmpty = 0;
249 : :
250 : : /* For each connected component... */
251 [ + + ]: 123 : for (i++; i <= num_components; i++)
252 : : {
253 [ + + - + : 69 : pINChI = ( i < num_components && ( is = is0 + i, 0 <= ( ii = GET_II( bOutType, is ) ) ) ) ? is->pINChI[ii] : NULL;
- - - - -
- - - - -
- - + - +
- + - - +
- - - - -
- - - - -
- - - - -
- - - - -
- - - - -
- - - - -
- - + - ]
254 [ + + ]: 69 : eq2prev = bUseMulipliers &&
255 [ + - + + ]: 15 : pINChI && pINChI_Prev && pINChI->lenConnTable > 1 &&
256 [ + - + + ]: 144 : pINChI_Prev->lenConnTable == pINChI->lenConnTable &&
257 : 6 : !memcmp( pINChI_Prev->nConnTable, pINChI->nConnTable,
258 [ + - ]: 6 : pINChI_Prev->lenConnTable * sizeof( pINChI->nConnTable[0] ) );
259 [ + + ]: 69 : if (eq2prev)
260 : : {
261 : 6 : mult++; /* mult = (number of non-empty equal items)-1 */
262 : 6 : continue;
263 : : }
264 : : else
265 : : {
266 [ + - ]: 63 : if (pINChI_Prev)
267 : : {
268 [ + + ]: 63 : if (bNext++)
269 : : {
270 : 9 : MakeDelim( sCompDelim, strbuf, bOverflow );
271 : : }
272 [ + - + + ]: 63 : if (pINChI_Prev && pINChI_Prev->lenConnTable > 1)
273 : : {
274 : 58 : MakeMult( mult + 1, "*", strbuf, 0, bOverflow );
275 : 58 : MakeCtStringNew( pCG, pINChI_Prev->nConnTable,
276 : : pINChI_Prev->lenConnTable,
277 : : 0, NULL,
278 : : pINChI_Prev->nNumberOfAtoms,
279 : : strbuf, ATOM_MODE, bOverflow );
280 : : }
281 : : else
282 : : {
283 : 5 : nNumEmpty++;
284 : : }
285 : : }
286 : : }
287 : 63 : pINChI_Prev = pINChI;
288 : 63 : mult = 0; /* we do not know whether the item is empty */
289 : : }
290 [ + + + - ]: 54 : if (nNumEmpty == num_components && strbuf->nUsedLength > nUsedLength0)
291 : : {
292 : 1 : strbuf->nUsedLength = nUsedLength0;
293 : 1 : strbuf->pStr[strbuf->nUsedLength] = '\0';
294 : : }
295 : : /*
296 : : if ( nNumEmpty == num_components && tot_len > tot_len_inp ) {
297 : : tot_len = tot_len_inp;
298 : : strbuf->pStr[tot_len] = '\0';
299 : : }
300 : : */
301 : :
302 : 54 : return ( strbuf->nUsedLength - nUsedLength0 );
303 : : }
304 : :
305 : :
306 : : /****************************************************************************
307 : : Produce H[ydrogens] substring of the whole structure InChI string
308 : : ****************************************************************************/
309 : 51 : int str_H_atoms( INCHI_SORT *pINChISort,
310 : : INCHI_IOS_STRING *strbuf,
311 : : int *bOverflow,
312 : : int bOutType,
313 : : int ATOM_MODE,
314 : : int TAUT_MODE,
315 : : int num_components,
316 : : int bUseMulipliers )
317 : : {
318 : : int i, j, ii, len_H, nUsedLength0;
319 : : INCHI_SORT *is, *is0;
320 : : INChI *pINChI, *pINChI_Prev;
321 : : int mult, eq2prev, bNext, bNotEmpty, nNumEmpty;
322 : :
323 : 51 : nNumEmpty = 0;
324 : 51 : is0 = pINChISort;
325 : 51 : is = NULL;
326 : 51 : i = 0;
327 [ - + - - : 51 : pINChI_Prev = ( 0 <= ( ii = GET_II( bOutType, is0 ) ) ) ? is0->pINChI[ii] : NULL;
- - - - -
- - - - -
+ - + - +
- - + - -
- - - - -
- - - - -
- - - - -
- - - - -
- - - - -
- - - - -
+ - ]
328 : 51 : mult = 0;
329 : 51 : bNext = 0;
330 : 51 : nUsedLength0 = strbuf->nUsedLength;
331 : :
332 : : /* For each connected component... */
333 [ + + ]: 117 : for (i++; i <= num_components; i++)
334 : : {
335 : :
336 [ + + - + : 66 : pINChI = ( i < num_components && ( is = is0 + i, 0 <= ( ii = GET_II( bOutType, is ) ) ) ) ? is->pINChI[ii] : NULL;
- - - - -
- - - - -
- - + - +
- + - - +
- - - - -
- - - - -
- - - - -
- - - - -
- - - - -
- - - - -
- - + - ]
337 : : /*========== compare to previous ============*/
338 [ + + ]: 66 : eq2prev = bUseMulipliers &&
339 [ + - - + : 15 : pINChI && pINChI_Prev && ( pINChI->nNumberOfAtoms > 0 || pINChI->lenTautomer > 1 ) &&
- - ]
340 [ + + ]: 15 : pINChI_Prev->nNumberOfAtoms == pINChI->nNumberOfAtoms &&
341 [ + - ]: 9 : ( !pINChI_Prev->nNumberOfAtoms || !memcmp( pINChI_Prev->nNum_H, pINChI->nNum_H,
342 [ + - + + : 140 : pINChI_Prev->nNumberOfAtoms * sizeof( pINChI->nNum_H[0] ) ) ) &&
+ - ]
343 : 8 : !CompareTautNonIsoPartOfINChI( pINChI_Prev, pINChI );
344 : :
345 [ + + + - ]: 66 : if (eq2prev && pINChI_Prev->lenTautomer <= 1)
346 : : {
347 : : /* make sure it is not empty */
348 : 8 : eq2prev = 0;
349 [ + - ]: 8 : for (j = 0; j < pINChI_Prev->nNumberOfAtoms; j++)
350 : : {
351 [ + - ]: 8 : if (pINChI_Prev->nNum_H[j])
352 : : {
353 : 8 : eq2prev = 1;
354 : 8 : break;
355 : : }
356 : : }
357 : : }
358 [ + + ]: 66 : if (eq2prev)
359 : : {
360 : 8 : mult++; /* mult = (number of non-empty equal items)-1 */
361 : 8 : continue;
362 : : }
363 : : else
364 : : {
365 [ + - ]: 58 : if (pINChI_Prev)
366 : : {
367 : : /* delimiter */
368 [ + + ]: 58 : if (bNext++)
369 : : {
370 : 7 : MakeDelim( sCompDelim, strbuf, bOverflow );
371 : : }
372 : : /* verify non-empty */
373 : 58 : bNotEmpty = 0;
374 [ + - ]: 58 : if (pINChI_Prev)
375 : : {
376 : 58 : bNotEmpty = ( pINChI_Prev->lenTautomer > 1 );
377 [ + - ]: 58 : if (!bNotEmpty)
378 : : {
379 [ + + ]: 60 : for (j = 0; j < pINChI_Prev->nNumberOfAtoms; j++)
380 : : {
381 [ + + ]: 58 : if (pINChI_Prev->nNum_H[j])
382 : : {
383 : 56 : bNotEmpty = 1;
384 : 56 : break;
385 : : }
386 : : }
387 : : }
388 : : }
389 [ + + ]: 58 : if (bNotEmpty)
390 : : {
391 : 56 : MakeMult( mult + 1, "*", strbuf, 0, bOverflow );
392 : : /* H-atoms */
393 : 56 : len_H = MakeHString( 0, pINChI_Prev->nNum_H, pINChI_Prev->nNumberOfAtoms,
394 : : strbuf, ATOM_MODE, bOverflow );
395 : : /* tautomeric groups */
396 : 56 : MakeTautString( pINChI_Prev->nTautomer, pINChI_Prev->lenTautomer, ( 0 != len_H ),
397 : : strbuf, TAUT_MODE, bOverflow );
398 : : }
399 : : else
400 : : {
401 : 2 : nNumEmpty++;
402 : : }
403 : : }
404 : : }
405 : 58 : pINChI_Prev = pINChI;
406 : 58 : mult = 0; /* we do not know whether the item is empty */
407 : : }
408 [ - + - - ]: 51 : if (nNumEmpty == num_components && strbuf->nUsedLength > nUsedLength0)
409 : : {
410 : 0 : strbuf->nUsedLength = nUsedLength0;
411 : 0 : strbuf->pStr[nUsedLength0] = '\0';
412 : : }
413 : : /*
414 : : if ( nNumEmpty == num_components && tot_len > tot_len_inp ) {
415 : : tot_len = tot_len_inp;
416 : : strbuf->pStr[tot_len] = '\0';
417 : : }
418 : : */
419 : :
420 : 51 : return ( strbuf->nUsedLength - nUsedLength0 );
421 : : }
422 : :
423 : :
424 : : /****************************************************************************
425 : : Produce charge substring of the whole structure InChI string
426 : : ****************************************************************************/
427 : 3 : int str_Charge2( INCHI_SORT *pINChISort,
428 : : INCHI_SORT *pINChISort2,
429 : : INCHI_IOS_STRING *strbuf,
430 : : int *bOverflow,
431 : : int bOutType,
432 : : int num_components,
433 : : int bSecondNonTautPass,
434 : : int bOmitRepetitions,
435 : : int bUseMulipliers )
436 : : {
437 : : int i, ii, ii2, nUsedLength0;
438 : : INCHI_SORT *is, *is2, *is0, *is20;
439 : : INChI *pINChI, *pINChI_Prev, *pINChI_Taut, *pINChI_Taut_Prev;
440 : : int nTotalCharge, nTotalCharge_Prev, nTotalCharge_Taut; /* djb-rwth: removing redundant variables */
441 : : int mult, eq2prev, eq2taut, eq2tautPrev, bNext;
442 : : const char *pPrevEquStr, *pCurrEquStr;
443 : : int multPrevEquStr;
444 : 3 : pINChI_Taut = NULL;
445 : 3 : pINChI_Prev = NULL;
446 : 3 : pINChI_Taut_Prev = NULL;
447 : 3 : mult = 0;
448 : 3 : bNext = 0;
449 : 3 : is = NULL;
450 : 3 : is2 = NULL;
451 : 3 : is0 = pINChISort;
452 [ - + ]: 3 : is20 = bSecondNonTautPass ? pINChISort2 : NULL;
453 : : /* djb-rwth: removing redundant code */
454 : 3 : eq2tautPrev = 1; /* pINChI_Prev (previous pINChI) does not exist */
455 : 3 : pPrevEquStr = NULL; /*, *pCurrEquStr;*/
456 : 3 : multPrevEquStr = 0;
457 : 3 : nUsedLength0 = strbuf->nUsedLength;
458 : :
459 : : /* For each connected component... */
460 [ + + ]: 14 : for (i = 0; i <= num_components; i++)
461 : : {
462 : :
463 : : /* 1st (taut) pass: bOutType=OUT_TN ; 2nd (non-taut pass) bOutType=OUT_NT */
464 [ + + - + : 11 : pINChI = ( i < num_components && ( is = is0 + i, 0 <= ( ii = GET_II( bOutType, is ) ) ) ) ? is->pINChI[ii] : NULL;
- - - - -
- - - - -
- - + - +
- + - - +
- - - - -
- - - - -
- - - - -
- - - - -
- - - - -
- - - - -
- - + - ]
465 : : /*================ compare sp3 to previous =====================*/
466 [ - + ]: 11 : if (bSecondNonTautPass)
467 : : {
468 : : /* component that was output on the 1st pass */
469 [ # # # # : 0 : pINChI_Taut = ( i < num_components && ( is2 = is20 + i, 0 <= ( ii2 = GET_II( OUT_T1, is2 ) ) ) ) ? is2->pINChI[ii2] : NULL;
# # # # #
# # # ]
470 : : }
471 : : /*========= if bSecondNonTautPass then compare non-iso non-taut stereo to non-iso taut ========*/
472 : 11 : eq2taut = 0;
473 [ + - - + : 11 : if (!eq2taut && bSecondNonTautPass && bOmitRepetitions)
- - ]
474 : : {
475 [ # # # # ]: 0 : eq2taut = pINChI && pINChI_Taut && !pINChI_Taut->bDeleted &&
476 [ # # # # : 0 : ( nTotalCharge = pINChI->nTotalCharge ) && ( nTotalCharge_Taut = pINChI_Taut->nTotalCharge ) &&
# # # # ]
477 : : nTotalCharge == nTotalCharge_Taut;
478 [ # # ]: 0 : eq2taut = eq2taut ? ( iiEQU | iitNONTAUT ) : 0;
479 : : }
480 [ - + ]: 11 : if (eq2taut)
481 : : {
482 : : /* we may be here only in case of the second (non-taut) pass */
483 : : /* current non-taut stereo has been found to be same as tautomeric */
484 [ # # # # ]: 0 : if (pINChI_Prev && pINChI_Prev->nNumberOfAtoms)
485 : : {
486 : : /* previous component exists; output it */
487 [ # # ]: 0 : if (bNext++)
488 : : {
489 : 0 : MakeDelim( sCompDelim, strbuf, bOverflow );
490 : : }
491 [ # # ]: 0 : if ((nTotalCharge_Prev = pINChI_Prev->nTotalCharge)) /* djb-rwth: addressing LLVM warning */
492 : : {
493 : 0 : MakeMult( mult + 1, "*", strbuf, 0, bOverflow );
494 : 0 : inchi_strbuf_printf( strbuf, "%+d", nTotalCharge_Prev );
495 : : }
496 : : }
497 : : else
498 : : {
499 [ # # # # : 0 : if (pINChI_Taut_Prev && pINChI_Taut_Prev->nNumberOfAtoms && !pINChI_Taut_Prev->bDeleted)
# # ]
500 : : {
501 : : /* previous non-taut component exists only in taut list */
502 [ # # ]: 0 : if (bNext++)
503 : : {
504 : 0 : MakeDelim( sCompDelim, strbuf, bOverflow );
505 : : }
506 : : }
507 : : }
508 : : /* we have found pINChI->nTotalCharge same as in pINChI_Taut */
509 : : /* output this (current) equivalence as '*', that is, same as tautomeric */
510 : : /* that was printed on the 1st pass. */
511 : :
512 : 0 : pCurrEquStr = EquString( eq2taut );
513 [ # # # # ]: 0 : if (multPrevEquStr && pPrevEquStr)
514 : : {
515 [ # # # # ]: 0 : if (pCurrEquStr && !strcmp( pCurrEquStr, pPrevEquStr ))
516 : : {
517 : 0 : multPrevEquStr++;
518 : : }
519 : : else
520 : : {
521 : : /* new EqStr is different; output it */
522 [ # # ]: 0 : if (bNext++)
523 : : {
524 : 0 : MakeDelim( sCompDelim, strbuf, bOverflow );
525 : : }
526 : 0 : MakeEqStr( pPrevEquStr, multPrevEquStr, strbuf, bOverflow );
527 : 0 : pPrevEquStr = pCurrEquStr;
528 : 0 : multPrevEquStr = 1;
529 : : }
530 : : }
531 : : else
532 : : {
533 : 0 : pPrevEquStr = pCurrEquStr;
534 : 0 : multPrevEquStr = 1;
535 : : }
536 : :
537 : 0 : pINChI_Prev = NULL; /* pINChI_Prev sp2 does not exist since */
538 : 0 : pINChI_Taut_Prev = NULL; /* pINChI has just been printed */
539 : 0 : mult = 0;
540 : 0 : eq2tautPrev = 1; /* pINChI_Prev sp2 does not exist */
541 : : }
542 : : else
543 : : {
544 [ + + ]: 11 : if (eq2tautPrev)
545 : : {
546 : : /* at this point pINChI_Prev does not exist; however, pINChI */
547 : : /*might have been discovered and it is different from pINChI_Taut */
548 [ - + - - ]: 3 : if (multPrevEquStr && pPrevEquStr)
549 : : {
550 : : /* new EqStr is different; output it */
551 [ # # ]: 0 : if (bNext++)
552 : : {
553 : 0 : MakeDelim( sCompDelim, strbuf, bOverflow );
554 : : }
555 : 0 : MakeEqStr( pPrevEquStr, multPrevEquStr, strbuf, bOverflow );
556 : 0 : pPrevEquStr = NULL;
557 : 0 : multPrevEquStr = 0;
558 : : }
559 : 3 : eq2tautPrev = 0;
560 : 3 : pINChI_Prev = pINChI;
561 : 3 : pINChI_Taut_Prev = pINChI_Taut;
562 : 3 : mult = 0;
563 : : }
564 : : else
565 : : {
566 : : /* check whether pINChI and pINChI_Prev have non-zero identical stereo sp3 */
567 : : /*================ compare sp3 to previous =====================*/
568 [ + + ]: 8 : eq2prev = bUseMulipliers &&
569 [ + - ]: 5 : pINChI && pINChI_Prev &&
570 [ + - + + : 16 : ( nTotalCharge = pINChI->nTotalCharge ) && ( nTotalCharge_Prev = pINChI_Prev->nTotalCharge ) &&
+ + + - ]
571 : : nTotalCharge == nTotalCharge_Prev;
572 [ + + ]: 8 : if (eq2prev)
573 : : {
574 : 1 : mult++; /* mult = (number of non-empty equal items)-1 */
575 : 1 : continue;
576 : : }
577 : : else
578 : : {
579 [ + + ]: 7 : if (bNext++)
580 : : {
581 : 4 : MakeDelim( sCompDelim, strbuf, bOverflow );
582 : : }
583 [ + - + - ]: 7 : if (pINChI_Prev && pINChI_Prev->nNumberOfAtoms)
584 : : {
585 [ + + ]: 7 : if ((nTotalCharge_Prev = pINChI_Prev->nTotalCharge)) /* djb-rwth: addressing LLVM warning */
586 : : {
587 : : /* pINChI_Prev exists and has charge info */
588 : 3 : MakeMult( mult + 1, "*", strbuf, 0, bOverflow );
589 : 3 : inchi_strbuf_printf( strbuf, "%+d", nTotalCharge_Prev );
590 : : }
591 : : /* else charge is not present in pINChI_Prev */
592 : : }
593 : : else
594 : : {
595 : : /* djb-rwth: removing redundant code */
596 : : #if ( bRELEASE_VERSION != 1 && defined(_DEBUG) )
597 : : if (!(bSecondNonTautPass && pINChI_Taut_Prev && pINChI_Taut_Prev->nNumberOfAtoms && !pINChI_Taut_Prev->bDeleted))
598 : : {
599 : : int stop = 1; /* <BRKPT> */
600 : : }
601 : : #endif
602 : : }
603 : : }
604 : 7 : pINChI_Prev = pINChI;
605 : 7 : pINChI_Taut_Prev = pINChI_Taut;
606 : 7 : mult = 0; /* we do not know whether the item is empty */
607 : : }
608 : : }
609 : : }
610 : :
611 : 3 : return ( strbuf->nUsedLength - nUsedLength0 );
612 : : }
613 : :
614 : :
615 : : /****************************************************************************
616 : : Produce FixedH substring of the whole structure InChI string
617 : : ****************************************************************************/
618 : 0 : int str_FixedH_atoms( INCHI_SORT *pINChISort,
619 : : INCHI_IOS_STRING *strbuf,
620 : : int *bOverflow,
621 : : int bOutType,
622 : : int ATOM_MODE,
623 : : int num_components,
624 : : int bUseMulipliers )
625 : : {
626 : : int i, j, ii, nNumEmpty, nUsedLength0;
627 : : INCHI_SORT *is, *is0;
628 : : INChI *pINChI, *pINChI_Prev;
629 : : int mult, eq2prev, bNext, bNotEmpty;
630 : :
631 : 0 : is = NULL;
632 : 0 : is0 = pINChISort;
633 : 0 : i = 0;
634 [ # # # # : 0 : pINChI_Prev = ( 0 <= ( ii = GET_II( bOutType, is0 ) ) ) ? is0->pINChI[ii] : NULL;
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # ]
635 : 0 : mult = 0;
636 : 0 : bNext = 0;
637 : 0 : nNumEmpty = 0;
638 : 0 : nUsedLength0 = strbuf->nUsedLength;
639 : :
640 : : /* For each connected component... */
641 [ # # ]: 0 : for (i++; i <= num_components; i++)
642 : : {
643 : : /* only non-tautomeric representation of tautomeric */
644 [ # # # # : 0 : pINChI = ( i < num_components && ( is = is0 + i, 0 <= ( ii = GET_II( bOutType, is ) ) ) ) ? is->pINChI[ii] : NULL;
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # ]
645 : : /*================ compare fixed H to previous =====================*/
646 [ # # ]: 0 : eq2prev = bUseMulipliers &&
647 [ # # # # ]: 0 : pINChI && pINChI_Prev && pINChI->nNumberOfAtoms > 0 &&
648 [ # # # # ]: 0 : pINChI_Prev->nNumberOfAtoms == pINChI->nNumberOfAtoms &&
649 : 0 : !memcmp( pINChI_Prev->nNum_H_fixed, pINChI->nNum_H_fixed,
650 [ # # ]: 0 : pINChI_Prev->nNumberOfAtoms * sizeof( pINChI->nNum_H_fixed[0] ) );
651 [ # # ]: 0 : if (eq2prev)
652 : : {
653 : : /* make sure it is not empty */
654 : 0 : eq2prev = 0;
655 [ # # ]: 0 : for (j = 0; j < pINChI_Prev->nNumberOfAtoms; j++)
656 : : {
657 [ # # ]: 0 : if (pINChI_Prev->nNum_H_fixed[j])
658 : : {
659 : 0 : eq2prev = 1;
660 : 0 : break;
661 : : }
662 : : }
663 : : }
664 [ # # ]: 0 : if (eq2prev)
665 : : {
666 : 0 : mult++; /* mult = (number of non-empty equal items)-1 */
667 : 0 : continue;
668 : : }
669 : : else
670 : : {
671 : : /* print pINChI_Prev */
672 : : /* delimiter */
673 [ # # ]: 0 : if (bNext++)
674 : : {
675 : 0 : MakeDelim( sCompDelim, strbuf, bOverflow );
676 : : }
677 [ # # ]: 0 : if (pINChI_Prev)
678 : : {
679 : : /* verify it is not empty */
680 : 0 : bNotEmpty = 0;
681 [ # # ]: 0 : for (j = 0; j < pINChI_Prev->nNumberOfAtoms; j++)
682 : : {
683 [ # # ]: 0 : if (pINChI_Prev->nNum_H_fixed[j])
684 : : {
685 : 0 : bNotEmpty = 1;
686 : 0 : break;
687 : : }
688 : : }
689 [ # # ]: 0 : if (bNotEmpty)
690 : : {
691 : 0 : MakeMult( mult + 1, "*", strbuf, 0, bOverflow );
692 : : /* H-atoms-fixed */
693 : 0 : MakeHString( 0, pINChI_Prev->nNum_H_fixed,
694 : : pINChI_Prev->nNumberOfAtoms,
695 : : strbuf, ATOM_MODE, bOverflow );
696 : : }
697 : : else
698 : : {
699 : 0 : nNumEmpty++;
700 : : }
701 : : }
702 : : }
703 : 0 : pINChI_Prev = pINChI;
704 : 0 : mult = 0; /* we do not know whether the item is empty */
705 : : }
706 [ # # # # ]: 0 : if (nNumEmpty == num_components && strbuf->nUsedLength > nUsedLength0)
707 : : {
708 : 0 : strbuf->nUsedLength = nUsedLength0;
709 : 0 : strbuf->pStr[nUsedLength0] = '\0';
710 : : }
711 : : /*
712 : : if ( nNumEmpty == num_components && tot_len > tot_len_inp ) {
713 : : tot_len = tot_len_inp;
714 : : strbuf->pStr[tot_len] = '\0';
715 : : }
716 : : */
717 : :
718 : 0 : return ( strbuf->nUsedLength - nUsedLength0 );
719 : : }
720 : :
721 : : /**
722 : : * @brief Produce double bond stereo substring of the whole structure InChI string.
723 : : *
724 : : * @param pINChISort Pointer to the primary INCHI_SORT structure containing input data.
725 : : * @param pINChISort2 Pointer to the secondary INCHI_SORT structure, used for comparison or additional data.
726 : : * @param strbuf Pointer to an INCHI_IOS_STRING buffer where the output string will be stored.
727 : : * @param bOverflow Pointer to an integer flag that will be set if the output overflows the buffer.
728 : : * @param bOutType Output type flag specifying the format or type of output.
729 : : * @param TAUT_MODE Tautomer mode flag indicating how tautomers are handled.
730 : : * @param num_components Number of components to process.
731 : : * @param bSecondNonTautPass Flag indicating if this is the second pass for non-tautomeric processing.
732 : : * @param bOmitRepetitions Flag to omit repeated entries in the output.
733 : : * @param bUseMulipliers Flag to use multipliers in the output representation.
734 : : * @return Returns number of characters written to strbuf
735 : : */
736 : 0 : int str_Sp2( INCHI_SORT *pINChISort,
737 : : INCHI_SORT *pINChISort2,
738 : : INCHI_IOS_STRING *strbuf,
739 : : int *bOverflow,
740 : : int bOutType,
741 : : int TAUT_MODE,
742 : : int num_components,
743 : : int bSecondNonTautPass,
744 : : int bOmitRepetitions,
745 : : int bUseMulipliers )
746 : : {
747 : : int i, ii, ii2, nUsedLength0;
748 : : INCHI_SORT *is, *is2, *is0, *is20;
749 : : INChI *pINChI, *pINChI_Prev, *pINChI_Taut, *pINChI_Taut_Prev;
750 : : INChI_Stereo *Stereo, *Stereo_Prev, *Stereo_Taut, *Stereo_Taut_Prev;
751 : : int mult, eq2prev, eq2taut, eq2tautPrev, bNext;
752 : : const char *pPrevEquStr, *pCurrEquStr;
753 : : int multPrevEquStr;
754 : :
755 : 0 : pINChI_Taut = NULL;
756 : 0 : pINChI_Prev = NULL;
757 : 0 : pINChI_Taut_Prev = NULL;
758 : 0 : mult = 0;
759 : 0 : bNext = 0;
760 : 0 : is = NULL;
761 : 0 : is2 = NULL;
762 : 0 : is0 = pINChISort;
763 [ # # ]: 0 : is20 = bSecondNonTautPass ? pINChISort2 : NULL;
764 : : /* djb-rwth: removing redundant code */
765 : 0 : eq2tautPrev = 1; /* pINChI_Prev (previous pINChI) does not exist */
766 : 0 : pPrevEquStr = NULL; /*, *pCurrEquStr;*/
767 : 0 : multPrevEquStr = 0;
768 : 0 : nUsedLength0 = strbuf->nUsedLength;
769 : :
770 : : /* For each connected component ... */
771 [ # # ]: 0 : for (i = 0; i <= num_components; i++)
772 : : {
773 : :
774 : : /* 1st (taut) pass: bOutType=OUT_TN ; 2nd (non-taut pass) bOutType=OUT_NT */
775 [ # # # # : 0 : pINChI = ( i < num_components && ( is = is0 + i, 0 <= ( ii = GET_II( bOutType, is ) ) ) ) ? is->pINChI[ii] : NULL;
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # ]
776 : : /*================ compare sp2 to previous =====================*/
777 [ # # ]: 0 : if (bSecondNonTautPass)
778 : : {
779 : : /* component that was output on the 1st pass */
780 [ # # # # : 0 : pINChI_Taut = ( i < num_components && ( is2 = is20 + i, 0 <= ( ii2 = GET_II( OUT_T1, is2 ) ) ) ) ? is2->pINChI[ii2] : NULL;
# # # # #
# # # ]
781 : : }
782 : : /*========= if bSecondNonTautPass then compare non-iso non-taut stereo to non-iso taut ========*/
783 : 0 : eq2taut = 0;
784 : : #if ( FIX_EMPTY_LAYER_BUG == 1 )
785 : : if (!eq2taut && bSecondNonTautPass && bOmitRepetitions && pINChI && pINChI_Taut)
786 : : {
787 : : Stereo = pINChI->Stereo;
788 : : Stereo_Taut = pINChI_Taut->Stereo;
789 : : eq2taut = Stereo && Stereo_Taut &&
790 : : Eql_INChI_Stereo( Stereo, EQL_SP2, Stereo_Taut, EQL_SP2, 0 );
791 : : eq2taut = eq2taut ? ( iiSTEREO | iitNONTAUT ) : 0;
792 : :
793 : : if (!eq2taut &&
794 : : !Eql_INChI_Stereo( Stereo, EQL_SP2, NULL, EQL_EXISTS, 0 ) &&
795 : : Eql_INChI_Stereo( Stereo_Taut, EQL_SP2, NULL, EQL_EXISTS, 0 ))
796 : : {
797 : : eq2taut = iiEmpty; /* the current is empty while the preceding (taut) is not */
798 : : }
799 : : }
800 : : #else
801 [ # # # # : 0 : if (!eq2taut && bSecondNonTautPass && bOmitRepetitions)
# # ]
802 : : {
803 [ # # ]: 0 : eq2taut = pINChI && pINChI_Taut &&
804 [ # # # # : 0 : ( Stereo = pINChI->Stereo ) && ( Stereo_Taut = pINChI_Taut->Stereo ) &&
# # # # ]
805 : 0 : Eql_INChI_Stereo( Stereo, EQL_SP2, Stereo_Taut, EQL_SP2, 0 );
806 [ # # ]: 0 : eq2taut = eq2taut ? ( iiSTEREO | iitNONTAUT ) : 0;
807 : : }
808 : : #endif
809 [ # # ]: 0 : if (eq2taut)
810 : : {
811 : : /* we may be here only in case of the second (non-taut) pass */
812 : : /* current non-taut stereo has been found to be same as tautomeric */
813 [ # # # # ]: 0 : if (pINChI_Prev && pINChI_Prev->nNumberOfAtoms)
814 : : {
815 : : /* previous component exists; output it */
816 [ # # ]: 0 : if (bNext++)
817 : : {
818 : 0 : MakeDelim( sCompDelim, strbuf, bOverflow );
819 : : }
820 [ # # # # ]: 0 : if (( Stereo_Prev = pINChI_Prev->Stereo ) && Stereo_Prev->nNumberOfStereoBonds > 0)
821 : : {
822 : 0 : MakeMult( mult + 1, "*", strbuf, 0, bOverflow );
823 : :
824 : 0 : MakeStereoString( Stereo_Prev->nBondAtom1, Stereo_Prev->nBondAtom2,
825 : : Stereo_Prev->b_parity,
826 : : 0, Stereo_Prev->nNumberOfStereoBonds,
827 : : strbuf, TAUT_MODE, bOverflow );
828 : : }
829 : : }
830 : : else
831 : : {
832 [ # # # # ]: 0 : if (pINChI_Taut_Prev && pINChI_Taut_Prev->nNumberOfAtoms)
833 : : {
834 : : /* previous non-taut component exists only in taut list */
835 [ # # ]: 0 : if (bNext++)
836 : : {
837 : 0 : MakeDelim( sCompDelim, strbuf, bOverflow );
838 : : }
839 : : }
840 : : }
841 : : /* we have found pINChI->Stereo sp2 same as in pINChI_Taut */
842 : : /* output this (current) equivalence as '*', that is, same as tautomeric */
843 : : /* that was printed on the 1st pass. */
844 : 0 : pCurrEquStr = EquString( eq2taut );
845 [ # # # # ]: 0 : if (multPrevEquStr && pPrevEquStr)
846 : : {
847 [ # # # # ]: 0 : if (pCurrEquStr && !strcmp( pCurrEquStr, pPrevEquStr ))
848 : : {
849 : 0 : multPrevEquStr++;
850 : : }
851 : : else
852 : : {
853 : : /* new EqStr is different; output the previous one */
854 [ # # ]: 0 : if (bNext++)
855 : : {
856 : 0 : MakeDelim( sCompDelim, strbuf, bOverflow );
857 : : }
858 : 0 : MakeEqStr( pPrevEquStr, multPrevEquStr, strbuf, bOverflow );
859 : 0 : pPrevEquStr = pCurrEquStr;
860 : 0 : multPrevEquStr = 1;
861 : : }
862 : : }
863 : : else
864 : : {
865 : 0 : pPrevEquStr = pCurrEquStr;
866 : 0 : multPrevEquStr = 1;
867 : : }
868 : 0 : pINChI_Prev = NULL; /* pINChI_Prev sp2 does not exist since */
869 : 0 : pINChI_Taut_Prev = NULL; /* pINChI has just been printed */
870 : 0 : mult = 0;
871 : 0 : eq2tautPrev = 1; /* pINChI_Prev sp2 does not exist */
872 : : }
873 : : else
874 : : {
875 [ # # ]: 0 : if (eq2tautPrev)
876 : : {
877 : : /* at this point pINChI_Prev does not exist; however, pINChI */
878 : : /*might have been discovered and it is different from pINChI_Taut */
879 [ # # # # ]: 0 : if (multPrevEquStr && pPrevEquStr)
880 : : {
881 : : /* new EqStr is different; output it */
882 [ # # ]: 0 : if (bNext++)
883 : : {
884 : 0 : MakeDelim( sCompDelim, strbuf, bOverflow );
885 : : }
886 : 0 : MakeEqStr( pPrevEquStr, multPrevEquStr, strbuf, bOverflow );
887 : 0 : pPrevEquStr = NULL;
888 : 0 : multPrevEquStr = 0;
889 : : }
890 : 0 : eq2tautPrev = 0;
891 : 0 : pINChI_Prev = pINChI;
892 : 0 : pINChI_Taut_Prev = pINChI_Taut;
893 : 0 : mult = 0;
894 : : }
895 : : else
896 : : {
897 : : /* check whether pINChI and pINChI_Prev have non-zero identical stereo sp2 */
898 [ # # ]: 0 : eq2prev = bUseMulipliers &&
899 [ # # ]: 0 : pINChI && pINChI_Prev &&
900 [ # # # # : 0 : ( Stereo = pINChI->Stereo ) && ( Stereo_Prev = pINChI_Prev->Stereo ) &&
# # # # ]
901 : 0 : Eql_INChI_Stereo( Stereo, EQL_SP2, Stereo_Prev, EQL_SP2, 0 );
902 [ # # ]: 0 : if (eq2prev)
903 : : {
904 : 0 : mult++; /* mult = (number of non-empty equal items)-1 */
905 : 0 : continue;
906 : : }
907 : : else
908 : : {
909 : : /* pINChI sp2 info is either different or trivial. Output pINChI_Prev anyway */
910 [ # # ]: 0 : if (bNext++)
911 : : {
912 : 0 : MakeDelim( sCompDelim, strbuf, bOverflow );
913 : : }
914 [ # # # # ]: 0 : if (pINChI_Prev && pINChI_Prev->nNumberOfAtoms)
915 : : {
916 [ # # # # ]: 0 : if (( Stereo_Prev = pINChI_Prev->Stereo ) && Stereo_Prev->nNumberOfStereoBonds > 0)
917 : : {
918 : : /* pINChI_Prev exists and has sp2 info */
919 : 0 : MakeMult( mult + 1, "*", strbuf, 0, bOverflow );
920 : :
921 : 0 : MakeStereoString( Stereo_Prev->nBondAtom1, Stereo_Prev->nBondAtom2,
922 : : Stereo_Prev->b_parity,
923 : : 0, Stereo_Prev->nNumberOfStereoBonds,
924 : : strbuf, TAUT_MODE, bOverflow );
925 : : }
926 : : /* else sp2 info is not present in pINChI_Prev */
927 : : }
928 : : else
929 : : {
930 [ # # # # : 0 : if (bSecondNonTautPass && pINChI_Taut_Prev && pINChI_Taut_Prev->nNumberOfAtoms)
# # ]
931 : : {
932 [ # # ]: 0 : if (( Stereo_Taut_Prev = pINChI_Taut_Prev->Stereo ) && Stereo_Taut_Prev->nNumberOfStereoBonds > 0)
933 : : {
934 : : /* since pINChI_Prev does not exist, pINChI_Taut_Prev is non-tautomeric */
935 : : /* and it has non-trivial sp2 info */
936 : : /*
937 : : tot_len += MakeDelim( sIdenticalValues, strbuf, bOverflow);
938 : : */
939 : : ;/* pINChI_Taut_Prev sp2 info was output in the main stereo section */
940 : : }
941 : : else
942 : : {
943 : : ; /* pINChI_Taut_Prev exists and has not sp2 info */
944 : : }
945 : : }
946 : : }
947 : : #if ( bRELEASE_VERSION != 1 && defined(_DEBUG) )
948 : : else
949 : : {
950 : : int stop = 1; /* <BRKPT> */
951 : : }
952 : : #endif
953 : : }
954 : 0 : pINChI_Prev = pINChI;
955 : 0 : pINChI_Taut_Prev = pINChI_Taut;
956 : 0 : mult = 0; /* we do not know whether the item is empty */
957 : : }
958 : : }
959 : : } /* end of for each connected component ... */
960 : :
961 : 0 : return ( strbuf->nUsedLength - nUsedLength0 );
962 : : }
963 : :
964 : : /**
965 : : * @brief Produce tetrahedral stereo substring of the whole structure InChI string.
966 : : *
967 : : * @param pINChISort Pointer to the primary INCHI_SORT structure containing input data.
968 : : * @param pINChISort2 Pointer to the secondary INCHI_SORT structure, used for comparison or additional data.
969 : : * @param strbuf Pointer to an INCHI_IOS_STRING buffer where the output string will be stored.
970 : : * @param bOverflow Pointer to an integer flag that will be set if the output overflows the buffer.
971 : : * @param bOutType Output type flag specifying the format or type of output.
972 : : * @param TAUT_MODE Tautomer mode flag indicating how tautomers are handled.
973 : : * @param num_components The number of components to process.
974 : : * @param bRelRac Flag for relative or racemic stereochemistry.
975 : : * @param bSecondNonTautPass Flag indicating if this is the second pass for non-tautomeric processing.
976 : : * @param bOmitRepetitions Flag to omit repeated entries in the output.
977 : : * @param bUseMulipliers Flag to use multipliers in the output representation.
978 : : * @return int
979 : : */
980 : 42 : int str_Sp3( INCHI_SORT *pINChISort,
981 : : INCHI_SORT *pINChISort2,
982 : : INCHI_IOS_STRING *strbuf,
983 : : int *bOverflow,
984 : : int bOutType,
985 : : int TAUT_MODE,
986 : : int num_components,
987 : : int bRelRac,
988 : : int bSecondNonTautPass,
989 : : int bOmitRepetitions,
990 : : int bUseMulipliers )
991 : : {
992 : : int i, ii, ii2, nUsedLength0;
993 : : INCHI_SORT *is, *is2, *is0, *is20;
994 : : INChI *pINChI, *pINChI_Prev, *pINChI_Taut, *pINChI_Taut_Prev;
995 : : INChI_Stereo *Stereo, *Stereo_Prev, *Stereo_Taut, *Stereo_Taut_Prev;
996 : : int mult, eq2prev, eq2taut, eq2tautPrev, bNext;
997 : : const char *pPrevEquStr, *pCurrEquStr;
998 : : int multPrevEquStr;
999 : 42 : pINChI_Taut = NULL;
1000 : 42 : pINChI_Prev = NULL;
1001 : 42 : pINChI_Taut_Prev = NULL;
1002 : 42 : mult = 0;
1003 : 42 : bNext = 0;
1004 : 42 : is = NULL;
1005 : 42 : is2 = NULL;
1006 : 42 : is0 = pINChISort;
1007 [ - + ]: 42 : is20 = bSecondNonTautPass ? pINChISort2 : NULL;
1008 : : /* djb-rwth: removing redundant code */
1009 : 42 : eq2tautPrev = 1; /* pINChI_Prev (previous pINChI) does not exist */
1010 : 42 : pPrevEquStr = NULL; /*, *pCurrEquStr;*/
1011 : 42 : multPrevEquStr = 0;
1012 : : #if ( REL_RAC_STEREO_IGN_1_SC == 1 )
1013 : : #else
1014 : 42 : bRelRac = 0;
1015 : : #endif
1016 : 42 : nUsedLength0 = strbuf->nUsedLength;
1017 : :
1018 : : /* For each connected component... */
1019 [ + + ]: 136 : for (i = 0; i <= num_components; i++)
1020 : : {
1021 : :
1022 : : /* 1st (taut) pass: bOutType=OUT_TN ; 2nd (non-taut pass) bOutType=OUT_NT */
1023 [ + + - + : 94 : pINChI = ( i < num_components && ( is = is0 + i, 0 <= ( ii = GET_II( bOutType, is ) ) ) ) ? is->pINChI[ii] : NULL;
- - - - -
- - - - -
- - + - +
- + - - +
- - - - -
- - - - -
- - - - -
- - - - -
- - - - -
- - - - -
- - + - ]
1024 : : /*================ compare sp3 to previous =====================*/
1025 [ - + ]: 94 : if (bSecondNonTautPass)
1026 : : {
1027 : : /* component that was output on the 1st pass */
1028 [ # # # # : 0 : pINChI_Taut = ( i < num_components && ( is2 = is20 + i, 0 <= ( ii2 = GET_II( OUT_T1, is2 ) ) ) ) ? is2->pINChI[ii2] : NULL;
# # # # #
# # # ]
1029 : : }
1030 : : /*========= if bSecondNonTautPass then compare non-iso non-taut stereo to non-iso taut ========*/
1031 : 94 : eq2taut = 0;
1032 : : #if ( FIX_EMPTY_LAYER_BUG == 1 )
1033 : : if (!eq2taut && bSecondNonTautPass && bOmitRepetitions && pINChI && pINChI_Taut)
1034 : : {
1035 : : Stereo = pINChI->Stereo;
1036 : : Stereo_Taut = pINChI_Taut->Stereo;
1037 : : eq2taut = Stereo && Stereo_Taut &&
1038 : : Eql_INChI_Stereo( Stereo, EQL_SP3, Stereo_Taut, EQL_SP3, bRelRac );
1039 : : eq2taut = eq2taut ? ( iiSTEREO | iitNONTAUT ) : 0;
1040 : : if (!eq2taut &&
1041 : : !Eql_INChI_Stereo( Stereo, EQL_SP3, NULL, EQL_EXISTS, 0 ) &&
1042 : : Eql_INChI_Stereo( Stereo_Taut, EQL_SP3, NULL, EQL_EXISTS, 0 ))
1043 : : {
1044 : : eq2taut = iiEmpty; /* the current is empty while the preceding (taut) is not */
1045 : : }
1046 : : }
1047 : : #else
1048 [ + - - + : 94 : if (!eq2taut && bSecondNonTautPass && bOmitRepetitions)
- - ]
1049 : : {
1050 [ # # ]: 0 : eq2taut = pINChI && pINChI_Taut &&
1051 [ # # # # : 0 : ( Stereo = pINChI->Stereo ) && ( Stereo_Taut = pINChI_Taut->Stereo ) &&
# # # # ]
1052 : 0 : Eql_INChI_Stereo( Stereo, EQL_SP3, Stereo_Taut, EQL_SP3, bRelRac );
1053 [ # # ]: 0 : eq2taut = eq2taut ? ( iiSTEREO | iitNONTAUT ) : 0;
1054 : : }
1055 : : #endif
1056 [ - + ]: 94 : if (eq2taut)
1057 : : {
1058 : : /* we may be here only in case of the second (non-taut) pass */
1059 : : /* current non-taut stereo has been found to be same as tautomeric */
1060 [ # # # # ]: 0 : if (pINChI_Prev && pINChI_Prev->nNumberOfAtoms)
1061 : : {
1062 : : /* previous component exists; output it */
1063 [ # # ]: 0 : if (bNext++)
1064 : : {
1065 : 0 : MakeDelim( sCompDelim, strbuf, bOverflow );
1066 : : }
1067 [ # # # # ]: 0 : if (( Stereo_Prev = pINChI_Prev->Stereo ) && Stereo_Prev->nNumberOfStereoCenters > 0)
1068 : : {
1069 : : /* non-empty item */
1070 : 0 : MakeMult( mult + 1, "*", strbuf, 0, bOverflow );
1071 : 0 : MakeStereoString( Stereo_Prev->nNumber, NULL,
1072 : : Stereo_Prev->t_parity,0,
1073 : : Stereo_Prev->nNumberOfStereoCenters,
1074 : : strbuf, TAUT_MODE, bOverflow );
1075 : : }
1076 : : }
1077 : : else
1078 [ # # # # ]: 0 : if (pINChI_Taut_Prev && pINChI_Taut_Prev->nNumberOfAtoms)
1079 : : {
1080 : : /* previous non-taut component exists only in taut list */
1081 [ # # ]: 0 : if (bNext++)
1082 : : {
1083 : 0 : MakeDelim( sCompDelim, strbuf, bOverflow );
1084 : : }
1085 : : }
1086 : : /* we have found pINChI->Stereo sp3 same as in pINChI_Taut */
1087 : : /* output this (current) equivalence as '*', that is, same as tautomeric */
1088 : : /* that was printed on the 1st pass. */
1089 : :
1090 : 0 : pCurrEquStr = EquString( eq2taut );
1091 [ # # # # ]: 0 : if (multPrevEquStr && pPrevEquStr)
1092 : : {
1093 [ # # # # ]: 0 : if (pCurrEquStr && !strcmp( pCurrEquStr, pPrevEquStr ))
1094 : : {
1095 : 0 : multPrevEquStr++;
1096 : : }
1097 : : else
1098 : : {
1099 : : /* new EqStr is different; output it */
1100 [ # # ]: 0 : if (bNext++)
1101 : : {
1102 : 0 : MakeDelim( sCompDelim, strbuf, bOverflow );
1103 : : }
1104 : 0 : MakeEqStr( pPrevEquStr, multPrevEquStr, strbuf, bOverflow );
1105 : 0 : pPrevEquStr = pCurrEquStr;
1106 : 0 : multPrevEquStr = 1;
1107 : : }
1108 : : }
1109 : : else
1110 : : {
1111 : 0 : pPrevEquStr = pCurrEquStr;
1112 : 0 : multPrevEquStr = 1;
1113 : : }
1114 : :
1115 : 0 : pINChI_Prev = NULL; /* pINChI_Prev sp2 does not exist since */
1116 : 0 : pINChI_Taut_Prev = NULL; /* pINChI has just been printed */
1117 : 0 : mult = 0;
1118 : 0 : eq2tautPrev = 1; /* pINChI_Prev sp2 does not exist */
1119 : : }
1120 : : else
1121 : : {
1122 [ + + ]: 94 : if (eq2tautPrev)
1123 : : {
1124 : : /* at this point pINChI_Prev does not exist; however, pINChI */
1125 : : /*might have been discovered and it is different from pINChI_Taut */
1126 [ - + - - ]: 42 : if (multPrevEquStr && pPrevEquStr)
1127 : : {
1128 : : /* new EqStr is different; output it */
1129 [ # # ]: 0 : if (bNext++)
1130 : : {
1131 : 0 : MakeDelim( sCompDelim, strbuf, bOverflow );
1132 : : }
1133 : 0 : MakeEqStr( pPrevEquStr, multPrevEquStr, strbuf, bOverflow );
1134 : 0 : pPrevEquStr = NULL;
1135 : 0 : multPrevEquStr = 0;
1136 : : }
1137 : 42 : eq2tautPrev = 0;
1138 : 42 : pINChI_Prev = pINChI;
1139 : 42 : pINChI_Taut_Prev = pINChI_Taut;
1140 : 42 : mult = 0;
1141 : : }
1142 : : else
1143 : : {
1144 : : /* check whether pINChI and pINChI_Prev have non-zero identical stereo sp3 */
1145 : : /*================ compare sp3 to previous =====================*/
1146 [ + + ]: 52 : eq2prev = bUseMulipliers &&
1147 [ + - ]: 10 : pINChI && pINChI_Prev &&
1148 [ + - + - : 114 : ( Stereo = pINChI->Stereo ) && ( Stereo_Prev = pINChI_Prev->Stereo ) &&
+ - + + ]
1149 : 10 : Eql_INChI_Stereo( Stereo, EQL_SP3, Stereo_Prev, EQL_SP3, bRelRac );
1150 [ + + ]: 52 : if (eq2prev)
1151 : : {
1152 : 5 : mult++; /* mult = (number of non-empty equal items)-1 */
1153 : 5 : continue;
1154 : : }
1155 : : else
1156 : : {
1157 [ + + ]: 47 : if (bNext++)
1158 : : {
1159 : 5 : MakeDelim( sCompDelim, strbuf, bOverflow );
1160 : : }
1161 [ + - + - ]: 47 : if (pINChI_Prev && pINChI_Prev->nNumberOfAtoms)
1162 : : {
1163 [ + - + + ]: 47 : if (( Stereo_Prev = pINChI_Prev->Stereo ) && Stereo_Prev->nNumberOfStereoCenters > bRelRac)
1164 : : {
1165 : : /* pINChI_Prev exists and has sp3 info */
1166 : 46 : MakeMult( mult + 1, "*", strbuf, 0, bOverflow );
1167 : :
1168 : 46 : MakeStereoString( Stereo_Prev->nNumber, NULL, Stereo_Prev->t_parity,
1169 : : 0, Stereo_Prev->nNumberOfStereoCenters,
1170 : : strbuf, TAUT_MODE, bOverflow );
1171 : : }
1172 : : /* else sp3 info is not present in pINChI_Prev */
1173 : : }
1174 : : else
1175 : : {
1176 [ # # # # : 0 : if (bSecondNonTautPass && pINChI_Taut_Prev && pINChI_Taut_Prev->nNumberOfAtoms)
# # ]
1177 : : {
1178 [ # # ]: 0 : if (( Stereo_Taut_Prev = pINChI_Taut_Prev->Stereo ) && Stereo_Taut_Prev->nNumberOfStereoCenters > bRelRac)
1179 : : {
1180 : : /* since pINChI_Prev does not exist, pINChI_Taut_Prev is non-tautomeric */
1181 : : /* and it has non-trivial sp3 info. This info has already been printed in the main section */
1182 : : /*
1183 : : tot_len += MakeDelim( sIdenticalValues, strbuf, bOverflow);
1184 : : */
1185 : : ; /* pINChI_Taut_Prev sp3 info was output in the main stereo section */
1186 : : }
1187 : : else
1188 : : {
1189 : : ; /* pINChI_Taut_Prev exists and has not sp3 info */
1190 : : }
1191 : : }
1192 : : #if ( bRELEASE_VERSION != 1 && defined(_DEBUG) )
1193 : : else
1194 : : {
1195 : : int stop = 1; /* <BRKPT> */
1196 : : }
1197 : : #endif
1198 : : }
1199 : : }
1200 : 47 : pINChI_Prev = pINChI;
1201 : 47 : pINChI_Taut_Prev = pINChI_Taut;
1202 : 47 : mult = 0; /* we do not know whether the item is empty */
1203 : : }
1204 : : }
1205 : : }
1206 : :
1207 : 42 : return ( strbuf->nUsedLength - nUsedLength0 );
1208 : : }
1209 : :
1210 : : /**
1211 : : * @brief Output absolute stereo inversion substring of the whole structure InChI string
1212 : : * @param pINChISort Pointer to INCHI_SORT array
1213 : : * @param strbuf Pointer to string buffer
1214 : : * @param bOverflow Overflow flag
1215 : : * @param bOutType Output type
1216 : : * @param num_components Number of connected components
1217 : : * @return Length of the added substring (return value '0', '1', or '.' in strbuf)
1218 : : */
1219 : 42 : int str_StereoAbsInv( INCHI_SORT *pINChISort,
1220 : : INCHI_IOS_STRING *strbuf,
1221 : : int *bOverflow,
1222 : : int bOutType,
1223 : : int num_components )
1224 : : {
1225 : : int i, j, ii, nUsedLength0;
1226 : : INCHI_SORT *is, *is0;
1227 : : INChI_Stereo *Stereo;
1228 : : INChI *pINChI;
1229 : :
1230 : 42 : is = NULL;
1231 : 42 : is0 = pINChISort;
1232 : 42 : nUsedLength0 = strbuf->nUsedLength;
1233 : :
1234 : : /* For each connected component... */
1235 [ + - + + ]: 94 : for (i = 0; !*bOverflow && i < num_components; i++)
1236 : : {
1237 : :
1238 : 52 : is = is0 + i;
1239 [ - + - - : 52 : pINChI = ( 0 <= ( ii = GET_II( bOutType, is ) ) ) ? is->pINChI[ii] : NULL;
- - - - -
- - - - -
+ - + - +
- - + - -
- - - - -
- - - - -
- - - - -
- - - - -
- - - - -
- - - - -
+ - ]
1240 [ + - + - : 52 : if (pINChI && ( Stereo = pINChI->Stereo ) && ( j = Stereo->nCompInv2Abs ))
+ + ]
1241 : : {
1242 [ + + ]: 51 : MakeDelim( j < 0 ? "1" : "0", strbuf, bOverflow );
1243 : : }
1244 : : else
1245 : : {
1246 : 1 : MakeDelim( ".", strbuf, bOverflow );
1247 : : }
1248 : : }
1249 : :
1250 : 42 : return ( strbuf->nUsedLength - nUsedLength0 );
1251 : : }
1252 : :
1253 : :
1254 : : /****************************************************************************
1255 : : Produce isotopic substring of the whole structure InChI string.
1256 : : ****************************************************************************/
1257 : 0 : int str_IsoAtoms( INCHI_SORT *pINChISort,
1258 : : INCHI_SORT *pINChISort2,
1259 : : INCHI_IOS_STRING *strbuf,
1260 : : int *bOverflow,
1261 : : int bOutType,
1262 : : int TAUT_MODE,
1263 : : int num_components,
1264 : : int bAbcNumbers,
1265 : : int bSecondNonTautPass,
1266 : : int bOmitRepetitions,
1267 : : int bUseMulipliers )
1268 : : {
1269 : : int i, ii, ii2, nUsedLength0;
1270 : : INCHI_SORT *is, *is2, *is0, *is20;
1271 : : INChI *pINChI, *pINChI_Prev, *pINChI_Taut, *pINChI_Taut_Prev;
1272 : : int mult, eq2prev, eq2taut, eq2tautPrev, bNext;
1273 : : const char *pPrevEquStr, *pCurrEquStr;
1274 : : int multPrevEquStr;
1275 : 0 : pINChI_Taut = NULL;
1276 : 0 : pINChI_Prev = NULL;
1277 : 0 : pINChI_Taut_Prev = NULL;
1278 : 0 : mult = 0;
1279 : 0 : bNext = 0;
1280 : 0 : is = NULL;
1281 : 0 : is2 = NULL;
1282 : 0 : is0 = pINChISort;
1283 [ # # ]: 0 : is20 = bSecondNonTautPass ? pINChISort2 : NULL;
1284 : : /* djb-rwth: removing redundant code */
1285 : 0 : eq2tautPrev = 1; /* pINChI_Prev (previous pINChI) does not exist */
1286 : 0 : pPrevEquStr = NULL; /*, *pCurrEquStr;*/
1287 : 0 : multPrevEquStr = 0;
1288 : 0 : nUsedLength0 = strbuf->nUsedLength;
1289 : :
1290 : : /* For each connected component... */
1291 [ # # ]: 0 : for (i = 0; i <= num_components; i++)
1292 : : {
1293 : :
1294 : : /* 1st (taut) pass: bOutType=OUT_TN ; 2nd (non-taut pass) bOutType=OUT_NT */
1295 [ # # # # : 0 : pINChI = ( i < num_components && ( is = is0 + i, 0 <= ( ii = GET_II( bOutType, is ) ) ) ) ? is->pINChI[ii] : NULL;
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # ]
1296 : : /*================ compare isotopic info to previous component =====================*/
1297 [ # # ]: 0 : if (bSecondNonTautPass)
1298 : : {
1299 : : /* component that was output on the 1st pass */
1300 [ # # # # : 0 : pINChI_Taut = ( i < num_components && ( is2 = is20 + i, 0 <= ( ii2 = GET_II( OUT_T1, is2 ) ) ) ) ? is2->pINChI[ii2] : NULL;
# # # # #
# # # ]
1301 : : }
1302 : : /*========= if bSecondNonTautPass then compare iso non-taut to taut non-iso ========*/
1303 : 0 : eq2taut = 0;
1304 [ # # # # : 0 : if (!eq2taut && bSecondNonTautPass && bOmitRepetitions)
# # ]
1305 : : {
1306 : 0 : eq2taut = Eql_INChI_Isotopic( pINChI, pINChI_Taut );
1307 [ # # ]: 0 : eq2taut = eq2taut ? ( iiNUMB | iitNONTAUT ) : 0;
1308 : : }
1309 [ # # ]: 0 : if (eq2taut)
1310 : : {
1311 : : /* we may be here only in case of the second (non-taut) pass */
1312 : : /* current non-taut isotopic info has been found to be same as current tautomeric */
1313 [ # # # # ]: 0 : if (pINChI_Prev && pINChI_Prev->nNumberOfAtoms)
1314 : : {
1315 : : /* previous component exists; output it */
1316 [ # # ]: 0 : if (bNext++)
1317 : : {
1318 : 0 : MakeDelim( sCompDelim, strbuf, bOverflow );
1319 : : }
1320 [ # # # # ]: 0 : if (pINChI_Prev && ( pINChI_Prev->nNumberOfIsotopicAtoms > 0 ||
1321 [ # # ]: 0 : pINChI_Prev->nNumberOfIsotopicTGroups > 0 ))
1322 : : {
1323 : : /* non-empty item */
1324 : 0 : MakeMult( mult + 1, "*", strbuf, 0, bOverflow );
1325 : : /* Isotopic atoms */
1326 [ # # # # ]: 0 : if (pINChI_Prev->nNumberOfIsotopicAtoms > 0/* && nStrLen-tot_len > 2*/ && !*bOverflow)
1327 : : { /* dereferenced bOverflow 2004-06-07 */
1328 : 0 : MakeIsoAtomString( pINChI_Prev->IsotopicAtom,
1329 : : pINChI_Prev->nNumberOfIsotopicAtoms,
1330 : : strbuf,
1331 : : TAUT_MODE, bOverflow );
1332 : : }
1333 : : /* Isotopic tautomeric groups */
1334 [ # # ]: 0 : if (pINChI_Prev->nNumberOfIsotopicTGroups > 0 &&
1335 : : /*nStrLen-tot_len > 3 && */
1336 [ # # ]: 0 : !*bOverflow)
1337 : : {
1338 [ # # ]: 0 : MakeDelim( bAbcNumbers ? ITEM_DELIMETER : "(", strbuf, bOverflow );
1339 : 0 : MakeIsoTautString( pINChI_Prev->IsotopicTGroup, pINChI_Prev->nNumberOfIsotopicTGroups,
1340 : : strbuf, TAUT_MODE, bOverflow );
1341 [ # # ]: 0 : if (!bAbcNumbers)
1342 : : {
1343 : 0 : MakeDelim( ")", strbuf, bOverflow );
1344 : : }
1345 : : }
1346 : : }
1347 : : }
1348 : : else
1349 : : {
1350 [ # # # # ]: 0 : if (pINChI_Taut_Prev && pINChI_Taut_Prev->nNumberOfAtoms)
1351 : : {
1352 : : /* previous non-taut component exists only in taut list */
1353 [ # # ]: 0 : if (bNext++)
1354 : : {
1355 : 0 : MakeDelim( sCompDelim, strbuf, bOverflow );
1356 : : }
1357 : : }
1358 : : }
1359 : : /* we have found pINChI isotopic info to be same as in pINChI_Taut */
1360 : : /* output this (current) equivalence as '*', that is, same as tautomeric */
1361 : : /* that was printed on the 1st pass. */
1362 : 0 : pCurrEquStr = EquString( eq2taut );
1363 [ # # # # ]: 0 : if (multPrevEquStr && pPrevEquStr)
1364 : : {
1365 [ # # # # ]: 0 : if (pCurrEquStr && !strcmp( pCurrEquStr, pPrevEquStr ))
1366 : : {
1367 : 0 : multPrevEquStr++;
1368 : : }
1369 : : else
1370 : : {
1371 : : /* new EqStr is different; output it */
1372 [ # # ]: 0 : if (bNext++)
1373 : : {
1374 : 0 : MakeDelim( sCompDelim, strbuf, bOverflow );
1375 : : }
1376 : 0 : MakeEqStr( pPrevEquStr, multPrevEquStr, strbuf, bOverflow );
1377 : 0 : pPrevEquStr = pCurrEquStr;
1378 : 0 : multPrevEquStr = 1;
1379 : : }
1380 : : }
1381 : : else
1382 : : {
1383 : 0 : pPrevEquStr = pCurrEquStr;
1384 : 0 : multPrevEquStr = 1;
1385 : : }
1386 : 0 : pINChI_Prev = NULL; /* pINChI_Prev isotopic info does not exist since */
1387 : 0 : pINChI_Taut_Prev = NULL; /* pINChI has just been printed */
1388 : 0 : mult = 0;
1389 : 0 : eq2tautPrev = 1; /* pINChI_Prev isotopic info does not exist */
1390 : : }
1391 : : else
1392 [ # # ]: 0 : if (eq2tautPrev)
1393 : : {
1394 : : /* at this point pINChI_Prev does not exist; however, pINChI */
1395 : : /* might have been discovered and it is different from pINChI_Taut */
1396 [ # # # # ]: 0 : if (multPrevEquStr && pPrevEquStr)
1397 : : {
1398 : : /* new EqStr is different; output it */
1399 [ # # ]: 0 : if (bNext++)
1400 : : {
1401 : 0 : MakeDelim( sCompDelim, strbuf, bOverflow );
1402 : : }
1403 : 0 : MakeEqStr( pPrevEquStr, multPrevEquStr, strbuf, bOverflow );
1404 : 0 : pPrevEquStr = NULL;
1405 : 0 : multPrevEquStr = 0;
1406 : : }
1407 : 0 : eq2tautPrev = 0;
1408 : 0 : pINChI_Prev = pINChI;
1409 : 0 : pINChI_Taut_Prev = pINChI_Taut;
1410 : 0 : mult = 0;
1411 : : }
1412 : : else
1413 : : {
1414 : : /*================ compare iso composition to previous =====================*/
1415 : : /* check whether pINChI and pINChI_Prev have non-zero identical isotopic info */
1416 [ # # # # ]: 0 : eq2prev = bUseMulipliers && Eql_INChI_Isotopic( pINChI, pINChI_Prev );
1417 [ # # ]: 0 : if (eq2prev)
1418 : : {
1419 : 0 : mult++; /* mult = (number of non-empty equal items)-1 */
1420 : 0 : continue;
1421 : : }
1422 : : else
1423 : : {
1424 : : /* pINChI isotopic info is either different or empty. Output pINChI_Prev anyway */
1425 [ # # ]: 0 : if (bNext++)
1426 : : {
1427 : 0 : MakeDelim( sCompDelim, strbuf, bOverflow );
1428 : : }
1429 [ # # # # ]: 0 : if (pINChI_Prev && pINChI_Prev->nNumberOfAtoms)
1430 : : {
1431 [ # # ]: 0 : if (( pINChI_Prev->nNumberOfIsotopicAtoms > 0 ||
1432 [ # # ]: 0 : pINChI_Prev->nNumberOfIsotopicTGroups > 0 ))
1433 : : {
1434 : : /* pINChI_Prev exists and has isotopic info */
1435 : 0 : MakeMult( mult + 1, "*", strbuf, 0, bOverflow );
1436 : : /* Isotopic atoms */
1437 [ # # ]: 0 : if (pINChI_Prev->nNumberOfIsotopicAtoms > 0 &&
1438 : : /*nStrLen-tot_len > 2 && */
1439 [ # # ]: 0 : !*bOverflow)
1440 : : {
1441 : 0 : MakeIsoAtomString( pINChI_Prev->IsotopicAtom,
1442 : : pINChI_Prev->nNumberOfIsotopicAtoms,
1443 : : strbuf, TAUT_MODE, bOverflow );
1444 : : }
1445 : : /* Isotopic tautomeric groups */
1446 [ # # ]: 0 : if (pINChI_Prev->nNumberOfIsotopicTGroups > 0 &&
1447 : : /*nStrLen-tot_len > 3 && */
1448 [ # # ]: 0 : !*bOverflow)
1449 : : {
1450 [ # # ]: 0 : MakeDelim( bAbcNumbers ? ITEM_DELIMETER : "(", strbuf, bOverflow );
1451 : 0 : MakeIsoTautString( pINChI_Prev->IsotopicTGroup, pINChI_Prev->nNumberOfIsotopicTGroups,
1452 : : strbuf, TAUT_MODE, bOverflow );
1453 [ # # ]: 0 : if (!bAbcNumbers)
1454 : : {
1455 : 0 : MakeDelim( ")", strbuf, bOverflow );
1456 : : }
1457 : : }
1458 : : }
1459 : : /* else isotopic info is not present in pINChI_Prev */
1460 : : }
1461 : : else
1462 : : {
1463 [ # # # # : 0 : if (bSecondNonTautPass && pINChI_Taut_Prev && pINChI_Taut_Prev->nNumberOfAtoms)
# # ]
1464 : : {
1465 [ # # ]: 0 : if (( pINChI_Taut_Prev->nNumberOfIsotopicAtoms > 0 ||
1466 : 0 : pINChI_Taut_Prev->nNumberOfIsotopicTGroups > 0 ))
1467 : : {
1468 : : /* since pINChI_Prev does not exist, pINChI_Taut_Prev is non-tautomeric */
1469 : : /* and it has non-trivial isotopic info */
1470 : : /*
1471 : : tot_len += MakeDelim( sIdenticalValues, strbuf, bOverflow);
1472 : : */
1473 : : ;/* pINChI_Taut_Prev isotopic info was output in the main isotopic section */
1474 : : }
1475 : : else
1476 : : {
1477 : : ; /* pINChI_Taut_Prev exists and has not isotopic info */
1478 : : }
1479 : : }
1480 : : #if ( bRELEASE_VERSION != 1 && defined(_DEBUG) )
1481 : : else
1482 : : {
1483 : : int stop = 1; /* <BRKPT> */
1484 : : }
1485 : : #endif
1486 : : }
1487 : : }
1488 : : /* Fix17: moved here 2004-10-08 */
1489 : 0 : pINChI_Prev = pINChI;
1490 : 0 : pINChI_Taut_Prev = pINChI_Taut;
1491 : 0 : mult = 0; /* we do not know whether the item is empty */
1492 : : }
1493 : : /* Fix17: moved from here 2004-10-08
1494 : : pINChI_Prev = pINChI;
1495 : : pINChI_Taut_Prev = pINChI_Taut;
1496 : : mult = 0;
1497 : : */
1498 : : }
1499 : :
1500 : 0 : return ( strbuf->nUsedLength - nUsedLength0 );
1501 : : }
1502 : :
1503 : :
1504 : : /****************************************************************************
1505 : : Produce isotopic-dbonds stereo substring of the whole structure InChI string.
1506 : : ****************************************************************************/
1507 : 0 : int str_IsoSp2( INCHI_SORT *pINChISort,
1508 : : INCHI_SORT *pINChISort2,
1509 : : INCHI_IOS_STRING *strbuf,
1510 : : int *bOverflow,
1511 : : int bOutType,
1512 : : int TAUT_MODE,
1513 : : int num_components,
1514 : : int bSecondNonTautPass,
1515 : : int bOmitRepetitions,
1516 : : int bUseMulipliers )
1517 : : {
1518 : : int i, ii, ii2, nUsedLength0;
1519 : : INCHI_SORT *is, *is2, *is0, *is20;
1520 : : INChI *pINChI, *pINChI_Prev, *pINChI_Taut, *pINChI_Taut_Prev;
1521 : : INChI_Stereo *Stereo, *Stereo_Prev, *Stereo_Taut, *Stereo_Taut_Prev;
1522 : 0 : int mult, eq2prev, eq2taut, eq2tautPrev = 1, bNext; /* djb-rwth: initialisation required to avoid garbage values */
1523 : : const char *pPrevEquStr, *pCurrEquStr;
1524 : : int multPrevEquStr;
1525 : 0 : pINChI_Taut = NULL;
1526 : 0 : pINChI_Prev = NULL;
1527 : 0 : pINChI_Taut_Prev = NULL;
1528 : 0 : mult = 0;
1529 : 0 : bNext = 0;
1530 : 0 : is = NULL;
1531 : 0 : is2 = NULL;
1532 : 0 : is0 = pINChISort;
1533 [ # # ]: 0 : is20 = bSecondNonTautPass ? pINChISort2 : NULL;
1534 : : /* djb-rwth: removing redundant code */
1535 : 0 : pPrevEquStr = NULL; /*, *pCurrEquStr;*/
1536 : 0 : multPrevEquStr = 0;
1537 : 0 : nUsedLength0 = strbuf->nUsedLength;
1538 : :
1539 : : /* For each connected component... */
1540 [ # # ]: 0 : for (i = 0; i <= num_components; i++)
1541 : : {
1542 : : /* 1st (taut) pass: bOutType=OUT_TN ; 2nd (non-taut pass) bOutType=OUT_NT */
1543 [ # # # # : 0 : pINChI = ( i < num_components && ( is = is0 + i, 0 <= ( ii = GET_II( bOutType, is ) ) ) ) ? is->pINChI[ii] : NULL;
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # ]
1544 : : /*================ compare sp2 to previous =====================*/
1545 [ # # ]: 0 : if (bSecondNonTautPass)
1546 : : {
1547 : : /* component that was output on the 1st pass */
1548 [ # # # # : 0 : pINChI_Taut = ( i < num_components && ( is2 = is20 + i, 0 <= ( ii2 = GET_II( OUT_T1, is2 ) ) ) ) ? is2->pINChI[ii2] : NULL;
# # # # #
# # # ]
1549 : : }
1550 : 0 : eq2taut = 0;
1551 : : /*========= if bSecondNonTautPass then compare iso non-taut stereo to other stereo ========*/
1552 [ # # # # ]: 0 : if (bSecondNonTautPass && bOmitRepetitions)
1553 : : {
1554 : : /* compare non-tautomeric isotopic to:
1555 : : * a) non-tautomeric non-isotopic
1556 : : * b) tautomeric non-isotopic
1557 : : * c) tautomeric isotopic
1558 : : */
1559 : : /* a) compare non-tautomeric isotopic to non-tautomeric non-isotopic */
1560 [ # # ]: 0 : if (!eq2taut)
1561 : : {
1562 : 0 : eq2taut = pINChI &&
1563 : : /* non-taut isotopic */ /* non-taut non-isotopic */
1564 [ # # # # : 0 : ( Stereo = pINChI->StereoIsotopic ) && ( Stereo_Taut = pINChI->Stereo ) &&
# # # # ]
1565 : 0 : Eql_INChI_Stereo( Stereo, EQL_SP2, Stereo_Taut, EQL_SP2, 0 );
1566 : : /* stereo isotopic non-taut = non-taut (stereo) */
1567 [ # # ]: 0 : eq2taut = eq2taut ? ( iiSTEREO | iitISO | iitNONTAUT | iiEq2NONTAUT ) : 0;
1568 : : }
1569 : : /* b) compare non-tautomeric isotopic to tautomeric non-isotopic */
1570 [ # # ]: 0 : if (!eq2taut)
1571 : : {
1572 [ # # ]: 0 : eq2taut = pINChI && pINChI_Taut &&
1573 : : /* non-taut isotopic */ /* taut non-isotopic */
1574 [ # # # # : 0 : ( Stereo = pINChI->StereoIsotopic ) && ( Stereo_Taut = pINChI_Taut->Stereo ) &&
# # # # ]
1575 : 0 : Eql_INChI_Stereo( Stereo, EQL_SP2, Stereo_Taut, EQL_SP2, 0 );
1576 : : /* stereo isotopic non-taut = taut (stereo) */
1577 [ # # ]: 0 : eq2taut = eq2taut ? ( iiSTEREO | iitISO | iitNONTAUT ) : 0;
1578 : : }
1579 : : /* c) compare non-tautomeric isotopic to tautomeric isotopic */
1580 [ # # # # : 0 : if (!eq2taut && bSecondNonTautPass && bOmitRepetitions)
# # ]
1581 : : {
1582 [ # # ]: 0 : eq2taut = pINChI && pINChI_Taut &&
1583 [ # # # # : 0 : ( Stereo = pINChI->StereoIsotopic ) && ( Stereo_Taut = pINChI_Taut->StereoIsotopic ) &&
# # # # ]
1584 : 0 : Eql_INChI_Stereo( Stereo, EQL_SP2, Stereo_Taut, EQL_SP2, 0 );
1585 : : /* stereo isotopic non-taut = isotopic taut (stereo) */
1586 [ # # ]: 0 : eq2taut = eq2taut ? ( iiSTEREO | iitISO | iitNONTAUT | iiEq2ISO ) : 0;
1587 : : }
1588 : : #if ( FIX_EMPTY_LAYER_BUG == 1 )
1589 : : if (!eq2taut && pINChI && !( ( Stereo = pINChI->StereoIsotopic ) &&
1590 : : Eql_INChI_Stereo( Stereo, EQL_SP2, NULL, EQL_EXISTS, 0 ) ))
1591 : : {
1592 : : /* component has no stereo; check whether it has stereo in the preceding layers */
1593 : : if (pINChI_Taut && ( Stereo_Taut = pINChI_Taut->Stereo ) && /* F is not empty */
1594 : : Eql_INChI_Stereo( Stereo_Taut, EQL_SP2, NULL, EQL_EXISTS, 0 ) ||
1595 : : !( pINChI_Taut && ( Stereo_Taut = pINChI_Taut->Stereo ) && /* M is empty and ... */
1596 : : Eql_INChI_Stereo( Stereo_Taut, EQL_SP2, NULL, EQL_EXISTS, 0 ) ) &&
1597 : : ( pINChI_Taut && ( Stereo_Taut = pINChI_Taut->StereoIsotopic ) && /* ... MI is not empty */
1598 : : Eql_INChI_Stereo( Stereo_Taut, EQL_SP2, NULL, EQL_EXISTS, 0 ) ))
1599 : : {
1600 : :
1601 : : eq2taut = iiEmpty; /* the component has stereo in the preceding layer */
1602 : : }
1603 : : }
1604 : : #endif
1605 : : }
1606 : : else
1607 : : {
1608 : : /*========= if not bSecondNonTautPass then compare iso taut stereo to non-iso taut ========*/
1609 [ # # # # ]: 0 : if (!bSecondNonTautPass && bOmitRepetitions)
1610 : : {
1611 : : /* compare tautomeric isotopic to tautomeric non-isotopic */
1612 [ # # ]: 0 : if (!eq2taut)
1613 : : {
1614 : 0 : eq2taut = pINChI &&
1615 : : /* taut isotopic */ /* taut non-isotopic */
1616 [ # # # # : 0 : ( Stereo = pINChI->StereoIsotopic ) && ( Stereo_Taut = pINChI->Stereo ) &&
# # # # ]
1617 : 0 : Eql_INChI_Stereo( Stereo, EQL_SP2, Stereo_Taut, EQL_SP2, 0 );
1618 : : /* stereo isotopic taut = taut (stereo) */
1619 [ # # ]: 0 : eq2taut = eq2taut ? ( iiSTEREO | iitISO ) : 0;
1620 : : #if ( FIX_EMPTY_LAYER_BUG == 1 )
1621 : : if (!eq2taut && pINChI && !( ( Stereo = pINChI->StereoIsotopic ) &&
1622 : : Eql_INChI_Stereo( Stereo, EQL_SP2, NULL, EQL_EXISTS, 0 ) ))
1623 : : {
1624 : : /* component has no MI stereo; check whether it has stereo in the preceding layer M */
1625 : : if (( Stereo_Taut = pINChI->Stereo ) &&
1626 : : Eql_INChI_Stereo( Stereo_Taut, EQL_SP2, NULL, EQL_EXISTS, 0 ))
1627 : : {
1628 : : eq2taut = iiEmpty; /* the component has stereo in the preceding layer */
1629 : : }
1630 : : }
1631 : : #endif
1632 : : }
1633 : : }
1634 : : }
1635 [ # # ]: 0 : if (eq2taut)
1636 : : {
1637 : : /* we may be here only in case of the current layer found equal in another layer the same component */
1638 [ # # # # ]: 0 : if (pINChI_Prev && pINChI_Prev->nNumberOfAtoms)
1639 : : {
1640 : : /* previous component exists; output it before output the current component */
1641 [ # # ]: 0 : if (bNext++)
1642 : : {
1643 : 0 : MakeDelim( sCompDelim, strbuf, bOverflow );
1644 : : }
1645 [ # # # # ]: 0 : if (( Stereo_Prev = pINChI_Prev->StereoIsotopic ) && Stereo_Prev->nNumberOfStereoBonds > 0)
1646 : : {
1647 : 0 : MakeMult( mult + 1, "*", strbuf, 0, bOverflow );
1648 : :
1649 : 0 : MakeStereoString( Stereo_Prev->nBondAtom1, Stereo_Prev->nBondAtom2,
1650 : : Stereo_Prev->b_parity,
1651 : : 0, Stereo_Prev->nNumberOfStereoBonds,
1652 : : strbuf, TAUT_MODE, bOverflow );
1653 : : }
1654 : : }
1655 : : else
1656 : : {
1657 [ # # # # ]: 0 : if (pINChI_Taut_Prev && pINChI_Taut_Prev->nNumberOfAtoms)
1658 : : {
1659 : : /* previous non-taut component exists only in taut list */
1660 [ # # ]: 0 : if (bNext++)
1661 : : {
1662 : 0 : MakeDelim( sCompDelim, strbuf, bOverflow );
1663 : : }
1664 : : /* do not output stereo of non-tautomeric in non-taut layer: it has been output in the main layer */
1665 : : }
1666 : : }
1667 : : /* we have found another (previously printed) layer of the current component equal to this layer */
1668 : : /* output this (current) equivalence mark = EquString(eq2taut) */
1669 : 0 : pCurrEquStr = EquString( eq2taut );
1670 [ # # # # ]: 0 : if (multPrevEquStr && pPrevEquStr)
1671 : : {
1672 [ # # # # ]: 0 : if (pCurrEquStr && !strcmp( pCurrEquStr, pPrevEquStr ))
1673 : : {
1674 : 0 : multPrevEquStr++;
1675 : : }
1676 : : else
1677 : : {
1678 : : /* new EqStr is different; output it */
1679 [ # # ]: 0 : if (bNext++)
1680 : : {
1681 : 0 : MakeDelim( sCompDelim, strbuf, bOverflow );
1682 : : }
1683 : 0 : MakeEqStr( pPrevEquStr, multPrevEquStr, strbuf, bOverflow );
1684 : 0 : pPrevEquStr = pCurrEquStr;
1685 : 0 : multPrevEquStr = 1;
1686 : : }
1687 : : }
1688 : : else
1689 : : {
1690 : 0 : pPrevEquStr = pCurrEquStr;
1691 : 0 : multPrevEquStr = 1;
1692 : : }
1693 : 0 : pINChI_Prev = NULL; /* pINChI_Prev sp2 does not exist since */
1694 : 0 : pINChI_Taut_Prev = NULL; /* pINChI has just been printed */
1695 : 0 : mult = 0;
1696 : 0 : eq2tautPrev = 1; /* pINChI_Prev and pINChI_Taut_Prev have already been */
1697 : : }
1698 : : else
1699 : : {
1700 [ # # ]: 0 : if (eq2tautPrev)
1701 : : {
1702 : : /* at this point pINChI_Prev does not exist; however, pINChI */
1703 : : /*might have been discovered and it is different from pINChI_Taut */
1704 [ # # # # ]: 0 : if (multPrevEquStr && pPrevEquStr)
1705 : : {
1706 : : /* new EqStr is different; output it */
1707 [ # # ]: 0 : if (bNext++)
1708 : : {
1709 : 0 : MakeDelim( sCompDelim, strbuf, bOverflow );
1710 : : }
1711 : 0 : MakeEqStr( pPrevEquStr, multPrevEquStr, strbuf, bOverflow );
1712 : 0 : pPrevEquStr = NULL;
1713 : 0 : multPrevEquStr = 0;
1714 : : }
1715 : 0 : eq2tautPrev = 0;
1716 : 0 : pINChI_Prev = pINChI;
1717 : 0 : pINChI_Taut_Prev = pINChI_Taut;
1718 : 0 : mult = 0;
1719 : : }
1720 : : else
1721 : : {
1722 : : /* current layer is different from previously printed layers of the current component */
1723 : : /* compare the current layer to this layer of the previous component: */
1724 : : /* check whether pINChI and pINChI_Prev have non-zero identical stereo sp2 */
1725 : : /*================ compare iso sp2 to previous =====================*/
1726 [ # # ]: 0 : eq2prev = bUseMulipliers &&
1727 [ # # ]: 0 : pINChI && pINChI_Prev &&
1728 [ # # # # : 0 : ( Stereo = pINChI->StereoIsotopic ) && ( Stereo_Prev = pINChI_Prev->StereoIsotopic ) &&
# # # # ]
1729 : 0 : Eql_INChI_Stereo( Stereo, EQL_SP2, Stereo_Prev, EQL_SP2, 0 );
1730 [ # # ]: 0 : if (eq2prev)
1731 : : {
1732 : 0 : mult++; /* mult = (number of non-empty equal items)-1 */
1733 : 0 : continue;
1734 : : }
1735 : : else
1736 : : {
1737 : : /* the current layer is different from this layer of the previous component */
1738 : : /* therefore print the current layer */
1739 [ # # ]: 0 : if (bNext++)
1740 : : {
1741 : 0 : MakeDelim( sCompDelim, strbuf, bOverflow );
1742 : : }
1743 [ # # # # ]: 0 : if (pINChI_Prev && pINChI_Prev->nNumberOfAtoms)
1744 : : {
1745 [ # # # # ]: 0 : if (( Stereo_Prev = pINChI_Prev->StereoIsotopic ) && Stereo_Prev->nNumberOfStereoBonds > 0)
1746 : : {
1747 : 0 : MakeMult( mult + 1, "*", strbuf, 0, bOverflow );
1748 : :
1749 : 0 : MakeStereoString( Stereo_Prev->nBondAtom1, Stereo_Prev->nBondAtom2,
1750 : : Stereo_Prev->b_parity,
1751 : : 0, Stereo_Prev->nNumberOfStereoBonds,
1752 : : strbuf, TAUT_MODE, bOverflow );
1753 : : }
1754 : : /* else sp2 info is not present in pINChI_Prev */
1755 : : }
1756 : : else
1757 : : {/* do not print pINChI_Prev because it either do not exist of have already been printed */
1758 [ # # # # : 0 : if (bSecondNonTautPass && pINChI_Taut_Prev && pINChI_Taut_Prev->nNumberOfAtoms)
# # ]
1759 : : {
1760 [ # # ]: 0 : if (( Stereo_Taut_Prev = pINChI_Taut_Prev->StereoIsotopic ) && Stereo_Taut_Prev->nNumberOfStereoBonds > 0)
1761 : : {
1762 : : /* since pINChI_Prev does not exist, pINChI_Taut_Prev is non-tautomeric */
1763 : : /* and it has non-trivial sp2 info */
1764 : : /*
1765 : : tot_len += MakeDelim( sIdenticalValues, strbuf, bOverflow);
1766 : : */
1767 : : ;/* pINChI_Taut_Prev sp3 info was output in the main stereo section */
1768 : : }
1769 : : else
1770 : : {
1771 : : ; /* pINChI_Taut_Prev exists and has not sp2 info */
1772 : : }
1773 : : }
1774 : : #if ( bRELEASE_VERSION != 1 && defined(_DEBUG) )
1775 : : else
1776 : : {
1777 : : int stop = 1; /* <BRKPT> */
1778 : : }
1779 : : #endif
1780 : : }
1781 : : }
1782 : 0 : pINChI_Prev = pINChI;
1783 : 0 : pINChI_Taut_Prev = pINChI_Taut;
1784 : 0 : mult = 0; /* we do not know whether the item is empty */
1785 : : }
1786 : : }
1787 : : }
1788 : :
1789 : 0 : return ( strbuf->nUsedLength - nUsedLength0 );
1790 : : }
1791 : :
1792 : :
1793 : : /****************************************************************************
1794 : : Produce isotopic-tetr stereo substring of the whole structure InChI string.
1795 : : ****************************************************************************/
1796 : 0 : int str_IsoSp3( INCHI_SORT *pINChISort,
1797 : : INCHI_SORT *pINChISort2,
1798 : : INCHI_IOS_STRING *strbuf,
1799 : : int *bOverflow,
1800 : : int bOutType,
1801 : : int TAUT_MODE,
1802 : : int num_components,
1803 : : int bRelRac,
1804 : : int bSecondNonTautPass,
1805 : : int bOmitRepetitions,
1806 : : int bUseMulipliers )
1807 : : {
1808 : : int i, ii, ii2, nUsedLength0;
1809 : : INCHI_SORT *is, *is2, *is0, *is20;
1810 : : INChI *pINChI, *pINChI_Prev, *pINChI_Taut, *pINChI_Taut_Prev;
1811 : : INChI_Stereo *Stereo, *Stereo_Prev, *Stereo_Taut, *Stereo_Taut_Prev;
1812 : : int mult, eq2prev, eq2taut, eq2tautPrev, bNext;
1813 : : const char *pPrevEquStr, *pCurrEquStr;
1814 : : int multPrevEquStr;
1815 : 0 : pINChI_Taut = NULL;
1816 : 0 : pINChI_Prev = NULL;
1817 : 0 : pINChI_Taut_Prev = NULL;
1818 : 0 : mult = 0;
1819 : 0 : bNext = 0;
1820 : 0 : is = NULL;
1821 : 0 : is2 = NULL;
1822 : 0 : is0 = pINChISort;
1823 [ # # ]: 0 : is20 = bSecondNonTautPass ? pINChISort2 : NULL;
1824 : : /* djb-rwth: removing redundant code */
1825 : 0 : eq2tautPrev = 1; /* pINChI_Prev (previous pINChI) does not exist */
1826 : 0 : pPrevEquStr = NULL; /*, *pCurrEquStr;*/
1827 : 0 : multPrevEquStr = 0;
1828 : : #if ( REL_RAC_STEREO_IGN_1_SC == 1 )
1829 : : #else
1830 : 0 : bRelRac = 0;
1831 : : #endif
1832 : 0 : nUsedLength0 = strbuf->nUsedLength;
1833 : :
1834 : : /* For each connected component... */
1835 [ # # ]: 0 : for (i = 0; i <= num_components; i++)
1836 : : {
1837 : :
1838 : : /* 1st (taut) pass: bOutType=OUT_TN ; 2nd (non-taut pass) bOutType=OUT_NT */
1839 [ # # # # : 0 : pINChI = ( i < num_components && ( is = is0 + i, 0 <= ( ii = GET_II( bOutType, is ) ) ) ) ? is->pINChI[ii] : NULL;
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # ]
1840 : : /*================ compare sp2 to previous =====================*/
1841 [ # # ]: 0 : if (bSecondNonTautPass)
1842 : : {
1843 : : /* component that was output on the 1st pass */
1844 [ # # # # : 0 : pINChI_Taut = ( i < num_components && ( is2 = is20 + i, 0 <= ( ii2 = GET_II( OUT_T1, is2 ) ) ) ) ? is2->pINChI[ii2] : NULL;
# # # # #
# # # ]
1845 : : }
1846 : 0 : eq2taut = 0;
1847 : : /*========= if bSecondNonTautPass then compare iso non-taut stereo to other stereo ========*/
1848 [ # # # # ]: 0 : if (bSecondNonTautPass && bOmitRepetitions)
1849 : : {
1850 : : /* compare non-tautomeric isotopic to:
1851 : : * a) non-tautomeric non-isotopic
1852 : : * b) tautomeric non-isotopic
1853 : : * c) tautomeric isotopic
1854 : : */
1855 : : /* a) compare non-tautomeric isotopic to non-tautomeric non-isotopic */
1856 [ # # ]: 0 : if (!eq2taut)
1857 : : {
1858 : 0 : eq2taut = pINChI && /* non-taut isotopic */ /* non-taut non-isotopic */
1859 [ # # # # : 0 : ( Stereo = pINChI->StereoIsotopic ) && ( Stereo_Taut = pINChI->Stereo ) &&
# # # # ]
1860 : 0 : Eql_INChI_Stereo( Stereo, EQL_SP3, Stereo_Taut, EQL_SP3, bRelRac );
1861 : : /* stereo isotopic non-taut = non-taut (stereo) */
1862 [ # # ]: 0 : eq2taut = eq2taut ? ( iiSTEREO | iitISO | iitNONTAUT | iiEq2NONTAUT ) : 0;
1863 : : }
1864 : : /* b) compare non-tautomeric isotopic to tautomeric non-isotopic */
1865 [ # # ]: 0 : if (!eq2taut)
1866 : : {
1867 [ # # ]: 0 : eq2taut = pINChI && pINChI_Taut &&
1868 : : /* non-taut isotopic */ /* taut non-isotopic */
1869 [ # # # # : 0 : ( Stereo = pINChI->StereoIsotopic ) && ( Stereo_Taut = pINChI_Taut->Stereo ) &&
# # # # ]
1870 : 0 : Eql_INChI_Stereo( Stereo, EQL_SP3, Stereo_Taut, EQL_SP3, bRelRac );
1871 : : /* stereo isotopic non-taut = taut (stereo) */
1872 [ # # ]: 0 : eq2taut = eq2taut ? ( iiSTEREO | iitISO | iitNONTAUT ) : 0;
1873 : : }
1874 : : /* c) compare non-tautomeric isotopic to tautomeric isotopic */
1875 [ # # # # : 0 : if (!eq2taut && bSecondNonTautPass && bOmitRepetitions)
# # ]
1876 : : {
1877 [ # # ]: 0 : eq2taut = pINChI && pINChI_Taut &&
1878 [ # # # # : 0 : ( Stereo = pINChI->StereoIsotopic ) && ( Stereo_Taut = pINChI_Taut->StereoIsotopic ) &&
# # # # ]
1879 : 0 : Eql_INChI_Stereo( Stereo, EQL_SP3, Stereo_Taut, EQL_SP3, bRelRac );
1880 : : /* stereo isotopic non-taut = isotopic taut (stereo) */
1881 [ # # ]: 0 : eq2taut = eq2taut ? ( iiSTEREO | iitISO | iitNONTAUT | iiEq2ISO ) : 0;
1882 : : }
1883 : : #if ( FIX_EMPTY_LAYER_BUG == 1 )
1884 : : if (!eq2taut && pINChI && !( ( Stereo = pINChI->StereoIsotopic ) &&
1885 : : Eql_INChI_Stereo( Stereo, EQL_SP3, NULL, EQL_EXISTS, 0 ) ))
1886 : : {
1887 : : /* component has no stereo; check whether it has stereo in the preceding layers */
1888 : : if (pINChI_Taut && ( Stereo_Taut = pINChI_Taut->Stereo ) && /* F is not empty */
1889 : : Eql_INChI_Stereo( Stereo_Taut, EQL_SP3, NULL, EQL_EXISTS, 0 ) ||
1890 : : !( pINChI_Taut && ( Stereo_Taut = pINChI_Taut->Stereo ) && /* M is empty and ... */
1891 : : Eql_INChI_Stereo( Stereo_Taut, EQL_SP3, NULL, EQL_EXISTS, 0 ) ) &&
1892 : : ( pINChI_Taut && ( Stereo_Taut = pINChI_Taut->StereoIsotopic ) && /* ... MI is not empty */
1893 : : Eql_INChI_Stereo( Stereo_Taut, EQL_SP3, NULL, EQL_EXISTS, 0 ) ))
1894 : : {
1895 : :
1896 : : eq2taut = iiEmpty; /* the component has stereo in the preceding layer */
1897 : : }
1898 : : }
1899 : : #endif
1900 : : }
1901 : : else
1902 : : {
1903 : : /*========= if not bSecondNonTautPass then compare iso taut stereo to non-iso taut ========*/
1904 [ # # # # ]: 0 : if (!bSecondNonTautPass && bOmitRepetitions)
1905 : : {
1906 : : /* compare tautomeric isotopic to tautomeric non-isotopic */
1907 [ # # ]: 0 : if (!eq2taut)
1908 : : {
1909 : 0 : eq2taut = pINChI &&
1910 : : /* taut isotopic */ /* taut non-isotopic */
1911 [ # # # # : 0 : ( Stereo = pINChI->StereoIsotopic ) && ( Stereo_Taut = pINChI->Stereo ) &&
# # # # ]
1912 : 0 : Eql_INChI_Stereo( Stereo, EQL_SP3, Stereo_Taut, EQL_SP3, bRelRac );
1913 : : /* stereo isotopic taut = taut (stereo) */
1914 [ # # ]: 0 : eq2taut = eq2taut ? ( iiSTEREO | iitISO ) : 0;
1915 : : #if ( FIX_EMPTY_LAYER_BUG == 1 )
1916 : : if (!eq2taut && pINChI && !( ( Stereo = pINChI->StereoIsotopic ) &&
1917 : : Eql_INChI_Stereo( Stereo, EQL_SP3, NULL, EQL_EXISTS, 0 ) ))
1918 : : {
1919 : : /* component has no MI stereo; check whether it has stereo in the preceding layer M */
1920 : : if (( Stereo_Taut = pINChI->Stereo ) &&
1921 : : Eql_INChI_Stereo( Stereo_Taut, EQL_SP3, NULL, EQL_EXISTS, 0 ))
1922 : : {
1923 : : eq2taut = iiEmpty; /* the component has stereo in the preceding layer */
1924 : : }
1925 : : }
1926 : : #endif
1927 : : }
1928 : : }
1929 : : }
1930 [ # # ]: 0 : if (eq2taut)
1931 : : {
1932 : : /* we may be here only in case of the current layer found equal in another layer the same component */
1933 [ # # # # ]: 0 : if (pINChI_Prev && pINChI_Prev->nNumberOfAtoms)
1934 : : {
1935 : : /* previous component exists; output it before output the current component */
1936 [ # # ]: 0 : if (bNext++)
1937 : : {
1938 : 0 : MakeDelim( sCompDelim, strbuf, bOverflow );
1939 : : }
1940 [ # # # # ]: 0 : if (( Stereo_Prev = pINChI_Prev->StereoIsotopic ) && Stereo_Prev->nNumberOfStereoCenters > bRelRac)
1941 : : {
1942 : 0 : MakeMult( mult + 1, "*", strbuf, 0, bOverflow );
1943 : :
1944 : 0 : MakeStereoString( Stereo_Prev->nNumber, NULL, Stereo_Prev->t_parity,
1945 : : 0, Stereo_Prev->nNumberOfStereoCenters,
1946 : : strbuf, TAUT_MODE, bOverflow );
1947 : : }
1948 : : }
1949 : : else
1950 : : {
1951 [ # # # # ]: 0 : if (pINChI_Taut_Prev && pINChI_Taut_Prev->nNumberOfAtoms)
1952 : : {
1953 : : /* previous non-taut component exists only in taut list */
1954 [ # # ]: 0 : if (bNext++)
1955 : : {
1956 : 0 : MakeDelim( sCompDelim, strbuf, bOverflow );
1957 : : }
1958 : : /* do not output stereo of non-tautomeric in non-taut layer: it has been output in the main layer */
1959 : : }
1960 : : }
1961 : : /* we have found another (previously printed) layer of the current component equal to this layer */
1962 : : /* output this (current) equivalence mark = EquString(eq2taut) */
1963 : 0 : pCurrEquStr = EquString( eq2taut );
1964 [ # # # # ]: 0 : if (multPrevEquStr && pPrevEquStr)
1965 : : {
1966 [ # # # # ]: 0 : if (pCurrEquStr && !strcmp( pCurrEquStr, pPrevEquStr ))
1967 : : {
1968 : 0 : multPrevEquStr++;
1969 : : }
1970 : : else
1971 : : {
1972 : : /* new EqStr is different; output it */
1973 [ # # ]: 0 : if (bNext++)
1974 : : {
1975 : 0 : MakeDelim( sCompDelim, strbuf, bOverflow );
1976 : : }
1977 : 0 : MakeEqStr( pPrevEquStr, multPrevEquStr, strbuf, bOverflow );
1978 : 0 : pPrevEquStr = pCurrEquStr;
1979 : 0 : multPrevEquStr = 1;
1980 : : }
1981 : : }
1982 : : else
1983 : : {
1984 : 0 : pPrevEquStr = pCurrEquStr;
1985 : 0 : multPrevEquStr = 1;
1986 : : }
1987 : 0 : pINChI_Prev = NULL; /* pINChI_Prev sp2 does not exist since */
1988 : 0 : pINChI_Taut_Prev = NULL; /* pINChI has just been printed */
1989 : 0 : mult = 0;
1990 : 0 : eq2tautPrev = 1; /* pINChI_Prev and pINChI_Taut_Prev have already been output */
1991 : : }
1992 : : else
1993 : : {
1994 [ # # ]: 0 : if (eq2tautPrev)
1995 : : {
1996 : : /* at this point pINChI_Prev does not exist; however, pINChI */
1997 : : /*might have been discovered and it is different from pINChI_Taut */
1998 [ # # # # ]: 0 : if (multPrevEquStr && pPrevEquStr)
1999 : : {
2000 : : /* new EqStr is different; output it */
2001 [ # # ]: 0 : if (bNext++)
2002 : : {
2003 : 0 : MakeDelim( sCompDelim, strbuf, bOverflow );
2004 : : }
2005 : 0 : MakeEqStr( pPrevEquStr, multPrevEquStr, strbuf, bOverflow );
2006 : 0 : pPrevEquStr = NULL;
2007 : 0 : multPrevEquStr = 0;
2008 : : }
2009 : 0 : eq2tautPrev = 0;
2010 : 0 : pINChI_Prev = pINChI;
2011 : 0 : pINChI_Taut_Prev = pINChI_Taut;
2012 : 0 : mult = 0;
2013 : : }
2014 : : else
2015 : : {
2016 : : /* current layer is different from previously printed layers of the current component */
2017 : : /* compare the current layer to this layer of the previous component: */
2018 : : /* check whether pINChI and pINChI_Prev have non-zero identical stereo sp2 */
2019 : : /*================ compare iso sp3 to previous =====================*/
2020 [ # # # # ]: 0 : eq2prev = bUseMulipliers && pINChI && pINChI_Prev &&
2021 [ # # # # : 0 : ( Stereo = pINChI->StereoIsotopic ) && ( Stereo_Prev = pINChI_Prev->StereoIsotopic ) &&
# # # # ]
2022 : 0 : Eql_INChI_Stereo( Stereo, EQL_SP3, Stereo_Prev, EQL_SP3, bRelRac );
2023 [ # # ]: 0 : if (eq2prev)
2024 : : {
2025 : 0 : mult++; /* mult = (number of non-empty equal items)-1 */
2026 : 0 : continue;
2027 : : }
2028 : : else
2029 : : {
2030 [ # # ]: 0 : if (bNext++)
2031 : : {
2032 : 0 : MakeDelim( sCompDelim, strbuf, bOverflow );
2033 : : }
2034 [ # # # # ]: 0 : if (pINChI_Prev && pINChI_Prev->nNumberOfAtoms)
2035 : : {
2036 [ # # # # ]: 0 : if (( Stereo_Prev = pINChI_Prev->StereoIsotopic ) && Stereo_Prev->nNumberOfStereoCenters > bRelRac)
2037 : : {
2038 : 0 : MakeMult( mult + 1, "*", strbuf, 0, bOverflow );
2039 : :
2040 : 0 : MakeStereoString( Stereo_Prev->nNumber, NULL, Stereo_Prev->t_parity,
2041 : : 0, Stereo_Prev->nNumberOfStereoCenters,
2042 : : strbuf, TAUT_MODE, bOverflow );
2043 : : }
2044 : : /* else sp3 info is not present in pINChI_Prev */
2045 : : }
2046 : : else
2047 : : /* do not print pINChI_Prev because it either do not exist of have already been printed */
2048 [ # # # # : 0 : if (bSecondNonTautPass && pINChI_Taut_Prev && pINChI_Taut_Prev->nNumberOfAtoms)
# # ]
2049 : : {
2050 [ # # ]: 0 : if (( Stereo_Taut_Prev = pINChI_Taut_Prev->StereoIsotopic ) && Stereo_Taut_Prev->nNumberOfStereoCenters > bRelRac)
2051 : : {
2052 : : /* since pINChI_Prev does not exist, pINChI_Taut_Prev is non-tautomeric */
2053 : : /* and it has non-trivial sp2 info */
2054 : : /*
2055 : : tot_len += MakeDelim( sIdenticalValues, strbuf, bOverflow);
2056 : : */
2057 : : ;/* pINChI_Taut_Prev sp3 info was output in the main stereo section */
2058 : : }
2059 : : else
2060 : : {
2061 : : ; /* pINChI_Taut_Prev exists and has not sp3 info */
2062 : : }
2063 : : }
2064 : : #if ( bRELEASE_VERSION != 1 && defined(_DEBUG) )
2065 : : else
2066 : : {
2067 : : int stop = 1; /* <BRKPT> */
2068 : : }
2069 : : #endif
2070 : : }
2071 : 0 : pINChI_Prev = pINChI;
2072 : 0 : pINChI_Taut_Prev = pINChI_Taut;
2073 : 0 : mult = 0; /* we do not know whether the item is empty */
2074 : : }
2075 : : }
2076 : : }
2077 : :
2078 : 0 : return ( strbuf->nUsedLength - nUsedLength0 );
2079 : : }
2080 : :
2081 : :
2082 : : /****************************************************************************
2083 : : Output isotopic abs stero inversion substring
2084 : : of the whole structure InChI string
2085 : : ****************************************************************************/
2086 : 0 : int str_IsoStereoAbsInv( INCHI_SORT *pINChISort,
2087 : : INCHI_IOS_STRING *strbuf,
2088 : : int *bOverflow,
2089 : : int bOutType,
2090 : : int num_components )
2091 : : {
2092 : : int i, j, ii, nUsedLength0;
2093 : : INCHI_SORT *is, *is0;
2094 : : INChI_Stereo *Stereo;
2095 : : INChI *pINChI;
2096 : :
2097 : 0 : is = NULL;
2098 : 0 : is0 = pINChISort;
2099 : 0 : nUsedLength0 = strbuf->nUsedLength;
2100 : :
2101 : : /* For each connected component... */
2102 [ # # # # ]: 0 : for (i = 0; !*bOverflow && i < num_components; i++)
2103 : : {
2104 : 0 : is = is0 + i;
2105 [ # # # # : 0 : pINChI = ( 0 <= ( ii = GET_II( bOutType, is ) ) )
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # #
# ]
2106 : : ? is->pINChI[ii]
2107 [ # # ]: 0 : : NULL;
2108 [ # # ]: 0 : if (pINChI &&
2109 [ # # ]: 0 : ( Stereo = pINChI->StereoIsotopic ) &&
2110 [ # # ]: 0 : ( j = Stereo->nCompInv2Abs ))
2111 : : {
2112 [ # # ]: 0 : MakeDelim( j < 0 ? "1" : "0", strbuf, bOverflow );
2113 : : }
2114 : : else
2115 : : {
2116 : 0 : MakeDelim( ".", strbuf, bOverflow );
2117 : : }
2118 : : }
2119 : :
2120 : 0 : return ( strbuf->nUsedLength - nUsedLength0 );
2121 : : }
2122 : :
2123 : :
2124 : :
2125 : : /*
2126 : : Generate AuxInfo substrings
2127 : : */
2128 : :
2129 : :
2130 : :
2131 : : /****************************************************************************
2132 : : Produce equivalence substring of AuxInfo
2133 : : ****************************************************************************/
2134 : 13 : int str_AuxEqu( INCHI_SORT *pINChISort,
2135 : : INCHI_SORT *pINChISort2,
2136 : : INCHI_IOS_STRING *strbuf,
2137 : : int *bOverflow,
2138 : : int bOutType,
2139 : : int TAUT_MODE,
2140 : : int num_components,
2141 : : int bSecondNonTautPass,
2142 : : int bOmitRepetitions,
2143 : : int bUseMulipliers )
2144 : : {
2145 : : int i, ii, ii2, nUsedLength0;
2146 : : INCHI_SORT *is, *is2, *is0, *is20;
2147 : 13 : INChI_Aux *pINChI_Aux = NULL, *pINChI_Aux_Prev, *pINChI_Aux_Taut, *pINChI_Aux_Taut_Prev;
2148 : : int mult, eq2prev, eq2taut, eq2tautPrev, bNext;
2149 : : const char *pPrevEquStr, *pCurrEquStr;
2150 : : int multPrevEquStr;
2151 : 13 : pINChI_Aux_Prev = NULL;
2152 : 13 : pINChI_Aux_Taut = NULL;
2153 : 13 : pINChI_Aux_Taut_Prev = NULL;
2154 : :
2155 : 13 : mult = 0;
2156 : 13 : bNext = 0;
2157 : 13 : is = NULL;
2158 : 13 : is2 = NULL;
2159 : 13 : is0 = pINChISort;
2160 [ - + ]: 13 : is20 = bSecondNonTautPass ? pINChISort2 : NULL;
2161 : : /* djb-rwth: removing redundant code */
2162 : 13 : eq2tautPrev = 1; /* pINChI_Aux_Prev (previous pINChI_Aux) does not exist */
2163 : 13 : pPrevEquStr = NULL; /*, *pCurrEquStr;*/
2164 : 13 : multPrevEquStr = 0;
2165 : 13 : nUsedLength0 = strbuf->nUsedLength;
2166 : :
2167 : : /* For each connected component... */
2168 [ + + ]: 47 : for (i = 0; i <= num_components; i++)
2169 : : {
2170 : :
2171 : : /* 1st (taut) pass: bOutType=OUT_TN ; 2nd (non-taut pass) bOutType=OUT_NT */
2172 [ + + - + : 34 : pINChI_Aux = ( i < num_components && ( is = is0 + i, 0 <= ( ii = GET_II( bOutType, is ) ) ) ) ? is->pINChI_Aux[ii] : NULL;
- - - - -
- - - - -
- - + - +
- + - - +
- - - - -
- - - - -
- - - - -
- - - - -
- - - - -
- - - - -
- - + - ]
2173 [ - + ]: 34 : if (bSecondNonTautPass)
2174 : : {
2175 : : /* component that was output on the 1st pass */
2176 [ # # # # : 0 : pINChI_Aux_Taut = ( i < num_components && ( is2 = is20 + i, 0 <= ( ii2 = GET_II( OUT_T1, is2 ) ) ) ) ? is2->pINChI_Aux[ii2] : NULL;
# # # # #
# # # ]
2177 : : }
2178 : : /*================ compare non-iso non-taut equivalence info to non-iso taut ========*/
2179 [ - + - - : 34 : eq2taut = bSecondNonTautPass && bOmitRepetitions &&
- - ]
2180 : 0 : Eql_INChI_Aux_Equ( pINChI_Aux, EQL_EQU, pINChI_Aux_Taut, EQL_EQU );
2181 [ - + ]: 34 : eq2taut = eq2taut ? ( iiEQU | iitNONTAUT ) : 0;
2182 [ - + ]: 34 : if (eq2taut)
2183 : : {
2184 : : /* we may be here only in case of the second (non-taut) pass */
2185 : : /* current non-taut equivalence has been found to be same as tautomeric */
2186 [ # # # # ]: 0 : if (pINChI_Aux_Prev && pINChI_Aux_Prev->nNumberOfAtoms)
2187 : : {
2188 : : /* previous component exists */
2189 [ # # ]: 0 : if (bNext++)
2190 : : {
2191 : 0 : MakeDelim( sCompDelim, strbuf, bOverflow );
2192 : : }
2193 [ # # ]: 0 : if (bHasEquString( pINChI_Aux_Prev->nConstitEquNumbers, pINChI_Aux_Prev->nNumberOfAtoms ))
2194 : : {
2195 : : /* output previous component(s) equivalence since it was found to be non-trivial */
2196 : 0 : MakeMult( mult + 1, "*", strbuf, 0, bOverflow );
2197 : 0 : MakeEquString( pINChI_Aux_Prev->nConstitEquNumbers,
2198 : : pINChI_Aux_Prev->nNumberOfAtoms,
2199 : : 0, strbuf, TAUT_MODE, bOverflow );
2200 : : }
2201 : : else
2202 : : {
2203 : : ; /* pINChI_Aux_Prev exists and has only trivial equivalence info */
2204 : : }
2205 : : }
2206 : : else
2207 [ # # # # ]: 0 : if (pINChI_Aux_Taut_Prev && pINChI_Aux_Taut_Prev->nNumberOfAtoms)
2208 : : {
2209 : : /* previous non-taut component exists only in taut list */
2210 [ # # ]: 0 : if (bNext++)
2211 : : {
2212 : 0 : MakeDelim( sCompDelim, strbuf, bOverflow );
2213 : : }
2214 : : }
2215 : : /* we have found pINChI_Aux->nConstitEquNumbers same as in pINChI_Aux_Taut */
2216 : : /* output this (current) equivalence as '*', that is, same as tautomeric */
2217 : : /* that was printed on the 1st pass. */
2218 : 0 : pCurrEquStr = EquString( eq2taut );
2219 [ # # # # ]: 0 : if (multPrevEquStr && pPrevEquStr)
2220 : : {
2221 [ # # # # ]: 0 : if (pCurrEquStr && !strcmp( pCurrEquStr, pPrevEquStr ))
2222 : : {
2223 : 0 : multPrevEquStr++;
2224 : : }
2225 : : else
2226 : : {
2227 : : /* new EqStr is different; output it */
2228 [ # # ]: 0 : if (bNext++)
2229 : : {
2230 : 0 : MakeDelim( sCompDelim, strbuf, bOverflow );
2231 : : }
2232 : 0 : MakeEqStr( pPrevEquStr, multPrevEquStr, strbuf, bOverflow );
2233 : 0 : pPrevEquStr = pCurrEquStr;
2234 : 0 : multPrevEquStr = 1;
2235 : : }
2236 : : }
2237 : : else
2238 : : {
2239 : 0 : pPrevEquStr = pCurrEquStr;
2240 : 0 : multPrevEquStr = 1;
2241 : : }
2242 : 0 : pINChI_Aux_Prev = NULL; /* pINChI_Aux_Prev does not exist since */
2243 : 0 : pINChI_Aux_Taut_Prev = NULL; /* pINChI_Aux has just been printed */
2244 : 0 : mult = 0;
2245 : 0 : eq2tautPrev = 1;
2246 : : }
2247 : : else
2248 : : {
2249 [ + + ]: 34 : if (eq2tautPrev)
2250 : : {
2251 : : /* at this point pINChI_Aux_Prev does not exist; however, pINChI_Aux */
2252 : : /*might have been discovered and it is different from pINChI_Aux_Taut */
2253 [ - + - - ]: 13 : if (multPrevEquStr && pPrevEquStr)
2254 : : {
2255 : : /* new EqStr is different; output it */
2256 [ # # ]: 0 : if (bNext++)
2257 : : {
2258 : 0 : MakeDelim( sCompDelim, strbuf, bOverflow );
2259 : : }
2260 : 0 : MakeEqStr( pPrevEquStr, multPrevEquStr, strbuf, bOverflow );
2261 : 0 : pPrevEquStr = NULL;
2262 : 0 : multPrevEquStr = 0;
2263 : : }
2264 : 13 : eq2tautPrev = 0;
2265 : 13 : pINChI_Aux_Prev = pINChI_Aux;
2266 : 13 : pINChI_Aux_Taut_Prev = pINChI_Aux_Taut;
2267 : 13 : mult = 0;
2268 : : }
2269 : : else
2270 : : {
2271 : : /* check whether pINChI_Aux and pINChI_Aux_Prev have identical non-trivial equivalence info */
2272 [ + - + + ]: 42 : eq2prev = bUseMulipliers &&
2273 : 21 : Eql_INChI_Aux_Equ( pINChI_Aux, EQL_EQU, pINChI_Aux_Prev, EQL_EQU );
2274 [ + + ]: 21 : if (eq2prev)
2275 : : {
2276 : : /* eq. info is same and non-trivial */
2277 : 1 : mult++; /* mult = (number of non-empty equal items)-1 */
2278 : 1 : continue;
2279 : : }
2280 : : else
2281 : : {
2282 : : /* pINChI_Aux eq. info is either different or trivial. Output pINChI_Aux_Prev anyway */
2283 [ + + ]: 20 : if (bNext++)
2284 : : {
2285 : 7 : MakeDelim( sCompDelim, strbuf, bOverflow );
2286 : : }
2287 [ + - + - ]: 20 : if (pINChI_Aux_Prev && pINChI_Aux_Prev->nNumberOfAtoms)
2288 : : {
2289 [ + + ]: 35 : if (bHasEquString( pINChI_Aux_Prev->nConstitEquNumbers, pINChI_Aux_Prev->nNumberOfAtoms ))
2290 : : {
2291 : : /* pINChI_Aux_Prev exists and has equivalence info */
2292 : 15 : MakeMult( mult + 1, "*", strbuf, 0, bOverflow );
2293 : 15 : MakeEquString( pINChI_Aux_Prev->nConstitEquNumbers, pINChI_Aux_Prev->nNumberOfAtoms, 0,
2294 : : strbuf, TAUT_MODE, bOverflow );
2295 : : }
2296 : : else
2297 : : {
2298 : : ; /* pINChI_Aux_Prev exists and has only trivial equivalence info */
2299 : : }
2300 : : }
2301 : :
2302 : : else
2303 : : {
2304 [ # # # # : 0 : if (bSecondNonTautPass && pINChI_Aux_Taut_Prev && pINChI_Aux_Taut_Prev->nNumberOfAtoms)
# # ]
2305 : : {
2306 : 0 : if (bHasEquString( pINChI_Aux_Taut_Prev->nConstitEquNumbers, pINChI_Aux_Taut_Prev->nNumberOfAtoms ))
2307 : : {
2308 : : /* since pINChI_Aux_Prev does not exist, pINChI_Aux_Taut_Prev is non-tautomeric */
2309 : : /* and it has non-trivial equivalence info. This info has already been printed in the main section */
2310 : : /*
2311 : : MakeDelim( sIdenticalValues, strbuf, bOverflow);
2312 : : */
2313 : : }
2314 : : else
2315 : : {
2316 : : ; /* pINChI_Aux_Taut_Prev exists and has only trivial equivalence info */
2317 : : }
2318 : : }
2319 : : #if ( bRELEASE_VERSION != 1 && defined(_DEBUG) )
2320 : : else
2321 : : {
2322 : : int stop = 1; /* <BRKPT> */
2323 : : }
2324 : : #endif
2325 : : }
2326 : :
2327 : : }
2328 : :
2329 : 20 : pINChI_Aux_Prev = pINChI_Aux;
2330 : 20 : pINChI_Aux_Taut_Prev = pINChI_Aux_Taut;
2331 : 20 : mult = 0; /* we do not know whether the item is empty */
2332 : : }
2333 : : }
2334 : : }
2335 : :
2336 : 13 : return ( strbuf->nUsedLength - nUsedLength0 );
2337 : : }
2338 : :
2339 : :
2340 : : /****************************************************************************
2341 : : Produce tetrahedral stereo inversion substring of AuxInfo.
2342 : : ****************************************************************************/
2343 : 42 : int str_AuxInvSp3( INCHI_SORT *pINChISort,
2344 : : INCHI_SORT *pINChISort2,
2345 : : INCHI_IOS_STRING *strbuf,
2346 : : int *bOverflow,
2347 : : int bOutType,
2348 : : int TAUT_MODE,
2349 : : int num_components,
2350 : : int bSecondNonTautPass,
2351 : : int bOmitRepetitions,
2352 : : int bUseMulipliers )
2353 : : {
2354 : : int i, ii, ii2, nUsedLength0;
2355 : : INCHI_SORT *is, *is2, *is0, *is20;
2356 : : INChI *pINChI, *pINChI_Prev, *pINChI_Taut, *pINChI_Taut_Prev;
2357 : : INChI_Stereo *Stereo, *Stereo_Prev, *Stereo_Taut, *Stereo_Taut_Prev;
2358 : : int mult, eq2prev, eq2taut, eq2tautPrev, bNext;
2359 : : const char *pPrevEquStr, *pCurrEquStr;
2360 : : int multPrevEquStr;
2361 : : /***************
2362 : : inverted sp3
2363 : : ****************/
2364 : 42 : pINChI_Taut = NULL;
2365 : 42 : pINChI_Prev = NULL;
2366 : 42 : pINChI_Taut_Prev = NULL;
2367 : 42 : mult = 0;
2368 : 42 : bNext = 0;
2369 : 42 : is = NULL;
2370 : 42 : is2 = NULL;
2371 : 42 : is0 = pINChISort;
2372 [ - + ]: 42 : is20 = bSecondNonTautPass ? pINChISort2 : NULL;
2373 : : /* djb-rwth: removing redundant code */
2374 : 42 : eq2tautPrev = 1; /* pINChI_Prev (previous pINChI) does not exist */
2375 : 42 : pPrevEquStr = NULL; /*, *pCurrEquStr;*/
2376 : 42 : multPrevEquStr = 0;
2377 : 42 : nUsedLength0 = strbuf->nUsedLength;
2378 : :
2379 : : /* For each connected component... */
2380 [ + + ]: 136 : for (i = 0; i <= num_components; i++)
2381 : : {
2382 : :
2383 : : /* 1st (taut) pass: bOutType=OUT_TN ; 2nd (non-taut pass) bOutType=OUT_NT */
2384 [ + + - + : 94 : pINChI = ( i < num_components && ( is = is0 + i, 0 <= ( ii = GET_II( bOutType, is ) ) ) ) ? is->pINChI[ii] : NULL;
- - - - -
- - - - -
- - + - +
- + - - +
- - - - -
- - - - -
- - - - -
- - - - -
- - - - -
- - - - -
- - + - ]
2385 : : /*================ compare sp2 to previous =====================*/
2386 [ - + ]: 94 : if (bSecondNonTautPass)
2387 : : {
2388 : : /* component that was output on the 1st pass */
2389 [ # # # # : 0 : pINChI_Taut = ( i < num_components && ( is2 = is20 + i, 0 <= ( ii2 = GET_II( OUT_T1, is2 ) ) ) ) ? is2->pINChI[ii2] : NULL;
# # # # #
# # # ]
2390 : : }
2391 : 94 : eq2taut = 0;
2392 : : /*========= if bSecondNonTautPass then compare iso non-taut stereo to other stereo ========*/
2393 [ - + - - ]: 94 : if (bSecondNonTautPass && bOmitRepetitions)
2394 : : {
2395 : : /* compare non-tautomeric inverted to:
2396 : : * a) tautomeric inverted
2397 : : * b) Inverted(tautomeric)
2398 : : * c) Inverted(non-tautomeric)
2399 : : */
2400 : : /* a) compare non-tautomeric inverted to tautomeric inverted */
2401 [ # # ]: 0 : if (!eq2taut)
2402 : : {
2403 [ # # ]: 0 : eq2taut = pINChI && pINChI_Taut &&
2404 : : /* non-taut inverted */ /* taut invertedc */
2405 [ # # # # : 0 : ( Stereo = pINChI->Stereo ) && ( Stereo_Taut = pINChI_Taut->Stereo ) &&
# # # # ]
2406 : 0 : Eql_INChI_Stereo( Stereo, EQL_SP3_INV, Stereo_Taut, EQL_SP3_INV, 0 );
2407 : : /* stereo-inv non-taut = taut (stereo-inv) */
2408 [ # # ]: 0 : eq2taut = eq2taut ? ( iiSTEREO_INV | iitNONTAUT ) : 0;
2409 : : }
2410 : : /* b) compare non-tautomeric inverted to Inverted(tautomeric stereo) */
2411 [ # # ]: 0 : if (!eq2taut)
2412 : : {
2413 [ # # ]: 0 : eq2taut = pINChI && pINChI_Taut &&
2414 [ # # # # : 0 : ( Stereo = pINChI->Stereo ) && ( Stereo_Taut = pINChI_Taut->Stereo ) &&
# # # # ]
2415 : 0 : Eql_INChI_Stereo( Stereo, EQL_SP3_INV, Stereo_Taut, EQL_SP3, 0 );
2416 : : /* stereo-inv non-taut = Inv(taut stereo) */
2417 [ # # ]: 0 : eq2taut = eq2taut ? ( iiSTEREO_INV | iitNONTAUT | iiEq2INV ) : 0;
2418 : : }
2419 : : /* c) compare non-tautomeric inverted to Inverted(non-tautomeric stereo) */
2420 [ # # ]: 0 : if (!eq2taut)
2421 : : {
2422 : 0 : eq2taut = pINChI &&
2423 [ # # # # : 0 : ( Stereo = pINChI->Stereo ) &&
# # ]
2424 : 0 : Eql_INChI_Stereo( Stereo, EQL_SP3_INV, Stereo, EQL_SP3, 0 );
2425 : : /* stereo-inv non-taut = Inv(non-taut stereo) */
2426 [ # # ]: 0 : eq2taut = eq2taut ? ( iiSTEREO_INV | iitNONTAUT | iiEq2INV | iiEq2NONTAUT ) : 0;
2427 : : }
2428 : : #if ( FIX_EMPTY_LAYER_BUG == 1 )
2429 : : if (!eq2taut && pINChI && pINChI_Taut &&
2430 : : !( ( Stereo = pINChI->Stereo ) && Eql_INChI_Stereo( Stereo, EQL_SP3_INV, NULL, EQL_EXISTS, 0 ) ))
2431 : : {
2432 : : if (( Stereo_Taut = pINChI_Taut->Stereo ) &&
2433 : : Eql_INChI_Stereo( Stereo_Taut, EQL_SP3, NULL, EQL_EXISTS, 0 ))
2434 : : {
2435 : :
2436 : : eq2taut = iiEmpty; /* the current is empty while the preceding (taut) is not */
2437 : : }
2438 : : }
2439 : : #endif
2440 : : }
2441 : : else
2442 : : /*========= if not bSecondNonTautPass then compare inv taut stereo to various taut stereo ========*/
2443 [ + - + - ]: 94 : if (!bSecondNonTautPass && bOmitRepetitions)
2444 : : {
2445 : : /* compare tautomeric inverted to Invetred(tautomeric) */
2446 [ + - ]: 94 : if (!eq2taut)
2447 : : {
2448 : 146 : eq2taut = pINChI &&
2449 [ + + + - : 146 : ( Stereo = pINChI->Stereo ) &&
+ + ]
2450 : 52 : Eql_INChI_Stereo( Stereo, EQL_SP3_INV, Stereo, EQL_SP3, 0 );
2451 : : /* stereo isotopic taut = taut (stereo) */
2452 [ + + ]: 94 : eq2taut = eq2taut ? ( iiSTEREO_INV | iiEq2INV ) : 0;
2453 : : }
2454 : : }
2455 [ + + ]: 94 : if (eq2taut)
2456 : : {
2457 : : /* we may be here only in case of the current layer found equal in another layer the same component */
2458 [ + + + - ]: 38 : if (pINChI_Prev && pINChI_Prev->nNumberOfAtoms)
2459 : : {
2460 : : /* previous component exists; output it before output the current component */
2461 [ + + ]: 4 : if (bNext++)
2462 : : {
2463 : 1 : MakeDelim( sCompDelim, strbuf, bOverflow );
2464 : : }
2465 [ + - + - ]: 4 : if (( Stereo_Prev = pINChI_Prev->Stereo ) && Stereo_Prev->nNumberOfStereoCenters > 0)
2466 : : {
2467 : 4 : MakeMult( mult + 1, "*", strbuf, 0, bOverflow );
2468 : :
2469 : 4 : MakeStereoString( Stereo_Prev->nNumber, NULL, Stereo_Prev->t_parityInv,
2470 : : 0, Stereo_Prev->nNumberOfStereoCenters,
2471 : : strbuf, TAUT_MODE, bOverflow );
2472 : : }
2473 : : }
2474 : : else
2475 [ - + - - ]: 34 : if (pINChI_Taut_Prev && pINChI_Taut_Prev->nNumberOfAtoms)
2476 : : {
2477 : : /* previous non-taut component exists only in taut list */
2478 [ # # ]: 0 : if (bNext++)
2479 : : {
2480 : 0 : MakeDelim( sCompDelim, strbuf, bOverflow );
2481 : : }
2482 : : /* do not output stereo of non-tautomeric in non-taut layer: it has been output in the main layer */
2483 : : }
2484 : : /* we have found another (previously printed) layer of the current component equal to this layer */
2485 : : /* output this (current) equivalence mark = EquString(eq2taut) */
2486 : 38 : pCurrEquStr = EquString( eq2taut );
2487 [ + + + - ]: 38 : if (multPrevEquStr && pPrevEquStr)
2488 : : {
2489 [ + - + - ]: 3 : if (pCurrEquStr && !strcmp( pCurrEquStr, pPrevEquStr ))
2490 : : {
2491 : 3 : multPrevEquStr++;
2492 : : }
2493 : : else
2494 : : {
2495 : : /* new EqStr is different; output it */
2496 [ # # ]: 0 : if (bNext++)
2497 : : {
2498 : 0 : MakeDelim( sCompDelim, strbuf, bOverflow );
2499 : : }
2500 : 0 : MakeEqStr( pPrevEquStr, multPrevEquStr, strbuf, bOverflow );
2501 : 0 : pPrevEquStr = pCurrEquStr;
2502 : 0 : multPrevEquStr = 1;
2503 : : }
2504 : : }
2505 : : else
2506 : : {
2507 : 35 : pPrevEquStr = pCurrEquStr;
2508 : 35 : multPrevEquStr = 1;
2509 : : }
2510 : 38 : pINChI_Prev = NULL; /* pINChI_Prev sp2 does not exist since */
2511 : 38 : pINChI_Taut_Prev = NULL; /* pINChI has just been printed */
2512 : 38 : mult = 0;
2513 : 38 : eq2tautPrev = 1; /* pINChI_Prev and pINChI_Taut_Prev have already been output */
2514 : : }
2515 : : else
2516 [ + + ]: 56 : if (eq2tautPrev)
2517 : : {
2518 : : /* at this point pINChI_Prev does not exist; however, pINChI */
2519 : : /*might have been discovered and it is different from pINChI_Taut */
2520 [ + + + - ]: 46 : if (multPrevEquStr && pPrevEquStr)
2521 : : {
2522 : : /* new EqStr is different; output it */
2523 [ + + ]: 35 : if (bNext++)
2524 : : {
2525 : 4 : MakeDelim( sCompDelim, strbuf, bOverflow );
2526 : : }
2527 : 35 : MakeEqStr( pPrevEquStr, multPrevEquStr, strbuf, bOverflow );
2528 : 35 : pPrevEquStr = NULL;
2529 : 35 : multPrevEquStr = 0;
2530 : : }
2531 : 46 : eq2tautPrev = 0;
2532 : 46 : pINChI_Prev = pINChI;
2533 : 46 : pINChI_Taut_Prev = pINChI_Taut;
2534 : 46 : mult = 0;
2535 : : }
2536 : : else
2537 : : {
2538 : : /* current layer is different from previously printed layers of the current component */
2539 : : /* compare the current layer to this layer of the previous component: */
2540 : : /* check whether pINChI and pINChI_Prev have non-zero identical stereo sp2 */
2541 : : /*================ compare iso sp3 to previous =====================*/
2542 [ - + ]: 10 : eq2prev = bUseMulipliers &&
2543 [ # # ]: 0 : pINChI && pINChI_Prev &&
2544 : : /* do both have stereo? */
2545 [ + - - - : 20 : ( Stereo = pINChI->Stereo ) && ( Stereo_Prev = pINChI_Prev->Stereo ) &&
- - - - ]
2546 : : /* is their inverted stereo same? */
2547 : 0 : Eql_INChI_Stereo( Stereo, EQL_SP3_INV, Stereo_Prev, EQL_SP3_INV, 0 );
2548 [ - + ]: 10 : if (eq2prev)
2549 : : {
2550 : 0 : mult++; /* mult = (number of non-empty equal items)-1 */
2551 : 0 : continue;
2552 : : }
2553 : : else
2554 : : {
2555 [ + + ]: 10 : if (bNext++)
2556 : : {
2557 : 2 : MakeDelim( sCompDelim, strbuf, bOverflow );
2558 : : }
2559 [ + - + - ]: 10 : if (pINChI_Prev && pINChI_Prev->nNumberOfAtoms)
2560 : : {
2561 [ + - ]: 10 : if (( Stereo_Prev = pINChI_Prev->Stereo ) &&
2562 [ + + + - ]: 10 : Stereo_Prev->nNumberOfStereoCenters > 0 && Stereo_Prev->nCompInv2Abs)
2563 : : {
2564 : 9 : MakeMult( mult + 1, "*", strbuf, 0, bOverflow );
2565 : :
2566 : 9 : MakeStereoString( Stereo_Prev->nNumberInv, NULL, Stereo_Prev->t_parityInv,
2567 : : 0, Stereo_Prev->nNumberOfStereoCenters,
2568 : : strbuf, TAUT_MODE, bOverflow );
2569 : : }
2570 : : /* else sp3 info is not present in pINChI_Prev */
2571 : : }
2572 : : else
2573 : : /* do not print pINChI_Prev because it either do not exist of have already been printed */
2574 [ # # # # : 0 : if (bSecondNonTautPass && pINChI_Taut_Prev && pINChI_Taut_Prev->nNumberOfAtoms)
# # ]
2575 : : {
2576 [ # # ]: 0 : if (( Stereo_Taut_Prev = pINChI_Taut_Prev->Stereo ) &&
2577 [ # # ]: 0 : Stereo_Taut_Prev->nNumberOfStereoCenters > 0 && Stereo_Taut_Prev->nCompInv2Abs)
2578 : : {
2579 : : /* since pINChI_Prev does not exist, pINChI_Taut_Prev is non-tautomeric */
2580 : : /* and it has non-trivial inv sp3 info. It has already been printed in the main section */
2581 : : /*
2582 : : MakeDelim( sIdenticalValues, strbuf, bOverflow);
2583 : : */
2584 : : ;/* pINChI_Taut_Prev sp3 info was output in the main stereo section */
2585 : : }
2586 : : else
2587 : : {
2588 : : ; /* pINChI_Taut_Prev exists and has not sp3 info */
2589 : : }
2590 : : }
2591 : : #if ( bRELEASE_VERSION != 1 && defined(_DEBUG) )
2592 : : else
2593 : : {
2594 : : int stop = 1; /* <BRKPT> */
2595 : : }
2596 : : #endif
2597 : : }
2598 : 10 : pINChI_Prev = pINChI;
2599 : 10 : mult = 0; /* we do not know whether the item is empty */
2600 : : }
2601 : : }
2602 : :
2603 : 42 : return ( strbuf->nUsedLength - nUsedLength0 );
2604 : : }
2605 : :
2606 : :
2607 : : /****************************************************************************
2608 : : Produce tetrahedral stereo inversion numbering substring of AuxInfo
2609 : : /iN: in Main and/or Isotopic and/or FixedH-Iso parts,
2610 : : in both normal and reconnected layers
2611 : : ****************************************************************************/
2612 : 0 : int str_AuxInvSp3Numb( CANON_GLOBALS *pCG,
2613 : : INCHI_SORT *pINChISort,
2614 : : INCHI_SORT *pINChISort2,
2615 : : INCHI_IOS_STRING *strbuf,
2616 : : int *bOverflow,
2617 : : int bOutType,
2618 : : int TAUT_MODE,
2619 : : int num_components,
2620 : : int bSecondNonTautPass,
2621 : : int bOmitRepetitions )
2622 : : {
2623 : : int i, ii, ii2, nUsedLength0;
2624 : : INCHI_SORT *is, *is0 /*, *is2*/;
2625 : : INChI *pINChI, *pINChI_Taut;
2626 : : INChI_Aux *pINChI_Aux, *pINChI_Aux_Taut; /* djb-rwth: removing redundant variables */
2627 : : INChI_Stereo *Stereo, *Stereo_Taut;
2628 : : int eq2taut, bNext;
2629 : : const char *pPrevEquStr, *pCurrEquStr;
2630 : : int multPrevEquStr;
2631 : : /**************************************************
2632 : : * specificity of numbering: there is no previous *
2633 : : * component because no repetition is possible *
2634 : : **************************************************/
2635 : 0 : pINChI = NULL;
2636 : 0 : pINChI_Taut = NULL;
2637 : 0 : pINChI_Aux = NULL;
2638 : 0 : pINChI_Aux_Taut = NULL;
2639 : : /* djb-rwth: removing redundant code */
2640 : 0 : bNext = 0;
2641 : 0 : is = NULL;
2642 : 0 : is0 = pINChISort;
2643 : : /*is2 = bSecondNonTautPass? pINChISort2 : NULL;*/
2644 : : /* djb-rwth: removing redundant code */
2645 : 0 : pPrevEquStr = NULL; /*, *pCurrEquStr;*/
2646 : 0 : multPrevEquStr = 0;
2647 : 0 : nUsedLength0 = strbuf->nUsedLength;
2648 : :
2649 : : /* For each connected component... */
2650 [ # # ]: 0 : for (i = 0; i < num_components; i++)
2651 : : {
2652 : :
2653 : : /* 1st (taut) pass: bOutType=OUT_TN ; 2nd (non-taut pass) bOutType=OUT_NT */
2654 : 0 : is = is0 + i;
2655 [ # # # # : 0 : pINChI = ( 0 <= ( ii = GET_II( bOutType, is ) ) ) ? is->pINChI[ii] : NULL;
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # ]
2656 [ # # ]: 0 : pINChI_Aux = pINChI ? is->pINChI_Aux[ii] : NULL;
2657 : : /*================ to compare to previously printed =====================*/
2658 [ # # ]: 0 : if (bSecondNonTautPass)
2659 : : {
2660 : : /* component that was printed on the 1st pass */
2661 [ # # # # : 0 : pINChI_Taut = ( 0 <= ( ii2 = GET_II( OUT_T1, is ) ) ) ? is->pINChI[ii2] : NULL;
# # # # #
# ]
2662 [ # # ]: 0 : pINChI_Aux_Taut = pINChI_Taut ? is->pINChI_Aux[ii2] : NULL;
2663 : : }
2664 : :
2665 : 0 : eq2taut = 0;
2666 : : /*========= if bSecondNonTautPass then compare inv non-taut stereo to other stereo ========*/
2667 [ # # # # : 0 : if (bSecondNonTautPass && bOmitRepetitions &&
# # ]
2668 [ # # # # ]: 0 : pINChI && ( Stereo = pINChI->Stereo ) && Stereo->nCompInv2Abs)
2669 : : {
2670 : : /* compare non-tautomeric inverted stereo numbering to:
2671 : : * a) tautomeric numbering
2672 : : * b) non-tautomeric numbering
2673 : : * c) tautomeric inverted stereo numbering
2674 : : */
2675 : : /* a) compare non-tautomeric inverted stereo numbering to tautomeric numbering */
2676 [ # # ]: 0 : if (!eq2taut)
2677 : : {
2678 [ # # # # ]: 0 : eq2taut = pINChI_Taut &&
2679 : 0 : Eql_INChI_Aux_Num( pINChI_Aux, EQL_NUM_INV, pINChI_Aux_Taut, EQL_NUM );
2680 : : /* stereo-inv numbering non-taut = taut numbering */
2681 [ # # ]: 0 : eq2taut = eq2taut ? ( iiSTEREO_INV | iiNUMB | iitNONTAUT ) : 0;
2682 : : }
2683 : : /* b) compare non-tautomeric inverted stereo numbering to non-tautomeric numbering */
2684 [ # # ]: 0 : if (!eq2taut)
2685 : : {
2686 : : eq2taut =
2687 : 0 : Eql_INChI_Aux_Num( pINChI_Aux, EQL_NUM_INV, pINChI_Aux, EQL_NUM );
2688 : : /* stereo-inv numb. non-taut = non-taut numbering */
2689 [ # # ]: 0 : eq2taut = eq2taut ? ( iiSTEREO_INV | iiNUMB | iitNONTAUT | iiEq2NONTAUT ) : 0;
2690 : : }
2691 : : /* c) compare non-tautomeric inverted stereo numbering to tautomeric inverted stereo numbering */
2692 [ # # ]: 0 : if (!eq2taut)
2693 : : {
2694 : 0 : eq2taut = pINChI_Taut &&
2695 [ # # # # : 0 : ( Stereo_Taut = pINChI_Taut->Stereo ) && Stereo_Taut->nCompInv2Abs &&
# # # # ]
2696 : 0 : Eql_INChI_Aux_Num( pINChI_Aux, EQL_NUM_INV, pINChI_Aux_Taut, EQL_NUM_INV );
2697 : : /* stereo-inv numb. non-taut = taut inv stereo numbering */
2698 [ # # ]: 0 : eq2taut = eq2taut ? ( iiSTEREO_INV | iiNUMB | iitNONTAUT | iiEq2INV ) : 0;
2699 : : }
2700 : : }
2701 : : else
2702 : : {
2703 : : /*========= if not bSecondNonTautPass then compare inv taut stereo numb to taut numb ========*/
2704 [ # # # # : 0 : if (!bSecondNonTautPass && bOmitRepetitions &&
# # ]
2705 [ # # # # ]: 0 : pINChI && ( Stereo = pINChI->Stereo ) && Stereo->nCompInv2Abs)
2706 : : {
2707 : : /* compare tautomeric inverted stereo numbering to tautomeric numbering */
2708 [ # # ]: 0 : if (!eq2taut)
2709 : : {
2710 : : eq2taut =
2711 : 0 : Eql_INChI_Aux_Num( pINChI_Aux, EQL_NUM_INV, pINChI_Aux, EQL_NUM );
2712 : : /* stereo-inv numbering (taut) = taut numbering */
2713 [ # # ]: 0 : eq2taut = eq2taut ? ( iiSTEREO_INV | iiNUMB ) : 0;
2714 : : }
2715 : : }
2716 : : }
2717 [ # # ]: 0 : if (eq2taut)
2718 : : {
2719 : : /* we have found another (previously printed) layer of the current component equal to this layer */
2720 : : /* output this (current) equivalence mark = EquString(eq2taut) */
2721 : 0 : pCurrEquStr = EquString( eq2taut );
2722 [ # # # # ]: 0 : if (multPrevEquStr && pPrevEquStr)
2723 : : {
2724 [ # # # # ]: 0 : if (pCurrEquStr && !strcmp( pCurrEquStr, pPrevEquStr ))
2725 : : {
2726 : 0 : multPrevEquStr++;
2727 : : }
2728 : : else
2729 : : {
2730 : : /* new EqStr is different; output it */
2731 [ # # ]: 0 : if (bNext++)
2732 : : {
2733 : 0 : MakeDelim( sCompDelim, strbuf, bOverflow );
2734 : : }
2735 : 0 : MakeEqStr( pPrevEquStr, multPrevEquStr, strbuf, bOverflow );
2736 : 0 : pPrevEquStr = pCurrEquStr;
2737 : 0 : multPrevEquStr = 1;
2738 : : }
2739 : : }
2740 : : else
2741 : : {
2742 : 0 : pPrevEquStr = pCurrEquStr;
2743 : 0 : multPrevEquStr = 1;
2744 : : }
2745 : : }
2746 : : else
2747 : : {
2748 : : /* current layer is different from previously printed layers of the current component */
2749 [ # # # # ]: 0 : if (multPrevEquStr && pPrevEquStr)
2750 : : {
2751 : : /* new EqStr is different; output it */
2752 [ # # ]: 0 : if (bNext++)
2753 : : {
2754 : 0 : MakeDelim( sCompDelim, strbuf, bOverflow );
2755 : : }
2756 : 0 : MakeEqStr( pPrevEquStr, multPrevEquStr, strbuf, bOverflow );
2757 : 0 : pPrevEquStr = NULL;
2758 : 0 : multPrevEquStr = 0;
2759 : : }
2760 [ # # ]: 0 : if (bNext++)
2761 : : {
2762 : 0 : MakeDelim( sCompDelim, strbuf, bOverflow );
2763 : : }
2764 [ # # # # : 0 : if (pINChI && pINChI_Aux && pINChI_Aux->nNumberOfAtoms &&
# # ]
2765 [ # # # # ]: 0 : ( Stereo = pINChI->Stereo ) && Stereo->nNumberOfStereoCenters &&
2766 [ # # # # ]: 0 : Stereo->nCompInv2Abs && pINChI_Aux->nOrigAtNosInCanonOrdInv)
2767 : : {
2768 : 0 : MakeCtString( pCG, pINChI_Aux->nOrigAtNosInCanonOrdInv,
2769 : : pINChI_Aux->nNumberOfAtoms, 0, NULL, 0,
2770 : : strbuf, TAUT_MODE, bOverflow );
2771 : : }
2772 : : /* else inv stereo info is not present in pINChI */
2773 : : }
2774 : : }
2775 : :
2776 [ # # # # ]: 0 : if (multPrevEquStr && pPrevEquStr)
2777 : : {
2778 : : /* the new EqStr of the last item has not been printed; output it now */
2779 [ # # ]: 0 : if (bNext++)
2780 : : {
2781 : 0 : MakeDelim( sCompDelim, strbuf, bOverflow );
2782 : : }
2783 : 0 : MakeEqStr( pPrevEquStr, multPrevEquStr, strbuf, bOverflow );
2784 : 0 : pPrevEquStr = NULL;
2785 : : /* djb-rwth: removing redundant code */
2786 : : }
2787 : :
2788 : 0 : return ( strbuf->nUsedLength - nUsedLength0 );
2789 : : }
2790 : :
2791 : :
2792 : : /****************************************************************************
2793 : : Produce isotopic numbering substring of AuxInfo
2794 : : /I: in Isotopic and/or FixedH-Iso parts,
2795 : : in both normal and reconnected layers
2796 : : ****************************************************************************/
2797 : 0 : int str_AuxIsoNumb( CANON_GLOBALS *pCG,
2798 : : INCHI_SORT *pINChISort,
2799 : : INCHI_SORT *pINChISort2,
2800 : : INCHI_IOS_STRING *strbuf,
2801 : : int *bOverflow,
2802 : : int bOutType,
2803 : : int TAUT_MODE,
2804 : : int num_components,
2805 : : int bSecondNonTautPass,
2806 : : int bOmitRepetitions )
2807 : : {
2808 : : int i, ii, ii2, nUsedLength0;
2809 : : INCHI_SORT *is, *is0 /*, *is2*/;
2810 : : /* djb-rwth: removing redundant variables */
2811 : : INChI_Aux *pINChI_Aux, *pINChI_Aux_Taut; /* djb-rwth: removing redundant variables */
2812 : : int eq2taut, bNext;
2813 : : const char *pPrevEquStr, *pCurrEquStr;
2814 : : int multPrevEquStr;
2815 : : /**************************************************
2816 : : * specificity of numbering: there is no previous *
2817 : : * component because no repetition is possible *
2818 : : **************************************************/
2819 : : /* djb-rwth: removing redundant code */
2820 : 0 : pINChI_Aux = NULL;
2821 : 0 : pINChI_Aux_Taut = NULL;
2822 : : /* djb-rwth: removing redundant code */
2823 : 0 : bNext = 0;
2824 : 0 : is = NULL;
2825 : 0 : is0 = pINChISort;
2826 : : /*is2 = bSecondNonTautPass? pINChISort2 : NULL;*/
2827 : : /* djb-rwth: removing redundant code */
2828 : 0 : pPrevEquStr = NULL; /*, *pCurrEquStr;*/
2829 : 0 : multPrevEquStr = 0;
2830 : 0 : nUsedLength0 = strbuf->nUsedLength;
2831 : :
2832 : : /* For each connected component... */
2833 [ # # ]: 0 : for (i = 0; i < num_components; i++)
2834 : : {
2835 : :
2836 : : /* 1st (taut) pass: bOutType=OUT_TN ; 2nd (non-taut pass) bOutType=OUT_NT */
2837 : 0 : is = is0 + i;
2838 [ # # # # : 0 : pINChI_Aux = ( i < num_components && 0 <= ( ii = GET_II( bOutType, is ) ) ) ? is->pINChI_Aux[ii] : NULL;
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # ]
2839 : : /*================ to compare to previously printed =====================*/
2840 [ # # ]: 0 : if (bSecondNonTautPass)
2841 : : {
2842 [ # # # # : 0 : pINChI_Aux_Taut = ( 0 <= ( ii2 = GET_II( OUT_T1, is ) ) ) ? is->pINChI_Aux[ii2] : NULL;
# # # # #
# ]
2843 : : }
2844 : 0 : eq2taut = 0;
2845 : : /*========= if bSecondNonTautPass then compare iso non-taut numb to other numb ========*/
2846 [ # # # # : 0 : if (bSecondNonTautPass && bOmitRepetitions && pINChI_Aux && pINChI_Aux->bIsIsotopic)
# # # # ]
2847 : : {
2848 : : /* compare non-tautomeric isotopic numbering to:
2849 : : * a) tautomeric numbering
2850 : : * b) non-tautomeric numbering
2851 : : * c) tautomeric isotopic numbering
2852 : : */
2853 : : /* a) compare non-tautomeric isotopic numbering to tautomeric numbering */
2854 [ # # ]: 0 : if (!eq2taut)
2855 : : {
2856 : 0 : eq2taut = Eql_INChI_Aux_Num( pINChI_Aux, EQL_NUM_ISO, pINChI_Aux_Taut, EQL_NUM );
2857 : : /* numbering non-taut isotopic = taut numbering */
2858 [ # # ]: 0 : eq2taut = eq2taut ? ( iiNUMB | iitNONTAUT | iitISO ) : 0;
2859 : : }
2860 : : /* b) compare non-tautomeric isotopic numbering to non-tautomeric numbering */
2861 [ # # ]: 0 : if (!eq2taut)
2862 : : {
2863 : 0 : eq2taut = Eql_INChI_Aux_Num( pINChI_Aux, EQL_NUM_ISO, pINChI_Aux, EQL_NUM );
2864 : : /* numbering non-taut isotopic = non-taut numbering */
2865 [ # # ]: 0 : eq2taut = eq2taut ? ( iiNUMB | iitNONTAUT | iitISO | iiEq2NONTAUT ) : 0;
2866 : : }
2867 : : /* c) compare non-tautomeric isotopic numbering to tautomeric isotopic numbering */
2868 [ # # ]: 0 : if (!eq2taut)
2869 : : {
2870 : 0 : eq2taut = Eql_INChI_Aux_Num( pINChI_Aux, EQL_NUM_ISO, pINChI_Aux_Taut, EQL_NUM_ISO );
2871 : : /* numbering non-taut isotopic = taut isotopic numbering */
2872 [ # # ]: 0 : eq2taut = eq2taut ? ( iiNUMB | iitNONTAUT | iitISO | iiEq2ISO ) : 0;
2873 : : }
2874 : : }
2875 : : else
2876 : : {
2877 : : /* 2011-10-28
2878 : : Fix bug in src:cano mapping of atoms printed to AuxInfo
2879 : : Reported by Sandor Mark on 2011-10-25 in inchi-discuss
2880 : : See http://sourceforge.net/p/inchi/mailman/message/28292914/ also
2881 : : */
2882 : : #define AUX_ISO_NUMB_BUG_FIX
2883 : : #ifdef AUX_ISO_NUMB_BUG_FIX
2884 : : /* Bug-fixed version */
2885 : : /*========= if not bSecondNonTautPass then compare isotopic taut numbering to taut numbering ========*/
2886 [ # # # # : 0 : if (!bSecondNonTautPass && bOmitRepetitions && pINChI_Aux && pINChI_Aux->bIsIsotopic)
# # # # ]
2887 : : {
2888 : : /* compare tautomeric isotopic numbering to tautomeric non-isotopic numbering */
2889 [ # # ]: 0 : if (!eq2taut)
2890 : : {
2891 : 0 : eq2taut = Eql_INChI_Aux_Num( pINChI_Aux, EQL_NUM_ISO, pINChI_Aux, EQL_NUM );
2892 : : /* numbering isotopic (taut) = taut numbering */
2893 [ # # ]: 0 : eq2taut = eq2taut ? ( iiNUMB | iitISO ) : 0;
2894 : : }
2895 : : }
2896 : : #else
2897 : : /* Original (buggy) version */
2898 : :
2899 : : /*========= if not bSecondNonTautPass then compare inv taut stereo numb to taut numb ========*/
2900 : : if (!bSecondNonTautPass && bOmitRepetitions && pINChI_Aux && pINChI_Aux->bIsIsotopic)
2901 : : {
2902 : : /* compare tautomeric isotopic numbering to tautomeric non-isotopic numbering */
2903 : : if (!eq2taut)
2904 : : {
2905 : : eq2taut = Eql_INChI_Aux_Num( pINChI_Aux, EQL_NUM_ISO, pINChI_Aux, EQL_NUM_ISO );
2906 : : /* stereo-inv numbering (taut) = taut numbering */
2907 : : eq2taut = eq2taut ? ( iiSTEREO_INV | iiNUMB ) : 0;
2908 : : }
2909 : : }
2910 : : #endif
2911 : : }
2912 : :
2913 [ # # ]: 0 : if (eq2taut)
2914 : : {
2915 : : /* we have found another (previously printed) layer of the current component equal to this layer */
2916 : : /* output this (current) equivalence mark = EquString(eq2taut) */
2917 : 0 : pCurrEquStr = EquString( eq2taut );
2918 [ # # # # ]: 0 : if (multPrevEquStr && pPrevEquStr)
2919 : : {
2920 [ # # # # ]: 0 : if (pCurrEquStr && !strcmp( pCurrEquStr, pPrevEquStr ))
2921 : : {
2922 : 0 : multPrevEquStr++;
2923 : : }
2924 : : else
2925 : : {
2926 : : /* new EqStr is different; output it */
2927 [ # # ]: 0 : if (bNext++)
2928 : : {
2929 : 0 : MakeDelim( sCompDelim, strbuf, bOverflow );
2930 : : }
2931 : 0 : MakeEqStr( pPrevEquStr, multPrevEquStr, strbuf, bOverflow );
2932 : 0 : pPrevEquStr = pCurrEquStr;
2933 : 0 : multPrevEquStr = 1;
2934 : : }
2935 : : }
2936 : : else
2937 : : {
2938 : 0 : pPrevEquStr = pCurrEquStr;
2939 : 0 : multPrevEquStr = 1;
2940 : : }
2941 : : }
2942 : : else
2943 : : {
2944 : : /* current layer is different from previously printed layers of the current component */
2945 [ # # # # ]: 0 : if (multPrevEquStr && pPrevEquStr)
2946 : : {
2947 : : /* new EqStr is different; output it */
2948 [ # # ]: 0 : if (bNext++)
2949 : : {
2950 : 0 : MakeDelim( sCompDelim, strbuf, bOverflow );
2951 : : }
2952 : 0 : MakeEqStr( pPrevEquStr, multPrevEquStr, strbuf, bOverflow );
2953 : 0 : pPrevEquStr = NULL;
2954 : 0 : multPrevEquStr = 0;
2955 : : }
2956 [ # # ]: 0 : if (bNext++)
2957 : : {
2958 : 0 : MakeDelim( sCompDelim, strbuf, bOverflow );
2959 : : }
2960 [ # # # # : 0 : if (pINChI_Aux && pINChI_Aux->nNumberOfAtoms && pINChI_Aux->bIsIsotopic &&
# # ]
2961 [ # # ]: 0 : pINChI_Aux->nIsotopicOrigAtNosInCanonOrd)
2962 : : {
2963 : 0 : MakeCtString( pCG, pINChI_Aux->nIsotopicOrigAtNosInCanonOrd,
2964 : : pINChI_Aux->nNumberOfAtoms,
2965 : : 0, NULL, 0, strbuf, TAUT_MODE, bOverflow );
2966 : : }
2967 : : /* else isotopic numbering is not present in pINChI */
2968 : : }
2969 : : }
2970 : :
2971 [ # # # # ]: 0 : if (multPrevEquStr && pPrevEquStr)
2972 : : {
2973 : : /* the new EqStr of the last item has not been printed; output it now */
2974 [ # # ]: 0 : if (bNext++)
2975 : : {
2976 : 0 : MakeDelim( sCompDelim, strbuf, bOverflow );
2977 : : }
2978 : 0 : MakeEqStr( pPrevEquStr, multPrevEquStr, strbuf, bOverflow );
2979 : 0 : pPrevEquStr = NULL;
2980 : : /* djb-rwth: removing redundant code */
2981 : : }
2982 : :
2983 : 0 : return ( strbuf->nUsedLength - nUsedLength0 );
2984 : : }
2985 : :
2986 : :
2987 : : /****************************************************************************
2988 : : Produce isotopic equivalence substring of AuxInfo.
2989 : : ****************************************************************************/
2990 : 0 : int str_AuxIsoEqu( INCHI_SORT *pINChISort,
2991 : : INCHI_SORT *pINChISort2,
2992 : : INCHI_IOS_STRING *strbuf,
2993 : : int *bOverflow,
2994 : : int bOutType,
2995 : : int TAUT_MODE,
2996 : : int num_components,
2997 : : int bSecondNonTautPass,
2998 : : int bOmitRepetitions,
2999 : : int bUseMulipliers )
3000 : : {
3001 : : int i, ii, ii2, nUsedLength0;
3002 : : INCHI_SORT *is, *is2, *is0, *is20;
3003 : : INChI_Aux *pINChI_Aux, *pINChI_Aux_Prev, *pINChI_Aux_Taut, *pINChI_Aux_Taut_Prev;
3004 : : int mult, eq2prev, eq2taut, eq2tautPrev, bNext;
3005 : : const char *pPrevEquStr, *pCurrEquStr;
3006 : : int multPrevEquStr;
3007 : 0 : pINChI_Aux = NULL;
3008 : 0 : pINChI_Aux_Prev = NULL;
3009 : 0 : pINChI_Aux_Taut = NULL;
3010 : 0 : pINChI_Aux_Taut_Prev = NULL;
3011 : 0 : mult = 0;
3012 : 0 : bNext = 0;
3013 : 0 : is = NULL;
3014 : 0 : is2 = NULL;
3015 : 0 : is0 = pINChISort;
3016 [ # # ]: 0 : is20 = bSecondNonTautPass ? pINChISort2 : NULL;
3017 : : /* djb-rwth: removing redundant code */
3018 : 0 : eq2tautPrev = 1; /* pINChI_Aux_Prev (previous pINChI_Aux) does not exist */
3019 : 0 : pPrevEquStr = NULL; /*, *pCurrEquStr;*/
3020 : 0 : multPrevEquStr = 0;
3021 : 0 : nUsedLength0 = strbuf->nUsedLength;
3022 : :
3023 : : /* For each connected component... */
3024 [ # # ]: 0 : for (i = 0; i <= num_components; i++)
3025 : : {
3026 : :
3027 : : /* 1st (taut) pass: bOutType=OUT_TN ; 2nd (non-taut pass) bOutType=OUT_NT */
3028 [ # # # # : 0 : pINChI_Aux = ( i < num_components && ( is = is0 + i, 0 <= ( ii = GET_II( bOutType, is ) ) ) ) ? is->pINChI_Aux[ii] : NULL;
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # ]
3029 [ # # ]: 0 : if (bSecondNonTautPass)
3030 : : {
3031 : : /* component that was output on the 1st pass */
3032 [ # # # # : 0 : pINChI_Aux_Taut = ( i < num_components && ( is2 = is20 + i, 0 <= ( ii2 = GET_II( OUT_T1, is2 ) ) ) ) ? is2->pINChI_Aux[ii2] : NULL;
# # # # #
# # # ]
3033 : : }
3034 : : /*================ compare iso non-taut equivalence info to non-iso taut ========*/
3035 : 0 : eq2taut = 0;
3036 [ # # # # : 0 : if (bSecondNonTautPass && bOmitRepetitions && pINChI_Aux && pINChI_Aux->bIsIsotopic)
# # # # ]
3037 : : {
3038 : : /**************************************************
3039 : : * compare isotopic non-tautomeric equivalence to:
3040 : : * a) tautomeric
3041 : : * b) non-tautomeric
3042 : : * c) isotopic tautomeric
3043 : : */
3044 [ # # ]: 0 : if (!eq2taut)
3045 : : {
3046 : : /* compare isotopic non-tautomeric equivalence to tautomeric */
3047 : 0 : eq2taut = Eql_INChI_Aux_Equ( pINChI_Aux, EQL_EQU_ISO, pINChI_Aux_Taut, EQL_EQU );
3048 : : /* equ non-taut isotopic = tautomeric*/
3049 [ # # ]: 0 : eq2taut = eq2taut ? ( iiEQU | iitNONTAUT | iitISO ) : 0;
3050 : : }
3051 [ # # ]: 0 : if (!eq2taut)
3052 : : {
3053 : : /* compare isotopic non-tautomeric equivalence to non-tautomeric */
3054 : 0 : eq2taut = Eql_INChI_Aux_Equ( pINChI_Aux, EQL_EQU_ISO, pINChI_Aux, EQL_EQU );
3055 : : /* equ non-taut isotopic = non-tautomeric*/
3056 [ # # ]: 0 : eq2taut = eq2taut ? ( iiEQU | iitNONTAUT | iitISO | iiEq2NONTAUT ) : 0;
3057 : : }
3058 [ # # ]: 0 : if (!eq2taut)
3059 : : {
3060 : : /* compare isotopic non-tautomeric equivalence to isotopic tautomeric */
3061 : 0 : eq2taut = Eql_INChI_Aux_Equ( pINChI_Aux, EQL_EQU_ISO, pINChI_Aux_Taut, EQL_EQU_ISO );
3062 : : /* equ non-taut isotopic = isotopic tautomeric*/
3063 [ # # ]: 0 : eq2taut = eq2taut ? ( iiEQU | iitNONTAUT | iitISO | iiEq2ISO ) : 0;
3064 : : }
3065 : : }
3066 : : else
3067 : : {
3068 [ # # # # : 0 : if (!bSecondNonTautPass && bOmitRepetitions && pINChI_Aux && pINChI_Aux->bIsIsotopic)
# # # # ]
3069 : : {
3070 : : /**************************************************
3071 : : * compare isotopic tautomeric equivalence to:
3072 : : * a) non-isotopic tautomeric
3073 : : */
3074 [ # # ]: 0 : if (!eq2taut)
3075 : : {
3076 : : /* compare isotopic tautomeric equivalence to tautomeric */
3077 : 0 : eq2taut = Eql_INChI_Aux_Equ( pINChI_Aux, EQL_EQU_ISO, pINChI_Aux, EQL_EQU );
3078 : : /* equ taut-isotopic = tautomeric*/
3079 [ # # ]: 0 : eq2taut = eq2taut ? ( iiEQU | iitISO ) : 0;
3080 : : }
3081 : : }
3082 : : }
3083 [ # # ]: 0 : if (eq2taut)
3084 : : {
3085 : : /* we may be here only in case of the second (non-taut) pass */
3086 : : /* current non-taut equivalence has been found to be same as tautomeric */
3087 [ # # # # ]: 0 : if (pINChI_Aux_Prev && pINChI_Aux_Prev->nNumberOfAtoms)
3088 : : {
3089 : : /* previous component exists */
3090 [ # # ]: 0 : if (bNext++)
3091 : : {
3092 : 0 : MakeDelim( sCompDelim, strbuf, bOverflow );
3093 : : }
3094 [ # # ]: 0 : if (bHasEquString( pINChI_Aux_Prev->nConstitEquIsotopicNumbers, pINChI_Aux_Prev->nNumberOfAtoms ))
3095 : : {
3096 : : /* output previous component(s) equivalence since it was found to be non-trivial */
3097 : 0 : MakeMult( mult + 1, "*", strbuf, 0, bOverflow );
3098 : 0 : MakeEquString( pINChI_Aux_Prev->nConstitEquIsotopicNumbers, pINChI_Aux_Prev->nNumberOfAtoms, 0,
3099 : : strbuf, TAUT_MODE, bOverflow );
3100 : : }
3101 : : else
3102 : : {
3103 : : ; /* pINChI_Aux_Prev exists and has only trivial equivalence info */
3104 : : }
3105 : : }
3106 : : else
3107 : : {
3108 [ # # # # ]: 0 : if (pINChI_Aux_Taut_Prev && pINChI_Aux_Taut_Prev->nNumberOfAtoms)
3109 : : {
3110 : : /* previous non-taut component exists only in taut list */
3111 [ # # ]: 0 : if (bNext++)
3112 : : {
3113 : 0 : MakeDelim( sCompDelim, strbuf, bOverflow );
3114 : : }
3115 : : }
3116 : : }
3117 : : /* we have found pINChI_Aux->pINChI_Aux->nConstitEquIsotopicNumbers same as in pINChI_Aux_Taut */
3118 : : /* output this (current) equivalence as '*', that is, same as tautomeric */
3119 : : /* that was printed on the 1st pass. */
3120 : 0 : pCurrEquStr = EquString( eq2taut );
3121 [ # # # # ]: 0 : if (multPrevEquStr && pPrevEquStr)
3122 : : {
3123 [ # # # # ]: 0 : if (pCurrEquStr && !strcmp( pCurrEquStr, pPrevEquStr ))
3124 : : {
3125 : 0 : multPrevEquStr++;
3126 : : }
3127 : : else
3128 : : {
3129 : : /* new EqStr is different; output it */
3130 [ # # ]: 0 : if (bNext++)
3131 : : {
3132 : 0 : MakeDelim( sCompDelim, strbuf, bOverflow );
3133 : : }
3134 : 0 : MakeEqStr( pPrevEquStr, multPrevEquStr, strbuf, bOverflow );
3135 : 0 : pPrevEquStr = pCurrEquStr;
3136 : 0 : multPrevEquStr = 1;
3137 : : }
3138 : : }
3139 : : else
3140 : : {
3141 : 0 : pPrevEquStr = pCurrEquStr;
3142 : 0 : multPrevEquStr = 1;
3143 : : }
3144 : 0 : pINChI_Aux_Prev = NULL; /* pINChI_Aux_Prev does not exist since */
3145 : 0 : pINChI_Aux_Taut_Prev = NULL; /* pINChI_Aux has just been printed */
3146 : 0 : mult = 0;
3147 : 0 : eq2tautPrev = 1;
3148 : : }
3149 : : else
3150 : : {
3151 [ # # ]: 0 : if (eq2tautPrev)
3152 : : {
3153 : : /* at this point pINChI_Aux_Prev does not exist; however, pINChI_Aux */
3154 : : /*might have been discovered and it is different from pINChI_Aux_Taut */
3155 [ # # # # ]: 0 : if (multPrevEquStr && pPrevEquStr)
3156 : : {
3157 : : /* new EqStr is different; output it */
3158 [ # # ]: 0 : if (bNext++)
3159 : : {
3160 : 0 : MakeDelim( sCompDelim, strbuf, bOverflow );
3161 : : }
3162 : 0 : MakeEqStr( pPrevEquStr, multPrevEquStr, strbuf, bOverflow );
3163 : 0 : pPrevEquStr = NULL;
3164 : 0 : multPrevEquStr = 0;
3165 : : }
3166 : 0 : eq2tautPrev = 0;
3167 : 0 : pINChI_Aux_Prev = pINChI_Aux;
3168 : 0 : pINChI_Aux_Taut_Prev = pINChI_Aux_Taut;
3169 : 0 : mult = 0;
3170 : : }
3171 : : else
3172 : : {
3173 : : /* check whether pINChI_Aux and pINChI_Aux_Prev have identical non-trivial equivalence info */
3174 [ # # # # ]: 0 : eq2prev = bUseMulipliers && Eql_INChI_Aux_Equ( pINChI_Aux, EQL_EQU_ISO, pINChI_Aux_Prev, EQL_EQU_ISO );
3175 [ # # ]: 0 : if (eq2prev)
3176 : : {
3177 : : /* eq. info is same and non-trivial */
3178 : 0 : mult++; /* mult = (number of non-empty equal items)-1 */
3179 : 0 : continue;
3180 : : }
3181 : : else
3182 : : {
3183 : : /* pINChI_Aux eq. info is either different or trivial. Output pINChI_Aux_Prev anyway */
3184 [ # # ]: 0 : if (bNext++)
3185 : : {
3186 : 0 : MakeDelim( sCompDelim, strbuf, bOverflow );
3187 : : }
3188 [ # # # # ]: 0 : if (pINChI_Aux_Prev && pINChI_Aux_Prev->nNumberOfAtoms)
3189 : : {
3190 [ # # ]: 0 : if (bHasEquString( pINChI_Aux_Prev->nConstitEquIsotopicNumbers, pINChI_Aux_Prev->nNumberOfAtoms ))
3191 : : {
3192 : : /* pINChI_Aux_Prev exists and has equivalence info */
3193 : 0 : MakeMult( mult + 1, "*", strbuf, 0, bOverflow );
3194 : 0 : MakeEquString( pINChI_Aux_Prev->nConstitEquIsotopicNumbers, pINChI_Aux_Prev->nNumberOfAtoms, 0,
3195 : : strbuf, TAUT_MODE, bOverflow );
3196 : : }
3197 : : else
3198 : : {
3199 : : ; /* pINChI_Aux_Prev exists and has only trivial equivalence info */
3200 : : }
3201 : : }
3202 : : else
3203 : : {
3204 [ # # # # : 0 : if (bSecondNonTautPass && pINChI_Aux_Taut_Prev && pINChI_Aux_Taut_Prev->nNumberOfAtoms)
# # ]
3205 : : {
3206 : 0 : if (bHasEquString( pINChI_Aux_Taut_Prev->nConstitEquIsotopicNumbers, pINChI_Aux_Taut_Prev->nNumberOfAtoms ))
3207 : : {
3208 : : /* since pINChI_Aux_Prev does not exist, pINChI_Aux_Taut_Prev is non-tautomeric */
3209 : : /* and it has non-trivial equivalence info. This info has already been printed in the main section */
3210 : : /*
3211 : : MakeDelim( sIdenticalValues, strbuf, bOverflow);
3212 : : */
3213 : : }
3214 : : else
3215 : : {
3216 : : ; /* pINChI_Aux_Taut_Prev exists and has only trivial equivalence info */
3217 : : }
3218 : : }
3219 : : #if ( bRELEASE_VERSION != 1 && defined(_DEBUG) )
3220 : : else
3221 : : {
3222 : : int stop = 1; /* <BRKPT> */
3223 : : }
3224 : : #endif
3225 : : }
3226 : : }
3227 : 0 : pINChI_Aux_Prev = pINChI_Aux;
3228 : 0 : pINChI_Aux_Taut_Prev = pINChI_Aux_Taut;
3229 : 0 : mult = 0; /* we do not know whether the item is empty */
3230 : : }
3231 : : }
3232 : : }
3233 : :
3234 : 0 : return ( strbuf->nUsedLength - nUsedLength0 );
3235 : : }
3236 : :
3237 : :
3238 : : /****************************************************************************
3239 : : Produce isotopic tetr stereo inversion substring of AuxInfo.
3240 : : ****************************************************************************/
3241 : 0 : int str_AuxInvIsoSp3( INCHI_SORT *pINChISort,
3242 : : INCHI_SORT *pINChISort2,
3243 : : INCHI_IOS_STRING *strbuf,
3244 : : int *bOverflow,
3245 : : int bOutType,
3246 : : int TAUT_MODE,
3247 : : int num_components,
3248 : : int bSecondNonTautPass,
3249 : : int bOmitRepetitions,
3250 : : int bUseMulipliers )
3251 : : {
3252 : : int i, ii, ii2, nUsedLength0;
3253 : : INCHI_SORT *is, *is2, *is0, *is20;
3254 : : INChI *pINChI, *pINChI_Prev, *pINChI_Taut, *pINChI_Taut_Prev;
3255 : : INChI_Stereo *Stereo, *Stereo_Prev, *Stereo_Taut, *Stereo_Taut_Prev;
3256 : : int mult, eq2prev, eq2taut, eq2tautPrev, bNext;
3257 : : const char *pPrevEquStr, *pCurrEquStr;
3258 : : int multPrevEquStr;
3259 : : /********************************
3260 : : inverted isotopic sp3
3261 : : *********************************/
3262 : 0 : pINChI_Taut = NULL;
3263 : 0 : pINChI_Prev = NULL;
3264 : 0 : pINChI_Taut_Prev = NULL;
3265 : 0 : mult = 0;
3266 : 0 : bNext = 0;
3267 : 0 : is = NULL;
3268 : 0 : is2 = NULL;
3269 : 0 : is0 = pINChISort;
3270 [ # # ]: 0 : is20 = bSecondNonTautPass ? pINChISort2 : NULL;
3271 : : /* djb-rwth: removing redundant code */
3272 : 0 : eq2tautPrev = 1; /* pINChI_Prev (previous pINChI) does not exist */
3273 : 0 : pPrevEquStr = NULL; /*, *pCurrEquStr;*/
3274 : 0 : multPrevEquStr = 0;
3275 : 0 : nUsedLength0 = strbuf->nUsedLength;
3276 : :
3277 : : /* For each connected component... */
3278 [ # # ]: 0 : for (i = 0; i <= num_components; i++)
3279 : : {
3280 : :
3281 : : /* 1st (taut) pass: bOutType=OUT_TN ; 2nd (non-taut pass) bOutType=OUT_NT */
3282 [ # # # # : 0 : pINChI = ( i < num_components && ( is = is0 + i, 0 <= ( ii = GET_II( bOutType, is ) ) ) ) ? is->pINChI[ii] : NULL;
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # ]
3283 : : /*================ compare sp2 to previous =====================*/
3284 [ # # ]: 0 : if (bSecondNonTautPass)
3285 : : {
3286 : : /* component that was output on the 1st pass */
3287 [ # # # # : 0 : pINChI_Taut = ( i < num_components && ( is2 = is20 + i, 0 <= ( ii2 = GET_II( OUT_T1, is2 ) ) ) ) ? is2->pINChI[ii2] : NULL;
# # # # #
# # # ]
3288 : : }
3289 : 0 : eq2taut = 0;
3290 : : /*========= if bSecondNonTautPass then compare iso non-taut stereo to other stereo ========*/
3291 [ # # # # : 0 : if (bSecondNonTautPass && bOmitRepetitions && pINChI && pINChI->nNumberOfIsotopicAtoms + pINChI->nNumberOfIsotopicTGroups > 0)
# # # # ]
3292 : : {
3293 : : /* compare non-tautomeric isotopic inverted to:
3294 : : * a) tautomeric inverted
3295 : : * b) *non-tautomeric inverted
3296 : : * c) *isotopic tautomeric inverted
3297 : : * d) Inverted(tautomeric)
3298 : : * e) *Inverted(tautomeric isotopic)
3299 : : * f) Inverted(non-tautomeric)
3300 : : * g) *Inverted(non-tautomeric isotopic)
3301 : : */
3302 : : /* a) compare non-tautomeric isotopic inverted to tautomeric inverted */
3303 [ # # ]: 0 : if (!eq2taut)
3304 : : {
3305 [ # # ]: 0 : eq2taut = pINChI && pINChI_Taut &&
3306 : : /* non-taut inverted */ /* taut invertedc */
3307 [ # # # # : 0 : ( Stereo = pINChI->StereoIsotopic ) && ( Stereo_Taut = pINChI_Taut->Stereo ) &&
# # # # ]
3308 : 0 : Eql_INChI_Stereo( Stereo, EQL_SP3_INV, Stereo_Taut, EQL_SP3_INV, 0 );
3309 : : /* stereo-inv isotopic non-taut = taut (stereo-inv) */
3310 [ # # ]: 0 : eq2taut = eq2taut ? ( iiSTEREO_INV | iitISO | iitNONTAUT ) : 0;
3311 : : }
3312 : : /* b) compare non-tautomeric isotopic inverted to non-tautomeric inverted */
3313 [ # # ]: 0 : if (!eq2taut)
3314 : : {
3315 : 0 : eq2taut = pINChI && /* it is non-taut non-iso stereo */
3316 [ # # # # : 0 : ( Stereo = pINChI->StereoIsotopic ) && ( Stereo_Taut = pINChI->Stereo ) &&
# # # # ]
3317 : 0 : Eql_INChI_Stereo( Stereo, EQL_SP3_INV, Stereo_Taut, EQL_SP3_INV, 0 );
3318 : : /* stereo-inv isotopic non-taut = non-taut stereo-inv */
3319 [ # # ]: 0 : eq2taut = eq2taut ? ( iiSTEREO_INV | iitISO | iitNONTAUT | iiEq2NONTAUT ) : 0;
3320 : : }
3321 : : /* c) compare non-tautomeric isotopic inverted to isotopic tautomeric inverted */
3322 [ # # ]: 0 : if (!eq2taut)
3323 : : {
3324 [ # # ]: 0 : eq2taut = pINChI && pINChI_Taut &&
3325 : : /* non-taut iso. inverted */ /* taut iso. inverted */
3326 [ # # # # : 0 : ( Stereo = pINChI->StereoIsotopic ) && ( Stereo_Taut = pINChI_Taut->StereoIsotopic ) &&
# # # # ]
3327 : 0 : Eql_INChI_Stereo( Stereo, EQL_SP3_INV, Stereo_Taut, EQL_SP3_INV, 0 );
3328 : : /* stereo-inv isotopic non-taut = taut iso. stereo-inv */
3329 [ # # ]: 0 : eq2taut = eq2taut ? ( iiSTEREO_INV | iitISO | iitNONTAUT | iiEq2ISO ) : 0;
3330 : : }
3331 : : /* d) compare non-tautomeric inverted to Inverted(tautomeric stereo) */
3332 [ # # ]: 0 : if (!eq2taut)
3333 : : {
3334 [ # # ]: 0 : eq2taut = pINChI && pINChI_Taut &&
3335 [ # # # # : 0 : ( Stereo = pINChI->StereoIsotopic ) && ( Stereo_Taut = pINChI_Taut->Stereo ) &&
# # # # ]
3336 : 0 : Eql_INChI_Stereo( Stereo, EQL_SP3_INV, Stereo_Taut, EQL_SP3_INV, 0 );
3337 : : /* stereo-inv isotopic non-taut = Inv(non-iso taut stereo) */
3338 [ # # ]: 0 : eq2taut = eq2taut ? ( iiSTEREO_INV | iitISO | iitNONTAUT | iiEq2INV ) : 0;
3339 : : }
3340 : : /* e) compare non-tautomeric inverted to Inverted(isotopic tautomeric stereo) */
3341 [ # # ]: 0 : if (!eq2taut)
3342 : : {
3343 [ # # ]: 0 : eq2taut = pINChI && pINChI_Taut &&
3344 [ # # # # : 0 : ( Stereo = pINChI->StereoIsotopic ) && ( Stereo_Taut = pINChI_Taut->StereoIsotopic ) &&
# # # # ]
3345 : 0 : Eql_INChI_Stereo( Stereo, EQL_SP3_INV, Stereo_Taut, EQL_SP3, 0 );
3346 : : /* stereo-inv isotopic non-taut = Inv(iso taut stereo) */
3347 [ # # ]: 0 : eq2taut = eq2taut ? ( iiSTEREO_INV | iitISO | iitNONTAUT | iiEq2INV | iiEq2ISO ) : 0;
3348 : : }
3349 : : /* f) compare non-tautomeric isotopic inverted to Inverted(non-tautomeric stereo) */
3350 [ # # ]: 0 : if (!eq2taut)
3351 : : {
3352 : 0 : eq2taut = pINChI && /* it is non-taut non-iso stereo */
3353 [ # # # # : 0 : ( Stereo = pINChI->StereoIsotopic ) && ( Stereo_Taut = pINChI->Stereo ) &&
# # # # ]
3354 : 0 : Eql_INChI_Stereo( Stereo, EQL_SP3_INV, Stereo_Taut, EQL_SP3, 0 );
3355 : : /* stereo-inv isotopic non-taut = Inv(non-taut stereo) */
3356 [ # # ]: 0 : eq2taut = eq2taut ? ( iiSTEREO_INV | iitISO | iitNONTAUT | iiEq2INV | iiEq2NONTAUT ) : 0;
3357 : : }
3358 : : /* g) compare non-tautomeric isotopic inverted to Inverted(non-tautomeric isotopic stereo) */
3359 [ # # ]: 0 : if (!eq2taut)
3360 : : {
3361 : 0 : eq2taut = pINChI && /* it is non-taut non-iso stereo */
3362 [ # # # # : 0 : ( Stereo = pINChI->StereoIsotopic ) &&
# # ]
3363 : 0 : Eql_INChI_Stereo( Stereo, EQL_SP3_INV, Stereo, EQL_SP3, 0 );
3364 : : /* stereo-inv isotopic non-taut = Inv( iso non-taut stereo) */
3365 [ # # ]: 0 : eq2taut = eq2taut ? ( iiSTEREO_INV | iitISO | iitNONTAUT | iiEq2INV | iiEq2ISO | iiEq2NONTAUT ) : 0;
3366 : : }
3367 : : #if ( FIX_EMPTY_LAYER_BUG == 1 )
3368 : : if (!eq2taut && pINChI && !( ( Stereo = pINChI->StereoIsotopic ) &&
3369 : : Eql_INChI_Stereo( Stereo, EQL_SP3_INV, NULL, EQL_EXISTS, 0 ) ))
3370 : : {
3371 : : /* component has no stereo; check whether it has stereo in the preceding layers */
3372 : : if (pINChI_Taut && ( Stereo_Taut = pINChI_Taut->Stereo ) && /* F is not empty */
3373 : : Eql_INChI_Stereo( Stereo_Taut, EQL_SP3_INV, NULL, EQL_EXISTS, 0 ) ||
3374 : : !( pINChI_Taut && ( Stereo_Taut = pINChI_Taut->Stereo ) && /* M is empty and ... */
3375 : : Eql_INChI_Stereo( Stereo_Taut, EQL_SP3_INV, NULL, EQL_EXISTS, 0 ) ) &&
3376 : : ( pINChI_Taut && ( Stereo_Taut = pINChI_Taut->StereoIsotopic ) && /* ... MI is not empty */
3377 : : Eql_INChI_Stereo( Stereo_Taut, EQL_SP3_INV, NULL, EQL_EXISTS, 0 ) ))
3378 : : {
3379 : :
3380 : : eq2taut = iiEmpty; /* the component has stereo in the preceding layer */
3381 : : }
3382 : : }
3383 : : #endif
3384 : : }
3385 : : else
3386 : : {
3387 : : /*========= if not bSecondNonTautPass then compare inv taut stereo to various stereo ========*/
3388 [ # # # # : 0 : if (!bSecondNonTautPass && bOmitRepetitions && pINChI &&
# # ]
3389 [ # # ]: 0 : ( pINChI->nNumberOfIsotopicAtoms > 0 ||
3390 [ # # ]: 0 : pINChI->nNumberOfIsotopicTGroups > 0 ||
3391 [ # # # # ]: 0 : (pINChI->nPossibleLocationsOfIsotopicH && pINChI->nPossibleLocationsOfIsotopicH[0] > 1) )) /* djb-rwth: addressing LLVM warning */
3392 : : {
3393 : : /* compare tautomeric isotopic stereo-inverted to:
3394 : : * a) tautomeric stereo-inverted
3395 : : * b) Inverted(tautomeric stereo)
3396 : : * c) Inverted(tautomeric isotopic stereo)
3397 : : */
3398 : : /* a) compare tautomeric isotopic stereo-inverted to tautomeric stereo-inverted */
3399 [ # # ]: 0 : if (!eq2taut)
3400 : : {
3401 : 0 : eq2taut = pINChI &&
3402 [ # # # # : 0 : ( Stereo = pINChI->StereoIsotopic ) && ( Stereo_Taut = pINChI->Stereo ) &&
# # # # ]
3403 : 0 : Eql_INChI_Stereo( Stereo, EQL_SP3_INV, Stereo_Taut, EQL_SP3_INV, 0 );
3404 : : /* stereo-inv isotopic taut = taut stereo-inv */
3405 [ # # ]: 0 : eq2taut = eq2taut ? ( iiSTEREO_INV | iitISO ) : 0;
3406 : : }
3407 : : /* b) compare tautomeric isotopic stereo-inverted to Inverted(tautomeric stereo) */
3408 [ # # ]: 0 : if (!eq2taut)
3409 : : {
3410 : 0 : eq2taut = pINChI &&
3411 [ # # # # : 0 : ( Stereo = pINChI->StereoIsotopic ) && ( Stereo_Taut = pINChI->Stereo ) &&
# # # # ]
3412 : 0 : Eql_INChI_Stereo( Stereo, EQL_SP3_INV, Stereo_Taut, EQL_SP3, 0 );
3413 : : /* stereo-inv isotopic taut = Inv(taut stereo) */
3414 [ # # ]: 0 : eq2taut = eq2taut ? ( iiSTEREO_INV | iitISO | iiEq2INV ) : 0;
3415 : : }
3416 : : /* c) compare tautomeric isotopic stereo-inverted to Inverted(tautomeric isotopic stereo) */
3417 [ # # ]: 0 : if (!eq2taut)
3418 : : {
3419 : 0 : eq2taut = pINChI &&
3420 [ # # # # : 0 : ( Stereo = pINChI->StereoIsotopic ) &&
# # ]
3421 : 0 : Eql_INChI_Stereo( Stereo, EQL_SP3_INV, Stereo, EQL_SP3, 0 );
3422 : : /* stereo-inv isotopic taut = Inv(taut iso stereo) */
3423 [ # # ]: 0 : eq2taut = eq2taut ? ( iiSTEREO_INV | iitISO | iiEq2INV | iiEq2ISO ) : 0;
3424 : : }
3425 : : #if ( FIX_EMPTY_LAYER_BUG == 1 )
3426 : : if (!eq2taut && pINChI && !( ( Stereo = pINChI->StereoIsotopic ) &&
3427 : : Eql_INChI_Stereo( Stereo, EQL_SP3_INV, NULL, EQL_EXISTS, 0 ) ))
3428 : : {
3429 : : /* component has no MI stereo; check whether it has stereo in the preceding layer M */
3430 : : if (( Stereo_Taut = pINChI->Stereo ) &&
3431 : : Eql_INChI_Stereo( Stereo_Taut, EQL_SP3_INV, NULL, EQL_EXISTS, 0 ))
3432 : : {
3433 : : eq2taut = iiEmpty; /* the component has stereo in the preceding layer */
3434 : : }
3435 : : }
3436 : : #endif
3437 : : }
3438 : : }
3439 [ # # ]: 0 : if (eq2taut)
3440 : : {
3441 : : /* we may be here only in case of the current layer found equal in another layer the same component */
3442 [ # # # # ]: 0 : if (pINChI_Prev && pINChI_Prev->nNumberOfAtoms)
3443 : : {
3444 : : /* previous component exists; output it before output the current component */
3445 [ # # ]: 0 : if (bNext++)
3446 : : {
3447 : 0 : MakeDelim( sCompDelim, strbuf, bOverflow );
3448 : : }
3449 [ # # # # ]: 0 : if (( Stereo_Prev = pINChI_Prev->StereoIsotopic ) && Stereo_Prev->nNumberOfStereoCenters > 0)
3450 : : {
3451 : 0 : MakeMult( mult + 1, "*", strbuf, 0, bOverflow );
3452 : :
3453 : 0 : MakeStereoString( Stereo_Prev->nNumber, NULL, Stereo_Prev->t_parityInv,
3454 : : 0, Stereo_Prev->nNumberOfStereoCenters,
3455 : : strbuf, TAUT_MODE, bOverflow );
3456 : : }
3457 : : }
3458 : : else
3459 : : {
3460 [ # # # # ]: 0 : if (pINChI_Taut_Prev && pINChI_Taut_Prev->nNumberOfAtoms)
3461 : : {
3462 : : /* previous non-taut component exists only in taut list */
3463 [ # # ]: 0 : if (bNext++)
3464 : : {
3465 : 0 : MakeDelim( sCompDelim, strbuf, bOverflow );
3466 : : }
3467 : : /* do not output stereo of non-tautomeric in non-taut layer: it has been output in the main layer */
3468 : : }
3469 : : }
3470 : : /* we have found another (previously printed) layer of the current component equal to this layer */
3471 : : /* output this (current) equivalence mark = EquString(eq2taut) */
3472 : 0 : pCurrEquStr = EquString( eq2taut );
3473 [ # # # # ]: 0 : if (multPrevEquStr && pPrevEquStr)
3474 : : {
3475 [ # # # # ]: 0 : if (pCurrEquStr && !strcmp( pCurrEquStr, pPrevEquStr ))
3476 : : {
3477 : 0 : multPrevEquStr++;
3478 : : }
3479 : : else
3480 : : {
3481 : : /* new EqStr is different; output it */
3482 [ # # ]: 0 : if (bNext++)
3483 : : {
3484 : 0 : MakeDelim( sCompDelim, strbuf, bOverflow );
3485 : : }
3486 : 0 : MakeEqStr( pPrevEquStr, multPrevEquStr, strbuf, bOverflow );
3487 : 0 : pPrevEquStr = pCurrEquStr;
3488 : 0 : multPrevEquStr = 1;
3489 : : }
3490 : : }
3491 : : else
3492 : : {
3493 : 0 : pPrevEquStr = pCurrEquStr;
3494 : 0 : multPrevEquStr = 1;
3495 : : }
3496 : 0 : pINChI_Prev = NULL; /* pINChI_Prev sp2 does not exist since */
3497 : 0 : pINChI_Taut_Prev = NULL; /* pINChI has just been printed */
3498 : 0 : mult = 0;
3499 : 0 : eq2tautPrev = 1; /* pINChI_Prev and pINChI_Taut_Prev have already been output */
3500 : : }
3501 : : else
3502 : : {
3503 [ # # ]: 0 : if (eq2tautPrev)
3504 : : {
3505 : : /* at this point pINChI_Prev does not exist; however, pINChI */
3506 : : /*might have been discovered and it is different from pINChI_Taut */
3507 [ # # # # ]: 0 : if (multPrevEquStr && pPrevEquStr)
3508 : : {
3509 : : /* new EqStr is different; output it */
3510 [ # # ]: 0 : if (bNext++)
3511 : : {
3512 : 0 : MakeDelim( sCompDelim, strbuf, bOverflow );
3513 : : }
3514 : 0 : MakeEqStr( pPrevEquStr, multPrevEquStr, strbuf, bOverflow );
3515 : 0 : pPrevEquStr = NULL;
3516 : 0 : multPrevEquStr = 0;
3517 : : }
3518 : 0 : eq2tautPrev = 0;
3519 : 0 : pINChI_Prev = pINChI;
3520 : 0 : pINChI_Taut_Prev = pINChI_Taut;
3521 : 0 : mult = 0;
3522 : : }
3523 : : else
3524 : : {
3525 : : /* current layer is different from previously printed layers of the current component */
3526 : : /* compare the current layer to this layer of the previous component: */
3527 : : /* check whether pINChI and pINChI_Prev have non-zero identical stereo sp2 */
3528 : : /*================ compare iso sp3 to previous =====================*/
3529 [ # # ]: 0 : eq2prev = bUseMulipliers &&
3530 [ # # # # ]: 0 : pINChI && pINChI->nNumberOfIsotopicAtoms + pINChI->nNumberOfIsotopicTGroups > 0 &&
3531 [ # # ]: 0 : pINChI_Prev && pINChI_Prev->nNumberOfIsotopicAtoms + pINChI_Prev->nNumberOfIsotopicTGroups > 0 &&
3532 : : /* do both have stereo? */
3533 [ # # # # : 0 : ( Stereo = pINChI->StereoIsotopic ) && ( Stereo_Prev = pINChI_Prev->StereoIsotopic ) &&
# # # # ]
3534 : : /* is their inverted stereo same? */
3535 : 0 : Eql_INChI_Stereo( Stereo, EQL_SP3_INV, Stereo_Prev, EQL_SP3_INV, 0 );
3536 [ # # ]: 0 : if (eq2prev)
3537 : : {
3538 : 0 : mult++; /* mult = (number of non-empty equal items)-1 */
3539 : 0 : continue;
3540 : : }
3541 : : else
3542 : : {
3543 [ # # ]: 0 : if (bNext++)
3544 : : {
3545 : 0 : MakeDelim( sCompDelim, strbuf, bOverflow );
3546 : : }
3547 [ # # # # : 0 : if (pINChI_Prev && pINChI_Prev->nNumberOfAtoms && pINChI_Prev->nNumberOfIsotopicAtoms + pINChI_Prev->nNumberOfIsotopicTGroups > 0)
# # ]
3548 : : {
3549 [ # # ]: 0 : if (( Stereo_Prev = pINChI_Prev->StereoIsotopic ) &&
3550 [ # # # # ]: 0 : Stereo_Prev->nNumberOfStereoCenters > 0 && Stereo_Prev->nCompInv2Abs)
3551 : : {
3552 : 0 : MakeMult( mult + 1, "*", strbuf, 0, bOverflow );
3553 : :
3554 : 0 : MakeStereoString( Stereo_Prev->nNumberInv, NULL, Stereo_Prev->t_parityInv,
3555 : : 0, Stereo_Prev->nNumberOfStereoCenters,
3556 : : strbuf, TAUT_MODE, bOverflow );
3557 : : }
3558 : : /* else sp3 info is not present in pINChI_Prev */
3559 : : }
3560 : : else
3561 : : {
3562 : : /* do not print pINChI_Prev because it either do not exist of have already been printed */
3563 [ # # # # : 0 : if (bSecondNonTautPass && pINChI_Taut_Prev && pINChI_Taut_Prev->nNumberOfAtoms)
# # ]
3564 : : {
3565 [ # # ]: 0 : if (( Stereo_Taut_Prev = pINChI_Taut_Prev->StereoIsotopic ) &&
3566 [ # # ]: 0 : Stereo_Taut_Prev->nNumberOfStereoCenters > 0 && Stereo_Taut_Prev->nCompInv2Abs)
3567 : : {
3568 : : /* since pINChI_Prev does not exist, pINChI_Taut_Prev is non-tautomeric */
3569 : : /* and it has non-trivial inv sp3 info. It has already been printed in the main section */
3570 : : /*
3571 : : tot_len += MakeDelim( sIdenticalValues, strbuf, bOverflow);
3572 : : */
3573 : : ;/* pINChI_Taut_Prev sp3 info was output in the main stereo section */
3574 : : }
3575 : : else
3576 : : {
3577 : : ; /* pINChI_Taut_Prev exists and has not sp3 info */
3578 : : }
3579 : : }
3580 : : #if ( bRELEASE_VERSION != 1 && defined(_DEBUG) )
3581 : : else
3582 : : {
3583 : : int stop = 1; /* <BRKPT> */
3584 : : }
3585 : : #endif
3586 : : }
3587 : : }
3588 : 0 : pINChI_Prev = pINChI;
3589 : 0 : mult = 0; /* we do not know whether the item is empty */
3590 : : }
3591 : : }
3592 : : }
3593 : :
3594 : 0 : return ( strbuf->nUsedLength - nUsedLength0 );
3595 : : }
3596 : :
3597 : :
3598 : : /****************************************************************************
3599 : : Produce isotopic tetr stereo inversion numbering substring of AuxInfo
3600 : : /iN: in Isotopic and/or FixedH-Iso parts,
3601 : : in both normal and in reconnected layers
3602 : : ****************************************************************************/
3603 : 0 : int str_AuxInvIsoSp3Numb( CANON_GLOBALS *pCG,
3604 : : INCHI_SORT *pINChISort,
3605 : : INCHI_SORT *pINChISort2,
3606 : : INCHI_IOS_STRING *strbuf,
3607 : : int *bOverflow,
3608 : : int bOutType,
3609 : : int TAUT_MODE,
3610 : : int num_components,
3611 : : int bSecondNonTautPass,
3612 : : int bOmitRepetitions )
3613 : : {
3614 : : int i, ii, ii2, nUsedLength0;
3615 : : INCHI_SORT *is, *is0 /*, *is2*/;
3616 : : INChI *pINChI, *pINChI_Taut;
3617 : : INChI_Aux *pINChI_Aux, *pINChI_Aux_Taut; /* djb-rwth: removing redundant variables */
3618 : : INChI_Stereo *Stereo, *Stereo_Taut;
3619 : : int eq2taut, bNext;
3620 : : const char *pPrevEquStr, *pCurrEquStr;
3621 : : int multPrevEquStr;
3622 : : /**************************************************
3623 : : * specificity of numbering: there is no previous *
3624 : : * component because no repetition is possible *
3625 : : **************************************************/
3626 : 0 : pINChI = NULL;
3627 : 0 : pINChI_Taut = NULL;
3628 : 0 : pINChI_Aux = NULL;
3629 : 0 : pINChI_Aux_Taut = NULL;
3630 : : /* djb-rwth: removing redundant code */
3631 : 0 : bNext = 0;
3632 : 0 : is = NULL;
3633 : : /* is2 = NULL;*/
3634 : 0 : is0 = pINChISort;
3635 : : /* is20 = bSecondNonTautPass? pINChISort2 : NULL;*/
3636 : : /* djb-rwth: removing redundant code */
3637 : 0 : pPrevEquStr = NULL; /*, *pCurrEquStr;*/
3638 : 0 : multPrevEquStr = 0;
3639 : 0 : nUsedLength0 = strbuf->nUsedLength;
3640 : :
3641 : : /* For each connected component... */
3642 [ # # ]: 0 : for (i = 0; i < num_components; i++)
3643 : : {
3644 : :
3645 : : /* 1st (taut) pass: bOutType=OUT_TN ; 2nd (non-taut pass) bOutType=OUT_NT */
3646 : 0 : is = is0 + i;
3647 [ # # # # : 0 : pINChI = ( 0 <= ( ii = GET_II( bOutType, is ) ) ) ? is->pINChI[ii] : NULL;
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # ]
3648 [ # # ]: 0 : pINChI_Aux = pINChI ? is->pINChI_Aux[ii] : NULL;
3649 : : /*================ to compare to previously printed =====================*/
3650 [ # # ]: 0 : if (bSecondNonTautPass)
3651 : : {
3652 : : /* component that was printed on the 1st pass */
3653 [ # # # # : 0 : pINChI_Taut = ( 0 <= ( ii2 = GET_II( OUT_T1, is ) ) ) ? is->pINChI[ii2] : NULL;
# # # # #
# ]
3654 [ # # ]: 0 : pINChI_Aux_Taut = pINChI_Taut ? is->pINChI_Aux[ii2] : NULL;
3655 : : }
3656 : 0 : eq2taut = 0;
3657 : : /*========= if bSecondNonTautPass then compare iso non-taut stereo to other stereo ========*/
3658 [ # # # # : 0 : if (bSecondNonTautPass && bOmitRepetitions && pINChI && pINChI_Aux && pINChI_Aux->bIsIsotopic &&
# # # # #
# ]
3659 [ # # # # ]: 0 : ( Stereo = pINChI->StereoIsotopic ) && Stereo->nCompInv2Abs &&
3660 [ # # # # ]: 0 : pINChI_Aux->nNumberOfAtoms > 0 && pINChI_Aux->nIsotopicOrigAtNosInCanonOrdInv)
3661 : : {
3662 : : /* compare isotopic non-tautomeric inverted stereo numbering to:
3663 : : * a) tautomeric numbering
3664 : : * b) non-tautomeric numbering
3665 : : * c) *tautomeric isotopic numbering
3666 : : * d) *non-tautomeric isotopic numbering
3667 : : * e) tautomeric inverted stereo numbering
3668 : : * f) *non-tautomeric inverted stereo numbering
3669 : : * g) tautomeric isotopic inverted stereo numbering
3670 : : */
3671 : : /* a) compare isotopic non-tautomeric inverted stereo numbering to tautomeric numbering */
3672 [ # # ]: 0 : if (!eq2taut)
3673 : : {
3674 [ # # # # ]: 0 : eq2taut = pINChI_Taut &&
3675 : 0 : Eql_INChI_Aux_Num( pINChI_Aux, EQL_NUM_INV | EQL_NUM_ISO, pINChI_Aux_Taut, EQL_NUM );
3676 : : /* stereo-inv isotopic numbering non-taut = taut numbering */
3677 [ # # ]: 0 : eq2taut = eq2taut ? ( iiSTEREO_INV | iitISO | iiNUMB | iitNONTAUT ) : 0;
3678 : : }
3679 : : /* b) compare isotopic non-tautomeric inverted stereo numbering to non-tautomeric numbering */
3680 [ # # ]: 0 : if (!eq2taut)
3681 : : {
3682 : : eq2taut =
3683 : 0 : Eql_INChI_Aux_Num( pINChI_Aux, EQL_NUM_INV | EQL_NUM_ISO, pINChI_Aux, EQL_NUM );
3684 : : /* stereo-inv isotopic numb. non-taut = non-taut numbering */
3685 [ # # ]: 0 : eq2taut = eq2taut ? ( iiSTEREO_INV | iitISO | iiNUMB | iitNONTAUT | iiEq2NONTAUT ) : 0;
3686 : : }
3687 : : /* c) compare isotopic non-tautomeric inverted stereo numbering to tautomeric isotopic numbering */
3688 [ # # ]: 0 : if (!eq2taut)
3689 : : {
3690 [ # # # # ]: 0 : eq2taut = pINChI_Taut &&
3691 : 0 : Eql_INChI_Aux_Num( pINChI_Aux, EQL_NUM_INV | EQL_NUM_ISO, pINChI_Aux_Taut, EQL_NUM_ISO );
3692 : : /* stereo-inv isotopic numb. non-taut = taut iso numbering */
3693 [ # # ]: 0 : eq2taut = eq2taut ? ( iiSTEREO_INV | iitISO | iiNUMB | iitNONTAUT | iiEq2ISO ) : 0;
3694 : : }
3695 : : /* d) compare isotopic non-tautomeric inverted stereo numbering to non-tautomeric isotopic numbering */
3696 [ # # ]: 0 : if (!eq2taut)
3697 : : {
3698 : 0 : eq2taut = Eql_INChI_Aux_Num( pINChI_Aux, EQL_NUM_INV | EQL_NUM_ISO, pINChI_Aux, EQL_NUM_ISO );
3699 : : /* stereo-inv isotopic numb. non-taut = non-taut isotopic numbering */
3700 [ # # ]: 0 : eq2taut = eq2taut ? ( iiSTEREO_INV | iitISO | iiNUMB | iitNONTAUT | iiEq2NONTAUT | iiEq2ISO ) : 0;
3701 : : }
3702 : : /* e) compare isotopic non-tautomeric inverted stereo numbering to tautomeric inverted stereo numbering */
3703 [ # # ]: 0 : if (!eq2taut)
3704 : : {
3705 [ # # ]: 0 : eq2taut = pINChI_Taut && pINChI_Aux_Taut &&
3706 [ # # # # : 0 : ( Stereo_Taut = pINChI_Taut->Stereo ) && Stereo_Taut->nCompInv2Abs &&
# # # # ]
3707 : 0 : Eql_INChI_Aux_Num( pINChI_Aux, EQL_NUM_INV | EQL_NUM_ISO, pINChI_Aux_Taut, EQL_NUM_INV );
3708 : : /* stereo-inv isotopic numbering non-taut = stereo-inv taut numbering */
3709 [ # # ]: 0 : eq2taut = eq2taut ? ( iiSTEREO_INV | iitISO | iiNUMB | iitNONTAUT | iiEq2INV ) : 0;
3710 : : }
3711 : : /* f) compare isotopic non-tautomeric inverted stereo numbering to non-tautomeric inverted stereo numbering */
3712 [ # # ]: 0 : if (!eq2taut)
3713 : : {
3714 : 0 : eq2taut =
3715 [ # # # # : 0 : ( Stereo_Taut = pINChI->StereoIsotopic ) && Stereo_Taut->nCompInv2Abs &&
# # ]
3716 : 0 : Eql_INChI_Aux_Num( pINChI_Aux, EQL_NUM_INV | EQL_NUM_ISO, pINChI_Aux, EQL_NUM_INV );
3717 : : /* stereo-inv isotopic numbering non-taut = stereo-inv non-taut numbering */
3718 [ # # ]: 0 : eq2taut = eq2taut ? ( iiSTEREO_INV | iitISO | iiNUMB | iitNONTAUT | iiEq2INV | iiEq2NONTAUT ) : 0;
3719 : : }
3720 : :
3721 : : /* g) compare isotopic non-tautomeric inverted stereo numbering to tautomeric isotopic inverted stereo numbering */
3722 [ # # ]: 0 : if (!eq2taut)
3723 : : {
3724 : 0 : eq2taut = pINChI_Taut &&
3725 [ # # # # : 0 : ( Stereo_Taut = pINChI_Taut->StereoIsotopic ) && Stereo_Taut->nCompInv2Abs &&
# # # # ]
3726 : 0 : Eql_INChI_Aux_Num( pINChI_Aux, EQL_NUM_INV | EQL_NUM_ISO, pINChI_Aux_Taut, EQL_NUM_INV | EQL_NUM_ISO );
3727 : : /* stereo-inv isotopic numbering non-taut = stereo-inv iso taut numbering */
3728 [ # # ]: 0 : eq2taut = eq2taut ? ( iiSTEREO_INV | iitISO | iiNUMB | iitNONTAUT | iiEq2INV | iiEq2ISO ) : 0;
3729 : : }
3730 : : }
3731 : : else
3732 : : {
3733 : : /*========= if not bSecondNonTautPass then compare inv taut stereo numb to taut numb ========*/
3734 [ # # # # : 0 : if (!bSecondNonTautPass && bOmitRepetitions && pINChI && pINChI_Aux && pINChI_Aux->bIsIsotopic &&
# # # # #
# ]
3735 [ # # # # ]: 0 : ( Stereo = pINChI->StereoIsotopic ) && Stereo->nCompInv2Abs &&
3736 [ # # # # ]: 0 : pINChI_Aux->nNumberOfAtoms > 0 && pINChI_Aux->nIsotopicOrigAtNosInCanonOrdInv)
3737 : : {
3738 : : /* compare isotopic tautomeric inverted stereo numbering to:
3739 : : * a) tautomeric numbering
3740 : : * b) tautomeric isotopic numbering
3741 : : * c) tautomeric inverted stereo numbering
3742 : : */
3743 : : /* a) compare isotopic tautomeric inverted stereo numbering to tautomeric numbering */
3744 [ # # ]: 0 : if (!eq2taut)
3745 : : {
3746 : 0 : eq2taut = Eql_INChI_Aux_Num( pINChI_Aux, EQL_NUM_INV | EQL_NUM_ISO, pINChI_Aux, EQL_NUM );
3747 : : /* stereo-inv isotopic numbering (taut) = taut numbering */
3748 [ # # ]: 0 : eq2taut = eq2taut ? ( iiSTEREO_INV | iitISO | iiNUMB ) : 0;
3749 : : }
3750 : : /* b) compare isotopic tautomeric inverted stereo numbering to tautomeric isotopic numbering */
3751 [ # # ]: 0 : if (!eq2taut)
3752 : : {
3753 : 0 : eq2taut = Eql_INChI_Aux_Num( pINChI_Aux, EQL_NUM_INV | EQL_NUM_ISO, pINChI_Aux, EQL_NUM_ISO );
3754 : : /* stereo-inv isotopic numbering(taut) = isotopic taut numbering */
3755 [ # # ]: 0 : eq2taut = eq2taut ? ( iiSTEREO_INV | iitISO | iiNUMB | iiEq2ISO ) : 0;
3756 : : }
3757 : : /* b) compare isotopic tautomeric inverted stereo numbering to tautomeric inverted stereo numbering */
3758 [ # # ]: 0 : if (!eq2taut)
3759 : : {
3760 [ # # # # : 0 : eq2taut = pINChI->Stereo && Stereo->nCompInv2Abs &&
# # ]
3761 : 0 : Eql_INChI_Aux_Num( pINChI_Aux, EQL_NUM_INV | EQL_NUM_ISO, pINChI_Aux, EQL_NUM_INV ); /* djb-rwth: removing redundant code */
3762 : : /* stereo-inv isotopic numbering (taut) = taut stereo-inv numbering */
3763 [ # # ]: 0 : eq2taut = eq2taut ? ( iiSTEREO_INV | iitISO | iiNUMB | iiEq2INV ) : 0;
3764 : : }
3765 : : }
3766 : : }
3767 [ # # ]: 0 : if (eq2taut)
3768 : : {
3769 : : /* we have found another (previously printed) layer of the current component equal to this layer */
3770 : : /* output this (current) equivalence mark = EquString(eq2taut) */
3771 : 0 : pCurrEquStr = EquString( eq2taut );
3772 [ # # # # ]: 0 : if (multPrevEquStr && pPrevEquStr)
3773 : : {
3774 [ # # # # ]: 0 : if (pCurrEquStr && !strcmp( pCurrEquStr, pPrevEquStr ))
3775 : : {
3776 : 0 : multPrevEquStr++;
3777 : : }
3778 : : else
3779 : : {
3780 : : /* new EqStr is different; output it */
3781 [ # # ]: 0 : if (bNext++)
3782 : : {
3783 : 0 : MakeDelim( sCompDelim, strbuf, bOverflow );
3784 : : }
3785 : 0 : MakeEqStr( pPrevEquStr, multPrevEquStr, strbuf, bOverflow );
3786 : 0 : pPrevEquStr = pCurrEquStr;
3787 : 0 : multPrevEquStr = 1;
3788 : : }
3789 : : }
3790 : : else
3791 : : {
3792 : 0 : pPrevEquStr = pCurrEquStr;
3793 : 0 : multPrevEquStr = 1;
3794 : : }
3795 : : }
3796 : : else
3797 : : {
3798 : : /* current layer is different from previously printed layers of the current component */
3799 [ # # # # ]: 0 : if (multPrevEquStr && pPrevEquStr)
3800 : : {
3801 : : /* new EqStr is different; output it */
3802 [ # # ]: 0 : if (bNext++)
3803 : : {
3804 : 0 : MakeDelim( sCompDelim, strbuf, bOverflow );
3805 : : }
3806 : 0 : MakeEqStr( pPrevEquStr, multPrevEquStr, strbuf, bOverflow );
3807 : 0 : pPrevEquStr = NULL;
3808 : 0 : multPrevEquStr = 0;
3809 : : }
3810 [ # # ]: 0 : if (bNext++)
3811 : : {
3812 : 0 : MakeDelim( sCompDelim, strbuf, bOverflow );
3813 : : }
3814 [ # # # # : 0 : if (pINChI && pINChI_Aux && pINChI_Aux->bIsIsotopic && pINChI_Aux->nNumberOfAtoms &&
# # # # ]
3815 [ # # # # ]: 0 : ( Stereo = pINChI->StereoIsotopic ) && Stereo->nNumberOfStereoCenters &&
3816 [ # # # # ]: 0 : Stereo->nCompInv2Abs && pINChI_Aux->nIsotopicOrigAtNosInCanonOrdInv)
3817 : : {
3818 : 0 : MakeCtString( pCG, pINChI_Aux->nIsotopicOrigAtNosInCanonOrdInv,
3819 : : pINChI_Aux->nNumberOfAtoms, 0, NULL, 0,
3820 : : strbuf, TAUT_MODE, bOverflow );
3821 : : }
3822 : : /* else isotopic inv stereo info is not present in pINChI */
3823 : : }
3824 : : }
3825 [ # # # # ]: 0 : if (multPrevEquStr && pPrevEquStr)
3826 : : {
3827 : : /* the new EqStr of the last item has not been printed; output it now */
3828 [ # # ]: 0 : if (bNext++)
3829 : : {
3830 : 0 : MakeDelim( sCompDelim, strbuf, bOverflow );
3831 : : }
3832 : 0 : MakeEqStr( pPrevEquStr, multPrevEquStr, strbuf, bOverflow );
3833 : 0 : pPrevEquStr = NULL;
3834 : : /* djb-rwth: removing redundant code */
3835 : : }
3836 : :
3837 : 0 : return ( strbuf->nUsedLength - nUsedLength0 );
3838 : : }
3839 : :
3840 : :
3841 : : /****************************************************************************
3842 : : Produce numbering substring of AuxInfo
3843 : : /N: in Main and/or /F: in FixedH part,
3844 : : in both normal and in reconnected layers
3845 : : ****************************************************************************/
3846 : 54 : int str_AuxNumb( CANON_GLOBALS *pCG,
3847 : : INCHI_SORT *pINChISort,
3848 : : INCHI_SORT *pINChISort2,
3849 : : INCHI_IOS_STRING *strbuf,
3850 : : int *bOverflow,
3851 : : int bOutType,
3852 : : int TAUT_MODE,
3853 : : int num_components,
3854 : : int bSecondNonTautPass,
3855 : : int bOmitRepetitions )
3856 : : {
3857 : : int i, ii, ii2, nUsedLength0;
3858 : : INCHI_SORT *is, *is0 /*, *is2*/;
3859 : 54 : INChI *pINChI, *pINChI_Taut = NULL;
3860 : 54 : INChI_Aux *pINChI_Aux, *pINChI_Aux_Taut = NULL;
3861 : : int eq2taut, bNext;
3862 : : const char *pPrevEquStr, *pCurrEquStr;
3863 : : int multPrevEquStr;
3864 : 54 : bNext = 0;
3865 : : /*is2 = bSecondNonTautPass? pINChISort2 : NULL;*/
3866 : : /* djb-rwth: removing redundant code */
3867 : 54 : pPrevEquStr = NULL; /*, *pCurrEquStr;*/
3868 : 54 : multPrevEquStr = 0;
3869 : 54 : is = NULL;
3870 : 54 : nUsedLength0 = strbuf->nUsedLength;
3871 : :
3872 [ - + ]: 54 : if (!( is0 = pINChISort ))
3873 : : {
3874 : 0 : return nUsedLength0;
3875 : : }
3876 : :
3877 : : /* For each connected component... */
3878 [ + + ]: 123 : for (i = 0; i < num_components; i++)
3879 : : {
3880 : : /* 1st (taut) pass: bOutType=OUT_TN ; 2nd (non-taut pass) bOutType=OUT_NT */
3881 : 69 : is = is0 + i;
3882 [ - + - - : 69 : pINChI = ( 0 <= ( ii = GET_II( bOutType, is ) ) ) ? is->pINChI[ii] : NULL;
- - - - -
- - - - -
+ - + - +
- - + - -
- - - - -
- - - - -
- - - - -
- - - - -
- - - - -
- - - - -
+ - ]
3883 [ + - ]: 69 : pINChI_Aux = pINChI ? is->pINChI_Aux[ii] : NULL;
3884 : : /*================ to compare to previously printed =====================*/
3885 [ - + ]: 69 : if (bSecondNonTautPass)
3886 : : {
3887 : : /* component that was printed on the 1st pass */
3888 [ # # # # : 0 : pINChI_Taut = ( 0 <= ( ii2 = GET_II( OUT_T1, is ) ) ) ? is->pINChI[ii2] : NULL;
# # # # #
# ]
3889 [ # # ]: 0 : pINChI_Aux_Taut = pINChI_Taut ? is->pINChI_Aux[ii2] : NULL;
3890 : : }
3891 : 69 : eq2taut = 0;
3892 : : /*========= if bSecondNonTautPass then compare iso non-taut stereo to other stereo ========*/
3893 [ - + - - : 69 : if (bSecondNonTautPass && bOmitRepetitions && pINChI && pINChI_Aux && pINChI_Aux->nNumberOfAtoms > 0)
- - - - -
- ]
3894 : : {
3895 : : /* compare non-tautomeric numbering to:
3896 : : * a) tautomeric numbering
3897 : : */
3898 : : /* a) compare non-tautomeric numbering to tautomeric numbering */
3899 [ # # ]: 0 : if (!eq2taut)
3900 : : {
3901 [ # # # # : 0 : eq2taut = pINChI_Taut && !pINChI_Taut->bDeleted &&
# # ]
3902 : 0 : Eql_INChI_Aux_Num( pINChI_Aux, EQL_NUM, pINChI_Aux_Taut, EQL_NUM );
3903 : : /* numbering non-taut = taut numbering */
3904 [ # # ]: 0 : eq2taut = eq2taut ? ( iiNUMB | iitNONTAUT ) : 0;
3905 : : }
3906 : : }
3907 [ - + ]: 69 : if (eq2taut)
3908 : : {
3909 : : /* we have found another (previously printed) layer of the current component equal to this layer */
3910 : : /* output this (current) equivalence mark = EquString(eq2taut) */
3911 : 0 : pCurrEquStr = EquString( eq2taut );
3912 [ # # # # ]: 0 : if (multPrevEquStr && pPrevEquStr)
3913 : : {
3914 [ # # # # ]: 0 : if (pCurrEquStr && !strcmp( pCurrEquStr, pPrevEquStr ))
3915 : : {
3916 : 0 : multPrevEquStr++;
3917 : : }
3918 : : else
3919 : : {
3920 : : /* new EqStr is different; output it */
3921 [ # # ]: 0 : if (bNext++)
3922 : : {
3923 : 0 : MakeDelim( sCompDelim, strbuf, bOverflow );
3924 : : }
3925 : 0 : MakeEqStr( pPrevEquStr, multPrevEquStr, strbuf, bOverflow );
3926 : 0 : pPrevEquStr = pCurrEquStr;
3927 : 0 : multPrevEquStr = 1;
3928 : : }
3929 : : }
3930 : : else
3931 : : {
3932 : 0 : pPrevEquStr = pCurrEquStr;
3933 : 0 : multPrevEquStr = 1;
3934 : : }
3935 : : }
3936 : : else
3937 : : {
3938 : : /* current layer is different from previously printed layers of the current component */
3939 [ - + - - ]: 69 : if (multPrevEquStr && pPrevEquStr)
3940 : : {
3941 : : /* new EqStr is different; output it */
3942 [ # # ]: 0 : if (bNext++)
3943 : : {
3944 : 0 : MakeDelim( sCompDelim, strbuf, bOverflow );
3945 : : }
3946 : 0 : MakeEqStr( pPrevEquStr, multPrevEquStr, strbuf, bOverflow );
3947 : 0 : pPrevEquStr = NULL;
3948 : 0 : multPrevEquStr = 0;
3949 : : }
3950 [ + + ]: 69 : if (bNext++)
3951 : : {
3952 : 15 : MakeDelim( sCompDelim, strbuf, bOverflow );
3953 : : }
3954 [ + - + - : 69 : if (pINChI && pINChI_Aux && pINChI_Aux->nNumberOfAtoms)
+ - ]
3955 : : {
3956 : 69 : MakeCtString( pCG, pINChI_Aux->nOrigAtNosInCanonOrd,
3957 : : pINChI_Aux->nNumberOfAtoms, 0, NULL, 0,
3958 : : strbuf, TAUT_MODE, bOverflow );
3959 : : }
3960 : : }
3961 : : }
3962 [ - + - - ]: 54 : if (multPrevEquStr && pPrevEquStr)
3963 : : {
3964 : : /* the new EqStr of the last item has not been printed; output it now */
3965 [ # # ]: 0 : if (bNext++)
3966 : : {
3967 : 0 : MakeDelim( sCompDelim, strbuf, bOverflow );
3968 : : }
3969 : 0 : MakeEqStr( pPrevEquStr, multPrevEquStr, strbuf, bOverflow );
3970 : 0 : pPrevEquStr = NULL;
3971 : : /* djb-rwth: removing redundant code */
3972 : : }
3973 : :
3974 : 54 : return ( strbuf->nUsedLength - nUsedLength0 );
3975 : : }
3976 : :
3977 : :
3978 : : /****************************************************************************
3979 : : Produce TGroup equivalence substring of AuxInfo
3980 : : ****************************************************************************/
3981 : 0 : int str_AuxTgroupEqu( INCHI_SORT *pINChISort,
3982 : : INCHI_IOS_STRING *strbuf,
3983 : : int *bOverflow,
3984 : : int bOutType,
3985 : : int TAUT_MODE,
3986 : : int num_components,
3987 : : int bUseMulipliers )
3988 : : {
3989 : : int i, ii, nUsedLength0;
3990 : : INCHI_SORT *is, *is0;
3991 : : INChI_Aux *pINChI_Aux, *pINChI_Aux_Prev;
3992 : : int mult, eq2prev, bNext;
3993 : :
3994 : 0 : nUsedLength0 = strbuf->nUsedLength;
3995 : :
3996 : 0 : is0 = pINChISort;
3997 : 0 : is = NULL;
3998 : 0 : i = 0;
3999 [ # # # # : 0 : pINChI_Aux_Prev = ( 0 <= ( ii = GET_II( bOutType, is0 ) ) ) ? is0->pINChI_Aux[ii] : NULL;
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # ]
4000 : 0 : mult = 0;
4001 : 0 : bNext = 0;
4002 : :
4003 : : /* For each connected component... */
4004 [ # # ]: 0 : for (i++; i <= num_components; i++)
4005 : : {
4006 [ # # # # : 0 : pINChI_Aux = ( i < num_components && ( is = is0 + i, 0 <= ( ii = GET_II( bOutType, is ) ) ) ) ? is->pINChI_Aux[ii] : NULL;
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # ]
4007 [ # # # # ]: 0 : eq2prev = bUseMulipliers &&
4008 : 0 : Eql_INChI_Aux_Equ( pINChI_Aux, EQL_EQU_TG, pINChI_Aux_Prev, EQL_EQU_TG );
4009 [ # # ]: 0 : if (eq2prev)
4010 : : {
4011 : 0 : mult++; /* mult = (number of non-empty equal items)-1 */
4012 : 0 : continue;
4013 : : }
4014 : : else
4015 : : {
4016 [ # # ]: 0 : if (bNext++)
4017 : : {
4018 : 0 : MakeDelim( sCompDelim, strbuf, bOverflow );
4019 : : }
4020 [ # # # # : 0 : if (pINChI_Aux_Prev && pINChI_Aux_Prev->nNumberOfTGroups &&
# # ]
4021 : 0 : bHasEquString( pINChI_Aux_Prev->nConstitEquTGroupNumbers, pINChI_Aux_Prev->nNumberOfTGroups ))
4022 : : {
4023 : 0 : MakeMult( mult + 1, "*", strbuf, 0, bOverflow );
4024 : 0 : MakeEquString( pINChI_Aux_Prev->nConstitEquTGroupNumbers,
4025 : : pINChI_Aux_Prev->nNumberOfTGroups,
4026 : : 0, strbuf,
4027 : : TAUT_MODE, bOverflow );
4028 : : }
4029 : : }
4030 : 0 : pINChI_Aux_Prev = pINChI_Aux;
4031 : 0 : mult = 0; /* we do not know whether the item is empty */
4032 : : }
4033 : :
4034 : 0 : return ( strbuf->nUsedLength - nUsedLength0 );
4035 : : }
4036 : :
4037 : :
4038 : : /****************************************************************************
4039 : : Produce charge-radical-valence substring of AuxInfo
4040 : : ****************************************************************************/
4041 : 3 : int str_AuxChargeRadVal( INCHI_SORT *pINChISort,
4042 : : INCHI_IOS_STRING *strbuf,
4043 : : int *bOverflow,
4044 : : int bOutType,
4045 : : int TAUT_MODE,
4046 : : int num_components,
4047 : : int bUseMulipliers )
4048 : : {
4049 : : int i, ii, nUsedLength0;
4050 : : INCHI_SORT *is, *is0;
4051 : : INChI_Aux *pINChI_Aux, *pINChI_Aux_Prev;
4052 : : int mult, eq2prev, bNext;
4053 : :
4054 : 3 : pINChI_Aux_Prev = NULL;
4055 : 3 : mult = 0;
4056 : 3 : bNext = 0;
4057 : 3 : is = NULL;
4058 : 3 : is0 = pINChISort;
4059 : 3 : nUsedLength0 = strbuf->nUsedLength;
4060 : :
4061 : : /* For each connected component... */
4062 [ + + ]: 11 : for (i = 0; i <= num_components; i++)
4063 : : {
4064 : :
4065 : : /* 1st (taut) pass: bOutType=OUT_TN ; 2nd (non-taut pass) bOutType=OUT_NT */
4066 [ + + - + : 8 : pINChI_Aux = ( i < num_components && ( is = is0 + i, 0 <= ( ii = GET_II( bOutType, is ) ) ) ) ? is->pINChI_Aux[ii] : NULL;
- - - - -
- - - - -
- - + - +
- + - - +
- - - - -
- - - - -
- - - - -
- - - - -
- - - - -
- - - - -
- - + - ]
4067 : : /* check whether pINChI_Aux and pINChI_Aux_Prev have identical info */
4068 [ + - - + ]: 16 : eq2prev = bUseMulipliers &&
4069 : 8 : EqlOrigInfo( pINChI_Aux, pINChI_Aux_Prev );
4070 [ - + ]: 8 : if (eq2prev)
4071 : : {
4072 : : /* eq. info is same and non-trivial */
4073 : 0 : mult++; /* mult = (number of non-empty equal items)-1 */
4074 : 0 : continue;
4075 : : }
4076 : : else
4077 : : {
4078 [ + + ]: 8 : if (i)
4079 : : {
4080 : : /* pINChI_Aux info is either different or trivial. Output pINChI_Aux_Prev anyway */
4081 [ + + ]: 5 : if (bNext++)
4082 : : {
4083 : 2 : MakeDelim( sCompDelim, strbuf, bOverflow );
4084 : : }
4085 [ + - + - ]: 5 : if (pINChI_Aux_Prev && pINChI_Aux_Prev->nNumberOfAtoms)
4086 : : {
4087 [ + + ]: 5 : if (bHasOrigInfo( pINChI_Aux_Prev->OrigInfo, pINChI_Aux_Prev->nNumberOfAtoms ))
4088 : : {
4089 : : /* pINChI_Aux_Prev exists and has orig. info info */
4090 : 4 : MakeMult( mult + 1, "*", strbuf, 0, bOverflow );
4091 : 4 : MakeCRVString( pINChI_Aux_Prev->OrigInfo,
4092 : : pINChI_Aux_Prev->nNumberOfAtoms,
4093 : : 0, strbuf, TAUT_MODE, bOverflow );
4094 : : }
4095 : : else
4096 : : {
4097 : : ; /* pINChI_Aux_Prev exists and has only trivial info */
4098 : : }
4099 : : }
4100 : : #if ( bRELEASE_VERSION != 1 && defined(_DEBUG) )
4101 : : else
4102 : : {
4103 : : int stop = 1; /* <BRKPT> */
4104 : : }
4105 : : #endif
4106 : : }
4107 : : }
4108 : 8 : pINChI_Aux_Prev = pINChI_Aux;
4109 : 8 : mult = 0; /* we do not know whether the item is empty */
4110 : : }
4111 : :
4112 : 3 : return ( strbuf->nUsedLength - nUsedLength0 );
4113 : : }
4114 : :
4115 : :
4116 : : /****************************************************************************
4117 : : Prepare tautomeric transposition substring of AuxInfo
4118 : : ****************************************************************************/
4119 : 0 : int bin_AuxTautTrans( INCHI_SORT *pINChISort,
4120 : : INCHI_SORT *pINChISort2,
4121 : : AT_NUMB **pTrans_n,
4122 : : AT_NUMB **pTrans_s,
4123 : : int bOutType,
4124 : : int num_components )
4125 : : {
4126 : 0 : int i, ii, ii2, ret = 0;
4127 : : INCHI_SORT *is, *is2, *is0, *is20;
4128 : : INChI *pINChI, *pINChI_Taut;
4129 : 0 : AT_NUMB *nTrans_n = NULL;
4130 : 0 : AT_NUMB *nTrans_s = NULL;
4131 : :
4132 : : /* djb-rwth: removing redundant code */
4133 : 0 : is0 = pINChISort;
4134 : 0 : is20 = pINChISort2;
4135 : :
4136 : : /* djb-rwth: rewritten to avoid memory leaks -- updated 25/09/2025 */
4137 : :
4138 : : /* Pass 1: save new non-taut numbering */
4139 : : /* For each connected component... */
4140 [ # # ]: 0 : for (i = 0; i < num_components; i++)
4141 : : {
4142 : 0 : is = is0 + i;
4143 : 0 : is2 = is20 + i;
4144 [ # # # # : 0 : pINChI = (0 <= (ii = GET_II(bOutType, is))) ? is->pINChI[ii] : NULL;
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # ]
4145 [ # # # # : 0 : pINChI_Taut = (0 <= (ii2 = GET_II(OUT_T1, is2))) ? is2->pINChI[ii2] : NULL;
# # # # #
# ]
4146 [ # # # # : 0 : if (pINChI && pINChI->nNumberOfAtoms > 0 &&
# # ]
4147 [ # # ]: 0 : pINChI_Taut && pINChI_Taut->nNumberOfAtoms > 0 &&
4148 : : /* different components save equal new ord. numbers: */
4149 [ # # ]: 0 : is->ord_number != is2->ord_number)
4150 : : {
4151 [ # # ]: 0 : if (!nTrans_n)
4152 : : {
4153 : 0 : nTrans_n = (AT_NUMB*)inchi_calloc((long long)num_components + 1, sizeof(nTrans_n[0]));
4154 : : }
4155 [ # # ]: 0 : if (!nTrans_s)
4156 : : {
4157 : 0 : nTrans_s = (AT_NUMB*)inchi_calloc((long long)num_components + 1, sizeof(nTrans_s[0]));
4158 : : }
4159 [ # # # # ]: 0 : if (nTrans_n && nTrans_s)
4160 : : {
4161 : : /* new ordering number for original non-tautomeric component number is->ord_number */
4162 : 0 : nTrans_n[is->ord_number] = i + 1; /*nTrans_t[is2->ord_number] =*/
4163 : : }
4164 : : }
4165 : : }
4166 [ # # # # ]: 0 : if (nTrans_n && nTrans_s)
4167 : : {
4168 : : /* Pass 2: get new taut numbering, retrieve new non-taut and save the transposition */
4169 [ # # ]: 0 : for (i = 0; i < num_components; i++)
4170 : : {
4171 : 0 : is = is0 + i;
4172 : 0 : is2 = is20 + i;
4173 [ # # # # : 0 : pINChI = (0 <= (ii = GET_II(bOutType, is))) ? is->pINChI[ii] : NULL;
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # ]
4174 [ # # # # : 0 : pINChI_Taut = (0 <= (ii2 = GET_II(OUT_T1, is2))) ? is2->pINChI[ii2] : NULL;
# # # # #
# ]
4175 [ # # # # : 0 : if (pINChI && pINChI->nNumberOfAtoms > 0 &&
# # ]
4176 [ # # ]: 0 : pINChI_Taut && pINChI_Taut->nNumberOfAtoms > 0 &&
4177 [ # # ]: 0 : is->ord_number != is2->ord_number &&
4178 [ # # ]: 0 : nTrans_n[is2->ord_number])
4179 : : {
4180 : : /* nTrans_n[is2->ord_number] is new ordering number of
4181 : : the non-taut representation of the tautomeric component
4182 : : that has new ord number i+1 and orig ordering number is2->ord_number.
4183 : : Old numbers start from 0, new start from 1
4184 : : */
4185 : :
4186 : : /* n = nTrans_s[t]: taut component #t is in position #n of the non-taut representation */
4187 : 0 : nTrans_s[i + 1] = nTrans_n[is2->ord_number];
4188 : : }
4189 : : }
4190 : 0 : *pTrans_n = nTrans_n;
4191 : 0 : *pTrans_s = nTrans_s;
4192 : 0 : ret = 1;
4193 : : }
4194 : : else
4195 : : {
4196 [ # # ]: 0 : if (nTrans_n)
4197 : : {
4198 [ # # ]: 0 : inchi_free(nTrans_n);
4199 : 0 : ret = -1;
4200 : : }
4201 [ # # ]: 0 : if (nTrans_s)
4202 : : {
4203 [ # # ]: 0 : inchi_free(nTrans_s);
4204 : 0 : ret = -1;
4205 : : }
4206 : : }
4207 : :
4208 : 0 : return ret;
4209 : : }
4210 : :
4211 : :
4212 : : /****************************************************************************
4213 : : Output tautomeric transposition substring of AuxInfo
4214 : : ****************************************************************************/
4215 : 0 : int str_AuxTautTrans( CANON_GLOBALS *pCG,
4216 : : AT_NUMB *nTrans_n,
4217 : : AT_NUMB *nTrans_s,
4218 : : INCHI_IOS_STRING *strbuf,
4219 : : int *bOverflow,
4220 : : int TAUT_MODE,
4221 : : int num_components )
4222 : : {
4223 : : int i, k, len, j, nUsedLength0;
4224 : :
4225 : 0 : nUsedLength0 = strbuf->nUsedLength;
4226 : :
4227 [ # # # # ]: 0 : if (nTrans_n && nTrans_s)
4228 : : {
4229 : : /* print the transposition, cycle after cycle */
4230 [ # # ]: 0 : for (i = 1; i <= num_components; i++)
4231 : : {
4232 [ # # ]: 0 : if (nTrans_s[i])
4233 : : {
4234 : : /* get one cycle of the transposition */
4235 [ # # ]: 0 : for (j = i, len = 0; ( k = nTrans_s[j] ); j = k, len++)
4236 : : {
4237 : 0 : nTrans_n[len] = j; /* save the transposition */
4238 : 0 : nTrans_s[j] = 0; /* clear used element to avoid repetitions */
4239 : : }
4240 : : /* print one cycle of the transposition */
4241 : 0 : MakeDelim( "(", strbuf, bOverflow );
4242 : 0 : MakeCtString( pCG, nTrans_n, len, 0, NULL, 0,
4243 : : strbuf, TAUT_MODE, bOverflow );
4244 : 0 : MakeDelim( ")", strbuf, bOverflow );
4245 : : }
4246 : : }
4247 : : }
4248 [ # # ]: 0 : if (nTrans_n)
4249 : : {
4250 [ # # ]: 0 : inchi_free( nTrans_n );
4251 : : }
4252 [ # # ]: 0 : if (nTrans_s)
4253 : : {
4254 [ # # ]: 0 : inchi_free( nTrans_s );
4255 : : }
4256 : :
4257 : 0 : return ( strbuf->nUsedLength - nUsedLength0 );
4258 : : }
4259 : :
4260 : :
4261 : : /****************************************************************************
4262 : : Output isotopic TGroup equivalence substring of AuxInfo
4263 : : ****************************************************************************/
4264 : 0 : int str_AuxIsoTgroupEqu( INCHI_SORT *pINChISort,
4265 : : INCHI_IOS_STRING *strbuf,
4266 : : int *bOverflow,
4267 : : int bOutType,
4268 : : int TAUT_MODE,
4269 : : int num_components,
4270 : : int bOmitRepetitions,
4271 : : int bUseMulipliers )
4272 : : {
4273 : : int i, ii, nUsedLength0;
4274 : : INCHI_SORT *is, *is0;
4275 : : INChI_Aux *pINChI_Aux, *pINChI_Aux_Prev;
4276 : : int mult, eq2prev, eq2taut, eq2tautPrev, bNext;
4277 : : const char *pPrevEquStr, *pCurrEquStr;
4278 : : int multPrevEquStr;
4279 : 0 : pINChI_Aux = NULL;
4280 : 0 : pINChI_Aux_Prev = NULL;
4281 : 0 : mult = 0;
4282 : 0 : bNext = 0;
4283 : 0 : is = NULL;
4284 : 0 : is0 = pINChISort;
4285 : : /* djb-rwth: removing redundant code */
4286 : 0 : eq2tautPrev = 1; /* pINChI_Aux_Prev (previous pINChI_Aux) does not exist */
4287 : 0 : pPrevEquStr = NULL; /*, *pCurrEquStr;*/
4288 : 0 : multPrevEquStr = 0;
4289 : 0 : nUsedLength0 = strbuf->nUsedLength;
4290 : :
4291 : : /* For each connected component... */
4292 [ # # ]: 0 : for (i = 0; i <= num_components; i++)
4293 : : {
4294 : : /* 1st (taut) pass: bOutType=OUT_TN ; 2nd (non-taut pass) bOutType=OUT_NT */
4295 [ # # # # : 0 : pINChI_Aux = ( i < num_components && ( is = is0 + i, 0 <= ( ii = GET_II( bOutType, is ) ) ) ) ? is->pINChI_Aux[ii] : NULL;
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # ]
4296 : : /*================ compare iso non-taut equivalence info to non-iso taut ========*/
4297 : 0 : eq2taut = 0;
4298 [ # # # # : 0 : if (bOmitRepetitions && pINChI_Aux && pINChI_Aux->bIsIsotopic)
# # ]
4299 : : {
4300 : : /**************************************************
4301 : : * compare isotopic tautomeric equivalence to:
4302 : : * a) non-isotopic tautomeric
4303 : : */
4304 : : /* compare isotopic t-group equivalence to non-isotopic */
4305 : 0 : eq2taut = Eql_INChI_Aux_Equ( pINChI_Aux, EQL_EQU_TG | EQL_EQU_ISO, pINChI_Aux, EQL_EQU_TG );
4306 : : /* equ taut-isotopic = tautomeric, same as for isotopic atom equivalence info*/
4307 [ # # ]: 0 : eq2taut = eq2taut ? ( iiEQU | iitISO ) : 0;
4308 : : }
4309 [ # # ]: 0 : if (eq2taut)
4310 : : {
4311 : : /* current isotopic t-group equivalence has been found to be same as non-isotopic */
4312 [ # # # # ]: 0 : if (pINChI_Aux_Prev && pINChI_Aux_Prev->nNumberOfAtoms)
4313 : : {
4314 : : /* previous component exists */
4315 [ # # ]: 0 : if (bNext++)
4316 : : {
4317 : 0 : MakeDelim( sCompDelim, strbuf, bOverflow );
4318 : : }
4319 [ # # ]: 0 : if (bHasEquString( pINChI_Aux_Prev->nConstitEquIsotopicTGroupNumbers, pINChI_Aux_Prev->nNumberOfTGroups ))
4320 : : {
4321 : : /* output previous component(s) equivalence since it was found to be non-trivial */
4322 : 0 : MakeMult( mult + 1, "*", strbuf, 0, bOverflow );
4323 : 0 : MakeEquString( pINChI_Aux_Prev->nConstitEquIsotopicTGroupNumbers, pINChI_Aux_Prev->nNumberOfTGroups, 0,
4324 : : strbuf, TAUT_MODE, bOverflow );
4325 : : }
4326 : : else
4327 : : {
4328 : : ; /* pINChI_Aux_Prev exists and does not have non-trivial t-group equivalence info */
4329 : : }
4330 : : }
4331 : : /* we have found pINChI_Aux->pINChI_Aux->nConstitEquIsotopicTGroupNumbers same as in pINChI_Aux->nConstitEquTGroupNumbers */
4332 : 0 : pCurrEquStr = EquString( eq2taut );
4333 [ # # # # ]: 0 : if (multPrevEquStr && pPrevEquStr)
4334 : : {
4335 [ # # # # ]: 0 : if (pCurrEquStr && !strcmp( pCurrEquStr, pPrevEquStr ))
4336 : : {
4337 : 0 : multPrevEquStr++;
4338 : : }
4339 : : else
4340 : : {
4341 : : /* new EqStr is different; output it */
4342 [ # # ]: 0 : if (bNext++)
4343 : : {
4344 : 0 : MakeDelim( sCompDelim, strbuf, bOverflow );
4345 : : }
4346 : 0 : MakeEqStr( pPrevEquStr, multPrevEquStr, strbuf, bOverflow );
4347 : 0 : pPrevEquStr = pCurrEquStr;
4348 : 0 : multPrevEquStr = 1;
4349 : : }
4350 : : }
4351 : : else
4352 : : {
4353 : 0 : pPrevEquStr = pCurrEquStr;
4354 : 0 : multPrevEquStr = 1;
4355 : : }
4356 : 0 : pINChI_Aux_Prev = NULL; /* pINChI_Aux_Prev has already been output */
4357 : 0 : mult = 0;
4358 : 0 : eq2tautPrev = 1;
4359 : : }
4360 : : else
4361 : : {
4362 [ # # ]: 0 : if (eq2tautPrev)
4363 : : {
4364 : : /* at this point pINChI_Aux_Prev does not exist; however, pINChI_Aux */
4365 : : /* might have been discovered and it may be different from non-isotopic */
4366 [ # # # # ]: 0 : if (multPrevEquStr && pPrevEquStr)
4367 : : {
4368 : : /* new EqStr is different; output it */
4369 [ # # ]: 0 : if (bNext++)
4370 : : {
4371 : 0 : MakeDelim( sCompDelim, strbuf, bOverflow );
4372 : : }
4373 : 0 : MakeEqStr( pPrevEquStr, multPrevEquStr, strbuf, bOverflow );
4374 : 0 : pPrevEquStr = NULL;
4375 : 0 : multPrevEquStr = 0;
4376 : : }
4377 : 0 : eq2tautPrev = 0;
4378 : 0 : pINChI_Aux_Prev = pINChI_Aux;
4379 : 0 : mult = 0;
4380 : : }
4381 : : else
4382 : : {
4383 : : /* check whether pINChI_Aux and pINChI_Aux_Prev have identical non-trivial isotopic t-group equivalence info */
4384 [ # # # # ]: 0 : eq2prev = bUseMulipliers && Eql_INChI_Aux_Equ( pINChI_Aux, EQL_EQU_TG | EQL_EQU_ISO, pINChI_Aux_Prev, EQL_EQU_TG | EQL_EQU_ISO );
4385 [ # # ]: 0 : if (eq2prev)
4386 : : {
4387 : : /* eq. info is same and non-trivial */
4388 : 0 : mult++; /* mult = (number of non-empty equal items)-1 */
4389 : 0 : continue;
4390 : : }
4391 : : else
4392 : : {
4393 : : /* pINChI_Aux eq. info is either different or trivial. Output pINChI_Aux_Prev anyway */
4394 [ # # ]: 0 : if (bNext++)
4395 : : {
4396 : 0 : MakeDelim( sCompDelim, strbuf, bOverflow );
4397 : : }
4398 [ # # # # ]: 0 : if (pINChI_Aux_Prev && pINChI_Aux_Prev->nNumberOfAtoms)
4399 : : {
4400 [ # # ]: 0 : if (bHasEquString( pINChI_Aux_Prev->nConstitEquIsotopicTGroupNumbers, pINChI_Aux_Prev->nNumberOfTGroups ))
4401 : : {
4402 : : /* pINChI_Aux_Prev exists and has equivalence info */
4403 : 0 : MakeMult( mult + 1, "*", strbuf, 0, bOverflow );
4404 : 0 : MakeEquString( pINChI_Aux_Prev->nConstitEquIsotopicTGroupNumbers, pINChI_Aux_Prev->nNumberOfTGroups, 0,
4405 : : strbuf, TAUT_MODE, bOverflow );
4406 : : }
4407 : : else
4408 : : {
4409 : : ; /* pINChI_Aux_Prev exists and has only trivial equivalence info */
4410 : : }
4411 : : }
4412 : : #if ( bRELEASE_VERSION != 1 && defined(_DEBUG) )
4413 : : else
4414 : : {
4415 : : int stop = 1; /* <BRKPT> */
4416 : : }
4417 : : #endif
4418 : : }
4419 : 0 : pINChI_Aux_Prev = pINChI_Aux;
4420 : 0 : mult = 0; /* we do not know whether the item is empty */
4421 : : }
4422 : : }
4423 : : }
4424 : :
4425 : 0 : return ( strbuf->nUsedLength - nUsedLength0 );
4426 : : }
|