rino 0.1.0 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (104) hide show
  1. data/Rakefile +1 -1
  2. data/ext/extconf.rb +1 -24
  3. data/ext/libinchi.so +0 -0
  4. data/ext/src/aux2atom.h +120 -39
  5. data/ext/src/comdef.h +3 -3
  6. data/ext/src/dispstru.c +2547 -0
  7. data/ext/src/dispstru.h +73 -0
  8. data/ext/src/extr_ct.h +5 -2
  9. data/ext/src/ichi.h +27 -11
  10. data/ext/src/ichi_bns.c +1800 -254
  11. data/ext/src/ichi_bns.h +205 -4
  12. data/ext/src/ichican2.c +197 -86
  13. data/ext/src/ichicano.c +8 -13
  14. data/ext/src/ichicano.h +2 -2
  15. data/ext/src/ichicans.c +11 -6
  16. data/ext/src/ichicant.h +2 -2
  17. data/ext/src/ichicomn.h +2 -2
  18. data/ext/src/ichicomp.h +19 -4
  19. data/ext/src/ichidrp.h +9 -5
  20. data/ext/src/ichierr.h +5 -3
  21. data/ext/src/ichiisot.c +2 -2
  22. data/ext/src/ichimain.c +461 -0
  23. data/ext/src/ichimain.h +23 -15
  24. data/ext/src/ichimak2.c +6 -6
  25. data/ext/src/ichimake.c +843 -42
  26. data/ext/src/ichimake.h +4 -2
  27. data/ext/src/ichimap1.c +5 -5
  28. data/ext/src/ichimap2.c +2 -2
  29. data/ext/src/ichimap4.c +34 -21
  30. data/ext/src/ichinorm.c +11 -5
  31. data/ext/src/ichinorm.h +3 -2
  32. data/ext/src/ichiparm.c +2 -2
  33. data/ext/src/ichiparm.h +232 -30
  34. data/ext/src/ichiprt1.c +35 -11
  35. data/ext/src/ichiprt2.c +78 -7
  36. data/ext/src/ichiprt3.c +300 -120
  37. data/ext/src/ichiqueu.c +17 -2
  38. data/ext/src/ichiread.c +6932 -0
  39. data/ext/src/ichiring.c +3 -2
  40. data/ext/src/ichiring.h +2 -2
  41. data/ext/src/ichirvr1.c +4891 -0
  42. data/ext/src/ichirvr2.c +6344 -0
  43. data/ext/src/ichirvr3.c +5499 -0
  44. data/ext/src/ichirvr4.c +3177 -0
  45. data/ext/src/ichirvr5.c +1166 -0
  46. data/ext/src/ichirvr6.c +1287 -0
  47. data/ext/src/ichirvr7.c +2319 -0
  48. data/ext/src/ichirvrs.h +882 -0
  49. data/ext/src/ichisize.h +2 -2
  50. data/ext/src/ichisort.c +5 -5
  51. data/ext/src/ichister.c +281 -86
  52. data/ext/src/ichister.h +9 -3
  53. data/ext/src/ichitaut.c +208 -9
  54. data/ext/src/ichitaut.h +13 -11
  55. data/ext/src/ichitime.h +16 -2
  56. data/ext/src/inchicmp.h +107 -0
  57. data/ext/src/inpdef.h +6 -3
  58. data/ext/src/libinchi_wrap.c +912 -0
  59. data/ext/src/lreadmol.h +34 -31
  60. data/ext/src/mode.h +244 -7
  61. data/ext/src/mol2atom.c +1060 -0
  62. data/ext/src/mol2atom.h +31 -0
  63. data/ext/src/readinch.c +239 -0
  64. data/ext/src/readmol.c +28 -0
  65. data/ext/src/{e_readmol.h → readmol.h} +7 -9
  66. data/ext/src/runichi.c +251 -177
  67. data/ext/src/strutil.c +444 -238
  68. data/ext/src/strutil.h +150 -11
  69. data/ext/src/util.c +176 -118
  70. data/ext/src/util.h +15 -3
  71. data/lib/rino.rb +71 -3
  72. data/test/test.rb +33 -4
  73. metadata +22 -34
  74. data/ext/ruby_inchi_main.so +0 -0
  75. data/ext/src/e_0dstereo.c +0 -3014
  76. data/ext/src/e_0dstereo.h +0 -31
  77. data/ext/src/e_comdef.h +0 -57
  78. data/ext/src/e_ctl_data.h +0 -147
  79. data/ext/src/e_ichi_io.c +0 -498
  80. data/ext/src/e_ichi_io.h +0 -40
  81. data/ext/src/e_ichi_parms.c +0 -37
  82. data/ext/src/e_ichi_parms.h +0 -41
  83. data/ext/src/e_ichicomp.h +0 -50
  84. data/ext/src/e_ichierr.h +0 -40
  85. data/ext/src/e_ichimain.c +0 -593
  86. data/ext/src/e_ichisize.h +0 -43
  87. data/ext/src/e_inchi_atom.c +0 -75
  88. data/ext/src/e_inchi_atom.h +0 -33
  89. data/ext/src/e_inpdef.h +0 -41
  90. data/ext/src/e_mode.h +0 -706
  91. data/ext/src/e_mol2atom.c +0 -649
  92. data/ext/src/e_readinch.c +0 -58
  93. data/ext/src/e_readmol.c +0 -54
  94. data/ext/src/e_readstru.c +0 -251
  95. data/ext/src/e_readstru.h +0 -33
  96. data/ext/src/e_util.c +0 -284
  97. data/ext/src/e_util.h +0 -61
  98. data/ext/src/ichilnct.c +0 -286
  99. data/ext/src/inchi_api.h +0 -670
  100. data/ext/src/inchi_dll.c +0 -1480
  101. data/ext/src/inchi_dll.h +0 -34
  102. data/ext/src/inchi_dll_main.c +0 -23
  103. data/ext/src/inchi_dll_main.h +0 -31
  104. data/ext/src/ruby_inchi_main.c +0 -558
@@ -2,8 +2,8 @@
2
2
  * International Union of Pure and Applied Chemistry (IUPAC)
3
3
  * International Chemical Identifier (InChI)
4
4
  * Version 1
5
- * Software version 1.00
6
- * April 13, 2005
5
+ * Software version 1.01
6
+ * July 21, 2006
7
7
  * Developed at NIST
8
8
  */
9
9
 
@@ -11,6 +11,7 @@
11
11
  #define __INCHIMAIN_H__
12
12
 
13
13
  #define ESC_KEY 27
14
+ #define INCHI_SEGM_BUFLEN 64000
14
15
 
15
16
  /********************************************************************/
16
17
  typedef struct tagStructData {
@@ -19,8 +20,8 @@ typedef struct tagStructData {
19
20
  int nErrorType;
20
21
  int nStructReadError;
21
22
  char pStrErrStruct[STR_ERR_LEN];
22
- long fPtrStart;
23
- long fPtrEnd;
23
+ long fPtrStart; /* or number of processed structures */
24
+ long fPtrEnd; /* or number of errors */
24
25
  int bXmlStructStarted;
25
26
  int bUserQuit;
26
27
  int bUserQuitComponent;
@@ -50,7 +51,7 @@ int ReadCommandLineParms( int argc, const char *argv[], INPUT_PARMS *ip, char *s
50
51
  void HelpCommandLineParms( INCHI_FILE *f );
51
52
  int OpenFiles( FILE **inp_file, FILE **output_file, FILE **log_file, FILE **prb_file, INPUT_PARMS *ip );
52
53
  #ifndef INCHI_ANSI_ONLY
53
- int DisplayStructure( inp_ATOM *at, int num_at, int num_removed_H, int nNumRemovedProtons, NUM_H nNumRemovedProtonsIsotopic[],
54
+ int DisplayStructure( inp_ATOM *at, int num_at, int num_removed_H, int bAdd_DT_to_num_H, int nNumRemovedProtons, NUM_H nNumRemovedProtonsIsotopic[],
54
55
  int bIsotopic, int j /*bTautomeric*/, INChI **cur_INChI, INChI_Aux **cur_INChI_Aux,
55
56
  int bAbcNumbers, DRAW_PARMS *dp, INCHI_MODE nMode, char *szTitle );
56
57
  void FillTableParms( SET_DRAW_PARMS *sdp, INChI **cur_INChI, INChI_Aux **cur_INChI_Aux, INCHI_MODE nMode, int bShowIsotopic, int bShowTaut );
@@ -65,7 +66,7 @@ int SortAndPrintINChI( INCHI_FILE *output_file, char *pStr, int nStrLen, INCHI_F
65
66
  ORIG_STRUCT *pOrigStruct, int num_components[INCHI_NUM],
66
67
  int num_non_taut[INCHI_NUM], int num_taut[INCHI_NUM],
67
68
  INCHI_MODE bTautFlags[INCHI_NUM], INCHI_MODE bTautFlagsDone[INCHI_NUM],
68
- NORM_CANON_FLAGS *pncFlags, int num_inp,
69
+ NORM_CANON_FLAGS *pncFlags, long num_inp,
69
70
  PINChI2 *pINChI[INCHI_NUM], PINChI_Aux2 *pINChI_Aux[INCHI_NUM], int *bSortPrintINChIFlags );
70
71
  void FreeAllINChIArrays( PINChI2 *pINChI[INCHI_NUM], PINChI_Aux2 *pINChI_Aux[INCHI_NUM], int num_components[2] );
71
72
  void FreeINChIArrays( PINChI2 *pINChI, PINChI_Aux2 *pINChI_Aux, int num_components );
@@ -75,24 +76,24 @@ int ReadTheStructure( STRUCT_DATA *sd, INPUT_PARMS *ip, FILE *inp_file, ORIG_ATO
75
76
  int inp_index, int *out_index );
76
77
  int TreatReadTheStructureErrors( STRUCT_DATA *sd, INPUT_PARMS *ip, int nLogMask,
77
78
  FILE *inp_file, INCHI_FILE *log_file, INCHI_FILE *output_file, INCHI_FILE *prb_file,
78
- ORIG_ATOM_DATA *orig_inp_data, int *num_inp, char *pStr, int nStrLen );
79
+ ORIG_ATOM_DATA *orig_inp_data, long *num_inp, char *pStr, int nStrLen );
79
80
 
80
81
  int GetOneComponent( STRUCT_DATA *sd, INPUT_PARMS *ip, INCHI_FILE *log_file, INCHI_FILE *output_file,
81
82
  INP_ATOM_DATA *inp_cur_data,
82
- ORIG_ATOM_DATA *orig_inp_data, int i, int num_inp, char *pStr, int nStrLen );
83
+ ORIG_ATOM_DATA *orig_inp_data, int i, long num_inp, char *pStr, int nStrLen );
83
84
  int CreateOneComponentINChI( STRUCT_DATA *sd, INPUT_PARMS *ip, INP_ATOM_DATA *inp_cur_data, ORIG_ATOM_DATA *orig_inp_data,
84
85
  PINChI2 *pINChI, PINChI_Aux2 *pINChI_Aux, int iINChI,
85
- int i, int num_inp, INP_ATOM_DATA **inp_norm_data,
86
+ int i, long num_inp, INP_ATOM_DATA **inp_norm_data,
86
87
  NORM_CANON_FLAGS *pncFlags, INCHI_FILE *log_file );
87
88
  int TreatCreateOneComponentINChIError(STRUCT_DATA *sd, INPUT_PARMS *ip, ORIG_ATOM_DATA *orig_inp_data,
88
- int i, int num_inp,
89
+ int i, long num_inp,
89
90
  FILE *inp_file, INCHI_FILE *log_file, INCHI_FILE *output_file, INCHI_FILE *prb_file,
90
91
  char *pStr, int nStrLen );
91
- int TreatCreateINChIWarning(STRUCT_DATA *sd, INPUT_PARMS *ip, ORIG_ATOM_DATA *orig_inp_data, int num_inp,
92
+ int TreatCreateINChIWarning(STRUCT_DATA *sd, INPUT_PARMS *ip, ORIG_ATOM_DATA *orig_inp_data, long num_inp,
92
93
  FILE *inp_file, INCHI_FILE *log_file, INCHI_FILE *output_file, INCHI_FILE *prb_file,
93
94
  char *pStr, int nStrLen );
94
95
 
95
- #if( TEST_RENUMB_ATOMS == 1 ) /* { */
96
+ #if( TEST_RENUMB_ATOMS == 1 || READ_INCHI_STRING == 1 ) /* { */
96
97
  int CompareINChI( INChI *i1, INChI *i2, INChI_Aux *a1, INChI_Aux *a2 );
97
98
  #endif
98
99
 
@@ -101,19 +102,19 @@ int user_quit( const char *msg, unsigned long ulMaxTime );
101
102
 
102
103
  int GetOneStructure( STRUCT_DATA *sd, INPUT_PARMS *ip, char *szTitle,
103
104
  FILE *inp_file, INCHI_FILE *log_file, INCHI_FILE *output_file, INCHI_FILE *prb_file,
104
- ORIG_ATOM_DATA *orig_inp_data, int *num_inp, char *pStr, int nStrLen, STRUCT_FPTRS *struct_fptrs );
105
+ ORIG_ATOM_DATA *orig_inp_data, long *num_inp, char *pStr, int nStrLen, STRUCT_FPTRS *struct_fptrs );
105
106
  int ProcessOneStructure( STRUCT_DATA *sd, INPUT_PARMS *ip, char *szTitle,
106
107
  PINChI2 *pINChI2[INCHI_NUM], PINChI_Aux2 *pINChI_Aux2[INCHI_NUM],
107
108
  FILE *inp_file, INCHI_FILE *log_file, INCHI_FILE *output_file, INCHI_FILE *prb_file,
108
109
  ORIG_ATOM_DATA *orig_inp_data, ORIG_ATOM_DATA *prep_inp_data,
109
- int num_inp, char *pStr, int nStrLen );
110
+ long num_inp, char *pStr, int nStrLen );
110
111
 
111
112
  int CreateOneStructureINChI( STRUCT_DATA *sd, INPUT_PARMS *ip, char *szTitle,
112
113
  PINChI2 *pINChI2[INCHI_NUM], PINChI_Aux2 *pINChI_Aux2[INCHI_NUM], int iINChI,
113
114
  FILE *inp_file, INCHI_FILE *log_file, INCHI_FILE *output_file, INCHI_FILE *prb_file,
114
115
  ORIG_ATOM_DATA *orig_inp_data, ORIG_ATOM_DATA *prep_inp_data,
115
116
  COMP_ATOM_DATA composite_norm_data2[][TAUT_NUM+1],
116
- int num_inp, char *pStr, int nStrLen, NORM_CANON_FLAGS *pncFlags );
117
+ long num_inp, char *pStr, int nStrLen, NORM_CANON_FLAGS *pncFlags );
117
118
 
