Voilà désolé de vous déranger mais je m'arrache les cheveux sur un problème, et comme je fais du OpenCL pour la première fois je ne sais pas si cela a un rapport ou non.

J'ai les erreurs suivantes données par mon compilateur :

g++ -Wall -std=c++11 -lOpenCL main.cpp YoUtil.cpp libIDAAOS.o -o main
/tmp/ccYhKM4y.o: In function `main':
main.cpp.text+0xb97): undefined reference to `computeDistances(cl::CommandQueue&, cl:rogram&, int, int, _cl_mem*&, int, _cl_mem*&, _cl_mem*&)'
main.cpp.text+0xc42): undefined reference to `computeWeights(cl::CommandQueue&, cl:rogram&, int, int, _cl_mem*&, _cl_mem*&, double)'
main.cpp.text+0xcf9): undefined reference to `computeInterpolation(cl::CommandQueue&, cl:rogram&, int, int, int, _cl_mem*, _cl_mem*, _cl_mem*&, _cl_mem*)'
collect2: error: ld returned 1 exit status

Voici les fichiers qui sont à mon avis concernés par les erreurs mais n'hésitez-pas à demander les autres si j'ai tort :

main.cpp

Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
#include <iostream>
#include <fstream>
#include <cmath>
#include <cstdlib>
#include "IDALib.h"
#include "YoUtil.hpp"
#include <string>
#include <CL/cl.hpp>
 
using namespace std;
 
static void g1(const int NPOINTS, const int DIM, const double(*bounds)[2], const int nDiv, double *grids, const int whichDIM, double *X, int &where) {
	if (whichDIM == DIM) {
		// store the grid point & return
		for (int dim = 0; dim < DIM; ++dim) writeGrid(DIM, NPOINTS, where, dim, grids, X[dim]);
		// for (int dim = 0; dim < DIM; ++dim) cout << "*" << X[dim] << "* "; cout << endl;
		++where;
		return;
	}
	const double inc = (bounds[whichDIM][1] - bounds[whichDIM][0]) / (nDiv - 1);
	X[whichDIM] = bounds[whichDIM][0];
	for (int i = 0; i < nDiv; ++i) {
		g1(NPOINTS, DIM, bounds, nDiv, grids, whichDIM + 1, X, where);
		X[whichDIM] += inc;
	}
}
 
// x1, x2, x3, ... y1, y2, y3, ... z1, z1, z3, ...
void computeGridCoordinates(const int DIM, const double(*bounds)[2], const int nDiv, double *grids) {
	const int NPOINTS = pow(nDiv, DIM);
	double *X = new double[DIM];
	int where = 0;
	g1(NPOINTS, DIM, bounds, nDiv, grids, 0, X, where);
	delete[]X;
}
 
