1 /* BurrTools
2 *
3 * BurrTools is the legal property of its developers, whose
4 * names are listed in the COPYRIGHT file, which is included
5 * within the source distribution.
6 *
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License
9 * as published by the Free Software Foundation; either version 2
10 * of the License, or (at your option) any later version.
11
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
20 */
21 #include "movementcache.h"
22
23 #include "voxel.h"
24 #include "problem.h"
25
26 #include <string.h>
27
28 /* the hash function. I don't know how well it performs, but it seems to be okay */
moHashValue(unsigned int s1,unsigned int s2,int dx,int dy,int dz,unsigned char t1,unsigned char t2)29 static unsigned int moHashValue(unsigned int s1, unsigned int s2, int dx, int dy, int dz, unsigned char t1, unsigned char t2) {
30 unsigned int val = dx * 0x10101010;
31 val += dy * 0x14814814;
32 val += dz * 0x95145951;
33 val += t1 * 0x1A54941A;
34 val += t2 * 0x5AA59401;
35 val += s1 * 0x01059a04;
36 val += s2 * 0x9af42682;
37 return val;
38 }
39
40 /* double the hash table size and copy the old elements into
41 * the new table
42 */
moRehash(void)43 void movementCache_c::moRehash(void) {
44 unsigned int oldSize = moTableSize;
45
46 /* the new size, roughly twice the old size but odd */
47 moTableSize = 2*moTableSize + 1;
48
49 /* allocate new table */
50 moEntry ** newHash = new moEntry * [moTableSize];
51 memset(newHash, 0, moTableSize * sizeof(moEntry*));
52
53 /* copy the elements */
54 for (unsigned int i = 0; i < oldSize; i++) {
55
56 while (moHash[i]) {
57
58 /* remove from old table */
59 moEntry * e = moHash[i];
60 moHash[i] = e->next;
61
62 /* enter into new one */
63 unsigned int h = moHashValue(e->s1, e->s2, e->dx, e->dy, e->dz, e->t1, e->t2) % moTableSize;
64 e->next = newHash[h];
65 newHash[h] = e;
66 }
67 }
68
69 /* delete the old table and make the new table the current one */
70 delete [] moHash;
71 moHash = newHash;
72 }
73
movementCache_c(const problem_c * puzzle)74 movementCache_c::movementCache_c(const problem_c * puzzle) : gt(puzzle->getGridType()) {
75
76 /* initial table */
77 moTableSize = 101;
78 moHash = new moEntry * [moTableSize];
79 memset(moHash, 0, moTableSize * sizeof(moEntry*));
80 moEntries = 0;
81
82 /* initialize the shape array with the shapes from the
83 * puzzle problem. The shape with transformation 0 is just
84 * a pointer into the puzzle, so don't delete them later on
85 */
86 num_shapes = puzzle->partNumber();
87
88 num_transformations = puzzle->getGridType()->getSymmetries()->getNumTransformations();
89
90 shapes = new const voxel_c ** [num_shapes];
91 for (unsigned int s = 0; s < num_shapes; s++) {
92 shapes[s] = new const voxel_c * [num_transformations];
93 memset(shapes[s], 0, num_transformations * sizeof(voxel_c*));
94 shapes[s][0] = puzzle->getShapeShape(s);
95 }
96
97 /* initialize the piece array */
98 pieces = new unsigned int [puzzle->pieceNumber()];
99
100 int pos = 0;
101
102 for (unsigned int s = 0; s < puzzle->partNumber(); s++)
103 for (unsigned int i = 0; i < puzzle->getShapeMax(s); i++)
104 pieces[pos++] = s;
105
106 }
107
~movementCache_c()108 movementCache_c::~movementCache_c() {
109
110 /* delete the hash nodes */
111 for (unsigned int i = 0; i < moTableSize; i++) {
112
113 while (moHash[i]) {
114 moEntry * e = moHash[i];
115 moHash[i] = e->next;
116
117 delete [] e->move;
118 delete e;
119 }
120 }
121 delete [] moHash;
122
123 /* the shape with transformation 0 is just
124 * a pointer into the puzzle, so don't delete them
125 *
126 * but all the others are created by us, so we free them
127 */
128 for (unsigned int s = 0; s < num_shapes; s++) {
129 for (unsigned int t = 1; t < num_transformations; t++)
130 if (shapes[s][t])
131 delete shapes[s][t];
132 delete [] shapes[s];
133 }
134
135 delete [] shapes;
136 delete [] pieces;
137 }
138
getTransformedShape(unsigned int s,unsigned char t)139 const voxel_c * movementCache_c::getTransformedShape(unsigned int s, unsigned char t) {
140
141 if (!shapes[s][t])
142 {
143 // our required orientation doesn't exist, so we calculate it
144
145 voxel_c * sh = gt->getVoxel(shapes[s][0]);
146 bt_assert2(sh->transform(t));
147
148 // in the single threaded case simply enter our new shape
149 shapes[s][t] = sh;
150 }
151
152 return shapes[s][t];
153 }
154
getMoValue(int dx,int dy,int dz,unsigned char t1,unsigned char t2,unsigned int p1,unsigned int p2,unsigned int * movements)155 void movementCache_c::getMoValue(int dx, int dy, int dz, unsigned char t1, unsigned char t2, unsigned int p1, unsigned int p2, unsigned int * movements)
156 {
157 /* find out the shapes that the pieces have */
158 unsigned int s1 = pieces[p1];
159 unsigned int s2 = pieces[p2];
160
161 unsigned int h = moHashValue(s1, s2, dx, dy, dz, t1, t2);
162
163 moEntry * e = moHash[h % moTableSize];
164
165 /* check the list of nodes in the current hash bucket */
166 while (e && (e->dx != dx || e->dy != dy || e->dz != dz ||
167 e->t1 != t1 || e->t2 != t2 || e->s1 != s1 || e->s2 != s2))
168 e = e->next;
169
170 /* check, if we found the required node */
171 if (!e)
172 {
173 /* no is not found, enter a new node into the table */
174 e = new moEntry;
175 e->dx = dx; e->dy = dy; e->dz = dz;
176 e->t1 = t1; e->t2 = t2;
177 e->s1 = s1; e->s2 = s2;
178 e->move = moCalcValues(getTransformedShape(s1, t1), getTransformedShape(s2, t2), dx, dy, dz);
179
180 if (++moEntries > moTableSize) moRehash();
181
182 e->next = moHash[h % moTableSize];
183 moHash[h % moTableSize] = e;
184 }
185
186 /* return the values */
187 memcpy(movements, e->move, numDirections()*sizeof(unsigned int));
188 }
189