rino 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (87) hide show
  1. data/README +44 -0
  2. data/Rakefile +123 -0
  3. data/ext/extconf.rb +26 -0
  4. data/ext/ruby_inchi_main.so +0 -0
  5. data/ext/src/aux2atom.h +2786 -0
  6. data/ext/src/comdef.h +148 -0
  7. data/ext/src/e_0dstereo.c +3014 -0
  8. data/ext/src/e_0dstereo.h +31 -0
  9. data/ext/src/e_comdef.h +57 -0
  10. data/ext/src/e_ctl_data.h +147 -0
  11. data/ext/src/e_ichi_io.c +498 -0
  12. data/ext/src/e_ichi_io.h +40 -0
  13. data/ext/src/e_ichi_parms.c +37 -0
  14. data/ext/src/e_ichi_parms.h +41 -0
  15. data/ext/src/e_ichicomp.h +50 -0
  16. data/ext/src/e_ichierr.h +40 -0
  17. data/ext/src/e_ichimain.c +593 -0
  18. data/ext/src/e_ichisize.h +43 -0
  19. data/ext/src/e_inchi_atom.c +75 -0
  20. data/ext/src/e_inchi_atom.h +33 -0
  21. data/ext/src/e_inpdef.h +41 -0
  22. data/ext/src/e_mode.h +706 -0
  23. data/ext/src/e_mol2atom.c +649 -0
  24. data/ext/src/e_readinch.c +58 -0
  25. data/ext/src/e_readmol.c +54 -0
  26. data/ext/src/e_readmol.h +180 -0
  27. data/ext/src/e_readstru.c +251 -0
  28. data/ext/src/e_readstru.h +33 -0
  29. data/ext/src/e_util.c +284 -0
  30. data/ext/src/e_util.h +61 -0
  31. data/ext/src/extr_ct.h +251 -0
  32. data/ext/src/ichi.h +206 -0
  33. data/ext/src/ichi_bns.c +7999 -0
  34. data/ext/src/ichi_bns.h +231 -0
  35. data/ext/src/ichican2.c +5000 -0
  36. data/ext/src/ichicano.c +2195 -0
  37. data/ext/src/ichicano.h +49 -0
  38. data/ext/src/ichicans.c +1625 -0
  39. data/ext/src/ichicant.h +379 -0
  40. data/ext/src/ichicomn.h +260 -0
  41. data/ext/src/ichicomp.h +50 -0
  42. data/ext/src/ichidrp.h +119 -0
  43. data/ext/src/ichierr.h +124 -0
  44. data/ext/src/ichiisot.c +101 -0
  45. data/ext/src/ichilnct.c +286 -0
  46. data/ext/src/ichimain.h +132 -0
  47. data/ext/src/ichimak2.c +1189 -0
  48. data/ext/src/ichimake.c +3812 -0
  49. data/ext/src/ichimake.h +205 -0
  50. data/ext/src/ichimap1.c +851 -0
  51. data/ext/src/ichimap2.c +2856 -0
  52. data/ext/src/ichimap4.c +1609 -0
  53. data/ext/src/ichinorm.c +741 -0
  54. data/ext/src/ichinorm.h +67 -0
  55. data/ext/src/ichiparm.c +45 -0
  56. data/ext/src/ichiparm.h +1441 -0
  57. data/ext/src/ichiprt1.c +3612 -0
  58. data/ext/src/ichiprt2.c +1511 -0
  59. data/ext/src/ichiprt3.c +3011 -0
  60. data/ext/src/ichiqueu.c +1003 -0
  61. data/ext/src/ichiring.c +326 -0
  62. data/ext/src/ichiring.h +49 -0
  63. data/ext/src/ichisize.h +35 -0
  64. data/ext/src/ichisort.c +539 -0
  65. data/ext/src/ichister.c +3538 -0
  66. data/ext/src/ichister.h +35 -0
  67. data/ext/src/ichitaut.c +3843 -0
  68. data/ext/src/ichitaut.h +387 -0
  69. data/ext/src/ichitime.h +74 -0
  70. data/ext/src/inchi_api.h +670 -0
  71. data/ext/src/inchi_dll.c +1480 -0
  72. data/ext/src/inchi_dll.h +34 -0
  73. data/ext/src/inchi_dll_main.c +23 -0
  74. data/ext/src/inchi_dll_main.h +31 -0
  75. data/ext/src/inpdef.h +328 -0
  76. data/ext/src/lreadmol.h +1246 -0
  77. data/ext/src/mode.h +706 -0
  78. data/ext/src/ruby_inchi_main.c +558 -0
  79. data/ext/src/runichi.c +4179 -0
  80. data/ext/src/strutil.c +3861 -0
  81. data/ext/src/strutil.h +182 -0
  82. data/ext/src/util.c +1130 -0
  83. data/ext/src/util.h +85 -0
  84. data/lib/clean_tempfile.rb +220 -0
  85. data/lib/rino.rb +111 -0
  86. data/test/test.rb +386 -0
  87. metadata +130 -0