int main(int argc, char **argv) {
	if (argc < 3) {
		cerr << argv[0] << " [input filename] [output filename]" << endl;
		return 255;
	}
	ifstream inp(argv[1]);
	if (!inp.good()) {
		cerr << "\nError opening file: " << argv[1] << endl;
		return 254;
	}
	int DIM, nPoints, nValues, nDivisions;
	inp >> DIM >> nPoints >> nValues >> nDivisions;
 
	// Allocate memory for storing all necessary data
	double *knownCoords = new double[DIM * nPoints];
	double *knownValues = new double[nPoints * nValues];
	double (*bounds)[2] = new double[DIM][2];					// size of DIMS * 2
	const int nGrids = (int)pow(nDivisions, DIM);				// # of grid points
	double *gridCoords = new double[(size_t) pow(nDivisions, DIM) * DIM];
	double *distances = new double[nGrids * nPoints];
	double *weightSum = new double[nGrids];
	double *gridValues = new double[nGrids * nValues];
 
	// read data from the specified file and store data into appropriate data structures using write & writeAttribute functions
	for (int pt = 0; pt < nPoints; ++pt) {
		for (int dim = 0; dim < DIM; ++dim) {
			double tmp;
			inp >> tmp;
			write(DIM, nPoints, pt, dim, knownCoords, tmp);
		}
		for (int attr = 0; attr < nValues; ++attr) {
			double tmp;
			inp >> tmp;
			writeAttribute(nValues, nPoints, pt, attr, knownValues, tmp);
		}
	}
	inp.close();
	// show data
	// for (int i = 0; i < nPoints * DIM; ++i) cout << knownCoords[i] << " "; cout << endl;
	// for (int i = 0; i < nPoints * nValues; ++i) cout << knownValues[i] << " "; cout << endl;
 
	// int where = 0;
	// find bounds of known data points
 
	// create context
	std::vector<cl::CommandQueue> cmdQueues = std::vector<cl::CommandQueue>();
	cl::Context *context = getContext(CL_DEVICE_TYPE_GPU, cmdQueues, 0, true);  
 
	// create buffers, 0 is the offset, TRUE means blocking
	cl_mem knownCoords_b = clCreateBuffer((*context)(), CL_MEM_READ_WRITE, sizeof(knownCoords), NULL, 0);
	clEnqueueWriteBuffer(cmdQueues[0](),knownCoords_b, CL_TRUE, 0, sizeof(knownCoords_b), knownCoords_b, 0, NULL, NULL);
 
	cl_mem knownValues_b = clCreateBuffer((*context)(), CL_MEM_READ_WRITE, sizeof(knownValues), NULL, 0);
	clEnqueueWriteBuffer(cmdQueues[0](), knownValues_b, CL_TRUE, 0, sizeof(knownValues_b), knownValues_b, 0, NULL, NULL);
 
	cl_mem gridCoords_b = clCreateBuffer((*context)(), CL_MEM_READ_WRITE, sizeof(gridCoords), NULL, 0);
	clEnqueueWriteBuffer(cmdQueues[0](), gridCoords_b, CL_TRUE, 0, sizeof(gridCoords_b), gridCoords_b, 0, NULL, NULL);
 
	cl_mem distances_b = clCreateBuffer((*context)(), CL_MEM_READ_WRITE, sizeof(distances), NULL, 0);
	clEnqueueWriteBuffer(cmdQueues[0](), distances_b, CL_TRUE, 0, sizeof(distances_b), distances, 0, NULL, NULL);
 
	cl_mem weightSum_b = clCreateBuffer((*context)(), CL_MEM_READ_WRITE, sizeof(weightSum), NULL, 0);
	clEnqueueWriteBuffer(cmdQueues[0](), weightSum_b, CL_TRUE, 0, sizeof(weightSum_b), weightSum, 0, NULL, NULL);
 
	cl_mem gridValues_b = clCreateBuffer((*context)(), CL_MEM_READ_WRITE, sizeof(gridValues), NULL, 0);
	clEnqueueWriteBuffer(cmdQueues[0](), gridValues_b, CL_TRUE, 0, sizeof(gridValues_b), gridValues_b, 0, NULL, NULL);
 
	// parse the source code and build the program
	std::string source_code = readSourceCode("shepard_extrapolation_kernels.cl");
	cl::Program *program = compile(*context, source_code); 
 
	stopWatch timer;
	double t1(0.0);
	timer.start();
	computeBounds(DIM, nPoints, knownCoords, bounds);
	timer.stop();
	t1 += timer.elapsedTime();
	// for (int i = 0; i < DIM; ++i) cout << bounds[i][0] << ":" << bounds[i][1] << endl; cout << endl;
 
	// create grid points in unknownCoords
	computeGridCoordinates(DIM, bounds, nDivisions, gridCoords);
 
	// for (int i = 0; i < nGrids*DIM; ++i) cout << gridCoords[i] << " "; cout << endl;
 
	// step 3. compute distances between all grids points and all known data points
	double t2(0.0);
	timer.start();
	computeDistances(cmdQueues[0], *program, DIM, nPoints, knownCoords_b, nGrids, gridCoords_b, distances_b);
	timer.stop();
	t2 += timer.elapsedTime();
	// for (int i = 0; i < nPoints*nGrids; ++i) cout << distances[i] << " "; cout << endl;
 
	// step 4. turn the distance array into weight array, and compute the total weight
	double t3(0.0);
	timer.start();
	computeWeights(cmdQueues[0], *program, nGrids, nPoints, distances_b, weightSum_b);
	timer.stop();
	t3 += timer.elapsedTime();
	// for (int i = 0; i < nPoints*nGrids; ++i) cout << distances[i] << " "; cout << endl;
 
	// step 5 & 6. compute sum (weights * known Values) / totalWeight
	double t4(0.0);
	timer.start();
	computeInterpolation(cmdQueues[0], *program, nValues, nGrids, nPoints, distances_b, weightSum_b, knownValues_b, gridValues_b);
	timer.stop();
	t4 += timer.elapsedTime();
 
	// read the results back to the host, CL_TRUE means blocking, 0 is the offset, we read from gridValues_b into gridValues, 
	// 0 events, no events list, no event
	clEnqueueReadBuffer(cmdQueues[0](), gridValues_b, CL_TRUE, 0, sizeof(gridValues_b), gridValues, 0, NULL, NULL);
/*
	std::cout << "computeBounds : " << t1 << std::endl;
	std::cout << "computeDistances : " << t2 << std::endl;
	std::cout << "computeWeights : " << t3 << std::endl;
	std::cout << "computeInterpolation : " << t4 << std::endl;
*/
	std::cout << t1 << " " << t2 << " " << t3 << " " << t4 << " " << std::endl;
	// All calculations are finished.  Write grid data to the specified output file.
	ofstream outp(argv[2]);
	// Output points
	if (outp.good()) {
		/*
		// This part writes scattered data points
		for (int i = 0; i < nPoints; ++i) {
			for (int dim = 0; dim < DIM; ++dim) {
				outp << read(DIM, nPoints, i, dim, knownCoords) << " ";
			}
			for (int attr = 0; attr < nValues; ++attr) {
				outp << readAttribute(nValues, nPoints, i, attr, knownValues);
			}
			outp << knownValues[i] << "\n";
		}
		outp << "\n\n";
		*/
 
		for (int i = 0; i < nGrids; ++i) {
			for (int dim = 0; dim < DIM; ++dim) {
				outp << readGrid(DIM, nGrids, i, dim, gridCoords) << " ";
			}
			for (int attr = 0; attr < nValues; ++attr) {
				outp << readGridAttribute(nValues, nGrids, i, attr, gridValues) << " ";
			}
			outp << "\n";
		}
 
		outp.close();
	}
 
	delete[] bounds;
	delete[] knownCoords;
	delete[] gridCoords;
	delete[] weightSum;
	delete[] distances;
	delete[] knownValues;
	delete[] gridValues;
 
	return 0;
}
libIDAAOS.cpp

Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
#include "IDALib.h"
#include <iostream>
#include <utility> // pair
#include <cmath> // sqrt
#include <cstdlib> // EXIT_FAILURE
#include <limits>
#include <cl.hpp>
 
