Browse Source

Add stencil example

Samuel Thibault 14 years ago
parent
commit
58330fd908

+ 2 - 2
Makefile.am

@@ -17,11 +17,11 @@
 ACLOCAL_AMFLAGS=-I m4
 CLEANFILES = *.gcno *.gcda *.linkinfo
 
-SUBDIRS = src tools examples tests doc
-
+SUBDIRS = src
 if USE_MPI
 SUBDIRS += mpi
 endif
+SUBDIRS += tools examples tests doc
 
 pkgconfigdir = $(libdir)/pkgconfig
 pkgconfig_DATA = libstarpu.pc

+ 11 - 2
configure.ac

@@ -704,12 +704,20 @@ fi
 AC_MSG_CHECKING(mpicc path)
 AC_MSG_RESULT($mpicc_path)
 AC_SUBST(MPICC, $mpicc_path)
+if test x$user_mpi = xyes; then
+	cc_or_mpicc=$mpicc_path
+else
+	cc=$CC
+fi
+AC_SUBST(CC_OR_MPICC, $mpicc_path)
 
-AC_MSG_CHECKING(whether the MPI library should be generated)
+AC_MSG_CHECKING(whether the StarPU MPI library should be generated)
 AC_MSG_RESULT($use_mpi)
 AC_SUBST(USE_MPI, $use_mpi)
-
 AM_CONDITIONAL(USE_MPI, test x$use_mpi = xyes)
+if test x$use_mpi = xyes; then
+	AC_DEFINE(STARPU_USE_MPI,[],[whether the StarPU MPI library is available])
+fi
 
 ###############################################################################
 #                                                                             #
