Index: /soft/giet_vm/Makefile
===================================================================
--- /soft/giet_vm/Makefile	(revision 580)
+++ /soft/giet_vm/Makefile	(revision 581)
@@ -11,6 +11,6 @@
 #ARCH      ?= ../tsar-trunk-svn-2013/platforms/tsar_generic_iob
 ARCH       ?= ../../../tsar/platforms/tsar_generic_iob
-X_SIZE    ?= 2
-Y_SIZE    ?= 2
+X_SIZE    ?= 1
+Y_SIZE    ?= 1
 NB_PROCS  ?= 4
 NB_TTYS   ?= 1
@@ -20,5 +20,5 @@
 
 
-.PHONY: map.bin build clean
+.PHONY: clean map.bin build
 
 ### FAT parameters definition for Disk image
@@ -244,4 +244,5 @@
 	mcopy -o -i $(DISK_IMAGE) applications/transpose/images.raw ::/misc
 	mcopy -o -i $(DISK_IMAGE) applications/convol/philips_image.raw ::/misc
+	mcopy -o -i $(DISK_IMAGE) applications/display/lena.raw ::/misc
 	mcopy -o -i $(DISK_IMAGE) map.bin ::/
 ### Copy bootloader into sector 2 of disk image
@@ -268,10 +269,10 @@
 	mmd -o -i $(DISK_IMAGE) ::/misc
 	mmd -o -i $(DISK_IMAGE) ::/home
-	mcopy -o -i $(DISK_IMAGE) applications/transpose/images.raw ::/misc
-	mcopy -o -i $(DISK_IMAGE) applications/convol/philips_image.raw ::/misc
-	mcopy -o -i $(DISK_IMAGE) applications/display/lena.raw ::/misc
+#	mcopy -o -i $(DISK_IMAGE) applications/transpose/images.raw ::/misc
+#	mcopy -o -i $(DISK_IMAGE) applications/convol/philips_image.raw ::/misc
+#	mcopy -o -i $(DISK_IMAGE) applications/display/lena.raw ::/misc
 
 ### mapping generation: map.bin / map.xml / hard_config.h / giet_vsegs.ld
-map.bin hard_config.h giet_vsegs.ld: $(ARCH)/arch.py  applications/$(APP)/$(APP).py
+map.bin hard_config.h giet_vsegs.ld: $(ARCH)/arch.py  applications/$(APP)/$(APP).py $(DISK_IMAGE)
 	giet_python/genmap --arch=$(ARCH)     \
                        --x=$(X_SIZE)      \
@@ -284,5 +285,5 @@
                        --$(APP)           \
                        --xml=.
-	mcopy -o -i $(DISK_IMAGE) map.bin ::/
+#	mcopy -o -i $(DISK_IMAGE) map.bin ::/
 
 ### drivers compilation
@@ -435,8 +436,7 @@
 ### boot compilation
 ### Copy bootloader into sector 2 of disk image
-build/boot:
-	mkdir $@
 
 build/boot/boot.elf: $(BOOT_OBJS)            \
+                     $(DISK_IMAGE)           \
                      giet_boot/boot.ld       \
                      build/drivers/libdrivers.a | build/boot
@@ -460,4 +460,5 @@
 ### kernel compilation
 build/kernel/kernel.elf: $(KERNEL_OBJS)        \
+                         $(DISK_IMAGE)         \
                          giet_kernel/kernel.ld \
                          build/drivers/libdrivers.a
@@ -465,5 +466,5 @@
 	$(DU) -D $@ > $@.txt	
 	mmd -o -i $(DISK_IMAGE) ::/build/kernel || true
-	mcopy -o -i $(DISK_IMAGE) $@ ::/build/kernel
+#	mcopy -o -i $(DISK_IMAGE) $@ ::/build/kernel
 
 build/kernel/%.o: giet_kernel/%.c    \
@@ -536,9 +537,9 @@
 ########################################
 ### display application compilation
-build/display/display.elf: $(DISPLAY_OBJS) applications/display/display.ld hard_config.h
+build/display/display.elf: $(DISPLAY_OBJS) applications/display/display.ld hard_config.h $(DISK_IMAGE)
 	$(LD) -o $@ -T applications/display/display.ld $(DISPLAY_OBJS)
 	$(DU) -D $@ > $@.txt
 	mmd -o -i $(DISK_IMAGE) ::/build/display || true
-	mcopy -o -i $(DISK_IMAGE) $@ ::/build/display
+#	mcopy -o -i $(DISK_IMAGE) $@ ::/build/display
 
 build/display/main.o: applications/display/main.c hard_config.h
@@ -547,9 +548,9 @@
 ########################################
 ### router compilation
-build/router/router.elf: $(ROUTER_OBJS) applications/router/router.ld hard_config.h
+build/router/router.elf: $(ROUTER_OBJS) applications/router/router.ld hard_config.h $(DISK_IMAGE)
 	$(LD) -o $@ -T applications/router/router.ld $(ROUTER_OBJS)
 	$(DU) -D $@ > $@.txt
 	mmd -o -i $(DISK_IMAGE) ::/build/router || true
-	mcopy -o -i $(DISK_IMAGE) $@ ::/build/router
+#	mcopy -o -i $(DISK_IMAGE) $@ ::/build/router
 
 build/router/main.o: applications/router/main.c hard_config.h
@@ -558,9 +559,9 @@
 ########################################
 ### hello compilation
-build/hello/hello.elf: $(HELLO_OBJS) applications/hello/hello.ld hard_config.h
+build/hello/hello.elf: $(HELLO_OBJS) applications/hello/hello.ld hard_config.h $(DISK_IMAGE)
 	$(LD) -o $@ -T applications/hello/hello.ld $(HELLO_OBJS)
 	$(DU) -D $@ > $@.txt
 	mmd -o -i $(DISK_IMAGE) ::/build/hello || true
-	mcopy -o -i $(DISK_IMAGE) $@ ::/build/hello
+#	mcopy -o -i $(DISK_IMAGE) $@ ::/build/hello
 
 build/hello/main.o: applications/hello/main.c hard_config.h
@@ -569,9 +570,9 @@
 ########################################
 ### pgcd compilation
-build/pgcd/pgcd.elf: $(PGCD_OBJS) applications/pgcd/pgcd.ld hard_config.h
+build/pgcd/pgcd.elf: $(PGCD_OBJS) applications/pgcd/pgcd.ld hard_config.h $(DISK_IMAGE)
 	$(LD) -o $@ -T applications/pgcd/pgcd.ld $(PGCD_OBJS)
 	$(DU) -D $@ > $@.txt
 	mmd -o -i $(DISK_IMAGE) ::/build/pgcd || true
-	mcopy -o -i $(DISK_IMAGE) $@ ::/build/pgcd
+#	mcopy -o -i $(DISK_IMAGE) $@ ::/build/pgcd
 
 build/pgcd/main.o: applications/pgcd/main.c hard_config.h
@@ -580,9 +581,9 @@
 ########################################
 ### gameoflife compilation
-build/gameoflife/gameoflife.elf: $(GAMEOFLIFE_OBJS) applications/gameoflife/gameoflife.ld
+build/gameoflife/gameoflife.elf: $(GAMEOFLIFE_OBJS) applications/gameoflife/gameoflife.ld $(DISK_IMAGE)
 	$(LD) -o $@ -T applications/gameoflife/gameoflife.ld $(GAMEOFLIFE_OBJS)
 	$(DU) -D $@ > $@.txt
 	mmd -o -i $(DISK_IMAGE) ::/build/gameoflife || true
-	mcopy -o -i $(DISK_IMAGE) $@ ::/build/gameoflife
+#	mcopy -o -i $(DISK_IMAGE) $@ ::/build/gameoflife
 
 build/gameoflife/main.o: applications/gameoflife/main.c
@@ -591,9 +592,9 @@
 ########################################
 ### dhrystone compilation
-build/dhrystone/dhrystone.elf: $(DHRYSTONE_OBJS) applications/dhrystone/dhrystone.ld hard_config.h
+build/dhrystone/dhrystone.elf: $(DHRYSTONE_OBJS) applications/dhrystone/dhrystone.ld hard_config.h $(DISK_IMAGE)
 	$(LD) -o $@ -T applications/dhrystone/dhrystone.ld $(DHRYSTONE_OBJS)
 	$(DU) -D $@ > $@.txt
 	mmd -o -i $(DISK_IMAGE) ::/build/dhrystone || true
-	mcopy -o -i $(DISK_IMAGE) $@ ::/build/dhrystone
+#	mcopy -o -i $(DISK_IMAGE) $@ ::/build/dhrystone
 
 build/dhrystone/dhry_1.o: applications/dhrystone/dhry_1.c hard_config.h
@@ -605,53 +606,53 @@
 ########################################
 ### sort compilation
-build/sort/sort.elf: $(SORT_OBJS) applications/sort/sort.ld hard_config.h 
+build/sort/sort.elf: $(SORT_OBJS) applications/sort/sort.ld hard_config.h $(DISK_IMAGE)
 	$(LD) -o $@ -T applications/sort/sort.ld $(SORT_OBJS)
 	$(DU) -D $@ > $@.txt
 	mmd -o -i $(DISK_IMAGE) ::/build/sort || true
-	mcopy -o -i $(DISK_IMAGE) $@ ::/build/sort
-
-build/sort/main.o: applications/sort/main.c
+#	mcopy -o -i $(DISK_IMAGE) $@ ::/build/sort
+
+build/sort/main.o: applications/sort/main.c hard_config.h
 	$(CC) $(USER_INCLUDE) $(CFLAGS) -c -o $@ $<
 
 ########################################
 ### transpose compilation
-build/transpose/transpose.elf: $(TRANSPOSE_OBJS) applications/transpose/transpose.ld hard_config.h
+build/transpose/transpose.elf: $(TRANSPOSE_OBJS) applications/transpose/transpose.ld hard_config.h $(DISK_IMAGE)
 	$(LD) -o $@ -T applications/transpose/transpose.ld $(TRANSPOSE_OBJS)
 	$(DU) -D $@ > $@.txt
 	mmd -o -i $(DISK_IMAGE) ::/build/transpose || true
-	mcopy -o -i $(DISK_IMAGE) $@ ::/build/transpose
-
-build/transpose/main.o: applications/transpose/main.c
+#	mcopy -o -i $(DISK_IMAGE) $@ ::/build/transpose
+
+build/transpose/main.o: applications/transpose/main.c hard_config.h
 	$(CC) $(USER_INCLUDE) $(CFLAGS) -c -o $@ $<
 
 ########################################
 ### convol compilation
-build/convol/convol.elf: $(CONVOL_OBJS) applications/convol/convol.ld hard_config.h
+build/convol/convol.elf: $(CONVOL_OBJS) applications/convol/convol.ld hard_config.h $(DISK_IMAGE)
 	$(LD) -o $@ -T applications/convol/convol.ld $(CONVOL_OBJS)
 	$(DU) -D $@ > $@.txt
 	mmd -o -i $(DISK_IMAGE) ::/build/convol || true
-	mcopy -o -i $(DISK_IMAGE) $@ ::/build/convol
-
-build/convol/main.o: applications/convol/main.c
+#	mcopy -o -i $(DISK_IMAGE) $@ ::/build/convol
+
+build/convol/main.o: applications/convol/main.c hard_config.h
 	$(CC) $(USER_INCLUDE) $(CFLAGS) -O0 -c -o $@ $<
 
 ########################################
 ### classif compilation
-build/classif/classif.elf: $(CLASSIF_OBJS) applications/classif/classif.ld hard_config.h
+build/classif/classif.elf: $(CLASSIF_OBJS) applications/classif/classif.ld hard_config.h $(DISK_IMAGE)
 	$(LD) -o $@ -T applications/classif/classif.ld $(CLASSIF_OBJS)
 	$(DU) -D $@ > $@.txt
 	mmd -o -i $(DISK_IMAGE) ::/build/classif || true
-	mcopy -o -i $(DISK_IMAGE) $@ ::/build/classif
-
-build/classif/main.o: applications/classif/main.c
+#	mcopy -o -i $(DISK_IMAGE) $@ ::/build/classif
+
+build/classif/main.o: applications/classif/main.c hard_config.h
 	$(CC) $(USER_INCLUDE) $(CFLAGS) -O0 -c -o $@ $<
 
 ########################################
 ### coproc compilation
-build/coproc/coproc.elf: $(COPROC_OBJS) applications/coproc/coproc.ld hard_config.h
+build/coproc/coproc.elf: $(COPROC_OBJS) applications/coproc/coproc.ld hard_config.h $(DISK_IMAGE)
 	$(LD) -o $@ -T applications/coproc/coproc.ld $(COPROC_OBJS)
 	$(DU) -D $@ > $@.txt
 	mmd -o -i $(DISK_IMAGE) ::/build/coproc || true
-	mcopy -o -i $(DISK_IMAGE) $@ ::/build/coproc
+#	mcopy -o -i $(DISK_IMAGE) $@ ::/build/coproc
 
 build/coproc/main.o: applications/coproc/main.c
Index: /soft/giet_vm/applications/ocean/Makefile
===================================================================
--- /soft/giet_vm/applications/ocean/Makefile	(revision 581)
+++ /soft/giet_vm/applications/ocean/Makefile	(revision 581)
@@ -0,0 +1,1 @@
+link Makefile.giet
Index: /soft/giet_vm/applications/ocean/Makefile.config.giet
===================================================================
--- /soft/giet_vm/applications/ocean/Makefile.config.giet	(revision 581)
+++ /soft/giet_vm/applications/ocean/Makefile.config.giet	(revision 581)
@@ -0,0 +1,88 @@
+
+#------------------------------------------------------------------------------
+# Default plateform architecture and default CPU
+#------------------------------------------------------------------------------
+CPU         = mipsel
+CCTOOLS	    = /opt/mipsel-toolchain
+GIET_DISTRIB= $(PWD)/../..
+
+#------------------------------------------------------------------------------
+# CC tools and parameters
+#------------------------------------------------------------------------------
+DIR_INC  = $(GIET_DISTRIB)/giet_libs
+DIR_LIB  = $(GIET_DISTRIB)/build/libs
+GCC_LIB  = $(CCTOOLS)/lib
+CC       = $(CCTOOLS)/bin/$(CPU)-unknown-elf-gcc
+AR       = $(CCTOOLS)/bin/$(CPU)-unknown-elf-ar
+AS       = $(CCTOOLS)/bin/$(CPU)-unknown-elf-as
+OD       = $(CCTOOLS)/bin/$(CPU)-unknown-elf-objdump
+OCPY     = $(CCTOOLS)/bin/$(CPU)-unknown-elf-objcopy
+LD       = $(CCTOOLS)/bin/$(CPU)-unknown-elfld
+NM       = $(CCTOOLS)/bin/$(CPU)-unknown-elf-nm
+
+OBJ=$(DIR_LIB)/malloc.o $(DIR_LIB)/stdio.o $(DIR_LIB)/user_barrier.o $(DIR_LIB)/user_lock.o $(DIR_LIB)/stdlib.o $(DIR_LIB)/user_sqt_lock.o
+
+
+BASEDIR := $(PWD)
+MACROS := $(BASEDIR)/null_macros/c.m4.null.GIET
+M4 := m4 -s -Ulen -Uindex
+
+CFLAGSW := -Wmissing-prototypes -Wmissing-declarations -Wredundant-decls -Wdisabled-optimization -Winline -Wpointer-arith -Wsign-compare -Wendif-labels
+CFLAGSCPU = -mips32 -EL -G0 -mhard-float
+CFLAGS := $(CFLAGS) -O2 -g -Wall -fomit-frame-pointer $(CFLAGSW) $(CFLAGSCPU) -I$(DIR_INC) -I$(GIET_DISTRIB)
+
+
+ifneq ($(ADD-LDSCRIPT),)
+LDSCRIPT=$(ADD-LDSCRIPT)
+else
+LDSCRIPT=ocean.ld
+endif
+
+#LDFLAGS := $(LDFLAGS) -L$(DIR_LIB) -L$(GCC_LIB) $(CPU-LFLAGS) -T$(LDSCRIPT) $(OBJ) $(ADD-LIBS) \
+#	-lpthread -lgomp -lc $(ADD-LIBS) -lgomp -lpthread -lm -lc -lgcc --hash-style=sysv
+LDFLAGS := $(LDFLAGS) -L$(DIR_LIB) -L$(GCC_LIB) $(CPU-LFLAGS) -T$(LDSCRIPT) -lmath $(OBJ) $(ADD-LIBS)
+
+
+
+
+ifeq ($(TARGET),)
+	$(error *** Error: Variable TARGET must be defined before calling Makefile.config)
+endif
+
+ifeq ($(OBJS),)
+	$(error *** Error: Variable OBJS must be defined before calling Makefile.config)
+endif
+
+ifneq ($(CPU),mipsel)
+	$(error *** Error: Variable CPU must be equal to \'mipsel\' when calling this Makefile)
+endif
+
+
+
+#------------------------------------------------------------------------------
+# Building rules
+#------------------------------------------------------------------------------
+
+.PHONY: clean
+
+
+all: $(TARGET)
+
+$(TARGET): $(OBJS)
+	$(LD) -o $@ $^ $(LDFLAGS)
+
+%.h: %.H
+	$(M4) $(MACROS) $< > $@
+
+%.c: %.C $(MACROS)
+	$(M4) $(MACROS) $< > $@
+
+%.o: %.c $(MACROS)
+	$(CC) -c $(CFLAGS) -o $@ $<
+
+
+clean:
+	$(RM) -f *.c *.h *.o *.pyc $(TARGET)
+
+
+
Index: /soft/giet_vm/applications/ocean/Makefile.config.natif
===================================================================
--- /soft/giet_vm/applications/ocean/Makefile.config.natif	(revision 581)
+++ /soft/giet_vm/applications/ocean/Makefile.config.natif	(revision 581)
@@ -0,0 +1,32 @@
+CC := gcc
+CFLAGS := $(CFLAGS) -O0 -pthread -D_POSIX_C_SOURCE=200112 -g -Wall -W -Wmissing-prototypes \
+	-Wmissing-declarations -Wredundant-decls -Wdisabled-optimization \
+	-Winline -Wpointer-arith -Wsign-compare -Wendif-labels
+LDFLAGS := $(LDFLAGS) -lm
+
+BASEDIR := $(PWD)
+MACROS := $(BASEDIR)/null_macros/c.m4.null.POSIX
+M4 := m4 -s -Ulen -Uindex
+
+.PHONY: clean
+
+
+all: $(TARGET)
+
+$(TARGET): $(OBJS)
+	$(CC) $(OBJS) $(CFLAGS) -o $(TARGET) $(LDFLAGS)
+
+
+%.h: %.H $(MACROS)
+	$(M4) $(MACROS) $< > $@
+
+%.c: %.C $(MACROS)
+	$(M4) $(MACROS) $< > $@
+
+%.o: %.c
+	$(CC) -c $(CFLAGS) -o $@ $<
+
+clean:
+	rm -rf *.c *.h *.o $(TARGET)
+
+
Index: /soft/giet_vm/applications/ocean/Makefile.giet
===================================================================
--- /soft/giet_vm/applications/ocean/Makefile.giet	(revision 581)
+++ /soft/giet_vm/applications/ocean/Makefile.giet	(revision 581)
@@ -0,0 +1,15 @@
+TARGET = ocean.elf
+OBJS = jacobcalc.o jacobcalc2.o laplacalc.o linkup.o main.o multi.o slave1.o slave2.o subblock.o giet_utils.o
+
+include Makefile.config.giet
+
+jacobcalc.o: jacobcalc.c decs.h giet_utils.h
+linkup.o: linkup.c decs.h giet_utils.h
+slave1.o: slave1.c decs.h giet_utils.h
+jacobcalc2.o: jacobcalc2.c decs.h giet_utils.h
+main.o: main.c decs.h giet_utils.h
+slave2.o: slave2.c decs.h giet_utils.h
+laplacalc.o: laplacalc.c decs.h giet_utils.h
+multi.o: multi.c decs.h giet_utils.h
+subblock.o: subblock.c decs.h giet_utils.h
+giet_utils.o: giet_utils.c giet_utils.h
Index: /soft/giet_vm/applications/ocean/Makefile.natif
===================================================================
--- /soft/giet_vm/applications/ocean/Makefile.natif	(revision 581)
+++ /soft/giet_vm/applications/ocean/Makefile.natif	(revision 581)
@@ -0,0 +1,15 @@
+TARGET = ocean
+OBJS = jacobcalc.o jacobcalc2.o laplacalc.o linkup.o main.o multi.o slave1.o slave2.o subblock.o global.o
+
+include Makefile.config.natif
+
+jacobcalc.o: jacobcalc.c decs.h
+linkup.o: linkup.c decs.h
+slave1.o: slave1.c decs.h
+jacobcalc2.o: jacobcalc2.c decs.h
+main.o: main.c decs.h
+slave2.o: slave2.c decs.h
+laplacalc.o: laplacalc.c decs.h
+multi.o: multi.c decs.h
+subblock.o: subblock.c decs.h
+global.o: global.c
Index: /soft/giet_vm/applications/ocean/README.ocean
===================================================================
--- /soft/giet_vm/applications/ocean/README.ocean	(revision 581)
+++ /soft/giet_vm/applications/ocean/README.ocean	(revision 581)
@@ -0,0 +1,83 @@
+GENERAL INFORMATION:
+
+The OCEAN program simulates large-scale ocean movements based on eddy and
+boundary currents, and is an enhanced version of the SPLASH Ocean code.
+A description of the functionality of this code can be found in the 
+original SPLASH report.  The implementations contained in SPLASH-2 
+differ from the original SPLASH implementation in the following ways:
+
+  (1) The SPLASH-2 implementations are written in C rather than 
+      FORTRAN.
+  (2) Grids are partitioned into square-like subgrids rather than 
+      groups of columns to improve the communication to computation 
+      ratio.
+  (3) The SOR solver in the SPLASH Ocean code has been replaced with a
+      restricted Red-Black Gauss-Seidel Multigrid solver based on that 
+      presented in:
+
+      Brandt, A. Multi-Level Adaptive Solutions to Boundary-Value Problems.
+           Mathematics of Computation, 31(138):333-390, April 1977.
+
+      The solver is restricted so that each processor has as least two
+      grid points in each dimension in each grid subpartition.
+
+Two implementations are provided in the SPLASH-2 distribution:
+
+  (1) Non-contiguous partition allocation
+
+      This implementation (contained in the non_contiguous_partitions
+      subdirectory) implements the grids to be operated on with
+      two-dimensional arrays.  This data structure prevents partitions 
+      from being allocated contiguously, but leads to a conceptually 
+      simple programming implementation.
+
+  (2) Contiguous partition allocation
+
+      This implementation (contained in the contiguous_partitions 
+      subdirectory) implements the grids to be operated on with
+      3-dimensional arrays.  The first dimension specifies the processor
+      which owns the partition, and the second and third dimensions 
+      specify the x and y offset within a partition.  This data structure 
+      allows partitions to be allocated contiguously and entirely in the 
+      local memory of processors that "own" them, thus enhancing data
+      locality properties.
+
+The contiguous partition allocation implementation is described in:
+
+Woo, S. C., Singh, J. P., and Hennessy, J. L.  The Performance Advantages
+     of Integrating Message Passing in Cache-Coherent Multiprocessors.
+     Technical Report CSL-TR-93-593, Stanford University, December 1993.
+
+A detailed description of both versions will appear in the SPLASH-2 report.
+The non-contiguous partition allocation implementation is conceptually
+similar, except for the use of statically allocated 2-dimensional arrays.
+
+These programs work under both the Unix FORK and SPROC models.
+
+RUNNING THE PROGRAM:
+
+To see how to run the program, please see the comment at the top of the
+file main.C, or run the application with the "-h" command line option.
+Five command line parameters can be specified, of which the ones which
+would normally be changed are the number of grid points in each dimension,
+and the number of processors.  The number of grid points must be a
+(power of 2+2) in each dimension (e.g. 130, 258, etc.).  The number of
+processors must be a power of 2.  Timing information is printed out at 
+the end of the program.  The first timestep is considered part of the 
+initialization phase of the program, and hence is not included in the 
+"Total time without initialization."
+
+BASE PROBLEM SIZE:
+
+The base problem size for an upto-64 processor machine is a 258x258 grid.
+The default values should be used for other parameters (except the number
+of processors, which can be varied).  In addition, sample output files 
+for the default parameters for each version of the code are contained in 
+the file correct.out in each subdirectory.
+
+DATA DISTRIBUTION:
+
+Our "POSSIBLE ENHANCEMENT" comments in the source code tell where one
+might want to distribute data and how.  Data distribution has an impact
+on performance on the Stanford DASH multiprocessor.
+
Index: /soft/giet_vm/applications/ocean/decs.H
===================================================================
--- /soft/giet_vm/applications/ocean/decs.H	(revision 581)
+++ /soft/giet_vm/applications/ocean/decs.H	(revision 581)
@@ -0,0 +1,235 @@
+/*************************************************************************/
+/*                                                                       */
+/*  Copyright (c) 1994 Stanford University                               */
+/*                                                                       */
+/*  All rights reserved.                                                 */
+/*                                                                       */
+/*  Permission is given to use, copy, and modify this software for any   */
+/*  non-commercial purpose as long as this copyright notice is not       */
+/*  removed.  All other uses, including redistribution in whole or in    */
+/*  part, are forbidden without prior written permission.                */
+/*                                                                       */
+/*  This software is provided with absolutely no warranty and no         */
+/*  support.                                                             */
+/*                                                                       */
+/*************************************************************************/
+
+#define MASTER            0
+#define RED_ITER          0
+#define BLACK_ITER        1
+#define UP                0
+#define DOWN              1
+#define LEFT              2
+#define RIGHT             3
+#define UPLEFT            4
+#define UPRIGHT           5
+#define DOWNLEFT          6
+#define DOWNRIGHT         7
+#define PAGE_SIZE      4096
+
+struct multi_struct {
+    double err_multi;
+};
+
+extern struct multi_struct *multi;
+
+struct global_struct {
+    //long id;
+    unsigned long long starttime;
+    unsigned long long trackstart;
+    double psiai;
+    double psibi;
+};
+
+extern struct global_struct *global;
+
+extern double eig2;
+extern double ysca;
+extern long jmm1;
+extern const double pi;
+extern const double t0;
+
+extern double ****psi;
+extern double ****psim;
+extern double ***psium;
+extern double ***psilm;
+extern double ***psib;
+extern double ***ga;
+extern double ***gb;
+extern double ****work1;
+extern double ***work2;
+extern double ***work3;
+extern double ****work4;
+extern double ****work5;
+extern double ***work6;
+extern double ****work7;
+extern double ****temparray;
+extern double ***tauz;
+extern double ***oldga;
+extern double ***oldgb;
+extern double *f;
+extern double ****q_multi;
+extern double ****rhs_multi;
+
+struct locks_struct {
+    LOCKDEC(idlock)
+    LOCKDEC(psiailock)
+    LOCKDEC(psibilock)
+    LOCKDEC(donelock)
+    LOCKDEC(error_lock)
+    LOCKDEC(bar_lock)
+};
+
+extern struct locks_struct *locks;
+
+struct bars_struct {
+#if defined(MULTIPLE_BARRIERS)
+    BARDEC(iteration)
+    BARDEC(gsudn)
+    BARDEC(p_setup)
+    BARDEC(p_redph)
+    BARDEC(p_soln)
+    BARDEC(p_subph)
+    BARDEC(sl_prini)
+    BARDEC(sl_psini)
+    BARDEC(sl_onetime)
+    BARDEC(sl_phase_1)
+    BARDEC(sl_phase_2)
+    BARDEC(sl_phase_3)
+    BARDEC(sl_phase_4)
+    BARDEC(sl_phase_5)
+    BARDEC(sl_phase_6)
+    BARDEC(sl_phase_7)
+    BARDEC(sl_phase_8)
+    BARDEC(sl_phase_9)
+    BARDEC(sl_phase_10)
+    BARDEC(error_barrier)
+#else
+    BARDEC(barrier)
+#endif
+};
+
+extern struct bars_struct *bars;
+
+extern double factjacob;
+extern double factlap;
+
+struct Global_Private {
+    char *pad;                  //[PAGE_SIZE];
+    long *rel_num_x;
+    long *rel_num_y;
+    long *eist;
+    long *ejst;
+    long *oist;
+    long *ojst;
+    long *rlist;
+    long *rljst;
+    long *rlien;
+    long *rljen;
+    long *rownum;
+    long *colnum;
+    long *neighbors;            //[8];
+    long *lpid;
+    double *multi_time;
+    double *total_time;
+    double *sync_time;
+    double *process_time;
+    double *steps_time;         //[10]
+    double *step_start;
+};
+
+extern struct Global_Private *gp;
+
+extern double *i_int_coeff;
+extern double *j_int_coeff;
+extern long xprocs;
+extern long yprocs;
+
+extern long numlev;
+extern long *imx;
+extern long *jmx;
+extern double tolerance;
+extern double *lev_res;
+extern double *lev_tol;
+extern const double maxwork;
+extern long *xpts_per_proc;
+extern long *ypts_per_proc;
+extern long minlevel;
+extern const double outday0;
+extern const double outday1;
+extern const double outday2;
+extern const double outday3;
+
+extern long nprocs;
+extern const double h1;
+extern const double h3;
+extern const double h;
+extern const double lf;
+extern double res;
+extern double dtau;
+extern const double f0;
+extern const double beta;
+extern const double gpr;
+extern long oim;
+extern long im;
+extern long jm;
+extern long do_stats;
+extern long do_output;
+extern long *multi_times;
+extern long *total_times;
+
+/*
+ * jacobcalc.C
+ */
+void jacobcalc (double ***x, double ***y, double ***z, long pid, long firstrow, long lastrow, long firstcol, long lastcol);
+
+/*
+ * jacobcalc2.C
+ */
+void jacobcalc2 (double ****x, double ****y, double ****z, long psiindex, long pid, long firstrow, long lastrow, long firstcol, long lastcol);
+
+/*
+ * laplacalc.C
+ */
+void laplacalc (long procid, double ****x, double ****z, long psiindex, long firstrow, long lastrow, long firstcol, long lastcol);
+
+/*
+ * linkup.C
+ */
+void link_all (void);
+void linkup (double **row_ptr);
+void link_multi (void);
+
+/*
+ * main.C
+ */
+long log_2 (long number);
+void printerr (char *s);
+
+/*
+ * multi.C
+ */
+void multig (long my_id);
+void relax (long k, double *err, long color, long my_num);
+void rescal (long kf, long my_num);
+void intadd (long kc, long my_num);
+void putz (long k, long my_num);
+void copy_borders (long k, long pid);
+void copy_rhs_borders (long k, long procid);
+void copy_red (long k, long procid);
+void copy_black (long k, long procid);
+
+/*
+ * slave1.C
+ */
+void slave (long *ptr_procid);
+
+/*
+ * slave2.C
+ */
+void slave2 (long procid, long firstrow, long lastrow, long numrows, long firstcol, long lastcol, long numcols);
+
+/*
+ * subblock.C
+ */
+void subblock (void);
Index: /soft/giet_vm/applications/ocean/giet_utils.C
===================================================================
--- /soft/giet_vm/applications/ocean/giet_utils.C	(revision 581)
+++ /soft/giet_vm/applications/ocean/giet_utils.C	(revision 581)
@@ -0,0 +1,279 @@
+/* DÃ©finitions des fonctions standard (simplifiÃ©es) utilisÃ©es par ocean pour GIET */
+
+#include <stdarg.h>
+#include <stdio.h>
+#include <malloc.h>
+#include <stdlib.h>
+
+EXTERN_ENV
+
+#include "decs.h"
+#include "giet_utils.h"
+
+FILE * stdout = "";
+FILE *stderr = "STDERR : ";
+
+extern double ****main_q_multi;
+extern double ****main_rhs_multi;
+extern double ****main_psi;
+extern double ****main_psim;
+extern double ***main_psium;
+extern double ***main_psilm;
+extern double ***main_psib;
+extern double ***main_ga;
+extern double ***main_gb;
+extern double ***main_oldga;
+extern double ***main_oldgb;
+extern double ****main_work1;
+extern double ***main_work2;
+extern double ***main_work3;
+extern double ****main_work4;
+extern double ****main_work5;
+extern double ***main_work6;
+extern double ****main_work7;
+extern long *main_imx;
+extern long *main_jmx;
+
+extern double *main_lev_res;
+extern double *main_lev_tol;
+extern double *main_i_int_coeff;
+extern double *main_j_int_coeff;
+extern long *main_xpts_per_proc;
+extern long *main_ypts_per_proc;
+extern long main_xprocs;
+extern long main_yprocs;
+extern long main_numlev;
+extern double main_eig2;
+extern long main_im;
+extern long main_jm;
+
+double ****work1 __attribute__ ((section("seg_ldata")));
+double ***work2 __attribute__ ((section("seg_ldata")));
+double ***work3 __attribute__ ((section("seg_ldata")));
+double ****work4 __attribute__ ((section("seg_ldata")));
+double ****work5 __attribute__ ((section("seg_ldata")));
+double ***work6 __attribute__ ((section("seg_ldata")));
+double ****work7 __attribute__ ((section("seg_ldata")));
+double ****psi __attribute__ ((section("seg_ldata")));
+double ****psim __attribute__ ((section("seg_ldata")));
+double ***psium __attribute__ ((section("seg_ldata")));
+double ***psilm __attribute__ ((section("seg_ldata")));
+double ***psib __attribute__ ((section("seg_ldata")));
+double ***ga __attribute__ ((section("seg_ldata")));
+double ***gb __attribute__ ((section("seg_ldata")));
+double ***oldga __attribute__ ((section("seg_ldata")));
+double ***oldgb __attribute__ ((section("seg_ldata")));
+double ****q_multi __attribute__ ((section("seg_ldata")));
+double ****rhs_multi __attribute__ ((section("seg_ldata")));
+long *imx __attribute__ ((section("seg_ldata")));
+long *jmx __attribute__ ((section("seg_ldata")));
+double *f __attribute__ ((section("seg_ldata")));
+struct Global_Private *gp;
+
+double *lev_res __attribute__ ((section("seg_ldata")));
+double *lev_tol __attribute__ ((section("seg_ldata")));
+double *i_int_coeff __attribute__ ((section("seg_ldata")));
+double *j_int_coeff __attribute__ ((section("seg_ldata")));
+long *xpts_per_proc __attribute__ ((section("seg_ldata")));
+long *ypts_per_proc __attribute__ ((section("seg_ldata")));
+long xprocs __attribute__ ((section("seg_ldata")));
+long yprocs __attribute__ ((section("seg_ldata")));
+long numlev __attribute__ ((section("seg_ldata")));
+double eig2 __attribute__ ((section("seg_ldata")));
+long im __attribute__ ((section("seg_ldata")));
+long jm __attribute__ ((section("seg_ldata")));
+
+unsigned int nclusters_x __attribute__ ((section("seg_ldata")));
+unsigned int nclusters_y __attribute__ ((section("seg_ldata")));
+unsigned int procs_per_cluster __attribute__ ((section("seg_ldata")));
+
+volatile long heap_inited = 0;
+volatile int run_threads = 0;
+
+//Entry point for all threads (except main)
+//  waiting allocs and inits of main then copy read-only tabs in ldata segment (replicated)
+//  some read-write tabs are also replicated, but not entirely : only pointers
+__attribute__ ((constructor)) void thread()
+{
+    unsigned long size;
+    long id = (long) giet_thread_id();
+
+    unsigned int cx, cy, lp;
+
+    giet_proc_xyp(&cx, &cy, &lp);
+    giet_shr_printf("Thread %d (%d:%d.%d) waiting\n", id, cx, cy, lp);
+
+    if (lp == 0) {
+        
+        giet_procs_number(&nclusters_x, &nclusters_y, &procs_per_cluster);
+        heap_init(cx, cy);
+
+        while (heap_inited != id) {
+            asm volatile ("nop\r\n");
+        }
+        heap_inited += procs_per_cluster;
+        
+        
+        size = nprocs * sizeof(double ***);
+        rhs_multi = (double ****) G_MALLOC(size, id);
+        q_multi = (double ****) G_MALLOC(size, id);
+        psi = (double ****) G_MALLOC(size, id);
+        psim = (double ****) G_MALLOC(size, id);
+        work1 = (double ****) G_MALLOC(size, id);
+        work4 = (double ****) G_MALLOC(size, id);
+        work5 = (double ****) G_MALLOC(size, id);
+        work7 = (double ****) G_MALLOC(size, id);
+        
+        size = nprocs * sizeof(double **);
+        psium = (double ***) G_MALLOC(size, id);
+        psilm = (double ***) G_MALLOC(size, id);
+        psib = (double ***) G_MALLOC(size, id);
+        ga = (double ***) G_MALLOC(size, id);
+        gb = (double ***) G_MALLOC(size, id);
+        oldga = (double ***) G_MALLOC(size, id);
+        oldgb = (double ***) G_MALLOC(size, id);
+        work2 = (double ***) G_MALLOC(size, id);
+        work3 = (double ***) G_MALLOC(size, id);
+        work6 = (double ***) G_MALLOC(size, id);
+    }
+    
+    while (run_threads != 1) {
+        asm volatile ("nop\r\n");
+    }
+
+    *gp[id].lpid = lp;
+        
+    if (lp == 0) {
+        int i, j, k;
+        
+        xprocs = main_xprocs;
+        yprocs = main_yprocs;
+        numlev = main_numlev;
+        eig2 = main_eig2;
+        im = main_im;
+        jm = main_jm;
+
+        size = numlev * sizeof(long);
+        imx = (long *) G_MALLOC(size, id);
+        jmx = (long *) G_MALLOC(size, id);
+        xpts_per_proc = (long *) G_MALLOC(size, id);
+        ypts_per_proc = (long *) G_MALLOC(size, id);
+        
+        size = numlev * sizeof(double);
+        lev_res = (double *) G_MALLOC(size, id);
+        lev_tol = (double *) G_MALLOC(size, id);
+        i_int_coeff = (double *) G_MALLOC(size, id);
+        j_int_coeff = (double *) G_MALLOC(size, id);
+        
+        for(i=0;i<numlev;i++) {
+            imx[i] = main_imx[i];
+            jmx[i] = main_jmx[i];
+            lev_res[i] = main_lev_res[i];
+            lev_tol[i] = main_lev_tol[i];
+            i_int_coeff[i] = main_i_int_coeff[i];
+            j_int_coeff[i] = main_j_int_coeff[i];
+            xpts_per_proc[i] = main_xpts_per_proc[i];
+            ypts_per_proc[i] = main_ypts_per_proc[i];
+        }
+        
+        size = numlev * sizeof(double **);        
+        for (i = 0; i < nprocs; i++) {
+            
+            q_multi[i] = (double ***) G_MALLOC(size, id);
+            rhs_multi[i] = (double ***) G_MALLOC(size, id);
+
+            for (j = 0; j < numlev; j++) {
+            
+                rhs_multi[i][j] = (double **) G_MALLOC(((imx[j] - 2) / yprocs + 2) * sizeof(double *), id);
+                q_multi[i][j] = (double **) G_MALLOC(((imx[j] - 2) / yprocs + 2) * sizeof(double *), id);
+                for (k = 0; k < ((imx[j] - 2) / yprocs + 2); k++) {
+                    q_multi[i][j][k] = main_q_multi[i][j][k];
+                    rhs_multi[i][j][k] = main_rhs_multi[i][j][k];
+                }
+                
+            }
+            
+            work1[i] = main_work1[i];
+            work2[i] = main_work2[i];
+            work3[i] = main_work3[i];
+            work4[i] = main_work4[i];
+            work5[i] = main_work5[i];
+            work6[i] = main_work6[i];
+            work7[i] = main_work7[i];
+            psi[i] = main_psi[i];
+            psim[i] = main_psim[i];
+            psium[i] = main_psium[i];
+            psilm[i] = main_psilm[i];
+            psib[i] = main_psib[i];
+            ga[i] = main_ga[i];
+            gb[i] = main_gb[i];
+            oldga[i] = main_oldga[i];
+            oldgb[i] = main_oldgb[i];
+        }
+    }
+    giet_shr_printf("Thread %d launched\n", id);
+
+    slave(&id);
+
+    BARRIER(bars->barrier, nprocs)
+    
+    giet_exit("done.");
+}
+
+
+const char *optarg;
+
+int getopt(int argc, char *const *argv, const char *optstring)
+{
+    return -1;
+}
+
+//give the cluster coordinate by thread number
+//  if tid=-1, return the next cluster (round robin)
+void clusterXY(int tid, unsigned int *cx, unsigned int *cy)
+{
+    unsigned int cid;
+    static unsigned int x = 0, y = 0;
+
+    cid = tid / procs_per_cluster;
+
+    if (tid != -1) {
+        *cx = (cid / nclusters_y);
+        *cy = (cid % nclusters_y);
+        return;
+    }
+    
+    if (giet_thread_id() != 0) {
+        giet_exit("pseudo-random mapped malloc : thread 0 only");
+    }
+
+    x++;
+    if (x == nclusters_x) {
+        x = 0;
+        y++;
+        if (y == nclusters_y) {
+            y = 0;
+        }
+    }
+    *cx = x;
+    *cy = y;
+}
+
+void *ocean_malloc(unsigned long s, int tid)
+{
+    void *ptr;
+    unsigned int x, y;
+    clusterXY(tid, &x, &y);
+    ptr = remote_malloc(s, x, y);
+    giet_assert (ptr != 0, "Malloc failed");
+    return ptr;
+}
+
+void exit(int status)
+{
+    if (status) {
+        giet_exit("Done (status != 0)");
+    } else {
+        giet_exit("Done (ok)");
+    }
+}
Index: /soft/giet_vm/applications/ocean/giet_utils.H
===================================================================
--- /soft/giet_vm/applications/ocean/giet_utils.H	(revision 581)
+++ /soft/giet_vm/applications/ocean/giet_utils.H	(revision 581)
@@ -0,0 +1,33 @@
+#ifndef UTILS_H
+#define UTILS_H
+
+#include <stdio.h>
+
+
+
+extern volatile int run_threads;
+extern volatile long heap_inited;
+
+extern unsigned int nclusters_x;
+extern unsigned int nclusters_y;
+extern unsigned int procs_per_cluster;
+
+
+#define printf(...) giet_shr_printf(__VA_ARGS__)
+
+extern const char *optarg;
+
+int getopt (int argc, char *const *argv, const char *optstring);
+void exit (int status);
+void clusterXY (int tid, unsigned int *cx, unsigned int *cy);
+void *ocean_malloc (unsigned long s, int tid);
+unsigned int getLpid ();
+
+/** pseudo fprintf **/
+typedef char FILE;
+extern FILE *stdout;
+extern FILE *stderr;
+#define fprintf(prologue, ...)	printf("%s", prologue); \
+									printf(__VA_ARGS__);
+
+#endif
Index: /soft/giet_vm/applications/ocean/global.C
===================================================================
--- /soft/giet_vm/applications/ocean/global.C	(revision 581)
+++ /soft/giet_vm/applications/ocean/global.C	(revision 581)
@@ -0,0 +1,42 @@
+
+double ****work1;
+double ***work2;
+double ***work3;
+double ****work4;
+double ****work5;
+double ***work6;
+double ****work7;
+double ***tauz;
+
+double ****psi;
+double ****psim;
+double ***psium;
+double ***psilm;
+double ***psib;
+double ***ga;
+double ***gb;
+double ***oldga;
+double ***oldgb;
+
+double ****q_multi;
+double ****rhs_multi;
+
+long *imx;
+long *jmx;
+
+double *f;
+struct Global_Private *gp;
+
+
+double *lev_res;
+double *lev_tol;
+double *i_int_coeff;
+double *j_int_coeff;
+long *xpts_per_proc;
+long *ypts_per_proc;
+long xprocs;
+long yprocs;
+long numlev;
+double eig2;
+long im;
+long jm;
Index: /soft/giet_vm/applications/ocean/jacobcalc.C
===================================================================
--- /soft/giet_vm/applications/ocean/jacobcalc.C	(revision 581)
+++ /soft/giet_vm/applications/ocean/jacobcalc.C	(revision 581)
@@ -0,0 +1,339 @@
+/*************************************************************************/
+/*                                                                       */
+/*  Copyright (c) 1994 Stanford University                               */
+/*                                                                       */
+/*  All rights reserved.                                                 */
+/*                                                                       */
+/*  Permission is given to use, copy, and modify this software for any   */
+/*  non-commercial purpose as long as this copyright notice is not       */
+/*  removed.  All other uses, including redistribution in whole or in    */
+/*  part, are forbidden without prior written permission.                */
+/*                                                                       */
+/*  This software is provided with absolutely no warranty and no         */
+/*  support.                                                             */
+/*                                                                       */
+/*************************************************************************/
+
+/* Does the arakawa jacobian calculation (of the x and y matrices,
+   putting the results in the z matrix) for a subblock.  */
+
+EXTERN_ENV
+
+#include <stdio.h>
+#include <math.h>
+
+#include "decs.h"
+
+void jacobcalc(double ***x, double ***y, double ***z, long pid, long firstrow, long lastrow, long firstcol, long lastcol)
+{
+    double f1;
+    double f2;
+    double f3;
+    double f4;
+    double f5;
+    double f6;
+    double f7;
+    double f8;
+    long iindex;
+    long indexp1;
+    long indexm1;
+    long im1;
+    long ip1;
+    long i;
+    long j;
+    long jj;
+    double **t2a;
+    double **t2b;
+    double **t2c;
+    double *t1a;
+    double *t1b;
+    double *t1c;
+    double *t1d;
+    double *t1e;
+    double *t1f;
+    double *t1g;
+
+    t2a = (double **) z[pid];
+    if ((gp[pid].neighbors[UP] == -1) && (gp[pid].neighbors[LEFT] == -1)) {
+        t2a[0][0] = 0.0;
+    }
+    if ((gp[pid].neighbors[DOWN] == -1) && (gp[pid].neighbors[LEFT] == -1)) {
+        t2a[im - 1][0] = 0.0;
+    }
+    if ((gp[pid].neighbors[UP] == -1) && (gp[pid].neighbors[RIGHT] == -1)) {
+        t2a[0][jm - 1] = 0.0;
+    }
+    if ((gp[pid].neighbors[DOWN] == -1) && (gp[pid].neighbors[RIGHT] == -1)) {
+        t2a[im - 1][jm - 1] = 0.0;
+    }
+
+    t2a = (double **) x[pid];
+    jj = gp[pid].neighbors[UPLEFT];
+    if (jj != -1) {
+        t2a[0][0] = x[jj][im - 2][jm - 2];
+    }
+    jj = gp[pid].neighbors[UPRIGHT];
+    if (jj != -1) {
+        t2a[0][jm - 1] = x[jj][im - 2][1];
+    }
+    jj = gp[pid].neighbors[DOWNLEFT];
+    if (jj != -1) {
+        t2a[im - 1][0] = x[jj][1][jm - 2];
+    }
+    jj = gp[pid].neighbors[DOWNRIGHT];
+    if (jj != -1) {
+        t2a[im - 1][jm - 1] = x[jj][1][1];
+    }
+
+    t2a = (double **) y[pid];
+    jj = gp[pid].neighbors[UPLEFT];
+    if (jj != -1) {
+        t2a[0][0] = y[jj][im - 2][jm - 2];
+    }
+    jj = gp[pid].neighbors[UPRIGHT];
+    if (jj != -1) {
+        t2a[0][jm - 1] = y[jj][im - 2][1];
+    }
+    jj = gp[pid].neighbors[DOWNLEFT];
+    if (jj != -1) {
+        t2a[im - 1][0] = y[jj][1][jm - 2];
+    }
+    jj = gp[pid].neighbors[DOWNRIGHT];
+    if (jj != -1) {
+        t2a[im - 1][jm - 1] = y[jj][1][1];
+    }
+
+    t2a = (double **) x[pid];
+    if (gp[pid].neighbors[UP] == -1) {
+        jj = gp[pid].neighbors[LEFT];
+        if (jj != -1) {
+            t2a[0][0] = x[jj][0][jm - 2];
+        } else {
+            jj = gp[pid].neighbors[DOWN];
+            if (jj != -1) {
+                t2a[im - 1][0] = x[jj][1][0];
+            }
+        }
+        jj = gp[pid].neighbors[RIGHT];
+        if (jj != -1) {
+            t2a[0][jm - 1] = x[jj][0][1];
+        } else {
+            jj = gp[pid].neighbors[DOWN];
+            if (jj != -1) {
+                t2a[im - 1][jm - 1] = x[jj][1][jm - 1];
+            }
+        }
+    } else if (gp[pid].neighbors[DOWN] == -1) {
+        jj = gp[pid].neighbors[LEFT];
+        if (jj != -1) {
+            t2a[im - 1][0] = x[jj][im - 1][jm - 2];
+        } else {
+            jj = gp[pid].neighbors[UP];
+            if (jj != -1) {
+                t2a[0][0] = x[jj][im - 2][0];
+            }
+        }
+        jj = gp[pid].neighbors[RIGHT];
+        if (jj != -1) {
+            t2a[im - 1][jm - 1] = x[jj][im - 1][1];
+        } else {
+            jj = gp[pid].neighbors[UP];
+            if (jj != -1) {
+                t2a[0][jm - 1] = x[jj][im - 2][jm - 1];
+            }
+        }
+    } else if (gp[pid].neighbors[LEFT] == -1) {
+        jj = gp[pid].neighbors[UP];
+        if (jj != -1) {
+            t2a[0][0] = x[jj][im - 2][0];
+        }
+        jj = gp[pid].neighbors[DOWN];
+        if (jj != -1) {
+            t2a[im - 1][0] = x[jj][1][0];
+        }
+    } else if (gp[pid].neighbors[RIGHT] == -1) {
+        jj = gp[pid].neighbors[UP];
+        if (jj != -1) {
+            t2a[0][jm - 1] = x[jj][im - 2][jm - 1];
+        }
+        jj = gp[pid].neighbors[DOWN];
+        if (jj != -1) {
+            t2a[im - 1][jm - 1] = x[jj][1][jm - 1];
+        }
+    }
+
+    t2a = (double **) y[pid];
+    if (gp[pid].neighbors[UP] == -1) {
+        jj = gp[pid].neighbors[LEFT];
+        if (jj != -1) {
+            t2a[0][0] = y[jj][0][jm - 2];
+        } else {
+            jj = gp[pid].neighbors[DOWN];
+            if (jj != -1) {
+                t2a[im - 1][0] = y[jj][1][0];
+            }
+        }
+        jj = gp[pid].neighbors[RIGHT];
+        if (jj != -1) {
+            t2a[0][jm - 1] = y[jj][0][1];
+        } else {
+            jj = gp[pid].neighbors[DOWN];
+            if (jj != -1) {
+                t2a[im - 1][jm - 1] = y[jj][1][jm - 1];
+            }
+        }
+    } else if (gp[pid].neighbors[DOWN] == -1) {
+        jj = gp[pid].neighbors[LEFT];
+        if (jj != -1) {
+            t2a[im - 1][0] = y[jj][im - 1][jm - 2];
+        } else {
+            jj = gp[pid].neighbors[UP];
+            if (jj != -1) {
+                t2a[0][0] = y[jj][im - 2][0];
+            }
+        }
+        jj = gp[pid].neighbors[RIGHT];
+        if (jj != -1) {
+            t2a[im - 1][jm - 1] = y[jj][im - 1][1];
+        } else {
+            jj = gp[pid].neighbors[UP];
+            if (jj != -1) {
+                t2a[0][jm - 1] = y[jj][im - 2][jm - 1];
+            }
+        }
+    } else if (gp[pid].neighbors[LEFT] == -1) {
+        jj = gp[pid].neighbors[UP];
+        if (jj != -1) {
+            t2a[0][0] = y[jj][im - 2][0];
+        }
+        jj = gp[pid].neighbors[DOWN];
+        if (jj != -1) {
+            t2a[im - 1][0] = y[jj][1][0];
+        }
+    } else if (gp[pid].neighbors[RIGHT] == -1) {
+        jj = gp[pid].neighbors[UP];
+        if (jj != -1) {
+            t2a[0][jm - 1] = y[jj][im - 2][jm - 1];
+        }
+        jj = gp[pid].neighbors[DOWN];
+        if (jj != -1) {
+            t2a[im - 1][jm - 1] = y[jj][1][jm - 1];
+        }
+    }
+
+    j = gp[pid].neighbors[UP];
+    if (j != -1) {
+        t1a = (double *) t2a[0];
+        t1b = (double *) y[j][im - 2];
+        for (i = 1; i <= lastcol; i++) {
+            t1a[i] = t1b[i];
+        }
+    }
+    j = gp[pid].neighbors[DOWN];
+    if (j != -1) {
+        t1a = (double *) t2a[im - 1];
+        t1b = (double *) y[j][1];
+        for (i = 1; i <= lastcol; i++) {
+            t1a[i] = t1b[i];
+        }
+    }
+    j = gp[pid].neighbors[LEFT];
+    if (j != -1) {
+        t2b = (double **) y[j];
+        for (i = 1; i <= lastrow; i++) {
+            t2a[i][0] = t2b[i][jm - 2];
+        }
+    }
+    j = gp[pid].neighbors[RIGHT];
+    if (j != -1) {
+        t2b = (double **) y[j];
+        for (i = 1; i <= lastrow; i++) {
+            t2a[i][jm - 1] = t2b[i][1];
+        }
+    }
+
+    t2a = (double **) x[pid];
+    j = gp[pid].neighbors[UP];
+    if (j != -1) {
+        t1a = (double *) t2a[0];
+        t1b = (double *) x[j][im - 2];
+        for (i = 1; i <= lastcol; i++) {
+            t1a[i] = t1b[i];
+        }
+    }
+    j = gp[pid].neighbors[DOWN];
+    if (j != -1) {
+        t1a = (double *) t2a[im - 1];
+        t1b = (double *) x[j][1];
+        for (i = 1; i <= lastcol; i++) {
+            t1a[i] = t1b[i];
+        }
+    }
+    j = gp[pid].neighbors[LEFT];
+    if (j != -1) {
+        t2b = (double **) x[j];
+        for (i = 1; i <= lastrow; i++) {
+            t2a[i][0] = t2b[i][jm - 2];
+        }
+    }
+    j = gp[pid].neighbors[RIGHT];
+    if (j != -1) {
+        t2b = (double **) x[j];
+        for (i = 1; i <= lastrow; i++) {
+            t2a[i][jm - 1] = t2b[i][1];
+        }
+    }
+
+    t2a = (double **) x[pid];
+    t2b = (double **) y[pid];
+    t2c = (double **) z[pid];
+    for (i = firstrow; i <= lastrow; i++) {
+        ip1 = i + 1;
+        im1 = i - 1;
+        t1a = (double *) t2a[i];
+        t1b = (double *) t2b[i];
+        t1c = (double *) t2c[i];
+        t1d = (double *) t2b[ip1];
+        t1e = (double *) t2b[im1];
+        t1f = (double *) t2a[ip1];
+        t1g = (double *) t2a[im1];
+        for (iindex = firstcol; iindex <= lastcol; iindex++) {
+            indexp1 = iindex + 1;
+            indexm1 = iindex - 1;
+            f1 = (t1b[indexm1] + t1d[indexm1] - t1b[indexp1] - t1d[indexp1]) * (t1f[iindex] - t1a[iindex]);
+            f2 = (t1e[indexm1] + t1b[indexm1] - t1e[indexp1] - t1b[indexp1]) * (t1a[iindex] - t1g[iindex]);
+            f3 = (t1d[iindex] + t1d[indexp1] - t1e[iindex] - t1e[indexp1]) * (t1a[indexp1] - t1a[iindex]);
+            f4 = (t1d[indexm1] + t1d[iindex] - t1e[indexm1] - t1e[iindex]) * (t1a[iindex] - t1a[indexm1]);
+            f5 = (t1d[iindex] - t1b[indexp1]) * (t1f[indexp1] - t1a[iindex]);
+            f6 = (t1b[indexm1] - t1e[iindex]) * (t1a[iindex] - t1g[indexm1]);
+            f7 = (t1b[indexp1] - t1e[iindex]) * (t1g[indexp1] - t1a[iindex]);
+            f8 = (t1d[iindex] - t1b[indexm1]) * (t1a[iindex] - t1f[indexm1]);
+
+            t1c[iindex] = factjacob * (f1 + f2 + f3 + f4 + f5 + f6 + f7 + f8);
+        }
+    }
+
+    if (gp[pid].neighbors[UP] == -1) {
+        t1c = (double *) t2c[0];
+        for (j = firstcol; j <= lastcol; j++) {
+            t1c[j] = 0.0;
+        }
+    }
+    if (gp[pid].neighbors[DOWN] == -1) {
+        t1c = (double *) t2c[im - 1];
+        for (j = firstcol; j <= lastcol; j++) {
+            t1c[j] = 0.0;
+        }
+    }
+    if (gp[pid].neighbors[LEFT] == -1) {
+        for (j = firstrow; j <= lastrow; j++) {
+            t2c[j][0] = 0.0;
+        }
+    }
+    if (gp[pid].neighbors[RIGHT] == -1) {
+        for (j = firstrow; j <= lastrow; j++) {
+            t2c[j][jm - 1] = 0.0;
+        }
+    }
+
+}
Index: /soft/giet_vm/applications/ocean/jacobcalc2.C
===================================================================
--- /soft/giet_vm/applications/ocean/jacobcalc2.C	(revision 581)
+++ /soft/giet_vm/applications/ocean/jacobcalc2.C	(revision 581)
@@ -0,0 +1,341 @@
+/*************************************************************************/
+/*                                                                       */
+/*  Copyright (c) 1994 Stanford University                               */
+/*                                                                       */
+/*  All rights reserved.                                                 */
+/*                                                                       */
+/*  Permission is given to use, copy, and modify this software for any   */
+/*  non-commercial purpose as long as this copyright notice is not       */
+/*  removed.  All other uses, including redistribution in whole or in    */
+/*  part, are forbidden without prior written permission.                */
+/*                                                                       */
+/*  This software is provided with absolutely no warranty and no         */
+/*  support.                                                             */
+/*                                                                       */
+/*************************************************************************/
+
+/* Does the arakawa jacobian calculation (of the x and y matrices,
+   putting the results in the z matrix) for a subblock. */
+
+EXTERN_ENV
+
+#include <stdio.h>
+#include <math.h>
+
+#include "decs.h"
+
+void jacobcalc2(double ****x, double ****y, double ****z, long psiindex, long pid, long firstrow, long lastrow, long firstcol, long lastcol)
+{
+    double f1;
+    double f2;
+    double f3;
+    double f4;
+    double f5;
+    double f6;
+    double f7;
+    double f8;
+    long iindex;
+    long indexp1;
+    long indexm1;
+    long im1;
+    long ip1;
+    long i;
+    long j;
+    long jj;
+    double **t2a;
+    double **t2b;
+    double **t2c;
+    double *t1a;
+    double *t1b;
+    double *t1c;
+    double *t1d;
+    double *t1e;
+    double *t1f;
+    double *t1g;
+
+    t2a = z[pid][psiindex];
+    if ((gp[pid].neighbors[UP] == -1) && (gp[pid].neighbors[LEFT] == -1)) {
+        t2a[0][0] = 0.0;
+    }
+    if ((gp[pid].neighbors[DOWN] == -1) && (gp[pid].neighbors[LEFT] == -1)) {
+        t2a[im - 1][0] = 0.0;
+    }
+    if ((gp[pid].neighbors[UP] == -1) && (gp[pid].neighbors[RIGHT] == -1)) {
+        t2a[0][jm - 1] = 0.0;
+    }
+    if ((gp[pid].neighbors[DOWN] == -1) && (gp[pid].neighbors[RIGHT] == -1)) {
+        t2a[im - 1][jm - 1] = 0.0;
+    }
+
+    t2a = x[pid][psiindex];
+    jj = gp[pid].neighbors[UPLEFT];
+    if (jj != -1) {
+        t2a[0][0] = x[jj][psiindex][im - 2][jm - 2];
+    }
+    jj = gp[pid].neighbors[UPRIGHT];
+    if (jj != -1) {
+        t2a[0][jm - 1] = x[jj][psiindex][im - 2][1];
+    }
+    jj = gp[pid].neighbors[DOWNLEFT];
+    if (jj != -1) {
+        t2a[im - 1][0] = x[jj][psiindex][1][jm - 2];
+    }
+    jj = gp[pid].neighbors[DOWNRIGHT];
+    if (jj != -1) {
+        t2a[im - 1][jm - 1] = x[jj][psiindex][1][1];
+    }
+
+    t2a = y[pid][psiindex];
+    jj = gp[pid].neighbors[UPLEFT];
+    if (jj != -1) {
+        t2a[0][0] = y[jj][psiindex][im - 2][jm - 2];
+    }
+    jj = gp[pid].neighbors[UPRIGHT];
+    if (jj != -1) {
+        t2a[0][jm - 1] = y[jj][psiindex][im - 2][1];
+    }
+    jj = gp[pid].neighbors[DOWNLEFT];
+    if (jj != -1) {
+        t2a[im - 1][0] = y[jj][psiindex][1][jm - 2];
+    }
+    jj = gp[pid].neighbors[DOWNRIGHT];
+    if (jj != -1) {
+        t2a[im - 1][jm - 1] = y[jj][psiindex][1][1];
+    }
+
+    t2a = x[pid][psiindex];
+    if (gp[pid].neighbors[UP] == -1) {
+        jj = gp[pid].neighbors[LEFT];
+        if (jj != -1) {
+            t2a[0][0] = x[jj][psiindex][0][jm - 2];
+        } else {
+            jj = gp[pid].neighbors[DOWN];
+            if (jj != -1) {
+                t2a[im - 1][0] = x[jj][psiindex][1][0];
+            }
+        }
+        jj = gp[pid].neighbors[RIGHT];
+        if (jj != -1) {
+            t2a[0][jm - 1] = x[jj][psiindex][0][1];
+        } else {
+            jj = gp[pid].neighbors[DOWN];
+            if (jj != -1) {
+                t2a[im - 1][jm - 1] = x[jj][psiindex][1][jm - 1];
+            }
+        }
+    } else if (gp[pid].neighbors[DOWN] == -1) {
+        jj = gp[pid].neighbors[LEFT];
+        if (jj != -1) {
+            t2a[im - 1][0] = x[jj][psiindex][im - 1][jm - 2];
+        } else {
+            jj = gp[pid].neighbors[UP];
+            if (jj != -1) {
+                t2a[0][0] = x[jj][psiindex][im - 2][0];
+            }
+        }
+        jj = gp[pid].neighbors[RIGHT];
+        if (jj != -1) {
+            t2a[im - 1][jm - 1] = x[jj][psiindex][im - 1][1];
+        } else {
+            jj = gp[pid].neighbors[UP];
+            if (jj != -1) {
+                t2a[0][jm - 1] = x[jj][psiindex][im - 2][jm - 1];
+            }
+        }
+    } else if (gp[pid].neighbors[LEFT] == -1) {
+        jj = gp[pid].neighbors[UP];
+        if (jj != -1) {
+            t2a[0][0] = x[jj][psiindex][im - 2][0];
+        }
+        jj = gp[pid].neighbors[DOWN];
+        if (jj != -1) {
+            t2a[im - 1][0] = x[jj][psiindex][1][0];
+        }
+    } else if (gp[pid].neighbors[RIGHT] == -1) {
+        jj = gp[pid].neighbors[UP];
+        if (jj != -1) {
+            t2a[0][jm - 1] = x[jj][psiindex][im - 2][jm - 1];
+        }
+        jj = gp[pid].neighbors[DOWN];
+        if (jj != -1) {
+            t2a[im - 1][jm - 1] = x[jj][psiindex][1][jm - 1];
+        }
+    }
+
+    t2a = y[pid][psiindex];
+    if (gp[pid].neighbors[UP] == -1) {
+        jj = gp[pid].neighbors[LEFT];
+        if (jj != -1) {
+            t2a[0][0] = y[jj][psiindex][0][jm - 2];
+        } else {
+            jj = gp[pid].neighbors[DOWN];
+            if (jj != -1) {
+                t2a[im - 1][0] = y[jj][psiindex][1][0];
+            }
+        }
+        jj = gp[pid].neighbors[RIGHT];
+        if (jj != -1) {
+            t2a[0][jm - 1] = y[jj][psiindex][0][1];
+        } else {
+            jj = gp[pid].neighbors[DOWN];
+            if (jj != -1) {
+                t2a[im - 1][jm - 1] = y[jj][psiindex][1][jm - 1];
+            }
+        }
+    } else if (gp[pid].neighbors[DOWN] == -1) {
+        jj = gp[pid].neighbors[LEFT];
+        if (jj != -1) {
+            t2a[im - 1][0] = y[jj][psiindex][im - 1][jm - 2];
+        } else {
+            jj = gp[pid].neighbors[UP];
+            if (jj != -1) {
+                t2a[0][0] = y[jj][psiindex][im - 2][0];
+            }
+        }
+        jj = gp[pid].neighbors[RIGHT];
+        if (jj != -1) {
+            t2a[im - 1][jm - 1] = y[jj][psiindex][im - 1][1];
+        } else {
+            jj = gp[pid].neighbors[UP];
+            if (jj != -1) {
+                t2a[0][jm - 1] = y[jj][psiindex][im - 2][jm - 1];
+            }
+        }
+    } else if (gp[pid].neighbors[LEFT] == -1) {
+        jj = gp[pid].neighbors[UP];
+        if (jj != -1) {
+            t2a[0][0] = y[jj][psiindex][im - 2][0];
+        }
+        jj = gp[pid].neighbors[DOWN];
+        if (jj != -1) {
+            t2a[im - 1][0] = y[jj][psiindex][1][0];
+        }
+    } else if (gp[pid].neighbors[RIGHT] == -1) {
+        jj = gp[pid].neighbors[UP];
+        if (jj != -1) {
+            t2a[0][jm - 1] = y[jj][psiindex][im - 2][jm - 1];
+        }
+        jj = gp[pid].neighbors[DOWN];
+        if (jj != -1) {
+            t2a[im - 1][jm - 1] = y[jj][psiindex][1][jm - 1];
+        }
+    }
+
+    t2a = y[pid][psiindex];
+    j = gp[pid].neighbors[UP];
+    if (j != -1) {
+        t1a = (double *) t2a[0];
+        t1b = (double *) y[j][psiindex][im - 2];
+        for (i = 1; i <= lastcol; i++) {
+            t1a[i] = t1b[i];
+        }
+    }
+    j = gp[pid].neighbors[DOWN];
+    if (j != -1) {
+        t1a = (double *) t2a[im - 1];
+        t1b = (double *) y[j][psiindex][1];
+        for (i = 1; i <= lastcol; i++) {
+            t1a[i] = t1b[i];
+        }
+    }
+    j = gp[pid].neighbors[LEFT];
+    if (j != -1) {
+        t2b = y[j][psiindex];
+        for (i = 1; i <= lastrow; i++) {
+            t2a[i][0] = t2b[i][jm - 2];
+        }
+    }
+    j = gp[pid].neighbors[RIGHT];
+    if (j != -1) {
+        t2b = y[j][psiindex];
+        for (i = 1; i <= lastrow; i++) {
+            t2a[i][jm - 1] = t2b[i][1];
+        }
+    }
+
+    t2a = x[pid][psiindex];
+    j = gp[pid].neighbors[UP];
+    if (j != -1) {
+        t1a = (double *) t2a[0];
+        t1b = (double *) x[j][psiindex][im - 2];
+        for (i = 1; i <= lastcol; i++) {
+            t1a[i] = t1b[i];
+        }
+    }
+    j = gp[pid].neighbors[DOWN];
+    if (j != -1) {
+        t1a = (double *) t2a[im - 1];
+        t1b = (double *) x[j][psiindex][1];
+        for (i = 1; i <= lastcol; i++) {
+            t1a[i] = t1b[i];
+        }
+    }
+    j = gp[pid].neighbors[LEFT];
+    if (j != -1) {
+        t2b = x[j][psiindex];
+        for (i = 1; i <= lastrow; i++) {
+            t2a[i][0] = t2b[i][jm - 2];
+        }
+    }
+    j = gp[pid].neighbors[RIGHT];
+    if (j != -1) {
+        t2b = x[j][psiindex];
+        for (i = 1; i <= lastrow; i++) {
+            t2a[i][jm - 1] = t2b[i][1];
+        }
+    }
+
+    t2a = x[pid][psiindex];
+    t2b = y[pid][psiindex];
+    t2c = z[pid][psiindex];
+    for (i = firstrow; i <= lastrow; i++) {
+        ip1 = i + 1;
+        im1 = i - 1;
+        t1a = (double *) t2a[i];
+        t1b = (double *) t2b[i];
+        t1c = (double *) t2c[i];
+        t1d = (double *) t2b[ip1];
+        t1e = (double *) t2b[im1];
+        t1f = (double *) t2a[ip1];
+        t1g = (double *) t2a[im1];
+        for (iindex = firstcol; iindex <= lastcol; iindex++) {
+            indexp1 = iindex + 1;
+            indexm1 = iindex - 1;
+            f1 = (t1b[indexm1] + t1d[indexm1] - t1b[indexp1] - t1d[indexp1]) * (t1f[iindex] - t1a[iindex]);
+            f2 = (t1e[indexm1] + t1b[indexm1] - t1e[indexp1] - t1b[indexp1]) * (t1a[iindex] - t1g[iindex]);
+            f3 = (t1d[iindex] + t1d[indexp1] - t1e[iindex] - t1e[indexp1]) * (t1a[indexp1] - t1a[iindex]);
+            f4 = (t1d[indexm1] + t1d[iindex] - t1e[indexm1] - t1e[iindex]) * (t1a[iindex] - t1a[indexm1]);
+            f5 = (t1d[iindex] - t1b[indexp1]) * (t1f[indexp1] - t1a[iindex]);
+            f6 = (t1b[indexm1] - t1e[iindex]) * (t1a[iindex] - t1g[indexm1]);
+            f7 = (t1b[indexp1] - t1e[iindex]) * (t1g[indexp1] - t1a[iindex]);
+            f8 = (t1d[iindex] - t1b[indexm1]) * (t1a[iindex] - t1f[indexm1]);
+
+            t1c[iindex] = factjacob * (f1 + f2 + f3 + f4 + f5 + f6 + f7 + f8);
+
+        }
+    }
+
+    if (gp[pid].neighbors[UP] == -1) {
+        t1c = (double *) t2c[0];
+        for (j = firstcol; j <= lastcol; j++) {
+            t1c[j] = 0.0;
+        }
+    }
+    if (gp[pid].neighbors[DOWN] == -1) {
+        t1c = (double *) t2c[im - 1];
+        for (j = firstcol; j <= lastcol; j++) {
+            t1c[j] = 0.0;
+        }
+    }
+    if (gp[pid].neighbors[LEFT] == -1) {
+        for (j = firstrow; j <= lastrow; j++) {
+            t2c[j][0] = 0.0;
+        }
+    }
+    if (gp[pid].neighbors[RIGHT] == -1) {
+        for (j = firstrow; j <= lastrow; j++) {
+            t2c[j][jm - 1] = 0.0;
+        }
+    }
+
+}
Index: /soft/giet_vm/applications/ocean/laplacalc.C
===================================================================
--- /soft/giet_vm/applications/ocean/laplacalc.C	(revision 581)
+++ /soft/giet_vm/applications/ocean/laplacalc.C	(revision 581)
@@ -0,0 +1,113 @@
+/*************************************************************************/
+/*                                                                       */
+/*  Copyright (c) 1994 Stanford University                               */
+/*                                                                       */
+/*  All rights reserved.                                                 */
+/*                                                                       */
+/*  Permission is given to use, copy, and modify this software for any   */
+/*  non-commercial purpose as long as this copyright notice is not       */
+/*  removed.  All other uses, including redistribution in whole or in    */
+/*  part, are forbidden without prior written permission.                */
+/*                                                                       */
+/*  This software is provided with absolutely no warranty and no         */
+/*  support.                                                             */
+/*                                                                       */
+/*************************************************************************/
+
+/* Performs the laplacian calculation for a subblock */
+
+EXTERN_ENV
+
+#include <stdio.h>
+#include <math.h>
+
+#include "decs.h"
+
+void laplacalc(long procid, double ****x, double ****z, long psiindex, long firstrow, long lastrow, long firstcol, long lastcol)
+{
+    long iindex;
+    long indexp1;
+    long indexm1;
+    long ip1;
+    long im1;
+    long i;
+    long j;
+    double **t2a;
+    double **t2b;
+    double *t1a;
+    double *t1b;
+    double *t1c;
+    double *t1d;
+
+    t2a = (double **) x[procid][psiindex];
+    j = gp[procid].neighbors[UP];
+    if (j != -1) {
+        t1a = (double *) t2a[0];
+        t1b = (double *) x[j][psiindex][im - 2];
+        for (i = 1; i <= lastcol; i++) {
+            t1a[i] = t1b[i];
+        }
+    }
+    j = gp[procid].neighbors[DOWN];
+    if (j != -1) {
+        t1a = (double *) t2a[im - 1];
+        t1b = (double *) x[j][psiindex][1];
+        for (i = 1; i <= lastcol; i++) {
+            t1a[i] = t1b[i];
+        }
+    }
+    j = gp[procid].neighbors[LEFT];
+    if (j != -1) {
+        t2b = (double **) x[j][psiindex];
+        for (i = 1; i <= lastrow; i++) {
+            t2a[i][0] = t2b[i][jm - 2];
+        }
+    }
+    j = gp[procid].neighbors[RIGHT];
+    if (j != -1) {
+        t2b = (double **) x[j][psiindex];
+        for (i = 1; i <= lastrow; i++) {
+            t2a[i][jm - 1] = t2b[i][1];
+        }
+    }
+
+    t2a = (double **) x[procid][psiindex];
+    t2b = (double **) z[procid][psiindex];
+    for (i = firstrow; i <= lastrow; i++) {
+        ip1 = i + 1;
+        im1 = i - 1;
+        t1a = (double *) t2a[i];
+        t1b = (double *) t2b[i];
+        t1c = (double *) t2a[ip1];
+        t1d = (double *) t2a[im1];
+        for (iindex = firstcol; iindex <= lastcol; iindex++) {
+            indexp1 = iindex + 1;
+            indexm1 = iindex - 1;
+            t1b[iindex] = factlap * (t1c[iindex] + t1d[iindex] + t1a[indexp1] + t1a[indexm1] - 4. * t1a[iindex]);
+        }
+    }
+
+    if (gp[procid].neighbors[UP] == -1) {
+        t1b = (double *) t2b[0];
+        for (j = firstcol; j <= lastcol; j++) {
+            t1b[j] = 0.0;
+        }
+    }
+    if (gp[procid].neighbors[DOWN] == -1) {
+        t1b = (double *) t2b[im - 1];
+        for (j = firstcol; j <= lastcol; j++) {
+            t1b[j] = 0.0;
+        }
+    }
+    if (gp[procid].neighbors[LEFT] == -1) {
+        for (j = firstrow; j <= lastrow; j++) {
+            t2b[j][0] = 0.0;
+        }
+    }
+    if (gp[procid].neighbors[RIGHT] == -1) {
+        for (j = firstrow; j <= lastrow; j++) {
+            t2b[j][jm - 1] = 0.0;
+        }
+    }
+
+}
Index: /soft/giet_vm/applications/ocean/linkup.C
===================================================================
--- /soft/giet_vm/applications/ocean/linkup.C	(revision 581)
+++ /soft/giet_vm/applications/ocean/linkup.C	(revision 581)
@@ -0,0 +1,190 @@
+/*************************************************************************/
+/*                                                                       */
+/*  Copyright (c) 1994 Stanford University                               */
+/*                                                                       */
+/*  All rights reserved.                                                 */
+/*                                                                       */
+/*  Permission is given to use, copy, and modify this software for any   */
+/*  non-commercial purpose as long as this copyright notice is not       */
+/*  removed.  All other uses, including redistribution in whole or in    */
+/*  part, are forbidden without prior written permission.                */
+/*                                                                       */
+/*  This software is provided with absolutely no warranty and no         */
+/*  support.                                                             */
+/*                                                                       */
+/*************************************************************************/
+
+/* Set all the pointers to the proper locations for the q_multi and
+   rhs_multi data structures */
+
+EXTERN_ENV
+
+#include "decs.h"
+
+void link_all()
+{
+    long i;
+    long j;
+
+    for (j = 0; j < nprocs; j++) {
+        linkup(psium[j]);
+        linkup(psilm[j]);
+        linkup(psib[j]);
+        linkup(ga[j]);
+        linkup(gb[j]);
+        linkup(work2[j]);
+        linkup(work3[j]);
+        linkup(work6[j]);
+        linkup(tauz[j]);
+        linkup(oldga[j]);
+        linkup(oldgb[j]);
+        for (i = 0; i <= 1; i++) {
+            linkup(psi[j][i]);
+            linkup(psim[j][i]);
+            linkup(work1[j][i]);
+            linkup(work4[j][i]);
+            linkup(work5[j][i]);
+            linkup(work7[j][i]);
+            linkup(temparray[j][i]);
+        }
+    }
+    link_multi();
+}
+
+void linkup(double **row_ptr)
+{
+    long i;
+    double *a;
+    double **row;
+    double **y;
+    long x_part;
+    long y_part;
+
+    x_part = (jm - 2) / xprocs + 2;
+    y_part = (im - 2) / yprocs + 2;
+    row = row_ptr;
+    y = row + y_part;
+    a = (double *) y;
+    for (i = 0; i < y_part; i++) {
+        *row = (double *) a;
+        row++;
+        a += x_part;
+    }
+}
+
+void link_multi()
+{
+    long i;
+    long j;
+    long l;
+    double *a;
+    double **row;
+    double **y;
+    unsigned long z;
+    unsigned long zz;
+    long x_part;
+    long y_part;
+    unsigned long d_size;
+
+    z = ((unsigned long) q_multi + nprocs * sizeof(double ***));
+
+    if (nprocs % 2 == 1) {      /* To make sure that the actual data
+                                   starts double word aligned, add an extra
+                                   pointer */
+        z += sizeof(double ***);
+    }
+
+    d_size = numlev * sizeof(double **);
+    if (numlev % 2 == 1) {      /* To make sure that the actual data
+                                   starts double word aligned, add an extra
+                                   pointer */
+        d_size += sizeof(double **);
+    }
+    for (i = 0; i < numlev; i++) {
+        d_size += ((imx[i] - 2) / yprocs + 2) * ((jmx[i] - 2) / xprocs + 2) * sizeof(double) + ((imx[i] - 2) / yprocs + 2) * sizeof(double *);
+    }
+    for (i = 0; i < nprocs; i++) {
+        q_multi[i] = (double ***) z;
+        z += d_size;
+    }
+    for (j = 0; j < nprocs; j++) {
+        zz = (unsigned long) q_multi[j];
+        zz += numlev * sizeof(double **);
+        if (numlev % 2 == 1) {  /* To make sure that the actual data
+                                   starts double word aligned, add an extra
+                                   pointer */
+            zz += sizeof(double **);
+        }
+        for (i = 0; i < numlev; i++) {
+            d_size = ((imx[i] - 2) / yprocs + 2) * ((jmx[i] - 2) / xprocs + 2) * sizeof(double) + ((imx[i] - 2) / yprocs + 2) * sizeof(double *);
+            q_multi[j][i] = (double **) zz;
+            zz += d_size;
+        }
+    }
+
+    for (l = 0; l < numlev; l++) {
+        x_part = (jmx[l] - 2) / xprocs + 2;
+        y_part = (imx[l] - 2) / yprocs + 2;
+        for (j = 0; j < nprocs; j++) {
+            row = q_multi[j][l];
+            y = row + y_part;
+            a = (double *) y;
+            for (i = 0; i < y_part; i++) {
+                *row = (double *) a;
+                row++;
+                a += x_part;
+            }
+        }
+    }
+
+    z = ((unsigned long) rhs_multi + nprocs * sizeof(double ***));
+    if (nprocs % 2 == 1) {      /* To make sure that the actual data
+                                   starts double word aligned, add an extra
+                                   pointer */
+        z += sizeof(double ***);
+    }
+
+    d_size = numlev * sizeof(double **);
+    if (numlev % 2 == 1) {      /* To make sure that the actual data
+                                   starts double word aligned, add an extra
+                                   pointer */
+        d_size += sizeof(double **);
+    }
+    for (i = 0; i < numlev; i++) {
+        d_size += ((imx[i] - 2) / yprocs + 2) * ((jmx[i] - 2) / xprocs + 2) * sizeof(double) + ((imx[i] - 2) / yprocs + 2) * sizeof(double *);
+    }
+    for (i = 0; i < nprocs; i++) {
+        rhs_multi[i] = (double ***) z;
+        z += d_size;
+    }
+    for (j = 0; j < nprocs; j++) {
+        zz = (unsigned long) rhs_multi[j];
+        zz += numlev * sizeof(double **);
+        if (numlev % 2 == 1) {  /* To make sure that the actual data
+                                   starts double word aligned, add an extra
+                                   pointer */
+            zz += sizeof(double **);
+        }
+        for (i = 0; i < numlev; i++) {
+            d_size = ((imx[i] - 2) / yprocs + 2) * ((jmx[i] - 2) / xprocs + 2) * sizeof(double) + ((imx[i] - 2) / yprocs + 2) * sizeof(double *);
+            rhs_multi[j][i] = (double **) zz;
+            zz += d_size;
+        }
+    }
+
+    for (l = 0; l < numlev; l++) {
+        x_part = (jmx[l] - 2) / xprocs + 2;
+        y_part = (imx[l] - 2) / yprocs + 2;
+        for (j = 0; j < nprocs; j++) {
+            row = rhs_multi[j][l];
+            y = row + y_part;
+            a = (double *) y;
+            for (i = 0; i < y_part; i++) {
+                *row = (double *) a;
+                row++;
+                a += x_part;
+            }
+        }
+    }
+
+}
Index: /soft/giet_vm/applications/ocean/main.C
===================================================================
--- /soft/giet_vm/applications/ocean/main.C	(revision 581)
+++ /soft/giet_vm/applications/ocean/main.C	(revision 581)
@@ -0,0 +1,696 @@
+/*************************************************************************/
+/*                                                                       */
+/*  Copyright (c) 1994 Stanford University                               */
+/*                                                                       */
+/*  All rights reserved.                                                 */
+/*                                                                       */
+/*  Permission is given to use, copy, and modify this software for any   */
+/*  non-commercial purpose as long as this copyright notice is not       */
+/*  removed.  All other uses, including redistribution in whole or in    */
+/*  part, are forbidden without prior written permission.                */
+/*                                                                       */
+/*  This software is provided with absolutely no warranty and no         */
+/*  support.                                                             */
+/*                                                                       */
+/*************************************************************************/
+
+/*************************************************************************/
+/*                                                                       */
+/*  SPLASH Ocean Code                                                    */
+/*                                                                       */
+/*  This application studies the role of eddy and boundary currents in   */
+/*  influencing large-scale ocean movements.  This implementation uses   */
+/*  dynamically allocated four-dimensional arrays for grid data storage. */
+/*                                                                       */
+/*  Command line options:                                                */
+/*                                                                       */
+/*     -mM : Simulate MxM ocean. M must be (power of 2) +2.              */
+/*     -nN : N = number of threads. N must be power of 2.                */
+/*     -eE : E = error tolerance for iterative relaxation.               */
+/*     -rR : R = distance between grid points in meters.                 */
+/*     -tT : T = timestep in seconds.                                    */
+/*     -s  : Print timing statistics.                                    */
+/*     -o  : Print out relaxation residual values.                       */
+/*     -h  : Print out command line options.                             */
+/*                                                                       */
+/*  Default: OCEAN -m130 -n1 -e1e-7 -r20000.0 -t28800.0                  */
+/*                                                                       */
+/*  NOTE: This code works under both the FORK and SPROC models.          */
+/*                                                                       */
+/*************************************************************************/
+
+MAIN_ENV
+
+#define DEFAULT_M        514
+#define DEFAULT_N        4
+#define DEFAULT_E        1e-7
+#define DEFAULT_T    28800.0
+#define DEFAULT_R    20000.0
+#define UP               0
+#define DOWN             1
+#define LEFT             2
+#define RIGHT            3
+#define UPLEFT           4
+#define UPRIGHT          5
+#define DOWNLEFT         6
+#define DOWNRIGHT        7
+#define PAGE_SIZE     4096
+
+#include <stdio.h>
+#include <math.h>
+#include <stdlib.h>
+
+#include "decs.h"
+
+struct multi_struct *multi;
+struct global_struct *global;
+struct locks_struct *locks;
+struct bars_struct *bars;
+
+struct Global_Private *main_gp;
+double ****main_psi;
+double ****main_psim;
+double ***main_psium;
+double ***main_psilm;
+double ***main_psib;
+double ***main_ga;
+double ***main_gb;
+double ****main_work1;
+double ***main_work2;
+double ***main_work3;
+double ****main_work4;
+double ****main_work5;
+double ***main_work6;
+double ****main_work7;
+double ***main_oldga;
+double ***main_oldgb;
+double ****main_q_multi;
+double ****main_rhs_multi;
+double ****temparray;
+double ***tauz;
+long *main_imx;
+long *main_jmx;
+
+long nprocs = DEFAULT_N;
+const double h1 = 1000.0;
+const double h3 = 4000.0;
+const double h = 5000.0;
+const double lf = -5.12e11;
+double res = DEFAULT_R;
+double dtau = DEFAULT_T;
+const double f0 = 8.3e-5;
+const double beta = 2.0e-11;
+const double gpr = 0.02;
+double ysca;
+long oim;
+long jmm1;
+double tolerance = DEFAULT_E;
+const double pi = 3.141592653589793;
+const double t0 = 0.5e-4;
+const double outday0 = 1.0;
+const double outday1 = 2.0;
+const double outday2 = 2.0;
+const double outday3 = 2.0;
+const double maxwork = 10000.0;
+double factjacob;
+double factlap;
+
+//TODO : rÃ©pliquer Ã§a :
+double *main_lev_res;
+double *main_lev_tol;
+double *main_i_int_coeff;
+double *main_j_int_coeff;
+long *main_xpts_per_proc;
+long *main_ypts_per_proc;
+long main_xprocs;
+long main_yprocs;
+long main_numlev;
+double main_eig2;
+long main_im = DEFAULT_M;
+long main_jm;
+
+long minlevel;
+long do_stats = 1;
+long do_output = 0;
+long *ids_procs;
+
+
+__attribute__ ((constructor)) int main(int argc, char *argv[])
+{
+    long i;
+    long j;
+    long k;
+    long x_part;
+    long y_part;
+    long d_size;
+    long itemp;
+    long jtemp;
+    double procsqrt;
+    long temp = 0;
+    double min_total;
+    double max_total;
+    double avg_total;
+    double avg_wait;
+    double max_wait;
+    double min_wait;
+    double min_multi;
+    double max_multi;
+    double avg_multi;
+    double min_frac;
+    double max_frac;
+    double avg_frac;
+    long imax_wait;
+    long imin_wait;
+    long ch;
+    unsigned long long computeend;
+    unsigned long long start;
+    im = main_im;
+    
+    CLOCK(start);
+
+    while ((ch = getopt(argc, argv, "m:n:e:r:t:soh")) != -1) {
+        switch (ch) {
+        case 'm':
+            im = atoi(optarg);
+            if (log_2(im - 2) == -1) {
+                printerr("Grid must be ((power of 2)+2) in each dimension\n");
+                exit(-1);
+            }
+            break;
+        case 'n':
+            nprocs = atoi(optarg);
+            if (nprocs < 1) {
+                printerr("N must be >= 1\n");
+                exit(-1);
+            }
+            if (log_2(nprocs) == -1) {
+                printerr("N must be a power of 2\n");
+                exit(-1);
+            }
+            break;
+        case 'e':
+            tolerance = atof(optarg);
+            break;
+        case 'r':
+            res = atof(optarg);
+            break;
+        case 't':
+            dtau = atof(optarg);
+            break;
+        case 's':
+            do_stats = !do_stats;
+            break;
+        case 'o':
+            do_output = !do_output;
+            break;
+        case 'h':
+            printf("Usage: ocean <options>\n\n");
+            printf("options:\n");
+            printf("  -mM : Simulate MxM ocean.  M must be (power of 2) + 2 (default = %d).\n", DEFAULT_M);
+            printf("  -nN : N = number of threads. N must be power of 2 (default = %d).\n", DEFAULT_N);
+            printf("  -eE : E = error tolerance for iterative relaxation (default = %f).\n", DEFAULT_E);
+            printf("  -rR : R = distance between grid points in meters (default = %f).\n", DEFAULT_R);
+            printf("  -tT : T = timestep in seconds (default = %f).\n", DEFAULT_T);
+            printf("  -s  : Print timing statistics.\n");
+            printf("  -o  : Print out relaxation residual values.\n");
+            printf("  -h  : Print out command line options.\n\n");
+            exit(0);
+            break;
+        }
+    }
+
+    MAIN_INITENV
+    
+    jm = im;
+
+    printf("\n");
+    printf("Ocean simulation with W-cycle multigrid solver\n");
+    printf("    Processors                         : %1ld\n", nprocs);
+    printf("    Grid size                          : %1ld x %1ld\n", im, jm);
+    printf("    Grid resolution (meters)           : %0.2f\n", res);
+    printf("    Time between relaxations (seconds) : %0.0f\n", dtau);
+    printf("    Error tolerance                    : %0.7g\n", tolerance);
+    printf("\n");
+
+    xprocs = 0;
+    yprocs = 0;
+
+    procsqrt = sqrt((double) nprocs);
+    j = (long) procsqrt;
+
+    while ((xprocs == 0) && (j > 0)) {
+        k = nprocs / j;
+        if (k * j == nprocs) {
+            if (k > j) {
+                xprocs = j;
+                yprocs = k;
+            } else {
+                xprocs = k;
+                yprocs = j;
+            }
+        }
+        j--;
+    }
+
+    if (xprocs == 0) {
+        printerr("Could not find factors for subblocking\n");
+        exit(-1);
+    }
+
+    minlevel = 0;
+    itemp = 1;
+    jtemp = 1;
+    numlev = 0;
+    minlevel = 0;
+
+    while (itemp < (im - 2)) {
+        itemp = itemp * 2;
+        jtemp = jtemp * 2;
+        if ((itemp / yprocs > 1) && (jtemp / xprocs > 1)) {
+            numlev++;
+        }
+    }
+
+    if (numlev == 0) {
+        printerr("Must have at least 2 grid points per processor in each dimension\n");
+        exit(-1);
+    }
+
+    main_imx = (long *) G_MALLOC(numlev * sizeof(long), 0);
+    main_jmx = (long *) G_MALLOC(numlev * sizeof(long), 0);
+    main_lev_res = (double *) G_MALLOC(numlev * sizeof(double), 0);
+    main_lev_tol = (double *) G_MALLOC(numlev * sizeof(double), 0);
+    main_i_int_coeff = (double *) G_MALLOC(numlev * sizeof(double), 0);
+    main_j_int_coeff = (double *) G_MALLOC(numlev * sizeof(double), 0);
+    main_xpts_per_proc = (long *) G_MALLOC(numlev * sizeof(long), 0);
+    main_ypts_per_proc = (long *) G_MALLOC(numlev * sizeof(long), 0);
+    ids_procs = (long *) G_MALLOC(nprocs * sizeof(long), 0);
+    
+    imx = main_imx;
+    jmx = main_jmx;
+    lev_res = main_lev_res;
+    lev_tol = main_lev_tol;
+    i_int_coeff = main_i_int_coeff;
+    j_int_coeff = main_j_int_coeff;
+    xpts_per_proc = main_xpts_per_proc;
+    ypts_per_proc = main_ypts_per_proc;
+
+    for (i = 0; i < nprocs; i++) {
+        ids_procs[i] = i;
+    }
+
+    imx[numlev - 1] = im;
+    jmx[numlev - 1] = jm;
+    lev_res[numlev - 1] = res;
+    lev_tol[numlev - 1] = tolerance;
+
+    for (i = numlev - 2; i >= 0; i--) {
+        imx[i] = ((imx[i + 1] - 2) / 2) + 2;
+        jmx[i] = ((jmx[i + 1] - 2) / 2) + 2;
+        lev_res[i] = lev_res[i + 1] * 2;
+    }
+
+    for (i = 0; i < numlev; i++) {
+        xpts_per_proc[i] = (jmx[i] - 2) / xprocs;
+        ypts_per_proc[i] = (imx[i] - 2) / yprocs;
+    }
+    for (i = numlev - 1; i >= 0; i--) {
+        if ((xpts_per_proc[i] < 2) || (ypts_per_proc[i] < 2)) {
+            minlevel = i + 1;
+            break;
+        }
+    }
+
+    for (i = 0; i < numlev; i++) {
+        temp += imx[i];
+    }
+    temp = 0;
+    j = 0;
+    for (k = 0; k < numlev; k++) {
+        for (i = 0; i < imx[k]; i++) {
+            j++;
+            temp += jmx[k];
+        }
+    }
+
+    d_size = nprocs * sizeof(double ***);
+    main_psi = (double ****) G_MALLOC(d_size, 0);
+    main_psim = (double ****) G_MALLOC(d_size, 0);
+    main_work1 = (double ****) G_MALLOC(d_size, 0);
+    main_work4 = (double ****) G_MALLOC(d_size, 0);
+    main_work5 = (double ****) G_MALLOC(d_size, 0);
+    main_work7 = (double ****) G_MALLOC(d_size, 0);
+    temparray = (double ****) G_MALLOC(d_size, -1);
+
+    psi = main_psi;
+    psim = main_psim;
+    work1 = main_work1;
+    work4 = main_work4;
+    work5 = main_work5;
+    work7 = main_work7;
+
+    d_size = 2 * sizeof(double **);
+    for (i = 0; i < nprocs; i++) {
+        psi[i] = (double ***) G_MALLOC(d_size, i);
+        psim[i] = (double ***) G_MALLOC(d_size, i);
+        work1[i] = (double ***) G_MALLOC(d_size, i);
+        work4[i] = (double ***) G_MALLOC(d_size, i);
+        work5[i] = (double ***) G_MALLOC(d_size, i);
+        work7[i] = (double ***) G_MALLOC(d_size, i);
+        temparray[i] = (double ***) G_MALLOC(d_size, i);
+    }
+
+    d_size = nprocs * sizeof(double **);
+    main_psium = (double ***) G_MALLOC(d_size, 0);
+    main_psilm = (double ***) G_MALLOC(d_size, 0);
+    main_psib = (double ***) G_MALLOC(d_size, 0);
+    main_ga = (double ***) G_MALLOC(d_size, 0);
+    main_gb = (double ***) G_MALLOC(d_size, 0);
+    main_work2 = (double ***) G_MALLOC(d_size, 0);
+    main_work3 = (double ***) G_MALLOC(d_size, 0);
+    main_work6 = (double ***) G_MALLOC(d_size, 0);
+    tauz = (double ***) G_MALLOC(d_size, 0);
+    main_oldga = (double ***) G_MALLOC(d_size, 0);
+    main_oldgb = (double ***) G_MALLOC(d_size, 0);
+
+    psium = main_psium;
+    psilm = main_psilm;
+    psib = main_psib;
+    ga = main_ga;
+    gb = main_gb;
+    work2 = main_work2;
+    work3 = main_work3;
+    work6 = main_work6;
+    oldga = main_oldga;
+    oldgb = main_oldgb;
+
+    main_gp = (struct Global_Private *) G_MALLOC((nprocs + 1) * sizeof(struct Global_Private), -1);
+    gp = main_gp;
+
+    for (i = 0; i < nprocs; i++) {
+        gp[i].pad = (char *) G_MALLOC(PAGE_SIZE * sizeof(char), i);
+        gp[i].rel_num_x = (long *) G_MALLOC(numlev * sizeof(long), i);
+        gp[i].rel_num_y = (long *) G_MALLOC(numlev * sizeof(long), i);
+        gp[i].eist = (long *) G_MALLOC(numlev * sizeof(long), i);
+        gp[i].ejst = (long *) G_MALLOC(numlev * sizeof(long), i);
+        gp[i].oist = (long *) G_MALLOC(numlev * sizeof(long), i);
+        gp[i].ojst = (long *) G_MALLOC(numlev * sizeof(long), i);
+        gp[i].rlist = (long *) G_MALLOC(numlev * sizeof(long), i);
+        gp[i].rljst = (long *) G_MALLOC(numlev * sizeof(long), i);
+        gp[i].rlien = (long *) G_MALLOC(numlev * sizeof(long), i);
+        gp[i].rljen = (long *) G_MALLOC(numlev * sizeof(long), i);
+        gp[i].neighbors = (long *) G_MALLOC(8 * sizeof(long), i);
+        gp[i].rownum = (long *) G_MALLOC(sizeof(long), i);
+        gp[i].colnum = (long *) G_MALLOC(sizeof(long), i);
+        gp[i].lpid = (long *) G_MALLOC(sizeof(long), i);
+        gp[i].multi_time = (double *) G_MALLOC(sizeof(double), i);
+        gp[i].total_time = (double *) G_MALLOC(sizeof(double), i);
+        gp[i].sync_time = (double *) G_MALLOC(sizeof(double), i);
+        gp[i].process_time = (double *) G_MALLOC(sizeof(double), i);
+        gp[i].step_start = (double *) G_MALLOC(sizeof(double), i);
+        gp[i].steps_time = (double *) G_MALLOC(10 * sizeof(double), i);
+        *gp[i].multi_time = 0;
+        *gp[i].total_time = 0;
+        *gp[i].sync_time = 0;
+        *gp[i].process_time = 0;
+        *gp[i].lpid = i;
+    }
+
+    subblock();
+
+    x_part = (jm - 2) / xprocs + 2;
+    y_part = (im - 2) / yprocs + 2;
+
+    d_size = x_part * y_part * sizeof(double) + y_part * sizeof(double *);
+
+    global = (struct global_struct *) G_MALLOC(sizeof(struct global_struct), -1);
+
+    for (i = 0; i < nprocs; i++) {
+        psi[i][0] = (double **) G_MALLOC(d_size, i);
+        psi[i][1] = (double **) G_MALLOC(d_size, i);
+        psim[i][0] = (double **) G_MALLOC(d_size, i);
+        psim[i][1] = (double **) G_MALLOC(d_size, i);
+        psium[i] = (double **) G_MALLOC(d_size, i);
+        psilm[i] = (double **) G_MALLOC(d_size, i);
+        psib[i] = (double **) G_MALLOC(d_size, i);
+        ga[i] = (double **) G_MALLOC(d_size, i);
+        gb[i] = (double **) G_MALLOC(d_size, i);
+        work1[i][0] = (double **) G_MALLOC(d_size, i);
+        work1[i][1] = (double **) G_MALLOC(d_size, i);
+        work2[i] = (double **) G_MALLOC(d_size, i);
+        work3[i] = (double **) G_MALLOC(d_size, i);
+        work4[i][0] = (double **) G_MALLOC(d_size, i);
+        work4[i][1] = (double **) G_MALLOC(d_size, i);
+        work5[i][0] = (double **) G_MALLOC(d_size, i);
+        work5[i][1] = (double **) G_MALLOC(d_size, i);
+        work6[i] = (double **) G_MALLOC(d_size, i);
+        work7[i][0] = (double **) G_MALLOC(d_size, i);
+        work7[i][1] = (double **) G_MALLOC(d_size, i);
+        temparray[i][0] = (double **) G_MALLOC(d_size, i);
+        temparray[i][1] = (double **) G_MALLOC(d_size, i);
+        tauz[i] = (double **) G_MALLOC(d_size, i);
+        oldga[i] = (double **) G_MALLOC(d_size, i);
+        oldgb[i] = (double **) G_MALLOC(d_size, i);
+    }
+
+    oim = im;
+    //f = (double *) G_MALLOC(oim*sizeof(double), 0);
+    multi = (struct multi_struct *) G_MALLOC(sizeof(struct multi_struct), -1);
+
+    d_size = numlev * sizeof(double **);
+    if (numlev % 2 == 1) {      /* To make sure that the actual data
+                                   starts double word aligned, add an extra
+                                   pointer */
+        d_size += sizeof(double **);
+    }
+    for (i = 0; i < numlev; i++) {
+        d_size += ((imx[i] - 2) / yprocs + 2) * ((jmx[i] - 2) / xprocs + 2) * sizeof(double) + ((imx[i] - 2) / yprocs + 2) * sizeof(double *);
+    }
+
+    d_size *= nprocs;
+
+    if (nprocs % 2 == 1) {      /* To make sure that the actual data
+                                   starts double word aligned, add an extra
+                                   pointer */
+        d_size += sizeof(double ***);
+    }
+
+    d_size += nprocs * sizeof(double ***);
+    main_q_multi = (double ****) G_MALLOC(d_size, -1);
+    main_rhs_multi = (double ****) G_MALLOC(d_size, -1);
+    q_multi = main_q_multi;
+    rhs_multi = main_rhs_multi;
+
+
+    locks = (struct locks_struct *) G_MALLOC(sizeof(struct locks_struct), -1);
+    bars = (struct bars_struct *) G_MALLOC(sizeof(struct bars_struct), -1);
+
+    LOCKINIT(locks->idlock)
+    LOCKINIT(locks->psiailock)
+    LOCKINIT(locks->psibilock)
+    LOCKINIT(locks->donelock)
+    LOCKINIT(locks->error_lock)
+    LOCKINIT(locks->bar_lock)
+#if defined(MULTIPLE_BARRIERS)
+    BARINIT(bars->iteration, nprocs)
+    BARINIT(bars->gsudn, nprocs)
+    BARINIT(bars->p_setup, nprocs)
+    BARINIT(bars->p_redph, nprocs)
+    BARINIT(bars->p_soln, nprocs)
+    BARINIT(bars->p_subph, nprocs)
+    BARINIT(bars->sl_prini, nprocs)
+    BARINIT(bars->sl_psini, nprocs)
+    BARINIT(bars->sl_onetime, nprocs)
+    BARINIT(bars->sl_phase_1, nprocs)
+    BARINIT(bars->sl_phase_2, nprocs)
+    BARINIT(bars->sl_phase_3, nprocs)
+    BARINIT(bars->sl_phase_4, nprocs)
+    BARINIT(bars->sl_phase_5, nprocs)
+    BARINIT(bars->sl_phase_6, nprocs)
+    BARINIT(bars->sl_phase_7, nprocs)
+    BARINIT(bars->sl_phase_8, nprocs)
+    BARINIT(bars->sl_phase_9, nprocs)
+    BARINIT(bars->sl_phase_10, nprocs)
+    BARINIT(bars->error_barrier, nprocs)
+#else
+    BARINIT(bars->barrier, nprocs)
+#endif
+    link_all();
+
+    multi->err_multi = 0.0;
+    i_int_coeff[0] = 0.0;
+    j_int_coeff[0] = 0.0;
+
+    for (i = 0; i < numlev; i++) {
+        i_int_coeff[i] = 1.0 / (imx[i] - 1);
+        j_int_coeff[i] = 1.0 / (jmx[i] - 1);
+    }
+
+    /*
+       initialize constants and variables
+
+       id is a global shared variable that has fetch-and-add operations
+       performed on it by processes to obtain their pids.   
+     */
+
+    //global->id = 0;
+    global->trackstart = 0;
+    global->psibi = 0.0;
+
+    factjacob = -1. / (12. * res * res);
+    factlap = 1. / (res * res);
+    eig2 = -h * f0 * f0 / (h1 * h3 * gpr);
+
+    jmm1 = jm - 1;
+    ysca = ((double) jmm1) * res;
+    im = (imx[numlev - 1] - 2) / yprocs + 2;
+    jm = (jmx[numlev - 1] - 2) / xprocs + 2;
+    
+    main_im = im;
+    main_jm = jm;
+    main_numlev = numlev;
+    main_xprocs = xprocs;
+    main_yprocs = yprocs;
+    main_eig2 = eig2;
+
+    if (do_output) {
+        printf("              MULTIGRID OUTPUTS\n");
+    }
+
+    CREATE(slave, nprocs);
+    WAIT_FOR_END(nprocs);
+    CLOCK(computeend);
+
+    printf("\n");
+    printf("                PROCESS STATISTICS\n");
+    printf("                  Total          Multigrid         Multigrid\n");
+    printf(" Proc             Time             Time            Fraction\n");
+    printf("    0   %15.0f    %15.0f        %10.3f\n", (*gp[0].total_time), (*gp[0].multi_time), (*gp[0].multi_time) / (*gp[0].total_time));
+
+    if (do_stats) {
+        double phase_time;
+        min_total = max_total = avg_total = (*gp[0].total_time);
+        min_multi = max_multi = avg_multi = (*gp[0].multi_time);
+        min_frac = max_frac = avg_frac = (*gp[0].multi_time) / (*gp[0].total_time);
+        avg_wait = *gp[0].sync_time;
+        max_wait = *gp[0].sync_time;
+        min_wait = *gp[0].sync_time;
+        imax_wait = 0;
+        imin_wait = 0;
+
+        for (i = 1; i < nprocs; i++) {
+            if ((*gp[i].total_time) > max_total) {
+                max_total = (*gp[i].total_time);
+            }
+            if ((*gp[i].total_time) < min_total) {
+                min_total = (*gp[i].total_time);
+            }
+            if ((*gp[i].multi_time) > max_multi) {
+                max_multi = (*gp[i].multi_time);
+            }
+            if ((*gp[i].multi_time) < min_multi) {
+                min_multi = (*gp[i].multi_time);
+            }
+            if ((*gp[i].multi_time) / (*gp[i].total_time) > max_frac) {
+                max_frac = (*gp[i].multi_time) / (*gp[i].total_time);
+            }
+            if ((*gp[i].multi_time) / (*gp[i].total_time) < min_frac) {
+                min_frac = (*gp[i].multi_time) / (*gp[i].total_time);
+            }
+            avg_total += (*gp[i].total_time);
+            avg_multi += (*gp[i].multi_time);
+            avg_frac += (*gp[i].multi_time) / (*gp[i].total_time);
+            avg_wait += (*gp[i].sync_time);
+            if (max_wait < (*gp[i].sync_time)) {
+                max_wait = (*gp[i].sync_time);
+                imax_wait = i;
+            }
+            if (min_wait > (*gp[i].sync_time)) {
+                min_wait = (*gp[i].sync_time);
+                imin_wait = i;
+            }
+        }
+        avg_total = avg_total / nprocs;
+        avg_multi = avg_multi / nprocs;
+        avg_frac = avg_frac / nprocs;
+        avg_wait = avg_wait / nprocs;
+        for (i = 1; i < nprocs; i++) {
+            printf("  %3ld   %15.0f    %15.0f        %10.3f\n", i, (*gp[i].total_time), (*gp[i].multi_time), (*gp[i].multi_time) / (*gp[i].total_time));
+        }
+        printf("  Avg   %15.0f    %15.0f        %10.3f\n", avg_total, avg_multi, avg_frac);
+        printf("  Min   %15.0f    %15.0f        %10.3f\n", min_total, min_multi, min_frac);
+        printf("  Max   %15.0f    %15.0f        %10.3f\n", max_total, max_multi, max_frac);
+        
+        printf("\n\n                  Sync\n");
+        printf(" Proc      Time        Fraction\n");
+        for (i = 0; i < nprocs; i++) {
+            printf("  %ld        %u      %f\n", i, (unsigned int)*gp[i].sync_time, *gp[i].sync_time / ((long)(*gp[i].total_time)));
+        }
+
+        printf("  Avg   %f   %f\n", avg_wait, (double) avg_wait / (long) (computeend - global->trackstart));
+        printf("  Min   %f   %f\n", min_wait, (double) min_wait / (long) (*gp[imin_wait].total_time));
+        printf("  Max   %f   %f\n", max_wait, (double) max_wait / (long) (*gp[imax_wait].total_time));
+
+        printf("\nPhases Avg :\n\n");
+        for (i = 0; i < 10; i++) {
+            phase_time = 0;
+            for (j = 0; j < nprocs; j++) {
+                phase_time += gp[j].steps_time[i];
+            }
+            phase_time /= (double) nprocs;
+            printf("  %d = %f (fraction %f)\n", i + 1, phase_time, phase_time / (long) (computeend - global->trackstart));
+        }
+    }
+    printf("\n");
+
+    global->starttime = start;
+    printf("                       TIMING INFORMATION\n");
+    printf("[NPROCS]           : %16ld\n", nprocs);
+    printf("[START1]           : %16llu\n", global->starttime);
+    printf("[START2]           : %16llu\n", global->trackstart);
+    printf("[END]              : %16llu\n", computeend);
+    printf("[TOTAL]            : %16llu\n", computeend - global->starttime);    // With init
+    printf("[PARALLEL_COMPUTE] : %16llu\n", computeend - global->trackstart);   // Without init
+    printf("(excludes first timestep)\n");
+    printf("\n");
+
+    MAIN_END
+    
+}
+
+long log_2(long number)
+{
+    long cumulative = 1;
+    long out = 0;
+    long done = 0;
+
+    while ((cumulative < number) && (!done) && (out < 50)) {
+        if (cumulative == number) {
+            done = 1;
+        } else {
+            cumulative = cumulative * 2;
+            out++;
+        }
+    }
+
+    if (cumulative == number) {
+        return (out);
+    } else {
+        return (-1);
+    }
+}
+
+void printerr(char *s)
+{
+    fprintf(stderr, "ERROR: %s\n", s);
+}
+
+
+// Local Variables:
+// tab-width: 4
+// c-basic-offset: 4
+// c-file-offsets:((innamespace . 0)(inline-open . 0))
+// indent-tabs-mode: nil
+// End:
+
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=4:softtabstop=4
Index: /soft/giet_vm/applications/ocean/multi.C
===================================================================
--- /soft/giet_vm/applications/ocean/multi.C	(revision 581)
+++ /soft/giet_vm/applications/ocean/multi.C	(revision 581)
@@ -0,0 +1,795 @@
+/*************************************************************************/
+/*                                                                       */
+/*  Copyright (c) 1994 Stanford University                               */
+/*                                                                       */
+/*  All rights reserved.                                                 */
+/*                                                                       */
+/*  Permission is given to use, copy, and modify this software for any   */
+/*  non-commercial purpose as long as this copyright notice is not       */
+/*  removed.  All other uses, including redistribution in whole or in    */
+/*  part, are forbidden without prior written permission.                */
+/*                                                                       */
+/*  This software is provided with absolutely no warranty and no         */
+/*  support.                                                             */
+/*                                                                       */
+/*************************************************************************/
+
+/* Shared memory implementation of the multigrid method
+   Implementation uses red-black gauss-seidel relaxation
+   iterations, w cycles, and the method of half-injection for
+   residual computation. */
+
+EXTERN_ENV
+
+#include <stdio.h>
+#include <math.h>
+#include <stdlib.h>
+
+#include "decs.h"
+
+/* perform multigrid (w cycles)                                     */
+void multig(long my_id)
+{
+    long iter;
+    double wu;
+    double errp;
+    long m;
+    long flag;
+    long k;
+    long my_num;
+    double wmax;
+    double local_err;
+    double red_local_err;
+    double black_local_err;
+    double g_error;
+
+    flag = 0;
+    iter = 0;
+    m = numlev - 1;
+    wmax = maxwork;
+    my_num = my_id;
+    wu = 0.0;
+
+    k = m;
+    g_error = 1.0e30;
+    while (!flag) {
+        errp = g_error;
+        iter++;
+        if (my_num == MASTER) {
+            multi->err_multi = 0.0;
+        }
+
+/* barrier to make sure all procs have finished intadd or rescal   */
+/* before proceeding with relaxation                               */
+#if defined(MULTIPLE_BARRIERS)
+        BARRIER(bars->error_barrier, nprocs)
+#else
+        BARRIER(bars->barrier, nprocs)
+#endif
+        copy_black(k, my_num);
+
+        relax(k, &red_local_err, RED_ITER, my_num);
+
+/* barrier to make sure all red computations have been performed   */
+#if defined(MULTIPLE_BARRIERS)
+        BARRIER(bars->error_barrier, nprocs)
+#else
+        BARRIER(bars->barrier, nprocs)
+#endif
+        copy_red(k, my_num);
+
+        relax(k, &black_local_err, BLACK_ITER, my_num);
+
+/* compute max local error from red_local_err and black_local_err  */
+
+        if (red_local_err > black_local_err) {
+            local_err = red_local_err;
+        } else {
+            local_err = black_local_err;
+        }
+
+/* update the global error if necessary                         */
+
+        LOCK(locks->error_lock)
+            if (local_err > multi->err_multi) {
+            multi->err_multi = local_err;
+        }
+        UNLOCK(locks->error_lock)
+
+/* a single relaxation sweep at the finest level is one unit of    */
+/* work                                                            */
+        wu += pow((double) 4.0, (double) k - m);
+
+/* barrier to make sure all processors have checked local error    */
+#if defined(MULTIPLE_BARRIERS)
+        BARRIER(bars->error_barrier, nprocs)
+#else
+        BARRIER(bars->barrier, nprocs)
+#endif
+        g_error = multi->err_multi;
+
+/* barrier to make sure master does not cycle back to top of loop  */
+/* and reset global->err before we read it and decide what to do   */
+#if defined(MULTIPLE_BARRIERS)
+        BARRIER(bars->error_barrier, nprocs)
+#else
+        BARRIER(bars->barrier, nprocs)
+#endif
+        if (g_error >= lev_tol[k]) {
+            if (wu > wmax) {
+/* max work exceeded                                               */
+                fprintf(stderr, "ERROR: Maximum work limit %0.5f exceeded\n", wmax);
+                exit(-1);
+            } else {
+/* if we have not converged                                        */
+                if ((k != 0) && (g_error / errp >= 0.6) && (k > minlevel)) {
+/* if need to go to coarser grid                                   */
+
+                    copy_borders(k, my_num);
+                    copy_rhs_borders(k, my_num);
+
+/* This bar is needed because the routine rescal uses the neighbor's
+   border points to compute s4.  We must ensure that the neighbor's
+   border points have been written before we try computing the new
+   rescal values                                                   */
+
+#if defined(MULTIPLE_BARRIERS)
+                    BARRIER(bars->error_barrier, nprocs)
+#else
+                    BARRIER(bars->barrier, nprocs)
+#endif
+                    rescal(k, my_num);
+
+/* transfer residual to rhs of coarser grid                        */
+                    lev_tol[k - 1] = 0.3 * g_error;
+                    k = k - 1;
+                    putz(k, my_num);
+/* make initial guess on coarser grid zero                         */
+                    g_error = 1.0e30;
+                }
+            }
+        } else {
+/* if we have converged at this level                              */
+            if (k == m) {
+/* if finest grid, we are done                                     */
+                flag = 1;
+            } else {
+/* else go to next finest grid                                     */
+
+                copy_borders(k, my_num);
+
+                intadd(k, my_num);
+/* changes the grid values at the finer level.  rhs at finer level */
+/* remains what it already is                                      */
+                k++;
+                g_error = 1.0e30;
+            }
+        }
+    }
+    if (do_output) {
+        if (my_num == MASTER) {
+            printf("iter %ld, level %ld, residual norm %12.8e, work = %7.3f\n", iter, k, multi->err_multi, wu);
+        }
+    }
+}
+
+/* perform red or black iteration (not both)                    */
+void relax(long k, double *err, long color, long my_num)
+{
+    long i;
+    long j;
+    long iend;
+    long jend;
+    long oddistart;
+    long oddjstart;
+    long evenistart;
+    long evenjstart;
+    double a;
+    double h;
+    double factor;
+    double maxerr;
+    double newerr;
+    double oldval;
+    double newval;
+    double **t2a;
+    double **t2b;
+    double *t1a;
+    double *t1b;
+    double *t1c;
+    double *t1d;
+
+    i = 0;
+    j = 0;
+
+    *err = 0.0;
+    h = lev_res[k];
+
+/* points whose sum of row and col index is even do a red iteration, */
+/* others do a black				                     */
+
+    evenistart = gp[my_num].eist[k];
+    evenjstart = gp[my_num].ejst[k];
+    oddistart = gp[my_num].oist[k];
+    oddjstart = gp[my_num].ojst[k];
+
+    iend = gp[my_num].rlien[k];
+    jend = gp[my_num].rljen[k];
+
+    factor = 4.0 - eig2 * h * h;
+    maxerr = 0.0;
+    t2a = (double **) q_multi[my_num][k];
+    t2b = (double **) rhs_multi[my_num][k];
+    if (color == RED_ITER) {
+        for (i = evenistart; i < iend; i += 2) {
+            t1a = (double *) t2a[i];
+            t1b = (double *) t2b[i];
+            t1c = (double *) t2a[i - 1];
+            t1d = (double *) t2a[i + 1];
+            for (j = evenjstart; j < jend; j += 2) {
+                a = t1a[j + 1] + t1a[j - 1] + t1c[j] + t1d[j] - t1b[j];
+                oldval = t1a[j];
+                newval = a / factor;
+                newerr = oldval - newval;
+                t1a[j] = newval;
+                if (fabs(newerr) > maxerr) {
+                    maxerr = fabs(newerr);
+                }
+            }
+        }
+        for (i = oddistart; i < iend; i += 2) {
+            t1a = (double *) t2a[i];
+            t1b = (double *) t2b[i];
+            t1c = (double *) t2a[i - 1];
+            t1d = (double *) t2a[i + 1];
+            for (j = oddjstart; j < jend; j += 2) {
+                a = t1a[j + 1] + t1a[j - 1] + t1c[j] + t1d[j] - t1b[j];
+                oldval = t1a[j];
+                newval = a / factor;
+                newerr = oldval - newval;
+                t1a[j] = newval;
+                if (fabs(newerr) > maxerr) {
+                    maxerr = fabs(newerr);
+                }
+            }
+        }
+    } else if (color == BLACK_ITER) {
+        for (i = evenistart; i < iend; i += 2) {
+            t1a = (double *) t2a[i];
+            t1b = (double *) t2b[i];
+            t1c = (double *) t2a[i - 1];
+            t1d = (double *) t2a[i + 1];
+            for (j = oddjstart; j < jend; j += 2) {
+                a = t1a[j + 1] + t1a[j - 1] + t1c[j] + t1d[j] - t1b[j];
+                oldval = t1a[j];
+                newval = a / factor;
+                newerr = oldval - newval;
+                t1a[j] = newval;
+                if (fabs(newerr) > maxerr) {
+                    maxerr = fabs(newerr);
+                }
+            }
+        }
+        for (i = oddistart; i < iend; i += 2) {
+            t1a = (double *) t2a[i];
+            t1b = (double *) t2b[i];
+            t1c = (double *) t2a[i - 1];
+            t1d = (double *) t2a[i + 1];
+            for (j = evenjstart; j < jend; j += 2) {
+                a = t1a[j + 1] + t1a[j - 1] + t1c[j] + t1d[j] - t1b[j];
+                oldval = t1a[j];
+                newval = a / factor;
+                newerr = oldval - newval;
+                t1a[j] = newval;
+                if (fabs(newerr) > maxerr) {
+                    maxerr = fabs(newerr);
+                }
+            }
+        }
+    }
+    *err = maxerr;
+}
+
+/* perform half-injection to next coarsest level                */
+void rescal(long kf, long my_num)
+{
+    long ic;
+    long if17;
+    long jf;
+    long jc;
+    long krc;
+    long istart;
+    long iend;
+    long jstart;
+    long jend;
+    double hf;
+    double s;
+    double s1;
+    double s2;
+    double s3;
+    double s4;
+    double factor;
+    double int1;
+    double int2;
+    double i_int_factor;
+    double j_int_factor;
+    long i_off;
+    long j_off;
+    long up_proc;
+    long left_proc;
+    long im;
+    long jm;
+    double temp;
+    double temp2;
+    double **t2a;
+    double **t2b;
+    double **t2c;
+    double *t1a;
+    double *t1b;
+    double *t1c;
+    double *t1d;
+    double *t1e;
+    double *t1f;
+    double *t1g;
+    double *t1h;
+
+    krc = kf - 1;
+    //hc = lev_res[krc];
+    hf = lev_res[kf];
+    i_off = (*gp[my_num].rownum) * ypts_per_proc[krc];
+    j_off = (*gp[my_num].colnum) * xpts_per_proc[krc];
+    up_proc = gp[my_num].neighbors[UP];
+    left_proc = gp[my_num].neighbors[LEFT];
+    im = (imx[kf] - 2) / yprocs;
+    jm = (jmx[kf] - 2) / xprocs;
+
+    istart = gp[my_num].rlist[krc];
+    jstart = gp[my_num].rljst[krc];
+    iend = gp[my_num].rlien[krc] - 1;
+    jend = gp[my_num].rljen[krc] - 1;
+
+    factor = 4.0 - eig2 * hf * hf;
+
+    t2a = (double **) q_multi[my_num][kf];
+    t2b = (double **) rhs_multi[my_num][kf];
+    t2c = (double **) rhs_multi[my_num][krc];
+    if17 = 2 * (istart - 1);
+    for (ic = istart; ic <= iend; ic++) {
+        if17 += 2;
+        i_int_factor = (ic + i_off) * i_int_coeff[krc] * 0.5;
+        jf = 2 * (jstart - 1);
+        t1a = (double *) t2a[if17];
+        t1b = (double *) t2b[if17];
+        t1c = (double *) t2c[ic];
+        t1d = (double *) t2a[if17 - 1];
+        t1e = (double *) t2a[if17 + 1];
+        t1f = (double *) t2a[if17 - 2];
+        t1g = (double *) t2a[if17 - 3];
+        t1h = (double *) t2b[if17 - 2];
+        for (jc = jstart; jc <= jend; jc++) {
+            jf += 2;
+            j_int_factor = (jc + j_off) * j_int_coeff[krc] * 0.5;
+
+/*             method of half-injection uses 2.0 instead of 4.0 */
+
+/* do bilinear interpolation */
+            s = t1a[jf + 1] + t1a[jf - 1] + t1d[jf] + t1e[jf];
+            s1 = 2.0 * (t1b[jf] - s + factor * t1a[jf]);
+            if (((if17 == 2) && (gp[my_num].neighbors[UP] == -1)) || ((jf == 2) && (gp[my_num].neighbors[LEFT] == -1))) {
+                s2 = 0;
+                s3 = 0;
+                s4 = 0;
+            } else if ((if17 == 2) || (jf == 2)) {
+                if (jf == 2) {
+                    temp = q_multi[left_proc][kf][if17][jm - 1];
+                } else {
+                    temp = t1a[jf - 3];
+                }
+                s = t1a[jf - 1] + temp + t1d[jf - 2] + t1e[jf - 2];
+                s2 = 2.0 * (t1b[jf - 2] - s + factor * t1a[jf - 2]);
+                if (if17 == 2) {
+                    temp = q_multi[up_proc][kf][im - 1][jf];
+                } else {
+                    temp = t1g[jf];
+                }
+                s = t1f[jf + 1] + t1f[jf - 1] + temp + t1d[jf];
+                s3 = 2.0 * (t1h[jf] - s + factor * t1f[jf]);
+                if (jf == 2) {
+                    temp = q_multi[left_proc][kf][if17 - 2][jm - 1];
+                } else {
+                    temp = t1f[jf - 3];
+                }
+                if (if17 == 2) {
+                    temp2 = q_multi[up_proc][kf][im - 1][jf - 2];
+                } else {
+                    temp2 = t1g[jf - 2];
+                }
+                s = t1f[jf - 1] + temp + temp2 + t1d[jf - 2];
+                s4 = 2.0 * (t1h[jf - 2] - s + factor * t1f[jf - 2]);
+            } else {
+                s = t1a[jf - 1] + t1a[jf - 3] + t1d[jf - 2] + t1e[jf - 2];
+                s2 = 2.0 * (t1b[jf - 2] - s + factor * t1a[jf - 2]);
+                s = t1f[jf + 1] + t1f[jf - 1] + t1g[jf] + t1d[jf];
+                s3 = 2.0 * (t1h[jf] - s + factor * t1f[jf]);
+                s = t1f[jf - 1] + t1f[jf - 3] + t1g[jf - 2] + t1d[jf - 2];
+                s4 = 2.0 * (t1h[jf - 2] - s + factor * t1f[jf - 2]);
+            }
+            int1 = j_int_factor * s4 + (1.0 - j_int_factor) * s3;
+            int2 = j_int_factor * s2 + (1.0 - j_int_factor) * s1;
+            //int_val = i_int_factor*int1+(1.0-i_int_factor)*int2;
+            t1c[jc] = i_int_factor * int1 + (1.0 - i_int_factor) * int2;
+        }
+    }
+}
+
+/* perform interpolation and addition to next finest grid       */
+void intadd(long kc, long my_num)
+{
+    long ic;
+    long if17;
+    long jf;
+    long jc;
+    long kf;
+    long istart;
+    long jstart;
+    long iend;
+    long jend;
+    double int1;
+    double int2;
+    double i_int_factor1;
+    double j_int_factor1;
+    double i_int_factor2;
+    double j_int_factor2;
+    long i_off;
+    long j_off;
+    double **t2a;
+    double **t2b;
+    double *t1a;
+    double *t1b;
+    double *t1c;
+    double *t1d;
+    double *t1e;
+
+    kf = kc + 1;
+    //hc = lev_res[kc];
+    //hf = lev_res[kf];
+
+    istart = gp[my_num].rlist[kc];
+    jstart = gp[my_num].rljst[kc];
+    iend = gp[my_num].rlien[kc] - 1;
+    jend = gp[my_num].rljen[kc] - 1;
+    i_off = (*gp[my_num].rownum) * ypts_per_proc[kc];
+    j_off = (*gp[my_num].colnum) * xpts_per_proc[kc];
+
+    t2a = (double **) q_multi[my_num][kc];
+    t2b = (double **) q_multi[my_num][kf];
+    if17 = 2 * (istart - 1);
+    for (ic = istart; ic <= iend; ic++) {
+        if17 += 2;
+        i_int_factor1 = ((imx[kc] - 2) - (ic + i_off - 1)) * (i_int_coeff[kf]);
+        i_int_factor2 = (ic + i_off) * i_int_coeff[kf];
+        jf = 2 * (jstart - 1);
+
+        t1a = (double *) t2a[ic];
+        t1b = (double *) t2a[ic - 1];
+        t1c = (double *) t2a[ic + 1];
+        t1d = (double *) t2b[if17];
+        t1e = (double *) t2b[if17 - 1];
+        for (jc = jstart; jc <= jend; jc++) {
+            jf += 2;
+            j_int_factor1 = ((jmx[kc] - 2) - (jc + j_off - 1)) * (j_int_coeff[kf]);
+            j_int_factor2 = (jc + j_off) * j_int_coeff[kf];
+
+            int1 = j_int_factor1 * t1a[jc - 1] + (1.0 - j_int_factor1) * t1a[jc];
+            int2 = j_int_factor1 * t1b[jc - 1] + (1.0 - j_int_factor1) * t1b[jc];
+            t1e[jf - 1] += i_int_factor1 * int2 + (1.0 - i_int_factor1) * int1;
+            int2 = j_int_factor1 * t1c[jc - 1] + (1.0 - j_int_factor1) * t1c[jc];
+            t1d[jf - 1] += i_int_factor2 * int2 + (1.0 - i_int_factor2) * int1;
+            int1 = j_int_factor2 * t1a[jc + 1] + (1.0 - j_int_factor2) * t1a[jc];
+            int2 = j_int_factor2 * t1b[jc + 1] + (1.0 - j_int_factor2) * t1b[jc];
+            t1e[jf] += i_int_factor1 * int2 + (1.0 - i_int_factor1) * int1;
+            int2 = j_int_factor2 * t1c[jc + 1] + (1.0 - j_int_factor2) * t1c[jc];
+            t1d[jf] += i_int_factor2 * int2 + (1.0 - i_int_factor2) * int1;
+        }
+    }
+}
+
+/* initialize a grid to zero in parallel                        */
+void putz(long k, long my_num)
+{
+    long i;
+    long j;
+    long istart;
+    long jstart;
+    long iend;
+    long jend;
+    double **t2a;
+    double *t1a;
+
+    istart = gp[my_num].rlist[k];
+    jstart = gp[my_num].rljst[k];
+    iend = gp[my_num].rlien[k];
+    jend = gp[my_num].rljen[k];
+
+    t2a = (double **) q_multi[my_num][k];
+    for (i = istart; i <= iend; i++) {
+        t1a = (double *) t2a[i];
+        for (j = jstart; j <= jend; j++) {
+            t1a[j] = 0.0;
+        }
+    }
+}
+
+void copy_borders(long k, long pid)
+{
+    long i;
+    long j;
+    long jj;
+    long im;
+    long jm;
+    long lastrow;
+    long lastcol;
+    double **t2a;
+    double **t2b;
+    double *t1a;
+    double *t1b;
+
+    im = (imx[k] - 2) / yprocs + 2;
+    jm = (jmx[k] - 2) / xprocs + 2;
+    lastrow = (imx[k] - 2) / yprocs;
+    lastcol = (jmx[k] - 2) / xprocs;
+
+    t2a = (double **) q_multi[pid][k];
+    jj = gp[pid].neighbors[UPLEFT];
+    if (jj != -1) {
+        t2a[0][0] = q_multi[jj][k][im - 2][jm - 2];
+    }
+    jj = gp[pid].neighbors[UPRIGHT];
+    if (jj != -1) {
+        t2a[0][jm - 1] = q_multi[jj][k][im - 2][1];
+    }
+    jj = gp[pid].neighbors[DOWNLEFT];
+    if (jj != -1) {
+        t2a[im - 1][0] = q_multi[jj][k][1][jm - 2];
+    }
+    jj = gp[pid].neighbors[DOWNRIGHT];
+    if (jj != -1) {
+        t2a[im - 1][jm - 1] = q_multi[jj][k][1][1];
+    }
+
+    if (gp[pid].neighbors[UP] == -1) {
+        jj = gp[pid].neighbors[LEFT];
+        if (jj != -1) {
+            t2a[0][0] = q_multi[jj][k][0][jm - 2];
+        } else {
+            jj = gp[pid].neighbors[DOWN];
+            if (jj != -1) {
+                t2a[im - 1][0] = q_multi[jj][k][1][0];
+            }
+        }
+        jj = gp[pid].neighbors[RIGHT];
+        if (jj != -1) {
+            t2a[0][jm - 1] = q_multi[jj][k][0][1];
+        } else {
+            jj = gp[pid].neighbors[DOWN];
+            if (jj != -1) {
+                t2a[im - 1][jm - 1] = q_multi[jj][k][1][jm - 1];
+            }
+        }
+    } else if (gp[pid].neighbors[DOWN] == -1) {
+        jj = gp[pid].neighbors[LEFT];
+        if (jj != -1) {
+            t2a[im - 1][0] = q_multi[jj][k][im - 1][jm - 2];
+        } else {
+            jj = gp[pid].neighbors[UP];
+            if (jj != -1) {
+                t2a[0][0] = q_multi[jj][k][im - 2][0];
+            }
+        }
+        jj = gp[pid].neighbors[RIGHT];
+        if (jj != -1) {
+            t2a[im - 1][jm - 1] = q_multi[jj][k][im - 1][1];
+        } else {
+            jj = gp[pid].neighbors[UP];
+            if (jj != -1) {
+                t2a[0][jm - 1] = q_multi[jj][k][im - 2][jm - 1];
+            }
+        }
+    } else if (gp[pid].neighbors[LEFT] == -1) {
+        jj = gp[pid].neighbors[UP];
+        if (jj != -1) {
+            t2a[0][0] = q_multi[jj][k][im - 2][0];
+        }
+        jj = gp[pid].neighbors[DOWN];
+        if (jj != -1) {
+            t2a[im - 1][0] = q_multi[jj][k][1][0];
+        }
+    } else if (gp[pid].neighbors[RIGHT] == -1) {
+        jj = gp[pid].neighbors[UP];
+        if (jj != -1) {
+            t2a[0][jm - 1] = q_multi[jj][k][im - 2][jm - 1];
+        }
+        jj = gp[pid].neighbors[DOWN];
+        if (jj != -1) {
+            t2a[im - 1][jm - 1] = q_multi[jj][k][1][jm - 1];
+        }
+    }
+
+    j = gp[pid].neighbors[UP];
+    if (j != -1) {
+        t1a = (double *) t2a[0];
+        t1b = (double *) q_multi[j][k][im - 2];
+        for (i = 1; i <= lastcol; i++) {
+            t1a[i] = t1b[i];
+        }
+    }
+    j = gp[pid].neighbors[DOWN];
+    if (j != -1) {
+        t1a = (double *) t2a[im - 1];
+        t1b = (double *) q_multi[j][k][1];
+        for (i = 1; i <= lastcol; i++) {
+            t1a[i] = t1b[i];
+        }
+    }
+    j = gp[pid].neighbors[LEFT];
+    if (j != -1) {
+        t2b = (double **) q_multi[j][k];
+        for (i = 1; i <= lastrow; i++) {
+            t2a[i][0] = t2b[i][jm - 2];
+        }
+    }
+    j = gp[pid].neighbors[RIGHT];
+    if (j != -1) {
+        t2b = (double **) q_multi[j][k];
+        for (i = 1; i <= lastrow; i++) {
+            t2a[i][jm - 1] = t2b[i][1];
+        }
+    }
+
+}
+
+void copy_rhs_borders(long k, long procid)
+{
+    long i;
+    long j;
+    long im;
+    long jm;
+    long lastrow;
+    long lastcol;
+    double **t2a;
+    double **t2b;
+    double *t1a;
+    double *t1b;
+
+    im = (imx[k] - 2) / yprocs + 2;
+    jm = (jmx[k] - 2) / xprocs + 2;
+    lastrow = (imx[k] - 2) / yprocs;
+    lastcol = (jmx[k] - 2) / xprocs;
+
+    t2a = (double **) rhs_multi[procid][k];
+    if (gp[procid].neighbors[UPLEFT] != -1) {
+        j = gp[procid].neighbors[UPLEFT];
+        t2a[0][0] = rhs_multi[j][k][im - 2][jm - 2];
+    }
+
+    if (gp[procid].neighbors[UP] != -1) {
+        j = gp[procid].neighbors[UP];
+        if (j != -1) {
+            t1a = (double *) t2a[0];
+            t1b = (double *) rhs_multi[j][k][im - 2];
+            for (i = 2; i <= lastcol; i += 2) {
+                t1a[i] = t1b[i];
+            }
+        }
+    }
+    if (gp[procid].neighbors[LEFT] != -1) {
+        j = gp[procid].neighbors[LEFT];
+        if (j != -1) {
+            t2b = (double **) rhs_multi[j][k];
+            for (i = 2; i <= lastrow; i += 2) {
+                t2a[i][0] = t2b[i][jm - 2];
+            }
+        }
+    }
+}
+
+void copy_red(long k, long procid)
+{
+    long i;
+    long j;
+    long im;
+    long jm;
+    long lastrow;
+    long lastcol;
+    double **t2a;
+    double **t2b;
+    double *t1a;
+    double *t1b;
+
+    im = (imx[k] - 2) / yprocs + 2;
+    jm = (jmx[k] - 2) / xprocs + 2;
+    lastrow = (imx[k] - 2) / yprocs;
+    lastcol = (jmx[k] - 2) / xprocs;
+
+    t2a = (double **) q_multi[procid][k];
+    j = gp[procid].neighbors[UP];
+    if (j != -1) {
+        t1a = (double *) t2a[0];
+        t1b = (double *) q_multi[j][k][im - 2];
+        for (i = 2; i <= lastcol; i += 2) {
+            t1a[i] = t1b[i];
+        }
+    }
+    j = gp[procid].neighbors[DOWN];
+    if (j != -1) {
+        t1a = (double *) t2a[im - 1];
+        t1b = (double *) q_multi[j][k][1];
+        for (i = 1; i <= lastcol; i += 2) {
+            t1a[i] = t1b[i];
+        }
+    }
+    j = gp[procid].neighbors[LEFT];
+    if (j != -1) {
+        t2b = (double **) q_multi[j][k];
+        for (i = 2; i <= lastrow; i += 2) {
+            t2a[i][0] = t2b[i][jm - 2];
+        }
+    }
+    j = gp[procid].neighbors[RIGHT];
+    if (j != -1) {
+        t2b = (double **) q_multi[j][k];
+        for (i = 1; i <= lastrow; i += 2) {
+            t2a[i][jm - 1] = t2b[i][1];
+        }
+    }
+}
+
+void copy_black(long k, long procid)
+{
+    long i;
+    long j;
+    long im;
+    long jm;
+    long lastrow;
+    long lastcol;
+    double **t2a;
+    double **t2b;
+    double *t1a;
+    double *t1b;
+
+    im = (imx[k] - 2) / yprocs + 2;
+    jm = (jmx[k] - 2) / xprocs + 2;
+    lastrow = (imx[k] - 2) / yprocs;
+    lastcol = (jmx[k] - 2) / xprocs;
+
+    t2a = (double **) q_multi[procid][k];
+    j = gp[procid].neighbors[UP];
+    if (j != -1) {
+        t1a = (double *) t2a[0];
+        t1b = (double *) q_multi[j][k][im - 2];
+        for (i = 1; i <= lastcol; i += 2) {
+            t1a[i] = t1b[i];
+        }
+    }
+    j = gp[procid].neighbors[DOWN];
+    if (j != -1) {
+        t1a = (double *) t2a[im - 1];
+        t1b = (double *) q_multi[j][k][1];
+        for (i = 2; i <= lastcol; i += 2) {
+            t1a[i] = t1b[i];
+        }
+    }
+    j = gp[procid].neighbors[LEFT];
+    if (j != -1) {
+        t2b = (double **) q_multi[j][k];
+        for (i = 1; i <= lastrow; i += 2) {
+            t2a[i][0] = t2b[i][jm - 2];
+        }
+    }
+    j = gp[procid].neighbors[RIGHT];
+    if (j != -1) {
+        t2b = (double **) q_multi[j][k];
+        for (i = 2; i <= lastrow; i += 2) {
+            t2a[i][jm - 1] = t2b[i][1];
+        }
+    }
+}
Index: /soft/giet_vm/applications/ocean/null_macros/c.m4.null
===================================================================
--- /soft/giet_vm/applications/ocean/null_macros/c.m4.null	(revision 581)
+++ /soft/giet_vm/applications/ocean/null_macros/c.m4.null	(revision 581)
@@ -0,0 +1,99 @@
+divert(-1)
+define(NEWPROC,) dnl
+
+define(BARRIER, `{;}')
+define(BARDEC, `long ($1);')
+define(BARINIT, `{;}')
+
+define(BAREXCLUDE, `{;}')
+
+define(BARINCLUDE, `{;}')
+
+define(GSDEC, `long ($1);')
+define(GSINIT, `{ ($1) = 0; }')
+define(GETSUB, `{
+  if (($1)<=($3))
+    ($2) = ($1)++;
+  else {
+    ($2) = -1;
+    ($1) = 0;
+  }
+}')
+
+define(NU_GSDEC, `long ($1);')
+define(NU_GSINIT, `{ ($1) = 0; }')
+define(NU_GETSUB, `GETSUB($1,$2,$3,$4)')
+
+define(ADEC, `long ($1);')
+define(AINIT, `{;}')
+define(PROBEND, `{;}')
+
+define(LOCKDEC, `long ($1);')
+define(LOCKINIT, `{;}')
+define(LOCK, `{;}')
+define(UNLOCK, `{;}')
+
+define(NLOCKDEC, `long ($1);')
+define(NLOCKINIT, `{;}')
+define(NLOCK, `{;}')
+define(NUNLOCK, `{;}')
+
+define(ALOCKDEC, `long ($1);')
+define(ALOCKINIT, `{;}')
+define(ALOCK, `{;}')
+define(AULOCK, `{;}')
+
+define(PAUSEDEC, ` ')
+define(PAUSEINIT, `{;}')
+define(CLEARPAUSE, `{;}')
+define(SETPAUSE, `{;}')
+define(EVENT, `{;}')
+define(WAITPAUSE, `{;}')
+define(PAUSE, `{;}')
+
+define(AUG_ON, ` ')
+define(AUG_OFF, ` ')
+define(TRACE_ON, ` ')
+define(TRACE_OFF, ` ')
+define(REF_TRACE_ON, ` ')
+define(REF_TRACE_OFF, ` ')
+define(DYN_TRACE_ON, `;')
+define(DYN_TRACE_OFF, `;')
+define(DYN_REF_TRACE_ON, `;')
+define(DYN_REF_TRACE_OFF, `;')
+define(DYN_SIM_ON, `;')
+define(DYN_SIM_OFF, `;')
+define(DYN_SCHED_ON, `;')
+define(DYN_SCHED_OFF, `;')
+define(AUG_SET_LOLIMIT, `;')
+define(AUG_SET_HILIMIT, `;')
+
+define(MENTER, `{;}')
+define(DELAY, `{;}')
+define(CONTINUE, `{;}')
+define(MEXIT, `{;}')
+define(MONINIT, `{;}')
+
+define(WAIT_FOR_END, `{;}')
+
+define(CREATE, `{fprintf(stderr, "No more processors -- this is a uniprocessor version!\n"); exit(-1);}')
+define(MAIN_INITENV, `{;}')
+define(MAIN_END, `{exit(0);}')
+define(MAIN_ENV,` ')
+define(ENV, ` ')
+define(EXTERN_ENV, ` ')
+
+define(G_MALLOC, `malloc($1);')
+define(G_FREE, `;')
+define(G_MALLOC_F, `malloc($1)')
+define(NU_MALLOC, `malloc($1);')
+define(NU_FREE, `;')
+define(NU_MALLOC_F, `malloc($1)')
+
+define(GET_HOME, `{($1) = 0;}')
+define(GET_PID, `{($1) = 0;}')
+define(AUG_DELAY, `{sleep ($1);}')
+define(ST_LOG, `{;}')
+define(SET_HOME, `{;}')
+define(CLOCK, `{long time(); ($1) = time(0);}')
+divert(0)
Index: /soft/giet_vm/applications/ocean/null_macros/c.m4.null.GIET
===================================================================
--- /soft/giet_vm/applications/ocean/null_macros/c.m4.null.GIET	(revision 581)
+++ /soft/giet_vm/applications/ocean/null_macros/c.m4.null.GIET	(revision 581)
@@ -0,0 +1,115 @@
+divert(-1)
+define(NEWPROC,) dnl
+
+define(BARRIER, `{
+    unsigned int wait_start, wait_end;
+    unsigned int id = giet_thread_id();
+    
+    CLOCK(wait_start)
+    sqt_barrier_wait(&($1));
+    CLOCK(wait_end)
+    *gp[id].sync_time += wait_end - wait_start;
+    
+}')
+
+define(BARDEC, `
+giet_sqt_barrier_t ($1);
+')
+
+define(BARINIT, `{
+    giet_assert (nclusters_x * nclusters_y * procs_per_cluster == (unsigned int)$2, "Incorrect mesh for sqt_barrier\n");
+    
+    while (heap_inited != $2) {
+        asm volatile("nop\r\n");
+    }
+    giet_shr_printf("Tas initialisÃ©s\n");
+	sqt_barrier_init(&($1), nclusters_x, nclusters_y, procs_per_cluster);
+}')
+
+define(LOCKDEC, `sqt_lock_t ($1);')
+define(LOCKINIT, `{
+    sqt_lock_init(&($1), nclusters_x, nclusters_y, procs_per_cluster);
+}')
+define(LOCK, `{
+    unsigned int wait_start, wait_end;
+    unsigned int id = giet_thread_id();
+    CLOCK(wait_start)
+    sqt_lock_acquire(&($1));
+    CLOCK(wait_end)
+    *gp[id].sync_time += wait_end - wait_start;
+}')
+define(UNLOCK, `{sqt_lock_release(&($1));}')
+
+define(WAIT_FOR_END, `{
+	giet_shr_printf("Wait threads...\n");
+	BARRIER(bars->barrier)
+}')
+
+define(CREATE, `{
+    long id_main = 0;
+	run_threads = 1;
+   $1(&id_main);
+}')
+
+define(MAIN_INITENV, `{
+    giet_procs_number(&nclusters_x, &nclusters_y, &procs_per_cluster);
+	heap_init(0, 0);
+	heap_inited += procs_per_cluster;
+}')
+define(MAIN_END, `{exit(0); return 0;}')
+
+define(MAIN_ENV,`
+#include <user_sqt_lock.h>
+#include <user_barrier.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <malloc.h>
+#include "giet_utils.h"
+
+#define MAX_THREADS 512
+/*#include <pthread.h>
+#include <sys/time.h>
+#include <sys/fcntl.h>
+#include <sys/resource.h>
+#include <unistd.h>
+#include <stdlib.h>
+pthread_t PThreadTable[MAX_THREADS];
+*/
+')
+
+define(ENV, ` ')
+define(EXTERN_ENV, `
+
+#include <user_sqt_lock.h>
+#include <user_barrier.h>
+#include <stdio.h>
+#include <malloc.h>
+
+#include "giet_utils.h"
+
+/*#include <pthread.h>
+#include <sys/time.h>
+#include <sys/stat.h>
+#include <sys/resource.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <stdio.h>
+extern pthread_t PThreadTable[];*/
+')
+
+define(G_MALLOC, `ocean_malloc($1, $2);')
+
+define(CLOCK, `{
+   ($1) = giet_proctime();
+}')
+
+define(START_PHASE, `{
+    CLOCK(*gp[$1].step_start)
+}')
+define(END_PHASE, `{
+    unsigned int t;
+    CLOCK(t)
+    gp[$1].steps_time[($2)-1] += (double)t - *gp[$1].step_start;
+}')
+
+divert(0)
Index: /soft/giet_vm/applications/ocean/null_macros/c.m4.null.POSIX
===================================================================
--- /soft/giet_vm/applications/ocean/null_macros/c.m4.null.POSIX	(revision 581)
+++ /soft/giet_vm/applications/ocean/null_macros/c.m4.null.POSIX	(revision 581)
@@ -0,0 +1,143 @@
+divert(-1)
+define(NEWPROC,) dnl
+
+define(BARRIER, `{
+   long int cycle;
+   int cancel, temp, error;
+   
+
+   error = pthread_mutex_lock(&($1).mutex);
+   if (error != 0) {
+      printf("Error while trying to get lock in barrier.\n");
+      exit(-1);
+   }
+
+   cycle = ($1).cycle;
+   if (++($1).counter != ($2)) {
+      pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &cancel);
+      while (cycle == ($1).cycle) {
+         error = pthread_cond_wait(&($1).cv, &($1).mutex);
+         if (error != 0) {
+            break;
+         }
+      }
+      pthread_setcancelstate(cancel, &temp);
+   } else {
+      ($1).cycle = !($1).cycle;
+      ($1).counter = 0;
+      error = pthread_cond_broadcast(&($1).cv);
+   }
+   pthread_mutex_unlock(&($1).mutex);
+}')
+
+define(BARDEC, `
+struct {
+   pthread_mutex_t mutex;
+   pthread_cond_t cv;
+   long int counter;
+   long int cycle;
+} ($1);
+')
+
+define(BARINIT, `{
+   long int error;
+
+   error = pthread_mutex_init(&($1).mutex, NULL);
+   if (error != 0) {
+      printf("Error while initializing barrier.\n");
+      exit(-1);
+   }
+
+   error = pthread_cond_init(&($1).cv, NULL);
+   if (error != 0) {
+      printf("Error while initializing barrier.\n");
+      pthread_mutex_destroy(&($1).mutex);
+      exit(-1);
+   }
+
+   ($1).counter = 0;
+   ($1).cycle = 0;
+}')
+
+define(LOCKDEC, `pthread_mutex_t ($1);')
+define(LOCKINIT, `{pthread_mutex_init(&($1), NULL);}')
+define(LOCK, `{
+    pthread_mutex_lock(&($1));
+    }')
+define(UNLOCK, `{pthread_mutex_unlock(&($1));}')
+
+define(WAIT_FOR_END, `{
+   long int i, error;
+   for (i = 0; i < ($1) - 1; i++) {
+      error = pthread_join(PThreadTable[i], NULL);
+      if (error != 0) {
+         printf("Error in pthread_join().\n");
+         exit(-1);
+      }
+   }
+}')
+
+define(CREATE, `{
+   long i, error;
+
+   for (i = 0; i < ($2) - 1; i++) {
+      error = pthread_create(&PThreadTable[i], NULL, (void * (*)(void *))($1), &ids_procs[i+1]);
+      if (error != 0) {
+         printf("Error in pthread_create().\n");
+         exit(-1);
+      }
+   }
+   $1(&ids_procs[0]);
+}')
+
+define(MAIN_INITENV, `{;}')
+define(MAIN_END, `{exit(0);}')
+
+define(MAIN_ENV,`
+#include <pthread.h>
+#include <sys/time.h>
+#include <sys/fcntl.h>
+#include <sys/resource.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <time.h>
+#define MAX_THREADS 512
+pthread_t PThreadTable[MAX_THREADS];
+')
+
+define(ENV, ` ')
+define(EXTERN_ENV, `
+#include <stdio.h>
+#include <math.h>
+#include <time.h>
+#include <pthread.h>
+#include <sys/time.h>
+#include <sys/stat.h>
+#include <sys/resource.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <stdio.h>
+extern pthread_t PThreadTable[];
+')
+
+define(G_MALLOC, `malloc($1);')
+
+define(CLOCK, `{
+   struct timeval   FullTime;
+
+   gettimeofday(&FullTime, NULL);
+   ($1) = (unsigned long)(FullTime.tv_usec + FullTime.tv_sec * 1000000);
+}')
+
+define(START_PHASE, `{
+    CLOCK(*gp[$1].step_start)
+}')
+
+define(END_PHASE, `{
+    unsigned int t;
+    CLOCK(t)
+    gp[$1].steps_time[($2)-1] += (double)t - *gp[$1].step_start;
+}')
+
+divert(0)
Index: /soft/giet_vm/applications/ocean/null_macros/c.m4.null.POSIX_BARRIER
===================================================================
--- /soft/giet_vm/applications/ocean/null_macros/c.m4.null.POSIX_BARRIER	(revision 581)
+++ /soft/giet_vm/applications/ocean/null_macros/c.m4.null.POSIX_BARRIER	(revision 581)
@@ -0,0 +1,185 @@
+divert(-1)
+define(NEWPROC,) dnl
+
+define(BARRIER, `{
+	pthread_barrier_wait(&($1));
+}')
+
+define(BARDEC, `
+pthread_barrier_t	($1);
+')
+
+define(BARINIT, `{
+	pthread_barrier_init(&($1), NULL, $2);
+}')
+
+define(BAREXCLUDE, `{;}')
+
+define(BARINCLUDE, `{;}')
+
+define(GSDEC, `long ($1);')
+define(GSINIT, `{ ($1) = 0; }')
+define(GETSUB, `{
+  if (($1)<=($3))
+    ($2) = ($1)++;
+  else {
+    ($2) = -1;
+    ($1) = 0;
+  }
+}')
+
+define(NU_GSDEC, `long ($1);')
+define(NU_GSINIT, `{ ($1) = 0; }')
+define(NU_GETSUB, `GETSUB($1,$2,$3,$4)')
+
+define(ADEC, `long ($1);')
+define(AINIT, `{;}')
+define(PROBEND, `{;}')
+
+define(LOCKDEC, `pthread_mutex_t ($1);')
+define(LOCKINIT, `{pthread_mutex_init(&($1), NULL);}')
+define(LOCK, `{pthread_mutex_lock(&($1));}')
+define(UNLOCK, `{pthread_mutex_unlock(&($1));}')
+
+define(NLOCKDEC, `long ($1);')
+define(NLOCKINIT, `{;}')
+define(NLOCK, `{;}')
+define(NUNLOCK, `{;}')
+
+define(ALOCKDEC, `pthread_mutex_t $1[$2];')
+define(ALOCKINIT, `{
+	unsigned long	i, Error;
+
+	for (i = 0; i < $2; i++) {
+		Error = pthread_mutex_init(&$1[i], NULL);
+		if (Error != 0) {
+			printf("Error while initializing array of locks.\n");
+			exit(-1);
+		}
+	}
+}')
+define(ALOCK, `{pthread_mutex_lock(&$1[$2]);}')
+define(AULOCK, `{pthread_mutex_unlock(&$1[$2]);}')
+
+define(PAUSEDEC, `
+struct {
+	pthread_mutex_t	Mutex;
+	pthread_cond_t	CondVar;
+	unsigned long	Flag;
+} $1;
+')
+define(PAUSEINIT, `{
+	pthread_mutex_init(&$1.Mutex, NULL);
+	pthread_cond_init(&$1.CondVar, NULL);
+	$1.Flag = 0;
+}
+')
+define(CLEARPAUSE, `{
+	$1.Flag = 0;
+	pthread_mutex_unlock(&$1.Mutex);}
+')
+define(SETPAUSE, `{
+	pthread_mutex_lock(&$1.Mutex);
+	$1.Flag = 1;
+	pthread_cond_broadcast(&$1.CondVar);
+	pthread_mutex_unlock(&$1.Mutex);}
+')
+define(EVENT, `{;}')
+define(WAITPAUSE, `{
+	pthread_mutex_lock(&$1.Mutex);
+	if ($1.Flag == 0) {
+		pthread_cond_wait(&$1.CondVar, &$1.Mutex);
+	}
+}')
+define(PAUSE, `{;}')
+
+define(AUG_ON, ` ')
+define(AUG_OFF, ` ')
+define(TRACE_ON, ` ')
+define(TRACE_OFF, ` ')
+define(REF_TRACE_ON, ` ')
+define(REF_TRACE_OFF, ` ')
+define(DYN_TRACE_ON, `;')
+define(DYN_TRACE_OFF, `;')
+define(DYN_REF_TRACE_ON, `;')
+define(DYN_REF_TRACE_OFF, `;')
+define(DYN_SIM_ON, `;')
+define(DYN_SIM_OFF, `;')
+define(DYN_SCHED_ON, `;')
+define(DYN_SCHED_OFF, `;')
+define(AUG_SET_LOLIMIT, `;')
+define(AUG_SET_HILIMIT, `;')
+
+define(MENTER, `{;}')
+define(DELAY, `{;}')
+define(CONTINUE, `{;}')
+define(MEXIT, `{;}')
+define(MONINIT, `{;}')
+
+define(WAIT_FOR_END, `{
+	long	i, Error;
+	for (i = 0; i < ($1) - 1; i++) {
+		Error = pthread_join(PThreadTable[i], NULL);
+		if (Error != 0) {
+			printf("Error in pthread_join().\n");
+			exit(-1);
+		}
+	}
+}')
+
+define(CREATE, `{
+	long	i, Error;
+
+	for (i = 0; i < ($2) - 1; i++) {
+		Error = pthread_create(&PThreadTable[i], NULL, (void * (*)(void *))($1), NULL);
+		if (Error != 0) {
+			printf("Error in pthread_create().\n");
+			exit(-1);
+		}
+	}
+
+	$1();
+}')
+
+define(MAIN_INITENV, `{;}')
+define(MAIN_END, `{exit(0);}')
+
+define(MAIN_ENV,`
+#include <pthread.h>
+#include <sys/time.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <malloc.h>
+#define MAX_THREADS 32
+pthread_t PThreadTable[MAX_THREADS];
+')
+
+define(ENV, ` ')
+define(EXTERN_ENV, `
+#include <pthread.h>
+#include <sys/time.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <malloc.h>
+extern pthread_t PThreadTable[];
+')
+
+define(G_MALLOC, `valloc($1);')
+define(G_FREE, `;')
+define(G_MALLOC_F, `valloc($1)')
+define(NU_MALLOC, `valloc($1);')
+define(NU_FREE, `;')
+define(NU_MALLOC_F, `valloc($1)')
+
+define(GET_HOME, `{($1) = 0;}')
+define(GET_PID, `{($1) = 0;}')
+define(AUG_DELAY, `{sleep ($1);}')
+define(ST_LOG, `{;}')
+define(SET_HOME, `{;}')
+define(CLOCK, `{
+	struct timeval	FullTime;
+
+	gettimeofday(&FullTime, NULL);
+	($1) = (unsigned long)(FullTime.tv_usec + FullTime.tv_sec * 1000000);
+}')
+divert(0)
Index: /soft/giet_vm/applications/ocean/null_macros/c.m4.null.SOCLIB
===================================================================
--- /soft/giet_vm/applications/ocean/null_macros/c.m4.null.SOCLIB	(revision 581)
+++ /soft/giet_vm/applications/ocean/null_macros/c.m4.null.SOCLIB	(revision 581)
@@ -0,0 +1,200 @@
+divert(-1)
+define(NEWPROC,) dnl
+
+define(BARRIER, `{
+	pthread_barrier_wait(&($1));
+}')
+
+define(BARDEC, `
+   pthread_barrier_t	($1);
+')
+
+define(BARINIT, `{
+	pthread_barrier_init(&($1), NULL, $2);
+}')
+
+define(BAREXCLUDE, `{;}')
+
+define(BARINCLUDE, `{;}')
+
+define(GSDEC, `long int ($1);')
+define(GSINIT, `{ ($1) = 0; }')
+define(GETSUB, `{
+  if (($1)<=($3))
+    ($2) = ($1)++;
+  else {
+    ($2) = -1;
+    ($1) = 0;
+  }
+}')
+
+define(NU_GSDEC, `long int ($1);')
+define(NU_GSINIT, `{ ($1) = 0; }')
+define(NU_GETSUB, `GETSUB($1,$2,$3,$4)')
+
+define(ADEC, `long int ($1);')
+define(AINIT, `{;}')
+define(PROBEND, `{;}')
+
+define(LOCKDEC, `pthread_mutex_t ($1);')
+define(LOCKINIT, `{pthread_mutex_init(&($1), NULL);}')
+define(LOCK, `{pthread_mutex_lock(&($1));}')
+define(UNLOCK, `{pthread_mutex_unlock(&($1));}')
+
+define(NLOCKDEC, `long int ($1);')
+define(NLOCKINIT, `{;}')
+define(NLOCK, `{;}')
+define(NUNLOCK, `{;}')
+
+define(ALOCKDEC, `pthread_mutex_t $1[$2];')
+define(ALOCKINIT, `{
+   unsigned long int i, error;
+
+   for (i = 0; i < $2; i++) {
+      error = pthread_mutex_init(&$1[i], NULL);
+      if (error != 0) {
+         printf("Error while initializing array of locks.\n");
+         exit(-1);
+      }
+   }
+}')
+define(ALOCK, `{pthread_mutex_lock(&$1[$2]);}')
+define(AULOCK, `{pthread_mutex_unlock(&$1[$2]);}')
+
+
+define(PAUSEDEC, `
+struct {
+   pthread_mutex_t   mutex;
+   pthread_cond_t    cond_var;
+   unsigned long int Flag;
+} $1;
+')
+
+define(PAUSEINIT, `{
+   pthread_mutex_init(&$1.mutex, NULL);
+   pthread_cond_init(&$1.cond_var, NULL);
+   $1.Flag = 0;
+}
+')
+
+define(CLEARPAUSE, `{
+   $1.Flag = 0;
+   pthread_mutex_unlock(&$1.mutex);}
+')
+define(SETPAUSE, `{
+   pthread_mutex_lock(&$1.mutex);
+   $1.Flag = 1;
+   pthread_cond_broadcast(&$1.cond_var);
+   pthread_mutex_unlock(&$1.mutex);}
+')
+
+define(EVENT, `{;}')
+define(WAITPAUSE, `{
+   pthread_mutex_lock(&$1.mutex);
+   if ($1.Flag == 0) {
+      pthread_cond_wait(&$1.cond_var, &$1.mutex);
+   }
+}')
+define(PAUSE, `{;}')
+
+define(AUG_ON, ` ')
+define(AUG_OFF, ` ')
+define(TRACE_ON, ` ')
+define(TRACE_OFF, ` ')
+define(REF_TRACE_ON, ` ')
+define(REF_TRACE_OFF, ` ')
+define(DYN_TRACE_ON, `;')
+define(DYN_TRACE_OFF, `;')
+define(DYN_REF_TRACE_ON, `;')
+define(DYN_REF_TRACE_OFF, `;')
+define(DYN_SIM_ON, `;')
+define(DYN_SIM_OFF, `;')
+define(DYN_SCHED_ON, `;')
+define(DYN_SCHED_OFF, `;')
+define(AUG_SET_LOLIMIT, `;')
+define(AUG_SET_HILIMIT, `;')
+
+define(MENTER, `{;}')
+define(DELAY, `{;}')
+define(CONTINUE, `{;}')
+define(MEXIT, `{;}')
+define(MONINIT, `{;}')
+
+define(WAIT_FOR_END, `{
+   long int i, error;
+   for (i = 1; i < ($1); i++) {
+      error = pthread_join(PThreadTable[i], NULL);
+      if (error != 0) {
+         printf("Error in pthread_join().\n");
+         exit(-1);
+      }
+   }
+}')
+
+define(CREATE, `{
+   long int i, error;
+   pthread_attr_t attr;
+   
+   error = pthread_attr_init(&attr);
+   if (error != 0) {
+      fprintf(stderr, "*** Error in pthread_attr_init\n");
+      exit(1);
+   }
+
+   // HypothÃšse : le thread "main" s exÃ©cute sur le proc 0 ; pour almos utiliser l option -p x de exec dans le shrc
+   for (i = 1; i < ($2); i++) {
+      pthread_attr_setcpuid_np(&attr, i, NULL);
+
+      error = pthread_create(&PThreadTable[i], &attr, (void * (*)(void *))($1), NULL);
+      if (error != 0) {
+         printf("Error in pthread_create().\n");
+         exit(-1);
+      }
+   }
+
+   $1();
+}')
+
+define(MAIN_INITENV, `{;}')
+define(MAIN_END, `{
+   *(unsigned int *) 0x0 = 0xDEADDEAD;
+   return 0;
+}')
+
+define(MAIN_ENV,`
+#include <pthread.h>
+//#include <sys/time.h>
+#include <unistd.h>
+#include <stdlib.h>
+#define MAX_THREADS 512
+pthread_t PThreadTable[MAX_THREADS];
+')
+
+define(ENV, ` ')
+define(EXTERN_ENV, `
+#include <pthread.h>
+//#include <sys/time.h>
+#include <unistd.h>
+#include <stdlib.h>
+extern pthread_t PThreadTable[];
+')
+
+define(G_MALLOC, `malloc($1);')
+define(G_FREE, `free($1);')
+define(G_MALLOC_F, `malloc($1)')
+define(NU_MALLOC, `malloc($1);')
+define(NU_FREE, `free($1);')
+define(NU_MALLOC_F, `malloc($1)')
+
+define(GET_HOME, `{($1) = 0;}')
+define(GET_PID, `{($1) = 0;}')
+define(AUG_DELAY, `{sleep ($1);}')
+define(ST_LOG, `{;}')
+define(SET_HOME, `{;}')
+define(CLOCK, `{
+   struct timeval timer;
+
+   gettimeofday(&timer, NULL);
+   ($1) = (unsigned long long int) (timer.tv_sec); // Number of cycles of simulation
+}')
+divert(0)
Index: /soft/giet_vm/applications/ocean/ocean.ld
===================================================================
--- /soft/giet_vm/applications/ocean/ocean.ld	(revision 581)
+++ /soft/giet_vm/applications/ocean/ocean.ld	(revision 581)
@@ -0,0 +1,46 @@
+/****************************************************************************
+* Definition of the base address for all virtual segments
+*****************************************************************************/
+
+seg_code_base      = 0x10000000;
+seg_data_base      = 0x20000000;
+seg_ldata_base     = 0x20200000;
+
+/***************************************************************************
+* Grouping sections into segments for code and data
+***************************************************************************/
+
+SECTIONS
+{
+    . = seg_code_base;
+    seg_code : 
+    {
+        . = ALIGN(0x40);
+        *(.text)
+        *(.text.*)
+        . = ALIGN(0x40);
+        *(.rodata)
+        *(.rodata.*)
+    }
+    . = seg_data_base;
+    seg_data : 
+    {
+        . = ALIGN(0x40);
+        *(.ctors)
+        *(.data)
+        *(.lit8)
+        *(.lit4)
+        *(.sdata)
+        *(.bss)
+        *(COMMON)
+        *(.sbss)
+        *(.scommon)
+    }
+    . = seg_ldata_base;
+    seg_ldata :
+    {
+        . = ALIGN(0x40);
+        *(seg_ldata)
+    }
+}
+
Index: /soft/giet_vm/applications/ocean/ocean.py
===================================================================
--- /soft/giet_vm/applications/ocean/ocean.py	(revision 581)
+++ /soft/giet_vm/applications/ocean/ocean.py	(revision 581)
@@ -0,0 +1,149 @@
+#!/usr/bin/env python
+
+from mapping import *
+
+##################################################################################
+#   file   : ocean.py  (for the ocean application)
+#   date   : may 2014
+#   author : Alain Greiner
+##################################################################################
+#  This file describes the mapping of the multi-threaded "ocean" 
+#  application on a multi-clusters, multi-processors architecture.
+#  This include both the mapping of virtual segments on the clusters,
+#  and the mapping of tasks on processors.
+#  There is one task per processor.
+#  The mapping of virtual segments is the following:
+#    - There is one shared data vseg in cluster[0][0]
+#    - The code vsegs are replicated on all clusters containing processors.
+#    - There is one heap vseg per cluster containing processors.
+#    - The stacks vsegs are distibuted on all clusters containing processors.
+#  This mapping uses 5 platform parameters, (obtained from the "mapping" argument)
+#    - x_size    : number of clusters in a row
+#    - y_size    : number of clusters in a column
+#    - x_width   : number of bits coding x coordinate
+#    - y_width   : number of bits coding y coordinate
+#    - nprocs    : number of processors per cluster
+##################################################################################
+
+#########################
+def ocean( mapping ):
+
+    x_size    = mapping.x_size
+    y_size    = mapping.y_size
+    nprocs    = mapping.nprocs
+    x_width   = mapping.x_width
+    y_width   = mapping.y_width
+
+    # define vsegs base & size
+    code_base  = 0x10000000
+    code_size  = 0x00100000     # (replicated in each cluster)
+    
+    data_base  = 0x20000000
+    data_size  = 0x00020000     # 128 Kbytes (non replicated)
+    
+    ldata_base = 0x20200000     # 16 Ko (per cluster)
+    ldata_size = 0x00004000
+
+    stack_base = 0x40000000 
+    stack_size = 0x00200000     # 2 Mbytes (per cluster)
+
+    heap_base  = 0x60000000
+    heap_size  = 0x08000000     # 128 Mbytes (per cluster) 
+
+    # create vspace
+    vspace = mapping.addVspace( name = 'ocean', startname = 'ocean_data' )
+    
+    # data vseg : shared (only in cluster[0,0])
+    mapping.addVseg( vspace, 'ocean_data', data_base , data_size, 
+                     'C_WU', vtype = 'ELF', x = 0, y = 0, pseg = 'RAM', 
+                     binpath = 'build/ocean/ocean.elf',
+                     local = False )
+
+    # code vsegs : local (one copy in each cluster)
+    for x in xrange (x_size):
+        for y in xrange (y_size):
+            cluster_id = (x * y_size) + y
+            if ( mapping.clusters[cluster_id].procs ):
+
+                mapping.addVseg( vspace, 'ocean_code_%d_%d' %(x,y), 
+                                 code_base , code_size,
+                                 'CXWU', vtype = 'ELF', x = x, y = y, pseg = 'RAM', 
+                                 binpath = 'build/ocean/ocean.elf',
+                                 local = True )
+
+    # stacks vsegs: local (one stack per processor => nprocs stacks per cluster)
+    for x in xrange (x_size):
+        for y in xrange (y_size):
+            cluster_id = (x * y_size) + y
+            if ( mapping.clusters[cluster_id].procs ):
+                for p in xrange( nprocs ):
+                    proc_id = (((x * y_size) + y) * nprocs) + p
+                    size    = (stack_size / nprocs) & 0xFFFFF000
+                    base    = stack_base + (proc_id * size)
+
+                    mapping.addVseg( vspace, 'ocean_stack_%d_%d_%d' % (x,y,p), 
+                                     base, size, 'C_WU', vtype = 'BUFFER', 
+                                     x = x , y = y , pseg = 'RAM',
+                                     local = True, big = True )
+
+    # heap vsegs: distributed non local (all heap vsegs can be accessed by all tasks)
+    for x in xrange (x_size):
+        for y in xrange (y_size):
+            cluster_id = (x * y_size) + y
+            if ( mapping.clusters[cluster_id].procs ):
+                size  = heap_size
+                base  = heap_base + (cluster_id * size)
+
+                mapping.addVseg( vspace, 'ocean_heap_%d_%d' % (x,y), base, size, 
+                                 'C_WU', vtype = 'HEAP', x = x, y = y, pseg = 'RAM',
+                                 local = False, big = True )
+
+    # Local data vsegs: local (one copy in each cluster)
+    for x in xrange (x_size):
+        for y in xrange (y_size):
+            cluster_id = (x * y_size) + y
+            if ( mapping.clusters[cluster_id].procs ):
+
+                mapping.addVseg( vspace, 'ocean_ldata_%d_%d' % (x,y), ldata_base, ldata_size, 
+                                 'C_WU', vtype = 'BUFFER', x = x, y = y, pseg = 'RAM',
+                                 local = True )
+
+    # distributed tasks / one task per processor
+    for x in xrange (x_size):
+        for y in xrange (y_size):
+            cluster_id = (x * y_size) + y
+            if ( mapping.clusters[cluster_id].procs ):
+                for p in xrange( nprocs ):
+                    trdid = (((x * y_size) + y) * nprocs) + p
+                    if x == 0 and y == 0 and p == 0 :
+                        startid=0
+                    else :
+                        startid = 1
+                    
+                    mapping.addTask( vspace, 'ocean_%d_%d_%d' % (x,y,p),
+                                     trdid, x, y, p,
+                                     'ocean_stack_%d_%d_%d' % (x,y,p),
+                                     'ocean_heap_%d_%d' % (x,y), startid )
+
+    # extend mapping name
+    mapping.name += '_ocean'
+
+    return vspace  # useful for test
+            
+################################ test ##################################################
+
+if __name__ == '__main__':
+
+    vspace = ocean( Mapping( 'test', 2, 2, 4 ) )
+    print vspace.xml()
+
+
+# Local Variables:
+# tab-width: 4;
+# c-basic-offset: 4;
+# c-file-offsets:((innamespace . 0)(inline-open . 0));
+# indent-tabs-mode: nil;
+# End:
+#
+# vim: filetype=python:expandtab:shiftwidth=4:tabstop=4:softtabstop=4
+
Index: /soft/giet_vm/applications/ocean/slave1.C
===================================================================
--- /soft/giet_vm/applications/ocean/slave1.C	(revision 581)
+++ /soft/giet_vm/applications/ocean/slave1.C	(revision 581)
@@ -0,0 +1,839 @@
+/*************************************************************************/
+/*                                                                       */
+/*  Copyright (c) 1994 Stanford University                               */
+/*                                                                       */
+/*  All rights reserved.                                                 */
+/*                                                                       */
+/*  Permission is given to use, copy, and modify this software for any   */
+/*  non-commercial purpose as long as this copyright notice is not       */
+/*  removed.  All other uses, including redistribution in whole or in    */
+/*  part, are forbidden without prior written permission.                */
+/*                                                                       */
+/*  This software is provided with absolutely no warranty and no         */
+/*  support.                                                             */
+/*                                                                       */
+/*************************************************************************/
+
+/*    ****************
+      subroutine slave
+      ****************  */
+
+EXTERN_ENV
+
+#include <stdio.h>
+#include <math.h>
+#include <stdlib.h>
+
+#include "decs.h"
+
+void slave(long *ptr_procid)
+{
+    long i;
+    long j;
+    long nstep;
+    long iindex;
+    long iday;
+    double ysca1;
+    double y;
+    double factor;
+    double sintemp;
+    double curlt;
+    double ressqr;
+    long istart;
+    long iend;
+    long jstart;
+    long jend;
+    long ist;
+    long ien;
+    long jst;
+    long jen;
+    double fac;
+    long dayflag = 0;
+    long dhourflag = 0;
+    long endflag = 0;
+    long firstrow;
+    long lastrow;
+    long numrows;
+    long firstcol;
+    long lastcol;
+    long numcols;
+    long psiindex;
+    double psibipriv;
+    double ttime;
+    double dhour;
+    double day;
+    long procid;
+    long j_off = 0;
+    unsigned long t1;
+    double **t2a;
+    double **t2b;
+    double *t1a;
+    double *t1b;
+    double *t1c;
+    double *t1d;
+
+
+    /*
+       LOCK(locks->idlock)
+       procid = global->id;
+       global->id = global->id+1;
+       UNLOCK(locks->idlock)
+     */
+
+    procid = *ptr_procid;
+    ressqr = lev_res[numlev - 1] * lev_res[numlev - 1];
+
+#if defined(MULTIPLE_BARRIERS)
+    BARRIER(bars->sl_prini, nprocs)
+#else
+    BARRIER(bars->barrier, nprocs)
+#endif
+/* POSSIBLE ENHANCEMENT:  Here is where one might pin processes to
+   processors to avoid migration. */
+/* POSSIBLE ENHANCEMENT:  Here is where one might distribute
+   data structures across physically distributed memories as
+   desired.
+
+   One way to do this is as follows.  The function allocate(START,SIZE,I)
+   is assumed to place all addresses x such that
+   (START <= x < START+SIZE) on node I.
+
+   long d_size;
+   unsigned long g_size;
+   unsigned long mg_size;
+
+   if (procid == MASTER) {
+     g_size = ((jmx[numlev-1]-2)/xprocs+2)*((imx[numlev-1]-2)/yprocs+2)*siz
+eof(double) +
+              ((imx[numlev-1]-2)/yprocs+2)*sizeof(double *);
+
+     mg_size = numlev*sizeof(double **);
+     for (i=0;i<numlev;i++) {
+       mg_size+=((imx[i]-2)/yprocs+2)*((jmx[i]-2)/xprocs+2)*sizeof(double)+
+                ((imx[i]-2)/yprocs+2)*sizeof(double *);
+     }
+     for (i= 0;i<nprocs;i++) {
+       d_size = 2*sizeof(double **);
+       allocate((unsigned long) psi[i],d_size,i);
+       allocate((unsigned long) psim[i],d_size,i);
+       allocate((unsigned long) work1[i],d_size,i);
+       allocate((unsigned long) work4[i],d_size,i);
+       allocate((unsigned long) work5[i],d_size,i);
+       allocate((unsigned long) work7[i],d_size,i);
+       allocate((unsigned long) temparray[i],d_size,i);
+       allocate((unsigned long) psi[i][0],g_size,i);
+       allocate((unsigned long) psi[i][1],g_size,i);
+       allocate((unsigned long) psim[i][0],g_size,i);
+       allocate((unsigned long) psim[i][1],g_size,i);
+       allocate((unsigned long) psium[i],g_size,i);
+       allocate((unsigned long) psilm[i],g_size,i);
+       allocate((unsigned long) psib[i],g_size,i);
+       allocate((unsigned long) ga[i],g_size,i);
+       allocate((unsigned long) gb[i],g_size,i);
+       allocate((unsigned long) work1[i][0],g_size,i);
+       allocate((unsigned long) work1[i][1],g_size,i);
+       allocate((unsigned long) work2[i],g_size,i);
+       allocate((unsigned long) work3[i],g_size,i);
+       allocate((unsigned long) work4[i][0],g_size,i);
+       allocate((unsigned long) work4[i][1],g_size,i);
+       allocate((unsigned long) work5[i][0],g_size,i);
+       allocate((unsigned long) work5[i][1],g_size,i);
+       allocate((unsigned long) work6[i],g_size,i);
+       allocate((unsigned long) work7[i][0],g_size,i);
+       allocate((unsigned long) work7[i][1],g_size,i);
+       allocate((unsigned long) temparray[i][0],g_size,i);
+       allocate((unsigned long) temparray[i][1],g_size,i);
+       allocate((unsigned long) tauz[i],g_size,i);
+       allocate((unsigned long) oldga[i],g_size,i);
+       allocate((unsigned long) oldgb[i],g_size,i);
+       d_size = numlev * sizeof(long);
+       allocate((unsigned long) gp[i].rel_num_x,d_size,i);
+       allocate((unsigned long) gp[i].rel_num_y,d_size,i);
+       allocate((unsigned long) gp[i].eist,d_size,i);
+       allocate((unsigned long) gp[i].ejst,d_size,i);
+       allocate((unsigned long) gp[i].oist,d_size,i);
+       allocate((unsigned long) gp[i].ojst,d_size,i);
+       allocate((unsigned long) gp[i].rlist,d_size,i);
+       allocate((unsigned long) gp[i].rljst,d_size,i);
+       allocate((unsigned long) gp[i].rlien,d_size,i);
+       allocate((unsigned long) gp[i].rljen,d_size,i);
+
+       allocate((unsigned long) q_multi[i],mg_size,i);
+       allocate((unsigned long) rhs_multi[i],mg_size,i);
+       allocate((unsigned long) &(gp[i]),sizeof(struct Global_Private),i);
+     }
+   }
+
+*/
+    t2a = (double **) oldga[procid];
+    t2b = (double **) oldgb[procid];
+    for (i = 0; i < im; i++) {
+        t1a = (double *) t2a[i];
+        t1b = (double *) t2b[i];
+        for (j = 0; j < jm; j++) {
+            t1a[j] = 0.0;
+            t1b[j] = 0.0;
+        }
+    }
+
+    firstcol = 1;
+    lastcol = firstcol + gp[procid].rel_num_x[numlev - 1] - 1;
+    firstrow = 1;
+    lastrow = firstrow + gp[procid].rel_num_y[numlev - 1] - 1;
+    numcols = gp[procid].rel_num_x[numlev - 1];
+    numrows = gp[procid].rel_num_y[numlev - 1];
+    j_off = (*gp[procid].colnum) * numcols;
+
+    /*
+       if (procid > nprocs/2) {
+       psinum = 2;
+       } else {
+       psinum = 1;
+       }
+     */
+
+/* every process gets its own copy of the timing variables to avoid
+   contention at shared memory locations.  here, these variables
+   are initialized.  */
+
+    ttime = 0.0;
+    dhour = 0.0;
+    nstep = 0;
+    day = 0.0;
+
+    ysca1 = 0.5 * ysca;
+
+    if (*gp[procid].lpid == MASTER) {
+
+        f = (double *) G_MALLOC(oim * sizeof(double), procid);
+
+        t1a = (double *) f;
+        for (iindex = 0; iindex <= jmx[numlev - 1] - 1; iindex++) {
+            y = ((double) iindex) * res;
+            t1a[iindex] = f0 + beta * (y - ysca1);
+        }
+    }
+
+    t2a = (double **) psium[procid];
+    if ((gp[procid].neighbors[UP] == -1) && (gp[procid].neighbors[LEFT] == -1)) {
+        t2a[0][0] = 0.0;
+    }
+    if ((gp[procid].neighbors[DOWN] == -1) && (gp[procid].neighbors[LEFT] == -1)) {
+        t2a[im - 1][0] = 0.0;
+    }
+    if ((gp[procid].neighbors[UP] == -1) && (gp[procid].neighbors[RIGHT] == -1)) {
+        t2a[0][jm - 1] = 0.0;
+    }
+    if ((gp[procid].neighbors[DOWN] == -1) && (gp[procid].neighbors[RIGHT] == -1)) {
+        t2a[im - 1][jm - 1] = 0.0;
+    }
+    if (gp[procid].neighbors[UP] == -1) {
+        t1a = (double *) t2a[0];
+        for (j = firstcol; j <= lastcol; j++) {
+            t1a[j] = 0.0;
+        }
+    }
+    if (gp[procid].neighbors[DOWN] == -1) {
+        t1a = (double *) t2a[im - 1];
+        for (j = firstcol; j <= lastcol; j++) {
+            t1a[j] = 0.0;
+        }
+    }
+    if (gp[procid].neighbors[LEFT] == -1) {
+        for (j = firstrow; j <= lastrow; j++) {
+            t2a[j][0] = 0.0;
+        }
+    }
+    if (gp[procid].neighbors[RIGHT] == -1) {
+        for (j = firstrow; j <= lastrow; j++) {
+            t2a[j][jm - 1] = 0.0;
+        }
+    }
+
+    for (i = firstrow; i <= lastrow; i++) {
+        t1a = (double *) t2a[i];
+        for (iindex = firstcol; iindex <= lastcol; iindex++) {
+            t1a[iindex] = 0.0;
+        }
+    }
+    t2a = (double **) psilm[procid];
+    if ((gp[procid].neighbors[UP] == -1) && (gp[procid].neighbors[LEFT] == -1)) {
+        t2a[0][0] = 0.0;
+    }
+    if ((gp[procid].neighbors[DOWN] == -1) && (gp[procid].neighbors[LEFT] == -1)) {
+        t2a[im - 1][0] = 0.0;
+    }
+    if ((gp[procid].neighbors[UP] == -1) && (gp[procid].neighbors[RIGHT] == -1)) {
+        t2a[0][jm - 1] = 0.0;
+    }
+    if ((gp[procid].neighbors[DOWN] == -1) && (gp[procid].neighbors[RIGHT] == -1)) {
+        t2a[im - 1][jm - 1] = 0.0;
+    }
+    if (gp[procid].neighbors[UP] == -1) {
+        t1a = (double *) t2a[0];
+        for (j = firstcol; j <= lastcol; j++) {
+            t1a[j] = 0.0;
+        }
+    }
+    if (gp[procid].neighbors[DOWN] == -1) {
+        t1a = (double *) t2a[im - 1];
+        for (j = firstcol; j <= lastcol; j++) {
+            t1a[j] = 0.0;
+        }
+    }
+    if (gp[procid].neighbors[LEFT] == -1) {
+        for (j = firstrow; j <= lastrow; j++) {
+            t2a[j][0] = 0.0;
+        }
+    }
+    if (gp[procid].neighbors[RIGHT] == -1) {
+        for (j = firstrow; j <= lastrow; j++) {
+            t2a[j][jm - 1] = 0.0;
+        }
+    }
+    for (i = firstrow; i <= lastrow; i++) {
+        t1a = (double *) t2a[i];
+        for (iindex = firstcol; iindex <= lastcol; iindex++) {
+            t1a[iindex] = 0.0;
+        }
+    }
+
+    t2a = (double **) psib[procid];
+    if ((gp[procid].neighbors[UP] == -1) && (gp[procid].neighbors[LEFT] == -1)) {
+        t2a[0][0] = 1.0;
+    }
+    if ((gp[procid].neighbors[UP] == -1) && (gp[procid].neighbors[RIGHT] == -1)) {
+        t2a[0][jm - 1] = 1.0;
+    }
+    if ((gp[procid].neighbors[DOWN] == -1) && (gp[procid].neighbors[LEFT] == -1)) {
+        t2a[im - 1][0] = 1.0;
+    }
+    if ((gp[procid].neighbors[DOWN] == -1) && (gp[procid].neighbors[RIGHT] == -1)) {
+        t2a[im - 1][jm - 1] = 1.0;
+    }
+    if (gp[procid].neighbors[UP] == -1) {
+        t1a = (double *) t2a[0];
+        for (j = firstcol; j <= lastcol; j++) {
+            t1a[j] = 1.0;
+        }
+    }
+    if (gp[procid].neighbors[DOWN] == -1) {
+        t1a = (double *) t2a[im - 1];
+        for (j = firstcol; j <= lastcol; j++) {
+            t1a[j] = 1.0;
+        }
+    }
+    if (gp[procid].neighbors[LEFT] == -1) {
+        for (j = firstrow; j <= lastrow; j++) {
+            t2a[j][0] = 1.0;
+        }
+    }
+    if (gp[procid].neighbors[RIGHT] == -1) {
+        for (j = firstrow; j <= lastrow; j++) {
+            t2a[j][jm - 1] = 1.0;
+        }
+    }
+    for (i = firstrow; i <= lastrow; i++) {
+        t1a = (double *) t2a[i];
+        for (iindex = firstcol; iindex <= lastcol; iindex++) {
+            t1a[iindex] = 0.0;
+        }
+    }
+
+/* wait until all processes have completed the above initialization  */
+#if defined(MULTIPLE_BARRIERS)
+    BARRIER(bars->sl_prini, nprocs)
+#else
+    BARRIER(bars->barrier, nprocs)
+#endif
+/* compute psib array (one-time computation) and integrate into psibi */
+        istart = 1;
+    iend = istart + gp[procid].rel_num_y[numlev - 1] - 1;
+    jstart = 1;
+    jend = jstart + gp[procid].rel_num_x[numlev - 1] - 1;
+    ist = istart;
+    ien = iend;
+    jst = jstart;
+    jen = jend;
+
+    if (gp[procid].neighbors[UP] == -1) {
+        istart = 0;
+    }
+    if (gp[procid].neighbors[LEFT] == -1) {
+        jstart = 0;
+    }
+    if (gp[procid].neighbors[DOWN] == -1) {
+        iend = im - 1;
+    }
+    if (gp[procid].neighbors[RIGHT] == -1) {
+        jend = jm - 1;
+    }
+
+    t2a = (double **) rhs_multi[procid][numlev - 1];
+    t2b = (double **) psib[procid];
+    for (i = istart; i <= iend; i++) {
+        t1a = (double *) t2a[i];
+        t1b = (double *) t2b[i];
+        for (j = jstart; j <= jend; j++) {
+            t1a[j] = t1b[j] * ressqr;
+        }
+    }
+    t2a = (double **) q_multi[procid][numlev - 1];
+    if (gp[procid].neighbors[UP] == -1) {
+        t1a = (double *) t2a[0];
+        t1b = (double *) t2b[0];
+        for (j = jstart; j <= jend; j++) {
+            t1a[j] = t1b[j];
+        }
+    }
+    if (gp[procid].neighbors[DOWN] == -1) {
+        t1a = (double *) t2a[im - 1];
+        t1b = (double *) t2b[im - 1];
+        for (j = jstart; j <= jend; j++) {
+            t1a[j] = t1b[j];
+        }
+    }
+    if (gp[procid].neighbors[LEFT] == -1) {
+        for (i = istart; i <= iend; i++) {
+            t2a[i][0] = t2b[i][0];
+        }
+    }
+    if (gp[procid].neighbors[RIGHT] == -1) {
+        for (i = istart; i <= iend; i++) {
+            t2a[i][jm - 1] = t2b[i][jm - 1];
+        }
+    }
+    
+#if defined(MULTIPLE_BARRIERS)
+    BARRIER(bars->sl_psini, nprocs)
+#else
+    BARRIER(bars->barrier, nprocs)
+#endif
+    
+    t2a = (double **) psib[procid];
+    j = gp[procid].neighbors[UP];
+    if (j != -1) {
+        t1a = (double *) t2a[0];
+        t1b = (double *) psib[j][im - 2];
+        for (i = 1; i < jm - 1; i++) {
+            t1a[i] = t1b[i];
+        }
+    }
+    j = gp[procid].neighbors[DOWN];
+    if (j != -1) {
+        t1a = (double *) t2a[im - 1];
+        t1b = (double *) psib[j][1];
+        for (i = 1; i < jm - 1; i++) {
+            t1a[i] = t1b[i];
+        }
+    }
+    j = gp[procid].neighbors[LEFT];
+    if (j != -1) {
+        t2b = (double **) psib[j];
+        for (i = 1; i < im - 1; i++) {
+            t2a[i][0] = t2b[i][jm - 2];
+        }
+    }
+    j = gp[procid].neighbors[RIGHT];
+    if (j != -1) {
+        t2b = (double **) psib[j];
+        for (i = 1; i < im - 1; i++) {
+            t2a[i][jm - 1] = t2b[i][1];
+        }
+    }
+
+    t2a = (double **) q_multi[procid][numlev - 1];
+    t2b = (double **) psib[procid];
+    fac = 1.0 / (4.0 - ressqr * eig2);
+    for (i = ist; i <= ien; i++) {
+        t1a = (double *) t2a[i];
+        t1b = (double *) t2b[i];
+        t1c = (double *) t2b[i - 1];
+        t1d = (double *) t2b[i + 1];
+        for (j = jst; j <= jen; j++) {
+            t1a[j] = fac * (t1d[j] + t1c[j] + t1b[j + 1] + t1b[j - 1] - ressqr * t1b[j]);
+        }
+    }
+
+    multig(procid);
+
+    for (i = istart; i <= iend; i++) {
+        t1a = (double *) t2a[i];
+        t1b = (double *) t2b[i];
+        for (j = jstart; j <= jend; j++) {
+            t1b[j] = t1a[j];
+        }
+    }
+    
+#if defined(MULTIPLE_BARRIERS)
+    BARRIER(bars->sl_prini, nprocs)
+#else
+    BARRIER(bars->barrier, nprocs)
+#endif
+    
+/* update the local running sum psibipriv by summing all the resulting
+   values in that process's share of the psib matrix   */
+   
+    t2a = (double **) psib[procid];
+    psibipriv = 0.0;
+    if ((gp[procid].neighbors[UP] == -1) && (gp[procid].neighbors[LEFT] == -1)) {
+        psibipriv = psibipriv + 0.25 * (t2a[0][0]);
+    }
+    if ((gp[procid].neighbors[UP] == -1) && (gp[procid].neighbors[RIGHT] == -1)) {
+        psibipriv = psibipriv + 0.25 * (t2a[0][jm - 1]);
+    }
+    if ((gp[procid].neighbors[DOWN] == -1) && (gp[procid].neighbors[LEFT] == -1)) {
+        psibipriv = psibipriv + 0.25 * (t2a[im - 1][0]);
+    }
+    if ((gp[procid].neighbors[DOWN] == -1) && (gp[procid].neighbors[RIGHT] == -1)) {
+        psibipriv = psibipriv + 0.25 * (t2a[im - 1][jm - 1]);
+    }
+    if (gp[procid].neighbors[UP] == -1) {
+        t1a = (double *) t2a[0];
+        for (j = firstcol; j <= lastcol; j++) {
+            psibipriv = psibipriv + 0.5 * t1a[j];
+        }
+    }
+    if (gp[procid].neighbors[DOWN] == -1) {
+        t1a = (double *) t2a[im - 1];
+        for (j = firstcol; j <= lastcol; j++) {
+            psibipriv = psibipriv + 0.5 * t1a[j];
+        }
+    }
+    if (gp[procid].neighbors[LEFT] == -1) {
+        for (j = firstrow; j <= lastrow; j++) {
+            psibipriv = psibipriv + 0.5 * t2a[j][0];
+        }
+    }
+    if (gp[procid].neighbors[RIGHT] == -1) {
+        for (j = firstrow; j <= lastrow; j++) {
+            psibipriv = psibipriv + 0.5 * t2a[j][jm - 1];
+        }
+    }
+    for (i = firstrow; i <= lastrow; i++) {
+        t1a = (double *) t2a[i];
+        for (iindex = firstcol; iindex <= lastcol; iindex++) {
+            psibipriv = psibipriv + t1a[iindex];
+        }
+    }
+
+/* update the shared variable psibi by summing all the psibiprivs
+   of the individual processes into it.  note that this combined
+   private and shared sum method avoids accessing the shared
+   variable psibi once for every element of the matrix.  */
+
+    LOCK(locks->psibilock);
+    global->psibi = global->psibi + psibipriv;
+    UNLOCK(locks->psibilock);
+
+/* initialize psim matrices
+
+   if there is more than one process, then split the processes
+   between the two psim matrices; otherwise, let the single process
+   work on one first and then the other   */
+
+    for (psiindex = 0; psiindex <= 1; psiindex++) {
+        t2a = (double **) psim[procid][psiindex];
+        if ((gp[procid].neighbors[UP] == -1) && (gp[procid].neighbors[LEFT] == -1)) {
+            t2a[0][0] = 0.0;
+        }
+        if ((gp[procid].neighbors[DOWN] == -1) && (gp[procid].neighbors[LEFT] == -1)) {
+            t2a[im - 1][0] = 0.0;
+        }
+        if ((gp[procid].neighbors[UP] == -1) && (gp[procid].neighbors[RIGHT] == -1)) {
+            t2a[0][jm - 1] = 0.0;
+        }
+        if ((gp[procid].neighbors[DOWN] == -1) && (gp[procid].neighbors[RIGHT] == -1)) {
+            t2a[im - 1][jm - 1] = 0.0;
+        }
+        if (gp[procid].neighbors[UP] == -1) {
+            t1a = (double *) t2a[0];
+            for (j = firstcol; j <= lastcol; j++) {
+                t1a[j] = 0.0;
+            }
+        }
+        if (gp[procid].neighbors[DOWN] == -1) {
+            t1a = (double *) t2a[im - 1];
+            for (j = firstcol; j <= lastcol; j++) {
+                t1a[j] = 0.0;
+            }
+        }
+        if (gp[procid].neighbors[LEFT] == -1) {
+            for (j = firstrow; j <= lastrow; j++) {
+                t2a[j][0] = 0.0;
+            }
+        }
+        if (gp[procid].neighbors[RIGHT] == -1) {
+            for (j = firstrow; j <= lastrow; j++) {
+                t2a[j][jm - 1] = 0.0;
+            }
+        }
+        for (i = firstrow; i <= lastrow; i++) {
+            t1a = (double *) t2a[i];
+            for (iindex = firstcol; iindex <= lastcol; iindex++) {
+                t1a[iindex] = 0.0;
+            }
+        }
+    }
+
+/* initialize psi matrices the same way  */
+
+    for (psiindex = 0; psiindex <= 1; psiindex++) {
+        t2a = (double **) psi[procid][psiindex];
+        if ((gp[procid].neighbors[UP] == -1) && (gp[procid].neighbors[LEFT] == -1)) {
+            t2a[0][0] = 0.0;
+        }
+        if ((gp[procid].neighbors[UP] == -1) && (gp[procid].neighbors[RIGHT] == -1)) {
+            t2a[0][jm - 1] = 0.0;
+        }
+        if ((gp[procid].neighbors[DOWN] == -1) && (gp[procid].neighbors[LEFT] == -1)) {
+            t2a[im - 1][0] = 0.0;
+        }
+        if ((gp[procid].neighbors[DOWN] == -1) && (gp[procid].neighbors[RIGHT] == -1)) {
+            t2a[im - 1][jm - 1] = 0.0;
+        }
+        if (gp[procid].neighbors[UP] == -1) {
+            t1a = (double *) t2a[0];
+            for (j = firstcol; j <= lastcol; j++) {
+                t1a[j] = 0.0;
+            }
+        }
+        if (gp[procid].neighbors[DOWN] == -1) {
+            t1a = (double *) t2a[im - 1];
+            for (j = firstcol; j <= lastcol; j++) {
+                t1a[j] = 0.0;
+            }
+        }
+        if (gp[procid].neighbors[LEFT] == -1) {
+            for (j = firstrow; j <= lastrow; j++) {
+                t2a[j][0] = 0.0;
+            }
+        }
+        if (gp[procid].neighbors[RIGHT] == -1) {
+            for (j = firstrow; j <= lastrow; j++) {
+                t2a[j][jm - 1] = 0.0;
+            }
+        }
+        for (i = firstrow; i <= lastrow; i++) {
+            t1a = (double *) t2a[i];
+            for (iindex = firstcol; iindex <= lastcol; iindex++) {
+                t1a[iindex] = 0.0;
+            }
+        }
+    }
+
+/* compute input curl of wind stress */
+
+
+    t2a = (double **) tauz[procid];
+    ysca1 = .5 * ysca;
+    factor = -t0 * pi / ysca1;
+    if ((gp[procid].neighbors[UP] == -1) && (gp[procid].neighbors[LEFT] == -1)) {
+        t2a[0][0] = 0.0;
+    }
+    if ((gp[procid].neighbors[DOWN] == -1) && (gp[procid].neighbors[LEFT] == -1)) {
+        t2a[im - 1][0] = 0.0;
+    }
+    if ((gp[procid].neighbors[UP] == -1) && (gp[procid].neighbors[RIGHT] == -1)) {
+        sintemp = pi * ((double) jm - 1 + j_off) * res / ysca1;
+        sintemp = sin(sintemp);
+        t2a[0][jm - 1] = factor * sintemp;
+    }
+    if ((gp[procid].neighbors[DOWN] == -1) && (gp[procid].neighbors[RIGHT] == -1)) {
+        sintemp = pi * ((double) jm - 1 + j_off) * res / ysca1;
+        sintemp = sin(sintemp);
+        t2a[im - 1][jm - 1] = factor * sintemp;
+    }
+    if (gp[procid].neighbors[UP] == -1) {
+        t1a = (double *) t2a[0];
+        for (j = firstcol; j <= lastcol; j++) {
+            sintemp = pi * ((double) j + j_off) * res / ysca1;
+            sintemp = sin(sintemp);
+            curlt = factor * sintemp;
+            t1a[j] = curlt;
+        }
+    }
+    if (gp[procid].neighbors[DOWN] == -1) {
+        t1a = (double *) t2a[im - 1];
+        for (j = firstcol; j <= lastcol; j++) {
+            sintemp = pi * ((double) j + j_off) * res / ysca1;
+            sintemp = sin(sintemp);
+            curlt = factor * sintemp;
+            t1a[j] = curlt;
+        }
+    }
+    if (gp[procid].neighbors[LEFT] == -1) {
+        for (j = firstrow; j <= lastrow; j++) {
+            t2a[j][0] = 0.0;
+        }
+    }
+    if (gp[procid].neighbors[RIGHT] == -1) {
+        sintemp = pi * ((double) jm - 1 + j_off) * res / ysca1;
+        sintemp = sin(sintemp);
+        curlt = factor * sintemp;
+        for (j = firstrow; j <= lastrow; j++) {
+            t2a[j][jm - 1] = curlt;
+        }
+    }
+    for (i = firstrow; i <= lastrow; i++) {
+        t1a = (double *) t2a[i];
+        for (iindex = firstcol; iindex <= lastcol; iindex++) {
+            sintemp = pi * ((double) iindex + j_off) * res / ysca1;
+            sintemp = sin(sintemp);
+            curlt = factor * sintemp;
+            t1a[iindex] = curlt;
+        }
+    }
+    
+#if defined(MULTIPLE_BARRIERS)
+    BARRIER(bars->sl_onetime, nprocs)
+#else
+    BARRIER(bars->barrier, nprocs)
+#endif
+    
+/***************************************************************
+ one-time stuff over at this point
+ ***************************************************************/
+    while (!endflag) {
+        while ((!dayflag) || (!dhourflag)) {
+            dayflag = 0;
+            dhourflag = 0;
+            if (nstep == 1) {
+                for (i = 0; i < 10; i++) {
+                    gp[procid].steps_time[i] = 0;
+                }
+                if (procid == MASTER) {
+                    CLOCK(global->trackstart)
+                }
+                if ((procid == MASTER) || (do_stats)) {
+                    CLOCK(t1);
+                    (*gp[procid].total_time) = t1;
+                    (*gp[procid].multi_time) = 0;
+                }
+/* POSSIBLE ENHANCEMENT:  Here is where one might reset the
+   statistics that one is measuring about the parallel execution */
+            }
+
+            slave2(procid, firstrow, lastrow, numrows, firstcol, lastcol, numcols);
+
+/* update time and step number
+   note that these time and step variables are private i.e. every
+   process has its own copy and keeps track of its own time  */
+
+            ttime = ttime + dtau;
+            nstep = nstep + 1;
+            day = ttime / 86400.0;
+
+            if (day > ((double) outday0)) {
+                dayflag = 1;
+                iday = (long) day;
+                dhour = dhour + dtau;
+                if (dhour >= 86400.0) {
+                    dhourflag = 1;
+                }
+            }
+        }
+        dhour = 0.0;
+
+        t2a = (double **) psium[procid];
+        t2b = (double **) psim[procid][0];
+        if ((gp[procid].neighbors[UP] == -1) && (gp[procid].neighbors[LEFT] == -1)) {
+            t2a[0][0] = t2a[0][0] + t2b[0][0];
+        }
+        if ((gp[procid].neighbors[DOWN] == -1) && (gp[procid].neighbors[LEFT] == -1)) {
+            t2a[im - 1][0] = t2a[im - 1][0] + t2b[im - 1][0];
+        }
+        if ((gp[procid].neighbors[UP] == -1) && (gp[procid].neighbors[RIGHT] == -1)) {
+            t2a[0][jm - 1] = t2a[0][jm - 1] + t2b[0][jm - 1];
+        }
+        if ((gp[procid].neighbors[DOWN] == -1) && (gp[procid].neighbors[RIGHT] == -1)) {
+            t2a[im - 1][jm - 1] = t2a[im - 1][jm - 1] + t2b[im - 1][jm - 1];
+        }
+        if (gp[procid].neighbors[UP] == -1) {
+            t1a = (double *) t2a[0];
+            t1b = (double *) t2b[0];
+            for (j = firstcol; j <= lastcol; j++) {
+                t1a[j] = t1a[j] + t1b[j];
+            }
+        }
+        if (gp[procid].neighbors[DOWN] == -1) {
+            t1a = (double *) t2a[im - 1];
+            t1b = (double *) t2b[im - 1];
+            for (j = firstcol; j <= lastcol; j++) {
+                t1a[j] = t1a[j] + t1b[j];
+            }
+        }
+        if (gp[procid].neighbors[LEFT] == -1) {
+            for (j = firstrow; j <= lastrow; j++) {
+                t2a[j][0] = t2a[j][0] + t2b[j][0];
+            }
+        }
+        if (gp[procid].neighbors[RIGHT] == -1) {
+            for (j = firstrow; j <= lastrow; j++) {
+                t2a[j][jm - 1] = t2a[j][jm - 1] + t2b[j][jm - 1];
+            }
+        }
+        for (i = firstrow; i <= lastrow; i++) {
+            t1a = (double *) t2a[i];
+            t1b = (double *) t2b[i];
+            for (iindex = firstcol; iindex <= lastcol; iindex++) {
+                t1a[iindex] = t1a[iindex] + t1b[iindex];
+            }
+        }
+
+/* update values of psilm array to psilm + psim[2]  */
+
+        t2a = (double **) psilm[procid];
+        t2b = (double **) psim[procid][1];
+        if ((gp[procid].neighbors[UP] == -1) && (gp[procid].neighbors[LEFT] == -1)) {
+            t2a[0][0] = t2a[0][0] + t2b[0][0];
+        }
+        if ((gp[procid].neighbors[DOWN] == -1) && (gp[procid].neighbors[LEFT] == -1)) {
+            t2a[im - 1][0] = t2a[im - 1][0] + t2b[im - 1][0];
+        }
+        if ((gp[procid].neighbors[UP] == -1) && (gp[procid].neighbors[RIGHT] == -1)) {
+            t2a[0][jm - 1] = t2a[0][jm - 1] + t2b[0][jm - 1];
+        }
+        if ((gp[procid].neighbors[DOWN] == -1) && (gp[procid].neighbors[RIGHT] == -1)) {
+            t2a[im - 1][jm - 1] = t2a[im - 1][jm - 1] + t2b[im - 1][jm - 1];
+        }
+        if (gp[procid].neighbors[UP] == -1) {
+            t1a = (double *) t2a[0];
+            t1b = (double *) t2b[0];
+            for (j = firstcol; j <= lastcol; j++) {
+                t1a[j] = t1a[j] + t1b[j];
+            }
+        }
+        if (gp[procid].neighbors[DOWN] == -1) {
+            t1a = (double *) t2a[im - 1];
+            t1b = (double *) t2b[im - 1];
+            for (j = firstcol; j <= lastcol; j++) {
+                t1a[j] = t1a[j] + t1b[j];
+            }
+        }
+        if (gp[procid].neighbors[LEFT] == -1) {
+            for (j = firstrow; j <= lastrow; j++) {
+                t2a[j][0] = t2a[j][0] + t2b[j][0];
+            }
+        }
+        if (gp[procid].neighbors[RIGHT] == -1) {
+            for (j = firstrow; j <= lastrow; j++) {
+                t2a[j][jm - 1] = t2a[j][jm - 1] + t2b[j][jm - 1];
+            }
+        }
+        for (i = firstrow; i <= lastrow; i++) {
+            t1a = (double *) t2a[i];
+            t1b = (double *) t2b[i];
+            for (iindex = firstcol; iindex <= lastcol; iindex++) {
+                t1a[iindex] = t1a[iindex] + t1b[iindex];
+            }
+        }
+        if (iday >= (long) outday3) {
+            endflag = 1;
+        }
+    }
+    if ((procid == MASTER) || (do_stats)) {
+        CLOCK(t1);
+        (*gp[procid].total_time) = t1 - (*gp[procid].total_time);
+    }
+}
Index: /soft/giet_vm/applications/ocean/slave2.C
===================================================================
--- /soft/giet_vm/applications/ocean/slave2.C	(revision 581)
+++ /soft/giet_vm/applications/ocean/slave2.C	(revision 581)
@@ -0,0 +1,1194 @@
+/*************************************************************************/
+/*                                                                       */
+/*  Copyright (c) 1994 Stanford University                               */
+/*                                                                       */
+/*  All rights reserved.                                                 */
+/*                                                                       */
+/*  Permission is given to use, copy, and modify this software for any   */
+/*  non-commercial purpose as long as this copyright notice is not       */
+/*  removed.  All other uses, including redistribution in whole or in    */
+/*  part, are forbidden without prior written permission.                */
+/*                                                                       */
+/*  This software is provided with absolutely no warranty and no         */
+/*  support.                                                             */
+/*                                                                       */
+/*************************************************************************/
+
+/*    ****************
+      subroutine slave2
+      ****************  */
+
+EXTERN_ENV
+
+#include <stdio.h>
+#include <math.h>
+#include <stdlib.h>
+
+#include "decs.h"
+
+void slave2(long procid, long firstrow, long lastrow, long numrows, long firstcol, long lastcol, long numcols)
+{
+    long i;
+    long j;
+    long iindex;
+    double hh1;
+    double hh3;
+    double hinv;
+    double h1inv;
+    long istart;
+    long iend;
+    long jstart;
+    long jend;
+    long ist;
+    long ien;
+    long jst;
+    long jen;
+    double ressqr;
+    double psiaipriv;
+    double f4;
+    double timst;
+    long psiindex;
+    long i_off;
+    long j_off;
+    long multi_start;
+    long multi_end;
+    double **t2a;
+    double **t2b;
+    double **t2c;
+    double **t2d;
+    double **t2e;
+    double **t2f;
+    double **t2g;
+    double **t2h;
+    double *t1a;
+    double *t1b;
+    double *t1c;
+    double *t1d;
+    double *t1e;
+    double *t1f;
+    double *t1g;
+    double *t1h;
+
+    ressqr = lev_res[numlev - 1] * lev_res[numlev - 1];
+    i_off = (*gp[procid].rownum) * numrows;
+    j_off = (*gp[procid].colnum) * numcols;
+
+    START_PHASE(procid, 1);
+
+/*   ***************************************************************
+
+          f i r s t     p h a s e   (of timestep calculation)
+
+     ***************************************************************/
+
+    t2a = (double **) ga[procid];
+    if ((gp[procid].neighbors[UP] == -1) && (gp[procid].neighbors[LEFT] == -1)) {
+        t2a[0][0] = 0.0;
+    }
+    if ((gp[procid].neighbors[DOWN] == -1) && (gp[procid].neighbors[LEFT] == -1)) {
+        t2a[im - 1][0] = 0.0;
+    }
+    if ((gp[procid].neighbors[UP] == -1) && (gp[procid].neighbors[RIGHT] == -1)) {
+        t2a[0][jm - 1] = 0.0;
+    }
+    if ((gp[procid].neighbors[DOWN] == -1) && (gp[procid].neighbors[RIGHT] == -1)) {
+        t2a[im - 1][jm - 1] = 0.0;
+    }
+    if (gp[procid].neighbors[UP] == -1) {
+        t1a = (double *) t2a[0];
+        for (j = firstcol; j <= lastcol; j++) {
+            t1a[j] = 0.0;
+        }
+    }
+    if (gp[procid].neighbors[DOWN] == -1) {
+        t1a = (double *) t2a[im - 1];
+        for (j = firstcol; j <= lastcol; j++) {
+            t1a[j] = 0.0;
+        }
+    }
+    if (gp[procid].neighbors[LEFT] == -1) {
+        for (j = firstrow; j <= lastrow; j++) {
+            t2a[j][0] = 0.0;
+        }
+    }
+    if (gp[procid].neighbors[RIGHT] == -1) {
+        for (j = firstrow; j <= lastrow; j++) {
+            t2a[j][jm - 1] = 0.0;
+        }
+    }
+    for (i = firstrow; i <= lastrow; i++) {
+        t1a = (double *) t2a[i];
+        for (iindex = firstcol; iindex <= lastcol; iindex++) {
+            t1a[iindex] = 0.0;
+        }
+    }
+
+    t2a = (double **) gb[procid];
+    if ((gp[procid].neighbors[UP] == -1) && (gp[procid].neighbors[LEFT] == -1)) {
+        t2a[0][0] = 0.0;
+    }
+    if ((gp[procid].neighbors[DOWN] == -1) && (gp[procid].neighbors[LEFT] == -1)) {
+        t2a[im - 1][0] = 0.0;
+    }
+    if ((gp[procid].neighbors[UP] == -1) && (gp[procid].neighbors[RIGHT] == -1)) {
+        t2a[0][jm - 1] = 0.0;
+    }
+    if ((gp[procid].neighbors[DOWN] == -1) && (gp[procid].neighbors[RIGHT] == -1)) {
+        t2a[im - 1][jm - 1] = 0.0;
+    }
+    if (gp[procid].neighbors[UP] == -1) {
+        t1a = (double *) t2a[0];
+        for (j = firstcol; j <= lastcol; j++) {
+            t1a[j] = 0.0;
+        }
+    }
+    if (gp[procid].neighbors[DOWN] == -1) {
+        t1a = (double *) t2a[im - 1];
+        for (j = firstcol; j <= lastcol; j++) {
+            t1a[j] = 0.0;
+        }
+    }
+    if (gp[procid].neighbors[LEFT] == -1) {
+        for (j = firstrow; j <= lastrow; j++) {
+            t2a[j][0] = 0.0;
+        }
+    }
+    if (gp[procid].neighbors[RIGHT] == -1) {
+        for (j = firstrow; j <= lastrow; j++) {
+            t2a[j][jm - 1] = 0.0;
+        }
+    }
+    for (i = firstrow; i <= lastrow; i++) {
+        t1a = (double *) t2a[i];
+        for (iindex = firstcol; iindex <= lastcol; iindex++) {
+            t1a[iindex] = 0.0;
+        }
+    }
+
+/* put the laplacian of psi{1,3} in work1{1,2}
+   note that psi(i,j,2) represents the psi3 array in
+   the original equations  */
+
+    for (psiindex = 0; psiindex <= 1; psiindex++) {
+        t2a = (double **) work1[procid][psiindex];
+        if ((gp[procid].neighbors[UP] == -1) && (gp[procid].neighbors[LEFT] == -1)) {
+            t2a[0][0] = 0;
+        }
+        if ((gp[procid].neighbors[DOWN] == -1) && (gp[procid].neighbors[LEFT] == -1)) {
+            t2a[im - 1][0] = 0;
+        }
+        if ((gp[procid].neighbors[UP] == -1) && (gp[procid].neighbors[RIGHT] == -1)) {
+            t2a[0][jm - 1] = 0;
+        }
+        if ((gp[procid].neighbors[DOWN] == -1) && (gp[procid].neighbors[RIGHT] == -1)) {
+            t2a[im - 1][jm - 1] = 0;
+        }
+        laplacalc(procid, psi, work1, psiindex, firstrow, lastrow, firstcol, lastcol);
+    }
+
+/* set values of work2 array to psi1 - psi3   */
+
+    t2a = (double **) work2[procid];
+    t2b = (double **) psi[procid][0];
+    t2c = (double **) psi[procid][1];
+    if ((gp[procid].neighbors[UP] == -1) && (gp[procid].neighbors[LEFT] == -1)) {
+        t2a[0][0] = t2b[0][0] - t2c[0][0];
+    }
+    if ((gp[procid].neighbors[DOWN] == -1) && (gp[procid].neighbors[LEFT] == -1)) {
+        t2a[im - 1][0] = t2b[im - 1][0] - t2c[im - 1][0];
+    }
+    if ((gp[procid].neighbors[UP] == -1) && (gp[procid].neighbors[RIGHT] == -1)) {
+        t2a[0][jm - 1] = t2b[0][jm - 1] - t2c[0][jm - 1];
+    }
+    if ((gp[procid].neighbors[DOWN] == -1) && (gp[procid].neighbors[RIGHT] == -1)) {
+        t2a[im - 1][jm - 1] = t2b[im - 1][jm - 1] - t2c[im - 1][jm - 1];
+    }
+    if (gp[procid].neighbors[UP] == -1) {
+        t1a = (double *) t2a[0];
+        t1b = (double *) t2b[0];
+        t1c = (double *) t2c[0];
+        for (j = firstcol; j <= lastcol; j++) {
+            t1a[j] = t1b[j] - t1c[j];
+        }
+    }
+    if (gp[procid].neighbors[DOWN] == -1) {
+        t1a = (double *) t2a[im - 1];
+        t1b = (double *) t2b[im - 1];
+        t1c = (double *) t2c[im - 1];
+        for (j = firstcol; j <= lastcol; j++) {
+            t1a[j] = t1b[j] - t1c[j];
+        }
+    }
+    if (gp[procid].neighbors[LEFT] == -1) {
+        for (j = firstrow; j <= lastrow; j++) {
+            t2a[j][0] = t2b[j][0] - t2c[j][0];
+        }
+    }
+    if (gp[procid].neighbors[RIGHT] == -1) {
+        for (j = firstrow; j <= lastrow; j++) {
+            t2a[j][jm - 1] = t2b[j][jm - 1] - t2c[j][jm - 1];
+        }
+    }
+    for (i = firstrow; i <= lastrow; i++) {
+        t1a = (double *) t2a[i];
+        t1b = (double *) t2b[i];
+        t1c = (double *) t2c[i];
+        for (iindex = firstcol; iindex <= lastcol; iindex++) {
+            t1a[iindex] = t1b[iindex] - t1c[iindex];
+        }
+    }
+
+/* set values of work3 array to h3/h * psi1 + h1/h * psi3  */
+
+    t2a = (double **) work3[procid];
+    hh3 = h3 / h;
+    hh1 = h1 / h;
+    if ((gp[procid].neighbors[UP] == -1) && (gp[procid].neighbors[LEFT] == -1)) {
+        t2a[0][0] = hh3 * t2a[0][0] + hh1 * t2c[0][0];
+    }
+    if ((gp[procid].neighbors[DOWN] == -1) && (gp[procid].neighbors[LEFT] == -1)) {
+        t2a[im - 1][0] = hh3 * t2a[im - 1][0] + hh1 * t2c[im - 1][0];
+    }
+    if ((gp[procid].neighbors[UP] == -1) && (gp[procid].neighbors[RIGHT] == -1)) {
+        t2a[0][jm - 1] = hh3 * t2a[0][jm - 1] + hh1 * t2c[0][jm - 1];
+    }
+    if ((gp[procid].neighbors[DOWN] == -1) && (gp[procid].neighbors[RIGHT] == -1)) {
+        t2a[im - 1][jm - 1] = hh3 * t2a[im - 1][jm - 1] + hh1 * t2c[im - 1][jm - 1];
+    }
+    if (gp[procid].neighbors[UP] == -1) {
+        for (j = firstcol; j <= lastcol; j++) {
+            t2a[0][j] = hh3 * t2a[0][j] + hh1 * t2c[0][j];
+        }
+    }
+    if (gp[procid].neighbors[DOWN] == -1) {
+        for (j = firstcol; j <= lastcol; j++) {
+            t2a[im - 1][j] = hh3 * t2a[im - 1][j] + hh1 * t2c[im - 1][j];
+        }
+    }
+    if (gp[procid].neighbors[LEFT] == -1) {
+        for (j = firstrow; j <= lastrow; j++) {
+            t2a[j][0] = hh3 * t2a[j][0] + hh1 * t2c[j][0];
+        }
+    }
+    if (gp[procid].neighbors[RIGHT] == -1) {
+        for (j = firstrow; j <= lastrow; j++) {
+            t2a[j][jm - 1] = hh3 * t2a[j][jm - 1] + hh1 * t2c[j][jm - 1];
+        }
+    }
+    for (i = firstrow; i <= lastrow; i++) {
+        t1a = (double *) t2a[i];
+        t1c = (double *) t2c[i];
+        for (iindex = firstcol; iindex <= lastcol; iindex++) {
+            t1a[iindex] = hh3 * t1a[iindex] + hh1 * t1c[iindex];
+        }
+    }
+
+/* set values of temparray{1,3} to psi{1,3}  */
+
+    for (psiindex = 0; psiindex <= 1; psiindex++) {
+        t2a = (double **) temparray[procid][psiindex];
+        t2b = (double **) psi[procid][psiindex];
+        if ((gp[procid].neighbors[UP] == -1) && (gp[procid].neighbors[LEFT] == -1)) {
+            t2a[0][0] = t2b[0][0];
+        }
+        if ((gp[procid].neighbors[DOWN] == -1) && (gp[procid].neighbors[LEFT] == -1)) {
+            t2a[im - 1][0] = t2b[im - 1][0];
+        }
+        if ((gp[procid].neighbors[UP] == -1) && (gp[procid].neighbors[RIGHT] == -1)) {
+            t2a[0][jm - 1] = t2b[0][jm - 1];
+        }
+        if ((gp[procid].neighbors[DOWN] == -1) && (gp[procid].neighbors[RIGHT] == -1)) {
+            t2a[im - 1][jm - 1] = t2b[im - 1][jm - 1];
+        }
+        if (gp[procid].neighbors[UP] == -1) {
+            for (j = firstcol; j <= lastcol; j++) {
+                t2a[0][j] = t2b[0][j];
+            }
+        }
+        if (gp[procid].neighbors[DOWN] == -1) {
+            for (j = firstcol; j <= lastcol; j++) {
+                t2a[im - 1][j] = t2b[im - 1][j];
+            }
+        }
+        if (gp[procid].neighbors[LEFT] == -1) {
+            for (j = firstrow; j <= lastrow; j++) {
+                t2a[j][0] = t2b[j][0];
+            }
+        }
+        if (gp[procid].neighbors[RIGHT] == -1) {
+            for (j = firstrow; j <= lastrow; j++) {
+                t2a[j][jm - 1] = t2b[j][jm - 1];
+            }
+        }
+
+        for (i = firstrow; i <= lastrow; i++) {
+            t1a = (double *) t2a[i];
+            t1b = (double *) t2b[i];
+            for (iindex = firstcol; iindex <= lastcol; iindex++) {
+                t1a[iindex] = t1b[iindex];
+            }
+        }
+    }
+
+    END_PHASE(procid, 1);
+
+#if defined(MULTIPLE_BARRIERS)
+    BARRIER(bars->sl_phase_1, nprocs)
+#else
+    BARRIER(bars->barrier, nprocs)
+#endif
+    
+/*     *******************************************************
+
+              s e c o n d   p h a s e
+
+       *******************************************************
+
+   set values of psi{1,3} to psim{1,3}   */
+
+    START_PHASE(procid, 2);
+
+    for (psiindex = 0; psiindex <= 1; psiindex++) {
+        t2a = (double **) psi[procid][psiindex];
+        t2b = (double **) psim[procid][psiindex];
+        if ((gp[procid].neighbors[UP] == -1) && (gp[procid].neighbors[LEFT] == -1)) {
+            t2a[0][0] = t2b[0][0];
+        }
+        if ((gp[procid].neighbors[UP] == -1) && (gp[procid].neighbors[RIGHT] == -1)) {
+            t2a[0][jm - 1] = t2b[0][jm - 1];
+        }
+        if ((gp[procid].neighbors[DOWN] == -1) && (gp[procid].neighbors[LEFT] == -1)) {
+            t2a[im - 1][0] = t2b[im - 1][0];
+        }
+        if ((gp[procid].neighbors[DOWN] == -1) && (gp[procid].neighbors[RIGHT] == -1)) {
+            t2a[im - 1][jm - 1] = t2b[im - 1][jm - 1];
+        }
+        if (gp[procid].neighbors[UP] == -1) {
+            for (j = firstcol; j <= lastcol; j++) {
+                t2a[0][j] = t2b[0][j];
+            }
+        }
+        if (gp[procid].neighbors[DOWN] == -1) {
+            for (j = firstcol; j <= lastcol; j++) {
+                t2a[im - 1][j] = t2b[im - 1][j];
+            }
+        }
+        if (gp[procid].neighbors[LEFT] == -1) {
+            for (j = firstrow; j <= lastrow; j++) {
+                t2a[j][0] = t2b[j][0];
+            }
+        }
+        if (gp[procid].neighbors[RIGHT] == -1) {
+            for (j = firstrow; j <= lastrow; j++) {
+                t2a[j][jm - 1] = t2b[j][jm - 1];
+            }
+        }
+
+        for (i = firstrow; i <= lastrow; i++) {
+            t1a = (double *) t2a[i];
+            t1b = (double *) t2b[i];
+            for (iindex = firstcol; iindex <= lastcol; iindex++) {
+                t1a[iindex] = t1b[iindex];
+            }
+        }
+    }
+
+/* put the laplacian of the psim array
+   into the work7 array; first part of a three-laplacian
+   calculation to compute the friction terms  */
+
+    for (psiindex = 0; psiindex <= 1; psiindex++) {
+        t2a = (double **) work7[procid][psiindex];
+        if ((gp[procid].neighbors[UP] == -1) && (gp[procid].neighbors[LEFT] == -1)) {
+            t2a[0][0] = 0;
+        }
+        if ((gp[procid].neighbors[DOWN] == -1) && (gp[procid].neighbors[LEFT] == -1)) {
+            t2a[im - 1][0] = 0;
+        }
+        if ((gp[procid].neighbors[UP] == -1) && (gp[procid].neighbors[RIGHT] == -1)) {
+            t2a[0][jm - 1] = 0;
+        }
+        if ((gp[procid].neighbors[DOWN] == -1) && (gp[procid].neighbors[RIGHT] == -1)) {
+            t2a[im - 1][jm - 1] = 0;
+        }
+        laplacalc(procid, psim, work7, psiindex, firstrow, lastrow, firstcol, lastcol);
+    }
+
+/* to the values of the work1{1,2} arrays obtained from the
+   laplacians of psi{1,2} in the previous phase, add to the
+   elements of every column the corresponding value in the
+   one-dimenional f array  */
+
+    for (psiindex = 0; psiindex <= 1; psiindex++) {
+        t2a = (double **) work1[procid][psiindex];
+        if ((gp[procid].neighbors[UP] == -1) && (gp[procid].neighbors[LEFT] == -1)) {
+            t2a[0][0] = t2a[0][0] + f[0];
+        }
+        if ((gp[procid].neighbors[DOWN] == -1) && (gp[procid].neighbors[LEFT] == -1)) {
+            t2a[im - 1][0] = t2a[im - 1][0] + f[0];
+        }
+        if ((gp[procid].neighbors[UP] == -1) && (gp[procid].neighbors[RIGHT] == -1)) {
+            t2a[0][jm - 1] = t2a[0][jm - 1] + f[jmx[numlev - 1] - 1];
+        }
+        if ((gp[procid].neighbors[DOWN] == -1) && (gp[procid].neighbors[RIGHT] == -1)) {
+            t2a[im - 1][jm - 1] = t2a[im - 1][jm - 1] + f[jmx[numlev - 1] - 1];
+        }
+        if (gp[procid].neighbors[UP] == -1) {
+            for (j = firstcol; j <= lastcol; j++) {
+                t2a[0][j] = t2a[0][j] + f[j + j_off];
+            }
+        }
+        if (gp[procid].neighbors[DOWN] == -1) {
+            for (j = firstcol; j <= lastcol; j++) {
+                t2a[im - 1][j] = t2a[im - 1][j] + f[j + j_off];
+            }
+        }
+        if (gp[procid].neighbors[LEFT] == -1) {
+            for (j = firstrow; j <= lastrow; j++) {
+                t2a[j][0] = t2a[j][0] + f[j + i_off];
+            }
+        }
+        if (gp[procid].neighbors[RIGHT] == -1) {
+            for (j = firstrow; j <= lastrow; j++) {
+                t2a[j][jm - 1] = t2a[j][jm - 1] + f[j + i_off];
+            }
+        }
+        for (i = firstrow; i <= lastrow; i++) {
+            t1a = (double *) t2a[i];
+            for (iindex = firstcol; iindex <= lastcol; iindex++) {
+                t1a[iindex] = t1a[iindex] + f[iindex + j_off];
+            }
+        }
+    }
+
+    END_PHASE(procid, 2);
+    
+#if defined(MULTIPLE_BARRIERS)
+    BARRIER(bars->sl_phase_2, nprocs)
+#else
+    BARRIER(bars->barrier, nprocs)
+#endif
+/* 	*******************************************************
+
+                 t h i r d   p h a s e
+
+ 	*******************************************************
+
+   put the jacobian of the work1{1,2} and psi{1,3} arrays
+   (the latter currently in temparray) in the work5{1,2} arrays  */
+
+    START_PHASE(procid, 3);
+
+    for (psiindex = 0; psiindex <= 1; psiindex++) {
+        jacobcalc2(work1, temparray, work5, psiindex, procid, firstrow, lastrow, firstcol, lastcol);
+    }
+
+/* set values of psim{1,3} to temparray{1,3}  */
+
+    for (psiindex = 0; psiindex <= 1; psiindex++) {
+        t2a = (double **) psim[procid][psiindex];
+        t2b = (double **) temparray[procid][psiindex];
+        if ((gp[procid].neighbors[UP] == -1) && (gp[procid].neighbors[LEFT] == -1)) {
+            t2a[0][0] = t2b[0][0];
+        }
+        if ((gp[procid].neighbors[DOWN] == -1) && (gp[procid].neighbors[LEFT] == -1)) {
+            t2a[im - 1][0] = t2b[im - 1][0];
+        }
+        if ((gp[procid].neighbors[UP] == -1) && (gp[procid].neighbors[RIGHT] == -1)) {
+            t2a[0][jm - 1] = t2b[0][jm - 1];
+        }
+        if ((gp[procid].neighbors[DOWN] == -1) && (gp[procid].neighbors[RIGHT] == -1)) {
+            t2a[im - 1][jm - 1] = t2b[im - 1][jm - 1];
+        }
+        if (gp[procid].neighbors[UP] == -1) {
+            t1a = (double *) t2a[0];
+            t1b = (double *) t2b[0];
+            for (j = firstcol; j <= lastcol; j++) {
+                t1a[j] = t1b[j];
+            }
+        }
+        if (gp[procid].neighbors[DOWN] == -1) {
+            t1a = (double *) t2a[im - 1];
+            t1b = (double *) t2b[im - 1];
+            for (j = firstcol; j <= lastcol; j++) {
+                t1a[j] = t1b[j];
+            }
+        }
+        if (gp[procid].neighbors[LEFT] == -1) {
+            for (j = firstrow; j <= lastrow; j++) {
+                t2a[j][0] = t2b[j][0];
+            }
+        }
+        if (gp[procid].neighbors[RIGHT] == -1) {
+            for (j = firstrow; j <= lastrow; j++) {
+                t2a[j][jm - 1] = t2b[j][jm - 1];
+            }
+        }
+        for (i = firstrow; i <= lastrow; i++) {
+            t1a = (double *) t2a[i];
+            t1b = (double *) t2b[i];
+            for (iindex = firstcol; iindex <= lastcol; iindex++) {
+                t1a[iindex] = t1b[iindex];
+            }
+        }
+    }
+
+/* put the laplacian of the work7{1,2} arrays in the work4{1,2}
+   arrays; second step in the three-laplacian friction calculation  */
+
+    for (psiindex = 0; psiindex <= 1; psiindex++) {
+        laplacalc(procid, work7, work4, psiindex, firstrow, lastrow, firstcol, lastcol);
+    }
+
+    END_PHASE(procid, 3);
+
+#if defined(MULTIPLE_BARRIERS)
+    BARRIER(bars->sl_phase_3, nprocs)
+#else
+    BARRIER(bars->barrier, nprocs)
+#endif
+
+/*     *******************************************************
+
+                f o u r t h   p h a s e
+
+       *******************************************************
+
+   put the jacobian of the work2 and work3 arrays in the work6
+   array  */
+
+    START_PHASE(procid, 4);
+
+    jacobcalc(work2, work3, work6, procid, firstrow, lastrow, firstcol, lastcol);
+
+/* put the laplacian of the work4{1,2} arrays in the work7{1,2}
+   arrays; third step in the three-laplacian friction calculation  */
+
+    for (psiindex = 0; psiindex <= 1; psiindex++) {
+        laplacalc(procid, work4, work7, psiindex, firstrow, lastrow, firstcol, lastcol);
+    }
+    
+    END_PHASE(procid, 4);
+
+#if defined(MULTIPLE_BARRIERS)
+    BARRIER(bars->sl_phase_4, nprocs)
+#else
+    BARRIER(bars->barrier, nprocs)
+#endif
+
+/*     *******************************************************
+
+                f i f t h   p h a s e
+
+       *******************************************************
+
+   use the values of the work5, work6 and work7 arrays
+   computed in the previous time-steps to compute the
+   ga and gb arrays   */
+
+    START_PHASE(procid, 5);
+
+    hinv = 1.0 / h;
+    h1inv = 1.0 / h1;
+
+    t2a = (double **) ga[procid];
+    t2b = (double **) gb[procid];
+    t2c = (double **) work5[procid][0];
+    t2d = (double **) work5[procid][1];
+    t2e = (double **) work7[procid][0];
+    t2f = (double **) work7[procid][1];
+    t2g = (double **) work6[procid];
+    t2h = (double **) tauz[procid];
+    if ((gp[procid].neighbors[UP] == -1) && (gp[procid].neighbors[LEFT] == -1)) {
+        t2a[0][0] = t2c[0][0] - t2d[0][0] + eig2 * t2g[0][0] + h1inv * t2h[0][0] + lf * t2e[0][0] - lf * t2f[0][0];
+        t2b[0][0] = hh1 * t2c[0][0] + hh3 * t2d[0][0] + hinv * t2h[0][0] + lf * hh1 * t2e[0][0] + lf * hh3 * t2f[0][0];
+    }
+    if ((gp[procid].neighbors[DOWN] == -1) && (gp[procid].neighbors[LEFT] == -1)) {
+        t2a[im - 1][0] = t2c[im - 1][0] - t2d[im - 1][0] + eig2 * t2g[im - 1][0] + h1inv * t2h[im - 1][0] + lf * t2e[im - 1][0] - lf * t2f[im - 1][0];
+        t2b[im - 1][0] = hh1 * t2c[im - 1][0] + hh3 * t2d[im - 1][0] + hinv * t2h[im - 1][0] + lf * hh1 * t2e[im - 1][0] + lf * hh3 * t2f[im - 1][0];
+    }
+    if ((gp[procid].neighbors[UP] == -1) && (gp[procid].neighbors[RIGHT] == -1)) {
+        t2a[0][jm - 1] = t2c[0][jm - 1] - t2d[0][jm - 1] + eig2 * t2g[0][jm - 1] + h1inv * t2h[0][jm - 1] + lf * t2e[0][jm - 1] - lf * t2f[0][jm - 1];
+        t2b[0][jm - 1] = hh1 * t2c[0][jm - 1] + hh3 * t2d[0][jm - 1] + hinv * t2h[0][jm - 1] + lf * hh1 * t2e[0][jm - 1] + lf * hh3 * t2f[0][jm - 1];
+    }
+    if ((gp[procid].neighbors[DOWN] == -1) && (gp[procid].neighbors[RIGHT] == -1)) {
+        t2a[im - 1][jm - 1] = t2c[im - 1][jm - 1] - t2d[im - 1][jm - 1] + eig2 * t2g[im - 1][jm - 1] + h1inv * t2h[im - 1][jm - 1] + lf * t2e[im - 1][jm - 1] - lf * t2f[im - 1][jm - 1];
+        t2b[im - 1][jm - 1] = hh1 * t2c[im - 1][jm - 1] + hh3 * t2d[im - 1][jm - 1] + hinv * t2h[im - 1][jm - 1] + lf * hh1 * t2e[im - 1][jm - 1] + lf * hh3 * t2f[im - 1][jm - 1];
+    }
+    if (gp[procid].neighbors[UP] == -1) {
+        t1a = (double *) t2a[0];
+        t1b = (double *) t2b[0];
+        t1c = (double *) t2c[0];
+        t1d = (double *) t2d[0];
+        t1e = (double *) t2e[0];
+        t1f = (double *) t2f[0];
+        t1g = (double *) t2g[0];
+        t1h = (double *) t2h[0];
+        for (j = firstcol; j <= lastcol; j++) {
+            t1a[j] = t1c[j] - t1d[j] + eig2 * t1g[j] + h1inv * t1h[j] + lf * t1e[j] - lf * t1f[j];
+            t1b[j] = hh1 * t1c[j] + hh3 * t1d[j] + hinv * t1h[j] + lf * hh1 * t1e[j] + lf * hh3 * t1f[j];
+        }
+    }
+    if (gp[procid].neighbors[DOWN] == -1) {
+        t1a = (double *) t2a[im - 1];
+        t1b = (double *) t2b[im - 1];
+        t1c = (double *) t2c[im - 1];
+        t1d = (double *) t2d[im - 1];
+        t1e = (double *) t2e[im - 1];
+        t1f = (double *) t2f[im - 1];
+        t1g = (double *) t2g[im - 1];
+        t1h = (double *) t2h[im - 1];
+        for (j = firstcol; j <= lastcol; j++) {
+            t1a[j] = t1c[j] - t1d[j] + eig2 * t1g[j] + h1inv * t1h[j] + lf * t1e[j] - lf * t1f[j];
+            t1b[j] = hh1 * t1c[j] + hh3 * t1d[j] + hinv * t1h[j] + lf * hh1 * t1e[j] + lf * hh3 * t1f[j];
+        }
+    }
+    if (gp[procid].neighbors[LEFT] == -1) {
+        for (j = firstrow; j <= lastrow; j++) {
+            t2a[j][0] = t2c[j][0] - t2d[j][0] + eig2 * t2g[j][0] + h1inv * t2h[j][0] + lf * t2e[j][0] - lf * t2f[j][0];
+            t2b[j][0] = hh1 * t2c[j][0] + hh3 * t2d[j][0] + hinv * t2h[j][0] + lf * hh1 * t2e[j][0] + lf * hh3 * t2f[j][0];
+        }
+    }
+    if (gp[procid].neighbors[RIGHT] == -1) {
+        for (j = firstrow; j <= lastrow; j++) {
+            t2a[j][jm - 1] = t2c[j][jm - 1] - t2d[j][jm - 1] + eig2 * t2g[j][jm - 1] + h1inv * t2h[j][jm - 1] + lf * t2e[j][jm - 1] - lf * t2f[j][jm - 1];
+            t2b[j][jm - 1] = hh1 * t2c[j][jm - 1] + hh3 * t2d[j][jm - 1] + hinv * t2h[j][jm - 1] + lf * hh1 * t2e[j][jm - 1] + lf * hh3 * t2f[j][jm - 1];
+        }
+    }
+
+    for (i = firstrow; i <= lastrow; i++) {
+        t1a = (double *) t2a[i];
+        t1b = (double *) t2b[i];
+        t1c = (double *) t2c[i];
+        t1d = (double *) t2d[i];
+        t1e = (double *) t2e[i];
+        t1f = (double *) t2f[i];
+        t1g = (double *) t2g[i];
+        t1h = (double *) t2h[i];
+        for (iindex = firstcol; iindex <= lastcol; iindex++) {
+            t1a[iindex] = t1c[iindex] - t1d[iindex] + eig2 * t1g[iindex] + h1inv * t1h[iindex] + lf * t1e[iindex] - lf * t1f[iindex];
+            t1b[iindex] = hh1 * t1c[iindex] + hh3 * t1d[iindex] + hinv * t1h[iindex] + lf * hh1 * t1e[iindex] + lf * hh3 * t1f[iindex];
+        }
+    }
+
+    END_PHASE(procid, 5);
+
+#if defined(MULTIPLE_BARRIERS)
+    BARRIER(bars->sl_phase_5, nprocs)
+#else
+    BARRIER(bars->barrier, nprocs)
+#endif
+
+/*     *******************************************************
+
+               s i x t h   p h a s e
+
+       *******************************************************  */
+
+    START_PHASE(procid, 6);
+
+    istart = 1;
+    iend = istart + gp[procid].rel_num_y[numlev - 1] - 1;
+    jstart = 1;
+    jend = jstart + gp[procid].rel_num_x[numlev - 1] - 1;
+    ist = istart;
+    ien = iend;
+    jst = jstart;
+    jen = jend;
+
+    if (gp[procid].neighbors[UP] == -1) {
+        istart = 0;
+    }
+    if (gp[procid].neighbors[LEFT] == -1) {
+        jstart = 0;
+    }
+    if (gp[procid].neighbors[DOWN] == -1) {
+        iend = im - 1;
+    }
+    if (gp[procid].neighbors[RIGHT] == -1) {
+        jend = jm - 1;
+    }
+    t2a = (double **) rhs_multi[procid][numlev - 1];
+    t2b = (double **) ga[procid];
+    t2c = (double **) oldga[procid];
+    t2d = (double **) q_multi[procid][numlev - 1];
+    for (i = istart; i <= iend; i++) {
+        t1a = (double *) t2a[i];
+        t1b = (double *) t2b[i];
+        for (j = jstart; j <= jend; j++) {
+            t1a[j] = t1b[j] * ressqr;
+        }
+    }
+
+    if (gp[procid].neighbors[UP] == -1) {
+        t1d = (double *) t2d[0];
+        t1b = (double *) t2b[0];
+        for (j = jstart; j <= jend; j++) {
+            t1d[j] = t1b[j];
+        }
+    }
+    if (gp[procid].neighbors[DOWN] == -1) {
+        t1d = (double *) t2d[im - 1];
+        t1b = (double *) t2b[im - 1];
+        for (j = jstart; j <= jend; j++) {
+            t1d[j] = t1b[j];
+        }
+    }
+    if (gp[procid].neighbors[LEFT] == -1) {
+        for (i = istart; i <= iend; i++) {
+            t2d[i][0] = t2b[i][0];
+        }
+    }
+    if (gp[procid].neighbors[RIGHT] == -1) {
+        for (i = istart; i <= iend; i++) {
+            t2d[i][jm - 1] = t2b[i][jm - 1];
+        }
+    }
+    //fac = 1.0 / (4.0 - ressqr*eig2);
+    for (i = ist; i <= ien; i++) {
+        t1d = (double *) t2d[i];
+        t1c = (double *) t2c[i];
+        for (j = jst; j <= jen; j++) {
+            t1d[j] = t1c[j];
+        }
+    }
+
+    if ((procid == MASTER) || (do_stats)) {
+        CLOCK(multi_start);
+    }
+
+    multig(procid);
+
+    if ((procid == MASTER) || (do_stats)) {
+        CLOCK(multi_end);
+        (*gp[procid].multi_time) += (multi_end - multi_start);
+    }
+
+/* the shared sum variable psiai is initialized to 0 at
+   every time-step  */
+
+    if (procid == MASTER) {
+        global->psiai = 0.0;
+    }
+
+/*  copy the solution for use as initial guess in next time-step  */
+
+    for (i = istart; i <= iend; i++) {
+        t1b = (double *) t2b[i];
+        t1c = (double *) t2c[i];
+        t1d = (double *) t2d[i];
+        for (j = jstart; j <= jend; j++) {
+            t1b[j] = t1d[j];
+            t1c[j] = t1d[j];
+        }
+    }
+
+    END_PHASE(procid, 6);
+
+#if defined(MULTIPLE_BARRIERS)
+    BARRIER(bars->sl_phase_6, nprocs)
+#else
+    BARRIER(bars->barrier, nprocs)
+#endif
+
+/*     *******************************************************
+
+                s e v e n t h   p h a s e
+
+       *******************************************************
+
+   every process computes the running sum for its assigned portion
+   in a private variable psiaipriv   */
+
+    START_PHASE(procid, 7);
+
+    psiaipriv = 0.0;
+    t2a = (double **) ga[procid];
+    if ((gp[procid].neighbors[UP] == -1) && (gp[procid].neighbors[LEFT] == -1)) {
+        psiaipriv = psiaipriv + 0.25 * (t2a[0][0]);
+    }
+    if ((gp[procid].neighbors[UP] == -1) && (gp[procid].neighbors[RIGHT] == -1)) {
+        psiaipriv = psiaipriv + 0.25 * (t2a[0][jm - 1]);
+    }
+    if ((gp[procid].neighbors[DOWN] == -1) && (gp[procid].neighbors[LEFT] == -1)) {
+        psiaipriv = psiaipriv + 0.25 * (t2a[im - 1][0]);
+    }
+    if ((gp[procid].neighbors[DOWN] == -1) && (gp[procid].neighbors[RIGHT] == -1)) {
+        psiaipriv = psiaipriv + 0.25 * (t2a[im - 1][jm - 1]);
+    }
+    if (gp[procid].neighbors[UP] == -1) {
+        t1a = (double *) t2a[0];
+        for (j = firstcol; j <= lastcol; j++) {
+            psiaipriv = psiaipriv + 0.5 * t1a[j];
+        }
+    }
+    if (gp[procid].neighbors[DOWN] == -1) {
+        t1a = (double *) t2a[im - 1];
+        for (j = firstcol; j <= lastcol; j++) {
+            psiaipriv = psiaipriv + 0.5 * t1a[j];
+        }
+    }
+    if (gp[procid].neighbors[LEFT] == -1) {
+        for (j = firstrow; j <= lastrow; j++) {
+            psiaipriv = psiaipriv + 0.5 * t2a[j][0];
+        }
+    }
+    if (gp[procid].neighbors[RIGHT] == -1) {
+        for (j = firstrow; j <= lastrow; j++) {
+            psiaipriv = psiaipriv + 0.5 * t2a[j][jm - 1];
+        }
+    }
+    for (i = firstrow; i <= lastrow; i++) {
+        t1a = (double *) t2a[i];
+        for (iindex = firstcol; iindex <= lastcol; iindex++) {
+            psiaipriv = psiaipriv + t1a[iindex];
+        }
+    }
+
+/* after computing its private sum, every process adds that to the
+   shared running sum psiai  */
+
+    LOCK(locks->psiailock)
+    global->psiai = global->psiai + psiaipriv;
+    UNLOCK(locks->psiailock)
+
+    END_PHASE(procid, 7);
+
+#if defined(MULTIPLE_BARRIERS)
+    BARRIER(bars->sl_phase_7, nprocs)
+#else
+    BARRIER(bars->barrier, nprocs)
+#endif
+    
+/*      *******************************************************
+
+                e i g h t h   p h a s e
+
+        *******************************************************
+
+   augment ga(i,j) with [-psiai/psibi]*psib(i,j) */
+
+    START_PHASE(procid, 8);
+
+    f4 = (-global->psiai) /(global->psibi);
+
+    t2a = (double **) ga[procid];
+    t2b = (double **) psib[procid];
+    if ((gp[procid].neighbors[UP] == -1) && (gp[procid].neighbors[LEFT] == -1)) {
+        t2a[0][0] = t2a[0][0] + f4 * t2b[0][0];
+    }
+    if ((gp[procid].neighbors[DOWN] == -1) && (gp[procid].neighbors[LEFT] == -1)) {
+        t2a[im - 1][0] = t2a[im - 1][0] + f4 * t2b[im - 1][0];
+    }
+    if ((gp[procid].neighbors[UP] == -1) && (gp[procid].neighbors[RIGHT] == -1)) {
+        t2a[0][jm - 1] = t2a[0][jm - 1] + f4 * t2b[0][jm - 1];
+    }
+    if ((gp[procid].neighbors[DOWN] == -1) && (gp[procid].neighbors[RIGHT] == -1)) {
+        t2a[im - 1][jm - 1] = t2a[im - 1][jm - 1] + f4 * t2b[im - 1][jm - 1];
+    }
+    if (gp[procid].neighbors[UP] == -1) {
+        t1a = (double *) t2a[0];
+        t1b = (double *) t2b[0];
+        for (j = firstcol; j <= lastcol; j++) {
+            t1a[j] = t1a[j] + f4 * t1b[j];
+        }
+    }
+    if (gp[procid].neighbors[DOWN] == -1) {
+        t1a = (double *) t2a[im - 1];
+        t1b = (double *) t2b[im - 1];
+        for (j = firstcol; j <= lastcol; j++) {
+            t1a[j] = t1a[j] + f4 * t1b[j];
+        }
+    }
+    if (gp[procid].neighbors[LEFT] == -1) {
+        for (j = firstrow; j <= lastrow; j++) {
+            t2a[j][0] = t2a[j][0] + f4 * t2b[j][0];
+        }
+    }
+    if (gp[procid].neighbors[RIGHT] == -1) {
+        for (j = firstrow; j <= lastrow; j++) {
+            t2a[j][jm - 1] = t2a[j][jm - 1] + f4 * t2b[j][jm - 1];
+        }
+    }
+    for (i = firstrow; i <= lastrow; i++) {
+        t1a = (double *) t2a[i];
+        t1b = (double *) t2b[i];
+        for (iindex = firstcol; iindex <= lastcol; iindex++) {
+            t1a[iindex] = t1a[iindex] + f4 * t1b[iindex];
+        }
+    }
+
+    t2a = (double **) rhs_multi[procid][numlev - 1];
+    t2b = (double **) gb[procid];
+    t2c = (double **) oldgb[procid];
+    t2d = (double **) q_multi[procid][numlev - 1];
+    for (i = istart; i <= iend; i++) {
+        t1a = (double *) t2a[i];
+        t1b = (double *) t2b[i];
+        for (j = jstart; j <= jend; j++) {
+            t1a[j] = t1b[j] * ressqr;
+        }
+    }
+    if (gp[procid].neighbors[UP] == -1) {
+        t1d = (double *) t2d[0];
+        t1b = (double *) t2b[0];
+        for (j = jstart; j <= jend; j++) {
+            t1d[j] = t1b[j];
+        }
+    }
+    if (gp[procid].neighbors[DOWN] == -1) {
+        t1d = (double *) t2d[im - 1];
+        t1b = (double *) t2b[im - 1];
+        for (j = jstart; j <= jend; j++) {
+            t1d[j] = t1b[j];
+        }
+    }
+    if (gp[procid].neighbors[LEFT] == -1) {
+        for (i = istart; i <= iend; i++) {
+            t2d[i][0] = t2b[i][0];
+        }
+    }
+    if (gp[procid].neighbors[RIGHT] == -1) {
+        for (i = istart; i <= iend; i++) {
+            t2d[i][jm - 1] = t2b[i][jm - 1];
+        }
+    }
+    //fac = 1.0 / (4.0 - ressqr*eig2);
+    for (i = ist; i <= ien; i++) {
+        t1d = (double *) t2d[i];
+        t1c = (double *) t2c[i];
+        for (j = jst; j <= jen; j++) {
+            t1d[j] = t1c[j];
+        }
+    }
+
+    if ((procid == MASTER) || (do_stats)) {
+        CLOCK(multi_start);
+    }
+
+    multig(procid);
+
+    if ((procid == MASTER) || (do_stats)) {
+        CLOCK(multi_end);
+        (*gp[procid].multi_time) += (multi_end - multi_start);
+    }
+
+    for (i = istart; i <= iend; i++) {
+        t1b = (double *) t2b[i];
+        t1c = (double *) t2c[i];
+        t1d = (double *) t2d[i];
+        for (j = jstart; j <= jend; j++) {
+            t1b[j] = t1d[j];
+            t1c[j] = t1d[j];
+        }
+    }
+
+    END_PHASE(procid, 8);
+
+#if defined(MULTIPLE_BARRIERS)
+    BARRIER(bars->sl_phase_8, nprocs)
+#else
+    BARRIER(bars->barrier, nprocs)
+#endif
+
+/*      *******************************************************
+
+                n i n t h   p h a s e
+
+        *******************************************************
+
+   put appropriate linear combinations of ga and gb in work2 and work3;
+   note that here (as in most cases) the constant multipliers are made
+   private variables; the specific order in which things are done is
+   chosen in order to hopefully reuse things brought into the cache
+
+   note that here again we choose to have all processes share the work
+   on both matrices despite the fact that the work done per element
+   is the same, because the operand matrices are the same in both cases */
+
+    START_PHASE(procid, 9);
+
+    t2a = (double **) ga[procid];
+    t2b = (double **) gb[procid];
+    t2c = (double **) work2[procid];
+    t2d = (double **) work3[procid];
+    if ((gp[procid].neighbors[UP] == -1) && (gp[procid].neighbors[LEFT] == -1)) {
+        t2c[0][0] = t2b[0][0] - hh1 * t2a[0][0];
+        t2d[0][0] = t2b[0][0] + hh3 * t2a[0][0];
+    }
+    if ((gp[procid].neighbors[DOWN] == -1) && (gp[procid].neighbors[LEFT] == -1)) {
+        t2c[im - 1][0] = t2b[im - 1][0] - hh1 * t2a[im - 1][0];
+        t2d[im - 1][0] = t2b[im - 1][0] + hh3 * t2a[im - 1][0];
+    }
+    if ((gp[procid].neighbors[UP] == -1) && (gp[procid].neighbors[RIGHT] == -1)) {
+        t2c[0][jm - 1] = t2b[0][jm - 1] - hh1 * t2a[0][jm - 1];
+        t2d[0][jm - 1] = t2b[0][jm - 1] + hh3 * t2a[0][jm - 1];
+    }
+    if ((gp[procid].neighbors[DOWN] == -1) && (gp[procid].neighbors[RIGHT] == -1)) {
+        t2c[im - 1][jm - 1] = t2b[im - 1][jm - 1] - hh1 * t2a[im - 1][jm - 1];
+        t2d[im - 1][jm - 1] = t2b[im - 1][jm - 1] + hh3 * t2a[im - 1][jm - 1];
+    }
+    if (gp[procid].neighbors[UP] == -1) {
+        t1a = (double *) t2a[0];
+        t1b = (double *) t2b[0];
+        t1c = (double *) t2c[0];
+        t1d = (double *) t2d[0];
+        for (j = firstcol; j <= lastcol; j++) {
+            t1d[j] = t1b[j] + hh3 * t1a[j];
+            t1c[j] = t1b[j] - hh1 * t1a[j];
+        }
+    }
+    if (gp[procid].neighbors[DOWN] == -1) {
+        t1a = (double *) t2a[im - 1];
+        t1b = (double *) t2b[im - 1];
+        t1c = (double *) t2c[im - 1];
+        t1d = (double *) t2d[im - 1];
+        for (j = firstcol; j <= lastcol; j++) {
+            t1d[j] = t1b[j] + hh3 * t1a[j];
+            t1c[j] = t1b[j] - hh1 * t1a[j];
+        }
+    }
+    if (gp[procid].neighbors[LEFT] == -1) {
+        for (j = firstrow; j <= lastrow; j++) {
+            t2d[j][0] = t2b[j][0] + hh3 * t2a[j][0];
+            t2c[j][0] = t2b[j][0] - hh1 * t2a[j][0];
+        }
+    }
+    if (gp[procid].neighbors[RIGHT] == -1) {
+        for (j = firstrow; j <= lastrow; j++) {
+            t2d[j][jm - 1] = t2b[j][jm - 1] + hh3 * t2a[j][jm - 1];
+            t2c[j][jm - 1] = t2b[j][jm - 1] - hh1 * t2a[j][jm - 1];
+        }
+    }
+
+    for (i = firstrow; i <= lastrow; i++) {
+        t1a = (double *) t2a[i];
+        t1b = (double *) t2b[i];
+        t1c = (double *) t2c[i];
+        t1d = (double *) t2d[i];
+        for (iindex = firstcol; iindex <= lastcol; iindex++) {
+            t1d[iindex] = t1b[iindex] + hh3 * t1a[iindex];
+            t1c[iindex] = t1b[iindex] - hh1 * t1a[iindex];
+        }
+    }
+
+    END_PHASE(procid, 9);
+
+#if defined(MULTIPLE_BARRIERS)
+    BARRIER(bars->sl_phase_9, nprocs)
+#else
+    BARRIER(bars->barrier, nprocs)
+#endif
+
+/*      *******************************************************
+
+                t e n t h    p h a s e
+
+        *******************************************************/
+
+    START_PHASE(procid, 10);
+    timst = 2 * dtau;
+
+/* update the psi{1,3} matrices by adding 2*dtau*work3 to each */
+
+    t2a = (double **) psi[procid][0];
+    t2b = (double **) work3[procid];
+    if ((gp[procid].neighbors[UP] == -1) && (gp[procid].neighbors[LEFT] == -1)) {
+        t2a[0][0] = t2a[0][0] + timst * t2b[0][0];
+    }
+    if ((gp[procid].neighbors[DOWN] == -1) && (gp[procid].neighbors[LEFT] == -1)) {
+        t2a[im - 1][0] = t2a[im - 1][0] + timst * t2b[im - 1][0];
+    }
+    if ((gp[procid].neighbors[UP] == -1) && (gp[procid].neighbors[RIGHT] == -1)) {
+        t2a[0][jm - 1] = t2a[0][jm - 1] + timst * t2b[0][jm - 1];
+    }
+    if ((gp[procid].neighbors[DOWN] == -1) && (gp[procid].neighbors[RIGHT] == -1)) {
+        t2a[im - 1][jm - 1] = t2a[im - 1][jm - 1] + timst * t2b[im - 1][jm - 1];
+    }
+    if (gp[procid].neighbors[UP] == -1) {
+        t1a = (double *) t2a[0];
+        t1b = (double *) t2b[0];
+        for (j = firstcol; j <= lastcol; j++) {
+            t1a[j] = t1a[j] + timst * t1b[j];
+        }
+    }
+    if (gp[procid].neighbors[DOWN] == -1) {
+        t1a = (double *) t2a[im - 1];
+        t1b = (double *) t2b[im - 1];
+        for (j = firstcol; j <= lastcol; j++) {
+            t1a[j] = t1a[j] + timst * t1b[j];
+        }
+    }
+    if (gp[procid].neighbors[LEFT] == -1) {
+        for (j = firstrow; j <= lastrow; j++) {
+            t2a[j][0] = t2a[j][0] + timst * t2b[j][0];
+        }
+    }
+    if (gp[procid].neighbors[RIGHT] == -1) {
+        for (j = firstrow; j <= lastrow; j++) {
+            t2a[j][jm - 1] = t2a[j][jm - 1] + timst * t2b[j][jm - 1];
+        }
+    }
+    for (i = firstrow; i <= lastrow; i++) {
+        t1a = (double *) t2a[i];
+        t1b = (double *) t2b[i];
+        for (iindex = firstcol; iindex <= lastcol; iindex++) {
+            t1a[iindex] = t1a[iindex] + timst * t1b[iindex];
+        }
+    }
+
+    t2a = (double **) psi[procid][1];
+    t2b = (double **) work2[procid];
+    if ((gp[procid].neighbors[UP] == -1) && (gp[procid].neighbors[LEFT] == -1)) {
+        t2a[0][0] = t2a[0][0] + timst * t2b[0][0];
+    }
+    if ((gp[procid].neighbors[DOWN] == -1) && (gp[procid].neighbors[LEFT] == -1)) {
+        t2a[im - 1][0] = t2a[im - 1][0] + timst * t2b[im - 1][0];
+    }
+    if ((gp[procid].neighbors[UP] == -1) && (gp[procid].neighbors[RIGHT] == -1)) {
+        t2a[0][jm - 1] = t2a[0][jm - 1] + timst * t2b[0][jm - 1];
+    }
+    if ((gp[procid].neighbors[DOWN] == -1) && (gp[procid].neighbors[RIGHT] == -1)) {
+        t2a[im - 1][jm - 1] = t2a[im - 1][jm - 1] + timst * t2b[im - 1][jm - 1];
+    }
+    if (gp[procid].neighbors[UP] == -1) {
+        t1a = (double *) t2a[0];
+        t1b = (double *) t2b[0];
+        for (j = firstcol; j <= lastcol; j++) {
+            t1a[j] = t1a[j] + timst * t1b[j];
+        }
+    }
+    if (gp[procid].neighbors[DOWN] == -1) {
+        t1a = (double *) t2a[im - 1];
+        t1b = (double *) t2b[im - 1];
+        for (j = firstcol; j <= lastcol; j++) {
+            t1a[j] = t1a[j] + timst * t1b[j];
+        }
+    }
+    if (gp[procid].neighbors[LEFT] == -1) {
+        for (j = firstrow; j <= lastrow; j++) {
+            t2a[j][0] = t2a[j][0] + timst * t2b[j][0];
+        }
+    }
+    if (gp[procid].neighbors[RIGHT] == -1) {
+        for (j = firstrow; j <= lastrow; j++) {
+            t2a[j][jm - 1] = t2a[j][jm - 1] + timst * t2b[j][jm - 1];
+        }
+    }
+
+    for (i = firstrow; i <= lastrow; i++) {
+        t1a = (double *) t2a[i];
+        t1b = (double *) t2b[i];
+        for (iindex = firstcol; iindex <= lastcol; iindex++) {
+            t1a[iindex] = t1a[iindex] + timst * t1b[iindex];
+        }
+    }
+
+    END_PHASE(procid, 10);
+
+#if defined(MULTIPLE_BARRIERS)
+    BARRIER(bars->sl_phase_10, nprocs)
+#else
+    BARRIER(bars->barrier, nprocs)
+#endif
+}
Index: /soft/giet_vm/applications/ocean/subblock.C
===================================================================
--- /soft/giet_vm/applications/ocean/subblock.C	(revision 581)
+++ /soft/giet_vm/applications/ocean/subblock.C	(revision 581)
@@ -0,0 +1,117 @@
+/*************************************************************************/
+/*                                                                       */
+/*  Copyright (c) 1994 Stanford University                               */
+/*                                                                       */
+/*  All rights reserved.                                                 */
+/*                                                                       */
+/*  Permission is given to use, copy, and modify this software for any   */
+/*  non-commercial purpose as long as this copyright notice is not       */
+/*  removed.  All other uses, including redistribution in whole or in    */
+/*  part, are forbidden without prior written permission.                */
+/*                                                                       */
+/*  This software is provided with absolutely no warranty and no         */
+/*  support.                                                             */
+/*                                                                       */
+/*************************************************************************/
+
+EXTERN_ENV
+
+#include <stdio.h>
+#include <math.h>
+
+#include "decs.h"
+
+
+void subblock()
+{
+    long i;
+    long j;
+    long k;
+    long xportion;
+    long yportion;
+    long my_num;
+
+/* Determine starting coord and number of points to process in     */
+/* each direction                                                  */
+
+    for (i = 0; i < numlev; i++) {
+        xportion = (jmx[i] - 2) / xprocs;
+        //xextra = (jmx[i] - 2) % xprocs;
+        for (j = 0; j < xprocs; j++) {
+            for (k = 0; k < yprocs; k++) {
+                gp[k * xprocs + j].rel_num_x[i] = xportion;
+            }
+        }
+        yportion = (imx[i] - 2) / yprocs;
+        //yextra = (imx[i] - 2) % yprocs;
+        for (j = 0; j < yprocs; j++) {
+            for (k = 0; k < xprocs; k++) {
+                gp[j * xprocs + k].rel_num_y[i] = yportion;
+            }
+        }
+    }
+
+    for (my_num = 0; my_num < nprocs; my_num++) {
+        for (i = 0; i < numlev; i++) {
+            gp[my_num].rlist[i] = 1;
+            gp[my_num].rljst[i] = 1;
+            gp[my_num].rlien[i] = gp[my_num].rlist[i] + gp[my_num].rel_num_y[i];
+            gp[my_num].rljen[i] = gp[my_num].rljst[i] + gp[my_num].rel_num_x[i];
+            gp[my_num].eist[i] = gp[my_num].rlist[i] + 1;
+            gp[my_num].oist[i] = gp[my_num].rlist[i];
+            gp[my_num].ejst[i] = gp[my_num].rljst[i] + 1;
+            gp[my_num].ojst[i] = gp[my_num].rljst[i];
+        }
+    }
+    
+    for (i = 0; i < nprocs; i++) {
+        gp[i].neighbors[LEFT] = -1;
+        gp[i].neighbors[RIGHT] = -1;
+        gp[i].neighbors[UP] = -1;
+        gp[i].neighbors[DOWN] = -1;
+        gp[i].neighbors[UPLEFT] = -1;
+        gp[i].neighbors[UPRIGHT] = -1;
+        gp[i].neighbors[DOWNLEFT] = -1;
+        gp[i].neighbors[DOWNRIGHT] = -1;
+        
+        if (i >= xprocs) {
+            gp[i].neighbors[UP] = i - xprocs;
+        }
+        if (i < nprocs - xprocs) {
+            gp[i].neighbors[DOWN] = i + xprocs;
+        }
+        if ((i % xprocs) > 0) {
+            gp[i].neighbors[LEFT] = i - 1;
+        }
+        if ((i % xprocs) < (xprocs - 1)) {
+            gp[i].neighbors[RIGHT] = i + 1;
+        }
+        
+        j = gp[i].neighbors[UP];
+        
+        if (j != -1) {
+            if ((j % xprocs) > 0) {
+                gp[i].neighbors[UPLEFT] = j - 1;
+            }
+            if ((j % xprocs) < (xprocs - 1)) {
+                gp[i].neighbors[UPRIGHT] = j + 1;
+            }
+        }
+        
+        j = gp[i].neighbors[DOWN];
+        
+        if (j != -1) {
+            if ((j % xprocs) > 0) {
+                gp[i].neighbors[DOWNLEFT] = j - 1;
+            }
+            if ((j % xprocs) < (xprocs - 1)) {
+                gp[i].neighbors[DOWNRIGHT] = j + 1;
+            }
+        }
+    }
+    
+    for (i = 0; i < nprocs; i++) {
+        (*gp[i].rownum) = i / xprocs;
+        (*gp[i].colnum) = i % xprocs;
+    }
+}
Index: /soft/giet_vm/giet_libs/math.h
===================================================================
--- /soft/giet_vm/giet_libs/math.h	(revision 581)
+++ /soft/giet_vm/giet_libs/math.h	(revision 581)
@@ -0,0 +1,20 @@
+// Avril 2015
+//  importation de fonctions mathÃ©matiques de la librairie ulibc-0.9.32 pour implÃ©mentations sur GIET
+//  Pierre LAURENT
+
+#ifndef MATH_H_
+#define MATH_H_
+
+double	fabs	(double x);
+double	floor	(double x);
+double	sin		(double x);
+double	pow		(double x, double y);
+int		isnan	(double x);
+int		isfinite(double x);
+double	scalbln	(double x, long n);
+double	scalbn	(double x, int n);
+double	copysign(double x, double y);
+double 	rint	(double x);
+double	sqrt	(double x);
+
+#endif
Index: /soft/giet_vm/giet_libs/math/e_pow.c
===================================================================
--- /soft/giet_vm/giet_libs/math/e_pow.c	(revision 581)
+++ /soft/giet_vm/giet_libs/math/e_pow.c	(revision 581)
@@ -0,0 +1,354 @@
+/*
+ * ====================================================
+ * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
+ *
+ * Developed at SunPro, a Sun Microsystems, Inc. business.
+ * Permission to use, copy, modify, and distribute this
+ * software is freely granted, provided that this notice
+ * is preserved.
+ * ====================================================
+ */
+
+/* Modified for GIET-VM static OS at UPMC, France 2015.
+ */
+
+/* __ieee754_pow(x,y) return x**y
+ *
+ *		      n
+ * Method:  Let x =  2   * (1+f)
+ *	1. Compute and return log2(x) in two pieces:
+ *		log2(x) = w1 + w2,
+ *	   where w1 has 53-24 = 29 bit trailing zeros.
+ *	2. Perform y*log2(x) = n+y' by simulating muti-precision
+ *	   arithmetic, where |y'|<=0.5.
+ *	3. Return x**y = 2**n*exp(y'*log2)
+ *
+ * Special cases:
+ *	1.  +-1 ** anything  is 1.0
+ *	2.  +-1 ** +-INF     is 1.0
+ *	3.  (anything) ** 0  is 1
+ *	4.  (anything) ** 1  is itself
+ *	5.  (anything) ** NAN is NAN
+ *	6.  NAN ** (anything except 0) is NAN
+ *	7.  +-(|x| > 1) **  +INF is +INF
+ *	8.  +-(|x| > 1) **  -INF is +0
+ *	9.  +-(|x| < 1) **  +INF is +0
+ *	10  +-(|x| < 1) **  -INF is +INF
+ *	11. +0 ** (+anything except 0, NAN)               is +0
+ *	12. -0 ** (+anything except 0, NAN, odd integer)  is +0
+ *	13. +0 ** (-anything except 0, NAN)               is +INF
+ *	14. -0 ** (-anything except 0, NAN, odd integer)  is +INF
+ *	15. -0 ** (odd integer) = -( +0 ** (odd integer) )
+ *	16. +INF ** (+anything except 0,NAN) is +INF
+ *	17. +INF ** (-anything except 0,NAN) is +0
+ *	18. -INF ** (anything)  = -0 ** (-anything)
+ *	19. (-anything) ** (integer) is (-1)**(integer)*(+anything**integer)
+ *	20. (-anything except 0 and inf) ** (non-integer) is NAN
+ *
+ * Accuracy:
+ *	pow(x,y) returns x**y nearly rounded. In particular
+ *			pow(integer,integer)
+ *	always returns the correct integer provided it is
+ *	representable.
+ *
+ * Constants :
+ * The hexadecimal values are the intended ones for the following
+ * constants. The decimal values may be used, provided that the
+ * compiler will convert from decimal to binary accurately enough
+ * to produce the hexadecimal values shown.
+ */
+
+#include "../math.h"
+#include "math_private.h"
+
+#include <stdio.h>
+
+static const double
+bp[] = {1.0, 1.5,},
+dp_h[] = { 0.0, 5.84962487220764160156e-01,}, /* 0x3FE2B803, 0x40000000 */
+dp_l[] = { 0.0, 1.35003920212974897128e-08,}, /* 0x3E4CFDEB, 0x43CFD006 */
+zero    =  0.0,
+one	=  1.0,
+two	=  2.0,
+two53	=  9007199254740992.0,	/* 0x43400000, 0x00000000 */
+huge	=  1.0e300,
+tiny    =  1.0e-300,
+	/* poly coefs for (3/2)*(log(x)-2s-2/3*s**3 */
+L1  =  5.99999999999994648725e-01, /* 0x3FE33333, 0x33333303 */
+L2  =  4.28571428578550184252e-01, /* 0x3FDB6DB6, 0xDB6FABFF */
+L3  =  3.33333329818377432918e-01, /* 0x3FD55555, 0x518F264D */
+L4  =  2.72728123808534006489e-01, /* 0x3FD17460, 0xA91D4101 */
+L5  =  2.30660745775561754067e-01, /* 0x3FCD864A, 0x93C9DB65 */
+L6  =  2.06975017800338417784e-01, /* 0x3FCA7E28, 0x4A454EEF */
+P1   =  1.66666666666666019037e-01, /* 0x3FC55555, 0x5555553E */
+P2   = -2.77777777770155933842e-03, /* 0xBF66C16C, 0x16BEBD93 */
+P3   =  6.61375632143793436117e-05, /* 0x3F11566A, 0xAF25DE2C */
+P4   = -1.65339022054652515390e-06, /* 0xBEBBBD41, 0xC5D26BF1 */
+P5   =  4.13813679705723846039e-08, /* 0x3E663769, 0x72BEA4D0 */
+lg2  =  6.93147180559945286227e-01, /* 0x3FE62E42, 0xFEFA39EF */
+lg2_h  =  6.93147182464599609375e-01, /* 0x3FE62E43, 0x00000000 */
+lg2_l  = -1.90465429995776804525e-09, /* 0xBE205C61, 0x0CA86C39 */
+ovt =  8.0085662595372944372e-0017, /* -(1024-log2(ovfl+.5ulp)) */
+cp    =  9.61796693925975554329e-01, /* 0x3FEEC709, 0xDC3A03FD =2/(3ln2) */
+cp_h  =  9.61796700954437255859e-01, /* 0x3FEEC709, 0xE0000000 =(float)cp */
+cp_l  = -7.02846165095275826516e-09, /* 0xBE3E2FE0, 0x145B01F5 =tail of cp_h*/
+ivln2    =  1.44269504088896338700e+00, /* 0x3FF71547, 0x652B82FE =1/ln2 */
+ivln2_h  =  1.44269502162933349609e+00, /* 0x3FF71547, 0x60000000 =24b 1/ln2*/
+ivln2_l  =  1.92596299112661746887e-08; /* 0x3E54AE0B, 0xF85DDF44 =1/ln2 tail*/
+
+double __ieee754_pow(double x, double y)
+{
+	double z,ax,z_h,z_l,p_h,p_l;
+	double y1,t1,t2,r,s,t,u,v,w;
+	int32_t i,j,k,yisint,n;
+	int32_t hx,hy,ix,iy;
+	u_int32_t lx,ly;
+
+	EXTRACT_WORDS(hx,lx,x);
+    /* x==1: 1**y = 1 (even if y is NaN) */
+	if (hx==0x3ff00000 && lx==0) {
+		return x;
+	}
+	ix = hx&0x7fffffff;
+
+	EXTRACT_WORDS(hy,ly,y);
+	iy = hy&0x7fffffff;
+
+    /* y==zero: x**0 = 1 */
+	if((iy|ly)==0) return one;
+
+    /* +-NaN return x+y */
+	if(ix > 0x7ff00000 || ((ix==0x7ff00000)&&(lx!=0)) ||
+	   iy > 0x7ff00000 || ((iy==0x7ff00000)&&(ly!=0)))
+		return x+y;
+
+    /* determine if y is an odd int when x < 0
+     * yisint = 0	... y is not an integer
+     * yisint = 1	... y is an odd int
+     * yisint = 2	... y is an even int
+     */
+	yisint  = 0;
+	if(hx<0) {
+	    if(iy>=0x43400000) yisint = 2; /* even integer y */
+	    else if(iy>=0x3ff00000) {
+		k = (iy>>20)-0x3ff;	   /* exponent */
+		if(k>20) {
+		    j = ly>>(52-k);
+		    if((j<<(52-k))==ly) yisint = 2-(j&1);
+		} else if(ly==0) {
+		    j = iy>>(20-k);
+		    if((j<<(20-k))==iy) yisint = 2-(j&1);
+		}
+	    }
+	}
+
+    /* special value of y */
+	if(ly==0) {
+	    if (iy==0x7ff00000) {       /* y is +-inf */
+	        if (((ix-0x3ff00000)|lx)==0)
+		    return one;	        /* +-1**+-inf is 1 (yes, weird rule) */
+	        if (ix >= 0x3ff00000)   /* (|x|>1)**+-inf = inf,0 */
+		    return (hy>=0) ? y : zero;
+	        /* (|x|<1)**-,+inf = inf,0 */
+		return (hy<0) ? -y : zero;
+	    }
+	    if(iy==0x3ff00000) {	/* y is  +-1 */
+		if(hy<0) return one/x; else return x;
+	    }
+	    if(hy==0x40000000) return x*x; /* y is  2 */
+	    if(hy==0x3fe00000) {	/* y is  0.5 */
+		if(hx>=0)	/* x >= +0 */
+		    return sqrt(x);
+	    }
+	}
+
+	ax   = fabs(x);
+    /* special value of x */
+	if(lx==0) {
+	    if(ix==0x7ff00000||ix==0||ix==0x3ff00000){
+		z = ax;			/*x is +-0,+-inf,+-1*/
+		if(hy<0) z = one/z;	/* z = (1/|x|) */
+		if(hx<0) {
+		    if(((ix-0x3ff00000)|yisint)==0) {
+			z = (z-z)/(z-z); /* (-1)**non-int is NaN */
+		    } else if(yisint==1)
+			z = -z;		/* (x<0)**odd = -(|x|**odd) */
+		}
+		return z;
+	    }
+	}
+
+    /* (x<0)**(non-int) is NaN */
+	if(((((u_int32_t)hx>>31)-1)|yisint)==0) return (x-x)/(x-x);
+
+    /* |y| is huge */
+	if(iy>0x41e00000) { /* if |y| > 2**31 */
+	    if(iy>0x43f00000){	/* if |y| > 2**64, must o/uflow */
+		if(ix<=0x3fefffff) return (hy<0)? huge*huge:tiny*tiny;
+		if(ix>=0x3ff00000) return (hy>0)? huge*huge:tiny*tiny;
+	    }
+	/* over/underflow if x is not close to one */
+	    if(ix<0x3fefffff) return (hy<0)? huge*huge:tiny*tiny;
+	    if(ix>0x3ff00000) return (hy>0)? huge*huge:tiny*tiny;
+	/* now |1-x| is tiny <= 2**-20, suffice to compute
+	   log(x) by x-x^2/2+x^3/3-x^4/4 */
+	    t = x-1;		/* t has 20 trailing zeros */
+	    w = (t*t)*(0.5-t*(0.3333333333333333333333-t*0.25));
+	    u = ivln2_h*t;	/* ivln2_h has 21 sig. bits */
+	    v = t*ivln2_l-w*ivln2;
+	    t1 = u+v;
+	    SET_LOW_WORD(t1,0);
+	    t2 = v-(t1-u);
+	} else {
+	    double s2,s_h,s_l,t_h,t_l;
+	    n = 0;
+	/* take care subnormal number */
+	    if(ix<0x00100000)
+		{ax *= two53; n -= 53; GET_HIGH_WORD(ix,ax); }
+	    n  += ((ix)>>20)-0x3ff;
+	    j  = ix&0x000fffff;
+	/* determine interval */
+	    ix = j|0x3ff00000;		/* normalize ix */
+	    if(j<=0x3988E) k=0;		/* |x|<sqrt(3/2) */
+	    else if(j<0xBB67A) k=1;	/* |x|<sqrt(3)   */
+	    else {k=0;n+=1;ix -= 0x00100000;}
+	    SET_HIGH_WORD(ax,ix);
+
+	/* compute s = s_h+s_l = (x-1)/(x+1) or (x-1.5)/(x+1.5) */
+	    u = ax-bp[k];		/* bp[0]=1.0, bp[1]=1.5 */
+	    v = one/(ax+bp[k]);
+	    s = u*v;
+	    s_h = s;
+	    SET_LOW_WORD(s_h,0);
+	/* t_h=ax+bp[k] High */
+	    t_h = zero;
+	    SET_HIGH_WORD(t_h,((ix>>1)|0x20000000)+0x00080000+(k<<18));
+	    t_l = ax - (t_h-bp[k]);
+	    s_l = v*((u-s_h*t_h)-s_h*t_l);
+	/* compute log(ax) */
+	    s2 = s*s;
+	    r = s2*s2*(L1+s2*(L2+s2*(L3+s2*(L4+s2*(L5+s2*L6)))));
+	    r += s_l*(s_h+s);
+	    s2  = s_h*s_h;
+	    t_h = 3.0+s2+r;
+	    SET_LOW_WORD(t_h,0);
+	    t_l = r-((t_h-3.0)-s2);
+	/* u+v = s*(1+...) */
+	    u = s_h*t_h;
+	    v = s_l*t_h+t_l*s;
+	/* 2/(3log2)*(s+...) */
+	    p_h = u+v;
+	    SET_LOW_WORD(p_h,0);
+	    p_l = v-(p_h-u);
+	    z_h = cp_h*p_h;		/* cp_h+cp_l = 2/(3*log2) */
+	    z_l = cp_l*p_h+p_l*cp+dp_l[k];
+	/* log2(ax) = (s+..)*2/(3*log2) = n + dp_h + z_h + z_l */
+	    t = (double)n;
+	    t1 = (((z_h+z_l)+dp_h[k])+t);
+	    SET_LOW_WORD(t1,0);
+	    t2 = z_l-(((t1-t)-dp_h[k])-z_h);
+	}
+
+	s = one; /* s (sign of result -ve**odd) = -1 else = 1 */
+	if(((((u_int32_t)hx>>31)-1)|(yisint-1))==0)
+	    s = -one;/* (-ve)**(odd int) */
+
+    /* split up y into y1+y2 and compute (y1+y2)*(t1+t2) */
+	y1  = y;
+	SET_LOW_WORD(y1,0);
+	p_l = (y-y1)*t1+y*t2;
+	p_h = y1*t1;
+	z = p_l+p_h;
+	EXTRACT_WORDS(j,i,z);
+	if (j>=0x40900000) {				/* z >= 1024 */
+	    if(((j-0x40900000)|i)!=0)			/* if z > 1024 */
+		return s*huge*huge;			/* overflow */
+	    else {
+		if(p_l+ovt>z-p_h) return s*huge*huge;	/* overflow */
+	    }
+	} else if((j&0x7fffffff)>=0x4090cc00 ) {	/* z <= -1075 */
+	    if(((j-0xc090cc00)|i)!=0) 		/* z < -1075 */
+		return s*tiny*tiny;		/* underflow */
+	    else {
+		if(p_l<=z-p_h) return s*tiny*tiny;	/* underflow */
+	    }
+	}
+    /*
+     * compute 2**(p_h+p_l)
+     */
+	i = j&0x7fffffff;
+	k = (i>>20)-0x3ff;
+	n = 0;
+	if(i>0x3fe00000) {		/* if |z| > 0.5, set n = [z+0.5] */
+	    n = j+(0x00100000>>(k+1));
+	    k = ((n&0x7fffffff)>>20)-0x3ff;	/* new k for n */
+	    t = zero;
+	    SET_HIGH_WORD(t,n&~(0x000fffff>>k));
+	    n = ((n&0x000fffff)|0x00100000)>>(20-k);
+	    if(j<0) n = -n;
+	    p_h -= t;
+	}
+	t = p_l+p_h;
+	SET_LOW_WORD(t,0);
+	u = t*lg2_h;
+	v = (p_l-(t-p_h))*lg2+t*lg2_l;
+	z = u+v;
+	w = v-(z-u);
+	t  = z*z;
+	t1  = z - t*(P1+t*(P2+t*(P3+t*(P4+t*P5))));
+	r  = (z*t1)/(t1-two)-(w+z*w);
+	z  = one-(r-z);
+	GET_HIGH_WORD(j,z);
+	j += (n<<20);
+	if((j>>20)<=0) z = scalbn(z,n);	/* subnormal output */
+	else SET_HIGH_WORD(z,j);
+	return s*z;
+}
+
+/*
+ * wrapper pow(x,y) return x**y
+ */
+double pow(double x, double y)
+{
+	double z = __ieee754_pow(x, y);
+	if (isnan(y))
+		return z;
+	if (isnan(x)) {
+		if (y == 0.0) {
+			giet_shr_printf("\nWarning : pow(NaN,0.0)\n");
+			return x; /* pow(NaN,0.0) */
+		}
+		return z;
+	}
+	if (x == 0.0) {
+		if (y == 0.0) {
+				giet_shr_printf("\nWarning : pow(0.0,0.0)\n");
+	    		return 0; /* pow(0.0,0.0) */
+		}
+		if (isfinite(y) && y < 0.0) {
+			giet_shr_printf("\nWarning : pow(0.0,negative)\n");
+			return -huge; /* pow(0.0,negative) */
+		}
+		return z;
+	}
+	if (!isfinite(z)) {
+		if (isfinite(x) && isfinite(y)) {
+			if (isnan(z)) {
+				giet_shr_printf("\nWarning : pow(neg,non-int)\n");
+				return 0.0/0.0; /* pow neg**non-int */
+			}
+			{
+				double ret = huge;
+				giet_shr_printf("\nWarning : pow overflow\n");
+				y *= 0.5;
+				if(x<zero&&rint(y)!=y) ret = -huge;
+				return ret;
+			}
+		}
+	}
+	if (z == 0.0 && isfinite(x) && isfinite(y)) {
+		giet_shr_printf("\nWarning : pow underflow\n");
+		return 0.0;
+	}
+	return z;
+}
Index: /soft/giet_vm/giet_libs/math/e_rem_pio2.c
===================================================================
--- /soft/giet_vm/giet_libs/math/e_rem_pio2.c	(revision 581)
+++ /soft/giet_vm/giet_libs/math/e_rem_pio2.c	(revision 581)
@@ -0,0 +1,164 @@
+/*
+ * ====================================================
+ * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
+ *
+ * Developed at SunPro, a Sun Microsystems, Inc. business.
+ * Permission to use, copy, modify, and distribute this
+ * software is freely granted, provided that this notice
+ * is preserved.
+ * ====================================================
+ */
+
+/* Modified for GIET-VM static OS at UPMC, France 2015.
+ */
+
+/* __ieee754_rem_pio2(x,y)
+ *
+ * return the remainder of x rem pi/2 in y[0]+y[1]
+ * use __kernel_rem_pio2()
+ */
+
+#include "../math.h"
+#include "math_private.h"
+
+/*
+ * Table of constants for 2/pi, 396 Hex digits (476 decimal) of 2/pi
+ */
+static const int32_t two_over_pi[] = {
+0xA2F983, 0x6E4E44, 0x1529FC, 0x2757D1, 0xF534DD, 0xC0DB62,
+0x95993C, 0x439041, 0xFE5163, 0xABDEBB, 0xC561B7, 0x246E3A,
+0x424DD2, 0xE00649, 0x2EEA09, 0xD1921C, 0xFE1DEB, 0x1CB129,
+0xA73EE8, 0x8235F5, 0x2EBB44, 0x84E99C, 0x7026B4, 0x5F7E41,
+0x3991D6, 0x398353, 0x39F49C, 0x845F8B, 0xBDF928, 0x3B1FF8,
+0x97FFDE, 0x05980F, 0xEF2F11, 0x8B5A0A, 0x6D1F6D, 0x367ECF,
+0x27CB09, 0xB74F46, 0x3F669E, 0x5FEA2D, 0x7527BA, 0xC7EBE5,
+0xF17B3D, 0x0739F7, 0x8A5292, 0xEA6BFB, 0x5FB11F, 0x8D5D08,
+0x560330, 0x46FC7B, 0x6BABF0, 0xCFBC20, 0x9AF436, 0x1DA9E3,
+0x91615E, 0xE61B08, 0x659985, 0x5F14A0, 0x68408D, 0xFFD880,
+0x4D7327, 0x310606, 0x1556CA, 0x73A8C9, 0x60E27B, 0xC08C6B,
+};
+
+static const int32_t npio2_hw[] = {
+0x3FF921FB, 0x400921FB, 0x4012D97C, 0x401921FB, 0x401F6A7A, 0x4022D97C,
+0x4025FDBB, 0x402921FB, 0x402C463A, 0x402F6A7A, 0x4031475C, 0x4032D97C,
+0x40346B9C, 0x4035FDBB, 0x40378FDB, 0x403921FB, 0x403AB41B, 0x403C463A,
+0x403DD85A, 0x403F6A7A, 0x40407E4C, 0x4041475C, 0x4042106C, 0x4042D97C,
+0x4043A28C, 0x40446B9C, 0x404534AC, 0x4045FDBB, 0x4046C6CB, 0x40478FDB,
+0x404858EB, 0x404921FB,
+};
+
+/*
+ * invpio2:  53 bits of 2/pi
+ * pio2_1:   first  33 bit of pi/2
+ * pio2_1t:  pi/2 - pio2_1
+ * pio2_2:   second 33 bit of pi/2
+ * pio2_2t:  pi/2 - (pio2_1+pio2_2)
+ * pio2_3:   third  33 bit of pi/2
+ * pio2_3t:  pi/2 - (pio2_1+pio2_2+pio2_3)
+ */
+
+static const double
+zero =  0.00000000000000000000e+00, /* 0x00000000, 0x00000000 */
+half =  5.00000000000000000000e-01, /* 0x3FE00000, 0x00000000 */
+two24 =  1.67772160000000000000e+07, /* 0x41700000, 0x00000000 */
+invpio2 =  6.36619772367581382433e-01, /* 0x3FE45F30, 0x6DC9C883 */
+pio2_1  =  1.57079632673412561417e+00, /* 0x3FF921FB, 0x54400000 */
+pio2_1t =  6.07710050650619224932e-11, /* 0x3DD0B461, 0x1A626331 */
+pio2_2  =  6.07710050630396597660e-11, /* 0x3DD0B461, 0x1A600000 */
+pio2_2t =  2.02226624879595063154e-21, /* 0x3BA3198A, 0x2E037073 */
+pio2_3  =  2.02226624871116645580e-21, /* 0x3BA3198A, 0x2E000000 */
+pio2_3t =  8.47842766036889956997e-32; /* 0x397B839A, 0x252049C1 */
+
+int __ieee754_rem_pio2(double x, double *y)
+{
+	double z=0.0,w,t,r,fn;
+	double tx[3];
+	int32_t e0,i,j,nx,n,ix,hx;
+	u_int32_t low;
+
+	GET_HIGH_WORD(hx,x);		/* high word of x */
+	ix = hx&0x7fffffff;
+	if(ix<=0x3fe921fb)   /* |x| ~<= pi/4 , no need for reduction */
+	    {y[0] = x; y[1] = 0; return 0;}
+	if(ix<0x4002d97c) {  /* |x| < 3pi/4, special case with n=+-1 */
+	    if(hx>0) {
+		z = x - pio2_1;
+		if(ix!=0x3ff921fb) { 	/* 33+53 bit pi is good enough */
+		    y[0] = z - pio2_1t;
+		    y[1] = (z-y[0])-pio2_1t;
+		} else {		/* near pi/2, use 33+33+53 bit pi */
+		    z -= pio2_2;
+		    y[0] = z - pio2_2t;
+		    y[1] = (z-y[0])-pio2_2t;
+		}
+		return 1;
+	    } else {	/* negative x */
+		z = x + pio2_1;
+		if(ix!=0x3ff921fb) { 	/* 33+53 bit pi is good enough */
+		    y[0] = z + pio2_1t;
+		    y[1] = (z-y[0])+pio2_1t;
+		} else {		/* near pi/2, use 33+33+53 bit pi */
+		    z += pio2_2;
+		    y[0] = z + pio2_2t;
+		    y[1] = (z-y[0])+pio2_2t;
+		}
+		return -1;
+	    }
+	}
+	if(ix<=0x413921fb) { /* |x| ~<= 2^19*(pi/2), medium size */
+	    t  = fabs(x);
+	    n  = (int32_t) (t*invpio2+half);
+	    fn = (double)n;
+	    r  = t-fn*pio2_1;
+	    w  = fn*pio2_1t;	/* 1st round good to 85 bit */
+	    if(n<32&&ix!=npio2_hw[n-1]) {
+		y[0] = r-w;	/* quick check no cancellation */
+	    } else {
+	        u_int32_t high;
+	        j  = ix>>20;
+	        y[0] = r-w;
+		GET_HIGH_WORD(high,y[0]);
+	        i = j-((high>>20)&0x7ff);
+	        if(i>16) {  /* 2nd iteration needed, good to 118 */
+		    t  = r;
+		    w  = fn*pio2_2;
+		    r  = t-w;
+		    w  = fn*pio2_2t-((t-r)-w);
+		    y[0] = r-w;
+		    GET_HIGH_WORD(high,y[0]);
+		    i = j-((high>>20)&0x7ff);
+		    if(i>49)  {	/* 3rd iteration need, 151 bits acc */
+		    	t  = r;	/* will cover all possible cases */
+		    	w  = fn*pio2_3;
+		    	r  = t-w;
+		    	w  = fn*pio2_3t-((t-r)-w);
+		    	y[0] = r-w;
+		    }
+		}
+	    }
+	    y[1] = (r-y[0])-w;
+	    if(hx<0) 	{y[0] = -y[0]; y[1] = -y[1]; return -n;}
+	    else	 return n;
+	}
+    /*
+     * all other (large) arguments
+     */
+	if(ix>=0x7ff00000) {		/* x is inf or NaN */
+	    y[0]=y[1]=x-x; return 0;
+	}
+    /* set z = scalbn(|x|,ilogb(x)-23) */
+	GET_LOW_WORD(low,x);
+	SET_LOW_WORD(z,low);
+	e0 	= (ix>>20)-1046;	/* e0 = ilogb(z)-23; */
+	SET_HIGH_WORD(z, ix - ((int32_t)(e0<<20)));
+	for(i=0;i<2;i++) {
+		tx[i] = (double)((int32_t)(z));
+		z     = (z-tx[i])*two24;
+	}
+	tx[2] = z;
+	nx = 3;
+	while(tx[nx-1]==zero) nx--;	/* skip zero term */
+	n  =  __kernel_rem_pio2(tx,y,e0,nx,2,two_over_pi);
+	if(hx<0) {y[0] = -y[0]; y[1] = -y[1]; return -n;}
+	return n;
+}
Index: /soft/giet_vm/giet_libs/math/e_sqrt.c
===================================================================
--- /soft/giet_vm/giet_libs/math/e_sqrt.c	(revision 581)
+++ /soft/giet_vm/giet_libs/math/e_sqrt.c	(revision 581)
@@ -0,0 +1,443 @@
+/*
+ * ====================================================
+ * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
+ *
+ * Developed at SunPro, a Sun Microsystems, Inc. business.
+ * Permission to use, copy, modify, and distribute this
+ * software is freely granted, provided that this notice
+ * is preserved.
+ * ====================================================
+ */
+
+/* Modified for GIET-VM static OS at UPMC, France 2015.
+ */
+
+/* __ieee754_sqrt(x)
+ * Return correctly rounded sqrt.
+ *           ------------------------------------------
+ *	     |  Use the hardware sqrt if you have one |
+ *           ------------------------------------------
+ * Method:
+ *   Bit by bit method using integer arithmetic. (Slow, but portable)
+ *   1. Normalization
+ *	Scale x to y in [1,4) with even powers of 2:
+ *	find an integer k such that  1 <= (y=x*2^(2k)) < 4, then
+ *		sqrt(x) = 2^k * sqrt(y)
+ *   2. Bit by bit computation
+ *	Let q  = sqrt(y) truncated to i bit after binary point (q = 1),
+ *	     i							 0
+ *                                     i+1         2
+ *	    s  = 2*q , and	y  =  2   * ( y - q  ).		(1)
+ *	     i      i            i                 i
+ *
+ *	To compute q    from q , one checks whether
+ *		    i+1       i
+ *
+ *			      -(i+1) 2
+ *			(q + 2      ) <= y.			(2)
+ *     			  i
+ *							      -(i+1)
+ *	If (2) is false, then q   = q ; otherwise q   = q  + 2      .
+ *		 	       i+1   i             i+1   i
+ *
+ *	With some algebric manipulation, it is not difficult to see
+ *	that (2) is equivalent to
+ *                             -(i+1)
+ *			s  +  2       <= y			(3)
+ *			 i                i
+ *
+ *	The advantage of (3) is that s  and y  can be computed by
+ *				      i      i
+ *	the following recurrence formula:
+ *	    if (3) is false
+ *
+ *	    s     =  s  ,	y    = y   ;			(4)
+ *	     i+1      i		 i+1    i
+ *
+ *	    otherwise,
+ *                         -i                     -(i+1)
+ *	    s	  =  s  + 2  ,  y    = y  -  s  - 2  		(5)
+ *           i+1      i          i+1    i     i
+ *
+ *	One may easily use induction to prove (4) and (5).
+ *	Note. Since the left hand side of (3) contain only i+2 bits,
+ *	      it does not necessary to do a full (53-bit) comparison
+ *	      in (3).
+ *   3. Final rounding
+ *	After generating the 53 bits result, we compute one more bit.
+ *	Together with the remainder, we can decide whether the
+ *	result is exact, bigger than 1/2ulp, or less than 1/2ulp
+ *	(it will never equal to 1/2ulp).
+ *	The rounding mode can be detected by checking whether
+ *	huge + tiny is equal to huge, and whether huge - tiny is
+ *	equal to huge for some floating point number "huge" and "tiny".
+ *
+ * Special cases:
+ *	sqrt(+-0) = +-0 	... exact
+ *	sqrt(inf) = inf
+ *	sqrt(-ve) = NaN		... with invalid signal
+ *	sqrt(NaN) = NaN		... with invalid signal for signaling NaN
+ *
+ * Other methods : see the appended file at the end of the program below.
+ *---------------
+ */
+
+#include "../math.h"
+#include "math_private.h"
+
+static const double one = 1.0, tiny = 1.0e-300;
+
+double __ieee754_sqrt(double x)
+{
+	double z;
+	int32_t sign = (int)0x80000000;
+	int32_t ix0,s0,q,m,t,i;
+	u_int32_t r,t1,s1,ix1,q1;
+
+	EXTRACT_WORDS(ix0,ix1,x);
+
+    /* take care of Inf and NaN */
+	if((ix0&0x7ff00000)==0x7ff00000) {
+	    return x*x+x;		/* sqrt(NaN)=NaN, sqrt(+inf)=+inf
+					   sqrt(-inf)=sNaN */
+	}
+    /* take care of zero */
+	if(ix0<=0) {
+	    if(((ix0&(~sign))|ix1)==0) return x;/* sqrt(+-0) = +-0 */
+	    else if(ix0<0)
+		return (x-x)/(x-x);		/* sqrt(-ve) = sNaN */
+	}
+    /* normalize x */
+	m = (ix0>>20);
+	if(m==0) {				/* subnormal x */
+	    while(ix0==0) {
+		m -= 21;
+		ix0 |= (ix1>>11); ix1 <<= 21;
+	    }
+	    for(i=0;(ix0&0x00100000)==0;i++) ix0<<=1;
+	    m -= i-1;
+	    ix0 |= (ix1>>(32-i));
+	    ix1 <<= i;
+	}
+	m -= 1023;	/* unbias exponent */
+	ix0 = (ix0&0x000fffff)|0x00100000;
+	if(m&1){	/* odd m, double x to make it even */
+	    ix0 += ix0 + ((ix1&sign)>>31);
+	    ix1 += ix1;
+	}
+	m >>= 1;	/* m = [m/2] */
+
+    /* generate sqrt(x) bit by bit */
+	ix0 += ix0 + ((ix1&sign)>>31);
+	ix1 += ix1;
+	q = q1 = s0 = s1 = 0;	/* [q,q1] = sqrt(x) */
+	r = 0x00200000;		/* r = moving bit from right to left */
+
+	while(r!=0) {
+	    t = s0+r;
+	    if(t<=ix0) {
+		s0   = t+r;
+		ix0 -= t;
+		q   += r;
+	    }
+	    ix0 += ix0 + ((ix1&sign)>>31);
+	    ix1 += ix1;
+	    r>>=1;
+	}
+
+	r = sign;
+	while(r!=0) {
+	    t1 = s1+r;
+	    t  = s0;
+	    if((t<ix0)||((t==ix0)&&(t1<=ix1))) {
+		s1  = t1+r;
+		if(((t1&sign)==sign)&&(s1&sign)==0) s0 += 1;
+		ix0 -= t;
+		if (ix1 < t1) ix0 -= 1;
+		ix1 -= t1;
+		q1  += r;
+	    }
+	    ix0 += ix0 + ((ix1&sign)>>31);
+	    ix1 += ix1;
+	    r>>=1;
+	}
+
+    /* use floating add to find out rounding direction */
+	if((ix0|ix1)!=0) {
+	    z = one-tiny; /* trigger inexact flag */
+	    if (z>=one) {
+	        z = one+tiny;
+	        if (q1==(u_int32_t)0xffffffff) { q1=0; q += 1;}
+		else if (z>one) {
+		    if (q1==(u_int32_t)0xfffffffe) q+=1;
+		    q1+=2;
+		} else
+	            q1 += (q1&1);
+	    }
+	}
+	ix0 = (q>>1)+0x3fe00000;
+	ix1 =  q1>>1;
+	if ((q&1)==1) ix1 |= sign;
+	ix0 += (m <<20);
+	INSERT_WORDS(z,ix0,ix1);
+	return z;
+}
+
+
+
+/*
+Other methods  (use floating-point arithmetic)
+-------------
+(This is a copy of a drafted paper by Prof W. Kahan
+and K.C. Ng, written in May, 1986)
+
+	Two algorithms are given here to implement sqrt(x)
+	(IEEE double precision arithmetic) in software.
+	Both supply sqrt(x) correctly rounded. The first algorithm (in
+	Section A) uses newton iterations and involves four divisions.
+	The second one uses reciproot iterations to avoid division, but
+	requires more multiplications. Both algorithms need the ability
+	to chop results of arithmetic operations instead of round them,
+	and the INEXACT flag to indicate when an arithmetic operation
+	is executed exactly with no roundoff error, all part of the
+	standard (IEEE 754-1985). The ability to perform shift, add,
+	subtract and logical AND operations upon 32-bit words is needed
+	too, though not part of the standard.
+
+A.  sqrt(x) by Newton Iteration
+
+   (1)	Initial approximation
+
+	Let x0 and x1 be the leading and the trailing 32-bit words of
+	a floating point number x (in IEEE double format) respectively
+
+	    1    11		     52				  ...widths
+	   ------------------------------------------------------
+	x: |s|	  e     |	      f				|
+	   ------------------------------------------------------
+	      msb    lsb  msb				      lsb ...order
+
+
+	     ------------------------  	     ------------------------
+	x0:  |s|   e    |    f1     |	 x1: |          f2           |
+	     ------------------------  	     ------------------------
+
+	By performing shifts and subtracts on x0 and x1 (both regarded
+	as integers), we obtain an 8-bit approximation of sqrt(x) as
+	follows.
+
+		k  := (x0>>1) + 0x1ff80000;
+		y0 := k - T1[31&(k>>15)].	... y ~ sqrt(x) to 8 bits
+	Here k is a 32-bit integer and T1[] is an integer array containing
+	correction terms. Now magically the floating value of y (y's
+	leading 32-bit word is y0, the value of its trailing word is 0)
+	approximates sqrt(x) to almost 8-bit.
+
+	Value of T1:
+	static int T1[32]= {
+	0,	1024,	3062,	5746,	9193,	13348,	18162,	23592,
+	29598,	36145,	43202,	50740,	58733,	67158,	75992,	85215,
+	83599,	71378,	60428,	50647,	41945,	34246,	27478,	21581,
+	16499,	12183,	8588,	5674,	3403,	1742,	661,	130,};
+
+    (2)	Iterative refinement
+
+	Apply Heron's rule three times to y, we have y approximates
+	sqrt(x) to within 1 ulp (Unit in the Last Place):
+
+		y := (y+x/y)/2		... almost 17 sig. bits
+		y := (y+x/y)/2		... almost 35 sig. bits
+		y := y-(y-x/y)/2	... within 1 ulp
+
+
+	Remark 1.
+	    Another way to improve y to within 1 ulp is:
+
+		y := (y+x/y)		... almost 17 sig. bits to 2*sqrt(x)
+		y := y - 0x00100006	... almost 18 sig. bits to sqrt(x)
+
+				2
+			    (x-y )*y
+		y := y + 2* ----------	...within 1 ulp
+			       2
+			     3y  + x
+
+
+	This formula has one division fewer than the one above; however,
+	it requires more multiplications and additions. Also x must be
+	scaled in advance to avoid spurious overflow in evaluating the
+	expression 3y*y+x. Hence it is not recommended uless division
+	is slow. If division is very slow, then one should use the
+	reciproot algorithm given in section B.
+
+    (3) Final adjustment
+
+	By twiddling y's last bit it is possible to force y to be
+	correctly rounded according to the prevailing rounding mode
+	as follows. Let r and i be copies of the rounding mode and
+	inexact flag before entering the square root program. Also we
+	use the expression y+-ulp for the next representable floating
+	numbers (up and down) of y. Note that y+-ulp = either fixed
+	point y+-1, or multiply y by nextafter(1,+-inf) in chopped
+	mode.
+
+		I := FALSE;	... reset INEXACT flag I
+		R := RZ;	... set rounding mode to round-toward-zero
+		z := x/y;	... chopped quotient, possibly inexact
+		If(not I) then {	... if the quotient is exact
+		    if(z=y) {
+		        I := i;	 ... restore inexact flag
+		        R := r;  ... restore rounded mode
+		        return sqrt(x):=y.
+		    } else {
+			z := z - ulp;	... special rounding
+		    }
+		}
+		i := TRUE;		... sqrt(x) is inexact
+		If (r=RN) then z=z+ulp	... rounded-to-nearest
+		If (r=RP) then {	... round-toward-+inf
+		    y = y+ulp; z=z+ulp;
+		}
+		y := y+z;		... chopped sum
+		y0:=y0-0x00100000;	... y := y/2 is correctly rounded.
+	        I := i;	 		... restore inexact flag
+	        R := r;  		... restore rounded mode
+	        return sqrt(x):=y.
+
+    (4)	Special cases
+
+	Square root of +inf, +-0, or NaN is itself;
+	Square root of a negative number is NaN with invalid signal.
+
+
+B.  sqrt(x) by Reciproot Iteration
+
+   (1)	Initial approximation
+
+	Let x0 and x1 be the leading and the trailing 32-bit words of
+	a floating point number x (in IEEE double format) respectively
+	(see section A). By performing shifs and subtracts on x0 and y0,
+	we obtain a 7.8-bit approximation of 1/sqrt(x) as follows.
+
+	    k := 0x5fe80000 - (x0>>1);
+	    y0:= k - T2[63&(k>>14)].	... y ~ 1/sqrt(x) to 7.8 bits
+
+	Here k is a 32-bit integer and T2[] is an integer array
+	containing correction terms. Now magically the floating
+	value of y (y's leading 32-bit word is y0, the value of
+	its trailing word y1 is set to zero) approximates 1/sqrt(x)
+	to almost 7.8-bit.
+
+	Value of T2:
+	static int T2[64]= {
+	0x1500,	0x2ef8,	0x4d67,	0x6b02,	0x87be,	0xa395,	0xbe7a,	0xd866,
+	0xf14a,	0x1091b,0x11fcd,0x13552,0x14999,0x15c98,0x16e34,0x17e5f,
+	0x18d03,0x19a01,0x1a545,0x1ae8a,0x1b5c4,0x1bb01,0x1bfde,0x1c28d,
+	0x1c2de,0x1c0db,0x1ba73,0x1b11c,0x1a4b5,0x1953d,0x18266,0x16be0,
+	0x1683e,0x179d8,0x18a4d,0x19992,0x1a789,0x1b445,0x1bf61,0x1c989,
+	0x1d16d,0x1d77b,0x1dddf,0x1e2ad,0x1e5bf,0x1e6e8,0x1e654,0x1e3cd,
+	0x1df2a,0x1d635,0x1cb16,0x1be2c,0x1ae4e,0x19bde,0x1868e,0x16e2e,
+	0x1527f,0x1334a,0x11051,0xe951,	0xbe01,	0x8e0d,	0x5924,	0x1edd,};
+
+    (2)	Iterative refinement
+
+	Apply Reciproot iteration three times to y and multiply the
+	result by x to get an approximation z that matches sqrt(x)
+	to about 1 ulp. To be exact, we will have
+		-1ulp < sqrt(x)-z<1.0625ulp.
+
+	... set rounding mode to Round-to-nearest
+	   y := y*(1.5-0.5*x*y*y)	... almost 15 sig. bits to 1/sqrt(x)
+	   y := y*((1.5-2^-30)+0.5*x*y*y)... about 29 sig. bits to 1/sqrt(x)
+	... special arrangement for better accuracy
+	   z := x*y			... 29 bits to sqrt(x), with z*y<1
+	   z := z + 0.5*z*(1-z*y)	... about 1 ulp to sqrt(x)
+
+	Remark 2. The constant 1.5-2^-30 is chosen to bias the error so that
+	(a) the term z*y in the final iteration is always less than 1;
+	(b) the error in the final result is biased upward so that
+		-1 ulp < sqrt(x) - z < 1.0625 ulp
+	    instead of |sqrt(x)-z|<1.03125ulp.
+
+    (3)	Final adjustment
+
+	By twiddling y's last bit it is possible to force y to be
+	correctly rounded according to the prevailing rounding mode
+	as follows. Let r and i be copies of the rounding mode and
+	inexact flag before entering the square root program. Also we
+	use the expression y+-ulp for the next representable floating
+	numbers (up and down) of y. Note that y+-ulp = either fixed
+	point y+-1, or multiply y by nextafter(1,+-inf) in chopped
+	mode.
+
+	R := RZ;		... set rounding mode to round-toward-zero
+	switch(r) {
+	    case RN:		... round-to-nearest
+	       if(x<= z*(z-ulp)...chopped) z = z - ulp; else
+	       if(x<= z*(z+ulp)...chopped) z = z; else z = z+ulp;
+	       break;
+	    case RZ:case RM:	... round-to-zero or round-to--inf
+	       R:=RP;		... reset rounding mod to round-to-+inf
+	       if(x<z*z ... rounded up) z = z - ulp; else
+	       if(x>=(z+ulp)*(z+ulp) ...rounded up) z = z+ulp;
+	       break;
+	    case RP:		... round-to-+inf
+	       if(x>(z+ulp)*(z+ulp)...chopped) z = z+2*ulp; else
+	       if(x>z*z ...chopped) z = z+ulp;
+	       break;
+	}
+
+	Remark 3. The above comparisons can be done in fixed point. For
+	example, to compare x and w=z*z chopped, it suffices to compare
+	x1 and w1 (the trailing parts of x and w), regarding them as
+	two's complement integers.
+
+	...Is z an exact square root?
+	To determine whether z is an exact square root of x, let z1 be the
+	trailing part of z, and also let x0 and x1 be the leading and
+	trailing parts of x.
+
+	If ((z1&0x03ffffff)!=0)	... not exact if trailing 26 bits of z!=0
+	    I := 1;		... Raise Inexact flag: z is not exact
+	else {
+	    j := 1 - [(x0>>20)&1]	... j = logb(x) mod 2
+	    k := z1 >> 26;		... get z's 25-th and 26-th
+					    fraction bits
+	    I := i or (k&j) or ((k&(j+j+1))!=(x1&3));
+	}
+	R:= r		... restore rounded mode
+	return sqrt(x):=z.
+
+	If multiplication is cheaper then the foregoing red tape, the
+	Inexact flag can be evaluated by
+
+	    I := i;
+	    I := (z*z!=x) or I.
+
+	Note that z*z can overwrite I; this value must be sensed if it is
+	True.
+
+	Remark 4. If z*z = x exactly, then bit 25 to bit 0 of z1 must be
+	zero.
+
+		    --------------------
+		z1: |        f2        |
+		    --------------------
+		bit 31		   bit 0
+
+	Further more, bit 27 and 26 of z1, bit 0 and 1 of x1, and the odd
+	or even of logb(x) have the following relations:
+
+	-------------------------------------------------
+	bit 27,26 of z1		bit 1,0 of x1	logb(x)
+	-------------------------------------------------
+	00			00		odd and even
+	01			01		even
+	10			10		odd
+	10			00		even
+	11			01		even
+	-------------------------------------------------
+
+    (4)	Special cases (see (4) of Section A).
+
+ */
Index: /soft/giet_vm/giet_libs/math/k_cos.c
===================================================================
--- /soft/giet_vm/giet_libs/math/k_cos.c	(revision 581)
+++ /soft/giet_vm/giet_libs/math/k_cos.c	(revision 581)
@@ -0,0 +1,84 @@
+/*
+ * ====================================================
+ * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
+ *
+ * Developed at SunPro, a Sun Microsystems, Inc. business.
+ * Permission to use, copy, modify, and distribute this
+ * software is freely granted, provided that this notice
+ * is preserved.
+ * ====================================================
+ */
+
+/* Modified for GIET-VM static OS at UPMC, France 2015.
+ */
+
+/*
+ * __kernel_cos( x,  y )
+ * kernel cos function on [-pi/4, pi/4], pi/4 ~ 0.785398164
+ * Input x is assumed to be bounded by ~pi/4 in magnitude.
+ * Input y is the tail of x.
+ *
+ * Algorithm
+ *	1. Since cos(-x) = cos(x), we need only to consider positive x.
+ *	2. if x < 2^-27 (hx<0x3e400000 0), return 1 with inexact if x!=0.
+ *	3. cos(x) is approximated by a polynomial of degree 14 on
+ *	   [0,pi/4]
+ *		  	                 4            14
+ *	   	cos(x) ~ 1 - x*x/2 + C1*x + ... + C6*x
+ *	   where the remez error is
+ *
+ * 	|              2     4     6     8     10    12     14 |     -58
+ * 	|cos(x)-(1-.5*x +C1*x +C2*x +C3*x +C4*x +C5*x  +C6*x  )| <= 2
+ * 	|    					               |
+ *
+ * 	               4     6     8     10    12     14
+ *	4. let r = C1*x +C2*x +C3*x +C4*x +C5*x  +C6*x  , then
+ *	       cos(x) = 1 - x*x/2 + r
+ *	   since cos(x+y) ~ cos(x) - sin(x)*y
+ *			  ~ cos(x) - x*y,
+ *	   a correction term is necessary in cos(x) and hence
+ *		cos(x+y) = 1 - (x*x/2 - (r - x*y))
+ *	   For better accuracy when x > 0.3, let qx = |x|/4 with
+ *	   the last 32 bits mask off, and if x > 0.78125, let qx = 0.28125.
+ *	   Then
+ *		cos(x+y) = (1-qx) - ((x*x/2-qx) - (r-x*y)).
+ *	   Note that 1-qx and (x*x/2-qx) is EXACT here, and the
+ *	   magnitude of the latter is at least a quarter of x*x/2,
+ *	   thus, reducing the rounding error in the subtraction.
+ */
+
+#include "math_private.h"
+
+static const double
+one =  1.00000000000000000000e+00, /* 0x3FF00000, 0x00000000 */
+C1  =  4.16666666666666019037e-02, /* 0x3FA55555, 0x5555554C */
+C2  = -1.38888888888741095749e-03, /* 0xBF56C16C, 0x16C15177 */
+C3  =  2.48015872894767294178e-05, /* 0x3EFA01A0, 0x19CB1590 */
+C4  = -2.75573143513906633035e-07, /* 0xBE927E4F, 0x809C52AD */
+C5  =  2.08757232129817482790e-09, /* 0x3E21EE9E, 0xBDB4B1C4 */
+C6  = -1.13596475577881948265e-11; /* 0xBDA8FAE9, 0xBE8838D4 */
+
+double __kernel_cos(double x, double y)
+{
+	double a,hz,z,r,qx;
+	int32_t ix;
+	GET_HIGH_WORD(ix,x);
+	ix &= 0x7fffffff;			/* ix = |x|'s high word*/
+	if(ix<0x3e400000) {			/* if x < 2**27 */
+	    if(((int)x)==0) return one;		/* generate inexact */
+	}
+	z  = x*x;
+	r  = z*(C1+z*(C2+z*(C3+z*(C4+z*(C5+z*C6)))));
+	if(ix < 0x3FD33333) 			/* if |x| < 0.3 */
+	    return one - (0.5*z - (z*r - x*y));
+	else {
+	    if(ix > 0x3fe90000) {		/* x > 0.78125 */
+		qx = 0.28125;
+	    } else {
+	        INSERT_WORDS(qx,ix-0x00200000,0);	/* x/4 */
+	    }
+	    hz = 0.5*z-qx;
+	    a  = one-qx;
+	    return a - (hz - (z*r-x*y));
+	}
+}
Index: /soft/giet_vm/giet_libs/math/k_rem_pio2.c
===================================================================
--- /soft/giet_vm/giet_libs/math/k_rem_pio2.c	(revision 581)
+++ /soft/giet_vm/giet_libs/math/k_rem_pio2.c	(revision 581)
@@ -0,0 +1,301 @@
+/*
+ * ====================================================
+ * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
+ *
+ * Developed at SunPro, a Sun Microsystems, Inc. business.
+ * Permission to use, copy, modify, and distribute this
+ * software is freely granted, provided that this notice
+ * is preserved.
+ * ====================================================
+ */
+
+/* Modified for GIET-VM static OS at UPMC, France 2015.
+ */
+
+/*
+ * __kernel_rem_pio2(x,y,e0,nx,prec,ipio2)
+ * double x[],y[]; int e0,nx,prec; int ipio2[];
+ *
+ * __kernel_rem_pio2 return the last three digits of N with
+ *		y = x - N*pi/2
+ * so that |y| < pi/2.
+ *
+ * The method is to compute the integer (mod 8) and fraction parts of
+ * (2/pi)*x without doing the full multiplication. In general we
+ * skip the part of the product that are known to be a huge integer (
+ * more accurately, = 0 mod 8 ). Thus the number of operations are
+ * independent of the exponent of the input.
+ *
+ * (2/pi) is represented by an array of 24-bit integers in ipio2[].
+ *
+ * Input parameters:
+ * 	x[]	The input value (must be positive) is broken into nx
+ *		pieces of 24-bit integers in double precision format.
+ *		x[i] will be the i-th 24 bit of x. The scaled exponent
+ *		of x[0] is given in input parameter e0 (i.e., x[0]*2^e0
+ *		match x's up to 24 bits.
+ *
+ *		Example of breaking a double positive z into x[0]+x[1]+x[2]:
+ *			e0 = ilogb(z)-23
+ *			z  = scalbn(z,-e0)
+ *		for i = 0,1,2
+ *			x[i] = floor(z)
+ *			z    = (z-x[i])*2**24
+ *
+ *
+ *	y[]	ouput result in an array of double precision numbers.
+ *		The dimension of y[] is:
+ *			24-bit  precision	1
+ *			53-bit  precision	2
+ *			64-bit  precision	2
+ *			113-bit precision	3
+ *		The actual value is the sum of them. Thus for 113-bit
+ *		precison, one may have to do something like:
+ *
+ *		long double t,w,r_head, r_tail;
+ *		t = (long double)y[2] + (long double)y[1];
+ *		w = (long double)y[0];
+ *		r_head = t+w;
+ *		r_tail = w - (r_head - t);
+ *
+ *	e0	The exponent of x[0]
+ *
+ *	nx	dimension of x[]
+ *
+ *  	prec	an integer indicating the precision:
+ *			0	24  bits (single)
+ *			1	53  bits (double)
+ *			2	64  bits (extended)
+ *			3	113 bits (quad)
+ *
+ *	ipio2[]
+ *		integer array, contains the (24*i)-th to (24*i+23)-th
+ *		bit of 2/pi after binary point. The corresponding
+ *		floating value is
+ *
+ *			ipio2[i] * 2^(-24(i+1)).
+ *
+ * External function:
+ *	double scalbn(), floor();
+ *
+ *
+ * Here is the description of some local variables:
+ *
+ * 	jk	jk+1 is the initial number of terms of ipio2[] needed
+ *		in the computation. The recommended value is 2,3,4,
+ *		6 for single, double, extended,and quad.
+ *
+ * 	jz	local integer variable indicating the number of
+ *		terms of ipio2[] used.
+ *
+ *	jx	nx - 1
+ *
+ *	jv	index for pointing to the suitable ipio2[] for the
+ *		computation. In general, we want
+ *			( 2^e0*x[0] * ipio2[jv-1]*2^(-24jv) )/8
+ *		is an integer. Thus
+ *			e0-3-24*jv >= 0 or (e0-3)/24 >= jv
+ *		Hence jv = max(0,(e0-3)/24).
+ *
+ *	jp	jp+1 is the number of terms in PIo2[] needed, jp = jk.
+ *
+ * 	q[]	double array with integral value, representing the
+ *		24-bits chunk of the product of x and 2/pi.
+ *
+ *	q0	the corresponding exponent of q[0]. Note that the
+ *		exponent for q[i] would be q0-24*i.
+ *
+ *	PIo2[]	double precision array, obtained by cutting pi/2
+ *		into 24 bits chunks.
+ *
+ *	f[]	ipio2[] in floating point
+ *
+ *	iq[]	integer array by breaking up q[] in 24-bits chunk.
+ *
+ *	fq[]	final product of x*(2/pi) in fq[0],..,fq[jk]
+ *
+ *	ih	integer. If >0 it indicates q[] is >= 0.5, hence
+ *		it also indicates the *sign* of the result.
+ *
+ */
+
+
+/*
+ * Constants:
+ * The hexadecimal values are the intended ones for the following
+ * constants. The decimal values may be used, provided that the
+ * compiler will convert from decimal to binary accurately enough
+ * to produce the hexadecimal values shown.
+ */
+
+#include "../math.h"
+#include "math_private.h"
+
+static const int init_jk[] = {2,3,4,6}; /* initial value for jk */
+
+static const double PIo2[] = {
+  1.57079625129699707031e+00, /* 0x3FF921FB, 0x40000000 */
+  7.54978941586159635335e-08, /* 0x3E74442D, 0x00000000 */
+  5.39030252995776476554e-15, /* 0x3CF84698, 0x80000000 */
+  3.28200341580791294123e-22, /* 0x3B78CC51, 0x60000000 */
+  1.27065575308067607349e-29, /* 0x39F01B83, 0x80000000 */
+  1.22933308981111328932e-36, /* 0x387A2520, 0x40000000 */
+  2.73370053816464559624e-44, /* 0x36E38222, 0x80000000 */
+  2.16741683877804819444e-51, /* 0x3569F31D, 0x00000000 */
+};
+
+static const double
+zero   = 0.0,
+one    = 1.0,
+two24   =  1.67772160000000000000e+07, /* 0x41700000, 0x00000000 */
+twon24  =  5.96046447753906250000e-08; /* 0x3E700000, 0x00000000 */
+
+int __kernel_rem_pio2(double *x, double *y, int e0, int nx, int prec, const int32_t *ipio2)
+{
+	int32_t jz,jx,jv,jp,jk,carry,n,iq[20],i,j,k,m,q0,ih;
+	double z,fw,f[20],fq[20],q[20];
+
+    /* initialize jk*/
+	jk = init_jk[prec];
+	jp = jk;
+
+    /* determine jx,jv,q0, note that 3>q0 */
+	jx =  nx-1;
+	jv = (e0-3)/24; if(jv<0) jv=0;
+	q0 =  e0-24*(jv+1);
+
+    /* set up f[0] to f[jx+jk] where f[jx+jk] = ipio2[jv+jk] */
+	j = jv-jx; m = jx+jk;
+	for(i=0;i<=m;i++,j++) f[i] = (j<0)? zero : (double) ipio2[j];
+
+    /* compute q[0],q[1],...q[jk] */
+	for (i=0;i<=jk;i++) {
+	    for(j=0,fw=0.0;j<=jx;j++) fw += x[j]*f[jx+i-j]; q[i] = fw;
+	}
+
+	jz = jk;
+recompute:
+    /* distill q[] into iq[] reversingly */
+	for(i=0,j=jz,z=q[jz];j>0;i++,j--) {
+	    fw    =  (double)((int32_t)(twon24* z));
+	    iq[i] =  (int32_t)(z-two24*fw);
+	    z     =  q[j-1]+fw;
+	}
+
+    /* compute n */
+	z  = scalbn(z,q0);		/* actual value of z */
+	z -= 8.0*floor(z*0.125);		/* trim off integer >= 8 */
+	n  = (int32_t) z;
+	z -= (double)n;
+	ih = 0;
+	if(q0>0) {	/* need iq[jz-1] to determine n */
+	    i  = (iq[jz-1]>>(24-q0)); n += i;
+	    iq[jz-1] -= i<<(24-q0);
+	    ih = iq[jz-1]>>(23-q0);
+	}
+	else if(q0==0) ih = iq[jz-1]>>23;
+	else if(z>=0.5) ih=2;
+
+	if(ih>0) {	/* q > 0.5 */
+	    n += 1; carry = 0;
+	    for(i=0;i<jz ;i++) {	/* compute 1-q */
+		j = iq[i];
+		if(carry==0) {
+		    if(j!=0) {
+			carry = 1; iq[i] = 0x1000000- j;
+		    }
+		} else  iq[i] = 0xffffff - j;
+	    }
+	    if(q0>0) {		/* rare case: chance is 1 in 12 */
+	        switch(q0) {
+	        case 1:
+	    	   iq[jz-1] &= 0x7fffff; break;
+	    	case 2:
+	    	   iq[jz-1] &= 0x3fffff; break;
+	        }
+	    }
+	    if(ih==2) {
+		z = one - z;
+		if(carry!=0) z -= scalbn(one,q0);
+	    }
+	}
+
+    /* check if recomputation is needed */
+	if(z==zero) {
+	    j = 0;
+	    for (i=jz-1;i>=jk;i--) j |= iq[i];
+	    if(j==0) { /* need recomputation */
+		for(k=1;iq[jk-k]==0;k++);   /* k = no. of terms needed */
+
+		for(i=jz+1;i<=jz+k;i++) {   /* add q[jz+1] to q[jz+k] */
+		    f[jx+i] = (double) ipio2[jv+i];
+		    for(j=0,fw=0.0;j<=jx;j++) fw += x[j]*f[jx+i-j];
+		    q[i] = fw;
+		}
+		jz += k;
+		goto recompute;
+	    }
+	}
+
+    /* chop off zero terms */
+	if(z==0.0) {
+	    jz -= 1; q0 -= 24;
+	    while(iq[jz]==0) { jz--; q0-=24;}
+	} else { /* break z into 24-bit if necessary */
+	    z = scalbn(z,-q0);
+	    if(z>=two24) {
+		fw = (double)((int32_t)(twon24*z));
+		iq[jz] = (int32_t)(z-two24*fw);
+		jz += 1; q0 += 24;
+		iq[jz] = (int32_t) fw;
+	    } else iq[jz] = (int32_t) z ;
+	}
+
+    /* convert integer "bit" chunk to floating-point value */
+	fw = scalbn(one,q0);
+	for(i=jz;i>=0;i--) {
+	    q[i] = fw*(double)iq[i]; fw*=twon24;
+	}
+
+    /* compute PIo2[0,...,jp]*q[jz,...,0] */
+	for(i=jz;i>=0;i--) {
+	    for(fw=0.0,k=0;k<=jp&&k<=jz-i;k++) fw += PIo2[k]*q[i+k];
+	    fq[jz-i] = fw;
+	}
+
+    /* compress fq[] into y[] */
+	switch(prec) {
+	    case 0:
+		fw = 0.0;
+		for (i=jz;i>=0;i--) fw += fq[i];
+		y[0] = (ih==0)? fw: -fw;
+		break;
+	    case 1:
+	    case 2:
+		fw = 0.0;
+		for (i=jz;i>=0;i--) fw += fq[i];
+		y[0] = (ih==0)? fw: -fw;
+		fw = fq[0]-fw;
+		for (i=1;i<=jz;i++) fw += fq[i];
+		y[1] = (ih==0)? fw: -fw;
+		break;
+	    case 3:	/* painful */
+		for (i=jz;i>0;i--) {
+		    fw      = fq[i-1]+fq[i];
+		    fq[i]  += fq[i-1]-fw;
+		    fq[i-1] = fw;
+		}
+		for (i=jz;i>1;i--) {
+		    fw      = fq[i-1]+fq[i];
+		    fq[i]  += fq[i-1]-fw;
+		    fq[i-1] = fw;
+		}
+		for (fw=0.0,i=jz;i>=2;i--) fw += fq[i];
+		if(ih==0) {
+		    y[0] =  fq[0]; y[1] =  fq[1]; y[2] =  fw;
+		} else {
+		    y[0] = -fq[0]; y[1] = -fq[1]; y[2] = -fw;
+		}
+	}
+	return n&7;
+}
Index: /soft/giet_vm/giet_libs/math/k_sin.c
===================================================================
--- /soft/giet_vm/giet_libs/math/k_sin.c	(revision 581)
+++ /soft/giet_vm/giet_libs/math/k_sin.c	(revision 581)
@@ -0,0 +1,67 @@
+/*
+ * ====================================================
+ * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
+ *
+ * Developed at SunPro, a Sun Microsystems, Inc. business.
+ * Permission to use, copy, modify, and distribute this
+ * software is freely granted, provided that this notice
+ * is preserved.
+ * ====================================================
+ */
+
+/* Modified for GIET-VM static OS at UPMC, France 2015.
+ */
+
+/* __kernel_sin( x, y, iy)
+ * kernel sin function on [-pi/4, pi/4], pi/4 ~ 0.7854
+ * Input x is assumed to be bounded by ~pi/4 in magnitude.
+ * Input y is the tail of x.
+ * Input iy indicates whether y is 0. (if iy=0, y assume to be 0).
+ *
+ * Algorithm
+ *	1. Since sin(-x) = -sin(x), we need only to consider positive x.
+ *	2. if x < 2^-27 (hx<0x3e400000 0), return x with inexact if x!=0.
+ *	3. sin(x) is approximated by a polynomial of degree 13 on
+ *	   [0,pi/4]
+ *		  	         3            13
+ *	   	sin(x) ~ x + S1*x + ... + S6*x
+ *	   where
+ *
+ * 	|sin(x)         2     4     6     8     10     12  |     -58
+ * 	|----- - (1+S1*x +S2*x +S3*x +S4*x +S5*x  +S6*x   )| <= 2
+ * 	|  x 					           |
+ *
+ *	4. sin(x+y) = sin(x) + sin'(x')*y
+ *		    ~ sin(x) + (1-x*x/2)*y
+ *	   For better accuracy, let
+ *		     3      2      2      2      2
+ *		r = x *(S2+x *(S3+x *(S4+x *(S5+x *S6))))
+ *	   then                   3    2
+ *		sin(x) = x + (S1*x + (x *(r-y/2)+y))
+ */
+
+#include "math_private.h"
+
+static const double
+half =  5.00000000000000000000e-01, /* 0x3FE00000, 0x00000000 */
+S1  = -1.66666666666666324348e-01, /* 0xBFC55555, 0x55555549 */
+S2  =  8.33333333332248946124e-03, /* 0x3F811111, 0x1110F8A6 */
+S3  = -1.98412698298579493134e-04, /* 0xBF2A01A0, 0x19C161D5 */
+S4  =  2.75573137070700676789e-06, /* 0x3EC71DE3, 0x57B1FE7D */
+S5  = -2.50507602534068634195e-08, /* 0xBE5AE5E6, 0x8A2B9CEB */
+S6  =  1.58969099521155010221e-10; /* 0x3DE5D93A, 0x5ACFD57C */
+
+double __kernel_sin(double x, double y, int iy)
+{
+	double z,r,v;
+	int32_t ix;
+	GET_HIGH_WORD(ix,x);
+	ix &= 0x7fffffff;			/* high word of x */
+	if(ix<0x3e400000)			/* |x| < 2**-27 */
+	   {if((int)x==0) return x;}		/* generate inexact */
+	z	=  x*x;
+	v	=  z*x;
+	r	=  S2+z*(S3+z*(S4+z*(S5+z*S6)));
+	if(iy==0) return x+v*(S1+z*r);
+	else      return x-((z*(half*y-v*r)-y)-v*S1);
+}
Index: /soft/giet_vm/giet_libs/math/math_private.h
===================================================================
--- /soft/giet_vm/giet_libs/math/math_private.h	(revision 581)
+++ /soft/giet_vm/giet_libs/math/math_private.h	(revision 581)
@@ -0,0 +1,143 @@
+/*
+ * ====================================================
+ * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
+ *
+ * Developed at SunPro, a Sun Microsystems, Inc. business.
+ * Permission to use, copy, modify, and distribute this
+ * software is freely granted, provided that this notice
+ * is preserved.
+ * ====================================================
+ */
+
+/* Modified for GIET-VM static OS at UPMC, France 2015.
+ */
+
+#ifndef _MATH_PRIVATE_H_
+#define _MATH_PRIVATE_H_
+
+#include <stdint.h>
+
+typedef uint32_t u_int32_t;
+
+
+/* The original fdlibm code used statements like:
+	n0 = ((*(int*)&one)>>29)^1;		* index of high word *
+	ix0 = *(n0+(int*)&x);			* high word of x *
+	ix1 = *((1-n0)+(int*)&x);		* low word of x *
+   to dig two 32 bit words out of the 64 bit IEEE floating point
+   value.  That is non-ANSI, and, moreover, the gcc instruction
+   scheduler gets it wrong.  We instead use the following macros.
+   Unlike the original code, we determine the endianness at compile
+   time, not at run time; I don't see much benefit to selecting
+   endianness at run time.  */
+
+/* A union which permits us to convert between a double and two 32 bit
+   ints.  */
+
+/*
+ * Math on arm is special (read: stupid):
+ * For FPA, float words are always big-endian.
+ * For VFP, float words follow the memory system mode.
+ * For Maverick, float words are always little-endian.
+ */
+
+
+/*
+#if (__BYTE_ORDER == __BIG_ENDIAN)
+
+
+typedef union
+{
+  double value;
+  struct
+  {
+    u_int32_t msw;
+    u_int32_t lsw;
+  } parts;
+} ieee_double_shape_type;
+
+#else
+*/
+
+typedef union
+{
+  double value;
+  struct
+  {
+    u_int32_t lsw;
+    u_int32_t msw;
+  } parts;
+} ieee_double_shape_type;
+
+//#endif
+
+
+/* Get two 32 bit ints from a double.  */
+
+#define EXTRACT_WORDS(ix0,ix1,d)				\
+do {								\
+  ieee_double_shape_type ew_u;					\
+  ew_u.value = (d);						\
+  (ix0) = ew_u.parts.msw;					\
+  (ix1) = ew_u.parts.lsw;					\
+} while (0)
+
+/* Get the more significant 32 bit int from a double.  */
+
+#define GET_HIGH_WORD(i,d)					\
+do {								\
+  ieee_double_shape_type gh_u;					\
+  gh_u.value = (d);						\
+  (i) = gh_u.parts.msw;						\
+} while (0)
+
+/* Get the less significant 32 bit int from a double.  */
+
+#define GET_LOW_WORD(i,d)					\
+do {								\
+  ieee_double_shape_type gl_u;					\
+  gl_u.value = (d);						\
+  (i) = gl_u.parts.lsw;						\
+} while (0)
+
+/* Set a double from two 32 bit ints.  */
+
+#define INSERT_WORDS(d,ix0,ix1)					\
+do {								\
+  ieee_double_shape_type iw_u;					\
+  iw_u.parts.msw = (ix0);					\
+  iw_u.parts.lsw = (ix1);					\
+  (d) = iw_u.value;						\
+} while (0)
+
+/* Set the more significant 32 bits of a double from an int.  */
+
+#define SET_HIGH_WORD(d,v)					\
+do {								\
+  ieee_double_shape_type sh_u;					\
+  sh_u.value = (d);						\
+  sh_u.parts.msw = (v);						\
+  (d) = sh_u.value;						\
+} while (0)
+
+/* Set the less significant 32 bits of a double from an int.  */
+
+#define SET_LOW_WORD(d,v)					\
+do {								\
+  ieee_double_shape_type sl_u;					\
+  sl_u.value = (d);						\
+  sl_u.parts.lsw = (v);						\
+  (d) = sl_u.value;						\
+} while (0)
+
+int __ieee754_rem_pio2 (double,double*);
+double __ieee754_pow(double x, double y);
+//double __ieee754_sqrt(double x);
+
+int __kernel_rem_pio2(double *x, double *y, int e0, int nx, int prec, const int32_t *ipio2);
+double __kernel_sin (double,double,int);
+double __kernel_cos (double,double);
+
+
+#endif
+
Index: /soft/giet_vm/giet_libs/math/s_copysign.c
===================================================================
--- /soft/giet_vm/giet_libs/math/s_copysign.c	(revision 581)
+++ /soft/giet_vm/giet_libs/math/s_copysign.c	(revision 581)
@@ -0,0 +1,32 @@
+/*
+ * ====================================================
+ * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
+ *
+ * Developed at SunPro, a Sun Microsystems, Inc. business.
+ * Permission to use, copy, modify, and distribute this
+ * software is freely granted, provided that this notice
+ * is preserved.
+ * ====================================================
+ */
+
+/* Modified for GIET-VM static OS at UPMC, France 2015.
+ */
+
+/*
+ * copysign(double x, double y)
+ * copysign(x,y) returns a value with the magnitude of x and
+ * with the sign bit of y.
+ */
+
+#include "../math.h"
+#include "math_private.h"
+
+double copysign(double x, double y)
+{
+	u_int32_t hx,hy;
+	GET_HIGH_WORD(hx,x);
+	GET_HIGH_WORD(hy,y);
+	SET_HIGH_WORD(x,(hx&0x7fffffff)|(hy&0x80000000));
+        return x;
+}
+
Index: /soft/giet_vm/giet_libs/math/s_fabs.c
===================================================================
--- /soft/giet_vm/giet_libs/math/s_fabs.c	(revision 581)
+++ /soft/giet_vm/giet_libs/math/s_fabs.c	(revision 581)
@@ -0,0 +1,29 @@
+/*
+ * ====================================================
+ * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
+ *
+ * Developed at SunPro, a Sun Microsystems, Inc. business.
+ * Permission to use, copy, modify, and distribute this
+ * software is freely granted, provided that this notice
+ * is preserved.
+ * ====================================================
+ */
+
+/* Modified for GIET-VM static OS at UPMC, France 2015.
+ */
+
+/*
+ * fabs(x) returns the absolute value of x.
+ */
+
+#include "../math.h"
+#include "math_private.h"
+
+double fabs(double x)
+{
+	u_int32_t high;
+	GET_HIGH_WORD(high,x);
+	SET_HIGH_WORD(x,high&0x7fffffff);
+        return x;
+}
+
Index: /soft/giet_vm/giet_libs/math/s_finite.c
===================================================================
--- /soft/giet_vm/giet_libs/math/s_finite.c	(revision 581)
+++ /soft/giet_vm/giet_libs/math/s_finite.c	(revision 581)
@@ -0,0 +1,32 @@
+/*
+ * ====================================================
+ * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
+ *
+ * Developed at SunPro, a Sun Microsystems, Inc. business.
+ * Permission to use, copy, modify, and distribute this
+ * software is freely granted, provided that this notice
+ * is preserved.
+ * ====================================================
+ */
+
+/* Modified for GIET-VM static OS at UPMC, France 2015.
+ */
+
+/*
+ * finite(x) returns 1 is x is finite, else 0;
+ * no branching!
+ */
+
+#include "../math.h"
+#include "math_private.h"
+
+int isfinite(double x)
+{
+	u_int32_t hx;
+
+	GET_HIGH_WORD(hx, x);
+	/* Finite numbers have at least one zero bit in exponent. */
+	/* All other numbers will result in 0xffffffff after OR: */
+	return (hx | 0x800fffff) != 0xffffffff;
+}
+
Index: /soft/giet_vm/giet_libs/math/s_floor.c
===================================================================
--- /soft/giet_vm/giet_libs/math/s_floor.c	(revision 581)
+++ /soft/giet_vm/giet_libs/math/s_floor.c	(revision 581)
@@ -0,0 +1,70 @@
+/*
+ * ====================================================
+ * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
+ *
+ * Developed at SunPro, a Sun Microsystems, Inc. business.
+ * Permission to use, copy, modify, and distribute this
+ * software is freely granted, provided that this notice
+ * is preserved.
+ * ====================================================
+ */
+
+/* Modified for GIET-VM static OS at UPMC, France 2015.
+ */
+
+/*
+ * floor(x)
+ * Return x rounded toward -inf to integral value
+ * Method:
+ *	Bit twiddling.
+ * Exception:
+ *	Inexact flag raised if x not equal to floor(x).
+ */
+
+#include "math_private.h"
+
+static const double huge = 1.0e300;
+
+double floor(double x)
+{
+	int32_t i0,i1,j0;
+	u_int32_t i,j;
+	EXTRACT_WORDS(i0,i1,x);
+	j0 = ((i0>>20)&0x7ff)-0x3ff;
+	if(j0<20) {
+	    if(j0<0) { 	/* raise inexact if x != 0 */
+		if(huge+x>0.0) {/* return 0*sign(x) if |x|<1 */
+		    if(i0>=0) {i0=i1=0;}
+		    else if(((i0&0x7fffffff)|i1)!=0)
+			{ i0=0xbff00000;i1=0;}
+		}
+	    } else {
+		i = (0x000fffff)>>j0;
+		if(((i0&i)|i1)==0) return x; /* x is integral */
+		if(huge+x>0.0) {	/* raise inexact flag */
+		    if(i0<0) i0 += (0x00100000)>>j0;
+		    i0 &= (~i); i1=0;
+		}
+	    }
+	} else if (j0>51) {
+	    if(j0==0x400) return x+x;	/* inf or NaN */
+	    else return x;		/* x is integral */
+	} else {
+	    i = ((u_int32_t)(0xffffffff))>>(j0-20);
+	    if((i1&i)==0) return x;	/* x is integral */
+	    if(huge+x>0.0) { 		/* raise inexact flag */
+		if(i0<0) {
+		    if(j0==20) i0+=1;
+		    else {
+			j = i1+(1<<(52-j0));
+			if(j<i1) i0 +=1 ; 	/* got a carry */
+			i1=j;
+		    }
+		}
+		i1 &= (~i);
+	    }
+	}
+	INSERT_WORDS(x,i0,i1);
+	return x;
+}
+
Index: /soft/giet_vm/giet_libs/math/s_isnan.c
===================================================================
--- /soft/giet_vm/giet_libs/math/s_isnan.c	(revision 581)
+++ /soft/giet_vm/giet_libs/math/s_isnan.c	(revision 581)
@@ -0,0 +1,31 @@
+/*
+ * ====================================================
+ * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
+ *
+ * Developed at SunPro, a Sun Microsystems, Inc. business.
+ * Permission to use, copy, modify, and distribute this
+ * software is freely granted, provided that this notice
+ * is preserved.
+ * ====================================================
+ */
+
+/* Modified for GIET-VM static OS at UPMC, France 2015.
+ */
+
+/*
+ * isnan(x) returns 1 is x is nan, else 0;
+ * no branching!
+ */
+
+#include "../math.h"
+#include "math_private.h"
+
+int isnan(double x)
+{
+	int32_t hx,lx;
+	EXTRACT_WORDS(hx,lx,x);
+	hx &= 0x7fffffff;
+	hx |= (u_int32_t)(lx|(-lx))>>31;
+	hx = 0x7ff00000 - hx;
+	return (int)(((u_int32_t)hx)>>31);
+}
Index: /soft/giet_vm/giet_libs/math/s_rint.c
===================================================================
--- /soft/giet_vm/giet_libs/math/s_rint.c	(revision 581)
+++ /soft/giet_vm/giet_libs/math/s_rint.c	(revision 581)
@@ -0,0 +1,91 @@
+/*
+ * ====================================================
+ * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
+ *
+ * Developed at SunPro, a Sun Microsystems, Inc. business.
+ * Permission to use, copy, modify, and distribute this
+ * software is freely granted, provided that this notice
+ * is preserved.
+ * ====================================================
+ */
+
+/* Modified for GIET-VM static OS at UPMC, France 2015.
+ */
+
+/*
+ * rint(x)
+ * Return x rounded to integral value according to the prevailing
+ * rounding mode.
+ * Method:
+ *	Using floating addition.
+ * Exception:
+ *	Inexact flag raised if x not equal to rint(x).
+ */
+
+#include "../math.h"
+#include "math_private.h"
+
+static const double
+TWO52[2]={
+  4.50359962737049600000e+15, /* 0x43300000, 0x00000000 */
+ -4.50359962737049600000e+15, /* 0xC3300000, 0x00000000 */
+};
+
+double rint(double x)
+{
+	int32_t i0, j0, sx;
+	u_int32_t i,i1;
+	double t;
+	/* We use w = x + 2^52; t = w - 2^52; trick to round x to integer.
+	 * This trick requires that compiler does not optimize it
+	 * by keeping intermediate result w in a register wider than double.
+	 * Declaring w volatile assures that value gets truncated to double
+	 * (unfortunately, it also forces store+load):
+	 */
+	volatile double w;
+
+	EXTRACT_WORDS(i0,i1,x);
+	/* Unbiased exponent */
+	j0 = ((((u_int32_t)i0) >> 20)&0x7ff)-0x3ff;
+
+	if (j0 > 51) {
+		//Why bother? Just returning x works too
+		//if (j0 == 0x400)  /* inf or NaN */
+		//	return x+x;
+		return x;  /* x is integral */
+	}
+
+	/* Sign */
+	sx = ((u_int32_t)i0) >> 31;
+
+	if (j0<20) {
+	    if (j0<0) { /* |x| < 1 */
+		if (((i0&0x7fffffff)|i1)==0) return x;
+		i1 |= (i0&0x0fffff);
+		i0 &= 0xfffe0000;
+		i0 |= ((i1|-i1)>>12)&0x80000;
+		SET_HIGH_WORD(x,i0);
+		w = TWO52[sx]+x;
+		t = w-TWO52[sx];
+		GET_HIGH_WORD(i0,t);
+		SET_HIGH_WORD(t,(i0&0x7fffffff)|(sx<<31));
+		return t;
+	    } else {
+		i = (0x000fffff)>>j0;
+		if (((i0&i)|i1)==0) return x; /* x is integral */
+		i>>=1;
+		if (((i0&i)|i1)!=0) {
+		    if (j0==19) i1 = 0x40000000;
+		    else i0 = (i0&(~i))|((0x20000)>>j0);
+		}
+	    }
+	} else {
+	    i = ((u_int32_t)(0xffffffff))>>(j0-20);
+	    if ((i1&i)==0) return x;	/* x is integral */
+	    i>>=1;
+	    if ((i1&i)!=0) i1 = (i1&(~i))|((0x40000000)>>(j0-20));
+	}
+	INSERT_WORDS(x,i0,i1);
+	w = TWO52[sx]+x;
+	return w-TWO52[sx];
+}
Index: /soft/giet_vm/giet_libs/math/s_scalbn.c
===================================================================
--- /soft/giet_vm/giet_libs/math/s_scalbn.c	(revision 581)
+++ /soft/giet_vm/giet_libs/math/s_scalbn.c	(revision 581)
@@ -0,0 +1,70 @@
+/*
+ * ====================================================
+ * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
+ *
+ * Developed at SunPro, a Sun Microsystems, Inc. business.
+ * Permission to use, copy, modify, and distribute this
+ * software is freely granted, provided that this notice
+ * is preserved.
+ * ====================================================
+ */
+
+/* Modified for GIET-VM static OS at UPMC, France 2015.
+ */
+
+/*
+ * scalbln(double x, long n)
+ * scalbln(x,n) returns x * 2**n computed by exponent
+ * manipulation rather than by actually performing an
+ * exponentiation or a multiplication.
+ */
+
+#include "../math.h"
+#include "math_private.h"
+#include <limits.h>
+
+static const double
+two54  = 1.80143985094819840000e+16, /* 0x43500000, 0x00000000 */
+twom54 = 5.55111512312578270212e-17, /* 0x3C900000, 0x00000000 */
+huge   = 1.0e+300,
+tiny   = 1.0e-300;
+
+double scalbln(double x, long n)
+{
+	int32_t k, hx, lx;
+
+	EXTRACT_WORDS(hx, lx, x);
+	k = (hx & 0x7ff00000) >> 20; /* extract exponent */
+	if (k == 0) { /* 0 or subnormal x */
+		if ((lx | (hx & 0x7fffffff)) == 0)
+			return x; /* +-0 */
+		x *= two54;
+		GET_HIGH_WORD(hx, x);
+		k = ((hx & 0x7ff00000) >> 20) - 54;
+	}
+	if (k == 0x7ff)
+		return x + x; /* NaN or Inf */
+	k = k + n;
+	if (k > 0x7fe)
+		return huge * copysign(huge, x); /* overflow */
+	if (n < -50000)
+		return tiny * copysign(tiny, x); /* underflow */
+	if (k > 0) { /* normal result */
+		SET_HIGH_WORD(x, (hx & 0x800fffff) | (k << 20));
+		return x;
+	}
+	if (k <= -54) {
+		if (n > 50000) /* in case integer overflow in n+k */
+			return huge * copysign(huge, x); /* overflow */
+		return tiny * copysign(tiny, x); /* underflow */
+	}
+	k += 54; /* subnormal result */
+	SET_HIGH_WORD(x, (hx & 0x800fffff) | (k << 20));
+	return x * twom54;
+}
+
+double scalbn(double x, int n)
+{
+	return scalbln(x, n);
+}
+
Index: /soft/giet_vm/giet_libs/math/s_sin.c
===================================================================
--- /soft/giet_vm/giet_libs/math/s_sin.c	(revision 581)
+++ /soft/giet_vm/giet_libs/math/s_sin.c	(revision 581)
@@ -0,0 +1,75 @@
+/*
+ * ====================================================
+ * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
+ *
+ * Developed at SunPro, a Sun Microsystems, Inc. business.
+ * Permission to use, copy, modify, and distribute this
+ * software is freely granted, provided that this notice
+ * is preserved.
+ * ====================================================
+ */
+
+/* Modified for GIET-VM static OS at UPMC, France 2015.
+ */
+
+/* sin(x)
+ * Return sine function of x.
+ *
+ * kernel function:
+ *	__kernel_sin		... sine function on [-pi/4,pi/4]
+ *	__kernel_cos		... cose function on [-pi/4,pi/4]
+ *	__ieee754_rem_pio2	... argument reduction routine
+ *
+ * Method.
+ *      Let S,C and T denote the sin, cos and tan respectively on
+ *	[-PI/4, +PI/4]. Reduce the argument x to y1+y2 = x-k*pi/2
+ *	in [-pi/4 , +pi/4], and let n = k mod 4.
+ *	We have
+ *
+ *          n        sin(x)      cos(x)        tan(x)
+ *     ----------------------------------------------------------
+ *	    0	       S	   C		 T
+ *	    1	       C	  -S		-1/T
+ *	    2	      -S	  -C		 T
+ *	    3	      -C	   S		-1/T
+ *     ----------------------------------------------------------
+ *
+ * Special cases:
+ *      Let trig be any of sin, cos, or tan.
+ *      trig(+-INF)  is NaN, with signals;
+ *      trig(NaN)    is that NaN;
+ *
+ * Accuracy:
+ *	TRIG(x) returns trig(x) nearly rounded
+ */
+
+#include "math_private.h"
+
+double sin(double x)
+{
+	double y[2],z=0.0;
+	int32_t n, ix;
+
+    /* High word of x. */
+	GET_HIGH_WORD(ix,x);
+
+    /* |x| ~< pi/4 */
+	ix &= 0x7fffffff;
+	if(ix <= 0x3fe921fb) return __kernel_sin(x,z,0);
+
+    /* sin(Inf or NaN) is NaN */
+	else if (ix>=0x7ff00000) return x-x;
+
+    /* argument reduction needed */
+	else {
+	    n = __ieee754_rem_pio2(x,y);
+	    switch(n&3) {
+		case 0: return  __kernel_sin(y[0],y[1],1);
+		case 1: return  __kernel_cos(y[0],y[1]);
+		case 2: return -__kernel_sin(y[0],y[1],1);
+		default:
+			return -__kernel_cos(y[0],y[1]);
+	    }
+	}
+}
+
Index: /soft/giet_vm/giet_libs/math/sqrt.c
===================================================================
--- /soft/giet_vm/giet_libs/math/sqrt.c	(revision 581)
+++ /soft/giet_vm/giet_libs/math/sqrt.c	(revision 581)
@@ -0,0 +1,8 @@
+
+double sqrt(double x)
+{
+  double z;
+  __asm__ ("sqrt.d %0,%1" : "=f" (z) : "f" (x));
+  return z;
+}
+
Index: /soft/giet_vm/giet_libs/stdio.c
===================================================================
--- /soft/giet_vm/giet_libs/stdio.c	(revision 580)
+++ /soft/giet_vm/giet_libs/stdio.c	(revision 581)
@@ -375,5 +375,5 @@
                 
                 vald -= (double)intp;
-                decp = (unsigned int)(vald * 100000000);
+                decp = (unsigned int)(vald * 1000000000);
                 
                 for(i = 0; i < 10; i++) 
Index: /soft/giet_vm/giet_libs/user_sqt_lock.c
===================================================================
--- /soft/giet_vm/giet_libs/user_sqt_lock.c	(revision 581)
+++ /soft/giet_vm/giet_libs/user_sqt_lock.c	(revision 581)
@@ -0,0 +1,283 @@
+
+#include "stdio.h"
+#include "malloc.h"
+#include "giet_config.h"
+#include "user_lock.h"
+#include "user_sqt_lock.h"
+
+static 
+void sqt_lock_build( sqt_lock_t*      lock,      // pointer on the SQT lock
+                      unsigned int     x,         // node X coordinate
+                      unsigned int     y,         // node Y coordinate
+                      unsigned int     level,     // node level
+                      sqt_lock_node_t* parent,    // pointer on parent node
+                      unsigned int     xmax,      // SQT X size
+                      unsigned int     ymax )     // SQT Y size
+{
+
+#if GIET_DEBUG_USER_LOCK
+
+unsigned int    px;
+unsigned int    py;
+unsigned int    pl;
+giet_proc_xyp( &px, &py, &pl );
+#endif
+
+    // get target node pointer
+    sqt_lock_node_t* node = lock->node[x][y][level];
+    
+    if (level == 0 )        // terminal case
+    {
+        // initializes target node
+        node->current  = 0;   
+        node->free     = 0;
+        node->level    = 0;
+        node->parent   = parent;
+        node->child[0] = NULL;
+        node->child[1] = NULL;
+        node->child[2] = NULL;
+        node->child[3] = NULL;
+
+#if GIET_DEBUG_USER_LOCK
+giet_shr_printf("\n[DEBUG USER SQT_LOCK] P[%d,%d,%d] initialises SQT node[%d,%d,%d] : \n"
+      " parent = %x / childO = %x / child1 = %x / child2 = %x / child3 = %x\n",
+      px , py , pl , x , y , level , 
+      (unsigned int)node->parent , 
+      (unsigned int)node->child[0] , 
+      (unsigned int)node->child[1] , 
+      (unsigned int)node->child[2] , 
+      (unsigned int)node->child[3] );
+#endif
+
+    }
+    else                   // non terminal case
+    {
+        unsigned int cx[4];      // x coordinate for children
+        unsigned int cy[4];      // y coordinate for children
+        unsigned int i;          // child index
+
+        // the child0 coordinates are equal to the parent coordinates
+        // other childs coordinates are incremented depending on the level value
+        cx[0] = x;
+        cy[0] = y;
+
+        cx[1] = x + (1 << (level-1));
+        cy[1] = y;
+
+        cx[2] = x;
+        cy[2] = y + (1 << (level-1));
+
+        cx[3] = x + (1 << (level-1));
+        cy[3] = y + (1 << (level-1));
+
+        // initializes target node
+        for ( i = 0 ; i < 4 ; i++ )
+        {
+            if ( (cx[i] < xmax) && (cy[i] < ymax) ) 
+                node->child[i] = lock->node[cx[i]][cy[i]][level-1];
+            else  
+                node->child[i] = NULL;
+        }
+        node->current  = 0;
+        node->free     = 0;
+        node->level    = level;
+        node->parent   = parent;
+
+#if GIET_DEBUG_USER_LOCK
+giet_shr_printf("\n[DEBUG USER SQT_LOCK] P[%d,%d,%d] initialises SQT node[%d,%d,%d] : \n"
+      " parent = %x / childO = %x / child1 = %x / child2 = %x / child3 = %x\n",
+      px , py , pl , x , y , level , 
+      (unsigned int)node->parent , 
+      (unsigned int)node->child[0] , 
+      (unsigned int)node->child[1] , 
+      (unsigned int)node->child[2] , 
+      (unsigned int)node->child[3] );
+#endif
+
+       // recursive calls for children nodes
+        for ( i = 0 ; i < 4 ; i++ )
+        {
+            if ( (cx[i] < xmax) && (cy[i] < ymax) ) 
+                sqt_lock_build( lock, 
+                                 cx[i], 
+                                 cy[i], 
+                                 level-1, 
+                                 node, 
+                                 xmax, 
+                                 ymax );
+        }
+    }
+}  // end _sqt_lock_build()
+
+
+
+/////////////////////////////////////////////////////////////////////////////////
+void sqt_lock_init( sqt_lock_t*  lock,
+                       unsigned int         x_size,    // number of clusters in a row
+                       unsigned int         y_size,    // number of clusters in a col
+                       unsigned int         ntasks )   // tasks per clusters
+{
+    // check parameters
+    if ( x_size > 16 ) giet_exit("SQT LOCK ERROR : x_size too large");
+    if ( y_size > 16 ) giet_exit("SQT LOCK ERROR : y_size too large");
+    if ( ntasks > 8  ) giet_exit("SQT LOCK ERROR : ntasks too large");
+    
+    // compute SQT levels
+    unsigned int levels; 
+    unsigned int z = (x_size > y_size) ? x_size : y_size;
+    levels = (z < 2) ? 1 : (z < 3) ? 2 : (z < 5) ? 3 : (z < 9) ? 4 : 5;
+
+#if GIET_DEBUG_USER_LOCK
+unsigned int    px;
+unsigned int    py;
+unsigned int    pl;
+giet_proc_xyp(&px, &py, &pl);
+unsigned int side   = (z < 2) ? 1 : (z < 3) ? 2 : (z < 5) ? 4 : (z < 9) ? 8 : 16;
+giet_shr_printf("\n[DEBUG USER SQT_LOCK] sqt_nodes allocation\n"
+                " x_size = %d / y_size = %d / levels = %d / side = %d\n",
+                x_size , y_size , levels , side );
+#endif
+
+    
+    unsigned int x;              // x coordinate for one SQT node
+    unsigned int y;              // y coordinate for one SQT node
+    unsigned int l;              // level for one SQT node
+
+    for ( x = 0 ; x < x_size ; x++ )
+    {
+        for ( y = 0 ; y < y_size ; y++ )
+        {
+            for ( l = 0 ; l < levels ; l++ )             // level 0 nodes
+            {
+                
+                if ( ( (l == 0) && ((x&0x00) == 0) && ((y&0x00) == 0) ) ||
+                     ( (l == 1) && ((x&0x01) == 0) && ((y&0x01) == 0) ) ||
+                     ( (l == 2) && ((x&0x03) == 0) && ((y&0x03) == 0) ) ||
+                     ( (l == 3) && ((x&0x07) == 0) && ((y&0x07) == 0) ) ||
+                     ( (l == 4) && ((x&0x0F) == 0) && ((y&0x0F) == 0) ) )
+                 {
+                     lock->node[x][y][l] = 
+                     (sqt_lock_node_t*)remote_malloc( sizeof(sqt_lock_node_t),
+                                                       x, y );
+
+#if GIET_DEBUG_USER_LOCK
+giet_shr_printf("\n[DEBUG USER SQT_LOCK] P[%d,%d,%d] allocates SQT node[%d,%d,%d]"
+               " : vaddr = %x\n",
+               px , py , pl , x , y , l , (unsigned int)lock->node[x][y][l] );
+#endif
+                 }
+            }
+        }
+    }
+            
+    // recursively initialize all SQT nodes from root to bottom
+    sqt_lock_build( lock,
+                     0,
+                     0,
+                     levels-1,
+                     NULL,
+                     x_size,
+                     y_size );
+
+    asm volatile ("sync" ::: "memory");
+
+#if GIET_DEBUG_USER_LOCK
+giet_shr_printf("\n[DEBUG USER SQT_LOCK] SQT nodes initialisation completed\n"); 
+#endif
+
+} // end sqt_lock_init()
+
+
+//////////////////////////////////////////////////////////////////////////////////
+static 
+void sqt_lock_take( sqt_lock_node_t* node )
+{
+    // get next free ticket from local lock
+    unsigned int ticket = atomic_increment( &node->free, 1 );
+
+#if GIET_DEBUG_USER_LOCK
+unsigned int    x;
+unsigned int    y;
+unsigned int    l;
+giet_proc_xyp(&x, &y, &l);
+giet_shr_printf("\n[DEBUG USER SQT_LOCK] P[%d,%d,%d] get ticket %d for SQT lock %x"
+               " / level = %d / current = %d / free = %d\n",
+               x , y , l , ticket , (unsigned int)node ,
+               node->level , node->current , node->free );
+#endif
+
+    // poll the local lock current index
+    while ( (*(volatile unsigned int *)( &node->current )) != ticket ) asm volatile( "nop" );
+
+#if GIET_DEBUG_USER_LOCK
+giet_shr_printf("\n[DEBUG SQT_LOCK] P[%d,%d,%d] get SQT lock %x"
+               " / level = %d / current = %d / free = %d\n",
+               x , y , l , (unsigned int)node ,
+               node->level , node->current , node->free );
+#endif
+
+    // try to take the parent node lock until top is reached
+    if ( node->parent != NULL ) sqt_lock_take( node->parent );
+
+} // end _sqt_lock_take()
+
+
+/////////////////////////////////////////////////////////////////////////////////
+void sqt_lock_acquire( sqt_lock_t*  lock )
+{
+    unsigned int x;
+    unsigned int y;
+    unsigned int p;
+    // get cluster coordinates
+    giet_proc_xyp( &x, &y, &p );
+
+    // try to recursively take the distributed locks (from bottom to top)
+    sqt_lock_take( lock->node[x][y][0] );
+}
+
+/////////////////////////////////////////////////////////////////////////////////
+static 
+void sqt_lock_give( sqt_lock_node_t* node )
+{
+    // release the local lock
+    node->current = node->current + 1;
+
+#if GIET_DEBUG_USER_LOCK
+unsigned int    x;
+unsigned int    y;
+unsigned int    l;
+giet_proc_xyp(&x, &y, &l);
+giet_shr_printf("\n[DEBUG USER SQT_LOCK] P[%d,%d,%d] release SQT lock %x"
+               " / level = %d / current = %d / free = %d\n",
+               x , y , l , (unsigned int)node, 
+               node->level , node->current , node->free );
+#endif
+
+    // reset parent node until top is reached
+    if ( node->parent != NULL ) sqt_lock_give( node->parent );
+
+} // end _sqt_lock_give()
+
+/////////////////////////////////////////////////////////////////////////////////
+void sqt_lock_release( sqt_lock_t*  lock )
+{
+    asm volatile ( "sync" );   // for consistency
+
+    unsigned int x;
+    unsigned int y;
+    unsigned int p;
+    // get cluster coordinates
+    giet_proc_xyp( &x, &y, &p );
+
+    // recursively reset the distributed locks (from bottom to top)
+    sqt_lock_give( lock->node[x][y][0] );
+}
+
+// Local Variables:
+// tab-width: 4
+// c-basic-offset: 4
+// c-file-offsets:((innamespace . 0)(inline-open . 0))
+// indent-tabs-mode: nil
+// End:
+// vim: filetype=c:expandtab:shiftwidth=4:tabstop=4:softtabstop=4
+
Index: /soft/giet_vm/giet_libs/user_sqt_lock.h
===================================================================
--- /soft/giet_vm/giet_libs/user_sqt_lock.h	(revision 581)
+++ /soft/giet_vm/giet_libs/user_sqt_lock.h	(revision 581)
@@ -0,0 +1,36 @@
+
+#ifndef USER_LOCKS_H
+#define USER_LOCKS_H
+
+#include "hard_config.h"
+
+/////////////////////////////////////////////////////////////////////////////
+//      SQT lock structures and access functions
+/////////////////////////////////////////////////////////////////////////////
+
+typedef struct sqt_lock_node_s 
+{
+    unsigned int            current;         // current ticket index
+    unsigned int            free;            // next free ticket index
+    unsigned int            level;           // hierarchical level (0 is bottom)
+    struct sqt_lock_node_s* parent;          // parent node (NULL for root)
+    struct sqt_lock_node_s* child[4];        // children node
+    unsigned int            padding[8];      // for 64 bytes alignment         
+} sqt_lock_node_t;
+
+typedef struct sqt_lock_s 
+{
+    sqt_lock_node_t* node[X_SIZE][Y_SIZE][5];  // array of pointers on SBT nodes 
+} sqt_lock_t;
+
+extern void sqt_lock_init( sqt_lock_t*  lock,
+                       unsigned int         x_size,
+                       unsigned int         y_size,
+                       unsigned int         ntasks );
+
+extern void sqt_lock_acquire( sqt_lock_t*  lock );
+
+extern void sqt_lock_release( sqt_lock_t*  lock );
+
+
+#endif
