line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
1
|
|
|
|
|
|
|
#include "EXTERN.h" |
2
|
|
|
|
|
|
|
#include "perl.h" |
3
|
|
|
|
|
|
|
#include "XSUB.h" |
4
|
|
|
|
|
|
|
|
5
|
|
|
|
|
|
|
#include "ppport.h" |
6
|
|
|
|
|
|
|
|
7
|
|
|
|
|
|
|
#define isPenalty(sv) (SvROK(sv) && sv_derived_from(sv, "Text::KnuthPlass::Penalty")) |
8
|
|
|
|
|
|
|
#define ivHash(hv, key) (IV)SvIV(*hv_fetch((HV*)hv, key, strlen(key), TRUE)) |
9
|
|
|
|
|
|
|
#define nvHash(hv, key) (NV)SvNVx(*hv_fetch((HV*)hv, key, strlen(key), TRUE)) |
10
|
|
|
|
|
|
|
#define debug(x) |
11
|
|
|
|
|
|
|
|
12
|
|
|
|
|
|
|
typedef SV * Text_KnuthPlass; |
13
|
|
|
|
|
|
|
|
14
|
|
|
|
|
|
|
struct Breakpoint_s { |
15
|
|
|
|
|
|
|
struct Breakpoint_s * prev; |
16
|
|
|
|
|
|
|
struct Breakpoint_s * next; |
17
|
|
|
|
|
|
|
struct Breakpoint_s * previous; |
18
|
|
|
|
|
|
|
struct Breakpoint_s * active; /* Just for candidates */ |
19
|
|
|
|
|
|
|
NV demerits; |
20
|
|
|
|
|
|
|
NV ratio; |
21
|
|
|
|
|
|
|
IV line; |
22
|
|
|
|
|
|
|
IV position; |
23
|
|
|
|
|
|
|
IV fitness_class; |
24
|
|
|
|
|
|
|
HV* totals; |
25
|
|
|
|
|
|
|
}; |
26
|
|
|
|
|
|
|
|
27
|
|
|
|
|
|
|
typedef struct Breakpoint_s Breakpoint; |
28
|
|
|
|
|
|
|
|
29
|
|
|
|
|
|
|
typedef struct LinkedList_s { |
30
|
|
|
|
|
|
|
Breakpoint* head; |
31
|
|
|
|
|
|
|
Breakpoint* tail; |
32
|
|
|
|
|
|
|
IV list_size; |
33
|
|
|
|
|
|
|
AV* to_free; |
34
|
|
|
|
|
|
|
} LinkedList; |
35
|
|
|
|
|
|
|
|
36
|
|
|
|
|
|
|
// overrides _computeCost() in Perl (note name difference!) |
37
|
|
|
|
|
|
|
// a = $active, current_line = $currentLine in Perl |
38
|
5384
|
|
|
|
|
|
NV _compute_cost(Text_KnuthPlass self, IV start, IV end, Breakpoint* a, |
39
|
|
|
|
|
|
|
IV current_line, AV* nodes) { |
40
|
5384
|
50
|
|
|
|
|
IV infinity = ivHash(self, "infinity"); // $self->{'infinity'} |
41
|
5384
|
|
|
|
|
|
HV* sum = (HV*)SvRV(*hv_fetch((HV*)self, "sum", 3, FALSE)); |
42
|
5384
|
|
|
|
|
|
HV* totals = a->totals; |
43
|
5384
|
100
|
|
|
|
|
NV width = nvHash(sum, "width") - nvHash(totals,"width"); |
|
|
50
|
|
|
|
|
|
44
|
5384
|
|
|
|
|
|
AV* linelengths = (AV*)SvRV(*hv_fetch((HV*)self, "linelengths", 11, FALSE)); |
45
|
|
|
|
|
|
|
/* ll is index of LAST element of linelengths, NOT the size (length) */ |
46
|
5384
|
|
|
|
|
|
I32 ll = av_len(linelengths); |
47
|
|
|
|
|
|
|
NV stretch = 0; |
48
|
|
|
|
|
|
|
NV shrink = 0; |
49
|
5384
|
100
|
|
|
|
|
NV linelength = SvNV(*av_fetch(linelengths, current_line <= ll ? current_line-1 : ll, 0)); |
|
|
100
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
51
|
|
|
|
|
|
|
debug(warn("Computing cost from %i to %i\n", start, end)); |
52
|
|
|
|
|
|
|
debug(warn("Sum width: %f\n", nvHash(sum, "width"))); |
53
|
|
|
|
|
|
|
debug(warn("Total width: %f\n", nvHash(totals, "width"))); |
54
|
|
|
|
|
|
|
|
55
|
5384
|
50
|
|
|
|
|
if (isPenalty(*av_fetch(nodes, end, 0))) { |
|
|
100
|
|
|
|
|
|
56
|
|
|
|
|
|
|
debug(warn("Adding penalty width\n")); |
57
|
1839
|
100
|
|
|
|
|
width += nvHash(SvRV(*av_fetch(nodes,end, 0)),"width"); |
58
|
|
|
|
|
|
|
} |
59
|
|
|
|
|
|
|
debug(warn("Width %f, linelength %f\n", width, linelength)); |
60
|
|
|
|
|
|
|
|
61
|
5384
|
100
|
|
|
|
|
if (width < linelength) { |
62
|
4075
|
100
|
|
|
|
|
stretch = nvHash(sum, "stretch") - nvHash(totals, "stretch"); |
|
|
50
|
|
|
|
|
|
63
|
|
|
|
|
|
|
debug(warn("Stretch %f\n", stretch)); |
64
|
4075
|
100
|
|
|
|
|
if (stretch > 0) { |
65
|
3264
|
|
|
|
|
|
return (linelength - width) / stretch; |
66
|
|
|
|
|
|
|
} else { |
67
|
811
|
|
|
|
|
|
return infinity; |
68
|
|
|
|
|
|
|
} |
69
|
1309
|
100
|
|
|
|
|
} else if (width > linelength) { |
70
|
|
|
|
|
|
|
debug(warn("Shrink %f\n", shrink)); |
71
|
1243
|
100
|
|
|
|
|
shrink = nvHash(sum, "shrink") - nvHash(totals, "shrink"); |
|
|
50
|
|
|
|
|
|
72
|
1243
|
100
|
|
|
|
|
if (shrink > 0) { |
73
|
36
|
|
|
|
|
|
return (linelength - width) / shrink; |
74
|
|
|
|
|
|
|
} else { |
75
|
1207
|
|
|
|
|
|
return infinity; |
76
|
|
|
|
|
|
|
} |
77
|
|
|
|
|
|
|
} else { return 0; } |
78
|
|
|
|
|
|
|
} |
79
|
|
|
|
|
|
|
|
80
|
|
|
|
|
|
|
// overrides _computeSum() in Perl (note name difference!) |
81
|
586
|
|
|
|
|
|
HV* _compute_sum(Text_KnuthPlass self, IV index, AV* nodes) { |
82
|
586
|
|
|
|
|
|
HV* result = newHV(); |
83
|
586
|
|
|
|
|
|
HV* sum = (HV*)SvRV(*hv_fetch((HV*)self, "sum", 3, FALSE)); |
84
|
586
|
50
|
|
|
|
|
IV infinity = ivHash(self, "infinity"); |
85
|
586
|
50
|
|
|
|
|
NV width = nvHash(sum, "width"); |
86
|
586
|
50
|
|
|
|
|
NV stretch = nvHash(sum, "stretch"); |
87
|
586
|
100
|
|
|
|
|
NV shrink = nvHash(sum, "shrink"); |
88
|
586
|
|
|
|
|
|
I32 len = av_len(nodes); |
89
|
586
|
|
|
|
|
|
I32 i = index; |
90
|
|
|
|
|
|
|
|
91
|
1151
|
100
|
|
|
|
|
while (i < len) { |
92
|
1106
|
|
|
|
|
|
SV* e = *av_fetch(nodes, i, 0); |
93
|
1106
|
100
|
|
|
|
|
if (sv_derived_from(e, "Text::KnuthPlass::Glue")) { |
94
|
411
|
100
|
|
|
|
|
width += nvHash(SvRV(e), "width"); |
95
|
411
|
100
|
|
|
|
|
stretch += nvHash(SvRV(e), "stretch"); |
96
|
411
|
100
|
|
|
|
|
shrink += nvHash(SvRV(e), "shrink"); |
97
|
695
|
100
|
|
|
|
|
} else if (sv_derived_from(e, "Text::KnuthPlass::Box") || |
|
|
50
|
|
|
|
|
|
98
|
154
|
50
|
|
|
|
|
(isPenalty(e) && ivHash(SvRV(e), "penalty") == -infinity |
|
|
50
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
99
|
0
|
0
|
|
|
|
|
&& i > index)) { |
100
|
|
|
|
|
|
|
break; |
101
|
|
|
|
|
|
|
} |
102
|
565
|
|
|
|
|
|
i++; |
103
|
|
|
|
|
|
|
} |
104
|
|
|
|
|
|
|
|
105
|
586
|
|
|
|
|
|
hv_stores(result, "width", newSVnv(width)); |
106
|
586
|
|
|
|
|
|
hv_stores(result, "stretch", newSVnv(stretch)); |
107
|
586
|
|
|
|
|
|
hv_stores(result, "shrink", newSVnv(shrink)); |
108
|
586
|
|
|
|
|
|
return result; |
109
|
|
|
|
|
|
|
} |
110
|
|
|
|
|
|
|
|
111
|
1176
|
|
|
|
|
|
Breakpoint* _new_breakpoint (void) { |
112
|
|
|
|
|
|
|
Breakpoint* dummy; |
113
|
1176
|
|
|
|
|
|
HV* totals = newHV(); |
114
|
1176
|
|
|
|
|
|
Newxz(dummy, 1, Breakpoint); |
115
|
1176
|
|
|
|
|
|
dummy->prev = dummy->next = dummy->previous = dummy->active = NULL; |
116
|
1176
|
|
|
|
|
|
dummy->demerits = dummy->ratio = 0; |
117
|
1176
|
|
|
|
|
|
dummy->line = dummy->position = dummy->fitness_class = 0; |
118
|
1176
|
|
|
|
|
|
hv_stores(totals, "width", newSVnv(0)); |
119
|
1176
|
|
|
|
|
|
hv_stores(totals, "stretch", newSVnv(0)); |
120
|
1176
|
|
|
|
|
|
hv_stores(totals, "shrink", newSVnv(0)); |
121
|
1176
|
|
|
|
|
|
dummy->totals = totals; |
122
|
1176
|
|
|
|
|
|
return dummy; |
123
|
|
|
|
|
|
|
} |
124
|
|
|
|
|
|
|
|
125
|
0
|
|
|
|
|
|
void free_breakpoint(Breakpoint* b) { |
126
|
0
|
0
|
|
|
|
|
while (b) { |
127
|
0
|
|
|
|
|
|
Breakpoint* p = b->previous; |
128
|
0
|
0
|
|
|
|
|
if (SvROK(b->totals)) { |
129
|
0
|
|
|
|
|
|
sv_free((SV*)b->totals); |
130
|
0
|
|
|
|
|
|
Safefree(b); |
131
|
|
|
|
|
|
|
} |
132
|
|
|
|
|
|
|
b = p; |
133
|
|
|
|
|
|
|
} |
134
|
0
|
0
|
|
|
|
|
if (b && b->totals) sv_free((SV*)b->totals); |
|
|
0
|
|
|
|
|
|
135
|
0
|
0
|
|
|
|
|
if (b) Safefree(b); |
136
|
0
|
|
|
|
|
|
} |
137
|
|
|
|
|
|
|
|
138
|
569
|
|
|
|
|
|
void _unlinkKP(LinkedList* list, Breakpoint* a) { |
139
|
569
|
100
|
|
|
|
|
if (!a->prev) { list->head = a->next; } else { a->prev->next = a->next; } |
140
|
569
|
100
|
|
|
|
|
if (!a->next) { list->tail = a->prev; } else { a->next->prev = a->prev; } |
141
|
569
|
|
|
|
|
|
list->list_size--; |
142
|
569
|
|
|
|
|
|
av_push(list->to_free, newSViv((IV)a)); |
143
|
569
|
|
|
|
|
|
} |
144
|
|
|
|
|
|
|
|
145
|
|
|
|
|
|
|
MODULE = Text::KnuthPlass PACKAGE = Text::KnuthPlass |
146
|
|
|
|
|
|
|
|
147
|
|
|
|
|
|
|
void |
148
|
|
|
|
|
|
|
_init_nodelist(self) |
149
|
|
|
|
|
|
|
Text_KnuthPlass self |
150
|
|
|
|
|
|
|
|
151
|
|
|
|
|
|
|
CODE: |
152
|
|
|
|
|
|
|
// overrides _init_nodelist() in Perl |
153
|
|
|
|
|
|
|
LinkedList* activelist; |
154
|
4
|
|
|
|
|
|
Newxz(activelist, 1, LinkedList); |
155
|
4
|
|
|
|
|
|
activelist->head = activelist->tail = _new_breakpoint(); |
156
|
4
|
|
|
|
|
|
activelist->list_size = 1; |
157
|
4
|
|
|
|
|
|
activelist->to_free = newAV(); |
158
|
4
|
|
|
|
|
|
hv_stores((HV*)self, "activeNodes", ((SV *)activelist)); |
159
|
|
|
|
|
|
|
|
160
|
|
|
|
|
|
|
void _active_to_breaks(self) |
161
|
|
|
|
|
|
|
Text_KnuthPlass self |
162
|
|
|
|
|
|
|
|
163
|
|
|
|
|
|
|
PREINIT: |
164
|
|
|
|
|
|
|
LinkedList* activelist; |
165
|
|
|
|
|
|
|
Breakpoint* b; |
166
|
|
|
|
|
|
|
Breakpoint* best = NULL; |
167
|
|
|
|
|
|
|
|
168
|
|
|
|
|
|
|
PPCODE: |
169
|
|
|
|
|
|
|
// overrides _active_to_breaks() in Perl |
170
|
4
|
|
|
|
|
|
activelist = (LinkedList*)(*hv_fetch((HV*)self, "activeNodes", 11, FALSE)); |
171
|
|
|
|
|
|
|
|
172
|
25
|
100
|
|
|
|
|
for (b = activelist->head; b; b = b->next) { |
173
|
21
|
100
|
|
|
|
|
if (!best || b->demerits < best->demerits) best = b; |
|
|
50
|
|
|
|
|
|
174
|
|
|
|
|
|
|
} |
175
|
30
|
100
|
|
|
|
|
while (best) { |
176
|
26
|
|
|
|
|
|
HV* posnode = newHV(); |
177
|
26
|
|
|
|
|
|
hv_stores(posnode, "position", newSViv(best->position)); |
178
|
26
|
|
|
|
|
|
hv_stores(posnode, "ratio", newSVnv(best->ratio)); |
179
|
26
|
50
|
|
|
|
|
XPUSHs(sv_2mortal(newRV((SV*)posnode))); |
180
|
26
|
|
|
|
|
|
best = best->previous; |
181
|
|
|
|
|
|
|
} |
182
|
|
|
|
|
|
|
|
183
|
|
|
|
|
|
|
void _cleanup(self) |
184
|
|
|
|
|
|
|
Text_KnuthPlass self |
185
|
|
|
|
|
|
|
|
186
|
|
|
|
|
|
|
CODE: |
187
|
|
|
|
|
|
|
// overrides _cleanup() in Perl (which is a dummy stub) |
188
|
|
|
|
|
|
|
Breakpoint* b; |
189
|
|
|
|
|
|
|
LinkedList* activelist; |
190
|
4
|
|
|
|
|
|
activelist = (LinkedList*)(*hv_fetch((HV*)self, "activeNodes", 11, FALSE)); |
191
|
|
|
|
|
|
|
return; |
192
|
|
|
|
|
|
|
/* Free nodes on the activelist */ |
193
|
|
|
|
|
|
|
b = activelist->head; |
194
|
|
|
|
|
|
|
while (b) { |
195
|
|
|
|
|
|
|
Breakpoint* n = b->next; |
196
|
|
|
|
|
|
|
free_breakpoint(b); |
197
|
|
|
|
|
|
|
b = n; |
198
|
|
|
|
|
|
|
} |
199
|
|
|
|
|
|
|
/* Shut down the activelist itself */ |
200
|
|
|
|
|
|
|
while (av_len(activelist->to_free)) { |
201
|
|
|
|
|
|
|
SV* pointer = av_shift(activelist->to_free); |
202
|
|
|
|
|
|
|
if ((Breakpoint*)SvIV(pointer)) |
203
|
|
|
|
|
|
|
free_breakpoint((Breakpoint*)SvIV(pointer)); |
204
|
|
|
|
|
|
|
sv_free(pointer); |
205
|
|
|
|
|
|
|
} |
206
|
|
|
|
|
|
|
sv_free((SV*)activelist->to_free); |
207
|
|
|
|
|
|
|
// Safefree(activelist); |
208
|
|
|
|
|
|
|
|
209
|
|
|
|
|
|
|
void |
210
|
|
|
|
|
|
|
_mainloop(self, node, index, nodes) |
211
|
|
|
|
|
|
|
Text_KnuthPlass self |
212
|
|
|
|
|
|
|
SV* node |
213
|
|
|
|
|
|
|
IV index |
214
|
|
|
|
|
|
|
AV* nodes |
215
|
|
|
|
|
|
|
|
216
|
|
|
|
|
|
|
CODE: |
217
|
|
|
|
|
|
|
// overrides _mainloop() in Perl |
218
|
147
|
|
|
|
|
|
LinkedList* activelist = (LinkedList*)(*hv_fetch((HV*)self, "activeNodes", 11, FALSE)); |
219
|
147
|
50
|
|
|
|
|
IV tolerance = ivHash(self, "tolerance"); |
220
|
147
|
50
|
|
|
|
|
IV infinity = ivHash(self, "infinity"); |
221
|
147
|
|
|
|
|
|
SV* demerits_r = *hv_fetch((HV*)self, "demerits", 8, FALSE); |
222
|
|
|
|
|
|
|
NV ratio = 0; |
223
|
|
|
|
|
|
|
IV nodepenalty = 0; |
224
|
|
|
|
|
|
|
NV demerits = 0; |
225
|
|
|
|
|
|
|
IV linedemerits = 0, flaggeddemerits = 0, fitnessdemerits = 0; |
226
|
|
|
|
|
|
|
Breakpoint* candidates[4]; |
227
|
|
|
|
|
|
|
NV badness; |
228
|
|
|
|
|
|
|
IV current_line = 0; |
229
|
|
|
|
|
|
|
HV* tmpsum; |
230
|
|
|
|
|
|
|
IV current_class = 0; |
231
|
147
|
|
|
|
|
|
Breakpoint* active = activelist->head; |
232
|
|
|
|
|
|
|
Breakpoint* next; |
233
|
|
|
|
|
|
|
|
234
|
147
|
50
|
|
|
|
|
if (demerits_r && SvRV(demerits_r)) { |
|
|
50
|
|
|
|
|
|
235
|
147
|
50
|
|
|
|
|
linedemerits = ivHash(SvRV(demerits_r), "line"); |
236
|
147
|
50
|
|
|
|
|
flaggeddemerits = ivHash(SvRV(demerits_r), "flagged"); |
237
|
147
|
50
|
|
|
|
|
fitnessdemerits = ivHash(SvRV(demerits_r), "fitness"); |
238
|
|
|
|
|
|
|
} else { |
239
|
0
|
|
|
|
|
|
croak("Demerits hash not properly set!"); |
240
|
|
|
|
|
|
|
} |
241
|
|
|
|
|
|
|
|
242
|
147
|
50
|
|
|
|
|
if (isPenalty(node)) { |
|
|
100
|
|
|
|
|
|
243
|
32
|
50
|
|
|
|
|
nodepenalty = SvIV(*hv_fetch((HV*)SvRV(node), "penalty", 7, TRUE)); |
244
|
|
|
|
|
|
|
} |
245
|
|
|
|
|
|
|
|
246
|
844
|
100
|
|
|
|
|
while (active) { |
247
|
|
|
|
|
|
|
int t; |
248
|
697
|
|
|
|
|
|
candidates[0] = NULL; candidates[1] = NULL; |
249
|
697
|
|
|
|
|
|
candidates[2] = NULL; candidates[3] = NULL; |
250
|
|
|
|
|
|
|
debug(warn("Outer\n")); |
251
|
5384
|
50
|
|
|
|
|
while (active) { |
252
|
|
|
|
|
|
|
|
253
|
5384
|
|
|
|
|
|
next = active->next; |
254
|
5384
|
|
|
|
|
|
IV position = active->position; |
255
|
|
|
|
|
|
|
|
256
|
|
|
|
|
|
|
debug(warn("Inner loop\n")); |
257
|
|
|
|
|
|
|
|
258
|
5384
|
|
|
|
|
|
current_line = 1+ active->line; |
259
|
|
|
|
|
|
|
/*warn("_mainloop, current_line=%i\n", current_line);*/ |
260
|
5384
|
|
|
|
|
|
ratio = _compute_cost(self, position, index, active, current_line, nodes); |
261
|
|
|
|
|
|
|
debug(warn("Got a ratio of %f\n", ratio)); |
262
|
|
|
|
|
|
|
|
263
|
5384
|
100
|
|
|
|
|
if (ratio < 1 || (isPenalty(node) && nodepenalty == -infinity)) { |
|
|
50
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
264
|
|
|
|
|
|
|
debug(warn("Dropping a node\n")); |
265
|
569
|
|
|
|
|
|
_unlinkKP(activelist, active); |
266
|
|
|
|
|
|
|
} |
267
|
|
|
|
|
|
|
|
268
|
5384
|
100
|
|
|
|
|
if (-1 <= ratio && ratio <= tolerance) { |
|
|
100
|
|
|
|
|
|
269
|
2439
|
|
|
|
|
|
SV* nodeAtPos = *av_fetch(nodes, position, FALSE); |
270
|
2439
|
|
|
|
|
|
badness = 100 * ratio * ratio * ratio; |
271
|
|
|
|
|
|
|
debug(warn("Badness is %f\n", badness)); |
272
|
2439
|
50
|
|
|
|
|
if (isPenalty(node) && nodepenalty > 0) { |
|
|
100
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
273
|
688
|
|
|
|
|
|
demerits = linedemerits + badness + nodepenalty; |
274
|
1751
|
50
|
|
|
|
|
} else if (isPenalty(node) && nodepenalty != -infinity) { |
|
|
100
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
275
|
0
|
|
|
|
|
|
demerits = linedemerits + badness - nodepenalty; |
276
|
|
|
|
|
|
|
} else { |
277
|
1751
|
|
|
|
|
|
demerits = linedemerits + badness; |
278
|
|
|
|
|
|
|
} |
279
|
2439
|
|
|
|
|
|
demerits = demerits * demerits; |
280
|
2439
|
50
|
|
|
|
|
if (isPenalty(node) && isPenalty(SvRV(nodeAtPos))) { |
|
|
100
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
281
|
0
|
|
|
|
|
|
demerits = demerits + (flaggeddemerits * |
282
|
0
|
0
|
|
|
|
|
ivHash(node, "flagged") * |
283
|
0
|
0
|
|
|
|
|
ivHash(SvRV(nodeAtPos), "flagged")); |
284
|
|
|
|
|
|
|
} |
285
|
|
|
|
|
|
|
|
286
|
2439
|
100
|
|
|
|
|
if (ratio < -0.5) current_class = 0; // tight |
287
|
2437
|
100
|
|
|
|
|
else if (ratio <= 0.5) current_class = 1; // normal |
288
|
2073
|
100
|
|
|
|
|
else if (ratio <= 1) current_class = 2; // loose |
289
|
|
|
|
|
|
|
else current_class = 3; // very loose |
290
|
|
|
|
|
|
|
|
291
|
2439
|
100
|
|
|
|
|
if (abs(current_class - active->fitness_class) > 1) |
292
|
594
|
|
|
|
|
|
demerits += fitnessdemerits; |
293
|
|
|
|
|
|
|
|
294
|
2439
|
|
|
|
|
|
demerits += active->demerits; |
295
|
|
|
|
|
|
|
|
296
|
2439
|
100
|
|
|
|
|
if (!candidates[current_class] || |
|
|
100
|
|
|
|
|
|
297
|
1853
|
|
|
|
|
|
demerits < candidates[current_class]->demerits) { |
298
|
|
|
|
|
|
|
debug(warn("Setting c %i\n", current_class)); |
299
|
1394
|
100
|
|
|
|
|
if (!candidates[current_class]) |
300
|
586
|
|
|
|
|
|
candidates[current_class] = _new_breakpoint(); |
301
|
1394
|
|
|
|
|
|
candidates[current_class]->active = active; |
302
|
1394
|
|
|
|
|
|
candidates[current_class]->demerits = demerits; |
303
|
1394
|
|
|
|
|
|
candidates[current_class]->ratio = ratio; |
304
|
|
|
|
|
|
|
} |
305
|
|
|
|
|
|
|
} |
306
|
|
|
|
|
|
|
active = next; |
307
|
5384
|
100
|
|
|
|
|
if (!active || active->line >= current_line) |
|
|
100
|
|
|
|
|
|
308
|
|
|
|
|
|
|
break; |
309
|
|
|
|
|
|
|
} |
310
|
|
|
|
|
|
|
debug(warn("Post inner loop\n")); |
311
|
|
|
|
|
|
|
|
312
|
|
|
|
|
|
|
|
313
|
3632
|
100
|
|
|
|
|
for (t = 0; t <= 3; t++) { |
314
|
2788
|
100
|
|
|
|
|
if (candidates[t]) { |
315
|
586
|
|
|
|
|
|
Breakpoint* newnode = _new_breakpoint(); |
316
|
586
|
|
|
|
|
|
HV* tmpsum = _compute_sum(self, index, nodes); |
317
|
586
|
|
|
|
|
|
newnode->position = index; |
318
|
586
|
|
|
|
|
|
newnode->demerits = candidates[t]->demerits; |
319
|
586
|
|
|
|
|
|
newnode->ratio = candidates[t]->ratio; |
320
|
586
|
|
|
|
|
|
newnode->line = candidates[t]->active->line + 1; |
321
|
586
|
|
|
|
|
|
newnode->fitness_class = t; |
322
|
586
|
|
|
|
|
|
newnode->totals = tmpsum; |
323
|
|
|
|
|
|
|
debug(warn("Setting previous to %p\n", candidates[t]->active)); |
324
|
586
|
|
|
|
|
|
newnode->previous = candidates[t]->active; |
325
|
586
|
100
|
|
|
|
|
if (active) { |
326
|
|
|
|
|
|
|
debug(warn("Before\n")); |
327
|
547
|
|
|
|
|
|
newnode->prev = active->prev; |
328
|
547
|
|
|
|
|
|
newnode->next = active; |
329
|
547
|
100
|
|
|
|
|
if (!active->prev) { activelist->head = newnode; } |
330
|
533
|
|
|
|
|
|
else { active->prev->next = newnode; } |
331
|
547
|
|
|
|
|
|
active->prev = newnode; |
332
|
547
|
|
|
|
|
|
activelist->list_size++; |
333
|
|
|
|
|
|
|
} else { |
334
|
|
|
|
|
|
|
debug(warn("After\n")); |
335
|
39
|
50
|
|
|
|
|
if (!activelist->head) { |
336
|
0
|
|
|
|
|
|
activelist->head = activelist->tail = newnode; |
337
|
0
|
|
|
|
|
|
newnode->prev = newnode->next = NULL; |
338
|
|
|
|
|
|
|
} else { |
339
|
39
|
|
|
|
|
|
newnode->prev = activelist->tail; |
340
|
39
|
|
|
|
|
|
newnode->next = NULL; |
341
|
39
|
|
|
|
|
|
activelist->tail->next = newnode; |
342
|
39
|
|
|
|
|
|
activelist->tail = newnode; |
343
|
39
|
|
|
|
|
|
activelist->list_size++; |
344
|
|
|
|
|
|
|
} |
345
|
|
|
|
|
|
|
} |
346
|
586
|
|
|
|
|
|
sv_free((SV*)candidates[t]->totals); |
347
|
586
|
|
|
|
|
|
Safefree(candidates[t]); |
348
|
|
|
|
|
|
|
} // demerits check (candidates[fitness class] > 0) |
349
|
|
|
|
|
|
|
} // fitness class (t) 0..3 loop |
350
|
|
|
|
|
|
|
} // while active loop |
351
|
|
|
|
|
|
|
|