@@ -872,6 +880,7 @@ AC_OUTPUT([
 	libstarpu.pc
 	examples/Makefile
 	examples/starpufft/Makefile
+	examples/stencil/Makefile
 	tests/Makefile
 	doc/Makefile
 	mpi/Makefile

+ 3 - 1
examples/Makefile.am

@@ -21,9 +21,11 @@ AM_CPPFLAGS = -I$(top_srcdir)/include/ -I$(top_srcdir)/examples/ -I$(top_builddi
 TESTS	=	coverage/coverage.sh	\
 		$(check_PROGRAMS)
 
+SUBDIRS = stencil
+
 if STARPU_HAVE_FFTW
 if STARPU_HAVE_FFTWL
-SUBDIRS = starpufft
+SUBDIRS += starpufft
 endif
 endif
 

+ 79 - 0
examples/stencil/0.5.out

@@ -0,0 +1,79 @@
+| 0 0 2 0 2 1 2 1 0 1 2 1 0 1 0 1 0 0 1 0 2 0 2 1 0 1 1 0 2 0 2 1 0 2 0 0 1 0 2 2 0 1 0 1 2 1 2 1 0 0 2 0 1 0 0 1 0 1 2 0 2 2 1 0 
+| 0 0 0 2 2 2 1 2 1 1 1 1 1 0 1 0 0 0 0 1 0 2 1 1 1 1 1 2 0 2 2 2 0 2 0 0 0 0 2 2 0 0 0 2 2 2 2 0 0 0 0 2 0 0 0 0 1 2 2 2 2 2 2 0 
+| * 0 0 2 2 2 2 * 1 1 1 1 * * * * 0 0 * * * * * 1 1 * * * * * * * * 0 * * * 2 * * * * * * * * * * * * * * * * * * * * * * * * * * 
+| 0 * * * * * * 1 * * * * 1 1 0 0 * * 0 1 1 1 1 * * 1 1 1 2 2 2 2 2 * 0 0 0 * 2 2 0 0 0 2 2 2 2 0 0 0 0 0 0 0 0 1 1 1 2 2 2 2 2 0 
+| 0 1 2 2 2 2 2 1 1 1 1 1 1 1 0 0 0 1 0 1 1 1 1 1 1 1 1 1 2 2 2 2 2 0 0 0 0 0 2 2 0 0 2 2 2 2 2 0 0 0 0 0 0 0 0 1 1 1 2 2 2 2 0 0 
+| 0 2 2 2 2 2 2 2 1 1 1 1 1 1 0 0 0 0 1 1 1 1 1 1 1 1 1 1 2 2 2 2 2 0 0 0 0 0 0 2 0 0 2 2 2 2 2 0 0 0 0 0 0 0 0 1 1 1 2 2 2 0 0 0 
+| 0 2 2 2 2 2 2 2 2 1 1 1 1 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 2 2 2 2 2 0 0 0 0 0 0 0 0 2 2 2 2 2 2 0 0 0 0 0 0 0 1 1 1 1 2 2 2 0 0 0 
+| 0 2 2 2 2 1 1 1 1 1 1 1 1 1 1 1 0 0 2 1 1 1 1 1 1 1 2 2 2 2 2 2 1 1 1 0 0 0 0 0 0 0 2 2 2 2 2 0 0 0 0 0 0 0 2 1 1 0 2 2 2 0 0 0 
+| 0 2 2 2 2 * * * * * 0 1 * * * * * 2 * * * * * * * * * 2 2 2 2 * * * * * * * * * 0 0 2 2 2 2 2 * * * 0 0 * 2 * * * * 2 2 2 * * * 
+| * * * * * 0 0 0 0 0 * * 1 1 1 1 1 * 2 1 0 1 2 1 1 2 2 * * * * 2 1 1 1 1 0 0 0 0 * * * 2 2 * * 0 0 0 * * 0 * 2 1 1 2 * * * 2 1 0 
+| 2 2 2 2 2 0 0 0 0 0 1 1 1 1 1 0 0 2 2 1 1 1 1 1 1 2 2 2 2 2 2 0 1 1 0 1 0 0 0 0 1 2 2 * * 2 2 2 0 2 1 1 0 0 2 2 1 2 2 2 2 2 1 0 
+| 2 2 0 2 0 0 0 0 0 1 0 0 1 1 1 0 0 2 2 1 1 1 1 1 1 2 2 2 2 2 2 0 0 0 0 0 0 0 0 0 0 2 2 2 0 0 2 2 2 1 1 0 0 0 0 1 1 0 2 2 2 2 2 1 
+| 2 2 0 0 0 0 0 0 1 0 0 0 1 1 1 0 0 2 1 1 1 1 1 1 1 1 2 2 2 2 2 2 0 1 2 0 0 0 0 1 2 2 2 2 2 0 1 2 1 1 1 0 0 0 0 1 1 0 2 2 2 2 2 2 
+| * 0 0 0 0 0 0 0 0 0 0 * * * * * 0 * * * * * * * * * * 2 2 2 2 0 0 2 2 0 0 0 0 1 2 2 2 2 2 0 2 1 1 1 1 0 0 0 * * * * * * 2 2 2 * 
+| 0 * 0 0 0 0 0 0 * * * 0 1 1 1 0 * 1 1 1 1 1 1 1 2 2 2 * * * * * * * * * 0 0 * * * * * * * * * * * * * * * * 0 1 1 0 2 2 * * * 2 
+| 0 0 * * * * * * 0 0 0 0 1 1 1 0 0 1 1 2 1 1 1 1 2 2 2 2 2 2 2 0 0 2 2 0 * * 0 0 2 2 2 2 2 0 1 1 1 1 1 0 0 1 1 1 1 0 0 2 1 2 2 2 
+| 0 0 0 0 0 0 0 0 0 0 0 0 1 1 2 0 0 2 2 0 1 1 1 2 2 2 2 2 2 2 2 0 0 2 2 1 0 2 0 2 0 2 2 2 2 0 1 1 1 1 1 0 1 1 1 1 1 0 0 1 1 2 2 2 
+| 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 0 2 2 2 2 0 1 1 2 2 0 2 1 1 2 0 0 0 2 2 0 0 0 2 2 1 2 2 2 2 0 1 1 1 1 0 1 1 1 1 1 2 0 0 1 1 2 2 2 
+| 1 0 0 0 0 0 0 0 0 0 0 * * * * * * 0 0 * * * * * * * 0 0 1 1 0 0 2 0 0 0 0 0 2 2 2 2 2 2 2 0 1 1 1 1 0 * * * * 2 2 0 * 1 1 2 2 2 
+| * * * * * 0 0 2 0 * * 0 1 1 1 1 0 * * 0 2 2 2 2 2 0 * * * * * * * * 2 0 0 0 * * * * 2 2 * * * * * * * 1 1 1 1 * * * 0 * * * * * 
+| 2 0 0 0 0 * * * * 0 0 0 1 1 1 1 0 2 2 0 2 2 2 2 2 0 0 0 1 1 0 0 0 1 * * * * 2 2 2 2 * * 2 2 1 1 1 1 1 1 1 1 1 2 2 0 0 1 1 2 2 2 
+| 0 0 0 0 0 0 0 0 0 0 0 0 2 1 1 1 1 0 2 0 2 2 2 2 2 0 0 2 1 1 0 0 0 2 2 0 0 0 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1 2 0 0 0 1 1 1 1 1 
+| 0 1 0 0 0 0 0 0 0 0 0 0 2 1 1 1 1 0 0 0 2 2 2 2 2 0 0 2 1 1 1 0 0 2 2 2 0 0 2 2 2 2 2 2 2 1 2 1 1 1 1 1 1 1 1 2 0 0 0 1 1 1 1 1 
+| 2 0 0 0 0 0 0 0 0 2 0 0 0 1 1 1 1 0 0 2 2 2 * * * * 0 2 2 1 2 0 0 0 2 0 0 0 0 2 2 2 2 2 1 1 2 1 1 1 1 1 1 1 * * * 2 0 1 0 1 1 1 
+| * * 0 0 0 0 2 0 * * * * * * 1 1 * * * * * * 2 2 0 0 * * * * * * 0 0 0 1 0 0 0 0 2 * * * * * * * 1 1 1 1 * * 1 2 0 * * * * * 1 * 
+| 2 0 * * * * * * 2 2 2 0 0 1 * * 1 0 2 2 2 2 2 2 0 0 2 2 2 1 0 0 * * * * * * * * * 2 2 2 1 1 1 1 * * * * 1 1 1 0 0 0 0 0 0 1 * 1 
+| 2 0 0 1 0 0 2 0 2 2 2 0 0 1 1 1 1 1 2 2 2 2 2 2 0 0 2 2 2 2 0 0 0 0 0 2 1 2 0 0 0 2 2 2 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 1 1 1 1 
+| 2 0 0 1 0 0 0 2 2 2 2 0 0 1 1 1 1 1 2 2 2 2 2 2 0 0 2 2 2 2 0 0 0 0 0 2 2 2 0 0 0 2 2 2 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 1 1 1 1 
+| 1 0 0 1 0 0 0 2 2 2 2 0 0 1 1 1 1 1 2 2 2 2 2 2 0 0 2 2 2 2 0 0 0 0 2 2 2 0 0 0 2 2 2 2 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 1 1 1 
+| 1 0 0 1 0 0 0 2 2 2 2 0 0 1 1 1 1 1 2 2 2 2 2 2 0 0 2 2 2 2 0 0 0 0 2 2 2 0 0 0 2 2 2 2 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 1 1 1 
+| 1 0 0 0 0 0 0 2 2 2 0 * * * * * * * * 2 2 * * * * * * * 2 2 2 0 0 0 2 2 2 0 0 0 2 2 2 2 1 1 1 1 1 1 * * * * * * * * 1 1 1 1 1 1 
+| * * * * * * * * * * * 0 0 0 1 1 1 1 2 * * 2 2 2 0 0 2 2 * * * * * * * * * * * * * * * * * * * * * * 1 1 1 1 1 1 0 0 * * * * * * 
+| 0 0 0 0 0 0 0 2 2 2 1 2 1 2 1 1 1 1 1 2 2 1 1 2 0 2 2 2 2 2 0 0 0 0 0 2 2 2 0 2 2 2 2 2 0 0 0 1 1 1 1 1 1 1 1 0 0 2 0 1 1 1 1 2 
+| 0 0 0 0 0 0 2 2 2 2 2 1 2 2 1 1 1 1 0 1 0 1 0 2 2 2 2 0 2 2 2 0 1 0 2 2 2 2 2 2 2 2 2 0 0 0 0 1 1 1 1 1 1 1 1 0 2 1 0 1 0 0 2 2 
+| 0 0 0 0 0 0 2 2 2 2 2 1 0 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 2 2 0 0 0 2 2 2 2 2 2 2 1 2 2 0 0 1 1 1 1 1 1 1 1 1 1 0 1 0 0 0 0 2 2 
+| 0 0 0 0 0 2 2 0 * * * * * * * * * 1 * 0 0 0 * * * * * * * * * 0 0 * * 1 1 1 2 2 2 1 1 2 0 0 2 1 * * 1 1 1 * * * * * * * 0 0 1 2 
+| * * * * * * * * 2 2 2 1 0 0 2 0 2 * 2 * * * 0 0 0 0 0 0 2 2 2 * * 2 2 * * * * * * * * * * * * * 1 1 * * * 1 1 1 1 1 1 0 * * * * 
+| 0 0 1 0 0 0 0 0 2 2 2 1 0 2 0 2 1 2 2 0 0 0 0 0 0 0 0 2 2 2 2 0 0 2 2 1 1 1 2 2 2 1 2 1 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 2 2 
+| 2 0 0 0 0 0 0 0 2 2 1 1 2 0 2 1 2 2 2 0 0 0 0 0 0 0 0 2 2 2 2 0 2 2 2 1 1 1 2 2 2 2 1 1 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 0 0 2 2 2 
+| 0 0 0 0 0 0 0 2 2 2 1 1 2 2 2 1 2 2 2 1 0 0 0 0 0 0 2 2 2 2 2 0 0 2 1 1 1 1 2 2 2 2 1 1 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 
+| 0 0 0 2 0 2 0 * * * * * * * * 1 * 2 2 0 0 0 2 0 0 0 2 2 0 2 2 1 2 1 0 1 1 1 2 2 2 2 0 1 1 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 
+| * * * * * * * 2 2 0 1 0 2 2 2 * 2 * * * * * * * * * * * * * * * * * * * * * * * * * * 1 * * * * * * 1 1 * * * * * * * * * * * * 
+| 0 1 0 0 0 2 0 2 2 0 1 1 2 2 2 2 2 2 2 0 0 0 0 0 0 0 2 0 0 2 2 2 2 0 1 1 1 1 1 2 2 2 0 * 2 2 2 0 1 0 * * 1 1 1 1 1 1 1 0 0 0 0 0 
+| 0 1 1 0 0 2 2 2 2 1 1 1 2 2 2 2 2 2 2 0 0 0 0 0 0 0 0 0 0 2 2 2 2 0 0 1 1 1 1 2 2 2 2 2 2 2 2 1 2 1 0 1 1 1 1 1 1 1 1 1 1 0 0 0 
+| 0 1 1 0 0 2 2 2 2 2 2 1 2 2 2 2 2 2 2 0 0 0 0 0 0 0 0 2 1 1 1 0 1 0 0 0 1 1 1 2 2 2 2 2 2 2 2 2 2 1 0 0 0 0 1 1 0 1 1 1 1 2 1 0 
+| 1 1 1 0 0 2 2 2 2 2 2 * * * 2 2 2 2 2 0 0 0 0 0 2 0 1 0 1 1 1 1 0 0 0 0 1 1 1 1 2 2 2 2 2 2 2 2 2 2 0 0 0 0 0 0 0 1 1 1 1 2 1 1 
+| * * * * * * * * * * * 2 2 2 * * * * * * 0 0 0 * * * * * * * * * * * * * * * * * * 2 2 2 2 1 0 0 2 0 0 0 0 0 0 0 * * * * * * * * 
+| 1 2 1 0 0 2 2 1 1 2 2 2 2 2 0 1 2 2 1 0 * * * 0 0 2 0 1 1 1 1 1 0 0 0 0 0 1 1 2 2 * * * * * * * * * * * 0 0 * * 0 2 1 1 1 2 1 1 
+| 1 2 0 0 0 1 1 1 1 2 2 2 2 2 2 0 2 2 0 0 1 1 0 0 0 0 0 1 1 1 1 1 0 0 0 2 2 2 2 2 2 2 2 2 2 1 0 0 0 0 0 0 * * 0 1 0 0 1 1 1 2 1 1 
+| 1 2 0 0 0 1 1 1 1 1 1 2 2 2 2 2 0 2 0 0 1 1 0 0 0 0 0 1 1 1 1 1 1 0 0 2 2 2 2 2 2 2 2 2 2 1 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 2 1 
+| 1 2 2 0 0 1 1 1 1 1 1 2 2 2 2 2 2 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 0 0 0 2 2 2 2 2 2 2 2 2 2 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 2 2 1 
+| 1 2 2 0 * 1 1 1 1 1 1 2 2 2 2 2 2 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 0 0 0 2 2 2 2 2 2 2 2 2 2 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 2 2 2 
+| * * * * 0 * * * * * * * * * 2 * * * * * * * * * * * * * * * * * * * * * 2 2 2 2 2 2 2 2 2 2 0 0 0 0 2 0 0 0 * * * * * * * * * * 
+| 2 2 2 0 0 1 1 1 1 1 1 2 2 2 * 2 2 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 0 0 * * * * * * 2 * * 2 * * * 0 * * * * 1 0 0 1 1 1 1 2 2 2 
+| 2 2 2 0 0 1 1 1 1 1 1 2 2 2 2 2 2 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 0 0 2 2 2 2 2 2 * 2 2 * 0 0 0 * 0 0 0 1 0 0 0 1 1 1 1 2 2 2 
+| 2 2 2 0 0 1 1 1 1 1 1 2 2 2 2 2 0 0 0 0 0 2 2 0 0 0 0 1 1 1 1 1 1 1 1 0 2 2 2 2 2 2 0 2 2 2 2 0 0 0 0 0 1 1 1 1 0 1 1 1 1 2 2 2 
+| 2 2 0 0 0 1 1 1 1 1 1 2 2 2 2 2 0 0 0 0 0 2 2 2 2 2 2 2 1 2 1 1 1 1 1 1 2 2 2 2 2 2 2 0 2 2 0 0 0 0 0 1 1 1 1 0 0 0 1 1 1 2 2 0 
+| 2 * 0 0 0 1 1 1 1 1 0 1 2 2 2 2 0 0 0 0 0 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 2 2 2 2 0 0 0 0 2 2 0 0 2 0 1 1 1 1 1 0 0 0 1 1 1 2 0 0 
+| * 2 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * 0 0 0 2 0 0 0 0 0 1 1 * * * * * * * * * 0 * * 
+| 2 2 0 0 0 2 1 1 1 1 1 1 2 2 2 2 0 0 0 0 0 2 2 2 2 2 2 2 0 2 2 1 1 1 1 1 2 2 2 2 0 * 0 * * * * * * * * * 1 1 1 0 0 0 1 1 2 * 2 0 
+| 2 2 0 0 0 0 1 1 1 1 1 1 2 2 2 2 0 0 0 0 0 2 2 2 2 2 2 2 2 0 1 1 1 1 1 1 2 1 2 0 0 0 * 0 0 0 0 0 0 0 1 1 1 1 1 0 0 0 1 1 2 1 0 1 
+| 2 0 0 0 0 0 1 1 1 2 2 2 2 2 2 2 0 0 0 0 2 2 2 2 1 2 1 0 0 0 1 1 1 1 1 1 1 1 0 2 0 0 0 0 0 0 0 0 0 0 1 1 2 2 2 0 0 0 1 1 1 0 0 0 
+| * * 0 0 0 0 2 1 1 2 2 1 2 2 2 2 0 0 0 0 2 2 2 1 1 1 1 0 0 0 1 2 1 1 2 1 1 1 2 0 0 0 0 0 0 0 0 0 0 0 1 1 2 2 2 0 0 0 1 2 1 0 0 0 
+| 2 1 * * * * * * * * * * * * * * * * * * * * * * * * * * 0 * * * * * * * * * * 0 * 0 1 0 0 0 0 0 0 0 0 1 2 2 2 2 * * * * * * * * 
+| 2 1 0 0 0 2 2 1 1 2 1 2 2 2 2 2 0 0 0 0 0 2 1 1 1 1 1 0 * 1 1 2 2 0 1 0 1 0 1 * 2 * * * 0 0 0 0 0 * * * * * * * 1 2 0 2 1 0 0 0 
+| 2 1 0 0 0 0 2 1 1 2 0 2 2 2 2 2 0 0 0 0 0 2 1 1 1 1 1 0 0 1 1 2 2 1 0 0 1 1 1 1 2 1 0 0 * * * * * 0 0 2 2 2 2 1 1 0 0 2 2 0 0 0 
+| 2 1 0 0 0 0 2 1 1 2 0 0 2 1 2 2 0 0 0 0 0 0 1 1 1 1 0 0 0 1 1 1 1 1 0 0 1 1 1 1 2 2 0 0 0 2 0 2 0 0 0 2 2 2 2 2 2 0 2 2 2 0 0 0 
+| 0 0 * 0 0 0 0 1 1 1 1 2 2 2 2 2 0 0 0 0 0 0 1 1 1 1 0 0 0 1 2 2 1 1 0 0 1 1 1 1 2 2 0 0 0 2 1 2 0 0 0 2 2 2 2 2 2 2 2 2 2 0 0 0 
+| * * 0 * 0 * * * * * * * * * * * * * 0 0 0 * * * * * * 0 0 * 2 2 * * 0 * * * * * * * 0 0 0 2 1 1 0 0 0 2 2 2 2 2 * * * * * * * * 
+| 0 0 0 0 * 0 0 1 1 1 1 2 1 1 2 1 2 0 * * * 0 1 1 1 1 0 * * 1 * * 2 1 * 0 1 1 1 0 1 2 * * * * * * * * * * * * * * 2 2 2 2 2 0 2 1 
+| 0 0 0 0 0 0 0 1 1 1 1 2 1 2 1 1 2 2 0 0 1 1 1 1 1 1 1 0 0 0 2 2 2 2 0 0 0 2 0 0 2 0 0 0 0 2 2 1 0 0 0 1 2 2 2 2 2 2 2 2 2 2 0 1 
+| 1 0 0 0 0 0 1 1 1 1 1 0 0 0 1 2 2 1 2 1 2 1 0 1 1 0 1 0 0 0 2 2 2 2 0 2 2 0 0 0 0 0 0 0 0 2 2 0 0 0 0 1 2 2 2 2 1 1 2 2 2 2 0 1 
+| * * 0 0 0 1 * * * * * * 0 0 0 0 0 0 1 1 1 1 1 1 1 1 * 0 0 2 2 2 2 2 2 2 2 0 0 2 2 1 1 0 0 2 2 2 2 2 0 1 2 2 2 1 1 1 2 2 2 2 * * 
+| 1 0 * * * * 0 2 1 1 1 0 * * * * * * * * * * * * * * 0 * * * * * * * * * * * * * * * * * 0 2 2 2 2 0 0 * * 2 1 1 * * * * * * 2 1 
+| 1 0 1 1 1 1 0 2 1 1 0 0 0 0 0 0 0 0 1 1 1 2 0 1 1 1 0 0 0 1 2 2 2 2 2 0 2 2 2 2 1 1 1 2 * * * * * * * 0 0 * * * 1 1 2 2 2 0 0 1 
+| 1 1 0 1 1 1 0 1 1 1 0 0 0 0 0 0 0 0 2 2 2 2 0 0 1 1 0 0 0 0 2 2 2 2 0 0 2 2 2 2 1 1 2 2 0 2 2 2 2 0 0 0 0 1 1 1 1 2 2 2 2 0 0 1 
+| 2 1 1 1 2 2 1 1 1 1 0 0 0 0 0 0 0 0 2 0 2 2 0 0 0 0 0 0 0 0 2 2 1 1 0 0 0 2 2 2 1 1 2 0 2 0 2 2 2 0 0 0 0 1 1 1 1 1 1 2 2 0 2 1 
+| 1 1 1 2 2 2 1 1 1 1 0 1 0 2 2 0 0 0 0 2 2 2 0 0 0 0 0 0 0 0 0 1 1 1 0 0 0 2 2 2 1 1 1 0 0 0 0 2 2 0 0 0 0 1 1 1 1 1 2 2 0 2 2 2 
+|                                                                                                                                 

+ 94 - 0
examples/stencil/0.out

@@ -0,0 +1,94 @@
+| 0 0 2 1 0 1 1 1 0 1 1 0 1 1 0 0 1 2 0 2 0 0 1 0 2 1 0 2 1 0 2 1 2 0 0 1 0 1 2 0 1 2 2 0 0 1 2 0 1 0 1 0 0 1 2 0 2 0 0 1 2 1 0 2 
+| * * 2 0 * 0 * 0 * * 0 * * * * * * 0 * * 0 * * 0 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * 0 * * * * * * * 
+| 0 0 * * 1 * 1 * 2 2 * 0 2 0 1 1 2 * 1 2 * 1 2 * 2 0 1 2 0 1 0 1 2 1 0 1 2 2 2 0 0 0 1 2 0 0 0 0 1 1 0 2 0 2 1 0 * 2 0 2 2 0 1 0 
+| 0 2 1 2 1 1 1 0 2 1 1 2 0 1 2 0 1 1 0 1 2 0 1 1 0 2 0 1 1 0 2 0 1 2 0 0 1 0 0 0 0 1 2 0 1 2 0 0 0 0 1 0 0 0 2 1 0 1 0 0 0 1 2 2 
+| * * * 1 * 0 2 1 1 * 0 0 0 0 * * * * 0 * 0 * 0 * * 1 * * * * * * * * * * * * 0 0 * * * * 0 * * * * * * * 0 * * * * * * 0 0 * * * 
+| 1 0 1 * 2 * * * * 2 * * * * 1 1 0 2 * 2 * 1 * 1 0 * 2 0 0 0 1 0 0 2 2 0 2 2 * * 2 1 0 1 * 0 0 2 1 2 1 0 * 0 1 0 1 0 2 * * 2 1 0 
+| 0 0 2 1 1 0 0 2 2 0 1 0 2 1 2 0 1 0 1 1 0 2 2 1 0 0 2 0 1 0 2 2 0 1 2 0 0 0 2 0 2 1 2 0 2 0 1 0 0 1 0 0 2 0 2 0 0 0 2 0 0 2 2 1 
+| * 1 1 2 * 1 0 0 2 2 0 0 0 2 0 0 2 0 * * 0 * * * * 1 0 * 0 * * 0 0 * * * * * * 2 * * * * 0 * * 0 * * * * 0 * * * * * * * * * * * 
+| 1 * * * 1 * * * * * * * * * * * * * 2 1 * 2 2 1 2 * * 2 * 0 0 * * 1 0 0 1 2 0 * 2 0 2 1 * 2 1 * 0 2 0 1 * 0 0 1 0 1 2 0 1 0 2 1 
+| 1 2 1 2 1 1 0 1 0 0 0 2 0 0 1 1 0 0 2 0 2 0 0 0 1 1 2 0 1 2 1 1 0 0 0 0 2 1 0 0 0 1 2 0 2 2 2 0 0 2 0 1 2 0 2 0 1 1 0 1 0 0 0 1 
+| * * 0 0 1 1 1 2 1 0 0 1 0 2 2 0 1 0 0 0 * * 0 * * * 0 0 1 2 0 2 1 2 * * * 1 * * 0 * * 0 * * 0 2 * * 0 1 0 1 2 0 0 0 1 * * 2 * * 
+| 1 0 * * * * * * 0 2 * * * * * * * * * * 2 1 * 2 1 0 * * * * * * * * 0 2 0 * 1 2 * 0 1 * 2 1 * * 1 2 * * * * * * * * * 2 1 * 1 2 
+| 0 1 1 1 2 1 0 0 * * 0 2 0 2 1 0 0 0 1 0 2 1 1 0 2 1 2 2 0 2 1 1 0 2 2 0 2 0 2 0 1 0 0 0 0 0 2 0 1 0 2 0 0 2 1 0 2 1 2 0 1 1 0 0 
+| 0 * * 1 2 1 2 1 2 0 0 0 1 1 0 2 0 2 0 0 0 * * 0 1 0 2 0 2 0 0 1 1 1 1 0 0 * * * 2 0 0 0 * * * * 2 0 0 * 0 0 1 2 0 0 2 2 2 * * * 
+| * 0 2 * * * * 0 * 0 0 2 * * * * * * * * * 2 1 * * * * * * * * * * * * * * 2 0 2 * * * * 1 1 0 2 * * * 1 * * * * * * * * * 1 2 1 
+| 1 0 2 0 1 2 2 * 2 * * * 0 0 0 2 0 0 1 0 0 0 0 2 2 1 0 0 2 1 1 1 0 2 0 1 1 0 0 2 1 0 2 0 0 0 0 1 0 1 2 1 0 0 0 1 1 0 0 2 2 2 2 0 
+| 0 0 2 1 0 2 0 0 2 1 0 2 0 1 0 0 1 0 2 1 1 1 0 0 2 0 1 2 2 1 0 2 0 1 0 1 2 0 1 0 2 1 2 1 0 2 0 2 0 2 2 0 1 2 0 0 1 0 2 0 0 0 2 1 
+| * * * * * * * 0 2 2 0 2 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * 
+| 1 0 2 0 1 2 0 * * * * * 0 1 1 0 0 0 0 1 0 0 0 2 1 0 2 1 2 0 1 1 1 0 2 0 0 1 0 0 2 0 0 0 0 2 2 1 0 0 0 2 1 0 0 2 2 2 2 2 1 2 0 2 
+| 0 1 2 2 0 1 0 2 0 1 1 0 2 0 1 1 1 2 0 2 0 0 1 0 1 1 0 1 0 2 1 1 2 1 0 0 2 1 0 0 0 2 0 0 2 1 2 0 1 0 0 0 0 1 0 1 0 2 2 0 2 0 0 0 
+| * * * * * * * * 0 0 1 1 * * 0 * * * * * * * * * * * * 0 * * * * * * * * * * * * * * * * * * * * * * * * * * * 1 * * * * * * * * 
+| 2 0 1 2 0 1 2 2 * * * * 2 2 * 1 0 2 2 0 1 1 0 0 2 0 1 * 0 0 0 0 2 0 2 0 1 0 0 1 0 1 0 2 0 1 1 2 0 1 0 2 0 1 2 * 1 0 0 2 1 1 1 0 
+| 2 1 0 0 2 0 2 2 2 0 1 2 0 0 2 0 1 0 0 1 1 0 2 0 2 1 2 0 1 0 0 0 0 1 1 2 2 2 2 2 0 0 0 2 0 2 0 1 1 1 2 1 0 1 0 0 0 0 2 2 0 1 0 1 
+| * * * * 0 * * * * * 0 * 0 0 * * * * * * * * * * * 2 2 0 2 0 0 * * * * * * * * * * * * * * * * * * * * * * * * * * 0 2 * * * * * 
+| 2 0 2 0 * 2 0 2 2 1 * 2 * * 1 1 1 0 0 2 1 1 1 2 1 * * * * * * 1 0 0 0 2 1 0 0 0 0 0 0 2 2 1 0 2 0 0 1 2 1 2 1 1 2 * * 0 2 2 0 0 
+| 0 2 0 0 0 0 0 0 2 2 2 2 0 0 1 1 2 0 0 0 0 0 0 0 2 1 0 1 1 0 0 2 1 1 2 0 2 2 2 0 1 2 0 2 1 2 1 2 0 2 1 2 1 1 0 1 2 0 0 0 0 2 0 0 
+| * * * * * 0 0 * 1 * * 2 0 * * * 0 0 * 0 0 0 * 0 * 1 0 2 2 0 0 * * * 0 1 * 0 * 0 * * * * 0 * 0 1 * * * * * * * * * 2 0 * * 1 * * 
+| 0 0 0 1 0 * * 2 * 2 1 * * 2 1 2 * * 1 * * * 1 * 1 * * * * * * 0 2 0 * * 2 * 1 * 2 0 1 2 * 2 * * 1 2 1 0 1 2 0 1 0 * * 0 0 * 2 0 
+| 1 2 1 0 1 0 1 2 0 0 1 0 1 0 2 0 1 1 1 1 0 0 2 1 0 1 2 1 2 0 0 1 1 0 1 0 0 0 2 1 0 0 2 0 2 1 0 0 1 1 1 2 0 2 0 0 1 2 2 1 1 0 0 2 
+| * 2 * * * * 1 1 2 2 0 * * * * * * * 0 0 1 0 0 0 2 1 0 1 0 2 0 * * * 0 0 0 2 0 2 0 * 0 * 2 1 1 0 0 1 0 * * * * * * * * 0 1 1 * * 
+| 0 * 2 0 2 0 * * * * * 0 1 0 2 1 2 1 * * * * * * * * * * * * * 2 0 1 * * * * * * * 1 * 2 * * * * * * * 2 2 1 2 1 0 0 0 * * * 0 1 
+| 1 2 2 0 1 2 1 2 0 0 0 0 1 0 0 1 0 0 1 2 2 1 0 0 0 2 2 1 1 0 1 2 0 2 0 1 2 2 0 2 0 0 0 1 0 2 0 0 0 0 0 2 1 1 2 1 1 0 1 1 0 2 2 0 
+| 1 * 0 0 2 1 1 2 2 0 1 0 1 0 0 * 0 2 0 1 2 0 * * * * 0 0 2 0 * 0 2 1 2 0 0 1 1 0 1 1 0 * 0 2 1 0 0 2 1 0 * * * * * 2 0 0 0 0 1 1 
+| * 2 * * * * * * * * * * * * * 2 * * * * * * 2 1 0 1 * * * * 2 * * * * * * * * * * * * 2 * * * * * * * * 0 0 1 0 0 * * * * * * * 
+| 0 2 0 0 1 0 2 2 0 0 1 0 0 0 1 1 0 2 0 0 0 2 2 0 1 0 1 1 2 1 0 2 2 1 0 1 2 1 0 1 2 1 0 1 0 0 2 1 1 0 2 1 0 0 0 2 2 0 0 1 0 0 2 1 
+| 2 2 0 2 1 0 1 2 1 2 0 1 0 * 2 0 0 0 0 1 0 2 0 2 0 1 1 2 1 0 2 0 1 0 2 2 0 0 2 2 1 1 0 0 2 2 0 1 2 0 1 0 1 * * * 0 0 2 0 0 0 0 2 
+| * * * * * * * * * * 0 1 * 1 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * 1 0 0 * * * * * * * * 
+| 0 0 0 2 0 0 0 2 1 2 * * 1 2 0 1 0 2 0 2 0 2 2 0 1 0 0 1 0 2 1 0 0 2 0 0 0 0 0 2 0 0 1 2 1 0 0 2 0 1 0 2 0 2 1 0 2 2 1 0 2 0 1 1 
+| 2 1 0 1 2 0 0 0 2 0 0 2 1 1 2 0 0 2 0 2 1 0 0 0 1 2 0 0 2 0 1 0 0 0 1 2 0 1 2 1 2 1 0 2 1 0 0 2 1 1 1 0 0 0 0 2 1 0 0 2 0 2 1 0 
+| * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * 0 * * * * * * * * * * * * * * * * * 
+| 0 2 0 0 0 2 1 0 1 2 0 2 1 0 2 0 2 2 0 0 2 0 0 0 2 1 2 1 1 1 1 2 2 0 0 2 2 0 0 1 2 2 0 1 0 2 * 0 0 1 1 2 0 1 2 2 2 1 2 0 0 1 2 1 
+| 1 2 1 1 2 0 0 0 1 2 0 0 0 2 0 1 1 0 1 0 0 0 0 0 0 0 2 2 2 1 1 1 2 1 2 0 1 0 0 1 0 2 0 2 0 0 2 1 2 1 2 2 0 0 1 2 0 0 0 0 2 1 1 1 
+| * 2 * * 2 1 * * * * * * * * * * * 2 * * * * * 2 1 2 0 * * * * * * * 0 * 2 * * * * * * * * * * * * * * * 0 * * * * * * 0 2 0 0 2 
+| 1 * 2 1 * * 1 2 0 0 2 1 2 1 0 0 0 * 0 0 0 2 0 * * * * 0 2 0 1 0 0 1 * 2 * 1 0 2 1 2 2 2 0 2 1 0 0 0 1 2 * 2 1 2 0 0 1 * * * * * 
+| 2 1 1 2 1 1 0 0 0 0 1 2 0 0 0 0 1 2 0 0 0 2 1 1 0 1 0 0 1 0 2 0 2 1 0 2 0 0 2 0 1 0 1 1 2 0 2 0 2 1 0 1 2 1 1 0 1 2 1 0 0 0 0 1 
+| 0 1 2 0 * 1 * * * * * * * 0 * * 1 0 2 * * * * * * 0 0 0 * * * * * * 0 2 1 * * * * * * * * * * * 0 1 0 0 * 0 2 0 1 2 * * 0 2 1 2 
+| * * * * 1 * 1 2 1 2 1 0 1 * 1 2 * * * 2 1 0 0 0 1 * * * 1 0 1 0 2 0 * * * 0 1 2 0 0 2 1 2 0 0 0 * * * * 2 * * * * * 0 0 * * * * 
+| 2 2 0 0 0 2 0 0 1 1 1 0 1 0 2 0 0 1 0 0 2 2 1 2 0 2 2 1 0 1 0 2 2 2 0 0 0 2 0 2 2 0 1 2 0 1 1 1 2 0 0 0 0 2 1 0 0 2 2 1 0 1 0 2 
+| 0 0 0 2 0 1 2 * * * 0 * * * 2 2 1 0 * * * * * * 0 * * 2 1 1 2 * * * * * 0 * * * 2 1 1 0 * * * * 1 1 0 0 0 * * 0 1 0 0 0 * 2 0 0 
+| * * * * * * * 0 2 1 * 2 0 1 * * * * 1 0 2 0 0 2 * 0 2 * * * * 0 1 1 0 2 * 1 1 2 * * * * 1 0 2 1 * * * * * 0 0 * * * * * 2 * * * 
+| 1 0 0 0 2 2 0 0 2 1 0 1 1 0 2 1 2 1 2 0 0 1 2 1 0 0 2 2 1 1 0 0 1 0 1 1 0 2 0 1 2 0 1 2 0 2 0 0 1 2 0 0 2 0 2 0 0 0 0 0 1 0 0 2 
+| 1 0 2 0 0 1 2 * * * * * 2 0 2 * 0 0 0 1 0 * * * * * 1 2 0 1 0 1 2 2 * * 1 2 0 1 2 0 2 2 * 0 0 * 0 2 0 * 2 0 0 0 0 0 2 0 1 0 2 0 
+| * * * * * * * 2 1 0 2 1 * * * 1 * * * * * 0 0 1 0 0 * * * * * * * * 1 0 * * * * * * * * 0 * * 1 * * * 1 * * * * * * * * * * * * 
+| 1 2 2 2 1 2 1 0 2 1 2 0 2 0 2 0 1 1 1 2 0 0 2 0 2 1 0 2 1 0 2 1 2 1 0 0 0 0 0 0 0 1 0 1 1 0 1 2 0 1 2 0 0 0 2 0 2 0 2 1 0 2 0 0 
+| 2 0 0 2 0 0 2 * 1 * * 0 0 2 0 1 0 2 1 1 2 1 2 0 0 0 1 2 0 2 2 0 2 0 2 1 0 0 0 0 1 1 * 2 * 1 2 1 0 1 0 0 0 1 0 2 0 2 2 1 2 0 1 0 
+| * * * 2 * * * 0 * 0 1 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * 0 * 0 * * * * * * * * * * * * * * * * * * * 
+| 0 1 0 * 2 0 0 1 2 0 2 2 1 1 1 2 1 1 0 0 0 0 2 0 0 2 0 1 1 2 2 0 0 2 0 1 2 0 2 2 0 0 2 2 0 1 0 1 2 0 2 0 0 1 2 0 2 1 1 0 2 2 0 1 
+| 2 0 0 0 2 1 0 0 1 1 0 2 2 0 2 1 0 2 0 0 2 1 0 2 0 1 0 1 2 1 1 2 2 1 0 2 1 2 1 0 2 1 0 0 0 1 0 0 0 0 2 1 2 0 1 0 0 0 0 0 1 2 0 2 
+| * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * 
+| 1 0 1 2 2 1 0 1 0 1 0 1 2 0 1 0 1 0 1 0 1 1 0 0 0 2 2 1 0 2 0 2 0 2 1 0 2 0 1 0 0 0 0 2 0 1 0 2 2 1 2 0 2 0 0 2 0 1 1 2 1 0 2 0 
+| 1 0 1 0 0 0 2 1 0 2 1 2 2 1 0 2 2 0 0 0 1 1 0 0 1 2 0 1 2 0 0 0 0 0 0 0 1 1 2 0 2 1 0 2 0 1 0 1 2 2 0 0 0 2 0 1 2 1 2 0 0 2 1 2 
+| * * * * * * * * * * * * * * * * * * * * * * * * * 0 * * * 1 1 * 0 * * * 1 0 1 0 * * * * * * 1 * * * * * * * * * 0 1 0 * * * * * 
+| 0 1 2 0 2 0 0 1 1 1 2 2 0 1 2 0 0 2 1 0 1 1 0 2 2 * 2 1 0 * * 2 * 0 0 1 * * * * 1 2 0 1 1 2 * 0 0 0 0 0 2 0 2 1 * * * 1 1 2 0 2 
+| 2 1 0 0 1 0 2 0 2 0 1 1 1 0 2 0 2 0 2 0 0 2 0 2 0 0 1 2 2 2 1 0 1 0 0 1 2 0 2 1 2 2 1 0 1 1 0 2 0 1 1 0 1 0 1 0 0 1 2 0 0 1 0 1 
+| 0 * 0 * * * * * * * 1 * * * * * 0 * 0 * * * * * * * * 1 * 1 1 0 0 0 0 0 1 * 0 * * * * * * * * 0 * * * * * * 0 0 0 2 0 0 * 2 0 0 
+| * 2 * 2 2 0 1 2 1 0 * 2 0 1 1 0 * 1 * 1 1 0 1 0 1 0 2 * 2 * * * * * * * * 2 * 1 1 2 0 0 0 1 0 * 0 2 0 0 0 1 * * * * * * 2 * * * 
+| 1 0 1 0 0 0 0 1 2 0 0 0 2 1 1 1 2 0 0 0 0 2 1 1 0 0 1 1 2 0 2 0 2 2 2 1 0 0 2 2 0 1 1 1 0 2 1 0 2 0 0 2 0 2 0 0 0 2 1 0 0 2 2 1 
+| 0 1 2 0 2 0 * * * 0 * 2 * * * * * * 0 0 0 * * 0 * * * 0 1 0 2 2 0 2 2 2 1 1 0 0 * * * 1 0 0 1 1 0 2 * * * * * * 0 2 1 1 1 2 0 1 
+| * * * * * * 2 1 0 * 0 * 0 0 0 1 0 2 * * * 0 1 * 1 1 1 * * * * * * * * * * * * * 1 0 2 * * * * * * * 1 2 2 1 1 2 * * * * * * * * 
+| 2 1 2 0 0 0 1 0 0 0 2 1 0 1 1 1 2 0 2 0 1 0 1 2 1 0 0 0 0 0 0 2 0 0 0 1 2 1 1 0 1 2 0 1 2 0 1 1 2 0 1 0 0 2 2 0 1 0 0 2 2 0 1 0 
+| 0 0 0 2 0 * * * 1 0 * 2 2 2 0 2 1 2 0 2 * * * * * * * 1 0 0 2 1 2 0 0 2 0 1 0 2 0 1 0 0 1 0 0 0 1 0 2 1 * * * * * * 1 0 0 1 0 2 
+| * * * * * 0 2 1 * * 1 * * * * * * * * * 0 1 1 0 0 1 0 * * * * * * * * * * * * * * * * * * * * * * * * * 2 2 0 1 0 1 * * * * * * 
+| 1 1 0 2 0 2 0 1 0 1 0 1 0 0 0 2 0 0 0 2 1 2 1 2 2 0 0 1 0 2 0 1 2 0 0 1 2 2 2 1 1 0 1 0 1 0 0 1 2 1 0 0 2 1 2 0 2 0 0 2 1 0 2 0 
+| 0 0 1 0 0 0 1 2 0 2 1 0 * 0 1 2 0 0 0 * * * * * * 0 2 0 1 0 2 0 1 1 2 0 1 1 0 1 0 2 1 0 2 0 1 1 1 2 2 2 0 0 2 0 2 2 2 2 2 1 0 1 
+| * * * * * * * * * * * * 1 * * * * * * 0 1 1 0 0 0 * * * * * 1 2 2 0 0 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * 
+| 1 1 0 2 2 0 0 2 2 2 2 1 2 0 0 0 0 1 0 0 0 0 0 0 0 2 1 0 1 0 * * * * * 0 1 2 2 2 1 0 0 2 0 2 2 1 1 1 0 2 1 0 0 1 2 1 0 1 2 1 2 1 
+| 2 0 0 0 1 0 2 0 1 2 0 0 1 0 0 1 0 2 0 1 2 1 0 1 1 1 0 2 0 2 1 0 2 0 2 0 2 0 1 0 2 0 2 2 1 1 2 2 1 1 0 0 2 1 0 0 2 1 0 1 2 1 1 0 
+| * * 0 * * * * * * * * * * * * * * * * * * * * * * * * * * * 1 * 2 0 1 * 1 * * * * * * * * * * * * * 0 0 * * * * * * * * * * * * 
+| 0 0 * 1 1 1 0 0 2 0 1 0 1 2 0 0 0 0 2 1 0 0 1 2 0 2 2 0 0 1 * 2 * * * 2 * 2 1 2 0 1 1 1 0 2 0 1 0 2 * * 1 0 2 1 0 0 1 2 1 2 0 1 
+| 0 0 2 2 0 2 1 2 0 1 0 1 2 0 2 1 1 0 1 1 1 0 0 1 2 0 0 1 1 1 0 1 2 2 0 0 1 0 0 0 1 0 0 1 2 1 0 0 1 1 2 0 0 1 2 0 1 2 1 1 0 0 2 0 
+| 2 * 0 * * * * * * * * * * * * * 2 0 * * * * * * * * * * * * 1 0 0 1 1 0 0 * 1 * * * 0 * * * * 2 1 0 * 0 2 0 * * * * * * * * * * 
+| * 2 * 1 0 0 1 2 2 0 0 1 0 1 1 0 * * 0 1 1 0 2 1 2 0 1 1 2 1 * * * * * * * 2 * 2 0 1 * 1 2 0 2 * * * 2 * * * 1 0 0 0 0 1 2 2 2 0 
+| 0 2 1 0 2 2 2 0 2 2 1 2 1 0 1 2 0 1 2 2 0 1 1 0 2 0 0 1 2 1 0 0 2 2 0 0 0 1 0 0 2 0 2 1 2 0 0 1 1 1 2 0 1 1 0 1 1 2 0 0 0 2 0 0 
+| 2 * 0 2 2 * * * * * * * * * * * * 0 0 2 0 * * * * * * * * * * 0 0 0 0 2 1 1 2 * * * * * 0 * 0 2 1 0 2 1 * * 0 0 * * 0 1 2 0 2 2 
+| * 1 * * * 0 0 0 1 0 0 2 0 2 1 0 0 * * * * 0 0 2 0 2 0 1 0 2 0 * * * * * * * * 1 2 1 2 1 * 2 * * * * * * 1 2 * * 2 1 * * * * * * 
+| 2 1 0 0 1 0 2 0 2 0 0 0 0 2 1 0 2 1 2 1 0 0 0 1 1 0 0 1 0 0 2 2 2 2 1 2 2 1 0 1 0 2 0 1 2 1 0 0 2 1 0 2 1 0 1 0 0 2 1 2 2 1 2 1 
+| 0 * 1 2 2 * * 2 0 0 0 1 0 1 2 0 * * 1 0 2 0 2 * 2 * 2 0 * 0 2 1 2 1 1 2 1 0 0 0 2 0 1 0 2 0 2 0 1 0 * 2 2 0 2 0 0 2 1 * * 0 0 1 
+| * 1 * * * 0 1 * * * * * * * * * 0 1 * * * * * 0 * 0 * * 1 * * * * * * * * * * * * * * * * * * * * * 0 * * * * * * * * 2 0 * * * 
+| 0 0 1 2 1 1 2 1 2 1 1 0 1 0 1 0 2 2 0 1 2 1 1 2 1 0 1 0 0 2 2 1 0 2 0 0 1 0 0 2 0 0 2 0 0 0 0 2 1 0 1 2 2 0 0 1 0 1 0 1 2 0 0 0 
+| 0 1 1 0 2 1 1 0 0 2 1 1 2 2 2 2 0 0 0 0 2 1 2 0 1 1 1 0 * 0 1 0 0 0 2 2 2 2 1 2 0 2 0 2 0 2 0 0 0 1 0 * 1 0 0 0 0 1 * * * 2 2 0 
+| * * * * * * * * * * * * * * * * * * * * * * * * * * * * 2 * * * * * * * * * * * * * * * * * * * * * * 2 * * * * * * 0 0 1 * * * 
+| 0 1 2 2 0 1 0 0 0 0 1 2 1 2 0 1 0 1 1 1 2 0 1 2 2 2 0 2 0 1 1 2 1 2 0 1 0 0 1 0 0 1 1 0 2 0 2 0 2 0 0 0 0 0 2 1 2 1 0 2 1 0 0 1 
+| 0 0 0 2 0 2 2 0 2 1 2 0 0 0 1 2 0 2 0 1 1 2 0 1 0 2 1 2 0 1 2 0 1 0 1 1 0 0 1 2 0 1 0 2 0 2 0 0 1 0 2 0 2 1 2 0 0 0 0 1 0 0 2 2 
+|                                                                                                                                 

+ 75 - 0
examples/stencil/1.out

@@ -0,0 +1,75 @@
+| 2 0 2 0 2 0 2 0 2 0 1 1 1 1 1 0 2 0 2 0 2 0 2 0 2 1 2 1 1 1 1 0 2 0 2 0 2 0 2 0 2 1 0 1 1 1 1 2 0 2 0 2 0 2 0 2 1 0 1 1 1 1 0 0 
+| 0 2 0 2 0 2 0 2 0 2 1 1 1 1 1 2 0 2 0 2 0 2 0 2 1 2 1 1 1 1 1 1 0 2 0 2 0 2 0 2 1 1 0 1 1 1 1 0 2 0 2 0 2 0 2 1 1 0 1 1 1 0 0 0 
+| * * * 0 * 0 * 0 0 * 1 1 1 1 1 * * 0 * * * * * 1 * 1 1 1 1 1 1 1 * * * * * * * * * 1 1 1 1 1 1 * * * * * * * * * 1 1 1 1 1 0 0 0 
+| 0 0 2 * 2 * 2 * * 2 * * 1 * * 2 2 * 2 0 2 0 2 * 2 * * * 1 1 * * 0 0 2 0 2 0 2 0 1 * * * 1 * * 0 0 2 0 2 0 2 1 1 * * * 1 * * * * 
+| 0 0 0 2 0 2 0 0 0 2 1 1 * 1 1 2 2 2 0 2 0 2 2 2 1 1 1 1 * * 1 1 0 0 0 2 0 2 0 0 1 1 1 1 * 1 1 0 0 0 2 0 2 1 1 1 1 1 1 * 1 0 0 0 
+| 0 0 0 0 2 0 0 0 0 2 1 1 1 1 1 2 2 2 2 0 2 2 2 2 1 1 1 1 1 1 1 1 0 0 0 0 2 0 0 0 1 1 1 1 1 1 1 0 0 2 2 2 2 1 1 1 1 1 1 1 1 0 0 0 
+| 0 0 0 0 2 0 0 0 0 0 1 1 1 1 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 0 0 2 2 2 2 1 1 1 1 1 1 1 1 0 0 0 
+| 0 0 0 0 2 0 0 0 0 0 0 1 1 1 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 0 2 2 2 2 2 1 1 1 1 1 1 1 1 0 0 0 
+| 0 0 0 0 0 0 0 0 2 2 2 2 0 2 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 * * 2 * 0 0 0 0 * * * * * 1 1 * * * * * 2 2 1 1 1 1 1 2 1 * * * 0 0 
+| * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * 1 1 * 0 * * * * 0 0 1 1 1 * * 1 1 0 0 1 * * * * * * * * * 1 1 0 * * 
+| 0 0 0 0 0 0 0 0 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 2 2 0 0 0 0 0 0 0 0 1 1 1 1 1 1 0 0 2 2 2 1 1 1 1 1 1 1 1 1 0 0 0 
+| 0 0 0 0 0 0 0 0 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 1 0 0 1 1 2 2 0 0 0 0 0 0 0 0 1 1 1 1 1 1 0 0 2 2 2 2 0 1 1 1 1 1 1 1 0 0 0 
+| 0 0 0 0 0 0 0 0 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 1 0 0 1 1 2 2 0 0 0 0 0 0 0 0 1 1 1 1 1 1 0 0 2 2 2 2 1 1 1 1 1 1 1 1 0 0 0 
+| 0 0 0 0 0 0 0 0 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 1 0 0 1 1 2 2 0 0 0 0 0 0 0 0 1 1 1 1 1 1 0 0 2 2 2 2 1 1 1 1 1 1 1 1 0 0 0 
+| 0 0 0 0 0 0 0 0 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 1 0 0 1 1 2 2 0 0 0 0 0 0 0 0 1 1 1 1 1 1 0 0 2 2 2 2 1 1 1 1 1 1 1 1 0 0 0 
+| 0 0 0 0 0 0 0 0 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 1 0 0 1 1 * 1 0 0 0 2 0 0 * * * * 1 1 1 1 0 * * * 2 2 1 1 1 1 1 1 1 1 0 0 0 
+| * * * 0 0 0 * * * * 2 2 2 1 1 2 2 2 * * * * * * * * * * * * * 1 * * * * * * * 0 0 1 1 * * * * * 0 2 2 * * * * 1 * * * * * * * * 
+| 0 2 0 * * * 0 0 2 2 * * * * * * * * 2 2 2 2 2 2 2 1 1 0 0 1 1 1 1 0 0 0 2 0 0 0 0 1 1 1 1 1 1 0 0 2 2 2 2 1 1 * 1 1 1 1 1 0 0 0 
+| 0 0 0 0 0 0 0 0 2 2 2 2 2 1 2 2 2 2 2 2 2 2 2 2 2 1 1 0 0 1 1 1 1 0 0 0 0 0 0 0 0 1 1 1 1 1 1 0 0 2 2 2 2 1 1 1 1 1 1 1 1 0 0 0 
+| 0 0 0 0 0 0 0 0 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 1 0 0 1 1 1 1 0 0 0 0 0 0 0 0 1 1 1 1 1 1 0 0 2 2 2 2 1 2 1 1 1 1 1 1 0 0 0 
+| 0 0 0 0 0 0 0 0 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 1 0 0 1 1 1 1 0 0 0 0 0 0 0 0 1 1 1 1 1 1 0 0 2 2 2 2 2 1 1 1 1 1 1 1 0 0 0 
+| 0 0 0 0 0 0 0 0 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 0 0 1 1 1 1 0 0 0 0 0 0 0 0 1 1 1 1 1 1 0 0 0 1 2 2 2 1 1 1 1 1 1 1 0 0 0 
+| 0 0 0 0 0 0 0 0 2 2 2 2 2 1 1 2 2 2 2 2 2 2 2 2 2 2 2 0 0 1 1 1 1 0 0 0 0 0 0 0 0 1 1 1 1 1 1 0 0 0 2 2 2 2 1 1 1 1 1 1 1 0 0 0 
+| 0 0 0 0 0 0 0 * * * 2 2 2 1 1 2 2 2 2 2 2 2 * * * * * * * * 1 * * * * * * * * * * * * 1 1 * * * * * * * * * * * * * 1 1 * * * * 
+| * * * * * * * 0 2 2 * * * * * * * * * * * * 2 2 2 2 2 0 0 1 * 1 1 0 0 0 0 0 0 0 0 1 1 * * 1 1 0 0 0 2 2 2 2 1 1 1 1 * * 1 0 0 0 
+| 0 0 0 0 0 0 0 0 2 2 2 2 2 1 1 2 2 2 2 2 2 2 2 2 2 2 2 0 0 1 1 1 1 0 0 0 0 0 0 0 0 1 1 1 1 1 1 0 0 0 2 2 2 2 1 1 1 1 1 1 1 0 0 0 
+| 0 0 0 0 0 0 0 0 2 2 2 2 2 1 1 2 2 2 2 2 2 2 2 2 2 2 2 0 0 1 1 1 1 0 0 0 0 0 0 0 0 1 1 1 1 1 1 0 0 0 2 2 2 2 1 1 1 1 1 1 1 0 0 0 
+| 0 0 0 0 0 0 0 0 2 2 2 2 2 1 1 2 2 2 2 2 2 2 2 2 2 2 2 0 0 1 1 1 1 0 0 0 0 0 0 0 1 1 1 1 1 1 1 0 0 0 2 2 2 2 1 1 1 1 1 1 1 0 0 0 
+| 0 0 0 0 0 0 0 0 2 2 2 2 2 1 1 2 2 2 2 2 2 2 2 2 2 2 2 0 0 1 1 1 1 0 0 0 0 0 0 0 1 1 1 1 1 1 1 0 0 0 2 2 2 2 1 1 1 1 1 1 1 0 0 0 
+| 0 0 0 0 0 0 0 0 2 2 2 2 2 1 1 2 2 2 2 2 2 2 2 2 2 2 2 0 0 1 1 1 1 0 0 0 0 0 0 0 1 1 1 1 1 1 1 0 0 0 2 2 2 2 1 1 1 1 1 1 1 0 0 0 
+| 0 0 0 0 0 0 0 * 2 2 2 2 2 1 1 2 2 2 2 2 2 2 2 2 2 2 2 0 0 1 1 1 1 * * * * * * * * 1 1 1 1 1 1 * * * * 2 2 2 1 1 1 1 1 1 1 0 0 0 
+| * * * * * * * 0 * * * * 2 1 1 2 2 2 2 2 2 2 2 * * * * * * * * * * 0 0 0 0 0 0 0 1 * * 1 * * * 0 0 0 2 * * * 1 1 1 1 1 * * * * * 
+| 0 0 0 0 0 0 0 0 2 2 2 2 * * * 2 2 2 * * * * * 2 2 2 2 1 1 1 1 1 1 0 0 0 0 0 0 0 1 1 1 * 1 1 1 0 0 0 2 2 2 2 * * * * * 1 1 2 0 0 
+| 0 0 0 0 0 0 0 0 2 2 2 2 2 1 1 * * * 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 0 0 0 0 0 0 0 1 1 1 1 1 1 1 0 0 0 2 2 2 2 1 1 1 1 1 1 1 0 0 0 
+| 0 0 0 0 0 0 0 0 2 2 2 2 2 1 1 2 2 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 0 0 0 0 0 0 0 1 1 1 1 1 1 1 0 0 0 2 2 2 2 1 1 1 1 1 1 1 0 0 0 
+| 0 0 0 0 0 0 0 0 2 2 2 2 2 1 1 2 2 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 0 0 0 0 0 0 0 1 1 1 1 1 1 1 0 0 0 2 2 2 2 1 1 1 1 1 1 1 0 0 0 
+| 0 0 0 0 0 0 0 0 2 2 2 2 2 1 1 2 2 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 0 0 0 0 0 0 0 1 1 1 1 1 1 1 0 0 0 2 2 2 2 1 1 1 1 1 1 1 0 0 0 
+| 0 0 0 0 0 0 0 0 2 2 2 2 2 1 1 2 2 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 0 0 0 0 0 0 0 1 1 1 1 1 1 1 0 0 0 2 2 2 2 1 1 1 1 1 1 1 0 0 0 
+| 0 0 0 0 0 0 0 0 2 2 2 2 2 1 1 2 2 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 0 0 0 0 0 0 * * * * * 1 1 * 0 0 0 2 2 2 2 1 1 1 1 1 1 1 0 0 0 
+| 0 * * * * * * * * * 2 2 2 1 1 2 2 2 2 2 2 2 2 2 2 2 * * * * * * * * * * * * * 0 1 1 1 1 * * 1 * * * * * * * * * * * * * * * * 0 
+| * 0 0 0 0 0 0 0 2 2 * * * * * * * * 2 2 * * * * * * 2 1 1 1 1 1 1 0 0 0 0 0 0 0 1 1 1 1 1 1 1 0 0 0 2 2 2 2 1 1 1 1 1 1 1 0 0 * 
+| 0 0 0 0 0 0 0 0 2 2 2 2 2 1 1 2 2 2 * * 2 2 2 2 2 2 2 1 1 1 1 1 1 0 0 0 0 0 0 0 1 1 1 1 1 1 1 0 0 0 2 2 2 2 1 1 1 1 1 1 1 0 0 0 
+| 0 0 0 0 0 0 0 0 2 2 2 2 2 1 1 2 2 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 0 0 0 0 0 0 0 1 1 1 1 1 1 1 0 0 0 2 2 2 2 1 1 1 1 1 1 1 0 0 0 
+| 0 0 0 0 0 0 0 0 2 2 2 2 2 1 1 2 2 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 0 0 0 0 0 0 0 1 1 1 1 1 1 1 0 0 0 2 2 2 2 1 1 1 1 1 1 1 0 0 0 
+| 0 0 0 0 0 0 0 0 2 2 2 2 2 1 1 2 2 2 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 0 0 0 0 0 0 0 1 1 1 1 1 1 1 0 0 0 2 2 2 2 1 1 1 1 1 1 1 0 0 0 
+| 0 0 0 0 0 0 0 0 2 2 2 2 2 1 1 2 2 2 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 0 0 0 0 0 0 0 1 1 1 1 1 1 1 0 0 0 2 2 2 2 1 1 1 1 1 1 1 0 0 0 
+| 0 0 0 0 0 0 0 0 2 2 2 2 2 1 1 2 2 2 2 2 2 2 2 2 2 2 2 2 * * * * * 0 0 0 0 0 0 * * * * * * * * * 0 0 2 2 2 2 1 1 1 1 1 1 1 0 0 0 
+| 0 0 0 0 0 0 0 0 2 2 2 2 2 1 1 2 2 2 2 2 2 2 2 2 2 * * * 1 1 1 1 1 * * * * * * 0 1 1 1 1 1 1 1 0 * * * * * * * * * * * * * * * 0 
+| * * 0 0 0 0 0 0 2 2 * * * * * * * * * 2 2 * * * * 2 2 2 1 1 1 1 1 0 0 0 0 0 0 0 1 1 1 1 1 1 1 0 0 0 2 2 2 2 1 1 1 1 1 1 1 0 0 * 
+| 0 0 * * * * * * * * 2 2 2 1 1 2 2 2 2 * * 2 2 2 2 2 2 2 1 1 1 1 1 0 0 0 0 0 0 0 1 1 1 1 1 1 1 0 0 0 2 2 2 2 1 1 1 1 1 1 1 0 0 0 
+| 0 0 0 0 0 0 0 0 2 2 2 2 2 1 1 2 2 2 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 0 0 0 0 0 0 0 1 1 1 1 1 1 1 0 0 0 2 2 2 2 1 1 1 1 1 1 1 0 0 0 
+| 0 0 0 0 0 0 0 0 2 2 2 2 2 1 1 2 2 2 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 0 0 0 0 0 0 0 1 1 1 1 1 1 1 0 0 0 2 2 2 2 1 1 1 1 1 1 1 0 0 0 
+| 0 0 0 0 0 0 0 0 2 2 2 2 2 1 1 2 2 2 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 0 0 0 0 0 0 0 1 1 1 1 1 1 1 0 0 0 2 2 2 2 1 1 1 1 1 1 0 0 0 0 
+| 0 0 0 0 0 0 0 0 2 2 2 2 2 1 1 2 2 2 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 0 0 0 0 0 0 0 1 1 1 1 1 1 1 0 0 0 2 2 2 2 1 1 1 1 1 1 0 0 0 0 
+| 0 0 0 0 0 0 0 0 2 2 2 2 2 1 1 2 2 2 2 2 2 2 2 2 2 2 2 * * * * * * 0 0 0 0 0 0 * * * * * * * * * 0 0 2 2 2 2 1 1 1 1 1 * 0 0 0 0 
+| 0 0 0 0 0 0 0 0 2 2 2 2 * * * * 2 2 2 2 2 2 2 2 * * * 2 1 1 1 1 1 * * * 0 * * 0 1 1 1 1 1 1 1 0 * * * 2 * * * * * * * 1 * * 0 0 
+| 0 0 0 0 0 0 0 0 2 2 * * 2 1 1 2 * * 2 2 2 2 * * 2 2 2 2 1 1 1 1 1 0 0 0 * 0 0 0 1 1 1 1 1 1 1 0 0 0 2 * 2 2 1 1 1 1 1 1 0 0 * * 
+| * * * 0 0 0 0 * * * 2 2 2 1 1 2 2 2 * * * * 2 2 2 2 2 2 1 1 1 1 1 0 0 0 0 0 0 0 1 1 1 1 1 1 1 0 0 0 2 2 2 2 1 1 1 1 1 1 0 0 0 0 
+| 0 0 0 * * * * 0 2 2 2 2 2 1 1 2 2 2 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 0 0 0 0 0 0 0 1 1 1 1 1 1 1 0 0 0 2 2 2 2 1 1 1 1 1 1 0 0 0 0 
+| 0 0 0 0 0 0 0 0 2 2 2 2 2 1 1 2 2 2 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 0 0 0 0 0 0 0 1 1 1 1 1 1 1 0 0 0 2 2 2 2 1 1 1 1 1 1 0 0 0 0 
+| 0 0 0 0 0 0 0 0 2 2 2 2 2 1 1 2 2 2 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 0 0 0 0 0 0 0 1 1 1 1 1 1 1 0 0 0 2 2 2 2 1 1 1 1 1 0 0 0 0 0 
+| 0 0 0 0 0 0 0 0 2 2 2 2 2 1 1 2 2 2 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 0 0 0 0 0 0 0 1 1 1 1 1 1 1 0 0 0 2 2 2 2 1 1 1 1 1 0 0 0 0 0 
+| 0 0 0 0 0 0 0 0 2 2 2 2 2 1 1 2 2 2 2 2 2 2 2 2 2 2 2 * * * * * * * 0 0 0 0 0 * * * * * * * * * 0 0 2 2 2 2 1 1 1 1 1 0 0 0 0 0 
+| 0 0 0 0 0 0 0 0 2 2 2 2 2 * * 2 2 2 2 2 2 2 2 2 * * * 2 1 1 1 1 1 0 * * * * * 0 1 1 1 1 1 1 1 0 * * * 2 * * * * * * * * * 0 0 0 
+| 0 0 0 0 0 0 0 0 2 * * * * 1 1 * * * * 2 2 * * * 2 2 2 2 1 1 1 1 1 0 0 0 0 0 0 0 1 1 1 1 1 1 1 0 0 0 2 * 2 2 1 1 1 1 1 0 0 * * 0 
+| * * * 0 0 0 0 * * 2 2 2 2 1 1 2 2 2 2 * * 2 2 2 2 2 2 2 1 1 1 1 1 0 0 0 0 0 0 0 1 1 1 1 1 1 1 0 0 0 2 2 2 2 1 1 1 1 1 0 0 0 0 * 
+| 0 0 0 * * * * 0 2 2 2 2 2 1 1 2 2 2 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 0 0 0 0 0 0 0 1 1 1 1 1 1 1 0 0 0 2 2 2 2 1 1 1 1 1 0 0 0 0 0 
+| 0 0 0 0 0 0 0 0 2 2 2 2 2 1 1 2 2 2 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 0 0 0 0 0 0 0 1 1 1 1 1 1 1 0 0 0 2 2 2 2 1 1 1 1 1 0 0 0 0 0 
+| 0 0 0 0 0 0 0 0 2 2 2 2 2 1 1 2 2 2 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 0 0 0 0 0 0 0 1 1 1 1 1 1 1 0 0 0 2 2 2 2 1 1 1 1 1 0 0 0 0 0 
+| 0 0 0 0 0 0 0 0 2 2 2 2 2 1 1 2 2 2 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 0 0 0 0 0 0 0 1 1 1 1 1 1 1 0 0 0 2 2 2 2 1 1 1 1 1 0 0 0 0 0 
+| 0 0 0 0 0 0 0 0 2 2 2 2 2 1 1 2 2 2 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 0 0 0 0 0 0 0 * * * * * * * 0 0 0 2 2 2 2 1 1 1 1 1 0 0 0 0 0 
+| 0 0 0 0 0 0 0 0 2 2 2 2 2 1 1 2 2 2 2 2 2 2 2 2 * * * * * * * * * * * * * * * * 1 1 1 1 1 1 1 * * * * * * * * * * * * * 0 0 0 0 
+| * 0 0 0 0 0 0 0 2 * * * * * * * * * * * * * * * 2 2 2 2 1 1 1 1 0 0 0 0 0 0 0 0 1 0 2 0 1 1 1 0 0 0 2 2 2 2 1 1 1 1 1 0 * * * * 
+| 0 _ _ _ _ _ _ _ _ 2 2 2 2 1 1 2 2 2 2 2 2 2 2 2 2 2 2 2 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 2 1 1 1 0 0 0 2 2 2 2 2 2 1 1 1 0 0 0 0 0 
+|                                                                                                                                 

+ 74 - 0
examples/stencil/2.out

@@ -0,0 +1,74 @@
+| 2 0 2 0 2 0 2 0 2 0 0 0 0 2 0 2 0 2 1 1 1 1 1 1 1 2 2 2 2 2 1 0 0 0 0 1 0 0 0 0 0 0 0 2 1 1 1 2 2 2 2 2 2 2 2 1 1 1 1 0 0 0 0 0 
+| 0 2 2 2 0 2 0 2 0 0 0 0 0 2 2 0 2 1 1 1 1 1 1 1 1 2 2 2 2 2 1 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 2 2 2 2 2 2 2 2 1 1 1 1 0 0 0 0 0 
+| 0 2 2 2 2 2 2 0 0 0 0 0 0 2 2 2 1 1 1 1 1 1 1 1 1 2 2 2 2 2 1 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 2 2 2 2 2 2 2 2 1 1 1 1 0 0 0 0 0 
+| 0 2 2 2 2 2 2 0 0 0 0 0 0 2 2 2 1 1 1 1 1 1 1 1 1 2 2 2 2 2 1 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 2 2 2 2 2 2 2 2 1 1 1 1 0 0 0 0 0 
+| * * * * * * * * * * * * * * * * * 1 1 1 1 1 1 1 1 * * * * * * 0 0 0 0 * * * * * * * * 1 1 1 * * * * * * * * * * 1 1 1 * * * * * 
+| 0 2 2 2 2 2 2 0 0 0 0 0 0 2 2 2 1 * 1 1 1 1 1 * * 2 2 2 2 2 1 * * * * 0 0 0 0 0 0 0 0 * * * 1 2 2 2 2 2 2 2 2 1 * * * 0 0 0 0 0 
+| 0 2 2 2 2 2 2 0 0 0 0 0 0 2 2 2 1 1 * 1 1 1 * 1 1 2 2 2 2 2 1 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 2 2 2 2 2 2 2 2 1 1 1 1 0 0 0 0 0 
+| 0 2 2 2 2 2 2 0 0 0 0 0 0 2 2 2 1 1 1 * 1 * 1 1 1 1 1 2 2 2 1 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 2 2 2 2 2 2 2 2 1 1 1 1 0 0 0 0 0 
+| 0 2 2 2 2 2 2 0 0 0 0 0 0 2 2 2 1 1 1 1 * 1 1 1 1 1 1 2 2 2 1 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 2 2 2 2 2 2 2 2 1 1 1 1 0 0 0 0 0 
+| 0 2 2 2 2 2 2 0 0 0 0 0 0 2 2 2 1 1 1 1 1 1 1 1 1 1 1 2 2 2 1 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 2 2 2 2 2 2 2 2 1 1 1 1 0 0 0 0 0 
+| 0 2 2 2 2 2 2 0 0 0 0 0 0 2 2 2 1 1 1 1 1 1 1 1 1 1 1 2 2 2 1 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 2 2 2 2 2 2 2 2 1 1 1 1 0 0 0 0 0 
+| * * 2 2 2 2 2 0 0 0 0 0 * 2 2 2 1 1 1 1 1 1 1 1 1 1 1 2 2 2 1 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 2 2 2 2 2 2 2 2 1 1 1 1 0 * * * * 
+| 0 2 * * * * * * * * * * 0 * * * * 1 1 1 1 1 1 1 1 1 1 * * * * * * * * * * * * * * * * * 1 1 * * * * * * * * * * 1 1 * * 0 0 0 0 
+| 0 2 2 2 2 2 2 0 0 0 0 0 0 2 2 2 1 * * 1 1 1 1 1 1 * * 2 2 2 1 0 0 0 0 0 0 0 0 0 0 0 0 1 * * 1 2 2 2 2 2 2 2 2 1 * * 1 0 0 0 0 0 
+| 0 2 2 2 2 2 2 0 0 0 0 0 0 2 2 2 1 1 1 * * 1 1 * * 1 1 2 2 2 1 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 2 2 2 2 2 2 2 2 1 1 1 1 0 0 0 0 0 
+| 0 2 2 2 2 2 2 0 0 0 0 0 0 2 2 2 1 1 1 1 1 * * 1 1 1 1 2 2 2 1 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 2 2 2 2 2 2 2 2 1 1 1 1 0 0 0 0 0 
+| 0 2 2 2 2 2 2 0 0 0 0 0 0 2 2 2 1 1 1 1 1 1 1 1 1 1 1 2 2 2 1 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 2 2 2 2 2 2 2 2 1 1 1 1 0 0 0 0 0 
+| 0 2 2 2 2 2 2 0 0 0 0 0 0 2 2 2 1 1 1 1 1 1 1 1 1 1 1 2 2 2 1 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 2 2 2 2 2 2 2 2 1 1 1 1 0 0 0 0 0 
+| 0 2 2 2 2 2 2 0 0 0 0 0 0 2 2 2 1 1 1 1 1 1 1 1 1 1 1 2 2 2 1 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 2 2 2 2 2 2 2 2 1 1 1 1 0 0 0 0 0 
+| * * * 2 2 2 * * * * * * * * * 2 1 1 1 1 1 1 1 1 1 1 1 2 2 2 1 0 0 0 0 0 0 0 0 0 * * * 1 1 1 1 2 2 2 2 2 2 2 2 1 1 1 * * * * * * 
+| 0 2 2 * * * 2 0 0 0 0 0 0 2 2 * * 1 1 1 1 1 1 1 1 1 1 2 2 * * * * * * * * * * * 0 0 0 * 1 1 1 2 2 2 2 2 2 2 2 1 * * 1 0 0 0 0 0 
+| 0 2 2 2 2 2 2 0 0 0 0 0 0 2 2 2 1 * * 1 1 1 1 1 1 1 1 * * 2 1 0 0 0 0 0 0 0 0 0 0 0 0 1 * * 1 2 2 2 * * * * * * 1 1 1 0 0 0 0 0 
+| 0 2 2 2 2 2 2 0 0 0 0 0 0 2 2 2 1 1 1 * * 1 1 1 1 * * 2 2 2 1 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 * * * * 2 2 2 2 2 1 1 1 1 0 0 0 0 0 
+| 0 2 2 2 2 2 2 0 0 0 0 0 0 2 2 2 1 1 1 1 1 * 1 * * 1 1 2 2 2 1 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 2 2 2 2 2 2 2 2 1 1 1 1 0 0 0 0 0 
+| 0 2 2 2 2 2 2 0 0 0 0 0 0 2 2 2 1 1 1 1 1 1 * 1 1 1 1 2 2 2 1 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 2 2 2 2 2 2 2 2 1 1 1 1 0 0 0 0 0 
+| 0 2 2 2 2 2 2 0 0 0 0 0 0 2 2 2 1 1 1 1 1 1 1 1 1 1 1 2 2 2 1 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 2 2 2 2 2 2 2 2 1 1 1 1 0 0 0 0 0 
+| 0 2 2 2 2 2 2 0 0 0 0 0 0 2 2 2 1 1 1 1 1 1 1 1 1 1 1 2 2 2 1 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 2 2 2 2 2 2 2 2 1 1 1 1 0 0 0 * * 
+| * * * 2 2 * * * * * * * * * * 2 1 1 1 1 1 1 1 1 1 1 1 2 2 2 1 * * * * * * * * * * * * 1 1 1 1 2 2 2 2 2 2 2 2 1 1 * * * * * 0 0 
+| 0 2 2 * * 2 2 0 0 0 0 0 0 2 2 * * 1 1 1 1 1 1 1 1 1 1 2 2 * * 0 0 0 0 0 0 0 0 0 0 0 0 * * 1 1 2 2 2 2 2 2 2 2 1 * 1 1 0 0 0 0 0 
+| 0 2 2 2 2 2 2 0 0 0 0 0 0 2 2 2 1 * 1 1 1 1 1 1 1 1 1 * * 2 1 0 0 0 0 0 0 0 0 0 0 0 0 1 1 * 1 2 2 2 2 2 2 2 * * 1 1 1 0 0 0 0 0 
+| 0 2 2 2 2 2 2 2 0 0 0 0 0 2 2 2 1 1 * * 1 1 1 1 1 * * 2 2 2 1 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 * * 2 2 2 2 2 * 2 1 1 1 1 0 0 0 0 0 
+| 0 2 2 2 2 2 2 2 0 0 0 0 0 2 2 2 1 1 1 1 * * 1 1 * 1 1 2 2 2 1 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 2 * * * * * 2 2 1 1 1 1 0 0 0 0 0 
+| 0 2 2 2 2 2 2 2 0 0 0 0 0 2 2 2 1 1 1 1 1 1 * * 1 1 1 2 2 2 1 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 2 2 2 2 2 2 2 2 1 1 1 1 0 0 0 0 0 
+| 0 2 2 2 2 2 2 2 0 0 0 0 0 2 2 2 1 1 1 1 1 1 1 1 1 1 1 2 2 2 1 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 2 2 2 2 2 2 2 2 1 1 1 1 0 0 0 0 0 
+| * * 2 2 2 2 2 2 * * * * * * 2 2 1 1 1 1 1 1 1 1 1 1 1 2 2 2 1 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 2 2 2 2 2 2 2 2 1 1 1 * * * * * * 
+| 0 2 * 2 2 2 * * 0 0 0 0 0 2 * 2 1 1 1 1 1 1 1 1 1 1 1 2 2 2 * * * * * * * * * * * * * * 1 1 1 2 2 2 2 2 2 2 2 1 1 * 1 0 0 0 0 0 
+| 0 2 2 * * * 2 2 0 0 0 0 0 2 2 * * 1 1 1 1 1 1 1 1 1 1 2 2 * 1 0 0 0 0 0 0 0 0 0 0 0 0 1 * 1 1 2 2 2 2 2 2 2 2 1 * 1 1 0 0 0 0 0 
+| 0 2 2 2 2 2 2 2 0 0 0 0 0 2 2 2 1 * 1 1 1 1 1 1 1 1 1 * * 2 1 0 0 0 0 0 0 0 0 0 0 0 0 1 1 * 1 2 2 2 2 2 2 2 * * 1 1 1 0 0 0 0 0 
+| 0 2 2 2 2 2 2 2 0 0 0 0 0 2 2 2 1 1 * 1 1 1 1 1 1 1 * 2 2 2 1 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 * * 2 2 2 2 2 * 2 1 1 1 1 0 0 0 0 0 
+| 0 2 2 2 2 2 2 2 0 0 0 0 0 2 2 2 1 1 1 * * 1 1 1 * * 1 2 2 2 1 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 2 * * 2 * * 2 2 1 1 1 1 0 0 0 0 0 
+| 0 2 2 2 2 2 2 2 2 0 0 0 0 2 2 2 1 1 1 1 1 * 1 * 1 1 1 2 2 2 1 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 2 2 2 * 2 2 2 2 1 1 1 1 0 0 0 0 0 
+| 0 2 2 2 2 2 2 2 2 0 0 0 0 2 2 2 1 1 1 1 1 1 * 1 1 1 1 2 2 2 1 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 2 2 2 2 2 2 2 2 1 1 1 1 0 0 0 0 0 
+| * * 2 2 2 2 2 2 * * * * * * 2 2 1 1 1 1 1 1 1 1 1 1 1 2 2 2 1 0 0 0 0 0 0 0 0 0 * * * 1 1 1 1 2 2 2 2 2 2 2 2 1 1 1 * * * * * * 
+| 0 2 * * 2 2 * * 2 0 0 0 0 2 * * 1 1 1 1 1 1 1 1 1 1 1 2 2 2 * * * * * * * * * * 0 0 0 * 1 1 1 2 2 2 2 2 2 2 2 1 1 * 1 0 0 0 0 0 
+| 0 2 2 2 * * 2 2 2 0 0 0 0 2 2 2 * 1 1 1 1 1 1 1 1 1 1 2 * * 1 0 0 0 0 0 0 0 0 0 0 0 1 1 * 1 1 2 2 2 2 2 2 2 2 1 * 1 1 0 0 0 0 0 
+| 0 2 2 2 2 2 2 2 2 0 0 0 0 2 2 2 1 * 1 1 1 1 1 1 1 1 1 * 2 2 1 0 0 0 0 0 0 0 0 0 0 0 1 1 1 * 1 2 2 2 2 2 2 2 * * 1 1 1 0 0 0 0 0 
+| 0 2 2 2 2 2 2 2 2 0 0 0 0 2 2 2 1 1 * * 1 1 1 1 1 1 * 2 2 2 1 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 * * 2 2 2 2 * * 2 1 1 1 1 0 0 0 0 0 
+| 0 2 2 2 2 2 2 2 2 0 0 0 0 2 2 2 1 1 1 1 * 1 1 1 * * 1 2 2 2 1 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 2 * * 2 * 2 2 2 1 1 1 1 0 0 0 0 0 
+| 0 2 2 2 2 2 2 2 2 0 0 0 0 2 2 2 1 1 1 1 1 * 1 * 1 1 1 2 2 2 1 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 2 2 2 * 2 2 2 2 1 1 1 1 0 0 0 0 0 
+| 0 2 2 2 2 2 2 2 2 0 0 0 0 2 2 2 1 1 1 1 1 1 * 1 1 1 1 2 2 2 1 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 2 2 2 2 2 2 2 2 1 1 1 1 0 0 0 0 0 
+| * * * 2 2 2 2 2 * 0 0 * * * 2 2 1 1 1 1 1 1 1 1 1 1 1 2 2 2 1 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 2 2 2 2 2 2 2 2 1 1 1 1 0 0 * * * 
+| 0 2 2 * * * * * 2 * * 0 0 2 * * * 1 1 1 1 1 1 1 1 1 1 2 2 2 * * * * * * * * * * * * * 1 1 1 1 2 2 2 2 2 2 2 2 1 1 * * * * 0 0 0 
+| 0 2 2 2 2 2 2 2 2 0 0 0 0 2 2 2 1 * 1 1 1 1 1 1 1 1 1 * * * 1 0 0 0 0 0 0 0 0 0 0 0 1 * 1 1 1 2 2 2 2 2 2 2 2 1 * 1 1 0 0 0 0 0 
+| 0 2 2 2 2 2 2 2 2 0 0 0 0 2 2 2 1 1 * * 1 1 1 1 1 * * 2 2 2 1 0 0 0 0 0 0 0 0 0 0 0 1 1 * * 1 2 2 2 2 2 * * * * 1 1 1 0 0 0 0 0 
+| 0 2 2 2 2 2 2 2 2 0 0 0 0 2 2 2 1 1 1 1 * 1 1 1 * 1 1 2 2 2 1 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 * * 2 * * * 2 2 2 1 1 1 1 0 0 0 0 0 
+| 0 2 2 2 2 2 2 2 2 0 0 0 0 2 2 2 1 1 1 1 1 * 1 * 1 1 1 2 2 2 1 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 2 * 2 2 2 2 2 2 1 1 1 1 0 0 0 0 0 
+| 0 2 2 2 2 2 2 2 2 0 0 0 0 2 2 2 1 1 1 1 1 1 * 1 1 1 1 2 2 2 1 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 2 2 2 2 2 2 2 2 1 1 1 1 0 0 0 0 0 
+| 0 2 2 2 2 2 2 2 2 0 0 0 0 2 2 2 1 1 1 1 1 1 1 1 1 1 1 2 2 2 1 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 2 2 2 2 2 2 2 2 1 1 1 1 0 0 0 0 0 
+| * * * 2 2 2 2 2 * 0 0 0 * * * 2 1 1 1 1 1 1 1 1 1 1 1 2 2 2 1 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 2 2 2 2 2 2 2 2 1 1 1 1 0 0 0 0 0 
+| 0 2 2 * * * * * 2 * * * 0 2 2 * * 1 1 1 1 1 1 1 1 1 1 2 2 2 1 0 0 0 0 0 0 * * * * * 1 1 1 1 1 2 2 2 2 2 2 2 2 1 1 * * * * * * * 
+| 0 2 2 2 2 2 2 2 2 0 0 0 0 2 2 2 1 * * 1 1 1 1 1 1 1 * * * * * * * * * * * 0 0 0 0 0 * * 1 1 1 2 2 2 2 2 2 2 2 1 * 1 1 0 0 0 0 0 
+| 0 2 2 2 2 2 2 2 2 0 0 0 0 2 2 2 1 1 1 * * 1 1 1 1 * 1 2 2 2 1 0 0 0 0 0 0 0 0 0 0 0 1 1 * * 1 2 * * * * * * * * 1 1 1 0 0 0 0 0 
+| 0 2 2 2 2 2 2 2 2 0 0 0 0 2 2 2 1 1 1 1 1 * 1 * * 1 1 2 2 2 1 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 * * 2 2 2 2 2 2 2 1 1 1 1 0 0 0 0 0 
+| 0 2 2 2 2 2 2 2 2 0 0 0 0 2 2 2 1 1 1 1 1 1 * 1 1 1 1 2 2 2 1 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 2 2 2 2 2 2 2 2 1 1 1 1 0 0 0 0 0 
+| 0 2 2 2 2 2 2 2 2 0 0 0 0 2 2 2 1 1 1 1 1 1 1 1 1 1 1 2 2 2 1 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 2 2 2 2 2 2 2 2 1 1 1 1 0 0 0 0 0 
+| 0 2 2 2 2 2 2 2 2 0 0 0 0 2 2 2 1 1 1 1 1 1 1 1 1 1 1 2 2 2 1 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 2 2 2 2 2 2 2 2 1 1 1 1 0 0 0 0 0 
+| * * * * * * * * * 0 0 0 * * * * 1 1 1 1 1 1 1 1 1 1 1 2 2 2 1 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 2 2 2 2 2 2 2 2 1 1 1 1 0 0 0 0 * 
+| 0 2 2 2 2 2 2 2 2 * * * 0 2 2 2 * * 1 1 1 1 1 1 1 1 1 2 2 2 1 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 2 2 2 2 2 2 2 2 1 1 1 1 * * * * 0 
+| 0 2 2 2 2 2 2 2 2 0 0 0 0 2 2 2 1 1 * * 1 1 1 1 1 * * * * * * * * 0 0 0 0 0 0 * * * 1 1 1 1 1 2 2 2 2 2 2 2 2 1 1 * * 0 0 0 0 0 
+| 0 2 2 2 2 2 2 2 2 0 0 0 0 2 2 2 1 1 1 1 * * 1 * * 1 1 2 2 2 1 0 0 * * * * * * 0 0 0 * * * * * * * * * * * * * * * 1 1 0 0 0 0 0 
+| 0 2 2 2 2 2 2 2 2 0 0 0 0 2 2 2 1 1 1 1 1 1 * 1 1 1 1 2 2 2 1 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 2 2 2 2 2 2 2 2 1 1 1 1 0 0 0 0 0 
+| 0 2 2 2 2 2 2 2 2 0 0 0 0 2 2 2 1 1 1 1 1 1 1 1 1 1 1 2 2 2 1 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 2 2 2 2 2 2 2 2 1 1 1 1 0 0 0 0 0 
+| 0 2 2 2 2 2 2 2 2 0 0 0 0 2 2 2 1 1 1 1 1 1 1 1 1 1 1 2 2 2 1 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 2 2 2 2 2 2 2 2 1 1 1 1 0 0 0 0 0 
+|                                                                                                                                 

+ 75 - 0
examples/stencil/3.out

@@ -0,0 +1,75 @@
+| 2 0 2 0 2 0 2 0 0 0 0 2 0 2 0 2 0 2 0 2 0 2 0 2 0 1 1 1 1 1 1 1 1 1 1 1 1 2 1 0 0 0 0 0 0 0 0 0 2 2 2 0 2 0 1 2 1 1 1 1 1 2 2 2 
+| 2 2 0 2 0 2 0 0 0 0 0 0 2 0 2 0 2 0 2 0 2 0 2 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 2 2 2 2 0 1 1 1 1 1 1 1 1 2 2 2 
+| 2 2 2 0 2 0 0 0 0 0 0 0 0 2 0 2 0 2 0 2 0 2 0 2 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 2 2 2 2 2 1 1 1 1 1 1 1 1 2 2 2 
+| 2 2 2 2 * * * * * * * * * * 2 * 2 * * * * * * * 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 * * 0 0 0 0 * * * * 2 2 2 * 1 1 1 1 1 1 1 * * 2 2 
+| * * * * 0 0 0 0 0 0 0 0 0 0 * 0 * 0 2 0 2 0 2 2 * * * 1 1 1 1 1 1 1 * * * * * 0 0 * * * * 0 0 0 2 * * * 2 * * * * * * * 1 2 * * 
+| 2 2 2 2 0 0 0 0 0 0 0 0 0 0 0 2 0 2 0 2 0 2 2 2 1 1 1 * * * * * * * 1 1 1 1 1 0 0 0 0 0 0 0 0 0 2 2 2 2 2 1 1 1 1 1 1 1 1 2 2 2 
+| 2 2 2 2 0 0 0 0 0 0 0 0 0 0 0 0 2 0 2 0 2 2 2 2 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 2 2 2 2 2 1 1 1 1 1 1 1 1 2 2 2 
+| 2 2 2 2 0 0 0 0 0 0 0 0 0 0 0 0 0 2 0 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 2 2 2 2 2 1 1 1 1 1 1 1 1 2 2 2 
+| 2 2 2 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 2 2 2 2 2 1 1 1 1 1 1 1 1 2 2 2 
+| 2 2 2 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 2 2 2 2 2 1 1 1 1 1 1 1 1 2 2 2 
+| 2 2 2 2 0 0 0 0 0 0 0 0 0 0 0 0 0 * 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1 1 1 * * * * * * * * * * * * 2 2 2 2 2 1 1 1 1 1 1 1 1 2 2 2 
+| 2 2 2 * * * * * * * * * * * * * * 0 * 2 2 2 2 2 1 1 1 1 1 1 1 1 1 * * * 1 1 1 0 0 0 0 0 0 0 0 0 * 2 2 2 2 1 1 1 1 1 1 1 1 2 2 2 
+| 2 * * 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 * * 2 2 * * * * * * * * * * 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 2 * * 2 2 1 1 * * * * * * 2 2 2 
+| * 2 2 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 2 2 * * 2 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 2 2 2 * * * * 1 1 1 1 1 1 * * 2 
+| 2 2 2 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 2 2 2 2 2 1 1 1 1 1 1 1 1 2 2 * 
+| 2 2 2 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 2 2 2 2 2 1 1 1 1 1 1 1 1 2 2 2 
+| 2 2 2 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 2 2 2 2 2 1 1 1 1 1 1 1 1 2 2 2 
+| 2 2 2 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 2 2 2 2 2 1 1 1 1 1 1 1 1 2 2 2 
+| 2 2 2 2 0 0 0 0 0 0 0 0 0 0 0 0 0 * 2 2 2 2 2 2 1 1 1 1 1 1 1 * * * * * * * * * * * * * * * * * 2 2 2 2 2 1 1 1 1 1 1 1 1 2 2 2 
+| 2 2 2 * * * * * * * * * * * * * * 0 * 2 2 2 2 2 1 1 * * * * * 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 * 2 2 2 2 1 1 1 1 1 1 1 1 2 2 2 
+| 2 2 * 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 * 2 2 2 2 * * 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 2 * 2 2 2 1 1 1 1 * * * * 2 2 2 
+| 2 * 2 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 2 * 2 2 * 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 2 2 * 2 * * * * * 1 1 1 1 * 2 2 
+| * 2 2 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 2 2 * * 2 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 2 2 2 * 2 1 1 1 1 1 1 1 1 2 * 2 
+| 2 2 2 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 2 2 2 2 2 1 1 1 1 1 1 1 1 2 2 * 
+| 2 2 2 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 2 2 2 2 2 1 1 1 1 1 1 1 1 2 2 2 
+| 2 2 2 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1 1 * * * * * * 0 0 0 0 0 0 0 2 2 2 2 2 1 1 1 1 1 1 1 1 2 2 2 
+| 2 2 2 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 2 2 2 2 2 * * * * * * * * * * * 1 1 1 1 0 0 * * * * * * * 2 2 2 2 2 1 1 1 1 1 1 1 1 2 2 2 
+| 2 2 2 2 * * * * * * * * * * * * * * * 2 2 2 2 * 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 * * 2 2 2 1 1 1 1 1 1 1 1 2 2 2 
+| 2 2 * * 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 * 2 2 * 2 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 2 2 * 2 2 1 1 1 1 1 1 1 1 2 2 2 
+| 2 * 2 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 2 * * 2 2 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 2 2 2 * * * * * * * * * * * 2 2 
+| * 2 2 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 2 2 2 2 2 1 1 1 1 1 1 1 1 2 * 2 
+| 2 2 2 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 2 2 2 2 2 1 1 1 1 1 1 1 1 2 2 * 
+| 2 2 2 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 2 2 2 2 2 1 1 1 1 1 1 1 1 2 2 2 
+| 2 2 2 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 2 2 2 2 2 1 1 1 * * * * * * * * * * * * * * * * * 0 0 0 0 2 2 2 2 2 1 1 1 1 1 1 1 1 2 2 2 
+| 2 2 2 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 2 2 2 2 * * * * 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 * * * * * 2 2 2 2 1 1 1 1 1 1 1 1 2 2 2 
+| 2 2 2 2 0 0 0 * * * * * * * * * * * 2 2 2 2 * 2 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 2 * 2 2 2 1 1 1 1 1 1 1 1 2 2 2 
+| 2 2 2 * * * * 0 0 0 0 0 0 0 0 0 0 0 * 2 2 * 2 2 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 2 2 * 2 2 1 1 1 1 1 1 * * 2 2 2 
+| 2 2 * 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 * * 2 2 2 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 2 2 2 * * * * * * * * 1 1 * 2 2 
+| * * 2 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 2 2 2 2 2 1 1 1 1 1 1 1 1 2 * 2 
+| 2 2 2 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 2 2 2 2 2 1 1 1 1 1 1 1 1 2 2 * 
+| 2 2 2 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 2 2 2 2 2 1 1 1 1 1 1 1 1 * * * * * * * * * * * * 0 0 0 0 2 2 2 2 2 1 1 1 1 1 1 1 1 2 2 2 
+| 2 2 2 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 2 2 2 2 2 * * * * * * * * 1 1 1 1 1 1 1 0 0 0 0 0 * * * * 2 2 2 2 2 1 1 1 1 1 1 1 1 2 2 2 
+| 2 2 2 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 2 2 2 2 * 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 * 2 2 2 2 1 1 1 1 1 1 1 1 2 2 2 
+| 2 2 2 2 0 0 0 0 0 0 0 0 0 0 0 0 * * 2 2 2 * * 2 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 2 * 2 2 2 1 1 1 1 1 1 1 1 2 2 2 
+| 2 2 2 * * * * * * * * * * * * * 0 0 * 2 * 2 2 2 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 2 2 * 2 2 1 1 1 1 * * * * 2 2 2 
+| 2 2 * 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 * 2 2 2 2 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 2 2 2 * * * * * * 1 1 1 1 * 2 2 
+| 2 * 2 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 2 2 2 2 2 1 1 1 1 1 1 1 1 2 * 2 
+| * 2 2 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 2 2 2 2 2 1 1 1 1 1 1 1 1 2 2 * 
+| 2 2 2 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 2 2 2 2 2 1 * * * * * * * * * * * * * * * * * * * * * * 0 2 2 2 2 2 1 1 1 1 1 1 1 1 2 2 2 
+| 2 2 2 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 2 2 2 2 * * 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 * * 2 2 2 2 1 1 1 1 1 1 1 1 2 2 2 
+| 2 2 2 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 2 2 2 * 2 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 2 * 2 2 2 1 1 1 1 1 1 1 1 2 2 2 
+| 2 2 2 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 2 2 * 2 2 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 2 2 * 2 2 1 1 1 1 1 1 1 1 2 2 2 
+| 2 2 2 2 * * * * * * * * * * * * * * 2 2 * 2 2 2 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 2 2 2 * 2 1 1 * * * * * * 2 2 2 
+| 2 2 2 * 0 0 0 0 0 0 0 0 0 0 0 0 0 0 * * 2 2 2 2 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 2 2 2 2 * * * 1 1 1 1 1 1 * 2 2 
+| 2 2 * 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 2 2 2 2 2 1 1 1 1 1 1 1 1 2 * 2 
+| 2 * 2 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 2 2 2 2 2 1 1 1 1 1 1 1 1 * * * * * * * * * * * * 0 0 0 0 2 2 2 2 2 1 1 1 1 1 1 1 1 2 2 * 
+| * 2 2 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 2 2 2 2 * * * * * * * * * 1 1 1 1 1 1 1 0 0 0 0 0 * * * * 2 2 2 2 2 1 1 1 1 1 1 1 1 2 2 2 
+| 2 2 2 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 2 2 2 * 2 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 * 2 2 2 2 1 1 1 1 1 1 1 1 2 2 2 
+| 2 2 2 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 2 2 * 2 2 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 2 * 2 2 2 1 1 1 1 1 1 1 1 2 2 2 
+| 2 2 2 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 2 * 2 2 2 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 2 2 * * 2 1 1 1 1 1 1 1 1 2 2 2 
+| 2 2 2 2 0 0 0 0 0 0 * * * * * * * * 2 * 2 2 2 2 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 2 2 2 2 * * * * * * 1 1 1 2 2 2 
+| 2 2 2 * * * * * * * 0 0 0 0 0 0 0 0 * 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 2 2 2 2 2 1 1 1 1 1 * * * * 2 2 
+| 2 2 * 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 2 2 2 2 2 1 1 1 1 1 1 1 1 2 * 2 
+| 2 * 2 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 2 2 2 2 2 1 1 * * * * * * * * * * * * * * * * * * * * * * 2 2 2 2 2 1 1 1 1 1 1 1 1 2 2 * 
+| * 2 2 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 2 2 2 2 * * * 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 * 2 2 2 2 1 1 1 1 1 1 1 1 2 2 2 
+| 2 2 2 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 2 2 2 * 2 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 2 * 2 2 2 1 1 1 1 1 1 1 1 2 2 2 
+| 2 2 2 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 2 2 * 2 2 1 1 1 1 1 1 * * * * * * * * * * 0 0 0 0 0 0 0 0 2 2 * 2 2 1 1 1 1 1 1 1 1 2 2 2 
+| 2 2 2 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 2 * 2 2 2 * * * * * * 1 1 1 1 1 1 1 1 1 0 * 0 0 0 0 0 0 0 2 2 2 * * 1 1 1 1 1 1 1 1 2 2 2 
+| 2 2 2 2 0 0 0 0 0 0 0 0 0 0 * * * * * * 2 2 2 * 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 * * 0 0 0 0 0 2 2 2 2 2 * * * * * * * * 2 2 2 
+| 2 2 2 * * * * * * * * * * * 0 0 0 0 2 2 2 2 * 2 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 * * * * * * 2 2 2 2 1 1 1 1 1 1 1 1 * 2 2 
+| 2 2 * 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 2 2 * 2 2 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 2 * 2 2 2 1 1 1 1 1 1 1 1 2 * 2 
+| 2 * 2 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 2 * 2 2 2 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 2 2 * 2 * * * * * * * * 1 2 2 * 
+| _ 2 2 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 * 2 2 2 2 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 2 2 2 * 2 1 1 1 1 1 1 1 * * 2 2 
+| _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 2 2 2 2 2 1 1 1 1 1 1 1 1 2 _ _ 
+|                                                                                                                                 

+ 78 - 0
examples/stencil/4.out

@@ -0,0 +1,78 @@
+| 2 0 2 0 2 0 0 0 0 2 0 2 0 2 0 2 0 2 0 2 0 2 0 2 0 2 0 2 0 2 0 2 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 2 2 2 0 2 0 2 0 2 0 0 0 0 2 0 
+| 0 2 0 2 0 0 0 0 0 0 2 0 2 0 2 0 2 0 2 0 2 0 2 0 2 0 2 0 2 0 2 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 2 2 2 2 0 2 0 2 0 0 0 0 0 0 2 
+| * * * * * * 0 * * * * 2 * 2 * 2 * 2 * 2 * 2 * * * * * * * * * * 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 * * * 2 2 * * * * * * * * * * * * 
+| 2 0 2 0 0 0 * 0 0 0 0 * 0 * 0 * 0 * 0 * 0 * 0 2 0 2 0 2 0 2 0 1 * * 1 1 1 1 1 1 1 1 1 1 1 1 * 0 0 2 * * 2 2 0 2 0 0 0 0 0 0 0 0 
+| 0 2 0 0 0 0 0 0 0 0 0 0 2 0 2 0 2 0 2 0 2 0 2 0 2 0 2 0 2 0 1 1 1 1 * 1 1 1 1 1 1 1 1 1 1 * 1 0 0 2 2 2 2 2 2 0 0 0 0 0 0 0 0 0 
+| 0 0 0 0 0 0 0 0 0 0 0 0 0 2 0 2 0 2 0 2 0 2 0 2 0 2 0 2 0 1 1 1 1 1 1 * 1 1 1 1 1 1 1 1 * 1 1 0 0 2 2 2 2 2 2 0 0 0 0 0 0 0 0 0 
+| * * * 0 0 0 0 0 0 0 0 0 0 0 2 0 2 0 2 0 2 0 2 0 2 0 2 0 1 1 1 1 1 1 1 1 * 1 1 1 1 1 1 * 1 1 1 0 0 2 2 2 2 2 2 0 0 * * * * * * * 
+| 0 0 0 * * * * * * * * * * * * * * * * * * * * * * * * * * 1 1 1 1 1 1 1 1 * 1 1 1 1 * 1 1 1 * * * * 2 2 2 2 * * * 0 0 0 0 0 0 0 
+| 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 0 2 0 2 0 2 0 2 0 2 0 1 1 * 1 1 1 1 1 1 1 1 * 1 1 * 1 1 1 * 1 0 0 2 * 2 2 * 2 0 0 0 0 0 0 0 0 0 
+| 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 0 2 0 2 0 2 0 2 0 1 1 1 1 * 1 1 1 1 1 1 1 1 * * 1 1 1 * 1 1 0 0 2 2 * * 2 2 0 0 0 0 0 0 0 0 0 
+| 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 0 2 0 2 0 2 0 1 1 1 1 1 1 * 1 1 1 1 1 1 1 1 1 1 1 * 1 1 1 0 0 2 2 2 2 2 2 0 0 0 0 0 0 0 0 0 
+| * * * * * 0 0 0 0 0 0 0 0 0 0 0 0 0 2 0 2 0 2 0 2 1 1 1 1 1 1 1 * 1 1 1 1 1 1 1 1 1 * 1 1 1 1 0 0 2 2 2 2 2 2 0 0 0 * * * * * * 
+| 0 0 0 0 0 * * * * * * * * * * * * * * * * * * * * 1 1 1 1 1 1 1 1 * * 1 1 1 1 1 * * 1 1 1 1 * * * * 2 2 2 2 * * * * 0 0 0 0 0 0 
+| 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 0 2 0 2 2 * 1 1 1 1 1 1 1 1 1 * * 1 1 * 1 1 1 1 1 * 1 0 0 2 * 2 2 * 2 0 0 0 0 0 0 0 0 0 
+| 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 0 2 2 2 1 * 1 1 1 1 1 1 1 1 1 1 * * 1 1 1 1 1 * 1 1 0 0 2 2 * * 2 2 0 0 0 0 0 0 0 0 0 
+| 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 2 2 2 1 1 * 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 * 1 1 1 0 0 2 2 2 2 2 2 0 0 0 0 0 0 0 0 0 
+| 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 2 2 2 1 1 1 * 1 1 1 1 1 1 1 1 1 1 1 1 1 * 1 1 1 1 0 0 2 2 2 2 2 2 0 0 0 0 0 0 0 0 0 
+| * * * * * * * * * * * 0 0 0 0 0 0 0 0 0 0 2 2 2 2 1 1 1 1 * * 1 1 1 1 1 1 1 1 1 1 * 1 1 1 1 1 0 0 2 2 2 2 2 2 * * * * * * * * * 
+| 0 0 0 0 0 0 0 0 0 0 0 * * * * * * * * * * * 2 2 2 1 1 1 1 1 1 * 1 1 1 1 1 1 1 1 * 1 1 1 1 1 * * * * 2 2 2 2 * 0 0 0 0 0 0 0 0 0 
+| 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 * 2 2 1 1 1 1 1 1 1 * 1 1 1 1 1 * * 1 1 1 1 1 * 1 0 0 2 * 2 2 * 2 0 0 0 0 0 0 0 0 0 
+| 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 2 * 2 1 1 1 1 1 1 1 1 * * 1 1 * 1 1 1 1 1 1 * 1 1 0 0 2 2 * * 2 2 0 0 0 0 0 0 0 0 0 
+| 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 2 2 * 1 1 1 1 1 1 1 1 1 1 * * 1 1 1 1 1 1 * 1 1 1 0 0 2 2 2 2 2 2 0 0 0 0 0 0 0 0 0 
+| 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 2 2 2 * * 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 * 1 1 1 1 0 0 2 2 2 2 2 2 0 0 0 0 0 0 0 0 0 
+| * * * * * * * * * 0 0 0 0 0 0 0 0 0 0 0 0 2 2 2 2 1 1 * 1 1 1 1 1 1 1 1 1 1 1 1 1 * 1 1 1 1 1 0 0 2 2 2 2 2 2 * * * * * * * * * 
+| 0 0 0 0 0 0 0 0 0 * * * * * * * * * * * * * 2 2 2 1 1 1 * 1 1 1 1 1 1 1 1 1 1 1 * 1 1 1 1 1 * * * * 2 2 2 2 * 0 0 0 0 0 0 0 0 0 
+| 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 * 2 2 1 1 1 1 * 1 1 1 1 1 1 1 1 1 * 1 1 1 1 1 * 1 0 0 2 * 2 2 * 2 0 0 0 0 0 0 0 0 0 
+| 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 2 * 2 1 1 1 1 1 * 1 1 1 1 1 1 1 * 1 1 1 1 1 * 1 1 0 0 2 2 * * 2 2 0 0 0 0 0 0 0 0 0 
+| 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 2 2 * 1 1 1 1 1 1 * 1 1 1 1 1 * 1 1 1 1 1 * 1 1 1 0 0 2 2 2 2 2 2 0 0 0 0 0 0 0 0 0 
+| 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 2 2 2 * 1 1 1 1 1 1 * 1 1 * * 1 1 1 1 1 * 1 1 1 1 0 0 2 2 2 2 2 2 0 0 0 0 0 0 0 0 0 
+| * * * * * * * 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 2 2 2 1 * * 1 1 1 1 1 * * 1 1 1 1 1 1 * 1 1 1 1 1 0 0 2 2 2 2 2 2 * * * * * * * * * 
+| 0 0 0 0 0 0 0 * * * * * * * * * * * * * * * 2 2 2 1 1 1 * 1 1 1 1 1 1 1 1 1 1 1 * 1 1 1 1 1 * * * * 2 2 2 2 * 0 0 0 0 0 0 0 0 0 
+| 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 * 2 2 1 1 1 1 * 1 1 1 1 1 1 1 1 1 * 1 1 1 1 1 * 1 0 0 2 * 2 2 * 2 0 0 0 0 0 0 0 0 0 
+| 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 2 * 2 1 1 1 1 1 * 1 1 1 1 1 1 1 * 1 1 1 1 1 * 1 1 0 0 2 2 * * 2 2 0 0 0 0 0 0 0 0 0 
+| 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 2 2 * 1 1 1 1 1 1 * 1 1 1 1 1 * 1 1 1 1 1 * 1 1 1 0 0 2 2 2 2 2 2 0 0 0 0 0 0 0 0 0 
+| 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 2 2 2 * 1 1 1 1 1 1 * 1 1 * * 1 1 1 1 1 * 1 1 1 1 0 0 2 2 2 2 2 2 0 0 0 0 0 0 0 0 0 
+| * * * * * * 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 2 2 2 1 * 1 1 1 1 1 1 * * 1 1 1 1 1 1 * 1 1 1 1 1 0 0 2 2 2 2 2 2 0 * * * * * * * * 
+| 0 0 0 0 0 0 * * * * * * * * * * * * * * * * 2 2 2 1 1 * * 1 1 1 1 1 1 1 1 1 1 1 * 1 1 1 1 1 * * * * 2 2 2 2 * * 0 0 0 0 0 0 0 0 
+| 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 * 2 2 1 1 1 1 * 1 1 1 1 1 1 1 1 1 * 1 1 1 1 1 * 1 0 0 2 * 2 2 * 2 0 0 0 0 0 0 0 0 0 
+| 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 2 * 2 1 1 1 1 1 * 1 1 1 1 1 1 1 * 1 1 1 1 1 * 1 1 0 0 2 2 * * 2 2 0 0 0 0 0 0 0 0 0 
+| 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 2 2 * 1 1 1 1 1 1 * 1 1 1 1 1 * 1 1 1 1 1 * 1 1 1 0 0 2 2 2 2 2 2 0 0 0 0 0 0 0 0 0 
+| 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 2 2 2 * 1 1 1 1 1 1 * 1 1 1 * 1 1 1 1 1 * 1 1 1 1 0 0 2 2 2 2 2 2 0 0 0 0 0 0 0 0 0 
+| * * * * * * 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 2 2 2 1 * 1 1 1 1 1 1 * * * 1 1 1 1 1 * 1 1 1 1 1 0 0 2 2 2 2 2 2 0 0 * * * * * * * 
+| 0 0 0 0 0 0 * * * * * * * * * * * * * * * * 2 2 2 1 1 * 1 1 1 1 1 1 1 1 1 1 1 1 * 1 1 1 1 1 * * * * 2 2 2 2 * * * 0 0 0 0 0 0 0 
+| 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 * 2 2 1 1 1 * * 1 1 1 1 1 1 1 1 1 * 1 1 1 1 1 * 1 0 0 2 * 2 2 * 2 0 0 0 0 0 0 0 0 0 
+| 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 2 * 2 1 1 1 1 1 * 1 1 1 1 1 1 1 * 1 1 1 1 1 * 1 1 0 0 2 2 * * 2 2 0 0 0 0 0 0 0 0 0 
+| 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 2 2 * 1 1 1 1 1 1 * 1 1 1 1 1 * 1 1 1 1 1 * 1 1 1 0 0 2 2 2 2 2 2 0 0 0 0 0 0 0 0 0 
+| 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 2 2 2 * 1 1 1 1 1 1 * 1 1 1 * 1 1 1 1 1 * 1 1 1 1 0 0 2 2 2 2 2 2 0 0 0 0 0 0 0 0 0 
+| * * * * 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 2 2 2 1 * 1 1 1 1 1 1 * 1 * 1 1 1 1 1 * 1 1 1 1 1 0 0 2 2 2 2 2 2 0 0 0 * * * * * * 
+| 0 0 0 0 * * * * * * * * * * * * * * * * * * 2 2 2 1 1 * 1 1 1 1 1 1 * 1 1 1 1 1 * 1 1 1 1 1 * * * * 2 2 2 2 * * * * 0 0 0 0 0 0 
+| 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 * 2 2 1 1 1 * 1 1 1 1 1 1 1 1 1 1 * 1 1 1 1 1 * 1 0 0 2 * 2 2 * 2 0 0 0 0 0 0 0 0 0 
+| 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 2 * 2 1 1 1 1 * * 1 1 1 1 1 1 1 * 1 1 1 1 1 * 1 1 0 0 2 2 * * 2 2 0 0 0 0 0 0 0 0 0 
+| 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 2 2 * 1 1 1 1 1 1 * 1 1 1 1 1 * 1 1 1 1 1 * 1 1 1 0 0 2 2 2 2 2 2 0 0 0 0 0 0 0 0 0 
+| 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 2 2 2 * 1 1 1 1 1 1 * 1 1 1 * 1 1 1 1 1 * 1 1 1 1 0 0 2 2 2 2 2 2 0 0 0 0 0 0 0 0 0 
+| * * * * 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 2 2 2 1 * 1 1 1 1 1 1 * 1 * 1 1 1 1 1 * 1 1 1 1 1 0 0 2 2 2 2 2 2 0 0 0 0 * * * * * 
+| 0 0 0 0 * * * * * * * * * * * * * * * * * * 2 2 2 1 1 * 1 1 1 1 1 1 * 1 1 1 1 1 * 1 1 1 1 1 * * * * 2 2 2 2 * * * * * 0 0 0 0 0 
+| 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 * 2 2 1 1 1 * 1 1 1 1 1 1 1 1 1 1 * 1 1 1 1 1 * 1 0 0 2 * 2 2 * 2 0 0 0 0 0 0 0 0 0 
+| 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 2 * 2 1 1 1 1 * 1 1 1 1 1 1 1 1 * 1 1 1 1 1 * 1 1 0 0 2 2 * * 2 2 0 0 0 0 0 0 0 0 0 
+| 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 2 2 * 1 1 1 1 1 * 1 1 1 1 1 1 * 1 1 1 1 1 * 1 1 1 0 0 2 2 2 2 2 2 0 0 0 0 0 0 0 0 0 
+| 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 2 2 2 * 1 1 1 1 1 * 1 1 1 1 * 1 1 1 1 1 * 1 1 1 1 0 0 2 2 2 2 2 2 0 0 0 0 0 0 0 0 0 
+| * * * 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 2 2 2 1 * 1 1 1 1 1 * * 1 * 1 1 1 1 1 * 1 1 1 1 1 0 0 2 2 2 2 2 2 0 0 0 0 * * * * * 
+| 0 0 0 * * * * * * * * * * * * * * * * * * * 2 2 2 1 1 * 1 1 1 1 1 1 * 1 1 1 1 1 * 1 1 1 1 1 * * * * 2 2 2 2 * * * * * 0 0 0 0 0 
+| 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 * 2 2 1 1 1 * 1 1 1 1 1 1 1 1 1 1 * 1 1 1 1 1 * 1 0 0 2 * 2 2 * 2 0 0 0 0 0 0 0 0 0 
+| 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 2 * 2 1 1 1 1 * 1 1 1 1 1 1 1 1 * 1 1 1 1 1 * 1 1 0 0 2 2 * * 2 2 0 0 0 0 0 0 0 0 0 
+| 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 2 2 * 1 1 1 1 1 * 1 1 1 1 1 1 * 1 1 1 1 1 * 1 1 1 0 0 2 2 2 2 2 2 0 0 0 0 0 0 0 0 0 
+| 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 2 2 2 * 1 1 1 1 1 * 1 1 1 1 * 1 1 1 1 1 * 1 1 1 1 0 0 2 2 2 2 2 2 0 0 0 0 0 0 0 0 0 
+| * * 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 2 2 2 1 * 1 1 1 1 1 * 1 1 * 1 1 1 1 1 * 1 1 1 1 1 0 0 2 2 2 2 2 2 0 0 0 0 0 * * * * 
+| 0 0 * * * * * * * * * * * * * * * * * * * * 2 2 2 1 1 * 1 1 1 1 1 * * 1 1 1 1 1 * 1 1 1 1 1 * * * * 2 2 2 2 * * * * * * 0 0 0 0 
+| 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 * 2 2 1 1 1 * 1 1 1 1 1 1 1 1 1 1 * 1 1 1 1 1 * 1 0 0 2 * 2 2 * 2 0 0 0 0 0 0 0 0 0 
+| 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 2 * 2 1 1 1 1 * 1 1 1 1 1 1 1 1 * 1 1 1 1 1 * 1 1 0 0 2 2 * * 2 2 0 0 0 0 0 0 0 0 0 
+| 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 2 2 * 1 1 1 1 1 * 1 1 1 1 1 1 * 1 1 1 1 1 * 1 1 1 0 0 2 2 2 2 2 2 0 0 0 0 0 0 0 0 0 
+| 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 2 2 2 * 1 1 1 1 1 * 1 1 1 1 * 1 1 1 1 1 * 1 1 1 1 0 0 2 2 2 2 2 2 0 0 0 0 0 0 0 0 0 
+| * 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 2 2 2 1 * 1 1 1 1 1 * 1 1 * 1 1 1 1 1 * 1 1 1 1 1 0 0 2 2 2 2 2 2 0 0 0 0 0 0 * * * 
+| 0 * * * * * * * * * * * * * * * * * * * * * 2 2 2 1 1 * 1 1 1 1 1 * * 1 1 1 1 1 * 1 1 1 1 1 * * * * 2 2 2 2 * * * * * * * 0 0 0 
+| 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 * 2 2 1 1 1 * 1 1 1 1 1 1 1 1 1 1 * 1 1 1 1 1 * 1 0 0 2 * 2 2 * 2 0 0 0 0 0 0 0 0 0 
+| 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 2 * 2 1 1 1 1 * 1 1 1 1 1 1 1 1 * 1 1 1 1 1 * 1 1 0 0 2 2 * * 2 2 0 0 0 0 0 0 0 0 0 
+| 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 2 2 * 1 1 1 1 1 _ _ _ _ _ _ _ _ 1 1 1 1 1 * 1 1 1 0 0 2 2 2 2 2 2 0 0 0 0 0 0 0 0 0 
+| 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 2 2 2 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 1 1 1 1 0 0 2 2 2 2 2 2 0 0 0 0 0 0 0 0 0 
+|                                                                                                                                 

+ 83 - 0
examples/stencil/6.out

@@ -0,0 +1,83 @@
+| 2 0 0 0 0 2 0 2 0 2 0 2 0 2 0 2 0 2 0 2 0 2 0 2 0 2 0 2 0 2 0 2 0 2 0 2 0 2 0 0 0 0 2 0 2 0 2 0 2 0 1 0 1 1 1 1 1 1 1 1 1 1 1 1 
+| 2 0 0 0 0 0 2 0 2 0 2 0 2 0 2 0 2 0 2 0 2 0 2 0 2 0 2 0 2 0 2 0 2 0 2 0 2 0 0 0 0 0 0 2 0 2 0 2 0 1 0 1 1 1 1 1 1 1 1 1 1 1 1 1 
+| 2 * * * * * * 2 * 2 * 2 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * 1 1 1 1 1 1 1 1 1 1 1 1 
+| * 0 0 0 0 0 0 * 0 * 0 * 0 2 0 2 0 2 0 2 0 2 0 2 0 2 0 2 0 2 0 2 0 2 0 2 0 0 0 0 0 0 0 0 2 0 2 0 1 0 1 1 * 1 1 1 1 1 1 1 1 1 1 * 
+| 2 0 0 0 0 0 0 0 2 0 2 0 2 0 2 0 2 0 2 0 2 0 2 0 2 0 2 0 2 0 2 0 2 0 2 0 0 0 0 0 0 0 0 0 0 2 0 1 0 1 1 1 1 * 1 1 1 1 1 1 1 1 * 1 
+| 2 0 0 0 0 0 0 0 0 2 0 2 0 2 0 2 0 2 0 2 0 2 0 2 0 2 0 2 0 2 0 2 0 2 0 0 0 0 0 0 0 0 0 0 0 0 1 0 1 1 1 1 1 1 * 1 1 1 1 1 1 * 1 1 
+| 2 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * 1 1 1 1 1 1 * 1 1 1 1 * 1 1 1 
+| * 0 0 0 0 0 0 0 0 0 2 0 2 0 2 0 2 0 2 0 2 0 2 0 2 0 2 0 2 0 2 0 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 * 1 1 1 1 1 1 * 1 1 * 1 1 1 * 
+| 2 0 0 0 0 0 0 0 0 0 0 2 0 2 0 2 0 2 0 2 0 2 0 2 0 2 0 2 0 2 0 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 * 1 1 1 1 1 1 * * 1 1 1 * 1 
+| 2 0 0 0 0 0 0 0 0 0 0 0 2 0 2 0 2 0 2 0 2 0 2 0 2 0 2 0 2 0 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 * 1 1 1 1 1 1 1 1 1 * 1 1 
+| 2 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * 1 1 1 1 * 1 1 1 1 1 1 1 * 1 1 1 
+| * 0 0 0 0 0 0 0 0 0 0 0 0 2 0 2 0 2 0 2 0 2 0 2 0 2 0 2 0 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 * 1 1 1 1 * 1 1 1 1 1 * 1 1 1 * 
+| 2 0 0 0 0 0 0 0 0 0 0 0 0 0 2 0 2 0 2 0 2 0 2 0 2 0 2 0 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 * 1 1 1 1 * 1 1 1 * 1 1 1 * 1 
+| 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 0 2 0 2 0 2 0 2 0 2 0 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 * 1 1 1 1 * 1 * 1 1 1 * 1 1 
+| 2 0 0 0 * * * * * * * * * * * * 2 * 2 * 2 * * * * * * * * * * * * * * * * * * * * * * * * * * * 1 1 1 * 1 1 1 1 * 1 1 1 * 1 1 1 
+| * * * * 0 0 0 0 0 0 0 0 0 0 0 0 * 0 * 0 * 0 2 0 2 0 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 * 1 1 1 * 1 1 1 1 1 1 * 1 1 1 1 
+| 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 0 2 0 2 0 2 0 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 * 1 1 1 * 1 1 1 1 * 1 1 1 * * 
+| 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 0 2 0 2 0 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 * 1 1 1 * 1 1 * 1 1 1 * 1 1 
+| 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 0 2 0 2 0 0 0 * * * * * * * * * * * * * * * * * * * * 1 1 1 1 * 1 1 1 * * 1 1 1 * 1 1 1 
+| * * * * * * * * * * * * * * * * * * * * * * * * * * * 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 * 1 1 1 1 * 1 1 1 1 1 1 * 1 1 1 1 
+| 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 0 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 * 1 1 1 1 * 1 1 1 1 * 1 1 1 1 * 
+| 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 * 1 1 1 1 * 1 1 * 1 1 1 1 * 1 
+| 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 * 1 1 1 1 * * 1 1 1 1 * 1 1 
+| 2 0 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * 1 1 1 * 1 1 1 1 1 1 1 1 * 1 1 1 
+| * * 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 * 1 1 1 * 1 1 1 1 1 1 * 1 1 1 1 
+| 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 * 1 1 1 * 1 1 1 1 * 1 1 1 1 * 
+| 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 * 1 1 1 * 1 1 * 1 1 1 * * 1 
+| 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 * * * * * * * * * * * * * * * * 1 1 1 1 * 1 1 1 * * 1 1 1 * 1 1 1 
+| * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 * 1 1 1 1 * 1 1 1 1 1 1 * 1 1 1 1 
+| 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 * 1 1 1 1 * 1 1 1 1 * 1 1 1 1 * 
+| 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 * 1 1 1 1 * 1 1 * 1 1 1 1 * 1 
+| 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 * 1 1 1 1 * * 1 1 1 1 * 1 1 
+| 2 0 0 0 0 0 0 0 0 0 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * 1 1 1 1 * 1 1 1 1 1 1 1 1 * 1 1 1 
+| * * * * * * * * * * 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 * 1 1 1 1 * 1 1 1 1 1 1 * 1 1 1 1 
+| 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 * 1 1 1 1 * 1 1 1 1 * 1 1 1 1 * 
+| 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 * 1 1 1 1 * 1 1 * 1 1 1 1 * 1 
+| 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 * * * * * * * * 1 1 1 * * 1 1 1 * * 1 1 1 1 * 1 1 
+| * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * 0 0 0 0 0 0 0 0 * 1 1 1 1 * 1 1 1 1 1 1 1 * 1 1 1 
+| 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 * 1 1 1 1 * 1 1 1 1 * * 1 1 1 * 
+| 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 * 1 1 1 1 * 1 1 * 1 1 1 1 * 1 
+| 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 * 1 1 1 1 * * 1 1 1 1 * 1 1 
+| 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 * * * * * * * * * * * * * * * * * * * * * * * * * * * * 1 1 1 1 * 1 1 1 1 1 1 1 1 * 1 1 1 
+| * * * * * * * * * * * * * * * * * * * 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 * 1 1 1 1 * 1 1 1 1 1 1 * 1 1 1 1 
+| 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 * 1 1 1 1 * 1 1 1 1 * 1 1 1 1 * 
+| 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 * 1 1 1 1 * 1 1 * 1 1 1 1 * 1 
+| 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 * 1 1 1 1 * * 1 1 1 1 * 1 1 
+| * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * 1 1 1 * 1 1 1 1 1 1 1 1 * 1 1 1 
+| 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 * 1 1 1 * 1 1 1 1 1 1 * 1 1 1 * 
+| 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 * 1 1 1 * 1 1 1 1 * 1 1 1 * 1 
+| 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 * 1 1 1 * 1 1 * 1 1 1 * 1 1 
+| 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 * * * * * * * * * * * * * * * * * * * * 1 1 1 1 * 1 1 1 * * 1 1 1 * 1 1 1 
+| * * * * * * * * * * * * * * * * * * * * * * * * * * * 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 * 1 1 1 1 * 1 1 1 1 1 1 * 1 1 1 1 
+| 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 * 1 1 1 1 * 1 1 1 1 * 1 1 1 1 * 
+| 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 * 1 1 1 1 * 1 1 * 1 1 1 1 * 1 
+| 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 * 1 1 1 1 * * 1 1 1 1 * 1 1 
+| 2 0 0 0 0 0 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * 1 1 1 1 * 1 1 1 1 1 1 1 1 * 1 1 1 
+| * * * * * * 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 * 1 1 1 1 * 1 1 1 1 1 1 * 1 1 1 1 
+| 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 * * 1 1 1 * 1 1 1 1 * 1 1 1 1 * 
+| 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 * 1 1 1 * 1 1 * 1 1 1 1 * 1 
+| 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 * * * * * * * * * * * * 1 1 1 1 * 1 1 1 * * 1 1 1 1 * 1 1 
+| * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * 0 0 0 0 0 0 0 0 0 0 0 0 * 1 1 1 1 * 1 1 1 1 1 1 * * 1 1 1 
+| 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 * 1 1 1 1 * 1 1 1 1 * 1 1 1 1 * 
+| 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 * 1 1 1 1 * 1 1 * 1 1 1 1 * 1 
+| 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 * 1 1 1 1 * * 1 1 1 1 * 1 1 
+| 2 0 0 0 0 0 0 0 0 0 0 0 0 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * 1 1 1 1 * 1 1 1 1 1 1 1 1 * 1 1 1 
+| * * * * * * * * * * * * * 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 * 1 1 1 1 * 1 1 1 1 1 1 * 1 1 1 1 
+| 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 * 1 1 1 1 * 1 1 1 1 * 1 1 1 1 * 
+| 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 * 1 1 1 1 * 1 1 * 1 1 1 1 * 1 
+| 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 * * * * 1 1 1 * 1 1 1 1 * * 1 1 1 1 * 1 1 
+| * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * 0 0 0 0 * 1 1 1 * 1 1 1 1 1 1 1 1 * 1 1 1 
+| 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 * 1 1 1 * * 1 1 1 1 1 * 1 1 1 * 
+| 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 * 1 1 1 1 * 1 1 1 * 1 1 1 * 1 
+| 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 * 1 1 1 1 * * * 1 1 1 * 1 1 
+| 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 * * * * * * * * * * * * * * * * * * * * * * * * * 1 1 1 1 * 1 1 1 1 1 1 1 1 * 1 1 1 
+| * * * * * * * * * * * * * * * * * * * * * * 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 * 1 1 1 1 * 1 1 1 1 1 1 * 1 1 1 1 
+| 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 * 1 1 1 1 * 1 1 1 1 * 1 1 1 1 * 
+| 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 * 1 1 1 1 * 1 1 * 1 1 1 1 * 1 
+| 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 * 1 1 1 1 * * 1 1 1 1 * 1 1 
+| 2 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * 1 1 1 * 1 1 1 1 1 1 1 1 * 1 1 1 
+| * 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 * 1 1 1 * 1 1 1 1 1 1 * 1 1 1 1 
+| 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 * 1 1 1 _ _ _ _ _ _ 1 1 1 * * 
+| 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 _ _ _ _ _ _ _ _ _ _ _ _ 1 1 
+|                                                                                                                                 

+ 102 - 0
examples/stencil/Makefile.am

@@ -0,0 +1,102 @@
+#
+# StarPU
+# Copyright (C) Université Bordeaux 1, CNRS 2008-2010 (see AUTHORS file)
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU Lesser General Public License as published by
+# the Free Software Foundation; either version 2.1 of the License, or (at
+# your option) any later version.
+#
+# This program is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+#
+# See the GNU Lesser General Public License in COPYING.LGPL for more details.
+#
+
+AM_CFLAGS = $(HWLOC_CFLAGS)
+LIBS = $(top_builddir)/src/libstarpu.la $(HWLOC_LIBS) @LIBS@
+AM_CPPFLAGS = -I$(top_srcdir)/include/ -I$(top_srcdir)/examples/ -I$(top_builddir)/include
+
+CC = $(CC_OR_MPICC)
+
+if STARPU_USE_CUDA
+
+NVCCFLAGS += $(HWLOC_CFLAGS)
+
+.cu.cubin:
+	$(MKDIR_P) `dirname $@`
+	$(NVCC) -cubin $< -o $@ --compiler-options -fno-strict-aliasing  $(NVCCFLAGS)
+
+.cu.o:
+	$(NVCC) $< -c -o $@ --compiler-options -fno-strict-aliasing  $(NVCCFLAGS) -I$(top_srcdir)/include/ -I$(top_builddir)/include/
+
+
+endif
+
+###################
+# stencil example #
+###################
+
+check_PROGRAMS =				\
+	stencil
+
+examplebindir = $(libdir)/starpu/examples/
+
+examplebin_PROGRAMS =				\
+	stencil
+
+stencil_SOURCES =				\
+	life.c					\
+	stencil-kernels.c			\
+	stencil-tasks.c				\
+	stencil-blocks.c			\
+	stencil.c
+
+noinst_HEADERS =				\
+	stencil.h
+
+if STARPU_USE_CUDA
+stencil_SOURCES +=				\
+	life_cuda.cu				\
+	shadow.cu
+endif
+
+outs =						\
+	0.5.out					\
+	0.out					\
+	1.out					\
+	2.out					\
+	3.out					\
+	4.out					\
+	6.out					\
+	mpi.out
+
+EXTRA_DIST = $(outs) results run README
+
+pics: $(outs:.out=.xpm)
+
+CLEANFILES = *.xpm
+
+%.out2: %.out
+	grep '^|' $< | tr -d ' ' > $@
+
+%.xpm: %.out2
+	( width=$$(expr $$(head -n 1 < $< | wc -c) - 1) ; \
+	height=`wc -l < $<` ; \
+	echo "/* XPM */" ; \
+	echo "static char * test_xpm[] = {" ; \
+	echo "\"$$width $$height 9 1\"," ; \
+	echo "\"_	c None\"," ; \
+	echo "\"0	c #FF0000\"," ; \
+	echo "\"1	c #00FF00\"," ; \
+	echo "\"2	c #0000FF\"," ; \
+	echo "\"3	c #FFFF00\"," ; \
+	echo "\"4	c #FF00FF\"," ; \
+	echo "\"5	c #00FFFF\"," ; \
+	echo "\"|	c #FFFFFF\"," ; \
+	echo "\"*	c #000000\"," ; \
+	< $< sed -e 's/^/"/' -e 's/$$/",/' | sed -e '$$s/",$$/"};/' ) > $@
+
+view:
+	feh --zoom 800 -F 0.xpm 0.5.xpm 1.xpm 2.xpm 3.xpm 4.xpm 6.xpm mpi.xpm

+ 27 - 0
examples/stencil/README

@@ -0,0 +1,27 @@
+This is a sample 3D stencil application (here just using the game of life rules
+for simplicity), split on the z axis.
+
+This is a suggest order of read:
+
+life.c
+life.cu: Heart of the stencil computation: compute a new state from an old one.
+
+shadow.cu
+shadow.h: Perform replication of data on X and Y edges, to fold the domain on
+itself through mere replication of the source state.
+
+stencil.h: Declarations
+
+stencil-kernels.c: Computation Kernels
+
+stencil-blocks.c: Manage block and tags allocation
+
+stencil-tasks.c: Schedule tasks for updates and saves
+
+stencil.c: Main application
+
+*.out: various results according to beta value (communication vs computation
+penalty ratio), run make pics or make view to get pictures.
+mpi.out: results on MPI.
+
+results: a few results

+ 44 - 0
examples/stencil/life.c

@@ -0,0 +1,44 @@
+/*
+ * StarPU
+ * Copyright (C) Université Bordeaux 1, CNRS 2009-2010 (see AUTHORS file)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation; either version 2.1 of the License, or (at
+ * your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * See the GNU Lesser General Public License in COPYING.LGPL for more details.
+ */
+
+#include "stencil.h"
+
+/* Heart of the stencil computation: compute a new state from an old one. */
+
+void life_update(int bz, const TYPE *old, TYPE *newp, int nx, int ny, int nz, int ldy, int ldz, int iter)
+{
+	unsigned x, y, z, num, alive;
+
+	for (z = iter; z < nz - iter; z++) {
+		for (y = K; y < ny - K; y++) {
+			for (x = K; x < nx - K; x++) {
+				num = 0
+                                        + old[x+(y+1)*ldy+(z+0)*ldz]
+                                        + old[x+(y+1)*ldy+(z+1)*ldz]
+                                        + old[x+(y+0)*ldy+(z+1)*ldz]
+                                        + old[x+(y-1)*ldy+(z+1)*ldz]
+                                        + old[x+(y-1)*ldy+(z+0)*ldz]
+                                        + old[x+(y-1)*ldy+(z-1)*ldz]
+                                        + old[x+(y+0)*ldy+(z-1)*ldz]
+                                        + old[x+(y+1)*ldy+(z-1)*ldz]
+					;
+				alive = old[x+y*ldy+z*ldz];
+				alive = (alive && num == 2) || num == 3;
+				newp[x+y*ldy+z*ldz] = alive;
+			}
+		}
+	}
+}

+ 76 - 0
examples/stencil/life_cuda.cu

@@ -0,0 +1,76 @@
+/*
+ * StarPU
+ * Copyright (C) Université Bordeaux 1, CNRS 2009-2010 (see AUTHORS file)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation; either version 2.1 of the License, or (at
+ * your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * See the GNU Lesser General Public License in COPYING.LGPL for more details.
+ */
+
+#define _externC extern "C"
+#include "stencil.h"
+
+/* Heart of the stencil computation: compute a new state from an old one. */
+
+extern "C" __global__ void
+cuda_life_update(int bz, const TYPE *old, TYPE *newp, int nx, int ny, int nz, int ldy, int ldz, int iter)
+{
+	unsigned idx = threadIdx.x + blockIdx.x * blockDim.x;
+	unsigned idy = threadIdx.y + blockIdx.y * blockDim.y;
+	//unsigned idz = threadIdx.z + blockIdx.z * blockDim.z;
+	unsigned idz = 0;
+	unsigned stepx = blockDim.x * gridDim.x;
+	unsigned stepy = blockDim.y * gridDim.y;
+	//unsigned stepz = blockDim.z * gridDim.z;
+	unsigned stepz = 1;
+	unsigned x, y, z;
+	unsigned num, alive;
+
+	for (z = iter + idz; z < nz - iter; z += stepz)
+		for (y = K + idy; y < ny - K; y += stepy) {
+			for (x = K + idx; x < nx - K; x += stepx) {
+				unsigned index = x + y*ldy + z*ldz;
+				num = 0
+                                        + old[index+1*ldy+0*ldz]
+                                        + old[index+1*ldy+1*ldz]
+                                        + old[index+0*ldy+1*ldz]
+                                        + old[index-1*ldy+1*ldz]
+                                        + old[index-1*ldy+0*ldz]
+                                        + old[index-1*ldy-1*ldz]
+                                        + old[index+0*ldy-1*ldz]
+                                        + old[index+1*ldy-1*ldz]
+					;
+				alive = old[index];
+				alive = (alive && num == 2) || num == 3;
+				newp[index] = alive;
+			}
+		}
+}
+
+extern "C" void
+cuda_life_update_host(int bz, const TYPE *old, TYPE *newp, int nx, int ny, int nz, int ldy, int ldz, int iter)
+{
+	unsigned max_parallelism = 512;
+	unsigned threads_per_dim_x = max_parallelism;
+	while (threads_per_dim_x / 2 >= nx)
+		threads_per_dim_x /= 2;
+	unsigned threads_per_dim_y = max_parallelism / threads_per_dim_x;
+	while (threads_per_dim_y / 2 >= ny)
+		threads_per_dim_y /= 2;
+#if 0
+	unsigned threads_per_dim_z = 4;
+	dim3 dimBlock(threads_per_dim_x, threads_per_dim_y, threads_per_dim_z);
+	dim3 dimGrid(nx / threads_per_dim_x, ny / threads_per_dim_y, nz / threads_per_dim_z);
+#else
+	dim3 dimBlock(threads_per_dim_x, threads_per_dim_y);
+	dim3 dimGrid((nx + threads_per_dim_x-1) / threads_per_dim_x, (ny + threads_per_dim_y-1) / threads_per_dim_y);
+#endif
+	cuda_life_update <<<dimGrid, dimBlock>>> (bz, old, newp, nx, ny, nz, ldy, ldz, iter);
+}

+ 94 - 0
examples/stencil/mpi.out

@@ -0,0 +1,94 @@
+Warning: MPI only has funneled thread support, not serialized, hoping this will work
+Running on 2 nodes
+Warning: MPI only has funneled thread support, not serialized, hoping this will work
+9 MB of memory were allocated on node 1
+9 MB of memory were allocated on node 0
+GO !
+update:
+	CPU 0 -> 2048 (100.00%)
+top:
+	CPU 0 -> 2048 (100.00%)
+bottom:
+	CPU 0 -> 2048 (100.00%)
+| 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 | 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 
+| 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 | 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 
+| 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 | 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 
+| 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 | 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 
+| * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * | * 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 * 
+| 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 | 1 * 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 * 1 
+| 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 | 1 1 * 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 * 1 1 
+| 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 | 1 1 1 * 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 * 1 1 1 
+| 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 | 1 1 1 1 * 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 * 1 1 1 1 
+| * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * | * 1 1 1 1 * 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 * 1 1 1 1 * 
+| 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 | 1 * 1 1 1 1 * 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 * 1 1 1 1 * 1 
+| 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 | 1 1 * 1 1 1 1 * 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 * 1 1 1 1 * 1 1 
+| 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 | 1 1 1 * 1 1 1 1 * 1 1 1 1 1 1 1 1 1 1 1 1 1 1 * 1 1 1 1 * 1 1 1 
+| * * * * * 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 * * * * | 1 1 1 1 * 1 1 1 1 * 1 1 1 1 1 1 1 1 1 1 1 1 * 1 1 1 1 * 1 1 1 1 
+| 0 0 0 0 0 * * * * * * * * * * * * * * * * * * * * * * * 0 0 0 0 | * 1 1 1 1 * 1 1 1 1 * 1 1 1 1 1 1 1 1 1 1 * 1 1 1 1 * 1 1 1 1 * 
+| 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 | 1 * 1 1 1 1 * 1 1 1 1 * 1 1 1 1 1 1 1 1 * 1 1 1 1 * 1 1 1 1 * 1 
+| 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 | 1 1 * 1 1 1 1 * 1 1 1 1 * 1 1 1 1 1 1 * 1 1 1 1 * 1 1 1 1 * 1 1 
+| 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 | 1 1 1 * 1 1 1 1 * 1 1 1 1 * 1 1 1 1 * 1 1 1 1 * 1 1 1 1 * 1 1 1 
+| * * * * * * * * * 0 0 0 0 0 0 0 0 0 0 0 0 0 * * * * * * * * * * | 1 1 1 1 * 1 1 1 1 * 1 1 1 1 * 1 1 * 1 1 1 1 * 1 1 1 1 * 1 1 1 1 
+| 0 0 0 0 0 0 0 0 0 * * * * * * * * * * * * * 0 0 0 0 0 0 0 0 0 0 | * 1 1 1 1 * 1 1 1 1 * 1 1 1 1 * * 1 1 1 1 * 1 1 1 1 * 1 1 1 1 * 
+| 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 | 1 * 1 1 1 1 * 1 1 1 1 * 1 1 1 1 1 1 1 1 * 1 1 1 1 * 1 1 1 1 * 1 
+| 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 | 1 1 * 1 1 1 1 * 1 1 1 1 * 1 1 1 1 1 1 * 1 1 1 1 * 1 1 1 1 * 1 1 
+| 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 | 1 1 1 * 1 1 1 1 * 1 1 1 1 * 1 1 1 1 * 1 1 1 1 * 1 1 1 1 * 1 1 1 
+| * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * | * 1 1 1 * 1 1 1 1 * 1 1 1 1 * 1 1 * 1 1 1 1 * 1 1 1 1 * 1 1 1 * 
+| 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 | 1 * 1 1 1 * 1 1 1 1 * 1 1 1 1 * * 1 1 1 1 * 1 1 1 1 * 1 1 1 * 1 
+| 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 | 1 1 * 1 1 1 * 1 1 1 1 * 1 1 1 1 1 1 1 1 * 1 1 1 1 * 1 1 1 * 1 1 
+| 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 | 1 1 1 * 1 1 1 * 1 1 1 1 * 1 1 1 1 1 1 * 1 1 1 1 * 1 1 1 * 1 1 1 
+| * * * * * * * * 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 * * * * * * * | 1 1 1 1 * 1 1 1 * 1 1 1 1 * 1 1 1 1 * 1 1 1 1 * 1 1 1 * 1 1 1 1 
+| 0 0 0 0 0 0 0 0 * * * * * * * * * * * * * * * * * 0 0 0 0 0 0 0 | * 1 1 1 1 * 1 1 1 * 1 1 1 1 * 1 1 * 1 1 1 1 * 1 1 1 * 1 1 1 1 * 
+| 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 | 1 * 1 1 1 1 * 1 1 1 * 1 1 1 1 * * 1 1 1 1 * 1 1 1 * 1 1 1 1 * 1 
+| 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 | 1 1 * 1 1 1 1 * 1 1 1 * 1 1 1 1 1 1 1 1 * 1 1 1 * 1 1 1 1 * 1 1 
+| * 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 * * | 1 1 1 * 1 1 1 1 * 1 1 1 * 1 1 1 1 1 1 * 1 1 1 * 1 1 1 1 * 1 1 1 
+| 0 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * 0 0 | * 1 1 1 * 1 1 1 1 * 1 1 1 * 1 1 1 1 * 1 1 1 * 1 1 1 1 * 1 1 1 * 
+| 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 | 1 * 1 1 1 * 1 1 1 1 * 1 1 1 * 1 1 * 1 1 1 * 1 1 1 1 * 1 1 1 * 1 
+| 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 | 1 1 * 1 1 1 * 1 1 1 1 * 1 1 1 * * 1 1 1 * 1 1 1 1 * 1 1 1 * 1 1 
+| 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 | 1 1 1 * 1 1 1 * 1 1 1 1 * 1 1 1 1 1 1 * 1 1 1 1 * 1 1 1 * 1 1 1 
+| * * * * * * * * * * 0 0 0 0 0 0 0 0 0 0 0 0 * * * * * * * * * * | 1 1 1 1 * 1 1 1 * 1 1 1 1 * 1 1 1 1 * 1 1 1 1 * 1 1 1 * 1 1 1 1 
+| 0 0 0 0 0 0 0 0 0 0 * * * * * * * * * * * * 0 0 0 0 0 0 0 0 0 0 | * 1 1 1 1 * 1 1 1 * 1 1 1 1 * 1 1 * 1 1 1 1 * 1 1 1 * 1 1 1 1 * 
+| 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 | 1 * 1 1 1 1 * 1 1 1 * 1 1 1 1 * * 1 1 1 1 * 1 1 1 * 1 1 1 1 * 1 
+| 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 | 1 1 * 1 1 1 1 * 1 1 1 * 1 1 1 1 1 1 1 1 * 1 1 1 * 1 1 1 1 * 1 1 
+| * * 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 * * * | 1 1 1 * 1 1 1 1 * 1 1 1 * 1 1 1 1 1 1 * 1 1 1 * 1 1 1 1 * 1 1 1 
+| 0 0 * * * * * * * * * * * * * * * * * * * * * * * * * * * 0 0 0 | * 1 1 1 * 1 1 1 1 * 1 1 1 * 1 1 1 1 * 1 1 1 * 1 1 1 1 * 1 1 1 * 
+| 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 | 1 * 1 1 1 * 1 1 1 1 * 1 1 1 * 1 1 * 1 1 1 * 1 1 1 1 * 1 1 1 * 1 
+| 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 | 1 1 * 1 1 1 * 1 1 1 1 * 1 1 1 * * 1 1 1 * 1 1 1 1 * 1 1 1 * 1 1 
+| 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 | 1 1 1 * 1 1 1 * 1 1 1 1 * 1 1 1 1 1 1 * 1 1 1 1 * 1 1 1 * 1 1 1 
+| * * * * * * * * * * 0 0 0 0 0 0 0 0 0 0 0 0 * * * * * * * * * * | 1 1 1 1 * 1 1 1 * 1 1 1 1 * 1 1 1 1 * 1 1 1 1 * 1 1 1 * 1 1 1 1 
+| 0 0 0 0 0 0 0 0 0 0 * * * * * * * * * * * * 0 0 0 0 0 0 0 0 0 0 | * 1 1 1 1 * 1 1 1 * 1 1 1 1 * 1 1 * 1 1 1 1 * 1 1 1 * 1 1 1 1 * 
+| 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 | 1 * 1 1 1 1 * 1 1 1 * 1 1 1 1 * * 1 1 1 1 * 1 1 1 * 1 1 1 1 * 1 
+| 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 | 1 1 * 1 1 1 1 * 1 1 1 * 1 1 1 1 1 1 1 1 * 1 1 1 * 1 1 1 1 * 1 1 
+| * 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 * | 1 1 1 * 1 1 1 1 * 1 1 1 * 1 1 1 1 1 1 * 1 1 1 * 1 1 1 1 * 1 1 1 
+| 0 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * 0 | * 1 1 1 * 1 1 1 1 * 1 1 1 * * 1 1 * * 1 1 1 * 1 1 1 1 * 1 1 1 * 
+| 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 | 1 * 1 1 1 * 1 1 1 1 * 1 1 1 1 * * 1 1 1 1 * 1 1 1 1 * 1 1 1 * 1 
+| 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 | 1 1 * 1 1 1 * 1 1 1 1 * 1 1 1 1 1 1 1 1 * 1 1 1 1 * 1 1 1 * 1 1 
+| 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 | 1 1 1 * 1 1 1 * 1 1 1 1 * 1 1 1 1 1 1 * 1 1 1 1 * 1 1 1 * 1 1 1 
+| * * * * * * * * * * * * 0 0 0 0 0 0 0 0 * * * * * * * * * * * * | 1 1 1 1 * 1 1 1 * 1 1 1 1 * 1 1 1 1 * 1 1 1 1 * 1 1 1 * 1 1 1 1 
+| 0 0 0 0 0 0 0 0 0 0 0 0 * * * * * * * * 0 0 0 0 0 0 0 0 0 0 0 0 | * 1 1 1 1 * 1 1 1 * 1 1 1 1 * 1 1 * 1 1 1 1 * 1 1 1 * 1 1 1 1 * 
+| 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 | 1 * 1 1 1 1 * 1 1 1 * 1 1 1 1 * * 1 1 1 1 * 1 1 1 * 1 1 1 1 * 1 
+| 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 | 1 1 * 1 1 1 1 * 1 1 1 * 1 1 1 1 1 1 1 1 * 1 1 1 * 1 1 1 1 * 1 1 
+| * 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 * | 1 1 1 * 1 1 1 1 * 1 1 1 * 1 1 1 1 1 1 * 1 1 1 * 1 1 1 1 * 1 1 1 
+| 0 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * 0 | * 1 1 1 * 1 1 1 1 * 1 1 1 * 1 1 1 1 * 1 1 1 * 1 1 1 1 * 1 1 1 * 
+| 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 | 1 * 1 1 1 * 1 1 1 1 * 1 1 1 * 1 1 * 1 1 1 * 1 1 1 1 * 1 1 1 * 1 
+| 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 | 1 1 * 1 1 1 * 1 1 1 1 * 1 1 1 * * 1 1 1 * 1 1 1 1 * 1 1 1 * 1 1 
+| 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 | 1 1 1 * 1 1 1 * 1 1 1 1 * 1 1 1 1 1 1 * 1 1 1 1 * 1 1 1 * 1 1 1 
+| * * * * 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 * * * | 1 1 1 1 * 1 1 1 * 1 1 1 1 * 1 1 1 1 * 1 1 1 1 * 1 1 1 * 1 1 1 1 
+| 0 0 0 0 * * * * * * * * * * * * * * * * * * * * * * * * * 0 0 0 | * 1 1 1 1 * 1 1 1 * 1 1 1 1 * 1 1 * 1 1 1 1 * 1 1 1 * 1 1 1 1 * 
+| 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 | 1 * 1 1 1 1 * 1 1 1 * 1 1 1 1 * * 1 1 1 1 * 1 1 1 * 1 1 1 1 * 1 
+| 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 | 1 1 * 1 1 1 1 * 1 1 1 * 1 1 1 1 1 1 1 1 * 1 1 1 * 1 1 1 1 * 1 1 
+| 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 | 1 1 1 * 1 1 1 1 * 1 1 1 * 1 1 1 1 1 1 * 1 1 1 * 1 1 1 1 * 1 1 1 
+| * * * * * * * * * 0 0 0 0 0 0 0 0 0 0 0 0 0 0 * * * * * * * * * | 1 1 1 1 * 1 1 1 1 * 1 1 1 * 1 1 1 1 * 1 1 1 * 1 1 1 1 * 1 1 1 1 
+| 0 0 0 0 0 0 0 0 0 * * * * * * * * * * * * * * 0 0 0 0 0 0 0 0 0 | * 1 1 1 1 * 1 1 1 1 * 1 1 1 * 1 1 * 1 1 1 * 1 1 1 1 * 1 1 1 1 * 
+| 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 | 1 * 1 1 1 1 * 1 1 1 1 * 1 1 1 * * 1 1 1 * 1 1 1 1 * 1 1 1 1 * 1 
+| 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 | 1 1 * 1 1 1 1 * 1 1 1 1 * 1 1 1 1 1 1 * 1 1 1 1 * 1 1 1 1 * 1 1 
+| 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 | 1 1 1 * 1 1 1 1 * 1 1 1 1 * 1 1 1 1 * 1 1 1 1 * 1 1 1 1 * 1 1 1 
+| * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * | * 1 1 1 * 1 1 1 1 * 1 1 1 1 * 1 1 * 1 1 1 1 * 1 1 1 1 * 1 1 1 * 
+| 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 | 1 * 1 1 1 * 1 1 1 1 * 1 1 1 1 * * 1 1 1 1 * 1 1 1 1 * 1 1 1 * 1 
+| 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 | 1 1 * 1 1 1 * 1 1 1 1 * 1 1 1 1 1 1 1 1 * 1 1 1 1 * 1 1 1 * 1 1 
+| 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 | 1 1 1 * 1 1 1 * 1 1 1 1 * 1 1 1 1 1 1 * 1 1 1 1 * 1 1 1 * 1 1 1 
+| * * * * * * * 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 * * * * * * | 1 1 1 1 * 1 1 1 * 1 1 1 1 _ _ _ _ _ _ 1 1 1 1 * 1 1 1 * 1 1 1 1 
+| 0 0 0 0 0 0 0 * * * * * * * * * * * * * * * * * * * 0 0 0 0 0 0 | * 1 1 1 1 * 1 1 1 _ _ _ _ _ _ _ _ _ _ _ _ _ _ 1 1 1 * 1 1 1 1 * 
+| 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 | 1 * 1 1 1 1 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 1 1 1 1 * 1 
+| 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 | 1 1 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 1 1 
+| _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

+ 398 - 0
examples/stencil/results

@@ -0,0 +1,398 @@
+B=0
+| 0 1 1 1 2 0 0 1 0 1 1 0 2 0 0 2 1 0 2 1 0 2 0 1 2 0 2 1 2 0 0 1 0 1 1 2 0 1 0 2 0 1 0 0 2 0 1 2 0 2 2 1 0 0 2 1 0 0 2 0 0 1 2 1 
+| 0 0 0 1 2 1 1 0 0 0 1 1 0 2 1 0 1 0 0 1 1 0 1 0 1 0 0 1 0 2 0 2 1 0 0 0 1 1 2 0 0 2 0 0 1 2 0 1 2 0 2 0 1 0 2 0 1 2 0 1 2 0 2 2 
+| 2 0 1 2 1 2 0 2 0 1 0 2 2 1 0 0 2 0 0 0 2 0 0 0 1 0 1 0 1 0 2 1 2 0 2 2 0 2 2 1 0 0 1 0 0 1 2 1 0 0 0 2 2 0 1 0 2 1 2 0 1 0 0 1 
+| 0 0 1 0 0 2 1 0 0 1 2 1 1 2 1 2 1 0 2 2 1 0 0 0 0 1 2 1 0 0 1 2 1 0 0 1 0 2 0 1 2 1 2 1 0 1 0 2 0 0 0 0 2 1 0 0 2 0 1 0 1 2 1 2 
+| 1 0 0 0 0 2 1 2 2 0 2 1 2 0 1 1 0 0 1 2 0 1 2 1 1 0 0 2 2 1 0 1 2 0 0 0 0 2 1 0 2 0 0 2 0 1 1 0 2 1 2 2 0 1 1 1 2 0 0 0 0 2 0 2 
+| 0 0 1 1 0 1 1 2 1 2 2 1 0 1 0 2 2 0 1 2 1 0 1 0 1 0 0 2 1 0 2 1 0 0 2 0 0 1 0 1 2 0 2 0 1 2 0 1 1 0 2 0 0 2 1 0 1 0 0 1 2 0 2 0 
+| 2 0 1 2 1 0 0 0 1 0 2 0 1 2 0 0 0 2 0 1 0 0 0 0 1 1 0 2 1 0 0 1 0 2 1 2 0 2 2 0 2 1 1 1 0 0 0 0 1 2 2 1 1 0 0 0 2 0 2 1 2 0 2 1 
+| 1 0 0 0 0 0 0 0 1 0 0 0 1 0 1 1 0 0 2 0 2 0 0 2 0 0 2 1 2 2 2 0 1 1 0 1 1 1 1 1 0 1 0 2 2 2 0 1 0 1 0 2 0 1 1 0 0 1 2 1 0 2 1 2 
+| 2 0 1 2 0 2 0 1 0 2 1 0 0 0 0 0 2 2 1 0 2 2 1 0 2 0 1 0 0 2 0 0 2 0 1 1 0 0 0 2 2 1 2 0 1 2 0 2 0 0 2 2 1 0 0 2 0 2 1 0 1 0 2 0 
+| 0 0 2 1 2 0 2 2 1 0 0 2 1 2 0 1 0 2 1 2 0 2 0 0 1 0 0 0 1 1 0 1 2 1 2 1 1 0 1 2 1 0 2 0 1 2 0 0 0 2 2 2 0 2 0 2 0 0 0 0 1 0 2 0 
+| 0 0 0 1 2 0 0 1 0 1 2 2 0 0 1 1 0 2 1 0 2 2 1 1 0 0 2 0 1 2 0 0 0 0 1 2 0 0 0 2 1 0 0 2 0 2 1 2 0 0 2 1 2 0 2 1 2 1 2 1 0 2 0 1 
+| 1 1 1 1 2 2 0 1 2 1 0 0 0 1 2 2 0 1 2 1 2 0 1 1 2 0 1 1 0 2 0 1 0 1 2 0 2 0 2 0 1 0 2 0 2 2 1 2 0 1 2 0 0 0 1 2 0 0 0 0 0 2 2 0 
+| 0 2 0 0 2 0 1 1 1 0 0 1 2 0 1 1 2 0 0 0 0 1 0 0 2 0 1 0 0 1 0 0 1 2 1 0 2 2 1 1 0 2 1 2 0 2 1 0 0 0 1 0 2 1 2 1 0 2 0 1 2 1 0 0 
+| 1 1 0 0 1 1 1 0 1 2 2 0 1 2 2 0 1 2 0 2 1 1 2 2 1 0 0 1 2 2 2 1 2 0 2 0 0 0 0 2 2 0 0 1 0 0 1 0 0 2 0 1 2 0 0 1 1 2 0 1 0 2 1 2 
+| 1 2 2 1 0 0 0 1 0 2 0 0 2 1 1 1 1 1 0 1 2 1 2 1 0 2 2 0 2 0 2 1 0 0 1 2 0 1 2 0 1 2 0 0 1 0 2 1 1 2 0 1 0 2 2 0 0 0 0 0 1 0 0 1 
+| 0 0 2 0 2 2 0 1 2 0 1 0 2 0 2 0 1 0 1 2 2 1 0 1 2 2 1 0 0 1 0 1 0 2 0 1 0 0 2 1 2 0 0 0 1 1 1 1 1 0 0 0 2 0 1 0 0 0 2 2 0 2 0 0 
+| 0 0 1 0 0 0 1 0 0 1 2 0 2 0 2 0 2 1 0 1 0 1 0 2 0 0 0 1 0 0 1 2 1 0 2 2 1 1 2 0 2 1 1 2 2 2 0 0 2 1 2 0 0 0 2 1 1 2 2 0 1 0 1 0 
+| 2 1 1 0 2 2 0 1 0 2 1 1 0 0 1 0 0 0 2 1 0 1 0 2 2 2 0 1 2 2 0 2 0 0 0 2 0 1 2 0 1 2 2 0 1 0 0 1 1 0 2 0 2 1 0 2 0 1 1 0 1 0 0 0 
+| 2 0 2 0 2 1 1 0 1 0 1 2 1 0 2 0 0 1 0 2 0 2 0 2 0 1 0 1 0 2 0 1 2 0 0 0 1 0 1 0 0 2 1 2 1 0 2 1 2 0 1 2 2 0 2 0 0 0 1 1 2 0 2 2 
+| 2 1 0 2 0 2 1 2 0 2 0 0 1 0 0 1 0 0 0 0 2 1 2 0 2 1 2 2 0 2 1 0 2 0 2 2 2 1 0 2 2 1 0 2 1 0 0 0 1 0 0 1 2 1 0 0 0 2 1 1 1 0 2 1 
+| 2 2 0 0 1 0 0 1 0 1 0 0 0 2 0 2 1 0 1 2 2 0 2 0 2 0 2 0 0 2 1 0 0 1 0 0 2 1 2 2 1 1 2 0 1 2 2 0 2 0 0 2 0 0 0 1 0 2 0 1 2 2 0 1 
+| 2 0 2 1 2 0 2 2 1 2 0 0 0 2 1 0 0 2 2 0 0 1 2 2 0 2 2 0 0 0 1 2 1 0 0 0 2 0 2 2 2 0 0 1 2 0 1 1 0 1 2 1 0 0 0 0 1 0 0 2 1 1 0 1 
+| 0 0 1 1 1 0 1 0 2 1 0 0 2 1 2 0 1 1 2 0 1 1 0 0 1 2 0 1 2 0 0 0 2 0 1 0 1 0 0 2 1 0 2 1 2 0 0 2 0 2 1 0 1 2 2 2 1 0 2 0 1 0 1 2 
+| 2 2 0 2 1 0 2 0 0 0 0 0 1 2 0 1 0 2 0 1 0 0 2 0 2 0 2 1 0 2 1 0 2 2 0 1 0 1 0 1 2 0 0 1 2 1 0 0 1 2 1 2 0 1 0 1 2 2 0 0 1 2 1 1 
+| 0 2 0 0 1 0 1 2 0 0 0 2 1 0 2 2 2 1 0 1 2 0 0 1 1 2 1 0 1 1 0 2 1 2 0 0 0 1 0 1 1 0 0 0 1 0 2 2 1 0 0 2 0 2 1 2 0 2 0 0 1 1 0 2 
+| 2 1 1 2 0 2 0 0 0 0 1 2 2 0 0 2 0 2 1 0 2 0 2 0 1 1 0 2 1 0 1 0 0 0 2 2 0 2 1 0 0 2 2 2 0 1 2 1 0 0 2 0 1 0 0 0 0 1 2 1 0 2 0 2 
+| 1 0 2 1 0 0 0 1 0 1 0 2 2 0 1 1 0 2 0 0 2 1 1 2 1 0 0 0 2 2 2 2 1 1 1 2 1 0 1 2 0 2 0 2 0 0 2 0 1 0 0 2 1 0 0 2 1 2 0 2 0 0 1 0 
+| 1 1 2 2 1 2 0 2 0 0 2 0 2 0 1 0 1 0 0 2 1 0 1 2 1 1 2 0 2 1 2 1 0 0 2 2 0 2 0 0 0 2 0 0 0 1 0 1 0 2 0 1 1 2 2 0 0 2 2 0 2 0 0 0 
+| 0 2 0 1 0 0 1 0 1 2 1 1 2 0 0 0 0 2 2 1 0 1 0 2 0 2 0 1 2 0 2 0 2 0 0 2 1 0 2 2 1 0 2 1 2 0 0 0 1 1 1 1 2 1 1 0 1 2 1 2 1 2 1 2 
+| 0 2 0 0 0 1 1 0 1 1 2 0 0 2 2 0 2 2 2 2 2 0 2 0 1 2 0 0 0 0 1 1 0 2 0 1 2 0 2 1 0 2 2 0 0 2 2 0 1 0 2 2 1 2 0 0 2 2 1 0 0 0 0 1 
+| 2 0 0 2 0 2 2 0 2 0 0 0 1 0 0 0 1 0 2 2 2 0 2 0 0 2 0 2 0 1 2 0 2 1 0 2 1 2 0 0 2 0 0 1 0 2 2 2 0 1 0 0 2 0 0 0 1 1 0 1 0 2 0 1 
+| 0 2 2 0 0 2 0 2 0 0 2 1 1 0 0 0 2 0 1 2 0 2 2 1 0 2 0 0 1 0 2 2 0 0 0 1 1 2 1 1 0 2 0 1 0 0 2 1 0 2 1 0 1 0 2 0 2 2 2 2 1 1 0 2 
+| 0 1 2 1 0 1 0 2 1 1 2 0 0 2 0 0 1 1 0 2 1 0 2 2 2 0 1 0 0 0 0 0 0 0 2 2 1 1 0 1 2 0 1 0 0 1 0 1 0 2 2 0 0 0 1 0 2 2 0 2 0 2 1 0 
+| 1 0 1 0 2 0 2 2 0 2 1 1 0 2 0 0 0 2 2 0 2 2 0 1 0 0 1 0 2 1 0 0 0 1 2 0 0 2 0 0 0 0 2 2 1 1 2 2 1 0 2 1 1 0 0 1 1 0 2 0 1 1 0 2 
+| 0 2 0 2 1 1 0 2 0 1 2 0 2 1 2 2 2 2 0 0 0 1 1 0 2 0 1 2 0 1 2 2 0 0 0 1 2 0 0 0 2 0 1 0 2 1 2 0 0 0 0 0 2 0 0 2 0 2 2 2 0 0 0 2 
+| 1 2 0 2 1 0 2 0 1 1 2 0 0 2 1 2 0 2 0 1 2 2 1 0 2 0 2 0 2 2 0 1 2 2 0 0 2 0 0 2 0 1 0 0 2 2 1 0 1 2 0 0 2 2 0 0 0 0 2 2 0 1 2 1 
+| 1 0 1 1 0 1 0 2 1 0 1 1 1 1 1 0 0 0 2 2 1 0 0 1 1 0 0 2 0 2 0 0 2 0 0 0 0 2 2 0 0 1 1 0 2 1 1 2 1 0 2 1 1 0 0 0 0 0 1 2 0 0 0 0 
+| 2 0 0 2 1 0 2 0 1 2 0 2 0 1 2 1 0 0 0 1 0 2 0 2 0 2 1 0 0 0 2 0 0 1 0 2 2 2 1 2 2 0 1 0 1 1 0 2 0 0 0 1 2 0 1 2 2 1 1 0 1 1 1 1 
+| 1 0 2 0 1 0 0 0 0 0 0 0 0 2 2 2 2 0 2 0 0 0 1 0 2 1 0 0 0 2 0 1 2 2 2 0 2 0 1 1 2 2 2 2 2 0 1 0 2 2 2 0 1 1 0 1 2 2 0 1 1 2 0 2 
+| 2 0 0 0 0 1 2 1 1 0 1 1 1 0 2 1 0 2 0 1 0 2 1 2 2 1 0 2 0 1 1 0 2 0 0 2 2 0 0 2 0 0 2 1 0 1 0 1 0 1 2 1 2 0 0 2 0 2 0 2 0 2 0 0 
+| 1 0 1 2 2 0 1 2 1 0 0 2 1 2 2 1 0 1 0 0 0 1 1 0 0 2 1 0 0 2 1 1 1 0 0 0 0 0 0 2 1 1 0 2 2 1 1 0 2 2 2 0 1 0 0 0 2 0 0 2 1 1 0 2 
+| 1 1 1 0 1 2 0 2 1 2 0 2 0 2 1 0 2 0 2 0 0 0 1 2 0 2 0 2 2 0 0 1 1 2 1 2 0 1 2 0 0 1 0 0 2 0 1 0 2 1 0 0 2 2 0 2 0 2 2 2 1 2 0 1 
+| 1 1 0 2 2 1 2 0 0 1 0 2 2 0 2 0 1 0 2 1 0 0 0 0 2 0 2 1 0 1 2 1 0 0 1 2 0 1 0 1 0 1 1 0 0 2 2 2 2 0 1 1 0 0 0 0 2 0 1 2 2 1 2 0 
+| 0 0 0 0 1 0 2 2 1 2 1 0 2 2 1 2 1 0 2 0 1 2 2 0 1 0 2 0 0 0 2 1 0 2 1 0 1 0 0 0 0 0 0 1 0 2 0 1 0 1 0 2 1 0 0 0 2 0 2 2 2 0 1 2 
+| 0 1 0 2 0 0 1 0 1 1 0 0 0 1 2 2 0 1 0 2 2 1 0 0 2 0 1 1 2 2 2 0 1 1 2 2 1 1 2 0 2 1 2 2 2 0 0 2 2 0 1 0 0 0 0 0 2 0 1 1 2 2 1 0 
+| 0 0 0 2 1 0 2 2 1 0 1 1 1 0 1 2 2 2 1 0 0 2 0 2 2 1 0 1 0 1 2 1 0 0 0 0 1 0 1 0 2 2 0 1 2 2 0 1 0 0 0 2 2 1 0 0 2 0 0 0 2 0 1 0 
+| 0 1 0 0 0 0 0 1 0 0 0 1 0 1 1 2 0 2 0 1 1 2 2 0 1 1 0 1 2 1 0 1 0 2 1 0 1 1 0 2 1 1 0 2 2 1 1 0 2 2 0 0 0 0 2 1 0 2 0 0 0 1 2 2 
+| 1 1 2 1 2 2 0 0 2 1 2 0 2 0 0 0 0 0 0 1 1 2 2 2 1 0 1 0 2 0 0 2 0 1 2 1 0 2 1 1 0 1 0 2 0 1 1 0 2 0 1 2 2 0 1 2 0 2 0 0 1 0 2 0 
+| 2 0 0 0 1 0 2 0 2 0 0 0 2 1 1 0 1 2 0 2 1 1 1 1 1 0 2 1 1 2 0 2 0 2 1 2 0 2 1 0 0 2 1 1 0 2 0 2 0 0 1 0 0 0 1 0 2 0 2 0 1 0 2 0 
+| 2 0 2 0 1 0 0 1 1 0 0 0 1 2 2 1 0 2 1 1 0 1 0 2 1 0 0 0 1 2 0 0 0 0 1 2 1 2 1 0 0 0 0 0 1 2 0 1 0 2 2 0 0 0 2 1 0 1 2 0 0 1 0 0 
+| 0 1 0 1 2 0 0 1 0 2 0 0 2 1 2 1 0 0 0 2 1 0 2 0 0 0 0 2 2 0 0 0 2 1 0 2 2 0 1 2 2 2 0 2 2 0 2 2 2 1 0 2 1 0 1 2 1 2 0 2 0 1 0 1 
+| 2 0 2 0 1 2 0 1 0 0 2 1 1 0 0 0 1 0 1 2 0 2 1 0 1 1 2 2 0 0 2 0 0 0 2 1 0 0 1 2 2 0 0 0 0 2 0 2 2 2 1 0 0 0 0 1 0 0 2 1 1 2 0 2 
+| 0 0 1 0 2 2 1 0 2 2 0 1 0 1 1 0 0 1 1 2 0 0 2 0 0 0 2 1 2 0 0 0 1 2 0 1 0 1 2 1 0 0 1 0 2 1 0 0 1 0 2 0 1 1 0 2 1 1 0 2 2 0 2 1 
+| 1 0 1 1 0 1 2 0 2 1 0 0 1 0 0 0 0 0 0 0 0 2 0 2 0 0 0 2 1 0 2 2 0 2 1 1 1 2 0 1 0 0 0 1 2 0 1 2 1 2 2 0 2 0 1 1 2 1 2 0 1 2 1 0 
+| 0 2 0 1 0 1 2 0 1 0 1 0 2 0 0 1 0 0 2 0 2 0 2 0 1 2 0 0 1 2 1 1 0 0 0 1 1 0 1 0 2 2 0 1 2 2 0 2 1 2 2 0 0 2 1 0 0 2 0 2 1 2 0 0 
+| 2 2 2 0 0 0 0 2 1 0 0 0 2 2 1 2 0 1 0 2 0 0 1 0 2 0 1 2 0 0 0 2 0 2 0 1 1 2 1 0 2 2 2 1 2 2 2 1 2 2 0 1 1 1 2 0 2 0 0 2 2 0 1 0 
+| 0 0 2 0 1 2 2 1 0 0 2 0 2 1 1 0 1 0 0 1 1 1 2 1 1 0 1 2 0 2 0 1 0 0 0 1 0 2 0 0 1 0 0 0 1 0 1 2 0 1 0 1 0 0 0 1 0 2 0 0 2 2 0 2 
+| 0 2 1 0 1 1 0 2 0 2 2 1 2 1 1 1 0 0 1 2 2 2 0 1 0 0 1 2 1 0 2 0 0 1 0 2 0 0 0 2 2 1 0 0 0 2 1 2 0 2 1 0 1 0 1 0 2 0 2 0 1 2 2 2 
+| 0 1 0 2 2 1 2 0 2 0 0 1 2 1 0 0 2 2 0 0 2 0 2 1 0 1 2 2 0 1 1 0 0 0 2 1 1 0 2 0 0 0 0 0 1 0 0 0 0 0 0 2 1 2 2 1 1 0 0 1 0 1 2 0 
+| 2 1 0 0 1 1 2 2 0 1 0 2 0 2 1 0 2 0 1 0 0 2 0 1 0 0 0 1 0 0 0 0 0 1 1 0 0 2 0 1 0 1 0 2 1 0 2 2 2 0 0 2 1 1 2 1 2 1 1 0 1 2 0 1 
+| 1 0 0 2 1 0 2 0 2 1 2 2 1 0 1 2 0 1 1 1 2 1 0 0 0 0 2 1 0 2 0 1 2 2 0 0 0 0 2 2 1 0 1 0 0 2 0 2 0 0 2 0 2 1 0 2 1 0 0 1 0 0 0 0 
+| 0 1 0 2 0 2 1 0 1 2 0 0 2 0 0 2 2 0 1 2 1 2 1 0 0 2 2 0 1 2 2 0 0 2 0 1 2 0 1 2 0 1 0 2 0 1 0 2 0 0 0 0 0 0 1 2 1 1 0 0 1 1 0 2 
+| 0 2 1 0 2 0 0 1 0 1 2 2 1 2 0 1 0 2 0 1 0 0 0 0 1 0 0 2 2 2 1 2 2 1 0 0 2 1 0 1 2 0 0 1 0 0 2 2 1 0 0 2 0 2 1 0 2 0 0 0 2 0 2 1 
+| 0 0 1 2 0 2 2 2 1 0 2 0 2 2 0 0 1 0 1 0 2 2 0 0 0 1 2 2 1 1 1 0 0 1 2 1 0 1 0 1 2 2 0 2 0 2 2 0 2 0 2 2 0 2 1 2 0 0 2 0 2 2 0 0 
+
+B=1
+| 0 0 2 0 2 0 2 0 2 0 1 1 1 1 1 1 0 0 0 0 2 2 2 1 0 1 2 2 2 2 2 1 2 1 0 0 0 0 1 0 0 2 0 2 0 1 1 1 2 2 2 2 1 1 1 0 0 0 0 2 0 1 1 1 
+| 0 0 0 2 0 2 0 2 0 0 1 1 1 1 1 1 0 0 0 0 2 2 2 1 1 1 2 2 2 2 2 2 1 1 0 0 0 0 0 0 0 2 2 0 2 1 1 1 2 2 2 2 1 1 1 0 0 0 0 0 2 1 1 1 
+| 0 0 0 0 2 0 2 0 0 0 1 1 1 1 1 1 0 0 0 0 2 2 2 1 1 1 2 2 2 2 2 2 1 1 0 0 0 0 0 0 0 2 2 2 2 1 1 1 2 2 2 2 1 1 1 0 0 0 0 0 2 1 1 1 
+| 0 0 0 0 0 2 0 0 0 0 1 1 1 1 1 1 0 0 0 0 2 2 2 1 1 1 2 2 2 2 2 2 1 1 0 0 0 0 0 0 0 2 2 2 2 1 1 1 2 2 2 2 1 1 1 0 0 0 0 0 2 1 1 1 
+| 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 0 0 0 0 2 2 2 1 1 1 2 2 2 2 2 2 1 1 0 0 0 0 0 0 0 2 2 2 2 1 1 1 2 2 2 2 1 1 1 0 0 0 0 2 2 1 1 1 
+| 0 0 0 0 0 0 2 0 2 1 1 1 1 1 1 1 2 2 0 2 2 2 2 1 1 1 2 2 2 2 2 2 1 1 0 0 0 0 0 0 0 2 2 2 2 1 1 1 2 2 2 2 1 1 1 0 0 0 0 2 2 1 1 1 
+| 0 0 0 0 0 0 0 2 0 1 1 1 1 1 1 1 2 2 2 2 2 2 2 1 1 1 1 2 2 2 2 2 1 1 0 0 0 0 0 0 0 2 2 2 2 1 1 1 2 2 2 2 1 1 1 0 0 0 0 2 2 1 1 1 
+| 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 2 2 2 2 2 2 2 1 1 1 1 2 2 2 2 2 1 1 0 0 0 0 0 0 0 2 2 2 2 1 1 1 2 2 2 2 1 1 1 0 0 0 0 2 2 1 1 1 
+| 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 2 2 2 2 2 2 2 1 1 1 1 2 2 2 2 2 1 1 0 0 0 0 0 0 0 2 2 2 2 1 1 1 2 2 2 2 1 1 1 0 0 0 0 2 2 1 1 1 
+| 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 2 2 2 2 2 2 2 1 1 1 1 2 2 2 2 2 1 1 0 0 0 0 0 0 0 2 2 2 2 1 1 1 2 2 2 2 1 1 1 0 0 0 0 2 2 1 1 1 
+| 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 2 2 2 2 2 2 2 1 1 1 1 2 2 2 2 2 1 1 0 0 0 0 0 0 0 2 2 2 2 1 1 1 2 2 2 2 1 1 0 0 0 0 0 0 2 1 1 0 
+| 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 2 2 2 2 2 2 2 1 1 1 1 2 2 2 2 2 1 1 0 0 0 0 0 0 0 2 2 2 2 1 1 1 2 2 2 2 1 1 0 0 0 0 0 0 0 1 1 0 
+| 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 2 2 2 2 2 2 2 1 1 1 1 2 2 2 2 2 1 1 0 0 0 0 0 0 0 2 2 2 2 1 1 1 2 2 2 2 1 1 0 0 0 0 0 0 0 1 1 0 
+| 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 2 2 2 2 2 2 2 1 1 1 1 2 2 2 2 2 1 1 0 0 0 0 0 0 0 2 2 2 2 2 1 1 2 2 2 2 1 1 0 0 0 0 0 0 0 1 1 0 
+| 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 2 2 2 2 2 2 2 1 1 1 1 2 2 2 2 2 1 1 0 0 0 0 0 0 0 2 2 2 2 2 1 1 2 2 2 2 1 1 0 0 0 0 0 0 0 1 1 0 
+| 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 2 2 2 2 2 2 2 1 1 1 1 2 2 2 2 2 1 1 0 0 0 0 0 0 0 2 2 2 2 2 1 1 2 2 2 2 1 1 0 0 0 0 0 0 0 1 1 0 
+| 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 2 2 2 2 2 2 2 1 1 1 1 2 2 2 2 2 1 1 0 0 0 0 0 0 0 2 2 2 2 2 1 1 2 2 2 2 1 1 0 0 0 0 0 0 0 1 1 0 
+| 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 2 2 2 2 2 2 2 1 1 1 1 2 2 2 2 2 1 1 0 0 0 0 0 0 0 2 2 2 2 2 1 1 2 2 2 2 1 1 0 0 0 0 0 0 0 1 1 0 
+| 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 2 2 2 2 2 2 2 1 1 1 1 2 2 2 2 2 1 1 0 0 0 0 0 0 0 2 2 2 2 2 1 1 2 2 2 2 1 1 0 0 0 0 0 0 0 1 1 0 
+| 0 0 0 0 0 0 0 0 0 1 1 2 2 1 1 1 2 2 2 2 2 2 2 1 1 1 1 2 2 2 2 2 1 1 0 0 0 0 0 0 0 2 2 2 2 2 1 1 2 2 2 2 1 1 0 0 0 0 0 0 0 1 1 0 
+| 0 0 0 0 0 0 0 0 0 1 1 2 2 1 1 1 2 2 2 2 2 2 2 1 1 1 1 2 2 2 2 2 1 1 0 0 0 0 0 0 0 2 2 2 2 2 1 1 2 2 2 2 1 1 0 0 0 0 0 0 0 1 1 0 
+| 0 0 0 0 0 0 0 0 0 1 1 2 2 1 1 1 2 2 2 2 2 2 2 1 1 1 1 2 2 2 2 2 1 1 0 0 0 0 0 0 0 2 2 2 2 2 1 1 2 2 2 2 1 1 0 0 0 0 0 0 0 1 1 0 
+| 0 0 0 0 0 0 0 0 0 1 1 2 2 1 1 1 2 2 2 2 2 2 2 1 1 1 1 2 2 2 2 2 1 1 0 0 0 0 0 0 0 2 2 2 2 2 1 1 2 2 2 2 1 1 0 0 0 0 0 0 0 1 1 0 
+| 0 0 0 0 0 0 0 0 0 1 1 2 2 1 1 1 2 2 2 2 2 2 2 1 1 1 1 2 2 2 2 2 1 1 0 0 0 0 0 0 0 2 2 2 2 2 1 1 2 2 2 2 1 1 0 0 0 0 0 0 0 1 1 0 
+| 0 0 0 0 0 0 0 0 0 1 1 2 2 1 1 1 2 2 2 2 2 2 2 1 1 1 1 2 2 2 2 2 1 1 0 0 0 0 0 0 0 2 2 2 2 2 1 1 2 2 2 2 1 1 0 0 0 0 0 0 0 1 1 0 
+| 0 0 0 0 0 0 0 0 0 1 1 2 2 1 1 1 2 2 2 2 2 2 2 1 1 1 1 2 2 2 2 2 1 1 0 0 0 0 0 0 0 2 2 2 2 2 1 1 2 2 2 2 1 1 0 0 0 0 0 0 0 1 1 0 
+| 0 0 0 0 0 0 0 0 0 1 1 2 2 1 1 1 2 2 2 2 2 2 2 1 1 1 1 2 2 2 2 2 1 1 0 0 0 0 0 0 0 2 2 2 2 1 1 1 2 2 2 1 1 1 0 0 0 0 0 0 0 1 1 0 
+| 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 2 2 2 2 2 2 2 1 1 1 1 2 2 2 2 2 1 1 1 0 0 0 0 0 0 2 2 2 2 1 1 1 2 2 2 1 1 1 0 0 0 0 0 0 0 1 1 0 
+| 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 2 2 2 2 2 2 2 1 1 1 1 2 2 2 2 2 2 1 1 0 0 0 0 0 0 2 2 2 2 1 1 1 2 2 2 1 1 1 0 0 0 0 0 0 0 1 1 0 
+| 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 2 2 2 2 2 2 2 1 1 1 1 2 2 2 2 2 2 1 1 0 0 0 0 0 0 2 2 2 2 1 1 1 2 2 2 1 1 1 0 0 0 0 0 0 0 1 1 0 
+| 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 2 2 2 2 2 2 2 1 1 1 1 2 2 2 2 2 2 1 1 0 0 0 0 0 0 2 2 2 2 1 1 1 2 2 2 1 1 1 0 0 0 0 0 0 0 1 1 0 
+| 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 2 2 2 2 2 2 2 1 1 1 1 2 2 2 2 2 2 1 1 0 0 0 0 0 0 2 2 2 2 1 1 1 2 2 2 1 1 1 0 0 0 0 0 0 0 2 2 0 
+| 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 2 2 2 2 2 2 2 1 1 1 1 2 2 2 2 2 2 1 1 0 0 0 0 0 0 2 2 2 2 1 1 1 2 2 2 1 1 1 0 0 0 0 0 0 0 2 2 0 
+| 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 2 2 2 2 2 2 2 1 1 1 1 2 2 2 2 2 2 1 1 0 0 0 0 0 0 2 2 2 2 1 1 1 2 2 2 1 1 1 0 0 0 0 0 0 0 2 2 0 
+| 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 2 2 2 2 2 2 2 1 1 1 1 2 2 2 2 2 2 1 1 0 0 0 0 0 0 2 2 2 2 1 1 1 2 2 2 1 1 1 0 0 0 0 0 0 0 2 2 0 
+| 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 2 2 2 2 2 2 2 1 1 1 1 2 2 2 2 2 2 1 1 0 0 0 0 0 0 2 2 2 2 1 1 1 2 2 2 1 1 1 0 0 0 0 0 0 0 2 2 0 
+| 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 2 2 2 2 2 2 2 1 1 1 1 2 2 2 2 2 2 1 1 0 0 0 0 0 0 2 2 2 2 1 1 1 2 2 1 1 1 1 0 0 0 0 0 0 0 2 2 0 
+| 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 2 2 2 2 2 2 2 1 1 1 1 2 2 2 2 2 2 1 1 0 0 0 0 0 0 2 2 2 2 1 1 1 2 1 1 1 1 1 0 0 0 0 0 0 0 2 2 0 
+| 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 2 2 2 1 2 2 2 1 1 1 1 2 2 2 2 2 1 1 1 0 0 0 0 0 0 2 2 2 2 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 2 2 2 2 
+| 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 2 2 2 2 2 2 2 1 1 1 1 2 2 2 2 2 1 1 1 0 0 0 0 0 0 2 2 2 2 1 1 1 1 1 1 1 1 1 0 0 0 0 0 2 2 2 2 2 
+| 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 2 2 2 2 2 2 2 1 1 1 1 2 2 2 2 2 1 1 1 0 0 0 0 0 0 2 2 2 2 1 1 1 1 1 1 1 1 1 0 0 0 0 0 2 2 2 2 2 
+| 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 2 2 2 2 2 2 2 1 1 1 1 2 2 2 2 2 1 1 1 0 0 0 0 0 0 2 2 2 2 1 1 1 1 1 1 1 1 1 0 0 0 0 0 2 2 2 2 2 
+| 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 2 2 2 2 2 2 2 1 1 1 1 2 2 2 2 2 1 1 1 0 0 0 0 0 0 2 2 2 2 1 1 1 1 1 1 1 1 1 0 0 0 0 0 2 2 2 2 2 
+| 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 2 2 2 2 2 2 2 1 1 1 1 2 2 2 2 2 1 1 1 0 0 0 0 0 0 2 2 2 2 1 1 1 1 1 1 1 1 1 0 0 0 0 0 2 2 2 2 2 
+| 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 2 2 2 2 2 2 2 1 1 1 1 2 2 2 2 2 1 1 1 0 0 0 0 0 0 2 2 2 2 1 1 1 1 1 1 1 1 1 0 0 0 0 0 2 2 2 2 2 
+| 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 2 2 2 2 2 2 2 1 1 1 1 2 2 2 2 2 1 1 1 0 0 0 0 0 0 2 2 2 2 1 1 1 1 1 1 1 1 1 0 0 0 0 0 2 2 2 2 2 
+| 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 2 2 2 2 2 2 2 1 1 1 1 2 2 2 2 2 1 1 0 0 0 0 0 0 0 2 2 2 2 1 1 1 1 1 1 1 1 0 0 0 0 0 0 2 2 2 2 2 
+| 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 2 2 2 2 2 2 2 1 1 1 1 2 2 2 2 2 1 1 0 0 0 0 0 0 0 2 2 2 2 1 1 1 1 1 1 1 1 0 0 0 0 0 0 2 2 2 2 2 
+| 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 2 2 2 2 2 2 2 1 1 1 1 2 2 2 2 2 1 1 0 0 0 0 0 0 0 2 2 2 2 1 1 1 1 1 1 1 1 0 0 0 0 0 0 2 2 2 2 2 
+| 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 2 2 2 2 2 2 2 1 1 1 1 2 2 2 2 2 1 1 0 0 0 0 0 0 0 2 2 2 2 1 1 1 1 1 1 1 1 0 0 0 0 0 0 2 2 2 2 2 
+| 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 2 2 2 2 2 2 2 1 1 1 1 2 2 2 2 2 1 1 0 0 0 0 0 0 0 2 2 2 2 1 1 1 1 1 1 1 1 0 0 0 0 0 0 2 2 2 2 2 
+| 0 0 0 0 0 0 2 1 0 0 0 0 0 1 1 1 2 2 2 2 2 2 2 1 1 1 1 2 2 2 2 2 1 0 0 0 0 0 0 0 0 2 2 2 2 1 1 1 1 1 1 1 1 0 2 2 2 1 2 2 2 2 2 2 
+| 0 0 0 0 0 0 1 1 1 1 0 0 0 0 1 1 2 2 2 2 2 2 2 1 0 1 1 2 2 2 2 2 2 0 0 0 0 0 0 0 2 2 2 2 2 1 1 1 1 1 1 1 1 1 2 2 2 0 0 0 0 2 2 2 
+| 0 1 1 0 0 0 1 1 1 1 0 0 0 0 0 1 2 2 2 2 2 2 2 0 1 1 1 2 2 2 2 2 2 0 0 0 0 0 0 0 2 2 2 2 2 1 1 1 1 1 1 0 1 2 2 2 2 0 0 0 0 2 2 2 
+| 1 1 1 0 0 0 1 1 1 1 0 0 0 0 0 0 1 0 2 2 2 2 2 0 1 1 1 2 2 2 2 2 2 0 0 0 0 0 0 0 2 2 2 2 2 1 1 1 1 1 1 1 0 2 2 2 2 0 0 0 0 2 2 2 
+| 1 1 1 0 0 0 1 1 1 1 0 0 0 0 0 0 0 0 2 2 2 2 2 0 1 1 1 2 2 2 2 2 2 0 0 0 0 0 0 0 2 2 2 2 2 1 1 1 1 1 1 1 0 2 2 2 2 0 0 0 0 2 2 2 
+| 1 1 1 0 0 0 1 1 1 1 0 0 0 0 0 0 0 0 2 2 2 2 2 0 1 1 1 2 2 2 2 2 2 0 0 0 0 0 0 0 2 2 2 2 2 1 1 1 1 1 1 1 1 2 2 2 2 0 0 0 0 2 2 2 
+| 1 1 1 0 0 0 1 1 1 1 0 0 0 0 0 0 0 0 2 2 2 2 2 1 1 1 1 2 2 2 2 2 2 0 0 0 0 0 0 0 2 2 2 2 2 1 1 1 1 1 1 1 1 2 2 2 2 0 0 0 0 2 2 2 
+| 1 1 1 0 0 0 1 1 1 1 0 0 0 0 0 0 0 0 2 2 2 2 2 1 1 1 1 2 2 2 2 2 2 0 0 0 0 0 0 0 2 2 2 2 2 1 1 1 1 1 1 1 1 2 2 2 2 0 0 0 0 2 2 2 
+| 1 1 1 0 0 0 1 1 1 1 0 0 0 0 0 0 0 0 2 2 2 2 2 1 1 1 1 2 2 2 2 2 2 0 0 0 0 0 0 0 2 2 2 2 2 1 1 1 1 1 1 1 1 1 2 2 2 0 0 0 0 2 2 2 
+| 1 1 1 0 0 0 1 1 1 1 0 0 0 0 0 0 0 0 2 2 2 2 2 1 1 1 1 2 2 2 2 2 2 0 0 0 0 0 0 0 2 2 2 2 2 1 1 1 1 1 1 1 1 1 2 2 2 0 0 0 0 2 2 2 
+| 1 1 1 0 0 0 1 1 1 1 0 0 0 0 0 0 0 0 2 2 2 2 2 1 1 1 1 2 2 2 2 2 2 0 0 0 0 0 0 0 2 2 2 2 2 1 1 1 1 1 1 1 1 1 2 2 2 0 0 0 0 2 2 2 
+| 1 1 1 0 0 0 1 1 1 1 0 0 0 0 0 0 0 0 2 2 2 2 2 1 1 1 1 2 2 2 2 2 2 0 0 0 0 0 0 0 2 2 2 2 2 1 1 1 1 1 1 1 1 1 2 2 2 0 0 0 0 2 2 2 
+| 1 1 1 0 0 0 1 1 1 1 0 0 0 0 0 0 0 0 2 2 2 2 1 1 1 1 1 1 1 2 2 2 2 0 0 0 0 0 0 0 0 0 0 2 2 1 1 1 1 1 1 1 1 1 2 2 0 0 0 0 0 2 2 2 
+
+
+B=2
+| 2 0 2 0 2 0 0 0 2 2 2 0 0 0 0 2 0 2 1 1 1 1 1 1 1 1 2 0 2 0 2 0 2 1 1 1 1 0 2 0 2 0 2 0 2 0 1 2 1 1 1 1 1 0 0 0 2 0 2 0 2 0 2 0 
+| 0 2 0 2 0 0 0 0 2 2 2 0 0 0 0 0 2 2 1 1 1 1 1 1 1 1 2 2 0 2 0 2 0 1 1 1 1 0 0 2 0 2 0 2 0 1 1 1 1 1 1 1 1 0 0 0 0 2 0 2 0 2 0 2 
+| 2 0 2 0 0 0 0 0 2 2 2 0 0 0 0 0 2 2 1 1 1 1 1 1 1 1 2 2 2 0 2 0 1 1 1 1 1 0 0 0 2 0 2 0 1 1 1 1 1 1 1 1 1 0 0 0 0 0 2 0 2 0 2 0 
+| 0 2 2 0 0 0 0 0 2 2 2 0 0 0 0 0 2 2 1 1 1 1 1 1 1 1 2 2 2 2 0 2 1 1 1 1 1 0 0 0 0 2 0 2 1 1 1 1 1 1 1 1 1 0 0 0 0 0 2 2 0 2 0 2 
+| 2 2 2 0 0 0 0 0 2 2 2 0 0 0 0 0 2 2 1 1 1 1 1 1 1 1 2 2 2 2 2 2 1 1 1 1 1 0 0 0 0 0 2 2 1 1 1 1 1 1 1 1 1 0 0 0 0 0 2 2 2 0 2 0 
+| 2 2 2 0 0 0 0 0 2 2 2 0 0 0 0 0 2 2 1 1 1 1 1 1 1 1 2 2 2 2 2 2 1 1 1 1 1 0 0 0 0 0 2 2 1 1 1 1 1 1 1 1 1 0 0 0 0 0 2 2 2 2 0 2 
+| 2 2 2 0 0 0 0 0 2 2 2 0 0 0 0 0 2 2 1 1 1 1 1 1 1 1 2 2 2 2 2 2 1 1 1 1 1 0 0 0 0 0 2 2 1 1 1 1 1 1 1 1 1 0 0 0 0 0 2 2 2 2 2 2 
+| 2 2 2 0 0 0 0 0 2 2 2 0 0 0 0 0 2 2 1 1 1 1 1 1 1 1 2 2 2 2 2 2 1 1 1 1 1 0 0 0 0 0 2 2 1 1 1 1 1 1 1 1 1 0 0 0 0 0 2 2 2 2 2 2 
+| 2 2 2 0 0 0 0 0 2 2 2 0 0 0 0 0 2 2 1 1 1 1 1 1 1 1 2 2 2 2 2 2 1 1 1 1 1 0 0 0 0 0 2 2 1 1 1 1 1 1 1 1 1 0 0 0 0 0 2 2 2 2 2 2 
+| 2 2 2 0 0 0 0 0 2 2 2 0 0 0 0 0 2 2 1 1 1 1 1 1 1 1 2 2 2 2 2 2 1 1 1 1 1 0 0 0 0 0 2 2 1 1 1 1 1 1 1 1 1 0 0 0 0 0 2 2 2 2 2 2 
+| 2 2 2 0 0 0 0 0 2 2 2 0 0 0 0 0 2 2 1 1 1 1 1 1 1 1 2 2 2 2 2 2 1 1 1 1 1 0 0 0 0 0 2 2 1 1 1 1 1 1 1 1 1 0 0 0 0 0 2 2 2 2 2 2 
+| 2 2 2 0 0 0 0 0 2 2 2 0 0 0 0 0 2 2 1 1 1 1 1 1 1 1 2 2 2 2 2 2 1 1 1 1 1 0 0 0 0 0 2 2 1 1 1 1 1 1 1 1 1 0 0 0 0 0 2 2 2 2 2 2 
+| 2 2 2 0 0 0 0 0 2 2 2 0 0 0 0 0 2 2 1 1 1 1 1 1 1 1 2 2 2 2 2 2 1 1 1 1 1 0 0 0 0 0 2 2 1 1 1 1 1 1 1 1 1 0 0 0 0 0 2 2 2 2 2 2 
+| 2 2 2 0 0 0 0 0 0 2 2 0 0 0 0 0 2 2 1 1 1 1 1 1 1 1 2 2 2 2 2 2 1 1 1 1 1 0 0 0 0 0 2 2 1 1 1 1 1 1 1 1 1 0 0 0 0 0 2 2 2 2 2 2 
+| 2 2 2 0 0 0 0 0 0 2 2 0 0 0 0 0 2 2 1 1 1 1 1 1 1 1 2 2 2 2 2 2 1 1 1 1 1 0 0 0 0 0 2 2 1 1 1 1 1 1 1 1 1 0 0 0 0 0 2 2 2 2 2 2 
+| 2 2 2 0 0 0 0 0 0 2 2 0 0 0 0 0 2 2 1 1 1 1 1 1 1 1 2 2 2 2 2 2 1 1 1 1 1 0 0 0 0 0 2 2 1 1 1 1 1 1 1 1 1 0 0 0 0 0 2 2 2 2 2 2 
+| 2 2 2 0 0 0 0 0 0 2 2 0 0 0 0 0 2 2 1 1 1 1 1 1 1 1 2 2 2 2 2 2 1 1 1 1 1 0 0 0 0 0 2 2 1 1 1 1 1 1 1 1 1 0 0 0 0 0 2 2 2 2 2 2 
+| 2 2 2 0 0 0 0 0 0 2 2 0 0 0 0 0 2 2 1 1 1 1 1 1 1 1 2 2 2 2 2 2 1 1 1 1 1 0 0 0 0 0 2 2 1 1 1 1 1 1 1 1 1 0 0 0 0 0 2 2 2 2 2 2 
+| 2 2 2 0 0 0 0 0 0 2 2 0 0 0 0 0 2 2 1 1 1 1 1 1 1 1 2 2 2 2 2 2 1 1 1 1 1 0 0 0 0 0 2 2 1 1 1 1 1 1 1 1 1 0 0 0 0 0 2 2 2 2 2 2 
+| 2 2 2 0 0 0 0 0 0 2 2 0 0 0 0 0 2 2 1 1 1 1 1 1 1 1 2 2 2 2 2 2 1 1 1 1 1 0 0 0 0 0 2 2 1 1 1 1 1 1 1 1 1 0 0 0 0 0 2 2 2 2 2 2 
+| 2 2 2 0 0 0 0 0 0 2 0 0 0 0 0 0 2 2 1 1 1 1 1 1 1 1 2 2 2 2 2 2 1 1 1 1 1 0 0 0 0 0 2 2 1 1 1 1 1 1 1 1 1 0 0 0 0 0 2 2 2 2 2 2 
+| 2 2 2 0 0 0 0 0 0 0 0 0 0 0 0 0 2 2 1 1 1 1 1 1 1 1 2 2 2 2 2 2 1 1 1 1 1 0 0 0 0 0 2 2 1 1 1 1 1 1 1 1 1 0 0 0 0 0 2 2 2 2 2 2 
+| 2 2 2 0 0 0 0 0 0 0 0 0 0 0 0 0 2 2 1 1 1 1 1 1 1 1 2 2 2 2 2 2 1 1 1 1 1 0 0 0 0 0 2 2 1 1 1 1 1 1 1 1 1 0 0 0 0 0 2 2 2 2 2 2 
+| 2 2 2 0 0 0 0 0 0 0 0 0 0 0 0 0 2 2 1 1 1 1 1 1 1 1 2 2 2 2 2 2 1 1 1 1 1 0 0 0 0 0 2 2 1 1 1 1 1 1 1 1 1 0 0 0 0 0 2 2 2 2 2 2 
+| 2 2 2 0 0 0 0 0 0 0 0 0 0 0 0 0 2 2 1 1 1 1 1 1 1 1 2 2 2 2 2 2 1 1 1 1 1 0 0 0 0 0 2 2 1 1 1 1 1 1 1 1 1 0 0 0 0 0 2 2 2 2 2 2 
+| 2 2 2 0 0 0 0 0 0 0 0 0 0 0 0 0 2 2 1 1 1 1 1 1 1 1 2 2 2 2 2 2 1 1 1 1 1 0 0 0 0 0 2 2 1 1 1 1 1 1 1 1 1 0 0 0 0 0 2 2 2 2 2 2 
+| 2 2 2 0 0 0 0 0 0 0 0 0 0 0 0 0 2 2 1 1 1 1 1 1 1 1 2 2 2 2 2 2 1 1 1 1 1 0 0 0 0 0 2 2 1 1 1 1 1 1 1 1 1 0 0 0 0 0 2 2 2 2 2 2 
+| 2 2 2 0 0 0 0 0 0 0 0 0 0 0 0 0 2 2 1 1 1 1 1 1 1 1 2 2 2 2 2 2 1 1 1 1 1 0 0 0 0 0 2 2 1 1 1 1 1 1 1 1 1 0 0 0 0 0 2 2 2 2 2 2 
+| 2 2 2 0 0 0 0 0 0 0 0 0 0 0 0 0 2 2 1 1 1 1 1 1 1 1 2 2 2 2 2 2 1 1 1 1 1 0 0 0 0 0 2 2 1 1 1 1 1 1 1 1 1 0 0 0 0 0 2 2 2 2 2 2 
+| 2 2 2 0 0 0 0 0 0 0 0 0 0 0 0 0 2 2 1 1 1 1 1 1 1 1 2 2 2 2 2 2 1 1 1 1 1 0 0 0 0 0 2 2 1 1 1 1 1 1 1 1 1 0 0 0 0 0 2 2 2 2 2 2 
+| 2 2 2 0 0 0 0 0 0 0 0 0 0 0 0 0 2 2 1 1 1 1 1 1 1 1 2 2 2 2 2 2 1 1 1 1 1 0 0 0 0 0 2 2 1 1 1 1 1 1 1 1 1 0 0 0 0 0 2 2 2 2 2 2 
+| 2 2 2 0 0 0 0 0 0 0 0 0 0 0 0 0 2 2 1 1 1 1 1 1 1 1 2 2 2 2 2 2 1 1 1 1 1 0 0 0 0 0 2 2 1 1 1 1 1 1 1 1 1 0 0 0 0 0 2 2 2 2 2 2 
+| 2 2 2 0 0 0 0 0 0 0 0 0 0 0 0 0 2 2 1 1 1 1 1 1 1 1 2 2 2 2 2 2 1 1 1 1 1 0 0 0 0 0 2 2 1 1 1 1 1 1 1 1 1 0 0 0 0 0 2 2 2 2 2 2 
+| 2 2 2 0 0 0 0 0 0 0 0 0 0 0 0 0 2 2 1 1 1 1 1 1 1 1 2 2 2 2 2 2 1 1 1 1 1 0 0 0 0 0 2 2 1 1 1 1 1 1 1 1 1 0 0 0 0 0 2 2 2 2 2 2 
+| 2 2 2 0 0 0 0 0 0 0 0 0 0 0 0 0 2 2 1 1 1 1 1 1 1 1 2 2 2 2 2 2 1 1 1 1 1 0 0 0 0 0 2 2 1 1 1 1 1 1 1 1 1 0 0 0 0 0 2 2 2 2 2 2 
+| 2 2 2 0 0 0 0 0 0 0 0 0 0 0 0 0 2 2 1 1 1 1 1 1 1 1 2 2 2 2 2 2 1 1 1 1 1 0 0 0 0 0 2 2 1 1 1 1 1 1 1 1 1 0 0 0 0 0 2 2 2 2 2 2 
+| 2 2 2 0 0 0 0 0 0 0 0 0 0 0 0 0 2 2 1 1 1 1 1 1 1 1 2 2 2 2 2 2 1 1 1 1 1 0 0 0 0 0 2 2 1 1 1 1 1 1 1 1 1 0 0 0 0 0 2 2 2 2 2 2 
+| 2 2 2 0 0 0 0 0 0 0 0 0 0 0 0 0 2 2 1 1 1 1 1 1 1 1 2 2 2 2 2 2 1 1 1 1 1 0 0 0 0 0 2 2 1 1 1 1 1 1 1 1 1 0 0 0 0 0 2 2 2 2 2 2 
+| 2 2 2 0 0 0 0 0 0 0 0 0 0 0 0 0 2 2 1 1 1 1 1 1 1 1 2 2 2 2 2 2 1 1 1 1 1 0 0 0 0 0 2 2 1 1 1 1 1 1 1 1 1 0 0 0 0 0 2 2 2 2 2 2 
+| 2 2 2 0 0 0 0 0 0 0 0 0 0 0 0 0 2 2 1 1 1 1 1 1 1 1 2 2 2 2 2 2 1 1 1 1 1 0 0 0 0 0 2 2 1 1 1 1 1 1 1 1 1 0 0 0 0 0 2 2 2 2 2 2 
+| 2 2 2 0 0 0 0 0 0 0 0 0 0 0 0 0 2 2 1 1 1 1 1 1 1 1 2 2 2 2 2 2 1 1 1 1 1 0 0 0 0 0 2 2 1 1 1 1 1 1 1 1 1 0 0 0 0 0 2 2 2 2 2 2 
+| 2 2 2 0 0 0 0 0 0 0 0 0 0 0 0 0 2 2 2 2 1 1 1 1 1 1 2 2 2 2 2 2 1 1 1 1 1 0 0 0 0 0 2 2 1 1 1 1 1 1 1 1 1 0 0 0 0 0 2 2 2 2 2 2 
+| 2 2 2 0 0 0 0 0 0 0 0 0 0 0 0 0 2 2 2 2 1 1 1 1 1 1 2 2 2 2 2 2 1 1 1 1 1 0 0 0 0 0 2 2 1 1 1 1 1 1 1 1 1 0 0 0 0 0 2 2 2 2 2 2 
+| 2 2 2 0 0 0 0 0 0 0 0 0 0 0 0 0 2 2 2 2 1 1 1 1 1 1 2 2 2 2 2 2 1 1 1 1 1 0 0 0 0 0 2 2 1 1 1 1 1 1 1 1 1 0 0 0 0 0 2 2 2 2 2 2 
+| 2 2 2 0 0 0 0 0 0 0 0 0 0 0 0 0 2 2 2 2 1 1 1 1 1 1 2 2 2 2 2 2 1 1 1 1 1 0 0 0 0 0 2 2 1 1 1 1 1 1 1 1 1 0 0 0 0 0 2 2 2 2 2 2 
+| 2 2 2 0 0 0 0 0 0 0 0 0 0 0 0 0 2 2 2 2 1 1 1 1 1 1 2 2 2 2 2 2 1 1 1 1 1 0 0 0 0 0 2 2 1 1 1 1 1 1 1 1 1 0 0 0 0 0 2 2 2 2 2 2 
+| 2 2 2 0 0 0 0 0 0 0 0 0 0 0 0 0 2 2 2 2 1 1 1 1 1 1 2 2 2 2 2 2 1 1 1 1 1 0 0 0 0 0 2 2 1 1 1 1 1 1 1 1 1 0 0 0 0 0 2 2 2 2 2 2 
+| 2 2 2 0 0 0 0 0 0 0 0 0 0 0 0 0 2 2 2 2 1 1 1 1 1 1 2 2 2 2 2 2 1 1 1 1 1 0 0 0 0 0 2 2 1 1 1 1 1 1 1 1 1 0 0 0 0 0 2 2 2 2 2 2 
+| 2 2 2 0 0 0 0 0 0 0 0 0 0 0 0 0 2 2 2 2 1 1 1 1 1 1 2 2 2 2 2 2 1 1 1 1 1 0 0 0 0 0 2 2 1 1 1 1 1 1 1 1 1 0 0 0 0 0 2 2 2 2 2 2 
+| 2 2 2 0 0 0 0 0 0 0 0 0 0 0 0 0 2 2 2 2 1 1 1 1 1 1 2 2 2 2 2 2 1 1 1 1 1 0 0 0 0 0 2 2 1 1 1 1 1 1 1 1 1 0 0 0 0 0 2 2 2 2 2 2 
+| 2 2 2 0 0 0 0 0 0 0 0 0 0 0 0 0 2 2 2 2 1 1 1 1 1 1 2 2 2 2 2 2 1 1 1 1 1 0 0 0 0 0 2 2 1 1 1 1 1 1 1 1 1 0 0 0 0 0 2 2 2 2 2 2 
+| 2 2 2 0 0 0 0 0 0 0 0 0 0 0 0 0 2 2 2 2 1 1 1 1 1 1 2 2 2 2 2 2 1 1 1 1 1 0 0 0 0 0 2 2 1 1 1 1 1 1 1 1 1 0 0 0 0 0 2 2 2 2 2 2 
+| 2 2 2 0 0 0 0 0 0 0 0 0 0 0 0 0 2 2 2 2 1 1 1 1 1 1 2 2 2 2 2 2 1 1 1 1 1 0 0 0 0 0 2 2 1 1 1 1 1 1 1 1 1 0 0 0 0 2 2 2 2 2 2 2 
+| 2 2 2 0 0 0 0 0 0 0 0 0 0 0 0 0 2 2 2 2 1 1 1 1 1 1 2 2 2 2 2 2 1 1 1 1 1 0 0 0 0 0 2 2 1 1 1 1 1 1 1 1 1 0 0 0 0 2 2 2 2 2 2 2 
+| 2 2 2 0 0 0 0 0 0 0 0 0 0 0 0 0 2 2 2 2 1 1 1 1 1 1 2 2 2 2 2 2 1 1 1 1 1 0 0 0 0 0 2 2 1 1 1 1 1 1 1 1 1 0 0 0 0 2 2 2 2 2 2 2 
+| 2 2 2 0 0 0 0 0 0 0 0 0 0 0 0 0 2 2 2 2 1 1 1 1 1 1 2 2 2 2 2 2 1 1 1 1 1 0 0 0 0 0 2 2 1 1 1 1 1 1 1 1 1 0 0 0 0 2 2 2 2 2 2 2 
+| 2 2 2 0 0 0 0 0 0 0 0 0 0 0 0 0 2 2 2 2 1 1 1 1 1 1 2 2 2 2 2 2 1 1 1 1 1 0 0 0 0 0 2 2 1 1 1 1 1 1 1 1 1 0 0 0 0 2 2 2 2 2 2 2 
+| 2 2 2 0 0 0 0 0 0 0 0 0 0 0 0 0 2 2 2 2 1 1 1 1 1 1 2 2 2 2 2 2 1 1 1 1 1 0 0 0 0 0 2 2 1 1 1 1 1 1 1 1 1 0 0 0 0 2 2 2 2 2 2 2 
+| 2 2 2 0 0 0 0 0 0 0 0 0 0 0 0 0 2 2 2 2 1 1 1 1 1 1 2 2 2 2 2 2 1 1 1 1 1 0 0 0 0 0 2 2 1 1 1 1 1 1 1 1 1 0 0 0 0 2 2 2 2 2 2 2 
+| 2 2 2 0 0 0 0 0 0 0 0 0 0 0 0 0 2 2 2 2 1 1 1 1 1 1 2 2 2 2 2 2 1 1 1 1 1 0 0 0 0 0 2 2 1 1 1 1 1 1 1 1 1 0 0 0 0 2 2 2 2 2 2 2 
+| 2 2 2 0 0 0 0 0 0 0 0 0 0 0 0 0 2 2 2 2 1 1 1 1 1 1 2 2 2 2 2 2 1 1 1 1 1 0 0 0 0 0 2 2 1 1 1 1 1 1 1 1 1 0 0 0 0 2 2 2 2 2 2 2 
+| 2 2 2 0 0 0 0 0 0 0 0 0 0 0 0 0 2 2 2 2 1 1 1 1 1 1 2 2 2 2 2 2 1 1 1 1 1 0 0 0 0 0 2 2 1 1 1 1 1 1 1 1 1 0 0 0 0 2 2 2 2 2 2 2 
+| 2 2 2 0 0 0 0 0 0 0 0 0 0 0 0 0 2 2 2 2 1 1 1 1 1 1 2 2 2 2 2 2 1 1 1 1 1 0 0 0 0 0 2 2 1 1 1 1 1 1 1 1 1 0 0 0 0 2 2 2 2 2 2 2 
+| 2 2 2 0 0 0 0 0 0 0 0 0 0 0 0 0 2 2 2 2 1 1 1 1 1 1 2 2 2 2 2 2 1 1 1 1 1 0 0 0 0 0 2 2 1 1 1 1 1 1 1 1 1 0 0 0 0 2 2 2 2 2 2 2 
+
+B=3
+| 0 0 2 0 2 0 0 0 2 2 0 0 0 2 0 2 0 2 0 2 0 2 0 2 0 2 1 1 1 1 1 1 1 1 1 0 0 0 0 2 2 2 2 0 2 0 2 0 1 0 1 2 1 1 1 1 1 2 1 2 0 2 0 0 
+| 0 0 0 2 0 0 0 0 2 2 0 0 0 0 2 0 2 0 2 0 2 0 2 0 2 2 1 1 1 1 1 1 1 1 1 0 0 0 0 2 2 2 2 2 0 2 0 1 0 1 1 1 1 1 1 1 1 1 2 1 2 0 0 0 
+| 0 0 0 0 0 0 0 0 2 2 0 0 0 0 0 2 0 2 0 2 0 2 0 2 2 2 1 1 1 1 1 1 1 1 1 0 0 0 0 2 2 2 2 2 2 0 1 0 1 1 1 1 1 1 1 1 1 1 1 2 2 0 0 0 
+| 0 0 0 0 0 0 0 0 2 2 0 0 0 0 0 0 2 0 2 0 2 0 2 2 2 2 1 1 1 1 1 1 1 1 1 0 0 0 0 2 2 2 2 2 2 2 0 1 1 1 1 1 1 1 1 1 1 1 1 2 2 0 0 0 
+| 0 0 0 0 0 0 0 0 2 2 0 0 0 0 0 0 0 2 0 2 0 2 2 2 2 2 1 1 1 1 1 1 1 1 1 0 0 0 0 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1 1 1 2 2 0 0 0 
+| 0 0 0 0 0 0 0 0 2 2 0 0 0 0 0 0 0 0 2 0 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 0 0 0 0 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1 1 1 2 2 0 0 0 
+| 0 0 0 0 0 0 0 0 2 2 0 0 0 0 0 0 0 0 0 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 0 0 0 0 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1 1 1 2 2 0 0 0 
+| 0 0 0 0 0 0 0 0 2 2 0 0 0 0 0 0 0 0 0 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 0 0 0 0 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1 1 1 2 2 0 0 0 
+| 0 0 0 0 0 0 0 0 2 2 0 0 0 0 0 0 0 0 0 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 0 0 0 0 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1 1 1 2 2 0 0 0 
+| 0 0 0 0 0 0 0 0 2 2 0 0 0 0 0 0 0 0 0 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 0 0 0 0 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1 1 1 2 2 0 0 0 
+| 0 0 0 0 0 0 0 0 2 2 0 0 0 0 0 0 0 0 0 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 0 0 0 0 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1 1 1 2 2 0 0 0 
+| 0 0 0 0 0 0 0 0 2 2 0 0 0 0 0 0 0 0 0 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 0 0 0 0 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1 1 1 2 2 0 0 0 
+| 0 0 0 0 0 0 0 0 2 2 0 0 0 0 0 0 0 0 0 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 0 0 0 0 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1 1 1 2 2 0 0 0 
+| 0 0 0 0 0 0 0 0 2 2 0 0 0 0 0 0 0 0 0 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 0 0 0 0 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1 1 1 2 2 0 0 0 
+| 0 0 0 0 0 0 0 0 2 2 0 0 0 0 0 0 0 0 0 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 0 0 0 0 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1 1 1 2 2 0 0 0 
+| 0 0 0 0 0 0 0 0 2 2 0 0 0 0 0 0 0 0 0 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 0 0 0 0 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1 1 1 2 2 0 0 0 
+| 0 0 0 0 0 0 0 0 2 2 0 0 0 0 0 0 0 0 0 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 0 0 0 0 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1 1 1 2 2 0 0 0 
+| 0 0 0 0 0 0 0 0 2 2 0 0 0 0 0 0 0 0 0 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 0 0 0 0 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1 1 1 2 2 0 0 0 
+| 0 0 0 0 0 0 0 0 2 2 0 0 0 0 0 0 0 0 0 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 0 0 0 0 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1 1 1 2 2 0 0 0 
+| 0 0 0 0 0 0 0 0 2 2 0 0 0 0 0 0 0 0 0 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 0 0 0 0 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1 1 1 2 2 0 0 0 
+| 0 0 0 0 0 0 0 0 2 2 0 0 0 0 0 0 0 0 0 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 0 0 0 0 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1 1 1 2 2 0 0 0 
+| 0 0 0 0 0 0 0 0 2 2 0 0 0 0 0 0 0 0 0 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 0 0 0 0 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1 1 1 2 2 0 0 0 
+| 0 0 0 0 0 0 0 0 2 2 0 0 0 0 0 0 0 0 0 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 0 0 0 0 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1 1 1 2 2 0 0 0 
+| 0 0 0 0 0 0 0 0 2 2 0 0 0 0 0 0 0 0 0 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 0 0 0 0 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1 1 1 2 2 0 0 0 
+| 0 0 0 0 0 0 0 0 2 2 0 0 0 0 0 0 0 0 0 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 0 0 0 0 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1 1 1 2 2 0 0 0 
+| 0 0 0 0 0 0 0 0 2 2 0 0 0 0 0 0 0 0 0 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 0 0 0 0 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1 1 1 2 2 0 0 0 
+| 0 0 0 0 0 0 0 0 2 2 0 0 0 0 0 0 0 0 0 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 0 0 0 0 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1 1 1 2 2 0 0 0 
+| 0 0 0 0 0 0 0 0 2 2 0 0 0 0 0 0 0 0 0 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 0 0 0 0 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1 1 1 2 2 0 0 0 
+| 0 0 0 0 0 0 0 0 2 2 0 0 0 0 0 0 0 0 0 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 0 0 0 0 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1 1 1 2 2 0 0 0 
+| 0 0 0 0 0 0 0 0 2 2 0 0 0 0 0 0 0 0 0 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 0 0 0 0 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1 1 1 2 2 0 0 0 
+| 0 0 0 0 0 0 0 0 2 2 0 0 0 0 0 0 0 0 0 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 0 0 0 0 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1 1 1 2 2 0 0 0 
+| 0 0 0 0 0 0 0 0 2 2 0 0 0 0 0 0 0 0 0 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 0 0 0 0 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1 1 1 2 2 0 0 0 
+| 0 0 0 0 0 0 0 0 2 2 0 0 0 0 0 0 0 0 0 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 0 0 0 0 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1 1 1 2 2 0 0 0 
+| 0 0 0 0 0 0 0 0 2 2 0 0 0 0 0 0 0 0 0 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 0 0 0 0 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1 1 1 2 2 0 0 0 
+| 0 0 0 0 0 0 0 0 2 2 0 0 0 0 0 0 0 0 0 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 0 0 0 0 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1 1 1 2 2 0 0 0 
+| 0 0 0 0 0 0 0 0 2 2 0 0 0 0 0 0 0 0 0 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 0 0 0 0 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1 1 1 2 2 0 0 0 
+| 0 0 0 0 0 0 0 0 2 2 0 0 0 0 0 0 0 0 0 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 0 0 0 0 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1 1 1 2 2 0 0 0 
+| 0 0 0 0 0 0 0 0 2 2 0 0 0 0 0 0 0 0 0 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 0 0 0 0 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1 1 1 2 2 0 0 0 
+| 0 0 0 0 0 0 0 0 2 2 0 0 0 0 0 0 0 0 0 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 0 0 0 0 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1 1 1 2 2 0 0 0 
+| 0 0 0 0 0 0 0 0 2 2 0 0 0 0 0 0 0 0 0 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 0 0 0 0 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1 1 1 2 2 0 0 0 
+| 0 0 0 0 0 0 0 0 2 2 0 0 0 0 0 0 0 0 0 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 0 0 0 0 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1 1 1 2 2 0 0 0 
+| 0 0 0 0 0 0 0 0 2 2 0 0 0 0 0 0 0 0 0 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 0 0 0 0 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1 1 1 2 2 0 0 0 
+| 0 0 0 0 0 0 0 0 2 2 0 0 0 0 0 0 0 0 0 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 0 0 0 0 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1 1 1 2 2 0 0 0 
+| 0 0 0 0 0 0 0 0 2 2 0 0 0 0 0 0 0 0 0 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 0 0 0 0 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1 1 1 2 2 0 0 0 
+| 0 0 0 0 0 0 0 0 2 2 0 0 0 0 0 0 0 0 0 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 0 0 0 0 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1 1 1 2 2 0 0 0 
+| 0 0 0 0 0 0 0 0 2 2 0 0 0 0 0 0 0 0 0 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 0 0 0 0 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1 1 1 2 2 0 0 0 
+| 0 0 0 0 0 0 0 0 2 2 0 0 0 0 0 0 0 0 0 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 0 0 0 0 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1 1 1 2 2 0 0 0 
+| 0 0 0 0 0 0 0 0 2 2 0 0 0 0 0 0 0 0 0 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 0 0 0 0 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1 1 1 2 2 0 0 0 
+| 0 0 0 0 0 0 0 0 2 2 0 0 0 0 0 0 0 0 0 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 0 0 0 0 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1 1 1 2 2 0 0 0 
+| 0 0 0 0 0 0 0 0 2 2 0 0 0 0 0 0 0 0 0 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 0 0 0 0 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1 1 1 2 2 0 0 0 
+| 0 0 0 0 0 0 0 0 2 2 0 0 0 0 0 0 0 0 0 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 0 0 0 0 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1 1 1 2 2 0 0 0 
+| 0 0 0 0 0 0 0 0 2 2 0 0 0 0 0 0 0 0 0 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 0 0 0 0 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1 1 1 2 2 0 0 0 
+| 0 0 0 0 0 0 0 0 2 2 0 0 0 0 0 0 0 0 0 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 0 0 0 0 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1 1 1 2 2 0 0 0 
+| 0 0 0 0 0 0 0 0 2 2 0 0 0 0 0 0 0 0 0 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 0 0 0 0 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1 1 1 2 2 0 0 0 
+| 0 0 0 0 0 0 0 0 2 2 0 0 0 0 0 0 0 0 0 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 0 0 0 0 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1 1 1 2 2 0 0 0 
+| 0 0 0 0 0 0 0 0 2 2 0 0 0 0 0 0 0 0 0 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 0 0 0 0 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1 1 1 2 2 0 0 0 
+| 0 0 0 0 0 0 0 0 2 2 0 0 0 0 0 0 0 0 0 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 0 0 0 0 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1 1 1 2 2 0 0 0 
+| 0 0 0 0 0 0 0 0 2 2 0 0 0 0 0 0 0 0 0 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 0 0 0 0 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1 1 1 2 2 0 0 0 
+| 0 0 0 0 0 0 0 0 2 2 0 0 0 0 0 0 0 0 0 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 0 0 0 0 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1 1 1 2 2 0 0 0 
+| 0 0 0 0 0 0 0 0 2 2 0 0 0 0 0 0 0 0 0 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 0 0 0 0 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1 1 1 2 2 0 0 0 
+| 0 0 0 0 0 0 0 0 2 2 0 0 0 0 0 0 0 0 0 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 0 0 0 0 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1 1 1 2 2 0 0 0 
+| 0 0 0 0 0 0 0 0 2 2 0 0 0 0 0 0 0 0 0 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 0 0 0 0 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1 1 1 2 2 0 0 0 
+| 0 0 0 0 0 0 0 0 2 2 0 0 0 0 0 0 0 0 0 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 0 0 0 0 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1 1 1 2 2 0 0 0 
+| 0 0 0 0 0 0 0 0 2 2 0 0 0 0 0 0 0 0 0 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 0 0 0 0 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1 1 1 2 2 0 0 0 
+
+
+B=4
+| 2 0 2 0 2 0 2 0 0 0 0 2 0 2 0 2 0 2 0 2 0 2 0 2 0 2 0 2 0 2 0 2 0 2 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 1 2 1 2 2 2 2 2 2 2 
+| 2 2 0 2 0 2 0 0 0 0 0 0 2 0 2 0 2 0 2 0 2 0 2 0 2 0 2 0 2 0 2 0 2 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 1 1 2 2 2 2 2 2 2 2 
+| 2 2 2 0 2 0 0 0 0 0 0 0 0 2 0 2 0 2 0 2 0 2 0 2 0 2 0 2 0 2 0 2 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 1 1 2 2 2 2 2 2 2 2 
+| 2 2 2 2 0 0 0 0 0 0 0 0 0 0 2 0 2 0 2 0 2 0 2 0 2 0 2 0 2 0 2 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 1 1 2 2 2 2 2 2 2 2 
+| 2 2 2 2 0 0 0 0 0 0 0 0 0 0 0 2 0 2 0 2 0 2 0 2 0 2 0 2 0 2 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 1 1 2 2 2 2 2 2 2 2 
+| 2 2 2 2 0 0 0 0 0 0 0 0 0 0 0 0 2 0 2 0 2 0 2 0 2 0 2 0 2 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 1 1 2 2 2 2 2 2 2 2 
+| 2 2 2 2 0 0 0 0 0 0 0 0 0 0 0 0 0 2 0 2 0 2 0 2 0 2 0 2 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 1 1 2 2 2 2 2 2 2 2 
+| 2 2 2 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 0 2 0 2 0 2 0 2 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 1 1 2 2 2 2 2 2 2 2 
+| 2 2 2 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 0 2 0 2 0 2 2 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 1 1 2 2 2 2 2 2 2 2 
+| 2 2 2 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 0 2 0 2 2 2 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 1 1 2 2 2 2 2 2 2 2 
+| 2 2 2 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 0 2 2 2 2 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 1 1 2 2 2 2 2 2 2 2 
+| 2 2 2 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 1 1 2 2 2 2 2 2 2 2 
+| 2 2 2 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 1 1 2 2 2 2 2 2 2 2 
+| 2 2 2 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 1 1 2 2 2 2 2 2 2 2 
+| 2 2 2 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 1 1 2 2 2 2 2 2 2 2 
+| 2 2 2 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 1 1 2 2 2 2 2 2 2 2 
+| 2 2 2 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 1 1 2 2 2 2 2 2 2 2 
+| 2 2 2 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 1 1 2 2 2 2 2 2 2 2 
+| 2 2 2 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 1 1 2 2 2 2 2 2 2 2 
+| 2 2 2 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 1 1 2 2 2 2 2 2 2 2 
+| 2 2 2 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 1 1 2 2 2 2 2 2 2 2 
+| 2 2 2 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 1 1 2 2 2 2 2 2 2 2 
+| 2 2 2 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 1 1 2 2 2 2 2 2 2 2 
+| 2 2 2 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 1 1 2 2 2 2 2 2 2 2 
+| 2 2 2 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 1 1 2 2 2 2 2 2 2 2 
+| 2 2 2 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 1 1 2 2 2 2 2 2 2 2 
+| 2 2 2 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 1 1 2 2 2 2 2 2 2 2 
+| 2 2 2 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 1 1 2 2 2 2 2 2 2 2 
+| 2 2 2 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 1 1 2 2 2 2 2 2 2 2 
+| 2 2 2 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 1 1 2 2 2 2 2 2 2 2 
+| 2 2 2 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 1 1 2 2 2 2 2 2 2 2 
+| 2 2 2 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 1 1 2 2 2 2 2 2 2 2 
+| 2 2 2 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 1 1 2 2 2 2 2 2 2 2 
+| 2 2 2 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 1 1 2 2 2 2 2 2 2 2 
+| 2 2 2 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 1 1 2 2 2 2 2 2 2 2 
+| 2 2 2 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 1 1 2 2 2 2 2 2 2 2 
+| 2 2 2 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 1 1 2 2 2 2 2 2 2 2 
+| 2 2 2 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 1 1 2 2 2 2 2 2 2 2 
+| 2 2 2 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 1 1 2 2 2 2 2 2 2 2 
+| 2 2 2 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 1 1 2 2 2 2 2 2 2 2 
+| 2 2 2 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 1 1 2 2 2 2 2 2 2 2 
+| 2 2 2 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 1 1 2 2 2 2 2 2 2 2 
+| 2 2 2 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 1 1 2 2 2 2 2 2 2 2 
+| 2 2 2 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 1 1 2 2 2 2 2 2 2 2 
+| 2 2 2 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 1 1 2 2 2 2 2 2 2 2 
+| 2 2 2 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 1 1 2 2 2 2 2 2 2 2 
+| 2 2 2 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 1 1 2 2 2 2 2 2 2 2 
+| 2 2 2 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 1 1 2 2 2 2 2 2 2 2 
+| 2 2 2 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 1 1 2 2 2 2 2 2 2 2 
+| 2 2 2 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 1 1 2 2 2 2 2 2 2 2 
+| 2 2 2 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 1 1 2 2 2 2 2 2 2 2 
+| 2 2 2 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 1 1 2 2 2 2 2 2 2 2 
+| 2 2 2 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 1 1 2 2 2 2 2 2 2 2 
+| 2 2 2 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 1 1 2 2 2 2 2 2 2 2 
+| 2 2 2 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 1 1 2 2 2 2 2 2 2 2 
+| 2 2 2 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 1 1 2 2 2 2 2 2 2 2 
+| 2 2 2 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 1 1 2 2 2 2 2 2 2 2 
+| 2 2 2 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 1 1 2 2 2 2 2 2 2 2 
+| 2 2 2 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 1 1 2 2 2 2 2 2 2 2 
+| 2 2 2 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 1 1 2 2 2 2 2 2 2 2 
+| 2 2 2 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 1 1 2 2 2 2 2 2 2 2 
+| 2 2 2 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 1 1 2 2 2 2 2 2 2 2 
+| 2 2 2 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 1 1 2 2 2 2 2 2 2 2 
+| 2 2 2 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 1 1 2 2 2 2 2 2 2 2 
+
+B=6
+| 0 0 0 0 0 2 0 2 0 2 0 2 0 2 0 2 0 2 0 2 0 2 0 2 0 2 0 2 0 2 0 2 0 2 0 2 0 2 0 0 0 0 2 0 2 0 2 0 2 0 1 0 1 1 1 1 1 1 1 1 1 1 1 0 
+| 0 0 0 0 0 0 2 0 2 0 2 0 2 0 2 0 2 0 2 0 2 0 2 0 2 0 2 0 2 0 2 0 2 0 2 0 2 0 0 0 0 0 0 2 0 2 0 2 0 1 0 1 1 1 1 1 1 1 1 1 1 1 1 0 
+| 0 0 0 0 0 0 0 2 0 2 0 2 0 2 0 2 0 2 0 2 0 2 0 2 0 2 0 2 0 2 0 2 0 2 0 2 0 0 0 0 0 0 0 0 2 0 2 0 1 0 1 1 1 1 1 1 1 1 1 1 1 1 1 0 
+| 0 0 0 0 0 0 0 0 2 0 2 0 2 0 2 0 2 0 2 0 2 0 2 0 2 0 2 0 2 0 2 0 2 0 2 0 0 0 0 0 0 0 0 0 0 2 0 1 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 
+| 0 0 0 0 0 0 0 0 0 2 0 2 0 2 0 2 0 2 0 2 0 2 0 2 0 2 0 2 0 2 0 2 0 2 0 0 0 0 0 0 0 0 0 0 0 0 1 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 
+| 0 0 0 0 0 0 0 0 0 0 2 0 2 0 2 0 2 0 2 0 2 0 2 0 2 0 2 0 2 0 2 0 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 
+| 0 0 0 0 0 0 0 0 0 0 0 2 0 2 0 2 0 2 0 2 0 2 0 2 0 2 0 2 0 2 0 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 
+| 0 0 0 0 0 0 0 0 0 0 0 0 2 0 2 0 2 0 2 0 2 0 2 0 2 0 2 0 2 0 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 
+| 0 0 0 0 0 0 0 0 0 0 0 0 0 2 0 2 0 2 0 2 0 2 0 2 0 2 0 2 0 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 
+| 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 0 2 0 2 0 2 0 2 0 2 0 2 0 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 
+| 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 0 2 0 2 0 2 0 2 0 2 0 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 
+| 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 0 2 0 2 0 2 0 2 0 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 
+| 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 0 2 0 2 0 2 0 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 
+| 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 0 2 0 2 0 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 
+| 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 0 2 0 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 
+| 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 0 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 
+| 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 
+| 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 
+| 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 
+| 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 
+| 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 
+| 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 
+| 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 
+| 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 
+| 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 
+| 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 
+| 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 
+| 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 
+| 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 
+| 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 
+| 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 
+| 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 
+| 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 
+| 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 
+| 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 
+| 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 
+| 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 
+| 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 
+| 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 
+| 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 
+| 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 
+| 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 
+| 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 
+| 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 
+| 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 
+| 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 
+| 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 
+| 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 
+| 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 
+| 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 
+| 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 
+| 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 
+| 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 
+| 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 
+| 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 
+| 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 
+| 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 
+| 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 
+| 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 
+| 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 
+| 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 
+| 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 
+| 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 
+| 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 
+

+ 13 - 0
examples/stencil/run

@@ -0,0 +1,13 @@
+#!/bin/bash
+[ -z "$N" ] && N=1
+export N
+[ -z "$STARPU_SCHED_BETA" ] && STARPU_SCHED_BETA="2"
+export STARPU_SCHED_BETA
+echo sched $STARPU_SCHED 1>&2
+echo sched_beta $STARPU_SCHED_BETA 1>&2
+echo prefetch $STARPU_PREFETCH 1>&2
+echo calibrate $STARPU_CALIBRATE 1>&2
+echo ncpus $STARPU_NCPUS 1>&2
+echo ncuda $STARPU_NCUDA 1>&2
+echo N $N
+./stencil -nbz $(($N * 64)) -sizex 128 -sizey 128 -sizez $(( $((16 * $N)) * 128 )) -niter 64 "$@"

+ 58 - 0
examples/stencil/shadow.cu

@@ -0,0 +1,58 @@
+/*
+ * StarPU
+ * Copyright (C) Université Bordeaux 1, CNRS 2009-2010 (see AUTHORS file)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation; either version 2.1 of the License, or (at
+ * your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * See the GNU Lesser General Public License in COPYING.LGPL for more details.
+ */
+
+#define _externC extern "C"
+#include "stencil.h"
+
+/* Perform replication of data on X and Y edges, to fold the domain on 
+   itself through mere replication of the source state. */
+
+extern "C" __global__ void
+cuda_shadow( int bz, TYPE *ptr, int nx, int ny, int nz, int ldy, int ldz, int i)
+{
+	unsigned idx = threadIdx.x + blockIdx.x * blockDim.x;
+	unsigned idy = threadIdx.y + blockIdx.y * blockDim.y;
+	//unsigned idz = threadIdx.z + blockIdx.z * blockDim.z;
+	unsigned idz = 0;
+	unsigned stepx = blockDim.x * gridDim.x;
+	unsigned stepy = blockDim.y * gridDim.y;
+	//unsigned stepz = blockDim.z * gridDim.z;
+	unsigned stepz = 1;
+	unsigned x, y, z;
+
+#include "shadow.h"
+}
+
+extern "C" void
+cuda_shadow_host(int bz, TYPE *ptr, int nx, int ny, int nz, int ldy, int ldz, int i)
+{
+	unsigned max_parallelism = 512;
+	unsigned threads_per_dim_x = max_parallelism;
+	while (threads_per_dim_x / 2 >= nx)
+		threads_per_dim_x /= 2;
+	unsigned threads_per_dim_y = max_parallelism / threads_per_dim_x;
+	while (threads_per_dim_y / 2 >= ny)
+		threads_per_dim_y /= 2;
+#if 0
+	unsigned threads_per_dim_z = 4;
+	dim3 dimBlock(threads_per_dim_x, threads_per_dim_y, threads_per_dim_z);
+	dim3 dimGrid(nx / threads_per_dim_x, ny / threads_per_dim_y, nz / threads_per_dim_z);
+#else
+	dim3 dimBlock(threads_per_dim_x, threads_per_dim_y);
+	dim3 dimGrid((nx + threads_per_dim_x-1) / threads_per_dim_x, (ny + threads_per_dim_y-1) / threads_per_dim_y);
+#endif
+	cuda_shadow <<<dimGrid, dimBlock>>> (bz, ptr, nx, ny, nz, ldy, ldz, i);
+}

+ 44 - 0
examples/stencil/shadow.h

@@ -0,0 +1,44 @@
+/*
+ * StarPU
+ * Copyright (C) Université Bordeaux 1, CNRS 2009-2010 (see AUTHORS file)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation; either version 2.1 of the License, or (at
+ * your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * See the GNU Lesser General Public License in COPYING.LGPL for more details.
+ */
+
+/* Perform replication of data on X and Y edges, to fold the domain on 
+   itself through mere replication of the source state. */
+
+/* TODO: rather use a dummy for loop, to assign the job to the threads that will work on it? */
+	if (idy == 0)
+		for (z = i-1 + idz; z < nz-(i-1); z += stepz)
+			for (x = K + idx; x < nx-K; x += stepx) {
+				unsigned index = x+z*ldz;
+				ptr[index+(K-1)*ldy] = ptr[index+(ny-K-1)*ldy];
+				ptr[index+(ny-K)*ldy] = ptr[index+K*ldy];
+			}
+
+	if (idx == 0)
+		for (z = i-1 + idz; z < nz-(i-1); z += stepz)
+			for (y = K + idy; y < ny-K; y += stepy) {
+				unsigned index = y*ldy+z*ldz;
+				ptr[(K-1)+index] = ptr[(nx-K-1)+index];
+				ptr[(nx-K)+index] = ptr[K+index];
+			}
+
+	if (idx == 0 && idy == 0)
+		for (z = i-1 + idz; z < nz-(i-1); z += stepz) {
+			unsigned index = z*ldz;
+			ptr[K-1+(K-1)*ldy+index] = ptr[(nx-K-1)+(ny-K-1)*ldy+index];
+			ptr[(nx-K)+(K-1)*ldy+index] = ptr[K+(ny-K-1)*ldy+index];
+			ptr[(K-1)+(ny-K)*ldy+index] = ptr[(nx-K-1)+K*ldy+index];
+			ptr[(nx-K)+(ny-K)*ldy+index] = ptr[K+K*ldy+index];
+		}

+ 350 - 0
examples/stencil/stencil-blocks.c

@@ -0,0 +1,350 @@
+/*
+ * StarPU
+ * Copyright (C) Université Bordeaux 1, CNRS 2009-2010 (see AUTHORS file)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation; either version 2.1 of the License, or (at
+ * your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * See the GNU Lesser General Public License in COPYING.LGPL for more details.
+ */
+
+#include "stencil.h"
+#include <math.h>
+
+/* Manage block and tags allocation */
+
+static struct block_description *blocks;
+static unsigned sizex, sizey, sizez;
+static unsigned nbz;
+static unsigned *block_sizes_z;
+
+/*
+ *	Tags for various codelet completion
+ */
+
+/*
+ * common tag format:
+ */
+static starpu_tag_t tag_common(int z, int dir, int type)
+{
+	return (((((starpu_tag_t)type) << 4) | ((dir+1)/2)) << 32)|(starpu_tag_t)z;
+}
+
+/* Completion of last update tasks */
+starpu_tag_t TAG_FINISH(int z)
+{
+	z = (z + nbz)%nbz;
+
+	starpu_tag_t tag = tag_common(z, 0, 1);
+	return tag;
+}
+
+/* Completion of the save codelet for MPI send/recv */
+starpu_tag_t TAG_START(int z, int dir)
+{
+	z = (z + nbz)%nbz;
+
+	starpu_tag_t tag = tag_common(z, dir, 2);
+	return tag;
+}
+
+/*
+ * common MPI tag format:
+ * iter is actually not needed for coherency, but it makes debugging easier
+ */
+static int mpi_tag_common(int z, int iter, int dir, int buffer)
+{
+	return (((((iter << 12)|z)<<4) | ((1+dir)/2))<<4)|buffer;
+}
+
+int MPI_TAG0(int z, int iter, int dir)
+{
+	z = (z + nbz)%nbz;
+
+	int tag = mpi_tag_common(z, iter, dir, 0);
+
+	return tag;
+}
+
+int MPI_TAG1(int z, int iter, int dir)
+{
+	z = (z + nbz)%nbz;
+
+	int tag = mpi_tag_common(z, iter, dir, 1);
+
+	return tag;
+}
+
+
+
+/*
+ *	Block descriptors
+ */
+
+/* Compute the size of the different blocks */
+static void compute_block_sizes(void)
+{
+	block_sizes_z = malloc(nbz*sizeof(unsigned));
+	STARPU_ASSERT(block_sizes_z);
+
+	/* Perhaps the last chunk is smaller */
+	unsigned default_block_size = (sizez+nbz-1)/nbz;
+	unsigned remaining = sizez;
+
+	unsigned b;
+	for (b = 0; b < nbz; b++)
+	{
+		block_sizes_z[b] = MIN(default_block_size, remaining);
+		remaining -= block_sizes_z[b];
+	}
+
+	STARPU_ASSERT(remaining == 0);
+}
+
+unsigned get_block_size(int bz)
+{
+	return block_sizes_z[bz];
+}
+
+struct block_description *get_block_description(int z)
+{
+	z = (z + nbz)%nbz;
+
+	STARPU_ASSERT(&blocks[z]);
+
+	return &blocks[z];
+}
+
+unsigned get_block_mpi_node(int z)
+{
+	z = (z + nbz)%nbz;
+	return blocks[z].mpi_node;
+}
+
+void create_blocks_array(unsigned _sizex, unsigned _sizey, unsigned _sizez, unsigned _nbz)
+{
+	/* Store the parameters */
+	nbz = _nbz;
+	sizex = _sizex;
+	sizey = _sizey;
+	sizez = _sizez;
+
+	/* Create a grid of block descriptors */
+	blocks = calloc(nbz, sizeof(struct block_description));
+	STARPU_ASSERT(blocks);
+
+	/* What is the size of the different blocks ? */
+	compute_block_sizes();
+
+	unsigned bz;
+	for (bz = 0; bz < nbz; bz++)
+	{
+		struct block_description * block =
+				get_block_description(bz);
+
+		/* Which block is it ? */
+		block->bz = bz;
+
+		/* For simplicity, we store which are the neighbours blocks */
+		block->boundary_blocks[B] = get_block_description((bz-1+nbz)%nbz);
+		block->boundary_blocks[T] = get_block_description((bz+1)%nbz);
+	}
+}
+
+/*
+ *	Initialization of the blocks
+ */
+
+void assign_blocks_to_workers(int rank)
+{
+	unsigned bz;
+
+	/* NB: perhaps we could count a GPU as multiple workers */
+
+	/* how many workers are there ? */
+	//unsigned nworkers = starpu_worker_get_count();
+
+	/* how many blocks are on that MPI node ? */
+	unsigned nblocks = 0;
+	for (bz = 0; bz < nbz; bz++)
+	{
+		struct block_description *block =
+				get_block_description(bz);
+
+		if (block->mpi_node == rank)
+			nblocks++;
+	}
+
+	/* how many blocks per worker ? */
+	//	unsigned nblocks_per_worker = (nblocks + nworkers - 1)/nworkers;
+
+	/* we now attribute up to nblocks_per_worker blocks per workers */
+	unsigned attributed = 0;
+	for (bz = 0; bz < nbz; bz++)
+	{
+		struct block_description *block =
+				get_block_description(bz);
+
+		if (block->mpi_node == rank)
+		{
+			unsigned workerid;
+			/* Manage initial block distribution between CPU and GPU */
+		#if 0
+			#if 1
+			/* GPUs then CPUs */
+			if (attributed < 3*18)
+				workerid = attributed / 18;
+			else
+				workerid = 3+ (attributed - 3*18) / 2;
+			#else
+			/* GPUs interleaved with CPUs */
+			if ((attributed % 20) <= 1)
+				workerid = 3 + attributed / 20;
+			else if (attributed < 60)
+				workerid = attributed / 20;
+			else
+				workerid = (attributed - 60)/2 + 6;
+			#endif
+		#else
+			/* Only GPUS */
+			workerid = (attributed / 21) % 3;
+		#endif
+			//= attributed/nblocks_per_worker;
+
+			block->preferred_worker = workerid;
+
+			attributed++;
+		}
+	}
+}
+
+
+
+void assign_blocks_to_mpi_nodes(int world_size)
+{
+	unsigned nzblocks_per_process = (nbz + world_size - 1) / world_size;
+
+	unsigned bz;
+	for (bz = 0; bz < nbz; bz++)
+	{
+		struct block_description *block =
+				get_block_description(bz);
+
+		block->mpi_node = bz / nzblocks_per_process;
+	}
+}
+
+static size_t allocated = 0;
+
+static void allocate_block_on_node(starpu_data_handle *handleptr, TYPE **ptr, unsigned nx, unsigned ny, unsigned nz)
+{
+	int ret;
+	size_t block_size = nx*ny*nz*sizeof(TYPE);
+
+	/* Allocate memory */
+#if 1
+	ret = starpu_data_malloc_pinned_if_possible((void **)ptr, block_size);
+	STARPU_ASSERT(ret == 0);
+#else
+	*ptr = malloc(block_size);
+	STARPU_ASSERT(*ptr);
+#endif
+
+	allocated += block_size;
+
+	/* Fill the blocks with 0 */
+	memset(*ptr, 0, block_size);
+
+	/* Register it to StarPU */
+	starpu_block_data_register(handleptr, 0, (uintptr_t)*ptr, nx, nx*ny, nx, ny, nz, sizeof(TYPE));
+}
+
+void display_memory_consumption(int rank)
+{
+	fprintf(stderr, "%lu MB of memory were allocated on node %d\n", allocated/(1024*1024), rank);
+}
+
+void allocate_memory_on_node(int rank)
+{
+	unsigned bz;
+	for (bz = 0; bz < nbz; bz++)
+	{
+		struct block_description *block = get_block_description(bz);
+
+		unsigned node = block->mpi_node;
+
+		unsigned size_bz = block_sizes_z[bz];
+	
+		/* Main blocks */
+		if (node == rank)
+		{
+			allocate_block_on_node(&block->layers_handle[0], &block->layers[0],
+						(sizex + 2*K), (sizey + 2*K), (size_bz + 2*K));
+#ifdef LIFE
+			unsigned x, y, z;
+			unsigned sum = 0;
+			for (x = 0; x < sizex; x++)
+				for (y = 0; y < sizey; y++)
+					for (z = 0; z < size_bz; z++)
+						/* Just random data */
+						sum += block->layers[0][(K+x)+(K+y)*(sizex + 2*K)+(K+z)*(sizex+2*K)*(sizey+2*K)] = (int)((x/7.+y/13.+(bz*size_bz + z)/17.) * 10.) % 2;
+//			printf("block %d starts with %d/%d alive\n", bz, sum, sizex*sizey*size_bz);
+#endif
+			allocate_block_on_node(&block->layers_handle[1], &block->layers[1],
+						(sizex + 2*K), (sizey + 2*K), (size_bz + 2*K));
+		}
+
+		/* Boundary blocks : Top */
+		unsigned top_node = block->boundary_blocks[T]->mpi_node;
+		if ((node == rank) || (top_node == rank))
+		{
+			allocate_block_on_node(&block->boundaries_handle[T][0], &block->boundaries[T][0],
+						(sizex + 2*K), (sizey + 2*K), K);
+			allocate_block_on_node(&block->boundaries_handle[T][1], &block->boundaries[T][1],
+						(sizex + 2*K), (sizey + 2*K), K);
+		} 
+
+		/* Boundary blocks : Bottom */
+		unsigned bottom_node = block->boundary_blocks[B]->mpi_node;
+		if ((node == rank) || (bottom_node == rank))
+		{
+			allocate_block_on_node(&block->boundaries_handle[B][0], &block->boundaries[B][0],
+						(sizex + 2*K), (sizey + 2*K), K);
+			allocate_block_on_node(&block->boundaries_handle[B][1], &block->boundaries[B][1],
+						(sizex + 2*K), (sizey + 2*K), K);
+		} 
+	}
+}
+
+/* check how many cells are alive */
+void check(int rank)
+{
+	unsigned bz;
+	for (bz = 0; bz < nbz; bz++)
+	{
+		struct block_description *block = get_block_description(bz);
+
+		unsigned node = block->mpi_node;
+
+		/* Main blocks */
+		if (node == rank)
+		{
+			unsigned size_bz = block_sizes_z[bz];
+#ifdef LIFE
+			unsigned x, y, z;
+			unsigned sum = 0;
+			for (x = 0; x < sizex; x++)
+				for (y = 0; y < sizey; y++)
+					for (z = 0; z < size_bz; z++)
+						sum += block->layers[0][(K+x)+(K+y)*(sizex + 2*K)+(K+z)*(sizex+2*K)*(sizey+2*K)];
+			printf("block %d got %d/%d alive\n", bz, sum, sizex*sizey*size_bz);
+#endif
+		}
+	}
+}

+ 494 - 0
examples/stencil/stencil-kernels.c

@@ -0,0 +1,494 @@
+/*
+ * StarPU
+ * Copyright (C) Université Bordeaux 1, CNRS 2009-2010 (see AUTHORS file)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation; either version 2.1 of the License, or (at
+ * your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * See the GNU Lesser General Public License in COPYING.LGPL for more details.
+ */
+
+#include "stencil.h"
+#include <sys/time.h>
+
+/* Computation Kernels */
+
+/*
+ * There are three codeletets:
+ *
+ * - cl_update, which takes a block and the boundaries of its neighbours, loads
+ *   the boundaries into the block and perform some update loops:
+ *
+ *     comp. buffer      save. buffers        comp. buffer        save. buffers        comp. buffer
+ *   |     ...     |                                                                                      
+ *   |             | +------------------+ +------------------+                                            
+ *   |     #N+1    | | #N+1 bottom copy====>#N+1 bottom copy |                                            
+ *   +-------------+ +------------------+ +------------------+                                            
+ *   | #N top copy | |   #N top copy    | |                  |                                            
+ *   +-------------+ +------------------+ |                  |                                            
+ *                                        | #N               |                                            
+ *                                                 ...                                                    
+ *                                        |                  | +----------------+ +----------------------+
+ *                                        |                  | | #N bottom copy | | block #N bottom copy |
+ * ^                                      +------------------+ +----------------+ +----------------------+
+ * |                                      | #N-1 top copy   <====#N-1 top copy  | |  block #N-1          |
+ * |                                      +------------------+ +----------------+ |                      |
+ * Z                                                                                     ...
+ *
+ * - save_cl_top, which take a block and its top boundary, and saves the top of
+ *   the block into the boundary (to be given as bottom of the neighbour above
+ *   this block).
+ *
+ *     comp. buffer      save. buffers        comp. buffer        save. buffers        comp. buffer
+ *   |     ...     |                                                                                      
+ *   |             | +------------------+ +------------------+                                            
+ *   |     #N+1    | | #N+1 bottom copy | | #N+1 bottom copy |                                            
+ *   +-------------+ +------------------+ +------------------+                                            
+ *   | #N top copy | |   #N top copy   <====                 |                                            
+ *   +-------------+ +------------------+ |..................|                                            
+ *                                        | #N               |                                            
+ *                                                 ...                                                    
+ *                                        |                  | +----------------+ +----------------------+
+ *                                        |                  | | #N bottom copy | | block #N bottom copy |
+ * ^                                      +------------------+ +----------------+ +----------------------+
+ * |                                      | #N-1 top copy    | | #N-1 top copy  | |  block #N-1          |
+ * |                                      +------------------+ +----------------+ |                      |
+ * Z                                                                                     ...
+ *
+ * - save_cl_bottom, same for the bottom
+ *     comp. buffer      save. buffers        comp. buffer        save. buffers        comp. buffer
+ *   |     ...     |                                                                                      
+ *   |             | +------------------+ +------------------+                                            
+ *   |     #N+1    | | #N+1 bottom copy | | #N+1 bottom copy |                                            
+ *   +-------------+ +------------------+ +------------------+                                            
+ *   | #N top copy | |   #N top copy    | |                  |                                            
+ *   +-------------+ +------------------+ |                  |                                            
+ *                                        | #N               |                                            
+ *                                                 ...                                                    
+ *                                        |..................| +----------------+ +----------------------+
+ *                                        |                 ====>#N bottom copy | | block #N bottom copy |
+ * ^                                      +------------------+ +----------------+ +----------------------+
+ * |                                      | #N-1 top copy    | | #N-1 top copy  | |  block #N-1          |
+ * |                                      +------------------+ +----------------+ |                      |
+ * Z                                                                                     ...
+ *
+ * The idea is that the computation buffers thus don't have to move, only their
+ * boundaries are copied to buffers that do move (be it CPU/GPU, GPU/GPU or via
+ * MPI)
+ *
+ * For each of the buffers above, there are two (0/1) buffers to make new/old switch costless.
+ */
+
+#if 0
+# define DEBUG(fmt, ...) fprintf(stderr,fmt,##__VA_ARGS__)
+#else
+# define DEBUG(fmt, ...) (void) 0
+#endif
+
+/* Record which GPU ran which block, for nice pictures */
+int who_runs_what_len;
+int *who_runs_what;
+int *who_runs_what_index;
+struct timeval *last_tick;
+
+/* Record how many updates each worker performed */
+unsigned update_per_worker[STARPU_NMAXWORKERS];
+
+/*
+ * Load a neighbour's boundary into block, CPU version
+ */
+static void load_subblock_from_buffer_cpu(starpu_block_interface_t *block,
+					starpu_block_interface_t *boundary,
+					unsigned firstz)
+{
+	/* Sanity checks */
+	STARPU_ASSERT(block->nx == boundary->nx);
+	STARPU_ASSERT(block->ny == boundary->ny);
+	STARPU_ASSERT(boundary->nz == K);
+
+	/* NB: this is not fully garanteed ... but it's *very* likely and that
+	 * makes our life much simpler */
+	STARPU_ASSERT(block->ldy == boundary->ldy);
+	STARPU_ASSERT(block->ldz == boundary->ldz);
+	
+	/* We do a contiguous memory transfer */
+	size_t boundary_size = K*block->ldz*block->elemsize;
+
+	unsigned offset = firstz*block->ldz;
+	TYPE *block_data = (TYPE *)block->ptr;
+	TYPE *boundary_data = (TYPE *)boundary->ptr;
+	memcpy(&block_data[offset], boundary_data, boundary_size);
+}
+
+/*
+ * Load a neighbour's boundary into block, CUDA version
+ */
+#ifdef STARPU_USE_CUDA
+static void load_subblock_from_buffer_cuda(starpu_block_interface_t *block,
+					starpu_block_interface_t *boundary,
+					unsigned firstz)
+{
+	/* Sanity checks */
+	STARPU_ASSERT(block->nx == boundary->nx);
+	STARPU_ASSERT(block->ny == boundary->ny);
+	STARPU_ASSERT(boundary->nz == K);
+
+	/* NB: this is not fully garanteed ... but it's *very* likely and that
+	 * makes our life much simpler */
+	STARPU_ASSERT(block->ldy == boundary->ldy);
+	STARPU_ASSERT(block->ldz == boundary->ldz);
+	
+	/* We do a contiguous memory transfer */
+	size_t boundary_size = K*block->ldz*block->elemsize;
+
+	unsigned offset = firstz*block->ldz;
+	TYPE *block_data = (TYPE *)block->ptr;
+	TYPE *boundary_data = (TYPE *)boundary->ptr;
+	cudaMemcpy(&block_data[offset], boundary_data, boundary_size, cudaMemcpyDeviceToDevice);
+}
+
+/*
+ * cl_update (CUDA version)
+ */
+static void update_func_cuda(void *descr[], void *arg)
+{
+	struct block_description *block = arg;
+	int workerid = starpu_worker_get_id();
+	DEBUG( "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n");
+	if (block->bz == 0)
+fprintf(stderr,"!!! DO update_func_cuda z %d CUDA%d !!!\n", block->bz, workerid);
+	else
+	DEBUG( "!!! DO update_func_cuda z %d CUDA%d !!!\n", block->bz, workerid);
+#ifdef STARPU_USE_MPI
+	int rank = 0;
+	MPI_Comm_rank(MPI_COMM_WORLD, &rank);
+	DEBUG( "!!!           RANK %d              !!!\n", rank);
+#endif
+	DEBUG( "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n");
+
+	unsigned block_size_z = get_block_size(block->bz);
+	unsigned i;
+	update_per_worker[workerid]++;
+
+	struct timeval tv, tv2, diff, delta = {.tv_sec = 0, .tv_usec = get_ticks()*1000};
+	gettimeofday(&tv, NULL);
+	timersub(&tv, &start, &tv2);
+	timersub(&tv2, &last_tick[block->bz], &diff);
+	while (timercmp(&diff, &delta, >=)) {
+		timeradd(&last_tick[block->bz], &delta, &last_tick[block->bz]);
+		timersub(&tv2, &last_tick[block->bz], &diff);
+		if (who_runs_what_index[block->bz] < who_runs_what_len)
+			who_runs_what[block->bz + (who_runs_what_index[block->bz]++) * get_nbz()] = -1;
+	}
+
+	if (who_runs_what_index[block->bz] < who_runs_what_len)
+		who_runs_what[block->bz + (who_runs_what_index[block->bz]++) * get_nbz()] = global_workerid(workerid);
+
+	/*
+	 *	Load neighbours' boundaries : TOP
+	 */
+
+	/* The offset along the z axis is (block_size_z + K) */
+	load_subblock_from_buffer_cuda(descr[0], descr[2], block_size_z+K);
+	load_subblock_from_buffer_cuda(descr[1], descr[3], block_size_z+K);
+
+	/*
+	 *	Load neighbours' boundaries : BOTTOM
+	 */
+	load_subblock_from_buffer_cuda(descr[0], descr[4], 0);
+	load_subblock_from_buffer_cuda(descr[1], descr[5], 0);
+
+	/*
+	 *	Stencils ... do the actual work here :) TODO
+	 */
+
+	for (i=1; i<=K; i++)
+	{
+		starpu_block_interface_t *oldb = descr[i%2], *newb = descr[(i+1)%2];
+		TYPE *old = (void*) oldb->ptr, *new = (void*) newb->ptr;
+
+		/* Shadow data */
+		cuda_shadow_host(block->bz, old, oldb->nx, oldb->ny, oldb->nz, oldb->ldy, oldb->ldz, i);
+
+		/* And perform actual computation */
+#ifdef LIFE
+		cuda_life_update_host(block->bz, old, new, oldb->nx, oldb->ny, oldb->nz, oldb->ldy, oldb->ldz, i);
+#else
+		cudaMemcpy(new, old, oldb->nx * oldb->ny * oldb->nz * sizeof(*new), cudaMemcpyDeviceToDevice);
+#endif /* LIFE */
+	}
+
+	cudaError_t cures;
+	if ((cures = cudaThreadSynchronize()) != cudaSuccess)
+		STARPU_CUDA_REPORT_ERROR(cures);
+
+}
+#endif /* STARPU_USE_CUDA */
+
+/*
+ * cl_update (CPU version)
+ */
+static void update_func_cpu(void *descr[], void *arg)
+{
+	struct block_description *block = arg;
+	int workerid = starpu_worker_get_id();
+	DEBUG( "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n");
+	if (block->bz == 0)
+fprintf(stderr,"!!! DO update_func_cpu z %d CPU%d !!!\n", block->bz, workerid);
+	else
+	DEBUG( "!!! DO update_func_cpu z %d CPU%d !!!\n", block->bz, workerid);
+#ifdef STARPU_USE_MPI
+	int rank = 0;
+	MPI_Comm_rank(MPI_COMM_WORLD, &rank);
+	DEBUG( "!!!           RANK %d            !!!\n", rank);
+#endif
+	DEBUG( "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n");
+
+	unsigned block_size_z = get_block_size(block->bz);
+	unsigned i;
+	update_per_worker[workerid]++;
+
+	struct timeval tv, tv2, diff, delta = {.tv_sec = 0, .tv_usec = get_ticks() * 1000};
+	gettimeofday(&tv, NULL);
+	timersub(&tv, &start, &tv2);
+	timersub(&tv2, &last_tick[block->bz], &diff);
+	while (timercmp(&diff, &delta, >=)) {
+		timeradd(&last_tick[block->bz], &delta, &last_tick[block->bz]);
+		timersub(&tv2, &last_tick[block->bz], &diff);
+		if (who_runs_what_index[block->bz] < who_runs_what_len)
+			who_runs_what[block->bz + (who_runs_what_index[block->bz]++) * get_nbz()] = -1;
+	}
+
+	if (who_runs_what_index[block->bz] < who_runs_what_len)
+		who_runs_what[block->bz + (who_runs_what_index[block->bz]++) * get_nbz()] = global_workerid(workerid);
+
+	/*
+	 *	Load neighbours' boundaries : TOP
+	 */
+
+	/* The offset along the z axis is (block_size_z + K) */
+	load_subblock_from_buffer_cpu(descr[0], descr[2], block_size_z+K);
+	load_subblock_from_buffer_cpu(descr[1], descr[3], block_size_z+K);
+
+	/*
+	 *	Load neighbours' boundaries : BOTTOM
+	 */
+	load_subblock_from_buffer_cpu(descr[0], descr[4], 0);
+	load_subblock_from_buffer_cpu(descr[1], descr[5], 0);
+
+	/*
+	 *	Stencils ... do the actual work here :) TODO
+	 */
+
+	for (i=1; i<=K; i++)
+	{
+		starpu_block_interface_t *oldb = descr[i%2], *newb = descr[(i+1)%2];
+		TYPE *old = (void*) oldb->ptr, *new = (void*) newb->ptr;
+
+		/* Shadow data */
+		unsigned ldy = oldb->ldy, ldz = oldb->ldz;
+		unsigned nx = oldb->nx, ny = oldb->ny, nz = oldb->nz;
+		unsigned x, y, z;
+		unsigned stepx = 1;
+		unsigned stepy = 1;
+		unsigned stepz = 1;
+		unsigned idx = 0;
+		unsigned idy = 0;
+		unsigned idz = 0;
+		TYPE *ptr = old;
+
+#		include "shadow.h"
+
+		/* And perform actual computation */
+#ifdef LIFE
+		life_update(block->bz, old, new, oldb->nx, oldb->ny, oldb->nz, oldb->ldy, oldb->ldz, i);
+#else
+		memcpy(new, old, oldb->nx * oldb->ny * oldb->nz * sizeof(*new));
+#endif /* LIFE */
+	}
+}
+
+/* Performance model and codelet structure */
+static struct starpu_perfmodel_t cl_update_model = {
+	.type = STARPU_HISTORY_BASED,
+	.symbol = "cl_update" 
+};
+
+starpu_codelet cl_update = {
+	.where = 
+#ifdef STARPU_USE_CUDA
+		STARPU_CUDA|
+#endif
+		STARPU_CPU,
+	.cpu_func = update_func_cpu,
+#ifdef STARPU_USE_CUDA
+	.cuda_func = update_func_cuda,
+#endif
+	.model = &cl_update_model,
+	.nbuffers = 6
+};
+
+/*
+ * Save the block internal boundaries to give them to our neighbours.
+ */
+
+/* CPU version */
+static void load_subblock_into_buffer_cpu(starpu_block_interface_t *block,
+					starpu_block_interface_t *boundary,
+					unsigned firstz)
+{
+	/* Sanity checks */
+	STARPU_ASSERT(block->nx == boundary->nx);
+	STARPU_ASSERT(block->ny == boundary->ny);
+	STARPU_ASSERT(boundary->nz == K);
+
+	/* NB: this is not fully garanteed ... but it's *very* likely and that
+	 * makes our life much simpler */
+	STARPU_ASSERT(block->ldy == boundary->ldy);
+	STARPU_ASSERT(block->ldz == boundary->ldz);
+	
+	/* We do a contiguous memory transfer */
+	size_t boundary_size = K*block->ldz*block->elemsize;
+
+	unsigned offset = firstz*block->ldz;
+	TYPE *block_data = (TYPE *)block->ptr;
+	TYPE *boundary_data = (TYPE *)boundary->ptr;
+	memcpy(boundary_data, &block_data[offset], boundary_size);
+}
+
+/* CUDA version */
+#ifdef STARPU_USE_CUDA
+static void load_subblock_into_buffer_cuda(starpu_block_interface_t *block,
+					starpu_block_interface_t *boundary,
+					unsigned firstz)
+{
+	/* Sanity checks */
+	STARPU_ASSERT(block->nx == boundary->nx);
+	STARPU_ASSERT(block->ny == boundary->ny);
+	STARPU_ASSERT(boundary->nz == K);
+
+	/* NB: this is not fully garanteed ... but it's *very* likely and that
+	 * makes our life much simpler */
+	STARPU_ASSERT(block->ldy == boundary->ldy);
+	STARPU_ASSERT(block->ldz == boundary->ldz);
+	
+	/* We do a contiguous memory transfer */
+	size_t boundary_size = K*block->ldz*block->elemsize;
+
+	unsigned offset = firstz*block->ldz;
+	TYPE *block_data = (TYPE *)block->ptr;
+	TYPE *boundary_data = (TYPE *)boundary->ptr;
+	cudaMemcpy(boundary_data, &block_data[offset], boundary_size, cudaMemcpyDeviceToDevice);
+}
+#endif /* STARPU_USE_CUDA */
+
+/* Record how many top/bottom saves each worker performed */
+unsigned top_per_worker[STARPU_NMAXWORKERS];
+unsigned bottom_per_worker[STARPU_NMAXWORKERS];
+
+/* top save, CPU version */
+static void dummy_func_top_cpu(void *descr[] __attribute__((unused)), void *arg)
+{
+	struct block_description *block = arg;
+	int workerid = starpu_worker_get_id();
+	top_per_worker[workerid]++;
+
+	DEBUG( "DO SAVE Bottom block %d\n", block->bz);
+
+	/* The offset along the z axis is (block_size_z + K)- K */
+	unsigned block_size_z = get_block_size(block->bz);
+
+	load_subblock_into_buffer_cpu(descr[0], descr[2], block_size_z);
+	load_subblock_into_buffer_cpu(descr[1], descr[3], block_size_z);
+}
+
+/* bottom save, CPU version */
+static void dummy_func_bottom_cpu(void *descr[] __attribute__((unused)), void *arg)
+{
+	struct block_description *block = arg;
+	int workerid = starpu_worker_get_id();
+	bottom_per_worker[workerid]++;
+
+	DEBUG( "DO SAVE Top block %d\n", block->bz);
+
+	load_subblock_into_buffer_cpu(descr[0], descr[2], K);
+	load_subblock_into_buffer_cpu(descr[1], descr[3], K);
+}
+
+/* top save, CUDA version */
+#ifdef STARPU_USE_CUDA
+static void dummy_func_top_cuda(void *descr[] __attribute__((unused)), void *arg)
+{
+	struct block_description *block = arg;
+	int workerid = starpu_worker_get_id();
+	top_per_worker[workerid]++;
+
+	DEBUG( "DO SAVE Top block %d\n", block->bz);
+
+	/* The offset along the z axis is (block_size_z + K)- K */
+	unsigned block_size_z = get_block_size(block->bz);
+
+	load_subblock_into_buffer_cuda(descr[0], descr[2], block_size_z);
+	load_subblock_into_buffer_cuda(descr[1], descr[3], block_size_z);
+	cudaThreadSynchronize();
+}
+
+/* bottom save, CUDA version */
+static void dummy_func_bottom_cuda(void *descr[] __attribute__((unused)), void *arg)
+{
+	struct block_description *block = arg;
+	int workerid = starpu_worker_get_id();
+	bottom_per_worker[workerid]++;
+
+	DEBUG( "DO SAVE Bottom block %d on CUDA\n", block->bz);
+
+	load_subblock_into_buffer_cuda(descr[0], descr[2], K);
+	load_subblock_into_buffer_cuda(descr[1], descr[3], K);
+	cudaThreadSynchronize();
+}
+#endif /* STARPU_USE_CUDA */
+
+/* Performance models and codelet for save */
+static struct starpu_perfmodel_t save_cl_bottom_model = {
+	.type = STARPU_HISTORY_BASED,
+	.symbol = "save_cl_bottom" 
+};
+
+static struct starpu_perfmodel_t save_cl_top_model = {
+	.type = STARPU_HISTORY_BASED,
+	.symbol = "save_cl_top" 
+};
+
+starpu_codelet save_cl_bottom = {
+	.where = 
+#ifdef STARPU_USE_CUDA
+		STARPU_CUDA|
+#endif
+		STARPU_CPU,
+	.cpu_func = dummy_func_bottom_cpu,
+#ifdef STARPU_USE_CUDA
+	.cuda_func = dummy_func_bottom_cuda,
+#endif
+	.model = &save_cl_bottom_model,
+	.nbuffers = 4
+};
+
+starpu_codelet save_cl_top = {
+	.where = 
+#ifdef STARPU_USE_CUDA
+		STARPU_CUDA|
+#endif
+		STARPU_CPU,
+	.cpu_func = dummy_func_top_cpu,
+#ifdef STARPU_USE_CUDA
+	.cuda_func = dummy_func_top_cuda,
+#endif
+	.model = &save_cl_top_model,
+	.nbuffers = 4
+};

+ 309 - 0
examples/stencil/stencil-tasks.c

@@ -0,0 +1,309 @@
+/*
+ * StarPU
+ * Copyright (C) Université Bordeaux 1, CNRS 2009-2010 (see AUTHORS file)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation; either version 2.1 of the License, or (at
+ * your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * See the GNU Lesser General Public License in COPYING.LGPL for more details.
+ */
+
+#include "stencil.h"
+
+#define BIND_LAST 1
+
+/*
+ * Schedule tasks for updates and saves
+ */
+
+/*
+ * NB: iter = 0: initialization phase, TAG_U(z, 0) = TAG_INIT
+ *
+ * dir is -1 or +1.
+ */
+
+#if 0
+# define DEBUG(fmt, ...) fprintf(stderr,fmt,##__VA_ARGS__)
+#else
+# define DEBUG(fmt, ...) 
+#endif
+
+/*
+ *	SAVE
+ */
+
+/* R(z) = R(z+d) = local, just call the save kernel */
+static void create_task_save_local(unsigned iter, unsigned z, int dir, unsigned local_rank)
+{
+	struct starpu_task *save_task = starpu_task_create();
+	struct block_description *descr = get_block_description(z);
+
+	save_task->cl = (dir == -1)?&save_cl_bottom:&save_cl_top;
+	save_task->cl_arg = descr;
+
+	/* Saving our border... */
+	save_task->buffers[0].handle = descr->layers_handle[0];
+	save_task->buffers[0].mode = STARPU_R;
+	save_task->buffers[1].handle = descr->layers_handle[1];
+	save_task->buffers[1].mode = STARPU_R;
+
+	/* ... to the neighbour's copy */
+	struct block_description *neighbour = descr->boundary_blocks[(1+dir)/2];
+	save_task->buffers[2].handle = neighbour->boundaries_handle[(1-dir)/2][0];
+	save_task->buffers[2].mode = STARPU_W;
+	save_task->buffers[3].handle = neighbour->boundaries_handle[(1-dir)/2][1];
+	save_task->buffers[3].mode = STARPU_W;
+
+	/* Bind */
+	if (iter <= BIND_LAST)
+		save_task->execute_on_a_specific_worker = get_bind_tasks();
+	save_task->workerid = descr->preferred_worker;
+
+	int ret = starpu_task_submit(save_task);
+	if (ret)
+	{
+		fprintf(stderr, "Could not submit task save: %d\n", ret);
+		STARPU_ASSERT(0);
+	}
+}
+
+/* R(z) = local & R(z+d) != local */
+/* We need to send our save over MPI */
+
+static void send_done(void *arg) {
+	uintptr_t z = (uintptr_t) arg;
+	DEBUG("DO SEND %d\n", (int)z);
+}
+
+#ifdef STARPU_USE_MPI
+/* Post MPI send */
+static void create_task_save_mpi_send(unsigned iter, unsigned z, int dir, unsigned local_rank)
+{
+	struct block_description *descr = get_block_description(z);
+	STARPU_ASSERT(descr->mpi_node == local_rank);
+
+	struct block_description *neighbour = descr->boundary_blocks[(1+dir)/2];
+	int dest = neighbour->mpi_node;
+	STARPU_ASSERT(neighbour->mpi_node != local_rank);
+
+	/* Send neighbour's border copy to the neighbour */
+	starpu_data_handle handle0 = neighbour->boundaries_handle[(1-dir)/2][0];
+	starpu_data_handle handle1 = neighbour->boundaries_handle[(1-dir)/2][1];
+
+	starpu_mpi_isend_detached(handle0, dest, MPI_TAG0(z, iter, dir), MPI_COMM_WORLD, send_done, (void*)(uintptr_t)z);
+	starpu_mpi_isend_detached(handle1, dest, MPI_TAG1(z, iter, dir), MPI_COMM_WORLD, send_done, (void*)(uintptr_t)z);
+}
+
+/* R(z) != local & R(z+d) = local */
+/* We need to receive over MPI */
+
+static void recv_done(void *arg) {
+	uintptr_t z = (uintptr_t) arg;
+	DEBUG("DO RECV %d\n", (int)z);
+}
+
+/* Post MPI recv */
+static void create_task_save_mpi_recv(unsigned iter, unsigned z, int dir, unsigned local_rank)
+{
+	struct block_description *descr = get_block_description(z);
+	STARPU_ASSERT(descr->mpi_node != local_rank);
+
+	struct block_description *neighbour = descr->boundary_blocks[(1+dir)/2];
+	int source = descr->mpi_node;
+	STARPU_ASSERT(neighbour->mpi_node == local_rank);
+
+	/* Receive our neighbour's border in our neighbour copy */
+	starpu_data_handle handle0 = neighbour->boundaries_handle[(1-dir)/2][0];
+	starpu_data_handle handle1 = neighbour->boundaries_handle[(1-dir)/2][1];
+
+	starpu_mpi_irecv_detached(handle0, source, MPI_TAG0(z, iter, dir), MPI_COMM_WORLD, recv_done, (void*)(uintptr_t)z);
+	starpu_mpi_irecv_detached(handle1, source, MPI_TAG1(z, iter, dir), MPI_COMM_WORLD, recv_done, (void*)(uintptr_t)z);
+}
+#endif // STARPU_USE_MPI
+
+/*
+ * Schedule saving boundaries of blocks to communication buffers
+ */
+void create_task_save(unsigned iter, unsigned z, int dir, unsigned local_rank)
+{
+	unsigned node_z = get_block_mpi_node(z);
+	unsigned node_z_and_d = get_block_mpi_node(z+dir);
+
+#ifdef STARPU_USE_MPI
+	if (node_z == local_rank)
+	{
+		/* Save data from update */
+		create_task_save_local(iter, z, dir, local_rank);
+		if (node_z_and_d != local_rank)
+		{ // R(z) = local & R(z+d) != local, We have to send the data
+			create_task_save_mpi_send(iter, z, dir, local_rank);
+		}
+
+	}
+	else {	// node_z != local_rank, this MPI node doesn't have the saved data
+		if (node_z_and_d == local_rank)
+		{
+			create_task_save_mpi_recv(iter, z, dir, local_rank);
+		}
+		else {  // R(z) != local & R(z+d) != local We don't have
+			// the saved data and don't need it, we shouldn't
+			// even have been called!
+			STARPU_ASSERT(0);
+		}
+	}
+#else // !STARPU_USE_MPI
+	STARPU_ASSERT((node_z == local_rank) && (node_z_and_d == local_rank));
+	create_task_save_local(iter, z, dir, local_rank);
+#endif // STARPU_USE_MPI
+}
+
+/*
+ * Schedule update computation in computation buffer
+ */
+
+void create_task_update(unsigned iter, unsigned z, unsigned local_rank)
+{
+	STARPU_ASSERT(iter != 0);
+
+	struct starpu_task *task = starpu_task_create();
+
+	unsigned niter = get_niter();
+
+	/* We are going to synchronize with the last tasks */
+	if (iter == niter) {
+		task->detach = 0;
+		task->use_tag = 1;
+		task->tag_id = TAG_FINISH(z);
+	}
+
+	unsigned old_layer = (K*(iter-1)) % 2;
+	unsigned new_layer = (old_layer + 1) % 2;
+
+	struct block_description *descr = get_block_description(z);
+	task->buffers[0].handle = descr->layers_handle[new_layer];
+	task->buffers[0].mode = STARPU_RW;
+	task->buffers[1].handle = descr->layers_handle[old_layer];
+	task->buffers[1].mode = STARPU_RW;
+
+	task->buffers[2].handle = descr->boundaries_handle[T][new_layer];
+	task->buffers[2].mode = STARPU_R;
+	task->buffers[3].handle = descr->boundaries_handle[T][old_layer];
+	task->buffers[3].mode = STARPU_R;
+
+	task->buffers[4].handle = descr->boundaries_handle[B][new_layer];
+	task->buffers[4].mode = STARPU_R;
+	task->buffers[5].handle = descr->boundaries_handle[B][old_layer];
+	task->buffers[5].mode = STARPU_R;
+
+	task->cl = &cl_update;
+	task->cl_arg = descr;
+
+	if (iter <= BIND_LAST)
+		task->execute_on_a_specific_worker = get_bind_tasks();
+	task->workerid = descr->preferred_worker;
+
+	int ret = starpu_task_submit(task);
+	if (ret)
+	{
+		fprintf(stderr, "Could not submit task update block: %d\n", ret);
+		STARPU_ASSERT(0);
+	}
+}
+
+/* Dummy empty codelet taking one buffer */
+static void null_func(void *descr[] __attribute__((unused)), void *arg __attribute__((unused))) { }
+static starpu_codelet null = {
+	.where = STARPU_CPU|STARPU_CUDA,
+	.cpu_func = null_func,
+	.cuda_func = null_func,
+	.nbuffers = 2
+};
+
+void create_start_task(int z, int dir) {
+	/* Dumb task depending on the init task and simulating writing the
+	   neighbour buffers, to avoid communications and computation running
+	   before we start measuring time */
+	struct starpu_task *wait_init = starpu_task_create();
+	struct block_description *descr = get_block_description(z);
+	starpu_tag_t tag_init = TAG_INIT_TASK;
+	wait_init->cl = &null;
+	wait_init->use_tag = 1;
+	wait_init->tag_id = TAG_START(z, dir);
+	wait_init->buffers[0].handle = descr->boundaries_handle[(1+dir)/2][0];
+	wait_init->buffers[0].mode = STARPU_W;
+	wait_init->buffers[1].handle = descr->boundaries_handle[(1+dir)/2][1];
+	wait_init->buffers[1].mode = STARPU_W;
+	starpu_tag_declare_deps_array(wait_init->tag_id, 1, &tag_init);
+
+	int ret = starpu_task_submit(wait_init);
+	if (ret)
+	{
+		fprintf(stderr, "Could not submit task initial wait: %d\n", ret);
+		STARPU_ASSERT(0);
+	}
+}
+
+
+/*
+ * Create all the tasks
+ */
+void create_tasks(int rank)
+{
+	unsigned iter;
+	unsigned bz;
+	int niter = get_niter();
+	int nbz = get_nbz();
+
+	for (bz = 0; bz < nbz; bz++) {
+		if ((get_block_mpi_node(bz) == rank) || (get_block_mpi_node(bz+1) == rank))
+			create_start_task(bz, +1);
+		if ((get_block_mpi_node(bz) == rank) || (get_block_mpi_node(bz-1) == rank))
+			create_start_task(bz, -1);
+	}
+
+	for (iter = 0; iter <= niter; iter++)
+	for (bz = 0; bz < nbz; bz++)
+	{
+		if ((iter > 0) && (get_block_mpi_node(bz) == rank))
+			create_task_update(iter, bz, rank);
+
+		if (iter != niter)
+		{
+			if ((get_block_mpi_node(bz) == rank) || (get_block_mpi_node(bz+1) == rank))
+				create_task_save(iter, bz, +1, rank);
+	
+			if ((get_block_mpi_node(bz) == rank) || (get_block_mpi_node(bz-1) == rank))
+				create_task_save(iter, bz, -1, rank);
+		}
+	}
+}
+
+/*
+ * Wait for termination
+ */
+void wait_end_tasks(int rank)
+{
+	unsigned bz;
+	int nbz = get_nbz();
+
+	for (bz = 0; bz < nbz; bz++)
+	{
+		if (get_block_mpi_node(bz) == rank)
+		{
+			/* Wait for the task producing block "bz" */
+			starpu_tag_wait(TAG_FINISH(bz));
+
+			/* Get the result back to memory */
+			struct block_description *block = get_block_description(bz);
+			starpu_data_acquire(block->layers_handle[0], STARPU_R);
+			starpu_data_acquire(block->layers_handle[1], STARPU_R);
+		}
+	}
+}
+

+ 320 - 0
examples/stencil/stencil.c

@@ -0,0 +1,320 @@
+/*
+ * StarPU
+ * Copyright (C) Université Bordeaux 1, CNRS 2009-2010 (see AUTHORS file)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation; either version 2.1 of the License, or (at
+ * your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * See the GNU Lesser General Public License in COPYING.LGPL for more details.
+ */
+
+#include <sys/time.h>
+#include "stencil.h"
+
+/* Main application */
+
+/* default parameter values */
+static unsigned  bind_tasks = 0;
+
+static unsigned niter = 32;
+static unsigned ticks = 100;
+
+#define SIZE 128
+
+/* Problem size */
+static unsigned sizex = SIZE;
+static unsigned sizey = SIZE;
+static unsigned sizez = 64*SIZE;
+
+/* Number of blocks (scattered over the different MPI processes) */
+unsigned nbz = 64;
+
+/*
+ *	Initialization
+ */
+
+unsigned get_bind_tasks(void)
+{
+	return bind_tasks;
+}
+
+unsigned get_nbz(void)
+{
+	return nbz;
+}
+
+unsigned get_niter(void)
+{
+	return niter;
+}
+
+unsigned get_ticks(void)
+{
+	return ticks;
+}
+
+static void parse_args(int argc, char **argv)
+{
+	int i;
+	for (i = 1; i < argc; i++) {
+		if (strcmp(argv[i], "-b") == 0) {
+			bind_tasks = 1;
+		}
+
+		if (strcmp(argv[i], "-nbz") == 0) {
+			nbz = atoi(argv[++i]);
+		}
+
+		if (strcmp(argv[i], "-sizex") == 0) {
+			sizex = atoi(argv[++i]);
+		}
+
+		if (strcmp(argv[i], "-sizey") == 0) {
+			sizey = atoi(argv[++i]);
+		}
+
+		if (strcmp(argv[i], "-sizez") == 0) {
+			sizez = atoi(argv[++i]);
+		}
+
+		if (strcmp(argv[i], "-niter") == 0) {
+			niter = atoi(argv[++i]);
+		}
+
+		if (strcmp(argv[i], "-ticks") == 0) {
+			ticks = atoi(argv[++i]);
+		}
+
+		if (strcmp(argv[i], "-h") == 0) {
+			 fprintf(stderr, "Usage : %s [options...]\n", argv[0]);
+			 fprintf(stderr, "\n");
+			 fprintf(stderr, "Options:\n");
+			 fprintf(stderr, "-b			bind tasks on CPUs/GPUs\n");
+			 fprintf(stderr, "-nbz <n>		Number of blocks on Z axis (%d by default)\n", nbz);
+			 fprintf(stderr, "-size[xyz] <size>	Domain size on x/y/z axis (%dx%dx%d by default)\n", sizex, sizey, sizez);
+			 fprintf(stderr, "-niter <n>		Number of iterations (%d by default)\n", niter);
+			 fprintf(stderr, "-ticks <t>		How often to put ticks in the output (ms, %d by default)\n", ticks);
+			 exit(0);
+		}
+	}
+}
+
+static void init_problem(int argc, char **argv, int rank, int world_size)
+{
+	parse_args(argc, argv);
+	create_blocks_array(sizex, sizey, sizez, nbz);
+
+	/* Select the MPI process which should compute the different blocks */
+	assign_blocks_to_mpi_nodes(world_size);
+
+	assign_blocks_to_workers(rank);
+
+	/* Allocate the different memory blocks, if used by the MPI process */
+	allocate_memory_on_node(rank);
+
+	display_memory_consumption(rank);
+
+	who_runs_what_len = 2*niter;
+	who_runs_what = calloc(nbz * who_runs_what_len, sizeof(*who_runs_what));
+	who_runs_what_index = calloc(nbz, sizeof(*who_runs_what_index));
+	last_tick = calloc(nbz, sizeof(*last_tick));
+}
+
+/*
+ *	Main body
+ */
+
+struct timeval start;
+struct timeval end;
+double timing; 
+
+void f(unsigned task_per_worker[STARPU_NMAXWORKERS])
+{
+	unsigned total = 0;
+	int worker;
+
+	for (worker = 0; worker < STARPU_NMAXWORKERS; worker++)
+		total += task_per_worker[worker];
+	for (worker = 0; worker < STARPU_NMAXWORKERS; worker++) {
+		if (task_per_worker[worker]) {
+			char name[32];
+			starpu_worker_get_name(worker, name, sizeof(name));
+			fprintf(stderr,"\t%s -> %d (%2.2f%%)\n", name, task_per_worker[worker], (100.0*task_per_worker[worker])/total);
+		}
+	}
+}
+
+unsigned global_workerid(unsigned local_workerid)
+{
+#ifdef STARPU_USE_MPI
+	int rank;
+	MPI_Comm_rank(MPI_COMM_WORLD, &rank);
+	unsigned workers_per_node = starpu_worker_get_count();
+
+	return (local_workerid + rank*workers_per_node);
+#else
+	return local_workerid;
+#endif
+}
+
+int main(int argc, char **argv)
+{
+	int rank;
+	int world_size;
+
+#ifdef STARPU_USE_MPI
+	int thread_support;
+	if (MPI_Init_thread(&argc, &argv, MPI_THREAD_SERIALIZED, &thread_support)) {
+		fprintf(stderr, "MPI_Init_thread failed\n");
+	}
+	if (thread_support == MPI_THREAD_FUNNELED)
+		fprintf(stderr,"Warning: MPI only has funneled thread support, not serialized, hoping this will work\n");
+	if (thread_support < MPI_THREAD_FUNNELED)
+		fprintf(stderr,"Warning: MPI does not have thread support!\n");
+	MPI_Comm_rank(MPI_COMM_WORLD, &rank);
+	MPI_Comm_size(MPI_COMM_WORLD, &world_size);
+#else
+	rank = 0;
+	world_size = 1;
+#endif
+
+	if (rank == 0)
+	{
+		fprintf(stderr, "Running on %d nodes\n", world_size);
+		fflush(stderr);
+	}
+
+	starpu_init(NULL);
+
+#ifdef STARPU_USE_MPI
+	starpu_mpi_initialize();
+#endif
+
+	init_problem(argc, argv, rank, world_size);
+
+	create_tasks(rank);
+
+#ifdef STARPU_USE_MPI
+	int barrier_ret = MPI_Barrier(MPI_COMM_WORLD);
+	STARPU_ASSERT(barrier_ret == MPI_SUCCESS);
+#endif
+	if (rank == 0)
+		fprintf(stderr, "GO !\n");
+
+	gettimeofday(&start, NULL);
+
+	starpu_tag_notify_from_apps(TAG_INIT_TASK);
+
+	wait_end_tasks(rank);
+
+	gettimeofday(&end, NULL);
+
+#ifdef STARPU_USE_MPI
+	barrier_ret = MPI_Barrier(MPI_COMM_WORLD);
+	STARPU_ASSERT(barrier_ret == MPI_SUCCESS);
+#endif
+
+#if 0
+	check(rank);
+#endif
+
+	//display_debug(nbz, niter, rank);
+
+#ifdef STARPU_USE_MPI
+	starpu_mpi_shutdown();
+#endif
+
+	/* timing in us */
+	timing = (double)((end.tv_sec - start.tv_sec)*1000000 + (end.tv_usec - start.tv_usec));
+
+	double min_timing = timing;
+	double max_timing = timing;
+	double sum_timing = timing;
+
+#ifdef STARPU_USE_MPI
+	int reduce_ret;
+
+	reduce_ret = MPI_Reduce(&timing, &min_timing, 1, MPI_DOUBLE, MPI_MIN, 0, MPI_COMM_WORLD);
+	STARPU_ASSERT(reduce_ret == MPI_SUCCESS);
+
+	reduce_ret = MPI_Reduce(&timing, &max_timing, 1, MPI_DOUBLE, MPI_MAX, 0, MPI_COMM_WORLD);
+	STARPU_ASSERT(reduce_ret == MPI_SUCCESS);
+
+	reduce_ret = MPI_Reduce(&timing, &sum_timing, 1, MPI_DOUBLE, MPI_SUM, 0, MPI_COMM_WORLD);
+	STARPU_ASSERT(reduce_ret == MPI_SUCCESS);
+
+	/* XXX we should do a gather instead, here we assume that non initialized values are still 0 */
+	int *who_runs_what_tmp = malloc(nbz * who_runs_what_len * sizeof(*who_runs_what));
+	reduce_ret = MPI_Reduce(who_runs_what, who_runs_what_tmp, nbz * who_runs_what_len, MPI_INT, MPI_SUM, 0, MPI_COMM_WORLD);
+	STARPU_ASSERT(reduce_ret == MPI_SUCCESS);
+
+	memcpy(who_runs_what, who_runs_what_tmp, nbz * who_runs_what_len * sizeof(*who_runs_what));
+
+	/* XXX we should do a gather instead, here we assume that non initialized values are still 0 */
+	int *who_runs_what_index_tmp = malloc(nbz * sizeof(*who_runs_what_index));
+	reduce_ret = MPI_Reduce(who_runs_what_index, who_runs_what_index_tmp, nbz, MPI_INT, MPI_SUM, 0, MPI_COMM_WORLD);
+	STARPU_ASSERT(reduce_ret == MPI_SUCCESS);
+
+	memcpy(who_runs_what_index, who_runs_what_index_tmp, nbz * sizeof(*who_runs_what_index));
+#endif
+
+	if (rank == 0)
+	{
+#if 1 
+		fprintf(stderr, "update:\n");
+		f(update_per_worker);
+		fprintf(stderr, "top:\n");
+		f(top_per_worker);
+		fprintf(stderr, "bottom:\n");
+		f(bottom_per_worker);
+#endif
+#if 1
+		unsigned nzblocks_per_process = (nbz + world_size - 1) / world_size;
+
+		unsigned bz, iter;
+		unsigned last;
+		for (iter = 0; iter < who_runs_what_len; iter++) {
+			last = 1;
+			for (bz = 0; bz < nbz; bz++) {
+				if ((bz % nzblocks_per_process) == 0)
+					fprintf(stderr, "| ");
+
+				if (who_runs_what_index[bz] <= iter)
+					fprintf(stderr,"_ ");
+				else {
+					last = 0;
+					if (who_runs_what[bz + iter * nbz] == -1)
+						fprintf(stderr,"* ");
+					else
+						fprintf(stderr, "%d ", who_runs_what[bz + iter * nbz]);
+				}
+			}
+			fprintf(stderr, "\n");
+
+			if (last)
+				break;
+		}
+#endif
+
+		fflush(stderr);
+
+		fprintf(stdout, "Computation took: %lf ms on %d MPI processes\n", max_timing/1000, world_size);
+		fprintf(stdout, "\tMIN : %lf ms\n", min_timing/1000);
+		fprintf(stdout, "\tMAX : %lf ms\n", max_timing/1000);
+		fprintf(stdout, "\tAVG : %lf ms\n", sum_timing/(world_size*1000));
+	}
+
+	starpu_shutdown();
+
+#ifdef STARPU_USE_MPI
+	MPI_Finalize();
+#endif
+
+	return 0;
+}

+ 138 - 0
examples/stencil/stencil.h

@@ -0,0 +1,138 @@
+/*
+ * StarPU
+ * Copyright (C) Université Bordeaux 1, CNRS 2009-2010 (see AUTHORS file)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation; either version 2.1 of the License, or (at
+ * your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * See the GNU Lesser General Public License in COPYING.LGPL for more details.
+ */
+
+#ifndef __STENCIL_H__
+#define __STENCIL_H__
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <starpu.h>
+#ifdef STARPU_USE_CUDA
+#include <starpu_cuda.h>
+#endif
+
+#ifndef __CUDACC__
+#ifdef STARPU_USE_MPI
+#include <mpi.h>
+#include <starpu_mpi.h>
+#endif
+#endif
+
+#define LIFE
+
+#ifdef LIFE
+#define TYPE	unsigned char
+extern void life_update(int bz, const TYPE *old, TYPE *newp, int nx, int ny, int nz, int ldy, int ldz, int iter);
+#else
+#define TYPE	float
+#endif
+
+#define K	1
+
+#define NDIRS 2
+
+/* Split only on the z axis to make things simple */
+typedef enum {
+	B = 0,
+	T = 1
+} direction;
+
+/* Description of a domain block */
+struct block_description {
+	/* Which MPI node should process that block ? */
+	unsigned mpi_node;
+	
+	unsigned preferred_worker;
+
+	unsigned bz;
+
+
+	/* For each of the following buffers, there are two (0/1) buffers to
+	 * make new/old switch costless. */
+
+	/* This is the computation buffer for this block, it includes
+	 * neighbours' border to make computation easier */
+	TYPE *layers[2];
+	starpu_data_handle layers_handle[2];
+
+	/* This is the "save" buffer, i.e. a copy of our neighbour's border.
+	 * This one is used for CPU/GPU or MPI communication (rather than the
+	 * whole domain block) */
+	TYPE *boundaries[NDIRS][2];
+	starpu_data_handle boundaries_handle[NDIRS][2];
+
+	/* Shortcut pointer to the neighbours */
+	struct block_description *boundary_blocks[NDIRS];
+};
+
+#define TAG_INIT_TASK			((starpu_tag_t)1)
+
+starpu_tag_t TAG_FINISH(int z);
+starpu_tag_t TAG_START(int z, int dir);
+int MPI_TAG0(int z, int iter, int dir);
+int MPI_TAG1(int z, int iter, int dir);
+
+#define MIN(a,b)	((a)<(b)?(a):(b))
+
+void create_blocks_array(unsigned sizex, unsigned sizey, unsigned sizez, unsigned nbz);
+struct block_description *get_block_description(int z);
+void assign_blocks_to_mpi_nodes(int world_size);
+void allocate_memory_on_node(int rank);
+void assign_blocks_to_workers(int rank);
+void create_tasks(int rank);
+void wait_end_tasks(int rank);
+void check(int rank);
+
+void display_memory_consumption(int rank);
+
+unsigned get_block_mpi_node(int z);
+unsigned get_block_size(int z);
+unsigned get_bind_tasks(void);
+
+unsigned get_nbz(void);
+unsigned get_niter(void);
+unsigned get_ticks(void);
+
+unsigned global_workerid(unsigned local_workerid);
+
+void create_task_update(unsigned iter, unsigned z, unsigned local_rank);
+void create_task_save(unsigned iter, unsigned z, int dir, unsigned local_rank);
+
+extern int starpu_mpi_initialize(void);
+extern int starpu_mpi_shutdown(void);
+
+/* kernels */
+extern starpu_codelet cl_update;
+extern starpu_codelet save_cl_bottom;
+extern starpu_codelet save_cl_top;
+
+extern unsigned update_per_worker[STARPU_NMAXWORKERS];
+extern unsigned top_per_worker[STARPU_NMAXWORKERS];
+extern unsigned bottom_per_worker[STARPU_NMAXWORKERS];
+
+extern struct timeval start;
+extern int who_runs_what_len;
+extern int *who_runs_what;
+extern int *who_runs_what_index;
+extern struct timeval *last_tick;
+
+#ifndef _externC
+#define _externC
+#endif
+_externC void cuda_life_update_host(int bz, const TYPE *old, TYPE *newp, int nx, int ny, int nz, int ldy, int ldz, int iter);
+_externC void cuda_shadow_host(int bz, TYPE *ptr, int nx, int ny, int nz, int ldy, int ldz, int i);
+
+#endif // __STENCIL_H__