| 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
|
|
|
|
|
|
|
|