This source file includes following definitions.
- diag
- compareseq
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77 #define OFFSET_MAX \
78 ((((OFFSET)1 << (sizeof (OFFSET) * CHAR_BIT - 2)) - 1) * 2 + 1)
79
80
81 #ifndef EARLY_ABORT
82 # define EARLY_ABORT(ctxt) false
83 #endif
84
85 #ifndef NOTE_ORDERED
86 # define NOTE_ORDERED false
87 #endif
88
89
90
91 #ifndef IF_LINT
92 # if defined GCC_LINT || defined lint
93 # define IF_LINT(Code) Code
94 # else
95 # define IF_LINT(Code)
96 # endif
97 #endif
98
99
100
101
102 struct context
103 {
104 #ifdef ELEMENT
105
106 ELEMENT const *xvec;
107 ELEMENT const *yvec;
108 #endif
109
110
111 EXTRA_CONTEXT_FIELDS
112
113
114
115
116 OFFSET *fdiag;
117
118
119
120
121 OFFSET *bdiag;
122
123 #ifdef USE_HEURISTIC
124
125
126
127 bool heuristic;
128 #endif
129
130
131 OFFSET too_expensive;
132
133
134 #define SNAKE_LIMIT 20
135 };
136
137 struct partition
138 {
139
140 OFFSET xmid;
141 OFFSET ymid;
142
143
144 bool lo_minimal;
145
146
147 bool hi_minimal;
148 };
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178 static void
179 diag (OFFSET xoff, OFFSET xlim, OFFSET yoff, OFFSET ylim, bool find_minimal,
180 struct partition *part, struct context *ctxt)
181 {
182 OFFSET *const fd = ctxt->fdiag;
183 OFFSET *const bd = ctxt->bdiag;
184 #ifdef ELEMENT
185 ELEMENT const *const xv = ctxt->xvec;
186 ELEMENT const *const yv = ctxt->yvec;
187 #define XREF_YREF_EQUAL(x,y) EQUAL (xv[x], yv[y])
188 #else
189 #define XREF_YREF_EQUAL(x,y) XVECREF_YVECREF_EQUAL (ctxt, x, y)
190 #endif
191 const OFFSET dmin = xoff - ylim;
192 const OFFSET dmax = xlim - yoff;
193 const OFFSET fmid = xoff - yoff;
194 const OFFSET bmid = xlim - ylim;
195 OFFSET fmin = fmid;
196 OFFSET fmax = fmid;
197 OFFSET bmin = bmid;
198 OFFSET bmax = bmid;
199 OFFSET c;
200 bool odd = (fmid - bmid) & 1;
201
202
203 fd[fmid] = xoff;
204 bd[bmid] = xlim;
205
206 for (c = 1;; ++c)
207 {
208 OFFSET d;
209 bool big_snake = false;
210
211
212 if (fmin > dmin)
213 fd[--fmin - 1] = -1;
214 else
215 ++fmin;
216 if (fmax < dmax)
217 fd[++fmax + 1] = -1;
218 else
219 --fmax;
220 for (d = fmax; d >= fmin; d -= 2)
221 {
222 OFFSET x;
223 OFFSET y;
224 OFFSET tlo = fd[d - 1];
225 OFFSET thi = fd[d + 1];
226 OFFSET x0 = tlo < thi ? thi : tlo + 1;
227
228 for (x = x0, y = x0 - d;
229 x < xlim && y < ylim && XREF_YREF_EQUAL (x, y);
230 x++, y++)
231 continue;
232 if (x - x0 > SNAKE_LIMIT)
233 big_snake = true;
234 fd[d] = x;
235 if (odd && bmin <= d && d <= bmax && bd[d] <= x)
236 {
237 part->xmid = x;
238 part->ymid = y;
239 part->lo_minimal = part->hi_minimal = true;
240 return;
241 }
242 }
243
244
245 if (bmin > dmin)
246 bd[--bmin - 1] = OFFSET_MAX;
247 else
248 ++bmin;
249 if (bmax < dmax)
250 bd[++bmax + 1] = OFFSET_MAX;
251 else
252 --bmax;
253 for (d = bmax; d >= bmin; d -= 2)
254 {
255 OFFSET x;
256 OFFSET y;
257 OFFSET tlo = bd[d - 1];
258 OFFSET thi = bd[d + 1];
259 OFFSET x0 = tlo < thi ? tlo : thi - 1;
260
261 for (x = x0, y = x0 - d;
262 xoff < x && yoff < y && XREF_YREF_EQUAL (x - 1, y - 1);
263 x--, y--)
264 continue;
265 if (x0 - x > SNAKE_LIMIT)
266 big_snake = true;
267 bd[d] = x;
268 if (!odd && fmin <= d && d <= fmax && x <= fd[d])
269 {
270 part->xmid = x;
271 part->ymid = y;
272 part->lo_minimal = part->hi_minimal = true;
273 return;
274 }
275 }
276
277 if (find_minimal)
278 continue;
279
280 #ifdef USE_HEURISTIC
281 bool heuristic = ctxt->heuristic;
282 #else
283 bool heuristic = false;
284 #endif
285
286
287
288
289
290
291
292
293
294 if (200 < c && big_snake && heuristic)
295 {
296 {
297 OFFSET best = 0;
298
299 for (d = fmax; d >= fmin; d -= 2)
300 {
301 OFFSET dd = d - fmid;
302 OFFSET x = fd[d];
303 OFFSET y = x - d;
304 OFFSET v = (x - xoff) * 2 - dd;
305
306 if (v > 12 * (c + (dd < 0 ? -dd : dd)))
307 {
308 if (v > best
309 && xoff + SNAKE_LIMIT <= x && x < xlim
310 && yoff + SNAKE_LIMIT <= y && y < ylim)
311 {
312
313
314 int k;
315
316 for (k = 1; XREF_YREF_EQUAL (x - k, y - k); k++)
317 if (k == SNAKE_LIMIT)
318 {
319 best = v;
320 part->xmid = x;
321 part->ymid = y;
322 break;
323 }
324 }
325 }
326 }
327 if (best > 0)
328 {
329 part->lo_minimal = true;
330 part->hi_minimal = false;
331 return;
332 }
333 }
334
335 {
336 OFFSET best = 0;
337
338 for (d = bmax; d >= bmin; d -= 2)
339 {
340 OFFSET dd = d - bmid;
341 OFFSET x = bd[d];
342 OFFSET y = x - d;
343 OFFSET v = (xlim - x) * 2 + dd;
344
345 if (v > 12 * (c + (dd < 0 ? -dd : dd)))
346 {
347 if (v > best
348 && xoff < x && x <= xlim - SNAKE_LIMIT
349 && yoff < y && y <= ylim - SNAKE_LIMIT)
350 {
351
352
353 int k;
354
355 for (k = 0; XREF_YREF_EQUAL (x + k, y + k); k++)
356 if (k == SNAKE_LIMIT - 1)
357 {
358 best = v;
359 part->xmid = x;
360 part->ymid = y;
361 break;
362 }
363 }
364 }
365 }
366 if (best > 0)
367 {
368 part->lo_minimal = false;
369 part->hi_minimal = true;
370 return;
371 }
372 }
373 }
374
375
376
377 if (c >= ctxt->too_expensive)
378 {
379 OFFSET fxybest;
380 OFFSET fxbest IF_LINT (= 0);
381 OFFSET bxybest;
382 OFFSET bxbest IF_LINT (= 0);
383
384
385 fxybest = -1;
386 for (d = fmax; d >= fmin; d -= 2)
387 {
388 OFFSET x = MIN (fd[d], xlim);
389 OFFSET y = x - d;
390 if (ylim < y)
391 {
392 x = ylim + d;
393 y = ylim;
394 }
395 if (fxybest < x + y)
396 {
397 fxybest = x + y;
398 fxbest = x;
399 }
400 }
401
402
403 bxybest = OFFSET_MAX;
404 for (d = bmax; d >= bmin; d -= 2)
405 {
406 OFFSET x = MAX (xoff, bd[d]);
407 OFFSET y = x - d;
408 if (y < yoff)
409 {
410 x = yoff + d;
411 y = yoff;
412 }
413 if (x + y < bxybest)
414 {
415 bxybest = x + y;
416 bxbest = x;
417 }
418 }
419
420
421 if ((xlim + ylim) - bxybest < fxybest - (xoff + yoff))
422 {
423 part->xmid = fxbest;
424 part->ymid = fxybest - fxbest;
425 part->lo_minimal = true;
426 part->hi_minimal = false;
427 }
428 else
429 {
430 part->xmid = bxbest;
431 part->ymid = bxybest - bxbest;
432 part->lo_minimal = false;
433 part->hi_minimal = true;
434 }
435 return;
436 }
437 }
438 #undef XREF_YREF_EQUAL
439 }
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458 static bool
459 compareseq (OFFSET xoff, OFFSET xlim, OFFSET yoff, OFFSET ylim,
460 bool find_minimal, struct context *ctxt)
461 {
462 #ifdef ELEMENT
463 ELEMENT const *xv = ctxt->xvec;
464 ELEMENT const *yv = ctxt->yvec;
465 #define XREF_YREF_EQUAL(x,y) EQUAL (xv[x], yv[y])
466 #else
467 #define XREF_YREF_EQUAL(x,y) XVECREF_YVECREF_EQUAL (ctxt, x, y)
468 #endif
469
470 while (true)
471 {
472
473 while (xoff < xlim && yoff < ylim && XREF_YREF_EQUAL (xoff, yoff))
474 {
475 xoff++;
476 yoff++;
477 }
478
479
480 while (xoff < xlim && yoff < ylim && XREF_YREF_EQUAL (xlim - 1, ylim - 1))
481 {
482 xlim--;
483 ylim--;
484 }
485
486
487 if (xoff == xlim)
488 {
489 while (yoff < ylim)
490 {
491 NOTE_INSERT (ctxt, yoff);
492 if (EARLY_ABORT (ctxt))
493 return true;
494 yoff++;
495 }
496 break;
497 }
498 if (yoff == ylim)
499 {
500 while (xoff < xlim)
501 {
502 NOTE_DELETE (ctxt, xoff);
503 if (EARLY_ABORT (ctxt))
504 return true;
505 xoff++;
506 }
507 break;
508 }
509
510 struct partition part;
511
512
513 diag (xoff, xlim, yoff, ylim, find_minimal, &part, ctxt);
514
515
516 OFFSET xoff1, xlim1, yoff1, ylim1, xoff2, xlim2, yoff2, ylim2;
517 bool find_minimal1, find_minimal2;
518 if (!NOTE_ORDERED
519 && ((xlim + ylim) - (part.xmid + part.ymid)
520 < (part.xmid + part.ymid) - (xoff + yoff)))
521 {
522
523
524
525 xoff1 = part.xmid; xlim1 = xlim;
526 yoff1 = part.ymid; ylim1 = ylim;
527 find_minimal1 = part.hi_minimal;
528
529 xoff2 = xoff; xlim2 = part.xmid;
530 yoff2 = yoff; ylim2 = part.ymid;
531 find_minimal2 = part.lo_minimal;
532 }
533 else
534 {
535 xoff1 = xoff; xlim1 = part.xmid;
536 yoff1 = yoff; ylim1 = part.ymid;
537 find_minimal1 = part.lo_minimal;
538
539 xoff2 = part.xmid; xlim2 = xlim;
540 yoff2 = part.ymid; ylim2 = ylim;
541 find_minimal2 = part.hi_minimal;
542 }
543
544
545 bool early = compareseq (xoff1, xlim1, yoff1, ylim1, find_minimal1, ctxt);
546 if (early)
547 return early;
548
549
550 xoff = xoff2; xlim = xlim2;
551 yoff = yoff2; ylim = ylim2;
552 find_minimal = find_minimal2;
553 }
554
555 return false;
556 #undef XREF_YREF_EQUAL
557 }
558
559 #undef ELEMENT
560 #undef EQUAL
561 #undef OFFSET
562 #undef EXTRA_CONTEXT_FIELDS
563 #undef NOTE_DELETE
564 #undef NOTE_INSERT
565 #undef EARLY_ABORT
566 #undef USE_HEURISTIC
567 #undef XVECREF_YVECREF_EQUAL
568 #undef OFFSET_MAX