WPBDC 2013.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/ext/WPBDC/WPBDC.c +237 -0
- data/ext/WPBDC/analysis.c +672 -0
- data/ext/WPBDC/bridge.c +288 -0
- data/ext/WPBDC/bridge_cost.c +60 -0
- data/ext/WPBDC/bridge_hash.c +126 -0
- data/ext/WPBDC/bridge_parser.c +1119 -0
- data/ext/WPBDC/bridge_random.c +292 -0
- data/ext/WPBDC/bridge_sketch.c +125 -0
- data/ext/WPBDC/extconf.rb +5 -0
- data/ext/WPBDC/geometry.c +46 -0
- data/ext/WPBDC/internal.h +518 -0
- data/ext/WPBDC/judge.c +563 -0
- data/ext/WPBDC/judge.h +142 -0
- data/ext/WPBDC/loading.c +128 -0
- data/ext/WPBDC/params.c +166 -0
- data/ext/WPBDC/proto.h +98 -0
- data/ext/WPBDC/rc4.c +62 -0
- data/ext/WPBDC/rc4.h +19 -0
- data/ext/WPBDC/rc4_key.c +2 -0
- data/ext/WPBDC/rubydefs.h +75 -0
- data/ext/WPBDC/scenario.c +671 -0
- data/ext/WPBDC/sketch.c +496 -0
- data/ext/WPBDC/sketch.h +51 -0
- data/ext/WPBDC/stdafx.h +11 -0
- data/lib/WPBDC.rb +9 -0
- metadata +71 -0
data/ext/WPBDC/bridge.c
ADDED
@@ -0,0 +1,288 @@
|
|
1
|
+
/*
|
2
|
+
* bridge.c -- Bridges
|
3
|
+
*/
|
4
|
+
|
5
|
+
// Constants and data structures Perl does not need to know about.
|
6
|
+
#include "stdafx.h"
|
7
|
+
#include "internal.h"
|
8
|
+
|
9
|
+
// TBridge initialization values. This must align with declaration!
|
10
|
+
// Set contents of a bridge to known-empty.
|
11
|
+
void init_bridge(TBridge *bridge)
|
12
|
+
{
|
13
|
+
static TBridge constant_init_bridge = INIT_BRIDGE;
|
14
|
+
*bridge = constant_init_bridge;
|
15
|
+
}
|
16
|
+
|
17
|
+
// Free allocated memory for a bridge and reset it to known-empty.
|
18
|
+
void clear_bridge(TBridge *bridge)
|
19
|
+
{
|
20
|
+
Safefree(bridge->designer);
|
21
|
+
Safefree(bridge->project_id);
|
22
|
+
Safefree(bridge->joints);
|
23
|
+
Safefree(bridge->members);
|
24
|
+
clear_load_scenario(&bridge->load_scenario);
|
25
|
+
init_bridge(bridge);
|
26
|
+
}
|
27
|
+
|
28
|
+
// Compare two joint lists (arrays) for functional equality.
|
29
|
+
TBool joint_lists_eq(TJoint *a, TJoint *b, unsigned n)
|
30
|
+
{
|
31
|
+
unsigned i;
|
32
|
+
|
33
|
+
for (i = 0; i < n; i++) {
|
34
|
+
if (a[i].x != b[i].x || a[i].y != b[i].y)
|
35
|
+
return False;
|
36
|
+
}
|
37
|
+
return True;
|
38
|
+
}
|
39
|
+
|
40
|
+
TBool x_section_lists_eq(TXSection *a, TXSection *b, unsigned n)
|
41
|
+
{
|
42
|
+
return memcmp(a, b, n * sizeof(TXSection)) == 0;
|
43
|
+
}
|
44
|
+
|
45
|
+
// Table mapping section to sectio name.
|
46
|
+
static char *section_str_table[NSections] = {
|
47
|
+
"Bar",
|
48
|
+
"Tube",
|
49
|
+
};
|
50
|
+
|
51
|
+
char *section_str(TSection section)
|
52
|
+
{
|
53
|
+
return (unsigned)section < NSections ? section_str_table[section] : "<unknown>";
|
54
|
+
}
|
55
|
+
|
56
|
+
// Compare two member lists (arrays) for functional equality.
|
57
|
+
TBool member_lists_eq(TMember *a, TMember *b, unsigned n)
|
58
|
+
{
|
59
|
+
unsigned i;
|
60
|
+
|
61
|
+
// Equality comparison must ignore the compression and tension strings.
|
62
|
+
for (i = 0; i < n; i++) {
|
63
|
+
if (a[i].start_joint != b[i].start_joint ||
|
64
|
+
a[i].end_joint != b[i].end_joint ||
|
65
|
+
!x_section_lists_eq(&a[i].x_section, &b[i].x_section, 1))
|
66
|
+
|
67
|
+
return False;
|
68
|
+
}
|
69
|
+
|
70
|
+
return True;
|
71
|
+
}
|
72
|
+
|
73
|
+
// Make a fresh copy of a bridge. The bridge
|
74
|
+
// can't be erroneous. If so, the copy just
|
75
|
+
// fails quietly.
|
76
|
+
void copy_bridge(TBridge *dst, TBridge *src)
|
77
|
+
{
|
78
|
+
if (src->error != BridgeNoError)
|
79
|
+
return;
|
80
|
+
|
81
|
+
clear_bridge(dst);
|
82
|
+
|
83
|
+
dst->version = src->version;
|
84
|
+
dst->test_status = src->test_status;
|
85
|
+
dst->scenario_descriptor = src->scenario_descriptor;
|
86
|
+
NewStr(145, dst->designer, src->designer);
|
87
|
+
NewStr(147, dst->project_id, src->project_id);
|
88
|
+
dst->n_design_iterations = src->n_design_iterations;
|
89
|
+
dst->n_joints = src->n_joints;
|
90
|
+
New(150, dst->joints, dst->n_joints + 1, TJoint);
|
91
|
+
memcpy(dst->joints, src->joints, (dst->n_joints + 1) * sizeof(TJoint));
|
92
|
+
dst->n_members = src->n_members;
|
93
|
+
New(160, dst->members, dst->n_members + 1, TMember);
|
94
|
+
memcpy(dst->members, src->members, (dst->n_members + 1) * sizeof(TMember));
|
95
|
+
dst->label_pos = src->label_pos;
|
96
|
+
copy_load_scenario(&dst->load_scenario, &src->load_scenario);
|
97
|
+
}
|
98
|
+
|
99
|
+
// Compare two bridges for identical geometry and materials.
|
100
|
+
TBool bridges_indentical(TBridge *a, TBridge *b)
|
101
|
+
{
|
102
|
+
return
|
103
|
+
a->version == b->version &&
|
104
|
+
a->scenario_descriptor.index == b->scenario_descriptor.index &&
|
105
|
+
a->n_joints == b->n_joints &&
|
106
|
+
a->n_members == b->n_members &&
|
107
|
+
joint_lists_eq(&a->joints[1], &b->joints[1], b->n_joints) &&
|
108
|
+
member_lists_eq(&a->members[1], &b->members[1], b->n_members);
|
109
|
+
}
|
110
|
+
|
111
|
+
// Make a canonical variant of the source bridge. This is just
|
112
|
+
// sorting joints and members into a canonical order. But we have
|
113
|
+
// to keep joint references in members correct.
|
114
|
+
void canonicalize(TBridge *dst, TBridge *src)
|
115
|
+
{
|
116
|
+
unsigned *new_joint_to_old, *old_joint_to_new;
|
117
|
+
unsigned joint_index, member_index;
|
118
|
+
|
119
|
+
if (src->error != BridgeNoError)
|
120
|
+
return;
|
121
|
+
|
122
|
+
copy_bridge(dst, src);
|
123
|
+
|
124
|
+
Newz(170, new_joint_to_old, dst->n_joints + 1, unsigned);
|
125
|
+
for (joint_index = 1; joint_index <= dst->n_joints; joint_index++)
|
126
|
+
new_joint_to_old[joint_index] = joint_index;
|
127
|
+
|
128
|
+
{ // Indirect insertion sort of joint map so that, when done,
|
129
|
+
// joints[new_joint_to_old[i]] for sort_base + 1 <= i <= n_joints are in ascending order.
|
130
|
+
// Sort_base is first joint after those fixed by the scenario. We could sort these, too,
|
131
|
+
// but then the canonical bridge won't be usable by the Designer.
|
132
|
+
// Sort order is lexicographic on x and then y.
|
133
|
+
unsigned i, j, t;
|
134
|
+
unsigned sort_base = dst->load_scenario.n_prescribed_joints + 1;
|
135
|
+
|
136
|
+
#define JointGT(A, B) \
|
137
|
+
(dst->joints[A].x > dst->joints[B].x || \
|
138
|
+
(dst->joints[A].x == dst->joints[B].x &&\
|
139
|
+
dst->joints[A].y > dst->joints[B].y))
|
140
|
+
|
141
|
+
for (i = sort_base + 1; i <= dst->n_joints; i++) {
|
142
|
+
t = new_joint_to_old[i];
|
143
|
+
for (j = i; j > sort_base && JointGT(new_joint_to_old[j-1], t); j--)
|
144
|
+
new_joint_to_old[j] = new_joint_to_old[j-1];
|
145
|
+
new_joint_to_old[j] = t;
|
146
|
+
}
|
147
|
+
}
|
148
|
+
|
149
|
+
// Compute inverse map.
|
150
|
+
Newz(180, old_joint_to_new, dst->n_joints + 1, unsigned);
|
151
|
+
for (joint_index = 1; joint_index <= dst->n_joints; joint_index++)
|
152
|
+
old_joint_to_new[new_joint_to_old[joint_index]] = joint_index;
|
153
|
+
|
154
|
+
// Translate joint numbers in members.
|
155
|
+
for (member_index = 1; member_index <= dst->n_members; member_index++) {
|
156
|
+
dst->members[member_index].start_joint = old_joint_to_new[dst->members[member_index].start_joint];
|
157
|
+
dst->members[member_index].end_joint = old_joint_to_new[dst->members[member_index].end_joint];
|
158
|
+
}
|
159
|
+
|
160
|
+
// Now actually move the joints.
|
161
|
+
// Copy from source joints to avoid overlapping moves. Renumber while copying.
|
162
|
+
for (joint_index = 1; joint_index <= dst->n_joints; joint_index++) {
|
163
|
+
dst->joints[joint_index] = src->joints[new_joint_to_old[joint_index]];
|
164
|
+
dst->joints[joint_index].number = joint_index;
|
165
|
+
}
|
166
|
+
|
167
|
+
Safefree(new_joint_to_old);
|
168
|
+
Safefree(old_joint_to_new);
|
169
|
+
|
170
|
+
// Swap joint references so lowest joint number is first.
|
171
|
+
for (member_index = 1; member_index <= dst->n_members; member_index++) {
|
172
|
+
TElementNumber j1 = dst->members[member_index].start_joint;
|
173
|
+
TElementNumber j2 = dst->members[member_index].end_joint;
|
174
|
+
if (j1 > j2) {
|
175
|
+
dst->members[member_index].start_joint = j2;
|
176
|
+
dst->members[member_index].end_joint = j1;
|
177
|
+
}
|
178
|
+
}
|
179
|
+
|
180
|
+
{ // Now do a direct sort of members into a canonical order.
|
181
|
+
// We use lexicographic order on start_joint then end_joint.
|
182
|
+
unsigned i, j;
|
183
|
+
TMember t;
|
184
|
+
|
185
|
+
for (i = 2; i <= dst->n_members; i++) {
|
186
|
+
t = dst->members[i];
|
187
|
+
for ( j = i;
|
188
|
+
j > 1 &&
|
189
|
+
(dst->members[j-1].start_joint > t.start_joint ||
|
190
|
+
(dst->members[j-1].start_joint == t.start_joint &&
|
191
|
+
dst->members[j-1].end_joint > t.end_joint));
|
192
|
+
j--)
|
193
|
+
dst->members[j] = dst->members[j-1];
|
194
|
+
dst->members[j] = t;
|
195
|
+
}
|
196
|
+
}
|
197
|
+
|
198
|
+
// And renumber members, too.
|
199
|
+
for (member_index = 1; member_index <= dst->n_members; member_index++)
|
200
|
+
dst->members[member_index].number = member_index;
|
201
|
+
|
202
|
+
// Set error in the canonical bridge if there are geometry problems.
|
203
|
+
// First check for duplicate joints, which will show up as adjacent
|
204
|
+
// in the canonical bridge.
|
205
|
+
for (joint_index = 1; joint_index < dst->n_joints; joint_index++) {
|
206
|
+
if (joint_lists_eq(
|
207
|
+
&dst->joints[joint_index],
|
208
|
+
&dst->joints[joint_index + 1], 1)) {
|
209
|
+
clear_bridge(dst);
|
210
|
+
dst->error = BridgeDupJoints;
|
211
|
+
return;
|
212
|
+
}
|
213
|
+
}
|
214
|
+
|
215
|
+
// Check for duplicate members, which, again, will show up as adjacent
|
216
|
+
// in canonical bridge.
|
217
|
+
for (member_index = 1; member_index < dst->n_members; member_index++) {
|
218
|
+
if (member_lists_eq(
|
219
|
+
&dst->members[member_index],
|
220
|
+
&dst->members[member_index + 1], 1)) {
|
221
|
+
clear_bridge(dst);
|
222
|
+
dst->error = BridgeDupMembers;
|
223
|
+
return;
|
224
|
+
}
|
225
|
+
}
|
226
|
+
|
227
|
+
// Finally check for joints lying exactly on members.
|
228
|
+
for (member_index = 1; member_index <= dst->n_members; member_index++) {
|
229
|
+
|
230
|
+
TMember *member = &dst->members[member_index];
|
231
|
+
TJoint *start = &dst->joints[member->start_joint];
|
232
|
+
TJoint *end = &dst->joints[member->end_joint];
|
233
|
+
|
234
|
+
for (joint_index = 1; joint_index <= dst->n_joints; joint_index++) {
|
235
|
+
long A, B;
|
236
|
+
TJoint *joint;
|
237
|
+
|
238
|
+
// First make sure we're not looking at one of the member's ends!
|
239
|
+
if (joint_index == member->start_joint ||
|
240
|
+
joint_index == member->end_joint)
|
241
|
+
continue;
|
242
|
+
|
243
|
+
// Ignore joints that are outside the rectangular extent of the member.
|
244
|
+
joint = &dst->joints[joint_index];
|
245
|
+
if (start->x > joint->x && end->x > joint->x ||
|
246
|
+
start->x < joint->x && end->x < joint->x ||
|
247
|
+
start->y > joint->y && end->y > joint->y ||
|
248
|
+
start->y < joint->y && end->y < joint->y)
|
249
|
+
continue;
|
250
|
+
|
251
|
+
// Check if the joint is on the line struck by the member ends.
|
252
|
+
A = end->y - start->y;
|
253
|
+
B = start->x - end->x;
|
254
|
+
if (A * start->x + B * start->y == A * joint->x + B * joint->y) {
|
255
|
+
clear_bridge(dst);
|
256
|
+
dst->error = BridgeJointOnMember;
|
257
|
+
return;
|
258
|
+
}
|
259
|
+
}
|
260
|
+
}
|
261
|
+
}
|
262
|
+
|
263
|
+
void print_material(FILE *f,
|
264
|
+
unsigned index,
|
265
|
+
TMaterial *material)
|
266
|
+
{
|
267
|
+
unsigned section_index;
|
268
|
+
|
269
|
+
fprintf(f, "[%u] material '%s (%s)':\n", index, material->name, material->short_name);
|
270
|
+
fprintf(f, " elasticity = %.4f\n", material->E);
|
271
|
+
fprintf(f, " yield strength = %.4f\n", material->Fy);
|
272
|
+
fprintf(f, " density = %.4f\n", material->density);
|
273
|
+
fprintf(f, " cost:\n");
|
274
|
+
for (section_index = 0; section_index < NSections; section_index++)
|
275
|
+
fprintf(f, "%4s = %f\n", section_str(section_index), material->cost[section_index]);
|
276
|
+
}
|
277
|
+
|
278
|
+
void print_shape(FILE *f,
|
279
|
+
unsigned section_index,
|
280
|
+
unsigned size_index,
|
281
|
+
TShape *shape)
|
282
|
+
{
|
283
|
+
fprintf(f, "[section=%u, size=%u] shape %s:\n", section_index, size_index, shape->name);
|
284
|
+
fprintf(f, " width = %.4f\n", shape->width);
|
285
|
+
fprintf(f, " area = %.4f\n", shape->area);
|
286
|
+
fprintf(f, " moment = %.4f\n", shape->moment);
|
287
|
+
}
|
288
|
+
|
@@ -0,0 +1,60 @@
|
|
1
|
+
#include "stdafx.h"
|
2
|
+
#include "internal.h"
|
3
|
+
|
4
|
+
// Compute the complete cost of a bridge.
|
5
|
+
TFloat bridge_cost(TBridge *bridge, TGeometry *geometry, TParams *params)
|
6
|
+
{
|
7
|
+
unsigned i, member_index;
|
8
|
+
TFloat mtl_cost, connection_cost, product_cost;
|
9
|
+
TXSection used[NMaterials * NSections * MaxNSizes];
|
10
|
+
unsigned n_used = 0;
|
11
|
+
TGeometry local_geometry[1];
|
12
|
+
TParams local_params[1];
|
13
|
+
|
14
|
+
if (bridge->error != BridgeNoError)
|
15
|
+
return 0.00;
|
16
|
+
|
17
|
+
// If caller didn't provide these things, we'll do it ourself.
|
18
|
+
if (!geometry) {
|
19
|
+
geometry = local_geometry;
|
20
|
+
init_geometry(geometry);
|
21
|
+
setup_geometry(geometry, bridge);
|
22
|
+
}
|
23
|
+
|
24
|
+
if (!params) {
|
25
|
+
params = local_params;
|
26
|
+
init_params(params);
|
27
|
+
setup_params(params);
|
28
|
+
}
|
29
|
+
|
30
|
+
// Loop counts number of unique material types for ordering fee.
|
31
|
+
// Loop also totals material cost based on volume, density, and cost per unit weight.
|
32
|
+
mtl_cost = 0.00;
|
33
|
+
for (member_index = 1; member_index <= bridge->n_members; member_index++) {
|
34
|
+
|
35
|
+
TXSection *xs = &bridge->members[member_index].x_section;
|
36
|
+
|
37
|
+
mtl_cost +=
|
38
|
+
params->materials[xs->material].cost[xs->section] *
|
39
|
+
params->shapes[xs->section][xs->size].area *
|
40
|
+
geometry->length[member_index] *
|
41
|
+
params->materials[xs->material].density;
|
42
|
+
|
43
|
+
// Look for this cross-section in the list of those already used.
|
44
|
+
for (i = 0; i < n_used && !x_section_lists_eq(&used[i], xs, 1); i++)
|
45
|
+
/* skip */;
|
46
|
+
if (i == n_used)
|
47
|
+
// Didn't find this cross-section in table. Add it.
|
48
|
+
used[n_used++] = *xs;
|
49
|
+
}
|
50
|
+
product_cost = n_used * params->ordering_fee;
|
51
|
+
connection_cost = bridge->n_joints * params->connection_cost;
|
52
|
+
|
53
|
+
if (geometry == local_geometry)
|
54
|
+
clear_geometry(geometry);
|
55
|
+
if (params == local_params)
|
56
|
+
clear_params(params);
|
57
|
+
|
58
|
+
return 2 * (mtl_cost + connection_cost) + product_cost + bridge->scenario_descriptor.site_cost;
|
59
|
+
}
|
60
|
+
|
@@ -0,0 +1,126 @@
|
|
1
|
+
#include "stdafx.h"
|
2
|
+
#include "internal.h"
|
3
|
+
|
4
|
+
static INLINE int bit_width(unsigned int n)
|
5
|
+
{
|
6
|
+
int w = 0;
|
7
|
+
while (n) {
|
8
|
+
n >>= 1;
|
9
|
+
w++;
|
10
|
+
}
|
11
|
+
return w;
|
12
|
+
}
|
13
|
+
|
14
|
+
// Hash function starts hash value with alternating 1's and 0's.
|
15
|
+
// Xors in the significant bits (omitting leading zeros) of the
|
16
|
+
// given vector with each set of signifcant bits separated by a 1,
|
17
|
+
// which is "or'ed" in.
|
18
|
+
void hashify_vec(unsigned int *v, unsigned v_len,
|
19
|
+
unsigned int *hash, unsigned h_len)
|
20
|
+
{
|
21
|
+
unsigned iv, ip;
|
22
|
+
|
23
|
+
assert(v);
|
24
|
+
assert(hash);
|
25
|
+
assert(h_len >= 1);
|
26
|
+
|
27
|
+
for (ip = 0; ip < h_len; ip++)
|
28
|
+
hash[ip] = 0x55555555u;
|
29
|
+
|
30
|
+
ip = 0;
|
31
|
+
for (iv = 0; iv < v_len; iv++) {
|
32
|
+
unsigned int val = (v[iv] << 1) | 1;
|
33
|
+
unsigned ipw = ip >> 5;
|
34
|
+
unsigned ipo = ip & 0x1f;
|
35
|
+
assert(ipw < h_len);
|
36
|
+
hash[ipw] ^= (val << ipo);
|
37
|
+
if (++ipw >= h_len)
|
38
|
+
ipw = 0;
|
39
|
+
hash[ipw] ^= (val >> (32 - ipo));
|
40
|
+
ip += bit_width(val);
|
41
|
+
if ((ip >> 5) >= h_len)
|
42
|
+
ip -= (h_len << 5);
|
43
|
+
}
|
44
|
+
}
|
45
|
+
|
46
|
+
char *hex_nibble(int n, char *p)
|
47
|
+
{
|
48
|
+
p[0] = "0123456789abcdef"[n & 0xf];
|
49
|
+
p[1] = '\0';
|
50
|
+
|
51
|
+
return p;
|
52
|
+
}
|
53
|
+
|
54
|
+
char *hex_byte(int b, char *p)
|
55
|
+
{
|
56
|
+
hex_nibble(b >> 4, &p[0]);
|
57
|
+
hex_nibble(b, &p[1]);
|
58
|
+
|
59
|
+
return p;
|
60
|
+
}
|
61
|
+
|
62
|
+
char *hex_str(char *s, unsigned n, char *p)
|
63
|
+
{
|
64
|
+
unsigned i;
|
65
|
+
|
66
|
+
if (n == 0)
|
67
|
+
n = strlen(s);
|
68
|
+
for (i = 0; i < n; i++)
|
69
|
+
hex_byte(s[i], &p[2 * i]);
|
70
|
+
|
71
|
+
return p;
|
72
|
+
}
|
73
|
+
|
74
|
+
int hash_bridge(TBridge *bridge, char *hash)
|
75
|
+
{
|
76
|
+
unsigned joint_index, member_index, hash_base;
|
77
|
+
TBridge cb[1];
|
78
|
+
|
79
|
+
unsigned v_size = 256;
|
80
|
+
unsigned p = 0;
|
81
|
+
unsigned int *v;
|
82
|
+
unsigned int h[HASH_SIZE / sizeof(unsigned int)];
|
83
|
+
|
84
|
+
New(190, v, v_size, unsigned int);
|
85
|
+
|
86
|
+
#define Add(Val) do { \
|
87
|
+
if (p >= v_size) { \
|
88
|
+
v_size *= 2; \
|
89
|
+
Renew(v, v_size, unsigned int); \
|
90
|
+
} \
|
91
|
+
v[p++] = (Val); \
|
92
|
+
} while (0)
|
93
|
+
|
94
|
+
init_bridge(cb);
|
95
|
+
canonicalize(cb, bridge);
|
96
|
+
|
97
|
+
// Canonicalization can fail if bridge has bad geometry.
|
98
|
+
if (cb->error != BridgeNoError)
|
99
|
+
return 1;
|
100
|
+
|
101
|
+
// Scenario
|
102
|
+
Add(cb->scenario_descriptor.index + 512);
|
103
|
+
|
104
|
+
// Start hashing joints after standard ones dictated by scenario.
|
105
|
+
hash_base = cb->load_scenario.n_prescribed_joints + 1;
|
106
|
+
for (joint_index = hash_base; joint_index <= bridge->n_joints; joint_index++) {
|
107
|
+
Add(cb->joints[joint_index].x);
|
108
|
+
Add(cb->joints[joint_index].y);
|
109
|
+
}
|
110
|
+
for (member_index = 1; member_index <= bridge->n_members; member_index++) {
|
111
|
+
Add(cb->members[member_index].start_joint);
|
112
|
+
Add(cb->members[member_index].end_joint);
|
113
|
+
Add(cb->members[member_index].x_section.material);
|
114
|
+
Add(cb->members[member_index].x_section.section);
|
115
|
+
Add(cb->members[member_index].x_section.size);
|
116
|
+
}
|
117
|
+
|
118
|
+
// Can't hashify directly into hash because it might not be aligned.
|
119
|
+
hashify_vec(v, p, h, HASH_SIZE / sizeof(unsigned int));
|
120
|
+
memcpy(hash, h, HASH_SIZE);
|
121
|
+
|
122
|
+
Safefree(v);
|
123
|
+
clear_bridge(cb);
|
124
|
+
return 0;
|
125
|
+
}
|
126
|
+
|