/* Array of structs format */
 
double read(const int DIM, const int nPoints, const int whichPt, const int whichDim, const double *coords){
    /* Read from known coordinates 
 
    DIM - Dimensionality of coordinates
    nPoints - Number of known data points
    whichPt - which known data point is to be read
    whichDim - which dimension of coordinates is to be read
    coords - array containing all coordinates of known data points
 
    return the coordinate of the DIM dimension of the whichPt point
 
    */
    if(whichPt > nPoints - 1) {
        std::cout << "The point that you want to read does not exist" << std::endl;
        exit(EXIT_FAILURE);
    }
 
    return coords[whichPt * DIM + whichDim];
}
 
 
void  write(const int DIM, const int nPoints, const int whichPt, const int whichDim, double *coords, const double val){
    /* Write to known coordinates
 
    DIM - Dimensionality of coordinates
    nPoints - Number of known data points
    whichPt - which known data point is to be read
    whichDim - which dimension of coordinates is to be read
    coords - array containing all coordinates of known data points
 
    */
    if(whichPt > nPoints - 1) {
        std::cout << "The point that you want to write does not exist" << std::endl;
    }
 
    coords[whichPt * DIM + whichDim] = val;
}
 
 
double readGrid(const int DIM, const int nGridPoints, const int whichGridPt, const int whichDim, const double *gridCoords){
    /* Read grid coordinates
 
    DIM - Dimensionality of coordinates
    nGridPoints - Number of points in the grid
    whichGridPt - which point in the gread is to be read
    whichDim - which dimension of coordinates is to be read
    gridCoords - array containing all coordinates of grid points
 
    return the coordinate of the DIM dimension of the whichGridPt
 
    */
    if(whichGridPt > nGridPoints - 1) {
        std::cout << "The point that you want to read does not exist in the grid" << std::endl;
        exit(EXIT_FAILURE);
    }
 
    return gridCoords[whichGridPt * DIM + whichDim];
}
 
void  writeGrid(const int DIM, const int nGridPoints, const int whichGridPt, const int whichDim, double *gridCoords, const double val){
    /* Write grid coordinates
 
    DIM - Dimensionality of coordinates
    nGridPoints - Number of points in the grid
    whichGridPt - which point in the gread is to be read
    whichDim - which dimension of coordinates is to be read
    gridCoords - array containing all coordinates of grid points
 
    */
    if(whichGridPt > nGridPoints - 1) {
        std::cout << "The point that you want to write does not exist in the grid" << std::endl;
    }
 
    gridCoords[whichGridPt * DIM + whichDim] = val;
 
}
 