118
119
  int bIsStructChiral( PINChI2 *pINChI2[INCHI_NUM], int num_components[] );
119
120
 
@@ -122,6 +123,13 @@ int PreprocessOneStructure( STRUCT_DATA *sd, INPUT_PARMS *ip, ORIG_ATOM_DATA *or
122
123
  int FillOutOrigStruct( ORIG_ATOM_DATA *orig_inp_data, ORIG_STRUCT *pOrigStruct, STRUCT_DATA *sd );
123
124
  void FreeOrigStruct( ORIG_STRUCT *pOrigStruct);
124
125
 
126
+ int ReadWriteInChI( INCHI_FILE *pInp, INCHI_FILE *pOut, INCHI_FILE *pLog,
127
+ INPUT_PARMS *ip, STRUCT_DATA *sd, inp_ATOM **at, int *num_at,
128
+ char *szMsg, int nMsgLen, unsigned long WarningFlags[2][2] );
129
+
130
+ int CompareHillFormulasNoH( const char *f1, const char *f2, int *num_H1, int *num_H2 );
131
+
132
+
125
133
  #ifndef INCHI_ALL_CPP
126
134
  #ifdef __cplusplus
127
135
  }
@@ -2,8 +2,8 @@
2
2
  * International Union of Pure and Applied Chemistry (IUPAC)
3
3
  * International Chemical Identifier (InChI)
4
4
  * Version 1
5
- * Software version 1.00
6
- * April 13, 2005
5
+ * Software version 1.01
6
+ * July 21, 2006
7
7
  * Developed at NIST
8
8
  */
9
9
 
@@ -94,7 +94,7 @@ int GetHillFormulaCounts( U_CHAR *nAtom, S_CHAR *nNum_H, int num_atoms,
94
94
  int *pnum_C, int *pnum_H, int *pnLen, int *pnNumNonHAtoms )
