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