RDKit
Open-source cheminformatics and machine learning.
Loading...
Searching...
No Matches
hanoiSort.h
Go to the documentation of this file.
1//
2// Copyright (C) 2014 Greg Landrum
3// Adapted from pseudo-code from Roger Sayle
4//
5// @@ All Rights Reserved @@
6// This file is part of the RDKit.
7// The contents are covered by the terms of the BSD license
8// which is included in the file license.txt, found at the root
9// of the RDKit source tree.
10//
11
12#include <RDGeneral/export.h>
13#ifndef HANOISORT_H_
14#define HANOISORT_H_
15
16#include <cstring>
17#include <cassert>
18#include <cstdlib>
19
20#if defined(_MSC_VER)
21#pragma warning(push, 1)
22#pragma warning(disable : 4800)
23#endif
24namespace RDKit {
25template <typename CompareFunc>
26bool hanoi(int *base, int nel, int *temp, int *count, int *changed,
27 CompareFunc compar) {
28 assert(base);
29 assert(temp);
30 assert(count);
31 assert(changed);
32 // std::cerr<<" hanoi: "<<nel<< " start " << (*base)+1 << std::endl;
33 int *b1, *b2;
34 int *t1, *t2;
35 int *s1, *s2;
36 int n1, n2;
37 int result;
38 int *ptr;
39
40 if (nel == 1) {
41 count[base[0]] = 1;
42 return false;
43 } else if (nel == 2) {
44 n1 = base[0];
45 n2 = base[1];
46 int stat =
47 (/*!changed || */ changed[n1] || changed[n2]) ? compar(n1, n2) : 0;
48 if (stat == 0) {
49 count[n1] = 2;
50 count[n2] = 0;
51 return false;
52 } else if (stat < 0) {
53 count[n1] = 1;
54 count[n2] = 1;
55 return false;
56 } else /* stat > 0 */ {
57 count[n1] = 1;
58 count[n2] = 1;
59 base[0] = n2; /* temp[0] = n2; */
60 base[1] = n1; /* temp[1] = n1; */
61 return false; /* return True; */
62 }
63 }
64
65 n1 = nel / 2;
66 n2 = nel - n1;
67 b1 = base;
68 t1 = temp;
69 b2 = base + n1;
70 t2 = temp + n1;
71
72 if (hanoi(b1, n1, t1, count, changed, compar)) {
73 if (hanoi(b2, n2, t2, count, changed, compar)) {
74 s2 = t2;
75 } else {
76 s2 = b2;
77 }
78 result = false;
79 ptr = base;
80 s1 = t1;
81 } else {
82 if (hanoi(b2, n2, t2, count, changed, compar)) {
83 s2 = t2;
84 } else {
85 s2 = b2;
86 }
87 result = true;
88 ptr = temp;
89 s1 = b1;
90 }
91
92 while (true) {
93 assert(*s1 != *s2);
94 int stat =
95 (/*!changed || */ changed[*s1] || changed[*s2]) ? compar(*s1, *s2) : 0;
96 int len1 = count[*s1];
97 int len2 = count[*s2];
98 assert(len1 > 0);
99 assert(len2 > 0);
100 if (stat == 0) {
101 count[*s1] = len1 + len2;
102 count[*s2] = 0;
103 memmove(ptr, s1, len1 * sizeof(int));
104 ptr += len1;
105 n1 -= len1;
106 if (n1 == 0) {
107 if (ptr != s2) {
108 memmove(ptr, s2, n2 * sizeof(int));
109 }
110 return result;
111 }
112 s1 += len1;
113
114 // std::cerr<<" cpy: "<<*s1<<" "<<*s2<<" "<<len2<<std::endl;
115 memmove(ptr, s2, len2 * sizeof(int));
116 ptr += len2;
117 n2 -= len2;
118 if (n2 == 0) {
119 memmove(ptr, s1, n1 * sizeof(int));
120 return result;
121 }
122 s2 += len2;
123 } else if (stat < 0 && len1 > 0) {
124 memmove(ptr, s1, len1 * sizeof(int));
125 ptr += len1;
126 n1 -= len1;
127 if (n1 == 0) {
128 if (ptr != s2) {
129 memmove(ptr, s2, n2 * sizeof(int));
130 }
131 return result;
132 }
133 s1 += len1;
134 } else if (stat > 0 && len2 > 0) /* stat > 0 */ {
135 memmove(ptr, s2, len2 * sizeof(int));
136 ptr += len2;
137 n2 -= len2;
138 if (n2 == 0) {
139 memmove(ptr, s1, n1 * sizeof(int));
140 return result;
141 }
142 s2 += len2;
143 } else {
144 assert(0);
145 }
146 }
147}
148
149template <typename CompareFunc>
150void hanoisort(int *base, int nel, int *count, int *changed,
151 CompareFunc compar) {
152 assert(base);
153 int *temp = (int *)malloc(nel * sizeof(int));
154 assert(temp);
155 if (hanoi(base, nel, temp, count, changed, compar)) {
156 memmove(base, temp, nel * sizeof(int));
157 }
158 free(temp);
159}
160} // namespace RDKit
161
162#if defined(_MSC_VER)
163#pragma warning(pop)
164#endif
165
166#endif /* HANOISORT_H_ */
Std stuff.
bool hanoi(int *base, int nel, int *temp, int *count, int *changed, CompareFunc compar)
Definition hanoiSort.h:26
void hanoisort(int *base, int nel, int *count, int *changed, CompareFunc compar)
Definition hanoiSort.h:150