this repo has no description
1#!/usr/bin/perl
2#
3# Main authors:
4# Christian Schulte <schulte@gecode.org>
5#
6# Copyright:
7# Christian Schulte, 2007
8#
9# This file is part of Gecode, the generic constraint
10# development environment:
11# http://www.gecode.org
12#
13# Permission is hereby granted, free of charge, to any person obtaining
14# a copy of this software and associated documentation files (the
15# "Software"), to deal in the Software without restriction, including
16# without limitation the rights to use, copy, modify, merge, publish,
17# distribute, sublicense, and/or sell copies of the Software, and to
18# permit persons to whom the Software is furnished to do so, subject to
19# the following conditions:
20#
21# The above copyright notice and this permission notice shall be
22# included in all copies or substantial portions of the Software.
23#
24# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
25# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
26# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
27# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
28# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
29# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
30# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
31#
32#
33
34while (($arg = $ARGV[$i]) && ($arg =~ /^-/)) {
35 $i++;
36 if ($arg eq "-header") {
37 $gen_header = 1;
38 } elsif ($arg eq "-typehpp") {
39 $gen_typehpp = 1;
40 }
41}
42
43$n_files = 0;
44while ($arg = $ARGV[$i]) {
45 $files[$n_files] = $arg;
46 $n_files++; $i++;
47}
48
49print <<EOF
50/*
51 * CAUTION:
52 * This file has been automatically generated. Do not edit,
53 * edit the following files instead:
54EOF
55;
56
57for ($f=0; $f<$n_files; $f++) {
58 print " * - $files[$f]\n";
59}
60
61print <<EOF
62 *
63 * This file contains generated code fragments which are
64 * copyrighted as follows:
65 *
66 * Main author:
67 * Christian Schulte <schulte\@gecode.org>
68 *
69 * Copyright:
70 * Christian Schulte, 2007
71 *
72 * The generated code fragments are part of Gecode, the generic
73 * constraint development environment:
74 * http://www.gecode.org
75 *
76 * Permission is hereby granted, free of charge, to any person obtaining
77 * a copy of this software and associated documentation files (the
78 * "Software"), to deal in the Software without restriction, including
79 * without limitation the rights to use, copy, modify, merge, publish,
80 * distribute, sublicense, and/or sell copies of the Software, and to
81 * permit persons to whom the Software is furnished to do so, subject to
82 * the following conditions:
83 *
84 * The above copyright notice and this permission notice shall be
85 * included in all copies or substantial portions of the Software.
86 *
87 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
88 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
89 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
90 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
91 * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
92 * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
93 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
94 *
95 */
96
97EOF
98;
99
100for ($f=0; $f<$n_files; $f++) {
101 open (FILE, $files[$f]) || die "Could not open ".$files[$f];
102
103 ## General values
104 $name[$f] = "";
105 $vti[$f] = "";
106 $ifdef[$f] = "";
107 $endif[$f] = "";
108 $dispose[$f] = 0;
109
110 ##
111 ## Headers and footers
112 ##
113 $mehdr[$f] = ""; # Header text for modification events
114 $meftr[$f] = ""; # Footer text for modification events
115
116 $pchdr[$f] = ""; # Header text for propagation conditions
117 $pcftr[$f] = ""; # Footer text for propagation conditions
118
119 ##
120 ## Real stuff
121 ##
122
123 # $mec[$f] : combination table
124 # $men[$f] : name table
125 # $meh[$f] : header table
126 $me_n[$f] = 0; # running number of modification events
127 $me_subscribe[$f] = "";
128
129 # $pcn[$f] : name table
130 # $pch[$f] : header table
131 $pc_n[$f] = 0; # running number of propagation conditions
132
133
134 $free_bits[$f] = 0;
135
136 while ($l = <FILE>) {
137 LINE:
138 next if ($l =~ /^\#/);
139 last if ($l =~ /^\[End\]/io);
140
141 if ($l =~ /^\[General\]/io) {
142 while (($l = <FILE>) && !($l =~ /^\[/)) {
143 next if ($l =~ /^\#/);
144 if ($l =~ /^Name:\s*(\w+)/io) {
145 $name[$f] = $1;
146 $vti[$f] = uc($name[$f]);
147 } elsif ($l =~ /^Ifdef:\s*(\w+)/io) {
148 $ifdef[$f] = "#ifdef $1\n";
149 $endif[$f] = "#endif\n";
150 } elsif ($l =~ /^Dispose:\s*true/io) {
151 $dispose[$f] = 1;
152 } elsif ($l =~ /^Namespace:\s*([^ \t\r\n]+)/io) {
153 $namespace[$f] = $1;
154 } elsif ($l =~ /^Bits:\s*([^ \t\r\n]+)/io) {
155 $free_bits[$f] = $1+0;
156 }
157 }
158 goto LINE;
159 } elsif ($l =~ /^\[ModEventHeader\]/io) {
160 while (($l = <FILE>) && !($l =~ /^\[/)) {
161 next if ($l =~ /^\#/);
162 $mehdr[$f] = $mehdr[$f] . $l;
163 }
164 goto LINE;
165 } elsif ($l =~ /^\[ModEvent\]/io) {
166 $n = "";
167 $h = "";
168
169 while (($l = <FILE>) && !($l =~ /^\[/)) {
170 next if ($l =~ /^\#/);
171 if ($l =~ /^Name:\s*(\w+)\s*=\s*(\w+)/io) {
172 # Found a special modification event
173 $lhs = $1; $rhs = $2;
174 if (!($rhs eq "FAILED") && !($rhs eq "NONE") &&
175 !($rhs eq "ASSIGNED") && !($rhs eq "SUBSCRIBE")) {
176 die "Unknown special modification event: $rhs\n";
177 }
178 if ($rhs eq "SUBSCRIBE") {
179 $me_subscribe[$f] = "ME_$vti[$f]_$lhs";
180 } else {
181 $mespecial{$f}{$lhs} = $rhs;
182 if ($rhs eq "ASSIGNED") {
183 $me_assigned[$f] = "ME_$vti[$f]_$lhs";
184 } elsif ($rhs eq "FAILED") {
185 $me_failed[$f] = "ME_$vti[$f]_$lhs";
186 }
187 }
188 $n = $lhs;
189 } elsif ($l =~ /^Name:\s*(\w+)/io) {
190 # Found a normal modification event
191 $n = $1;
192 } elsif ($l =~ /^Combine:\s*(.+)/io) {
193 # Found combination information
194 $combines = $1;
195 while ($combines =~ /(\w+)\s*=(\w+)/g) {
196 $mec{$f}{$n}{$1} = $2;
197 $mec{$f}{$1}{$n} = $2;
198 }
199 } else {
200 $h = $h . $l;
201 }
202 }
203 $men[$f][$me_n[$f]] = $n;
204 $meh[$f][$me_n[$f]] = $h;
205 $me_n[$f]++;
206 $mec{$f}{"NONE"}{$n} = $n;
207 $mec{$f}{$n}{"NONE"} = $n;
208 goto LINE;
209 } elsif ($l =~ /^\[ModEventFooter\]/io) {
210 while (($l = <FILE>) && !($l =~ /^\[/)) {
211 next if ($l =~ /^\#/);
212 $meftr[$f] = $meftr[$f] . $l;
213 }
214 goto LINE;
215 } elsif ($l =~ /^\[PropCondHeader\]/io) {
216 while (($l = <FILE>) && !($l =~ /^\[/)) {
217 next if ($l =~ /^\#/);
218 $pchdr[$f] = $pchdr[$f] . $l;
219 }
220 goto LINE;
221 } elsif ($l =~ /^\[PropCond\]/io) {
222 $n = "";
223 $h = "";
224
225 while (($l = <FILE>) && !($l =~ /^\[/)) {
226 next if ($l =~ /^\#/);
227 if ($l =~ /^Name:\s*(\w+)\s*=\s*(\w+)/io) {
228 # Found a special propagation condition
229 $lhs = $1; $rhs = $2;
230 if (!($rhs eq "ASSIGNED") && !($rhs eq "NONE")) {
231 die "Unknown special propagation condition: $rhs\n";
232 }
233 $pcspecial{$f}{$lhs} = $rhs;
234 if ($rhs eq "ASSIGNED") {
235 $pc_assigned[$f] = "PC_$vti[$f]_$lhs";
236 }
237 if ($rhs eq "NONE") {
238 $pc_none[$f] = "PC_$vti[$f]_$lhs";
239 }
240 $n = $lhs;
241 } elsif ($l =~ /^Name:\s*(\w+)/io) {
242 # Found a normal modification event
243 $n = $1;
244 } elsif ($l =~ /^ScheduledBy:\s*(.+)/io) {
245 # Found relation to modification events
246 $events = $1;
247 while ($events =~ /(\w+)/g) {
248 $mepc{$f}{$1}{$n} = 1;
249 }
250 } else {
251 $h = $h . $l;
252 }
253 }
254 $pcn[$f][$pc_n[$f]] = $n;
255 $pch[$f][$pc_n[$f]] = $h;
256 $pc_n[$f]++;
257 goto LINE;
258 } elsif ($l =~ /^\[PropCondFooter\]/io) {
259 while (($l = <FILE>) && !($l =~ /^\[/)) {
260 next if ($l =~ /^\#/);
261 $pcftr[$f] = $pcftr[$f] . $l;
262 }
263 goto LINE;
264 }
265
266 }
267 close FILE;
268
269
270 $maxpc[$f] = "PC_$vti[$f]_" . $pcn[$f][$pc_n[$f]-1];
271 $class[$f] = "$name[$f]VarImpBase";
272 $conf[$f] = "$name[$f]VarImpConf";
273 $base[$f] = "Gecode::VarImp<$namespace[$f]::$conf[$f]>";
274 # Generate namespace header and footer
275 foreach $ns (split('::',$namespace[$f])) {
276 $hdr[$f] = "$hdr[$f]namespace $ns { ";
277 $ftr[$f] = "$ftr[$f]}";
278 }
279 $hdr[$f] =~ s| $||g;
280 $hdr[$f] = "$hdr[$f]\n";
281 $ftr[$f] = "$ftr[$f]\n";
282
283 ## Check whether there is only one real event
284 if ($me_n[$f] == 3) {
285 $me_subscribe[$f] = $me_assigned[$f];
286 }
287
288 if (!$me_subscribe[$f]) {
289 die "Missing special event specification = SUBSCRIBE";
290 }
291
292 $o = 2;
293 for ($i=0; $i<$me_n[$f]; $i++) {
294 $n = $men[$f][$i];
295 if ($mespecial{$f}{$n} eq "NONE") {
296 $val2me[$f][0] = $n;
297 } elsif ($mespecial{$f}{$n} eq "ASSIGNED") {
298 $val2me[$f][1] = $n;
299 } elsif (!$mespecial{$f}{$n}) {
300 $val2me[$f][$o] = $n; $o++;
301 }
302 }
303 $me_max[$f] = "ME_$vti[$f]_" . $val2me[$f][$o-1] . "+1";
304 $me_max_n[$f] = $o;
305
306 $len = 0;
307 for ($i=0; $i<$me_max_n[$f];$i++) {
308 $n = $val2me[$f][$i];
309 $me_a{$f}{$n} = "ME_$vti[$f]_$n";
310 if (length($me_a{$f}{$n}) > $len) {
311 $len = length($me_a{$f}{$n});
312 }
313 }
314 for ($i=0; $i<$me_max_n[$f]; $i++) {
315 $n = $val2me[$f][$i];
316 while ($len > length($me_a{$f}{$n})) {
317 $me_a{$f}{$n} = "$me_a{$f}{$n} ";
318 }
319 }
320
321 for ($b=1; (1 << $b) < $me_max_n[$f]; $b++) {}
322 $bits[$f] = $b;
323}
324
325if ($gen_typehpp) {
326 for ($f = 0; $f<$n_files; $f++) {
327 print $ifdef[$f];
328 print $hdr[$f];
329 print $mehdr[$f];
330 $o = 1;
331 for ($i=0; $i<$me_n[$f]; $i++) {
332 $n = $men[$f][$i];
333 print $meh[$f][$i];
334 print " const Gecode::ModEvent ME_" . $vti[$f] . "_${n} = ";
335 if ($mespecial{$f}{$n}) {
336 print "Gecode::ME_GEN_" . $mespecial{$f}{$n};
337 } else {
338 print "Gecode::ME_GEN_ASSIGNED + " . $o;
339 $o++;
340 }
341 print ";\n";
342 }
343
344 print $meftr[$f];
345 print $pchdr[$f];
346
347 $o = 1;
348 for ($i=0; $i<$pc_n[$f]; $i++) {
349 $n = $pcn[$f][$i];
350 print $pch[$f][$i];
351 print " const Gecode::PropCond PC_$vti[$f]_${n} = ";
352 if ($pcspecial{$f}{$n}) {
353 print "Gecode::PC_GEN_" . $pcspecial{$f}{$n};
354 } else {
355 print "Gecode::PC_GEN_ASSIGNED + " . $o;
356 $o++;
357 }
358 print ";\n";
359 }
360 print $pcftr[$f];
361 print $ftr[$f];
362 print $endif[$f];
363 }
364
365
366 for ($f = 0; $f<$n_files; $f++) {
367 print $ifdef[$f];
368 if ($dispose[$f]) {
369 print "\n#ifndef GECODE_HAS_VAR_DISPOSE\n";
370 print "#define GECODE_HAS_VAR_DISPOSE 1\n";
371 print "#endif\n\n";
372 }
373 print $hdr[$f];
374 print " /// Configuration for $name[$f]-variable implementations\n";
375 print " class $conf[$f] {\n";
376 print " public:\n";
377 print " /// Index for cloning\n";
378 print " static const int idx_c = ";
379 if ($f == 0) {
380 print "0;\n";
381 } else {
382 print "$namespace[$f-1]::$conf[$f-1]::idx_c+1;\n";
383 }
384 print " /// Index for disposal\n";
385 print " static const int idx_d = ";
386 if ($dispose[$f]) {
387 if ($f == 0) {
388 print "0;\n";
389 } else {
390 print "$namespace[$f-1]::$conf[$f-1]::idx_d+1;\n";
391 }
392 } else {
393 if ($f == 0) {
394 print "-1;\n";
395 } else {
396 print "$namespace[$f-1]::$conf[$f-1]::idx_d;\n";
397 }
398 }
399 print " /// Maximal propagation condition\n";
400 print " static const Gecode::PropCond pc_max = $maxpc[$f];\n";
401 print " /// Freely available bits\n";
402 print " static const int free_bits = $free_bits[$f];\n";
403 print " /// Start of bits for modification event delta\n";
404 print " static const int med_fst = ";
405 if ($f == 0) {
406 print "0;\n";
407 } else {
408 print "$namespace[$f-1]::$conf[$f-1]::med_lst;\n";
409 }
410 print " /// End of bits for modification event delta\n";
411 print " static const int med_lst = med_fst + $bits[$f];\n";
412 print " /// Bitmask for modification event delta\n";
413 print " static const int med_mask = ((1 << $bits[$f]) - 1) << med_fst;\n";
414 print " /// Combine modification events \\a me1 and \\a me2\n";
415 print " static Gecode::ModEvent me_combine(Gecode::ModEvent me1, Gecode::ModEvent me2);\n";
416 print " /// Update modification even delta \\a med by \\a me, return true on change\n";
417 print " static bool med_update(Gecode::ModEventDelta& med, Gecode::ModEvent me);\n";
418 print " };\n";
419 print $ftr[$f];
420 if (!($ifdef[$f] eq "")) {
421 print "#else\n";
422 print $hdr[$f];
423 print " /// Dummy configuration for $name[$f]-variable implementations\n";
424 print " class $conf[$f] {\n";
425 print " public:\n";
426 print " /// Index for cloning\n";
427 print " static const int idx_c = ";
428 if ($f == 0) {
429 print "-1;\n";
430 } else {
431 print "$namespace[$f-1]::$conf[$f-1]::idx_c;\n";
432 }
433 print " /// Index for disposal\n";
434 print " static const int idx_d = ";
435 if ($f == 0) {
436 print "-1;\n";
437 } else {
438 print "$namespace[$f-1]::$conf[$f-1]::idx_d;\n";
439 }
440 print " /// End of bits for modification event delta\n";
441 print " static const int med_lst = ";
442 if ($f == 0) {
443 print "0;\n";
444 } else {
445 print "$namespace[$f-1]::$conf[$f-1]::med_lst;\n";
446 }
447 print " };\n";
448 print $ftr[$f];
449 }
450 print $endif[$f];
451 }
452 print "\n";
453 print "namespace Gecode {\n\n";
454 print " /// Configuration for all variable implementations\n";
455 print " class AllVarConf {\n";
456 print " public:\n";
457 print " /// Index for cloning\n";
458 print " static const int idx_c = $namespace[$n_files-1]::$conf[$n_files-1]::idx_c+1;\n";
459 print " /// Index for dispose\n";
460 print " static const int idx_d = $namespace[$n_files-1]::$conf[$n_files-1]::idx_d+1;\n";
461 print " /// Combine modification event delta \\a med1 with \\a med2\n";
462 print " static ModEventDelta med_combine(ModEventDelta med1, ModEventDelta med2);\n";
463 print " };\n\n}\n\n";
464 for ($f = 0; $f<$n_files; $f++) {
465 print $ifdef[$f];
466 print $hdr[$f];
467 print " forceinline Gecode::ModEvent\n";
468 print " $conf[$f]::me_combine(Gecode::ModEvent me1, Gecode::ModEvent me2) {\n";
469
470 if ($me_max_n[$f] == 2) {
471 print " return me1 | me2;\n";
472 } elsif ($me_max_n[$f] <= 4) {
473 print " static const Gecode::ModEvent me_c = (\n";
474
475 for ($i=0; $i<$me_max_n[$f];$i++) {
476 $n1 = $val2me[$f][$i];
477 print " (\n";
478 for ($j=0; $j<$me_max_n[$f];$j++) {
479 $n2 = $val2me[$f][$j];
480 $n3 = $mec{$f}{$n1}{$n2};
481 $shift = (($i << 3) + ($j << 1));
482 if ($shift < 10) {
483 $shift = " $shift";
484 }
485 print " ($me_a{$f}{$n3} << $shift)";
486 if ($j+1 == $me_max_n[$f]) {
487 print " ";
488 } else {
489 print " | ";
490 }
491 print " // [$me_a{$f}{$n1}][$me_a{$f}{$n2}]\n";
492 }
493 if ($i+1 == $me_max_n[$f]) {
494 print " )\n";
495 } else {
496 print " ) |\n";
497 }
498 }
499 print " );\n";
500 print " return ((me_c >> (me2 << 3)) >> (me1 << 1)) & 3;\n";
501 } else {
502 print " static const Gecode::ModEvent me_c[$me_max[$f]][$me_max[$f]] = {\n";
503 for ($i=0; $i<$me_max_n[$f];$i++) {
504 $n1 = $val2me[$f][$i];
505 print " {\n";
506 for ($j=0; $j<$me_max_n[$f];$j++) {
507 $n2 = $val2me[$f][$j];
508 $n3 = $mec{$f}{$n1}{$n2};
509 print " $me_a{$f}{$n3}";
510 if ($j+1 == $me_max_n[$f]) {
511 print " ";
512 } else {
513 print ",";
514 }
515 print " // [$me_a{$f}{$n1}][$me_a{$f}{$n2}]\n";
516 }
517 print " }";
518 if ($i+1 == $me_max_n[$f]) {
519 print "\n";
520 } else {
521 print ",\n";
522 }
523 }
524 print " };\n";
525 print " return me_c[me1][me2];\n";
526 }
527 print " }\n";
528 print " forceinline bool\n";
529 print " $conf[$f]::med_update(Gecode::ModEventDelta& med, Gecode::ModEvent me) {\n";
530
531 print " switch (me) {\n";
532 if ($me_max_n[$f] == 2) {
533 $ME_NONE = "ME_$vti[$f]_NONE";
534 if ($val2me[$f][0] eq "NONE") {
535 $ME_ASSIGNED = "ME_$vti[$f]_$val2me[$f][1]";
536 } else {
537 $ME_ASSIGNED = "ME_$vti[$f]_$val2me[$f][0]";
538 }
539 print " case $ME_NONE:\n";
540 print " return false;\n";
541 print " case $ME_ASSIGNED:\n";
542 print " if ((med & ($ME_ASSIGNED << med_fst)) != 0)\n";
543 print " return false;\n";
544 print " med |= $ME_ASSIGNED << med_fst;\n";
545 print " break;\n";
546 } else {
547 $lvti = lc($vti[$f]);
548 for ($i=0; $i<$me_max_n[$f];$i++) {
549 $n1 = $val2me[$f][$i];
550 $weak = 1;
551 for ($j=0; $j<$me_max_n[$f];$j++) {
552 $n2 = $val2me[$f][$j];
553 if (!($n2 eq "NONE") && !($n2 eq $n1) &&
554 !($mec{$f}{$n1}{$n2} eq $n2)) {
555 $weak = 0;
556 }
557 }
558 print " case ME_$vti[$f]_$n1:\n";
559 if ($n1 eq "NONE") {
560 print " return false;\n";
561 } elsif ($mespecial{$f}{$n1} eq "ASSIGNED") {
562 print " {\n";
563 print " Gecode::ModEventDelta med_$lvti = med & med_mask;\n";
564 print " if (med_$lvti == (ME_$vti[$f]_$n1 << med_fst))\n";
565 print " return false;\n";
566 print " med ^= med_$lvti;\n";
567 print " med ^= ME_$vti[$f]_$n1 << med_fst;\n";
568 print " break;\n";
569 print " }\n";
570 } elsif ($weak) {
571 print " {\n";
572 print " Gecode::ModEventDelta med_$lvti = med & med_mask;\n";
573 print " if (med_$lvti != 0)\n";
574 print " return false;\n";
575 print " med |= ME_$vti[$f]_$n1 << med_fst;\n";
576 print " break;\n";
577 print " }\n";
578 } else {
579 print " {\n";
580 if ($me_max_n[$f] <= 8) {
581 print " static const Gecode::ModEvent me_c = (\n";
582 for ($j=0; $j<$me_max_n[$f];$j++) {
583 $n2 = $val2me[$f][$j];
584 $n3 = $mec{$f}{$n1}{$n2};
585 $shift = $j << 2;
586 if ($shift < 10) {
587 $shift = " $shift";
588 }
589 print " (($me_a{$f}{$n2} ^ $me_a{$f}{$n3}) << $shift)";
590 if ($j+1 != $me_max_n[$f]) {
591 print " |\n";
592 }
593 }
594 print "\n );\n";
595 print " Gecode::ModEvent me_o = (med & med_mask) >> med_fst;\n";
596 print " Gecode::ModEvent me_n = (me_c >> (me_o << 2)) & (med_mask >> med_fst);\n";
597 print " if (me_n == 0)\n";
598 print " return false;\n";
599 print " med ^= me_n << med_fst;\n";
600 print " break;\n";
601 } else {
602 print " static const Gecode::ModEventDelta me_c[$me_max[$f]] = {\n";
603 for ($j=0; $j<$me_max_n[$f];$j++) {
604 $n2 = $val2me[$f][$j];
605 $n3 = $mec{$f}{$n1}{$n2};
606 print " ($me_a{$f}{$n2} ^ $me_a{$f}{$n3}) << med_fst";
607 if ($j+1 != $me_max_n[$f]) {
608 print ",\n";
609 }
610 }
611 print "\n };\n";
612 print " Gecode::ModEvent me_o = (med & med_mask) >> med_fst;\n";
613 print " Gecode::ModEventDelta med_n = me_c[me_o];\n";
614 print " if (med_n == 0)\n";
615 print " return false;\n";
616 print " med ^= med_n;\n";
617 print " break;\n";
618 }
619 print " }\n";
620 }
621 }
622 }
623 print " default: GECODE_NEVER;\n";
624 print " }\n";
625 print " return true;\n";
626 print " }\n\n";
627 print $ftr[$f];
628 print $endif[$f];
629 }
630 print "namespace Gecode {\n";
631 print " forceinline ModEventDelta\n";
632 print " AllVarConf::med_combine(ModEventDelta med1, ModEventDelta med2) {\n";
633 for ($f = 0; $f<$n_files; $f++) {
634 $vic = "$namespace[$f]::$conf[$f]";
635 print $ifdef[$f];
636 print " (void) ${vic}::med_update(med1,(med2 & ${vic}::med_mask) >> ${vic}::med_fst);\n";
637 print $endif[$f];
638 }
639 print " return med1;\n";
640 print " }\n}\n\n";
641}
642
643if ($gen_header) {
644 for ($f = 0; $f<$n_files; $f++) {
645 print $ifdef[$f];
646 print $hdr[$f];
647 print " /// Base-class for $name[$f]-variable implementations\n";
648 print " class $class[$f] : public $base[$f] {\n";
649 if ($dispose[$f]) {
650 print <<EOF
651 private:
652 /// Link to next variable, used for disposal
653 $class[$f]* _next_d;
654EOF
655;
656 }
657
658 print <<EOF
659 protected:
660 /// Constructor for cloning \\a x
661 $class[$f](Gecode::Space& home, $class[$f]\& x);
662 public:
663 /// Constructor for creating static instance of variable
664 $class[$f](void);
665 /// Constructor for creating variable
666 $class[$f](Gecode::Space& home);
667 /// \\name Dependencies
668 //\@{
669 /** \\brief Subscribe propagator \\a p with propagation condition \\a pc
670 *
671 * In case \\a schedule is false, the propagator is just subscribed but
672 * not scheduled for execution (this must be used when creating
673 * subscriptions during propagation).
674 *
675 * In case the variable is assigned (that is, \\a assigned is
676 * true), the subscribing propagator is scheduled for execution.
677 * Otherwise, the propagator subscribes and is scheduled for execution
678 * with modification event \\a me provided that \\a pc is different
679 * from \\a $pc_assigned[$f].
680 */
681 void subscribe(Gecode::Space& home, Gecode::Propagator& p, Gecode::PropCond pc, bool assigned, bool schedule);
682 /// Subscribe advisor \\a a if \\a assigned is false.
683 void subscribe(Gecode::Space& home, Gecode::Advisor& a, bool assigned, bool failed);
684 /// Notify that variable implementation has been modified with modification event \\a me and delta information \\a d
685 Gecode::ModEvent notify(Gecode::Space& home, Gecode::ModEvent me, Gecode::Delta& d);
686 /// \\brief Schedule propagator \\a p
687 static void schedule(Gecode::Space& home, Gecode::Propagator& p, Gecode::ModEvent me);
688 /** \\brief Re-schedule propagator \\a p
689 *
690 * In case the variable is assigned (that is, \\a assigned is
691 * true), the propagator is scheduled for execution.
692 * Otherwise, the propagator is scheduled for execution
693 * with modification event \\a me provided that \\a pc is different
694 * from \\a $pc_assigned[$f].
695 */
696 void reschedule(Gecode::Space& home, Gecode::Propagator& p, Gecode::PropCond pc, bool assigned);
697 //\@}
698EOF
699;
700
701 if ($dispose[$f]) {
702 print <<EOF
703 /// Return link to next variable to be disposed
704 $class[$f]* next_d(void) const;
705EOF
706;
707 }
708
709 print <<EOF
710 };
711EOF
712;
713
714 print $ftr[$f];
715 print $endif[$f];
716
717
718}
719
720 for ($f = 0; $f<$n_files; $f++) {
721 print $ifdef[$f];
722 print $hdr[$f];
723
724if ($dispose[$f]) {
725 print <<EOF
726
727 forceinline
728 $class[$f]::$class[$f](void) {}
729
730 forceinline
731 $class[$f]::$class[$f](Gecode::Space& home)
732 : $base[$f](home) {
733 _next_d = static_cast<$class[$f]*>(vars_d(home)); vars_d(home,this);
734 }
735
736 forceinline
737 $class[$f]::$class[$f](Gecode::Space& home, $class[$f]\& x)
738 : $base[$f](home,x) {
739 _next_d = static_cast<$class[$f]*>(vars_d(home)); vars_d(home,this);
740 }
741
742 forceinline $class[$f]*
743 $class[$f]::next_d(void) const {
744 return _next_d;
745 }
746
747EOF
748;
749} else {
750 print <<EOF
751
752 forceinline
753 $class[$f]::$class[$f](void) {}
754
755 forceinline
756 $class[$f]::$class[$f](Gecode::Space& home)
757 : $base[$f](home) {}
758
759 forceinline
760 $class[$f]::$class[$f](Gecode::Space& home, $class[$f]\& x)
761 : $base[$f](home,x) {}
762EOF
763;
764}
765 print <<EOF
766
767 forceinline void
768 $class[$f]::subscribe(Gecode::Space& home, Gecode::Propagator& p, Gecode::PropCond pc, bool assigned, bool schedule) {
769 $base[$f]::subscribe(home,p,pc,assigned,$me_subscribe[$f],schedule);
770 }
771 forceinline void
772 $class[$f]::subscribe(Gecode::Space& home, Gecode::Advisor& a, bool assigned, bool failed) {
773 $base[$f]::subscribe(home,a,assigned,failed);
774 }
775
776 forceinline void
777 $class[$f]::schedule(Gecode::Space& home, Gecode::Propagator& p, Gecode::ModEvent me) {
778 $base[$f]::schedule(home,p,me);
779 }
780 forceinline void
781 $class[$f]::reschedule(Gecode::Space& home, Gecode::Propagator& p, Gecode::PropCond pc, bool assigned) {
782 $base[$f]::reschedule(home,p,pc,assigned,$me_subscribe[$f]);
783 }
784
785EOF
786;
787
788if ($me_max_n[$f] == 2) {
789 print <<EOF
790 forceinline Gecode::ModEvent
791 $class[$f]::notify(Gecode::Space& home, Gecode::ModEvent, Gecode::Delta& d) {
792 $base[$f]::schedule(home,$pc_assigned[$f],$pc_assigned[$f],$me_assigned[$f]);
793 if (!$base[$f]::advise(home,$me_assigned[$f],d))
794 return $me_failed[$f];
795 cancel(home);
796 return $me_assigned[$f];
797 }
798
799EOF
800;
801} else {
802 print <<EOF
803 forceinline Gecode::ModEvent
804 $class[$f]::notify(Gecode::Space& home, Gecode::ModEvent me, Gecode::Delta& d) {
805 switch (me) {
806EOF
807;
808
809 for ($i=0; $i<$pc_n[$f]; $i++) {
810 if ($pcspecial{$f}{$pcn[$f][$i]} eq "ASSIGNED") {
811 $val2pc[$f][0] = $pcn[$f][$i];
812 }
813 }
814 $o = 1;
815 for ($i=0; $i<$pc_n[$f]; $i++) {
816 if (!($pcspecial{$f}{$pcn[$f][$i]} eq "ASSIGNED") &&
817 !($pcspecial{$f}{$pcn[$f][$i]} eq "NONE")) {
818 $val2pc[$f][$o] = $pcn[$f][$i]; $o++;
819 }
820 }
821
822 for ($i=0; $i<$me_n[$f]; $i++) {
823 $n = $men[$f][$i];
824 if (!($mespecial{$f}{$n} eq "NONE") && !($mespecial{$f}{$n} eq "FAILED")) {
825 print " case ME_$vti[$f]_$n:\n";
826 print " // Conditions: ";
827 $fst = 1;
828 for ($j=0; $j<$pc_n[$f]; $j++) {
829 if ($mepc{$f}{$men[$f][$i]}{$pcn[$f][$j]}) {
830 if ($fst) {
831 $fst = 0;
832 } else {
833 print ", ";
834 }
835 print $pcn[$f][$j];
836 }
837 }
838 print "\n";
839 for ($j=0; $j<$pc_n[$f]; $j++) {
840 if ($mepc{$f}{$men[$f][$i]}{$val2pc[$f][$j]}) {
841 # Found initial entry (plus one for stopping)
842 print " $base[$f]::schedule(home,PC_$vti[$f]_" . $val2pc[$f][$j] . ",";
843 # Look for all connected entries
844 while ($mepc{$f}{$men[$f][$i]}{$val2pc[$f][$j+1]}) {
845 $j++;
846 }
847 # Found last entry
848 print "PC_$vti[$f]_" . $val2pc[$f][$j] . ",ME_$vti[$f]_$n);\n";
849 }
850 }
851 print " if (!$base[$f]::advise(home,ME_$vti[$f]_$n,d))\n";
852 print " return $me_failed[$f];\n";
853 if ($mespecial{$f}{$n} eq "ASSIGNED") {
854 print " cancel(home);\n";
855 }
856 print " break;\n";
857 }
858 }
859
860
861 print <<EOF
862 default: GECODE_NEVER;
863 }
864 return me;
865 }
866
867EOF
868;
869}
870 print $ftr[$f];
871 print $endif[$f];
872}
873
874 print <<EOF
875namespace Gecode {
876
877 forceinline void
878 Space::update(ActorLink** sub) {
879EOF
880;
881
882 for ($f = 0; $f<$n_files; $f++) {
883 print $ifdef[$f];
884 print " $base[$f]::update(*this,sub);\n";
885 print $endif[$f];
886 }
887
888 print <<EOF
889 }
890}
891EOF
892;
893
894
895
896}
897
898print "// STATISTICS: kernel-var\n";