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