double readAttribute(const int noAttr, const int nPoints, const int whichPt, const int whichAttr, const double *values){
    /* Read known values
 
    noAttr - number of attributes at each point
    nPoints - Number of known data points
    whichPt - which known data point is to be read
    whichAttr - which attribute is to be read
    values - array containing all the values 
 
    return the value of whichAttr of whichPt 
 
    */
    if(whichPt > nPoints - 1){
        std::cout << "The point that you are trying to read does not exist" << std::endl;
        exit(EXIT_FAILURE);
    }
 
    return values[whichPt * noAttr + whichAttr];
}
 
void writeAttribute(const int noAttr, const int nPoints, const int whichPt, const int whichAttr, double *values, const double val){
    /* Write known values
 
    noAttr - number of attributes at each point
    nPoints - Number of known data points
    whichPt - which known data point is to be read
    whichAttr - which attribute is to be read
    values - array containing all the values 
 
    */
    if(whichPt > nPoints - 1){
        std::cout << "The point that you are trying to write does not exist" << std::endl;
        exit(EXIT_FAILURE);
    }
 
    values[whichPt * noAttr + whichAttr] = val;
}
 
double readGridAttribute(const int noAttr, const int nPoints, const int whichPt, const int whichAttr, const double *values){
    /* Read a grid attribute
 
    noAttr - number of attributes at each point
    nPoints - Number of known data points
    whichPt - which known data point is to be read
    whichAttr - which attribute is to be read
    values - array containing all the values
 
    return the value of whichAttr of whichPt 
 
    */
 
    if(whichPt > nPoints - 1){
        std::cout << "The point that you are trying to read does not exist" << std::endl;
        exit(EXIT_FAILURE);
    }
 
    return values[whichPt * noAttr + whichAttr];
 
}
 
 
void writeGridAttribute(const int noAttr, const int nPoints, const int whichPt, const int whichAttr, double *values, const double val){
/* Write known values
 
    noAttr - number of attributes at each point
    nPoints - Number of known data points
    whichPt - which known data point is to be read
    whichAttr - which attribute is to be read
    values - array containing all the values 
 
    */
    if(whichPt > nPoints - 1){
        std::cout << "The point that you are trying to write does not exist" << std::endl;
        exit(EXIT_FAILURE);
    }
 
    values[whichPt * noAttr + whichAttr] = val;
}
 
void computeBounds(const int DIM, const int nPoints, const double *knownCoords, double(*bounds)[2]){
    /* Find extremes in each dimension of a given set of scatter points
    
    DIM - Dimensionality of coordinates    
    nPoints - Number of known data points
    knowCoords - array containing all coordinates of known data points
    bounds - 2D array to store the extremes, each row corresponds to a dimension
 
    */
 
    for(int i = 0; i < DIM; i++){
        double min = std::numeric_limits<double>::max();
        double max = std::numeric_limits<double>::min();
        for(int j = 0; j < DIM * nPoints; j+= DIM){
            if(knownCoords[i + j] < min)
                min = knownCoords[i + j];
 
            if(knownCoords[i + j] > max)
                max= knownCoords[i + j];
        }
        bounds[i][0] = min;
        bounds[i][1] = max;
    }
}
 
void computeDistances(const int DIM, const int nPoints, const double *knownCoords, const int nGrids, const double *gridCoords, double *distances){
    /* Compute distances between all known points and all grid points.
 
    DIM - Dimensionality of coordinates    
    nPoints - Number of known data points
    nGrids - number of points in the grid
    knowCoords - array containing all coordinates of known data points
    gridCoords - containing all grid points
    distances - array containing all the distances all data points and all grid points
 
    */
 
    for(int k = 0; k < nGrids; k++){
        for(int i = 0; i < nPoints; i++){
            double distance(0.0);
            for(int j = 0; j < DIM; j++){
                distance += pow(knownCoords[i * DIM + j] - gridCoords[k * DIM + j], 2.0);
            }
            distances[k * nPoints + i] = sqrt(distance);
        }
    }
 
}
 
