--- /dev/null
+# 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 ""
--- /dev/null
+/**
+ * \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
--- /dev/null
+/**
+ * \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
--- /dev/null
+#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
--- /dev/null
+#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
--- /dev/null
+/**
+ * \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) ;
+}
--- /dev/null
+/**
+ * \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) ;
+}
--- /dev/null
+#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) ;
--- /dev/null
+#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) ;
--- /dev/null
+/**
+ * \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;
+}
--- /dev/null
+#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_
--- /dev/null
+
+#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
+ */
+}
+
+
--- /dev/null
+
+#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
+ */
+}
+
+
--- /dev/null
+#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_
--- /dev/null
+#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_
--- /dev/null
+/**
+ * \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) ;
+
+}
--- /dev/null
+/**
+ * \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) ;
+}
--- /dev/null
+#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) ;
--- /dev/null
+#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) ;
--- /dev/null
+
+
+__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]);
+}
--- /dev/null
+
+
+__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]);
+}
--- /dev/null
+#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];
+ }
+}
+
--- /dev/null
+#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];
+ }
+}
+
--- /dev/null
+#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__
--- /dev/null
+
+
+
+__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;
+
+}
--- /dev/null
+
+
+
+__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;
+
+}
--- /dev/null
+
+__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;
+}
--- /dev/null
+
+__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;
+}
--- /dev/null
+
+#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
--- /dev/null
+#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 );
+}
--- /dev/null
+#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 );
+}
--- /dev/null
+/**
+ * \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] ;
+}
--- /dev/null
+/**
+ * \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] ;
+}
--- /dev/null
+#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
--- /dev/null
+#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
--- /dev/null
+
+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
--- /dev/null
+
+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;
+}
--- /dev/null
+#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
--- /dev/null
+#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
--- /dev/null
+/**
+ * \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 ;
+}
+
--- /dev/null
+/**
+ * \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 ;
+}
+
--- /dev/null
+#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);
--- /dev/null
+#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);
--- /dev/null
+#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]);
+ }
+ }
--- /dev/null
+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 );
+}
--- /dev/null
+#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
--- /dev/null
+
+void verif_cumuls(int ** img_in, uint64 ** d_img_1, uint64 ** d_img_x, uint64 ** d_img_x2);
--- /dev/null
+/**
+ * \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 ;
+}
+
--- /dev/null
+/**
+ * \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 ;
+}
+
--- /dev/null
+/**
+ * \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
--- /dev/null
+/**
+ * \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