@@ -0,0 +1,3011 @@
1
+ /*
2
+ * International Union of Pure and Applied Chemistry (IUPAC)
3
+ * International Chemical Identifier (InChI)
4
+ * Version 1
5
+ * Software version 1.00
6
+ * April 13, 2005
7
+ * Developed at NIST
8
+ */
9
+
10
+ #include <stdio.h>
11
+ #include <stdlib.h>
12
+ #include <string.h>
13
+ #include <ctype.h>
14
+
15
+ #include "mode.h"
16
+
17
+ #include "inpdef.h"
18
+ #include "ichi.h"
19
+ #include "strutil.h"
20
+ #include "util.h"
21
+ #include "extr_ct.h"
22
+ #include "ichitaut.h"
23
+ #include "ichinorm.h"
24
+ #include "ichicant.h"
25
+ #include "ichicano.h"
26
+ #include "ichicomn.h"
27
+
28
+ #include "ichicomp.h"
29
+ #include "ichimain.h"
30
+ #include "ichimake.h"
31
+
32
+
33
+ /***************************************************************************/
34
+ int str_Sp2(INCHI_SORT *pINChISort, INCHI_SORT *pINChISort2, char *pStr, int nStrLen, int tot_len,
35
+ int *bOverflow, int bOutType, int TAUT_MODE, int num_components,
36
+ int bSecondNonTautPass, int bOmitRepetitions, int bUseMulipliers)
37
+ {
38
+ int i, ii, ii2;
39
+ INCHI_SORT *is, *is2;
40
+ INChI *pINChI, *pINChI_Prev, *pINChI_Taut, *pINChI_Taut_Prev;
41
+ INChI_Stereo *Stereo, *Stereo_Prev, *Stereo_Taut, *Stereo_Taut_Prev;
42
+ int mult, eq2prev, eq2taut, eq2tautPrev, bNext;
43
+ const char *pPrevEquStr, *pCurrEquStr;
44
+ int multPrevEquStr;
45
+
46
+ pINChI_Taut = NULL;
47
+ pINChI_Prev = NULL;
48
+ pINChI_Taut_Prev = NULL;
49
+ mult = 0;
50
+ bNext = 0;
51
+ is2 = bSecondNonTautPass? pINChISort2 : NULL;
52
+ eq2taut = 0; /* may be non-zero only on the 2nd (non-taut) pass */
53
+ eq2tautPrev = 1; /* pINChI_Prev (previous pINChI) does not exist */
54
+ pPrevEquStr = NULL; /*, *pCurrEquStr;*/
55
+ multPrevEquStr = 0;
56
+ for ( i = 0, is = pINChISort; i <= num_components; i ++, is ++, (bSecondNonTautPass? is2++ : 0) ) {
57
+ /* 1st (taut) pass: bOutType=OUT_TN ; 2nd (non-taut pass) bOutType=OUT_NT */
58
+ pINChI = (i < num_components && 0 <= (ii=GET_II(bOutType,is)))? is->pINChI[ii] : NULL;
59
+ /*================ compare sp2 to previous =====================*/
60
+ if ( bSecondNonTautPass ) {
61
+ /* component that was output on the 1st pass */
62
+ pINChI_Taut = ( i < num_components && 0 <= (ii2=GET_II(OUT_T1,is2)))? is2->pINChI[ii2] : NULL;
63
+ }
64
+ /*========= if bSecondNonTautPass then compare non-iso non-taut stereo to non-iso taut ========*/
65
+ eq2taut = 0;
66
+ if ( !eq2taut && bSecondNonTautPass && bOmitRepetitions ) {
67
+ eq2taut = pINChI && pINChI_Taut &&
68
+ (Stereo = pINChI->Stereo) && (Stereo_Taut = pINChI_Taut->Stereo) &&
69
+ Eql_INChI_Stereo( Stereo, EQL_SP2, Stereo_Taut, EQL_SP2, 0 );
70
+ eq2taut = eq2taut? (iiSTEREO | iitNONTAUT) : 0;
71
+ }
72
+ if ( eq2taut ) {
73
+ /* we may be here only in case of the second (non-taut) pass */
74
+ /* current non-taut stereo has been found to be same as tautomeric */
75
+ if ( pINChI_Prev && pINChI_Prev->nNumberOfAtoms ) {
76
+ /* previous component exists; output it */
77
+ if ( bNext ++ ) {
78
+ tot_len += MakeDelim( sCompDelim, pStr + tot_len, nStrLen-tot_len, bOverflow);
79
+ }
80
+ if ( (Stereo_Prev = pINChI_Prev->Stereo) && Stereo_Prev->nNumberOfStereoBonds > 0 ) {
81
+ tot_len += MakeMult( mult+1, "*", pStr + tot_len, nStrLen-tot_len, 0, bOverflow);
82
+
83
+ tot_len += MakeStereoString( Stereo_Prev->nBondAtom1, Stereo_Prev->nBondAtom2,
84
+ Stereo_Prev->b_parity,
85
+ 0, Stereo_Prev->nNumberOfStereoBonds,
86
+ pStr + tot_len, nStrLen-tot_len, TAUT_MODE, bOverflow);
87
+ }
88
+ } else
89
+ if ( pINChI_Taut_Prev && pINChI_Taut_Prev->nNumberOfAtoms ) {
90
+ /* previous non-taut component exists only in taut list */
91
+ if ( bNext ++ ) {
92
+ tot_len += MakeDelim( sCompDelim, pStr + tot_len, nStrLen-tot_len, bOverflow);
93
+ }
94
+ }
95
+ /* we have found pINChI->Stereo sp2 same as in pINChI_Taut */
96
+ /* output this (current) equivalence as '*', that is, same as tautomeric */
97
+ /* that was printed on the 1st pass. */
98
+ pCurrEquStr = EquString(eq2taut);
99
+ if ( multPrevEquStr && pPrevEquStr ) {
100
+ if ( pCurrEquStr && !strcmp(pCurrEquStr, pPrevEquStr) ) {
101
+ multPrevEquStr ++;
102
+ } else {
103
+ /* new EqStr is different; output it */
104
+ if ( bNext ++ ) {
105
+ tot_len += MakeDelim( sCompDelim, pStr + tot_len, nStrLen-tot_len, bOverflow);
106
+ }
107
+ tot_len += MakeEqStr( pPrevEquStr, multPrevEquStr, pStr + tot_len, nStrLen-tot_len, bOverflow);
108
+ pPrevEquStr = pCurrEquStr;
109
+ multPrevEquStr = 1;
110
+ }
111
+ } else {
112
+ pPrevEquStr = pCurrEquStr;
113
+ multPrevEquStr = 1;
114
+ }
115
+ pINChI_Prev = NULL; /* pINChI_Prev sp2 does not exist since */
116
+ pINChI_Taut_Prev = NULL; /* pINChI has just been printed */
117
+ mult = 0;
118
+ eq2tautPrev = 1; /* pINChI_Prev sp2 does not exist */
119
+ } else
120
+ if ( eq2tautPrev ) {
121
+ /* at this point pINChI_Prev does not exist; however, pINChI */
122
+ /*might have been discovered and it is different from pINChI_Taut */
123
+ if ( multPrevEquStr && pPrevEquStr ) {
124
+ /* new EqStr is different; output it */
125
+ if ( bNext ++ ) {
126
+ tot_len += MakeDelim( sCompDelim, pStr + tot_len, nStrLen-tot_len, bOverflow);
127
+ }
128
+ tot_len += MakeEqStr( pPrevEquStr, multPrevEquStr, pStr + tot_len, nStrLen-tot_len, bOverflow);
129
+ pPrevEquStr = NULL;
130
+ multPrevEquStr = 0;
131
+ }
132
+ eq2tautPrev = 0;
133
+ pINChI_Prev = pINChI;
134
+ pINChI_Taut_Prev = pINChI_Taut;
135
+ mult = 0;
136
+ } else {
137
+ /* check whether pINChI and pINChI_Prev have non-zero identical stereo sp2 */
138
+ eq2prev =bUseMulipliers &&
139
+ pINChI && pINChI_Prev &&
140
+ (Stereo = pINChI->Stereo) && (Stereo_Prev = pINChI_Prev->Stereo) &&
141
+ Eql_INChI_Stereo( Stereo, EQL_SP2, Stereo_Prev, EQL_SP2, 0 );
142
+ if ( eq2prev ) {
143
+ mult ++; /* mult = (number of non-empty equal items)-1 */
144
+ continue;
145
+ } else {
146
+ /* pINChI sp2 info is either different or trivial. Output pINChI_Prev anyway */
147
+ if ( bNext ++ ) {
148
+ tot_len += MakeDelim( sCompDelim, pStr + tot_len, nStrLen-tot_len, bOverflow);
149
+ }
150
+ if ( pINChI_Prev && pINChI_Prev->nNumberOfAtoms ) {
151
+ if ( (Stereo_Prev = pINChI_Prev->Stereo) && Stereo_Prev->nNumberOfStereoBonds > 0 ) {
152
+ /* pINChI_Prev exists and has sp2 info */
153
+ tot_len += MakeMult( mult+1, "*", pStr + tot_len, nStrLen-tot_len, 0, bOverflow);
154
+
155
+ tot_len += MakeStereoString( Stereo_Prev->nBondAtom1, Stereo_Prev->nBondAtom2,
156
+ Stereo_Prev->b_parity,
157
+ 0, Stereo_Prev->nNumberOfStereoBonds,
158
+ pStr + tot_len, nStrLen-tot_len, TAUT_MODE, bOverflow);
159
+ }
160
+ /* else sp2 info is not present in pINChI_Prev */
161
+ } else
162
+ if ( bSecondNonTautPass && pINChI_Taut_Prev && pINChI_Taut_Prev->nNumberOfAtoms ) {
163
+ if ( (Stereo_Taut_Prev = pINChI_Taut_Prev->Stereo) && Stereo_Taut_Prev->nNumberOfStereoBonds > 0 ) {
164
+ /* since pINChI_Prev does not exist, pINChI_Taut_Prev is non-tautomeric */
165
+ /* and it has non-trivial sp2 info */
166
+ /*
167
+ tot_len += MakeDelim( sIdenticalValues, pStr + tot_len, nStrLen-tot_len, bOverflow);
168
+ */
169
+ ;/* pINChI_Taut_Prev sp2 info was output in the main stereo section */
170
+ } else {
171
+ ; /* pINChI_Taut_Prev exists and has not sp2 info */
172
+ }
173
+ }
174
+ #if( bRELEASE_VERSION != 1 && defined(_DEBUG) )
175
+ else {
176
+ int stop = 1; /* <BRKPT> */
177
+ }
178
+ #endif
179
+ }
180
+ pINChI_Prev = pINChI;
181
+ pINChI_Taut_Prev = pINChI_Taut;
182
+ mult = 0; /* we do not know whether the item is empty */
183
+ }
184
+ }
185
+ return tot_len;
186
+ }
187
+
188
+ /***************************************************************************/
189
+ int str_Sp3(INCHI_SORT *pINChISort, INCHI_SORT *pINChISort2, char *pStr, int nStrLen, int tot_len,
190
+ int *bOverflow, int bOutType, int TAUT_MODE, int num_components, int bRelRac,
191
+ int bSecondNonTautPass, int bOmitRepetitions, int bUseMulipliers)
192
+ {
193
+ int i, ii, ii2;
194
+ INCHI_SORT *is, *is2;
195
+ INChI *pINChI, *pINChI_Prev, *pINChI_Taut, *pINChI_Taut_Prev;
196
+ INChI_Stereo *Stereo, *Stereo_Prev, *Stereo_Taut, *Stereo_Taut_Prev;
197
+ int mult, eq2prev, eq2taut, eq2tautPrev, bNext;
198
+ const char *pPrevEquStr, *pCurrEquStr;
199
+ int multPrevEquStr;
200
+ pINChI_Taut = NULL;
201
+ pINChI_Prev = NULL;
202
+ pINChI_Taut_Prev = NULL;
203
+ mult = 0;
204
+ bNext = 0;
205
+ is2 = bSecondNonTautPass? pINChISort2 : NULL;
206
+ eq2taut = 0; /* may be non-zero only on the 2nd (non-taut) pass */
207
+ eq2tautPrev = 1; /* pINChI_Prev (previous pINChI) does not exist */
208
+ pPrevEquStr = NULL; /*, *pCurrEquStr;*/
209
+ multPrevEquStr = 0;
210
+ #if( REL_RAC_STEREO_IGN_1_SC == 1 )
211
+ #else
212
+ bRelRac = 0;
213
+ #endif
214
+ for ( i = 0, is = pINChISort; i <= num_components; i ++, is ++, (bSecondNonTautPass? is2++ : 0) ) {
215
+ /* 1st (taut) pass: bOutType=OUT_TN ; 2nd (non-taut pass) bOutType=OUT_NT */
216
+ pINChI = (i < num_components && 0 <= (ii=GET_II(bOutType,is)))? is->pINChI[ii] : NULL;
217
+ /*================ compare sp3 to previous =====================*/
218
+ if ( bSecondNonTautPass ) {
219
+ /* component that was output on the 1st pass */
220
+ pINChI_Taut = ( i < num_components && 0 <= (ii2=GET_II(OUT_T1,is2)))? is2->pINChI[ii2] : NULL;
221
+ }
222
+ /*========= if bSecondNonTautPass then compare non-iso non-taut stereo to non-iso taut ========*/
223
+ eq2taut = 0;
224
+ if ( !eq2taut && bSecondNonTautPass && bOmitRepetitions ) {
225
+ eq2taut = pINChI && pINChI_Taut &&
226
+ (Stereo = pINChI->Stereo) && (Stereo_Taut = pINChI_Taut->Stereo) &&
227
+ Eql_INChI_Stereo( Stereo, EQL_SP3, Stereo_Taut, EQL_SP3, bRelRac );
228
+ eq2taut = eq2taut? (iiSTEREO | iitNONTAUT) : 0;
229
+ }
230
+ if ( eq2taut ) {
231
+ /* we may be here only in case of the second (non-taut) pass */
232
+ /* current non-taut stereo has been found to be same as tautomeric */
233
+ if ( pINChI_Prev && pINChI_Prev->nNumberOfAtoms ) {
234
+ /* previous component exists; output it */
235
+ if ( bNext ++ ) {
236
+ tot_len += MakeDelim( sCompDelim, pStr + tot_len, nStrLen-tot_len, bOverflow);
237
+ }
238
+ if ( (Stereo_Prev = pINChI_Prev->Stereo) && Stereo_Prev->nNumberOfStereoCenters > 0 ) {
239
+ /* non-empty item */
240
+ tot_len += MakeMult( mult+1, "*", pStr + tot_len, nStrLen-tot_len, 0, bOverflow);
241
+
242
+ tot_len += MakeStereoString( Stereo_Prev->nNumber, NULL,
243
+ Stereo_Prev->t_parity,
244
+ 0, Stereo_Prev->nNumberOfStereoCenters,
245
+ pStr + tot_len, nStrLen-tot_len, TAUT_MODE, bOverflow);
246
+ }
247
+ } else
248
+ if ( pINChI_Taut_Prev && pINChI_Taut_Prev->nNumberOfAtoms ) {
249
+ /* previous non-taut component exists only in taut list */
250
+ if ( bNext ++ ) {
251
+ tot_len += MakeDelim( sCompDelim, pStr + tot_len, nStrLen-tot_len, bOverflow);
252
+ }
253
+ }
254
+ /* we have found pINChI->Stereo sp3 same as in pINChI_Taut */
255
+ /* output this (current) equivalence as '*', that is, same as tautomeric */
256
+ /* that was printed on the 1st pass. */
257
+
258
+ pCurrEquStr = EquString(eq2taut);
259
+ if ( multPrevEquStr && pPrevEquStr ) {
260
+ if ( pCurrEquStr && !strcmp(pCurrEquStr, pPrevEquStr) ) {
261
+ multPrevEquStr ++;
262
+ } else {
263
+ /* new EqStr is different; output it */
264
+ if ( bNext ++ ) {
265
+ tot_len += MakeDelim( sCompDelim, pStr + tot_len, nStrLen-tot_len, bOverflow);
266
+ }
267
+ tot_len += MakeEqStr( pPrevEquStr, multPrevEquStr, pStr + tot_len, nStrLen-tot_len, bOverflow);
268
+ pPrevEquStr = pCurrEquStr;
269
+ multPrevEquStr = 1;
270
+ }
271
+ } else {
272
+ pPrevEquStr = pCurrEquStr;
273
+ multPrevEquStr = 1;
274
+ }
275
+
276
+ pINChI_Prev = NULL; /* pINChI_Prev sp2 does not exist since */
277
+ pINChI_Taut_Prev = NULL; /* pINChI has just been printed */
278
+ mult = 0;
279
+ eq2tautPrev = 1; /* pINChI_Prev sp2 does not exist */
280
+ } else
281
+ if ( eq2tautPrev ) {
282
+ /* at this point pINChI_Prev does not exist; however, pINChI */
283
+ /*might have been discovered and it is different from pINChI_Taut */
284
+ if ( multPrevEquStr && pPrevEquStr ) {
285
+ /* new EqStr is different; output it */
286
+ if ( bNext ++ ) {
287
+ tot_len += MakeDelim( sCompDelim, pStr + tot_len, nStrLen-tot_len, bOverflow);
288
+ }
289
+ tot_len += MakeEqStr( pPrevEquStr, multPrevEquStr, pStr + tot_len, nStrLen-tot_len, bOverflow);
290
+ pPrevEquStr = NULL;
291
+ multPrevEquStr = 0;
292
+ }
293
+ eq2tautPrev = 0;
294
+ pINChI_Prev = pINChI;
295
+ pINChI_Taut_Prev = pINChI_Taut;
296
+ mult = 0;
297
+ } else {
298
+ /* check whether pINChI and pINChI_Prev have non-zero identical stereo sp3 */
299
+ /*================ compare sp3 to previous =====================*/
300
+ eq2prev =bUseMulipliers &&
301
+ pINChI && pINChI_Prev &&
302
+ (Stereo = pINChI->Stereo) && (Stereo_Prev = pINChI_Prev->Stereo) &&
303
+ Eql_INChI_Stereo( Stereo, EQL_SP3, Stereo_Prev, EQL_SP3, bRelRac );
304
+ if ( eq2prev ) {
305
+ mult ++; /* mult = (number of non-empty equal items)-1 */
306
+ continue;
307
+ } else {
308
+ if ( bNext ++ ) {
309
+ tot_len += MakeDelim( sCompDelim, pStr + tot_len, nStrLen-tot_len, bOverflow);
310
+ }
311
+ if ( pINChI_Prev && pINChI_Prev->nNumberOfAtoms ) {
312
+ if ( (Stereo_Prev = pINChI_Prev->Stereo) && Stereo_Prev->nNumberOfStereoCenters > bRelRac ) {
313
+ /* pINChI_Prev exists and has sp3 info */
314
+ tot_len += MakeMult( mult+1, "*", pStr + tot_len, nStrLen-tot_len, 0, bOverflow);
315
+
316
+ tot_len += MakeStereoString( Stereo_Prev->nNumber, NULL, Stereo_Prev->t_parity,
317
+ 0, Stereo_Prev->nNumberOfStereoCenters,
318
+ pStr + tot_len, nStrLen-tot_len, TAUT_MODE, bOverflow);
319
+ }
320
+ /* else sp3 info is not present in pINChI_Prev */
321
+ } else
322
+ if ( bSecondNonTautPass && pINChI_Taut_Prev && pINChI_Taut_Prev->nNumberOfAtoms ) {
323
+ if ( (Stereo_Taut_Prev = pINChI_Taut_Prev->Stereo) && Stereo_Taut_Prev->nNumberOfStereoCenters > bRelRac ) {
324
+ /* since pINChI_Prev does not exist, pINChI_Taut_Prev is non-tautomeric */
325
+ /* and it has non-trivial sp3 info. This info has already been printed in the main section */
326
+ /*
327
+ tot_len += MakeDelim( sIdenticalValues, pStr + tot_len, nStrLen-tot_len, bOverflow);
328
+ */
329
+ ; /* pINChI_Taut_Prev sp3 info was output in the main stereo section */
330
+ } else {
331
+ ; /* pINChI_Taut_Prev exists and has not sp3 info */
332
+ }
333
+ }
334
+ #if( bRELEASE_VERSION != 1 && defined(_DEBUG) )
335
+ else {
336
+ int stop = 1; /* <BRKPT> */
337
+ }
338
+ #endif
339
+ }
340
+ pINChI_Prev = pINChI;
341
+ pINChI_Taut_Prev = pINChI_Taut;
342
+ mult = 0; /* we do not know whether the item is empty */
343
+ }
344
+ }
345
+ return tot_len;
346
+ }
347
+ /***************************************************************************/
348
+ int str_IsoAtoms(INCHI_SORT *pINChISort, INCHI_SORT *pINChISort2, char *pStr, int nStrLen, int tot_len,
349
+ int *bOverflow, int bOutType, int TAUT_MODE, int num_components, int bAbcNumbers,
350
+ int bSecondNonTautPass, int bOmitRepetitions, int bUseMulipliers)
351
+ {
352
+ int i, ii, ii2;
353
+ INCHI_SORT *is, *is2;
354
+ INChI *pINChI, *pINChI_Prev, *pINChI_Taut, *pINChI_Taut_Prev;
355
+ int mult, eq2prev, eq2taut, eq2tautPrev, bNext;
356
+ const char *pPrevEquStr, *pCurrEquStr;
357
+ int multPrevEquStr;
358
+ pINChI_Taut = NULL;
359
+ pINChI_Prev = NULL;
360
+ pINChI_Taut_Prev = NULL;
361
+ mult = 0;
362
+ bNext = 0;
363
+ is2 = bSecondNonTautPass? pINChISort2 : NULL;
364
+ eq2taut = 0; /* may be non-zero only on the 2nd (non-taut) pass */
365
+ eq2tautPrev = 1; /* pINChI_Prev (previous pINChI) does not exist */
366
+ pPrevEquStr = NULL; /*, *pCurrEquStr;*/
367
+ multPrevEquStr = 0;
368
+ for ( i = 0, is = pINChISort; i <= num_components; i ++, is ++, (bSecondNonTautPass? is2++ : 0) ) {
369
+ /* 1st (taut) pass: bOutType=OUT_TN ; 2nd (non-taut pass) bOutType=OUT_NT */
370
+ pINChI = (i < num_components && 0 <= (ii=GET_II(bOutType,is)))? is->pINChI[ii] : NULL;
371
+ /*================ compare isotopic info to previous component =====================*/
372
+ if ( bSecondNonTautPass ) {
373
+ /* component that was output on the 1st pass */
374
+ pINChI_Taut = ( i < num_components && 0 <= (ii2=GET_II(OUT_T1,is2)))? is2->pINChI[ii2] : NULL;
375
+ }
376
+ /*========= if bSecondNonTautPass then compare iso non-taut to taut non-iso ========*/
377
+ eq2taut = 0;
378
+ if ( !eq2taut && bSecondNonTautPass && bOmitRepetitions ) {
379
+ eq2taut = Eql_INChI_Isotopic( pINChI, pINChI_Taut );
380
+ eq2taut = eq2taut? (iiNUMB | iitNONTAUT) : 0;
381
+ }
382
+ if ( eq2taut ) {
383
+ /* we may be here only in case of the second (non-taut) pass */
384
+ /* current non-taut isotopic info has been found to be same as current tautomeric */
385
+ if ( pINChI_Prev && pINChI_Prev->nNumberOfAtoms ) {
386
+ /* previous component exists; output it */
387
+ if ( bNext ++ ) {
388
+ tot_len += MakeDelim( sCompDelim, pStr + tot_len, nStrLen-tot_len, bOverflow);
389
+ }
390
+ if ( pINChI_Prev && (pINChI_Prev->nNumberOfIsotopicAtoms > 0 ||
391
+ pINChI_Prev->nNumberOfIsotopicTGroups > 0) ) {
392
+ /* non-empty item */
393
+ tot_len += MakeMult( mult+1, "*", pStr + tot_len, nStrLen-tot_len, 0, bOverflow);
394
+ /* Isotopic atoms */
395
+ if ( pINChI_Prev->nNumberOfIsotopicAtoms > 0 && nStrLen-tot_len > 2 && !*bOverflow ) { /* dereferenced bOverflow 2004-06-07 */
396
+ tot_len += MakeIsoAtomString( pINChI_Prev->IsotopicAtom, pINChI_Prev->nNumberOfIsotopicAtoms,
397
+ pStr + tot_len, nStrLen-tot_len, TAUT_MODE, bOverflow);
398
+ }
399
+ /* Isotopic tautomeric groups */
400
+ if ( pINChI_Prev->nNumberOfIsotopicTGroups > 0 && nStrLen-tot_len > 3 && !*bOverflow ) {
401
+ tot_len += MakeDelim( bAbcNumbers? ITEM_DELIMETER : "(", pStr + tot_len, nStrLen-tot_len, bOverflow);
402
+ tot_len += MakeIsoTautString( pINChI_Prev->IsotopicTGroup, pINChI_Prev->nNumberOfIsotopicTGroups,
403
+ pStr + tot_len, nStrLen-tot_len, TAUT_MODE, bOverflow);
404
+ if ( !bAbcNumbers ) {
405
+ tot_len += MakeDelim( ")", pStr + tot_len, nStrLen-tot_len, bOverflow);
406
+ }
407
+ }
408
+ }
409
+ } else
410
+ if ( pINChI_Taut_Prev && pINChI_Taut_Prev->nNumberOfAtoms ) {
411
+ /* previous non-taut component exists only in taut list */
412
+ if ( bNext ++ ) {
413
+ tot_len += MakeDelim( sCompDelim, pStr + tot_len, nStrLen-tot_len, bOverflow);
414
+ }
415
+ }
416
+ /* we have found pINChI isotopic info to be same as in pINChI_Taut */
417
+ /* output this (current) equivalence as '*', that is, same as tautomeric */
418
+ /* that was printed on the 1st pass. */
419
+ pCurrEquStr = EquString(eq2taut);
420
+ if ( multPrevEquStr && pPrevEquStr ) {
421
+ if ( pCurrEquStr && !strcmp(pCurrEquStr, pPrevEquStr) ) {
422
+ multPrevEquStr ++;
423
+ } else {
424
+ /* new EqStr is different; output it */
425
+ if ( bNext ++ ) {
426
+ tot_len += MakeDelim( sCompDelim, pStr + tot_len, nStrLen-tot_len, bOverflow);
427
+ }
428
+ tot_len += MakeEqStr( pPrevEquStr, multPrevEquStr, pStr + tot_len, nStrLen-tot_len, bOverflow);
429
+ pPrevEquStr = pCurrEquStr;
430
+ multPrevEquStr = 1;
431
+ }
432
+ } else {
433
+ pPrevEquStr = pCurrEquStr;
434
+ multPrevEquStr = 1;
435
+ }
436
+ pINChI_Prev = NULL; /* pINChI_Prev isotopic info does not exist since */
437
+ pINChI_Taut_Prev = NULL; /* pINChI has just been printed */
438
+ mult = 0;
439
+ eq2tautPrev = 1; /* pINChI_Prev isotopic info does not exist */
440
+ } else
441
+ if ( eq2tautPrev ) {
442
+ /* at this point pINChI_Prev does not exist; however, pINChI */
443
+ /* might have been discovered and it is different from pINChI_Taut */
444
+ if ( multPrevEquStr && pPrevEquStr ) {
445
+ /* new EqStr is different; output it */
446
+ if ( bNext ++ ) {
447
+ tot_len += MakeDelim( sCompDelim, pStr + tot_len, nStrLen-tot_len, bOverflow);
448
+ }
449
+ tot_len += MakeEqStr( pPrevEquStr, multPrevEquStr, pStr + tot_len, nStrLen-tot_len, bOverflow);
450
+ pPrevEquStr = NULL;
451
+ multPrevEquStr = 0;
452
+ }
453
+ eq2tautPrev = 0;
454
+ pINChI_Prev = pINChI;
455
+ pINChI_Taut_Prev = pINChI_Taut;
456
+ mult = 0;
457
+ } else {
458
+ /*================ compare iso composition to previous =====================*/
459
+ /* check whether pINChI and pINChI_Prev have non-zero identical isotopic info */
460
+ eq2prev =bUseMulipliers && Eql_INChI_Isotopic( pINChI, pINChI_Prev );
461
+ if ( eq2prev ) {
462
+ mult ++; /* mult = (number of non-empty equal items)-1 */
463
+ continue;
464
+ } else {
465
+ /* pINChI isotopic info is either different or empty. Output pINChI_Prev anyway */
466
+ if ( bNext ++ ) {
467
+ tot_len += MakeDelim( sCompDelim, pStr + tot_len, nStrLen-tot_len, bOverflow);
468
+ }
469
+ if ( pINChI_Prev && pINChI_Prev->nNumberOfAtoms ) {
470
+ if ( (pINChI_Prev->nNumberOfIsotopicAtoms > 0 ||
471
+ pINChI_Prev->nNumberOfIsotopicTGroups > 0) ) {
472
+ /* pINChI_Prev exists and has isotopic info */
473
+ tot_len += MakeMult( mult+1, "*", pStr + tot_len, nStrLen-tot_len, 0, bOverflow);
474
+ /* Isotopic atoms */
475
+ if ( pINChI_Prev->nNumberOfIsotopicAtoms > 0 && nStrLen-tot_len > 2 && !*bOverflow ) {
476
+ tot_len += MakeIsoAtomString( pINChI_Prev->IsotopicAtom, pINChI_Prev->nNumberOfIsotopicAtoms,
477
+ pStr + tot_len, nStrLen-tot_len, TAUT_MODE, bOverflow);
478
+ }
479
+ /* Isotopic tautomeric groups */
480
+ if ( pINChI_Prev->nNumberOfIsotopicTGroups > 0 && nStrLen-tot_len > 3 && !*bOverflow ) {
481
+ tot_len += MakeDelim( bAbcNumbers? ITEM_DELIMETER : "(", pStr + tot_len, nStrLen-tot_len, bOverflow);
482
+ tot_len += MakeIsoTautString( pINChI_Prev->IsotopicTGroup, pINChI_Prev->nNumberOfIsotopicTGroups,
483
+ pStr + tot_len, nStrLen-tot_len, TAUT_MODE, bOverflow);
484
+ if ( !bAbcNumbers ) {
485
+ tot_len += MakeDelim( ")", pStr + tot_len, nStrLen-tot_len, bOverflow);
486
+ }
487
+ }
488
+ }
489
+ /* else isotopic info is not present in pINChI_Prev */
490
+ } else
491
+ if ( bSecondNonTautPass && pINChI_Taut_Prev && pINChI_Taut_Prev->nNumberOfAtoms ) {
492
+ if ( (pINChI_Taut_Prev->nNumberOfIsotopicAtoms > 0 ||
493
+ pINChI_Taut_Prev->nNumberOfIsotopicTGroups > 0) ) {
494
+ /* since pINChI_Prev does not exist, pINChI_Taut_Prev is non-tautomeric */
495
+ /* and it has non-trivial isotopic info */
496
+ /*
497
+ tot_len += MakeDelim( sIdenticalValues, pStr + tot_len, nStrLen-tot_len, bOverflow);
498
+ */
499
+ ;/* pINChI_Taut_Prev isotopic info was output in the main isotopic section */
500
+ } else {
501
+ ; /* pINChI_Taut_Prev exists and has not isotopic info */
502
+ }
503
+ }
504
+ #if( bRELEASE_VERSION != 1 && defined(_DEBUG) )
505
+ else {
506
+ int stop = 1; /* <BRKPT> */
507
+ }
508
+ #endif
509
+ }
510
+ /* Fix17: moved here 2004-10-08 */
511
+ pINChI_Prev = pINChI;
512
+ pINChI_Taut_Prev = pINChI_Taut;
513
+ mult = 0; /* we do not know whether the item is empty */
514
+ }
515
+ /* Fix17: moved from here 2004-10-08
516
+ pINChI_Prev = pINChI;
517
+ pINChI_Taut_Prev = pINChI_Taut;
518
+ mult = 0;
519
+ */
520
+ }
521
+ return tot_len;
522
+ }
523
+ /***************************************************************************/
524
+ int str_IsoSp2(INCHI_SORT *pINChISort, INCHI_SORT *pINChISort2, char *pStr, int nStrLen, int tot_len,
525
+ int *bOverflow, int bOutType, int TAUT_MODE, int num_components,
526
+ int bSecondNonTautPass, int bOmitRepetitions, int bUseMulipliers)
527
+ {
528
+ int i, ii, ii2;
529
+ INCHI_SORT *is, *is2;
530
+ INChI *pINChI, *pINChI_Prev, *pINChI_Taut, *pINChI_Taut_Prev;
531
+ INChI_Stereo *Stereo, *Stereo_Prev, *Stereo_Taut, *Stereo_Taut_Prev;
532
+ int mult, eq2prev, eq2taut, eq2tautPrev, bNext;
533
+ const char *pPrevEquStr, *pCurrEquStr;
534
+ int multPrevEquStr;
535
+ pINChI_Taut = NULL;
536
+ pINChI_Prev = NULL;
537
+ pINChI_Taut_Prev = NULL;
538
+ mult = 0;
539
+ bNext = 0;
540
+ is2 = bSecondNonTautPass? pINChISort2 : NULL;
541
+ eq2taut = 0; /* may be non-zero if another layer of the current component = current layer */
542
+ eq2tautPrev = 1; /* pINChI_Prev (previous pINChI) does not exist */
543
+ pPrevEquStr = NULL; /*, *pCurrEquStr;*/
544
+ multPrevEquStr = 0;
545
+ for ( i = 0, is = pINChISort; i <= num_components; i ++, is ++, (bSecondNonTautPass? is2++ : 0) ) {
546
+ /* 1st (taut) pass: bOutType=OUT_TN ; 2nd (non-taut pass) bOutType=OUT_NT */
547
+ pINChI = (i < num_components && 0 <= (ii=GET_II(bOutType,is)))? is->pINChI[ii] : NULL;
548
+ /*================ compare sp2 to previous =====================*/
549
+ if ( bSecondNonTautPass ) {
550
+ /* component that was output on the 1st pass */
551
+ pINChI_Taut = ( i < num_components && 0 <= (ii2=GET_II(OUT_T1,is2)))? is2->pINChI[ii2] : NULL;
552
+ }
553
+ eq2taut = 0;
554
+ /*========= if bSecondNonTautPass then compare iso non-taut stereo to other stereo ========*/
555
+ if ( bSecondNonTautPass && bOmitRepetitions ) {
556
+ /* compare non-tautomeric isotopic to:
557
+ * a) non-tautomeric non-isotopic
558
+ * b) tautomeric non-isotopic
559
+ * c) tautomeric non-isotopic and isotopic
560
+ */
561
+ /* a) compare non-tautomeric isotopic to non-tautomeric non-isotopic */
562
+ if ( !eq2taut ) {
563
+ eq2taut = pINChI &&
564
+ /* non-taut isotopic */ /* non-taut non-isotopic */
565
+ (Stereo = pINChI->StereoIsotopic) && (Stereo_Taut = pINChI->Stereo) &&
566
+ Eql_INChI_Stereo( Stereo, EQL_SP2, Stereo_Taut, EQL_SP2, 0 );
567
+ /* stereo isotopic non-taut = non-taut (stereo) */
568
+ eq2taut = eq2taut? (iiSTEREO | iitISO | iitNONTAUT | iiEq2NONTAUT ) : 0;
569
+ }
570
+ /* b) compare non-tautomeric isotopic to tautomeric non-isotopic */
571
+ if ( !eq2taut ) {
572
+ eq2taut = pINChI && pINChI_Taut &&
573
+ /* non-taut isotopic */ /* taut non-isotopic */
574
+ (Stereo = pINChI->StereoIsotopic) && (Stereo_Taut = pINChI_Taut->Stereo) &&
575
+ Eql_INChI_Stereo( Stereo, EQL_SP2, Stereo_Taut, EQL_SP2, 0 );
576
+ /* stereo isotopic non-taut = taut (stereo) */
577
+ eq2taut = eq2taut? (iiSTEREO | iitISO | iitNONTAUT ) : 0;
578
+ }
579
+ /* c) compare non-tautomeric isotopic to tautomeric isotopic */
580
+ if ( !eq2taut && bSecondNonTautPass && bOmitRepetitions ) {
581
+ eq2taut = pINChI && pINChI_Taut &&
582
+ (Stereo = pINChI->StereoIsotopic) && (Stereo_Taut = pINChI_Taut->StereoIsotopic) &&
583
+ Eql_INChI_Stereo( Stereo, EQL_SP2, Stereo_Taut, EQL_SP2, 0 );
584
+ /* stereo isotopic non-taut = isotopic taut (stereo) */
585
+ eq2taut = eq2taut? (iiSTEREO | iitISO | iitNONTAUT | iiEq2ISO) : 0;
586
+ }
587
+ } else
588
+ /*========= if not bSecondNonTautPass then compare iso taut stereo to non-iso taut ========*/
589
+ if ( !bSecondNonTautPass && bOmitRepetitions ) {
590
+ /* compare tautomeric isotopic to tautomeric non-isotopic */
591
+ if ( !eq2taut ) {
592
+ eq2taut = pINChI &&
593
+ /* taut isotopic */ /* taut non-isotopic */
594
+ (Stereo = pINChI->StereoIsotopic) && (Stereo_Taut = pINChI->Stereo) &&
595
+ Eql_INChI_Stereo( Stereo, EQL_SP2, Stereo_Taut, EQL_SP2, 0 );
596
+ /* stereo isotopic taut = taut (stereo) */
597
+ eq2taut = eq2taut? (iiSTEREO | iitISO ) : 0;
598
+ }
599
+ }
600
+ if ( eq2taut ) {
601
+ /* we may be here only in case of the current layer found equal in another layer the same component */
602
+ if ( pINChI_Prev && pINChI_Prev->nNumberOfAtoms ) {
603
+ /* previous component exists; output it before output the current component */
604
+ if ( bNext ++ ) {
605
+ tot_len += MakeDelim( sCompDelim, pStr + tot_len, nStrLen-tot_len, bOverflow);
606
+ }
607
+ if ( (Stereo_Prev = pINChI_Prev->StereoIsotopic) && Stereo_Prev->nNumberOfStereoBonds > 0 ) {
608
+ tot_len += MakeMult( mult+1, "*", pStr + tot_len, nStrLen-tot_len, 0, bOverflow);
609
+
610
+ tot_len += MakeStereoString( Stereo_Prev->nBondAtom1, Stereo_Prev->nBondAtom2,
611
+ Stereo_Prev->b_parity,
612
+ 0, Stereo_Prev->nNumberOfStereoBonds,
613
+ pStr + tot_len, nStrLen-tot_len, TAUT_MODE, bOverflow);
614
+ }
615
+ } else
616
+ if ( pINChI_Taut_Prev && pINChI_Taut_Prev->nNumberOfAtoms ) {
617
+ /* previous non-taut component exists only in taut list */
618
+ if ( bNext ++ ) {
619
+ tot_len += MakeDelim( sCompDelim, pStr + tot_len, nStrLen-tot_len, bOverflow);
620
+ }
621
+ /* do not output stereo of non-tautomeric in non-taut layer: it has been output in the main layer */
622
+ }
623
+ /* we have found another (previously printed) layer of the current component equal to this layer */
624
+ /* output this (current) equivalence mark = EquString(eq2taut) */
625
+ pCurrEquStr = EquString(eq2taut);
626
+ if ( multPrevEquStr && pPrevEquStr ) {
627
+ if ( pCurrEquStr && !strcmp(pCurrEquStr, pPrevEquStr) ) {
628
+ multPrevEquStr ++;
629
+ } else {
630
+ /* new EqStr is different; output it */
631
+ if ( bNext ++ ) {
632
+ tot_len += MakeDelim( sCompDelim, pStr + tot_len, nStrLen-tot_len, bOverflow);
633
+ }
634
+ tot_len += MakeEqStr( pPrevEquStr, multPrevEquStr, pStr + tot_len, nStrLen-tot_len, bOverflow);
635
+ pPrevEquStr = pCurrEquStr;
636
+ multPrevEquStr = 1;
637
+ }
638
+ } else {
639
+ pPrevEquStr = pCurrEquStr;
640
+ multPrevEquStr = 1;
641
+ }
642
+ pINChI_Prev = NULL; /* pINChI_Prev sp2 does not exist since */
643
+ pINChI_Taut_Prev = NULL; /* pINChI has just been printed */
644
+ mult = 0;
645
+ eq2tautPrev = 1; /* pINChI_Prev and pINChI_Taut_Prev have already been output */
646
+ } else
647
+ if ( eq2tautPrev ) {
648
+ /* at this point pINChI_Prev does not exist; however, pINChI */
649
+ /*might have been discovered and it is different from pINChI_Taut */
650
+ if ( multPrevEquStr && pPrevEquStr ) {
651
+ /* new EqStr is different; output it */
652
+ if ( bNext ++ ) {
653
+ tot_len += MakeDelim( sCompDelim, pStr + tot_len, nStrLen-tot_len, bOverflow);
654
+ }
655
+ tot_len += MakeEqStr( pPrevEquStr, multPrevEquStr, pStr + tot_len, nStrLen-tot_len, bOverflow);
656
+ pPrevEquStr = NULL;
657
+ multPrevEquStr = 0;
658
+ }
659
+ eq2tautPrev = 0;
660
+ pINChI_Prev = pINChI;
661
+ pINChI_Taut_Prev = pINChI_Taut;
662
+ mult = 0;
663
+ } else {
664
+ /* current layer is different from previously printed layers of the current component */
665
+ /* compare the current layer to this layer of the previous component: */
666
+ /* check whether pINChI and pINChI_Prev have non-zero identical stereo sp2 */
667
+ /*================ compare iso sp2 to previous =====================*/
668
+ eq2prev =bUseMulipliers &&
669
+ pINChI && pINChI_Prev &&
670
+ (Stereo = pINChI->StereoIsotopic) && (Stereo_Prev = pINChI_Prev->StereoIsotopic) &&
671
+ Eql_INChI_Stereo( Stereo, EQL_SP2, Stereo_Prev, EQL_SP2, 0 );
672
+ if ( eq2prev ) {
673
+ mult ++; /* mult = (number of non-empty equal items)-1 */
674
+ continue;
675
+ } else {
676
+ /* the current layer is different from this layer of the previous component */
677
+ /* therefore print the current layer */
678
+ if ( bNext ++ ) {
679
+ tot_len += MakeDelim( sCompDelim, pStr + tot_len, nStrLen-tot_len, bOverflow);
680
+ }
681
+ if ( pINChI_Prev && pINChI_Prev->nNumberOfAtoms ) {
682
+ if ( (Stereo_Prev = pINChI_Prev->StereoIsotopic) && Stereo_Prev->nNumberOfStereoBonds > 0 ) {
683
+ tot_len += MakeMult( mult+1, "*", pStr + tot_len, nStrLen-tot_len, 0, bOverflow);
684
+
685
+ tot_len += MakeStereoString( Stereo_Prev->nBondAtom1, Stereo_Prev->nBondAtom2,
686
+ Stereo_Prev->b_parity,
687
+ 0, Stereo_Prev->nNumberOfStereoBonds,
688
+ pStr + tot_len, nStrLen-tot_len, TAUT_MODE, bOverflow);
689
+ }
690
+ /* else sp2 info is not present in pINChI_Prev */
691
+ } else
692
+ /* do not print pINChI_Prev because it either do not exist of have already been printed */
693
+ if ( bSecondNonTautPass && pINChI_Taut_Prev && pINChI_Taut_Prev->nNumberOfAtoms ) {
694
+ if ( (Stereo_Taut_Prev = pINChI_Taut_Prev->StereoIsotopic) && Stereo_Taut_Prev->nNumberOfStereoBonds > 0 ) {
695
+ /* since pINChI_Prev does not exist, pINChI_Taut_Prev is non-tautomeric */
696
+ /* and it has non-trivial sp2 info */
697
+ /*
698
+ tot_len += MakeDelim( sIdenticalValues, pStr + tot_len, nStrLen-tot_len, bOverflow);
699
+ */
700
+ ;/* pINChI_Taut_Prev sp3 info was output in the main stereo section */
701
+ } else {
702
+ ; /* pINChI_Taut_Prev exists and has not sp2 info */
703
+ }
704
+ }
705
+ #if( bRELEASE_VERSION != 1 && defined(_DEBUG) )
706
+ else {
707
+ int stop = 1; /* <BRKPT> */
708
+ }
709
+ #endif
710
+ }
711
+ pINChI_Prev = pINChI;
712
+ pINChI_Taut_Prev = pINChI_Taut;
713
+ mult = 0; /* we do not know whether the item is empty */
714
+ }
715
+ }
716
+ return tot_len;
717
+ }
718
+ /******************************************************************************************/
719
+ int str_IsoSp3(INCHI_SORT *pINChISort, INCHI_SORT *pINChISort2, char *pStr, int nStrLen, int tot_len,
720
+ int *bOverflow, int bOutType, int TAUT_MODE, int num_components, int bRelRac,
721
+ int bSecondNonTautPass, int bOmitRepetitions, int bUseMulipliers)
722
+ {
723
+ int i, ii, ii2;
724
+ INCHI_SORT *is, *is2;
725
+ INChI *pINChI, *pINChI_Prev, *pINChI_Taut, *pINChI_Taut_Prev;
726
+ INChI_Stereo *Stereo, *Stereo_Prev, *Stereo_Taut, *Stereo_Taut_Prev;
727
+ int mult, eq2prev, eq2taut, eq2tautPrev, bNext;
728
+ const char *pPrevEquStr, *pCurrEquStr;
729
+ int multPrevEquStr;
730
+ pINChI_Taut = NULL;
731
+ pINChI_Prev = NULL;
732
+ pINChI_Taut_Prev = NULL;
733
+ mult = 0;
734
+ bNext = 0;
735
+ is2 = bSecondNonTautPass? pINChISort2 : NULL;
736
+ eq2taut = 0; /* may be non-zero if another layer of the current component = current layer */
737
+ eq2tautPrev = 1; /* pINChI_Prev (previous pINChI) does not exist */
738
+ pPrevEquStr = NULL; /*, *pCurrEquStr;*/
739
+ multPrevEquStr = 0;
740
+ #if( REL_RAC_STEREO_IGN_1_SC == 1 )
741
+ #else
742
+ bRelRac = 0;
743
+ #endif
744
+ for ( i = 0, is = pINChISort; i <= num_components; i ++, is ++, (bSecondNonTautPass? is2++ : 0) ) {
745
+ /* 1st (taut) pass: bOutType=OUT_TN ; 2nd (non-taut pass) bOutType=OUT_NT */
746
+ pINChI = (i < num_components && 0 <= (ii=GET_II(bOutType,is)))? is->pINChI[ii] : NULL;
747
+ /*================ compare sp2 to previous =====================*/
748
+ if ( bSecondNonTautPass ) {
749
+ /* component that was output on the 1st pass */
750
+ pINChI_Taut = ( i < num_components && 0 <= (ii2=GET_II(OUT_T1,is2)))? is2->pINChI[ii2] : NULL;
751
+ }
752
+ eq2taut = 0;
753
+ /*========= if bSecondNonTautPass then compare iso non-taut stereo to other stereo ========*/
754
+ if ( bSecondNonTautPass && bOmitRepetitions ) {
755
+ /* compare non-tautomeric isotopic to:
756
+ * a) non-tautomeric non-isotopic
757
+ * b) tautomeric non-isotopic
758
+ * c) tautomeric non-isotopic and isotopic
759
+ */
760
+ /* a) compare non-tautomeric isotopic to non-tautomeric non-isotopic */
761
+ if ( !eq2taut ) {
762
+ eq2taut = pINChI && /* non-taut isotopic */ /* non-taut non-isotopic */
763
+ (Stereo = pINChI->StereoIsotopic) && (Stereo_Taut = pINChI->Stereo) &&
764
+ Eql_INChI_Stereo( Stereo, EQL_SP3, Stereo_Taut, EQL_SP3, bRelRac );
765
+ /* stereo isotopic non-taut = non-taut (stereo) */
766
+ eq2taut = eq2taut? (iiSTEREO | iitISO | iitNONTAUT | iiEq2NONTAUT ) : 0;
767
+ }
768
+ /* b) compare non-tautomeric isotopic to tautomeric non-isotopic */
769
+ if ( !eq2taut ) {
770
+ eq2taut = pINChI && pINChI_Taut &&
771
+ /* non-taut isotopic */ /* taut non-isotopic */
772
+ (Stereo = pINChI->StereoIsotopic) && (Stereo_Taut = pINChI_Taut->Stereo) &&
773
+ Eql_INChI_Stereo( Stereo, EQL_SP3, Stereo_Taut, EQL_SP3, bRelRac );
774
+ /* stereo isotopic non-taut = taut (stereo) */
775
+ eq2taut = eq2taut? (iiSTEREO | iitISO | iitNONTAUT ) : 0;
776
+ }
777
+ /* c) compare non-tautomeric isotopic to tautomeric isotopic */
778
+ if ( !eq2taut && bSecondNonTautPass && bOmitRepetitions ) {
779
+ eq2taut = pINChI && pINChI_Taut &&
780
+ (Stereo = pINChI->StereoIsotopic) && (Stereo_Taut = pINChI_Taut->StereoIsotopic) &&
781
+ Eql_INChI_Stereo( Stereo, EQL_SP3, Stereo_Taut, EQL_SP3, bRelRac );
782
+ /* stereo isotopic non-taut = isotopic taut (stereo) */
783
+ eq2taut = eq2taut? (iiSTEREO | iitISO | iitNONTAUT | iiEq2ISO) : 0;
784
+ }
785
+ } else
786
+ /*========= if not bSecondNonTautPass then compare iso taut stereo to non-iso taut ========*/
787
+ if ( !bSecondNonTautPass && bOmitRepetitions ) {
788
+ /* compare tautomeric isotopic to tautomeric non-isotopic */
789
+ if ( !eq2taut ) {
790
+ eq2taut = pINChI &&
791
+ /* taut isotopic */ /* taut non-isotopic */
792
+ (Stereo = pINChI->StereoIsotopic) && (Stereo_Taut = pINChI->Stereo) &&
793
+ Eql_INChI_Stereo( Stereo, EQL_SP3, Stereo_Taut, EQL_SP3, bRelRac );
794
+ /* stereo isotopic taut = taut (stereo) */
795
+ eq2taut = eq2taut? (iiSTEREO | iitISO ) : 0;
796
+ }
797
+ }
798
+ if ( eq2taut ) {
799
+ /* we may be here only in case of the current layer found equal in another layer the same component */
800
+ if ( pINChI_Prev && pINChI_Prev->nNumberOfAtoms ) {
801
+ /* previous component exists; output it before output the current component */
802
+ if ( bNext ++ ) {
803
+ tot_len += MakeDelim( sCompDelim, pStr + tot_len, nStrLen-tot_len, bOverflow);
804
+ }
805
+ if ( (Stereo_Prev = pINChI_Prev->StereoIsotopic) && Stereo_Prev->nNumberOfStereoCenters > bRelRac ) {
806
+ tot_len += MakeMult( mult+1, "*", pStr + tot_len, nStrLen-tot_len, 0, bOverflow);
807
+
808
+ tot_len += MakeStereoString( Stereo_Prev->nNumber, NULL, Stereo_Prev->t_parity,
809
+ 0, Stereo_Prev->nNumberOfStereoCenters,
810
+ pStr + tot_len, nStrLen-tot_len, TAUT_MODE, bOverflow);
811
+ }
812
+ } else
813
+ if ( pINChI_Taut_Prev && pINChI_Taut_Prev->nNumberOfAtoms ) {
814
+ /* previous non-taut component exists only in taut list */
815
+ if ( bNext ++ ) {
816
+ tot_len += MakeDelim( sCompDelim, pStr + tot_len, nStrLen-tot_len, bOverflow);
817
+ }
818
+ /* do not output stereo of non-tautomeric in non-taut layer: it has been output in the main layer */
819
+ }
820
+ /* we have found another (previously printed) layer of the current component equal to this layer */
821
+ /* output this (current) equivalence mark = EquString(eq2taut) */
822
+ pCurrEquStr = EquString(eq2taut);
823
+ if ( multPrevEquStr && pPrevEquStr ) {
824
+ if ( pCurrEquStr && !strcmp(pCurrEquStr, pPrevEquStr) ) {
825
+ multPrevEquStr ++;
826
+ } else {
827
+ /* new EqStr is different; output it */
828
+ if ( bNext ++ ) {
829
+ tot_len += MakeDelim( sCompDelim, pStr + tot_len, nStrLen-tot_len, bOverflow);
830
+ }
831
+ tot_len += MakeEqStr( pPrevEquStr, multPrevEquStr, pStr + tot_len, nStrLen-tot_len, bOverflow);
832
+ pPrevEquStr = pCurrEquStr;
833
+ multPrevEquStr = 1;
834
+ }
835
+ } else {
836
+ pPrevEquStr = pCurrEquStr;
837
+ multPrevEquStr = 1;
838
+ }
839
+ pINChI_Prev = NULL; /* pINChI_Prev sp2 does not exist since */
840
+ pINChI_Taut_Prev = NULL; /* pINChI has just been printed */
841
+ mult = 0;
842
+ eq2tautPrev = 1; /* pINChI_Prev and pINChI_Taut_Prev have already been output */
843
+ } else
844
+ if ( eq2tautPrev ) {
845
+ /* at this point pINChI_Prev does not exist; however, pINChI */
846
+ /*might have been discovered and it is different from pINChI_Taut */
847
+ if ( multPrevEquStr && pPrevEquStr ) {
848
+ /* new EqStr is different; output it */
849
+ if ( bNext ++ ) {
850
+ tot_len += MakeDelim( sCompDelim, pStr + tot_len, nStrLen-tot_len, bOverflow);
851
+ }
852
+ tot_len += MakeEqStr( pPrevEquStr, multPrevEquStr, pStr + tot_len, nStrLen-tot_len, bOverflow);
853
+ pPrevEquStr = NULL;
854
+ multPrevEquStr = 0;
855
+ }
856
+ eq2tautPrev = 0;
857
+ pINChI_Prev = pINChI;
858
+ pINChI_Taut_Prev = pINChI_Taut;
859
+ mult = 0;
860
+ } else {
861
+ /* current layer is different from previously printed layers of the current component */
862
+ /* compare the current layer to this layer of the previous component: */
863
+ /* check whether pINChI and pINChI_Prev have non-zero identical stereo sp2 */
864
+ /*================ compare iso sp3 to previous =====================*/
865
+ eq2prev =bUseMulipliers && pINChI && pINChI_Prev &&
866
+ (Stereo = pINChI->StereoIsotopic) && (Stereo_Prev = pINChI_Prev->StereoIsotopic) &&
867
+ Eql_INChI_Stereo( Stereo, EQL_SP3, Stereo_Prev, EQL_SP3, bRelRac );
868
+ if ( eq2prev ) {
869
+ mult ++; /* mult = (number of non-empty equal items)-1 */
870
+ continue;
871
+ } else {
872
+ if ( bNext ++ ) {
873
+ tot_len += MakeDelim( sCompDelim, pStr + tot_len, nStrLen-tot_len, bOverflow);
874
+ }
875
+ if ( pINChI_Prev && pINChI_Prev->nNumberOfAtoms ) {
876
+ if ( (Stereo_Prev = pINChI_Prev->StereoIsotopic) && Stereo_Prev->nNumberOfStereoCenters > bRelRac ) {
877
+ tot_len += MakeMult( mult+1, "*", pStr + tot_len, nStrLen-tot_len, 0, bOverflow);
878
+
879
+ tot_len += MakeStereoString( Stereo_Prev->nNumber, NULL, Stereo_Prev->t_parity,
880
+ 0, Stereo_Prev->nNumberOfStereoCenters,
881
+ pStr + tot_len, nStrLen-tot_len, TAUT_MODE, bOverflow);
882
+ }
883
+ /* else sp3 info is not present in pINChI_Prev */
884
+ } else
885
+ /* do not print pINChI_Prev because it either do not exist of have already been printed */
886
+ if ( bSecondNonTautPass && pINChI_Taut_Prev && pINChI_Taut_Prev->nNumberOfAtoms ) {
887
+ if ( (Stereo_Taut_Prev = pINChI_Taut_Prev->StereoIsotopic) && Stereo_Taut_Prev->nNumberOfStereoCenters > bRelRac ) {
888
+ /* since pINChI_Prev does not exist, pINChI_Taut_Prev is non-tautomeric */
889
+ /* and it has non-trivial sp2 info */
890
+ /*
891
+ tot_len += MakeDelim( sIdenticalValues, pStr + tot_len, nStrLen-tot_len, bOverflow);
892
+ */
893
+ ;/* pINChI_Taut_Prev sp3 info was output in the main stereo section */
894
+ } else {
895
+ ; /* pINChI_Taut_Prev exists and has not sp3 info */
896
+ }
897
+ }
898
+ #if( bRELEASE_VERSION != 1 && defined(_DEBUG) )
899
+ else {
900
+ int stop = 1; /* <BRKPT> */
901
+ }
902
+ #endif
903
+ }
904
+ pINChI_Prev = pINChI;
905
+ pINChI_Taut_Prev = pINChI_Taut;
906
+ mult = 0; /* we do not know whether the item is empty */
907
+ }
908
+ }
909
+ return tot_len;
910
+ }
911
+ /***************************************************************************/
912
+ int str_AuxEqu(INCHI_SORT *pINChISort, INCHI_SORT *pINChISort2, char *pStr, int nStrLen, int tot_len,
913
+ int *bOverflow, int bOutType, int TAUT_MODE, int num_components,
914
+ int bSecondNonTautPass, int bOmitRepetitions, int bUseMulipliers)
915
+ {
916
+ int i, ii, ii2;
917
+ INCHI_SORT *is, *is2;
918
+ INChI_Aux *pINChI_Aux = NULL, *pINChI_Aux_Prev, *pINChI_Aux_Taut, *pINChI_Aux_Taut_Prev;
919
+ int mult, eq2prev, eq2taut, eq2tautPrev, bNext;
920
+ const char *pPrevEquStr, *pCurrEquStr;
921
+ int multPrevEquStr;
922
+ pINChI_Aux_Prev = NULL;
923
+ pINChI_Aux_Taut = NULL;
924
+ pINChI_Aux_Taut_Prev = NULL;
925
+
926
+ mult = 0;
927
+ bNext = 0;
928
+ is2 = bSecondNonTautPass? pINChISort2 : NULL;
929
+ eq2taut = 0; /* may be non-zero only on the 2nd (non-taut) pass */
930
+ eq2tautPrev = 1; /* pINChI_Aux_Prev (previous pINChI_Aux) does not exist */
931
+ pPrevEquStr = NULL; /*, *pCurrEquStr;*/
932
+ multPrevEquStr = 0;
933
+ for ( i = 0, is = pINChISort; i <= num_components; i ++, is ++, (bSecondNonTautPass? is2++ : 0) ) {
934
+ /* 1st (taut) pass: bOutType=OUT_TN ; 2nd (non-taut pass) bOutType=OUT_NT */
935
+ pINChI_Aux = (i < num_components && 0 <= (ii=GET_II(bOutType,is)))? is->pINChI_Aux[ii] : NULL;
936
+ if ( bSecondNonTautPass ) {
937
+ /* component that was output on the 1st pass */
938
+ pINChI_Aux_Taut = ( i < num_components && 0 <= (ii2=GET_II(OUT_T1,is2)))? is2->pINChI_Aux[ii2] : NULL;
939
+ }
940
+ /*================ compare non-iso non-taut equivalence info to non-iso taut ========*/
941
+ eq2taut = bSecondNonTautPass && bOmitRepetitions &&
942
+ Eql_INChI_Aux_Equ( pINChI_Aux, EQL_EQU, pINChI_Aux_Taut, EQL_EQU );
943
+ eq2taut = eq2taut? (iiEQU | iitNONTAUT) : 0;
944
+ if ( eq2taut ) {
945
+ /* we may be here only in case of the second (non-taut) pass */
946
+ /* current non-taut equivalence has been found to be same as tautomeric */
947
+ if ( pINChI_Aux_Prev && pINChI_Aux_Prev->nNumberOfAtoms ) {
948
+ /* previous component exists */
949
+ if ( bNext ++ ) {
950
+ tot_len += MakeDelim( sCompDelim, pStr + tot_len, nStrLen-tot_len, bOverflow);
951
+ }
952
+ if ( bHasEquString( pINChI_Aux_Prev->nConstitEquNumbers, pINChI_Aux_Prev->nNumberOfAtoms) ) {
953
+ /* output previous component(s) equivalence since it was found to be non-trivial */
954
+ tot_len += MakeMult( mult+1, "*", pStr + tot_len, nStrLen-tot_len, 0, bOverflow);
955
+ tot_len += MakeEquString( pINChI_Aux_Prev->nConstitEquNumbers, pINChI_Aux_Prev->nNumberOfAtoms, 0,
956
+ pStr + tot_len, nStrLen-tot_len, TAUT_MODE, bOverflow);
957
+ } else {
958
+ ; /* pINChI_Aux_Prev exists and has only trivial equivalence info */
959
+ }
960
+ } else
961
+ if ( pINChI_Aux_Taut_Prev && pINChI_Aux_Taut_Prev->nNumberOfAtoms ) {
962
+ /* previous non-taut component exists only in taut list */
963
+ if ( bNext ++ ) {
964
+ tot_len += MakeDelim( sCompDelim, pStr + tot_len, nStrLen-tot_len, bOverflow);
965
+ }
966
+ }
967
+ /* we have found pINChI_Aux->nConstitEquNumbers same as in pINChI_Aux_Taut */
968
+ /* output this (current) equivalence as '*', that is, same as tautomeric */
969
+ /* that was printed on the 1st pass. */
970
+ pCurrEquStr = EquString(eq2taut);
971
+ if ( multPrevEquStr && pPrevEquStr ) {
972
+ if ( pCurrEquStr && !strcmp(pCurrEquStr, pPrevEquStr) ) {
973
+ multPrevEquStr ++;
974
+ } else {
975
+ /* new EqStr is different; output it */
976
+ if ( bNext ++ ) {
977
+ tot_len += MakeDelim( sCompDelim, pStr + tot_len, nStrLen-tot_len, bOverflow);
978
+ }
979
+ tot_len += MakeEqStr( pPrevEquStr, multPrevEquStr, pStr + tot_len, nStrLen-tot_len, bOverflow);
980
+ pPrevEquStr = pCurrEquStr;
981
+ multPrevEquStr = 1;
982
+ }
983
+ } else {
984
+ pPrevEquStr = pCurrEquStr;
985
+ multPrevEquStr = 1;
986
+ }
987
+ pINChI_Aux_Prev = NULL; /* pINChI_Aux_Prev does not exist since */
988
+ pINChI_Aux_Taut_Prev = NULL; /* pINChI_Aux has just been printed */
989
+ mult = 0;
990
+ eq2tautPrev = 1;
991
+ } else
992
+ if ( eq2tautPrev ) {
993
+ /* at this point pINChI_Aux_Prev does not exist; however, pINChI_Aux */
994
+ /*might have been discovered and it is different from pINChI_Aux_Taut */
995
+ if ( multPrevEquStr && pPrevEquStr ) {
996
+ /* new EqStr is different; output it */
997
+ if ( bNext ++ ) {
998
+ tot_len += MakeDelim( sCompDelim, pStr + tot_len, nStrLen-tot_len, bOverflow);
999
+ }
1000
+ tot_len += MakeEqStr( pPrevEquStr, multPrevEquStr, pStr + tot_len, nStrLen-tot_len, bOverflow);
1001
+ pPrevEquStr = NULL;
1002
+ multPrevEquStr = 0;
1003
+ }
1004
+ eq2tautPrev = 0;
1005
+ pINChI_Aux_Prev = pINChI_Aux;
1006
+ pINChI_Aux_Taut_Prev = pINChI_Aux_Taut;
1007
+ mult = 0;
1008
+ } else {
1009
+ /* check whether pINChI_Aux and pINChI_Aux_Prev have identical non-trivial equivalence info */
1010
+ eq2prev = bUseMulipliers &&
1011
+ Eql_INChI_Aux_Equ( pINChI_Aux, EQL_EQU, pINChI_Aux_Prev, EQL_EQU );
1012
+ if ( eq2prev ) {
1013
+ /* eq. info is same and non-trivial */
1014
+ mult ++; /* mult = (number of non-empty equal items)-1 */
1015
+ continue;
1016
+ } else {
1017
+ /* pINChI_Aux eq. info is either different or trivial. Output pINChI_Aux_Prev anyway */
1018
+ if ( bNext ++ ) {
1019
+ tot_len += MakeDelim( sCompDelim, pStr + tot_len, nStrLen-tot_len, bOverflow);
1020
+ }
1021
+ if ( pINChI_Aux_Prev && pINChI_Aux_Prev->nNumberOfAtoms ) {
1022
+ if ( bHasEquString( pINChI_Aux_Prev->nConstitEquNumbers, pINChI_Aux_Prev->nNumberOfAtoms) ) {
1023
+ /* pINChI_Aux_Prev exists and has equivalence info */
1024
+ tot_len += MakeMult( mult+1, "*", pStr + tot_len, nStrLen-tot_len, 0, bOverflow);
1025
+ tot_len += MakeEquString( pINChI_Aux_Prev->nConstitEquNumbers, pINChI_Aux_Prev->nNumberOfAtoms, 0,
1026
+ pStr + tot_len, nStrLen-tot_len, TAUT_MODE, bOverflow);
1027
+ } else {
1028
+ ; /* pINChI_Aux_Prev exists and has only trivial equivalence info */
1029
+ }
1030
+ } else
1031
+ if ( bSecondNonTautPass && pINChI_Aux_Taut_Prev && pINChI_Aux_Taut_Prev->nNumberOfAtoms ) {
1032
+ if ( bHasEquString( pINChI_Aux_Taut_Prev->nConstitEquNumbers, pINChI_Aux_Taut_Prev->nNumberOfAtoms) ) {
1033
+ /* since pINChI_Aux_Prev does not exist, pINChI_Aux_Taut_Prev is non-tautomeric */
1034
+ /* and it has non-trivial equivalence info. This info has already been printed in the main section */
1035
+ /*
1036
+ tot_len += MakeDelim( sIdenticalValues, pStr + tot_len, nStrLen-tot_len, bOverflow);
1037
+ */
1038
+ } else {
1039
+ ; /* pINChI_Aux_Taut_Prev exists and has only trivial equivalence info */
1040
+ }
1041
+ }
1042
+ #if( bRELEASE_VERSION != 1 && defined(_DEBUG) )
1043
+ else {
1044
+ int stop = 1; /* <BRKPT> */
1045
+ }
1046
+ #endif
1047
+ }
1048
+ pINChI_Aux_Prev = pINChI_Aux;
1049
+ pINChI_Aux_Taut_Prev = pINChI_Aux_Taut;
1050
+ mult = 0; /* we do not know whether the item is empty */
1051
+ }
1052
+ }
1053
+ return tot_len;
1054
+ }
1055
+ /******************************************************************************************/
1056
+ int str_AuxInvSp3(INCHI_SORT *pINChISort, INCHI_SORT *pINChISort2, char *pStr, int nStrLen, int tot_len,
1057
+ int *bOverflow, int bOutType, int TAUT_MODE, int num_components,
1058
+ int bSecondNonTautPass, int bOmitRepetitions, int bUseMulipliers)
1059
+ {
1060
+ int i, ii, ii2;
1061
+ INCHI_SORT *is, *is2;
1062
+ INChI *pINChI, *pINChI_Prev, *pINChI_Taut, *pINChI_Taut_Prev;
1063
+ INChI_Stereo *Stereo, *Stereo_Prev, *Stereo_Taut, *Stereo_Taut_Prev;
1064
+ int mult, eq2prev, eq2taut, eq2tautPrev, bNext;
1065
+ const char *pPrevEquStr, *pCurrEquStr;
1066
+ int multPrevEquStr;
1067
+ /***************
1068
+ inverted sp3
1069
+ ****************/
1070
+ pINChI_Taut = NULL;
1071
+ pINChI_Prev = NULL;
1072
+ pINChI_Taut_Prev = NULL;
1073
+ mult = 0;
1074
+ bNext = 0;
1075
+ is2 = bSecondNonTautPass? pINChISort2 : NULL;
1076
+ eq2taut = 0; /* may be non-zero if another layer of the current component = current layer */
1077
+ eq2tautPrev = 1; /* pINChI_Prev (previous pINChI) does not exist */
1078
+ pPrevEquStr = NULL; /*, *pCurrEquStr;*/
1079
+ multPrevEquStr = 0;
1080
+ for ( i = 0, is = pINChISort; i <= num_components; i ++, is ++, (bSecondNonTautPass? is2++ : 0) ) {
1081
+ /* 1st (taut) pass: bOutType=OUT_TN ; 2nd (non-taut pass) bOutType=OUT_NT */
1082
+ pINChI = (i < num_components && 0 <= (ii=GET_II(bOutType,is)))? is->pINChI[ii] : NULL;
1083
+ /*================ compare sp2 to previous =====================*/
1084
+ if ( bSecondNonTautPass ) {
1085
+ /* component that was output on the 1st pass */
1086
+ pINChI_Taut = ( i < num_components && 0 <= (ii2=GET_II(OUT_T1,is2)))? is2->pINChI[ii2] : NULL;
1087
+ }
1088
+ eq2taut = 0;
1089
+ /*========= if bSecondNonTautPass then compare iso non-taut stereo to other stereo ========*/
1090
+ if ( bSecondNonTautPass && bOmitRepetitions ) {
1091
+ /* compare non-tautomeric inverted to:
1092
+ * a) tautomeric inverted
1093
+ * b) Inverted(tautomeric)
1094
+ * c) Inverted(non-tautomeric)
1095
+ */
1096
+ /* a) compare non-tautomeric inverted to tautomeric inverted */
1097
+ if ( !eq2taut ) {
1098
+ eq2taut = pINChI && pINChI_Taut &&
1099
+ /* non-taut inverted */ /* taut invertedc */
1100
+ (Stereo = pINChI->Stereo) && (Stereo_Taut = pINChI_Taut->Stereo) &&
1101
+ Eql_INChI_Stereo( Stereo, EQL_SP3_INV, Stereo_Taut, EQL_SP3_INV, 0 );
1102
+ /* stereo-inv non-taut = taut (stereo-inv) */
1103
+ eq2taut = eq2taut? (iiSTEREO_INV | iitNONTAUT ) : 0;
1104
+ }
1105
+ /* b) compare non-tautomeric inverted to Inverted(tautomeric stereo) */
1106
+ if ( !eq2taut ) {
1107
+ eq2taut = pINChI && pINChI_Taut &&
1108
+ (Stereo = pINChI->Stereo) && (Stereo_Taut = pINChI_Taut->Stereo) &&
1109
+ Eql_INChI_Stereo( Stereo, EQL_SP3_INV, Stereo_Taut, EQL_SP3, 0 );
1110
+ /* stereo-inv non-taut = Inv(taut stereo) */
1111
+ eq2taut = eq2taut? (iiSTEREO_INV | iitNONTAUT | iiEq2INV) : 0;
1112
+ }
1113
+ /* c) compare non-tautomeric inverted to Inverted(non-tautomeric stereo) */
1114
+ if ( !eq2taut ) {
1115
+ eq2taut = pINChI &&
1116
+ (Stereo = pINChI->Stereo) &&
1117
+ Eql_INChI_Stereo( Stereo, EQL_SP3_INV, Stereo, EQL_SP3, 0 );
1118
+ /* stereo-inv non-taut = Inv(non-taut stereo) */
1119
+ eq2taut = eq2taut? (iiSTEREO_INV | iitNONTAUT | iiEq2INV | iiEq2NONTAUT) : 0;
1120
+ }
1121
+ } else
1122
+ /*========= if not bSecondNonTautPass then compare inv taut stereo to various taut stereo ========*/
1123
+ if ( !bSecondNonTautPass && bOmitRepetitions ) {
1124
+ /* compare tautomeric inverted to Invetred(tautomeric) */
1125
+ if ( !eq2taut ) {
1126
+ eq2taut = pINChI &&
1127
+ (Stereo = pINChI->Stereo) &&
1128
+ Eql_INChI_Stereo( Stereo, EQL_SP3_INV, Stereo, EQL_SP3, 0 );
1129
+ /* stereo isotopic taut = taut (stereo) */
1130
+ eq2taut = eq2taut? (iiSTEREO_INV | iiEq2INV ) : 0;
1131
+ }
1132
+ }
1133
+ if ( eq2taut ) {
1134
+ /* we may be here only in case of the current layer found equal in another layer the same component */
1135
+ if ( pINChI_Prev && pINChI_Prev->nNumberOfAtoms ) {
1136
+ /* previous component exists; output it before output the current component */
1137
+ if ( bNext ++ ) {
1138
+ tot_len += MakeDelim( sCompDelim, pStr + tot_len, nStrLen-tot_len, bOverflow);
1139
+ }
1140
+ if ( (Stereo_Prev = pINChI_Prev->Stereo) && Stereo_Prev->nNumberOfStereoCenters > 0 ) {
1141
+ tot_len += MakeMult( mult+1, "*", pStr + tot_len, nStrLen-tot_len, 0, bOverflow);
1142
+
1143
+ tot_len += MakeStereoString( Stereo_Prev->nNumber, NULL, Stereo_Prev->t_parityInv,
1144
+ 0, Stereo_Prev->nNumberOfStereoCenters,
1145
+ pStr + tot_len, nStrLen-tot_len, TAUT_MODE, bOverflow);
1146
+ }
1147
+ } else
1148
+ if ( pINChI_Taut_Prev && pINChI_Taut_Prev->nNumberOfAtoms ) {
1149
+ /* previous non-taut component exists only in taut list */
1150
+ if ( bNext ++ ) {
1151
+ tot_len += MakeDelim( sCompDelim, pStr + tot_len, nStrLen-tot_len, bOverflow);
1152
+ }
1153
+ /* do not output stereo of non-tautomeric in non-taut layer: it has been output in the main layer */
1154
+ }
1155
+ /* we have found another (previously printed) layer of the current component equal to this layer */
1156
+ /* output this (current) equivalence mark = EquString(eq2taut) */
1157
+ pCurrEquStr = EquString(eq2taut);
1158
+ if ( multPrevEquStr && pPrevEquStr ) {
1159
+ if ( pCurrEquStr && !strcmp(pCurrEquStr, pPrevEquStr) ) {
1160
+ multPrevEquStr ++;
1161
+ } else {
1162
+ /* new EqStr is different; output it */
1163
+ if ( bNext ++ ) {
1164
+ tot_len += MakeDelim( sCompDelim, pStr + tot_len, nStrLen-tot_len, bOverflow);
1165
+ }
1166
+ tot_len += MakeEqStr( pPrevEquStr, multPrevEquStr, pStr + tot_len, nStrLen-tot_len, bOverflow);
1167
+ pPrevEquStr = pCurrEquStr;
1168
+ multPrevEquStr = 1;
1169
+ }
1170
+ } else {
1171
+ pPrevEquStr = pCurrEquStr;
1172
+ multPrevEquStr = 1;
1173
+ }
1174
+ pINChI_Prev = NULL; /* pINChI_Prev sp2 does not exist since */
1175
+ pINChI_Taut_Prev = NULL; /* pINChI has just been printed */
1176
+ mult = 0;
1177
+ eq2tautPrev = 1; /* pINChI_Prev and pINChI_Taut_Prev have already been output */
1178
+ } else
1179
+ if ( eq2tautPrev ) {
1180
+ /* at this point pINChI_Prev does not exist; however, pINChI */
1181
+ /*might have been discovered and it is different from pINChI_Taut */
1182
+ if ( multPrevEquStr && pPrevEquStr ) {
1183
+ /* new EqStr is different; output it */
1184
+ if ( bNext ++ ) {
1185
+ tot_len += MakeDelim( sCompDelim, pStr + tot_len, nStrLen-tot_len, bOverflow);
1186
+ }
1187
+ tot_len += MakeEqStr( pPrevEquStr, multPrevEquStr, pStr + tot_len, nStrLen-tot_len, bOverflow);
1188
+ pPrevEquStr = NULL;
1189
+ multPrevEquStr = 0;
1190
+ }
1191
+ eq2tautPrev = 0;
1192
+ pINChI_Prev = pINChI;
1193
+ pINChI_Taut_Prev = pINChI_Taut;
1194
+ mult = 0;
1195
+ } else {
1196
+ /* current layer is different from previously printed layers of the current component */
1197
+ /* compare the current layer to this layer of the previous component: */
1198
+ /* check whether pINChI and pINChI_Prev have non-zero identical stereo sp2 */
1199
+ /*================ compare iso sp3 to previous =====================*/
1200
+ eq2prev =bUseMulipliers &&
1201
+ pINChI && pINChI_Prev &&
1202
+ /* do both have stereo? */
1203
+ (Stereo = pINChI->Stereo) && (Stereo_Prev = pINChI_Prev->Stereo) &&
1204
+ /* is their inverted stereo same? */
1205
+ Eql_INChI_Stereo( Stereo, EQL_SP3_INV, Stereo_Prev, EQL_SP3_INV, 0 );
1206
+ if ( eq2prev ) {
1207
+ mult ++; /* mult = (number of non-empty equal items)-1 */
1208
+ continue;
1209
+ } else {
1210
+ if ( bNext ++ ) {
1211
+ tot_len += MakeDelim( sCompDelim, pStr + tot_len, nStrLen-tot_len, bOverflow);
1212
+ }
1213
+ if ( pINChI_Prev && pINChI_Prev->nNumberOfAtoms ) {
1214
+ if ( (Stereo_Prev = pINChI_Prev->Stereo) &&
1215
+ Stereo_Prev->nNumberOfStereoCenters > 0 && Stereo_Prev->nCompInv2Abs ) {
1216
+ tot_len += MakeMult( mult+1, "*", pStr + tot_len, nStrLen-tot_len, 0, bOverflow);
1217
+
1218
+ tot_len += MakeStereoString( Stereo_Prev->nNumberInv, NULL, Stereo_Prev->t_parityInv,
1219
+ 0, Stereo_Prev->nNumberOfStereoCenters,
1220
+ pStr + tot_len, nStrLen-tot_len, TAUT_MODE, bOverflow);
1221
+ }
1222
+ /* else sp3 info is not present in pINChI_Prev */
1223
+ } else
1224
+ /* do not print pINChI_Prev because it either do not exist of have already been printed */
1225
+ if ( bSecondNonTautPass && pINChI_Taut_Prev && pINChI_Taut_Prev->nNumberOfAtoms ) {
1226
+ if ( (Stereo_Taut_Prev = pINChI_Taut_Prev->Stereo) &&
1227
+ Stereo_Taut_Prev->nNumberOfStereoCenters > 0 && Stereo_Taut_Prev->nCompInv2Abs ) {
1228
+ /* since pINChI_Prev does not exist, pINChI_Taut_Prev is non-tautomeric */
1229
+ /* and it has non-trivial inv sp3 info. It has already been printed in the main section */
1230
+ /*
1231
+ tot_len += MakeDelim( sIdenticalValues, pStr + tot_len, nStrLen-tot_len, bOverflow);
1232
+ */
1233
+ ;/* pINChI_Taut_Prev sp3 info was output in the main stereo section */
1234
+ } else {
1235
+ ; /* pINChI_Taut_Prev exists and has not sp3 info */
1236
+ }
1237
+ }
1238
+ #if( bRELEASE_VERSION != 1 && defined(_DEBUG) )
1239
+ else {
1240
+ int stop = 1; /* <BRKPT> */
1241
+ }
1242
+ #endif
1243
+ }
1244
+ pINChI_Prev = pINChI;
1245
+ mult = 0; /* we do not know whether the item is empty */
1246
+ }
1247
+ }
1248
+ return tot_len;
1249
+ }
1250
+ /***************************************************************************/
1251
+ int str_AuxInvSp3Numb(INCHI_SORT *pINChISort, INCHI_SORT *pINChISort2, char *pStr, int nStrLen, int tot_len,
1252
+ int *bOverflow, int bOutType, int TAUT_MODE, int num_components,
1253
+ int bSecondNonTautPass, int bOmitRepetitions)
1254
+ {
1255
+ int i, ii, ii2;
1256
+ INCHI_SORT *is, *is2;
1257
+ INChI *pINChI, *pINChI_Taut;
1258
+ INChI_Aux *pINChI_Aux, *pINChI_Aux_Prev, *pINChI_Aux_Taut;
1259
+ INChI_Stereo *Stereo, *Stereo_Taut;
1260
+ int eq2taut, bNext;
1261
+ const char *pPrevEquStr, *pCurrEquStr;
1262
+ int multPrevEquStr;
1263
+ /**************************************************
1264
+ * specificity of numbering: there is no previous *
1265
+ * component because no repetition is possible *
1266
+ **************************************************/
1267
+ pINChI = NULL;
1268
+ pINChI_Taut = NULL;
1269
+ pINChI_Aux = NULL;
1270
+ pINChI_Aux_Taut = NULL;
1271
+ pINChI_Aux_Prev = NULL;
1272
+ bNext = 0;
1273
+ is2 = bSecondNonTautPass? pINChISort2 : NULL;
1274
+ eq2taut = 0; /* may be non-zero if another layer of the current component = current layer */
1275
+ pPrevEquStr = NULL; /*, *pCurrEquStr;*/
1276
+ multPrevEquStr = 0;
1277
+ for ( i = 0, is = pINChISort; i < num_components; i ++, is ++, (bSecondNonTautPass? is2++ : 0) ) {
1278
+ /* 1st (taut) pass: bOutType=OUT_TN ; 2nd (non-taut pass) bOutType=OUT_NT */
1279
+ pINChI = (0 <= (ii=GET_II(bOutType,is)))? is->pINChI[ii] : NULL;
1280
+ pINChI_Aux = pINChI? is->pINChI_Aux[ii] : NULL;
1281
+ /*================ to compare to previously printed =====================*/
1282
+ if ( bSecondNonTautPass ) {
1283
+ /* component that was printed on the 1st pass */
1284
+ pINChI_Taut = (0 <= (ii2=GET_II(OUT_T1,is)))? is->pINChI[ii2] : NULL;
1285
+ pINChI_Aux_Taut = pINChI_Taut? is->pINChI_Aux[ii2] : NULL;
1286
+ }
1287
+
1288
+ eq2taut = 0;
1289
+ /*========= if bSecondNonTautPass then compare inv non-taut stereo to other stereo ========*/
1290
+ if ( bSecondNonTautPass && bOmitRepetitions &&
1291
+ pINChI && (Stereo = pINChI->Stereo) && Stereo->nCompInv2Abs ) {
1292
+ /* compare non-tautomeric inverted stereo numbering to:
1293
+ * a) tautomeric numbering
1294
+ * b) non-tautomeric numbering
1295
+ * c) tautomeric inverted stereo numbering
1296
+ */
1297
+ /* a) compare non-tautomeric inverted stereo numbering to tautomeric numbering */
1298
+ if ( !eq2taut ) {
1299
+ eq2taut = pINChI_Taut &&
1300
+ Eql_INChI_Aux_Num( pINChI_Aux, EQL_NUM_INV, pINChI_Aux_Taut, EQL_NUM );
1301
+ /* stereo-inv numbering non-taut = taut numbering */
1302
+ eq2taut = eq2taut? (iiSTEREO_INV | iiNUMB | iitNONTAUT ) : 0;
1303
+ }
1304
+ /* b) compare non-tautomeric inverted stereo numbering to non-tautomeric numbering */
1305
+ if ( !eq2taut ) {
1306
+ eq2taut =
1307
+ Eql_INChI_Aux_Num( pINChI_Aux, EQL_NUM_INV, pINChI_Aux, EQL_NUM );
1308
+ /* stereo-inv numb. non-taut = non-taut numbering */
1309
+ eq2taut = eq2taut? (iiSTEREO_INV | iiNUMB | iitNONTAUT | iiEq2NONTAUT ) : 0;
1310
+ }
1311
+ /* c) compare non-tautomeric inverted stereo numbering to tautomeric inverted stereo numbering */
1312
+ if ( !eq2taut ) {
1313
+ eq2taut = pINChI_Taut &&
1314
+ (Stereo_Taut = pINChI_Taut->Stereo) && Stereo_Taut->nCompInv2Abs &&
1315
+ Eql_INChI_Aux_Num( pINChI_Aux, EQL_NUM_INV, pINChI_Aux_Taut, EQL_NUM_INV );
1316
+ /* stereo-inv numb. non-taut = taut inv stereo numbering */
1317
+ eq2taut = eq2taut? (iiSTEREO_INV | iiNUMB | iitNONTAUT | iiEq2INV ) : 0;
1318
+ }
1319
+ } else
1320
+ /*========= if not bSecondNonTautPass then compare inv taut stereo numb to taut numb ========*/
1321
+ if ( !bSecondNonTautPass && bOmitRepetitions &&
1322
+ pINChI && (Stereo = pINChI->Stereo) && Stereo->nCompInv2Abs ) {
1323
+ /* compare tautomeric inverted stereo numbering to tautomeric numbering */
1324
+ if ( !eq2taut ) {
1325
+ eq2taut =
1326
+ Eql_INChI_Aux_Num( pINChI_Aux, EQL_NUM_INV, pINChI_Aux, EQL_NUM );
1327
+ /* stereo-inv numbering (taut) = taut numbering */
1328
+ eq2taut = eq2taut? (iiSTEREO_INV | iiNUMB ) : 0;
1329
+ }
1330
+ }
1331
+ if ( eq2taut ) {
1332
+ /* we have found another (previously printed) layer of the current component equal to this layer */
1333
+ /* output this (current) equivalence mark = EquString(eq2taut) */
1334
+ pCurrEquStr = EquString(eq2taut);
1335
+ if ( multPrevEquStr && pPrevEquStr ) {
1336
+ if ( pCurrEquStr && !strcmp(pCurrEquStr, pPrevEquStr) ) {
1337
+ multPrevEquStr ++;
1338
+ } else {
1339
+ /* new EqStr is different; output it */
1340
+ if ( bNext ++ ) {
1341
+ tot_len += MakeDelim( sCompDelim, pStr + tot_len, nStrLen-tot_len, bOverflow);
1342
+ }
1343
+ tot_len += MakeEqStr( pPrevEquStr, multPrevEquStr, pStr + tot_len, nStrLen-tot_len, bOverflow);
1344
+ pPrevEquStr = pCurrEquStr;
1345
+ multPrevEquStr = 1;
1346
+ }
1347
+ } else {
1348
+ pPrevEquStr = pCurrEquStr;
1349
+ multPrevEquStr = 1;
1350
+ }
1351
+ } else {
1352
+ /* current layer is different from previously printed layers of the current component */
1353
+ if ( multPrevEquStr && pPrevEquStr ) {
1354
+ /* new EqStr is different; output it */
1355
+ if ( bNext ++ ) {
1356
+ tot_len += MakeDelim( sCompDelim, pStr + tot_len, nStrLen-tot_len, bOverflow);
1357
+ }
1358
+ tot_len += MakeEqStr( pPrevEquStr, multPrevEquStr, pStr + tot_len, nStrLen-tot_len, bOverflow);
1359
+ pPrevEquStr = NULL;
1360
+ multPrevEquStr = 0;
1361
+ }
1362
+ if ( bNext ++ ) {
1363
+ tot_len += MakeDelim( sCompDelim, pStr + tot_len, nStrLen-tot_len, bOverflow);
1364
+ }
1365
+ if ( pINChI && pINChI_Aux && pINChI_Aux->nNumberOfAtoms &&
1366
+ (Stereo = pINChI->Stereo) && Stereo->nNumberOfStereoCenters &&
1367
+ Stereo->nCompInv2Abs && pINChI_Aux->nOrigAtNosInCanonOrdInv ) {
1368
+ tot_len += MakeCtString( pINChI_Aux->nOrigAtNosInCanonOrdInv,
1369
+ pINChI_Aux->nNumberOfAtoms, 0, NULL, 0,
1370
+ pStr + tot_len, nStrLen-tot_len, TAUT_MODE, bOverflow);
1371
+ }
1372
+ /* else inv stereo info is not present in pINChI */
1373
+ }
1374
+ }
1375
+ if ( multPrevEquStr && pPrevEquStr ) {
1376
+ /* the new EqStr of the last item has not been printed; output it now */
1377
+ if ( bNext ++ ) {
1378
+ tot_len += MakeDelim( sCompDelim, pStr + tot_len, nStrLen-tot_len, bOverflow);
1379
+ }
1380
+ tot_len += MakeEqStr( pPrevEquStr, multPrevEquStr, pStr + tot_len, nStrLen-tot_len, bOverflow);
1381
+ pPrevEquStr = NULL;
1382
+ multPrevEquStr = 0;
1383
+ }
1384
+ return tot_len;
1385
+ }
1386
+ /***************************************************************************/
1387
+ int str_AuxIsoNumb(INCHI_SORT *pINChISort, INCHI_SORT *pINChISort2, char *pStr, int nStrLen, int tot_len,
1388
+ int *bOverflow, int bOutType, int TAUT_MODE, int num_components,
1389
+ int bSecondNonTautPass, int bOmitRepetitions)
1390
+ {
1391
+ int i, ii, ii2;
1392
+ INCHI_SORT *is, *is2;
1393
+ INChI *pINChI, *pINChI_Taut;
1394
+ INChI_Aux *pINChI_Aux, *pINChI_Aux_Prev, *pINChI_Aux_Taut;
1395
+ int eq2taut, bNext;
1396
+ const char *pPrevEquStr, *pCurrEquStr;
1397
+ int multPrevEquStr;
1398
+ /**************************************************
1399
+ * specificity of numbering: there is no previous *
1400
+ * component because no repetition is possible *
1401
+ **************************************************/
1402
+ pINChI = NULL; /* not used here, for debug only */
1403
+ pINChI_Taut = NULL; /* not used here, for debug only */
1404
+ pINChI_Aux = NULL;
1405
+ pINChI_Aux_Taut = NULL;
1406
+ pINChI_Aux_Prev = NULL;
1407
+ bNext = 0;
1408
+ is2 = bSecondNonTautPass? pINChISort2 : NULL;
1409
+ eq2taut = 0; /* may be non-zero if another layer of the current component = current layer */
1410
+ pPrevEquStr = NULL; /*, *pCurrEquStr;*/
1411
+ multPrevEquStr = 0;
1412
+ for ( i = 0, is = pINChISort; i < num_components; i ++, is ++, (bSecondNonTautPass? is2++ : 0) ) {
1413
+ /* 1st (taut) pass: bOutType=OUT_TN ; 2nd (non-taut pass) bOutType=OUT_NT */
1414
+ pINChI_Aux = (i < num_components && 0 <= (ii=GET_II(bOutType,is)))? is->pINChI_Aux[ii] : NULL;
1415
+ /*================ to compare to previously printed =====================*/
1416
+ if ( bSecondNonTautPass ) {
1417
+ pINChI_Aux_Taut = (0 <= (ii2=GET_II(OUT_T1,is)))? is->pINChI_Aux[ii2] : NULL;
1418
+ }
1419
+ eq2taut = 0;
1420
+ /*========= if bSecondNonTautPass then compare iso non-taut numb to other numb ========*/
1421
+ if ( bSecondNonTautPass && bOmitRepetitions && pINChI_Aux && pINChI_Aux->bIsIsotopic ) {
1422
+ /* compare non-tautomeric isotopic numbering to:
1423
+ * a) tautomeric numbering
1424
+ * b) non-tautomeric numbering
1425
+ * c) tautomeric isotopic numbering
1426
+ */
1427
+ /* a) compare non-tautomeric isotopic numbering to tautomeric numbering */
1428
+ if ( !eq2taut ) {
1429
+ eq2taut = Eql_INChI_Aux_Num( pINChI_Aux, EQL_NUM_ISO, pINChI_Aux_Taut, EQL_NUM );
1430
+ /* numbering non-taut isotopic = taut numbering */
1431
+ eq2taut = eq2taut? ( iiNUMB | iitNONTAUT | iitISO ) : 0;
1432
+ }
1433
+ /* b) compare non-tautomeric isotopic numbering to non-tautomeric numbering */
1434
+ if ( !eq2taut ) {
1435
+ eq2taut = Eql_INChI_Aux_Num( pINChI_Aux, EQL_NUM_ISO, pINChI_Aux, EQL_NUM );
1436
+ /* numbering non-taut isotopic = non-taut numbering */
1437
+ eq2taut = eq2taut? ( iiNUMB | iitNONTAUT | iitISO | iiEq2NONTAUT ) : 0;
1438
+ }
1439
+ /* c) compare non-tautomeric isotopic numbering to tautomeric isotopic numbering */
1440
+ if ( !eq2taut ) {
1441
+ eq2taut = Eql_INChI_Aux_Num( pINChI_Aux, EQL_NUM_ISO, pINChI_Aux_Taut, EQL_NUM_ISO );
1442
+ /* numbering non-taut isotopic = taut isotopic numbering */
1443
+ eq2taut = eq2taut? ( iiNUMB | iitNONTAUT | iitISO | iiEq2ISO ) : 0;
1444
+ }
1445
+ } else
1446
+ /*========= if not bSecondNonTautPass then compare inv taut stereo numb to taut numb ========*/
1447
+ if ( !bSecondNonTautPass && bOmitRepetitions && pINChI_Aux && pINChI_Aux->bIsIsotopic ) {
1448
+ /* compare tautomeric isotopic numbering to tautomeric non-isotopic numbering */
1449
+ if ( !eq2taut ) {
1450
+ eq2taut = Eql_INChI_Aux_Num( pINChI_Aux, EQL_NUM_ISO, pINChI_Aux, EQL_NUM_ISO );
1451
+ /* stereo-inv numbering (taut) = taut numbering */
1452
+ eq2taut = eq2taut? (iiSTEREO_INV | iiNUMB ) : 0;
1453
+ }
1454
+ }
1455
+ if ( eq2taut ) {
1456
+ /* we have found another (previously printed) layer of the current component equal to this layer */
1457
+ /* output this (current) equivalence mark = EquString(eq2taut) */
1458
+ pCurrEquStr = EquString(eq2taut);
1459
+ if ( multPrevEquStr && pPrevEquStr ) {
1460
+ if ( pCurrEquStr && !strcmp(pCurrEquStr, pPrevEquStr) ) {
1461
+ multPrevEquStr ++;
1462
+ } else {
1463
+ /* new EqStr is different; output it */
1464
+ if ( bNext ++ ) {
1465
+ tot_len += MakeDelim( sCompDelim, pStr + tot_len, nStrLen-tot_len, bOverflow);
1466
+ }
1467
+ tot_len += MakeEqStr( pPrevEquStr, multPrevEquStr, pStr + tot_len, nStrLen-tot_len, bOverflow);
1468
+ pPrevEquStr = pCurrEquStr;
1469
+ multPrevEquStr = 1;
1470
+ }
1471
+ } else {
1472
+ pPrevEquStr = pCurrEquStr;
1473
+ multPrevEquStr = 1;
1474
+ }
1475
+ } else {
1476
+ /* current layer is different from previously printed layers of the current component */
1477
+ if ( multPrevEquStr && pPrevEquStr ) {
1478
+ /* new EqStr is different; output it */
1479
+ if ( bNext ++ ) {
1480
+ tot_len += MakeDelim( sCompDelim, pStr + tot_len, nStrLen-tot_len, bOverflow);
1481
+ }
1482
+ tot_len += MakeEqStr( pPrevEquStr, multPrevEquStr, pStr + tot_len, nStrLen-tot_len, bOverflow);
1483
+ pPrevEquStr = NULL;
1484
+ multPrevEquStr = 0;
1485
+ }
1486
+ if ( bNext ++ ) {
1487
+ tot_len += MakeDelim( sCompDelim, pStr + tot_len, nStrLen-tot_len, bOverflow);
1488
+ }
1489
+ if ( pINChI_Aux && pINChI_Aux->nNumberOfAtoms && pINChI_Aux->bIsIsotopic &&
1490
+ pINChI_Aux->nIsotopicOrigAtNosInCanonOrd ) {
1491
+ tot_len += MakeCtString( pINChI_Aux->nIsotopicOrigAtNosInCanonOrd,
1492
+ pINChI_Aux->nNumberOfAtoms, 0, NULL, 0,
1493
+ pStr + tot_len, nStrLen-tot_len, TAUT_MODE, bOverflow);
1494
+ }
1495
+ /* else isotopic numbering is not present in pINChI */
1496
+ }
1497
+ }
1498
+ if ( multPrevEquStr && pPrevEquStr ) {
1499
+ /* the new EqStr of the last item has not been printed; output it now */
1500
+ if ( bNext ++ ) {
1501
+ tot_len += MakeDelim( sCompDelim, pStr + tot_len, nStrLen-tot_len, bOverflow);
1502
+ }
1503
+ tot_len += MakeEqStr( pPrevEquStr, multPrevEquStr, pStr + tot_len, nStrLen-tot_len, bOverflow);
1504
+ pPrevEquStr = NULL;
1505
+ multPrevEquStr = 0;
1506
+ }
1507
+ return tot_len;
1508
+ }
1509
+ /***************************************************************************/
1510
+ int str_AuxIsoEqu(INCHI_SORT *pINChISort, INCHI_SORT *pINChISort2, char *pStr, int nStrLen, int tot_len,
1511
+ int *bOverflow, int bOutType, int TAUT_MODE, int num_components,
1512
+ int bSecondNonTautPass, int bOmitRepetitions, int bUseMulipliers)
1513
+ {
1514
+ int i, ii, ii2;
1515
+ INCHI_SORT *is, *is2;
1516
+ INChI_Aux *pINChI_Aux, *pINChI_Aux_Prev, *pINChI_Aux_Taut, *pINChI_Aux_Taut_Prev;
1517
+ int mult, eq2prev, eq2taut, eq2tautPrev, bNext;
1518
+ const char *pPrevEquStr, *pCurrEquStr;
1519
+ int multPrevEquStr;
1520
+ pINChI_Aux = NULL;
1521
+ pINChI_Aux_Prev = NULL;
1522
+ pINChI_Aux_Taut = NULL;
1523
+ pINChI_Aux_Taut_Prev = NULL;
1524
+ mult = 0;
1525
+ bNext = 0;
1526
+ is2 = bSecondNonTautPass? pINChISort2 : NULL;
1527
+ eq2taut = 0; /* may be non-zero only on the 2nd (non-taut) pass */
1528
+ eq2tautPrev = 1; /* pINChI_Aux_Prev (previous pINChI_Aux) does not exist */
1529
+ pPrevEquStr = NULL; /*, *pCurrEquStr;*/
1530
+ multPrevEquStr = 0;
1531
+ for ( i = 0, is = pINChISort; i <= num_components; i ++, is ++, (bSecondNonTautPass? is2++ : 0) ) {
1532
+ /* 1st (taut) pass: bOutType=OUT_TN ; 2nd (non-taut pass) bOutType=OUT_NT */
1533
+ pINChI_Aux = (i < num_components && 0 <= (ii=GET_II(bOutType,is)))? is->pINChI_Aux[ii] : NULL;
1534
+ if ( bSecondNonTautPass ) {
1535
+ /* component that was output on the 1st pass */
1536
+ pINChI_Aux_Taut = ( i < num_components && 0 <= (ii2=GET_II(OUT_T1,is2)))? is2->pINChI_Aux[ii2] : NULL;
1537
+ }
1538
+ /*================ compare iso non-taut equivalence info to non-iso taut ========*/
1539
+ eq2taut = 0;
1540
+ if ( bSecondNonTautPass && bOmitRepetitions && pINChI_Aux && pINChI_Aux->bIsIsotopic ) {
1541
+ /**************************************************
1542
+ * compare isotopic non-tautomeric equivalence to:
1543
+ * a) tautomeric
1544
+ * b) non-tautomeric
1545
+ * c) isotopic tautomeric
1546
+ */
1547
+ if ( !eq2taut ) {
1548
+ /* compare isotopic non-tautomeric equivalence to tautomeric */
1549
+ eq2taut = Eql_INChI_Aux_Equ( pINChI_Aux, EQL_EQU_ISO, pINChI_Aux_Taut, EQL_EQU );
1550
+ /* equ non-taut isotopic = tautomeric*/
1551
+ eq2taut = eq2taut? (iiEQU | iitNONTAUT | iitISO) : 0;
1552
+ }
1553
+ if ( !eq2taut ) {
1554
+ /* compare isotopic non-tautomeric equivalence to non-tautomeric */
1555
+ eq2taut = Eql_INChI_Aux_Equ( pINChI_Aux, EQL_EQU_ISO, pINChI_Aux, EQL_EQU );
1556
+ /* equ non-taut isotopic = non-tautomeric*/
1557
+ eq2taut = eq2taut? (iiEQU | iitNONTAUT | iitISO | iiEq2NONTAUT) : 0;
1558
+ }
1559
+ if ( !eq2taut ) {
1560
+ /* compare isotopic non-tautomeric equivalence to isotopic tautomeric */
1561
+ eq2taut = Eql_INChI_Aux_Equ( pINChI_Aux, EQL_EQU_ISO, pINChI_Aux_Taut, EQL_EQU_ISO );
1562
+ /* equ non-taut isotopic = isotopic tautomeric*/
1563
+ eq2taut = eq2taut? (iiEQU | iitNONTAUT | iitISO | iiEq2ISO) : 0;
1564
+ }
1565
+ } else
1566
+ if ( !bSecondNonTautPass && bOmitRepetitions && pINChI_Aux && pINChI_Aux->bIsIsotopic ) {
1567
+ /**************************************************
1568
+ * compare isotopic tautomeric equivalence to:
1569
+ * a) non-isotopic tautomeric
1570
+ */
1571
+ if ( !eq2taut ) {
1572
+ /* compare isotopic tautomeric equivalence to tautomeric */
1573
+ eq2taut = Eql_INChI_Aux_Equ( pINChI_Aux, EQL_EQU_ISO, pINChI_Aux, EQL_EQU );
1574
+ /* equ taut-isotopic = tautomeric*/
1575
+ eq2taut = eq2taut? (iiEQU | iitISO) : 0;
1576
+ }
1577
+ }
1578
+ if ( eq2taut ) {
1579
+ /* we may be here only in case of the second (non-taut) pass */
1580
+ /* current non-taut equivalence has been found to be same as tautomeric */
1581
+ if ( pINChI_Aux_Prev && pINChI_Aux_Prev->nNumberOfAtoms ) {
1582
+ /* previous component exists */
1583
+ if ( bNext ++ ) {
1584
+ tot_len += MakeDelim( sCompDelim, pStr + tot_len, nStrLen-tot_len, bOverflow);
1585
+ }
1586
+ if ( bHasEquString( pINChI_Aux_Prev->nConstitEquIsotopicNumbers, pINChI_Aux_Prev->nNumberOfAtoms) ) {
1587
+ /* output previous component(s) equivalence since it was found to be non-trivial */
1588
+ tot_len += MakeMult( mult+1, "*", pStr + tot_len, nStrLen-tot_len, 0, bOverflow);
1589
+ tot_len += MakeEquString( pINChI_Aux_Prev->nConstitEquIsotopicNumbers, pINChI_Aux_Prev->nNumberOfAtoms, 0,
1590
+ pStr + tot_len, nStrLen-tot_len, TAUT_MODE, bOverflow);
1591
+ } else {
1592
+ ; /* pINChI_Aux_Prev exists and has only trivial equivalence info */
1593
+ }
1594
+ } else
1595
+ if ( pINChI_Aux_Taut_Prev && pINChI_Aux_Taut_Prev->nNumberOfAtoms ) {
1596
+ /* previous non-taut component exists only in taut list */
1597
+ if ( bNext ++ ) {
1598
+ tot_len += MakeDelim( sCompDelim, pStr + tot_len, nStrLen-tot_len, bOverflow);
1599
+ }
1600
+ }
1601
+ /* we have found pINChI_Aux->pINChI_Aux->nConstitEquIsotopicNumbers same as in pINChI_Aux_Taut */
1602
+ /* output this (current) equivalence as '*', that is, same as tautomeric */
1603
+ /* that was printed on the 1st pass. */
1604
+ pCurrEquStr = EquString(eq2taut);
1605
+ if ( multPrevEquStr && pPrevEquStr ) {
1606
+ if ( pCurrEquStr && !strcmp(pCurrEquStr, pPrevEquStr) ) {
1607
+ multPrevEquStr ++;
1608
+ } else {
1609
+ /* new EqStr is different; output it */
1610
+ if ( bNext ++ ) {
1611
+ tot_len += MakeDelim( sCompDelim, pStr + tot_len, nStrLen-tot_len, bOverflow);
1612
+ }
1613
+ tot_len += MakeEqStr( pPrevEquStr, multPrevEquStr, pStr + tot_len, nStrLen-tot_len, bOverflow);
1614
+ pPrevEquStr = pCurrEquStr;
1615
+ multPrevEquStr = 1;
1616
+ }
1617
+ } else {
1618
+ pPrevEquStr = pCurrEquStr;
1619
+ multPrevEquStr = 1;
1620
+ }
1621
+ pINChI_Aux_Prev = NULL; /* pINChI_Aux_Prev does not exist since */
1622
+ pINChI_Aux_Taut_Prev = NULL; /* pINChI_Aux has just been printed */
1623
+ mult = 0;
1624
+ eq2tautPrev = 1;
1625
+ } else
1626
+ if ( eq2tautPrev ) {
1627
+ /* at this point pINChI_Aux_Prev does not exist; however, pINChI_Aux */
1628
+ /*might have been discovered and it is different from pINChI_Aux_Taut */
1629
+ if ( multPrevEquStr && pPrevEquStr ) {
1630
+ /* new EqStr is different; output it */
1631
+ if ( bNext ++ ) {
1632
+ tot_len += MakeDelim( sCompDelim, pStr + tot_len, nStrLen-tot_len, bOverflow);
1633
+ }
1634
+ tot_len += MakeEqStr( pPrevEquStr, multPrevEquStr, pStr + tot_len, nStrLen-tot_len, bOverflow);
1635
+ pPrevEquStr = NULL;
1636
+ multPrevEquStr = 0;
1637
+ }
1638
+ eq2tautPrev = 0;
1639
+ pINChI_Aux_Prev = pINChI_Aux;
1640
+ pINChI_Aux_Taut_Prev = pINChI_Aux_Taut;
1641
+ mult = 0;
1642
+ } else {
1643
+ /* check whether pINChI_Aux and pINChI_Aux_Prev have identical non-trivial equivalence info */
1644
+ eq2prev = bUseMulipliers && Eql_INChI_Aux_Equ( pINChI_Aux, EQL_EQU_ISO, pINChI_Aux_Prev, EQL_EQU_ISO );
1645
+ if ( eq2prev ) {
1646
+ /* eq. info is same and non-trivial */
1647
+ mult ++; /* mult = (number of non-empty equal items)-1 */
1648
+ continue;
1649
+ } else {
1650
+ /* pINChI_Aux eq. info is either different or trivial. Output pINChI_Aux_Prev anyway */
1651
+ if ( bNext ++ ) {
1652
+ tot_len += MakeDelim( sCompDelim, pStr + tot_len, nStrLen-tot_len, bOverflow);
1653
+ }
1654
+ if ( pINChI_Aux_Prev && pINChI_Aux_Prev->nNumberOfAtoms ) {
1655
+ if ( bHasEquString( pINChI_Aux_Prev->nConstitEquIsotopicNumbers, pINChI_Aux_Prev->nNumberOfAtoms) ) {
1656
+ /* pINChI_Aux_Prev exists and has equivalence info */
1657
+ tot_len += MakeMult( mult+1, "*", pStr + tot_len, nStrLen-tot_len, 0, bOverflow);
1658
+ tot_len += MakeEquString( pINChI_Aux_Prev->nConstitEquIsotopicNumbers, pINChI_Aux_Prev->nNumberOfAtoms, 0,
1659
+ pStr + tot_len, nStrLen-tot_len, TAUT_MODE, bOverflow);
1660
+ } else {
1661
+ ; /* pINChI_Aux_Prev exists and has only trivial equivalence info */
1662
+ }
1663
+ } else
1664
+ if ( bSecondNonTautPass && pINChI_Aux_Taut_Prev && pINChI_Aux_Taut_Prev->nNumberOfAtoms ) {
1665
+ if ( bHasEquString( pINChI_Aux_Taut_Prev->nConstitEquIsotopicNumbers, pINChI_Aux_Taut_Prev->nNumberOfAtoms) ) {
1666
+ /* since pINChI_Aux_Prev does not exist, pINChI_Aux_Taut_Prev is non-tautomeric */
1667
+ /* and it has non-trivial equivalence info. This info has already been printed in the main section */
1668
+ /*
1669
+ tot_len += MakeDelim( sIdenticalValues, pStr + tot_len, nStrLen-tot_len, bOverflow);
1670
+ */
1671
+ } else {
1672
+ ; /* pINChI_Aux_Taut_Prev exists and has only trivial equivalence info */
1673
+ }
1674
+ }
1675
+ #if( bRELEASE_VERSION != 1 && defined(_DEBUG) )
1676
+ else {
1677
+ int stop = 1; /* <BRKPT> */
1678
+ }
1679
+ #endif
1680
+ }
1681
+ pINChI_Aux_Prev = pINChI_Aux;
1682
+ pINChI_Aux_Taut_Prev = pINChI_Aux_Taut;
1683
+ mult = 0; /* we do not know whether the item is empty */
1684
+ }
1685
+ }
1686
+ return tot_len;
1687
+ }
1688
+ /******************************************************************************************/
1689
+ int str_AuxInvIsoSp3(INCHI_SORT *pINChISort, INCHI_SORT *pINChISort2, char *pStr, int nStrLen, int tot_len,
1690
+ int *bOverflow, int bOutType, int TAUT_MODE, int num_components,
1691
+ int bSecondNonTautPass, int bOmitRepetitions, int bUseMulipliers)
1692
+ {
1693
+ int i, ii, ii2;
1694
+ INCHI_SORT *is, *is2;
1695
+ INChI *pINChI, *pINChI_Prev, *pINChI_Taut, *pINChI_Taut_Prev;
1696
+ INChI_Stereo *Stereo, *Stereo_Prev, *Stereo_Taut, *Stereo_Taut_Prev;
1697
+ int mult, eq2prev, eq2taut, eq2tautPrev, bNext;
1698
+ const char *pPrevEquStr, *pCurrEquStr;
1699
+ int multPrevEquStr;
1700
+ /********************************
1701
+ inverted isotopic sp3
1702
+ *********************************/
1703
+ pINChI_Taut = NULL;
1704
+ pINChI_Prev = NULL;
1705
+ pINChI_Taut_Prev = NULL;
1706
+ mult = 0;
1707
+ bNext = 0;
1708
+ is2 = bSecondNonTautPass? pINChISort2 : NULL;
1709
+ eq2taut = 0; /* may be non-zero if another layer of the current component = current layer */
1710
+ eq2tautPrev = 1; /* pINChI_Prev (previous pINChI) does not exist */
1711
+ pPrevEquStr = NULL; /*, *pCurrEquStr;*/
1712
+ multPrevEquStr = 0;
1713
+ for ( i = 0, is = pINChISort; i <= num_components; i ++, is ++, (bSecondNonTautPass? is2++ : 0) ) {
1714
+ /* 1st (taut) pass: bOutType=OUT_TN ; 2nd (non-taut pass) bOutType=OUT_NT */
1715
+ pINChI = (i < num_components && 0 <= (ii=GET_II(bOutType,is)))? is->pINChI[ii] : NULL;
1716
+ /*================ compare sp2 to previous =====================*/
1717
+ if ( bSecondNonTautPass ) {
1718
+ /* component that was output on the 1st pass */
1719
+ pINChI_Taut = ( i < num_components && 0 <= (ii2=GET_II(OUT_T1,is2)))? is2->pINChI[ii2] : NULL;
1720
+ }
1721
+ eq2taut = 0;
1722
+ /*========= if bSecondNonTautPass then compare iso non-taut stereo to other stereo ========*/
1723
+ if ( bSecondNonTautPass && bOmitRepetitions && pINChI && pINChI->nNumberOfIsotopicAtoms+pINChI->nNumberOfIsotopicTGroups > 0 ) {
1724
+ /* compare non-tautomeric isotopic inverted to:
1725
+ * a) tautomeric inverted
1726
+ * b) *non-tautomeric inverted
1727
+ * c) *isotopic tautomeric inverted
1728
+ * d) Inverted(tautomeric)
1729
+ * e) *Inverted(tautomeric isotopic)
1730
+ * f) Inverted(non-tautomeric)
1731
+ * g) *Inverted(non-tautomeric isotopic)
1732
+ */
1733
+ /* a) compare non-tautomeric isotopic inverted to tautomeric inverted */
1734
+ if ( !eq2taut ) {
1735
+ eq2taut = pINChI && pINChI_Taut &&
1736
+ /* non-taut inverted */ /* taut invertedc */
1737
+ (Stereo = pINChI->StereoIsotopic) && (Stereo_Taut = pINChI_Taut->Stereo) &&
1738
+ Eql_INChI_Stereo( Stereo, EQL_SP3_INV, Stereo_Taut, EQL_SP3_INV, 0 );
1739
+ /* stereo-inv isotopic non-taut = taut (stereo-inv) */
1740
+ eq2taut = eq2taut? (iiSTEREO_INV | iitISO | iitNONTAUT ) : 0;
1741
+ }
1742
+ /* b) compare non-tautomeric isotopic inverted to non-tautomeric inverted */
1743
+ if ( !eq2taut ) {
1744
+ eq2taut = pINChI && /* it is non-taut non-iso stereo */
1745
+ (Stereo = pINChI->StereoIsotopic) && (Stereo_Taut = pINChI->Stereo) &&
1746
+ Eql_INChI_Stereo( Stereo, EQL_SP3_INV, Stereo_Taut, EQL_SP3_INV, 0 );
1747
+ /* stereo-inv isotopic non-taut = non-taut stereo-inv */
1748
+ eq2taut = eq2taut? (iiSTEREO_INV | iitISO | iitNONTAUT | iiEq2NONTAUT) : 0;
1749
+ }
1750
+ /* c) compare non-tautomeric isotopic inverted to isotopic tautomeric inverted */
1751
+ if ( !eq2taut ) {
1752
+ eq2taut = pINChI && pINChI_Taut &&
1753
+ /* non-taut iso. inverted */ /* taut iso. inverted */
1754
+ (Stereo = pINChI->StereoIsotopic) && (Stereo_Taut = pINChI_Taut->StereoIsotopic) &&
1755
+ Eql_INChI_Stereo( Stereo, EQL_SP3_INV, Stereo_Taut, EQL_SP3_INV, 0 );
1756
+ /* stereo-inv isotopic non-taut = taut iso. stereo-inv */
1757
+ eq2taut = eq2taut? (iiSTEREO_INV | iitISO | iitNONTAUT | iiEq2ISO ) : 0;
1758
+ }
1759
+ /* d) compare non-tautomeric inverted to Inverted(tautomeric stereo) */
1760
+ if ( !eq2taut ) {
1761
+ eq2taut = pINChI && pINChI_Taut &&
1762
+ (Stereo = pINChI->StereoIsotopic) && (Stereo_Taut = pINChI_Taut->Stereo) &&
1763
+ Eql_INChI_Stereo( Stereo, EQL_SP3_INV, Stereo_Taut, EQL_SP3_INV, 0 );
1764
+ /* stereo-inv isotopic non-taut = Inv(non-iso taut stereo) */
1765
+ eq2taut = eq2taut? (iiSTEREO_INV | iitISO | iitNONTAUT | iiEq2INV) : 0;
1766
+ }
1767
+ /* e) compare non-tautomeric inverted to Inverted(isotopic tautomeric stereo) */
1768
+ if ( !eq2taut ) {
1769
+ eq2taut = pINChI && pINChI_Taut &&
1770
+ (Stereo = pINChI->StereoIsotopic) && (Stereo_Taut = pINChI_Taut->StereoIsotopic) &&
1771
+ Eql_INChI_Stereo( Stereo, EQL_SP3_INV, Stereo_Taut, EQL_SP3, 0 );
1772
+ /* stereo-inv isotopic non-taut = Inv(iso taut stereo) */
1773
+ eq2taut = eq2taut? (iiSTEREO_INV | iitISO | iitNONTAUT | iiEq2INV | iiEq2ISO) : 0;
1774
+ }
1775
+ /* f) compare non-tautomeric isotopic inverted to Inverted(non-tautomeric stereo) */
1776
+ if ( !eq2taut ) {
1777
+ eq2taut = pINChI && /* it is non-taut non-iso stereo */
1778
+ (Stereo = pINChI->StereoIsotopic) && (Stereo_Taut = pINChI->Stereo) &&
1779
+ Eql_INChI_Stereo( Stereo, EQL_SP3_INV, Stereo_Taut, EQL_SP3, 0 );
1780
+ /* stereo-inv isotopic non-taut = Inv(non-taut stereo) */
1781
+ eq2taut = eq2taut? (iiSTEREO_INV | iitISO | iitNONTAUT | iiEq2INV | iiEq2NONTAUT) : 0;
1782
+ }
1783
+ /* g) compare non-tautomeric isotopic inverted to Inverted(non-tautomeric isotopic stereo) */
1784
+ if ( !eq2taut ) {
1785
+ eq2taut = pINChI && /* it is non-taut non-iso stereo */
1786
+ (Stereo = pINChI->StereoIsotopic) &&
1787
+ Eql_INChI_Stereo( Stereo, EQL_SP3_INV, Stereo, EQL_SP3, 0 );
1788
+ /* stereo-inv isotopic non-taut = Inv( iso non-taut stereo) */
1789
+ eq2taut = eq2taut? (iiSTEREO_INV | iitISO | iitNONTAUT | iiEq2INV | iiEq2ISO | iiEq2NONTAUT) : 0;
1790
+ }
1791
+ } else
1792
+ /*========= if not bSecondNonTautPass then compare inv taut stereo to various stereo ========*/
1793
+ if ( !bSecondNonTautPass && bOmitRepetitions && pINChI &&
1794
+ (pINChI->nNumberOfIsotopicAtoms > 0 ||
1795
+ pINChI->nNumberOfIsotopicTGroups > 0 ||
1796
+ pINChI->nPossibleLocationsOfIsotopicH && pINChI->nPossibleLocationsOfIsotopicH[0] > 1) ) {
1797
+ /* compare tautomeric isotopic stereo-inverted to:
1798
+ * a) tautomeric stereo-inverted
1799
+ * b) Inverted(tautomeric stereo)
1800
+ * c) Inverted(tautomeric isotopic stereo)
1801
+ */
1802
+ /* a) compare tautomeric isotopic stereo-inverted to tautomeric stereo-inverted */
1803
+ if ( !eq2taut ) {
1804
+ eq2taut = pINChI &&
1805
+ (Stereo = pINChI->StereoIsotopic) && (Stereo_Taut = pINChI->Stereo) &&
1806
+ Eql_INChI_Stereo( Stereo, EQL_SP3_INV, Stereo_Taut, EQL_SP3_INV, 0 );
1807
+ /* stereo-inv isotopic taut = taut stereo-inv */
1808
+ eq2taut = eq2taut? (iiSTEREO_INV | iitISO ) : 0;
1809
+ }
1810
+ /* b) compare tautomeric isotopic stereo-inverted to Inverted(tautomeric stereo) */
1811
+ if ( !eq2taut ) {
1812
+ eq2taut = pINChI &&
1813
+ (Stereo = pINChI->StereoIsotopic) && (Stereo_Taut = pINChI->Stereo) &&
1814
+ Eql_INChI_Stereo( Stereo, EQL_SP3_INV, Stereo_Taut, EQL_SP3, 0 );
1815
+ /* stereo-inv isotopic taut = Inv(taut stereo) */
1816
+ eq2taut = eq2taut? (iiSTEREO_INV | iitISO | iiEq2INV ) : 0;
1817
+ }
1818
+ /* c) compare tautomeric isotopic stereo-inverted to Inverted(tautomeric isotopic stereo) */
1819
+ if ( !eq2taut ) {
1820
+ eq2taut = pINChI &&
1821
+ (Stereo = pINChI->StereoIsotopic) &&
1822
+ Eql_INChI_Stereo( Stereo, EQL_SP3_INV, Stereo, EQL_SP3, 0 );
1823
+ /* stereo-inv isotopic taut = Inv(taut iso stereo) */
1824
+ eq2taut = eq2taut? (iiSTEREO_INV | iitISO | iiEq2INV | iiEq2ISO ) : 0;
1825
+ }
1826
+ }
1827
+ if ( eq2taut ) {
1828
+ /* we may be here only in case of the current layer found equal in another layer the same component */
1829
+ if ( pINChI_Prev && pINChI_Prev->nNumberOfAtoms ) {
1830
+ /* previous component exists; output it before output the current component */
1831
+ if ( bNext ++ ) {
1832
+ tot_len += MakeDelim( sCompDelim, pStr + tot_len, nStrLen-tot_len, bOverflow);
1833
+ }
1834
+ if ( (Stereo_Prev = pINChI_Prev->StereoIsotopic) && Stereo_Prev->nNumberOfStereoCenters > 0 ) {
1835
+ tot_len += MakeMult( mult+1, "*", pStr + tot_len, nStrLen-tot_len, 0, bOverflow);
1836
+
1837
+ tot_len += MakeStereoString( Stereo_Prev->nNumber, NULL, Stereo_Prev->t_parityInv,
1838
+ 0, Stereo_Prev->nNumberOfStereoCenters,
1839
+ pStr + tot_len, nStrLen-tot_len, TAUT_MODE, bOverflow);
1840
+ }
1841
+ } else
1842
+ if ( pINChI_Taut_Prev && pINChI_Taut_Prev->nNumberOfAtoms ) {
1843
+ /* previous non-taut component exists only in taut list */
1844
+ if ( bNext ++ ) {
1845
+ tot_len += MakeDelim( sCompDelim, pStr + tot_len, nStrLen-tot_len, bOverflow);
1846
+ }
1847
+ /* do not output stereo of non-tautomeric in non-taut layer: it has been output in the main layer */
1848
+ }
1849
+ /* we have found another (previously printed) layer of the current component equal to this layer */
1850
+ /* output this (current) equivalence mark = EquString(eq2taut) */
1851
+ pCurrEquStr = EquString(eq2taut);
1852
+ if ( multPrevEquStr && pPrevEquStr ) {
1853
+ if ( pCurrEquStr && !strcmp(pCurrEquStr, pPrevEquStr) ) {
1854
+ multPrevEquStr ++;
1855
+ } else {
1856
+ /* new EqStr is different; output it */
1857
+ if ( bNext ++ ) {
1858
+ tot_len += MakeDelim( sCompDelim, pStr + tot_len, nStrLen-tot_len, bOverflow);
1859
+ }
1860
+ tot_len += MakeEqStr( pPrevEquStr, multPrevEquStr, pStr + tot_len, nStrLen-tot_len, bOverflow);
1861
+ pPrevEquStr = pCurrEquStr;
1862
+ multPrevEquStr = 1;
1863
+ }
1864
+ } else {
1865
+ pPrevEquStr = pCurrEquStr;
1866
+ multPrevEquStr = 1;
1867
+ }
1868
+ pINChI_Prev = NULL; /* pINChI_Prev sp2 does not exist since */
1869
+ pINChI_Taut_Prev = NULL; /* pINChI has just been printed */
1870
+ mult = 0;
1871
+ eq2tautPrev = 1; /* pINChI_Prev and pINChI_Taut_Prev have already been output */
1872
+ } else
1873
+ if ( eq2tautPrev ) {
1874
+ /* at this point pINChI_Prev does not exist; however, pINChI */
1875
+ /*might have been discovered and it is different from pINChI_Taut */
1876
+ if ( multPrevEquStr && pPrevEquStr ) {
1877
+ /* new EqStr is different; output it */
1878
+ if ( bNext ++ ) {
1879
+ tot_len += MakeDelim( sCompDelim, pStr + tot_len, nStrLen-tot_len, bOverflow);
1880
+ }
1881
+ tot_len += MakeEqStr( pPrevEquStr, multPrevEquStr, pStr + tot_len, nStrLen-tot_len, bOverflow);
1882
+ pPrevEquStr = NULL;
1883
+ multPrevEquStr = 0;
1884
+ }
1885
+ eq2tautPrev = 0;
1886
+ pINChI_Prev = pINChI;
1887
+ pINChI_Taut_Prev = pINChI_Taut;
1888
+ mult = 0;
1889
+ } else {
1890
+ /* current layer is different from previously printed layers of the current component */
1891
+ /* compare the current layer to this layer of the previous component: */
1892
+ /* check whether pINChI and pINChI_Prev have non-zero identical stereo sp2 */
1893
+ /*================ compare iso sp3 to previous =====================*/
1894
+ eq2prev =bUseMulipliers &&
1895
+ pINChI && pINChI->nNumberOfIsotopicAtoms + pINChI->nNumberOfIsotopicTGroups > 0 &&
1896
+ pINChI_Prev && pINChI_Prev->nNumberOfIsotopicAtoms + pINChI_Prev->nNumberOfIsotopicTGroups > 0 &&
1897
+ /* do both have stereo? */
1898
+ (Stereo = pINChI->StereoIsotopic) && (Stereo_Prev = pINChI_Prev->StereoIsotopic) &&
1899
+ /* is their inverted stereo same? */
1900
+ Eql_INChI_Stereo( Stereo, EQL_SP3_INV, Stereo_Prev, EQL_SP3_INV, 0 );
1901
+ if ( eq2prev ) {
1902
+ mult ++; /* mult = (number of non-empty equal items)-1 */
1903
+ continue;
1904
+ } else {
1905
+ if ( bNext ++ ) {
1906
+ tot_len += MakeDelim( sCompDelim, pStr + tot_len, nStrLen-tot_len, bOverflow);
1907
+ }
1908
+ if ( pINChI_Prev && pINChI_Prev->nNumberOfAtoms && pINChI_Prev->nNumberOfIsotopicAtoms + pINChI_Prev->nNumberOfIsotopicTGroups > 0 ) {
1909
+ if ( (Stereo_Prev = pINChI_Prev->StereoIsotopic) &&
1910
+ Stereo_Prev->nNumberOfStereoCenters > 0 && Stereo_Prev->nCompInv2Abs ) {
1911
+ tot_len += MakeMult( mult+1, "*", pStr + tot_len, nStrLen-tot_len, 0, bOverflow);
1912
+
1913
+ tot_len += MakeStereoString( Stereo_Prev->nNumberInv, NULL, Stereo_Prev->t_parityInv,
1914
+ 0, Stereo_Prev->nNumberOfStereoCenters,
1915
+ pStr + tot_len, nStrLen-tot_len, TAUT_MODE, bOverflow);
1916
+ }
1917
+ /* else sp3 info is not present in pINChI_Prev */
1918
+ } else
1919
+ /* do not print pINChI_Prev because it either do not exist of have already been printed */
1920
+ if ( bSecondNonTautPass && pINChI_Taut_Prev && pINChI_Taut_Prev->nNumberOfAtoms ) {
1921
+ if ( (Stereo_Taut_Prev = pINChI_Taut_Prev->StereoIsotopic) &&
1922
+ Stereo_Taut_Prev->nNumberOfStereoCenters > 0 && Stereo_Taut_Prev->nCompInv2Abs ) {
1923
+ /* since pINChI_Prev does not exist, pINChI_Taut_Prev is non-tautomeric */
1924
+ /* and it has non-trivial inv sp3 info. It has already been printed in the main section */
1925
+ /*
1926
+ tot_len += MakeDelim( sIdenticalValues, pStr + tot_len, nStrLen-tot_len, bOverflow);
1927
+ */
1928
+ ;/* pINChI_Taut_Prev sp3 info was output in the main stereo section */
1929
+ } else {
1930
+ ; /* pINChI_Taut_Prev exists and has not sp3 info */
1931
+ }
1932
+ }
1933
+ #if( bRELEASE_VERSION != 1 && defined(_DEBUG) )
1934
+ else {
1935
+ int stop = 1; /* <BRKPT> */
1936
+ }
1937
+ #endif
1938
+ }
1939
+ pINChI_Prev = pINChI;
1940
+ mult = 0; /* we do not know whether the item is empty */
1941
+ }
1942
+ }
1943
+ return tot_len;
1944
+ }
1945
+ /***************************************************************************/
1946
+ int str_AuxInvIsoSp3Numb(INCHI_SORT *pINChISort, INCHI_SORT *pINChISort2, char *pStr, int nStrLen, int tot_len,
1947
+ int *bOverflow, int bOutType, int TAUT_MODE, int num_components,
1948
+ int bSecondNonTautPass, int bOmitRepetitions)
1949
+ {
1950
+ int i, ii, ii2;
1951
+ INCHI_SORT *is, *is2;
1952
+ INChI *pINChI, *pINChI_Taut;
1953
+ INChI_Aux *pINChI_Aux, *pINChI_Aux_Prev, *pINChI_Aux_Taut;
1954
+ INChI_Stereo *Stereo, *Stereo_Taut;
1955
+ int eq2taut, bNext;
1956
+ const char *pPrevEquStr, *pCurrEquStr;
1957
+ int multPrevEquStr;
1958
+ /**************************************************
1959
+ * specificity of numbering: there is no previous *
1960
+ * component because no repetition is possible *
1961
+ **************************************************/
1962
+ pINChI = NULL;
1963
+ pINChI_Taut = NULL;
1964
+ pINChI_Aux = NULL;
1965
+ pINChI_Aux_Taut = NULL;
1966
+ pINChI_Aux_Prev = NULL;
1967
+ bNext = 0;
1968
+ is2 = bSecondNonTautPass? pINChISort2 : NULL;
1969
+ eq2taut = 0; /* may be non-zero if another layer of the current component = current layer */
1970
+ pPrevEquStr = NULL; /*, *pCurrEquStr;*/
1971
+ multPrevEquStr = 0;
1972
+ for ( i = 0, is = pINChISort; i < num_components; i ++, is ++, (bSecondNonTautPass? is2++ : 0) ) {
1973
+ /* 1st (taut) pass: bOutType=OUT_TN ; 2nd (non-taut pass) bOutType=OUT_NT */
1974
+ pINChI = (0 <= (ii=GET_II(bOutType,is)))? is->pINChI[ii] : NULL;
1975
+ pINChI_Aux = pINChI? is->pINChI_Aux[ii] : NULL;
1976
+ /*================ to compare to previously printed =====================*/
1977
+ if ( bSecondNonTautPass ) {
1978
+ /* component that was printed on the 1st pass */
1979
+ pINChI_Taut = (0 <= (ii2=GET_II(OUT_T1,is)))? is->pINChI[ii2] : NULL;
1980
+ pINChI_Aux_Taut = pINChI_Taut? is->pINChI_Aux[ii2] : NULL;
1981
+ }
1982
+ eq2taut = 0;
1983
+ /*========= if bSecondNonTautPass then compare iso non-taut stereo to other stereo ========*/
1984
+ if ( bSecondNonTautPass && bOmitRepetitions && pINChI && pINChI_Aux && pINChI_Aux->bIsIsotopic &&
1985
+ (Stereo = pINChI->StereoIsotopic) && Stereo->nCompInv2Abs &&
1986
+ pINChI_Aux->nNumberOfAtoms > 0 && pINChI_Aux->nIsotopicOrigAtNosInCanonOrdInv ) {
1987
+ /* compare isotopic non-tautomeric inverted stereo numbering to:
1988
+ * a) tautomeric numbering
1989
+ * b) non-tautomeric numbering
1990
+ * c) *tautomeric isotopic numbering
1991
+ * d) *non-tautomeric isotopic numbering
1992
+ * e) tautomeric inverted stereo numbering
1993
+ * f) *non-tautomeric inverted stereo numbering
1994
+ * g) tautomeric isotopic inverted stereo numbering
1995
+ */
1996
+ /* a) compare isotopic non-tautomeric inverted stereo numbering to tautomeric numbering */
1997
+ if ( !eq2taut ) {
1998
+ eq2taut = pINChI_Taut &&
1999
+ Eql_INChI_Aux_Num( pINChI_Aux, EQL_NUM_INV | EQL_NUM_ISO, pINChI_Aux_Taut, EQL_NUM );
2000
+ /* stereo-inv isotopic numbering non-taut = taut numbering */
2001
+ eq2taut = eq2taut? (iiSTEREO_INV | iitISO | iiNUMB | iitNONTAUT ) : 0;
2002
+ }
2003
+ /* b) compare isotopic non-tautomeric inverted stereo numbering to non-tautomeric numbering */
2004
+ if ( !eq2taut ) {
2005
+ eq2taut =
2006
+ Eql_INChI_Aux_Num( pINChI_Aux, EQL_NUM_INV | EQL_NUM_ISO, pINChI_Aux, EQL_NUM );
2007
+ /* stereo-inv isotopic numb. non-taut = non-taut numbering */
2008
+ eq2taut = eq2taut? (iiSTEREO_INV | iitISO | iiNUMB | iitNONTAUT | iiEq2NONTAUT ) : 0;
2009
+ }
2010
+ /* c) compare isotopic non-tautomeric inverted stereo numbering to tautomeric isotopic numbering */
2011
+ if ( !eq2taut ) {
2012
+ eq2taut = pINChI_Taut &&
2013
+ Eql_INChI_Aux_Num( pINChI_Aux, EQL_NUM_INV | EQL_NUM_ISO, pINChI_Aux_Taut, EQL_NUM_ISO );
2014
+ /* stereo-inv isotopic numb. non-taut = taut iso numbering */
2015
+ eq2taut = eq2taut? (iiSTEREO_INV | iitISO | iiNUMB | iitNONTAUT | iiEq2ISO ) : 0;
2016
+ }
2017
+ /* d) compare isotopic non-tautomeric inverted stereo numbering to non-tautomeric isotopic numbering */
2018
+ if ( !eq2taut ) {
2019
+ eq2taut = Eql_INChI_Aux_Num( pINChI_Aux, EQL_NUM_INV | EQL_NUM_ISO, pINChI_Aux, EQL_NUM_ISO );
2020
+ /* stereo-inv isotopic numb. non-taut = non-taut isotopic numbering */
2021
+ eq2taut = eq2taut? (iiSTEREO_INV | iitISO | iiNUMB | iitNONTAUT | iiEq2NONTAUT | iiEq2ISO) : 0;
2022
+ }
2023
+ /* e) compare isotopic non-tautomeric inverted stereo numbering to tautomeric inverted stereo numbering */
2024
+ if ( !eq2taut ) {
2025
+ eq2taut = pINChI_Taut && pINChI_Aux_Taut &&
2026
+ (Stereo_Taut = pINChI_Taut->Stereo) && Stereo_Taut->nCompInv2Abs &&
2027
+ Eql_INChI_Aux_Num( pINChI_Aux, EQL_NUM_INV | EQL_NUM_ISO, pINChI_Aux_Taut, EQL_NUM_INV );
2028
+ /* stereo-inv isotopic numbering non-taut = stereo-inv taut numbering */
2029
+ eq2taut = eq2taut? (iiSTEREO_INV | iitISO | iiNUMB | iitNONTAUT | iiEq2INV) : 0;
2030
+ }
2031
+ /* f) compare isotopic non-tautomeric inverted stereo numbering to non-tautomeric inverted stereo numbering */
2032
+ if ( !eq2taut ) {
2033
+ eq2taut =
2034
+ (Stereo_Taut = pINChI->StereoIsotopic) && Stereo_Taut->nCompInv2Abs &&
2035
+ Eql_INChI_Aux_Num( pINChI_Aux, EQL_NUM_INV | EQL_NUM_ISO, pINChI_Aux, EQL_NUM_INV );
2036
+ /* stereo-inv isotopic numbering non-taut = stereo-inv non-taut numbering */
2037
+ eq2taut = eq2taut? (iiSTEREO_INV | iitISO | iiNUMB | iitNONTAUT | iiEq2INV | iiEq2NONTAUT) : 0;
2038
+ }
2039
+
2040
+ /* g) compare isotopic non-tautomeric inverted stereo numbering to tautomeric isotopic inverted stereo numbering */
2041
+ if ( !eq2taut ) {
2042
+ eq2taut = pINChI_Taut &&
2043
+ (Stereo_Taut = pINChI_Taut->StereoIsotopic) && Stereo_Taut->nCompInv2Abs &&
2044
+ Eql_INChI_Aux_Num( pINChI_Aux, EQL_NUM_INV | EQL_NUM_ISO, pINChI_Aux_Taut, EQL_NUM_INV | EQL_NUM_ISO );
2045
+ /* stereo-inv isotopic numbering non-taut = stereo-inv iso taut numbering */
2046
+ eq2taut = eq2taut? (iiSTEREO_INV | iitISO | iiNUMB | iitNONTAUT | iiEq2INV | iiEq2ISO) : 0;
2047
+ }
2048
+ } else
2049
+ /*========= if not bSecondNonTautPass then compare inv taut stereo numb to taut numb ========*/
2050
+ if ( !bSecondNonTautPass && bOmitRepetitions && pINChI && pINChI_Aux && pINChI_Aux->bIsIsotopic &&
2051
+ (Stereo = pINChI->StereoIsotopic) && Stereo->nCompInv2Abs &&
2052
+ pINChI_Aux->nNumberOfAtoms > 0 && pINChI_Aux->nIsotopicOrigAtNosInCanonOrdInv ) {
2053
+ /* compare isotopic tautomeric inverted stereo numbering to:
2054
+ * a) tautomeric numbering
2055
+ * b) tautomeric isotopic numbering
2056
+ * c) tautomeric inverted stereo numbering
2057
+ */
2058
+ /* a) compare isotopic tautomeric inverted stereo numbering to tautomeric numbering */
2059
+ if ( !eq2taut ) {
2060
+ eq2taut = Eql_INChI_Aux_Num( pINChI_Aux, EQL_NUM_INV | EQL_NUM_ISO, pINChI_Aux, EQL_NUM );
2061
+ /* stereo-inv isotopic numbering (taut) = taut numbering */
2062
+ eq2taut = eq2taut? (iiSTEREO_INV | iitISO | iiNUMB ) : 0;
2063
+ }
2064
+ /* b) compare isotopic tautomeric inverted stereo numbering to tautomeric isotopic numbering */
2065
+ if ( !eq2taut ) {
2066
+ eq2taut = Eql_INChI_Aux_Num( pINChI_Aux, EQL_NUM_INV | EQL_NUM_ISO, pINChI_Aux, EQL_NUM_ISO );
2067
+ /* stereo-inv isotopic numbering(taut) = isotopic taut numbering */
2068
+ eq2taut = eq2taut? (iiSTEREO_INV | iitISO | iiNUMB | iiEq2ISO ) : 0;
2069
+ }
2070
+ /* b) compare isotopic tautomeric inverted stereo numbering to tautomeric inverted stereo numbering */
2071
+ if ( !eq2taut ) {
2072
+ eq2taut = (Stereo_Taut = pINChI->Stereo) && Stereo->nCompInv2Abs &&
2073
+ Eql_INChI_Aux_Num( pINChI_Aux, EQL_NUM_INV | EQL_NUM_ISO, pINChI_Aux, EQL_NUM_INV );
2074
+ /* stereo-inv isotopic numbering (taut) = taut stereo-inv numbering */
2075
+ eq2taut = eq2taut? (iiSTEREO_INV | iitISO | iiNUMB | iiEq2INV ) : 0;
2076
+ }
2077
+ }
2078
+ if ( eq2taut ) {
2079
+ /* we have found another (previously printed) layer of the current component equal to this layer */
2080
+ /* output this (current) equivalence mark = EquString(eq2taut) */
2081
+ pCurrEquStr = EquString(eq2taut);
2082
+ if ( multPrevEquStr && pPrevEquStr ) {
2083
+ if ( pCurrEquStr && !strcmp(pCurrEquStr, pPrevEquStr) ) {
2084
+ multPrevEquStr ++;
2085
+ } else {
2086
+ /* new EqStr is different; output it */
2087
+ if ( bNext ++ ) {
2088
+ tot_len += MakeDelim( sCompDelim, pStr + tot_len, nStrLen-tot_len, bOverflow);
2089
+ }
2090
+ tot_len += MakeEqStr( pPrevEquStr, multPrevEquStr, pStr + tot_len, nStrLen-tot_len, bOverflow);
2091
+ pPrevEquStr = pCurrEquStr;
2092
+ multPrevEquStr = 1;
2093
+ }
2094
+ } else {
2095
+ pPrevEquStr = pCurrEquStr;
2096
+ multPrevEquStr = 1;
2097
+ }
2098
+ } else {
2099
+ /* current layer is different from previously printed layers of the current component */
2100
+ if ( multPrevEquStr && pPrevEquStr ) {
2101
+ /* new EqStr is different; output it */
2102
+ if ( bNext ++ ) {
2103
+ tot_len += MakeDelim( sCompDelim, pStr + tot_len, nStrLen-tot_len, bOverflow);
2104
+ }
2105
+ tot_len += MakeEqStr( pPrevEquStr, multPrevEquStr, pStr + tot_len, nStrLen-tot_len, bOverflow);
2106
+ pPrevEquStr = NULL;
2107
+ multPrevEquStr = 0;
2108
+ }
2109
+ if ( bNext ++ ) {
2110
+ tot_len += MakeDelim( sCompDelim, pStr + tot_len, nStrLen-tot_len, bOverflow);
2111
+ }
2112
+ if ( pINChI && pINChI_Aux && pINChI_Aux->bIsIsotopic && pINChI_Aux->nNumberOfAtoms &&
2113
+ (Stereo = pINChI->StereoIsotopic) && Stereo->nNumberOfStereoCenters &&
2114
+ Stereo->nCompInv2Abs && pINChI_Aux->nIsotopicOrigAtNosInCanonOrdInv ) {
2115
+ tot_len += MakeCtString( pINChI_Aux->nIsotopicOrigAtNosInCanonOrdInv,
2116
+ pINChI_Aux->nNumberOfAtoms, 0, NULL, 0,
2117
+ pStr + tot_len, nStrLen-tot_len, TAUT_MODE, bOverflow);
2118
+ }
2119
+ /* else isotopic inv stereo info is not present in pINChI */
2120
+ }
2121
+ }
2122
+ if ( multPrevEquStr && pPrevEquStr ) {
2123
+ /* the new EqStr of the last item has not been printed; output it now */
2124
+ if ( bNext ++ ) {
2125
+ tot_len += MakeDelim( sCompDelim, pStr + tot_len, nStrLen-tot_len, bOverflow);
2126
+ }
2127
+ tot_len += MakeEqStr( pPrevEquStr, multPrevEquStr, pStr + tot_len, nStrLen-tot_len, bOverflow);
2128
+ pPrevEquStr = NULL;
2129
+ multPrevEquStr = 0;
2130
+ }
2131
+ return tot_len;
2132
+ }
2133
+ /***************************************************************************/
2134
+ int str_HillFormula(INCHI_SORT *pINChISort, char *pStr, int nStrLen, int tot_len,
2135
+ int *bOverflow, int bOutType, int num_components, int bUseMulipliers)
2136
+ {
2137
+ int i, ii;
2138
+ INCHI_SORT *is;
2139
+ INChI *pINChI, *pINChI_Prev;
2140
+ int mult, eq2prev, bNext;
2141
+
2142
+ if ( !(is = pINChISort) ) {
2143
+ return tot_len;
2144
+ }
2145
+ i = 0;
2146
+ pINChI_Prev = (0 <= (ii=GET_II(bOutType,is)))? is->pINChI[ii] : NULL;
2147
+ mult = 0;
2148
+ bNext = 0;
2149
+ for ( i++, is++; i <= num_components; i ++, is ++ ) {
2150
+ pINChI = (i < num_components && 0 <= (ii=GET_II(bOutType,is)))? is->pINChI[ii] : NULL;
2151
+ eq2prev = bUseMulipliers &&
2152
+ pINChI && pINChI_Prev && pINChI->szHillFormula && pINChI_Prev->szHillFormula &&
2153
+ pINChI->szHillFormula[0] && !strcmp(pINChI_Prev->szHillFormula, pINChI->szHillFormula);
2154
+ if ( eq2prev ) {
2155
+ mult ++; /* mult = (number of non-empty equal items)-1 */
2156
+ continue;
2157
+ } else {
2158
+ if ( bNext ++ ) {
2159
+ tot_len += MakeDelim( ".", pStr + tot_len, nStrLen-tot_len, bOverflow);
2160
+ }
2161
+ if ( pINChI_Prev && pINChI_Prev->szHillFormula && pINChI_Prev->szHillFormula[0] ) {
2162
+ tot_len += MakeMult( mult+1, "", pStr + tot_len, nStrLen-tot_len, 0, bOverflow);
2163
+ tot_len += MakeHillFormulaString( pINChI_Prev->szHillFormula, pStr + tot_len,
2164
+ nStrLen-tot_len, bOverflow);
2165
+ }
2166
+ }
2167
+ pINChI_Prev = pINChI;
2168
+ mult = 0; /* we do not know whether the item is empty */
2169
+ }
2170
+ return tot_len;
2171
+ }
2172
+ /***************************************************************************/
2173
+ int str_HillFormula2(INCHI_SORT *pINChISort /* non-taut */, INCHI_SORT *pINChISort2 /* taut */,
2174
+ char *pStr, int nStrLen, int tot_len,
2175
+ int *bOverflow, int bOutType, int num_components, int bUseMulipliers)
2176
+ {
2177
+ int i, ii, ii2;
2178
+ INCHI_SORT *is, *is2;
2179
+ INChI *pINChI, *pINChI_Prev, *pINChI_Taut, *pINChI_Taut_Prev;
2180
+ int mult, eq2prev, bNext, bEqToTaut, tot_len_inp = tot_len;
2181
+
2182
+ is = pINChISort;
2183
+ is2 = pINChISort2;
2184
+ i = 0;
2185
+
2186
+ pINChI_Prev = (0 <= (ii=GET_II(bOutType,is)))? is->pINChI[ii] : NULL;
2187
+ pINChI_Taut_Prev = (0 <= (ii2=GET_II(OUT_T1,is2)))? is2->pINChI[ii2] : NULL;
2188
+ mult = 0;
2189
+ bNext = 0;
2190
+ bEqToTaut = 1;
2191
+ bEqToTaut = bEqToTaut &&
2192
+ pINChI_Prev && pINChI_Taut_Prev && !pINChI_Taut_Prev->bDeleted &&
2193
+ pINChI_Prev->szHillFormula && pINChI_Taut_Prev->szHillFormula &&
2194
+ !strcmp(pINChI_Prev->szHillFormula, pINChI_Taut_Prev->szHillFormula);
2195
+ for ( i++, is++, is2++; i <= num_components; i ++, is ++, is2 ++ ) {
2196
+ pINChI = (i < num_components && 0 <= (ii =GET_II(bOutType,is)))? is->pINChI[ii] : NULL;
2197
+ pINChI_Taut = (i < num_components && 0 <= (ii2=GET_II(OUT_T1,is2)))? is2->pINChI[ii2] : NULL;
2198
+ if ( bEqToTaut && (pINChI || pINChI_Taut) ) {
2199
+ bEqToTaut = pINChI && pINChI_Taut && !pINChI_Taut->bDeleted &&
2200
+ pINChI->szHillFormula && pINChI_Taut->szHillFormula &&
2201
+ !strcmp(pINChI->szHillFormula, pINChI_Taut->szHillFormula);
2202
+ }
2203
+ eq2prev = bUseMulipliers &&
2204
+ pINChI && pINChI_Prev && pINChI->szHillFormula && pINChI_Prev->szHillFormula &&
2205
+ pINChI->szHillFormula[0] && !strcmp(pINChI_Prev->szHillFormula, pINChI->szHillFormula);
2206
+ if ( eq2prev ) {
2207
+ mult ++; /* mult = (number of non-empty equal items)-1 */
2208
+ continue;
2209
+ } else {
2210
+ if ( bNext ++ ) {
2211
+ tot_len += MakeDelim( ".", pStr + tot_len, nStrLen-tot_len, bOverflow);
2212
+ }
2213
+ if ( pINChI_Prev && pINChI_Prev->szHillFormula && pINChI_Prev->szHillFormula[0] ) {
2214
+ tot_len += MakeMult( mult+1, "", pStr + tot_len, nStrLen-tot_len, 0, bOverflow);
2215
+ tot_len += MakeHillFormulaString( pINChI_Prev->szHillFormula, pStr + tot_len,
2216
+ nStrLen-tot_len, bOverflow);
2217
+ }
2218
+ }
2219
+ pINChI_Prev = pINChI;
2220
+ mult = 0; /* we do not know whether the item is empty */
2221
+ }
2222
+ if ( bEqToTaut ) {
2223
+ pStr[tot_len=tot_len_inp] = '\0';
2224
+ }
2225
+ return tot_len;
2226
+ }
2227
+ /***************************************************************************/
2228
+ int str_Connections(INCHI_SORT *pINChISort, char *pStr, int nStrLen, int tot_len,
2229
+ int *bOverflow, int bOutType, int ATOM_MODE, int num_components, int bUseMulipliers)
2230
+ {
2231
+ int i, ii;
2232
+ INCHI_SORT *is;
2233
+ INChI *pINChI, *pINChI_Prev;
2234
+ int mult, eq2prev, bNext, tot_len_inp, nNumEmpty;
2235
+
2236
+ if ( !(is = pINChISort) ) {
2237
+ return tot_len;
2238
+ }
2239
+ i = 0;
2240
+ pINChI_Prev = (0 <= (ii=GET_II(bOutType,is)))? is->pINChI[ii] : NULL;
2241
+ mult = 0;
2242
+ bNext = 0;
2243
+ tot_len_inp = tot_len;
2244
+ nNumEmpty = 0;
2245
+ for ( i++, is++; i <= num_components; i ++, is ++ ) {
2246
+ pINChI = (i < num_components && 0 <= (ii=GET_II(bOutType,is)))? is->pINChI[ii] : NULL;
2247
+ eq2prev = bUseMulipliers &&
2248
+ pINChI && pINChI_Prev && pINChI->lenConnTable > 1 &&
2249
+ pINChI_Prev->lenConnTable==pINChI->lenConnTable &&
2250
+ !memcmp( pINChI_Prev->nConnTable, pINChI->nConnTable,
2251
+ pINChI_Prev->lenConnTable*sizeof(pINChI->nConnTable[0]) );
2252
+ if ( eq2prev ) {
2253
+ mult ++; /* mult = (number of non-empty equal items)-1 */
2254
+ continue;
2255
+ } else
2256
+ if ( pINChI_Prev ) {
2257
+ if ( bNext ++ ) {
2258
+ tot_len += MakeDelim( sCompDelim, pStr + tot_len, nStrLen-tot_len, bOverflow);
2259
+ }
2260
+ if ( pINChI_Prev && pINChI_Prev->lenConnTable > 1 ) {
2261
+ tot_len += MakeMult( mult+1, "*", pStr + tot_len, nStrLen-tot_len, 0, bOverflow);
2262
+ tot_len += MakeCtStringNew( pINChI_Prev->nConnTable, pINChI_Prev->lenConnTable, 0,
2263
+ NULL, pINChI_Prev->nNumberOfAtoms,
2264
+ pStr + tot_len, nStrLen-tot_len, ATOM_MODE, bOverflow);
2265
+ } else {
2266
+ nNumEmpty ++;
2267
+ }
2268
+ }
2269
+ pINChI_Prev = pINChI;
2270
+ mult = 0; /* we do not know whether the item is empty */
2271
+ }
2272
+ if ( nNumEmpty == num_components && tot_len > tot_len_inp ) {
2273
+ tot_len = tot_len_inp;
2274
+ pStr[tot_len] = '\0';
2275
+ }
2276
+ return tot_len;
2277
+ }
2278
+ /***************************************************************************/
2279
+ int str_H_atoms(INCHI_SORT *pINChISort, char *pStr, int nStrLen, int tot_len,
2280
+ int *bOverflow, int bOutType, int ATOM_MODE, int TAUT_MODE,
2281
+ int num_components, int bUseMulipliers)
2282
+ {
2283
+ int i, j, ii, len_H;
2284
+ INCHI_SORT *is;
2285
+ INChI *pINChI, *pINChI_Prev;
2286
+ int mult, eq2prev, bNext, bNotEmpty, nNumEmpty, tot_len_inp;
2287
+
2288
+ nNumEmpty = 0;
2289
+ tot_len_inp = tot_len;
2290
+ is = pINChISort;
2291
+ i = 0;
2292
+ pINChI_Prev = (0 <= (ii=GET_II(bOutType,is)))? is->pINChI[ii] : NULL;
2293
+ mult = 0;
2294
+ bNext = 0;
2295
+ for ( i++, is++; i <= num_components; i ++, is ++ ) {
2296
+ pINChI = (i < num_components && 0 <= (ii=GET_II(bOutType,is)))? is->pINChI[ii] : NULL;
2297
+ /*========== compare to previous ============*/
2298
+ eq2prev = bUseMulipliers &&
2299
+ pINChI && pINChI_Prev && (pINChI->nNumberOfAtoms > 0 || pINChI->lenTautomer>1) &&
2300
+ pINChI_Prev->nNumberOfAtoms==pINChI->nNumberOfAtoms &&
2301
+ (!pINChI_Prev->nNumberOfAtoms || !memcmp( pINChI_Prev->nNum_H, pINChI->nNum_H,
2302
+ pINChI_Prev->nNumberOfAtoms*sizeof(pINChI->nNum_H[0]) ) ) &&
2303
+ !CompareTautNonIsoPartOfINChI( pINChI_Prev, pINChI );
2304
+
2305
+ if ( eq2prev && pINChI_Prev->lenTautomer <= 1 ) {
2306
+ /* make sure it is not empty */
2307
+ eq2prev = 0;
2308
+ for ( j = 0; j < pINChI_Prev->nNumberOfAtoms; j ++ ) {
2309
+ if ( pINChI_Prev->nNum_H[j] ) {
2310
+ eq2prev = 1;
2311
+ break;
2312
+ }
2313
+ }
2314
+ }
2315
+ if ( eq2prev ) {
2316
+ mult ++; /* mult = (number of non-empty equal items)-1 */
2317
+ continue;
2318
+ } else
2319
+ if ( pINChI_Prev ) {
2320
+ /* delimiter */
2321
+ if ( bNext ++ ) {
2322
+ tot_len += MakeDelim( sCompDelim, pStr + tot_len, nStrLen-tot_len, bOverflow);
2323
+ }
2324
+ /* verify non-empty */
2325
+ bNotEmpty = 0;
2326
+ if ( pINChI_Prev ) {
2327
+ bNotEmpty = (pINChI_Prev->lenTautomer > 1);
2328
+ if ( !bNotEmpty ) {
2329
+ for ( j = 0; j < pINChI_Prev->nNumberOfAtoms; j ++ ) {
2330
+ if ( pINChI_Prev->nNum_H[j] ) {
2331
+ bNotEmpty = 1;
2332
+ break;
2333
+ }
2334
+ }
2335
+ }
2336
+ }
2337
+ if ( bNotEmpty ) {
2338
+ tot_len += MakeMult( mult+1, "*", pStr + tot_len, nStrLen-tot_len, 0, bOverflow);
2339
+ /* H-atoms */
2340
+ tot_len += (len_H = MakeHString( 0, pINChI_Prev->nNum_H, pINChI_Prev->nNumberOfAtoms,
2341
+ pStr + tot_len, nStrLen-tot_len, ATOM_MODE, bOverflow ));
2342
+ /* tautomeric groups */
2343
+ tot_len += MakeTautString( pINChI_Prev->nTautomer, pINChI_Prev->lenTautomer, (0!=len_H),
2344
+ pStr + tot_len, nStrLen-tot_len, TAUT_MODE, bOverflow);
2345
+ } else {
2346
+ nNumEmpty ++;
2347
+ }
2348
+ }
2349
+ pINChI_Prev = pINChI;
2350
+ mult = 0; /* we do not know whether the item is empty */
2351
+ }
2352
+ if ( nNumEmpty == num_components && tot_len > tot_len_inp ) {
2353
+ tot_len = tot_len_inp;
2354
+ pStr[tot_len] = '\0';
2355
+ }
2356
+ return tot_len;
2357
+ }
2358
+ /***************************************************************************/
2359
+ int str_Charge2(INCHI_SORT *pINChISort, INCHI_SORT *pINChISort2, char *pStr, int nStrLen, int tot_len,
2360
+ int *bOverflow, int bOutType, int num_components,
2361
+ int bSecondNonTautPass, int bOmitRepetitions, int bUseMulipliers)
2362
+ {
2363
+ int i, ii, ii2;
2364
+ INCHI_SORT *is, *is2;
2365
+ INChI *pINChI, *pINChI_Prev, *pINChI_Taut, *pINChI_Taut_Prev;
2366
+ int nTotalCharge, nTotalCharge_Prev, nTotalCharge_Taut, nTotalCharge_Taut_Prev;
2367
+ int mult, eq2prev, eq2taut, eq2tautPrev, bNext;
2368
+ const char *pPrevEquStr, *pCurrEquStr;
2369
+ int multPrevEquStr;
2370
+ pINChI_Taut = NULL;
2371
+ pINChI_Prev = NULL;
2372
+ pINChI_Taut_Prev = NULL;
2373
+ mult = 0;
2374
+ bNext = 0;
2375
+ is2 = bSecondNonTautPass? pINChISort2 : NULL;
2376
+ eq2taut = 0; /* may be non-zero only on the 2nd (non-taut) pass */
2377
+ eq2tautPrev = 1; /* pINChI_Prev (previous pINChI) does not exist */
2378
+ pPrevEquStr = NULL; /*, *pCurrEquStr;*/
2379
+ multPrevEquStr = 0;
2380
+ for ( i = 0, is = pINChISort; i <= num_components; i ++, is ++, (bSecondNonTautPass? is2++ : 0) ) {
2381
+ /* 1st (taut) pass: bOutType=OUT_TN ; 2nd (non-taut pass) bOutType=OUT_NT */
2382
+ pINChI = (i < num_components && 0 <= (ii=GET_II(bOutType,is)))? is->pINChI[ii] : NULL;
2383
+ /*================ compare sp3 to previous =====================*/
2384
+ if ( bSecondNonTautPass ) {
2385
+ /* component that was output on the 1st pass */
2386
+ pINChI_Taut = ( i < num_components && 0 <= (ii2=GET_II(OUT_T1,is2)))? is2->pINChI[ii2] : NULL;
2387
+ }
2388
+ /*========= if bSecondNonTautPass then compare non-iso non-taut stereo to non-iso taut ========*/
2389
+ eq2taut = 0;
2390
+ if ( !eq2taut && bSecondNonTautPass && bOmitRepetitions ) {
2391
+ eq2taut = pINChI && pINChI_Taut && !pINChI_Taut->bDeleted &&
2392
+ (nTotalCharge = pINChI->nTotalCharge) && (nTotalCharge_Taut = pINChI_Taut->nTotalCharge) &&
2393
+ nTotalCharge == nTotalCharge_Taut;
2394
+ eq2taut = eq2taut? (iiEQU | iitNONTAUT) : 0;
2395
+ }
2396
+ if ( eq2taut ) {
2397
+ /* we may be here only in case of the second (non-taut) pass */
2398
+ /* current non-taut stereo has been found to be same as tautomeric */
2399
+ if ( pINChI_Prev && pINChI_Prev->nNumberOfAtoms ) {
2400
+ /* previous component exists; output it */
2401
+ if ( bNext ++ ) {
2402
+ tot_len += MakeDelim( sCompDelim, pStr + tot_len, nStrLen-tot_len, bOverflow);
2403
+ }
2404
+ if ( nTotalCharge_Prev = pINChI_Prev->nTotalCharge ) {
2405
+ tot_len += MakeMult( mult+1, "*", pStr + tot_len, nStrLen-tot_len, 0, bOverflow);
2406
+ tot_len += sprintf( pStr + tot_len, "%+d", nTotalCharge_Prev );
2407
+ }
2408
+ } else
2409
+ if ( pINChI_Taut_Prev && pINChI_Taut_Prev->nNumberOfAtoms && !pINChI_Taut_Prev->bDeleted ) {
2410
+ /* previous non-taut component exists only in taut list */
2411
+ if ( bNext ++ ) {
2412
+ tot_len += MakeDelim( sCompDelim, pStr + tot_len, nStrLen-tot_len, bOverflow);
2413
+ }
2414
+ }
2415
+ /* we have found pINChI->nTotalCharge same as in pINChI_Taut */
2416
+ /* output this (current) equivalence as '*', that is, same as tautomeric */
2417
+ /* that was printed on the 1st pass. */
2418
+
2419
+ pCurrEquStr = EquString(eq2taut);
2420
+ if ( multPrevEquStr && pPrevEquStr ) {
2421
+ if ( pCurrEquStr && !strcmp(pCurrEquStr, pPrevEquStr) ) {
2422
+ multPrevEquStr ++;
2423
+ } else {
2424
+ /* new EqStr is different; output it */
2425
+ if ( bNext ++ ) {
2426
+ tot_len += MakeDelim( sCompDelim, pStr + tot_len, nStrLen-tot_len, bOverflow);
2427
+ }
2428
+ tot_len += MakeEqStr( pPrevEquStr, multPrevEquStr, pStr + tot_len, nStrLen-tot_len, bOverflow);
2429
+ pPrevEquStr = pCurrEquStr;
2430
+ multPrevEquStr = 1;
2431
+ }
2432
+ } else {
2433
+ pPrevEquStr = pCurrEquStr;
2434
+ multPrevEquStr = 1;
2435
+ }
2436
+
2437
+ pINChI_Prev = NULL; /* pINChI_Prev sp2 does not exist since */
2438
+ pINChI_Taut_Prev = NULL; /* pINChI has just been printed */
2439
+ mult = 0;
2440
+ eq2tautPrev = 1; /* pINChI_Prev sp2 does not exist */
2441
+ } else
2442
+ if ( eq2tautPrev ) {
2443
+ /* at this point pINChI_Prev does not exist; however, pINChI */
2444
+ /*might have been discovered and it is different from pINChI_Taut */
2445
+ if ( multPrevEquStr && pPrevEquStr ) {
2446
+ /* new EqStr is different; output it */
2447
+ if ( bNext ++ ) {
2448
+ tot_len += MakeDelim( sCompDelim, pStr + tot_len, nStrLen-tot_len, bOverflow);
2449
+ }
2450
+ tot_len += MakeEqStr( pPrevEquStr, multPrevEquStr, pStr + tot_len, nStrLen-tot_len, bOverflow);
2451
+ pPrevEquStr = NULL;
2452
+ multPrevEquStr = 0;
2453
+ }
2454
+ eq2tautPrev = 0;
2455
+ pINChI_Prev = pINChI;
2456
+ pINChI_Taut_Prev = pINChI_Taut;
2457
+ mult = 0;
2458
+ } else {
2459
+ /* check whether pINChI and pINChI_Prev have non-zero identical stereo sp3 */
2460
+ /*================ compare sp3 to previous =====================*/
2461
+ eq2prev =bUseMulipliers &&
2462
+ pINChI && pINChI_Prev &&
2463
+ (nTotalCharge = pINChI->nTotalCharge) && (nTotalCharge_Prev = pINChI_Prev->nTotalCharge) &&
2464
+ nTotalCharge == nTotalCharge_Prev;
2465
+ if ( eq2prev ) {
2466
+ mult ++; /* mult = (number of non-empty equal items)-1 */
2467
+ continue;
2468
+ } else {
2469
+ if ( bNext ++ ) {
2470
+ tot_len += MakeDelim( sCompDelim, pStr + tot_len, nStrLen-tot_len, bOverflow);
2471
+ }
2472
+ if ( pINChI_Prev && pINChI_Prev->nNumberOfAtoms ) {
2473
+ if ( nTotalCharge_Prev = pINChI_Prev->nTotalCharge ) {
2474
+ /* pINChI_Prev exists and has charge info */
2475
+ tot_len += MakeMult( mult+1, "*", pStr + tot_len, nStrLen-tot_len, 0, bOverflow);
2476
+ tot_len += sprintf( pStr + tot_len, "%+d", nTotalCharge_Prev );
2477
+ }
2478
+ /* else charge is not present in pINChI_Prev */
2479
+ } else
2480
+ if ( bSecondNonTautPass && pINChI_Taut_Prev && pINChI_Taut_Prev->nNumberOfAtoms && !pINChI_Taut_Prev->bDeleted ) {
2481
+ if ( nTotalCharge_Taut_Prev = pINChI_Taut_Prev->nTotalCharge ) {
2482
+ /* since pINChI_Prev does not exist, pINChI_Taut_Prev is non-tautomeric */
2483
+ /* and it has charge info. This info has already been printed in the main section */
2484
+ /*
2485
+ tot_len += MakeDelim( sIdenticalValues, pStr + tot_len, nStrLen-tot_len, bOverflow);
2486
+ */
2487
+ ; /* pINChI_Taut_Prev sp3 info was output in the main stereo section */
2488
+ } else {
2489
+ ; /* pINChI_Taut_Prev exists and has not sp3 info */
2490
+ }
2491
+ }
2492
+ #if( bRELEASE_VERSION != 1 && defined(_DEBUG) )
2493
+ else {
2494
+ int stop = 1; /* <BRKPT> */
2495
+ }
2496
+ #endif
2497
+ }
2498
+ pINChI_Prev = pINChI;
2499
+ pINChI_Taut_Prev = pINChI_Taut;
2500
+ mult = 0; /* we do not know whether the item is empty */
2501
+ }
2502
+ }
2503
+ return tot_len;
2504
+ }
2505
+ /***************************************************************************/
2506
+ int str_FixedH_atoms(INCHI_SORT *pINChISort, char *pStr, int nStrLen, int tot_len,
2507
+ int *bOverflow, int bOutType, int ATOM_MODE, int num_components, int bUseMulipliers)
2508
+ {
2509
+ int i, j, ii, nNumEmpty;
2510
+ INCHI_SORT *is;
2511
+ INChI *pINChI, *pINChI_Prev;
2512
+ int mult, eq2prev, bNext, bNotEmpty, tot_len_inp;
2513
+
2514
+ is = pINChISort;
2515
+ i = 0;
2516
+ pINChI_Prev = (0 <= (ii=GET_II(bOutType,is)))? is->pINChI[ii] : NULL;
2517
+ mult = 0;
2518
+ bNext = 0;
2519
+ nNumEmpty = 0;
2520
+ tot_len_inp = tot_len;
2521
+ for ( i++, is++; i <= num_components; i ++, is ++ ) {
2522
+ /* only non-tautomeric representation of tautomeric */
2523
+ pINChI = (i < num_components && 0 <= (ii=GET_II(bOutType,is)))? is->pINChI[ii] : NULL;
2524
+ /*================ compare fixed H to previous =====================*/
2525
+ eq2prev =bUseMulipliers &&
2526
+ pINChI && pINChI_Prev && pINChI->nNumberOfAtoms > 0 &&
2527
+ pINChI_Prev->nNumberOfAtoms==pINChI->nNumberOfAtoms &&
2528
+ !memcmp( pINChI_Prev->nNum_H_fixed, pINChI->nNum_H_fixed,
2529
+ pINChI_Prev->nNumberOfAtoms*sizeof(pINChI->nNum_H_fixed[0]) );
2530
+ if ( eq2prev ) {
2531
+ /* make sure it is not empty */
2532
+ eq2prev = 0;
2533
+ for ( j = 0; j < pINChI_Prev->nNumberOfAtoms; j ++ ) {
2534
+ if ( pINChI_Prev->nNum_H_fixed[j] ) {
2535
+ eq2prev = 1;
2536
+ break;
2537
+ }
2538
+ }
2539
+ }
2540
+ if ( eq2prev ) {
2541
+ mult ++; /* mult = (number of non-empty equal items)-1 */
2542
+ continue;
2543
+ } else {
2544
+ /* print pINChI_Prev */
2545
+ /* delimiter */
2546
+ if ( bNext ++ ) {
2547
+ tot_len += MakeDelim( sCompDelim, pStr + tot_len, nStrLen-tot_len, bOverflow);
2548
+ }
2549
+ if ( pINChI_Prev ) {
2550
+ /* verify it is not empty */
2551
+ bNotEmpty = 0;
2552
+ for ( j = 0; j < pINChI_Prev->nNumberOfAtoms; j ++ ) {
2553
+ if ( pINChI_Prev->nNum_H_fixed[j] ) {
2554
+ bNotEmpty = 1;
2555
+ break;
2556
+ }
2557
+ }
2558
+ if ( bNotEmpty ) {
2559
+ tot_len += MakeMult( mult+1, "*", pStr + tot_len, nStrLen-tot_len, 0, bOverflow);
2560
+ /* H-atoms-fixed */
2561
+ tot_len += MakeHString( 0, pINChI_Prev->nNum_H_fixed, pINChI_Prev->nNumberOfAtoms,
2562
+ pStr + tot_len, nStrLen-tot_len, ATOM_MODE, bOverflow );
2563
+ } else {
2564
+ nNumEmpty ++;
2565
+ }
2566
+ }
2567
+ }
2568
+ pINChI_Prev = pINChI;
2569
+ mult = 0; /* we do not know whether the item is empty */
2570
+ }
2571
+ if ( nNumEmpty == num_components && tot_len > tot_len_inp ) {
2572
+ tot_len = tot_len_inp;
2573
+ pStr[tot_len] = '\0';
2574
+ }
2575
+ return tot_len;
2576
+ }
2577
+ /***************************************************************************/
2578
+ int str_AuxNumb(INCHI_SORT *pINChISort, INCHI_SORT *pINChISort2, char *pStr, int nStrLen, int tot_len,
2579
+ int *bOverflow, int bOutType, int TAUT_MODE, int num_components,
2580
+ int bSecondNonTautPass, int bOmitRepetitions)
2581
+ {
2582
+ int i, ii, ii2;
2583
+ INCHI_SORT *is, *is2;
2584
+ INChI *pINChI, *pINChI_Taut;
2585
+ INChI_Aux *pINChI_Aux, *pINChI_Aux_Taut;
2586
+ int eq2taut, bNext;
2587
+ const char *pPrevEquStr, *pCurrEquStr;
2588
+ int multPrevEquStr;
2589
+ bNext = 0;
2590
+ is2 = bSecondNonTautPass? pINChISort2 : NULL;
2591
+ eq2taut = 0; /* may be non-zero if another layer of the current component = current layer */
2592
+ pPrevEquStr = NULL; /*, *pCurrEquStr;*/
2593
+ multPrevEquStr = 0;
2594
+ if ( !(is = pINChISort) ) {
2595
+ return tot_len;
2596
+ }
2597
+ for ( i = 0; i < num_components; i ++, is ++, (bSecondNonTautPass? is2++ : 0) ) {
2598
+ /* 1st (taut) pass: bOutType=OUT_TN ; 2nd (non-taut pass) bOutType=OUT_NT */
2599
+ pINChI = ( 0 <= (ii=GET_II(bOutType,is)))? is->pINChI[ii] : NULL;
2600
+ pINChI_Aux = pINChI? is->pINChI_Aux[ii] : NULL;
2601
+ /*================ to compare to previously printed =====================*/
2602
+ if ( bSecondNonTautPass ) {
2603
+ /* component that was printed on the 1st pass */
2604
+ pINChI_Taut = (0 <= (ii2=GET_II(OUT_T1,is)))? is->pINChI[ii2] : NULL;
2605
+ pINChI_Aux_Taut = pINChI_Taut? is->pINChI_Aux[ii2] : NULL;
2606
+ }
2607
+ eq2taut = 0;
2608
+ /*========= if bSecondNonTautPass then compare iso non-taut stereo to other stereo ========*/
2609
+ if ( bSecondNonTautPass && bOmitRepetitions && pINChI && pINChI_Aux && pINChI_Aux->nNumberOfAtoms > 0 ) {
2610
+ /* compare non-tautomeric numbering to:
2611
+ * a) tautomeric numbering
2612
+ */
2613
+ /* a) compare non-tautomeric numbering to tautomeric numbering */
2614
+ if ( !eq2taut ) {
2615
+ eq2taut = pINChI_Taut && !pINChI_Taut->bDeleted &&
2616
+ Eql_INChI_Aux_Num( pINChI_Aux, EQL_NUM, pINChI_Aux_Taut, EQL_NUM );
2617
+ /* numbering non-taut = taut numbering */
2618
+ eq2taut = eq2taut? ( iiNUMB | iitNONTAUT ) : 0;
2619
+ }
2620
+ }
2621
+ if ( eq2taut ) {
2622
+ /* we have found another (previously printed) layer of the current component equal to this layer */
2623
+ /* output this (current) equivalence mark = EquString(eq2taut) */
2624
+ pCurrEquStr = EquString(eq2taut);
2625
+ if ( multPrevEquStr && pPrevEquStr ) {
2626
+ if ( pCurrEquStr && !strcmp(pCurrEquStr, pPrevEquStr) ) {
2627
+ multPrevEquStr ++;
2628
+ } else {
2629
+ /* new EqStr is different; output it */
2630
+ if ( bNext ++ ) {
2631
+ tot_len += MakeDelim( sCompDelim, pStr + tot_len, nStrLen-tot_len, bOverflow);
2632
+ }
2633
+ tot_len += MakeEqStr( pPrevEquStr, multPrevEquStr, pStr + tot_len, nStrLen-tot_len, bOverflow);
2634
+ pPrevEquStr = pCurrEquStr;
2635
+ multPrevEquStr = 1;
2636
+ }
2637
+ } else {
2638
+ pPrevEquStr = pCurrEquStr;
2639
+ multPrevEquStr = 1;
2640
+ }
2641
+ } else {
2642
+ /* current layer is different from previously printed layers of the current component */
2643
+ if ( multPrevEquStr && pPrevEquStr ) {
2644
+ /* new EqStr is different; output it */
2645
+ if ( bNext ++ ) {
2646
+ tot_len += MakeDelim( sCompDelim, pStr + tot_len, nStrLen-tot_len, bOverflow);
2647
+ }
2648
+ tot_len += MakeEqStr( pPrevEquStr, multPrevEquStr, pStr + tot_len, nStrLen-tot_len, bOverflow);
2649
+ pPrevEquStr = NULL;
2650
+ multPrevEquStr = 0;
2651
+ }
2652
+ if ( bNext ++ ) {
2653
+ tot_len += MakeDelim( sCompDelim, pStr + tot_len, nStrLen-tot_len, bOverflow);
2654
+ }
2655
+ if ( pINChI && pINChI_Aux && pINChI_Aux->nNumberOfAtoms ) {
2656
+ tot_len += MakeCtString( pINChI_Aux->nOrigAtNosInCanonOrd,
2657
+ pINChI_Aux->nNumberOfAtoms, 0, NULL, 0,
2658
+ pStr + tot_len, nStrLen-tot_len, TAUT_MODE, bOverflow);
2659
+ }
2660
+ }
2661
+ }
2662
+ if ( multPrevEquStr && pPrevEquStr ) {
2663
+ /* the new EqStr of the last item has not been printed; output it now */
2664
+ if ( bNext ++ ) {
2665
+ tot_len += MakeDelim( sCompDelim, pStr + tot_len, nStrLen-tot_len, bOverflow);
2666
+ }
2667
+ tot_len += MakeEqStr( pPrevEquStr, multPrevEquStr, pStr + tot_len, nStrLen-tot_len, bOverflow);
2668
+ pPrevEquStr = NULL;
2669
+ multPrevEquStr = 0;
2670
+ }
2671
+ return tot_len;
2672
+ }
2673
+ /***************************************************************************/
2674
+ int str_AuxTgroupEqu(INCHI_SORT *pINChISort, char *pStr, int nStrLen, int tot_len,
2675
+ int *bOverflow, int bOutType, int TAUT_MODE, int num_components, int bUseMulipliers)
2676
+ {
2677
+ int i, ii;
2678
+ INCHI_SORT *is;
2679
+ INChI_Aux *pINChI_Aux, *pINChI_Aux_Prev;
2680
+ int mult, eq2prev, bNext;
2681
+
2682
+ is = pINChISort;
2683
+ i = 0;
2684
+ pINChI_Aux_Prev = (0 <= (ii=GET_II(bOutType,is)))? is->pINChI_Aux[ii] : NULL;
2685
+ mult = 0;
2686
+ bNext = 0;
2687
+ for ( i++, is++; i <= num_components; i ++, is ++ ) {
2688
+ pINChI_Aux = (i < num_components && 0 <= (ii=GET_II(bOutType,is)))? is->pINChI_Aux[ii] : NULL;
2689
+ eq2prev = bUseMulipliers &&
2690
+ Eql_INChI_Aux_Equ( pINChI_Aux, EQL_EQU_TG, pINChI_Aux_Prev, EQL_EQU_TG );
2691
+ if ( eq2prev ) {
2692
+ mult ++; /* mult = (number of non-empty equal items)-1 */
2693
+ continue;
2694
+ } else {
2695
+ if ( bNext ++ ) {
2696
+ tot_len += MakeDelim( sCompDelim, pStr + tot_len, nStrLen-tot_len, bOverflow);
2697
+ }
2698
+ if ( pINChI_Aux_Prev && pINChI_Aux_Prev->nNumberOfTGroups &&
2699
+ bHasEquString( pINChI_Aux_Prev->nConstitEquTGroupNumbers, pINChI_Aux_Prev->nNumberOfTGroups) ) {
2700
+ tot_len += MakeMult( mult+1, "*", pStr + tot_len, nStrLen-tot_len, 0, bOverflow);
2701
+ tot_len += MakeEquString( pINChI_Aux_Prev->nConstitEquTGroupNumbers, pINChI_Aux_Prev->nNumberOfTGroups, 0,
2702
+ pStr + tot_len, nStrLen-tot_len, TAUT_MODE, bOverflow);
2703
+ }
2704
+ }
2705
+ pINChI_Aux_Prev = pINChI_Aux;
2706
+ mult = 0; /* we do not know whether the item is empty */
2707
+ }
2708
+ return tot_len;
2709
+ }
2710
+
2711
+ /***************************************************************************/
2712
+ int str_AuxChargeRadVal(INCHI_SORT *pINChISort, char *pStr, int nStrLen, int tot_len,
2713
+ int *bOverflow, int bOutType, int TAUT_MODE, int num_components, int bUseMulipliers)
2714
+ {
2715
+ int i, ii;
2716
+ INCHI_SORT *is;
2717
+ INChI_Aux *pINChI_Aux, *pINChI_Aux_Prev;
2718
+ int mult, eq2prev, bNext;
2719
+
2720
+ pINChI_Aux_Prev = NULL;
2721
+ mult = 0;
2722
+ bNext = 0;
2723
+ for ( i = 0, is = pINChISort; i <= num_components; i ++, is ++ ) {
2724
+ /* 1st (taut) pass: bOutType=OUT_TN ; 2nd (non-taut pass) bOutType=OUT_NT */
2725
+ pINChI_Aux = (i < num_components && 0 <= (ii=GET_II(bOutType,is)))? is->pINChI_Aux[ii] : NULL;
2726
+ /* check whether pINChI_Aux and pINChI_Aux_Prev have identical info */
2727
+ eq2prev = bUseMulipliers &&
2728
+ EqlOrigInfo( pINChI_Aux, pINChI_Aux_Prev );
2729
+ if ( eq2prev ) {
2730
+ /* eq. info is same and non-trivial */
2731
+ mult ++; /* mult = (number of non-empty equal items)-1 */
2732
+ continue;
2733
+ } else
2734
+ if ( i ) {
2735
+ /* pINChI_Aux info is either different or trivial. Output pINChI_Aux_Prev anyway */
2736
+ if ( bNext ++ ) {
2737
+ tot_len += MakeDelim( sCompDelim, pStr + tot_len, nStrLen-tot_len, bOverflow);
2738
+ }
2739
+ if ( pINChI_Aux_Prev && pINChI_Aux_Prev->nNumberOfAtoms ) {
2740
+ if ( bHasOrigInfo( pINChI_Aux_Prev->OrigInfo, pINChI_Aux_Prev->nNumberOfAtoms ) ) {
2741
+ /* pINChI_Aux_Prev exists and has orig. info info */
2742
+ tot_len += MakeMult( mult+1, "*", pStr + tot_len, nStrLen-tot_len, 0, bOverflow);
2743
+ tot_len += MakeCRVString( pINChI_Aux_Prev->OrigInfo, pINChI_Aux_Prev->nNumberOfAtoms, 0,
2744
+ pStr + tot_len, nStrLen-tot_len, TAUT_MODE, bOverflow);
2745
+ } else {
2746
+ ; /* pINChI_Aux_Prev exists and has only trivial info */
2747
+ }
2748
+ }
2749
+ #if( bRELEASE_VERSION != 1 && defined(_DEBUG) )
2750
+ else {
2751
+ int stop = 1; /* <BRKPT> */
2752
+ }
2753
+ #endif
2754
+ }
2755
+ pINChI_Aux_Prev = pINChI_Aux;
2756
+ mult = 0; /* we do not know whether the item is empty */
2757
+ }
2758
+ return tot_len;
2759
+ }
2760
+ /******************************************************************************************/
2761
+ int bin_AuxTautTrans(INCHI_SORT *pINChISort, INCHI_SORT *pINChISort2,
2762
+ AT_NUMB **pTrans_n, AT_NUMB **pTrans_s, int bOutType, int num_components)
2763
+ {
2764
+ int i, ii, ii2, ret;
2765
+ INCHI_SORT *is, *is2;
2766
+ INChI *pINChI, *pINChI_Taut;
2767
+ AT_NUMB *nTrans_n = NULL;
2768
+ AT_NUMB *nTrans_s = NULL;
2769
+
2770
+ ret = 0;
2771
+ *pTrans_n = NULL;
2772
+ *pTrans_s = NULL;
2773
+ /* pass 1: save new non-taut numbering */
2774
+ for ( i = 0, is = pINChISort, is2 = pINChISort2; i < num_components; i ++, is ++, is2 ++ ) {
2775
+ pINChI = ( 0 <= (ii=GET_II(bOutType,is)))? is->pINChI[ii] : NULL;
2776
+ pINChI_Taut = ( 0 <= (ii2=GET_II(OUT_T1,is2)))? is2->pINChI[ii2] : NULL;
2777
+ if ( pINChI && pINChI->nNumberOfAtoms > 0 &&
2778
+ pINChI_Taut && pINChI_Taut->nNumberOfAtoms > 0 &&
2779
+ /* different components save equal new ord. numbers: */
2780
+ is->ord_number != is2->ord_number ) {
2781
+ if ( (nTrans_n && nTrans_s) ||
2782
+ (nTrans_n = (AT_NUMB *)inchi_calloc( num_components+1, sizeof(nTrans_n[0]))) &&
2783
+ (nTrans_s = (AT_NUMB *)inchi_calloc( num_components+1, sizeof(nTrans_s[0]))) ) {
2784
+ /* new ordering number for original non-tautomeric component number is->ord_number */
2785
+ nTrans_n[is->ord_number] = /*nTrans_t[is2->ord_number] =*/ i+1;
2786
+ }
2787
+ }
2788
+ }
2789
+ if ( nTrans_n && nTrans_s ) {
2790
+ /* pass 2: get new taut numbering, retrieve new non-taut and save the transposition */
2791
+ for ( i = 0, is = pINChISort, is2 = pINChISort2; i < num_components; i ++, is ++, is2 ++ ) {
2792
+ pINChI = ( 0 <= (ii=GET_II(bOutType,is)))? is->pINChI[ii] : NULL;
2793
+ pINChI_Taut = ( 0 <= (ii2=GET_II(OUT_T1,is2)))? is2->pINChI[ii2] : NULL;
2794
+ if ( pINChI && pINChI->nNumberOfAtoms > 0 &&
2795
+ pINChI_Taut && pINChI_Taut->nNumberOfAtoms > 0 &&
2796
+ is->ord_number != is2->ord_number &&
2797
+ nTrans_n[is2->ord_number] ) {
2798
+ /* nTrans_n[is2->ord_number] is new ordering number of
2799
+ the non-taut representation of the tautomeric component
2800
+ that has new ord number i+1 and orig ordering number is2->ord_number.
2801
+ Old numbers start from 0, new start from 1
2802
+ */
2803
+
2804
+ /* n = nTrans_s[t]: taut component #t is in position #n of the non-taut representation */
2805
+ nTrans_s[i+1] = nTrans_n[is2->ord_number];
2806
+ }
2807
+ }
2808
+ *pTrans_n = nTrans_n;
2809
+ *pTrans_s = nTrans_s;
2810
+ ret = 1;
2811
+ } else {
2812
+ if ( nTrans_n ) {
2813
+ inchi_free( nTrans_n );
2814
+ ret = -1;
2815
+ }
2816
+ if ( nTrans_s ) {
2817
+ inchi_free( nTrans_s );
2818
+ ret = -1;
2819
+ }
2820
+ }
2821
+ return ret;
2822
+ }
2823
+ /******************************************************************************************/
2824
+ int str_AuxTautTrans(AT_NUMB *nTrans_n, AT_NUMB *nTrans_s, char *pStr, int nStrLen, int tot_len,
2825
+ int *bOverflow, int TAUT_MODE, int num_components)
2826
+ {
2827
+ int i, k, len, j;
2828
+
2829
+ if ( nTrans_n && nTrans_s ) {
2830
+ /* print the transposition, cycle after cycle */
2831
+ for ( i = 1; i <= num_components; i ++ ) {
2832
+ if ( nTrans_s[i] ) {
2833
+ /* get one cycle of the transposition */
2834
+ for ( j = i, len = 0; (k = nTrans_s[j]); j = k, len ++ ) {
2835
+ nTrans_n[len] = j; /* save the transposition */
2836
+ nTrans_s[j] = 0; /* clear used element to avoid repetitions */
2837
+ }
2838
+ /* print one cycle of the transposition */
2839
+ tot_len += MakeDelim( "(", pStr + tot_len, nStrLen-tot_len, bOverflow);
2840
+ tot_len += MakeCtString( nTrans_n, len, 0, NULL, 0,
2841
+ pStr + tot_len, nStrLen-tot_len, TAUT_MODE, bOverflow);
2842
+ tot_len += MakeDelim( ")", pStr + tot_len, nStrLen-tot_len, bOverflow);
2843
+ }
2844
+ }
2845
+ }
2846
+ if ( nTrans_n )
2847
+ inchi_free( nTrans_n );
2848
+ if ( nTrans_s )
2849
+ inchi_free( nTrans_s );
2850
+ return tot_len;
2851
+ }
2852
+ /***************************************************************************/
2853
+ int str_StereoAbsInv(INCHI_SORT *pINChISort, char *pStr, int nStrLen, int tot_len,
2854
+ int *bOverflow, int bOutType, int num_components)
2855
+ {
2856
+ int i, j, ii;
2857
+ INCHI_SORT *is;
2858
+ INChI_Stereo *Stereo;
2859
+ INChI *pINChI;
2860
+
2861
+ for ( i = 0, is = pINChISort; !*bOverflow && i < num_components; i ++, is ++ ) {
2862
+ pINChI = (0 <= (ii=GET_II(bOutType,is)))? is->pINChI[ii] : NULL;
2863
+ if ( pINChI && (Stereo = pINChI->Stereo) && (j=Stereo->nCompInv2Abs) ) {
2864
+ tot_len += MakeDelim( j<0? "1":"0", pStr + tot_len, nStrLen-tot_len, bOverflow);
2865
+ } else {
2866
+ tot_len += MakeDelim( ".", pStr + tot_len, nStrLen-tot_len, bOverflow);
2867
+ }
2868
+ }
2869
+
2870
+ return tot_len;
2871
+ }
2872
+ /***************************************************************************/
2873
+ int str_IsoStereoAbsInv(INCHI_SORT *pINChISort, char *pStr, int nStrLen, int tot_len,
2874
+ int *bOverflow, int bOutType, int num_components)
2875
+ {
2876
+ int i, j, ii;
2877
+ INCHI_SORT *is;
2878
+ INChI_Stereo *Stereo;
2879
+ INChI *pINChI;
2880
+
2881
+ for ( i = 0, is = pINChISort; !*bOverflow && i < num_components; i ++, is ++ ) {
2882
+ pINChI = (0 <= (ii=GET_II(bOutType,is)))? is->pINChI[ii] : NULL;
2883
+ if ( pINChI && (Stereo = pINChI->StereoIsotopic) && (j=Stereo->nCompInv2Abs) ) {
2884
+ tot_len += MakeDelim( j<0? "1":"0", pStr + tot_len, nStrLen-tot_len, bOverflow);
2885
+ } else {
2886
+ tot_len += MakeDelim( ".", pStr + tot_len, nStrLen-tot_len, bOverflow);
2887
+ }
2888
+ }
2889
+
2890
+ return tot_len;
2891
+ }
2892
+ /***************************************************************************/
2893
+ int str_AuxIsoTgroupEqu(INCHI_SORT *pINChISort, char *pStr, int nStrLen, int tot_len,
2894
+ int *bOverflow, int bOutType, int TAUT_MODE, int num_components, int bOmitRepetitions, int bUseMulipliers)
2895
+ {
2896
+ int i, ii;
2897
+ INCHI_SORT *is;
2898
+ INChI_Aux *pINChI_Aux, *pINChI_Aux_Prev;
2899
+ int mult, eq2prev, eq2taut, eq2tautPrev, bNext;
2900
+ const char *pPrevEquStr, *pCurrEquStr;
2901
+ int multPrevEquStr;
2902
+ pINChI_Aux = NULL;
2903
+ pINChI_Aux_Prev = NULL;
2904
+ mult = 0;
2905
+ bNext = 0;
2906
+ eq2taut = 0; /* equal to non-isotopic equivalence */
2907
+ eq2tautPrev = 1; /* pINChI_Aux_Prev (previous pINChI_Aux) does not exist */
2908
+ pPrevEquStr = NULL; /*, *pCurrEquStr;*/
2909
+ multPrevEquStr = 0;
2910
+ for ( i = 0, is = pINChISort; i <= num_components; i ++, is ++ ) {
2911
+ /* 1st (taut) pass: bOutType=OUT_TN ; 2nd (non-taut pass) bOutType=OUT_NT */
2912
+ pINChI_Aux = (i < num_components && 0 <= (ii=GET_II(bOutType,is)))? is->pINChI_Aux[ii] : NULL;
2913
+ /*================ compare iso non-taut equivalence info to non-iso taut ========*/
2914
+ eq2taut = 0;
2915
+ if ( bOmitRepetitions && pINChI_Aux && pINChI_Aux->bIsIsotopic ) {
2916
+ /**************************************************
2917
+ * compare isotopic tautomeric equivalence to:
2918
+ * a) non-isotopic tautomeric
2919
+ */
2920
+ /* compare isotopic t-group equivalence to non-isotopic */
2921
+ eq2taut = Eql_INChI_Aux_Equ( pINChI_Aux, EQL_EQU_TG | EQL_EQU_ISO, pINChI_Aux, EQL_EQU_TG );
2922
+ /* equ taut-isotopic = tautomeric, same as for isotopic atom equivalence info*/
2923
+ eq2taut = eq2taut? (iiEQU | iitISO) : 0;
2924
+ }
2925
+ if ( eq2taut ) {
2926
+ /* current isotopic t-group equivalence has been found to be same as non-isotopic */
2927
+ if ( pINChI_Aux_Prev && pINChI_Aux_Prev->nNumberOfAtoms ) {
2928
+ /* previous component exists */
2929
+ if ( bNext ++ ) {
2930
+ tot_len += MakeDelim( sCompDelim, pStr + tot_len, nStrLen-tot_len, bOverflow);
2931
+ }
2932
+ if ( bHasEquString( pINChI_Aux_Prev->nConstitEquIsotopicTGroupNumbers, pINChI_Aux_Prev->nNumberOfTGroups) ) {
2933
+ /* output previous component(s) equivalence since it was found to be non-trivial */
2934
+ tot_len += MakeMult( mult+1, "*", pStr + tot_len, nStrLen-tot_len, 0, bOverflow);
2935
+ tot_len += MakeEquString( pINChI_Aux_Prev->nConstitEquIsotopicTGroupNumbers, pINChI_Aux_Prev->nNumberOfTGroups, 0,
2936
+ pStr + tot_len, nStrLen-tot_len, TAUT_MODE, bOverflow);
2937
+ } else {
2938
+ ; /* pINChI_Aux_Prev exists and does not have non-trivial t-group equivalence info */
2939
+ }
2940
+ }
2941
+ /* we have found pINChI_Aux->pINChI_Aux->nConstitEquIsotopicTGroupNumbers same as in pINChI_Aux->nConstitEquTGroupNumbers */
2942
+ pCurrEquStr = EquString(eq2taut);
2943
+ if ( multPrevEquStr && pPrevEquStr ) {
2944
+ if ( pCurrEquStr && !strcmp(pCurrEquStr, pPrevEquStr) ) {
2945
+ multPrevEquStr ++;
2946
+ } else {
2947
+ /* new EqStr is different; output it */
2948
+ if ( bNext ++ ) {
2949
+ tot_len += MakeDelim( sCompDelim, pStr + tot_len, nStrLen-tot_len, bOverflow);
2950
+ }
2951
+ tot_len += MakeEqStr( pPrevEquStr, multPrevEquStr, pStr + tot_len, nStrLen-tot_len, bOverflow);
2952
+ pPrevEquStr = pCurrEquStr;
2953
+ multPrevEquStr = 1;
2954
+ }
2955
+ } else {
2956
+ pPrevEquStr = pCurrEquStr;
2957
+ multPrevEquStr = 1;
2958
+ }
2959
+ pINChI_Aux_Prev = NULL; /* pINChI_Aux_Prev has already been output */
2960
+ mult = 0;
2961
+ eq2tautPrev = 1;
2962
+ } else
2963
+ if ( eq2tautPrev ) {
2964
+ /* at this point pINChI_Aux_Prev does not exist; however, pINChI_Aux */
2965
+ /* might have been discovered and it may be different from non-isotopic */
2966
+ if ( multPrevEquStr && pPrevEquStr ) {
2967
+ /* new EqStr is different; output it */
2968
+ if ( bNext ++ ) {
2969
+ tot_len += MakeDelim( sCompDelim, pStr + tot_len, nStrLen-tot_len, bOverflow);
2970
+ }
2971
+ tot_len += MakeEqStr( pPrevEquStr, multPrevEquStr, pStr + tot_len, nStrLen-tot_len, bOverflow);
2972
+ pPrevEquStr = NULL;
2973
+ multPrevEquStr = 0;
2974
+ }
2975
+ eq2tautPrev = 0;
2976
+ pINChI_Aux_Prev = pINChI_Aux;
2977
+ mult = 0;
2978
+ } else {
2979
+ /* check whether pINChI_Aux and pINChI_Aux_Prev have identical non-trivial isotopic t-group equivalence info */
2980
+ eq2prev = bUseMulipliers && Eql_INChI_Aux_Equ( pINChI_Aux, EQL_EQU_TG | EQL_EQU_ISO, pINChI_Aux_Prev, EQL_EQU_TG | EQL_EQU_ISO );
2981
+ if ( eq2prev ) {
2982
+ /* eq. info is same and non-trivial */
2983
+ mult ++; /* mult = (number of non-empty equal items)-1 */
2984
+ continue;
2985
+ } else {
2986
+ /* pINChI_Aux eq. info is either different or trivial. Output pINChI_Aux_Prev anyway */
2987
+ if ( bNext ++ ) {
2988
+ tot_len += MakeDelim( sCompDelim, pStr + tot_len, nStrLen-tot_len, bOverflow);
2989
+ }
2990
+ if ( pINChI_Aux_Prev && pINChI_Aux_Prev->nNumberOfAtoms ) {
2991
+ if ( bHasEquString( pINChI_Aux_Prev->nConstitEquIsotopicTGroupNumbers, pINChI_Aux_Prev->nNumberOfTGroups) ) {
2992
+ /* pINChI_Aux_Prev exists and has equivalence info */
2993
+ tot_len += MakeMult( mult+1, "*", pStr + tot_len, nStrLen-tot_len, 0, bOverflow);
2994
+ tot_len += MakeEquString( pINChI_Aux_Prev->nConstitEquIsotopicTGroupNumbers, pINChI_Aux_Prev->nNumberOfTGroups, 0,
2995
+ pStr + tot_len, nStrLen-tot_len, TAUT_MODE, bOverflow);
2996
+ } else {
2997
+ ; /* pINChI_Aux_Prev exists and has only trivial equivalence info */
2998
+ }
2999
+ }
3000
+ #if( bRELEASE_VERSION != 1 && defined(_DEBUG) )
3001
+ else {
3002
+ int stop = 1; /* <BRKPT> */
3003
+ }
3004
+ #endif
3005
+ }
3006
+ pINChI_Aux_Prev = pINChI_Aux;
3007
+ mult = 0; /* we do not know whether the item is empty */
3008
+ }
3009
+ }
3010
+ return tot_len;
3011
+ }