Branch data Line data Source code
1 : : /*
2 : : * International Chemical Identifier (InChI)
3 : : * Version 1
4 : : * Software version 1.07
5 : : * April 30, 2024
6 : : *
7 : : * MIT License
8 : : *
9 : : * Copyright (c) 2024 IUPAC and InChI Trust
10 : : *
11 : : * Permission is hereby granted, free of charge, to any person obtaining a copy
12 : : * of this software and associated documentation files (the "Software"), to deal
13 : : * in the Software without restriction, including without limitation the rights
14 : : * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
15 : : * copies of the Software, and to permit persons to whom the Software is
16 : : * furnished to do so, subject to the following conditions:
17 : : *
18 : : * The above copyright notice and this permission notice shall be included in all
19 : : * copies or substantial portions of the Software.
20 : : *
21 : : * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
22 : : * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
23 : : * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
24 : : * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
25 : : * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
26 : : * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
27 : : * SOFTWARE.
28 : : *
29 : : * The InChI library and programs are free software developed under the
30 : : * auspices of the International Union of Pure and Applied Chemistry (IUPAC).
31 : : * Originally developed at NIST.
32 : : * Modifications and additions by IUPAC and the InChI Trust.
33 : : * Some portions of code were developed/changed by external contributors
34 : : * (either contractor or volunteer) which are listed in the file
35 : : * 'External-contributors' included in this distribution.
36 : : *
37 : : * info@inchi-trust.org
38 : : *
39 : : */
40 : :
41 : : #include <stdlib.h>
42 : : #include <string.h>
43 : : #include <ctype.h>
44 : : #include <math.h>
45 : : #include <stdbool.h>
46 : : #include <limits.h>
47 : :
48 : : #include "mode.h"
49 : : #include "ichinorm.h" /* @nnuk */
50 : : #include "strutil.h"
51 : : #include "ichister.h"
52 : : #include "ichi_io.h"
53 : : #include "ichimain.h"
54 : : #include "ichidrp.h" /* @nnuk */
55 : :
56 : : #include "bcf_s.h"
57 : :
58 : : /* Added fix to remove_ion_pairs() -- 2010-03-17 DT */
59 : : #define FIX_P_IV_Plus_O_Minus
60 : :
61 : : #ifndef COMPILE_ALL_CPP
62 : : #ifdef __cplusplus
63 : : extern "C"
64 : : {
65 : : #endif
66 : : #endif
67 : :
68 : : /* Defined in ichisort.c, prototype in ichicomn.h */
69 : : int insertions_sort_AT_RANK(AT_RANK *base, int num);
70 : :
71 : : #ifndef COMPILE_ALL_CPP
72 : : #ifdef __cplusplus
73 : : }
74 : : #endif
75 : : #endif
76 : :
77 : : typedef struct tagTreeAtom
78 : : {
79 : : AT_NUMB neighbor[MAXVAL]; /* positions (from 0) of the neighbors in the inp_ATOM array */
80 : : S_CHAR valence; /* number of bonds = number of neighbors */
81 : : AT_NUMB nRingSystem;
82 : : AT_NUMB nBlockSystem;
83 : : S_CHAR bCutVertex;
84 : : } tre_ATOM;
85 : :
86 : : /* Local prototypes */
87 : :
88 : : int cmp_iso_atw_diff_component_no(const void *a1, const void *a2);
89 : : int cmp_components(const void *a1, const void *a2);
90 : : /* int mark_one_struct_component( inp_ATOM* at,
91 : : int j,
92 : : AT_NUMB *mark,
93 : : AT_NUMB num_disconnected_components );
94 : : */
95 : : INChI_Stereo *Alloc_INChI_Stereo(int num_at, int num_bonds);
96 : : static int is_only_HDT_neighbors(const inp_ATOM* at, int num_atoms, int metal_idx);
97 : : int RemoveInpAtBond(inp_ATOM *at, int iat, int k);
98 : : int DisconnectInpAtBond(inp_ATOM *at,
99 : : AT_NUMB *nOldCompNumber,
100 : : int iat,
101 : : int neigh_ord);
102 : : int move_explicit_Hcation(inp_ATOM *at,
103 : : int num_at,
104 : : int iat,
105 : : int iat_H,
106 : : int bInAllComponents);
107 : : int DisconnectOneLigand(inp_ATOM *at,
108 : : AT_NUMB *nOldCompNumber,
109 : : S_CHAR *bMetal,
110 : : char *elnumber_Heteroat,
111 : : int num_halogens,
112 : : int num_atoms,
113 : : int iMetal,
114 : : int jLigand,
115 : : INCHI_MODE *bTautFlagsDone);
116 : : int bIsAmmoniumSalt(inp_ATOM *at,
117 : : int i,
118 : : int *piO,
119 : : int *pk,
120 : : S_CHAR *num_explicit_H);
121 : : int DisconnectAmmoniumSalt(inp_ATOM *at,
122 : : int i,
123 : : int iO,
124 : : int k,
125 : : S_CHAR *num_explicit_H);
126 : : /*int bIsMetalSalt( inp_ATOM *at, int i ); - moved to strutil,h */
127 : : int DisconnectMetalSalt(inp_ATOM *at, int i);
128 : : int bIsMetalToDisconnect(inp_ATOM *at, int i, int bCheckMetalValence);
129 : : int get_iat_number(int el_number);
130 : : int tot_unsat(int unsat[]);
131 : : int max_unsat(int unsat[]);
132 : : double dist3D(inp_ATOM *at1, inp_ATOM *at2);
133 : : double dist2D(inp_ATOM *at1, inp_ATOM *at2);
134 : : double dist_from_segm(double x, double y,
135 : : double x1, double y1,
136 : : double x2, double y2);
137 : : int segments_intersect(double x11, double y11,
138 : : double x12, double y12, /* segment #1 */
139 : : double x21, double y21,
140 : : double x22, double y22);
141 : : double GetMinDistDistribution(inp_ATOM *at,
142 : : int num_at,
143 : : int iat,
144 : : int iat_H,
145 : : int bInAllComponents,
146 : : double min_dist[],
147 : : int num_segm);
148 : : int nFindOneOM(inp_ATOM *at,
149 : : int at_no,
150 : : int ord_OM[],
151 : : int num_OM);
152 : : int the_only_doublet_neigh(inp_ATOM *at, int i1, int *ineigh1, int *ineigh2);
153 : : int fix_non_uniform_drawn_oxoanions(int num_atoms, inp_ATOM *at, int *num_changes);
154 : : int fix_non_uniform_drawn_amidiniums(int num_atoms, inp_ATOM *at, int *num_changes);
155 : :
156 : : void add_bond_if_unseen(subgraf_pathfinder *spf,
157 : : int node0, int node,
158 : : int *nbonds, int **bonds);
159 : :
160 : : /****************************************************************************/
161 : : #ifndef NUMH
162 : : #define NUM_ISO_H(AT, N) (AT[N].num_iso_H[0] + AT[N].num_iso_H[1] + AT[N].num_iso_H[2])
163 : : #define NUMH(AT, N) (AT[N].num_H + NUM_ISO_H(AT, N))
164 : : #endif
165 : : /****************************************************************************/
166 : :
167 : : /****************************************************************************/
168 : 0 : int cmp_iso_atw_diff_component_no(const void *a1, const void *a2)
169 : : {
170 : 0 : int ret = (int)((const inp_ATOM *)a1)->iso_atw_diff - (int)((const inp_ATOM *)a2)->iso_atw_diff;
171 [ # # ]: 0 : if (!ret) /* make the sort stable */
172 : : {
173 : 0 : ret = (int)((const inp_ATOM *)a1)->component - (int)((const inp_ATOM *)a2)->component;
174 : : }
175 : :
176 : 0 : return ret;
177 : : }
178 : :
179 : : /****************************************************************************/
180 : 0 : int the_only_doublet_neigh(inp_ATOM *at,
181 : : int i1,
182 : : int *ineigh1,
183 : : int *ineigh2)
184 : : {
185 : 0 : int i, neigh1, num_rad1 = 0, num_rad2 = 0;
186 : :
187 : 0 : inp_ATOM *a = at + i1, *b;
188 [ # # ]: 0 : if (RADICAL_DOUBLET != a->radical)
189 : : {
190 : 0 : return -1;
191 : : }
192 [ # # ]: 0 : for (i = 0; i < a->valence; i++)
193 : : {
194 : 0 : b = at + ((int)a->neighbor[i]); /* djb-rwth: removing redundant code */
195 [ # # ]: 0 : if (RADICAL_DOUBLET == b->radical)
196 : : {
197 : 0 : num_rad1++;
198 : 0 : *ineigh1 = i;
199 : : }
200 : : }
201 : :
202 [ # # ]: 0 : if (1 == num_rad1)
203 : : {
204 : 0 : a = at + (neigh1 = (int)a->neighbor[*ineigh1]);
205 [ # # ]: 0 : for (i = 0; i < a->valence; i++)
206 : : {
207 : 0 : b = at + (int)a->neighbor[i];
208 [ # # ]: 0 : if (RADICAL_DOUBLET == b->radical)
209 : : {
210 : 0 : num_rad2++;
211 : 0 : *ineigh2 = i;
212 : : }
213 : : }
214 : :
215 [ # # ]: 0 : if (1 == num_rad2)
216 : : {
217 : 0 : return neigh1;
218 : : }
219 : : }
220 : :
221 : 0 : return -1;
222 : : }
223 : :
224 : : /****************************************************************************
225 : : Correct non-uniformly drawn oxoanions
226 : : ****************************************************************************/
227 : 54 : int fix_non_uniform_drawn_oxoanions(int num_atoms,
228 : : inp_ATOM *at,
229 : : int *num_changes)
230 : : {
231 : : /* For central halogen, apply the following
232 : : correction rules:
233 : :
234 : : O O(-)
235 : : || |
236 : : O=Hal(-)=O ===> O=Hal=O
237 : : || ||
238 : : O O
239 : :
240 : : (perchlorate, etc.)
241 : :
242 : :
243 : : O O(-)
244 : : || |
245 : : Hal(-)=O ===> Hal=O
246 : : || ||
247 : : O O
248 : :
249 : : (chlorate, etc.)
250 : :
251 : : O O(-)
252 : : || |
253 : : Hal(-)=O ===> Hal=O
254 : :
255 : :
256 : : (chlorite, etc.)
257 : :
258 : : Hal(-)=O ===> Hal-O(-)
259 : :
260 : :
261 : : (hypochlorite, etc.)
262 : :
263 : :
264 : :
265 : : For halcogenes (S, Se, Te)
266 : : Y Y(-)
267 : : || |
268 : : RnX(-) ===> RnX
269 : :
270 : : if:
271 : : 1) (X = S, Y = O) || (X = Se, Y = S, O) || (X = Te, Y = O, S, Se)
272 : : 2) valence of X exceeds 6, in initially drawn form
273 : :
274 : :
275 : : So the following is corrected:
276 : :
277 : : O O(-)
278 : : || |
279 : : O=S(-)-R ===> O=S-R
280 : : || ||
281 : : O O
282 : :
283 : : Or
284 : :
285 : : O O-
286 : : || |
287 : : F5Te(-) ===> F5Te
288 : :
289 : : but the following remains unchanged:
290 : :
291 : :
292 : : O
293 : : ||
294 : : O=S(-)-R
295 : :
296 : :
297 : : The central atom (of IUPAC Group 16-17) is shown as negative but it contains double bond(s)
298 : : to terminal atom of greater electronegativity (of Group 16).
299 : : The central atom is halcogen (S,Se,Te) in highest oxidation state or halogen.
300 : :
301 : : Fix:
302 : : move negative charge to terminal atom and change double bond to a single one.
303 : :
304 : : Eligible central atom Eligible terminal atom at double bond's end
305 : : Cl O
306 : : Br O
307 : : I O
308 : : [At S,Se,Te]
309 : : S O
310 : : Se O,S
311 : : Te O, S, Se
312 : :
313 : : Comments:
314 : : 1. Central atoms of Groups 13-15 are not considered.
315 : : 2. Pauling electronegativities are:
316 : : F(3.98) > O(3.44) > Cl (3.16) > N (3.04) > Br(2.96) > I(2.66) > S(2.58) > Se(2.55) > At (2.2) > Te(2.1)
317 : :
318 : :
319 : : */
320 : :
321 : : /* constants for element numbers */
322 : : enum elems
323 : : {
324 : : dNone,
325 : : dCl = 17,
326 : : dBr = 35,
327 : : dI = 53,
328 : : dAt = 85,
329 : : dO = 8,
330 : : dS = 16,
331 : : dSe = 34,
332 : : dTe = 52,
333 : : dP = 15,
334 : : dC = 6,
335 : : dN = 7
336 : : };
337 : :
338 : : static U_CHAR allowed_elnums_center_halogen[] = {dCl, dBr, dI, dAt};
339 : : static U_CHAR allowed_elnums_center_halcogen[] = {dS, dSe, dTe};
340 : :
341 : : int en_center;
342 : : int i, j, k;
343 : :
344 [ + + ]: 673 : for (i = 0; i < num_atoms; i++)
345 : : {
346 : : /* Find appropriate central atom. This center should be: ...*/
347 : :
348 : : /* charged exactly (-1) ... */
349 [ + + ]: 619 : if (at[i].charge != -1)
350 : : {
351 : 613 : continue;
352 : : }
353 : 6 : en_center = at[i].el_number;
354 : : /* from eligible element list ... */
355 [ + - ]: 6 : if (!memchr(allowed_elnums_center_halogen, en_center, sizeof(allowed_elnums_center_halogen)))
356 : : {
357 : : /* central atom is not not halogen; check if it is halcogen */
358 [ - + ]: 6 : if (memchr(allowed_elnums_center_halcogen, en_center, sizeof(allowed_elnums_center_halcogen)))
359 : : {
360 [ # # ]: 0 : if (at[i].chem_bonds_valence < 7)
361 : : {
362 : : /* central atom is anionic halcogen, but not in the highest oxidation state */
363 : 0 : continue;
364 : : }
365 : : }
366 : : else
367 : : {
368 : 6 : continue;
369 : : }
370 : : }
371 : :
372 : : /* OK, found central halogen or eligible central halcogen. */
373 : :
374 : : /* non-radical... */
375 [ # # # # ]: 0 : if (at[i].radical && (at[i].radical != RADICAL_SINGLET))
376 : : {
377 : 0 : continue;
378 : : }
379 : :
380 : : /* Center found, now examine the adjacent terminals... */
381 : : {
382 : 0 : int en_term, kk = 0, jj = 0, min_en = 999, iso = 0, min_iso = 999;
383 : 0 : jj = -1;
384 [ # # ]: 0 : for (k = 0; k < at[i].valence; k++)
385 : : {
386 : 0 : j = at[i].neighbor[k];
387 : :
388 : : /* Terminal should be: ... */
389 : :
390 : : /* terminal... */
391 [ # # ]: 0 : if (at[j].valence != 1)
392 : : {
393 : 0 : continue;
394 : : }
395 : : /* double-bonded ... */
396 [ # # ]: 0 : if (at[i].bond_type[k] != BOND_TYPE_DOUBLE)
397 : : {
398 : 0 : continue;
399 : : }
400 : : /* zero-charged ... */
401 [ # # ]: 0 : if (at[j].charge != 0)
402 : : {
403 : 0 : continue;
404 : : }
405 : : /* non-radical */
406 [ # # # # ]: 0 : if (at[j].radical && (at[j].radical != RADICAL_SINGLET))
407 : : {
408 : 0 : continue;
409 : : }
410 : : /* of eligible elements list ... */
411 : 0 : en_term = at[j].el_number;
412 [ # # # # : 0 : switch (en_term)
# ]
413 : : {
414 : 0 : case dO:
415 : 0 : break;
416 : 0 : case dS:
417 [ # # # # : 0 : if ((en_center == dSe) || (en_center == dAt) || (en_center == dTe))
# # ]
418 : : break;
419 : 0 : continue;
420 : 0 : case dSe:
421 [ # # # # ]: 0 : if ((en_center == dAt) || (en_center == dTe))
422 : : break;
423 : 0 : continue;
424 : 0 : case dTe:
425 [ # # ]: 0 : if (en_center == dAt)
426 : 0 : break;
427 : 0 : continue;
428 : 0 : default:
429 : 0 : continue;
430 : : }
431 : :
432 : : /* From several candidates, select one with less el. number (==more electronegative). */
433 [ # # ]: 0 : if (en_term < min_en)
434 : : {
435 : 0 : min_en = en_term;
436 : 0 : kk = k;
437 : 0 : jj = j;
438 [ # # ]: 0 : min_iso = at[j].iso_atw_diff > 0 ? at[i].iso_atw_diff - 1 : at[i].iso_atw_diff;
439 : 0 : continue;
440 : : }
441 : : /* From same-element candidates, select one with less isotopic mass (arbitrary choice). */
442 [ # # ]: 0 : else if (en_term == min_en)
443 : : {
444 [ # # ]: 0 : iso = at[j].iso_atw_diff > 0 ? at[i].iso_atw_diff - 1 : at[i].iso_atw_diff;
445 [ # # ]: 0 : if (iso < min_iso)
446 : : {
447 : 0 : min_iso = iso;
448 : 0 : kk = k;
449 : 0 : jj = j;
450 : 0 : continue;
451 : : }
452 : : }
453 : : } /* end of checking nbrs. */
454 : :
455 : : /* If OK, apply changes. */
456 [ # # ]: 0 : if (jj >= 0)
457 : : {
458 : 0 : at[i].charge = 0;
459 : 0 : at[jj].charge = -1;
460 : 0 : at[i].bond_type[kk] = BOND_TYPE_SINGLE;
461 : 0 : at[jj].bond_type[0] = BOND_TYPE_SINGLE;
462 : 0 : at[i].bond_stereo[kk] = at[jj].bond_stereo[0] = 0;
463 : 0 : at[i].chem_bonds_valence--;
464 : 0 : at[jj].chem_bonds_valence--;
465 : 0 : (*num_changes)++;
466 : : }
467 : : }
468 : : } /* end of search for candidate centers. */
469 : :
470 : 54 : return 0;
471 : : }
472 : :
473 : : /****************************************************************************
474 : : Correct non-uniformly drawn amidinium cations.
475 : : ****************************************************************************/
476 : 54 : int fix_non_uniform_drawn_amidiniums(int num_atoms,
477 : : inp_ATOM *at,
478 : : int *num_changes)
479 : :
480 : : {
481 : : /* Amidines include carboxamidines RC(=NR)NR2,
482 : : sulfinamidines RS(=NR)NR2 and phosphinamidines, R2P(=NR)NR2.
483 : :
484 : :
485 : : NR NR
486 : : | |
487 : : R"-Y-NHR' ===> R"-Y=N(+)HR'
488 : : (+)
489 : :
490 : :
491 : : Y = C, S, P
492 : :
493 : :
494 : : Fix:
495 : : move positive charge to nitrogen and change single bond to a double one.
496 : :
497 : :
498 : : Comment:
499 : : Fix is applied only if at least one of R's at N is hydrogen
500 : : (otherwise we have just a '+' delocalization which is already recognized).
501 : :
502 : :
503 : : */
504 : :
505 : : /* constants for element numbers */
506 : : enum elems
507 : : {
508 : : dNone,
509 : : dCl = 17,
510 : : dBr = 35,
511 : : dI = 53,
512 : : dAt = 85,
513 : : dO = 8,
514 : : dS = 16,
515 : : dSe = 34,
516 : : dTe = 52,
517 : : dP = 15,
518 : : dC = 6,
519 : : dN = 7
520 : : };
521 : :
522 : : static U_CHAR allowed_elnums_center[] = {dC, dS, dP};
523 : : int en_center;
524 : : int i, j, k, jj, kk, k1;
525 : 54 : int mismatch = 0, nuH = 0, nuN = 0, nitrogens[MAXVAL];
526 : :
527 [ + + ]: 673 : for (i = 0; i < num_atoms; i++)
528 : : {
529 : : /* Find appropriate central atom. This center should be: ...*/
530 : :
531 : : /* charged exactly (+1) ... */
532 [ + - ]: 619 : if (at[i].charge != 1)
533 : : {
534 : 619 : continue;
535 : : }
536 : 0 : en_center = at[i].el_number;
537 : : /* from eligible element list ... */
538 [ # # ]: 0 : if (!memchr(allowed_elnums_center, en_center, sizeof(allowed_elnums_center)))
539 : : {
540 : 0 : continue;
541 : : }
542 : : /* has exactly 3 neighbours connected by single bonds*/
543 [ # # ]: 0 : if (at[i].valence != 3)
544 : : {
545 : 0 : continue;
546 : : }
547 [ # # ]: 0 : if (at[i].chem_bonds_valence != 3)
548 : : {
549 : 0 : continue;
550 : : }
551 : :
552 : : /* non-radical. */
553 [ # # # # ]: 0 : if (at[i].radical && (at[i].radical != RADICAL_SINGLET))
554 : : {
555 : 0 : continue;
556 : : }
557 : :
558 : : /* NB: center must have neutral neighbours, two of them are aliphatic N's of which at least one bears H. */
559 : 0 : mismatch = nuH = nuN = kk = 0; /* djb-rwth: removing redundant code */
560 : 0 : memset(nitrogens, 0, sizeof(nitrogens)); /* djb-rwth: memset_s C11/Annex K variant? */
561 : 0 : jj = -1;
562 [ # # ]: 0 : for (k = 0; k < at[i].valence; k++)
563 : : {
564 : 0 : j = at[i].neighbor[k];
565 : :
566 [ # # ]: 0 : if (at[j].charge != 0)
567 : : {
568 : 0 : mismatch = 1;
569 : 0 : break;
570 : : }
571 [ # # ]: 0 : if (at[j].el_number == dN)
572 : : {
573 [ # # # # ]: 0 : if ((at[j].valence > 3) || (at[j].chem_bonds_valence > 3))
574 : : {
575 : 0 : mismatch = 1;
576 : 0 : break;
577 : : }
578 : 0 : nuH += NUMH(at, j);
579 : 0 : nuN++;
580 [ # # ]: 0 : if (jj < 0)
581 : : {
582 : 0 : jj = j;
583 : 0 : kk = k;
584 : : }
585 : : }
586 : : }
587 : :
588 : : /* If OK, apply changes. */
589 [ # # ]: 0 : if (mismatch)
590 : : {
591 : 0 : continue;
592 : : }
593 [ # # ]: 0 : if (nuN != 2)
594 : : {
595 : 0 : continue;
596 : : }
597 [ # # ]: 0 : if (nuH < 1)
598 : : {
599 : 0 : continue;
600 : : }
601 [ # # ]: 0 : if (jj >= 0)
602 : : {
603 : 0 : at[i].charge = 0;
604 : 0 : at[jj].charge = 1;
605 : 0 : at[i].bond_type[kk] = BOND_TYPE_DOUBLE;
606 [ # # # # ]: 0 : for (k1 = 0; k1 < at[jj].valence && i != at[jj].neighbor[k1]; k1++)
607 : : ;
608 : 0 : at[jj].bond_type[k1] = BOND_TYPE_DOUBLE;
609 : 0 : at[i].chem_bonds_valence++;
610 : 0 : at[jj].chem_bonds_valence++;
611 : : /* NB: do nothing with wedge stereo bonds (retain wedge) */
612 : :
613 : 0 : (*num_changes)++;
614 : : }
615 : : } /* end of search for candidate centers. */
616 : :
617 : 54 : return 0;
618 : : }
619 : :
620 : : /****************************************************************************
621 : : Not used --
622 : : int FixAromaticOxygenAndSulfur( inp_ATOM *atom )
623 : : {
624 : : if ( !atom->elname[1] && (atom->elname[0]=='O' || atom->elname[0]=='S') &&
625 : : atom->valence==2 && !atom->charge && !atom->radical &&
626 : : atom->bond_type[0] + atom->bond_type[1] == 3 ) {
627 : : atom->charge = 1;
628 : : return 1; // fixed
629 : : }
630 : : return 0;
631 : : }
632 : : ****************************************************************************/
633 : :
634 : : /****************************************************************************/
635 : 54 : int fix_odd_things(int num_atoms,
636 : : inp_ATOM *at,
637 : : int bFixBug,
638 : : int bFixNonUniformDraw)
639 : : {
640 : : /* N;P;As;Sb;O;S;Se;Te;C;Si */
641 : : static const U_CHAR en[] = {
642 : : EL_NUMBER_N,
643 : : EL_NUMBER_P,
644 : : EL_NUMBER_AS,
645 : : EL_NUMBER_SB,
646 : : EL_NUMBER_O,
647 : : EL_NUMBER_S,
648 : : EL_NUMBER_SE,
649 : : EL_NUMBER_TE};
650 : : static int ne = sizeof(en) / sizeof(en[0]);
651 : :
652 : : #define FIRST_NEIGHB2 4
653 : : #define FIRST_CENTER2 5
654 : :
655 : 54 : int i1, i2, k1, k2, c = -1, num_changes = 0;
656 : : /* djb-rwth: removing redundant variables */
657 : :
658 [ + - ]: 54 : if (bFixNonUniformDraw)
659 : : {
660 : : int ret1; /* djb-rwth: ignoring LLVM warning: variable used to store function return value */
661 : 54 : ret1 = fix_non_uniform_drawn_oxoanions(num_atoms, at, &num_changes); /* djb-rwth: ignoring LLVM warning: variable used to store function return value */
662 : 54 : ret1 = fix_non_uniform_drawn_amidiniums(num_atoms, at, &num_changes); /* djb-rwth: ignoring LLVM warning: variable used to store function return value */
663 : : }
664 : :
665 : : /* H(-)-X -> H-X(-); H(+)-X -> H-X(+) */
666 [ + + ]: 673 : for (i1 = 0; i1 < num_atoms; i1++)
667 : : {
668 [ + + ]: 619 : if (1 == at[i1].valence &&
669 [ - + ]: 308 : 1 == abs(at[i1].charge) &&
670 [ # # # # ]: 0 : (0 == at[i1].radical || RADICAL_SINGLET == at[i1].radical) &&
671 [ # # ]: 0 : BOND_TYPE_SINGLE == at[i1].bond_type[0] &&
672 [ # # # # ]: 0 : EL_NUMBER_H == at[i1].el_number && EL_NUMBER_H != at[i2 = (int)at[i1].neighbor[0]].el_number &&
673 [ # # # # ]: 0 : !NUMH(at, i1) && !NUMH(at, i2))
674 : : {
675 : 0 : at[i2].charge += at[i1].charge;
676 : 0 : at[i1].charge = 0;
677 : : }
678 : : }
679 : :
680 : : /* replace XHm(-)--Y==XHn(+) with XHm==Y--XHn, (n>=0 ,m>=0, X=N,P,As,Sb,O,S,Se,Te) */
681 [ + + ]: 673 : for (i1 = 0; i1 < num_atoms; i1++)
682 : : {
683 [ - + ]: 619 : if (1 != at[i1].charge ||
684 [ # # # # ]: 0 : (at[i1].radical && RADICAL_SINGLET != at[i1].radical) ||
685 [ # # ]: 0 : at[i1].chem_bonds_valence == at[i1].valence ||
686 [ # # ]: 0 : !memchr(en, at[i1].el_number, ne) ||
687 [ # # ]: 0 : get_el_valence(at[i1].el_number, at[i1].charge, 0) != at[i1].chem_bonds_valence + NUMH(at, i1)) /* djb-rwth: addressing LLVM warning */
688 : : {
689 : 619 : continue;
690 : : }
691 : :
692 : : /* found a candidate at[i1] for X in XHn(+) */
693 [ # # ]: 0 : if (1 == at[i1].valence &&
694 [ # # ]: 0 : BOND_TYPE_DOUBLE == at[i1].bond_type[0])
695 : : {
696 : 0 : c = (int)at[i1].neighbor[0];
697 [ # # ]: 0 : for (k2 = 0; k2 < at[c].valence; k2++)
698 : : {
699 : 0 : i2 = at[c].neighbor[k2];
700 [ # # ]: 0 : if (1 == at[i2].valence &&
701 [ # # ]: 0 : -1 == at[i2].charge &&
702 [ # # ]: 0 : at[i2].el_number == at[i1].el_number && /* exact match */
703 [ # # # # ]: 0 : (0 == at[i2].radical || RADICAL_SINGLET == at[i2].radical) &&
704 [ # # ]: 0 : BOND_TYPE_SINGLE == at[i2].bond_type[0] &&
705 : : /*memchr(en, at[i2].el_number, ne) &&*/
706 [ # # ]: 0 : get_el_valence(at[i2].el_number, at[i2].charge, 0) == at[i2].chem_bonds_valence + NUMH(at, i2))
707 : : {
708 : : /* found both X(-) and X(+); change bonds and remove charges */
709 [ # # # # ]: 0 : for (k1 = 0; k1 < at[c].valence && i1 != at[c].neighbor[k1]; k1++)
710 : : ;
711 : 0 : at[i1].charge = at[i2].charge = 0;
712 : 0 : at[i1].bond_type[0] = at[c].bond_type[k1] = BOND_TYPE_SINGLE;
713 : 0 : at[i1].chem_bonds_valence--;
714 : 0 : at[i2].bond_type[0] = at[c].bond_type[k2] = BOND_TYPE_DOUBLE;
715 : 0 : at[i2].chem_bonds_valence++;
716 : 0 : num_changes++;
717 : 0 : break;
718 : : }
719 : : }
720 : : }
721 : : else
722 : : {
723 : : /* explicit H case: detect H-neighbors and Y */
724 : : int ineigh, neigh, i1_c, i2_c, num_H_i1, num_H_i2;
725 [ # # ]: 0 : for (ineigh = 0, num_H_i1 = 0, i1_c = -1; ineigh < at[i1].valence; ineigh++)
726 : : {
727 : 0 : neigh = at[i1].neighbor[ineigh];
728 [ # # ]: 0 : if (at[neigh].el_number == EL_NUMBER_H)
729 : : {
730 [ # # ]: 0 : if (at[neigh].chem_bonds_valence == 1 &&
731 [ # # # # ]: 0 : (0 == at[neigh].radical || RADICAL_SINGLET == at[neigh].radical))
732 : : {
733 : 0 : num_H_i1++; /* found H-neighbor */
734 : : }
735 : : else
736 : : {
737 : : break; /* wrong neighbor */
738 : : }
739 : : }
740 [ # # ]: 0 : else if (at[i1].bond_type[ineigh] == BOND_TYPE_DOUBLE)
741 : : {
742 : : /* found a candidate for Y; bond must be double */
743 : 0 : i1_c = ineigh;
744 : 0 : c = neigh;
745 : : }
746 : : }
747 [ # # # # ]: 0 : if (i1_c < 0 || num_H_i1 + 1 != at[i1].valence)
748 : : {
749 : 0 : continue;
750 : : }
751 [ # # ]: 0 : for (k2 = 0; k2 < at[c].valence; k2++)
752 : : {
753 : 0 : i2 = at[c].neighbor[k2];
754 [ # # ]: 0 : if (-1 == at[i2].charge &&
755 [ # # ]: 0 : at[i2].el_number == at[i1].el_number && /* exact match */
756 [ # # # # ]: 0 : (0 == at[i2].radical || RADICAL_SINGLET == at[i2].radical) &&
757 [ # # ]: 0 : get_el_valence(at[i2].el_number, at[i2].charge, 0) == at[i2].chem_bonds_valence + NUMH(at, i2))
758 : : {
759 [ # # ]: 0 : for (ineigh = 0, num_H_i2 = 0, i2_c = -1; ineigh < at[i2].valence; ineigh++)
760 : : {
761 : 0 : neigh = at[i2].neighbor[ineigh];
762 [ # # ]: 0 : if (at[neigh].el_number == EL_NUMBER_H)
763 : : {
764 [ # # ]: 0 : if (at[neigh].chem_bonds_valence == 1 &&
765 [ # # # # ]: 0 : (0 == at[neigh].radical || RADICAL_SINGLET == at[neigh].radical))
766 : : {
767 : 0 : num_H_i2++; /* found H-neighbor */
768 : : }
769 : : else
770 : : {
771 : : break; /* wrong neighbor */
772 : : }
773 : : }
774 : : else
775 : : {
776 [ # # # # ]: 0 : if (c == neigh && at[i2].bond_type[ineigh] == BOND_TYPE_SINGLE)
777 : : {
778 : 0 : i2_c = ineigh; /* position of Y neighbor; bond must be single */
779 : : }
780 : : else
781 : : {
782 : : break;
783 : : }
784 : : }
785 : : }
786 [ # # ]: 0 : if (num_H_i2 + (i2_c >= 0) != at[i2].valence)
787 : : {
788 : 0 : continue;
789 : : }
790 : : /* found both X(-) and X(+); change bonds and remove charges */
791 [ # # # # ]: 0 : for (k1 = 0; k1 < at[c].valence && i1 != at[c].neighbor[k1]; k1++)
792 : : ;
793 [ # # # # ]: 0 : if ((i1_c >= 0) && (i2_c >= 0)) /* djb-rwth: fixing coverity ID #499537 */
794 : : {
795 : 0 : at[i1].charge = at[i2].charge = 0;
796 : 0 : at[i1].bond_type[i1_c] = at[c].bond_type[k1] = BOND_TYPE_SINGLE;
797 : 0 : at[i1].chem_bonds_valence--;
798 : 0 : at[i2].bond_type[i2_c] = at[c].bond_type[k2] = BOND_TYPE_DOUBLE;
799 : 0 : at[i2].chem_bonds_valence++;
800 : 0 : num_changes++;
801 : 0 : break;
802 : : }
803 : : else
804 : : {
805 : 0 : continue;
806 : : }
807 : : }
808 : : } /* k2 */
809 : : }
810 : : }
811 : :
812 : : /* Replace
813 : :
814 : : X- X X=O,S,Se,Te -- terminal atoms (NEIGHB2)
815 : : \ | \ ||
816 : : >Y++ with >Y Y=S,Se,Te -- central cation (CENTER2)
817 : : / | / ||
818 : : X- X Y valence=4, original Y bond valence = 4
819 : :
820 : :
821 : : --- the following case of P is processed separately in remove_ion_pairs()
822 : : --- therefire, it has been disabled here, see #ifndef FIX_P_IV_Plus_O_Minus -- 2010-03-17 DT
823 : :
824 : : X- X X=O,S,Se,Te -- terminal atoms (NEIGHB2)
825 : : \ | \ ||
826 : : >P+ with >P
827 : : / | / |
828 : : X- X- Y valence=4, original Y bond valence = 4
829 : :
830 : : */
831 : :
832 [ + + ]: 673 : for (i1 = 0; i1 < num_atoms; i1++)
833 : : {
834 [ + + ]: 619 : if (1 == at[i1].valence &&
835 [ - + ]: 308 : -1 == at[i1].charge &&
836 [ # # # # ]: 0 : (0 == at[i1].radical || RADICAL_SINGLET == at[i1].radical) &&
837 [ # # ]: 0 : !NUMH(at, i1) &&
838 [ # # ]: 0 : BOND_TYPE_SINGLE == at[i1].bond_type[0] &&
839 [ # # ]: 0 : memchr(en + FIRST_NEIGHB2, at[i1].el_number, (long long)ne - FIRST_NEIGHB2)) /* djb-rwth: cast operator added */
840 : : {
841 : : int charge, i;
842 : : /* found a candidate for X */
843 : 0 : c = (int)at[i1].neighbor[0]; /* candidate for Y */
844 [ # # # # ]: 0 : if (((charge = 2) == at[c].charge && memchr(en + FIRST_CENTER2, at[c].el_number, (long long)ne - FIRST_CENTER2) /* djb-rwth: cast operator added */
845 : :
846 : : #ifndef FIX_P_IV_Plus_O_Minus
847 : : || (charge = 1) == at[c].charge && EL_NUMBER_P == at[c].el_number
848 : : #endif
849 : 0 : ) &&
850 [ # # ]: 0 : 4 == at[c].valence &&
851 [ # # # # ]: 0 : (0 == at[c].radical || RADICAL_SINGLET == at[c].radical) &&
852 [ # # ]: 0 : at[c].valence == at[c].chem_bonds_valence &&
853 [ # # ]: 0 : !NUMH(at, c))
854 : : {
855 : : ; /* accept */
856 : : }
857 : : else
858 : : {
859 : 0 : continue; /* ignore at[i1] */
860 : : }
861 [ # # ]: 0 : for (k2 = 0; k2 < at[c].valence; k2++)
862 : : {
863 : 0 : i2 = at[c].neighbor[k2];
864 [ # # ]: 0 : if (i2 == i1)
865 : : {
866 : 0 : continue;
867 : : }
868 [ # # ]: 0 : if (1 == at[i2].valence &&
869 [ # # ]: 0 : -1 == at[i2].charge &&
870 [ # # ]: 0 : memchr(en + FIRST_NEIGHB2, at[i2].el_number, (long long)ne - FIRST_NEIGHB2) && /* djb-rwth: cast operator added */
871 : : /*at[i2].el_number == at[i1].el_number &&*/ /* exact match */
872 [ # # # # ]: 0 : (0 == at[i2].radical || RADICAL_SINGLET == at[i2].radical) &&
873 [ # # ]: 0 : !NUMH(at, i2) &&
874 [ # # ]: 0 : BOND_TYPE_SINGLE == at[i2].bond_type[0])
875 : : {
876 : : /* found both X(-) and X(-); change bonds and remove charges */
877 [ # # # # ]: 0 : for (k1 = 0; k1 < at[c].valence && i1 != at[c].neighbor[k1]; k1++)
878 : : {
879 : : ;
880 : : }
881 [ # # ]: 0 : for (i = 0; i < charge; i++)
882 : : {
883 : : /* in case of P it does not matter which X atom is neutralized
884 : : because of tautomerism. However, neutral central atom is important
885 : : for the neutralization of the components */
886 [ # # # ]: 0 : switch (i)
887 : : {
888 : 0 : case 0:
889 : 0 : at[i1].charge++; /* = 0; changed 2010-03-17 DT*/
890 : 0 : at[i1].bond_type[0] = at[c].bond_type[k1] = BOND_TYPE_DOUBLE;
891 : 0 : at[i1].bond_stereo[0] = at[c].bond_stereo[k1] = 0;
892 : 0 : at[i1].chem_bonds_valence++;
893 : 0 : at[c].chem_bonds_valence++;
894 [ # # ]: 0 : if (bFixBug)
895 : 0 : at[c].charge--; /* added 2010-03-17 DT*/
896 : 0 : num_changes++;
897 : 0 : break;
898 : 0 : case 1:
899 : 0 : at[i2].charge++; /*= 0; changed 2010-03-17 DT*/
900 : 0 : at[i2].bond_type[0] = at[c].bond_type[k2] = BOND_TYPE_DOUBLE;
901 : 0 : at[i2].bond_stereo[0] = at[c].bond_stereo[k2] = 0;
902 : 0 : at[i2].chem_bonds_valence++;
903 : 0 : at[c].chem_bonds_valence++;
904 [ # # ]: 0 : if (bFixBug)
905 : 0 : at[c].charge--; /* added 2010-03-17 DT */
906 : 0 : num_changes++;
907 : 0 : break;
908 : : }
909 : : }
910 : :
911 : : /* -- removed -- 2010-03-17 DT
912 : : #if ( FIX_ODD_THINGS_REM_Plus_BUG == 1 )
913 : : at[c].charge -= charge;
914 : : #else
915 : : if ( bFixBug )
916 : : {
917 : : at[c].charge -= charge;
918 : : }
919 : : #endif
920 : : */
921 : 0 : break;
922 : : }
923 : : }
924 : : }
925 : : }
926 : :
927 : : /* A(doublet)-B(doublet) -> A=B (A and B have no other doublet neighbors) */
928 : : /* A(doublet)=B(doublet) -> A#B (A and B have no other doublet neighbors) */
929 [ + + ]: 673 : for (i1 = 0; i1 < num_atoms; i1++)
930 : : {
931 [ - + - - ]: 619 : if (RADICAL_DOUBLET == at[i1].radical &&
932 : 0 : 0 <= (i2 = the_only_doublet_neigh(at, i1, &k1, &k2)))
933 : : {
934 [ # # ]: 0 : if (at[i1].bond_type[k1] <= BOND_TYPE_DOUBLE)
935 : : {
936 : 0 : at[i1].bond_type[k1]++;
937 : 0 : at[i1].chem_bonds_valence++;
938 : 0 : at[i2].bond_type[k2]++;
939 : 0 : at[i2].chem_bonds_valence++;
940 : 0 : at[i1].radical = 0;
941 : 0 : at[i2].radical = 0;
942 : : }
943 : : }
944 : : }
945 : :
946 : : #if (REMOVE_ION_PAIRS_EARLY == 1)
947 : 54 : num_changes += remove_ion_pairs(num_atoms, at);
948 : : #endif
949 : :
950 : 54 : return num_changes;
951 : : }
952 : :
953 : : /****************************************************************************/
954 : 48 : int post_fix_odd_things(int num_atoms, inp_ATOM *at)
955 : : {
956 : 48 : int num_changes = 0;
957 : : /* currently does nothing */
958 : 48 : return num_changes;
959 : : }
960 : :
961 : : /****************************************************************************/
962 : 0 : int nFindOneOM(inp_ATOM *at, int at_no, int ord_OM[], int num_OM)
963 : : {
964 : : int i, n_OM, best_value, cur_value, diff; /* djb-rwth: removing redundant variables */
965 : : int num_best;
966 : :
967 [ # # ]: 0 : if (1 == num_OM)
968 : : {
969 : 0 : return ord_OM[0];
970 : : }
971 [ # # ]: 0 : if (1 > num_OM)
972 : : {
973 : 0 : return -1;
974 : : }
975 : :
976 : : /* select neighbors with min. number of bonds */
977 : 0 : num_best = 1;
978 : 0 : n_OM = (int)at[at_no].neighbor[ord_OM[0]];
979 : 0 : best_value = (int)at[n_OM].valence;
980 : : /* compare number of bonds; move indexes of the best neighbors to the first elements of ord_OM[] */
981 [ # # ]: 0 : for (i = 1; i < num_OM; i++)
982 : : {
983 : 0 : n_OM = at[at_no].neighbor[ord_OM[i]];
984 : 0 : cur_value = (int)at[n_OM].valence;
985 : 0 : diff = cur_value - best_value;
986 [ # # ]: 0 : if (diff < 0)
987 : : {
988 : : /* djb-rwth: removing redundant code */
989 : 0 : best_value = cur_value;
990 : 0 : ord_OM[0] = ord_OM[i];
991 : 0 : num_best = 1;
992 : : }
993 [ # # ]: 0 : else if (diff == 0)
994 : : { /* was '=', pointed by WDI */
995 : 0 : ord_OM[num_best++] = ord_OM[i];
996 : : }
997 : : }
998 : 0 : num_OM = num_best;
999 [ # # ]: 0 : if (1 == num_OM)
1000 : : {
1001 : 0 : return ord_OM[0];
1002 : : }
1003 : :
1004 : : /* select neighbors with min. periodic numbers */
1005 : 0 : num_best = 1;
1006 : 0 : n_OM = (int)at[at_no].neighbor[ord_OM[0]];
1007 : 0 : best_value = (int)at[n_OM].el_number;
1008 : :
1009 : : /* compare periodic numbers; move indexes of the best neighbors to the first elements of ord_OM[] */
1010 [ # # ]: 0 : for (i = 1; i < num_OM; i++)
1011 : : {
1012 : 0 : n_OM = at[at_no].neighbor[ord_OM[i]];
1013 : 0 : cur_value = (int)at[n_OM].el_number;
1014 : 0 : diff = cur_value - best_value;
1015 [ # # ]: 0 : if (diff < 0)
1016 : : {
1017 : : /* djb-rwth: removing redundant code */
1018 : 0 : best_value = cur_value;
1019 : 0 : ord_OM[0] = ord_OM[i];
1020 : 0 : num_best = 1;
1021 : : }
1022 [ # # ]: 0 : else if (diff == 0)
1023 : : { /* was '=', pointed by WDI */
1024 : 0 : ord_OM[num_best++] = ord_OM[i];
1025 : : }
1026 : : }
1027 : 0 : num_OM = num_best;
1028 [ # # ]: 0 : if (1 == num_OM)
1029 : : {
1030 : 0 : return ord_OM[0];
1031 : : }
1032 : :
1033 : : /* if neighbors are not terminal atoms then reject */
1034 [ # # ]: 0 : if (1 < at[n_OM].valence)
1035 : : {
1036 : 0 : return -1;
1037 : : }
1038 : :
1039 : : /* if neighbors are terminal atoms then the one without isotope or with lightest isotope */
1040 : 0 : num_best = 1;
1041 : 0 : n_OM = (int)at[at_no].neighbor[ord_OM[0]];
1042 : 0 : best_value = (int)at[n_OM].iso_atw_diff;
1043 : :
1044 : : /* compare periodic numbers; move indexes of the best neighbors to the first elements of ord_OM[] */
1045 [ # # ]: 0 : for (i = 1; i < num_OM; i++)
1046 : : {
1047 : 0 : n_OM = at[at_no].neighbor[ord_OM[i]];
1048 : 0 : cur_value = (int)at[n_OM].el_number;
1049 : 0 : diff = cur_value - best_value;
1050 [ # # # # : 0 : if ((!cur_value && best_value) || diff < 0)
# # ]
1051 : : {
1052 : : /* djb-rwth: removing redundant code */
1053 : 0 : best_value = cur_value;
1054 : 0 : ord_OM[0] = ord_OM[i];
1055 : 0 : num_best = 1;
1056 : : }
1057 [ # # ]: 0 : else if (diff == 0)
1058 : : {
1059 : : /* was '=', pointed by WDI */
1060 : 0 : ord_OM[num_best++] = ord_OM[i];
1061 : : }
1062 : : }
1063 : :
1064 : 0 : num_OM = num_best;
1065 [ # # ]: 0 : if (1 == num_OM)
1066 : : {
1067 : 0 : return ord_OM[0];
1068 : : }
1069 : :
1070 : : /* return any */
1071 : 0 : return ord_OM[0];
1072 : : }
1073 : :
1074 : : /****************************************************************************
1075 : : NB:
1076 : : the bonds are fixed in fix_special_bonds()
1077 : : ****************************************************************************/
1078 : 55 : int remove_ion_pairs(int num_atoms, inp_ATOM *at)
1079 : : {
1080 : 55 : int num_changes = 0;
1081 : : #define MAX_NEIGH 6
1082 : :
1083 : : int i, n, n2, i1, i2, i3, i4, type, chrg;
1084 : 55 : int num_C_II = 0, num_C_plus = 0, num_C_minus = 0, num_N_plus = 0, num_N_minus = 0, num_O_plus = 0, num_O_minus = 0, num_All;
1085 : :
1086 : : #ifdef FIX_P_IV_Plus_O_Minus
1087 : 55 : int num_P_IV_plus = 0; /* added 2010-03-17 DT */
1088 : : #endif
1089 : :
1090 : : inp_ATOM *a;
1091 : : /****** count candidates ********/
1092 [ + + ]: 685 : for (i = 0, a = at; i < num_atoms; i++, a++)
1093 : : {
1094 [ + - + + ]: 630 : if (1 == (chrg = a->charge) || -1 == chrg)
1095 : : {
1096 [ + - - + ]: 12 : switch (ion_el_group(a->el_number))
1097 : : {
1098 : 4 : case EL_NUMBER_C:
1099 [ - + ]: 4 : if (chrg > 0)
1100 : : {
1101 : 0 : num_C_plus++;
1102 : : }
1103 : : else
1104 : : {
1105 : 4 : num_C_minus++;
1106 : : }
1107 : 4 : break;
1108 : 0 : case EL_NUMBER_O:
1109 [ # # ]: 0 : if (chrg > 0)
1110 : : {
1111 : 0 : num_O_plus++;
1112 : : }
1113 : : else
1114 : : {
1115 : 0 : num_O_minus++;
1116 : : }
1117 : 0 : break;
1118 : 0 : case EL_NUMBER_N:
1119 [ # # ]: 0 : if (chrg > 0)
1120 : : {
1121 : 0 : num_N_plus++;
1122 : : }
1123 : : else
1124 : : {
1125 : 0 : num_N_minus++;
1126 : : }
1127 : : #ifdef FIX_P_IV_Plus_O_Minus
1128 [ # # ]: 0 : num_P_IV_plus += a->el_number != EL_NUMBER_N &&
1129 : 0 : chrg == 1 &&
1130 [ # # # # ]: 0 : a->valence == 4 &&
1131 [ # # ]: 0 : a->chem_bonds_valence == 4; /* added 2010-03-17 DT */
1132 : : #endif
1133 : 0 : break;
1134 : : }
1135 : : }
1136 [ + + + + : 684 : else if (!chrg && a->chem_bonds_valence + NUMH(a, 0) == 2 &&
- + ]
1137 [ - - ]: 62 : get_el_valence(a->el_number, 0, 0) == 4 &&
1138 : 0 : ion_el_group(a->el_number) == EL_NUMBER_C)
1139 : : {
1140 : 0 : num_C_II++;
1141 : : }
1142 : : }
1143 : :
1144 : 55 : num_All = num_C_II + num_C_plus + num_C_minus + num_N_plus + num_N_minus + num_O_plus + num_O_minus;
1145 : :
1146 : : /* do not add num_P_IV_plus ! -- 2010-03-17 DT */
1147 [ + + ]: 55 : if (!num_All)
1148 : : {
1149 : 53 : return 0;
1150 : : }
1151 : :
1152 : : /**************************************************************************/
1153 : : /*************************** Terminal ion pairs ***************************/
1154 : : /**************************************************************************/
1155 : :
1156 : : /*-------------------------------------------------------------------------
1157 : : Pair type 1 N=N,P,As,Sb; O=O,S,Se,Te
1158 : : ===========
1159 : :
1160 : : X X if X is another -O(-) then neutralize O(-)
1161 : : | | that has the smallest periodic table number
1162 : : O=N(+)-O(-) => O=N=O
1163 : : i n
1164 : : --------------------------------------------------------------------------*/
1165 : :
1166 [ + + ]: 38 : for (type = 1; type <= 18; type++)
1167 : : {
1168 [ + - + + ]: 36 : if ((!type || 1 == type))
1169 : : {
1170 [ + - - + : 2 : for (i = 0; i < num_atoms && 0 < num_N_plus && 0 < num_O_minus; i++)
- - ]
1171 : : {
1172 [ # # # # : 0 : if (1 == at[i].charge && 3 == nNoMetalNumBonds(at, i) &&
# # ]
1173 [ # # ]: 0 : 4 == nNoMetalBondsValence(at, i) &&
1174 : 0 : ion_el_group(at[i].el_number) == EL_NUMBER_N)
1175 : : {
1176 : 0 : int num_OM = 0, ord_OM[3]; /* -O(-) */
1177 : 0 : int num_O = 0; /* =O */
1178 : 0 : int num_O_other = 0;
1179 [ # # ]: 0 : for (i1 = 0; i1 < at[i].valence; i1++)
1180 : : {
1181 : 0 : n = at[i].neighbor[i1];
1182 [ # # # # : 0 : if (1 == nNoMetalNumBonds(at, n) && 0 == num_of_H(at, n) &&
# # ]
1183 : 0 : ion_el_group(at[n].el_number) == EL_NUMBER_O) /* djb-rwth: ignoring LLVM warning: variable used */
1184 : : {
1185 [ # # ]: 0 : if (BOND_TYPE_SINGLE == at[i].bond_type[i1] &&
1186 [ # # ]: 0 : -1 == at[n].charge)
1187 : : {
1188 : 0 : ord_OM[num_OM++] = i1;
1189 : : }
1190 [ # # ]: 0 : else if (BOND_TYPE_DOUBLE == at[n].bond_type[0] &&
1191 [ # # ]: 0 : 0 == at[n].charge)
1192 : : {
1193 : 0 : num_O++;
1194 : : }
1195 : : else
1196 : : {
1197 : 0 : num_O_other++;
1198 : : }
1199 : : }
1200 : : }
1201 [ # # # # : 0 : if (num_OM > 0 && num_O > 0 && !num_O_other &&
# # # # ]
1202 : 0 : 0 <= (i1 = nFindOneOM(at, i, ord_OM, num_OM)))
1203 : : {
1204 : : /* remove charges and increase bond order */
1205 : 0 : n = at[i].neighbor[i1];
1206 : 0 : i2 = (int)(is_in_the_list(at[n].neighbor, (AT_NUMB)i, at[n].valence) - at[n].neighbor);
1207 : 0 : at[i].bond_type[i1]++;
1208 : 0 : at[n].bond_type[i2]++;
1209 : 0 : at[i].chem_bonds_valence++;
1210 : 0 : at[n].chem_bonds_valence++;
1211 : 0 : at[i].charge--;
1212 : 0 : at[n].charge++;
1213 : 0 : at[i].radical = 0;
1214 : 0 : at[n].radical = 0;
1215 : 0 : num_changes++;
1216 : 0 : num_N_plus--;
1217 : 0 : num_O_minus--;
1218 : 0 : num_All -= 2;
1219 : : }
1220 : : }
1221 : : }
1222 : :
1223 : : #ifdef FIX_P_IV_Plus_O_Minus
1224 : :
1225 : : /*-------------------------------------------------------------------------
1226 : : Pair type 1a P=P,As,Sb; O=O,S,Se,Te -- added 2010-03-17
1227 : : =============
1228 : :
1229 : : X X if X, Y, or Z is another -O(-) then neutralize O(-)
1230 : : | | that has the smallest periodic table number
1231 : : Y-P(+)-O(-) => Y-P=O
1232 : : |i n |
1233 : : Z Z
1234 : :
1235 : : --------------------------------------------------------------------------*/
1236 : :
1237 [ + - - + : 2 : for (i = 0; i < num_atoms && 0 < num_P_IV_plus /*&& 0 < num_N_plus*/ && 0 < num_O_minus; i++)
- - ]
1238 : : {
1239 [ # # # # : 0 : if (1 == at[i].charge && 4 == nNoMetalNumBonds(at, i) &&
# # ]
1240 : 0 : 4 == nNoMetalBondsValence(at, i) &&
1241 [ # # # # ]: 0 : at[i].el_number != EL_NUMBER_N && ion_el_group(at[i].el_number) == EL_NUMBER_N)
1242 : : {
1243 : 0 : int num_OM = 0, ord_OM[4]; /* -O(-) */
1244 : : /*int num_O = 0;*/ /* =O */
1245 : : /* djb-rwth: removing redundant variables */
1246 [ # # ]: 0 : for (i1 = 0; i1 < at[i].valence; i1++)
1247 : : {
1248 : 0 : n = at[i].neighbor[i1];
1249 [ # # # # : 0 : if (1 == nNoMetalNumBonds(at, n) && 0 == num_of_H(at, n) &&
# # ]
1250 : 0 : ion_el_group(at[n].el_number) == EL_NUMBER_O) /* djb-rwth: ignoring LLVM warning: variable used */
1251 : : {
1252 [ # # ]: 0 : if (BOND_TYPE_SINGLE == at[i].bond_type[i1] &&
1253 [ # # ]: 0 : -1 == at[n].charge)
1254 : : {
1255 : 0 : ord_OM[num_OM++] = i1;
1256 : : /*
1257 : : }
1258 : : if ( BOND_TYPE_DOUBLE == at[n].bond_type[0] &&
1259 : : 0 == at[n].charge ) {
1260 : : num_O ++;
1261 : : */
1262 : : }
1263 : : /* djb-rwth: removing redundant code */
1264 : : }
1265 : : }
1266 [ # # # # ]: 0 : if (num_OM > 0 /*&& num_O > 0 && !num_O_other*/ &&
1267 : 0 : 0 <= (i1 = nFindOneOM(at, i, ord_OM, num_OM)))
1268 : : {
1269 : : /* remove charges and increase bond order */
1270 : 0 : n = at[i].neighbor[i1];
1271 : 0 : i2 = is_in_the_list(at[n].neighbor, (AT_NUMB)i, at[n].valence) - at[n].neighbor;
1272 : 0 : at[i].bond_type[i1]++;
1273 : 0 : at[n].bond_type[i2]++;
1274 : 0 : at[i].chem_bonds_valence++;
1275 : 0 : at[n].chem_bonds_valence++;
1276 : 0 : at[i].charge--;
1277 : 0 : at[n].charge++;
1278 : 0 : at[i].radical = 0;
1279 : 0 : at[n].radical = 0;
1280 : 0 : num_changes++;
1281 : 0 : num_N_plus--;
1282 : 0 : num_O_minus--;
1283 : 0 : num_P_IV_plus--;
1284 : 0 : num_All -= 2;
1285 : : }
1286 : : }
1287 : : }
1288 : : #endif /* FIX_P_IV_Plus_O_Minus */
1289 : : }
1290 : :
1291 : : /*-------------------------------------------------------------------------
1292 : : Terminal pair types: 2,3,4,5,6,7,8,9 N=N,P,As,Sb; O=O,S,Se,Te; C=C,Si
1293 : : ====================================
1294 : : type #
1295 : : 2 2: O=N-C(II)- => O=N#C- N=N,P,As,Sb; O=O,S,Se,Te; C=C,Si
1296 : : 3 9: O=O(+)-C(-)(III) => O=O=C(IV)
1297 : : 4 3: O(-)-N(+)(IV) => O=N(V) (input structure has at least 1 double bond)
1298 : : 5 4: O(-)-O(+)(III) => O=O(IV)
1299 : : 6 8: O(-)-O-C(+)(III) => O=O=C(IV)
1300 : : 7 5: N(-)=N(+)(IV) => N#N(V) allow terminal H on N(-)
1301 : : 8 6: N(-)=O(+)(III) => N#O-
1302 : : 9 7: N(-)=C(+)(III) => N#C-
1303 : : --------------------------------------------------------------------------*/
1304 : :
1305 [ + - + + : 36 : if (!type || (2 <= type && type <= 9)) /* djb-rwth: addressing LLVM warning */
+ + ]
1306 : : {
1307 [ + + + - ]: 192 : for (i = 0; i < num_atoms && 0 < num_All; i++)
1308 : : {
1309 [ + + - + : 176 : if (0 == at[i].charge && 1 == nNoMetalNumBonds(at, i) && 2 == nNoMetalBondsValence(at, i) &&
- - - - ]
1310 [ # # ]: 0 : 0 == num_of_H(at, i) &&
1311 [ # # ]: 0 : ion_el_group(at[i].el_number) == EL_NUMBER_O &&
1312 : 0 : 0 <= (i1 = nNoMetalNeighIndex(at, i)) &&
1313 [ # # ]: 0 : at[i].bond_type[i1] <= BOND_TYPE_TRIPLE)
1314 : : {
1315 : : /* terminal O= */
1316 : 0 : n = at[i].neighbor[i1];
1317 [ # # # # : 0 : if ((!type || type == 2) && 0 < num_C_II)
# # ]
1318 : : {
1319 : : /* avoid alternating bonds */
1320 [ # # # # ]: 0 : if (0 == at[n].charge &&
1321 [ # # # # ]: 0 : 2 == nNoMetalNumBonds(at, n) && 3 == nNoMetalBondsValence(at, n) &&
1322 [ # # ]: 0 : 0 == num_of_H(at, n) &&
1323 [ # # ]: 0 : ion_el_group(at[n].el_number) == EL_NUMBER_N &&
1324 : 0 : 0 <= (i2 = nNoMetalOtherNeighIndex(at, n, i)) &&
1325 [ # # ]: 0 : at[n].bond_type[i2] <= BOND_TYPE_TRIPLE)
1326 : : {
1327 : : /* i2 = index of opposite to at[i] neighbor of at[n] */
1328 : : /*i2 = (at[n].neighbor[0] == i);*/
1329 : 0 : n2 = at[n].neighbor[i2];
1330 [ # # ]: 0 : if (0 == at[n2].charge &&
1331 [ # # # # : 0 : 2 == at[n2].valence && 2 == at[n2].chem_bonds_valence &&
# # ]
1332 [ # # ]: 0 : 0 == num_of_H(at, n2) &&
1333 : 0 : ion_el_group(at[n2].el_number) == EL_NUMBER_C)
1334 : : {
1335 : : /* i n n2 */
1336 : : /* found O=N-C(II)- */
1337 : : /* convert O=N-C(II)- => O=N#C- */
1338 : :
1339 : 0 : i3 = (at[n2].neighbor[0] != n); /* index of at[n] neighbor of n2 */
1340 : 0 : at[n].chem_bonds_valence = 5; /* N */
1341 : 0 : at[n2].chem_bonds_valence = 4; /* C */
1342 : 0 : at[n].bond_type[i2] = BOND_TYPE_TRIPLE;
1343 : 0 : at[n2].bond_type[i3] = BOND_TYPE_TRIPLE;
1344 : 0 : at[n2].radical = 0;
1345 : 0 : num_changes++;
1346 : 0 : num_C_II--;
1347 : 0 : num_All--;
1348 : 0 : continue;
1349 : : }
1350 : : }
1351 : : }
1352 : :
1353 [ # # # # : 0 : if ((!type || type == 3) && 0 < num_O_plus && 0 < num_C_minus)
# # # # ]
1354 : : {
1355 [ # # # # : 0 : if (1 == at[n].charge && 2 == nNoMetalNumBonds(at, n) && 3 == nNoMetalBondsValence(at, n) &&
# # # # ]
1356 [ # # ]: 0 : 0 == num_of_H(at, n) &&
1357 [ # # ]: 0 : ion_el_group(at[n].el_number) == EL_NUMBER_O &&
1358 : 0 : 0 <= (i2 = nNoMetalOtherNeighIndex(at, n, i)) &&
1359 [ # # ]: 0 : at[n].bond_type[i2] <= BOND_TYPE_TRIPLE)
1360 : : {
1361 : : /* found O=O(+)- */
1362 : : /* i2 = index of opposite to at[i] neighbor of at[n] */
1363 : : /*i2 = (at[n].neighbor[0] == i);*/
1364 : 0 : n2 = at[n].neighbor[i2];
1365 [ # # # # : 0 : if (-1 == at[n2].charge && 3 >= nNoMetalNumBonds(at, n2) && 3 == nNoMetalBondsValence(at, n2) + NUMH(at, n2) &&
# # # # ]
1366 : 0 : ion_el_group(at[n2].el_number) == EL_NUMBER_C)
1367 : : {
1368 : : /* i n n2 */
1369 : : /* found found O=O(+)-C(-)(III) */
1370 : : /* convert O=O(+)-C(-)(III) => O=O=C(IV) */
1371 : 0 : i3 = (at[n2].neighbor[0] != n); /* index of at[n] neighbor of n2 */
1372 : 0 : at[n].charge--;
1373 : 0 : at[n2].charge++;
1374 : 0 : at[n].chem_bonds_valence += 1; /* =O- => =O= */
1375 : 0 : at[n2].chem_bonds_valence += 1; /* -C => =C */
1376 : 0 : at[n].bond_type[i2] = BOND_TYPE_DOUBLE;
1377 : 0 : at[n2].bond_type[i3] = BOND_TYPE_DOUBLE;
1378 : 0 : num_changes++;
1379 : 0 : num_O_plus--;
1380 : 0 : num_C_minus--;
1381 : 0 : num_All -= 2;
1382 : 0 : continue;
1383 : : }
1384 : : }
1385 : : }
1386 : : }
1387 : :
1388 [ + + ]: 176 : else if (-1 == at[i].charge &&
1389 [ - + ]: 32 : 0 < num_O_minus + num_N_minus &&
1390 [ # # # # ]: 0 : 0 < num_N_plus + num_O_plus + num_C_plus &&
1391 [ # # # # ]: 0 : 1 == nNoMetalNumBonds(at, i) && 1 == nNoMetalBondsValence(at, i) &&
1392 [ # # ]: 0 : 0 == num_of_H(at, i) &&
1393 [ # # ]: 0 : ion_el_group(at[i].el_number) == EL_NUMBER_O &&
1394 : 0 : 0 <= (i1 = nNoMetalNeighIndex(at, i)) &&
1395 [ # # ]: 0 : at[i].bond_type[i1] <= BOND_TYPE_TRIPLE)
1396 : : {
1397 : : /* terminal O(-)- */
1398 : 0 : n = at[i].neighbor[i1];
1399 : :
1400 [ # # # # : 0 : if ((!type || type == 4) && 0 < num_O_minus && 0 < num_N_plus && /* O(-)-N(+)(IV) */
# # # # ]
1401 [ # # # # : 0 : 1 == at[n].charge && 3 >= nNoMetalNumBonds(at, n) && 4 == nNoMetalBondsValence(at, n) &&
# # # # ]
1402 [ # # ]: 0 : 0 == num_of_H(at, n) &&
1403 : 0 : ion_el_group(at[n].el_number) == EL_NUMBER_N /* except >O(+)- */
1404 : : )
1405 : : {
1406 : : /* found O(-)-N(+)(IV) */
1407 : : /* convert O(-)-N(+)(IV) => O=N(V) */
1408 : :
1409 : 0 : i2 = (int)(is_in_the_list(at[n].neighbor, (AT_NUMB)i, at[n].valence) - at[n].neighbor); /* index of at[i] neighbor of at[n] */
1410 : 0 : at[i].charge++;
1411 : 0 : at[n].charge--;
1412 : 0 : at[i].chem_bonds_valence++;
1413 : 0 : at[n].chem_bonds_valence++;
1414 : 0 : at[i].bond_type[i1]++;
1415 : 0 : at[n].bond_type[i2]++;
1416 : 0 : num_changes++;
1417 : 0 : num_O_minus--;
1418 : 0 : num_N_plus--;
1419 : 0 : num_All -= 2;
1420 : 0 : continue;
1421 : : }
1422 : :
1423 [ # # # # : 0 : if ((!type || type == 5) && 0 < num_O_minus && 0 < num_O_plus && /* O(-)-O(+)(III) */
# # # # ]
1424 [ # # # # : 0 : 1 == at[n].charge && 3 >= nNoMetalNumBonds(at, n) && 3 == nNoMetalBondsValence(at, n) &&
# # # # ]
1425 [ # # ]: 0 : 0 == num_of_H(at, n) &&
1426 : 0 : ion_el_group(at[n].el_number) == EL_NUMBER_O /* except >O(+)- */
1427 : : )
1428 : : {
1429 : : /* found O(+)(III) */
1430 : : /* convert O(-)-O(+)(III) => O=O(IV) */
1431 : :
1432 : 0 : i2 = (int)(is_in_the_list(at[n].neighbor, (AT_NUMB)i, at[n].valence) - at[n].neighbor); /* index of at[i] neighbor of at[n] */
1433 : 0 : at[i].charge++;
1434 : 0 : at[n].charge--;
1435 : 0 : at[i].chem_bonds_valence++;
1436 : 0 : at[n].chem_bonds_valence++;
1437 : 0 : at[i].bond_type[i1]++;
1438 : 0 : at[n].bond_type[i2]++;
1439 : 0 : num_changes++;
1440 : 0 : num_O_minus--;
1441 : 0 : num_O_plus--;
1442 : 0 : num_All -= 2;
1443 : 0 : continue;
1444 : : }
1445 : :
1446 : : /* i n n2 */
1447 [ # # # # : 0 : if ((!type || type == 6) && /* O(-)-O-C(+)(III) */
# # ]
1448 [ # # ]: 0 : 0 < num_O_minus && 0 < num_C_plus &&
1449 [ # # # # : 0 : 0 == at[n].charge && 2 == nNoMetalNumBonds(at, n) && 2 == nNoMetalBondsValence(at, n) &&
# # # # ]
1450 [ # # ]: 0 : 0 == num_of_H(at, n) &&
1451 [ # # ]: 0 : ion_el_group(at[n].el_number) == EL_NUMBER_O &&
1452 : 0 : 0 <= (i2 = nNoMetalOtherNeighIndex(at, n, i)) &&
1453 [ # # ]: 0 : at[n].bond_type[i2] <= BOND_TYPE_TRIPLE)
1454 : : {
1455 : : /* found O(-)-O- */
1456 : : /* i2 = index of opposite to at[i] neighbor of at[n] */
1457 : : /*i2 = (at[n].neighbor[0] == i);*/
1458 : 0 : n2 = at[n].neighbor[i2];
1459 [ # # # # ]: 0 : if (1 == at[n2].charge && 3 >= nNoMetalNumBonds(at, n2) &&
1460 [ # # # # ]: 0 : 3 == nNoMetalBondsValence(at, n2) + NUMH(at, n2) &&
1461 : 0 : ion_el_group(at[n2].el_number) == EL_NUMBER_C)
1462 : : {
1463 : : /* i n n2 */
1464 : : /* found O(-)-O-C(+)(III) */
1465 : : /* convert O(-)-O-C(+)(III) => O=O=C(IV) */
1466 : : /*i3 = (at[n2].neighbor[0] != n);*/ /* i3 = index of at[n] neighbor of at[n2] */
1467 : 0 : i3 = (int)(is_in_the_list(at[n2].neighbor, (AT_NUMB)n, at[n2].valence) - at[n2].neighbor);
1468 : : /*i4 = index of at[i] in the adjacency list of at[n] */
1469 : 0 : i4 = (int)(is_in_the_list(at[n].neighbor, (AT_NUMB)i, at[n].valence) - at[n].neighbor);
1470 : 0 : at[i].charge++;
1471 : 0 : at[n2].charge--;
1472 : 0 : at[i].chem_bonds_valence += 1; /* O- => O= */
1473 : 0 : at[n].chem_bonds_valence += 2; /* -O- => =O= */
1474 : 0 : at[n2].chem_bonds_valence += 1; /* -C => =C */
1475 : 0 : at[i].bond_type[i1] = BOND_TYPE_DOUBLE;
1476 : 0 : at[n].bond_type[i4] = BOND_TYPE_DOUBLE;
1477 : 0 : at[n].bond_type[i2] = BOND_TYPE_DOUBLE;
1478 : 0 : at[n2].bond_type[i3] = BOND_TYPE_DOUBLE;
1479 : 0 : num_changes++;
1480 : 0 : num_O_minus--;
1481 : 0 : num_C_plus--;
1482 : 0 : num_All -= 2;
1483 : 0 : continue;
1484 : : }
1485 : : }
1486 : : }
1487 [ + + - + : 176 : else if (-1 == at[i].charge && 0 < num_N_minus && 0 < num_N_plus + num_O_plus + num_C_plus &&
- - - - ]
1488 [ # # # # ]: 0 : 1 == nNoMetalNumBonds(at, i) && 2 == nNoMetalBondsValence(at, i) + NUMH(at, i) &&
1489 : : /*0 == num_of_H( at, i ) &&*/
1490 [ # # ]: 0 : ion_el_group(at[i].el_number) == EL_NUMBER_N &&
1491 : 0 : 0 <= (i1 = nNoMetalNeighIndex(at, i)) &&
1492 [ # # ]: 0 : at[i].bond_type[i1] <= BOND_TYPE_TRIPLE)
1493 : : {
1494 : : /* terminal N(-)= */
1495 : 0 : n = at[i].neighbor[i1 = 0];
1496 [ # # # # : 0 : if ((!type || type == 7) && 0 < num_N_plus && /* N(-)=N(+)(IV) */
# # ]
1497 [ # # # # : 0 : 1 == at[n].charge && 3 >= nNoMetalNumBonds(at, n) && 4 == nNoMetalBondsValence(at, n) &&
# # # # ]
1498 [ # # ]: 0 : 0 == num_of_H(at, n) &&
1499 : 0 : ion_el_group(at[n].el_number) == EL_NUMBER_N)
1500 : : {
1501 : : /* found N(-)-N(+)(IV) */
1502 : : /* convert N(-)=N(+)(IV) => N#N(V) */
1503 : :
1504 : 0 : i2 = (int)(is_in_the_list(at[n].neighbor, (AT_NUMB)i, at[n].valence) - at[n].neighbor); /* index of at[i] neighbor of at[n] */
1505 : 0 : at[i].charge++;
1506 : 0 : at[n].charge--;
1507 : 0 : at[i].chem_bonds_valence++;
1508 : 0 : at[n].chem_bonds_valence++;
1509 : 0 : at[i].bond_type[i1]++;
1510 : 0 : at[n].bond_type[i2]++;
1511 : 0 : num_changes++;
1512 : 0 : num_N_minus--;
1513 : 0 : num_N_plus--;
1514 : 0 : num_All -= 2;
1515 : 0 : continue;
1516 : : }
1517 [ # # # # : 0 : if ((!type || type == 8) && 0 < num_O_plus && /* N(-)=O(+)(III) */
# # ]
1518 [ # # # # : 0 : 1 == at[n].charge && 2 == nNoMetalNumBonds(at, n) && 3 == nNoMetalBondsValence(at, n) &&
# # # # ]
1519 [ # # ]: 0 : 0 == num_of_H(at, n) &&
1520 : 0 : ion_el_group(at[n].el_number) == EL_NUMBER_O)
1521 : : {
1522 : : /* found N(-)-O(+)(III) */
1523 : : /* convert N(-)=O(+)(III) => N#O(IV)- */
1524 : 0 : i2 = (int)(is_in_the_list(at[n].neighbor, (AT_NUMB)i, at[n].valence) - at[n].neighbor); /* index of at[i] neighbor of at[n] */
1525 : 0 : at[i].charge++;
1526 : 0 : at[n].charge--;
1527 : 0 : at[i].chem_bonds_valence++;
1528 : 0 : at[n].chem_bonds_valence++;
1529 : 0 : at[i].bond_type[i1]++;
1530 : 0 : at[n].bond_type[i2]++;
1531 : 0 : num_changes++;
1532 : 0 : num_N_minus--;
1533 : 0 : num_O_plus--;
1534 : 0 : num_All -= 2;
1535 : 0 : continue;
1536 : : }
1537 [ # # # # : 0 : if ((!type || type == 9) && 0 < num_C_plus && /* N(-)=C(+)(III) */
# # ]
1538 [ # # # # : 0 : 1 == at[n].charge && 2 == at[n].valence && 3 == at[n].chem_bonds_valence &&
# # # # ]
1539 [ # # ]: 0 : 0 == num_of_H(at, n) &&
1540 : 0 : ion_el_group(at[n].el_number) == EL_NUMBER_C)
1541 : : {
1542 : : /* found N(-)=C(+)(III) */
1543 : : /* convert N(-)=C(+)(III) => N#C(IV)- */
1544 : :
1545 : 0 : i2 = (int)(is_in_the_list(at[n].neighbor, (AT_NUMB)i, at[n].valence) - at[n].neighbor); /* index of at[i] neighbor of at[n] */
1546 : 0 : at[i].charge++;
1547 : 0 : at[n].charge--;
1548 : 0 : at[i].chem_bonds_valence++;
1549 : 0 : at[n].chem_bonds_valence++;
1550 : 0 : at[i].bond_type[i1]++;
1551 : 0 : at[n].bond_type[i2]++;
1552 : 0 : num_changes++;
1553 : 0 : num_N_minus--;
1554 : 0 : num_C_plus--;
1555 : 0 : num_All -= 2;
1556 : 0 : continue;
1557 : : }
1558 : : }
1559 : : }
1560 : : }
1561 : :
1562 : : /**************************************************************************/
1563 : : /*********************** NON-Terminal ion pairs ***************************/
1564 : : /**************************************************************************/
1565 : : /*-------------------------------------------------------------------------
1566 : : Non-Terminal pair types: 10,11,12,13,14 N=N,P,As,Sb; O=O,S,Se,Te; C=C,Si
1567 : : ========================================
1568 : :
1569 : : 10: N(+)(IV)-C(-)(III) => N(V)=C(IV) (N has 3 or 2 bonds)
1570 : : 11: N(+)(IV)=C(-)(III) => N(V)#C(IV) (N has 3 or 2 bonds)
1571 : : 12: N(+)(IV)-N(-)(II) => N(V)=N(III) (allow terminal H on N(-))
1572 : : 13: -O(+)-C(-)(III) => -O=C-
1573 : : 14: -O(+)=C(-)(III) => -O#C-
1574 : : 15: O(+)(III)-N(-)(II) => O(IV)=N(III) (allow terminal H on N(-))
1575 : : --------------------------------------------------------------------------*/
1576 : :
1577 [ + - + + : 36 : if (!type || (10 <= type && type <= 15)) /* djb-rwth: addressing LLVM warning */
+ + ]
1578 : : {
1579 [ + + + - ]: 144 : for (i = 0; i < num_atoms && 0 < num_All; i++)
1580 : : {
1581 [ - + ]: 132 : if (1 == at[i].charge &&
1582 [ # # # # : 0 : 0 < num_N_plus + num_O_plus && 0 < num_C_minus + num_N_minus &&
# # ]
1583 [ # # # # ]: 0 : 4 >= nNoMetalNumBonds(at, i) && 4 == nNoMetalBondsValence(at, i) &&
1584 [ # # ]: 0 : 0 == num_of_H(at, i) &&
1585 : 0 : ion_el_group(at[i].el_number) == EL_NUMBER_N)
1586 : : {
1587 : : /* found non-terminal N(+)(IV) */
1588 [ # # # # : 0 : if ((!type || 10 == type) && 0 < num_N_plus && 0 < num_C_minus)
# # # # ]
1589 : : {
1590 : 0 : int num_neigh = 0, pos_neigh = -1;
1591 [ # # ]: 0 : for (i1 = 0; i1 < at[i].valence; i1++)
1592 : : {
1593 : 0 : n = at[i].neighbor[i1];
1594 [ # # # # : 0 : if (-1 == at[n].charge && 3 >= at[n].valence && 3 == at[n].chem_bonds_valence + NUMH(at, n) &&
# # ]
1595 : : /*0 == at[n].num_H &&*/
1596 [ # # # # ]: 0 : at[i].bond_type[i1] == BOND_TYPE_SINGLE &&
1597 : 0 : ion_el_group(at[n].el_number) == EL_NUMBER_C)
1598 : : {
1599 : : /* found N(+)(IV)-C(-)(III); prepare conversion to N(V)=C(IV) */
1600 : 0 : num_neigh++;
1601 : 0 : pos_neigh = i1;
1602 : : }
1603 : : }
1604 : 0 : i1 = pos_neigh;
1605 [ # # ]: 0 : if (1 == num_neigh &&
1606 [ # # # # ]: 0 : at[i].bond_type[i1] <= BOND_TYPE_TRIPLE &&
1607 [ # # ]: 0 : !has_other_ion_neigh(at, i, n = at[i].neighbor[i1]) &&
1608 : 0 : !has_other_ion_neigh(at, n, i))
1609 : : {
1610 : : /*n = at[i].neighbor[i1=pos_neigh];*/
1611 : 0 : i2 = (int)(is_in_the_list(at[n].neighbor, (AT_NUMB)i, at[n].valence) - at[n].neighbor);
1612 : 0 : at[i].charge--;
1613 : 0 : at[n].charge++;
1614 : 0 : at[i].chem_bonds_valence++;
1615 : 0 : at[n].chem_bonds_valence++;
1616 : 0 : at[i].bond_type[i1]++;
1617 : 0 : at[n].bond_type[i2]++;
1618 : 0 : num_changes++;
1619 : 0 : num_C_minus--;
1620 : 0 : num_N_plus--;
1621 : 0 : num_All -= 2;
1622 : 0 : continue;
1623 : : }
1624 : : }
1625 [ # # # # : 0 : if ((!type || 11 == type) && 0 < num_N_plus && 0 < num_C_minus)
# # # # ]
1626 : : {
1627 : 0 : int num_neigh = 0, pos_neigh = -1;
1628 [ # # ]: 0 : for (i1 = 0; i1 < at[i].valence; i1++)
1629 : : {
1630 : 0 : n = at[i].neighbor[i1];
1631 [ # # # # : 0 : if (-1 == at[n].charge && 3 >= at[n].valence && 3 == at[n].chem_bonds_valence + NUMH(at, n) &&
# # ]
1632 : : /*0 == at[n].num_H &&*/
1633 [ # # # # ]: 0 : at[i].bond_type[i1] == BOND_TYPE_DOUBLE &&
1634 : 0 : ion_el_group(at[n].el_number) == EL_NUMBER_C)
1635 : : {
1636 : : /* found N(+)(IV)=C(-)(III); prepare conversion to N(V)#C(IV) */
1637 : 0 : num_neigh++;
1638 : 0 : pos_neigh = i1;
1639 : : }
1640 : : }
1641 [ # # # # ]: 0 : if (1 == num_neigh &&
1642 [ # # ]: 0 : !has_other_ion_neigh(at, i, n = at[i].neighbor[i1 = pos_neigh]) &&
1643 : 0 : !has_other_ion_neigh(at, n, i))
1644 : : {
1645 : : /*n = at[i].neighbor[i1=pos_neigh];*/
1646 : 0 : i2 = (int)(is_in_the_list(at[n].neighbor, (AT_NUMB)i, at[n].valence) - at[n].neighbor);
1647 : 0 : at[i].charge--;
1648 : 0 : at[n].charge++;
1649 : 0 : at[i].chem_bonds_valence++;
1650 : 0 : at[n].chem_bonds_valence++;
1651 : 0 : at[i].bond_type[i1]++;
1652 : 0 : at[n].bond_type[i2]++;
1653 : 0 : num_changes++;
1654 : 0 : num_C_minus--;
1655 : 0 : num_N_plus--;
1656 : 0 : num_All -= 2;
1657 : 0 : continue;
1658 : : }
1659 : : }
1660 [ # # # # : 0 : if (!type || (12 == type && 0 < num_N_plus && 0 < num_N_minus)) /* djb-rwth: addressing LLVM warning */
# # # # ]
1661 : : {
1662 : 0 : int num_neigh = 0, pos_neigh = -1;
1663 [ # # ]: 0 : for (i1 = 0; i1 < at[i].valence; i1++)
1664 : : {
1665 : 0 : n = at[i].neighbor[i1];
1666 [ # # # # ]: 0 : if (-1 == at[n].charge && 2 >= nNoMetalNumBonds(at, n) &&
1667 [ # # ]: 0 : 2 == nNoMetalBondsValence(at, n) + NUMH(at, n) &&
1668 : : /*0 == num_of_H( at, n ) &&*/
1669 [ # # # # ]: 0 : at[i].bond_type[i1] == BOND_TYPE_SINGLE &&
1670 : 0 : ion_el_group(at[n].el_number) == EL_NUMBER_N)
1671 : : {
1672 : : /* found N(+)(IV)=N(-)(II); prepare conversion to N(V)#N(III) */
1673 : 0 : num_neigh++;
1674 : 0 : pos_neigh = i1;
1675 : : }
1676 : : }
1677 [ # # # # ]: 0 : if (1 == num_neigh &&
1678 [ # # ]: 0 : !has_other_ion_neigh(at, i, n = at[i].neighbor[i1 = pos_neigh]) &&
1679 : 0 : !has_other_ion_neigh(at, n, i))
1680 : : {
1681 : : /*n = at[i].neighbor[i1=pos_neigh];*/
1682 : 0 : i2 = (int)(is_in_the_list(at[n].neighbor, (AT_NUMB)i, at[n].valence) - at[n].neighbor);
1683 : 0 : at[i].charge--;
1684 : 0 : at[n].charge++;
1685 : 0 : at[i].chem_bonds_valence++;
1686 : 0 : at[n].chem_bonds_valence++;
1687 : 0 : at[i].bond_type[i1]++;
1688 : 0 : at[n].bond_type[i2]++;
1689 : 0 : num_changes++;
1690 : 0 : num_N_minus--;
1691 : 0 : num_N_plus--;
1692 : 0 : num_All -= 2;
1693 : 0 : continue;
1694 : : }
1695 : : }
1696 : : }
1697 [ - + - - ]: 132 : else if (1 == at[i].charge &&
1698 [ # # # # ]: 0 : 0 < num_O_plus && 0 < num_C_minus + num_N_minus &&
1699 [ # # # # ]: 0 : 3 >= nNoMetalNumBonds(at, i) && 3 == nNoMetalBondsValence(at, i) &&
1700 [ # # ]: 0 : 0 == num_of_H(at, i) &&
1701 : 0 : ion_el_group(at[i].el_number) == EL_NUMBER_O)
1702 : : {
1703 : : /* found non-terminal O(+)(III) */
1704 [ # # # # : 0 : if ((!type || 13 == type) && 0 < num_C_minus)
# # ]
1705 : : {
1706 : 0 : int num_neigh = 0, pos_neigh = -1;
1707 [ # # ]: 0 : for (i1 = 0; i1 < at[i].valence; i1++)
1708 : : {
1709 : 0 : n = at[i].neighbor[i1];
1710 [ # # # # : 0 : if (-1 == at[n].charge && 3 >= at[n].valence && 3 == at[n].chem_bonds_valence + NUMH(at, n) &&
# # ]
1711 : : /*0 == at[n].num_H &&*/
1712 [ # # # # ]: 0 : at[i].bond_type[i1] == BOND_TYPE_SINGLE &&
1713 : 0 : ion_el_group(at[n].el_number) == EL_NUMBER_C)
1714 : : {
1715 : : /* found O(+)(III)-C(-)(II); prepare conversion to O(IV)=C(IV) */
1716 : 0 : num_neigh++;
1717 : 0 : pos_neigh = i1;
1718 : : }
1719 : : }
1720 [ # # # # ]: 0 : if (1 == num_neigh &&
1721 [ # # ]: 0 : !has_other_ion_neigh(at, i, n = at[i].neighbor[i1 = pos_neigh]) &&
1722 : 0 : !has_other_ion_neigh(at, n, i))
1723 : : {
1724 : : /*n = at[i].neighbor[i1=pos_neigh];*/
1725 : 0 : i2 = (int)(is_in_the_list(at[n].neighbor, (AT_NUMB)i, at[n].valence) - at[n].neighbor);
1726 : 0 : at[i].charge--;
1727 : 0 : at[n].charge++;
1728 : 0 : at[i].chem_bonds_valence++;
1729 : 0 : at[n].chem_bonds_valence++;
1730 : 0 : at[i].bond_type[i1]++;
1731 : 0 : at[n].bond_type[i2]++;
1732 : 0 : num_changes++;
1733 : 0 : num_C_minus--;
1734 : 0 : num_O_plus--;
1735 : 0 : num_All -= 2;
1736 : 0 : continue;
1737 : : }
1738 : : }
1739 [ # # # # : 0 : if ((!type || 14 == type) && 0 < num_C_minus)
# # ]
1740 : : {
1741 : 0 : int num_neigh = 0, pos_neigh = -1;
1742 [ # # ]: 0 : for (i1 = 0; i1 < at[i].valence; i1++)
1743 : : {
1744 : 0 : n = at[i].neighbor[i1];
1745 [ # # # # : 0 : if (-1 == at[n].charge && 3 >= at[n].valence && 3 == at[n].chem_bonds_valence + NUMH(at, n) &&
# # ]
1746 : : /*0 == at[n].num_H &&*/
1747 [ # # # # ]: 0 : at[i].bond_type[i1] == BOND_TYPE_DOUBLE &&
1748 : 0 : ion_el_group(at[n].el_number) == EL_NUMBER_C)
1749 : : {
1750 : : /* found O(+)(III)=C(-)(III); prepare conversion to O(IV)#C(IV) */
1751 : 0 : num_neigh++;
1752 : 0 : pos_neigh = i1;
1753 : : }
1754 : : }
1755 [ # # # # ]: 0 : if (1 == num_neigh &&
1756 [ # # ]: 0 : !has_other_ion_neigh(at, i, n = at[i].neighbor[i1 = pos_neigh]) &&
1757 : 0 : !has_other_ion_neigh(at, n, i))
1758 : : {
1759 : : /*n = at[i].neighbor[i1=pos_neigh];*/
1760 : 0 : i2 = (int)(is_in_the_list(at[n].neighbor, (AT_NUMB)i, at[n].valence) - at[n].neighbor);
1761 : 0 : at[i].charge--;
1762 : 0 : at[n].charge++;
1763 : 0 : at[i].chem_bonds_valence++;
1764 : 0 : at[n].chem_bonds_valence++;
1765 : 0 : at[i].bond_type[i1]++;
1766 : 0 : at[n].bond_type[i2]++;
1767 : 0 : num_changes++;
1768 : 0 : num_C_minus--;
1769 : 0 : num_O_plus--;
1770 : 0 : num_All -= 2;
1771 : 0 : continue;
1772 : : }
1773 : : }
1774 [ # # # # : 0 : if ((!type || 15 == type) && 0 < num_N_minus)
# # ]
1775 : : {
1776 : 0 : int num_neigh = 0, pos_neigh = -1;
1777 [ # # ]: 0 : for (i1 = 0; i1 < at[i].valence; i1++)
1778 : : {
1779 : 0 : n = at[i].neighbor[i1];
1780 [ # # # # ]: 0 : if (-1 == at[n].charge && 2 >= nNoMetalNumBonds(at, n) &&
1781 [ # # ]: 0 : 2 == nNoMetalBondsValence(at, n) + NUMH(at, n) &&
1782 : : /*0 == num_of_H( at, n ) &&*/
1783 [ # # # # ]: 0 : at[i].bond_type[i1] == BOND_TYPE_SINGLE &&
1784 : 0 : ion_el_group(at[n].el_number) == EL_NUMBER_N)
1785 : : {
1786 : : /* found O(+)(III)=N(-)(II); prepare conversion to O(IV)#N(III) */
1787 : 0 : num_neigh++;
1788 : 0 : pos_neigh = i1;
1789 : : }
1790 : : }
1791 [ # # # # ]: 0 : if (1 == num_neigh &&
1792 [ # # ]: 0 : !has_other_ion_neigh(at, i, n = at[i].neighbor[i1 = pos_neigh]) &&
1793 : 0 : !has_other_ion_neigh(at, n, i))
1794 : : {
1795 : : /*n = at[i].neighbor[i1=pos_neigh];*/
1796 : 0 : i2 = (int)(is_in_the_list(at[n].neighbor, (AT_NUMB)i, at[n].valence) - at[n].neighbor);
1797 : 0 : at[i].charge--;
1798 : 0 : at[n].charge++;
1799 : 0 : at[i].chem_bonds_valence++;
1800 : 0 : at[n].chem_bonds_valence++;
1801 : 0 : at[i].bond_type[i1]++;
1802 : 0 : at[n].bond_type[i2]++;
1803 : 0 : num_changes++;
1804 : 0 : num_N_minus--;
1805 : 0 : num_O_plus--;
1806 : 0 : num_All -= 2;
1807 : 0 : continue;
1808 : : }
1809 : : }
1810 : : }
1811 : : }
1812 : : }
1813 : :
1814 : : /**************************************************************************/
1815 : : /*********************** NON-Terminal ion triples *************************/
1816 : : /**************************************************************************/
1817 : : /*-------------------------------------------------------------------------
1818 : : Non-Terminal triple types: 16, 17, 18 N=N,P,As,Sb; O=O,S,Se,Te; C=C,Si
1819 : : ========================================
1820 : : 16: C(+)(III)-O-N(-)(II) => C(IV)=O=N(III) (allow terminal H on N(-))
1821 : : | |
1822 : : 17: C(+)(III)-N-C(-)(III) => C(IV)=N=C(IV)
1823 : :
1824 : : 18: C(-)(III)-N=C(+)(III) => C(IV)=N#C(IV) (may have two or no charges)
1825 : : C(IV)=N-C(II) => C(IV)=N#C(IV)
1826 : :
1827 : : */
1828 : :
1829 [ + - + + : 36 : if ((!type || 16 == type) && 0 < num_C_plus && 0 < num_N_minus)
- + - - ]
1830 : : {
1831 : : int m[2], j[2], k;
1832 [ # # ]: 0 : for (i = 0; i < num_atoms; i++)
1833 : : {
1834 [ # # # # : 0 : if (0 == at[i].charge && 2 == nNoMetalNumBonds(at, i) && 2 == nNoMetalBondsValence(at, i) &&
# # # # ]
1835 : 0 : 0 == num_of_H(at, i) &&
1836 [ # # ]: 0 : 0 <= (j[0] = nNoMetalNeighIndex(at, i)) &&
1837 [ # # ]: 0 : at[m[0] = at[i].neighbor[j[0]]].charge &&
1838 [ # # ]: 0 : 0 <= (j[1] = nNoMetalOtherNeighIndex(at, i, m[0])) &&
1839 [ # # ]: 0 : 0 == at[m[0]].charge + at[m[1] = at[i].neighbor[j[1]]].charge &&
1840 [ # # # # ]: 0 : 5 >= nNoMetalBondsValence(at, m[0]) + nNoMetalBondsValence(at, m[1]) &&
1841 : : /*5 >= at[m[0]].chem_bonds_valence + at[m[1]].chem_bonds_valence &&*/
1842 : 0 : ion_el_group(at[i].el_number) == EL_NUMBER_O)
1843 : : {
1844 : : /* found non-terminal A(+)-O-B(-); chem_bond_val of A+B <= 5 */
1845 : 0 : int n_N = -1, n_C = -1, i_C = -1;
1846 [ # # ]: 0 : for (k = 0; k < 2; k++)
1847 : : {
1848 : 0 : n = m[k];
1849 [ # # # # : 0 : if (-1 == at[n].charge && 2 == nNoMetalNumBonds(at, n) + NUMH(at, n) &&
# # ]
1850 : : /*0 == num_of_H( at, n ) &&*/
1851 : 0 : ion_el_group(at[n].el_number) == EL_NUMBER_N)
1852 : : {
1853 : 0 : n_N = n;
1854 : : }
1855 [ # # # # : 0 : else if (1 == at[n].charge && 3 == at[n].chem_bonds_valence + NUMH(at, n) &&
# # ]
1856 : 0 : ion_el_group(at[n].el_number) == EL_NUMBER_C)
1857 : : {
1858 : 0 : n_C = n;
1859 : 0 : i_C = k;
1860 : : }
1861 : : }
1862 [ # # # # : 0 : if (n_C < 0 || n_N < 0 ||
# # ]
1863 [ # # ]: 0 : has_other_ion_in_sphere_2(at, n_C, n_N) ||
1864 : 0 : has_other_ion_in_sphere_2(at, n_N, n_C))
1865 : : {
1866 : 0 : continue;
1867 : : }
1868 : :
1869 : : /* C(+)(III)-O-N(-)(II) => C(IV)=O=N(III) */
1870 [ # # ]: 0 : for (k = 0; k < 2; k++)
1871 : : {
1872 [ # # ]: 0 : n = k ? n_C : n_N;
1873 [ # # ]: 0 : i1 = k ? j[i_C] : j[1 - i_C];
1874 : 0 : i2 = (int)(is_in_the_list(at[n].neighbor, (AT_NUMB)i, at[n].valence) - at[n].neighbor);
1875 : 0 : at[i].bond_type[i1]++;
1876 : 0 : at[n].bond_type[i2]++;
1877 : 0 : at[i].chem_bonds_valence++;
1878 : 0 : at[n].chem_bonds_valence++;
1879 [ # # ]: 0 : at[n].charge += (k ? -1 : 1);
1880 : : }
1881 : 0 : num_changes++;
1882 : 0 : num_N_minus--;
1883 : 0 : num_C_plus--;
1884 : 0 : num_All -= 2;
1885 : : }
1886 : : }
1887 : : }
1888 : :
1889 [ + - + + : 36 : if ((!type || 17 == type) && 0 < num_C_plus && 0 < num_C_minus)
- + - - ]
1890 : : {
1891 : : int m[3], c[3], j[3], k;
1892 [ # # ]: 0 : for (i = 0; i < num_atoms; i++)
1893 : : {
1894 [ # # # # : 0 : if (0 == at[i].charge && 3 == nNoMetalNumBonds(at, i) && 3 == nNoMetalBondsValence(at, i) &&
# # # # ]
1895 : 0 : 0 == num_of_H(at, i) &&
1896 [ # # ]: 0 : 0 <= (j[0] = nNoMetalNeighIndex(at, i)) &&
1897 [ # # ]: 0 : 0 <= (j[1] = nNoMetalOtherNeighIndex(at, i, m[0] = at[i].neighbor[j[0]])) &&
1898 [ # # ]: 0 : 0 <= (j[2] = nNoMetalOtherNeighIndex2(at, i, m[0], m[1] = at[i].neighbor[j[1]])) &&
1899 [ # # ]: 0 : 1 == !(c[0] = at[m[0]].charge) + !(c[1] = at[m[1]].charge) + !(c[2] = at[m[2] = at[i].neighbor[j[2]]].charge) &&
1900 [ # # ]: 0 : 0 == c[0] + c[1] + c[2] &&
1901 [ # # # # : 0 : 2 == (3 == (c[0] ? at[m[0]].chem_bonds_valence + NUMH(at, m[0]) : 0)) + (3 == (c[1] ? at[m[1]].chem_bonds_valence + NUMH(at, m[1]) : 0)) + (3 == (c[2] ? at[m[2]].chem_bonds_valence + NUMH(at, m[2]) : 0)) &&
# # # # #
# # # # #
# # ]
1902 : 0 : ion_el_group(at[i].el_number) == EL_NUMBER_N)
1903 : : {
1904 : : /* found non-terminal A(+)-O-B(-) */
1905 : 0 : int n_Cp = -1, n_Cm = -1, i_Cp = -1, i_Cm = -1; /* p = positive, m = negatice ion C */
1906 [ # # ]: 0 : for (k = 0; k < 3; k++)
1907 : : {
1908 [ # # ]: 0 : if (c[k])
1909 : : {
1910 : 0 : n = m[k];
1911 [ # # # # ]: 0 : if (-1 == at[n].charge &&
1912 : 0 : ion_el_group(at[n].el_number) == EL_NUMBER_C)
1913 : : {
1914 : 0 : n_Cm = n;
1915 : 0 : i_Cm = k;
1916 : : }
1917 [ # # # # ]: 0 : else if (1 == at[n].charge &&
1918 : 0 : ion_el_group(at[n].el_number) == EL_NUMBER_C)
1919 : : {
1920 : 0 : n_Cp = n;
1921 : 0 : i_Cp = k;
1922 : : }
1923 : : }
1924 : : }
1925 [ # # # # : 0 : if (n_Cp < 0 || n_Cm < 0 ||
# # ]
1926 [ # # ]: 0 : has_other_ion_in_sphere_2(at, n_Cp, n_Cm) ||
1927 : 0 : has_other_ion_in_sphere_2(at, n_Cm, n_Cp))
1928 : : {
1929 : 0 : continue;
1930 : : }
1931 : :
1932 : : /* | | */
1933 : : /* C(+)(III)-N-C(-)(III) => C(IV)=N=C(IV) */
1934 [ # # ]: 0 : for (k = 0; k < 2; k++)
1935 : : {
1936 [ # # ]: 0 : n = k ? n_Cp : n_Cm;
1937 [ # # ]: 0 : i1 = k ? j[i_Cp] : j[i_Cm];
1938 : 0 : i2 = (int)(is_in_the_list(at[n].neighbor, (AT_NUMB)i, at[n].valence) - at[n].neighbor);
1939 : 0 : at[i].bond_type[i1]++;
1940 : 0 : at[n].bond_type[i2]++;
1941 : 0 : at[i].chem_bonds_valence++;
1942 : 0 : at[n].chem_bonds_valence++;
1943 [ # # ]: 0 : at[n].charge += (k ? -1 : 1);
1944 : : }
1945 : 0 : num_changes++;
1946 : 0 : num_C_minus--;
1947 : 0 : num_C_plus--;
1948 : 0 : num_All -= 2;
1949 : : }
1950 : : }
1951 : : }
1952 : :
1953 [ + - + + : 36 : if ((!type || 18 == type) && ((0 < num_C_plus && 0 < num_C_minus) || 0 < num_C_II)) /* djb-rwth: addressing LLVM warning */
- + - - -
+ ]
1954 : : {
1955 : : int m[2], v[2], j[2], k;
1956 [ # # ]: 0 : for (i = 0; i < num_atoms; i++)
1957 : : {
1958 [ # # # # : 0 : if (0 == at[i].charge && 2 == nNoMetalNumBonds(at, i) && 3 == nNoMetalBondsValence(at, i) &&
# # # # ]
1959 : 0 : 0 == num_of_H(at, i) &&
1960 [ # # ]: 0 : 0 <= (j[0] = nNoMetalNeighIndex(at, i)) &&
1961 [ # # ]: 0 : 0 <= (j[1] = nNoMetalOtherNeighIndex(at, i, m[0] = at[i].neighbor[j[0]])) &&
1962 [ # # ]: 0 : 0 == at[m[0]].charge + at[m[1] = at[i].neighbor[j[1]]].charge &&
1963 [ # # ]: 0 : 6 == (v[0] = at[m[0]].chem_bonds_valence + NUMH(at, m[0])) + (v[1] = at[m[1]].chem_bonds_valence + NUMH(at, m[1])) &&
1964 [ # # # # : 0 : 2 >= abs(v[0] - v[1]) &&
# # ]
1965 [ # # ]: 0 : ion_el_group(at[i].el_number) == EL_NUMBER_N &&
1966 [ # # ]: 0 : ion_el_group(at[m[0]].el_number) == EL_NUMBER_C &&
1967 : 0 : ion_el_group(at[m[1]].el_number) == EL_NUMBER_C)
1968 : : {
1969 : : /* n_Cm i n_Cp */
1970 : : /* found non-terminal C(-)(III)-N=C(+)(III) or C(IV)=N-C(II): Cm-N-Cp */
1971 : : /* convert to C(IV)=N#C(IV) */
1972 : 0 : int n_Cp = -1, n_Cm = -1, i_Cp = -1, i_Cm = -1; /* p = positive, m = negatice ion C */
1973 [ # # ]: 0 : for (k = 0; k < 2; k++)
1974 : : {
1975 : 0 : n = m[k];
1976 [ # # # # : 0 : if (v[k] == 4 || (v[k] == 3 && at[i].bond_type[j[k]] == BOND_TYPE_SINGLE)) /* djb-rwth: addressing LLVM warning */
# # ]
1977 : : {
1978 : 0 : n_Cm = n;
1979 : 0 : i_Cm = k;
1980 : : }
1981 [ # # # # : 0 : else if (v[k] == 2 || (v[k] == 3 && at[i].bond_type[j[k]] == BOND_TYPE_DOUBLE)) /* djb-rwth: addressing LLVM warning */
# # ]
1982 : : {
1983 : 0 : n_Cp = n;
1984 : 0 : i_Cp = k;
1985 : : }
1986 : : }
1987 [ # # # # : 0 : if (n_Cp < 0 || n_Cm < 0 || at[n_Cp].valence + NUMH(at, n_Cp) != 2)
# # ]
1988 : : {
1989 : 0 : continue; /* guarantees at[n_Cp].valence <= 2 */
1990 : : }
1991 [ # # # # ]: 0 : if (v[i_Cp] == 2 || !at[n_Cp].charge)
1992 : : {
1993 [ # # ]: 0 : if (at[n_Cp].valence == 2)
1994 : : {
1995 : : /* neighbor of at[n_Cp] opposite to at[i] */
1996 : 0 : k = at[n_Cp].neighbor[at[n_Cp].neighbor[0] == i];
1997 [ # # ]: 0 : if (ion_el_group(at[k].el_number) == EL_NUMBER_N)
1998 : : {
1999 : 0 : continue;
2000 : : }
2001 : : }
2002 : : }
2003 [ # # ]: 0 : else if (at[n_Cp].charge)
2004 : : {
2005 [ # # # # ]: 0 : if (has_other_ion_in_sphere_2(at, n_Cp, n_Cm) ||
2006 : 0 : has_other_ion_in_sphere_2(at, n_Cm, n_Cp))
2007 : : {
2008 : 0 : continue;
2009 : : }
2010 : : }
2011 : : else
2012 : : {
2013 : 0 : continue; /* unknown case */
2014 : : }
2015 : :
2016 : : /* */
2017 : : /* C(-)(III)-N=C(+)(III) => C(IV)=N#C(IV) */
2018 : : /* C(IV)=N-C(II) => C(IV)=N#C(IV) */
2019 [ # # ]: 0 : if (at[n_Cp].charge)
2020 : : {
2021 : 0 : num_C_minus--;
2022 : 0 : num_C_plus--;
2023 : 0 : num_All -= 2;
2024 : : }
2025 : : else
2026 : : {
2027 : 0 : num_C_II--;
2028 : 0 : num_All--;
2029 : : }
2030 : :
2031 [ # # ]: 0 : for (k = 0; k < 2; k++)
2032 : : {
2033 [ # # ]: 0 : n = k ? n_Cp : n_Cm;
2034 [ # # ]: 0 : i3 = k ? i_Cp : i_Cm; /* added to fix the bug */
2035 : : /*i1 = k? j[i_Cp] : j[i_Cm];*/ /* replaced with next line */
2036 : 0 : i1 = j[i3];
2037 [ # # ]: 0 : if (v[i3 /*was i1*/] < 4)
2038 : : {
2039 : : /* WDI found a bug here: bounds violation */
2040 : 0 : int delta = 4 - v[i3 /*was i1*/];
2041 : 0 : i2 = (int)(is_in_the_list(at[n].neighbor, (AT_NUMB)i, at[n].valence) - at[n].neighbor);
2042 : 0 : at[i].bond_type[i1] += delta;
2043 : 0 : at[n].bond_type[i2] += delta;
2044 : 0 : at[i].chem_bonds_valence += delta;
2045 : 0 : at[n].chem_bonds_valence += delta;
2046 : 0 : at[n].charge = 0;
2047 : 0 : at[n].radical = 0;
2048 : : }
2049 : : }
2050 : 0 : at[i].charge = 0;
2051 : 0 : at[i].radical = 0;
2052 : 0 : num_changes++;
2053 : : }
2054 : : }
2055 : : }
2056 : : }
2057 : :
2058 : 2 : return num_changes;
2059 : : }
2060 : :
2061 : : /*#if ( DISCONNECT_SALTS == 1 )*/ /* { */
2062 : :
2063 : : /****************************************************************************/
2064 : 26 : int RemoveInpAtBond(inp_ATOM *atom, int iat, int k)
2065 : : {
2066 : : int i, j, m, m2; /* djb-rwth: removing redundant variables */
2067 : 26 : inp_ATOM *at = atom + iat;
2068 : 26 : inp_ATOM *at2 = NULL;
2069 : 26 : int val = at->valence - 1;
2070 : :
2071 [ + - ]: 26 : if (val >= 0)
2072 : : {
2073 : 26 : int bond = at->bond_type[k];
2074 [ + + ]: 26 : if (bond > BOND_TYPE_TRIPLE)
2075 : 20 : bond = BOND_TYPE_SINGLE; /* added 08-06-2003 */
2076 : :
2077 : : /* update CML tetrahedral atom parity. */
2078 [ - + ]: 26 : if (at->p_parity)
2079 : : {
2080 [ # # ]: 0 : for (m = 0; m < MAX_NUM_STEREO_ATOM_NEIGH; m++)
2081 : : {
2082 [ # # ]: 0 : if (at->p_orig_at_num[m] == at->orig_at_number)
2083 : : {
2084 : 0 : at->p_parity = 0;
2085 : 0 : break; /* only 3 bonds are present; removing one bond removes stereo */
2086 : : }
2087 : : }
2088 [ # # ]: 0 : if (at->p_parity /* at->valence == MAX_NUM_STEREO_ATOM_NEIGH*/)
2089 : : {
2090 : : /* p_orig_at_num is a fixed size array of MAX_NUM_STEREO_ATOM_NEIGH (4) elements */
2091 [ # # # # ]: 0 : for (m = 0; m < at->valence && m < MAX_NUM_STEREO_ATOM_NEIGH; m++) /* djb-rwth: fixing GH PR #72 */
2092 : : {
2093 [ # # ]: 0 : if (atom[(int)at->neighbor[k]].orig_at_number == at->p_orig_at_num[m])
2094 : : {
2095 : 0 : break;
2096 : : }
2097 : : }
2098 [ # # # # ]: 0 : if (m < at->valence && m < MAX_NUM_STEREO_ATOM_NEIGH) /* djb-rwth: fixing GH PR #72 */
2099 : : {
2100 : 0 : at->p_orig_at_num[m] = at->orig_at_number;
2101 : : }
2102 : : else
2103 : : {
2104 : 0 : at->p_parity = 0; /* wrong neighbors: at->neighbor[k] is not in the list of a stereo neighbors */
2105 : : }
2106 : : }
2107 : : }
2108 : :
2109 : : /* update CML stereogenic bond parities; at this point no removed explicit H exist yet */
2110 [ - + ]: 26 : if (at->sb_parity[0])
2111 : : {
2112 [ # # # # ]: 0 : for (m = 0; m < MAX_NUM_STEREO_BONDS && at->sb_parity[m];)
2113 : : {
2114 [ # # # # : 0 : if (k == at->sb_ord[m] || (k == at->sn_ord[m] && val < 2 && ATOM_PARITY_WELL_DEF(at->sb_parity[m]))) /* djb-rwth: addressing LLVM warning */
# # # # #
# ]
2115 : 0 : {
2116 : : /* !!! FLAW: does take into account removed H !!! */
2117 : : /* stereogenic bond is being removed OR */
2118 : : /* remove stereogenic bond because its only neighbor is being removed */
2119 : : int pnxt_atom, pinxt2cur, pinxt_sb_parity_ord;
2120 : 0 : int len = get_opposite_sb_atom(atom, iat, at->sb_ord[m], &pnxt_atom, &pinxt2cur, &pinxt_sb_parity_ord);
2121 [ # # ]: 0 : if (len)
2122 : : {
2123 : 0 : i = pinxt_sb_parity_ord;
2124 : 0 : at2 = atom + pnxt_atom;
2125 : : /* djb-rwth: removing redundant code */
2126 : : }
2127 : : else
2128 : : {
2129 : 0 : i = MAX_NUM_STEREO_BONDS;
2130 : : }
2131 : : /*
2132 : : at2 = atom + at->neighbor[ (int)at->sb_ord[m] ];
2133 : : for ( i = 0; i < MAX_NUM_STEREO_BONDS && at2->sb_parity[i]; i ++ )
2134 : : {
2135 : : if ( iat == at2->neighbor[ (int)at2->sb_ord[i] ] )
2136 : : break;
2137 : : }
2138 : : */
2139 [ # # # # ]: 0 : if (i < MAX_NUM_STEREO_BONDS && at2->sb_parity[i])
2140 : : {
2141 : 0 : m2 = i;
2142 : : /* remove bond parity from at */
2143 [ # # ]: 0 : if (m < MAX_NUM_STEREO_BONDS - 1)
2144 : : {
2145 : 0 : memmove(at->sb_parity + m, at->sb_parity + m + 1, (MAX_NUM_STEREO_BONDS - 1 - (long long)m) * sizeof(at->sb_parity[0])); /* djb-rwth: cast operator added */
2146 : 0 : memmove(at->sb_ord + m, at->sb_ord + m + 1, (MAX_NUM_STEREO_BONDS - 1 - (long long)m) * sizeof(at->sb_ord[0])); /* djb-rwth: cast operator added */
2147 : 0 : memmove(at->sn_ord + m, at->sn_ord + m + 1, (MAX_NUM_STEREO_BONDS - 1 - (long long)m) * sizeof(at->sn_ord[0])); /* djb-rwth: cast operator added */
2148 : 0 : memmove(at->sn_orig_at_num + m, at->sn_orig_at_num + m + 1, (MAX_NUM_STEREO_BONDS - 1 - (long long)m) * sizeof(at->sn_orig_at_num[0])); /* djb-rwth: cast operator added */
2149 : : }
2150 : 0 : at->sb_parity[MAX_NUM_STEREO_BONDS - 1] = 0;
2151 : 0 : at->sb_ord[MAX_NUM_STEREO_BONDS - 1] = 0;
2152 : 0 : at->sn_ord[MAX_NUM_STEREO_BONDS - 1] = 0;
2153 : 0 : at->sn_orig_at_num[MAX_NUM_STEREO_BONDS - 1] = 0;
2154 : : /* remove bond parity from at2 */
2155 [ # # ]: 0 : if (m2 < MAX_NUM_STEREO_BONDS - 1)
2156 : : {
2157 : 0 : memmove(at2->sb_parity + m2, at2->sb_parity + m2 + 1, (MAX_NUM_STEREO_BONDS - 1 - (long long)m2) * sizeof(at2->sb_parity[0])); /* djb-rwth: cast operator added */
2158 : 0 : memmove(at2->sb_ord + m2, at2->sb_ord + m2 + 1, (MAX_NUM_STEREO_BONDS - 1 - (long long)m2) * sizeof(at2->sb_ord[0])); /* djb-rwth: cast operator added */
2159 : 0 : memmove(at2->sn_ord + m2, at2->sn_ord + m2 + 1, (MAX_NUM_STEREO_BONDS - 1 - (long long)m2) * sizeof(at2->sn_ord[0])); /* djb-rwth: cast operator added */
2160 : 0 : memmove(at2->sn_orig_at_num + m2, at2->sn_orig_at_num + m2 + 1, (MAX_NUM_STEREO_BONDS - 1 - (long long)m2) * sizeof(at2->sn_orig_at_num[0])); /* djb-rwth: cast operator added */
2161 : : }
2162 : 0 : at2->sb_parity[MAX_NUM_STEREO_BONDS - 1] = 0;
2163 : 0 : at2->sb_ord[MAX_NUM_STEREO_BONDS - 1] = 0;
2164 : 0 : at2->sn_ord[MAX_NUM_STEREO_BONDS - 1] = 0;
2165 : 0 : at2->sn_orig_at_num[MAX_NUM_STEREO_BONDS - 1] = 0;
2166 : : /* do not increment m here because the array elements have been shifted */
2167 : : }
2168 : : else
2169 : : {
2170 : 0 : m++; /* program error: inconsistent stereobond parity */
2171 : : }
2172 : : }
2173 [ # # ]: 0 : else if (k == at->sn_ord[m])
2174 : : {
2175 : : /* stereogenic bond neighbor is being removed; another neighbor remains */
2176 : : /* !!! FLAW: does take into account removed H !!! */
2177 [ # # ]: 0 : for (j = 0, i = -1; j < at->valence; j++)
2178 : : {
2179 [ # # # # ]: 0 : if (j != k && j != at->sb_ord[m])
2180 : : {
2181 : 0 : i = j;
2182 : 0 : break;
2183 : : }
2184 : : }
2185 : :
2186 : : /* i is the position of the neighbor that will become a new neighbor */
2187 : : /***************************************************************************
2188 : : * at->sb_parity[m] is the direction (EVEN=clockwise, ODD=counterclockwise)
2189 : : * from stereobond to the neighbor. If the neighbor is removed then
2190 : : * the parity should invert, otherwise it should be unchanged.
2191 : : ***************************************************************************/
2192 [ # # ]: 0 : if (i < 0)
2193 : : {
2194 : : /* no alternative neighbor is available */
2195 [ # # # # ]: 0 : if (ATOM_PARITY_WELL_DEF(at->sb_parity[m]))
2196 : : {
2197 : : /* parity cannot be not well-defined anymore */
2198 : : int pnxt_atom, pinxt2cur, pinxt_sb_parity_ord;
2199 : 0 : int len = get_opposite_sb_atom(atom, iat, at->sb_ord[m], &pnxt_atom, &pinxt2cur, &pinxt_sb_parity_ord);
2200 [ # # ]: 0 : if (len > 0)
2201 : : {
2202 : 0 : atom[pnxt_atom].sb_parity[pinxt_sb_parity_ord] = at->sb_parity[m] = AB_PARITY_UNDF;
2203 : : }
2204 : : }
2205 : 0 : at->sn_ord[m] = -99; /* sb neighbor has been disconnected */
2206 : 0 : at->sb_ord[m] -= (at->sb_ord[m] > k); /* same as above */
2207 : 0 : at->sn_orig_at_num[m] = 0;
2208 : : }
2209 [ # # ]: 0 : else if (i < at->valence)
2210 : : {
2211 : : /* choose another stereogenic bond neighbor, its ord. number is i before bond removal */
2212 [ # # # # ]: 0 : if (ATOM_PARITY_WELL_DEF(at->sb_parity[m]))
2213 : : {
2214 : : /* ALL WRONG: 'move' previous stereo bond neighbor to the last position (pos. 2 out of 0,1,2) */
2215 : : /* the parity of the transpositions is (2 - at->sn_ord[m])%2 = at->sn_ord[m] % 2 */
2216 : : /* and replace the neighbor with another; the contribution to the parity is 1 */
2217 : :
2218 : : /*at->sb_parity[m] = 2 - ( at->sb_parity[m] + at->sn_ord[m] + 1 ) % 2;*/
2219 : :
2220 : : /*at->sb_parity[m] = 2 - ( at->sb_parity[m] + k + i +
2221 : : (i > k) + (i > at->sb_ord[m]) ) % 2;*/
2222 : : /*=== parity should be INVERTED ===*/
2223 : 0 : at->sb_parity[m] = 3 - at->sb_parity[m];
2224 : : }
2225 : 0 : at->sn_ord[m] = i - (i > k); /* ord. number shifted because preceding bond is removed */
2226 : 0 : at->sb_ord[m] -= (at->sb_ord[m] > k); /* same as above */
2227 : 0 : at->sn_orig_at_num[m] = atom[(int)at->neighbor[i]].orig_at_number;
2228 : : /*at->sb_parity[m] = 2 - ( at->sb_parity[m] + 1 ) % 2;*/
2229 : : }
2230 : : else
2231 : : {
2232 : 0 : at->sb_parity[m] = 0; /* program error: inconsistent stereobond parity */
2233 : : }
2234 : 0 : m++;
2235 : : }
2236 : : else
2237 : : {
2238 : : /* removing another neighbor, k: first move it to the last position (pos. 2 out of 0,1,2) */
2239 [ # # # # ]: 0 : if (k < 2 && ATOM_PARITY_WELL_DEF(at->sb_parity[m]))
2240 : : {
2241 : : /*at->sb_parity[m] = 2 - ( at->sb_parity[m] + k ) % 2;*/
2242 : : /*at->sb_parity[m] = 2 - ( at->sb_parity[m] + (at->sn_ord[m] > k) + (at->sb_ord[m] > k) ) % 2;*/
2243 : : ; /*==== Parity should remain UNCHANGED ===*/
2244 : : }
2245 [ # # ]: 0 : if (at->sb_ord[m] > k)
2246 : : {
2247 : 0 : at->sb_ord[m]--;
2248 : : }
2249 [ # # ]: 0 : if (at->sn_ord[m] > k)
2250 : : {
2251 : 0 : at->sn_ord[m]--;
2252 : : }
2253 : 0 : m++;
2254 : : }
2255 : : }
2256 : : }
2257 : :
2258 [ - + ]: 26 : if (k < val)
2259 : : {
2260 : 0 : memmove(at->neighbor + k, at->neighbor + k + 1, sizeof(at->neighbor[0]) * ((long long)val - (long long)k)); /* djb-rwth: cast operators added */
2261 : 0 : memmove(at->bond_stereo + k, at->bond_stereo + k + 1, sizeof(at->bond_stereo[0]) * ((long long)val - (long long)k)); /* djb-rwth: cast operators added */
2262 : 0 : memmove(at->bond_type + k, at->bond_type + k + 1, sizeof(at->bond_type[0]) * ((long long)val - (long long)k)); /* djb-rwth: cast operators added */
2263 : : }
2264 : :
2265 : 26 : at->neighbor[val] = 0;
2266 : 26 : at->bond_stereo[val] = 0;
2267 : 26 : at->bond_type[val] = 0;
2268 : 26 : at->valence = val;
2269 : 26 : at->chem_bonds_valence -= bond;
2270 : 26 : return 1;
2271 : : }
2272 : :
2273 : 0 : return 0;
2274 : : }
2275 : :
2276 : : /****************************************************************************/
2277 : 13 : int DisconnectInpAtBond(inp_ATOM *at,
2278 : : AT_NUMB *nOldCompNumber,
2279 : : int iat,
2280 : : int neigh_ord)
2281 : : {
2282 : 13 : int neigh, i, ret = 0;
2283 : : int component;
2284 : 13 : neigh = at[iat].neighbor[neigh_ord];
2285 : :
2286 [ + - ]: 58 : for (i = 0; i < at[neigh].valence; i++)
2287 : : {
2288 [ + + ]: 58 : if (iat == (int)at[neigh].neighbor[i])
2289 : : {
2290 : 13 : break;
2291 : : }
2292 : : }
2293 : :
2294 [ + - ]: 13 : if (i < at[neigh].valence)
2295 : : {
2296 : 13 : ret += RemoveInpAtBond(at, iat, neigh_ord);
2297 : 13 : ret += RemoveInpAtBond(at, neigh, i);
2298 [ + + + - ]: 13 : if (nOldCompNumber && ret)
2299 : : {
2300 [ + - ]: 10 : if ((component = at[iat].component)) /* djb-rwth: addressing LLVM warning */
2301 : : {
2302 : 10 : nOldCompNumber[component - 1] = 0;
2303 : : }
2304 [ + - ]: 10 : if ((component = at[neigh].component)) /* djb-rwth: addressing LLVM warning */
2305 : : {
2306 : 10 : nOldCompNumber[component - 1] = 0;
2307 : : }
2308 : : }
2309 : : }
2310 : :
2311 : 13 : return (ret == 2);
2312 : : }
2313 : :
2314 : : /****************************************************************************/
2315 : 1193 : int bIsAmmoniumSalt(inp_ATOM *at,
2316 : : int i,
2317 : : int *piO,
2318 : : int *pk,
2319 : : S_CHAR *num_explicit_H)
2320 : : {
2321 : : /* NH4(+charge)-O(-charge)-C -> NH3 + HO-C; any charge including 0, */
2322 : : /* any C except charged or radical F, Cl, Br, I */
2323 : :
2324 : 1193 : int num_H, num_non_iso_H, num_impl_iso_H, bDisconnect = 1;
2325 : 1193 : int j, val, neigh, iO = -1, iC, k = -1;
2326 : :
2327 [ + + ]: 1193 : if (at[i].el_number != EL_NUMBER_N)
2328 : : {
2329 : 1159 : return 0;
2330 : : }
2331 : :
2332 : : /* check for NH4-O-C... -> NH3 + HO-C... */
2333 : 34 : val = at[i].valence;
2334 : 34 : num_impl_iso_H = NUM_ISO_H(at, i);
2335 : 34 : num_non_iso_H = at[i].num_H;
2336 : 34 : num_H = num_non_iso_H + num_impl_iso_H;
2337 [ - + ]: 34 : if (val + num_H == 5)
2338 : : {
2339 : 0 : int num_O = 0;
2340 : 0 : memset(num_explicit_H, 0, (NUM_H_ISOTOPES + 1) * sizeof(num_explicit_H[0])); /* djb-rwth: memset_s C11/Annex K variant? */
2341 [ # # ]: 0 : for (j = 0; j < val; j++)
2342 : : { /* looking for O: H4N-O-C... */
2343 : 0 : neigh = at[i].neighbor[j];
2344 [ # # ]: 0 : if (at[neigh].num_H ||
2345 [ # # # # : 0 : (at[neigh].charge && (at[neigh].el_number != EL_NUMBER_O || at[neigh].charge + at[i].charge)) ||
# # ]
2346 [ # # # # ]: 0 : (at[neigh].radical && at[neigh].radical != RADICAL_SINGLET)) /* djb-rwth: addressing LLVM warnings */
2347 : : {
2348 : 0 : bDisconnect = 0;
2349 : 0 : break; /* reject */
2350 : : }
2351 [ # # # # ]: 0 : if (at[neigh].el_number == EL_NUMBER_H && at[neigh].valence == 1 &&
2352 [ # # # # ]: 0 : !at[neigh].charge && !at[neigh].radical)
2353 : : {
2354 : 0 : num_H++; /* at this point at[].num_H does not include explicit H count */
2355 : 0 : num_non_iso_H += (0 == at[neigh].iso_atw_diff);
2356 : 0 : num_explicit_H[at[neigh].iso_atw_diff]++; /* explicit H on N */
2357 : : }
2358 [ # # # # : 0 : else if (at[neigh].el_number == EL_NUMBER_O && at[neigh].valence == 2 && !num_O)
# # ]
2359 : : {
2360 : 0 : num_O++; /* found O: N-O- */
2361 : 0 : iO = neigh;
2362 : 0 : k = j;
2363 : 0 : iC = at[iO].neighbor[at[iO].neighbor[0] == i];
2364 [ # # ]: 0 : if (at[iC].el_number != EL_NUMBER_C || /*
2365 : : at[iC].num_H ||
2366 : : at[iC].chem_bonds_valence != 4 || */
2367 [ # # ]: 0 : at[iC].charge ||
2368 [ # # # # ]: 0 : (at[iC].radical && at[iC].radical != RADICAL_SINGLET) /*||
2369 : : at[iC].valence == at[iC].chem_bonds_valence*/
2370 : : ) /* djb-rwth: addressing LLVM warning */
2371 : : {
2372 : 0 : bDisconnect = 0;
2373 : 0 : break; /* reject */
2374 : : }
2375 : : }
2376 [ # # ]: 0 : else if ((at[neigh].el_number == EL_NUMBER_F ||
2377 [ # # ]: 0 : at[neigh].el_number == EL_NUMBER_CL ||
2378 [ # # ]: 0 : at[neigh].el_number == EL_NUMBER_BR ||
2379 [ # # ]: 0 : at[neigh].el_number == EL_NUMBER_I) &&
2380 [ # # # # ]: 0 : at[neigh].valence == 1 && at[neigh].chem_bonds_valence == 1 &&
2381 [ # # # # : 0 : !at[neigh].charge && !NUMH(at, neigh) && !num_O)
# # ]
2382 : : {
2383 : 0 : num_O++; /* found O: N-O- */
2384 : 0 : iO = neigh;
2385 : 0 : k = j;
2386 : : /* djb-rwth: removing redundant code */
2387 : : }
2388 : : else
2389 : : {
2390 : 0 : bDisconnect = 0;
2391 : 0 : break; /* reject */
2392 : : }
2393 : : }
2394 [ # # # # : 0 : if (bDisconnect && (num_O != 1 || num_H != 4))
# # ]
2395 : : {
2396 : 0 : bDisconnect = 0; /* reject */
2397 : : }
2398 : : }
2399 : : else
2400 : : {
2401 : 34 : bDisconnect = 0;
2402 : : }
2403 [ - + ]: 34 : if (bDisconnect)
2404 : : {
2405 : 0 : *piO = iO;
2406 : 0 : *pk = k;
2407 : : }
2408 : :
2409 : 34 : return bDisconnect;
2410 : : }
2411 : :
2412 : : /****************************************************************************/
2413 : 0 : int DisconnectAmmoniumSalt(inp_ATOM *at,
2414 : : int iN,
2415 : : int iO,
2416 : : int k,
2417 : : S_CHAR *num_explicit_H)
2418 : : {
2419 : :
2420 : : /* disconnect NH4-O from O */
2421 : : /* Note: iO = at[iN].neighbor[k], at[iN] is N, at[iO].neighbor[0] is either N=at[iN] or C=at[iC] */
2422 : :
2423 : 0 : int nMove_H_iso_diff = -1; /* do not move explicit H */
2424 : : int j, neigh, iso_diff, neigh_pos;
2425 : 0 : int val = at[iN].valence;
2426 : :
2427 [ # # # # ]: 0 : if (at[iN].charge && !(at[iN].charge + at[iO].charge))
2428 : : {
2429 : 0 : at[iN].charge = at[iO].charge = 0; /* remove charges */
2430 : : }
2431 : :
2432 [ # # # # ]: 0 : neigh_pos = (at[iO].valence == 2) ? (at[iO].neighbor[1] == iN) : 0; /* position of at[iN] in the neigh list of iO */
2433 : : /* disconnect bond O-N */
2434 : 0 : RemoveInpAtBond(at, iO, neigh_pos);
2435 : 0 : RemoveInpAtBond(at, iN, k);
2436 : 0 : val--;
2437 : :
2438 : : /* move 1 H from NH4 to O- or Cl */
2439 : :
2440 : : /* find non-isotopic or the lightest isotopic H to move from N to O */
2441 [ # # ]: 0 : for (iso_diff = 0; iso_diff <= NUM_H_ISOTOPES; iso_diff++) /* djb-rwth: fixing GH PR #72 */
2442 : : {
2443 [ # # ]: 0 : if (!iso_diff)
2444 : : {
2445 : : /* find non-isotopic H */
2446 [ # # ]: 0 : if (at[iN].num_H)
2447 : : {
2448 : 0 : at[iN].num_H--; /* move non-isotopic implicit H */
2449 : 0 : at[iO].num_H++;
2450 : 0 : break;
2451 : : }
2452 [ # # ]: 0 : else if (num_explicit_H[0])
2453 : : {
2454 : 0 : nMove_H_iso_diff = 0; /* flag: move explicit non-isotopic H */
2455 : 0 : break;
2456 : : }
2457 : : }
2458 : : else
2459 : : {
2460 : : /* find isotopic H */
2461 : : /* num_iso_H has length NUM_H_ISOTOPES; do not access out-of-bounds */
2462 [ # # # # ]: 0 : if ((iso_diff < NUM_H_ISOTOPES) && at[iN].num_iso_H[iso_diff]) /* djb-rwth: fixing GH PR #72 */
2463 : : {
2464 : 0 : at[iN].num_iso_H[iso_diff]--; /* move implicit isotopic H, atw = 1 */
2465 : 0 : at[iO].num_iso_H[iso_diff]++;
2466 : 0 : break;
2467 : : }
2468 : : else
2469 : : {
2470 [ # # ]: 0 : if (num_explicit_H[iso_diff])
2471 : : {
2472 : 0 : nMove_H_iso_diff = iso_diff; /* flag: move explicit isotopic H, atw = 1 */
2473 : 0 : break;
2474 : : }
2475 : : }
2476 : : }
2477 : : }
2478 : :
2479 [ # # ]: 0 : if (nMove_H_iso_diff >= 0)
2480 : : {
2481 : : /* move explicit H, it is isotopic if nMove_H_iso_diff > 0 */
2482 : 0 : double dist2_H_O, min_dist2_H_O = -1.0;
2483 : 0 : int jH = -1, iH = -1;
2484 [ # # ]: 0 : for (j = 0; j < val; j++)
2485 : : { /* looking H in N-H such that H-O is shortest */
2486 : 0 : neigh = at[iN].neighbor[j];
2487 [ # # ]: 0 : if (at[neigh].el_number == EL_NUMBER_H &&
2488 [ # # ]: 0 : at[neigh].iso_atw_diff == nMove_H_iso_diff)
2489 : : {
2490 : 0 : dist2_H_O = (at[neigh].x - at[iO].x) * (at[neigh].x - at[iO].x) +
2491 : 0 : (at[neigh].y - at[iO].y) * (at[neigh].y - at[iO].y) +
2492 : 0 : (at[neigh].z - at[iO].z) * (at[neigh].z - at[iO].z);
2493 [ # # # # ]: 0 : if (min_dist2_H_O < 0.0 || min_dist2_H_O > dist2_H_O)
2494 : : {
2495 : 0 : min_dist2_H_O = dist2_H_O;
2496 : 0 : iH = neigh;
2497 : 0 : jH = j;
2498 : : }
2499 : : }
2500 : : }
2501 : :
2502 : : /* reconnect; bonds do not need changes except stereo */
2503 : 0 : neigh_pos = at[iO].valence;
2504 : 0 : at[iO].neighbor[neigh_pos] = iH;
2505 : 0 : at[iO].bond_stereo[neigh_pos] = 0;
2506 : 0 : at[iO].bond_type[neigh_pos] = at[iH].bond_type[0];
2507 : 0 : at[iO].chem_bonds_valence += at[iH].bond_type[0];
2508 : 0 : at[iO].valence++;
2509 : 0 : at[iH].neighbor[0] = iO;
2510 : 0 : at[iH].bond_stereo[0] = 0;
2511 : :
2512 : : /* disconnect H from N */
2513 : 0 : RemoveInpAtBond(at, iN, jH);
2514 : 0 : val--;
2515 [ # # ]: 0 : if (k > jH)
2516 : : {
2517 : 0 : k--;
2518 : : }
2519 : : }
2520 : :
2521 : 0 : return 1;
2522 : : }
2523 : :
2524 : : /****************************************************************************/
2525 : 1165 : int bIsMetalSalt(inp_ATOM *at, int i)
2526 : : {
2527 : : int type, val, k, iO, iC, j, neigh;
2528 : 1165 : int bDisconnect = 1;
2529 : :
2530 : : /* check for a metal atom:
2531 : : metal atom should be connected and be a metal */
2532 [ + - + + ]: 2330 : if (!(val = at[i].valence) ||
2533 : 1165 : !(type = get_el_type(at[i].el_number)) ||
2534 [ - + ]: 7 : !(type & IS_METAL))
2535 : : {
2536 : 1158 : bDisconnect = 0; /* reject */
2537 : : }
2538 [ - + ]: 7 : else if (at[i].num_H)
2539 : : /* metal atom should not have adjacent H or multiple bonds or radical */
2540 : : {
2541 : 0 : bDisconnect = 0; /* reject */
2542 : : }
2543 : : else
2544 : : {
2545 : : /* check valence */
2546 [ + + ]: 7 : if ((at[i].charge == 0 &&
2547 [ + - + - ]: 6 : (((type & 1) && val == get_el_valence(at[i].el_number, 0, 0)) ||
2548 [ + - + + ]: 6 : ((type & 2) && val == get_el_valence(at[i].el_number, 0, 1)))) ||
2549 [ - + ]: 5 : (at[i].charge > 0 &&
2550 [ # # # # ]: 0 : (type & 1) && val == get_el_valence(at[i].el_number, at[i].charge, 0))) /* djb-rwth: addressing LLVM warnings */
2551 : : {
2552 : : ; /* accept */
2553 : : }
2554 : : else
2555 : : {
2556 : 5 : bDisconnect = 0; /* reject */
2557 : : }
2558 : : }
2559 : :
2560 [ + + ]: 1165 : if (bDisconnect)
2561 : : {
2562 : : /*************************************************************************
2563 : : * | *
2564 : : * check M neighbors. Disconnect if all neighbors are M-O-C# or M-O-C= *
2565 : : * | *
2566 : : *************************************************************************/
2567 [ + + ]: 5 : for (k = 0; k < at[i].valence; k++)
2568 : : {
2569 : 4 : iO = at[i].neighbor[k];
2570 : : /* halogenide 2004-07-08 */
2571 [ + - ]: 4 : if ((at[iO].el_number == EL_NUMBER_F ||
2572 [ + + ]: 4 : at[iO].el_number == EL_NUMBER_CL ||
2573 [ + - ]: 1 : at[iO].el_number == EL_NUMBER_BR ||
2574 [ - + ]: 1 : at[iO].el_number == EL_NUMBER_I) &&
2575 [ + - + - ]: 3 : at[iO].valence == 1 && at[iO].chem_bonds_valence == 1 &&
2576 [ + - - + : 3 : !at[iO].charge && !(at[iO].radical && at[iO].radical != RADICAL_SINGLET) && !NUMH(at, iO))
- - + - ]
2577 : : {
2578 : : ; /* found */
2579 : : }
2580 : : else
2581 : : {
2582 : : /* -O-C= */
2583 [ - + ]: 1 : if (at[iO].el_number != EL_NUMBER_O ||
2584 [ # # ]: 0 : NUMH(at, iO) ||
2585 [ # # ]: 0 : at[iO].valence != 2 ||
2586 [ # # ]: 0 : at[iO].charge ||
2587 [ # # # # ]: 0 : (at[iO].radical && at[iO].radical != RADICAL_SINGLET) ||
2588 [ # # ]: 0 : at[iO].valence != at[iO].chem_bonds_valence) /* djb-rwth: addressing LLVM warning */
2589 : : {
2590 : 1 : bDisconnect = 0; /* reject */
2591 : 1 : break;
2592 : : }
2593 : 0 : iC = at[iO].neighbor[at[iO].neighbor[0] == i];
2594 [ # # ]: 0 : if (at[iC].el_number != EL_NUMBER_C ||
2595 [ # # ]: 0 : at[iC].num_H ||
2596 [ # # ]: 0 : at[iC].chem_bonds_valence != 4 ||
2597 [ # # ]: 0 : at[iC].charge ||
2598 [ # # # # ]: 0 : (at[iC].radical && at[iC].radical != RADICAL_SINGLET) ||
2599 [ # # ]: 0 : at[iC].valence == at[iC].chem_bonds_valence) /* djb-rwth: addressing LLVM warning */
2600 : : {
2601 : 0 : bDisconnect = 0; /* reject */
2602 : 0 : break;
2603 : : }
2604 [ # # ]: 0 : for (j = 0; j < at[iC].valence; j++)
2605 : : {
2606 : 0 : neigh = at[iC].neighbor[j];
2607 [ # # ]: 0 : if (at[neigh].el_number == EL_NUMBER_H)
2608 : : {
2609 : 0 : break;
2610 : : }
2611 : : }
2612 [ # # ]: 0 : if (j != at[iC].valence)
2613 : : {
2614 : 0 : bDisconnect = 0; /* reject */
2615 : 0 : break;
2616 : : }
2617 : : }
2618 : : }
2619 : : }
2620 : :
2621 : 1165 : return bDisconnect;
2622 : : }
2623 : :
2624 : : /****************************************************************************/
2625 : 0 : int DisconnectMetalSalt(inp_ATOM *at, int i)
2626 : : {
2627 : : int k, iO;
2628 : : /* disconnect metal atom or ion at[i] */
2629 : :
2630 [ # # ]: 0 : for (k = 0; k < at[i].valence; k++)
2631 : : {
2632 : 0 : iO = at[i].neighbor[k];
2633 [ # # ]: 0 : if (at[iO].valence == 2)
2634 : : {
2635 [ # # ]: 0 : if (at[iO].neighbor[0] == i)
2636 : : {
2637 : : /* assuming atom O always has 2 bonds */
2638 : : /* copy the remaining neighbor to the 0 position */
2639 : 0 : at[iO].neighbor[0] = at[iO].neighbor[1];
2640 : 0 : at[iO].bond_stereo[0] = at[iO].bond_stereo[1];
2641 : 0 : at[iO].bond_type[0] = at[iO].bond_type[1];
2642 : : }
2643 : : /* clear neighbor at position 1 */
2644 : 0 : at[iO].neighbor[1] = 0;
2645 : 0 : at[iO].bond_stereo[1] = 0;
2646 : 0 : at[iO].bond_type[1] = 0;
2647 : : }
2648 : : else
2649 : : {
2650 : : /* clear neighbor at position 1 */
2651 : 0 : at[iO].neighbor[0] = 0;
2652 : 0 : at[iO].bond_stereo[0] = 0;
2653 : 0 : at[iO].bond_type[0] = 0;
2654 : : }
2655 : :
2656 : : /* make O negatively charged */
2657 : 0 : at[iO].charge = -1;
2658 : :
2659 : : /* reduce O valence to account for the removed single bond */
2660 : 0 : at[iO].valence--;
2661 : 0 : at[iO].chem_bonds_valence--;
2662 : :
2663 : : /* clear metal neighbor (O) */
2664 : 0 : at[i].neighbor[k] = 0;
2665 : 0 : at[i].bond_stereo[k] = 0;
2666 : 0 : at[i].bond_type[k] = 0;
2667 : :
2668 : : /* add a positive charge to the metal */
2669 : 0 : at[i].charge++;
2670 : : }
2671 : :
2672 : : /* set metal valence to zero because it has been disconnected */
2673 : 0 : at[i].valence = 0;
2674 : 0 : at[i].chem_bonds_valence = 0;
2675 : :
2676 : 0 : return k;
2677 : : }
2678 : :
2679 : : /****************************************************************************/
2680 : 48 : int DisconnectSalts(ORIG_ATOM_DATA *orig_inp_data, int bDisconnect)
2681 : : {
2682 : : int i, k, iO, num_changes, val;
2683 : : S_CHAR num_explicit_H[NUM_H_ISOTOPES + 1];
2684 : 48 : inp_ATOM *at = orig_inp_data->at;
2685 : 48 : int num_at = orig_inp_data->num_inp_atoms;
2686 : :
2687 : : /* check each atom */
2688 [ + + ]: 639 : for (i = 0, num_changes = 0; i < num_at; i++)
2689 : : {
2690 : :
2691 [ + - ]: 591 : if (!(val = at[i].valence) || /* disconnected atom */
2692 [ + + ]: 591 : val != at[i].chem_bonds_valence || /* a bond has higher multiplicity than 1 */
2693 [ - + - - ]: 571 : (at[i].radical && at[i].radical != RADICAL_SINGLET) /* radical */) /* djb-rwth: addressing LLVM warning */
2694 : : {
2695 : 20 : continue; /* reject */
2696 : : }
2697 : :
2698 [ - + ]: 571 : if (bIsAmmoniumSalt(at, i, &iO, &k, num_explicit_H))
2699 : : {
2700 [ # # ]: 0 : if (bDisconnect)
2701 : : {
2702 : 0 : DisconnectAmmoniumSalt(at, i, iO, k, num_explicit_H);
2703 : 0 : orig_inp_data->num_inp_bonds--;
2704 : : }
2705 : :
2706 : : /* count disconnected atoms */
2707 : 0 : num_changes++;
2708 : : }
2709 [ - + ]: 571 : else if (bIsMetalSalt(at, i))
2710 : : {
2711 [ # # ]: 0 : if (bDisconnect)
2712 : : {
2713 : 0 : k = DisconnectMetalSalt(at, i);
2714 : 0 : orig_inp_data->num_inp_bonds -= k;
2715 : : }
2716 : 0 : num_changes++;
2717 : : }
2718 : : }
2719 : :
2720 : 48 : return num_changes;
2721 : : }
2722 : :
2723 : : /*****************************************************************************/
2724 : : /* Important: Salt disconnection is independent from coord. disconnection: */
2725 : : /* because different atoms are disconnected. */
2726 : : /* However, sal disconnection may need to be rerun after metal disconnection */
2727 : : /* because metal disconnection may make certain atoms be eligible for salt */
2728 : : /* disconnection */
2729 : : /*****************************************************************************/
2730 : 625 : int bIsMetalToDisconnect(inp_ATOM *at, int i, int bCheckMetalValence)
2731 : : {
2732 : : int type, at_valence, num_H;
2733 : :
2734 : : /*
2735 : : if ( !at[i].valence )
2736 : : */
2737 : :
2738 [ + + ]: 625 : if (!(type = get_el_type(at[i].el_number)) ||
2739 [ - + ]: 6 : !(type & IS_METAL))
2740 : : {
2741 : 619 : return 0;
2742 : : }
2743 : :
2744 : 6 : num_H = NUMH(at, i);
2745 : 6 : at_valence = num_H + at[i].chem_bonds_valence;
2746 : :
2747 [ - + ]: 6 : if (!at_valence)
2748 : : {
2749 : 0 : return 0; /* nothing to disconnect */
2750 : : }
2751 : :
2752 [ - + ]: 6 : if (bCheckMetalValence)
2753 : : {
2754 [ # # ]: 0 : if (abs(at[i].charge) > 1)
2755 : : {
2756 : 0 : return 1; /* multiple charges */
2757 : : }
2758 : :
2759 [ # # # # ]: 0 : for (i = 0; i < 2 && (i & type); i++)
2760 : : {
2761 [ # # ]: 0 : if (at_valence == get_el_valence( at[i].el_number, at[i].charge, i )) /* djb-rwth: fixing coverity ID #499532 -- unresolved issue -- revision required */
2762 : : {
2763 : 0 : return 2; /* atom has normal valence */
2764 : : }
2765 : : }
2766 : : }
2767 : :
2768 : 6 : return 1;
2769 : : }
2770 : :
2771 : : /****************************************************************************/
2772 : 54 : int bMayDisconnectMetals(ORIG_ATOM_DATA *orig_inp_data,
2773 : : int bCheckMetalValence,
2774 : : INCHI_MODE *bTautFlagsDone)
2775 : : {
2776 : 54 : int i, j, k, iO, num_changes, val, bRadOrMultBonds, num_impl_H = 0;
2777 : : S_CHAR num_explicit_H[NUM_H_ISOTOPES + 1];
2778 : 54 : inp_ATOM *at = orig_inp_data->at;
2779 : 54 : int num_at = orig_inp_data->num_inp_atoms;
2780 : 54 : int *nNumImplH = &orig_inp_data->bDisconnectCoord;
2781 : :
2782 : : /* check each atom */
2783 [ + + ]: 673 : for (i = 0, num_changes = 0; i < num_at; i++)
2784 : : {
2785 : :
2786 [ + + + - ]: 619 : if (!(val = at[i].valence) && !NUMH(at, i))
2787 : : {
2788 : 4 : continue; /* disconnected atom */
2789 : : }
2790 : :
2791 : 1230 : bRadOrMultBonds = (val == 0) ||
2792 [ + - + + ]: 1206 : (val != at[i].chem_bonds_valence) || /* a bond has higher multiplicity than 1 */
2793 [ - + - - ]: 591 : (at[i].radical && at[i].radical != RADICAL_SINGLET); /* radical */
2794 : :
2795 [ + + - + ]: 615 : if (!bRadOrMultBonds && bIsAmmoniumSalt(at, i, &iO, &k, num_explicit_H))
2796 : : {
2797 : : ;
2798 : : }
2799 [ + + + + ]: 615 : else if (!bRadOrMultBonds && bIsMetalSalt(at, i))
2800 : : {
2801 : : ;
2802 : : }
2803 [ + + ]: 614 : else if (1 == (j = bIsMetalToDisconnect(at, i, bCheckMetalValence)))
2804 : : {
2805 : 5 : num_impl_H += NUMH(at, i);
2806 : 5 : num_changes++;
2807 : : }
2808 [ - + - - ]: 609 : else if (2 == j && bTautFlagsDone)
2809 : : {
2810 : 0 : *bTautFlagsDone |= TG_FLAG_CHECK_VALENCE_COORD_DONE;
2811 : : }
2812 : : }
2813 : :
2814 [ + - ]: 54 : if (nNumImplH)
2815 : : {
2816 [ + + ]: 54 : *nNumImplH = num_changes ? num_impl_H + 1 : 0;
2817 : : }
2818 : :
2819 : 54 : return num_changes;
2820 : : }
2821 : :
2822 : : /****************************************************************************/
2823 : :
2824 : : #if (bRELEASE_VERSION == 0 && (EXTR_HAS_METAL_ATOM & (EXTR_MASK | EXTR_FLAG)))
2825 : :
2826 : : /****************************************************************************/
2827 : : int bHasMetalAtom(ORIG_ATOM_DATA *orig_inp_data)
2828 : : {
2829 : : int i;
2830 : : inp_ATOM *at;
2831 : :
2832 : : if (orig_inp_data && (at = orig_inp_data->at))
2833 : : {
2834 : : int num_at = orig_inp_data->num_inp_atoms;
2835 : : /* check each atom */
2836 : : for (i = 0; i < num_at; i++)
2837 : : {
2838 : : if (IS_METAL & get_el_type(at[i].el_number))
2839 : : {
2840 : : return 1;
2841 : : }
2842 : : }
2843 : : }
2844 : :
2845 : : return 0;
2846 : : }
2847 : : #endif
2848 : :
2849 : : /*****************************************************************************
2850 : : { "F", 19, 19, 18.998403220, 0 , 0, {{0,}, {0,}, {1,}, {2,}, {3,5}, },},
2851 : : { "Cl", 35, 35, 34.968852730, 0 , 0, {{0,}, {0,}, {1,3,5,7}, {2,4,6}, {3,5,}, },},
2852 : : { "Br", 80, 79, 78.918336100, 0 , 0, {{0,}, {0,}, {1,3,5,7,}, {2,4,6,}, {3,5,}, },},
2853 : : { "I", 127, 127, 126.904500000, 0 , 0, {{0,}, {0,}, {1,3,5,7,}, {2,4,6}, {3,5,}, },},
2854 : : { "At", 210, 210, 209.987100000, 0 , 0, {{0,}, {0,}, {1,3,5,7,}, {2,4,6}, {3,5,}, },},
2855 : : { "N", 14, 14, 14.003074000, 0 , 0, {{1,}, {2,}, {3,5}, {4,}, {3,}, },},
2856 : : { "P", 31, 31, 30.973762000, 0 , 0, {{1,3,5,7,}, {2,4,6,}, {3,5,}, {4,}, {3,}, },},
2857 : : { "As", 75, 75, 74.921594200, 0 , 0, {{0,}, {2,4,6,}, {3,5,}, {4,}, {3,}, },},
2858 : : { "Sb", 122, 121, 120.903800000, 0 , 0, {{1,3,5,7,}, {2,4,6,}, {3,5,}, {2,4,}, {3,}, },},
2859 : : { "O", 16, 16, 15.994914630, 0 , 0, {{0,}, {1,}, {2,}, {3,5,}, {4,}, },},
2860 : : { "S", 32, 32, 31.972070700, 0 , 0, {{0,}, {1,3,5,7,}, {2,4,6}, {3,5,}, {4,}, },},
2861 : : { "Se", 79, 80, 79.916519600, 0 , 0, {{0,}, {1,3,5,7,}, {2,4,6,}, {3,5,}, {4,}, },},
2862 : : { "Te", 128, 130, 129.906200000, 0 , 0, {{0,}, {1,3,5,7,}, {2,4,6,}, {3,5,}, {2,4,}, },},
2863 : : { "Po", 209, 209, 208.982400000, 0 , 0, {{0,}, {1,3,5,7,}, {2,4,6,}, {3,5,}, {2,4,}, },},
2864 : : { "B", 11, 11, 11.009300000, 0 , 0, {{3,}, {4,}, {3,}, {2,}, {1,}, },},
2865 : : *****************************************************************************/
2866 : :
2867 : : /****************************************************************************/
2868 : 1 : int DisconnectMetals(ORIG_ATOM_DATA *orig_inp_data,
2869 : : int bCheckMetalValence,
2870 : : INCHI_MODE *bTautFlagsDone)
2871 : : {
2872 : : int i, j, k, n, iO, num_changes, val, bRadOrMultBonds;
2873 : : int num_impl_H, num_at, err, num_disconnected;
2874 : : S_CHAR num_explicit_H[NUM_H_ISOTOPES + 1];
2875 : : static char elnumber_Heteroat[16] = {
2876 : : '\0',
2877 : : };
2878 : : static int num_halogens = 0;
2879 : : int num_halogens2;
2880 : :
2881 : 1 : inp_ATOM *at = NULL;
2882 : 1 : S_CHAR *bMetal = NULL;
2883 : 1 : inp_ATOM *atom = orig_inp_data->at;
2884 : 1 : int num_atoms = orig_inp_data->num_inp_atoms;
2885 : 1 : int nNumExplH = (orig_inp_data->bDisconnectCoord > 0) ? orig_inp_data->bDisconnectCoord - 1 : 0;
2886 : 1 : AT_NUMB *nOldCompNumber = orig_inp_data->nOldCompNumber;
2887 : :
2888 : 1 : err = 0;
2889 : 1 : num_impl_H = 0;
2890 : 1 : num_at = num_atoms;
2891 : 1 : num_disconnected = 0;
2892 : :
2893 [ + - ]: 1 : if (!(at = (inp_ATOM *)inchi_calloc((long long)num_at + (long long)nNumExplH, sizeof(at[0]))) || /* djb-rwth: cast operators added */
2894 [ - + ]: 1 : !(bMetal = (S_CHAR *)inchi_calloc((long long)num_at + (long long)nNumExplH, sizeof(bMetal[0])))) /* djb-rwth: cast operators added */
2895 : : {
2896 : 0 : err = 1;
2897 : 0 : goto exit_function;
2898 : : }
2899 : :
2900 [ + - ]: 1 : if (!num_halogens) /* if (!elnumber_Heteroat[0] ) */
2901 : : {
2902 : 1 : i = 0;
2903 : : /* halogens */
2904 : 1 : elnumber_Heteroat[i++] = (char)EL_NUMBER_F; /* 0 */
2905 : 1 : elnumber_Heteroat[i++] = (char)EL_NUMBER_CL;
2906 : 1 : elnumber_Heteroat[i++] = (char)EL_NUMBER_BR;
2907 : 1 : elnumber_Heteroat[i++] = (char)EL_NUMBER_I;
2908 : 1 : elnumber_Heteroat[i++] = (char)EL_NUMBER_AT; /* 4 */
2909 : 1 : num_halogens2 = i;
2910 : : /* other non-metal */
2911 : 1 : elnumber_Heteroat[i++] = (char)EL_NUMBER_N;
2912 : 1 : elnumber_Heteroat[i++] = (char)EL_NUMBER_P;
2913 : 1 : elnumber_Heteroat[i++] = (char)EL_NUMBER_AS;
2914 : : /*elnumber_Heteroat[i++] = EL_NUMBER_SB;*/ /* metal 10-28-2003 */
2915 : 1 : elnumber_Heteroat[i++] = (char)EL_NUMBER_O;
2916 : 1 : elnumber_Heteroat[i++] = (char)EL_NUMBER_S;
2917 : 1 : elnumber_Heteroat[i++] = (char)EL_NUMBER_SE;
2918 : 1 : elnumber_Heteroat[i++] = (char)EL_NUMBER_TE;
2919 : : /*elnumber_Heteroat[i++] = EL_NUMBER_PO;*/ /* metal 10-28-2003 */
2920 : 1 : elnumber_Heteroat[i++] = (char)EL_NUMBER_B;
2921 : 1 : elnumber_Heteroat[i++] = 0;
2922 : 1 : num_halogens = num_halogens2;
2923 : : }
2924 : :
2925 : 1 : memcpy(at, atom, num_atoms * sizeof(at[0]));
2926 : :
2927 : : /* check each atom, mark metals */
2928 [ + + ]: 12 : for (i = 0, k = 0, num_changes = 0; i < num_atoms; i++)
2929 : : {
2930 [ - + - - ]: 11 : if (!(val = at[i].valence) && !NUMH(at, i))
2931 : : {
2932 : 0 : continue; /* disconnected atom */
2933 : : }
2934 : 22 : bRadOrMultBonds = (val == 0) ||
2935 [ + - + + ]: 14 : (val != at[i].chem_bonds_valence) || /* a bond has higher multiplicity than 1 */
2936 [ - + - - ]: 3 : (at[i].radical && at[i].radical != RADICAL_SINGLET); /* radical */
2937 : :
2938 [ + + - + ]: 11 : if (!bRadOrMultBonds && bIsAmmoniumSalt(at, i, &iO, &k, num_explicit_H))
2939 : : {
2940 : : ;
2941 : : }
2942 [ + + - + ]: 11 : else if (!bRadOrMultBonds && bIsMetalSalt(at, i))
2943 : : {
2944 : : ;
2945 : : }
2946 [ + + ]: 11 : else if (1 == (j = bIsMetalToDisconnect(at, i, bCheckMetalValence)))
2947 : : {
2948 : 1 : num_impl_H += (k = NUMH(at, i));
2949 : 1 : bMetal[i] = 1 + k;
2950 : 1 : num_changes++;
2951 : : }
2952 [ - + - - ]: 10 : else if (2 == j && bTautFlagsDone)
2953 : : {
2954 : 0 : *bTautFlagsDone |= TG_FLAG_CHECK_VALENCE_COORD_DONE;
2955 : : }
2956 : : }
2957 : :
2958 [ - + ]: 1 : if (num_impl_H != nNumExplH)
2959 : : {
2960 : 0 : err = 2;
2961 : 0 : goto exit_function;
2962 : : }
2963 : :
2964 : : /* replace implicit H atoms with explicit H atoms */
2965 [ + - - + ]: 1 : for (i = 0; i < num_atoms && 0 < num_impl_H; i++)
2966 : : {
2967 [ # # ]: 0 : if (bMetal[i] <= 1)
2968 : : {
2969 : 0 : continue;
2970 : : }
2971 [ # # ]: 0 : for (k = 0; k < NUM_H_ISOTOPES + 1; k++)
2972 : : {
2973 [ # # ]: 0 : n = k ? at[i].num_iso_H[k - 1] : at[i].num_H;
2974 [ # # ]: 0 : for (j = 0; j < n; j++)
2975 : : {
2976 [ # # ]: 0 : if (num_at >= num_atoms + nNumExplH)
2977 : : {
2978 : 0 : err = 3;
2979 : 0 : goto exit_function;
2980 : : }
2981 : 0 : at[num_at].elname[0] = 'H';
2982 : 0 : at[num_at].el_number = get_periodic_table_number(at[num_at].elname);
2983 : 0 : at[num_at].iso_atw_diff = k;
2984 : 0 : at[num_at].component = at[i].component;
2985 : 0 : move_explicit_Hcation(at, num_at + 1, i, num_at, 1);
2986 : 0 : at[num_at].orig_at_number = num_at + 1;
2987 : 0 : num_at++;
2988 : 0 : num_impl_H--;
2989 : 0 : bMetal[i]--;
2990 [ # # ]: 0 : if (k)
2991 : : {
2992 : 0 : at[i].num_iso_H[k - 1]--;
2993 : : }
2994 : : else
2995 : : {
2996 : 0 : at[i].num_H--;
2997 : : }
2998 : : }
2999 : : }
3000 : :
3001 [ # # ]: 0 : if (bMetal[i] != 1)
3002 : : {
3003 : 0 : err = 4;
3004 : 0 : goto exit_function;
3005 : : }
3006 : : }
3007 : :
3008 [ - + ]: 1 : if (num_at != num_atoms + nNumExplH)
3009 : : {
3010 : 0 : err = 5;
3011 : 0 : goto exit_function;
3012 : : }
3013 : :
3014 : : /* disconnect metal - ligand bonds */
3015 [ + + ]: 12 : for (i = 0; i < num_atoms; i++)
3016 : : {
3017 [ + + ]: 11 : if (!bMetal[i])
3018 : : {
3019 : 10 : continue;
3020 : : }
3021 : :
3022 : : /* disconnect metal atom M
3023 : :
3024 : : Note: Defect in case of bridging ligands:
3025 : :
3026 : : M M M M M M(+)
3027 : : \ / will be transformed to , not to
3028 : : N(+) N(+) N(-)
3029 : : / \ / \ / \
3030 : : R R R R R R
3031 : :
3032 : : Non-bridging are OK:
3033 : :
3034 : : M R M(+) R
3035 : : \ / /
3036 : : N(+) ---> N
3037 : : / \ / \
3038 : : R R R R
3039 : :
3040 : : */
3041 : :
3042 [ + + ]: 11 : for (j = at[i].valence - 1; 0 <= j; j--)
3043 : : {
3044 [ + - + - ]: 10 : if (j < at[i].valence && !bMetal[(int)at[i].neighbor[j]])
3045 : : {
3046 : : /* do not break metal-metal bond here */
3047 : :
3048 : 10 : num_disconnected += DisconnectOneLigand(at,
3049 : : nOldCompNumber,
3050 : : bMetal,
3051 : : elnumber_Heteroat,
3052 : : num_halogens,
3053 : : num_atoms,
3054 : : i,
3055 : : j,
3056 : : bTautFlagsDone);
3057 : : }
3058 : : }
3059 : : }
3060 : :
3061 : : /* disconnect metal-metal bonds */
3062 [ + + ]: 12 : for (i = 0; i < num_atoms; i++)
3063 : : {
3064 [ + + ]: 11 : if (!bMetal[i])
3065 : : {
3066 : 10 : continue;
3067 : : }
3068 [ - + ]: 1 : for (j = at[i].valence - 1; 0 <= j; j--)
3069 : : {
3070 [ # # # # ]: 0 : if (j < at[i].valence && bMetal[(int)at[i].neighbor[j]])
3071 : : {
3072 : : /* break metal-metal bond here */
3073 : :
3074 : 0 : num_disconnected += DisconnectOneLigand(at,
3075 : : nOldCompNumber,
3076 : : bMetal,
3077 : : elnumber_Heteroat,
3078 : : num_halogens,
3079 : : num_atoms,
3080 : : i,
3081 : : j,
3082 : : bTautFlagsDone);
3083 : : }
3084 : : }
3085 : : }
3086 : :
3087 : 1 : exit_function:
3088 : :
3089 [ - + ]: 1 : if (!num_disconnected)
3090 : : {
3091 : 0 : err = 6;
3092 : : }
3093 [ + - - + ]: 1 : if (at && err)
3094 : : {
3095 [ # # ]: 0 : inchi_free(at);
3096 : 0 : at = NULL;
3097 : : }
3098 [ + - + - ]: 1 : if (atom && at)
3099 : : { /* changed if ( at ) to if ( atom && at ) 2004-04-03 */
3100 [ + - ]: 1 : inchi_free(atom);
3101 : 1 : atom = NULL;
3102 : : }
3103 [ + - ]: 1 : if (bMetal)
3104 [ + - ]: 1 : inchi_free(bMetal);
3105 : :
3106 [ + - ]: 1 : if (at)
3107 : : {
3108 : 1 : orig_inp_data->at = at;
3109 : 1 : orig_inp_data->num_inp_atoms = num_at;
3110 : : }
3111 : :
3112 [ - + ]: 1 : return err ? -err : num_disconnected;
3113 : : }
3114 : :
3115 : : /****************************************************************************/
3116 : 10 : int DisconnectOneLigand(inp_ATOM *at,
3117 : : AT_NUMB *nOldCompNumber,
3118 : : S_CHAR *bMetal,
3119 : : char *elnumber_Heteroat,
3120 : : int num_halogens,
3121 : : int num_atoms,
3122 : : int iMetal,
3123 : : int jLigand,
3124 : : INCHI_MODE *bTautFlagsDone)
3125 : : {
3126 : : int i, j, iLigand, neigh, val;
3127 : : int metal_neigh_ord[MAXVAL], num_neigh_arom_bonds[MAXVAL];
3128 : : int num_metal_neigh, num_disconnections;
3129 : : int num_del_arom_bonds, num_tot_arom_bonds, new_charge;
3130 : : char *p;
3131 : :
3132 : 10 : iLigand = at[iMetal].neighbor[jLigand];
3133 : 10 : num_metal_neigh = 0;
3134 : 10 : num_disconnections = 0;
3135 : 10 : num_del_arom_bonds = num_tot_arom_bonds = 0;
3136 : :
3137 : : /* find bonds to disconnect */
3138 [ + + ]: 40 : for (i = 0; i < at[iLigand].valence; i++)
3139 : : {
3140 : 30 : num_neigh_arom_bonds[i] = 0;
3141 : 30 : neigh = (int)at[iLigand].neighbor[i];
3142 [ + - + + ]: 30 : if (neigh < num_atoms && bMetal[neigh])
3143 : : {
3144 : 10 : metal_neigh_ord[num_metal_neigh++] = i;
3145 [ + - ]: 10 : if (at[iLigand].bond_type[i] > BOND_TYPE_TRIPLE)
3146 : : {
3147 : : /* aromatic bond */
3148 [ + + ]: 65 : for (j = 0; j < at[neigh].valence; j++)
3149 : : {
3150 : 55 : num_neigh_arom_bonds[i] += (at[neigh].bond_type[j] > BOND_TYPE_TRIPLE);
3151 : : }
3152 : 10 : num_del_arom_bonds++;
3153 : : }
3154 : : }
3155 : 30 : num_tot_arom_bonds += (at[iLigand].bond_type[i] > BOND_TYPE_TRIPLE);
3156 : : }
3157 : :
3158 : : /* Disconnect */
3159 [ + - ]: 10 : if (num_del_arom_bonds)
3160 : : {
3161 : : /* fix chem_valence of the ligand and its neighbors in case of disconnecting arom. bonds */
3162 : : /* because in this case special care should be taken of updating at[].chem_bonds_valence */
3163 [ + + ]: 20 : for (i = 0; i < num_metal_neigh; i++)
3164 : : {
3165 : 10 : j = metal_neigh_ord[i];
3166 [ + - ]: 10 : if (num_neigh_arom_bonds[j])
3167 : : {
3168 : 10 : neigh = at[iLigand].neighbor[j];
3169 : 10 : at[neigh].chem_bonds_valence -= num_neigh_arom_bonds[j] / 2 - (num_neigh_arom_bonds[j] - 1) / 2;
3170 : : }
3171 : : }
3172 : 10 : at[iLigand].chem_bonds_valence -= num_tot_arom_bonds / 2 - (num_tot_arom_bonds - num_del_arom_bonds) / 2;
3173 : : }
3174 : :
3175 : : /* disconnect in reverse order, otherwise the metal_neigh_ord[i]
3176 : : becomes invalid after the first disconnection
3177 : : */
3178 [ + + ]: 20 : for (i = num_metal_neigh - 1; 0 <= i; i--)
3179 : : {
3180 : 10 : num_disconnections += DisconnectInpAtBond(at,
3181 : : nOldCompNumber,
3182 : : iLigand,
3183 : : metal_neigh_ord[i]);
3184 : : }
3185 : :
3186 : : /* attempt to change ligand charge to make its valence 'natural' */
3187 : 10 : i = num_tot_arom_bonds - num_del_arom_bonds;
3188 [ - + - - : 10 : if ((i && i != 2 && i != 3) ||
- - ]
3189 [ - + - - ]: 10 : (at[iLigand].radical && at[iLigand].radical != RADICAL_SINGLET) ||
3190 [ + - ]: 10 : !(p = strchr(elnumber_Heteroat, at[iLigand].el_number))) /* djb-rwth: addressing LLVM warnings */
3191 : : {
3192 : 10 : goto exit_function; /* non-standard atom */
3193 : : }
3194 : :
3195 : 0 : val = at[iLigand].chem_bonds_valence + NUMH(at, iLigand);
3196 : 0 : new_charge = MAX_ATOMS; /* impossible value */
3197 : :
3198 [ # # ]: 0 : if (!val)
3199 : : {
3200 [ # # ]: 0 : if (p - elnumber_Heteroat < num_halogens)
3201 : : {
3202 : 0 : new_charge = -1;
3203 : : }
3204 : : }
3205 : : else
3206 : : {
3207 [ # # ]: 0 : for (i = -1; i <= 1; i++)
3208 : : {
3209 [ # # ]: 0 : if (val == get_el_valence(at[iLigand].el_number, i, 0))
3210 : : {
3211 : 0 : new_charge = i; /* found charge that fits chem. valence */
3212 : 0 : break;
3213 : : }
3214 : : }
3215 : : }
3216 : :
3217 [ # # ]: 0 : if (new_charge != MAX_ATOMS)
3218 : : {
3219 [ # # ]: 0 : if ((new_charge != at[iLigand].charge ||
3220 [ # # # # : 0 : (at[iLigand].radical && at[iLigand].radical != RADICAL_SINGLET)) &&
# # ]
3221 : : 1 == num_metal_neigh)
3222 : : {
3223 [ # # # # : 0 : if (1 == new_charge && 4 == val && 2 == at[iLigand].valence &&
# # ]
3224 [ # # ]: 0 : 4 == at[iLigand].chem_bonds_valence &&
3225 [ # # ]: 0 : at[iLigand].bond_type[0] == at[iLigand].bond_type[1])
3226 : : {
3227 : : ; /* do not add +1 charge to disconnected =N=, etc. 2004-10-27 */
3228 : : }
3229 : : else
3230 : : {
3231 [ # # # # ]: 0 : if (bTautFlagsDone && new_charge != at[iLigand].charge)
3232 : : {
3233 : 0 : *bTautFlagsDone |= TG_FLAG_MOVE_CHARGE_COORD_DONE;
3234 : : }
3235 : 0 : at[iMetal].charge -= new_charge - at[iLigand].charge;
3236 : 0 : at[iLigand].charge = new_charge;
3237 : : /*at[iLigand].radical = 0;*/
3238 : : }
3239 : : }
3240 : : }
3241 : :
3242 : 0 : exit_function:
3243 : :
3244 : 10 : return num_disconnections; /* ret;*/
3245 : : }
3246 : :
3247 : : /****************************************************************************/
3248 : 0 : double dist3D(inp_ATOM *at1, inp_ATOM *at2)
3249 : : {
3250 : 0 : double dx = at1->x - at2->x;
3251 : 0 : double dy = at1->y - at2->y;
3252 : 0 : double dz = at1->z - at2->z;
3253 : :
3254 : 0 : return sqrt(dx * dx + dy * dy + dz * dz);
3255 : : }
3256 : :
3257 : : /****************************************************************************/
3258 : : #define MIN_BOND_LENGTH (1.0e-6)
3259 : : #define MIN_COS (1.0e-6)
3260 : : #define MIN_BOND_LENGTH2 (MIN_BOND_LENGTH * MIN_BOND_LENGTH)
3261 : : #define MAX_BOND_LENGTH (1.0e30)
3262 : : /****************************************************************************/
3263 : :
3264 : : /****************************************************************************/
3265 : 0 : double GetMinDistDistribution(inp_ATOM *at,
3266 : : int num_at,
3267 : : int iat,
3268 : : int iat_H,
3269 : : int bInAllComponents,
3270 : : double min_dist[],
3271 : : int num_segm)
3272 : : {
3273 : : /* const double one_pi = 2.0*atan2(1.0 , 0.0 ); */
3274 : 0 : const double one_pi = 3.14159265358979323846; /* M_PI */
3275 : 0 : const double two_pi = 2.0 * one_pi;
3276 : 0 : const double f_step = two_pi / num_segm;
3277 : 0 : const double h_step = f_step / 2.0;
3278 : : int i, j, k, kk, ki, kn, n, num_bonds;
3279 : : double xi, yi, xn, yn, cross_prod_in, dot_prod_in, xni, yni, rni, tni, rmin;
3280 : 0 : double fi, fk, fn, ft = 0, rt = 0, rk, ri, rn, c, ave_bond_len;
3281 : :
3282 [ # # ]: 0 : for (i = 0; i < num_segm; i++)
3283 : : {
3284 : 0 : min_dist[i] = MAX_BOND_LENGTH; /* more than any distance */
3285 : : }
3286 : 0 : num_bonds = 0;
3287 : 0 : ave_bond_len = 0.0;
3288 : :
3289 [ # # ]: 0 : for (i = 0; i < num_at; i++)
3290 : : {
3291 [ # # # # : 0 : if (i != iat && i != iat_H &&
# # ]
3292 [ # # ]: 0 : (bInAllComponents || at[i].component == at[iat].component))
3293 : : {
3294 [ # # ]: 0 : for (j = 0; j < at[i].valence; j++)
3295 : : {
3296 : 0 : n = at[i].neighbor[j];
3297 [ # # # # : 0 : if ((n > i && n != iat) || n == iat_H)
# # ]
3298 : : {
3299 : 0 : continue;
3300 : : }
3301 : : #if (bRELEASE_VERSION != 1 && defined(_DEBUG))
3302 : : if (n == iat)
3303 : : {
3304 : : int stop = 1; /* <BRKPT> */
3305 : : }
3306 : : #endif
3307 : 0 : xi = at[i].x - at[iat].x; /* ri; i != iat */
3308 : 0 : yi = at[i].y - at[iat].y;
3309 : 0 : xn = at[n].x - at[iat].x; /* rn; possibly n == iat */
3310 : 0 : yn = at[n].y - at[iat].y;
3311 : 0 : cross_prod_in = xi * yn - xn * yi; /* ((r(i)-r(iat)) x (r(n)-r(iat)) */
3312 [ # # ]: 0 : if (cross_prod_in < -0.01 * MIN_BOND_LENGTH2)
3313 : : {
3314 : : /* make sure the r(i)->r(n) vector is counterclockwise around at[iat] */
3315 : 0 : inchi_swap((char *)&xi, (char *)&xn, sizeof(xi));
3316 : 0 : inchi_swap((char *)&yi, (char *)&yn, sizeof(yi));
3317 : : /* djb-rwth: removing redundant code */
3318 : : }
3319 : :
3320 : 0 : xni = xn - xi; /* r(n)->r(i) */
3321 : 0 : yni = yn - yi;
3322 : 0 : rni = xni * xni + yni * yni;
3323 [ # # ]: 0 : if (rni > 0.01 * MIN_BOND_LENGTH2)
3324 : : {
3325 : : /* vector length |ri->rn| is not too small */
3326 : : /* arrowhead of the vector r(t) = ri + (rn-ri)*t; 0 <= t <= 1 points to the bond ri->rn */
3327 : : /* r(tni) is perpendicular to the bond ri->rn so that min|r(t)| = r(tni) = |tni|*rni */
3328 : 0 : tni = -(xni * xi + yni * yi) / rni;
3329 : : /* find min. distance from n-i bond to at[iat] */
3330 [ # # ]: 0 : if (tni < 0.0)
3331 : : {
3332 : 0 : rmin = sqrt(xi * xi + yi * yi);
3333 : : }
3334 [ # # ]: 0 : else if (tni > 1.0)
3335 : : {
3336 : 0 : rmin = sqrt(xn * xn + yn * yn);
3337 : : }
3338 : : else
3339 : : {
3340 : 0 : rmin = sqrt(tni * tni * rni);
3341 : : }
3342 : 0 : ave_bond_len += sqrt(rni);
3343 : 0 : num_bonds++;
3344 : : }
3345 : : else
3346 : : {
3347 : : /* zero length i-n bond */
3348 : 0 : tni = 0.5; /* fake */
3349 : 0 : rmin = sqrt(xi * xi + yi * yi); /* arbitrarily choose one */
3350 : : }
3351 [ # # ]: 0 : if (rmin >= 0.1 * MIN_BOND_LENGTH)
3352 : : {
3353 : : /* at[iat] does not belong to at[i]-at[n] bond */
3354 : 0 : int bCalc_rt = 1;
3355 : 0 : fi = atan2(yi, xi);
3356 [ # # ]: 0 : fn = (n == iat) ? fi : atan2(yn, xn);
3357 [ # # ]: 0 : if (fi > fn)
3358 : : {
3359 : : /* make sure fn - fi >= 0 */
3360 : 0 : fn += two_pi;
3361 : : }
3362 [ # # ]: 0 : if (fi < 0.0)
3363 : : {
3364 : 0 : fi += two_pi;
3365 : 0 : fn += two_pi;
3366 : : }
3367 : 0 : ki = (int)floor((fi + h_step) / f_step); /* cast does not match function type */
3368 : 0 : kn = (int)floor((fn + h_step) / f_step);
3369 : :
3370 : : /* the bond may affect several segments */
3371 [ # # ]: 0 : for (k = ki; k <= kn; k++)
3372 : : {
3373 : 0 : kk = k % num_segm;
3374 [ # # ]: 0 : if (min_dist[kk] < rmin)
3375 : : {
3376 : 0 : continue;
3377 : : }
3378 [ # # ]: 0 : if (bCalc_rt)
3379 : : {
3380 [ # # ]: 0 : if (n == iat)
3381 : : {
3382 : 0 : ft = fi;
3383 : 0 : rt = rmin;
3384 : : }
3385 : : else
3386 : : {
3387 : : double xt, yt;
3388 : 0 : xt = xi + xni * tni;
3389 : 0 : yt = yi + yni * tni;
3390 : 0 : ft = atan2(yt, xt);
3391 : 0 : rt = sqrt(xt * xt + yt * yt);
3392 : : }
3393 : 0 : bCalc_rt = 0;
3394 : : }
3395 : 0 : fk = f_step * kk;
3396 : 0 : c = fabs(cos(fk - ft));
3397 [ # # ]: 0 : if (c < MIN_COS)
3398 : 0 : c = MIN_COS;
3399 : 0 : rk = rt / c;
3400 [ # # ]: 0 : if (min_dist[kk] > rk)
3401 : : {
3402 : 0 : min_dist[kk] = rk;
3403 : : }
3404 : : }
3405 : : }
3406 : : else
3407 : : {
3408 : : /* rmin < 0.1*MIN_BOND_LENGTH */
3409 : 0 : ri = xi * xi + yi * yi;
3410 : 0 : rn = xn * xn + yn * yn;
3411 [ # # # # ]: 0 : if (ri > MIN_BOND_LENGTH2 && rn > MIN_BOND_LENGTH2)
3412 : : {
3413 : 0 : dot_prod_in = xn * xi + yn * yi;
3414 : : /* a very short bond */
3415 [ # # ]: 0 : if (dot_prod_in > 0.01 * MIN_BOND_LENGTH2)
3416 : : {
3417 : : /* bond does not cross at[iat] */
3418 : 0 : double fyixi = atan2(yi, xi);
3419 [ # # ]: 0 : if (fyixi < 0.0)
3420 : 0 : fyixi += two_pi;
3421 : 0 : kk = (int)floor((fyixi + h_step) / f_step) % num_segm;
3422 [ # # ]: 0 : if (min_dist[kk] > rmin)
3423 : : {
3424 : 0 : min_dist[kk] = rmin;
3425 : : }
3426 : : }
3427 [ # # ]: 0 : else if (dot_prod_in < -0.01 * MIN_BOND_LENGTH2)
3428 : : {
3429 : : /* bond does cross at[iat] */
3430 : 0 : double fyixi = atan2(yi, xi);
3431 [ # # ]: 0 : if (fyixi < 0.0)
3432 : 0 : fyixi += two_pi;
3433 : 0 : kk = (int)floor((fyixi + h_step) / f_step) % num_segm;
3434 [ # # ]: 0 : if (min_dist[kk] > rmin)
3435 : : {
3436 : 0 : min_dist[kk] = rmin;
3437 : : }
3438 : 0 : fyixi += one_pi;
3439 : 0 : kk = (int)floor((fyixi + h_step) / f_step) % num_segm;
3440 [ # # ]: 0 : if (min_dist[kk] > rmin)
3441 : : {
3442 : 0 : min_dist[kk] = rmin;
3443 : : }
3444 : : }
3445 : : else
3446 : : {
3447 : : ; /* error, should not happen */
3448 : : }
3449 : : }
3450 [ # # # # ]: 0 : else if (ri <= MIN_BOND_LENGTH2 && rn <= MIN_BOND_LENGTH2)
3451 : : {
3452 : : /* a very short bond coincides with at[iat]; ignore */
3453 : : ;
3454 : : }
3455 : : else
3456 : : {
3457 : : /* one end of the bond coincides with at[iat] */
3458 [ # # ]: 0 : fi = ri > rn ? atan2(yi, xi) : atan2(yn, xn);
3459 [ # # ]: 0 : if (fi < 0.0)
3460 : 0 : fi += two_pi;
3461 : 0 : kk = (int)floor((fi + h_step) / f_step) % num_segm;
3462 [ # # ]: 0 : if (min_dist[kk] > rmin)
3463 : : {
3464 : 0 : min_dist[kk] = rmin;
3465 : : }
3466 : : }
3467 : : }
3468 : : }
3469 : : }
3470 : : }
3471 : :
3472 [ # # ]: 0 : if (num_bonds)
3473 : : {
3474 : 0 : return ave_bond_len / (double)num_bonds;
3475 : : }
3476 : : else
3477 : : {
3478 : 0 : return 0.0;
3479 : : }
3480 : : }
3481 : :
3482 : : /****************************************************************************/
3483 : 0 : int move_explicit_Hcation(inp_ATOM *at,
3484 : : int num_at,
3485 : : int iat,
3486 : : int iat_H,
3487 : : int bInAllComponents)
3488 : : {
3489 : :
3490 : : #define NUM_SEGM 20
3491 : :
3492 : : /* const double one_pi = 2.0*atan2(1.0 , 0.0 ); */
3493 : 0 : const double one_pi = 3.14159265358979323846; /* M_PI */
3494 : 0 : const double two_pi = 2.0 * one_pi;
3495 : 0 : const double f_step = two_pi / NUM_SEGM;
3496 : 0 : const double h_step = f_step / 2.0;
3497 : : double min_dist[NUM_SEGM];
3498 : 0 : int nB, i, k, kk, next, val = 0;
3499 : : double r, r0, xd, yd, zd, xr, yr, zr, ave_bond_len;
3500 : : /*double step = 4.0*atan(1.0)/NUM_SEGM;*/
3501 : : /* find at[iat] neighbors coordinates */
3502 : :
3503 : 0 : xd = yd = zd = 0.0;
3504 : :
3505 [ # # ]: 0 : if (at[iat].valence)
3506 : : {
3507 [ # # ]: 0 : for (i = 0, nB = 0, r = 0.0; i < at[iat].valence; i++)
3508 : : {
3509 : 0 : next = at[iat].neighbor[i];
3510 : 0 : xd += at[next].x;
3511 : 0 : yd += at[next].y;
3512 : 0 : zd += at[next].z;
3513 : 0 : r += dist3D(at + iat, at + next);
3514 : 0 : nB++;
3515 : : }
3516 : 0 : xd /= (double)nB;
3517 : 0 : yd /= (double)nB;
3518 : 0 : zd /= (double)nB;
3519 : 0 : r /= (double)nB;
3520 : 0 : r0 = sqrt((double)(xd - at[iat].x) * (xd - at[iat].x) + (double)(yd - at[iat].y) * (yd - at[iat].y));
3521 : : }
3522 : : else
3523 : : {
3524 [ # # ]: 0 : if (at[iat_H].valence)
3525 : : {
3526 : 0 : r = dist3D(at + iat_H, at + (int)at[iat_H].neighbor[0]);
3527 : : }
3528 : : else
3529 : : {
3530 : 0 : r = 0.0;
3531 : : }
3532 : 0 : r0 = 0.0;
3533 : : }
3534 : :
3535 : 0 : ave_bond_len = GetMinDistDistribution(at, num_at, iat, iat_H,
3536 : : bInAllComponents, min_dist,
3537 : : NUM_SEGM);
3538 : :
3539 [ # # # # ]: 0 : if (r < MIN_BOND_LENGTH && ave_bond_len > MIN_BOND_LENGTH)
3540 : : {
3541 : 0 : r = ave_bond_len; /* ave_bond_len = 0.0 may mean that it is 0D structure */
3542 : : }
3543 : :
3544 [ # # ]: 0 : if (r > MIN_BOND_LENGTH)
3545 : : {
3546 : : /* process non-zero bond lengths */
3547 : : double f;
3548 [ # # ]: 0 : if (10.0 * r0 < r)
3549 : : {
3550 : 0 : xr = -r; /* arbitrary */
3551 : 0 : yr = 0.0;
3552 : 0 : zr = 0.0;
3553 : : }
3554 : : else
3555 : : {
3556 : : /*
3557 : : if ( r0 < MIN_BOND_LENGTH ) {
3558 : : r0 = 1.0;
3559 : : }
3560 : : */
3561 : 0 : xr = r * (at[iat].x - xd) / r0;
3562 : 0 : yr = r * (at[iat].y - yd) / r0; /* length = r */
3563 : 0 : zr = r * (at[iat].z - zd) / r0;
3564 : :
3565 : : /* -- test: opposire direction --
3566 : : xr = -r * ( at[iat].x - xd )/r0;
3567 : : yr = -r * ( at[iat].y - yd )/r0;
3568 : : zr = -r * ( at[iat].z - zd )/r0;
3569 : : */
3570 [ # # ]: 0 : if (xr * xr + yr * yr < 0.04 * r * r)
3571 : : {
3572 : 0 : xr = -r;
3573 : 0 : yr = 0.0;
3574 : : }
3575 : : }
3576 : :
3577 : 0 : r = sqrt(xr * xr + yr * yr);
3578 : 0 : f = atan2(yr, xr);
3579 : :
3580 [ # # ]: 0 : if (f < 0.0)
3581 : : {
3582 : 0 : f += two_pi;
3583 : : }
3584 : :
3585 : 0 : kk = (int)floor((f + h_step) / f_step) % NUM_SEGM;
3586 : : /* cast does not match function type by design */
3587 : :
3588 [ # # ]: 0 : if (min_dist[kk] < 1.5 * r)
3589 : : {
3590 : 0 : double dist = 1.5 * r;
3591 : 0 : int start = -1, len = 0, start_max = -1, len_max = 0;
3592 : :
3593 : 0 : again:
3594 : : /* look for longest kk interval with min_dist[kk] >= dist */
3595 [ # # ]: 0 : for (k = 0, start = 0, len = 0, len_max = 0; k < 2 * NUM_SEGM; k++)
3596 : : {
3597 : 0 : kk = k % NUM_SEGM;
3598 [ # # ]: 0 : if (min_dist[kk] >= dist)
3599 : : {
3600 [ # # ]: 0 : if (!len++)
3601 : : {
3602 : 0 : start = k;
3603 : : }
3604 : : }
3605 : : else
3606 : : {
3607 [ # # ]: 0 : if (len > len_max)
3608 : : {
3609 : 0 : len_max = len;
3610 : 0 : start_max = start;
3611 : : }
3612 : 0 : len = 0;
3613 : : }
3614 : : }
3615 [ # # ]: 0 : if (!len_max)
3616 : : {
3617 [ # # ]: 0 : if (dist > 0.1 * r)
3618 : : {
3619 : 0 : dist *= 0.75;
3620 : 0 : goto again;
3621 : : }
3622 : : else
3623 : : {
3624 : 0 : goto done; /* do it anyway */
3625 : : }
3626 : : }
3627 : : else
3628 : : {
3629 : : /* found a good sector */
3630 : 0 : f = f_step * ((double)start_max + ((double)len_max - 1.0) / 2.0); /* djb-rwth: cast operators added */
3631 : 0 : r0 = dist / 1.5;
3632 : 0 : xr = r0 * cos(f);
3633 : 0 : yr = r0 * sin(f);
3634 : 0 : zr = zr / r * r0;
3635 : : }
3636 : : }
3637 : : }
3638 : : else
3639 : : {
3640 : 0 : xr = yr = zr = 0;
3641 : : }
3642 : :
3643 : 0 : done:
3644 [ # # ]: 0 : if (at[iat_H].valence)
3645 : : {
3646 : : /* disconnect H */
3647 : 0 : next = at[iat_H].neighbor[0];
3648 [ # # ]: 0 : for (i = 0; i < at[next].valence; i++)
3649 : : {
3650 [ # # ]: 0 : if (at[next].neighbor[i] == iat_H)
3651 : : {
3652 : 0 : RemoveInpAtBond(at, next, i);
3653 : 0 : i = 0; /* success */
3654 : 0 : break;
3655 : : }
3656 : : }
3657 : : }
3658 : : else
3659 : : {
3660 : : /* isolated H+ cation */
3661 : 0 : next = iat_H;
3662 : 0 : i = 0;
3663 : 0 : at[iat_H].valence = 1;
3664 : 0 : at[iat_H].chem_bonds_valence = 1;
3665 : 0 : at[iat_H].bond_type[0] = BOND_TYPE_SINGLE;
3666 : : }
3667 : :
3668 [ # # ]: 0 : if (0 == i /*i < at[next].valence*/)
3669 : : {
3670 : : /* move charge */
3671 [ # # # # ]: 0 : if (at[next].charge > 0 && at[iat].charge < 0)
3672 : : {
3673 : 0 : at[next].charge--;
3674 : 0 : at[iat].charge++;
3675 : : }
3676 : :
3677 : : /* connect H to at[iat] */
3678 : 0 : val = at[iat].valence;
3679 : :
3680 : : #pragma warning (push)
3681 : : #pragma warning (disable: 6386)
3682 [ # # ]: 0 : if (val < MAXVAL)
3683 : : {
3684 : 0 : at[iat].neighbor[val] = iat_H;
3685 : 0 : at[iat].bond_type[val] = at[iat_H].bond_type[0];
3686 : 0 : at[iat].bond_stereo[val] = 0;
3687 : 0 : at[iat].chem_bonds_valence += at[iat_H].bond_type[0];
3688 : 0 : at[iat].valence = val + 1;
3689 : : };
3690 : : #pragma warning(pop)
3691 : :
3692 : 0 : at[iat_H].component = at[iat].component;
3693 : 0 : at[iat_H].neighbor[0] = iat;
3694 : 0 : at[iat_H].bond_stereo[0] = 0; /* possible loss of stereo info */
3695 : 0 : at[iat_H].x = at[iat].x + xr;
3696 : 0 : at[iat_H].y = at[iat].y + yr;
3697 : 0 : at[iat_H].z = at[iat].z + zr;
3698 : :
3699 : 0 : return 1; /* success */
3700 : : }
3701 : :
3702 : 0 : return 0; /* failed */
3703 : : }
3704 : :
3705 : : /****************************************************************************/
3706 : 69 : int add_DT_to_num_H(int num_atoms, inp_ATOM *at)
3707 : : /* assume num_1H, num_D and num_T are not included in num_H */
3708 : : {
3709 : : int i, j;
3710 [ + + ]: 688 : for (i = 0; i < num_atoms; i++)
3711 : : {
3712 [ + + ]: 2476 : for (j = 0; j < NUM_H_ISOTOPES; j++)
3713 : : {
3714 : 1857 : at[i].num_H += at[i].num_iso_H[j];
3715 : : }
3716 : : }
3717 : 69 : return 0;
3718 : : }
3719 : :
3720 : : /****************************************************************************
3721 : : **@nnuk
3722 : : * @param at input atom array
3723 : : * @param num_atoms number of atoms
3724 : : * @param metal_idx index of the metal atom
3725 : : * @return 1 all neighbors are H/D/T
3726 : : * @return 0 at least one non-hydrogen neighbor is present
3727 : : ****************************************************************************/
3728 : 1 : static int is_only_HDT_neighbors(const inp_ATOM* at, int num_atoms, int metal_idx)
3729 : : {
3730 : : int v;
3731 : :
3732 [ + - + - : 1 : if (!at || metal_idx < 0 || metal_idx >= num_atoms)
- + ]
3733 : : {
3734 : 0 : return 0;
3735 : : }
3736 : :
3737 [ + - ]: 2 : for (v = 0; v < at[metal_idx].valence; v++)
3738 : : {
3739 : 2 : int nb = at[metal_idx].neighbor[v];
3740 : :
3741 [ + - - + ]: 2 : if (nb < 0 || nb >= num_atoms)
3742 : : {
3743 : 0 : continue;
3744 : : }
3745 : :
3746 [ + + - + ]: 2 : if (!(at[nb].elname[0] == 'H' && at[nb].elname[1] == '\0'))
3747 : : {
3748 : 1 : return 0;
3749 : : }
3750 : : }
3751 : :
3752 : 0 : return 1;
3753 : : }
3754 : :
3755 : : /****************************************************************************
3756 : : Return value: new number of atoms > 0 or -1=out of RAM
3757 : : ****************************************************************************/
3758 : 69 : int remove_terminal_HDT(int num_atoms, inp_ATOM *at, int bFixTermHChrg)
3759 : : {
3760 : : AT_NUMB *new_ord;
3761 : : inp_ATOM *new_at;
3762 : : char *p;
3763 : : static const char szHDT[] = "HDT";
3764 : : static const int kMax = sizeof(szHDT); /* = 4 */
3765 : 69 : int ret = -1;
3766 : 69 : int num_hydrogens = 0, num_H = 0; /* number of terminal H, D, T */
3767 : : int i, j, k, n, m;
3768 : : int val;
3769 : : AT_RANK new_HydrogenAt_order[NUM_H_ISOTOPES + 1];
3770 : : AT_RANK new_OtherNeigh_order[MAXVAL];
3771 : : S_CHAR old_trans[MAX_NUM_STEREO_BONDS];
3772 : :
3773 : : int num_OtherNeigh, num_HydrogenAt;
3774 : :
3775 : 69 : new_ord = (AT_NUMB *)inchi_calloc(num_atoms, sizeof(new_ord[0])); /* changed malloc to calloc 9-11-2003 */
3776 : 69 : new_at = (inp_ATOM *)inchi_malloc(sizeof(new_at[0]) * num_atoms);
3777 [ + - - + ]: 69 : if (!new_ord || !new_at)
3778 : : {
3779 : 0 : goto exit_function;
3780 : : }
3781 : :
3782 : : /* move H. D, T to the end of the list of atoms */
3783 [ + + ]: 688 : for (i = 0; i < num_atoms; i++)
3784 : : {
3785 : 619 : at[i].component = i; /* temporarily save original numbering */
3786 : : /* get k = temp. hydrogen isotope/non-hydrogen atom type: */
3787 : : /* k=0:H, k=2:D, k=3:T, k=4=kMax: not a hydrogen */
3788 [ + + ]: 1126 : k = at[i].elname[1] ? kMax : (p = (char *)strchr(szHDT, at[i].elname[0])) ? (int)(p - szHDT)
3789 [ + + ]: 507 : : kMax;
3790 : : /* set hydrogen isotope atw differences */
3791 : : /* Notes: k-value of isotopic H is incremented to correct iso_atw_diff value later. */
3792 : : /* 1H isotope cannot be detected here. */
3793 [ + - - + ]: 619 : if (k == ATW_H || k == ATW_H + 1)
3794 : : {
3795 : : /* D or T, k = 1 or 2 */
3796 : 0 : at[i].elname[0] = 'H'; /* hydrogen isotope */
3797 : 0 : at[i].iso_atw_diff = ++k; /* increment k to make k = iso_atw_diff ( 2 for D, 3 for T ) */
3798 : : }
3799 [ + + + - : 619 : num_H += (k != kMax && at[i].valence == 1 && at[i].chem_bonds_valence == 1 && !NUMH(at, i));
+ - + - ]
3800 : : }
3801 : :
3802 : : /* special case: HD, HT, DT, HH: the only non-isotopic H or
3803 : : * the lightest isotopic H out of two is removed
3804 : : * to become implicit (make the heavier H the "central atom").
3805 : : * Note: This must be consistent with MOL_FMT_to_atom()
3806 : : * treatment of isotopic Hn aliases.
3807 : : */
3808 [ - + - - : 69 : if (2 == num_H && 2 == num_atoms && !NUMH(at, 0) && !NUMH(at, 1))
- - - - ]
3809 : : {
3810 : :
3811 [ # # ]: 0 : if (at[0].iso_atw_diff >= at[1].iso_atw_diff)
3812 : : {
3813 : 0 : new_ord[0] = 0;
3814 : 0 : new_ord[1] = 1;
3815 : : }
3816 : : else
3817 : : {
3818 : 0 : new_ord[0] = 1;
3819 : 0 : new_ord[1] = 0;
3820 : : }
3821 [ # # ]: 0 : if (at[new_ord[1]].charge)
3822 : : {
3823 : 0 : at[new_ord[0]].charge += at[new_ord[1]].charge;
3824 : 0 : at[new_ord[1]].charge = 0;
3825 : : }
3826 : 0 : new_at[new_ord[0]] = at[0];
3827 : 0 : new_at[new_ord[1]] = at[1];
3828 : 0 : num_hydrogens = 1;
3829 : : }
3830 : : else
3831 : : {
3832 : : /* general case except H-H */
3833 [ + + ]: 688 : for (i = 0; i < num_atoms; i++)
3834 : : {
3835 [ + + + + ]: 638 : k = (at[i].elname[1] || NUMH(at, i)) ? kMax : (at[i].elname[0] == 'H') ? at[i].iso_atw_diff
3836 [ + + ]: 19 : : kMax;
3837 : 619 : n = (int)at[i].neighbor[0];
3838 [ + + + - : 619 : if (k < kMax && at[i].valence == 1 && at[i].chem_bonds_valence == 1 &&
+ - + - ]
3839 : : /* the order of comparison is important */
3840 : 1 : ((n > i) /* at[n] has not been encountered yet*/ ||
3841 [ + - + - ]: 2 : (int)new_ord[n] < num_atoms - num_hydrogens) /* at[n] might have been encountered; it has not been moved */ &&
3842 [ - + ]: 2 : (!is_el_a_metal(at[n].el_number) || is_only_HDT_neighbors(at, num_atoms, n))/*@nnuk*/ )
3843 : : {
3844 : : /* found an explicit terminal hydrogen */
3845 : 0 : num_hydrogens++;
3846 [ # # # # : 0 : if (k == 0 && ATW_H <= at[i].iso_atw_diff && at[i].iso_atw_diff < ATW_H + NUM_H_ISOTOPES)
# # ]
3847 : : {
3848 : 0 : k = at[i].iso_atw_diff; /* H isotope has already been marked above or elsewhere */ /* djb-rwth: ignoring LLVM warning: variable used */
3849 : : }
3850 [ # # ]: 0 : if (at[i].charge)
3851 : : {
3852 : : /* transfer charge from the hydrogen */
3853 : 0 : at[n].charge += at[i].charge;
3854 : 0 : at[i].charge = 0;
3855 [ # # ]: 0 : if (bFixTermHChrg)
3856 : : {
3857 : : /* Fixed bug (July 6, 2008 IPl) :
3858 : : if terminal H was charged (not neutralized before call of remove_terminal_HDT)
3859 : : and had an ordering number > than that of heavy-atom neighbour, then
3860 : : charge on neighbour atom was not adjusted (though charge on H was removed). */
3861 [ # # ]: 0 : if (i > n)
3862 : : /* new_at[new_ord[n]] has been created and filled already */
3863 : 0 : new_at[new_ord[n]].charge = at[n].charge;
3864 : : }
3865 : : }
3866 : 0 : new_ord[i] = num_atoms - num_hydrogens; /* move hydrogens to the end of the list */
3867 : : }
3868 : : else
3869 : : {
3870 : : /* atom is not an explicit terminal hydrogen */
3871 : 619 : new_ord[i] = i - num_hydrogens; /* adjust non-hydrogens positions */
3872 : : }
3873 : :
3874 : : /* copy atom to the new position */
3875 : 619 : new_at[new_ord[i]] = at[i];
3876 : : } /* i */
3877 : : } /* general case except H-H */
3878 : :
3879 [ - + ]: 69 : if (num_hydrogens)
3880 : : {
3881 : 0 : int num_others = num_atoms - num_hydrogens; /* atoms which are not terminal H, D, T */
3882 [ # # ]: 0 : if (num_hydrogens > 1)
3883 : : {
3884 : : /* sort hydrogen isotopes in ascending order, */
3885 : : /* orig, numbers being the secondary sorting key */
3886 : 0 : qsort(new_at + num_others, num_hydrogens, sizeof(new_at[0]), cmp_iso_atw_diff_component_no);
3887 : : }
3888 : : /* save new numbering of hydrogen atoms using temporarily saved orig numbering */
3889 [ # # ]: 0 : for (i = num_others; i < num_atoms; i++)
3890 : : {
3891 : 0 : new_ord[(int)new_at[i].component] = i;
3892 : : }
3893 : :
3894 : : /* renumber neighbors according to new_ord[] and detach terminal hydrogens */
3895 [ # # ]: 0 : for (i = 0; i < num_others; i++)
3896 : : {
3897 : 0 : memset(new_HydrogenAt_order, 0, sizeof(new_HydrogenAt_order)); /* djb-rwth: memset_s C11/Annex K variant? */
3898 : 0 : memset(new_OtherNeigh_order, 0, sizeof(new_OtherNeigh_order)); /* djb-rwth: memset_s C11/Annex K variant? */
3899 : 0 : num_OtherNeigh = 0;
3900 : 0 : num_HydrogenAt = 0;
3901 : 0 : num_H = 0;
3902 : :
3903 [ # # # # ]: 0 : for (m = 0; m < MAX_NUM_STEREO_BONDS && new_at[i].sb_parity[m]; m++)
3904 : : {
3905 : 0 : old_trans[m] = 2 - (new_at[i].sn_ord[m] + new_at[i].sb_ord[m] + (new_at[i].sn_ord[m] > new_at[i].sb_ord[m])) % 2;
3906 : : }
3907 : :
3908 [ # # ]: 0 : for (k = val = 0; k < new_at[i].valence; k++) /* djb-rwth: removing redundant variables/code */
3909 : : {
3910 [ # # ]: 0 : if (num_others <= (n = new_ord[new_at[i].neighbor[k]]))
3911 : : {
3912 : : /* discovered neighbor = disconnected explicit hydrogen
3913 : : * i = new atom new_at[i] ordering number
3914 : : * n = new number of the explicit H
3915 : : * k = ordering number of the explicit H in new_at[i] adjacency list
3916 : : */
3917 [ # # # # ]: 0 : if (0 < new_at[n].iso_atw_diff && new_at[n].iso_atw_diff < ATW_H + NUM_H_ISOTOPES)
3918 : : {
3919 : : /* make explicit isotopic H implicit */
3920 : 0 : new_at[i].num_iso_H[new_at[n].iso_atw_diff - 1]++; /* isotopic H */
3921 : 0 : num_HydrogenAt += !new_HydrogenAt_order[new_at[n].iso_atw_diff];
3922 : 0 : new_HydrogenAt_order[new_at[n].iso_atw_diff] = k + 1;
3923 : : }
3924 : : else
3925 : : {
3926 : : /* make explicit non-isotopic H implicit */
3927 : 0 : new_at[i].num_H++; /* non-isotopic H */
3928 : 0 : num_HydrogenAt += !num_H;
3929 : 0 : num_H++;
3930 : 0 : new_HydrogenAt_order[0] = k + 1;
3931 : : }
3932 : : /* decrement chem. bonds valence because one bond is removed */
3933 [ # # ]: 0 : new_at[i].chem_bonds_valence = inchi_max(0, new_at[i].chem_bonds_valence - 1);
3934 : 0 : new_at[n].neighbor[0] = i; /* update removed hydrogen neighbor number */
3935 [ # # ]: 0 : if (new_at[i].sb_parity[0])
3936 : : {
3937 : : /* if the removed H is an SB neighbor then mark it as removed */
3938 [ # # # # ]: 0 : for (m = 0; m < MAX_NUM_STEREO_BONDS && new_at[i].sb_parity[m]; m++)
3939 : : {
3940 [ # # ]: 0 : if (k == (int)new_at[i].sn_ord[m])
3941 : : {
3942 : 0 : new_at[i].sn_ord[m] = -(new_at[n].iso_atw_diff + 1);
3943 : : /* means the SB neighbor has been removed; (-4)=H, (-3)=1H, (-2)=D, (-1)=T */
3944 : : }
3945 : : }
3946 : : }
3947 : : }
3948 : : else
3949 : : {
3950 : : /* discovered a regular (not an explicit H) neighbor */
3951 [ # # ]: 0 : if (new_at[i].sb_parity[0])
3952 : : {
3953 [ # # ]: 0 : if (num_OtherNeigh < MAX_NUM_STEREO_BONDS)
3954 : : {
3955 : 0 : new_OtherNeigh_order[num_OtherNeigh] = k + 1;
3956 : : }
3957 : 0 : num_OtherNeigh++; /* increment outside of if() to detect overflow */
3958 [ # # ]: 0 : if (val != k)
3959 : : {
3960 : : /* store new stereobond and sb-neighbor ordering numbers */
3961 [ # # # # ]: 0 : for (m = 0; m < MAX_NUM_STEREO_BONDS && new_at[i].sb_parity[m]; m++)
3962 : : {
3963 [ # # ]: 0 : if (k == (int)new_at[i].sb_ord[m])
3964 : 0 : new_at[i].sb_ord[m] = val;
3965 [ # # ]: 0 : else if (k == (int)new_at[i].sn_ord[m])
3966 : 0 : new_at[i].sn_ord[m] = val;
3967 : : }
3968 : : }
3969 : : }
3970 : 0 : new_at[i].neighbor[val] = new_ord[new_at[i].neighbor[k]];
3971 : 0 : new_at[i].bond_type[val] = new_at[i].bond_type[k];
3972 : 0 : new_at[i].bond_stereo[val] = new_at[i].bond_stereo[k];
3973 : 0 : val++;
3974 : : }
3975 : : }
3976 [ # # # # ]: 0 : if (new_at[i].valence > val && new_at[i].sb_parity[0])
3977 : : {
3978 [ # # # # ]: 0 : if (num_HydrogenAt == new_at[i].valence - val && num_HydrogenAt + num_OtherNeigh <= MAXVAL)
3979 : : {
3980 : : /* recalculate parity so that it would describe neighbor sequence H,1H,D,T,neigh[0],neigh[1]... */
3981 : 0 : memmove(new_OtherNeigh_order + num_HydrogenAt, new_OtherNeigh_order, num_OtherNeigh * sizeof(new_OtherNeigh_order[0]));
3982 [ # # ]: 0 : for (k = 0, j = 1; k <= NUM_H_ISOTOPES; k++)
3983 : : {
3984 [ # # # # : 0 : if (new_HydrogenAt_order[k] && (num_HydrogenAt - j < MAXVAL) && (num_HydrogenAt - j >= 0)) /* djb-rwth: fixing buffer overruns */
# # ]
3985 : : {
3986 : 0 : new_OtherNeigh_order[num_HydrogenAt - j] = new_HydrogenAt_order[k];
3987 [ # # # # ]: 0 : for (m = 0; m < MAX_NUM_STEREO_BONDS && new_at[i].sb_parity[m]; m++)
3988 : : {
3989 [ # # ]: 0 : if ((int)new_at[i].sn_ord[m] == -(k + 1))
3990 : : {
3991 : 0 : new_at[i].sn_ord[m] = -j;
3992 : : /* negative means explicit H isotope ord are
3993 : : (contiguously) in front of the adjacency list */
3994 : : }
3995 : : }
3996 : 0 : j++;
3997 : : }
3998 : : }
3999 : : /* at this point new_OtherNeigh_order[] contains
4000 : : incremented old ordering numbers in new order */
4001 : 0 : k = insertions_sort_AT_RANK(new_OtherNeigh_order, num_HydrogenAt + num_OtherNeigh); /* djb-rwth: ignoring LLVM warning: variable used to store function return value */
4002 : : /* djb-rwth: removing redundant code */
4003 : : /*if ( k ) {*/
4004 : : /*
4005 : : for ( m = 0; m < MAX_NUM_STEREO_BONDS && new_at[i].sb_parity[m]; m ++ ) {
4006 : : if ( PARITY_WELL_DEF(new_at[i].sb_parity[m]) ) {
4007 : : if ( old_trans[m] != 2 - (4 + new_at[i].sn_ord[m] + new_at[i].sb_ord[m] + (new_at[i].sn_ord[m] > new_at[i].sb_ord[m]))%2 ) {
4008 : : new_at[i].sb_parity[m] = 3 - new_at[i].sb_parity[m];
4009 : : }
4010 : : }
4011 : : }
4012 : : */
4013 : : /*}*/
4014 : : }
4015 : : }
4016 : 0 : new_at[i].valence = val;
4017 : : }
4018 : 0 : memcpy(at, new_at, sizeof(at[0]) * num_atoms);
4019 : 0 : ret = num_others;
4020 : : }
4021 : : else
4022 : : {
4023 : 69 : ret = num_atoms;
4024 : : }
4025 : :
4026 : 69 : exit_function:
4027 : :
4028 [ + - ]: 69 : if (new_ord)
4029 : : {
4030 [ + - ]: 69 : inchi_free(new_ord);
4031 : : }
4032 [ + - ]: 69 : if (new_at)
4033 : : {
4034 [ + - ]: 69 : inchi_free(new_at);
4035 : : }
4036 : :
4037 : 69 : return ret;
4038 : : }
4039 : :
4040 : : /*#endif*/ /* } DISCONNECT_SALTS */
4041 : :
4042 : : typedef enum tagIonAtomType
4043 : : {
4044 : : IAT_H = 0,
4045 : : IAT_C,
4046 : : IAT_N,
4047 : : IAT_P,
4048 : : IAT_O,
4049 : : IAT_S,
4050 : : IAT_Se,
4051 : : IAT_Te,
4052 : : IAT_F,
4053 : : IAT_Cl,
4054 : : IAT_Br,
4055 : : IAT_I,
4056 : : IAT_MAX = 12
4057 : : } ION_ATOM_TYPE;
4058 : :
4059 : : /****************************************************************************/
4060 : 619 : int get_iat_number(int el_number)
4061 : : {
4062 [ + + + - : 619 : switch (el_number)
+ - - - +
+ + - + ]
4063 : : {
4064 : 1 : case EL_NUMBER_H:
4065 : 1 : return IAT_H;
4066 : 416 : case EL_NUMBER_C:
4067 : 416 : return IAT_C;
4068 : 17 : case EL_NUMBER_N:
4069 : 17 : return IAT_N;
4070 : 0 : case EL_NUMBER_P:
4071 : 0 : return IAT_P;
4072 : 62 : case EL_NUMBER_O:
4073 : 62 : return IAT_O;
4074 : 0 : case EL_NUMBER_S:
4075 : 0 : return IAT_S;
4076 : 0 : case EL_NUMBER_SE:
4077 : 0 : return IAT_Se;
4078 : 0 : case EL_NUMBER_TE:
4079 : 0 : return IAT_Te;
4080 : 10 : case EL_NUMBER_F:
4081 : 10 : return IAT_F;
4082 : 89 : case EL_NUMBER_CL:
4083 : 89 : return IAT_Cl;
4084 : 17 : case EL_NUMBER_BR:
4085 : 17 : return IAT_Br;
4086 : 0 : case EL_NUMBER_I:
4087 : 0 : return IAT_I;
4088 : 7 : default:
4089 : 7 : return -1;
4090 : : }
4091 : : }
4092 : :
4093 : : /*****************************************************************************
4094 : : * (@nnuk : Nauman Ullah Khan)
4095 : : * Array only to be used for molecular inorganics. It is seperate from the ElData
4096 : : * array in util.c file. The need for duplicate array arrives as in molecular inorganics
4097 : : * we need a change in metal type. Some changes include an upgrade from lower metal
4098 : : * type to higher metal type (meaning : more valences of an atom can be used).
4099 : : * Some changes include a degradation from higher metal type to a lower metal type
4100 : : * where fewer number of valences for an atom are used. Due to these changes there
4101 : : * is an urge to have a duplicate array so that the current functionality does
4102 : : * not get affected.
4103 : : *
4104 : : * (Summary) : Type of the element has changed from METAL -> MolInOrg.
4105 : : ******************************************************************************/
4106 : : const MolecularInorganicsElData MolecularInorganicsArray[] =
4107 : : {
4108 : : /* avg norm El No -------- Valence(s) of an ion or neutral atom -------------*/
4109 : : /* mw mass exact mw type neg H -2 -1 0 +1 +2 */
4110 : : {"H", 1, 1, 1.007825035, 0, 21, 0, {{
4111 : : 0,
4112 : : },
4113 : : {
4114 : : 0,
4115 : : },
4116 : : {
4117 : : 1,
4118 : : },
4119 : : {
4120 : : 0,
4121 : : },
4122 : : {
4123 : : 0,
4124 : : }}},
4125 : : {"D", 2, 2, 2.014101778, 0, 21, 0, {{
4126 : : 0,
4127 : : },
4128 : : {
4129 : : 0,
4130 : : },
4131 : : {
4132 : : 1,
4133 : : },
4134 : : {
4135 : : 0,
4136 : : },
4137 : : {
4138 : : 0,
4139 : : }}},
4140 : : {"T", 3, 3, 3.016049268, 0, 21, 0, {{
4141 : : 0,
4142 : : },
4143 : : {
4144 : : 0,
4145 : : },
4146 : : {
4147 : : 1,
4148 : : },
4149 : : {
4150 : : 0,
4151 : : },
4152 : : {
4153 : : 0,
4154 : : }}},
4155 : : {"He", 4, 4, 4.002600000, 0, 0, 0, {{
4156 : : 0,
4157 : : },
4158 : : {
4159 : : 0,
4160 : : },
4161 : : {
4162 : : 0,
4163 : : },
4164 : : {
4165 : : 0,
4166 : : },
4167 : : {
4168 : : 0,
4169 : : }}},
4170 : : {"Li", 7, 7, 7.016000000, MolInOrg1, 10, 0, {{
4171 : : 0,
4172 : : },
4173 : : {
4174 : : 0,
4175 : : },
4176 : : {
4177 : : 1,
4178 : : },
4179 : : {
4180 : : 0,
4181 : : },
4182 : : {
4183 : : 0,
4184 : : }}},
4185 : : {"Be", 9, 9, 9.012180000, MolInOrg1, 15, 0, {{
4186 : : 0,
4187 : : },
4188 : : {
4189 : : 0,
4190 : : },
4191 : : {
4192 : : 2,
4193 : : },
4194 : : {
4195 : : 1,
4196 : : },
4197 : : {
4198 : : 0,
4199 : : }}},
4200 : : {"B", 11, 11, 11.009300000, 0, 20, 0, {{
4201 : : 3,
4202 : : },
4203 : : {
4204 : : 4,
4205 : : },
4206 : : {
4207 : : 3,
4208 : : },
4209 : : {
4210 : : 2,
4211 : : },
4212 : : {
4213 : : 1,
4214 : : }}},
4215 : : {"C", 12, 12, 12.000000000, 0, 25, 0, {{
4216 : : 2,
4217 : : },
4218 : : {
4219 : : 3,
4220 : : },
4221 : : {
4222 : : 4,
4223 : : },
4224 : : {
4225 : : 3,
4226 : : },
4227 : : {
4228 : : 2,
4229 : : }}},
4230 : : {"N", 14, 14, 14.003074000, 0, 30, 0, {{
4231 : : 1,
4232 : : },
4233 : : {
4234 : : 2,
4235 : : },
4236 : : {3, 5},
4237 : : {
4238 : : 4,
4239 : : },
4240 : : {
4241 : : 3,
4242 : : }}},
4243 : : {"O", 16, 16, 15.994914630, 0, 35, 0, {{
4244 : : 0,
4245 : : },
4246 : : {
4247 : : 1,
4248 : : },
4249 : : {
4250 : : 2,
4251 : : },
4252 : : {
4253 : : 3,
4254 : : 5,
4255 : : },
4256 : : {
4257 : : 4,
4258 : : }}},
4259 : : {"F", 19, 19, 18.998403220, 0, 40, 0, {{
4260 : : 0,
4261 : : },
4262 : : {
4263 : : 0,
4264 : : },
4265 : : {
4266 : : 1,
4267 : : },
4268 : : {
4269 : : 2,
4270 : : },
4271 : : {3, 5}}},
4272 : : {"Ne", 20, 20, 19.992440000, 0, 0, 0, {{
4273 : : 0,
4274 : : },
4275 : : {
4276 : : 0,
4277 : : },
4278 : : {
4279 : : 0,
4280 : : },
4281 : : {
4282 : : 0,
4283 : : },
4284 : : {
4285 : : 0,
4286 : : }}},
4287 : : {"Na", 23, 23, 22.989770000, MolInOrg1, 9, 0, {{
4288 : : 0,
4289 : : },
4290 : : {
4291 : : 0,
4292 : : },
4293 : : {
4294 : : 1,
4295 : : },
4296 : : {
4297 : : 0,
4298 : : },
4299 : : {
4300 : : 0,
4301 : : }}},
4302 : : {"Mg", 24, 24, 23.985000000, MolInOrg1, 12, 0, {{
4303 : : 0,
4304 : : },
4305 : : {
4306 : : 0,
4307 : : },
4308 : : {
4309 : : 2,
4310 : : },
4311 : : {
4312 : : 1,
4313 : : },
4314 : : {
4315 : : 0,
4316 : : }}},
4317 : : {"Al", 27, 27, 26.981540000, MolInOrg1, 15, 0, {{
4318 : : 3,
4319 : : 5,
4320 : : },
4321 : : {
4322 : : 4,
4323 : : },
4324 : : {
4325 : : 3,
4326 : : },
4327 : : {
4328 : : 2,
4329 : : },
4330 : : {
4331 : : 1,
4332 : : }}},
4333 : : {"Si", 28, 28, 27.976927100, 0, 18, 0, {{
4334 : : 2,
4335 : : },
4336 : : {3, 5},
4337 : : {
4338 : : 4,
4339 : : },
4340 : : {
4341 : : 3,
4342 : : },
4343 : : {
4344 : : 2,
4345 : : }}},
4346 : : {"P", 31, 31, 30.973762000, 0, 21, 0, {{
4347 : : 1,
4348 : : 3,
4349 : : 5,
4350 : : 7,
4351 : : },
4352 : : {
4353 : : 2,
4354 : : 4,
4355 : : 6,
4356 : : },
4357 : : {
4358 : : 3,
4359 : : 5,
4360 : : },
4361 : : {
4362 : : 4,
4363 : : },
4364 : : {
4365 : : 3,
4366 : : }}},
4367 : : {"S", 32, 32, 31.972070700, 0, 25, 0, {{
4368 : : 0,
4369 : : },
4370 : : {
4371 : : 1,
4372 : : 3,
4373 : : 5,
4374 : : 7,
4375 : : },
4376 : : {2, 4, 6},
4377 : : {
4378 : : 3,
4379 : : 5,
4380 : : },
4381 : : {
4382 : : 4,
4383 : : }}},
4384 : : {"Cl", 35, 35, 34.968852730, 0, 30, 0, {{
4385 : : 0,
4386 : : },
4387 : : {
4388 : : 0,
4389 : : },
4390 : : {1, 3, 5, 7},
4391 : : {2, 4, 6},
4392 : : {
4393 : : 3,
4394 : : 5,
4395 : : }}},
4396 : : {"Ar", 40, 40, 39.962400000, 0, 0, 0, {{
4397 : : 0,
4398 : : },
4399 : : {
4400 : : 0,
4401 : : },
4402 : : {
4403 : : 0,
4404 : : },
4405 : : {
4406 : : 0,
4407 : : },
4408 : : {
4409 : : 0,
4410 : : }}},
4411 : : {"K", 39, 39, 38.963700000, MolInOrg1, 8, 0, {{
4412 : : 0,
4413 : : },
4414 : : {
4415 : : 0,
4416 : : },
4417 : : {
4418 : : 1,
4419 : : },
4420 : : {
4421 : : 0,
4422 : : },
4423 : : {
4424 : : 0,
4425 : : }}},
4426 : : {"Ca", 40, 40, 39.962600000, MolInOrg1, 10, 0, {{
4427 : : 0,
4428 : : },
4429 : : {
4430 : : 0,
4431 : : },
4432 : : {
4433 : : 2,
4434 : : },
4435 : : {
4436 : : 1,
4437 : : },
4438 : : {
4439 : : 0,
4440 : : }}},
4441 : : {"Sc", 45, 45, 44.955910000, MolInOrg1, 13, 1, {{
4442 : : 0,
4443 : : },
4444 : : {
4445 : : 0,
4446 : : },
4447 : : {
4448 : : 3,
4449 : : },
4450 : : {
4451 : : 0,
4452 : : },
4453 : : {
4454 : : 0,
4455 : : }}},
4456 : : {"Ti", 48, 48, 47.947950000, MolInOrg2, 15, 1, {{
4457 : : 0,
4458 : : },
4459 : : {
4460 : : 0,
4461 : : },
4462 : : {3, 4},
4463 : : {
4464 : : 0,
4465 : : },
4466 : : {
4467 : : 0,
4468 : : }}},
4469 : : {"V", 51, 51, 50.943960000, MolInOrg4, 16, 1, {{
4470 : : 0,
4471 : : },
4472 : : {
4473 : : 0,
4474 : : },
4475 : : {
4476 : : 2,
4477 : : 3,
4478 : : 4,
4479 : : 5,
4480 : : },
4481 : : {
4482 : : 0,
4483 : : },
4484 : : {
4485 : : 0,
4486 : : }}},
4487 : : {"Cr", 52, 52, 51.940500000, MolInOrg2, 16, 1, {{
4488 : : 0,
4489 : : },
4490 : : {
4491 : : 0,
4492 : : },
4493 : : {
4494 : : 2,
4495 : : 3,
4496 : : 6,
4497 : : },
4498 : : {
4499 : : 0,
4500 : : },
4501 : : {
4502 : : 0,
4503 : : }}},
4504 : : {"Mn", 55, 55, 54.938050000, MolInOrg1, 15, 1, {{
4505 : : 0,
4506 : : },
4507 : : {
4508 : : 0,
4509 : : },
4510 : : {
4511 : : 2,
4512 : : 3,
4513 : : 4,
4514 : : 6,
4515 : : 7,
4516 : : },
4517 : : {
4518 : : 0,
4519 : : },
4520 : : {
4521 : : 0,
4522 : : }}},
4523 : : {"Fe", 56, 56, 55.934900000, MolInOrg2, 18, 1, {{
4524 : : 0,
4525 : : },
4526 : : {
4527 : : 0,
4528 : : },
4529 : : {
4530 : : 2,
4531 : : 3,
4532 : : 4,
4533 : : 6,
4534 : : },
4535 : : {
4536 : : 0,
4537 : : },
4538 : : {
4539 : : 0,
4540 : : }}},
4541 : : {"Co", 59, 59, 58.933200000, MolInOrg2, 18, 1, {{
4542 : : 0,
4543 : : },
4544 : : {
4545 : : 0,
4546 : : },
4547 : : {
4548 : : 2,
4549 : : 3,
4550 : : },
4551 : : {
4552 : : 0,
4553 : : },
4554 : : {
4555 : : 0,
4556 : : }}},
4557 : : {"Ni", 59, 58, 57.935300000, MolInOrg1, 18, 1, {{
4558 : : 0,
4559 : : },
4560 : : {
4561 : : 0,
4562 : : },
4563 : : {
4564 : : 2,
4565 : : 3,
4566 : : },
4567 : : {
4568 : : 0,
4569 : : },
4570 : : {
4571 : : 0,
4572 : : }}},
4573 : : {"Cu", 64, 63, 62.929600000, MolInOrg2, 19, 1, {{
4574 : : 0,
4575 : : },
4576 : : {
4577 : : 0,
4578 : : },
4579 : : {
4580 : : 1,
4581 : : 2,
4582 : : },
4583 : : {
4584 : : 0,
4585 : : },
4586 : : {
4587 : : 0,
4588 : : }}},
4589 : : {"Zn", 65, 64, 63.929147000, MolInOrg1, 16, 1, {{
4590 : : 0,
4591 : : },
4592 : : {
4593 : : 0,
4594 : : },
4595 : : {
4596 : : 2,
4597 : : },
4598 : : {
4599 : : 0,
4600 : : },
4601 : : {
4602 : : 0,
4603 : : }}},
4604 : : {"Ga", 70, 69, 68.925600000, MolInOrg1, 18, 0, {{
4605 : : 3,
4606 : : 5,
4607 : : },
4608 : : {
4609 : : 4,
4610 : : },
4611 : : {
4612 : : 3,
4613 : : },
4614 : : {
4615 : : 0,
4616 : : },
4617 : : {
4618 : : 1,
4619 : : }}},
4620 : : {"Ge", 73, 74, 73.921177400, 0, 18, 0, {{
4621 : : 2,
4622 : : 4,
4623 : : 6,
4624 : : },
4625 : : {
4626 : : 3,
4627 : : 5,
4628 : : },
4629 : : {
4630 : : 4,
4631 : : },
4632 : : {
4633 : : 3,
4634 : : },
4635 : : {
4636 : : 0,
4637 : : }}},
4638 : : {"As", 75, 75, 74.921594200, 0, 20, 0, {{
4639 : : 1,
4640 : : 3,
4641 : : 5,
4642 : : 7,
4643 : : },
4644 : : {
4645 : : 2,
4646 : : 4,
4647 : : 6,
4648 : : },
4649 : : {
4650 : : 3,
4651 : : 5,
4652 : : },
4653 : : {
4654 : : 4,
4655 : : },
4656 : : {
4657 : : 3,
4658 : : }}},
4659 : : {"Se", 79, 80, 79.916519600, 0, 24, 0, {{
4660 : : 0,
4661 : : },
4662 : : {
4663 : : 1,
4664 : : 3,
4665 : : 5,
4666 : : 7,
4667 : : },
4668 : : {
4669 : : 2,
4670 : : 4,
4671 : : 6,
4672 : : },
4673 : : {
4674 : : 3,
4675 : : 5,
4676 : : },
4677 : : {
4678 : : 4,
4679 : : }}},
4680 : : {"Br", 80, 79, 78.918336100, 0, 28, 0, {{
4681 : : 0,
4682 : : },
4683 : : {
4684 : : 0,
4685 : : },
4686 : : {
4687 : : 1,
4688 : : 3,
4689 : : 5,
4690 : : 7,
4691 : : },
4692 : : {
4693 : : 2,
4694 : : 4,
4695 : : 6,
4696 : : },
4697 : : {
4698 : : 3,
4699 : : 5,
4700 : : }}},
4701 : : {"Kr", 84, 84, 83.911500000, 0, 0, 0, {{
4702 : : 0,
4703 : : },
4704 : : {
4705 : : 0,
4706 : : },
4707 : : {
4708 : : 0,
4709 : : },
4710 : : {
4711 : : 0,
4712 : : },
4713 : : {
4714 : : 0,
4715 : : }}},
4716 : : {"Rb", 85, 85, 84.911800000, MolInOrg1, 8, 0, {{
4717 : : 0,
4718 : : },
4719 : : {
4720 : : 0,
4721 : : },
4722 : : {
4723 : : 1,
4724 : : },
4725 : : {
4726 : : 0,
4727 : : },
4728 : : {
4729 : : 0,
4730 : : }}},
4731 : : {"Sr", 88, 88, 87.905600000, MolInOrg1, 10, 0, {{
4732 : : 0,
4733 : : },
4734 : : {
4735 : : 0,
4736 : : },
4737 : : {
4738 : : 2,
4739 : : },
4740 : : {
4741 : : 1,
4742 : : },
4743 : : {
4744 : : 0,
4745 : : }}},
4746 : : {"Y", 89, 89, 88.905860000, MolInOrg1, 12, 1, {{
4747 : : 0,
4748 : : },
4749 : : {
4750 : : 0,
4751 : : },
4752 : : {
4753 : : 3,
4754 : : },
4755 : : {
4756 : : 0,
4757 : : },
4758 : : {
4759 : : 0,
4760 : : }}},
4761 : : {"Zr", 91, 90, 89.904700000, MolInOrg1, 14, 1, {{
4762 : : 0,
4763 : : },
4764 : : {
4765 : : 0,
4766 : : },
4767 : : {
4768 : : 4,
4769 : : },
4770 : : {
4771 : : 0,
4772 : : },
4773 : : {
4774 : : 0,
4775 : : }}},
4776 : : {"Nb", 93, 93, 92.906400000, MolInOrg2, 16, 1, {{
4777 : : 0,
4778 : : },
4779 : : {
4780 : : 0,
4781 : : },
4782 : : {
4783 : : 3,
4784 : : 5,
4785 : : },
4786 : : {
4787 : : 0,
4788 : : },
4789 : : {
4790 : : 0,
4791 : : }}},
4792 : : {"Mo", 96, 98, 97.905400000, MolInOrg4, 18, 1, {{
4793 : : 0,
4794 : : },
4795 : : {
4796 : : 0,
4797 : : },
4798 : : {
4799 : : 3,
4800 : : 4,
4801 : : 5,
4802 : : 6,
4803 : : },
4804 : : {
4805 : : 0,
4806 : : },
4807 : : {
4808 : : 0,
4809 : : }}},
4810 : : {"Tc", 98, 98, 97.907200000, MolInOrg1, 19, 1, {{
4811 : : 0,
4812 : : },
4813 : : {
4814 : : 0,
4815 : : },
4816 : : {
4817 : : 7,
4818 : : },
4819 : : {
4820 : : 0,
4821 : : },
4822 : : {
4823 : : 0,
4824 : : }}},
4825 : : {"Ru", 101, 102, 101.904300000, MolInOrg2, 22, 1, {{
4826 : : 0,
4827 : : },
4828 : : {
4829 : : 0,
4830 : : },
4831 : : {
4832 : : 2,
4833 : : 3,
4834 : : 4,
4835 : : 6,
4836 : : },
4837 : : {
4838 : : 0,
4839 : : },
4840 : : {
4841 : : 0,
4842 : : }}},
4843 : : {"Rh", 103, 103, 102.905500000, MolInOrg2, 22, 1, {{
4844 : : 0,
4845 : : },
4846 : : {
4847 : : 0,
4848 : : },
4849 : : {
4850 : : 2,
4851 : : 3,
4852 : : 4,
4853 : : },
4854 : : {
4855 : : 0,
4856 : : },
4857 : : {
4858 : : 0,
4859 : : }}},
4860 : : {"Pd", 106, 106, 105.903500000, MolInOrg1, 22, 1, {{
4861 : : 0,
4862 : : },
4863 : : {
4864 : : 0,
4865 : : },
4866 : : {
4867 : : 2,
4868 : : 4,
4869 : : },
4870 : : {
4871 : : 0,
4872 : : },
4873 : : {
4874 : : 0,
4875 : : }}},
4876 : : {"Ag", 108, 107, 106.905100000, MolInOrg1, 19, 1, {{
4877 : : 0,
4878 : : },
4879 : : {
4880 : : 0,
4881 : : },
4882 : : {
4883 : : 1,
4884 : : },
4885 : : {
4886 : : 0,
4887 : : },
4888 : : {
4889 : : 0,
4890 : : }}},
4891 : : {"Cd", 112, 114, 113.903400000, MolInOrg1, 17, 1, {{
4892 : : 0,
4893 : : },
4894 : : {
4895 : : 0,
4896 : : },
4897 : : {
4898 : : 2,
4899 : : },
4900 : : {
4901 : : 0,
4902 : : },
4903 : : {
4904 : : 0,
4905 : : }}},
4906 : : {"In", 115, 115, 114.903900000, MolInOrg1, 17, 0, {{
4907 : : 3,
4908 : : 5,
4909 : : },
4910 : : {
4911 : : 2,
4912 : : 4,
4913 : : },
4914 : : {
4915 : : 3,
4916 : : },
4917 : : {
4918 : : 0,
4919 : : },
4920 : : {
4921 : : 1,
4922 : : }}},
4923 : : {"Sn", 119, 120, 119.902200000, MolInOrg2, 18, 0, {{
4924 : : 2,
4925 : : 4,
4926 : : 6,
4927 : : },
4928 : : {3, 5},
4929 : : {
4930 : : 2,
4931 : : 4,
4932 : : },
4933 : : {
4934 : : 3,
4935 : : },
4936 : : {
4937 : : 0,
4938 : : }}},
4939 : : {"Sb", 122, 121, 120.903800000, MolInOrg2, 19, 0, {{
4940 : : 1,
4941 : : 3,
4942 : : 5,
4943 : : 7,
4944 : : },
4945 : : {
4946 : : 2,
4947 : : 4,
4948 : : 6,
4949 : : },
4950 : : {
4951 : : 3,
4952 : : 5,
4953 : : },
4954 : : {
4955 : : 2,
4956 : : 4,
4957 : : },
4958 : : {
4959 : : 3,
4960 : : }}},
4961 : : {"Te", 128, 130, 129.906200000, 0, 21, 0, {{
4962 : : 0,
4963 : : },
4964 : : {
4965 : : 1,
4966 : : 3,
4967 : : 5,
4968 : : 7,
4969 : : },
4970 : : {
4971 : : 2,
4972 : : 4,
4973 : : 6,
4974 : : },
4975 : : {
4976 : : 3,
4977 : : 5,
4978 : : },
4979 : : {
4980 : : 2,
4981 : : 4,
4982 : : }}},
4983 : : {"I", 127, 127, 126.904500000, 0, 25, 0, {{
4984 : : 0,
4985 : : },
4986 : : {
4987 : : 0,
4988 : : },
4989 : : {
4990 : : 1,
4991 : : 3,
4992 : : 5,
4993 : : 7,
4994 : : },
4995 : : {2, 4, 6},
4996 : : {
4997 : : 3,
4998 : : 5,
4999 : : }}},
5000 : : {"Xe", 131, 132, 131.904100000, 0, 0, 0, {{
5001 : : 0,
5002 : : },
5003 : : {
5004 : : 0,
5005 : : },
5006 : : {
5007 : : 0,
5008 : : },
5009 : : {
5010 : : 0,
5011 : : },
5012 : : {
5013 : : 0,
5014 : : }}},
5015 : : {"Cs", 133, 133, 132.905430000, MolInOrg1, 7, 0, {{
5016 : : 0,
5017 : : },
5018 : : {
5019 : : 0,
5020 : : },
5021 : : {
5022 : : 1,
5023 : : },
5024 : : {
5025 : : 0,
5026 : : },
5027 : : {
5028 : : 0,
5029 : : }}},
5030 : : {"Ba", 137, 138, 137.905200000, MolInOrg1, 9, 0, {{
5031 : : 0,
5032 : : },
5033 : : {
5034 : : 0,
5035 : : },
5036 : : {
5037 : : 2,
5038 : : },
5039 : : {
5040 : : 1,
5041 : : },
5042 : : {
5043 : : 0,
5044 : : }}},
5045 : : {"La", 139, 139, 138.906360000, MolInOrg1, 11, 1, {{
5046 : : 0,
5047 : : },
5048 : : {
5049 : : 0,
5050 : : },
5051 : : {
5052 : : 3,
5053 : : },
5054 : : {
5055 : : 0,
5056 : : },
5057 : : {
5058 : : 0,
5059 : : }}},
5060 : : {"Ce", 140, 140, 139.905400000, MolInOrg1, 0, 1, {{
5061 : : 0,
5062 : : },
5063 : : {
5064 : : 0,
5065 : : },
5066 : : {
5067 : : 3,
5068 : : 4,
5069 : : },
5070 : : {
5071 : : 0,
5072 : : },
5073 : : {
5074 : : 0,
5075 : : }}},
5076 : : {"Pr", 141, 141, 140.907660000, MolInOrg1, 0, 1, {{
5077 : : 0,
5078 : : },
5079 : : {
5080 : : 0,
5081 : : },
5082 : : {
5083 : : 3,
5084 : : 4,
5085 : : },
5086 : : {
5087 : : 0,
5088 : : },
5089 : : {
5090 : : 0,
5091 : : }}},
5092 : : {"Nd", 144, 142, 141.907719000, MolInOrg1, 0, 1, {{
5093 : : 0,
5094 : : },
5095 : : {
5096 : : 0,
5097 : : },
5098 : : {
5099 : : 3,
5100 : : },
5101 : : {
5102 : : 0,
5103 : : },
5104 : : {
5105 : : 0,
5106 : : }}},
5107 : : {"Pm", 145, 145, 144.912800000, MolInOrg1, 0, 1, {{
5108 : : 0,
5109 : : },
5110 : : {
5111 : : 0,
5112 : : },
5113 : : {
5114 : : 3,
5115 : : },
5116 : : {
5117 : : 0,
5118 : : },
5119 : : {
5120 : : 0,
5121 : : }}},
5122 : : {"Sm", 150, 152, 151.919700000, MolInOrg2, 0, 1, {{
5123 : : 0,
5124 : : },
5125 : : {
5126 : : 0,
5127 : : },
5128 : : {
5129 : : 2,
5130 : : 3,
5131 : : },
5132 : : {
5133 : : 0,
5134 : : },
5135 : : {
5136 : : 0,
5137 : : }}},
5138 : : {"Eu", 152, 153, 152.921200000, MolInOrg2, 0, 1, {{
5139 : : 0,
5140 : : },
5141 : : {
5142 : : 0,
5143 : : },
5144 : : {
5145 : : 2,
5146 : : 3,
5147 : : },
5148 : : {
5149 : : 0,
5150 : : },
5151 : : {
5152 : : 0,
5153 : : }}},
5154 : : {"Gd", 157, 158, 157.924099000, MolInOrg1, 0, 1, {{
5155 : : 0,
5156 : : },
5157 : : {
5158 : : 0,
5159 : : },
5160 : : {
5161 : : 3,
5162 : : },
5163 : : {
5164 : : 0,
5165 : : },
5166 : : {
5167 : : 0,
5168 : : }}},
5169 : : {"Tb", 159, 159, 158.925350000, MolInOrg2, 0, 1, {{
5170 : : 0,
5171 : : },
5172 : : {
5173 : : 0,
5174 : : },
5175 : : {
5176 : : 3,
5177 : : 4,
5178 : : },
5179 : : {
5180 : : 0,
5181 : : },
5182 : : {
5183 : : 0,
5184 : : }}},
5185 : : {"Dy", 163, 164, 163.929200000, MolInOrg1, 0, 1, {{
5186 : : 0,
5187 : : },
5188 : : {
5189 : : 0,
5190 : : },
5191 : : {
5192 : : 3,
5193 : : },
5194 : : {
5195 : : 0,
5196 : : },
5197 : : {
5198 : : 0,
5199 : : }}}, /* mw rounding uncertain */
5200 : : {"Ho", 165, 165, 164.930300000, MolInOrg1, 0, 1, {{
5201 : : 0,
5202 : : },
5203 : : {
5204 : : 0,
5205 : : },
5206 : : {
5207 : : 3,
5208 : : },
5209 : : {
5210 : : 0,
5211 : : },
5212 : : {
5213 : : 0,
5214 : : }}},
5215 : : {"Er", 167, 166, 165.930300000, MolInOrg1, 0, 1, {{
5216 : : 0,
5217 : : },
5218 : : {
5219 : : 0,
5220 : : },
5221 : : {
5222 : : 3,
5223 : : },
5224 : : {
5225 : : 0,
5226 : : },
5227 : : {
5228 : : 0,
5229 : : }}},
5230 : : {"Tm", 169, 169, 168.934230000, MolInOrg2, 0, 1, {{
5231 : : 0,
5232 : : },
5233 : : {
5234 : : 0,
5235 : : },
5236 : : {
5237 : : 2,
5238 : : 3,
5239 : : },
5240 : : {
5241 : : 0,
5242 : : },
5243 : : {
5244 : : 0,
5245 : : }}},
5246 : : {"Yb", 173, 174, 173.938900000, MolInOrg2, 0, 1, {{
5247 : : 0,
5248 : : },
5249 : : {
5250 : : 0,
5251 : : },
5252 : : {
5253 : : 2,
5254 : : 3,
5255 : : },
5256 : : {
5257 : : 0,
5258 : : },
5259 : : {
5260 : : 0,
5261 : : }}},
5262 : : {"Lu", 175, 175, 174.940800000, MolInOrg1, 0, 1, {{
5263 : : 0,
5264 : : },
5265 : : {
5266 : : 0,
5267 : : },
5268 : : {
5269 : : 3,
5270 : : },
5271 : : {
5272 : : 0,
5273 : : },
5274 : : {
5275 : : 0,
5276 : : }}},
5277 : : {"Hf", 178, 180, 179.946600000, MolInOrg1, 13, 1, {{
5278 : : 0,
5279 : : },
5280 : : {
5281 : : 0,
5282 : : },
5283 : : {
5284 : : 4,
5285 : : },
5286 : : {
5287 : : 0,
5288 : : },
5289 : : {
5290 : : 0,
5291 : : }}},
5292 : : {"Ta", 181, 181, 180.948010000, MolInOrg1, 15, 1, {{
5293 : : 0,
5294 : : },
5295 : : {
5296 : : 0,
5297 : : },
5298 : : {
5299 : : 5,
5300 : : },
5301 : : {
5302 : : 0,
5303 : : },
5304 : : {
5305 : : 0,
5306 : : }}},
5307 : : {"W", 184, 184, 183.951000000, MolInOrg4, 17, 1, {{
5308 : : 0,
5309 : : },
5310 : : {
5311 : : 0,
5312 : : },
5313 : : {
5314 : : 3,
5315 : : 4,
5316 : : 5,
5317 : : 6,
5318 : : },
5319 : : {
5320 : : 0,
5321 : : },
5322 : : {
5323 : : 0,
5324 : : }}},
5325 : : {"Re", 186, 187, 186.955800000, MolInOrg4, 19, 1, {{
5326 : : 0,
5327 : : },
5328 : : {
5329 : : 0,
5330 : : },
5331 : : {
5332 : : 2,
5333 : : 4,
5334 : : 6,
5335 : : 7,
5336 : : },
5337 : : {
5338 : : 0,
5339 : : },
5340 : : {
5341 : : 0,
5342 : : }}},
5343 : : {"Os", 190, 192, 191.961500000, MolInOrg3, 22, 1, {{
5344 : : 0,
5345 : : },
5346 : : {
5347 : : 0,
5348 : : },
5349 : : {
5350 : : 2,
5351 : : 3,
5352 : : 4,
5353 : : 6,
5354 : : },
5355 : : {
5356 : : 0,
5357 : : },
5358 : : {
5359 : : 0,
5360 : : }}},
5361 : : {"Ir", 192, 193, 192.962900000, MolInOrg2, 22, 1, {{
5362 : : 0,
5363 : : },
5364 : : {
5365 : : 0,
5366 : : },
5367 : : {
5368 : : 2,
5369 : : 3,
5370 : : 4,
5371 : : 6,
5372 : : },
5373 : : {
5374 : : 0,
5375 : : },
5376 : : {
5377 : : 0,
5378 : : }}},
5379 : : {"Pt", 195, 195, 194.964800000, MolInOrg1, 22, 1, {{
5380 : : 0,
5381 : : },
5382 : : {
5383 : : 0,
5384 : : },
5385 : : {
5386 : : 2,
5387 : : 4,
5388 : : },
5389 : : {
5390 : : 0,
5391 : : },
5392 : : {
5393 : : 0,
5394 : : }}},
5395 : : {"Au", 197, 197, 196.966560000, MolInOrg2, 24, 1, {{
5396 : : 0,
5397 : : },
5398 : : {
5399 : : 0,
5400 : : },
5401 : : {
5402 : : 1,
5403 : : 3,
5404 : : },
5405 : : {
5406 : : 0,
5407 : : },
5408 : : {
5409 : : 0,
5410 : : }}},
5411 : : {"Hg", 201, 202, 201.970617000, MolInOrg2, 19, 1, {{
5412 : : 0,
5413 : : },
5414 : : {
5415 : : 0,
5416 : : },
5417 : : {
5418 : : 1,
5419 : : 2,
5420 : : },
5421 : : {
5422 : : 0,
5423 : : },
5424 : : {
5425 : : 0,
5426 : : }}},
5427 : : {"Tl", 204, 205, 204.974400000, MolInOrg1, 18, 0, {{
5428 : : 3,
5429 : : 5,
5430 : : },
5431 : : {
5432 : : 2,
5433 : : 4,
5434 : : },
5435 : : {
5436 : : 1,
5437 : : 3,
5438 : : },
5439 : : {
5440 : : 0,
5441 : : },
5442 : : {
5443 : : 0,
5444 : : }}},
5445 : : {"Pb", 207, 208, 207.976627000, MolInOrg1, 18, 0, {{
5446 : : 2,
5447 : : 4,
5448 : : 6,
5449 : : },
5450 : : {3, 5},
5451 : : {
5452 : : 2,
5453 : : 4,
5454 : : },
5455 : : {
5456 : : 3,
5457 : : },
5458 : : {
5459 : : 0,
5460 : : }}},
5461 : : {"Bi", 209, 209, 208.980390000, MolInOrg1, 19, 0, {{
5462 : : 1,
5463 : : 3,
5464 : : 5,
5465 : : 7,
5466 : : },
5467 : : {
5468 : : 2,
5469 : : 4,
5470 : : 6,
5471 : : },
5472 : : {
5473 : : 3,
5474 : : 5,
5475 : : },
5476 : : {
5477 : : 2,
5478 : : 4,
5479 : : },
5480 : : {
5481 : : 3,
5482 : : }}},
5483 : : {"Po", 209, 209, 208.982400000, MolInOrg2, 20, 0, {{
5484 : : 0,
5485 : : },
5486 : : {
5487 : : 1,
5488 : : 3,
5489 : : 5,
5490 : : 7,
5491 : : },
5492 : : {
5493 : : 2,
5494 : : 4,
5495 : : 6,
5496 : : },
5497 : : {
5498 : : 3,
5499 : : 5,
5500 : : },
5501 : : {
5502 : : 2,
5503 : : 4,
5504 : : }}},
5505 : : {"At", 210, 210, 209.987100000, 0, 22, 0, {{
5506 : : 0,
5507 : : },
5508 : : {
5509 : : 0,
5510 : : },
5511 : : {
5512 : : 1,
5513 : : 3,
5514 : : 5,
5515 : : 7,
5516 : : },
5517 : : {2, 4, 6},
5518 : : {
5519 : : 3,
5520 : : 5,
5521 : : }}},
5522 : : {"Rn", 222, 222, 222.017500000, 0, 0, 0, {{
5523 : : 0,
5524 : : },
5525 : : {
5526 : : 0,
5527 : : },
5528 : : {
5529 : : 0,
5530 : : },
5531 : : {
5532 : : 0,
5533 : : },
5534 : : {
5535 : : 0,
5536 : : }}},
5537 : : {"Fr", 223, 223, 223.019700000, MolInOrg1, 0, 0, {{
5538 : : 0,
5539 : : },
5540 : : {
5541 : : 0,
5542 : : },
5543 : : {
5544 : : 1,
5545 : : },
5546 : : {
5547 : : 0,
5548 : : },
5549 : : {
5550 : : 0,
5551 : : }}},
5552 : : {"Ra", 226, 226, 226.025410000, MolInOrg1, 0, 0, {{
5553 : : 0,
5554 : : },
5555 : : {
5556 : : 0,
5557 : : },
5558 : : {
5559 : : 2,
5560 : : },
5561 : : {
5562 : : 1,
5563 : : },
5564 : : {
5565 : : 0,
5566 : : }}},
5567 : : {"Ac", 227, 227, 227.027750000, MolInOrg1, 0, 1, {{
5568 : : 0,
5569 : : },
5570 : : {
5571 : : 0,
5572 : : },
5573 : : {
5574 : : 3,
5575 : : },
5576 : : {
5577 : : 0,
5578 : : },
5579 : : {
5580 : : 0,
5581 : : }}},
5582 : : {"Th", 232, 232, 232.038050000, MolInOrg2, 0, 1, {{
5583 : : 0,
5584 : : },
5585 : : {
5586 : : 0,
5587 : : },
5588 : : {
5589 : : 3,
5590 : : 4,
5591 : : },
5592 : : {
5593 : : 0,
5594 : : },
5595 : : {
5596 : : 0,
5597 : : }}},
5598 : : {"Pa", 231, 231, 231.035880000, MolInOrg3, 0, 1, {{
5599 : : 0,
5600 : : },
5601 : : {
5602 : : 0,
5603 : : },
5604 : : {
5605 : : 3,
5606 : : 4,
5607 : : 5,
5608 : : },
5609 : : {
5610 : : 0,
5611 : : },
5612 : : {
5613 : : 0,
5614 : : }}},
5615 : : {"U", 238, 238, 238.050790000, MolInOrg4, 0, 1, {{
5616 : : 0,
5617 : : },
5618 : : {
5619 : : 0,
5620 : : },
5621 : : {
5622 : : 3,
5623 : : 4,
5624 : : 5,
5625 : : 6,
5626 : : },
5627 : : {
5628 : : 0,
5629 : : },
5630 : : {
5631 : : 0,
5632 : : }}},
5633 : : {"Np", 237, 237, 237.048170000, MolInOrg1, 0, 1, {{
5634 : : 0,
5635 : : },
5636 : : {
5637 : : 0,
5638 : : },
5639 : : {
5640 : : 3,
5641 : : 4,
5642 : : 5,
5643 : : 6,
5644 : : },
5645 : : {
5646 : : 0,
5647 : : },
5648 : : {
5649 : : 0,
5650 : : }}},
5651 : : {"Pu", 244, 244, 244.064200000, MolInOrg1, 0, 1, {{
5652 : : 0,
5653 : : },
5654 : : {
5655 : : 0,
5656 : : },
5657 : : {
5658 : : 3,
5659 : : 4,
5660 : : 5,
5661 : : 6,
5662 : : },
5663 : : {
5664 : : 0,
5665 : : },
5666 : : {
5667 : : 0,
5668 : : }}},
5669 : : {"Am", 243, 243, 243.061370000, MolInOrg1, 0, 1, {{
5670 : : 0,
5671 : : },
5672 : : {
5673 : : 0,
5674 : : },
5675 : : {
5676 : : 3,
5677 : : 4,
5678 : : 5,
5679 : : 6,
5680 : : },
5681 : : {
5682 : : 0,
5683 : : },
5684 : : {
5685 : : 0,
5686 : : }}},
5687 : : {"Cm", 247, 247, 247.070300000, MolInOrg1, 0, 1, {{
5688 : : 0,
5689 : : },
5690 : : {
5691 : : 0,
5692 : : },
5693 : : {
5694 : : 3,
5695 : : },
5696 : : {
5697 : : 0,
5698 : : },
5699 : : {
5700 : : 0,
5701 : : }}},
5702 : : {"Bk", 247, 247, 247.070300000, MolInOrg1, 0, 1, {{
5703 : : 0,
5704 : : },
5705 : : {
5706 : : 0,
5707 : : },
5708 : : {
5709 : : 3,
5710 : : 4,
5711 : : },
5712 : : {
5713 : : 0,
5714 : : },
5715 : : {
5716 : : 0,
5717 : : }}},
5718 : : {"Cf", 251, 251, 251.079600000, MolInOrg1, 0, 1, {{
5719 : : 0,
5720 : : },
5721 : : {
5722 : : 0,
5723 : : },
5724 : : {
5725 : : 3,
5726 : : },
5727 : : {
5728 : : 0,
5729 : : },
5730 : : {
5731 : : 0,
5732 : : }}},
5733 : : {"Es", 252, 252, 252.082800000, MolInOrg1, 0, 1, {{
5734 : : 0,
5735 : : },
5736 : : {
5737 : : 0,
5738 : : },
5739 : : {
5740 : : 3,
5741 : : },
5742 : : {
5743 : : 0,
5744 : : },
5745 : : {
5746 : : 0,
5747 : : }}},
5748 : : {"Fm", 257, 257, 257.095100000, MolInOrg1, 0, 1, {{
5749 : : 0,
5750 : : },
5751 : : {
5752 : : 0,
5753 : : },
5754 : : {
5755 : : 3,
5756 : : },
5757 : : {
5758 : : 0,
5759 : : },
5760 : : {
5761 : : 0,
5762 : : }}},
5763 : : {"Md", 258, 258, 258.098600000, MolInOrg1, 0, 1, {{
5764 : : 0,
5765 : : },
5766 : : {
5767 : : 0,
5768 : : },
5769 : : {
5770 : : 3,
5771 : : },
5772 : : {
5773 : : 0,
5774 : : },
5775 : : {
5776 : : 0,
5777 : : }}},
5778 : : {"No", 259, 259, 259.100900000, MolInOrg1, 0, 1, {{
5779 : : 0,
5780 : : },
5781 : : {
5782 : : 0,
5783 : : },
5784 : : {
5785 : : 1,
5786 : : },
5787 : : {
5788 : : 0,
5789 : : },
5790 : : {
5791 : : 0,
5792 : : }}},
5793 : : {"Lr", 260, 260, 260.105400000, MolInOrg1, 0, 1, {{
5794 : : 0,
5795 : : },
5796 : : {
5797 : : 0,
5798 : : },
5799 : : {
5800 : : 1,
5801 : : },
5802 : : {
5803 : : 0,
5804 : : },
5805 : : {
5806 : : 0,
5807 : : }}},
5808 : : {"Rf", 261, 261, 261.108700000, MolInOrg1, 0, 1, {{
5809 : : 0,
5810 : : },
5811 : : {
5812 : : 0,
5813 : : },
5814 : : {
5815 : : 1,
5816 : : },
5817 : : {
5818 : : 0,
5819 : : },
5820 : : {
5821 : : 0,
5822 : : }}},
5823 : :
5824 : : /*
5825 : : The elements below were added after v. 1.03.
5826 : : When available, the mass is given for isotope with the longest half-life.
5827 : : Standard valences given here are just placeholders.
5828 : : v. 1.04: added elements 105-112.
5829 : : Ref.: M. E. WIESER AND T. B. COPLEN.
5830 : : Atomic weights of the elements 2009 (IUPAC Technical Report).
5831 : : Pure Appl. Chem., Vol. 83, No. 2, pp. 359-396, 2011.
5832 : : v. 1.05: added elements 114 and 116;
5833 : : updated data for elements 105-112.
5834 : : Ref.: J. Meija, T.B. Coplen, M.Berglund et al.
5835 : : Atomic weights of the elements 2013 (IUPAC Technical Report).
5836 : : Pure Appl. Chem., Vol. 88, No. 3, pp. 265-291, 2016.
5837 : : added elements 113, 115, 117, and 118, according to IUPAC provisional recommendations:
5838 : : Ref.: L. Ohrstrom, J. Reedijk.
5839 : : Names and Symbols of the Elements with Atomic Numbers 113, 115, 117 and 118.
5840 : : Pure Appl. Chem., May 1, 2016, Manuscript ID PAC-REC-16-05-01
5841 : : http://iupac.org/cms/wp-content/uploads/2016/06/names-and-symbols-of-elements.pdf
5842 : : */
5843 : :
5844 : : /* 105 dubnium Db ? Like: Ta */
5845 : : {"Db", 270, 270, 270.131000000, MolInOrg1, 0, 1, {{
5846 : : 0,
5847 : : },
5848 : : {
5849 : : 0,
5850 : : },
5851 : : {
5852 : : 1,
5853 : : },
5854 : : {
5855 : : 0,
5856 : : },
5857 : : {
5858 : : 0,
5859 : : }}},
5860 : : /* 106 seaborgium Sg ? Like: W */
5861 : : {"Sg", 269, 269, 269.129000000, MolInOrg1, 0, 1, {{
5862 : : 0,
5863 : : },
5864 : : {
5865 : : 0,
5866 : : },
5867 : : {
5868 : : 1,
5869 : : },
5870 : : {
5871 : : 0,
5872 : : },
5873 : : {
5874 : : 0,
5875 : : }}},
5876 : : /* 107 bohrium Bh ? Like: Re */
5877 : : {"Bh", 270, 270, 270.133000000, MolInOrg1, 0, 1, {{
5878 : : 0,
5879 : : },
5880 : : {
5881 : : 0,
5882 : : },
5883 : : {
5884 : : 1,
5885 : : },
5886 : : {
5887 : : 0,
5888 : : },
5889 : : {
5890 : : 0,
5891 : : }}},
5892 : : /* 108 hassium Hs ? Like: Os */
5893 : : {"Hs", 270, 270, 270.134000000, MolInOrg1, 0, 1, {{
5894 : : 0,
5895 : : },
5896 : : {
5897 : : 0,
5898 : : },
5899 : : {
5900 : : 1,
5901 : : },
5902 : : {
5903 : : 0,
5904 : : },
5905 : : {
5906 : : 0,
5907 : : }}},
5908 : : /* 109 meitnerium Mt ? Like: Ir */
5909 : : {"Mt", 278, 278, 278.156000000, MolInOrg1, 0, 1, {{
5910 : : 0,
5911 : : },
5912 : : {
5913 : : 0,
5914 : : },
5915 : : {
5916 : : 1,
5917 : : },
5918 : : {
5919 : : 0,
5920 : : },
5921 : : {
5922 : : 0,
5923 : : }}},
5924 : : /* 110 darmstadtium Ds ? Like: Pt */
5925 : : {"Ds", 281, 281, 281.165000000, MolInOrg1, 0, 1, {{
5926 : : 0,
5927 : : },
5928 : : {
5929 : : 0,
5930 : : },
5931 : : {
5932 : : 1,
5933 : : },
5934 : : {
5935 : : 0,
5936 : : },
5937 : : {
5938 : : 0,
5939 : : }}},
5940 : : /* 111 roentgenium Rg ? Like: Au */
5941 : : {"Rg", 281, 281, 281.166000000, MolInOrg1, 0, 1, {{
5942 : : 0,
5943 : : },
5944 : : {
5945 : : 0,
5946 : : },
5947 : : {
5948 : : 1,
5949 : : },
5950 : : {
5951 : : 0,
5952 : : },
5953 : : {
5954 : : 0,
5955 : : }}},
5956 : : /* 112 copernicium Cn ? Like: Hg */
5957 : : {"Cn", 285, 285, 285.177000000, MolInOrg1, 0, 1, {{
5958 : : 0,
5959 : : },
5960 : : {
5961 : : 0,
5962 : : },
5963 : : {
5964 : : 1,
5965 : : },
5966 : : {
5967 : : 0,
5968 : : },
5969 : : {
5970 : : 0,
5971 : : }}},
5972 : : /* 113 nihonium Nh ? Like: ? */
5973 : : {"Nh", 278, 278, 278.000000000, MolInOrg1, 0, 1, {{
5974 : : 0,
5975 : : },
5976 : : {
5977 : : 0,
5978 : : },
5979 : : {
5980 : : 1,
5981 : : },
5982 : : {
5983 : : 0,
5984 : : },
5985 : : {
5986 : : 0,
5987 : : }}},
5988 : : /* 114 flerovium Fl ? Like: Pb */
5989 : : {"Fl", 289, 289, 289.190000000, MolInOrg1, 0, 1, {{
5990 : : 0,
5991 : : },
5992 : : {
5993 : : 0,
5994 : : },
5995 : : {
5996 : : 1,
5997 : : },
5998 : : {
5999 : : 0,
6000 : : },
6001 : : {
6002 : : 0,
6003 : : }}},
6004 : : /* 115 moscovium Mc ? Like: ? */
6005 : : {"Mc", 289, 289, 289.000000000, MolInOrg1, 0, 1, {{
6006 : : 0,
6007 : : },
6008 : : {
6009 : : 0,
6010 : : },
6011 : : {
6012 : : 1,
6013 : : },
6014 : : {
6015 : : 0,
6016 : : },
6017 : : {
6018 : : 0,
6019 : : }}},
6020 : : /* 116 livermorium Lv ? Like: Po */
6021 : : {"Lv", 293, 293, 293.204000000, MolInOrg1, 0, 1, {{
6022 : : 0,
6023 : : },
6024 : : {
6025 : : 0,
6026 : : },
6027 : : {
6028 : : 1,
6029 : : },
6030 : : {
6031 : : 0,
6032 : : },
6033 : : {
6034 : : 0,
6035 : : }}},
6036 : : /* 117 tennessine Ts ? Like: ? */
6037 : : {"Ts", 297, 297, 297.000000000, MolInOrg1, 0, 1, {{
6038 : : 0,
6039 : : },
6040 : : {
6041 : : 0,
6042 : : },
6043 : : {
6044 : : 1,
6045 : : },
6046 : : {
6047 : : 0,
6048 : : },
6049 : : {
6050 : : 0,
6051 : : }}},
6052 : : /* 118 oganesson Og ? Like: ? */
6053 : : {"Og", 294, 294, 294.000000000, MolInOrg1, 0, 1, {{
6054 : : 0,
6055 : : },
6056 : : {
6057 : : 0,
6058 : : },
6059 : : {
6060 : : 1,
6061 : : },
6062 : : {
6063 : : 0,
6064 : : },
6065 : : {
6066 : : 0,
6067 : : }}},
6068 : : /* End of added in v. 1.04 - 1.05 */
6069 : : {"Zy", 0, 0, 0.000000000, 0, 0, 1, {{
6070 : : 0,
6071 : : },
6072 : : {
6073 : : 0,
6074 : : },
6075 : : {
6076 : : 1,
6077 : : },
6078 : : {
6079 : : 0,
6080 : : },
6081 : : {
6082 : : 0,
6083 : : }}},
6084 : : {"Zz", 0, 0, 0.000000000, 0, 0, 1, {{
6085 : : 0,
6086 : : },
6087 : : {
6088 : : 0,
6089 : : },
6090 : : {
6091 : : 1,
6092 : : },
6093 : : {
6094 : : 0,
6095 : : },
6096 : : {
6097 : : 0,
6098 : : }}},
6099 : : #ifdef INCHI_ZFRAG
6100 : : {"Zu", 0, 0, 0.000000000, 0, 0, 1, {{
6101 : : 0,
6102 : : },
6103 : : {
6104 : : 0,
6105 : : },
6106 : : {
6107 : : 1,
6108 : : },
6109 : : {
6110 : : 0,
6111 : : },
6112 : : {
6113 : : 0,
6114 : : }}},
6115 : : {"Zv", 0, 0, 0.000000000, 0, 0, 1, {{
6116 : : 0,
6117 : : },
6118 : : {
6119 : : 0,
6120 : : },
6121 : : {
6122 : : 2,
6123 : : },
6124 : : {
6125 : : 0,
6126 : : },
6127 : : {
6128 : : 0,
6129 : : }}},
6130 : : {"Zw", 0, 0, 0.000000000, 0, 0, 1, {{
6131 : : 0,
6132 : : },
6133 : : {
6134 : : 0,
6135 : : },
6136 : : {
6137 : : 3,
6138 : : },
6139 : : {
6140 : : 0,
6141 : : },
6142 : : {
6143 : : 0,
6144 : : }}},
6145 : : {"Zx", 0, 0, 0.000000000, 0, 0, 1, {{
6146 : : 0,
6147 : : },
6148 : : {
6149 : : 0,
6150 : : },
6151 : : {
6152 : : 1,
6153 : : 2,
6154 : : },
6155 : : {
6156 : : 0,
6157 : : },
6158 : : {
6159 : : 0,
6160 : : }}},
6161 : : #endif
6162 : :
6163 : : {"", 0, 0, 0.000000000, 0, 0, 0, {{
6164 : : 0,
6165 : : },
6166 : : {
6167 : : 0,
6168 : : },
6169 : : {
6170 : : 0,
6171 : : },
6172 : : {
6173 : : 0,
6174 : : },
6175 : : {
6176 : : 0,
6177 : : }}},
6178 : : };
6179 : :
6180 : : /****************************************************************************
6181 : : * (@nnuk : Nauman Ullah Khan)
6182 : : * Function retrieves the valence values from the MolecularInoragnicsArray
6183 : : ****************************************************************************/
6184 : 6 : int getElValenceforMolecularInorganics(int nPeriodicNum, int charge, int val_num)
6185 : : {
6186 [ + - + - : 6 : if (charge < MIN_ATOM_CHARGE || charge > MAX_ATOM_CHARGE || val_num >= MAX_NUM_VALENCES)
- + ]
6187 : : {
6188 : 0 : return 0;
6189 : : }
6190 : :
6191 [ + - ]: 6 : return MolecularInorganicsArray[nPeriodicNum > 1 ? nPeriodicNum + 1 : 0].cValence[NEUTRAL_STATE + charge][val_num];
6192 : : }
6193 : :
6194 : : /****************************************************************************
6195 : : * (@nnuk : Nauman Ullah Khan)
6196 : : * Function retrieves the element type value from the MolecularInorganicsArray
6197 : : ****************************************************************************/
6198 : 3 : int getElTypeforMolecularInorganics(int nPeriodicNum)
6199 : : {
6200 : 3 : return MolecularInorganicsArray[nPeriodicNum + 1].nType;
6201 : : }
6202 : :
6203 : : /*****************************************************************************
6204 : : * (@nnuk : Nauman Ullah Khan)
6205 : : * Function check for molecular inorganics if a metal atom has to be disconnected
6206 : : * or not.
6207 : : ******************************************************************************/
6208 : 3 : int MolecularInorganicsIsMetalToDisconnect(inp_ATOM *at, int atom_idx)
6209 : : {
6210 : :
6211 : : int at_valence, num_H;
6212 : 3 : int type = getElTypeforMolecularInorganics(at[atom_idx].el_number);
6213 : : int j;
6214 : :
6215 : : /* Calculate the actual valence of the atom
6216 : : * It means that the total bounding capacity
6217 : : * of the atom has to be taken into account
6218 : : * which will further get equated within the
6219 : : * elements array to a metal atom(neutral or an ion) */
6220 : 3 : num_H = NUMH(at, atom_idx);
6221 : 3 : at_valence = num_H + at[atom_idx].chem_bonds_valence;
6222 : :
6223 [ + - - + ]: 3 : if (!at_valence || (abs(at[atom_idx].charge) > 1))
6224 : : {
6225 : 0 : return 0; /* Isolated metal atom or Atom has multiple charges */
6226 : : }
6227 : :
6228 : : /* Check if the valence matches a known normal valence */
6229 [ + + ]: 9 : for (j = 0; j < 4; j++)
6230 : : {
6231 : 8 : const int bitmask = (1 << j); /* Create bitmask for the j-th bit */
6232 : 8 : const bool is_valence_state_valid = (bitmask & type) != 0; /* Check if the j-th valence state is allowed */
6233 : :
6234 [ + + + + ]: 8 : if (is_valence_state_valid && at_valence == getElValenceforMolecularInorganics(at[atom_idx].el_number, at[atom_idx].charge, j))
6235 : : {
6236 : 2 : return 1; /* Atom has normal valence follows disconnection logic if applicable */
6237 : : }
6238 : : }
6239 : :
6240 : : /* Default: Valence greater than usual or the atom is isolated hence no disconnection */
6241 : 1 : return 0;
6242 : : }
6243 : :
6244 : : #define NUM_ELEMENTS 118 /* Adjust according to the number of elements in the array */
6245 : : /*****************************************************************************
6246 : : * (@nnuk : Nauman Ullah Khan)
6247 : : * Elements Array for for molecular inorganics
6248 : : ******************************************************************************/
6249 : :
6250 : : ElementsMolecularInorganics elementListMolecularInorganics[NUM_ELEMENTS] =
6251 : : {
6252 : : {1, "H"}, {2, "He"}, {3, "Li"}, {4, "Be"}, {5, "B"}, {6, "C"}, {7, "N"}, {8, "O"}, {9, "F"}, {10, "Ne"}, {11, "Na"}, {12, "Mg"}, {13, "Al"}, {14, "Si"}, {15, "P"}, {16, "S"}, {17, "Cl"}, {18, "Ar"}, {19, "K"}, {20, "Ca"}, {21, "Sc"}, {22, "Ti"}, {23, "V"}, {24, "Cr"}, {25, "Mn"}, {26, "Fe"}, {27, "Co"}, {28, "Ni"}, {29, "Cu"}, {30, "Zn"}, {31, "Ga"}, {32, "Ge"}, {33, "As"}, {34, "Se"}, {35, "Br"}, {36, "Kr"}, {37, "Rb"}, {38, "Sr"}, {39, "Y"}, {40, "Zr"}, {41, "Nb"}, {42, "Mo"}, {43, "Tc"}, {44, "Ru"}, {45, "Rh"}, {46, "Pd"}, {47, "Ag"}, {48, "Cd"}, {49, "In"}, {50, "Sn"}, {51, "Sb"}, {52, "Te"}, {53, "I"}, {54, "Xe"}, {55, "Cs"}, {56, "Ba"}, {57, "La"}, {58, "Ce"}, {59, "Pr"}, {60, "Nd"}, {61, "Pm"}, {62, "Sm"}, {63, "Eu"}, {64, "Gd"}, {65, "Tb"}, {66, "Dy"}, {67, "Ho"}, {68, "Er"}, {69, "Tm"}, {70, "Yb"}, {71, "Lu"}, {72, "Hf"}, {73, "Ta"}, {74, "W"}, {75, "Re"}, {76, "Os"}, {77, "Ir"}, {78, "Pt"}, {79, "Au"}, {80, "Hg"}, {81, "Tl"}, {82, "Pb"}, {83, "Bi"}, {84, "Po"}, {85, "At"}, {86, "Rn"}, {87, "Fr"}, {88, "Ra"}, {89, "Ac"}, {90, "Th"}, {91, "Pa"}, {92, "U"}, {93, "Np"}, {94, "Pu"}, {95, "Am"}, {96, "Cm"}, {97, "Bk"}, {98, "Cf"}, {99, "Es"}, {100, "Fm"}, {101, "Md"}, {102, "No"}, {103, "Lr"}, {104, "Rf"}, {105, "Db"}, {106, "Sg"}, {107, "Bh"}, {108, "Hs"}, {109, "Mt"}, {110, "Ds"}, {111, "Rg"}, {112, "Cn"}, {113, "Nh"}, {114, "Fl"}, {115, "Mc"}, {116, "Lv"}, {117, "Ts"}, {118, "Og"}};
6253 : :
6254 : : /*************************************************************************
6255 : : * (@nnuk : NaumanUllahKhan)
6256 : : * Binary Array of all the Electronegativity values between Elements
6257 : : **************************************************************************/
6258 : :
6259 : : const int binaryArrayMolecularInorganics[NUM_ELEMENTS][NUM_ELEMENTS] = {
6260 : : {0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
6261 : : {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
6262 : : {0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
6263 : : {0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
6264 : : {0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
6265 : : {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
6266 : : {0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
6267 : : {0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
6268 : : {1, 0, 1, 1, 1, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 0, 0, 1, 1, 0, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
6269 : : {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
6270 : : {0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
6271 : : {0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
6272 : : {0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
6273 : : {0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
6274 : : {0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
6275 : : {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
6276 : : {0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
6277 : : {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
6278 : : {0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
6279 : : {0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
6280 : : {0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
6281 : : {0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
6282 : : {0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
6283 : : {0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
6284 : : {0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
6285 : : {0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
6286 : : {0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
6287 : : {0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
6288 : : {0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
6289 : : {0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
6290 : : {0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
6291 : : {0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
6292 : : {0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
6293 : : {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
6294 : : {0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
6295 : : {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
6296 : : {0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
6297 : : {0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
6298 : : {0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
6299 : : {0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
6300 : : {0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
6301 : : {0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
6302 : : {0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
6303 : : {0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
6304 : : {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
6305 : : {0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
6306 : : {0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
6307 : : {0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
6308 : : {0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
6309 : : {0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
6310 : : {0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
6311 : : {0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
6312 : : {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
6313 : : {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
6314 : : {0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
6315 : : {0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
6316 : : {0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
6317 : : {0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
6318 : : {0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
6319 : : {0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
6320 : : {0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
6321 : : {0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
6322 : : {0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
6323 : : {0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
6324 : : {0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
6325 : : {0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
6326 : : {0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
6327 : : {0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
6328 : : {0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
6329 : : {0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
6330 : : {0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
6331 : : {0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
6332 : : {0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
6333 : : {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
6334 : : {0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
6335 : : {0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
6336 : : {0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
6337 : : {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
6338 : : {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
6339 : : {0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
6340 : : {0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
6341 : : {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
6342 : : {0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
6343 : : {0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
6344 : : {0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
6345 : : {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
6346 : : {0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
6347 : : {0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
6348 : : {0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
6349 : : {0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
6350 : : {0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
6351 : : {0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
6352 : : {0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
6353 : : {0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
6354 : : {0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
6355 : : {0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
6356 : : {0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
6357 : : {0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
6358 : : {0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
6359 : : {0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
6360 : : {0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
6361 : : {0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
6362 : : {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
6363 : : {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
6364 : : {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
6365 : : {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
6366 : : {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
6367 : : {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
6368 : : {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
6369 : : {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
6370 : : {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
6371 : : {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
6372 : : {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
6373 : : {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
6374 : : {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
6375 : : {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
6376 : : {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
6377 : : {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
6378 : : };
6379 : :
6380 : : /*****************************************************************************
6381 : : * (@nnuk : Nauman Ullah Khan)
6382 : : * Function to retrieve binary values for MolecularInorganicsPreprocessing
6383 : : * Binary values are retrieved from the disconnection array "binaryArrayMolecularInorganics"
6384 : : * "1" means that the bond between atom and the neighbouring atom has to be
6385 : : * disconnected whereas, "0" means the bond has to be kept.
6386 : : ******************************************************************************/
6387 : :
6388 : 25 : int shouldBondBeCut(int atom1, int atom2)
6389 : : {
6390 : : int index1, index2, binaryValue;
6391 : :
6392 : : /* Get the indices corresponding to the atomic numbers */
6393 : 25 : index1 = atom1 - 1;
6394 : 25 : index2 = atom2 - 1;
6395 : :
6396 : : /* Retrieve the binary value from the binary array */
6397 : 25 : binaryValue = binaryArrayMolecularInorganics[index1][index2];
6398 : :
6399 : : /* Output for debugging purposes */
6400 : : /*printf("Electronegativity binary value between the atom and it's neighbour is: %d\n", binaryValue); */
6401 : :
6402 : 25 : return binaryValue;
6403 : : }
6404 : :
6405 : : /*****************************************************************************
6406 : : * (@nnuk : Nauman Ullah Khan)
6407 : : * Function to update the neighboring list of the atom for MolecularInorganicsPreprocessing.
6408 : : ******************************************************************************/
6409 : :
6410 : 6 : void updateNeighborListMolecularInorganics(inp_ATOM *at, int atom_idx, int neighbor_idx)
6411 : : {
6412 : :
6413 : 6 : int valence = at[atom_idx].valence;
6414 : : int i, j;
6415 : :
6416 [ + + ]: 9 : for (i = 0; i < valence; i++)
6417 : : {
6418 [ - + ]: 3 : if (at[atom_idx].neighbor[i] == neighbor_idx)
6419 : : {
6420 : : /* Shift remaining neighbors to fill the gap */
6421 [ # # ]: 0 : for (j = i; j < valence - 1; j++)
6422 : : {
6423 : 0 : at[atom_idx].neighbor[j] = at[atom_idx].neighbor[j + 1];
6424 : : }
6425 : 0 : at[atom_idx].valence--; /* Reduce the valence (number of neighbors) */
6426 : :
6427 : 0 : break;
6428 : : }
6429 : : }
6430 : 6 : }
6431 : :
6432 : : /*****************************************************************************
6433 : : * (@nnuk :: Nauman Ullah Khan)
6434 : : * @brief Function to preprocess molecular inorganics structures by disconnecting metal bonds and handling salts + ammonium salts.
6435 : : *
6436 : : * This function processes a given molecular structure, identifies metal atoms,
6437 : : * and performs bond disconnections based on electronegativity differences. After metal disconnections,
6438 : : * it also checks for ammonium salt patterns and disconnects them where applicable.
6439 : : *
6440 : : * @param orig_at_data Pointer to the original atom data structure.
6441 : : * @param ip Pointer to the input parameters structure.
6442 : : * @return Number of successful disconnections or -1 on error.
6443 : : *****************************************************************************/
6444 : :
6445 : 6 : int MolecularInorganicsPreprocessing(ORIG_ATOM_DATA *orig_at_data, INPUT_PARMS *ip)
6446 : : {
6447 : 6 : int ret_code = 0;
6448 : :
6449 [ + - + - : 6 : if (!ip || !orig_at_data || !orig_at_data->at)
- + ]
6450 : : {
6451 : 0 : return -1;
6452 : : }
6453 : :
6454 [ - + ]: 6 : if (!ip->bMolecularInorganics)
6455 : : {
6456 : 0 : return -1;
6457 : : }
6458 : :
6459 : : /* Pointer to the array of input atoms from the original atom data structure */
6460 : 6 : inp_ATOM *at = orig_at_data->at;
6461 : :
6462 : : /* Total number of input atoms present in the molecular structure */
6463 : 6 : int num_at = orig_at_data->num_inp_atoms;
6464 : :
6465 : : /* Pointer to the array storing the old component numbers for each atom, used for tracking connectivity */
6466 : 6 : AT_NUMB *nOldCompNumber = orig_at_data->nOldCompNumber;
6467 : :
6468 : : /* Track number of disconnections */
6469 : 6 : int num_disconnected = 0;
6470 : :
6471 : : /* variables declared */
6472 : : int i, j, n, k, t;
6473 : : int binaryValue;
6474 : : int disconnectDecision;
6475 : : int neighbor_idx, neigh_pos;
6476 : : int num_metals, current_component;
6477 : :
6478 : : /* memory allocation */
6479 : 6 : S_CHAR* dfs_visited = (S_CHAR*)inchi_calloc(num_at, sizeof(S_CHAR));
6480 : 6 : int* dfs_stack = (int*)inchi_malloc(num_at * sizeof(int));
6481 : 6 : int* ligand_elem_array = (int*)inchi_malloc(num_at * sizeof(int));
6482 : 6 : int* structure_id = (int*)inchi_malloc(num_at * sizeof(int));
6483 : 6 : int* structure_metal_count = (int*)inchi_calloc(num_at, sizeof(int));
6484 : :
6485 [ + - + - : 6 : if (!dfs_visited || !dfs_stack || !ligand_elem_array || !structure_id || !structure_metal_count)
+ - + - -
+ ]
6486 : : {
6487 : 0 : ret_code = -1;
6488 : 0 : goto cleanup;
6489 : : }
6490 : :
6491 : : /* Before disconnection, invoke ammonium salt functions */
6492 [ + + ]: 34 : for (j = 0; j < num_at; j++)
6493 : : {
6494 : : int piO, pk;
6495 : : S_CHAR num_explicit_H[NUM_H_ISOTOPES + 1];
6496 : :
6497 [ - + ]: 28 : if (bIsAmmoniumSalt(at, j, &piO, &pk, num_explicit_H))
6498 : : {
6499 : 0 : DisconnectAmmoniumSalt(at, j, piO, pk, num_explicit_H);
6500 : : }
6501 : : }
6502 : :
6503 : : /* Function call to Mark ring systems */
6504 : 6 : MarkRingSystemsInp(at, num_at, 0);
6505 : :
6506 : : /* Compute metal list */
6507 : 6 : num_metals = 0;
6508 [ + + ]: 34 : for (i = 0; i < num_at; i++)
6509 : : {
6510 [ + + ]: 28 : if (is_el_a_metal(at[i].el_number))
6511 : : {
6512 : 6 : num_metals++;
6513 : : }
6514 : : }
6515 : :
6516 : : /*
6517 : : * Precompute structure components (DFS RUN ONCE) to satisfy this rule below,
6518 : : * (if there is a path from this metal to ANY other metal,
6519 : : * keep all bonds for this metal)
6520 : : */
6521 [ + + ]: 34 : for (i = 0; i < num_at; i++)
6522 : : {
6523 : 28 : structure_id[i] = -1;
6524 : : }
6525 : :
6526 : 6 : current_component = 0;
6527 : :
6528 [ + + ]: 34 : for (i = 0; i < num_at; i++)
6529 : : {
6530 [ + + ]: 28 : if (structure_id[i] >= 0)
6531 : : {
6532 : 22 : continue;
6533 : : }
6534 : :
6535 : 6 : int dfs_stack_size = 0;
6536 : 6 : dfs_stack[dfs_stack_size++] = i;
6537 : 6 : structure_id[i] = current_component;
6538 : :
6539 [ + + ]: 34 : while (dfs_stack_size)
6540 : : {
6541 : 28 : int current_atom = dfs_stack[--dfs_stack_size];
6542 : :
6543 [ + + ]: 28 : if (is_el_a_metal(at[current_atom].el_number))
6544 : : {
6545 : 6 : structure_metal_count[current_component]++;
6546 : : }
6547 : :
6548 [ + + ]: 74 : for (neigh_pos = 0; neigh_pos < at[current_atom].valence; neigh_pos++)
6549 : : {
6550 : 46 : int neighbor_atom = at[current_atom].neighbor[neigh_pos];
6551 : :
6552 [ + - - + ]: 46 : if (neighbor_atom < 0 || neighbor_atom >= num_at)
6553 : : {
6554 : 0 : continue;
6555 : : }
6556 : :
6557 [ + + ]: 46 : if (structure_id[neighbor_atom] >= 0)
6558 : : {
6559 : 24 : continue;
6560 : : }
6561 : :
6562 : 22 : structure_id[neighbor_atom] = current_component;
6563 : :
6564 [ + - ]: 22 : if (dfs_stack_size < num_at)
6565 : : {
6566 : 22 : dfs_stack[dfs_stack_size++] = neighbor_atom;
6567 : : }
6568 : : }
6569 : : }
6570 : :
6571 : 6 : current_component++;
6572 : : }
6573 : :
6574 [ + + ]: 34 : for (i = 0; i < num_at; i++)
6575 : : {
6576 [ + + ]: 28 : if (!is_el_a_metal(at[i].el_number))
6577 : : {
6578 : 22 : continue;
6579 : : }
6580 : :
6581 : : /*@nnuk
6582 : : *If there exists any path between this metal and any other metal OR
6583 : : *the atom belongs to a ring system containing at least one metal, then keep all bonds for this metal.
6584 : : */
6585 : 6 : int keep_all_ligand_for_this_metal = 0;
6586 : :
6587 : : /* @nnuk
6588 : : *if this metal is part of a ring system that contains at least one metal,
6589 : : *keep all bonds for this metal
6590 : : */
6591 [ + - ]: 6 : if (at[i].nRingSystem)
6592 : : {
6593 : : /* scan atoms that are in same ring system and check for a metal */
6594 : 6 : AT_NUMB ring_id = at[i].nRingSystem;
6595 : :
6596 [ + + ]: 34 : for (k = 0; k < num_at; k++)
6597 : : {
6598 [ + + + + : 28 : if (k != i && at[k].nRingSystem == ring_id && is_el_a_metal(at[k].el_number))
- + ]
6599 : : {
6600 : 0 : keep_all_ligand_for_this_metal = 1;
6601 : 0 : break;
6602 : : }
6603 : : }
6604 : : }
6605 : :
6606 : : /*@nnuk
6607 : : *if there is a path from this metal to ANY other metal,
6608 : : *keep all bonds for this metal.
6609 : : */
6610 [ + - - + ]: 6 : if (!keep_all_ligand_for_this_metal && num_metals > 1)
6611 : : {
6612 : 0 : int processed_structure = structure_id[i];
6613 : :
6614 [ # # ]: 0 : if (structure_metal_count[processed_structure] > 1)
6615 : : {
6616 : 0 : keep_all_ligand_for_this_metal = 1;
6617 : : }
6618 : : }
6619 : :
6620 [ - + ]: 6 : if (keep_all_ligand_for_this_metal)
6621 : : {
6622 : 0 : ip->bMolecularInorganicsReconnectedInChI = 1;
6623 : 0 : continue;
6624 : : }
6625 : :
6626 : : /*@nnuk
6627 : : *If central metal is bound to different ligand atom element types
6628 : : *AND at least one of the bonds must be kept according to existing bond rules,
6629 : : *then keep ALL bonds
6630 : : */
6631 : : {
6632 : 6 : int ligand_type_count = 0;
6633 : 6 : int must_keep_neighbor = 0;
6634 : :
6635 [ + + ]: 28 : for (n = 0; n < at[i].valence; n++)
6636 : : {
6637 : 22 : int neigh_idx = at[i].neighbor[n];
6638 : :
6639 [ + - - + ]: 22 : if (neigh_idx < 0 || neigh_idx >= num_at)
6640 : : {
6641 : 0 : continue;
6642 : : }
6643 : :
6644 : 22 : int neigh_elem = at[neigh_idx].el_number;
6645 : 22 : int found = 0;
6646 : :
6647 [ + + ]: 27 : for (t = 0; t < ligand_type_count; t++)
6648 : : {
6649 [ + + ]: 18 : if (ligand_elem_array[t] == neigh_elem)
6650 : : {
6651 : 13 : found = 1;
6652 : 13 : break;
6653 : : }
6654 : : }
6655 : :
6656 [ + + ]: 22 : if (!found)
6657 : : {
6658 : 9 : ligand_elem_array[ligand_type_count++] = neigh_elem;
6659 : : }
6660 : :
6661 [ + + - + ]: 22 : if (at[i].bond_type[n] > 1 || is_el_a_metal(at[neigh_idx].el_number))
6662 : : {
6663 : 3 : must_keep_neighbor = 1;
6664 : : }
6665 : : else
6666 : : {
6667 : 19 : binaryValue = shouldBondBeCut(at[i].el_number, neigh_elem);
6668 : :
6669 [ + + ]: 19 : if (binaryValue != 1)
6670 : : {
6671 : 9 : must_keep_neighbor = 1;
6672 : : }
6673 : : }
6674 : : }
6675 : :
6676 [ + + + - ]: 6 : if (ligand_type_count > 1 && must_keep_neighbor)
6677 : : {
6678 : 3 : ip->bMolecularInorganicsReconnectedInChI = 1;
6679 : 3 : continue;
6680 : : }
6681 : : }
6682 : :
6683 : : /* Call the MolecularInorganicsIsMetalToDisconnect function */
6684 : 3 : disconnectDecision = MolecularInorganicsIsMetalToDisconnect(at, i);
6685 : :
6686 [ + + ]: 3 : if (disconnectDecision != 1) /* If disconnectDecision = 1, then disconnection procedure will be followed if applicable */
6687 : : {
6688 : : /* (@nnuk) : No disconnection if the metal atom bounding capacity is greater than
6689 : : * the limit set inside Molecular Inorganics elements array or if the metal atom is
6690 : : * isolated. */
6691 : 1 : ip->bMolecularInorganicsReconnectedInChI = 1;
6692 : 1 : continue;
6693 : : }
6694 : :
6695 : : /* Proceed with electronegativity and disconnection logic */
6696 [ + + ]: 8 : for (n = at[i].valence - 1; n >= 0; n--)
6697 : : {
6698 : 6 : neighbor_idx = at[i].neighbor[n];
6699 : :
6700 : : /* Check if the neighboring atom has more than 1 bond connected to the metal atom or
6701 : : * if the neighbour is also a metal atom. In both cases no disconnection has to be done */
6702 [ + - - + ]: 6 : if (at[i].bond_type[n] > 1 || is_el_a_metal(at[neighbor_idx].el_number))
6703 : : {
6704 : 0 : ip->bMolecularInorganicsReconnectedInChI = 1;
6705 : 0 : continue; /* Skip disconnection for this bond */
6706 : : }
6707 : :
6708 : 6 : binaryValue = shouldBondBeCut(at[i].el_number, at[neighbor_idx].el_number);
6709 : :
6710 [ + + ]: 6 : if (binaryValue != 1)
6711 : : {
6712 : : /* (@nnuk : Keep the bonds, no disconnection) */
6713 : 3 : ip->bMolecularInorganicsReconnectedInChI = 1;
6714 : 3 : continue;
6715 : : }
6716 : :
6717 : 3 : DisconnectInpAtBond(at, nOldCompNumber, i, n);
6718 : :
6719 : : /* Updating the metal as well as neighbor list */
6720 : 3 : updateNeighborListMolecularInorganics(at, i, neighbor_idx);
6721 : 3 : updateNeighborListMolecularInorganics(at, neighbor_idx, i);
6722 : :
6723 : 3 : at[i].charge += 1; /* Metal atom loses an electron -> +1 charge */
6724 : 3 : at[neighbor_idx].charge -= 1; /* Neighbor atom gains an electron -> -1 charge */
6725 : :
6726 : 3 : num_disconnected++;
6727 : : }
6728 : : }
6729 : :
6730 : 6 : cleanup:
6731 [ + - + - ]: 6 : if (dfs_visited) inchi_free(dfs_visited);
6732 [ + - + - ]: 6 : if (dfs_stack) inchi_free(dfs_stack);
6733 [ + - + - ]: 6 : if (ligand_elem_array) inchi_free(ligand_elem_array);
6734 [ + - + - ]: 6 : if (structure_id) inchi_free(structure_id);
6735 [ + - + - ]: 6 : if (structure_metal_count) inchi_free(structure_metal_count);
6736 : :
6737 [ - + ]: 6 : return (ret_code < 0) ? ret_code : num_disconnected;
6738 : : }
6739 : :
6740 : : #if (READ_INCHI_STRING == 1)
6741 : :
6742 : : /****************************************************************************/
6743 : 0 : int bHeteroAtomMayHaveXchgIsoH(inp_ATOM *atom, int iat)
6744 : : {
6745 : 0 : inp_ATOM *at = atom + iat, *at2;
6746 : 0 : int j, val, is_H = 0, num_H, iat_numb, bAccept; /* djb-rwth: removing redundant variables */
6747 : :
6748 [ # # ]: 0 : if (0 > (iat_numb = get_iat_number(at->el_number)))
6749 : : {
6750 : 0 : return 0;
6751 : : }
6752 : :
6753 [ # # # # : 0 : if (abs(at->charge) > 1 || (at->radical && RADICAL_SINGLET != at->radical)) /* djb-rwth: addressing LLVM warning */
# # ]
6754 : : {
6755 : 0 : return 0;
6756 : : }
6757 : :
6758 : 0 : val = -1;
6759 [ # # # # : 0 : switch (iat_numb)
# ]
6760 : : {
6761 : 0 : case IAT_N:
6762 : : case IAT_P:
6763 : : /* djb-rwth: removing redundant code */
6764 : 0 : val = 3 + at->charge;
6765 : 0 : break;
6766 : :
6767 : 0 : case IAT_O:
6768 : : case IAT_S:
6769 : : case IAT_Se:
6770 : : case IAT_Te:
6771 : : /* djb-rwth: removing redundant code */
6772 : 0 : val = 2 + at->charge;
6773 : 0 : break;
6774 : :
6775 : 0 : case IAT_F:
6776 : : case IAT_Cl:
6777 : : case IAT_Br:
6778 : : case IAT_I:
6779 [ # # ]: 0 : if (at->charge == 0)
6780 : : {
6781 : : /* djb-rwth: removing redundant code */
6782 : 0 : val = 1;
6783 : : }
6784 : 0 : break;
6785 : :
6786 : 0 : case IAT_H:
6787 [ # # ]: 0 : if (at->valence == 0 &&
6788 [ # # ]: 0 : at->charge == 1)
6789 : : {
6790 : 0 : is_H = 1; /* isolated proton */
6791 : 0 : val = 0;
6792 : : }
6793 : : }
6794 [ # # ]: 0 : if (val < 0)
6795 : : {
6796 : 0 : return 0;
6797 : : }
6798 : 0 : num_H = NUMH(at, 0);
6799 [ # # ]: 0 : if (val != at->chem_bonds_valence + num_H)
6800 : : {
6801 : 0 : return 0;
6802 : : }
6803 [ # # ]: 0 : if (is_H)
6804 : : {
6805 : 0 : return 2; /* H atom */
6806 : : }
6807 : : else
6808 : : {
6809 : : /* djb-rwth: removing redundant code */
6810 [ # # # # ]: 0 : for (j = 0, bAccept = 1; j < at->valence && bAccept; j++)
6811 : : {
6812 : 0 : at2 = atom + (int)at->neighbor[j];
6813 [ # # # # ]: 0 : if ((at2->charge && at->charge) ||
6814 [ # # # # ]: 0 : (at2->radical && RADICAL_SINGLET != at2->radical)) /* djb-rwth: addressing LLVM warning */
6815 : : {
6816 : 0 : return 0; /* adjacent charged/radical atoms: do not neutralizate */
6817 : : }
6818 : : }
6819 : : }
6820 : :
6821 : 0 : return 1;
6822 : : }
6823 : :
6824 : : #endif
6825 : :
6826 : : /****************************************************************************/
6827 : 54 : int bNumHeterAtomHasIsotopicH(inp_ATOM *atom, int num_atoms)
6828 : : {
6829 : 54 : int i, j, val, is_H = 0, num_H, iat_numb, bAccept, num_iso_H, cur_num_iso_H, num_iso_atoms; /* djb-rwth: removing redundant variables */
6830 : : inp_ATOM *at, *at2;
6831 : :
6832 : 54 : num_iso_H = 0;
6833 : 54 : num_iso_atoms = 0;
6834 : :
6835 [ + + ]: 673 : for (i = 0, at = atom; i < num_atoms; i++, at++)
6836 : : {
6837 : :
6838 [ + - - + ]: 619 : num_iso_atoms += (at->iso_atw_diff != 0 || NUM_ISO_H(at, 0));
6839 : : /* isotopic atoms and implicit isotopic H */
6840 : :
6841 [ + + ]: 619 : if (0 > (iat_numb = get_iat_number(at->el_number)))
6842 : : {
6843 : 7 : continue;
6844 : : }
6845 : :
6846 [ + - - + : 612 : if (abs(at->charge) > 1 || (at->radical && RADICAL_SINGLET != at->radical)) /* djb-rwth: addressing LLVM warning */
- - ]
6847 : : {
6848 : 0 : continue;
6849 : : }
6850 : :
6851 : 612 : val = -1;
6852 [ + + + + : 612 : switch (iat_numb)
+ ]
6853 : : {
6854 : 17 : case IAT_N:
6855 : : case IAT_P:
6856 : : /* djb-rwth: removing redundant code */
6857 : 17 : val = 3 + at->charge;
6858 : 17 : break;
6859 : :
6860 : 62 : case IAT_O:
6861 : : case IAT_S:
6862 : : case IAT_Se:
6863 : : case IAT_Te:
6864 : : /* djb-rwth: removing redundant code */
6865 : 62 : val = 2 + at->charge;
6866 : 62 : break;
6867 : :
6868 : 116 : case IAT_F:
6869 : : case IAT_Cl:
6870 : : case IAT_Br:
6871 : : case IAT_I:
6872 [ + + ]: 116 : if (at->charge == 0)
6873 : : {
6874 : : /* djb-rwth: removing redundant code */
6875 : 113 : val = 1;
6876 : : }
6877 : 116 : break;
6878 : :
6879 : 1 : case IAT_H:
6880 [ - + ]: 1 : if (at->valence == 0 &&
6881 [ # # ]: 0 : at->charge == 1)
6882 : : {
6883 : 0 : is_H = 1; /* isolated proton */
6884 : 0 : val = 0;
6885 : : }
6886 : : }
6887 [ + + ]: 612 : if (val < 0)
6888 : : {
6889 : 420 : continue;
6890 : : }
6891 : :
6892 : 192 : num_H = NUMH(at, 0);
6893 [ - + ]: 192 : if (val != at->chem_bonds_valence + num_H)
6894 : : {
6895 : 0 : continue;
6896 : : }
6897 : :
6898 [ - + ]: 192 : if (is_H)
6899 : : {
6900 : 0 : bAccept = 1;
6901 : 0 : cur_num_iso_H = (at->iso_atw_diff != 0);
6902 : : }
6903 : : else
6904 : : {
6905 : 192 : cur_num_iso_H = 0;
6906 [ + + + - ]: 384 : for (j = 0, bAccept = 1; j < at->valence && bAccept; j++)
6907 : : {
6908 : 192 : at2 = atom + (int)at->neighbor[j];
6909 [ + + + - ]: 192 : if ((at2->charge && at->charge) ||
6910 [ - + - - ]: 192 : (at2->radical && RADICAL_SINGLET != at2->radical)) /* djb-rwth: addressing LLVM warning */
6911 : : {
6912 : 0 : bAccept = 0; /* adjacent charged/radical atoms: do not neutralizate */
6913 : 0 : break;
6914 : : }
6915 [ - + ]: 192 : else if (at2->el_number == EL_NUMBER_H &&
6916 [ # # # # ]: 0 : at2->valence == 1 && at2->iso_atw_diff)
6917 : : {
6918 : 0 : cur_num_iso_H++; /* isotopic explicit H */
6919 : : }
6920 : : }
6921 : :
6922 [ + - ]: 192 : if (bAccept)
6923 : : {
6924 : 192 : num_iso_atoms -= cur_num_iso_H; /* avoid counting explicit H as isotopic atom */
6925 : 192 : cur_num_iso_H += NUM_ISO_H(at, 0);
6926 : : }
6927 : : }
6928 : :
6929 [ + - - + ]: 192 : num_iso_H += (bAccept && cur_num_iso_H); /* number of acceptable heteroatoms that have isotopic H */
6930 : : }
6931 : :
6932 [ - + ]: 54 : return ((num_iso_H ? 1 : 0) | (num_iso_atoms ? 2 : 0));
6933 : : }
6934 : :
6935 : : /****************************************************/
6936 : : /* Mark and count disconnected structure components */
6937 : : /* by Depth-first searching each component */
6938 : : /****************************************************/
6939 : 17 : int cmp_components(const void *a1, const void *a2)
6940 : : {
6941 : : int ret;
6942 : : AT_NUMB n1;
6943 : : AT_NUMB n2;
6944 : :
6945 : 17 : n1 = ((const AT_NUMB *)a1)[0];
6946 : : /* number of atoms in the component -- descending order */
6947 : 17 : n2 = ((const AT_NUMB *)a2)[0];
6948 : :
6949 [ + + ]: 17 : if ((ret = (int)n2 - (int)n1)) /* djb-rwth: addressing LLVM warning */
6950 : : {
6951 : 7 : return ret;
6952 : : }
6953 : :
6954 : : /* stable sort */
6955 : 10 : n1 = ((const AT_NUMB *)a1)[1];
6956 : : /* component ordering number -- ascending order */
6957 : 10 : n2 = ((const AT_NUMB *)a2)[1];
6958 : :
6959 : 10 : ret = (int)n1 - (int)n2;
6960 : :
6961 : 10 : return ret;
6962 : : }
6963 : :
6964 : : /**
6965 : : * @brief Get the canonical atom number from original atom number
6966 : : *
6967 : : * @param aux Pointer to INChI auxiliary data
6968 : : * @param orig_atom_num Original atom number
6969 : : * @return Returns the canonical atom number, or -1 if not found
6970 : : */
6971 : 670 : int get_canonical_atom_number( const INChI_Aux *aux,
6972 : : int orig_atom_num)
6973 : : {
6974 [ - + ]: 670 : if (aux == NULL) {
6975 : 0 : return -1;
6976 : : }
6977 : :
6978 [ - + ]: 670 : if (aux->nOrigAtNosInCanonOrd == NULL) {
6979 : 0 : return -1;
6980 : : }
6981 : :
6982 [ + + ]: 7290 : for (int canon_num = 1; canon_num <= aux->nNumberOfAtoms; canon_num++) {
6983 [ + + ]: 6964 : if (aux->nOrigAtNosInCanonOrd[canon_num - 1] == orig_atom_num) {
6984 : 344 : return canon_num;
6985 : : }
6986 : : }
6987 : 326 : return -1;
6988 : : }
6989 : :
6990 : : /**
6991 : : * @brief Get the parity idx from canonical atom number object
6992 : : *
6993 : : * @param canon_atom_num Canonical atom number
6994 : : * @param nNumber Pointer to array of canonical atom numbers
6995 : : * @param nof_atoms Number of atoms
6996 : : * @return Returns the parity index, or -1 if not found
6997 : : */
6998 : 137 : int get_parity_idx_from_canonical_atom_number( int canon_atom_num,
6999 : : const AT_NUMB *nNumber,
7000 : : int nof_atoms)
7001 : : {
7002 [ - + ]: 137 : if (nNumber == NULL) {
7003 : 0 : return -1;
7004 : : }
7005 : :
7006 [ - + ]: 137 : if (nof_atoms <= 0) {
7007 : 0 : return -1;
7008 : : }
7009 : :
7010 [ + + ]: 425 : for (int i = 0; i < nof_atoms; i++) {
7011 [ + + ]: 418 : if (nNumber[i] == canon_atom_num) {
7012 : 130 : return i;
7013 : : }
7014 : : }
7015 : 7 : return -1;
7016 : : }
7017 : :
7018 : : /**
7019 : : * @brief Invert the parities for enhanced stereochemistry t- and m-layers
7020 : : *
7021 : : * @param inchi Pointer to INChI structure
7022 : : * @param aux Pointer to INChI auxiliary data
7023 : : * @param list_atoms Pointer to list of atom lists for abs, rel or rac information
7024 : : * @param nof_lists Number of lists
7025 : : * @param is_absolute Flag indicating if processing absolute stereochemistry
7026 : : * @return Returns 0 on success, 1 if list_atoms is NULL
7027 : : */
7028 : 153 : int invert_parities(const INChI *inchi,
7029 : : const INChI_Aux *aux,
7030 : : int **list_atoms,
7031 : : int nof_lists,
7032 : : int is_absolute)
7033 : : {
7034 : :
7035 : : // t - layer: parities
7036 : : // 2 = +
7037 : : // 1 = -
7038 : :
7039 : : // m - layer
7040 : : // -1 = m0
7041 : : // 1 = m1
7042 : :
7043 [ + + ]: 153 : if (list_atoms == NULL) {
7044 : 64 : return 1;
7045 : : }
7046 : :
7047 [ - + ]: 89 : if (nof_lists == 0)
7048 : : {
7049 : 0 : return 1;
7050 : : }
7051 : :
7052 : 89 : S_CHAR *t_parity = inchi->Stereo->t_parity;
7053 : :
7054 [ + + ]: 254 : for (int i = 0; i < nof_lists; i++) {
7055 : 165 : int nof_atoms = list_atoms[i][1];
7056 : :
7057 : 165 : AT_NUMB min_c_atom_num = (AT_NUMB)INT_MAX;
7058 [ + + ]: 478 : for (int j = 0; j < nof_atoms; j++) {
7059 : 313 : int orig_atom_num = list_atoms[i][2 + j];
7060 : 313 : AT_NUMB canon_atom_num = (AT_NUMB)get_canonical_atom_number(aux, orig_atom_num);
7061 [ + + ]: 313 : if (canon_atom_num < min_c_atom_num) {
7062 : 153 : min_c_atom_num = canon_atom_num;
7063 : : }
7064 : : }
7065 [ + + ]: 165 : if (min_c_atom_num == (AT_NUMB)INT_MAX) {
7066 : 53 : continue;
7067 : : }
7068 : 112 : int min_c_parity_idx = get_parity_idx_from_canonical_atom_number(min_c_atom_num,
7069 : 112 : inchi->Stereo->nNumber,
7070 : 112 : inchi->Stereo->nNumberOfStereoCenters);
7071 : :
7072 [ + + ]: 112 : if (min_c_parity_idx == -1) {
7073 : 3 : continue;
7074 : : }
7075 : :
7076 : 109 : int min_c_atom_parity = t_parity[min_c_parity_idx];
7077 [ + + ]: 109 : if (min_c_atom_parity == 2) {
7078 : :
7079 [ + + ]: 38 : for (int j = 0; j < nof_atoms; j++) {
7080 : 25 : int orig_atom_num = list_atoms[i][2 + j];
7081 : 25 : AT_NUMB canon_atom_num = (AT_NUMB)get_canonical_atom_number(aux, orig_atom_num);
7082 : 25 : int parity_idx = get_parity_idx_from_canonical_atom_number(canon_atom_num,
7083 : 25 : inchi->Stereo->nNumber,
7084 : 25 : inchi->Stereo->nNumberOfStereoCenters);
7085 : :
7086 [ + + ]: 25 : if (parity_idx == -1) {
7087 : 4 : continue;
7088 : : }
7089 : :
7090 [ + + ]: 21 : if (t_parity[parity_idx] == 2) {
7091 : 19 : t_parity[parity_idx] = 1;
7092 [ + - ]: 2 : } else if(t_parity[parity_idx] == 1) {
7093 : 2 : t_parity[parity_idx] = 2;
7094 : : }
7095 : : }
7096 : :
7097 [ + + ]: 13 : if (is_absolute) {
7098 : 2 : inchi->Stereo->nCompInv2Abs = -1; //m1
7099 : : }
7100 : : }
7101 : : }
7102 : 89 : return 0;
7103 : : }
7104 : :
7105 : : /**
7106 : : * @brief Set the enhanced stereochemistry information for t- and m-layers
7107 : : *
7108 : : * @param orig_inp_data Pointer to original input atom data
7109 : : * @param inchi Pointer to INChI structure
7110 : : * @param aux Pointer to INChI auxiliary data
7111 : : * @return Retruns 1 if not V3000, otherwise 0
7112 : : */
7113 : 57 : int set_EnhancedStereo_t_m_layers( const ORIG_ATOM_DATA *orig_inp_data,
7114 : : const INChI *inchi,
7115 : : const INChI_Aux *aux)
7116 : : {
7117 : 57 : int ret = 0;
7118 : :
7119 [ + + ]: 57 : if (!orig_inp_data->v3000)
7120 : : {
7121 : 1 : return 1;
7122 : : }
7123 : :
7124 [ + - - + ]: 56 : if (inchi == NULL || aux == NULL)
7125 : : {
7126 : 0 : return 1;
7127 : : }
7128 : :
7129 [ + - ]: 56 : if (inchi->Stereo == NULL ||
7130 [ + - ]: 56 : inchi->Stereo->t_parity == NULL ||
7131 [ + - ]: 56 : inchi->Stereo->nNumber == NULL ||
7132 [ + + ]: 56 : inchi->Stereo->nNumberOfStereoCenters <= 0) {
7133 : 5 : return 1;
7134 : : }
7135 : :
7136 [ + - ]: 51 : if (aux->nOrigAtNosInCanonOrd == NULL ||
7137 [ - + ]: 51 : aux->nNumberOfAtoms <= 0) {
7138 : 0 : return 1;
7139 : : }
7140 : :
7141 : 51 : int ret_abs = invert_parities(inchi, aux, orig_inp_data->v3000->lists_steabs, orig_inp_data->v3000->n_steabs, 1);
7142 : 51 : int ret_rac = invert_parities(inchi, aux, orig_inp_data->v3000->lists_sterac, orig_inp_data->v3000->n_sterac, 0);
7143 : 51 : int ret_rel = invert_parities(inchi, aux, orig_inp_data->v3000->lists_sterel, orig_inp_data->v3000->n_sterel, 0);
7144 : :
7145 [ + + ]: 51 : if ((orig_inp_data->v3000->n_steabs == 0) &&
7146 [ + + ]: 21 : (orig_inp_data->v3000->n_sterel > 0 ||
7147 [ + + ]: 17 : orig_inp_data->v3000->n_sterac)) {
7148 : 15 : inchi->Stereo->nCompInv2Abs = 1; //m0
7149 : : }
7150 : :
7151 : 51 : return ret;
7152 : : }
7153 : :
7154 : : /****************************************************************************
7155 : : Set the (disconnected) component numbers in ORIG_ATOM_DATA 'at[*].component'
7156 : : NB: components are (stable) sorted by number of heavy atoms
7157 : : ****************************************************************************/
7158 : 56 : int MarkDisconnectedComponents(ORIG_ATOM_DATA *orig_at_data,
7159 : : int bProcessOldCompNumbers)
7160 : : {
7161 : : typedef AT_NUMB AT_TRIPLE[3];
7162 : :
7163 : 56 : inp_ATOM *at = orig_at_data->at;
7164 : 56 : int num_at = orig_at_data->num_inp_atoms;
7165 : 56 : AT_NUMB *nCurAtLen = NULL;
7166 : :
7167 : 56 : AT_NUMB *nNewCompNumber = NULL;
7168 : 56 : AT_NUMB *nPrevAtom = NULL;
7169 : 56 : S_CHAR *iNeigh = NULL;
7170 : :
7171 : 56 : AT_NUMB *nOldCompNumber = NULL;
7172 : : int i, j, num_components, ret;
7173 : : int new_comp_no;
7174 : : AT_NUMB old_comp_no, another_comp_no, no_component;
7175 : :
7176 : : /* component_nbr[i][0] = number of atoms in the component i-1
7177 : : * component_nbr[i][1] = original component number (id-1) = i
7178 : : * after sorting:
7179 : : * component_nbr[j][2] = new number of component #(component_nbr[i][1]+1)
7180 : : */
7181 : 56 : AT_TRIPLE *component_nbr = NULL;
7182 : : int fst_at, nxt_at, cur_at, cur_neq_fst; /* moved from below 2024-09-01 DT */
7183 : :
7184 : : /* initialize */
7185 [ + + - + ]: 56 : if (bProcessOldCompNumbers && !orig_at_data->nOldCompNumber)
7186 : : {
7187 : 0 : bProcessOldCompNumbers = 0;
7188 : : }
7189 : 56 : num_components = 0;
7190 : :
7191 : : /*
7192 : : for ( j = 0; j < num_at; j ++ )
7193 : : {
7194 : : at[j].component = 0;
7195 : : }
7196 : : */
7197 : :
7198 : 56 : ret = -1;
7199 [ - + ]: 56 : if (!num_at)
7200 : : {
7201 : 0 : return 0;
7202 : : }
7203 : :
7204 : 56 : nNewCompNumber = (AT_NUMB *)inchi_calloc(num_at, sizeof(nNewCompNumber[0]));
7205 : 56 : nPrevAtom = (AT_NUMB *)inchi_calloc(num_at, sizeof(nPrevAtom[0]));
7206 : 56 : iNeigh = (S_CHAR *)inchi_calloc(num_at, sizeof(iNeigh[0]));
7207 : :
7208 [ + - + - : 56 : if (!nNewCompNumber || !nPrevAtom || !iNeigh) /* nNewCompNumber: for non-recursive DFS only: */
- + ]
7209 : : {
7210 : 0 : goto exit_function;
7211 : : }
7212 : :
7213 : : /*printf("\nnum_at = %d\n", num_at);*/
7214 : :
7215 : : /* Mark and count; avoid deep DFS recursion: it may make verifying software unhappy */
7216 : : /* nNewCompNumber[i] will contain new component number for atoms at[i], i=0..num_at-1 */
7217 : :
7218 [ + + ]: 697 : for (j = 0; j < num_at; j++)
7219 : : {
7220 [ + + ]: 641 : if (!nNewCompNumber[j])
7221 : : {
7222 : : /* mark starting with at[j] */
7223 : 71 : fst_at = 0;
7224 : 71 : nxt_at = 0;
7225 : 71 : cur_at = j;
7226 : 71 : cur_neq_fst = 1;
7227 : 71 : num_components++;
7228 : :
7229 : : /* first time at at[j] */
7230 : 71 : fst_at = cur_at;
7231 : 71 : nNewCompNumber[fst_at] = (AT_NUMB)num_components;
7232 : :
7233 : : /* find next neighbor */
7234 : : do
7235 : : {
7236 [ + + ]: 1855 : if (iNeigh[cur_at] < at[cur_at].valence)
7237 : : {
7238 : 1214 : int ineigh_incr = (int)iNeigh[cur_at];
7239 : 1214 : nxt_at = at[cur_at].neighbor[ineigh_incr];
7240 : 1214 : iNeigh[cur_at]++;
7241 : :
7242 [ + + ]: 1214 : if (!nNewCompNumber[nxt_at])
7243 : : {
7244 : : /* forward edge: found new atom */
7245 : 570 : nNewCompNumber[nxt_at] = (AT_NUMB)num_components;
7246 : 570 : nPrevAtom[nxt_at] = (AT_NUMB)cur_at;
7247 : 570 : cur_at = nxt_at;
7248 : : }
7249 : : }
7250 [ + + ]: 641 : else if (cur_at == fst_at)
7251 : : {
7252 : 71 : cur_neq_fst = 0;
7253 : : /* break; done */
7254 : : }
7255 : : else
7256 : : {
7257 : 570 : cur_at = nPrevAtom[cur_at]; /* retract */
7258 : : }
7259 [ + + ]: 1855 : } while (cur_neq_fst);
7260 : : }
7261 : : }
7262 : :
7263 [ + - ]: 56 : inchi_free(nPrevAtom);
7264 : 56 : nPrevAtom = NULL;
7265 [ + - ]: 56 : inchi_free(iNeigh);
7266 : 56 : iNeigh = NULL;
7267 : :
7268 : : /* Allocate more memory */
7269 : 56 : i = inchi_max(num_components, orig_at_data->num_components);
7270 : :
7271 : 56 : nCurAtLen = (AT_NUMB *)inchi_calloc((long long)num_components + 1, sizeof(nCurAtLen[0])); /* djb-rwth: cast operator added */
7272 : 56 : nOldCompNumber = (AT_NUMB *)inchi_calloc((long long)i + 1, sizeof(nOldCompNumber[0])); /* djb-rwth: cast operator added */
7273 : 56 : component_nbr = (AT_TRIPLE *)inchi_calloc((long long)num_components + 1, sizeof(component_nbr[0])); /* djb-rwth: cast operator added */
7274 : :
7275 [ + - + - : 56 : if (!nCurAtLen || !nOldCompNumber || !component_nbr)
- + ]
7276 : : {
7277 : 0 : goto exit_function;
7278 : : }
7279 : :
7280 : : /* Count atoms per component and renumber the components */
7281 [ + + ]: 127 : for (i = 0; i < num_components; i++)
7282 : : {
7283 : 71 : component_nbr[i][0] = 0; /* number of atoms in the component */
7284 : 71 : component_nbr[i][1] = i; /* component ordering number */
7285 : : }
7286 : :
7287 [ + + ]: 697 : for (j = 0; j < num_at; j++)
7288 : : {
7289 : 641 : component_nbr[(int)nNewCompNumber[j] - 1][0]++; /* count atoms in each component */
7290 : : }
7291 : :
7292 : : /* Sort settings
7293 : : key: number of atoms
7294 : : order: descending
7295 : : stable sort
7296 : : */
7297 : :
7298 : 56 : qsort( (void*) component_nbr[0], num_components, sizeof( component_nbr[0] ), cmp_components ); /* djb-rwth: fixed buffer overrun */
7299 : :
7300 : : /* Invert the transposition */
7301 [ + + ]: 127 : for (i = 0; i < num_components; i++)
7302 : : {
7303 : 71 : nCurAtLen[i] = component_nbr[i][0];
7304 : 71 : component_nbr[component_nbr[i][1]][2] = i + 1;
7305 : : }
7306 : :
7307 : : /* Renumber the components so that the component with the greatest number of atoms is the first */
7308 : 56 : no_component = num_at + 1;
7309 : :
7310 [ + + ]: 697 : for (j = 0; j < num_at; j++)
7311 : : {
7312 : : /* new component number for at[j] */
7313 : 641 : new_comp_no = component_nbr[(int)nNewCompNumber[j] - 1][2] - 1; /* starts from 0 */
7314 [ + + ]: 641 : if (bProcessOldCompNumbers)
7315 : : {
7316 : : /* old component number for at[j] */
7317 : 11 : old_comp_no = at[j].component;
7318 : : /* fill out nOldCompNumber[]; initially it contains zeroes */
7319 [ - + ]: 11 : if (!old_comp_no)
7320 : : {
7321 : 0 : nOldCompNumber[new_comp_no] = no_component; /* atom did not have component number */
7322 : : }
7323 [ + + ]: 11 : else if (nOldCompNumber[new_comp_no] != old_comp_no)
7324 : : {
7325 [ + - ]: 3 : if (!nOldCompNumber[new_comp_no])
7326 : : {
7327 : 3 : nOldCompNumber[new_comp_no] = old_comp_no;
7328 : : }
7329 : : else
7330 : : {
7331 : : /* at[j] moved from old comp #old_comp_no to old comp #nOldCompNumber[new_comp_no]
7332 : : Both components cannot be equal to any current component */
7333 : 0 : another_comp_no = nOldCompNumber[new_comp_no];
7334 [ # # ]: 0 : for (i = 0; i < num_components; i++)
7335 : : {
7336 [ # # ]: 0 : if (nOldCompNumber[i] == old_comp_no ||
7337 [ # # ]: 0 : nOldCompNumber[i] == another_comp_no)
7338 : : {
7339 : 0 : nOldCompNumber[i] = no_component;
7340 : : }
7341 : : }
7342 : : /* nOldCompNumber[new_comp_no] = num_at+1; */
7343 : : }
7344 : : }
7345 : : }
7346 : :
7347 : : /* orig_at_data->nOldCompNumber */
7348 : :
7349 : : /* Finally, set the new component number for atom j (NB: starts from 1 ) */
7350 : 641 : at[j].component = new_comp_no + 1;
7351 : : }
7352 : :
7353 [ + + ]: 56 : if (bProcessOldCompNumbers)
7354 : : {
7355 [ + + ]: 4 : for (j = 0; j < num_components; j++)
7356 : : {
7357 [ - + ]: 3 : if (nOldCompNumber[j] == no_component)
7358 : : {
7359 : : /* the component has atom from another component */
7360 : 0 : nOldCompNumber[j] = 0;
7361 : : }
7362 [ + - ]: 3 : else if (nOldCompNumber[j] &&
7363 [ + - ]: 3 : !orig_at_data->nOldCompNumber[nOldCompNumber[j] - 1])
7364 : : {
7365 : : /* the component has changed in the previous processing */
7366 : 3 : nOldCompNumber[j] = 0;
7367 : : }
7368 : : }
7369 : : }
7370 : : else
7371 : : {
7372 [ + + ]: 123 : for (j = 0; j < num_components; j++)
7373 : : {
7374 : 68 : nOldCompNumber[j] = j + 1;
7375 : : }
7376 : : }
7377 : :
7378 : 56 : ret = num_components;
7379 : :
7380 : 56 : exit_function:
7381 : :
7382 [ + - ]: 56 : if (nNewCompNumber)
7383 : : {
7384 [ + - ]: 56 : inchi_free(nNewCompNumber);
7385 : : }
7386 [ + - ]: 56 : if (component_nbr)
7387 : : {
7388 [ + - ]: 56 : inchi_free(component_nbr);
7389 : : }
7390 : :
7391 [ - + ]: 56 : if (ret < 0)
7392 : : {
7393 [ # # ]: 0 : if (nPrevAtom)
7394 : : {
7395 [ # # ]: 0 : inchi_free(nPrevAtom);
7396 : 0 : nPrevAtom = NULL;
7397 : : }
7398 [ # # ]: 0 : if (iNeigh)
7399 : : {
7400 [ # # ]: 0 : inchi_free(iNeigh);
7401 : 0 : iNeigh = NULL;
7402 : : }
7403 [ # # ]: 0 : if (nCurAtLen)
7404 : : {
7405 [ # # ]: 0 : inchi_free(nCurAtLen);
7406 : 0 : nCurAtLen = NULL;
7407 : : }
7408 [ # # ]: 0 : if (nOldCompNumber)
7409 : : {
7410 [ # # ]: 0 : inchi_free(nOldCompNumber);
7411 : 0 : nOldCompNumber = NULL;
7412 : : }
7413 : 0 : num_components = ret;
7414 : : }
7415 : :
7416 : : /* avoid memory leaks */
7417 [ + - ]: 56 : if (orig_at_data->nCurAtLen)
7418 : : {
7419 [ + - ]: 56 : inchi_free(orig_at_data->nCurAtLen);
7420 : : }
7421 [ + - ]: 56 : if (orig_at_data->nOldCompNumber)
7422 : : {
7423 [ + - ]: 56 : inchi_free(orig_at_data->nOldCompNumber);
7424 : : }
7425 : :
7426 : 56 : orig_at_data->nCurAtLen = nCurAtLen;
7427 : 56 : orig_at_data->nOldCompNumber = nOldCompNumber;
7428 : :
7429 : 56 : orig_at_data->num_components = num_components;
7430 : :
7431 : 56 : return ret; /* number of disconnected components;
7432 : : 1=>single connected structure */
7433 : : }
7434 : :
7435 : : /****************************************************************************
7436 : : Extract one (connected) component
7437 : : ****************************************************************************/
7438 : 69 : int ExtractConnectedComponent(inp_ATOM *at,
7439 : : int num_at,
7440 : : int component_number,
7441 : : inp_ATOM *component_at)
7442 : : {
7443 : : int i, j, num_component_at;
7444 : : AT_NUMB *number;
7445 : :
7446 [ - + ]: 69 : if (NULL == (number = (AT_NUMB *)inchi_calloc(num_at, sizeof(AT_NUMB))))
7447 : : {
7448 : 0 : return CT_OUT_OF_RAM; /* out of memory */ /* <BRKPT> */
7449 : : }
7450 : :
7451 : : /* copy atoms */
7452 [ + + ]: 1122 : for (i = 0, num_component_at = 0; i < num_at; i++)
7453 : : {
7454 [ + + ]: 1053 : if (at[i].component == component_number)
7455 : : {
7456 : 619 : number[i] = num_component_at;
7457 : 619 : component_at[num_component_at++] = at[i];
7458 : : }
7459 : : }
7460 : :
7461 : : /* renumber neighbors */
7462 [ + + ]: 688 : for (i = 0; i < num_component_at; i++)
7463 : : {
7464 : 619 : component_at[i].orig_compt_at_numb = (AT_NUMB)(i + 1);
7465 [ + + ]: 1753 : for (j = 0; j < component_at[i].valence; j++)
7466 : : {
7467 : 1134 : component_at[i].neighbor[j] = number[(int)component_at[i].neighbor[j]];
7468 : : }
7469 : : }
7470 : :
7471 [ + - ]: 69 : inchi_free(number);
7472 : :
7473 : 69 : return num_component_at;
7474 : : }
7475 : :
7476 : : /****************************************************************************/
7477 : 69 : int SetConnectedComponentNumber(inp_ATOM *at, int num_at, int component_number)
7478 : : {
7479 : : int i;
7480 [ + + ]: 688 : for (i = 0; i < num_at; i++)
7481 : : {
7482 : 619 : at[i].component = (AT_NUMB)component_number;
7483 : : }
7484 : :
7485 : 69 : return 0;
7486 : : }
7487 : :
7488 : : /****************************************************************************/
7489 : 138 : int Free_INChI_Stereo(INChI_Stereo *pINChI_Stereo)
7490 : : {
7491 [ + + ]: 138 : if (pINChI_Stereo)
7492 : : {
7493 [ + - + - ]: 69 : qzfree(pINChI_Stereo->nNumber);
7494 [ + - + - ]: 69 : qzfree(pINChI_Stereo->t_parity);
7495 [ + - + - ]: 69 : qzfree(pINChI_Stereo->nNumberInv);
7496 [ + - + - ]: 69 : qzfree(pINChI_Stereo->t_parityInv);
7497 [ + + + - ]: 69 : qzfree(pINChI_Stereo->nBondAtom1);
7498 [ + + + - ]: 69 : qzfree(pINChI_Stereo->nBondAtom2);
7499 [ + + + - ]: 69 : qzfree(pINChI_Stereo->b_parity);
7500 : : }
7501 : :
7502 : 138 : return 0;
7503 : : }
7504 : :
7505 : : /****************************************************************************/
7506 : 69 : INChI_Stereo *Alloc_INChI_Stereo(int num_at, int num_bonds)
7507 : : {
7508 : :
7509 : : INChI_Stereo *pINChI_Stereo = (INChI_Stereo *)
7510 : 69 : inchi_calloc(1, sizeof(INChI_Stereo));
7511 : :
7512 [ + - ]: 69 : if (pINChI_Stereo)
7513 : : {
7514 [ + - ]: 69 : if (num_at &&
7515 [ + - ]: 69 : (pINChI_Stereo->nNumber = (AT_NUMB *)inchi_calloc(num_at, sizeof(pINChI_Stereo->nNumber[0]))) &&
7516 [ + - ]: 69 : (pINChI_Stereo->t_parity = (S_CHAR *)inchi_calloc(num_at, sizeof(pINChI_Stereo->t_parity[0]))) &&
7517 [ + - ]: 69 : (pINChI_Stereo->nNumberInv = (AT_NUMB *)inchi_calloc(num_at, sizeof(pINChI_Stereo->nNumberInv[0]))) &&
7518 [ + - ]: 69 : (pINChI_Stereo->t_parityInv = (S_CHAR *)inchi_calloc(num_at, sizeof(pINChI_Stereo->t_parityInv[0]))))
7519 : : {
7520 : : ;
7521 : : }
7522 [ # # ]: 0 : else if (num_at)
7523 : : {
7524 : 0 : goto out_of_RAM;
7525 : : }
7526 : :
7527 [ + + ]: 69 : if (num_bonds &&
7528 [ + - ]: 64 : (pINChI_Stereo->nBondAtom1 = (AT_NUMB *)inchi_calloc(num_bonds, sizeof(pINChI_Stereo->nBondAtom1[0]))) &&
7529 [ + - ]: 64 : (pINChI_Stereo->nBondAtom2 = (AT_NUMB *)inchi_calloc(num_bonds, sizeof(pINChI_Stereo->nBondAtom2[0]))) &&
7530 [ + - ]: 64 : (pINChI_Stereo->b_parity = (S_CHAR *)inchi_calloc(num_bonds, sizeof(pINChI_Stereo->b_parity[0]))))
7531 : : {
7532 : : ;
7533 : : }
7534 [ - + ]: 5 : else if (num_bonds)
7535 : : {
7536 : 0 : goto out_of_RAM;
7537 : : }
7538 : :
7539 : 69 : return pINChI_Stereo;
7540 : :
7541 : 0 : out_of_RAM:
7542 : :
7543 : 0 : Free_INChI_Stereo(pINChI_Stereo);
7544 [ # # # # ]: 0 : qzfree(pINChI_Stereo);
7545 : : } /* if ( pINChI_Stereo ) */
7546 : :
7547 : 0 : return NULL;
7548 : : }
7549 : :
7550 : : /****************************************************************************/
7551 : 138 : int Free_INChI(INChI **ppINChI)
7552 : : {
7553 : :
7554 : : INChI *pINChI;
7555 : :
7556 [ + + ]: 138 : if ((pINChI = *ppINChI)) /* djb-rwth: addressing LLVM warning */
7557 : : {
7558 : :
7559 : : #if (bREUSE_INCHI == 1)
7560 [ - + ]: 69 : if (pINChI->nRefCount-- > 0)
7561 : 0 : return 1;
7562 : : #endif
7563 : :
7564 : 69 : Free_INChI_Members(pINChI);
7565 [ + - + - ]: 69 : qzfree(pINChI);
7566 : 69 : *ppINChI = NULL;
7567 : : }
7568 : :
7569 : 138 : return 0;
7570 : : }
7571 : :
7572 : : /****************************************************************************/
7573 : 69 : int Free_INChI_Members(INChI *pINChI)
7574 : : {
7575 [ + - ]: 69 : if (pINChI)
7576 : : {
7577 : 69 : Free_INChI_Stereo(pINChI->Stereo);
7578 : 69 : Free_INChI_Stereo(pINChI->StereoIsotopic);
7579 [ + - + - ]: 69 : qzfree(pINChI->nAtom);
7580 [ + - + - ]: 69 : qzfree(pINChI->nConnTable);
7581 [ + - + - ]: 69 : qzfree(pINChI->nTautomer);
7582 [ + - + - ]: 69 : qzfree(pINChI->nNum_H);
7583 [ + - + - ]: 69 : qzfree(pINChI->nNum_H_fixed);
7584 [ - + - - ]: 69 : qzfree(pINChI->IsotopicAtom);
7585 [ - + - - ]: 69 : qzfree(pINChI->IsotopicTGroup);
7586 [ - + - - ]: 69 : qzfree(pINChI->nPossibleLocationsOfIsotopicH);
7587 [ + - + - ]: 69 : qzfree(pINChI->Stereo);
7588 [ - + - - ]: 69 : qzfree(pINChI->StereoIsotopic);
7589 [ + - + - ]: 69 : qzfree(pINChI->szHillFormula);
7590 : : }
7591 : :
7592 : 69 : return 0;
7593 : : }
7594 : :
7595 : : /****************************************************************************/
7596 : 69 : INChI *Alloc_INChI(inp_ATOM *at,
7597 : : int num_at,
7598 : : int *found_num_bonds,
7599 : : int *found_num_isotopic,
7600 : : int nAllocMode)
7601 : : {
7602 : : int i, num_bonds, num_isotopic_atoms;
7603 : : INChI *pINChI;
7604 : 69 : int bIsotopic = (nAllocMode & REQ_MODE_ISO);
7605 : : /* int bTautomeric = (nAllocMode & REQ_MODE_TAUT); */
7606 : :
7607 [ + - ]: 69 : if (num_at <= 0 ||
7608 [ - + ]: 69 : NULL == (pINChI = (INChI *)inchi_calloc(1, sizeof(INChI))))
7609 : : {
7610 : 0 : return NULL;
7611 : : }
7612 : :
7613 [ + + ]: 688 : for (i = 0, num_bonds = 0, num_isotopic_atoms = 0; i < num_at; i++)
7614 : : {
7615 : 619 : num_bonds += at[i].valence;
7616 : : /* if ( bIsotopic ) { */
7617 : 619 : num_isotopic_atoms += (0 != at[i].iso_atw_diff ||
7618 [ + - ]: 619 : !strcmp(at[i].elname, "D") ||
7619 [ + - ]: 619 : !strcmp(at[i].elname, "T") ||
7620 [ + - ]: 619 : at[i].num_iso_H[0] ||
7621 [ + - + - ]: 1857 : at[i].num_iso_H[1] ||
7622 [ - + ]: 619 : at[i].num_iso_H[2]);
7623 : : /* } */
7624 : : }
7625 : 69 : num_bonds /= 2;
7626 : :
7627 : 69 : *found_num_bonds = num_bonds;
7628 : 69 : *found_num_isotopic = num_isotopic_atoms;
7629 : :
7630 [ + - ]: 69 : if ((pINChI->nAtom = (U_CHAR *)inchi_calloc(num_at, sizeof(pINChI->nAtom[0]))) &&
7631 [ + - ]: 69 : (pINChI->nConnTable = (AT_NUMB *)inchi_calloc((long long)num_at + (long long)num_bonds, sizeof(pINChI->nConnTable[0]))) && /* djb-rwth: cast operator added */
7632 [ + - ]: 69 : (pINChI->nTautomer = (AT_NUMB *)inchi_calloc(((3 + INCHI_T_NUM_MOVABLE) * (long long)num_at) / 2 + 1, sizeof(pINChI->nTautomer[0]))) && /* djb-rwth: cast operator added */
7633 [ + - ]: 69 : (pINChI->nNum_H = (S_CHAR *)inchi_calloc(num_at, sizeof(pINChI->nNum_H[0]))) &&
7634 [ + - ]: 69 : (pINChI->nNum_H_fixed = (S_CHAR *)inchi_calloc(num_at, sizeof(pINChI->nNum_H_fixed[0]))))
7635 : : {
7636 : : ;
7637 : : /* nTautomer length: max. number of tautomeric groups is num_at/2
7638 : :
7639 : : 1 word -> number of t-groups
7640 : :
7641 : : each group has:
7642 : :
7643 : : 1 word -> number of endpoints+INCHI_T_NUM_MOVABLE
7644 : : INCHI_T_NUM_MOVABLE words -> number(s) of moveable attachments
7645 : : numbers of endpoints words -> canon. numbers
7646 : :
7647 : : max. occurs if each t-group has 2 atoms (num_at/2 t-groups) and all atoms
7648 : : belong to t-groups (num_at endpoints)
7649 : :
7650 : : Total: 1 + (number of t-groups)*(1+INCHI_T_NUM_MOVABLE) + (number of endpoints) <=
7651 : : 1 + (num_at/2) * (1+INCHI_T_NUM_MOVABLE) + num_at <=
7652 : : 1 + (3+INCHI_T_NUM_MOVABLE)*num_at/2 words.
7653 : : */
7654 : : }
7655 : : else
7656 : : {
7657 : 0 : goto out_of_RAM;
7658 : : }
7659 : :
7660 : 69 : pINChI->szHillFormula = NULL; /* the length is unknown */
7661 : :
7662 [ - + ]: 69 : if (bIsotopic)
7663 : : {
7664 [ # # ]: 0 : if (num_isotopic_atoms &&
7665 [ # # ]: 0 : (pINChI->IsotopicAtom = (INChI_IsotopicAtom *)inchi_calloc(num_isotopic_atoms, sizeof(INChI_IsotopicAtom))) &&
7666 [ # # ]: 0 : (pINChI->IsotopicTGroup = (INChI_IsotopicTGroup *)inchi_calloc(num_isotopic_atoms, sizeof(INChI_IsotopicTGroup))))
7667 : : {
7668 : : ;
7669 : : }
7670 [ # # ]: 0 : else if (num_isotopic_atoms)
7671 : : {
7672 : 0 : goto out_of_RAM;
7673 : : }
7674 [ # # ]: 0 : if (!(pINChI->nPossibleLocationsOfIsotopicH = (AT_NUMB *)inchi_calloc((long long)num_at + 1, sizeof(pINChI->nPossibleLocationsOfIsotopicH[0])))) /* djb-rwth: cast operator added */
7675 : : {
7676 : 0 : goto out_of_RAM;
7677 : : }
7678 : : }
7679 : :
7680 [ - + ]: 69 : if ((pINChI->Stereo = Alloc_INChI_Stereo(num_at, num_bonds)))
7681 : : {
7682 : : ;
7683 : : }
7684 : : else
7685 : : {
7686 : 0 : goto out_of_RAM;
7687 : : }
7688 : :
7689 [ - + ]: 69 : if (bIsotopic)
7690 : : {
7691 [ # # ]: 0 : if ((pINChI->StereoIsotopic = Alloc_INChI_Stereo(num_at, num_bonds)))
7692 : : {
7693 : : ;
7694 : : }
7695 : : else
7696 : : {
7697 : 0 : goto out_of_RAM;
7698 : : }
7699 : : }
7700 : :
7701 : 69 : return pINChI;
7702 : :
7703 : 0 : out_of_RAM:
7704 [ # # ]: 0 : if (pINChI)
7705 : : {
7706 : 0 : Free_INChI(&pINChI);
7707 : : /*
7708 : : inchi_free(pINChI);
7709 : : */
7710 : : }
7711 : :
7712 : 0 : return NULL;
7713 : : }
7714 : :
7715 : : /****************************************************************************/
7716 : 138 : int Free_INChI_Aux(INChI_Aux **ppINChI_Aux)
7717 : : {
7718 : 138 : INChI_Aux *pINChI_Aux = *ppINChI_Aux;
7719 [ + + ]: 138 : if (pINChI_Aux)
7720 : : {
7721 : :
7722 : : #if (bREUSE_INCHI == 1)
7723 [ - + ]: 69 : if (pINChI_Aux->nRefCount-- > 0)
7724 : 0 : return 1;
7725 : : #endif
7726 : :
7727 [ + - + - ]: 69 : qzfree(pINChI_Aux->nOrigAtNosInCanonOrd);
7728 [ - + - - ]: 69 : qzfree(pINChI_Aux->nIsotopicOrigAtNosInCanonOrd);
7729 [ + - + - ]: 69 : qzfree(pINChI_Aux->nOrigAtNosInCanonOrdInv);
7730 [ - + - - ]: 69 : qzfree(pINChI_Aux->nIsotopicOrigAtNosInCanonOrdInv);
7731 [ + - + - ]: 69 : qzfree(pINChI_Aux->szOrigCoord);
7732 [ + - + - ]: 69 : qzfree(pINChI_Aux->OrigInfo);
7733 : : /*
7734 : : qzfree( pINChI_Aux->nOriginalAtomNumber );
7735 : : qzfree( pINChI_Aux->nCanonicalTGroupNumbers );
7736 : : qzfree( pINChI_Aux->nIsotopicCanonicalTGroupNumbers);
7737 : : qzfree( pINChI_Aux->nTautomer );
7738 : : qzfree( pINChI_Aux->nNontautomericCanonicalNumbers );
7739 : : qzfree( pINChI_Aux->nIsotopicCanonicalNumbers );
7740 : : qzfree( pINChI_Aux->nNontautomericIsotopicCanonicalNumbers );
7741 : : qzfree( pINChI_Aux->nNontautomericEquNumbers );
7742 : : qzfree( pINChI_Aux->nNontautomericIsotopicEquNumbers );
7743 : : */
7744 [ + - + - ]: 69 : qzfree(pINChI_Aux->nConstitEquNumbers);
7745 [ + + + - ]: 69 : qzfree(pINChI_Aux->nConstitEquTGroupNumbers);
7746 [ - + - - ]: 69 : qzfree(pINChI_Aux->nConstitEquIsotopicNumbers);
7747 [ - + - - ]: 69 : qzfree(pINChI_Aux->nConstitEquIsotopicTGroupNumbers);
7748 [ + - + - ]: 69 : qzfree(pINChI_Aux);
7749 : 69 : *ppINChI_Aux = NULL;
7750 : : }
7751 : :
7752 : 138 : return 0;
7753 : : }
7754 : :
7755 : : /****************************************************************************/
7756 : 69 : INChI_Aux *Alloc_INChI_Aux(int num_at,
7757 : : int num_isotopic_atoms,
7758 : : int nAllocMode,
7759 : : int bOrigCoord)
7760 : : {
7761 : : INChI_Aux *pINChI_Aux;
7762 : 69 : int bIsotopic = (nAllocMode & REQ_MODE_ISO);
7763 : 69 : int num_at_tg = num_at + num_at / 2;
7764 : : /* int bTautomeric = (nAllocMode & REQ_MODE_TAUT); */
7765 : :
7766 [ + - ]: 69 : if (num_at <= 0 ||
7767 [ - + ]: 69 : NULL == (pINChI_Aux = (INChI_Aux *)inchi_calloc(1, sizeof(INChI_Aux))))
7768 : : {
7769 : 0 : return NULL;
7770 : : }
7771 : :
7772 : 69 : if ((pINChI_Aux->nOrigAtNosInCanonOrd = (AT_NUMB *)
7773 [ + - ]: 69 : inchi_calloc(num_at_tg, sizeof(pINChI_Aux->nOrigAtNosInCanonOrd[0]))) &&
7774 : 69 : (pINChI_Aux->nOrigAtNosInCanonOrdInv = (AT_NUMB *)
7775 [ + - ]: 69 : inchi_calloc(num_at_tg, sizeof(pINChI_Aux->nOrigAtNosInCanonOrd[0]))) &&
7776 : 69 : (pINChI_Aux->nConstitEquNumbers = (AT_NUMB *)
7777 [ + - ]: 69 : inchi_calloc(num_at_tg, sizeof(pINChI_Aux->nConstitEquNumbers[0]))))
7778 : : {
7779 : : ;
7780 : : }
7781 : : else
7782 : : {
7783 : 0 : goto out_of_RAM;
7784 : : }
7785 : :
7786 [ + + ]: 133 : if (num_at > 1 &&
7787 [ + - ]: 64 : (pINChI_Aux->nConstitEquTGroupNumbers = (AT_NUMB *)inchi_calloc((long long)num_at / 2 + 1, sizeof(pINChI_Aux->nConstitEquTGroupNumbers[0])))) /* djb-rwth: cast operator added */
7788 : : {
7789 : : ;
7790 : : }
7791 : : else
7792 : : {
7793 [ - + ]: 5 : if (num_at > 1)
7794 : : {
7795 : 0 : goto out_of_RAM;
7796 : : }
7797 : : }
7798 : :
7799 [ + - ]: 69 : if (num_at > 0)
7800 : : {
7801 : 69 : pINChI_Aux->OrigInfo = (ORIG_INFO *)inchi_calloc(num_at, sizeof(pINChI_Aux->OrigInfo[0]));
7802 [ - + ]: 69 : if (!pINChI_Aux->OrigInfo)
7803 : 0 : goto out_of_RAM;
7804 : : }
7805 : :
7806 [ + - + - ]: 69 : if (bOrigCoord && num_at > 0)
7807 : : {
7808 : 69 : pINChI_Aux->szOrigCoord = (MOL_COORD *)inchi_calloc(num_at, sizeof(pINChI_Aux->szOrigCoord[0]));
7809 [ - + ]: 69 : if (!pINChI_Aux->szOrigCoord)
7810 : 0 : goto out_of_RAM;
7811 : : }
7812 : :
7813 [ - + ]: 69 : if (bIsotopic)
7814 : : {
7815 : 0 : if (/*num_isotopic_atoms &&*/
7816 [ # # ]: 0 : (pINChI_Aux->nIsotopicOrigAtNosInCanonOrd = (AT_NUMB *)inchi_calloc(num_at_tg, sizeof(pINChI_Aux->nIsotopicOrigAtNosInCanonOrd[0]))) &&
7817 [ # # ]: 0 : (pINChI_Aux->nIsotopicOrigAtNosInCanonOrdInv = (AT_NUMB *)inchi_calloc(num_at_tg, sizeof(pINChI_Aux->nIsotopicOrigAtNosInCanonOrd[0]))) &&
7818 [ # # ]: 0 : (pINChI_Aux->nConstitEquIsotopicNumbers = (AT_NUMB *)inchi_calloc(num_at_tg, sizeof(pINChI_Aux->nConstitEquIsotopicNumbers[0]))))
7819 : : {
7820 : : ;
7821 : : }
7822 [ # # ]: 0 : else if (num_isotopic_atoms)
7823 : : {
7824 : 0 : goto out_of_RAM;
7825 : : }
7826 : :
7827 : 0 : if ( /*num_isotopic_atoms && num_at > 1 &&*/
7828 [ # # ]: 0 : (pINChI_Aux->nConstitEquIsotopicTGroupNumbers = (AT_NUMB *)inchi_calloc((long long)num_at / 2 + 1, sizeof(pINChI_Aux->nConstitEquIsotopicTGroupNumbers[0])))) /* djb-rwth: cast operator added */
7829 : : {
7830 : : ;
7831 : : }
7832 [ # # # # ]: 0 : else if (num_isotopic_atoms && num_at > 1)
7833 : : {
7834 : 0 : goto out_of_RAM;
7835 : : }
7836 : : }
7837 : :
7838 : 69 : return pINChI_Aux;
7839 : :
7840 : 0 : out_of_RAM:
7841 : :
7842 [ # # ]: 0 : if (pINChI_Aux)
7843 : : {
7844 : 0 : Free_INChI_Aux(&pINChI_Aux);
7845 : : /*
7846 : : inchi_free(pINChI_Aux);
7847 : : */
7848 : : }
7849 : :
7850 : 0 : return NULL;
7851 : : }
7852 : :
7853 : : /****************************************************************************
7854 : : Note that orig_num, curr_num are allocd by caller as (n+1)-long lists
7855 : : ****************************************************************************/
7856 : 0 : void CompAtomData_GetNumMapping(COMP_ATOM_DATA *adata, int *orig_num, int *curr_num)
7857 : : {
7858 : : int i;
7859 [ # # # # ]: 0 : if (!orig_num || !curr_num)
7860 : : {
7861 : 0 : return;
7862 : : }
7863 [ # # ]: 0 : for (i = 0; i < adata->num_at; i++)
7864 : : {
7865 : 0 : int orig = adata->at[i].orig_at_number;
7866 : 0 : orig_num[i] = orig; /* orig's are from 1 */
7867 : 0 : curr_num[orig] = i; /* curr's are from 0 */
7868 : : }
7869 : : }
7870 : :
7871 : : /****************************************************************************
7872 : : Allocate integer matrix [mxn]
7873 : : ****************************************************************************/
7874 : 0 : int imat_new(int m, int n, int ***a)
7875 : : {
7876 : : int i;
7877 [ # # # # ]: 0 : if (m == 0 || n == 0)
7878 : : {
7879 : 0 : return 0;
7880 : : }
7881 [ # # ]: 0 : if (*a)
7882 : : {
7883 : 0 : imat_free(m, *a);
7884 : 0 : *a = NULL;
7885 : : }
7886 : 0 : *a = (int **)inchi_calloc(m, sizeof(int *));
7887 [ # # ]: 0 : if (NULL == *a)
7888 : : {
7889 : 0 : return 1;
7890 : : }
7891 [ # # ]: 0 : for (i = 0; i < m; i++)
7892 : : {
7893 : 0 : (*a)[i] = (int *)inchi_calloc(n, sizeof(int));
7894 [ # # ]: 0 : if (NULL == (*a)[i])
7895 : : {
7896 : 0 : return 1;
7897 : : }
7898 : : }
7899 : 0 : return 0;
7900 : : }
7901 : :
7902 : : /****************************************************************************
7903 : : Free integer matrix [mxn]
7904 : : ****************************************************************************/
7905 : 0 : void imat_free(int m, int **a)
7906 : : {
7907 : : int i;
7908 [ # # ]: 0 : if (NULL != a)
7909 : : {
7910 [ # # ]: 0 : for (i = 0; i < m; i++)
7911 : : {
7912 [ # # ]: 0 : if (NULL != a[i]) /* djb-rwth: unresolved issue -- revision required? -- false positive as this function just does the clean-up job */
7913 : : {
7914 [ # # ]: 0 : inchi_free(a[i]);
7915 : : }
7916 : : }
7917 [ # # ]: 0 : inchi_free(a);
7918 : 0 : a = NULL;
7919 : : }
7920 : :
7921 : 0 : return;
7922 : : }
7923 : :
7924 : : /*
7925 : : Lt-wt subgraph
7926 : : */
7927 : :
7928 : : /****************************************************************************
7929 : : Establish light-weight subgraph representing (part of) orig_inp_data
7930 : : ****************************************************************************/
7931 : 0 : subgraf *subgraf_new(ORIG_ATOM_DATA *orig_inp_data,
7932 : : int nnodes,
7933 : : int *nodes)
7934 : : {
7935 : 0 : int i, j, iat, nbr, jat, nj, degree, nat, err = 0;
7936 : :
7937 : 0 : subgraf *sg = (subgraf *)inchi_calloc(1, sizeof(subgraf));
7938 [ # # ]: 0 : if (!sg)
7939 : : {
7940 : 0 : return NULL;
7941 : : }
7942 : :
7943 : 0 : nat = orig_inp_data->num_inp_atoms;
7944 : :
7945 : : /* orig2node is mapping of original at numbers --> subgraph node numbers */
7946 : 0 : err = 1;
7947 [ # # ]: 0 : if (!(sg->orig2node = (int *)inchi_calloc((long long)nat + 1, sizeof(int)))) /* djb-rwth: cast operator added */
7948 : : {
7949 : 0 : goto exit_function;
7950 : : }
7951 [ # # ]: 0 : if (!(sg->nodes = (int *)inchi_calloc(nnodes, sizeof(int))))
7952 : : {
7953 : 0 : goto exit_function;
7954 : : }
7955 [ # # ]: 0 : if (!(sg->degrees = (int *)inchi_calloc(nnodes, sizeof(int))))
7956 : : {
7957 : 0 : goto exit_function;
7958 : : }
7959 : : /* NB: input list of 'nodes' is assumed to be in 'original_atom_numbering domain' which starts from 1.
7960 : : Now it is mapped to current atom numbers which starts from 0/connections using at[j].orig_at_number */
7961 : 0 : sg->nnodes = 0;
7962 [ # # ]: 0 : for (i = 0; i < nnodes; i++)
7963 : : {
7964 : 0 : sg->nodes[sg->nnodes++] = nodes[i];
7965 : : }
7966 : :
7967 [ # # ]: 0 : for (i = 0; i <= nat; i++)
7968 : : {
7969 : 0 : sg->orig2node[i] = -1;
7970 : : }
7971 [ # # ]: 0 : for (i = 0; i < nnodes; i++)
7972 : : {
7973 : 0 : sg->orig2node[sg->nodes[i]] = i;
7974 : : }
7975 : :
7976 : : /* Create and fill subgraph adjacency matrix based on nodes/orig atom numbers
7977 : : and connections stored in orig_inp_data */
7978 : 0 : sg->adj = (subgraf_edge **)inchi_calloc(nnodes, sizeof(subgraf_edge *));
7979 [ # # ]: 0 : if (!sg->adj)
7980 : : {
7981 : 0 : goto exit_function;
7982 : : }
7983 : :
7984 [ # # ]: 0 : for (i = 0; i < sg->nnodes; i++)
7985 : : {
7986 : 0 : iat = nodes[i] - 1; /* current atom number for this node */
7987 : 0 : degree = orig_inp_data->at[iat].valence;
7988 : 0 : nj = -1;
7989 : 0 : sg->adj[i] = (subgraf_edge *)inchi_calloc(degree, sizeof(subgraf_edge));
7990 [ # # ]: 0 : if (!sg->adj[i])
7991 : : {
7992 : 0 : goto exit_function;
7993 : : }
7994 [ # # ]: 0 : for (j = 0; j < degree; j++)
7995 : : {
7996 : 0 : jat = orig_inp_data->at[iat].neighbor[j]; /* for curr num jat, a (jat+1) would be an orig num */
7997 : 0 : nbr = sg->orig2node[jat + 1];
7998 [ # # ]: 0 : if (nbr < 0)
7999 : 0 : continue;
8000 : 0 : nj++;
8001 : 0 : sg->adj[i][nj].nbr = nbr;
8002 : 0 : sg->adj[i][nj].etype = orig_inp_data->at[iat].bond_type[j];
8003 : : }
8004 : 0 : sg->degrees[i] = nj + 1;
8005 : : }
8006 : 0 : err = 0;
8007 : :
8008 : : /* subgraf_debug_trace( sg ); */
8009 : :
8010 : 0 : exit_function:
8011 [ # # ]: 0 : if (err)
8012 : : {
8013 : 0 : subgraf_free(sg);
8014 : 0 : return NULL; /* djb-rwth: avoiding reading from freed memory */
8015 : : }
8016 : :
8017 : 0 : return sg;
8018 : : }
8019 : :
8020 : : /****************************************************************************/
8021 : 0 : void subgraf_free(subgraf *sg)
8022 : : {
8023 : : int i;
8024 [ # # ]: 0 : if (!sg)
8025 : : {
8026 : 0 : return;
8027 : : }
8028 [ # # ]: 0 : if (sg->nodes)
8029 : : {
8030 [ # # ]: 0 : inchi_free(sg->nodes);
8031 : : }
8032 [ # # ]: 0 : if (sg->degrees)
8033 : : {
8034 [ # # ]: 0 : inchi_free(sg->degrees);
8035 : : }
8036 [ # # ]: 0 : if (sg->orig2node)
8037 : : {
8038 [ # # ]: 0 : inchi_free(sg->orig2node);
8039 : : }
8040 [ # # ]: 0 : if (sg->adj)
8041 : : {
8042 [ # # ]: 0 : for (i = 0; i < sg->nnodes; i++)
8043 : : {
8044 [ # # ]: 0 : if (sg->adj[i]) /* djb-rwth: unresolved issue -- revision required? -- false positive as this function just does the clean-up job */
8045 : : {
8046 [ # # ]: 0 : inchi_free(sg->adj[i]);
8047 : : }
8048 : : }
8049 [ # # ]: 0 : inchi_free(sg->adj);
8050 : : }
8051 [ # # ]: 0 : inchi_free(sg);
8052 : 0 : sg = NULL;
8053 : :
8054 : 0 : return;
8055 : : }
8056 : :
8057 : : /****************************************************************************/
8058 : 0 : void subgraf_debug_trace(subgraf *sg)
8059 : : {
8060 : : int p, q;
8061 : :
8062 : : ITRACE_("\n\n*********************************************************************\n* Subgraf:");
8063 : : ITRACE_("\n\tNodes: %-d ( ", sg->nnodes);
8064 [ # # ]: 0 : for (p = 0; p < sg->nnodes; p++)
8065 : : {
8066 : : ITRACE_("%-d ", sg->nodes[p]);
8067 : : }
8068 : : ITRACE_(")\n\tAdj lists:\n");
8069 [ # # ]: 0 : for (p = 0; p < sg->nnodes; p++)
8070 : : {
8071 : : ITRACE_("\tNode #%-d (orig# %-d) ::: Neighbors (node#, orig#) : ",
8072 : : p, sg->nodes[p]);
8073 [ # # ]: 0 : for (q = 0; q < sg->degrees[p]; q++)
8074 : : {
8075 : 0 : int nbr = sg->adj[p][q].nbr; /* djb-rwth: ignoring LLVM warning: variable used */
8076 : : ITRACE_("(%-d/%-d/%-d) ", nbr, sg->nodes[nbr]);
8077 : : }
8078 : : ITRACE_("\n");
8079 : : }
8080 : : ITRACE_("\n* End Subgraf\n*********************************************************************\n");
8081 : :
8082 : 0 : return;
8083 : : }
8084 : :
8085 : : /****************************************************************************/
8086 : 0 : subgraf_pathfinder *subgraf_pathfinder_new(subgraf *sg,
8087 : : ORIG_ATOM_DATA *orig_inp_data,
8088 : : int start,
8089 : : int end)
8090 : : {
8091 : 0 : subgraf_pathfinder *spf = NULL;
8092 : :
8093 : 0 : spf = (subgraf_pathfinder *)inchi_calloc(1, sizeof(subgraf_pathfinder));
8094 [ # # ]: 0 : if (!spf)
8095 : : {
8096 : 0 : goto exit_function;
8097 : : }
8098 : :
8099 : 0 : spf->sg = sg;
8100 : 0 : spf->start = start;
8101 : 0 : spf->end = end;
8102 : 0 : spf->nbonds = 0;
8103 : 0 : spf->nseen = 0;
8104 : :
8105 : 0 : spf->seen = (int *)inchi_calloc(spf->sg->nnodes, sizeof(int));
8106 [ # # ]: 0 : if (!spf->seen)
8107 : : {
8108 [ # # ]: 0 : inchi_free(spf);
8109 : 0 : spf = NULL;
8110 : : }
8111 : :
8112 : 0 : exit_function:
8113 : 0 : return spf;
8114 : : }
8115 : :
8116 : : /****************************************************************************/
8117 : 0 : void subgraf_pathfinder_free(subgraf_pathfinder *spf)
8118 : : {
8119 [ # # ]: 0 : if (!spf)
8120 : : {
8121 : 0 : return;
8122 : : }
8123 [ # # ]: 0 : if (spf->seen)
8124 : : {
8125 [ # # ]: 0 : inchi_free(spf->seen);
8126 : : }
8127 [ # # ]: 0 : inchi_free(spf);
8128 : 0 : spf = NULL;
8129 : 0 : return;
8130 : : }
8131 : :
8132 : : /****************************************************************************
8133 : : Find path(s) from subgraf node spf->start to spf->end
8134 : : and fill bonds[nbonds] and atoms[natoms]
8135 : : Do not traverse through supplied forbidden edges (if not zero/NULL)
8136 : : ****************************************************************************/
8137 : 0 : void subgraf_pathfinder_run(subgraf_pathfinder *spf,
8138 : : int nforbidden, /* number of edges forbidden for traversal */
8139 : : int *forbidden, /* nodes of forbidden edges: [edge1node1,edge1node2, edge2node1, edge2node2, ... ] */
8140 : : int *nbonds,
8141 : : int **bonds, /* collect subgraf bonds here */
8142 : : int *natoms,
8143 : : int *atoms /* if not NULL, collect subgraf atoms here */
8144 : : )
8145 : : {
8146 : : int j, k, node, node0;
8147 : : int f, skip;
8148 : :
8149 [ # # ]: 0 : if (spf->nseen < 1)
8150 : : {
8151 : : /* Even at very beginning, push start node to seen and set nseen = 1
8152 : : and put end node into subgraf_pathfinder's end */
8153 : 0 : return;
8154 : : }
8155 : :
8156 : 0 : node0 = spf->seen[spf->nseen - 1];
8157 [ # # ]: 0 : for (j = 0; j < spf->sg->degrees[node0]; j++)
8158 : : {
8159 : 0 : node = spf->sg->adj[node0][j].nbr;
8160 [ # # ]: 0 : if (is_in_the_ilist(spf->seen, node, spf->nseen))
8161 : : {
8162 : 0 : continue;
8163 : : }
8164 [ # # # # ]: 0 : if (nforbidden && forbidden)
8165 : : {
8166 : 0 : skip = 0;
8167 [ # # ]: 0 : for (f = 0; f < nforbidden; f++)
8168 : : {
8169 [ # # ]: 0 : if (bIsSameBond(node0, node, forbidden[2 * f], forbidden[2 * f + 1]))
8170 : : {
8171 : 0 : skip = 1;
8172 : 0 : break;
8173 : : }
8174 : : }
8175 [ # # ]: 0 : if (skip)
8176 : : {
8177 : 0 : continue;
8178 : : }
8179 : : }
8180 [ # # ]: 0 : if (node == spf->end)
8181 : : {
8182 : 0 : spf->seen[spf->nseen++] = node;
8183 : :
8184 : : ITRACE_("\n\tFound path (in orig atom numbers):\t");
8185 [ # # ]: 0 : for (k = 0; k < spf->nseen; k++)
8186 : : {
8187 : 0 : int orig_atnum = spf->sg->nodes[spf->seen[k]];
8188 : : ITRACE_("%-d ", orig_atnum);
8189 [ # # # # ]: 0 : if (atoms && !is_in_the_ilist(atoms, orig_atnum, *natoms))
8190 : : {
8191 : 0 : atoms[(*natoms)++] = orig_atnum;
8192 : : }
8193 : : }
8194 : : ITRACE_("\t( In node nums: ");
8195 [ # # ]: 0 : for (k = 1; k < spf->nseen; k++)
8196 : : {
8197 : 0 : int at1 = spf->seen[k - 1];
8198 : 0 : int at2 = spf->seen[k];
8199 : 0 : add_bond_if_unseen(spf, at1, at2, nbonds, bonds);
8200 : :
8201 : : ITRACE_("%-d ", spf->seen[k]);
8202 : : }
8203 : : ITRACE_(")");
8204 : :
8205 : 0 : spf->seen[spf->nseen - 1] = 0;
8206 : 0 : spf->nseen--; /* pop_back */
8207 : 0 : break;
8208 : : }
8209 : : }
8210 [ # # ]: 0 : for (j = 0; j < spf->sg->degrees[node0]; j++)
8211 : : {
8212 : 0 : node = spf->sg->adj[node0][j].nbr;
8213 [ # # # # ]: 0 : if (node == spf->end || is_in_the_ilist(spf->seen, node, spf->nseen))
8214 : : {
8215 : 0 : continue;
8216 : : }
8217 [ # # # # ]: 0 : if (nforbidden && forbidden)
8218 : : {
8219 : 0 : skip = 0;
8220 [ # # ]: 0 : for (f = 0; f < nforbidden; f++)
8221 : : {
8222 [ # # ]: 0 : if (bIsSameBond(node0, node, forbidden[2 * f], forbidden[2 * f + 1]))
8223 : : {
8224 : 0 : skip = 1;
8225 : 0 : break;
8226 : : }
8227 : : }
8228 [ # # ]: 0 : if (skip)
8229 : : {
8230 : 0 : continue;
8231 : : }
8232 : : }
8233 : 0 : spf->seen[spf->nseen++] = node;
8234 : 0 : subgraf_pathfinder_run(spf, 0, NULL, nbonds, bonds, natoms, atoms);
8235 : 0 : spf->seen[spf->nseen - 1] = 0;
8236 : 0 : spf->nseen--;
8237 : : }
8238 : :
8239 : 0 : return;
8240 : : }
8241 : :
8242 : : /****************************************************************************/
8243 : 0 : void add_bond_if_unseen(subgraf_pathfinder *spf,
8244 : : int node0,
8245 : : int node,
8246 : : int *nbonds,
8247 : : int **bonds)
8248 : : {
8249 : : int seen, p, at1, at2;
8250 : :
8251 : 0 : at1 = spf->sg->nodes[node0];
8252 : 0 : at2 = spf->sg->nodes[node];
8253 : : #if 0
8254 : : if ( at1 > at2 )
8255 : : {
8256 : : int tmp = at1;
8257 : : at1 = at2;
8258 : : at2 = tmp;
8259 : : }
8260 : : #endif
8261 : 0 : seen = 0;
8262 [ # # ]: 0 : for (p = 0; p < *nbonds; p++)
8263 : : {
8264 : : /*if (bonds[p][0] == at1 && bonds[p][1] == at2)*/
8265 [ # # ]: 0 : if (bIsSameBond(at1, at2, bonds[p][0], bonds[p][1]))
8266 : : {
8267 : 0 : seen = 1;
8268 : 0 : break;
8269 : : }
8270 : : }
8271 [ # # ]: 0 : if (!seen)
8272 : : {
8273 : 0 : bonds[*nbonds][0] = at1;
8274 : 0 : bonds[*nbonds][1] = at2;
8275 : 0 : (*nbonds)++;
8276 : : }
8277 : :
8278 : 0 : return;
8279 : : }
8280 : :
8281 : : /****************************************************************************
8282 : : At the first call, push start node to spf->start and set spf->nseen = 0
8283 : : ****************************************************************************/
8284 : 0 : int subgraf_pathfinder_collect_all(subgraf_pathfinder *spf,
8285 : : int nforbidden, /* number of edges forbidden for traversal */
8286 : : int *forbidden, /* nodes of forbidden edges: [edge1node1,edge1node2, edge2node1, edge2node2, ... ] */
8287 : : int *atnums /* 1-based origs# */
8288 : : )
8289 : : {
8290 : : int j, f, node, next_node, skip;
8291 : :
8292 : 0 : node = spf->start;
8293 : 0 : spf->seen[spf->nseen] = node;
8294 : 0 : atnums[spf->nseen] = spf->sg->nodes[node];
8295 : 0 : spf->nseen++;
8296 : :
8297 [ # # ]: 0 : for (j = 0; j < spf->sg->degrees[node]; j++)
8298 : : {
8299 : 0 : next_node = spf->sg->adj[node][j].nbr;
8300 [ # # ]: 0 : if (is_in_the_ilist(spf->seen, next_node, spf->nseen))
8301 : : {
8302 : 0 : continue;
8303 : : }
8304 [ # # # # ]: 0 : if (nforbidden && forbidden)
8305 : : {
8306 : 0 : skip = 0;
8307 [ # # ]: 0 : for (f = 0; f < nforbidden; f++)
8308 : : {
8309 [ # # ]: 0 : if (bIsSameBond(node, next_node, forbidden[2 * f], forbidden[2 * f + 1]))
8310 : : {
8311 : 0 : skip = 1;
8312 : 0 : break;
8313 : : }
8314 : : }
8315 [ # # ]: 0 : if (skip)
8316 : : {
8317 : 0 : continue;
8318 : : }
8319 : : }
8320 : 0 : spf->start = next_node;
8321 : 0 : subgraf_pathfinder_collect_all(spf, nforbidden, forbidden, atnums);
8322 : : }
8323 : :
8324 : 0 : return spf->nseen;
8325 : : }
8326 : :
8327 : : #if (FIX_ADJ_RAD == 1)
8328 : :
8329 : : /****************************************************************************/
8330 : : int FixNextRadicals(int cur_at, inp_ATOM *at);
8331 : : int FixNextRadicals(int cur_at, inp_ATOM *at)
8332 : : {
8333 : : int j, neigh, num_found = 0;
8334 : :
8335 : : for (j = 0; j < at[cur_at].valence; j++)
8336 : : {
8337 : : neigh = at[cur_at].neighbor[j];
8338 : : if (at[neigh].radical == RADICAL_DOUBLET)
8339 : : {
8340 : : at[neigh].radical = 0;
8341 : : num_found++;
8342 : : num_found += FixNextRadicals(neigh, at);
8343 : : }
8344 : : }
8345 : :
8346 : : return num_found;
8347 : : }
8348 : :
8349 : : /****************************************************************************/
8350 : : int FixAdjacentRadicals(int num_inp_atoms, inp_ATOM *at)
8351 : : {
8352 : : int i, j;
8353 : : char *bVisited = NULL;
8354 : : int nNumFound = 0, neigh, cur_found;
8355 : :
8356 : : for (i = 0; i < num_inp_atoms; i++)
8357 : : {
8358 : : if (at[i].radical == RADICAL_DOUBLET)
8359 : : {
8360 : : cur_found = 1;
8361 : : for (j = 0; j < at[i].valence; j++)
8362 : : {
8363 : : neigh = at[i].neighbor[j];
8364 : : if (at[neigh].radical == RADICAL_DOUBLET)
8365 : : {
8366 : : cur_found++;
8367 : : }
8368 : : }
8369 : : if (cur_found >= 3)
8370 : : {
8371 : : nNumFound++;
8372 : : at[i].radical = 0;
8373 : : nNumFound += FixNextRadicals(i, at);
8374 : : }
8375 : : }
8376 : : }
8377 : :
8378 : : return nNumFound;
8379 : : }
8380 : :
8381 : : #endif
8382 : :
8383 : : #ifdef COMPILE_ANSI_ONLY
8384 : :
8385 : : #ifndef TARGET_API_LIB
8386 : : /*
8387 : : #include <stdio.h>
8388 : : #include "inpdef.h"
8389 : : */
8390 : :
8391 : : /****************************************************************************/
8392 : : void PrintFileName(const char *fmt,
8393 : : FILE *out_file,
8394 : : /* INCHI_IOSTREAM *out_file, */
8395 : : const char *szFname)
8396 : : {
8397 : : inchi_print_nodisplay(out_file, fmt, szFname);
8398 : : }
8399 : : #endif
8400 : :
8401 : : #endif
|