95
95
  {
96
96
  char szElement[4];
97
- U_CHAR nPrevAtom = (U_CHAR)-1;
97
+ U_CHAR nPrevAtom = (U_CHAR)-2;
98
98
  int bCarbon, bHydrogen, nElemLen, nFormLen, nNumNonHAtoms;
99
99
  int mult, i, num_H, num_C;
100
100
 
@@ -210,7 +210,7 @@ int MakeHillFormula( U_CHAR *nAtom, int num_atoms,
210
210
  nLen = 0;
211
211
  mult = 0;
212
212
  bOvfl = 0;
213
- nPrevAtom = (U_CHAR)-1; /* non-existent number */
213
+ nPrevAtom = (U_CHAR)-2; /* non-existent number */
214
214
 
215
215
 
216
216
  if ( num_C ) {
@@ -958,8 +958,8 @@ int FillOutINChI( INChI *pINChI, INChI_Aux *pINChI_Aux,
958
958
  /* Allocate and fill Hill formula */
959
959
  if ( !(pINChI->szHillFormula = AllocateAndFillHillFormula( pINChI ) ) ) {
960
960
  nErrorCode = 0;
961
- ret = CT_OUT_OF_RAM; /* <BRKPT> */
962
- pINChI->nErrorCode = pINChI_Aux->nErrorCode = CT_OUT_OF_RAM;
961
+ ret = CT_WRONG_FORMULA; /* CT_OUT_OF_RAM;*/ /* <BRKPT> */
962
+ pINChI->nErrorCode = pINChI_Aux->nErrorCode = ret;
963
963
  goto exit_function;
964
964
  }
965
965
 
@@ -2,8 +2,8 @@
2
2
  * International Union of Pure and Applied Chemistry (IUPAC)
3
3
  * International Chemical Identifier (InChI)
4
4
  * Version 1
5
- * Software version 1.00
6
- * April 13, 2005
5
+ * Software version 1.01
6
+ * July 21, 2006
7
7
  * Developed at NIST
8
8
  */
9
9
 
@@ -36,8 +36,8 @@
36
36
  int inp2spATOM( inp_ATOM *inp_at, int num_inp_at, sp_ATOM *at );
37
37
  int GetElementAndCount( const char **f, char *szEl, int *count );
38
38
  int CompareHillFormulas( const char *f1, const char *f2 );
39
- int CompareHillFormulasNoH( const char *f1, const char *f2, int *num_H1, int *num_H2 );
40
39
  int CompareInchiStereo( INChI_Stereo *Stereo1, INCHI_MODE nFlags1, INChI_Stereo *Stereo2, INCHI_MODE nFlags2 );
40
+ int CompareReversedStereoINChI( INChI_Stereo *s1/* InChI from reversed struct */, INChI_Stereo *s2 /* input InChI */);
41
41
  int GetAtomOrdNbrInCanonOrd( inp_ATOM *norm_at, AT_NUMB *nAtomOrdNbr,
42
42
  AT_NUMB *nOrigAtNosInCanonOrd, int num_at );
43
43
  int FillOutCanonInfAtom(inp_ATOM *norm_at, INF_ATOM_DATA *inf_norm_at_data, int init_num_at, int bIsotopic,
@@ -46,7 +46,7 @@ int FillOutOneCanonInfAtom(inp_ATOM *inp_norm_at, INF_ATOM_DATA *inf_norm_at_dat
46
46
  AT_NUMB *pStereoFlags, int init_num_at, int offset, int offset_H, int bIsotopic,
47
47
  INChI *pINChI, INChI_Aux *pINChI_Aux, int bAbcNumbers, INCHI_MODE nMode);
48
48
  int FillOutInputInfAtom(inp_ATOM *inp_at, INF_ATOM_DATA *inf_at_data, int init_num_at, int num_removed_H,
49
- int nNumRemovedProtons, NUM_H *nNumRemovedProtonsIsotopic, int bIsotopic, int bAbcNumbers);
49
+ int bAdd_DT_to_num_H, int nNumRemovedProtons, NUM_H *nNumRemovedProtonsIsotopic, int bIsotopic, int bAbcNumbers);
50
50
 
51
51
  int CheckCanonNumberingCorrectness(
52
52
  int num_atoms, int num_at_tg,
@@ -57,10 +57,16 @@ static int CompareDfsDescendants4CT( const void *a1, const void *a2 );
57
57
  int GetSp3RelRacAbs( const INChI *pINChI, INChI_Stereo *Stereo );
58
58
 
59
59
 
60
- #if( TEST_RENUMB_ATOMS == 1 ) /* { */
60
+ #if( TEST_RENUMB_ATOMS == 1 || READ_INCHI_STRING == 1 ) /* { */
61
61
  int CompareStereoINChI( INChI_Stereo *s1, INChI_Stereo *s2 );
62
62
  #endif
63
63
 
64
+ #if( READ_INCHI_STRING == 1 ) /* { */
65
+ /*************************************************************************************/
66
+
67
+ int CompareReversedStereoINChI2( INChI_Stereo *s1, INChI_Stereo *s2, ICR *picr);
68
+
69
+ #endif
64
70
  /**********************************************************************************************/
65
71
  int inp2spATOM( inp_ATOM *inp_at, int num_inp_at, sp_ATOM *at )
66
72
  {
@@ -742,9 +748,9 @@ int CompINChILayers(const INCHI_SORT *p1, const INCHI_SORT *p2, char sDifSegs[][
742
748
  /*==== /t, /m, /s for M ======*/
743
749
  /*==================================*/
744
750
  /* M sp3 stereo */
745
- bRelRac[DIFL_M ] = GetSp3RelRacAbs( i1, Stereo1 );
751
+ bRelRac[DIFL_M ] = GetSp3RelRacAbs( i1, Stereo1 ); /* Mobile-H */
746
752
  bRelRac[DIFL_MI] = GetSp3RelRacAbs( i1, IsoStereo1 );
747
- bRelRac[DIFL_F ] = GetSp3RelRacAbs( i2, Stereo2 );
753
+ bRelRac[DIFL_F ] = GetSp3RelRacAbs( i2, Stereo2 ); /* Fixed-H */
748
754
  bRelRac[DIFL_FI] = GetSp3RelRacAbs( i2, IsoStereo2 );
749
755
  if ( SP3_NONE != bRelRac[DIFL_M] ) {
750
756
  sDifSegs[DIFL_M][DIFS_t_SATOMS] |= (bRelRac[DIFL_M] & SP3_ANY)? DIFV_NEQ2PRECED : DIFV_BOTH_EMPTY;
@@ -1567,7 +1573,10 @@ AT_NUMB *GetDfsOrder4CT( AT_NUMB *LinearCT, int nLenCT, S_CHAR *nNum_H, int num_
1567
1573
 
1568
1574
  do {
1569
1575
  /* advance */
1570
- while ( (int)nl[i=nStackAtom[nTopStackAtom]][0] >= (j = (int)cNeighNumb[i]+1) ) {
1576
+ while ( i=(int)nStackAtom[nTopStackAtom], j = (int)cNeighNumb[i]+1, (int)nl[i][0] >= j )
1577
+ /*while ( (int)nl[i=nStackAtom[nTopStackAtom]][0] >= (j = (int)cNeighNumb[i]+1) )*/
1578
+ /* replaced due to missing sequence point; undefined behavior, pointed by Geoffrey Hutchison */
1579
+ {
1571
1580
  cNeighNumb[i] ++;
1572
1581
  u = (int)nl[i][j]; /* jth neighbor of the vertex i */
1573
1582
  if ( !nDfsNumber[u] ) {
@@ -1679,7 +1688,10 @@ AT_NUMB *GetDfsOrder4CT( AT_NUMB *LinearCT, int nLenCT, S_CHAR *nNum_H, int num_
1679
1688
 
1680
1689
  do {
1681
1690
  /* advance */
1682
- while ( (int)nl[i=nStackAtom[nTopStackAtom]][0] >= (j = (int)cNeighNumb[i]+1) ) {
1691
+ while ( i=(int)nStackAtom[nTopStackAtom], j = (int)cNeighNumb[i]+1, (int)nl[i][0] >= j )
1692
+ /*while ( (int)nl[i=nStackAtom[nTopStackAtom]][0] >= (j = (int)cNeighNumb[i]+1) )*/
1693
+ /* replaced due to missing sequence point; undefined behavior, reported by Geoffrey Hutchison */
1694
+ {
1683
1695
  k += 3;
1684
1696
  if ( k+6 > nTotOutputStringLen ) {
1685
1697
  goto exit_error; /* program error */
@@ -1760,7 +1772,7 @@ int GetInpStructErrorType( INPUT_PARMS *ip, int err, char *pStrErrStruct, int nu
1760
1772
  }
1761
1773
  /**********************************************************************************************/
1762
1774
  int ProcessStructError( INCHI_FILE *output_file, INCHI_FILE *log_file, /*int err,*/ char *pStrErrStruct, int nErrorType,
1763
- int *bXmlStructStarted, int num_inp, INPUT_PARMS *ip, char *pStr, int nStrLen )
1775
+ int *bXmlStructStarted, long num_inp, INPUT_PARMS *ip, char *pStr, int nStrLen )
1764
1776
  {
1765
1777
  int b_ok;
1766
1778
  #ifdef INCHI_LIB
@@ -1777,20 +1789,20 @@ int ProcessStructError( INCHI_FILE *output_file, INCHI_FILE *log_file, /*int err
1777
1789
  if ( nErrorType ) {
1778
1790
  if ( bPlainText ) {
1779
1791
  if ( !(b_ok=OutputINChIPlainError( output_file, pStr, nStrLen, pStrErrStruct, nErrorType ) ) ) {
1780
- my_fprintf( log_file, "Cannot create message for error (structure #%d.%s%s%s%s) Terminating.\n",
1792
+ my_fprintf( log_file, "Cannot create message for error (structure #%ld.%s%s%s%s) Terminating.\n",
1781
1793
  num_inp, SDF_LBL_VAL(ip->pSdfLabel,ip->pSdfValue) );
1782
1794
  } else {
1783
1795
  inchi_print( output_file, "\n" ); /* add a blank line after the WINCHI Window message */
1784
1796
  }
1785
1797
  } else {
1786
1798
  if ( !(b_ok=OutputINChIXmlError( output_file, pStr, nStrLen, 2, /*err,*/ pStrErrStruct, nErrorType ) ) ) {
1787
- my_fprintf( log_file, "Cannot create xml tag for error (structure #%d.%s%s%s%s) Terminating.\n",
1799
+ my_fprintf( log_file, "Cannot create xml tag for error (structure #%ld.%s%s%s%s) Terminating.\n",
1788
1800
  num_inp, SDF_LBL_VAL(ip->pSdfLabel,ip->pSdfValue) );
1789
1801
  }
1790
1802
  if ( !b_ok || nErrorType == _IS_FATAL || nErrorType == _IS_ERROR ) {
1791
1803
  /* close current structure output */
1792
1804
  if ( !OutputINChIXmlStructEndTag( output_file, pStr, nStrLen, 1 ) ) {
1793
- my_fprintf( log_file, "Cannot create end xml tag for structure #%d.%s%s%s%s Terminating.\n", num_inp, SDF_LBL_VAL(ip->pSdfLabel,ip->pSdfValue) );
1805
+ my_fprintf( log_file, "Cannot create end xml tag for structure #%ld.%s%s%s%s Terminating.\n", num_inp, SDF_LBL_VAL(ip->pSdfLabel,ip->pSdfValue) );
1794
1806
  *bXmlStructStarted = -1;
1795
1807
  b_ok = 0;
1796
1808
  } else {
@@ -1919,12 +1931,787 @@ int CompareINChI( INChI *i1, INChI *i2, INChI_Aux *a1, INChI_Aux *a2 )
1919
1931
  return 0;
1920
1932
  }
1921
1933
  #endif /* } TEST_RENUMB_ATOMS == 1 */
1934
+ #if( READ_INCHI_STRING == 1 ) /* { */
1935
+ /*************************************************************************************/
1936
+ int CompareReversedStereoINChI( INChI_Stereo *s1/* InChI from reversed struct */, INChI_Stereo *s2 /* input InChI */)
1937
+ {
1938
+ if ( s1 == NULL && s2 == NULL )
1939
+ return 0;
1940
+ if ( (s1 == NULL) ^ (s2 == NULL) ) {
1941
+ INChI_Stereo *s = s1? s1 : s2;
1942
+ if ( s->nNumberOfStereoCenters || s->nNumberOfStereoBonds ) {
1943
+ return 20; /* Diff: Missing Stereo */
1944
+ } else {
1945
+ return 0;
1946
+ }
1947
+ }
1948
+
1949
+ if ( s1->nNumberOfStereoCenters != s2->nNumberOfStereoCenters )
1950
+ return 21; /* Diff: Number of sp3 stereocenters */
1951
+ if ( s1->nNumberOfStereoCenters > 0 ) {
1952
+ if ( memcmp( s1->nNumber, s2->nNumber, s1->nNumberOfStereoCenters*sizeof(s1->nNumber[0]) ) )
1953
+ return 22; /* Diff: sp3 stereocenter locations */
1954
+ if ( memcmp( s1->t_parity, s2->t_parity, s1->nNumberOfStereoCenters*sizeof(s1->t_parity[0]) ) )
1955
+ return 23; /* Diff: sp3 stereocenter parities */
1956
+ if ( s1->nCompInv2Abs != s2->nCompInv2Abs && s1->nCompInv2Abs && s2->nCompInv2Abs )
1957
+ return 24; /* Diff: sp3 inversion */
1958
+ /*
1959
+ if ( s1->nNumberInv && s2->nNumberInv ) {
1960
+ if ( memcmp( s1->nNumberInv, s2->nNumberInv, s1->nNumberOfStereoCenters*sizeof(s1->nNumber[0]) ) )
1961
+ return 25;
1962
+ if ( memcmp( s1->t_parityInv, s2->t_parityInv, s1->nNumberOfStereoCenters*sizeof(s1->t_parity[0]) ) )
1963
+ return 26;
1964
+ if ( s1->nCompInv2Abs != s2->nCompInv2Abs ||
1965
+ s1->bTrivialInv != s2->bTrivialInv ) {
1966
+ return 27;
1967
+ }
1968
+ } else
1969
+ if ( s1->nNumberInv || s2->nNumberInv ) {
1970
+ return 28;
1971
+ }
1972
+ */
1973
+ }
1974
+ if ( s1->nNumberOfStereoBonds != s2->nNumberOfStereoBonds )
1975
+ return 25; /* Diff: Number of stereobonds */
1976
+ if ( s1->nNumberOfStereoBonds > 0 ) {
1977
+ if ( memcmp( s1->nBondAtom1, s2->nBondAtom1, s1->nNumberOfStereoBonds*sizeof(s1->nBondAtom1[0]) ) )
1978
+ return 26; /* Diff: Stereobond 1st atom locations */
1979
+ if ( memcmp( s1->nBondAtom2, s2->nBondAtom2, s1->nNumberOfStereoBonds*sizeof(s1->nBondAtom2[0]) ) )
1980
+ return 27; /* Diff: Stereobond 2nd atom locations */
1981
+ if ( memcmp( s1->b_parity, s2->b_parity, s1->nNumberOfStereoBonds*sizeof(s1->b_parity[0]) ) )
1982
+ return 28; /* Diff: Stereobond parities */
1983
+ }
1984
+ return 0;
1985
+ }
1986
+ /*************************************************************************************/
1987
+ int CompareReversedStereoINChI2( INChI_Stereo *s1/* InChI from reversed struct */, INChI_Stereo *s2 /* input InChI */, ICR *picr)
1988
+ {
1989
+ int ret = 0;
1990
+ int j1, j2, num_eq, num_dif, num_extra_undf, num_miss_undf, num_in1_only, num_in2_only;
1991
+ int bAddSb = !(picr->num_sb_undef_in1_only + picr->num_sb_in1_only + picr->num_sb_in2_only);
1992
+ int bAddSc = !(picr->num_sc_undef_in1_only + picr->num_sc_in1_only + picr->num_sc_in2_only);
1993
+
1994
+ int nNumSc1 = s1? s1->nNumberOfStereoCenters : 0;
1995
+ int nNumSc2 = s2? s2->nNumberOfStereoCenters : 0;
1996
+ int nNumSb1 = s1? s1->nNumberOfStereoBonds : 0;
1997
+ int nNumSb2 = s2? s2->nNumberOfStereoBonds : 0;
1998
+
1999
+ if ( (nNumSc1 || nNumSc1) &&
2000
+ ( nNumSc1 != nNumSc2 ||
2001
+ memcmp( s1->nNumber, s2->nNumber, nNumSc1*sizeof(s1->nNumber[0] ) ) ||
2002
+ memcmp( s1->t_parity, s2->t_parity, nNumSc1*sizeof(s1->t_parity[0]) ) ) ) {
2003
+
2004
+ num_eq = num_dif = num_extra_undf = num_miss_undf = num_in1_only = num_in2_only = 0;
2005
+ for ( j1 = j2 = 0; j1 < nNumSc1 && j2 < nNumSc2; ) {
2006
+ if ( s1->nNumber[j1] == s2->nNumber[j2] ) {
2007
+ if ( s1->t_parity[j1] == s2->t_parity[j2] ) {
2008
+ num_eq ++;
2009
+ } else {
2010
+ num_dif ++;
2011
+ }
2012
+ j1 ++;
2013
+ j2 ++;
2014
+ } else
2015
+ if ( s1->nNumber[j1] < s2->nNumber[j2] ) {
2016
+ num_in1_only ++;
2017
+ if ( s1->t_parity[j1] == AB_PARITY_UNDF ) {
2018
+ num_extra_undf ++;
2019
+ }
2020
+ if ( bAddSc ) {
2021
+ if ( picr->num_sc_in1_only < ICR_MAX_SC_IN1_ONLY )
2022
+ picr->sc_in1_only[picr->num_sc_in1_only ++] = j1;
2023
+ if ( s1->t_parity[j1] == AB_PARITY_UNDF ) {
2024
+ if ( picr->num_sc_undef_in1_only < ICR_MAX_SC_UNDF )
2025
+ picr->sc_undef_in1_only[picr->num_sc_undef_in1_only ++] = j1;
2026
+ }
2027
+ }
2028
+ j1 ++;
2029
+ } else {
2030
+ num_in2_only ++;
2031
+ if ( s2->t_parity[j2] == AB_PARITY_UNDF ) {
2032
+ num_miss_undf ++;
2033
+ }
2034
+ if ( bAddSc ) {
2035
+ if ( picr->num_sc_in2_only < ICR_MAX_SC_IN2_ONLY )
2036
+ picr->sc_in2_only[picr->num_sc_in2_only ++] = j2;
2037
+ if ( s2->t_parity[j2] == AB_PARITY_UNDF ) {
2038
+ if ( picr->num_sc_undef_in2_only < ICR_MAX_SC_UNDF )
2039
+ picr->sc_undef_in2_only[picr->num_sc_undef_in2_only ++] = j1;
2040
+ }
2041
+ }
2042
+ j2 ++;
2043
+ }
2044
+ }
2045
+ while ( j1 < nNumSc1 ) {
2046
+ if ( s1->t_parity[j1] == AB_PARITY_UNDF ) {
2047
+ num_extra_undf ++;
2048
+ }
2049
+ num_in1_only ++;
2050
+ if ( bAddSc ) {
2051
+ if ( picr->num_sc_in1_only < ICR_MAX_SC_IN1_ONLY )
2052
+ picr->sc_in1_only[picr->num_sc_in1_only ++] = j1;
2053
+ if ( s1->t_parity[j1] == AB_PARITY_UNDF ) {
2054
+ if ( picr->num_sc_undef_in1_only < ICR_MAX_SC_UNDF )
2055
+ picr->sc_undef_in1_only[picr->num_sc_undef_in1_only ++] = j1;
2056
+ }
2057
+ }
2058
+ j1 ++;
2059
+ }
2060
+ while ( j2 < nNumSc2 ) {
2061
+ if ( s2->t_parity[j2] == AB_PARITY_UNDF ) {
2062
+ num_miss_undf ++;
2063
+ }
2064
+ num_in2_only ++;
2065
+ if ( bAddSc ) {
2066
+ if ( picr->num_sc_in2_only < ICR_MAX_SC_IN2_ONLY )
2067
+ picr->sc_in2_only[picr->num_sc_in2_only ++] = j2;
2068
+ }
2069
+ j2 ++;
2070
+ }
2071
+ if ( num_dif ) {
2072
+ ret |= IDIF_SC_PARITY;
2073
+ }
2074
+ if ( num_in1_only ) {
2075
+ if ( num_extra_undf ) {
2076
+ ret |= IDIF_SC_EXTRA_UNDF;
2077
+ }
2078
+ if ( num_in1_only != num_extra_undf ) {
2079
+ ret |= IDIF_SC_EXTRA;
2080
+ }
2081
+ }
2082
+ if ( num_in2_only ) {
2083
+ if ( num_miss_undf ) {
2084
+ ret |= IDIF_SC_MISS_UNDF;
2085
+ }
2086
+ if ( num_in2_only != num_miss_undf ) {
2087
+ ret |= IDIF_SC_MISS;
2088
+ }
2089
+ }
2090
+ }
2091
+ if ( s1 && s2 && s1->nCompInv2Abs != s2->nCompInv2Abs && s1->nCompInv2Abs && s2->nCompInv2Abs ) {
2092
+ ret |= IDIF_SC_INV;
2093
+ }
2094
+
2095
+ if ( (nNumSb1 || nNumSb2 ) &&
2096
+ (nNumSb1 != nNumSb2 ||
2097
+ memcmp( s1->nBondAtom1, s2->nBondAtom1, nNumSb1*sizeof(s1->nBondAtom1[0]) ) ||
2098
+ memcmp( s1->nBondAtom2, s2->nBondAtom2, nNumSb1*sizeof(s1->nBondAtom2[0]) ) ||
2099
+ memcmp( s1->b_parity, s2->b_parity, nNumSb1*sizeof(s1->b_parity[0]) ) ) ) {
2100
+
2101
+ num_eq = num_dif = num_extra_undf = num_miss_undf = num_in1_only = num_in2_only = 0;
2102
+ for ( j1 = j2 = 0; j1 < nNumSb1 && j2 < nNumSb2; ) {
2103
+ if ( s1->nBondAtom1[j1] == s2->nBondAtom1[j2] &&
2104
+ s1->nBondAtom2[j1] == s2->nBondAtom2[j2] ) {
2105
+ if ( s1->b_parity[j1] == s2->b_parity[j2] ) {
2106
+ num_eq ++;
2107
+ } else {
2108
+ num_dif ++;
2109
+ }
2110
+ j1 ++;
2111
+ j2 ++;
2112
+ } else
2113
+ if ( s1->nBondAtom1[j1] < s2->nBondAtom1[j2] ||
2114
+ s1->nBondAtom1[j1] == s2->nBondAtom1[j2] && s1->nBondAtom2[j1] < s2->nBondAtom2[j2]) {
2115
+ num_in1_only ++;
2116
+ if ( s1->b_parity[j1] == AB_PARITY_UNDF ) {
2117
+ num_extra_undf ++;
2118
+ }
2119
+ if ( bAddSb ) {
2120
+ if ( picr->num_sb_in1_only < ICR_MAX_SB_IN1_ONLY )
2121
+ picr->sb_in1_only[picr->num_sb_in1_only ++] = j1;
2122
+ if ( s1->b_parity[j1] == AB_PARITY_UNDF ) {
2123
+ if ( picr->num_sb_undef_in1_only < ICR_MAX_SB_UNDF )
2124
+ picr->sb_undef_in1_only[picr->num_sb_undef_in1_only ++] = j1;
2125
+ }
2126
+ }
2127
+ j1 ++;
2128
+ } else {
2129
+ num_in2_only ++;
2130
+ if ( s2->b_parity[j2] == AB_PARITY_UNDF ) {
2131
+ num_miss_undf ++;
2132
+ }
2133
+ if ( bAddSb ) {
2134
+ if ( picr->num_sb_in2_only < ICR_MAX_SB_IN2_ONLY )
2135
+ picr->sb_in2_only[picr->num_sb_in2_only ++] = j2;
2136
+ if ( s2->b_parity[j2] == AB_PARITY_UNDF ) {
2137
+ if ( picr->num_sb_undef_in2_only < ICR_MAX_SB_UNDF )
2138
+ picr->sb_undef_in2_only[picr->num_sb_undef_in2_only ++] = j1;
2139
+ }
2140
+ }
2141
+ j2 ++;
2142
+ }
2143
+ }
2144
+ while ( j1 < nNumSb1 ) {
2145
+ num_in1_only ++;
2146
+ if ( s1->b_parity[j1] == AB_PARITY_UNDF ) {
2147
+ num_extra_undf ++;
2148
+ }
2149
+ if ( bAddSb ) {
2150
+ if ( picr->num_sb_in1_only < ICR_MAX_SB_IN1_ONLY )
2151
+ picr->sb_in1_only[picr->num_sb_in1_only ++] = j1;
2152
+ if ( s1->b_parity[j1] == AB_PARITY_UNDF ) {
2153
+ if ( picr->num_sb_undef_in1_only < ICR_MAX_SB_UNDF )
2154
+ picr->sb_undef_in1_only[picr->num_sb_undef_in1_only ++] = j1;
2155
+ }
2156
+ }
2157
+ j1 ++;
2158
+ }
2159
+ while ( j2 < nNumSb2 ) {
2160
+ num_in2_only ++;
2161
+ if ( s2->b_parity[j2] == AB_PARITY_UNDF ) {
2162
+ num_miss_undf ++;
2163
+ }
2164
+ if ( bAddSb ) {
2165
+ if ( picr->num_sb_in2_only < ICR_MAX_SB_IN2_ONLY )
2166
+ picr->sb_in2_only[picr->num_sb_in2_only ++] = j2;
2167
+ if ( s2->b_parity[j2] == AB_PARITY_UNDF ) {
2168
+ if ( picr->num_sb_undef_in2_only < ICR_MAX_SB_UNDF )
2169
+ picr->sb_undef_in2_only[picr->num_sb_undef_in2_only ++] = j1;
2170
+ }
2171
+ }
2172
+ j2 ++;
2173
+ }
2174
+ if ( num_dif ) {
2175
+ ret |= IDIF_SB_PARITY;
2176
+ }
2177
+ if ( num_in1_only ) {
2178
+ if ( num_extra_undf ) {
2179
+ ret |= IDIF_SB_EXTRA_UNDF;
2180
+ }
2181
+ if ( num_in1_only != num_extra_undf ) {
2182
+ ret |= IDIF_SB_EXTRA;
2183
+ }
2184
+ }
2185
+ if ( num_in2_only ) {
2186
+ if ( num_miss_undf ) {
2187
+ ret |= IDIF_SB_MISS_UNDF;
2188
+ }
2189
+ if ( num_in2_only != num_miss_undf ) {
2190
+ ret |= IDIF_SB_MISS;
2191
+ }
2192
+ }
2193
+ }
2194
+
2195
+ return ret;
2196
+ }
2197
+ /*************************************************************************************/
2198
+ int CompareReversedINChI( INChI *i1 /* InChI from reversed struct */, INChI *i2 /* input InChI */, INChI_Aux *a1, INChI_Aux *a2 )
2199
+ {
2200
+ int ret;
2201
+ if ( i1 == NULL && i2 == NULL )
2202
+ return 0;
2203
+ if ( (i1 == NULL) ^ (i2 == NULL) )
2204
+ return 1; /* Diff: Missing InChI */
2205
+
2206
+ if ( i1->nErrorCode == i2->nErrorCode ) {
2207
+ if ( i1->nErrorCode )
2208
+ return 0;
2209
+ } else {
2210
+ return 2; /* Diff: Error codes */
2211
+ }
2212
+ if ( i1->bDeleted != i2->bDeleted ) {
2213
+ return 1; /* Diff: Missing InChI */
2214
+ }
2215
+ if ( i1->nNumberOfAtoms != i2->nNumberOfAtoms )
2216
+ return 3; /* Diff: Num. atoms */
2217
+ if ( i1->nNumberOfAtoms > 0 ) {
2218
+ if ( memcmp( i1->nAtom, i2->nAtom, i1->nNumberOfAtoms*sizeof(i1->nAtom[0]) ) )
2219
+ return 4; /* Diff: Elements */
2220
+ if ( strcmp( i1->szHillFormula, i2->szHillFormula ) )
2221
+ return 7; /* Diff: Hill Formulas */
2222
+ if ( memcmp( i1->nNum_H, i2->nNum_H, i1->nNumberOfAtoms*sizeof(i1->nNum_H[0]) ) ) {
2223
+ if ( i1->lenConnTable > 1 || i2->lenConnTable > 1 ) {
2224
+ return 5; /* Diff: H Locations (mobile H present) */
2225
+ } else {
2226
+ return 6; /* Diff: H Locations (no mobile H) */
2227
+ }
2228
+ }
2229
+ /* fixed H */
2230
+ if ( i1->nNum_H_fixed || i2->nNum_H_fixed ) {
2231
+ int bHasFixedH1 = 0, bHasFixedH2 = 0, i, j1, j2;
2232
+ if ( i1->nNum_H_fixed ) {
2233
+ for ( i = 0; i < i1->nNumberOfAtoms; i ++ ) {
2234
+ if ( i1->nNum_H_fixed[i] ) {
2235
+ bHasFixedH1 ++;
2236
+ }
2237
+ }
2238
+ }
2239
+ if ( i2->nNum_H_fixed ) {
2240
+ for ( i = 0; i < i2->nNumberOfAtoms; i ++ ) {
2241
+ if ( i2->nNum_H_fixed[i] ) {
2242
+ bHasFixedH2 ++;
2243
+ }
2244
+ }
2245
+ }
2246
+ /* count the differences */
2247
+ j1 = j2 = 0;
2248
+ if ( bHasFixedH1 && !bHasFixedH2 ) {
2249
+ for ( i = 0; i < i1->nNumberOfAtoms; i ++ ) {
2250
+ if ( i1->nNum_H_fixed[i] > 0 ) {
2251
+ j1 ++;
2252
+ } else
2253
+ if ( i1->nNum_H_fixed[i] < 0 ) {
2254
+ j2 ++;
2255
+ }
2256
+ }
2257
+
2258
+ return 18; /* Diff: Extra Fixed-H */
2259
+ } else
2260
+ if ( !bHasFixedH1 && bHasFixedH2 ) {
2261
+ for ( i = j1 = j2 = 0; i < i1->nNumberOfAtoms; i ++ ) {
2262
+ if ( 0 > i2->nNum_H_fixed[i] ) {
2263
+ j1 ++;
2264
+ } else
2265
+ if ( 0 < i2->nNum_H_fixed[i] ) {
2266
+ j2 ++;
2267
+ }
2268
+ }
2269
+ return 19; /* Diff: Missed Fixed-H */
2270
+ } else
2271
+ if ( bHasFixedH1 && bHasFixedH2 &&
2272
+ memcmp( i1->nNum_H_fixed, i2->nNum_H_fixed, i1->nNumberOfAtoms*sizeof(i1->nNum_H_fixed[0]) ) ) {
2273
+ for ( i = j1 = j2 = 0; i < i1->nNumberOfAtoms; i ++ ) {
2274
+ if ( i1->nNum_H_fixed[i] > i2->nNum_H_fixed[i] ) {
2275
+ j1 ++;
2276
+ } else
2277
+ if ( i1->nNum_H_fixed[i] < i2->nNum_H_fixed[i] ) {
2278
+ j2 ++;
2279
+ }
2280
+ }
2281
+ }
2282
+ ret = (j1 && j2)? 20 : j1? 18 : j2? 19 : 0;
2283
+ if ( ret ) {
2284
+ return ret; /* 20 => Diff: NotEql Fixed-H */
2285
+ /* 19 => Diff: Missed Fixed-H (i1 has less) */
2286
+ /* 18 => Diff: Extra Fixed-H (i1 has more) */
2287
+ }
2288
+ }
2289
+ }
2290
+
2291
+ if ( i1->lenConnTable != i2->lenConnTable )
2292
+ return 8; /* Diff: Connections length */
2293
+ if ( i1->lenConnTable > 0 && memcmp( i1->nConnTable, i2->nConnTable, i1->lenConnTable*sizeof(i1->nConnTable[0]) ) )
2294
+ return 9; /* Diff: Connections */
2295
+ /* output special cases: different number of t-groups, different sizes of t-groups, different endpoints */
2296
+ if ( i1->lenTautomer != i2->lenTautomer && (i1->lenTautomer > 1 || i2->lenTautomer > 1) )
2297
+ return 10; /* Diff: Mobile groups length */ /* in isotopic or deprotonated cases i1->lenTautomer == 1 && i1->nTautomer[0] = 0 */
2298
+ if ( (i1->lenTautomer > 1 && i2->lenTautomer > 1) &&
2299
+ memcmp( i1->nTautomer, i2->nTautomer, i1->lenTautomer*sizeof(i1->nTautomer[0]) ) )
2300
+ return 11; /* Diff: Mobile groups */
2301
+
2302
+ if ( i1->nNumberOfIsotopicAtoms != i2->nNumberOfIsotopicAtoms )
2303
+ return 12; /* Diff: Isotopic atoms number */
2304
+ if ( i1->nNumberOfIsotopicAtoms > 0 && memcmp( i1->IsotopicAtom, i2->IsotopicAtom, i1->nNumberOfIsotopicAtoms*sizeof(i1->IsotopicAtom[0]) ) )
2305
+ return 13; /* Diff: Isotopic atoms */
2306
+ if ( i1->nTotalCharge != i2->nTotalCharge )
2307
+ return 14; /* Diff: Charge */
2308
+ /*
2309
+ if ( i1->nNumberOfIsotopicTGroups != i2->nNumberOfIsotopicTGroups )
2310
+ return 14;
2311
+ if ( i1->nNumberOfIsotopicTGroups > 0 && memcmp( i1->IsotopicTGroup, i2->IsotopicTGroup, i1->nNumberOfIsotopicTGroups*sizeof(i1->IsotopicTGroup[0]) ) )
2312
+ return 15;
2313
+ */
2314
+ if ( a1 && a2 ) {
2315
+ if ( a1->nNumRemovedProtons != a2->nNumRemovedProtons )
2316
+ return 16; /* Diff: Number of removed protons */
2317
+ if ( memcmp( a1->nNumRemovedIsotopicH, a2->nNumRemovedIsotopicH, sizeof(a1->nNumRemovedIsotopicH) ) )
2318
+ return 17; /* Diff: Removed isotopic H */
2319
+ }
2320
+ /*
2321
+ if ( i1->nPossibleLocationsOfIsotopicH && i2->nPossibleLocationsOfIsotopicH ) {
2322
+ if ( i1->nPossibleLocationsOfIsotopicH[0] != i2->nPossibleLocationsOfIsotopicH[0] ||
2323
+ memcmp(i1->nPossibleLocationsOfIsotopicH, i2->nPossibleLocationsOfIsotopicH,
2324
+ sizeof(i1->nPossibleLocationsOfIsotopicH[0])*i1->nPossibleLocationsOfIsotopicH[0]) )
2325
+ return 18;
2326
+ } else
2327
+ if ( !i1->nPossibleLocationsOfIsotopicH != !i2->nPossibleLocationsOfIsotopicH ) {
2328
+ return 19;
2329
+ }
2330
+ */
2331
+ /* ret = 20..31 => 40..51 */
2332
+ if ( ret = CompareReversedStereoINChI( i1->Stereo, i2->Stereo ) )
2333
+ return ret+20;
2334
+ /* ret = 40..51 => 60..71 */
2335
+
2336
+ if ( !i2->StereoIsotopic && i2->Stereo && i1->StereoIsotopic &&
2337
+ 0 < (i1->StereoIsotopic->nNumberOfStereoBonds + i1->StereoIsotopic->nNumberOfStereoCenters) &&
2338
+ 0 == CompareReversedStereoINChI( i1->StereoIsotopic, i2->Stereo ) ) {
2339
+ /* InChI from reversed structure does not contain fully duplicated isotopic stereo */
2340
+ ;
2341
+ } else
2342
+
2343
+ if ( ret = CompareReversedStereoINChI( i1->StereoIsotopic, i2->StereoIsotopic ) ) {
2344
+ return ret+40;
2345
+ }
2346
+
2347
+ return 0;
2348
+ }
2349
+
2350
+ /*******************************************************************************/
2351
+ int CompareIcr( ICR *picr1, ICR *picr2, INCHI_MODE *pin1, INCHI_MODE *pin2, INCHI_MODE mask )
2352
+ {
2353
+ int nNumExtraBits1 = 0, nNumExtraBits2 = 0, bit1, bit2;
2354
+ INCHI_MODE Flg1=picr1->flags, Flg2 = picr2->flags, cur_bit = 1, in1, in2;
2355
+ int i, ret;
2356
+
2357
+ /* compare flags */
2358
+ in1 = in2 = 0;
2359
+ for ( i = 0; Flg1 || Flg2; i ++, Flg1 >>= 1, Flg2 >>= 1, cur_bit <<= 1 ) {
2360
+ if ( !(mask & cur_bit) ) {
2361
+ continue;
2362
+ }
2363
+ bit1 = Flg1 & 1;
2364
+ bit2 = Flg2 & 1;
2365
+ if ( bit1 && !bit2 ) {
2366
+ in1 |= 1 << i;
2367
+ nNumExtraBits1 ++;
2368
+ } else
2369
+ if ( !bit1 && bit2 ) {
2370
+ in2 |= 1 << i;
2371
+ nNumExtraBits2 ++;
2372
+ }
2373
+ }
2374
+ if ( nNumExtraBits1 && !nNumExtraBits2 ) {
2375
+ ret = 1;
2376
+ } else
2377
+ if ( !nNumExtraBits1 && nNumExtraBits2 ) {
2378
+ ret = -1;
2379
+ } else
2380
+ if ( !in1 && !in2 ) {
2381
+ ret = 0;
2382
+ } else {
2383
+ ret = 2; /* compare produced undefined results */
2384
+ }
2385
+ if ( pin1 ) *pin1 = in1;
2386
+ if ( pin2 ) *pin2 = in2;
2387
+ /* more detailed compare not implemented */
2388
+ return ret;
2389
+ }
2390
+
2391
+ /*********************************************************************************************************/
2392
+ INCHI_MODE CompareReversedINChI2( INChI *i1 /* InChI from reversed struct */, INChI *i2 /* input InChI */,
2393
+ INChI_Aux *a1, INChI_Aux *a2, ICR *picr, int *err )
2394
+ {
2395
+ INCHI_MODE ret = 0;
2396
+ INChI_Stereo *Stereo1=NULL, *Stereo2=NULL;
2397
+ int n1, n2, m, j, j1, j2, ret2, num_H1, num_H2;
2398
+
2399
+ *err = 0;
2400
+
2401
+ memset( picr, 0, sizeof(*picr) );
2402
+
2403
+ if ( i1 == NULL && i2 == NULL )
2404
+ return 0;
2405
+ if ( (i1 == NULL) ^ (i2 == NULL) ) {
2406
+ ret |= IDIF_PROBLEM; /* one InChI exists while another doesn't */
2407
+ goto exit_function;
2408
+ }
2409
+
2410
+ if ( i1->nErrorCode == i2->nErrorCode ) {
2411
+ if ( i1->nErrorCode ) {
2412
+ ret |= IDIF_PROBLEM; /* both InChI have same error codes */
2413
+ goto exit_function;
2414
+ }
2415
+ } else {
2416
+ ret |= IDIF_PROBLEM; /* at least one InChI has an error code */
2417
+ goto exit_function;
2418
+ }
2419
+
2420
+ if ( i1->nNumberOfAtoms != i2->nNumberOfAtoms ) {
2421
+ ret |= IDIF_NUM_AT;
2422
+ goto exit_function;
2423
+ }
2424
+ if ( i1->nNumberOfAtoms > 0 ) {
2425
+ if ( memcmp( i1->nAtom, i2->nAtom, i1->nNumberOfAtoms*sizeof(i1->nAtom[0]) ) ) {
2426
+ ret |= IDIF_ATOMS;
2427
+ goto exit_function;
2428
+ }
2429
+ /* IDIF_NON_TAUT_H, IDIF_MORE_FH, IDIF_LESS_FH */
2430
+ if ( memcmp( i1->nNum_H, i2->nNum_H, i1->nNumberOfAtoms*sizeof(i1->nNum_H[0]) ) ) {
2431
+ ret |= IDIF_POSITION_H;
2432
+ for ( j1 = 0; j1 < i1->nNumberOfAtoms; j1 ++ ) {
2433
+ if ( i1->nNum_H[j1] != i2->nNum_H[j1] && picr->num_diff_pos_H < ICR_MAX_DIFF_FIXED_H ) {
2434
+ picr->diff_pos_H_at[picr->num_diff_pos_H] = j1;
2435
+ picr->diff_pos_H_nH[picr->num_diff_pos_H] = i1->nNum_H[j1] - i2->nNum_H[j1];
2436
+ picr->num_diff_pos_H ++;
2437
+ }
2438
+ }
2439
+ }
2440
+ /* fixed H */
2441
+ if ( i1->nNum_H_fixed || i2->nNum_H_fixed ) {
2442
+ int bHasFixedH1 = 0, bHasFixedH2 = 0, i;
2443
+ if ( i1->nNum_H_fixed ) {
2444
+ for ( i = 0; i < i1->nNumberOfAtoms; i ++ ) {
2445
+ if ( i1->nNum_H_fixed[i] ) {
2446
+ bHasFixedH1 ++;
2447
+ }
2448
+ }
2449
+ }
2450
+ if ( i2->nNum_H_fixed ) {
2451
+ for ( i = 0; i < i2->nNumberOfAtoms; i ++ ) {
2452
+ if ( i2->nNum_H_fixed[i] ) {
2453
+ bHasFixedH2 ++;
2454
+ }
2455
+ }
2456
+ }
2457
+ if ( bHasFixedH1 && !bHasFixedH2 ) {
2458
+ for ( i = j = 0; i < i1->nNumberOfAtoms; i ++ ) {
2459
+ if ( i1->nNum_H_fixed[i] ) {
2460
+ if ( j < ICR_MAX_DIFF_FIXED_H ) {
2461
+ picr->fixed_H_at1_more[j] = i;
2462
+ picr->fixed_H_nH1_more[j] = i1->nNum_H_fixed[i];
2463
+ j ++;
2464
+ }
2465
+ }
2466
+ }
2467
+ picr->num_fixed_H1_more = j;
2468
+ ret |= IDIF_MORE_FH; /* Extra Fixed-H */
2469
+ } else
2470
+ if ( !bHasFixedH1 && bHasFixedH2 ) {
2471
+ for ( i = j = 0; i < i2->nNumberOfAtoms; i ++ ) {
2472
+ if ( i2->nNum_H_fixed[i] ) {
2473
+ if ( j < ICR_MAX_DIFF_FIXED_H ) {
2474
+ picr->fixed_H_at2_more[j] = i;
2475
+ picr->fixed_H_nH2_more[j] = i2->nNum_H_fixed[i];
2476
+ j ++;
2477
+ }
2478
+ }
2479
+ }
2480
+ picr->num_fixed_H2_more = j;
2481
+ ret |= IDIF_LESS_FH; /* Missed Fixed-H */
2482
+ } else
2483
+ if ( bHasFixedH1 && bHasFixedH2 &&
2484
+ memcmp( i1->nNum_H_fixed, i2->nNum_H_fixed, i1->nNumberOfAtoms*sizeof(i1->nNum_H_fixed[0]) ) ) {
2485
+ for ( i = j1 = j2 = 0; i < i1->nNumberOfAtoms; i ++ ) {
2486
+ if ( i1->nNum_H_fixed[i] > i2->nNum_H_fixed[i] ) {
2487
+ if ( j1 < ICR_MAX_DIFF_FIXED_H ) {
2488
+ picr->fixed_H_at1_more[j1] = i;
2489
+ picr->fixed_H_nH1_more[j1] = i1->nNum_H_fixed[i] - i2->nNum_H_fixed[i];
2490
+ j1 ++;
2491
+ }
2492
+ } else
2493
+ if ( i1->nNum_H_fixed[i] < i2->nNum_H_fixed[i] ) {
2494
+ if ( j2 < ICR_MAX_DIFF_FIXED_H ) {
2495
+ picr->fixed_H_at2_more[j2] = i;
2496
+ picr->fixed_H_nH2_more[j2] = i2->nNum_H_fixed[i] - i1->nNum_H_fixed[i];
2497
+ j2 ++;
2498
+ }
2499
+ }
2500
+ }
2501
+ ret |= (j1? IDIF_MORE_FH:0) | (j2? IDIF_LESS_FH:0);
2502
+ picr->num_fixed_H1_more = j1;
2503
+ picr->num_fixed_H2_more = j2;
2504
+ }
2505
+ }
2506
+ }
2507
+ /* compare formulas and H */
2508
+ num_H1 = 0;
2509
+ num_H2 = 0;
2510
+ ret2 = CompareHillFormulasNoH( i1->szHillFormula, i2->szHillFormula, &num_H1, &num_H2 );
2511
+ picr->tot_num_H1 = num_H1;
2512
+ picr->tot_num_H2 = num_H2;
2513
+ if ( ret2 ) {
2514
+ ret |= IDIF_NUM_EL;
2515
+ goto exit_function;
2516
+ }
2517
+ if ( num_H1 > num_H2 ) {
2518
+ ret |= IDIF_MORE_H;
2519
+ }
2520
+ if ( num_H1 < num_H2 ) {
2521
+ ret |= IDIF_LESS_H;
2522
+ }
2523
+
2524
+ if ( i1->lenConnTable != i2->lenConnTable ) {
2525
+ ret |= IDIF_CON_LEN;
2526
+ goto exit_function;
2527
+ } else
2528
+ if ( i1->lenConnTable > 0 && memcmp( i1->nConnTable, i2->nConnTable, i1->lenConnTable*sizeof(i1->nConnTable[0]) ) ) {
2529
+ ret |= IDIF_CON_TBL;
2530
+ goto exit_function;
2531
+ }
2532
+ /* output special cases: different number of t-groups, different sizes of t-groups, different endpoints */
2533
+ /* in isotopic or deprotonated cases i1->lenTautomer == 1 && i1->nTautomer[0] = 0 */
2534
+ /*
2535
+ if ( i1->lenTautomer != i2->lenTautomer && (i1->lenTautomer > 1 || i2->lenTautomer > 1) ) {
2536
+ ret |= IDIF_TAUT_LEN;
2537
+ }
2538
+ */
2539
+ /* compare number of t-groups */
2540
+ n1 = i1->lenTautomer? i1->nTautomer[0] : 0;
2541
+ n2 = i2->lenTautomer? i2->nTautomer[0] : 0;
2542
+ if ( !n1 && n2 ) {
2543
+ ret |= IDIF_NO_TAUT;
2544
+ } else
2545
+ if ( n1 && !n2 ) {
2546
+ ret |= IDIF_WRONG_TAUT;
2547
+ } else
2548
+ if ( n1 == 1 && n2 > 1 ) {
2549
+ ret |= IDIF_SINGLE_TG;
2550
+ } else
2551
+ if ( n1 > 1 && n2 == 1 ) {
2552
+ ret |= IDIF_MULTIPLE_TG;
2553
+ } else
2554
+ if ( n1 != n2 ) {
2555
+ ret |= IDIF_NUM_TG;
2556
+ }
2557
+ if ( n1 || n2 ) {
2558
+ /* number of endpoints */
2559
+ int num1 = 0, num2 = 0, num_M1=0, num_M2=0;
2560
+ int len, num_eq, num_in1_only, num_in2_only;
2561
+ AT_NUMB *pe1 = (AT_NUMB *)inchi_malloc( (i1->lenTautomer+1) * sizeof(pe1[0]) );
2562
+ AT_NUMB *pe2 = (AT_NUMB *)inchi_malloc( (i2->lenTautomer+1) * sizeof(pe2[0]) );
2563
+ num_H1 = num_H2=0;
2564
+ /* collect endpoints, H, (-) */
2565
+ if ( !pe1 || !pe2 ) {
2566
+ if ( pe1 ) inchi_free( pe1 );
2567
+ if ( pe2 ) inchi_free( pe2 );
2568
+ *err = -1; /* allocation error */
2569
+ goto exit_function;
2570
+ }
2571
+ for ( m = 1; m < i1->lenTautomer; m += len ) {
2572
+ len = i1->nTautomer[m ++];
2573
+ num_H1 += i1->nTautomer[m];
2574
+ num_M1 += i1->nTautomer[m+1];
2575
+ for ( j = 2; j < len; j ++ ) {
2576
+ pe1[num1 ++] = i1->nTautomer[m + j];
2577
+ }
2578
+ }
2579
+ for ( m = 1; m < i2->lenTautomer; m += len ) {
2580
+ len = i2->nTautomer[m ++];
2581
+ num_H2 += i2->nTautomer[m];
2582
+ num_M2 += i2->nTautomer[m+1];
2583
+ for ( j = 2; j < len; j ++ ) {
2584
+ pe2[num2 ++] = i2->nTautomer[m + j];
2585
+ }
2586
+ }
2587
+ picr->num_taut_H1 = num_H1;
2588
+ picr->num_taut_H2 = num_H2;
2589
+ picr->num_taut_M1 = num_M1;
2590
+ picr->num_taut_M2 = num_M2;
2591
+ /* sort endpoints */
2592
+ insertions_sort_AT_RANK( pe1, num1 );
2593
+ insertions_sort_AT_RANK( pe2, num2 );
2594
+ /* compare */
2595
+ /*
2596
+ if ( num1 < num2 ) {
2597
+ ret |= IDIF_LESS_TG_ENDP;
2598
+ } else
2599
+ if ( num1 > num2 ) {
2600
+ ret |= IDIF_MORE_TG_ENDP;
2601
+ }
2602
+ */
2603
+ /* compare all */
2604
+ num_eq = num_in1_only = num_in2_only = 0;
2605
+ for ( j1 = j2 = 0; j1 < num1 && j2 < num2; ) {
2606
+ if( pe1[j1] == pe2[j2] ) {
2607
+ j1 ++;
2608
+ j2 ++;
2609
+ num_eq ++;
2610
+ } else
2611
+ if ( pe1[j1] < pe2[j2] ) { /* BC: fixed, was pe2[j1] 2006-03-27 */
2612
+ if ( picr->num_endp_in1_only < ICR_MAX_ENDP_IN1_ONLY ) {
2613
+ picr->endp_in1_only[picr->num_endp_in1_only ++] = pe1[j1];
2614
+ }
2615
+ j1 ++;
2616
+ num_in1_only ++;
2617
+ } else {
2618
+ if ( picr->num_endp_in2_only < ICR_MAX_ENDP_IN2_ONLY ) {
2619
+ picr->endp_in2_only[picr->num_endp_in2_only ++] = pe2[j2];
2620
+ }
2621
+ j2 ++;
2622
+ num_in2_only ++;
2623
+ }
2624
+ }
2625
+ while ( j1 < num1 ) {
2626
+ if ( picr->num_endp_in1_only < ICR_MAX_ENDP_IN1_ONLY ) {
2627
+ picr->endp_in1_only[picr->num_endp_in1_only ++] = pe1[j1];
2628
+ }
2629
+ j1 ++;
2630
+ num_in1_only ++;
2631
+ }
2632
+ while ( j2 < num2 ) {
2633
+ if ( picr->num_endp_in2_only < ICR_MAX_ENDP_IN2_ONLY ) {
2634
+ picr->endp_in2_only[picr->num_endp_in2_only ++] = pe2[j2];
2635
+ }
2636
+ j2 ++;
2637
+ num_in2_only ++;
2638
+ }
2639
+ if ( num_in1_only ) {
2640
+ ret |= IDIF_EXTRA_TG_ENDP;
2641
+ }
2642
+ if ( num_in2_only ) {
2643
+ ret |= IDIF_MISS_TG_ENDP;
2644
+ }
2645
+ if ( !num_in1_only && !num_in2_only && num_eq ) {
2646
+ ; /* same t-groups endpoints */
2647
+ } else {
2648
+ ret |= IDIF_DIFF_TG_ENDP;
2649
+ }
2650
+ inchi_free( pe1 );
2651
+ inchi_free( pe2 );
2652
+
2653
+ }
2654
+
2655
+ if ( (i1->lenTautomer > 1 && i2->lenTautomer > 1) &&
2656
+ ( i1->lenTautomer != i2->lenTautomer ||
2657
+ memcmp( i1->nTautomer, i2->nTautomer, i1->lenTautomer*sizeof(i1->nTautomer[0]) ) ) )
2658
+ ret |= IDIF_TG;
2659
+
2660
+ if ( i1->nNumberOfIsotopicAtoms != i2->nNumberOfIsotopicAtoms ) {
2661
+ ret |= IDIF_NUM_ISO_AT;
2662
+ } else
2663
+ if ( i1->nNumberOfIsotopicAtoms > 0 && memcmp( i1->IsotopicAtom, i2->IsotopicAtom, i1->nNumberOfIsotopicAtoms*sizeof(i1->IsotopicAtom[0]) ) )
2664
+ ret |= IDIF_ISO_AT;
2665
+ if ( i1->nTotalCharge != i2->nTotalCharge )
2666
+ ret |= IDIF_CHARGE;
2667
+ if ( a1 && a1->nNumRemovedProtons && (!a2 || a2->nNumRemovedProtons != a1->nNumRemovedProtons) ) {
2668
+ ret |= IDIF_REM_PROT;
2669
+ }
2670
+ if ( a1 && (!a2 ||
2671
+ a2->nNumRemovedIsotopicH[0] != a1->nNumRemovedIsotopicH[0] ||
2672
+ a2->nNumRemovedIsotopicH[1] != a1->nNumRemovedIsotopicH[1] ||
2673
+ a2->nNumRemovedIsotopicH[2] != a1->nNumRemovedIsotopicH[2]) ) {
2674
+ ret |= IDIF_REM_ISO_H;
2675
+ }
2676
+
2677
+ /*
2678
+ if ( i1->nPossibleLocationsOfIsotopicH && i2->nPossibleLocationsOfIsotopicH ) {
2679
+ if ( i1->nPossibleLocationsOfIsotopicH[0] != i2->nPossibleLocationsOfIsotopicH[0] ||
2680
+ memcmp(i1->nPossibleLocationsOfIsotopicH, i2->nPossibleLocationsOfIsotopicH,
2681
+ sizeof(i1->nPossibleLocationsOfIsotopicH[0])*i1->nPossibleLocationsOfIsotopicH[0]) )
2682
+ return 18;
2683
+ } else
2684
+ if ( !i1->nPossibleLocationsOfIsotopicH != !i2->nPossibleLocationsOfIsotopicH ) {
2685
+ return 19;
2686
+ }
2687
+ */
2688
+ if ( i1->StereoIsotopic &&
2689
+ i1->StereoIsotopic->nNumberOfStereoBonds + i1->StereoIsotopic->nNumberOfStereoCenters ) {
2690
+ Stereo1 = i1->StereoIsotopic;
2691
+ } else {
2692
+ Stereo1 = i1->Stereo;
2693
+ }
2694
+ if ( i2->StereoIsotopic &&
2695
+ i2->StereoIsotopic->nNumberOfStereoBonds + i2->StereoIsotopic->nNumberOfStereoCenters ) {
2696
+ Stereo2 = i2->StereoIsotopic;
2697
+ } else {
2698
+ Stereo2 = i2->Stereo;
2699
+ }
2700
+ ret |= CompareReversedStereoINChI2( Stereo1, Stereo2, picr );
2701
+
2702
+ exit_function:
2703
+
2704
+ picr->flags = ret;
2705
+
2706
+ return ret;
2707
+ }
2708
+ #endif /* } READ_INCHI_STRING */
1922
2709
  /***************************************************************************************/
1923
- int Create_INChI( INChI **ppINChI, INChI_Aux **ppINChI_Aux, ORIG_ATOM_DATA *orig_inp_data,
2710
+ int Create_INChI( INChI **ppINChI, INChI_Aux **ppINChI_Aux, ORIG_ATOM_DATA *orig_inp_data, /* not used */
1924
2711
  inp_ATOM *inp_at, INP_ATOM_DATA *out_norm_data[2],
1925
2712
  int num_inp_at, INCHI_MODE nUserMode,
1926
2713
  INCHI_MODE *pbTautFlags, INCHI_MODE *pbTautFlagsDone,
1927
- struct tagInchiTime *ulMaxTime, char *pStrErrStruct)
2714
+ struct tagInchiTime *ulMaxTime, T_GROUP_INFO *ti_out, char *pStrErrStruct)
1928
2715
  {
1929
2716
  /*
1930
2717
  #define NON_TAUT 0
@@ -1952,10 +2739,13 @@ int Create_INChI( INChI **ppINChI, INChI_Aux **ppINChI_Aux, ORIG_ATOM_DATA *ori
1952
2739
  int bMayHaveStereo = 0;
1953
2740
  int num_taut_at = 0;
1954
2741
 
1955
- inp_ATOM *out_at = NULL; /*, *norm_at_fixed_bonds[TAUT_NUM]; *//* = {out_norm_nontaut_at, out_norm_taut_at} ; */
1956
- INChI *pINChI;
1957
- INChI_Aux *pINChI_Aux;
1958
- int bPointedEdgeStereo = (0 != (TG_FLAG_POINTED_EDGE_STEREO & *pbTautFlags));
2742
+ inp_ATOM *out_at = NULL; /*, *norm_at_fixed_bonds[TAUT_NUM]; */ /* = {out_norm_nontaut_at, out_norm_taut_at} ; */
2743
+ INChI *pINChI=NULL; /* added initialization 2006-03 */
2744
+ INChI_Aux *pINChI_Aux=NULL; /* added initialization 2006-03 */
2745
+ int bPointedEdgeStereo = ((TG_FLAG_POINTED_EDGE_STEREO & *pbTautFlags)? PES_BIT_POINT_EDGE_STEREO:0)
2746
+ | ((TG_FLAG_PHOSPHINE_STEREO & *pbTautFlags)? PES_BIT_PHOSPHINE_STEREO :0)
2747
+ | ((TG_FLAG_ARSINE_STEREO & *pbTautFlags)? PES_BIT_ARSINE_STEREO :0)
2748
+ | ((TG_FLAG_FIX_SP3_BUG & *pbTautFlags)? PES_BIT_FIX_SP3_BUG :0);
1959
2749
  INCHI_MODE bTautFlags = (*pbTautFlags & (~(INCHI_MODE)TG_FLAG_ALL_TAUTOMERIC) );
1960
2750
  INCHI_MODE bTautFlagsDone = (*pbTautFlagsDone /*& (~(INCHI_MODE)TG_FLAG_ALL_TAUTOMERIC) */);
1961
2751
  #if( bRELEASE_VERSION == 0 )
@@ -2006,11 +2796,25 @@ int Create_INChI( INChI **ppINChI, INChI_Aux **ppINChI_Aux, ORIG_ATOM_DATA *ori
2006
2796
 
2007
2797
  /* Preprocess the structure; here THE NUMBER OF ATOMS MAY BE REDUCED */
2008
2798
  /* ??? Ambiguity: H-D may become HD or DH (that is, H+implicit D or D+implicit H) */
2009
- num_at_tg =
2010
- num_atoms = remove_terminal_HDT( num_inp_at, out_at );
2011
- num_removed_H = num_inp_at - num_atoms;
2012
- t_group_info->tni.nNumRemovedExplicitH = num_removed_H;
2013
- add_DT_to_num_H( num_atoms, out_at );
2799
+ if ( TG_FLAG_H_ALREADY_REMOVED & bTautFlags ) {
2800
+ INP_ATOM_DATA *out_norm_data1 = out_norm_data[TAUT_YES]->at? out_norm_data[TAUT_YES] :
2801
+ out_norm_data[TAUT_NON]->at? out_norm_data[TAUT_NON] : NULL;
2802
+ if ( out_norm_data1 ) {
2803
+ num_at_tg =
2804
+ num_atoms = out_norm_data1->num_at - out_norm_data1->num_removed_H;
2805
+ num_removed_H = out_norm_data1->num_removed_H;
2806
+ t_group_info->tni.nNumRemovedExplicitH = num_removed_H;
2807
+ } else {
2808
+ ret = -1;
2809
+ goto exit_function;
2810
+ }
2811
+ } else {
2812
+ num_at_tg =
2813
+ num_atoms = remove_terminal_HDT( num_inp_at, out_at );
2814
+ num_removed_H = num_inp_at - num_atoms;
2815
+ t_group_info->tni.nNumRemovedExplicitH = num_removed_H;
2816
+ add_DT_to_num_H( num_atoms, out_at );
2817
+ }
2014
2818
  /*fix_odd_things( num_atoms, out_at );*/
2015
2819
  #if( FIND_RING_SYSTEMS == 1 )
2016
2820
  MarkRingSystemsInp( out_at, num_atoms );
@@ -2114,7 +2918,7 @@ int Create_INChI( INChI **ppINChI, INChI_Aux **ppINChI_Aux, ORIG_ATOM_DATA *ori
2114
2918
  if ( s[TAUT_YES].nLenLinearCTTautomer > 0 ) {
2115
2919
  num_at_tg = num_taut_at+t_group_info->num_t_groups;
2116
2920
  /* ??? -not true- create t_group_info_orig for multiple calls with atom renumbering */
2117
- make_a_copy_of_t_group_info( t_group_info_orig, t_group_info );
2921
+ make_a_copy_of_t_group_info( t_group_info_orig /* dest*/, t_group_info /* source*/ );
2118
2922
  /* mark isotopic tautomer groups: calculate t_group->iWeight */
2119
2923
  s[TAUT_YES].nLenLinearCTIsotopicTautomer=set_tautomer_iso_sort_keys( t_group_info );
2120
2924
  if ( s[TAUT_YES].nLenLinearCTIsotopicTautomer < 0 ) {
@@ -2400,7 +3204,7 @@ int Create_INChI( INChI **ppINChI, INChI_Aux **ppINChI_Aux, ORIG_ATOM_DATA *ori
2400
3204
  ret = Canon_INChI( num_atoms, i?num_at_tg:num_atoms, at[i], pCS, nMode, i);
2401
3205
  }
2402
3206
 
2403
- pINChI = ppINChI[i];
3207
+ pINChI = ppINChI[i]; /* pointers to already allocated still empty InChI */
2404
3208
  pINChI_Aux = ppINChI_Aux[i];
2405
3209
  if ( ret <= 0 ) {
2406
3210
  /***************************************/
@@ -2466,6 +3270,9 @@ int Create_INChI( INChI **ppINChI, INChI_Aux **ppINChI_Aux, ORIG_ATOM_DATA *ori
2466
3270
  #endif
2467
3271
  FreeNeighList( pCS->NeighList );
2468
3272
  DeAllocateCS( pCS2 );
3273
+
3274
+ pINChI = NULL; /* avoid dangling pointers */
3275
+ pINChI_Aux = NULL; /* avoid dangling pointers */
2469
3276
  }
2470
3277
  if ( ret == 0 ) {
2471
3278
  ret = num_atoms;
@@ -2478,7 +3285,11 @@ exit_function:
2478
3285
  inchi_free( at[TAUT_YES] );
2479
3286
  if ( at[TAUT_NON] )
2480
3287
  inchi_free( at[TAUT_NON] );
2481
- free_t_group_info( t_group_info );
3288
+ if ( ti_out ) {
3289
+ *ti_out = *t_group_info;
3290
+ } else {
3291
+ free_t_group_info( t_group_info );
3292
+ }
2482
3293
  free_t_group_info( t_group_info_orig );
2483
3294
  return ret;
2484
3295
  }
@@ -3499,7 +4310,7 @@ exit_function:
3499
4310
 
3500
4311
  /***************************************************************************************/
3501
4312
  int FillOutInputInfAtom(inp_ATOM *inp_at, INF_ATOM_DATA *inf_at_data, int init_num_at, int num_removed_H,
3502
- int nNumRemovedProtons, NUM_H *nNumRemovedProtonsIsotopic, int bIsotopic, int bAbcNumbers)
4313
+ int bAdd_DT_to_num_H, int nNumRemovedProtons, NUM_H *nNumRemovedProtonsIsotopic, int bIsotopic, int bAbcNumbers)
3503
4314
  {
3504
4315
  int i, j, m, n, ret, len_str, len, atw;
3505
4316
  int num_iso_H[NUM_H_ISOTOPES];
@@ -3520,16 +4331,6 @@ int FillOutInputInfAtom(inp_ATOM *inp_at, INF_ATOM_DATA *inf_at_data, int init_n
3520
4331
 
3521
4332
  inf_at_data->nNumRemovedProtons = nNumRemovedProtons;
3522
4333
  MakeRemovedProtonsString( nNumRemovedProtons, nNumRemovedProtonsIsotopic, NULL, bIsotopic, inf_at_data->szRemovedProtons, NULL );
3523
- /*
3524
- if ( inf_at_data->nNumRemovedProtons ) {
3525
- sprintf ( inf_at_data->szRemovedProtons, "Proton balance: %c %d H+",
3526
- inf_at_data->nNumRemovedProtons>=0? '+':'-',
3527
- abs(inf_at_data->nNumRemovedProtons) );
3528
- } else {
3529
- inf_at_data->szRemovedProtons[0] = '\0';
3530
-
3531
- }
3532
- */
3533
4334
  /* atom canonical and equivalence numbers > 0 */
3534
4335
  for ( i = 0; i < num_at; i ++ ) {
3535
4336
  #if( DISPLAY_ORIG_AT_NUMBERS == 1 )
@@ -3577,7 +4378,7 @@ int FillOutInputInfAtom(inp_ATOM *inp_at, INF_ATOM_DATA *inf_at_data, int init_n
3577
4378
  }
3578
4379
  }
3579
4380
  }
3580
- if ( bIsotopic ) {
4381
+ if ( bIsotopic && !bAdd_DT_to_num_H ) {
3581
4382
  /* subtract number of isotopic H atoms from the total number of H atoms */
3582
4383
  for ( j = 0; j < NUM_H_ISOTOPES; j ++ ) {
3583
4384
  n -= num_iso_H[j];
@@ -3656,7 +4457,7 @@ int FillOutInputInfAtom(inp_ATOM *inp_at, INF_ATOM_DATA *inf_at_data, int init_n
3656
4457
  }
3657
4458
  /**********************************************************************************************/
3658
4459
  int FillOutInfAtom(inp_ATOM *norm_at, INF_ATOM_DATA *inf_norm_at_data, int init_num_at, int num_removed_H,
3659
- int nNumRemovedProtons, NUM_H *nNumRemovedProtonsIsotopic, int bIsotopic,
4460
+ int bAdd_DT_to_num_H, int nNumRemovedProtons, NUM_H *nNumRemovedProtonsIsotopic, int bIsotopic,
3660
4461
  INChI *pINChI, INChI_Aux *pINChI_Aux, int bAbcNumbers, INCHI_MODE nMode )
3661
4462
  {
3662
4463
  if ( norm_at && inf_norm_at_data && inf_norm_at_data->at ) {
@@ -3664,7 +4465,7 @@ int FillOutInfAtom(inp_ATOM *norm_at, INF_ATOM_DATA *inf_norm_at_data, int init_
3664
4465
  return FillOutCanonInfAtom( norm_at, inf_norm_at_data, init_num_at, bIsotopic, pINChI,
3665
4466
  pINChI_Aux, bAbcNumbers, nMode);
3666
4467
  } else {
3667
- return FillOutInputInfAtom( norm_at, inf_norm_at_data, init_num_at, num_removed_H,
4468
+ return FillOutInputInfAtom( norm_at, inf_norm_at_data, init_num_at, num_removed_H, bAdd_DT_to_num_H,
3668
4469
  nNumRemovedProtons, nNumRemovedProtonsIsotopic, bIsotopic, bAbcNumbers);
3669
4470
  }
3670
4471
  }
@@ -3689,7 +4490,7 @@ int FillOutCompositeCanonInfAtom(COMP_ATOM_DATA *composite_norm_data, INF_ATOM_D
3689
4490
  offset_H = composite_norm_data->num_at - composite_norm_data->num_removed_H;
3690
4491
  if ( bTautomeric == TAUT_INI ) {
3691
4492
  ret = FillOutInputInfAtom( composite_norm_data->at, inf_norm_at_data, composite_norm_data->num_at,
3692
- composite_norm_data->num_removed_H,
4493
+ composite_norm_data->num_removed_H, 0 /*bAdd_DT_to_num_H*/,
3693
4494
  composite_norm_data->nNumRemovedProtons,
3694
4495
  composite_norm_data->nNumRemovedProtonsIsotopic,
3695
4496
  bIsotopic, bAbcNumbers);