rino 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/README +44 -0
- data/Rakefile +123 -0
- data/ext/extconf.rb +26 -0
- data/ext/ruby_inchi_main.so +0 -0
- data/ext/src/aux2atom.h +2786 -0
- data/ext/src/comdef.h +148 -0
- data/ext/src/e_0dstereo.c +3014 -0
- data/ext/src/e_0dstereo.h +31 -0
- data/ext/src/e_comdef.h +57 -0
- data/ext/src/e_ctl_data.h +147 -0
- data/ext/src/e_ichi_io.c +498 -0
- data/ext/src/e_ichi_io.h +40 -0
- data/ext/src/e_ichi_parms.c +37 -0
- data/ext/src/e_ichi_parms.h +41 -0
- data/ext/src/e_ichicomp.h +50 -0
- data/ext/src/e_ichierr.h +40 -0
- data/ext/src/e_ichimain.c +593 -0
- data/ext/src/e_ichisize.h +43 -0
- data/ext/src/e_inchi_atom.c +75 -0
- data/ext/src/e_inchi_atom.h +33 -0
- data/ext/src/e_inpdef.h +41 -0
- data/ext/src/e_mode.h +706 -0
- data/ext/src/e_mol2atom.c +649 -0
- data/ext/src/e_readinch.c +58 -0
- data/ext/src/e_readmol.c +54 -0
- data/ext/src/e_readmol.h +180 -0
- data/ext/src/e_readstru.c +251 -0
- data/ext/src/e_readstru.h +33 -0
- data/ext/src/e_util.c +284 -0
- data/ext/src/e_util.h +61 -0
- data/ext/src/extr_ct.h +251 -0
- data/ext/src/ichi.h +206 -0
- data/ext/src/ichi_bns.c +7999 -0
- data/ext/src/ichi_bns.h +231 -0
- data/ext/src/ichican2.c +5000 -0
- data/ext/src/ichicano.c +2195 -0
- data/ext/src/ichicano.h +49 -0
- data/ext/src/ichicans.c +1625 -0
- data/ext/src/ichicant.h +379 -0
- data/ext/src/ichicomn.h +260 -0
- data/ext/src/ichicomp.h +50 -0
- data/ext/src/ichidrp.h +119 -0
- data/ext/src/ichierr.h +124 -0
- data/ext/src/ichiisot.c +101 -0
- data/ext/src/ichilnct.c +286 -0
- data/ext/src/ichimain.h +132 -0
- data/ext/src/ichimak2.c +1189 -0
- data/ext/src/ichimake.c +3812 -0
- data/ext/src/ichimake.h +205 -0
- data/ext/src/ichimap1.c +851 -0
- data/ext/src/ichimap2.c +2856 -0
- data/ext/src/ichimap4.c +1609 -0
- data/ext/src/ichinorm.c +741 -0
- data/ext/src/ichinorm.h +67 -0
- data/ext/src/ichiparm.c +45 -0
- data/ext/src/ichiparm.h +1441 -0
- data/ext/src/ichiprt1.c +3612 -0
- data/ext/src/ichiprt2.c +1511 -0
- data/ext/src/ichiprt3.c +3011 -0
- data/ext/src/ichiqueu.c +1003 -0
- data/ext/src/ichiring.c +326 -0
- data/ext/src/ichiring.h +49 -0
- data/ext/src/ichisize.h +35 -0
- data/ext/src/ichisort.c +539 -0
- data/ext/src/ichister.c +3538 -0
- data/ext/src/ichister.h +35 -0
- data/ext/src/ichitaut.c +3843 -0
- data/ext/src/ichitaut.h +387 -0
- data/ext/src/ichitime.h +74 -0
- data/ext/src/inchi_api.h +670 -0
- data/ext/src/inchi_dll.c +1480 -0
- data/ext/src/inchi_dll.h +34 -0
- data/ext/src/inchi_dll_main.c +23 -0
- data/ext/src/inchi_dll_main.h +31 -0
- data/ext/src/inpdef.h +328 -0
- data/ext/src/lreadmol.h +1246 -0
- data/ext/src/mode.h +706 -0
- data/ext/src/ruby_inchi_main.c +558 -0
- data/ext/src/runichi.c +4179 -0
- data/ext/src/strutil.c +3861 -0
- data/ext/src/strutil.h +182 -0
- data/ext/src/util.c +1130 -0
- data/ext/src/util.h +85 -0
- data/lib/clean_tempfile.rb +220 -0
- data/lib/rino.rb +111 -0
- data/test/test.rb +386 -0
- metadata +130 -0
data/ext/src/ichiprt3.c
ADDED
@@ -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
|
+
}
|