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-2025 Greg Landrum and other RDKit contributors
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#include <vector>
20#include <span>
21
22#if defined(_MSC_VER)
23#pragma warning(push, 1)
24#pragma warning(disable : 4800)
25#endif
26namespace RDKit {
27namespace detail {
28template <typename CompareFunc>
29bool hanoi(int *base, int nel, int *temp, int *count, int *changed,
30 CompareFunc compar) {
31 assert(base);
32 assert(temp);
33 assert(count);
34 assert(changed);
35 // std::cerr<<" hanoi: "<<nel<< " start " << (*base)+1 << std::endl;
36 int *b1, *b2;
37 int *t1, *t2;
38 int *s1, *s2;
39 int n1, n2;
40 int result;
41 int *ptr;
42
43 if (nel == 1) {
44 count[base[0]] = 1;
45 return false;
46 } else if (nel == 2) {
47 n1 = base[0];
48 n2 = base[1];
49 int stat =
50 (/*!changed || */ changed[n1] || changed[n2]) ? compar(n1, n2) : 0;
51 if (stat == 0) {
52 count[n1] = 2;
53 count[n2] = 0;
54 return false;
55 } else if (stat < 0) {
56 count[n1] = 1;
57 count[n2] = 1;
58 return false;
59 } else /* stat > 0 */ {
60 count[n1] = 1;
61 count[n2] = 1;
62 base[0] = n2; /* temp[0] = n2; */
63 base[1] = n1; /* temp[1] = n1; */
64 return false; /* return True; */
65 }
66 }
67
68 n1 = nel / 2;
69 n2 = nel - n1;
70 b1 = base;
71 t1 = temp;
72 b2 = base + n1;
73 t2 = temp + n1;
74
75 if (hanoi(b1, n1, t1, count, changed, compar)) {
76 if (hanoi(b2, n2, t2, count, changed, compar)) {
77 s2 = t2;
78 } else {
79 s2 = b2;
80 }
81 result = false;
82 ptr = base;
83 s1 = t1;
84 } else {
85 if (hanoi(b2, n2, t2, count, changed, compar)) {
86 s2 = t2;
87 } else {
88 s2 = b2;
89 }
90 result = true;
91 ptr = temp;
92 s1 = b1;
93 }
94
95 while (true) {
96 assert(*s1 != *s2);
97 int stat =
98 (/*!changed || */ changed[*s1] || changed[*s2]) ? compar(*s1, *s2) : 0;
99 int len1 = count[*s1];
100 int len2 = count[*s2];
101 assert(len1 > 0);
102 assert(len2 > 0);
103 if (stat == 0) {
104 count[*s1] = len1 + len2;
105 count[*s2] = 0;
106 memmove(ptr, s1, len1 * sizeof(int));
107 ptr += len1;
108 n1 -= len1;
109 if (n1 == 0) {
110 if (ptr != s2) {
111 memmove(ptr, s2, n2 * sizeof(int));
112 }
113 return result;
114 }
115 s1 += len1;
116
117 // std::cerr<<" cpy: "<<*s1<<" "<<*s2<<" "<<len2<<std::endl;
118 memmove(ptr, s2, len2 * sizeof(int));
119 ptr += len2;
120 n2 -= len2;
121 if (n2 == 0) {
122 memmove(ptr, s1, n1 * sizeof(int));
123 return result;
124 }
125 s2 += len2;
126 } else if (stat < 0 && len1 > 0) {
127 memmove(ptr, s1, len1 * sizeof(int));
128 ptr += len1;
129 n1 -= len1;
130 if (n1 == 0) {
131 if (ptr != s2) {
132 memmove(ptr, s2, n2 * sizeof(int));
133 }
134 return result;
135 }
136 s1 += len1;
137 } else if (stat > 0 && len2 > 0) /* stat > 0 */ {
138 memmove(ptr, s2, len2 * sizeof(int));
139 ptr += len2;
140 n2 -= len2;
141 if (n2 == 0) {
142 memmove(ptr, s1, n1 * sizeof(int));
143 return result;
144 }
145 s2 += len2;
146 } else {
147 assert(0);
148 }
149 }
150}
151} // namespace detail
152template <typename CompareFunc>
153[[deprecated("Use the overload that takes std::span and std::vector instead")]]
154void hanoisort(int *base, int nel, int *count, int *changed,
155 CompareFunc compar) {
156 assert(base);
157 std::vector<int> tempVec(nel);
158 if (detail::hanoi(base, nel, tempVec.data(), count, changed, compar)) {
159 memmove(base, tempVec.data(), nel * sizeof(int));
160 }
161}
162template <typename CompareFunc>
163void hanoisort(std::span<int> &base, std::vector<int> &count,
164 std::vector<int> &changed, CompareFunc compar) {
165 std::vector<int> tempVec(base.size());
166 if (detail::hanoi(base.data(), base.size(), tempVec.data(), count.data(),
167 changed.data(), compar)) {
168 std::copy(tempVec.begin(), tempVec.end(), base.begin());
169 }
170}
171} // namespace RDKit
172
173#if defined(_MSC_VER)
174#pragma warning(pop)
175#endif
176
177#endif /* HANOISORT_H_ */
bool hanoi(int *base, int nel, int *temp, int *count, int *changed, CompareFunc compar)
Definition hanoiSort.h:29
Std stuff.
void hanoisort(int *base, int nel, int *count, int *changed, CompareFunc compar)
Definition hanoiSort.h:154