]> AND Private Git Repository - snake_gpu.git/commitdiff
Logo AND Algorithmique Numérique Distribuée

Private GIT Repository
Initial commit
authorperrot <perrot@debzulu.iut-bm.univ-fcomte.fr>
Tue, 15 Feb 2011 12:29:51 +0000 (13:29 +0100)
committerperrot <perrot@debzulu.iut-bm.univ-fcomte.fr>
Tue, 15 Feb 2011 12:29:51 +0000 (13:29 +0100)
Snake gpu for sm20

57 files changed:
exec/SNAKE2D [new file with mode: 0755]
lib/lib_alloc.o [new file with mode: 0644]
lib/lib_contour.o [new file with mode: 0644]
lib/lib_images.o [new file with mode: 0644]
lib/lib_math.o [new file with mode: 0644]
lib/lib_snake_common.o [new file with mode: 0644]
makefile [new file with mode: 0644]
src/constantes.h [new file with mode: 0644]
src/constantes.h~ [new file with mode: 0644]
src/defines.h [new file with mode: 0644]
src/defines.h~ [new file with mode: 0644]
src/lib_alloc.c [new file with mode: 0644]
src/lib_alloc.c~ [new file with mode: 0644]
src/lib_alloc.h [new file with mode: 0644]
src/lib_alloc.h~ [new file with mode: 0644]
src/lib_contour.c [new file with mode: 0644]
src/lib_contour.h [new file with mode: 0644]
src/lib_gpu.cu [new file with mode: 0644]
src/lib_gpu.cu~ [new file with mode: 0644]
src/lib_gpu.h [new file with mode: 0644]
src/lib_gpu.h~ [new file with mode: 0644]
src/lib_images.c [new file with mode: 0644]
src/lib_images.c~ [new file with mode: 0644]
src/lib_images.h [new file with mode: 0644]
src/lib_images.h~ [new file with mode: 0644]
src/lib_kernel_snake_2_gpu.cu [new file with mode: 0644]
src/lib_kernel_snake_2_gpu.cu~ [new file with mode: 0644]
src/lib_kernels_contribs.cu [new file with mode: 0644]
src/lib_kernels_contribs.cu~ [new file with mode: 0644]
src/lib_kernels_contribs.h [new file with mode: 0644]
src/lib_kernels_cumuls.cu [new file with mode: 0644]
src/lib_kernels_cumuls.cu~ [new file with mode: 0644]
src/lib_kernels_maths.cu [new file with mode: 0644]
src/lib_kernels_maths.cu~ [new file with mode: 0644]
src/lib_kernels_maths.h [new file with mode: 0644]
src/lib_kernels_maths.h~ [new file with mode: 0644]
src/lib_kernels_maths_gpu.cu~ [new file with mode: 0644]
src/lib_math.c [new file with mode: 0644]
src/lib_math.c~ [new file with mode: 0644]
src/lib_math.h [new file with mode: 0644]
src/lib_math.h~ [new file with mode: 0644]
src/lib_snake_2_gpu.cu [new file with mode: 0644]
src/lib_snake_2_gpu.cu~ [new file with mode: 0644]
src/lib_snake_2_gpu.h [new file with mode: 0644]
src/lib_snake_2_gpu.h~ [new file with mode: 0644]
src/lib_snake_common.c [new file with mode: 0644]
src/lib_snake_common.c~ [new file with mode: 0644]
src/lib_snake_common.h [new file with mode: 0644]
src/lib_snake_common.h~ [new file with mode: 0644]
src/lib_test_gpu.cu [new file with mode: 0644]
src/lib_test_gpu.cu~ [new file with mode: 0644]
src/lib_test_gpu.h [new file with mode: 0644]
src/lib_test_gpu.h~ [new file with mode: 0644]
src/snake2D_gpu.cu [new file with mode: 0644]
src/snake2D_gpu.cu~ [new file with mode: 0644]
src/structures.h [new file with mode: 0644]
src/structures.h~ [new file with mode: 0644]

diff --git a/exec/SNAKE2D b/exec/SNAKE2D
new file mode 100755 (executable)
index 0000000..67f3437
Binary files /dev/null and b/exec/SNAKE2D differ
diff --git a/lib/lib_alloc.o b/lib/lib_alloc.o
new file mode 100644 (file)
index 0000000..a7408ec
Binary files /dev/null and b/lib/lib_alloc.o differ
diff --git a/lib/lib_contour.o b/lib/lib_contour.o
new file mode 100644 (file)
index 0000000..26fc29d
Binary files /dev/null and b/lib/lib_contour.o differ
diff --git a/lib/lib_images.o b/lib/lib_images.o
new file mode 100644 (file)
index 0000000..120abff
Binary files /dev/null and b/lib/lib_images.o differ
diff --git a/lib/lib_math.o b/lib/lib_math.o
new file mode 100644 (file)
index 0000000..a9ff110
Binary files /dev/null and b/lib/lib_math.o differ
diff --git a/lib/lib_snake_common.o b/lib/lib_snake_common.o
new file mode 100644 (file)
index 0000000..a7abed2
Binary files /dev/null and b/lib/lib_snake_common.o differ
diff --git a/makefile b/makefile
new file mode 100644 (file)
index 0000000..70d42b5
--- /dev/null
+++ b/makefile
@@ -0,0 +1,82 @@
+# chemin des librairies
+
+
+PATH_GCC = $(PWD)
+
+PATH_LIB = $(PATH_GCC)/lib/
+PATH_SRC = $(PATH_GCC)/src/
+PATH_EXEC = $(PATH_GCC)/exec/
+
+# repertoires pour les headers
+PATH_INCLUDE = $(PATH_GCC)/src/
+
+# compilateur
+CC = gcc
+NVCC = /usr/local/cuda/bin/nvcc
+CXX = g++
+
+# options de compilation
+# -Wall : Warning all
+# -g : debug (ex : gdb sas)
+# -pg : profile memoire et cpu pour chaque fonctions (ex : gprof name | less)
+# -O3 : optimisation code -O0 (rien) ~ -O3 (maxi)
+# -fstrict-aliasing : aligne  la memoire sur 32 bits
+
+# gcc
+OPTION_CC1 = -Wall -O3 -static #-pg #-g -fprofile-arcs -ftest-coverage
+OPTION_CC2 =  $(OPTION_CC1)  -funroll-all-loops -fstrict-aliasing 
+
+OPTION_CC = $(OPTION_CC2) -I$(PATH_INCLUDE) -I$(PATH_SRC)
+
+
+# librairies pour la compilation
+LIB_CC = -lm 
+LIBSNV = -L/usr/local/cuda/lib64 -lcuda -lcudart
+
+# sources utiles a la compilation des main
+SRCS =         lib_alloc.c lib_images.c lib_math.c lib_snake_common.c lib_contour.c
+
+SRCS_NV =  lib_test_gpu.cu lib_snake_2_gpu.cu lib_gpu.cu snake2D_gpu.cu
+
+OBJS = $(SRCS:%.c=$(PATH_LIB)%.o) $(SRCS_NV:%.cu=$(PATH_LIB)%.o)
+
+# dependances supplementaires
+DEPS =  $(PATH_SRC)/constantes.h $(PATH_SRC)/structures.h $(PATH_GCC)/makefile
+help :
+       @echo "cibles : snake2D doc clean"
+
+all : snake2D doc
+clean :
+       -rm -f $(PATH_LIB)*.o
+       -rm -rf $(PATH_GCC)/docs/
+
+
+# regle pour les .o
+# --use_fast_math
+# --ptxas-options=-v
+$(PATH_LIB)%_gpu.o :   $(PATH_SRC)%_gpu.cu
+                       $(NVCC) -arch=sm_20 --use_fast_math -c $< -o $@ 
+
+$(PATH_LIB)%.o :       $(PATH_SRC)%.c $(DEPS)
+                       $(CC) $(OPTION_CC) -c $< -o $@
+
+# regle pour l'exec
+
+$(PATH_EXEC)SNAKE2D :  $(PATH_SRC)snake2D_gpu.cu $(OBJS) $(DEPS)
+                       $(CXX) $(OBJS) $(LIBSNV) \
+                       -o $(PATH_EXEC)SNAKE2D
+
+# compilation main
+
+snake2D :      $(PATH_EXEC)SNAKE2D
+               @echo ""
+               @echo "***** fin compil snake2D *****"
+               @echo ""
+
+# generation des doc
+
+doc :          
+               doxygen doxygen.conf
+               @echo ""
+               @echo "***** fin compil doc *****"
+               @echo ""
diff --git a/src/constantes.h b/src/constantes.h
new file mode 100644 (file)
index 0000000..38ad9db
--- /dev/null
@@ -0,0 +1,52 @@
+/**
+ * \file constantes.h
+ * \brief Definition des parametres de l'algo snake
+ * \author NB - PhyTI 
+ * \version x.x
+ * \date 20 decembre 2009
+ *
+ *
+ */
+
+
+#ifndef _CONSTANTES_H
+
+#define _CONSTANTES_H
+
+
+/**
+ * \def COEF_DECROI pourcentage de decroissance pour accepter les modifications
+ * \def INV_COEF_DECROI pourcentage de decroissance pour accepter les modifications
+ */
+#define COEF_DECROI 0.99999
+#define INV_COEF_DECROI 1.00001
+
+
+/**
+ * \def ALIGN_SSE attribut d'alignement memoire pour sse2 (128 bits)
+ */
+//#define ATT_ALIGN_SSE __attribute__ ((aligned (16)))
+
+
+/**
+ * \def ALIGN_SSE alignement memoire pour sse2 (128 bits)
+ */
+//#define ALIGN_SSE 16
+
+
+/**
+ * \def NBBIT_SUM1 longueur du champ de bits associe a sum_1
+ * \def NBBIT_SUMX longueur du champ de bits associe a sum_x
+ */
+/*#define NBBIT_SUM1 24  sur 64 */
+/*#define NBBIT_SUMX 40  sur 64 (complement) */
+
+/**
+ * \def SIZE_NAME_FILE longueur maxi associee aux noms de fichiers
+ * \def SIZE_LINE_TEXT longueur maxi associee a une ligne de texte
+ */
+#define SIZE_NAME_FILE 256 
+#define SIZE_LINE_TEXT 256 
+
+
+#endif //_CONSTANTES_H
diff --git a/src/constantes.h~ b/src/constantes.h~
new file mode 100644 (file)
index 0000000..38ad9db
--- /dev/null
@@ -0,0 +1,52 @@
+/**
+ * \file constantes.h
+ * \brief Definition des parametres de l'algo snake
+ * \author NB - PhyTI 
+ * \version x.x
+ * \date 20 decembre 2009
+ *
+ *
+ */
+
+
+#ifndef _CONSTANTES_H
+
+#define _CONSTANTES_H
+
+
+/**
+ * \def COEF_DECROI pourcentage de decroissance pour accepter les modifications
+ * \def INV_COEF_DECROI pourcentage de decroissance pour accepter les modifications
+ */
+#define COEF_DECROI 0.99999
+#define INV_COEF_DECROI 1.00001
+
+
+/**
+ * \def ALIGN_SSE attribut d'alignement memoire pour sse2 (128 bits)
+ */
+//#define ATT_ALIGN_SSE __attribute__ ((aligned (16)))
+
+
+/**
+ * \def ALIGN_SSE alignement memoire pour sse2 (128 bits)
+ */
+//#define ALIGN_SSE 16
+
+
+/**
+ * \def NBBIT_SUM1 longueur du champ de bits associe a sum_1
+ * \def NBBIT_SUMX longueur du champ de bits associe a sum_x
+ */
+/*#define NBBIT_SUM1 24  sur 64 */
+/*#define NBBIT_SUMX 40  sur 64 (complement) */
+
+/**
+ * \def SIZE_NAME_FILE longueur maxi associee aux noms de fichiers
+ * \def SIZE_LINE_TEXT longueur maxi associee a une ligne de texte
+ */
+#define SIZE_NAME_FILE 256 
+#define SIZE_LINE_TEXT 256 
+
+
+#endif //_CONSTANTES_H
diff --git a/src/defines.h b/src/defines.h
new file mode 100644 (file)
index 0000000..d6dc963
--- /dev/null
@@ -0,0 +1,45 @@
+#ifndef __DEFINES_H__
+#define __DEFINES_H__
+
+
+const unsigned int CORRESPONDANCE_Di_Dj_FREEMAN[3][3] = 
+  {{3,2,1},
+   {4,8,0},
+   {5,6,7}} ;
+
+
+const int TABLE_CODAGE[8][8] = 
+  {{ 0, 0, 0, 0, 0,-1,-1,-1},  /* 0 */
+   { 1, 1, 1, 1, 1, 0, 0, 0},  /* 1 */
+   { 1, 1, 1, 1, 1, 0, 0, 0},  /* 2 */
+   { 1, 1, 1, 1, 1, 0, 0, 0},  /* 3 */
+   { 0, 0, 0, 0, 0,-1,-1,-1},  /* 4 */
+   { 0, 0, 0, 0, 0,-1,-1,-1},  /* 5 */
+   { 0, 0, 0, 0, 0,-1,-1,-1},  /* 6 */
+   { 0, 0, 0, 0, 0,-1,-1,-1}}; /* 7 */
+/*   0  1  2  3  4  5  6  7         */
+
+const int TABLE_CODAGE1[8][8] = 
+  {{ 0, 1, 1, 1, 1, 0, 0, 0},  /* 0 */
+   { 0, 1, 1, 1, 1, 2, 0, 0},  /* 1 */
+   { 0, 1, 1, 1, 1, 2, 2, 0},  /* 2 */
+   { 0, 1, 1, 1, 1, 2, 2, 2},  /* 3 */
+   {-1, 0, 0, 0, 0,-1,-1,-1},  /* 4 */
+   {-1, 2, 0, 0, 0,-1,-1,-1},  /* 5 */
+   {-1, 2, 2, 0, 0,-1,-1,-1},  /* 6 */
+   {-1, 2, 2, 2, 0,-1,-1,-1}}; /* 7 */
+/*   0  1  2  3  4  5  6  7         */
+
+#define BSMAX 128
+#define MAX_PIX 20000
+#define MAX_NODES 1000
+#define MAX_LISTE_PIX 10000000
+#define MAX(x,y) ( ( (x)>=(y) )?(x):(y) )
+#define ABS(x) ( ((x)>0)?(x):-(x))
+#define DEC 4
+#define DEC2 8 
+#define CONFLICT_FREE_OFFSET(index)  ( ((index) >>(DEC)) + ((index) >>(DEC2) ) )
+#define CFO(index)  ( ( (index) >>(DEC) ) + ( (index) >>(DEC2) ) ) 
+#define CFI(index)  ( (index) + (CFO(index)) )
+
+#endif 
diff --git a/src/defines.h~ b/src/defines.h~
new file mode 100644 (file)
index 0000000..5bfa254
--- /dev/null
@@ -0,0 +1,45 @@
+#ifndef __DEFINES_H__
+#define __DEFINES_H__
+
+
+const unsigned int CORRESPONDANCE_Di_Dj_FREEMAN[3][3] = 
+  {{3,2,1},
+   {4,8,0},
+   {5,6,7}} ;
+
+
+const int TABLE_CODAGE[8][8] = 
+  {{ 0, 0, 0, 0, 0,-1,-1,-1},  /* 0 */
+   { 1, 1, 1, 1, 1, 0, 0, 0},  /* 1 */
+   { 1, 1, 1, 1, 1, 0, 0, 0},  /* 2 */
+   { 1, 1, 1, 1, 1, 0, 0, 0},  /* 3 */
+   { 0, 0, 0, 0, 0,-1,-1,-1},  /* 4 */
+   { 0, 0, 0, 0, 0,-1,-1,-1},  /* 5 */
+   { 0, 0, 0, 0, 0,-1,-1,-1},  /* 6 */
+   { 0, 0, 0, 0, 0,-1,-1,-1}}; /* 7 */
+/*   0  1  2  3  4  5  6  7         */
+
+const int TABLE_CODAGE1[8][8] = 
+  {{ 0, 1, 1, 1, 1, 0, 0, 0},  /* 0 */
+   { 0, 1, 1, 1, 1, 2, 0, 0},  /* 1 */
+   { 0, 1, 1, 1, 1, 2, 2, 0},  /* 2 */
+   { 0, 1, 1, 1, 1, 2, 2, 2},  /* 3 */
+   {-1, 0, 0, 0, 0,-1,-1,-1},  /* 4 */
+   {-1, 2, 0, 0, 0,-1,-1,-1},  /* 5 */
+   {-1, 2, 2, 0, 0,-1,-1,-1},  /* 6 */
+   {-1, 2, 2, 2, 0,-1,-1,-1}}; /* 7 */
+/*   0  1  2  3  4  5  6  7         */
+
+#define BS 512
+#define MAX_PIX 20000
+#define MAX_NODES 1000
+#define MAX_LISTE_PIX 10000000
+#define MAX(x,y) ( ( (x)>=(y) )?(x):(y) )
+#define ABS(x) ( ((x)>0)?(x):-(x))
+#define DEC 4
+#define DEC2 8 
+#define CONFLICT_FREE_OFFSET(index)  ( ((index) >>(DEC)) + ((index) >>(DEC2) ) )
+#define CFO(index)  ( ( (index) >>(DEC) ) + ( (index) >>(DEC2) ) ) 
+#define CFI(index)  ( (index) + (CFO(index)) )
+
+#endif 
diff --git a/src/lib_alloc.c b/src/lib_alloc.c
new file mode 100644 (file)
index 0000000..21bc735
--- /dev/null
@@ -0,0 +1,110 @@
+/**
+ * \file lib_alloc.c
+ * \brief routines d'allocation des differentes datas du snake2D3D
+ * \author NB - PhyTI 
+ * \version x.x
+ * \date 20 decembre 2009
+ *
+ */
+
+#include <malloc.h>
+
+#include "lib_alloc.h"
+
+/**
+ * \fn int **new_matrix_int(int i_dim, int j_dim)
+ * \brief allocation d'un tableau 2D (tab[i][j]) avec data en ligne (tab[0][n])
+ *
+ * \param[in]  i_dim dimension verticale du tableau
+ * \param[in]  j_dim dimension horizontale du tableau 
+ *
+ * \return pointeur sur le tableau
+ *
+ */
+int **new_matrix_int(int i_dim, int j_dim)
+{
+  // allocation en ligne
+  int **matrice ;
+  int *vecteur  ;
+  int i ;
+  
+  vecteur = malloc(sizeof(int)*i_dim*j_dim) ;
+  matrice = malloc(sizeof(int*)*i_dim) ;
+  for (i=0;i<i_dim;i++)
+    matrice[i] = &(vecteur[i*j_dim]) ;
+  return matrice;
+}
+
+unsigned short  **new_matrix_ushort(int i_dim, int j_dim)
+{
+  // allocation en ligne
+  unsigned short **matrice ;
+  unsigned short *vecteur  ;
+  int i ;
+  
+  vecteur = malloc(sizeof(unsigned short)*i_dim*j_dim) ;
+  matrice = malloc(sizeof(unsigned short*)*i_dim) ;
+  for (i=0;i<i_dim;i++)
+    matrice[i] = &(vecteur[i*j_dim]) ;
+  return matrice;
+}
+
+
+/**
+ * \fn void del_matrix_int(int **image, int i_dim)
+ * \brief deallocation d'un tableau 2D (tab[i][j]) avec data en ligne (tab[0][n])
+ *
+ * \param[in]  image tableau int 2D avec allocation en ligne 
+ * \param[in]  i_dim dimension horizontale du tableau 
+ *
+ *
+ */
+void del_matrix_int(int **image, int i_dim)
+{
+  // allocation en ligne
+  free(image[0]) ;
+  free(image) ;
+}
+
+
+
+/**
+ * \fn int **new_matrix_pixel_cumul_sse(int i_dim, int j_dim)
+ * \brief allocation d'un tableau 2D (tab[i][j]) avec data en ligne (tab[0][n])
+ *
+ * \param[in]  i_dim dimension verticale du tableau
+ * \param[in]  j_dim dimension horizontale du tableau 
+ *
+ * \return pointeur sur le tableau
+ *
+ */
+struct pixel_cumul **new_matrix_pixel_cumul(int i_dim, int j_dim)
+{
+  // allocation en ligne
+  struct pixel_cumul **matrice ;
+  struct pixel_cumul *vecteur  ;
+  int i ;
+  
+  vecteur = malloc(sizeof(struct pixel_cumul)*i_dim*j_dim) ;
+  matrice = malloc(sizeof(struct pixel_cumul *)*i_dim) ;
+  for (i=0;i<i_dim;i++)
+    matrice[i] = &(vecteur[i*j_dim]) ;
+  return matrice;
+}
+
+
+/**
+ * \fn void del_matrix_pixel_cumul_sse(union pixel_cumul_sse **image, int i_dim)
+ * \brief deallocation d'un tableau 2D (tab[i][j]) avec data en ligne (tab[0][n])
+ *
+ * \param[in]  image tableau int 2D avec allocation en ligne 
+ * \param[in]  i_dim dimension horizontale du tableau 
+ *
+ *
+ */
+void del_matrix_pixel_cumul(struct pixel_cumul **image, int i_dim)
+{
+  // allocation en ligne
+  free(image[0]) ;
+  free(image) ;
+}
diff --git a/src/lib_alloc.c~ b/src/lib_alloc.c~
new file mode 100644 (file)
index 0000000..27bedc3
--- /dev/null
@@ -0,0 +1,96 @@
+/**
+ * \file lib_alloc.c
+ * \brief routines d'allocation des differentes datas du snake2D3D
+ * \author NB - PhyTI 
+ * \version x.x
+ * \date 20 decembre 2009
+ *
+ */
+
+#include <malloc.h>
+
+#include "lib_alloc.h"
+
+/**
+ * \fn int **new_matrix_int(int i_dim, int j_dim)
+ * \brief allocation d'un tableau 2D (tab[i][j]) avec data en ligne (tab[0][n])
+ *
+ * \param[in]  i_dim dimension verticale du tableau
+ * \param[in]  j_dim dimension horizontale du tableau 
+ *
+ * \return pointeur sur le tableau
+ *
+ */
+int **new_matrix_int(int i_dim, int j_dim)
+{
+  // allocation en ligne
+  int **matrice ;
+  int *vecteur  ;
+  int i ;
+  
+  vecteur = malloc(sizeof(int)*i_dim*j_dim) ;
+  matrice = malloc(sizeof(int*)*i_dim) ;
+  for (i=0;i<i_dim;i++)
+    matrice[i] = &(vecteur[i*j_dim]) ;
+  return matrice;
+}
+
+
+/**
+ * \fn void del_matrix_int(int **image, int i_dim)
+ * \brief deallocation d'un tableau 2D (tab[i][j]) avec data en ligne (tab[0][n])
+ *
+ * \param[in]  image tableau int 2D avec allocation en ligne 
+ * \param[in]  i_dim dimension horizontale du tableau 
+ *
+ *
+ */
+void del_matrix_int(int **image, int i_dim)
+{
+  // allocation en ligne
+  free(image[0]) ;
+  free(image) ;
+}
+
+
+
+/**
+ * \fn int **new_matrix_pixel_cumul_sse(int i_dim, int j_dim)
+ * \brief allocation d'un tableau 2D (tab[i][j]) avec data en ligne (tab[0][n])
+ *
+ * \param[in]  i_dim dimension verticale du tableau
+ * \param[in]  j_dim dimension horizontale du tableau 
+ *
+ * \return pointeur sur le tableau
+ *
+ */
+struct pixel_cumul **new_matrix_pixel_cumul(int i_dim, int j_dim)
+{
+  // allocation en ligne
+  struct pixel_cumul **matrice ;
+  struct pixel_cumul *vecteur  ;
+  int i ;
+  
+  vecteur = malloc(sizeof(struct pixel_cumul)*i_dim*j_dim) ;
+  matrice = malloc(sizeof(struct pixel_cumul *)*i_dim) ;
+  for (i=0;i<i_dim;i++)
+    matrice[i] = &(vecteur[i*j_dim]) ;
+  return matrice;
+}
+
+
+/**
+ * \fn void del_matrix_pixel_cumul_sse(union pixel_cumul_sse **image, int i_dim)
+ * \brief deallocation d'un tableau 2D (tab[i][j]) avec data en ligne (tab[0][n])
+ *
+ * \param[in]  image tableau int 2D avec allocation en ligne 
+ * \param[in]  i_dim dimension horizontale du tableau 
+ *
+ *
+ */
+void del_matrix_pixel_cumul(struct pixel_cumul **image, int i_dim)
+{
+  // allocation en ligne
+  free(image[0]) ;
+  free(image) ;
+}
diff --git a/src/lib_alloc.h b/src/lib_alloc.h
new file mode 100644 (file)
index 0000000..7c3e3ef
--- /dev/null
@@ -0,0 +1,12 @@
+#include "constantes.h"
+#include "structures.h"
+
+
+
+int **new_matrix_int(int i_dim, int j_dim) ;
+unsigned short **new_matrix_ushort(int i_dim, int j_dim) ;
+void del_matrix_int(int **image, int i_dim) ;
+
+
+struct pixel_cumul **new_matrix_pixel_cumul(int i_dim, int j_dim) ;
+void del_matrix_pixel_cumul(struct pixel_cumul **image, int i_dim) ;
diff --git a/src/lib_alloc.h~ b/src/lib_alloc.h~
new file mode 100644 (file)
index 0000000..5bf41e9
--- /dev/null
@@ -0,0 +1,11 @@
+#include "constantes.h"
+#include "structures.h"
+
+
+
+int **new_matrix_int(int i_dim, int j_dim) ;
+void del_matrix_int(int **image, int i_dim) ;
+
+
+struct pixel_cumul **new_matrix_pixel_cumul(int i_dim, int j_dim) ;
+void del_matrix_pixel_cumul(struct pixel_cumul **image, int i_dim) ;
diff --git a/src/lib_contour.c b/src/lib_contour.c
new file mode 100644 (file)
index 0000000..06fb7f9
--- /dev/null
@@ -0,0 +1,254 @@
+/**
+ * \file lib_contour.c
+ * \brief routines pour la gestion des contours polygonaux
+ * \author NB - PhyTI 
+ * \version x.x
+ * \date 24 decembre 2009
+ *
+ */
+
+#include "lib_contour.h"
+
+
+
+/**
+ * \fn int calcul_liste_pixel_segment(int y1,int x1,int y2,int x2, 
+ *                            int *liste_pixel_segment, int ind_offset=0)
+ *
+ * \brief calcul la liste des pixels du segment entre 2 noeuds
+ * \author FG - PhyTI (mars 2007), modifiee NB - PhyTI
+ *
+ * \param[in] y1 coordonnee du point P1 (equiv i1)
+ * \param[in] x1 coordonnee du point P1 (equiv j1)
+ * \param[in] y2 coordonnee du point P2 (equiv i2)
+ * \param[in] x2 coordonnee du point P2 (equiv j2)
+ * \param[out] liste_pixel_segment coordonnees des pixels [i j i j i j ...]
+ * \param[in] ind_offset decalage de la position origine dans la liste
+ *
+ * \return nb_pixel_segment, la dimension de la liste en nombre de coord (i,j)
+ *
+ * donne la liste des pixels d'un segment [P1 -> P2]
+ * Utilise l'algo de Bresenham en version int (recupere sur Wikipedia)
+ *
+ */
+uint32 calcul_liste_pixel_segment(uint32 y1,uint32 x1,uint32 y2,uint32 x2, uint32 *liste_pixel_segment, int ind_offset)
+{
+  int dx, dy ;
+  int e ;
+  uint32 *liste ;
+
+  liste = liste_pixel_segment + ind_offset ;
+
+  if ( (dx=x2-x1) != 0) 
+    {
+      if ( dx > 0 )
+       {
+         if ( (dy=y2-y1) != 0 )
+           {
+             if ( dy > 0 )
+               {
+                 // vecteur oblique dans le 1er quadran
+                 if ( dx >= dy )
+                   {
+                     // vecteur diagonal ou oblique proche de l'horizontale, dans le 1er octant
+                     dx = (e=dx) * 2 ; dy = dy * 2 ;  // e est positif
+                     while( x1!=x2 ) //boucler sans fin: deplacements horizontaux
+                       {                         
+                         *liste++=y1;
+                         *liste++=x1;
+
+                         x1++;
+                         if ( (e-=dy) < 0 )
+                           {
+                             y1++ ;  // deplacement diagonal
+                             e += dx ;
+                           }
+                       }
+                   }
+                 else
+                   {
+                     // vecteur oblique proche de la verticale, dans le 2nd octant
+                     dy = (e=dy) * 2 ; dx = dx * 2 ;  // e est positif
+                     while ( y1 != y2 ) //boucler sans fin: deplacements verticaux
+                       {
+                         *liste++=y1;
+                         *liste++=x1;
+                         y1 += 1 ;
+                         if ( (e -= dx) < 0 )
+                           {
+                             x1++ ;  // deplacement diagonal
+                             e += dy ;
+                           }
+                       }
+                   }
+               }                             
+             else // dy < 0 (et dx > 0)
+               {
+                 // vecteur oblique dans le 4e cadran
+                 if ( dx >= -dy )
+                   {
+                     // vecteur diagonal ou oblique proche de l'horizontale, dans le 8e octant
+                     dx = (e=dx) * 2 ; dy = dy * 2 ;  // e est positif
+                     while ( x1 != x2 ) //boucler sans fin  // deplacements horizontaux
+                       {
+                         *liste++=y1;
+                         *liste++=x1;
+                         x1 ++;
+                         if ( (e += dy) < 0 )
+                           {
+                             y1--;  // deplacement diagonal
+                             e += dx ;
+                           }
+                       }
+                   }
+                 else // vecteur oblique proche de la verticale, dans le 7e octant
+                   {
+                     dy = (e=dy) * 2 ; dx = dx * 2 ;  // e est negatif
+                     while ( y1 != y2 ) // boucler sans fin: deplacements verticaux
+                       {
+                         *liste++=y1;
+                         *liste++=x1;
+                         y1--;
+                         if ( (e += dx) > 0 )
+                           {
+                             x1 ++;  // deplacement diagonal
+                             e += dy ;
+                           }
+                       }
+                   }
+               }
+           }    
+         else // dy = 0 (et dx > 0)
+           {
+             // vecteur horizontal vers la droite
+             while ( x1 != x2 )
+               {
+                 *liste++=y1;
+                 *liste++=x1;
+                 x1++ ;
+               }
+           }
+       }       
+      else
+       {
+         // dx < 0
+         if ( (dy=y2-y1) != 0 )
+           {
+             if ( dy > 0 ) 
+               {
+                 // vecteur oblique dans le 2nd quadran
+                 if ( -dx >= dy )
+                   {
+                     // vecteur diagonal ou oblique proche de l'horizontale, dans le 4e octant
+                     dx = (e=dx) * 2 ; dy = dy * 2 ;  // e est negatif
+                     while ( x1 != x2 ) //boucler sans fin  // deplacements horizontaux
+                       {
+                         *liste++=y1;
+                         *liste++=x1;
+                         x1 -- ;
+                         if ( (e += dy) >= 0 )
+                           {
+                             y1++ ;  // deplacement diagonal
+                             e += dx ;
+                           }
+                       }
+                   }
+                 else
+                   {
+                     // vecteur oblique proche de la verticale, dans le 3e octant
+                     dy = (e=dy) * 2 ; dx = dx * 2 ;  // e est positif
+                     while ( y1 != y2 ) //boucler sans fin  // deplacements verticaux
+                       {
+                         *liste++=y1;
+                         *liste++=x1;
+                         y1++ ;
+                         if ( (e += dx) <= 0 )
+                           {
+                             x1--;  // depacement diagonal
+                             e += dy ;
+                           }
+                       }
+                   }
+               }
+             
+             else  // dy < 0 (et dx < 0)
+               {
+                 // vecteur oblique dans le 3e cadran
+                 if ( dx <= dy )
+                   {
+                     // vecteur diagonal ou oblique proche de l'horizontale, dans le 5e octant
+                     dx = (e=dx) * 2 ; dy = dy * 2 ;  // e est negatif
+                     while ( x1 != x2 ) //boucler sans fin  // deplacements horizontaux
+                       {
+                         *liste++=y1;
+                         *liste++=x1;
+                         x1 -- ;
+                         if ( (e -= dy) >= 0 )
+                           {
+                             y1-- ;  // deplacement diagonal
+                             e += dx ;
+                           }
+                       }
+                   }
+                 else
+                   {
+                     // vecteur oblique proche de la verticale, dans le 6e octant
+                     dy = (e=dy) * 2 ; dx = dx * 2 ;  // e est negatif
+                     while ( y1 != y2 ) //boucler sans fin  // deplacements verticaux
+                       {
+                         *liste++=y1;
+                         *liste++=x1;
+                         y1-- ;
+                         if ( (e-=dx) >= 0 )
+                           {
+                             x1 --;  // deplacement diagonal
+                             e += dy ;
+                           }
+                       }
+                   }
+               }
+           } 
+         else // dy = 0 (et dx < 0)
+           {
+             // vecteur horizontal vers la gauche
+             while ( x1 != x2 )
+               {
+                 *liste++=y1;
+                 *liste++=x1;
+                 x1 -- ;
+               }
+           }
+       }
+    }
+  else // dx = 0
+    {
+      if ( (dy=y2-y1) != 0 )
+       {
+         if ( dy > 0 )
+           {
+             // vecteur vertical croissant
+             while ( y1 != y2 )
+               {
+                 *liste++=y1;
+                 *liste++=x1;
+                 y1 ++ ;
+               }
+           }
+         else // dy < 0 (et dx = 0)
+           {
+             // vecteur vertical décroissant
+             while ( y1 != y2 )
+               { 
+                 *liste++=y1;
+                 *liste++=x1;
+                 y1 -- ;
+             }
+           }
+       }
+    }
+  
+  *liste++=y2;
+  *liste++=x2;
+
+  return (uint32)(liste-liste_pixel_segment)/2;
+}
diff --git a/src/lib_contour.h b/src/lib_contour.h
new file mode 100644 (file)
index 0000000..12d2903
--- /dev/null
@@ -0,0 +1,8 @@
+#ifndef _LIB_CONTOUR_H_
+#define _LIB_CONTOUR_H_ 
+
+#include "structures.h"
+
+uint32 calcul_liste_pixel_segment(uint32 y1,uint32 x1,uint32 y2,uint32 x2, uint32 *liste_pixel_segment, int ind_offset) ;
+
+#endif //_LIB_CONTOUR_H_
diff --git a/src/lib_gpu.cu b/src/lib_gpu.cu
new file mode 100644 (file)
index 0000000..d6df5ec
--- /dev/null
@@ -0,0 +1,623 @@
+
+#include <stdio.h>
+
+
+extern "C"{
+#include "structures.h"
+#include "lib_math.h"
+#include "defines.h"
+#include "lib_gpu.h"
+#include "lib_snake_2_gpu.h"
+}
+#include "lib_test_gpu.h"
+#include "lib_kernels_cumuls.cu"
+#include "lib_kernel_snake_2_gpu.cu"
+
+#define DEBUG_IMG_CUMUL 1
+bool DISPLAY_ERR_IMG_CUMUL = 1;
+//#define DEBUG_POSITIONS
+//#define DEBUG_MOVE
+//#define DEBUG_CRST
+//#define DEBUG_MV
+//#define DEBUG_SOMSOM
+//#define DEBUG_SOMBLOCS
+//#define DEBUG_LISTES
+//#define DEBUG_STATS_REF
+
+
+
+void cuda_init_img_cumul(unsigned short ** img_in, int H, int L, int nb_nodes,
+                                                unsigned short ** d_img, t_cumul_x ** d_img_x, t_cumul_x2 ** d_img_x2,
+                                                int ** d_freemanDiDj, int ** d_codeNoeud,
+                                                snake_node_gpu ** d_snake, uint32 ** d_nb_pix_max,
+                                                uint4 ** d_positions, uint64 ** d_contribs_segments, uint4 ** d_freemans_centres,
+                                                int ** d_codes_segments, int64 ** d_stats_snake,
+                                                int64 ** d_stats, int64 ** d_stats_ref, double ** d_vrais, double ** d_vrais_snake,
+                                                uint2 ** d_liste_pixels, uint64 ** d_contribs_segments_blocs,
+                                                bool ** d_move
+                                                )
+{
+  unsigned int taille = H*L;
+  timeval chrono;
+
+  
+  //allocation cumuls en memoire GPU
+  tic(&chrono, NULL);
+  /*
+       MAX_PIX 20000
+       MAX_NODES 10000
+       MAX_LISTE_PIX 10000000
+   */
+  cudaMalloc( (void**) d_snake, MAX_NODES*sizeof(snake_node_gpu) );
+  
+  cudaMalloc( (void**) d_img, taille*sizeof(unsigned short) );
+  cudaMalloc( (void**) d_img_x, taille*sizeof(t_cumul_x) );
+  cudaMalloc( (void**) d_img_x2, taille*sizeof(t_cumul_x2) );
+  cudaMalloc( (void**) d_freemanDiDj, 9*sizeof(int) );
+  cudaMalloc( (void**) d_codeNoeud, 64*sizeof(int) );
+  
+  cudaMalloc( (void**) d_stats_snake, 6*sizeof(int64)) ;
+  cudaMalloc( (void**) d_positions, 8*MAX_NODES*sizeof(uint4)) ;
+  cudaMalloc( (void**) d_contribs_segments, 3*16*MAX_NODES*sizeof(uint64)) ;
+  cudaMalloc( (void**) d_contribs_segments_blocs, (3*MAX_LISTE_PIX/32)*sizeof(uint64)) ;
+  cudaMalloc( (void**) d_freemans_centres, 16*MAX_NODES*sizeof(uint4)) ;
+  cudaMalloc( (void**) d_codes_segments, 16*MAX_NODES*sizeof(int)) ;
+  cudaMalloc( (void**) d_stats, 3*8*MAX_NODES*sizeof(int64)) ;
+  cudaMalloc( (void**) d_stats_ref, 3*MAX_NODES*sizeof(int64)) ;
+  cudaMalloc( (void**) d_vrais, 8*MAX_NODES*sizeof(double)) ;
+  cudaMalloc( (void**) d_move, MAX_NODES*sizeof(bool)) ;
+  cudaMalloc( (void**) d_nb_pix_max, sizeof(uint32)) ;
+  cudaMalloc( (void**) d_vrais_snake, sizeof(double)) ;
+  
+  cudaMalloc( (void**) d_liste_pixels, 16*5*(MAX_NODES)*sizeof(uint2) );
+  
+  printf("TOTAL MEM = %ld octets\n",
+                (2*MAX_NODES*(sizeof(snake_node_gpu)+(8+16)*sizeof(uint4)+3*16*8+16*4+24*8+3*8+8*sizeof(double)+sizeof(bool))
+                +(MAX_LISTE_PIX)*(sizeof(uint2)+1)
+                +taille*(8+sizeof(t_cumul_x)+sizeof(t_cumul_x2))
+                 +9*4+64*4+6*8+4+sizeof(double)) );
+           
+  int64 * h_stats_snake = new int64[6];
+  
+  toc(chrono, "temps alloc mem GPU");
+
+  /*detection-choix-initialisation de la carte GPU*/
+  tic(&chrono, NULL) ;
+  cudaDeviceProp deviceProp;
+  deviceProp.major = 2;
+  deviceProp.minor = 0;
+  int dev;
+  cudaChooseDevice(&dev, &deviceProp);
+  cudaGetDeviceProperties(&deviceProp, dev);
+  if(deviceProp.major >= 2 )
+       {
+         printf("Using Device %d: \"%s\"\n", dev, deviceProp.name);
+         cudaSetDevice(dev);
+       }
+  toc(chrono, "temps acces GPU") ;
+  
+  //copie tables correspondances freeman en mem GPU
+  tic(&chrono, NULL) ;
+  cudaMemcpy( *d_freemanDiDj, CORRESPONDANCE_Di_Dj_FREEMAN , 9*sizeof(int), cudaMemcpyHostToDevice);
+  cudaMemcpy( *d_codeNoeud, TABLE_CODAGE , 64*sizeof(unsigned int), cudaMemcpyHostToDevice);
+  toc(chrono, "temps transfert tables de codage") ;
+  
+  /*transfert image en global mem GPU*/
+  tic(&chrono, NULL);
+  cudaMemcpy( *d_img, img_in[0], taille*sizeof(unsigned short), cudaMemcpyHostToDevice);
+  toc(chrono, "transfert image vers GPU");
+
+  //calculs images cumulees sur GPU
+  int blocs_max = 65536 ;
+  int bs = 256 ; //arbitraire, d'apres les observations c'est souvent l'optimu
+  unsigned int base = 0 ;
+  unsigned int bl_l  = (L+bs-1)/bs ;
+  unsigned int nb_lines =  blocs_max / bl_l ;
+  unsigned int lines ;
+  unsigned int tranches = ( 1 + H / nb_lines ) ;
+  nb_lines = (H +tranches -1)/ tranches ; // equilibre la taille des tranches
+  
+  dim3 threads(bs,1,1);
+  int smem = nextPow2(bl_l)*2; //smem pour le prefixscan des sommes de blocs (etape 2)
+  smem += smem >> DEC;
+  smem += smem >> DEC;
+  int smem_size = smem*sizeof(uint64);
+  uint64 * d_somblocs ; // sommes des cumuls par bloc de calcul
+  
+
+  if(DEBUG_IMG_CUMUL)
+       {
+         printf("--- CALCULS IMAGES CUMULEES+STATS GPU  ----\n");
+         printf("\t%d threads par bloc  -- %u blocs par ligne -- %u tranches -- %u lignes par tranche \n",bs, bl_l, tranches,nb_lines);
+         printf(" Smem totale pour cumuls : %d\n", CFI(bs)*(sizeof(t_cumul_x)+sizeof(t_cumul_x2)) );
+         tic(&chrono, NULL);
+       }
+  //calculs cumuls generiques : necessitent 3 etapes / 3 kernels  
+  cudaMalloc( (void**) &d_somblocs, 2*bl_l*nb_lines*sizeof(uint64) );
+  cudaFuncSetCacheConfig(calcul_cumuls_gpu, cudaFuncCachePreferShared);
+  do
+       {
+         if  ( H-base < nb_lines ) lines = H - base ; else lines = nb_lines ;
+         printf("base = ligne %d -- traitement de %d lignes \n", base, lines) ;
+         dim3 grid(bl_l*lines,1,1) ;
+         calcul_cumuls_gpu<<<grid, threads, CFI(bs)*sizeof(tcumuls)>>>(*d_img, *d_img_x, *d_img_x2, H, L, d_somblocs, bl_l, base, lines) ;
+         scan_somblocs<<<2*lines, nextPow2(bl_l)/2, smem_size>>>(d_somblocs, bl_l) ;
+         add_soms_to_cumuls<<<grid, threads>>>(*d_img_x, *d_img_x2, H, L, d_somblocs, bl_l, base, lines) ;
+         base += lines ;
+       }
+  while (base < H) ;
+  cudaFree(d_somblocs) ;
+  
+  //calcul des sommes totales N, sigX et sigX2 sur l'image
+  calcul_stats_image<<<1, 1>>>( *d_img_x, *d_img_x2, H, L, (uint64*)*d_stats_snake);
+  
+  
+         cudaThreadSynchronize()   ;
+         toc(chrono, "\tTemps GPU");
+        if(DEBUG_IMG_CUMUL)
+       { 
+         
+         //allocation memoire CPU
+         t_cumul_x  * img_x = new t_cumul_x [H*L];
+         t_cumul_x2 *  img_x2 = new t_cumul_x2 [H*L];
+         
+         /*pour test comparaison*/
+         t_cumul_x * img_xb = new t_cumul_x [H*L];
+         t_cumul_x2 * img_x2b = new t_cumul_x2 [H*L];
+         
+         cudaMemcpy( img_xb, *d_img_x, taille*sizeof(t_cumul_x), cudaMemcpyDeviceToHost);
+         cudaMemcpy( img_x2b, *d_img_x2, taille*sizeof(t_cumul_x2), cudaMemcpyDeviceToHost);
+         
+         //cumuls : etape 1 CPU
+         /*      
+               for (int i=0; i<H; i++)
+               {
+                       for (int b=0; b<bl_l; b++)
+                       {
+                               int offset = b*bs ;
+                               img_x[i*L+offset] = img_in[i][offset] ;
+                               img_x2[i*L+offset]= img_in[i][offset]*img_in[i][offset] ;
+                               for (int p=1; p<bs; p++)
+                               {
+                                       int j = p+offset ;
+                                       if (j<L)
+                                       {
+                                               img_x[i*L+j] = img_x[i*L+j-1] + img_in[i][j];
+                                               img_x2[i*L+j] = img_x2[i*L+j-1] + img_in[i][j]*img_in[i][j] ;
+                                       }
+                               }
+                       }
+               }
+         */
+         //cumuls complets CPU
+          
+         for (int i=0; i<H; i++)
+               {
+                 img_x[i*L+0] = img_in[i][0] ;
+                 img_x2[i*L+0]= img_in[i][0]*img_in[i][0] ;
+                 for (int j=1; j<L; j++)
+                       {
+                         img_x[i*L+j]  = img_x[i*L+j-1]  + img_in[i][j] ;
+                         img_x2[i*L+j] = img_x2[i*L+j-1] + img_in[i][j]*img_in[i][j] ;
+                       }
+               }
+         
+         int cpt = 0;
+         int cpt_errx=0, cpt_errx2 = 0;
+         for (int i=0; i< H; i++){
+               for (int j=0; j< L; j++){
+                 if ( (img_x[i*L+j] !=  img_xb[i*L+j]) ) cpt_errx++ ;
+                 if ( (img_x2[i*L+j] !=  img_x2b[i*L+j]) ) cpt_errx2++ ;
+                 if ( (img_x[i*L+j] !=  img_xb[i*L+j]) || (img_x2[i*L+j] !=  img_x2b[i*L+j]))
+                 {
+                       //printf("(%d,%d)sxCPU=%lu  sxGPU=%lu -- sx2CPU=%lu  sx2GPU=%lu\n",i,j,img_x[i*L+j], img_xb[i*L+j], img_x2[i*L+j], img_x2b[i*L+j]);
+                 }
+                 cpt++;
+               }
+         }
+         printf("%d erreurs sur CX / %d points\n", cpt_errx, cpt );
+         printf("%d erreurs sur CX2 / %d points\n", cpt_errx2, cpt );
+         uint64 sigX = 0, sigX2 = 0 ;
+         for (int i=0; i<H; i++)
+               {
+                 sigX += img_x[i*L+L-1] ;
+                 sigX2+= img_x2[i*L+L-1];
+               }
+         printf("STATS IMAGE  N = %d - sigX = %lu - sigX2 = %lu\n",  H*L, sigX, sigX2 );
+       }
+  
+  /*
+   * generation snake en mem GPU
+   */
+  int dist = 140 ;
+  
+  tic(&chrono, NULL);
+  if (nb_nodes == 4)  genere_snake_rectangle_4nodes_gpu<<< 1, 1>>>(*d_snake, 140, H, L) ;
+  else if (nb_nodes == 40) genere_snake_rectangle_Nnodes_gpu<<< 1, 1>>>(*d_snake, (H+L)/20, H, L) ;
+
+  int nnodes = nb_nodes ;
+  snake_node_gpu * h_snake = new snake_node_gpu[nnodes];
+  snake_node * h_snake_ll = new snake_node[nnodes] ;
+  uint4 * h_liste_positions = new uint4[nnodes*8]; 
+  double * h_vrais_snake = new double ;
+  //init les stats du snake
+  uint2 * d_liste_temp  ;
+  t_sum_x2 * d_sompart  ;
+  int tpb, bps, npixmax ;
+  //calcul nb threads par bloc
+  npixmax = 2*(H+L-4*dist)/(nnodes-1) ;
+  tpb = nextPow2(npixmax) ;
+  if (tpb >= 256) tpb = 256 ;//  /!\ le kernel <<< calcul_contrib...>>> ne supporte pas un bs>256 a cause de la shared-mem nécessaire
+  if (tpb < 32 ) tpb = 32 ;
+  tpb=128 ; 
+  bps = (npixmax+tpb-1)/tpb ;
+  printf("PARAMS EXEC INIT : %d pix max, %d threads/bloc, %d blocs/seg, %d blocs/grille\n", npixmax, tpb, bps, nnodes*bps);
+  //alloc
+  cudaMalloc((void**) &d_liste_temp, nnodes*bps*tpb*sizeof(uint2));
+  cudaMalloc((void**) &d_sompart, 3*nnodes*bps*sizeof(t_sum_x2));
+  cudaMalloc((void**) &d_stats_ref, 3*nnodes*sizeof(int64));
+
+  //DEBUG : pour forcer la mise à zero du tableau intermediaire d_stats_ref
+  int64 h_stats_ref[3*nnodes] ;
+  for (int a=0; a<3*nnodes ; a++) h_stats_ref[a] = 0 ;
+  cudaMemcpy( h_stats_ref, d_stats_ref, sizeof(int64), cudaMemcpyHostToDevice) ;
+  //fin forçage a 0
+  
+  //DEBUG : pour forcer la mise à zero du tableau intermediaire d_sompart
+     t_sum_x2 h_sompart[ 3*nnodes*bps ] ;
+     for (int a=0; a<3*nnodes*bps ; a++) h_sompart[a] = 0 ;
+     cudaMemcpy( h_sompart, d_sompart, sizeof(t_sum_x2), cudaMemcpyHostToDevice) ;
+  //fin forçage a 0
+  
+  calcul_contribs_segments_snake<<< nnodes*bps, tpb, (CFI(tpb))*(3*sizeof(t_sum_x2))>>>
+       (*d_snake, nnodes, 
+        *d_img_x, *d_img_x2, 
+        L, d_liste_temp, d_sompart, *d_freemanDiDj );
+
+  //TODO
+  //parametrer pour ne pas appeler qd tpb=1
+  //oblige a modifier le kernel <<< calcul_contrib...>>> pour ecrire directement ds d_snake
+  // au lieu de d_sompart
+  somsom_snake<<< nnodes , 1 >>>(d_sompart, nnodes, bps, *d_snake);
+  
+  
+  calcul_stats_snake<<< 1 , 1 >>>(*d_snake, nnodes, *d_stats_snake, *d_vrais_snake,
+                                                                 *d_img_x, *d_img_x2,
+                                                                 *d_codeNoeud, L
+                                                                 );
+  cudaThreadSynchronize() ;
+  toc(chrono, "\tTemps") ;
+  
+  /*
+       verif stats initiales du snake
+  */
+  cudaMemcpy( h_vrais_snake, *d_vrais_snake, sizeof(double), cudaMemcpyDeviceToHost) ; 
+  cudaMemcpy( h_stats_snake, *d_stats_snake, 6*sizeof(int64), cudaMemcpyDeviceToHost) ;
+  
+  printf("STATS SNAKE log vrais=%lf : c1=%lu - cx=%lu - cx2=%lu - N=%lu - SUMX=%lu - SUMX2=%lu\n",
+                *h_vrais_snake,
+                h_stats_snake[0],  h_stats_snake[1],  h_stats_snake[2],
+                h_stats_snake[3],  h_stats_snake[4],  h_stats_snake[5] );
+  
+  /*
+       verif stats diminuees des contribs des 2 segments associes a chaque noeud
+  */  
+#ifdef DEBUG_STATS_REF
+  cudaMemcpy( h_stats_ref, d_stats_ref, 3*nnodes*sizeof(int64), cudaMemcpyDeviceToHost) ;
+  cudaMemcpy( h_snake, *d_snake, nnodes*sizeof(snake_node_gpu), cudaMemcpyDeviceToHost) ;
+  
+       
+  printf("******* STATS DIMINUEES\n");
+  for(int n=0; n<nnodes;n++)
+       {
+         int i = h_snake[n].posi, j = h_snake[n].posj ;
+         printf("node %d (%d,%d) : %ld - %ld - %ld - img1= %lu - imgx= %lu - imgx2= %lu \n", n, i, j,
+                        h_stats_ref[3*n], h_stats_ref[3*n +1], h_stats_ref[3*n +2],
+                        img_1[i][j], img_x[i][j], img_x2[i][j]);
+       }
+#endif //DEBUG_STATS_REF
+  
+  //snake2gpu(d_snake, snake, nb_nodes);
+  //gpu2snake(*d_snake, &h_snake_ll, nnodes);
+
+#ifdef DEBUG_POSITIONS
+  for (int n=0; n<nnodes; n++)
+       {
+         printf("Node %d :\n", n);
+         for (int pos=0; pos<8; pos++)
+               {
+                 printf("(%d , %d):%d:%d | ", h_liste_positions[8*n + pos].x, h_liste_positions[8*n + pos].y,
+                                h_liste_positions[8*n + pos].z, h_liste_positions[8*n + pos].w);
+               }
+         printf("\n");
+       }
+#endif //DEBUG_POSITIONS
+
+//verif liste pixels noeuds pairs/impairs selon
+
+#ifdef DEBUG_LISTES
+  printf("NOMBRE PIXELS pour LISTE = %d\n", *h_nb_pix_max) ;
+  printf("bs = %d - grid = %d - nblocs_seg = %d - npix_max = %d - taille mem = %d\n",
+                bs, grid.x, nblocs_seg, *h_nb_pix_max, taille_mem);
+
+  cudaMemcpy( h_liste_pix, d_liste_pix, taille_mem*sizeof(uint2), cudaMemcpyDeviceToHost ) ;
+  cudaMemcpy( h_snake, *d_snake, nnodes*sizeof(snake_node_gpu), cudaMemcpyDeviceToHost );
+  uint32 * h_liste_pixels_segment = new uint32[2*(*h_nb_pix_max)] ;
+  int idx_n, idx_nprec, idx_nsuiv ;
+
+  printf("********* LISTE PIX  ***********\n");
+  printf("bs = %d - grid = %d - nblocs_seg = %d - npix_max = %d - taille mem = %d\n",
+                bs, grid.x, nblocs_seg, *h_nb_pix_max, taille_mem);
+  
+  for (int n=0; n<(nnodes/2 + (nnodes%2)*pairs); n++)
+       {
+         idx_n = 2*n + !pairs ;
+         if (idx_n == 0) idx_nprec = nnodes - 1;
+         else idx_nprec = idx_n - 1;
+         if (idx_n == nnodes-1) idx_nsuiv = 0;
+         else idx_nsuiv = idx_n + 1 ;
+               
+         for (int pos=0; pos < 8 ; pos++) //test des segments avant le noeud
+               {
+                 
+                 int nb_pix = calcul_liste_pixel_segment(h_snake[idx_nprec].posi,h_snake[idx_nprec].posj,
+                                                                                                 h_liste_positions[8*idx_n+pos].x, h_liste_positions[8*idx_n+pos].y,
+                                                                                                 h_liste_pixels_segment, 0);
+                 
+                 for (int pix=0; pix < nb_pix; pix++)
+                       {
+                         
+                         if ( (h_liste_pix[(16*n + pos)*nblocs_seg*bs + pix].x != h_liste_pixels_segment[2*pix] )
+                                  || ( h_liste_pix[(16*n + pos)*nblocs_seg*bs + pix].y != h_liste_pixels_segment[2*pix+1] ) )
+                               printf("erreur avant n=%d pix %d/%d segment %d noeuds[ %d-%d-%d ] , CPU (%d,%d) - GPU (%d, %d)\n", n, pix, nb_pix, pos,
+                                          idx_nprec, idx_n, idx_nsuiv,
+                                          h_liste_pixels_segment[2*pix], h_liste_pixels_segment[2*pix+1],
+                                          h_liste_pix[(16*n + pos)*nblocs_seg*bs + pix].x,  h_liste_pix[(16*n + pos)*nblocs_seg*bs + pix].y);
+                         
+                       }
+                 
+               }
+         for (int pos=0; pos < 8 ; pos++) //test des segments apres le noeud
+               {
+                 
+                 int nb_pix = calcul_liste_pixel_segment(h_liste_positions[8*idx_n+pos].x, h_liste_positions[8*idx_n+pos].y,
+                                                                                                 h_snake[idx_nsuiv].posi,h_snake[idx_nsuiv].posj,
+                                                                                                 h_liste_pixels_segment, 0);
+                 
+                 for (int pix=0; pix < nb_pix; pix++)
+                       {
+                         
+                         if ( (h_liste_pix[(16*n + pos + 8)*nblocs_seg*bs + pix].x != h_liste_pixels_segment[2*pix] )
+                            || ( h_liste_pix[(16*n + pos + 8)*nblocs_seg*bs + pix].y != h_liste_pixels_segment[2*pix+1] ) )
+                               printf("erreur apres n=%d pix %d/%d segment %d noeuds[ %d-%d-%d ] , CPU (%d,%d) - GPU (%d, %d)\n", n, pix, nb_pix, pos+8,
+                                          idx_nprec, idx_n, idx_nsuiv,
+                                          h_liste_pixels_segment[2*pix], h_liste_pixels_segment[2*pix+1],
+                                          h_liste_pix[(16*n + pos + 8)*nblocs_seg*bs + pix].x,  h_liste_pix[(16*n + pos + 8)*nblocs_seg*bs + pix].y);
+                         
+                       }
+                 
+               }
+               }
+  
+#endif //DEBUG_LISTES
+  
+  /*
+       
+       Test du calcul des sommes partielles 'somblocs' faites par le kernel 'calcul_contribs_segments_blocs_full'
+
+   */
+#ifdef DEBUG_SOMBLOCS
+  printf("********* SOMMES PARTIELLES  ***********\n");
+  printf("bs = %d - grid = %d -  intervalles = %d - nblocs_seg = %d - pairs = %d \n", bs, grid.x, n_interval, nblocs_seg, pairs);
+  for (int n=0; n< n_interval; n++)
+       {
+         idx_n = 2*n + !pairs ;
+         if (idx_n == 0) idx_nprec = nnodes - 1 ;
+         else idx_nprec = idx_n - 1 ;
+         if (idx_n == nnodes-1) idx_nsuiv = 0 ;
+         else idx_nsuiv = idx_n + 1 ;
+         printf("******** node %d\n", idx_n) ;
+         for(int s=0; s<8; s++)
+               {
+                 int nb_pix = calcul_liste_pixel_segment(h_snake[idx_nprec].posi,h_snake[idx_nprec].posj,
+                                                                                                 h_liste_positions[8*idx_n+s].x, h_liste_positions[8*idx_n+s].y,
+                                                                                                 h_liste_pixels_segment, 0);
+                 for (int b=0; b<nblocs_seg; b++)
+                       {
+                         uint64 c1=0, cx=0, cx2=0 ;
+                         int i,j;
+                         for (int p=0; p<bs; p++)
+                               {
+                                 if ( ((b*bs+p) < (nb_pix-1)) && ((b*bs+p)>0) )
+                                       {
+                                         //  /!\ penser a oter le test de prise en
+                                         // compte pour les pix sur la même ligne dans
+                                         // le kernel, sinon les comparaisons des
+                                         // sommes par colonne seront fausses
+                                         i = h_liste_pixels_segment[2*(b*bs + p)] ;
+                                         j = h_liste_pixels_segment[2*(b*bs + p) + 1] ;
+                                         c1 += img_1[i][j] ;
+                                         cx += img_x[i][j] ;
+                                         cx2+= img_x2[i][j];
+                                       }
+                               }
+                         if ( ( c1 != h_sombloc[(16*n + s)*nblocs_seg + b ] ) || ( cx != h_sombloc[(16*n + s)*nblocs_seg + b + grid.x] )
+                                  ||  ( cx2 != h_sombloc[ (16*n + s)*nblocs_seg + b + 2*grid.x] ) )
+                               printf("seg %d - %d pix : bloc %d -> CPU : %lu - %lu - %lu \t|| GPU : %lu - %lu - %lu \n", s, nb_pix, b,
+                                          c1, cx, cx2, h_sombloc[(16*n+s)*nblocs_seg + b], h_sombloc[(16*n+s)*nblocs_seg + b + grid.x],
+                                          h_sombloc[(16*n+s)*nblocs_seg + b + 2*grid.x]) ;    
+                       }
+                
+               }
+          for(int s=0; s<8; s++)
+               {
+                 int nb_pix = calcul_liste_pixel_segment( h_liste_positions[8*idx_n+s].x, h_liste_positions[8*idx_n+s].y,
+                                                                                                 h_snake[idx_nsuiv].posi,h_snake[idx_nsuiv].posj,
+                                                                                                 h_liste_pixels_segment, 0);
+                 for (int b=0; b<nblocs_seg; b++)
+                       {
+                         uint64 c1=0, cx=0, cx2=0 ;
+                         int i,j;
+                         for (int p=0; p<bs; p++)
+                               {
+                                 if ( ((b*bs+p) < (nb_pix-1)) && ((b*bs+p)>0) )
+                                       {
+                                         //  /!\ penser a oter le test de prise en
+                                         // compte pour les pix sur la même ligne dans
+                                         // le kernel, sinon les comparaisons des
+                                         // sommes par colonne seront fausses
+                                         i = h_liste_pixels_segment[2*(b*bs + p)] ;
+                                         j = h_liste_pixels_segment[2*(b*bs + p) + 1] ;
+                                         c1 += img_1[i][j] ;
+                                         cx += img_x[i][j] ;
+                                         cx2+= img_x2[i][j];
+                                       }
+                               }
+                         if ( ( c1 != h_sombloc[(16*n + s + 8)*nblocs_seg + b ] ) || ( cx != h_sombloc[(16*n + s + 8)*nblocs_seg + b + grid.x] )
+                                  ||  ( cx2 != h_sombloc[ (16*n + s + 8)*nblocs_seg + b + 2*grid.x] ) )
+                               printf("seg %d - %d pix : bloc %d -> CPU : %lu - %lu - %lu \t|| GPU : %lu - %lu - %lu \n", s, nb_pix, b,
+                                          c1, cx, cx2, h_sombloc[(16*n+s+8)*nblocs_seg + b], h_sombloc[(16*n+s+8)*nblocs_seg + b + grid.x],
+                                          h_sombloc[(16*n+s+8)*nblocs_seg + b + 2*grid.x]) ;    
+                       }
+                
+               }
+         
+       }
+#endif //DEBUG_SOMBLOCS
+
+ /*
+       
+       Test du calcul des sommes totales 'somsom' faites par le kernel 'somsom_full'
+
+   */
+
+#ifdef DEBUG_SOMSOM
+ printf("********* SOMMES TOTALES  ***********\n");
+  printf("bs = %d - grid = %d -  intervalles = %d - nblocs_seg = %d - pairs = %d \n", bs, grid.x, n_interval, nblocs_seg, pairs);
+  for (int n=0; n< n_interval; n++)
+       {
+         idx_n = 2*n + !pairs ;
+         if (idx_n == 0) idx_nprec = nnodes - 1 ;
+         else idx_nprec = idx_n - 1 ;
+         if (idx_n == nnodes-1) idx_nsuiv = 0 ;
+         else idx_nsuiv = idx_n + 1 ;
+         printf("******** node %d\n", idx_n) ;
+         for(int s=0; s<8; s++)
+               {
+                 int nb_pix = calcul_liste_pixel_segment(h_snake[idx_nprec].posi,h_snake[idx_nprec].posj,
+                                                                                                 h_liste_positions[8*idx_n+s].x, h_liste_positions[8*idx_n+s].y,
+                                                                                                 h_liste_pixels_segment, 0);
+                 uint64 c1=0, cx=0, cx2=0 ;
+                 for (int b=0; b<nblocs_seg; b++)
+                       {
+                         int i,j;
+                         for (int p=0; p<bs; p++)
+                               {
+                                 if ( ((b*bs+p) < (nb_pix-1)) && ((b*bs+p)>0) )
+                                       {
+                                         //  /!\ penser a oter le test de prise en
+                                         // compte pour les pix sur la même ligne dans
+                                         // le kernel, sinon les comparaisons des
+                                         // sommes par colonne seront fausses
+                                         i = h_liste_pixels_segment[2*(b*bs + p)] ;
+                                         j = h_liste_pixels_segment[2*(b*bs + p) + 1] ;
+                                         c1 += img_1[i][j] ;
+                                         cx += img_x[i][j] ;
+                                         cx2+= img_x2[i][j];
+                                       }
+                               }    
+                       }
+                 if ( ( c1 != h_somsom[3*(16*n + s)] ) || ( cx != h_somsom[3*(16*n + s) + 1] )
+                          ||  ( cx2 != h_somsom[3*(16*n + s) + 2] ) )
+                               printf("seg %d - %d pix -> CPU : %lu - %lu - %lu \t|| GPU : %lu - %lu - %lu \n", s, nb_pix, 
+                                          c1, cx, cx2, h_somsom[3*(16*n + s)], h_somsom[3*(16*n + s) + 1],
+                                          h_somsom[3*(16*n + s) + 2]) ;
+                
+               }
+         
+          for(int s=0; s<8; s++)
+               {
+                 int nb_pix = calcul_liste_pixel_segment( h_liste_positions[8*idx_n+s].x, h_liste_positions[8*idx_n+s].y,
+                                                                                                 h_snake[idx_nsuiv].posi,h_snake[idx_nsuiv].posj,
+                                                                                                  h_liste_pixels_segment, 0);
+                 uint64 c1=0, cx=0, cx2=0 ;
+                 for (int b=0; b<nblocs_seg; b++)
+                       {
+                         
+                         int i,j;
+                         for (int p=0; p<bs; p++)
+                               {
+                                 if ( ((b*bs+p) < (nb_pix-1)) && ((b*bs+p)>0) )
+                                       {
+                                         //  /!\ penser a oter le test de prise en
+                                         // compte pour les pix sur la même ligne dans
+                                         // le kernel, sinon les comparaisons des
+                                         // sommes par colonne seront fausses
+                                         i = h_liste_pixels_segment[2*(b*bs + p)] ;
+                                         j = h_liste_pixels_segment[2*(b*bs + p) + 1] ;
+                                         c1 += img_1[i][j] ;
+                                         cx += img_x[i][j] ;
+                                         cx2+= img_x2[i][j];
+                                       }
+                               }
+                       }
+                 if ( ( c1 != h_somsom[3*(16*n + s + 8)]  ) || ( cx != h_somsom[3*(16*n + s + 8) + 1] )
+                          ||  ( cx2 != h_somsom[3*(16*n + s + 8) + 2] ) )
+                       printf("seg %d - %d pix -> CPU : %lu - %lu - %lu \t|| GPU : %lu - %lu - %lu \n", s, nb_pix,
+                                  c1, cx, cx2, h_somsom[3*(16*n + s + 8)], h_somsom[3*(16*n + s + 8) + 1],
+                                  h_somsom[3*(16*n + s + 8)  + 2]) ;      
+                 
+               }
+         
+       }
+  
+#endif
+  
+#ifdef DEBUG_MV
+  printf("**** STATS - REF : %lf \n", *h_vrais_snake);
+  for(int n=0; n<n_interval; n++)
+       {
+         for(int p=0; p<8; p++)
+               {
+                 printf("test %d du node %d : %lu - %lu - %lu - - log_vrais = %lf\n", p, (2*n + !pairs),
+                                h_stats[3*(8*n+p)], h_stats[3*(8*n+p)+1], h_stats[3*(8*n+p)+2], h_vrais[8*n+p]);
+               }
+       }
+#endif //DEBUG_MV
+
+#ifdef DEBUG_CRST
+  printf("**** CROISEMENTS \n");
+  for(int n=0; n<nnodes; n++)
+       {
+         printf("test du seg %d : ",  n);
+         if ( h_croist[n] ) printf("CROISEMENT\n"); else printf("\n");
+       }
+#endif //DEBUG_CRST
+
+#ifdef DEBUG_MOVE
+  printf("**** MOUVEMENTS \n");
+  for(int n=0; n<nnodes; n++)
+       {
+         printf("Node %d : (%s) ",n, (h_move[n])? "yes":"no");
+       }
+#endif //DEBUG_MOVE
+  
+  delete h_liste_positions ;
+  delete h_snake;
+                                                                        
+  /*
+   * fin generation snake GPU
+   */ 
+}
+
+
diff --git a/src/lib_gpu.cu~ b/src/lib_gpu.cu~
new file mode 100644 (file)
index 0000000..6c5cc6f
--- /dev/null
@@ -0,0 +1,634 @@
+
+#include <stdio.h>
+
+
+extern "C"{
+#include "structures.h"
+#include "lib_math.h"
+#include "defines.h"
+#include "lib_gpu.h"
+#include "lib_snake_2_gpu.h"
+}
+#include "lib_test_gpu.h"
+#include "lib_kernels_cumuls.cu"
+#include "lib_kernel_snake_2_gpu.cu"
+
+#define DEBUG_IMG_CUMUL 1
+bool DISPLAY_ERR_IMG_CUMUL = 1;
+//#define DEBUG_POSITIONS
+//#define DEBUG_MOVE
+//#define DEBUG_CRST
+//#define DEBUG_MV
+//#define DEBUG_SOMSOM
+//#define DEBUG_SOMBLOCS
+//#define DEBUG_LISTES
+//#define DEBUG_STATS_REF
+
+
+inline unsigned int nextPow2( unsigned int x ) {
+  --x;
+  x |= x >> 1;
+  x |= x >> 2;
+  x |= x >> 4;
+  x |= x >> 8;
+  x |= x >> 16;
+  return ++x;
+}
+
+
+void cuda_init_img_cumul(unsigned short ** img_in, int H, int L, int nb_nodes,
+                                                unsigned short ** d_img, t_cumul_x ** d_img_x, t_cumul_x2 ** d_img_x2,
+                                                int ** d_freemanDiDj, int ** d_codeNoeud,
+                                                snake_node_gpu ** d_snake, uint32 ** d_nb_pix_max,
+                                                uint4 ** d_positions, uint64 ** d_contribs_segments, uint4 ** d_freemans_centres,
+                                                int ** d_codes_segments, int64 ** d_stats_snake,
+                                                int64 ** d_stats, int64 ** d_stats_ref, double ** d_vrais, double ** d_vrais_snake,
+                                                uint2 ** d_liste_pixels, uint64 ** d_contribs_segments_blocs,
+                                                bool ** d_move
+                                                )
+{
+  unsigned int taille = H*L;
+  timeval chrono;
+
+  
+  //allocation cumuls en memoire GPU
+  tic(&chrono, NULL);
+  /*
+       MAX_PIX 20000
+       MAX_NODES 10000
+       MAX_LISTE_PIX 10000000
+   */
+  cudaMalloc( (void**) d_snake, MAX_NODES*sizeof(snake_node_gpu) );
+  
+  cudaMalloc( (void**) d_img, taille*sizeof(unsigned short) );
+  cudaMalloc( (void**) d_img_x, taille*sizeof(t_cumul_x) );
+  cudaMalloc( (void**) d_img_x2, taille*sizeof(t_cumul_x2) );
+  cudaMalloc( (void**) d_freemanDiDj, 9*sizeof(int) );
+  cudaMalloc( (void**) d_codeNoeud, 64*sizeof(int) );
+  
+  cudaMalloc( (void**) d_stats_snake, 6*sizeof(int64)) ;
+  cudaMalloc( (void**) d_positions, 8*MAX_NODES*sizeof(uint4)) ;
+  cudaMalloc( (void**) d_contribs_segments, 3*16*MAX_NODES*sizeof(uint64)) ;
+  cudaMalloc( (void**) d_contribs_segments_blocs, (3*MAX_LISTE_PIX/32)*sizeof(uint64)) ;
+  cudaMalloc( (void**) d_freemans_centres, 16*MAX_NODES*sizeof(uint4)) ;
+  cudaMalloc( (void**) d_codes_segments, 16*MAX_NODES*sizeof(int)) ;
+  cudaMalloc( (void**) d_stats, 3*8*MAX_NODES*sizeof(int64)) ;
+  cudaMalloc( (void**) d_stats_ref, 3*MAX_NODES*sizeof(int64)) ;
+  cudaMalloc( (void**) d_vrais, 8*MAX_NODES*sizeof(double)) ;
+  cudaMalloc( (void**) d_move, MAX_NODES*sizeof(bool)) ;
+  cudaMalloc( (void**) d_nb_pix_max, sizeof(uint32)) ;
+  cudaMalloc( (void**) d_vrais_snake, sizeof(double)) ;
+  
+  cudaMalloc( (void**) d_liste_pixels, 16*5*(MAX_NODES)*sizeof(uint2) );
+  
+  printf("TOTAL MEM = %ld octets\n",
+                (2*MAX_NODES*(sizeof(snake_node_gpu)+(8+16)*sizeof(uint4)+3*16*8+16*4+24*8+3*8+8*sizeof(double)+sizeof(bool))
+                +(MAX_LISTE_PIX)*(sizeof(uint2)+1)
+                +taille*(8+sizeof(t_cumul_x)+sizeof(t_cumul_x2))
+                 +9*4+64*4+6*8+4+sizeof(double)) );
+           
+  int64 * h_stats_snake = new int64[6];
+  
+  toc(chrono, "temps alloc mem GPU");
+
+  /*detection-choix-initialisation de la carte GPU*/
+  tic(&chrono, NULL) ;
+  cudaDeviceProp deviceProp;
+  deviceProp.major = 1;
+  deviceProp.minor = 0;
+  int desiredMinorRevision = 3;
+  int dev;
+  cudaChooseDevice(&dev, &deviceProp);
+  cudaGetDeviceProperties(&deviceProp, dev);
+  if(deviceProp.major > 1 || deviceProp.minor >= desiredMinorRevision)
+       {
+         printf("Using Device %d: \"%s\"\n", dev, deviceProp.name);
+         cudaSetDevice(dev);
+       }
+  toc(chrono, "temps acces GPU") ;
+  
+  //copie tables correspondances freeman en mem GPU
+  tic(&chrono, NULL) ;
+  cudaMemcpy( *d_freemanDiDj, CORRESPONDANCE_Di_Dj_FREEMAN , 9*sizeof(int), cudaMemcpyHostToDevice);
+  cudaMemcpy( *d_codeNoeud, TABLE_CODAGE , 64*sizeof(unsigned int), cudaMemcpyHostToDevice);
+  toc(chrono, "temps transfert tables de codage") ;
+  
+  /*transfert image en global mem GPU*/
+  tic(&chrono, NULL);
+  cudaMemcpy( *d_img, img_in[0], taille*sizeof(unsigned short), cudaMemcpyHostToDevice);
+  toc(chrono, "transfert image vers GPU");
+
+  //calculs images cumulees sur GPU
+  int blocs_max = 65536 ;
+  int bs = 256 ; //arbitraire, d'apres les observations c'est souvent l'optimu
+  unsigned int base = 0 ;
+  unsigned int bl_l  = (L+bs-1)/bs ;
+  unsigned int nb_lines =  blocs_max / bl_l ;
+  unsigned int lines ;
+  unsigned int tranches = ( 1 + H / nb_lines ) ;
+  nb_lines = (H +tranches -1)/ tranches ; // equilibre la taille des tranches
+  unsigned blocs = bl_l*nb_lines ;
+  dim3 threads(bs,1,1);
+  int smem = nextPow2(bl_l)*2; //smem pour le prefixscan des sommes de blocs (etape 2)
+  smem += smem >> DEC;
+  smem += smem >> DEC;
+  int smem_size = smem*sizeof(uint64);
+  uint64 * d_somblocs ; // sommes des cumuls par bloc de calcul
+  
+
+  if(DEBUG_IMG_CUMUL)
+       {
+         printf("--- CALCULS IMAGES CUMULEES+STATS GPU  ----\n");
+         printf("\t%d threads par bloc  -- %u blocs par ligne -- %u tranches -- %u lignes par tranche \n",bs, bl_l, tranches,nb_lines);
+         printf(" Smem totale pour cumuls : %d\n", CFI(bs)*(sizeof(t_cumul_x)+sizeof(t_cumul_x2)) );
+         tic(&chrono, NULL);
+       }
+  //calculs cumuls generiques : necessitent 3 etapes / 3 kernels  
+  cudaMalloc( (void**) &d_somblocs, 2*bl_l*nb_lines*sizeof(uint64) );
+  cudaFuncSetCacheConfig(calcul_cumuls_gpu, cudaFuncCachePreferShared);
+  do
+       {
+         if  ( H-base < nb_lines ) lines = H - base ; else lines = nb_lines ;
+         printf("base = ligne %d -- traitement de %d lignes \n", base, lines) ;
+         dim3 grid(bl_l*lines,1,1) ;
+         calcul_cumuls_gpu<<<grid, threads, CFI(bs)*sizeof(tcumuls)>>>(*d_img, *d_img_x, *d_img_x2, H, L, d_somblocs, bl_l, base, lines) ;
+         scan_somblocs<<<2*lines, nextPow2(bl_l)/2, smem_size>>>(d_somblocs, bl_l) ;
+         add_soms_to_cumuls<<<grid, threads>>>(*d_img_x, *d_img_x2, H, L, d_somblocs, bl_l, base, lines) ;
+         base += lines ;
+       }
+  while (base < H) ;
+  cudaFree(d_somblocs) ;
+  
+  //calcul des sommes totales N, sigX et sigX2 sur l'image
+  calcul_stats_image<<<1, 1>>>( *d_img_x, *d_img_x2, H, L, (uint64*)*d_stats_snake);
+  
+  
+         cudaThreadSynchronize()   ;
+         toc(chrono, "\tTemps GPU");
+        if(DEBUG_IMG_CUMUL)
+       { 
+         
+         //allocation memoire CPU
+         t_cumul_x  * img_x = new t_cumul_x [H*L];
+         t_cumul_x2 *  img_x2 = new t_cumul_x2 [H*L];
+         
+         /*pour test comparaison*/
+         t_cumul_x * img_xb = new t_cumul_x [H*L];
+         t_cumul_x2 * img_x2b = new t_cumul_x2 [H*L];
+         
+         cudaMemcpy( img_xb, *d_img_x, taille*sizeof(t_cumul_x), cudaMemcpyDeviceToHost);
+         cudaMemcpy( img_x2b, *d_img_x2, taille*sizeof(t_cumul_x2), cudaMemcpyDeviceToHost);
+         
+         //cumuls : etape 1 CPU
+         /*      
+               for (int i=0; i<H; i++)
+               {
+                       for (int b=0; b<bl_l; b++)
+                       {
+                               int offset = b*bs ;
+                               img_x[i*L+offset] = img_in[i][offset] ;
+                               img_x2[i*L+offset]= img_in[i][offset]*img_in[i][offset] ;
+                               for (int p=1; p<bs; p++)
+                               {
+                                       int j = p+offset ;
+                                       if (j<L)
+                                       {
+                                               img_x[i*L+j] = img_x[i*L+j-1] + img_in[i][j];
+                                               img_x2[i*L+j] = img_x2[i*L+j-1] + img_in[i][j]*img_in[i][j] ;
+                                       }
+                               }
+                       }
+               }
+         */
+         //cumuls complets CPU
+          
+         for (int i=0; i<H; i++)
+               {
+                 img_x[i*L+0] = img_in[i][0] ;
+                 img_x2[i*L+0]= img_in[i][0]*img_in[i][0] ;
+                 for (int j=1; j<L; j++)
+                       {
+                         img_x[i*L+j]  = img_x[i*L+j-1]  + img_in[i][j] ;
+                         img_x2[i*L+j] = img_x2[i*L+j-1] + img_in[i][j]*img_in[i][j] ;
+                       }
+               }
+         
+         int cpt = 0;
+         int cpt_err1=0, cpt_errx=0, cpt_errx2 = 0;
+         for (int i=0; i< H; i++){
+               for (int j=0; j< L; j++){
+                 if ( (img_x[i*L+j] !=  img_xb[i*L+j]) ) cpt_errx++ ;
+                 if ( (img_x2[i*L+j] !=  img_x2b[i*L+j]) ) cpt_errx2++ ;
+                 if ( (img_x[i*L+j] !=  img_xb[i*L+j]) || (img_x2[i*L+j] !=  img_x2b[i*L+j]))
+                 {
+                       //printf("(%d,%d)sxCPU=%lu  sxGPU=%lu -- sx2CPU=%lu  sx2GPU=%lu\n",i,j,img_x[i*L+j], img_xb[i*L+j], img_x2[i*L+j], img_x2b[i*L+j]);
+                 }
+                 cpt++;
+               }
+         }
+         printf("%d erreurs sur CX / %d points\n", cpt_errx, cpt );
+         printf("%d erreurs sur CX2 / %d points\n", cpt_errx2, cpt );
+         uint64 sigX = 0, sigX2 = 0 ;
+         for (int i=0; i<H; i++)
+               {
+                 sigX += img_x[i*L+L-1] ;
+                 sigX2+= img_x2[i*L+L-1];
+               }
+         printf("STATS IMAGE  N = %d - sigX = %lu - sigX2 = %lu\n",  H*L, sigX, sigX2 );
+       }
+  
+  /*
+   * generation snake en mem GPU
+   */
+  int dist = 140 ;
+  
+  tic(&chrono, NULL);
+  if (nb_nodes == 4)  genere_snake_rectangle_4nodes_gpu<<< 1, 1>>>(*d_snake, 140, H, L) ;
+  else if (nb_nodes == 40) genere_snake_rectangle_Nnodes_gpu<<< 1, 1>>>(*d_snake, (H+L)/20, H, L) ;
+
+  int nnodes = nb_nodes ;
+  snake_node_gpu * h_snake = new snake_node_gpu[nnodes];
+  snake_node * h_snake_ll = new snake_node[nnodes] ;
+  uint4 * h_liste_positions = new uint4[nnodes*8]; 
+  double * h_vrais_snake = new double ;
+  //init les stats du snake
+  uint2 * d_liste_temp  ;
+  t_sum_x2 * d_sompart  ;
+  int tpb, bps, npixmax ;
+  //calcul nb threads par bloc
+  npixmax = 2*(H+L-4*dist)/(nnodes-1) ;
+  tpb = nextPow2(npixmax) ;
+  if (tpb >= 256) tpb = 256 ;//  /!\ le kernel <<< calcul_contrib...>>> ne supporte pas un bs>256 a cause de la shared-mem nécessaire
+  if (tpb < 32 ) tpb = 32 ;
+  tpb=128 ; 
+  bps = (npixmax+tpb-1)/tpb ;
+  printf("PARAMS EXEC INIT : %d pix max, %d threads/bloc, %d blocs/seg, %d blocs/grille\n", npixmax, tpb, bps, nnodes*bps);
+  //alloc
+  cudaMalloc((void**) &d_liste_temp, nnodes*bps*tpb*sizeof(uint2));
+  cudaMalloc((void**) &d_sompart, 3*nnodes*bps*sizeof(t_sum_x2));
+  cudaMalloc((void**) &d_stats_ref, 3*nnodes*sizeof(int64));
+
+  //DEBUG : pour forcer la mise à zero du tableau intermediaire d_stats_ref
+  int64 h_stats_ref[3*nnodes] ;
+  for (int a=0; a<3*nnodes ; a++) h_stats_ref[a] = 0 ;
+  cudaMemcpy( h_stats_ref, d_stats_ref, sizeof(int64), cudaMemcpyHostToDevice) ;
+  //fin forçage a 0
+  
+  //DEBUG : pour forcer la mise à zero du tableau intermediaire d_sompart
+     t_sum_x2 h_sompart[ 3*nnodes*bps ] ;
+     for (int a=0; a<3*nnodes*bps ; a++) h_sompart[a] = 0 ;
+     cudaMemcpy( h_sompart, d_sompart, sizeof(t_sum_x2), cudaMemcpyHostToDevice) ;
+  //fin forçage a 0
+  
+  calcul_contribs_segments_snake<<< nnodes*bps, tpb, (CFI(tpb))*(3*sizeof(t_sum_x2))>>>
+       (*d_snake, nnodes, 
+        *d_img_x, *d_img_x2, 
+        L, d_liste_temp, d_sompart, *d_freemanDiDj );
+
+  //TODO
+  //parametrer pour ne pas appeler qd tpb=1
+  //oblige a modifier le kernel <<< calcul_contrib...>>> pour ecrire directement ds d_snake
+  // au lieu de d_sompart
+  somsom_snake<<< nnodes , 1 >>>(d_sompart, nnodes, bps, *d_snake);
+  
+  
+  calcul_stats_snake<<< 1 , 1 >>>(*d_snake, nnodes, *d_stats_snake, *d_vrais_snake,
+                                                                 *d_img_x, *d_img_x2,
+                                                                 *d_codeNoeud, L
+                                                                 );
+  cudaThreadSynchronize() ;
+  toc(chrono, "\tTemps") ;
+  
+  /*
+       verif stats initiales du snake
+  */
+  cudaMemcpy( h_vrais_snake, *d_vrais_snake, sizeof(double), cudaMemcpyDeviceToHost) ; 
+  cudaMemcpy( h_stats_snake, *d_stats_snake, 6*sizeof(int64), cudaMemcpyDeviceToHost) ;
+  
+  printf("STATS SNAKE log vrais=%lf : c1=%lu - cx=%lu - cx2=%lu - N=%lu - SUMX=%lu - SUMX2=%lu\n",
+                *h_vrais_snake,
+                h_stats_snake[0],  h_stats_snake[1],  h_stats_snake[2],
+                h_stats_snake[3],  h_stats_snake[4],  h_stats_snake[5] );
+  
+  /*
+       verif stats diminuees des contribs des 2 segments associes a chaque noeud
+  */  
+#ifdef DEBUG_STATS_REF
+  cudaMemcpy( h_stats_ref, d_stats_ref, 3*nnodes*sizeof(int64), cudaMemcpyDeviceToHost) ;
+  cudaMemcpy( h_snake, *d_snake, nnodes*sizeof(snake_node_gpu), cudaMemcpyDeviceToHost) ;
+  
+       
+  printf("******* STATS DIMINUEES\n");
+  for(int n=0; n<nnodes;n++)
+       {
+         int i = h_snake[n].posi, j = h_snake[n].posj ;
+         printf("node %d (%d,%d) : %ld - %ld - %ld - img1= %lu - imgx= %lu - imgx2= %lu \n", n, i, j,
+                        h_stats_ref[3*n], h_stats_ref[3*n +1], h_stats_ref[3*n +2],
+                        img_1[i][j], img_x[i][j], img_x2[i][j]);
+       }
+#endif //DEBUG_STATS_REF
+  
+  //snake2gpu(d_snake, snake, nb_nodes);
+  //gpu2snake(*d_snake, &h_snake_ll, nnodes);
+
+#ifdef DEBUG_POSITIONS
+  for (int n=0; n<nnodes; n++)
+       {
+         printf("Node %d :\n", n);
+         for (int pos=0; pos<8; pos++)
+               {
+                 printf("(%d , %d):%d:%d | ", h_liste_positions[8*n + pos].x, h_liste_positions[8*n + pos].y,
+                                h_liste_positions[8*n + pos].z, h_liste_positions[8*n + pos].w);
+               }
+         printf("\n");
+       }
+#endif //DEBUG_POSITIONS
+
+//verif liste pixels noeuds pairs/impairs selon
+
+#ifdef DEBUG_LISTES
+  printf("NOMBRE PIXELS pour LISTE = %d\n", *h_nb_pix_max) ;
+  printf("bs = %d - grid = %d - nblocs_seg = %d - npix_max = %d - taille mem = %d\n",
+                bs, grid.x, nblocs_seg, *h_nb_pix_max, taille_mem);
+
+  cudaMemcpy( h_liste_pix, d_liste_pix, taille_mem*sizeof(uint2), cudaMemcpyDeviceToHost ) ;
+  cudaMemcpy( h_snake, *d_snake, nnodes*sizeof(snake_node_gpu), cudaMemcpyDeviceToHost );
+  uint32 * h_liste_pixels_segment = new uint32[2*(*h_nb_pix_max)] ;
+  int idx_n, idx_nprec, idx_nsuiv ;
+
+  printf("********* LISTE PIX  ***********\n");
+  printf("bs = %d - grid = %d - nblocs_seg = %d - npix_max = %d - taille mem = %d\n",
+                bs, grid.x, nblocs_seg, *h_nb_pix_max, taille_mem);
+  
+  for (int n=0; n<(nnodes/2 + (nnodes%2)*pairs); n++)
+       {
+         idx_n = 2*n + !pairs ;
+         if (idx_n == 0) idx_nprec = nnodes - 1;
+         else idx_nprec = idx_n - 1;
+         if (idx_n == nnodes-1) idx_nsuiv = 0;
+         else idx_nsuiv = idx_n + 1 ;
+               
+         for (int pos=0; pos < 8 ; pos++) //test des segments avant le noeud
+               {
+                 
+                 int nb_pix = calcul_liste_pixel_segment(h_snake[idx_nprec].posi,h_snake[idx_nprec].posj,
+                                                                                                 h_liste_positions[8*idx_n+pos].x, h_liste_positions[8*idx_n+pos].y,
+                                                                                                 h_liste_pixels_segment, 0);
+                 
+                 for (int pix=0; pix < nb_pix; pix++)
+                       {
+                         
+                         if ( (h_liste_pix[(16*n + pos)*nblocs_seg*bs + pix].x != h_liste_pixels_segment[2*pix] )
+                                  || ( h_liste_pix[(16*n + pos)*nblocs_seg*bs + pix].y != h_liste_pixels_segment[2*pix+1] ) )
+                               printf("erreur avant n=%d pix %d/%d segment %d noeuds[ %d-%d-%d ] , CPU (%d,%d) - GPU (%d, %d)\n", n, pix, nb_pix, pos,
+                                          idx_nprec, idx_n, idx_nsuiv,
+                                          h_liste_pixels_segment[2*pix], h_liste_pixels_segment[2*pix+1],
+                                          h_liste_pix[(16*n + pos)*nblocs_seg*bs + pix].x,  h_liste_pix[(16*n + pos)*nblocs_seg*bs + pix].y);
+                         
+                       }
+                 
+               }
+         for (int pos=0; pos < 8 ; pos++) //test des segments apres le noeud
+               {
+                 
+                 int nb_pix = calcul_liste_pixel_segment(h_liste_positions[8*idx_n+pos].x, h_liste_positions[8*idx_n+pos].y,
+                                                                                                 h_snake[idx_nsuiv].posi,h_snake[idx_nsuiv].posj,
+                                                                                                 h_liste_pixels_segment, 0);
+                 
+                 for (int pix=0; pix < nb_pix; pix++)
+                       {
+                         
+                         if ( (h_liste_pix[(16*n + pos + 8)*nblocs_seg*bs + pix].x != h_liste_pixels_segment[2*pix] )
+                            || ( h_liste_pix[(16*n + pos + 8)*nblocs_seg*bs + pix].y != h_liste_pixels_segment[2*pix+1] ) )
+                               printf("erreur apres n=%d pix %d/%d segment %d noeuds[ %d-%d-%d ] , CPU (%d,%d) - GPU (%d, %d)\n", n, pix, nb_pix, pos+8,
+                                          idx_nprec, idx_n, idx_nsuiv,
+                                          h_liste_pixels_segment[2*pix], h_liste_pixels_segment[2*pix+1],
+                                          h_liste_pix[(16*n + pos + 8)*nblocs_seg*bs + pix].x,  h_liste_pix[(16*n + pos + 8)*nblocs_seg*bs + pix].y);
+                         
+                       }
+                 
+               }
+               }
+  
+#endif //DEBUG_LISTES
+  
+  /*
+       
+       Test du calcul des sommes partielles 'somblocs' faites par le kernel 'calcul_contribs_segments_blocs_full'
+
+   */
+#ifdef DEBUG_SOMBLOCS
+  printf("********* SOMMES PARTIELLES  ***********\n");
+  printf("bs = %d - grid = %d -  intervalles = %d - nblocs_seg = %d - pairs = %d \n", bs, grid.x, n_interval, nblocs_seg, pairs);
+  for (int n=0; n< n_interval; n++)
+       {
+         idx_n = 2*n + !pairs ;
+         if (idx_n == 0) idx_nprec = nnodes - 1 ;
+         else idx_nprec = idx_n - 1 ;
+         if (idx_n == nnodes-1) idx_nsuiv = 0 ;
+         else idx_nsuiv = idx_n + 1 ;
+         printf("******** node %d\n", idx_n) ;
+         for(int s=0; s<8; s++)
+               {
+                 int nb_pix = calcul_liste_pixel_segment(h_snake[idx_nprec].posi,h_snake[idx_nprec].posj,
+                                                                                                 h_liste_positions[8*idx_n+s].x, h_liste_positions[8*idx_n+s].y,
+                                                                                                 h_liste_pixels_segment, 0);
+                 for (int b=0; b<nblocs_seg; b++)
+                       {
+                         uint64 c1=0, cx=0, cx2=0 ;
+                         int i,j;
+                         for (int p=0; p<bs; p++)
+                               {
+                                 if ( ((b*bs+p) < (nb_pix-1)) && ((b*bs+p)>0) )
+                                       {
+                                         //  /!\ penser a oter le test de prise en
+                                         // compte pour les pix sur la même ligne dans
+                                         // le kernel, sinon les comparaisons des
+                                         // sommes par colonne seront fausses
+                                         i = h_liste_pixels_segment[2*(b*bs + p)] ;
+                                         j = h_liste_pixels_segment[2*(b*bs + p) + 1] ;
+                                         c1 += img_1[i][j] ;
+                                         cx += img_x[i][j] ;
+                                         cx2+= img_x2[i][j];
+                                       }
+                               }
+                         if ( ( c1 != h_sombloc[(16*n + s)*nblocs_seg + b ] ) || ( cx != h_sombloc[(16*n + s)*nblocs_seg + b + grid.x] )
+                                  ||  ( cx2 != h_sombloc[ (16*n + s)*nblocs_seg + b + 2*grid.x] ) )
+                               printf("seg %d - %d pix : bloc %d -> CPU : %lu - %lu - %lu \t|| GPU : %lu - %lu - %lu \n", s, nb_pix, b,
+                                          c1, cx, cx2, h_sombloc[(16*n+s)*nblocs_seg + b], h_sombloc[(16*n+s)*nblocs_seg + b + grid.x],
+                                          h_sombloc[(16*n+s)*nblocs_seg + b + 2*grid.x]) ;    
+                       }
+                
+               }
+          for(int s=0; s<8; s++)
+               {
+                 int nb_pix = calcul_liste_pixel_segment( h_liste_positions[8*idx_n+s].x, h_liste_positions[8*idx_n+s].y,
+                                                                                                 h_snake[idx_nsuiv].posi,h_snake[idx_nsuiv].posj,
+                                                                                                 h_liste_pixels_segment, 0);
+                 for (int b=0; b<nblocs_seg; b++)
+                       {
+                         uint64 c1=0, cx=0, cx2=0 ;
+                         int i,j;
+                         for (int p=0; p<bs; p++)
+                               {
+                                 if ( ((b*bs+p) < (nb_pix-1)) && ((b*bs+p)>0) )
+                                       {
+                                         //  /!\ penser a oter le test de prise en
+                                         // compte pour les pix sur la même ligne dans
+                                         // le kernel, sinon les comparaisons des
+                                         // sommes par colonne seront fausses
+                                         i = h_liste_pixels_segment[2*(b*bs + p)] ;
+                                         j = h_liste_pixels_segment[2*(b*bs + p) + 1] ;
+                                         c1 += img_1[i][j] ;
+                                         cx += img_x[i][j] ;
+                                         cx2+= img_x2[i][j];
+                                       }
+                               }
+                         if ( ( c1 != h_sombloc[(16*n + s + 8)*nblocs_seg + b ] ) || ( cx != h_sombloc[(16*n + s + 8)*nblocs_seg + b + grid.x] )
+                                  ||  ( cx2 != h_sombloc[ (16*n + s + 8)*nblocs_seg + b + 2*grid.x] ) )
+                               printf("seg %d - %d pix : bloc %d -> CPU : %lu - %lu - %lu \t|| GPU : %lu - %lu - %lu \n", s, nb_pix, b,
+                                          c1, cx, cx2, h_sombloc[(16*n+s+8)*nblocs_seg + b], h_sombloc[(16*n+s+8)*nblocs_seg + b + grid.x],
+                                          h_sombloc[(16*n+s+8)*nblocs_seg + b + 2*grid.x]) ;    
+                       }
+                
+               }
+         
+       }
+#endif //DEBUG_SOMBLOCS
+
+ /*
+       
+       Test du calcul des sommes totales 'somsom' faites par le kernel 'somsom_full'
+
+   */
+
+#ifdef DEBUG_SOMSOM
+ printf("********* SOMMES TOTALES  ***********\n");
+  printf("bs = %d - grid = %d -  intervalles = %d - nblocs_seg = %d - pairs = %d \n", bs, grid.x, n_interval, nblocs_seg, pairs);
+  for (int n=0; n< n_interval; n++)
+       {
+         idx_n = 2*n + !pairs ;
+         if (idx_n == 0) idx_nprec = nnodes - 1 ;
+         else idx_nprec = idx_n - 1 ;
+         if (idx_n == nnodes-1) idx_nsuiv = 0 ;
+         else idx_nsuiv = idx_n + 1 ;
+         printf("******** node %d\n", idx_n) ;
+         for(int s=0; s<8; s++)
+               {
+                 int nb_pix = calcul_liste_pixel_segment(h_snake[idx_nprec].posi,h_snake[idx_nprec].posj,
+                                                                                                 h_liste_positions[8*idx_n+s].x, h_liste_positions[8*idx_n+s].y,
+                                                                                                 h_liste_pixels_segment, 0);
+                 uint64 c1=0, cx=0, cx2=0 ;
+                 for (int b=0; b<nblocs_seg; b++)
+                       {
+                         int i,j;
+                         for (int p=0; p<bs; p++)
+                               {
+                                 if ( ((b*bs+p) < (nb_pix-1)) && ((b*bs+p)>0) )
+                                       {
+                                         //  /!\ penser a oter le test de prise en
+                                         // compte pour les pix sur la même ligne dans
+                                         // le kernel, sinon les comparaisons des
+                                         // sommes par colonne seront fausses
+                                         i = h_liste_pixels_segment[2*(b*bs + p)] ;
+                                         j = h_liste_pixels_segment[2*(b*bs + p) + 1] ;
+                                         c1 += img_1[i][j] ;
+                                         cx += img_x[i][j] ;
+                                         cx2+= img_x2[i][j];
+                                       }
+                               }    
+                       }
+                 if ( ( c1 != h_somsom[3*(16*n + s)] ) || ( cx != h_somsom[3*(16*n + s) + 1] )
+                          ||  ( cx2 != h_somsom[3*(16*n + s) + 2] ) )
+                               printf("seg %d - %d pix -> CPU : %lu - %lu - %lu \t|| GPU : %lu - %lu - %lu \n", s, nb_pix, 
+                                          c1, cx, cx2, h_somsom[3*(16*n + s)], h_somsom[3*(16*n + s) + 1],
+                                          h_somsom[3*(16*n + s) + 2]) ;
+                
+               }
+         
+          for(int s=0; s<8; s++)
+               {
+                 int nb_pix = calcul_liste_pixel_segment( h_liste_positions[8*idx_n+s].x, h_liste_positions[8*idx_n+s].y,
+                                                                                                 h_snake[idx_nsuiv].posi,h_snake[idx_nsuiv].posj,
+                                                                                                  h_liste_pixels_segment, 0);
+                 uint64 c1=0, cx=0, cx2=0 ;
+                 for (int b=0; b<nblocs_seg; b++)
+                       {
+                         
+                         int i,j;
+                         for (int p=0; p<bs; p++)
+                               {
+                                 if ( ((b*bs+p) < (nb_pix-1)) && ((b*bs+p)>0) )
+                                       {
+                                         //  /!\ penser a oter le test de prise en
+                                         // compte pour les pix sur la même ligne dans
+                                         // le kernel, sinon les comparaisons des
+                                         // sommes par colonne seront fausses
+                                         i = h_liste_pixels_segment[2*(b*bs + p)] ;
+                                         j = h_liste_pixels_segment[2*(b*bs + p) + 1] ;
+                                         c1 += img_1[i][j] ;
+                                         cx += img_x[i][j] ;
+                                         cx2+= img_x2[i][j];
+                                       }
+                               }
+                       }
+                 if ( ( c1 != h_somsom[3*(16*n + s + 8)]  ) || ( cx != h_somsom[3*(16*n + s + 8) + 1] )
+                          ||  ( cx2 != h_somsom[3*(16*n + s + 8) + 2] ) )
+                       printf("seg %d - %d pix -> CPU : %lu - %lu - %lu \t|| GPU : %lu - %lu - %lu \n", s, nb_pix,
+                                  c1, cx, cx2, h_somsom[3*(16*n + s + 8)], h_somsom[3*(16*n + s + 8) + 1],
+                                  h_somsom[3*(16*n + s + 8)  + 2]) ;      
+                 
+               }
+         
+       }
+  
+#endif
+  
+#ifdef DEBUG_MV
+  printf("**** STATS - REF : %lf \n", *h_vrais_snake);
+  for(int n=0; n<n_interval; n++)
+       {
+         for(int p=0; p<8; p++)
+               {
+                 printf("test %d du node %d : %lu - %lu - %lu - - log_vrais = %lf\n", p, (2*n + !pairs),
+                                h_stats[3*(8*n+p)], h_stats[3*(8*n+p)+1], h_stats[3*(8*n+p)+2], h_vrais[8*n+p]);
+               }
+       }
+#endif //DEBUG_MV
+
+#ifdef DEBUG_CRST
+  printf("**** CROISEMENTS \n");
+  for(int n=0; n<nnodes; n++)
+       {
+         printf("test du seg %d : ",  n);
+         if ( h_croist[n] ) printf("CROISEMENT\n"); else printf("\n");
+       }
+#endif //DEBUG_CRST
+
+#ifdef DEBUG_MOVE
+  printf("**** MOUVEMENTS \n");
+  for(int n=0; n<nnodes; n++)
+       {
+         printf("Node %d : (%s) ",n, (h_move[n])? "yes":"no");
+       }
+#endif //DEBUG_MOVE
+  
+  delete h_liste_positions ;
+  delete h_snake;
+                                                                        
+  /*
+   * fin generation snake GPU
+   */ 
+}
+
+
diff --git a/src/lib_gpu.h b/src/lib_gpu.h
new file mode 100644 (file)
index 0000000..8cda947
--- /dev/null
@@ -0,0 +1,29 @@
+#ifndef _LIB_GPU_H_
+#define _LIB_GPU_H_
+
+inline unsigned int nextPow2( unsigned int x ) {
+  --x;
+  x |= x >> 1;
+  x |= x >> 2;
+  x |= x >> 4;
+  x |= x >> 8;
+  x |= x >> 16;
+  return ++x;
+}
+
+
+void cuda_init_img_cumul(unsigned short ** img_in, int H, int L, int nb_nodes,
+                                                unsigned short ** d_img, t_cumul_x ** d_img_x, t_cumul_x2 ** d_img_x2,
+                                                int ** d_freemanDiDj, int ** d_codeNoeud,
+                                                snake_node_gpu ** d_snake, uint32 ** d_nb_pix_max,
+                                                uint4 ** d_positions, uint64 ** d_contribs_segments, uint4 ** d_freemans_centres,
+                                                int ** d_codes_segments, int64 ** d_stats_snake,
+                                                int64 ** d_stats, int64 ** d_stats_ref, double ** d_vrais, double ** d_vrais_snake,
+                                                uint2 ** d_liste_pixels, uint64 ** d_contribs_segments_blocs,
+                                                bool ** d_move
+                                                );
+
+void affiche_snake_gpu(int **image, snake_node_gpu *snake, int nnodes_, int valseg, int valnoeud,
+                                          uint32 *liste_pixel_segment);
+
+#endif //_LIB_GPU_H_
diff --git a/src/lib_gpu.h~ b/src/lib_gpu.h~
new file mode 100644 (file)
index 0000000..9cfb894
--- /dev/null
@@ -0,0 +1,20 @@
+#ifndef _LIB_GPU_H_
+#define _LIB_GPU_H_
+
+inline unsigned int nextPow2( unsigned int x );
+
+void cuda_init_img_cumul(unsigned short ** img_in, int H, int L, int nb_nodes,
+                                                unsigned short ** d_img, t_cumul_x ** d_img_x, t_cumul_x2 ** d_img_x2,
+                                                int ** d_freemanDiDj, int ** d_codeNoeud,
+                                                snake_node_gpu ** d_snake, uint32 ** d_nb_pix_max,
+                                                uint4 ** d_positions, uint64 ** d_contribs_segments, uint4 ** d_freemans_centres,
+                                                int ** d_codes_segments, int64 ** d_stats_snake,
+                                                int64 ** d_stats, int64 ** d_stats_ref, double ** d_vrais, double ** d_vrais_snake,
+                                                uint2 ** d_liste_pixels, uint64 ** d_contribs_segments_blocs,
+                                                bool ** d_move
+                                                );
+
+void affiche_snake_gpu(int **image, snake_node_gpu *snake, int nnodes_, int valseg, int valnoeud,
+                                          uint32 *liste_pixel_segment);
+
+#endif //_LIB_GPU_H_
diff --git a/src/lib_images.c b/src/lib_images.c
new file mode 100644 (file)
index 0000000..0aaf81e
--- /dev/null
@@ -0,0 +1,305 @@
+/**
+ * \file lib_images.c
+ * \brief Librairie de lecture/ecriture d'image ppm/pgm 8/16 bits
+ * \author NB - PhyTI 
+ * \version x.x
+ * \date 20 decembre 2009
+ *
+ */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <malloc.h>
+#include <unistd.h>
+
+#include "lib_images.h"
+#include "lib_math.h"
+
+
+/**
+ * \fn int type_image_ppm(int *prof, int *i_dim, int *j_dim, int *level, char *file_name)
+ * \brief Fonction qui renvoie le type de l'image ppm et des caracteristiques
+ *
+ * \param[out] prof profondeur de l'image 1 pour pgm 3 pour ppm, 0 sinon
+ * \param[out] i_dim renvoie la dimension verticale de l'image (si NULL, renvoie que prof)
+ * \param[out] j_dim renvoie la dimension horizontale de l'image
+ * \param[out] level renvoie la dynamique de l'image
+ * \param[in]  file_name fichier image
+ *
+ * \return 1 si ok O sinon
+ *
+ */
+int type_image_ppm(int *prof, uint32 *i_dim, uint32 *j_dim, int *level, char *file_name)
+{
+  char buffer[SIZE_LINE_TEXT] ;
+  FILE *file ;
+
+  *prof = 0 ;
+  file = fopen(file_name, "rb");
+  if (file == NULL) 
+      return 0 ;
+  // lecture de la premiere ligne
+  fgets(buffer, SIZE_LINE_TEXT, file);
+  /* pgm */
+  if ((buffer[0] == 'P') & (buffer[1] == '5'))
+    *prof = 1 ; // GGG
+  /* ppm */
+  if ((buffer[0] == 'P') & (buffer[1] == '6'))
+    *prof = 3 ; // RVBRVBRVB
+
+  /* type non gere */
+  if (*prof == 0) return 0 ;
+
+  /* pour une utilisation du type */
+  /* ret = type_image_ppm(&prof, NULL, NULL, NULL, file_name) */
+  if (i_dim == NULL)  
+    return 1 ;
+
+  /* on saute les lignes de commentaires */
+  fgets(buffer, SIZE_LINE_TEXT, file);
+  while ((buffer[0] == '#')|(buffer[0] == '\n')) 
+    fgets(buffer, SIZE_LINE_TEXT, file);
+  
+  /* on lit les dimensions de l'image */
+  sscanf(buffer, "%d %d", j_dim, i_dim) ;
+  fgets(buffer, SIZE_LINE_TEXT, file);
+  sscanf(buffer, "%d", level) ;
+  
+
+  fclose(file);
+  return 1 ;
+}
+
+
+
+
+/**
+ * \fn void load_pgm2int(int **image, int i_dim, int j_dim, 
+ *                      int nb_level, char *fichier_image)
+ * \brief lecture pgm 8 ou 16 bits
+ *
+ * \param[out] image 
+ * \param[in]  i_dim dimension verticale de l'image
+ * \param[in]  j_dim dimension horizontale de l'image
+ * \param[in]  nb_level dynamique de l'image
+ * \param[in]  fichier_image fichier image
+ *
+ *
+ */
+void load_pgm2int(int **image, int i_dim, int j_dim, 
+                 int nb_level, char *fichier_image)
+{
+  int i, j ;
+  char buffer[SIZE_LINE_TEXT] ;
+  unsigned char *ligne;
+  unsigned short *ligne2;
+  FILE *file = fopen(fichier_image, "rb");
+  
+  fgets(buffer, SIZE_LINE_TEXT, file); /* P5 */
+  /* on saute les lignes de commentaires */
+  fgets(buffer, SIZE_LINE_TEXT, file);
+  while ((buffer[0] == '#')|(buffer[0] == '\n')) 
+    fgets(buffer, SIZE_LINE_TEXT, file);
+  /* derniere ligne lue : dimensions */
+  fgets(buffer, SIZE_LINE_TEXT, file); /* dynamique */
+
+  /* data */
+
+  if (nb_level < 256)
+    {
+      // fichier en char, on converti au format int
+      ligne = malloc(sizeof(unsigned char)*j_dim) ;
+      
+      for (i=0;i<i_dim;i++)
+       {
+         fread(ligne, 1, j_dim, file);
+         for (j=0;j<j_dim;j++)    
+           image[i][j] = (int)(ligne[j]) ; 
+       }
+      free(ligne) ;
+    }
+  else
+    {
+      // fichier en short, on converti au format int
+      ligne2 = malloc(sizeof(unsigned short)*j_dim) ;
+      
+      for (i=0;i<i_dim;i++)
+       {
+         fread(ligne2, 2, j_dim, file);
+         for (j=0;j<j_dim;j++)    
+           image[i][j] = (int)(ligne2[j]) ; 
+       }
+      free(ligne2);
+    }  
+  fclose(file);
+}
+
+
+void load_pgm2ushort(unsigned short **image, int i_dim, int j_dim, 
+                                        int nb_level, char *fichier_image)
+{
+  int i, j ;
+  char buffer[SIZE_LINE_TEXT] ;
+  unsigned char *ligne;
+  unsigned short *ligne2;
+  FILE *file = fopen(fichier_image, "rb");
+  
+  fgets(buffer, SIZE_LINE_TEXT, file); /* P5 */
+  /* on saute les lignes de commentaires */
+  fgets(buffer, SIZE_LINE_TEXT, file);
+  while ((buffer[0] == '#')|(buffer[0] == '\n')) 
+    fgets(buffer, SIZE_LINE_TEXT, file);
+  /* derniere ligne lue : dimensions */
+  fgets(buffer, SIZE_LINE_TEXT, file); /* dynamique */
+
+  /* data */
+
+  if (nb_level < 256)
+    {
+      // fichier en char, on converti au format ushort
+      ligne = malloc(sizeof(unsigned char)*j_dim) ;
+      
+      for (i=0;i<i_dim;i++)
+       {
+         fread(ligne, 1, j_dim, file);
+         for (j=0;j<j_dim;j++)    
+           image[i][j] = (unsigned short)(ligne[j]) ; 
+       }
+      free(ligne) ;
+    }
+  else
+    {
+      // fichier en short,
+      ligne2 = malloc(sizeof(unsigned short)*j_dim) ;
+      
+      for (i=0;i<i_dim;i++)
+       {
+         fread(ligne2, 2, j_dim, file);
+         for (j=0;j<j_dim;j++)    
+           image[i][j] = (unsigned short)(ligne2[j]) ; 
+       }
+      free(ligne2);
+    }  
+  fclose(file);
+}
+
+
+
+/**
+ * \fn void write_int2pgm(int **image, int i_dim, int j_dim, char *fichier_image, int recal)
+ * \brief copie au format pgm 8 bits
+ *
+ * \param[in]  image 
+ * \param[in]  i_dim dimension verticale de l'image
+ * \param[in]  j_dim dimension horizontale de l'image
+ * \param[in]  fichier_image fichier image
+ * \param[in]  recal recalage de l'image en 0-255
+ *
+ */
+void write_int2pgm(int **image, int i_dim, int j_dim, char *fichier_image, int recal)
+{
+  int i, j ;
+  int val_min, val_max ; 
+  double coef ;
+  unsigned char *ligne;
+  FILE *file=fopen(fichier_image,"wb");
+
+  // entete pgm
+  // format
+  fprintf(file, "P5\n") ;
+  fprintf(file, "# Physics and Images Processing Group\n") ;
+  fprintf(file, "# Fresnel Institut - Marseille - France\n") ;
+  // taille
+  fprintf(file, "%d %d\n", j_dim, i_dim) ;
+  // dynamique
+  fprintf(file, "%d\n" , 255 );
+  
+  min_max_int1d(&val_min, &val_max, image[0], i_dim*j_dim) ;
+  coef = 255.0 / (val_max - val_min) ;
+  
+  // on converti l'image en entier 8 bits (char)
+  ligne = malloc(sizeof(unsigned char)*j_dim );
+  for (i=0;i<i_dim;i++) 
+    {
+      if (recal == 1)
+       for (j=0;j<j_dim;j++) ligne[j] = (unsigned char)(coef * (image[i][j]-val_min)) ;
+      else
+       for (j=0;j<j_dim;j++) ligne[j] = (unsigned char)image[i][j] ;
+      fwrite(ligne, 1, j_dim, file);
+    }
+
+  fclose(file);
+  free(ligne) ;
+}
+
+void write_ushort2pgm(unsigned short **image, int i_dim, int j_dim, char *fichier_image, int recal)
+{
+  int i, j ;
+  int val_min, val_max ; 
+  double coef ;
+  unsigned char *ligne;
+  FILE *file=fopen(fichier_image,"wb");
+
+  // entete pgm
+  // format
+  fprintf(file, "P5\n") ;
+  fprintf(file, "# Physics and Images Processing Group\n") ;
+  fprintf(file, "# Fresnel Institute - Marseille - France\n") ;
+  // taille
+  fprintf(file, "%d %d\n", j_dim, i_dim) ;
+  // dynamique
+  fprintf(file, "%d\n" , 255 );
+  
+  min_max_ushort1d(&val_min, &val_max, image[0], i_dim*j_dim) ;
+  coef = 255.0 / (val_max - val_min) ;
+  
+  // on converti l'image en entier 8 bits (char)
+  ligne = malloc(sizeof(unsigned char)*j_dim );
+  for (i=0;i<i_dim;i++) 
+    {
+      if (recal == 1)
+       for (j=0;j<j_dim;j++) ligne[j] = (unsigned char)(coef * (image[i][j]-val_min)) ;
+      else
+       for (j=0;j<j_dim;j++) ligne[j] = (unsigned char)image[i][j] ;
+      fwrite(ligne, 1, j_dim, file);
+    }
+
+  fclose(file);
+  free(ligne) ;
+}
+
+
+/**
+ * \fn void imagesc(int **image, int i_dim, int j_dim)
+ * \brief affiche une image via xti
+ *
+ * \param[in]  image 
+ * \param[in]  i_dim dimension verticale de l'image
+ * \param[in]  j_dim dimension horizontale de l'image
+ *
+ */
+void imagesc(int **image, int i_dim, int j_dim)
+{
+  char nom[SIZE_NAME_FILE] ;
+  //char cmd[SIZE_LINE_TEXT] ;
+
+  sprintf(nom, "imagesc_%d.pgm", getuid());
+  write_int2pgm(image, i_dim, j_dim, nom, 1) ;
+
+  // affichage avec xti
+  //sprintf(cmd, "xti %s &", nom) ;
+  //system(cmd) ;
+}
+
+void imagesc_ushort(unsigned short **image, int i_dim, int j_dim)
+{
+  char nom[SIZE_NAME_FILE] ;
+  //char cmd[SIZE_LINE_TEXT] ;
+
+  sprintf(nom, "imagesc_%d.pgm", getuid());
+  write_ushort2pgm(image, i_dim, j_dim, nom, 1) ;
+  
+}
diff --git a/src/lib_images.c~ b/src/lib_images.c~
new file mode 100644 (file)
index 0000000..f1412a0
--- /dev/null
@@ -0,0 +1,211 @@
+/**
+ * \file lib_images.c
+ * \brief Librairie de lecture/ecriture d'image ppm/pgm 8/16 bits
+ * \author NB - PhyTI 
+ * \version x.x
+ * \date 20 decembre 2009
+ *
+ */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <malloc.h>
+#include <unistd.h>
+
+#include "lib_images.h"
+#include "lib_math.h"
+
+
+/**
+ * \fn int type_image_ppm(int *prof, int *i_dim, int *j_dim, int *level, char *file_name)
+ * \brief Fonction qui renvoie le type de l'image ppm et des caracteristiques
+ *
+ * \param[out] prof profondeur de l'image 1 pour pgm 3 pour ppm, 0 sinon
+ * \param[out] i_dim renvoie la dimension verticale de l'image (si NULL, renvoie que prof)
+ * \param[out] j_dim renvoie la dimension horizontale de l'image
+ * \param[out] level renvoie la dynamique de l'image
+ * \param[in]  file_name fichier image
+ *
+ * \return 1 si ok O sinon
+ *
+ */
+int type_image_ppm(int *prof, uint32 *i_dim, uint32 *j_dim, int *level, char *file_name)
+{
+  char buffer[SIZE_LINE_TEXT] ;
+  FILE *file ;
+
+  *prof = 0 ;
+  file = fopen(file_name, "rb");
+  if (file == NULL) 
+      return 0 ;
+  // lecture de la premiere ligne
+  fgets(buffer, SIZE_LINE_TEXT, file);
+  /* pgm */
+  if ((buffer[0] == 'P') & (buffer[1] == '5'))
+    *prof = 1 ; // GGG
+  /* ppm */
+  if ((buffer[0] == 'P') & (buffer[1] == '6'))
+    *prof = 3 ; // RVBRVBRVB
+
+  /* type non gere */
+  if (*prof == 0) return 0 ;
+
+  /* pour une utilisation du type */
+  /* ret = type_image_ppm(&prof, NULL, NULL, NULL, file_name) */
+  if (i_dim == NULL)  
+    return 1 ;
+
+  /* on saute les lignes de commentaires */
+  fgets(buffer, SIZE_LINE_TEXT, file);
+  while ((buffer[0] == '#')|(buffer[0] == '\n')) 
+    fgets(buffer, SIZE_LINE_TEXT, file);
+  
+  /* on lit les dimensions de l'image */
+  sscanf(buffer, "%d %d", j_dim, i_dim) ;
+  fgets(buffer, SIZE_LINE_TEXT, file);
+  sscanf(buffer, "%d", level) ;
+  
+
+  fclose(file);
+  return 1 ;
+}
+
+
+
+
+/**
+ * \fn void load_pgm2int(int **image, int i_dim, int j_dim, 
+ *                      int nb_level, char *fichier_image)
+ * \brief lecture pgm 8 ou 16 bits
+ *
+ * \param[out] image 
+ * \param[in]  i_dim dimension verticale de l'image
+ * \param[in]  j_dim dimension horizontale de l'image
+ * \param[in]  nb_level dynamique de l'image
+ * \param[in]  fichier_image fichier image
+ *
+ *
+ */
+void load_pgm2int(int **image, int i_dim, int j_dim, 
+                 int nb_level, char *fichier_image)
+{
+  int i, j ;
+  char buffer[SIZE_LINE_TEXT] ;
+  unsigned char *ligne;
+  unsigned short *ligne2;
+  FILE *file = fopen(fichier_image, "rb");
+  
+  fgets(buffer, SIZE_LINE_TEXT, file); /* P5 */
+  /* on saute les lignes de commentaires */
+  fgets(buffer, SIZE_LINE_TEXT, file);
+  while ((buffer[0] == '#')|(buffer[0] == '\n')) 
+    fgets(buffer, SIZE_LINE_TEXT, file);
+  /* derniere ligne lue : dimensions */
+  fgets(buffer, SIZE_LINE_TEXT, file); /* dynamique */
+
+  /* data */
+
+  if (nb_level < 256)
+    {
+      // fichier en char, on converti au format int
+      ligne = malloc(sizeof(unsigned char)*j_dim) ;
+      
+      for (i=0;i<i_dim;i++)
+       {
+         fread(ligne, 1, j_dim, file);
+         for (j=0;j<j_dim;j++)    
+           image[i][j] = (int)(ligne[j]) ; 
+       }
+      free(ligne) ;
+    }
+  else
+    {
+      // fichier en short, on converti au format int
+      ligne2 = malloc(sizeof(unsigned short)*j_dim) ;
+      
+      for (i=0;i<i_dim;i++)
+       {
+         fread(ligne2, 2, j_dim, file);
+         for (j=0;j<j_dim;j++)    
+           image[i][j] = (int)(ligne2[j]) ; 
+       }
+      free(ligne2);
+    }  
+  fclose(file);
+}
+
+
+
+/**
+ * \fn void write_int2pgm(int **image, int i_dim, int j_dim, char *fichier_image, int recal)
+ * \brief copie au format pgm 8 bits
+ *
+ * \param[in]  image 
+ * \param[in]  i_dim dimension verticale de l'image
+ * \param[in]  j_dim dimension horizontale de l'image
+ * \param[in]  fichier_image fichier image
+ * \param[in]  recal recalage de l'image en 0-255
+ *
+ */
+void write_int2pgm(int **image, int i_dim, int j_dim, char *fichier_image, int recal)
+{
+  int i, j ;
+  int val_min, val_max ; 
+  double coef ;
+  unsigned char *ligne;
+  FILE *file=fopen(fichier_image,"wb");
+
+  // entete pgm
+  // format
+  fprintf(file, "P5\n") ;
+  fprintf(file, "# Physics and Images Processing Group\n") ;
+  fprintf(file, "# Fresnel Institut - Marseille - France\n") ;
+  // taille
+  fprintf(file, "%d %d\n", j_dim, i_dim) ;
+  // dynamique
+  fprintf(file, "%d\n" , 255 );
+  
+  min_max_int1d(&val_min, &val_max, image[0], i_dim*j_dim) ;
+  coef = 255.0 / (val_max - val_min) ;
+  
+  // on converti l'image en entier 8 bits (char)
+  ligne = malloc(sizeof(unsigned char)*j_dim );
+  for (i=0;i<i_dim;i++) 
+    {
+      if (recal == 1)
+       for (j=0;j<j_dim;j++) ligne[j] = (unsigned char)(coef * (image[i][j]-val_min)) ;
+      else
+       for (j=0;j<j_dim;j++) ligne[j] = (unsigned char)image[i][j] ;
+      fwrite(ligne, 1, j_dim, file);
+    }
+
+  fclose(file);
+  free(ligne) ;
+}
+
+
+
+/**
+ * \fn void imagesc(int **image, int i_dim, int j_dim)
+ * \brief affiche une image via xti
+ *
+ * \param[in]  image 
+ * \param[in]  i_dim dimension verticale de l'image
+ * \param[in]  j_dim dimension horizontale de l'image
+ *
+ */
+void imagesc(int **image, int i_dim, int j_dim)
+{
+  char nom[SIZE_NAME_FILE] ;
+  //char cmd[SIZE_LINE_TEXT] ;
+
+  sprintf(nom, "imagesc_%d_%d.pgm", getuid(), rand()%20);
+  write_int2pgm(image, i_dim, j_dim, nom, 1) ;
+
+  // affichage avec xti
+  //sprintf(cmd, "xti %s &", nom) ;
+  //system(cmd) ;
+}
diff --git a/src/lib_images.h b/src/lib_images.h
new file mode 100644 (file)
index 0000000..485c33f
--- /dev/null
@@ -0,0 +1,11 @@
+#include "constantes.h"
+#include "structures.h"
+
+int type_image_ppm(int *prof, uint32 *i_dim, uint32 *j_dim, int *level, char *file_name) ;
+void load_pgm2int(int **image, int i_dim, int j_dim, int nb_level, char *fichier_image) ;
+void load_pgm2ushort(unsigned short **image, int i_dim, int j_dim, int nb_level, char *fichier_image) ;
+
+void write_int2pgm(int **image, int i_dim, int j_dim, char *fichier_image, int recal) ;
+void write_ushort2pgm(unsigned short **image, int i_dim, int j_dim, char *fichier_image, int recal) ;
+void imagesc(int **image, int i_dim, int j_dim) ;
+void imagesc_ushort(unsigned short **image, int i_dim, int j_dim) ;
diff --git a/src/lib_images.h~ b/src/lib_images.h~
new file mode 100644 (file)
index 0000000..60244e7
--- /dev/null
@@ -0,0 +1,8 @@
+#include "constantes.h"
+#include "structures.h"
+
+int type_image_ppm(int *prof, uint32 *i_dim, uint32 *j_dim, int *level, char *file_name) ;
+void load_pgm2int(int **image, int i_dim, int j_dim, int nb_level, char *fichier_image) ;
+
+void write_int2pgm(int **image, int i_dim, int j_dim, char *fichier_image, int recal) ;
+void imagesc(int **image, int i_dim, int j_dim) ;
diff --git a/src/lib_kernel_snake_2_gpu.cu b/src/lib_kernel_snake_2_gpu.cu
new file mode 100644 (file)
index 0000000..8d819a8
--- /dev/null
@@ -0,0 +1,447 @@
+
+
+__global__ void genere_snake_rectangle_4nodes_gpu(snake_node_gpu * d_snake, int dist_bords, int i_dim, int j_dim){
+  if (threadIdx.x == 0){
+       int n = 0;
+       /* n0 */
+       d_snake[n].posi = dist_bords ;
+       d_snake[n].posj = dist_bords ;
+       n++ ;
+       /* n1 */
+       d_snake[n].posi = i_dim - dist_bords ;
+       d_snake[n].posj = dist_bords ; 
+       n++ ;
+       /* n2 */
+       d_snake[n].posi = i_dim - dist_bords ;
+       d_snake[n].posj = j_dim - dist_bords ; 
+       n++ ;
+       /* n3 */
+       d_snake[n].posi = dist_bords ;
+       d_snake[n].posj = j_dim - dist_bords ;
+
+       for (int i=0; i<4; i++)
+         {
+               d_snake[i].freeman_in = 0;
+               d_snake[i].freeman_out = 0;
+               d_snake[i].centre_i = 0;
+               d_snake[i].centre_j = 0;
+               d_snake[i].last_move = 0;
+               d_snake[i].nb_pixels = 123;
+               d_snake[i].code_segment = 0;
+               
+         }
+  }
+}
+
+
+__global__ void genere_snake_rectangle_Nnodes_gpu(snake_node_gpu * d_snake, int dist_bords, int i_dim, int j_dim){
+  int nb_node_seg = 9 ;
+  int limite = 64 ;
+  
+  int i , h= i_dim-2*dist_bords, l= j_dim-2*dist_bords ;
+  int inch = h/(nb_node_seg+1), incl= l/(nb_node_seg+1) ;
+  if (threadIdx.x == 0){
+       int n = 0;
+       /* n0 */
+       d_snake[n].posi = dist_bords ;
+       d_snake[n].posj = dist_bords ;
+       n++ ;
+       /*entre sommet 0 et 1*/
+       i = 0 ;
+       while (i < nb_node_seg)
+         {
+               if ( (d_snake[n-1].posi + inch)-(i_dim - dist_bords) > limite )
+                 d_snake[n].posi = d_snake[n-1].posi + inch ;
+               else
+                 d_snake[n].posi = d_snake[n-1].posi + inch/2 ;
+               d_snake[n].posj = dist_bords ;
+               d_snake[n-1].nb_pixels =  d_snake[n].posi -  d_snake[n-1].posi ;
+               n++ ; i++ ;
+         }
+       /* n1 */
+       d_snake[n].posi = i_dim - dist_bords ;
+       d_snake[n].posj = dist_bords ;
+       d_snake[n-1].nb_pixels =  d_snake[n].posi -  d_snake[n-1].posi ;
+       n++ ;
+       /*entre S1 et S2*/
+       i = 0 ; 
+       while (i< nb_node_seg)
+         {
+               if ( (j_dim - dist_bords) - (d_snake[n-1].posj + incl) > limite )
+                 d_snake[n].posj = d_snake[n-1].posj + incl ;
+               else
+                 d_snake[n].posj = d_snake[n-1].posj + incl/2 ;
+               d_snake[n].posi = i_dim - dist_bords ;
+               d_snake[n-1].nb_pixels =  d_snake[n].posj -  d_snake[n-1].posj ;
+               n++ ; i++ ;
+         }
+       /* n2 */
+       d_snake[n].posi = i_dim - dist_bords ;
+       d_snake[n].posj = j_dim - dist_bords ;
+       d_snake[n-1].nb_pixels =  d_snake[n].posj -  d_snake[n-1].posj ;
+       n++ ;
+       /*entre S2 et S3*/
+       i = 0 ;
+       while (i< nb_node_seg)
+         {
+               if ( (d_snake[n-1].posi - inch) - dist_bords > limite )
+                 d_snake[n].posi = d_snake[n-1].posi - inch ;
+               else
+                 d_snake[n].posi = d_snake[n-1].posi - inch/2 ;
+               d_snake[n].posj = j_dim - dist_bords ;
+               d_snake[n-1].nb_pixels =  d_snake[n-1].posi -  d_snake[n].posi ;
+               n++ ; i++ ;
+         }
+       /* n3 */ 
+       d_snake[n].posi = dist_bords ;
+       d_snake[n].posj = j_dim - dist_bords ;
+       d_snake[n-1].nb_pixels =  d_snake[n-1].posi -  d_snake[n].posi ;
+       n++ ;
+       /*entre S3 et S0*/
+       i = 0 ;
+       while (i< nb_node_seg)
+         {
+               if ( (d_snake[n-1].posj - incl) - dist_bords > limite)
+                 d_snake[n].posj = d_snake[n-1].posj - incl ;
+               else
+                 d_snake[n].posj = d_snake[n-1].posj - incl/2 ;
+               d_snake[n].posi = dist_bords ;
+               d_snake[n-1].nb_pixels =  d_snake[n-1].posj -  d_snake[n].posj ;
+               n++ ; i++ ;
+         }
+       d_snake[n-1].nb_pixels =  d_snake[n-1].posj -  d_snake[0].posj ;
+       for (i=0; i<n; i++)
+         {
+               d_snake[i].freeman_in = 0;
+               d_snake[i].freeman_out = 0;
+               d_snake[i].centre_i = 0;
+               d_snake[i].centre_j = 0;
+               d_snake[i].last_move = 1;
+               d_snake[i].code_segment = 0;
+               
+         }
+  }
+}
+
+__global__ void calcul_contribs_segments_snake(snake_node_gpu * d_snake, int nb_nodes,
+                                                                                          t_cumul_x * cumul_x, t_cumul_x2 * cumul_x2, 
+                                                                                          int l, uint2 * liste_pix, t_sum_x2 * gsombloc, int * d_table_freeman)
+{
+  // indices des elements
+  int blockSize = blockDim.x ;
+  int tib = threadIdx.x ;
+  int nblocs_seg =  gridDim.x / nb_nodes ;
+  int idx = blockDim.x*blockIdx.x + threadIdx.x ;
+  int segment = blockIdx.x / nblocs_seg ;
+  int tis = idx - segment*nblocs_seg*blockDim.x ;
+
+  //tab pour coordonnées pixels & contribs pixels de taille = (blockDim.x+offset(dec,dec2) )*(sizeof(t_sum_1+t_sum_x+t_sum_x2))
+  extern __shared__ t_sum_1 scumuls_1[] ; // blockDim varie selon la longueur des segments => taille smem dynamique 
+  t_sum_x* scumuls_x = (t_sum_x*) &scumuls_1[CFI(blockDim.x)] ;
+  t_sum_x2* scumuls_x2 = (t_sum_x2*) &scumuls_x[CFI(blockDim.x)] ;
+  
+  //indices des noeuds
+  uint x1, y1, x2, y2 ;
+  int n1, n2 ;
+  
+  n1 = segment ;
+  n2 = segment +1 ;
+  //gestion du bouclage du snake
+  if (n2 >= nb_nodes) n2 = 0 ;
+  
+  //affectation des differentes positions aux différents segments 'blocs de threads'
+       x1 = d_snake[n1].posj ;
+       y1 = d_snake[n1].posi ;
+       x2 = d_snake[n2].posj ;
+       y2 = d_snake[n2].posi ;
+  
+  //params des deplacements
+  int dx=x2-x1;
+  int dy=y2-y1;
+  uint abs_dx = ABS(dx);
+  uint abs_dy = ABS(dy);
+  uint nb_pix = abs_dy>abs_dx?(abs_dy+1):(abs_dx+1); // alternative -> lecture ds liste_points[]
+  int incx=0, incy=0;
+  uint2 p ;
+  int xprec, xsuiv ; 
+  
+  //calcul liste des pixels du segment (x1,y1)-(x2,y2)  
+  if (dy > 0) incy=1; else incy=-1 ;
+  if (dx > 0) incx=1; else incx=-1 ;
+  
+  if (tis < nb_pix){
+       if (abs_dy > abs_dx){
+         //1 thread par ligne
+         double k = (double)dx/dy ;
+         p.x = y1 + incy*tis ;
+         p.y =  x1 + floor((double)incy*k*tis+0.5) ;
+         //enreg. coords. pixels en global mem pour freemans
+         
+         if ((tis < 2)||(tis > nb_pix - 3)||(tis == nb_pix/2))
+               {
+                 liste_pix[idx].x = p.x ;
+                 liste_pix[idx].y = p.y ;
+                 }
+         
+       } else {
+         //1 thread par colonne          
+         double k=(double)dy/dx ;
+         p.x = y1 + floor((double)(incx*k*tis)+0.5) ;
+         p.y = x1 + incx*tis ;
+         if ( tis > 0 ){ 
+               xsuiv = y1 + floor((double)(incx*k*(tis+1))+0.5) ;
+               xprec = y1 + floor((double)(incx*k*(tis-1))+0.5) ;
+         }
+         //enreg. coords. pixels en global mem pour freeman
+         //TODO
+         //on peut calculer les freemans des segments
+         //sans stocker l'ensemble des valeurs des pixels
+         //juste avec les derivees aux extremites a calculer ici
+         
+         if ((tis < 2)||(tis > nb_pix - 3)||(tis == nb_pix/2))
+               {
+                 liste_pix[idx].x = p.x ;
+                 liste_pix[idx].y = p.y ;
+                 }
+         
+       }
+  }
+  __syncthreads();
+    
+  //calcul contribs individuelles des pixels
+  
+  if ( (tis >0) && (tis < nb_pix-1)
+          && ( (abs_dy <= abs_dx)
+                       && ( (xprec > p.x) || (xsuiv > p.x))
+                       || (abs_dy > abs_dx) ) )
+       {
+       int pos = p.x * l + p.y ;
+       scumuls_1[ CFI(tib)] = 1+p.y; 
+       scumuls_x[ CFI(tib)] = cumul_x[ pos ] ;
+       scumuls_x2[CFI(tib)] = cumul_x2[ pos ];
+  } else {
+       scumuls_1[ CFI(tib)] = 0;
+       scumuls_x[ CFI(tib)] = 0;
+       scumuls_x2[CFI(tib)] = 0;
+  }
+  
+   __syncthreads();
+  //somme des contribs individuelles 
+  // unroll des  sommes partielles en smem
+  
+  if (blockSize >= 512) {
+       if (tib < 256) {
+         scumuls_1[ CFI(tib)] += scumuls_1[ CFI(tib + 256) ];
+         scumuls_x[ CFI(tib)] += scumuls_x[ CFI(tib + 256) ];
+         scumuls_x2[CFI(tib)] += scumuls_x2[CFI(tib + 256) ];
+       }
+       __syncthreads();
+  }
+  if (blockSize >= 256) {
+       if (tib < 128) {
+         scumuls_1[ CFI(tib)] += scumuls_1[ CFI(tib + 128) ];
+         scumuls_x[ CFI(tib)] += scumuls_x[ CFI(tib + 128) ];
+         scumuls_x2[CFI(tib)] += scumuls_x2[CFI(tib + 128) ]; 
+       }
+       __syncthreads();
+  }
+  if (blockSize >= 128) {
+       if (tib <  64) {
+         scumuls_1[ CFI(tib)] += scumuls_1[ CFI(tib +  64) ];
+         scumuls_x[ CFI(tib)] += scumuls_x[ CFI(tib +  64) ];
+         scumuls_x2[CFI(tib)] += scumuls_x2[CFI(tib +  64) ];    
+       }
+       __syncthreads();
+  }
+  
+  //32 threads <==> 1 warp
+  if (tib < 32)
+       {
+         {
+               scumuls_1[ CFI(tib)] += scumuls_1[ CFI(tib + 32) ];
+               scumuls_x[ CFI(tib)] += scumuls_x[ CFI(tib + 32) ];
+               scumuls_x2[CFI(tib)] += scumuls_x2[CFI(tib + 32) ];
+         }
+         {
+               scumuls_1[ CFI(tib)] += scumuls_1[ CFI(tib + 16) ];
+               scumuls_x[ CFI(tib)] += scumuls_x[ CFI(tib + 16) ];
+               scumuls_x2[CFI(tib)] += scumuls_x2[CFI(tib + 16) ];
+         }
+         {
+               scumuls_1[ CFI(tib)] += scumuls_1[ CFI(tib +  8) ];
+               scumuls_x[ CFI(tib)] += scumuls_x[ CFI(tib +  8) ];
+               scumuls_x2[CFI(tib)] += scumuls_x2[CFI(tib +  8) ];
+         }
+         scumuls_1[ CFI(tib)] += scumuls_1[ CFI(tib +  4) ];
+         scumuls_x[ CFI(tib)] += scumuls_x[ CFI(tib +  4) ];
+         scumuls_x2[CFI(tib)] += scumuls_x2[CFI(tib +  4) ];
+         
+         scumuls_1[ CFI(tib)] += scumuls_1[ CFI(tib +  2) ];
+         scumuls_x[ CFI(tib)] += scumuls_x[ CFI(tib +  2) ];
+         scumuls_x2[CFI(tib)] += scumuls_x2[CFI(tib +  2) ];
+         
+         scumuls_1[ CFI(tib)] += scumuls_1[ CFI(tib +  1) ];
+         scumuls_x[ CFI(tib)] += scumuls_x[ CFI(tib +  1) ];
+         scumuls_x2[CFI(tib)] += scumuls_x2[CFI(tib +  1) ];
+       }
+  
+  // resultat sommes partielles en gmem
+  if (tib == 0) {
+       gsombloc[ blockIdx.x ] = (t_sum_x2) scumuls_1[0]; 
+       gsombloc[ blockIdx.x + gridDim.x ] = (t_sum_x2) scumuls_x[0];
+       gsombloc[ blockIdx.x + 2*gridDim.x ] = (t_sum_x2) scumuls_x2[0];
+  }
+
+  //calculs freemans, centre et code segment
+  //1 uint4 par segment
+  
+  int Di, Dj;
+  if (tis == 0){
+       Di = 1 + liste_pix[idx+1].x - liste_pix[idx].x ; 
+       Dj = 1 + liste_pix[idx+1].y - liste_pix[idx].y ;
+       d_snake[segment].freeman_out = d_table_freeman[3*Di + Dj] ;
+       //code seg
+       if (dy > 0 ) d_snake[segment].code_segment = -1 ;
+       if (dy < 0 ) d_snake[segment].code_segment = 1 ;
+       if (dy == 0) d_snake[segment].code_segment = 0 ;
+  }
+
+  if (tis == nb_pix-1){
+       Di = 1 + liste_pix[idx].x - liste_pix[idx-1].x  ; 
+       Dj = 1 + liste_pix[idx].y - liste_pix[idx-1].y;
+       d_snake[segment].freeman_in = d_table_freeman[3*Di + Dj] ;
+  }
+  
+  if (tis == (nb_pix/2)){
+       d_snake[segment].centre_i = liste_pix[idx].x ;
+       d_snake[segment].centre_j = liste_pix[idx].y ;
+       }  
+}
+
+/*
+  sommme des contribs par bloc -> contribs segment, pour le snake
+
+  execution sur : 1bloc / 1 thread par segment
+ */
+
+__global__ void somsom_snake(t_sum_x2 * somblocs, int nb_nodes, unsigned int nb_bl_seg, snake_node_gpu * d_snake){
+
+  t_sum_x2 sdata[3];
+  unsigned int seg = blockIdx.x ;
+  
+  //un thread par segment
+  {
+       sdata[0] = 0;
+       sdata[1] = 0;
+       sdata[2] = 0;
+  }
+
+  for (int b=0; b < nb_bl_seg ; b++){
+       sdata[0] += somblocs[seg*nb_bl_seg + b];
+       sdata[1] += somblocs[(seg + nb_nodes)*nb_bl_seg + b];
+       sdata[2] += somblocs[(seg + 2*nb_nodes)*nb_bl_seg + b];
+  }
+  
+  //totaux en gmem
+  {
+       d_snake[seg].sum_1 = sdata[0];
+       d_snake[seg].sum_x = sdata[1];
+       d_snake[seg].sum_x2 = sdata[2];
+  }      
+}
+
+__device__ double codage_gl_gauss(uint64 stat_sum_1, uint64 stat_sum_x, uint64 stat_sum_x2,
+                                                                                  uint64 n_dim, uint64 SUM_X, uint64 SUM_X2){
+  uint64 stat_sum_xe ;  /* somme des xn region exterieure */
+  uint32 ne ;             /* nombre de pixel region exterieure */
+  double sigi2, sige2; /* variance region interieure et exterieure */
+
+  /* variance des valeurs des niveaux de gris a l'interieur du snake */
+  sigi2 = 
+    ((double)stat_sum_x2/(double)stat_sum_1) - 
+    ((double)stat_sum_x/(uint64)stat_sum_1)*((double)stat_sum_x/(uint64)stat_sum_1) ;
+
+  /* variance des valeurs des niveaux de gris a l'exterieur du snake */
+  ne = n_dim-stat_sum_1 ;
+  stat_sum_xe = SUM_X - stat_sum_x ;
+  sige2 =
+    ((double)SUM_X2-stat_sum_x2)/(double)ne - 
+    ((double)stat_sum_xe/(uint64)ne)*((double)stat_sum_xe/(uint64)ne) ;
+  
+  if ((sigi2 > 0)|(sige2 > 0))
+  return  0.5*((double)stat_sum_1*log(sigi2) + (double)ne*log(sige2)) ;
+  return -1 ;
+}
+
+
+__global__ void calcul_stats_snake(snake_node_gpu * d_snake, int  nnodes, int64 * d_stats_snake, double * vrais_min,
+                                                                  t_cumul_x * cumul_x, t_cumul_x2 * cumul_x2, int * TABLE_CODAGE, uint32 l
+                                                                  )
+{
+  
+  int id_nx, id_nprec, id_nprecprec ;
+  int code_noeud, code_segment, pos ; 
+  __shared__ int64 s_stats_snake[3] ;
+  //init stats en shared mem
+  s_stats_snake[0] = 0 ;
+  s_stats_snake[1] = 0 ;
+  s_stats_snake[2] = 0 ;
+
+    
+  for (id_nx = 0; id_nx < nnodes; id_nx++)
+    {
+         if (id_nx == 0) id_nprec = nnodes - 1;
+         else id_nprec = id_nx - 1;
+         if (id_nprec == 0) id_nprecprec = nnodes -1 ;
+         else id_nprecprec = id_nprec - 1 ;
+      /* gestion des segments partant du noeud */
+      /* vers le noeud suivant dans l'ordre trigo */
+      code_segment = d_snake[id_nprec].code_segment ;
+      if (code_segment > 0)
+               {
+                 /* on somme les contributions */
+                 s_stats_snake[0] += d_snake[id_nprec].sum_1 ;
+                 s_stats_snake[1] += d_snake[id_nprec].sum_x ;
+                 s_stats_snake[2] += d_snake[id_nprec].sum_x2 ;
+               }
+      else if (code_segment < 0)
+               {
+                 /* on soustrait les contributions */
+                 s_stats_snake[0] -= d_snake[id_nprec].sum_1 ;
+                 s_stats_snake[1] -= d_snake[id_nprec].sum_x ;
+                 s_stats_snake[2] -= d_snake[id_nprec].sum_x2 ;
+               }
+      // else (code_segment == 0), on ne fait rien
+      /* gestion des pixels connectant les segments */
+      /* pixel de depart du segment actuel np --> np->noeud_suiv */
+      /* freeman_out = np->freeman_out ; */
+      /* freeman_in = np->noeud_prec->freeman_in ; */
+         pos = d_snake[id_nprecprec].freeman_in*8 + d_snake[id_nprec].freeman_out ;
+      code_noeud = TABLE_CODAGE[pos] ;
+         pos = d_snake[id_nprec].posi*l + d_snake[id_nprec].posj ;
+   
+      if (code_noeud > 0)
+               {
+                 /* on somme les contributions */
+                 s_stats_snake[0] += 1 + d_snake[id_nprec].posj ;
+                 s_stats_snake[1] += cumul_x[pos] ;
+                 s_stats_snake[2] += cumul_x2[pos] ;
+               }
+      else if (code_noeud < 0)
+               {
+                 /* on soustrait les contributions */
+                 s_stats_snake[0] -= 1 + d_snake[id_nprec].posj ;
+                 s_stats_snake[1] -= cumul_x[pos] ;
+                 s_stats_snake[2] -= cumul_x2[pos] ;
+               }
+      // else (code_pixel == 0), on ne fait rien
+    }
+  d_stats_snake[0] = s_stats_snake[0] ;
+  d_stats_snake[1] = s_stats_snake[1] ;
+  d_stats_snake[2] = s_stats_snake[2] ;
+  
+  *vrais_min = codage_gl_gauss(s_stats_snake[0], s_stats_snake[1], s_stats_snake[2],
+                                                          d_stats_snake[3], d_stats_snake[4], d_stats_snake[5]);
+}
diff --git a/src/lib_kernel_snake_2_gpu.cu~ b/src/lib_kernel_snake_2_gpu.cu~
new file mode 100644 (file)
index 0000000..eba3a46
--- /dev/null
@@ -0,0 +1,447 @@
+
+
+__global__ void genere_snake_rectangle_4nodes_gpu(snake_node_gpu * d_snake, int dist_bords, int i_dim, int j_dim){
+  if (threadIdx.x == 0){
+       int n = 0;
+       /* n0 */
+       d_snake[n].posi = dist_bords ;
+       d_snake[n].posj = dist_bords ;
+       n++ ;
+       /* n1 */
+       d_snake[n].posi = i_dim - dist_bords ;
+       d_snake[n].posj = dist_bords ; 
+       n++ ;
+       /* n2 */
+       d_snake[n].posi = i_dim - dist_bords ;
+       d_snake[n].posj = j_dim - dist_bords ; 
+       n++ ;
+       /* n3 */
+       d_snake[n].posi = dist_bords ;
+       d_snake[n].posj = j_dim - dist_bords ;
+
+       for (int i=0; i<4; i++)
+         {
+               d_snake[i].freeman_in = 0;
+               d_snake[i].freeman_out = 0;
+               d_snake[i].centre_i = 0;
+               d_snake[i].centre_j = 0;
+               d_snake[i].last_move = 0;
+               d_snake[i].nb_pixels = 0;
+               d_snake[i].code_segment = 0;
+               
+         }
+  }
+}
+
+
+__global__ void genere_snake_rectangle_Nnodes_gpu(snake_node_gpu * d_snake, int dist_bords, int i_dim, int j_dim){
+  int nb_node_seg = 9 ;
+  int limite = 64 ;
+  
+  int i , h= i_dim-2*dist_bords, l= j_dim-2*dist_bords ;
+  int inch = h/(nb_node_seg+1), incl= l/(nb_node_seg+1) ;
+  if (threadIdx.x == 0){
+       int n = 0;
+       /* n0 */
+       d_snake[n].posi = dist_bords ;
+       d_snake[n].posj = dist_bords ;
+       n++ ;
+       /*entre sommet 0 et 1*/
+       i = 0 ;
+       while (i < nb_node_seg)
+         {
+               if ( (d_snake[n-1].posi + inch)-(i_dim - dist_bords) > limite )
+                 d_snake[n].posi = d_snake[n-1].posi + inch ;
+               else
+                 d_snake[n].posi = d_snake[n-1].posi + inch/2 ;
+               d_snake[n].posj = dist_bords ;
+               d_snake[n-1].nb_pixels =  d_snake[n].posi -  d_snake[n-1].posi ;
+               n++ ; i++ ;
+         }
+       /* n1 */
+       d_snake[n].posi = i_dim - dist_bords ;
+       d_snake[n].posj = dist_bords ;
+       d_snake[n-1].nb_pixels =  d_snake[n].posi -  d_snake[n-1].posi ;
+       n++ ;
+       /*entre S1 et S2*/
+       i = 0 ; 
+       while (i< nb_node_seg)
+         {
+               if ( (j_dim - dist_bords) - (d_snake[n-1].posj + incl) > limite )
+                 d_snake[n].posj = d_snake[n-1].posj + incl ;
+               else
+                 d_snake[n].posj = d_snake[n-1].posj + incl/2 ;
+               d_snake[n].posi = i_dim - dist_bords ;
+               d_snake[n-1].nb_pixels =  d_snake[n].posj -  d_snake[n-1].posj ;
+               n++ ; i++ ;
+         }
+       /* n2 */
+       d_snake[n].posi = i_dim - dist_bords ;
+       d_snake[n].posj = j_dim - dist_bords ;
+       d_snake[n-1].nb_pixels =  d_snake[n].posj -  d_snake[n-1].posj ;
+       n++ ;
+       /*entre S2 et S3*/
+       i = 0 ;
+       while (i< nb_node_seg)
+         {
+               if ( (d_snake[n-1].posi - inch) - dist_bords > limite )
+                 d_snake[n].posi = d_snake[n-1].posi - inch ;
+               else
+                 d_snake[n].posi = d_snake[n-1].posi - inch/2 ;
+               d_snake[n].posj = j_dim - dist_bords ;
+               d_snake[n-1].nb_pixels =  d_snake[n-1].posi -  d_snake[n].posi ;
+               n++ ; i++ ;
+         }
+       /* n3 */ 
+       d_snake[n].posi = dist_bords ;
+       d_snake[n].posj = j_dim - dist_bords ;
+       d_snake[n-1].nb_pixels =  d_snake[n-1].posi -  d_snake[n].posi ;
+       n++ ;
+       /*entre S3 et S0*/
+       i = 0 ;
+       while (i< nb_node_seg)
+         {
+               if ( (d_snake[n-1].posj - incl) - dist_bords > limite)
+                 d_snake[n].posj = d_snake[n-1].posj - incl ;
+               else
+                 d_snake[n].posj = d_snake[n-1].posj - incl/2 ;
+               d_snake[n].posi = dist_bords ;
+               d_snake[n-1].nb_pixels =  d_snake[n-1].posj -  d_snake[n].posj ;
+               n++ ; i++ ;
+         }
+       d_snake[n-1].nb_pixels =  d_snake[n-1].posj -  d_snake[0].posj ;
+       for (i=0; i<n; i++)
+         {
+               d_snake[i].freeman_in = 0;
+               d_snake[i].freeman_out = 0;
+               d_snake[i].centre_i = 0;
+               d_snake[i].centre_j = 0;
+               d_snake[i].last_move = 1;
+               d_snake[i].code_segment = 0;
+               
+         }
+  }
+}
+
+__global__ void calcul_contribs_segments_snake(snake_node_gpu * d_snake, int nb_nodes,
+                                                                                          t_cumul_x * cumul_x, t_cumul_x2 * cumul_x2, 
+                                                                                          int l, uint2 * liste_pix, t_sum_x2 * gsombloc, int * d_table_freeman)
+{
+  // indices des elements
+  int blockSize = blockDim.x ;
+  int tib = threadIdx.x ;
+  int nblocs_seg =  gridDim.x / nb_nodes ;
+  int idx = blockDim.x*blockIdx.x + threadIdx.x ;
+  int segment = blockIdx.x / nblocs_seg ;
+  int tis = idx - segment*nblocs_seg*blockDim.x ;
+
+  //tab pour coordonnées pixels & contribs pixels de taille = (blockDim.x+offset(dec,dec2) )*(sizeof(t_sum_1+t_sum_x+t_sum_x2))
+  extern __shared__ t_sum_1 scumuls_1[] ; // blockDim varie selon la longueur des segments => taille smem dynamique 
+  t_sum_x* scumuls_x = (t_sum_x*) &scumuls_1[CFI(blockDim.x)] ;
+  t_sum_x2* scumuls_x2 = (t_sum_x2*) &scumuls_x[CFI(blockDim.x)] ;
+  
+  //indices des noeuds
+  uint x1, y1, x2, y2 ;
+  int n1, n2 ;
+  
+  n1 = segment ;
+  n2 = segment +1 ;
+  //gestion du bouclage du snake
+  if (n2 >= nb_nodes) n2 = 0 ;
+  
+  //affectation des differentes positions aux différents segments 'blocs de threads'
+       x1 = d_snake[n1].posj ;
+       y1 = d_snake[n1].posi ;
+       x2 = d_snake[n2].posj ;
+       y2 = d_snake[n2].posi ;
+  
+  //params des deplacements
+  int dx=x2-x1;
+  int dy=y2-y1;
+  uint abs_dx = ABS(dx);
+  uint abs_dy = ABS(dy);
+  uint nb_pix = abs_dy>abs_dx?(abs_dy+1):(abs_dx+1); // alternative -> lecture ds liste_points[]
+  int incx=0, incy=0;
+  uint2 p ;
+  int xprec, xsuiv ; 
+  
+  //calcul liste des pixels du segment (x1,y1)-(x2,y2)  
+  if (dy > 0) incy=1; else incy=-1 ;
+  if (dx > 0) incx=1; else incx=-1 ;
+  
+  if (tis < nb_pix){
+       if (abs_dy > abs_dx){
+         //1 thread par ligne
+         double k = (double)dx/dy ;
+         p.x = y1 + incy*tis ;
+         p.y =  x1 + floor((double)incy*k*tis+0.5) ;
+         //enreg. coords. pixels en global mem pour freemans
+         
+         if ((tis < 2)||(tis > nb_pix - 3)||(tis == nb_pix/2))
+               {
+                 liste_pix[idx].x = p.x ;
+                 liste_pix[idx].y = p.y ;
+                 }
+         
+       } else {
+         //1 thread par colonne          
+         double k=(double)dy/dx ;
+         p.x = y1 + floor((double)(incx*k*tis)+0.5) ;
+         p.y = x1 + incx*tis ;
+         if ( tis > 0 ){ 
+               xsuiv = y1 + floor((double)(incx*k*(tis+1))+0.5) ;
+               xprec = y1 + floor((double)(incx*k*(tis-1))+0.5) ;
+         }
+         //enreg. coords. pixels en global mem pour freeman
+         //TODO
+         //on peut calculer les freemans des segments
+         //sans stocker l'ensemble des valeurs des pixels
+         //juste avec les derivees aux extremites a calculer ici
+         
+         if ((tis < 2)||(tis > nb_pix - 3)||(tis == nb_pix/2))
+               {
+                 liste_pix[idx].x = p.x ;
+                 liste_pix[idx].y = p.y ;
+                 }
+         
+       }
+  }
+  __syncthreads();
+    
+  //calcul contribs individuelles des pixels
+  
+  if ( (tis >0) && (tis < nb_pix-1)
+          && ( (abs_dy <= abs_dx)
+                       && ( (xprec > p.x) || (xsuiv > p.x))
+                       || (abs_dy > abs_dx) ) )
+       {
+       int pos = p.x * l + p.y ;
+       scumuls_1[ CFI(tib)] = 1+p.y; 
+       scumuls_x[ CFI(tib)] = cumul_x[ pos ] ;
+       scumuls_x2[CFI(tib)] = cumul_x2[ pos ];
+  } else {
+       scumuls_1[ CFI(tib)] = 0;
+       scumuls_x[ CFI(tib)] = 0;
+       scumuls_x2[CFI(tib)] = 0;
+  }
+  
+   __syncthreads();
+  //somme des contribs individuelles 
+  // unroll des  sommes partielles en smem
+  
+  if (blockSize >= 512) {
+       if (tib < 256) {
+         scumuls_1[ CFI(tib)] += scumuls_1[ CFI(tib + 256) ];
+         scumuls_x[ CFI(tib)] += scumuls_x[ CFI(tib + 256) ];
+         scumuls_x2[CFI(tib)] += scumuls_x2[CFI(tib + 256) ];
+       }
+       __syncthreads();
+  }
+  if (blockSize >= 256) {
+       if (tib < 128) {
+         scumuls_1[ CFI(tib)] += scumuls_1[ CFI(tib + 128) ];
+         scumuls_x[ CFI(tib)] += scumuls_x[ CFI(tib + 128) ];
+         scumuls_x2[CFI(tib)] += scumuls_x2[CFI(tib + 128) ]; 
+       }
+       __syncthreads();
+  }
+  if (blockSize >= 128) {
+       if (tib <  64) {
+         scumuls_1[ CFI(tib)] += scumuls_1[ CFI(tib +  64) ];
+         scumuls_x[ CFI(tib)] += scumuls_x[ CFI(tib +  64) ];
+         scumuls_x2[CFI(tib)] += scumuls_x2[CFI(tib +  64) ];    
+       }
+       __syncthreads();
+  }
+  
+  //32 threads <==> 1 warp
+  if (tib < 32)
+       {
+         {
+               scumuls_1[ CFI(tib)] += scumuls_1[ CFI(tib + 32) ];
+               scumuls_x[ CFI(tib)] += scumuls_x[ CFI(tib + 32) ];
+               scumuls_x2[CFI(tib)] += scumuls_x2[CFI(tib + 32) ];
+         }
+         {
+               scumuls_1[ CFI(tib)] += scumuls_1[ CFI(tib + 16) ];
+               scumuls_x[ CFI(tib)] += scumuls_x[ CFI(tib + 16) ];
+               scumuls_x2[CFI(tib)] += scumuls_x2[CFI(tib + 16) ];
+         }
+         {
+               scumuls_1[ CFI(tib)] += scumuls_1[ CFI(tib +  8) ];
+               scumuls_x[ CFI(tib)] += scumuls_x[ CFI(tib +  8) ];
+               scumuls_x2[CFI(tib)] += scumuls_x2[CFI(tib +  8) ];
+         }
+         scumuls_1[ CFI(tib)] += scumuls_1[ CFI(tib +  4) ];
+         scumuls_x[ CFI(tib)] += scumuls_x[ CFI(tib +  4) ];
+         scumuls_x2[CFI(tib)] += scumuls_x2[CFI(tib +  4) ];
+         
+         scumuls_1[ CFI(tib)] += scumuls_1[ CFI(tib +  2) ];
+         scumuls_x[ CFI(tib)] += scumuls_x[ CFI(tib +  2) ];
+         scumuls_x2[CFI(tib)] += scumuls_x2[CFI(tib +  2) ];
+         
+         scumuls_1[ CFI(tib)] += scumuls_1[ CFI(tib +  1) ];
+         scumuls_x[ CFI(tib)] += scumuls_x[ CFI(tib +  1) ];
+         scumuls_x2[CFI(tib)] += scumuls_x2[CFI(tib +  1) ];
+       }
+  
+  // resultat sommes partielles en gmem
+  if (tib == 0) {
+       gsombloc[ blockIdx.x ] = (t_sum_x2) scumuls_1[0]; 
+       gsombloc[ blockIdx.x + gridDim.x ] = (t_sum_x2) scumuls_x[0];
+       gsombloc[ blockIdx.x + 2*gridDim.x ] = (t_sum_x2) scumuls_x2[0];
+  }
+
+  //calculs freemans, centre et code segment
+  //1 uint4 par segment
+  
+  int Di, Dj;
+  if (tis == 0){
+       Di = 1 + liste_pix[idx+1].x - liste_pix[idx].x ; 
+       Dj = 1 + liste_pix[idx+1].y - liste_pix[idx].y ;
+       d_snake[segment].freeman_out = d_table_freeman[3*Di + Dj] ;
+       //code seg
+       if (dy > 0 ) d_snake[segment].code_segment = -1 ;
+       if (dy < 0 ) d_snake[segment].code_segment = 1 ;
+       if (dy == 0) d_snake[segment].code_segment = 0 ;
+  }
+
+  if (tis == nb_pix-1){
+       Di = 1 + liste_pix[idx].x - liste_pix[idx-1].x  ; 
+       Dj = 1 + liste_pix[idx].y - liste_pix[idx-1].y;
+       d_snake[segment].freeman_in = d_table_freeman[3*Di + Dj] ;
+  }
+  
+  if (tis == (nb_pix/2)){
+       d_snake[segment].centre_i = liste_pix[idx].x ;
+       d_snake[segment].centre_j = liste_pix[idx].y ;
+       }  
+}
+
+/*
+  sommme des contribs par bloc -> contribs segment, pour le snake
+
+  execution sur : 1bloc / 1 thread par segment
+ */
+
+__global__ void somsom_snake(t_sum_x2 * somblocs, int nb_nodes, unsigned int nb_bl_seg, snake_node_gpu * d_snake){
+
+  t_sum_x2 sdata[3];
+  unsigned int seg = blockIdx.x ;
+  
+  //un thread par segment
+  {
+       sdata[0] = 0;
+       sdata[1] = 0;
+       sdata[2] = 0;
+  }
+
+  for (int b=0; b < nb_bl_seg ; b++){
+       sdata[0] += somblocs[seg*nb_bl_seg + b];
+       sdata[1] += somblocs[(seg + nb_nodes)*nb_bl_seg + b];
+       sdata[2] += somblocs[(seg + 2*nb_nodes)*nb_bl_seg + b];
+  }
+  
+  //totaux en gmem
+  {
+       d_snake[seg].sum_1 = sdata[0];
+       d_snake[seg].sum_x = sdata[1];
+       d_snake[seg].sum_x2 = sdata[2];
+  }      
+}
+
+__device__ double codage_gl_gauss(uint64 stat_sum_1, uint64 stat_sum_x, uint64 stat_sum_x2,
+                                                                                  uint64 n_dim, uint64 SUM_X, uint64 SUM_X2){
+  uint64 stat_sum_xe ;  /* somme des xn region exterieure */
+  uint32 ne ;             /* nombre de pixel region exterieure */
+  double sigi2, sige2; /* variance region interieure et exterieure */
+
+  /* variance des valeurs des niveaux de gris a l'interieur du snake */
+  sigi2 = 
+    ((double)stat_sum_x2/(double)stat_sum_1) - 
+    ((double)stat_sum_x/(uint64)stat_sum_1)*((double)stat_sum_x/(uint64)stat_sum_1) ;
+
+  /* variance des valeurs des niveaux de gris a l'exterieur du snake */
+  ne = n_dim-stat_sum_1 ;
+  stat_sum_xe = SUM_X - stat_sum_x ;
+  sige2 =
+    ((double)SUM_X2-stat_sum_x2)/(double)ne - 
+    ((double)stat_sum_xe/(uint64)ne)*((double)stat_sum_xe/(uint64)ne) ;
+  
+  if ((sigi2 > 0)|(sige2 > 0))
+  return  0.5*((double)stat_sum_1*log(sigi2) + (double)ne*log(sige2)) ;
+  return -1 ;
+}
+
+
+__global__ void calcul_stats_snake(snake_node_gpu * d_snake, int  nnodes, int64 * d_stats_snake, double * vrais_min,
+                                                                  t_cumul_x * cumul_x, t_cumul_x2 * cumul_x2, int * TABLE_CODAGE, uint32 l
+                                                                  )
+{
+  
+  int id_nx, id_nprec, id_nprecprec ;
+  int code_noeud, code_segment, pos ; 
+  __shared__ int64 s_stats_snake[3] ;
+  //init stats en shared mem
+  s_stats_snake[0] = 0 ;
+  s_stats_snake[1] = 0 ;
+  s_stats_snake[2] = 0 ;
+
+    
+  for (id_nx = 0; id_nx < nnodes; id_nx++)
+    {
+         if (id_nx == 0) id_nprec = nnodes - 1;
+         else id_nprec = id_nx - 1;
+         if (id_nprec == 0) id_nprecprec = nnodes -1 ;
+         else id_nprecprec = id_nprec - 1 ;
+      /* gestion des segments partant du noeud */
+      /* vers le noeud suivant dans l'ordre trigo */
+      code_segment = d_snake[id_nprec].code_segment ;
+      if (code_segment > 0)
+               {
+                 /* on somme les contributions */
+                 s_stats_snake[0] += d_snake[id_nprec].sum_1 ;
+                 s_stats_snake[1] += d_snake[id_nprec].sum_x ;
+                 s_stats_snake[2] += d_snake[id_nprec].sum_x2 ;
+               }
+      else if (code_segment < 0)
+               {
+                 /* on soustrait les contributions */
+                 s_stats_snake[0] -= d_snake[id_nprec].sum_1 ;
+                 s_stats_snake[1] -= d_snake[id_nprec].sum_x ;
+                 s_stats_snake[2] -= d_snake[id_nprec].sum_x2 ;
+               }
+      // else (code_segment == 0), on ne fait rien
+      /* gestion des pixels connectant les segments */
+      /* pixel de depart du segment actuel np --> np->noeud_suiv */
+      /* freeman_out = np->freeman_out ; */
+      /* freeman_in = np->noeud_prec->freeman_in ; */
+         pos = d_snake[id_nprecprec].freeman_in*8 + d_snake[id_nprec].freeman_out ;
+      code_noeud = TABLE_CODAGE[pos] ;
+         pos = d_snake[id_nprec].posi*l + d_snake[id_nprec].posj ;
+   
+      if (code_noeud > 0)
+               {
+                 /* on somme les contributions */
+                 s_stats_snake[0] += 1 + d_snake[id_nprec].posj ;
+                 s_stats_snake[1] += cumul_x[pos] ;
+                 s_stats_snake[2] += cumul_x2[pos] ;
+               }
+      else if (code_noeud < 0)
+               {
+                 /* on soustrait les contributions */
+                 s_stats_snake[0] -= 1 + d_snake[id_nprec].posj ;
+                 s_stats_snake[1] -= cumul_x[pos] ;
+                 s_stats_snake[2] -= cumul_x2[pos] ;
+               }
+      // else (code_pixel == 0), on ne fait rien
+    }
+  d_stats_snake[0] = s_stats_snake[0] ;
+  d_stats_snake[1] = s_stats_snake[1] ;
+  d_stats_snake[2] = s_stats_snake[2] ;
+  
+  *vrais_min = codage_gl_gauss(s_stats_snake[0], s_stats_snake[1], s_stats_snake[2],
+                                                          d_stats_snake[3], d_stats_snake[4], d_stats_snake[5]);
+}
diff --git a/src/lib_kernels_contribs.cu b/src/lib_kernels_contribs.cu
new file mode 100644 (file)
index 0000000..2440f0c
--- /dev/null
@@ -0,0 +1,1043 @@
+#include "constantes.h"
+
+/*
+ * determine et retourne le nb de pixels composant le segment (i,j)-(i1,j1)
+ *
+ */
+__device__ int calcul_nb_pixels(int i, int j, int i1, int j1){
+          int absi, absj,nbpix =0;
+          //MAX( ABS(i1-i) , ABS(j1-j)) + 1
+          if (i1 > i) absi = i1 - i ; else absi = i - i1 ;
+          if (j1 > j) absj = j1 - j ; else absj = j - j1 ;
+          if (absi > absj ) nbpix = absi+1 ; else nbpix = absj+1 ;
+          return nbpix ;
+}
+
+/*
+  construit la liste des coordonnées des 8  positions a tester pour l'ensemble des N noeuds du snake
+  ainsi que le liste des nombres de pixels correspondant (en z, seg avant, en w seg apres)
+  a executer avec N blocs de 8 threads
+*/
+__global__ void liste_positions_a_tester(snake_node_gpu * d_snake, uint4 * liste_positions, uint32 * nb_pix_max, int pas, int nb_nodes, int h, int l){
+  int tib = threadIdx.x;                                    // une position par thread
+  int node = blockIdx.x;                                    // 1 noeud par bloc de threads
+  int node_prec, node_suiv ;                                // indices des nodes
+  int i, j, i1, j1, i2, j2, i3, j3, npix_prec, npix_suiv ;  // coordonnees des noeuds , nb de pixels
+
+  //lecture des coordonnees
+  node_prec = (node == 0)? (nb_nodes-1) : (node - 1) ;
+  node_suiv = (node == nb_nodes-1)? (0) : (node + 1) ;
+  i1 = d_snake[node_prec].posi ;
+  j1 = d_snake[node_prec].posj ;
+  i2 = d_snake[node].posi ;
+  j2 = d_snake[node].posj ;
+  i3 = d_snake[node_suiv].posi ;
+  j3 = d_snake[node_suiv].posj ;
+  
+  switch(tib){                         // on considere un voisinage a 8 points
+  case 0:
+       i = i2 ;
+       if ((j2 + pas) < l) j = j2 + pas ; else j = l-2 ; 
+       break;
+  case 1:
+       if ((j2 + pas) < l) j = j2 + pas ; else j = l-2 ;
+       if (i2 > pas ) i = i2 - pas ; else i = 1 ;
+       break;
+  case 2:
+       if (i2 > pas ) i = i2 - pas ; else i = 1 ;
+       j = j2 ; 
+       break;
+  case 3:
+       if (i2 > pas) i = i2 - pas ; else i = 1 ;
+       if (j2 > pas) j = j2 - pas ; else j = 1 ;
+       break;
+  case 4:
+       i = i2 ;
+       if (j2 > pas) j = j2 - pas ; else j = 1 ;
+       break;
+  case 5:
+       if ((i2 + pas) < h) i = i2 + pas ; else i = h-2 ;
+       if (j2 > pas) j = j2 - pas ; else j = 1 ;
+       break;
+  case 6:
+       if ((i2 + pas) < h) i = i2 + pas ; else i = h-2 ;
+       j = j2 ;
+       break;
+  case 7:
+       if ((i2 + pas) < h) i = i2 + pas ; else i = h-2 ;
+       if ((j2 + pas) < l) j = j2 + pas ; else j = l-2 ;
+       break;
+  }
+
+  //calcul des nombres de pixels dans chaque cas
+  npix_prec =  calcul_nb_pixels(i,j,i1,j1) ;
+  npix_suiv =  calcul_nb_pixels(i,j,i3,j3) ;
+  
+  liste_positions[8*node + tib] = make_uint4(i,j, (uint)npix_prec, (uint)npix_suiv );
+  
+  // calcule du maximum global du nb de pixels
+  if ((node == 0) && (tib == 0))
+       {
+         *nb_pix_max = 0 ;
+         for (int n=0; n<nb_nodes; n++)
+               {
+                 if (liste_positions[n].z > *nb_pix_max) *nb_pix_max = liste_positions[n].z ;
+                 if (liste_positions[n].w > *nb_pix_max) *nb_pix_max = liste_positions[n].w ;
+               }
+       }
+}
+
+/*
+ * calcule :
+ *  - les coordonnees de chaque pixel de chaque segment a evaluer pour les 8 voisins de chaque noeud (pair ou impair)
+ *    cela represente 16 segments par noeud pair/impair
+ *  - les contributions de chacun de ces pixels
+ *  - les sommes, par blocs, des contributions des pixels (les sommes totales sont faites par le kernel somsom)
+ *  - le code de chaque segment envisage
+ */
+
+__global__ void calcul_contribs_segments_blocs_full(snake_node_gpu * d_snake, int nb_nodes, uint4 * liste_points, uint32 npix_max,
+                                                                                                       t_cumul_x * cumul_x, t_cumul_x2 * cumul_x2,  int * d_codes_x16,
+                                                                                                       int l, uint2 * liste_pix, uint64 * gsombloc, bool pairs)
+{
+  // indices des elements
+  int blockSize = blockDim.x ;                                                         // nb threads par bloc
+  int tib = threadIdx.x ;                                                                      // position du thread dans le bloc
+  int nblocs_noeud =  gridDim.x / (nb_nodes/2 + pairs*(nb_nodes%2)) ;   // nb de blocs dédié à chaque noeud 
+  int nblocs_seg = nblocs_noeud / 16 ;                                  // nb de blocs dédiés à un segment de test
+  int idx = blockDim.x*blockIdx.x + threadIdx.x ;                       // position absolue du thread ds la grille
+  int id_interval = blockIdx.x / nblocs_noeud ;                         // indice de l'intervalle du noeud dans la grille
+  int segment = ( blockIdx.x - id_interval*nblocs_noeud )/nblocs_seg ;  // indice du segment de 0 à 15
+  int tis = idx - ( id_interval*nblocs_noeud + segment*nblocs_seg )*blockDim.x ; // position du thread ds le segment
+  int id_base_seg = 16*id_interval + segment ;                          // indice du segment courant
+  int id_base_pix = 5*id_base_seg ;                                                // indice du pixel 0/5 du segment courant dans la liste_pix pour le calcul des freemans
+
+  //tab pour contribs pixels 
+  extern __shared__ tcontribs scumuls[];  
+
+  //coordonnees des extremites de segment
+  uint x1, y1, x2, y2 ;
+  //indices des noeuds precedent(n1), courant(n2), suivant(n3)
+  int n1, n2, n3 ;
+  // pixel courant
+  uint2 p ;
+  // nb de pixels du segment precedent, suivant
+  int xprec, xsuiv ; 
+
+  // determine les indices des noeuds prec, courant, suiv
+  if (pairs)
+       {
+         n1 = 2*id_interval -1 ;
+         n2 = 2*id_interval ;
+         n3 = 2*id_interval +1 ;
+       }
+  else
+       {
+         n1 = 2*id_interval ;
+         n2 = 2*id_interval +1 ;
+         n3 = 2*id_interval +2 ;
+       }
+  //gestion du bouclage du snake
+  if (n1 < 0) n1 = nb_nodes-1 ;
+  if (n3 >= nb_nodes) n3 = 0 ;
+
+  
+  //affectation des differentes positions aux différents segments 'blocs de threads'
+  if ( segment < 8 ){
+       x1 = d_snake[n1].posj ;
+       y1 = d_snake[n1].posi ; 
+       x2 = liste_points[8*n2 + segment].y ;
+       y2 = liste_points[8*n2 + segment].x ;
+  } else {
+       x1 = liste_points[8*n2 + segment-8].y ;
+       y1 = liste_points[8*n2 + segment-8].x ;
+       x2 = d_snake[n3].posj ;
+       y2 = d_snake[n3].posi ;
+  }
+  
+  //params des deplacements
+  int dx=x2-x1;
+  int dy=y2-y1;
+  uint abs_dx = ABS(dx);
+  uint abs_dy = ABS(dy);
+  uint nb_pix = abs_dy>abs_dx?(abs_dy+1):(abs_dx+1);
+  int incx=0, incy=0;
+  
+  
+  //calcul liste des pixels du segment (x1,y1)-(x2,y2)  
+  if (dy > 0) incy=1; else incy=-1 ;
+  if (dx > 0) incx=1; else incx=-1 ;
+  
+  if (tis < nb_pix){
+       if (abs_dy > abs_dx){
+         //1 thread par ligne pente 1/k
+         double k = (double)dx/dy ;
+         //coordonnees pixel
+         p.x = y1 + incy*tis ;
+         p.y = x1 + floor((double)incy*k*tis+0.5) ;
+       } else {
+         //1 thread par colonne pente k          
+         double k=(double)dy/dx ;
+         //coordonnees pixel
+         p.x = y1 + floor((double)(incx*k*tis)+0.5) ;
+         p.y =  x1 + incx*tis ;
+         // ordonnees des pixels suivant & precedent
+         if ( tis > 0 ){ 
+               xsuiv = y1 + floor((double)(incx*k*(tis+1))+0.5) ;
+               xprec = y1 + floor((double)(incx*k*(tis-1))+0.5) ;
+         }
+       }
+       // memorisation des valeurs necessaires au calcul des freemans et des centres
+       if (tis == 0)  liste_pix[id_base_pix] = make_uint2(p.x, p.y) ;
+       if (tis == 1)  liste_pix[id_base_pix +1] = make_uint2(p.x,p.y) ;
+       if (tis == nb_pix/2) liste_pix[id_base_pix +2] = make_uint2(p.x,p.y) ;
+       if (tis == nb_pix-2) liste_pix[id_base_pix +3] = make_uint2(p.x,p.y) ;
+       if (tis == nb_pix-1) liste_pix[id_base_pix +4] = make_uint2(p.x,p.y) ;
+  }
+  
+  __syncthreads();  
+  // calcul contribs individuelles des pixels
+  // dans le cas des segments 'plutot horizontaux', on ne garde qu'une contrib par ligne ; celle du pixel le plus a l'interieur du snake
+  if ( (tis >0) && (tis < nb_pix-1)
+          && ( ((abs_dy <= abs_dx) && ( ( xprec > p.x) || ( xsuiv > p.x)))
+                       || (abs_dy > abs_dx) ) )
+       {
+         int pos = p.x * l + p.y ;
+         scumuls[ CFI(tib)].c1 = 1 + p.y ;  
+         scumuls[ CFI(tib)].cx = cumul_x[ pos ] ;
+         scumuls[CFI(tib)].cx2 = cumul_x2[ pos ];
+       } else {
+         scumuls[ CFI(tib)].c1 = 0;
+         scumuls[ CFI(tib)].cx = 0;
+         scumuls[ CFI(tib)].cx2 = 0;
+  }
+  
+   __syncthreads();
+  // somme des contribs individuelles 
+  // unroll des  sommes partielles en shared memory
+  if (blockSize >= 512) {
+       if (tib < 256) {
+         scumuls[ CFI(tib)].c1 += scumuls[ CFI(tib + 256) ].c1;
+         scumuls[ CFI(tib)].cx += scumuls[ CFI(tib + 256) ].cx;
+         scumuls[ CFI(tib)].cx2 += scumuls[CFI(tib + 256) ].cx2;
+       }
+       __syncthreads();
+  }
+  if (blockSize >= 256) {
+       if (tib < 128) {
+         scumuls[ CFI(tib)].c1 += scumuls[ CFI(tib + 128) ].c1;
+         scumuls[ CFI(tib)].cx += scumuls[ CFI(tib + 128) ].cx;
+         scumuls[ CFI(tib)].cx2 += scumuls[CFI(tib + 128) ].cx2; 
+       }
+       __syncthreads();
+  }
+  if (blockSize >= 128) {
+       if (tib <  64) {
+         scumuls[ CFI(tib)].c1 += scumuls[ CFI(tib +  64) ].c1;
+         scumuls[ CFI(tib)].cx += scumuls[ CFI(tib +  64) ].cx;
+         scumuls[CFI(tib)].cx2 += scumuls[CFI(tib +  64) ].cx2;          
+       }
+       __syncthreads();
+  }
+  
+  //32 threads <==> 1 warp
+ volatile tcontribs * scontribs = scumuls ;
+ if (tib < 32){
+        {
+               scontribs[ CFI(tib)].c1 += scontribs[ CFI(tib + 32) ].c1;
+               scontribs[ CFI(tib)].cx += scontribs[ CFI(tib + 32) ].cx;
+               scontribs[CFI(tib)].cx2 += scontribs[CFI(tib + 32) ].cx2;
+         }
+ if (tib < 16)
+         {
+               scontribs[ CFI(tib)].c1 += scontribs[ CFI(tib + 16) ].c1;
+               scontribs[ CFI(tib)].cx += scontribs[ CFI(tib + 16) ].cx;
+               scontribs[CFI(tib)].cx2 += scontribs[CFI(tib + 16) ].cx2;
+         }
+ if (tib < 8)
+         {
+               scontribs[ CFI(tib)].c1 += scontribs[ CFI(tib +  8) ].c1;
+               scontribs[ CFI(tib)].cx += scontribs[ CFI(tib +  8) ].cx;
+               scontribs[CFI(tib)].cx2 += scontribs[CFI(tib +  8) ].cx2;
+         }
+ if (tib < 4)
+       {
+         scontribs[ CFI(tib)].c1 += scontribs[ CFI(tib +  4) ].c1;
+         scontribs[ CFI(tib)].cx += scontribs[ CFI(tib +  4) ].cx;
+         scontribs[ CFI(tib)].cx2 +=scontribs[ CFI(tib +  4) ].cx2;
+       }
+ if (tib < 2)
+       {  
+         scontribs[ CFI(tib)].c1 += scontribs[ CFI(tib +  2) ].c1;
+         scontribs[ CFI(tib)].cx += scontribs[ CFI(tib +  2) ].cx;
+         scontribs[CFI(tib)].cx2 += scontribs[CFI(tib +  2) ].cx2;
+        } 
+ if (tib == 0)
+       {
+         scontribs[ CFI(tib)].c1 += scontribs[ CFI(tib +  1) ].c1;
+         scontribs[ CFI(tib)].cx += scontribs[ CFI(tib +  1) ].cx;
+         scontribs[CFI(tib)].cx2 += scontribs[CFI(tib +  1) ].cx2;
+  
+  // resultat sommes partielles en gmem
+  //if (tib == 0) {
+       gsombloc[ blockIdx.x ] = scontribs[0].c1 ; 
+       gsombloc[ blockIdx.x + gridDim.x ] = scontribs[0].cx ;
+       gsombloc[ blockIdx.x + 2*gridDim.x ] = scontribs[0].cx2 ;
+       
+ //code seg
+       if (dy > 0 ) d_codes_x16[id_base_seg] = -1 ;
+       if (dy < 0 ) d_codes_x16[id_base_seg] =  1 ;
+       if (dy == 0) d_codes_x16[id_base_seg]=  0 ;
+  }
+ }
+}
+
+/*
+ calcul des freeman et du centre de chaque segment de test
+ a executer sur 'n_interval' blocs de 16 threads
+ soit un thread par segment 
+*/
+__global__ void calcul_freemans_centre(uint2 * liste_pix, int * d_table_freeman, uint4 * d_freemans_x16){
+       
+  int id_segment = threadIdx.x ;    
+  int id_freeman = ( blockDim.x*blockIdx.x + id_segment ) ;
+  int id_base_pix = 5*id_freeman ;
+  
+  //calculs freemans, centre et code segment
+  //1 uint4 par segment  
+  int Dio, Djo, Dii, Dji;
+       
+       //freeman out
+       Dio = 1 + liste_pix[id_base_pix +1].x - liste_pix[id_base_pix].x ; 
+       Djo = 1 + liste_pix[id_base_pix +1].y - liste_pix[id_base_pix].y ;
+       d_freemans_x16[id_freeman].z = d_table_freeman[3*Dio + Djo] ;
+       
+       
+       //freeman_in
+       Dii = 1 + liste_pix[id_base_pix +4].x - liste_pix[id_base_pix +3].x ; 
+       Dji = 1 + liste_pix[id_base_pix +4].y - liste_pix[id_base_pix +3].y ;
+       d_freemans_x16[id_freeman].w = d_table_freeman[3*Dii + Dji] ;
+       
+       //centre 
+       d_freemans_x16[id_freeman].x = liste_pix[id_base_pix +2].x ;
+       d_freemans_x16[id_freeman].y = liste_pix[id_base_pix +2].y ;
+          
+}
+
+
+/*
+  calcul des contribs 1, x et x2 des 16 segments
+  autour du noeud
+  a partir des sommes partielles des blocs
+  1 bloc / 1 thread par segment 
+*/
+
+__global__ void somsom_full(uint64 * somblocs, int nb_nodes, unsigned int nb_bl_seg, uint64 * somsom){
+
+  uint64 sdata[3];
+  unsigned int seg = blockIdx.x ;
+  unsigned int nb_seg = gridDim.x ;
+  
+  //un thread par segment
+  {
+       sdata[0] = 0;
+       sdata[1] = 0;
+       sdata[2] = 0;
+  }
+
+  for (int b=0; b < nb_bl_seg ; b++){ //voir atomicadd 64bits
+       sdata[0] += somblocs[seg*nb_bl_seg + b];
+       sdata[1] += somblocs[(seg + nb_seg)*nb_bl_seg + b];
+       sdata[2] += somblocs[(seg + 2*nb_seg)*nb_bl_seg + b];
+  }
+  
+  //totaux en gmem
+  {
+       somsom[3*seg] = sdata[0];
+       somsom[3*seg + 1] = sdata[1];
+       somsom[3*seg + 2] = sdata[2];
+  }      
+}
+
+/*
+  version GPU de la fonction definie ds src/lib_math.c
+*/
+__device__ bool test_inf_gpu(double arg1, double arg2){
+   if (arg2 > 0)
+        return (arg1 < (arg2*COEF_DECROI)) ;
+  else
+    return (arg1 < (arg2*INV_COEF_DECROI)) ;
+}
+
+/*
+  version GPU de la fonction codage_niveau_gris_hyp_gaussienne
+ */
+__device__ double codage_gl_hyp_gauss(uint64 stat_sum_1, uint64 stat_sum_x, uint64 stat_sum_x2,
+                                                                         uint64 n_dim, uint64 SUM_X, uint64 SUM_X2){
+  uint64 stat_sum_xe ;  /* somme des xn region exterieure */
+  uint32 ne ;             /* nombre de pixel region exterieure */
+  double sigi2, sige2; /* variance region interieure et exterieure */
+  
+  /* variance des valeurs des niveaux de gris a l'interieur du snake */
+  sigi2 = 
+    (double)stat_sum_x2/(double)stat_sum_1 - 
+    ((double)stat_sum_x/stat_sum_1)*((double)stat_sum_x/stat_sum_1) ;
+
+  /* variance des valeurs des niveaux de gris a l'exterieur du snake */
+  ne = n_dim-stat_sum_1 ;
+  stat_sum_xe = SUM_X - stat_sum_x ;
+  sige2 =
+    ((double)SUM_X2-stat_sum_x2)/ne - 
+    ((double)stat_sum_xe/ne)*((double)stat_sum_xe/ne) ;
+  
+  if ((sigi2 > 0)&&(sige2 > 0))
+  return  0.5*((double)stat_sum_1*log(sigi2) + (double)ne*log(sige2)) ;
+  return -1 ;
+}
+
+/*
+  soustrait, pour chaque intervalle [N1--Nx--N2] 
+  les contributions des segments N1--Nx et Nx--N2
+  
+  A executer par nnodes blocs de 1 thread par intervalle
+ */
+
+__global__ void soustrait_aux_stats_2N_segments_noeud(snake_node_gpu * d_snake, int64 * d_stats_snake, int64 * d_stats_ref, 
+                                                                                                         t_cumul_x * cumul_x, t_cumul_x2 * cumul_x2,
+                                                                                                         int * TABLE_CODAGE, uint32 l
+                                                                                                         )
+{
+  int nnodes = gridDim.x ;
+  int id_nx, id_nprec, id_nprecprec, id_nsuiv ;
+  int code_noeud, pos; 
+  __shared__ int64 s_stats_snake[3] ;
+
+  id_nx = blockIdx.x ;
+  if (id_nx == 0) id_nprec = nnodes - 1;
+  else id_nprec = id_nx - 1;
+  if (id_nprec == 0) id_nprecprec = nnodes -1 ;
+  else id_nprecprec = id_nprec - 1 ;
+  if (id_nx == nnodes-1) id_nsuiv = 0;
+  else id_nsuiv = id_nx + 1 ;
+  
+  //init avec les valeurs du contour actuel
+  s_stats_snake[0] = d_stats_snake[0] ;
+  s_stats_snake[1] = d_stats_snake[1] ;
+  s_stats_snake[2] = d_stats_snake[2] ;
+
+  /* segment Na -- Nx */
+  if (d_snake[id_nprec].code_segment > 0)
+    {
+     s_stats_snake[0] -= d_snake[id_nprec].sum_1 ;
+     s_stats_snake[1] -= d_snake[id_nprec].sum_x ;
+     s_stats_snake[2] -= d_snake[id_nprec].sum_x2 ;
+    }
+  else if (d_snake[id_nprec].code_segment < 0)
+    {
+        s_stats_snake[0] += d_snake[id_nprec].sum_1 ;
+     s_stats_snake[1] += d_snake[id_nprec].sum_x ;
+     s_stats_snake[2] += d_snake[id_nprec].sum_x2 ;
+    }
+  // else (code_segment_NaNx == 0), on ne fait rien
+  
+  /* gestion des pixels connectant les segments */
+  /* pixel de depart du segment Na --> Nx */
+  pos = d_snake[id_nprecprec].freeman_in*8 + d_snake[id_nprec].freeman_out ;
+  code_noeud = TABLE_CODAGE[pos] ;
+  pos = d_snake[id_nprec].posi*l + d_snake[id_nprec].posj ;
+  if (code_noeud > 0)
+    {
+     s_stats_snake[0] -= 1 + d_snake[id_nprec].posj ;
+     s_stats_snake[1] -= cumul_x[pos] ;
+        s_stats_snake[2] -= cumul_x2[pos];
+    }
+  else if (code_noeud < 0)
+    {
+        s_stats_snake[0] += 1 + d_snake[id_nprec].posj ;
+     s_stats_snake[1] += cumul_x[pos] ;
+        s_stats_snake[2] += cumul_x2[pos];
+    }
+  // else (code_noeud == 0), on ne fait rien
+  
+  /* -------------------------- */
+  /* -------------------------- */
+  /* segment Nx -- Nb */
+  if ( d_snake[id_nx].code_segment > 0 )
+    {
+      // on soustrait la contribution 
+        s_stats_snake[0] -= d_snake[id_nx].sum_1 ;
+     s_stats_snake[1] -= d_snake[id_nx].sum_x ;
+     s_stats_snake[2] -= d_snake[id_nx].sum_x2 ;
+    }
+  else if ( d_snake[id_nx].code_segment < 0)
+    {
+        s_stats_snake[0] += d_snake[id_nx].sum_1 ;
+     s_stats_snake[1] += d_snake[id_nx].sum_x ;
+     s_stats_snake[2] += d_snake[id_nx].sum_x2 ;
+    }
+  // else (code_segment_NxNb == 0), on ne fait rien
+  
+  /* gestion des pixels connectant les segments */
+  /* pixel de depart du segment Nx --> Nb */
+  pos = d_snake[id_nprec].freeman_in*8 + d_snake[id_nx].freeman_out ;
+  code_noeud = TABLE_CODAGE[pos] ;
+  pos = d_snake[id_nx].posi*l + d_snake[id_nx].posj ;
+  if (code_noeud > 0)
+    {
+     s_stats_snake[0] -= 1 + d_snake[id_nx].posj  ;
+     s_stats_snake[1] -= cumul_x[pos] ;
+        s_stats_snake[2] -= cumul_x2[pos];
+    }
+  else if (code_noeud < 0)
+    {
+        s_stats_snake[0] += 1 + d_snake[id_nx].posj ;
+     s_stats_snake[1] += cumul_x[pos] ;
+        s_stats_snake[2] += cumul_x2[pos];
+    }
+  // else (code_noeud == 0), on ne fait rien
+  
+  /* pixel d'arrivee du segment Nx --> Nb */
+  pos = d_snake[id_nx].freeman_in*8 + d_snake[id_nsuiv].freeman_out ;
+  code_noeud = TABLE_CODAGE[pos] ;
+  pos = d_snake[id_nsuiv].posi*l +  d_snake[id_nsuiv].posj ;
+  if (code_noeud > 0)
+    {
+        s_stats_snake[0] -= 1 + d_snake[id_nsuiv].posj ;
+     s_stats_snake[1] -= cumul_x[pos] ;
+        s_stats_snake[2] -= cumul_x2[pos];
+    }
+  else if (code_noeud < 0)
+    {
+        s_stats_snake[0] += 1 + d_snake[id_nsuiv].posj ;
+     s_stats_snake[1] += cumul_x[pos] ;
+        s_stats_snake[2] += cumul_x2[pos];
+        }
+  // else (code_noeud == 0), on ne fait rien
+  __syncthreads();
+  
+  d_stats_ref[3*id_nx] = s_stats_snake[0] ;
+  d_stats_ref[3*id_nx + 1] = s_stats_snake[1] ;
+  d_stats_ref[3*id_nx + 2] = s_stats_snake[2] ;
+}
+
+
+/*
+  calcul des stats associees a chaque position de test
+
+  EXEC : sur n_interval blocs de 8 threads
+*/
+__global__ void calcul_stats_full(snake_node_gpu * d_snake, int nnodes, bool pairs, int64 * d_stats_snake,
+                                                                 int64 * d_stats_ref, int64 * d_stats, uint64 * d_contribs,
+                                                                 uint4 * d_liste_points, int * code_segment, uint4 * d_freemans,
+                                                                 int * d_table_codes, t_cumul_x * cumul_x, t_cumul_x2 * cumul_x2,
+                                                                 uint32 h, uint32 l, double * vrais, double * vrais_min, bool * move){
+
+  int interval = blockIdx.x ;
+  int seg = threadIdx.x ;
+  int thread = seg;
+  int id_nx, id_nprec, id_nprecprec, id_nsuiv, id_seg ;
+  int code_noeud; 
+  __shared__ int64 s_stats_snake[3*8] ;
+
+  id_nx = 2*interval + !pairs ;
+  if (id_nx == 0) id_nprec = nnodes - 1 ;
+  else id_nprec = id_nx - 1 ;
+  if (id_nprec == 0) id_nprecprec = nnodes -1 ;
+  else id_nprecprec = id_nprec - 1 ;
+  if (id_nx == nnodes-1) id_nsuiv = 0 ;
+  else id_nsuiv = id_nx + 1 ;
+  
+  //chargement en smem , prevoir CFI car on a 24x64bits par blocs => conflits 
+  s_stats_snake[3*thread + 0] = d_stats_ref[3*id_nx] ;
+  s_stats_snake[3*thread + 1] = d_stats_ref[3*id_nx + 1] ;
+  s_stats_snake[3*thread + 2] = d_stats_ref[3*id_nx + 2] ;
+  
+  //stats segments N1-Nx
+  id_seg = 16*interval + seg ;
+  if ( code_segment[id_seg] > 0 ){
+       s_stats_snake[3*thread +0]  += d_contribs[3*id_seg] ;
+       s_stats_snake[3*thread +1]  += d_contribs[3*id_seg + 1 ] ;
+       s_stats_snake[3*thread +2]  += d_contribs[3*id_seg + 2 ] ;
+  } else if ( code_segment[16*interval + seg] < 0 ) {
+       s_stats_snake[3*thread +0]  -= d_contribs[3*id_seg] ;
+       s_stats_snake[3*thread +1]  -= d_contribs[3*id_seg + 1] ;
+       s_stats_snake[3*thread +2]  -= d_contribs[3*id_seg + 2] ;
+  }
+  
+  //stats noeud N1(i1,j1)
+  int fo_N1 = d_freemans[id_seg].z ;
+  int fi_Nprecprec = d_snake[id_nprecprec].freeman_in ;
+  int pos = d_snake[id_nprec].posi*l + d_snake[id_nprec].posj ;
+   
+  code_noeud = d_table_codes[fi_Nprecprec*8 + fo_N1];
+  if (code_noeud > 0){
+       s_stats_snake[3*thread +0] += 1 + d_snake[id_nprec].posj ;
+       s_stats_snake[3*thread +1] += cumul_x[ pos ] ;
+       s_stats_snake[3*thread +2] += cumul_x2[pos ] ;
+  } else if (code_noeud < 0){
+       s_stats_snake[3*thread +0] -= 1 + d_snake[id_nprec].posj ;
+       s_stats_snake[3*thread +1] -= cumul_x[ pos ] ;
+       s_stats_snake[3*thread +2] -= cumul_x2[pos ] ;
+  }
+  
+  //stats noeud Nx
+  int fo_Nx = d_freemans[id_seg + 8].z ;
+  int fi_Nx = d_freemans[id_seg].w ;
+  int Nxi = d_liste_points[8*id_nx + seg].x ;
+  int Nxj = d_liste_points[8*id_nx + seg].y ;
+  pos = Nxi*l + Nxj ;
+  
+  code_noeud = d_table_codes[fi_Nx*8 + fo_Nx];
+  if (code_noeud > 0){
+       s_stats_snake[3*thread +0] += 1 + Nxj ;
+       s_stats_snake[3*thread +1] += cumul_x[ pos ] ;
+       s_stats_snake[3*thread +2] += cumul_x2[pos ] ;
+  }
+  if (code_noeud < 0){
+       s_stats_snake[3*thread +0] -= 1 + Nxj ;
+       s_stats_snake[3*thread +1] -= cumul_x[ pos ] ;
+       s_stats_snake[3*thread +2] -= cumul_x2[pos ] ;
+  }
+  
+  //stats segments Nx-N2
+  seg += 8;
+  id_seg = 16*interval + seg ;
+  if ( code_segment[id_seg] > 0 ){
+       s_stats_snake[3*thread +0]  += d_contribs[3*id_seg] ;
+       s_stats_snake[3*thread +1]  += d_contribs[3*id_seg + 1] ;
+       s_stats_snake[3*thread +2]  += d_contribs[3*id_seg + 2] ;
+  }
+  if ( code_segment[id_seg] < 0 ) {
+       s_stats_snake[3*thread +0]  -= d_contribs[3*id_seg] ;
+       s_stats_snake[3*thread +1]  -= d_contribs[3*id_seg + 1] ;
+       s_stats_snake[3*thread +2]  -= d_contribs[3*id_seg + 2] ;
+  }
+  
+  //stats noeud N2(i2,j2)
+  int fi_N2 = d_freemans[id_seg].w ;
+  int fo_N2 = d_snake[id_nsuiv].freeman_out ;
+  pos = d_snake[id_nsuiv].posi*l + d_snake[id_nsuiv].posj ;
+  
+  code_noeud = d_table_codes[fi_N2*8 + fo_N2];
+  if (code_noeud > 0){
+       s_stats_snake[3*thread +0] += 1 + d_snake[id_nsuiv].posj ;
+       s_stats_snake[3*thread +1] += cumul_x[ pos ] ;
+       s_stats_snake[3*thread +2] += cumul_x2[pos ] ;
+  }
+  if (code_noeud < 0){
+       s_stats_snake[3*thread +0] -= 1 + d_snake[id_nsuiv].posj ;
+       s_stats_snake[3*thread +1] -= cumul_x[ pos ] ;
+       s_stats_snake[3*thread +2] -= cumul_x2[pos ] ;
+  }
+  
+         //TODO
+         //voir si on peut s'en passer
+  d_stats[3*(8*interval + thread)] = s_stats_snake[3*thread +0]; 
+  d_stats[3*(8*interval + thread) + 1] = s_stats_snake[3*thread +1];
+  d_stats[3*(8*interval + thread) + 2] = s_stats_snake[3*thread +2];
+  
+  //codage hyp gaussienne  
+  uint64 stat_sum_xe[8] ;    //somme des xn region exterieure 
+  uint32 ne[8] ;             // nombre de pixels region exterieure 
+  double sigi2[8], sige2[8]; //  carres des variances, regions interieure et exterieure 
+
+  /* variance des valeurs des niveaux de gris a l'interieur du snake */
+  sigi2[thread] =
+       ((double)s_stats_snake[3*thread +2]/(double)s_stats_snake[3*thread +0]) -
+       ((double)s_stats_snake[3*thread +1]/s_stats_snake[3*thread +0])*((double)s_stats_snake[3*thread +1]/s_stats_snake[3*thread +0]) ;
+  
+  /* variance des valeurs des niveaux de gris a l'exterieur du snake */
+  ne[thread] = h*l-s_stats_snake[3*thread +0] ;
+  stat_sum_xe[thread] = d_stats_snake[4] - s_stats_snake[3*thread +1] ;
+  sige2[thread] =
+       (double)(d_stats_snake[5]-s_stats_snake[3*thread +2])/(double)ne[thread] -
+       ((double)stat_sum_xe[thread]/ne[thread])*((double)stat_sum_xe[thread]/ne[thread]) ;
+
+  if (sige2[thread]>0 && sigi2[thread]>0)
+       vrais[8*interval + thread] = 0.5*((double)s_stats_snake[3*thread]*log(sigi2[thread]) + (double)ne[thread]*log(sige2[thread])) ;
+  else
+       vrais[8*interval + thread] = -1.0;
+
+  if ( thread == 0 ){
+        //init move
+       move[id_nx] = false ;
+       int pos_optim = -1;
+       double vrais_tmp = *vrais_min;
+       for (int v=0; v < 8; v++){
+         if ( (vrais[8*interval + v] > 0) && (vrais[8*interval + v] < vrais_tmp*COEF_DECROI) ) {
+               vrais_tmp = vrais[8*interval + v];
+               pos_optim = v;
+         }
+       }
+       if (pos_optim >-1){
+         if ( !croisement(d_snake, id_nx, d_liste_points[8*id_nx + pos_optim].x, d_liste_points[8*id_nx + pos_optim].y, nnodes) )
+               {
+                 /*maj data snake*/
+                 move[id_nx] = true ;
+                 //new position 
+                 d_snake[id_nx].posi = d_liste_points[8*id_nx + pos_optim].x ;
+                 d_snake[id_nx].posj = d_liste_points[8*id_nx + pos_optim].y ;
+                 //nb pixels segment precedent
+                 d_snake[id_nprec].nb_pixels = d_liste_points[8*id_nx + pos_optim].z ;
+                 //nb pixels segment suivant
+                 d_snake[id_nx].nb_pixels = d_liste_points[8*id_nx + pos_optim].w ;
+                 //contribs segment precedent
+                 d_snake[id_nprec].sum_1 = d_contribs[3*(16*interval + pos_optim)] ;
+                 d_snake[id_nprec].sum_x = d_contribs[3*(16*interval + pos_optim) + 1] ;
+                 d_snake[id_nprec].sum_x2 = d_contribs[3*(16*interval + pos_optim) + 2] ;
+                 //contribs segment suivant
+                 d_snake[id_nx].sum_1 = d_contribs[3*(16*interval + pos_optim + 8)] ;
+                 d_snake[id_nx].sum_x = d_contribs[3*(16*interval + pos_optim + 8) + 1] ;
+                 d_snake[id_nx].sum_x2 = d_contribs[3*(16*interval + pos_optim + 8) + 2] ;
+                 //freemans segment precedent
+                 d_snake[id_nprec].freeman_out = d_freemans[16*interval + pos_optim].z ;
+                 d_snake[id_nprec].freeman_in = d_freemans[16*interval + pos_optim].w ;
+                 //freemans segment suivant
+                 d_snake[id_nx].freeman_out = d_freemans[16*interval + pos_optim + 8].z ;
+                 d_snake[id_nx].freeman_in = d_freemans[16*interval + pos_optim + 8].w ;
+                 //codes segment precedent
+                 d_snake[id_nprec].code_segment = code_segment[16*interval + pos_optim] ;
+                 //code segment suivant
+                 d_snake[id_nx].code_segment = code_segment[16*interval + pos_optim + 8] ;
+                 //centre segment precedent
+                 d_snake[id_nprec].centre_i = d_freemans[16*interval + pos_optim ].x ;
+                 d_snake[id_nprec].centre_j = d_freemans[16*interval + pos_optim ].y ;
+                 //centre segment suivant 
+                 d_snake[id_nx].centre_i = d_freemans[16*interval + pos_optim + 8].x ;
+                 d_snake[id_nx].centre_j = d_freemans[16*interval + pos_optim + 8].y ;
+                 
+               }                          
+       }
+  }
+
+  
+}
+
+__global__ void recalcul_stats_snake(snake_node_gpu * d_snake, int  nnodes, int64 * d_stats_snake, double * vrais_min,
+                                                                        t_cumul_x * cumul_x, t_cumul_x2 * cumul_x2, int * TABLE_CODAGE, uint32 l
+                                                                        )
+{
+  
+  int id_nx, id_nprec, id_nprecprec ;
+  int code_noeud, code_segment, pos; 
+  int64 s_stats_snake[3] ;
+  //init stats en shared mem
+  s_stats_snake[0] = 0 ;
+  s_stats_snake[1] = 0 ;
+  s_stats_snake[2] = 0 ;
+
+    
+  for (id_nx = 0; id_nx < nnodes; id_nx++)
+    {
+         if (id_nx == 0) id_nprec = nnodes - 1;
+         else id_nprec = id_nx - 1;
+         if (id_nprec == 0) id_nprecprec = nnodes -1 ;
+         else id_nprecprec = id_nprec - 1 ;
+      /* gestion des segments partant du noeud */
+      /* vers le noeud suivant dans l'ordre trigo */
+      code_segment = d_snake[id_nprec].code_segment ;
+      if (code_segment > 0)
+               {
+                 /* on somme les contributions */
+                 s_stats_snake[0] += d_snake[id_nprec].sum_1 ;
+                 s_stats_snake[1] += d_snake[id_nprec].sum_x ;
+                 s_stats_snake[2] += d_snake[id_nprec].sum_x2 ;
+               }
+      else if (code_segment < 0)
+               {
+                 /* on soustrait les contributions */
+                 s_stats_snake[0] -= d_snake[id_nprec].sum_1 ;
+                 s_stats_snake[1] -= d_snake[id_nprec].sum_x ;
+                 s_stats_snake[2] -= d_snake[id_nprec].sum_x2 ;
+               }
+      // else (code_segment == 0), on ne fait rien
+      /* gestion des pixels connectant les segments */
+         pos = d_snake[id_nprecprec].freeman_in*8 + d_snake[id_nprec].freeman_out ;
+      code_noeud = TABLE_CODAGE[pos] ;
+         pos = d_snake[id_nprec].posi*l + d_snake[id_nprec].posj ;
+   
+      if (code_noeud > 0)
+               {
+                 /* on somme les contributions */
+                 s_stats_snake[0] += 1 + d_snake[id_nprec].posj ;
+                 s_stats_snake[1] += cumul_x[pos] ;
+                 s_stats_snake[2] += cumul_x2[pos] ;
+               }
+      else if (code_noeud < 0)
+               {
+                 /* on soustrait les contributions */
+                 s_stats_snake[0] -= 1 + d_snake[id_nprec].posj ;
+                 s_stats_snake[1] -= cumul_x[pos] ;
+                 s_stats_snake[2] -= cumul_x2[pos] ;
+               }
+      // else (code_pixel == 0), on ne fait rien
+    }
+  d_stats_snake[0] = s_stats_snake[0] ;
+  d_stats_snake[1] = s_stats_snake[1] ;
+  d_stats_snake[2] = s_stats_snake[2] ;
+  
+  *vrais_min = codage_gl_hyp_gauss(s_stats_snake[0], s_stats_snake[1], s_stats_snake[2],
+                                                                  d_stats_snake[3], d_stats_snake[4], d_stats_snake[5]);
+}
+
+
+__global__ void ajoute_noeuds(snake_node_gpu * snake, snake_node_gpu * snake_tmp, int nnodes, int seuil, int * new_nb_nodes){
+
+  volatile snake_node_gpu * st = snake_tmp ;
+
+ int id_cpy = 0;  
+ for (int id_nx=0; id_nx < nnodes; id_nx++){
+       //position du noeud existant
+       st[id_cpy].posi =  snake[id_nx].posi ;
+    st[id_cpy].posj =  snake[id_nx].posj ;
+        
+       id_cpy++ ;
+       
+       if ( snake[id_nx].nb_pixels > seuil)
+       {
+               //position du nouveau noeud
+               st[id_cpy].posi = snake[id_nx].centre_i ;
+               st[id_cpy].posj = snake[id_nx].centre_j ;
+               id_cpy++ ;
+       }       
+ }
+ for( int node=0; node<id_cpy; node++ ){
+   snake[node].posi = st[node].posi ;
+   snake[node].posj = st[node].posj ;
+ }
+*new_nb_nodes = id_cpy-nnodes ;
+}
+  
+
+
+
+
+__global__ void recalcul_contribs_segments_snake(snake_node_gpu * d_snake, int nb_nodes,
+                                                                                                t_cumul_x * cumul_x, t_cumul_x2 * cumul_x2, 
+                                                                                                int l, uint2 * liste_pix, uint64 * gsombloc )
+{
+  // indices des elements
+  int blockSize = blockDim.x ;
+  int tib = threadIdx.x ;
+  int nblocs_seg =  gridDim.x / nb_nodes ;
+  int idx = blockDim.x*blockIdx.x + threadIdx.x ;
+  int segment = blockIdx.x / nblocs_seg ;
+  int tis = idx - segment*nblocs_seg*blockDim.x ;
+
+  //tab pour contribs pixels 
+  extern __shared__ tcontribs scumuls[];
+
+  //indices des noeuds
+  uint x1, y1, x2, y2 ;
+  int n1, n2 ;
+  uint2 p ;
+  int xsuiv, xprec ;
+  
+  n1 = segment ;
+  n2 = segment +1 ;
+  //gestion du bouclage du snake
+  if (n2 >= nb_nodes) n2 = 0 ;
+  
+  //affectation des differentes positions aux différents segments 'blocs de threads'
+       x1 = d_snake[n1].posj ;
+       y1 = d_snake[n1].posi ;
+       x2 = d_snake[n2].posj ;
+       y2 = d_snake[n2].posi ;
+  
+  //params des deplacements
+  int dx=x2-x1;
+  int dy=y2-y1;
+  uint abs_dx = ABS(dx);
+  uint abs_dy = ABS(dy);
+  uint nb_pix = abs_dy>abs_dx?(abs_dy+1):(abs_dx+1); // alternative -> lecture ds liste_points[]
+  int incx=0, incy=0;
+  
+  
+  //calcul liste des pixels du segment (x1,y1)-(x2,y2)  
+  if (dy > 0) incy=1; else incy=-1 ;
+  if (dx > 0) incx=1; else incx=-1 ;
+  
+  if (tis < nb_pix){
+       if (abs_dy > abs_dx){
+         //1 thread par ligne
+         double k = (double)dx/dy ;
+         p.x = y1 + incy*tis ;
+         p.y = x1 + floor((double)incy*k*tis+0.5) ;
+
+       } else {
+         //1 thread par colonne          
+         double k=(double)dy/dx ;
+         p.x = y1 + floor((double)(incx*k*tis)+0.5) ;
+         p.y =  x1 + incx*tis ;
+         if ( tis > 0 ){ 
+               xsuiv = y1 + floor((double)(incx*k*(tis+1))+0.5) ;
+               xprec = y1 + floor((double)(incx*k*(tis-1))+0.5) ;
+         }
+
+       }
+       if (tis == 0)  liste_pix[5*segment] = make_uint2(p.x, p.y) ;
+       if (tis == 1)  liste_pix[5*segment +1] = make_uint2(p.x,p.y) ;
+    if (tis == nb_pix/2) liste_pix[5*segment +2] = make_uint2(p.x,p.y) ;
+    if (tis == nb_pix-2) liste_pix[5*segment +3] = make_uint2(p.x,p.y) ;
+    if (tis == nb_pix-1) liste_pix[5*segment +4] = make_uint2(p.x,p.y) ;
+  }
+  __syncthreads();
+    
+  //calcul contribs individuelles des pixels
+  
+  if ( (tis >0) && (tis < nb_pix-1)
+          && ( ( (abs_dy <= abs_dx) && ( ( xprec > p.x) || ( xsuiv > p.x)) )
+                       || (abs_dy > abs_dx) ) )
+       {
+       int pos = p.x * l + p.y ;
+       scumuls[ CFI(tib)].c1 = 1+p.y;        
+       scumuls[ CFI(tib)].cx = cumul_x[ pos ] ;
+       scumuls[CFI(tib)].cx2 = cumul_x2[ pos ];
+  } else {
+       scumuls[ CFI(tib)].c1 = 0;
+       scumuls[ CFI(tib)].cx = 0;
+       scumuls[CFI(tib)].cx2 = 0;
+  }
+  
+   __syncthreads();
+  //somme des contribs individuelles 
+  // unroll des  sommes partielles en smem
+  
+  if (blockSize >= 512) {
+       if (tib < 256) {
+         scumuls[ CFI(tib)].c1 += scumuls[ CFI(tib + 256) ].c1;
+         scumuls[ CFI(tib)].cx += scumuls[ CFI(tib + 256) ].cx;
+         scumuls[CFI(tib)].cx2 += scumuls[CFI(tib + 256) ].cx2;
+       }
+       __syncthreads();
+  }
+  if (blockSize >= 256) {
+       if (tib < 128) {
+         scumuls[ CFI(tib)].c1 += scumuls[ CFI(tib + 128) ].c1;
+         scumuls[ CFI(tib)].cx += scumuls[ CFI(tib + 128) ].cx;
+         scumuls[CFI(tib)].cx2 += scumuls[CFI(tib + 128) ].cx2; 
+       }
+       __syncthreads();
+  }
+  if (blockSize >= 128) {
+       if (tib <  64) {
+         scumuls[ CFI(tib)].c1 += scumuls[ CFI(tib +  64) ].c1;
+         scumuls[ CFI(tib)].cx += scumuls[ CFI(tib +  64) ].cx;
+         scumuls[CFI(tib)].cx2 += scumuls[ CFI(tib +  64) ].cx2;         
+       }
+       __syncthreads();
+  }
+  
+  //32 threads <==> 1 warp
+  volatile tcontribs * scontribs = scumuls ;
+  if (tib < 32)
+       {
+         {
+               scontribs[ CFI(tib)].c1 += scontribs[ CFI(tib + 32) ].c1;
+               scontribs[ CFI(tib)].cx += scontribs[ CFI(tib + 32) ].cx;
+               scontribs[ CFI(tib)].cx2 +=scontribs[ CFI(tib + 32) ].cx2;
+         }
+         if (tib<16)
+         {
+               scontribs[ CFI(tib)].c1 += scontribs[ CFI(tib + 16) ].c1;
+               scontribs[ CFI(tib)].cx += scontribs[ CFI(tib + 16) ].cx;
+               scontribs[ CFI(tib)].cx2 +=scontribs[ CFI(tib + 16) ].cx2;
+         }
+         if (tib<8)
+         {
+               scontribs[ CFI(tib)].c1 += scontribs[ CFI(tib +  8) ].c1;
+               scontribs[ CFI(tib)].cx += scontribs[ CFI(tib +  8) ].cx;
+               scontribs[ CFI(tib)].cx2 +=scontribs[ CFI(tib +  8) ].cx2;}
+       if (tib<4){     
+         scontribs[ CFI(tib)].c1 += scontribs[ CFI(tib +  4) ].c1;
+         scontribs[ CFI(tib)].cx += scontribs[ CFI(tib +  4) ].cx;
+         scontribs[ CFI(tib)].cx2 +=scontribs[ CFI(tib +  4) ].cx2;
+         }
+         if (tib<2){
+         scontribs[ CFI(tib)].c1 += scontribs[ CFI(tib +  2) ].c1;
+         scontribs[ CFI(tib)].cx += scontribs[ CFI(tib +  2) ].cx;
+         scontribs[ CFI(tib)].cx2 +=scontribs[ CFI(tib +  2) ].cx2;
+         }
+         if (tib==0){
+         scontribs[ CFI(tib)].c1 += scontribs[ CFI(tib +  1) ].c1;
+         scontribs[ CFI(tib)].cx += scontribs[ CFI(tib +  1) ].cx;
+         scontribs[ CFI(tib)].cx2 +=scontribs[ CFI(tib +  1) ].cx2;
+  // resultat sommes partielles en gmem
+  //if (tib == 0) {
+       gsombloc[ blockIdx.x ] = scontribs[0].c1; 
+       gsombloc[ blockIdx.x + gridDim.x ] = scontribs[0].cx;
+       gsombloc[ blockIdx.x + 2*gridDim.x ] = scontribs[0].cx2;
+
+  //calculs code segment
+       //code seg
+       if (dy > 0 ) d_snake[segment].code_segment = -1 ;
+       if (dy < 0 ) d_snake[segment].code_segment = 1 ;
+       if (dy == 0) d_snake[segment].code_segment = 0 ;
+  }
+       }
+}
+
+__global__ void recalcul_freemans_centre(snake_node_gpu * snake, uint2 * liste_pix, int * d_table_freeman){
+       
+  int id_segment = blockIdx.x ;    
+  int id_base_pix = 5*id_segment ;    
+
+  //calculs freemans, centre et code segment
+  //1 uint4 par segment  
+  int Dio, Djo, Dii, Dji;
+       
+       //freeman out
+       Dio = 1 + liste_pix[id_base_pix +1].x - liste_pix[id_base_pix].x ; 
+       Djo = 1 + liste_pix[id_base_pix +1].y - liste_pix[id_base_pix].y ;
+       snake[id_segment].freeman_out = d_table_freeman[3*Dio + Djo] ;
+               
+       //freeman_in
+       Dii = 1 + liste_pix[id_base_pix +4].x - liste_pix[id_base_pix +3].x ; 
+       Dji = 1 + liste_pix[id_base_pix +4].y - liste_pix[id_base_pix +3].y ;
+       snake[id_segment].freeman_in = d_table_freeman[3*Dii + Dji] ;
+       
+       //centre 
+       snake[id_segment].centre_i = liste_pix[id_base_pix +2].x ;
+       snake[id_segment].centre_j = liste_pix[id_base_pix +2].y ;
+          
+}
+
+
+/*
+  sommme des contribs par bloc -> contribs segment, pour le snake
+
+  execution sur : 1bloc / 1 thread par segment
+ */
+
+__global__ void resomsom_snake(uint64 * somblocs, int nb_nodes, unsigned int nb_bl_seg, snake_node_gpu * d_snake){
+
+  uint64 sdata[3];
+  unsigned int seg = blockIdx.x ;
+  
+  //un thread par segment
+  {
+       sdata[0] = 0;
+       sdata[1] = 0;
+       sdata[2] = 0;
+  }
+
+  for (int b=0; b < nb_bl_seg ; b++){
+       sdata[0] += somblocs[seg*nb_bl_seg + b];
+       sdata[1] += somblocs[(seg + nb_nodes)*nb_bl_seg + b];
+       sdata[2] += somblocs[(seg + 2*nb_nodes)*nb_bl_seg + b];
+  }
+  
+  //totaux en gmem
+  {
+       d_snake[seg].sum_1 = sdata[0];
+       d_snake[seg].sum_x = sdata[1];
+       d_snake[seg].sum_x2 = sdata[2];
+  }      
+}
+
diff --git a/src/lib_kernels_contribs.cu~ b/src/lib_kernels_contribs.cu~
new file mode 100644 (file)
index 0000000..2052ac2
--- /dev/null
@@ -0,0 +1,1043 @@
+#include "constantes.h"
+
+/*
+ * determine et retourne le nb de pixels composant le segment (i,j)-(i1,j1)
+ *
+ */
+__device__ int calcul_nb_pixels(int i, int j, int i1, int j1){
+          int absi, absj,nbpix =0;
+          //MAX( ABS(i1-i) , ABS(j1-j)) + 1
+          if (i1 > i) absi = i1 - i ; else absi = i - i1 ;
+          if (j1 > j) absj = j1 - j ; else absj = j - j1 ;
+          if (absi > absj ) nbpix = absi+1 ; else nbpix = absj+1 ;
+          return nbpix ;
+}
+
+/*
+  construit la liste des coordonnées des 8  positions a tester pour l'ensemble des N noeuds du snake
+  ainsi que le liste des nombres de pixels correspondant (en z, seg avant, en w seg apres)
+  a executer avec N blocs de 8 threads
+*/
+__global__ void liste_positions_a_tester(snake_node_gpu * d_snake, uint4 * liste_positions, uint32 * nb_pix_max, int pas, int nb_nodes, int h, int l){
+  int tib = threadIdx.x;                                    // une position par thread
+  int node = blockIdx.x;                                    // 1 noeud par bloc de threads
+  int node_prec, node_suiv ;                                // indices des nodes
+  int i, j, i1, j1, i2, j2, i3, j3, npix_prec, npix_suiv ;  // coordonnees des noeuds , nb de pixels
+
+  //lecture des coordonnees
+  node_prec = (node == 0)? (nb_nodes-1) : (node - 1) ;
+  node_suiv = (node == nb_nodes-1)? (0) : (node + 1) ;
+  i1 = d_snake[node_prec].posi ;
+  j1 = d_snake[node_prec].posj ;
+  i2 = d_snake[node].posi ;
+  j2 = d_snake[node].posj ;
+  i3 = d_snake[node_suiv].posi ;
+  j3 = d_snake[node_suiv].posj ;
+  
+  switch(tib){                         // on considere un voisinage a 8 points
+  case 0:
+       i = i2 ;
+       if ((j2 + pas) < l) j = j2 + pas ; else j = l-2 ; 
+       break;
+  case 1:
+       if ((j2 + pas) < l) j = j2 + pas ; else j = l-2 ;
+       if (i2 > pas ) i = i2 - pas ; else i = 1 ;
+       break;
+  case 2:
+       if (i2 > pas ) i = i2 - pas ; else i = 1 ;
+       j = j2 ; 
+       break;
+  case 3:
+       if (i2 > pas) i = i2 - pas ; else i = 1 ;
+       if (j2 > pas) j = j2 - pas ; else j = 1 ;
+       break;
+  case 4:
+       i = i2 ;
+       if (j2 > pas) j = j2 - pas ; else j = 1 ;
+       break;
+  case 5:
+       if ((i2 + pas) < h) i = i2 + pas ; else i = h-2 ;
+       if (j2 > pas) j = j2 - pas ; else j = 1 ;
+       break;
+  case 6:
+       if ((i2 + pas) < h) i = i2 + pas ; else i = h-2 ;
+       j = j2 ;
+       break;
+  case 7:
+       if ((i2 + pas) < h) i = i2 + pas ; else i = h-2 ;
+       if ((j2 + pas) < l) j = j2 + pas ; else j = l-2 ;
+       break;
+  }
+
+  //calcul des nombres de pixels dans chaque cas
+  npix_prec =  calcul_nb_pixels(i,j,i1,j1) ;
+  npix_suiv =  calcul_nb_pixels(i,j,i3,j3) ;
+  
+  liste_positions[8*node + tib] = make_uint4(i,j, (uint)npix_prec, (uint)npix_suiv );
+  
+  // calcule du maximum global du nb de pixels
+  if ((node == 0) && (tib == 0))
+       {
+         *nb_pix_max = 0 ;
+         for (int n=0; n<nb_nodes; n++)
+               {
+                 if (liste_positions[n].z > *nb_pix_max) *nb_pix_max = liste_positions[n].z ;
+                 if (liste_positions[n].w > *nb_pix_max) *nb_pix_max = liste_positions[n].w ;
+               }
+       }
+}
+
+/*
+ * calcule :
+ *  - les coordonnees de chaque pixel de chaque segment a evaluer pour les 8 voisins de chaque noeud (pair ou impair)
+ *    cela represente 16 segments par noeud pair/impair
+ *  - les contributions de chacun de ces pixels
+ *  - les sommes, par blocs, des contributions des pixels (les sommes totales sont faites par le kernel somsom)
+ *  - le code de chaque segment envisage
+ */
+
+__global__ void calcul_contribs_segments_blocs_full(snake_node_gpu * d_snake, int nb_nodes, uint4 * liste_points, uint32 npix_max,
+                                                                                                       t_cumul_x * cumul_x, t_cumul_x2 * cumul_x2,  int * d_codes_x16,
+                                                                                                       int l, uint2 * liste_pix, uint64 * gsombloc, bool pairs)
+{
+  // indices des elements
+  int blockSize = blockDim.x ;                                                         // nb threads par bloc
+  int tib = threadIdx.x ;                                                                      // position du thread dans le bloc
+  int nblocs_noeud =  gridDim.x / (nb_nodes/2 + pairs*(nb_nodes%2)) ;   // nb de blocs dédié à chaque noeud 
+  int nblocs_seg = nblocs_noeud / 16 ;                                  // nb de blocs dédiés à un segment de test
+  int idx = blockDim.x*blockIdx.x + threadIdx.x ;                       // position absolue du thread ds la grille
+  int id_interval = blockIdx.x / nblocs_noeud ;                         // indice de l'intervalle du noeud dans la grille
+  int segment = ( blockIdx.x - id_interval*nblocs_noeud )/nblocs_seg ;  // indice du segment de 0 à 15
+  int tis = idx - ( id_interval*nblocs_noeud + segment*nblocs_seg )*blockDim.x ; // position du thread ds le segment
+  int id_base_seg = 16*id_interval + segment ;                          // indice du segment courant
+  int id_base_pix = 5*id_base_seg ;                                                // indice du pixel 0/5 du segment courant dans la liste_pix pour le calcul des freemans
+
+  //tab pour contribs pixels 
+  extern __shared__ tcontribs scumuls[];  
+
+  //coordonnees des extremites de segment
+  uint x1, y1, x2, y2 ;
+  //indices des noeuds precedent(n1), courant(n2), suivant(n3)
+  int n1, n2, n3 ;
+  // pixel courant
+  uint2 p ;
+  // nb de pixels du segment precedent, suivant
+  int xprec, xsuiv ; 
+
+  // determine les indices des noeuds prec, courant, suiv
+  if (pairs)
+       {
+         n1 = 2*id_interval -1 ;
+         n2 = 2*id_interval ;
+         n3 = 2*id_interval +1 ;
+       }
+  else
+       {
+         n1 = 2*id_interval ;
+         n2 = 2*id_interval +1 ;
+         n3 = 2*id_interval +2 ;
+       }
+  //gestion du bouclage du snake
+  if (n1 < 0) n1 = nb_nodes-1 ;
+  if (n3 >= nb_nodes) n3 = 0 ;
+
+  
+  //affectation des differentes positions aux différents segments 'blocs de threads'
+  if ( segment < 8 ){
+       x1 = d_snake[n1].posj ;
+       y1 = d_snake[n1].posi ; 
+       x2 = liste_points[8*n2 + segment].y ;
+       y2 = liste_points[8*n2 + segment].x ;
+  } else {
+       x1 = liste_points[8*n2 + segment-8].y ;
+       y1 = liste_points[8*n2 + segment-8].x ;
+       x2 = d_snake[n3].posj ;
+       y2 = d_snake[n3].posi ;
+  }
+  
+  //params des deplacements
+  int dx=x2-x1;
+  int dy=y2-y1;
+  uint abs_dx = ABS(dx);
+  uint abs_dy = ABS(dy);
+  uint nb_pix = abs_dy>abs_dx?(abs_dy+1):(abs_dx+1);
+  int incx=0, incy=0;
+  
+  
+  //calcul liste des pixels du segment (x1,y1)-(x2,y2)  
+  if (dy > 0) incy=1; else incy=-1 ;
+  if (dx > 0) incx=1; else incx=-1 ;
+  
+  if (tis < nb_pix){
+       if (abs_dy > abs_dx){
+         //1 thread par ligne pente 1/k
+         double k = (double)dx/dy ;
+         //coordonnees pixel
+         p.x = y1 + incy*tis ;
+         p.y = x1 + floor((double)incy*k*tis+0.5) ;
+       } else {
+         //1 thread par colonne pente k          
+         double k=(double)dy/dx ;
+         //coordonnees pixel
+         p.x = y1 + floor((double)(incx*k*tis)+0.5) ;
+         p.y =  x1 + incx*tis ;
+         // ordonnees des pixels suivant & precedent
+         if ( tis > 0 ){ 
+               xsuiv = y1 + floor((double)(incx*k*(tis+1))+0.5) ;
+               xprec = y1 + floor((double)(incx*k*(tis-1))+0.5) ;
+         }
+       }
+       // memorisation des valeurs necessaires au calcul des freemans et des centres
+       if (tis == 0)  liste_pix[id_base_pix] = make_uint2(p.x, p.y) ;
+       if (tis == 1)  liste_pix[id_base_pix +1] = make_uint2(p.x,p.y) ;
+       if (tis == nb_pix/2) liste_pix[id_base_pix +2] = make_uint2(p.x,p.y) ;
+       if (tis == nb_pix-2) liste_pix[id_base_pix +3] = make_uint2(p.x,p.y) ;
+       if (tis == nb_pix-1) liste_pix[id_base_pix +4] = make_uint2(p.x,p.y) ;
+  }
+  
+  __syncthreads();  
+  // calcul contribs individuelles des pixels
+  // dans le cas des segments 'plutot horizontaux', on ne garde qu'une contrib par ligne ; celle du pixel le plus a l'interieur du snake
+  if ( (tis >0) && (tis < nb_pix-1)
+          && ( ((abs_dy <= abs_dx) && ( ( xprec > p.x) || ( xsuiv > p.x)))
+                       || (abs_dy > abs_dx) ) )
+       {
+         int pos = p.x * l + p.y ;
+         scumuls[ CFI(tib)].c1 = 1 + p.y ;  
+         scumuls[ CFI(tib)].cx = cumul_x[ pos ] ;
+         scumuls[CFI(tib)].cx2 = cumul_x2[ pos ];
+       } else {
+         scumuls[ CFI(tib)].c1 = 0;
+         scumuls[ CFI(tib)].cx = 0;
+         scumuls[ CFI(tib)].cx2 = 0;
+  }
+  
+   __syncthreads();
+  // somme des contribs individuelles 
+  // unroll des  sommes partielles en shared memory
+  if (blockSize >= 512) {
+       if (tib < 256) {
+         scumuls[ CFI(tib)].c1 += scumuls[ CFI(tib + 256) ].c1;
+         scumuls[ CFI(tib)].cx += scumuls[ CFI(tib + 256) ].cx;
+         scumuls[ CFI(tib)].cx2 += scumuls[CFI(tib + 256) ].cx2;
+       }
+       __syncthreads();
+  }
+  if (blockSize >= 256) {
+       if (tib < 128) {
+         scumuls[ CFI(tib)].c1 += scumuls[ CFI(tib + 128) ].c1;
+         scumuls[ CFI(tib)].cx += scumuls[ CFI(tib + 128) ].cx;
+         scumuls[ CFI(tib)].cx2 += scumuls[CFI(tib + 128) ].cx2; 
+       }
+       __syncthreads();
+  }
+  if (blockSize >= 128) {
+       if (tib <  64) {
+         scumuls[ CFI(tib)].c1 += scumuls[ CFI(tib +  64) ].c1;
+         scumuls[ CFI(tib)].cx += scumuls[ CFI(tib +  64) ].cx;
+         scumuls[CFI(tib)].cx2 += scumuls[CFI(tib +  64) ].cx2;          
+       }
+       __syncthreads();
+  }
+  
+  //32 threads <==> 1 warp
+ volatile tcontribs * scontribs = scumuls ;
+ if (tib < 32){
+        {
+               scontribs[ CFI(tib)].c1 += scontribs[ CFI(tib + 32) ].c1;
+               scontribs[ CFI(tib)].cx += scontribs[ CFI(tib + 32) ].cx;
+               scontribs[CFI(tib)].cx2 += scontribs[CFI(tib + 32) ].cx2;
+         }
+ if (tib < 16)
+         {
+               scontribs[ CFI(tib)].c1 += scontribs[ CFI(tib + 16) ].c1;
+               scontribs[ CFI(tib)].cx += scontribs[ CFI(tib + 16) ].cx;
+               scontribs[CFI(tib)].cx2 += scontribs[CFI(tib + 16) ].cx2;
+         }
+ if (tib < 8)
+         {
+               scontribs[ CFI(tib)].c1 += scontribs[ CFI(tib +  8) ].c1;
+               scontribs[ CFI(tib)].cx += scontribs[ CFI(tib +  8) ].cx;
+               scontribs[CFI(tib)].cx2 += scontribs[CFI(tib +  8) ].cx2;
+         }
+ if (tib < 4)
+       {
+         scontribs[ CFI(tib)].c1 += scontribs[ CFI(tib +  4) ].c1;
+         scontribs[ CFI(tib)].cx += scontribs[ CFI(tib +  4) ].cx;
+         scontribs[ CFI(tib)].cx2 +=scontribs[ CFI(tib +  4) ].cx2;
+       }
+ if (tib < 2)
+       {  
+         scontribs[ CFI(tib)].c1 += scontribs[ CFI(tib +  2) ].c1;
+         scontribs[ CFI(tib)].cx += scontribs[ CFI(tib +  2) ].cx;
+         scontribs[CFI(tib)].cx2 += scontribs[CFI(tib +  2) ].cx2;
+        } 
+ if (tib == 0)
+       {
+         scontribs[ CFI(tib)].c1 += scontribs[ CFI(tib +  1) ].c1;
+         scontribs[ CFI(tib)].cx += scontribs[ CFI(tib +  1) ].cx;
+         scontribs[CFI(tib)].cx2 += scontribs[CFI(tib +  1) ].cx2;
+  
+  // resultat sommes partielles en gmem
+  //if (tib == 0) {
+       gsombloc[ blockIdx.x ] = scontribs[0].c1 ; 
+       gsombloc[ blockIdx.x + gridDim.x ] = scontribs[0].cx ;
+       gsombloc[ blockIdx.x + 2*gridDim.x ] = scontribs[0].cx2 ;
+       
+ //code seg
+       if (dy > 0 ) d_codes_x16[id_base_seg] = -1 ;
+       if (dy < 0 ) d_codes_x16[id_base_seg] =  1 ;
+       if (dy == 0) d_codes_x16[id_base_seg]=  0 ;
+  }
+ }
+}
+
+/*
+ calcul des freeman et du centre de chaque segment de test
+ a executer sur 'n_interval' blocs de 16 threads
+ soit un thread par segment 
+*/
+__global__ void calcul_freemans_centre(uint2 * liste_pix, int * d_table_freeman, uint4 * d_freemans_x16){
+       
+  int id_segment = threadIdx.x ;    
+  int id_freeman = ( blockDim.x*blockIdx.x + id_segment ) ;
+  int id_base_pix = 5*id_freeman ;
+  
+  //calculs freemans, centre et code segment
+  //1 uint4 par segment  
+  int Dio, Djo, Dii, Dji;
+       
+       //freeman out
+       Dio = 1 + liste_pix[id_base_pix +1].x - liste_pix[id_base_pix].x ; 
+       Djo = 1 + liste_pix[id_base_pix +1].y - liste_pix[id_base_pix].y ;
+       d_freemans_x16[id_freeman].z = d_table_freeman[3*Dio + Djo] ;
+       
+       
+       //freeman_in
+       Dii = 1 + liste_pix[id_base_pix +4].x - liste_pix[id_base_pix +3].x ; 
+       Dji = 1 + liste_pix[id_base_pix +4].y - liste_pix[id_base_pix +3].y ;
+       d_freemans_x16[id_freeman].w = d_table_freeman[3*Dii + Dji] ;
+       
+       //centre 
+       d_freemans_x16[id_freeman].x = liste_pix[id_base_pix +2].x ;
+       d_freemans_x16[id_freeman].y = liste_pix[id_base_pix +2].y ;
+          
+}
+
+
+/*
+  calcul des contribs 1, x et x2 des 16 segments
+  autour du noeud
+  a partir des sommes partielles des blocs
+  1 bloc / 1 thread par segment 
+*/
+
+__global__ void somsom_full(uint64 * somblocs, int nb_nodes, unsigned int nb_bl_seg, uint64 * somsom){
+
+  uint64 sdata[3];
+  unsigned int seg = blockIdx.x ;
+  unsigned int nb_seg = gridDim.x ;
+  
+  //un thread par segment
+  {
+       sdata[0] = 0;
+       sdata[1] = 0;
+       sdata[2] = 0;
+  }
+
+  for (int b=0; b < nb_bl_seg ; b++){ //voir atomicadd 64bits
+       sdata[0] += somblocs[seg*nb_bl_seg + b];
+       sdata[1] += somblocs[(seg + nb_seg)*nb_bl_seg + b];
+       sdata[2] += somblocs[(seg + 2*nb_seg)*nb_bl_seg + b];
+  }
+  
+  //totaux en gmem
+  {
+       somsom[3*seg] = sdata[0];
+       somsom[3*seg + 1] = sdata[1];
+       somsom[3*seg + 2] = sdata[2];
+  }      
+}
+
+/*
+  version GPU de la fonction definie ds src/lib_math.c
+*/
+__device__ bool test_inf_gpu(double arg1, double arg2){
+   if (arg2 > 0)
+        return (arg1 < (arg2*COEF_DECROI)) ;
+  else
+    return (arg1 < (arg2*INV_COEF_DECROI)) ;
+}
+
+/*
+  version GPU de la fonction codage_niveau_gris_hyp_gaussienne
+ */
+__device__ double codage_gl_hyp_gauss(uint64 stat_sum_1, uint64 stat_sum_x, uint64 stat_sum_x2,
+                                                                         uint64 n_dim, uint64 SUM_X, uint64 SUM_X2){
+  uint64 stat_sum_xe ;  /* somme des xn region exterieure */
+  uint32 ne ;             /* nombre de pixel region exterieure */
+  double sigi2, sige2; /* variance region interieure et exterieure */
+  
+  /* variance des valeurs des niveaux de gris a l'interieur du snake */
+  sigi2 = 
+    (double)stat_sum_x2/(double)stat_sum_1 - 
+    ((double)stat_sum_x/stat_sum_1)*((double)stat_sum_x/stat_sum_1) ;
+
+  /* variance des valeurs des niveaux de gris a l'exterieur du snake */
+  ne = n_dim-stat_sum_1 ;
+  stat_sum_xe = SUM_X - stat_sum_x ;
+  sige2 =
+    ((double)SUM_X2-stat_sum_x2)/ne - 
+    ((double)stat_sum_xe/ne)*((double)stat_sum_xe/ne) ;
+  
+  if ((sigi2 > 0)&&(sige2 > 0))
+  return  0.5*((double)stat_sum_1*log(sigi2) + (double)ne*log(sige2)) ;
+  return -1 ;
+}
+
+/*
+  soustrait, pour chaque intervalle [N1--Nx--N2] 
+  les contributions des segments N1--Nx et Nx--N2
+  
+  A executer par nnodes blocs de 1 thread par intervalle
+ */
+
+__global__ void soustrait_aux_stats_2N_segments_noeud(snake_node_gpu * d_snake, int64 * d_stats_snake, int64 * d_stats_ref, 
+                                                                                                         t_cumul_x * cumul_x, t_cumul_x2 * cumul_x2,
+                                                                                                         int * TABLE_CODAGE, uint32 l
+                                                                                                         )
+{
+  int nnodes = gridDim.x ;
+  int id_nx, id_nprec, id_nprecprec, id_nsuiv ;
+  int code_noeud, pos; 
+  __shared__ int64 s_stats_snake[3] ;
+
+  id_nx = blockIdx.x ;
+  if (id_nx == 0) id_nprec = nnodes - 1;
+  else id_nprec = id_nx - 1;
+  if (id_nprec == 0) id_nprecprec = nnodes -1 ;
+  else id_nprecprec = id_nprec - 1 ;
+  if (id_nx == nnodes-1) id_nsuiv = 0;
+  else id_nsuiv = id_nx + 1 ;
+  
+  //init avec les valeurs du contour actuel
+  s_stats_snake[0] = d_stats_snake[0] ;
+  s_stats_snake[1] = d_stats_snake[1] ;
+  s_stats_snake[2] = d_stats_snake[2] ;
+
+  /* segment Na -- Nx */
+  if (d_snake[id_nprec].code_segment > 0)
+    {
+     s_stats_snake[0] -= d_snake[id_nprec].sum_1 ;
+     s_stats_snake[1] -= d_snake[id_nprec].sum_x ;
+     s_stats_snake[2] -= d_snake[id_nprec].sum_x2 ;
+    }
+  else if (d_snake[id_nprec].code_segment < 0)
+    {
+        s_stats_snake[0] += d_snake[id_nprec].sum_1 ;
+     s_stats_snake[1] += d_snake[id_nprec].sum_x ;
+     s_stats_snake[2] += d_snake[id_nprec].sum_x2 ;
+    }
+  // else (code_segment_NaNx == 0), on ne fait rien
+  
+  /* gestion des pixels connectant les segments */
+  /* pixel de depart du segment Na --> Nx */
+  pos = d_snake[id_nprecprec].freeman_in*8 + d_snake[id_nprec].freeman_out ;
+  code_noeud = TABLE_CODAGE[pos] ;
+  pos = d_snake[id_nprec].posi*l + d_snake[id_nprec].posj ;
+  if (code_noeud > 0)
+    {
+     s_stats_snake[0] -= 1 + d_snake[id_nprec].posj ;
+     s_stats_snake[1] -= cumul_x[pos] ;
+        s_stats_snake[2] -= cumul_x2[pos];
+    }
+  else if (code_noeud < 0)
+    {
+        s_stats_snake[0] += 1 + d_snake[id_nprec].posj ;
+     s_stats_snake[1] += cumul_x[pos] ;
+        s_stats_snake[2] += cumul_x2[pos];
+    }
+  // else (code_noeud == 0), on ne fait rien
+  
+  /* -------------------------- */
+  /* -------------------------- */
+  /* segment Nx -- Nb */
+  if ( d_snake[id_nx].code_segment > 0 )
+    {
+      // on soustrait la contribution 
+        s_stats_snake[0] -= d_snake[id_nx].sum_1 ;
+     s_stats_snake[1] -= d_snake[id_nx].sum_x ;
+     s_stats_snake[2] -= d_snake[id_nx].sum_x2 ;
+    }
+  else if ( d_snake[id_nx].code_segment < 0)
+    {
+        s_stats_snake[0] += d_snake[id_nx].sum_1 ;
+     s_stats_snake[1] += d_snake[id_nx].sum_x ;
+     s_stats_snake[2] += d_snake[id_nx].sum_x2 ;
+    }
+  // else (code_segment_NxNb == 0), on ne fait rien
+  
+  /* gestion des pixels connectant les segments */
+  /* pixel de depart du segment Nx --> Nb */
+  pos = d_snake[id_nprec].freeman_in*8 + d_snake[id_nx].freeman_out ;
+  code_noeud = TABLE_CODAGE[pos] ;
+  pos = d_snake[id_nx].posi*l + d_snake[id_nx].posj ;
+  if (code_noeud > 0)
+    {
+     s_stats_snake[0] -= 1 + d_snake[id_nx].posj  ;
+     s_stats_snake[1] -= cumul_x[pos] ;
+        s_stats_snake[2] -= cumul_x2[pos];
+    }
+  else if (code_noeud < 0)
+    {
+        s_stats_snake[0] += 1 + d_snake[id_nx].posj ;
+     s_stats_snake[1] += cumul_x[pos] ;
+        s_stats_snake[2] += cumul_x2[pos];
+    }
+  // else (code_noeud == 0), on ne fait rien
+  
+  /* pixel d'arrivee du segment Nx --> Nb */
+  pos = d_snake[id_nx].freeman_in*8 + d_snake[id_nsuiv].freeman_out ;
+  code_noeud = TABLE_CODAGE[pos] ;
+  pos = d_snake[id_nsuiv].posi*l +  d_snake[id_nsuiv].posj ;
+  if (code_noeud > 0)
+    {
+        s_stats_snake[0] -= 1 + d_snake[id_nsuiv].posj ;
+     s_stats_snake[1] -= cumul_x[pos] ;
+        s_stats_snake[2] -= cumul_x2[pos];
+    }
+  else if (code_noeud < 0)
+    {
+        s_stats_snake[0] += 1 + d_snake[id_nsuiv].posj ;
+     s_stats_snake[1] += cumul_x[pos] ;
+        s_stats_snake[2] += cumul_x2[pos];
+        }
+  // else (code_noeud == 0), on ne fait rien
+  __syncthreads();
+  
+  d_stats_ref[3*id_nx] = s_stats_snake[0] ;
+  d_stats_ref[3*id_nx + 1] = s_stats_snake[1] ;
+  d_stats_ref[3*id_nx + 2] = s_stats_snake[2] ;
+}
+
+
+/*
+  calcul des stats associees a chaque position de test
+
+  EXEC : sur n_interval blocs de 8 threads
+*/
+__global__ void calcul_stats_full(snake_node_gpu * d_snake, int nnodes, bool pairs, int64 * d_stats_snake,
+                                                                 int64 * d_stats_ref, int64 * d_stats, uint64 * d_contribs,
+                                                                 uint4 * d_liste_points, int * code_segment, uint4 * d_freemans,
+                                                                 int * d_table_codes, t_cumul_x * cumul_x, t_cumul_x2 * cumul_x2,
+                                                                 uint32 h, uint32 l, double * vrais, double * vrais_min, bool * move){
+
+  int interval = blockIdx.x ;
+  int seg = threadIdx.x ;
+  int thread = seg;
+  int id_nx, id_nprec, id_nprecprec, id_nsuiv, id_seg ;
+  int code_noeud; 
+  __shared__ int64 s_stats_snake[3*8] ;
+
+  id_nx = 2*interval + !pairs ;
+  if (id_nx == 0) id_nprec = nnodes - 1 ;
+  else id_nprec = id_nx - 1 ;
+  if (id_nprec == 0) id_nprecprec = nnodes -1 ;
+  else id_nprecprec = id_nprec - 1 ;
+  if (id_nx == nnodes-1) id_nsuiv = 0 ;
+  else id_nsuiv = id_nx + 1 ;
+  
+  //chargement en smem , prevoir CFI car on a 24x64bits par blocs => conflits 
+  s_stats_snake[3*thread + 0] = d_stats_ref[3*id_nx] ;
+  s_stats_snake[3*thread + 1] = d_stats_ref[3*id_nx + 1] ;
+  s_stats_snake[3*thread + 2] = d_stats_ref[3*id_nx + 2] ;
+  
+  //stats segments N1-Nx
+  id_seg = 16*interval + seg ;
+  if ( code_segment[id_seg] > 0 ){
+       s_stats_snake[3*thread +0]  += d_contribs[3*id_seg] ;
+       s_stats_snake[3*thread +1]  += d_contribs[3*id_seg + 1 ] ;
+       s_stats_snake[3*thread +2]  += d_contribs[3*id_seg + 2 ] ;
+  } else if ( code_segment[16*interval + seg] < 0 ) {
+       s_stats_snake[3*thread +0]  -= d_contribs[3*id_seg] ;
+       s_stats_snake[3*thread +1]  -= d_contribs[3*id_seg + 1] ;
+       s_stats_snake[3*thread +2]  -= d_contribs[3*id_seg + 2] ;
+  }
+  
+  //stats noeud N1(i1,j1)
+  int fo_N1 = d_freemans[id_seg].z ;
+  int fi_Nprecprec = d_snake[id_nprecprec].freeman_in ;
+  int pos = d_snake[id_nprec].posi*l + d_snake[id_nprec].posj ;
+   
+  code_noeud = d_table_codes[fi_Nprecprec*8 + fo_N1];
+  if (code_noeud > 0){
+       s_stats_snake[3*thread +0] += 1 + d_snake[id_nprec].posj ;
+       s_stats_snake[3*thread +1] += cumul_x[ pos ] ;
+       s_stats_snake[3*thread +2] += cumul_x2[pos ] ;
+  } else if (code_noeud < 0){
+       s_stats_snake[3*thread +0] -= 1 + d_snake[id_nprec].posj ;
+       s_stats_snake[3*thread +1] -= cumul_x[ pos ] ;
+       s_stats_snake[3*thread +2] -= cumul_x2[pos ] ;
+  }
+  
+  //stats noeud Nx
+  int fo_Nx = d_freemans[id_seg + 8].z ;
+  int fi_Nx = d_freemans[id_seg].w ;
+  int Nxi = d_liste_points[8*id_nx + seg].x ;
+  int Nxj = d_liste_points[8*id_nx + seg].y ;
+  pos = Nxi*l + Nxj ;
+  
+  code_noeud = d_table_codes[fi_Nx*8 + fo_Nx];
+  if (code_noeud > 0){
+       s_stats_snake[3*thread +0] += 1 + Nxj ;
+       s_stats_snake[3*thread +1] += cumul_x[ pos ] ;
+       s_stats_snake[3*thread +2] += cumul_x2[pos ] ;
+  }
+  if (code_noeud < 0){
+       s_stats_snake[3*thread +0] -= 1 + Nxj ;
+       s_stats_snake[3*thread +1] -= cumul_x[ pos ] ;
+       s_stats_snake[3*thread +2] -= cumul_x2[pos ] ;
+  }
+  
+  //stats segments Nx-N2
+  seg += 8;
+  id_seg = 16*interval + seg ;
+  if ( code_segment[id_seg] > 0 ){
+       s_stats_snake[3*thread +0]  += d_contribs[3*id_seg] ;
+       s_stats_snake[3*thread +1]  += d_contribs[3*id_seg + 1] ;
+       s_stats_snake[3*thread +2]  += d_contribs[3*id_seg + 2] ;
+  }
+  if ( code_segment[id_seg] < 0 ) {
+       s_stats_snake[3*thread +0]  -= d_contribs[3*id_seg] ;
+       s_stats_snake[3*thread +1]  -= d_contribs[3*id_seg + 1] ;
+       s_stats_snake[3*thread +2]  -= d_contribs[3*id_seg + 2] ;
+  }
+  
+  //stats noeud N2(i2,j2)
+  int fi_N2 = d_freemans[id_seg].w ;
+  int fo_N2 = d_snake[id_nsuiv].freeman_out ;
+  pos = d_snake[id_nsuiv].posi*l + d_snake[id_nsuiv].posj ;
+  
+  code_noeud = d_table_codes[fi_N2*8 + fo_N2];
+  if (code_noeud > 0){
+       s_stats_snake[3*thread +0] += 1 + d_snake[id_nsuiv].posj ;
+       s_stats_snake[3*thread +1] += cumul_x[ pos ] ;
+       s_stats_snake[3*thread +2] += cumul_x2[pos ] ;
+  }
+  if (code_noeud < 0){
+       s_stats_snake[3*thread +0] -= 1 + d_snake[id_nsuiv].posj ;
+       s_stats_snake[3*thread +1] -= cumul_x[ pos ] ;
+       s_stats_snake[3*thread +2] -= cumul_x2[pos ] ;
+  }
+  
+         //TODO
+         //voir si on peut s'en passer
+  d_stats[3*(8*interval + thread)] = s_stats_snake[3*thread +0]; 
+  d_stats[3*(8*interval + thread) + 1] = s_stats_snake[3*thread +1];
+  d_stats[3*(8*interval + thread) + 2] = s_stats_snake[3*thread +2];
+  
+  //codage hyp gaussienne  
+  uint64 stat_sum_xe[8] ;    //somme des xn region exterieure 
+  uint32 ne[8] ;             // nombre de pixels region exterieure 
+  double sigi2[8], sige2[8]; //  carres des variances, regions interieure et exterieure 
+
+  /* variance des valeurs des niveaux de gris a l'interieur du snake */
+  sigi2[thread] =
+       ((double)s_stats_snake[3*thread +2]/(double)s_stats_snake[3*thread +0]) -
+       ((double)s_stats_snake[3*thread +1]/s_stats_snake[3*thread +0])*((double)s_stats_snake[3*thread +1]/s_stats_snake[3*thread +0]) ;
+  
+  /* variance des valeurs des niveaux de gris a l'exterieur du snake */
+  ne[thread] = h*l-s_stats_snake[3*thread +0] ;
+  stat_sum_xe[thread] = d_stats_snake[4] - s_stats_snake[3*thread +1] ;
+  sige2[thread] =
+       (double)(d_stats_snake[5]-s_stats_snake[3*thread +2])/(double)ne[thread] -
+       ((double)stat_sum_xe[thread]/ne[thread])*((double)stat_sum_xe[thread]/ne[thread]) ;
+
+  if (sige2[thread]>0 && sigi2[thread]>0)
+       vrais[8*interval + thread] = 0.5*((double)s_stats_snake[3*thread]*log(sigi2[thread]) + (double)ne[thread]*log(sige2[thread])) ;
+  else
+       vrais[8*interval + thread] = -1.0;
+
+  if ( thread == 0 ){
+        //init move
+       move[id_nx] = false ;
+       int pos_optim = -1;
+       double vrais_tmp = *vrais_min;
+       for (int v=0; v < 8; v++){
+         if ( (vrais[8*interval + v] > 0) && (vrais[8*interval + v] < vrais_tmp*COEF_DECROI) ) {
+               vrais_tmp = vrais[8*interval + v];
+               pos_optim = v;
+         }
+       }
+       if (pos_optim >-1){
+        if ( !croisement(d_snake, id_nx, d_liste_points[8*id_nx + pos_optim].x, d_liste_points[8*id_nx + pos_optim].y, nnodes) )
+               {
+                 /*maj data snake*/
+                 move[id_nx] = true ;
+                 //new position 
+                 d_snake[id_nx].posi = d_liste_points[8*id_nx + pos_optim].x ;
+                 d_snake[id_nx].posj = d_liste_points[8*id_nx + pos_optim].y ;
+                 //nb pixels segment precedent
+                 d_snake[id_nprec].nb_pixels = d_liste_points[8*id_nx + pos_optim].z ;
+                 //nb pixels segment suivant
+                 d_snake[id_nx].nb_pixels = d_liste_points[8*id_nx + pos_optim].w ;
+                 //contribs segment precedent
+                 d_snake[id_nprec].sum_1 = d_contribs[3*(16*interval + pos_optim)] ;
+                 d_snake[id_nprec].sum_x = d_contribs[3*(16*interval + pos_optim) + 1] ;
+                 d_snake[id_nprec].sum_x2 = d_contribs[3*(16*interval + pos_optim) + 2] ;
+                 //contribs segment suivant
+                 d_snake[id_nx].sum_1 = d_contribs[3*(16*interval + pos_optim + 8)] ;
+                 d_snake[id_nx].sum_x = d_contribs[3*(16*interval + pos_optim + 8) + 1] ;
+                 d_snake[id_nx].sum_x2 = d_contribs[3*(16*interval + pos_optim + 8) + 2] ;
+                 //freemans segment precedent
+                 d_snake[id_nprec].freeman_out = d_freemans[16*interval + pos_optim].z ;
+                 d_snake[id_nprec].freeman_in = d_freemans[16*interval + pos_optim].w ;
+                 //freemans segment suivant
+                 d_snake[id_nx].freeman_out = d_freemans[16*interval + pos_optim + 8].z ;
+                 d_snake[id_nx].freeman_in = d_freemans[16*interval + pos_optim + 8].w ;
+                 //codes segment precedent
+                 d_snake[id_nprec].code_segment = code_segment[16*interval + pos_optim] ;
+                 //code segment suivant
+                 d_snake[id_nx].code_segment = code_segment[16*interval + pos_optim + 8] ;
+                 //centre segment precedent
+                 d_snake[id_nprec].centre_i = d_freemans[16*interval + pos_optim ].x ;
+                 d_snake[id_nprec].centre_j = d_freemans[16*interval + pos_optim ].y ;
+                 //centre segment suivant 
+                 d_snake[id_nx].centre_i = d_freemans[16*interval + pos_optim + 8].x ;
+                 d_snake[id_nx].centre_j = d_freemans[16*interval + pos_optim + 8].y ;
+                 
+               }                          
+       }
+  }
+
+  
+}
+
+__global__ void recalcul_stats_snake(snake_node_gpu * d_snake, int  nnodes, int64 * d_stats_snake, double * vrais_min,
+                                                                        t_cumul_x * cumul_x, t_cumul_x2 * cumul_x2, int * TABLE_CODAGE, uint32 l
+                                                                        )
+{
+  
+  int id_nx, id_nprec, id_nprecprec ;
+  int code_noeud, code_segment, pos; 
+  int64 s_stats_snake[3] ;
+  //init stats en shared mem
+  s_stats_snake[0] = 0 ;
+  s_stats_snake[1] = 0 ;
+  s_stats_snake[2] = 0 ;
+
+    
+  for (id_nx = 0; id_nx < nnodes; id_nx++)
+    {
+         if (id_nx == 0) id_nprec = nnodes - 1;
+         else id_nprec = id_nx - 1;
+         if (id_nprec == 0) id_nprecprec = nnodes -1 ;
+         else id_nprecprec = id_nprec - 1 ;
+      /* gestion des segments partant du noeud */
+      /* vers le noeud suivant dans l'ordre trigo */
+      code_segment = d_snake[id_nprec].code_segment ;
+      if (code_segment > 0)
+               {
+                 /* on somme les contributions */
+                 s_stats_snake[0] += d_snake[id_nprec].sum_1 ;
+                 s_stats_snake[1] += d_snake[id_nprec].sum_x ;
+                 s_stats_snake[2] += d_snake[id_nprec].sum_x2 ;
+               }
+      else if (code_segment < 0)
+               {
+                 /* on soustrait les contributions */
+                 s_stats_snake[0] -= d_snake[id_nprec].sum_1 ;
+                 s_stats_snake[1] -= d_snake[id_nprec].sum_x ;
+                 s_stats_snake[2] -= d_snake[id_nprec].sum_x2 ;
+               }
+      // else (code_segment == 0), on ne fait rien
+      /* gestion des pixels connectant les segments */
+         pos = d_snake[id_nprecprec].freeman_in*8 + d_snake[id_nprec].freeman_out ;
+      code_noeud = TABLE_CODAGE[pos] ;
+         pos = d_snake[id_nprec].posi*l + d_snake[id_nprec].posj ;
+   
+      if (code_noeud > 0)
+               {
+                 /* on somme les contributions */
+                 s_stats_snake[0] += 1 + d_snake[id_nprec].posj ;
+                 s_stats_snake[1] += cumul_x[pos] ;
+                 s_stats_snake[2] += cumul_x2[pos] ;
+               }
+      else if (code_noeud < 0)
+               {
+                 /* on soustrait les contributions */
+                 s_stats_snake[0] -= 1 + d_snake[id_nprec].posj ;
+                 s_stats_snake[1] -= cumul_x[pos] ;
+                 s_stats_snake[2] -= cumul_x2[pos] ;
+               }
+      // else (code_pixel == 0), on ne fait rien
+    }
+  d_stats_snake[0] = s_stats_snake[0] ;
+  d_stats_snake[1] = s_stats_snake[1] ;
+  d_stats_snake[2] = s_stats_snake[2] ;
+  
+  *vrais_min = codage_gl_hyp_gauss(s_stats_snake[0], s_stats_snake[1], s_stats_snake[2],
+                                                                  d_stats_snake[3], d_stats_snake[4], d_stats_snake[5]);
+}
+
+
+__global__ void ajoute_noeuds(snake_node_gpu * snake, snake_node_gpu * snake_tmp, int nnodes, int seuil, int * new_nb_nodes){
+
+  volatile snake_node_gpu * st = snake_tmp ;
+
+ int id_cpy = 0;  
+ for (int id_nx=0; id_nx < nnodes; id_nx++){
+       //position du noeud existant
+       st[id_cpy].posi =  snake[id_nx].posi ;
+    st[id_cpy].posj =  snake[id_nx].posj ;
+        
+       id_cpy++ ;
+       
+       if ( snake[id_nx].nb_pixels > seuil)
+       {
+               //position du nouveau noeud
+               st[id_cpy].posi = snake[id_nx].centre_i ;
+               st[id_cpy].posj = snake[id_nx].centre_j ;
+               id_cpy++ ;
+       }       
+ }
+ for( int node=0; node<id_cpy; node++ ){
+   snake[node].posi = st[node].posi ;
+   snake[node].posj = st[node].posj ;
+ }
+*new_nb_nodes = id_cpy-nnodes ;
+}
+  
+
+
+
+
+__global__ void recalcul_contribs_segments_snake(snake_node_gpu * d_snake, int nb_nodes,
+                                                                                                t_cumul_x * cumul_x, t_cumul_x2 * cumul_x2, 
+                                                                                                int l, uint2 * liste_pix, uint64 * gsombloc )
+{
+  // indices des elements
+  int blockSize = blockDim.x ;
+  int tib = threadIdx.x ;
+  int nblocs_seg =  gridDim.x / nb_nodes ;
+  int idx = blockDim.x*blockIdx.x + threadIdx.x ;
+  int segment = blockIdx.x / nblocs_seg ;
+  int tis = idx - segment*nblocs_seg*blockDim.x ;
+
+  //tab pour contribs pixels 
+  extern __shared__ tcontribs scumuls[];
+
+  //indices des noeuds
+  uint x1, y1, x2, y2 ;
+  int n1, n2 ;
+  uint2 p ;
+  int xsuiv, xprec ;
+  
+  n1 = segment ;
+  n2 = segment +1 ;
+  //gestion du bouclage du snake
+  if (n2 >= nb_nodes) n2 = 0 ;
+  
+  //affectation des differentes positions aux différents segments 'blocs de threads'
+       x1 = d_snake[n1].posj ;
+       y1 = d_snake[n1].posi ;
+       x2 = d_snake[n2].posj ;
+       y2 = d_snake[n2].posi ;
+  
+  //params des deplacements
+  int dx=x2-x1;
+  int dy=y2-y1;
+  uint abs_dx = ABS(dx);
+  uint abs_dy = ABS(dy);
+  uint nb_pix = abs_dy>abs_dx?(abs_dy+1):(abs_dx+1); // alternative -> lecture ds liste_points[]
+  int incx=0, incy=0;
+  
+  
+  //calcul liste des pixels du segment (x1,y1)-(x2,y2)  
+  if (dy > 0) incy=1; else incy=-1 ;
+  if (dx > 0) incx=1; else incx=-1 ;
+  
+  if (tis < nb_pix){
+       if (abs_dy > abs_dx){
+         //1 thread par ligne
+         double k = (double)dx/dy ;
+         p.x = y1 + incy*tis ;
+         p.y = x1 + floor((double)incy*k*tis+0.5) ;
+
+       } else {
+         //1 thread par colonne          
+         double k=(double)dy/dx ;
+         p.x = y1 + floor((double)(incx*k*tis)+0.5) ;
+         p.y =  x1 + incx*tis ;
+         if ( tis > 0 ){ 
+               xsuiv = y1 + floor((double)(incx*k*(tis+1))+0.5) ;
+               xprec = y1 + floor((double)(incx*k*(tis-1))+0.5) ;
+         }
+
+       }
+       if (tis == 0)  liste_pix[5*segment] = make_uint2(p.x, p.y) ;
+       if (tis == 1)  liste_pix[5*segment +1] = make_uint2(p.x,p.y) ;
+    if (tis == nb_pix/2) liste_pix[5*segment +2] = make_uint2(p.x,p.y) ;
+    if (tis == nb_pix-2) liste_pix[5*segment +3] = make_uint2(p.x,p.y) ;
+    if (tis == nb_pix-1) liste_pix[5*segment +4] = make_uint2(p.x,p.y) ;
+  }
+  __syncthreads();
+    
+  //calcul contribs individuelles des pixels
+  
+  if ( (tis >0) && (tis < nb_pix-1)
+          && ( ( (abs_dy <= abs_dx) && ( ( xprec > p.x) || ( xsuiv > p.x)) )
+                       || (abs_dy > abs_dx) ) )
+       {
+       int pos = p.x * l + p.y ;
+       scumuls[ CFI(tib)].c1 = 1+p.y;        
+       scumuls[ CFI(tib)].cx = cumul_x[ pos ] ;
+       scumuls[CFI(tib)].cx2 = cumul_x2[ pos ];
+  } else {
+       scumuls[ CFI(tib)].c1 = 0;
+       scumuls[ CFI(tib)].cx = 0;
+       scumuls[CFI(tib)].cx2 = 0;
+  }
+  
+   __syncthreads();
+  //somme des contribs individuelles 
+  // unroll des  sommes partielles en smem
+  
+  if (blockSize >= 512) {
+       if (tib < 256) {
+         scumuls[ CFI(tib)].c1 += scumuls[ CFI(tib + 256) ].c1;
+         scumuls[ CFI(tib)].cx += scumuls[ CFI(tib + 256) ].cx;
+         scumuls[CFI(tib)].cx2 += scumuls[CFI(tib + 256) ].cx2;
+       }
+       __syncthreads();
+  }
+  if (blockSize >= 256) {
+       if (tib < 128) {
+         scumuls[ CFI(tib)].c1 += scumuls[ CFI(tib + 128) ].c1;
+         scumuls[ CFI(tib)].cx += scumuls[ CFI(tib + 128) ].cx;
+         scumuls[CFI(tib)].cx2 += scumuls[CFI(tib + 128) ].cx2; 
+       }
+       __syncthreads();
+  }
+  if (blockSize >= 128) {
+       if (tib <  64) {
+         scumuls[ CFI(tib)].c1 += scumuls[ CFI(tib +  64) ].c1;
+         scumuls[ CFI(tib)].cx += scumuls[ CFI(tib +  64) ].cx;
+         scumuls[CFI(tib)].cx2 += scumuls[ CFI(tib +  64) ].cx2;         
+       }
+       __syncthreads();
+  }
+  
+  //32 threads <==> 1 warp
+  volatile tcontribs * scontribs = scumuls ;
+  if (tib < 32)
+       {
+         {
+               scontribs[ CFI(tib)].c1 += scontribs[ CFI(tib + 32) ].c1;
+               scontribs[ CFI(tib)].cx += scontribs[ CFI(tib + 32) ].cx;
+               scontribs[ CFI(tib)].cx2 +=scontribs[ CFI(tib + 32) ].cx2;
+         }
+         if (tib<16)
+         {
+               scontribs[ CFI(tib)].c1 += scontribs[ CFI(tib + 16) ].c1;
+               scontribs[ CFI(tib)].cx += scontribs[ CFI(tib + 16) ].cx;
+               scontribs[ CFI(tib)].cx2 +=scontribs[ CFI(tib + 16) ].cx2;
+         }
+         if (tib<8)
+         {
+               scontribs[ CFI(tib)].c1 += scontribs[ CFI(tib +  8) ].c1;
+               scontribs[ CFI(tib)].cx += scontribs[ CFI(tib +  8) ].cx;
+               scontribs[ CFI(tib)].cx2 +=scontribs[ CFI(tib +  8) ].cx2;}
+       if (tib<4){     
+         scontribs[ CFI(tib)].c1 += scontribs[ CFI(tib +  4) ].c1;
+         scontribs[ CFI(tib)].cx += scontribs[ CFI(tib +  4) ].cx;
+         scontribs[ CFI(tib)].cx2 +=scontribs[ CFI(tib +  4) ].cx2;
+         }
+         if (tib<2){
+         scontribs[ CFI(tib)].c1 += scontribs[ CFI(tib +  2) ].c1;
+         scontribs[ CFI(tib)].cx += scontribs[ CFI(tib +  2) ].cx;
+         scontribs[ CFI(tib)].cx2 +=scontribs[ CFI(tib +  2) ].cx2;
+         }
+         if (tib==0){
+         scontribs[ CFI(tib)].c1 += scontribs[ CFI(tib +  1) ].c1;
+         scontribs[ CFI(tib)].cx += scontribs[ CFI(tib +  1) ].cx;
+         scontribs[ CFI(tib)].cx2 +=scontribs[ CFI(tib +  1) ].cx2;
+  // resultat sommes partielles en gmem
+  //if (tib == 0) {
+       gsombloc[ blockIdx.x ] = scontribs[0].c1; 
+       gsombloc[ blockIdx.x + gridDim.x ] = scontribs[0].cx;
+       gsombloc[ blockIdx.x + 2*gridDim.x ] = scontribs[0].cx2;
+
+  //calculs code segment
+       //code seg
+       if (dy > 0 ) d_snake[segment].code_segment = -1 ;
+       if (dy < 0 ) d_snake[segment].code_segment = 1 ;
+       if (dy == 0) d_snake[segment].code_segment = 0 ;
+  }
+       }
+}
+
+__global__ void recalcul_freemans_centre(snake_node_gpu * snake, uint2 * liste_pix, int * d_table_freeman){
+       
+  int id_segment = blockIdx.x ;    
+  int id_base_pix = 5*id_segment ;    
+
+  //calculs freemans, centre et code segment
+  //1 uint4 par segment  
+  int Dio, Djo, Dii, Dji;
+       
+       //freeman out
+       Dio = 1 + liste_pix[id_base_pix +1].x - liste_pix[id_base_pix].x ; 
+       Djo = 1 + liste_pix[id_base_pix +1].y - liste_pix[id_base_pix].y ;
+       snake[id_segment].freeman_out = d_table_freeman[3*Dio + Djo] ;
+               
+       //freeman_in
+       Dii = 1 + liste_pix[id_base_pix +4].x - liste_pix[id_base_pix +3].x ; 
+       Dji = 1 + liste_pix[id_base_pix +4].y - liste_pix[id_base_pix +3].y ;
+       snake[id_segment].freeman_in = d_table_freeman[3*Dii + Dji] ;
+       
+       //centre 
+       snake[id_segment].centre_i = liste_pix[id_base_pix +2].x ;
+       snake[id_segment].centre_j = liste_pix[id_base_pix +2].y ;
+          
+}
+
+
+/*
+  sommme des contribs par bloc -> contribs segment, pour le snake
+
+  execution sur : 1bloc / 1 thread par segment
+ */
+
+__global__ void resomsom_snake(uint64 * somblocs, int nb_nodes, unsigned int nb_bl_seg, snake_node_gpu * d_snake){
+
+  uint64 sdata[3];
+  unsigned int seg = blockIdx.x ;
+  
+  //un thread par segment
+  {
+       sdata[0] = 0;
+       sdata[1] = 0;
+       sdata[2] = 0;
+  }
+
+  for (int b=0; b < nb_bl_seg ; b++){
+       sdata[0] += somblocs[seg*nb_bl_seg + b];
+       sdata[1] += somblocs[(seg + nb_nodes)*nb_bl_seg + b];
+       sdata[2] += somblocs[(seg + 2*nb_nodes)*nb_bl_seg + b];
+  }
+  
+  //totaux en gmem
+  {
+       d_snake[seg].sum_1 = sdata[0];
+       d_snake[seg].sum_x = sdata[1];
+       d_snake[seg].sum_x2 = sdata[2];
+  }      
+}
+
diff --git a/src/lib_kernels_contribs.h b/src/lib_kernels_contribs.h
new file mode 100644 (file)
index 0000000..486b0ba
--- /dev/null
@@ -0,0 +1,33 @@
+#ifndef __KERNEL_CONTRIB__
+#define __KERNEL_CONTRIB__
+
+__global__ void liste_positions_a_tester(snake_node_gpu * d_snake, uint4 * liste_positions, uint32 * nb_pix_max,
+                                                                                int pas, int nb_nodes, int h, int l);
+__global__ void calcul_contribs_segments_snake(snake_node_gpu * d_snake, int nb_nodes,
+                                                                                          uint64 * cumul_1, uint64 * cumul_x, uint64 * cumul_x2, 
+                                                                                          int l, uint2 * liste_pix, uint64 * gsombloc, int * d_table_freeman);
+
+__global__ void somsom_snake(uint64 * somblocs, int nb_nodes, unsigned int nb_bl_seg, snake_node_gpu * d_snake);
+
+
+__global__ void calcul_contribs_segments_blocs_full(snake_node_gpu * d_snake, int nb_nodes, uint4 * liste_points, uint32 npix_max,
+                                                                                                       uint64 * cumul_1, uint64 * cumul_x, uint64 * cumul_x2,  int * d_codes_x16,
+                                                                                                       int l, uint2 * liste_pix, uint64 * gsombloc, int * d_table_freeman,
+                                                                                                       uint4 * d_freemans_x16,  bool pairs);
+
+__global__ void somsom_full(uint64 * somblocs, int nb_nodes, unsigned int nb_bl_seg, uint64 * somsom, bool pairs);
+__device__ bool test_inf_gpu(double arg1, double arg2);
+
+__global__ void calcul_stats_snake(snake_node_gpu * d_snake, int  nnodes, int64 * d_stats_snake, double * vrais_min,
+                                                                  uint64 * cumul_1, uint64 * cumul_x, uint64 * cumul_x2, int * TABLE_CODAGE, uint32 l);
+
+__global__ void soustrait_aux_stats_2N_segments_noeud(snake_node_gpu * d_snake, int64 * d_stats_snake, int64 * d_stats_ref, 
+                                                                                                         uint64 * cumul_1, uint64 * cumul_x, uint64 * cumul_x2,
+                                                                                                         int * TABLE_CODAGE, uint32 l);
+
+__global__ void calcul_stats_full(snake_node_gpu * d_snake, int nnodes, bool pairs, int64 * d_stats_snake,
+                                                                 int64 * d_stats_ref, int64 * d_stats, uint64 * d_contribs,
+                                                                 uint4 * d_liste_points, int * code_segment, uint4 * d_freemans,
+                                                                 int * d_table_codes, uint64 * cumul_1, uint64 * cumul_x, uint64 * cumul_x2,
+                                                                 uint32 h, uint32 l, double * vrais, double * vrais_min, bool * move);
+#endif // __KERNEL_CONTRIB__
diff --git a/src/lib_kernels_cumuls.cu b/src/lib_kernels_cumuls.cu
new file mode 100644 (file)
index 0000000..641a0ff
--- /dev/null
@@ -0,0 +1,233 @@
+
+
+
+__global__ void calcul_cumuls_gpu(unsigned short * img, t_cumul_x * cumul_x, t_cumul_x2 * cumul_x2, uint32 h, uint32 l, uint64 * gsomblocs, unsigned int N_BLOCS_LIGNE, unsigned int baseline, unsigned int nb_lines )
+{
+  int bs = blockDim.x ;
+  int offsetSom = N_BLOCS_LIGNE * nb_lines;         //indice du premier element de cumul_x2 dans le tableau
+    
+  int tib = threadIdx.x ;                           //indice du thread dans le bloc
+  int idx = blockIdx.x*bs + tib ;                   //indice global du thread dans la portion d'image
+  int num_ligne = blockIdx.x / N_BLOCS_LIGNE ;      //indice de la ligne du thread dans la portion d'image
+  int til = idx - num_ligne*bs*N_BLOCS_LIGNE ;      //indice du thread ds la ligne
+  int pos = num_ligne*l + til ;                     //indice du pixel dans la 'tranche' courante
+  int pos_img = pos + baseline*l ;                  //indice correspondant dans l'image originale
+  int id, stride=1;
+  
+  extern __shared__ tcumuls sdata[];
+  //chargement en smem avec complement de 0  
+  id = CFI(tib);
+  if (til < l){
+           sdata[id].x = img[ pos_img ] ;
+           sdata[id].x2 = img[ pos_img ]*img[ pos_img ] ;
+        } else {
+          sdata[id].x = 0 ;
+          sdata[id].x2 = 0 ;
+       }
+       /*
+        *prefix sum en smem
+        */
+       //passe 1 : construction des sommes
+  
+       for (int d = bs/2; d > 0; d >>= 1)
+         {
+               __syncthreads();
+       
+               if (tib < d)
+                 {
+                       int i  = __mul24(__mul24(2, stride), tib);
+                       int ai = i + stride - 1;
+                       int bi = CFI(ai + stride);
+
+                       ai = CFI(ai);
+                       //bi = CFI(bi);
+                       
+                       sdata[bi].x += sdata[ai].x;
+                       sdata[bi].x2 += sdata[ai].x2;
+                       
+                 }
+               stride *= 2;
+         }
+  
+       //stockage somme du bloc en gmem
+       // et 
+       //mise a zero dernier element du bloc
+       
+       __syncthreads();
+       
+       if (tib == bs-1) {
+         t_cumul_x som_x = sdata[CFI(tib)].x;
+         t_cumul_x2 som_x2 = sdata[CFI(tib)].x2;
+         if (til < l){                                 //il ne faut pas ecrire de somme dans le dernier bloc, elle serait hors image
+            cumul_x[ pos_img ] = som_x;  
+            cumul_x2[pos_img ] = som_x2;
+            }       
+         gsomblocs[blockIdx.x] = som_x;
+         gsomblocs[blockIdx.x + offsetSom] = som_x2;  
+         sdata[CFI(tib)].x = 0;
+         sdata[CFI(tib)].x2 = 0;
+       }
+       
+       //Passe 2 : construction des scans
+       for (int d = 1; d <= (bs/2); d *= 2)
+         {
+               stride >>= 1;
+               __syncthreads();
+
+               if (tib < d)
+                 {
+                       int i  = __mul24(__mul24(2, stride), tib);
+                       int ai = i + stride - 1;
+                       int bi = CFI(ai + stride);
+
+                       ai = CFI(ai);
+                       //bi = CFI(bi);
+                       
+                       t_cumul_x tx = sdata[ai].x;
+                       t_cumul_x2 tx2 = sdata[ai].x2;
+               
+                       sdata[ai].x = sdata[bi].x;
+                       sdata[bi].x += tx;
+
+                       sdata[ai].x2 = sdata[bi].x2;
+                       sdata[bi].x2 += tx2;
+                 }
+         }
+       
+       //transfert en gmem des scans
+       //il faut décaler à gauche de 1 element
+       __syncthreads();
+       if ( (til < l) && ( tib < (bs-1) ) ){
+               cumul_x[ pos_img ] = sdata[CFI(tib+1)].x;  
+               cumul_x2[pos_img ] = sdata[CFI(tib+1)].x2;
+        }
+       
+}
+
+
+
+/*
+  kernel pour faire le prefixsum des sommes de blocs des lignes de l'image
+  les params d'executions kivonbien sont :
+  - threads : la moitié de la nextpow2 du nb de blocs par ligne
+  - grid : 2 x le nombre de blocs de sommes dans l'image , soit le nb_blocs_par_ligne x nb_lignes x 2 
+  - shared mem : 2 x nextPow2(nb_blocs par ligne) 
+*/
+
+
+
+__global__ void scan_somblocs(uint64 * g_idata, int n_bl_l){
+
+  extern __shared__  uint64 temp[];
+    
+  int tib = threadIdx.x;
+  int toff = blockIdx.x*n_bl_l;         // offset des positions des sommes partielles dans le tableau g_idata
+  int nmax = blockDim.x*2;              //nb max de sommes partielles par ligne
+
+  
+  int aai = tib;
+  int bbi = tib + blockDim.x;
+  
+   
+  // chargement data en smem
+  temp[ CFI(aai) ] = (aai < n_bl_l)? g_idata[ toff + aai ] : 0; 
+  temp[ CFI(bbi) ] = (bbi < n_bl_l)? g_idata[ toff + bbi ] : 0; 
+    
+  int offset = 1;
+
+  // passe 1 de bas en haut
+  for (int d = nmax/2; d > 0; d >>= 1)
+    {
+         __syncthreads();
+
+         if (tib < d)      
+        {
+                 int ai = CFI(offset*(2*tib+1)-1);
+                 int bi = CFI(offset*(2*tib+2)-1);
+
+                 temp[bi] += temp[ai];
+        }
+
+         offset *= 2;
+    }
+  
+  // zero le dernier element
+  __syncthreads();
+  if (tib == 0)
+    {
+         int index = CFI(nmax - 1);
+         g_idata[ toff + n_bl_l - 1 ] =  temp[ index ]; //memorisation de la somme du bloc a sa place en gmem
+         temp[index] = 0;
+    }   
+  
+  // passe 2 de haut en bas
+  for (int d = 1; d < nmax; d *= 2)
+    {
+         offset /= 2;
+         
+         __syncthreads();
+
+         if (tib < d)
+        {
+                 int ai = CFI(offset*(2*tib+1)-1);
+                 int bi = CFI(offset*(2*tib+2)-1);
+
+                 uint64 t  = temp[ai];
+                 temp[ai] = temp[bi];
+                 temp[bi] += t; //tester atomicadd 64 bits
+                 }
+         
+    }
+  
+  __syncthreads();
+  
+  // transfert resultats en gmem decales d'un element vers la gauche
+  g_idata[ toff + aai ] = temp[ CFI(aai + 1) ]; //pour le demi tableau smem inferieur
+  if ( bbi < n_bl_l-1 ) g_idata[ toff + bbi ] = temp[CFI( bbi + 1) ]; //demi tableau smem sup. sauf  dernier=somme.
+   
+}
+
+
+__global__ void add_soms_to_cumuls(t_cumul_x * cumul_x, t_cumul_x2 * cumul_x2, uint32 h, uint32 l, uint64 * gsomblocs,
+                                                                  unsigned int  N_BLOCS_LIGNE, unsigned int baseline, unsigned int nb_lines){
+
+  int bs = blockDim.x ;
+  int offsetSom = N_BLOCS_LIGNE * nb_lines;
+  int tib = threadIdx.x ;                           //indice du thread dans le bloc
+  int idx = blockIdx.x*blockDim.x + tib ;           //indice global du thread
+  int num_ligne = blockIdx.x / N_BLOCS_LIGNE ;      //indice de la ligne du thread dans l'image partielle
+  int til = idx - num_ligne*bs*N_BLOCS_LIGNE ;      //indice du thread ds la ligne
+  int pos = num_ligne*l + til;
+  int pos_img = pos + baseline*l ;
+
+  
+  //chargement des valeurs a ajouter en smem 0<-->x et 1<-->x2
+  uint64 __shared__ ajout[2];
+  
+  if ( til >= bs ){
+         ajout[0] = gsomblocs[blockIdx.x -1 ];
+         ajout[1] = gsomblocs[blockIdx.x -1 + offsetSom];
+       __syncthreads(); //tester les nouveaux __sync__
+       
+       //addition par bloc
+       if (til < l) {
+         cumul_x[pos_img] += ajout[0];
+         cumul_x2[pos_img]+= ajout[1];
+       }
+  } 
+}
+
+//calcul des SUM_1, SUM_X et SUM_X2 de l'image
+
+__global__ void calcul_stats_image( t_cumul_x * cumul_x, t_cumul_x2 * cumul_x2, uint32 h, uint32 l, uint64 * d_stats_snake){
+  uint64 sigX = 0, sigX2 = 0 ;
+  for (int i=l-1; i<h*l; i+=l)
+       {
+         sigX += cumul_x[i] ;
+         sigX2+= cumul_x2[i];
+       }
+  d_stats_snake[3] = h*l ;
+  d_stats_snake[4] = sigX ;
+  d_stats_snake[5] = sigX2;
+  
+}
diff --git a/src/lib_kernels_cumuls.cu~ b/src/lib_kernels_cumuls.cu~
new file mode 100644 (file)
index 0000000..a2024fe
--- /dev/null
@@ -0,0 +1,233 @@
+
+
+
+__global__ void calcul_cumuls_gpu(unsigned short * img, t_cumul_x * cumul_x, t_cumul_x2 * cumul_x2, uint32 h, uint32 l, uint64 * gsomblocs, unsigned int N_BLOCS_LIGNE, unsigned int baseline, unsigned int nb_lines )
+{
+  int bs = blockDim.x ;
+  int offsetSom = N_BLOCS_LIGNE * nb_lines;         //indice du premier element de cumul_x2 dans le tableau
+    
+  Int tib = threadIdx.x ;                           //indice du thread dans le bloc
+  int idx = blockIdx.x*bs + tib ;                   //indice global du thread dans la portion d'image
+  int num_ligne = blockIdx.x / N_BLOCS_LIGNE ;      //indice de la ligne du thread dans la portion d'image
+  int til = idx - num_ligne*bs*N_BLOCS_LIGNE ;      //indice du thread ds la ligne
+  int pos = num_ligne*l + til ;                     //indice du pixel dans la 'tranche' courante
+  int pos_img = pos + baseline*l ;                  //indice correspondant dans l'image originale
+  int id, stride=1;
+  
+  extern __shared__ tcumuls sdata[];
+  //chargement en smem avec complement de 0  
+  id = CFI(tib);
+  if (til < l){
+           sdata[id].x = img[ pos_img ] ;
+           sdata[id].x2 = img[ pos_img ]*img[ pos_img ] ;
+        } else {
+          sdata[id].x = 0 ;
+          sdata[id].x2 = 0 ;
+       }
+       /*
+        *prefix sum en smem
+        */
+       //passe 1 : construction des sommes
+  
+       for (int d = bs/2; d > 0; d >>= 1)
+         {
+               __syncthreads();
+       
+               if (tib < d)
+                 {
+                       int i  = __mul24(__mul24(2, stride), tib);
+                       int ai = i + stride - 1;
+                       int bi = CFI(ai + stride);
+
+                       ai = CFI(ai);
+                       //bi = CFI(bi);
+                       
+                       sdata[bi].x += sdata[ai].x;
+                       sdata[bi].x2 += sdata[ai].x2;
+                       
+                 }
+               stride *= 2;
+         }
+  
+       //stockage somme du bloc en gmem
+       // et 
+       //mise a zero dernier element du bloc
+       
+       __syncthreads();
+       
+       if (tib == bs-1) {
+         t_cumul_x som_x = sdata[CFI(tib)].x;
+         t_cumul_x2 som_x2 = sdata[CFI(tib)].x2;
+         if (til < l){                                 //il ne faut pas ecrire de somme dans le dernier bloc, elle serait hors image
+            cumul_x[ pos_img ] = som_x;  
+            cumul_x2[pos_img ] = som_x2;
+            }       
+         gsomblocs[blockIdx.x] = som_x;
+         gsomblocs[blockIdx.x + offsetSom] = som_x2;  
+         sdata[CFI(tib)].x = 0;
+         sdata[CFI(tib)].x2 = 0;
+       }
+       
+       //Passe 2 : construction des scans
+       for (int d = 1; d <= (bs/2); d *= 2)
+         {
+               stride >>= 1;
+               __syncthreads();
+
+               if (tib < d)
+                 {
+                       int i  = __mul24(__mul24(2, stride), tib);
+                       int ai = i + stride - 1;
+                       int bi = CFI(ai + stride);
+
+                       ai = CFI(ai);
+                       //bi = CFI(bi);
+                       
+                       t_cumul_x tx = sdata[ai].x;
+                       t_cumul_x2 tx2 = sdata[ai].x2;
+               
+                       sdata[ai].x = sdata[bi].x;
+                       sdata[bi].x += tx;
+
+                       sdata[ai].x2 = sdata[bi].x2;
+                       sdata[bi].x2 += tx2;
+                 }
+         }
+       
+       //transfert en gmem des scans
+       //il faut décaler à gauche de 1 element
+       __syncthreads();
+       if ( (til < l) && ( tib < (bs-1) ) ){
+               cumul_x[ pos_img ] = sdata[CFI(tib+1)].x;  
+               cumul_x2[pos_img ] = sdata[CFI(tib+1)].x2;
+        }
+       
+}
+
+
+
+/*
+  kernel pour faire le prefixsum des sommes de blocs des lignes de l'image
+  les params d'executions kivonbien sont :
+  - threads : la moitié de la nextpow2 du nb de blocs par ligne
+  - grid : 2 x le nombre de blocs de sommes dans l'image , soit le nb_blocs_par_ligne x nb_lignes x 2 
+  - shared mem : 2 x nextPow2(nb_blocs par ligne) 
+*/
+
+
+
+__global__ void scan_somblocs(uint64 * g_idata, int n_bl_l){
+
+  extern __shared__  uint64 temp[];
+    
+  int tib = threadIdx.x;
+  int toff = blockIdx.x*n_bl_l;         // offset des positions des sommes partielles dans le tableau g_idata
+  int nmax = blockDim.x*2;              //nb max de sommes partielles par ligne
+
+  
+  int aai = tib;
+  int bbi = tib + blockDim.x;
+  
+   
+  // chargement data en smem
+  temp[ CFI(aai) ] = (aai < n_bl_l)? g_idata[ toff + aai ] : 0; 
+  temp[ CFI(bbi) ] = (bbi < n_bl_l)? g_idata[ toff + bbi ] : 0; 
+    
+  int offset = 1;
+
+  // passe 1 de bas en haut
+  for (int d = nmax/2; d > 0; d >>= 1)
+    {
+         __syncthreads();
+
+         if (tib < d)      
+        {
+                 int ai = CFI(offset*(2*tib+1)-1);
+                 int bi = CFI(offset*(2*tib+2)-1);
+
+                 temp[bi] += temp[ai];
+        }
+
+         offset *= 2;
+    }
+  
+  // zero le dernier element
+  __syncthreads();
+  if (tib == 0)
+    {
+         int index = CFI(nmax - 1);
+         g_idata[ toff + n_bl_l - 1 ] =  temp[ index ]; //memorisation de la somme du bloc a sa place en gmem
+         temp[index] = 0;
+    }   
+  
+  // passe 2 de haut en bas
+  for (int d = 1; d < nmax; d *= 2)
+    {
+         offset /= 2;
+         
+         __syncthreads();
+
+         if (tib < d)
+        {
+                 int ai = CFI(offset*(2*tib+1)-1);
+                 int bi = CFI(offset*(2*tib+2)-1);
+
+                 uint64 t  = temp[ai];
+                 temp[ai] = temp[bi];
+                 temp[bi] += t; //tester atomicadd 64 bits
+                 }
+         
+    }
+  
+  __syncthreads();
+  
+  // transfert resultats en gmem decales d'un element vers la gauche
+  g_idata[ toff + aai ] = temp[ CFI(aai + 1) ]; //pour le demi tableau smem inferieur
+  if ( bbi < n_bl_l-1 ) g_idata[ toff + bbi ] = temp[CFI( bbi + 1) ]; //demi tableau smem sup. sauf  dernier=somme.
+   
+}
+
+
+__global__ void add_soms_to_cumuls(t_cumul_x * cumul_x, t_cumul_x2 * cumul_x2, uint32 h, uint32 l, uint64 * gsomblocs,
+                                                                  unsigned int  N_BLOCS_LIGNE, unsigned int baseline, unsigned int nb_lines){
+
+  int bs = blockDim.x ;
+  int offsetSom = N_BLOCS_LIGNE * nb_lines;
+  int tib = threadIdx.x ;                           //indice du thread dans le bloc
+  int idx = blockIdx.x*blockDim.x + tib ;           //indice global du thread
+  int num_ligne = blockIdx.x / N_BLOCS_LIGNE ;      //indice de la ligne du thread dans l'image partielle
+  int til = idx - num_ligne*bs*N_BLOCS_LIGNE ;      //indice du thread ds la ligne
+  int pos = num_ligne*l + til;
+  int pos_img = pos + baseline*l ;
+
+  
+  //chargement des valeurs a ajouter en smem 0<-->x et 1<-->x2
+  uint64 __shared__ ajout[2];
+  
+  if ( til >= bs ){
+         ajout[0] = gsomblocs[blockIdx.x -1 ];
+         ajout[1] = gsomblocs[blockIdx.x -1 + offsetSom];
+       __syncthreads(); //tester les nouveaux __sync__
+       
+       //addition par bloc
+       if (til < l) {
+         cumul_x[pos_img] += ajout[0];
+         cumul_x2[pos_img]+= ajout[1];
+       }
+  } 
+}
+
+//calcul des SUM_1, SUM_X et SUM_X2 de l'image
+
+__global__ void calcul_stats_image( t_cumul_x * cumul_x, t_cumul_x2 * cumul_x2, uint32 h, uint32 l, uint64 * d_stats_snake){
+  uint64 sigX = 0, sigX2 = 0 ;
+  for (int i=l-1; i<h*l; i+=l)
+       {
+         sigX += cumul_x[i] ;
+         sigX2+= cumul_x2[i];
+       }
+  d_stats_snake[3] = h*l ;
+  d_stats_snake[4] = sigX ;
+  d_stats_snake[5] = sigX2;
+  
+}
diff --git a/src/lib_kernels_maths.cu b/src/lib_kernels_maths.cu
new file mode 100644 (file)
index 0000000..42db50b
--- /dev/null
@@ -0,0 +1,244 @@
+
+__device__ void calcul_indices_prec_suiv(int nb_nodes, int nx, int& nprec, int& nsuiv){
+  nprec = (nx > 0)? (nx - 1):(nb_nodes - 1);
+  nsuiv = (nx < nb_nodes - 1)? (nx + 1):(0);
+}
+
+__device__ double codage_niveau_gris_hyp_gaussienne_gpu(uint32 stat_sum_1, uint64 stat_sum_x,
+                                                                                                               uint64 stat_sum_x2, uint32 n_dim,
+                                                                                                               uint64 SUM_X, uint64 SUM_X2)
+{
+  uint64 stat_sum_xe ;  /* somme des xn region exterieure */
+  uint32 ne ;             /* nombre de pixel region exterieure */
+  double sigi2, sige2; /* variance region interieure et exterieure */
+
+  /* variance des valeurs des niveaux de gris a l'interieur du snake */
+  sigi2 = 
+    (double)stat_sum_x2/(double)stat_sum_1 - 
+    (double)(stat_sum_x*stat_sum_x)/(double)((uint64)stat_sum_1*(uint64)stat_sum_1) ;
+
+  /* variance des valeurs des niveaux de gris a l'exterieur du snake */
+  ne = n_dim-stat_sum_1 ;
+  stat_sum_xe = SUM_X - stat_sum_x ;
+  sige2 =
+    (double)(SUM_X2-stat_sum_x2)/(double)ne - 
+    (double)(stat_sum_xe*stat_sum_xe)/(double)((uint64)ne*(uint64)ne) ;
+  
+  if ((sigi2 <= 0)|(sige2 <= 0)) return -1;
+    
+  return  0.5*((double)stat_sum_1*log(sigi2) + (double)ne*log(sige2)) ;
+}
+
+__device__ double codage_gl_hyp_gaussienne(uint64 stat_sum_1, uint64 stat_sum_x, uint64 stat_sum_x2,
+                                                                                  uint64 n_dim, uint64 SUM_X, uint64 SUM_X2){
+  uint64 stat_sum_xe ;  /* somme des xn region exterieure */
+  uint32 ne ;             /* nombre de pixel region exterieure */
+  double sigi2, sige2; /* variance region interieure et exterieure */
+
+  /* variance des valeurs des niveaux de gris a l'interieur du snake */
+  sigi2 = 
+    (double)stat_sum_x2/(double)stat_sum_1 - 
+    (double)(stat_sum_x*stat_sum_x)/(double)((uint64)stat_sum_1*(uint64)stat_sum_1) ;
+
+  /* variance des valeurs des niveaux de gris a l'exterieur du snake */
+  ne = n_dim-stat_sum_1 ;
+  stat_sum_xe = SUM_X - stat_sum_x ;
+  sige2 =
+    (double)(SUM_X2-stat_sum_x2)/(double)ne - 
+    (double)(stat_sum_xe*stat_sum_xe)/(double)((uint64)ne*(uint64)ne) ;
+  
+  if ((sigi2 > 0)|(sige2 > 0))
+  return  0.5*((double)stat_sum_1*log(sigi2) + (double)ne*log(sige2)) ;
+  return -1 ;
+}
+
+__device__ inline unsigned int nextPow2_gpu( unsigned int x ) {
+  --x;
+  x |= x >> 1;
+  x |= x >> 2;
+  x |= x >> 4;
+  x |= x >> 8;
+  x |= x >> 16;
+  return ++x;
+}
+
+
+__device__ inline int sign_diff_strict(int val1, int val2)
+{
+  if (val1 > 0) 
+    {
+      if (val2 >= 0) return 0 ;
+      else return 1 ;
+    }
+  else 
+    if (val1 < 0)
+      {
+       if (val2 <= 0) return 0 ;
+       else  return 1 ;
+      }
+    else
+      return 0 ;/* val1 == 0 */
+}
+
+__device__ inline int sign_diff_ou_egal_zero(int val1, int val2)
+{
+  if (val1 > 0) 
+    {
+      if (val2 > 0) return 0 ;
+      else return 1 ;
+    }
+  else 
+    if (val1 < 0)
+      {
+               if (val2 < 0) return 0 ;
+               else  return 1 ;
+      }
+    else
+      return 1 ;/* val1 == 0 */
+}
+
+
+__device__  int sinus_triangle(int Ai, int Aj, int Bi, int Bj, int Ci, int Cj)
+{
+  return (((Bi-Ai)*(Cj-Aj)) - ((Ci-Ai)*(Bj-Aj))) ;
+}
+
+__device__  int test_croisement_large(uint32 Ai, uint32 Aj, uint32 Bi, uint32 Bj,
+                                                                                       uint32 Ui, uint32 Uj, uint32 Vi, uint32 Vj)
+{
+  if (sign_diff_strict(sinus_triangle(Ai, Aj, Bi, Bj, Ui, Uj),     // Bi-Ai, Uj-Aj, Ui-Ai, Bj-Aj
+                      sinus_triangle(Ai, Aj, Bi, Bj, Vi, Vj)))    // Bi-Ai, Vj-Aj, Vi-Ai, Bj-Aj
+    if (sign_diff_strict(sinus_triangle(Ui, Uj, Vi, Vj, Ai, Aj),   // Vi-Ui, Aj-Uj, Ai-Ui, Vj-Uj
+                        sinus_triangle(Ui, Uj, Vi, Vj, Bi, Bj)))  // Vi-Ui, Bj-Uj, Bi-Ui, Vj-Uj
+       return 1 ;
+  return 0 ;
+}
+
+__device__  int test_croisement_strict(uint32 Ai, uint32 Aj, uint32 Bi, uint32 Bj,
+                                                                                        uint32 Ui, uint32 Uj, uint32 Vi, uint32 Vj )
+{
+  if (sign_diff_ou_egal_zero(sinus_triangle(Ai, Aj, Bi, Bj, Ui, Uj),
+                                                        sinus_triangle(Ai, Aj, Bi, Bj, Vi, Vj)))  
+    if (sign_diff_ou_egal_zero(sinus_triangle(Ui, Uj, Vi, Vj, Ai, Aj),
+                                                          sinus_triangle(Ui, Uj, Vi, Vj, Bi, Bj)))
+      return 1 ;
+  return 0 ;
+}
+
+__global__ void kernel_test_croisement_move_seg_strict(struct snake_node_gpu *d_snake, uint32 nx, uint32 Nxi, uint32 Nxj, int Nb_nodes, bool * croist)
+{
+  int idx = blockDim.x*blockIdx.x + threadIdx.x, idx_prec, idx_suiv ;
+  int na, nb, naa, nbb  ;
+  int Nai, Naj, Nbi, Nbj ;
+  bool croistil = false ;
+  
+  calcul_indices_prec_suiv(Nb_nodes, nx, na, nb);
+  calcul_indices_prec_suiv(Nb_nodes, na, naa, nbb);
+
+  //coord. nodes extremites des segments a tester
+  Nai = d_snake[na].posi ;
+  Naj = d_snake[na].posj ;
+  Nbi = d_snake[nb].posi ;
+  Nbj = d_snake[nb].posj ;
+  
+  if (idx == nb) //premier segment apres
+       {
+         calcul_indices_prec_suiv(Nb_nodes, idx, idx_prec, idx_suiv);
+         if ( test_croisement_large(Nxi, Nxj, Nbi, Nbj,
+                                                                 Nbi, Nbj, d_snake[idx_suiv].posi, d_snake[idx_suiv].posj))
+               croistil = true ;
+         else if ( test_croisement_strict(Nai, Naj, Nxi, Nxj,
+                                                                          Nbi, Nbj, d_snake[idx_suiv].posi, d_snake[idx_suiv].posj) )
+               croistil = true ;
+       }
+  else if ( idx == naa ) //premier segment avant
+       {
+         if ( test_croisement_large(d_snake[naa].posi, d_snake[naa].posj, Nai, Naj,
+                                                                Nai, Naj, Nxi, Nxj) )
+               croistil = true ;
+         else if ( test_croisement_strict(d_snake[naa].posi, d_snake[naa].posj, Nai, Naj,
+                                                                          Nxi, Nxj, Nbi, Nbj))
+               croistil = true ;
+       }
+  else if ( (idx != nx) && (idx != na) ) //les autres segments
+       {
+         calcul_indices_prec_suiv(Nb_nodes, idx, idx_prec, idx_suiv);
+         if ( test_croisement_strict(Nai, Naj, Nxi, Nxj,
+                                                                 d_snake[idx].posi, d_snake[idx].posj,
+                                                                 d_snake[idx_suiv].posi, d_snake[idx_suiv].posj) )
+               croistil = true ;
+         else if ( test_croisement_strict(Nxi, Nxj, Nbi, Nbj,
+                                                                          d_snake[idx].posi, d_snake[idx].posj,
+                                                                          d_snake[idx_suiv].posi, d_snake[idx_suiv].posj) )
+               croistil = true ;
+       }
+        
+  croist[idx] = croistil ;
+}
+
+__device__ bool croisement(snake_node_gpu *d_snake, uint32 nx, uint32 Nxi, uint32 Nxj, int Nb_nodes)
+{
+  int idx_prec, idx_suiv ;
+  int na, nb, naa, nbb  ;
+  int Nai, Naj, Nbi, Nbj ;
+  bool croistil = false ;
+  
+  //coord. nodes extremites des segments a tester
+  calcul_indices_prec_suiv(Nb_nodes, nx, na, nb);
+  calcul_indices_prec_suiv(Nb_nodes, na, naa, nbb);
+
+  Nai = d_snake[na].posi ;
+  Naj = d_snake[na].posj ;
+  Nbi = d_snake[nb].posi ;
+  Nbj = d_snake[nb].posj ;
+
+  //parcours du snake
+  for (int idx=0; idx < Nb_nodes; idx++){
+       if (idx == nb) //premier segment apres
+         {
+               calcul_indices_prec_suiv(Nb_nodes, idx, idx_prec, idx_suiv);
+               if ( test_croisement_large(Nxi, Nxj, Nbi, Nbj, Nbi, Nbj, d_snake[idx_suiv].posi, d_snake[idx_suiv].posj) )
+                 {
+                       croistil = true ;
+                       break ;
+                 }
+               if ( test_croisement_strict(Nai, Naj, Nxi, Nxj, Nbi, Nbj, d_snake[idx_suiv].posi, d_snake[idx_suiv].posj) )
+                 {
+                       croistil = true ;
+                       break ;
+                 }
+         }
+       if ( idx == naa ) //premier segment avant
+         {
+               if ( test_croisement_large(d_snake[naa].posi, d_snake[naa].posj, Nai, Naj, Nai, Naj, Nxi, Nxj) )
+                 {
+                       croistil = true ;
+                       break ;
+                 }
+               if ( test_croisement_strict(d_snake[naa].posi, d_snake[naa].posj, Nai, Naj, Nxi, Nxj, Nbi, Nbj))
+                 {
+                       croistil = true ;
+                       break ;
+                 }
+         }
+       if ( (idx != nx) && (idx != na) && (idx != nb) && (idx != naa) ) //les autres segments
+         {
+               calcul_indices_prec_suiv(Nb_nodes, idx, idx_prec, idx_suiv);
+               if ( test_croisement_strict(Nai, Naj, Nxi, Nxj,
+                                                                       d_snake[idx].posi, d_snake[idx].posj,
+                                                                       d_snake[idx_suiv].posi, d_snake[idx_suiv].posj) )
+                 {
+                       croistil = true ;
+                       break ;
+                 }
+               if ( test_croisement_strict(Nxi, Nxj, Nbi, Nbj,
+                                                                       d_snake[idx].posi, d_snake[idx].posj,
+                                                                       d_snake[idx_suiv].posi, d_snake[idx_suiv].posj) )
+                 {
+                       croistil = true ;
+                       break ;
+                 }
+         }
+  }     
+  return croistil;
+}
diff --git a/src/lib_kernels_maths.cu~ b/src/lib_kernels_maths.cu~
new file mode 100644 (file)
index 0000000..c98f3bc
--- /dev/null
@@ -0,0 +1,226 @@
+
+__device__ void calcul_indices_prec_suiv(int nb_nodes, int nx, int& nprec, int& nsuiv){
+  nprec = (nx > 0)? (nx - 1):(nb_nodes - 1);
+  nsuiv = (nx < nb_nodes - 1)? (nx + 1):(0);
+}
+
+__device__ double codage_niveau_gris_hyp_gaussienne_gpu(uint32 stat_sum_1, uint64 stat_sum_x,
+                                                                                                               uint64 stat_sum_x2, uint32 n_dim,
+                                                                                                               uint64 SUM_X, uint64 SUM_X2)
+{
+  uint64 stat_sum_xe ;  /* somme des xn region exterieure */
+  uint32 ne ;             /* nombre de pixel region exterieure */
+  double sigi2, sige2; /* variance region interieure et exterieure */
+
+  /* variance des valeurs des niveaux de gris a l'interieur du snake */
+  sigi2 = 
+    (double)stat_sum_x2/(double)stat_sum_1 - 
+    (double)(stat_sum_x*stat_sum_x)/(double)((uint64)stat_sum_1*(uint64)stat_sum_1) ;
+
+  /* variance des valeurs des niveaux de gris a l'exterieur du snake */
+  ne = n_dim-stat_sum_1 ;
+  stat_sum_xe = SUM_X - stat_sum_x ;
+  sige2 =
+    (double)(SUM_X2-stat_sum_x2)/(double)ne - 
+    (double)(stat_sum_xe*stat_sum_xe)/(double)((uint64)ne*(uint64)ne) ;
+  
+  if ((sigi2 <= 0)|(sige2 <= 0)) return -1;
+    
+  return  0.5*((double)stat_sum_1*log(sigi2) + (double)ne*log(sige2)) ;
+}
+
+__device__ double codage_gl_hyp_gaussienne(uint64 stat_sum_1, uint64 stat_sum_x, uint64 stat_sum_x2,
+                                                                                  uint64 n_dim, uint64 SUM_X, uint64 SUM_X2){
+  uint64 stat_sum_xe ;  /* somme des xn region exterieure */
+  uint32 ne ;             /* nombre de pixel region exterieure */
+  double sigi2, sige2; /* variance region interieure et exterieure */
+
+  /* variance des valeurs des niveaux de gris a l'interieur du snake */
+  sigi2 = 
+    (double)stat_sum_x2/(double)stat_sum_1 - 
+    (double)(stat_sum_x*stat_sum_x)/(double)((uint64)stat_sum_1*(uint64)stat_sum_1) ;
+
+  /* variance des valeurs des niveaux de gris a l'exterieur du snake */
+  ne = n_dim-stat_sum_1 ;
+  stat_sum_xe = SUM_X - stat_sum_x ;
+  sige2 =
+    (double)(SUM_X2-stat_sum_x2)/(double)ne - 
+    (double)(stat_sum_xe*stat_sum_xe)/(double)((uint64)ne*(uint64)ne) ;
+  
+  if ((sigi2 > 0)|(sige2 > 0))
+  return  0.5*((double)stat_sum_1*log(sigi2) + (double)ne*log(sige2)) ;
+  return -1 ;
+}
+
+__device__ inline unsigned int nextPow2_gpu( unsigned int x ) {
+  --x;
+  x |= x >> 1;
+  x |= x >> 2;
+  x |= x >> 4;
+  x |= x >> 8;
+  x |= x >> 16;
+  return ++x;
+}
+
+
+__device__ inline int sign_diff_strict(int val1, int val2)
+{
+  if (val1 > 0) 
+    {
+      if (val2 >= 0) return 0 ;
+      else return 1 ;
+    }
+  else 
+    if (val1 < 0)
+      {
+       if (val2 <= 0) return 0 ;
+       else  return 1 ;
+      }
+    else
+      return 0 ;/* val1 == 0 */
+}
+
+__device__ inline int sign_diff_ou_egal_zero(int val1, int val2)
+{
+  if (val1 > 0) 
+    {
+      if (val2 > 0) return 0 ;
+      else return 1 ;
+    }
+  else 
+    if (val1 < 0)
+      {
+               if (val2 < 0) return 0 ;
+               else  return 1 ;
+      }
+    else
+      return 1 ;/* val1 == 0 */
+}
+
+
+__device__  int sinus_triangle(int Ai, int Aj, int Bi, int Bj, int Ci, int Cj)
+{
+  return (((Bi-Ai)*(Cj-Aj)) - ((Ci-Ai)*(Bj-Aj))) ;
+}
+
+__device__  int test_croisement_large(uint32 Ai, uint32 Aj, uint32 Bi, uint32 Bj,
+                                                                                       uint32 Ui, uint32 Uj, uint32 Vi, uint32 Vj)
+{
+  if (sign_diff_strict(sinus_triangle(Ai, Aj, Bi, Bj, Ui, Uj),     // Bi-Ai, Uj-Aj, Ui-Ai, Bj-Aj
+                      sinus_triangle(Ai, Aj, Bi, Bj, Vi, Vj)))    // Bi-Ai, Vj-Aj, Vi-Ai, Bj-Aj
+    if (sign_diff_strict(sinus_triangle(Ui, Uj, Vi, Vj, Ai, Aj),   // Vi-Ui, Aj-Uj, Ai-Ui, Vj-Uj
+                        sinus_triangle(Ui, Uj, Vi, Vj, Bi, Bj)))  // Vi-Ui, Bj-Uj, Bi-Ui, Vj-Uj
+       return 1 ;
+  return 0 ;
+}
+
+__device__  int test_croisement_strict(uint32 Ai, uint32 Aj, uint32 Bi, uint32 Bj,
+                                                                                        uint32 Ui, uint32 Uj, uint32 Vi, uint32 Vj )
+{
+  if (sign_diff_ou_egal_zero(sinus_triangle(Ai, Aj, Bi, Bj, Ui, Uj),
+                                                        sinus_triangle(Ai, Aj, Bi, Bj, Vi, Vj)))  
+    if (sign_diff_ou_egal_zero(sinus_triangle(Ui, Uj, Vi, Vj, Ai, Aj),
+                                                          sinus_triangle(Ui, Uj, Vi, Vj, Bi, Bj)))
+      return 1 ;
+  return 0 ;
+}
+
+__global__ void kernel_test_croisement_move_seg_strict(struct snake_node_gpu *d_snake, uint32 nx, uint32 Nxi, uint32 Nxj, int Nb_nodes, bool * croist)
+{
+  int idx = blockDim.x*blockIdx.x + threadIdx.x, idx_prec, idx_suiv ;
+  int na, nb, naa, nbb  ;
+  int Nai, Naj, Nbi, Nbj ;
+  bool croistil = false ;
+  
+  calcul_indices_prec_suiv(Nb_nodes, nx, na, nb);
+  calcul_indices_prec_suiv(Nb_nodes, na, naa, nbb);
+
+  //coord. nodes extremites des segments a tester
+  Nai = d_snake[na].posi ;
+  Naj = d_snake[na].posj ;
+  Nbi = d_snake[nb].posi ;
+  Nbj = d_snake[nb].posj ;
+  
+  if (idx == nb) //premier segment apres
+       {
+         calcul_indices_prec_suiv(Nb_nodes, idx, idx_prec, idx_suiv);
+         if ( test_croisement_large(Nxi, Nxj, Nbi, Nbj,
+                                                                 Nbi, Nbj, d_snake[idx_suiv].posi, d_snake[idx_suiv].posj))
+               croistil = true ;
+         else if ( test_croisement_strict(Nai, Naj, Nxi, Nxj,
+                                                                          Nbi, Nbj, d_snake[idx_suiv].posi, d_snake[idx_suiv].posj) )
+               croistil = true ;
+       }
+  else if ( idx == naa ) //premier segment avant
+       {
+         if ( test_croisement_large(d_snake[naa].posi, d_snake[naa].posj, Nai, Naj,
+                                                                Nai, Naj, Nxi, Nxj) )
+               croistil = true ;
+         else if ( test_croisement_strict(d_snake[naa].posi, d_snake[naa].posj, Nai, Naj,
+                                                                          Nxi, Nxj, Nbi, Nbj))
+               croistil = true ;
+       }
+  else if ( (idx != nx) && (idx != na) ) //les autres segments
+       {
+         calcul_indices_prec_suiv(Nb_nodes, idx, idx_prec, idx_suiv);
+         if ( test_croisement_strict(Nai, Naj, Nxi, Nxj,
+                                                                 d_snake[idx].posi, d_snake[idx].posj,
+                                                                 d_snake[idx_suiv].posi, d_snake[idx_suiv].posj) )
+               croistil = true ;
+         else if ( test_croisement_strict(Nxi, Nxj, Nbi, Nbj,
+                                                                          d_snake[idx].posi, d_snake[idx].posj,
+                                                                          d_snake[idx_suiv].posi, d_snake[idx_suiv].posj) )
+               croistil = true ;
+       }
+        
+  croist[idx] = croistil ;
+}
+
+__device__ bool croisement(snake_node_gpu *d_snake, uint32 nx, uint32 Nxi, uint32 Nxj, int Nb_nodes)
+{
+  int idx_prec, idx_suiv ;
+  int na, nb, naa, nbb  ;
+  int Nai, Naj, Nbi, Nbj ;
+  bool croistil = false ;
+
+  //coord. nodes extremites des segments a tester
+  calcul_indices_prec_suiv(Nb_nodes, nx, na, nb);
+  calcul_indices_prec_suiv(Nb_nodes, na, naa, nbb);
+
+  Nai = d_snake[na].posi ;
+  Naj = d_snake[na].posj ;
+  Nbi = d_snake[nb].posi ;
+  Nbj = d_snake[nb].posj ;
+
+  //parcours du snake
+  for (int idx=0; idx < Nb_nodes; idx++){
+       if (idx == nb) //premier segment apres
+         {
+               calcul_indices_prec_suiv(Nb_nodes, idx, idx_prec, idx_suiv);
+               if ( test_croisement_large(Nxi, Nxj, Nbi, Nbj, Nbi, Nbj, d_snake[idx_suiv].posi, d_snake[idx_suiv].posj) )
+                 return true ;
+               if ( test_croisement_strict(Nai, Naj, Nxi, Nxj, Nbi, Nbj, d_snake[idx_suiv].posi, d_snake[idx_suiv].posj) )
+                 return  true ;
+         }
+       if ( idx == naa ) //premier segment avant
+         {
+               if ( test_croisement_large(d_snake[naa].posi, d_snake[naa].posj, Nai, Naj, Nai, Naj, Nxi, Nxj) )
+                 return true ;
+               if ( test_croisement_strict(d_snake[naa].posi, d_snake[naa].posj, Nai, Naj, Nxi, Nxj, Nbi, Nbj))
+                 return  true ;
+         }
+       if ( (idx != nx) && (idx != na) && (idx != nb) && (idx != naa) ) //les autres segments
+         {
+               calcul_indices_prec_suiv(Nb_nodes, idx, idx_prec, idx_suiv);
+               if ( test_croisement_strict(Nai, Naj, Nxi, Nxj,
+                                                                       d_snake[idx].posi, d_snake[idx].posj,
+                                                                       d_snake[idx_suiv].posi, d_snake[idx_suiv].posj) )
+                 return  true ;
+               if ( test_croisement_strict(Nxi, Nxj, Nbi, Nbj,
+                                                                       d_snake[idx].posi, d_snake[idx].posj,
+                                                                       d_snake[idx_suiv].posi, d_snake[idx_suiv].posj) )
+                 return  true ;
+         }
+  }     
+  return false;
+}
diff --git a/src/lib_kernels_maths.h b/src/lib_kernels_maths.h
new file mode 100644 (file)
index 0000000..d827597
--- /dev/null
@@ -0,0 +1,37 @@
+
+#ifndef __KERNELS_MATHS__
+#define __KERNELS_MATHS__
+
+__device__ void calcul_indices_prec_suiv(int nb_nodes, int nx, int& nprec, int& nsuiv);
+
+__device__ double codage_niveau_gris_hyp_gaussienne_gpu(uint32 stat_sum_1, uint64 stat_sum_x,
+                                                                                                               uint64 stat_sum_x2, uint32 n_dim,
+                                                                                                               uint64 SUM_X, uint64 SUM_X2);
+
+__device__ double codage_gl_hyp_gaussienne(uint64 stat_sum_1, uint64 stat_sum_x, uint64 stat_sum_x2,
+                                                                                  uint64 n_dim, uint64 SUM_X, uint64 SUM_X2);
+
+__device__ inline unsigned int nextPow2_gpu( unsigned int x ); 
+
+__device__ inline int sign_diff_strict(int val1, int val2);
+
+
+__device__ inline int sign_diff_ou_egal_zero(int val1, int val2);
+
+
+__device__ inline int sinus_triangle(int Ai, int Aj, int Bi, int Bj, int Ci, int Cj);
+
+__device__ inline int test_croisement_large(uint32 Ai, uint32 Aj, uint32 Bi, uint32 Bj,
+                                                                                       uint32 Ui, uint32 Uj, uint32 Vi, uint32 Vj);
+
+
+__device__ inline int test_croisement_strict(uint32 Ai, uint32 Aj, uint32 Bi, uint32 Bj,
+                                                                                        uint32 Ui, uint32 Uj, uint32 Vi, uint32 Vj );
+
+
+__global__ void kernel_test_croisement_move_seg_strict(struct snake_node_gpu *d_snake, uint32 nx, uint32 Nxi, uint32 Nxj, int Nb_nodes, bool * croist);
+
+
+__device__ bool test_croisement(struct snake_node_gpu *d_snake, uint32 nx, uint32 Nxi, uint32 Nxj, int Nb_nodes);
+
+#endif
diff --git a/src/lib_kernels_maths.h~ b/src/lib_kernels_maths.h~
new file mode 100644 (file)
index 0000000..98d2830
--- /dev/null
@@ -0,0 +1,231 @@
+#include "lib_kernels_maths.h"
+
+__device__ void calcul_indices_prec_suiv(int nb_nodes, int nx, int& nprec, int& nsuiv){
+  nprec = (nx > 0)? (nx - 1):(nb_nodes - 1);
+  nsuiv = (nx < nb_nodes - 1)? (nx + 1):(0);
+}
+
+__device__ double codage_niveau_gris_hyp_gaussienne_gpu(uint32 stat_sum_1, uint64 stat_sum_x,
+                                                                                                               uint64 stat_sum_x2, uint32 n_dim,
+                                                                                                               uint64 SUM_X, uint64 SUM_X2)
+{
+  uint64 stat_sum_xe ;  /* somme des xn region exterieure */
+  uint32 ne ;             /* nombre de pixel region exterieure */
+  double sigi2, sige2; /* variance region interieure et exterieure */
+
+  /* variance des valeurs des niveaux de gris a l'interieur du snake */
+  sigi2 = 
+    (double)stat_sum_x2/(double)stat_sum_1 - 
+    (double)(stat_sum_x*stat_sum_x)/(double)((uint64)stat_sum_1*(uint64)stat_sum_1) ;
+
+  /* variance des valeurs des niveaux de gris a l'exterieur du snake */
+  ne = n_dim-stat_sum_1 ;
+  stat_sum_xe = SUM_X - stat_sum_x ;
+  sige2 =
+    (double)(SUM_X2-stat_sum_x2)/(double)ne - 
+    (double)(stat_sum_xe*stat_sum_xe)/(double)((uint64)ne*(uint64)ne) ;
+  
+  if ((sigi2 <= 0)|(sige2 <= 0)) return -1;
+    
+  return  0.5*((double)stat_sum_1*log(sigi2) + (double)ne*log(sige2)) ;
+}
+
+__device__ double codage_gl_hyp_gaussienne(uint64 stat_sum_1, uint64 stat_sum_x, uint64 stat_sum_x2,
+                                                                                  uint64 n_dim, uint64 SUM_X, uint64 SUM_X2){
+  uint64 stat_sum_xe ;  /* somme des xn region exterieure */
+  uint32 ne ;             /* nombre de pixel region exterieure */
+  double sigi2, sige2; /* variance region interieure et exterieure */
+
+  /* variance des valeurs des niveaux de gris a l'interieur du snake */
+  sigi2 = 
+    (double)stat_sum_x2/(double)stat_sum_1 - 
+    (double)(stat_sum_x*stat_sum_x)/(double)((uint64)stat_sum_1*(uint64)stat_sum_1) ;
+
+  /* variance des valeurs des niveaux de gris a l'exterieur du snake */
+  ne = n_dim-stat_sum_1 ;
+  stat_sum_xe = SUM_X - stat_sum_x ;
+  sige2 =
+    (double)(SUM_X2-stat_sum_x2)/(double)ne - 
+    (double)(stat_sum_xe*stat_sum_xe)/(double)((uint64)ne*(uint64)ne) ;
+  
+  if ((sigi2 > 0)|(sige2 > 0))
+  return  0.5*((double)stat_sum_1*log(sigi2) + (double)ne*log(sige2)) ;
+  return -1 ;
+}
+
+__device__ inline unsigned int nextPow2_gpu( unsigned int x ) {
+  --x;
+  x |= x >> 1;
+  x |= x >> 2;
+  x |= x >> 4;
+  x |= x >> 8;
+  x |= x >> 16;
+  return ++x;
+}
+
+
+__device__ inline int sign_diff_strict(int val1, int val2)
+{
+  if (val1 > 0) 
+    {
+      if (val2 >= 0) return 0 ;
+      else return 1 ;
+    }
+  else 
+    if (val1 < 0)
+      {
+       if (val2 <= 0) return 0 ;
+       else  return 1 ;
+      }
+    else
+      return 0 ;/* val1 == 0 */
+}
+
+__device__ inline int sign_diff_ou_egal_zero(int val1, int val2)
+{
+  if (val1 > 0) 
+    {
+      if (val2 > 0) return 0 ;
+      else return 1 ;
+    }
+  else 
+    if (val1 < 0)
+      {
+               if (val2 < 0) return 0 ;
+               else  return 1 ;
+      }
+    else
+      return 1 ;/* val1 == 0 */
+}
+
+
+__device__ inline int sinus_triangle(int Ai, int Aj, int Bi, int Bj, int Ci, int Cj)
+{
+  return (((Bi-Ai)*(Cj-Aj)) - ((Ci-Ai)*(Bj-Aj))) ;
+}
+
+__device__ inline int test_croisement_large(uint32 Ai, uint32 Aj, uint32 Bi, uint32 Bj,
+                                                                                       uint32 Ui, uint32 Uj, uint32 Vi, uint32 Vj)
+{
+  if (sign_diff_strict(sinus_triangle(Ai, Aj, Bi, Bj, Ui, Uj),     // Bi-Ai, Uj-Aj, Ui-Ai, Bj-Aj
+                      sinus_triangle(Ai, Aj, Bi, Bj, Vi, Vj)))    // Bi-Ai, Vj-Aj, Vi-Ai, Bj-Aj
+    if (sign_diff_strict(sinus_triangle(Ui, Uj, Vi, Vj, Ai, Aj),   // Vi-Ui, Aj-Uj, Ai-Ui, Vj-Uj
+                        sinus_triangle(Ui, Uj, Vi, Vj, Bi, Bj)))  // Vi-Ui, Bj-Uj, Bi-Ui, Vj-Uj
+       return 1 ;
+  return 0 ;
+}
+
+__device__ inline int test_croisement_strict(uint32 Ai, uint32 Aj, uint32 Bi, uint32 Bj,
+                                                                                        uint32 Ui, uint32 Uj, uint32 Vi, uint32 Vj )
+{
+  if (sign_diff_ou_egal_zero(sinus_triangle(Ai, Aj, Bi, Bj, Ui, Uj),
+                                                        sinus_triangle(Ai, Aj, Bi, Bj, Vi, Vj)))  
+    if (sign_diff_ou_egal_zero(sinus_triangle(Ui, Uj, Vi, Vj, Ai, Aj),
+                                                          sinus_triangle(Ui, Uj, Vi, Vj, Bi, Bj)))
+      return 1 ;
+  return 0 ;
+}
+
+__global__ void kernel_test_croisement_move_seg_strict(struct snake_node_gpu *d_snake, uint32 nx, uint32 Nxi, uint32 Nxj, int Nb_nodes, bool * croist)
+{
+  int idx = blockDim.x*blockIdx.x + threadIdx.x, idx_prec, idx_suiv ;
+  int na, nb, naa, nbb  ;
+  int Nai, Naj, Nbi, Nbj ;
+  bool croistil = false ;
+  
+  calcul_indices_prec_suiv(Nb_nodes, nx, na, nb);
+  calcul_indices_prec_suiv(Nb_nodes, na, naa, nbb);
+
+  //coord. nodes extremites des segments a tester
+  Nai = d_snake[na].posi ;
+  Naj = d_snake[na].posj ;
+  Nbi = d_snake[nb].posi ;
+  Nbj = d_snake[nb].posj ;
+  
+  if (idx == nb) //premier segment apres
+       {
+         calcul_indices_prec_suiv(Nb_nodes, idx, idx_prec, idx_suiv);
+         if ( test_croisement_large(Nxi, Nxj, Nbi, Nbj,
+                                                                 Nbi, Nbj, d_snake[idx_suiv].posi, d_snake[idx_suiv].posj))
+               croistil = true ;
+         else if ( test_croisement_strict(Nai, Naj, Nxi, Nxj,
+                                                                          Nbi, Nbj, d_snake[idx_suiv].posi, d_snake[idx_suiv].posj) )
+               croistil = true ;
+       }
+  else if ( idx == naa ) //premier segment avant
+       {
+         if ( test_croisement_large(d_snake[naa].posi, d_snake[naa].posj, Nai, Naj,
+                                                                Nai, Naj, Nxi, Nxj) )
+               croistil = true ;
+         else if ( test_croisement_strict(d_snake[naa].posi, d_snake[naa].posj, Nai, Naj,
+                                                                          Nxi, Nxj, Nbi, Nbj))
+               croistil = true ;
+       }
+  else if ( (idx != nx) && (idx != na) ) //les autres segments
+       {
+         calcul_indices_prec_suiv(Nb_nodes, idx, idx_prec, idx_suiv);
+         if ( test_croisement_strict(Nai, Naj, Nxi, Nxj,
+                                                                 d_snake[idx].posi, d_snake[idx].posj,
+                                                                 d_snake[idx_suiv].posi, d_snake[idx_suiv].posj) )
+               croistil = true ;
+         else if ( test_croisement_strict(Nxi, Nxj, Nbi, Nbj,
+                                                                          d_snake[idx].posi, d_snake[idx].posj,
+                                                                          d_snake[idx_suiv].posi, d_snake[idx_suiv].posj) )
+               croistil = true ;
+       }
+        
+  croist[idx] = croistil ;
+}
+
+__device__ bool test_croisement(struct snake_node_gpu *d_snake, uint32 nx, uint32 Nxi, uint32 Nxj, int Nb_nodes)
+{
+  int idx_prec, idx_suiv ;
+  int na, nb, naa, nbb  ;
+  int Nai, Naj, Nbi, Nbj ;
+  bool croistil = false ;
+
+  //coord. nodes extremites des segments a tester
+  calcul_indices_prec_suiv(Nb_nodes, nx, na, nb);
+  calcul_indices_prec_suiv(Nb_nodes, na, naa, nbb);
+
+  Nai = d_snake[na].posi ;
+  Naj = d_snake[na].posj ;
+  Nbi = d_snake[nb].posi ;
+  Nbj = d_snake[nb].posj ;
+
+  //parcours du snake
+  for (int idx=0; idx < Nb_nodes; idx++){
+       if (idx == nb) //premier segment apres
+         {
+               calcul_indices_prec_suiv(Nb_nodes, idx, idx_prec, idx_suiv);
+               if ( test_croisement_large(Nxi, Nxj, Nbi, Nbj,
+                                                                  Nbi, Nbj, d_snake[idx_suiv].posi, d_snake[idx_suiv].posj))
+                 croistil = true ;
+               else if ( test_croisement_strict(Nai, Naj, Nxi, Nxj,
+                                                                          Nbi, Nbj, d_snake[idx_suiv].posi, d_snake[idx_suiv].posj) )
+                 croistil = true ;
+         }
+       else if ( idx == naa ) //premier segment avant
+         {
+               if ( test_croisement_large(d_snake[naa].posi, d_snake[naa].posj, Nai, Naj,
+                                                                  Nai, Naj, Nxi, Nxj) )
+                 croistil = true ;
+               else if ( test_croisement_strict(d_snake[naa].posi, d_snake[naa].posj, Nai, Naj,
+                                                                                Nxi, Nxj, Nbi, Nbj))
+                 croistil = true ;
+         }
+       else if ( (idx != nx) && (idx != na) ) //les autres segments
+         {
+               calcul_indices_prec_suiv(Nb_nodes, idx, idx_prec, idx_suiv);
+               if ( test_croisement_strict(Nai, Naj, Nxi, Nxj,
+                                                                       d_snake[idx].posi, d_snake[idx].posj,
+                                                                       d_snake[idx_suiv].posi, d_snake[idx_suiv].posj) )
+                 croistil = true ;
+               else if ( test_croisement_strict(Nxi, Nxj, Nbi, Nbj,
+                                                                                d_snake[idx].posi, d_snake[idx].posj,
+                                                                                d_snake[idx_suiv].posi, d_snake[idx_suiv].posj) )
+                 croistil = true ;
+         }
+  }     
+  return ( croistil );
+}
diff --git a/src/lib_kernels_maths_gpu.cu~ b/src/lib_kernels_maths_gpu.cu~
new file mode 100644 (file)
index 0000000..98d2830
--- /dev/null
@@ -0,0 +1,231 @@
+#include "lib_kernels_maths.h"
+
+__device__ void calcul_indices_prec_suiv(int nb_nodes, int nx, int& nprec, int& nsuiv){
+  nprec = (nx > 0)? (nx - 1):(nb_nodes - 1);
+  nsuiv = (nx < nb_nodes - 1)? (nx + 1):(0);
+}
+
+__device__ double codage_niveau_gris_hyp_gaussienne_gpu(uint32 stat_sum_1, uint64 stat_sum_x,
+                                                                                                               uint64 stat_sum_x2, uint32 n_dim,
+                                                                                                               uint64 SUM_X, uint64 SUM_X2)
+{
+  uint64 stat_sum_xe ;  /* somme des xn region exterieure */
+  uint32 ne ;             /* nombre de pixel region exterieure */
+  double sigi2, sige2; /* variance region interieure et exterieure */
+
+  /* variance des valeurs des niveaux de gris a l'interieur du snake */
+  sigi2 = 
+    (double)stat_sum_x2/(double)stat_sum_1 - 
+    (double)(stat_sum_x*stat_sum_x)/(double)((uint64)stat_sum_1*(uint64)stat_sum_1) ;
+
+  /* variance des valeurs des niveaux de gris a l'exterieur du snake */
+  ne = n_dim-stat_sum_1 ;
+  stat_sum_xe = SUM_X - stat_sum_x ;
+  sige2 =
+    (double)(SUM_X2-stat_sum_x2)/(double)ne - 
+    (double)(stat_sum_xe*stat_sum_xe)/(double)((uint64)ne*(uint64)ne) ;
+  
+  if ((sigi2 <= 0)|(sige2 <= 0)) return -1;
+    
+  return  0.5*((double)stat_sum_1*log(sigi2) + (double)ne*log(sige2)) ;
+}
+
+__device__ double codage_gl_hyp_gaussienne(uint64 stat_sum_1, uint64 stat_sum_x, uint64 stat_sum_x2,
+                                                                                  uint64 n_dim, uint64 SUM_X, uint64 SUM_X2){
+  uint64 stat_sum_xe ;  /* somme des xn region exterieure */
+  uint32 ne ;             /* nombre de pixel region exterieure */
+  double sigi2, sige2; /* variance region interieure et exterieure */
+
+  /* variance des valeurs des niveaux de gris a l'interieur du snake */
+  sigi2 = 
+    (double)stat_sum_x2/(double)stat_sum_1 - 
+    (double)(stat_sum_x*stat_sum_x)/(double)((uint64)stat_sum_1*(uint64)stat_sum_1) ;
+
+  /* variance des valeurs des niveaux de gris a l'exterieur du snake */
+  ne = n_dim-stat_sum_1 ;
+  stat_sum_xe = SUM_X - stat_sum_x ;
+  sige2 =
+    (double)(SUM_X2-stat_sum_x2)/(double)ne - 
+    (double)(stat_sum_xe*stat_sum_xe)/(double)((uint64)ne*(uint64)ne) ;
+  
+  if ((sigi2 > 0)|(sige2 > 0))
+  return  0.5*((double)stat_sum_1*log(sigi2) + (double)ne*log(sige2)) ;
+  return -1 ;
+}
+
+__device__ inline unsigned int nextPow2_gpu( unsigned int x ) {
+  --x;
+  x |= x >> 1;
+  x |= x >> 2;
+  x |= x >> 4;
+  x |= x >> 8;
+  x |= x >> 16;
+  return ++x;
+}
+
+
+__device__ inline int sign_diff_strict(int val1, int val2)
+{
+  if (val1 > 0) 
+    {
+      if (val2 >= 0) return 0 ;
+      else return 1 ;
+    }
+  else 
+    if (val1 < 0)
+      {
+       if (val2 <= 0) return 0 ;
+       else  return 1 ;
+      }
+    else
+      return 0 ;/* val1 == 0 */
+}
+
+__device__ inline int sign_diff_ou_egal_zero(int val1, int val2)
+{
+  if (val1 > 0) 
+    {
+      if (val2 > 0) return 0 ;
+      else return 1 ;
+    }
+  else 
+    if (val1 < 0)
+      {
+               if (val2 < 0) return 0 ;
+               else  return 1 ;
+      }
+    else
+      return 1 ;/* val1 == 0 */
+}
+
+
+__device__ inline int sinus_triangle(int Ai, int Aj, int Bi, int Bj, int Ci, int Cj)
+{
+  return (((Bi-Ai)*(Cj-Aj)) - ((Ci-Ai)*(Bj-Aj))) ;
+}
+
+__device__ inline int test_croisement_large(uint32 Ai, uint32 Aj, uint32 Bi, uint32 Bj,
+                                                                                       uint32 Ui, uint32 Uj, uint32 Vi, uint32 Vj)
+{
+  if (sign_diff_strict(sinus_triangle(Ai, Aj, Bi, Bj, Ui, Uj),     // Bi-Ai, Uj-Aj, Ui-Ai, Bj-Aj
+                      sinus_triangle(Ai, Aj, Bi, Bj, Vi, Vj)))    // Bi-Ai, Vj-Aj, Vi-Ai, Bj-Aj
+    if (sign_diff_strict(sinus_triangle(Ui, Uj, Vi, Vj, Ai, Aj),   // Vi-Ui, Aj-Uj, Ai-Ui, Vj-Uj
+                        sinus_triangle(Ui, Uj, Vi, Vj, Bi, Bj)))  // Vi-Ui, Bj-Uj, Bi-Ui, Vj-Uj
+       return 1 ;
+  return 0 ;
+}
+
+__device__ inline int test_croisement_strict(uint32 Ai, uint32 Aj, uint32 Bi, uint32 Bj,
+                                                                                        uint32 Ui, uint32 Uj, uint32 Vi, uint32 Vj )
+{
+  if (sign_diff_ou_egal_zero(sinus_triangle(Ai, Aj, Bi, Bj, Ui, Uj),
+                                                        sinus_triangle(Ai, Aj, Bi, Bj, Vi, Vj)))  
+    if (sign_diff_ou_egal_zero(sinus_triangle(Ui, Uj, Vi, Vj, Ai, Aj),
+                                                          sinus_triangle(Ui, Uj, Vi, Vj, Bi, Bj)))
+      return 1 ;
+  return 0 ;
+}
+
+__global__ void kernel_test_croisement_move_seg_strict(struct snake_node_gpu *d_snake, uint32 nx, uint32 Nxi, uint32 Nxj, int Nb_nodes, bool * croist)
+{
+  int idx = blockDim.x*blockIdx.x + threadIdx.x, idx_prec, idx_suiv ;
+  int na, nb, naa, nbb  ;
+  int Nai, Naj, Nbi, Nbj ;
+  bool croistil = false ;
+  
+  calcul_indices_prec_suiv(Nb_nodes, nx, na, nb);
+  calcul_indices_prec_suiv(Nb_nodes, na, naa, nbb);
+
+  //coord. nodes extremites des segments a tester
+  Nai = d_snake[na].posi ;
+  Naj = d_snake[na].posj ;
+  Nbi = d_snake[nb].posi ;
+  Nbj = d_snake[nb].posj ;
+  
+  if (idx == nb) //premier segment apres
+       {
+         calcul_indices_prec_suiv(Nb_nodes, idx, idx_prec, idx_suiv);
+         if ( test_croisement_large(Nxi, Nxj, Nbi, Nbj,
+                                                                 Nbi, Nbj, d_snake[idx_suiv].posi, d_snake[idx_suiv].posj))
+               croistil = true ;
+         else if ( test_croisement_strict(Nai, Naj, Nxi, Nxj,
+                                                                          Nbi, Nbj, d_snake[idx_suiv].posi, d_snake[idx_suiv].posj) )
+               croistil = true ;
+       }
+  else if ( idx == naa ) //premier segment avant
+       {
+         if ( test_croisement_large(d_snake[naa].posi, d_snake[naa].posj, Nai, Naj,
+                                                                Nai, Naj, Nxi, Nxj) )
+               croistil = true ;
+         else if ( test_croisement_strict(d_snake[naa].posi, d_snake[naa].posj, Nai, Naj,
+                                                                          Nxi, Nxj, Nbi, Nbj))
+               croistil = true ;
+       }
+  else if ( (idx != nx) && (idx != na) ) //les autres segments
+       {
+         calcul_indices_prec_suiv(Nb_nodes, idx, idx_prec, idx_suiv);
+         if ( test_croisement_strict(Nai, Naj, Nxi, Nxj,
+                                                                 d_snake[idx].posi, d_snake[idx].posj,
+                                                                 d_snake[idx_suiv].posi, d_snake[idx_suiv].posj) )
+               croistil = true ;
+         else if ( test_croisement_strict(Nxi, Nxj, Nbi, Nbj,
+                                                                          d_snake[idx].posi, d_snake[idx].posj,
+                                                                          d_snake[idx_suiv].posi, d_snake[idx_suiv].posj) )
+               croistil = true ;
+       }
+        
+  croist[idx] = croistil ;
+}
+
+__device__ bool test_croisement(struct snake_node_gpu *d_snake, uint32 nx, uint32 Nxi, uint32 Nxj, int Nb_nodes)
+{
+  int idx_prec, idx_suiv ;
+  int na, nb, naa, nbb  ;
+  int Nai, Naj, Nbi, Nbj ;
+  bool croistil = false ;
+
+  //coord. nodes extremites des segments a tester
+  calcul_indices_prec_suiv(Nb_nodes, nx, na, nb);
+  calcul_indices_prec_suiv(Nb_nodes, na, naa, nbb);
+
+  Nai = d_snake[na].posi ;
+  Naj = d_snake[na].posj ;
+  Nbi = d_snake[nb].posi ;
+  Nbj = d_snake[nb].posj ;
+
+  //parcours du snake
+  for (int idx=0; idx < Nb_nodes; idx++){
+       if (idx == nb) //premier segment apres
+         {
+               calcul_indices_prec_suiv(Nb_nodes, idx, idx_prec, idx_suiv);
+               if ( test_croisement_large(Nxi, Nxj, Nbi, Nbj,
+                                                                  Nbi, Nbj, d_snake[idx_suiv].posi, d_snake[idx_suiv].posj))
+                 croistil = true ;
+               else if ( test_croisement_strict(Nai, Naj, Nxi, Nxj,
+                                                                          Nbi, Nbj, d_snake[idx_suiv].posi, d_snake[idx_suiv].posj) )
+                 croistil = true ;
+         }
+       else if ( idx == naa ) //premier segment avant
+         {
+               if ( test_croisement_large(d_snake[naa].posi, d_snake[naa].posj, Nai, Naj,
+                                                                  Nai, Naj, Nxi, Nxj) )
+                 croistil = true ;
+               else if ( test_croisement_strict(d_snake[naa].posi, d_snake[naa].posj, Nai, Naj,
+                                                                                Nxi, Nxj, Nbi, Nbj))
+                 croistil = true ;
+         }
+       else if ( (idx != nx) && (idx != na) ) //les autres segments
+         {
+               calcul_indices_prec_suiv(Nb_nodes, idx, idx_prec, idx_suiv);
+               if ( test_croisement_strict(Nai, Naj, Nxi, Nxj,
+                                                                       d_snake[idx].posi, d_snake[idx].posj,
+                                                                       d_snake[idx_suiv].posi, d_snake[idx_suiv].posj) )
+                 croistil = true ;
+               else if ( test_croisement_strict(Nxi, Nxj, Nbi, Nbj,
+                                                                                d_snake[idx].posi, d_snake[idx].posj,
+                                                                                d_snake[idx_suiv].posi, d_snake[idx_suiv].posj) )
+                 croistil = true ;
+         }
+  }     
+  return ( croistil );
+}
diff --git a/src/lib_math.c b/src/lib_math.c
new file mode 100644 (file)
index 0000000..79a2b20
--- /dev/null
@@ -0,0 +1,276 @@
+/**
+ * \file lib_math.c
+ * \brief routines 
+ * \author NB - PhyTI 
+ * \version x.x
+ * \date 20 decembre 2009
+ *
+ */
+
+#include <stdio.h>
+#include "lib_math.h"
+#include "constantes.h"
+
+/**
+ * \fn void tic(struct timeval* temps, char* texte)
+ * \brief Initialise le compteur de temps
+ *
+ * \param[out]  temps  
+ * \param[in]   texte texte a afficher
+ *
+ */
+void tic(struct timeval* temps, char* texte)
+{
+  gettimeofday(temps, NULL);
+
+  if (texte != NULL)
+    printf("%s\n", texte) ;
+}
+
+/**
+ * \fn double toc(struct timeval start, char* texte)
+ * \brief Calcule le temps ecoule
+ *
+ * \param[in]  start temps de debut du chrono  
+ * \param[in]  texte texte a afficher
+ *
+ * \return le temps ecoule entre tic et toc
+ */
+double toc(struct timeval start, char* texte)
+{
+  struct timeval end ;
+  double elapsed ;
+
+  gettimeofday(&end, NULL);
+
+  elapsed = (double)(end.tv_sec-start.tv_sec) 
+    + 0.000001*(double)(end.tv_usec-start.tv_usec);
+  if (texte != NULL)
+    printf("%s : %f\n", texte, elapsed) ;
+
+  return elapsed ;
+}
+
+
+/**
+ * \fn void min_max_int1d(int *val_min, int *val_max, int *vect, int dim)
+ * \brief determine le min et max d'un vecteur de int
+ *
+ * \param[out]  val_min 
+ * \param[out]  val_max 
+ * \param[in]   vect
+ * \param[in]   dim dimension du vecteur
+ *
+ */
+
+void min_max_int1d(int *val_min, int *val_max, int *vect, int dim)
+{
+  int n, min, max ;
+
+  min = vect[1];
+  max = min;
+  
+  for (n=0;n<dim;n++)
+    {
+      if (vect[n] > max) max = vect[n];
+      if (vect[n] < min) min = vect[n];
+    }
+
+  *val_min = min ;
+  *val_max = max ;
+}
+
+void min_max_ushort1d(int *val_min, int *val_max, unsigned short *vect, int dim)
+{
+  int n ;
+  unsigned short min, max ;
+
+  min = vect[1];
+  max = min;
+  
+  for (n=0;n<dim;n++)
+    {
+      if (vect[n] > max) max = vect[n];
+      if (vect[n] < min) min = vect[n];
+    }
+
+  *val_min = min ;
+  *val_max = max ;
+}
+
+
+
+
+/**
+ * \fn inline int test_inf(double arg1, double arg2)
+ *
+ * \brief test (arg1 < arg2) inferieur a avec pourcentage minimum
+ *
+ * \param[in]   arg1
+ * \param[in]   arg2
+ *
+ * return test
+ */
+inline int test_inf(double arg1, double arg2)
+{
+  if (arg2 > 0)
+    return arg1 < (arg2*COEF_DECROI) ;
+  else
+    return arg1 < (arg2*INV_COEF_DECROI) ;
+}
+
+
+
+/**
+ * \fn int calcul_px_autour_noeud(int ni, int nj, int pas, 
+ *                        int idim_m1, int jdim_m1,
+ *                        int *liste_pixel_move)
+ *
+ * \brief determine les positions de test autout d'un noeud
+ *
+ * \param[in]   ni coordonnee i
+ * \param[in]   nj coordonnee j
+ * \param[in]   pas ecartement par rapport au centre
+ * \param[in]   idim_m1 dimension de l'image sur l'axe i (-1)
+ * \param[in]   jdim_m1 dimension de l'image sur l'axe j (-1)
+ * \param[out]  liste_pixel_move liste des coordonnees [i,j,i,j,...]
+ *
+ * return le nombre de coordonnees (*2)
+ */
+uint32 calcul_px_autour_noeud(uint32 ni, uint32 nj, int pas, 
+                          uint32 idim_m1, uint32 jdim_m1,
+                          uint32 *liste_pixel_move)
+{
+  uint32 ind = 0 ;
+  
+  liste_pixel_move[ind++] = min(ni + pas, idim_m1) ;
+  liste_pixel_move[ind++] = nj ;
+
+  liste_pixel_move[ind++] = min(ni + pas, idim_m1) ;
+  liste_pixel_move[ind++] = min(nj + pas, jdim_m1) ;
+
+  liste_pixel_move[ind++] = ni ;
+  liste_pixel_move[ind++] = min(nj + pas, jdim_m1) ;
+
+  liste_pixel_move[ind++] = max(ni - pas, 0) ;
+  liste_pixel_move[ind++] = min(nj + pas, jdim_m1) ;
+
+  liste_pixel_move[ind++] = max(ni - pas, 0) ;
+  liste_pixel_move[ind++] = nj ;
+
+  liste_pixel_move[ind++] = max(ni - pas, 0) ;
+  liste_pixel_move[ind++] = max(nj - pas, 0) ;
+
+  liste_pixel_move[ind++] = ni  ;
+  liste_pixel_move[ind++] = max(nj - pas, 0) ;
+
+  liste_pixel_move[ind++] = min(ni + pas, idim_m1) ;
+  liste_pixel_move[ind++] = max(nj - pas, 0) ;
+
+  return ind ;
+}
+
+
+
+/**
+ * \fn inline int sign_diff_ou_egal_zero(int val1, int val2)
+ *
+ * \brief fonction qui test si les arguments sont de signes differents ou nuls
+ * \author NB - PhyTI
+ *
+ * \param[in] val1 
+ * \param[in] val2
+ *
+ * \return le test 0/1 
+ *
+ */
+inline int sign_diff_ou_egal_zero(int val1, int val2)
+{
+  if (val1 > 0) 
+    {
+      if (val2 > 0) return 0 ;
+      else return 1 ;
+    }
+  else 
+    if (val1 < 0)
+      {
+               if (val2 < 0) return 0 ;
+               else  return 1 ;
+      }
+    else
+      return 1 ;/* val1 == 0 */
+}
+
+/**
+ * \fn inline int sign_diff_strict(int val1, int val2)
+ *
+ * \brief fonction qui test si les arguments sont de signes differents strictement
+ * \author NB - PhyTI
+ *
+ * \param[in] val1 
+ * \param[in] val2
+ *
+ * \return le test 0/1 
+ *
+ */
+inline int sign_diff_strict(int val1, int val2)
+{
+  if (val1 > 0) 
+    {
+      if (val2 >= 0) return 0 ;
+      else return 1 ;
+    }
+  else 
+    if (val1 < 0)
+      {
+       if (val2 <= 0) return 0 ;
+       else  return 1 ;
+      }
+    else
+      return 0 ;/* val1 == 0 */
+}
+
+
+
+/**
+ * \fn inline int sinus_triangle(int Ai, int Aj, int Bi, int Bj, int Ci, int Cj)
+ *
+ * \brief calcul le "sinus" de l'angle du triangle ABC 
+ * \author NB - PhyTI
+ *
+ * \param[in] Ai les coordonnees
+ * \param[in] Aj
+ * \param[in] Bi
+ * \param[in] Bj
+ * \param[in] Ci
+ * \param[in] Cj
+ *
+ * \return le sinus non normalise 
+ *
+ * Cette fonction est utile pour determiner si un triangle ABC
+ * est donne dans l'ordre trigo. 
+ * Signe > 0: sens trigo,
+ * signe < 0: sens antitrigo
+ *       = 0: plat
+ */
+inline int sinus_triangle(int Ai, int Aj, int Bi, int Bj, int Ci, int Cj)
+{
+  return (((Bi-Ai)*(Cj-Aj)) - ((Ci-Ai)*(Bj-Aj))) ;
+}
+
+
+/**
+ * \fn void recopie_vecteur(int *in, int *out, int dim)
+ *
+ * \brief recopie le vecteur out vers in
+ * \author NB - PhyTI
+ *
+ * \param[in]  in  vecteur d'entree
+ * \param[out] out vecteur recopier
+ * \param[in]  dim longueur du vecteur
+ */
+void recopie_vecteur(int *in, int *out, int dim)
+{
+  int n ;
+  for (n=0; n<dim; n++) out[n] = in[n] ;
+}
diff --git a/src/lib_math.c~ b/src/lib_math.c~
new file mode 100644 (file)
index 0000000..9a0bcb2
--- /dev/null
@@ -0,0 +1,257 @@
+/**
+ * \file lib_math.c
+ * \brief routines 
+ * \author NB - PhyTI 
+ * \version x.x
+ * \date 20 decembre 2009
+ *
+ */
+
+#include <stdio.h>
+#include "lib_math.h"
+#include "constantes.h"
+
+/**
+ * \fn void tic(struct timeval* temps, char* texte)
+ * \brief Initialise le compteur de temps
+ *
+ * \param[out]  temps  
+ * \param[in]   texte texte a afficher
+ *
+ */
+void tic(struct timeval* temps, char* texte)
+{
+  gettimeofday(temps, NULL);
+
+  if (texte != NULL)
+    printf("%s\n", texte) ;
+}
+
+/**
+ * \fn double toc(struct timeval start, char* texte)
+ * \brief Calcule le temps ecoule
+ *
+ * \param[in]  start temps de debut du chrono  
+ * \param[in]  texte texte a afficher
+ *
+ * \return le temps ecoule entre tic et toc
+ */
+double toc(struct timeval start, char* texte)
+{
+  struct timeval end ;
+  double elapsed ;
+
+  gettimeofday(&end, NULL);
+
+  elapsed = (double)(end.tv_sec-start.tv_sec) 
+    + 0.000001*(double)(end.tv_usec-start.tv_usec);
+  if (texte != NULL)
+    printf("%s : %f\n", texte, elapsed) ;
+
+  return elapsed ;
+}
+
+
+/**
+ * \fn void min_max_int1d(int *val_min, int *val_max, int *vect, int dim)
+ * \brief determine le min et max d'un vecteur de int
+ *
+ * \param[out]  val_min 
+ * \param[out]  val_max 
+ * \param[in]   vect
+ * \param[in]   dim dimension du vecteur
+ *
+ */
+void min_max_int1d(int *val_min, int *val_max, int *vect, int dim)
+{
+  int n, min, max ;
+
+  min = vect[1];
+  max = min;
+  
+  for (n=0;n<dim;n++)
+    {
+      if (vect[n] > max) max = vect[n];
+      if (vect[n] < min) min = vect[n];
+    }
+
+  *val_min = min ;
+  *val_max = max ;
+}
+
+
+
+
+/**
+ * \fn inline int test_inf(double arg1, double arg2)
+ *
+ * \brief test (arg1 < arg2) inferieur a avec pourcentage minimum
+ *
+ * \param[in]   arg1
+ * \param[in]   arg2
+ *
+ * return test
+ */
+inline int test_inf(double arg1, double arg2)
+{
+  if (arg2 > 0)
+    return arg1 < (arg2*COEF_DECROI) ;
+  else
+    return arg1 < (arg2*INV_COEF_DECROI) ;
+}
+
+
+
+/**
+ * \fn int calcul_px_autour_noeud(int ni, int nj, int pas, 
+ *                        int idim_m1, int jdim_m1,
+ *                        int *liste_pixel_move)
+ *
+ * \brief determine les positions de test autout d'un noeud
+ *
+ * \param[in]   ni coordonnee i
+ * \param[in]   nj coordonnee j
+ * \param[in]   pas ecartement par rapport au centre
+ * \param[in]   idim_m1 dimension de l'image sur l'axe i (-1)
+ * \param[in]   jdim_m1 dimension de l'image sur l'axe j (-1)
+ * \param[out]  liste_pixel_move liste des coordonnees [i,j,i,j,...]
+ *
+ * return le nombre de coordonnees (*2)
+ */
+uint32 calcul_px_autour_noeud(uint32 ni, uint32 nj, int pas, 
+                          uint32 idim_m1, uint32 jdim_m1,
+                          uint32 *liste_pixel_move)
+{
+  uint32 ind = 0 ;
+  
+  liste_pixel_move[ind++] = min(ni + pas, idim_m1) ;
+  liste_pixel_move[ind++] = nj ;
+
+  liste_pixel_move[ind++] = min(ni + pas, idim_m1) ;
+  liste_pixel_move[ind++] = min(nj + pas, jdim_m1) ;
+
+  liste_pixel_move[ind++] = ni ;
+  liste_pixel_move[ind++] = min(nj + pas, jdim_m1) ;
+
+  liste_pixel_move[ind++] = max(ni - pas, 0) ;
+  liste_pixel_move[ind++] = min(nj + pas, jdim_m1) ;
+
+  liste_pixel_move[ind++] = max(ni - pas, 0) ;
+  liste_pixel_move[ind++] = nj ;
+
+  liste_pixel_move[ind++] = max(ni - pas, 0) ;
+  liste_pixel_move[ind++] = max(nj - pas, 0) ;
+
+  liste_pixel_move[ind++] = ni  ;
+  liste_pixel_move[ind++] = max(nj - pas, 0) ;
+
+  liste_pixel_move[ind++] = min(ni + pas, idim_m1) ;
+  liste_pixel_move[ind++] = max(nj - pas, 0) ;
+
+  return ind ;
+}
+
+
+
+/**
+ * \fn inline int sign_diff_ou_egal_zero(int val1, int val2)
+ *
+ * \brief fonction qui test si les arguments sont de signes differents ou nuls
+ * \author NB - PhyTI
+ *
+ * \param[in] val1 
+ * \param[in] val2
+ *
+ * \return le test 0/1 
+ *
+ */
+inline int sign_diff_ou_egal_zero(int val1, int val2)
+{
+  if (val1 > 0) 
+    {
+      if (val2 > 0) return 0 ;
+      else return 1 ;
+    }
+  else 
+    if (val1 < 0)
+      {
+               if (val2 < 0) return 0 ;
+               else  return 1 ;
+      }
+    else
+      return 1 ;/* val1 == 0 */
+}
+
+/**
+ * \fn inline int sign_diff_strict(int val1, int val2)
+ *
+ * \brief fonction qui test si les arguments sont de signes differents strictement
+ * \author NB - PhyTI
+ *
+ * \param[in] val1 
+ * \param[in] val2
+ *
+ * \return le test 0/1 
+ *
+ */
+inline int sign_diff_strict(int val1, int val2)
+{
+  if (val1 > 0) 
+    {
+      if (val2 >= 0) return 0 ;
+      else return 1 ;
+    }
+  else 
+    if (val1 < 0)
+      {
+       if (val2 <= 0) return 0 ;
+       else  return 1 ;
+      }
+    else
+      return 0 ;/* val1 == 0 */
+}
+
+
+
+/**
+ * \fn inline int sinus_triangle(int Ai, int Aj, int Bi, int Bj, int Ci, int Cj)
+ *
+ * \brief calcul le "sinus" de l'angle du triangle ABC 
+ * \author NB - PhyTI
+ *
+ * \param[in] Ai les coordonnees
+ * \param[in] Aj
+ * \param[in] Bi
+ * \param[in] Bj
+ * \param[in] Ci
+ * \param[in] Cj
+ *
+ * \return le sinus non normalise 
+ *
+ * Cette fonction est utile pour determiner si un triangle ABC
+ * est donne dans l'ordre trigo. 
+ * Signe > 0: sens trigo,
+ * signe < 0: sens antitrigo
+ *       = 0: plat
+ */
+inline int sinus_triangle(int Ai, int Aj, int Bi, int Bj, int Ci, int Cj)
+{
+  return (((Bi-Ai)*(Cj-Aj)) - ((Ci-Ai)*(Bj-Aj))) ;
+}
+
+
+/**
+ * \fn void recopie_vecteur(int *in, int *out, int dim)
+ *
+ * \brief recopie le vecteur out vers in
+ * \author NB - PhyTI
+ *
+ * \param[in]  in  vecteur d'entree
+ * \param[out] out vecteur recopier
+ * \param[in]  dim longueur du vecteur
+ */
+void recopie_vecteur(int *in, int *out, int dim)
+{
+  int n ;
+  for (n=0; n<dim; n++) out[n] = in[n] ;
+}
diff --git a/src/lib_math.h b/src/lib_math.h
new file mode 100644 (file)
index 0000000..63b4402
--- /dev/null
@@ -0,0 +1,31 @@
+#ifndef _LIB_MATH_H
+#define _LIB_MATH_H
+
+
+#include <sys/time.h>
+#include "structures.h"
+
+void tic(struct timeval* temps, char* texte) ;
+double toc(struct timeval start, char* texte) ;
+
+void min_max_int1d(int *val_min, int *val_max, int *vect, int dim) ;
+void min_max_ushort1d(int *val_min, int *val_max, unsigned short *vect, int dim) ;
+
+#define min(a,b) ((a)<(b)) ? (a) : (b) 
+#define max(a,b) ((a)>(b)) ? (a) : (b) 
+
+uint32 calcul_px_autour_noeud(uint32 ni, uint32 nj, int pas, 
+                          uint32 idim_m1, uint32 jdim_m1,
+                          uint32 *liste_pixel_move);
+
+inline int test_inf(double arg1, double arg2);
+
+inline int sign_diff_ou_egal_zero(int val1, int val2);
+inline int sign_diff_strict(int val1, int val2);
+
+inline int sinus_triangle(int Ai, int Aj, int Bi, int Bj, int Ci, int Cj);
+
+void recopie_vecteur(int *in, int *out, int dim) ;
+
+
+#endif
diff --git a/src/lib_math.h~ b/src/lib_math.h~
new file mode 100644 (file)
index 0000000..ba4bead
--- /dev/null
@@ -0,0 +1,30 @@
+#ifndef _LIB_MATH_H
+#define _LIB_MATH_H
+
+
+#include <sys/time.h>
+#include "structures.h"
+
+void tic(struct timeval* temps, char* texte) ;
+double toc(struct timeval start, char* texte) ;
+
+void min_max_int1d(int *val_min, int *val_max, int *vect, int dim) ;
+
+#define min(a,b) ((a)<(b)) ? (a) : (b) 
+#define max(a,b) ((a)>(b)) ? (a) : (b) 
+
+uint32 calcul_px_autour_noeud(uint32 ni, uint32 nj, int pas, 
+                          uint32 idim_m1, uint32 jdim_m1,
+                          uint32 *liste_pixel_move);
+
+inline int test_inf(double arg1, double arg2);
+
+inline int sign_diff_ou_egal_zero(int val1, int val2);
+inline int sign_diff_strict(int val1, int val2);
+
+inline int sinus_triangle(int Ai, int Aj, int Bi, int Bj, int Ci, int Cj);
+
+void recopie_vecteur(int *in, int *out, int dim) ;
+
+
+#endif
diff --git a/src/lib_snake_2_gpu.cu b/src/lib_snake_2_gpu.cu
new file mode 100644 (file)
index 0000000..63db755
--- /dev/null
@@ -0,0 +1,141 @@
+
+extern "C"{
+#include "structures.h"
+#include "lib_snake_2_gpu.h"
+}
+#include "stdio.h"
+
+void snake2gpu( snake_node_gpu * d_snake, snake_node* h_snake, int n ){
+
+  snake_node * snake = h_snake;
+  snake_node_gpu snake_nodes[n];
+
+  for (int i=0; i<n; i++){
+       
+       snake_nodes[i].sum_1 = snake->contrib.sum_1 ;
+       snake_nodes[i].sum_x = snake->contrib.sum_x ;
+       snake_nodes[i].sum_x2 = snake->contrib.sum_x2 ;
+       
+       snake_nodes[i].code_segment = snake->code_segment ;
+       snake_nodes[i].freeman_in = snake->freeman_in ;
+       snake_nodes[i].freeman_out = snake->freeman_out ;
+       snake_nodes[i].nb_pixels = snake->nb_pixels ;
+
+       snake_nodes[i].posi = snake->posi ;
+       snake_nodes[i].posj = snake->posj ;
+       snake_nodes[i].centre_i = snake->centre_i ;
+       snake_nodes[i].centre_j = snake->centre_j ;
+
+       snake_nodes[i].last_move = snake->last_move ;
+       
+       snake = snake->noeud_suiv ;
+  }
+  
+  cudaMemcpy( d_snake, snake_nodes, n*sizeof(snake_node_gpu), cudaMemcpyHostToDevice );
+
+  /*verif integrite data*/
+  /*
+  snake_node_gpu new_snake_nodes[n];
+  cudaMemcpy( new_snake_nodes , d_snake, n*sizeof(snake_node_gpu), cudaMemcpyDeviceToHost );
+
+  for (int i=0; i<n; i++){
+       printf("NODE %d : ", i);
+       printf("\tsum_1 : %u - sum_x : %lu - sum_x2 : %lu\n", new_snake_nodes[i].sum_1,  new_snake_nodes[i].sum_x ,  new_snake_nodes[i].sum_x2) ;
+       
+       printf("\tcode_segment : %d\n", new_snake_nodes[i].code_segment ) ;
+       printf("\tfreeman_in : %d\n", new_snake_nodes[i].freeman_in );
+       printf("\tfreeman_out : %d\n", new_snake_nodes[i].freeman_out ) ;
+       printf("\tnb_pixels : %d\n", new_snake_nodes[i].nb_pixels ) ;
+
+       printf("\ti = %d\n", new_snake_nodes[i].posi ) ;
+       printf("\tj = %d\n", new_snake_nodes[i].posj ) ;
+       printf("\tcentre i = %d\n", new_snake_nodes[i].centre_i ) ;
+       printf("\tcentre j = %d\n", new_snake_nodes[i].centre_j ) ;
+
+       printf("\tlast_move : %d\n", new_snake_nodes[i].last_move ) ;
+
+       }
+  */
+}
+
+
+void gpu2snake( snake_node_gpu * d_snake, snake_node **h_snake, int n ){
+  
+  snake_node *snake_prec, *snake ;
+  snake_node_gpu * snake_nodes = new snake_node_gpu[n];
+  cudaMemcpy( snake_nodes, d_snake, n*sizeof(snake_node_gpu), cudaMemcpyDeviceToHost );
+
+  *h_snake = new snake_node;
+  
+  for (int i=0; i<n; i++){
+       if (i == 0 ) snake = *h_snake;
+       else {
+         snake_prec = snake;
+         snake = new snake_node;
+         snake_prec->noeud_suiv = snake;
+         snake->noeud_prec = snake_prec;
+       }
+       if (i == n-1) {
+         snake->noeud_suiv = *h_snake;
+         (*h_snake)->noeud_prec = snake;
+       }
+       /*
+       snake->contrib.sum_1 = snake_nodes[i].sum_1 ;
+       snake->contrib.sum_x = snake_nodes[i].sum_x ;
+       snake->contrib.sum_x2 = snake_nodes[i].sum_x2 ;
+       
+       snake->code_segment = snake_nodes[i].code_segment ;
+       snake->freeman_in = snake_nodes[i].freeman_in ;
+       snake->freeman_out = snake_nodes[i].freeman_out ;
+       */
+       snake->nb_pixels = snake_nodes[i].nb_pixels ;
+       snake->posi = snake_nodes[i].posi ;
+       snake->posj = snake_nodes[i].posj ;
+       /*
+       snake->centre_i = snake_nodes[i].centre_i ;
+       snake->centre_j = snake_nodes[i].centre_j ;
+       snake->last_move = snake_nodes[i].last_move ;
+       */
+  }
+  
+  /*verif integrite donnees*/
+  
+  snake = *h_snake ;
+  for (int i=0; i<n; i++){
+       printf("NODE %d : ", i);
+       /*
+       printf("\tcode_segment : %d\n", snake->code_segment ) ;
+       printf("\tfreeman_in : %d\n", snake->freeman_in );
+       printf("\tfreeman_out : %d\n", snake->freeman_out ) ;
+       */
+       printf("\tnb_pixels : %d", snake->nb_pixels ) ;
+
+       printf("\ti = %d ", snake->posi ) ;
+       printf("\tj = %d \n", snake->posj ) ;
+       /*
+       printf("\tcentre i = %d\n", snake->centre_i ) ;
+       printf("\tcentre j = %d\n", snake->centre_j ) ;
+
+       printf("\tcontribs = %lu - %lu - %lu\n", snake->contrib.sum_1, snake->contrib.sum_x, snake->contrib.sum_x2 ) ;
+
+       printf("\tlast_move : %d\n", snake->last_move ) ;
+       */
+       snake = snake->noeud_suiv;
+       }
+  delete snake_nodes;
+}
+
+void dessine_snake(snake_node_gpu * snake, int nnodes, unsigned short ** img, int r){
+     int couleur = 255;
+     int i,j;
+     for (int node=0;node < nnodes; node++){
+        i = snake[node].posi ;
+        j = snake[node].posj ;
+        for (int xi=0; xi<=r; xi++){
+                img[i-xi][j] = couleur ;
+                img[i+xi][j] = couleur ; 
+                img[i][j-xi] = couleur ;
+                img[i][j+xi] = couleur ; 
+                }
+     }
+}
\ No newline at end of file
diff --git a/src/lib_snake_2_gpu.cu~ b/src/lib_snake_2_gpu.cu~
new file mode 100644 (file)
index 0000000..3f44329
--- /dev/null
@@ -0,0 +1,126 @@
+
+extern "C"{
+#include "structures.h"
+#include "lib_snake_2_gpu.h"
+}
+#include "stdio.h"
+
+void snake2gpu( snake_node_gpu * d_snake, snake_node* h_snake, int n ){
+
+  snake_node * snake = h_snake;
+  snake_node_gpu snake_nodes[n];
+
+  for (int i=0; i<n; i++){
+       
+       snake_nodes[i].sum_1 = snake->contrib.sum_1 ;
+       snake_nodes[i].sum_x = snake->contrib.sum_x ;
+       snake_nodes[i].sum_x2 = snake->contrib.sum_x2 ;
+       
+       snake_nodes[i].code_segment = snake->code_segment ;
+       snake_nodes[i].freeman_in = snake->freeman_in ;
+       snake_nodes[i].freeman_out = snake->freeman_out ;
+       snake_nodes[i].nb_pixels = snake->nb_pixels ;
+
+       snake_nodes[i].posi = snake->posi ;
+       snake_nodes[i].posj = snake->posj ;
+       snake_nodes[i].centre_i = snake->centre_i ;
+       snake_nodes[i].centre_j = snake->centre_j ;
+
+       snake_nodes[i].last_move = snake->last_move ;
+       
+       snake = snake->noeud_suiv ;
+  }
+  
+  cudaMemcpy( d_snake, snake_nodes, n*sizeof(snake_node_gpu), cudaMemcpyHostToDevice );
+
+  /*verif integrite data*/
+  /*
+  snake_node_gpu new_snake_nodes[n];
+  cudaMemcpy( new_snake_nodes , d_snake, n*sizeof(snake_node_gpu), cudaMemcpyDeviceToHost );
+
+  for (int i=0; i<n; i++){
+       printf("NODE %d : ", i);
+       printf("\tsum_1 : %u - sum_x : %lu - sum_x2 : %lu\n", new_snake_nodes[i].sum_1,  new_snake_nodes[i].sum_x ,  new_snake_nodes[i].sum_x2) ;
+       
+       printf("\tcode_segment : %d\n", new_snake_nodes[i].code_segment ) ;
+       printf("\tfreeman_in : %d\n", new_snake_nodes[i].freeman_in );
+       printf("\tfreeman_out : %d\n", new_snake_nodes[i].freeman_out ) ;
+       printf("\tnb_pixels : %d\n", new_snake_nodes[i].nb_pixels ) ;
+
+       printf("\ti = %d\n", new_snake_nodes[i].posi ) ;
+       printf("\tj = %d\n", new_snake_nodes[i].posj ) ;
+       printf("\tcentre i = %d\n", new_snake_nodes[i].centre_i ) ;
+       printf("\tcentre j = %d\n", new_snake_nodes[i].centre_j ) ;
+
+       printf("\tlast_move : %d\n", new_snake_nodes[i].last_move ) ;
+
+       }
+  */
+}
+
+
+void gpu2snake( snake_node_gpu * d_snake, snake_node **h_snake, int n ){
+  
+  snake_node *snake_prec, *snake ;
+  snake_node_gpu * snake_nodes = new snake_node_gpu[n];
+  cudaMemcpy( snake_nodes, d_snake, n*sizeof(snake_node_gpu), cudaMemcpyDeviceToHost );
+
+  *h_snake = new snake_node;
+  
+  for (int i=0; i<n; i++){
+       if (i == 0 ) snake = *h_snake;
+       else {
+         snake_prec = snake;
+         snake = new snake_node;
+         snake_prec->noeud_suiv = snake;
+         snake->noeud_prec = snake_prec;
+       }
+       if (i == n-1) {
+         snake->noeud_suiv = *h_snake;
+         (*h_snake)->noeud_prec = snake;
+       }
+       /*
+       snake->contrib.sum_1 = snake_nodes[i].sum_1 ;
+       snake->contrib.sum_x = snake_nodes[i].sum_x ;
+       snake->contrib.sum_x2 = snake_nodes[i].sum_x2 ;
+       
+       snake->code_segment = snake_nodes[i].code_segment ;
+       snake->freeman_in = snake_nodes[i].freeman_in ;
+       snake->freeman_out = snake_nodes[i].freeman_out ;
+       */
+       snake->nb_pixels = snake_nodes[i].nb_pixels ;
+       snake->posi = snake_nodes[i].posi ;
+       snake->posj = snake_nodes[i].posj ;
+       /*
+       snake->centre_i = snake_nodes[i].centre_i ;
+       snake->centre_j = snake_nodes[i].centre_j ;
+       snake->last_move = snake_nodes[i].last_move ;
+       */
+  }
+  
+  /*verif integrite donnees*/
+  
+  snake = *h_snake ;
+  for (int i=0; i<n; i++){
+       printf("NODE %d : ", i);
+       /*
+       printf("\tcode_segment : %d\n", snake->code_segment ) ;
+       printf("\tfreeman_in : %d\n", snake->freeman_in );
+       printf("\tfreeman_out : %d\n", snake->freeman_out ) ;
+       */
+       printf("\tnb_pixels : %d", snake->nb_pixels ) ;
+
+       printf("\ti = %d ", snake->posi ) ;
+       printf("\tj = %d \n", snake->posj ) ;
+       /*
+       printf("\tcentre i = %d\n", snake->centre_i ) ;
+       printf("\tcentre j = %d\n", snake->centre_j ) ;
+
+       printf("\tcontribs = %lu - %lu - %lu\n", snake->contrib.sum_1, snake->contrib.sum_x, snake->contrib.sum_x2 ) ;
+
+       printf("\tlast_move : %d\n", snake->last_move ) ;
+       */
+       snake = snake->noeud_suiv;
+       }
+  delete snake_nodes;
+}
diff --git a/src/lib_snake_2_gpu.h b/src/lib_snake_2_gpu.h
new file mode 100644 (file)
index 0000000..b4fa104
--- /dev/null
@@ -0,0 +1,9 @@
+#ifndef __LIB_SNAKE_2_GPU_H__
+#define __LIB_SNAKE_2_GPU_H__
+
+void snake2gpu( struct snake_node_gpu * d_snake, struct snake_node * h_snake, int n );
+
+void gpu2snake( struct snake_node_gpu * d_snake, struct snake_node ** h_snake, int n );
+
+void dessine_snake(snake_node_gpu * snake, int nnodes, unsigned short ** img, int r);
+#endif
diff --git a/src/lib_snake_2_gpu.h~ b/src/lib_snake_2_gpu.h~
new file mode 100644 (file)
index 0000000..506c387
--- /dev/null
@@ -0,0 +1,8 @@
+#ifndef __LIB_SNAKE_2_GPU_H__
+#define __LIB_SNAKE_2_GPU_H__
+
+void snake2gpu( struct snake_node_gpu * d_snake, struct snake_node * h_snake, int n );
+
+void gpu2snake( struct snake_node_gpu * d_snake, struct snake_node ** h_snake, int n );
+
+#endif
diff --git a/src/lib_snake_common.c b/src/lib_snake_common.c
new file mode 100644 (file)
index 0000000..dc2b49e
--- /dev/null
@@ -0,0 +1,723 @@
+/**
+ * \file lib_snake_common.c
+ * \brief routines de bases pour la gestion du snake
+ * \author NB - PhyTI 
+ * \version x.x
+ * \date 25 decembre 2009
+ *
+ */
+
+#include <malloc.h>
+
+#include "lib_snake_common.h"
+#include "lib_contour.h" 
+#include "lib_math.h"
+
+
+/* debug */
+#include <stdio.h>
+#include "lib_images.h"
+#include "lib_alloc.h"
+
+
+/**
+ * \fn struct snake_node* genere_snake_rectangle_bords(int *nb_noeud, int distance_bords,
+ *                         int i_dim, int j_dim)
+ *
+ * \brief Initialise un snake rectangulaire par rapport au bords de l'image
+ * \author NB - PhyTI
+ *
+ * \param[out] nb_noeud renvoie le nombre de node du snake 
+ * \param[in]  distance_bords distance du rectangle par rapport au bords 
+ * \param[in]  i_dim dimension verticale de l'image
+ * \param[in]  j_dim dimension horizontale de l'image
+ *
+ * \return le pointeur du premier noeud du snake
+ *
+ * note : les calculs sse necessite l'alignement memoire des snake_node
+ */
+struct snake_node* genere_snake_rectangle_bords(uint32 *nb_noeud, uint32 distance_bords, 
+                                               uint32 i_dim, uint32 j_dim)
+{
+  struct snake_node *n1, *n2, *n3 ; /* noeuds courant */
+  struct snake_node *n0 = malloc(sizeof(struct snake_node)) ;
+
+  /* n0 */
+  *nb_noeud = 1 ;
+  n0->posi = distance_bords ;
+  n0->posj = distance_bords ;
+  n0->noeud_suiv = malloc(sizeof(struct snake_node)) ;
+  (*nb_noeud)++ ;
+  /* n1 */
+  n1 = n0->noeud_suiv ;
+  n1->posi = i_dim - distance_bords ;
+  n1->posj = distance_bords ; 
+  n1->noeud_prec = n0 ; 
+  n1->noeud_suiv = malloc(sizeof(struct snake_node)) ;
+  (*nb_noeud)++ ;
+  /* n2 */
+  n2 = n1->noeud_suiv ;
+  n2->posi = i_dim - distance_bords ;
+  n2->posj = j_dim - distance_bords ; 
+  n2->noeud_prec = n1 ; 
+  n2->noeud_suiv = malloc(sizeof(struct snake_node)) ;
+  (*nb_noeud)++ ;
+  /* n3 */
+  n3 = n2->noeud_suiv ;
+  n3->posi = distance_bords ;
+  n3->posj = j_dim - distance_bords ; 
+  n3->noeud_prec = n2 ; 
+  n3->noeud_suiv = n0 ;  /* on ferme le snake */
+  /* n0, on ferme le snake */
+  n0->noeud_prec = n3 ; 
+  
+  return n0 ;
+}
+
+/**
+ * \fn struct snake_node* genere_snake_rectangle(int *nb_noeud,int i1,int j1,int i2,int j2, 
+ *                         int i_dim, int j_dim)
+ *
+ * \brief Initialise un snake rectangulaire definie par deux noeuds
+ * \author NB - PhyTI
+ *
+ * \param[out] nb_noeud renvoie le nombre de node du snake 
+ * \param[in]  i1 coordonnee du coin haut-gauche
+ * \param[in]  j1 coordonnee du coin haut-gauche
+ * \param[in]  i2 coordonnee du coin bas-droit
+ * \param[in]  j2 coordonnee du coin bas-droit 
+ * \param[in]  i_dim dimension verticale de l'image
+ * \param[in]  j_dim dimension horizontale de l'image
+ *
+ * \return le pointeur du premier noeud du snake
+ *
+ * note : les calculs sse necessite l'alignement memoire des snake_node
+ */
+struct snake_node* genere_snake_rectangle(int *nb_noeud, uint32 i1, uint32 j1, uint32 i2, uint32 j2, 
+                                         uint32 i_dim, uint32 j_dim)
+{
+  struct snake_node *n1, *n2, *n3 ; /* noeuds courant */
+  struct snake_node *n0 = malloc(sizeof(struct snake_node)) ;
+
+  /* n0 */
+  *nb_noeud = 1 ;
+  n0->posi = i1 ;
+  n0->posj = j1 ;
+  n0->noeud_suiv = malloc(sizeof(struct snake_node)) ;
+  (*nb_noeud)++ ;
+  /* n1 */
+  n1 = n0->noeud_suiv ;
+  n1->posi = i2 ;
+  n1->posj = j1 ; 
+  n1->noeud_prec = n0 ; 
+  n1->noeud_suiv = malloc(sizeof(struct snake_node)) ;
+  (*nb_noeud)++ ;
+  /* n2 */
+  n2 = n1->noeud_suiv ;
+  n2->posi = i2 ;
+  n2->posj = j2 ; 
+  n2->noeud_prec = n1 ; 
+  n2->noeud_suiv = malloc(sizeof(struct snake_node)) ;
+  (*nb_noeud)++ ;
+  /* n3 */
+  n3 = n2->noeud_suiv ;
+  n3->posi = i1 ;
+  n3->posj = j2 ; 
+  n3->noeud_prec = n2 ; 
+  n3->noeud_suiv = n0 ;  /* on ferme le snake */
+  /* n0, on ferme le snake */
+  n0->noeud_prec = n3 ; 
+
+  return n0 ;
+}
+
+
+
+
+
+
+/**
+ * \fn int affiche_snake(int **image, struct snake_node *snake, 
+ *                       int valseg, int valnoeud, int *liste_pixel_segment)
+ *
+ * \brief Affiche le snake sur une image N&B 
+ * \author NB - PhyTI
+ *
+ * \param[out] image image ou le snake doit etre affiche 
+ * \param[in]  snake premier noeud du snake 
+ * \param[in]  valseg valeur de niveau de gris des segments
+ * \param[in]  valnoeud valeur de niveau de gris des noeuds
+ * \param[out] liste_pixel_segment pour caluls temporaire
+ *
+ * \return nb_noeud le nombre de noeuds du snake
+ *
+ */
+void affiche_snake(int **image, struct snake_node *snake, int valseg, int valnoeud,
+                 uint32 *liste_pixel_segment)
+{
+  uint32 i1, j1, i2, j2 ;
+  uint32 n, nb_pixel_segment ;
+  struct snake_node *np, *npp1 ;
+  
+  /* les segments */
+  np = snake ;
+  npp1 = snake->noeud_suiv ;
+  do
+    {
+      i1 = np->posi ; j1 = np->posj ;
+      i2 = npp1->posi ; j2 = npp1->posj ;
+      
+      nb_pixel_segment = calcul_liste_pixel_segment(i1,j1,i2,j2, liste_pixel_segment, 0) ;
+      for (n=1; n<nb_pixel_segment-1; n++)
+       image[liste_pixel_segment[2*n]][liste_pixel_segment[2*n+1]] = valseg ;
+      
+      np = npp1 ;
+      npp1 = np->noeud_suiv ;
+    }
+  while (np != snake) ;
+  
+  /* les deux noeuds */
+  np = snake ;
+  npp1 = snake->noeud_suiv ;
+  do
+    {
+      i1 = np->posi ; j1 = np->posj ;
+      i2 = npp1->posi ; j2 = npp1->posj ;
+      
+      image[i1][j1] = valnoeud ;
+      image[i2][j2] = valnoeud ;
+      
+      np = npp1 ;
+      npp1 = np->noeud_suiv ;
+    }
+  while (np != snake) ;
+}
+
+void affiche_snake_ushort(unsigned short **image, struct snake_node *snake, int valseg, unsigned short valnoeud,
+                                                 uint32 *liste_pixel_segment)
+{
+  uint32 i1, j1, i2, j2 ;
+  uint32 n, nb_pixel_segment ;
+  struct snake_node *np, *npp1 ;
+  
+  /* les segments */
+  np = snake ;
+  npp1 = snake->noeud_suiv ;
+  
+  do
+    {
+      i1 = np->posi ; j1 = np->posj ;
+      i2 = npp1->posi ; j2 = npp1->posj ;
+         
+      nb_pixel_segment = calcul_liste_pixel_segment(i1,j1,i2,j2, liste_pixel_segment, 0) ;
+        
+      for (n=1; n<nb_pixel_segment-1; n++)
+               image[liste_pixel_segment[2*n]][liste_pixel_segment[2*n+1]] = valseg ;
+      
+      np = npp1 ;
+      npp1 = np->noeud_suiv ;
+        
+    }
+  while (np != snake) ;
+  
+  /* les deux noeuds */
+  np = snake ;
+  npp1 = snake->noeud_suiv ;
+  /*
+  do
+    {
+      i1 = np->posi ; j1 = np->posj ;
+      i2 = npp1->posi ; j2 = npp1->posj ;
+      
+      image[i1][j1] = valnoeud ;
+      image[i2][j2] = valnoeud ;
+      
+      np = npp1 ;
+      npp1 = np->noeud_suiv ;
+    }
+       while (np != snake) ;
+  */
+}
+
+/* ========== DEBUG ================= */
+/* fonction d'affichage pour le debug */
+/* affiche les deux premiers segments avec valseg-1 */
+/* et incremenent les valeurs des noeuds */
+void affiche_snake_couleur(int **image, struct snake_node *snake, int valseg, int valnoeud,
+                          uint32 *liste_pixel_segment)
+{
+  uint32 i1, j1, i2, j2 ;
+  uint32 n, nb_pixel_segment ;
+  struct snake_node *np, *npp1 ;
+  int cpt = 0;
+  snake = snake->noeud_prec ;  
+
+  /* les segments */
+  np = snake ;
+  npp1 = np->noeud_suiv ;
+  do
+    {
+      i1 = np->posi ; j1 = np->posj ;
+      i2 = npp1->posi ; j2 = npp1->posj ;
+      
+      nb_pixel_segment = calcul_liste_pixel_segment(i1,j1,i2,j2, liste_pixel_segment, 0) ;
+      if (cpt < 2 )
+       for (n=1; n<nb_pixel_segment-1; n++)
+         image[liste_pixel_segment[2*n]][liste_pixel_segment[2*n+1]] = valseg-1 ;
+      else
+       for (n=1; n<nb_pixel_segment-1; n++)
+         image[liste_pixel_segment[2*n]][liste_pixel_segment[2*n+1]] = valseg ;
+       
+      cpt++ ;
+      np = npp1 ;
+      npp1 = np->noeud_suiv ;
+    }
+  while (np != snake) ;
+  
+  /* les deux noeuds */
+  cpt = 0 ;
+  np = snake ;
+  npp1 = snake->noeud_suiv ;
+  do
+    {
+      i1 = np->posi ; j1 = np->posj ;
+      i2 = npp1->posi ; j2 = npp1->posj ;
+      
+      image[i1][j1] = valnoeud+cpt ;
+      image[i2][j2] = valnoeud+cpt++ ;
+      
+      np = npp1 ;
+      npp1 = np->noeud_suiv ;
+    }
+  while (np != snake) ;
+}
+
+/* ========= DEBUG ===================== */
+/* copie l'image du snake avec un numero */
+/* de fichier incremente a chaque appel */
+void debug_aff_snake(struct snake_node *snake)
+{
+  const int idim=256, jdim=256 ;
+
+  int **image = new_matrix_int(idim, jdim) ;
+  uint32 *liste_pixel = malloc(sizeof(int)*2*(idim+jdim)) ;
+  static int iter=0 ;
+  char output[256] ;
+  int n;
+
+  for (n=0; n<idim*jdim; n++)
+    image[0][n] = 128 ;
+
+  affiche_snake_couleur(image, snake, 255, 0, liste_pixel) ;
+  sprintf(output, "debug_im%.4d.pgm", iter++) ;
+  write_int2pgm(image, idim, idim, output, 0) ;
+
+  del_matrix_int(image, idim); 
+  free(liste_pixel);
+}
+
+
+
+
+/**
+ * \fn int ajout_noeud_snake(struct snake_node *node, int *nb_noeud)
+ * \brief ajout un noeud au snake 
+ * \author NB - PhyTI
+ *
+ * \param[in]  node adresse du noeud 
+ * \param[out] nb_noeud nombre de noeuds du snake
+ *
+ * \return le pointeur du nouveau noeud si ajout reussi, NULL sinon
+ *
+ * Ajout d'un noeud au millieu du segment.
+ * !!! Pour algo rapide, cette fonction doit etre suivie
+ * d'une mise a jour des contrib des noeuds qui conviennent !!!
+ *
+ */
+struct snake_node* ajout_noeud_snake(struct snake_node *node, uint32 *nb_noeud)
+{
+  struct snake_node *najout ;
+
+  najout = malloc(sizeof(struct snake_node)) ;
+  
+  najout->posi = node->centre_i ;
+  najout->posj = node->centre_j ; 
+  
+  najout->noeud_prec = node ;
+  najout->noeud_suiv = node->noeud_suiv ;
+  node->noeud_suiv->noeud_prec = najout ;
+  node->noeud_suiv = najout ; 
+
+  (*nb_noeud)++ ;
+  return najout ;
+}
+
+
+
+
+/**
+ * \fn inline int test_croisement_segment_large(int Ai, int Aj, int Bi, int Bj,
+ *                                int Ui, int Uj, int Vi, int Vj)
+ *
+ * \brief Test qui determine si deux segments croisent 
+ * \author NB - PhyTI
+ *
+ * \param[in] Ai 
+ * \param[in] Aj
+ * \param[in] Bi
+ * \param[in] Bj
+ * \param[in] Ui 
+ * \param[in] Uj
+ * \param[in] Vi
+ * \param[in] Vj
+ *
+ * \return  1 si croisement, 0 sinon
+ *
+ * Version large : autorise les triangles nulles
+ * Test de croisement des segments :  
+ * si deux segments AB et UV croisent, alors 
+ * les triangles ABU et ABV change d'ordre de rotation 
+ * ET 
+ * les triangles UVA et UVB change aussi d'ordre de rotation
+ *
+ */
+inline int test_croisement_segment_large(uint32 Ai, uint32 Aj, uint32 Bi, uint32 Bj,
+                                  uint32 Ui, uint32 Uj, uint32 Vi, uint32 Vj)
+{
+  if (sign_diff_strict(sinus_triangle(Ai, Aj, Bi, Bj, Ui, Uj),     // Bi-Ai, Uj-Aj, Ui-Ai, Bj-Aj
+                      sinus_triangle(Ai, Aj, Bi, Bj, Vi, Vj)))    // Bi-Ai, Vj-Aj, Vi-Ai, Bj-Aj
+    if (sign_diff_strict(sinus_triangle(Ui, Uj, Vi, Vj, Ai, Aj),   // Vi-Ui, Aj-Uj, Ai-Ui, Vj-Uj
+                        sinus_triangle(Ui, Uj, Vi, Vj, Bi, Bj)))  // Vi-Ui, Bj-Uj, Bi-Ui, Vj-Uj
+       return 1 ;
+  return 0 ;
+}
+
+
+/**
+ * \fn inline int test_croisement_segment_strict(int Ai, int Aj, int Bi, int Bj,
+ *                                int Ui, int Uj, int Vi, int Vj)
+ *
+ * \brief Test qui determine si deux segments croisent 
+ * \author NB - PhyTI
+ *
+ * \param[in] Ai 
+ * \param[in] Aj
+ * \param[in] Bi
+ * \param[in] Bj
+ * \param[in] Ui 
+ * \param[in] Uj
+ * \param[in] Vi
+ * \param[in] Vj
+ *
+ * \return  1 si croisement, 0 sinon
+ *
+ * Version strict : n'autorise pas les triangles nulles
+ * Test de croisement des segments :  
+ * si deux segments AB et UV croisent, alors 
+ * les triangles ABU et ABV change d'ordre de rotation 
+ * ET 
+ * les triangles UVA et UVB change aussi d'ordre de rotation
+ *
+ */
+inline int test_croisement_segment_strict(uint32 Ai, uint32 Aj, uint32 Bi, uint32 Bj,
+                                  uint32 Ui, uint32 Uj, uint32 Vi, uint32 Vj)
+{
+  if (sign_diff_ou_egal_zero(sinus_triangle(Ai, Aj, Bi, Bj, Ui, Uj),
+                            sinus_triangle(Ai, Aj, Bi, Bj, Vi, Vj)))  
+    if (sign_diff_ou_egal_zero(sinus_triangle(Ui, Uj, Vi, Vj, Ai, Aj),
+                              sinus_triangle(Ui, Uj, Vi, Vj, Bi, Bj)))
+      return 1 ;
+  return 0 ;
+}
+
+
+
+
+
+/**
+ * \fn int test_croisement_add_noeud_large(struct snake_node *N, int Nxi, int Nxj, int seg)
+ *
+ * \brief test si il y a croisement de segments lors de l'ajout d'un noeud 
+ * \author NB - PhyTI
+ *
+ * \param[in] N le noeud ou l'on veut ajouter un noeud Nx au milieu de son segment
+ * \param[in] Nxi coordonnee i du nouveau node Nx
+ * \param[in] Nxj coordonnee j du nouveau node Nx
+ * \param[in] seg booleen pour definir quel segment on test:
+ *             Nx --> Nsuiv si seg==1
+ *             N --> Nx si seg==0 
+ *
+ * \return 1 si croisement, 0 sinon
+ *
+ * Version large : autorise les triangles nulles
+ *
+ */
+int test_croisement_add_noeud_large(struct snake_node *N, uint32 Nxi, uint32 Nxj, int seg)
+{
+  uint32 Nrefi=0, Nrefj=0 ; /* reference avec Nxi et Nxj */
+  uint32 posi, posj, suivi, suivj ; /* segment courant de test */
+  struct snake_node *node, *end ;
+
+  if (seg==1)
+    {
+      Nrefi = N->noeud_suiv->posi ;
+      Nrefj = N->noeud_suiv->posj ;
+    }
+  else
+    {
+      Nrefi = N->posi ;
+      Nrefj = N->posj ;
+    }
+
+  node = N->noeud_suiv ;
+  suivi = node->posi ;
+  suivj = node->posj ;
+
+  end = N ;
+  while (node != end) 
+  {
+    posi = suivi ;
+    posj = suivj ;
+    node = node->noeud_suiv ;
+    suivi = node->posi ;
+    suivj = node->posj ;
+    if (test_croisement_segment_large(Nxi,Nxj,Nrefi,Nrefj, posi,posj,suivi,suivj))
+      return 1 ;
+  }
+  return 0 ;
+}
+
+
+
+/**
+ * \fn int test_croisement_add_noeud_strict(struct snake_node *N, int Nxi, int Nxj, int seg)
+ *
+ * \brief test si il y a croisement de segments lors de l'ajout d'un noeud 
+ * \author NB - PhyTI
+ *
+ * \param[in] N le noeud ou l'on veut ajouter un noeud Nx au milieu de son segment
+ * \param[in] Nxi coordonnee i du nouveau node Nx
+ * \param[in] Nxj coordonnee j du nouveau node Nx
+ * \param[in] seg booleen pour definir quel segment on test:
+ *             Nx --> Nsuiv si seg==1
+ *             N --> Nx si seg==0 
+ *
+ * \return 1 si croisement, 0 sinon
+ *
+ * Version strict : n'autorise pas les triangles nulles
+ *
+ */
+int test_croisement_add_noeud_strict(struct snake_node *N, uint32 Nxi, uint32 Nxj, int seg)
+{
+  uint32 Nrefi=0, Nrefj=0 ; /* reference avec Nxi et Nxj */
+  uint32 posi, posj, suivi, suivj ; /* segment courant de test */
+  struct snake_node *node, *end ;
+
+  /* segment de reference */
+  if (seg)
+    {
+      Nrefi = N->noeud_suiv->posi ;
+      Nrefj = N->noeud_suiv->posj ;
+    }
+  else
+    {
+      Nrefi = N->posi ;
+      Nrefj = N->posj ;
+    }
+
+  /* segments de tests */
+  node = N->noeud_suiv ;
+  suivi = node->posi ;
+  suivj = node->posj ;
+  if (seg) 
+    {
+      /* premier segment : il touche le segment de ref */
+      /* pour Nx --> Nsuiv(ref) */
+      posi = suivi ;
+      posj = suivj ;
+      node = node->noeud_suiv ;
+      suivi = node->posi ;
+      suivj = node->posj ;
+      if (test_croisement_segment_large(Nxi,Nxj,Nrefi,Nrefj,posi,posj,suivi,suivj))
+       return 1 ;     
+      end = N ; /* pour boucle while */
+   }
+  else     
+    /* pour N --> Nx */ 
+    end = N->noeud_prec ; /* pour boucle while */
+
+  /* boucle sur les segments */
+  while (node != end) 
+  {
+    posi = suivi ;
+    posj = suivj ;
+    node = node->noeud_suiv ;
+    suivi = node->posi ;
+    suivj = node->posj ;
+    if (test_croisement_segment_strict(posi,posj,suivi,suivj,Nxi,Nxj,Nrefi,Nrefj))
+      return 1 ;
+  }
+
+  /* dernier segment */
+  /* cas N --> Nx */
+  if (!seg)
+    {
+      posi = suivi ;
+      posj = suivj ;
+      node = node->noeud_suiv ;
+      suivi = node->posi ;
+      suivj = node->posj ;  
+      if (test_croisement_segment_large(Nxi,Nxj,Nrefi,Nrefj, posi,posj,suivi,suivj))
+       return 1 ;
+    }
+  return 0 ;
+}
+
+
+
+
+
+
+/**
+ * \fn int test_croisement_move_seg_large(struct snake_node *Nx, int Nxi, int Nxj, int seg)
+ *
+ * \brief test si il y a croisement de segments lors du deplacement d'un noeud 
+ * \author NB - PhyTI
+ *
+ * \param[in] Nx le noeud que l'on veut deplacer
+ * \param[in] Nxi coordonnee i du nouveau node Nx
+ * \param[in] Nxj coordonnee j du nouveau node Nx
+ * \param[in] seg booleen pour definir quel segment on test:
+ *             Nx --> Nsuiv si seg==1
+ *             Nprec --> Nx si seg==0 
+ *
+ * \return 1 si croisement, 0 sinon
+ *
+ * Version large : autorise les triangles nulles
+ * Version non optimisee car elle test systematiquement tout les segments du snake !
+ *
+ */
+int test_croisement_move_seg_large(struct snake_node *Nx, uint32 Nxi, uint32 Nxj, int seg)
+{
+  uint32 Nrefi=0, Nrefj=0 ; /* reference avec Nxi et Nxj */
+  uint32 posi, posj, suivi, suivj ; /* segment courant de test */
+  struct snake_node *node, *end ;
+
+  if (seg==1)
+    {
+      Nrefi = Nx->noeud_suiv->posi ;
+      Nrefj = Nx->noeud_suiv->posj ;
+    }
+  else
+    {
+      Nrefi = Nx->noeud_prec->posi ;
+      Nrefj = Nx->noeud_prec->posj ;
+    }
+
+  node = Nx->noeud_suiv ;
+  suivi = node->posi ;
+  suivj = node->posj ;
+
+  end = Nx->noeud_prec ;
+  while (node != end) 
+  {
+    posi = suivi ;
+    posj = suivj ;
+    node = node->noeud_suiv ;
+    suivi = node->posi ;
+    suivj = node->posj ;
+    if (test_croisement_segment_large(Nxi,Nxj,Nrefi,Nrefj, posi,posj,suivi,suivj))
+      return 1 ;
+  }
+  return 0 ;
+}
+
+
+
+/**
+ * \fn int test_croisement_move_seg_strict(struct snake_node *Nx, int Nxi, int Nxj, int seg)
+ *
+ * \brief test si il y a croisement de segments lors du deplacement d'un noeud 
+ * \author NB - PhyTI
+ *
+ * \param[in] Nx le noeud que l'on veut deplacer
+ * \param[in] Nxi coordonnee i du nouveau node Nx
+ * \param[in] Nxj coordonnee j du nouveau node Nx
+ * \param[in] seg booleen pour definir quel segment on test:
+ *             Nx --> Nsuiv si seg==1
+ *             Nprec --> Nx si seg==0 
+ *
+ * \return 1 si croisement, 0 sinon
+ *
+ * Version strict : n'autorise pas les triangles nulles
+ * Version non optimisee car elle test systematiquement tout les segments du snake !
+ */
+int test_croisement_move_seg_strict(struct snake_node *Nx, uint32 Nxi, uint32 Nxj, int seg)
+{
+  uint32 Nrefi=0, Nrefj=0 ; /* reference avec Nxi et Nxj */
+  uint32 posi, posj, suivi, suivj ; /* segment courant de test */
+  struct snake_node *node, *end ;
+
+  /* segment de reference */
+  if (seg)
+    {
+      Nrefi = Nx->noeud_suiv->posi ;
+      Nrefj = Nx->noeud_suiv->posj ;
+    }
+  else
+    {
+      Nrefi = Nx->noeud_prec->posi ;
+      Nrefj = Nx->noeud_prec->posj ;
+    }
+
+  /* segments de tests */
+  node = Nx->noeud_suiv ;
+  suivi = node->posi ;
+  suivj = node->posj ;
+  if (seg) 
+    {
+      /* premier segment : il touche le segment de ref */
+      /* pour Nx --> Nsuiv(ref) */
+      posi = suivi ;
+      posj = suivj ;
+      node = node->noeud_suiv ;
+      suivi = node->posi ;
+      suivj = node->posj ;
+      if (test_croisement_segment_large(Nxi,Nxj,Nrefi,Nrefj,posi,posj,suivi,suivj))
+       return 1 ;
+      
+      end = Nx->noeud_prec ; /* pour boucle while */
+   }
+  else     
+    /* pour Nprec --> Nx */ 
+    end = Nx->noeud_prec->noeud_prec ; /* pour boucle while */
+
+  /* boucle sur les segments */
+  while (node != end) 
+  {
+    posi = suivi ;
+    posj = suivj ;
+    node = node->noeud_suiv ;
+    suivi = node->posi ;
+    suivj = node->posj ;
+    if (test_croisement_segment_strict(posi,posj,suivi,suivj,Nxi,Nxj,Nrefi,Nrefj))
+      return 1 ;
+  }
+
+  /* dernier segment */
+  /* cas Nprec --> Nx */
+  if (!seg)
+    {
+      posi = suivi ;
+      posj = suivj ;
+      node = node->noeud_suiv ;
+      suivi = node->posi ;
+      suivj = node->posj ;  
+      if (test_croisement_segment_large(Nxi,Nxj,Nrefi,Nrefj, posi,posj,suivi,suivj))
+       return 1 ;
+    }
+  return 0 ;
+}
+
diff --git a/src/lib_snake_common.c~ b/src/lib_snake_common.c~
new file mode 100644 (file)
index 0000000..ed1bfc8
--- /dev/null
@@ -0,0 +1,718 @@
+/**
+ * \file lib_snake_common.c
+ * \brief routines de bases pour la gestion du snake
+ * \author NB - PhyTI 
+ * \version x.x
+ * \date 25 decembre 2009
+ *
+ */
+
+#include <malloc.h>
+
+#include "lib_snake_common.h"
+#include "lib_contour.h" 
+#include "lib_math.h"
+
+
+/* debug */
+#include <stdio.h>
+#include "lib_images.h"
+#include "lib_alloc.h"
+
+
+/**
+ * \fn struct snake_node* genere_snake_rectangle_bords(int *nb_noeud, int distance_bords,
+ *                         int i_dim, int j_dim)
+ *
+ * \brief Initialise un snake rectangulaire par rapport au bords de l'image
+ * \author NB - PhyTI
+ *
+ * \param[out] nb_noeud renvoie le nombre de node du snake 
+ * \param[in]  distance_bords distance du rectangle par rapport au bords 
+ * \param[in]  i_dim dimension verticale de l'image
+ * \param[in]  j_dim dimension horizontale de l'image
+ *
+ * \return le pointeur du premier noeud du snake
+ *
+ * note : les calculs sse necessite l'alignement memoire des snake_node
+ */
+struct snake_node* genere_snake_rectangle_bords(uint32 *nb_noeud, uint32 distance_bords, 
+                                               uint32 i_dim, uint32 j_dim)
+{
+  struct snake_node *n1, *n2, *n3 ; /* noeuds courant */
+  struct snake_node *n0 = malloc(sizeof(struct snake_node)) ;
+
+  /* n0 */
+  *nb_noeud = 1 ;
+  n0->posi = distance_bords ;
+  n0->posj = distance_bords ;
+  n0->noeud_suiv = malloc(sizeof(struct snake_node)) ;
+  (*nb_noeud)++ ;
+  /* n1 */
+  n1 = n0->noeud_suiv ;
+  n1->posi = i_dim - distance_bords ;
+  n1->posj = distance_bords ; 
+  n1->noeud_prec = n0 ; 
+  n1->noeud_suiv = malloc(sizeof(struct snake_node)) ;
+  (*nb_noeud)++ ;
+  /* n2 */
+  n2 = n1->noeud_suiv ;
+  n2->posi = i_dim - distance_bords ;
+  n2->posj = j_dim - distance_bords ; 
+  n2->noeud_prec = n1 ; 
+  n2->noeud_suiv = malloc(sizeof(struct snake_node)) ;
+  (*nb_noeud)++ ;
+  /* n3 */
+  n3 = n2->noeud_suiv ;
+  n3->posi = distance_bords ;
+  n3->posj = j_dim - distance_bords ; 
+  n3->noeud_prec = n2 ; 
+  n3->noeud_suiv = n0 ;  /* on ferme le snake */
+  /* n0, on ferme le snake */
+  n0->noeud_prec = n3 ; 
+  
+  return n0 ;
+}
+
+/**
+ * \fn struct snake_node* genere_snake_rectangle(int *nb_noeud,int i1,int j1,int i2,int j2, 
+ *                         int i_dim, int j_dim)
+ *
+ * \brief Initialise un snake rectangulaire definie par deux noeuds
+ * \author NB - PhyTI
+ *
+ * \param[out] nb_noeud renvoie le nombre de node du snake 
+ * \param[in]  i1 coordonnee du coin haut-gauche
+ * \param[in]  j1 coordonnee du coin haut-gauche
+ * \param[in]  i2 coordonnee du coin bas-droit
+ * \param[in]  j2 coordonnee du coin bas-droit 
+ * \param[in]  i_dim dimension verticale de l'image
+ * \param[in]  j_dim dimension horizontale de l'image
+ *
+ * \return le pointeur du premier noeud du snake
+ *
+ * note : les calculs sse necessite l'alignement memoire des snake_node
+ */
+struct snake_node* genere_snake_rectangle(int *nb_noeud, uint32 i1, uint32 j1, uint32 i2, uint32 j2, 
+                                         uint32 i_dim, uint32 j_dim)
+{
+  struct snake_node *n1, *n2, *n3 ; /* noeuds courant */
+  struct snake_node *n0 = malloc(sizeof(struct snake_node)) ;
+
+  /* n0 */
+  *nb_noeud = 1 ;
+  n0->posi = i1 ;
+  n0->posj = j1 ;
+  n0->noeud_suiv = malloc(sizeof(struct snake_node)) ;
+  (*nb_noeud)++ ;
+  /* n1 */
+  n1 = n0->noeud_suiv ;
+  n1->posi = i2 ;
+  n1->posj = j1 ; 
+  n1->noeud_prec = n0 ; 
+  n1->noeud_suiv = malloc(sizeof(struct snake_node)) ;
+  (*nb_noeud)++ ;
+  /* n2 */
+  n2 = n1->noeud_suiv ;
+  n2->posi = i2 ;
+  n2->posj = j2 ; 
+  n2->noeud_prec = n1 ; 
+  n2->noeud_suiv = malloc(sizeof(struct snake_node)) ;
+  (*nb_noeud)++ ;
+  /* n3 */
+  n3 = n2->noeud_suiv ;
+  n3->posi = i1 ;
+  n3->posj = j2 ; 
+  n3->noeud_prec = n2 ; 
+  n3->noeud_suiv = n0 ;  /* on ferme le snake */
+  /* n0, on ferme le snake */
+  n0->noeud_prec = n3 ; 
+
+  return n0 ;
+}
+
+
+
+
+
+
+/**
+ * \fn int affiche_snake(int **image, struct snake_node *snake, 
+ *                       int valseg, int valnoeud, int *liste_pixel_segment)
+ *
+ * \brief Affiche le snake sur une image N&B 
+ * \author NB - PhyTI
+ *
+ * \param[out] image image ou le snake doit etre affiche 
+ * \param[in]  snake premier noeud du snake 
+ * \param[in]  valseg valeur de niveau de gris des segments
+ * \param[in]  valnoeud valeur de niveau de gris des noeuds
+ * \param[out] liste_pixel_segment pour caluls temporaire
+ *
+ * \return nb_noeud le nombre de noeuds du snake
+ *
+ */
+void affiche_snake(int **image, struct snake_node *snake, int valseg, int valnoeud,
+                 uint32 *liste_pixel_segment)
+{
+  uint32 i1, j1, i2, j2 ;
+  uint32 n, nb_pixel_segment ;
+  struct snake_node *np, *npp1 ;
+  
+  /* les segments */
+  np = snake ;
+  npp1 = snake->noeud_suiv ;
+  do
+    {
+      i1 = np->posi ; j1 = np->posj ;
+      i2 = npp1->posi ; j2 = npp1->posj ;
+      
+      nb_pixel_segment = calcul_liste_pixel_segment(i1,j1,i2,j2, liste_pixel_segment, 0) ;
+      for (n=1; n<nb_pixel_segment-1; n++)
+       image[liste_pixel_segment[2*n]][liste_pixel_segment[2*n+1]] = valseg ;
+      
+      np = npp1 ;
+      npp1 = np->noeud_suiv ;
+    }
+  while (np != snake) ;
+  
+  /* les deux noeuds */
+  np = snake ;
+  npp1 = snake->noeud_suiv ;
+  do
+    {
+      i1 = np->posi ; j1 = np->posj ;
+      i2 = npp1->posi ; j2 = npp1->posj ;
+      
+      image[i1][j1] = valnoeud ;
+      image[i2][j2] = valnoeud ;
+      
+      np = npp1 ;
+      npp1 = np->noeud_suiv ;
+    }
+  while (np != snake) ;
+}
+
+void affiche_snake_ushort(unsigned short **image, struct snake_node *snake, int valseg, unsigned short valnoeud,
+                                                 uint32 *liste_pixel_segment)
+{
+  uint32 i1, j1, i2, j2 ;
+  uint32 n, nb_pixel_segment ;
+  struct snake_node *np, *npp1 ;
+  
+  /* les segments */
+  np = snake ;
+  npp1 = snake->noeud_suiv ;
+  do
+    {
+      i1 = np->posi ; j1 = np->posj ;
+      i2 = npp1->posi ; j2 = npp1->posj ;
+      
+      nb_pixel_segment = calcul_liste_pixel_segment(i1,j1,i2,j2, liste_pixel_segment, 0) ;
+      for (n=1; n<nb_pixel_segment-1; n++)
+               image[liste_pixel_segment[2*n]][liste_pixel_segment[2*n+1]] = valseg ;
+      
+      np = npp1 ;
+      npp1 = np->noeud_suiv ;
+    }
+  while (np != snake) ;
+  
+  /* les deux noeuds */
+  np = snake ;
+  npp1 = snake->noeud_suiv ;
+  do
+    {
+      i1 = np->posi ; j1 = np->posj ;
+      i2 = npp1->posi ; j2 = npp1->posj ;
+      
+      image[i1][j1] = valnoeud ;
+      image[i2][j2] = valnoeud ;
+      
+      np = npp1 ;
+      npp1 = np->noeud_suiv ;
+    }
+  while (np != snake) ;
+}
+
+/* ========== DEBUG ================= */
+/* fonction d'affichage pour le debug */
+/* affiche les deux premiers segments avec valseg-1 */
+/* et incremenent les valeurs des noeuds */
+void affiche_snake_couleur(int **image, struct snake_node *snake, int valseg, int valnoeud,
+                          uint32 *liste_pixel_segment)
+{
+  uint32 i1, j1, i2, j2 ;
+  uint32 n, nb_pixel_segment ;
+  struct snake_node *np, *npp1 ;
+  int cpt = 0;
+  snake = snake->noeud_prec ;  
+
+  /* les segments */
+  np = snake ;
+  npp1 = np->noeud_suiv ;
+  do
+    {
+      i1 = np->posi ; j1 = np->posj ;
+      i2 = npp1->posi ; j2 = npp1->posj ;
+      
+      nb_pixel_segment = calcul_liste_pixel_segment(i1,j1,i2,j2, liste_pixel_segment, 0) ;
+      if (cpt < 2 )
+       for (n=1; n<nb_pixel_segment-1; n++)
+         image[liste_pixel_segment[2*n]][liste_pixel_segment[2*n+1]] = valseg-1 ;
+      else
+       for (n=1; n<nb_pixel_segment-1; n++)
+         image[liste_pixel_segment[2*n]][liste_pixel_segment[2*n+1]] = valseg ;
+       
+      cpt++ ;
+      np = npp1 ;
+      npp1 = np->noeud_suiv ;
+    }
+  while (np != snake) ;
+  
+  /* les deux noeuds */
+  cpt = 0 ;
+  np = snake ;
+  npp1 = snake->noeud_suiv ;
+  do
+    {
+      i1 = np->posi ; j1 = np->posj ;
+      i2 = npp1->posi ; j2 = npp1->posj ;
+      
+      image[i1][j1] = valnoeud+cpt ;
+      image[i2][j2] = valnoeud+cpt++ ;
+      
+      np = npp1 ;
+      npp1 = np->noeud_suiv ;
+    }
+  while (np != snake) ;
+}
+
+/* ========= DEBUG ===================== */
+/* copie l'image du snake avec un numero */
+/* de fichier incremente a chaque appel */
+void debug_aff_snake(struct snake_node *snake)
+{
+  const int idim=256, jdim=256 ;
+
+  int **image = new_matrix_int(idim, jdim) ;
+  uint32 *liste_pixel = malloc(sizeof(int)*2*(idim+jdim)) ;
+  static int iter=0 ;
+  char output[256] ;
+  int n;
+
+  for (n=0; n<idim*jdim; n++)
+    image[0][n] = 128 ;
+
+  affiche_snake_couleur(image, snake, 255, 0, liste_pixel) ;
+  sprintf(output, "debug_im%.4d.pgm", iter++) ;
+  write_int2pgm(image, idim, idim, output, 0) ;
+
+  del_matrix_int(image, idim); 
+  free(liste_pixel);
+}
+
+
+
+
+/**
+ * \fn int ajout_noeud_snake(struct snake_node *node, int *nb_noeud)
+ * \brief ajout un noeud au snake 
+ * \author NB - PhyTI
+ *
+ * \param[in]  node adresse du noeud 
+ * \param[out] nb_noeud nombre de noeuds du snake
+ *
+ * \return le pointeur du nouveau noeud si ajout reussi, NULL sinon
+ *
+ * Ajout d'un noeud au millieu du segment.
+ * !!! Pour algo rapide, cette fonction doit etre suivie
+ * d'une mise a jour des contrib des noeuds qui conviennent !!!
+ *
+ */
+struct snake_node* ajout_noeud_snake(struct snake_node *node, uint32 *nb_noeud)
+{
+  struct snake_node *najout ;
+
+  najout = malloc(sizeof(struct snake_node)) ;
+  
+  najout->posi = node->centre_i ;
+  najout->posj = node->centre_j ; 
+  
+  najout->noeud_prec = node ;
+  najout->noeud_suiv = node->noeud_suiv ;
+  node->noeud_suiv->noeud_prec = najout ;
+  node->noeud_suiv = najout ; 
+
+  (*nb_noeud)++ ;
+  return najout ;
+}
+
+
+
+
+/**
+ * \fn inline int test_croisement_segment_large(int Ai, int Aj, int Bi, int Bj,
+ *                                int Ui, int Uj, int Vi, int Vj)
+ *
+ * \brief Test qui determine si deux segments croisent 
+ * \author NB - PhyTI
+ *
+ * \param[in] Ai 
+ * \param[in] Aj
+ * \param[in] Bi
+ * \param[in] Bj
+ * \param[in] Ui 
+ * \param[in] Uj
+ * \param[in] Vi
+ * \param[in] Vj
+ *
+ * \return  1 si croisement, 0 sinon
+ *
+ * Version large : autorise les triangles nulles
+ * Test de croisement des segments :  
+ * si deux segments AB et UV croisent, alors 
+ * les triangles ABU et ABV change d'ordre de rotation 
+ * ET 
+ * les triangles UVA et UVB change aussi d'ordre de rotation
+ *
+ */
+inline int test_croisement_segment_large(uint32 Ai, uint32 Aj, uint32 Bi, uint32 Bj,
+                                  uint32 Ui, uint32 Uj, uint32 Vi, uint32 Vj)
+{
+  if (sign_diff_strict(sinus_triangle(Ai, Aj, Bi, Bj, Ui, Uj),     // Bi-Ai, Uj-Aj, Ui-Ai, Bj-Aj
+                      sinus_triangle(Ai, Aj, Bi, Bj, Vi, Vj)))    // Bi-Ai, Vj-Aj, Vi-Ai, Bj-Aj
+    if (sign_diff_strict(sinus_triangle(Ui, Uj, Vi, Vj, Ai, Aj),   // Vi-Ui, Aj-Uj, Ai-Ui, Vj-Uj
+                        sinus_triangle(Ui, Uj, Vi, Vj, Bi, Bj)))  // Vi-Ui, Bj-Uj, Bi-Ui, Vj-Uj
+       return 1 ;
+  return 0 ;
+}
+
+
+/**
+ * \fn inline int test_croisement_segment_strict(int Ai, int Aj, int Bi, int Bj,
+ *                                int Ui, int Uj, int Vi, int Vj)
+ *
+ * \brief Test qui determine si deux segments croisent 
+ * \author NB - PhyTI
+ *
+ * \param[in] Ai 
+ * \param[in] Aj
+ * \param[in] Bi
+ * \param[in] Bj
+ * \param[in] Ui 
+ * \param[in] Uj
+ * \param[in] Vi
+ * \param[in] Vj
+ *
+ * \return  1 si croisement, 0 sinon
+ *
+ * Version strict : n'autorise pas les triangles nulles
+ * Test de croisement des segments :  
+ * si deux segments AB et UV croisent, alors 
+ * les triangles ABU et ABV change d'ordre de rotation 
+ * ET 
+ * les triangles UVA et UVB change aussi d'ordre de rotation
+ *
+ */
+inline int test_croisement_segment_strict(uint32 Ai, uint32 Aj, uint32 Bi, uint32 Bj,
+                                  uint32 Ui, uint32 Uj, uint32 Vi, uint32 Vj)
+{
+  if (sign_diff_ou_egal_zero(sinus_triangle(Ai, Aj, Bi, Bj, Ui, Uj),
+                            sinus_triangle(Ai, Aj, Bi, Bj, Vi, Vj)))  
+    if (sign_diff_ou_egal_zero(sinus_triangle(Ui, Uj, Vi, Vj, Ai, Aj),
+                              sinus_triangle(Ui, Uj, Vi, Vj, Bi, Bj)))
+      return 1 ;
+  return 0 ;
+}
+
+
+
+
+
+/**
+ * \fn int test_croisement_add_noeud_large(struct snake_node *N, int Nxi, int Nxj, int seg)
+ *
+ * \brief test si il y a croisement de segments lors de l'ajout d'un noeud 
+ * \author NB - PhyTI
+ *
+ * \param[in] N le noeud ou l'on veut ajouter un noeud Nx au milieu de son segment
+ * \param[in] Nxi coordonnee i du nouveau node Nx
+ * \param[in] Nxj coordonnee j du nouveau node Nx
+ * \param[in] seg booleen pour definir quel segment on test:
+ *             Nx --> Nsuiv si seg==1
+ *             N --> Nx si seg==0 
+ *
+ * \return 1 si croisement, 0 sinon
+ *
+ * Version large : autorise les triangles nulles
+ *
+ */
+int test_croisement_add_noeud_large(struct snake_node *N, uint32 Nxi, uint32 Nxj, int seg)
+{
+  uint32 Nrefi=0, Nrefj=0 ; /* reference avec Nxi et Nxj */
+  uint32 posi, posj, suivi, suivj ; /* segment courant de test */
+  struct snake_node *node, *end ;
+
+  if (seg==1)
+    {
+      Nrefi = N->noeud_suiv->posi ;
+      Nrefj = N->noeud_suiv->posj ;
+    }
+  else
+    {
+      Nrefi = N->posi ;
+      Nrefj = N->posj ;
+    }
+
+  node = N->noeud_suiv ;
+  suivi = node->posi ;
+  suivj = node->posj ;
+
+  end = N ;
+  while (node != end) 
+  {
+    posi = suivi ;
+    posj = suivj ;
+    node = node->noeud_suiv ;
+    suivi = node->posi ;
+    suivj = node->posj ;
+    if (test_croisement_segment_large(Nxi,Nxj,Nrefi,Nrefj, posi,posj,suivi,suivj))
+      return 1 ;
+  }
+  return 0 ;
+}
+
+
+
+/**
+ * \fn int test_croisement_add_noeud_strict(struct snake_node *N, int Nxi, int Nxj, int seg)
+ *
+ * \brief test si il y a croisement de segments lors de l'ajout d'un noeud 
+ * \author NB - PhyTI
+ *
+ * \param[in] N le noeud ou l'on veut ajouter un noeud Nx au milieu de son segment
+ * \param[in] Nxi coordonnee i du nouveau node Nx
+ * \param[in] Nxj coordonnee j du nouveau node Nx
+ * \param[in] seg booleen pour definir quel segment on test:
+ *             Nx --> Nsuiv si seg==1
+ *             N --> Nx si seg==0 
+ *
+ * \return 1 si croisement, 0 sinon
+ *
+ * Version strict : n'autorise pas les triangles nulles
+ *
+ */
+int test_croisement_add_noeud_strict(struct snake_node *N, uint32 Nxi, uint32 Nxj, int seg)
+{
+  uint32 Nrefi=0, Nrefj=0 ; /* reference avec Nxi et Nxj */
+  uint32 posi, posj, suivi, suivj ; /* segment courant de test */
+  struct snake_node *node, *end ;
+
+  /* segment de reference */
+  if (seg)
+    {
+      Nrefi = N->noeud_suiv->posi ;
+      Nrefj = N->noeud_suiv->posj ;
+    }
+  else
+    {
+      Nrefi = N->posi ;
+      Nrefj = N->posj ;
+    }
+
+  /* segments de tests */
+  node = N->noeud_suiv ;
+  suivi = node->posi ;
+  suivj = node->posj ;
+  if (seg) 
+    {
+      /* premier segment : il touche le segment de ref */
+      /* pour Nx --> Nsuiv(ref) */
+      posi = suivi ;
+      posj = suivj ;
+      node = node->noeud_suiv ;
+      suivi = node->posi ;
+      suivj = node->posj ;
+      if (test_croisement_segment_large(Nxi,Nxj,Nrefi,Nrefj,posi,posj,suivi,suivj))
+       return 1 ;     
+      end = N ; /* pour boucle while */
+   }
+  else     
+    /* pour N --> Nx */ 
+    end = N->noeud_prec ; /* pour boucle while */
+
+  /* boucle sur les segments */
+  while (node != end) 
+  {
+    posi = suivi ;
+    posj = suivj ;
+    node = node->noeud_suiv ;
+    suivi = node->posi ;
+    suivj = node->posj ;
+    if (test_croisement_segment_strict(posi,posj,suivi,suivj,Nxi,Nxj,Nrefi,Nrefj))
+      return 1 ;
+  }
+
+  /* dernier segment */
+  /* cas N --> Nx */
+  if (!seg)
+    {
+      posi = suivi ;
+      posj = suivj ;
+      node = node->noeud_suiv ;
+      suivi = node->posi ;
+      suivj = node->posj ;  
+      if (test_croisement_segment_large(Nxi,Nxj,Nrefi,Nrefj, posi,posj,suivi,suivj))
+       return 1 ;
+    }
+  return 0 ;
+}
+
+
+
+
+
+
+/**
+ * \fn int test_croisement_move_seg_large(struct snake_node *Nx, int Nxi, int Nxj, int seg)
+ *
+ * \brief test si il y a croisement de segments lors du deplacement d'un noeud 
+ * \author NB - PhyTI
+ *
+ * \param[in] Nx le noeud que l'on veut deplacer
+ * \param[in] Nxi coordonnee i du nouveau node Nx
+ * \param[in] Nxj coordonnee j du nouveau node Nx
+ * \param[in] seg booleen pour definir quel segment on test:
+ *             Nx --> Nsuiv si seg==1
+ *             Nprec --> Nx si seg==0 
+ *
+ * \return 1 si croisement, 0 sinon
+ *
+ * Version large : autorise les triangles nulles
+ * Version non optimisee car elle test systematiquement tout les segments du snake !
+ *
+ */
+int test_croisement_move_seg_large(struct snake_node *Nx, uint32 Nxi, uint32 Nxj, int seg)
+{
+  uint32 Nrefi=0, Nrefj=0 ; /* reference avec Nxi et Nxj */
+  uint32 posi, posj, suivi, suivj ; /* segment courant de test */
+  struct snake_node *node, *end ;
+
+  if (seg==1)
+    {
+      Nrefi = Nx->noeud_suiv->posi ;
+      Nrefj = Nx->noeud_suiv->posj ;
+    }
+  else
+    {
+      Nrefi = Nx->noeud_prec->posi ;
+      Nrefj = Nx->noeud_prec->posj ;
+    }
+
+  node = Nx->noeud_suiv ;
+  suivi = node->posi ;
+  suivj = node->posj ;
+
+  end = Nx->noeud_prec ;
+  while (node != end) 
+  {
+    posi = suivi ;
+    posj = suivj ;
+    node = node->noeud_suiv ;
+    suivi = node->posi ;
+    suivj = node->posj ;
+    if (test_croisement_segment_large(Nxi,Nxj,Nrefi,Nrefj, posi,posj,suivi,suivj))
+      return 1 ;
+  }
+  return 0 ;
+}
+
+
+
+/**
+ * \fn int test_croisement_move_seg_strict(struct snake_node *Nx, int Nxi, int Nxj, int seg)
+ *
+ * \brief test si il y a croisement de segments lors du deplacement d'un noeud 
+ * \author NB - PhyTI
+ *
+ * \param[in] Nx le noeud que l'on veut deplacer
+ * \param[in] Nxi coordonnee i du nouveau node Nx
+ * \param[in] Nxj coordonnee j du nouveau node Nx
+ * \param[in] seg booleen pour definir quel segment on test:
+ *             Nx --> Nsuiv si seg==1
+ *             Nprec --> Nx si seg==0 
+ *
+ * \return 1 si croisement, 0 sinon
+ *
+ * Version strict : n'autorise pas les triangles nulles
+ * Version non optimisee car elle test systematiquement tout les segments du snake !
+ */
+int test_croisement_move_seg_strict(struct snake_node *Nx, uint32 Nxi, uint32 Nxj, int seg)
+{
+  uint32 Nrefi=0, Nrefj=0 ; /* reference avec Nxi et Nxj */
+  uint32 posi, posj, suivi, suivj ; /* segment courant de test */
+  struct snake_node *node, *end ;
+
+  /* segment de reference */
+  if (seg)
+    {
+      Nrefi = Nx->noeud_suiv->posi ;
+      Nrefj = Nx->noeud_suiv->posj ;
+    }
+  else
+    {
+      Nrefi = Nx->noeud_prec->posi ;
+      Nrefj = Nx->noeud_prec->posj ;
+    }
+
+  /* segments de tests */
+  node = Nx->noeud_suiv ;
+  suivi = node->posi ;
+  suivj = node->posj ;
+  if (seg) 
+    {
+      /* premier segment : il touche le segment de ref */
+      /* pour Nx --> Nsuiv(ref) */
+      posi = suivi ;
+      posj = suivj ;
+      node = node->noeud_suiv ;
+      suivi = node->posi ;
+      suivj = node->posj ;
+      if (test_croisement_segment_large(Nxi,Nxj,Nrefi,Nrefj,posi,posj,suivi,suivj))
+       return 1 ;
+      
+      end = Nx->noeud_prec ; /* pour boucle while */
+   }
+  else     
+    /* pour Nprec --> Nx */ 
+    end = Nx->noeud_prec->noeud_prec ; /* pour boucle while */
+
+  /* boucle sur les segments */
+  while (node != end) 
+  {
+    posi = suivi ;
+    posj = suivj ;
+    node = node->noeud_suiv ;
+    suivi = node->posi ;
+    suivj = node->posj ;
+    if (test_croisement_segment_strict(posi,posj,suivi,suivj,Nxi,Nxj,Nrefi,Nrefj))
+      return 1 ;
+  }
+
+  /* dernier segment */
+  /* cas Nprec --> Nx */
+  if (!seg)
+    {
+      posi = suivi ;
+      posj = suivj ;
+      node = node->noeud_suiv ;
+      suivi = node->posi ;
+      suivj = node->posj ;  
+      if (test_croisement_segment_large(Nxi,Nxj,Nrefi,Nrefj, posi,posj,suivi,suivj))
+       return 1 ;
+    }
+  return 0 ;
+}
+
diff --git a/src/lib_snake_common.h b/src/lib_snake_common.h
new file mode 100644 (file)
index 0000000..7fa395a
--- /dev/null
@@ -0,0 +1,21 @@
+#include "structures.h"
+
+
+struct snake_node* genere_snake_rectangle_bords(uint32 *nb_noeud, uint32 distance_bords, uint32 i_dim, uint32 j_dim) ;
+struct snake_node* genere_snake_rectangle(int *nb_noeud, uint32 i1, uint32 j1, uint32 i2, uint32 j2, 
+                                         uint32 i_dim, uint32 j_dim) ;
+
+
+void affiche_snake(int **image, struct snake_node *snake, int valseg, int valnoeud, uint32 *liste_pixel_segment) ;
+void affiche_snake_ushort(unsigned short **image, struct snake_node *snake, int valseg, unsigned short valnoeud, uint32 *liste_pixel_segment) ;
+
+
+struct snake_node* ajout_noeud_snake(struct snake_node *node, uint32 *nb_noeud) ;
+int test_croisement_add_noeud_large(struct snake_node *N, uint32 Nxi, uint32 Nxj, int seg);
+int test_croisement_add_noeud_strict(struct snake_node *N, uint32 Nxi, uint32 Nxj, int seg);
+
+int test_croisement_move_seg_strict(struct snake_node *Nx, uint32 Nxi, uint32 Nxj, int seg);
+int test_croisement_move_seg_large(struct snake_node *Nx, uint32 Nxi, uint32 Nxj, int seg);
+
+
+void debug_aff_snake(struct snake_node *snake);
diff --git a/src/lib_snake_common.h~ b/src/lib_snake_common.h~
new file mode 100644 (file)
index 0000000..ba8e011
--- /dev/null
@@ -0,0 +1,21 @@
+#include "structures.h"
+
+
+struct snake_node* genere_snake_rectangle_bords(uint32 *nb_noeud, uint32 distance_bords, uint32 i_dim, uint32 j_dim) ;
+struct snake_node* genere_snake_rectangle(int *nb_noeud, uint32 i1, uint32 j1, uint32 i2, uint32 j2, 
+                                         uint32 i_dim, uint32 j_dim) ;
+
+
+void affiche_snake(int **image, struct snake_node *snake, int valseg, int valnoeud, uint32 *liste_pixel_segment) ;
+void affiche_snake_ushort(unsigned short **image, struct snake_node *snake, int valseg, int valnoeud, uint32 *liste_pixel_segment) ;
+
+
+struct snake_node* ajout_noeud_snake(struct snake_node *node, uint32 *nb_noeud) ;
+int test_croisement_add_noeud_large(struct snake_node *N, uint32 Nxi, uint32 Nxj, int seg);
+int test_croisement_add_noeud_strict(struct snake_node *N, uint32 Nxi, uint32 Nxj, int seg);
+
+int test_croisement_move_seg_strict(struct snake_node *Nx, uint32 Nxi, uint32 Nxj, int seg);
+int test_croisement_move_seg_large(struct snake_node *Nx, uint32 Nxi, uint32 Nxj, int seg);
+
+
+void debug_aff_snake(struct snake_node *snake);
diff --git a/src/lib_test_gpu.cu b/src/lib_test_gpu.cu
new file mode 100644 (file)
index 0000000..c65ea16
--- /dev/null
@@ -0,0 +1,78 @@
+#include "stdio.h"
+#include "structures.h"
+#include "lib_test_gpu.h"
+
+void verif_cumuls(int ** img_in, int H, int L, uint64 ** d_img_1, uint64 ** d_img_x, uint64 ** d_img_x2, int BS, bool DISPLAY){
+  int taille = H*L ;
+  //allocation memoire CPU
+  uint64  img_1[H][L];
+  uint64  img_x[H][L];
+  uint64  img_x2[H][L];
+
+  /*pour test comparaison*/
+  uint64  img_1b[H][L];
+  uint64  img_xb[H][L];
+  uint64  img_x2b[H][L];
+  cudaMemcpy( img_1b, *d_img_1, taille*sizeof(uint64), cudaMemcpyDeviceToHost );
+  cudaMemcpy( img_xb, *d_img_x, taille*sizeof(uint64), cudaMemcpyDeviceToHost);
+  cudaMemcpy( img_x2b, *d_img_x2, taille*sizeof(uint64), cudaMemcpyDeviceToHost);
+  for (int i=0; i<H; i++)
+       {
+         img_1[i][0] = 1 ;
+         img_x[i][0] = img_in[i][0] ;
+         img_x2[i][0]= img_in[i][0]*img_in[i][0] ;
+         for (int j=1; j<L; j++)
+               {
+                 img_1[i][j]  = img_1[i][j-1]  + 1 ;
+                 img_x[i][j]  = img_x[i][j-1]  + img_in[i][j] ;
+                 img_x2[i][j] = img_x2[i][j-1] + img_in[i][j]*img_in[i][j] ;
+               }
+       }
+  
+  int cpt = 0;
+  int cpt_err = 0;
+  for (int i=0; i<H; i++){
+       for (int j=0; j<L; j++){
+         if( (img_1[i][j] !=  img_1b[i][j]) ||  (img_x[i][j] !=  img_xb[i][j]) ||  (img_x2[i][j] !=  img_x2b[i][j]) )
+               {
+                 if (!(j%BS)) printf("\n");
+                 if (DISPLAY)
+                       {
+                         printf("(%d,%d)CPU:%lu GPU:%lu\n",i, j, img_x2[i][j], img_x2b[i][j]);
+                         printf("(%d,%d):CPU=%lu  GPU=%lu\n",i,j,img_x[i][j], img_xb[i][j]);
+                       }
+                 cpt_err++;
+               }
+         cpt++;
+       }
+  }
+  printf("%d erreurs / %d points\n", cpt_err, cpt );
+}
+
+  void verif_stats_ref(int64 ** d_stats_ref, snake_node_gpu ** d_snake, int nnodes, int H, int L,
+                                          uint64 ** d_img_1, uint64 ** d_img_x, uint64 ** d_img_x2){
+       
+       int64 * h_stats_ref = new int64[3*nnodes];
+       snake_node_gpu * h_snake = new snake_node_gpu[nnodes] ;
+       uint64 * img_1 = new uint64[H*L];
+       uint64 * img_x = new uint64[H*L];
+       uint64 * img_x2 = new uint64[H*L];
+       
+       cudaMemcpy( img_1, *d_img_1, H*L*nnodes*sizeof(uint64), cudaMemcpyDeviceToHost) ;
+       cudaMemcpy( img_x, *d_img_x, H*L*nnodes*sizeof(uint64), cudaMemcpyDeviceToHost) ;
+       cudaMemcpy( img_x2, *d_img_x2, H*L*nnodes*sizeof(uint64), cudaMemcpyDeviceToHost) ;
+       
+       cudaMemcpy( h_stats_ref, *d_stats_ref, 3*nnodes*sizeof(int64), cudaMemcpyDeviceToHost) ;
+       cudaMemcpy( h_snake, *d_snake, nnodes*sizeof(snake_node_gpu), cudaMemcpyDeviceToHost) ;
+       
+       
+       printf("******* STATS DIMINUEES\n");
+  for(int n=0; n<nnodes;n++)
+       {
+         int i = h_snake[n].posi, j = h_snake[n].posj ;
+         printf("node %d (%d,%d) : %ld - %ld - %ld - img1= %lu - imgx= %lu - imgx2= %lu \n", n, i, j,
+                        h_stats_ref[3*n], h_stats_ref[3*n +1], h_stats_ref[3*n +2],
+                        img_1[i*L+j], img_x[i*L+j], img_x2[i*L+j]);
+       }
+  }
diff --git a/src/lib_test_gpu.cu~ b/src/lib_test_gpu.cu~
new file mode 100644 (file)
index 0000000..5e4e943
--- /dev/null
@@ -0,0 +1,45 @@
+void verif_cumuls(int ** img_in, uint64 ** d_img_1, uint64 ** d_img_x, uint64 ** d_img_x2){
+//allocation memoire CPU
+  uint64  img_1[H][L];
+  uint64  img_x[H][L];
+  uint64  img_x2[H][L];
+
+  /*pour test comparaison*/
+  uint64  img_1b[H][L];
+  uint64  img_xb[H][L];
+  uint64  img_x2b[H][L];
+  cudaMemcpy( img_1b, *d_img_1, taille*sizeof(uint64), cudaMemcpyDeviceToHost );
+  cudaMemcpy( img_xb, *d_img_x, taille*sizeof(uint64), cudaMemcpyDeviceToHost);
+  cudaMemcpy( img_x2b, *d_img_x2, taille*sizeof(uint64), cudaMemcpyDeviceToHost);
+  for (int i=0; i<H; i++)
+       {
+         img_1[i][0] = 1 ;
+         img_x[i][0] = img_in[i][0] ;
+         img_x2[i][0]= img_in[i][0]*img_in[i][0] ;
+         for (int j=1; j<L; j++)
+               {
+                 img_1[i][j]  = img_1[i][j-1]  + 1 ;
+                 img_x[i][j]  = img_x[i][j-1]  + img_in[i][j] ;
+                 img_x2[i][j] = img_x2[i][j-1] + img_in[i][j]*img_in[i][j] ;
+               }
+       }
+  
+  int cpt = 0;
+  int cpt_err = 0;
+  for (int i=0; i<H; i++){
+       for (int j=0; j<L; j++){
+         if( (img_1[i][j] !=  img_1b[i][j]) ||  (img_x[i][j] !=  img_xb[i][j]) ||  (img_x2[i][j] !=  img_x2b[i][j]) )
+               {
+                 if (!(j%BS)) printf("\n");
+#ifdef DISPLAY_ERR_IMG_CUMUL
+                 printf("(%d,%d)CPU:%lu GPU:%lu\n",i, j, img_x2[i][j], img_x2b[i][j]);
+                 printf("(%d,%d):CPU=%lu  GPU=%lu\n",i,j,img_x[i][j], img_xb[i][j]);
+#endif
+                 cpt_err++;
+               }
+         cpt++;
+       }
+  }
+  printf("%d erreurs / %d points\n", cpt_err, cpt );
+}
diff --git a/src/lib_test_gpu.h b/src/lib_test_gpu.h
new file mode 100644 (file)
index 0000000..d92e26c
--- /dev/null
@@ -0,0 +1,9 @@
+#ifndef __TEST_GPU__
+#define __TEST_GPU__
+
+void verif_cumuls(int ** , int , int , uint64 ** , uint64 ** , uint64 ** , int, bool);
+
+void verif_stats_ref(int64 ** d_stats_ref, snake_node_gpu ** d_snake, int nnodes, int h, int l,
+                                        uint64 ** d_img_1, uint64 ** d_img_x, uint64 ** d_img_x2);
+
+#endif
diff --git a/src/lib_test_gpu.h~ b/src/lib_test_gpu.h~
new file mode 100644 (file)
index 0000000..23c25bf
--- /dev/null
@@ -0,0 +1,2 @@
+
+void verif_cumuls(int ** img_in, uint64 ** d_img_1, uint64 ** d_img_x, uint64 ** d_img_x2);
diff --git a/src/snake2D_gpu.cu b/src/snake2D_gpu.cu
new file mode 100644 (file)
index 0000000..d5a42bb
--- /dev/null
@@ -0,0 +1,347 @@
+/**
+ * \file snake2D.c
+ * \brief snake polygonale approche region sous hypothese Gaussienne ou Gamma.
+ * \author NB - PhyTI 
+ * \version x.x
+ * \date 20 decembre 2009
+ *
+ * traitement d'images en entiers 16 bits non signe : ppm
+ * USAGE : SNAKE2D image.pgm 0 (ou 1)
+ */
+
+#include <stdio.h>
+#include <malloc.h>
+#include "structures.h"
+extern "C"{
+#include "lib_alloc.h"
+#include "lib_images.h"
+#include "lib_snake_common.h"
+#include "lib_math.h"
+#include "lib_gpu.h"
+#include "defines.h"
+#include "lib_snake_2_gpu.h"
+}
+#include "lib_kernels_maths.cu"
+#include "lib_kernels_contribs.cu"
+
+
+
+
+int main(int argc, char **argv)
+{
+  /* declaration des variables */
+  int ret ;
+  int Prof ;        /* profondeur en octets */
+  uint32 I_dim ;       /* hauteur de l'image */
+  uint32 J_dim ;       /* largeur de l'image */
+  int Nb_level ;    /* dynamique de l'image */
+  char *File_name ;
+  
+
+  /* images */
+  unsigned short **Image_in;
+  struct timeval chrono, chrono_all ;
+
+  /* lecture argument entree (basique!) */
+  File_name = argv[3] ;
+
+  /* verif type image (pgm 8/16) */
+  ret = type_image_ppm(&Prof, &I_dim, &J_dim, &Nb_level, File_name) ;
+
+  if ((ret == 0) | (Prof == 3))
+    {
+      printf("format non pris en charge ... exit\n") ;
+      return(0) ;
+    }
+
+  /* infos */
+  printf("Image : %s\n", File_name) ;
+  printf("lecture OK : %d\n", ret) ;
+  printf("Image (%d x %d) pixels\n", I_dim, J_dim) ;
+  printf("Dynamique : %d\n", Nb_level) ;
+
+  /* Allocation */
+  Image_in = new_matrix_ushort(I_dim, J_dim) ;
+  
+  /* chargement image d'entree */
+  load_pgm2ushort(Image_in, I_dim, J_dim, Nb_level, File_name) ;
+
+  //POINTEURS VARIABLES MEMOIRE GLOBALE GPU
+  unsigned short    * d_img ;   // image 
+  t_cumul_x * d_img_x ;         // images cumulees
+  t_cumul_x2 * d_img_x2;        //
+
+  snake_node_gpu * d_snake ;    //image du snake CPU dans un tableau en gmem GPUe
+
+  int    * d_freemanDiDj ;            // table de correspondance [Di][Dj]->Freemans
+  int    * d_codeNoeud ;              // table de correspondance [F_in][F_out]->codeNoeud
+
+  uint4  * d_positions ;              // positions de test autour des noeuds 
+
+  uint2  * d_listes_pixels ;          // coordonnees des pixels des segments correspondants aux 8 posiionstest
+  uint2  * d_liste_temp ;             
+  uint32 * d_nb_pix_max ;             // taille max des segments a tester
+
+  uint64 * d_contribs_segments_blocs ;// sommes des contribs pixels par blocs de calcul
+  uint64 * d_contribs_segments ;      // contribs segments 1, x et x2
+  uint64 * d_sompart ;                // vecteur de resultats intermediaires (sommes partielles = sommes par blocs)
+  
+  int64  * d_stats, * d_stats_ref ;   // stats des positions de test, du snake sans les segments en test
+  int64  * d_stats_snake;             // stats du snake + stats de l'image complete
+  double * d_vrais, * d_vrais_snake ; // valeurs de la log-vraisemblance des positions de test, du snake  
+
+  uint4  * d_freemans_centres ;       // valeurs des F_in, F_out et coord.
+                                      // centres des 16 segments associes aux 8 positions de test
+
+  int    * d_codes_segments ;         // valeurs de codes des 16 segments
+  bool   * d_move ;                   // nb de deplacement effectues lors d'une iteration
+  int    * d_nb_nodes ;               // nb de noeuds du snake
+  
+  snake_node_gpu * d_snake_tmp ;      // snake tampon pour l'etape d'ajout de noeuds
+  
+  /* pointeurs sur mem CPU */
+  int *h_nb_nodes = new int;          // image CPU du nb de noeud du snake  
+  snake_node_gpu  h_snake[MAX_NODES];
+  double h_vrais_snake, h_vrais_mem ; // image CPU de la log-vraisemblance
+  bool * h_move = new bool[MAX_NODES];// image CPU du vecteur identifiant les noeuds qui ont bouge
+  uint32 h_nb_pix_max, npixmax ;      // taille max des segments a tester : utile pour determiner les params d'execution
+  int nnodes = 4 ;                    // 4 ou 40 pour l'instant
+  
+  
+  /*allocation memoire GPU  */
+  cudaMalloc((void**) &d_nb_nodes, sizeof(int));
+  cudaMalloc((void**) &d_sompart, MAX_NODES*256*16*sizeof(uint64));
+  cudaMalloc((void**) &d_liste_temp, MAX_NODES*5*16*sizeof(uint2));
+  cudaMalloc((void**) &d_snake_tmp, MAX_NODES*sizeof(snake_node_gpu) );
+  
+  /*init snake (positions/contribs/stats/freemans/centres/codes)*/
+  cuda_init_img_cumul(Image_in, I_dim, J_dim, nnodes,
+                                         &d_img, &d_img_x, &d_img_x2,
+                                         &d_freemanDiDj, &d_codeNoeud,
+                                         &d_snake, &d_nb_pix_max, 
+                                         &d_positions, &d_contribs_segments, &d_freemans_centres,
+                                         &d_codes_segments, &d_stats_snake,
+                                         &d_stats, &d_stats_ref, &d_vrais, &d_vrais_snake,
+                                         &d_listes_pixels, &d_contribs_segments_blocs,
+                                         &d_move
+                                         );
+
+  /* debug : affichage snake */
+  int Verbose = 1 ;
+  int VERBOSE = 1 ;
+  int Display = 1 ;
+  //snake_node * h_snake_ll;
+  uint64 h_stats_snake[6];
+  //gpu2snake(d_snake, &h_snake_ll, nnodes);
+  
+  // variables de debug 
+  int nb_move, iter, i ;
+  int nb_move_total=0, nb_test_total=0 ;
+  int NB_iter_max = atoi(argv[1]);
+  int Pas = atoi(argv[2]) ;                       // distance entre la position actuelle et les positions de test
+  int Dist_min_entre_noeud = 4*Pas ;
+  int bs, nblocs_seg, tpb, bps ;                  // nb de threads par blocs pour l'execution des kernels, nb de blocs de threads par segment a tester
+  dim3 threads, grid ;                            // params d'execution des kernels
+  int n_interval ;                                // nombre d'intervalles Na--Nx--Nb concernes
+  int taille_smem ;                               // quantite de shared memory allouee pour le calcul des contribs des segments de test
+  bool pairs = true ;                             // mouvement des noeuds pairs/impairs
+  
+  if (Verbose) {
+       printf("nb noeuds : %d\n", nnodes) ;
+       tic(&chrono_all, NULL) ;
+  }
+  
+  for (iter=1; (iter<=NB_iter_max)&&(Pas>0); iter++, Pas>>=1)
+    {
+        
+      if (VERBOSE)
+               {
+                 cudaMemcpy( &h_vrais_snake, d_vrais_snake, sizeof(double), cudaMemcpyDeviceToHost);
+                 printf("\n#%d : pas %d pixels, LV = %lf \n", iter, Pas, h_vrais_snake) ;
+                 tic(&chrono, NULL) ;
+               }
+         // DEBUT MOVE SNAKE
+         do {
+
+               //memorisation precedente LV
+               h_vrais_mem = h_vrais_snake ;
+               // calcul stats sans les paires de segments a bouger
+               soustrait_aux_stats_2N_segments_noeud<<< nnodes , 1 >>>(d_snake, d_stats_snake, d_stats_ref, 
+                                                                       d_img_x, d_img_x2,
+                                                                       d_codeNoeud, J_dim
+                                                                       );
+
+               // calcul des coordonnées de toutes les positions possibles des noeud a l'etape N+1 
+               liste_positions_a_tester<<<nnodes, 8>>>(d_snake, d_positions, d_nb_pix_max, Pas, nnodes, I_dim, J_dim) ;
+               
+               // recupere la taille maxi des segments
+               cudaMemcpy( &h_nb_pix_max, d_nb_pix_max, sizeof(uint32), cudaMemcpyDeviceToHost) ;
+               
+               // determination des parametres des kernels
+               bs = nextPow2(h_nb_pix_max) ;
+               if (bs>=BSMAX) bs = BSMAX ; //  /!\ le kernel <<< calcul_contrib...>>> ne supporte pas un bs>256 a cause de la shared-mem nécessaire
+               if (bs<32) bs = 32 ;
+               nblocs_seg = (h_nb_pix_max+bs-1)/bs ;
+
+               pairs = false ;
+               n_interval = nnodes/2 + pairs*(nnodes%2) ;
+               taille_smem =  CFI(bs)*sizeof(tcontribs) ;
+               threads = dim3(bs,1,1) ;
+               grid = dim3( n_interval*16*nblocs_seg ,1,1) ; 
+               
+                 //calcul listes pix + contrib partielles + freemans + centres  
+                 calcul_contribs_segments_blocs_full<<< grid , threads, taille_smem >>>( d_snake, nnodes, d_positions, h_nb_pix_max,
+                                                                                         d_img_x, d_img_x2, d_codes_segments,
+                                                                                         J_dim, d_listes_pixels, d_contribs_segments_blocs,
+                                                                                                                                                                 pairs);
+                 
+          calcul_freemans_centre<<<n_interval, 16>>>( d_listes_pixels,  d_freemanDiDj, d_freemans_centres);
+                 //printf("EXEC impairs : %d max pix - %d intervalles => %d blocs de %d threads - %d octets de smem\n", h_nb_pix_max, n_interval, grid.x, threads.x, taille_smem);
+                 //sommes des contribs partielles -> contribs segments
+                 somsom_full<<< 16*n_interval , 1>>>(d_contribs_segments_blocs, nnodes, nblocs_seg, d_contribs_segments) ;
+                 
+                 //calcul des stats associees a chaque position de test
+                 calcul_stats_full<<< n_interval, 8 >>>(d_snake, nnodes, pairs, d_stats_snake, d_stats_ref, d_stats, d_contribs_segments,
+                                                                                                d_positions, d_codes_segments,  d_freemans_centres, d_codeNoeud,
+                                                                                                d_img_x, d_img_x2, I_dim, J_dim, d_vrais, d_vrais_snake, d_move);
+               
+                 pairs = true ;
+                 n_interval = nnodes/2 + pairs*(nnodes%2) ;
+                 grid = dim3( n_interval*16*nblocs_seg ,1,1) ; 
+
+                 //calcul listes pix + contrib partielles + freemans + centres
+                 calcul_contribs_segments_blocs_full<<< grid , threads, taille_smem >>>( d_snake, nnodes, d_positions, h_nb_pix_max,
+                                                                                         d_img_x, d_img_x2, d_codes_segments,
+                                                                                         J_dim, d_listes_pixels, d_contribs_segments_blocs,
+                                                                                         pairs);
+                 calcul_freemans_centre<<<n_interval, 16>>>( d_listes_pixels, d_freemanDiDj, d_freemans_centres);                                                                                      
+                 //printf("EXEC pairs : %d max pix - %d intervalles => %d blocs de %d threads - %d octets de smem\n", h_nb_pix_max, n_interval, grid.x, threads.x, taille_smem);
+               //sommes des contribs partielles -> contribs segments
+                 somsom_full<<< 16*n_interval , 1>>>(d_contribs_segments_blocs, nnodes, nblocs_seg, d_contribs_segments) ;
+                 
+                 //calcul des stats associees a chaque position de test
+                 calcul_stats_full<<< n_interval, 8 >>>(d_snake, nnodes, pairs, d_stats_snake, d_stats_ref, d_stats, d_contribs_segments,
+                                                                                                d_positions, d_codes_segments,  d_freemans_centres, d_codeNoeud,
+                                                                                                d_img_x, d_img_x2, I_dim, J_dim, d_vrais, d_vrais_snake, d_move);
+               
+                 
+               //il faut recalculer les stats du snake apres modif
+               recalcul_stats_snake<<< 1 , 1  >>>(d_snake, nnodes, d_stats_snake, d_vrais_snake,
+                                                                                  d_img_x, d_img_x2,
+                                                                                  d_codeNoeud, J_dim
+                                                                                  );
+               
+               cudaMemcpy( &h_vrais_snake, d_vrais_snake, sizeof(double), cudaMemcpyDeviceToHost);
+               //printf("iter %d apres recalcul du move LV = %lf - ",  iter, h_vrais_snake) ;
+               
+               nb_move = 0;
+               //recup move
+               cudaMemcpy( h_move, d_move, nnodes*sizeof(bool), cudaMemcpyDeviceToHost);
+               i = 0;
+               while (i<nnodes)
+                 {
+                       nb_move += (int)h_move[i];
+                       i++;
+                 }
+               
+               nb_move_total += nb_move ;
+               nb_test_total+= nnodes*8 ;
+         } while ( nb_move && (h_vrais_snake < h_vrais_mem));
+
+         if ( iter < NB_iter_max ){
+           // ajout de noeuds 
+           ajoute_noeuds<<< 1 , 1 >>>(d_snake, d_snake_tmp, nnodes, Dist_min_entre_noeud, d_nb_nodes );                     
+               //recup nb de nouveaux noeuds
+               cudaMemcpy( h_nb_nodes, d_nb_nodes, sizeof(int), cudaMemcpyDeviceToHost);
+               //mise a jour nb de noeuds
+           nnodes += (*h_nb_nodes) ;
+
+               //parametres d'execution des kernels pour le recalcul des contribs et stats du snake
+           npixmax = h_nb_pix_max ;
+           tpb = nextPow2(npixmax) ;
+           if (tpb >= BSMAX) tpb = BSMAX ;//  /!\ le kernel <<< calcul_contrib...>>> ne supporte pas un bs>BSMAX a cause de la shared-mem nécessaire
+           if (tpb < 32 ) tpb = 32 ;
+           bps = (npixmax+tpb-1)/tpb ;
+
+               //calcul sommes partielles des contribs + codes segments
+           recalcul_contribs_segments_snake<<< nnodes*bps, tpb, CFI(tpb)*sizeof(tcontribs)>>>(d_snake, nnodes, 
+                                                                                                                                                                                  d_img_x, d_img_x2, 
+                                                                                                                                                                                  J_dim, d_liste_temp, d_sompart );
+               //calcul des freemans et des centres a partir des 5 points stockes par segment dans 'd_liste_temp'
+           recalcul_freemans_centre<<<nnodes, 1>>>(d_snake, d_liste_temp, d_freemanDiDj);
+               //somme des sommes partielles
+           resomsom_snake<<< nnodes , 1 >>>(d_sompart, nnodes, bps, d_snake);
+               //calcul des stats 
+           recalcul_stats_snake<<< 1 , 1 >>>(d_snake, nnodes, d_stats_snake, d_vrais_snake,
+                                                                                 d_img_x, d_img_x2,
+                                                                                 d_codeNoeud, J_dim
+                                                                                 );
+           //tant que l'on peut ajouter des noeuds
+               if (*h_nb_nodes == 0) break ;
+               //recup LogVraisemblance 
+               cudaMemcpy( &h_vrais_snake, d_vrais_snake, sizeof(double), cudaMemcpyDeviceToHost);
+                 
+         }
+         
+      if (VERBOSE) 
+       {
+         toc(chrono, "temps sequence move");
+         
+         printf("nb deplacements    : %d\n", nb_move) ;
+         printf("nb deplacements total/test   : %d/%d\n", nb_move_total, nb_test_total) ;
+         printf("nb nouveaux noeuds : %d (total: %d)\n", *h_nb_nodes, nnodes) ;
+         printf("\nlongueur de codage de gl : %lf  \n", h_vrais_snake) ;     
+       }
+    }
+  
+  if (Verbose) {
+       toc(chrono_all, "temps move mv") ;
+       cudaMemcpy( h_stats_snake, d_stats_snake, 6*sizeof(uint64), cudaMemcpyDeviceToHost);
+       cudaMemcpy( &h_vrais_snake, d_vrais_snake, sizeof(double), cudaMemcpyDeviceToHost);
+       printf("\nFIN : longueur de codage de gl : %lf  (%d)\n", h_vrais_snake, h_stats_snake[0]) ;     
+       printf("nb noeuds : %d, nb_iter : %d\n", nnodes, iter-1) ;
+       printf("nb deplacements total/test   : %d/%d\n", nb_move_total, nb_test_total) ;
+  }  
+  
+      
+  if (Display) {
+       /* old fashion way to draw the snake
+       gpu2snake(d_snake, &h_snake_ll, nnodes);
+       uint32 * Liste_pixel_segment = new uint32[I_dim+J_dim];
+       affiche_snake_ushort(Image_in, h_snake_ll, 255, 0, Liste_pixel_segment) ;
+       delete Liste_pixel_segment ; 
+       delete h_snake_ll;
+       */
+       cudaMemcpy( h_snake, d_snake, nnodes*sizeof(snake_node_gpu), cudaMemcpyDeviceToHost);
+       //affiche coordonnees
+       for (int node=0; node<nnodes; node++){
+           printf("NODE %d  %d  %d \n", node, h_snake[node].posi, h_snake[node].posj);
+       }
+       // draw only the nodes with + marks
+       dessine_snake(h_snake, nnodes, Image_in, 10);
+       imagesc_ushort(Image_in, I_dim, J_dim) ;
+  }
+  cudaFree(d_img);
+  cudaFree(d_img_x);
+  cudaFree(d_img_x2);
+  cudaFree(d_freemanDiDj);
+  cudaFree(d_codeNoeud);
+  cudaFree(d_snake);
+  cudaFree(d_nb_pix_max); 
+  cudaFree(d_positions);
+  cudaFree(d_contribs_segments);
+  cudaFree(d_freemans_centres);
+  cudaFree(d_codes_segments);
+  cudaFree(d_stats_snake);
+  cudaFree(d_stats);
+  cudaFree(d_stats_ref);
+  cudaFree(d_vrais);
+  cudaFree(d_vrais_snake);
+  cudaFree(d_listes_pixels);
+  cudaFree(d_contribs_segments_blocs);
+  cudaFree(d_move);
+  return 1 ;
+}
+
diff --git a/src/snake2D_gpu.cu~ b/src/snake2D_gpu.cu~
new file mode 100644 (file)
index 0000000..7152723
--- /dev/null
@@ -0,0 +1,362 @@
+/**
+ * \file snake2D.c
+ * \brief snake polygonale approche region sous hypothese Gaussienne ou Gamma.
+ * \author NB - PhyTI 
+ * \version x.x
+ * \date 20 decembre 2009
+ *
+ * traitement d'images en entiers 16 bits non signe : ppm
+ * USAGE : SNAKE2D image.pgm 0 (ou 1)
+ */
+
+#include <stdio.h>
+#include <malloc.h>
+#include "structures.h"
+extern "C"{
+#include "lib_alloc.h"
+#include "lib_images.h"
+#include "lib_snake_common.h"
+#include "lib_math.h"
+#include "lib_gpu.h"
+#include "defines.h"
+#include "lib_snake_2_gpu.h"
+}
+#include "lib_kernels_maths.cu"
+#include "lib_kernels_contribs.cu"
+
+
+
+
+int main(int argc, char **argv)
+{
+  /* declaration des variables */
+  int ret ;
+  int Prof ;        /* profondeur en octets */
+  uint32 I_dim ;       /* hauteur de l'image */
+  uint32 J_dim ;       /* largeur de l'image */
+  int Nb_level ;    /* dynamique de l'image */
+  char *File_name ;
+  
+
+  /* images */
+  unsigned short **Image_in;
+  struct timeval chrono, chrono2, chrono_all ;
+
+  /* lecture argument entree (basique!) */
+  File_name = argv[3] ;
+
+  /* verif type image (pgm 8/16) */
+  ret = type_image_ppm(&Prof, &I_dim, &J_dim, &Nb_level, File_name) ;
+
+  if ((ret == 0) | (Prof == 3))
+    {
+      printf("format non pris en charge ... exit\n") ;
+      return(0) ;
+    }
+
+  /* infos */
+  printf("Image : %s\n", File_name) ;
+  printf("lecture OK : %d\n", ret) ;
+  printf("Image (%d x %d) pixels\n", I_dim, J_dim) ;
+  printf("Dynamique : %d\n", Nb_level) ;
+
+  /* Allocation */
+  Image_in = new_matrix_ushort(I_dim, J_dim) ;
+  
+  /* chargement image d'entree */
+  load_pgm2ushort(Image_in, I_dim, J_dim, Nb_level, File_name) ;
+
+  //POINTEURS VARIABLES MEMOIRE GLOBALE GPU
+  unsigned short    * d_img ;   // image 
+  t_cumul_x * d_img_x ;         // images cumulees
+  t_cumul_x2 * d_img_x2;        //
+
+  snake_node_gpu * d_snake ;    //image du snake CPU dans un tableau en gmem GPUe
+
+  int    * d_freemanDiDj ;            // table de correspondance [Di][Dj]->Freemans
+  int    * d_codeNoeud ;              // table de correspondance [F_in][F_out]->codeNoeud
+
+  uint4  * d_positions ;              // positions de test autour des noeuds 
+
+  uint2  * d_listes_pixels ;          // coordonnees des pixels des segments correspondants aux 8 posiionstest
+  uint2  * d_liste_temp ;             
+  uint32 * d_nb_pix_max ;             // taille max des segments a tester
+
+  uint64 * d_contribs_segments_blocs ;// sommes des contribs pixels par blocs de calcul
+  uint64 * d_contribs_segments ;      // contribs segments 1, x et x2
+  uint64 * d_sompart ;                // vecteur de resultats intermediaires (sommes partielles = sommes par blocs)
+  
+  int64  * d_stats, * d_stats_ref ;   // stats des positions de test, du snake sans les segments en test
+  int64  * d_stats_snake;             // stats du snake + stats de l'image complete
+  double * d_vrais, * d_vrais_snake ; // valeurs de la log-vraisemblance des positions de test, du snake  
+
+  uint4  * d_freemans_centres ;       // valeurs des F_in, F_out et coord.
+                                      // centres des 16 segments associes aux 8 positions de test
+
+  int    * d_codes_segments ;         // valeurs de codes des 16 segments
+  bool   * d_move ;                   // nb de deplacement effectues lors d'une iteration
+  int    * d_nb_nodes ;               // nb de noeuds du snake
+  
+  snake_node_gpu * d_snake_tmp ;      // snake tampon pour l'etape d'ajout de noeuds
+  
+  /* pointeurs sur mem CPU */
+  int *h_nb_nodes = new int;          // image CPU du nb de noeud du snake  
+  snake_node_gpu  h_snake[MAX_NODES] ;
+  uint2 h_listes_pixels[MAX_NODES*16*5] ;
+  double h_vrais_snake, h_vrais_mem, h_vrais[8*MAX_NODES] ;              // image CPU de la log-vraisemblance
+  bool * h_move = new bool[MAX_NODES];// image CPU du vecteur identifiant les noeuds qui ont bouge
+  uint32 h_nb_pix_max, npixmax ;      // taille max des segments a tester : utile pour determiner les params d'execution
+  int nnodes = 4 ;                    // 4 ou 40 pour l'instant
+  
+  
+  /*allocation memoire GPU  */
+  int retour_cmd = 0;
+  cudaMalloc((void**) &d_nb_nodes, sizeof(int));
+  cudaMalloc((void**) &d_sompart, MAX_NODES*256*16*sizeof(uint64));
+  cudaMalloc((void**) &d_liste_temp, MAX_NODES*5*16*sizeof(uint2));
+  retour_cmd = cudaMalloc((void**) &d_snake_tmp, MAX_NODES*sizeof(snake_node_gpu) );
+  printf("RESULTAT ALLOC snake_tmp = %d\n", retour_cmd);
+  
+
+  /*init snake (positions/contribs/stats/freemans/centres/codes)*/
+  cuda_init_img_cumul(Image_in, I_dim, J_dim, nnodes,
+                                         &d_img, &d_img_x, &d_img_x2,
+                                         &d_freemanDiDj, &d_codeNoeud,
+                                         &d_snake, &d_nb_pix_max, 
+                                         &d_positions, &d_contribs_segments, &d_freemans_centres,
+                                         &d_codes_segments, &d_stats_snake,
+                                         &d_stats, &d_stats_ref, &d_vrais, &d_vrais_snake,
+                                         &d_listes_pixels, &d_contribs_segments_blocs,
+                                         &d_move
+                                         );
+
+  /* debug : affichage snake */
+  int Verbose = 1 ;
+  int VERBOSE = 1 ;
+  int Display = 1 ;
+  /* debug : tests fonctions*/
+  int H= I_dim, L= J_dim ;
+  
+  //snake_node * h_snake_ll;
+  uint64 h_stats_snake[6];
+  //gpu2snake(d_snake, &h_snake_ll, nnodes);
+  
+  // variables de debug 
+  int nb_move, nb_newnode, iter, i ;
+  int nb_move_total=0, nb_test_total=0 ;
+  int NB_iter_max = atoi(argv[1]);
+  int dist = (I_dim+J_dim)/5;
+  int Pas = atoi(argv[2]) ;                           // dist entre la position actuelle et les positions de test
+  int Dist_min_entre_noeud = 4*Pas ;
+  int bs, nblocs_seg, tpb, bps ;                  // nb de threads par blocs pour l'execution des kernels, nb de blocs de threads par segment a tester
+  dim3 threads, grid ;                            // params d'execution des kernels
+  int n_interval ;                                // nombre d'intervalles Na--Nx--Nb concernes
+  int taille_smem ;                               // quantite de shared memory allouee pour le calcul des contribs des segments de test
+  bool pairs = true ;                             // mouvement des noeuds pairs/impairs
+  
+  if (Verbose) {
+       printf("nb noeuds : %d\n", nnodes) ;
+       tic(&chrono_all, NULL) ;
+  }
+  
+  for (iter=1; (iter<=NB_iter_max)&&(Pas>0); iter++, Pas>>=1)
+    {
+        
+      if (VERBOSE)
+               {
+                 cudaMemcpy( &h_vrais_snake, d_vrais_snake, sizeof(double), cudaMemcpyDeviceToHost);
+                 printf("\n#%d : pas %d pixels, LV = %lf \n", iter, Pas, h_vrais_snake) ;
+                 tic(&chrono, NULL) ;
+               }
+         // DEBUT MOVE SNAKE
+         do {
+
+               //memorisation precedente LV
+               h_vrais_mem = h_vrais_snake ;
+               // calcul stats sans les paires de segments a bouger
+               soustrait_aux_stats_2N_segments_noeud<<< nnodes , 1 >>>(d_snake, d_stats_snake, d_stats_ref, 
+                                                                       d_img_x, d_img_x2,
+                                                                       d_codeNoeud, J_dim
+                                                                       );
+
+               // calcul des coordonnées de toutes les positions possibles des noeud a l'etape N+1 
+               liste_positions_a_tester<<<nnodes, 8>>>(d_snake, d_positions, d_nb_pix_max, Pas, nnodes, I_dim, J_dim) ;
+               
+               // recupere la taille maxi des segments
+               cudaMemcpy( &h_nb_pix_max, d_nb_pix_max, sizeof(uint32), cudaMemcpyDeviceToHost) ;
+               
+               // determination des parametres des kernels
+               bs = nextPow2(h_nb_pix_max) ;
+               if (bs>=BSMAX) bs = BSMAX ; //  /!\ le kernel <<< calcul_contrib...>>> ne supporte pas un bs>256 a cause de la shared-mem nécessaire
+               if (bs<32) bs = 32 ;
+               nblocs_seg = (h_nb_pix_max+bs-1)/bs ;
+
+               pairs = false ;
+               n_interval = nnodes/2 + pairs*(nnodes%2) ;
+               taille_smem =  CFI(bs)*sizeof(tcontribs) ;
+               threads = dim3(bs,1,1) ;
+               grid = dim3( n_interval*16*nblocs_seg ,1,1) ; 
+               
+                 //calcul listes pix + contrib partielles + freemans + centres  
+                 calcul_contribs_segments_blocs_full<<< grid , threads, taille_smem >>>( d_snake, nnodes, d_positions, h_nb_pix_max,
+                                                                                         d_img_x, d_img_x2, d_codes_segments,
+                                                                                         J_dim, d_listes_pixels, d_contribs_segments_blocs,
+                                                                                                                                                                 pairs);
+                 /*debug*/
+                 cudaMemcpy( h_listes_pixels, d_listes_pixels, 16*5*n_interval*sizeof(uint2), cudaMemcpyDeviceToHost);
+                 for(int inter=0; inter < 3; inter++){
+                       for(int seg=0; seg<16; seg++){
+                         printf(" intervalle %d segment %d : (%d,%d)-(%d,%d)-(%d,%d)-(%d,%d)-(%d,%d)\n",
+                                        inter, seg, h_listes_pixels[5*(16*inter+seg)].x,h_listes_pixels[5*(16*inter+seg)].y,h_listes_pixels[5*(16*inter+seg)+1].x,
+                                        h_listes_pixels[5*(16*inter+seg)+1].y,h_listes_pixels[5*(16*inter+seg)+2].x,h_listes_pixels[5*(16*inter+seg)+2].y,
+                               h_listes_pixels[5*(16*inter+seg)+3].x,h_listes_pixels[5*(16*inter+seg)+3].y,h_listes_pixels[5*(16*inter+seg)+4].x,
+                               h_listes_pixels[5*(16*inter+seg)+4].y);
+                       }
+                 }
+                 /*fin*/
+          calcul_freemans_centre<<<n_interval, 16>>>( d_listes_pixels,  d_freemanDiDj, d_freemans_centres);
+                 //printf("EXEC impairs : %d max pix - %d intervalles => %d blocs de %d threads - %d octets de smem\n", h_nb_pix_max, n_interval, grid.x, threads.x, taille_smem);
+                 //sommes des contribs partielles -> contribs segments
+                 somsom_full<<< 16*n_interval , 1>>>(d_contribs_segments_blocs, nnodes, nblocs_seg, d_contribs_segments) ;
+                 
+                 //calcul des stats associees a chaque position de test
+                 calcul_stats_full<<< n_interval, 8 >>>(d_snake, nnodes, pairs, d_stats_snake, d_stats_ref, d_stats, d_contribs_segments,
+                                                                                                d_positions, d_codes_segments,  d_freemans_centres, d_codeNoeud,
+                                                                                                d_img_x, d_img_x2, I_dim, J_dim, d_vrais, d_vrais_snake, d_move);
+               
+                 pairs = true ;
+                 n_interval = nnodes/2 + pairs*(nnodes%2) ;
+                 grid = dim3( n_interval*16*nblocs_seg ,1,1) ; 
+
+                 //calcul listes pix + contrib partielles + freemans + centres
+                 calcul_contribs_segments_blocs_full<<< grid , threads, taille_smem >>>( d_snake, nnodes, d_positions, h_nb_pix_max,
+                                                                                         d_img_x, d_img_x2, d_codes_segments,
+                                                                                         J_dim, d_listes_pixels, d_contribs_segments_blocs,
+                                                                                         pairs);
+               calcul_freemans_centre<<<n_interval, 16>>>( d_listes_pixels, d_freemanDiDj, d_freemans_centres);                                                                                        
+               //printf("EXEC pairs : %d max pix - %d intervalles => %d blocs de %d threads - %d octets de smem\n", h_nb_pix_max, n_interval, grid.x, threads.x, taille_smem);
+               //sommes des contribs partielles -> contribs segments
+               somsom_full<<< 16*n_interval , 1>>>(d_contribs_segments_blocs, nnodes, nblocs_seg, d_contribs_segments) ;
+                 
+               //calcul des stats associees a chaque position de test
+               calcul_stats_full<<< n_interval, 8 >>>(d_snake, nnodes, pairs, d_stats_snake, d_stats_ref, d_stats, d_contribs_segments,
+                                                                                                d_positions, d_codes_segments,  d_freemans_centres, d_codeNoeud,
+                                                                                                d_img_x, d_img_x2, I_dim, J_dim, d_vrais, d_vrais_snake, d_move);
+               
+                 
+               //il faut recalculer les stats du snake apres modif
+               recalcul_stats_snake<<< 1 , 1  >>>(d_snake, nnodes, d_stats_snake, d_vrais_snake,
+                                                                                  d_img_x, d_img_x2,
+                                                                                  d_codeNoeud, J_dim
+                                                                                  );
+               
+               cudaMemcpy( &h_vrais_snake, d_vrais_snake, sizeof(double), cudaMemcpyDeviceToHost);
+               //printf("iter %d apres recalcul du move LV = %lf - ",  iter, h_vrais_snake) ;
+               
+               nb_move = 0;
+               //recup move
+               cudaMemcpy( h_move, d_move, nnodes*sizeof(bool), cudaMemcpyDeviceToHost);
+               i = 0;
+               while (i<nnodes)
+                 {
+                       nb_move += (int)h_move[i];
+                       i++;
+                 }
+               
+               nb_move_total += nb_move ;
+               nb_test_total+= nnodes*8 ;
+         } while ( nb_move && (h_vrais_snake < h_vrais_mem));
+
+         if ( iter < NB_iter_max ){
+           // ajout de noeud et recalcul stats
+           ajoute_noeuds<<< 1 , 1 >>>(d_snake, d_snake_tmp, nnodes, Dist_min_entre_noeud, d_nb_nodes );                     
+           cudaMemcpy( h_nb_nodes, d_nb_nodes, sizeof(int), cudaMemcpyDeviceToHost);
+           nnodes += (*h_nb_nodes) ;
+
+           cudaMemcpy( d_snake, d_snake_tmp, nnodes*sizeof(snake_node_gpu), cudaMemcpyDeviceToDevice);
+
+           npixmax = h_nb_pix_max ;
+           tpb = nextPow2(npixmax) ;
+           if (tpb >= BSMAX) tpb = BSMAX ;//  /!\ le kernel <<< calcul_contrib...>>> ne supporte pas un bs>256 a cause de la shared-mem nécessaire
+           if (tpb < 32 ) tpb = 32 ;
+           bps = (npixmax+tpb-1)/tpb ;
+               
+           recalcul_contribs_segments_snake<<< nnodes*bps, tpb, CFI(tpb)*sizeof(tcontribs)>>>(d_snake, nnodes, 
+                                                                                               d_img_x, d_img_x2, 
+                                                                                               J_dim, d_liste_temp, d_sompart );
+
+           recalcul_freemans_centre<<<nnodes, 1>>>(d_snake, d_liste_temp, d_freemanDiDj);
+           resomsom_snake<<< nnodes , 1 >>>(d_sompart, nnodes, bps, d_snake);
+       
+           recalcul_stats_snake<<< 1 , 1 >>>(d_snake, nnodes, d_stats_snake, d_vrais_snake,
+                                                 d_img_x, d_img_x2,
+                                                 d_codeNoeud, J_dim
+                                                 );
+           
+               if (*h_nb_nodes == 0) break ;
+               cudaMemcpy( &h_vrais_snake, d_vrais_snake, sizeof(double), cudaMemcpyDeviceToHost);
+               printf("\niter %d LV apres ajout noeuds = %lf \n ", iter, h_vrais_snake) ;  
+         }
+         
+      if (VERBOSE) 
+       {
+         toc(chrono, "temps sequence move");
+         
+         printf("nb deplacements    : %d\n", nb_move) ;
+         printf("nb deplacements total/test   : %d/%d\n", nb_move_total, nb_test_total) ;
+         printf("nb nouveaux noeuds : %d (total: %d)\n", *h_nb_nodes, nnodes) ;
+         printf("\nlongueur de codage de gl : %lf  \n", h_vrais_snake) ;     
+       }
+    }
+  
+  if (Verbose) {
+       toc(chrono_all, "temps move mv") ;
+       cudaMemcpy( h_stats_snake, d_stats_snake, 6*sizeof(uint64), cudaMemcpyDeviceToHost);
+       cudaMemcpy( &h_vrais_snake, d_vrais_snake, sizeof(double), cudaMemcpyDeviceToHost);
+       printf("\nFIN : longueur de codage de gl : %lf  (%d)\n", h_vrais_snake, h_stats_snake[0]) ;     
+       printf("nb noeuds : %d, nb_iter : %d\n", nnodes, iter-1) ;
+       printf("nb deplacements total/test   : %d/%d\n", nb_move_total, nb_test_total) ;
+  }  
+  
+      
+  if (Display) {
+       /* old fashion way to draw the snake
+       gpu2snake(d_snake, &h_snake_ll, nnodes);
+       uint32 * Liste_pixel_segment = new uint32[I_dim+J_dim];
+       affiche_snake_ushort(Image_in, h_snake_ll, 255, 0, Liste_pixel_segment) ;
+       delete Liste_pixel_segment ; 
+       delete h_snake_ll;
+       */
+       cudaMemcpy( h_snake, d_snake, nnodes*sizeof(snake_node_gpu), cudaMemcpyDeviceToHost);
+       //affiche coordonnees
+       for (int node=0; node<nnodes; node++){
+           printf("NODE %d  %d  %d \n", node, h_snake[node].posi, h_snake[node].posj);
+       }
+       // draw only the nodes with + marks
+       //dessine_snake(h_snake, nnodes, Image_in, 10);
+       //imagesc_ushort(Image_in, I_dim, J_dim) ;
+  }
+  cudaFree(d_img);
+  cudaFree(d_img_x);
+  cudaFree(d_img_x2);
+  cudaFree(d_freemanDiDj);
+  cudaFree(d_codeNoeud);
+  cudaFree(d_snake);
+  cudaFree(d_nb_pix_max); 
+  cudaFree(d_positions);
+  cudaFree(d_contribs_segments);
+  cudaFree(d_freemans_centres);
+  cudaFree(d_codes_segments);
+  cudaFree(d_stats_snake);
+  cudaFree(d_stats);
+  cudaFree(d_stats_ref);
+  cudaFree(d_vrais);
+  cudaFree(d_vrais_snake);
+  cudaFree(d_listes_pixels);
+  cudaFree(d_contribs_segments_blocs);
+  cudaFree(d_move);
+  return 1 ;
+}
+
diff --git a/src/structures.h b/src/structures.h
new file mode 100644 (file)
index 0000000..b2a9554
--- /dev/null
@@ -0,0 +1,145 @@
+/**
+ * \file structures.h
+ * \author NB - PhyTI 
+ * \version x.x
+ * \date 20 decembre 2009
+ *
+ *
+ */
+
+#ifndef _STRUCTURES_H
+#define _STRUCTURES_H
+
+
+/**
+ * \def uint64 entier non signe 64 bits
+ * \def int64 entier signe 64 bits
+ * \def uint32 entier non signe 32 bits
+ */
+typedef unsigned long long int uint64 ; 
+typedef unsigned int uint32;
+typedef long long int int64 ; 
+typedef long int int32 ;
+
+typedef unsigned short t_cumul_1 ;
+typedef unsigned int t_cumul_x ;
+typedef unsigned long long t_cumul_x2 ;
+
+typedef unsigned int t_sum_1 ;
+typedef unsigned long long t_sum_x ;
+typedef unsigned long long t_sum_x2 ;
+
+
+/** 
+ * \struct pixel_cumul structures.h
+ *
+ * \brief structure des images cumulees
+ *
+ * Version d'algorithme sans SSE2 \n
+ * les images cumulees correspondent a \n
+ * [sum 1, sum x, sum x^2] \n
+ * 
+ * Trois donnees a stocker de dynamique differente \n
+ *
+ * cas d'images en profondeur 16 bits \n 
+ * avec xum_x2 sur 64 bits => taill image sur 14 bits soit 16000 x 16000 \n
+ * longueur des segments sur 15 bits
+ * \verbatim
+  sum_1  : 0/1 + 14b + 15b = 29b => unsigned int 
+  sum_x  : 16b + 14b + 15b = 45b => unsigned long int
+  sum_x2 : 32b + 14b + 15b = 61b => unsigned long int
+  \endverbatim
+ * 
+ * Avec la definition suivante, les contributions des segments
+ * ne pourrons etre que positives. Le signe associe au segment devra
+ * etre memorise par une autre variable (code_segment)
+ */
+struct pixel_cumul
+{ 
+  uint32 sum_1;
+  uint64 sum_x;
+  uint64 sum_x2; 
+ } ;
+
+/*
+ * structure pour la smem des kernels cumuls
+ * 
+ */
+struct tcumuls {
+        t_cumul_x x;
+        t_cumul_x2 x2;
+};
+
+
+/*
+ * structure pour le smem des kernels contribs
+ *
+ */
+
+struct tcontribs {
+  t_sum_1 c1;
+  t_sum_x cx;
+  t_sum_x2 cx2;
+};
+
+/** 
+ * \struct snake_node structures.h
+ *
+ * \brief noeud du snake defini par liste chainee
+ *
+ * Cette structure memorise la position du noeud
+ * ET les informations concernant le segment qui
+ * part de ce noeud et va au noeud suivant dans
+ * l'ordre trigo 
+ */
+
+struct snake_node
+{ 
+  /* contribution du segment allant de ce noeud */
+  /* au noeud suivant, defini dans l'ordre trigo */
+  /* l'union pixel_cumul est definie en premier */
+  /* pour permettre l'alignement memoire */
+  struct pixel_cumul contrib ;
+  int code_segment ; /* signe de la contrib */
+  int freeman_in ;  /* du noeud d'arrivee du segment (ordre trigo) */
+  int freeman_out ; /* du noeud de depart du segment (ordre trigo) */
+  uint32 nb_pixels ;
+
+  uint32 posi ; /* position i du noeud */
+  uint32 posj ; /* position j du noeud */
+  uint32 centre_i ; /* centre i du segment */
+  uint32 centre_j ; /* centre j du segment */
+
+  int last_move ; /* dernier test deplacement accepte */
+  /* lien liste chainee snake2D */
+  struct snake_node *noeud_suiv ; /* dans le sens trigo */
+  struct snake_node *noeud_prec ;
+  
+
+  /* lien liste chainee snake3D */
+};
+
+
+struct snake_node_gpu
+{
+  t_sum_1 sum_1 ;
+  t_sum_x sum_x ;
+  t_sum_x2 sum_x2;
+
+  int code_segment ; /* signe de la contrib */
+  int freeman_in ;  /* du noeud d'arrivee du segment (ordre trigo) */
+  int freeman_out ; /* du noeud de depart du segment (ordre trigo) */
+  uint32 nb_pixels ;
+
+  uint32 posi ; /* position i du noeud */
+  uint32 posj ; /* position j du noeud */
+  uint32 centre_i ; /* centre i du segment */
+  uint32 centre_j ; /* centre j du segment */
+
+  int last_move ; /* dernier test deplacement accepte */
+};
+
+
+#endif
diff --git a/src/structures.h~ b/src/structures.h~
new file mode 100644 (file)
index 0000000..40b16dd
--- /dev/null
@@ -0,0 +1,129 @@
+/**
+ * \file structures.h
+ * \author NB - PhyTI 
+ * \version x.x
+ * \date 20 decembre 2009
+ *
+ *
+ */
+
+#ifndef _STRUCTURES_H
+#define _STRUCTURES_H
+
+
+/**
+ * \def uint64 entier non signe 64 bits
+ * \def int64 entier signe 64 bits
+ * \def uint32 entier non signe 32 bits
+ */
+typedef unsigned long long int uint64 ; 
+typedef unsigned int uint32;
+typedef long long int int64 ; 
+typedef long int int32 ;
+
+typedef unsigned short t_cumul_1 ;
+typedef unsigned int t_cumul_x ;
+typedef unsigned long long t_cumul_x2 ;
+
+typedef unsigned int t_sum_1 ;
+typedef unsigned long long t_sum_x ;
+typedef unsigned long long t_sum_x2 ;
+
+
+/** 
+ * \struct pixel_cumul structures.h
+ *
+ * \brief structure des images cumulees
+ *
+ * Version d'algorithme sans SSE2 \n
+ * les images cumulees correspondent a \n
+ * [sum 1, sum x, sum x^2] \n
+ * 
+ * Trois donnees a stocker de dynamique differente \n
+ *
+ * cas d'images en profondeur 16 bits \n 
+ * avec xum_x2 sur 64 bits => taill image sur 14 bits soit 16000 x 16000 \n
+ * longueur des segments sur 15 bits
+ * \verbatim
+  sum_1  : 0/1 + 14b + 15b = 29b => unsigned int 
+  sum_x  : 16b + 14b + 15b = 45b => unsigned long int
+  sum_x2 : 32b + 14b + 15b = 61b => unsigned long int
+  \endverbatim
+ * 
+ * Avec la definition suivante, les contributions des segments
+ * ne pourrons etre que positives. Le signe associe au segment devra
+ * etre memorise par une autre variable (code_segment)
+ */
+struct pixel_cumul
+{ 
+  uint32 sum_1;
+  uint64 sum_x;
+  uint64 sum_x2; 
+ } ;
+
+struct tcumuls {
+        t_cumul_x x;
+        t_cumul_x2 x2;
+};
+
+/** 
+ * \struct snake_node structures.h
+ *
+ * \brief noeud du snake defini par liste chainee
+ *
+ * Cette structure memorise la position du noeud
+ * ET les informations concernant le segment qui
+ * part de ce noeud et va au noeud suivant dans
+ * l'ordre trigo 
+ */
+
+struct snake_node
+{ 
+  /* contribution du segment allant de ce noeud */
+  /* au noeud suivant, defini dans l'ordre trigo */
+  /* l'union pixel_cumul est definie en premier */
+  /* pour permettre l'alignement memoire */
+  struct pixel_cumul contrib ;
+  int code_segment ; /* signe de la contrib */
+  int freeman_in ;  /* du noeud d'arrivee du segment (ordre trigo) */
+  int freeman_out ; /* du noeud de depart du segment (ordre trigo) */
+  uint32 nb_pixels ;
+
+  uint32 posi ; /* position i du noeud */
+  uint32 posj ; /* position j du noeud */
+  uint32 centre_i ; /* centre i du segment */
+  uint32 centre_j ; /* centre j du segment */
+
+  int last_move ; /* dernier test deplacement accepte */
+  /* lien liste chainee snake2D */
+  struct snake_node *noeud_suiv ; /* dans le sens trigo */
+  struct snake_node *noeud_prec ;
+  
+
+  /* lien liste chainee snake3D */
+};
+
+
+struct snake_node_gpu
+{
+  t_sum_1 sum_1 ;
+  t_sum_x sum_x ;
+  t_sum_x2 sum_x2;
+
+  int code_segment ; /* signe de la contrib */
+  int freeman_in ;  /* du noeud d'arrivee du segment (ordre trigo) */
+  int freeman_out ; /* du noeud de depart du segment (ordre trigo) */
+  uint32 nb_pixels ;
+
+  uint32 posi ; /* position i du noeud */
+  uint32 posj ; /* position j du noeud */
+  uint32 centre_i ; /* centre i du segment */
+  uint32 centre_j ; /* centre j du segment */
+
+  int last_move ; /* dernier test deplacement accepte */
+};
+
+
+#endif