rino 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
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
+ }