rino 0.1.0 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (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);