void computeWeights(const int nGrids, const int nPoints, double *distances, double *weightSum, const double p){
    /* Compute weights from known points to each grid point
    
    nPoints - Number of known data points
    nGrids - number of points in the grid
    distances - array containing all the distances all data points and all grid points
    weightSum - array containing the weight sums of each grid point
    p - parameter to compute sums
 
    */
 
    for(int i = 0; i < nGrids; i++){
        double weight(0.0);
        for(int j = 0; j < nPoints; j++){
            double this_weight(0.0);
            if(distances[i * nPoints + j] == 0){
                weight = 0.0;
                break;
            }
            this_weight = 1.0 / pow(distances[i * nPoints + j], p);
            weight += this_weight;
            distances[i * nPoints + j] = this_weight;
        }
        weightSum[i] = weight;
    }
}
 
 
void computeInterpolation(const int nValues, const int nGrids, const int nPoints, const double *distances, const double *weightSum, 
    const double *knownValues, double *gridValues){
 
    /* Compute unknown values on grid points using weights and known values
 
    nValues - number of attributes
    nGrids - number of points in the grid
    nPoints - number of known points
    distances - distances between each pair (known_point, grid_point)
    weightSum - Sum of the weights for each grid point
 
    */
 
    for(int i = 0; i < nGrids; i++){
        for(int j = 0; j < nValues; j++){
            double weigh_value_sum(0.0);
            bool to_change(true);
            for(int k = 0; k < nPoints; k++){
                weigh_value_sum += distances[i * nPoints + k] * knownValues[nValues * k + j];
                if(distances[i * nPoints + k] == 0){
                    writeGridAttribute(nValues, nGrids, i, j, gridValues, knownValues[nValues * k + j]);
                    to_change = false;
                    break;
                }
            }
            if(to_change) writeGridAttribute(nValues, nGrids, i, j, gridValues, weigh_value_sum / weightSum[i]);
        }
    }
}
 
// prepare kernel arguments, work-groups config and launch kernels - No data movements
void computeDistances(cl::CommandQueue &cmdQueue, cl::Program &prog, const int DIM, const int nPoints, 
    cl::Buffer &knownCoords, const int nGrids, cl::Buffer &gridCoords, cl::Buffer &distances){
 
    cl_Kernel kernel = clCreateKernel(prog(), "compute_distances", NULL);
    kernel->setArg(0, DIM);
    kernel->setArg(1, nPoints);
    kernel->setArg(2, knownCoords);
    kernel->setArg(3, nGrids);
    kernel->setArg(4, gridCoords);
    kernel->setArg(5, distances);
    size_t group_size = 4;
    cl::NDRange local(group_size, group_size, group_size);
    cl::NDRange global(DIM*nPoints*nGrids + pow(group_size, 3.0) - 1 / pow(group_size, 3.0));
    //clEnqueueNDRangeKernel(cmdQueue, kernel, 3, NULL, global, local, 0, NULL, NULL);
    kernel.bind(cmdQueue, 0, global, local);
}
 
void computeWeights(cl::CommandQueue &cmdQueue, cl::Program &prog, const int nGrids, const int nPoints,
    cl::Buffer &distances, cl::Buffer &weightSum, const MY_DATA_TYPE p = 2.0){
 
    cl_Kernel kernel = clCreateKernel(prog(), "compute_weights", NULL);
    clSetKernelArg(kernel, 0, sizeof(cl_int), nGrids);
    clSetKernelArg(kernel, 1, sizeof(cl_int), nPoints);
    clSetKernelArg(kernel, 2, sizeof(cl_mem), distances);
    clSetKernelArg(kernel, 3, sizeof(cl_mem), weightSum;
    clSetKernelArg(kernel, 4, sizeof(cl_double), p);
    size_t group_size = 8;
    cl::NDRange local(group_size, group_size);
    cl::NDRange global(nGrids*nPoints + pow(group_size, 2.0) - 1 / pow(group_size, 2.0));
    //clEnqueueNDRangeKernel(cmdQueue, kernel, 2, NULL, global, local, 0, NULL, NULL);
    kernel.bind(cmdQueue, 0, global, local);
}
 
void computeInterpolation(cl::CommandQueue &cmdQueue, cl::Program &prog, const int nValues, const int nGrids,
    const int nPoints, cl::Buffer &distances, cl::Buffer &weightSum, cl::Buffer &knownValues, cl::Buffer &gridValues){
 
    cl_Kernel kernel = clCreateKernel(prog(), "compute_interpolation", NULL);
    kernel->setArg(0, nValues);
    kernel->setArg(1, nGrids);
    kernel->setArg(2, nPoints);
    kernel->setArg(3, distances);
    kernel->setArg(4, weightSum);
    kernel->setArg(5, knownValues);
    kernel->setArg(6, gridValues);
    size_t group_size = 4;
    cl::NDRange local(group_size, group_size, group_size);
    cl::NDRange global(nValues*nGrids*nPoints + pow(group_size, 3.0) - 1 / pow(group_size, 3.0));
    //clEnqueueNDRangeKernel(cmdQueue, kernel, 3, NULL, global, local, 0, NULL, NULL);
    // 0 is the offset
    kernel.bind(cmdQueue, 0, global, local);
}
 
// page 111 pour enqueue un kernel
// conversion page 137
// max and co 177
Je remercie tous ceux qui auront eu la gentillesse de lire jusqu'ici et ceux qui pourront éventuellement m'aider car je suis perdu.

Immo